Как загрузить EFI-ядро с помощью QEMU (kvm)?

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

Я пытаюсь эмулировать среду EFI с помощью QEMU (kvm); virtualbox загружается в режим EFI за 15 минут, используя archboot.

В режиме традиционного BIOS я могу загрузиться, используя эту команду:

root@citsnmaiko-deb:/home/maiko/uefi/ovmf# qemu-system-x86_64 -kernel  ../bzImage -initrd ../rootfs.gz -append "rw root=/dev/ram0  ramdisk_size=40960"

и это работает с моим пользовательским ядром и файловой системой.

file ../bzImage 
../bzImage: Linux kernel x86 boot executable bzImage, version 3.6.1 (root@citsnmaiko-deb) #4, RO-rootFS, swap_dev 0x3, Normal VGA

он также поддерживает EFI.

Я пытаюсь сделать то же самое с EFI файлами, которые скачал отсюда:

wget http://ufpr.dl.sourceforge.net/project/edk2/OVMF/OVMF-X64-r11337-alpha.zip -P ovmf
cd ovmf/
unzip -x OVMF-X64-r11337-alpha.zip
# переименовать файлы для QEMU
mv OVMF.fd bios.bin
mv CirrusLogic5446.rom vgabios-cirrus.bin
# запустить QEMU
root@citsnmaiko-deb:/home/maiko/uefi/ovmf# qemu-system-x86_64 -L .  -kernel  ../bzImage -initrd ../rootfs.gz -append "rw root=/dev/ram0  ramdisk_size=40960" 
Не удалось открыть опцию rom 'linuxboot.bin': Нет такого файла или каталога
pci_add_option_rom: не удалось найти romfile "pxe-e1000.bin"

И я попадаю в оболочку EFI, не имея возможности загрузиться.

QEMU + EFI + LINUX KERNEL + SHELL

Если я использую последнюю версию Ubuntu, используя ту же среду EFI:

root@citsnmaiko-deb:/home/maiko/uefi/ovmf# qemu-system-x86_64 -L . -boot d -cdrom ../ubuntu-12.10-desktop-amd64.iso
pci_add_option_rom: не удалось найти romfile "pxe-e1000.bin"

… процесс загрузки работает нормально.

введите описание изображения здесь

Я пытался заменить файлы загрузки Ubuntu на свои, но, возможно, я не полностью понимаю их функциональность. Когда я просто заменяю файлы после монтирования ISO:

mkdir tmp
bsdtar xf ubuntu-12.10-desktop-amd64.iso -C tmp
cp bzImage tmp/casper/vmlinuz
cp rootfs.gz tmp/casper/initrd.lz 
genisoimage -o customUbuntu.iso tmp/
qemu-system-x86_64 -L . -boot d -cdrom customUbuntu.iso 

появляется та же оболочка EFI. Это нормально? initrd.lz и rootfs.gz можно использовать взаимозаменяемо, верно? Как насчет bzImage и vmlinuz?

Что я упускаю?

OVMF поддерживает -boot с r13683, и поддерживает -kernel -append -initrd с r13923.

  1. Скачать OVMF-0.1+r14071-1.1.x86_64.rpm или более новую версию.
  2. Извлечь bios.bin из rpm: rpm2cpio OVMF-0.1+r14071-1.1.x86_64.rpm | cpio -idmv
  3. Указать параметр прошивки для QEMU: qemu-kvm -bios ./usr/share/qemu-ovmf/bios/bios.bin -m 1G -cdrom boot.iso (протестировано с boot.iso от Fedora, созданным с особыми мерами)

Я также протестировал qemu -kernel -append -initrd с ядрами 3.5, 3.6 и 3.8.


EFI прошивка имеет требования к формату и иерархии файлов для образа ISO, чтобы он был загрузочным (1), и другие требования для дисков. Ваш измененный образ ISO, вероятно, не соответствовал требованиям, поэтому прошивка его не распознала. EFI прошивка также имеет требования к формату для исполняемого бинарного файла, поэтому ваш bzImage или любой другой образ ядра необходимо собрать с EFISTUB.

