📄 locate.c
字号:
OUT VOID **Interface
)
/*++
Routine Description:
Routine to get the next Handle, when you are searching for a given protocol.
Arguments:
Position - Information about which Handle to seach for.
Interface - Return the interface structure for the matching protocol.
Returns:
IHANDLE - An IHANDLE is returned if the next Position is not the end of the
list. A NULL_HANDLE is returned if it's the end of the list.
--*/
{
IHANDLE *Handle;
LIST_ENTRY *Link;
PROTOCOL_INTERFACE *Prot;
Handle = NULL;
*Interface = NULL;
for (; ;) {
//
// Next entry
//
Link = Position->Position->Flink;
Position->Position = Link;
//
// If not at the end, return the handle
//
if (Link == &Position->ProtEntry->Protocols) {
Handle = NULL;
break;
}
//
// Get the handle
//
Prot = CR(Link, PROTOCOL_INTERFACE, ByProtocol, PROTOCOL_INTERFACE_SIGNATURE);
Handle = (IHANDLE *) Prot->Handle;
*Interface = Prot->Interface;
//
// If this handle has not been returned this request, then
// return it now
//
if (Handle->LocateRequest != EfiLocateHandleRequest) {
Handle->LocateRequest = EfiLocateHandleRequest;
break;
}
}
return Handle;
}
EFI_STATUS
BOOTSERVICE
LocateDevicePath (
IN EFI_GUID *Protocol,
IN OUT EFI_DEVICE_PATH **FilePath,
OUT EFI_HANDLE *Device
)
{
UINTN NoHandles, Index;
INTN BestMatch, SourceSize, Size;
EFI_HANDLE *Handles, Handle;
EFI_DEVICE_PATH *SourcePath, *DevicePath, *Eop, *Inst;
// For now just get it working..
*Device = NULL;
SourcePath = *FilePath;
//
// The source path can only have 1 instance
//
if (DevicePathInstanceCount(SourcePath) != 1) {
DEBUG((D_ERROR, "LocateDevicePath: Device path has too many instances\n"));
return EFI_INVALID_PARAMETER;
}
//
// Get a list of all handles that support the requested protocol
//
LibLocateHandle (ByProtocol, Protocol, NULL, &NoHandles, &Handles);
SourceSize = DevicePathSize(SourcePath) - sizeof(EFI_DEVICE_PATH);
BestMatch = -1;
for(Index = 0; Index < NoHandles; Index += 1) {
Handle = Handles[Index];
DevicePath = DevicePathFromHandle (Handle);
//
// If this handle doesn't support device path, then skip it
//
if (!DevicePath) {
continue;
}
//
// Check each instance
//
while (Inst = DevicePathInstance (&DevicePath, &Size)) {
//
// Check if DevicePath is first part of SourcePath
//
if (Size <= SourceSize &&
CompareMem (SourcePath, Inst, Size) == 0) {
Eop = (EFI_DEVICE_PATH *) (((UINT8 *) Inst) + Size);
if (IsDevicePathEndType(Eop)) {
//
// If the size is equal to the best match, then we
// have a duplice device path for 2 different device
// handles
//
ASSERT (Size != BestMatch);
//
// We've got a match, see if it's the best match so far
//
if (Size > BestMatch) {
BestMatch = Size;
*Device = Handle;
}
}
}
}
}
if (Handles) {
FreePool(Handles);
}
//
// If there wasn't any match, then no parts of the device path
// was found. (which is strange since there is likely a "root level"
// device path in the system
//
if (BestMatch == -1) {
return EFI_NOT_FOUND;
}
//
// Return the remaining part of the device path
//
*FilePath = (EFI_DEVICE_PATH *) (((UINT8 *) SourcePath) + BestMatch);
return EFI_SUCCESS;
}
EFI_STATUS
BOOTSERVICE
LocateProtocol (
EFI_GUID *Protocol,
VOID *Registration, OPTIONAL
VOID **Interface
)
/*++
Routine Description:
Return the first Protocol Interface that matches the Protocol GUID. If
Registration is pasased in return a Protocol Instance that was just add
to the system. If Retistration is NULL return the first Protocol Interface
you find.
Arguments:
Protocol - The protocol to search for
Registration - Optional Registration Key returned from RegisterProtocolNotify()
Interface - Return the Protocol interface (instance).
Returns:
EFI_SUCCESS - If a valid Interface is returned
other - Interface not found and NULL is returned.
--*/
{
EFI_STATUS Status;
LOCATE_POSITION Position;
PROTOCOL_NOTIFY *ProtNotify;
IHANDLE *Handle;
if (Interface == NULL) {
return EFI_INVALID_PARAMETER;
}
*Interface = NULL;
Status = EFI_SUCCESS;
//
// Set initial position
//
Position.Protocol = Protocol;
Position.SearchKey = Registration;
Position.Position = &HandleList;
//
// Lock the protocol database
//
AcquireLock (&ProtocolDatabaseLock);
EfiLocateHandleRequest += 1;
if (NULL == Registration) {
//
// Look up the protocol entry and set the head pointer
//
Position.ProtEntry = FindProtocolEntry (Protocol, FALSE);
if (!Position.ProtEntry) {
Status = EFI_NOT_FOUND;
goto Done;
}
Position.Position = &Position.ProtEntry->Protocols;
Handle = GetNextLocateByProtocol (&Position, Interface);
} else {
Handle = GetNextLocateByRegisterNotify (&Position, Interface);
}
if (NULL == Handle) {
Status = EFI_NOT_FOUND;
} else if (NULL != Registration) {
//
// If this is a search by register notify and a handle was
// returned, update the register notification position
//
ProtNotify = Registration;
ProtNotify->Position = ProtNotify->Position->Flink;
}
Done:
ReleaseLock (&ProtocolDatabaseLock);
return Status;
}
EFI_STATUS
BOOTSERVICE
LocateHandleBuffer (
IN EFI_LOCATE_SEARCH_TYPE SearchType,
IN EFI_GUID *Protocol OPTIONAL,
IN VOID *SearchKey OPTIONAL,
IN OUT UINTN *NumberHandles,
OUT EFI_HANDLE **Buffer
)
/*++
Routine Description:
Function returns an array of handles that support the requested protocol
in a buffer allocated from pool. This is a version of LocateHandle()
that allocates a buffer for the caller.
Arguments:
SearchType - Specifies which handle(s) are to be returned.
Protocol - Provides the protocol to search by.
This parameter is only valid for SearchType ByProtocol.
SearchKey - Supplies the search key depending on the SearchType.
NoHandles - The number of handles returned in Buffer.
Buffer - A pointer to the buffer to return the requested array of
handles that support Protocol.
Returns:
EFI_SUCCESS - The result array of handles was returned.
EFI_NOT_FOUND - No handles match the search.
EFI_OUT_OF_RESOURCES - There is not enough pool memory to store the matching results.
EFI_INVALIDE_PARAMETER - One of the parameters has an invalid value.
--*/
{
EFI_STATUS Status;
UINTN BufferSize;
if (NumberHandles == NULL) {
return EFI_INVALID_PARAMETER;
}
if (Buffer == NULL) {
return EFI_INVALID_PARAMETER;
}
BufferSize = 0;
*NumberHandles = 0;
*Buffer = NULL;
Status = LocateHandle (
SearchType, Protocol, SearchKey,
&BufferSize, *Buffer
);
//
//EFI_INVALID_PARAMETER should be returned if one of the parameters is invalid, otherwise return EFI_NOT_FOUND.
//
switch(Status){
case EFI_BUFFER_TOO_SMALL:
break;
case EFI_INVALID_PARAMETER:
return Status;
default:
return EFI_NOT_FOUND;
}
Status = BS->AllocatePool (EfiBootServicesData, BufferSize, (VOID *)Buffer);
if (EFI_ERROR (Status)) {
return Status;
}
Status = LocateHandle (
SearchType, Protocol, SearchKey,
&BufferSize, *Buffer
);
*NumberHandles = BufferSize/sizeof(EFI_HANDLE);
if (EFI_ERROR(Status)) {
*NumberHandles = 0;
}
return Status;
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -