You press power. A few seconds later, Linux is at a login prompt. In between, a careful relay race runs: from a single hardwired address, through tiny on-chip code that wakes up DRAM, through bootloaders, to the kernel — each stage building the world the next one needs. This lesson ties the whole course together.
When the core comes out of reset it has almost nothing — caches off, MMU off, no stack, DRAM not even initialised. It does exactly one thing: start fetching from a fixed reset address, the reset vector (the first entry of the vector table, Day 17). That address points into immutable, on-chip boot ROM — the only code guaranteed to be present and trustworthy.
The boot ROM is tiny and runs from small, fast on-chip SRAM because external DRAM isn't working yet — DRAM controllers need configuration before they're usable. So boot is a relay of increasingly capable stages, each loading the next:
Compiled C assumes a working environment — a stack, initialised globals, zeroed variables. Something must build that before main(). That's the startup / C runtime (crt0) code, and it ties together everything from earlier lessons:
.data (initialised globals) from flash to RAM..bss (uninitialised globals) — C guarantees they start at 0.main() — your program finally runs.How do you know none of those stages was swapped for malware? Secure boot. The immutable boot ROM holds (or knows) a root public key. It verifies the cryptographic signature of the next stage before running it; that stage verifies the next; and so on — an unbroken chain of trust rooted in hardware, all the way to the OS. This is the foundation under TrustZone: the Secure world is brought up first, verified.
A microcontroller has no DRAM to train and no Linux to load, so its boot is tiny. At reset the Cortex-M core (Day 18) does two things automatically from the vector table: load slot 0 → the initial stack pointer, and slot 1 → the reset handler. The reset handler runs the C-runtime steps above and calls main(). Power-on to your code in microseconds — no bootloader relay required.
Boot is like powering up a city at dawn. First a single guaranteed generator (boot ROM) starts. It powers the substations (clocks, DRAM). Those light the districts (bootloader, kernel). Finally the shops open for the public (userspace). You can't open shops before the power plant — order is everything.
Boot is a relay from a single hardwired address: the reset vector → immutable boot ROM → bootloader stages that wake up clocks/DRAM and load the OS, with C-runtime startup building the stack/globals/vectors so main() can run. Secure boot verifies each stage in a hardware-rooted chain of trust. Cortex-M does a tiny version: SP + reset handler straight from the vector table.
main().main().The core fetches from the fixed reset vector into immutable on-chip boot ROM — the first trusted code.
Early code is tiny and runs before DRAM works; a small stage inits clocks/DRAM, then loads a bigger loader (U-Boot), then the OS.
Each boot stage cryptographically verifies the next, rooted in immutable hardware, so only authentic software runs.
← Back to the full course roadmap · Deep dive: how a boot ROM works →