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