3221d01d2cc96598825ad07f8a939e93ee3cd867
[mw/micromonitor-lm32.git] / umon_main / host / src / utils / f2mem.c
1 /* f2mem.c:
2  * This program takes as input a group of files and builds them into
3  * one file that can be burned into embedded system memory.
4  * The first file specified is assumed to be a binary file containing
5  * the embedded system's monitor.  All remaining files are assumed to
6  * be the TFS files that will be seen by the monitor as files in TFS.
7  * 
8  * General notice:
9  * This code is part of a boot-monitor package developed as a generic base
10  * platform for embedded system designs.  As such, it is likely to be
11  * distributed to various projects beyond the control of the original
12  * author.  Please notify the author of any enhancements made or bugs found
13  * so that all may benefit from the changes.  In addition, notification back
14  * to the author will allow the new user to pick up changes that may have
15  * been made by other users after this version of the code was distributed.
16  * 
17  * Author:      Ed Sutter
18  * email:       esutter@lucent.com
19  * phone:       908-582-2351
20  */
21 #include <stdio.h>
22 #include <stdlib.h>
23 #include <fcntl.h>
24 #include <string.h>
25 #include <sys/stat.h>
26 #include <sys/types.h>
27 #include "utils.h"
28
29 #ifdef BUILD_WITH_VCC
30 typedef unsigned short ushort;
31 #endif
32
33 #ifndef O_BINARY
34 #define O_BINARY 0
35 #endif
36
37 typedef unsigned char uchar;
38
39 #define TYPE_ASCII              1
40 #define TYPE_BINARY             2
41 #define TYPE_MONITOR    3
42
43 #define MAXFILES                64
44 #define TFSNAMESIZE             23
45 #define TFSHDRSIZ               sizeof(struct tfshdr)
46
47 #define TFS_RESERVED            4
48
49 /* Flags: */
50 #define TFS_EXEC        0x00000001      /* 'e': Executable. */
51 #define TFS_BRUN        0x00000002      /* 'b': To be executed at boot. */
52 #define TFS_QRYBRUN     0x00000004      /* 'B': To be executed at boot if */
53                                                                 /*      query passes. */
54 #define TFS_COFF        0x00000008      /* 'C': COFF absolute. */
55 #define TFS_ELF         0x00000010      /* 'E': ELF absolute. */
56 #define TFS_AOUT        0x00000020      /* 'A': AOUT absolute. */
57 #define TFS_CPRS        0x00000040      /* 'c': File is compressed. */
58 #define TFS_IPMOD       0x00000080      /* 'i': File is in-place modifiable. */
59 #define TFS_UNREAD      0x00000100      /* 'u': File is not even readable if the */
60                                                                 /*              user-level requirement is not met; */
61                                                                 /*              else, it is read-only. */
62 #define TFS_ULVLMSK     0x00000600      /*      User level mask defines 4 access levels: */
63 #define TFS_ULVL0       0x00000000      /* '0'  level 0 */
64 #define TFS_ULVL1       0x00000200      /* '1'  level 1 */
65 #define TFS_ULVL2       0x00000400      /* '2'  level 2 */
66 #define TFS_ULVL3       0x00000600      /* '3'  level 3 */
67 #define TFS_AIPNOT      0x00000800      /* Append not in progress, invisible to user. */
68                                                                 /* When this bit is clear, AIP is in    */
69                                                                 /* progress for the file. */
70                                                                 /* See notes in tfsclose() for this. */
71 #define TFS_ACTIVE      0x00008000      /* Used to indicate that file is not deleted. */
72
73 struct tfsflg {
74         long    flag;
75         char    sdesc;
76 };
77
78 struct tfshdr {
79         unsigned short  hdrsize;                /* Size of this header.                                 */
80         unsigned short  hdrvrsn;                /* Header version #.                                    */
81         long    filsize;                                /* Size of the file.                                    */
82         long    flags;                                  /* Flags describing the file.                   */
83         unsigned long  filcrc;                  /* 32 bit CRC of file.                                  */
84         unsigned long  hdrcrc;                  /* 32 bit CRC of header.                                */
85         unsigned long   modtime;                /* Time when file was last modified.    */
86         struct  tfshdr  *next;                  /* Pointer to next file in list.                */
87         char    name[TFSNAMESIZE+1];    /* Name of file.                                                */
88         char    info[TFSNAMESIZE+1];    /* Miscellaneous info field.                    */
89         unsigned long   rsvd[TFS_RESERVED];
90 };
91
92 struct finfo {
93         char *name;
94         char *filecontent;
95         char *flags;
96         char *info;
97         int     type;
98         int     size;
99 };
100
101 struct tfsflg tfsflgtbl[] = {
102         TFS_BRUN,                       'b',
103         TFS_QRYBRUN,            'B',
104         TFS_EXEC,                       'e',
105         TFS_AOUT,                       'A',
106         TFS_COFF,                       'C',
107         TFS_ELF,                        'E',
108         TFS_IPMOD,                      'i',
109         TFS_UNREAD,                     'u',
110         TFS_ULVL0,                      '0',
111         TFS_ULVL1,                      '1',
112         TFS_ULVL2,                      '2',
113         TFS_ULVL3,                      '3',
114         TFS_CPRS,                       'c',
115         0, 0,
116 };
117
118 char *usage_txt[] = {
119         "f2mem (files to memory translator) is a tool that allows the user to",
120         "take a group of files and generate a file that is suitable for a flash",
121         "programmer.  The intent is to feed it a monitor binary followed by a",
122         "list of files that are destined to exist in TFS (Tiny File System).",
123         "The monitor binary is placed at the base of the memory, then, starting",
124         "at the offset specified by -t, each of the remaining files are processed",
125         "and made to look as if they were residing in flash memory under TFS.",
126         "",
127         "Usage: f2mem [options] ",
128         " Options:",
129         " -a tfsname   ascii file for TFS",
130         " -B address   address flash base in CPU memory (default=0)",
131         " -b tfsname   binary file for TFS",
132         " -e           endian swap on portions of TFS struct",
133         " -f hexbyte   byte to be used as filler (default=0xff)",
134         " -m filename  monitor file",
135         " -O 's|b'     output type: S3-record or binary (default=S3)",
136         " -o filename  output file (default = mem.bin | mem.srec)",
137         " -p padto     pad-to size (default is no padding; uses -f hexbyte as pad)",
138         " -s {m|a}     swap bytes in monitor binary (m) or all bytes (a)",
139         " -S address   s-record base address (default=0)",
140         " -t ###       tfs offset",
141         " -T ###       tfs header version (default = 1)",
142         " -V           show version",
143         " -v           verbose",
144         "",
145         " Notes:",
146         "  * The -m and -t options are required.",
147         "  * Syntax for tfsname:  name,flags[,info]",
148         "  * This tool creates an image that could also be created by populating",
149         "    the target with all files, then using TFTP to retrieve the content",
150         "    of that freshly populated memory space.",
151         " Example:",
152         "  * f2mem -v -Ob -mmonppc.bin -amonrc,e -t0x40000 -B0x80000000",
153         "",
154         (char *)0,
155 };
156
157 unsigned long crc32tab[] = {
158         0x00000000, 0x77073096, 0xEE0E612C, 0x990951BA, 0x076DC419, 0x706AF48F,
159         0xE963A535, 0x9E6495A3, 0x0EDB8832, 0x79DCB8A4, 0xE0D5E91E, 0x97D2D988, 
160         0x09B64C2B, 0x7EB17CBD, 0xE7B82D07, 0x90BF1D91, 0x1DB71064, 0x6AB020F2,
161         0xF3B97148, 0x84BE41DE, 0x1ADAD47D, 0x6DDDE4EB, 0xF4D4B551, 0x83D385C7, 
162         0x136C9856, 0x646BA8C0, 0xFD62F97A, 0x8A65C9EC, 0x14015C4F, 0x63066CD9,
163         0xFA0F3D63, 0x8D080DF5, 0x3B6E20C8, 0x4C69105E, 0xD56041E4, 0xA2677172, 
164         0x3C03E4D1, 0x4B04D447, 0xD20D85FD, 0xA50AB56B, 0x35B5A8FA, 0x42B2986C,
165         0xDBBBC9D6, 0xACBCF940, 0x32D86CE3, 0x45DF5C75, 0xDCD60DCF, 0xABD13D59, 
166         0x26D930AC, 0x51DE003A, 0xC8D75180, 0xBFD06116, 0x21B4F4B5, 0x56B3C423,
167         0xCFBA9599, 0xB8BDA50F, 0x2802B89E, 0x5F058808, 0xC60CD9B2, 0xB10BE924, 
168         0x2F6F7C87, 0x58684C11, 0xC1611DAB, 0xB6662D3D, 0x76DC4190, 0x01DB7106,
169         0x98D220BC, 0xEFD5102A, 0x71B18589, 0x06B6B51F, 0x9FBFE4A5, 0xE8B8D433, 
170         0x7807C9A2, 0x0F00F934, 0x9609A88E, 0xE10E9818, 0x7F6A0DBB, 0x086D3D2D,
171         0x91646C97, 0xE6635C01, 0x6B6B51F4, 0x1C6C6162, 0x856530D8, 0xF262004E, 
172         0x6C0695ED, 0x1B01A57B, 0x8208F4C1, 0xF50FC457, 0x65B0D9C6, 0x12B7E950,
173         0x8BBEB8EA, 0xFCB9887C, 0x62DD1DDF, 0x15DA2D49, 0x8CD37CF3, 0xFBD44C65, 
174         0x4DB26158, 0x3AB551CE, 0xA3BC0074, 0xD4BB30E2, 0x4ADFA541, 0x3DD895D7,
175         0xA4D1C46D, 0xD3D6F4FB, 0x4369E96A, 0x346ED9FC, 0xAD678846, 0xDA60B8D0, 
176         0x44042D73, 0x33031DE5, 0xAA0A4C5F, 0xDD0D7CC9, 0x5005713C, 0x270241AA,
177         0xBE0B1010, 0xC90C2086, 0x5768B525, 0x206F85B3, 0xB966D409, 0xCE61E49F, 
178         0x5EDEF90E, 0x29D9C998, 0xB0D09822, 0xC7D7A8B4, 0x59B33D17, 0x2EB40D81,
179         0xB7BD5C3B, 0xC0BA6CAD, 0xEDB88320, 0x9ABFB3B6, 0x03B6E20C, 0x74B1D29A, 
180         0xEAD54739, 0x9DD277AF, 0x04DB2615, 0x73DC1683, 0xE3630B12, 0x94643B84,
181         0x0D6D6A3E, 0x7A6A5AA8, 0xE40ECF0B, 0x9309FF9D, 0x0A00AE27, 0x7D079EB1, 
182         0xF00F9344, 0x8708A3D2, 0x1E01F268, 0x6906C2FE, 0xF762575D, 0x806567CB,
183         0x196C3671, 0x6E6B06E7, 0xFED41B76, 0x89D32BE0, 0x10DA7A5A, 0x67DD4ACC, 
184         0xF9B9DF6F, 0x8EBEEFF9, 0x17B7BE43, 0x60B08ED5, 0xD6D6A3E8, 0xA1D1937E,
185         0x38D8C2C4, 0x4FDFF252, 0xD1BB67F1, 0xA6BC5767, 0x3FB506DD, 0x48B2364B, 
186         0xD80D2BDA, 0xAF0A1B4C, 0x36034AF6, 0x41047A60, 0xDF60EFC3, 0xA867DF55,
187         0x316E8EEF, 0x4669BE79, 0xCB61B38C, 0xBC66831A, 0x256FD2A0, 0x5268E236, 
188         0xCC0C7795, 0xBB0B4703, 0x220216B9, 0x5505262F, 0xC5BA3BBE, 0xB2BD0B28,
189         0x2BB45A92, 0x5CB36A04, 0xC2D7FFA7, 0xB5D0CF31, 0x2CD99E8B, 0x5BDEAE1D, 
190         0x9B64C2B0, 0xEC63F226, 0x756AA39C, 0x026D930A, 0x9C0906A9, 0xEB0E363F,
191         0x72076785, 0x05005713, 0x95BF4A82, 0xE2B87A14, 0x7BB12BAE, 0x0CB61B38, 
192         0x92D28E9B, 0xE5D5BE0D, 0x7CDCEFB7, 0x0BDBDF21, 0x86D3D2D4, 0xF1D4E242,
193         0x68DDB3F8, 0x1FDA836E, 0x81BE16CD, 0xF6B9265B, 0x6FB077E1, 0x18B74777, 
194         0x88085AE6, 0xFF0F6A70, 0x66063BCA, 0x11010B5C, 0x8F659EFF, 0xF862AE69,
195         0x616BFFD3, 0x166CCF45, 0xA00AE278, 0xD70DD2EE, 0x4E048354, 0x3903B3C2, 
196         0xA7672661, 0xD06016F7, 0x4969474D, 0x3E6E77DB, 0xAED16A4A, 0xD9D65ADC,
197         0x40DF0B66, 0x37D83BF0, 0xA9BCAE53, 0xDEBB9EC5, 0x47B2CF7F, 0x30B5FFE9, 
198         0xBDBDF21C, 0xCABAC28A, 0x53B39330, 0x24B4A3A6, 0xBAD03605, 0xCDD70693,
199         0x54DE5729, 0x23D967BF, 0xB3667A2E, 0xC4614AB8, 0x5D681B02, 0x2A6F2B94, 
200         0xB40BBE37, 0xC30C8EA1, 0x5A05DF1B, 0x2D02EF8D
201 };
202
203 struct finfo FileTable[MAXFILES];
204 int     verbose, debug, endianSwap;
205 short TFSHeaderVersion;
206 char *Outfile;
207 unsigned long   SrecBase;
208
209 /* tfsflagsatob():
210    Convert ascii flags to binary and return the long.
211 */
212 static long
213 tfsflagsatob(char *fstr)
214 {
215         long    flag;
216         struct  tfsflg  *tfp;
217
218         if (!fstr)
219                 return(0);
220
221         flag = 0;
222         while(*fstr) {
223                 tfp = tfsflgtbl;
224                 while(tfp->sdesc) {
225                         if (*fstr == tfp->sdesc) {
226                                 flag |= tfp->flag;
227                                 break;
228                         }
229                         tfp++;
230                 }
231                 if (!tfp->flag)
232                         return(-1);
233                 fstr++;
234         }
235         return(flag);
236 }
237
238 /* crc32():
239 */
240 unsigned long
241 crc32(uchar *buffer,unsigned long nbytes)
242 {
243         unsigned long crc_rslt, temp;
244
245         crc_rslt = 0xffffffff;
246         while(nbytes) {
247                 temp = (crc_rslt ^ *buffer++) & 0x000000FFL;
248                 crc_rslt = ((crc_rslt >> 8) & 0x00FFFFFFL) ^ crc32tab[temp];
249                 nbytes--;
250         }
251         return(~crc_rslt);
252 }
253
254 void
255 err(int exitval, char *msg1, char *msg2)
256 {
257         if (!msg2)
258                 msg2 = "";
259         fprintf(stderr,"ERROR: %s %s.\n",msg1,msg2);
260         exit(exitval);
261 }
262
263 /* buildTfsHeader():
264         Build the header into the buffer pointed to by buf.
265         Use the incoming fip pointer to retrieve file information and
266         assume the incoming value of address is the physical location
267         at which the file will be in CPU memory.
268         Return the number of bytes of adjustment made so that the next
269         file is properly aligned.
270 */
271 int
272 buildTfsHeader(unsigned long address, struct finfo *fip, struct tfshdr *tfp)
273 {
274         int     sizeofheader, modnext, alignadjust, rsvd;
275         
276         memset((char *)tfp,0,TFSHDRSIZ);
277         strncpy(tfp->name,fip->name,TFSNAMESIZE);
278         if (fip->info)
279                 strncpy(tfp->info,fip->info,TFSNAMESIZE);
280         tfp->name[TFSNAMESIZE] = 0;
281         tfp->info[TFSNAMESIZE] = 0;
282         tfp->hdrsize = otherEnd16(endianSwap,TFSHDRSIZ);
283         tfp->filsize = otherEnd32(endianSwap,fip->size);
284         tfp->flags = tfsflagsatob(fip->flags);
285         if (tfp->flags == -1)
286                 tfp->flags = 0;
287         tfp->flags |= (TFS_ACTIVE | TFS_AIPNOT);
288         if (!(tfp->flags & TFS_IPMOD))
289                 tfp->filcrc = otherEnd32(endianSwap,crc32(fip->filecontent,fip->size));
290         else
291                 tfp->filcrc = 0xffffffff;
292
293         tfp->flags = otherEnd32(endianSwap,tfp->flags);
294         tfp->hdrvrsn = otherEnd16(endianSwap,TFSHeaderVersion);
295         tfp->next = 0;
296         tfp->hdrcrc = 0;
297         tfp->modtime = 0xffffffff;
298         for(rsvd=0;rsvd<TFS_RESERVED;rsvd++)
299                 tfp->rsvd[rsvd] = 0xffffffff;
300         tfp->hdrcrc = otherEnd32(endianSwap,crc32((uchar *)tfp,TFSHDRSIZ));
301
302         /* Put next pointer on mod 16 address... */
303         modnext = address + TFSHDRSIZ + fip->size;
304         if (modnext % 16)
305                 alignadjust = 16 - ((unsigned)modnext % 16);
306         else
307                 alignadjust = 0;
308
309         tfp->next = (struct tfshdr *)(address+TFSHDRSIZ+fip->size+alignadjust);
310         tfp->next = (struct tfshdr *)otherEnd32(endianSwap,
311                 (unsigned long)(tfp->next));
312
313         return(alignadjust);
314 }
315
316 void
317 storeFileinfo(int idx,char *fstring,int type)
318 {
319         char *comma1, *comma2;
320         struct  finfo *fip;
321
322         fip = &FileTable[idx];
323         comma1 = strchr(fstring,',');
324
325         if (!comma1)
326                 err(1,"file name must have flags appended:",fstring);
327         *comma1 = 0;
328         fip->name = fstring;
329         fip->flags = comma1+1;
330         comma2 = strchr(comma1+1,',');
331         if (comma2) {
332                 *comma2 = 0;
333                 fip->info = comma2+1;
334         }
335         else
336                 fip->info = (char *)0;
337         fip->type = type;
338 }
339
340 void
341 buf2bin(uchar *data, int size)
342 {
343         int     fd;
344
345         if (verbose)
346                 fprintf(stderr,"Building binary file...\n");
347
348         fd = open(Outfile,O_WRONLY|O_BINARY|O_CREAT|O_TRUNC,0777);
349         if (fd < 0)
350                 err(1,"Can't open output file:",Outfile);
351
352         if (write(fd,data,size) != size)
353                 err(1,"Can't write file:",Outfile);
354
355         close(fd);
356 }
357
358 void
359 buf2srec(uchar *data, int size)
360 {
361         FILE    *fp;
362         uchar   *cp, *dp;
363         unsigned long   address;
364         int             cnt, csum, i;
365
366         if (verbose)
367                 fprintf(stderr,"Building S-record file...\n");
368         
369         fp = fopen(Outfile,"w+");
370         if (fp == NULL)
371                 err(1,"Can't open output file:",Outfile);
372
373         /* Create Srecord output file: */
374         fprintf(fp,"S0030000FC\n");
375         address = SrecBase;
376         dp = data;
377
378         while(size) {
379                 if (size > 32)
380                         cnt = 32;
381                 else
382                         cnt = size;
383
384                 /* Print S3 idendifier with byte count for line plus
385                    4-byte address: */
386                 fprintf(fp,"S3%02X%08X",cnt+5,address);
387
388                 /* Accumlate checksum subtotal: */
389                 csum = 0;
390                 cp = (uchar *)&address;
391                 csum += (cnt+5);
392                 csum += cp[0]; csum += cp[1]; csum += cp[2]; csum += cp[3];
393
394                 /* Print each byte of data: */
395                 for(i=0;i<cnt;i++) {
396                         fprintf(fp,"%02X",dp[i]);
397                         csum += (int)dp[i];
398                 }
399
400                 /* Print sumcheck (includes bytecount, address & data): */
401                 /* (binary one's compliment) */
402                 fprintf(fp,"%02X\n",255 - (csum & 0xff));
403                 size -= cnt;
404                 dp += cnt;
405                 address += cnt;
406         }
407         fprintf(fp,"S705000019E001\n");
408         fclose(fp);
409 }
410
411 main(int argc,char *argv[])
412 {
413         unsigned long   tfsoffset, flashbase, padto;
414         struct  stat statbuf;
415         struct  finfo   *fip;
416         int             ftot, totalmem;
417         int             i, opt, ifd, size, swapmonitor, swapall;
418         uchar   fillbyte;
419         struct  tfshdr  hdrbuf;
420         char    *membase, *memptr, outtype;
421
422         if (argc == 1)
423                 usage(0);
424
425         endianSwap = 1;
426         swapmonitor = swapall = 0;
427         TFSHeaderVersion = 1;
428         SrecBase = 0;
429         verbose = 0;
430         padto = 0;
431         outtype = 's';
432         tfsoffset = 0;
433         flashbase = 0;
434         Outfile = (char *)0;
435         fillbyte = 0xff;
436         for(i=0;i<MAXFILES;i++)
437                 FileTable[0].name = (char *)0;
438         ftot = 1;
439
440         while ((opt=getopt(argc,argv,"a:B:b:ef:m:O:o:p:s:S:t:T:vV")) != EOF) {
441                 switch(opt) {
442                 case 'a':       /* ascii file */
443                         storeFileinfo(ftot++,optarg,TYPE_ASCII);
444                         break;
445                 case 'B':       /* CPU address that base of flash resides at */
446                         flashbase = strtoul(optarg,(char **)0,0);
447                         break;
448                 case 'b':       /* binary file */
449                         storeFileinfo(ftot++,optarg,TYPE_BINARY);
450                         break;
451                 case 'e':       /* disable endian swap */
452                         endianSwap = 0;
453                         break;
454                 case 'f':       /* filler byte */
455                         fillbyte = (uchar)strtoul(optarg,(char **)0,0);
456                         break;
457                 case 'm':       /* monitor file */
458                         /* Slot 0 of the file table is reserved for the monitor. */
459                         if (FileTable[0].name)
460                                 err(1,"only one monitor file should be specified",0);
461                         FileTable[0].name = optarg;
462                         FileTable[0].type = TYPE_MONITOR;
463                         break;
464                 case 'O':       /* output file type */
465                         outtype = *optarg;
466                         if ((outtype != 's') && (outtype != 'b'))
467                                 err(1,"output type must be 's' or 'b'",0);
468                         break;
469                 case 'o':       /* output file */
470                         Outfile = optarg;
471                         break;
472                 case 'p':       /* output file */
473                         padto = strtoul(optarg,(char **)0,0);
474                         break;
475                 case 's':       /* swap binary */
476                         if (*optarg == 'm')
477                                 swapmonitor = 1;
478                         else if (*optarg == 'a')
479                                 swapall = 1;
480                         else {
481                                 fprintf(stderr,"Invalid argument to 's' option\n");
482                                 usage(0);
483                         }
484                         break;
485                 case 'S':       /* S-record base */
486                         SrecBase = strtoul(optarg,(char **)0,0);
487                         break;
488                 case 'T':       /* TFS header version */
489                         TFSHeaderVersion = atoi(optarg);
490                         break;
491                 case 't':       /* TFS offset */
492                         tfsoffset = strtoul(optarg,(char **)0,0);
493                         break;
494                 case 'V':
495                         showVersion();
496                         break;
497                 case 'v':
498                         verbose++;
499                         break;
500                 default:
501                         usage(0);
502                 }
503         }
504
505         if (!FileTable[0].name)
506                 err(1,"monitor file must be specified",0);
507         
508         if (stat(FileTable[0].name,&statbuf) < 0)
509                 err(1,"can't find file:",FileTable[0].name);
510
511         if (statbuf.st_size > tfsoffset) {
512                 fprintf(stderr,"TFS offset = 0x%x, monitor size = 0x%x\n",
513                         tfsoffset,statbuf.st_size);
514                 err(1,"TFS offset must be greater than size of monitor",0);
515         }
516
517         if (swapall & swapmonitor)
518                 err(1,"Can't swap monitor, then swap all... Do one or the other.",0);
519
520         FileTable[0].size = statbuf.st_size;
521
522         /* Now build each of the FileTable entries after the monitor... */
523         /* Determine the size of the file, and copy the entire file into a */
524         /* newly allocated buffer pointed to by filecontent... */
525         /* Also keep track of just how much memory must be allocated to */
526         /* fit the entire image into (store this in totalmem). */
527         totalmem = tfsoffset;
528         fip = &FileTable[1];
529         for(i=1;i<ftot;i++) {
530                 if (stat(fip->name,&statbuf) < 0)
531                         err(1,"can't find file:",fip->name);
532                 totalmem += statbuf.st_size + TFSHDRSIZ;
533                 fip->size = statbuf.st_size;
534                 
535                 if ((ifd = open(fip->name,O_RDONLY | O_BINARY)) < 0)
536                         err(1,"can't open file:",fip->name);
537                 fip->filecontent = malloc(fip->size);
538                 if (!fip->filecontent)
539                         err(1,"can't allocate memory",0);
540
541                 if (read(ifd,fip->filecontent,fip->size) != fip->size)
542                         err(1,"read failed:",fip->name);
543                 close(ifd);
544                 fip++;
545         }
546         totalmem;
547
548         memptr = membase = malloc(totalmem+1024);
549         if (!memptr)
550                 err(1,"can't allocate memory",0);
551
552         /* Load the memory with the fill byte prior to loading anything else... */
553         memset(membase,fillbyte,totalmem+1024);
554
555         if (verbose > 1)
556                 fprintf(stderr,"TFS header size: %d\n",TFSHDRSIZ);
557
558         /* First transfer the monitor file directly into allocated space... */
559         fip = &FileTable[0];
560         if ((ifd = open(fip->name,O_RDONLY | O_BINARY)) < 0)
561                 err(1,"can't open file:",fip->name);
562
563         if (read(ifd,memptr,fip->size) != fip->size)
564                 err(1,"read failed:",fip->name);
565
566         close(ifd);
567
568         if (swapmonitor) {
569                 char tmp;
570                 i = 0;
571                 while(i < fip->size) {
572                         tmp = membase[i];
573                         membase[i] = membase[i+1];
574                         membase[i+1] = tmp;
575                         i += 2;
576                 }
577         }
578
579         if (verbose) {
580                 fprintf(stderr,"Processing files...\n");
581                 fprintf(stderr," 0: %-20s @ 0x%08x (%d bytes)\n",
582                         fip->name,flashbase,fip->size);
583         }
584
585         /* Now that we have loaded the monitor binary into ram, adjust the              */
586         /* memory pointer to the start of TFS and begin loading each file and   */
587         /* create the TFS header for each... */
588         memptr += tfsoffset;
589         fip = &FileTable[1];
590         for(i=1;i<ftot;i++,fip++) {
591                 int     alignadjust;
592
593                 /* If filetype is TYPE_ASCII, strip out all CRs first... */
594                 if (fip->type == TYPE_ASCII) {
595                         int     j, choppedCRcnt;
596                         char *from, *to;
597
598                         choppedCRcnt = 0;
599                         from = to = fip->filecontent;
600                         for(j=0;j<fip->size;j++,from++) {
601                                 if (*from == 0x0d)
602                                         choppedCRcnt++;
603                                 else
604                                         *to++ = *from;
605                         }
606                         fip->size -= choppedCRcnt;
607                         totalmem -= choppedCRcnt;
608                 }
609
610                 if (verbose)
611                         fprintf(stderr,"%2d: %-20s @ 0x%08x (%d bytes)\n",
612                                 i,fip->name,flashbase+(memptr-membase)+TFSHDRSIZ,fip->size);
613
614                 /* Build the header: */
615                 alignadjust = buildTfsHeader(flashbase+(memptr-membase),fip,&hdrbuf);
616
617                 /* Transfer header to memory: */
618                 memcpy(memptr,(char *)&hdrbuf,TFSHDRSIZ);
619                 memptr += TFSHDRSIZ;
620
621                 /* Copy file content to buffer... */
622                 memcpy(memptr,fip->filecontent,fip->size);
623                 memptr += fip->size;
624                 totalmem += alignadjust;
625                 memptr += alignadjust;
626         }
627
628         /* If padto is non-zero, and it is smaller than the current value of */
629         /* totalmem, then use the fillbyte value to padd the memory out to the */
630         /* size specified by padto... */
631         if (padto) {
632                 char *paddedspace;
633
634                 if (padto > totalmem) {
635                         paddedspace = realloc(membase,padto);
636                         if (!paddedspace)
637                                 fprintf(stderr,"Can't allocate space for padding\n");
638                         else {
639                                 memset(paddedspace+totalmem,fillbyte,padto-totalmem);
640                                 totalmem = padto;
641                                 membase = paddedspace;
642                         }
643                 }
644                 else {
645                         fprintf(stderr,
646                                 "Warning: pad-to value (0x%x) <= total memspace (0x%x)\n", 
647                                 padto,totalmem);
648                 }
649         }
650
651         if (verbose)
652                 fprintf(stderr,"Total flash space required: %d (0x%x) bytes.\n",
653                         totalmem,totalmem);
654         if (verbose > 1) {
655                 unsigned long   gap;
656                 gap = tfsoffset - FileTable[0].size;
657                 fprintf(stderr,
658                         "Gap between end of monitor and TFS: %d (0x%x) bytes.\n",gap,gap);
659         }
660                         
661         if (swapall) {
662                 char tmp;
663                 i = 0;
664                 while(i < totalmem) {
665                         tmp = membase[i];
666                         membase[i] = membase[i+1];
667                         membase[i+1] = tmp;
668                         i += 2;
669                 }
670         }
671
672         /* Now convert buffer to Srecord... */
673         if (outtype == 's') {
674                 if (!Outfile)
675                         Outfile = "mem.srec";
676                 buf2srec(membase,totalmem);
677         }
678         else {
679                 if (!Outfile)
680                         Outfile = "mem.bin";
681                 buf2bin(membase,totalmem);
682         }
683
684         if (verbose)
685                 fprintf(stderr,"Output saved to file %s.\n",Outfile);
686
687         /* Cleanup... */
688         for(i=1;i<ftot;i++) 
689                 free(FileTable[i].filecontent);
690         
691         free(membase);
692         exit(0);
693 }