151973Smsmith/****************************************************************************** 251973Smsmith * 351973Smsmith * Filename: loader_prompt.c 451973Smsmith * 551973Smsmith * Instantiation of the interactive loader functions. 651973Smsmith * 751973Smsmith * Revision information: 851973Smsmith * 951973Smsmith * 20AUG2004 kb_admin initial creation 1051973Smsmith * 12JAN2005 kb_admin massive changes for tftp, strings, and more 1151973Smsmith * 05JUL2005 kb_admin save tag address, and set registers on boot 1251973Smsmith * 1351973Smsmith * BEGIN_KBDD_BLOCK 1451973Smsmith * No warranty, expressed or implied, is included with this software. It is 1551973Smsmith * provided "AS IS" and no warranty of any kind including statutory or aspects 1651973Smsmith * relating to merchantability or fitness for any purpose is provided. All 1751973Smsmith * intellectual property rights of others is maintained with the respective 1851973Smsmith * owners. This software is not copyrighted and is intended for reference 1951973Smsmith * only. 2051973Smsmith * END_BLOCK 2151973Smsmith * 2251973Smsmith * $FreeBSD: releng/10.2/sys/boot/arm/at91/bootiic/loader_prompt.c 163596 2006-10-21 22:43:39Z imp $ 2351973Smsmith *****************************************************************************/ 2451973Smsmith 2551973Smsmith#include "at91rm9200_lowlevel.h" 2651973Smsmith#ifdef SUPPORT_TAG_LIST 27119418Sobrien#include "tag_list.h" 28119418Sobrien#endif 29119418Sobrien#include "emac.h" 3051973Smsmith#include "loader_prompt.h" 3151973Smsmith#include "env_vars.h" 32240963Sjhb#include "lib.h" 3351973Smsmith 34240608Sjhb 35129879Sphk/******************************* GLOBALS *************************************/ 36240608Sjhb 37240608Sjhb 3851973Smsmith/*********************** PRIVATE FUNCTIONS/DATA ******************************/ 3951973Smsmith 4051973Smsmithstatic char inputBuffer[MAX_INPUT_SIZE]; 4151973Smsmithstatic int buffCount; 4251973Smsmith 4351973Smsmith// argv pointer are either NULL or point to locations in inputBuffer 4451973Smsmithstatic char *argv[MAX_COMMAND_PARAMS]; 4551973Smsmith 46112946Sphkstatic const char *backspaceString = "\010 \010"; 47112946Sphk 48119285Simpstatic const command_entry_t CommandTable[] = { 49119285Simp {COMMAND_COPY, "c"}, 5051973Smsmith {COMMAND_DUMP, "d"}, 5151973Smsmith {COMMAND_EXEC, "e"}, 5251973Smsmith {COMMAND_HELP, "?"}, 5352544Smsmith {COMMAND_LOCAL_IP, "ip"}, 5451973Smsmith {COMMAND_MAC, "m"}, 5551973Smsmith {COMMAND_SERVER_IP, "server_ip"}, 5651973Smsmith {COMMAND_SET, "s"}, 5751973Smsmith#ifdef SUPPORT_TAG_LIST 5851973Smsmith {COMMAND_TAG, "t"}, 5951973Smsmith#endif 6051973Smsmith {COMMAND_TFTP, "tftp"}, 6151973Smsmith {COMMAND_WRITE, "w"}, 6251973Smsmith {COMMAND_XMODEM, "x"}, 6351973Smsmith {COMMAND_FINAL_FLAG, 0} 6451973Smsmith}; 6551973Smsmith 6651973Smsmithstatic unsigned tagAddress; 67227843Smarius 6851973Smsmith/* 6951973Smsmith * .KB_C_FN_DEFINITION_START 7051973Smsmith * unsigned BuildIP(void) 7151973Smsmith * This private function packs the test IP info to an unsigned value. 7251973Smsmith * .KB_C_FN_DEFINITION_END 7351973Smsmith */ 7451973Smsmithstatic unsigned 7551973SmsmithBuildIP(void) 7651973Smsmith{ 7751973Smsmith return ((p_ASCIIToDec(argv[1]) << 24) | 7854419Smsmith (p_ASCIIToDec(argv[2]) << 16) | 7951973Smsmith (p_ASCIIToDec(argv[3]) << 8) | 8051973Smsmith p_ASCIIToDec(argv[4])); 8151973Smsmith} 8254419Smsmith 8354419Smsmith 8451973Smsmith/* 8551973Smsmith * .KB_C_FN_DEFINITION_START 8651973Smsmith * int StringToCommand(char *cPtr) 8758188Smsmith * This private function converts a command string to a command code. 8854419Smsmith * .KB_C_FN_DEFINITION_END 8954419Smsmith */ 9054419Smsmithstatic int 9154419SmsmithStringToCommand(char *cPtr) 9251973Smsmith{ 9351973Smsmith int i; 94240608Sjhb 95240608Sjhb for (i = 0; CommandTable[i].command != COMMAND_FINAL_FLAG; ++i) 96240608Sjhb if (!strcmp(CommandTable[i].c_string, cPtr)) 97240608Sjhb return (CommandTable[i].command); 98240608Sjhb 99240608Sjhb return (COMMAND_INVALID); 100240608Sjhb} 101240608Sjhb 102240608Sjhb 103240608Sjhb/* 104240608Sjhb * .KB_C_FN_DEFINITION_START 105240608Sjhb * void RestoreSpace(int) 106240608Sjhb * This private function restores NULL characters to spaces in order to 107240608Sjhb * process the remaining args as a string. The number passed is the argc 108240608Sjhb * of the first entry to begin restoring space in the inputBuffer. 10951973Smsmith * .KB_C_FN_DEFINITION_END 11051973Smsmith */ 11151973Smsmithstatic void 11254419SmsmithRestoreSpace(int startArgc) 11351973Smsmith{ 11458188Smsmith char *cPtr; 11551973Smsmith 116240608Sjhb for (startArgc++; startArgc < MAX_COMMAND_PARAMS; startArgc++) { 117240608Sjhb if ((cPtr = argv[startArgc])) 118240608Sjhb *(cPtr - 1) = ' '; 119240608Sjhb } 12051973Smsmith} 12151973Smsmith 12251973Smsmith 12351973Smsmith/* 12451973Smsmith * .KB_C_FN_DEFINITION_START 12551973Smsmith * int BreakCommand(char *) 12651973Smsmith * This private function splits the buffer into separate strings as pointed 12751973Smsmith * by argv and returns the number of parameters (< 0 on failure). 128240608Sjhb * .KB_C_FN_DEFINITION_END 129240608Sjhb */ 13051973Smsmithstatic int 13158188SmsmithBreakCommand(char *buffer) 13251973Smsmith{ 133240608Sjhb int pCount, cCount, state; 13451973Smsmith 13551973Smsmith state = pCount = 0; 13651973Smsmith p_memset((char*)argv, 0, sizeof(argv)); 13751973Smsmith 13851973Smsmith for (cCount = 0; cCount < MAX_INPUT_SIZE; ++cCount) { 13951973Smsmith 14051973Smsmith if (!state) { 14151973Smsmith /* look for next command */ 142240608Sjhb if (!p_IsWhiteSpace(buffer[cCount])) { 143240608Sjhb argv[pCount++] = &buffer[cCount]; 14451973Smsmith state = 1; 145240608Sjhb } else { 146240608Sjhb buffer[cCount] = 0; 147240608Sjhb } 148240608Sjhb } else { 149240608Sjhb /* in command, find next white space */ 150240608Sjhb if (p_IsWhiteSpace(buffer[cCount])) { 15151973Smsmith buffer[cCount] = 0; 15251973Smsmith state = 0; 15351973Smsmith } 15451973Smsmith } 15564223Smsmith 15658188Smsmith if (pCount >= MAX_COMMAND_PARAMS) { 15758188Smsmith return (-1); 15858188Smsmith } 15969292Smdodd } 16069292Smdodd 161127135Snjl return (pCount); 162127135Snjl} 16364223Smsmith 16469292Smdodd 16569292Smdodd/* 166127135Snjl * .KB_C_FN_DEFINITION_START 167127135Snjl * void ParseCommand(char *) 16864223Smsmith * This private function executes matching functions. 16958188Smsmith * .KB_C_FN_DEFINITION_END 17058188Smsmith */ 17158188Smsmithstatic void 17269292SmdoddParseCommand(char *buffer) 17369292Smdodd{ 174127135Snjl int argc, i; 175127135Snjl 17658188Smsmith if ((argc = BreakCommand(buffer)) < 1) 17758188Smsmith return; 17851973Smsmith 17951973Smsmith switch (StringToCommand(argv[0])) { 18051973Smsmith case COMMAND_COPY: 18151973Smsmith { 18251973Smsmith // "c <to> <from> <size in bytes>" 18351973Smsmith // copy memory 18451973Smsmith char *to, *from; 18551973Smsmith unsigned size; 18651973Smsmith 187232854Sscottl if (argc > 3) { 18851973Smsmith to = (char *)p_ASCIIToHex(argv[1]); 18951973Smsmith from = (char *)p_ASCIIToHex(argv[2]); 19051973Smsmith size = p_ASCIIToHex(argv[3]); 19151973Smsmith memcpy(to, from, size); 19260074Smsmith } 19351973Smsmith break; 19451973Smsmith } 195117126Sscottl 196117126Sscottl case COMMAND_DUMP: 19751973Smsmith // display boot commands 19851973Smsmith DumpBootCommands(); 19951973Smsmith break; 20051973Smsmith 20151973Smsmith case COMMAND_EXEC: 20251973Smsmith { 20351973Smsmith // "e <address>" 20451973Smsmith // execute at address 20551973Smsmith void (*execAddr)(unsigned, unsigned, unsigned); 20651973Smsmith 20751973Smsmith if (argc > 1) { 208148570Scsjp /* in future, include machtypes (MACH_KB9200 = 612) */ 209144161Sphk execAddr = (void (*)(unsigned, unsigned, unsigned)) 21051973Smsmith p_ASCIIToHex(argv[1]); 211148570Scsjp (*execAddr)(0, 612, tagAddress); 21251973Smsmith } 21351973Smsmith break; 21451973Smsmith } 21551973Smsmith 21651973Smsmith case COMMAND_TFTP: 21751973Smsmith { 21851973Smsmith // "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