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