49569浏览
查看: 49569|回复: 0

[讨论分享] 如何在 LattePanda BIOS 插入自定义模块

[复制链接]
UEFI 的一个优点是模块化,意思是你可以编写一个模块,编译后能够插入到已有的BIOS中并且执行。在此之前,每个IVB 实现方式差异巨大,除了按照PCI ROM 这种特别形式插入几乎没有办法实现通用。这次演示的就是在EDK2环境下编写一个DXE模块,然后插入到LattePanda中。
首先进行代码的设计,仿照\OvmfPkg\8254TimerDxe这个模块就可以写好。
代码非常简单,入口是InitializezMessage() 函数,进入之后注册OnMyReadyToBoot函数,当ReadyToBootEvent事件时触发之。代码如下:
  1. EFI_STATUS
  2. EFIAPI
  3. InitializezMessage (
  4.   IN EFI_HANDLE        ImageHandle,
  5.   IN EFI_SYSTEM_TABLE  *SystemTable
  6.   )
  7. {
  8.   EFI_STATUS  Status=EFI_SUCCESS;
  9.   EFI_EVENT   ReadyToBootEvent;
  10.   DEBUG ((DEBUG_INFO, "UPassword DXE Loaded\n"));
  11.   //
  12.   // Register the event to reclaim variable for OS usage.
  13.   //
  14.   EfiCreateEventReadyToBootEx (
  15.     TPL_NOTIFY,              
  16.     OnMyReadyToBoot,
  17.     NULL,
  18.     &ReadyToBootEvent  
  19.     );  
  20.   return Status;
  21. }
复制代码
这样,当BIOS准备启动的时候就是跳入OnMyReadyToBoot()函数,执行,在函数中只是循环显示一段字符串。
  1. /**
  2.   On Ready To Boot Services Event notification handler.
  3.   Notify SMM variable driver about the event.
  4.   @param[in]  Event     Event whose notification function is being invoked
  5.   @param[in]  Context   Pointer to the notification function's context
  6. **/
  7. VOID
  8. EFIAPI
  9. OnMyReadyToBoot (
  10.   IN      EFI_EVENT                         Event,
  11.   IN      VOID                              *Context
  12.   )
  13. {
  14.   DEBUG ((EFI_D_INFO, "Invoke OnMyReadyToBoot\n"));
  15.   
  16.   for (UINTN i=0;i<5;i++) {
  17.         gST->ConOut->OutputString(gST->ConOut,L"\r\n delay from www.lab-z.com\r\n");
  18.         gBS->Stall(1000000UL);
  19.   }
  20.        
  21.   gBS->CloseEvent (Event);
  22. }
复制代码
然后将其加入编译,在\OvmfPkg\OvmfPkgX64.dsc修改如下:

  1. !ifdef $(CSM_ENABLE)
  2.   OvmfPkg/8259InterruptControllerDxe/8259.inf
  3.   OvmfPkg/8254TimerDxe/8254Timer.inf
  4. !else
  5.   OvmfPkg/LocalApicTimerDxe/LocalApicTimerDxe.inf
  6. !endif
  7.   #LABZ_Debug_Start
  8.   OvmfPkg/ zMessage / zMessage.inf
  9.   #LABZ_Debug_End
  10.   OvmfPkg/IncompatiblePciDeviceSupportDxe/IncompatiblePciDeviceSupport.inf
  11.   OvmfPkg/PciHotPlugInitDxe/PciHotPlugInit.inf
复制代码
\OvmfPkg\OvmfPkgX64.fdf 修改如下:
  1. !ifdef $(CSM_ENABLE)
  2.   INF  OvmfPkg/8259InterruptControllerDxe/8259.inf
  3.   INF  OvmfPkg/8254TimerDxe/8254Timer.inf
  4. !else
  5.   INF  OvmfPkg/LocalApicTimerDxe/LocalApicTimerDxe.inf
  6. !endif
  7. #LABZ_Debug_Start
  8. INF  OvmfPkg/ zMessage / zMessage.inf
  9. #LABZ_Debug_End
  10. INF  OvmfPkg/IncompatiblePciDeviceSupportDxe/IncompatiblePciDeviceSupport.inf
  11. INF  OvmfPkg/PciHotPlugInitDxe/PciHotPlugInit.inf
  12. INF  MdeModulePkg/Bus/Pci/PciHostBridgeDxe/PciHostBridgeDxe.inf
复制代码
使用如下命令在QEMU 上测试:

  1. 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 文件:
如何在 LattePanda BIOS 插入自定义模块图1

我们选择在Volume03:02-01 Index 137 的地方插入(理论上 UEFI模块在BIOS中的位置不影响加载顺序,这里只是为了方便查找随便选择的位置),下面就是完成后的结果:

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

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

最终加入模块的LattePanda IFWI:


工作的视频可以在这里看到:



您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

为本项目制作心愿单
购买心愿单
心愿单 编辑
[[wsData.name]]

硬件清单

  • [[d.name]]
btnicon
我也要做!
点击进入购买页面
上海智位机器人股份有限公司 沪ICP备09038501号-4

© 2013-2024 Comsenz Inc. Powered by Discuz! X3.4 Licensed

mail