← Fundamentos de Sistemas Operativos Bloque 5 · El proceso de arranque · Tema 20 de 34

Tema 20

Del botón de encendido al firmware: BIOS y UEFI

Al encender una computadora, la memoria está vacía y el sistema operativo es un archivo en un disco que nadie sabe leer todavía. En este tema seguimos los primeros segundos: qué ejecuta el procesador antes de que exista nada, quién prepara el hardware y cómo se encuentra, en un disco de cientos de gigabytes, el programa que debe continuar.

1. Arrancar: un problema circular

A lo largo del curso dimos por hecho que el kernel ya estaba en memoria, con su tabla de vectores construida, sus drivers cargados y el temporizador en marcha. Pero la memoria principal es volátil, como vimos en el tema 7: al encender el equipo no contiene nada útil. El kernel está en el disco, como un archivo.

Para traerlo a la memoria hay que leer el disco. Leer el disco requiere un driver, y encontrar un archivo requiere entender un sistema de archivos. Las dos cosas son parte del sistema operativo. Hace falta el sistema operativo para cargar el sistema operativo.

El círculo se rompe procediendo por etapas. Un programa muy pequeño, que está disponible sin necesidad de cargarlo, sabe lo justo para cargar otro algo mayor; este, a su vez, sabe cargar el siguiente. Cada etapa es más capaz que la anterior, y la última es el sistema completo. El nombre en inglés, boot, viene de bootstrap y de la expresión «levantarse tirando de los cordones de las propias botas».

La cadena de arranque: el firmware, guardado en un chip de la placa, carga al cargador de arranque; este carga al kernel, y el kernel inicia el primer proceso Firmware chip de la placa tema 20 Cargador partición EFI tema 21 Kernel /boot/vmlinuz tema 21 Primer proceso systemd tema 22
Cada eslabón carga al siguiente y le entrega el control. Este tema trata del primero.

Las cuatro etapas ocupan los tres temas de este bloque. La primera es la única que no vive en el disco, y por eso puede empezar.

Según tu entorno

Todo lo de este bloque se aplica a una instalación nativa de Linux. En una máquina virtual el recorrido es el mismo, con un firmware simulado por el programa de virtualización. En WSL no existe: Windows inicia el kernel de Linux directamente, sin firmware ni cargador, como advertimos en el tema 4. Allí los comandos de la sección 11 informan poco o nada.

2. El primer instante

Al pulsar el botón, la fuente de alimentación tarda unas décimas de segundo en estabilizar sus tensiones. Mientras tanto mantiene al procesador en estado de reinicio. Cuando lo libera, el procesador hace lo único que sabe hacer, el ciclo del tema 6: captar la instrucción que indica el contador de programa, y ejecutarla.

La cuestión es qué valor tiene el contador de programa cuando nadie lo fijó todavía. La respuesta está en el diseño del procesador:

El vector de reinicio es la dirección de memoria, fija y determinada por el fabricante, en la que un procesador busca su primera instrucción después de encenderse o reiniciarse.

En los procesadores x86 es la dirección 0xFFFFFFF0, dieciséis bytes por debajo de los 4 GB. En ese instante el estado de la máquina es el siguiente:

ComponenteEstado al encender
ProcesadorEn su modo más privilegiado, como vimos en el tema 12, y en un modo de compatibilidad de 16 bits heredado de 1978. Un solo núcleo activo.
Memoria principalSin contenido válido, y ni siquiera utilizable: sus circuitos necesitan ser configurados antes del primer acceso.
InterrupcionesDeshabilitadas. No existe ninguna tabla de vectores.
DispositivosSin inicializar. No hay pantalla, ni teclado, ni disco.

Si la memoria principal está vacía, en la dirección del vector de reinicio tiene que haber otra cosa. Los fabricantes de la placa base conectan en ese rango un chip de memoria flash, que conserva su contenido sin alimentación. El procesador no nota la diferencia: pide el contenido de una dirección y recibe una instrucción. Esa instrucción es un salto al comienzo de un programa grabado en el chip.

3. Qué es el firmware

