
On 11/4/21 04:09, Simon Glass wrote:
It is quite complicated to run U-Boot on QEMU since we have four different builds and they must use different versions of qemu and the UEFI binaries.
Add a script to help. It requires U-Boot itself to be built. Once that is done you can use this script to build an image for use with qemu and optionally run it.
Signed-off-by: Simon Glass sjg@chromium.org
Changes in v4:
- Change the patch subject to make it clear this does not build U-Boot
- Update commit message to mention that you have to build U-Boot
Changes in v3:
- Fix 'complicating' typo
- s/qemu/QEMU/
Changes in v2:
Add MAINTAINERS entry
Add support for creating a partition table with a filesystem inside
Add support for running qemu with just a serial console (no display)
MAINTAINERS | 1 + doc/develop/uefi/u-boot_on_efi.rst | 62 +++++++++ scripts/build-efi.sh | 193 +++++++++++++++++++++++++++++ 3 files changed, 256 insertions(+) create mode 100755 scripts/build-efi.sh
diff --git a/MAINTAINERS b/MAINTAINERS index 9d8cba90280..fa7fe900705 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -710,6 +710,7 @@ M: Heinrich Schuchardt xypron.glpk@gmx.de S: Maintained W: https://u-boot.readthedocs.io/en/latest/develop/uefi/u-boot_on_efi.html F: lib/efi/efi_app.c +F: scripts/build-efi.sh
EFI PAYLOAD M: Heinrich Schuchardt xypron.glpk@gmx.de diff --git a/doc/develop/uefi/u-boot_on_efi.rst b/doc/develop/uefi/u-boot_on_efi.rst index 43afb11de56..8856af3db56 100644 --- a/doc/develop/uefi/u-boot_on_efi.rst +++ b/doc/develop/uefi/u-boot_on_efi.rst @@ -98,6 +98,11 @@ that EFI does not support booting a 64-bit application from a 32-bit EFI (or vice versa). Also it will often fail to print an error message if you get this wrong.
+You may find the script `scripts/build-efi.sh` helpful for building and testing +U-Boot on UEFI on QEMU. It also includes links to UEFI binaries dating from +2021.
+See `Example run`_ for an example run.
Inner workings
@@ -193,6 +198,63 @@ of code is built this way (see the extra- line in lib/efi/Makefile). Everything else is built as a normal U-Boot, so is always 32-bit on x86 at present.
+Example run +-----------
+This shows running with serial enabled (see `include/configs/efi-x86_app.h`)::
- $ scripts/build-efi.sh -wsPr
- Packaging efi-x86_app32
- Running qemu-system-i386
- BdsDxe: failed to load Boot0001 "UEFI QEMU HARDDISK QM00005 " from PciRoot(0x0)/Pci(0x3,0x0)/Sata(0x0,0xFFFF,0x0): Not Found
- BdsDxe: loading Boot0002 "EFI Internal Shell" from Fv(7CB8BDC9-F8EB-4F34-AAEA-3EE4AF6516A1)/FvFile(7C04A583-9E3E-4F1C-AD65-E05268D0B4D1)
- BdsDxe: starting Boot0002 "EFI Internal Shell" from Fv(7CB8BDC9-F8EB-4F34-AAEA-3EE4AF6516A1)/FvFile(7C04A583-9E3E-4F1C-AD65-E05268D0B4D1)
- UEFI Interactive Shell v2.2
- EDK II
- UEFI v2.70 (EDK II, 0x00010000)
- Mapping table
FS0: Alias(s):HD0a65535a1:;BLK1:
PciRoot(0x0)/Pci(0x3,0x0)/Sata(0x0,0xFFFF,0x0)/HD(1,GPT,0FFD5E61-3B0C-4326-8049-BDCDC910AF72,0x800,0xB000)
BLK0: Alias(s):
PciRoot(0x0)/Pci(0x3,0x0)/Sata(0x0,0xFFFF,0x0)
- Press ESC in 5 seconds to skip startup.nsh or any other key to continue.
- Shell> fs0:u-boot-app.efi
- U-Boot EFI App (using allocated RAM address 47d4000) key=8d4, image=06a6f610
- starting
- U-Boot 2022.01-rc4 (Sep 19 2021 - 14:03:20 -0600)
- CPU: x86, vendor Intel, device 663h
- DRAM: 32 MiB
- 0: efi_media_0 PciRoot(0x0)/Pci(0x3,0x0)/Sata(0x0,0xFFFF,0x0)
- 1: <partition> PciRoot(0x0)/Pci(0x3,0x0)/Sata(0x0,0xFFFF,0x0)/HD(1,GPT,0FFD5E61-3B0C-4326-8049-BDCDC910AF72,0x800,0xB000)
- Loading Environment from nowhere... OK
- Model: EFI x86 Application
- Hit any key to stop autoboot: 0
- Partition Map for EFI device 0 -- Partition Type: EFI
- Part Start LBA End LBA Name
Attributes
Type GUID
Partition GUID
1 0x00000800 0x0000b7ff "boot"
attrs: 0x0000000000000000
type: ebd0a0a2-b9e5-4433-87c0-68b6b72699c7
guid: 0ffd5e61-3b0c-4326-8049-bdcdc910af72
19 startup.nsh
528384 u-boot-app.efi
10181 NvVars
- 3 file(s), 0 dir(s)
- => QEMU: Terminated
Future work
This work could be extended in a number of ways:diff --git a/scripts/build-efi.sh b/scripts/build-efi.sh new file mode 100755 index 00000000000..ce761840097 --- /dev/null +++ b/scripts/build-efi.sh @@ -0,0 +1,193 @@ +#!/bin/bash +# SPDX-License-Identifier: GPL-2.0+ +# +# Script to build an EFI thing suitable for booting with QEMU, possibly running +# it also.
+# This just an example. It assumes that
+# - you build U-Boot in ${ubdir}/<name> where <name> is the U-Boot board config +# - /mnt/x is a directory used for mounting +# - you have access to the 'pure UEFI' builds for QEMU +# +# UEFI binaries for QEMU used for testing this script: +# +# OVMF-pure-efi.i386.fd at +# https://drive.google.com/file/d/1jWzOAZfQqMmS2_dAK2G518GhIgj9r2RY/view?usp=s...
+# OVMF-pure-efi.x64.fd at +# https://drive.google.com/file/d/1c39YI9QtpByGQ4V0UNNQtGqttEzS-eFV/view?usp=s...
+set -e
+usage() {
- echo "Usage: $0 [-a | -p] [other opts]" 1>&2
- echo 1>&2
- echo " -a - Package up the app" 1>&2
- echo " -o - Use old EFI app build (before 32/64 split)" 1>&2
- echo " -p - Package up the payload" 1>&2
- echo " -P - Create a partition table" 1>&2
- echo " -r - Run QEMU with the image" 1>&2
- echo " -s - Run QEMU with serial only (no display)" 1>&2
- echo " -w - Use word version (32-bit)" 1>&2
- exit 1
+}
+# 32- or 64-bit EFI +bitness=64
+# app or payload ? +type=app
+# create a partition table and put the filesystem in that (otherwise put the +# filesystem in the raw device) +part=
+# run the image with QEMU +run=
+# run QEMU without a display (U-Boot must be set to stdout=serial) +serial=
+# before the 32/64 split of the app +old=
+# Set ubdir to the build directory where you build U-Boot out-of-tree +# We avoid in-tree build because it gets confusing trying different builds +ubdir=/tmp/b/
+while getopts "aopPrsw" opt; do
- case "${opt}" in
- a)
type=app
;;
- p)
type=payload
;;
- r)
run=1
;;
- s)
serial=1
;;
- w)
bitness=32
;;
- o)
old=1
;;
- P)
part=1
;;
- *)
usage
;;
- esac
+done
+run_qemu() {
- extra=
- if [[ "${bitness}" = "64" ]]; then
qemu=qemu-system-x86_64
bios=OVMF-pure-efi.x64.fd
- else
qemu=qemu-system-i386
bios=OVMF-pure-efi.i386.fd
- fi
- if [[ -n "${serial}" ]]; then
extra="-display none -serial mon:stdio"
- fi
- echo "Running ${qemu}"
- # Use 512MB since U-Boot EFI likes to have 256MB to play with
- "${qemu}" -bios "${bios}" \
-m 512 \
-drive id=disk,file="${IMG}",if=none,format=raw \
-nic none -device ahci,id=ahci \
-device ide-hd,drive=disk,bus=ahci.0 ${extra}
+}
+setup_files() {
- echo "Packaging ${BUILD}"
- mkdir -p $TMP
- cat >$TMP/startup.nsh <<EOF
+fs0:u-boot-${type}.efi +EOF
- sudo cp ${ubdir}/${BUILD}/u-boot-${type}.efi $TMP
- # Can copy in other files here:
- #sudo cp ${ubdir}/$BUILD/image.bin $TMP/chromeos.rom
- #sudo cp /boot/vmlinuz-5.4.0-77-generic $TMP/vmlinuz
+}
+# Copy files into the filesystem +copy_files() {
- sudo cp $TMP/* $MNT
Please, don't expect the user to be a sudoer. virt-make-fs is a better solution.
This can be changed in a follow up patch.
+}
+# Create a filesystem on a raw device and copy in the files +setup_raw() {
- mkfs.vfat "${IMG}" >/dev/null
- sudo mount -o loop "${IMG}" $MNT
- copy_files
- sudo umount $MNT
+}
+# Create a partition table and put the filesystem in the first partition +# then copy in the files +setup_part() {
- # Create a gpt partition table with one parittion
%s/parittion/partition/
I will fix this one when merging.
Best regards
Heinrich
- parted "${IMG}" mklabel gpt 2>/dev/null
- # This doesn't work correctly. It creates:
- # Number Start End Size File system Name Flags
- # 1 1049kB 24.1MB 23.1MB boot msftdata
- # Odd if the same is entered interactively it does set the FS type
- parted -s -a optimal -- "${IMG}" mkpart boot fat32 1MiB 23MiB
- # Map this partition to a loop device
- kp="$(sudo kpartx -av ${IMG})"
- read boot_dev<<<$(grep -o 'loop.*p.' <<< "${kp}")
- test "${boot_dev}"
- dev="/dev/mapper/${boot_dev}"
- mkfs.vfat "${dev}" >/dev/null
- sudo mount -o loop "${dev}" $MNT
- copy_files
- # Sync here since this makes kpartx more likely to work the first time
- sync
- sudo umount $MNT
- # For some reason this needs a sleep or it sometimes fails, if it was
- # run recently (in the last few seconds)
- if ! sudo kpartx -d "${IMG}" > /dev/null; then
sleep .5
sudo kpartx -d "${IMG}" > /dev/null || \
echo "Failed to remove ${boot_dev}, use: sudo kpartx -d ${IMG}"
- fi
+}
+TMP="/tmp/efi${bitness}${type}" +MNT=/mnt/x +BUILD="efi-x86_${type}${bitness}" +IMG=try.img
+if [[ -n "${old}" && "${bitness}" = "32" ]]; then
- BUILD="efi-x86_${type}"
+fi
+setup_files
+qemu-img create "${IMG}" 24M >/dev/null
+if [[ -n "${part}" ]]; then
- setup_part
+else
- setup_raw
+fi
+if [[ -n "${run}" ]]; then
- run_qemu
+fi