loader_prompt.c revision 163596
166458Sdfr/****************************************************************************** 266458Sdfr * 366458Sdfr * Filename: loader_prompt.c 466458Sdfr * 566458Sdfr * Instantiation of the interactive loader functions. 666458Sdfr * 766458Sdfr * Revision information: 866458Sdfr * 966458Sdfr * 20AUG2004 kb_admin initial creation 1066458Sdfr * 12JAN2005 kb_admin massive changes for tftp, strings, and more 1166458Sdfr * 05JUL2005 kb_admin save tag address, and set registers on boot 1266458Sdfr * 1366458Sdfr * BEGIN_KBDD_BLOCK 1466458Sdfr * No warranty, expressed or implied, is included with this software. It is 1566458Sdfr * provided "AS IS" and no warranty of any kind including statutory or aspects 1666458Sdfr * relating to merchantability or fitness for any purpose is provided. All 1766458Sdfr * intellectual property rights of others is maintained with the respective 1866458Sdfr * owners. This software is not copyrighted and is intended for reference 1966458Sdfr * only. 2066458Sdfr * END_BLOCK 2166458Sdfr * 2266458Sdfr * $FreeBSD: head/sys/boot/arm/at91/bootiic/loader_prompt.c 163596 2006-10-21 22:43:39Z imp $ 2366458Sdfr *****************************************************************************/ 2466458Sdfr 2566458Sdfr#include "at91rm9200_lowlevel.h" 2666458Sdfr#ifdef SUPPORT_TAG_LIST 2766458Sdfr#include "tag_list.h" 2866458Sdfr#endif 2966458Sdfr#include "emac.h" 3066458Sdfr#include "loader_prompt.h" 3166458Sdfr#include "env_vars.h" 3266458Sdfr#include "lib.h" 3366458Sdfr 3466458Sdfr 3583511Sdfr/******************************* GLOBALS *************************************/ 3696912Smarcel 3766458Sdfr 3893264Sdillon/*********************** PRIVATE FUNCTIONS/DATA ******************************/ 3988088Sjhb 40127253Smarcelstatic char inputBuffer[MAX_INPUT_SIZE]; 41127253Smarcelstatic int buffCount; 4266458Sdfr 4366458Sdfr// argv pointer are either NULL or point to locations in inputBuffer 4466458Sdfrstatic char *argv[MAX_COMMAND_PARAMS]; 4566458Sdfr 4666458Sdfrstatic const char *backspaceString = "\010 \010"; 47127253Smarcel 4866458Sdfrstatic const command_entry_t CommandTable[] = { 4966458Sdfr {COMMAND_COPY, "c"}, 50124478Sdes {COMMAND_DUMP, "d"}, 51123419Speter {COMMAND_EXEC, "e"}, 52123419Speter {COMMAND_HELP, "?"}, 53123419Speter {COMMAND_LOCAL_IP, "ip"}, 54123419Speter {COMMAND_MAC, "m"}, 55123419Speter {COMMAND_SERVER_IP, "server_ip"}, 56123419Speter {COMMAND_SET, "s"}, 57123419Speter#ifdef SUPPORT_TAG_LIST 5866458Sdfr {COMMAND_TAG, "t"}, 5966458Sdfr#endif 60114208Smarcel {COMMAND_TFTP, "tftp"}, 61114208Smarcel {COMMAND_WRITE, "w"}, 62114208Smarcel {COMMAND_XMODEM, "x"}, 63114208Smarcel {COMMAND_FINAL_FLAG, 0} 6483511Sdfr}; 65114208Smarcel 66114208Smarcelstatic unsigned tagAddress; 67114208Smarcel 68114208Smarcel/* 69114208Smarcel * .KB_C_FN_DEFINITION_START 7083511Sdfr * unsigned BuildIP(void) 71114208Smarcel * This private function packs the test IP info to an unsigned value. 72114208Smarcel * .KB_C_FN_DEFINITION_END 73114208Smarcel */ 7483511Sdfrstatic unsigned 75114208SmarcelBuildIP(void) 76114208Smarcel{ 77114208Smarcel return ((p_ASCIIToDec(argv[1]) << 24) | 78114208Smarcel (p_ASCIIToDec(argv[2]) << 16) | 7966458Sdfr (p_ASCIIToDec(argv[3]) << 8) | 8066458Sdfr p_ASCIIToDec(argv[4])); 81114208Smarcel} 82114208Smarcel 8366458Sdfr 84114208Smarcel/* 85114208Smarcel * .KB_C_FN_DEFINITION_START 86114208Smarcel * int StringToCommand(char *cPtr) 8783511Sdfr * This private function converts a command string to a command code. 88114208Smarcel * .KB_C_FN_DEFINITION_END 89114208Smarcel */ 90114208Smarcelstatic int 91114208SmarcelStringToCommand(char *cPtr) 9266458Sdfr{ 9366458Sdfr int i; 94114208Smarcel 95114208Smarcel for (i = 0; CommandTable[i].command != COMMAND_FINAL_FLAG; ++i) 9666458Sdfr if (!strcmp(CommandTable[i].c_string, cPtr)) 97114208Smarcel return (CommandTable[i].command); 98114208Smarcel 99114208Smarcel return (COMMAND_INVALID); 10083511Sdfr} 101114208Smarcel 102114208Smarcel 103114208Smarcel/* 104114208Smarcel * .KB_C_FN_DEFINITION_START 10566458Sdfr * void RestoreSpace(int) 10666458Sdfr * This private function restores NULL characters to spaces in order to 10766458Sdfr * process the remaining args as a string. The number passed is the argc 108114208Smarcel * of the first entry to begin restoring space in the inputBuffer. 10966458Sdfr * .KB_C_FN_DEFINITION_END 110114208Smarcel */ 11166458Sdfrstatic void 112114208SmarcelRestoreSpace(int startArgc) 11366458Sdfr{ 11466458Sdfr char *cPtr; 11566458Sdfr 116114208Smarcel for (startArgc++; startArgc < MAX_COMMAND_PARAMS; startArgc++) { 11766458Sdfr if ((cPtr = argv[startArgc])) 118114208Smarcel *(cPtr - 1) = ' '; 11966458Sdfr } 120114208Smarcel} 12166458Sdfr 12266458Sdfr 12366458Sdfr/* 124114208Smarcel * .KB_C_FN_DEFINITION_START 12566458Sdfr * int BreakCommand(char *) 126114208Smarcel * This private function splits the buffer into separate strings as pointed 12766458Sdfr * by argv and returns the number of parameters (< 0 on failure). 128114208Smarcel * .KB_C_FN_DEFINITION_END 12966458Sdfr */ 13066458Sdfrstatic int 13166458SdfrBreakCommand(char *buffer) 132114208Smarcel{ 13366458Sdfr int pCount, cCount, state; 134114208Smarcel 135114208Smarcel state = pCount = 0; 13683511Sdfr p_memset((char*)argv, 0, sizeof(argv)); 13783511Sdfr 138114208Smarcel for (cCount = 0; cCount < MAX_INPUT_SIZE; ++cCount) { 13983511Sdfr 14066458Sdfr if (!state) { 14166458Sdfr /* look for next command */ 14266458Sdfr if (!p_IsWhiteSpace(buffer[cCount])) { 143114208Smarcel argv[pCount++] = &buffer[cCount]; 14466458Sdfr state = 1; 145114208Smarcel } else { 146114208Smarcel buffer[cCount] = 0; 14783511Sdfr } 14883836Sdfr } else { 149114208Smarcel /* in command, find next white space */ 15083836Sdfr if (p_IsWhiteSpace(buffer[cCount])) { 15166458Sdfr buffer[cCount] = 0; 15266458Sdfr state = 0; 15366458Sdfr } 154114208Smarcel } 15566458Sdfr 156114208Smarcel if (pCount >= MAX_COMMAND_PARAMS) { 157114208Smarcel return (-1); 15883836Sdfr } 15983836Sdfr } 160114208Smarcel 16183836Sdfr return (pCount); 16266458Sdfr} 16366458Sdfr 16466458Sdfr 165114208Smarcel/* 16684581Smarcel * .KB_C_FN_DEFINITION_START 167114208Smarcel * void ParseCommand(char *) 16884581Smarcel * This private function executes matching functions. 169114208Smarcel * .KB_C_FN_DEFINITION_END 17084581Smarcel */ 17184581Smarcelstatic void 17284581SmarcelParseCommand(char *buffer) 173114208Smarcel{ 17484581Smarcel int argc, i; 175114208Smarcel 17684581Smarcel if ((argc = BreakCommand(buffer)) < 1) 177114208Smarcel return; 17884581Smarcel 17984581Smarcel switch (StringToCommand(argv[0])) { 18084581Smarcel case COMMAND_COPY: 181114208Smarcel { 18284581Smarcel // "c <to> <from> <size in bytes>" 183114208Smarcel // copy memory 18484581Smarcel char *to, *from; 185114208Smarcel unsigned size; 18684581Smarcel 18784581Smarcel if (argc > 3) { 18884581Smarcel to = (char *)p_ASCIIToHex(argv[1]); 18966458Sdfr from = (char *)p_ASCIIToHex(argv[2]); 19066458Sdfr size = p_ASCIIToHex(argv[3]); 191114208Smarcel memcpy(to, from, size); 19266458Sdfr } 19366458Sdfr break; 19466458Sdfr } 19566458Sdfr 19666458Sdfr case COMMAND_DUMP: 197114208Smarcel // display boot commands 19866458Sdfr DumpBootCommands(); 19966458Sdfr break; 20092870Sdfr 20192781Sdfr case COMMAND_EXEC: 20266458Sdfr { 20392870Sdfr // "e <address>" 204114208Smarcel // execute at address 20574897Sjhb void (*execAddr)(unsigned, unsigned, unsigned); 206115295Smarcel 20766458Sdfr if (argc > 1) { 20866458Sdfr /* in future, include machtypes (MACH_KB9200 = 612) */ 20966458Sdfr execAddr = (void (*)(unsigned, unsigned, unsigned)) 210115295Smarcel p_ASCIIToHex(argv[1]); 21166458Sdfr (*execAddr)(0, 612, tagAddress); 212115295Smarcel } 213115295Smarcel break; 21466458Sdfr } 21566458Sdfr 21666458Sdfr case COMMAND_TFTP: 21766458Sdfr { 21866458Sdfr // "tftp <local_dest_addr filename>" 219 // tftp download 220 unsigned address = 0; 221 222 if (argc > 2) 223 address = p_ASCIIToHex(argv[1]); 224 TFTP_Download(address, argv[2]); 225 break; 226 } 227 228 case COMMAND_SERVER_IP: 229 // "server_ip <server IP 192 200 1 20>" 230 // set download server address 231 if (argc > 4) 232 SetServerIPAddress(BuildIP()); 233 break; 234 235 case COMMAND_HELP: 236 // dump command info 237 printf("Commands:\n" 238 "\tc\n" 239 "\td\n" 240 "\te\n" 241 "\tip\n" 242 "\tserver_ip\n" 243 "\tm\n" 244 "\ttftp\n" 245 "\ts\n" 246#ifdef SUPPORT_TAG_LIST 247 "\tt\n" 248#endif 249 "\tw\n" 250 "\tx\n"); 251 break; 252 253 case COMMAND_LOCAL_IP: 254 // "local_ip <local IP 192 200 1 21> 255 // set ip of this module 256 if (argc > 4) 257 SetLocalIPAddress(BuildIP()); 258 break; 259 260 case COMMAND_MAC: 261 { 262 // "m <mac address 12 34 56 78 9a bc> 263 // set mac address using 6 byte values 264 unsigned char mac[6]; 265 266 if (argc > 6) { 267 for (i = 0; i < 6; i++) 268 mac[i] = p_ASCIIToHex(argv[i + 1]); 269 EMAC_SetMACAddress(mac); 270 } 271 break; 272 } 273 274 case COMMAND_SET: 275 { 276 // s <index> <new boot command> 277 // set the boot command at index (0-based) 278 unsigned index; 279 280 if (argc > 1) { 281 RestoreSpace(2); 282 index = p_ASCIIToHex(argv[1]); 283 SetBootCommand(index, argv[2]); 284 } 285 break; 286 } 287 288#ifdef SUPPORT_TAG_LIST 289 case COMMAND_TAG: 290 // t <address> <boot command line> 291 // create tag-list for linux boot 292 if (argc > 2) { 293 RestoreSpace(2); 294 tagAddress = p_ASCIIToHex(argv[1]); 295 InitTagList(argv[2], (void*)tagAddress); 296 } 297 break; 298#endif 299 300 case COMMAND_WRITE: 301 // write the command table to non-volatile 302 WriteCommandTable(); 303 break; 304 305 case COMMAND_XMODEM: 306 { 307 // "x <address>" 308 // download X-modem record at address 309 if (argc > 1) 310 xmodem_rx((char *)p_ASCIIToHex(argv[1])); 311 break; 312 } 313 314 default: 315 break; 316 } 317 318 printf("\n"); 319} 320 321 322/* 323 * .KB_C_FN_DEFINITION_START 324 * void ServicePrompt(char) 325 * This private function process each character checking for valid commands. 326 * This function is only executed if the character is considered valid. 327 * Each command is terminated with NULL (0) or ''. 328 * .KB_C_FN_DEFINITION_END 329 */ 330static void 331ServicePrompt(char p_char) 332{ 333 if (p_char == '\r') 334 p_char = 0; 335 336 if (p_char == '\010') { 337 if (buffCount) { 338 /* handle backspace BS */ 339 inputBuffer[--buffCount] = 0; 340 printf(backspaceString); 341 } 342 return; 343 } 344 if (buffCount < MAX_INPUT_SIZE - 1) { 345 inputBuffer[buffCount++] = p_char; 346 putchar(p_char); 347 } 348 if (!p_char) { 349 printf("\n"); 350 ParseCommand(inputBuffer); 351 p_memset(inputBuffer, 0, MAX_INPUT_SIZE); 352 buffCount = 0; 353 printf("\n>"); 354 } 355} 356 357 358/* ************************** GLOBAL FUNCTIONS ********************************/ 359 360 361/* 362 * .KB_C_FN_DEFINITION_START 363 * void Bootloader(void *inputFunction) 364 * This global function is the entry point for the bootloader. If the 365 * inputFunction pointer is NULL, the loader input will be serviced from 366 * the uart. Otherwise, inputFunction is called to get characters which 367 * the loader will parse. 368 * .KB_C_FN_DEFINITION_END 369 */ 370void 371Bootloader(int(*inputFunction)(int)) 372{ 373 int ch = 0; 374 375 p_memset((void*)inputBuffer, 0, sizeof(inputBuffer)); 376 377 buffCount = 0; 378 if (!inputFunction) { 379 inputFunction = getc; 380 } 381 382 printf("\n>"); 383 384 while (1) 385 if ((ch = ((*inputFunction)(0))) > 0) 386 ServicePrompt(ch); 387} 388