Patrick Rudolph has uploaded this change for review. ( https://review.coreboot.org/c/coreboot/+/33663
Change subject: Documentation: Convert cbfs.txt to markdown ......................................................................
Documentation: Convert cbfs.txt to markdown
Convert the document to markdown. Needs to be fixed in a separate commit as it doesn't reflect coreboot v4.
Change-Id: I0fb2713a9cda08e528902ec641dd4a4e0dc148fe Signed-off-by: Patrick Rudolph patrick.rudolph@9elements.com --- A Documentation/lib/cbfs.md M Documentation/lib/index.md 2 files changed, 372 insertions(+), 0 deletions(-)
git pull ssh://review.coreboot.org:29418/coreboot refs/changes/63/33663/1
diff --git a/Documentation/lib/cbfs.md b/Documentation/lib/cbfs.md new file mode 100644 index 0000000..83d8b44 --- /dev/null +++ b/Documentation/lib/cbfs.md @@ -0,0 +1,371 @@ +# coreboot CBFS Specification +by Jordan Crouse jordan@cosmicpenguin.net + +**WARNING: This documentation is written against coreboot v1.** + +**TODO: Update this document ASAP** + +## Introduction + +This document describes the coreboot CBFS specification (from here +referred to as CBFS). CBFS is a scheme for managing independent chunks +of data in a system ROM. Though not a true filesystem, the style and +concepts are similar. + + +## Architecture + +The CBFS architecture looks like the following: + +``` +/---------------\ <-- Start of ROM +| /-----------\ | --| +| | Header | | | +| |-----------| | | +| | Name | | |-- Component +| |-----------| | | +| |Data | | | +| |.. | | | +| -----------/ | --| +| | +| /-----------\ | +| | Header | | +| |-----------| | +| | Name | | +| |-----------| | +| |Data | | +| |.. | | +| -----------/ | +| | +| ... | +| /-----------\ | +| | | | +| | Bootblock | | +| | --------- | | +| | Reset | | <- 0xFFFFFFF0 +| -----------/ | +---------------/ +``` + +The CBFS architecture consists of a binary associated with a physical +ROM disk referred hereafter as the ROM. A number of independent of +components, each with a header prepended on to data are located within +the ROM. The components are nominally arranged sequentially, though they +are aligned along a pre-defined boundary. + +The bootblock occupies the last 20k of the ROM. Within +the bootblock is a master header containing information about the ROM +including the size, alignment of the components, and the offset of the +start of the first CBFS component within the ROM. + +## Master Header + +The master header contains essential information about the ROM that is +used by both the CBFS implementation within coreboot at runtime as well +as host based utilities to create and manage the ROM. The master header +will be located somewhere within the bootblock (last 20k of the ROM). A +pointer to the location of the header will be located at offset +-4 from the end of the ROM. This translates to address 0xFFFFFFFC on a +normal x86 system. The pointer will be to physical memory somewhere +between - 0xFFFFB000 and 0xFFFFFFF0. This makes it easier for coreboot +to locate the header at run time. Build time utilities will +need to read the pointer and do the appropriate math to locate the header. + +The following is the structure of the master header: + +```c +struct cbfs_header { + u32 magic; + u32 version; + u32 romsize; + u32 bootblocksize; + u32 align; + u32 offset; + u32 architecture; + u32 pad[1]; +} __packed; +``` + +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 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. + +## Bootblock +The bootblock is a mandatory component in the ROM. It is located in the +last 20k of the ROM space, and contains, among other things, the location of the +master header and the entry point for the loader firmware. The bootblock +does not have a component header attached to it. + +## Components + +CBFS components are placed in the ROM starting at 'offset' specified in +the master header and ending at the bootblock. Thus the total size +available for components in the ROM is (ROM size - 20k - 'offset'). +Each CBFS component is to be aligned according to the 'align' value in the +header. +Thus, if a component of size 1052 is located at offset 0 with an 'align' +value of 1024, the next component will be located at offset 2048. + +Each CBFS component will be indexed with a unique ASCII string name of +unlimited size. + +Each CBFS component starts with a header: + +```c +struct cbfs_file { + char magic[8]; + unsigned int len; + unsigned int type; + unsigned int checksum; + unsigned int offset; +}; +``` + +`magic` is a magic value used to identify the header. During runtime, +coreboot will scan the ROM looking for this value. The default magic is +the string 'LARCHIVE'. + +`len` is the length of the data, not including the size of the header and +the size of the name. + +`type` is a 32 bit number indicating the type of data that is attached. +The data type is used in a number of ways, as detailed in the section +below. + +`checksum` is a 32bit checksum of the entire component, including the +header and name. + +`offset` is the start of the component data, based off the start of the +header. +The difference between the size of the header and offset is the size of the +component name. + +Immediately following the header will be the name of the component, +which will null terminated and 16 byte aligned. The following picture shows the +structure of the header: + +``` +/--------\ <- start +| Header | +|--------| <- sizeof(struct cbfs_file) +| Name | +|--------| <- 'offset' +| Data | +| ... | +--------/ <- start + 'offset' + 'len' +``` + +### Searching Algorithm + +To locate a specific component in the ROM, one starts at the 'offset' +specified in the CBFS master header. For this example, the offset will +be 0. + +From that offset, the code should search for the magic string on the +component, jumping 'align' bytes each time. So, assuming that 'align' is +16, the code will search for the string 'LARCHIVE' at offset 0, 16, 32, etc. +If the offset ever exceeds the allowable range for CBFS components, then no +component was found. + +Upon recognizing a component, the software then has to search for the +specific name of the component. This is accomplished by comparing the +desired name with the string on the component located at +`offset + sizeof(struct cbfs_file)`. If the string matches, then the +component has been located, otherwise the software should add +`'offset' + 'len'` to the offset and resume the search for the magic value. + +### Data Types + +The 'type' member of struct cbfs_file is used to identify the content +of the component data, and is used by coreboot and other +run-time entities to make decisions about how to handle the data. + +There are three component types that are essential to coreboot, and so +are defined here. + +#### Stages + +Stages are code loaded by coreboot during the boot process. They are +essential to a successful boot. Stages are comprised of a single blob +of binary data that is to be loaded into a particular location in memory +and executed. The uncompressed header contains information about how +large the data is, and where it should be placed, and what additional memory +needs to be cleared. + +Stages are assigned a component value of 0x10. When coreboot sees this +component type, it knows that it should pass the data to a sub-function +that will process the stage. + +The following is the format of a stage component: + +``` +/--------\ +| Header | +|--------| +| Binary | +| .. | +--------/ +``` + +The header is defined as: + +```c +struct cbfs_stage { + unsigned int compression; + unsigned long long entry; + unsigned long long load; + unsigned int len; + unsigned int memlen; +}; +``` + +`compression` is an integer defining how the data is compressed. There +are three compression types defined by this version of the standard: +none (0x0), lzma (0x1), and nrv2b (0x02, deprecated), though additional +types may be added assuming that coreboot understands how to handle the scheme. + +`entry` is a 64 bit value indicating the location where the program +counter should jump following the loading of the stage. This should be +an absolute physical memory address. + +`load` is a 64 bit value indicating where the subsequent data should be +loaded. This should be an absolute physical memory address. + +`len` is the length of the compressed data in the component. + +`memlen` is the amount of memory that will be used by the component when +it is loaded. + +The component data will start immediately following the header. + +When coreboot loads a stage, it will first zero the memory from 'load' to +'memlen'. It will then decompress the component data according to the +specified scheme and place it in memory starting at 'load'. Following that, +it will jump execution to the address specified by 'entry'. +Some components are designed to execute directly from the ROM - coreboot +knows which components must do that and will act accordingly. + +#### Payloads + +Payloads are loaded by coreboot following the boot process. + +Stages are assigned a component value of 0x20. When coreboot sees this +component type, it knows that it should pass the data to a sub-function +that will process the payload. Furthermore, other run time applications such +as 'bayou' may easily index all available payloads +on the system by searching for the payload type. + + +The following is the format of a stage component: + +``` +/-----------\ +| Header | +| Segment 1 | +| Segment 2 | +| ... | +|-----------| +| Binary | +| .. | +-----------/ +``` + +The header is as follows: + +```c +struct cbfs_payload { + struct cbfs_payload_segment segments; +} +``` + +The header contains a number of segments corresponding to the segments +that need to be loaded for the payload. + +The following is the structure of each segment header: + +```c +struct cbfs_payload_segment { + unsigned int type; + unsigned int compression; + unsigned int offset; + unsigned long long load_addr; + unsigned int len; + unsigned int mem_len; +}; +``` + +`type` is the type of segment, one of the following: + +```eval_rst ++----------------------+-------------+---------------------------------------+ +|PAYLOAD_SEGMENT_CODE | 0x45444F43 | The segment contains executable code | ++----------------------+-------------+---------------------------------------+ +|PAYLOAD_SEGMENT_DATA | 0x41544144 | The segment contains data | ++----------------------+-------------+---------------------------------------+ +|PAYLOAD_SEGMENT_BSS | 0x20535342 | The memory specified by the segment | +| | | should be zeroed | ++----------------------+-------------+---------------------------------------+ +|PAYLOAD_SEGMENT_PARAMS| 0x41524150 | The segment contains information for | +| | | the payload | ++----------------------+-------------+---------------------------------------+ +|PAYLOAD_SEGMENT_ENTRY | 0x52544E45 | The segment contains the entry point | +| | | for the payload | ++----------------------+-------------+---------------------------------------+ +``` + +`compression` is the compression scheme for the segment. Each segment can +be independently compressed. There are three compression types defined by +this version of the standard: none (0x0), lzma (0x1), and nrv2b +(0x02, deprecated), though additional types may be added assuming that +coreboot understands how to handle the scheme. + +`offset` is the address of the data within the component, starting from +the component header. + +`load_addr` is a 64 bit value indicating where the segment should be placed +in memory. + +`len` is a 32 bit value indicating the size of the segment within the +component. + +`mem_len` is the size of the data when it is placed into memory. + +The data will located immediately following the last segment. + +#### Option ROMS + +The third specified component type will be Option ROMs. Option ROMS will +have component type '0x30'. They will have no additional header, the +uncompressed binary data will be located in the data portion of the +component. + +#### NULL + +There is a 4th component type ,defined as NULL (0xFFFFFFFF). This is +the "don't care" component type. This can be used when the component +type is not necessary (such as when the name of the component is unique. +i.e. option_table). It is recommended that all components be assigned a +unique type, but NULL can be used when the type does not matter. diff --git a/Documentation/lib/index.md b/Documentation/lib/index.md index 99b8061..808bac8 100644 --- a/Documentation/lib/index.md +++ b/Documentation/lib/index.md @@ -6,4 +6,5 @@ ## Structure and layout - [Flashmap and Flashmap Descriptor](flashmap.md) - [ABI data consumption](abi-data-consumption.md) +- [CBFS](cbfs.md) - [Timestamps](timestamp.md)