Skip to content

Commit d333fff

Browse files
committed
SMBIOS reader: check the serial-number string index before reading it
ISO copy of the reader, kept identical to the disk copy in vm-config-dist, plus the matching gitlink bump (00dd919..52d2087, reachable on org-ai-assisted). Type 1 offset 7 holds a string INDEX, and 0 means "no string" (DSP0134 6.1.3), so an unguarded --get-string 7 makes GRUB print 'error: failed to retrieve the structure field.' on every ordinary boot of an image built with the reader -- the QEMU gate passes on any QEMU guest, and the serial is set only when a tester injects. Probe the index byte first; read the string only when it is non-zero. Found by coderabbit on org-ai-assisted/vm-config-dist#8. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
1 parent d3301d6 commit d333fff

1 file changed

Lines changed: 16 additions & 4 deletions

File tree

live-build-data/grub-config/smbios-reader.cfg

Lines changed: 16 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -36,9 +36,11 @@
3636
# passed, so it holds across SeaBIOS and OVMF, i440fx and q35, amd64 and arm64.
3737
# Product Name carries the machine type and Type 0 vendor differs per firmware, so
3838
# either would break a boot-test leg on a machine type nobody thought about.
39-
# Reading Manufacturer FIRST also keeps an ordinary boot quiet: DSP0134 requires
39+
# Reading Manufacturer FIRST also keeps a BARE-METAL boot quiet: DSP0134 requires
4040
# Manufacturer to be non-null but leaves the serial number optional, and GRUB prints
41-
# 'error: failed to retrieve the structure field.' for an absent string.
41+
# 'error: failed to retrieve the structure field.' for an absent string. Under QEMU
42+
# the gate passes, so that alone is not enough -- the serial-index check inside the
43+
# gate is what keeps an ordinary QEMU boot quiet.
4244
# dm-smbios-reader: begin
4345
insmod regexp
4446
insmod smbios
@@ -48,14 +50,24 @@ insmod serial
4850
# so a value surviving from an earlier load_env would select the tester path on an
4951
# ordinary boot.
5052
set dm_smbios_vendor=
53+
set dm_smbios_serial_index=0
5154
set dm_smbios_oem=
5255
set dm_smbios_extra=
5356
# Nothing below runs off QEMU: the serial number is only consulted once the
5457
# manufacturer identifies a QEMU guest.
5558
smbios --type 1 --get-string 4 --set dm_smbios_vendor
5659
if [ "${dm_smbios_vendor}" = "QEMU" ]; then
57-
smbios --type 1 --get-string 7 --set dm_smbios_oem
58-
regexp --set 1:dm_smbios_extra "^dm-cmdline=(.*)" "${dm_smbios_oem}"
60+
# Offset 7 holds a string INDEX, and 0 means "no string" (DSP0134 6.1.3).
61+
# Asking for the string when the index is 0 makes GRUB print 'error: failed to
62+
# retrieve the structure field.' on the console -- which is EVERY ordinary boot
63+
# of an image built with the reader, because the serial is set only when a
64+
# tester injects. Reading the index byte first never errors, so the noisy call
65+
# happens only when there is something to read.
66+
smbios --type 1 --get-byte 7 --set dm_smbios_serial_index
67+
if [ "${dm_smbios_serial_index}" != "0" ]; then
68+
smbios --type 1 --get-string 7 --set dm_smbios_oem
69+
regexp --set 1:dm_smbios_extra "^dm-cmdline=(.*)" "${dm_smbios_oem}"
70+
fi
5971
fi
6072
# Route GRUB to the serial console ONLY when a boot-tester injected a cmdline via
6173
# SMBIOS (dm_smbios_extra non-empty), so the headless firmware -> GRUB -> kernel

0 commit comments

Comments
 (0)