El firmware es el software grabado en una memoria no volátil de la placa base, que el procesador ejecuta automáticamente al encenderse. Su tarea es dejar el hardware en condiciones de funcionar y transferir el control a un programa cargado desde un dispositivo de almacenamiento.

El nombre lo sitúa entre el hardware y el software: es un programa, pero viene con la máquina y se cambia rara vez. Hoy ocupa entre 16 y 32 MB, y se puede actualizar, aunque es una operación delicada: un firmware dañado deja el equipo sin primera instrucción que ejecutar.

Sus responsabilidades son cinco:

TareaEn qué consiste
InicializarConfigurar el procesador, la memoria principal y el conjunto de circuitos de la placa. Es código específico de cada modelo, y la razón de que el firmware lo provea el fabricante.
ComprobarVerificar que los componentes esenciales responden. Es el POST de la sección siguiente.
ConfigurarOfrecer una pantalla de ajustes, a la que se entra pulsando una tecla durante el arranque, y recordar lo elegido.
CargarLocalizar en un dispositivo el programa de la etapa siguiente, copiarlo a la memoria y saltar a él.
InformarDejar en memoria unas tablas que describen la máquina, para que el sistema operativo las consulte.

La última tarea suele pasarse por alto y es importante. Un kernel no puede adivinar cuánta memoria hay instalada, qué rangos están reservados ni cómo se apaga ese modelo de equipo. El firmware se lo comunica mediante tablas con formatos normalizados; la más conocida es ACPI, que describe los dispositivos de la placa y la gestión de energía.

En las PC hubo dos generaciones de firmware, muy distintas entre sí: BIOS y UEFI. Todos los equipos actuales usan la segunda, pero muchos conceptos y casi todo el vocabulario provienen de la primera, y por eso las vemos en orden.

4. El POST

La primera fase visible del firmware es la autocomprobación de encendido, POST por Power-On Self-Test. Es común a BIOS y a UEFI, y sigue un orden forzado por la dependencia entre componentes: no se puede usar nada que todavía no fue preparado.

  1. El procesador y el propio firmware. Se verifica que el contenido del chip no esté corrupto, mediante una suma de comprobación.
  2. La memoria principal. Se detecta cuánta hay, se ajustan sus parámetros eléctricos y se la prueba someramente. Hasta aquí el firmware trabajó sin memoria, usando registros y la caché del procesador.
  3. El video. Se inicializa la tarjeta gráfica. A partir de este momento puede mostrarse algo en pantalla.
  4. El teclado y los puertos USB, para poder entrar a la configuración.
  5. Los buses. Se recorren para descubrir qué dispositivos hay conectados y asignarles rangos de direcciones e interrupciones. Es la enumeración que describimos en el tema 8, hecha una primera vez.
  6. Los dispositivos de almacenamiento, entre los que se buscará el sistema.

Si algo falla antes del paso 3, no hay pantalla en la que avisar. Por eso las placas informan los errores tempranos con secuencias de pitidos o con un indicador luminoso de dos dígitos, cuyo significado figura en el manual. Un equipo que enciende sus ventiladores y no muestra imagen suele estar detenido en el paso 2 por un módulo de memoria mal colocado.

En los equipos actuales el POST dura uno o dos segundos. La opción de «arranque rápido» del firmware lo acorta omitiendo pruebas y dejando para el sistema operativo la inicialización de lo que no hace falta para arrancar.

5. BIOS: el diseño de 1981

La BIOS, de Basic Input/Output System, es el firmware de la IBM PC original. Su forma de iniciar el sistema es de una simplicidad extrema, porque la máquina para la que se diseñó tenía 64 KB de memoria y arrancaba desde disquetes:

  1. Recorre los dispositivos de almacenamiento en el orden configurado.
  2. De cada uno lee el primer sector, 512 bytes, y lo copia a la dirección 0x7C00 de la memoria.
  3. Comprueba que los dos últimos bytes sean 0x55 y 0xAA. Si lo son, considera que el dispositivo es arrancable.
  4. Salta a la dirección 0x7C00.

Eso es todo. La BIOS no sabe qué es un archivo, ni una partición, ni un sistema operativo. Carga 512 bytes de una posición fija y los ejecuta sin examinarlos; lo que ocurra después es asunto de esos 512 bytes.

