1 /*!***************************************************************************
3 *! FILE NAME : common.c
5 *! DESCRIPTION: Common functions for e100boot.
7 *! ---------------------------------------------------------------------------
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 $ */
18 /************************** Version **************************************/
20 char version
[] = "Time-stamp: $Id: common.c,v 1.13 2006/02/08 14:00:25 pkj Exp $";
22 /************************** Include files ********************************/
29 #include "boot_images.h"
31 #include <sv_addr_ag.h>
37 /************************** Constants and macros *************************/
39 #define BOOT_CMDS_FILE "BOOT_CMDS"
41 /************************** Type definitions *****************************/
49 /************************** Global variables *****************************/
51 char needle
[MAX_STRING_LEN
] = "END"; /* search needle for --find */
54 int exitonfind
= FALSE
;
56 int doing_flash
= FALSE
; /* Just a flag to see if we should
57 warn that it might take some
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? */
65 struct label_t
*loop_label
= NULL
;
66 struct label_t
*label
= NULL
;
68 struct packet_buf
*first_packet
= NULL
;
69 struct packet_buf
*last_packet
= NULL
;
71 struct packet_buf
*boot_cmds_packet
;
73 int create_boot_loader
= TRUE
;
75 /* We use the INTERNAL boot image as default */
76 char boot_loader_file
[MAX_STRING_LEN
] = INTERNAL_NW
;
78 int noleds
= FALSE
; /* Use boot images that doesn't toggle leds? */
80 struct boot_files_T
*first_boot_file
= NULL
;
81 struct boot_files_T
*last_boot_file
= NULL
;
83 unsigned int boot_cmds
[SIZE_OF_BOOT_CMDS
/ sizeof(unsigned int)];
84 int boot_cmds_cnt
= 0;
90 struct packet_header_T send_packet
;
91 struct packet_header_T
*receive_packet
;
101 char device
[MAX_STRING_LEN
] = "eth0";
103 /************************** Function prototypes **************************/
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);
123 /****************************************************************************
125 *# FUNCTION NAME: main
127 *# PARAMETERS: Command line arguments.
129 *#---------------------------------------------------------------------------
134 *# 961022 ronny Initial version
136 *#***************************************************************************/
139 main(int argc
, const char *argv
[])
141 ParseArgs(argc
, argv
);
144 /* We make this a special case to avoid messing up other code. */
147 SendToDevice(&boot_cmds_packet
->data
[SIZE_OF_HEADER
],SIZE_OF_BOOT_CMDS
);
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. */
157 if (!SetupSerial()) {
166 printf("Starting boot...\n");
168 printf("We're doing a flash write, this may take up to a few minutes...\n");
173 struct packet_buf
*p
;
175 while((p
= create_packet(seq
++))) {
176 SendToDevice(p
->data
, p
->size
);
193 /****************************************************************************
195 *# FUNCTION NAME: free_packet
197 *# PARAMETERS: struct to free
199 *# DESCRIPTION: Frees struct and data in struct.
201 *# RETURNS: Pointer to next struct.
203 *#---------------------------------------------------------------------------
208 *# 2000 02 07 ronny Initial version
210 *#***************************************************************************/
213 free_packet(struct packet_buf
*p
)
215 struct packet_buf
*next_p
;
223 /****************************************************************************
225 *# FUNCTION NAME: create_packet
227 *# PARAMETERS: Sequence number of desired packet.
231 *#---------------------------------------------------------------------------
236 *# 2000 06 28 ronny Initial version
238 *#***************************************************************************/
241 create_packet(udword seq
)
243 struct packet_buf
*p
= first_packet
;
244 /* Should check last first? */
246 if (db4
) printf("> create_packet seq %d\n", seq
);
255 return(CreateNewBootPacket());
258 /****************************************************************************
260 *# FUNCTION NAME: find_string
262 *# PARAMETERS: New string to search.
264 *# DESCRIPTION: Searches a number of strings for needle[], including strings
265 *# overlapping between different calls.
267 *#---------------------------------------------------------------------------
272 *# 020502 ronny Initial version
274 *#***************************************************************************/
277 find_string(char *str
)
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;
285 static int cur_needle
= 0;
290 // printf("# adding >%s<\n", str);
296 while((c
= str
[s
])) {
297 // printf("\n# cur_hs %d, hs_len %d\n", cur_hs, hs_len);
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]);
306 if (cur_hs
== hs_len
) {
307 // printf("adding char %d(%c) at hs[%d]\n", (int)c, c < 32 ? 'X' : c, hs_len);
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);
316 if (hs
[cur_hs
] == needle
[cur_needle
]) {
317 if (cur_needle
+1 == needle_len
) {
318 int exitcode
= EXIT_SUCCESS
;
320 // printf("\nFound needle from --find option.\n");
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]);
327 printf("Exiting with code %d\n", exitcode
);
334 // printf("no match, shifting hs.\n");
337 for(i
=0; i
!= hs_len
-1; i
++) {
349 /****************************************************************************
351 *# FUNCTION NAME: Fopen
353 *# PARAMETERS: Name and mode, both strings.
355 *# DESCRIPTION: Opens a file and returns its fd, or NULL.
357 *#---------------------------------------------------------------------------
362 *# 961022 ronny Initial version
364 *#***************************************************************************/
367 Fopen(const char *name
, const char *mode
)
371 if (db2
) printf(">>> Fopen '%s', mode '%s'\n", name
, mode
);
374 fd
= _fsopen(name
, mode
, _SH_DENYNO
);
376 fd
= fopen(name
, mode
);
380 printf("<<< Fopen failed on '%s', mode '%s'\n", name
, mode
);
381 return ((FILE*) NULL
);
384 if (strncmp(mode
, "a", 1) == 0) {
385 if (db3
) printf("* Append mode, seeking to end.\n");
386 fseek(fd
, 0L, SEEK_SET
);
389 if (db2
) printf("<<< Fopen: '%s'\n", name
);
394 /****************************************************************************
396 *# FUNCTION NAME: ParseArgs
398 *# PARAMETERS: Standard command line args.
400 *# DESCRIPTION: Parses command line arguments.
402 *#---------------------------------------------------------------------------
407 *# 960909 ronny Initial version
408 *#***************************************************************************/
411 ParseArgs (int argc
, const char *argv
[])
415 int printHelp
= FALSE
;
416 int exitCode
= EXIT_SUCCESS
;
417 char dbStr
[MAX_STRING_LEN
]; /* Debug option string. */
420 const char **argVect
;
423 if (db4
) printf(">>> ParseArgs\n");
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) {
432 exitCode
= EXIT_FAILURE
;
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");
442 else if (strncmp(argVect
[argi
], "--device", 8) == 0) {
443 if (GetStringOption(&argi
, argCount
, argVect
, device
, "--device") == 0) {
445 exitCode
= EXIT_FAILURE
;
449 else if (strncmp(argVect
[argi
], "--network", 9) == 0) {
452 strcpy(device
, "eth0");
453 strcpy(boot_loader_file
, INTERNAL_NW
);
456 else if (strncmp(argVect
[argi
], "--serial", 8) == 0) {
459 strcpy(device
, "/dev/ttyS0");
460 strcpy(boot_loader_file
, INTERNAL_SER
);
463 else if (strncmp(argVect
[argi
], "--noleds", 8) == 0) {
467 else if (strncmp(argVect
[argi
], "--images", 8) == 0) {
470 printf("Internal images:\n");
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
483 else if (strncmp(argv
[argi
], "--baudrate", 10) == 0) {
484 if (GetNumberOption (&argi
, argCount
, argVect
, &set_baudrate
, "--baudrate", 10) == 0) {
486 exitCode
= EXIT_FAILURE
;
490 else if (strncmp(argVect
[argi
], "--tofiles", 9) == 0) {
494 else if (strncmp(argVect
[argi
], "--cmdsonly", 10) == 0) {
498 else if (strncmp(argVect
[argi
], "--to", 4) == 0) {
499 if ((GetStringOption(&argi
, argCount
, argVect
, host2
, "--to") == 0)) {
501 exitCode
= EXIT_FAILURE
;
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");
512 else if (strncmp(argVect
[argi
], "--printp", 8) == 0) {
516 else if (strncmp(argVect
[argi
], "--printascii", 11) == 0) {
518 printPacketType
= ASCII
;
521 else if (strncmp(argVect
[argi
], "--printudec", 11) == 0) {
523 printPacketType
= UDEC
;
526 else if (strncmp(argVect
[argi
], "--printhex", 10) == 0) {
528 printPacketType
= HEX
;
531 else if (strncmp(argVect
[argi
], "--bpl", 5) == 0) {
532 if (GetNumberOption(&argi
, argCount
, argVect
, &p_packet_bpl
, "--bpl", 10) == 0) {
534 exitCode
= EXIT_FAILURE
;
538 else if (strncmp(argVect
[argi
], "--promisc", 11) == 0) {
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;
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;
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;
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;
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;
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);
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);
627 GetNumberOption(&argi
, argCount
, argVect
, &boot_cmds
[boot_cmds_cnt
++], "--setreg", 16);
629 GetNumberOption(&argi
, argCount
, argVect
, &boot_cmds
[boot_cmds_cnt
++], "--setreg", 16);
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);
638 GetNumberOption(&argi
, argCount
, argVect
, &boot_cmds
[boot_cmds_cnt
++], "--getreg", 16);
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);
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);
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
);
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
);
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);
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);
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);
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);
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
));
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
;
718 GetNumberOption(&argi
, argCount
, argVect
,
719 &last_boot_file
->size
, str
, 16); /* size */
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
);
727 else if (strncmp(argVect
[argi
], "--bootfile", 10) == 0) {
728 GetStringOption(&argi
, argCount
, argVect
,
729 boot_loader_file
, "--bootfile");
732 else if (strncmp(argVect
[argi
], "-d", 2) == 0) {
733 if (GetNumberOption (&argi
, argCount
, argVect
, &number
, "-d", 10) == 0) {
735 exitCode
= EXIT_FAILURE
;
738 sprintf(dbStr
, "%d", number
);
739 for (i
= 0; i
!= (int) strlen(dbStr
); i
++) {
740 switch (dbStr
[i
] - '0') {
754 printf("ERROR! Debug level %d is not defined.\n", dbStr
[i
] - '0');
756 exitCode
= EXIT_FAILURE
;
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 */
772 for (i
= 0; (c
= needle
[i
]); i
++,j
++) {
773 // printf("c = %d, i %d, j %d\n", (int)c, i, j);
795 printf("Uknown escape sequence '\\%c'\n", c
);
800 // printf("setting j %d to %d\n", j, (int)c);
806 for (i
= 0; needle
[i
]; i
++) {
807 //printf("i = %d, c %d\n", i,(int)needle[i]);
811 else if (strncmp(argVect
[argi
], "--exitonfind", 12) == 0) {
815 else if (strncmp(argVect
[argi
], "--help", 6) == 0) {
820 printf("ERROR! Don't understand option '%s'\n", argVect
[argi
]);
822 exitCode
= EXIT_FAILURE
;
826 if (printHelp
== TRUE
) {
832 strcpy(&boot_loader_file
[strlen(boot_loader_file
)], "_NOLEDS");
838 /****************************************************************************
840 *# FUNCTION NAME: handle_labels
842 *# PARAMETERS: global loop_label, label
844 *# DESCRIPTION: Checks and matches labels from --loop and --label commands
845 *# and inserts the resolved addresses into boot commands.
847 *#---------------------------------------------------------------------------
852 *# 20020204 ronny Initial version
854 *#***************************************************************************/
859 struct label_t
*ll
= loop_label
;
860 struct label_t
*l
= label
;
861 struct label_t
*last_l
= l
;
870 if (l
->name
&& ll
->name
&& (strcmp(l
->name
, ll
->name
) == 0)) {
872 boot_cmds
[ll
->addr
] = IO_BUF_START
+(l
->addr
*4);
878 printf("Error. No label '%s' defined as needed by --loop command.\n", ll
->name
);
885 /****************************************************************************
887 *# FUNCTION NAME: new_label
893 *#---------------------------------------------------------------------------
898 *# 20020201 ronny Initial version
900 *#***************************************************************************/
903 new_label(struct label_t
**label
, udword addr
, const char *name
)
905 struct label_t
*new_p
;
907 new_p
= malloc(sizeof(struct label_t
));
909 if (*label
== NULL
) { /* first one? */
914 new_p
->prev
= *label
;
917 new_p
->addr
= boot_cmds_cnt
;
918 new_p
->name
= malloc(strlen(name
));
919 strcpy(new_p
->name
, name
);
922 /****************************************************************************
924 *# FUNCTION NAME: GetStringOption
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.
932 *# DESCRIPTION: Extracts a string option from argv, and updates argnr.
933 *# Returns TRUE/FALSE and string in *ret.
935 *#---------------------------------------------------------------------------
940 *# 960930 ronny Initial version
941 *# 961203 ronny Handles filenames with spaces within 'file name'.
943 *#***************************************************************************/
946 GetStringOption(int *argNr
, int argCount
, const char *argVect
[], char *ret
,
949 int startChar
= strlen(option
);
953 /* Are there any more chars after option? If not skip to next argv. */
954 if (strlen(argVect
[*argNr
]) <= (unsigned int)startChar
) {
960 if (*argNr
>= argCount
) {
961 printf("ERROR! The option '%s' needs a string argument.\n", option
);
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
);
973 strcpy(ret
, &argVect
[*argNr
][startChar
]);
974 if (db4
) printf("<<< GetStringOption '%s'\n", ret
);
979 /****************************************************************************
981 *# FUNCTION NAME: GetNumberOption
987 *#---------------------------------------------------------------------------
992 *# 960930 ronny Initial version
994 *#***************************************************************************/
997 GetNumberOption(int *argNr
, int argCount
, const char *argVect
[],
998 unsigned int *ret
, const char *option
, int base
)
1001 int add_io_base
= 0;
1005 if (*argNr
>= argCount
) {
1006 printf("ERROR! The option '%s' needs a number argument.\n", option
);
1011 if (argVect
[*argNr
][startChar
] == '+') {
1016 *ret
= strtoul(&argVect
[*argNr
][startChar
], NULL
, 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
);
1027 if (db4
) printf("<<< GetNumberOption %08x\r\n", *ret
);
1032 /****************************************************************************
1034 *# FUNCTION NAME: GetRegisterOption
1040 *#---------------------------------------------------------------------------
1043 *# DATE NAME CHANGES
1044 *# ---- ---- -------
1045 *# 960930 ronny Initial version
1047 *#***************************************************************************/
1050 GetRegisterOption(int *argNr
, int argCount
, const char *argVect
[],
1051 unsigned int *ret
, const char *option
, int base
)
1057 if (*argNr
>= argCount
) {
1058 printf("Error! The option '%s' needs a register name.\n", option
);
1066 while (reg_des
[r
].name
) {
1067 if (strcmp(reg_des
[r
].name
, argVect
[*argNr
]) == 0) {
1068 *ret
= reg_des
[r
].addr
;
1076 printf("Error! Didn't find a register name matching '%s'.\n",
1084 /****************************************************************************
1086 *# FUNCTION NAME: PrintHelp
1088 *# PARAMETERS: None.
1090 *# DESCRIPTION: Prints help info.
1092 *#---------------------------------------------------------------------------
1093 *# DATE NAME CHANGES
1094 *# ---- ---- -------
1095 *# 960909 ronny Initial version
1097 *#***************************************************************************/
1102 printf("e100boot version %s.\n", version
);
1104 printf("\ne100boot [--device devicename] [--file filename|- addr [size]]\n"
1105 " [--flash ram-source flash-offset size]\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"
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
);
1120 printf(" See the man page for more details about e100boot.\n\n");
1123 /****************************************************************************
1125 *# FUNCTION NAME: CreateBootLoader
1127 *# PARAMETERS: None.
1129 *# DESCRIPTION: Creates boot packets from boot file or internal loader.
1131 *#---------------------------------------------------------------------------
1132 *# DATE NAME CHANGES
1133 *# ---- ---- -------
1134 *# 960909 ronny Initial version
1135 *#***************************************************************************/
1138 CreateBootLoader(void)
1142 // int size_pos = 0x18;
1143 // int addr_pos = 0x28;
1144 struct packet_header_T
*ph
;
1151 if (create_boot_loader
) {
1154 const struct boot_image_info_type
*info
;
1156 if (db4
) printf("> CreateBootLoader\n");
1158 info
= &boot_image_info
[image_nbr
];
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? */
1167 printf("Using internal boot loader: %s - %s.\n",
1168 info
->name
, info
->info
);
1172 info
= &boot_image_info
[image_nbr
];
1176 /* No internal? Load it from file instead. */
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
));
1187 if (fstat(fileno(fd
), &st
) == -1) {
1188 printf("Cannot get filestatus of bootloader '%s'. %s.\n",
1189 boot_loader_file
, strerror(errno
));
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",
1204 /* Alright, got loader in buf[] and size in st. */
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. */
1213 packet_size
= DATA_SIZE
;
1216 packet_size
= st
.st_size
;
1219 /* Hack binary, insert size and address. */
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.
1228 #define SIZE_PATTERN 0x12345678
1229 #define ADDR_PATTERN 0x87654321
1230 #define SIZE_POS (netBoot ? 0x0c : 0x10)
1231 #define ADDR_POS (netBoot ? 0x10 : 0x14)
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
]);
1239 /* How much data to load except data in first packet. */
1242 *(udword
*)(&buf
[SIZE_POS
]) = swap_endian(st
.st_size
- DATA_SIZE
);
1245 *(udword
*)(&buf
[SIZE_POS
]) = swap_endian(st
.st_size
- 784);
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
]);
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
]);
1259 *(udword
*)(&buf
[ADDR_POS
]) = swap_endian(BOOT_ADDRESS
+ DATA_SIZE
);
1262 *(udword
*)(&buf
[ADDR_POS
]) = swap_endian(BOOT_ADDRESS
-4 + 784);
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
]);
1270 for (i
= 0; i
!= st
.st_size
; i
++) {
1271 sum
+= ((byte
*)buf
)[i
];
1273 if (db1
) printf("Checksum 0x%x, bytes %d\n", sum
, i
);
1278 for(i
=0; i
<st
.st_size
; i
+=8) {
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
]);
1288 /* Now create list of packets. */
1289 while (buf_cnt
<= st
.st_size
) {
1291 header_size
= seq_nr
== 0 ?
1292 SIZE_OF_FIRST_HEADER
: sizeof(struct packet_header_T
);
1295 packet_size
= ((st
.st_size
- buf_cnt
) < DATA_SIZE
?
1296 st
.st_size
- buf_cnt
: DATA_SIZE
) + header_size
;
1299 packet_size
= st
.st_size
;
1303 if (db4
) printf("seq_nr %d, header_size %d, packet_size %d\n",
1304 seq_nr
, header_size
, packet_size
);
1306 last_packet
= allocate_packet(last_packet
);
1308 first_packet
= first_packet
? first_packet
: last_packet
;
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;
1315 last_packet
->boot_file
= allocate_boot_file(NULL
);
1316 last_packet
->boot_file
->fileName
= boot_loader_file
;
1318 // printf("last_packet->size %8.8x\n", last_packet->size);
1319 // printf("last_packet->data %8.8x\n",last_packet->data);
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
);
1331 ph
->type
= htonl(BOOT_PACKET
);
1336 memcpy(&last_packet
->data
[header_size
], &buf
[buf_cnt
],
1337 packet_size
- header_size
);
1338 if (db3
) DecodeSvintoBoot(last_packet
->data
);
1341 buf_cnt
+= DATA_SIZE
;
1344 buf_cnt
+= packet_size
+1;
1351 if (db4
) printf("< CreateBootLoader\n");
1354 /****************************************************************************
1356 *# FUNCTION NAME: allocate_packet
1358 *# PARAMETERS: None.
1362 *#---------------------------------------------------------------------------
1363 *# DATE NAME CHANGES
1364 *# ---- ---- -------
1365 *# 960909 ronny Initial version
1366 *#***************************************************************************/
1369 allocate_packet(struct packet_buf
*p
)
1371 if (db4
) printf("> allocate_packet\n");
1374 p
->next
= (struct packet_buf
*) malloc(sizeof(struct packet_buf
));
1378 p
= (struct packet_buf
*) malloc(sizeof(struct packet_buf
));
1385 /****************************************************************************
1387 *# FUNCTION NAME: allocate_boot_file
1389 *# PARAMETERS: None.
1393 *#---------------------------------------------------------------------------
1394 *# DATE NAME CHANGES
1395 *# ---- ---- -------
1396 *# 960909 ronny Initial version
1397 *#***************************************************************************/
1399 struct boot_files_T
*
1400 allocate_boot_file(struct boot_files_T
*bf
)
1403 bf
->next
= (struct boot_files_T
*) malloc(sizeof(struct boot_files_T
));
1407 bf
= (struct boot_files_T
*) malloc(sizeof(struct boot_files_T
));
1414 /****************************************************************************
1416 *# FUNCTION NAME: CreateBootCmds
1418 *# PARAMETERS: None.
1420 *# DESCRIPTION: Creates a boot packet from the boot commands. The data is
1421 *# filled in later by FinishBootCmds().
1423 *#---------------------------------------------------------------------------
1424 *# DATE NAME CHANGES
1425 *# ---- ---- -------
1426 *# 980818 ronny Initial version
1427 *#***************************************************************************/
1430 CreateBootCmds(void)
1432 struct packet_header_T
*ph
;
1434 if (db4
) printf("***> CreateBootCmds\n");
1436 last_packet
= allocate_packet(last_packet
);
1438 boot_cmds_packet
= last_packet
;
1440 last_packet
->boot_file
= allocate_boot_file(NULL
);
1441 last_packet
->boot_file
->fileName
= BOOT_CMDS_FILE
;
1442 last_packet
->baud_rate
= 9600;
1444 last_packet
->size
= netBoot
? SIZE_OF_BOOT_CMDS
+ sizeof(struct packet_header_T
)
1445 : SIZE_OF_BOOT_CMDS
;
1447 last_packet
->data
= (char *) malloc(last_packet
->size
);
1448 last_packet
->seq
= seq_nr
;
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
);
1461 ph
->type
= htonl(BOOT_CMDS
);
1465 if (db3
) DecodeSvintoBoot(last_packet
->data
);
1466 if (db4
) printf("<*** CreateBootCmds\n");
1469 /****************************************************************************
1471 *# FUNCTION NAME: FinishBootCmds
1473 *# PARAMETERS: None.
1475 *# DESCRIPTION: Copies the boot commands into the correct packet and changes
1476 *# the dwords to network order.
1478 *#---------------------------------------------------------------------------
1479 *# DATE NAME CHANGES
1480 *# ---- ---- -------
1481 *# 960909 ronny Initial version
1482 *#***************************************************************************/
1485 FinishBootCmds(void)
1488 unsigned int offset
= 0;
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
]);
1495 /* Copy boot commands into packet. */
1497 offset
= sizeof(struct packet_header_T
);
1500 memcpy(&boot_cmds_packet
->data
[offset
], boot_cmds
,
1501 boot_cmds_cnt
* sizeof(udword
));
1504 /****************************************************************************
1506 *# FUNCTION NAME: CreateNewBootPacket
1508 *# PARAMETERS: None.
1510 *# DESCRIPTION: Creates next packet for the files specified by '--file'.
1512 *# RETURNS: Next packet, or NULL.
1514 *#---------------------------------------------------------------------------
1515 *# DATE NAME CHANGES
1516 *# ---- ---- -------
1517 *# 960909 ronny Initial version
1518 *#***************************************************************************/
1521 CreateNewBootPacket(void)
1523 static char buf
[DATA_SIZE
];
1524 struct packet_header_T
*ph
;
1532 static struct boot_files_T
*bf
= NULL
;
1534 if (db3
) printf("> CreateNewBootPacket\n");
1536 bf
= bf
? bf
: first_boot_file
;
1540 if (strcmp(bf
->fileName
, "-") == 0) {
1544 bf
->fd
= fopen(bf
->fileName
, "r");
1547 if (bf
->fd
== NULL
) {
1548 printf("Cannot open boot file %s. Exiting\n", bf
->fileName
);
1551 if (db3
) printf("Opening boot file %s\n", bf
->fileName
);
1555 size
= fread(buf
, 1, DATA_SIZE
, bf
->fd
);
1557 if (db3
) printf("Nothing more to read. Read: %d/%d\n",
1558 bf
->size_sent
, bf
->size
);
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
);
1571 if (db3
) printf("All written\n");
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
);
1582 /* Calculate checksum. */
1584 for (i
= 0; i
!= size
; i
++) {
1585 sum
+= ((byte
*)buf
)[i
];
1587 if (db2
) printf("Checksum 0x%x, bytes %d\n", sum
, i
);
1589 /* Figure out size of packet. */
1591 header_size
= seq_nr
== 0 ?
1592 SIZE_OF_FIRST_HEADER
: sizeof(struct packet_header_T
);
1594 packet_size
= ((size
) < DATA_SIZE
? size
: DATA_SIZE
) + header_size
;
1601 if (packet_size
< 60) { /* CRC adds 4 bytes to 64 */
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
);
1607 *(bf
->size_p
) += 60-packet_size
;
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
;
1616 /* printf("size %8.8x\n", last_packet->size);*/
1617 /* printf("data %8.8x\n",last_packet->data);*/
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
;
1632 ph
->type
= htonl(BOOT_PACKET
);
1633 ph
->id
= htonl(0); /* id doesn't matter, we send to a unicast address */
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);*/
1643 if (db3
) printf("< CreateNewBootPacket\n");
1644 return(last_packet
);
1646 else { /* Nothing read from fd. */
1652 if (db3
) printf("< CreateNewBootPacket\n");
1656 /****************************************************************************
1658 *# FUNCTION NAME: swap_endian
1660 *# PARAMETERS: u - An unsigned value.
1662 *# DESCRIPTION: Convert the unsigned value from host order to little endian.
1664 *# RETURNS: The unsigned value as little endian.
1666 *#***************************************************************************/
1669 swap_endian(unsigned int u
)
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.
1674 return ntohl(0x12345678) == 0x12345678 ? bswap_32(u
) : u
;
1677 /****************** END OF FILE common.c ************************************/