1/****************************************************************************** 2 * 3 * Filename: loader_prompt.c 4 * 5 * Instantiation of the interactive loader functions. 6 * 7 * Revision information: 8 * 9 * 20AUG2004 kb_admin initial creation 10 * 12JAN2005 kb_admin massive changes for tftp, strings, and more 11 * 05JUL2005 kb_admin save tag address, and set registers on boot 12 * 13 * BEGIN_KBDD_BLOCK 14 * No warranty, expressed or implied, is included with this software. It is 15 * provided "AS IS" and no warranty of any kind including statutory or aspects 16 * relating to merchantability or fitness for any purpose is provided. All 17 * intellectual property rights of others is maintained with the respective 18 * owners. This software is not copyrighted and is intended for reference 19 * only. 20 * END_BLOCK 21 * 22 * $FreeBSD: releng/10.2/sys/boot/arm/at91/bootiic/loader_prompt.c 163596 2006-10-21 22:43:39Z imp $ 23 *****************************************************************************/ 24 25#include "at91rm9200_lowlevel.h" 26#ifdef SUPPORT_TAG_LIST 27#include "tag_list.h" 28#endif 29#include "emac.h" 30#include "loader_prompt.h" 31#include "env_vars.h" 32#include "lib.h" 33 34 35/******************************* GLOBALS *************************************/ 36 37 38/*********************** PRIVATE FUNCTIONS/DATA ******************************/ 39 40static char inputBuffer[MAX_INPUT_SIZE]; 41static int buffCount; 42 43// argv pointer are either NULL or point to locations in inputBuffer 44static char *argv[MAX_COMMAND_PARAMS]; 45 46static const char *backspaceString = "\010 \010"; 47 48static const command_entry_t CommandTable[] = { 49 {COMMAND_COPY, "c"}, 50 {COMMAND_DUMP, "d"}, 51 {COMMAND_EXEC, "e"}, 52 {COMMAND_HELP, "?"}, 53 {COMMAND_LOCAL_IP, "ip"}, 54 {COMMAND_MAC, "m"}, 55 {COMMAND_SERVER_IP, "server_ip"}, 56 {COMMAND_SET, "s"}, 57#ifdef SUPPORT_TAG_LIST 58 {COMMAND_TAG, "t"}, 59#endif 60 {COMMAND_TFTP, "tftp"}, 61 {COMMAND_WRITE, "w"}, 62 {COMMAND_XMODEM, "x"}, 63 {COMMAND_FINAL_FLAG, 0} 64}; 65 66static unsigned tagAddress; 67 68/* 69 * .KB_C_FN_DEFINITION_START 70 * unsigned BuildIP(void) 71 * This private function packs the test IP info to an unsigned value. 72 * .KB_C_FN_DEFINITION_END 73 */ 74static unsigned 75BuildIP(void) 76{ 77 return ((p_ASCIIToDec(argv[1]) << 24) | 78 (p_ASCIIToDec(argv[2]) << 16) | 79 (p_ASCIIToDec(argv[3]) << 8) | 80 p_ASCIIToDec(argv[4])); 81} 82 83 84/* 85 * .KB_C_FN_DEFINITION_START 86 * int StringToCommand(char *cPtr) 87 * This private function converts a command string to a command code. 88 * .KB_C_FN_DEFINITION_END 89 */ 90static int 91StringToCommand(char *cPtr) 92{ 93 int i; 94 95 for (i = 0; CommandTable[i].command != COMMAND_FINAL_FLAG; ++i) 96 if (!strcmp(CommandTable[i].c_string, cPtr)) 97 return (CommandTable[i].command); 98 99 return (COMMAND_INVALID); 100} 101 102 103/* 104 * .KB_C_FN_DEFINITION_START 105 * void RestoreSpace(int) 106 * This private function restores NULL characters to spaces in order to 107 * process the remaining args as a string. The number passed is the argc 108 * of the first entry to begin restoring space in the inputBuffer. 109 * .KB_C_FN_DEFINITION_END 110 */ 111static void 112RestoreSpace(int startArgc) 113{ 114 char *cPtr; 115 116 for (startArgc++; startArgc < MAX_COMMAND_PARAMS; startArgc++) { 117 if ((cPtr = argv[startArgc])) 118 *(cPtr - 1) = ' '; 119 } 120} 121 122 123/* 124 * .KB_C_FN_DEFINITION_START 125 * int BreakCommand(char *) 126 * This private function splits the buffer into separate strings as pointed 127 * by argv and returns the number of parameters (< 0 on failure). 128 * .KB_C_FN_DEFINITION_END 129 */ 130static int 131BreakCommand(char *buffer) 132{ 133 int pCount, cCount, state; 134 135 state = pCount = 0; 136 p_memset((char*)argv, 0, sizeof(argv)); 137 138 for (cCount = 0; cCount < MAX_INPUT_SIZE; ++cCount) { 139 140 if (!state) { 141 /* look for next command */ 142 if (!p_IsWhiteSpace(buffer[cCount])) { 143 argv[pCount++] = &buffer[cCount]; 144 state = 1; 145 } else { 146 buffer[cCount] = 0; 147 } 148 } else { 149 /* in command, find next white space */ 150 if (p_IsWhiteSpace(buffer[cCount])) { 151 buffer[cCount] = 0; 152 state = 0; 153 } 154 } 155 156 if (pCount >= MAX_COMMAND_PARAMS) { 157 return (-1); 158 } 159 } 160 161 return (pCount); 162} 163 164 165/* 166 * .KB_C_FN_DEFINITION_START 167 * void ParseCommand(char *) 168 * This private function executes matching functions. 169 * .KB_C_FN_DEFINITION_END 170 */ 171static void 172ParseCommand(char *buffer) 173{ 174 int argc, i; 175 176 if ((argc = BreakCommand(buffer)) < 1) 177 return; 178 179 switch (StringToCommand(argv[0])) { 180 case COMMAND_COPY: 181 { 182 // "c <to> <from> <size in bytes>" 183 // copy memory 184 char *to, *from; 185 unsigned size; 186 187 if (argc > 3) { 188 to = (char *)p_ASCIIToHex(argv[1]); 189 from = (char *)p_ASCIIToHex(argv[2]); 190 size = p_ASCIIToHex(argv[3]); 191 memcpy(to, from, size); 192 } 193 break; 194 } 195 196 case COMMAND_DUMP: 197 // display boot commands 198 DumpBootCommands(); 199 break; 200 201 case COMMAND_EXEC: 202 { 203 // "e <address>" 204 // execute at address 205 void (*execAddr)(unsigned, unsigned, unsigned); 206 207 if (argc > 1) { 208 /* in future, include machtypes (MACH_KB9200 = 612) */ 209 execAddr = (void (*)(unsigned, unsigned, unsigned)) 210 p_ASCIIToHex(argv[1]); 211 (*execAddr)(0, 612, tagAddress); 212 } 213 break; 214 } 215 216 case COMMAND_TFTP: 217 { 218 // "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