mirror of
https://github.com/acidanthera/OpenCorePkg.git
synced 2025-12-08 19:25:01 +00:00
539 lines
19 KiB
C
539 lines
19 KiB
C
/** @file
|
|
Provides interface to shell functionality for shell commands and applications.
|
|
|
|
(C) Copyright 2016 Hewlett Packard Enterprise Development LP<BR>
|
|
Copyright 2016-2018 Dell Technologies.<BR>
|
|
Copyright (c) 2006 - 2019, Intel Corporation. All rights reserved.<BR>
|
|
SPDX-License-Identifier: BSD-2-Clause-Patent
|
|
|
|
**/
|
|
|
|
#include <Uefi.h>
|
|
#include <Library/BaseLib.h>
|
|
#include <Library/BaseMemoryLib.h>
|
|
#include <Library/DebugLib.h>
|
|
#include <Library/MemoryAllocationLib.h>
|
|
#include <Library/UefiLib.h>
|
|
#include <Library/UefiBootServicesTableLib.h>
|
|
#include <Protocol/LoadedImage.h>
|
|
|
|
#include "HandleParsingMin.h"
|
|
|
|
STATIC HANDLE_INDEX_LIST mHandleList = {
|
|
{
|
|
{ NULL, NULL }, 0, 0
|
|
}, 0
|
|
};
|
|
|
|
/**
|
|
Function to initialize the file global mHandleList object for use in
|
|
vonverting handles to index and index to handle.
|
|
|
|
@retval EFI_SUCCESS The operation was successful.
|
|
**/
|
|
STATIC
|
|
EFI_STATUS
|
|
InternalShellInitHandleList (
|
|
VOID
|
|
)
|
|
{
|
|
EFI_STATUS Status;
|
|
EFI_HANDLE *HandleBuffer;
|
|
UINTN HandleCount;
|
|
HANDLE_LIST *ListWalker;
|
|
|
|
if (mHandleList.NextIndex != 0) {
|
|
return EFI_SUCCESS;
|
|
}
|
|
|
|
InitializeListHead (&mHandleList.List.Link);
|
|
mHandleList.NextIndex = 1;
|
|
Status = gBS->LocateHandleBuffer (
|
|
AllHandles,
|
|
NULL,
|
|
NULL,
|
|
&HandleCount,
|
|
&HandleBuffer
|
|
);
|
|
ASSERT_EFI_ERROR (Status);
|
|
if (EFI_ERROR (Status)) {
|
|
return (Status);
|
|
}
|
|
|
|
for (mHandleList.NextIndex = 1; mHandleList.NextIndex <= HandleCount; mHandleList.NextIndex++) {
|
|
ListWalker = AllocateZeroPool (sizeof (HANDLE_LIST));
|
|
if (ListWalker != NULL) {
|
|
ListWalker->TheHandle = HandleBuffer[mHandleList.NextIndex - 1];
|
|
ListWalker->TheIndex = mHandleList.NextIndex;
|
|
InsertTailList (&mHandleList.List.Link, &ListWalker->Link);
|
|
}
|
|
}
|
|
|
|
FreePool (HandleBuffer);
|
|
return (EFI_SUCCESS);
|
|
}
|
|
|
|
/**
|
|
Function to retrieve the human-friendly index of a given handle. If the handle
|
|
does not have a index one will be automatically assigned. The index value is valid
|
|
until the termination of the shell application.
|
|
|
|
@param[in] TheHandle The handle to retrieve an index for.
|
|
|
|
@retval 0 A memory allocation failed.
|
|
@return The index of the handle.
|
|
|
|
**/
|
|
UINTN
|
|
EFIAPI
|
|
InternalConvertHandleToHandleIndex (
|
|
IN CONST EFI_HANDLE TheHandle
|
|
)
|
|
{
|
|
EFI_STATUS Status;
|
|
EFI_GUID **ProtocolBuffer;
|
|
UINTN ProtocolCount;
|
|
HANDLE_LIST *ListWalker;
|
|
|
|
if (TheHandle == NULL) {
|
|
return 0;
|
|
}
|
|
|
|
InternalShellInitHandleList ();
|
|
|
|
for (ListWalker = (HANDLE_LIST *)GetFirstNode (&mHandleList.List.Link)
|
|
; !IsNull (&mHandleList.List.Link, &ListWalker->Link)
|
|
; ListWalker = (HANDLE_LIST *)GetNextNode (&mHandleList.List.Link, &ListWalker->Link)
|
|
)
|
|
{
|
|
if (ListWalker->TheHandle == TheHandle) {
|
|
//
|
|
// Verify that TheHandle is still present in the Handle Database
|
|
//
|
|
Status = gBS->ProtocolsPerHandle (TheHandle, &ProtocolBuffer, &ProtocolCount);
|
|
if (EFI_ERROR (Status)) {
|
|
//
|
|
// TheHandle is not present in the Handle Database, so delete from the handle list
|
|
//
|
|
RemoveEntryList (&ListWalker->Link);
|
|
return 0;
|
|
}
|
|
|
|
FreePool (ProtocolBuffer);
|
|
return (ListWalker->TheIndex);
|
|
}
|
|
}
|
|
|
|
//
|
|
// Verify that TheHandle is valid handle
|
|
//
|
|
Status = gBS->ProtocolsPerHandle (TheHandle, &ProtocolBuffer, &ProtocolCount);
|
|
if (EFI_ERROR (Status)) {
|
|
//
|
|
// TheHandle is not valid, so do not add to handle list
|
|
//
|
|
return 0;
|
|
}
|
|
|
|
FreePool (ProtocolBuffer);
|
|
|
|
ListWalker = AllocateZeroPool (sizeof (HANDLE_LIST));
|
|
if (ListWalker == NULL) {
|
|
return 0;
|
|
}
|
|
|
|
ListWalker->TheHandle = TheHandle;
|
|
ListWalker->TheIndex = mHandleList.NextIndex++;
|
|
InsertTailList (&mHandleList.List.Link, &ListWalker->Link);
|
|
return (ListWalker->TheIndex);
|
|
}
|
|
|
|
/**
|
|
Gets all the related EFI_HANDLEs based on the mask supplied.
|
|
|
|
This function scans all EFI_HANDLES in the UEFI environment's handle database
|
|
and returns the ones with the specified relationship (Mask) to the specified
|
|
controller handle.
|
|
|
|
If both DriverBindingHandle and ControllerHandle are NULL, then ASSERT.
|
|
If MatchingHandleCount is NULL, then ASSERT.
|
|
|
|
If MatchingHandleBuffer is not NULL upon a successful return the memory must be
|
|
caller freed.
|
|
|
|
@param[in] DriverBindingHandle The handle with Driver Binding protocol on it.
|
|
@param[in] ControllerHandle The handle with Device Path protocol on it.
|
|
@param[in] MatchingHandleCount The pointer to UINTN that specifies the number of HANDLES in
|
|
MatchingHandleBuffer.
|
|
@param[out] MatchingHandleBuffer On a successful return, a buffer of MatchingHandleCount
|
|
EFI_HANDLEs with a terminating NULL EFI_HANDLE.
|
|
@param[out] HandleType An array of type information.
|
|
|
|
@retval EFI_SUCCESS The operation was successful, and any related handles
|
|
are in MatchingHandleBuffer.
|
|
@retval EFI_NOT_FOUND No matching handles were found.
|
|
@retval EFI_INVALID_PARAMETER A parameter was invalid or out of range.
|
|
**/
|
|
STATIC
|
|
EFI_STATUS
|
|
EFIAPI
|
|
ParseHandleDatabaseByRelationshipWithType (
|
|
IN CONST EFI_HANDLE DriverBindingHandle OPTIONAL,
|
|
IN CONST EFI_HANDLE ControllerHandle OPTIONAL,
|
|
IN UINTN *HandleCount,
|
|
OUT EFI_HANDLE **HandleBuffer,
|
|
OUT UINTN **HandleType
|
|
)
|
|
{
|
|
EFI_STATUS Status;
|
|
UINTN HandleIndex;
|
|
EFI_GUID **ProtocolGuidArray;
|
|
UINTN ArrayCount;
|
|
UINTN ProtocolIndex;
|
|
EFI_OPEN_PROTOCOL_INFORMATION_ENTRY *OpenInfo;
|
|
UINTN OpenInfoCount;
|
|
UINTN OpenInfoIndex;
|
|
UINTN ChildIndex;
|
|
INTN DriverBindingHandleIndex;
|
|
|
|
ASSERT (HandleCount != NULL);
|
|
ASSERT (HandleBuffer != NULL);
|
|
ASSERT (HandleType != NULL);
|
|
ASSERT (DriverBindingHandle != NULL || ControllerHandle != NULL);
|
|
|
|
*HandleCount = 0;
|
|
*HandleBuffer = NULL;
|
|
*HandleType = NULL;
|
|
|
|
//
|
|
// Retrieve the list of all handles from the handle database
|
|
//
|
|
Status = gBS->LocateHandleBuffer (
|
|
AllHandles,
|
|
NULL,
|
|
NULL,
|
|
HandleCount,
|
|
HandleBuffer
|
|
);
|
|
if (EFI_ERROR (Status)) {
|
|
return (Status);
|
|
}
|
|
|
|
*HandleType = AllocateZeroPool (*HandleCount * sizeof (UINTN));
|
|
if (*HandleType == NULL) {
|
|
if (*HandleBuffer != NULL) {
|
|
FreePool (*HandleBuffer);
|
|
*HandleBuffer = NULL;
|
|
}
|
|
|
|
*HandleCount = 0;
|
|
return EFI_OUT_OF_RESOURCES;
|
|
}
|
|
|
|
DriverBindingHandleIndex = -1;
|
|
for (HandleIndex = 0; HandleIndex < *HandleCount; HandleIndex++) {
|
|
if ((DriverBindingHandle != NULL) && ((*HandleBuffer)[HandleIndex] == DriverBindingHandle)) {
|
|
DriverBindingHandleIndex = (INTN)HandleIndex;
|
|
}
|
|
}
|
|
|
|
for (HandleIndex = 0; HandleIndex < *HandleCount; HandleIndex++) {
|
|
//
|
|
// Retrieve the list of all the protocols on each handle
|
|
//
|
|
Status = gBS->ProtocolsPerHandle (
|
|
(*HandleBuffer)[HandleIndex],
|
|
&ProtocolGuidArray,
|
|
&ArrayCount
|
|
);
|
|
if (EFI_ERROR (Status)) {
|
|
continue;
|
|
}
|
|
|
|
for (ProtocolIndex = 0; ProtocolIndex < ArrayCount; ProtocolIndex++) {
|
|
//
|
|
// Set the bit describing what this handle has
|
|
//
|
|
if (CompareGuid (ProtocolGuidArray[ProtocolIndex], &gEfiLoadedImageProtocolGuid)) {
|
|
(*HandleType)[HandleIndex] |= (UINTN)HR_IMAGE_HANDLE;
|
|
} else if (CompareGuid (ProtocolGuidArray[ProtocolIndex], &gEfiDriverBindingProtocolGuid)) {
|
|
(*HandleType)[HandleIndex] |= (UINTN)HR_DRIVER_BINDING_HANDLE;
|
|
} else if (CompareGuid (ProtocolGuidArray[ProtocolIndex], &gEfiDriverConfiguration2ProtocolGuid)) {
|
|
(*HandleType)[HandleIndex] |= (UINTN)HR_DRIVER_CONFIGURATION_HANDLE;
|
|
} else if (CompareGuid (ProtocolGuidArray[ProtocolIndex], &gEfiDriverConfigurationProtocolGuid)) {
|
|
(*HandleType)[HandleIndex] |= (UINTN)HR_DRIVER_CONFIGURATION_HANDLE;
|
|
} else if (CompareGuid (ProtocolGuidArray[ProtocolIndex], &gEfiDriverDiagnostics2ProtocolGuid)) {
|
|
(*HandleType)[HandleIndex] |= (UINTN)HR_DRIVER_DIAGNOSTICS_HANDLE;
|
|
} else if (CompareGuid (ProtocolGuidArray[ProtocolIndex], &gEfiDriverDiagnosticsProtocolGuid)) {
|
|
(*HandleType)[HandleIndex] |= (UINTN)HR_DRIVER_DIAGNOSTICS_HANDLE;
|
|
} else if (CompareGuid (ProtocolGuidArray[ProtocolIndex], &gEfiComponentName2ProtocolGuid)) {
|
|
(*HandleType)[HandleIndex] |= (UINTN)HR_COMPONENT_NAME_HANDLE;
|
|
} else if (CompareGuid (ProtocolGuidArray[ProtocolIndex], &gEfiComponentNameProtocolGuid)) {
|
|
(*HandleType)[HandleIndex] |= (UINTN)HR_COMPONENT_NAME_HANDLE;
|
|
} else if (CompareGuid (ProtocolGuidArray[ProtocolIndex], &gEfiDevicePathProtocolGuid)) {
|
|
(*HandleType)[HandleIndex] |= (UINTN)HR_DEVICE_HANDLE;
|
|
}
|
|
|
|
//
|
|
// Retrieve the list of agents that have opened each protocol
|
|
//
|
|
Status = gBS->OpenProtocolInformation (
|
|
(*HandleBuffer)[HandleIndex],
|
|
ProtocolGuidArray[ProtocolIndex],
|
|
&OpenInfo,
|
|
&OpenInfoCount
|
|
);
|
|
if (EFI_ERROR (Status)) {
|
|
continue;
|
|
}
|
|
|
|
if (ControllerHandle == NULL) {
|
|
//
|
|
// ControllerHandle == NULL and DriverBindingHandle != NULL.
|
|
// Return information on all the controller handles that the driver specified by DriverBindingHandle is managing
|
|
//
|
|
for (OpenInfoIndex = 0; OpenInfoIndex < OpenInfoCount; OpenInfoIndex++) {
|
|
if ((OpenInfo[OpenInfoIndex].AgentHandle == DriverBindingHandle) && ((OpenInfo[OpenInfoIndex].Attributes & EFI_OPEN_PROTOCOL_BY_DRIVER) != 0)) {
|
|
(*HandleType)[HandleIndex] |= (UINTN)(HR_DEVICE_HANDLE | HR_CONTROLLER_HANDLE);
|
|
if (DriverBindingHandleIndex != -1) {
|
|
(*HandleType)[DriverBindingHandleIndex] |= (UINTN)HR_DEVICE_DRIVER;
|
|
}
|
|
}
|
|
|
|
if ((OpenInfo[OpenInfoIndex].AgentHandle == DriverBindingHandle) && ((OpenInfo[OpenInfoIndex].Attributes & EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER) != 0)) {
|
|
(*HandleType)[HandleIndex] |= (UINTN)(HR_DEVICE_HANDLE | HR_CONTROLLER_HANDLE);
|
|
if (DriverBindingHandleIndex != -1) {
|
|
(*HandleType)[DriverBindingHandleIndex] |= (UINTN)(HR_BUS_DRIVER | HR_DEVICE_DRIVER);
|
|
}
|
|
|
|
for (ChildIndex = 0; ChildIndex < *HandleCount; ChildIndex++) {
|
|
if (OpenInfo[OpenInfoIndex].ControllerHandle == (*HandleBuffer)[ChildIndex]) {
|
|
(*HandleType)[ChildIndex] |= (UINTN)(HR_DEVICE_HANDLE | HR_CHILD_HANDLE);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
if ((DriverBindingHandle == NULL) && (ControllerHandle != NULL)) {
|
|
if (ControllerHandle == (*HandleBuffer)[HandleIndex]) {
|
|
(*HandleType)[HandleIndex] |= (UINTN)(HR_DEVICE_HANDLE | HR_CONTROLLER_HANDLE);
|
|
for (OpenInfoIndex = 0; OpenInfoIndex < OpenInfoCount; OpenInfoIndex++) {
|
|
if ((OpenInfo[OpenInfoIndex].Attributes & EFI_OPEN_PROTOCOL_BY_DRIVER) != 0) {
|
|
for (ChildIndex = 0; ChildIndex < *HandleCount; ChildIndex++) {
|
|
if (OpenInfo[OpenInfoIndex].AgentHandle == (*HandleBuffer)[ChildIndex]) {
|
|
(*HandleType)[ChildIndex] |= (UINTN)HR_DEVICE_DRIVER;
|
|
}
|
|
}
|
|
}
|
|
|
|
if ((OpenInfo[OpenInfoIndex].Attributes & EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER) != 0) {
|
|
for (ChildIndex = 0; ChildIndex < *HandleCount; ChildIndex++) {
|
|
if (OpenInfo[OpenInfoIndex].AgentHandle == (*HandleBuffer)[ChildIndex]) {
|
|
(*HandleType)[ChildIndex] |= (UINTN)(HR_BUS_DRIVER | HR_DEVICE_DRIVER);
|
|
}
|
|
|
|
if (OpenInfo[OpenInfoIndex].ControllerHandle == (*HandleBuffer)[ChildIndex]) {
|
|
(*HandleType)[ChildIndex] |= (UINTN)(HR_DEVICE_HANDLE | HR_CHILD_HANDLE);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
} else {
|
|
for (OpenInfoIndex = 0; OpenInfoIndex < OpenInfoCount; OpenInfoIndex++) {
|
|
if ((OpenInfo[OpenInfoIndex].Attributes & EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER) != 0) {
|
|
if (OpenInfo[OpenInfoIndex].ControllerHandle == ControllerHandle) {
|
|
(*HandleType)[HandleIndex] |= (UINTN)(HR_DEVICE_HANDLE | HR_PARENT_HANDLE);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
if ((DriverBindingHandle != NULL) && (ControllerHandle != NULL)) {
|
|
if (ControllerHandle == (*HandleBuffer)[HandleIndex]) {
|
|
(*HandleType)[HandleIndex] |= (UINTN)(HR_DEVICE_HANDLE | HR_CONTROLLER_HANDLE);
|
|
for (OpenInfoIndex = 0; OpenInfoIndex < OpenInfoCount; OpenInfoIndex++) {
|
|
if ((OpenInfo[OpenInfoIndex].Attributes & EFI_OPEN_PROTOCOL_BY_DRIVER) != 0) {
|
|
if (OpenInfo[OpenInfoIndex].AgentHandle == DriverBindingHandle) {
|
|
if (DriverBindingHandleIndex != -1) {
|
|
(*HandleType)[DriverBindingHandleIndex] |= (UINTN)HR_DEVICE_DRIVER;
|
|
}
|
|
}
|
|
}
|
|
|
|
if ((OpenInfo[OpenInfoIndex].Attributes & EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER) != 0) {
|
|
if (OpenInfo[OpenInfoIndex].AgentHandle == DriverBindingHandle) {
|
|
for (ChildIndex = 0; ChildIndex < *HandleCount; ChildIndex++) {
|
|
if (OpenInfo[OpenInfoIndex].ControllerHandle == (*HandleBuffer)[ChildIndex]) {
|
|
(*HandleType)[ChildIndex] |= (UINTN)(HR_DEVICE_HANDLE | HR_CHILD_HANDLE);
|
|
}
|
|
}
|
|
}
|
|
|
|
for (ChildIndex = 0; ChildIndex < *HandleCount; ChildIndex++) {
|
|
if (OpenInfo[OpenInfoIndex].AgentHandle == (*HandleBuffer)[ChildIndex]) {
|
|
(*HandleType)[ChildIndex] |= (UINTN)(HR_BUS_DRIVER | HR_DEVICE_DRIVER);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
} else {
|
|
for (OpenInfoIndex = 0; OpenInfoIndex < OpenInfoCount; OpenInfoIndex++) {
|
|
if ((OpenInfo[OpenInfoIndex].Attributes & EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER) != 0) {
|
|
if (OpenInfo[OpenInfoIndex].ControllerHandle == ControllerHandle) {
|
|
(*HandleType)[HandleIndex] |= (UINTN)(HR_DEVICE_HANDLE | HR_PARENT_HANDLE);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
FreePool (OpenInfo);
|
|
}
|
|
|
|
FreePool (ProtocolGuidArray);
|
|
}
|
|
|
|
return EFI_SUCCESS;
|
|
}
|
|
|
|
/**
|
|
Gets all the related EFI_HANDLEs based on the single EFI_HANDLE and the mask
|
|
supplied.
|
|
|
|
This function will scan all EFI_HANDLES in the UEFI environment's handle database
|
|
and return all the ones with the specified relationship (Mask) to the specified
|
|
controller handle.
|
|
|
|
If both DriverBindingHandle and ControllerHandle are NULL, then ASSERT.
|
|
If MatchingHandleCount is NULL, then ASSERT.
|
|
|
|
If MatchingHandleBuffer is not NULL upon a sucessful return the memory must be
|
|
caller freed.
|
|
|
|
@param[in] DriverBindingHandle Handle to a object with Driver Binding protocol
|
|
on it.
|
|
@param[in] ControllerHandle Handle to a device with Device Path protocol on it.
|
|
@param[in] Mask Mask of what relationship(s) is desired.
|
|
@param[in] MatchingHandleCount Poitner to UINTN specifying number of HANDLES in
|
|
MatchingHandleBuffer.
|
|
@param[out] MatchingHandleBuffer On a sucessful return a buffer of MatchingHandleCount
|
|
EFI_HANDLEs and a terminating NULL EFI_HANDLE.
|
|
|
|
@retval EFI_SUCCESS The operation was sucessful and any related handles
|
|
are in MatchingHandleBuffer;
|
|
@retval EFI_NOT_FOUND No matching handles were found.
|
|
@retval EFI_INVALID_PARAMETER A parameter was invalid or out of range.
|
|
**/
|
|
EFI_STATUS
|
|
EFIAPI
|
|
InternalParseHandleDatabaseByRelationship (
|
|
IN CONST EFI_HANDLE DriverBindingHandle OPTIONAL,
|
|
IN CONST EFI_HANDLE ControllerHandle OPTIONAL,
|
|
IN CONST UINTN Mask,
|
|
IN UINTN *MatchingHandleCount,
|
|
OUT EFI_HANDLE **MatchingHandleBuffer OPTIONAL
|
|
)
|
|
{
|
|
EFI_STATUS Status;
|
|
UINTN HandleCount;
|
|
EFI_HANDLE *HandleBuffer;
|
|
UINTN *HandleType;
|
|
UINTN HandleIndex;
|
|
|
|
ASSERT (MatchingHandleCount != NULL);
|
|
ASSERT (DriverBindingHandle != NULL || ControllerHandle != NULL);
|
|
|
|
if ((Mask & HR_VALID_MASK) != Mask) {
|
|
return (EFI_INVALID_PARAMETER);
|
|
}
|
|
|
|
if (((Mask & HR_CHILD_HANDLE) != 0) && (DriverBindingHandle == NULL)) {
|
|
return (EFI_INVALID_PARAMETER);
|
|
}
|
|
|
|
*MatchingHandleCount = 0;
|
|
if (MatchingHandleBuffer != NULL) {
|
|
*MatchingHandleBuffer = NULL;
|
|
}
|
|
|
|
HandleBuffer = NULL;
|
|
HandleType = NULL;
|
|
|
|
Status = ParseHandleDatabaseByRelationshipWithType (
|
|
DriverBindingHandle,
|
|
ControllerHandle,
|
|
&HandleCount,
|
|
&HandleBuffer,
|
|
&HandleType
|
|
);
|
|
if (!EFI_ERROR (Status)) {
|
|
//
|
|
// Count the number of handles that match the attributes in Mask
|
|
//
|
|
for (HandleIndex = 0; HandleIndex < HandleCount; HandleIndex++) {
|
|
if ((HandleType[HandleIndex] & Mask) == Mask) {
|
|
(*MatchingHandleCount)++;
|
|
}
|
|
}
|
|
|
|
//
|
|
// If no handles match the attributes in Mask then return EFI_NOT_FOUND
|
|
//
|
|
if (*MatchingHandleCount == 0) {
|
|
Status = EFI_NOT_FOUND;
|
|
} else {
|
|
if (MatchingHandleBuffer == NULL) {
|
|
//
|
|
// Someone just wanted the count...
|
|
//
|
|
Status = EFI_SUCCESS;
|
|
} else {
|
|
//
|
|
// Allocate a handle buffer for the number of handles that matched the attributes in Mask
|
|
//
|
|
*MatchingHandleBuffer = AllocateZeroPool ((*MatchingHandleCount +1)* sizeof (EFI_HANDLE));
|
|
if (*MatchingHandleBuffer == NULL) {
|
|
Status = EFI_OUT_OF_RESOURCES;
|
|
} else {
|
|
for (HandleIndex = 0, *MatchingHandleCount = 0
|
|
; HandleIndex < HandleCount
|
|
; HandleIndex++
|
|
)
|
|
{
|
|
//
|
|
// Fill the allocated buffer with the handles that matched the attributes in Mask
|
|
//
|
|
if ((HandleType[HandleIndex] & Mask) == Mask) {
|
|
(*MatchingHandleBuffer)[(*MatchingHandleCount)++] = HandleBuffer[HandleIndex];
|
|
}
|
|
}
|
|
|
|
//
|
|
// Make the last one NULL
|
|
//
|
|
(*MatchingHandleBuffer)[*MatchingHandleCount] = NULL;
|
|
|
|
Status = EFI_SUCCESS;
|
|
} // *MatchingHandleBuffer == NULL (ELSE)
|
|
} // MacthingHandleBuffer == NULL (ELSE)
|
|
} // *MatchingHandleCount == 0 (ELSE)
|
|
} // no error on ParseHandleDatabaseByRelationshipWithType
|
|
|
|
if (HandleBuffer != NULL) {
|
|
FreePool (HandleBuffer);
|
|
}
|
|
|
|
if (HandleType != NULL) {
|
|
FreePool (HandleType);
|
|
}
|
|
|
|
ASSERT (
|
|
(MatchingHandleBuffer == NULL) ||
|
|
(*MatchingHandleCount == 0 && *MatchingHandleBuffer == NULL) ||
|
|
(*MatchingHandleCount != 0 && *MatchingHandleBuffer != NULL)
|
|
);
|
|
return Status;
|
|
}
|