2 puntos por GN⁺ 2025-10-26 | 1 comentarios | Compartir por WhatsApp
  • Explicación técnica paso a paso del proceso desde el momento en que se presiona el botón de encendido de la computadora hasta que se ejecuta el kernel de Linux
  • Aborda en detalle cómo la CPU comienza en modo real (real mode) y luego entra en modo protegido (protected mode) y modo largo (long mode)
  • Describe en detalle el rol y el funcionamiento de cada etapa, como el firmware BIOS/UEFI, el bootloader (GRUB) y la descompresión del kernel y reubicación de direcciones
  • Explica conceptos clave necesarios para la inicialización del kernel, como mapeo de memoria, interrupciones, tablas de páginas y kASLR, con ejemplos breves
  • Al entender los mecanismos internos del arranque de Linux, ofrece una perspectiva sobre arquitectura de sistemas, seguridad y optimización de rendimiento

Part 1 — Del botón de encendido a la primera ejecución del kernel

  • Cuando se presiona el botón de encendido, la CPU se reinicia en modo real (real mode) y ejecuta sus primeras instrucciones

    • El modo real es un esquema de direccionamiento simple que existe desde la era del 8086, y calcula direcciones físicas combinando segmento (segment) y desplazamiento (offset)
    • Ejemplo: physical_address = (segment << 4) + offset
    • Después del reset, la CPU salta a la dirección 0xFFFFFFF0 (reset vector) y cede el control al firmware
  • Los registros (registers) son ranuras de almacenamiento ultrarrápidas dentro de la CPU, como CS (code segment) e IP (instruction pointer)

    • CS indica la ubicación del código actual, e IP apunta a la siguiente instrucción a ejecutar

BIOS y UEFI

  • BIOS es un firmware antiguo que, después del POST (autoprueba de encendido), verifica el orden de arranque y busca un disco arrancable
    • Un disco arrancable se identifica porque el final de su primer sector de 512 bytes está marcado con 0x55AA
    • BIOS copia ese sector a la dirección 0x7C00, luego salta allí para ejecutarlo
  • UEFI es la alternativa moderna, capaz de entender directamente el sistema de archivos y cargar programas de arranque más grandes
    • A diferencia de BIOS, no tiene la restricción del “primer sector” y entrega información del sistema más rica al sistema operativo

Bootloader

  • El bootloader es el programa que carga el kernel en memoria y lo prepara para su ejecución
    • Uno de los más usados es GRUB, que lee archivos de configuración y carga en memoria el kernel y el initrd (ramdisk inicial)
    • El archivo del kernel está compuesto por un pequeño programa de configuración para modo real y el cuerpo principal comprimido del kernel
    • GRUB escribe información como la ubicación del kernel, la línea de comandos y la posición del initrd en la estructura setup header, y luego salta al código de configuración del kernel

Programa de configuración (setup code)

  • Su función es crear un espacio de trabajo predecible antes de ejecutar el kernel
    • Alinea los registros de segmento (CS, DS, SS) y limpia el direction flag para que las copias de memoria funcionen de forma consistente
    • Crea una pila (stack) para guardar datos temporales durante las llamadas a funciones
    • Inicializa en cero la sección BSS (espacio de variables globales que debe comenzar con valor 0)
  • Si está la opción earlyprintk, puede configurar el puerto serial para mostrar mensajes de depuración temprana
  • Solicita al firmware el mapa de RAM (e820) para conocer las regiones de memoria disponibles y las reservadas
  • Cuando todo está listo, llama a main, la primera función en C, y luego entra en la etapa de cambio de modo

Interrupciones (interrupts)

  • Las interrupciones son un mecanismo por el que la CPU pausa temporalmente su trabajo actual para atender algo urgente
    • Ejemplos típicos son eventos de hardware como entradas de teclado o temporizadores
    • Las interrupciones enmascarables pueden bloquearse temporalmente, mientras que NMI (Non-Maskable Interrupt) siempre se atiende
    • Durante el cambio de modo se bloquean temporalmente para evitar interrupciones inesperadas

Part 2 — Del modo real a 32 bits, y luego a 64 bits

  • Linux moderno funciona en modo largo (long mode) de la arquitectura x86_64
    • Se requiere una transición gradual en este orden: modo real → modo protegido → modo largo

