2 pontos por GN⁺ 2025-10-26 | Ainda não há comentários. | Compartilhar no WhatsApp
  • Explicação técnica, passo a passo, do processo desde o momento em que se aperta o botão de energia do computador até a execução do kernel Linux
  • Aborda em detalhe como a CPU sai do real mode e entra no protected mode e no long mode
  • Descreve com detalhes o papel e o funcionamento de cada etapa, como firmware BIOS/UEFI, bootloader (GRUB) e descompressão e relocação de endereços do kernel
  • Explica, com exemplos concisos, conceitos centrais necessários para a inicialização do kernel, como mapeamento de memória, interrupções, tabelas de páginas e kASLR
  • Ao compreender os mecanismos internos do boot do Linux, oferece insights sobre arquitetura de sistemas, segurança e otimização de desempenho

Part 1 — Do botão de energia até a primeira execução do kernel

  • Ao apertar o botão de energia, a CPU é resetada em real mode e executa as instruções iniciais

    • O real mode é um esquema simples de endereçamento que existe desde a era do 8086 e calcula o endereço físico combinando segmento (segment) e offset
    • Exemplo: physical_address = (segment << 4) + offset
    • Após o reset, a CPU salta para o endereço 0xFFFFFFF0 (vetor de reset) e entrega o controle ao firmware
  • Registradores (registers) são slots de armazenamento ultrarrápidos dentro da CPU, como CS (code segment) e IP (instruction pointer)

    • CS indica a localização do código atual, e IP aponta para a próxima instrução a ser executada

BIOS e UEFI

  • BIOS é o firmware mais antigo: após o POST (autoteste ao ligar), verifica a ordem de boot e procura um disco inicializável
    • Um disco inicializável é marcado por 0x55AA no fim dos primeiros 512 bytes do setor inicial
    • A BIOS copia esse setor para o endereço 0x7C00 e então salta para executá-lo
  • UEFI é a alternativa moderna, capaz de entender diretamente o sistema de arquivos e carregar programas de boot maiores
    • Diferentemente da BIOS, não há a limitação do “primeiro setor”, e ela entrega informações de sistema mais ricas ao sistema operacional

Bootloader

  • O bootloader é o programa que carrega o kernel na memória e prepara sua execução
    • O mais comum é o GRUB, que lê o arquivo de configuração e carrega o kernel e o initrd (initial ramdisk) na memória
    • O arquivo do kernel é composto por um pequeno programa de setup para real mode e pelo corpo principal compactado do kernel
    • O GRUB grava informações como a localização do kernel, a linha de comando e a posição do initrd na estrutura setup header e então salta para o código de configuração do kernel

Programa de setup (setup code)

  • Antes da execução do kernel, ele cria um espaço de trabalho previsível
    • Alinha os registradores de segmento (CS, DS, SS) e limpa a direction flag para que a cópia de memória funcione de forma consistente
    • Cria a stack para armazenar dados temporários durante chamadas de função
    • Inicializa com zero a área BSS (espaço de variáveis globais que devem começar com valor 0)
  • Se a opção earlyprintk estiver presente, pode configurar a porta serial para emitir mensagens iniciais de depuração
  • Solicita ao firmware o mapa de RAM (e820) para identificar áreas de memória disponíveis e reservadas
  • Quando tudo está pronto, chama main, a primeira função em C, e em seguida entra na etapa de troca de modo

Interrupções

  • Interrupções são o mecanismo pelo qual a CPU pausa temporariamente a tarefa atual para tratar algo urgente
    • Eventos de hardware como teclas pressionadas e timers são exemplos típicos
    • Interrupções mascaráveis podem ser bloqueadas temporariamente, enquanto a NMI (Non-Maskable Interrupt) é sempre tratada
    • Durante a troca de modo, elas são bloqueadas temporariamente para evitar interrupções inesperadas

Part 2 — Do real mode para 32 bits, e depois para 64 bits

  • O Linux moderno roda no long mode da arquitetura x86_64
    • É necessário fazer uma transição em etapas: real mode → protected mode → long mode

Protected mode

  • Trata-se do modo de 32 bits introduzido para superar limitações dos anos 1980, com duas estruturas centrais
    • GDT (Global Descriptor Table): define endereço inicial, tamanho e permissões dos segmentos
      • O Linux usa o flat model, simplificando todo o espaço de 32 bits como uma única região contínua
    • IDT (Interrupt Descriptor Table): armazena os endereços dos handlers a serem chamados quando ocorre uma interrupção
      • Durante o boot, apenas uma IDT mínima é carregada; depois da inicialização do kernel, instala-se a IDT completa

