summaryrefslogtreecommitdiff
path: root/util/romtool/README
diff options
context:
space:
mode:
Diffstat (limited to 'util/romtool/README')
-rw-r--r--util/romtool/README358
1 files changed, 358 insertions, 0 deletions
diff --git a/util/romtool/README b/util/romtool/README
new file mode 100644
index 0000000000..10c5cdf5d6
--- /dev/null
+++ b/util/romtool/README
@@ -0,0 +1,358 @@
+Coreboot ROMFS Specification
+Jordan Crouse <jordan@cosmicpenguin.net>
+
+= Introduction =
+
+This document describes the coreboot ROMFS specification (from here referred
+to as ROMFS). ROMFS 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 ROMFS architecture looks like the following:
+
+/---------------\ <-- Start of ROM
+| /-----------\ | --|
+| | Header | | |
+| |-----------| | |
+| | Name | | |-- Component
+| |-----------| | |
+| |Data | | |
+| |.. | | |
+| \-----------/ | --|
+| |
+| /-----------\ |
+| | Header | |
+| |-----------| |
+| | Name | |
+| |-----------| |
+| |Data | |
+| |.. | |
+| \-----------/ |
+| |
+| ... |
+| /-----------\ |
+| | | |
+| | Bootblock | |
+| | --------- | |
+| | Reset | | <- 0xFFFFFFF0
+| \-----------/ |
+\---------------/
+
+
+The ROMFS 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 ROMFS component within the ROM.
+
+= Master Header =
+
+The master header contains essential information about the ROM that is
+used by both the ROMFS 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 romfs_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 ROMFS type. The magic
+number is 0x4F524243, which is 'ORBC' in ASCII.
+
+'version' is a 32 bit number that identifies the version of ROMFS. 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 ROMFS 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 bits 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 =
+
+ROMFS 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 ROMFS
+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 ROMFS component will be indexed with a unique ASCII string name of
+unlimited size.
+
+Each ROMFS component starts with a header:
+
+struct ROMFS_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 romfs_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 ROMFS 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 ROMFS 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 romfs_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 romfs_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 romfs_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 romfs_payload {
+ struct romfs_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 romfs_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.
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+