¿Cómo instalar grub en un archivo .img?

26

Hice lo siguiente:

  1. creó un archivo .img vacío con dd
  2. lo asoció a / dev / loop0 con losetup
  3. creó una partición con fdisk
  4. formateó dicha partición con mke2fs
  5. Copió un sistema GNU / Linux personalizado en esa partición

Ahora me gustaría hacer que el archivo .img sea de arranque instalando grub en su directorio MBR y / boot. Mi objetivo es cargar el archivo .img con qemu. Sería mejor si se usa grub2 en lugar de grub legacy.

Gracias.

Francesco Turco
fuente
unix.stackexchange.com/questions/163791/…
Ciro Santilli 新疆 改造 中心 法轮功 六四 事件

Respuestas:

24

Esto es con grub-pc versión 1.98 + 20100804-5ubuntu3 (Maverick Meerkat).

El instalador de grub2 puede instalarse en dispositivos de bucle invertido, pero si monta usando el mapeador de dispositivos, se confundirá y creerá que tiene un esquema LVM, fallando misteriosamente con una queja sobre una abstracción faltante.

En su lugar, debe configurar el dispositivo loopback para la partición usted mismo, con un nombre que debe coincidir con el patrón "/ dev / loop [0-9]", es decir, sin ningún designador de partición al final:

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

(Tenga en cuenta que si desea que grub-mkconfig / update-grub funcione en este volumen, entonces el loopback de la partición debe estar conectado al loopback del disco en / dev, y no directamente al archivo de imagen).

Como usó fdisk para particionar la imagen, tiene una tabla de partición de estilo msdos (también conocida como etiqueta) y arranca usando un BIOS. Además de poner el stage1 / boot.img en el MBR, el stage1.5 / core.img se colocará en un área de incrustación en un espacio no particionado (!) Siguiendo inmediatamente después, y debe haber espacio para esto.

El truco ahora es decirle al instalador grub2 a través de un mapa de dispositivos cómo su configuración de bucle invertido se asignará a las unidades de BIOS en la máquina virtual. (En el legado de grub1 esto se hizo directamente en el shell). Probablemente esté planeando arrancar esta imagen como el primer disco, por lo que supongo que la asignación adecuada sería:

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

Aquí he puesto el mapa del dispositivo dentro de la imagen del disco invitado, para que pueda generar el archivo de configuración de arranque grub.cfg:

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

(Tenga en cuenta que el post-instalador del paquete grub-pc ejecutará una sonda que sobrescribe el mapa del dispositivo (!), Por lo que tendrá que escribirlo después de la instalación y ejecutar grub-mkconfig / update-grub usted mismo).

Ahora ejecute el instalador desde el host , señalando la instalación del invitado:

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

Finalmente, desmonte todo lo configurado aquí antes de iniciar qemu en su imagen:

umount /mnt/dev
umount /mnt
losetup -d /dev/loop1
kpartx -v -d /dev/loop0
RolKau
fuente
¡Guauu! Acabo de encontrarme con su respuesta mientras intentaba entender por qué no podía actualizar-arrancar un archivo de imagen en bucle montado en bucle. Veré si esto puede aplicarse a mi problema, pero definitivamente es una pista interesante y vale la pena mi voto positivo. ¡Gracias!
filofel
1
Buena respuesta, desafortunadamente chroot /mnt grub-mkconfig -o /boot/grub/grub.cfgfalla porque no hay grub-mkconfigningún binario para ese asunto en el disco .img, y /mntya está montado. Sería genial si lo tomaras paso a paso y escribieras todos los detalles / comandos.
Flavio
@RolKau: ¡gracias por esta excelente documentación! Junto con las modificaciones de toh a continuación, resolvió muchos problemas que tuve durante años con grub al incrustar desde entornos con chroot.
sparkie
1
losetup -Pes otra buena manera de montar una sola partición: stackoverflow.com/a/15200862/895245
Ciro Santilli 新疆 改造 中心 法轮功 六四 事件
Estoy obteniendo: /usr/sbin/grub-probe: warning: the device.map entry 'hd0,1' is invalid. Ignoring it. Please correct or delete your device.map.Entonces esta respuesta es inútil.
Calmarius
11

Muchas gracias por estas explicaciones. Integre su solución en mis propios scripts con las siguientes modificaciones (traducidas a su notación / variables):

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

Esto funciona al menos en Debian Squeeze. Verifique '/boot/grub/grub.cfg' para ver si es correcto.

toh
fuente
1
¿Debería cat > /mnt/boot/grub/device.maphacerse en el entorno chrooteado? Si es así, el camino debería ser /boot/grub/device.map.
cbliard
0

Aquí hay un tutorial rápido sobre cómo instalar e iniciar GRUB manualmente en una imagen de disco QEMU. No lo he llevado al siguiente paso con un grub.cfg, pero supongo que es bastante sencillo una vez que se completa esta configuración principal.

Suposiciones

  • 'grub-install --version' es "grub-install (GRUB) 2.02 ~ beta2-36ubuntu3.2"
  • 'qemu-system-x86_64 --version' es "QEMU emulator versión 2.5.0 (Debian 1: 2.5 + dfsg-5ubuntu10.6), Copyright (c) 2003-2008 Fabrice Bellard"
  • Una imagen de disco llamada "disk1" en el directorio actual
  • / dev / loop0 tiene "Tipo de etiqueta de disco: dos" (es decir, con fdisk)
  • / dev / loop0p1 es una partición de arranque, ya formateada con ext4

Así es como inicié qemu en el menú de 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

Entonces aparece el shell GRUB:

                        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>

Si hubiera copiado un núcleo y un disco RAM en / dev / loop0p1, podría arrancarlo:

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

Y aquí está el shell predeterminado de Linux (porque no / sbin / init estaba disponible en este 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
fuente