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