One advantage of UEFI is its modularity, meaning you can write a module that, once compiled, can be inserted into an existing BIOS and executed. Previously, the implementation methods of each IBV varied greatly, and there was almost no way to achieve universality except for inserting in a special form like PCI ROM. The demonstration here is to write a DXE module in the EDK2 environment and then insert it into LattePanda.
First, design the code, and you can write it by referring to the module \\OvmfPkg\\8254TimerDxe.
The code is very simple, the entry is the InitializezMessage() function, which registers the OnMyReadyToBoot function when the ReadyToBootEvent event is triggered. The code is as follows:
EFI_STATUS EFIAPI InitializezMessage ( IN EFI_HANDLE ImageHandle, IN EFI_SYSTEM_TABLE *SystemTable ){ EFI_STATUS Status=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;}
Thus, when the BIOS is ready to boot, it jumps into the OnMyReadyToBoot() function, which simply loops and displays a string.
/** On Ready To Boot Services Event notification handler.
Notify SMM variable driver about the event.
@param[in] Event Event whose notification function is being invoked @param[in] Context 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);}
Then add it to the compilation, modify \\OvmfPkg\\OvmfPkgX64.dsc as follows:
!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
Modify \\OvmfPkg\\OvmfPkgX64.fdf as follows:
!ifdef $(CSM_ENABLE) INF OvmfPkg/8259InterruptControllerDxe/8259.inf INF OvmfPkg/8254TimerDxe/8254Timer.inf!else INF OvmfPkg/LocalApicTimerDxe/LocalApicTimerDxe.inf!endif#LABZ_Debug_StartINF OvmfPkg/ zMessage / zMessage.inf#LABZ_Debug_EndINF OvmfPkg/IncompatiblePciDeviceSupportDxe/IncompatiblePciDeviceSupport.infINF OvmfPkg/PciHotPlugInitDxe/PciHotPlugInit.infINF MdeModulePkg/Bus/Pci/PciHostBridgeDxe/PciHostBridgeDxe.inf
Use the following command to test on QEMU:
qemu-system-x86_64 -bios ovmf.fd -net none
You can see that the defined string is output on the screen during the boot process.
The generated FFS file is located in \\Build\\OvmfX64\\DEBUG_VS2019\\FV\\Ffs\\00002237-2024-0513-A7F3-1449F9E0E4BDzMessage directory (for convenience, we specified the module’s GUID in the INF to start with 0000). The file name is 00002237-2024-0513-A7F3-1449F9E0E4BD.ffs. This is our compiled module.
Next, use MMTOOL to open the IFWI file provided by LattePanda:
We choose to insert at Volume 03:02-01 Index 137 (theoretically, the position of the UEFI module in the BIOS does not affect the loading order, this is just a randomly chosen position for convenience). Below is the completed result:
Finally, use “Save Image as…” to save it again as zMessage.fd, and then flash it to LattePanda.
The test video
Leave a Comment
Your email address will not be published. Required fields are marked *