通过串口与UEFI交互

幽兰的UEFI固件默认开启了串口打印和串口控制台功能,因此,大家可以使用很多经典的串口工具来与UEFI进行交互,比如接收调试信息,进入UEFI外壳,执行外壳命令等。

1. 硬件连接

最方便的连接方式是使用格蠹的SD串口套件,一端插入幽兰的SD口,另一端插到普通PC的USB口。

2. 开启软件

连接好硬件后,在PC打开你喜欢的串口软件,比如MobaXterm,点击Session建立一个新的会话,波特率输入1500000(5个0),串口编号选Choose at session start,这样串口号变化时也不用改会话设置。

3. 接收UEFI的调试信息

开启串口会话后,重启幽兰代码本,顺利的话,就会接收到调试信息。

注意:因为sd转接头的串口信号是与SD卡信号复用的,所以需要软件初始化后才可以接收到。因为此,使用SD卡转接的串口可能错过一些早期的行为。使用主板上的接头可以接收到更多的信息,包括来自ATF固件的信息。

4. 进入UEFI Shell

UEFI具有强大的人机交互能力,包括图形界面和命令外壳。大家可以在收到UEFI的调试信息后,按ESC键(幽兰上按,或者在MobaXterm的串口会话按)进入UEFI Shell

[Bds]Booting UEFI Shell
[Bds] Expand MemoryMapped(0xB,0x3EC6F000,0x3F61DEBF)/FvFile(7C04A583-9E3E-4F1C-AD65-E05268D0B4D1) -> MemoryMapped(0xB,0x3EC6F000,0x3F61DEBF)/FvFile(7C04A583-9E3E-4F1C-AD65-E05268D0B4D1)
add-symbol-file /gewu/uefi/edk2-rk3588/workspace/Build/YourLand/DEBUG_GCC/AARCH64/ShellPkg/Application/Shell/Shell/DEBUG/Shell.dll 0xE9C55000
Loading driver at 0x000E9C54000 EntryPoint=0x000E9C5B350 Shell.efi
[HiiDatabase]: Memory allocation is required after ReadyToBoot, which may change memory map and cause S4 resume issue.
~Filed to add Hii package
UEFI Interactive Shell v2.2
EDK II
UEFI v2.70 (EDK II, 0x00010000)

进入UEFI Shell后,就可以执行各种UEFI命令了,比如输入help命令可以列出所有其它命令。

5. 通过串口控制台操作UEFI图形界面

有趣的是,UEFI的图形界面也可以显示在串口控制台中,而且而可以按方向键来切换菜单。

通过串口操作界面支持的虽然不完美,但是能通过串口操作固件阶段的图形界面还是让人很赞的。

6. 观察设备

有两条命令都可以用来列出系统里的设备。
一条是devtree,它可以按设备关系以树形列出所有设备。

Shell> devtree
 Ctrl[04] MemoryMapped(0xB,0x200000,0x6FFFFF)
 Ctrl[05] MemoryMapped(0xB,0x3EC6F000,0x3F61DEBF)
 Ctrl[19] VenHw(FC0CB972-21DF-44D2-92A5-789899CBF661)
 Ctrl[1D] VenHw(D3987D4B-971A-435F-8CAF-4967EB627241)/Uart(1500000,8,N,1)
   Ctrl[BD] VenHw(D3987D4B-971A-435F-8CAF-4967EB627241)/Uart(1500000,8,N,1)/VenM
sg(7D916D80-5BB1-458C-A48F-E25FDD51EF94)
     Ctrl[6D] Unknown
     Ctrl[6E] Unknown
     Ctrl[6F] Unknown
 Ctrl[47] VenHw(10F41C33-A468-42CD-85EE-7043213F73A3)
 Ctrl[4F] VenHw(9335A854-4B88-11EC-A8EE-F42A7DCB925D,000000000200000000000000)
   Ctrl[AD] VenHw(9335A854-4B88-11EC-A8EE-F42A7DCB925D,000000000200000000000000)
