/*!*************************************************************************** *! *! FILE NAME : common.c *! *! DESCRIPTION: Common functions for e100boot. *! *! --------------------------------------------------------------------------- *! HISTORY *! *! DATE NAME CHANGES *! ---- ---- ------- *! ??? ? ???? Ronny Ranerup Initial version *! --------------------------------------------------------------------------- *! (C) Copyright 1999-2006 Axis Communications AB, LUND, SWEDEN *!***************************************************************************/ /* $Id: common.c,v 1.13 2006/02/08 14:00:25 pkj Exp $ */ /************************** Version **************************************/ char version[] = "Time-stamp: $Id: common.c,v 1.13 2006/02/08 14:00:25 pkj Exp $"; /************************** Include files ********************************/ #include #include #include #include #include "boot_images.h" #include #include #include #include #include /************************** Constants and macros *************************/ #define BOOT_CMDS_FILE "BOOT_CMDS" /************************** Type definitions *****************************/ struct label_t { struct label_t *prev; udword addr; char *name; }; /************************** Global variables *****************************/ char needle[MAX_STRING_LEN] = "END"; /* search needle for --find */ int needle_len = 3; int exitonfind = FALSE; int doing_flash = FALSE; /* Just a flag to see if we should warn that it might take some time. */ int toFiles = FALSE; /* Dump all packets to files. */ int cmdsOnly = FALSE; /* Just dump boot cmds to file. */ int netBoot = TRUE; /* Do network boot? */ int serBoot = FALSE; /* Do serial boot? */ struct label_t *loop_label = NULL; struct label_t *label = NULL; struct packet_buf *first_packet = NULL; struct packet_buf *last_packet = NULL; struct packet_buf *boot_cmds_packet; int create_boot_loader = TRUE; /* We use the INTERNAL boot image as default */ char boot_loader_file[MAX_STRING_LEN] = INTERNAL_NW; int noleds = FALSE; /* Use boot images that doesn't toggle leds? */ struct boot_files_T *first_boot_file = NULL; struct boot_files_T *last_boot_file = NULL; unsigned int boot_cmds[SIZE_OF_BOOT_CMDS / sizeof(unsigned int)]; int boot_cmds_cnt = 0; int svboot = FALSE; int quiet = 0; struct packet_header_T send_packet; struct packet_header_T *receive_packet; int seq_nr = 0; /* debug flags */ int db1 = FALSE; int db2 = FALSE; int db3 = FALSE; int db4 = FALSE; char device[MAX_STRING_LEN] = "eth0"; /************************** Function prototypes **************************/ FILE *Fopen (const char *name, const char *mode); int main (int argc, const char *argv[]); int GetNumberOption (int *argNr, int argCount, const char *argVect[], unsigned int *ret, const char *option, int base); int GetStringOption (int *argNr, int argCount, const char *argVect[], char *ret, const char *option); int GetRegisterOption (int *argNr, int argCount, const char *argVect[], unsigned int *ret, const char *option, int base); struct boot_files_T* allocate_boot_file (struct boot_files_T *bf); struct packet_buf* CreateNewBootPacket (void); struct packet_buf* allocate_packet (struct packet_buf *p); void SigHandler (int sig); void CreateBootLoader (void); void FinishBootCmds (void); void ParseArgs (int argc, const char *argv[]); void PrintHelp (void); void CreateBootCmds (void); void handle_labels (void); void new_label (struct label_t **label, udword addr, const char *name); unsigned int swap_endian (unsigned int); /**************************************************************************** *# *# FUNCTION NAME: main *# *# PARAMETERS: Command line arguments. *# *#--------------------------------------------------------------------------- *# HISTORY *# *# DATE NAME CHANGES *# ---- ---- ------- *# 961022 ronny Initial version *# *#***************************************************************************/ int main(int argc, const char *argv[]) { ParseArgs(argc, argv); if (cmdsOnly) { /* We make this a special case to avoid messing up other code. */ CreateBootCmds(); FinishBootCmds(); SendToDevice(&boot_cmds_packet->data[SIZE_OF_HEADER],SIZE_OF_BOOT_CMDS); exit(EXIT_SUCCESS); } if (netBoot && !toFiles) { /* Do not bother with this if we just want to write the packets to files. Means you do not have to be root to run --tofiles. */ net_init(); } else if (serBoot) { if (!SetupSerial()) { exit(0); } } CreateBootLoader(); CreateBootCmds(); FinishBootCmds(); printf("Starting boot...\n"); if (doing_flash) { printf("We're doing a flash write, this may take up to a few minutes...\n"); } if (toFiles) { udword seq = 0; struct packet_buf *p; while((p = create_packet(seq++))) { SendToDevice(p->data, p->size); } exit(EXIT_SUCCESS); } if (netBoot) { NetBoot(); } else if (serBoot) { SerBoot(); } printf("Done.\n"); return EXIT_SUCCESS; } /* main */ /**************************************************************************** *# *# FUNCTION NAME: free_packet *# *# PARAMETERS: struct to free *# *# DESCRIPTION: Frees struct and data in struct. *# *# RETURNS: Pointer to next struct. *# *#--------------------------------------------------------------------------- *# HISTORY *# *# DATE NAME CHANGES *# ---- ---- ------- *# 2000 02 07 ronny Initial version *# *#***************************************************************************/ struct packet_buf* free_packet(struct packet_buf *p) { struct packet_buf *next_p; next_p = p->next; free(p->data); free(p); return(next_p); } /**************************************************************************** *# *# FUNCTION NAME: create_packet *# *# PARAMETERS: Sequence number of desired packet. *# *# DESCRIPTION: *# *#--------------------------------------------------------------------------- *# HISTORY *# *# DATE NAME CHANGES *# ---- ---- ------- *# 2000 06 28 ronny Initial version *# *#***************************************************************************/ struct packet_buf* create_packet(udword seq) { struct packet_buf *p = first_packet; /* Should check last first? */ if (db4) printf("> create_packet seq %d\n", seq); while (p) { if (p->seq == seq) { return(p); } p = p->next; } return(CreateNewBootPacket()); } /**************************************************************************** *# *# FUNCTION NAME: find_string *# *# PARAMETERS: New string to search. *# *# DESCRIPTION: Searches a number of strings for needle[], including strings *# overlapping between different calls. *# *#--------------------------------------------------------------------------- *# HISTORY *# *# DATE NAME CHANGES *# ---- ---- ------- *# 020502 ronny Initial version *# *#***************************************************************************/ void find_string(char *str) { static int matched = 0; int hs[MAX_STRING_LEN]; static int cur_hs = 0; static int hs_len = 0; static int last_hs = 0; static int cur_needle = 0; if (!needle[0]) { return; } // printf("# adding >%s<\n", str); { int c = 0; int s = 0; while((c = str[s])) { // printf("\n# cur_hs %d, hs_len %d\n", cur_hs, hs_len); { int i; for(i = 0; i != hs_len; i++) { // printf("hs[%d] = %d(%c)\n", i, (int)hs[i], hs[i] < 32 ? 'X' : hs[i]); } } if (cur_hs == hs_len) { // printf("adding char %d(%c) at hs[%d]\n", (int)c, c < 32 ? 'X' : c, hs_len); hs[hs_len] = c; hs_len++; s++; } // printf("testing %d at cur_hs %d against %d at cur_needle %d\n", // (int)hs[cur_hs], cur_hs, (int)needle[cur_needle], cur_needle); if (hs[cur_hs] == needle[cur_needle]) { if (cur_needle+1 == needle_len) { int exitcode = EXIT_SUCCESS; // printf("\nFound needle from --find option.\n"); if (exitonfind) { int ret; // printf("scanf (s=%d)'%s'\n", s, &str[s+1]); ret = sscanf(&str[s+1], "%i", &exitcode); // printf("ret %d, '%s'\n", ret, &str[s+1]); } printf("Exiting with code %d\n", exitcode); exit(exitcode); } cur_needle++; cur_hs++; } else { // printf("no match, shifting hs.\n"); { int i; for(i=0; i!= hs_len-1; i++) { hs[i] = hs[i+1]; } } hs_len--; cur_needle = 0; cur_hs = 0; } } } } /**************************************************************************** *# *# FUNCTION NAME: Fopen *# *# PARAMETERS: Name and mode, both strings. *# *# DESCRIPTION: Opens a file and returns its fd, or NULL. *# *#--------------------------------------------------------------------------- *# HISTORY *# *# DATE NAME CHANGES *# ---- ---- ------- *# 961022 ronny Initial version *# *#***************************************************************************/ FILE * Fopen(const char *name, const char *mode) { FILE *fd; if (db2) printf(">>> Fopen '%s', mode '%s'\n", name, mode); #if defined(_WIN32) fd = _fsopen(name, mode, _SH_DENYNO); #else fd = fopen(name, mode); #endif if (fd == NULL) { printf("<<< Fopen failed on '%s', mode '%s'\n", name, mode); return ((FILE*) NULL); } if (strncmp(mode, "a", 1) == 0) { if (db3) printf("* Append mode, seeking to end.\n"); fseek(fd, 0L, SEEK_SET); } if (db2) printf("<<< Fopen: '%s'\n", name); return(fd); } /**************************************************************************** *# *# FUNCTION NAME: ParseArgs *# *# PARAMETERS: Standard command line args. *# *# DESCRIPTION: Parses command line arguments. *# *#--------------------------------------------------------------------------- *# HISTORY *# *# DATE NAME CHANGES *# ---- ---- ------- *# 960909 ronny Initial version *#***************************************************************************/ void ParseArgs (int argc, const char *argv[]) { int argi; int i; int printHelp = FALSE; int exitCode = EXIT_SUCCESS; char dbStr[MAX_STRING_LEN]; /* Debug option string. */ int number; int argCount; const char **argVect; struct stat st; if (db4) printf(">>> ParseArgs\n"); argCount = argc; argVect = argv; for (argi = 1; argi < argCount; argi++) { if (db4) printf("argv[%d] = '%s'\n", argi, argVect[argi]); if (strncmp(argVect[argi], "--from", 6) == 0) { if (GetStringOption(&argi, argCount, argVect, host1, "--from") == 0) { printHelp = TRUE; exitCode = EXIT_FAILURE; } else { printf("Host: %s %s\n", host1, host2); if (sscanf(host1, "%x-%x-%x-%x-%x-%x", &i, &i, &i, &i, &i, &i) == 6) { printf("Ethernet address\n"); } } } else if (strncmp(argVect[argi], "--device", 8) == 0) { if (GetStringOption(&argi, argCount, argVect, device, "--device") == 0) { printHelp = TRUE; exitCode = EXIT_FAILURE; } } else if (strncmp(argVect[argi], "--network", 9) == 0) { netBoot = TRUE; serBoot = FALSE; strcpy(device, "eth0"); strcpy(boot_loader_file, INTERNAL_NW); } else if (strncmp(argVect[argi], "--serial", 8) == 0) { serBoot = TRUE; netBoot = FALSE; strcpy(device, "/dev/ttyS0"); strcpy(boot_loader_file, INTERNAL_SER); } else if (strncmp(argVect[argi], "--noleds", 8) == 0) { noleds = TRUE; } else if (strncmp(argVect[argi], "--images", 8) == 0) { int i = 0; printf("Internal images:\n"); while(boot_image_info[i].name) { printf("'%s', %s, size %lu bytes.\n", boot_image_info[i].name, boot_image_info[i].info, boot_image_info[i].len ); i++; } exit(EXIT_SUCCESS); } else if (strncmp(argv[argi], "--baudrate", 10) == 0) { if (GetNumberOption (&argi, argCount, argVect, &set_baudrate, "--baudrate", 10) == 0) { printHelp = TRUE; exitCode = EXIT_FAILURE; } } else if (strncmp(argVect[argi], "--tofiles", 9) == 0) { toFiles = TRUE; } else if (strncmp(argVect[argi], "--cmdsonly", 10) == 0) { cmdsOnly = TRUE; } else if (strncmp(argVect[argi], "--to", 4) == 0) { if ((GetStringOption(&argi, argCount, argVect, host2, "--to") == 0)) { printHelp = TRUE; exitCode = EXIT_FAILURE; } else { printf("Host: %s %s\n", host1, host2); both_addresses = TRUE; if (sscanf(host2, "%x-%x-%x-%x-%x-%x", &i, &i, &i, &i, &i, &i) == 6) { printf("Ethernet address\n"); } } } else if (strncmp(argVect[argi], "--printp", 8) == 0) { pPacket = 1; } else if (strncmp(argVect[argi], "--printascii", 11) == 0) { pPacket = 1; printPacketType = ASCII; } else if (strncmp(argVect[argi], "--printudec", 11) == 0) { pPacket = 1; printPacketType = UDEC; } else if (strncmp(argVect[argi], "--printhex", 10) == 0) { pPacket = 1; printPacketType = HEX; } else if (strncmp(argVect[argi], "--bpl", 5) == 0) { if (GetNumberOption(&argi, argCount, argVect, &p_packet_bpl, "--bpl", 10) == 0) { printHelp = TRUE; exitCode = EXIT_FAILURE; } } else if (strncmp(argVect[argi], "--promisc", 11) == 0) { promisc = 1; } else if (strncmp(argVect[argi], "--5400", 6) == 0) { boot_cmds[boot_cmds_cnt++] = SET_REGISTER; boot_cmds[boot_cmds_cnt++] = 0xb0000000; boot_cmds[boot_cmds_cnt++] = 0x000095b6; boot_cmds[boot_cmds_cnt++] = SET_REGISTER; boot_cmds[boot_cmds_cnt++] = 0xb0000008; boot_cmds[boot_cmds_cnt++] = 0x0000e751; boot_cmds[boot_cmds_cnt++] = SET_REGISTER; boot_cmds[boot_cmds_cnt++] = 0xb000000c; boot_cmds[boot_cmds_cnt++] = 0x12604040; } else if (strncmp(argVect[argi], "--5600", 6) == 0) { boot_cmds[boot_cmds_cnt++] = SET_REGISTER; boot_cmds[boot_cmds_cnt++] = 0xb0000000; boot_cmds[boot_cmds_cnt++] = 0x000095b6; boot_cmds[boot_cmds_cnt++] = SET_REGISTER; boot_cmds[boot_cmds_cnt++] = 0xb0000008; boot_cmds[boot_cmds_cnt++] = 0x00006751; boot_cmds[boot_cmds_cnt++] = SET_REGISTER; boot_cmds[boot_cmds_cnt++] = 0xb000000c; boot_cmds[boot_cmds_cnt++] = 0x12204040; } else if (strncmp(argVect[argi], "--testcardlx", 12) == 0) { boot_cmds[boot_cmds_cnt++] = SET_REGISTER; boot_cmds[boot_cmds_cnt++] = (unsigned int)R_DRAM_CONFIG; boot_cmds[boot_cmds_cnt++] = 0x12604040; boot_cmds[boot_cmds_cnt++] = SET_REGISTER; boot_cmds[boot_cmds_cnt++] = (unsigned int)R_DRAM_TIMING; boot_cmds[boot_cmds_cnt++] = 0x0000e751; boot_cmds[boot_cmds_cnt++] = SET_REGISTER; boot_cmds[boot_cmds_cnt++] = (unsigned int)R_WAITSTATES; boot_cmds[boot_cmds_cnt++] = 0x00b395b5; boot_cmds[boot_cmds_cnt++] = SET_REGISTER; boot_cmds[boot_cmds_cnt++] = (unsigned int)R_BUS_CONFIG; boot_cmds[boot_cmds_cnt++] = 0x00000207; } else if (strncmp(argVect[argi], "--testcard", 10) == 0) { boot_cmds[boot_cmds_cnt++] = SET_REGISTER; boot_cmds[boot_cmds_cnt++] = (unsigned int)R_WAITSTATES; boot_cmds[boot_cmds_cnt++] = 0x000010b3; boot_cmds[boot_cmds_cnt++] = SET_REGISTER; boot_cmds[boot_cmds_cnt++] = (unsigned int)R_DRAM_TIMING; boot_cmds[boot_cmds_cnt++] = 0x00006543; boot_cmds[boot_cmds_cnt++] = SET_REGISTER; boot_cmds[boot_cmds_cnt++] = (unsigned int)R_DRAM_CONFIG; boot_cmds[boot_cmds_cnt++] = 0x12966060; } else if (strncmp(argVect[argi], "--devboard", 10) == 0) { /* Printing on serial port will not work until PORT_PB is set... */ boot_cmds[boot_cmds_cnt++] = SET_REGISTER; boot_cmds[boot_cmds_cnt++] = (unsigned int)R_PORT_PB_SET; boot_cmds[boot_cmds_cnt++] = 0x01001ef3; boot_cmds[boot_cmds_cnt++] = SET_REGISTER; boot_cmds[boot_cmds_cnt++] = (unsigned int)R_PORT_PA_SET; boot_cmds[boot_cmds_cnt++] = 0x00001df0; boot_cmds[boot_cmds_cnt++] = SET_REGISTER; boot_cmds[boot_cmds_cnt++] = (unsigned int)R_WAITSTATES; boot_cmds[boot_cmds_cnt++] = 0x000095a6; boot_cmds[boot_cmds_cnt++] = SET_REGISTER; boot_cmds[boot_cmds_cnt++] = (unsigned int)R_DRAM_CONFIG; boot_cmds[boot_cmds_cnt++] = 0x1a200040; boot_cmds[boot_cmds_cnt++] = SET_REGISTER; boot_cmds[boot_cmds_cnt++] = (unsigned int)R_DRAM_TIMING; boot_cmds[boot_cmds_cnt++] = 0x00005611; boot_cmds[boot_cmds_cnt++] = SET_REGISTER; boot_cmds[boot_cmds_cnt++] = (unsigned int)R_BUS_CONFIG; boot_cmds[boot_cmds_cnt++] = 0x00000104; } else if (strncmp(argVect[argi], "--verify", 8) == 0) { boot_cmds[boot_cmds_cnt++] = MEM_VERIFY; GetNumberOption(&argi, argCount, argVect, &boot_cmds[boot_cmds_cnt++], "--verify", 16); GetNumberOption(&argi, argCount, argVect, &boot_cmds[boot_cmds_cnt++], "--verify", 16); } else if (strncmp(argVect[argi], "--setreg", 8) == 0) { boot_cmds[boot_cmds_cnt++] = SET_REGISTER; if ((argVect[argi+1][0] >= 'A') && (argVect[argi+1][0] <= 'Z')) { GetRegisterOption(&argi, argCount, argVect, &boot_cmds[boot_cmds_cnt++], "--setreg", 16); } else { GetNumberOption(&argi, argCount, argVect, &boot_cmds[boot_cmds_cnt++], "--setreg", 16); } GetNumberOption(&argi, argCount, argVect, &boot_cmds[boot_cmds_cnt++], "--setreg", 16); } else if (strncmp(argVect[argi], "--getreg", 8) == 0) { boot_cmds[boot_cmds_cnt++] = GET_REGISTER; if ((argVect[argi+1][0] >= 'A') && (argVect[argi+1][0] <= 'Z')) { GetRegisterOption(&argi, argCount, argVect, &boot_cmds[boot_cmds_cnt++], "--getreg", 16); } else { GetNumberOption(&argi, argCount, argVect, &boot_cmds[boot_cmds_cnt++], "--getreg", 16); } } else if (strncmp(argVect[argi], "--pause", 7) == 0) { boot_cmds[boot_cmds_cnt++] = PAUSE_LOOP; GetNumberOption(&argi, argCount, argVect, &boot_cmds[boot_cmds_cnt++], "--pause", 16); } else if (strncmp(argVect[argi], "--memtest", 9) == 0) { boot_cmds[boot_cmds_cnt++] = MEM_TEST; GetNumberOption(&argi, argCount, argVect, &boot_cmds[boot_cmds_cnt++], "--memtest", 16); GetNumberOption(&argi, argCount, argVect, &boot_cmds[boot_cmds_cnt++], "--memtest", 16); } else if (strncmp(argVect[argi], "--loop", 6) == 0) { char str[MAX_STRING_LEN]; boot_cmds[boot_cmds_cnt++] = LOOP; GetNumberOption(&argi, argCount, argVect, &boot_cmds[boot_cmds_cnt++], "--loop", 16); GetStringOption(&argi, argCount, argVect, str, argVect[argi]); new_label(&loop_label, boot_cmds_cnt+1, str); boot_cmds_cnt++; } else if (strncmp(argVect[argi], "--label", 7) == 0) { char str[MAX_STRING_LEN]; GetStringOption(&argi, argCount, argVect, str, "--label"); new_label(&label, boot_cmds_cnt, str); } else if (strncmp(argVect[argi], "--memdump", 9) == 0) { boot_cmds[boot_cmds_cnt++] = MEM_DUMP; GetNumberOption(&argi, argCount, argVect, &boot_cmds[boot_cmds_cnt++], "--memdump", 16); GetNumberOption(&argi, argCount, argVect, &boot_cmds[boot_cmds_cnt++], "--memdump", 16); } else if (strncmp(argVect[argi], "--memclear", 10) == 0) { boot_cmds[boot_cmds_cnt++] = MEM_CLEAR; GetNumberOption(&argi, argCount, argVect, &boot_cmds[boot_cmds_cnt++], "--memclear", 16); GetNumberOption(&argi, argCount, argVect, &boot_cmds[boot_cmds_cnt++], "--memclear", 16); } else if (strncmp(argVect[argi], "--flash", 7) == 0) { boot_cmds[boot_cmds_cnt++] = FLASH; GetNumberOption(&argi, argCount, argVect, &boot_cmds[boot_cmds_cnt++], "--flash", 16); GetNumberOption(&argi, argCount, argVect, &boot_cmds[boot_cmds_cnt++], "--flash", 16); GetNumberOption(&argi, argCount, argVect, &boot_cmds[boot_cmds_cnt++], "--flash", 16); doing_flash = TRUE; } else if (strncmp(argVect[argi], "--jump", 6) == 0) { boot_cmds[boot_cmds_cnt++] = JUMP; GetNumberOption(&argi, argCount, argVect, &boot_cmds[boot_cmds_cnt++], "--jump", 16); } else if (strncmp(argVect[argi], "--file", 6) == 0) { char str[MAX_STRING_LEN]; boot_cmds[boot_cmds_cnt++] = PACKET_INFO; GetStringOption(&argi, argCount, argVect, str, "--file"); /* file name */ GetNumberOption(&argi, argCount, argVect, &boot_cmds[boot_cmds_cnt++], str, 16); /* address */ last_boot_file = allocate_boot_file(last_boot_file); first_boot_file = first_boot_file ? first_boot_file : last_boot_file; last_boot_file->fileName = malloc(strlen(str) + 1); strcpy(last_boot_file->fileName, str); last_boot_file->size_p = &boot_cmds[boot_cmds_cnt]; last_boot_file->size_sent = 0; if (strncmp(str, "-", 1) != 0) { if (stat(last_boot_file->fileName, &st) == -1) { printf("Cannot get size of file '%s'. %s.\n", last_boot_file->fileName, strerror(errno)); exit(EXIT_FAILURE); } if (db2) printf("* size is %d 0x%8.8x\n", (int)st.st_size, (unsigned int)st.st_size); last_boot_file->size = st.st_size; boot_cmds[boot_cmds_cnt++] = st.st_size; } else { GetNumberOption(&argi, argCount, argVect, &last_boot_file->size , str, 16); /* size */ boot_cmds[boot_cmds_cnt++] = last_boot_file->size; printf("* size is %d 0x%8.8x\n", last_boot_file->size, last_boot_file->size); } } else if (strncmp(argVect[argi], "--bootfile", 10) == 0) { GetStringOption(&argi, argCount, argVect, boot_loader_file, "--bootfile"); } else if (strncmp(argVect[argi], "-d", 2) == 0) { if (GetNumberOption (&argi, argCount, argVect, &number, "-d", 10) == 0) { printHelp = TRUE; exitCode = EXIT_FAILURE; } else { sprintf(dbStr, "%d", number); for (i = 0; i != (int) strlen(dbStr); i++) { switch (dbStr[i] - '0') { case 1: db1 = TRUE; break; case 2: db2 = TRUE; break; case 3: db3 = TRUE; break; case 4: db4 = TRUE; break; default: printf("ERROR! Debug level %d is not defined.\n", dbStr[i] - '0'); printHelp = TRUE; exitCode = EXIT_FAILURE; break; } } } } else if (strncmp(argVect[argi], "--find", 6) == 0) { GetStringOption(&argi, argCount, argVect, needle, "--find"); /* convert control characters like /n to the real ascii valure */ { int i; int j = 0; char c; int esc = 0; for (i = 0; (c = needle[i]); i++,j++) { // printf("c = %d, i %d, j %d\n", (int)c, i, j); if (c == '\\') { // printf("esc\n"); esc = 1; continue; } else if (esc) { esc = 0; switch(c) { case 'r': c = '\r'; break; case 'n': c = '\n'; break; case '\\': c = '\\'; break; default: printf("Uknown escape sequence '\\%c'\n", c); exit(EXIT_FAILURE); } j--; } // printf("setting j %d to %d\n", j, (int)c); needle[j] = c; } needle_len = j; } for (i = 0; needle[i]; i++) { //printf("i = %d, c %d\n", i,(int)needle[i]); } } else if (strncmp(argVect[argi], "--exitonfind", 12) == 0) { exitonfind = TRUE; } else if (strncmp(argVect[argi], "--help", 6) == 0) { printHelp = TRUE; } else { printf("ERROR! Don't understand option '%s'\n", argVect[argi]); printHelp = TRUE; exitCode = EXIT_FAILURE; } } if (printHelp == TRUE) { PrintHelp(); exit(exitCode); } if (noleds) { strcpy(&boot_loader_file[strlen(boot_loader_file)], "_NOLEDS"); } handle_labels(); } /**************************************************************************** *# *# FUNCTION NAME: handle_labels *# *# PARAMETERS: global loop_label, label *# *# DESCRIPTION: Checks and matches labels from --loop and --label commands *# and inserts the resolved addresses into boot commands. *# *#--------------------------------------------------------------------------- *# HISTORY *# *# DATE NAME CHANGES *# ---- ---- ------- *# 20020204 ronny Initial version *# *#***************************************************************************/ void handle_labels(void) { struct label_t *ll = loop_label; struct label_t *l = label; struct label_t *last_l = l; while(ll) { int match = 0; l = last_l; while(l) { match = 0; if (l->name && ll->name && (strcmp(l->name, ll->name) == 0)) { match = 1; boot_cmds[ll->addr] = IO_BUF_START+(l->addr*4); break; } l = l->prev; } if (!match) { printf("Error. No label '%s' defined as needed by --loop command.\n", ll->name); exit(EXIT_FAILURE); } ll = ll->prev; } } /**************************************************************************** *# *# FUNCTION NAME: new_label *# *# PARAMETERS: *# *# DESCRIPTION: *# *#--------------------------------------------------------------------------- *# HISTORY *# *# DATE NAME CHANGES *# ---- ---- ------- *# 20020201 ronny Initial version *# *#***************************************************************************/ void new_label(struct label_t **label, udword addr, const char *name) { struct label_t *new_p; new_p = malloc(sizeof(struct label_t)); if (*label == NULL) { /* first one? */ *label = new_p; new_p->prev = NULL; } else { new_p->prev = *label; } *label = new_p; new_p->addr = boot_cmds_cnt; new_p->name = malloc(strlen(name)); strcpy(new_p->name, name); } /**************************************************************************** *# *# FUNCTION NAME: GetStringOption *# *# PARAMETERS: int *argNr : Returns next argc here. *# int argCount : Index of last argument. *# char *argVect[] : argv. *# char *ret : Copy string here. *# char *option : Name of the option. *# *# DESCRIPTION: Extracts a string option from argv, and updates argnr. *# Returns TRUE/FALSE and string in *ret. *# *#--------------------------------------------------------------------------- *# HISTORY *# *# DATE NAME CHANGES *# ---- ---- ------- *# 960930 ronny Initial version *# 961203 ronny Handles filenames with spaces within 'file name'. *# *#***************************************************************************/ int GetStringOption(int *argNr, int argCount, const char *argVect[], char *ret, const char *option) { int startChar = strlen(option); *ret = '\0'; /* Are there any more chars after option? If not skip to next argv. */ if (strlen(argVect[*argNr]) <= (unsigned int)startChar) { (*argNr)++; startChar = 0; } /* Any args left? */ if (*argNr >= argCount) { printf("ERROR! The option '%s' needs a string argument.\n", option); PrintHelp(); exit(EXIT_FAILURE); } /* avoid stack overflow hacks */ if (strlen(&argVect[*argNr][startChar]) > MAX_STRING_LEN) { printf("Argument '%s' longer than maximum allowable %d characters.\n", &argVect[*argNr][startChar], MAX_STRING_LEN); exit(EXIT_FAILURE); } strcpy(ret, &argVect[*argNr][startChar]); if (db4) printf("<<< GetStringOption '%s'\n", ret); return TRUE; } /**************************************************************************** *# *# FUNCTION NAME: GetNumberOption *# *# PARAMETERS: *# *# DESCRIPTION: *# *#--------------------------------------------------------------------------- *# HISTORY *# *# DATE NAME CHANGES *# ---- ---- ------- *# 960930 ronny Initial version *# *#***************************************************************************/ int GetNumberOption(int *argNr, int argCount, const char *argVect[], unsigned int *ret, const char *option, int base) { int startChar = 0; int add_io_base = 0; (*argNr)++; if (*argNr >= argCount) { printf("ERROR! The option '%s' needs a number argument.\n", option); PrintHelp(); exit(EXIT_FAILURE); } if (argVect[*argNr][startChar] == '+') { add_io_base = 1; startChar++; } *ret = strtoul(&argVect[*argNr][startChar], NULL, base); if (add_io_base) { *ret += IO_BUF_START; if (*ret < IO_BUF_START || *ret >= IO_BUF_END) { printf("ERROR! '%s' is outside the IO buffer (option '%s').\n", argVect[*argNr], option); exit(EXIT_FAILURE); } } if (db4) printf("<<< GetNumberOption %08x\r\n", *ret); return TRUE; } /**************************************************************************** *# *# FUNCTION NAME: GetRegisterOption *# *# PARAMETERS: *# *# DESCRIPTION: *# *#--------------------------------------------------------------------------- *# HISTORY *# *# DATE NAME CHANGES *# ---- ---- ------- *# 960930 ronny Initial version *# *#***************************************************************************/ int GetRegisterOption(int *argNr, int argCount, const char *argVect[], unsigned int *ret, const char *option, int base) { int startChar = 0; (*argNr)++; if (*argNr >= argCount) { printf("Error! The option '%s' needs a register name.\n", option); PrintHelp(); exit(EXIT_FAILURE); } { int r = 0; while (reg_des[r].name) { if (strcmp(reg_des[r].name, argVect[*argNr]) == 0) { *ret = reg_des[r].addr; return TRUE; break; } r++; } } printf("Error! Didn't find a register name matching '%s'.\n", argVect[*argNr]); exit(EXIT_FAILURE); return FALSE; } /**************************************************************************** *# *# FUNCTION NAME: PrintHelp *# *# PARAMETERS: None. *# *# DESCRIPTION: Prints help info. *# *#--------------------------------------------------------------------------- *# DATE NAME CHANGES *# ---- ---- ------- *# 960909 ronny Initial version *# *#***************************************************************************/ void PrintHelp(void) { printf("e100boot version %s.\n", version); printf("\ne100boot [--device devicename] [--file filename|- addr [size]]\n" " [--flash ram-source flash-offset size]\n" " [--pause iter]\n" " [--memtest addr addr]\n" " [--memclear addr addr] [--memdump addr addr]\n" " [--setreg addr|regname val] [--getreg addr|regname]\n" " [--verify addr val] [--label label] [--loop addr label]\n" " [--5400] [--5600] [--testcard] [--devboard]\n" " [--testcardlx] [--network] [--serial]\n" " [--baudrate baudrate] [--bootfile file] [--jump addr]\n" " [--tofiles] [--cmdsonly] [--images] [--noleds]\n" " [--help]\n\n"); printf(" The commands sent to the cbl, and which are parsed by the cbl,\n" " are stored at 0x%8.8x-0x%8.8x.\n\n", IO_BUF_START, IO_BUF_END); printf(" See the man page for more details about e100boot.\n\n"); } /**************************************************************************** *# *# FUNCTION NAME: CreateBootLoader *# *# PARAMETERS: None. *# *# DESCRIPTION: Creates boot packets from boot file or internal loader. *# *#--------------------------------------------------------------------------- *# DATE NAME CHANGES *# ---- ---- ------- *# 960909 ronny Initial version *#***************************************************************************/ void CreateBootLoader(void) { struct stat st; char *buf = NULL; // int size_pos = 0x18; // int addr_pos = 0x28; struct packet_header_T *ph; int packet_size; int header_size; int buf_cnt = 0; int i; udword sum = 0; if (create_boot_loader) { int image_nbr = 0; int found = 0; const struct boot_image_info_type *info; if (db4) printf("> CreateBootLoader\n"); info = &boot_image_info[image_nbr]; /* Use internal boot loader? */ while (!found && info->name != NULL) { if (strcmp(boot_loader_file, info->name) == 0) { st.st_size = info->len; buf = (char*) malloc(st.st_size); memcpy(buf, info->ptr, st.st_size); /* unnecessary? */ found = TRUE; printf("Using internal boot loader: %s - %s.\n", info->name, info->info); } else { image_nbr++; info = &boot_image_info[image_nbr]; } } /* No internal? Load it from file instead. */ if (!found) { FILE *fd; /* We didn't find an internal match, load the boot file from disk. */ if ((fd = Fopen(boot_loader_file, "r")) == NULL) { printf("Cannot open bootloader '%s'. %s.\n", boot_loader_file, strerror(errno)); exit(EXIT_FAILURE); } if (fstat(fileno(fd), &st) == -1) { printf("Cannot get filestatus of bootloader '%s'. %s.\n", boot_loader_file, strerror(errno)); exit(EXIT_FAILURE); } buf = (char*) malloc(st.st_size); // printf("CreateBootLoader: buf = (char*) malloc(st.st_size); 2\n"); if (read(fileno(fd), buf, st.st_size) != st.st_size) { printf("Read fewer bytes than there should be in %s.\n", boot_loader_file); exit(EXIT_FAILURE); } fclose(fd); } /* Alright, got loader in buf[] and size in st. */ if (netBoot) { /* The etrax code for all boot methods are linked to adress 380000f0 but since network boot starts execution at 380000f4 we have two nops in the beginning of the code which we do not transmit to etrax in the network case. The link adress doesn't change though. */ buf += 4; st.st_size -= 4; packet_size = DATA_SIZE; } else { packet_size = st.st_size; } /* Hack binary, insert size and address. */ /* Giovanni Varasano (24/06/2005) : bug * It is not a good habit to make code endian dependent on the host * processor where cross compilation happens. Intel is little endian and * PowerPC is big endian, but the target (ETRAX) is always little endian. * The use of swap_endian() solves the problem. */ #define SIZE_PATTERN 0x12345678 #define ADDR_PATTERN 0x87654321 #define SIZE_POS (netBoot ? 0x0c : 0x10) #define ADDR_POS (netBoot ? 0x10 : 0x14) if (swap_endian(*(udword*)&buf[SIZE_POS]) != SIZE_PATTERN) { printf("Bootloader corrupt. Should contain ret/nop (0x%8.8x) at 0x%x, but contains %x\n", SIZE_PATTERN, SIZE_POS, *(udword*)&buf[SIZE_POS]); exit(EXIT_FAILURE); } /* How much data to load except data in first packet. */ if (netBoot) { *(udword*)(&buf[SIZE_POS]) = swap_endian(st.st_size - DATA_SIZE); } else { *(udword*)(&buf[SIZE_POS]) = swap_endian(st.st_size - 784); } if (db3) printf("Inserting boot size 0x%x at 0x%x.\n", (unsigned int) *(udword*)(&buf[SIZE_POS]), (unsigned int)&buf[SIZE_POS]); if (swap_endian(*(udword*)&buf[ADDR_POS]) != ADDR_PATTERN) { printf("Bootloader corrupt. Should contain ret/nop (0x%8.8x) at 0x%x, but contains %x\n", ADDR_PATTERN, ADDR_POS, *(udword*)&buf[ADDR_POS]); exit(EXIT_FAILURE); } if (netBoot) { *(udword*)(&buf[ADDR_POS]) = swap_endian(BOOT_ADDRESS + DATA_SIZE); } else { *(udword*)(&buf[ADDR_POS]) = swap_endian(BOOT_ADDRESS-4 + 784); } if (db3) printf("Inserting boot address 0x%x at 0x%x.\n", (unsigned int)*(udword*)(&buf[ADDR_POS]), (unsigned int)&buf[ADDR_POS]); for (i = 0; i != st.st_size; i++) { sum += ((byte*)buf)[i]; } if (db1) printf("Checksum 0x%x, bytes %d\n", sum, i); if (db4) { int i; for(i=0; isize = packet_size; last_packet->data = (char*)malloc(packet_size); last_packet->seq = seq_nr; last_packet->baud_rate = 9600; last_packet->boot_file = allocate_boot_file(NULL); last_packet->boot_file->fileName = boot_loader_file; // printf("last_packet->size %8.8x\n", last_packet->size); // printf("last_packet->data %8.8x\n",last_packet->data); if (netBoot) { ph = (struct packet_header_T*) last_packet->data; memcpy(ph->dest, dst_addr_of_device, 6); memcpy(ph->src, eth_addr_local, 6); ph->length = htons(packet_size); ph->snap1 = htonl(SNAP1); ph->snap2 = htonl(SNAP2); ph->tag = htonl(SERVER_TAG); ph->seq = htonl(seq_nr); if (seq_nr != 0) { ph->type = htonl(BOOT_PACKET); ph->id = htonl(0); } } memcpy(&last_packet->data[header_size], &buf[buf_cnt], packet_size - header_size); if (db3) DecodeSvintoBoot(last_packet->data); if (netBoot) { buf_cnt += DATA_SIZE; } else { buf_cnt += packet_size +1; } seq_nr++; } } if (db4) printf("< CreateBootLoader\n"); } /**************************************************************************** *# *# FUNCTION NAME: allocate_packet *# *# PARAMETERS: None. *# *# DESCRIPTION: *# *#--------------------------------------------------------------------------- *# DATE NAME CHANGES *# ---- ---- ------- *# 960909 ronny Initial version *#***************************************************************************/ struct packet_buf* allocate_packet(struct packet_buf *p) { if (db4) printf("> allocate_packet\n"); if (p) { p->next = (struct packet_buf*) malloc(sizeof(struct packet_buf)); p = p->next; } else { p = (struct packet_buf*) malloc(sizeof(struct packet_buf)); } p->next = NULL; return(p); } /**************************************************************************** *# *# FUNCTION NAME: allocate_boot_file *# *# PARAMETERS: None. *# *# DESCRIPTION: *# *#--------------------------------------------------------------------------- *# DATE NAME CHANGES *# ---- ---- ------- *# 960909 ronny Initial version *#***************************************************************************/ struct boot_files_T* allocate_boot_file(struct boot_files_T *bf) { if (bf) { bf->next = (struct boot_files_T*) malloc(sizeof(struct boot_files_T)); bf = bf->next; } else { bf = (struct boot_files_T*) malloc(sizeof(struct boot_files_T)); } bf->next = NULL; return(bf); } /**************************************************************************** *# *# FUNCTION NAME: CreateBootCmds *# *# PARAMETERS: None. *# *# DESCRIPTION: Creates a boot packet from the boot commands. The data is *# filled in later by FinishBootCmds(). *# *#--------------------------------------------------------------------------- *# DATE NAME CHANGES *# ---- ---- ------- *# 980818 ronny Initial version *#***************************************************************************/ void CreateBootCmds(void) { struct packet_header_T *ph; if (db4) printf("***> CreateBootCmds\n"); last_packet = allocate_packet(last_packet); boot_cmds_packet = last_packet; last_packet->boot_file = allocate_boot_file(NULL); last_packet->boot_file->fileName = BOOT_CMDS_FILE; last_packet->baud_rate = 9600; last_packet->size = netBoot ? SIZE_OF_BOOT_CMDS + sizeof(struct packet_header_T) : SIZE_OF_BOOT_CMDS; last_packet->data = (char *) malloc(last_packet->size); last_packet->seq = seq_nr; if (netBoot) { /* Create packet header. */ ph = (struct packet_header_T *) last_packet->data; memcpy(ph->dest, dst_addr_of_device, 6); memcpy(ph->src, eth_addr_local, 6); ph->length = htons(last_packet->size); ph->snap1 = htonl(SNAP1); ph->snap2 = htonl(SNAP2); ph->tag = htonl(SERVER_TAG); ph->seq = htonl(seq_nr); seq_nr++; ph->type = htonl(BOOT_CMDS); ph->id = htonl(0); } if (db3) DecodeSvintoBoot(last_packet->data); if (db4) printf("<*** CreateBootCmds\n"); } /**************************************************************************** *# *# FUNCTION NAME: FinishBootCmds *# *# PARAMETERS: None. *# *# DESCRIPTION: Copies the boot commands into the correct packet and changes *# the dwords to network order. *# *#--------------------------------------------------------------------------- *# DATE NAME CHANGES *# ---- ---- ------- *# 960909 ronny Initial version *#***************************************************************************/ void FinishBootCmds(void) { int i; unsigned int offset = 0; for (i = 0; i != boot_cmds_cnt; i++) { boot_cmds[i] = htonl(boot_cmds[i]); if (db3) printf("%8.8x\n", boot_cmds[i]); } /* Copy boot commands into packet. */ if (netBoot) { offset = sizeof(struct packet_header_T); } memcpy(&boot_cmds_packet->data[offset], boot_cmds, boot_cmds_cnt * sizeof(udword)); } /**************************************************************************** *# *# FUNCTION NAME: CreateNewBootPacket *# *# PARAMETERS: None. *# *# DESCRIPTION: Creates next packet for the files specified by '--file'. *# *# RETURNS: Next packet, or NULL. *# *#--------------------------------------------------------------------------- *# DATE NAME CHANGES *# ---- ---- ------- *# 960909 ronny Initial version *#***************************************************************************/ struct packet_buf* CreateNewBootPacket(void) { static char buf[DATA_SIZE]; struct packet_header_T *ph; int packet_size; int header_size; int i; udword sum; int size = 0; int padding = 0; static struct boot_files_T *bf = NULL; if (db3) printf("> CreateNewBootPacket\n"); bf = bf ? bf : first_boot_file; while (bf) { if (!bf->fd) { if (strcmp(bf->fileName, "-") == 0) { bf->fd = stdin; } else { bf->fd = fopen(bf->fileName, "r"); } if (bf->fd == NULL) { printf("Cannot open boot file %s. Exiting\n", bf->fileName); exit(EXIT_FAILURE); } if (db3) printf("Opening boot file %s\n", bf->fileName); } if (!padding) { size = fread(buf, 1, DATA_SIZE, bf->fd); if (size == 0) { if (db3) printf("Nothing more to read. Read: %d/%d\n", bf->size_sent, bf->size); padding = 1; } } if (padding) { if (bf->size_sent < bf->size) { if (db3) printf("padding...\n"); size = (bf->size - bf->size_sent > DATA_SIZE) ? DATA_SIZE : bf->size - bf->size_sent; memset(buf, 0, size); } else { if (db3) printf("All written\n"); padding = 0; size = 0; } } if (size != 0) { if (db3) printf("size: %d %d/%d\n", size, bf->size_sent, bf->size); bf->size_sent += size; last_packet = allocate_packet(last_packet); /* Calculate checksum. */ sum = 0; for (i = 0; i != size; i++) { sum += ((byte*)buf)[i]; } if (db2) printf("Checksum 0x%x, bytes %d\n", sum, i); /* Figure out size of packet. */ if (netBoot) { header_size = seq_nr == 0 ? SIZE_OF_FIRST_HEADER : sizeof(struct packet_header_T); packet_size = ((size) < DATA_SIZE ? size : DATA_SIZE) + header_size; } else { header_size = 0; packet_size = size; } if (packet_size < 60) { /* CRC adds 4 bytes to 64 */ printf( "Last packet from file '%s', is smaller than 64 bytes. \n" "This is not allowed in the Ethernet standard. Will pad with %d " "bytes.\n", bf->fileName, 60-packet_size); *(bf->size_p) += 60-packet_size; packet_size = 60; } last_packet->size = packet_size; last_packet->data = (char*)malloc(packet_size); last_packet->boot_file = bf; last_packet->baud_rate = set_baudrate; /* printf("size %8.8x\n", last_packet->size);*/ /* printf("data %8.8x\n",last_packet->data);*/ if (netBoot) { /* Initialize ethernet header. */ ph = (struct packet_header_T*) last_packet->data; memcpy(ph->dest, dst_addr_of_device, 6); memcpy(ph->src, eth_addr_local, 6); /* printf("packet_size %d\n", packet_size);*/ ph->length = htons(packet_size); ph->snap1 = htonl(SNAP1); ph->snap2 = htonl(SNAP2); ph->tag = htonl(SERVER_TAG); ph->seq = htonl(seq_nr); last_packet->seq = seq_nr; if (seq_nr != 0) { ph->type = htonl(BOOT_PACKET); ph->id = htonl(0); /* id doesn't matter, we send to a unicast address */ } } /* Copy data in place. */ memcpy(&last_packet->data[header_size], buf, packet_size - header_size); if (db2) DecodeSvintoBoot(last_packet->data); /* PrintPacket(last_packet->data, last_packet->size, HEX);*/ seq_nr++; if (db3) printf("< CreateNewBootPacket\n"); return(last_packet); } else { /* Nothing read from fd. */ fclose(bf->fd); bf = bf->next; } } if (db3) printf("< CreateNewBootPacket\n"); return(NULL); } /**************************************************************************** *# *# FUNCTION NAME: swap_endian *# *# PARAMETERS: u - An unsigned value. *# *# DESCRIPTION: Convert the unsigned value from host order to little endian. *# *# RETURNS: The unsigned value as little endian. *# *#***************************************************************************/ unsigned int swap_endian(unsigned int u) { /* If the host order is the same as the network order (which is big endian), * we need to swap the bytes in the supplied value. */ return ntohl(0x12345678) == 0x12345678 ? bswap_32(u) : u; } /****************** END OF FILE common.c ************************************/