• source navigation  • diff markup  • identifier search  • freetext search  • 

Sources/firmware-utils/src/mksercommfw.c

  1 // SPDX-License-Identifier: GPL-2.0-only
  2 #include <stdio.h>
  3 #include <string.h>
  4 #include <stdlib.h>
  5 #include <sys/types.h>
  6 #include <unistd.h>
  7 #include <byteswap.h>
  8 #include <endian.h>
  9 #include <getopt.h>
 10 
 11 #if !defined(__BYTE_ORDER)
 12 #error "Unknown byte order"
 13 #endif
 14 
 15 #if __BYTE_ORDER == __BIG_ENDIAN
 16 #define cpu_to_be32(x)  (x)
 17 #elif __BYTE_ORDER == __LITTLE_ENDIAN
 18 #define cpu_to_be32(x)  bswap_32(x)
 19 #else
 20 #error "Unsupported endianness"
 21 #endif
 22 
 23 /* #define DEBUG 1 */
 24 
 25 #ifdef DEBUG
 26 #define DBG(...) {printf(__VA_ARGS__); }
 27 #else
 28 #define DBG(...) {}
 29 #endif
 30 
 31 #define ERR(...) {printf(__VA_ARGS__); }
 32 
 33 /*
 34  * Fw Header Layout for Netgear / Sercomm devices (bytes)
 35  *
 36  * Size : 512 bytes + zipped image size
 37  *
 38  * Locations:
 39  * magic  : 0-6    ASCII
 40  * version: 7-11   fixed
 41  * hwID   : 11-44  ASCII
 42  * hwVer  : 45-54  ASCII
 43  * swVer  : 55-62  uint32_t in BE
 44  * magic  : 63-69  ASCII
 45  * ChkSum : 511    Inverse value of the full image checksum while this location is 0x00
 46  */
 47 static const char* magic = "sErCoMm"; /* 7 */
 48 static const unsigned char version[4] = { 0x00, 0x01, 0x00, 0x00 };
 49 static const int header_sz = 512;
 50 static const int footer_sz = 71;
 51 
 52 static int is_header = 1;
 53 
 54 struct file_info {
 55         char* file_name; /* name of the file */
 56         char* file_data; /* data of the file in memory */
 57         u_int32_t file_size; /* length of the file */
 58 };
 59 
 60 static u_int8_t getCheckSum(char* data, int len) {
 61         u_int8_t new = 0;
 62         int i;
 63 
 64         if (!data) {
 65                 ERR("Invalid pointer provided!\n");
 66                 return 0;
 67         }
 68 
 69         for (i = 0; i < len; i++) {
 70                 new += data[i];
 71         }
 72 
 73         return new;
 74 }
 75 
 76 /*
 77  * read file into buffer
 78  * add space for header/footer
 79  */
 80 static int copyToOutputBuf(struct file_info* finfo) {
 81         FILE* fp = NULL;
 82 
 83         int file_sz = 0;
 84         int extra_sz;
 85         int hdr_pos;
 86         int img_pos;
 87 
 88         if (!finfo || !finfo->file_name) {
 89                 ERR("Invalid pointer provided!\n");
 90                 return -1;
 91         }
 92 
 93         DBG("Opening file: %s\n", finfo->file_name);
 94 
 95         if (!(fp = fopen(finfo->file_name, "rb"))) {
 96                 ERR("Error opening file: %s\n", finfo->file_name);
 97                 return -1;
 98         }
 99 
100         /* Get filesize */
101         rewind(fp);
102         fseek(fp, 0L, SEEK_END);
103         file_sz = ftell(fp);
104         rewind(fp);
105 
106         if (file_sz < 1) {
107                 ERR("Error getting filesize: %s\n", finfo->file_name);
108                 fclose(fp);
109                 return -1;
110         }
111 
112         if (is_header) {
113                 extra_sz = header_sz;
114                 hdr_pos = 0;
115                 img_pos = header_sz;
116         } else {
117                 extra_sz = footer_sz;
118                 hdr_pos = file_sz;
119                 img_pos = 0;
120         }
121 
122         DBG("Filesize: %i\n", file_sz);
123         finfo->file_size = file_sz + extra_sz;
124 
125         if (!(finfo->file_data = malloc(finfo->file_size))) {
126                 ERR("Out of memory!\n");
127                 fclose(fp);
128                 return -1;
129         }
130 
131         /* init header/footer bytes */
132         memset(finfo->file_data + hdr_pos, 0, extra_sz);
133 
134         /* read file and take care of leading header if exists */
135         if (fread(finfo->file_data + img_pos, 1, file_sz, fp) != file_sz) {
136                 ERR("Error reading file %s\n", finfo->file_name);
137                 fclose(fp);
138                 return -1;
139         }
140 
141         DBG("File: read successful\n");
142         fclose(fp);
143 
144         return hdr_pos;
145 }
146 
147 static int writeFile(struct file_info* finfo) {
148         FILE* fp;
149 
150         if (!finfo || !finfo->file_name) {
151                 ERR("Invalid pointer provided!\n");
152                 return -1;
153         }
154 
155         DBG("Opening file: %s\n", finfo->file_name);
156 
157         if (!(fp = fopen(finfo->file_name, "w"))) {
158                 ERR("Error opening file: %s\n", finfo->file_name);
159                 return -1;
160         }
161 
162         DBG("Writing file: %s\n", finfo->file_name);
163 
164         if (fwrite(finfo->file_data, 1, finfo->file_size, fp) != finfo->file_size) {
165                 ERR("Wanted to write, but something went wrong!\n");
166                 fclose(fp);
167                 return -1;
168         }
169 
170         fclose(fp);
171         return 0;
172 }
173 
174 static void usage(char* argv[]) {
175         printf("Usage: %s [OPTIONS...]\n"
176                "\n"
177                "Options:\n"
178                "  -f            add sercom footer (if absent, header)\n"
179                "  -b <hwid>     use hardware id specified with <hwid> (ASCII)\n"
180                "  -r <hwrev>    use hardware revision specified with <hwrev> (ASCII)\n"
181                "  -v <version>  set image version to <version> (decimal, hex or octal notation)\n"
182                "  -i <file>     input file\n"
183                , argv[0]);
184 }
185 
186 int main(int argc, char* argv[]) {
187         struct file_info image = { 0 };
188 
189         char* hwID = NULL;
190         char* hwVer = NULL;
191         u_int32_t swVer = 0;
192         u_int8_t chkSum;
193         int hdr_offset;
194 
195         while ( 1 ) {
196                 int c;
197 
198                 c = getopt(argc, argv, "b:i:r:v:f");
199                 if (c == -1)
200                         break;
201 
202                 switch (c) {
203                 case 'b':
204                         hwID = optarg;
205                         break;
206                 case 'f':
207                         is_header = 0;
208                         break;
209                 case 'i':
210                         image.file_name = optarg;
211                         break;
212                 case 'r':
213                         hwVer = optarg;
214                         break;
215                 case 'v':
216                         swVer = (u_int32_t) strtol(optarg, NULL, 0);
217                         swVer = cpu_to_be32(swVer);
218                         break;
219                 default:
220                         usage(argv);
221                         return EXIT_FAILURE;
222                 }
223         }
224 
225         if (!hwID || !hwVer || !image.file_name) {
226                         usage(argv);
227                         return EXIT_FAILURE;
228         }
229 
230         /*
231          * copy input to buffer, add extra space for header/footer and return
232          * header position
233          */
234         hdr_offset = copyToOutputBuf(&image);
235         if (hdr_offset < 0)
236                 return EXIT_FAILURE;
237 
238         DBG("Filling header: %s %s %2X %s\n", hwID, hwVer, swVer, magic);
239 
240         strncpy(image.file_data + hdr_offset + 0, magic, 7);
241         memcpy(image.file_data + hdr_offset + 7, version, sizeof(version));
242         strncpy(image.file_data + hdr_offset + 11, hwID, 34);
243         strncpy(image.file_data + hdr_offset + 45, hwVer, 10);
244         memcpy(image.file_data + hdr_offset + 55, &swVer, sizeof(swVer));
245         strncpy(image.file_data + hdr_offset + 63, magic, 7);
246 
247         /* calculate checksum and invert checksum */
248         if (is_header) {
249                 chkSum = getCheckSum(image.file_data, image.file_size);
250                 chkSum = (chkSum ^ 0xFF) + 1;
251                 DBG("Checksum for Image: %hhX\n", chkSum);
252 
253                 /* write checksum to header */
254                 image.file_data[511] = (char) chkSum;
255         }
256 
257         /* overwrite input file */
258         if (writeFile(&image))
259                 return EXIT_FAILURE;
260 
261         return EXIT_SUCCESS;
262 }
263 

This page was automatically generated by LXR 0.3.1.  •  OpenWrt