01

The Boot Chain Overview

Your MacBook boots through a chain of trust: each stage is cryptographically signed, and each stage verifies the next before handing over control. Compromise any link and the chain breaks — the Mac refuses to boot.

SecureROM
0–5ms
Immutable mask ROM on silicon. Cannot be patched, updated, or replaced. Apple's root of trust. Verifies iBoot signature using Apple Root CA. If verification fails: DFU mode only.
iBoot
5–800ms
Apple's bootloader in NAND flash (updatable via firmware). Initializes DRAM, sets up MMU, loads and verifies the XNU kernel from the APFS Sealed System Volume.
XNU Kernel
800ms–2.5s
Hybrid kernel: Mach microkernel + BSD + I/O Kit. Initializes virtual memory, scheduler, IPC, mounts filesystems, starts the BSD subsystem, then executes PID 1.
launchd
2.5s–8s
PID 1. Replaces init, inetd, cron, and rc scripts. Starts all system services from plist files. On-demand launching: services start when first needed. Manages the entire service graph.
Login
8s–15s
WindowServer already running. loginwindow shows UI. Authentication via opendirectoryd. User session spawns Dock, Finder, SystemUIServer. Previous windows restored (Resume).
02

SecureROM — The Immutable Root (0ms–5ms)

When you press the power button, the Power Management IC (PMU) sequences the power rails in a specific order — VCORE, VDDR, IO — to prevent damage from voltage spikes. Once stable, the Apple Silicon SoC's CPU cores come out of reset at a hardcoded address in the SecureROM.

WHAT MAKES IT "SECURE"

SecureROM is mask-programmed ROM — written once during chip fabrication. It is physically impossible to modify without destroying the chip. Apple bakes roughly 32KB of code into the silicon at the factory. No firmware update, no exploit, no DFU mode can change it. This is the unconditional trust anchor.

What SecureROM Does

VFY

Verifies iBoot signature

SecureROM reads iBoot from NAND flash and verifies its ECDSA/RSA signature against Apple's Root CA certificate. The certificate is also stored in ROM. Any bit flip in iBoot's code changes the signature hash — verification fails.

DFU

Falls back to DFU mode if verification fails

If iBoot is corrupted or modified, SecureROM enters Device Firmware Update (DFU) mode. The Mac appears dead but is actually waiting for a USB-C connection to a Mac running Apple Configurator or Finder's Recovery mode. This is how you restore a brick.

Hands control to iBoot

If all checks pass, SecureROM jumps to iBoot's entry point. From this moment, SecureROM's job is done — it doesn't run again until the next power cycle.

SECURE ENCLAVE

The Secure Enclave (SEP) is a separate processor on the Apple Silicon die. It has its own ROM, RAM, and runs its own OS (sepOS). It boots independently and holds long-term cryptographic keys — Touch ID templates, Face ID models, your disk encryption key. The main CPU never has direct access to these keys. Even if an attacker fully compromises macOS, Secure Enclave secrets remain protected.

03

iBoot — The Bootloader (5ms–800ms)

iBoot is Apple's bootloader — software stored in NAND flash that can be updated via firmware updates (but always signed and verified). It bridges the hardware initialization phase and the OS loading phase.

What iBoot Does

DRAM

DRAM Initialization (Memory Training)

Before any data can be stored in RAM, the memory controller must calibrate timing parameters — signal delays, voltage levels, timing margins — for the specific DRAM modules on this exact logic board. This "memory training" takes ~200–400ms and is the single slowest hardware initialization step.

MMU

Sets Up the Memory Management Unit

iBoot configures initial page tables so the CPU can use virtual addresses. This allows later code to run at fixed addresses regardless of physical memory layout. The real page tables will be rebuilt by the XNU kernel.

SSV

Verifies the Sealed System Volume

macOS lives on an APFS Sealed System Volume (SSV). The entire contents are hashed into a Merkle tree. iBoot computes the root hash and compares it against the expected value. Any modification to any system file — a single byte in any dylib — changes the root hash, and the Mac refuses to boot.

WHY /SYSTEM IS READ-ONLY

The SSV seal is why /System/Library and /usr/bin are mounted read-only. Even root can't write to them without disabling SIP and breaking the seal. On production Macs, this means the entire OS is tamper-evident.

KRNL

Loads and Launches XNU

iBoot reads the XNU kernel from the APFS volume into RAM, verifies its signature, builds a device tree (a data structure describing all hardware: CPU cores, memory map, I/O controllers, peripherals), and jumps to the kernel's entry point with the device tree pointer in a register.

Secure Boot Policies

PolicyWhat's AllowedUse Case
Full Security (default)Only Apple-signed OS matching current macOSAll normal Macs
Reduced SecurityOlder macOS, developer kexts with notarizationDevelopment, older software
Permissive SecurityAny OS, unsigned code, custom kernelsSecurity research, Linux on Mac
04

XNU Kernel — X is Not Unix (800ms–2.5s)

XNU is a hybrid kernel: it combines the Mach microkernel, the BSD UNIX subsystem, and the I/O Kit driver framework into a single kernel image. This architecture gives Apple performance (monolithic kernel — everything runs in kernel space) and flexibility (Mach IPC allows modular-like communication).

Mach Layer
  • Mach ports (IPC)
  • Virtual memory (VM maps)
  • Threads & scheduling
  • Real-time scheduling
  • Exception handling
BSD Layer
  • POSIX syscall API
  • VFS (filesystem)
  • Networking stack
  • Process model (fork/exec)
  • Signals
