2 * Broadcom Common Firmware Environment (CFE)
3 * Board device initialization, File: ui_bcm947xx.c
5 * Copyright (C) 2011, Broadcom Corporation
8 * This is UNPUBLISHED PROPRIETARY SOURCE CODE of Broadcom Corporation;
9 * the contents of this file may not be disclosed to third parties, copied
10 * or duplicated in any form, in whole or in part, without the prior
11 * written permission of Broadcom Corporation.
13 * $Id: ui_bcm947xx.c 323091 2012-03-22 23:32:36Z $
16 #include "lib_types.h"
17 #include "lib_string.h"
18 #include "lib_queue.h"
19 #include "lib_malloc.h"
20 #include "lib_printf.h"
23 #include "cfe_devfuncs.h"
24 #include "cfe_ioctl.h"
25 #include "cfe_error.h"
26 #include "cfe_fileops.h"
27 #include "cfe_loader.h"
28 #include "ui_command.h"
29 #include "bsp_config.h"
39 #include <dmemc_core.h>
40 #include <bcmendian.h>
44 #include "addrspace.h"
50 ui_cmd_reboot(ui_cmdline_t
*cmd
, int argc
, char *argv
[])
58 ui_cmd_nvram(ui_cmdline_t
*cmd
, int argc
, char *argv
[])
60 char *command
, *name
, *value
;
65 if (!(command
= cmd_getarg(cmd
, 0)))
66 return CFE_ERR_INV_PARAM
;
68 if (!strcmp(command
, "get")) {
69 if ((name
= cmd_getarg(cmd
, 1)))
70 if ((value
= nvram_get(name
)))
71 printf("%s\n", value
);
72 } else if (!strcmp(command
, "set")) {
73 if ((name
= cmd_getarg(cmd
, 1))) {
74 if ((value
= strchr(name
, '=')))
76 else if ((value
= cmd_getarg(cmd
, 2))) {
78 value
= cmd_getarg(cmd
, 3);
81 nvram_set(name
, value
);
83 } else if (!strcmp(command
, "unset")) {
84 if ((name
= cmd_getarg(cmd
, 1)))
86 } else if (!strcmp(command
, "commit")) {
88 } else if (!strcmp(command
, "erase")) {
89 extern char *flashdrv_nvram
;
90 if ((ret
= cfe_open(flashdrv_nvram
)) < 0)
92 if (!(buf
= KMALLOC(NVRAM_SPACE
, 0)))
94 memset(buf
, 0xff, NVRAM_SPACE
);
95 cfe_writeblk(ret
, 0, (unsigned char *)buf
, NVRAM_SPACE
);
98 } else if (!strcmp(command
, "show") || !strcmp(command
, "getall")) {
99 if (!(buf
= KMALLOC(NVRAM_SPACE
, 0)))
100 return CFE_ERR_NOMEM
;
101 nvram_getall(buf
, NVRAM_SPACE
);
102 for (name
= buf
; *name
; name
+= strlen(name
) + 1)
103 printf("%s\n", name
);
104 size
= sizeof(struct nvram_header
) + ((uintptr
)name
- (uintptr
)buf
);
105 printf("size: %d bytes (%d left)\n", size
, NVRAM_SPACE
- size
);
113 check_trx(char *trx_name
)
118 struct trx_header trx
;
121 static uint32 buf
[16*1024];
123 uint32 crc
, buf
[512];
124 #endif /* CFG_NFLASH */
126 unsigned int len
, count
;
129 ret
= fs_init("raw", &fsctx
, trx_name
);
133 ret
= fs_open(fsctx
, &ref
, "", FILE_MODE_READ
);
140 ret
= fs_read(fsctx
, ref
, (unsigned char *) &trx
, sizeof(struct trx_header
));
141 if (ret
!= sizeof(struct trx_header
)) {
146 /* Verify magic number */
147 if (ltoh32(trx
.magic
) != TRX_MAGIC
) {
148 ret
= CFE_ERR_INVBOOTBLOCK
;
152 /* Checksum over header */
153 crc
= hndcrc32((uint8
*) &trx
.flag_version
,
154 sizeof(struct trx_header
) - OFFSETOF(struct trx_header
, flag_version
),
157 for (len
= ltoh32(trx
.len
) - sizeof(struct trx_header
); len
; len
-= count
) {
159 count
= MIN(len
, sizeof(buf
) - sizeof(struct trx_header
));
162 count
= MIN(len
, sizeof(buf
));
165 ret
= fs_read(fsctx
, ref
, (unsigned char *) &buf
, count
);
171 /* Checksum over data */
172 crc
= hndcrc32((uint8
*) &buf
, count
, crc
);
175 /* Verify checksum */
176 if (ltoh32(trx
.crc32
) != crc
) {
177 ret
= CFE_ERR_BOOTPROGCHKSUM
;
184 fs_close(fsctx
, ref
);
187 xprintf("%s\n", cfe_errortext(ret
));
192 * ui_get_loadbuf(bufptr, bufsize)
194 * Figure out the location and size of the staging buffer.
197 * bufptr - address to return buffer location
198 * bufsize - address to return buffer size
200 static void ui_get_loadbuf(uint8_t **bufptr
, int *bufsize
)
202 int size
= CFG_FLASH_STAGING_BUFFER_SIZE
;
205 * Get the address of the staging buffer. We can't
206 * allocate the space from the heap to store the
207 * new flash image, because the heap may not be big
208 * enough. So, if FLASH_STAGING_BUFFER_SIZE is non-zero
209 * then just use it and FLASH_STAGING_BUFFER; else
210 * use the larger of (mem_bottomofmem - FLASH_STAGING_BUFFER)
211 * and (mem_totalsize - mem_topofmem).
215 *bufptr
= (uint8_t *) KERNADDR(CFG_FLASH_STAGING_BUFFER_ADDR
);
219 int reserved
= CFG_FLASH_STAGING_BUFFER_ADDR
;
221 /* For small memory size (8MB), we tend to use the below region.
222 * The buffer address may conflict with the os running address,
223 * so we reserve 3MB for the os.
225 if ((mem_totalsize
== (8*1024)) && (PHYSADDR(mem_bottomofmem
) > 0x300000))
228 below
= PHYSADDR(mem_bottomofmem
) - reserved
;
229 above
= (mem_totalsize
<< 10) - PHYSADDR(mem_topofmem
);
232 *bufptr
= (uint8_t *) KERNADDR(reserved
);
235 *bufptr
= (uint8_t *) KERNADDR(mem_topofmem
);
241 #if defined(DUAL_IMAGE) || defined(FAILSAFE_UPGRADE)
243 int check_image_prepare_cmd(int the_image
, char *buf
, uint32 osaddr
, int bufsize
)
246 char trx_name
[16], os_name
[16];
247 char trx2_name
[16], os2_name
[16];
250 ui_get_trx_flashdev(trx_name
);
251 ui_get_os_flashdev(os_name
);
253 strcpy(trx_name
, "flash1.trx");
254 strcpy(os_name
, "flash0.os");
257 strncpy (trx2_name
,trx_name
,sizeof(trx2_name
));
258 strncpy (os2_name
,os_name
,sizeof(os2_name
));
259 strcat (trx2_name
, "2");
260 strcat (os2_name
, "2");
262 if (the_image
== 0) {
263 if ((ret
= check_trx(trx_name
)) == 0) {
264 sprintf(buf
, "boot -raw -z -addr=0x%x -max=0x%x %s:", osaddr
, bufsize
,
267 printf("%s CRC check failed!\n", trx_name
);
269 } else if (the_image
== 1) {
270 if ((ret
= check_trx(trx2_name
)) == 0) {
271 sprintf(buf
, "boot -raw -z -addr=0x%x -max=0x%x %s:", osaddr
, bufsize
,
274 printf("%s CRC check failed!\n", trx2_name
);
277 printf("Image partition %d does not exist\n", the_image
);
281 #endif /* DUAL_IMAGE || FAILSAFE_UPGRADE */
284 static int ui_get_bootflags(void)
289 /* Only support chipcommon revision == 38 and BCM4706 for now */
290 if (((CHIPID(sih
->chip
) == BCM4706_CHIP_ID
) || sih
->ccrev
== 38) &&
291 (sih
->cccaps
& CC_CAP_NFLASH
)) {
292 if ((val
= nvram_get("bootflags")))
293 bootflags
= atoi(val
);
294 else if ((sih
->chipst
& (1 << 4)) != 0) {
295 /* This is NANDBOOT */
296 bootflags
= FLASH_KERNEL_NFLASH
| FLASH_BOOT_NFLASH
;
302 void ui_get_boot_flashdev(char *flashdev
)
306 if ((ui_get_bootflags() & FLASH_BOOT_NFLASH
) == FLASH_BOOT_NFLASH
)
307 strcpy(flashdev
, "nflash1.boot");
309 strcpy(flashdev
, "flash1.boot");
314 void ui_get_os_flashdev(char *flashdev
)
318 if ((ui_get_bootflags() & FLASH_KERNEL_NFLASH
) == FLASH_KERNEL_NFLASH
)
319 strcpy(flashdev
, "nflash0.os");
321 strcpy(flashdev
, "flash0.os");
326 void ui_get_trx_flashdev(char *flashdev
)
330 if ((ui_get_bootflags() & FLASH_KERNEL_NFLASH
) == FLASH_KERNEL_NFLASH
)
331 strcpy(flashdev
, "nflash1.trx");
333 strcpy(flashdev
, "flash1.trx");
336 #endif /* CFG_NFLASH */
339 ui_cmd_go(ui_cmdline_t
*cmd
, int argc
, char *argv
[])
343 struct trx_header
*file_buf
;
350 #ifdef FAILSAFE_UPGRADE
351 char *bootpartition
= nvram_get(BOOTPARTITION
);
352 char *partialboots
= nvram_get(PARTIALBOOTS
);
353 char *maxpartialboots
= nvram_get(MAXPARTIALBOOTS
);
356 char *bootpartition
= nvram_get(IMAGE_BOOT
);
359 char trx_name
[16], os_name
[16];
361 char *trx_name
= "flash1.trx";
362 char *os_name
= "flash0.os";
363 #endif /* CFG_NFLASH */
365 val
= nvram_get("os_ram_addr");
367 osaddr
= bcm_strtoul(val
, NULL
, 16);
371 #if defined(FAILSAFE_UPGRADE) || defined(DUAL_IMAGE)
372 if (bootpartition
!= NULL
) {
374 ui_get_trx_flashdev(trx_name
);
376 trx_failed
= check_trx(trx_name
);
378 strcat(trx_name
,"2");
380 trx_failed
&= check_trx(trx_name
);
382 #endif /* FAILSAFE_UPGRADE || DUAL_IMAGE*/
385 ui_get_trx_flashdev(trx_name
);
386 ui_get_os_flashdev(os_name
);
388 trx_failed
= check_trx(trx_name
);
392 /* Wait for CFE_ERR_TIMEOUT_LIMIT for an image */
394 sprintf(buf
, "flash -noheader :%s", trx_name
);
395 if ((ret
= ui_docommand(buf
)) != CFE_ERR_TIMEOUT
)
397 if (++retry
== CFE_ERR_TIMEOUT_LIMIT
) {
402 } else if (!nvram_invmatch("boot_wait", "on")) {
403 ui_get_loadbuf(&ptr
, &bufsize
);
405 sprintf(buf
, "load -raw -addr=0x%p -max=0x%x :", ptr
, bufsize
);
406 ret
= ui_docommand(buf
);
408 /* Load was successful. Check for the TRX magic.
409 * If it's a TRX image, then proceed to flash it, else try to boot
410 * Note: To boot a TRX image directly from the memory, address will need to be
411 * load address + trx header length.
414 file_buf
= (struct trx_header
*)ptr
;
415 /* If it's a TRX, then proceed to writing to flash else,
416 * try to boot from memory
418 if (file_buf
->magic
!= TRX_MAGIC
) {
419 sprintf(buf
, "boot -raw -z -addr=0x%x -max=0x%x -fs=memory :0x%p",
420 osaddr
, bufsize
, ptr
);
421 return ui_docommand(buf
);
423 /* Flash the image from memory directly */
424 sprintf(buf
, "flash -noheader -mem -size=0x%x 0x%p %s",
425 file_buf
->len
, ptr
, trx_name
);
426 ret
= ui_docommand(buf
);
430 if (ret
== CFE_ERR_INTR
)
433 bufsize
= PHYSADDR(mem_bottomofmem
) - PHYSADDR(osaddr
);
435 #if defined(FAILSAFE_UPGRADE) || defined(DUAL_IMAGE)
436 /* Get linux_boot variable to see what is current image */
437 if (bootpartition
!= NULL
) {
439 int i
= atoi(bootpartition
);
440 #ifdef FAILSAFE_UPGRADE
441 if (maxpartialboots
&& (atoi(maxpartialboots
) > 0)) {
442 if (partialboots
&& (atoi(partialboots
) > atoi(maxpartialboots
))) {
444 printf("Changed to the other image %d (maxpartialboots exceeded)\n", i
);
445 /* reset to new image */
446 sprintf(temp
, "%d", i
);
447 nvram_set(PARTIALBOOTS
, "1");
448 nvram_set(BOOTPARTITION
, temp
);
451 /* Increment the counter */
452 sprintf(temp
,"%d",partialboots
? atoi(partialboots
)+1:1);
453 nvram_set(PARTIALBOOTS
, temp
);
461 /* We try the specified one, if it is failed, we try the other one */
462 if (check_image_prepare_cmd(i
, buf
, osaddr
, bufsize
) == 0) {
463 printf("Booting(%d): %s\n",i
,buf
);
464 } else if (check_image_prepare_cmd(1-i
, buf
, osaddr
, bufsize
) == 0) {
465 printf("Changed to the other image %d\n", 1 - i
);
466 sprintf(temp
, "%d", 1-i
);
467 nvram_set(BOOTPARTITION
, temp
);
468 #ifdef FAILSAFE_UPGRADE
469 nvram_set(PARTIALBOOTS
, "1");
473 printf ("Both images bad!!!\n");
478 #endif /* FAILSAFE_UPGRADE || DUAL_IMAGE */
479 sprintf(buf
, "boot -raw -z -addr=0x%x -max=0x%x %s:", osaddr
, bufsize
, os_name
);
481 return ui_docommand(buf
);
485 ui_cmd_clocks(ui_cmdline_t
*cmd
, int argc
, char *argv
[])
487 chipcregs_t
*cc
= (chipcregs_t
*)si_setcoreidx(sih
, SI_CC_IDX
);
488 uint32 ccc
= R_REG(NULL
, &cc
->capabilities
);
489 uint32 pll
= ccc
& CC_CAP_PLL_MASK
;
491 if (pll
!= PLL_NONE
) {
492 uint32 n
= R_REG(NULL
, &cc
->clockcontrol_n
);
493 printf("Current clocks for pll=0x%x:\n", pll
);
494 printf(" mips: %d\n", si_clock_rate(pll
, n
, R_REG(NULL
, &cc
->clockcontrol_m3
)));
495 printf(" sb: %d\n", si_clock_rate(pll
, n
, R_REG(NULL
, &cc
->clockcontrol_sb
)));
496 printf(" pci: %d\n", si_clock_rate(pll
, n
, R_REG(NULL
, &cc
->clockcontrol_pci
)));
497 printf(" mipsref: %d\n", si_clock_rate(pll
, n
,
498 R_REG(NULL
, &cc
->clockcontrol_m2
)));
500 printf("Current clocks: %d/%d/%d/%d Mhz.\n",
501 si_cpu_clock(sih
) / 1000000,
502 si_mem_clock(sih
) / 1000000,
503 si_clock(sih
) / 1000000,
504 si_alp_clock(sih
) / 1000000);
510 extern int ui_init_devcmds(void); // J++
512 ui_init_bcm947xxcmds(void)
525 "nvram [command] [args..]\n\n"
527 "get [name];Gets the value of the specified variable|"
528 "set [name=value];Sets the value of the specified variable|"
529 "unset [name];Deletes the specified variable|"
530 "commit;Commit variables to flash|"
531 "erase;Erase all nvram|"
532 "show;Shows all variables|");
536 "Verify and boot OS image.",
538 "Boots OS image if valid. Waits for a new OS image if image is invalid\n"
539 "or boot_wait is unset or not on.",
541 cmd_addcmd("show clocks",
544 "Show current values of the clocks.",
546 "Shows the current values of the clocks.",
548 ui_init_devcmds(); // J++