]> CyberLeo.Net >> Repos - FreeBSD/releng/9.2.git/blob - sys/boot/arm/at91/bootiic/loader_prompt.c
- Copy stable/9 to releng/9.2 as part of the 9.2-RELEASE cycle.
[FreeBSD/releng/9.2.git] / sys / boot / arm / at91 / bootiic / loader_prompt.c
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$
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
40 static char     inputBuffer[MAX_INPUT_SIZE];
41 static int      buffCount;
42
43 // argv pointer are either NULL or point to locations in inputBuffer
44 static char     *argv[MAX_COMMAND_PARAMS];
45
46 static const char *backspaceString = "\010 \010";
47
48 static 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
66 static 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  */
74 static unsigned
75 BuildIP(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  */
90 static int
91 StringToCommand(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  */
111 static void
112 RestoreSpace(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  */
130 static int
131 BreakCommand(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  */
171 static void
172 ParseCommand(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  */
330 static void
331 ServicePrompt(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  */
370 void
371 Bootloader(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 }