summaryrefslogtreecommitdiffstats
path: root/cfe/cfe/arch/mips/board/bcm63xx_rom/src/bcm63xx_main.c
diff options
context:
space:
mode:
Diffstat (limited to 'cfe/cfe/arch/mips/board/bcm63xx_rom/src/bcm63xx_main.c')
-rwxr-xr-xcfe/cfe/arch/mips/board/bcm63xx_rom/src/bcm63xx_main.c649
1 files changed, 649 insertions, 0 deletions
diff --git a/cfe/cfe/arch/mips/board/bcm63xx_rom/src/bcm63xx_main.c b/cfe/cfe/arch/mips/board/bcm63xx_rom/src/bcm63xx_main.c
new file mode 100755
index 0000000..201d6d8
--- /dev/null
+++ b/cfe/cfe/arch/mips/board/bcm63xx_rom/src/bcm63xx_main.c
@@ -0,0 +1,649 @@
+/* *********************************************************************
+ * Broadcom Common Firmware Environment (CFE)
+ *
+ * Main Module File: bcm63xxBoot_main.c
+ *
+ * This module contains the main "C" routine for CFE bootstrap loader
+ * and decompressor to decompress the real CFE to ram and jump over.
+ *
+ * Author: Mitch Lichtenberg (mpl@broadcom.com)
+ * Revised: seanl
+ *
+ *********************************************************************
+ *
+ * Copyright 2000,2001,2002,2003
+ * Broadcom Corporation. All rights reserved.
+ *
+ * This software is furnished under license and may be used and
+ * copied only in accordance with the following terms and
+ * conditions. Subject to these conditions, you may download,
+ * copy, install, use, modify and distribute modified or unmodified
+ * copies of this software in source and/or binary form. No title
+ * or ownership is transferred hereby.
+ *
+ * 1) Any source code used, modified or distributed must reproduce
+ * and retain this copyright notice and list of conditions
+ * as they appear in the source file.
+ *
+ * 2) No right is granted to use any trade name, trademark, or
+ * logo of Broadcom Corporation. The "Broadcom Corporation"
+ * name may not be used to endorse or promote products derived
+ * from this software without the prior written permission of
+ * Broadcom Corporation.
+ *
+ * 3) THIS SOFTWARE IS PROVIDED "AS-IS" AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING BUT NOT LIMITED TO, ANY IMPLIED
+ * WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
+ * PURPOSE, OR NON-INFRINGEMENT ARE DISCLAIMED. IN NO EVENT
+ * SHALL BROADCOM BE LIABLE FOR ANY DAMAGES WHATSOEVER, AND IN
+ * PARTICULAR, BROADCOM SHALL NOT BE LIABLE FOR DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
+ * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+ * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
+ * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR
+ * TORT (INCLUDING NEGLIGENCE OR OTHERWISE), EVEN IF ADVISED OF
+ * THE POSSIBILITY OF SUCH DAMAGE.
+ ********************************************************************* */
+
+
+#include "lib_types.h"
+#include "lib_string.h"
+#include "lib_malloc.h"
+#include "lib_printf.h"
+
+#include "cfe_iocb.h"
+#include "cfe_device.h"
+#include "cfe_console.h"
+#include "cfe_timer.h"
+
+#include "env_subr.h"
+#include "ui_command.h"
+#include "cfe_mem.h"
+#include "cfe.h"
+
+#include "bsp_config.h"
+#include "bcm_hwdefs.h"
+#include "bcm_map.h"
+
+#include "exception.h"
+
+#include "segtable.h"
+
+#include "initdata.h"
+
+#if defined(_BCM96368_) || defined(_BCM96362_) || defined(_BCM96328_) || defined(_BCM96816_)
+#include "flash_api.h"
+#include "jffs2.h"
+#endif
+
+#if CFG_PCI
+#include "pcivar.h"
+#endif
+
+
+
+int cfe_size_ram(void);
+inline static int is_aliased(int max_bits) __attribute__((always_inline));
+
+/* *********************************************************************
+ * Constants
+ ********************************************************************* */
+
+#ifndef CFG_STACK_SIZE
+#define STACK_SIZE 8192
+#else
+#define STACK_SIZE ((CFG_STACK_SIZE+1023) & ~1023)
+#endif
+
+inline static int is_aliased(int max_bits)
+{
+ volatile uint32 *mem_base;
+ volatile uint32 *test_ptr;
+ uint32 tmp;
+ int bit;
+ int res = 0;
+
+ mem_base = (uint32*)DRAM_BASE_NOCACHE;
+
+ *mem_base = 0;
+
+ for (bit = 8; bit < max_bits; bit++) {
+ test_ptr = (uint32*)((uint32)mem_base | 1 << bit);
+ /* ram may contain useful data, save location before modifying */
+ tmp = *test_ptr;
+ *test_ptr = -1;
+ if (*mem_base == *test_ptr) {
+ *test_ptr = tmp;
+ res = 1;
+ break;
+ }
+ *test_ptr = tmp;
+ }
+ return res;
+}
+
+#define MEMC_MAX_ROWS 14
+
+int cfe_size_ram(void)
+{
+#if !(defined(_BCM96328_) || defined (_BCM96362_) || defined(_BCM96816_))
+ uint32 col_bits, row_bits, bus_bits, bank_bits;
+ uint32 size;
+
+ /* Bus width is configured during early boot */
+ if (((MEMC->Config & MEMC_WIDTH_MASK) >> MEMC_WIDTH_SHFT) == MEMC_32BIT_BUS)
+ bus_bits = 2;
+ else
+ bus_bits = 1;
+
+ bank_bits = 2;
+ /* Start from setting to the lowest possible configuration */
+ col_bits = 8;
+ row_bits = 11;
+
+ MEMC->Config &= ~MEMC_COL_MASK;
+ MEMC->Config |= ((col_bits - 8) << MEMC_COL_SHFT);
+
+ MEMC->Config &= ~MEMC_ROW_MASK;
+ MEMC->Config |= ((row_bits - 11) << MEMC_ROW_SHFT);
+
+ /* Determine number of rows */
+ for (row_bits = 12; row_bits <= MEMC_MAX_ROWS; row_bits++) {
+ MEMC->Config &= ~MEMC_ROW_MASK;
+ MEMC->Config |= ((row_bits - 11) << MEMC_ROW_SHFT);
+ /* check if this address bit is valid */
+ if (is_aliased (col_bits + row_bits + bus_bits + bank_bits))
+ break;
+ }
+ row_bits -= 1;
+ MEMC->Config &= ~MEMC_ROW_MASK;
+ MEMC->Config |= ((row_bits - 11) << MEMC_ROW_SHFT);
+
+ /* Determine number of columns */
+ for (col_bits = 9; col_bits <= 11; col_bits++) {
+ MEMC->Config &= ~MEMC_COL_MASK;
+ MEMC->Config |= ((col_bits - 8) << MEMC_COL_SHFT);
+ /* check if this address bit is valid */
+ if (is_aliased (col_bits + row_bits + bus_bits + bank_bits))
+ break;
+ }
+ col_bits -= 1;
+ MEMC->Config &= ~MEMC_COL_MASK;
+ MEMC->Config |= ((col_bits - 8) << MEMC_COL_SHFT);
+
+ /* Compute memory size in MB */
+ size = 1 << (bus_bits + col_bits + row_bits + bank_bits - 20);
+
+ return size;
+#else
+ return (DDR->CSEND << 24);
+#endif
+}
+
+// fake functions for not to modifying init_mips.S
+void _exc_entry(void);
+void cfe_command_restart(void);
+void cfe_doxreq(void);
+
+void _exc_entry(void)
+{
+}
+
+void cfe_command_restart(void)
+{
+}
+void cfe_doxreq(void)
+{
+}
+
+/* *********************************************************************
+ * Externs
+ ********************************************************************* */
+
+void cfe_main(int,int);
+
+/* *********************************************************************
+ * Globals
+ ********************************************************************* */
+
+void cfe_ledstr(const char *leds)
+{
+}
+
+#if !defined(CONFIG_BRCM_IKOS)
+extern void _binArrayStart(void);
+extern void _binArrayEnd(void);
+extern int decompressLZMA(unsigned char *in, unsigned insize, unsigned char *out, unsigned outsize);
+
+#if (INC_NAND_FLASH_DRIVER==1) || (INC_SPI_PROG_NAND==1)
+#define je16_to_cpu(x) ((x).v16)
+#define je32_to_cpu(x) ((x).v32)
+extern void rom_nand_flash_init(void);
+extern int nand_flash_get_sector_size(unsigned short sector);
+extern int nand_flash_get_numsectors(void);
+extern int nand_flash_read_buf(unsigned short blk, int offset,
+ unsigned char *buffer, int len);
+extern void board_setleds(unsigned long);
+
+void *lib_memcpy(void *dest,const void *src,size_t cnt)
+{
+ unsigned char *d;
+ const unsigned char *s;
+
+ d = (unsigned char *) dest;
+ s = (const unsigned char *) src;
+
+ while (cnt) {
+ *d++ = *s++;
+ cnt--;
+ }
+
+ return dest;
+}
+
+int lib_memcmp(const void *dest,const void *src,size_t cnt)
+{
+ const unsigned char *d;
+ const unsigned char *s;
+
+ d = (const unsigned char *) dest;
+ s = (const unsigned char *) src;
+
+ while (cnt) {
+ if (*d < *s) return -1;
+ if (*d > *s) return 1;
+ d++; s++; cnt--;
+ }
+
+ return 0;
+}
+
+#if (INC_NAND_FLASH_DRIVER==1)
+/* Find uncompressed file cferam.bin on the JFFS2 file system, load it into
+ * memory and jump to its entry point function.
+ */
+char g_fname[] = NAND_CFE_RAM_NAME;
+int g_fname_actual_len = sizeof(g_fname) - 1;
+int g_fname_cmp_len = sizeof(g_fname) - 4; /* last three are digits */
+static void bootImageFromNand(void)
+{
+ const unsigned long bv_invalid = 0xfffffff;
+ const int max_not_jffs2 = 10;
+
+ struct rootfs_info
+ {
+ int rootfs;
+ int start_blk;
+ int end_blk;
+ unsigned long boot_val;
+ unsigned long ino;
+ } rfs_info[2], *prfs_info[2], *rfsi;
+
+ unsigned char *buf = (unsigned char *) mem_heapstart;
+ unsigned long version = 0;
+ struct jffs2_raw_dirent *pdir;
+ struct jffs2_raw_inode *pino;
+ unsigned char *p;
+ int i, j, k, done, not_jffs2;
+ int num_blks;
+ int len;
+ int boot_prev;
+ PNVRAM_DATA nd;
+ static int err0=0, err1=1;
+
+ rom_nand_flash_init();
+ num_blks = nand_flash_get_numsectors();
+ len = nand_flash_get_sector_size(0);
+ nd = (PNVRAM_DATA) (buf + len);
+
+ NAND->NandNandBootConfig = NBC_AUTO_DEV_ID_CFG | 0x101;
+ NAND->NandCsNandXor = 1;
+
+ memcpy((unsigned char *) nd, (unsigned char *)
+ FLASH_BASE + NVRAM_DATA_OFFSET, sizeof(NVRAM_DATA));
+
+ NAND->NandNandBootConfig = NBC_AUTO_DEV_ID_CFG | 0x2;
+ NAND->NandCsNandXor = 0;
+
+ /* Look at config to determine whether to boot current or previous image.*/
+ for( i = 0, p = (unsigned char *) nd->szBootline, boot_prev = 0;
+ i < NVRAM_BOOTLINE_LEN; i++, p++ )
+ {
+ if( p[0] == ' ' && p[1] == 'p' && p[2] == '=' )
+ {
+ boot_prev = p[3] - '0';
+ if( boot_prev != 0 && boot_prev != 1 )
+ boot_prev = '0';
+ break;
+ }
+ }
+
+ /* Find the CFE ram inode entry point for both root file systems. */
+ board_setleds((boot_prev == 0) ? 0x4e414e30 : 0x4e414e31);
+ for( k = 0, rfsi = rfs_info; k < 2; k++, rfsi++ )
+ {
+ version = 0;
+ not_jffs2 = 0;
+ rfsi->rootfs = k + NP_ROOTFS_1;
+ rfsi->boot_val = bv_invalid;
+ if( nd->ulNandPartOfsKb[rfsi->rootfs] > 0 &&
+ nd->ulNandPartOfsKb[rfsi->rootfs] < ((num_blks * len) / 1024))
+ {
+ rfsi->start_blk = nd->ulNandPartOfsKb[rfsi->rootfs] / (len/1024);
+ rfsi->end_blk = rfsi->start_blk +
+ (nd->ulNandPartSizeKb[rfsi->rootfs] / (len / 1024));
+ }
+ else
+ rfsi->start_blk = rfsi->end_blk = 0;
+
+ if( rfsi->start_blk == 0 || rfsi->start_blk >= rfsi->end_blk ||
+ rfsi->start_blk >= num_blks || rfsi->end_blk >= num_blks )
+ {
+ /* NVRAM_DATA fields for this rootfs are not valid. */
+ if( k == 0 )
+ {
+ /* Skip this rootfs. */
+ board_setleds(0x4e414e36);
+ continue;
+ }
+
+ if( rfs_info[0].boot_val == bv_invalid )
+ {
+ /* File system info cannot be found for either rootfs.
+ * NVRAM_DATA may not be set. Use default values.
+ */
+ board_setleds(0x4e414e37);
+ rfsi = rfs_info;
+ rfsi->start_blk = 1;
+ rfsi->end_blk = num_blks;
+ }
+ }
+
+ /* Find the directory entry. */
+ for( i = rfsi->start_blk, done = 0; i < rfsi->end_blk && done == 0; i++ )
+ {
+ /* This loop sequentially reads a NAND flash block into memory and
+ * processes it.
+ */
+ if( nand_flash_read_buf(i, 0, buf, len) > 0 )
+ {
+ /* This loop reads inodes in a block. */
+ p = buf;
+ while( p < buf + len )
+ {
+ pdir = (struct jffs2_raw_dirent *) p;
+ if( je16_to_cpu(pdir->magic) == JFFS2_MAGIC_BITMASK )
+ {
+ if( je16_to_cpu(pdir->nodetype) ==
+ JFFS2_NODETYPE_DIRENT &&
+ g_fname_actual_len == pdir->nsize &&
+ !memcmp(g_fname, pdir->name, g_fname_cmp_len) )
+ {
+ /* The desired directory was found. */
+ if( je32_to_cpu(pdir->version) > version )
+ {
+ if( (rfsi->ino = je32_to_cpu(pdir->ino)) != 0 )
+ {
+ unsigned char *fname =
+ pdir->name + g_fname_cmp_len;
+ rfsi->boot_val =
+ ((fname[0] - '0') * 100) +
+ ((fname[1] - '0') * 10) +
+ ((fname[2] - '0') * 1);
+ version = je32_to_cpu(pdir->version);
+
+ board_setleds(0x42540000 +
+ ((unsigned long) fname[1] << 8) +
+ (unsigned long) fname[2]);
+
+ /* Setting 'done = 1' assumes there is only
+ * one version of the directory entry. This
+ * may not be correct if the file is
+ * updated after it was initially flashed.
+ *
+ * TBD. Look for a higher version of the
+ * directory entry without searching the
+ * entire flash part.
+ */
+ done = 1;
+ break;
+ }
+ }
+ }
+
+ p += (je32_to_cpu(pdir->totlen) + 0x03) & ~0x03;
+ not_jffs2 = 0;
+ }
+ else
+ {
+ if( not_jffs2++ > max_not_jffs2 )
+ {
+ /* No JFFS2 magic bitmask for consecutive blocks.
+ * Assume this partion does not have a file system
+ * on it.
+ */
+ board_setleds(0x53544F50);
+ done = 1;
+ }
+ break;
+ }
+ }
+ }
+ else
+ {
+ if(!err0)
+ {
+ err0=1;
+ board_setleds(0x45525230);
+ }
+ }
+ }
+ board_setleds(0x4e414e39);
+ }
+
+ /* Set the rfs_info to the index to boot from. */
+ if( (boot_prev == 0 && rfs_info[0].boot_val > rfs_info[1].boot_val) ||
+ (boot_prev == 1 && rfs_info[0].boot_val < rfs_info[1].boot_val) ||
+ rfs_info[1].boot_val == bv_invalid )
+ {
+ /* Boot from the most recent image. */
+ prfs_info[0] = &rfs_info[0];
+ prfs_info[1] = &rfs_info[1];
+ }
+ else
+ {
+ /* Boot from the previous image. */
+ prfs_info[0] = &rfs_info[1];
+ prfs_info[1] = &rfs_info[0];
+ }
+
+ /* If the directory entry for the desired file, which is the CFE RAM image,
+ * is found, read it into memory and jump to its entry point function.
+ * This loop checks for CFE RAM image in two possible rootfs file sytems.
+ */
+ for( k = 0; k < 2; k++ )
+ {
+ unsigned char *pucDest = NULL;
+ unsigned char *pucEntry = NULL;
+ long isize = 0;
+
+ board_setleds(0x4e414e33);
+ rfsi = prfs_info[k];
+ if( rfsi->boot_val == bv_invalid )
+ continue;
+
+ /* When j == 0, get the first inode to find the entry point address.
+ * When j == 1, read the file contents into memory.
+ */
+ for( j = 0; j < 2; j++ )
+ {
+ /* This loop sequentially reads a NAND flash block into memory and
+ * processes it.
+ */
+ for(i = rfsi->start_blk, done = 0; i<rfsi->end_blk && done==0; i++)
+ {
+ if( nand_flash_read_buf(i, 0, buf, len) > 0 )
+ {
+ /* This loop reads inodes in a block. */
+ p = buf;
+ while( p < buf + len )
+ {
+ /* Verify the first short word is the JFFS2 magic
+ * number.
+ */
+ pino = (struct jffs2_raw_inode *) p;
+ if( je16_to_cpu(pino->magic) == JFFS2_MAGIC_BITMASK )
+ {
+ if( je16_to_cpu(pino->nodetype) ==
+ JFFS2_NODETYPE_INODE &&
+ je32_to_cpu(pino->ino) == rfsi->ino )
+ {
+ unsigned long size = je32_to_cpu(pino->dsize);
+ unsigned long ofs = je32_to_cpu(pino->offset);
+
+ if( size )
+ {
+ /* A node of the CFE RAM file was found
+ * with data. */
+ if( pucDest == NULL )
+ {
+ /* The entry point and copy destination
+ * addresses have not been obtained.
+ * If this is the first node of the CFE
+ * RAM file, obtain this information.
+ */
+ if( ofs == 0 )
+ {
+ /* The first 12 bytes contain a
+ * header. The first word is the
+ * entry point address.
+ */
+ pucEntry = (unsigned char *)
+ *(unsigned long *) pino->data;
+ pucDest = pucEntry - 12;
+ isize = je32_to_cpu(pino->isize);
+ done = 1;
+ board_setleds(0x52465330 |
+ rfsi->rootfs);
+ break;
+ }
+ }
+ else
+ {
+ /* Copy the image to memory. Stop when
+ * the entire image has been copied.
+ */
+ memcpy(pucDest+ofs, pino->data, size);
+ if( (isize -= size) <= 0 )
+ {
+ done = 1;
+ break;
+ }
+ }
+ }
+ }
+
+ /* Skip to the next inode entry. */
+ p += (je32_to_cpu(pino->totlen) + 0x03) & ~0x03;
+ }
+ else
+ break;
+ }
+ }
+ else
+ {
+ if(!err1)
+ {
+ err1=1;
+ board_setleds(0x45525231);
+ }
+ }
+ }
+ }
+
+ if( pucEntry && isize <= 0 )
+ {
+ board_setleds(0x4e414e35);
+
+ /* Save the rootfs partition that the CFE RAM image boots from
+ * at the memory location before the CFE RAM load address. The
+ * CFE RAM image uses this value to determine the partition to
+ * flash a new rootfs to.
+ */
+ *(pucEntry - 1) = (unsigned char) rfsi->rootfs;
+
+ cfe_launch((unsigned long) pucEntry); // never return...
+ }
+ board_setleds(0x4e414e38);
+ }
+
+ /* Error occurred. */
+ board_setleds(0x44494530);
+ while(1);
+}
+#endif
+#endif
+
+/* *********************************************************************
+ * cfe_main(a,b)
+ *
+ * It's gotta start somewhere.
+ * Input parameters:
+ * a,b - not used
+ *
+ * Return value:
+ * does not return
+ ********************************************************************* */
+
+void cfe_main(int a,int b)
+{
+ unsigned char *pucSrc;
+ unsigned char *pucDst;
+ unsigned int *entryPoint;
+ unsigned int binArrayStart = (unsigned int) _binArrayStart;
+ unsigned int binArrayEnd = (unsigned int) _binArrayEnd;
+ unsigned int dataLen = binArrayEnd - binArrayStart - 4;
+ int ret;
+
+ KMEMINIT((unsigned char *) (uint32_t) mem_heapstart,
+ ((CFG_HEAP_SIZE)*1024));
+
+#if (INC_NAND_FLASH_DRIVER==1) && (defined(_BCM96816_) || defined(_BCM96362_) || defined(_BCM96328_))
+ if( ((MISC->miscStrapBus & MISC_STRAP_BUS_BOOT_SEL_MASK) >>
+ MISC_STRAP_BUS_BOOT_SEL_SHIFT) == MISC_STRAP_BUS_BOOT_NAND )
+ {
+ bootImageFromNand(); /* Will not return. */
+ }
+#elif (INC_NAND_FLASH_DRIVER==1) && defined(_BCM96368_)
+ if( ((GPIO->StrapBus & MISC_STRAP_BUS_BOOT_SEL_MASK) >>
+ MISC_STRAP_BUS_BOOT_SEL_SHIFT) == MISC_STRAP_BUS_BOOT_NAND )
+ {
+ bootImageFromNand(); /* Will not return. */
+ }
+#endif
+
+ entryPoint = (unsigned int*) binArrayStart;
+ pucSrc = (unsigned char *) (binArrayStart + 4);
+
+ pucDst = (unsigned char *) *entryPoint;
+ ret = decompressLZMA((unsigned char*)pucSrc,
+ (unsigned int)dataLen,
+ (unsigned char *) pucDst,
+ 23*1024*1024);
+
+ if (ret != 0)
+ while (1); // if not decompressed ok, loop for EJTAG
+
+ cfe_launch((unsigned long) pucDst); // never return...
+}
+#else
+/* 0x694b6f31 (iKo1) is replaced with actual address during the build process.*/
+unsigned long cfeRamStartAddr=0x694b6f31;
+void cfe_main(int a,int b)
+{
+ cfe_size_ram();
+ cfe_launch(cfeRamStartAddr); // never return...
+}
+#endif
+