/****************************************************************************** * * Filename: loader_prompt.c * * Instantiation of the interactive loader functions. * * Revision information: * * 20AUG2004 kb_admin initial creation * 12JAN2005 kb_admin massive changes for tftp, strings, and more * 05JUL2005 kb_admin save tag address, and set registers on boot * * BEGIN_KBDD_BLOCK * No warranty, expressed or implied, is included with this software. It is * provided "AS IS" and no warranty of any kind including statutory or aspects * relating to merchantability or fitness for any purpose is provided. All * intellectual property rights of others is maintained with the respective * owners. This software is not copyrighted and is intended for reference * only. * END_BLOCK * * $FreeBSD: head/sys/boot/arm/at91/bootspi/loader_prompt.c 163597 2006-10-21 22:44:26Z imp $ *****************************************************************************/ #include "at91rm9200_lowlevel.h" #include "at91rm9200.h" #include "emac.h" #include "loader_prompt.h" #include "env_vars.h" #include "lib.h" #include "spi_flash.h" #include "fpga.h" #include "ee.h" /******************************* GLOBALS *************************************/ /*********************** PRIVATE FUNCTIONS/DATA ******************************/ static char inputBuffer[MAX_INPUT_SIZE]; static int buffCount; // argv pointer are either NULL or point to locations in inputBuffer static char *argv[MAX_COMMAND_PARAMS]; #define FLASH_OFFSET (0 * FLASH_PAGE_SIZE) #define FPGA_OFFSET (15 * FLASH_PAGE_SIZE) #define FPGA_LEN (212608) #define KERNEL_OFFSET (220 * FLASH_PAGE_SIZE) #define KERNEL_LEN (6 * 1024 * FLASH_PAGE_SIZE) static const char *backspaceString = "\010 \010"; static const command_entry_t CommandTable[] = { {COMMAND_DUMP, "d"}, {COMMAND_EXEC, "e"}, {COMMAND_LOCAL_IP, "ip"}, {COMMAND_MAC, "m"}, {COMMAND_SERVER_IP, "server_ip"}, {COMMAND_TFTP, "tftp"}, {COMMAND_XMODEM, "x"}, {COMMAND_RESET, "R"}, {COMMAND_LOAD_SPI_KERNEL, "k"}, {COMMAND_REPLACE_KERNEL_VIA_XMODEM, "K"}, {COMMAND_REPLACE_FLASH_VIA_XMODEM, "I"}, {COMMAND_REPLACE_FPGA_VIA_XMODEM, "F"}, {COMMAND_REPLACE_ID_EEPROM, "E"}, {COMMAND_FINAL_FLAG, 0} }; #ifdef TSC_FPGA #include "fpga.h" const struct fpga main_fpga = { AT91C_BASE_PIOB, AT91C_PIO_PB0, AT91C_BASE_PIOC, AT91C_PIO_PC11, AT91C_BASE_PIOB, AT91C_PIO_PB2, AT91C_BASE_PIOC, AT91C_PIO_PC12 }; void fpga_load(void) { int len, off, i, offset; char *addr = (char *)SDRAM_BASE + (1 << 20); /* Load to base + 1MB */ len = FPGA_LEN; offset = FPGA_OFFSET; for (i = 0; i < len; i+= FLASH_PAGE_SIZE) { off = i + offset; SPI_ReadFlash(off, addr + i, FLASH_PAGE_SIZE); } fpga_init(&main_fpga); fpga_clear(&main_fpga); fpga_write_bytes(&main_fpga, addr, len); fpga_done(&main_fpga); } #endif /* * .KB_C_FN_DEFINITION_START * unsigned BuildIP(void) * This private function packs the test IP info to an unsigned value. * .KB_C_FN_DEFINITION_END */ static unsigned BuildIP(void) { return ((p_ASCIIToDec(argv[1]) << 24) | (p_ASCIIToDec(argv[2]) << 16) | (p_ASCIIToDec(argv[3]) << 8) | p_ASCIIToDec(argv[4])); } /* * .KB_C_FN_DEFINITION_START * int StringToCommand(char *cPtr) * This private function converts a command string to a command code. * .KB_C_FN_DEFINITION_END */ static int StringToCommand(char *cPtr) { int i; for (i = 0; CommandTable[i].command != COMMAND_FINAL_FLAG; ++i) if (!strcmp(CommandTable[i].c_string, cPtr)) return (CommandTable[i].command); return (COMMAND_INVALID); } /* * .KB_C_FN_DEFINITION_START * int BreakCommand(char *) * This private function splits the buffer into separate strings as pointed * by argv and returns the number of parameters (< 0 on failure). * .KB_C_FN_DEFINITION_END */ static int BreakCommand(char *buffer) { int pCount, cCount, state; state = pCount = 0; p_memset((char*)argv, 0, sizeof(argv)); for (cCount = 0; cCount < MAX_INPUT_SIZE; ++cCount) { if (!state) { /* look for next command */ if (!p_IsWhiteSpace(buffer[cCount])) { argv[pCount++] = &buffer[cCount]; state = 1; } else { buffer[cCount] = 0; } } else { /* in command, find next white space */ if (p_IsWhiteSpace(buffer[cCount])) { buffer[cCount] = 0; state = 0; } } if (pCount >= MAX_COMMAND_PARAMS) { return (-1); } } return (pCount); } #if 0 static void UpdateEEProm(int eeaddr) { char *addr = (char *)SDRAM_BASE + (1 << 20); /* Load to base + 1MB */ int len; while ((len = xmodem_rx(addr)) == -1) continue; printf("\nDownloaded %u bytes.\n", len); WriteEEPROM(eeaddr, 0, addr, len); } #endif static void UpdateFlash(int offset) { char *addr = (char *)SDRAM_BASE + (1 << 20); /* Load to base + 1MB */ int len, i, off; while ((len = xmodem_rx(addr)) == -1) continue; printf("\nDownloaded %u bytes.\n", len); for (i = 0; i < len; i+= FLASH_PAGE_SIZE) { off = i + offset; SPI_WriteFlash(off, addr + i, FLASH_PAGE_SIZE); } } static void LoadKernelFromSpi(char *addr) { int i, off; for (i = 0; i < KERNEL_LEN; i+= FLASH_PAGE_SIZE) { off = i + KERNEL_OFFSET; SPI_ReadFlash(off, addr + i, FLASH_PAGE_SIZE); } } /* * .KB_C_FN_DEFINITION_START * void ParseCommand(char *) * This private function executes matching functions. * .KB_C_FN_DEFINITION_END */ static void ParseCommand(char *buffer) { int argc, i; if ((argc = BreakCommand(buffer)) < 1) return; switch (StringToCommand(argv[0])) { case COMMAND_DUMP: // display boot commands DumpBootCommands(); break; case COMMAND_EXEC: { // "e
" // execute at address void (*execAddr)(unsigned, unsigned); if (argc > 1) { /* in future, include machtypes (MACH_KB9200 = 612) */ execAddr = (void (*)(unsigned, unsigned)) p_ASCIIToHex(argv[1]); (*execAddr)(0, 612); } break; } case COMMAND_TFTP: { // "tftp