coreboot consists of multiple stages that are compiled as separate binaries and are inserted into the CBFS with custom compression. The bootblock usually doesn't have compression while the ramstage and payload are compressed with LZMA.
Each stage loads the next stage a given address (possibly decompressing it).
Some stages are relocatable and can be placed anywhere in DRAM. Those stages are usually cached in CBMEM for faster loading times on ACPI S3 resume.
Supported stage compressions:
The bootblock is the first stage executed after CPU reset. It is written in assembly language and its main task is to set up everything for a C-environment:
On x86 platforms that includes:
The bootblock loads the romstage or the verstage if verified boot is enabled.
The Cache-As-Ram, also called Non-Eviction mode, or CAR allows to use the CPU cache like regular SRAM. This is particullary usefull for high level languages like
C, which need RAM for heap and stack.
The CAR needs to be activated using vendor specific CPU instructions.
The following stages run when Cache-As-Ram is active:
The verstage is where the root-of-trust starts. It's assumed that it cannot be overwritten in-field (together with the public key) and it starts at the very beginning of the boot process. The verstage installs a hook to verify a file before it's loaded from CBFS or a partition before it's accessed.
The verified boot mechanism allows trusted in-field firmware updates combined with a fail-safe recovery mode.
The romstage initializes the DRAM and prepares everything for device init.
To leave the CAR setup and run code from regular DRAM the postcar-stage tears down CAR and loads the ramstage. Compared to other stages it's minimal in size.
The ramstage does the main device init:
After initialization tables are written to inform the payload or operating system about the current hardware existance and state. That includes:
It also does hardware and firmware lockdown:
The payload is the software that is run after coreboot is done. It resides in the CBFS and there's no possibility to choose it at runtime.
For more details have a look at payloads.