/ Documentation / technotes / 2015-11-rebuilding-coreboot-image-generation.md
2015-11-rebuilding-coreboot-image-generation.md
  1  Rebuilding coreboot image generation
  2  ====================================
  3  
  4  Current situation
  5  -----------------
  6  ChromeOS (CrOS) probably has the most complex image bundling process in the
  7  coreboot ecosystem. To make CrOS features more accessible to the wider
  8  coreboot community, we want to move these capabilities into upstream
  9  coreboot’s build system.
 10  
 11  Right now, the CrOS build system creates coreboot images, and various
 12  instances of the payload (with different configuration options), plus some
 13  more files (eg. EC firmware), then passes them to a CrOS-specific utility
 14  (`bundle_firmware.py`) to build the final image from that.
 15  
 16  `bundle_firmware` adds a flashmap (fmap) to the final image and creates
 17  additional CBFS filesystems in fmap regions. It then extracts some files from
 18  the original CBFS region (that was put in place carefully to later match to
 19  the default fmap region) and copies some of them into the others, as well as
 20  putting more data (eg. the bitmap data, keys) as raw data into other fmap
 21  regions.
 22  
 23  With the recent addition of more files to CBFS, both on the coreboot side
 24  (dsdt, FSP, and so on) and with ChromeOS specifics (eg. more files describing
 25  boot screens) we either need to expand the scope of bundle\_firmware or move
 26  the capability to build complex images to upstream coreboot’s build system.
 27  This document proposes to do the latter and outlines how this could be
 28  achieved.
 29  
 30  Problems with the current build system parts
 31  --------------------------------------------
 32  One common sentiment is that it should be possible to reuse some of the
 33  existing mechanisms that are supposed to be supplanted by this.
 34  The main concern during this design that precluded their use was that none of
 35  them provides a comprehensive solution to building complex coreboot based
 36  images:
 37  * fmap.dts and fmd provide a flash layout, but no assignment of files of regions
 38  * cbfs-files-y ends up as an internal make variable using
 39    `weird|formatting|to|deal|with|make’s|limitations`
 40  * make isn’t powerful enough to deal with ordering these entries in said
 41    variable to guarantee success if there’s enough room for the files. While that
 42    could be added, that becomes more make macro work indistinguishable from magic
 43    that people fail to understand, break and with good reason complain about
 44    to work around such issues, ChromeOS firmware uses a custom tool with even
 45    more special cases to finally build the image it needs. If coreboot upstream
 46    is to support vboot, it should also be powerful enough not to need magic tools
 47    that only live within downstream projects.
 48  
 49  Requirements
 50  ------------
 51  A complete ChromeOS coreboot image consists of (depending on the device)
 52  * platform specific data in raw fmap regions (eg IFD, ME firmware),
 53  * the bootblock (coming from the bootblock),
 54  * three copies of coreboot, consisting of the stages (verstage, romstage,
 55    ramstage) plus data,
 56  * depthcharge plus data (with each of the coreboot copies),
 57  * EC firmware files (with each of the coreboot copies),
 58  * signatures over several parts of the image and
 59  * some final checksumming over parts of the image to satisfy boot ROM
 60    tests on ARM
 61  
 62  A complete upstream coreboot image (with fallback/normal switch configuration,
 63  using a yet to be implemented switching scheme based on fmaps) consists of
 64  * platform specific data in raw fmap regions (eg IFD, ME firmware),
 65  * two copies of coreboot, consisting of
 66   * the bootblock and
 67   * the stages (romstage, ramstage) plus data,
 68  * payload plus data (with each of the coreboot copies),
 69  
 70  Since a single platform is potentially built with different payload
 71  configurations (eg. modding a Chromebook to not use the verified ChromeOS
 72  boot scheme), some concerns need to be kept separate:
 73  * Platform requirements that have nothing to do with the payload or boot schemes
 74   * IFD, ME, … need to copied to the right place
 75   * boot ROM requirements such as checksums must be honored
 76  * Payload/boot scheme requirements
 77   * Having one to three regions with certain files copied into them
 78  
 79  Proposal
 80  --------
 81  The proposal is based on manifest files that describe certain aspects of the
 82  final image.
 83  The number of manifest files may change over time, but this seems to be a
 84  reasonable approach for now. As long as coreboot uses fmap and cbfs, there
 85  should be few need to change the language, since composition is done through
 86  files.
 87  
 88  The final image is generated by a utility that is handed a number of manifests
 89  and the size of the flash (derived from `CONFIG_ROM_SIZE`). These manifest files
 90  deal with different concerns, with the following an example that should match
 91  current use cases:
 92  
 93  Chipset manifest
 94  ----------------
 95  The chipset details if there are any non-coreboot regions, and assigns them
 96  names, locations, sizes and file contents and prepares a region for what is
 97  “platform visible” (eg. IFD’s BIOS region) that may be of flexible size
 98  (depending on the flash chip’s size). For the purpose of this document, that
 99  region is called “BIOS”.
