loader_prompt.c revision 163598
11573Srgrimes/****************************************************************************** 21573Srgrimes * 31573Srgrimes * Filename: loader_prompt.c 41573Srgrimes * 51573Srgrimes * Instantiation of the interactive loader functions. 61573Srgrimes * 71573Srgrimes * Revision information: 81573Srgrimes * 91573Srgrimes * 20AUG2004 kb_admin initial creation 101573Srgrimes * 12JAN2005 kb_admin massive changes for tftp, strings, and more 111573Srgrimes * 05JUL2005 kb_admin save tag address, and set registers on boot 121573Srgrimes * 131573Srgrimes * BEGIN_KBDD_BLOCK 141573Srgrimes * No warranty, expressed or implied, is included with this software. It is 151573Srgrimes * provided "AS IS" and no warranty of any kind including statutory or aspects 161573Srgrimes * relating to merchantability or fitness for any purpose is provided. All 171573Srgrimes * intellectual property rights of others is maintained with the respective 181573Srgrimes * owners. This software is not copyrighted and is intended for reference 191573Srgrimes * only. 201573Srgrimes * END_BLOCK 211573Srgrimes * 221573Srgrimes * $FreeBSD: head/sys/boot/arm/at91/bootspi/loader_prompt.c 163598 2006-10-21 22:51:21Z imp $ 231573Srgrimes *****************************************************************************/ 241573Srgrimes 251573Srgrimes#include "at91rm9200_lowlevel.h" 261573Srgrimes#include "at91rm9200.h" 271573Srgrimes#include "emac.h" 281573Srgrimes#include "loader_prompt.h" 291573Srgrimes#include "env_vars.h" 301573Srgrimes#include "lib.h" 3123658Speter#include "spi_flash.h" 321573Srgrimes#include "ee.h" 3390039Sobrien 3490039Sobrien/******************************* GLOBALS *************************************/ 351573Srgrimes 3671579Sdeischen 371573Srgrimes/*********************** PRIVATE FUNCTIONS/DATA ******************************/ 381573Srgrimes 3953812Salfredstatic char inputBuffer[MAX_INPUT_SIZE]; 4061193Skrisstatic int buffCount; 4153812Salfred 4271579Sdeischen// argv pointer are either NULL or point to locations in inputBuffer 431573Srgrimesstatic char *argv[MAX_COMMAND_PARAMS]; 4471579Sdeischen 45235647Sgleb#define FLASH_OFFSET (0 * FLASH_PAGE_SIZE) 46150065Sstefanf#define FPGA_OFFSET (15 * FLASH_PAGE_SIZE) 4771579Sdeischen#define FPGA_LEN (212608) 481573Srgrimes#define KERNEL_OFFSET (220 * FLASH_PAGE_SIZE) 491573Srgrimes#define KERNEL_LEN (6 * 1024 * FLASH_PAGE_SIZE) 501573Srgrimesstatic const char *backspaceString = "\010 \010"; 511573Srgrimes 52178772Skibstatic const command_entry_t CommandTable[] = { 5369656Sdeischen {COMMAND_DUMP, "d"}, 54178772Skib {COMMAND_EXEC, "e"}, 551573Srgrimes {COMMAND_LOCAL_IP, "ip"}, 5669656Sdeischen {COMMAND_MAC, "m"}, 57282979Sjulian {COMMAND_SERVER_IP, "server_ip"}, 58282979Sjulian {COMMAND_TFTP, "tftp"}, 591573Srgrimes {COMMAND_XMODEM, "x"}, 601573Srgrimes {COMMAND_RESET, "R"}, 6123658Speter {COMMAND_LOAD_SPI_KERNEL, "k"}, 6223658Speter {COMMAND_REPLACE_KERNEL_VIA_XMODEM, "K"}, 6323658Speter {COMMAND_REPLACE_FLASH_VIA_XMODEM, "I"}, 64282979Sjulian {COMMAND_REPLACE_FPGA_VIA_XMODEM, "F"}, 65282979Sjulian {COMMAND_REPLACE_ID_EEPROM, "E"}, 6623658Speter {COMMAND_FINAL_FLAG, 0} 6723658Speter}; 68270002Sjhb 69270002Sjhb#ifdef TSC_FPGA 70282979Sjulian#include "fpga.h" 7171579Sdeischen 721573Srgrimesconst struct fpga main_fpga = 731573Srgrimes{ 7423658Speter AT91C_BASE_PIOB, AT91C_PIO_PB0, 75282979Sjulian AT91C_BASE_PIOC, AT91C_PIO_PC11, 761573Srgrimes AT91C_BASE_PIOB, AT91C_PIO_PB2, 77270002Sjhb AT91C_BASE_PIOC, AT91C_PIO_PC12 781573Srgrimes}; 7933665Sjb 8023658Spetervoid 811573Srgrimesfpga_load(void) 821573Srgrimes{ 8323658Speter int len, off, i, offset; 841573Srgrimes char *addr = (char *)SDRAM_BASE + (1 << 20); /* Load to base + 1MB */ 85178772Skib 861573Srgrimes len = FPGA_LEN; 8723658Speter offset = FPGA_OFFSET; 8823658Speter for (i = 0; i < len; i+= FLASH_PAGE_SIZE) { 891573Srgrimes off = i + offset; 901573Srgrimes SPI_ReadFlash(off, addr + i, FLASH_PAGE_SIZE); 911573Srgrimes } 9253812Salfred fpga_init(&main_fpga); 9371579Sdeischen fpga_clear(&main_fpga); 9471579Sdeischen fpga_write_bytes(&main_fpga, addr, len); 9571579Sdeischen fpga_done(&main_fpga); 9671579Sdeischen} 9771579Sdeischen#endif 9871579Sdeischen 9971579Sdeischen/* 100174221Sdes * .KB_C_FN_DEFINITION_START 101178772Skib * unsigned BuildIP(void) 102174221Sdes * This private function packs the test IP info to an unsigned value. 10371579Sdeischen * .KB_C_FN_DEFINITION_END 10471579Sdeischen */ 105178772Skibstatic unsigned 10671579SdeischenBuildIP(void) 10771579Sdeischen{ 10871579Sdeischen return ((p_ASCIIToDec(argv[1]) << 24) | 10953812Salfred (p_ASCIIToDec(argv[2]) << 16) | 11053812Salfred (p_ASCIIToDec(argv[3]) << 8) | 11153812Salfred p_ASCIIToDec(argv[4])); 11253812Salfred} 11353812Salfred 11453812Salfred 11553812Salfred/* 11669656Sdeischen * .KB_C_FN_DEFINITION_START 11753812Salfred * int StringToCommand(char *cPtr) 11853892Salfred * This private function converts a command string to a command code. 11953812Salfred * .KB_C_FN_DEFINITION_END 12071579Sdeischen */ 121174221Sdesstatic int 122178772SkibStringToCommand(char *cPtr) 12391330Salfred{ 124174221Sdes int i; 12571579Sdeischen 126178772Skib for (i = 0; CommandTable[i].command != COMMAND_FINAL_FLAG; ++i) 12791330Salfred if (!strcmp(CommandTable[i].c_string, cPtr)) 12871579Sdeischen return (CommandTable[i].command); 12953892Salfred 13071579Sdeischen return (COMMAND_INVALID); 13153892Salfred} 13253892Salfred 13353892Salfred 13453892Salfred/* 13553892Salfred * .KB_C_FN_DEFINITION_START 13653872Swes * int BreakCommand(char *) 13753892Salfred * This private function splits the buffer into separate strings as pointed 13853812Salfred * by argv and returns the number of parameters (< 0 on failure). 13953892Salfred * .KB_C_FN_DEFINITION_END 14053892Salfred */ 14153812Salfredstatic int 142BreakCommand(char *buffer) 143{ 144 int pCount, cCount, state; 145 146 state = pCount = 0; 147 p_memset((char*)argv, 0, sizeof(argv)); 148 149 for (cCount = 0; cCount < MAX_INPUT_SIZE; ++cCount) { 150 151 if (!state) { 152 /* look for next command */ 153 if (!p_IsWhiteSpace(buffer[cCount])) { 154 argv[pCount++] = &buffer[cCount]; 155 state = 1; 156 } else { 157 buffer[cCount] = 0; 158 } 159 } else { 160 /* in command, find next white space */ 161 if (p_IsWhiteSpace(buffer[cCount])) { 162 buffer[cCount] = 0; 163 state = 0; 164 } 165 } 166 167 if (pCount >= MAX_COMMAND_PARAMS) { 168 return (-1); 169 } 170 } 171 172 return (pCount); 173} 174 175#if 0 176static void 177UpdateEEProm(int eeaddr) 178{ 179 char *addr = (char *)SDRAM_BASE + (1 << 20); /* Load to base + 1MB */ 180 int len; 181 182 while ((len = xmodem_rx(addr)) == -1) 183 continue; 184 printf("\nDownloaded %u bytes.\n", len); 185 WriteEEPROM(eeaddr, 0, addr, len); 186} 187#endif 188 189static void 190UpdateFlash(int offset) 191{ 192 char *addr = (char *)SDRAM_BASE + (1 << 20); /* Load to base + 1MB */ 193 int len, i, off; 194 195 while ((len = xmodem_rx(addr)) == -1) 196 continue; 197 printf("\nDownloaded %u bytes.\n", len); 198 for (i = 0; i < len; i+= FLASH_PAGE_SIZE) { 199 off = i + offset; 200 SPI_WriteFlash(off, addr + i, FLASH_PAGE_SIZE); 201 } 202} 203 204static void 205LoadKernelFromSpi(char *addr) 206{ 207 int i, off; 208 209 for (i = 0; i < KERNEL_LEN; i+= FLASH_PAGE_SIZE) { 210 off = i + KERNEL_OFFSET; 211 SPI_ReadFlash(off, addr + i, FLASH_PAGE_SIZE); 212 } 213} 214 215/* 216 * .KB_C_FN_DEFINITION_START 217 * void ParseCommand(char *) 218 * This private function executes matching functions. 219 * .KB_C_FN_DEFINITION_END 220 */ 221static void 222ParseCommand(char *buffer) 223{ 224 int argc, i; 225 226 if ((argc = BreakCommand(buffer)) < 1) 227 return; 228 229 switch (StringToCommand(argv[0])) { 230 case COMMAND_DUMP: 231 // display boot commands 232 DumpBootCommands(); 233 break; 234 235 case COMMAND_EXEC: 236 { 237 // "e <address>" 238 // execute at address 239 void (*execAddr)(unsigned, unsigned); 240 241 if (argc > 1) { 242 /* in future, include machtypes (MACH_KB9200 = 612) */ 243 execAddr = (void (*)(unsigned, unsigned)) 244 p_ASCIIToHex(argv[1]); 245 (*execAddr)(0, 612); 246 } 247 break; 248 } 249 250 case COMMAND_TFTP: 251 { 252 // "tftp <local_dest_addr filename>" 253 // tftp download 254 unsigned address = 0; 255 256 if (argc > 2) 257 address = p_ASCIIToHex(argv[1]); 258 TFTP_Download(address, argv[2]); 259 break; 260 } 261 262 case COMMAND_SERVER_IP: 263 // "server_ip <server IP 192 200 1 20>" 264 // set download server address 265 if (argc > 4) 266 SetServerIPAddress(BuildIP()); 267 break; 268 269 case COMMAND_LOCAL_IP: 270 // "local_ip <local IP 192 200 1 21> 271 // set ip of this module 272 if (argc > 4) 273 SetLocalIPAddress(BuildIP()); 274 break; 275 276 case COMMAND_MAC: 277 { 278 // "m <mac address 12 34 56 78 9a bc> 279 // set mac address using 6 byte values 280 unsigned char mac[6]; 281 282 if (argc > 6) { 283 for (i = 0; i < 6; i++) 284 mac[i] = p_ASCIIToHex(argv[i + 1]); 285 EMAC_SetMACAddress(mac); 286 } 287 break; 288 } 289 290 case COMMAND_LOAD_SPI_KERNEL: 291 // "k <address>" 292 if (argc > 1) 293 LoadKernelFromSpi((char *)p_ASCIIToHex(argv[1])); 294 break; 295 296 case COMMAND_XMODEM: 297 // "x <address>" 298 // download X-modem record at address 299 if (argc > 1) 300 xmodem_rx((char *)p_ASCIIToHex(argv[1])); 301 break; 302 303 case COMMAND_RESET: 304 printf("Reset\n"); 305 reset(); 306 while (1) continue; 307 break; 308 309 case COMMAND_REPLACE_KERNEL_VIA_XMODEM: 310 printf("Updating KERNEL image\n"); 311 UpdateFlash(KERNEL_OFFSET); 312 break; 313 case COMMAND_REPLACE_FPGA_VIA_XMODEM: 314 printf("Updating FPGA image\n"); 315 UpdateFlash(FPGA_OFFSET); 316 break; 317 case COMMAND_REPLACE_FLASH_VIA_XMODEM: 318 printf("Updating FLASH image\n"); 319 UpdateFlash(FLASH_OFFSET); 320 break; 321 322 case COMMAND_REPLACE_ID_EEPROM: 323 { 324 char buf[25]; 325 printf("Testing Config EEPROM\n"); 326 EEWrite(0, "This is a test", 15); 327 EERead(0, buf, 15); 328 printf("Found '%s'\n", buf); 329 break; 330 } 331 default: 332 break; 333 } 334 335 printf("\n"); 336} 337 338 339/* 340 * .KB_C_FN_DEFINITION_START 341 * void ServicePrompt(char) 342 * This private function process each character checking for valid commands. 343 * This function is only executed if the character is considered valid. 344 * Each command is terminated with NULL (0) or ''. 345 * .KB_C_FN_DEFINITION_END 346 */ 347static void 348ServicePrompt(char p_char) 349{ 350 if (p_char == '\r') 351 p_char = 0; 352 353 if (p_char == '\010') { 354 if (buffCount) { 355 /* handle backspace BS */ 356 inputBuffer[--buffCount] = 0; 357 printf(backspaceString); 358 } 359 return; 360 } 361 if (buffCount < MAX_INPUT_SIZE - 1) { 362 inputBuffer[buffCount++] = p_char; 363 putchar(p_char); 364 } 365 if (!p_char) { 366 printf("\n"); 367 ParseCommand(inputBuffer); 368 p_memset(inputBuffer, 0, MAX_INPUT_SIZE); 369 buffCount = 0; 370 printf("\n>"); 371 } 372} 373 374 375/* ************************** GLOBAL FUNCTIONS ********************************/ 376 377 378/* 379 * .KB_C_FN_DEFINITION_START 380 * void Bootloader(void *inputFunction) 381 * This global function is the entry point for the bootloader. If the 382 * inputFunction pointer is NULL, the loader input will be serviced from 383 * the uart. Otherwise, inputFunction is called to get characters which 384 * the loader will parse. 385 * .KB_C_FN_DEFINITION_END 386 */ 387void 388Bootloader(int(*inputFunction)(int)) 389{ 390 int ch = 0; 391 392 p_memset((void*)inputBuffer, 0, sizeof(inputBuffer)); 393 buffCount = 0; 394 395 printf("\n>"); 396 397 while (1) 398 if ((ch = ((*inputFunction)(0))) > 0) 399 ServicePrompt(ch); 400} 401