Step to UEFI (124) Ready_To_Boot Event

很早之前的代码,如果想完成在引导之前的一些工作,需要在Log中查找确定跳入引导代码之前的代码。直观,但是没有规范,同一个项目很容易出现好多代码都塞到同一处的情况。到了 UEFI ,规范中给出了一个规范的做法:使用 ReadyToBoot Event。对于这个,在《UEFI 原理与编程》第6章 事件有简单的介绍:

EFI_EVENT_GROUP_READY_TO_BOOT
GUID: gEfiEventReadyToBootGuid

Boot Manager 加载并且执行一个启动项时触发该组内所有 Event。

对应函数原型可以在 \MdePkg\Include\Library\UefiLib.h 看到:

/**
  Create an EFI event in the Ready To Boot Event Group and allows
  the caller to specify a notification function.  
  
  This function abstracts the creation of the Ready to Boot Event.
  The Framework moved from a proprietary to UEFI 2.0 based mechanism.
  This library abstracts the caller from how this event is created to prevent
  to code form having to change with the version of the specification supported.
  If ReadyToBootEvent is NULL, then ASSERT().

  @param  NotifyTpl         The task priority level of the event.
  @param  NotifyFunction    The notification function to call when the event is signaled.
  @param  NotifyContext     The content to pass to NotifyFunction when the event is signaled.
  @param  ReadyToBootEvent  Returns the EFI event returned from gBS->CreateEvent(Ex).

  @retval EFI_SUCCESS       The event was created.
  @retval Other             The event was not created.

**/
EFI_STATUS
EFIAPI
EfiCreateEventReadyToBootEx (
  IN  EFI_TPL           NotifyTpl,                  //事件优先级
  IN  EFI_EVENT_NOTIFY  NotifyFunction,  OPTIONAL   //事件 Notification 函数
  IN  VOID              *NotifyContext,  OPTIONAL  //传递给事件 Notification 函数的参数
  OUT EFI_EVENT         *ReadyToBootEvent   //生成的事件
  );

 

为此,在 UDK2017 上做一个简单的实验,在GraphicsConsole.c 文件中加入创建事件和 Notification函数的代码:

1. 创建事件

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

 

2. 事件 Notification 函数

//LABZ_Debug_Start
/**
  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"));
  
  gBS->CloseEvent (Event);
}
//LABZ_Debug_End

 

运行结果中可以看到,这个函数会被 Invoke 2次

event1

研究代码发现,这是因为创建的函数运行了两次,因此创建了2个不同的事件

event2

附件是修改后的GraphicsConsole.c,有兴趣的朋友可以自己动手实验。实验使用的编译命令是:

build -a X64
build -a X64 run

发表评论

电子邮件地址不会被公开。 必填项已用*标注