Root/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
8struct 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 ***************************************************************************/
18void 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 ***************************************************************************/
40void 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
76CMDLINE_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 ***************************************************************************/
114int 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
464static 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
520int 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
531unsigned 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
540int 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
577unsigned 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
594unsigned 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
616int 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
633void 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
643int 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
673typedef 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 */
686typedef 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 */
693typedef 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 */
701typedef 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 ********* */
709static CMDLINE_CFG cmdline_cfg;
710static CMDLINE_DATA cmdline_data;
711
712char* cmdline_errmsg = "CMDLINE ERROR";
713
714/* ***************************************************************
715* Print all found command line options and their arguments
716****************************************************************** */
717void* 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****************************************************************** */
735int 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****************************************************************** */
746int 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****************************************************************** */
761int 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****************************************************************** */
780int 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****************************************************************** */
794char* 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****************************************************************** */
803static 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****************************************************************** */
824void 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****************************************************************** */
855void cmdline_print_cfg(void)
856{
857
858}
859
860static 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****************************************************************** */
889int 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}
1041

Archive Download this file



interactive