IRQ handler rewrite by Gabor Juhos, uses C no longer assembly
[openwrt.git] / target / linux / etrax-2.6 / image / e100boot / src / sbl / win32 / common.c
1 /*!***************************************************************************
2 *!
3 *! FILE NAME  : common.c
4 *!
5 *! DESCRIPTION: Common functions for e100boot.
6 *!
7 *! ---------------------------------------------------------------------------
8 *! HISTORY
9 *!
10 *! DATE         NAME               CHANGES
11 *! ----         ----               -------
12 *! ???  ? ????  Ronny Ranerup      Initial version
13 *! ---------------------------------------------------------------------------
14 *! (C) Copyright 1999-2003 Axis Communications AB, LUND, SWEDEN
15 *!***************************************************************************/
16 /* $Id: common.c,v 1.1 2004/01/26 10:52:40 mikaelp Exp $ */
17
18 /**************************  Version  **************************************/
19
20 char version[] = "Time-stamp: $Id: common.c,v 1.1 2004/01/26 10:52:40 mikaelp Exp $";
21
22 /**************************  Include files  ********************************/
23
24 #define WIN32_LEAN_AND_MEAN
25 #include <windows.h>
26 #include <stdlib.h>
27 #include <stdio.h>
28 #include <sys/types.h>
29 #include <sys/stat.h>
30 #include <io.h>
31 #include <winsock2.h>
32
33 #include <e100boot.h>
34 #include <pcap.h>
35 #include "boot_images.h"
36 #include <reg_des.h>
37 #include <sv_addr_ag.h>
38 #include <common.h>
39
40 #include <serial.h>
41 #include <network.h>
42
43 /**************************  Constants and macros  *************************/
44
45 #define BOOT_CMDS_FILE "BOOT_CMDS"
46
47 /**************************  Type definitions  *****************************/
48
49 struct label_t {
50   struct label_t *prev;
51   udword addr;
52   char *name;
53 };
54
55 /**************************  Global variables  *****************************/
56
57 char needle[MAX_STRING_LEN] = "END";    /* search needle for --find */
58 int needle_len = 3;
59
60 int exitonfind = FALSE;
61
62 int doing_flash = FALSE;        /* Just a flag to see if we should
63                                    warn that it might take some
64                                    time. */
65
66 int toFiles             = FALSE;        /* Dump all packets to files. */
67 int cmdsOnly            = FALSE;        /* Just dump boot cmds to file. */
68 int netBoot             = TRUE;         /* Do network boot? */
69 int serBoot             = FALSE;        /* Do serial boot? */
70
71 struct label_t *loop_label = NULL;
72 struct label_t *label      = NULL;
73
74 struct packet_buf *first_packet = NULL;
75 struct packet_buf *last_packet  = NULL;
76
77 struct packet_buf *boot_cmds_packet;
78
79 int create_boot_loader = TRUE;
80
81 /* We use the INTERNAL boot image as default */
82 char boot_loader_file[MAX_STRING_LEN] = INTERNAL_NW;
83
84 int noleds = FALSE;                     /* Use boot images that doesn't toggle leds? */
85
86 struct boot_files_T *first_boot_file = NULL;
87 struct boot_files_T *last_boot_file = NULL;
88
89 unsigned int boot_cmds[SIZE_OF_BOOT_CMDS / sizeof(unsigned int)];
90 int boot_cmds_cnt = 0;
91
92 int svboot = FALSE;
93
94 int quiet = 0;
95
96 struct packet_header_T send_packet;
97 struct packet_header_T *receive_packet;
98
99 int seq_nr = 0;
100
101 /* debug flags */
102 int db1 = FALSE;
103 int db2 = FALSE;
104 int db3 = FALSE;
105 int db4 = FALSE;
106
107 char device[MAX_STRING_LEN] = "";
108
109
110 /**************************  Function prototypes  **************************/
111
112 FILE                   *Fopen                   (const char *name, const char *mode);
113 int                     main                    (int argc, const char *argv[]);
114 int                     GetNumberOption         (int *argNr, int argCount, const char *argVect[], unsigned int *ret, const char *option, int base);
115 int                     GetStringOption         (int *argNr, int argCount, const char *argVect[], char *ret, const char *option);
116 int                     GetRegisterOption       (int *argNr, int argCount, const char *argVect[], unsigned int *ret, const char *option, int base);
117 struct boot_files_T*    allocate_boot_file      (struct boot_files_T *bf);
118 struct packet_buf*      CreateNewBootPacket     (void);
119 struct packet_buf*      allocate_packet         (struct packet_buf *p);
120 void                    SigHandler              (int sig);
121 void                    CreateBootLoader        (void);
122 void                    FinishBootCmds          (void);
123 void                    ParseArgs               (int argc, const char *argv[]);
124 void                    PrintHelp               (void);
125 void                    CreateBootCmds          (void);
126 void                    handle_labels           (void);
127 void                    new_label               (struct label_t **label, udword addr, const char *name);
128
129 /****************************************************************************
130 *#
131 *#  FUNCTION NAME: main
132 *#
133 *#  PARAMETERS: Command line arguments.
134 *#
135 *#---------------------------------------------------------------------------
136 *#  HISTORY
137 *#
138 *#  DATE     NAME     CHANGES
139 *#  ----     ----     -------
140 *#  961022   ronny    Initial version
141 *#
142 *#***************************************************************************/
143
144 int
145 main(int argc, const char *argv[])
146 {
147   ParseArgs(argc, argv);
148
149   if (cmdsOnly) {
150     /* We make this a special case to avoid messing up other code. */
151     CreateBootCmds();
152     FinishBootCmds();
153     SendToDevice(&boot_cmds_packet->data[SIZE_OF_HEADER],SIZE_OF_BOOT_CMDS);
154     exit(EXIT_SUCCESS);
155   }
156
157   if (netBoot && !toFiles) {
158     /* Do not bother with this if we just want to write the packets to
159        files. Means you do not have to be root to run --tofiles. */
160     net_init();
161   }
162   else if (serBoot) {
163     /*if (!SetupSerial())*/ {
164       exit(0);
165     }
166   }
167
168   CreateBootLoader();
169   CreateBootCmds();
170   FinishBootCmds();
171
172   printf("Starting boot...\n");
173   if (doing_flash) {
174     printf("We're doing a flash write, this may take up to a few minutes...\n");
175   }
176
177   if (toFiles) {
178     udword seq = 0;
179     struct packet_buf *p;
180
181     while((p = create_packet(seq++))) {
182       SendToDevice(p->data, p->size);
183     }
184
185     exit(EXIT_SUCCESS);
186   }
187
188   if (netBoot) {
189     NetBoot();
190   }
191   else if (serBoot) {
192     /*SerBoot();*/
193   }
194
195   printf("Done.\n");
196   return EXIT_SUCCESS;
197 } /* main  */
198
199 /****************************************************************************
200 *#
201 *#  FUNCTION NAME: free_packet
202 *#
203 *#  PARAMETERS: struct to free
204 *#
205 *#  DESCRIPTION: Frees struct and data in struct.
206 *#
207 *#  RETURNS: Pointer to next struct.
208 *#
209 *#---------------------------------------------------------------------------
210 *#  HISTORY
211 *#
212 *#  DATE         NAME     CHANGES
213 *#  ----         ----     -------
214 *#  2000 02 07   ronny    Initial version
215 *#
216 *#***************************************************************************/
217
218 struct packet_buf*
219 free_packet(struct packet_buf *p)
220 {
221   struct packet_buf *next_p;
222
223   next_p = p->next;
224   free(p->data);
225   free(p);
226   return(next_p);
227 }
228
229 /****************************************************************************
230 *#
231 *#  FUNCTION NAME: create_packet
232 *#
233 *#  PARAMETERS: Sequence number of desired packet.
234 *#
235 *#  DESCRIPTION:
236 *#
237 *#---------------------------------------------------------------------------
238 *#  HISTORY
239 *#
240 *#  DATE         NAME     CHANGES
241 *#  ----         ----     -------
242 *#  2000 06 28   ronny    Initial version
243 *#
244 *#***************************************************************************/
245
246 struct packet_buf*
247 create_packet(udword seq)
248 {
249   struct packet_buf *p = first_packet;
250   /* Should check last first? */
251
252   if (db4) printf("> create_packet seq %d\n", seq);
253
254   while (p) {
255     if (p->seq == seq) {
256       return(p);
257     }
258     p = p->next;
259   }
260
261   return(CreateNewBootPacket());
262 }
263
264 /****************************************************************************
265 *#
266 *#  FUNCTION NAME: find_string
267 *#
268 *#  PARAMETERS: New string to search.
269 *#
270 *#  DESCRIPTION: Searches a number of strings for needle[], including strings
271 *#  overlapping between different calls.
272 *#
273 *#---------------------------------------------------------------------------
274 *#  HISTORY
275 *#
276 *#  DATE     NAME     CHANGES
277 *#  ----     ----     -------
278 *#  020502   ronny    Initial version
279 *#
280 *#***************************************************************************/
281
282 void
283 find_string(char *str)
284 {
285   static int matched = 0;
286   int hs[MAX_STRING_LEN];
287   static int cur_hs = 0;
288   static int hs_len = 0;
289   static int last_hs = 0;
290
291   static int cur_needle = 0;
292
293   if (!needle[0]) {
294     return;
295   }
296   //    printf("# adding >%s<\n", str);
297
298   {
299     int c = 0;
300     int s = 0;
301
302     while((c = str[s])) {
303       //    printf("\n# cur_hs %d, hs_len %d\n", cur_hs, hs_len);
304       {
305         int i;
306
307         for(i = 0; i != hs_len; i++) {
308           //      printf("hs[%d] = %d(%c)\n", i, (int)hs[i], hs[i] < 32 ? 'X' : hs[i]);
309         }
310       }
311
312       if (cur_hs == hs_len) {
313         //      printf("adding char %d(%c) at hs[%d]\n", (int)c, c < 32 ? 'X' : c, hs_len);
314         hs[hs_len] = c;
315         hs_len++;
316         s++;
317       }
318
319       //      printf("testing %d at cur_hs %d against %d at cur_needle  %d\n",
320       //             (int)hs[cur_hs], cur_hs, (int)needle[cur_needle], cur_needle);
321
322       if (hs[cur_hs] == needle[cur_needle]) {
323         if (cur_needle+1 == needle_len) {
324           int exitcode = EXIT_SUCCESS;
325
326           //      printf("\nFound needle from --find option.\n");
327           if (exitonfind) {
328             int ret;
329             //      printf("scanf (s=%d)'%s'\n", s, &str[s+1]);
330             ret = sscanf(&str[s+1], "%i", &exitcode);
331             //      printf("ret %d, '%s'\n", ret, &str[s+1]);
332           }
333           printf("Exiting with code %d\n", exitcode);
334           exit(exitcode);
335         }
336         cur_needle++;
337         cur_hs++;
338       }
339       else {
340         //      printf("no match, shifting hs.\n");
341         {
342           int i;
343           for(i=0; i!= hs_len-1; i++) {
344             hs[i] = hs[i+1];
345           }
346         }
347         hs_len--;
348         cur_needle = 0;
349         cur_hs = 0;
350       }
351     }
352   }
353 }
354
355 /****************************************************************************
356 *#
357 *#  FUNCTION NAME: Fopen
358 *#
359 *#  PARAMETERS: Name and mode, both strings.
360 *#
361 *#  DESCRIPTION: Opens a file and returns its fd, or NULL.
362 *#
363 *#---------------------------------------------------------------------------
364 *#  HISTORY
365 *#
366 *#  DATE     NAME     CHANGES
367 *#  ----     ----     -------
368 *#  961022   ronny    Initial version
369 *#
370 *#***************************************************************************/
371
372 FILE *
373 Fopen(const char *name, const char *mode)
374 {
375   FILE *fd;
376
377   if (db2) printf(">>> Fopen '%s', mode '%s'\n", name, mode);
378
379   fd = fopen(name, mode);
380
381   if (fd == NULL) {
382     printf("<<< Fopen failed on '%s', mode '%s'\n", name, mode);
383     return ((FILE*) NULL);
384   }
385
386   if (strncmp(mode, "a", 1) == 0) {
387     if (db3) printf("* Append mode, seeking to end.\n");
388     fseek(fd, 0L, SEEK_SET);
389   }
390
391   if (db2) printf("<<< Fopen: '%s'\n", name);
392
393   return(fd);
394 }
395
396 /****************************************************************************
397 *#
398 *#  FUNCTION NAME: ParseArgs
399 *#
400 *#  PARAMETERS: Standard command line args.
401 *#
402 *#  DESCRIPTION: Parses command line arguments.
403 *#
404 *#---------------------------------------------------------------------------
405 *#  HISTORY
406 *#
407 *#  DATE     NAME     CHANGES
408 *#  ----     ----     -------
409 *#  960909   ronny    Initial version
410 *#***************************************************************************/
411
412 void
413 ParseArgs (int argc, const char *argv[])
414 {
415   int  argi;
416   int  i;
417   int  printHelp = FALSE;
418   int  exitCode = EXIT_SUCCESS;
419   char dbStr[MAX_STRING_LEN];              /* Debug option string. */
420   int  number;
421   int  argCount;
422   const char **argVect;
423   struct stat st;
424
425   if (db4) printf(">>> ParseArgs\n");
426   argCount = argc;
427   argVect = argv;
428
429   for (argi = 1; argi < argCount; argi++) {
430     if (db4) printf("argv[%d] = '%s'\n", argi, argVect[argi]);
431     if (strncmp(argVect[argi], "--from", 6) == 0) {
432       if (GetStringOption(&argi, argCount, argVect, host1, "--from") == 0) {
433         printHelp = TRUE;
434         exitCode = EXIT_FAILURE;
435       }
436       else {
437         printf("Host: %s %s\n", host1, host2);
438         if (sscanf(host1, "%x-%x-%x-%x-%x-%x", &i, &i, &i, &i, &i, &i) == 6) {
439           printf("Ethernet address\n");
440         }
441       }
442     }
443
444     else if (strncmp(argVect[argi], "--device", 8) == 0) {
445       if (GetStringOption(&argi, argCount, argVect, device, "--device") == 0) {
446         printHelp = TRUE;
447         exitCode = EXIT_FAILURE;
448       }
449     }
450
451     else if (strncmp(argVect[argi], "--network", 9) == 0) {
452       netBoot = TRUE;
453       serBoot = FALSE;
454       strcpy(boot_loader_file, INTERNAL_NW);
455     }
456
457     else if (strncmp(argVect[argi], "--serial", 8) == 0) {
458       serBoot = TRUE;
459       netBoot = FALSE;
460       strcpy(device, "/dev/ttyS0");
461       strcpy(boot_loader_file, INTERNAL_SER);
462     }
463
464     else if (strncmp(argVect[argi], "--noleds", 8) == 0) {
465       noleds = TRUE;
466     }
467
468     else if (strncmp(argVect[argi], "--images", 8) == 0) {
469       int i = 0;
470
471       printf("Internal images:\n");
472
473       while(boot_image_info[i].name) {
474         printf("'%s', %s, size %lu bytes.\n",
475                boot_image_info[i].name,
476                boot_image_info[i].info,
477                boot_image_info[i].len
478                );
479         i++;
480       }
481       exit(EXIT_SUCCESS);
482     }
483
484     else if (strncmp(argv[argi], "--baudrate", 10) == 0) {
485       /*      if (GetNumberOption (&argi, argCount, argVect, &set_baudrate, "--baudrate", 10) == 0)*/ {
486         printHelp = TRUE;
487         exitCode = EXIT_FAILURE;
488       }
489     }
490
491     else if (strncmp(argVect[argi], "--tofiles", 9) == 0) {
492       toFiles = TRUE;
493     }
494
495     else if (strncmp(argVect[argi], "--cmdsonly", 10) == 0) {
496       cmdsOnly = TRUE;
497     }
498
499     else if (strncmp(argVect[argi], "--to", 4) == 0) {
500       if ((GetStringOption(&argi, argCount, argVect, host2, "--to") == 0)) {
501         printHelp = TRUE;
502         exitCode = EXIT_FAILURE;
503       }
504       else {
505         printf("Host: %s %s\n", host1, host2);
506         both_addresses = TRUE;
507         if (sscanf(host2, "%x-%x-%x-%x-%x-%x", &i, &i, &i, &i, &i, &i) == 6) {
508           printf("Ethernet address\n");
509         }
510       }
511     }
512
513     else if (strncmp(argVect[argi], "--printp", 8) == 0) {
514       pPacket = 1;
515     }
516
517     else if (strncmp(argVect[argi], "--printascii", 11) == 0) {
518       pPacket = 1;
519       printPacketType = ASCII;
520     }
521
522     else if (strncmp(argVect[argi], "--printudec", 11) == 0) {
523       pPacket = 1;
524       printPacketType = UDEC;
525     }
526
527     else if (strncmp(argVect[argi], "--printhex", 10) == 0) {
528       pPacket = 1;
529       printPacketType = HEX;
530     }
531
532     else if (strncmp(argVect[argi], "--bpl", 5) == 0) {
533       if (GetNumberOption(&argi, argCount, argVect, &p_packet_bpl, "--bpl", 10) == 0) {
534         printHelp = TRUE;
535         exitCode = EXIT_FAILURE;
536       }
537     }
538
539     else if (strncmp(argVect[argi], "--promisc", 11) == 0) {
540       promisc = 1;
541     }
542
543     else if (strncmp(argVect[argi], "--5400", 6) == 0) {
544       boot_cmds[boot_cmds_cnt++] = SET_REGISTER;
545       boot_cmds[boot_cmds_cnt++] = 0xb0000000;
546       boot_cmds[boot_cmds_cnt++] = 0x000095b6;
547       boot_cmds[boot_cmds_cnt++] = SET_REGISTER;
548       boot_cmds[boot_cmds_cnt++] = 0xb0000008;
549       boot_cmds[boot_cmds_cnt++] = 0x0000e751;
550       boot_cmds[boot_cmds_cnt++] = SET_REGISTER;
551       boot_cmds[boot_cmds_cnt++] = 0xb000000c;
552       boot_cmds[boot_cmds_cnt++] = 0x12604040;
553     }
554
555     else if (strncmp(argVect[argi], "--5600", 6) == 0) {
556       boot_cmds[boot_cmds_cnt++] = SET_REGISTER;
557       boot_cmds[boot_cmds_cnt++] = 0xb0000000;
558       boot_cmds[boot_cmds_cnt++] = 0x000095b6;
559       boot_cmds[boot_cmds_cnt++] = SET_REGISTER;
560       boot_cmds[boot_cmds_cnt++] = 0xb0000008;
561       boot_cmds[boot_cmds_cnt++] = 0x00006751;
562       boot_cmds[boot_cmds_cnt++] = SET_REGISTER;
563       boot_cmds[boot_cmds_cnt++] = 0xb000000c;
564       boot_cmds[boot_cmds_cnt++] = 0x12204040;
565     }
566
567     else if (strncmp(argVect[argi], "--testcardlx", 12) == 0) {
568       boot_cmds[boot_cmds_cnt++] = SET_REGISTER;
569       boot_cmds[boot_cmds_cnt++] = (unsigned int)R_DRAM_CONFIG;
570       boot_cmds[boot_cmds_cnt++] = 0x12604040;
571       boot_cmds[boot_cmds_cnt++] = SET_REGISTER;
572       boot_cmds[boot_cmds_cnt++] = (unsigned int)R_DRAM_TIMING;
573       boot_cmds[boot_cmds_cnt++] = 0x0000e751;
574       boot_cmds[boot_cmds_cnt++] = SET_REGISTER;
575       boot_cmds[boot_cmds_cnt++] = (unsigned int)R_WAITSTATES;
576       boot_cmds[boot_cmds_cnt++] = 0x00b395b5;
577       boot_cmds[boot_cmds_cnt++] = SET_REGISTER;
578       boot_cmds[boot_cmds_cnt++] = (unsigned int)R_BUS_CONFIG;
579       boot_cmds[boot_cmds_cnt++] = 0x00000207;
580     }
581
582     else if (strncmp(argVect[argi], "--testcard", 10) == 0) {
583       boot_cmds[boot_cmds_cnt++] = SET_REGISTER;
584       boot_cmds[boot_cmds_cnt++] = (unsigned int)R_WAITSTATES;
585       boot_cmds[boot_cmds_cnt++] = 0x000010b3;
586       boot_cmds[boot_cmds_cnt++] = SET_REGISTER;
587       boot_cmds[boot_cmds_cnt++] = (unsigned int)R_DRAM_TIMING;
588       boot_cmds[boot_cmds_cnt++] = 0x00006543;
589       boot_cmds[boot_cmds_cnt++] = SET_REGISTER;
590       boot_cmds[boot_cmds_cnt++] = (unsigned int)R_DRAM_CONFIG;
591       boot_cmds[boot_cmds_cnt++] = 0x12966060;
592     }
593
594     else if (strncmp(argVect[argi], "--devboard", 10) == 0) {
595       /* Printing on serial port will not work until PORT_PB is set... */
596       boot_cmds[boot_cmds_cnt++] = SET_REGISTER;
597       boot_cmds[boot_cmds_cnt++] = (unsigned int)R_PORT_PB_SET;
598       boot_cmds[boot_cmds_cnt++] = 0x01001ef3;
599       boot_cmds[boot_cmds_cnt++] = SET_REGISTER;
600       boot_cmds[boot_cmds_cnt++] = (unsigned int)R_PORT_PA_SET;
601       boot_cmds[boot_cmds_cnt++] = 0x00001df0;
602       boot_cmds[boot_cmds_cnt++] = SET_REGISTER;
603       boot_cmds[boot_cmds_cnt++] = (unsigned int)R_WAITSTATES;
604       boot_cmds[boot_cmds_cnt++] = 0x000095a6;
605       boot_cmds[boot_cmds_cnt++] = SET_REGISTER;
606       boot_cmds[boot_cmds_cnt++] = (unsigned int)R_DRAM_CONFIG;
607       boot_cmds[boot_cmds_cnt++] = 0x1a200040;
608       boot_cmds[boot_cmds_cnt++] = SET_REGISTER;
609       boot_cmds[boot_cmds_cnt++] = (unsigned int)R_DRAM_TIMING;
610       boot_cmds[boot_cmds_cnt++] = 0x00005611;
611       boot_cmds[boot_cmds_cnt++] = SET_REGISTER;
612       boot_cmds[boot_cmds_cnt++] = (unsigned int)R_BUS_CONFIG;
613       boot_cmds[boot_cmds_cnt++] = 0x00000104;
614     }
615
616     else if (strncmp(argVect[argi], "--verify", 8) == 0) {
617       boot_cmds[boot_cmds_cnt++] = MEM_VERIFY;
618       GetNumberOption(&argi, argCount, argVect, &boot_cmds[boot_cmds_cnt++], "--verify", 16);
619       GetNumberOption(&argi, argCount, argVect, &boot_cmds[boot_cmds_cnt++], "--verify", 16);
620     }
621
622     else if (strncmp(argVect[argi], "--setreg", 8) == 0) {
623       boot_cmds[boot_cmds_cnt++] = SET_REGISTER;
624       if ((argVect[argi+1][0] >= 'A') && (argVect[argi+1][0] <= 'Z')) {
625         GetRegisterOption(&argi, argCount, argVect, &boot_cmds[boot_cmds_cnt++], "--setreg", 16);
626       }
627       else {
628         GetNumberOption(&argi, argCount, argVect, &boot_cmds[boot_cmds_cnt++], "--setreg", 16);
629       }
630       GetNumberOption(&argi, argCount, argVect, &boot_cmds[boot_cmds_cnt++], "--setreg", 16);
631     }
632
633     else if (strncmp(argVect[argi], "--getreg", 8) == 0) {
634       boot_cmds[boot_cmds_cnt++] = GET_REGISTER;
635       if ((argVect[argi+1][0] >= 'A') && (argVect[argi+1][0] <= 'Z')) {
636         GetRegisterOption(&argi, argCount, argVect, &boot_cmds[boot_cmds_cnt++], "--getreg", 16);
637       }
638       else {
639         GetNumberOption(&argi, argCount, argVect, &boot_cmds[boot_cmds_cnt++], "--getreg", 16);
640       }
641     }
642
643     else if (strncmp(argVect[argi], "--pause", 7) == 0) {
644       boot_cmds[boot_cmds_cnt++] = PAUSE_LOOP;
645       GetNumberOption(&argi, argCount, argVect, &boot_cmds[boot_cmds_cnt++], "--pause", 16);
646     }
647
648     else if (strncmp(argVect[argi], "--memtest", 9) == 0) {
649       boot_cmds[boot_cmds_cnt++] = MEM_TEST;
650       GetNumberOption(&argi, argCount, argVect, &boot_cmds[boot_cmds_cnt++], "--memtest", 16);
651       GetNumberOption(&argi, argCount, argVect, &boot_cmds[boot_cmds_cnt++], "--memtest", 16);
652     }
653
654     else if (strncmp(argVect[argi], "--loop", 6) == 0) {
655       char str[MAX_STRING_LEN];
656       boot_cmds[boot_cmds_cnt++] = LOOP;
657       GetNumberOption(&argi, argCount, argVect, &boot_cmds[boot_cmds_cnt++], "--loop", 16);
658       GetStringOption(&argi, argCount, argVect, str, argVect[argi]);
659       new_label(&loop_label, boot_cmds_cnt+1, str);
660       boot_cmds_cnt++;
661     }
662
663     else if (strncmp(argVect[argi], "--label", 7) == 0) {
664       char str[MAX_STRING_LEN];
665       GetStringOption(&argi, argCount, argVect, str, "--label");
666       new_label(&label, boot_cmds_cnt, str);
667     }
668
669     else if (strncmp(argVect[argi], "--memdump", 9) == 0) {
670       boot_cmds[boot_cmds_cnt++] = MEM_DUMP;
671       GetNumberOption(&argi, argCount, argVect, &boot_cmds[boot_cmds_cnt++], "--memdump", 16);
672       GetNumberOption(&argi, argCount, argVect, &boot_cmds[boot_cmds_cnt++], "--memdump", 16);
673     }
674
675     else if (strncmp(argVect[argi], "--memclear", 10) == 0) {
676       boot_cmds[boot_cmds_cnt++] = MEM_CLEAR;
677       GetNumberOption(&argi, argCount, argVect, &boot_cmds[boot_cmds_cnt++], "--memclear", 16);
678       GetNumberOption(&argi, argCount, argVect, &boot_cmds[boot_cmds_cnt++], "--memclear", 16);
679     }
680
681     else if (strncmp(argVect[argi], "--flash", 7) == 0) {
682             boot_cmds[boot_cmds_cnt++] = FLASH;
683             GetNumberOption(&argi, argCount, argVect, &boot_cmds[boot_cmds_cnt++], "--flash", 16);
684             GetNumberOption(&argi, argCount, argVect, &boot_cmds[boot_cmds_cnt++], "--flash", 16);
685             GetNumberOption(&argi, argCount, argVect, &boot_cmds[boot_cmds_cnt++], "--flash", 16);
686             doing_flash = TRUE;
687     }
688
689     else if (strncmp(argVect[argi], "--jump", 6) == 0) {
690       boot_cmds[boot_cmds_cnt++] = JUMP;
691       GetNumberOption(&argi, argCount, argVect, &boot_cmds[boot_cmds_cnt++], "--jump", 16);
692     }
693
694     else if (strncmp(argVect[argi], "--file", 6) == 0) {
695       char str[MAX_STRING_LEN];
696       boot_cmds[boot_cmds_cnt++] = PACKET_INFO;
697       GetStringOption(&argi, argCount, argVect,
698                       str, "--file");   /* file name */
699       GetNumberOption(&argi, argCount, argVect,
700                       &boot_cmds[boot_cmds_cnt++], str, 16); /* address */
701       last_boot_file = allocate_boot_file(last_boot_file);
702       first_boot_file = first_boot_file ? first_boot_file : last_boot_file;
703       last_boot_file->fileName = malloc(strlen(str) + 1);
704       strcpy(last_boot_file->fileName, str);
705       last_boot_file->size_p = &boot_cmds[boot_cmds_cnt];
706       last_boot_file->fd = NULL;
707       last_boot_file->size_sent = 0;
708       if (strncmp(str, "-", 1) != 0) {
709         if (stat(last_boot_file->fileName, &st) == -1) {
710           printf("Cannot get size of file '%s'. %s.\n",
711                  last_boot_file->fileName, strerror(errno));
712           exit(EXIT_FAILURE);
713         }
714         if (db2) printf("* size is %d 0x%8.8x\n",
715                         (int)st.st_size, (unsigned int)st.st_size);
716         last_boot_file->size = st.st_size;
717         boot_cmds[boot_cmds_cnt++] = st.st_size;
718       }
719       else {
720         GetNumberOption(&argi, argCount, argVect,
721                         &last_boot_file->size , str, 16); /* size */
722
723         boot_cmds[boot_cmds_cnt++] = last_boot_file->size;
724         printf("* size is %d 0x%8.8x\n", last_boot_file->size,
725                last_boot_file->size);
726       }
727     }
728
729     else if (strncmp(argVect[argi], "--bootfile", 10) == 0) {
730       GetStringOption(&argi, argCount, argVect,
731                       boot_loader_file, "--bootfile");
732     }
733
734     else if (strncmp(argVect[argi], "-d", 2) == 0) {
735       if (GetNumberOption (&argi, argCount, argVect, &number, "-d", 10) == 0) {
736         printHelp = TRUE;
737         exitCode = EXIT_FAILURE;
738       }
739       else {
740         sprintf(dbStr, "%d", number);
741         for (i = 0; i != (int) strlen(dbStr); i++) {
742           switch (dbStr[i] - '0') {
743           case 1:
744             db1 = TRUE;
745             break;
746           case 2:
747             db2 = TRUE;
748             break;
749           case 3:
750             db3 = TRUE;
751             break;
752           case 4:
753             db4 = TRUE;
754             break;
755           default:
756             printf("ERROR! Debug level %d is not defined.\n", dbStr[i] - '0');
757             printHelp = TRUE;
758             exitCode = EXIT_FAILURE;
759             break;
760           }
761         }
762       }
763     }
764
765     else if (strncmp(argVect[argi], "--find", 6) == 0) {
766       GetStringOption(&argi, argCount, argVect, needle, "--find");
767       /* convert control characters like /n to the real ascii valure */
768       {
769         int i;
770         int j = 0;
771         char c;
772         int esc = 0;
773
774         for (i = 0; (c = needle[i]); i++,j++) {
775 //        printf("c = %d, i %d, j %d\n", (int)c, i, j);
776           if (c == '\\') {
777 //          printf("esc\n");
778             esc = 1;
779             continue;
780           }
781           else if (esc) {
782             esc = 0;
783             switch(c) {
784             case 'r':
785               c = '\r';
786               break;
787
788             case 'n':
789               c = '\n';
790               break;
791
792             case '\\':
793               c = '\\';
794               break;
795
796             default:
797               printf("Uknown escape sequence '\\%c'\n", c);
798               exit(EXIT_FAILURE);
799             }
800             j--;
801           }
802           //      printf("setting j %d to %d\n", j, (int)c);
803           needle[j] = c;
804         }
805         needle_len = j;
806       }
807
808       for (i = 0; needle[i]; i++) {
809         //printf("i = %d, c %d\n", i,(int)needle[i]);
810       }
811     }
812
813     else if (strncmp(argVect[argi], "--exitonfind", 12) == 0) {
814       exitonfind = TRUE;
815     }
816
817     else if (strncmp(argVect[argi], "--help", 6) == 0) {
818       printHelp = TRUE;
819     }
820
821     else {
822       printf("ERROR! Don't understand option '%s'\n", argVect[argi]);
823       printHelp = TRUE;
824       exitCode = EXIT_FAILURE;
825     }
826   }
827
828   if (printHelp == TRUE) {
829     PrintHelp();
830     exit(exitCode);
831   }
832
833   if (noleds) {
834     strcpy(&boot_loader_file[strlen(boot_loader_file)], "_NOLEDS");
835   }
836
837   handle_labels();
838 }
839
840 /****************************************************************************
841 *#
842 *#  FUNCTION NAME: handle_labels
843 *#
844 *#  PARAMETERS: global loop_label, label
845 *#
846 *#  DESCRIPTION: Checks and matches labels from --loop and --label commands
847 *#  and inserts the resolved addresses into boot commands.
848 *#
849 *#---------------------------------------------------------------------------
850 *#  HISTORY
851 *#
852 *#  DATE     NAME     CHANGES
853 *#  ----     ----     -------
854 *#  20020204 ronny    Initial version
855 *#
856 *#***************************************************************************/
857
858 void
859 handle_labels(void)
860 {
861   struct label_t *ll = loop_label;
862   struct label_t *l  = label;
863   struct label_t *last_l  = l;
864
865   while(ll) {
866     int match = 0;
867
868     l = last_l;
869     while(l) {
870       match = 0;
871
872       if (l->name && ll->name && (strcmp(l->name, ll->name) == 0)) {
873         match = 1;
874         boot_cmds[ll->addr] = IO_BUF_START+(l->addr*4);
875         break;
876       }
877       l = l->prev;
878     }
879     if (!match) {
880       printf("Error. No label '%s' defined as needed by --loop command.\n", ll->name);
881       exit(EXIT_FAILURE);
882     }
883     ll = ll->prev;
884   }
885 }
886
887 /****************************************************************************
888 *#
889 *#  FUNCTION NAME: new_label
890 *#
891 *#  PARAMETERS:
892 *#
893 *#  DESCRIPTION:
894 *#
895 *#---------------------------------------------------------------------------
896 *#  HISTORY
897 *#
898 *#  DATE     NAME     CHANGES
899 *#  ----     ----     -------
900 *#  20020201 ronny    Initial version
901 *#
902 *#***************************************************************************/
903
904 void
905 new_label(struct label_t **label, udword addr, const char *name)
906 {
907   struct label_t *new_p;
908
909   new_p = malloc(sizeof(struct label_t));
910
911   if (*label == NULL) {         /* first one? */
912     *label = new_p;
913     new_p->prev = NULL;
914   }
915   else {
916     new_p->prev = *label;
917   }
918   *label = new_p;
919   new_p->addr = boot_cmds_cnt;
920   new_p->name = malloc(strlen(name));
921   strcpy(new_p->name, name);
922 }
923
924 /****************************************************************************
925 *#
926 *#  FUNCTION NAME: GetStringOption
927 *#
928 *#  PARAMETERS: int *argNr      : Returns next argc here.
929 *#              int argCount    : Index of last argument.
930 *#              char *argVect[] : argv.
931 *#              char *ret       : Copy string here.
932 *#              char *option    : Name of the option.
933 *#
934 *#  DESCRIPTION: Extracts a string option from argv, and updates argnr.
935 *#  Returns TRUE/FALSE and string in *ret.
936 *#
937 *#---------------------------------------------------------------------------
938 *#  HISTORY
939 *#
940 *#  DATE     NAME     CHANGES
941 *#  ----     ----     -------
942 *#  960930   ronny    Initial version
943 *#  961203   ronny    Handles filenames with spaces within 'file name'.
944 *#
945 *#***************************************************************************/
946
947 int
948 GetStringOption(int *argNr, int argCount, const char *argVect[], char *ret,
949                 const char *option)
950 {
951   int startChar = strlen(option);
952
953   *ret = '\0';
954
955   /* Are there any more chars after option? If not skip to next argv. */
956   if (strlen(argVect[*argNr]) <= (unsigned int)startChar) {
957     (*argNr)++;
958     startChar = 0;
959   }
960
961   /* Any args left? */
962   if (*argNr >= argCount) {
963     printf("ERROR! The option '%s' needs a string argument.\n", option);
964     PrintHelp();
965     exit(EXIT_FAILURE);
966   }
967
968   /* avoid stack overflow hacks */
969   if (strlen(&argVect[*argNr][startChar]) > MAX_STRING_LEN) {
970     printf("Argument '%s' longer than maximum allowable %d characters.\n",
971            &argVect[*argNr][startChar], MAX_STRING_LEN);
972     exit(EXIT_FAILURE);
973   }
974
975   strcpy(ret, &argVect[*argNr][startChar]);
976   if (db4) printf("<<< GetStringOption '%s'\n", ret);
977
978   return TRUE;
979 }
980
981 /****************************************************************************
982 *#
983 *#  FUNCTION NAME: GetNumberOption
984 *#
985 *#  PARAMETERS:
986 *#
987 *#  DESCRIPTION:
988 *#
989 *#---------------------------------------------------------------------------
990 *#  HISTORY
991 *#
992 *#  DATE     NAME     CHANGES
993 *#  ----     ----     -------
994 *#  960930   ronny    Initial version
995 *#
996 *#***************************************************************************/
997
998 int
999 GetNumberOption(int *argNr, int argCount, const char *argVect[],
1000                 unsigned int *ret, const char *option, int base)
1001 {
1002   int startChar = 0;
1003   int add_io_base = 0;
1004
1005   (*argNr)++;
1006
1007   if (*argNr >= argCount) {
1008     printf("ERROR! The option '%s' needs a number argument.\n", option);
1009     PrintHelp();
1010     exit(EXIT_FAILURE);
1011   }
1012
1013   if (argVect[*argNr][startChar] == '+') {
1014     add_io_base = 1;
1015     startChar++;
1016   }
1017
1018   *ret = strtoul(&argVect[*argNr][startChar], NULL, base);
1019
1020   if (add_io_base) {
1021     *ret += IO_BUF_START;
1022     if (*ret < IO_BUF_START || *ret >= IO_BUF_END) {
1023       printf("ERROR! '%s' is outside the IO buffer (option '%s').\n",
1024              argVect[*argNr], option);
1025       exit(EXIT_FAILURE);
1026     }
1027   }
1028
1029   if (db4) printf("<<< GetNumberOption %08x\r\n", *ret);
1030
1031   return TRUE;
1032 }
1033
1034 /****************************************************************************
1035 *#
1036 *#  FUNCTION NAME: GetRegisterOption
1037 *#
1038 *#  PARAMETERS:
1039 *#
1040 *#  DESCRIPTION:
1041 *#
1042 *#---------------------------------------------------------------------------
1043 *#  HISTORY
1044 *#
1045 *#  DATE     NAME     CHANGES
1046 *#  ----     ----     -------
1047 *#  960930   ronny    Initial version
1048 *#
1049 *#***************************************************************************/
1050
1051 int
1052 GetRegisterOption(int *argNr, int argCount, const char *argVect[],
1053                   unsigned int *ret, const char *option, int base)
1054 {
1055   int startChar = 0;
1056
1057   (*argNr)++;
1058
1059   if (*argNr >= argCount) {
1060     printf("Error! The option '%s' needs a register name.\n", option);
1061     PrintHelp();
1062     exit(EXIT_FAILURE);
1063   }
1064
1065   {
1066     int r = 0;
1067
1068     while (reg_des[r].name) {
1069       if (strcmp(reg_des[r].name, argVect[*argNr]) == 0) {
1070         *ret = reg_des[r].addr;
1071         return TRUE;
1072         break;
1073       }
1074       r++;
1075     }
1076   }
1077
1078   printf("Error! Didn't find a register name matching '%s'.\n",
1079          argVect[*argNr]);
1080
1081   exit(EXIT_FAILURE);
1082
1083   return FALSE;
1084 }
1085
1086 /****************************************************************************
1087 *#
1088 *#  FUNCTION NAME: PrintHelp
1089 *#
1090 *#  PARAMETERS: None.
1091 *#
1092 *#  DESCRIPTION: Prints help info.
1093 *#
1094 *#---------------------------------------------------------------------------
1095 *#  DATE     NAME     CHANGES
1096 *#  ----     ----     -------
1097 *#  960909   ronny    Initial version
1098 *#
1099 *#***************************************************************************/
1100
1101 void
1102 PrintHelp(void)
1103 {
1104   printf("e100boot version %s.\n", version);
1105
1106   printf("\ne100boot [--device devicename] [--file filename|- addr [size]]\n"
1107          "         [--flash ram-source flash-offset size]\n"
1108          "         [--pause iter]\n"
1109          "         [--memtest addr addr]\n"
1110          "         [--memclear addr addr] [--memdump addr addr]\n"
1111          "         [--setreg addr|regname val] [--getreg addr|regname]\n"
1112          "         [--verify addr val] [--label label] [--loop addr label]\n"
1113          "         [--5400] [--5600] [--testcard] [--devboard]\n"
1114          "         [--testcardlx] [--network] [--serial]\n"
1115          "         [--baudrate baudrate] [--bootfile file] [--jump addr]\n"
1116          "         [--tofiles] [--cmdsonly] [--images] [--noleds]\n"
1117          "         [--help]\n\n");
1118
1119   printf("         The commands sent to the cbl, and which are parsed by the cbl,\n"
1120          "         are stored at 0x%8.8x-0x%8.8x.\n\n", IO_BUF_START, IO_BUF_END);
1121
1122   printf("         See the man page for more details about e100boot.\n\n");
1123 }
1124
1125 /****************************************************************************
1126 *#
1127 *#  FUNCTION NAME: CreateBootLoader
1128 *#
1129 *#  PARAMETERS: None.
1130 *#
1131 *#  DESCRIPTION: Creates boot packets from boot file or internal loader.
1132 *#
1133 *#---------------------------------------------------------------------------
1134 *#  DATE     NAME     CHANGES
1135 *#  ----     ----     -------
1136 *#  960909   ronny    Initial version
1137 *#***************************************************************************/
1138
1139 void
1140 CreateBootLoader(void)
1141 {
1142   struct stat st;
1143   char *buf = NULL;
1144   //  int size_pos = 0x18;
1145   //  int addr_pos = 0x28;
1146   struct packet_header_T *ph;
1147   int packet_size;
1148   int header_size;
1149   int buf_cnt = 0;
1150   int i;
1151   udword sum = 0;
1152
1153   if (create_boot_loader) {
1154     int image_nbr = 0;
1155     int found = 0;
1156     const struct boot_image_info_type *info;
1157
1158     if (db4) printf("> CreateBootLoader\n");
1159
1160     info = &boot_image_info[image_nbr];
1161
1162     /* Use internal boot loader? */
1163     while (!found && info->name != NULL) {
1164       if (strcmp(boot_loader_file, info->name) == 0) {
1165         st.st_size = info->len;
1166         buf = (char*) malloc(st.st_size);
1167         memcpy(buf, info->ptr, st.st_size); /* unnecessary? */
1168         found = TRUE;
1169         printf("Using internal boot loader: %s - %s.\n",
1170                info->name, info->info);
1171       }
1172       else {
1173         image_nbr++;
1174         info = &boot_image_info[image_nbr];
1175       }
1176     }
1177
1178     /* No internal? Load it from file instead. */
1179     if (!found) {
1180       FILE *fd;
1181
1182       /* We didn't find an internal match, load the boot file from disk. */
1183       if ((fd = Fopen(boot_loader_file, "r")) == NULL) {
1184         printf("Cannot open bootloader '%s'. %s.\n",
1185                boot_loader_file, strerror(errno));
1186         exit(EXIT_FAILURE);
1187       }
1188
1189       if (fstat(fileno(fd), &st) == -1) {
1190         printf("Cannot get filestatus of bootloader '%s'. %s.\n",
1191                boot_loader_file, strerror(errno));
1192         exit(EXIT_FAILURE);
1193       }
1194
1195       buf = (char*) malloc(st.st_size);
1196       //      printf("CreateBootLoader: buf = (char*) malloc(st.st_size); 2\n");
1197       if (read(fileno(fd), buf, st.st_size) != st.st_size) {
1198         printf("Read fewer bytes than there should be in %s.\n",
1199                boot_loader_file);
1200         exit(EXIT_FAILURE);
1201       }
1202
1203       fclose(fd);
1204     }
1205
1206     /* Alright, got loader in buf[] and size in st. */
1207     if (netBoot) {
1208       /* The etrax code for all boot methods are linked to adress
1209          380000f0 but since network boot starts execution at 380000f4
1210          we have two nops in the beginning of the code which we do not
1211          transmit to etrax in the network case. The link adress
1212          doesn't change though. */
1213       buf += 4;
1214       st.st_size -= 4;
1215       packet_size = DATA_SIZE;
1216     }
1217     else {
1218       packet_size = st.st_size;
1219     }
1220
1221     /* Hack binary, insert size and address. */
1222
1223 #define SIZE_PATTERN 0x12345678
1224 #define ADDR_PATTERN 0x87654321
1225 #define SIZE_POS (netBoot ? 0x0c : 0x10)
1226 #define ADDR_POS (netBoot ? 0x10 : 0x14)
1227
1228     if (*(udword*)&buf[SIZE_POS] != SIZE_PATTERN) {
1229       printf("Bootloader corrupt. Should contain ret/nop (0x%8.8x) at 0x%x, but contains %x\n",
1230              SIZE_PATTERN, SIZE_POS, *(udword*)&buf[SIZE_POS]);
1231       exit(EXIT_FAILURE);
1232     }
1233
1234     /* How much data to load except data in first packet. */
1235
1236     if (netBoot) {
1237       *(udword*)(&buf[SIZE_POS]) = st.st_size - DATA_SIZE;
1238     }
1239     else {
1240       *(udword*)(&buf[SIZE_POS]) = st.st_size - 784;
1241     }
1242
1243     if (db3) printf("Inserting boot size 0x%x at 0x%x.\n",
1244                     (unsigned int) *(udword*)(&buf[SIZE_POS]),
1245                     (unsigned int)&buf[SIZE_POS]);
1246
1247     if (*(udword*)&buf[ADDR_POS] != ADDR_PATTERN) {
1248       printf("Bootloader corrupt. Should contain ret/nop (0x%8.8x) at 0x%x, but contains %x\n",
1249              ADDR_PATTERN, ADDR_POS, *(udword*)&buf[ADDR_POS]);
1250       exit(EXIT_FAILURE);
1251     }
1252
1253     if (netBoot) {
1254       *(udword*)(&buf[ADDR_POS]) = BOOT_ADDRESS + DATA_SIZE;
1255     }
1256     else {
1257       *(udword*)(&buf[ADDR_POS]) = BOOT_ADDRESS-4 + 784;
1258     }
1259
1260     if (db3) printf("Inserting boot address 0x%x at 0x%x.\n",
1261                     (unsigned int)*(udword*)(&buf[ADDR_POS]),
1262                     (unsigned int)&buf[ADDR_POS]);
1263
1264
1265     for (i = 0; i != st.st_size; i++) {
1266       sum += ((byte*)buf)[i];
1267     }
1268     if (db1) printf("Checksum 0x%x, bytes %d\n", sum, i);
1269
1270     if (db4) {
1271       int i;
1272
1273       for(i=0; i<st.st_size; i+=8) {
1274         int j;
1275
1276         printf("0x%8.8x[%4.4x]: ", BOOT_ADDRESS+i, i);
1277         for(j=0; i+j<st.st_size && j<8; j++) {
1278           printf("%2.2x ", (unsigned char) buf[i+j]);
1279         }
1280         printf("\n");
1281       }
1282     }
1283     /* Now create list of packets. */
1284     while (buf_cnt <= st.st_size) {
1285
1286       header_size = seq_nr == 0 ?
1287         SIZE_OF_FIRST_HEADER : sizeof(struct packet_header_T);
1288
1289       if (netBoot) {
1290         packet_size = ((st.st_size - buf_cnt) < DATA_SIZE ?
1291                        st.st_size - buf_cnt : DATA_SIZE) + header_size;
1292       }
1293       else {
1294         packet_size = st.st_size;
1295         header_size = 0;
1296       }
1297
1298       if (db4) printf("seq_nr %d, header_size %d, packet_size %d\n",
1299                       seq_nr, header_size, packet_size);
1300
1301       last_packet = allocate_packet(last_packet);
1302
1303       first_packet = first_packet ? first_packet : last_packet;
1304
1305       last_packet->size = packet_size;
1306       last_packet->data = (char*)malloc(packet_size);
1307       last_packet->seq = seq_nr;
1308       last_packet->baud_rate = 9600;
1309
1310       last_packet->boot_file = allocate_boot_file(NULL);
1311       last_packet->boot_file->fileName = boot_loader_file;
1312
1313       //      printf("last_packet->size %8.8x\n", last_packet->size);
1314       //      printf("last_packet->data %8.8x\n",last_packet->data);
1315
1316       if (netBoot) {
1317         ph = (struct packet_header_T*) last_packet->data;
1318         memcpy(ph->dest, dst_addr_of_device, 6);
1319         memcpy(ph->src,  eth_addr_local,     6);
1320         ph->length = htons(packet_size);
1321         ph->snap1  = htonl(SNAP1);
1322         ph->snap2  = htonl(SNAP2);
1323         ph->tag    = htonl(SERVER_TAG);
1324         ph->seq    = htonl(seq_nr);
1325         if (seq_nr != 0) {
1326           ph->type   = htonl(BOOT_PACKET);
1327           ph->id     = htonl(0);
1328         }
1329       }
1330
1331       memcpy(&last_packet->data[header_size], &buf[buf_cnt],
1332              packet_size - header_size);
1333       if (db3) DecodeSvintoBoot(last_packet->data);
1334
1335       if (netBoot) {
1336         buf_cnt += DATA_SIZE;
1337       }
1338       else {
1339         buf_cnt += packet_size +1;
1340       }
1341
1342       seq_nr++;
1343     }
1344   }
1345
1346   if (db4) printf("< CreateBootLoader\n");
1347 }
1348
1349 /****************************************************************************
1350 *#
1351 *#  FUNCTION NAME: allocate_packet
1352 *#
1353 *#  PARAMETERS: None.
1354 *#
1355 *#  DESCRIPTION:
1356 *#
1357 *#---------------------------------------------------------------------------
1358 *#  DATE     NAME     CHANGES
1359 *#  ----     ----     -------
1360 *#  960909   ronny    Initial version
1361 *#***************************************************************************/
1362
1363 struct packet_buf*
1364 allocate_packet(struct packet_buf *p)
1365 {
1366   if (db4) printf("> allocate_packet\n");
1367
1368   if (p) {
1369     p->next = (struct packet_buf*) malloc(sizeof(struct packet_buf));
1370     p       = p->next;
1371   }
1372   else {
1373     p = (struct packet_buf*) malloc(sizeof(struct packet_buf));
1374   }
1375   p->next = NULL;
1376
1377   return(p);
1378 }
1379
1380 /****************************************************************************
1381 *#
1382 *#  FUNCTION NAME: allocate_boot_file
1383 *#
1384 *#  PARAMETERS: None.
1385 *#
1386 *#  DESCRIPTION:
1387 *#
1388 *#---------------------------------------------------------------------------
1389 *#  DATE     NAME     CHANGES
1390 *#  ----     ----     -------
1391 *#  960909   ronny    Initial version
1392 *#***************************************************************************/
1393
1394 struct boot_files_T*
1395 allocate_boot_file(struct boot_files_T *bf)
1396 {
1397   if (bf) {
1398     bf->next = (struct boot_files_T*) malloc(sizeof(struct boot_files_T));
1399     bf       = bf->next;
1400   }
1401   else {
1402     bf = (struct boot_files_T*) malloc(sizeof(struct boot_files_T));
1403   }
1404   bf->next = NULL;
1405
1406   return(bf);
1407 }
1408
1409 /****************************************************************************
1410 *#
1411 *#  FUNCTION NAME: CreateBootCmds
1412 *#
1413 *#  PARAMETERS: None.
1414 *#
1415 *#  DESCRIPTION: Creates a boot packet from the boot commands. The data is
1416 *#  filled in later by FinishBootCmds().
1417 *#
1418 *#---------------------------------------------------------------------------
1419 *#  DATE     NAME     CHANGES
1420 *#  ----     ----     -------
1421 *#  980818   ronny    Initial version
1422 *#***************************************************************************/
1423
1424 void
1425 CreateBootCmds(void)
1426 {
1427   struct packet_header_T *ph;
1428
1429   if (db4) printf("***> CreateBootCmds\n");
1430
1431   last_packet = allocate_packet(last_packet);
1432
1433   boot_cmds_packet = last_packet;
1434
1435   last_packet->boot_file = allocate_boot_file(NULL);
1436   last_packet->boot_file->fileName =  BOOT_CMDS_FILE;
1437   last_packet->baud_rate =  9600;
1438
1439   last_packet->size = netBoot ? SIZE_OF_BOOT_CMDS + sizeof(struct packet_header_T)
1440     : SIZE_OF_BOOT_CMDS;
1441
1442   last_packet->data = (char *) malloc(last_packet->size);
1443   last_packet->seq = seq_nr;
1444
1445   if (netBoot) {
1446     /* Create packet header. */
1447     ph = (struct packet_header_T *) last_packet->data;
1448     memcpy(ph->dest, dst_addr_of_device, 6);
1449     memcpy(ph->src, eth_addr_local, 6);
1450     ph->length = htons(last_packet->size);
1451     ph->snap1 = htonl(SNAP1);
1452     ph->snap2 = htonl(SNAP2);
1453     ph->tag = htonl(SERVER_TAG);
1454     ph->seq = htonl(seq_nr);
1455     seq_nr++;
1456     ph->type = htonl(BOOT_CMDS);
1457     ph->id = htonl(0);
1458   }
1459
1460   if (db3) DecodeSvintoBoot(last_packet->data);
1461   if (db4) printf("<*** CreateBootCmds\n");
1462 }
1463
1464 /****************************************************************************
1465 *#
1466 *#  FUNCTION NAME: FinishBootCmds
1467 *#
1468 *#  PARAMETERS: None.
1469 *#
1470 *#  DESCRIPTION: Copies the boot commands into the correct packet and changes
1471 *#  the dwords to network order.
1472 *#
1473 *#---------------------------------------------------------------------------
1474 *#  DATE     NAME     CHANGES
1475 *#  ----     ----     -------
1476 *#  960909   ronny    Initial version
1477 *#***************************************************************************/
1478
1479 void
1480 FinishBootCmds(void)
1481 {
1482   int i;
1483   unsigned int offset = 0;
1484
1485   for (i = 0; i != boot_cmds_cnt; i++) {
1486     boot_cmds[i] = htonl(boot_cmds[i]);
1487     if (db3) printf("%8.8x\n", boot_cmds[i]);
1488   }
1489
1490   /* Copy boot commands into packet. */
1491   if (netBoot) {
1492     offset = sizeof(struct packet_header_T);
1493   }
1494
1495   memcpy(&boot_cmds_packet->data[offset], boot_cmds,
1496          boot_cmds_cnt * sizeof(udword));
1497 }
1498
1499 /****************************************************************************
1500 *#
1501 *#  FUNCTION NAME: CreateNewBootPacket
1502 *#
1503 *#  PARAMETERS: None.
1504 *#
1505 *#  DESCRIPTION: Creates next packet for the files specified by '--file'.
1506 *#
1507 *#  RETURNS: Next packet, or NULL.
1508 *#
1509 *#---------------------------------------------------------------------------
1510 *#  DATE     NAME     CHANGES
1511 *#  ----     ----     -------
1512 *#  960909   ronny    Initial version
1513 *#***************************************************************************/
1514
1515 struct packet_buf*
1516 CreateNewBootPacket(void)
1517 {
1518   static char buf[DATA_SIZE];
1519   struct packet_header_T *ph;
1520   int packet_size;
1521   int header_size;
1522   int i;
1523   udword sum;
1524   int size = 0;
1525   int padding = 0;
1526
1527   static struct boot_files_T *bf = NULL;
1528
1529   if (db3) printf("> CreateNewBootPacket\n");
1530
1531   bf = bf ? bf : first_boot_file;
1532
1533   while (bf) {
1534     if (!bf->fd) {
1535       if (strcmp(bf->fileName, "-") == 0) {
1536         bf->fd = stdin;
1537       }
1538       else {
1539         bf->fd = fopen(bf->fileName, "rb");
1540       }
1541
1542       if (bf->fd == NULL) {
1543         printf("Cannot open boot file %s. Exiting\n", bf->fileName);
1544         exit(EXIT_FAILURE);
1545       }
1546       if (db3) printf("Opening boot file %s\n", bf->fileName);
1547     }
1548
1549     if (!padding) {
1550       size = fread(buf, 1, DATA_SIZE, bf->fd);
1551       if (size == 0) {
1552         if (db3) printf("Nothing more to read. Read: %d/%d\n",
1553                         bf->size_sent, bf->size);
1554         padding = 1;
1555       }
1556     }
1557
1558     if (padding) {
1559       if (bf->size_sent < bf->size) {
1560         if (db3) printf("padding...\n");
1561         size = (bf->size - bf->size_sent > DATA_SIZE) ?
1562           DATA_SIZE : bf->size - bf->size_sent;
1563         memset(buf, 0, size);
1564       }
1565       else {
1566         if (db3) printf("All written\n");
1567         padding = 0;
1568         size = 0;
1569       }
1570     }
1571
1572     if (size != 0) {
1573       if (db3) printf("size: %d %d/%d\n", size, bf->size_sent, bf->size);
1574       bf->size_sent += size;
1575       last_packet = allocate_packet(last_packet);
1576
1577       /* Calculate checksum. */
1578       sum = 0;
1579       for (i = 0; i != size; i++) {
1580         sum += ((byte*)buf)[i];
1581       }
1582       if (db2) printf("Checksum 0x%x, bytes %d\n", sum, i);
1583
1584       /* Figure out size of packet. */
1585       if (netBoot) {
1586         header_size = seq_nr == 0 ?
1587           SIZE_OF_FIRST_HEADER : sizeof(struct packet_header_T);
1588
1589         packet_size = ((size) < DATA_SIZE ? size : DATA_SIZE) + header_size;
1590       }
1591       else {
1592         header_size = 0;
1593         packet_size = size;
1594       }
1595
1596       if (packet_size < 60) { /* CRC adds 4 bytes to 64 */
1597         printf(
1598           "Last packet from file '%s', is smaller than 64 bytes. \n"
1599           "This is not allowed in the Ethernet standard. Will pad with %d "
1600           "bytes.\n", bf->fileName, 60-packet_size);
1601
1602         *(bf->size_p) += 60-packet_size;
1603         packet_size = 60;
1604       }
1605
1606       last_packet->size = packet_size;
1607       last_packet->data = (char*)malloc(packet_size);
1608       last_packet->boot_file = bf;
1609       last_packet->baud_rate = 0;/*set_baudrate;*/
1610
1611       /*      printf("size %8.8x\n", last_packet->size);*/
1612       /*      printf("data %8.8x\n",last_packet->data);*/
1613
1614       if (netBoot) {
1615         /* Initialize ethernet header. */
1616         ph = (struct packet_header_T*) last_packet->data;
1617         memcpy(ph->dest, dst_addr_of_device, 6);
1618         memcpy(ph->src,  eth_addr_local,     6);
1619         /*      printf("packet_size %d\n", packet_size);*/
1620         ph->length = htons(packet_size);
1621         ph->snap1  = htonl(SNAP1);
1622         ph->snap2  = htonl(SNAP2);
1623         ph->tag    = htonl(SERVER_TAG);
1624         ph->seq    = htonl(seq_nr);
1625         last_packet->seq = seq_nr;
1626         if (seq_nr != 0) {
1627           ph->type = htonl(BOOT_PACKET);
1628           ph->id   = htonl(0); /* id doesn't matter, we send to a unicast address */
1629         }
1630       }
1631
1632       /* Copy data in place. */
1633       memcpy(&last_packet->data[header_size], buf, packet_size - header_size);
1634       if (db2) DecodeSvintoBoot(last_packet->data);
1635       /*      PrintPacket(last_packet->data, last_packet->size, HEX);*/
1636       seq_nr++;
1637
1638       if (db3) printf("< CreateNewBootPacket\n");
1639       return(last_packet);
1640     }
1641     else {                   /* Nothing read from fd. */
1642       fclose(bf->fd);
1643       bf = bf->next;
1644     }
1645   }
1646
1647   if (db3) printf("< CreateNewBootPacket\n");
1648   return(NULL);
1649 }
1650
1651 /****************** END OF FILE common.c ************************************/