User talk:MrNuke/CBFS Ideas

From coreboot
Jump to: navigation, search

Extending CBFS to support partitioning

Reasoning

  • To separate write-protected (RO) and writeable (RW) regions of flash chip
  • To incorporate relevant FMAP features directly into CBFS
  • To be able to better handle the requirements of ChromeOS

Tentative terminology

  • Partition
    • A region indexed by CBFS
  • File
    • Same meaning as before. A CBFS file that resides entirely within the boundaries of one partition.

Design constraints

  • Backwards compatibility
    • New CBFS structure should be backwards compatible with old structure
    • Old payloads should still be able to access old features of CBFS

Tentative API

  • cbfs_get_file(const char *name) <- Get file in main partition, also backwards compatible
  • cbfs_get_partition(const char *name) <- Get location of partition other than main (or even main)
  • cbfs_get_partition_file(cbfs_part_t partition, const char *name) <- Get file in given partition

Hypothetical examples

Partition in read-write portion of flash

Here, we assume that "rw1" is not in a write-protected area of flash.

void *rw1 = cbfs_get_partition("rw1");
file *romstage cbfs_get_partition_file(rw1, "fallback/romstage);
load_and_run_stage(romstage);

MRC cache

void *mrc_cache = cbfs_get_partition("mrc.cache");
/* Access raw partition, there is no file in this partition */
mrc_cache_check(mrc_cache);
mrc_cache_write(mrc_cache, data);

Technical stuff

Current CBFS master header

All values are big endian

Offset 0 1 2 3 4 5 6 7 8 9 A B C D E F
0x00 "ORBC" version romsize bootblocksize
0x10 align offset arch padding

The meaning of each member is as follows:

  • magic is a 32 bit number that identifies the ROM as a CBFS type. The magic number is 0x4F524243, which is 'ORBC' in ASCII.
  • version is a version number for CBFS header. cbfs_header structure may be different if version is not matched.
  • romsize is the size of the ROM in bytes. Coreboot will subtract 'size' from 0xFFFFFFFF to locate the beginning of the ROM in memory.
  • bootblocksize is the size of bootblock reserved in firmware image.
  • align is the number of bytes that each component is aligned to within the ROM. This is used to make sure that each component is aligned correctly with regards to the erase block sizes on the ROM - allowing one to replace a component at runtime without disturbing the others.
  • offset is the offset of the the first CBFS component (from the start of the ROM). This is to allow for arbitrary space to be left at the beginning of the ROM for things like embedded controller firmware.
  • architecture describes which architecture (x86, arm, ...) this CBFS is created for.


  • PROPOSED: Change padding to an offset pointing to partition table; all '1's means no partition table is available
    • The offset shall have the same meaning as all other offsets (from the start of ROM).
    • (PatrickG) alternatively: limit number of partitions to something reasonable, move names into partitions (so partition entries are fixed size) and append the partition table to the master header. Existence proven by master_header's version field (cbfs_core ignores it right now, which is good).
      • (mrnuke) Partition name in partition would violate the out-of-band metadata requirement. (adurbin can explain this better)
      • (mrnuke) Also, partition entries can be made fixed size by using Proposal 2 (similar to FMAP).

Proposal 1: Variable name length partition table

All values are big endian

Entry format
Offset 0 1 2 3 4 5 6 7 8 9 A B C D E F
0x00 "CBPT" offset size region_name
0x10 region_name ...
  • region_name shall be null-terminated.
  • Each partition entry shall be 16 byte aligned.
  • Subsequent entries shall be placed at the closest 16-byte aligned offset
Proposed partition table
Offset 0 1 2 3 4 5 6 7 8 9 A B C D E F
0x10 CBPT1
0x_0 CBPT2
0x_0 CBPT3
0x_0 terminator all '1's
  • Generally, CBPT1 will point to the same region as the master header, but this is not required. The idea is that old payloads will still be able to read CBFS by using the region pointed to by the master header. Whether this region is the same as CBPT1 or not is not guaranteed. This is to not impose a specific order on the partition entries.
Example partition table
Offset 0 1 2 3 4 5 6 7 8 9 A B C D E F
0x00 "CBPT" 0x00070000 0x00010000 c o r e
0x10 b o o t \0 0xff
0x20 "CBPT" 0x00040000 0x00020000 t h i s
0x30 _ p a r t i t i o n _ h a s _ a
0x40 _ l u d i c r o u s l y _ l o n
0x50 g . n a m e \0 0xff
0x60 "CBPT" 0x00060000 0x00010000 m r c .
0x70 c a c h e \0 0xff
0x80 0xffffffff
  • "coreboot": 0x00070000 + 0x00010000
  • "this_partition_has_a_ludicrously_long.name" 0x00040000 + 0x00020000
  • "mrc.cache": 0x00070000 + 0x00010000
Questions
  • Should region_name be fixed to 32-bytes, like in FMAP?
  • Should we include a field for partition flags?
    • What are the use-cases
    • Would this really be useful?
    • Would this actually get used in the wild?
  • Should we just use the FMAP format?

Proposal 2: Fixed name length partition table

Entry format
Offset 0 1 2 3 4 5 6 7 8 9 A B C D E F
0x00 "CBPT" offset size flags
0x10 region_name
0x20 region_name

Each entry shall be aligned to 16-bytes. This allows for easy identification of entries with hexdump -C. Non-aligned entries shall be considered invalid.

  • Partitions cannot overlap.
  • Partitions should not include the bootblock. (Should we allow a partition to specify the bootblock ?)
  • Partitions must be entirely contained within the ROM. This is handled by having the partition offest counted from the start of ROM. Other than that, partition_offset + partition_size <= size_of_rom.
  • Partition table shall be considered immutable (i.e. constant, readonly, and not user-replaceable). The only exception is in cbfstool, which shall allow manipulation of partitions.

The meaning of each member is as follows:

  • "CBPT" is a 32 bit number that identifies the entry as a CBFS partition entry. The is 'CBPT' in ASCII.
  • offset is the offset (from the start of the ROM) to the start of the partition.
  • size is the size of the partition in bytes.
  • flags is yet undefined.
    • FMAP defines the following three flags
      • STATIC: area's contents will not change
      • COMPRESSED: area holds potentially compressed data
      • RO: area is considered read-only
    • STATIC and RO flags seem to be redundant
    • FMAP flags seems to be of limited use
  • region_name shall be null-terminated.
    • It is always 32-bytes, but can be null-terminated earlier
    • Unused bytes will be all '1's
  • This structure is marginally easier to parse as opposed to variable length
Table format
Offset 0 1 2 3 4 5 6 7 8 9 A B C D E F
0x00 CBPT1
0x30 CBPT2
0x60 CBPT3
0x90 terminator all '1's
  • Generally, CBPT1 will point to the same region as the master header, but this is not required. The idea is that old payloads will still be able to read CBFS by using the region pointed to by the master header. Whether this region is the same as CBPT1 or not is not guaranteed. This is to not impose a specific order on the partition entries.
Example table
Offset 0 1 2 3 4 5 6 7 8 9 A B C D E F
0x00 "CBPT" 0x00070000 0x00010000 0x00000000
0x10 c o r e b o o t \0 0xff
0x20 0xff
0x30 "CBPT" 0x00040000 0x00020000 0x00000000
0x40 t h i s _ p a r t i t i o n _ h
0x50 a s _ a _ l u d i c r o u s l \0
0x60 "CBPT" 0x00060000 0x00010000 0x00000000
0x70 m r c . c a c h e \0 0xff
0x80 0xffffffff
0x90 0xffffffff
  • "coreboot": 0x00070000 + 0x00010000
  • "this_partition_has_a_ludicrousl" 0x00040000 + 0x00020000
  • "mrc.cache": 0x00070000 + 0x00010000