15 / 15
Internals / 15

Power-on, firmware, boot

Pressing the power button doesn't start the CPU running your code. It starts a multi-second cascade of microcontrollers, firmware blobs, security checks, and DRAM training before the main CPU ever fetches its first instruction. Modern computers have at least three independent processors that run before the OS does — the main CPU, a Management Engine, and various peripheral controllers. Understanding this layer is the difference between debugging a flaky machine and watching it boot into a black screen for the third time.


Nine phases, end to end

From the moment the power button closes the circuit to the moment the login prompt appears, a modern PC traverses roughly nine distinct phases, and it skips none of them. The phases form a relay. Each stage does just enough to find, verify, and start the next, then steps out of the way. No single piece of code runs the whole boot; control is handed from silicon mask ROM to firmware to a bootloader to the kernel to the first user-space process, and each handoff is a point where things can go right or fail in a way that looks, from the screen, like "nothing happened."

The mental model that helps most is this: boot is not one program starting. It is a chain of small programs, each loading the next from a slower, larger store into a faster one, until finally a real operating system is resident in RAM and running. The firmware lives in a tiny flash chip soldered to the board. The bootloader lives on disk. The kernel lives on disk. Each step copies the next stage into memory, checks it is what it claims to be, and jumps to it. Hold that picture and the rest of this page is just detail.

power-onreset heldfirmwareUEFI · POSTbootloaderGRUBkernel initmount rootPID 1systemdlogin~ ms~1–60 s~ ms–s~1–3 s~1–10 scold-boot wall clock, dominated by firmware not storage →each box loads, verifies, and jumps to the next
The boot relay. Most of a cold boot is spent in firmware (POST, DRAM training), not in reading the kernel off disk.
#PhaseDurationWhat happens
1Power-on reset~msPower supply stabilises voltage rails. CPU pins held in reset until clocks lock. PCH releases the reset signal once everything is ready.
2Microcode load~msCPU loads its built-in microcode ROM. Modern Intel/AMD chips support runtime microcode patches; if a signed update is in firmware, it loads here.
3Pre-firmware (ME / PSP)~100s msOn Intel: the Management Engine boots a separate ARC/x86 core running its own OS. On AMD: the Platform Security Processor. These run before the main CPU does.
4BIOS/UEFI early init~1 sMain CPU starts in 16-bit real mode (legacy) or directly in long mode (UEFI). Initializes DRAM controller, sets up memory training, runs SMBus probes for hardware identification.
5POST~1–10 sPower-On Self-Test. Probes CPUs, memory, PCIe devices. Builds the ACPI tables that describe the hardware to the OS.
6Boot device selection~msReads the boot order from NVRAM. UEFI looks for an EFI System Partition; legacy BIOS reads the MBR.
7Bootloader~msGRUB / systemd-boot / Windows Boot Manager / Apple iBoot. Reads the kernel image and initrd from disk into memory. Hands off control.
8Kernel init~1–3 sKernel runs its early init: enables paging, brings up additional CPU cores, mounts the root filesystem, runs init/systemd.
9User-space init~1–10 ssystemd / launchd / SMSS starts services in parallel. Login prompt appears.

The reset vector

On x86, the CPU starts executing from a hardcoded address: 0xFFFFFFF0 — sixteen bytes from the top of 4 GB. The motherboard chipset arranges for the BIOS/UEFI ROM to be mapped there at boot, so the first instruction the CPU fetches is the firmware's entry point. On ARM the equivalent is the reset vector at the start of the SoC's boot ROM, which is small mask-programmed silicon (4–64 KB) that lives forever and contains just enough code to load the next stage from external flash.

There is nothing special about that first instruction from the CPU's point of view. It runs the same fetch-decode-execute loop it will run for the rest of its life (the instruction cycle does not change because the machine just powered on). The only thing the reset vector does is guarantee a known starting program counter so that the chip, which has no idea what is on its disks, always begins at code the board vendor put in a place it can reach. Everything after that first instruction is software deciding what to run next.

