Commit Graph
87640 Commits
Author SHA1 Message Date
Lennart Poettering f83e47bd57 vmspawn: add a bunch of func param assert()s 2026-04-02 23:28:33 +02:00
Daan De Meyer 0508f15b7f ci: Drop base64 encoding in claude review workflow
Doesn't seem to work nearly as good as the previous solution which
just told claude not to escape stuff.
2026-04-02 21:45:11 +02:00
Nikolas Kyx 1f6935145d manager: Add DefaultMemoryZSwapWriteback
Allow setting system-wide MemoryZSwapWriteback in system.conf

Resolves: #41320
2026-04-02 20:04:30 +01:00
Daan De Meyer a586648800 vmspawn: Add --console-transport= option to select serial vs virtio-serial
Add a --console-transport= option that selects between virtio-serial
(the default, appearing as /dev/hvc0) and a regular serial port
(appearing as /dev/ttyS0 or /dev/ttyAMA0 depending on architecture).

This is primarily useful for testing purposes, for example to test
sd-stub's automatic console= kernel command line parameter handling. It
allows verifying that the guest OS correctly handles serial console
configurations without virtio.

When serial transport is selected, -serial chardev:console is used on
the QEMU command line to connect the chardev to the platform's default
serial device. This cannot be done via the QEMU config file as on some
platforms (e.g. ARM) the serial device is a sysbus device that can only
be connected via serial_hd() which is populated by -serial.
2026-04-02 20:43:42 +02:00
Daan De Meyer eb584f164f loop-util: create loop device for block devices with sector size mismatch
Previously, loop_device_make_internal() always used the block device
directly (via loop_device_open_from_fd()) for whole-device access,
regardless of sector size. This is incorrect when the GPT partition
table was written with a different sector size than the device reports,
as happens with CD-ROM/ISO boot via El Torito: the device has
2048-byte blocks but the GPT uses 512-byte sectors.

Restructure the sector size handling in loop_device_make_internal():

- Move GPT sector size probing (UINT32_MAX case) before the
  block-vs-regular-file split so both paths share the same logic and
  O_DIRECT handling. Check f_flags instead of loop_flags for O_DIRECT
  detection, since we're probing the original fd before any reopening.

- For block devices, get the device sector size and compare it against
  the resolved sector_size. Only use the block device directly when
  sector sizes match. When they differ (probed GPT mismatch or explicit
  sector size request), fall through to create a real loop device with
  the correct sector size.

- Default sector_size=0 to the device sector size for block devices
  (instead of always 512), so "no preference" correctly matches the
  device's sector size.

Co-developed-by: Claude Opus 4.6 <noreply@anthropic.com>
2026-04-02 18:08:25 +02:00
Daan De Meyer d49df940ec test-loop-block: Migrate to new assertion macros and framework
While we're at it, rename to test-loop-util.c so it matches its
source file.

We also drop the root check and solely check for CAP_SYS_ADMIN since
that's sufficient to run the tests.
2026-04-02 18:08:25 +02:00
Daan De Meyer dcce04e649 vmspawn: propagate $TERM from host into VM via kernel command line
When running in a console mode (interactive, native, or read-only),
propagate the host's $TERM into the VM by adding TERM= and
systemd.tty.term.hvc0= to the kernel command line.

TERM= is picked up by PID 1 and inherited by services on /dev/console
(such as emergency.service). systemd.tty.term.hvc0= is used by services
directly attached to /dev/hvc0 (such as serial-getty@hvc0.service) which
look up $TERM via the systemd.tty.term.<tty> kernel command line
parameter.

While systemd can auto-detect the terminal type via DCS XTGETTCAP, not
all terminal emulators implement this, so explicitly propagating $TERM
provides a more reliable experience. We skip propagation when $TERM is
unset or set to "unknown" (as is the case in GitHub Actions and some
other CI environments).

Previously this was handled by mkosi synthesizing the corresponding
kernel command line parameters externally.