I/O Kit
  • C++ driver framework
  • Device tree parsing
  • USB, Thunderbolt, PCIe
  • DriverKit (user-space)
  • Power management

Kernel Boot Sequence (Simplified)

XNU Kernel Initialization Order
1. start_common() ← per-CPU setup: TLS, exception vectors, VBAR 2. machine_startup() ← ARM64 MMU, CPACR, debug registers 3. vm_mem_bootstrap() ← virtual memory subsystem, page tables 4. zone_init() ← slab allocator (zalloc) init 5. ipc_init() ← Mach IPC ports, messaging queues 6. sched_init() ← scheduler, run queues, P/E cores 7. bsd_init() ← BSD subsystem: VFS, socket layer, proc table 8. IOKitBSDInit() ← I/O Kit registry, device tree parse, driver probe 9. vfs_mountroot() ← mount root APFS volume read-only 10. load_init_program() ← exec /sbin/launchd as PID 1

Apple Silicon Architecture

CPU Topology
  • P-cores (Avalanche): high performance, large caches, out-of-order
  • E-cores (Blizzard): energy efficient, smaller, simpler pipeline
  • Scheduler automatically migrates threads between P/E cores based on QoS
  • M3 Pro: 6P + 6E cores = 12 total
Unified Memory
  • CPU, GPU, Neural Engine share the same physical RAM
  • No discrete VRAM — GPU can use all system memory
  • Metal uses zero-copy: CPU writes, GPU reads, no DMA transfer
  • Memory bandwidth: ~200 GB/s on M3 Pro
05

launchd — PID 1 (2.5s–8s)

After the kernel finishes bootstrapping, it executes /sbin/launchd as PID 1. launchd is Apple's universal service manager — it replaced BSD init, inetd (network services), cron, and rc scripts all in one process.

ON-DEMAND LAUNCHING

launchd's key innovation: services don't start at boot — they start when first needed. com.apple.mDNSResponder starts when your first DNS-SD query arrives. com.apple.bluetoothd starts when Bluetooth is enabled. This is why macOS boots faster than it appears: fewer services actually run at startup than you think.

Plist File Locations

LocationTypeRuns AsPurpose
/System/Library/LaunchDaemons/DaemonrootApple system services
/Library/LaunchDaemons/DaemonrootThird-party system services
/System/Library/LaunchAgents/AgentuserApple per-user agents
/Library/LaunchAgents/AgentuserThird-party per-user agents
~/Library/LaunchAgents/AgentuserYour personal agents

A Real Plist Explained

com.apple.mDNSResponder.plist (simplified)
<?xml version="1.0" encoding="UTF-8"?> <!DOCTYPE plist ...> <plist version="1.0"> <dict> <key>Label</key> <string>com.apple.mDNSResponder</string> ← unique service ID <key>ProgramArguments</key> <array><string>/usr/sbin/mDNSResponder</string></array> <key>MachServices</key> ← on-demand: start when port is looked up <dict><key>com.apple.mDNSResponder</key><true/></dict> <key>KeepAlive</key> <true/> ← restart automatically if it crashes <key>POSIXSpawnType</key> <string>Interactive</string> ← P-core, not E-core </dict></plist>
06

Animated Boot Timeline

Step through each boot stage, or play the full boot sequence. Watch how early WindowServer starts — the Apple logo appears way before the kernel is done initializing everything!

BOOT SEQUENCE VISUALIZER
Press play or step to boot your virtual Mac.
07

Interactive Process Tree

After login, launchd (PID 1) has spawned hundreds of processes. Click any node to expand its children and see what each process does.

PROCESS TREE — click to expand
Click any process to see what it does.
08

Apple Silicon vs Intel Boot

StageIntel Mac (2017–2020)Apple Silicon (M1+)
Root of trustT2 chip (separate from CPU)SecureROM on the SoC itself
Boot ROMEFI firmware (~16MB, updateable)SecureROM (~32KB, immutable)
BootloaderUEFI + macOS BootPickeriBoot (Apple custom)
OS sealSIP + code signingSealed System Volume (SSV)
Boot time20–40s (UEFI POST)8–15s (no BIOS POST)
DRAM trainingSPD-based, fastCustom, longer (200–400ms)
09

What Slows Boot Down

Slow Boot Causes
  • Too many ~/Library/LaunchAgents (Zoom, Dropbox, etc.)
  • Spotlight re-indexing after hard crash
  • FileVault key derivation (+500ms cold boot)
  • Memory pressure → paging during early boot
  • Near-full SSD (fragmentation, less trim)
  • Backup software intercepting file opens
How to Diagnose
  • launchctl list | grep -v apple — third-party services
  • Console.app → filter "bootlog" for verbose boot
  • sudo fs_usage -e -f filesys /sbin/launchd
  • System Settings → Login Items — remove what you don't need
  • log show --last boot | grep error
10

Commands Cheat Sheet

launchd commands
# List all services launchctl list # Start / stop a service launchctl start com.example.service launchctl stop com.example.service # Load/unload a plist launchctl load ~/Library/LaunchAgents/com.foo.plist launchctl unload ~/Library/LaunchAgents/com.foo.plist # Check SIP status csrutil status # Print all NVRAM variables nvram -p
boot diagnostics
# Boot log from last boot log show --last boot \ --predicate 'eventMessage contains "boot"' # List APFS snapshots (SSV seal) diskutil apfs listSnapshots / # Startup items system_profiler SPStartupItemDataType # Processes at login launchctl print-disabled user/$(id -u) # Verbose boot mode nvram boot-args="-v"
END OF HOW-05