blob: 46c28807ef1f6db871e7b8dec7ef34ea79be02fe [file] [log] [blame]
Simon Glassdaa53a22021-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"
Simon Glass5b78e872023-03-10 12:47:19 -080099 else
100 extra="-serial mon:stdio"
Simon Glassdaa53a22021-11-03 21:09:03 -0600101 fi
102 echo "Running ${qemu}"
103 # Use 512MB since U-Boot EFI likes to have 256MB to play with
104 "${qemu}" -bios "${bios}" \
105 -m 512 \
106 -drive id=disk,file="${IMG}",if=none,format=raw \
107 -nic none -device ahci,id=ahci \
108 -device ide-hd,drive=disk,bus=ahci.0 ${extra}
109}
110
111setup_files() {
112 echo "Packaging ${BUILD}"
113 mkdir -p $TMP
114 cat >$TMP/startup.nsh <<EOF
115fs0:u-boot-${type}.efi
116EOF
117 sudo cp ${ubdir}/${BUILD}/u-boot-${type}.efi $TMP
118
119 # Can copy in other files here:
120 #sudo cp ${ubdir}/$BUILD/image.bin $TMP/chromeos.rom
121 #sudo cp /boot/vmlinuz-5.4.0-77-generic $TMP/vmlinuz
122}
123
124# Copy files into the filesystem
125copy_files() {
126 sudo cp $TMP/* $MNT
127}
128
129# Create a filesystem on a raw device and copy in the files
130setup_raw() {
131 mkfs.vfat "${IMG}" >/dev/null
132 sudo mount -o loop "${IMG}" $MNT
133 copy_files
134 sudo umount $MNT
135}
136
137# Create a partition table and put the filesystem in the first partition
138# then copy in the files
139setup_part() {
140 # Create a gpt partition table with one partition
141 parted "${IMG}" mklabel gpt 2>/dev/null
142
143 # This doesn't work correctly. It creates:
144 # Number Start End Size File system Name Flags
145 # 1 1049kB 24.1MB 23.1MB boot msftdata
146 # Odd if the same is entered interactively it does set the FS type
147 parted -s -a optimal -- "${IMG}" mkpart boot fat32 1MiB 23MiB
148
149 # Map this partition to a loop device
150 kp="$(sudo kpartx -av ${IMG})"
151 read boot_dev<<<$(grep -o 'loop.*p.' <<< "${kp}")
152 test "${boot_dev}"
153 dev="/dev/mapper/${boot_dev}"
154
155 mkfs.vfat "${dev}" >/dev/null
156
157 sudo mount -o loop "${dev}" $MNT
158
159 copy_files
160
161 # Sync here since this makes kpartx more likely to work the first time
162 sync
163 sudo umount $MNT
164
165 # For some reason this needs a sleep or it sometimes fails, if it was
166 # run recently (in the last few seconds)
167 if ! sudo kpartx -d "${IMG}" > /dev/null; then
168 sleep .5
169 sudo kpartx -d "${IMG}" > /dev/null || \
170 echo "Failed to remove ${boot_dev}, use: sudo kpartx -d ${IMG}"
171 fi
172}
173
174TMP="/tmp/efi${bitness}${type}"
175MNT=/mnt/x
176BUILD="efi-x86_${type}${bitness}"
177IMG=try.img
178
179if [[ -n "${old}" && "${bitness}" = "32" ]]; then
180 BUILD="efi-x86_${type}"
181fi
182
183setup_files
184
185qemu-img create "${IMG}" 24M >/dev/null
186
187if [[ -n "${part}" ]]; then
188 setup_part
189else
190 setup_raw
191fi
192
193if [[ -n "${run}" ]]; then
194 run_qemu
195fi