事件日志的驱动包括四个部分:追加一条记录,删除记录,覆盖记录,得到下一条记录。
四个部分都涉及到链表的操作
定义一个链表的全局变量,该变量的数据代表当前记录,forwardLink表示指针指向前一个链表,backLink表示指针指向后一个链表。
LIST_ENTRY mEventLogList;
struct _LIST_ENTRY {
LIST_ENTRY *ForwardLink;
LIST_ENTRY *BackLink;
};
每一条记录的结构体包括,链表指针和内容(事件,日期,事件)
EFI_EVENT_LOG_DATA *EventLog;
typedef struct {
UINT32 Signature;
LIST_ENTRY Link;
EVENT_LOG_ORGANIZATION *Buffer;
} EFI_EVENT_LOG_DATA;
typedef struct {
//
//Log Header is optional, default is no header
//
UINT8 Type;
UINT8 Length;
UINT8 Year;
UINT8 Month;
UINT8 Day;
UINT8 Hour;
UINT8 Minute;
UINT8 Second;
UINT8 DataFormatType;
UINT8 Data[8];
//
//Log Variable Data is optional
//
} EVENT_LOG_ORGANIZATION;
追加记录使用插入头链表的方法,由图可以看出,追加记录的初始地址 = 当前记录初始地址+一条记录的大小
CopyMem ((UINT8*) ((UINTN) EventLog->Buffer + NumBytes - OptionDataSize), OptionLogData, OptionDataSize);
InsertTailList (&mEventLogList, &EventLog->Link);
初始化链表就可以删除链表里的记录
InitializeListHead (&mEventLogList);
先初始化再追加记录
InitializeListHead (&mEventLogList);
CopyMem ((UINT8*) ((UINTN) EventLog->Buffer + NumBytes - OptionDataSize), OptionLogData, OptionDataSize);
InsertTailList (&mEventLogList, &EventLog->Link);
1)得到第一条记录
2)一直查询直到匹配输入的一条记录,匹配成功返回下一条记录地址
Link = mEventLogList.ForwardLink;
while (Link != &mEventLogList) {
EventLog = DATA_FROM_EFI_EVENT_LOG_THIS(Link);
if (EventLog->Buffer == *EventListAddress) {
Link = Link->ForwardLink;
if (Link == &mEventLogList) {
return EFI_NOT_FOUND;
}
EventLog = DATA_FROM_EFI_EVENT_LOG_THIS(Link);
*EventListAddress = (VOID *) EventLog->Buffer;
return EFI_SUCCESS;
}
Link = Link->ForwardLink;
}
ELPrivate->Signature = EVENT_LOG_SIGNATURE;
ELPrivate->DevicePtr = NULL;
ELPrivate->GPNVBase = (UINTN)mGPNVBase;
ELPrivate->GPNVLength = GetGPNVSize ();
ELPrivate->EventLogService.LogAddress = (UINTN)mGPNVBase;
ELPrivate->EventLogService.Write = EfiWriteEventLog;
ELPrivate->EventLogService.Clear = EfiClearEventLog;
ELPrivate->EventLogService.ReadNext = EfiReadNextEventLog;
// ELPrivate->EventLogService.DetectDevice = FlashFdDetectDevice;
ELPrivate->EventLogService.OverWrite = EfiOverWriteEventLog;
ELPrivate->Handle = NULL;
Status = gBS->InstallProtocolInterface (
&ELPrivate->Handle,
&gEfiEventLogProtocolGuid,
EFI_NATIVE_INTERFACE,
&(ELPrivate->EventLogService)
);
1)通过locateprotocol 得到驱动接口
2)调用 读取下一条记录的 遍历事件链表
3)事件链表值进行组合拼装成需要的格式,更新到Setup表格中
Time.Year = BcdToDecimal8(EventLog->Year) + 2000;
Time.Month = BcdToDecimal8(EventLog->Month);
Time.Day = BcdToDecimal8(EventLog->Day);
Time.Hour = BcdToDecimal8(EventLog->Hour);
Time.Minute = BcdToDecimal8(EventLog->Minute);
Time.Second = BcdToDecimal8(EventLog->Second);
ZeroMem(String, sizeof(String));
UnicodeSPrint(String, sizeof (String), L"%04d/%02d/%02d %02d:%02d:%02d",
Time.Year,Time.Month,Time.Day,Time.Hour,Time.Minute,Time.Second);
StrRef = HiiSetString (mHiiHandle, 0, String, NULL);
ZeroMem(String, sizeof(String));
QueryTable (SELTypesTable, sizeof(SELTypesTable)/sizeof(TABLE_ITEM), EventLog->Type, String);
Info = HiiSetString (mHiiHandle, 0, String, NULL);
HiiCreateTextOpCode (StartOpCodeHandle, StrRef, STRING_TOKEN (STR_EMPTY), Info);