diff --git a/Documentation/technotes/2015-11-rebuilding-coreboot-image-generation.md b/Documentation/technotes/2015-11-rebuilding-coreboot-image-generation.md new file mode 100644 index 0000000000..d2a8fdcc0d --- /dev/null +++ b/Documentation/technotes/2015-11-rebuilding-coreboot-image-generation.md @@ -0,0 +1,266 @@ +Rebuilding coreboot image generation +==================================== + +Current situation +----------------- +Chrome OS (CrOS) probably has the most complex image bundling process in the +coreboot ecosystem. To make CrOS features more accessible to the wider +coreboot community, we want to move these capabilities into upstream +coreboot’s build system. + +Right now, the CrOS build system creates coreboot images, and various +instances of the payload (with different configuration options), plus some +more files (eg. EC firmware), then passes them to a CrOS-specific utility +(`bundle_firmware.py`) to build the final image from that. + +`bundle_firmware` adds a flashmap (fmap) to the final image and creates +additional CBFS filesystems in fmap regions. It then extracts some files from +the original CBFS region (that was put in place carefully to later match to +the default fmap region) and copies some of them into the others, as well as +putting more data (eg. the bitmap data, keys) as raw data into other fmap +regions. + +With the recent addition of more files to CBFS, both on the coreboot side +(dsdt, FSP, and so on) and with Chrome OS specifics (eg. more files describing +boot screens) we either need to expand the scope of bundle\_firmware or move +the capability to build complex images to upstream coreboot’s build system. +This document proposes to do the latter and outlines how this could be +achieved. + +Problems with the current build system parts +-------------------------------------------- +One common sentiment is that it should be possible to reuse some of the +existing mechanisms that are supposed to be supplanted by this. +The main concern during this design that precluded their use was that none of +them provides a comprehensive solution to building complex coreboot based +images: +* fmap.dts and fmd provide a flash layout, but no assignment of files of regions +* cbfs-files-y ends up as an internal make variable using + `weird|formatting|to|deal|with|make’s|limitations` +* make isn’t powerful enough to deal with ordering these entries in said + variable to guarantee success if there’s enough room for the files. While that + could be added, that becomes more make macro work indistinguishable from magic + that people fail to understand, break and with good reason complain about + to work around such issues, Chrome OS firmware uses a custom tool with even + more special cases to finally build the image it needs. If coreboot upstream + is to support vboot, it should also be powerful enough not to need magic tools + that only live within downstream projects. + +Requirements +------------ +A complete Chrome OS coreboot image consists of (depending on the device) +* platform specific data in raw fmap regions (eg IFD, ME firmware), +* the bootblock (coming from the bootblock), +* three copies of coreboot, consisting of the stages (verstage, romstage, + ramstage) plus data, +* depthcharge plus data (with each of the coreboot copies), +* EC firmware files (with each of the coreboot copies), +* signatures over several parts of the image and +* some final checksumming over parts of the image to satisfy boot ROM + tests on ARM + +A complete upstream coreboot image (with fallback/normal switch configuration, +using a yet to be implemented switching scheme based on fmaps) consists of +* platform specific data in raw fmap regions (eg IFD, ME firmware), +* two copies of coreboot, consisting of + * the bootblock and + * the stages (romstage, ramstage) plus data, +* payload plus data (with each of the coreboot copies), + +Since a single platform is potentially built with different payload +configurations (eg. modding a Chromebook to not use the verified Chrome OS +boot scheme), some concerns need to be kept separate: +* Platform requirements that have nothing to do with the payload or boot schemes + * IFD, ME, … need to copied to the right place + * boot ROM requirements such as checksums must be honored +* Payload/boot scheme requirements + * Having one to three regions with certain files copied into them + +Proposal +-------- +The proposal is based on manifest files that describe certain aspects of the +final image. +The number of manifest files may change over time, but this seems to be a +reasonable approach for now. As long as coreboot uses fmap and cbfs, there +should be few need to change the language, since composition is done through +files. + +The final image is generated by a utility that is handed a number of manifests +and the size of the flash (derived from `CONFIG_ROM_SIZE`). These manifest files +deal with different concerns, with the following an example that should match +current use cases: + +Chipset manifest +---------------- +The chipset details if there are any non-coreboot regions, and assigns them +names, locations, sizes and file contents and prepares a region for what is +“platform visible” (eg. IFD’s BIOS region) that may be of flexible size +(depending on the flash chip’s size). For the purpose of this document, that +region is called “BIOS”. +It can also specify if there’s a post processing requirement on the final +image. + +coreboot manifest +----------------- +coreboot provides lists of the files it generates for each category it’s +building (eg. bootblock, verstage, romstage, ramstage). They not only contain +the stages themselves, but also additional files (eg. dsdt belongs to ramstage +since that’s where it is used) + +Boot method manifest +-------------------- +The boot method manifest can subdivide the BIOS region, eg. using it directly +(for coreboot’s “simple” bootblock), splitting it in two (for coreboot’s +fallback/normal) or in many parts (for Chrome OS, which requires two CBFS +regions, one for GBB, several for VPD, …). +It also specifies which of the file lists specified earlier belong in which +region (eg. with verstage verifying romstage, verstage needs to be only in +Chrome OS’ RO region, while romstage belongs in RO and both RW regions). +It can also specify a post processing step that is executed before the +chipset’s. + +Payload and additional manifests +-------------------------------- +External components should also provide manifests to add files to categories. +This way the payload and other components (eg. EC firmware) can be developed +without needing to touch the central boot method manifest (that likely resides +in the coreboot tree, given that coreboot needs to deal with choosing fmap +regions already). + +coreboot build system +--------------------- +The coreboot build system will be split more distinctly in two phases: The +first is about building the files (with results like romstage.elf), while the +second phase covers the assembly of the final image. + +By having a global picture of the final image’s requirements, we can also +avoid issues where files added earlier may prevent later additions that have +stricter constraints - without resorting to hacks like +https://chromium-review.googlesource.com/289491 that reorder the file addition +manually. + +Example +------- +As an example, we’ll define an Intel-based board with a postprocessing tool +(something that doesn’t exist, but isn’t hard to imagine): + +It specifies an IFD region, an ME, and the BIOS region. After the image is +built, the entire image needs to be processed (although the tool likely works +only on a small part of it) + +It’s built in a Chrome OS-like configuration (simplified at places to avoid +distracting from the important parts), so it has three CBFS regions, and +several data regions for its own purpose (similar to GBB, FWID, VPD, …). After +the regions are filled, one data region must be post-processed to contain +signatures to enable verifying other regions. + +Chipset manifest +================ +# A region called IFD, starting at 0, ending at 4K +region IFD: 0 4K +# Add the specified file “raw” into the region. +# If the file is smaller than the region, put it at the bottom and fill up +# with 0xff +raw IFD: build/ifd.bin align=bottom empty=0xff +# Call the postprocessor on the data that ends up in IFD (in this example it +# might lock the IFD) +postprocess IFD: util/ifdprocess -l + +# a region called ME, starting at 4K, ending at 2M +region ME: 4K 2M +raw ME: 3rdparty/blobs/soc/intel/xanadu/me.bin align=bottom empty=0x00 + +# a region called BIOS, starting at 2M, filling up the free space +# filling up fails (build error) if two regions are requested to fill up +# against each other +region BIOS: 2M * + +# This would define a region that covers the last 4K of flash. +# The BIOS region specified above will end right before it instead of +# expanding to end of flash +# region AUX: -4K -0 + +# specify the tool that post-processes the entire image. +postprocess image: util/intelchksum/intelchksum.sh + +coreboot manifest +================= +# declare that build/verstage.elf belongs into the group ‘verstage’ +# these groups are later referred to by the “cbfs” command. +group verstage: build/verstage.elf stage xip name=fallback/verstage +group romstage: build/romstage.elf stage xip name=fallback/romstage +group ramstage: build/ramstage.elf stage name=fallback/ramstage +compression=lzma +group ramstage: build/dsdt.aml compression=lzma + +boot method manifest +==================== +# Define RO as region inside BIOS, covering the upper half of the image. +# It’s a build error if the result crosses outside BIOS. +# math expressions are wrapped with ( ), +# and mentions of regions therein always refer to their size +subregion BIOS RO: ( image / 2 ) -0 + +# Define RW to cover the rest of BIOS. +# The order of RW and RO doesn’t matter except to keep comments clearer. +# Dynamic items like RW (“*”) will be sized to fill unused space after +# everything else is placed. +subregion BIOS RW: 0 * + +# It may be necessary to separate the RO/RW definition into another manifest +# file +# that defines the RO configuration of the flash + +# Some more subregions, with dynamically calculated sizes +subregion RW RW_A: 0 ( RW / 2 ) +subregion RW RW_B: * -0 +subregion RW_A FW_MAIN_A: RW_A * -0 +subregion RW_A VBLOCK_A: 0 64K +# foo +bar specifies start + size, not (start, end) +# also, start is given as “the end of VBLOCK_A” +# (while using a region in the “end” field means “start of region”) +subregion RW_A FWID_A: VBLOCK_A +64 + +# To make the example not too verbose, RO only has the CBFS region +subregion RO BOOTSTUB: 0 * + +# Postprocess the data that ends up in VBLOCK_A, +# passing the listed regions as additional arguments. +# Circular dependencies are build errors. +postprocess VBLOCK_A(FW_MAIN_A): signtool + +# binding files to regions indirectly through groups +cbfs BOOTSTUB: verstage, romstage, ramstage, payload +cbfs FW_MAIN_A: romstage, ramstage, payload + +# defining defaults: unless overridden, in all regions that use CBFS (“*”), +# we want all files to come with SHA256 hashes. +# Wildcard defaults have lower priority than specific defaults. +# Other conflicts lead to a build error. +cbfsdefaults *: hash=sha3 + +payload manifest +================ +group payload: payload.elf payload +group payload: bootscreen.jpg name=splashscreen.jpg type=splashscreen + +EC firmware manifest +==================== +# overrides the cbfsdefault above +group payload: ecrw.bin name=ecrw hash=sha256 +group payload: pdrw.bin name=pdrw hash=sha256 + +manifest parsing +================ +The exact BNF is work in progress. + +Some parser rules are +* one line per statement +* # introduces a command until the end of line + +Some processing rules +* When there’s a conflict (eg. two statements on what to do to a region, + overlap, anything that can’t be determined), that is a build error. +* the order of statements doesn’t matter, enabling simple addition of more + manifests where the need arises. +