Como instalar o grub em um arquivo .img?

26

Eu fiz o seguinte:

  1. criou um arquivo .img vazio com dd
  2. associou-o a / dev / loop0 com losetup
  3. criou uma partição nele com o fdisk
  4. formatou essa partição com mke2fs
  5. copiou um sistema GNU / Linux personalizado para essa partição

Agora eu gostaria de tornar o arquivo .img inicializável instalando o grub em seu diretório MBR e / boot. Meu objetivo é carregar o arquivo .img com o qemu. Seria melhor se o grub2 fosse usado em vez do legado do grub.

Obrigado.

Francesco Turco
fonte

Respostas:

24

Esta é a versão 1.98 do grub-pc + 20100804-5ubuntu3 (Maverick Meerkat).

O instalador do grub2 pode ser instalado em dispositivos de loopback, mas se você montar usando o mapeador de dispositivos, ele ficará confuso e acreditará que possui um esquema LVM, falhando misteriosamente com uma reclamação sobre uma abstração ausente.

Em vez disso, você deve configurar o dispositivo de auto-retorno para a partição mesmo, com um nome que deve corresponder ao padrão "/ dev / loop [0-9]", ou seja, sem qualquer designador de partição no final:

kpartx -v -a /dev/loop0
losetup /dev/loop1 /dev/mapper/loop0p1
mount /dev/loop1 /mnt

(Observe que se você deseja que o grub-mkconfig / update-grub opere neste volume, o loopback da partição deve estar conectado ao loopback do disco em / dev e não diretamente ao arquivo de imagem).

Desde que você usou o fdisk para particionar a imagem, você tem uma tabela de partições no estilo msdos (aka label) e inicializa usando um BIOS. Além de colocar o stage1 / boot.img no MBR, o stage1.5 / core.img será colocado em uma área de incorporação no espaço não particionado (!) A seguir, e deve haver espaço para isso.

O truque agora é informar ao instalador do grub2 através de um mapa de dispositivo como sua configuração de loopback será mapeada para as unidades do BIOS na máquina virtual. (No legado do grub1, isso foi feito diretamente no shell). Você provavelmente está planejando inicializar esta imagem como o primeiro disco, então acho que o mapeamento apropriado seria:

mkdir -p /mnt/boot/grub
cat > /mnt/boot/grub/device.map <<EOF
(hd0)   /dev/loop0
(hd0,1) /dev/loop1
EOF

Aqui, coloquei o mapa do dispositivo dentro da imagem do disco convidado, para que você possa gerar o arquivo de configuração de inicialização grub.cfg:

mount --bind /dev /mnt/dev
chroot /mnt grub-mkconfig -o /boot/grub/grub.cfg

(Lembre-se de que o pós-instalador do pacote grub-pc executará um probe que sobrescreve o mapa do dispositivo (!); Portanto, você deverá escrevê-lo após a instalação e executar o grub-mkconfig / update-grub você mesmo).

Agora execute o instalador a partir do host , apontando para a instalação do convidado:

grub-install --no-floppy --grub-mkdevicemap=/mnt/boot/grub/device.map --root-directory=/mnt /dev/loop0

Por fim, desmonte tudo configurado aqui antes de iniciar o qemu na sua imagem:

umount /mnt/dev
umount /mnt
losetup -d /dev/loop1
kpartx -v -d /dev/loop0
RolKau
fonte
Uau! Acabei de encontrar sua resposta enquanto tentava entender por que não consegui atualizar o grub de um arquivo de imagem com chroot em loop de montagem. Vou ver se isso pode se aplicar ao meu problema, mas essa é definitivamente uma faixa interessante e vale muito a pena o meu voto positivo. Obrigado!
filofel
1
Boa resposta, infelizmente chroot /mnt grub-mkconfig -o /boot/grub/grub.cfgfalha porque não existe grub-mkconfigou existe algum binário no disco .img e /mntjá está montado. Seria ótimo se você o seguisse passo a passo e escrevesse todos os detalhes / comandos.
Flavius
@RolKau: obrigado por esta excelente documentação! Juntamente com as modificações do toh abaixo, ele resolveu muitos problemas que tive durante anos com o grub ao incorporar a partir de ambientes chrootados.
Spark9
1
losetup -Pé outra boa maneira de montar uma única partição: stackoverflow.com/a/15200862/895245
Ciro Santilli Última atualização
Estou recebendo: /usr/sbin/grub-probe: warning: the device.map entry 'hd0,1' is invalid. Ignoring it. Please correct or delete your device.map.Portanto, esta resposta é inútil.
Calmarius 15/03
11

