summaryrefslogtreecommitdiffstats
path: root/paxf.c
blob: 3e167e65ec50cf9340df789a24a13a524a27cc65 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
/**********************************************************************
 *  Given a linux-system.axf file built in a certain way, replace
 *  the kernel parameters used with whatever I'd like to put in
 *  there instead.
 *
 *  This is a quick and dirty hack; if it works for *anything* other
 *  than this, I think I'll laugh hysterically.
 *
 * 
 *  Copyright (c) 2012, Al Stone <ahs3@ahs3.net>
 * 
 *  This program is free software; you can redistribute it and/or
 *  modify it under the terms of version 2 (only) of the GNU General
 *  Public License as published by the Free Software Foundation.
 *
 **********************************************************************/

#include <errno.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/mman.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>

#define ARG_OFFSET      0x4000e4
#define AXF_FILE        "./linux-system-useless.axf"
#define BUFFER_LENGTH   400

void
usage() {
    fprintf(stderr, "usage: paxf <output-axf> <kernel-parameters>\n\n");
    fprintf(stderr, "where:\n");
    fprintf(stderr, 
            "   <output-axf>        => name to use for patched axf file\n");
    fprintf(stderr,
            "   <kernel-parameters> => the kernel parameters wanted as a\n");
    fprintf(stderr,
            "                          single string (assume there are NO\n");
    fprintf(stderr,
            "                          parameters provided by default)\n");
}

int
main(int argv, char *argc[]) {

    int infd, outfd;
    char *fname;
    char *kargs;

    /* crude argument handling */
    if (argv < 3) {
        usage();
        exit(1);
    }
    fname = argc[1];
    kargs = argc[2];

    outfd = open(fname, O_RDWR | O_CREAT | O_TRUNC,
                 S_IRUSR|S_IWUSR|S_IRGRP|S_IROTH);
    if (! (outfd > 0)) {
        fprintf(stderr, "? cannot open %s as output\n", fname);
        exit(1);
    }

    if (strlen(kargs) > BUFFER_LENGTH) {
        fprintf(stderr, "? not enough space for the kernel args (%d)\n",
                strlen(kargs));
        exit(1);
    }

    /*
     * map in the entire axf file to use as a template, then copy
     * it all to the new location, except for the bits we need to
     * change
     */
    unsigned char *axf = NULL;
    struct stat stat_buf;
    off_t axf_size;
    int count;
    unsigned char *buf;

    if (stat(AXF_FILE, &stat_buf) == 0) {
        axf_size = stat_buf.st_size;
    }
    else {
        fprintf(stderr, "? cannot stat %s (%d)\n", AXF_FILE, errno);
        exit(1);
    }

    infd = open(AXF_FILE, O_RDONLY);
    if (infd) {
        axf = mmap(NULL, axf_size, PROT_READ, MAP_PRIVATE, infd, 0);
        if (axf <= 0) {
            fprintf(stderr, "? memory map failed (%d)\n", errno);
            exit(1);
        }

        /* copy everything before the kernel args */
        lseek(infd, 0, SEEK_SET);
        lseek(outfd, 0, SEEK_SET);
        write(outfd, axf, ARG_OFFSET);

        /*
         * replace the BUFFER_LENGTH space in the input axf file
         * with the arguments we really want
         */
        buf = malloc(BUFFER_LENGTH + 1);
        memset(buf, ' ', BUFFER_LENGTH);
        memcpy(buf, kargs, strlen(kargs));
        write(outfd, buf, BUFFER_LENGTH);

        /* copy everything after the kernel args */
        write(outfd, axf + ARG_OFFSET + BUFFER_LENGTH,
              axf_size - (ARG_OFFSET + BUFFER_LENGTH));

        close(outfd);
        free(buf);
        munmap(axf, axf_size);
        close(infd);
    }
    else {
        fprintf(stderr, "? cannot open %s as input\n", AXF_FILE);
        exit(1);
    }
}