1 // SPDX-License-Identifier: GPL-2.0-only 2 /* 3 * mkbrnimg.c - partially based on OpenWrt's wndr3700.c 4 * 5 * Copyright (C) 2011 Tobias Diedrich <ranma+openwrt@tdiedrich.de> 6 */ 7 8 #include <stdio.h> 9 #include <stdlib.h> 10 #include <stddef.h> 11 #include <unistd.h> 12 #include <errno.h> 13 #include <fcntl.h> 14 #include <sys/mman.h> 15 #include <string.h> 16 #include <netinet/in.h> 17 #include <inttypes.h> 18 19 #define BPB 8 /* bits/byte */ 20 21 static uint32_t crc32[1<<BPB]; 22 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; 27 28 static void init_crc32() 29 { 30 const uint32_t poly = ntohl(crc32_poly); 31 int n; 32 33 for (n = 0; n < 1<<BPB; n++) { 34 uint32_t crc = n; 35 int bit; 36 37 for (bit = 0; bit < BPB; bit++) 38 crc = (crc & 1) ? (poly ^ (crc >> 1)) : (crc >> 1); 39 crc32[n] = crc; 40 } 41 } 42 43 static uint32_t crc32buf(const void *buf, size_t len) 44 { 45 uint32_t crc = 0xFFFFFFFF; 46 const uint8_t *in = buf; 47 48 for (; len; len--, in++) 49 crc = crc32[(uint8_t)crc ^ *in] ^ (crc >> BPB); 50 return ~crc; 51 } 52 53 static void usage(const char *) __attribute__ (( __noreturn__ )); 54 55 static void usage(const char *mess) 56 { 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"); 60 exit(1); 61 } 62 63 static void parseopts(int *argc, char ***argv) 64 { 65 char *endptr; 66 int res; 67 68 while ((res = getopt(*argc, *argv, "o:m:s:p:")) != -1) { 69 switch (res) { 70 default: 71 usage("Unknown option"); 72 break; 73 case 'o': 74 output_file = optarg; 75 break; 76 case 'm': 77 magic = strtoul(optarg, &endptr, 0); 78 if (endptr == optarg || *endptr != 0) 79 usage("magic must be a decimal or hexadecimal 32-bit value"); 80 break; 81 case 's': 82 signature = optarg; 83 break; 84 case 'p': 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"); 88 break; 89 } 90 } 91 *argc -= optind; 92 *argv += optind; 93 } 94 95 static void appendfile(int outfd, char *path, int kernel) { 96 int fd; 97 size_t len, padded_len; 98 char *input_file; 99 uint32_t crc; 100 char padding[0x400]; 101 char footer[12]; 102 103 memset(padding, 0xff, sizeof(padding)); 104 105 // mmap input_file 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) 109 || close(fd) < 0) 110 { 111 fprintf(stderr, "Error mapping file '%s': %s\n", path, strerror(errno)); 112 exit(1); 113 } 114 115 // kernel should be lzma compressed image, not uImage 116 if (kernel && 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"); 122 exit(1); 123 } 124 125 init_crc32(); 126 crc = crc32buf(input_file, len); 127 fprintf(stderr, "crc32 for '%s' is %08x.\n", path, crc); 128 129 // write the file 130 write(outfd, input_file, len); 131 132 // write padding 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); 136 137 // write footer 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)); 151 152 munmap(input_file, len); 153 } 154 155 int main(int argc, char **argv) 156 { 157 int outfd; 158 int i; 159 160 parseopts(&argc, &argv); 161 162 if (argc < 1) 163 usage("wrong number of arguments"); 164 165 if ((outfd = open(output_file, O_WRONLY|O_CREAT|O_TRUNC, 0644)) == -1) 166 { 167 fprintf(stderr, "Error opening '%s' for writing: %s\n", output_file, strerror(errno)); 168 exit(1); 169 } 170 171 for (i=0; i<argc; i++) { 172 appendfile(outfd, argv[i], i == 0); 173 } 174 write(outfd, signature, strlen(signature)+1); 175 close(outfd); 176 177 return 0; 178 } 179
This page was automatically generated by LXR 0.3.1. • OpenWrt