blob: bc9aeebbf4f8a081eda65449d1fd9fe8522de9f3 [file] [log] [blame]
Simon Glass6b2f8292021-11-03 21:09:03 -06001#!/bin/bash
2# SPDX-License-Identifier: GPL-2.0+
3#
4# Script to build an EFI thing suitable for booting with QEMU, possibly running
5# it also.
6
7# This just an example. It assumes that
8
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
12#
13# UEFI binaries for QEMU used for testing this script:
14#
15# OVMF-pure-efi.i386.fd at
16# https://drive.google.com/file/d/1jWzOAZfQqMmS2_dAK2G518GhIgj9r2RY/view?usp=sharing
17
18# OVMF-pure-efi.x64.fd at
19# https://drive.google.com/file/d/1c39YI9QtpByGQ4V0UNNQtGqttEzS-eFV/view?usp=sharing
20
21set -e
22
23usage() {
24 echo "Usage: $0 [-a | -p] [other opts]" 1>&2
25 echo 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
33 exit 1
34}
35
36# 32- or 64-bit EFI
37bitness=64
38
39# app or payload ?
40type=app
41
42# create a partition table and put the filesystem in that (otherwise put the
43# filesystem in the raw device)
44part=
45
46# run the image with QEMU
47run=
48
49# run QEMU without a display (U-Boot must be set to stdout=serial)
50serial=
51
52# before the 32/64 split of the app
53old=
54
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
57ubdir=/tmp/b/
58
59while getopts "aopPrsw" opt; do
60 case "${opt}" in
61 a)
62 type=app
63 ;;
64 p)
65 type=payload
66 ;;
67 r)
68 run=1
69 ;;
70 s)
71 serial=1
72 ;;
73 w)
74 bitness=32
75 ;;
76 o)
77 old=1
78 ;;
79 P)
80 part=1
81 ;;
82 *)
83 usage
84 ;;
85 esac
86done
87
88run_qemu() {
89 extra=
90 if [[ "${bitness}" = "64" ]]; then
91 qemu=qemu-system-x86_64
92 bios=OVMF-pure-efi.x64.fd
93 else
94 qemu=qemu-system-i386
95 bios=OVMF-pure-efi.i386.fd
96 fi
97 if [[ -n "${serial}" ]]; then
98 extra="-display none -serial mon:stdio"
99 fi
100 echo "Running ${qemu}"
101 # Use 512MB since U-Boot EFI likes to have 256MB to play with
102 "${qemu}" -bios "${bios}" \
103 -m 512 \
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}
107}
108
109setup_files() {
110 echo "Packaging ${BUILD}"
111 mkdir -p $TMP
112 cat >$TMP/startup.nsh <<EOF
113fs0:u-boot-${type}.efi
114EOF
115 sudo cp ${ubdir}/${BUILD}/u-boot-${type}.efi $TMP
116
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
120}
121
122# Copy files into the filesystem
123copy_files() {
124 sudo cp $TMP/* $MNT
125}
126
127# Create a filesystem on a raw device and copy in the files
128setup_raw() {
129 mkfs.vfat "${IMG}" >/dev/null
130 sudo mount -o loop "${IMG}" $MNT
131 copy_files
132 sudo umount $MNT
133}
134
135# Create a partition table and put the filesystem in the first partition
136# then copy in the files
137setup_part() {
138 # Create a gpt partition table with one partition
139 parted "${IMG}" mklabel gpt 2>/dev/null
140
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
146
147 # Map this partition to a loop device
148 kp="$(sudo kpartx -av ${IMG})"
149 read boot_dev<<<$(grep -o 'loop.*p.' <<< "${kp}")
150 test "${boot_dev}"
151 dev="/dev/mapper/${boot_dev}"
152
153 mkfs.vfat "${dev}" >/dev/null
154
155 sudo mount -o loop "${dev}" $MNT
156
157 copy_files
158
159 # Sync here since this makes kpartx more likely to work the first time
160 sync
161 sudo umount $MNT
162
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
166 sleep .5
167 sudo kpartx -d "${IMG}" > /dev/null || \
168 echo "Failed to remove ${boot_dev}, use: sudo kpartx -d ${IMG}"
169 fi
170}
171
172TMP="/tmp/efi${bitness}${type}"
173MNT=/mnt/x
174BUILD="efi-x86_${type}${bitness}"
175IMG=try.img
176
177if [[ -n "${old}" && "${bitness}" = "32" ]]; then
178 BUILD="efi-x86_${type}"
179fi
180
181setup_files
182
183qemu-img create "${IMG}" 24M >/dev/null
184
185if [[ -n "${part}" ]]; then
186 setup_part
187else
188 setup_raw
189fi
190
191if [[ -n "${run}" ]]; then
192 run_qemu
193fi