zoologist 发表于 2024-5-18 09:45:12

如何在 LattePanda BIOS 插入自定义模块

UEFI 的一个优点是模块化,意思是你可以编写一个模块,编译后能够插入到已有的BIOS中并且执行。在此之前,每个IVB 实现方式差异巨大,除了按照PCI ROM 这种特别形式插入几乎没有办法实现通用。这次演示的就是在EDK2环境下编写一个DXE模块,然后插入到LattePanda中。首先进行代码的设计,仿照\OvmfPkg\8254TimerDxe这个模块就可以写好。代码非常简单,入口是InitializezMessage() 函数,进入之后注册OnMyReadyToBoot函数,当ReadyToBootEvent事件时触发之。代码如下:EFI_STATUS
EFIAPI
InitializezMessage (
IN EFI_HANDLE      ImageHandle,
IN EFI_SYSTEM_TABLE*SystemTable
)
{
EFI_STATUSStatus=EFI_SUCCESS;
EFI_EVENT   ReadyToBootEvent;

DEBUG ((DEBUG_INFO, "UPassword DXE Loaded\n"));

//
// Register the event to reclaim variable for OS usage.
//
EfiCreateEventReadyToBootEx (
    TPL_NOTIFY,            
    OnMyReadyToBoot,
    NULL,
    &ReadyToBootEvent
    );

return Status;
}
这样,当BIOS准备启动的时候就是跳入OnMyReadyToBoot()函数,执行,在函数中只是循环显示一段字符串。/**
On Ready To Boot Services Event notification handler.

Notify SMM variable driver about the event.

@paramEvent   Event whose notification function is being invoked
@paramContext   Pointer to the notification function's context

**/
VOID
EFIAPI
OnMyReadyToBoot (
IN      EFI_EVENT                         Event,
IN      VOID                              *Context
)
{
DEBUG ((EFI_D_INFO, "Invoke OnMyReadyToBoot\n"));

for (UINTN i=0;i<5;i++) {
        gST->ConOut->OutputString(gST->ConOut,L"\r\n delay from www.lab-z.com\r\n");
        gBS->Stall(1000000UL);
}
       
gBS->CloseEvent (Event);
}
然后将其加入编译,在\OvmfPkg\OvmfPkgX64.dsc修改如下:
!ifdef $(CSM_ENABLE)
OvmfPkg/8259InterruptControllerDxe/8259.inf
OvmfPkg/8254TimerDxe/8254Timer.inf
!else
OvmfPkg/LocalApicTimerDxe/LocalApicTimerDxe.inf
!endif
#LABZ_Debug_Start
OvmfPkg/ zMessage / zMessage.inf
#LABZ_Debug_End
OvmfPkg/IncompatiblePciDeviceSupportDxe/IncompatiblePciDeviceSupport.inf
OvmfPkg/PciHotPlugInitDxe/PciHotPlugInit.inf
在 \OvmfPkg\OvmfPkgX64.fdf 修改如下:!ifdef $(CSM_ENABLE)
INFOvmfPkg/8259InterruptControllerDxe/8259.inf
INFOvmfPkg/8254TimerDxe/8254Timer.inf
!else
INFOvmfPkg/LocalApicTimerDxe/LocalApicTimerDxe.inf
!endif
#LABZ_Debug_Start
INFOvmfPkg/ zMessage / zMessage.inf
#LABZ_Debug_End
INFOvmfPkg/IncompatiblePciDeviceSupportDxe/IncompatiblePciDeviceSupport.inf
INFOvmfPkg/PciHotPlugInitDxe/PciHotPlugInit.inf
INFMdeModulePkg/Bus/Pci/PciHostBridgeDxe/PciHostBridgeDxe.inf
使用如下命令在QEMU 上测试:
qemu-system-x86_64 -bios ovmf.fd-net none
可以看到在启动过程中屏幕上输出了定义的字符串。确认代码可以工作接下来就可以实际操作了。
生成的FFS文件在\Build\OvmfX64\DEBUG_VS2019\FV\Ffs\00002237-2024-0513-A7F3-1449F9E0E4BDzMessage目录中(为了方便查找,我们在INF中指定模块的GUID 是 0000开头的)。文件名是 00002237-2024-0513-A7F3-1449F9E0E4BD.ffs。这就是我们编译后的模块。接下来,使用MMTOOL打开LattePanda官方提供的IFWI 文件:
我们选择在Volume03:02-01 Index 137 的地方插入(理论上 UEFI模块在BIOS中的位置不影响加载顺序,这里只是为了方便查找随便选择的位置),下面就是完成后的结果:

最后,使用“SaveImage as…”重新保存命名为zMessage.fd,然后烧录到LattePanda上即可。本文提到的UEFI 源代码:UEFI 源代码生成的FFS 文件:
最终加入模块的LattePanda 的IFWI:

工作的视频可以在这里看到:
https://www.bilibili.com/video/BV1g1421B7Gu/

页: [1]
查看完整版本: 如何在 LattePanda BIOS 插入自定义模块