muito obrigado por essas explicações. Integrei sua solução em meus próprios scripts com as seguintes modificações (traduzidas para sua notação / variáveis):

modprobe dm_mod
kpartx -va /root/rootfs.img # *.img is setup elsewhere
# normally you now would mount /dev/loop0p1 directly. BUT
# grub specialists didn't manage to work with loop partitions other than /dev/loop[0-9]
losetup -v -f --show /dev/mapper/loop0p1
mount /dev/loop1 /mnt
mkdir -p /mnt/boot/grub

# change into chrooted environment. all remaining work will be done from here. this differs from the howto above.
LANG=C chroot /mnt /bin/bash
set -o vi
mount -t sysfs sysfs /sys
mount -t proc  proc  /proc
# avoid grub asking questions
cat << ! | debconf-set-selections -v
grub2   grub2/linux_cmdline                select   
grub2   grub2/linux_cmdline_default        select   
grub-pc grub-pc/install_devices_empty      select yes
grub-pc grub-pc/install_devices            select   
!
apt-get -y install grub-pc
# don't setup device.map prior to this point. It will be overwritten by grub-pc install
#corrected the /mnt/boot/grub/device.map to /boot/grub/device.map
cat > /boot/grub/device.map << !
(hd0)   /dev/loop0
(hd0,1) /dev/loop1
!
# install here to fill /boot/grub for grub-mkconfig (update-grub)
grub-install /dev/loop0
# generate /boot/grub/grub.cfg
update-grub

isso funciona pelo menos no aperto do debian. Marque '/boot/grub/grub.cfg' para ver se está correto.

toh
fonte
1
Deve cat > /mnt/boot/grub/device.mapser feito no ambiente chroot? Nesse caso, o caminho deve ser /boot/grub/device.map.
Cbliard
0

Aqui está uma rápida explicação sobre como instalar e inicializar o GRUB manualmente em uma imagem de disco do QEMU. Não o levei para a próxima etapa com o grub.cfg, mas presumo que isso seja bastante simples assim que essa configuração principal for concluída.

Suposições:

  • 'grub-install --version' é "grub-install (GRUB) 2.02 ~ beta2-36ubuntu3.2"
  • 'qemu-system-x86_64 --version' é "emulador QEMU versão 2.5.0 (Debian 1: 2.5 + dfsg-5ubuntu10.6), Copyright (c) 2003-2008 Fabrice Bellard"
  • Uma imagem de disco denominada "disk1" no diretório atual
  • / dev / loop0 tem "Tipo de rótulo de disco: dos" (ou seja, com fdisk)
  • / dev / loop0p1 é uma partição inicializável, já formatada com ext4

Foi assim que iniciei o qemu no menu do GRUB:

    # losetup -fP disk1
    # ls /dev/loop0*
    /dev/loop0  /dev/loop0p1  /dev/loop0p2  /dev/loop0p3
    # mount /dev/loop0p1 /mnt
    # cat > loop0device.map <<EOF
    (hd0) /dev/loop0
    EOF
    # grub-install --no-floppy --grub-mkdevicemap=loop0device.map \
    --modules="part_msdos" --boot-directory=/mnt /dev/loop0 -v
    # umount /mnt
    # losetup -d /dev/loop0
    # qemu-system-x86_64 -m 512 -curses -hda disk1 -enable-kvm

Em seguida, o shell do GRUB aparece:

                        GNU GRUB  version 2.02~beta2-36ubuntu3.2

       Minimal BASH-like line editing is supported. For the first word, TAB
       lists possible command completions. Anywhere else TAB lists possible
       device or file completions.


    grub> ls
    (hd0) (hd0,msdos3) (hd0,msdos2) (hd0,msdos1) (fd0)
    grub>

Se você copiou um kernel e um disco ram para / dev / loop0p1, você pode inicializá-lo:

    grub> linux (hd0,msdos1)/vmlinuz
    grub> initrd (hd0,msdos1)/initrd
    grub> boot

E aqui está o shell padrão do Linux (porque nenhum / sbin / init estava disponível neste caso)

    BusyBox v1.22.1 (Ubuntu 1:1.22.0-15ubuntu1) built-in shell (ash)
    Enter 'help' for a list of built-in commands.

    (initramfs)
Beau Harder
fonte