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.
This commit is contained in:
Warner Losh 2006-08-10 19:55:52 +00:00
parent 5b0bac7af0
commit 100d8ed79b
Notes: svn2git 2020-12-20 02:59:44 +00:00
svn path=/head/; revision=161202
7 changed files with 705 additions and 2 deletions

View File

@ -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}

View File

@ -117,3 +117,4 @@ BootCommandSection:
.string "tftp 0x20000000 kernel.bin "
.string "e 0x20000000 "
#endif
.space 0x50

View File

@ -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);
}

View File

@ -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_ */

View File

@ -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);
}

View File

@ -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_ */

View File

@ -27,7 +27,6 @@
#include "loader_prompt.h"
#include "emac.h"
#include "lib.h"
#include "eeprom.h"
/*
* .KB_C_FN_DEFINITION_START