El nombre alude a su segunda función. Además de arrancar, la BIOS ofrecía rutinas para usar el teclado, la pantalla y el disco, a las que los programas llegaban mediante interrupciones provocadas por software: int 0x10 para el video, int 0x13 para el disco. Era el mismo recurso que el int 0x80 de las llamadas al sistema de Linux en 32 bits, que vimos en el tema 13: usar la tabla de vectores del tema 17 para llegar a un servicio. MS-DOS dependía de esas rutinas. Los sistemas modernos las abandonan en cuanto arrancan, porque funcionan solo en el modo de 16 bits y son lentas; usan sus propios drivers.

Las limitaciones de este diseño se fueron volviendo insostenibles:

LimitaciónConsecuencia
Se ejecuta en modo de 16 bits, con acceso a 1 MB de memoria.Un firmware pequeño y primitivo, sin lugar para drivers ni funciones nuevas.
Carga solo 512 bytes.El programa de arranque no cabe, y debe cargarse a sí mismo por etapas.
Depende del formato de particiones MBR.Discos de 2 TB como máximo.
No verifica lo que ejecuta.Un programa malicioso instalado en el primer sector toma el control antes que el sistema operativo.

6. El MBR: un sector para todo

Ese primer sector tiene nombre propio: registro maestro de arranque, o MBR, de Master Boot Record. En 512 bytes debe contener dos cosas que no tienen relación entre sí: el comienzo del programa de arranque, y la descripción de cómo está dividido el disco.

Una partición es una porción contigua de un disco que el sistema trata como si fuera un dispositivo independiente. La tabla de particiones es la estructura, guardada en el propio disco, que indica dónde empieza y dónde termina cada una.

Estructura del primer sector de un disco con formato MBR: 446 bytes de código de arranque, cuatro entradas de partición de 16 bytes cada una y dos bytes de firma, 55 y AA 0 446 510 512 Código de arranque 446 bytes 1 2 3 4 55 AA tabla de particiones 4 entradas de 16 bytes firma
Los 512 bytes del sector 0. El dibujo no está a escala: el código ocupa casi nueve décimas del sector.

Cada entrada de 16 bytes describe una partición: si es la de arranque, de qué tipo es, en qué sector empieza y cuántos sectores ocupa. Los dos últimos datos se guardan en 4 bytes cada uno, y de ese tamaño salen las dos limitaciones del formato:

El formato es tan simple que se puede leer con un programa de cuarenta líneas. Usa las llamadas open y read del tema 14: para el kernel, un disco entero es un archivo más del que se pueden pedir bytes.

mbr.c
#include <fcntl.h>
#include <stdio.h>
#include <unistd.h>

#define TAM_SECTOR 512

/* Lee un entero de 32 bits guardado con el byte menos significativo primero. */
static unsigned long leer32(const unsigned char *p)
{
    return p[0] | (p[1] << 8) | (p[2] << 16) | ((unsigned long)p[3] << 24);
}

int main(int argc, char *argv[])
{
    unsigned char sector[TAM_SECTOR];
    int fd;

    if (argc != 2) {
        fprintf(stderr, "uso: %s disco\n", argv[0]);
        return 1;
    }

    fd = open(argv[1], O_RDONLY);
    if (fd == -1) {
        perror("open");
        return 1;
    }
    if (read(fd, sector, TAM_SECTOR) != TAM_SECTOR) {   /* el sector 0 */
        fprintf(stderr, "No se pudo leer el primer sector\n");
        return 1;
    }
    close(fd);

    printf("Firma: 0x%02x%02x (%s)\n", sector[510], sector[511],
           (sector[510] == 0x55 && sector[511] == 0xaa) ? "valida" : "no valida");

    for (int i = 0; i < 4; i++) {
        const unsigned char *e = sector + 446 + i * 16;     /* entrada i de la tabla */
        unsigned long inicio = leer32(e + 8);
        unsigned long cantidad = leer32(e + 12);

        if (e[4] == 0) {
            printf("Particion %d: vacia\n", i + 1);
            continue;
        }
        printf("Particion %d: tipo 0x%02x, arranque %s, sector inicial %lu, %lu sectores (%lu MB)\n",
               i + 1, e[4], (e[0] == 0x80) ? "si" : "no",
               inicio, cantidad, cantidad / 2048);
    }
    return 0;
}

