一般通过下面的函数来将image copy到dram中
Status = gBS->LoadImage (
TRUE,
gImageHandle,
FullDevicePath,
NULL,
0,
&ImageHandle
);
而在dxemain.c中的mBootService 这个数组中已经指定gBS->LoadImage == CoreLoadImage
CoreLoadImage ->CoreLoadImageCommon->CoreInstallProtocolInterfaceNotify
CoreInstallProtocolInterfaceNotify (
IN OUT EFI_HANDLE *UserHandle,
IN EFI_GUID *Protocol,
IN EFI_INTERFACE_TYPE InterfaceType,
IN VOID *Interface,
IN BOOLEAN Notify
)
{
if (Notify) {
CoreNotifyProtocolEntry (ProtEntry);
}
Status = EFI_SUCCESS;
return Status;
}
在CoreInstallProtocolInterfaceNotify 中会调用用户注册的notify函数.
VOID
CoreNotifyProtocolEntry (
IN PROTOCOL_ENTRY *ProtEntry
)
{
PROTOCOL_NOTIFY *ProtNotify;
LIST_ENTRY *Link;
ASSERT_LOCKED (&gProtocolDatabaseLock);
for (Link=ProtEntry->Notify.ForwardLink; Link != &ProtEntry->Notify; Link=Link->ForwardLink) {
ProtNotify = CR(Link, PROTOCOL_NOTIFY, Link, PROTOCOL_NOTIFY_SIGNATURE);
CoreSignalEvent (ProtNotify->Event);
}
}
可见CoreNotifyProtocolEntry 会遍历ProtEntry,针对每个event调用CoreSignalEvent。也就是说每个protocol 可以注册多个event.
这样当用户再调用CoreRegisterProtocolNotify 时候,当用户load这个protocol的时候就会用这个Entry->Event 对应的函数.
// Register for protocol notifactions on this event
Status = CoreRegisterProtocolNotify (
Entry->ProtocolGuid,
Entry->Event,
&Entry->Registration
);
CoreRegisterProtocolNotify (
IN EFI_GUID *Protocol,
IN EFI_EVENT Event,
OUT VOID **Registration
)
{
PROTOCOL_ENTRY *ProtEntry;
PROTOCOL_NOTIFY *ProtNotify;
EFI_STATUS Status;
if ((Protocol == NULL) || (Event == NULL) || (Registration == NULL)) {
return EFI_INVALID_PARAMETER;
}
CoreAcquireProtocolLock ();
ProtNotify = NULL;
//
// Get the protocol entry to add the notification too
//
ProtEntry = CoreFindProtocolEntry (Protocol, TRUE);
if (ProtEntry != NULL) {
//
// Allocate a new notification record
//
ProtNotify = AllocatePool (sizeof(PROTOCOL_NOTIFY));
if (ProtNotify != NULL) {
((IEVENT *)Event)->ExFlag |= EVT_EXFLAG_EVENT_PROTOCOL_NOTIFICATION;
ProtNotify->Signature = PROTOCOL_NOTIFY_SIGNATURE;
ProtNotify->Protocol = ProtEntry;
ProtNotify->Event = Event;
//
// start at the begining
//
ProtNotify->Position = &ProtEntry->Protocols;
InsertTailList (&ProtEntry->Notify, &ProtNotify->Link);
}
}
CoreReleaseProtocolLock ();
return Status;
}
CoreRegisterProtocolNotify的实现也比较简单,就是找到protocol的ProtEntry,然后申请一个PROTOCOL_NOTIFY。最后将ProtNotify 插入到ProtEntry的列表中,刚好可以和上面调用的函数相对应.