2 * add_header.c - partially based on OpenWrt's motorola-bin.c
4 * Copyright (C) 2008 Imre Kaloz <kaloz@openwrt.org>
5 * Gabor Juhos <juhosg@openwrt.org>
7 * This program is free software; you can redistribute it and/or
8 * modify it under the terms of the GNU General Public License,
9 * version 2 as published by the Free Software Foundation.
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
16 * You should have received a copy of the GNU General Public License
17 * along with this program; if not, write to the Free Software
18 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
22 * The add_header utility used by various vendors preprends the buf
23 * image with a header containing a CRC32 value which is generated for the
24 * model id + reserved space for CRC32 + buf, then replaces the reserved
25 * area with the actual CRC32. This replacement tool mimics this behavior.
36 #include <netinet/in.h>
39 #define BPB 8 /* bits/byte */
41 static uint32_t crc32
[1<<BPB
];
43 static void init_crc32()
45 const uint32_t poly
= ntohl(0x2083b8ed);
48 for (n
= 0; n
< 1<<BPB
; n
++) {
52 for (bit
= 0; bit
< BPB
; bit
++)
53 crc
= (crc
& 1) ? (poly
^ (crc
>> 1)) : (crc
>> 1);
58 static uint32_t crc32buf(unsigned char *buf
, size_t len
)
60 uint32_t crc
= 0xFFFFFFFF;
62 for (; len
; len
--, buf
++)
63 crc
= crc32
[(uint8_t)crc
^ *buf
] ^ (crc
>> BPB
);
68 unsigned char model
[16];
72 static void usage(const char *) __attribute__ (( __noreturn__
));
74 static void usage(const char *mess
)
76 fprintf(stderr
, "Error: %s\n", mess
);
77 fprintf(stderr
, "Usage: add_header model_id input_file output_file\n");
78 fprintf(stderr
, "\n");
82 int main(int argc
, char **argv
)
84 off_t len
; // of original buf
85 off_t buflen
; // of the output file
87 void *input_file
; // pointer to the input file (mmmapped)
89 unsigned char *buf
; // pointer to prefix + copy of original buf
94 usage("wrong number of arguments");
97 if ((fd
= open(argv
[2], O_RDONLY
)) < 0
98 || (len
= lseek(fd
, 0, SEEK_END
)) < 0
99 || (input_file
= mmap(0, len
, PROT_READ
, MAP_SHARED
, fd
, 0)) == (void *) (-1)
102 fprintf(stderr
, "Error loading file %s: %s\n", argv
[2], strerror(errno
));
106 buflen
= len
+ sizeof(header
);
110 // copy model name into header
111 strncpy(header
.model
, argv
[1], sizeof(header
.model
));
114 // create a firmware image in memory and copy the input_file to it
115 buf
= malloc(buflen
);
116 memcpy(buf
, &header
, sizeof(header
));
117 memcpy(&buf
[sizeof(header
)], input_file
, len
);
119 // CRC of temporary header + buf
120 header
.crc
= htonl(crc32buf(buf
, buflen
));
122 memcpy(buf
, &header
, sizeof(header
));
125 if ((fd
= open(argv
[3], O_CREAT
|O_WRONLY
|O_TRUNC
,0644)) < 0
126 || write(fd
, buf
, buflen
) != buflen
129 fprintf(stderr
, "Error storing file %s: %s\n", argv
[3], strerror(errno
));
135 munmap(input_file
,len
);