On Apple silicon Macs, the boot ROM is signed and immutable. It loads iBoot from a secure storage area, which loads the kernel. The Secure Enclave bootstraps in parallel and verifies every step. There's no "BIOS shell" to drop into and no equivalent of UEFI variables — the entire chain is locked down end to end.

DRAM training

Bringing up DDR memory is one of the slowest parts of boot. The memory controller doesn't know the timing characteristics of the installed DIMMs in advance — it has to train them by sweeping a range of voltages, frequencies, and delay-line settings, looking for the values where signals are stable. This can take 1–10 seconds per channel on server hardware with 12-channel DDR5.

The trained values are cached in NVRAM so the next boot is faster ("warm boot"), but a cold boot or BIOS update reruns the full training. Datacenter operators notice this when rebooting a 2 TB-of-RAM server takes longer than they expect — most of the wall-clock time is DRAM training, not OS init.

Firmware lineage

FirmwareSizeEraNotes
Legacy BIOS~1–4 MB1980s–2010s16-bit real mode at boot. MBR-only. Limited to ~2 TB disks. Mostly retired.
UEFI~16 MB2010s–todayStandard on every modern x86 PC and server. Supports GPT, Secure Boot, network boot.
Coreboot~256 KB2000s–todayOpen-source BIOS replacement. Used on Chromebooks, some servers, Framework laptops.
Open Firmware~512 KB1990s–2000sIEEE 1275, Forth-based. Used on PowerPC Macs and Sun servers.
iBoot (Apple)~4 MBiPhone/MacApple's custom bootloader for iOS, iPadOS, and Apple silicon Macs. Tightly integrated with Secure Enclave.
OpenSBI~256 KB2020s–todayRISC-V Supervisor Binary Interface. Equivalent of UEFI for RISC-V boards.

UEFI is what almost every modern PC and server runs. Inside, it's a roughly POSIX- like environment with a shell, file system access (FAT32 typically), a network stack, and pre-OS drivers. UEFI is itself an OS, small and real-mode-free, and it is intended to hand off to a "real" OS, but it can run before any kernel boots.

Finding the boot device

Once POST is done and the hardware is described, the firmware has to decide what to boot. This is the moment the two worlds diverge sharply, and it is worth seeing both side by side because most engineers learned one and then quietly assumed the other worked the same way.

On legacy BIOS, the firmware reads the very first 512-byte sector of the boot disk: the Master Boot Record (MBR). The first 446 bytes of that sector are executable code; the next 64 bytes are the partition table; the last two bytes are a magic signature (0x55AA) that tells the BIOS "yes, this is bootable." The BIOS copies those 446 bytes to a fixed address (0x7C00) and jumps to them. That is all the room there is. 446 bytes cannot load a kernel, so MBR code is just a stub whose only job is to find and load a bigger bootloader from elsewhere on the disk. This is why old-school booting has "stages": there is no space to do it in one shot.

On UEFI, there is no magic 512-byte sector. The firmware understands the GUID Partition Table and the FAT32 filesystem directly. It looks for an EFI System Partition, opens it like a normal disk, and runs a regular file: a .efi executable, usually at a well-known path such as \EFI\BOOT\BOOTX64.EFI. There is no tiny assembly stub, no chain of cramped stages. The bootloader is just a program the firmware knows how to run, which is why UEFI bootloaders can be large, written in C, and even ship their own drivers.

LEGACY BIOSread sector 0 (512 B)446 B MBR stub → 0x7C00stage-2 bootloaderkernelUEFIread GPT, find EFI partitionrun BOOTX64.EFI (a file)bootloader / boot managerkernel
Old vs new. BIOS squeezes through a 512-byte sector and chains stages; UEFI runs a normal file off a filesystem it understands.

The bootloader, in stages

The bootloader's one job is to find a kernel, load it into memory along with an initial ramdisk, set up the handoff data the kernel expects, and jump to it. The best-known example on Linux is GRUB (the GRand Unified Bootloader), and its internal structure is a clean illustration of why this is harder than it sounds.

