In short: A bootloader is the small program that runs first when an embedded device powers on, preparing the hardware and then loading and transferring control to the main application firmware. It also provides the mechanism for safely updating that firmware in the field through OTA or DFU.
A bootloader is a dedicated piece of code that executes immediately after reset, before the main application ever runs. Its job is to bring the processor from a raw, just-powered-on state to a point where real firmware can take over. On a microcontroller this means setting up the clock tree, configuring memory, optionally initialising a communication peripheral, and then jumping to the application's entry point.
The bootloader lives in a reserved, protected region of non-volatile memory, usually at the start of flash where the reset vector points. Because it is the very first instruction stream the CPU fetches, it must be self-sufficient: it cannot rely on the application, an operating system, or any driver that has not yet been initialised. This independence is what makes it both powerful and easy to get wrong.
When power is applied, the processor reads a fixed reset vector and begins executing. On an Arm Cortex-M part, for example, the hardware loads the initial stack pointer and the reset handler address from the first two words of memory. Control then flows through a predictable chain:
Without this ordered sequence, higher-level firmware would face an unconfigured chip. The bootloader matters because it is the only guaranteed-present code that can recover a device: if an application update is corrupted or a field unit crashes on boot, a well-designed bootloader can fall back and re-flash rather than bricking the product.
Simple microcontrollers often use a single-stage bootloader: one small program does everything and then launches the application. Larger systems-on-chip that run Linux use a multi-stage chain because the hardware is too complex to initialise in one tiny program stored in on-chip ROM.
A mask-ROM routine burned into the silicon runs first. It is immutable and only knows enough to load the next stage from a configured source such as eMMC, SD, QSPI flash, or a serial download.
This small loader initialises DRAM — the critical step the ROM cannot do — and then loads the full bootloader into that freshly available RAM.
The full-featured stage brings up more peripherals, offers a command environment, loads the kernel and device tree, and passes boot arguments. On application-class devices this is also where secure boot verifies signatures before handing control to the OS.
A major reason bootloaders exist is in-field firmware update. Two mechanisms dominate embedded practice:
Robust OTA almost always uses an A/B (dual-bank) layout: two application slots plus the bootloader. The new image is written to the inactive slot, so the running system is never at risk mid-download. After reboot the bootloader checks the new image's integrity (CRC or hash) and authenticity (digital signature), marks it as the boot target, and launches it. If the new firmware fails to confirm itself as healthy within a watchdog window, the bootloader rolls back to the last known-good slot. This confirm-or-rollback pattern is what makes unattended updates safe at scale.
A bootloader only works if the flash map is deliberate. A typical microcontroller partition includes a protected bootloader region at the reset address, one or two application slots, and a small non-volatile area for metadata such as the active-slot pointer, image version, and a boot-success flag. Key engineering rules:
Real projects and industry tool flows, with certification.
Explore CourseTron Courses →Engineers rarely write every line from scratch. Widely used frameworks include MCUboot, a secure, open-source bootloader with built-in image signing, A/B swap, and rollback that is integrated into Zephyr RTOS and many vendor SDKs. For application-class SoCs, U-Boot is the de-facto multi-stage loader, while Das U-Boot SPL handles the DRAM-init first stage. Vendor stacks such as STMicroelectronics' X-CUBE / STM32CubeProgrammer, Nordic's nRF Secure Immutable Bootloader, and Espressif's ESP-IDF OTA framework all package the flash layout, signing keys, and update agent together. These tools matter because getting secure boot, key management, and rollback logic right is subtle, and a proven implementation removes an entire class of field-failure risk.
It relocates the vector table to the application's base (on Cortex-M, by setting SCB->VTOR), loads the application's initial stack pointer from the first flash word of its slot, and branches to the reset handler at the second word. It typically also de-initialises any peripherals it enabled so the application starts from a clean state.
Because the running image is never overwritten during download. The new firmware goes into the inactive bank, and only after a successful integrity and signature check does the bootloader switch the active pointer. If the update is corrupt or the new firmware fails to confirm health, the device rolls back to the known-good bank instead of bricking.
The boot ROM is immutable code in silicon that runs first and loads the next stage; the bootloader is updatable flash-resident code that performs richer initialisation, image validation, and field updates. On small MCUs the ROM may be minimal and the bootloader does most of the work; on large SoCs a multi-stage chain splits the job.
Secure boot is the bootloader verifying a cryptographic signature on the application image against a trusted public key (often rooted in fuses or OTP) before executing it. This establishes a chain of trust so only authentic, unmodified firmware ever runs on the device.
Related: FreeRTOS tasks and scheduling · the VLSI Glossary · all courses.