/VenHw(ADC1901B-B83C-4831-8F59-70898F26571E)/Ctrl(0x20051)
 Ctrl[53] VenHw(28A03FF4-12B3-4305-A417-BB1A4F94081E)
 Ctrl[54] VenHw(2A46715F-3581-4A55-8E73-2B769AAA30C5)
 Ctrl[57] VenHw(7CA1024F-EB17-11E5-9DBA-28D2447C4829)
 Ctrl[58] VenHw(B0EAE4F8-9A04-4C6D-A748-793DAA0F65DF)
 Ctrl[5D] PcieRoot(0x0)
   Ctrl[B5] PcieRoot(0x0)/Pci(0x0,0x0)
   Ctrl[B6] PcieRoot(0x0)/Pci(0x0,0x0)/Pci(0x0,0x0)
     Ctrl[C1] PcieRoot(0x0)/Pci(0x0,0x0)/Pci(0x0,0x0)/NVMe(0x1,12-00-00-00-00-00
-00-00)
       Ctrl[C2] PcieRoot(0x0)/Pci(0x0,0x0)/Pci(0x0,0x0)/NVMe(0x1,12-00-00-00-00-
00-00-00)/HD(1,GPT,CD9F10FB-4904-0848-93A6-2E4C64F5268B,0xF000,0x200000)
       Ctrl[C3] PcieRoot(0x0)/Pci(0x0,0x0)/Pci(0x0,0x0)/NVMe(0x1,12-00-00-00-00-
00-00-00)/HD(2,GPT,1E64B7AF-C9C3-F042-A6AE-D879E58995A6,0x20F000,0x29C4FDF)
 Ctrl[A7] VenHw(100C2CFA-B586-4198-9B4C-1683D195B1DA)
   Ctrl[A8] VenHw(100C2CFA-B586-4198-9B4C-1683D195B1DA)/HD(1,GPT,0F747F5E-EFDB-4
A3B-8C5F-ED1A6AFD01B6,0x800,0x32000)
   Ctrl[A9] VenHw(100C2CFA-B586-4198-9B4C-1683D195B1DA)/HD(2,GPT,D175CA65-9BD2-4
D2C-AF09-510719479A4E,0x32800,0x8000)
   Ctrl[AA] VenHw(100C2CFA-B586-4198-9B4C-1683D195B1DA)/HD(3,GPT,AD3DA2A3-6660-4
5F0-A7B8-73B50A020695,0x3A800,0xE513000)
   Ctrl[AB] VenHw(100C2CFA-B586-4198-9B4C-1683D195B1DA)/HD(4,GPT,D9B32D7E-598A-4
3A5-8208-E41024402A02,0xE54D800,0x129800)
 Ctrl[AC] VenHw(EAF89AD8-92E1-11EC-B51D-F42A7DCB925D)
   Ctrl[6E] Unknown
   Ctrl[6F] Unknown
 Ctrl[AE] VenHw(0D51905B-B77E-452A-A2C0-ECA0CC8D514A,000000FC0000000000)
 Ctrl[AF] VenHw(0D51905B-B77E-452A-A2C0-ECA0CC8D514A,000040FC0000000000)
   Ctrl[B7] VenHw(0D51905B-B77E-452A-A2C0-ECA0CC8D514A,000040FC0000000000)/USB(0
x0,0x0)
     Ctrl[6D] Unknown
 Ctrl[B0] VenHw(0D51905B-B77E-452A-A2C0-ECA0CC8D514A,0000D0FC0000000000)
 Ctrl[B1] VenHw(0D51905B-B77E-452A-A2C0-ECA0CC8D514A,000080FC0000000000)
   Ctrl[B8] VenHw(0D51905B-B77E-452A-A2C0-ECA0CC8D514A,000080FC0000000000)/USB(0
x0,0x0)
   Ctrl[B9] VenHw(0D51905B-B77E-452A-A2C0-ECA0CC8D514A,000080FC0000000000)/USB(0
x0,0x1)
 Ctrl[B2] VenHw(54BCE5E6-BAAE-488A-8267-C0857FB4E805,000084FC)
 Ctrl[B3] VenHw(0D51905B-B77E-452A-A2C0-ECA0CC8D514A,000088FC0000000000)
   Ctrl[BA] VenHw(0D51905B-B77E-452A-A2C0-ECA0CC8D514A,000088FC0000000000)/USB(0
x0,0x0)
   Ctrl[BB] VenHw(0D51905B-B77E-452A-A2C0-ECA0CC8D514A,000088FC0000000000)/USB(0
x0,0x0)/USB(0x0,0x0)
     Ctrl[6D] Unknown
   Ctrl[BC] VenHw(0D51905B-B77E-452A-A2C0-ECA0CC8D514A,000088FC0000000000)/USB(0
x0,0x0)/USB(0x0,0x1)
 Ctrl[B4] VenHw(54BCE5E6-BAAE-488A-8267-C0857FB4E805,00008CFC)
 Ctrl[BF] VenHw(462CAA21-7614-4503-836E-8AB6F4662331)
 Ctrl[C0] VenHw(102579A0-3686-466E-ACD8-80C087044F4A)
 Ctrl[C4] VenHw(1DDDBE15-481D-4D2B-8277-B191EAF66525)
 Ctrl[C5] VenHw(165A028F-0BB2-4B5F-8747-77592E3F6499)
 Ctrl[C6] VenHw(8E6D99EE-7531-48F8-8745-7F6144468FF2)

另一条命令是devices,它是以表格形式列出所有设备。

Shell> devices
     T   D
     Y C I
     P F A
