如何使用 efivars 检索 BIOS 使用的控制台端口的详细信息?

How to retrieve details of the console port used by BIOS using efivars?

作为 linux 安装的一部分,我想通过基于 Intel 的平台的内核命令行设置“控制台设备属性”(例如,console=ttyS0,115200n1)。

没有 VGA 控制台,只有通过 COM 接口的串行控制台。 在这些系统上,BIOS 已经具有使用适当的串行端口进行交互所需的设置。

我看到 EFI 有变量 ConIn、ConOut、ConErr,我可以从 /sys/firmware/efi 中看到这些变量,但无法解码其中的内容。

是否可以通过检查 efi 变量来识别 BIOS 正在使用哪个 COM 端口。

示例,我的盒子上的 EFI 变量。

root@linux:~# efivar -p -n 8be4df61-93ca-11d2-aa0d-00e098032b8c-ConOut
GUID: 8be4df61-93ca-11d2-aa0d-00e098032b8c
Name: "ConOut"
Attributes:
        Non-Volatile
        Boot Service Access
        Runtime Service Access
Value:
00000000  02 01 0c 00 d0 41 03 0a  00 00 00 00 01 01 06 00  |.....A..........|
00000010  00 1a 03 0e 13 00 00 00  00 00 00 c2 01 00 00 00  |................|
00000020  00 00 08 01 01 03 0a 18  00 9d 9a 49 37 2f 54 89  |...........I7/T.|
00000030  4c a0 26 35 da 14 20 94  e4 01 00 00 00 03 0a 14  |L.&5.. .........|
00000040  00 53 47 c1 e0 be f9 d2  11 9a 0c 00 90 27 3f c1  |.SG..........'?.|
00000050  4d 7f 01 04 00 02 01 0c  00 d0 41 03 0a 00 00 00  |M.........A.....|
00000060  00 01 01 06 00 00 1f 02  01 0c 00 d0 41 01 05 00  |............A...|
00000070  00 00 00 03 0e 13 00 00  00 00 00 00 c2 01 00 00  |................|
00000080  00 00 00 08 01 01 03 0a  18 00 9d 9a 49 37 2f 54  |............I7/T|
00000090  89 4c a0 26 35 da 14 20  94 e4 01 00 00 00 03 0a  |.L.&5.. ........|
000000a0  14 00 53 47 c1 e0 be f9  d2 11 9a 0c 00 90 27 3f  |..SG..........'?|
000000b0  c1 4d 7f ff 04 00                                 |.M....          |
root@linux:~#

在我的例子中,因为我知道控制台端口是一个“串行 IOPORT”, 我现在可以得到详细信息如下。 一种。弄个/sys/firmware/acpi/tables/SPCtable。 b.读取地址偏移量 44-52。实际上一个最后两个字节就足够了。

参考: 一种。 https://docs.microsoft.com/en-us/windows-hardware/drivers/serports/serial-port-console-redirection-table 表示

Base Address    12  40  
The base address of the Serial Port register set described using the ACPI Generic Address Structure.

0 = console redirection disabled
Note:

COM1 (0x3F8) would be:

Integer Form: 0x 01 08 00 00 00000000000003F8
Viewed in Memory: 0x01080000F803000000000000
COM2 (Ox2F8) would be:

Integer Form: 0x 01 08 00 00 00000000000002F8
Viewed in Memory: 0x01080000F802000000000000

UEFI 规范中描述了 ConOut 变量的内容 - current version (2.8B):

3.3 - 全局定义的变量:

| Name    | Attribute  | Description                                    |
|---------|------------|------------------------------------------------|
| ConOut  | NV, BS, RT | The device path of the default output console. |

关于设备路径的信息,我们有:

10 - 协议 - 设备路径协议:

除了设备路径的初始描述之外,table44 向您展示了通用设备路径节点结构,我们可以从中开始解码变量的内容。

第一个节点的类型是0x02,告诉我们这个节点描述了一个0x000c字节长度的ACPI设备路径。现在跳转到 10.3.3 - ACPI 设备路径和 table 52,它告诉我们 1) 这是正确的 table(子类型 0x01)和 2) 默认 ConOut 具有0x0a03410d 的 _HID 和 0.

的 _UID

下一个节点的类型为 0x01 - 硬件设备路径,在 10.3.2 中进一步描述,在本例中 table 46(SubType0x01) 用于 PCI 设备路径。 下一个节点描述了 UART 类型的消息传递设备路径等等...

不过,这只告诉您 UEFI 认为什么是它的默认控制台,SPCR 是操作系统应该查看的串行控制台。不幸的是,在 X86 上,linux 内核很容易忽略 SPCR,除了 earlycon。我想这就是您要解决的问题。最好在内核开发列表上开始一些关于是否修复该问题并让 X86 像 ARM64 一样工作的讨论。