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