On a legacy install, GRUB is split into pieces that match the space available at each point. stage 1 is the 446-byte MBR stub. It is too small to understand a filesystem, so all it knows is a hardcoded disk sector to load next. That sector holds stage 1.5, which lives in the gap between the MBR and the first partition and contains just enough filesystem code to read files by name. stage 1.5 then loads stage 2, the full GRUB: the menu you see, the config parsing, the ability to read /boot/grub/grub.cfg, edit kernel command lines, and load the kernel and initrd. On a UEFI install the dance collapses: GRUB is a single grubx64.efi file the firmware runs directly, with no stages, because the firmware already handed it a working filesystem.

Whatever the path, the bootloader ends the same way. It loads the kernel image, loads the initramfs (a compressed cpio archive containing a minimal root filesystem with just enough tools and drivers to find and mount the real root), fills in a structure describing memory, the command line, and the firmware tables, and transfers control to the kernel's entry point. From that instruction on, the firmware and bootloader are done. They will not run again until the next boot.

Why the initramfs exists: the real root filesystem might live on an encrypted LVM volume, on a software RAID array, or on an NVMe drive needing a driver that is not built into the kernel. The kernel cannot mount what it cannot reach. The initramfs is a tiny throwaway root that contains exactly the drivers and tools needed to unlock, assemble, or probe the real root, mount it, and then pivot to it. This is why "regenerate your initramfs" is the fix for so many boots that hang right after the bootloader.

Kernel init and the handoff to PID 1

When the bootloader jumps to the kernel, the machine is still half-built. Early kernel init is the kernel finishing the job: it sets up its own page tables and turns on paging so the rest of the kernel can run in the virtual address space it expects (the same virtual memory machinery every later process relies on), parses the firmware-provided memory map, sets up interrupt handling, initialises the scheduler, and brings the other CPU cores online (see "Bringing up additional cores" below). It decompresses and unpacks the initramfs into a RAM filesystem and mounts it as the temporary root.

Then comes the most important handoff of the whole sequence. The kernel runs the init program out of the initramfs, which loads the drivers needed for the real root device, unlocks and mounts the real root filesystem, and then performs a pivot_root to switch the root from the throwaway ramdisk to the real disk. Finally the kernel executes the real init binary, conventionally at /sbin/init, as process number 1. From here the kernel never starts another top-level process directly. Everything else, every daemon, every login shell, every browser, descends from PID 1 by being forked (how processes are created and managed is its own topic). If PID 1 ever dies, the kernel panics, because there is nothing left to parent the system.

On most Linux systems PID 1 is systemd, which reads unit files describing services and their dependencies and starts as many as it can in parallel, which is a large part of why modern Linux boots faster than the old sequential SysV init scripts that ran one shell script after another. On macOS the equivalent is launchd; on older Unix it was the SysV init with its numbered runlevels; on Windows the chain runs through the Session Manager (smss.exe) into wininit.exe and the service control manager. Different names, same shape: one privileged ancestor process that brings up everything else and then stays resident as the root of the process tree for the life of the machine.

Microcode — the silicon's patch layer

Modern x86 chips internally translate complex instructions into RISC-shaped µops. The translation is implemented in microcode — firmware that lives in the CPU's microcode ROM. Most µops come from a fast hardwired path, but rarely- used or particularly complex instructions (CPUID, RDTSC, REP MOVSB strings) come from microcode.

Critically: the microcode is patchable at runtime. The CPU vendor publishes signed updates that the BIOS/UEFI loads at boot, and the OS reloads at every boot afterward. This is how Spectre, Meltdown, Zenbleed, Downfall, Reptar, and dozens of other CPU bugs have been mitigated without swapping silicon. Microcode updates are the security industry's most underrated patch path — they're what keeps ten-year-old chips secure against new vulnerabilities.

Why this matters: when Intel SA-00086 (a Management Engine vulnerability) was disclosed in 2017, the patch shipped via microcode + ME firmware update. Some chips were never patched because their motherboard vendors didn't push updates. The boundary between "your CPU" and "your CPU as currently configured" matters more than most users realise.

The hidden coprocessors

Modern computers run multiple processors before, alongside, and after the main CPU. Most users never see them. Most are unkillable. Some have been the source of significant security disclosures.

