bloggerads

2016年5月28日 星期六

UEFI : Event (事件)

UEFI 基本上是個單核/單工/提供Timer中斷的系統。<note 1>
但因為他提供了Timer中斷, 理論上就有機會做到異步操作以及分時多工。

實現這樣的目標可以透過 Boot Service提供的事件(Event)來達成。

首先使用 gBS->CreateEvent() 註冊一個 NotifyFunction (或稱CallBackFunction) 等待事件的發生或讓事件週期性的在背景執行。關閉Event須要呼叫  gBS->CloseEvent() 。因為是Boot Service所提供的,因此ExitBootServices()被系統呼叫後,BS的service/data都會消失。

先來看看Event的 typedef


 typedef

 EFI_BOOTSERVICE
 EFI_STATUS
 (EFIAPI *EFI_CREATE_EVENT) (
     IN UINT32 Type,
     IN EFI_TPL NotifyTpl,
     IN EFI_EVENT_NOTIFY NotifyFunction,
     IN VOID *NotifyContext,
     OUT EFI_EVENT * Event
 );



選定不同種Type可以達到不同的效果:

比較常用的 Type 是 EVT_TIMER | EVT_NOTIFY_SIGNAL, 一旦所對應Event的Timer設定完成, 即執行到gBS->SetTimer(), 就會在背景周期性的執行所註冊的NotifyFunction。這就是一種分時多工的概念。


另一種也常用的 Type EVT_TIMER | EVT_NOTIFY_WAIT, 做法是先透過gBS->SetTimer()給一個TimeOut時間,一旦所對應Event開始啟動等待, 即執行到gBS->WaitForEvent(), 就會不停的執行註冊的NotifyFunction並停在gBS->WaitForEvent()這支函式執行點,直到TimeOut

另外我們還可以使用改良版的Event函式EfiCreateProtocolNotifyEvent, 透過他我們可以指定某個Protocol被安裝後才啟動執行我們的NotifyFunction



 EFI_EVENT
 EFIAPI
 EfiCreateProtocolNotifyEvent(
   IN  EFI_GUID          *ProtocolGuid,
   IN  EFI_TPL           NotifyTpl,
   IN  EFI_EVENT_NOTIFY  NotifyFunction,
   IN  VOID              *NotifyContext,  OPTIONAL
   OUT VOID              **Registration
   )
 {
   EFI_STATUS  Status;
   EFI_EVENT   Event;

   //
   // Create the event
   //

   Status = 
gBS->CreateEvent (
                   EFI_EVENT_NOTIFY_SIGNAL,
                   NotifyTpl,
                   NotifyFunction,
                   NotifyContext,
                   &Event
                   );
   ASSERT_EFI_ERROR (Status);

   //
   // Register for protocol notifactions on this event
   //

   Status = 
gBS->RegisterProtocolNotify (
                   ProtocolGuid,
                   Event,
                   Registration
                   );

   ASSERT_EFI_ERROR (Status);

   //
   // Kick the event so we will perform an initial pass of
   // current installed drivers
   //
   // the library will signal this event immediately once
   gBS->SignalEvent (Event);
   return Event;
}

<note 1> UEFI有提供多線程(Multi-Processor)來執行函式的library,請參考EFI_MP_SERVICES_PROTOCOL,用途是呼叫特定AP的或呼叫全部的AP來執行函式。

2 則留言:

  1. Martin 每次看你的文章都覺得收穫很多 希望能看到你更多分享

    回覆刪除
  2. 收穫很多很好
    那你要準備轉行了嗎XDD

    回覆刪除