Modo protegido (protected mode)

  • Es un modo de 32 bits introducido para superar las limitaciones de los años 80, con dos estructuras clave
    • GDT (Global Descriptor Table): define la dirección base, el tamaño y los permisos de los segmentos
      • Linux usa el modelo plano (flat model) para simplificar todo el espacio de 32 bits como una sola región continua
    • IDT (Interrupt Descriptor Table): almacena la dirección del handler que debe llamarse cuando ocurre una interrupción
      • Durante el arranque se carga solo una IDT mínima, y después de la inicialización del kernel se instala una IDT completa

Proceso de cambio de modo

  • El código de configuración primero realiza desactivación de interrupciones, detención del chip PIC, activación de la línea A20 e inicialización del coprocesador matemático
    • La línea A20 es un mecanismo histórico para resolver el problema del wrapping de direcciones en 1 MB
  • Después de cargar una GDT e IDT mínimas, configura el bit PE del registro CR0 y realiza un far jump
    • Con esto entra en modo protegido, y vuelve a configurar los segmentos y el puntero de pila según el nuevo esquema de direcciones

Registros de control (control registers)

  • CR0: activa el modo protegido
  • CR3: almacena la dirección de nivel superior de las tablas de páginas
  • CR4: activa funciones extendidas como PAE

Preparación para entrar en modo largo (long mode)

  • Para cambiar a modo de 64 bits se necesitan dos condiciones
    • Activar la paginación (paging): realiza el mapeo entre direcciones virtuales y físicas
    • Configurar el bit LME (Long Mode Enable) del registro EFER
  • Las tablas de páginas mapean páginas en unidades de 4 KB, pero en el arranque inicial se usan de forma simple con un identity map de 2 MB

Procedimiento para activar la paginación

  • Activa PAE en CR4 y crea una tabla de páginas mínima que cubre la zona de direcciones bajas en bloques de 2 MB
  • Escribe en CR3 la dirección de la tabla superior y luego activa la paginación
  • Configura el bit LME de EFER y salta al código de 64 bits para entrar en modo largo
  • Con las direcciones y los registros extendidos a 64 bits, el kernel queda listo para ejecutarse

Part 3 — Descompresión del kernel, ajuste de direcciones y auto-reubicación

  • En este punto la CPU ya está en modo de 64 bits y en memoria existe una imagen comprimida del kernel
    • Un pequeño stub de 64 bits se encarga de descomprimir el kernel y ajustar sus direcciones

Limpieza inicial y configuración de salvaguardas

  • El stub calcula su ubicación real de ejecución y, si el kernel se superpone, se mueve a una posición segura mediante self-relocation
  • Inicializa su propia sección BSS y carga una IDT simple (incluye handlers para page fault y NMI)
    • Si ocurre un page fault, agrega de inmediato el mapeo faltante para recuperarse
  • Crea mapeos de identidad para las áreas necesarias, como el kernel, los parámetros de arranque y el búfer de línea de comandos

Descompresión del kernel

  • Se ejecuta la función extract_kernel para descomprimir el kernel
    • Soporta varios algoritmos de compresión, como gzip, xz, zstd y lzo
    • Tras descomprimir, lee el encabezado ELF para copiar las secciones de código y datos a las direcciones correctas
  • Si la dirección para la que se compiló el kernel y la dirección real de carga son distintas, se realiza una reubicación (relocation)
    • Se ajustan las instrucciones o punteros que contienen direcciones para que coincidan con la ubicación real en memoria
  • Cuando todo está listo, salta a la función start_kernel y comienza la inicialización formal del kernel

Auto-reubicación del kernel (kASLR)

  • kASLR (Kernel Address Space Layout Randomization) aleatoriza las direcciones físicas y virtuales del kernel para dificultar los ataques
    • Durante el arranque se eligen aleatoriamente dos bases (base)
      • Base física: la dirección de RAM donde realmente quedará ubicado el kernel
      • Base virtual: el punto inicial de la dirección virtual que usará el kernel
  • Proceso de selección
    • Se prepara una lista de áreas que deben protegerse, como el bootloader, el initrd y el búfer de línea de comandos
    • Se escanea el mapa de memoria del firmware para encontrar un espacio libre lo bastante grande
    • Se elige un slot aleatorio usando entropía obtenida de instrucciones de números aleatorios por hardware u otras fuentes
  • Si no hay una región adecuada, vuelve a la dirección predeterminada, y con la opción nokaslr se desactiva la aleatorización