Para probarlo sin tocar ningún disco real, creamos un archivo de 64 MB y le escribimos una tabla de particiones con sfdisk. Las herramientas de particionado trabajan igual sobre un archivo que sobre un dispositivo, y sobre un archivo propio no requieren privilegios.

terminal
$ gcc -Wall -Wextra -g mbr.c -o mbr
$ truncate -s 64M disco.img                      # un «disco» vacío de 64 MB
$ printf 'label: dos\n,32M,L,*\n,,L\n' | sfdisk -q disco.img

$ xxd -s 510 -l 2 disco.img                      # los dos últimos bytes del sector 0
000001fe: 55aa                                     U.

$ ./mbr disco.img
Firma: 0x55aa (valida)
Particion 1: tipo 0x83, arranque si, sector inicial 2048, 65536 sectores (32 MB)
Particion 2: tipo 0x83, arranque no, sector inicial 67584, 63488 sectores (31 MB)
Particion 3: vacia
Particion 4: vacia

Las tres líneas que recibe sfdisk piden una tabla de tipo MBR, que esa herramienta llama dos; una partición de 32 MB de tipo Linux marcada como arranque; y otra con el resto. El programa encuentra exactamente eso: el tipo 0x83 identifica una partición de Linux, y la primera empieza en el sector 2048, a 1 MB del comienzo, una separación que las herramientas dejan por costumbre.

Lo que el programa hace con disco.img es lo mismo que hace la BIOS con el disco real: leer 512 bytes de la posición 0 y mirar los dos últimos.

7. UEFI: un firmware que entiende archivos

A fines de los años noventa, Intel diseñó un firmware nuevo para una línea de procesadores en la que la BIOS no podía funcionar. De ese trabajo salió una especificación abierta, hoy mantenida por un consorcio de fabricantes: UEFI, de Unified Extensible Firmware Interface. Reemplazó a la BIOS de manera gradual entre 2006 y 2020.

La diferencia de fondo está en cuánto sabe el firmware. La BIOS carga un sector sin entenderlo. UEFI es casi un pequeño sistema operativo:

Con estas capacidades, el arranque deja de depender de una posición fija del disco. El firmware lee de sus variables una entrada que dice, en esencia, «en tal partición de tal disco, ejecutar tal archivo», y lo hace. Instalar un segundo sistema operativo consiste en copiar su cargador a un directorio y añadir una entrada, sin sobrescribir nada del primero.

BIOSUEFI
Época1981 a 2020Desde 2006
Modo del procesador16 bits, 1 MB de memoria64 bits
Qué cargaEl sector 0 del disco: 512 bytesUn archivo .efi, del tamaño que haga falta
Dónde lo buscaEn una posición fijaEn un sistema de archivos, por su ruta
Tabla de particionesMBRGPT
Varios sistemas en un discoCompiten por el mismo sectorCada uno tiene su directorio y su entrada
Verifica lo que ejecutaNoSí, con el arranque seguro
ConfiguraciónPantalla de textoGráfica, con ratón; modificable también desde el sistema operativo

En la conversación diaria se sigue diciendo «entrar a la BIOS» para referirse a la pantalla de configuración, aunque el firmware sea UEFI. Durante la transición, muchas placas incluían además un modo de compatibilidad que imitaba a la BIOS, llamado CSM o Legacy; los equipos recientes ya no lo traen.

8. GPT: la tabla de particiones actual

La especificación de UEFI incluye un formato de tabla de particiones nuevo, que resuelve las limitaciones del MBR: GPT, de GUID Partition Table. Un GUID es un identificador de 128 bits, tan largo que se lo puede generar al azar con la seguridad práctica de que no se repetirá. GPT los usa para identificar el disco, cada partición y cada tipo de partición.

Disposición de un disco con formato GPT: un MBR de protección en el sector 0, la cabecera en el sector 1, la tabla de particiones en los sectores 2 a 33, las particiones, y al final del disco una copia de la tabla y de la cabecera MBR deprotección Cabecera Tabla departiciones Particiones Copia dela tabla Copia de lacabecera sector 0 1 2 a 33 últimos 33 sectores
Un disco con GPT. La tabla está al principio y, repetida, al final.