Вы можете загрузить ядро из оболочки EFI с ручным указанием параметров. Примеры: 2. Вы можете создать startup.nsh, чтобы немного сократить ввод. Вы можете использовать загрузчики для более полного управления. Вам нужно научиться этому: 2

EFI прошивка сохраняет параметры загрузки в NVRAM. В данный момент QEMU не сохраняет NVRAM, поэтому параметры загрузки теряются при закрытии QEMU. Без параметров загрузки прошивка пытается найти \EFI\BOOT\BOOTX64.EFI для выполнения, но он не здесь, поэтому она не знает, что загружать, и оставляет управление вам. Что вам нужно сделать, чтобы загрузить ядро в оболочке EFI, это просто войти в файловую систему, перейти к нужному пути и выполнить бинарный файл.

fs0:
    cd EFI\fedora
    grub.efi

или

vmlinuz.efi ...

OVMF поддерживает virtio-scsi с EDK2 r13867.

На последнем Ubuntu 20.04:

sudo qemu-system-x86_64 -enable-kvm -bios /usr/share/ovmf/OVMF.fd -hda myimage.raw 

На более ранних версиях Ubuntu и, возможно, других Linux:

cd ~
git clone git://github.com/tianocore/edk2.git
cd edk2
git submodule init
git submodule update --depth=1
make -C BaseTools
. edksetup.sh
vi Conf/target.txt
  ACTIVE_PLATFORM       = MdeModulePkg/MdeModulePkg.dsc 
  TOOL_CHAIN_TAG        = GCC5  # или GCC49 GCC48 ... проверьте ./Conf/tools_def.txt
  TARGET_ARCH           = X64
build
vi Conf/target.txt
  ACTIVE_PLATFORM       = OvmfPkg/OvmfPkgX64.dsc
build
sudo qemu-system-x86_64 -enable-kvm -bios ./Build/OvmfX64/RELEASE_GCC5/FV/OVMF.fd -hda myimage.raw 

Инструкции адаптированы из https://wiki.ubuntu.com/UEFI/OVMF и https://wiki.ubuntu.com/UEFI/EDK2 и протестированы на Ubuntu 20.04 на момент этой публикации.

Используя этот скрипт, перейдите в дерево исходного кода ядра и запустите:

runlinux -- -bios ~/path/to/OVMF.fd

где OVMF.fd был извлечен из https://sourceforge.net/projects/edk2/files/OVMF/OVMF-X64-r15214.zip/download

Скрипт генерирует минимальную файловую систему с BusyBox, компилирует ядро и запускает его в QEMU с:

qemu-system-x86_64 -enable-kvm -kernel bzImage \
                   -initrd ../rootfs.gz -bios ~/path/to/OVMF.fd

Теперь мы можем проверить, что UEFI использовался изнутри QEMU как упоминалось в этом посте:

ls /sys/firmware/efi

Не прямой ответ, но так как никаких нет, вам может быть интересно это сообщение об ошибке xorriso — я собираюсь прокомментировать это тоже, но вкратце, xorriso-1.2.4 с упряженной редакцией 1044 работает отлично для меня и моего оборудования с точно этим скриптом (это русскоязычная википедия, но часть со скриптом должна быть читабельной; обратите внимание на efiboot.img).

Обратите внимание, что /usr/lib/syslinux/isohdpfx.bin поступает из syslinux, и похоже, что последняя 4.06 имеет соответствующие изменения в области EFI.

Вот еще один источник полезных знаний о (U)EFI, и спасибо за скрипт в вопросе тоже 🙂

В моем случае, для aarch64 архитектуры, эта ссылка на Ubuntu помогла.

В частности, нижеуказанный код:

truncate -s 64m varstore.img
truncate -s 64m efi.img
dd if=/usr/share/qemu-efi-aarch64/QEMU_EFI.fd of=efi.img conv=notrunc

Затем, используя эти varstore.img и efi.img в качестве параметров qemu

qemu-system-aarch64
 <параметры qemu...>
 -drive if=pflash,format=raw,file=efi.img,readonly=on \
 -drive if=pflash,format=raw,file=varstore.img

Я не указывал никакой аргумент -boot, он загрузился с задержкой через несколько секунд – но процесс загрузки EFI сработал для меня.

