Multiboot
Multiboot é uma especificação definindo como um bootloader passa o controle a um kernel: um contrato padronizado cobrindo como o kernel se identifica como compatível com Multiboot, em qual estado a CPU tem garantia de estar na entrada, e como o bootloader repassa informação (um mapa de memória, argumentos de linha de comando, localizações de módulos) de volta ao kernel. Seu principal benefício prático é desacoplar um kernel dos detalhes internos de qualquer bootloader específico: um kernel compatível com Multiboot funciona com qualquer bootloader que implemente a mesma especificação, mais comumente o GRUB, sem que nenhum dos dois lados precise saber mais nada sobre o outro.
O header Multiboot
Seção intitulada “O header Multiboot”Um kernel se declara compatível com Multiboot embutindo uma estrutura específica dentro dos primeiros 8 KB de seu binário, identificada por um magic number fixo que o bootloader busca. Multiboot 1 usa o magic number 0x1BADB002; Multiboot 2, uma revisão posterior e mais extensível, usa 0xE85250D6 e uma estrutura marcada um tanto mais elaborada, em vez de um único header de tamanho fixo.
// Header Multiboot 1struct multiboot_header { uint32_t magic; // 0x1BADB002 uint32_t flags; uint32_t checksum; // magic + flags + checksum == 0};
__attribute__((section(".multiboot")))struct multiboot_header mb_header = { .magic = 0x1BADB002, .flags = 0, .checksum = -(0x1BADB002 + 0),};O campo de checksum existe puramente para que um bootloader consiga validar que o header não foi corrompido ou identificado incorretamente por coincidência: os três campos são definidos para somar zero, módulo 2³², e um bootloader rejeita um header onde isso não acontece. Posicionar corretamente essa estrutura dentro dos primeiros 8 KB exigidos depende do linker script do kernel; um header enterrado mais adiante no binário por uma escolha azarada de ordenação de seção nunca será encontrado, e o bootloader recorre a tratar o kernel como não-Multiboot, geralmente falhando em carregá-lo por completo.
Estado de entrada garantido
Seção intitulada “Estado de entrada garantido”Um bootloader Multiboot garante um estado específico e documentado de CPU ao saltar para dentro do kernel: protected mode de 32 bits já ativo, paginação desabilitada, interrupções desabilitadas, e um par definido de registradores: EAX contendo um valor mágico (0x2BADB002 para Multiboot 1) confirmando que um carregador compatível com Multiboot foi de fato usado, e EBX contendo um ponteiro para a estrutura de informação Multiboot, a resposta do bootloader contendo o mapa de memória, a linha de comando de boot, e as localizações de quaisquer módulos carregados. O código de entrada mais inicial de um kernel convencionalmente verifica o valor mágico de EAX antes de confiar em qualquer outra coisa que lhe foi passada, já que um kernel acidentalmente carregado por um caminho não ciente de Multiboot deixaria ambos os registradores contendo valores não relacionados e sem sentido.
Notavelmente, esse estado garantido para no protected mode de 32 bits: um kernel visando long mode ainda precisa realizar a transição de protected para long mode por conta própria depois que o Multiboot passa o controle, já que o Multiboot é anterior ao x86-64 e não faz garantia alguma sobre estado de 64 bits.
A estrutura de informação
Seção intitulada “A estrutura de informação”A estrutura para a qual EBX aponta é, ela mesma, uma coleção marcada (Multiboot 2) ou orientada por flags (Multiboot 1) de informações opcionais, das quais apenas algumas um bootloader é obrigado a de fato popular. O mapa de memória física é a peça que praticamente todo kernel consome imediatamente, já que remove a necessidade de consultar a BIOS ou a UEFI diretamente; localizações de módulos de boot (usadas para carregar um ramdisk inicial, por exemplo) e a string de linha de comando do kernel também costumam estar presentes e são consumidas cedo.
Multiboot 1 versus Multiboot 2
Seção intitulada “Multiboot 1 versus Multiboot 2”O Multiboot 2 reestrutura o header de flags fixas em uma série de tags tipadas e prefixadas por comprimento, permitindo que a especificação adicione nova informação opcional sem quebrar as suposições de offset fixo de toda implementação existente, da forma que estender o campo de flags do Multiboot 1 faria. O Multiboot 2 também suporta formalmente ser carregado diretamente em modo de 64 bits em hardware capaz, embora o comportamento real de handoff do GRUB na prática ainda comumente deixe um kernel em protected mode de 32 bits independentemente da versão, deixando a transição para long mode a cargo do kernel de qualquer forma. Um kernel novo, sem requisito de compatibilidade legada, geralmente tem como alvo o Multiboot 2 por sua estrutura de tags mais extensível, embora o Multiboot 1 continue mais simples de implementar corretamente para um primeiro boot mínimo.
Notas de implementação
Seção intitulada “Notas de implementação”O requisito de linker script (posicionar o header Multiboot dentro dos primeiros 8 KB do binário) é uma fonte comum inicial de um kernel que o GRUB simplesmente se recusa a reconhecer, sem mensagem de erro além da falha genérica “unrecognized” do próprio GRUB, já que o bootloader não tem como distinguir “não é um kernel” de “um kernel cujo header está presente mas não onde ele está procurando”. Posicionar explicitamente o header em sua própria seção de linker, posicionada primeiro no layout do binário de saída, evita isso independentemente de como o compilador acabe ordenando o restante do código e dos dados.
Referências
Seção intitulada “Referências”- ^ GNU, Multiboot2 Specification: a especificação formal que este artigo resume.
Ver também
Seção intitulada “Ver também”- Bootloaders: o GRUB e outros carregadores compatíveis com Multiboot que implementam esse handoff.
- The Boot Process: onde o handoff Multiboot se encaixa na sequência de boot mais ampla.
- initrd: o que um módulo de boot comumente carrega, e por quê.