1161370Simp/******************************************************************************
2161370Simp *
3161370Simp * Filename: loader_prompt.c
4161370Simp *
5161370Simp * Instantiation of the interactive loader functions.
6161370Simp *
7161370Simp * Revision information:
8161370Simp *
9161370Simp * 20AUG2004	kb_admin	initial creation
10161370Simp * 12JAN2005	kb_admin	massive changes for tftp, strings, and more
11161370Simp * 05JUL2005	kb_admin	save tag address, and set registers on boot
12161370Simp *
13161370Simp * BEGIN_KBDD_BLOCK
14161370Simp * No warranty, expressed or implied, is included with this software.  It is
15161370Simp * provided "AS IS" and no warranty of any kind including statutory or aspects
16161370Simp * relating to merchantability or fitness for any purpose is provided.  All
17161370Simp * intellectual property rights of others is maintained with the respective
18161370Simp * owners.  This software is not copyrighted and is intended for reference
19161370Simp * only.
20161370Simp * END_BLOCK
21161370Simp *
22161370Simp * $FreeBSD: releng/10.2/sys/boot/arm/at91/bootspi/loader_prompt.c 167586 2007-03-15 03:31:49Z imp $
23161370Simp *****************************************************************************/
24161370Simp
25161370Simp#include "at91rm9200_lowlevel.h"
26161370Simp#include "at91rm9200.h"
27161370Simp#include "emac.h"
28161370Simp#include "loader_prompt.h"
29161370Simp#include "env_vars.h"
30161370Simp#include "lib.h"
31161370Simp#include "spi_flash.h"
32163597Simp#include "ee.h"
33161370Simp
34161370Simp/******************************* GLOBALS *************************************/
35161370Simp
36161370Simp
37161370Simp/*********************** PRIVATE FUNCTIONS/DATA ******************************/
38161370Simp
39161370Simpstatic char	inputBuffer[MAX_INPUT_SIZE];
40161370Simpstatic int	buffCount;
41161370Simp
42161370Simp// argv pointer are either NULL or point to locations in inputBuffer
43161370Simpstatic char	*argv[MAX_COMMAND_PARAMS];
44161370Simp
45161370Simp#define FLASH_OFFSET (0 * FLASH_PAGE_SIZE)
46161370Simp#define KERNEL_OFFSET (220 * FLASH_PAGE_SIZE)
47161370Simp#define KERNEL_LEN (6 * 1024 * FLASH_PAGE_SIZE)
48161370Simpstatic const char *backspaceString = "\010 \010";
49161370Simp
50161370Simpstatic const command_entry_t	CommandTable[] = {
51161370Simp	{COMMAND_DUMP, "d"},
52161370Simp	{COMMAND_EXEC, "e"},
53161370Simp	{COMMAND_LOCAL_IP, "ip"},
54161370Simp	{COMMAND_MAC, "m"},
55161370Simp	{COMMAND_SERVER_IP, "server_ip"},
56161370Simp	{COMMAND_TFTP, "tftp"},
57161370Simp	{COMMAND_XMODEM, "x"},
58161370Simp	{COMMAND_RESET, "R"},
59161370Simp	{COMMAND_LOAD_SPI_KERNEL, "k"},
60161370Simp	{COMMAND_REPLACE_KERNEL_VIA_XMODEM, "K"},
61161370Simp	{COMMAND_REPLACE_FLASH_VIA_XMODEM, "I"},
62161370Simp	{COMMAND_REPLACE_ID_EEPROM, "E"},
63161370Simp	{COMMAND_FINAL_FLAG, 0}
64161370Simp};
65161370Simp
66161370Simp/*
67161370Simp * .KB_C_FN_DEFINITION_START
68161370Simp * unsigned BuildIP(void)
69161370Simp *  This private function packs the test IP info to an unsigned value.
70161370Simp * .KB_C_FN_DEFINITION_END
71161370Simp */
72161370Simpstatic unsigned
73161370SimpBuildIP(void)
74161370Simp{
75161370Simp	return ((p_ASCIIToDec(argv[1]) << 24) |
76161370Simp	    (p_ASCIIToDec(argv[2]) << 16) |
77161370Simp	    (p_ASCIIToDec(argv[3]) << 8) |
78161370Simp	    p_ASCIIToDec(argv[4]));
79161370Simp}
80161370Simp
81161370Simp
82161370Simp/*
83161370Simp * .KB_C_FN_DEFINITION_START
84161370Simp * int StringToCommand(char *cPtr)
85161370Simp *  This private function converts a command string to a command code.
86161370Simp * .KB_C_FN_DEFINITION_END
87161370Simp */
88161370Simpstatic int
89161370SimpStringToCommand(char *cPtr)
90161370Simp{
91161370Simp	int	i;
92161370Simp
93161370Simp	for (i = 0; CommandTable[i].command != COMMAND_FINAL_FLAG; ++i)
94163597Simp		if (!strcmp(CommandTable[i].c_string, cPtr))
95161370Simp			return (CommandTable[i].command);
96161370Simp
97161370Simp	return (COMMAND_INVALID);
98161370Simp}
99161370Simp
100161370Simp
101161370Simp/*
102161370Simp * .KB_C_FN_DEFINITION_START
103161370Simp * int BreakCommand(char *)
104161370Simp *  This private function splits the buffer into separate strings as pointed
105161370Simp * by argv and returns the number of parameters (< 0 on failure).
106161370Simp * .KB_C_FN_DEFINITION_END
107161370Simp */
108161370Simpstatic int
109161370SimpBreakCommand(char *buffer)
110161370Simp{
111161370Simp	int	pCount, cCount, state;
112161370Simp
113161370Simp	state = pCount = 0;
114161370Simp	p_memset((char*)argv, 0, sizeof(argv));
115161370Simp
116161370Simp	for (cCount = 0; cCount < MAX_INPUT_SIZE; ++cCount) {
117161370Simp
118161370Simp		if (!state) {
119161370Simp			/* look for next command */
120161370Simp			if (!p_IsWhiteSpace(buffer[cCount])) {
121161370Simp				argv[pCount++] = &buffer[cCount];
122161370Simp				state = 1;
123161370Simp			} else {
124161370Simp				buffer[cCount] = 0;
125161370Simp			}
126161370Simp		} else {
127161370Simp			/* in command, find next white space */
128161370Simp			if (p_IsWhiteSpace(buffer[cCount])) {
129161370Simp				buffer[cCount] = 0;
130161370Simp				state = 0;
131161370Simp			}
132161370Simp		}
133161370Simp
134161370Simp		if (pCount >= MAX_COMMAND_PARAMS) {
135161370Simp			return (-1);
136161370Simp		}
137161370Simp	}
138161370Simp
139161370Simp	return (pCount);
140161370Simp}
141161370Simp
142161370Simp#if 0
143161370Simpstatic void
144161370SimpUpdateEEProm(int eeaddr)
145161370Simp{
146161370Simp	char *addr = (char *)SDRAM_BASE + (1 << 20); /* Load to base + 1MB */
147161370Simp	int len;
148161370Simp
149161370Simp	while ((len = xmodem_rx(addr)) == -1)
150161370Simp		continue;
151163597Simp	printf("\nDownloaded %u bytes.\n", len);
152161370Simp	WriteEEPROM(eeaddr, 0, addr, len);
153161370Simp}
154161370Simp#endif
155161370Simp
156161370Simpstatic void
157161370SimpUpdateFlash(int offset)
158161370Simp{
159161370Simp	char *addr = (char *)SDRAM_BASE + (1 << 20); /* Load to base + 1MB */
160161370Simp	int len, i, off;
161161370Simp
162161370Simp	while ((len = xmodem_rx(addr)) == -1)
163161370Simp		continue;
164163597Simp	printf("\nDownloaded %u bytes.\n", len);
165161370Simp	for (i = 0; i < len; i+= FLASH_PAGE_SIZE) {
166161370Simp		off = i + offset;
167161370Simp		SPI_WriteFlash(off, addr + i, FLASH_PAGE_SIZE);
168161370Simp	}
169161370Simp}
170161370Simp
171161370Simpstatic void
172161370SimpLoadKernelFromSpi(char *addr)
173161370Simp{
174161370Simp	int i, off;
175161370Simp
176161370Simp	for (i = 0; i < KERNEL_LEN; i+= FLASH_PAGE_SIZE) {
177161370Simp		off = i + KERNEL_OFFSET;
178161370Simp		SPI_ReadFlash(off, addr + i, FLASH_PAGE_SIZE);
179161370Simp	}
180161370Simp}
181161370Simp
182161370Simp/*
183161370Simp * .KB_C_FN_DEFINITION_START
184161370Simp * void ParseCommand(char *)
185161370Simp *  This private function executes matching functions.
186161370Simp * .KB_C_FN_DEFINITION_END
187161370Simp */
188161370Simpstatic void
189161370SimpParseCommand(char *buffer)
190161370Simp{
191161370Simp	int		argc, i;
192161370Simp
193161370Simp	if ((argc = BreakCommand(buffer)) < 1)
194161370Simp		return;
195161370Simp
196161370Simp	switch (StringToCommand(argv[0])) {
197161370Simp	case COMMAND_DUMP:
198161370Simp		// display boot commands
199161370Simp		DumpBootCommands();
200161370Simp		break;
201161370Simp
202161370Simp	case COMMAND_EXEC:
203161370Simp	{
204161370Simp		// "e <address>"
205161370Simp		// execute at address
206161370Simp		void (*execAddr)(unsigned, unsigned);
207161370Simp
208161370Simp		if (argc > 1) {
209161370Simp			/* in future, include machtypes (MACH_KB9200 = 612) */
210161370Simp			execAddr = (void (*)(unsigned, unsigned))
211161370Simp			    p_ASCIIToHex(argv[1]);
212161370Simp			(*execAddr)(0, 612);
213161370Simp		}
214161370Simp		break;
215161370Simp	}
216161370Simp
217161370Simp	case COMMAND_TFTP:
218161370Simp	{
219161370Simp		// "tftp <local_dest_addr filename>"
220161370Simp		//  tftp download
221161370Simp		unsigned address = 0;
222161370Simp
223161370Simp		if (argc > 2)
224161370Simp			address = p_ASCIIToHex(argv[1]);
225161370Simp		TFTP_Download(address, argv[2]);
226161370Simp		break;
227161370Simp	}
228161370Simp
229161370Simp	case COMMAND_SERVER_IP:
230161370Simp		// "server_ip <server IP 192 200 1 20>"
231161370Simp		// set download server address
232161370Simp		if (argc > 4)
233161370Simp			SetServerIPAddress(BuildIP());
234161370Simp		break;
235161370Simp
236161370Simp	case COMMAND_LOCAL_IP:
237161370Simp		// "local_ip <local IP 192 200 1 21>
238161370Simp		// set ip of this module
239161370Simp		if (argc > 4)
240161370Simp			SetLocalIPAddress(BuildIP());
241161370Simp		break;
242161370Simp
243161370Simp	case COMMAND_MAC:
244161370Simp	{
245161370Simp		// "m <mac address 12 34 56 78 9a bc>
246161370Simp		// set mac address using 6 byte values
247161370Simp		unsigned char mac[6];
248161370Simp
249161370Simp		if (argc > 6) {
250161370Simp			for (i = 0; i < 6; i++)
251161370Simp				mac[i] = p_ASCIIToHex(argv[i + 1]);
252161370Simp			EMAC_SetMACAddress(mac);
253161370Simp		}
254161370Simp		break;
255161370Simp	}
256161370Simp
257161370Simp	case COMMAND_LOAD_SPI_KERNEL:
258161370Simp		// "k <address>"
259161370Simp		if (argc > 1)
260161370Simp			LoadKernelFromSpi((char *)p_ASCIIToHex(argv[1]));
261161370Simp		break;
262161370Simp
263161370Simp	case COMMAND_XMODEM:
264161370Simp		// "x <address>"
265161370Simp		// download X-modem record at address
266161370Simp		if (argc > 1)
267161370Simp			xmodem_rx((char *)p_ASCIIToHex(argv[1]));
268161370Simp		break;
269161370Simp
270161370Simp	case COMMAND_RESET:
271163597Simp		printf("Reset\n");
272161370Simp		reset();
273161370Simp		while (1) continue;
274161370Simp		break;
275161370Simp
276161370Simp	case COMMAND_REPLACE_KERNEL_VIA_XMODEM:
277163597Simp		printf("Updating KERNEL image\n");
278161370Simp		UpdateFlash(KERNEL_OFFSET);
279161370Simp		break;
280161370Simp	case COMMAND_REPLACE_FLASH_VIA_XMODEM:
281163597Simp		printf("Updating FLASH image\n");
282161370Simp		UpdateFlash(FLASH_OFFSET);
283161370Simp		break;
284161370Simp
285163597Simp	case COMMAND_REPLACE_ID_EEPROM:
286163597Simp	{
287163597Simp	    char buf[25];
288163597Simp		printf("Testing Config EEPROM\n");
289163597Simp		EEWrite(0, "This is a test", 15);
290163597Simp		EERead(0, buf, 15);
291163597Simp		printf("Found '%s'\n", buf);
292163597Simp		break;
293163597Simp	}
294161370Simp	default:
295161370Simp		break;
296161370Simp	}
297161370Simp
298163597Simp	printf("\n");
299161370Simp}
300161370Simp
301161370Simp
302161370Simp/*
303161370Simp * .KB_C_FN_DEFINITION_START
304161370Simp * void ServicePrompt(char)
305161370Simp *  This private function process each character checking for valid commands.
306161370Simp * This function is only executed if the character is considered valid.
307163597Simp * Each command is terminated with NULL (0) or ''.
308161370Simp * .KB_C_FN_DEFINITION_END
309161370Simp */
310161370Simpstatic void
311161370SimpServicePrompt(char p_char)
312161370Simp{
313161370Simp	if (p_char == '\r')
314161370Simp		p_char = 0;
315161370Simp
316161370Simp	if (p_char == '\010') {
317161370Simp		if (buffCount) {
318161370Simp			/* handle backspace BS */
319161370Simp			inputBuffer[--buffCount] = 0;
320161370Simp			printf(backspaceString);
321161370Simp		}
322161370Simp		return;
323161370Simp	}
324161370Simp	if (buffCount < MAX_INPUT_SIZE - 1) {
325161370Simp		inputBuffer[buffCount++] = p_char;
326161370Simp		putchar(p_char);
327161370Simp	}
328161370Simp	if (!p_char) {
329163597Simp		printf("\n");
330161370Simp		ParseCommand(inputBuffer);
331161370Simp		p_memset(inputBuffer, 0, MAX_INPUT_SIZE);
332161370Simp		buffCount = 0;
333163597Simp		printf("\n>");
334161370Simp	}
335161370Simp}
336161370Simp
337161370Simp
338161370Simp/* ************************** GLOBAL FUNCTIONS ********************************/
339161370Simp
340161370Simp
341161370Simp/*
342161370Simp * .KB_C_FN_DEFINITION_START
343161370Simp * void Bootloader(void *inputFunction)
344161370Simp *  This global function is the entry point for the bootloader.  If the
345161370Simp * inputFunction pointer is NULL, the loader input will be serviced from
346161370Simp * the uart.  Otherwise, inputFunction is called to get characters which
347161370Simp * the loader will parse.
348161370Simp * .KB_C_FN_DEFINITION_END
349161370Simp */
350161370Simpvoid
351161370SimpBootloader(int(*inputFunction)(int))
352161370Simp{
353161370Simp	int	ch = 0;
354161370Simp
355161370Simp	p_memset((void*)inputBuffer, 0, sizeof(inputBuffer));
356161370Simp	buffCount = 0;
357161370Simp
358163597Simp	printf("\n>");
359161370Simp
360161370Simp	while (1)
361161370Simp		if ((ch = ((*inputFunction)(0))) > 0)
362161370Simp			ServicePrompt(ch);
363161370Simp}
364