Я надеюсь, что это будет похоже и для других архитектур, включая x86_64, но я не пробовал это; документировал свой опыт здесь, на случай если это поможет кому-то, кто наткнется на этот пост, как и я.

qemu-system-x86_64  -kernel xxx.elf -serial /dev/stdout -monitor stdio

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

Для загрузки ядра EFI с использованием QEMU (kvm) вам необходимо выполнить следующие шаги. Эти инструкции помогут вам настроить вашу виртуальную машину и успешно загрузить ваше пользовательское ядро с поддержкой EFI.

Шаг 1: Установка необходимых пакетов

Убедитесь, что у вас установлены необходимые пакеты для QEMU и UEFI. На Ubuntu используйте:

sudo apt update
sudo apt install qemu qemu-system-x86 ovmf

Шаг 2: Подготовка файлов

  1. Убедитесь, что у вас есть ядро с поддержкой EFI. Если вы используете bzImage, убедитесь, что оно собранно с поддержкой EFI (CONFIG_EFI_STUB=y).
  2. Если у вас есть rootfs.gz, убедитесь, что он также правильно подготовлен для использования в вашей виртуальной машине.

Шаг 3: Запуск QEMU с поддержкой UEFI

Используйте следующую команду для запуска QEMU с поддержкой UEFI:

qemu-system-x86_64 -enable-kvm -bios /usr/share/ovmf/OVMF.fd -kernel ../bzImage -initrd ../rootfs.gz -append "rw root=/dev/ram0 ramdisk_size=40960"

Объяснение параметров:

  • -enable-kvm: Включает аппаратную виртуализацию (KVM).
  • -bios /usr/share/ovmf/OVMF.fd: Указывает путь к файлу прошивки OVMF, который обеспечивает UEFI.
  • -kernel ../bzImage: Указывает путь к вашему ядру.
  • -initrd ../rootfs.gz: Указывает путь к вашему образу initrd.
  • -append "rw root=/dev/ram0 ramdisk_size=40960": Передает параметры ядру.

Решение проблем

Если вам отображается оболочка EFI и вы не можете загрузиться, это может быть связано с несколькими проблемами:

  1. Загрузка из EFI Shell:
    Если QEMU загружает оболочку EFI, это может означать, что ваше ядро или загружаемый образ не распознаны. В этом случае вам потребуется вручную перейти в файловую систему и выполнить ваше ядро. Используйте следующие команды в оболочке EFI:

    fs0:
    cd EFI/BOOT
    bootx64.efi   # Или имя вашего EFI-загрузчика
  2. Создание собственного загрузочного образа:
    Вам может потребоваться создать загрузочный ISO-образ в соответствии с требованиями UEFI. Для этого вам может понадобиться следовать специальной структуре каталогов. Например, скопируйте ваше ядро и файловую систему в соответствующие директории:

    mkdir iso_contents
    mkdir iso_contents/EFI
    mkdir iso_contents/EFI/BOOT
    cp ../bzImage iso_contents/EFI/BOOT/BOOTX64.EFI # Переименуйте ваше ядро

    Затем создайте ISO-образ с помощью genisoimage:

    genisoimage -o mybootable.iso -b EFI/BOOT/BOOTX64.EFI -no-emul-boot -boot-load-size 4 -boot-info-table iso_contents

    После этого запустите QEMU с созданным ISO-образом:

    qemu-system-x86_64 -bios /usr/share/ovmf/OVMF.fd -boot d -cdrom mybootable.iso

Важно

  1. NVRAM в QEMU: QEMU не сохраняет состояния NVRAM после завершения сессии. Вам придется каждый раз заново настраивать параметры загрузки.
  2. Использование файловых систем: Убедитесь, что используемые вами образы соответствуют требованиям UEFI. Если вы собираете ISO-образ, следуйте стандартам, чтобы UEFI могла его распознать.

Заключение

Эти шаги помогут вам настроить загрузку вашего ядра с поддержкой EFI в QEMU. Если у вас возникнут дополнительные вопросы или проблемы, пожалуйста, уточните их, и мы постараемся помочь вам!

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

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