La estructura tiene tres ideas que merecen comentario:

MBRGPT
Cantidad de particiones4, o más con el recurso de las extendidas128 por defecto
Tamaño de las direcciones de sector32 bits64 bits
Tamaño máximo del disco2 TBMiles de millones de TB: sin límite práctico
Tipo de particiónUn byte: 0x83 es LinuxUn GUID
Identificación de cada particiónNinguna propiaUn GUID único y un nombre
Copia de seguridadNoSí, al final del disco
Detección de dañosNoSí
Contiene código de arranqueSí, 446 bytesNo

La última fila resume el cambio de diseño. En MBR, la tabla de particiones y el programa de arranque compartían un sector, y dañar uno era dañar el otro. En GPT la tabla es solo una tabla; el programa de arranque es un archivo, y vive en una partición.

9. La partición EFI

Esa partición es la partición del sistema EFI, abreviada ESP. Es una partición normal, con dos condiciones: su tipo en la tabla GPT es un GUID reservado, por el que el firmware la reconoce, y su sistema de archivos es FAT32, el único que la especificación obliga al firmware a entender.

FAT es un sistema de archivos de los años ochenta, muy simple, sin permisos ni dueños. Se eligió precisamente por eso: es fácil de implementar en un firmware, y todos los sistemas operativos saben leerlo y escribirlo. La partición ocupa entre 100 MB y 1 GB, y Linux la monta en /boot/efi. Es la primera línea de la salida de lsblk que vimos, sin explicarla, en el tema 5.

terminal
$ sudo ls -R /boot/efi/EFI
/boot/efi/EFI:
BOOT  Microsoft  ubuntu

/boot/efi/EFI/BOOT:
BOOTX64.EFI  fbx64.efi  mmx64.efi

/boot/efi/EFI/Microsoft:
…

/boot/efi/EFI/ubuntu:
BOOTX64.CSV  grub.cfg  grubx64.efi  mmx64.efi  shimx64.efi

$ sudo file /boot/efi/EFI/ubuntu/grubx64.efi
/boot/efi/EFI/ubuntu/grubx64.efi: PE32+ executable (EFI application) x86-64, for MS Windows

La organización sigue una convención: dentro del directorio EFI, cada sistema operativo instalado tiene un subdirectorio con su nombre. Este equipo tiene también Windows, y por eso hay un directorio Microsoft, con su cargador.

ArchivoFunción
EFI/ubuntu/shimx64.efiUn cargador mínimo, que el firmware ejecuta primero. Interviene en el arranque seguro de la sección 12.
EFI/ubuntu/grubx64.efiGRUB, el cargador de arranque propiamente dicho. Es el protagonista del tema 21.
EFI/BOOT/BOOTX64.EFILa ruta por defecto. El firmware la usa cuando no tiene ninguna entrada configurada, por ejemplo al arrancar desde una memoria USB.

El resultado de file tiene una curiosidad. Los programas .efi no usan el formato ELF del tema 9, sino PE, el de los ejecutables de Windows: la especificación de UEFI lo adoptó en su origen. El cargador de arranque de Linux es, por su formato, un ejecutable de Windows.

10. El recorrido completo

Reuniendo las piezas, esto es lo que ocurre en un equipo actual desde que se pulsa el botón hasta que el firmware cede el control:

  1. La fuente estabiliza la alimentación y libera al procesador del estado de reinicio. hardware
  2. El procesador capta su primera instrucción en el vector de reinicio, que corresponde al chip de memoria flash de la placa. hardware
  3. El firmware inicializa el procesador y la memoria principal, y pasa a ejecutarse en 64 bits. firmware
  4. Hace el POST: video, teclado, buses, dispositivos de almacenamiento. firmware
  5. Lee sus variables de arranque y toma la primera entrada de la lista. Si se pulsó la tecla correspondiente, muestra el menú para elegir otra. firmware
  6. Localiza el disco y la partición indicados. Para eso lee la tabla GPT y encuentra la partición EFI. firmware
  7. Abre el sistema de archivos FAT de esa partición y lee el archivo señalado, por ejemplo \EFI\ubuntu\shimx64.efi. firmware
  8. Verifica su firma, si el arranque seguro está activado. firmware
  9. Lo carga en memoria y salta a él. El firmware queda a disposición del cargador, que puede pedirle servicios. cargador de arranque

