654a6bd09bdc7e1460e139fd97ffc12bc9fd5404
[openwrt/staging/mkresin.git] / tools / firmware-utils / src / mktitanimg.c
1 // SPDX-License-Identifier: GPL-2.0-only
2 #include <stdio.h>
3 #include <stdlib.h>
4 #include <string.h>
5 #include <libgen.h>
6 #include "mktitanimg.h"
7
8
9 struct checksumrecord
10 {
11 unsigned int magic;
12 unsigned int chksum; /* The checksum for the complete header.
13 Excepting the
14 checksum block */
15 };
16 /***************************************************************************
17 * void print_help(void)
18 ***************************************************************************/
19 void print_help(void)
20 {
21 static char* help_page[]=
22 {
23 "mknspimg version 1.0, Texas Instruments, 2004",
24 "Syntax:",
25 " mknspimg -o outfile -i image1 image2 -a align1 align2 [-v] [-b] [-p prod_id] [-r rel_id] [-s rel_name] [-f flags]",
26 "Example:",
27 " mknspimg -o nsp_image.bin -i kernel.bin files.img -a 0 4096",
28 "This generates 'nsp_image.bin' from two input files aligning first to 0 and second to 4096 bytes."
29 };
30
31 int num_lines = sizeof(help_page)/sizeof(char*);
32 int i;
33 for(i=0; i < num_lines; i++) {
34 printf("%s\n", help_page[i]);
35 }
36 }
37
38 /***************************************************************************
39 * void mknspimg_print_hdr(NSP_IMG_HDR* p_img_hdr)
40 ***************************************************************************/
41 void mknspimg_print_hdr(struct nsp_img_hdr *hdr)
42 {
43 struct nsp_img_hdr_chksum *chksum;
44 struct nsp_img_hdr_sections *section;
45 int i;
46
47 printf("****************** NSP Image Summary ******************\n");
48 printf("Magic: 0x%x\n", hdr->head.magic);
49 printf("Image Header Size: 0x%x bytes\n", hdr->head.hdr_size);
50 printf("Total Image Size: %d bytes\n", hdr->head.image_size);
51 printf("Product ID: 0x%x\n", hdr->head.prod_id);
52 printf("Release ID: 0x%x\n", hdr->head.rel_id);
53 printf("Version ID: 0x%x\n", hdr->head.version);
54
55 printf("Offset Info: 0x%x\n", hdr->head.info_offset);
56 printf("Offset Sect info: 0x%x\n", hdr->head.sect_info_offset);
57 printf("Offset Sections: 0x%x\n", hdr->sect_info.sections_offset);
58
59 chksum=(struct nsp_img_hdr_chksum *)(hdr+hdr->head.chksum_offset);
60 printf("Header Checksum: 0x%x\n", chksum->hdr_chksum);
61
62 printf("+++ Section Information +++\n");
63 printf("# of sections: %u\n", hdr->sect_info.num_sects);
64 section=&(hdr->sections);
65 for(i = 0; i < hdr->sect_info.num_sects; i++, section++) {
66 printf("+++++ Section %d +++++\n", i);
67 printf("Total size: %u bytes\n", section->total_size);
68 printf("Raw Size: %u bytes\n", section->raw_size);
69 printf("Offset: 0x%x\n", section->offset);
70 printf("Type: 0x%x\n", section->type);
71 printf("Name: %s\n", section->name);
72 }
73 printf("*******************************************************\n");
74 }
75
76 CMDLINE_CFG cmd_line_cfg =
77 {
78 {
79 /* MIN MAX FLAGS OPTION */
80 { 2, 2, (CMDLINE_OPTFLAG_ALLOW | CMDLINE_OPTFLAG_MANDAT) }, /* '-a' align1 align2 */
81 { 0, 0, CMDLINE_OPTFLAG_ALLOW }, /* '-b' bootstrap */
82 { 0, 0, !CMDLINE_OPTFLAG_ALLOW }, /* '-c' */
83 { 0, 0, !CMDLINE_OPTFLAG_ALLOW }, /* '-d' */
84 { 0, 0, !CMDLINE_OPTFLAG_ALLOW }, /* '-e' */
85 { 1, 1, CMDLINE_OPTFLAG_ALLOW }, /* '-f' flags */
86 { 0, 0, !CMDLINE_OPTFLAG_ALLOW }, /* '-g' */
87 { 1, 1, CMDLINE_OPTFLAG_ALLOW }, /* '-h' */
88 { 2, 2, (CMDLINE_OPTFLAG_ALLOW | CMDLINE_OPTFLAG_MANDAT) }, /* '-i arg1 arg2 ' */
89 { 0, 0, !CMDLINE_OPTFLAG_ALLOW }, /* '-j' */
90 { 0, 0, !CMDLINE_OPTFLAG_ALLOW }, /* '-k' */
91 { 0, 0, !CMDLINE_OPTFLAG_ALLOW }, /* '-l' */
92 { 0, 0, !CMDLINE_OPTFLAG_ALLOW }, /* '-m' */
93 { 0, 0, !CMDLINE_OPTFLAG_ALLOW }, /* '-n' */
94 { 1, 1, (CMDLINE_OPTFLAG_ALLOW | CMDLINE_OPTFLAG_MANDAT) }, /* '-o arg' */
95 { 1, 1, CMDLINE_OPTFLAG_ALLOW }, /* '-p' PROD_ID */
96 { 0, 0, !CMDLINE_OPTFLAG_ALLOW }, /* '-q' */
97 { 1, 1, CMDLINE_OPTFLAG_ALLOW }, /* '-r' REL_ID */
98 { 1, 1, CMDLINE_OPTFLAG_ALLOW }, /* '-s' "Release XXX.XXX" */
99 { 0, 0, !CMDLINE_OPTFLAG_ALLOW }, /* '-t' */
100 { 0, 0, !CMDLINE_OPTFLAG_ALLOW }, /* '-u' */
101 { 0, 0, CMDLINE_OPTFLAG_ALLOW }, /* '-v' control VERBOSE/NON-VERBOSE mode */
102 { 0, 0, !CMDLINE_OPTFLAG_ALLOW }, /* '-w' */
103 { 0, 0, !CMDLINE_OPTFLAG_ALLOW }, /* '-x' */
104 { 0, 0, !CMDLINE_OPTFLAG_ALLOW }, /* '-y' */
105 { 0, 0, !CMDLINE_OPTFLAG_ALLOW } /* '-z' */
106 },
107 { 0, 0, !CMDLINE_OPTFLAG_ALLOW }, /* global arguments */
108 };
109
110 /***************************************************************************
111 * int nsp_img_write(void* image, char* file, int padding)
112 * Write out the image.
113 ***************************************************************************/
114 int main(int argc, char* argv[], char* env[])
115 {
116 FILE* nsp_image = NULL;
117 int header_version=1;
118 int cmdline_err;
119 char* cmdline_error_msg;
120
121 char* filen_out;
122
123 int i,count; /* loop variables */
124 int num_sects = 2; /* We require exactly two image with -i option
125 (see CMDLINE_CFG structure above) */
126 int total = 0;
127
128 int header_size=0;
129 struct nsp_img_hdr_head *img_hdr_head; /* Start of image header */
130 struct nsp_img_hdr_info *img_hdr_info;
131 struct nsp_img_hdr_section_info *img_hdr_section_info ;
132 struct nsp_img_hdr_sections *img_hdr_sections, *section; /* Section pointers */
133
134
135 /* Configure the command line. */
136 cmdline_configure(&cmd_line_cfg);
137
138 /* Read and parse the command line. */
139 cmdline_err = cmdline_read(argc, argv);
140
141 /* Check for parsing errors. */
142 if(cmdline_err != 0) {
143 /* Get the parse error message */
144 cmdline_error_msg = cmdline_error(cmdline_err);
145
146 /* Print it out */
147 printf("%s\n", cmdline_error_msg);
148
149 /* Print our help too */
150 print_help();
151 return -1;
152 }
153 if(cmdline_getopt_count('h') > 0)
154 {
155 header_version=atoi(argv[cmdline_getarg(cmdline_getarg_list('h'),0)]);
156 }
157 /* Set up arguments */
158 filen_out = argv[cmdline_getarg(cmdline_getarg_list('o'),0)];
159 /* Command line arguments have been parsed. Start doing our work. */
160
161 /* Caculate the header size, and allocate the memory, and assign the sub pointers */
162 header_size = sizeof(struct nsp_img_hdr_head) + /* This has a single section
163 desc block already */
164 (header_version==1?0:4) +
165 sizeof(struct nsp_img_hdr_info) +
166 sizeof(struct nsp_img_hdr_section_info) +
167 sizeof(struct nsp_img_hdr_sections) * num_sects ;
168
169 img_hdr_head = (struct nsp_img_hdr_head *)malloc(header_size);
170 memset(img_hdr_head, 0x0, header_size);
171 img_hdr_info = (struct nsp_img_hdr_info*)((char *)img_hdr_head + sizeof(struct nsp_img_hdr_head) + (header_version==1?0:4));
172 img_hdr_section_info = (struct nsp_img_hdr_section_info*)((char *)img_hdr_info + sizeof(struct nsp_img_hdr_info));
173 img_hdr_sections = (struct nsp_img_hdr_sections*)((char *)img_hdr_section_info + sizeof(struct nsp_img_hdr_section_info));
174 section = img_hdr_sections;
175 memset(img_hdr_head, 0xff, (void*)img_hdr_info - (void*)img_hdr_head);
176
177 img_hdr_head->hdr_version = header_version;
178 img_hdr_head->hdr_size = header_size;
179 img_hdr_head->info_offset = (void*)img_hdr_info - (void*)img_hdr_head;
180 img_hdr_head->sect_info_offset = (void*)img_hdr_section_info - (void*)img_hdr_head;
181
182 img_hdr_section_info->num_sects = num_sects;
183 img_hdr_section_info->sect_size = sizeof(struct nsp_img_hdr_sections);
184 img_hdr_section_info->sections_offset = (void*)img_hdr_sections - (void*)img_hdr_head;
185
186 /* chksum = (struct nsp_img_hdr_chksum *)
187 ((unsigned int)image_hdr + header_size - sizeof(struct nsp_img_hdr_chksum));*/
188
189 /* Open the out file */
190 nsp_image = fopen(filen_out,"wb+");
191 if(nsp_image==NULL) {
192 printf("ERROR: can't open %s for writing.\n", filen_out);
193 return -1;
194 }
195
196 /* Skip image header. We'll come back to it after we've written out the images. */
197 fseek(nsp_image,header_size,SEEK_SET);
198 total = ftell(nsp_image);
199 total = header_size;
200 printf("total=%x\n",total);
201 {
202 int align;
203 int padding;
204 char * buf;
205 align = (header_version==1?0x10000:0x4000);
206 if(align==0) {
207 /* The user indicated no padding */
208 padding = 0;
209 } else {
210 /* Calculate number padding bytes */
211 if((total %align) ==0)
212 padding=0;
213 else
214 padding = align - (total % align);
215 }
216 if(padding>0)
217 {
218 buf=malloc(padding);
219 memset(buf, 0xff, padding);
220 if(fwrite((void*)buf,1,padding,nsp_image)!=padding) {
221 printf("ERROR: can't write to %s.\n", filen_out);
222 free(buf);
223 fclose(nsp_image);
224 return -1;
225 }
226 free(buf);
227
228 }
229 total+=padding;
230
231
232 }
233 /* Write out all specified images (with -i option) */
234 for(i=0; i < num_sects; i++) {
235 char* file_name; /* input file name */
236 FILE* filep; /* input file pointer */
237 int padding; /* number of padding bytes to prepend */
238 int align; /* align factor from command line */
239 int result; /* intermediate result */
240 char * buf;
241
242 /* Open the specified image for reading */
243 file_name = argv[cmdline_getarg(cmdline_getarg_list('i'),i)];
244 filep = fopen(file_name, "rb");
245 if(filep==NULL) {
246 printf("ERROR: can't open file %s for reading.\n", file_name);
247 return -1;
248 }
249 section->flags = ~0x00;
250 /* Determine file size */
251 fseek(filep,0,SEEK_END);
252 section->raw_size=ftell(filep);
253 fseek(filep,0,SEEK_SET);
254 cs_calc_sum(filep,(unsigned long *)&section->chksum,0);
255 fseek(filep,0,SEEK_SET);
256
257 /* Retrieve the alignment constant */
258 /* Set image offset from the beginning of the out file */
259 section->offset=total;// + padding;
260
261 //total += padding;
262
263 /* Copy the image file into nsp_image */
264 count = section->raw_size;
265 buf=malloc(count);
266 result=fread(buf, 1, count, filep);
267 fwrite(buf, 1, result, nsp_image);
268 free(buf);
269
270 /* HACK: This is a hack to get the names and types to the files.
271 TODO: Fix this to be a real method */
272 if(i==0){
273 section->type=NSP_IMG_SECTION_TYPE_KERNEL;
274 strncpy(section->name, "kernel", 16);
275 } else if(i==1){
276 section->type=NSP_IMG_SECTION_TYPE_FILESYSTEM_ROOT;
277 strncpy(section->name, "root", 16);
278 }
279
280 /* Account for the total */
281 align = strtoul(argv[cmdline_getarg(cmdline_getarg_list('a'),i)],NULL,0);
282 if(i==0){
283 if(align==0 || (((section->raw_size+ section->offset)%align)==0))
284 padding=0;
285 else
286 padding = align - ((section->raw_size+ section->offset) % align);
287
288 section->total_size=section->raw_size + padding;
289 }
290 else{
291 #define EXTRA_BLOCK 0x10000
292 unsigned int squash_padding;
293 squash_padding = EXTRA_BLOCK - section->raw_size % EXTRA_BLOCK;
294 buf=malloc(EXTRA_BLOCK + 4);
295 memset(buf, 0, squash_padding);
296 fwrite(buf, 1, squash_padding, nsp_image);
297 memset(buf, 0, EXTRA_BLOCK + 4);
298 *((unsigned int *)buf)=0xdec0adde;
299 *((unsigned int *)(buf+EXTRA_BLOCK))=0xdec0adde;
300 fwrite(buf, 1, EXTRA_BLOCK+4, nsp_image);
301 free(buf);
302
303 if(align==0 || (((section->raw_size + (EXTRA_BLOCK + 4 + squash_padding)) %align)==0))
304 padding=0;
305 else
306 padding = align - ((section->raw_size + (EXTRA_BLOCK + 4 + squash_padding)) % align);
307 section->total_size=section->raw_size + (EXTRA_BLOCK + 4 + squash_padding) + padding;
308 }
309 if(padding>0){
310 buf=malloc(padding);
311 memset(buf, 0xff, padding);
312 fwrite(buf, 1, padding, nsp_image);
313 free(buf);
314 }
315 printf("*****padding is %d\ttotal_size=%d\traw_size=%d\n",padding, section->total_size, section->raw_size);
316
317 //total += section->raw_size;
318 total = section->total_size + section->offset;
319 printf("total=0x%x\n",total);
320 /* Close the input file */
321 fclose(filep);
322
323 /* Move the section pointer to the next slot */
324 section++;
325 }
326
327 /* Take care of the NSP image header fields */
328
329 /* head fields */
330 img_hdr_head->magic = NSP_IMG_MAGIC_NUMBER;
331 img_hdr_head->boot_offset = img_hdr_sections->offset;
332 img_hdr_head->flags = ~0x00; /* Set to all 1's */
333
334 if(cmdline_getopt_count('b'))
335 img_hdr_head->flags &= ~(NSP_IMG_FLAG_FAILBACK_5 | NSP_IMG_FLAG_FAILBACK_1);
336
337 if(cmdline_getopt_count('f'))
338 img_hdr_head->flags = strtoul(argv[cmdline_getarg(cmdline_getarg_list('f'),0)], 0, 16);
339
340 #if 0
341 img_hdr_head->hdr_version = 2;
342 img_hdr_head->hdr_size = header_size;
343 #endif
344
345 if(cmdline_getopt_count('p'))
346 img_hdr_head->prod_id = strtoul(argv[cmdline_getarg(cmdline_getarg_list('p'),0)], 0, 16);
347 else
348 img_hdr_head->prod_id = 0x4C575943;
349
350 if(cmdline_getopt_count('r'))
351 img_hdr_head->rel_id = strtoul(argv[cmdline_getarg(cmdline_getarg_list('r'),0)], 0, 0);
352 else
353 img_hdr_head->rel_id = 0x10203040;
354
355 if(cmdline_getopt_count('s'))
356 img_hdr_head->version = strtoul(argv[cmdline_getarg(cmdline_getarg_list('s'),0)], 0, 0);
357 else
358 img_hdr_head->version = 0x0b040000;
359 img_hdr_head->image_size = total;
360 #if 0
361 img_hdr_head->info_offset = (unsigned int)(&(image_hdr->info)) -
362 (unsigned int)image_hdr;
363 img_hdr_head->sect_info_offset= (unsigned int)(&(image_hdr->sect_info)) -
364 (unsigned int)image_hdr;
365 #endif
366 // image_hdr->head.chksum_offset = (unsigned int)chksum - (unsigned int)image_hdr;
367 img_hdr_head->chksum_offset = 0xffffffff;
368 // image_hdr->head.pad1 = 0xffffffff;
369 /* info fields */
370 /* TODO: Fix. Do nothing yet */
371 // strncpy(nsp_img_hdr.id.prod_info,NSP_PRODINFO_STRING,sizeof(NSP_PRODINFO_STRING));
372 strcpy(img_hdr_info->image_filename, (const char *)basename(filen_out));
373 /* section fields */
374 #if 0
375 img_hdr_section_info->num_sects= num_sects;
376 img_hdr_section_info->sect_size= sizeof(struct nsp_img_hdr_sections);
377 img_hdr_section_info->sections_offset= (unsigned int)(&(image_hdr->sections)) -
378 (unsigned int)image_hdr;
379 #endif
380
381 /* Calculate checksum(s) */
382 #if 0
383 chksum->hdr_chksum = cs_calc_buf_sum((char*)image_hdr,
384 header_size - sizeof(struct nsp_img_hdr_chksum));
385 #endif
386 /* Write out the NSP header. */
387 fseek(nsp_image,0,SEEK_SET);
388 count = fwrite((void*)img_hdr_head, header_size, 1, nsp_image);
389 if(count!=1) {
390 printf("ERROR: can't write to %s.\n", filen_out);
391 return -1;
392 }
393
394 /* Check if -v option was specified (no arg needed) */
395 if(cmdline_getopt_count('v') > 0)
396 {
397 struct nsp_img_hdr_head head;
398 struct nsp_img_hdr *hdr;
399
400 /* Rewind the file back to the beginning */
401 fseek(nsp_image,0,SEEK_SET);
402
403 /* Read header from the file */
404 fread((void*)&head, sizeof(struct nsp_img_hdr_head),
405 1, nsp_image);
406
407 /* Get memory to store the complete header */
408 hdr = (struct nsp_img_hdr *)malloc(head.hdr_size);
409
410 /* Read header from the file */
411 fseek(nsp_image,0,SEEK_SET);
412 fread((void*)hdr, head.hdr_size, 1, nsp_image);
413
414 /* Print it out */
415 mknspimg_print_hdr(hdr);
416 printf("Generated total %d bytes\n",total);
417 free(hdr);
418 }
419
420 free(img_hdr_head);
421
422 {
423 struct checksumrecord cr;
424 cr.magic=CKSUM_MAGIC_NUMBER;
425 cs_calc_sum(nsp_image, (unsigned long *)&cr.chksum, 0);
426 fseek(nsp_image,0, SEEK_END);
427 fwrite(&cr, 1, sizeof(cr), nsp_image);
428 }
429 {
430 FILE * non_web;
431 char fname[256];
432 char * img_buf;
433 unsigned int len;
434 strcpy(fname, filen_out);
435 strcat(fname, ".non_web");
436 non_web = fopen(fname,"wb+");
437 fseek(nsp_image, 0, SEEK_END);
438 len = ftell(nsp_image);
439 img_buf=malloc(len);
440 fseek(nsp_image, 0, SEEK_SET);
441 fread(img_buf, 1, len, nsp_image);
442 img_buf[0xb] = 0x17;
443 fwrite(img_buf, 1, len-sizeof(struct checksumrecord), non_web);
444 fclose(non_web);
445 free(img_buf);
446 }
447 /* Close NSP image file */
448 fclose(nsp_image);
449
450 /* return result */
451 return(0);
452 }
453
454 #ifdef DMALLOC
455 #include <dmalloc.h>
456 #endif /* DMALLOC */
457
458 #define BUFLEN (1 << 16)
459
460 static unsigned long crctab[256] =
461 {
462 0x0,
463 0x04C11DB7, 0x09823B6E, 0x0D4326D9, 0x130476DC, 0x17C56B6B,
464 0x1A864DB2, 0x1E475005, 0x2608EDB8, 0x22C9F00F, 0x2F8AD6D6,
465 0x2B4BCB61, 0x350C9B64, 0x31CD86D3, 0x3C8EA00A, 0x384FBDBD,
466 0x4C11DB70, 0x48D0C6C7, 0x4593E01E, 0x4152FDA9, 0x5F15ADAC,
467 0x5BD4B01B, 0x569796C2, 0x52568B75, 0x6A1936C8, 0x6ED82B7F,
468 0x639B0DA6, 0x675A1011, 0x791D4014, 0x7DDC5DA3, 0x709F7B7A,
469 0x745E66CD, 0x9823B6E0, 0x9CE2AB57, 0x91A18D8E, 0x95609039,
470 0x8B27C03C, 0x8FE6DD8B, 0x82A5FB52, 0x8664E6E5, 0xBE2B5B58,
471 0xBAEA46EF, 0xB7A96036, 0xB3687D81, 0xAD2F2D84, 0xA9EE3033,
472 0xA4AD16EA, 0xA06C0B5D, 0xD4326D90, 0xD0F37027, 0xDDB056FE,
473 0xD9714B49, 0xC7361B4C, 0xC3F706FB, 0xCEB42022, 0xCA753D95,
474 0xF23A8028, 0xF6FB9D9F, 0xFBB8BB46, 0xFF79A6F1, 0xE13EF6F4,
475 0xE5FFEB43, 0xE8BCCD9A, 0xEC7DD02D, 0x34867077, 0x30476DC0,
476 0x3D044B19, 0x39C556AE, 0x278206AB, 0x23431B1C, 0x2E003DC5,
477 0x2AC12072, 0x128E9DCF, 0x164F8078, 0x1B0CA6A1, 0x1FCDBB16,
478 0x018AEB13, 0x054BF6A4, 0x0808D07D, 0x0CC9CDCA, 0x7897AB07,
479 0x7C56B6B0, 0x71159069, 0x75D48DDE, 0x6B93DDDB, 0x6F52C06C,
480 0x6211E6B5, 0x66D0FB02, 0x5E9F46BF, 0x5A5E5B08, 0x571D7DD1,
481 0x53DC6066, 0x4D9B3063, 0x495A2DD4, 0x44190B0D, 0x40D816BA,
482 0xACA5C697, 0xA864DB20, 0xA527FDF9, 0xA1E6E04E, 0xBFA1B04B,
483 0xBB60ADFC, 0xB6238B25, 0xB2E29692, 0x8AAD2B2F, 0x8E6C3698,
484 0x832F1041, 0x87EE0DF6, 0x99A95DF3, 0x9D684044, 0x902B669D,
485 0x94EA7B2A, 0xE0B41DE7, 0xE4750050, 0xE9362689, 0xEDF73B3E,
486 0xF3B06B3B, 0xF771768C, 0xFA325055, 0xFEF34DE2, 0xC6BCF05F,
487 0xC27DEDE8, 0xCF3ECB31, 0xCBFFD686, 0xD5B88683, 0xD1799B34,
488 0xDC3ABDED, 0xD8FBA05A, 0x690CE0EE, 0x6DCDFD59, 0x608EDB80,
489 0x644FC637, 0x7A089632, 0x7EC98B85, 0x738AAD5C, 0x774BB0EB,
490 0x4F040D56, 0x4BC510E1, 0x46863638, 0x42472B8F, 0x5C007B8A,
491 0x58C1663D, 0x558240E4, 0x51435D53, 0x251D3B9E, 0x21DC2629,
492 0x2C9F00F0, 0x285E1D47, 0x36194D42, 0x32D850F5, 0x3F9B762C,
493 0x3B5A6B9B, 0x0315D626, 0x07D4CB91, 0x0A97ED48, 0x0E56F0FF,
494 0x1011A0FA, 0x14D0BD4D, 0x19939B94, 0x1D528623, 0xF12F560E,
495 0xF5EE4BB9, 0xF8AD6D60, 0xFC6C70D7, 0xE22B20D2, 0xE6EA3D65,
496 0xEBA91BBC, 0xEF68060B, 0xD727BBB6, 0xD3E6A601, 0xDEA580D8,
497 0xDA649D6F, 0xC423CD6A, 0xC0E2D0DD, 0xCDA1F604, 0xC960EBB3,
498 0xBD3E8D7E, 0xB9FF90C9, 0xB4BCB610, 0xB07DABA7, 0xAE3AFBA2,
499 0xAAFBE615, 0xA7B8C0CC, 0xA379DD7B, 0x9B3660C6, 0x9FF77D71,
500 0x92B45BA8, 0x9675461F, 0x8832161A, 0x8CF30BAD, 0x81B02D74,
501 0x857130C3, 0x5D8A9099, 0x594B8D2E, 0x5408ABF7, 0x50C9B640,
502 0x4E8EE645, 0x4A4FFBF2, 0x470CDD2B, 0x43CDC09C, 0x7B827D21,
503 0x7F436096, 0x7200464F, 0x76C15BF8, 0x68860BFD, 0x6C47164A,
504 0x61043093, 0x65C52D24, 0x119B4BE9, 0x155A565E, 0x18197087,
505 0x1CD86D30, 0x029F3D35, 0x065E2082, 0x0B1D065B, 0x0FDC1BEC,
506 0x3793A651, 0x3352BBE6, 0x3E119D3F, 0x3AD08088, 0x2497D08D,
507 0x2056CD3A, 0x2D15EBE3, 0x29D4F654, 0xC5A92679, 0xC1683BCE,
508 0xCC2B1D17, 0xC8EA00A0, 0xD6AD50A5, 0xD26C4D12, 0xDF2F6BCB,
509 0xDBEE767C, 0xE3A1CBC1, 0xE760D676, 0xEA23F0AF, 0xEEE2ED18,
510 0xF0A5BD1D, 0xF464A0AA, 0xF9278673, 0xFDE69BC4, 0x89B8FD09,
511 0x8D79E0BE, 0x803AC667, 0x84FBDBD0, 0x9ABC8BD5, 0x9E7D9662,
512 0x933EB0BB, 0x97FFAD0C, 0xAFB010B1, 0xAB710D06, 0xA6322BDF,
513 0xA2F33668, 0xBCB4666D, 0xB8757BDA, 0xB5365D03, 0xB1F740B4
514 };
515
516 int cs_is_tagged(FILE *fp)
517 {
518 char buf[8];
519
520 fseek(fp, -8, SEEK_END);
521 fread(buf, 8, 1, fp);
522 if(*(unsigned long*)buf == CKSUM_MAGIC_NUMBER)
523 return 1;
524 return 0;
525 }
526
527 unsigned long cs_read_sum(FILE *fp)
528 {
529 char buf[8];
530
531 fseek(fp, -8, SEEK_END);
532 fread(buf, 8, 1, fp);
533 return *((unsigned long*)&buf[4]);
534 }
535
536 int cs_calc_sum(FILE *fp, unsigned long *res, int tagged)
537 {
538 unsigned char buf[BUFLEN];
539 unsigned long crc = 0;
540 uintmax_t length = 0;
541 size_t bytes_read;
542
543 fseek(fp, 0, SEEK_SET);
544
545 while((bytes_read = fread(buf, 1, BUFLEN, fp)) > 0)
546 {
547 unsigned char *cp = buf;
548
549 if(length + bytes_read < length)
550 return 0;
551
552 if(bytes_read != BUFLEN && tagged)
553 bytes_read -= 8;
554
555 length += bytes_read;
556 while(bytes_read--)
557 crc =(crc << 8) ^ crctab[((crc >> 24) ^ *cp++) & 0xFF];
558 }
559
560 if(ferror(fp))
561 return 0;
562
563 for(; length; length >>= 8)
564 crc =(crc << 8) ^ crctab[((crc >> 24) ^ length) & 0xFF];
565
566 crc = ~crc & 0xFFFFFFFF;
567
568 *res = crc;
569
570 return 1;
571 }
572
573 unsigned long cs_calc_buf_sum(char *buf, int size)
574 {
575 unsigned long crc = 0;
576 char *cp = buf;
577 unsigned long length = size;
578
579 while(size--)
580 crc =(crc << 8) ^ crctab[((crc >> 24) ^ *cp++) & 0xFF];
581
582 for(; length; length >>= 8)
583 crc =(crc << 8) ^ crctab[((crc >> 24) ^ length) & 0xFF];
584
585 crc = ~crc & 0xFFFFFFFF;
586
587 return crc;
588 }
589
590 unsigned long cs_calc_buf_sum_ds(char *buf, int buf_size, char *sign, int sign_len)
591 {
592 unsigned long crc = 0;
593 char *cp = buf;
594 unsigned long length = buf_size+sign_len;
595
596 while(buf_size--)
597 crc =(crc << 8) ^ crctab[((crc >> 24) ^ *cp++) & 0xFF];
598
599 cp = sign;
600 while(sign_len--)
601 crc =(crc << 8) ^ crctab[((crc >> 24) ^ *cp++) & 0xFF];
602
603
604 for(; length; length >>= 8)
605 crc =(crc << 8) ^ crctab[((crc >> 24) ^ length) & 0xFF];
606
607 crc = ~crc & 0xFFFFFFFF;
608
609 return crc;
610 }
611
612 int cs_set_sum(FILE *fp, unsigned long sum, int tagged)
613 {
614 unsigned long magic = CKSUM_MAGIC_NUMBER;
615
616 if(tagged)
617 fseek(fp, -8, SEEK_END);
618 else
619 fseek(fp, 0, SEEK_END);
620
621 if(fwrite(&magic, 1, 4, fp) < 4)
622 return 0;
623 if(fwrite(&sum, 1, 4, fp) < 4)
624 return 0;
625
626 return 1;
627 }
628
629 void cs_get_sum(FILE *fp, unsigned long *sum)
630 {
631 unsigned long magic = 0;
632
633 fseek(fp, -8, SEEK_END);
634
635 fread(&magic, 4, 1, fp);
636 fread(sum, 4, 1, fp);
637 }
638
639 int cs_validate_file(char *filename)
640 {
641 FILE *pFile = NULL;
642 unsigned long sum = 0, res = 0;
643
644 if((pFile = fopen(filename, "r")) == NULL)
645 return 0;
646
647 if(!cs_is_tagged(pFile))
648 {
649 fclose(pFile);
650 return 0;
651 }
652 if(!cs_calc_sum(pFile, &sum, 1))
653 {
654 fclose(pFile);
655 return 0;
656 }
657 cs_get_sum(pFile, &res);
658 fclose(pFile);
659
660 if(sum != res)
661 return 0;
662 return 1;
663 }
664
665 /* ********* Library internal data ********* */
666 #define CMDLINE_TRUE 1
667 #define CMDLINE_FALSE 0
668
669 typedef enum CMDLINE_ERR
670 {
671 CMDLINE_ERR_OK = 0, /* No Error (OK) */
672 CMDLINE_ERR_ERROR = -1, /* Unspecified error */
673 CMDLINE_ERR_INVKEY = -3, /* Invalid option key */
674 CMDLINE_ERR_MANYARG = -4, /* Too many arguments */
675 CMDLINE_ERR_FEWARG = -5, /* Too few arguments */
676 CMDLINE_ERR_ILLOPT = -6, /* Option not allowed (illegal option) */
677 CMDLINE_ERR_NOMEM = -7, /* No memory */
678 CMDLINE_ERR_OPTMIS = -8 /* A mandatory option is missing */
679 } CMDLINE_ERR;
680
681 /* Argument list */
682 typedef struct CMDLINE_ARG
683 {
684 int index; /* Index of the argument in the command line */
685 struct CMDLINE_ARG* p_next; /* Next node in the linked list */
686 } CMDLINE_ARG;
687
688 /* Master control block for an option */
689 typedef struct CMDLINE_ARGS
690 {
691 int argc; /* Total count of arguments found */
692 int optc; /* Total count of options found */
693 CMDLINE_ARG* list; /* Argument list */
694 } CMDLINE_ARGS;
695
696 /* Master control block for all found arguments */
697 typedef struct CMDLINE_DATA
698 {
699 CMDLINE_ARGS opt_args[26]; /* Array of MCBs for each option ('a' through 'z') */
700 CMDLINE_ARGS glb_args; /* Global arguments */
701 int parsed; /* Internal flag to prevent client calls if library is not initialized */
702 } CMDLINE_DATA;
703
704 /* ********* Local Data ********* */
705 static CMDLINE_CFG cmdline_cfg;
706 static CMDLINE_DATA cmdline_data;
707
708 char* cmdline_errmsg = "CMDLINE ERROR";
709
710 /* ***************************************************************
711 * Print all found command line options and their arguments
712 ****************************************************************** */
713 void* cmdline_getarg_list(char opt)
714 {
715 int index = (opt - 'a');
716
717 /* Check the validity of the index */
718 if((index < 0) || (index > 25))
719 {
720 /* ERROR: Wrong option */
721 return NULL;
722 }
723
724 /* Return a pointer to the ARGS control structure */
725 return((void*)(&cmdline_data.opt_args[index]));
726 }
727
728 /* ***************************************************************
729 * Print all found command line options and their arguments
730 ****************************************************************** */
731 int cmdline_getarg_count(void* list)
732 {
733 CMDLINE_ARGS* p_args = (CMDLINE_ARGS*)list;
734
735 /* Return number of arguments for this option */
736 return(p_args->argc);
737 }
738
739 /* ***************************************************************
740 * Print all found command line options and their arguments
741 ****************************************************************** */
742 int cmdline_getopt_count(char opt)
743 {
744 int index;
745
746 /* Calculate index value */
747 index = opt - 'a';
748 if(index < 0 || index > 25) return -1;
749
750 /* Return number of arguments for this option */
751 return(cmdline_data.opt_args[index].optc);
752 }
753
754 /* ***************************************************************
755 * Print all found command line options and their arguments
756 ****************************************************************** */
757 int cmdline_getarg(void* list, int num)
758 {
759 int i;
760 CMDLINE_ARGS* p_args = (CMDLINE_ARGS*)list;
761 CMDLINE_ARG* p_arg;
762
763 /* Search the 'num' argument in the list for this option */
764 for(i=0,p_arg=p_args->list; (p_arg!=NULL) && (i<p_args->argc); i++, p_arg=p_arg->p_next)
765 {
766 /* if num matches i, we found it */
767 if(i==num) return(p_arg->index);
768 }
769 /* We did not find the specified argument or the list was empty */
770 return -1;
771 }
772
773 /* ***************************************************************
774 * Print all found command line options and their arguments
775 ****************************************************************** */
776 int cmdline_configure(CMDLINE_CFG* p_cfg)
777 {
778 /* reset global data */
779 memset(&cmdline_cfg,0,sizeof(cmdline_cfg));
780 memset(&cmdline_data,0,sizeof(cmdline_data));
781
782 /* Copy the user's config structure */
783 cmdline_cfg = *p_cfg;
784 return 0;
785 }
786
787 /* ***************************************************************
788 * Print all found command line options and their arguments
789 ****************************************************************** */
790 char* cmdline_error(int err)
791 {
792 /* TODO: implement a table of error messages */
793 return(cmdline_errmsg);
794 }
795
796 /* ***************************************************************
797 * Print all found command line options and their arguments
798 ****************************************************************** */
799 static void cmdline_print_args(CMDLINE_ARGS* p_arglist, char* argv[])
800 {
801 CMDLINE_ARG* p_arg;
802
803 printf(" Number of times option was specified: %d\n", p_arglist->optc);
804 printf(" Number of Arguments: %d\n", p_arglist->argc);
805
806 if(p_arglist->argc > 0)
807 {
808 printf(" Argument List: ");
809
810 for(p_arg=p_arglist->list; p_arg != NULL; p_arg=p_arg->p_next)
811 printf("%s ", argv[p_arg->index]);
812 }
813
814 printf("\n");
815 }
816
817 /* ***************************************************************
818 * Print all found command line options and their arguments
819 ****************************************************************** */
820 void cmdline_print(char* argv[])
821 {
822 int i;
823
824 /* Check if the command line was parsed */
825 if(cmdline_data.parsed != CMDLINE_TRUE)
826 {
827 printf("The command line has not been parsed yet.\n");
828 return;
829 }
830
831 /* Print out option arguments */
832 for( i = 0; i < 26; i++ )
833 {
834 /* Check if the option was specified */
835 if(cmdline_data.opt_args[i].optc !=0 )
836 {
837 /* Print out option name and arguments */
838 printf("Option: -%c\n", (char)('a'+i));
839 cmdline_print_args(&(cmdline_data.opt_args[i]), argv);
840 }
841 }
842
843 /* Print out global arguments */
844 printf("Global arguments:\n");
845 cmdline_print_args(&(cmdline_data.glb_args), argv);
846 }
847
848 /* ***************************************************************
849 * Print configuration
850 ****************************************************************** */
851 void cmdline_print_cfg(void)
852 {
853
854 }
855
856 static void cmdline_argadd(CMDLINE_ARGS* p_arglist, CMDLINE_ARG* p_arg)
857 {
858 CMDLINE_ARG* p_list;
859 CMDLINE_ARG* p_prev=NULL;
860
861 /* See if we had anything in the list */
862 if(p_arglist->argc == 0)
863 {
864 /* Link the argument in */
865 p_arglist->list = p_arg;
866 }
867 else
868 {
869 /* Find the tail of the list */
870 for(p_list=p_arglist->list; p_list != NULL; p_list=p_list->p_next)
871 p_prev = p_list;
872
873 /* Link the argument in */
874 p_prev->p_next=p_arg;
875 }
876
877 /* Keep track of arg number */
878 p_arglist->argc++;
879 }
880
881 /* ***************************************************************
882 * cmdline_read()
883 * Read and parse command line arguments
884 ****************************************************************** */
885 int cmdline_read(int argc, char* argv[])
886 {
887 int i, option=0;
888
889 /* Process every command line argument in argv[] array */
890 for( i = 1; i < argc; i++ )
891 {
892 /* Does the argument start with a dash? */
893 if( *argv[i] == '-' )
894 {
895 /* The argument must be two characters: a dash, and a letter */
896 if( strlen(argv[i]) != 2 )
897 {
898 /* ERROR: option syntax (needs to be a dash and one letter) */
899 return(CMDLINE_ERR_ERROR);
900 }
901
902 /* Check validity of the option key ('a' through 'z') */
903 if( ((*(argv[i] + 1)) < 'a') || ((*(argv[i] + 1)) > 'z') )
904 {
905 /* ERROR: option sysntax (invalid option key) */
906 return(CMDLINE_ERR_INVKEY);
907 }
908
909 /* Calculate the option index */
910 option = (*(argv[i] + 1)) - 'a';
911 if((option < 0) || (option > 25)) return(CMDLINE_ERR_INVKEY);
912
913 /* Check to see if the option is allowed */
914 if( cmdline_cfg.opts[option].flags & CMDLINE_OPTFLAG_ALLOW )
915 {
916 /* Option allowed. */
917 cmdline_data.opt_args[option].optc++;
918 continue;
919 }
920 else
921 {
922 /* ERROR: Option is not allowed */
923 return(CMDLINE_ERR_ILLOPT);
924 }
925 }
926 else
927 {
928 /* Read the arguments for the option */
929 CMDLINE_ARG* p_arg;
930
931 /* Allocate space for the argument node */
932 p_arg = (CMDLINE_ARG*)calloc(1,sizeof(CMDLINE_ARG));
933 if( p_arg== NULL )
934 {
935 /* ERROR: Can't allocate memory for the argument index */
936 return(CMDLINE_ERR_NOMEM);
937 }
938
939 /* Initialize the argument */
940 p_arg->index = i;
941 p_arg->p_next = NULL;
942
943 /* Check if we can add to the list of arguments for this option */
944 if( (option < 0) /* Do we have to add to the global list? */
945 || (cmdline_data.opt_args[option].argc == cmdline_cfg.opts[option].max) /* Did we reach MAX arguments? */
946 )
947 {
948 /* This option does not require arguments. Keep the argument in the global list. */
949 cmdline_argadd(&(cmdline_data.glb_args), p_arg);
950 continue;
951 }
952 else
953 {
954 /* See if the current count has reached max for this option */
955 if( cmdline_data.opt_args[option].argc == cmdline_cfg.opts[option].max )
956 {
957 /* ERROR: too many arguments for an option */
958 return(CMDLINE_ERR_MANYARG);
959 }
960 else
961 {
962 /* Link the argument to the arg list of the option */
963 cmdline_argadd(&(cmdline_data.opt_args[option]), p_arg);
964 continue;
965 }
966 }
967 }
968 }
969
970 /* ****** We read the complete command line. See if what we collected matches the configuration ******* */
971
972 /* Check every collected option against its configuration */
973 for( i=0; i < 26; i++ )
974 {
975 /* Check if this option was allowed */
976 if(cmdline_cfg.opts[i].flags & CMDLINE_OPTFLAG_ALLOW)
977 {
978 /* See if it was mandatory */
979 if(cmdline_cfg.opts[i].flags & CMDLINE_OPTFLAG_MANDAT)
980 {
981 /* Check if we really collected this option on the command line. */
982 if(cmdline_data.opt_args[i].optc == 0)
983 {
984 /* ERROR: a missing mandatory option */
985 return(CMDLINE_ERR_OPTMIS);
986 }
987 else
988 {
989 /* Option was there. Check how many args we got for it. */
990 if(cmdline_data.opt_args[i].argc < cmdline_cfg.opts[i].min)
991 {
992 /* ERROR: too few arguments for an option */
993 return(CMDLINE_ERR_FEWARG);
994 }
995 else
996 {
997 /* This mandatory option was proper. */
998 continue;
999 }
1000 }
1001 }
1002 else /* This is non-mandatory option: */
1003 {
1004 /* Check if the option was specified on the command line */
1005 if(cmdline_data.opt_args[i].optc == 0)
1006 {
1007 /* option wasn't specified, go to the next */
1008 continue;
1009 }
1010 else
1011 {
1012 /* Option was there. Check how many args we collected for it. */
1013 if(cmdline_data.opt_args[i].argc < cmdline_cfg.opts[i].min)
1014 {
1015 /* ERROR: too few arguments for a non-mandatory option */
1016 return(CMDLINE_ERR_FEWARG);
1017 }
1018 else
1019 {
1020 /* This non-mandatory option was proper. */
1021 continue;
1022 }
1023 }
1024 }
1025 }
1026 else /* Option was not allowed. */
1027 {
1028 /* We should not get here as the non-allowed options should have been
1029 trapped eariler. */
1030 }
1031 }
1032
1033 /* Command line was proper as far as the number of options and their arguments */
1034 cmdline_data.parsed = CMDLINE_TRUE;
1035 return(CMDLINE_ERR_OK);
1036 }