MÓDULO 2.8

Bootloaders y DFU

Actualización segura de firmware en dispositivos desplegados

Santi Scagliusi, PhD

Comenzar arrow_downward
deployed_code
Bootloader
Código de arranque
system_update
DFU
Device Firmware Update
wifi
FOTA
Firmware Over The Air
security
Seguridad
Firmas digitales

¿Por qué necesitamos un bootloader?

El bootloader permite actualizar dispositivos en campo sin acceso físico.

warning Sin bootloader...

  • close Debugger obligatorio: Necesitas J-Link o similar para cada actualización
  • close Acceso físico: Debes conectar cables al dispositivo
  • close Sin verificación: No hay forma de validar que el firmware es legítimo
  • close Sin rollback: Si algo falla, el dispositivo queda inoperativo

check_circle Con bootloader...

  • check Actualización remota: DFU por USB, BLE, Wi-Fi o Cellular
  • check Sin hardware especial: No necesitas debugger en producción
  • check Verificación de firma: Solo firmware autorizado puede ejecutarse
  • check Rollback automático: Si la nueva versión falla, vuelve a la anterior
lightbulb
Caso real: Imagina 10.000 sensores IoT desplegados en una fábrica. Sin bootloader, actualizar cada uno requeriría acceso físico. Con FOTA, puedes actualizar todos remotamente en minutos.

Memoria Flash y bootloader

El bootloader reside al inicio de la memoria Flash y carga la aplicación.

Mapa de memoria Flash

0x000F0000 Scratch (temporal)
0x00080000 Slot secundario
Nueva imagen (actualización)
0x00010000 Slot primario
Aplicación activa
0x00000000 MCUboot (Bootloader)
Inmutable - Root of Trust

Flujo de arranque

1
Reset del procesador
CPU comienza en dirección 0x00000000
2
Bootloader se ejecuta
Verifica firma de la imagen en slot primario
3
Verificación de firma
Comprueba autenticidad con clave pública
4
Salto a aplicación
Transfiere ejecución al slot primario
info
Root of Trust: El bootloader es inmutable y contiene la clave pública. Si la firma no es válida, la aplicación no se ejecuta.

Verificación de la aplicación

Firmas digitales garantizan que solo firmware autorizado puede ejecutarse.

edit_document Proceso de firma (desarrollo)

key
Clave privada
Secreta, solo en el servidor de build
arrow_downward
description
Imagen firmada (.bin)
Firmware + firma digital

verified Proceso de verificación (dispositivo)

lock
Clave pública
Embebida en bootloader (inmutable)
arrow_downward
check_circle
Firma válida
La aplicación se ejecuta
shield
Seguridad asimétrica: Aunque alguien obtenga la clave pública del dispositivo, no puede crear firmware válido sin la clave privada.

DFU: Métodos de actualización

Device Firmware Update - tres estrategias según recursos disponibles.

memory

Single Slot

Serial Recovery

Bootloader recibe imagen por UART y escribe directamente en el slot de aplicación.

Ventaja: Menor uso de Flash
Desventaja: Sin rollback
swap_horiz

Dual Slot

Swap directo

Aplicación escribe en slot secundario. Bootloader intercambia al reiniciar.

Ventaja: App sigue funcionando durante descarga
Desventaja: Requiere doble espacio
history

Swap + Revert

Recomendado

Como dual slot, pero si la nueva app falla, bootloader revierte automáticamente.

Ventaja: Máxima seguridad
Ventaja: Rollback automático
tips_and_updates
Swap con revert: La nueva aplicación debe llamar a boot_write_img_confirmed() para marcar la imagen como válida. Si no lo hace antes del siguiente reinicio, el bootloader revierte a la versión anterior.

Swap con revert: flujo completo

Cómo funciona la actualización segura con rollback automático.

Secuencia de actualización

1
Descarga de imagen
App actual escribe nueva imagen en slot secundario
2
Marca como pendiente
App solicita actualización y reinicia
3
Bootloader intercambia
Swap entre slot primario y secundario
4
Nueva app arranca
Imagen nueva se ejecuta en modo TEST
5
Confirmación
boot_write_img_confirmed() marca como permanente

Escenario de fallo

error Si la nueva app falla...
  1. Nueva app se ejecuta pero tiene un bug
  2. Dispositivo se reinicia (crash o watchdog)
  3. Bootloader detecta que no se confirmó
  4. Automáticamente revierte a versión anterior
Confirmar imagen en código
#include <zephyr/dfu/mcuboot.h>
void main(void) {
/* Verificar que todo funciona */
if (self_test_passed()) {
boot_write_img_confirmed();
}
}

MCUboot: el bootloader de Zephyr

Bootloader por defecto en NCS/Zephyr, configurable y seguro.

Habilitar MCUboot

