Two stage load of ibl from I2C
[keystone-rtos/ibl.git] / src / main / iblmain.c
1 /*****************************************************************************************
2  * FILE PURPOSE: Perform the top level boot
3  *****************************************************************************************
4  * FILE NAME: iblmain.c
5  *
6  * DESCRIPTION: The top level boot examines the boot configuration and performs boot
7  *                              based on this configuration
8  *
9  * @file iblmain.c
10  *
11  * @brief
12  *   This file is used to launch a boot based on the boot configuration structure
13  *
14  *****************************************************************************************/
15 #include "ibl.h"
16 #include "iblloc.h"
17 #include "iblcfg.h"
18 #include "device.h"
19 #include "ethboot.h"
20 #include "bis.h"
21 #include "coffwrap.h"
22 #include "iblbtbl.h"
23 #include "iblblob.h"
24 #include "timer.h"
25 #include "i2c.h"
26 #include "ibl_elf.h"
27 #include <string.h>
29 /**
30  *  @brief
31  *      Data structures shared between the 1st and 2nd stage IBL load
32  *      are declared in a single header file, included in both stages
33  */
34 #include "iblStage.h"
38 /* Eat printfs */
39 void mprintf(char *x, ...) { }
41 /**
42  * @b Description
43  * @n
44  *
45  *  Returns TRUE if the input priority is valid and enabled
46  */
47 BOOL iblPriorityIsValid (uint32 priority)
48 {
49     if ( (priority >= ibl_HIGHEST_PRIORITY)  &&
50          (priority <= ibl_LOWEST_PRIORITY)   )
52         return (TRUE);
55     return (FALSE);
57 }
59 /**
60  * @b Description
61  * @n
62  *
63  *  Returns TRUE if the mac address is 0
64  */
65 BOOL iblMacAddrIsZero (uint8 *maddr)
66 {
67     int32 i;
69     for (i = 0; i < 6; i++)
70         if (maddr[i] != 0)
71             return (FALSE);
73     return (TRUE);
75 }
78 /**
79  * @b Description
80  * @n
81  *
82  * The main function kicks off the boot. If it does not find the magic value in the
83  *     configuration array then default values are loaded. This default load
84  *     is done only once at the start of boot. 
85  *
86  * @retval
87  *  None
88  */
89 void main (void)
90 {
91     int32 i, j;
93     /* Initialize the status structure */
94     memset (&iblStatus, 0, sizeof(iblStatus_t));
95     iblStatus.iblMagic = ibl_MAGIC_VALUE;
98     /* Power up the timer */
99     devicePowerPeriph (TARGET_PWR_TIMER_0);
101     /* Initialize the system timer (software tracking of the hardware timer state) */
102     timer_init ();
106     /* Load the default configuration table from the i2c. The actual speed of the device
107      * isn't really known here, since it is part of the table, so a compile time
108      * value is used (the pll may have been configured during the initial load) */
109     hwI2Cinit (IBL_I2C_DEV_FREQ_MHZ,        /* The CPU frequency during I2C data load */
110                DEVICE_I2C_MODULE_DIVISOR,   /* The divide down of CPU that drives the i2c */
111                IBL_I2C_CLK_FREQ_KHZ,        /* The I2C data rate used during table load */
112                IBL_I2C_OWN_ADDR);           /* The address used by this device on the i2c bus */
114     if (hwI2cMasterRead (IBL_I2C_CFG_TABLE_DATA_ADDR,    /* The address on the eeprom of the table */
115                          sizeof(ibl_t),                  /* The number of bytes to read */
116                          (UINT8 *)&ibl,                  /* Where to store the bytes */
117                          IBL_I2C_CFG_EEPROM_BUS_ADDR,    /* The bus address of the eeprom */
118                          IBL_I2C_CFG_ADDR_DELAY)         /* The delay between sending the address and reading data */
120          != I2C_RET_OK)  {
122        /* There is no recovery if the load of the configuration table failed */
123        iblStatus.tableLoadFail = 0x11111111;
124        for (;;);
126     }
129     /* Load default mac addresses for ethernet boot if requested */
130     for (i = 0; i < ibl_N_ETH_PORTS; i++)  {
132         if ( (iblPriorityIsValid (ibl.ethConfig[i].ethPriority)       )   &&
133              (iblMacAddrIsZero   (ibl.ethConfig[i].ethInfo.hwAddress) )   )
135             deviceLoadDefaultEthAddress (ibl.ethConfig[i].ethInfo.hwAddress);
137     }
140     /* DDR configuration is device specific */
141     deviceDdrConfig ();
143     /* Try booting forever */
144     for (;;)  {
146         /* Start looping through the boot modes to find the one with the lowest priority
147          * value, and try to boot it. If a boot mode is not supported the function
148          * statement is simply defined to be a void statement */
149         for (i = ibl_HIGHEST_PRIORITY; i < ibl_LOWEST_PRIORITY; i++)  {
151             for (j = 0; j < ibl_N_ETH_PORTS; j++)  {
152                 if (ibl.ethConfig[j].ethPriority == i)
153                 iblEthBoot (j);
154             }
156             if (ibl.nandConfig.nandPriority == i)
157                 iblNandBoot ();
159             iblStatus.heartBeat += 1;
160         }
162     }
165 } /* main */
168     
169 /**
170  * @b Description
171  * @n
172  * 
173  * The ibl boot function links a device to a data format. The data format
174  * parser pulls data from the boot device
175  *
176  * @param[in] bootFxn      The structure containing the boot device functions
177  *
178  * @retval
179  *  None
180  */
181 Uint32 iblBoot (BOOT_MODULE_FXN_TABLE *bootFxn, Int32 dataFormat, void *formatParams)
182
183     Uint32 entry = 0;
185     union  {
187         Uint8   dataBuf[4];   /* Place holder */
188         Uint32  bisValue;
189         Uint16  coffVer;    
191     } fid;
194     /* Determine the data format if required */
195     if (dataFormat == ibl_BOOT_FORMAT_AUTO)  {
197         (*bootFxn->peek)((Uint8 *)&fid, sizeof(fid));
199         /* BIS */
200         if (fid.bisValue == BIS_MAGIC_NUMBER)
201             dataFormat = ibl_BOOT_FORMAT_BIS;
203         if (iblIsCoff (fid.coffVer))
204             dataFormat = ibl_BOOT_FORMAT_COFF;
206         if (iblIsElf (fid.dataBuf))
207             dataFormat = ibl_BOOT_FORMAT_ELF;
209         else  {
210             iblStatus.autoDetectFailCnt += 1;
211             return (0);
212         }
213     }        
216     /* Invoke the parser */
217     switch (dataFormat)  {
219         case ibl_BOOT_FORMAT_BIS:
220             iblBootBis (bootFxn, &entry);
221             break;
223         case ibl_BOOT_FORMAT_COFF:
224             iblBootCoff (bootFxn, &entry);
225             break;
227         case ibl_BOOT_FORMAT_BTBL:
228             iblBootBtbl (bootFxn, &entry);
229             break;
231         case ibl_BOOT_FORMAT_BBLOB:
232             iblBootBlob (bootFxn, &entry, formatParams);
233             break;
235         case ibl_BOOT_FORMAT_ELF:
236             iblBootElf (bootFxn, &entry);
237             break;
239         default:
240             iblStatus.invalidDataFormatSpec += 1;
241             break;
243     }
244     
246     return (entry);