]> CyberLeo.Net >> Repos - FreeBSD/releng/10.0.git/blob - sys/boot/arm/at91/bootspi/loader_prompt.c
- Copy stable/10 (r259064) to releng/10.0 as part of the
[FreeBSD/releng/10.0.git] / sys / boot / arm / at91 / bootspi / 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 #include "at91rm9200.h"
27 #include "emac.h"
28 #include "loader_prompt.h"
29 #include "env_vars.h"
30 #include "lib.h"
31 #include "spi_flash.h"
32 #include "ee.h"
33
34 /******************************* GLOBALS *************************************/
35
36
37 /*********************** PRIVATE FUNCTIONS/DATA ******************************/
38
39 static char     inputBuffer[MAX_INPUT_SIZE];
40 static int      buffCount;
41
42 // argv pointer are either NULL or point to locations in inputBuffer
43 static char     *argv[MAX_COMMAND_PARAMS];
44
45 #define FLASH_OFFSET (0 * FLASH_PAGE_SIZE)
46 #define KERNEL_OFFSET (220 * FLASH_PAGE_SIZE)
47 #define KERNEL_LEN (6 * 1024 * FLASH_PAGE_SIZE)
48 static const char *backspaceString = "\010 \010";
49
50 static const command_entry_t    CommandTable[] = {
51         {COMMAND_DUMP, "d"},
52         {COMMAND_EXEC, "e"},
53         {COMMAND_LOCAL_IP, "ip"},
54         {COMMAND_MAC, "m"},
55         {COMMAND_SERVER_IP, "server_ip"},
56         {COMMAND_TFTP, "tftp"},
57         {COMMAND_XMODEM, "x"},
58         {COMMAND_RESET, "R"},
59         {COMMAND_LOAD_SPI_KERNEL, "k"},
60         {COMMAND_REPLACE_KERNEL_VIA_XMODEM, "K"},
61         {COMMAND_REPLACE_FLASH_VIA_XMODEM, "I"},
62         {COMMAND_REPLACE_ID_EEPROM, "E"},
63         {COMMAND_FINAL_FLAG, 0}
64 };
65
66 /*
67  * .KB_C_FN_DEFINITION_START
68  * unsigned BuildIP(void)
69  *  This private function packs the test IP info to an unsigned value.
70  * .KB_C_FN_DEFINITION_END
71  */
72 static unsigned
73 BuildIP(void)
74 {
75         return ((p_ASCIIToDec(argv[1]) << 24) |
76             (p_ASCIIToDec(argv[2]) << 16) |
77             (p_ASCIIToDec(argv[3]) << 8) |
78             p_ASCIIToDec(argv[4]));
79 }
80
81
82 /*
83  * .KB_C_FN_DEFINITION_START
84  * int StringToCommand(char *cPtr)
85  *  This private function converts a command string to a command code.
86  * .KB_C_FN_DEFINITION_END
87  */
88 static int
89 StringToCommand(char *cPtr)
90 {
91         int     i;
92
93         for (i = 0; CommandTable[i].command != COMMAND_FINAL_FLAG; ++i)
94                 if (!strcmp(CommandTable[i].c_string, cPtr))
95                         return (CommandTable[i].command);
96
97         return (COMMAND_INVALID);
98 }
99
100
101 /*
102  * .KB_C_FN_DEFINITION_START
103  * int BreakCommand(char *)
104  *  This private function splits the buffer into separate strings as pointed
105  * by argv and returns the number of parameters (< 0 on failure).
106  * .KB_C_FN_DEFINITION_END
107  */
108 static int
109 BreakCommand(char *buffer)
110 {
111         int     pCount, cCount, state;
112
113         state = pCount = 0;
114         p_memset((char*)argv, 0, sizeof(argv));
115
116         for (cCount = 0; cCount < MAX_INPUT_SIZE; ++cCount) {
117
118                 if (!state) {
119                         /* look for next command */
120                         if (!p_IsWhiteSpace(buffer[cCount])) {
121                                 argv[pCount++] = &buffer[cCount];
122                                 state = 1;
123                         } else {
124                                 buffer[cCount] = 0;
125                         }
126                 } else {
127                         /* in command, find next white space */
128                         if (p_IsWhiteSpace(buffer[cCount])) {
129                                 buffer[cCount] = 0;
130                                 state = 0;
131                         }
132                 }
133
134                 if (pCount >= MAX_COMMAND_PARAMS) {
135                         return (-1);
136                 }
137         }
138
139         return (pCount);
140 }
141
142 #if 0
143 static void
144 UpdateEEProm(int eeaddr)
145 {
146         char *addr = (char *)SDRAM_BASE + (1 << 20); /* Load to base + 1MB */
147         int len;
148
149         while ((len = xmodem_rx(addr)) == -1)
150                 continue;
151         printf("\nDownloaded %u bytes.\n", len);
152         WriteEEPROM(eeaddr, 0, addr, len);
153 }
154 #endif
155
156 static void
157 UpdateFlash(int offset)
158 {
159         char *addr = (char *)SDRAM_BASE + (1 << 20); /* Load to base + 1MB */
160         int len, i, off;
161
162         while ((len = xmodem_rx(addr)) == -1)
163                 continue;
164         printf("\nDownloaded %u bytes.\n", len);
165         for (i = 0; i < len; i+= FLASH_PAGE_SIZE) {
166                 off = i + offset;
167                 SPI_WriteFlash(off, addr + i, FLASH_PAGE_SIZE);
168         }
169 }
170
171 static void
172 LoadKernelFromSpi(char *addr)
173 {
174         int i, off;
175
176         for (i = 0; i < KERNEL_LEN; i+= FLASH_PAGE_SIZE) {
177                 off = i + KERNEL_OFFSET;
178                 SPI_ReadFlash(off, addr + i, FLASH_PAGE_SIZE);
179         }
180 }
181
182 /*
183  * .KB_C_FN_DEFINITION_START
184  * void ParseCommand(char *)
185  *  This private function executes matching functions.
186  * .KB_C_FN_DEFINITION_END
187  */
188 static void
189 ParseCommand(char *buffer)
190 {
191         int             argc, i;
192
193         if ((argc = BreakCommand(buffer)) < 1)
194                 return;
195
196         switch (StringToCommand(argv[0])) {
197         case COMMAND_DUMP:
198                 // display boot commands
199                 DumpBootCommands();
200                 break;
201
202         case COMMAND_EXEC:
203         {
204                 // "e <address>"
205                 // execute at address
206                 void (*execAddr)(unsigned, unsigned);
207
208                 if (argc > 1) {
209                         /* in future, include machtypes (MACH_KB9200 = 612) */
210                         execAddr = (void (*)(unsigned, unsigned))
211                             p_ASCIIToHex(argv[1]);
212                         (*execAddr)(0, 612);
213                 }
214                 break;
215         }
216
217         case COMMAND_TFTP:
218         {
219                 // "tftp <local_dest_addr filename>"
220                 //  tftp download
221                 unsigned address = 0;
222
223                 if (argc > 2)
224                         address = p_ASCIIToHex(argv[1]);
225                 TFTP_Download(address, argv[2]);
226                 break;
227         }
228
229         case COMMAND_SERVER_IP:
230                 // "server_ip <server IP 192 200 1 20>"
231                 // set download server address
232                 if (argc > 4)
233                         SetServerIPAddress(BuildIP());
234                 break;
235
236         case COMMAND_LOCAL_IP:
237                 // "local_ip <local IP 192 200 1 21>
238                 // set ip of this module
239                 if (argc > 4)
240                         SetLocalIPAddress(BuildIP());
241                 break;
242
243         case COMMAND_MAC:
244         {
245                 // "m <mac address 12 34 56 78 9a bc>
246                 // set mac address using 6 byte values
247                 unsigned char mac[6];
248
249                 if (argc > 6) {
250                         for (i = 0; i < 6; i++)
251                                 mac[i] = p_ASCIIToHex(argv[i + 1]);
252                         EMAC_SetMACAddress(mac);
253                 }
254                 break;
255         }
256
257         case COMMAND_LOAD_SPI_KERNEL:
258                 // "k <address>"
259                 if (argc > 1)
260                         LoadKernelFromSpi((char *)p_ASCIIToHex(argv[1]));
261                 break;
262
263         case COMMAND_XMODEM:
264                 // "x <address>"
265                 // download X-modem record at address
266                 if (argc > 1)
267                         xmodem_rx((char *)p_ASCIIToHex(argv[1]));
268                 break;
269
270         case COMMAND_RESET:
271                 printf("Reset\n");
272                 reset();
273                 while (1) continue;
274                 break;
275
276         case COMMAND_REPLACE_KERNEL_VIA_XMODEM:
277                 printf("Updating KERNEL image\n");
278                 UpdateFlash(KERNEL_OFFSET);
279                 break;
280         case COMMAND_REPLACE_FLASH_VIA_XMODEM: 
281                 printf("Updating FLASH image\n");
282                 UpdateFlash(FLASH_OFFSET);
283                 break;
284
285         case COMMAND_REPLACE_ID_EEPROM: 
286         {
287             char buf[25];
288                 printf("Testing Config EEPROM\n");
289                 EEWrite(0, "This is a test", 15);
290                 EERead(0, buf, 15);
291                 printf("Found '%s'\n", buf);
292                 break;
293         }
294         default:
295                 break;
296         }
297
298         printf("\n");
299 }
300
301
302 /*
303  * .KB_C_FN_DEFINITION_START
304  * void ServicePrompt(char)
305  *  This private function process each character checking for valid commands.
306  * This function is only executed if the character is considered valid.
307  * Each command is terminated with NULL (0) or ''.
308  * .KB_C_FN_DEFINITION_END
309  */
310 static void
311 ServicePrompt(char p_char)
312 {
313         if (p_char == '\r')
314                 p_char = 0;
315
316         if (p_char == '\010') {
317                 if (buffCount) {
318                         /* handle backspace BS */
319                         inputBuffer[--buffCount] = 0;
320                         printf(backspaceString);
321                 }
322                 return;
323         }
324         if (buffCount < MAX_INPUT_SIZE - 1) {
325                 inputBuffer[buffCount++] = p_char;
326                 putchar(p_char);
327         }
328         if (!p_char) {
329                 printf("\n");
330                 ParseCommand(inputBuffer);
331                 p_memset(inputBuffer, 0, MAX_INPUT_SIZE);
332                 buffCount = 0;
333                 printf("\n>");
334         }
335 }
336
337
338 /* ************************** GLOBAL FUNCTIONS ********************************/
339
340
341 /*
342  * .KB_C_FN_DEFINITION_START
343  * void Bootloader(void *inputFunction)
344  *  This global function is the entry point for the bootloader.  If the
345  * inputFunction pointer is NULL, the loader input will be serviced from
346  * the uart.  Otherwise, inputFunction is called to get characters which
347  * the loader will parse.
348  * .KB_C_FN_DEFINITION_END
349  */
350 void
351 Bootloader(int(*inputFunction)(int))
352 {
353         int     ch = 0;
354
355         p_memset((void*)inputBuffer, 0, sizeof(inputBuffer));
356         buffCount = 0;
357
358         printf("\n>");
359
360         while (1)
361                 if ((ch = ((*inputFunction)(0))) > 0)
362                         ServicePrompt(ch);
363 }