1161370Simp/****************************************************************************** 2161370Simp * 3161370Simp * Filename: loader_prompt.c 4161370Simp * 5161370Simp * Instantiation of the interactive loader functions. 6161370Simp * 7161370Simp * Revision information: 8161370Simp * 9161370Simp * 20AUG2004 kb_admin initial creation 10161370Simp * 12JAN2005 kb_admin massive changes for tftp, strings, and more 11161370Simp * 05JUL2005 kb_admin save tag address, and set registers on boot 12161370Simp * 13161370Simp * BEGIN_KBDD_BLOCK 14161370Simp * No warranty, expressed or implied, is included with this software. It is 15161370Simp * provided "AS IS" and no warranty of any kind including statutory or aspects 16161370Simp * relating to merchantability or fitness for any purpose is provided. All 17161370Simp * intellectual property rights of others is maintained with the respective 18161370Simp * owners. This software is not copyrighted and is intended for reference 19161370Simp * only. 20161370Simp * END_BLOCK 21161370Simp * 22161370Simp * $FreeBSD: releng/10.2/sys/boot/arm/at91/bootspi/loader_prompt.c 167586 2007-03-15 03:31:49Z imp $ 23161370Simp *****************************************************************************/ 24161370Simp 25161370Simp#include "at91rm9200_lowlevel.h" 26161370Simp#include "at91rm9200.h" 27161370Simp#include "emac.h" 28161370Simp#include "loader_prompt.h" 29161370Simp#include "env_vars.h" 30161370Simp#include "lib.h" 31161370Simp#include "spi_flash.h" 32163597Simp#include "ee.h" 33161370Simp 34161370Simp/******************************* GLOBALS *************************************/ 35161370Simp 36161370Simp 37161370Simp/*********************** PRIVATE FUNCTIONS/DATA ******************************/ 38161370Simp 39161370Simpstatic char inputBuffer[MAX_INPUT_SIZE]; 40161370Simpstatic int buffCount; 41161370Simp 42161370Simp// argv pointer are either NULL or point to locations in inputBuffer 43161370Simpstatic char *argv[MAX_COMMAND_PARAMS]; 44161370Simp 45161370Simp#define FLASH_OFFSET (0 * FLASH_PAGE_SIZE) 46161370Simp#define KERNEL_OFFSET (220 * FLASH_PAGE_SIZE) 47161370Simp#define KERNEL_LEN (6 * 1024 * FLASH_PAGE_SIZE) 48161370Simpstatic const char *backspaceString = "\010 \010"; 49161370Simp 50161370Simpstatic const command_entry_t CommandTable[] = { 51161370Simp {COMMAND_DUMP, "d"}, 52161370Simp {COMMAND_EXEC, "e"}, 53161370Simp {COMMAND_LOCAL_IP, "ip"}, 54161370Simp {COMMAND_MAC, "m"}, 55161370Simp {COMMAND_SERVER_IP, "server_ip"}, 56161370Simp {COMMAND_TFTP, "tftp"}, 57161370Simp {COMMAND_XMODEM, "x"}, 58161370Simp {COMMAND_RESET, "R"}, 59161370Simp {COMMAND_LOAD_SPI_KERNEL, "k"}, 60161370Simp {COMMAND_REPLACE_KERNEL_VIA_XMODEM, "K"}, 61161370Simp {COMMAND_REPLACE_FLASH_VIA_XMODEM, "I"}, 62161370Simp {COMMAND_REPLACE_ID_EEPROM, "E"}, 63161370Simp {COMMAND_FINAL_FLAG, 0} 64161370Simp}; 65161370Simp 66161370Simp/* 67161370Simp * .KB_C_FN_DEFINITION_START 68161370Simp * unsigned BuildIP(void) 69161370Simp * This private function packs the test IP info to an unsigned value. 70161370Simp * .KB_C_FN_DEFINITION_END 71161370Simp */ 72161370Simpstatic unsigned 73161370SimpBuildIP(void) 74161370Simp{ 75161370Simp return ((p_ASCIIToDec(argv[1]) << 24) | 76161370Simp (p_ASCIIToDec(argv[2]) << 16) | 77161370Simp (p_ASCIIToDec(argv[3]) << 8) | 78161370Simp p_ASCIIToDec(argv[4])); 79161370Simp} 80161370Simp 81161370Simp 82161370Simp/* 83161370Simp * .KB_C_FN_DEFINITION_START 84161370Simp * int StringToCommand(char *cPtr) 85161370Simp * This private function converts a command string to a command code. 86161370Simp * .KB_C_FN_DEFINITION_END 87161370Simp */ 88161370Simpstatic int 89161370SimpStringToCommand(char *cPtr) 90161370Simp{ 91161370Simp int i; 92161370Simp 93161370Simp for (i = 0; CommandTable[i].command != COMMAND_FINAL_FLAG; ++i) 94163597Simp if (!strcmp(CommandTable[i].c_string, cPtr)) 95161370Simp return (CommandTable[i].command); 96161370Simp 97161370Simp return (COMMAND_INVALID); 98161370Simp} 99161370Simp 100161370Simp 101161370Simp/* 102161370Simp * .KB_C_FN_DEFINITION_START 103161370Simp * int BreakCommand(char *) 104161370Simp * This private function splits the buffer into separate strings as pointed 105161370Simp * by argv and returns the number of parameters (< 0 on failure). 106161370Simp * .KB_C_FN_DEFINITION_END 107161370Simp */ 108161370Simpstatic int 109161370SimpBreakCommand(char *buffer) 110161370Simp{ 111161370Simp int pCount, cCount, state; 112161370Simp 113161370Simp state = pCount = 0; 114161370Simp p_memset((char*)argv, 0, sizeof(argv)); 115161370Simp 116161370Simp for (cCount = 0; cCount < MAX_INPUT_SIZE; ++cCount) { 117161370Simp 118161370Simp if (!state) { 119161370Simp /* look for next command */ 120161370Simp if (!p_IsWhiteSpace(buffer[cCount])) { 121161370Simp argv[pCount++] = &buffer[cCount]; 122161370Simp state = 1; 123161370Simp } else { 124161370Simp buffer[cCount] = 0; 125161370Simp } 126161370Simp } else { 127161370Simp /* in command, find next white space */ 128161370Simp if (p_IsWhiteSpace(buffer[cCount])) { 129161370Simp buffer[cCount] = 0; 130161370Simp state = 0; 131161370Simp } 132161370Simp } 133161370Simp 134161370Simp if (pCount >= MAX_COMMAND_PARAMS) { 135161370Simp return (-1); 136161370Simp } 137161370Simp } 138161370Simp 139161370Simp return (pCount); 140161370Simp} 141161370Simp 142161370Simp#if 0 143161370Simpstatic void 144161370SimpUpdateEEProm(int eeaddr) 145161370Simp{ 146161370Simp char *addr = (char *)SDRAM_BASE + (1 << 20); /* Load to base + 1MB */ 147161370Simp int len; 148161370Simp 149161370Simp while ((len = xmodem_rx(addr)) == -1) 150161370Simp continue; 151163597Simp printf("\nDownloaded %u bytes.\n", len); 152161370Simp WriteEEPROM(eeaddr, 0, addr, len); 153161370Simp} 154161370Simp#endif 155161370Simp 156161370Simpstatic void 157161370SimpUpdateFlash(int offset) 158161370Simp{ 159161370Simp char *addr = (char *)SDRAM_BASE + (1 << 20); /* Load to base + 1MB */ 160161370Simp int len, i, off; 161161370Simp 162161370Simp while ((len = xmodem_rx(addr)) == -1) 163161370Simp continue; 164163597Simp printf("\nDownloaded %u bytes.\n", len); 165161370Simp for (i = 0; i < len; i+= FLASH_PAGE_SIZE) { 166161370Simp off = i + offset; 167161370Simp SPI_WriteFlash(off, addr + i, FLASH_PAGE_SIZE); 168161370Simp } 169161370Simp} 170161370Simp 171161370Simpstatic void 172161370SimpLoadKernelFromSpi(char *addr) 173161370Simp{ 174161370Simp int i, off; 175161370Simp 176161370Simp for (i = 0; i < KERNEL_LEN; i+= FLASH_PAGE_SIZE) { 177161370Simp off = i + KERNEL_OFFSET; 178161370Simp SPI_ReadFlash(off, addr + i, FLASH_PAGE_SIZE); 179161370Simp } 180161370Simp} 181161370Simp 182161370Simp/* 183161370Simp * .KB_C_FN_DEFINITION_START 184161370Simp * void ParseCommand(char *) 185161370Simp * This private function executes matching functions. 186161370Simp * .KB_C_FN_DEFINITION_END 187161370Simp */ 188161370Simpstatic void 189161370SimpParseCommand(char *buffer) 190161370Simp{ 191161370Simp int argc, i; 192161370Simp 193161370Simp if ((argc = BreakCommand(buffer)) < 1) 194161370Simp return; 195161370Simp 196161370Simp switch (StringToCommand(argv[0])) { 197161370Simp case COMMAND_DUMP: 198161370Simp // display boot commands 199161370Simp DumpBootCommands(); 200161370Simp break; 201161370Simp 202161370Simp case COMMAND_EXEC: 203161370Simp { 204161370Simp // "e <address>" 205161370Simp // execute at address 206161370Simp void (*execAddr)(unsigned, unsigned); 207161370Simp 208161370Simp if (argc > 1) { 209161370Simp /* in future, include machtypes (MACH_KB9200 = 612) */ 210161370Simp execAddr = (void (*)(unsigned, unsigned)) 211161370Simp p_ASCIIToHex(argv[1]); 212161370Simp (*execAddr)(0, 612); 213161370Simp } 214161370Simp break; 215161370Simp } 216161370Simp 217161370Simp case COMMAND_TFTP: 218161370Simp { 219161370Simp // "tftp <local_dest_addr filename>" 220161370Simp // tftp download 221161370Simp unsigned address = 0; 222161370Simp 223161370Simp if (argc > 2) 224161370Simp address = p_ASCIIToHex(argv[1]); 225161370Simp TFTP_Download(address, argv[2]); 226161370Simp break; 227161370Simp } 228161370Simp 229161370Simp case COMMAND_SERVER_IP: 230161370Simp // "server_ip <server IP 192 200 1 20>" 231161370Simp // set download server address 232161370Simp if (argc > 4) 233161370Simp SetServerIPAddress(BuildIP()); 234161370Simp break; 235161370Simp 236161370Simp case COMMAND_LOCAL_IP: 237161370Simp // "local_ip <local IP 192 200 1 21> 238161370Simp // set ip of this module 239161370Simp if (argc > 4) 240161370Simp SetLocalIPAddress(BuildIP()); 241161370Simp break; 242161370Simp 243161370Simp case COMMAND_MAC: 244161370Simp { 245161370Simp // "m <mac address 12 34 56 78 9a bc> 246161370Simp // set mac address using 6 byte values 247161370Simp unsigned char mac[6]; 248161370Simp 249161370Simp if (argc > 6) { 250161370Simp for (i = 0; i < 6; i++) 251161370Simp mac[i] = p_ASCIIToHex(argv[i + 1]); 252161370Simp EMAC_SetMACAddress(mac); 253161370Simp } 254161370Simp break; 255161370Simp } 256161370Simp 257161370Simp case COMMAND_LOAD_SPI_KERNEL: 258161370Simp // "k <address>" 259161370Simp if (argc > 1) 260161370Simp LoadKernelFromSpi((char *)p_ASCIIToHex(argv[1])); 261161370Simp break; 262161370Simp 263161370Simp case COMMAND_XMODEM: 264161370Simp // "x <address>" 265161370Simp // download X-modem record at address 266161370Simp if (argc > 1) 267161370Simp xmodem_rx((char *)p_ASCIIToHex(argv[1])); 268161370Simp break; 269161370Simp 270161370Simp case COMMAND_RESET: 271163597Simp printf("Reset\n"); 272161370Simp reset(); 273161370Simp while (1) continue; 274161370Simp break; 275161370Simp 276161370Simp case COMMAND_REPLACE_KERNEL_VIA_XMODEM: 277163597Simp printf("Updating KERNEL image\n"); 278161370Simp UpdateFlash(KERNEL_OFFSET); 279161370Simp break; 280161370Simp case COMMAND_REPLACE_FLASH_VIA_XMODEM: 281163597Simp printf("Updating FLASH image\n"); 282161370Simp UpdateFlash(FLASH_OFFSET); 283161370Simp break; 284161370Simp 285163597Simp case COMMAND_REPLACE_ID_EEPROM: 286163597Simp { 287163597Simp char buf[25]; 288163597Simp printf("Testing Config EEPROM\n"); 289163597Simp EEWrite(0, "This is a test", 15); 290163597Simp EERead(0, buf, 15); 291163597Simp printf("Found '%s'\n", buf); 292163597Simp break; 293163597Simp } 294161370Simp default: 295161370Simp break; 296161370Simp } 297161370Simp 298163597Simp printf("\n"); 299161370Simp} 300161370Simp 301161370Simp 302161370Simp/* 303161370Simp * .KB_C_FN_DEFINITION_START 304161370Simp * void ServicePrompt(char) 305161370Simp * This private function process each character checking for valid commands. 306161370Simp * This function is only executed if the character is considered valid. 307163597Simp * Each command is terminated with NULL (0) or ''. 308161370Simp * .KB_C_FN_DEFINITION_END 309161370Simp */ 310161370Simpstatic void 311161370SimpServicePrompt(char p_char) 312161370Simp{ 313161370Simp if (p_char == '\r') 314161370Simp p_char = 0; 315161370Simp 316161370Simp if (p_char == '\010') { 317161370Simp if (buffCount) { 318161370Simp /* handle backspace BS */ 319161370Simp inputBuffer[--buffCount] = 0; 320161370Simp printf(backspaceString); 321161370Simp } 322161370Simp return; 323161370Simp } 324161370Simp if (buffCount < MAX_INPUT_SIZE - 1) { 325161370Simp inputBuffer[buffCount++] = p_char; 326161370Simp putchar(p_char); 327161370Simp } 328161370Simp if (!p_char) { 329163597Simp printf("\n"); 330161370Simp ParseCommand(inputBuffer); 331161370Simp p_memset(inputBuffer, 0, MAX_INPUT_SIZE); 332161370Simp buffCount = 0; 333163597Simp printf("\n>"); 334161370Simp } 335161370Simp} 336161370Simp 337161370Simp 338161370Simp/* ************************** GLOBAL FUNCTIONS ********************************/ 339161370Simp 340161370Simp 341161370Simp/* 342161370Simp * .KB_C_FN_DEFINITION_START 343161370Simp * void Bootloader(void *inputFunction) 344161370Simp * This global function is the entry point for the bootloader. If the 345161370Simp * inputFunction pointer is NULL, the loader input will be serviced from 346161370Simp * the uart. Otherwise, inputFunction is called to get characters which 347161370Simp * the loader will parse. 348161370Simp * .KB_C_FN_DEFINITION_END 349161370Simp */ 350161370Simpvoid 351161370SimpBootloader(int(*inputFunction)(int)) 352161370Simp{ 353161370Simp int ch = 0; 354161370Simp 355161370Simp p_memset((void*)inputBuffer, 0, sizeof(inputBuffer)); 356161370Simp buffCount = 0; 357161370Simp 358163597Simp printf("\n>"); 359161370Simp 360161370Simp while (1) 361161370Simp if ((ch = ((*inputFunction)(0))) > 0) 362161370Simp ServicePrompt(ch); 363161370Simp} 364