Настройка GRUB для загрузки в QEMU

Вопрос или проблема

У меня есть образ Debian, созданный с помощью следующих команд:

qemu-img create -f qcow2 disk.qcow2 16G

su

export PATH=$PATH:/sbin:/usr/sbin
export TERM=xterm

modprobe nbd
qemu-nbd --connect=/dev/nbd0 disk.qcow2 --cache=unsafe --discard=unmap
parted --align optimal --script --machine --fix /dev/nbd0 -- \
       mklabel gpt \
       mkpart efi fat32 '0%' 500MiB \
       set 1 boot on \
       mkpart swap linux-swap 500MiB 1GiB \
       mkpart root ext4 1GiB '100%'
mkfs.vfat -F 32 /dev/nbd0p1
mkswap /dev/nbd0p2
mkfs.ext4 /dev/nbd0p3

mkdir -p disk
mount /dev/nbd0p3 disk

debootstrap --arch amd64 bullseye ./disk
mkdir -p ./disk/boot/efi
mount /dev/nbd0p1 ./disk/boot/efi
mount --bind /dev ./disk/dev
mount -t devpts /dev/pts ./disk/dev/pts
mount -t proc proc ./disk/proc
mount -t sysfs sysfs ./disk/sys
mount -t tmpfs tmpfs ./disk/tmp

chroot ./disk

echo -e 'password\npassword' | passwd

echo debian > /etc/hostname

UUID1=$(blkid /dev/nbd0p1 | grep -Eo ' UUID="[^ ]*"' | sed 's/[" ]//g')
UUID2=$(blkid /dev/nbd0p2 | grep -Eo ' UUID="[^ ]*"' | sed 's/[" ]//g')
UUID3=$(blkid /dev/nbd0p3 | grep -Eo ' UUID="[^ ]*"' | sed 's/[" ]//g')
echo "none /tmp tmpfs defaults 0 0" > /etc/fstab
echo "$UUID1 /boot/efi vfat defaults 0 2" >> /etc/fstab
echo "$UUID2 none swap sw 0 0" >> /etc/fstab
echo "$UUID3 / ext4 errors=remount-ro 0 1" >> /etc/fstab

cat > /etc/apt/sources.list << __EOF__
deb http://deb.debian.org/debian/ bullseye main
deb-src http://deb.debian.org/debian/ bullseye main
deb http://deb.debian.org/debian/ bullseye-updates main
deb-src http://mirror.mephi.ru/debian/ bullseye-updates main
deb http://deb.debian.org/debian-security/ bullseye-security main
deb-src http://deb.debian.org/debian-security/ bullseye-security main
__EOF__

export DEBIAN_FRONTEND=noninteractive
export LANG="C.UTF-8"
apt-get update
apt-get upgrade

systemctl enable [email protected]
systemctl enable systemd-networkd.service

cat > /etc/systemd/network/80-dhcp.network << __EOF__
[Match]
Name=en*
[Network]
DHCP=yes
__EOF__

