Since the topic of optimal flash usage for configuration data comes up repeatedly, I'd like to propose a flash-friendly and LAR/CBFS compatible way to store and update configuration data.
The CDFF data is stored inside an uncompressed LAR/CBFS archive member which occupies a full flash erase block, either with the start of the header at the start of the erase block or with the start of the data section at the start of the erase block.
The CDFF file format is as follows:
File Format header: 4 bytes magic header "CDFF" 4 bytes total length of CDFF area excluding file header
Configuration Data header: 2 bytes magic header "CD" 2 bytes version number of configuration data, at least 0x0001 (0x0000 means invalid) 4 bytes total length of Configuration Data excluding Configuration Data header
Configuration Item header (version 0x0001): 2 bytes magic header "CI" 2 bytes data type, must not be 0x0000 (which is reserved) 4 bytes length of Configuration Item n bytes of Configuration Item content
Each header is aligned at a 4 byte boundary.
The File Format header exists exactly once at the start. Directly after the File Format header, the first Configuration Data header starts. It is a "container" for multiple Configuration Items. The version number has to be at least 0x0001. To mark the Configuation Data as invalid, the version number is set to 0x0000 which is a flash-friendly operation possible without erase. If the version number is 0x0000, the reader skips over CD total length bytes starting after the header and looks for the next CD header aligned to the next 4 byte boundary. Directly after the Configuration Data header, the first Configuration Item header starts. It holds a single configuration item or its description. The CI data type MSB is 0 if the data is a value and 1 for the matching (null-terminated) name/description. After the data there is the next CI header aligned at the next 4 byte boundary.
If you need to update the data, simply write a new CD container with CI data directly after the end of the last valid CD container. If the write was successful, mark the previous container as invalid. If not, the old container will still be valid and everything is OK. If there's not enough room left for a new CD container, erase the whole block and write a new CDFF header, CD header and all CIs.
This scheme keeps flash wear at a minium, has safe updates (except in the case where all space is used up and the block has to be erased), is fast and easy to walk and extensible enough to last a lifetime.
Example file: 0x43444646 (CDFF magic) 0x00000FF8 (eraseblockisze 4096 - headersize 8) 0x4344 (CD magic) 0x0001 (version) 0xbla (CD length) 0x4349 (CI magic) 0x0001 (data type, data) 0x00000013 (CI length) "hda1:/boot/vmlinux\0" (data) 0xff (padding) 0x4349 (CI magic) 0x8001 (data type, description) 0x00000009 (CI length) "bootfile\0" 0xffffff (padding) 0x4349 (CI magic) 0x0002 (data type, data) 0x00000018 (CI length) "acpi=off root=/dev/sda2\0" (data) 0x4349 (CI magic) 0x8002 (data type, description) 0x0000000B (CI length) "bootparams\0" 0xff (padding)
Since the CI name is (optionally) stored along with the CI data, running out of data types is only possible if we have more than 32767 different CIs. Any config reader can just search for the name if it wants some data. The naming also avoids having a central registry about which data type has which number, an annoyance present with our current NVRAM scheme.
A checksum is possible (even in a mostly flash-friendly way), but it would have cluttered this design doc.
Regards, Carl-Daniel