/* * * Copyright (C) 2010 Texas Instruments Incorporated - http://www.ti.com/ * * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the * distribution. * * Neither the name of Texas Instruments Incorporated nor the names of * its contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY 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) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * */ /***************************************************************************************** * FILE PURPOSE: Perform the top level boot ***************************************************************************************** * FILE NAME: iblmain.c * * DESCRIPTION: The top level boot examines the boot configuration and performs boot * based on this configuration * * @file iblmain.c * * @brief * This file is used to launch a boot based on the boot configuration structure * *****************************************************************************************/ #include "ibl.h" #include "iblloc.h" #include "iblcfg.h" #include "device.h" #include "ethboot.h" #include "nandboot.h" #include "bis.h" #include "coffwrap.h" #include "iblbtbl.h" #include "iblblob.h" #include "timer.h" #include "i2c.h" #include "ibl_elf.h" #include /** * @brief * Data structures shared between the 1st and 2nd stage IBL load * are declared in a single header file, included in both stages */ #include "iblStage.h" /* Eat printfs */ void mprintf(char *x, ...) { } /** * @b Description * @n * * Returns TRUE if the input priority is valid and enabled */ BOOL iblPriorityIsValid (uint32 priority) { if ( (priority >= ibl_HIGHEST_PRIORITY) && (priority <= ibl_LOWEST_PRIORITY) ) return (TRUE); return (FALSE); } /** * @b Description * @n * * Returns TRUE if the mac address is 0 */ BOOL iblMacAddrIsZero (uint8 *maddr) { int32 i; for (i = 0; i < 6; i++) if (maddr[i] != 0) return (FALSE); return (TRUE); } /** * @b Description * @n * * The main function kicks off the boot. If it does not find the magic value in the * configuration array then default values are loaded. This default load * is done only once at the start of boot. * * @retval * None */ void main (void) { int32 i, j; /* Initialize the status structure */ iblMemset (&iblStatus, 0, sizeof(iblStatus_t)); iblStatus.iblMagic = ibl_MAGIC_VALUE; iblStatus.iblVersion = ibl_VERSION; /* Power up the timer */ devicePowerPeriph (TARGET_PWR_TIMER_0); /* Initialize the system timer (software tracking of the hardware timer state) */ timer_init (); /* Load default mac addresses for ethernet boot if requested */ for (i = 0; i < ibl_N_ETH_PORTS; i++) { if ( (iblPriorityIsValid (ibl.ethConfig[i].ethPriority) ) && (iblMacAddrIsZero (ibl.ethConfig[i].ethInfo.hwAddress) ) ) deviceLoadDefaultEthAddress (ibl.ethConfig[i].ethInfo.hwAddress); } /* DDR configuration is device specific */ deviceDdrConfig (); /* Try booting forever */ for (;;) { /* Start looping through the boot modes to find the one with the lowest priority * value, and try to boot it. If a boot mode is not supported the function * statement is simply defined to be a void statement */ for (i = ibl_HIGHEST_PRIORITY; i < ibl_LOWEST_PRIORITY; i++) { #ifndef EXCLUDE_ETH for (j = 0; j < ibl_N_ETH_PORTS; j++) { if (ibl.ethConfig[j].ethPriority == i) { iblStatus.activePeriph = ibl_ACTIVE_PERIPH_ETH; memcpy (&iblStatus.ethParams, &ibl.ethConfig[j].ethInfo, sizeof (iblEthBootInfo_t)); iblEthBoot (j); } } #endif #ifndef EXCLUDE_NAND if (ibl.nandConfig.nandPriority == i) { iblStatus.activePeriph = ibl_ACTIVE_PERIPH_NAND; iblNandBoot (); } #endif iblStatus.heartBeat += 1; } } } /* main */ /** * @b Description * @n * * The ibl boot function links a device to a data format. The data format * parser pulls data from the boot device * * @param[in] bootFxn The structure containing the boot device functions * * @retval * None */ Uint32 iblBoot (BOOT_MODULE_FXN_TABLE *bootFxn, Int32 dataFormat, void *formatParams) { Uint32 entry = 0; Uint32 value32; Uint8 dataBuf[4]; Uint16 value16; /* Determine the data format if required */ if (dataFormat == ibl_BOOT_FORMAT_AUTO) { (*bootFxn->peek)(dataBuf, sizeof(dataBuf)); value32 = (dataBuf[0] << 24) | (dataBuf[1] << 16) | (dataBuf[2] << 8) | (dataBuf[3] << 0); value16 = (dataBuf[0] << 8) | (dataBuf[1] << 0); /* BIS */ #ifndef EXCLUDE_BIS if (value32 == BIS_MAGIC_NUMBER) dataFormat = ibl_BOOT_FORMAT_BIS; #endif #ifndef EXCLUDE_COFF if (iblIsCoff (value16)) dataFormat = ibl_BOOT_FORMAT_COFF; #endif #ifndef EXCLUDE_ELF if (iblIsElf (dataBuf)) dataFormat = ibl_BOOT_FORMAT_ELF; #endif if (dataFormat == ibl_BOOT_FORMAT_AUTO) { iblStatus.autoDetectFailCnt += 1; return (0); } } iblStatus.activeFormat = dataFormat; /* Invoke the parser */ switch (dataFormat) { #ifndef EXCLUDE_BIS case ibl_BOOT_FORMAT_BIS: iblBootBis (bootFxn, &entry); break; #endif #ifndef EXCLUDE_COFF case ibl_BOOT_FORMAT_COFF: iblBootCoff (bootFxn, &entry); break; #endif case ibl_BOOT_FORMAT_BTBL: iblBootBtbl (bootFxn, &entry); break; #ifndef EXCLUDE_BLOB case ibl_BOOT_FORMAT_BBLOB: iblBootBlob (bootFxn, &entry, formatParams); break; #endif #ifndef EXCLUDE_ELF case ibl_BOOT_FORMAT_ELF: iblBootElf (bootFxn, &entry); break; #endif default: iblStatus.invalidDataFormatSpec += 1; break; } return (entry); }