CoprocessorRole
Intel Management Engine (ME)ARC core (older), x86 mini-core (recent). Runs Minix-based firmware. Implements AMT (remote management), Boot Guard, anti-theft. Cannot be disabled completely on most chips. Critical CVEs in 2017 (SA-00086) prompted disclosure debates.
AMD Platform Security Processor (PSP)ARM Cortex-A5 inside every Zen and post-Zen chip. Runs trustlets for cryptographic operations. Equivalent role to Intel ME.
Apple Secure EnclaveSeparate ARM core on the Apple SoC. Manages TouchID/FaceID, Apple Pay keys, FileVault. Communicates with main CPU via mailbox protocol; runs sepOS.
Baseboard Management Controller (BMC)On servers: a separate ARM SoC (e.g., AST2600) running OpenBMC or vendor firmware. Provides IPMI / Redfish / KVM-over-LAN. Fully independent of the main CPU.
Embedded Controller (EC)On laptops: a separate microcontroller managing keyboard, fans, battery charging, lid switch, power button. Runs its own firmware, often customizable on Chromebooks via System76 EC or Framework EC.

On a typical Lenovo or Dell business laptop in 2026, there are at minimum: the main CPU + integrated GPU, the Management Engine (Intel) or PSP (AMD), the Embedded Controller, the WiFi card's microcontroller, the SSD's controller, the Thunderbolt controller, the trackpad's microcontroller, and possibly a TPM. Eight to twelve programmable processors per machine, only one of which the OS controls.

Secure Boot and the chain of trust

Secure Boot is UEFI's mechanism for verifying that every stage of boot is signed by a trusted authority. The UEFI firmware contains a list of trusted public keys (Microsoft's, the OEM's, optionally the user's). When loading the bootloader, UEFI verifies its signature against those keys; the bootloader verifies the kernel; the kernel verifies its modules. Each stage extends the chain of trust to the next.

The reason this works is that trust has to start somewhere it cannot be rewritten. That somewhere is the root of trust: on x86 it is keys fused into the silicon and the immutable early firmware (Intel Boot Guard, AMD Platform Secure Boot); on Apple silicon it is the mask-ROM Boot ROM. That root is the only link in the chain nobody can replace without replacing the chip. Everything after it is verified before it runs, so a single unmodifiable anchor at the bottom guarantees the integrity of a long mutable chain on top. Break any link and verification fails at that point; the machine refuses to advance.

root of trustfused keys /mask ROMfirmwareUEFIbootloadershim / GRUBkernelmodulesverifiesverifiesverifiesverifiesa broken signature anywhere stops the boot at that linkcannot be rewritten
The chain of trust. Trust flows left to right; the only link nobody can replace is the silicon anchor on the far left.