Processo de troca de modo

  • O código de setup primeiro realiza desativação de interrupções, parada do chip PIC, ativação da linha A20 e inicialização do coprocessador matemático
    • A linha A20 é um mecanismo histórico para resolver o problema de wrap de endereços em 1 MB
  • Depois de carregar uma GDT e uma IDT mínimas, ele define o bit PE do registrador CR0 e executa um far jump
    • Com isso, entra no protected mode e reconfigura os segmentos e o ponteiro de stack de acordo com o novo esquema de endereçamento

Registradores de controle

  • CR0: ativa o protected mode
  • CR3: armazena o endereço de topo das tabelas de páginas
  • CR4: ativa recursos estendidos como PAE

Preparação para entrar no long mode

  • Para mudar para o modo de 64 bits, duas condições são necessárias
    • Ativar a paginação (paging): faz o mapeamento entre endereços virtuais e físicos
    • Definir o bit LME (Long Mode Enable) no registrador EFER
  • As tabelas de páginas mapeiam páginas de 4 KB e, no boot inicial, são montadas de forma simples com um identity map em blocos de 2 MB

Procedimento para ativar a paginação

  • Ativa o recurso PAE em CR4 e cria o conjunto mínimo de tabelas de páginas cobrindo a região de endereços baixos em blocos de 2 MB
  • Grava o endereço da tabela de topo em CR3 e ativa a paginação
  • Define o bit LME em EFER e salta para código de 64 bits, entrando no long mode
  • Com endereços e registradores expandidos para 64 bits, a execução do kernel fica pronta para começar

Part 3 — Descompressão do kernel, ajuste de endereços e auto-relocação

  • Agora a CPU já está em modo de 64 bits e existe na memória uma imagem compactada do kernel
    • Um pequeno stub de 64 bits fica responsável por descompactar o kernel e ajustar seus endereços

Limpeza inicial e configuração de mecanismos de segurança

  • O stub calcula sua posição real de execução e, se houver sobreposição com o kernel, move-se para uma posição segura por self-relocation
  • Inicializa sua própria área BSS e carrega uma IDT simples (incluindo handlers de page fault e NMI)
    • Se ocorrer um page fault, ele adiciona imediatamente o mapeamento ausente para se recuperar
  • Cria mapeamentos identity para as áreas necessárias, como kernel, parâmetros de boot e buffer da linha de comando

Descompressão do kernel

  • A função extract_kernel é executada para descompactar o kernel
    • Suporta vários algoritmos de compressão, como gzip, xz, zstd e lzo
    • Após a descompressão, lê o cabeçalho ELF e copia as seções de código/dados para os endereços corretos
  • Se o endereço em que o kernel foi compilado diferir do endereço real em que foi carregado, é feita a relocação (relocation)
    • Instruções e ponteiros que contêm endereços são ajustados para corresponder à posição real na memória
  • Quando tudo está pronto, ele salta para a função start_kernel, iniciando a fase principal de inicialização do kernel

Auto-relocação do kernel (kASLR)

  • kASLR (Kernel Address Space Layout Randomization) randomiza os endereços físicos e virtuais do kernel para dificultar ataques
    • Durante o boot, escolhe aleatoriamente duas bases
      • Base física: o endereço de RAM onde o kernel realmente ficará
      • Base virtual: o endereço virtual inicial que o kernel usará
  • Processo de escolha
    • Cria uma lista de áreas que precisam ser protegidas, como bootloader, initrd e buffer da linha de comando
    • Examina o mapa de memória do firmware em busca de uma área livre suficientemente grande
    • Escolhe um slot aleatório com base em entropia obtida, por exemplo, de instruções de geração de números aleatórios do hardware
  • Se não houver uma área adequada, volta ao endereço padrão; com a opção nokaslr, a randomização é desativada

Resumo dos termos

  • Hexadecimal (base 16): indicado pelo prefixo 0x, facilita a representação de estruturas de bits e alinhamento em hardware
  • Register: armazenamento temporário dentro da CPU (CS, DS, SS, IP, SP etc.)
  • Segment/Offset: forma de cálculo de endereços no real mode (segment * 16 + offset)
  • BIOS/UEFI: firmware responsável pela inicialização do sistema e pelo carregamento do programa de boot
  • Bootloader (GRUB): carrega o kernel e repassa informações do sistema
  • Stack/BSS: área temporária para funções e área de variáveis globais inicializadas com zero
  • Interrupt/NMI: mecanismo de tratamento de eventos de hardware e software
  • GDT/IDT: tabelas que definem segmentos e interrupções
  • A20 Line: chave para evitar o wrap de endereços em 1 MB
  • Protected Mode/Long Mode: modos de execução de 32 e 64 bits
  • Paging/Page Tables: mapeamento entre endereços virtuais e físicos

Ainda não há comentários.

Ainda não há comentários.