sysbuild.conf
# Habilitar MCUboot como bootloader
SB_CONFIG_BOOTLOADER_MCUBOOT=y

Con esta única línea, el sistema de build genera automáticamente el bootloader junto con tu aplicación.

auto_awesome
Firma automática: La herramienta imgtool.py firma la imagen de tu aplicación durante el build.

Modos de actualización

science
Modo TEST
Por defecto

La imagen nueva se ejecuta una vez. Si no se confirma, el siguiente reinicio revierte a la anterior.

verified
Modo CONFIRM
Permanente

Después de llamar boot_write_img_confirmed(), la imagen se marca como permanente.

Sysbuild: builds multi-imagen

Sistema de build de alto nivel para proyectos con bootloader.

Estructura de archivos

mi-proyecto/
src/
main.c
CMakeLists.txt
prj.conf # Config de app
sysbuild.conf # Config de sysbuild
sysbuild/
mcuboot.conf # Overlay MCUboot

Archivos de configuración

sysbuild.conf
# Prefijo SB_CONFIG_ para sysbuild
SB_CONFIG_BOOTLOADER_MCUBOOT=y
sysbuild/mcuboot.conf
# Configuración específica de MCUboot
CONFIG_BOOT_SWAP_USING_MOVE=y
CONFIG_BOOT_UPGRADE_ONLY=n
info
Prefijo SB_CONFIG_: Las opciones de sysbuild usan el prefijo SB_CONFIG_, mientras que las opciones normales de Kconfig usan CONFIG_.

Partition Manager

Gestiona las particiones de memoria para bootloader y aplicación.

Particiones típicas

Partición Tamaño Uso
mcuboot 48 KB Bootloader
mcuboot_primary ~200 KB App activa
mcuboot_secondary ~200 KB Actualización
mcuboot_scratch 16 KB Swap temporal
settings_storage 8 KB NVS/Settings

Configuración estática

pm_static.yml
mcuboot:
address: 0x0
size: 0xc000
mcuboot_primary:
address: 0xc000
size: 0x32000
mcuboot_secondary:
address: 0x3e000
size: 0x32000
lightbulb
Flash externa: Si la Flash interna no es suficiente, el slot secundario puede ubicarse en memoria Flash externa (QSPI).

FOTA: Firmware Over The Air

DFU a través de conexiones inalámbricas: BLE, Wi-Fi, Cellular.

bluetooth

BLE DFU

Actualización desde app móvil o gateway BLE.

nRF Connect SDK
cell_tower

Cellular (LTE-M/NB-IoT)

Para dispositivos con nRF9160 y conectividad celular.

AWS IoT / Azure IoT
wifi

Wi-Fi

Para dispositivos con nRF7002 o Wi-Fi externo.

HTTP/HTTPS/CoAP
info
FOTA siempre usa dual-slot: La aplicación actual sigue ejecutándose mientras descarga la nueva imagen en el slot secundario. Esto es necesario porque la conexión inalámbrica la gestiona la aplicación.

Claves propias para producción

Nunca uses las claves de desarrollo en dispositivos reales.

Generar claves propias

Terminal
# Generar clave privada EC P-256
imgtool keygen -k my_private_key.pem -t ecdsa-p256
# Extraer clave pública (para bootloader)
imgtool getpub -k my_private_key.pem

Configurar en sysbuild

sysbuild.conf
# Usar clave propia para firmar
SB_CONFIG_BOOT_SIGNATURE_KEY_FILE=\
"keys/my_private_key.pem"

warning Buenas prácticas de seguridad

  • close Nunca subas la clave privada a repositorios Git
  • close Nunca uses las claves de ejemplo del SDK en producción
  • check Usa un HSM (Hardware Security Module) para almacenar claves en entornos críticos
  • check Genera claves diferentes para cada producto/cliente

Resumen del módulo

Conceptos clave para actualizaciones seguras de firmware.

deployed_code

Bootloader

Programa inmutable en 0x00000000 que verifica y carga la aplicación.

swap_horiz

DFU Dual-slot

Actualización segura con rollback automático si la nueva imagen falla.

security

Firmas digitales

Clave pública en bootloader, clave privada segura en servidor de build.

tips_and_updates

"Un buen bootloader es la diferencia entre un producto actualizable y un ladrillo."

Invierte tiempo en configurar correctamente MCUboot y FOTA desde el principio. Es mucho más difícil añadirlo después.

Referencia rápida

Configuración y particiones esenciales para MCUboot.

Configuración básica
SB_CONFIG_BOOTLOADER_MCUBOOT=y
boot_write_img_confirmed()
Particiones clave
Bootloader mcuboot
App activa mcuboot_primary
Nueva imagen mcuboot_secondary
arrow_forward Siguiente módulo

3.1 Introducción a BLE

Fundamentos de Bluetooth Low Energy y comunicación inalámbrica.