388 lines
8.0 KiB
C
388 lines
8.0 KiB
C
/******************************************************************************
|
|
*
|
|
* 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]);
|
|
EMAC_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);
|
|
}
|