Todo el recorrido transcurre con el procesador en su modo más privilegiado y sin sistema operativo. No hay procesos, ni protección de memoria, ni llamadas al sistema: hay un programa que tiene la máquina entera para sí, como en los primeros tiempos que describimos en el tema 3.

11. Explorar tu equipo

El kernel conserva la información que recibió del firmware y la publica. Lo primero es saber con cuál de los dos tipos arrancó el equipo. Cuando arranca por UEFI, el kernel crea un directorio para dar acceso a las variables del firmware; su existencia es la respuesta:

terminal
$ [ -d /sys/firmware/efi ] && echo "UEFI" || echo "BIOS"
UEFI

$ cat /sys/class/dmi/id/bios_vendor /sys/class/dmi/id/bios_version /sys/class/dmi/id/bios_date
American Megatrends International, LLC.
F12
08/15/2023

$ sudo dmesg | grep -E 'efi: EFI|DMI:'
[    0.000000] efi: EFI v2.8 by American Megatrends
[    0.000000] DMI: Gigabyte Technology Co., Ltd. B550M DS3H/B550M DS3H, BIOS F12 08/15/2023

El segundo comando muestra el fabricante del firmware, su versión y su fecha, tomados de una de las tablas que el firmware deja en memoria. El tercero muestra al kernel leyéndolas en el instante cero de su ejecución. Los archivos conservan el nombre bios_ aunque el firmware sea UEFI.

La tabla de particiones se consulta con las herramientas habituales:

terminal
$ lsblk -o NAME,SIZE,FSTYPE,PARTTYPENAME,MOUNTPOINTS
NAME          SIZE FSTYPE PARTTYPENAME     MOUNTPOINTS
nvme0n1     476,9G
├─nvme0n1p1     1G vfat   EFI System       /boot/efi
└─nvme0n1p2 475,9G ext4   Linux filesystem /

$ sudo fdisk -l /dev/nvme0n1 | grep -E '^Disk /|Disklabel'
Disk /dev/nvme0n1: 476,94 GiB, 512110190592 bytes, 1000215216 sectors
Disklabel type: gpt

$ sudo ./mbr /dev/nvme0n1
Firma: 0x55aa (valida)
Particion 1: tipo 0xee, arranque no, sector inicial 1, 1000215215 sectores (488386 MB)
Particion 2: vacia
Particion 3: vacia
Particion 4: vacia

La partición de 1 GB es la partición EFI, con sistema de archivos vfat, el nombre que da Linux a FAT. Y el último comando, que ejecuta nuestro programa sobre el disco real, muestra el MBR de protección de la sección 8: una única partición de tipo 0xee, que empieza en el sector 1 y ocupa todos los demás. Hace falta sudo porque leer un disco entero permite saltarse los permisos de todos los archivos que contiene.

Las variables de arranque del firmware se leen con efibootmgr:

terminal (salida abreviada)
$ sudo efibootmgr
BootCurrent: 0001
Timeout: 1 seconds
BootOrder: 0001,0000,0002
Boot0000* Windows Boot Manager	HD(1,GPT,…)/File(\EFI\Microsoft\Boot\bootmgfw.efi)
Boot0001* ubuntu	HD(1,GPT,…)/File(\EFI\ubuntu\shimx64.efi)
Boot0002* UEFI: SanDisk Cruzer	…
LíneaSignificado
BootCurrentLa entrada con la que arrancó el sistema en esta ocasión.
BootOrderEl orden en que el firmware prueba las entradas.
Boot0001* ubuntuUna entrada: su nombre, la partición —la número 1 de un disco GPT, identificada por su GUID— y el archivo a ejecutar.

Este equipo tiene dos sistemas operativos, y cada uno tiene su entrada, que apunta a un archivo distinto de la misma partición EFI. Con este mismo comando, un administrador puede cambiar el orden o elegir con qué sistema arrancará la próxima vez, sin entrar a la pantalla del firmware. Las barras invertidas de las rutas son herencia de FAT y de MS-DOS.

