Skip to content

Commit 7d12acd

Browse files
committed
Try Pi 3 direct boot in image smoke
1 parent a30f59a commit 7d12acd

2 files changed

Lines changed: 192 additions & 21 deletions

File tree

.github/workflows/image-boot-smoke.yml

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -42,7 +42,9 @@ jobs:
4242
parted \
4343
p7zip-full \
4444
qemu-system-arm \
45+
qemu-user-static \
4546
rsync \
47+
file \
4648
unzip \
4749
xz-utils
4850

test/image-boot-smoke.sh

Lines changed: 190 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -66,6 +66,42 @@ require_commands() {
6666
done
6767
}
6868

69+
cmdline_set_arg() {
70+
local cmdline="$1"
71+
local key="$2"
72+
local value="$3"
73+
local arg found
74+
local -a args output
75+
read -r -a args <<< "$cmdline"
76+
found=0
77+
output=()
78+
for arg in "${args[@]}"; do
79+
if [[ "$arg" == "$key="* ]]; then
80+
output+=("$key=$value")
81+
found=1
82+
else
83+
output+=("$arg")
84+
fi
85+
done
86+
if [[ "$found" == "0" ]]; then
87+
output+=("$key=$value")
88+
fi
89+
printf '%s\n' "${output[*]}"
90+
}
91+
92+
cmdline_add_flag() {
93+
local cmdline="$1"
94+
local flag="$2"
95+
local arg
96+
for arg in $cmdline; do
97+
if [[ "$arg" == "$flag" ]]; then
98+
printf '%s\n' "$cmdline"
99+
return 0
100+
fi
101+
done
102+
printf '%s %s\n' "$cmdline" "$flag"
103+
}
104+
69105
github_api() {
70106
local url="$1"
71107
local -a headers
@@ -170,6 +206,21 @@ partition_values() {
170206
| awk -F: -v part="$part" '$1 == part { gsub(/B/, "", $2); gsub(/B/, "", $4); print $2, $4 }'
171207
}
172208

209+
partition_uuid() {
210+
local part="$1"
211+
local disk_id uuid
212+
if uuid="$(sfdisk --part-uuid "$IMAGE_FILE" "$part" 2>/dev/null)" && [[ -n "$uuid" ]]; then
213+
printf '%s\n' "$uuid"
214+
return 0
215+
fi
216+
if disk_id="$(sfdisk --disk-id "$IMAGE_FILE" 2>/dev/null)" && [[ "$disk_id" == 0x* ]]; then
217+
disk_id="${disk_id#0x}"
218+
printf '%s-%02x\n' "${disk_id,,}" "$part"
219+
return 0
220+
fi
221+
return 1
222+
}
223+
173224
mount_partitions() {
174225
local boot_start boot_size root_start root_size
175226
mkdir -p "$ROOT_MNT" "$BOOT_MNT"
@@ -221,34 +272,139 @@ copy_boot_file() {
221272
cp "$BOOT_MNT/$name" "$BOOT_FILES/$name"
222273
}
223274

275+
copy_optional_boot_file() {
276+
local name="$1"
277+
if [[ -f "$BOOT_MNT/$name" ]]; then
278+
cp "$BOOT_MNT/$name" "$BOOT_FILES/$name"
279+
return 0
280+
fi
281+
return 1
282+
}
283+
284+
select_initrd() {
285+
local kernel="$1"
286+
local config="$BOOT_MNT/config.txt"
287+
local explicit candidate
288+
if [[ -f "$config" ]]; then
289+
explicit="$(awk '
290+
/^[[:space:]]*#/ { next }
291+
/^[[:space:]]*initramfs[[:space:]]+/ { print $2; exit }
292+
' "$config")"
293+
if [[ -n "$explicit" && -f "$BOOT_MNT/$explicit" ]]; then
294+
printf '%s\n' "$explicit"
295+
return 0
296+
fi
297+
fi
298+
299+
case "$kernel" in
300+
kernel8.img)
301+
for candidate in initramfs8 initramfs_2710 initrd.img; do
302+
[[ -f "$BOOT_MNT/$candidate" ]] && printf '%s\n' "$candidate" && return 0
303+
done
304+
;;
305+
kernel7l.img)
306+
for candidate in initramfs7l initramfs_2711 initrd.img; do
307+
[[ -f "$BOOT_MNT/$candidate" ]] && printf '%s\n' "$candidate" && return 0
308+
done
309+
;;
310+
kernel7.img)
311+
for candidate in initramfs7 initramfs_2709 initrd.img; do
312+
[[ -f "$BOOT_MNT/$candidate" ]] && printf '%s\n' "$candidate" && return 0
313+
done
314+
;;
315+
kernel.img)
316+
for candidate in initramfs initrd.img; do
317+
[[ -f "$BOOT_MNT/$candidate" ]] && printf '%s\n' "$candidate" && return 0
318+
done
319+
;;
320+
esac
321+
return 1
322+
}
323+
324+
try_dtmerge() {
325+
local source_dtb="$1"
326+
local output_dtb="$2"
327+
local dtmerge="$ROOT_MNT/usr/bin/dtmerge"
328+
local emulator
329+
[[ -x "$dtmerge" ]] || return 1
330+
331+
case "$(file -b "$dtmerge")" in
332+
*aarch64*)
333+
emulator="qemu-aarch64-static"
334+
;;
335+
*ARM*)
336+
emulator="qemu-arm-static"
337+
;;
338+
*)
339+
return 1
340+
;;
341+
esac
342+
command -v "$emulator" >/dev/null 2>&1 || return 1
343+
344+
"$emulator" -L "$ROOT_MNT" "$dtmerge" "$source_dtb" "$output_dtb" - uart0=on >/dev/null 2>&1 \
345+
|| return 1
346+
if [[ -f "$BOOT_MNT/overlays/disable-bt.dtbo" ]]; then
347+
"$emulator" -L "$ROOT_MNT" "$dtmerge" "$output_dtb" "$output_dtb.tmp" \
348+
"$BOOT_MNT/overlays/disable-bt.dtbo" >/dev/null 2>&1 \
349+
|| return 1
350+
mv "$output_dtb.tmp" "$output_dtb"
351+
fi
352+
}
353+
354+
prepare_qemu_dtb() {
355+
local dtb="$1"
356+
local merged="qemu-$dtb"
357+
if try_dtmerge "$BOOT_FILES/$dtb" "$BOOT_FILES/$merged"; then
358+
echo "Prepared QEMU DTB with uart0=on and disable-bt overlay when available: $merged" >&2
359+
printf '%s\n' "$merged"
360+
return 0
361+
fi
362+
echo "Using unmodified DTB: $dtb" >&2
363+
printf '%s\n' "$dtb"
364+
}
365+
224366
prepare_boot_files() {
225-
local kernel dtb cmdline
367+
local kernel dtb qemu_dtb cmdline initrd root_partuuid
226368
mkdir -p "$BOOT_FILES"
227369

228-
if [[ -f "$BOOT_MNT/kernel7.img" ]]; then
370+
if [[ -f "$BOOT_MNT/kernel8.img" ]]; then
371+
kernel="kernel8.img"
372+
dtb="bcm2710-rpi-3-b.dtb"
373+
elif [[ -f "$BOOT_MNT/kernel7.img" ]]; then
229374
kernel="kernel7.img"
230375
dtb="bcm2709-rpi-2-b.dtb"
231376
elif [[ -f "$BOOT_MNT/kernel7l.img" ]]; then
232377
kernel="kernel7l.img"
233378
dtb="bcm2711-rpi-4-b.dtb"
234-
elif [[ -f "$BOOT_MNT/kernel8.img" ]]; then
235-
kernel="kernel8.img"
236-
dtb="bcm2710-rpi-3-b.dtb"
237379
else
238380
fail "no supported Raspberry Pi kernel found in boot partition"
239381
fi
240382

241383
copy_boot_file "$kernel"
242384
copy_boot_file "$dtb"
385+
qemu_dtb="$(prepare_qemu_dtb "$dtb")"
386+
if initrd="$(select_initrd "$kernel")"; then
387+
copy_optional_boot_file "$initrd"
388+
printf '%s\n' "$initrd" > "$BOOT_FILES/initrd-name"
389+
echo "Using initramfs for direct QEMU boot: $initrd"
390+
else
391+
rm -f "$BOOT_FILES/initrd-name"
392+
echo "No initramfs selected for direct QEMU boot"
393+
fi
243394

244395
cmdline="$(tr -d '\n' < "$BOOT_MNT/cmdline.txt")"
245396
cmdline="${cmdline//console=serial0,115200/console=ttyAMA0,115200}"
246397
cmdline="${cmdline//console=serial0/console=ttyAMA0,115200}"
247398
cmdline="$(printf '%s\n' "$cmdline" \
248399
| sed -E 's/(^| )init=[^ ]+//g; s/(^| )quiet( |$)/ /g; s/[[:space:]]+/ /g; s/^ //; s/ $//')"
400+
if root_partuuid="$(partition_uuid 2)"; then
401+
cmdline="$(cmdline_set_arg "$cmdline" root "PARTUUID=$root_partuuid")"
402+
fi
403+
cmdline="$(cmdline_add_flag "$cmdline" rootwait)"
404+
cmdline="$(cmdline_set_arg "$cmdline" rootfstype ext4)"
249405
printf '%s systemd.unit=multi-user.target systemd.show_status=1 nr_cpus=1 maxcpus=1\n' "$cmdline" > "$BOOT_FILES/cmdline.txt"
250406
printf '%s\n' "$kernel" > "$BOOT_FILES/kernel-name"
251-
printf '%s\n' "$dtb" > "$BOOT_FILES/dtb-name"
407+
printf '%s\n' "$qemu_dtb" > "$BOOT_FILES/dtb-name"
252408
}
253409

