This thread has been locked.

If you have a related question, please click the "Ask a related question" button in the top right corner. The newly created question will be automatically linked to this question.

Second stage bootloader backup copies

I was examining the initialization procedure of the AM335x as listed in the TRM and I saw that the ROM Code will look at 4 consecutive blocks trying to find the first stage bootloader (MLO) if we're set to boot off of NAND or MMC.

This allows for 4 copies of the MLO, but what about the second stage bootloader (u-boot)? Is there any capability to have the 1st stage bootloader look for more than one copy of the second stage bootloader?

Is this either a feature currently built in or something that could be added in with some ease?


The second set of questions I have is with respect to the multiple copies of the MLO. The ROM code will look for more than one copy, is this to prevent a corrupt image from preventing the board from booting? For example if during an upgrade the first copy of MLO got corrupted, the next time the board boots it will try to boot the first copy and when that fails it will check to see if there are any other copies?

  • A partial answer to the first set of my questions. I found this: http://omappedia.org/wiki/Bootloader_Project

    It's regarding OMAP, but I'm pretty sure it's applicable here as well. The MLO is just a stripped down version of u-boot, and it appears the last step it does it load a fixed address (0x80008000 was the example given) for the full u-boot and does not return.

    So I guess the answer to my first set of questions is that it currently does not have the ability to look for more than one second stage bootloader, I would probably be able to set a different address for it to jump to if I wanted, but I'm guessing that doing a "check for corruption then use a different copy if required" would not be easy.

    Could anyone let me know if my thoughts here are correct as well as where I can find the real offset (I'm guessing it's something like 0x81080000)?

  • Mike Worster said:

    This allows for 4 copies of the MLO, but what about the second stage bootloader (u-boot)? Is there any capability to have the 1st stage bootloader look for more than one copy of the second stage bootloader?

    Is this either a feature currently built in or something that could be added in with some ease?

    The first-level bootloader is called u-boot SPL (secondary program loader). It's just a chopped down version of the full u-boot source in order to fit completely in internal memory.  I'm not aware of this capability being built into u-boot SPL.  You could certainly add something.  Although it sounds "easy" I imagine it would probably be a lot of work to really harden the code.  For example, in order to really make it robust I would envision putting some kind of CRC header on the file being loaded so that u-boot SPL can validate that it has been loaded correctly.  But then you're looking at modifying the tooling for image creation, etc.  Some of that already exists as the uImage files that u-boot loads for the kernel have CRCs built into them.  Of course once you start adding all the CRC code back into u-boot SPL you might not have enough internal RAM to do it all.  So I wouldn't expect it to be trivial.

    Mike Worster said:
    The ROM code will look for more than one copy, is this to prevent a corrupt image from preventing the board from booting?

    It looks for more than one copy to prevent a bad page from preventing your device from booting.

    Mike Worster said:
    For example if during an upgrade the first copy of MLO got corrupted, the next time the board boots it will try to boot the first copy and when that fails it will check to see if there are any other copies?

    Not necessarily.  If the pages are programmed with valid data (e.g. half from the original bootloader and half from the new bootloader, due to a power interruption for example) then this would look ok to the ROM.  It's only looking for bad pages, i.e. it is not checking the integrity of the complete image (i.e. no CRC, etc.) to make sure it's "good".

  • Brad, thanks for that. First one quick question about the proper nomenclature:

    You said: "u-boot SPL" I've seen both the terms "SPL" and "MLO". Are they interchangeable, and if not what's the difference?

    Now, what I had read before is that the SPL (I guess) jumps to the u-boot at a specific address and hands over control. Is that much correct? Is this a hardcoded address that the SPL expects to find the second stage bootloader, u-boot, at? If so, where is the code where this address is set?

    What I'm thinking right now is that you may be correct that adding a CRC header to the uboot images and a CRC check algorithm to the SPL might be a bit much... but maybe I can make this simpler. I can tell the SPL to boot from address B if some flag is set and otherwise boot from address A, the flag can be set/cleared during the boot and upgrade procedures.

    For this idea to work I need only 2 things:

    1) I need the SPL (MLO?) to be capable of loading u-boot from a variable address instead of a fixed one. Hope you can point me to where I'd find that.

    2) I need set some sort of flag in a file, or something... for the SPL (MLO?) to be able to read/write and use that to pick the address noted in #1. Are you aware of a way to set any sort of flags that the SPL can look for?

  • I hope I can explain some of this better. The include/configs/am335x_evm.h file controls a lot of those addresses. If you look at the #defines below

     #define CONFIG_SYS_NAND_U_BOOT_START    CONFIG_SYS_TEXT_BASE
     #define CONFIG_SYS_NAND_U_BOOT_OFFS     0x80000

    You can see that u-boot is read from NAND from offset 0x80000 and is stored into SDRAM at CONFIG_SYS_TEXT_BASE, which is also a #define in that file

     #define CONFIG_SYS_TEXT_BASE            0x80800000

    Then SPL automatically jumps to that address. Another important #define is MTDPARTS:

     #define MTDPARTS_DEFAULT                "mtdparts=omap2-nand.0:128k(SPL)," \
                                             "128k(SPL.backup1)," \
                                             "128k(SPL.backup2)," \
                                             "128k(SPL.backup3),1920k(u-boot)," \
                                             "128k(u-boot-env),5m(kernel),-(rootfs)"

    This shows that NAND IS layed out:

      SPL       offset 0 - 0x1ffff
      backup1   offset 0x20000 - 0x3ffff
      backup2   offset 0x40000 - 0x5ffff
      backup3   offset 0x60000 - 0x7ffff
      u-boot    offset 0x80000 - 0x1dffff
      env       offset 0x1e0000 - 0x1fffff
      kernel...
      rootfs...

    You could probably modify the .h file and add a u-boot backup after u-boot and shift the u-boot environment/kernel/rootfs higher in NAND. You would also have to modify the SPL code to do some type of CRC and use the backup copy if something is wrong. The MTD table in your kernel would have to be modified, too.

    SPL and MLO are the same. I think of it as SPL is the function (secondary program loader) while MLO is the file name.

    Steve K.

  • Steve and Brad,

        Thanks for your answers that does clarify a lot. I have a few additional questions on this same topic but with respect to the SPI boot (specificly NOR flash hooked up via SPI):

    It says in section 26.1.7.6.2 (Initialization / Functional Description / Memory Booting / SPI / Initializaion and Detection): 



    The ROM Code initializes the SPI controller, pin muxing and clocks for communicating with the SPI
    device. The controller is initialized in Mode 3 and the clock is setup to operate at 12 MHz. There is no
    specific device identification routine that is executed by the ROM code to identify whether a boot device is
    preset or not. If no SPI device is present, the sector read will return only 0xFFFFFFFF and the SPI boot
    will be treated as failed.

     The highlighted statement appears to be pretty definitive and I would interpret it in such a way that the Boot ROM goes on and tries the next boot device in its list when something like that happens. But the next section in the TRM says “The ROM Code reads SPI data from the boot device in 512 byte sectors.”, which is then followed by table 26-29 that looks like this:
     
    Memory Max number of blocks checked number of sectors searched
    NAND first 4 Number of sectors in one block
    SPI first 4 1

    So, this table says that the Boot ROM checks the first 4 _blocks_ in 1 sector. This is somewhat in conflict with the highlighted statement of the first paragraph and nowhere is stated what a ‘block’ is on a SPI device.

    So the follow up SPI boot device questions are:
    1) Are blocks and sectors equivalent?
    2) Is it correct that the Boot ROM reads up to 4 consecutive 512 byte sectors?
    3) How does the almost 1MB x-loader fit into a 512 byte sector? (section 26.1.9 says the GP header must be followed immediately by executable code, and that's bigger than 512 bytes)
    4) What (if there is any) is the need for having multiple x-loaders in the SPI device if hooked up to NOR Flash?

    Thanks
    -Mike