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