1/*  *********************************************************************
2    *  Broadcom Common Firmware Environment (CFE)
3    *
4    *  Test commands				File: cfe_tests.c
5    *
6    *  A temporary sandbox for misc test routines and commands.
7    *
8    *  Author:  Mitch Lichtenberg (mpl@broadcom.com)
9    *
10    *********************************************************************
11    *
12    *  Copyright 2000,2001
13    *  Broadcom Corporation. All rights reserved.
14    *
15    *  This software is furnished under license and may be used and
16    *  copied only in accoddance with the following terms and
17    *  conditions.  Subject to these conditions, you may download,
18    *  copy, install, use, modify and distribute modified or unmodified
19    *  copies of this software in source and/or binary form.  No title
20    *  or ownership is transferred hereby.
21    *
22    *  1) Any source code used, modified or distributed must reproduce
23    *     and retain this copyright notice and list of conditions as
24    *     they appear in the source file.
25    *
26    *  2) No right is granted to use any trade name, trademark, or
27    *     logo of Broadcom Corporation. Neither the "Broadcom
28    *     Corporation" name nor any trademark or logo of Broadcom
29    *     Corporation may be used to endorse or promote products
30    *     derived from this software without the prior written
31    *     permission of Broadcom Corporation.
32    *
33    *  3) THIS SOFTWARE IS PROVIDED "AS-IS" AND ANY EXPRESS OR
34    *     IMPLIED WARRANTIES, INCLUDING BUT NOT LIMITED TO, ANY IMPLIED
35    *     WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
36    *     PURPOSE, OR NON-INFRINGEMENT ARE DISCLAIMED. IN NO EVENT
37    *     SHALL BROADCOM BE LIABLE FOR ANY DAMAGES WHATSOEVER, AND IN
38    *     PARTICULAR, BROADCOM SHALL NOT BE LIABLE FOR DIRECT, INDIRECT,
39    *     INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
40    *     (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
41    *     GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
42    *     BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
43    *     OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR
44    *     TORT (INCLUDING NEGLIGENCE OR OTHERWISE), EVEN IF ADVISED OF
45    *     THE POSSIBILITY OF SUCH DAMAGE.
46    ********************************************************************* */
47
48
49#include "lib_types.h"
50#include "lib_string.h"
51#include "lib_queue.h"
52#include "lib_malloc.h"
53#include "lib_printf.h"
54#include "cfe.h"
55#include "cfe_iocb.h"
56#include "cfe_devfuncs.h"
57#include "cfe_error.h"
58#include "cfe_fileops.h"
59#include "cfe_loader.h"
60#include "ui_command.h"
61#include "bsp_config.h"
62
63#include <typedefs.h>
64#include <osl.h>
65#include <bcmutils.h>
66#include <sbutils.h>
67#include <sbconfig.h>
68#include <sbchipc.h>
69#include <sbmemc.h>
70#include <bcmendian.h>
71#include <bcmnvram.h>
72#include <hndcpu.h>
73#include <trxhdr.h>
74#include "addrspace.h"
75#include "initdata.h"
76
77#include "bsp_priv.h"
78
79/* Additional BSP UI */
80#if CFG_ET
81extern int ui_cmd_et(ui_cmdline_t *cmd, int argc, char *argv[]);
82#endif
83
84static int
85ui_cmd_reboot(ui_cmdline_t *cmd, int argc, char *argv[])
86{
87	hnd_cpu_reset(sbh);
88	return 0;
89}
90
91static int
92ui_cmd_nvram(ui_cmdline_t *cmd, int argc, char *argv[])
93{
94	char *command, *name, *value, *buf;
95	size_t size;
96	int ret;
97
98	if (!(command = cmd_getarg(cmd, 0)))
99		return CFE_ERR_INV_PARAM;
100
101	if (!strcmp(command, "get")) {
102		if ((name = cmd_getarg(cmd, 1)))
103			if ((value = nvram_get(name)))
104				printf("%s\n", value);
105	}
106	else if (!strcmp(command, "set")){
107		if ((name = cmd_getarg(cmd, 1))) {
108			if ((value = strchr(name, '=')))
109				*value++ = '\0';
110			else if ((value = cmd_getarg(cmd, 2))) {
111				if (*value == '=')
112					value = cmd_getarg(cmd, 3);
113			}
114			if (value)
115				nvram_set(name, value);
116		}
117	}
118	else if (!strcmp(command, "unset")) {
119		if ((name = cmd_getarg(cmd, 1)))
120			nvram_unset(name);
121	}
122	else if (!strcmp(command, "commit")) {
123		nvram_commit();
124	}
125	else if (!strcmp(command, "erase")) {
126		if ((ret = cfe_open("flash0.nvram")) < 0)
127			return ret;
128		if (!(buf = KMALLOC(NVRAM_SPACE, 0)))
129			return CFE_ERR_NOMEM;
130		memset(buf, 0xff, NVRAM_SPACE);
131		cfe_writeblk(ret, 0, buf, NVRAM_SPACE);
132		cfe_close(ret);
133		KFREE(buf);
134	}
135	else if (!strcmp(command, "show") || !strcmp(command, "getall")) {
136		if (!(buf = KMALLOC(NVRAM_SPACE, 0)))
137			return CFE_ERR_NOMEM;
138		nvram_getall(buf, NVRAM_SPACE);
139		for (name = buf; *name; name += strlen(name) + 1)
140			printf("%s\n", name);
141		size = sizeof(struct nvram_header) + (name - buf);
142		printf("size: %d bytes (%d left)\n", size, NVRAM_SPACE - size);
143		KFREE(buf);
144	}
145
146	return 0;
147}
148
149static int
150check_trx(void)
151{
152	int ret;
153	fileio_ctx_t *fsctx;
154	void *ref;
155	struct trx_header trx;
156	uint32 crc, buf[128];
157	unsigned int len, count;
158
159	/* Open header */
160	ret = fs_init("raw", &fsctx, "flash0.trx");
161	if (ret)
162		return ret;
163
164	ret = fs_open(fsctx, &ref, "", FILE_MODE_READ);
165	if (ret) {
166		fs_uninit(fsctx);
167		return ret;
168	}
169
170	/* Read header */
171	ret = fs_read(fsctx, ref, (unsigned char *) &trx, sizeof(struct trx_header));
172	if (ret != sizeof(struct trx_header)) {
173		ret = CFE_ERR_IOERR;
174		goto done;
175	}
176
177	/* Verify magic number */
178	if (ltoh32(trx.magic) != TRX_MAGIC) {
179		ret = CFE_ERR_INVBOOTBLOCK;
180		goto done;
181	}
182
183	/* Checksum over header */
184	crc = hndcrc32((uint8 *) &trx.flag_version,
185		    sizeof(struct trx_header) - OFFSETOF(struct trx_header, flag_version),
186		    CRC32_INIT_VALUE);
187
188	fs_close(fsctx, ref);
189	fs_uninit(fsctx);
190
191	/* Open data */
192	ret = fs_init("raw", &fsctx, "flash0.os");
193	if (ret)
194		return ret;
195
196	ret = fs_open(fsctx, &ref, "", FILE_MODE_READ);
197	if (ret) {
198		fs_uninit(fsctx);
199		return ret;
200	}
201
202	for (len = ltoh32(trx.len) - sizeof(struct trx_header); len; len -= count) {
203		count = MIN(len, sizeof(buf));
204
205		/* Read data */
206		ret = fs_read(fsctx, ref, (unsigned char *) &buf, count);
207		if (ret != count) {
208			ret = CFE_ERR_IOERR;
209			goto done;
210		}
211
212		/* Checksum over data */
213		crc = hndcrc32((uint8 *) &buf, count, crc);
214	}
215
216	/* Verify checksum */
217	if (ltoh32(trx.crc32) != crc) {
218		ret = CFE_ERR_BOOTPROGCHKSUM;
219		goto done;
220	}
221
222	ret = 0;
223
224 done:
225	fs_close(fsctx, ref);
226	fs_uninit(fsctx);
227	if (ret)
228		xprintf("%s\n", cfe_errortext(ret));
229	return ret;
230}
231
232/*  *********************************************************************
233    *  ui_get_loadbuf(bufptr, bufsize)
234    *
235    *  Figure out the location and size of the staging buffer.
236    *
237    *  Input parameters:
238    *	   bufptr - address to return buffer location
239    *	   bufsize - address to return buffer size
240    ********************************************************************* */
241static void ui_get_loadbuf(uint8_t **bufptr, int *bufsize)
242{
243    int size = CFG_FLASH_STAGING_BUFFER_SIZE;
244
245    /*
246     * Get the address of the staging buffer.  We can't
247     * allocate the space from the heap to store the
248     * new flash image, because the heap may not be big
249     * enough.  So, if FLASH_STAGING_BUFFER_SIZE is non-zero
250     * then just use it and FLASH_STAGING_BUFFER; else
251     * use the larger of (mem_bottomofmem - FLASH_STAGING_BUFFER)
252     * and (mem_totalsize - mem_topofmem).
253     */
254
255    if (size > 0) {
256	*bufptr = (uint8_t *) KERNADDR(CFG_FLASH_STAGING_BUFFER_ADDR);
257	*bufsize = size;
258    } else {
259	int below, above;
260
261	below = PHYSADDR(mem_bottomofmem) - CFG_FLASH_STAGING_BUFFER_ADDR;
262	above = (mem_totalsize << 10) - PHYSADDR(mem_topofmem);
263
264	if (below > above) {
265	    *bufptr = (uint8_t *) KERNADDR(CFG_FLASH_STAGING_BUFFER_ADDR);
266	    *bufsize = below;
267	} else {
268	    *bufptr = (uint8_t *) KERNADDR(mem_topofmem);
269	    *bufsize = above;
270	}
271    }
272}
273
274static int
275ui_cmd_go(ui_cmdline_t *cmd, int argc, char *argv[])
276{
277	int ret = 0;
278	char buf[512];
279	struct trx_header *file_buf;
280	uint8_t *ptr;
281	int bufsize = 0;
282
283	if (check_trx()) {
284		/* Wait forever for an image */
285		while ((ret = ui_docommand("flash -noheader : flash1.trx")) == CFE_ERR_TIMEOUT);
286	} else if (!nvram_invmatch("boot_wait", "on")) {
287		ui_get_loadbuf(&ptr, &bufsize);
288		/* Load the image */
289		sprintf(buf, "load -raw -addr=0x%x -max=0x%x :", ptr, TRX_MAX_LEN);
290		ret = ui_docommand(buf);
291
292		/* Load was successful. Check for the TRX magic.
293		 * If it's a TRX image, then proceed to flash it, else try to boot
294		 * Note: To boot a TRX image directly from the memory, address will need to be
295		 * load address + trx header length.
296		 */
297		if (ret == 0) {
298			file_buf = (struct trx_header *)ptr;
299			/* If it's a TRX, then proceed to writing to flash else,
300			 * try to boot from memory
301			 */
302			if (file_buf->magic != TRX_MAGIC) {
303				sprintf(buf, "boot -raw -z -addr=0x%s -max=0x%x -fs=memory :0x%x",
304				        nvram_get("os_ram_addr") ? : "80001000",
305				        TRX_MAX_LEN, ptr);
306				return ui_docommand(buf);
307			}
308			/* Flash the image from memory directly */
309			sprintf(buf, "flash -noheader -mem -size=0x%x 0x%x flash1.trx",
310			        file_buf->len, ptr);
311			ret = ui_docommand(buf);
312		}
313	}
314
315	if (ret == CFE_ERR_INTR)
316		return ret;
317
318	/* Boot the image */
319	sprintf(buf, "boot -raw -z -addr=0x%s -max=0x%x flash0.os:",
320		nvram_get("os_ram_addr") ? : "80001000",
321		TRX_MAX_LEN);
322	return ui_docommand(buf);
323}
324
325
326int
327ui_init_bcm947xxcmds(void)
328{
329	cmd_addcmd("reboot",
330		   ui_cmd_reboot,
331		   NULL,
332		   "Reboot.",
333		   "reboot\n\n"
334		   "Reboots.",
335		   "");
336	cmd_addcmd("nvram",
337		   ui_cmd_nvram,
338		   NULL,
339		   "NVRAM utility.",
340#ifndef CFG_MINIMAL_SIZE
341		   "nvram [command] [args..]\n\n"
342		   "Access NVRAM.",
343		   "get [name];Gets the value of the specified variable|"
344		   "set [name=value];Sets the value of the specified variable|"
345		   "unset [name];Deletes the specified variable|"
346		   "commit;Commit variables to flash|"
347		   "erase;Erase all nvram|"
348		   "show;Shows all variables|"
349#else /* CFG_MINIMAL_SIZE */
350		   "nvram [command] [args..]\n",
351		   "get [name];|"
352		   "set [name=value];|"
353		   "unset [name];|"
354		   "commit;|"
355		   "erase;|"
356		   "show;|"
357#endif /* CFG_MINIMAL_SIZE */
358		   );
359	cmd_addcmd("go",
360		   ui_cmd_go,
361		   NULL,
362		   "Verify and boot OS image.",
363#ifndef CFG_MINIMAL_SIZE
364		   "go\n\n"
365		   "Boots OS image if valid. Waits for a new OS image if image is invalid\n"
366		   "or boot_wait is unset or not on.",
367#else /* CFG_MINIMAL_SIZE */
368		   "go\n",
369#endif /* CFG_MINIMAL_SIZE */
370		   "");
371#if CFG_ET
372	et_addcmd();
373#endif
374#if CFG_WLU
375	wl_addcmd();
376#endif
377
378	return 0;
379}
380