Não tenho certeza se esta pergunta deve ser feita aqui ou no estouro de pilha, mas estou escrevendo um aplicativo UEFI para inicializar um kernel personalizado. Posso testar o aplicativo UEFI no QEMU e usar o GDB para depurar e examinar a memória. Também posso fazer algumas coisas básicas, como localizar protocolos, imprimir e limpar a tela.
Minha pergunta é qual é o processo típico de inicialização de um kernel a partir de um aplicativo UEFI? O aplicativo UEFI precisa ler o sistema de arquivos para encontrar o kernel?
A maioria dos exemplos de aplicativos UEFI que encontro online são aplicativos hello world. Encontrei um exemplo simples que inicializa um kernel, mas não entendo como o aplicativo UEFI encontra o kernel. Eu também não entendo a cópia da memória.
https://devcodef1.com/news/1304006/custom-kernel-uefi-boot-with-qemu
Também encontrei alguns exemplos mais complexos, mas ainda estou um pouco confuso. https://gitlab.com/bztsrc/bootboot/-/blob/master/x86_64-efi/bootboot.c https://github.com/KunYi/Simple-UEFI-Bootloader/blob/master/Simple_UEFI_Bootloader/src/Loader .c#L2771
O artigo com exemplo que você encontrou parece gerado por IA – se fosse escrito por uma pessoa real, certamente ela teria olhado sua própria postagem pelo menos uma vez e corrigido o HTML quebrado de #includes. (Algumas de suas outras postagens fazem referência direta a comandos e opções que não existem e nunca existiram.)
Não há processo fixo. O programa UEFI faz tudo o que precisa, carrega na memória tudo o que precisa ser carregado da maneira que desejar e, eventualmente, chama ExitBootServices() e salta para o ponto de entrada do kernel. Provavelmente a única constante é obter o mapa de memória da EFI.
O programa pode usar o protocolo de acesso ao sistema de arquivos EFI para carregar um arquivo separado na memória (por exemplo, usando Open/Read/Close comum), ou também pode usar o protocolo de acesso a dispositivos de bloco EFI para implementar seus próprios drivers de sistema de arquivos (por exemplo, GRUB2 faz isso ), ou pode ser o próprio kernel (o Linux faz isso com seu recurso "EFI stub").
Dando uma olhada no Linux:
O antigo gerenciador de inicialização efilinux para Linux é bastante simples - fs/fs.c usa o "File System Protocol" EFI para ler seu arquivo de configuração e carregar a imagem do kernel Linux do sistema de arquivos (bem como o arquivo initrd que será entregue para Linux), então loaders/bzimage/bzimage.c prepara uma estrutura com alguns parâmetros iniciais para entregar ao kernel, então chama ExitBootServices e salta (via loaders/bzimage/x86_64.h) para um ponteiro de memória.
GRUB2 usa alguns serviços EFI, mas também depende muito do acesso direto ao dispositivo; ele vem com suporte interno para vários sistemas de arquivos e até tipos de hardware (por exemplo, possui suporte interno para SATA). A configuração inicial está incorporada no grub.efi e aponta para o caminho do grub.cfg, que inclui o caminho para o kernel.
systemd-boot não carrega nenhum kernel; ele espera que o kernel inclua um "stub EFI" para que possa ser lançado como um executável EFI (ou seja, o kernel sendo seu próprio gerenciador de inicialização). O stub EFI do kernel já possui o resto do kernel na memória, portanto não precisa de nenhum acesso ao sistema de arquivos.