1 // SPDX-License-Identifier: GPL-2.0-only
3 * mkbrnimg.c - partially based on OpenWrt's wndr3700.c
5 * Copyright (C) 2011 Tobias Diedrich <ranma+openwrt@tdiedrich.de>
16 #include <netinet/in.h>
19 #define BPB 8 /* bits/byte */
21 static uint32_t crc32
[1<<BPB
];
23 static char *output_file
= "default-brnImage";
24 static uint32_t magic
= 0x12345678;
25 static char *signature
= "BRNDTW502";
26 static uint32_t crc32_poly
= 0x2083b8ed;
28 static void init_crc32()
30 const uint32_t poly
= ntohl(crc32_poly
);
33 for (n
= 0; n
< 1<<BPB
; n
++) {
37 for (bit
= 0; bit
< BPB
; bit
++)
38 crc
= (crc
& 1) ? (poly
^ (crc
>> 1)) : (crc
>> 1);
43 static uint32_t crc32buf(const void *buf
, size_t len
)
45 uint32_t crc
= 0xFFFFFFFF;
46 const uint8_t *in
= buf
;
48 for (; len
; len
--, in
++)
49 crc
= crc32
[(uint8_t)crc
^ *in
] ^ (crc
>> BPB
);
53 static void usage(const char *) __attribute__ (( __noreturn__
));
55 static void usage(const char *mess
)
57 fprintf(stderr
, "Error: %s\n", mess
);
58 fprintf(stderr
, "Usage: mkbrnimg [-o output_file] [-m magic] [-s signature] [-p crc32 poly] kernel_file [additional files]\n");
59 fprintf(stderr
, "\n");
63 static void parseopts(int *argc
, char ***argv
)
68 while ((res
= getopt(*argc
, *argv
, "o:m:s:p:")) != -1) {
71 usage("Unknown option");
77 magic
= strtoul(optarg
, &endptr
, 0);
78 if (endptr
== optarg
|| *endptr
!= 0)
79 usage("magic must be a decimal or hexadecimal 32-bit value");
85 crc32_poly
= strtoul(optarg
, &endptr
, 0);
86 if (endptr
== optarg
|| *endptr
!= 0)
87 usage("'crc32 poly' must be a decimal or hexadecimal 32-bit value");
95 static void appendfile(int outfd
, char *path
, int kernel
) {
97 size_t len
, padded_len
;
103 memset(padding
, 0xff, sizeof(padding
));
106 if ((fd
= open(path
, O_RDONLY
)) < 0
107 || (len
= lseek(fd
, 0, SEEK_END
)) < 0
108 || (input_file
= mmap(0, len
, PROT_READ
, MAP_SHARED
, fd
, 0)) == (void *) (-1)
111 fprintf(stderr
, "Error mapping file '%s': %s\n", path
, strerror(errno
));
115 // kernel should be lzma compressed image, not uImage
117 (input_file
[0] != (char)0x5d ||
118 input_file
[1] != (char)0x00 ||
119 input_file
[2] != (char)0x00 ||
120 input_file
[3] != (char)0x80)) {
121 fprintf(stderr
, "lzma signature not found on kernel image.\n");
126 crc
= crc32buf(input_file
, len
);
127 fprintf(stderr
, "crc32 for '%s' is %08x.\n", path
, crc
);
130 write(outfd
, input_file
, len
);
133 padded_len
= ((len
+ sizeof(footer
) + sizeof(padding
) - 1) & ~(sizeof(padding
) - 1)) - sizeof(footer
);
134 fprintf(stderr
, "len=%08zx padded_len=%08zx\n", len
, padded_len
);
135 write(outfd
, padding
, padded_len
- len
);
138 footer
[0] = (len
>> 0) & 0xff;
139 footer
[1] = (len
>> 8) & 0xff;
140 footer
[2] = (len
>> 16) & 0xff;
141 footer
[3] = (len
>> 24) & 0xff;
142 footer
[4] = (magic
>> 0) & 0xff;
143 footer
[5] = (magic
>> 8) & 0xff;
144 footer
[6] = (magic
>> 16) & 0xff;
145 footer
[7] = (magic
>> 24) & 0xff;
146 footer
[8] = (crc
>> 0) & 0xff;
147 footer
[9] = (crc
>> 8) & 0xff;
148 footer
[10] = (crc
>> 16) & 0xff;
149 footer
[11] = (crc
>> 24) & 0xff;
150 write(outfd
, footer
, sizeof(footer
));
152 munmap(input_file
, len
);
155 int main(int argc
, char **argv
)
160 parseopts(&argc
, &argv
);
163 usage("wrong number of arguments");
165 if ((outfd
= open(output_file
, O_WRONLY
|O_CREAT
|O_TRUNC
, 0644)) == -1)
167 fprintf(stderr
, "Error opening '%s' for writing: %s\n", output_file
, strerror(errno
));
171 for (i
=0; i
<argc
; i
++) {
172 appendfile(outfd
, argv
[i
], i
== 0);
174 write(outfd
, signature
, strlen(signature
)+1);