Co-developed-by: Claude Opus 4.6 <noreply@anthropic.com>
2026-04-02 18:06:10 +02:00
Daan De Meyer 214f7f0b8a vmspawn: Warn about --grow-image= in combo with --image-disk-type=scsi-cd 2026-04-02 18:04:29 +02:00
Lennart Poettering 5af9b6dd04 Support CopyBlocks= for Verity={hash,sig} (#41393)
This enables deriving the minimum size of the `Verity=hash` partition
using the `Verity=` logic when the size of the `Verity=data` partition
is bigger than the `CopyBlocks=` target.

This enables using `Minimize=true` for an "installer image" and later
using sd-repart to install to a system with reserve space for future
updates by specifying `Size{Min,Max}Bytes=` only in the `Verity=data`
partition, without needing to hardcode the corresponding size for the
`Verity=hash` partition.

While not strictly necessary for `Verity=signature` partitions (since
they have a fixed size) there isn't too much reason to not support it,
since then you can still specify `VerityMatchKey=` to indicate that the
partition is logically still part of that group of partitions.

---

Alternative to: https://github.com/systemd/systemd/pull/41156
Fixes https://github.com/systemd/systemd/issues/40995
2026-04-02 16:18:14 +02:00
Lennart Poettering ba54784c86 report: implement facts interface (#41117)
This is a rebased version of #40936:
- the first few commits are #41003, which is greenlighted for merging
after the release
- then there's #40923
- and some changes on top
2026-04-02 16:17:43 +02:00
Lennart Poettering 5f598576b8 network-generator: support BOOTIF= and rd.bootif=0 options (#41028)
The network generator currently supports many of the options described
by dracut.cmdline(7), but not everything.

This commit adds support for the BOOTIF= option (and the related
rd.bootif= option) used in PXE setups.

This is implemented by treating BOOTIF as a special name/placeholder
when used as an interface name, and expecting a MAC address to be set in
the BOOTIF= parameter. The resulting .network file then uses MACAddress=
in the [Match] section, instead of Name=.
2026-04-02 16:17:11 +02:00
Daan De Meyer bfdc389ea7 terminal-util: Protect errno in termios_reset() 2026-04-02 16:08:56 +02:00
Daan De Meyer 7d11e8bed7 basic/terminal-util: use getenv_terminal_is_dumb()
terminal_prepare_query() is called from terminal_get_size() which
operates on an explicitly passed fd — typically /dev/console opened
directly by PID 1 via reset_dev_console_fd(), or a service's TTY via
exec_context_apply_tty_size(). Using terminal_is_dumb() here is wrong
because it additionally checks on_tty(), which tests whether stderr is
a tty. PID 1's stderr may not be a tty (e.g. connected to kmsg or the
journal), causing terminal_is_dumb() to return true and skip the ANSI
query even though the fd we're operating on is a perfectly functional
terminal.

Use getenv_terminal_is_dumb() instead, which only checks $TERM, matching
what terminal_reset_ansi_seq() already does.

Also use it in terminal_get_cursor_position(), which also receives fds
to operate on.
2026-04-02 16:08:56 +02:00
Daan De Meyer ba10d789a8 basic/terminal-util: use non-blocking writes when sending ANSI sequences in terminal_get_size()
terminal_get_size() writes ANSI escape sequences (CSI 18 and DSR
queries) to the output fd to determine terminal dimensions. This is
called during early boot via reset_dev_console_fd() and from service
execution contexts via exec_context_apply_tty_size().

Previously, these writes used loop_write() on a blocking fd, which
could block indefinitely if the terminal is not consuming data — for
example on a serial console with flow control asserted, or a
disconnected terminal. This is the same problem that was solved for
terminal_reset_ansi_seq() in systemd/systemd#32369 by temporarily
setting the fd to non-blocking mode with a write timeout.

Apply the same pattern here: set the output fd to non-blocking in
terminal_get_size() before issuing the queries, and restore blocking
mode afterward. Change the loop_write() calls in
terminal_query_size_by_dsr() and terminal_query_size_by_csi18() to
loop_write_full() with a 100ms timeout so writes fail gracefully
instead of hanging.

Also introduce the CONSOLE_ANSI_SEQUENCE_TIMEOUT_USEC constant for all
timeouts used across all ANSI sequence writes and reads (vt_disallocate(),
terminal_reset_ansi_seq(), and the two size query functions). 333ms
is now used for all timeouts in terminal-util.c.

Also introduce a cleanup function for resetting a fd back to blocking
mode after it was made non-blocking.
2026-04-02 16:08:56 +02:00
Daan De Meyer e98a26ddc0 vmspawn: use fstab.extra credential for runtime mounts instead of kernel cmdline
Switch runtime virtiofs mount configuration from systemd.mount-extra=
kernel command line parameters to the fstab.extra credential. This
avoids consuming kernel command line space (which is limited) and
matches the approach used by mkosi.

Each mount is added as an fstab entry in the format:
  {tag} {destination} virtiofs {ro|rw},x-initrd.mount

If the user already specified a fstab.extra credential via
--set-credential= or --load-credential=, the virtiofs mount entries
are appended to it rather than conflicting.

Co-developed-by: Claude Opus 4.6 <noreply@anthropic.com>
2026-04-02 16:03:29 +02:00
Daan De Meyer 2371c9e798 vmspawn: add scsi-cd disk type for ISO/CD-ROM image support
Add DISK_TYPE_SCSI_CD to support attaching disk images as CD-ROM
drives, needed for testing El Torito ISO images built by
systemd-repart.

When --image-disk-type=scsi-cd is specified, the image is attached
with media=cdrom and readonly=on on the drive, using scsi-cd as the
device driver on the SCSI bus. This also works for --extra-drive=
with the scsi-cd: prefix.

The QEMU configuration matches the standard OVMF CD-ROM boot setup:
  -drive if=none,media=cdrom,format=raw,readonly=on
  -device virtio-scsi-pci
  -device scsi-cd

When direct kernel booting with scsi-cd, if the kernel command line
contains "rw", append "ro" to override it since CD-ROMs are
read-only.

Co-developed-by: Claude Opus 4.6 <noreply@anthropic.com>
2026-04-02 16:02:43 +02:00
Daan De Meyer 1b7a42178a vmspawn: use PTY for native console to avoid QEMU O_NONBLOCK issue
QEMU's stdio chardev sets O_NONBLOCK on both stdin and stdout (see
chardev/char-stdio.c [1] and chardev/char-fd.c [2]). Since forked
processes share file descriptions, and on a terminal all three stdio
fds typically reference the same file description, this affects our
own stdio too.

Avoid this by using a PTY with chardev serial instead of chardev
stdio for native console mode, matching the approach already used
for interactive and read-only modes. The PTY forwarder shovels bytes
transparently between our stdio and QEMU's PTY using the new
PTY_FORWARD_DUMB_TERMINAL and PTY_FORWARD_TRANSPARENT flags, which
disable terminal decoration (background tinting, window title, OSC
context) and escape sequence handling (Ctrl-] exit, hotkeys)
respectively.

