1 // SPDX-License-Identifier: GPL-2.0-only 2 /* 3 * add_header.c - partially based on OpenWrt's motorola-bin.c 4 * 5 * Copyright (C) 2008 Imre Kaloz <kaloz@openwrt.org> 6 * Gabor Juhos <juhosg@openwrt.org> 7 */ 8 9 /* 10 * The add_header utility used by various vendors preprends the buf 11 * image with a header containing a CRC32 value which is generated for the 12 * model id + reserved space for CRC32 + buf, then replaces the reserved 13 * area with the actual CRC32. This replacement tool mimics this behavior. 14 */ 15 16 #include <stdio.h> 17 #include <stdlib.h> 18 #include <stddef.h> 19 #include <unistd.h> 20 #include <errno.h> 21 #include <fcntl.h> 22 #include <sys/mman.h> 23 #include <string.h> 24 #include <netinet/in.h> 25 #include <inttypes.h> 26 27 #define BPB 8 /* bits/byte */ 28 29 static uint32_t crc32[1<<BPB]; 30 31 static void init_crc32() 32 { 33 const uint32_t poly = ntohl(0x2083b8ed); 34 int n; 35 36 for (n = 0; n < 1<<BPB; n++) { 37 uint32_t crc = n; 38 int bit; 39 40 for (bit = 0; bit < BPB; bit++) 41 crc = (crc & 1) ? (poly ^ (crc >> 1)) : (crc >> 1); 42 crc32[n] = crc; 43 } 44 } 45 46 static uint32_t crc32buf(unsigned char *buf, size_t len) 47 { 48 uint32_t crc = 0xFFFFFFFF; 49 50 for (; len; len--, buf++) 51 crc = crc32[(uint8_t)crc ^ *buf] ^ (crc >> BPB); 52 return ~crc; 53 } 54 55 struct header { 56 char model[16]; 57 uint32_t crc; 58 }; 59 60 static void usage(const char *) __attribute__ (( __noreturn__ )); 61 62 static void usage(const char *mess) 63 { 64 fprintf(stderr, "Error: %s\n", mess); 65 fprintf(stderr, "Usage: add_header model_id input_file output_file\n"); 66 fprintf(stderr, "\n"); 67 exit(1); 68 } 69 70 int main(int argc, char **argv) 71 { 72 off_t len; // of original buf 73 off_t buflen; // of the output file 74 int fd; 75 void *input_file; // pointer to the input file (mmmapped) 76 struct header header; 77 unsigned char *buf; // pointer to prefix + copy of original buf 78 79 // verify parameters 80 81 if (argc != 4) 82 usage("wrong number of arguments"); 83 84 // mmap input_file 85 if ((fd = open(argv[2], O_RDONLY)) < 0 86 || (len = lseek(fd, 0, SEEK_END)) < 0 87 || (input_file = mmap(0, len, PROT_READ, MAP_SHARED, fd, 0)) == (void *) (-1) 88 || close(fd) < 0) 89 { 90 fprintf(stderr, "Error loading file %s: %s\n", argv[2], strerror(errno)); 91 exit(1); 92 } 93 94 buflen = len + sizeof(header); 95 96 init_crc32(); 97 98 // copy model name into header 99 strncpy(header.model, argv[1], sizeof(header.model)); 100 header.crc = 0; 101 102 // create a firmware image in memory and copy the input_file to it 103 buf = malloc(buflen); 104 memcpy(buf, &header, sizeof(header)); 105 memcpy(&buf[sizeof(header)], input_file, len); 106 107 // CRC of temporary header + buf 108 header.crc = htonl(crc32buf(buf, buflen)); 109 110 memcpy(buf, &header, sizeof(header)); 111 112 // write the buf 113 if ((fd = open(argv[3], O_CREAT|O_WRONLY|O_TRUNC,0644)) < 0 114 || write(fd, buf, buflen) != buflen 115 || close(fd) < 0) 116 { 117 fprintf(stderr, "Error storing file %s: %s\n", argv[3], strerror(errno)); 118 exit(2); 119 } 120 121 free(buf); 122 123 munmap(input_file,len); 124 125 return 0; 126 } 127
This page was automatically generated by LXR 0.3.1. • OpenWrt