2 * mkbrnimg.c - partially based on OpenWrt's wndr3700.c
4 * Copyright (C) 2011 Tobias Diedrich <ranma+openwrt@tdiedrich.de>
6 * This program is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU General Public License,
8 * version 2 as published by the Free Software Foundation.
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
15 * You should have received a copy of the GNU General Public License
16 * along with this program; if not, write to the Free Software
17 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
28 #include <netinet/in.h>
31 #define BPB 8 /* bits/byte */
33 static uint32_t crc32
[1<<BPB
];
35 static char *output_file
= "default-brnImage";
36 static uint32_t magic
= 0x12345678;
37 static char *signature
= "BRNDTW502";
38 static uint32_t crc32_poly
= 0x2083b8ed;
40 static void init_crc32()
42 const uint32_t poly
= ntohl(crc32_poly
);
45 for (n
= 0; n
< 1<<BPB
; n
++) {
49 for (bit
= 0; bit
< BPB
; bit
++)
50 crc
= (crc
& 1) ? (poly
^ (crc
>> 1)) : (crc
>> 1);
55 static uint32_t crc32buf(unsigned char *buf
, size_t len
)
57 uint32_t crc
= 0xFFFFFFFF;
59 for (; len
; len
--, buf
++)
60 crc
= crc32
[(uint8_t)crc
^ *buf
] ^ (crc
>> BPB
);
64 static void usage(const char *) __attribute__ (( __noreturn__
));
66 static void usage(const char *mess
)
68 fprintf(stderr
, "Error: %s\n", mess
);
69 fprintf(stderr
, "Usage: mkbrnimg [-o output_file] [-m magic] [-s signature] [-p crc32 poly] kernel_file [additional files]\n");
70 fprintf(stderr
, "\n");
74 static void parseopts(int *argc
, char ***argv
)
79 while ((res
= getopt(*argc
, *argv
, "o:m:s:p:")) != -1) {
82 usage("Unknown option");
88 magic
= strtoul(optarg
, &endptr
, 0);
89 if (endptr
== optarg
|| *endptr
!= 0)
90 usage("magic must be a decimal or hexadecimal 32-bit value");
96 crc32_poly
= strtoul(optarg
, &endptr
, 0);
97 if (endptr
== optarg
|| *endptr
!= 0)
98 usage("'crc32 poly' must be a decimal or hexadecimal 32-bit value");
106 static void appendfile(int outfd
, char *path
, int kernel
) {
108 size_t len
, padded_len
;
114 memset(padding
, 0xff, sizeof(padding
));
117 if ((fd
= open(path
, O_RDONLY
)) < 0
118 || (len
= lseek(fd
, 0, SEEK_END
)) < 0
119 || (input_file
= mmap(0, len
, PROT_READ
, MAP_SHARED
, fd
, 0)) == (void *) (-1)
122 fprintf(stderr
, "Error mapping file '%s': %s\n", path
, strerror(errno
));
126 // kernel should be lzma compressed image, not uImage
128 (input_file
[0] != (char)0x5d ||
129 input_file
[1] != (char)0x00 ||
130 input_file
[2] != (char)0x00 ||
131 input_file
[3] != (char)0x80)) {
132 fprintf(stderr
, "lzma signature not found on kernel image.\n");
137 crc
= crc32buf(input_file
, len
);
138 fprintf(stderr
, "crc32 for '%s' is %08x.\n", path
, crc
);
141 write(outfd
, input_file
, len
);
144 padded_len
= ((len
+ sizeof(footer
) + sizeof(padding
) - 1) & ~(sizeof(padding
) - 1)) - sizeof(footer
);
145 fprintf(stderr
, "len=%08zx padded_len=%08zx\n", len
, padded_len
);
146 write(outfd
, padding
, padded_len
- len
);
149 footer
[0] = (len
>> 0) & 0xff;
150 footer
[1] = (len
>> 8) & 0xff;
151 footer
[2] = (len
>> 16) & 0xff;
152 footer
[3] = (len
>> 24) & 0xff;
153 footer
[4] = (magic
>> 0) & 0xff;
154 footer
[5] = (magic
>> 8) & 0xff;
155 footer
[6] = (magic
>> 16) & 0xff;
156 footer
[7] = (magic
>> 24) & 0xff;
157 footer
[8] = (crc
>> 0) & 0xff;
158 footer
[9] = (crc
>> 8) & 0xff;
159 footer
[10] = (crc
>> 16) & 0xff;
160 footer
[11] = (crc
>> 24) & 0xff;
161 write(outfd
, footer
, sizeof(footer
));
163 munmap(input_file
, len
);
166 int main(int argc
, char **argv
)
171 parseopts(&argc
, &argv
);
174 usage("wrong number of arguments");
176 if ((outfd
= open(output_file
, O_WRONLY
|O_CREAT
|O_TRUNC
, 0644)) == -1)
178 fprintf(stderr
, "Error opening '%s' for writing: %s\n", output_file
, strerror(errno
));
182 for (i
=0; i
<argc
; i
++) {
183 appendfile(outfd
, argv
[i
], i
== 0);
185 write(outfd
, signature
, strlen(signature
)+1);