Resumen de términos

  • Hexadecimal (hexadecimal): se representa con el prefijo 0x, útil para la estructura de bits y la alineación en hardware
  • Register: almacenamiento temporal dentro de la CPU (CS, DS, SS, IP, SP, etc.)
  • Segment/Offset: método de cálculo de direcciones en modo real (segment * 16 + offset)
  • BIOS/UEFI: firmware encargado de la inicialización del sistema y la carga del programa de arranque
  • Bootloader (GRUB): carga del kernel y entrega de información del sistema
  • Stack/BSS: almacenamiento temporal para funciones y zona de variables globales inicializadas en cero
  • Interrupt/NMI: mecanismo para manejar eventos de hardware y software
  • GDT/IDT: tablas de definición de segmentos e interrupciones
  • A20 Line: interruptor para evitar el wrapping de direcciones en 1 MB
  • Protected Mode/Long Mode: modos de ejecución de 32 y 64 bits
  • Paging/Page Tables: mapeo entre direcciones virtuales y físicas

1 comentarios

 
GN⁺ 2025-10-26
Comentarios de Hacker News
  • Fue un artículo realmente bueno. Hace unos meses yo también escribí sobre el proceso de arranque de Linux, pero enfocándome un poco más en el lado del I/O de disco (qué hay en el disco y cómo se carga). Mi artículo se puede ver en Booting x86-64
  • Había este código en el código fuente de la página
    
      uwu
    
    
    Me dejó con cara de “¿qué es esto?”
    • Aún es una función en desarrollo
  • UEFI es una interfaz implementada por el firmware. Es decir, no es el firmware en sí, sino una interfaz estándar para comunicarse con él. Decir que “UEFI inicia la máquina” es usar el término de forma un poco incorrecta. En realidad, el firmware inicia la máquina, y nosotros nos comunicamos con el firmware a través de UEFI. Este artículo omite muchas partes interesantes del firmware moderno. Por ejemplo, al llamar a ExitBootServices() ya se entró en long mode. No hace falta pasar por todo el proceso de cambio entre real/protected mode
    • Me gustaría saber dónde se puede leer más sobre esto
  • Me preguntaba si el botón de encendido realmente enciende directamente la CPU. Tal vez Intel Management Engine (o alguna función similar de AMD) está siempre encendido, recibe la señal del botón y luego inicia la CPU
    • Creo que ese papel lo cumple el Embedded Controller (EC). Es la parte que funciona antes de que el bootloader levante la CPU. En los Chromebook, esta parte está publicada como open source junto con el bootloader coreboot. La documentación relacionada se puede ver en Chromium EC Zephyr README
  • Estoy buscando una versión más detallada que este artículo. No quiero leer completo un datasheet de microprocesador, pero me gustaría encontrar material que profundice un poco más incluso en lo anterior a UEFI/BIOS
  • El artículo fue interesante, pero por otro lado me pregunté por qué tenía que incluir hasta una explicación de hexadecimal (HEX). Me costó creer que alguien que lea un artículo de este nivel no sepa eso. Otra cosa que me da curiosidad es cómo, en el momento en que se presiona el botón físico de encendido, eso termina conectado al reset vector. Esa ya es una zona de magia de hardware y circuitos electrónicos
    • HN no lo leen solo profesionales de TI. Puede haber gente con curiosidad sobre el proceso de arranque de Linux que no conozca bien el concepto de hexadecimal o lo haya olvidado
  • El tema es interesante, pero se sintió demasiado orientado a principiantes
    • Cuando ves explicaciones como “cuando la energía se estabiliza, la CPU se reinicia en real mode”, dan ganas de preguntarse si mi abuela es lo suficientemente experta como para entender esto
    • En la universidad aprendí sobre análisis de audiencia (audience analysis), y es importante decidir qué conocimientos se van a asumir y qué términos o siglas se deben explicar. En escritura técnica, eso es una especie de arte
  • Fue difícil de leer en móvil. El color del texto era demasiado tenue
    • Incluso en navegador de escritorio, el estilo visual no era muy bueno. Si usas el modo lector de Firefox o Firefox Mobile, se lee mucho mejor
    • Parecía un diseño un poco autodenigrante
  • Se mencionó GRUB, pero no se trató en detalle. Sobre eso, el documento sobre estructura de discos de Pixelbeat ayuda bastante
  • Este artículo me hizo recordar una entrevista técnica de Facebook que tuve hace años. Fue una entrevista telefónica, alrededor de 2010, para un puesto de Production Engineer, y me preguntaron: “explica el proceso de arranque de un servidor Linux”. No me dieron ninguna ayuda aparte de insinuar que profundizara más. Al final no me mudé a Dublín y, bueno, aquello de surveillance capitalism y todo eso... digamos que las uvas seguían verdes