diff options
author | imp <imp@FreeBSD.org> | 2006-08-10 19:55:52 +0000 |
---|---|---|
committer | imp <imp@FreeBSD.org> | 2006-08-10 19:55:52 +0000 |
commit | 246a49807bbaf0b18e35bbf7ca6bdb8ef438e578 (patch) | |
tree | 2f653e85800ebbd248d7d24755a557d62c9015e6 /sys/boot/arm | |
parent | b5e61b2d3fd9d63344994ed2412795ba871f4dba (diff) | |
download | FreeBSD-src-246a49807bbaf0b18e35bbf7ca6bdb8ef438e578.zip FreeBSD-src-246a49807bbaf0b18e35bbf7ca6bdb8ef438e578.tar.gz |
MFp4: Integrate a boatload of bug fixes from p4. We're right on the
8k boundary with this program still.
text data bss dec hex filename
7925 4 4476 12405 3075 bootiic.out
so we have like 293 bytes left before we have to play games. There
may be ways to reduce that somewhat, but they start to be very board
specific.
Diffstat (limited to 'sys/boot/arm')
-rw-r--r-- | sys/boot/arm/at91/bootiic/Makefile | 2 | ||||
-rw-r--r-- | sys/boot/arm/at91/bootiic/arm_init.S | 1 | ||||
-rw-r--r-- | sys/boot/arm/at91/bootiic/env_vars.c | 207 | ||||
-rw-r--r-- | sys/boot/arm/at91/bootiic/env_vars.h | 54 | ||||
-rw-r--r-- | sys/boot/arm/at91/bootiic/loader_prompt.c | 387 | ||||
-rw-r--r-- | sys/boot/arm/at91/bootiic/loader_prompt.h | 55 | ||||
-rw-r--r-- | sys/boot/arm/at91/bootiic/main.c | 1 |
7 files changed, 705 insertions, 2 deletions
diff --git a/sys/boot/arm/at91/bootiic/Makefile b/sys/boot/arm/at91/bootiic/Makefile index 639f28e..c9da664 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 0aad977..90e5c5c 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 0000000..78afae9 --- /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 0000000..c6e46b4 --- /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: */ +/* <command> <parm1> <parm2> ... */ +/* 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 0000000..58b06ce --- /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 <to> <from> <size in bytes>" + // 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 <address>" + // 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 <local_dest_addr filename>" + // 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 <server IP 192 200 1 20>" + // 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 <local IP 192 200 1 21> + // set ip of this module + if (argc > 4) + SetLocalIPAddress(BuildIP()); + break; + + case COMMAND_MAC: + { + // "m <mac address 12 34 56 78 9a bc> + // 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 <index> <new boot command> + // 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 <address> <boot command line> + // 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 <address>" + // 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 0000000..0223340 --- /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 cc71b8e..b2b6e39 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 |