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