2023-07-25
事件函数
#
WaitForEvent 等待事件发生
#
/**
@retval EFI_SUCCESS The event indicated by Index was signaled.
@retval EFI_INVALID_PARAMETER 1. NumberOfEvents is 0; 2. The event indicated by Index is of type EVT_NOTIFY_SIGNAL.
@retval EFI_UNSUPPORTED The current TPL is not TPL_APPLICATION.
**/
typedef
EFI_STATUS
(EFIAPI *EFI_WAIT_FOR_EVENT)(
IN UINTN NumberOfEvents, //event数组的长度
IN EFI_EVENT *Event, //event数组
OUT UINTN *Index //返回触发事件的下标
);
- WaitForEvent是阻塞操作,直到Event数组内任一事件被触发或者事件导致错误出现时,WaitForEvent才返回。
- 事件触发后返回index,并将事件重置为非触发状态。
- EVT_NOTIFY_SIGNAL类型的事件似乎不能用WaitForEvent。
CreateEvent 创建事件
#
/**
@retval EFI_SUCCESS The event structure was created.
@retval EFI_INVALID_PARAMETER One or more parameters are invalid.
@retval EFI_OUT_OF_RESOURCES The event could not be allocated.
**/
typedef
EFI_STATUS
(EFIAPI *EFI_CREATE_EVENT)(
IN UINT32 Type, //事件类型
IN EFI_TPL NotifyTpl, //Notification函数的优先级
IN EFI_EVENT_NOTIFY NotifyFunction, //Notification函数
IN VOID *NotifyContext, //传给Notification函数的参数
OUT EFI_EVENT *Event //生成的事件
);
事件类型
#
- 事件类型可以是一种或多种基本类型的组合。常用的事件类型如下:
类型 |
特征 |
EVT_TIMER |
定时器事件,没有Notification函数,生成事件后需要调用setTimer服务设置时钟属性。事件可以通过SetTimer设置等待事件、到期后通过SignalEvent触发、通过WaitForEvent等待事件触发、通过CheckEvent检查事件 |
EVT_NOTIFY_WAIT |
有一个Notification函数,当调用CheckEvent或WaitForEvent时,Notifyication函数会被放到待执行队列 |
EVT_NOTIFY_SIGNAL |
有一个Notification函数,当前事件通过SignalEvent被触发时,这个Notification函数会被放到待执行队列 |
0X00000000 |
没有Notification函数,事件可以通过signalevent触发、waitforevent等待事件被触发、checkevent检查状态 |
- 还有两种特殊的事件
- EVT_SIGNAL_EXIT_BOOT_SERVICES:当ExitBootServices被执行时,事件被触发。
- EVT_SIGNAL_VIRTUAL_ADDRESS_CHANGE:当SetVirtualAddressMap被调用时触发此类型的事件。
优先级
#
优先级 |
用法 |
函数 |
TPL_APPLICATION |
优先级最低,当程序运行在此级别时,任务队列中没有任何处于就绪状态的Notification函数 |
下列安徽念书运行在此级别ExitBootServices()、WaitForEvent()等 |
TPL_CALLBACK |
比较耗时的操作通常在这个优先级 |
Serial I/O Protocol、UnloadImage |
TPL_NOTIFY |
运行在这个级别的程序不允许阻塞,大部分Event的Notification函数允许在这个级别 |
Memory Allocation Services、HII Protocols |
TPL_HIGH_LEVEL |
UEFI内核全局变量的修改允许在这个级别 |
SignalEvent、stall |
Notification函数
#
typedef
VOID
(EFIAPI *EFI_EVENT_NOTIFY)(
IN EFI_EVENT Event, //拥有此函数的事件
IN VOID *Context //上下文指针,在CreateEvent设置
);
- 根据上面的事件类型可知,EVT_NOTIFY_WAIT的函数会在等待事件的过程中调用,而EVT_NOTIFY_SIGNAL的Notification函数会在SignalEvent调用。
CreateEventEx
#
/**
@retval EFI_SUCCESS The event structure was created.
@retval EFI_INVALID_PARAMETER One or more parameters are invalid.
@retval EFI_OUT_OF_RESOURCES The event could not be allocated.
**/
typedef
EFI_STATUS
(EFIAPI *EFI_CREATE_EVENT_EX)(
IN UINT32 Type,
IN EFI_TPL NotifyTpl,
IN EFI_EVENT_NOTIFY NotifyFunction OPTIONAL,
IN CONST VOID *NotifyContext OPTIONAL,
IN CONST EFI_GUID *EventGroup OPTIONAL, //事件组
OUT EFI_EVENT *Event
);
- CreateEventEx用于生成事件并将事件加入事件组。当事件组中的任意事件被触发后,组中的所有事件都会被触发,进而组内所有的Notification函数都会被加入待执行队列,组内优先级最高的Notification函数会被先执行。
- 存在四个预定义的Event组:
- EFI_EVENT_GROUP_EXIT_BOOT_SERVICES:当执行ExitBootServices触发组内所有的事件。
- EFI_EVENT_GROUP_VIRTUAL_ADDRESS_CHANGE:当执行SetVirtualAddressMap触发组内所有的Event。
- EFI_EVENT_GROUP_MEMORY_MAP_CHANGE:Memory Map改变时触发组内所有的Event。
- EFI_EVENT_GROUP_READY_TO_BOOT:Boot Manager加载并且执行一个启动项时触发组内所有的Event。
CheckEvent 检查事件状态
#
/**
@retval EFI_SUCCESS 事件是触发态
@retval EFI_NOT_READY 事件是非触发态
@retval EFI_INVALID_PARAMETER 事件类型是EVT_NOTIFY_SIGNAL
**/
typedef
EFI_STATUS
(EFIAPI *EFI_CHECK_EVENT)(
IN EFI_EVENT Event
);
SignalEvent 触发事件
#
typedef
EFI_STATUS
(EFIAPI *EFI_SIGNAL_EVENT)(
IN EFI_EVENT Event
);
- 将事件设置为触发态。如果该事件在一个组中,则将族中所有的事件设置为触发态。
CloseEvent 关闭事件
#
typedef
EFI_STATUS
(EFIAPI *EFI_CLOSE_EVENT)(
IN EFI_EVENT Event
);
SetTimer
#
- EVT_TIMER是一类特殊的事件,可以通过SetTimer服务设置定时器属性。
/**
@retval EFI_SUCCESS The event has been set to be signaled at the requested time.
@retval EFI_INVALID_PARAMETER Event or Type is not valid.
**/
typedef
EFI_STATUS
(EFIAPI *EFI_SET_TIMER)(
IN EFI_EVENT Event,
IN EFI_TIMER_DELAY Type, //定时器类型
IN UINT64 TriggerTime //过期事件,100ns为一个单位
);
类型 |
|
TimerCancel |
取消定时器触发 |
TimerPeriodic |
重复型定时器 |
TimerRelative |
一次性定时器 |
- 如果Type为TimerPeriodic并且TriggerTIme是0,则定时器每个时钟滴答触发一次。
- 生成定时器事件包含两步:
- 通过CreateEvent生成一个EVT_TIMER事件
- 通过SetTimer设置这个定时器事件的属性。