100  It can also specify if there’s a post processing requirement on the final
101  image.
102  
103  coreboot manifest
104  -----------------
105  coreboot provides lists of the files it generates for each category it’s
106  building (eg. bootblock, verstage, romstage, ramstage). They not only contain
107  the stages themselves, but also additional files (eg. dsdt belongs to ramstage
108  since that’s where it is used)
109  
110  Boot method manifest
111  --------------------
112  The boot method manifest can subdivide the BIOS region, eg. using it directly
113  (for coreboot’s “simple” bootblock), splitting it in two (for coreboot’s
114  fallback/normal) or in many parts (for ChromeOS, which requires two CBFS
115  regions, one for GBB, several for VPD, …).
116  It also specifies which of the file lists specified earlier belong in which
117  region (eg. with verstage verifying romstage, verstage needs to be only in
118  ChromeOS’ RO region, while romstage belongs in RO and both RW regions).
119  It can also specify a post processing step that is executed before the
120  chipset’s.
121  
122  Payload and additional manifests
123  --------------------------------
124  External components should also provide manifests to add files to categories.
125  This way the payload and other components (eg. EC firmware) can be developed
126  without needing to touch the central boot method manifest (that likely resides
127  in the coreboot tree, given that coreboot needs to deal with choosing fmap
128  regions already).
129  
130  coreboot build system
131  ---------------------
132  The coreboot build system will be split more distinctly in two phases: The
133  first is about building the files (with results like romstage.elf), while the
134  second phase covers the assembly of the final image.
135  
136  By having a global picture of the final image’s requirements, we can also
137  avoid issues where files added earlier may prevent later additions that have
138  stricter constraints - without resorting to hacks like
139  <https://chromium-review.googlesource.com/289491> that reorder the file
140  addition manually.
141  
142  Example
143  -------
144  As an example, we’ll define an Intel-based board with a postprocessing tool
145  (something that doesn’t exist, but isn’t hard to imagine):
146  
147  It specifies an IFD region, an ME, and the BIOS region. After the image is
148  built, the entire image needs to be processed (although the tool likely works
149  only on a small part of it)
150  
151  It’s built in a ChromeOS-like configuration (simplified at places to avoid
152  distracting from the important parts), so it has three CBFS regions, and
153  several data regions for its own purpose (similar to GBB, FWID, VPD, …). After
154  the regions are filled, one data region must be post-processed to contain
155  signatures to enable verifying other regions.
156  
157  ```
158  Chipset manifest
159  ================
160  # A region called IFD, starting at 0, ending at 4K
161  region IFD: 0 4K
162  # Add the specified file “raw” into the region.
163  # If the file is smaller than the region, put it at the bottom and fill up
164  # with 0xff
165  raw IFD: build/ifd.bin align=bottom empty=0xff
166  # Call the postprocessor on the data that ends up in IFD (in this example it
167  # might lock the IFD)
168  postprocess IFD: util/ifdprocess -l
169  
170  # a region called ME, starting at 4K, ending at 2M
171  region ME: 4K 2M
172  raw ME: 3rdparty/blobs/soc/intel/xanadu/me.bin align=bottom empty=0x00
173  
174  # a region called BIOS, starting at 2M, filling up the free space
175  # filling up fails (build error) if two regions are requested to fill up
176  # against each other
177  region BIOS: 2M *
178  
179  # This would define a region that covers the last 4K of flash.
180  # The BIOS region specified above will end right before it instead of
181  # expanding to end of flash
182  # region AUX: -4K -0
183  
184  # specify the tool that post-processes the entire image.
185  postprocess image: util/intelchksum/intelchksum.sh
186  
187  coreboot manifest
188  =================
189  # declare that build/verstage.elf belongs into the group ‘verstage’
190  # these groups are later referred to by the “cbfs” command.
191  group verstage: build/verstage.elf stage xip name=fallback/verstage
192  group romstage: build/romstage.elf stage xip name=fallback/romstage
193  group ramstage: build/ramstage.elf stage name=fallback/ramstage
194  compression=lzma
195  group ramstage: build/dsdt.aml compression=lzma
196  
197  boot method manifest
198  ====================
199  # Define RO as region inside BIOS, covering the upper half of the image.
200  # It’s a build error if the result crosses outside BIOS.
201  # math expressions are wrapped with ( ),
202  # and mentions of regions therein always refer to their size
203  subregion BIOS RO: ( image / 2 ) -0
204  
205  # Define RW to cover the rest of BIOS.
206  # The order of RW and RO doesn’t matter except to keep comments clearer.
207  # Dynamic items like RW (“*”) will be sized to fill unused space after
208  # everything else is placed.
209  subregion BIOS RW: 0 *
210  
211  # It may be necessary to separate the RO/RW definition into another manifest
212  # file
213  # that defines the RO configuration of the flash
214  
215  # Some more subregions, with dynamically calculated sizes
216  subregion RW RW_A: 0 ( RW / 2 )
217  subregion RW RW_B: * -0
218  subregion RW_A FW_MAIN_A: RW_A * -0
219  subregion RW_A VBLOCK_A: 0 64K
220  # foo +bar specifies start + size, not (start, end)
221  # also, start is given as “the end of VBLOCK_A”
222  # (while using a region in the “end” field means “start of region”)
223  subregion RW_A FWID_A: VBLOCK_A +64
224  
225  # To make the example not too verbose, RO only has the CBFS region
226  subregion RO BOOTSTUB: 0 *
227  
228  # Postprocess the data that ends up in VBLOCK_A,
229  # passing the listed regions as additional arguments.
230  # Circular dependencies are build errors.
231  postprocess VBLOCK_A(FW_MAIN_A): signtool
232  
233  # binding files to regions indirectly through groups
234  cbfs BOOTSTUB: verstage, romstage, ramstage, payload
235  cbfs FW_MAIN_A: romstage, ramstage, payload
236  
237  # defining defaults: unless overridden, in all regions that use CBFS (“*”),
238  # we want all files to come with SHA256 hashes.
239  # Wildcard defaults have lower priority than specific defaults.
240  # Other conflicts lead to a build error.
241  cbfsdefaults *: hash=sha3
242  
243  payload manifest
244  ================
245  group payload: payload.elf payload
246  group payload: bootscreen.jpg name=splashscreen.jpg type=splashscreen
247  
248  EC firmware manifest
249  ====================
250  # overrides the cbfsdefault above
251  group payload: ecrw.bin name=ecrw hash=sha256
252  group payload: pdrw.bin name=pdrw hash=sha256
253  ```
254  
255  manifest parsing
256  ----------------
257  The exact BNF is work in progress.
258  
259  Some parser rules are
260  * one line per statement
261  * '#' introduces a command until the end of line
262  
263  Some processing rules
264  * When there’s a conflict (eg. two statements on what to do to a region,
265    overlap, anything that can’t be determined), that is a build error.
266  * the order of statements doesn’t matter, enabling simple addition of more
267    manifests where the need arises.
268