2 # SPDX-License-Identifier: GPL-2.0+
4 # Script to build an EFI thing suitable for booting with QEMU, possibly running
7 # This just an example. It assumes that
9 # - you build U-Boot in ${ubdir}/<name> where <name> is the U-Boot board config
10 # - /mnt/x is a directory used for mounting
11 # - you have access to the 'pure UEFI' builds for QEMU
13 # UEFI binaries for QEMU used for testing this script:
15 # OVMF-pure-efi.i386.fd at
16 # https://drive.google.com/file/d/1jWzOAZfQqMmS2_dAK2G518GhIgj9r2RY/view?usp=sharing
18 # OVMF-pure-efi.x64.fd at
19 # https://drive.google.com/file/d/1c39YI9QtpByGQ4V0UNNQtGqttEzS-eFV/view?usp=sharing
24 echo "Usage: $0 [-a | -p] [other opts]" 1>&2
26 echo " -a - Package up the app" 1>&2
27 echo " -o - Use old EFI app build (before 32/64 split)" 1>&2
28 echo " -p - Package up the payload" 1>&2
29 echo " -P - Create a partition table" 1>&2
30 echo " -r - Run QEMU with the image" 1>&2
31 echo " -s - Run QEMU with serial only (no display)" 1>&2
32 echo " -w - Use word version (32-bit)" 1>&2
42 # create a partition table and put the filesystem in that (otherwise put the
43 # filesystem in the raw device)
46 # run the image with QEMU
49 # run QEMU without a display (U-Boot must be set to stdout=serial)
52 # before the 32/64 split of the app
55 # Set ubdir to the build directory where you build U-Boot out-of-tree
56 # We avoid in-tree build because it gets confusing trying different builds
59 while getopts "aopPrsw" opt; do
90 if [[ "${bitness}" = "64" ]]; then
91 qemu=qemu-system-x86_64
92 bios=OVMF-pure-efi.x64.fd
95 bios=OVMF-pure-efi.i386.fd
97 if [[ -n "${serial}" ]]; then
98 extra="-display none -serial mon:stdio"
100 echo "Running ${qemu}"
101 # Use 512MB since U-Boot EFI likes to have 256MB to play with
102 "${qemu}" -bios "${bios}" \
104 -drive id=disk,file="${IMG}",if=none,format=raw \
105 -nic none -device ahci,id=ahci \
106 -device ide-hd,drive=disk,bus=ahci.0 ${extra}
110 echo "Packaging ${BUILD}"
112 cat >$TMP/startup.nsh <<EOF
113 fs0:u-boot-${type}.efi
115 sudo cp ${ubdir}/${BUILD}/u-boot-${type}.efi $TMP
117 # Can copy in other files here:
118 #sudo cp ${ubdir}/$BUILD/image.bin $TMP/chromeos.rom
119 #sudo cp /boot/vmlinuz-5.4.0-77-generic $TMP/vmlinuz
122 # Copy files into the filesystem
127 # Create a filesystem on a raw device and copy in the files
129 mkfs.vfat "${IMG}" >/dev/null
130 sudo mount -o loop "${IMG}" $MNT
135 # Create a partition table and put the filesystem in the first partition
136 # then copy in the files
138 # Create a gpt partition table with one partition
139 parted "${IMG}" mklabel gpt 2>/dev/null
141 # This doesn't work correctly. It creates:
142 # Number Start End Size File system Name Flags
143 # 1 1049kB 24.1MB 23.1MB boot msftdata
144 # Odd if the same is entered interactively it does set the FS type
145 parted -s -a optimal -- "${IMG}" mkpart boot fat32 1MiB 23MiB
147 # Map this partition to a loop device
148 kp="$(sudo kpartx -av ${IMG})"
149 read boot_dev<<<$(grep -o 'loop.*p.' <<< "${kp}")
151 dev="/dev/mapper/${boot_dev}"
153 mkfs.vfat "${dev}" >/dev/null
155 sudo mount -o loop "${dev}" $MNT
159 # Sync here since this makes kpartx more likely to work the first time
163 # For some reason this needs a sleep or it sometimes fails, if it was
164 # run recently (in the last few seconds)
165 if ! sudo kpartx -d "${IMG}" > /dev/null; then
167 sudo kpartx -d "${IMG}" > /dev/null || \
168 echo "Failed to remove ${boot_dev}, use: sudo kpartx -d ${IMG}"
172 TMP="/tmp/efi${bitness}${type}"
174 BUILD="efi-x86_${type}${bitness}"
177 if [[ -n "${old}" && "${bitness}" = "32" ]]; then
178 BUILD="efi-x86_${type}"
183 qemu-img create "${IMG}" 24M >/dev/null
185 if [[ -n "${part}" ]]; then
191 if [[ -n "${run}" ]]; then