diff options
Diffstat (limited to 'cfe/cfe/arch/mips/board/bcm63xx_rom/src/bcm63xx_main.c')
-rwxr-xr-x | cfe/cfe/arch/mips/board/bcm63xx_rom/src/bcm63xx_main.c | 649 |
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 + |