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