我的BIOS之行6-事件的使用
前言
UEFI已经不再支持中断了,所有的异步操作都是要通过事件来完成的,所以我在这一章节会教如何使用事件来完成一个非常简单的事件处理。
上一章节我们说到了hob,那么继续在这个上面来完善我们的code,需要做的是,在dex阶段通过event事件来驱动读取hob。
简介
一个来说事件会提供用于操作事件、定时器以及TPL(任务优先级)
UEFI事件服务
- CreateEvent(生成一个事件对象)
- CreateEventEx(生成一个事件对象并将改事件加入到一个组内)
- CloseEvent(关闭事件对象)
- SignalEvent(触发事件对象)
- WaitForEvent(等待事件数组中的任一事件触发)
- CheckEvent(检查事件状态)
- SetTimer(设置定时器属性)
- RaiseTPL(提升任务优先级)
- RestoreTPL(恢复任务优先级)
一般你可以直接在uefispec.h中找到这个原型,而且在spec中也有详细的介绍,因此在这边我就以CreateEvent为例,简单介绍一下,spec应该会比我解释得更加清晰
//
// Event & Timer Services
//
EFI_CREATE_EVENT CreateEvent;
EFI_SET_TIMER SetTimer;
EFI_WAIT_FOR_EVENT WaitForEvent;
EFI_SIGNAL_EVENT SignalEvent;
EFI_CLOSE_EVENT CloseEvent;
EFI_CHECK_EVENT CheckEvent;
而EFI_CREATE_EVENT又可以找到,具体解释可以看上面的注释,也可以参考我的注释
/**
Creates an event.
@param[in] Type The type of event to create and its mode and attributes.
@param[in] NotifyTpl The task priority level of event notifications, if needed.
@param[in] NotifyFunction The pointer to the event's notification function, if any.
@param[in] NotifyContext The pointer to the notification function's context; corresponds to parameter
Context in the notification function.
@param[out] Event The pointer to the newly created event if the call succeeds; undefined
otherwise.
@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//生成的事件
);
实例
创建事件
在这里我们只需要创建一个事件就可以了,不需要整组事件联动的,所以直接使用CreateEvent就可以了,如果是整组的话,就需要用CreateEventEx.
在入口函数中创建事件
Status = pBS->CreateEvent(
EVT_NOTIFY_WAIT,
TPL_NOTIFY,
(EFI_EVENT_NOTIFY)HomeWorkDxeHobnotify,
(VOID*)NULL,
&homeworkevent
);
完成notification函数
注意在notification函数中我们用SignalEvent(Event)触发事件,也就是说我们目前的事件是直接被触发的,后面我们会通过其他手段来触发事件
VOID HomeWorkDxeHobnotify(
IN EFI_EVENT Event,
IN VOID *Context
)
{
EFI_GUID GuidHob = HOB_LIST_GUID;
HOMEWORK_HOB *Homeworkhob=NULL;
EFI_GUID HomeworkHobGuid=HOMEWORK_HOB_GUID;
VOID *pHobList = NULL;
EFI_STATUS Status;
pHobList = GetEfiConfigurationTable(pST, &GuidHob);
if (!pHobList) return;
Homeworkhob = (HOMEWORK_HOB*)pHobList;
while (!EFI_ERROR(Status = FindNextHobByType(EFI_HOB_TYPE_GUID_EXTENSION, &Homeworkhob)))
{
if (guidcmp(&(*Homeworkhob).EfiHobGuidType.Name, &HomeworkHobGuid) == 0)
break;
}
if (EFI_ERROR(Status))
{
return;
}else{
OEM_TRACE("data=%d\n",Homeworkhob->homeworkdata);
}
pBS->SignalEvent(Event);
}
等待事件发生
Status = pBS->WaitForEvent(1,&homeworkevent,&index);
WaitForEvent属于阻塞操作,指导Event数组中的事件被触发或者出错才会返回,其实我并不太建议这样做,毕竟这是一种浪费资源的行为,不过呢,我们在这边仅仅是为了实验,所以我就不说什么了。
作者:King_Alex【The Horizon Blog】
出处:http://www.cnblogs.com/samuelwnb/
版权:本文版权归作者和博客园共有
转载:欢迎转载,为了保存作者的创作热情,请按要求【转载】,谢谢
要求:未经作者同意,必须保留此段声明;必须在文章中给出原文连接;否则必究法律责任
出处:http://www.cnblogs.com/samuelwnb/
版权:本文版权归作者和博客园共有
转载:欢迎转载,为了保存作者的创作热情,请按要求【转载】,谢谢
要求:未经作者同意,必须保留此段声明;必须在文章中给出原文连接;否则必究法律责任