1 /*
2 *
3 * Copyright (C) 2010 Texas Instruments Incorporated - http://www.ti.com/
4 *
5 *
6 * Redistribution and use in source and binary forms, with or without
7 * modification, are permitted provided that the following conditions
8 * are met:
9 *
10 * Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
12 *
13 * Redistributions in binary form must reproduce the above copyright
14 * notice, this list of conditions and the following disclaimer in the
15 * documentation and/or other materials provided with the
16 * distribution.
17 *
18 * Neither the name of Texas Instruments Incorporated nor the names of
19 * its contributors may be used to endorse or promote products derived
20 * from this software without specific prior written permission.
21 *
22 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
23 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
24 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
25 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
26 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
27 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
28 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
29 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
30 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
31 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
32 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
33 *
34 */
38 /*****************************************************************************************
39 * FILE PURPOSE: Perform the top level boot
40 *****************************************************************************************
41 * FILE NAME: iblmain.c
42 *
43 * DESCRIPTION: The top level boot examines the boot configuration and performs boot
44 * based on this configuration
45 *
46 * @file iblmain.c
47 *
48 * @brief
49 * This file is used to launch a boot based on the boot configuration structure
50 *
51 *****************************************************************************************/
52 #include "ibl.h"
53 #include "iblloc.h"
54 #include "iblcfg.h"
55 #include "device.h"
56 #include "ethboot.h"
57 #include "bis.h"
58 #include "coffwrap.h"
59 #include "iblbtbl.h"
60 #include "iblblob.h"
61 #include "timer.h"
62 #include "i2c.h"
63 #include "ibl_elf.h"
64 #include <string.h>
67 /**
68 * @brief The ibl table is declared.
69 *
70 * @details
71 * The ibl table is declared uninitialized by this ibl program. An external
72 * initialization can be performed if the default operation of the ibl is
73 * not desired.
74 */
75 #pragma DATA_SECTION(ibl, ".ibl_config_table")
76 ibl_t ibl;
79 /**
80 * @brief The ibl status table is declared.
81 *
82 * @details
83 * The ibl status table is declared. It is initialized at run time
84 * in function main.
85 */
86 #pragma DATA_SECTION(iblStatus, ".ibl_status_table")
87 iblStatus_t iblStatus;
90 /* Eat printfs */
91 void mprintf(char *x, ...) { }
93 /**
94 * @b Description
95 * @n
96 *
97 * Returns TRUE if the input priority is valid and enabled
98 */
99 BOOL iblPriorityIsValid (uint32 priority)
100 {
101 if ( (priority >= ibl_HIGHEST_PRIORITY) &&
102 (priority <= ibl_LOWEST_PRIORITY) )
104 return (TRUE);
107 return (FALSE);
109 }
111 /**
112 * @b Description
113 * @n
114 *
115 * Returns TRUE if the mac address is 0
116 */
117 BOOL iblMacAddrIsZero (uint8 *maddr)
118 {
119 int32 i;
121 for (i = 0; i < 6; i++)
122 if (maddr[i] != 0)
123 return (FALSE);
125 return (TRUE);
127 }
130 /**
131 * @b Description
132 * @n
133 *
134 * The main function kicks off the boot. If it does not find the magic value in the
135 * configuration array then default values are loaded. This default load
136 * is done only once at the start of boot.
137 *
138 * @retval
139 * None
140 */
141 void main (void)
142 {
143 int32 i, j;
145 /* Initialize the status structure */
146 memset (&iblStatus, 0, sizeof(iblStatus_t));
147 iblStatus.iblMagic = ibl_MAGIC_VALUE;
150 /* Power up the timer */
151 devicePowerPeriph (TARGET_PWR_TIMER_0);
153 /* Initialize the system timer (software tracking of the hardware timer state) */
154 timer_init ();
158 /* Load the default configuration table from the i2c. The actual speed of the device
159 * isn't really known here, since it is part of the table, so a compile time
160 * value is used (the pll may have been configured during the initial load) */
161 hwI2Cinit (IBL_I2C_DEV_FREQ_MHZ, /* The CPU frequency during I2C data load */
162 DEVICE_I2C_MODULE_DIVISOR, /* The divide down of CPU that drives the i2c */
163 IBL_I2C_CLK_FREQ_KHZ, /* The I2C data rate used during table load */
164 IBL_I2C_OWN_ADDR); /* The address used by this device on the i2c bus */
166 if (hwI2cMasterRead (IBL_I2C_CFG_TABLE_DATA_ADDR, /* The address on the eeprom of the table */
167 sizeof(ibl_t), /* The number of bytes to read */
168 (UINT8 *)&ibl, /* Where to store the bytes */
169 IBL_I2C_CFG_EEPROM_BUS_ADDR, /* The bus address of the eeprom */
170 IBL_I2C_CFG_ADDR_DELAY) /* The delay between sending the address and reading data */
172 != I2C_RET_OK) {
174 /* There is no recovery if the load of the configuration table failed */
175 iblStatus.tableLoadFail = 0x11111111;
176 for (;;);
178 }
181 /* Load default mac addresses for ethernet boot if requested */
182 for (i = 0; i < ibl_N_ETH_PORTS; i++) {
184 if ( (iblPriorityIsValid (ibl.ethConfig[i].ethPriority) ) &&
185 (iblMacAddrIsZero (ibl.ethConfig[i].ethInfo.hwAddress) ) )
187 deviceLoadDefaultEthAddress (ibl.ethConfig[i].ethInfo.hwAddress);
189 }
192 /* Pll configuration is device specific */
193 devicePllConfig ();
195 /* DDR configuration is device specific */
196 deviceDdrConfig ();
198 /* Try booting forever */
199 for (;;) {
201 /* Start looping through the boot modes to find the one with the lowest priority
202 * value, and try to boot it. If a boot mode is not supported the function
203 * statement is simply defined to be a void statement */
204 for (i = ibl_HIGHEST_PRIORITY; i < ibl_LOWEST_PRIORITY; i++) {
206 for (j = 0; j < ibl_N_ETH_PORTS; j++) {
207 if (ibl.ethConfig[j].ethPriority == i)
208 iblEthBoot (j);
209 }
211 if (ibl.nandConfig.nandPriority == i)
212 iblNandBoot ();
214 iblStatus.heartBeat += 1;
215 }
217 }
220 } /* main */
224 /**
225 * @b Description
226 * @n
227 *
228 * The ibl boot function links a device to a data format. The data format
229 * parser pulls data from the boot device
230 *
231 * @param[in] bootFxn The structure containing the boot device functions
232 *
233 * @retval
234 * None
235 */
236 Uint32 iblBoot (BOOT_MODULE_FXN_TABLE *bootFxn, Int32 dataFormat, void *formatParams)
237 {
238 Uint32 entry = 0;
240 union {
242 Uint8 dataBuf[4]; /* Place holder */
243 Uint32 bisValue;
244 Uint16 coffVer;
246 } fid;
249 /* Determine the data format if required */
250 if (dataFormat == ibl_BOOT_FORMAT_AUTO) {
252 (*bootFxn->peek)((Uint8 *)&fid, sizeof(fid));
254 /* BIS */
255 if (fid.bisValue == BIS_MAGIC_NUMBER)
256 dataFormat = ibl_BOOT_FORMAT_BIS;
258 if (iblIsCoff (fid.coffVer))
259 dataFormat = ibl_BOOT_FORMAT_COFF;
261 if (iblIsElf (fid.dataBuf))
262 dataFormat = ibl_BOOT_FORMAT_ELF;
264 else {
265 iblStatus.autoDetectFailCnt += 1;
266 return (0);
267 }
268 }
271 /* Invoke the parser */
272 switch (dataFormat) {
274 case ibl_BOOT_FORMAT_BIS:
275 iblBootBis (bootFxn, &entry);
276 break;
278 case ibl_BOOT_FORMAT_COFF:
279 iblBootCoff (bootFxn, &entry);
280 break;
282 case ibl_BOOT_FORMAT_BTBL:
283 iblBootBtbl (bootFxn, &entry);
284 break;
286 case ibl_BOOT_FORMAT_BBLOB:
287 iblBootBlob (bootFxn, &entry, formatParams);
288 break;
290 case ibl_BOOT_FORMAT_ELF:
291 iblBootElf (bootFxn, &entry);
292 break;
294 default:
295 iblStatus.invalidDataFormatSpec += 1;
296 break;
298 }
301 return (entry);
303 }