Hi folks,
I'm using Coreboot to implement an old-school Linux-as-bootloader for a prototype board, which has an 8-MByte SPI flash attached to an AMD SB800 southbridge. I'd like to take advantage of that nice roomy flash, as well as the normal/fallback capabilities of Coreboot and the layout and partial-rewrite features of flashrom, to provide a safe firmware upgrade path for end users.
Ideally I'd divide up the flash so that the normal Coreboot+payload are separate from the fallback Coreboot+payload and bootblock. The end user would only rewrite the normal Coreboot+payload. If the rewrite fails leaving the normal area of the flash completely scrambled, the board would still boot using the fallback Coreboot+payload. And for extra credit, I'd try to put the critical fallback bits in an area of the flash that can be turned read-only once it's programmed at the factory.
Following the flashrom layout format, here's how I imagine partitioning the flash:
00000000:003fffff normal+payload 00400000:ffffffff fallback+payload+bootblock
Following Patrick's helpful recipe (http://www.coreboot.org/pipermail/coreboot/2010-February/055944.html) I figured out how to build a rom image with a cbfs containing normal and fallback files. Unfortunately the build system insists on placing each new file at the beginning of the free space; I didn't see any obvious way to convince cbfstool to leave a gap after normal+payload and place the fallback files at 00400000. I hacked around this by creating a dummy pad file and adding it before the fallback files. Is there a better way to do this?
The next issue I encountered is that when I test my scheme by erasing the 00000000:003fffff region, Coreboot takes approximately forever to locate the fallback files. In cbfs, information about each file is stored in a header along with the file itself. To locate a file, Coreboot starts at the first file's header and hops from one to the next until it finds a matching filename. If instead of a header it finds gibberish, it doesn't throw up its hands in despair; rather, it goes into PRESS PLAY ON TAPE mode, scanning along until it either finds a header signature or hits the end of the rom. At this early stage of the boot process, caches and other such niceties aren't enabled; on my board, each iteration in the walkcbfs loop causes ~75 SPI reads, yielding a scan rate of ~175kB/sec.
Placing the fallback files before the normal ones doesn't help, because the bootblock needs to discover that the normal files are AWOL before deciding to use the fallback. Increasing the cbfs file alignment from the default of 64 bytes is more promising, allowing the scan to take much bigger hops. I tried bumping it up to 4096 bytes and ran into several bugs in cbfstool and walkcbfs, which assume that the bootblock region is larger than the alignment in deciding when to terminate the scan. While I'm sure these issues can be fixed, the whole flash-as-tape thing bothers me. In my scheme, I've decided ahead of time where the files are supposed to reside. A file's header is either there or it isn't; there's no point wasting time scanning the entire flash in the vain hope that the file is actually present, just in an unexpected location.
I'm thinking of extending the cbfs format to allow more than one top-level header in the bootblock. In my scheme, there would be two: one pointing to the first normal file, and another pointing to the first fallback file. Searching for a file would involve scanning each series of files linked from the headers in the bootblock, and would simply terminate if no matching filename were found in any of them.
This implies changing cbfstool and any code in Coreboot that touches cbfs. Before I jump off the deep end, is there an easier or better way to achieve this?
--Ed
-----Original Message----- From: coreboot-bounces@coreboot.org [mailto:coreboot-bounces@coreboot.org] On Behalf Of Ed Swierk Sent: Wednesday, July 14, 2010 12:45 AM To: Coreboot Subject: [coreboot] cbfs for safe flashing
Hi folks,
I'm using Coreboot to implement an old-school Linux-as-bootloader for a prototype board, which has an 8-MByte SPI flash attached to an AMD SB800 southbridge. I'd like to take advantage of that nice roomy flash, as well as the normal/fallback capabilities of Coreboot and the layout and partial-rewrite features of flashrom, to provide a safe firmware upgrade path for end users.
Ideally I'd divide up the flash so that the normal Coreboot+payload are separate from the fallback Coreboot+payload and bootblock. The end user would only rewrite the normal Coreboot+payload. If the rewrite fails leaving the normal area of the flash completely scrambled, the board would still boot using the fallback Coreboot+payload. And for extra credit, I'd try to put the critical fallback bits in an area of the flash that can be turned read-only once it's programmed at the factory.
Following the flashrom layout format, here's how I imagine partitioning the flash:
00000000:003fffff normal+payload 00400000:ffffffff fallback+payload+bootblock
Wouldn't you want three areas? I'd think you'd want another for just the bootblock.
Following Patrick's helpful recipe (http://www.coreboot.org/pipermail/coreboot/2010-February/055944.html) I figured out how to build a rom image with a cbfs containing normal and fallback files. Unfortunately the build system insists on placing each new file at the beginning of the free space; I didn't see any obvious way to convince cbfstool to leave a gap after normal+payload and place the fallback files at 00400000. I hacked around this by creating a dummy pad file and adding it before the fallback files. Is there a better way to do this?
It seems like there used to be a way to specify an address, which would force CBFS to add the empty space for you.
I'm thinking of extending the cbfs format to allow more than one top-level header in the bootblock. In my scheme, there would be two: one pointing to the first normal file, and another pointing to the first fallback file. Searching for a file would involve scanning each series of files linked from the headers in the bootblock, and would simply terminate if no matching filename were found in any of them.
This implies changing cbfstool and any code in Coreboot that touches cbfs. Before I jump off the deep end, is there an easier or better way to achieve this?
Instead of erasing one image to test it, you could add blank images with the same name. That would allow you to test the case of a bad flash. The case where CBFS is corrupted shouldn't happen too often, and when it does it is only inconvenient to have it take a long time to boot. The fact that it recovers will make up for that :)
Thanks, Myles