254410
write_guest_probe() {
@@ -399,34 +555,47 @@ UNIT
399555
}
400556

401557
qemu_command() {
402-
local kernel dtb cmdline qemu_bin machine
558+
local kernel dtb cmdline qemu_bin machine cpu initrd
559+
local -a args
403560
kernel="$(cat "$BOOT_FILES/kernel-name")"
404561
dtb="$(cat "$BOOT_FILES/dtb-name")"
405562
cmdline="$(cat "$BOOT_FILES/cmdline.txt")"
406563

407564
if [[ "$kernel" == "kernel8.img" ]]; then
408565
qemu_bin="qemu-system-aarch64"
409566
machine="raspi3b"
567+
cpu="cortex-a53"
410568
else
411569
qemu_bin="qemu-system-arm"
412570
machine="raspi2b"
571+
cpu=""
413572
fi
414573

415574
require_command "$qemu_bin"
416-
printf '%q ' \
417-
"$qemu_bin" \
418-
-M "$machine" \
419-
-smp 1 \
420-
-m 1G \
421-
-kernel "$BOOT_FILES/$kernel" \
422-
-dtb "$BOOT_FILES/$dtb" \
423-
-append "$cmdline" \
424-
-drive "file=$IMAGE_FILE,format=raw,if=sd" \
425-
-netdev user,id=net0 \
426-
-device usb-net,netdev=net0 \
427-
-serial mon:stdio \
428-
-display none \
575+
args=("$qemu_bin" -M "$machine")
576+
if [[ -n "$cpu" ]]; then
577+
args+=(-cpu "$cpu")
578+
fi
579+
args+=(
580+
-smp 1
581+
-m 1G
582+
-kernel "$BOOT_FILES/$kernel"
583+
-dtb "$BOOT_FILES/$dtb"
584+
)
585+
if [[ -f "$BOOT_FILES/initrd-name" ]]; then
586+
initrd="$(cat "$BOOT_FILES/initrd-name")"
587+
args+=(-initrd "$BOOT_FILES/$initrd")
588+
fi
589+
args+=(
590+
-append "$cmdline"
591+
-drive "file=$IMAGE_FILE,format=raw,if=sd"
592+
-netdev "user,id=net0"
593+
-device "usb-net,netdev=net0"
594+
-serial mon:stdio
595+
-display none
429596
-no-reboot
597+
)
598+
printf '%q ' "${args[@]}"
430599
}
431600

432601
run_one_boot() {
@@ -491,7 +660,7 @@ run_boot_smoke() {
491660

492661
main() {
493662
local image_archive
494-
require_commands curl jq git rsync parted awk mount umount find cp tee timeout
663+
require_commands curl jq git rsync parted sfdisk awk mount umount find cp tee timeout file
495664
require_commands unzip xz gzip
496665
if [[ -n "${AIRPLANES_IMAGE_PATH:-}" ]]; then
497666
image_archive="$AIRPLANES_IMAGE_PATH"

0 commit comments

Comments
 (0)