12. El arranque seguro

El firmware entrega el control de la máquina, con privilegio total, al primer programa que carga. Si alguien consiguiera reemplazar ese programa por otro, tendría el control antes de que el sistema operativo existiera, y podría ocultarse de él para siempre. Es una amenaza real, y se conoce como bootkit.

El arranque seguro (Secure Boot) es la defensa que añade UEFI. El firmware guarda una lista de claves públicas de confianza, y solo ejecuta un programa .efi si lleva una firma digital hecha con alguna de las claves correspondientes. La comprobación se propaga por toda la cadena:

  1. El firmware verifica la firma del primer cargador.
  2. Ese cargador verifica la del siguiente.
  3. El último cargador verifica la del kernel.
  4. El kernel verifica la de cada módulo que incorpora.

Cada eslabón responde por el siguiente, y eso se llama cadena de confianza. Explica la presencia de shimx64.efi en la partición EFI. Las placas se venden con las claves de Microsoft instaladas, de modo que las distribuciones de Linux usan ese cargador mínimo, firmado por Microsoft, cuya única función es verificar con la clave de la propia distribución al cargador real, GRUB.

terminal
$ mokutil --sb-state
SecureBoot enabled

La consecuencia práctica aparece al usar código no firmado: un kernel compilado por uno mismo, o un módulo de un fabricante. Con el arranque seguro activado, el sistema se niega a cargarlo hasta que su dueño registre una clave propia o desactive la función en el firmware. No es un fallo: es la cadena de confianza haciendo su trabajo.

13. Otras plataformas

BIOS y UEFI son la historia de la PC. El problema del arranque es universal, y cada familia de equipos lo resolvió con las mismas etapas y distintos nombres:

PlataformaPrimera etapaParticularidad
PC y servidores x86UEFILo descrito en este tema.
Máquinas virtualesUn firmware simulado: SeaBIOS para BIOS, OVMF para UEFIEl hardware que inicializa también es simulado.
Placas ARM, como la Raspberry PiUn programa en una memoria de solo lectura del propio procesador, seguido a menudo del cargador U-BootNo hay enumeración de dispositivos: el hardware se describe al kernel en un archivo, el device tree.
Teléfonos AndroidUn cargador del fabricante, con verificación de firmasLa cadena de confianza suele venir bloqueada de fábrica.
Mac con procesador de AppleiBootCadena de confianza verificada desde el propio procesador.
MicrocontroladoresNinguna aparte: el programa completo está grabado en la memoria flashEl vector de reinicio apunta directamente a la aplicación.

La última fila es el caso límite, y aclara por qué existe todo lo demás. Cuando el programa es uno solo, pequeño y permanente, puede grabarse donde el procesador lo busca y no hace falta cadena alguna. Las etapas aparecen cuando el sistema es demasiado grande para caber en un chip, cuando debe poder actualizarse y cuando el usuario quiere elegir entre varios.

14. Resumen

15. Preguntas de repaso

Intenta responder cada una antes de abrir la respuesta.

1. ¿Por qué el sistema operativo no puede cargarse a sí mismo desde el disco?

Porque para leer el disco y encontrar un archivo hacen falta un driver y el código de un sistema de archivos, que son parte del propio sistema operativo y todavía no están en memoria. Hace falta un programa previo, disponible sin ser cargado.

2. ¿Qué es el vector de reinicio y por qué no puede apuntar a la memoria principal?

Es la dirección fija en la que el procesador busca su primera instrucción al encenderse. La memoria principal es volátil y en ese momento no contiene nada válido, así que esa dirección debe corresponder a una memoria que conserve su contenido sin alimentación.

3. Menciona las cinco tareas del firmware.

Inicializar el hardware, comprobarlo con el POST, ofrecer y recordar la configuración, cargar el programa de la etapa siguiente, y dejar en memoria tablas que describen la máquina para el sistema operativo.

4. Un equipo enciende los ventiladores, emite tres pitidos y no muestra imagen. ¿Por qué pitidos?

