- 源代码:EDK2
- 版本:UDK2017
- UEFI源码分析第二篇,异步事件服务
- 第一部分,事件驱动
- 优先级的讨论将在另一篇,即第二部分。
- 定时器类型
EVT_TIMER将在第三部分
事件
每一个事件都是一个IEvent类型
/** /Dxe/Event/Event.h **/
45 #define EVENT_SIGNATURE SIGNATURE_32('e','v','n','t')
46 typedef struct {
47 UINTN Signature;
48 UINT32 Type;
49 UINT32 SignalCount;
53 LIST_ENTRY SignalLink;
57 EFI_TPL NotifyTpl;
58 EFI_EVENT_NOTIFY NotifyFunction;
59 VOID *NotifyContext;
60 EFI_GUID EventGroup;
61 LIST_ENTRY NotifyLink;
62 UINT8 ExFlag;
66 EFI_RUNTIME_EVENT_ENTRY RuntimeData;
67 TIMER_EVENT_INFO Timer;
68 } IEVENT;
可以看到有多个链表
SignalLinkNotifyLink
这是提供给不同事件类型所使用。事件有以下几种类型。
/** MdePkg/Include/Uefi/UefiSpec.h **/
384 //
385 // These types can be ORed together as needed - for example,
386 // EVT_TIMER might be Ored with EVT_NOTIFY_WAIT or
387 // EVT_NOTIFY_SIGNAL.
388 //
389 #define EVT_TIMER 0x80000000
390 #define EVT_RUNTIME 0x40000000
391 #define EVT_NOTIFY_WAIT 0x00000100
392 #define EVT_NOTIFY_SIGNAL 0x00000200
393
394 #define EVT_SIGNAL_EXIT_BOOT_SERVICES 0x00000201
395 #define EVT_SIGNAL_VIRTUAL_ADDRESS_CHANGE 0x60000202
大致有如下特性
- Notify意味着有NotifyFunction在事件发生的时候被调用,也就是回调函数
- Wait意味着可以使用WaitForEvent来等待事件的发生,其阻塞直到事件被Signal
- Signal意味着事件可以被唤醒
- Timer意味着该事件是一个定时器,IEvent的Timer域会被填充,其中包含一个Link来链接所有的定时器
- 这些特性是可以被OR来组合到一起的,即运算符|
两个类型只在此提一下,不详述
- EVT_SIGNAL_EXIT_BOOT_SERVICES是在UEFI系统退出(ExitBootServices())的时候调用,通常用来回收资源
- EVT_SIGNAL_VIRTUAL_ADDRESS_CHANGE在操作系统加载器调用运行时服务RuntimeServices的虚拟地址服务来进行虚拟地址转换的时候调用。
主要关注两个类型
- EVT_NOTIFY_WAIT可等待事件
- EVT_NOTIFY_SIGNAL可唤醒事件
重要的全局变量
gEventSignalQueue保存所有未被唤醒、类型为EVT_NOTIFY_SIGNAL的事件gEventQueue保存已经被唤醒、需要执行回调函数的事件,根据优先级分为多个链表gEventPending使用位图来保存gEventQueue是否含有某个优先级的链表mEventTable包含了所有合法的事件类型
相关接口
创建事件CreateEvent
/** /Dxe/Event/Event.c **/
378 EFI_STATUS
379 EFIAPI
380 CoreCreateEventInternal (
381 IN UINT32 Type,
382 IN EFI_TPL NotifyTpl,
383 IN EFI_EVENT_NOTIFY NotifyFunction, OPTIONAL
384 IN CONST VOID *NotifyContext, OPTIONAL
385 IN CONST EFI_GUID *EventGroup, OPTIONAL
386 OUT EFI_EVENT *Event
387 )
388 {
Type域即事件的类型
NotifyTpl是回调函数的优先级,在本系列的第二部分会介绍,NorifyFunction即回调函数本身,NofityContext即传递给回调函数的参数。
EventGroup是事件组特性,其使用一个GUID来标识该事件属于一个事件组,同组内的事件均含有相同的GUID,不同事件组的GUID必然不同。
Event是返回的、创建完成的事件,EFI_EVENT类型本质上是IEvent*类型。
1、检查事件的类型
401 Status = EFI_INVALID_PARAMETER;
402 for (Index = 0; Index < (sizeof (mEventTable) / sizeof (UINT32)); Index++) {
403 if (Type == mEventTable[Index]) {
404 Status = EFI_SUCCESS;
405 break;
406 }
407 }
408 if(EFI_ERROR (Status)) {
409 return EFI_INVALID_PARAMETER;

本文是UEFI源码分析的第二篇,聚焦于DXE阶段的异步事件服务,特别是事件驱动机制。文章详细介绍了事件的类型、重要全局变量、相关接口如创建、唤醒、回调和检查事件等,并通过实例阐述了常见使用场景。重点关注可等待和可唤醒事件,以及它们在系统中的交互与作用。
最低0.47元/天 解锁文章
1142

被折叠的 条评论
为什么被折叠?