The chardev is configured with mux=on so the QEMU monitor remains
accessible via Ctrl-a c.

Also dedup CONSOLE_NATIVE, CONSOLE_READ_ONLY, and CONSOLE_INTERACTIVE
handling by using fallthrough, with the only differences being the
ptyfwd flags, mux setting, and monitor section.

[1] https://gitlab.com/qemu-project/qemu/-/blob/master/chardev/char-stdio.c
[2] https://gitlab.com/qemu-project/qemu/-/blob/master/chardev/char-fd.c

Co-developed-by: Claude Opus 4.6 <noreply@anthropic.com>
2026-04-02 15:12:52 +02:00
Daan De Meyer b68898530e ptyfwd: Add transparent flag 2026-04-02 15:12:52 +02:00
Daan De Meyer e306f4d123 stub: Determine the correct serial console from the ACPI device path
Instead of requiring exactly one serial device and assuming ttyS0,
extract the COM port index from the ACPI device path and use the
uart I/O port address format for the console= kernel argument.

On x86, the ACPI UID for PNP0501 (16550 UART) maps directly to the
COM port number: UID 0 = COM1 (0x3F8), UID 1 = COM2 (0x2F8), etc.
The I/O port addresses are fixed in the kernel (see
arch/x86/include/asm/serial.h). Using the console=uart,io,<addr>
format (see Documentation/admin-guide/kernel-parameters.txt) addresses
the UART by I/O port directly rather than relying on ttyS naming,
and also provides early console output before the full serial driver
loads.

Restrict the entire serial console auto-detection to x86. On non-x86
(e.g. ARM with PL011 UARTs), displays may be available without GOP
(e.g. simple-framebuffer via device tree), serial device indices are
assigned dynamically during probe rather than being fixed to I/O port
addresses, and the kernel has its own console auto-detection via DT
stdout-path.

When ConOut has no device path (ConSplitter), all text output handles
are enumerated. If multiple handles have PNP0501 UART nodes with
different UIDs, bail out rather than guessing.