apt-get install -y linux-image-5.10.0-8-amd64 grub-efi
apt-get clean
apt-get autoclean
rm -rf /var/lib/apt/lists/*

grub-install --target=x86_64-efi --efi-directory=/boot/efi --bootloader-id=debian --recheck --no-nvram /dev/nbd0

echo 'GRUB_DISABLE_OS_PROBER=true' >> /etc/default/grub
update-grub2

exit

for dev in tmp sys proc dev/pts dev boot/efi; do
    umount ./disk/$dev
done

umount disk
rmdir disk
qemu-nbd --disconnect /dev/nbd0

exit

Я могу успешно запускать этот образ, когда копирую ядро и initrd изображение с диска и запускаю их напрямую с помощью команды

qemu-system-x86_64 \
    -drive format=qcow2,file=disk.qcow2 \
    -kernel vmlinuz \
    -initrd initrd.img \
    -cpu host -M q35  \
    -enable-kvm \
    -m 2G,maxmem=4G \
    -device rtl8139,netdev=network0 \
    -netdev user,id=network0 \
    -append "root=/dev/sda3"

Но когда я пытаюсь запустить этот диск, используя GRUB с SeaBIOS (стандартный BIOS QEMU) с командой

qemu-system-x86_64 \
    -drive format=qcow2,file=disk.qcow2 \
    -boot c  \
    -cpu host -M q35  \
    -enable-kvm \
    -m 2G,maxmem=4G \
    -device rtl8139,netdev=network0 \
    -netdev user,id=network0

он зависает на строке Booting from Hard Disk....

При использовании OVMF EFI с командой

qemu-system-x86_64 \
    -drive format=qcow2,file=disk.qcow2 \
    -boot c  \
    -bios /usr/share/ovmf/OVMF.fd \
    -cpu host -M q35  \
    -enable-kvm \
    -m 2G,maxmem=4G \
    -device rtl8139,netdev=network0 \
    -netdev user,id=network0

Я получаю ошибки:

BdsDxe: не удалось загрузить Boot0001 "UEFI QEMU DVD-ROM QM00005 " из PciRoot(0x0)/Pci(0x1F,0x2)/Sata(0x2,0xFFFF,0x0): Не найдено
BdsDxe: не удалось загрузить Boot0002 "UEFI QEMU HARDDISK QM00001 " из PciRoot(0x0)/Pci(0x1F,0x2)/Sata(0x0,0xFFFF,0x0): Не найдено

Как сделать так, чтобы мой диск загружался с GRUB?

Мне не удалось заставить UEFI версию работать, но установка BIOS работала нормально.

Вот полный код для получения debootstrapped Debian, который можно загрузить из QEMU:

qemu-img create -f qcow2 disk.qcow2 16G

su

export PATH=$PATH:/sbin:/usr/sbin
export TERM=xterm

modprobe nbd
qemu-nbd --connect=/dev/nbd0 disk.qcow2 --cache=unsafe --discard=unmap
parted --align optimal --script --machine --fix /dev/nbd0 -- \
       mklabel gpt \
       mkpart fat32 '0%' 2MiB \
       set 1 bios_grub on \
       mkpart swap linux-swap 2MiB 1GiB \
       mkpart root ext4 1GiB '100%'
mkswap /dev/nbd0p2
mkfs.ext4 /dev/nbd0p3

mkdir -p disk
mount /dev/nbd0p3 disk

debootstrap --include=systemd-sysv --variant=minbase --arch amd64 bullseye ./disk

mount --bind /dev ./disk/dev
mount -t devpts /dev/pts ./disk/dev/pts
mount -t proc proc ./disk/proc
mount -t sysfs sysfs ./disk/sys
mount -t tmpfs tmpfs ./disk/tmp

chroot ./disk

echo -e 'password\npassword' | passwd
echo debian > /etc/hostname

UUID1=$(blkid /dev/nbd0p2 | grep -Eo ' UUID="[^ ]*"' | sed 's/[" ]//g')
UUID2=$(blkid /dev/nbd0p3 | grep -Eo ' UUID="[^ ]*"' | sed 's/[" ]//g')
echo "none /tmp tmpfs defaults 0 0" > /etc/fstab
echo "$UUID1 none swap sw 0 0" >> /etc/fstab
echo "$UUID2 / ext4 errors=remount-ro 0 1" >> /etc/fstab

cat > /etc/apt/sources.list << __EOF__
deb http://deb.debian.org/debian/ bullseye main
deb-src http://deb.debian.org/debian/ bullseye main
deb http://deb.debian.org/debian/ bullseye-updates main
deb-src http://deb.debian.org/debian/ bullseye-updates main
deb http://deb.debian.org/debian-security/ bullseye-security main
deb-src http://deb.debian.org/debian-security/ bullseye-security main
__EOF__

export DEBIAN_FRONTEND=noninteractive
export LANG="C.UTF-8"
apt-get update
apt-get upgrade -y

systemctl enable [email protected]
systemctl enable systemd-networkd.service

cat > /etc/systemd/network/80-dhcp.network << __EOF__
[Match]
Name=en*
[Network]
DHCP=yes
__EOF__

apt-get install -y linux-image-5.10.0-8-amd64 grub2
apt-get clean
apt-get autoclean
rm -rf /var/lib/apt/lists/*

echo 'GRUB_DISABLE_OS_PROBER=true' >> /etc/default/grub
grub-install --target=i386-pc --recheck /dev/nbd0
update-grub2

exit

for dev in tmp sys proc dev/pts dev; do
    umount ./disk/$dev
done

umount disk

rmdir disk
qemu-nbd --disconnect /dev/nbd0

exit

qemu-system-x86_64 \
     -drive format=qcow2,file=disk.qcow2 \
     -boot c  \
     -cpu host -M q35  \
     -enable-kvm \
     -m 2G,maxmem=4G \
     -device rtl8139,netdev=network0 \
     -netdev user,id=network0

Ответ или решение

Конфигурация загрузчика GRUB для загрузки в QEMU может быть сложным процессом, особенно когда речь идет о различных вариантах BIOS или UEFI. В описанной вами ситуации, прежде всего, нужно разобраться в причинах, почему текущая конфигурация запуска операционной системы не работает, и изменить ее в соответствии с потребностями.

Теория

GRUB (GRand Unified Bootloader) — это многозадачный загрузчик, который используется для запуска различных операционных систем. В контексте виртуальных машин QEMU, GRUB выполняет важную функцию загрузки гостевой операционной системы с правильной конфигурацией загрузочного диска.

QEMU поддерживает два основных типа BIOS: традиционный SeaBIOS и OVMF UEFI. Каждый из них имеет свой собственный подход к конфигурации загрузочного процессора, и различия в их настройках могут потребовать различных манипуляций с загрузчиком GRUB и структурой разделов диска.

Пример

В вашем случае, вы сталкиваетесь с проблемами загрузки как в среде SeaBIOS, так и с UEFI OVMF. Проблема может заключаться в ряде факторов, включая неправильную установку GRUB или некорректную конфигурацию таблицы разделов.

Ваш текущий процесс подразумевает создание образа диска через qemu-img, разделение диска с использованием parted, и последующую установку Debian через debootstrap. Основные моменты, на которые следует обратить внимание:

  1. Конфигурация таблицы разделов:

    • Для SeaBIOS требуется наличие раздела BIOS Boot (BIOS_GRUB), что вы учли во второй реализации, когда перешли от GPT с EFI к традиционной схеме с BIOS_GRUB.
  2. Установка и настройка GRUB:

    • SeaBIOS: Должен использовать grub-install --target=i386-pc для установки загрузчика в MBR диска, как у вас и указано.
    • UEFI OVMF: Требуют наличия EFI System Partition (ESP) и использования grub-install --target=x86_64-efi. В вашей первой попытке это предусматривалось, но, вероятно, возникали ошибки при настройке ESP.
  3. Параметры QEMU:

    • Для BIOS загрузки: Убедитесь, что -boot c действительно соответствует первичному загрузочному устройству.
    • Для UEFI загрузки: Убедитесь, что предоставляется правильный файл прошивки OVMF и правильно настроен стартовый порядок загрузки.

Применение

Для устранения проблем с запуском в SeaBIOS, необходимо убедиться, что вы использовали таблицу разделов с меткой BIOS_GRUB и установкой GRUB в MBR. Это означает, что на этапе parted в вашем скрипте необходимо было создать раздел исключительно под boios_grub:

parted --align optimal --script --machine --fix /dev/nbd0 -- \
       mklabel gpt \
       mkpart fat32 '0%' 2MiB \
       set 1 bios_grub on \
       mkpart swap linux-swap 2MiB 1GiB \
       mkpart root ext4 1GiB '100%'

При запуске с UEFI OVMF, необходимо убедиться в правильности использования grub-install --target=x86_64-efi. Возможно, возникла проблема с неверной настройкой раздела EFI или его монтированием при конфигурации GRUB. Использовав команду:

grub-install --target=x86_64-efi --efi-directory=/boot/efi --bootloader-id=debian --recheck --no-nvram /dev/nbd0

Убедитесь, что update-grub2 корректно генерирует конфигурационные файлы для UEFI.

Заключение

Настройка GRUB в виртуальной среде требует тщательного подхода с учетом особенностей BIOS и UEFI. Ваша проблема, вероятно, связана с некорректным распределением загрузочных разделов и неверной установкой GRUB. Рекомендую удостовериться, что вы используете схемы разделов, соответствующие типу BIOS, и внимательно следить за выводами команд grub-install и update-grub2, анализируя их на наличие потенциальных ошибок.

Сложности с UEFI OVMF зачастую связаны с неверным порядком загрузки или отсутствием нужного доступа к ESP, что требует внимательной проверки всех этапов установки и их корректной реализации.

Оцените материал
Добавить комментарий

Капча загружается...