/****************************************************************************** * * 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$ *****************************************************************************/ #include "at91rm9200_lowlevel.h" #ifdef SUPPORT_TAG_LIST #include "tag_list.h" #endif #include "emac.h" #include "loader_prompt.h" #include "env_vars.h" #include "lib.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]; static const char *backspaceString = "\010 \010"; static const command_entry_t CommandTable[] = { {COMMAND_COPY, "c"}, {COMMAND_DUMP, "d"}, {COMMAND_EXEC, "e"}, {COMMAND_HELP, "?"}, {COMMAND_LOCAL_IP, "ip"}, {COMMAND_MAC, "m"}, {COMMAND_SERVER_IP, "server_ip"}, {COMMAND_SET, "s"}, #ifdef SUPPORT_TAG_LIST {COMMAND_TAG, "t"}, #endif {COMMAND_TFTP, "tftp"}, {COMMAND_WRITE, "w"}, {COMMAND_XMODEM, "x"}, {COMMAND_FINAL_FLAG, 0} }; static unsigned tagAddress; /* * .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 * void RestoreSpace(int) * This private function restores NULL characters to spaces in order to * process the remaining args as a string. The number passed is the argc * of the first entry to begin restoring space in the inputBuffer. * .KB_C_FN_DEFINITION_END */ static void RestoreSpace(int startArgc) { char *cPtr; for (startArgc++; startArgc < MAX_COMMAND_PARAMS; startArgc++) { if ((cPtr = argv[startArgc])) *(cPtr - 1) = ' '; } } /* * .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); } /* * .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_COPY: { // "c " // copy memory char *to, *from; unsigned size; if (argc > 3) { to = (char *)p_ASCIIToHex(argv[1]); from = (char *)p_ASCIIToHex(argv[2]); size = p_ASCIIToHex(argv[3]); memcpy(to, from, size); } break; } case COMMAND_DUMP: // display boot commands DumpBootCommands(); break; case COMMAND_EXEC: { // "e
" // execute at address void (*execAddr)(unsigned, unsigned, unsigned); if (argc > 1) { /* in future, include machtypes (MACH_KB9200 = 612) */ execAddr = (void (*)(unsigned, unsigned, unsigned)) p_ASCIIToHex(argv[1]); (*execAddr)(0, 612, tagAddress); } break; } case COMMAND_TFTP: { // "tftp " // tftp download unsigned address = 0; if (argc > 2) address = p_ASCIIToHex(argv[1]); TFTP_Download(address, argv[2]); break; } case COMMAND_SERVER_IP: // "server_ip " // set download server address if (argc > 4) SetServerIPAddress(BuildIP()); break; case COMMAND_HELP: // dump command info printf("Commands:\n" "\tc\n" "\td\n" "\te\n" "\tip\n" "\tserver_ip\n" "\tm\n" "\ttftp\n" "\ts\n" #ifdef SUPPORT_TAG_LIST "\tt\n" #endif "\tw\n" "\tx\n"); break; case COMMAND_LOCAL_IP: // "local_ip // set ip of this module if (argc > 4) SetLocalIPAddress(BuildIP()); break; case COMMAND_MAC: { // "m // set mac address using 6 byte values unsigned char mac[6]; if (argc > 6) { for (i = 0; i < 6; i++) mac[i] = p_ASCIIToHex(argv[i + 1]); EMAC_SetMACAddress(mac); } break; } case COMMAND_SET: { // s // set the boot command at index (0-based) unsigned index; if (argc > 1) { RestoreSpace(2); index = p_ASCIIToHex(argv[1]); SetBootCommand(index, argv[2]); } break; } #ifdef SUPPORT_TAG_LIST case COMMAND_TAG: // t
// create tag-list for linux boot if (argc > 2) { RestoreSpace(2); tagAddress = p_ASCIIToHex(argv[1]); InitTagList(argv[2], (void*)tagAddress); } break; #endif case COMMAND_WRITE: // write the command table to non-volatile WriteCommandTable(); break; case COMMAND_XMODEM: { // "x
" // download X-modem record at address if (argc > 1) xmodem_rx((char *)p_ASCIIToHex(argv[1])); break; } default: break; } printf("\n"); } /* * .KB_C_FN_DEFINITION_START * void ServicePrompt(char) * This private function process each character checking for valid commands. * This function is only executed if the character is considered valid. * Each command is terminated with NULL (0) or ''. * .KB_C_FN_DEFINITION_END */ static void ServicePrompt(char p_char) { if (p_char == '\r') p_char = 0; if (p_char == '\010') { if (buffCount) { /* handle backspace BS */ inputBuffer[--buffCount] = 0; printf(backspaceString); } return; } if (buffCount < MAX_INPUT_SIZE - 1) { inputBuffer[buffCount++] = p_char; putchar(p_char); } if (!p_char) { printf("\n"); ParseCommand(inputBuffer); p_memset(inputBuffer, 0, MAX_INPUT_SIZE); buffCount = 0; printf("\n>"); } } /* ************************** GLOBAL FUNCTIONS ********************************/ /* * .KB_C_FN_DEFINITION_START * void Bootloader(void *inputFunction) * This global function is the entry point for the bootloader. If the * inputFunction pointer is NULL, the loader input will be serviced from * the uart. Otherwise, inputFunction is called to get characters which * the loader will parse. * .KB_C_FN_DEFINITION_END */ void Bootloader(int(*inputFunction)(int)) { int ch = 0; p_memset((void*)inputBuffer, 0, sizeof(inputBuffer)); buffCount = 0; if (!inputFunction) { inputFunction = getc; } printf("\n>"); while (1) if ((ch = ((*inputFunction)(0))) > 0) ServicePrompt(ch); }