Add ACPI_DP device path subtype, ACPI_HID_DEVICE_PATH struct, and
EISA_PNP_ID() macro to device-path.h for parsing ACPI device path
nodes. Remove MSG_UART_DP, device_path_has_uart(), count_serial_devices()
and proto/serial-io.h (no longer needed).

Move all the console logic to console.c as well.
2026-04-02 14:58:42 +02:00
Daan De Meyer 1653ac8db5 stub: Do a single PCI read to get the vendor and device ID 2026-04-02 14:58:42 +02:00
Daan De Meyer f9339b9087 stub: Drop needless enum value assignment
Follow up for 45e4df9a33
2026-04-02 14:58:42 +02:00
Lennart Poettering 353e220a95 update TODO 2026-04-02 14:13:54 +02:00
Daan De Meyer 0e187fae07 shared/gpt: add gpt_probe() for GPT header and partition entry reading
Add gpt_probe() which probes for a GPT partition table at various sector
sizes (512-4096) and optionally returns the header and partition entries.
Returns the detected sector size on success, 0 if no GPT was found, or
negative errno on error.

Refactor probe_sector_size() in dissect-image.c to be a thin wrapper
around gpt_probe().

Co-developed-by: Claude Opus 4.6 <noreply@anthropic.com>
2026-04-02 13:59:55 +02:00
Mike Yuan 08eff23a2d mount-util: restore compat for kernels without MOUNT_ATTR_NOSYMFOLLOW (< 5.14)
Follow-up for 6753bd8a2f

