1 // SPDX-License-Identifier: GPL-2.0-or-later 2 /* 3 * Copyright (C) 2020 Andreas Boehler <dev@aboehler.at> 4 * 5 * This tool was based on: 6 * firmware-crc.pl by Atheros Communications 7 * 8 * This program is free software; you can redistribute it and/or modify it 9 * under the terms of the GNU General Public License version 2 as published 10 * by the Free Software Foundation. 11 * 12 */ 13 14 #include <stdlib.h> 15 #include <stdio.h> 16 #include <stdint.h> 17 #include <string.h> 18 #include <getopt.h> /* for getopt() */ 19 #include <byteswap.h> 20 21 char *infile; 22 char *outfile; 23 char *progname; 24 enum { 25 MODEL_3390, 26 MODEL_X490 27 } model; 28 29 #define CHUNK_SIZE 256 30 31 uint32_t crc32_for_byte(uint32_t r) 32 { 33 for (int j = 0; j < 8; ++j) 34 r = (r & 1 ? 0 : (uint32_t)0xEDB88320L) ^ r >> 1; 35 return r ^ (uint32_t)0xFF000000L; 36 } 37 38 void crc32(const void *data, size_t n_bytes, uint32_t *crc) 39 { 40 static uint32_t table[0x100]; 41 42 if (!*table) 43 for (size_t i = 0; i < 0x100; ++i) 44 table[i] = crc32_for_byte(i); 45 for (size_t i = 0; i < n_bytes; ++i) 46 *crc = table[(uint8_t)*crc ^ ((uint8_t *)data)[i]] ^ *crc >> 8; 47 } 48 49 static void usage(int status) 50 { 51 fprintf(stderr, "Usage: %s [OPTIONS...]\n", progname); 52 fprintf(stderr, 53 "\n" 54 "Options:\n" 55 " -i input file name\n" 56 " -o output file name\n" 57 " -m model (3390, x490 for 3490/5490/7490)\n" 58 " -h show this screen\n" 59 ); 60 61 exit(status); 62 } 63 64 int main(int argc, char *argv[]) 65 { 66 uint32_t crc = 0; 67 FILE *in_fp; 68 FILE *out_fp; 69 uint32_t buf[CHUNK_SIZE]; 70 size_t read; 71 72 progname = argv[0]; 73 74 while (1) { 75 int c; 76 77 c = getopt(argc, argv, "i:o:m:h"); 78 if (c == -1) 79 break; 80 81 switch (c) { 82 case 'i': 83 infile = optarg; 84 break; 85 case 'o': 86 outfile = optarg; 87 break; 88 case 'm': 89 if (strcmp(optarg, "3390") == 0) 90 model = MODEL_3390; 91 else if (strcmp(optarg, "x490") == 0) 92 model = MODEL_X490; 93 else 94 usage(EXIT_FAILURE); 95 break; 96 case 'h': 97 usage(EXIT_SUCCESS); 98 default: 99 usage(EXIT_FAILURE); 100 break; 101 } 102 } 103 104 if (!infile || !outfile) 105 usage(EXIT_FAILURE); 106 107 in_fp = fopen(infile, "r"); 108 if (!in_fp) { 109 fprintf(stderr, "Error opening input file: %s\n", infile); 110 return EXIT_FAILURE; 111 } 112 out_fp = fopen(outfile, "w"); 113 if (!out_fp) { 114 fprintf(stderr, "Error opening output file: %s\n", outfile); 115 fclose(in_fp); 116 return EXIT_FAILURE; 117 } 118 119 while (!feof(in_fp)) { 120 switch (model) { 121 case MODEL_3390: 122 read = fread(buf, sizeof(uint32_t), CHUNK_SIZE, in_fp); 123 if (ferror(in_fp)) { 124 fprintf(stderr, "Error reading input file: %s\n", infile); 125 fclose(in_fp); 126 fclose(out_fp); 127 return EXIT_FAILURE; 128 } 129 for (int i = 0; i < read; i++) 130 crc = crc ^ buf[i]; 131 fwrite(buf, sizeof(uint32_t), read, out_fp); 132 if (ferror(out_fp)) { 133 fprintf(stderr, "Error writing output file: %s\n", outfile); 134 fclose(in_fp); 135 fclose(out_fp); 136 return EXIT_FAILURE; 137 } 138 break; 139 case MODEL_X490: 140 read = fread(buf, 1, sizeof(uint32_t) * CHUNK_SIZE, in_fp); 141 if (ferror(in_fp)) { 142 fprintf(stderr, "Error reading input file: %s\n", infile); 143 fclose(in_fp); 144 fclose(out_fp); 145 return EXIT_FAILURE; 146 } 147 crc32(buf, read, &crc); 148 fwrite(buf, 1, read, out_fp); 149 if (ferror(out_fp)) { 150 fprintf(stderr, "Error writing output file: %s\n", outfile); 151 fclose(in_fp); 152 fclose(out_fp); 153 return EXIT_FAILURE; 154 } 155 break; 156 } 157 } 158 if (model == MODEL_X490) 159 crc = bswap_32(crc); 160 fwrite(&crc, sizeof(uint32_t), 1, out_fp); 161 if (ferror(out_fp)) { 162 fprintf(stderr, "Error writing checksum to output file: %s\n", outfile); 163 fclose(in_fp); 164 fclose(out_fp); 165 return EXIT_FAILURE; 166 } 167 fclose(in_fp); 168 fclose(out_fp); 169 printf("Done.\n"); 170 return EXIT_SUCCESS; 171 } 172
This page was automatically generated by LXR 0.3.1. • OpenWrt