Drop duplicate version of the documentation/cbfs.txt file as discussed.
Signed-off-by: Uwe Hermann <uwe@hermann-uwe.de> Acked-by: Uwe Hermann <uwe@hermann-uwe.de> git-svn-id: svn://svn.coreboot.org/coreboot/trunk@4797 2b7e53f0-3cfb-0310-b3e9-8179ed1497e1
This commit is contained in:
parent
5e19eee460
commit
e052bb7a60
|
@ -1,337 +0,0 @@
|
|||
Coreboot CBFS Specification
|
||||
Jordan Crouse <jordan@cosmicpenguin.net>
|
||||
|
||||
= 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 (high end 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 - 0xFFFF0000 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:
|
||||
|
||||
struct cbfs_header {
|
||||
unsigned int magic;
|
||||
unsigned int version;
|
||||
unsigned int romsize;
|
||||
unsigned int bootblocksize;
|
||||
unsigned int align;
|
||||
unsigned int offset;
|
||||
unsigned int pad[2];
|
||||
};
|
||||
|
||||
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 32 bit number that identifies the version of CBFS. The current
|
||||
version is 0x31313131 ('1111' in ASCII) which is endian-independent.
|
||||
|
||||
'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 boot block size in bytes. There is no limitation on
|
||||
the boot block size as in v3.
|
||||
|
||||
'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.
|
||||
|
||||
'pad' rounds the header to 32 bytes and reserves a little room for later use.
|
||||
|
||||
= Bootblock =
|
||||
The bootblock is a mandatory component in the ROM. It is located in the
|
||||
last bootblocksize bytes of 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 - bootblocksize - '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:
|
||||
|
||||
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 Alogrithm ==
|
||||
|
||||
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:
|
||||
|
||||
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), 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:
|
||||
|
||||
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:
|
||||
|
||||
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:
|
||||
|
||||
PAYLOAD_SEGMENT_CODE 0x45444F43 The segment contains executable code
|
||||
PAYLOAD_SEGMENT_DATA 0x41544144 The segment contains data
|
||||
PAYLOAD_SEGMENT_BSS 0x20535342 The memory speicfied 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),
|
||||
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.
|
Loading…
Reference in New Issue