1 2Received: from www.crouse-house.com ([199.45.160.146] 3 for [email protected]; Fri, 19 Dec 2008 23:11:59 +0100 4From: Jordan Crouse <[email protected]> 5 6 7Greetings. I apologize for the incompleteness of what I am about to 8discuss. I was planning on working on it leisurely, but my employment 9circumstances changed and I've been trying to get it completed in a 10hurry before I had to leave it behind. 11 12I've been thinking a lot about LAR lately, and ways to make it more 13extensible and robust. Marc and I have been trading ideas back and 14forth for a number of months, and over time a clear idea of what I 15wanted to do started to take shape. 16 17My goal was to add small things to LAR while retaining the overall 18scheme. Over time, the scheme evolved slightly, but I think you'll find 19that it remains true to the original idea. Below is the beginnings of 20an architecture document - I did it in text form, but if met with 21aclaim, it should be wikified. This presents what I call CBFS - the 22next generation LAR for next generation coreboot. Its easier to 23describe what it is by describing what changed: 24 25A header has been added somewhere in the bootblock similar to Carl 26Daniel's scheme. In addition to the coreboot information, the header 27reports the size of the ROM, the alignment of the blocks, and the offset 28of the first component in the CBFS. The master header provides all 29the information LAR needs plus the magic number information flashrom needs. 30 31Each "file" (or component, as I style them) now has a type associated 32with it. The type is used by coreboot to identify the type of file that 33it is loading, and it can also be used by payloads to group items in the 34CBFS by type (i.e - bayou can ask for all components that are payloads). 35 36The header on each "file" (or component, as I like to style them) has 37been simplified - We now only store the length, the type, the checksum, 38and the offset to the data. The name scheme remains the same. The 39additional information, which is component specific, has been moved to 40the component itself (see below). 41 42The components are arranged in the ROM aligned along the specified 43alignment from the master header - this is to facilitate partial re-write. 44 45Other then that, the LAR ideas remain pretty much the same. 46 47The plan for moving the metadata to the components is to allow many 48different kinds of components, not all of which are groked by coreboot. 49 However, there are three essential component types that are groked by 50coreboot, and they are defined: 51 52stage - the stage is being parsed from the original ELF, and stored in 53the ROM as a single blob of binary data. The load address, start 54address, compression type and length are stored in the component sub-header. 55 56payload - this is essentially SELF in different clothing - same idea as 57SELF, with the sub-header as above. 58 59optionrom - This is in flux - right now, the optionrom is stored 60unadulterated and uncompressed, but that is likely to be changed. 61 62Following this email are two replies containing the v3 code and a new 63ROM tool to implement this respectively. I told you that I was trying 64to get this out before I disappear, and I'm not kidding - the code is 65compile tested and not run-tested. I hope that somebody will embrace 66this code and take it the rest of the way, otherwise it will die a 67pretty short death. 68 69I realize that this will start an awesome flamewar, and I'm looking 70forward to it. Thanks for listening to me over the years - and good 71luck with coreboot. When you all make a million dollars, send me a few 72bucks, will you? 73 74Jordan 75 76coreboot CBFS Specification 77Jordan Crouse <[email protected]> 78 79= Introduction = 80 81This document describes the coreboot CBFS specification (from here 82referred to as CBFS). CBFS is a scheme for managing independent chunks 83of data in a system ROM. Though not a true filesystem, the style and 84concepts are similar. 85 86 87= Architecture = 88 89The CBFS architecture looks like the following: 90 91/---------------\ <-- Start of ROM 92| /-----------\ | --| 93| | Header | | | 94| |-----------| | | 95| | Name | | |-- Component 96| |-----------| | | 97| |Data | | | 98| |.. | | | 99| \-----------/ | --| 100| | 101| /-----------\ | 102| | Header | | 103| |-----------| | 104| | Name | | 105| |-----------| | 106| |Data | | 107| |.. | | 108| \-----------/ | 109| | 110| ... | 111| /-----------\ | 112| | | | 113| | Bootblock | | 114| | --------- | | 115| | Reset | | <- 0xFFFFFFF0 116| \-----------/ | 117\---------------/ 118 119 120The CBFS architecture consists of a binary associated with a physical 121ROM disk referred hereafter as the ROM. A number of independent of 122components, each with a header prepended on to data are located within 123the ROM. The components are nominally arranged sequentially, though they 124are aligned along a pre-defined boundary. 125 126The bootblock occupies the last 20k of the ROM. Within 127the bootblock is a master header containing information about the ROM 128including the size, alignment of the components, and the offset of the 129start of the first CBFS component within the ROM. 130 131= Master Header = 132 133The master header contains essential information about the ROM that is 134used by both the CBFS implementation within coreboot at runtime as well 135as host based utilities to create and manage the ROM. The master header 136will be located somewhere within the bootblock (last 20k of the ROM). A 137pointer to the location of the header will be located at offset 138-4 from the end of the ROM. This translates to address 0xFFFFFFFC on a 139normal x86 system. The pointer will be to physical memory somewhere 140between - 0xFFFFB000 and 0xFFFFFFF0. This makes it easier for coreboot 141to locate the header at run time. Build time utilities will 142need to read the pointer and do the appropriate math to locate the header. 143 144The following is the structure of the master header: 145 146struct cbfs_header { 147 u32 magic; 148 u32 version; 149 u32 romsize; 150 u32 bootblocksize; 151 u32 align; 152 u32 offset; 153 u32 architecture; 154 u32 pad[1]; 155} __packed; 156 157The meaning of each member is as follows: 158 159'magic' is a 32 bit number that identifies the ROM as a CBFS type. The 160magic 161number is 0x4F524243, which is 'ORBC' in ASCII. 162 163'version' is a version number for CBFS header. cbfs_header structure may be 164different if version is not matched. 165 166'romsize' is the size of the ROM in bytes. coreboot will subtract 'size' from 1670xFFFFFFFF to locate the beginning of the ROM in memory. 168 169'bootblocksize' is the size of bootblock reserved in firmware image. 170 171'align' is the number of bytes that each component is aligned to within the 172ROM. This is used to make sure that each component is aligned correctly 173with 174regards to the erase block sizes on the ROM - allowing one to replace a 175component at runtime without disturbing the others. 176 177'offset' is the offset of the first CBFS component (from the start of 178the ROM). This is to allow for arbitrary space to be left at the beginning 179of the ROM for things like embedded controller firmware. 180 181'architecture' describes which architecture (x86, arm, ...) this CBFS is created 182for. 183 184= Bootblock = 185The bootblock is a mandatory component in the ROM. It is located in the 186last 18720k of the ROM space, and contains, among other things, the location of the 188master header and the entry point for the loader firmware. The bootblock 189does not have a component header attached to it. 190 191= Components = 192 193CBFS components are placed in the ROM starting at 'offset' specified in 194the master header and ending at the bootblock. Thus the total size 195available 196for components in the ROM is (ROM size - 20k - 'offset'). Each CBFS 197component is to be aligned according to the 'align' value in the header. 198Thus, if a component of size 1052 is located at offset 0 with an 'align' 199value 200of 1024, the next component will be located at offset 2048. 201 202Each CBFS component will be indexed with a unique ASCII string name of 203unlimited size. 204 205Each CBFS component starts with a header: 206 207struct cbfs_file { 208 char magic[8]; 209 unsigned int len; 210 unsigned int type; 211 unsigned int checksum; 212 unsigned int offset; 213}; 214 215'magic' is a magic value used to identify the header. During runtime, 216coreboot will scan the ROM looking for this value. The default magic is 217the string 'LARCHIVE'. 218 219'len' is the length of the data, not including the size of the header and 220the size of the name. 221 222'type' is a 32 bit number indicating the type of data that is attached. 223The data type is used in a number of ways, as detailed in the section 224below. 225 226'checksum' is a 32bit checksum of the entire component, including the 227header and name. 228 229'offset' is the start of the component data, based off the start of the 230header. 231The difference between the size of the header and offset is the size of the 232component name. 233 234Immediately following the header will be the name of the component, 235which will 236null terminated and 16 byte aligned. The following picture shows the 237structure of the header: 238 239/--------\ <- start 240| Header | 241|--------| <- sizeof(struct cbfs_file) 242| Name | 243|--------| <- 'offset' 244| Data | 245| ... | 246\--------/ <- start + 'offset' + 'len' 247 248== Searching Algorithm == 249 250To locate a specific component in the ROM, one starts at the 'offset' 251specified in the CBFS master header. For this example, the offset will 252be 0. 253 254 From that offset, the code should search for the magic string on the 255component, jumping 'align' bytes each time. So, assuming that 'align' is 25616, the code will search for the string 'LARCHIVE' at offset 0, 16, 32, etc. 257If the offset ever exceeds the allowable range for CBFS components, then no 258component was found. 259 260Upon recognizing a component, the software then has to search for the 261specific name of the component. This is accomplished by comparing the 262desired name with the string on the component located at 263offset + sizeof(struct cbfs_file). If the string matches, then the 264component 265has been located, otherwise the software should add 'offset' + 'len' to 266the offset and resume the search for the magic value. 267 268== Data Types == 269 270The 'type' member of struct cbfs_file is used to identify the content 271of the component data, and is used by coreboot and other 272run-time entities to make decisions about how to handle the data. 273 274There are three component types that are essential to coreboot, and so 275are defined here. 276 277=== Stages === 278 279Stages are code loaded by coreboot during the boot process. They are 280essential to a successful boot. Stages are comprised of a single blob 281of binary data that is to be loaded into a particular location in memory 282and executed. The uncompressed header contains information about how 283large the data is, and where it should be placed, and what additional memory 284needs to be cleared. 285 286Stages are assigned a component value of 0x10. When coreboot sees this 287component type, it knows that it should pass the data to a sub-function 288that will process the stage. 289 290The following is the format of a stage component: 291 292/--------\ 293| Header | 294|--------| 295| Binary | 296| .. | 297\--------/ 298 299The header is defined as: 300 301struct cbfs_stage { 302 unsigned int compression; 303 unsigned long long entry; 304 unsigned long long load; 305 unsigned int len; 306 unsigned int memlen; 307}; 308 309'compression' is an integer defining how the data is compressed. There 310are three compression types defined by this version of the standard: 311none (0x0), lzma (0x1), and nrv2b (0x02, deprecated), though additional 312types may be added assuming that coreboot understands how to handle the scheme. 313 314'entry' is a 64 bit value indicating the location where the program 315counter should jump following the loading of the stage. This should be 316an absolute physical memory address. 317 318'load' is a 64 bit value indicating where the subsequent data should be 319loaded. This should be an absolute physical memory address. 320 321'len' is the length of the compressed data in the component. 322 323'memlen' is the amount of memory that will be used by the component when 324it is loaded. 325 326The component data will start immediately following the header. 327 328When coreboot loads a stage, it will first zero the memory from 'load' to 329'memlen'. It will then decompress the component data according to the 330specified scheme and place it in memory starting at 'load'. Following that, 331it will jump execution to the address specified by 'entry'. 332Some components are designed to execute directly from the ROM - coreboot 333knows which components must do that and will act accordingly. 334 335=== Payloads === 336 337Payloads are loaded by coreboot following the boot process. 338 339Stages are assigned a component value of 0x20. When coreboot sees this 340component type, it knows that it should pass the data to a sub-function 341that will process the payload. Furthermore, other run time 342applications such as 'bayou' may easily index all available payloads 343on the system by searching for the payload type. 344 345 346The following is the format of a stage component: 347 348/-----------\ 349| Header | 350| Segment 1 | 351| Segment 2 | 352| ... | 353|-----------| 354| Binary | 355| .. | 356\-----------/ 357 358The header is as follows: 359 360struct cbfs_payload { 361 struct cbfs_payload_segment segments; 362} 363 364The header contains a number of segments corresponding to the segments 365that need to be loaded for the payload. 366 367The following is the structure of each segment header: 368 369struct cbfs_payload_segment { 370 unsigned int type; 371 unsigned int compression; 372 unsigned int offset; 373 unsigned long long load_addr; 374 unsigned int len; 375 unsigned int mem_len; 376}; 377 378'type' is the type of segment, one of the following: 379 380PAYLOAD_SEGMENT_CODE 0x45444F43 The segment contains executable code 381PAYLOAD_SEGMENT_DATA 0x41544144 The segment contains data 382PAYLOAD_SEGMENT_BSS 0x20535342 The memory specified by the segment 383 should be zeroed 384PAYLOAD_SEGMENT_PARAMS 0x41524150 The segment contains information for 385 the payload 386PAYLOAD_SEGMENT_ENTRY 0x52544E45 The segment contains the entry point 387 for the payload 388 389'compression' is the compression scheme for the segment. Each segment can 390be independently compressed. There are three compression types defined by 391this version of the standard: none (0x0), lzma (0x1), and nrv2b 392(0x02, deprecated), though additional types may be added assuming that 393coreboot understands how to handle the scheme. 394 395'offset' is the address of the data within the component, starting from 396the component header. 397 398'load_addr' is a 64 bit value indicating where the segment should be placed 399in memory. 400 401'len' is a 32 bit value indicating the size of the segment within the 402component. 403 404'mem_len' is the size of the data when it is placed into memory. 405 406The data will located immediately following the last segment. 407 408=== Option ROMS === 409 410The third specified component type will be Option ROMs. Option ROMS will 411have component type '0x30'. They will have no additional header, the 412uncompressed binary data will be located in the data portion of the 413component. 414 415=== NULL === 416 417There is a 4th component type ,defined as NULL (0xFFFFFFFF). This is 418the "don't care" component type. This can be used when the component 419type is not necessary (such as when the name of the component is unique. 420i.e. option_table). It is recommended that all components be assigned a 421unique type, but NULL can be used when the type does not matter. 422