diff --git a/sys/boot/arm/at91/bootiic/Makefile b/sys/boot/arm/at91/bootiic/Makefile index 639f28e17d2..c9da664ae20 100644 --- a/sys/boot/arm/at91/bootiic/Makefile +++ b/sys/boot/arm/at91/bootiic/Makefile @@ -2,7 +2,7 @@ P=bootiic FILES=${P} -SRCS=arm_init.S main.c +SRCS=arm_init.S main.c loader_prompt.c env_vars.c NO_MAN= LDFLAGS=-e 0 -T ${.CURDIR}/../linker.cfg OBJS+= ${SRCS:N*.h:R:S/$/.o/g} diff --git a/sys/boot/arm/at91/bootiic/arm_init.S b/sys/boot/arm/at91/bootiic/arm_init.S index 0aad9772f25..90e5c5cb2b0 100644 --- a/sys/boot/arm/at91/bootiic/arm_init.S +++ b/sys/boot/arm/at91/bootiic/arm_init.S @@ -117,3 +117,4 @@ BootCommandSection: .string "tftp 0x20000000 kernel.bin " .string "e 0x20000000 " #endif + .space 0x50 diff --git a/sys/boot/arm/at91/bootiic/env_vars.c b/sys/boot/arm/at91/bootiic/env_vars.c new file mode 100644 index 00000000000..78afae9c1df --- /dev/null +++ b/sys/boot/arm/at91/bootiic/env_vars.c @@ -0,0 +1,207 @@ +/****************************************************************************** + * + * Filename: env_vars.c + * + * Instantiation of environment variables, structures, and other globals. + * + * Revision information: + * + * 20AUG2004 kb_admin initial creation + * + * 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 "env_vars.h" +#include "loader_prompt.h" +#include "lib.h" + +/******************************* GLOBALS *************************************/ +char boot_commands[MAX_BOOT_COMMANDS][MAX_INPUT_SIZE]; + +char env_table[MAX_ENV_SIZE_BYTES]; + +extern char BootCommandSection; + +/************************** PRIVATE FUNCTIONS ********************************/ + + +static int currentIndex; +static int currentOffset; + + +/* + * .KB_C_FN_DEFINITION_START + * int ReadCharFromEnvironment(char *) + * This private function reads characters from the enviroment variables + * to service the command prompt during auto-boot or just to setup the + * default environment. Returns positive value if valid character was + * set in the pointer. Returns negative value to signal input stream + * terminated. Returns 0 to indicate _wait_ condition. + * .KB_C_FN_DEFINITION_END + */ +static int +ReadCharFromEnvironment(int timeout) +{ + int ch; + + if (currentIndex < MAX_BOOT_COMMANDS) { + ch = boot_commands[currentIndex][currentOffset++]; + if (ch == '\0' || (currentOffset >= MAX_INPUT_SIZE)) { + currentOffset = 0; + ++currentIndex; + ch = '\r'; + } + return (ch); + } + + return (-1); +} + + +/*************************** GLOBAL FUNCTIONS ********************************/ + + +/* + * .KB_C_FN_DEFINITION_START + * void WriteCommandTable(void) + * This global function write the current command table to the non-volatile + * memory. + * .KB_C_FN_DEFINITION_END + */ +void +WriteCommandTable(void) +{ + int i, size = MAX_ENV_SIZE_BYTES, copySize; + char *cPtr = env_table; + + p_memset(env_table, 0, sizeof(env_table)); + + for (i = 0; i < MAX_BOOT_COMMANDS; ++i) { + + copySize = p_strlen(boot_commands[i]); + size -= copySize + 1; + + if (size < 0) { + continue; + } + p_memcpy(cPtr, boot_commands[i], copySize); + cPtr += copySize; + *cPtr++ = 0; + } + + /* We're executing in low RAM so addr in ram == offset in eeprom */ + WriteEEPROM((unsigned)&BootCommandSection, env_table, + sizeof(env_table)); +} + + +/* + * .KB_C_FN_DEFINITION_START + * void SetBootCommand(int index, char *command) + * This global function replaces the specified index with the string residing + * at command. Execute this function with a NULL string to clear the + * associated command index. + * .KB_C_FN_DEFINITION_END + */ +void +SetBootCommand(int index, char *command) +{ + int i; + + if ((unsigned)index < MAX_BOOT_COMMANDS) { + + p_memset(boot_commands[index], 0, MAX_INPUT_SIZE); + + if (!command) + return ; + + for (i = 0; i < MAX_INPUT_SIZE; ++i) { + boot_commands[index][i] = command[i]; + if (!(boot_commands[index][i])) + return; + } + } +} + + +/* + * .KB_C_FN_DEFINITION_START + * void DumpBootCommands(void) + * This global function displays the current boot commands. + * .KB_C_FN_DEFINITION_END + */ +void +DumpBootCommands(void) +{ + int i, j; + + for (i = 0; i < MAX_BOOT_COMMANDS; ++i) { + printf("0x%x : ", i); + for (j = 0; j < MAX_INPUT_SIZE; ++j) { + putchar(boot_commands[i][j]); + if (!(boot_commands[i][j])) + break; + } + printf("[E]\n\r"); + } +} + + +/* + * .KB_C_FN_DEFINITION_START + * void LoadBootCommands(void) + * This global function loads the existing boot commands from raw format and + * coverts it to the standard, command-index format. Notice, the processed + * boot command table has much more space allocated than the actual table + * stored in non-volatile memory. This is because the processed table + * exists in RAM which is larger than the non-volatile space. + * .KB_C_FN_DEFINITION_END + */ +void +LoadBootCommands(void) +{ + int index, j, size; + char *cPtr; + + p_memset((char*)boot_commands, 0, sizeof(boot_commands)); + + cPtr = &BootCommandSection; + + size = MAX_ENV_SIZE_BYTES; + + for (index = 0; (index < MAX_BOOT_COMMANDS) && size; ++index) { + for (j = 0; (j < MAX_INPUT_SIZE) && size; ++j) { + size--; + boot_commands[index][j] = *cPtr++; + if (!(boot_commands[index][j])) { + break; + } + } + } +} + + +/* + * .KB_C_FN_DEFINITION_START + * void ExecuteEnvironmentFunctions(void) + * This global function executes applicable entries in the environment. + * .KB_C_FN_DEFINITION_END + */ +void +ExecuteEnvironmentFunctions(void) +{ + currentIndex = 0; + currentOffset = 0; + + DumpBootCommands(); + Bootloader(ReadCharFromEnvironment); +} diff --git a/sys/boot/arm/at91/bootiic/env_vars.h b/sys/boot/arm/at91/bootiic/env_vars.h new file mode 100644 index 00000000000..c6e46b4e433 --- /dev/null +++ b/sys/boot/arm/at91/bootiic/env_vars.h @@ -0,0 +1,54 @@ +/****************************************************************************** + * + * Filename: env_vars.h + * + * Definition of environment variables, structures, and other globals. + * + * Revision information: + * + * 20AUG2004 kb_admin initial creation + * + * 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$ + *****************************************************************************/ + +#ifndef _ENV_VARS_H_ +#define _ENV_VARS_H_ + +/* each environment variable is a string following the standard command */ +/* definition used by the interactive loader in the following format: */ +/* ... */ +/* all environment variables (or commands) are stored in a string */ +/* format: NULL-terminated. */ +/* this implies that commands can never utilize 0-values: actual 0, not */ +/* the string '0'. this is not an issue as the string '0' is handled */ +/* by the command parse routine. */ + +/* the following defines the maximum size of the environment for */ +/* including variables. */ +/* this value must match that declared in the low-level file that */ +/* actually reserves the space for the non-volatile environment. */ +#define MAX_ENV_SIZE_BYTES 0x100 + +#define MAX_BOOT_COMMANDS 10 + +/* C-style reference section */ +#ifndef __ASSEMBLY__ + +extern void WriteCommandTable(void); +extern void SetBootCommand(int index, char *command); +extern void DumpBootCommands(void); +extern void LoadBootCommands(void); +extern void ExecuteEnvironmentFunctions(void); + +#endif /* !__ASSEMBLY__ */ + +#endif /* _ENV_VARS_H_ */ diff --git a/sys/boot/arm/at91/bootiic/loader_prompt.c b/sys/boot/arm/at91/bootiic/loader_prompt.c new file mode 100644 index 00000000000..58b06ce8470 --- /dev/null +++ b/sys/boot/arm/at91/bootiic/loader_prompt.c @@ -0,0 +1,387 @@ +/****************************************************************************** + * + * 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 (!p_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]); + p_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:\r\n" + "\tc\r\n" + "\td\r\n" + "\te\r\n" + "\tip\r\n" + "\tserver_ip\r\n" + "\tm\r\n" + "\ttftp\r\n" + "\ts\r\n" +#ifdef SUPPORT_TAG_LIST + "\tt\r\n" +#endif + "\tw\r\n" + "\tx\r\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]); + 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("\r\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 '\r'. + * .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("\r\n"); + ParseCommand(inputBuffer); + p_memset(inputBuffer, 0, MAX_INPUT_SIZE); + buffCount = 0; + printf("\r\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("\r\n>"); + + while (1) + if ((ch = ((*inputFunction)(0))) > 0) + ServicePrompt(ch); +} diff --git a/sys/boot/arm/at91/bootiic/loader_prompt.h b/sys/boot/arm/at91/bootiic/loader_prompt.h new file mode 100644 index 00000000000..02233405f96 --- /dev/null +++ b/sys/boot/arm/at91/bootiic/loader_prompt.h @@ -0,0 +1,55 @@ +/****************************************************************************** + * + * Filename: loader_prompt.h + * + * Definition of the interactive loader functions. + * + * Revision information: + * + * 20AUG2004 kb_admin initial creation + * + * 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$ + *****************************************************************************/ + +#ifndef _LOADER_PROMPT_H_ +#define _LOADER_PROMPT_H_ + +#define MAX_INPUT_SIZE 256 +#define MAX_COMMAND_PARAMS 10 + +enum { + COMMAND_INVALID = 0, + COMMAND_COPY, + COMMAND_DUMP, + COMMAND_EXEC, + COMMAND_HELP, + COMMAND_LOCAL_IP, + COMMAND_MAC, + COMMAND_SERVER_IP, + COMMAND_SET, + COMMAND_TAG, + COMMAND_TFTP, + COMMAND_WRITE, + COMMAND_XMODEM, + COMMAND_FINAL_FLAG +} e_cmd_t; + + +typedef struct { + int command; + const char *c_string; +} command_entry_t; + +void EnterInteractiveBootloader(int(*inputFunction)(int)); +void Bootloader(int(*inputFunction)(int)); + +#endif /* _LOADER_PROMPT_H_ */ diff --git a/sys/boot/arm/at91/bootiic/main.c b/sys/boot/arm/at91/bootiic/main.c index cc71b8ec03d..b2b6e39041e 100644 --- a/sys/boot/arm/at91/bootiic/main.c +++ b/sys/boot/arm/at91/bootiic/main.c @@ -27,7 +27,6 @@ #include "loader_prompt.h" #include "emac.h" #include "lib.h" -#include "eeprom.h" /* * .KB_C_FN_DEFINITION_START