Practical limitations: most distros need to ship a "shim" bootloader signed by Microsoft (the only authority that's universally trusted), which then loads the distro's actual bootloader. Self-signed firmware on consumer hardware works but requires manual key enrollment. Apple silicon takes the chain further: every byte of firmware on the SoC is signed by Apple, with no user override.

TPM and measured boot

A Trusted Platform Module is a small dedicated security chip (sometimes integrated into the CPU as fTPM on AMD, or PTT on Intel). It stores cryptographic keys in tamper-resistant hardware and provides services like random number generation, key sealing, and remote attestation.

During boot, each firmware stage measures (hashes) the next stage and extends the hash into the TPM's PCR registers. The final PCR values uniquely identify the entire boot chain. If any stage is modified — a malicious bootloader, a tampered kernel — the PCRs differ. BitLocker / FileVault / LUKS bind disk encryption keys to specific PCR values; if the boot chain is tampered with, the keys can't be unsealed and the disk stays encrypted.

This is what "your laptop refuses to boot after a BIOS update because BitLocker is asking for a recovery key" actually is: the BIOS update changed PCR 7 (the BIOS hash), so the TPM won't release the BitLocker key. Recovery keys exist as the explicit out-of-band escape hatch.

x86's mode tour

x86's history is visible at boot. The CPU starts in real mode — 16-bit registers, segmented memory, no protection. The BIOS sets up the GDT (Global Descriptor Table), enables the A20 line, and switches to protected mode. UEFI skips the real-mode dance and starts directly in long mode (64-bit). Either way, the kernel runs entirely in long mode with paging on.

x86 modes traversed at boot:

Legacy BIOS:  Real mode  (16-bit, 1 MB)
              → Protected mode (32-bit, 4 GB)
              → Long mode (64-bit, 256 TB / 128 PB)

UEFI:          Long mode  (64-bit) from the start
              → Kernel takes over in long mode

Secure boot + Apple silicon:  No mode transitions visible to user code.
              The SoC bootstraps directly into the OS.

Bringing up additional cores

A multi-core CPU starts with only the BSP (Bootstrap Processor) running. The other cores — APs (Application Processors) — are held in reset until the kernel explicitly wakes them. The kernel sends a sequence of inter-processor interrupts (INIT, then SIPI — Startup Inter-Processor Interrupt), each AP starts at a kernel-provided trampoline, sets up its own stack and page tables, and joins the scheduler.

This sequence is why dmesg on Linux shows "smpboot: Booting Node 0 Processor 1 APIC 0x2" messages during boot. Each core takes ~10–50 µs to come online; bringing up 256 cores on a big EPYC is itself a measurable fraction of the boot time.

Phones and embedded boards

The PC story is the most baroque version. Phones and embedded systems run the same relay with fewer, more locked-down links. The shape is identical: an immutable boot ROM in silicon loads a first-stage loader, which loads a second-stage loader, which loads the kernel, each step verified against keys fused into the chip.

On an Android phone the chain runs through the SoC's boot ROM into a primary bootloader, then into U-Boot or a vendor loader, then into the Android boot image (kernel plus ramdisk). The "unlock the bootloader" toggle that voids your warranty is literally a fuse-backed flag that tells the verified-boot stage whether to enforce signature checks on the next link. On iPhones the chain is Boot ROM into iBoot into the kernel, every byte signed by Apple, with the Secure Enclave verifying in parallel and no override at all. On a small Linux board or a microcontroller the chain can be as short as a ROM that copies one image from flash to RAM and jumps to it, with no filesystem, no menu, and no kernel in the operating-system sense at all, just your firmware running on bare metal.

The pattern to take away is that "boot" is not an x86 thing. It is the universal problem of a chip that wakes up knowing nothing having to find, verify, and start trustworthy software, and every computing device from a thermostat to a datacenter server solves it with some version of the same staged, verified relay.

Common misconceptions

  • "The BIOS / UEFI is just a few kilobytes of code." Modern UEFI is ~16 MB compressed and runs on top of millions of lines of code. EFI System Partitions can be several GB. UEFI is more "small OS" than "boot ROM".
  • "You can disable Intel ME." You can disable some user-facing parts (AMT, vPro) but the ME core itself runs whether you want it to or not, on every Intel chip since 2008. The "HAP bit" disables most ME functionality but isn't supported on consumer chips. On AMD, the PSP is similarly unkillable.
  • "Secure Boot is unbreakable." Several Secure Boot bypasses have been found (BootHole in 2020, others since). It's a defence-in-depth layer, not a guarantee. Combine with verified boot, measured boot, and disk encryption.
  • "Faster SSDs make boot faster." Past a point, no. UEFI POST and DRAM training dominate cold boot. From SSD-read perspective, the bootloader is <100 KB and the kernel + initrd is <200 MB; modern NVMe loads them in milliseconds. The slow parts are firmware, not storage.

Numbers worth remembering

QuantityValue
x86 reset vector address0xFFFFFFF0
UEFI image size, typical~16 MB
BIOS image size, legacy~1–4 MB
Coreboot image size~256 KB
DRAM training time, cold boot, 12-channel server1–10 s
Secure Boot trust anchor count, typical3–10 keys
TPM 2.0 PCR count24 registers
AP startup IPI sequenceINIT + SIPI + SIPI
Intel ME firmware version, recent~16.x (2024-25)
Apple Boot ROM size~4 KB (immutable mask ROM)
Typical cold boot time, modern laptop~10–20 s
Typical cold boot time, big server~1–3 min

Further reading

Found this useful?