CTRL E G G #P #D #C  Device Name
==== = = = == == === =========================================================
  1D R - -  0  1   1 VenHw(D3987D4B-971A-435F-8CAF-4967EB627241)/Uart(1500000,8,
N,1)
  4F R - -  0  2   1 VenHw(9335A854-4B88-11EC-A8EE-F42A7DCB925D,0000000002000000
00000000)
  5D R - -  0  1   2 PcieRoot(0x0)
  A7 R - -  0  2   4 VenHw(100C2CFA-B586-4198-9B4C-1683D195B1DA)
  A8 D - -  1  2   0 VenHw(100C2CFA-B586-4198-9B4C-1683D195B1DA)/HD(1,GPT,0F747F
5E-EFDB-4A3B-8C5F-ED1A6AFD01B6,0x800,0x32000)
  A9 D - -  1  1   0 VenHw(100C2CFA-B586-4198-9B4C-1683D195B1DA)/HD(2,GPT,D175CA
65-9BD2-4D2C-AF09-510719479A4E,0x32800,0x8000)
  AA D - -  1  1   0 VenHw(100C2CFA-B586-4198-9B4C-1683D195B1DA)/HD(3,GPT,AD3DA2
A3-6660-45F0-A7B8-73B50A020695,0x3A800,0xE513000)
  AB D - -  1  1   0 VenHw(100C2CFA-B586-4198-9B4C-1683D195B1DA)/HD(4,GPT,D9B32D
7E-598A-43A5-8208-E41024402A02,0xE54D800,0x129800)
  AC R - -  0  4   2 VenHw(EAF89AD8-92E1-11EC-B51D-F42A7DCB925D)
  AD D - -  1  0   0 VenHw(9335A854-4B88-11EC-A8EE-F42A7DCB925D,0000000002000000
00000000)/VenHw(ADC1901B-B83C-4831-8F59-70898F26571E)/Ctrl(0x20051)
  AE R - -  0  3   0 VenHw(0D51905B-B77E-452A-A2C0-ECA0CC8D514A,000000FC00000000
00)
  AF R - -  0  3   1 VenHw(0D51905B-B77E-452A-A2C0-ECA0CC8D514A,000040FC00000000
00)
  B0 R - -  0  3   0 VenHw(0D51905B-B77E-452A-A2C0-ECA0CC8D514A,0000D0FC00000000
00)
  B1 R - -  0  3   2 VenHw(0D51905B-B77E-452A-A2C0-ECA0CC8D514A,000080FC00000000
00)
  B2 R - -  0  2   0 VenHw(54BCE5E6-BAAE-488A-8267-C0857FB4E805,000084FC)
  B3 R - -  0  3   3 VenHw(0D51905B-B77E-452A-A2C0-ECA0CC8D514A,000088FC00000000
00)
  B4 R - -  0  2   0 VenHw(54BCE5E6-BAAE-488A-8267-C0857FB4E805,00008CFC)
  B5 D - -  1  0   0 PcieRoot(0x0)/Pci(0x0,0x0)
  B6 B - -  1  1   1 PcieRoot(0x0)/Pci(0x0,0x0)/Pci(0x0,0x0)
  B7 B - -  1  2   1 VenHw(0D51905B-B77E-452A-A2C0-ECA0CC8D514A,000040FC00000000
00)/USB(0x0,0x0)
  B8 D - -  1  0   0 VenHw(0D51905B-B77E-452A-A2C0-ECA0CC8D514A,000080FC00000000
00)/USB(0x0,0x0)
  B9 D - -  1  0   0 VenHw(0D51905B-B77E-452A-A2C0-ECA0CC8D514A,000080FC00000000
00)/USB(0x0,0x1)
  BA D - -  1  0   0 VenHw(0D51905B-B77E-452A-A2C0-ECA0CC8D514A,000088FC00000000
00)/USB(0x0,0x0)
  BB B - -  1  3   1 VenHw(0D51905B-B77E-452A-A2C0-ECA0CC8D514A,000088FC00000000
00)/USB(0x0,0x0)/USB(0x0,0x0)
  BC D - -  1  0   0 VenHw(0D51905B-B77E-452A-A2C0-ECA0CC8D514A,000088FC00000000
00)/USB(0x0,0x0)/USB(0x0,0x1)
  BD B - -  1  5   3 VenHw(D3987D4B-971A-435F-8CAF-4967EB627241)/Uart(1500000,8,
N,1)/VenMsg(7D916D80-5BB1-458C-A48F-E25FDD51EF94)
  C1 B - -  1  2   2 PcieRoot(0x0)/Pci(0x0,0x0)/Pci(0x0,0x0)/NVMe(0x1,12-00-00-0
0-00-00-00-00)
  C2 D - -  1  2   0 PcieRoot(0x0)/Pci(0x0,0x0)/Pci(0x0,0x0)/NVMe(0x1,12-00-00-0
0-00-00-00-00)/HD(1,GPT,CD9F10FB-4904-0848-93A6-2E4C64F5268B,0xF000,0x200000)
  C3 D - -  1  1   0 PcieRoot(0x0)/Pci(0x0,0x0)/Pci(0x0,0x0)/NVMe(0x1,12-00-00-0
0-00-00-00-00)/HD(2,GPT,1E64B7AF-C9C3-F042-A6AE-D879E58995A6,0x20F000,0x29C4FDF)

