Software that lives in the hardware
Every processor needs code to run the moment power arrives. That code has to be stored somewhere that survives power-off, so it sits in non-volatile memory such as flash or ROM on the chip or right beside it. That stored code is firmware.
NIST SP 800-193, the US guidance on platform firmware resiliency, defines firmware as a generic term for any code stored in a chip that either resides at the reset vector (or equivalent) of the processor or is provided as an extension to other firmware. The reset vector is where the processor starts executing after it is switched on or reset, so firmware is, by definition, what runs first.
Firmware is everywhere in a computer, not only in small gadgets. NIST lists boot firmware on the main processor (BIOS and UEFI are examples), and firmware in storage and network controllers, graphics processors and service processors. Some power supplies and batteries have their own microcontroller and firmware governing how they charge and discharge.
Firmware on a microcontroller
On a microcontroller, the line between firmware and the application tends to disappear. There is no separate operating system on a disk and no apps to install. The firmware is the program: it sets up the clocks and peripherals, then runs the device’s job until the power goes.
The Embedonomicon, the Rust project’s guide to bare-metal programming, puts it this way: a program built without the standard library can be the first and the only code that runs on a system, and it lists firmware, bootloaders and operating system kernels as examples. That is why bare-metal Rust firmware is written in no_std mode.
Inside, microcontroller firmware can have some or all of these layers:
- A bootloader that runs first, checks what is in flash, and starts the main image. It can also install updates.
- Drivers for the peripherals: pins, timers, serial buses, radios.
- Optionally, a real-time operating system (RTOS) kernel for scheduling several tasks. Zephyr, for example, describes itself as a small-footprint kernel for resource-constrained and embedded systems.
- The application, the code that reads the sensor, drives the motor or talks to the phone.
Simple firmware can do without an RTOS and run a single loop with interrupt handlers.
How firmware is updated
Firmware is not fixed for the life of a device. NIST notes that updates can remove vulnerabilities and correct operational problems, and its core baseline for IoT devices, NISTIR 8259A, includes software update as one of its device capabilities. Its common elements include the ability to update through remote or local means, to verify and authenticate any update before installing it, to roll back to a previous version, and to restrict updates to authorised entities.
An update delivered by radio or network is called over-the-air (OTA). The risk is a power cut halfway through. Espressif’s ESP-IDF handles this with at least two app slots in flash: the new image is written to the slot that is not currently booting, and only once it is verified does the device switch to it on the next boot. If power fails during the write, the chip still boots the current application. MCUboot, an open bootloader project for 32-bit microcontrollers, likewise defines a common flash layout and a secure bootloader for software upgrades, and works with Zephyr, Apache Mynewt, Apache NuttX and other systems.
Keeping firmware trustworthy
Because firmware runs first and is highly privileged, an attacker who changes it can undermine everything that runs above it. NIST SP 800-193 warns that a successful attack on platform firmware could render a system inoperable, or install persistent malware that survives in low-level code. Its guidance rests on three principles:
- Protection: keep firmware and its critical data intact, including by checking the authenticity and integrity of updates.
- Detection: notice when firmware or critical data has been corrupted or changed from an authorised state.
- Recovery: restore firmware and critical data to a state of integrity when corruption is found.
Authenticity comes from digital signatures. In NIST’s model, an authenticated update relies on a root of trust for update that holds a signature verification algorithm and a key store with the public key needed to check each new image. NIST also notes that the matching private key could be stolen, so a design needs a way to recover from key compromise.
Secure boot applies the same idea every time the device starts. In ESP-IDF’s Secure Boot v2, the first-stage bootloader in ROM, which cannot be changed, verifies the signature of the second-stage bootloader, and that bootloader verifies the application before running it. Only the public key is stored on the device; the private key that signs releases is kept elsewhere.
Signatures prove where an image came from, not what it does once running. Firmware that handles keys still needs a good entropy source and careful storage, which running encrypted messaging on a microcontroller covers.