Bug 299090 - loader.efi: hw.uart.console in loader.conf is replaced by the SPCR value
Summary: loader.efi: hw.uart.console in loader.conf is replaced by the SPCR value
Status: New
Alias: None
Product: Base System
Classification: Unclassified
Component: kern (show other bugs)
Version: 15.1-RELEASE
Hardware: Any Any
: --- Affects Some People
Assignee: Warner Losh
URL:
Keywords:
Depends on:
Blocks:
 
Reported: 2026-10-03 11:57 UTC by Rick Richard
Modified: 2026-10-08 19:46 UTC (History)
2 users (show)

See Also:


Attachments
[PATCH] loader.efi: Don't replace a hw.uart.console set by the user (1.48 KB, patch)
2026-10-03 11:57 UTC, Rick Richard
no flags Details | Diff

Note You need to log in before you can comment on or make changes to this bug.
Description Rick Richard 2026-10-03 11:57:30 UTC
Created attachment 275337 [details]
[PATCH] loader.efi: Don't replace a hw.uart.console set by the user

DESCRIPTION

When the firmware provides an ACPI SPCR table, a hw.uart.console line in
loader.conf has no effect.  At the OK prompt, "show hw.uart.console" prints
the value derived from the SPCR, not the one from loader.conf.

check_acpi_spcr() sets hw.uart.console unconditionally.  It is called from
parse_uefi_con_out(), which runs once in main() and again from
efi_console.c whenever the console mode is updated.  loader.lua runs
efi-autoresizecons right after config.load(), so the order is:

  1. main(): hw.uart.console = SPCR value
  2. loader.conf: hw.uart.console = the user's value (setenv succeeds)
  3. efi-autoresizecons -> parse_uefi_con_out() -> check_acpi_spcr():
     hw.uart.console = SPCR value again

I confirmed step 2 by printing from config.lua's setEnv(): the user's value
is set and reads back, and it is gone by the time local.lua runs.  Setting
the variable at the OK prompt works, because nothing runs the SPCR code
after that.

This leaves no persistent way to correct or override what the SPCR says,
for example when the table describes the UART wrongly or the user wants a
different port or speed.

Related: PR 292206, fixed by d82698ac68 ("loader.efi: Only use SPCR if
enabled"), was a case of the SPCR producing a bad hw.uart.console.  Its
commit message notes "While one could unset this value to boot, you
couldn't do that automatically very easily."  This is the same problem in
general: with this patch, loader.conf can correct whatever the SPCR says.

The attached patch skips the SPCR translation when hw.uart.console is
already set, as the x86 code in bootinfo.c already does ("if someone
specifically setup hw.uart.console, don't override that").  At the first
call nothing has set it yet, so the default behaviour doesn't change.


AFFECTED VERSIONS

main, stable/15 and releng/15.1.  check_acpi_spcr() came in with
70253b538f68 ("loader.efi: Parse SPCR table entry in ACPI tables"), so 14.x
is not affected.


HOW TO REPEAT

On an EFI system whose firmware provides SPCR, put a hw.uart.console line
in /boot/loader.conf, stop at the OK prompt and run
"show hw.uart.console".

I used QEMU's riscv virt machine with its bundled EDK2 firmware, which
provides SPCR, and hw.uart.console="mm:0x10000000,rs:0,br:115200".  That
table gives a 32-bit register stride for a byte-spaced UART (being reported
to QEMU), so the SPCR value can't boot the kernel and the loader.conf value
is needed.


TESTED

riscv64 15.1-RELEASE-p3 world, kernel with the uart_cpu_fdt.c NULL-tag fix
from PR 299089, hw.uart.console in loader.conf:

  loader             result
  15.1-RELEASE-p3    loader.conf value replaced; kernel faults (rs:2)
  with patch         loader.conf value kept; boots to multi-user

Without a loader.conf setting the patched loader passes the SPCR value as
before.  Not tested on arm64 or amd64.


ATTACHMENTS

0001-loader.efi-Don-t-replace-a-hw.uart.console-set-by-th.patch
  against main ff2efe65a89a