Replaces #41341
2026-04-02 12:33:21 +01:00
Luca Boccassi 34ff7243e1 networkd: fix assert with IPFamily=both in MobileNetwork conf and add minimal mock for test coverage (#41402) 2026-04-02 12:28:04 +01:00
Michael Ferrari ecf2329e14 Initialize roothash when populating sig partition
This allows one to specify `CopyBlocks=` on both the `Verity=` data and
hash partition and the signature is recreated correctly.
2026-04-02 13:21:08 +02:00
Michael Vogt ebdc91263a test: tweak TEST-74-AUX-UTILS.varlinkctl.sh varlink test
This commit tweaks the TEST-74-AUX-UTILS.varlinkctl.sh code
to use `systemd-notify --fork $UPGRADE_SERVER` instead of
the (ugly) timeout.

This also fixes a stale comment in around
`Test --upgrade with stdin redirected from a regular file`.

Thanks to Daan for suggesting this!
2026-04-02 13:20:17 +02:00
Michael Vogt f6c8b35529 varlinkctl: simplify error handling in exec_with_listen_fds
Instead of exiting in exec_with_listen_fds() just return an error
and do the actual _exit() in the caller. Much nicer this way.

Thanks for Lennart for suggesting this.
2026-04-02 13:20:17 +02:00
Michael Vogt f180ff5983 sd-varlink: fix fd handling in upgrade code path
This commit fixes an issue with the fd handling in
sd_varlink_call_and_upgrade() when one direction of the output
FDs is unset.

Thanks to Lennart for spotting this and suggesting the fix.
2026-04-02 13:20:17 +02:00
Daan De Meyer 73c0a79789 vmspawn: Use qemu config file for smp and memory
Pass -no-user-config while we're at it to avoid loading qemu config
from /etc which is more likely to cause hard to debug issues rather
than do something useful.
2026-04-02 13:19:40 +02:00
Daan De Meyer fd1b84af98 vmspawn: pass --log-level=error and --modcaps=-mknod to virtiofsd
Reduce virtiofsd log noise by setting --log-level=error, and drop
the unnecessary mknod capability with --modcaps=-mknod, matching
mkosi's virtiofsd invocation.

Co-developed-by: Claude Opus 4.6 <noreply@anthropic.com>
2026-04-02 13:03:36 +02:00
Kit Dallege adc4757b9e docs: fix misleading VM/machined documentation
Fix two issues in WRITING_VM_AND_CONTAINER_MANAGERS.md:

1. The Host OS Integration section implied that -M switch and
   machinectl shell/login work for VMs, but they currently only
   work for containers. Add a note clarifying this limitation.

2. The Guest OS Integration section said "there's only one" VM
   integration API (SMBIOS Product UUID), but VM_INTERFACE.md
   documents five. Replace the outdated single-API description
   with a reference to VM_INTERFACE.md listing all five.

Fixes #40935

Co-developed-by: Claude Opus 4.6 <noreply@anthropic.com>
2026-04-02 12:55:33 +02:00
Michael Ferrari 189d5c020b Support CopyBlocks= for Verity={hash,sig}
This enables deriving the minimum size of the `Verity=hash` partition
using the `Verity=` logic when the size of the `Verity=data` partition
is bigger than the `CopyBlocks=` target.

This enables using `Minimize=true` for an "installer image" and later
using sd-repart to install to a system with reserve space for future
updates by specifying `Size{Min,Max}Bytes=` only in the `Verity=data`
partition, without needing to hardcode the corresponding size for the
`Verity=hash` partition.

While not strictly necessary for `Verity=signature` partitions (since
they have a fixed size) there isn't too much reason to not support it,
since then you can still specify `VerityMatchKey=` to indicate that
the partition is logically still part of that group of partitions.

We ensure that if one of the hash uses `CopyBlocks=` that the data
partition does so as well. Similarly if the signature partition does it
checks that the hash and data partition do so as well. This is to
minimize the chance of accidental misconfiguration of mixing
`CopyBlocks=auto` and `CopyBlocks=<path>` and of manually populating
partitions while hash/sig partitions are copied from existing sources.
2026-04-02 10:45:32 +02:00
Daan De Meyer ca347a9494 vmspawn: Pass extra cmdline via smbios when direct booting a UKI
-cmdline doesn't work when direct booting a UKI so use SMBIOS instead.
2026-04-02 10:18:48 +02:00
Christian Hesse 7ae0a58815 hwdb/keyboard: fix enter key for X+ piccolo
The main enter key gives a code for keypad one... Map it to
regular enter key.
2026-04-01 18:23:35 +01:00
Luca Boccassi 7918e02fc7 Two followups for recent commits (#41457) 2026-04-01 18:20:58 +01:00
Daan De Meyer c8a68dc7b3 nspawn: move boot_id and kmsg backing file creation to outer child
Follow-up for af5126568a ("nspawn: keep backing files for boot_id and
kmsg bind mounts alive").

The backing files for the boot_id and kmsg bind mounts were previously
created in the inner child. However, /run/host/ is remounted read-only
by mount_all() in the inner child (via the MOUNT_IN_USERNS mount table
entry) before setup_boot_id() and setup_kmsg() run, so creating files
there would fail with EROFS.

Fix this by splitting the file creation into separate functions
(setup_boot_id_file() and setup_kmsg_fifo()) that run in the outer
child, where /run/host/ is still writable. The bind mounts onto /proc
remain in the inner child, since procfs is only mounted there.

Also move the backing files from /run/ to /run/host/ and drop the dot
prefix, since /run/host/ is the container-manager-owned namespace and
there is no need to hide these files there. Additionally, apply
userns_lchown() to the created files, matching the convention used by
all other outer child functions that create files in the container.
2026-04-01 18:19:55 +01:00
Zbigniew Jędrzejewski-Szmek 09b0a6ab4f units: allow systemd-report-basic@.service to run in early boot 2026-04-01 16:38:27 +02:00
Zbigniew Jędrzejewski-Szmek 5d0a953960 report-basic: lock down the service
The basic approach is copied from systemd-journal-gatewayd.service,
with some additions to lock down unneeded network access.
2026-04-01 16:38:14 +02:00
Zbigniew Jędrzejewski-Szmek b47139e489 report: move facts generator out of PID1 into a separate varlink service
The collection of facts is entirely unprivileged and has very little to
do with PID1. PID1 is privileged and single-threaded and a point of
contention, so we shouldn't put things in PID1 that don't need to be
there. A separate service can be enabled/disabled/started/stopped at
will, is easy to sandbox, etc. If it turns out to be necessary to
collect some facts through PID1 in the future, we can always add a
smaller facts endpoint to PID1 again.
2026-04-01 16:38:11 +02:00
Zbigniew Jędrzejewski-Szmek 45571d2fa3 Two claude fixes (#41451) 2026-04-01 16:30:04 +02:00
Zbigniew Jędrzejewski-Szmek d0f482d342 basic/terminal-util: flush stray input when terminal query fails
Follow-up for da69848791.
2026-04-01 16:01:58 +02:00
Zbigniew Jędrzejewski-Szmek e1342e063b test-efi-string: add more cases
This excercises the patterns used in
45e4df9a33.
2026-04-01 16:01:58 +02:00
Daan De Meyer 60b10fa0f1 ci: base64 encode multiline strings in structured output
Avoid claude trying to escape characters in the structured JSON by
just having it base64 encode the multiline strings in the structured
JSON.
2026-04-01 15:47:34 +02:00
Daan De Meyer bedd902f9a ci: Delay instructions to read pr-context.json until 2nd phase
The main agent doesn't need to read pr-context.json until all
reviews have finished. This should prevent it from passing unnecessary
data from pr-context.json in the prompt to its subagents, which can just
read that file themselves when needed.
2026-04-01 15:46:20 +02:00
Zbigniew Jędrzejewski-Szmek c26f432729 shared/options: allow output ret_arg to be omitted
Sometimes we have a parser which would never use the argument.
2026-04-01 15:34:45 +02:00
Zbigniew Jędrzejewski-Szmek 3220a1c57f report: rename variables/fields, use string table
Noop refactoring to make naming more consistent.
2026-04-01 15:34:45 +02:00
Yaping Li f60d5985e5 report: implement facts interface 2026-04-01 15:34:45 +02:00
Zbigniew Jędrzejewski-Szmek e11158af38 report: downgrade message for org.varlink.service.MethodNotFound
We now have three kinds of endpoints under /run/systemd/report/:
those that implement facts, those that implement metrics, and those that
implement both. Let's downgrade the message to avoid pointless warnings.
2026-04-01 15:34:45 +02:00
Daan De Meyer 45e4df9a33 stub: auto-detect console device and append console= to kernel command line
The Linux kernel does not reliably auto-detect serial consoles on
headless systems. While the docs claim serial is used as a fallback
when no VGA card is found, in practice CONFIG_VT's dummy console
(dummycon) registers early and satisfies the kernel's console
requirement, preventing the serial fallback from ever triggering. The
ACPI SPCR table can help on ARM/RISC-V where QEMU generates it, but
x86 QEMU does not produce SPCR, and SPCR cannot describe virtio
consoles at all. This means UKIs booted via sd-stub in headless VMs
produce no visible console output unless console= is explicitly
passed on the kernel command line.

Fix this by having sd-stub auto-detect the console type and append an
appropriate console= argument when one isn't already present.

Detection priority:

1. VirtIO console PCI device (vendor 0x1AF4, device 0x1003): if
   exactly one is found, append console=hvc0. This takes highest
   priority since a VirtIO console is explicitly configured by the
   VMM (e.g. systemd-vmspawn's virtconsole device). If multiple
   VirtIO console devices exist, we cannot determine which hvc index
   is correct, so we skip this path entirely.

2. EFI Graphics Output Protocol (GOP): if present, don't add any
   console= argument. The kernel will use the framebuffer console by
   default, and adding a serial console= would redirect the primary
   console away from the display.

3. Serial console: first, we count the total number of serial devices
   via EFI_SERIAL_IO_PROTOCOL. If there are zero or more than one,
   we bail out — with multiple UARTs, the kernel assigns ttyS indices
   based on its own enumeration order and we cannot determine which
   index the console UART will receive. Only when exactly one serial
   device exists (guaranteeing it will be ttyS0) do we proceed to
   verify it's actually used as a console by checking for UART device
   path nodes (MESSAGING_DEVICE_PATH + MSG_UART_DP). The firmware's
   ConOut handle is checked first; if it has no device path (common
   with OVMF's ConSplitter virtual handle when using -nographic
   -nodefaults), we fall back to enumerating all
   EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL handles and checking each one's
   device path. The architecture-specific console argument is then
   appended:
   - x86:     console=ttyS0
   - ARM:     console=ttyAMA0
   - Others:  console=ttyS0 (RISC-V, LoongArch, MIPS all use ttyS0)

Note on OVMF's VirtioSerialDxe: it exposes virtio serial ports with
the same UART device path nodes as real serial ports (ACPI PNP 0x0501
+ MSG_UART_DP), making them indistinguishable from real UARTs via
device path inspection alone. This is why we check for the VirtIO
console PCI device via EFI_PCI_IO_PROTOCOL before falling back to
device path analysis.

Also add a minimal EFI_PCI_IO_PROTOCOL definition (proto/pci-io.h)
with just enough to call Pci.Read for vendor/device ID enumeration,
and add the MSG_UART_DP subtype to the device path header.

Co-developed-by: Claude Opus 4.6 <noreply@anthropic.com>
2026-04-01 15:32:13 +02:00