7. 观察UEFI的接口表

熟悉ACPI的格友知道,EFI的核心功能之一是为OS提供统一的硬件接口,而它提供接口的基本方式便是内存里的数据表。
直接执行dmem命令,便会列出接口表的目录。

Shell> dmem
Memory Address 00000000EFFD0018 78 Bytes
  EFFD0018: 49 42 49 20 53 59 53 54-46 00 02 00 78 00 00 00  *IBI SYSTF...x...*
  EFFD0028: BE 1D A1 47 00 00 00 00-18 E3 FD EF 00 00 00 00  *...G............*
  EFFD0038: 00 00 01 00 00 00 00 00-18 69 22 EF 00 00 00 00  *.........i".....*
  EFFD0048: 00 E4 A0 EA 00 00 00 00-98 EA BB EE 00 00 00 00  *................*
  EFFD0058: 20 4D BD EE 00 00 00 00-98 4E 22 EF 00 00 00 00  * M.......N".....*
  EFFD0068: 90 E1 A0 EA 00 00 00 00-18 FF FD EF 00 00 00 00  *................*
  EFFD0078: D8 11 C5 3E 00 00 00 00-0D 00 00 00 00 00 00 00  *...>............*
  EFFD0088: 18 FB FD EF 00 00 00 00-                         *........*

Valid EFI Header at Address 00000000EFFD0018
---------------------------------------------
System: Table Structure size 00000078 revision 00020046
ConIn (00000000EAA0E400) ConOut (00000000EEBD4D20) StdErr (00000000EAA0E190)
Runtime Services              00000000EFFDFF18
Boot Services                 000000003EC511D8
SAL System Table              0000000000000000
ACPI Table                    0000000000000000
ACPI 2.0 Table                00000000EAC30018
MPS Table                     0000000000000000
SMBIOS Table                  00000000EABC0000
DTB Table                     0000000000000000
Memory Attribute Table        00000000EEA0F018
RT Properties Table           0000000000000000
System Resource Table         0000000000000000
Debug Image Info Table        000000003EC535F0
Image Execution Info Table    0000000000000000
Json Config Data Table        0000000000000000
Json Capsule Data Table       0000000000000000
Json Capsule Results Table    0000000000000000
Memory Range Capsule          0000000000000000
Hii Database Export Buffer    00000000E9B10018
Conformance Profile Table     0000000000000000

根据这个目录便可以继续观察你想观察的某个表,比如要观察调试符号表,那么便执行dmem <地址>:

Shell> dmem 000000003EC535F0
Memory Address 000000003EC535F0 200 Bytes
  3EC535F0: 02 00 00 00 63 00 00 00-18 A0 DE EF 00 00 00 00  *....c...........*
  3EC53600: 00 00 C0 EF 00 00 00 00-98 EC DF EF 00 00 00 00  *................*
  3EC53610: 98 ED DF EF 00 00 00 00-18 36 C5 3E 00 00 00 00  *.........6.>....*
  3EC53620: 18 36 C5 3E 00 00 00 00-28 36 C5 3E 00 00 00 00  *.6.>....(6.>....*

根据EDK2的源代码,上面的前16个字节是如下结构体:

typedef struct {
  ///
  /// UpdateStatus is used by the system to indicate the state of the debug image info table.
  ///
  volatile UINT32         UpdateStatus;
  ///
  /// The number of EFI_DEBUG_IMAGE_INFO elements in the array pointed to by EfiDebugImageInfoTable.
  ///
  UINT32                  TableSize;
  ///
  /// A pointer to the first element of an array of EFI_DEBUG_IMAGE_INFO structures.
  ///
  EFI_DEBUG_IMAGE_INFO    *EfiDebugImageInfoTable;
} EFI_DEBUG_IMAGE_INFO_TABLE_HEADER;

依照这个结构体,模块的更新状态是“已经修改”

#define EFI_DEBUG_IMAGE_INFO_UPDATE_IN_PROGRESS 0x01

#define EFI_DEBUG_IMAGE_INFO_TABLE_MODIFIED 0x02
系统里一共有99个模块,第一个模块的描述信息在第三个字段所指向的地址。

UEFI的世界很精彩,还有很多命令大家可以自己试一试。

作者:沈根成  创建时间:2024-01-02 13:47
最后编辑:Zhang Yinkui  更新时间:2024-05-06 17:42