1 /*!***************************************************************************
3 *! FILE NAME : common.c
5 *! DESCRIPTION: Common functions for e100boot.
7 *! ---------------------------------------------------------------------------
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 $ */
18 /************************** Version **************************************/
20 char version[] = "Time-stamp: $Id: common.c,v 1.1 2004/01/26 10:52:40 mikaelp Exp $";
22 /************************** Include files ********************************/
24 #define WIN32_LEAN_AND_MEAN
28 #include <sys/types.h>
35 #include "boot_images.h"
37 #include <sv_addr_ag.h>
43 /************************** Constants and macros *************************/
45 #define BOOT_CMDS_FILE "BOOT_CMDS"
47 /************************** Type definitions *****************************/
55 /************************** Global variables *****************************/
57 char needle[MAX_STRING_LEN] = "END"; /* search needle for --find */
60 int exitonfind = FALSE;
62 int doing_flash = FALSE; /* Just a flag to see if we should
63 warn that it might take some
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? */
71 struct label_t *loop_label = NULL;
72 struct label_t *label = NULL;
74 struct packet_buf *first_packet = NULL;
75 struct packet_buf *last_packet = NULL;
77 struct packet_buf *boot_cmds_packet;
79 int create_boot_loader = TRUE;
81 /* We use the INTERNAL boot image as default */
82 char boot_loader_file[MAX_STRING_LEN] = INTERNAL_NW;
84 int noleds = FALSE; /* Use boot images that doesn't toggle leds? */
86 struct boot_files_T *first_boot_file = NULL;
87 struct boot_files_T *last_boot_file = NULL;
89 unsigned int boot_cmds[SIZE_OF_BOOT_CMDS / sizeof(unsigned int)];
90 int boot_cmds_cnt = 0;
96 struct packet_header_T send_packet;
97 struct packet_header_T *receive_packet;
107 char device[MAX_STRING_LEN] = "";
110 /************************** Function prototypes **************************/
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);
129 /****************************************************************************
131 *# FUNCTION NAME: main
133 *# PARAMETERS: Command line arguments.
135 *#---------------------------------------------------------------------------
140 *# 961022 ronny Initial version
142 *#***************************************************************************/
145 main(int argc, const char *argv[])
147 ParseArgs(argc, argv);
150 /* We make this a special case to avoid messing up other code. */
153 SendToDevice(&boot_cmds_packet->data[SIZE_OF_HEADER],SIZE_OF_BOOT_CMDS);
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. */
163 /*if (!SetupSerial())*/ {
172 printf("Starting boot...\n");
174 printf("We're doing a flash write, this may take up to a few minutes...\n");
179 struct packet_buf *p;
181 while((p = create_packet(seq++))) {
182 SendToDevice(p->data, p->size);
199 /****************************************************************************
201 *# FUNCTION NAME: free_packet
203 *# PARAMETERS: struct to free
205 *# DESCRIPTION: Frees struct and data in struct.
207 *# RETURNS: Pointer to next struct.
209 *#---------------------------------------------------------------------------
214 *# 2000 02 07 ronny Initial version
216 *#***************************************************************************/
219 free_packet(struct packet_buf *p)
221 struct packet_buf *next_p;
229 /****************************************************************************
231 *# FUNCTION NAME: create_packet
233 *# PARAMETERS: Sequence number of desired packet.
237 *#---------------------------------------------------------------------------
242 *# 2000 06 28 ronny Initial version
244 *#***************************************************************************/
247 create_packet(udword seq)
249 struct packet_buf *p = first_packet;
250 /* Should check last first? */
252 if (db4) printf("> create_packet seq %d\n", seq);
261 return(CreateNewBootPacket());
264 /****************************************************************************
266 *# FUNCTION NAME: find_string
268 *# PARAMETERS: New string to search.
270 *# DESCRIPTION: Searches a number of strings for needle[], including strings
271 *# overlapping between different calls.
273 *#---------------------------------------------------------------------------
278 *# 020502 ronny Initial version
280 *#***************************************************************************/
283 find_string(char *str)
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;
291 static int cur_needle = 0;
296 // printf("# adding >%s<\n", str);
302 while((c = str[s])) {
303 // printf("\n# cur_hs %d, hs_len %d\n", cur_hs, hs_len);
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]);
312 if (cur_hs == hs_len) {
313 // printf("adding char %d(%c) at hs[%d]\n", (int)c, c < 32 ? 'X' : c, hs_len);
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);
322 if (hs[cur_hs] == needle[cur_needle]) {
323 if (cur_needle+1 == needle_len) {
324 int exitcode = EXIT_SUCCESS;
326 // printf("\nFound needle from --find option.\n");
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]);
333 printf("Exiting with code %d\n", exitcode);
340 // printf("no match, shifting hs.\n");
343 for(i=0; i!= hs_len-1; i++) {
355 /****************************************************************************
357 *# FUNCTION NAME: Fopen
359 *# PARAMETERS: Name and mode, both strings.
361 *# DESCRIPTION: Opens a file and returns its fd, or NULL.
363 *#---------------------------------------------------------------------------
368 *# 961022 ronny Initial version
370 *#***************************************************************************/
373 Fopen(const char *name, const char *mode)
377 if (db2) printf(">>> Fopen '%s', mode '%s'\n", name, mode);
379 fd = fopen(name, mode);
382 printf("<<< Fopen failed on '%s', mode '%s'\n", name, mode);
383 return ((FILE*) NULL);
386 if (strncmp(mode, "a", 1) == 0) {
387 if (db3) printf("* Append mode, seeking to end.\n");
388 fseek(fd, 0L, SEEK_SET);
391 if (db2) printf("<<< Fopen: '%s'\n", name);
396 /****************************************************************************
398 *# FUNCTION NAME: ParseArgs
400 *# PARAMETERS: Standard command line args.
402 *# DESCRIPTION: Parses command line arguments.
404 *#---------------------------------------------------------------------------
409 *# 960909 ronny Initial version
410 *#***************************************************************************/
413 ParseArgs (int argc, const char *argv[])
417 int printHelp = FALSE;
418 int exitCode = EXIT_SUCCESS;
419 char dbStr[MAX_STRING_LEN]; /* Debug option string. */
422 const char **argVect;
425 if (db4) printf(">>> ParseArgs\n");
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) {
434 exitCode = EXIT_FAILURE;
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");
444 else if (strncmp(argVect[argi], "--device", 8) == 0) {
445 if (GetStringOption(&argi, argCount, argVect, device, "--device") == 0) {
447 exitCode = EXIT_FAILURE;
451 else if (strncmp(argVect[argi], "--network", 9) == 0) {
454 strcpy(boot_loader_file, INTERNAL_NW);
457 else if (strncmp(argVect[argi], "--serial", 8) == 0) {
460 strcpy(device, "/dev/ttyS0");
461 strcpy(boot_loader_file, INTERNAL_SER);
464 else if (strncmp(argVect[argi], "--noleds", 8) == 0) {
468 else if (strncmp(argVect[argi], "--images", 8) == 0) {
471 printf("Internal images:\n");
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
484 else if (strncmp(argv[argi], "--baudrate", 10) == 0) {
485 /* if (GetNumberOption (&argi, argCount, argVect, &set_baudrate, "--baudrate", 10) == 0)*/ {
487 exitCode = EXIT_FAILURE;
491 else if (strncmp(argVect[argi], "--tofiles", 9) == 0) {
495 else if (strncmp(argVect[argi], "--cmdsonly", 10) == 0) {
499 else if (strncmp(argVect[argi], "--to", 4) == 0) {
500 if ((GetStringOption(&argi, argCount, argVect, host2, "--to") == 0)) {
502 exitCode = EXIT_FAILURE;
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");
513 else if (strncmp(argVect[argi], "--printp", 8) == 0) {
517 else if (strncmp(argVect[argi], "--printascii", 11) == 0) {
519 printPacketType = ASCII;
522 else if (strncmp(argVect[argi], "--printudec", 11) == 0) {
524 printPacketType = UDEC;
527 else if (strncmp(argVect[argi], "--printhex", 10) == 0) {
529 printPacketType = HEX;
532 else if (strncmp(argVect[argi], "--bpl", 5) == 0) {
533 if (GetNumberOption(&argi, argCount, argVect, &p_packet_bpl, "--bpl", 10) == 0) {
535 exitCode = EXIT_FAILURE;
539 else if (strncmp(argVect[argi], "--promisc", 11) == 0) {
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;
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;
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;
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;
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;
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);
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);
628 GetNumberOption(&argi, argCount, argVect, &boot_cmds[boot_cmds_cnt++], "--setreg", 16);
630 GetNumberOption(&argi, argCount, argVect, &boot_cmds[boot_cmds_cnt++], "--setreg", 16);
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);
639 GetNumberOption(&argi, argCount, argVect, &boot_cmds[boot_cmds_cnt++], "--getreg", 16);
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);
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);
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);
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);
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);
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);
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);
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);
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));
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;
720 GetNumberOption(&argi, argCount, argVect,
721 &last_boot_file->size , str, 16); /* size */
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);
729 else if (strncmp(argVect[argi], "--bootfile", 10) == 0) {
730 GetStringOption(&argi, argCount, argVect,
731 boot_loader_file, "--bootfile");
734 else if (strncmp(argVect[argi], "-d", 2) == 0) {
735 if (GetNumberOption (&argi, argCount, argVect, &number, "-d", 10) == 0) {
737 exitCode = EXIT_FAILURE;
740 sprintf(dbStr, "%d", number);
741 for (i = 0; i != (int) strlen(dbStr); i++) {
742 switch (dbStr[i] - '0') {
756 printf("ERROR! Debug level %d is not defined.\n", dbStr[i] - '0');
758 exitCode = EXIT_FAILURE;
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 */
774 for (i = 0; (c = needle[i]); i++,j++) {
775 // printf("c = %d, i %d, j %d\n", (int)c, i, j);
797 printf("Uknown escape sequence '\\%c'\n", c);
802 // printf("setting j %d to %d\n", j, (int)c);
808 for (i = 0; needle[i]; i++) {
809 //printf("i = %d, c %d\n", i,(int)needle[i]);
813 else if (strncmp(argVect[argi], "--exitonfind", 12) == 0) {
817 else if (strncmp(argVect[argi], "--help", 6) == 0) {
822 printf("ERROR! Don't understand option '%s'\n", argVect[argi]);
824 exitCode = EXIT_FAILURE;
828 if (printHelp == TRUE) {
834 strcpy(&boot_loader_file[strlen(boot_loader_file)], "_NOLEDS");
840 /****************************************************************************
842 *# FUNCTION NAME: handle_labels
844 *# PARAMETERS: global loop_label, label
846 *# DESCRIPTION: Checks and matches labels from --loop and --label commands
847 *# and inserts the resolved addresses into boot commands.
849 *#---------------------------------------------------------------------------
854 *# 20020204 ronny Initial version
856 *#***************************************************************************/
861 struct label_t *ll = loop_label;
862 struct label_t *l = label;
863 struct label_t *last_l = l;
872 if (l->name && ll->name && (strcmp(l->name, ll->name) == 0)) {
874 boot_cmds[ll->addr] = IO_BUF_START+(l->addr*4);
880 printf("Error. No label '%s' defined as needed by --loop command.\n", ll->name);
887 /****************************************************************************
889 *# FUNCTION NAME: new_label
895 *#---------------------------------------------------------------------------
900 *# 20020201 ronny Initial version
902 *#***************************************************************************/
905 new_label(struct label_t **label, udword addr, const char *name)
907 struct label_t *new_p;
909 new_p = malloc(sizeof(struct label_t));
911 if (*label == NULL) { /* first one? */
916 new_p->prev = *label;
919 new_p->addr = boot_cmds_cnt;
920 new_p->name = malloc(strlen(name));
921 strcpy(new_p->name, name);
924 /****************************************************************************
926 *# FUNCTION NAME: GetStringOption
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.
934 *# DESCRIPTION: Extracts a string option from argv, and updates argnr.
935 *# Returns TRUE/FALSE and string in *ret.
937 *#---------------------------------------------------------------------------
942 *# 960930 ronny Initial version
943 *# 961203 ronny Handles filenames with spaces within 'file name'.
945 *#***************************************************************************/
948 GetStringOption(int *argNr, int argCount, const char *argVect[], char *ret,
951 int startChar = strlen(option);
955 /* Are there any more chars after option? If not skip to next argv. */
956 if (strlen(argVect[*argNr]) <= (unsigned int)startChar) {
962 if (*argNr >= argCount) {
963 printf("ERROR! The option '%s' needs a string argument.\n", option);
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);
975 strcpy(ret, &argVect[*argNr][startChar]);
976 if (db4) printf("<<< GetStringOption '%s'\n", ret);
981 /****************************************************************************
983 *# FUNCTION NAME: GetNumberOption
989 *#---------------------------------------------------------------------------
994 *# 960930 ronny Initial version
996 *#***************************************************************************/
999 GetNumberOption(int *argNr, int argCount, const char *argVect[],
1000 unsigned int *ret, const char *option, int base)
1003 int add_io_base = 0;
1007 if (*argNr >= argCount) {
1008 printf("ERROR! The option '%s' needs a number argument.\n", option);
1013 if (argVect[*argNr][startChar] == '+') {
1018 *ret = strtoul(&argVect[*argNr][startChar], NULL, 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);
1029 if (db4) printf("<<< GetNumberOption %08x\r\n", *ret);
1034 /****************************************************************************
1036 *# FUNCTION NAME: GetRegisterOption
1042 *#---------------------------------------------------------------------------
1045 *# DATE NAME CHANGES
1046 *# ---- ---- -------
1047 *# 960930 ronny Initial version
1049 *#***************************************************************************/
1052 GetRegisterOption(int *argNr, int argCount, const char *argVect[],
1053 unsigned int *ret, const char *option, int base)
1059 if (*argNr >= argCount) {
1060 printf("Error! The option '%s' needs a register name.\n", option);
1068 while (reg_des[r].name) {
1069 if (strcmp(reg_des[r].name, argVect[*argNr]) == 0) {
1070 *ret = reg_des[r].addr;
1078 printf("Error! Didn't find a register name matching '%s'.\n",
1086 /****************************************************************************
1088 *# FUNCTION NAME: PrintHelp
1090 *# PARAMETERS: None.
1092 *# DESCRIPTION: Prints help info.
1094 *#---------------------------------------------------------------------------
1095 *# DATE NAME CHANGES
1096 *# ---- ---- -------
1097 *# 960909 ronny Initial version
1099 *#***************************************************************************/
1104 printf("e100boot version %s.\n", version);
1106 printf("\ne100boot [--device devicename] [--file filename|- addr [size]]\n"
1107 " [--flash ram-source flash-offset size]\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"
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);
1122 printf(" See the man page for more details about e100boot.\n\n");
1125 /****************************************************************************
1127 *# FUNCTION NAME: CreateBootLoader
1129 *# PARAMETERS: None.
1131 *# DESCRIPTION: Creates boot packets from boot file or internal loader.
1133 *#---------------------------------------------------------------------------
1134 *# DATE NAME CHANGES
1135 *# ---- ---- -------
1136 *# 960909 ronny Initial version
1137 *#***************************************************************************/
1140 CreateBootLoader(void)
1144 // int size_pos = 0x18;
1145 // int addr_pos = 0x28;
1146 struct packet_header_T *ph;
1153 if (create_boot_loader) {
1156 const struct boot_image_info_type *info;
1158 if (db4) printf("> CreateBootLoader\n");
1160 info = &boot_image_info[image_nbr];
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? */
1169 printf("Using internal boot loader: %s - %s.\n",
1170 info->name, info->info);
1174 info = &boot_image_info[image_nbr];
1178 /* No internal? Load it from file instead. */
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));
1189 if (fstat(fileno(fd), &st) == -1) {
1190 printf("Cannot get filestatus of bootloader '%s'. %s.\n",
1191 boot_loader_file, strerror(errno));
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",
1206 /* Alright, got loader in buf[] and size in st. */
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. */
1215 packet_size = DATA_SIZE;
1218 packet_size = st.st_size;
1221 /* Hack binary, insert size and address. */
1223 #define SIZE_PATTERN 0x12345678
1224 #define ADDR_PATTERN 0x87654321
1225 #define SIZE_POS (netBoot ? 0x0c : 0x10)
1226 #define ADDR_POS (netBoot ? 0x10 : 0x14)
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]);
1234 /* How much data to load except data in first packet. */
1237 *(udword*)(&buf[SIZE_POS]) = st.st_size - DATA_SIZE;
1240 *(udword*)(&buf[SIZE_POS]) = st.st_size - 784;
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]);
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]);
1254 *(udword*)(&buf[ADDR_POS]) = BOOT_ADDRESS + DATA_SIZE;
1257 *(udword*)(&buf[ADDR_POS]) = BOOT_ADDRESS-4 + 784;
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]);
1265 for (i = 0; i != st.st_size; i++) {
1266 sum += ((byte*)buf)[i];
1268 if (db1) printf("Checksum 0x%x, bytes %d\n", sum, i);
1273 for(i=0; i<st.st_size; i+=8) {
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]);
1283 /* Now create list of packets. */
1284 while (buf_cnt <= st.st_size) {
1286 header_size = seq_nr == 0 ?
1287 SIZE_OF_FIRST_HEADER : sizeof(struct packet_header_T);
1290 packet_size = ((st.st_size - buf_cnt) < DATA_SIZE ?
1291 st.st_size - buf_cnt : DATA_SIZE) + header_size;
1294 packet_size = st.st_size;
1298 if (db4) printf("seq_nr %d, header_size %d, packet_size %d\n",
1299 seq_nr, header_size, packet_size);
1301 last_packet = allocate_packet(last_packet);
1303 first_packet = first_packet ? first_packet : last_packet;
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;
1310 last_packet->boot_file = allocate_boot_file(NULL);
1311 last_packet->boot_file->fileName = boot_loader_file;
1313 // printf("last_packet->size %8.8x\n", last_packet->size);
1314 // printf("last_packet->data %8.8x\n",last_packet->data);
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);
1326 ph->type = htonl(BOOT_PACKET);
1331 memcpy(&last_packet->data[header_size], &buf[buf_cnt],
1332 packet_size - header_size);
1333 if (db3) DecodeSvintoBoot(last_packet->data);
1336 buf_cnt += DATA_SIZE;
1339 buf_cnt += packet_size +1;
1346 if (db4) printf("< CreateBootLoader\n");
1349 /****************************************************************************
1351 *# FUNCTION NAME: allocate_packet
1353 *# PARAMETERS: None.
1357 *#---------------------------------------------------------------------------
1358 *# DATE NAME CHANGES
1359 *# ---- ---- -------
1360 *# 960909 ronny Initial version
1361 *#***************************************************************************/
1364 allocate_packet(struct packet_buf *p)
1366 if (db4) printf("> allocate_packet\n");
1369 p->next = (struct packet_buf*) malloc(sizeof(struct packet_buf));
1373 p = (struct packet_buf*) malloc(sizeof(struct packet_buf));
1380 /****************************************************************************
1382 *# FUNCTION NAME: allocate_boot_file
1384 *# PARAMETERS: None.
1388 *#---------------------------------------------------------------------------
1389 *# DATE NAME CHANGES
1390 *# ---- ---- -------
1391 *# 960909 ronny Initial version
1392 *#***************************************************************************/
1394 struct boot_files_T*
1395 allocate_boot_file(struct boot_files_T *bf)
1398 bf->next = (struct boot_files_T*) malloc(sizeof(struct boot_files_T));
1402 bf = (struct boot_files_T*) malloc(sizeof(struct boot_files_T));
1409 /****************************************************************************
1411 *# FUNCTION NAME: CreateBootCmds
1413 *# PARAMETERS: None.
1415 *# DESCRIPTION: Creates a boot packet from the boot commands. The data is
1416 *# filled in later by FinishBootCmds().
1418 *#---------------------------------------------------------------------------
1419 *# DATE NAME CHANGES
1420 *# ---- ---- -------
1421 *# 980818 ronny Initial version
1422 *#***************************************************************************/
1425 CreateBootCmds(void)
1427 struct packet_header_T *ph;
1429 if (db4) printf("***> CreateBootCmds\n");
1431 last_packet = allocate_packet(last_packet);
1433 boot_cmds_packet = last_packet;
1435 last_packet->boot_file = allocate_boot_file(NULL);
1436 last_packet->boot_file->fileName = BOOT_CMDS_FILE;
1437 last_packet->baud_rate = 9600;
1439 last_packet->size = netBoot ? SIZE_OF_BOOT_CMDS + sizeof(struct packet_header_T)
1440 : SIZE_OF_BOOT_CMDS;
1442 last_packet->data = (char *) malloc(last_packet->size);
1443 last_packet->seq = seq_nr;
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);
1456 ph->type = htonl(BOOT_CMDS);
1460 if (db3) DecodeSvintoBoot(last_packet->data);
1461 if (db4) printf("<*** CreateBootCmds\n");
1464 /****************************************************************************
1466 *# FUNCTION NAME: FinishBootCmds
1468 *# PARAMETERS: None.
1470 *# DESCRIPTION: Copies the boot commands into the correct packet and changes
1471 *# the dwords to network order.
1473 *#---------------------------------------------------------------------------
1474 *# DATE NAME CHANGES
1475 *# ---- ---- -------
1476 *# 960909 ronny Initial version
1477 *#***************************************************************************/
1480 FinishBootCmds(void)
1483 unsigned int offset = 0;
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]);
1490 /* Copy boot commands into packet. */
1492 offset = sizeof(struct packet_header_T);
1495 memcpy(&boot_cmds_packet->data[offset], boot_cmds,
1496 boot_cmds_cnt * sizeof(udword));
1499 /****************************************************************************
1501 *# FUNCTION NAME: CreateNewBootPacket
1503 *# PARAMETERS: None.
1505 *# DESCRIPTION: Creates next packet for the files specified by '--file'.
1507 *# RETURNS: Next packet, or NULL.
1509 *#---------------------------------------------------------------------------
1510 *# DATE NAME CHANGES
1511 *# ---- ---- -------
1512 *# 960909 ronny Initial version
1513 *#***************************************************************************/
1516 CreateNewBootPacket(void)
1518 static char buf[DATA_SIZE];
1519 struct packet_header_T *ph;
1527 static struct boot_files_T *bf = NULL;
1529 if (db3) printf("> CreateNewBootPacket\n");
1531 bf = bf ? bf : first_boot_file;
1535 if (strcmp(bf->fileName, "-") == 0) {
1539 bf->fd = fopen(bf->fileName, "rb");
1542 if (bf->fd == NULL) {
1543 printf("Cannot open boot file %s. Exiting\n", bf->fileName);
1546 if (db3) printf("Opening boot file %s\n", bf->fileName);
1550 size = fread(buf, 1, DATA_SIZE, bf->fd);
1552 if (db3) printf("Nothing more to read. Read: %d/%d\n",
1553 bf->size_sent, bf->size);
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);
1566 if (db3) printf("All written\n");
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);
1577 /* Calculate checksum. */
1579 for (i = 0; i != size; i++) {
1580 sum += ((byte*)buf)[i];
1582 if (db2) printf("Checksum 0x%x, bytes %d\n", sum, i);
1584 /* Figure out size of packet. */
1586 header_size = seq_nr == 0 ?
1587 SIZE_OF_FIRST_HEADER : sizeof(struct packet_header_T);
1589 packet_size = ((size) < DATA_SIZE ? size : DATA_SIZE) + header_size;
1596 if (packet_size < 60) { /* CRC adds 4 bytes to 64 */
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);
1602 *(bf->size_p) += 60-packet_size;
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;*/
1611 /* printf("size %8.8x\n", last_packet->size);*/
1612 /* printf("data %8.8x\n",last_packet->data);*/
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;
1627 ph->type = htonl(BOOT_PACKET);
1628 ph->id = htonl(0); /* id doesn't matter, we send to a unicast address */
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);*/
1638 if (db3) printf("< CreateNewBootPacket\n");
1639 return(last_packet);
1641 else { /* Nothing read from fd. */
1647 if (db3) printf("< CreateNewBootPacket\n");
1651 /****************** END OF FILE common.c ************************************/