Como inicializar o carregamento do kernel usando o carregador EFI stub (efistub)?

14

Eu tenho o Ubuntu 14.04 em execução no modo UEFI como único sistema operacional, sem inicialização dupla aqui. A versão do kernel é 3.13.0-24-genérica. Existe uma partição EFI. Nesse caso, a partição EFI não está no padrão, /dev/sda1mas /dev/sda3porque eu realmente converti o modo BIOS para o modo EFI . Eu usei o grub-efi-amd64pacote, embora isso realmente carregue o menu de inicialização do GRUB no menu de inicialização do firmware UEFI (cargas de inicialização UEFI \EFI\ubuntu\grubx64.efi).

Quero pular essa etapa de carregamento do menu de inicialização dupla e inicializar mais rapidamente, diretamente da UEFI no kernel. Os kernels do Ubuntu desde a 12.10 têm o recurso "Kernel EFI stub loader" .

Eu sei que preciso copiar o kernel do Ubuntu para a partição EFI (possivelmente renomear) e criar uma entrada no menu de inicialização UEFI (por exemplo, usando efibootmgr). Quais comandos exatos do terminal são necessários para fazer isso?

Pro Backup
fonte

Respostas:

14

Os comandos abaixo são mais genéricos do que apenas para a versão 3.13.0-35 do kernel.

1. Monte a partição efi e copie os arquivos do kernel lá

$ mount /dev/sda3 /boot/efi

$ mkdir -pv /boot/efi/EFI/ubuntu/

$ cp -uv /boot/vmlinuz-* /boot/initrd.img-* /boot/efi/EFI/ubuntu/
'/boot/vmlinuz-3.13.0-35-generic' -> '/boot/efi/EFI/ubuntu/vmlinuz-3.13.0-35-generic'
'/boot/initrd.img-3.13.0-35-generic' -> '/boot/efi/EFI/ubuntu/initrd.img-3.13.0-35-generic'

2. Altere o nome do arquivo do kernel

Reduza o nome do arquivo do kernel removendo -genericporque parece haver um limite de caminho de 39 caracteres e renomear o (s) arquivo (s) do kernel para terminar .efi, isso garante compatibilidade com a maioria dos sistemas

$ for f in /boot/efi/EFI/ubuntu/vmlinuz-*-generic; do mv -uv -- "$f" "${f//-generic/}.efi"; done
'/boot/efi/EFI/ubuntu/vmlinuz-3.13.0-35-generic' -> '/boot/efi/EFI/ubuntu/vmlinuz-3.13.0-35-generic.efi'`

O encurtamento do nome do arquivo do kernel do nome acima não é suficiente para um kernel da linha principaldpkg instalado , porque, por exemplo, sem ainda tem 40 caracteres./EFI/ubuntu/vmlinuz-3.16.0-031600rc6.efi-generic

3. Adicione uma nova entrada ao menu de inicialização EFI

Substitua 3.13.0-35neste exemplo pela sua versão específica do kernel

$ kv=3.13.0-35;efibootmgr -c -p 3 -L $kv -l \EFI\ubuntu\vmlinuz-$kv.efi -u root=/dev/sda1 initrd=\\EFI\\ubuntu\\initrd.img-$kv-generic ro rootfstype=ext4 debug ignore_loglevel libata.force=dump_id crashkernel=384M-:128M

Essa nova entrada do menu de inicialização se tornará sua nova opção de inicialização padrão.

Você pode não precisar os parâmetros de depuração extras debug, ignore_loglevel, libata.force=dump_ide crashkernel=384M-:128M. Initrddeve estar presente, caso contrário, a inicialização trava em " Switched to clocksource tsc. " porque o dispositivo raiz sda1 não pode ser aberto.

Pro Backup
fonte
Eu não sei como você descobriu isso, mas você é incrível. Surpreendentemente, existem poucos documentos sobre esse recurso interessante.
user3549648
No caso, não está funcionando para você tentar colocar argumentos de -le -uentre aspas duplas (ou escapar barra invertida manualmente). Você pode testar se esse é o problema executando efibootmgr -vapós adicionar uma nova entrada ao menu de inicialização EFI. Além disso, no caso de sua máquina tem mais de discos (dizem que um SSD e um HDD), então você precisará especificar um por -dcujo padrão é /dev/sda(ver man efibootmgr)
Peeyush Kushwaha
5

De acordo com o wiki Debian , isso pode ser feito em algumas etapas simples que sobreviverão a uma atualização do kernel .

Nota: isso pressupõe que você tenha uma partição EFI montada em /boot/efi.

  1. Crie /etc/kernel/postinst.d/zz-update-efistubcom o seguinte conteúdo:

    #!/bin/sh
    cp /vmlinuz /initrd.img /boot/efi/EFI/ubuntu/
    

    Este é um gancho que será executado na atualização do kernel para copiar a imagem mais recente do kernel e o initrd no local apropriado. Em seguida, torne-o executável e execute-o:

    sudo chmod +x /etc/kernel/postinst.d/zz-update-efistub
    sudo /etc/kernel/postinst.d/zz-update-efistub
    
  2. Adicione a entrada de inicialização:

    sudo efibootmgr -c -d /dev/sdb -p 1 -L "Ubuntu (efistub)" -l /EFI/ubuntu/vmlinuz -u "root=/dev/sdb2 rw initrd=/EFI/ubuntu/initrd.img quiet splash"
    

    Não se esqueça de alterar os argumentos -de, -pdependendo de onde está sua partição do sistema EFI. No meu caso, é / dev / sdb1, mas é provável que seja diferente para você. Você provavelmente também precisará alterar o root=valor no cmdline do kernel para sua partição raiz.

    (Você pode alterar o rótulo para o que quiser, alterando o -Lparâmetro.)

    A entrada de inicialização que você acabou de adicionar se tornará a entrada padrão. E não será interrompido após uma atualização do kernel, pois o gancho garantirá vmlinuze initrd.imgserá sempre atualizado.

Léo Lam
fonte
Qualquer maneira de obtê-lo para trabalhar com inicialização segura, uma vez no meu laptop HP quando eu tento isso, ele dá um erro seguro boot (é claro que eu posso desativar inicialização segura também)
Suici Doga
Parece que você precisaria usar o cryptboot e algumas ferramentas para assinar o kernel primeiro . É um pouco complicado, especialmente se você não estiver usando o Arch (como não há ferramenta pronta para usar), então eu desativaria a inicialização segura.
Léo Lam
Que tal copiar o kernel .signed?
Suici Doga