Porque el fallo ocurrió en una fase del POST anterior a la inicialización del video, y no hay pantalla donde escribir un mensaje. Los pitidos son el único medio disponible; su significado está en el manual de la placa.

5. ¿Qué hace exactamente una BIOS para iniciar el sistema?

Lee el primer sector del dispositivo de arranque, 512 bytes, lo copia a una dirección fija de la memoria, comprueba que termine con los bytes 0x55 y 0xAA, y salta a esa dirección.

6. ¿De dónde sale el límite de 2 TB de los discos con MBR?

La tabla guarda el sector inicial y la cantidad de sectores de cada partición en 32 bits. Con ese tamaño se cuentan unos 4300 millones de sectores, que a 512 bytes cada uno suman 2,2 billones de bytes.

7. ¿Cuál es la diferencia fundamental entre cómo carga la siguiente etapa una BIOS y cómo lo hace UEFI?

La BIOS carga un sector de una posición fija del disco, sin entender su contenido. UEFI entiende la tabla de particiones y un sistema de archivos, y carga un archivo indicado por su ruta en las variables de arranque.

8. ¿Para qué sirve el MBR de protección de un disco con GPT?

Para que una herramienta antigua, que solo conoce MBR, vea el disco como completamente ocupado por una partición de tipo desconocido, en lugar de verlo vacío y ofrecer inicializarlo.

9. ¿Qué ventaja tiene que GPT guarde una copia de la tabla al final del disco?

Si los primeros sectores se dañan o se sobrescriben por error, la tabla puede reconstruirse desde la copia. Con MBR, perder el sector 0 significaba perder la ubicación de todas las particiones.

10. ¿Por qué la partición EFI usa FAT32 y no el sistema de archivos de Linux?

Porque es el firmware quien debe leerla, y la especificación de UEFI solo le exige entender FAT. Es un formato simple de implementar, y todos los sistemas operativos pueden leerlo y escribirlo.

11. En un equipo con Windows y Linux, ¿cómo conviven los dos cargadores de arranque?

Cada uno es un archivo en su propio directorio de la partición EFI, y cada uno tiene una entrada en las variables de arranque del firmware. El orden de esas entradas decide cuál se ejecuta primero.

12. ¿Qué es la cadena de confianza del arranque seguro?

La secuencia de verificaciones en la que cada etapa comprueba la firma digital de la siguiente antes de ejecutarla: el firmware al cargador, el cargador al kernel, el kernel a sus módulos. Si un eslabón fue alterado, el anterior se niega a cargarlo.

Para practicar

  1. Averigua si tu equipo arrancó por UEFI o por BIOS, y quién fabricó su firmware, en qué versión y en qué fecha.
  2. Con lsblk -o NAME,SIZE,FSTYPE,PARTTYPENAME,MOUNTPOINTS, identifica la partición EFI de tu equipo. ¿Qué tamaño tiene? Mira cuánto está ocupada con df -h /boot/efi.
  3. Crea disco.img con cuatro particiones y verifícalo con mbr. Intenta después crear una quinta: ¿qué responde sfdisk?
  4. Modifica mbr.c para que, cuando el tipo sea 0xee, informe «disco con GPT: este MBR es solo de protección».
  5. Crea otra imagen con label: gpt en lugar de label: dos y ejecuta mbr sobre ella. Luego examina el sector 1 con xxd -s 512 -l 16: ¿qué texto contiene?
  6. Sobre esa imagen GPT, ejecuta sfdisk -l. Después borra la cabecera y la tabla, sin tocar el sector 0, con dd if=/dev/zero of=disco.img bs=512 seek=1 count=33 conv=notrunc, y repite. ¿Qué informa la herramienta, y de dónde saca los datos?
  7. Lista el contenido de tu partición EFI y relaciona cada directorio con una entrada de efibootmgr.
  8. Comprueba el estado del arranque seguro con mokutil --sb-state. Si está activado, busca en sudo dmesg | grep -i secure el momento en que el kernel lo detecta.
  9. La próxima vez que reinicies, entra a la pantalla de configuración del firmware y localiza el orden de arranque, el arranque seguro y la opción de virtualización que mencionamos en el tema 4. No modifiques nada que no entiendas.