2 Provides interface to advanced shell functionality for parsing both handle and protocol database.
4 Copyright (c) 2013 Hewlett-Packard Development Company, L.P.
5 Copyright (c) 2010 - 2014, Intel Corporation. All rights reserved.<BR>
6 This program and the accompanying materials
7 are licensed and made available under the terms and conditions of the BSD License
8 which accompanies this distribution. The full text of the license may be found at
9 http://opensource.org/licenses/bsd-license.php
11 THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
12 WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
16 #include "UefiHandleParsingLib.h"
17 #include "IndustryStandard/Acpi10.h"
19 EFI_HANDLE mHandleParsingHiiHandle
;
20 HANDLE_INDEX_LIST mHandleList
= {{{NULL
,NULL
},0,0},0};
23 Function to translate the EFI_MEMORY_TYPE into a string.
25 @param[in] Memory The memory type.
27 @retval A string representation of the type allocated from BS Pool.
32 IN CONST EFI_MEMORY_TYPE Memory
39 case EfiReservedMemoryType
: StrnCatGrow(&RetVal
, NULL
, L
"EfiReservedMemoryType", 0); break;
40 case EfiLoaderCode
: StrnCatGrow(&RetVal
, NULL
, L
"EfiLoaderCode", 0); break;
41 case EfiLoaderData
: StrnCatGrow(&RetVal
, NULL
, L
"EfiLoaderData", 0); break;
42 case EfiBootServicesCode
: StrnCatGrow(&RetVal
, NULL
, L
"EfiBootServicesCode", 0); break;
43 case EfiBootServicesData
: StrnCatGrow(&RetVal
, NULL
, L
"EfiBootServicesData", 0); break;
44 case EfiRuntimeServicesCode
: StrnCatGrow(&RetVal
, NULL
, L
"EfiRuntimeServicesCode", 0); break;
45 case EfiRuntimeServicesData
: StrnCatGrow(&RetVal
, NULL
, L
"EfiRuntimeServicesData", 0); break;
46 case EfiConventionalMemory
: StrnCatGrow(&RetVal
, NULL
, L
"EfiConventionalMemory", 0); break;
47 case EfiUnusableMemory
: StrnCatGrow(&RetVal
, NULL
, L
"EfiUnusableMemory", 0); break;
48 case EfiACPIReclaimMemory
: StrnCatGrow(&RetVal
, NULL
, L
"EfiACPIReclaimMemory", 0); break;
49 case EfiACPIMemoryNVS
: StrnCatGrow(&RetVal
, NULL
, L
"EfiACPIMemoryNVS", 0); break;
50 case EfiMemoryMappedIO
: StrnCatGrow(&RetVal
, NULL
, L
"EfiMemoryMappedIO", 0); break;
51 case EfiMemoryMappedIOPortSpace
: StrnCatGrow(&RetVal
, NULL
, L
"EfiMemoryMappedIOPortSpace", 0); break;
52 case EfiPalCode
: StrnCatGrow(&RetVal
, NULL
, L
"EfiPalCode", 0); break;
53 case EfiMaxMemoryType
: StrnCatGrow(&RetVal
, NULL
, L
"EfiMaxMemoryType", 0); break;
54 default: ASSERT(FALSE
);
60 Constructor for the library.
62 @param[in] ImageHandle Ignored.
63 @param[in] SystemTable Ignored.
65 @retval EFI_SUCCESS The operation was successful.
69 HandleParsingLibConstructor (
70 IN EFI_HANDLE ImageHandle
,
71 IN EFI_SYSTEM_TABLE
*SystemTable
74 mHandleParsingHiiHandle
= HiiAddPackages (&gHandleParsingHiiGuid
, gImageHandle
, UefiHandleParsingLibStrings
, NULL
);
75 if (mHandleParsingHiiHandle
== NULL
) {
76 return (EFI_DEVICE_ERROR
);
83 Destructor for the library. free any resources.
85 @param[in] ImageHandle Ignored.
86 @param[in] SystemTable Ignored.
88 @retval EFI_SUCCESS The operation was successful.
92 HandleParsingLibDestructor (
93 IN EFI_HANDLE ImageHandle
,
94 IN EFI_SYSTEM_TABLE
*SystemTable
97 if (mHandleParsingHiiHandle
!= NULL
) {
98 HiiRemovePackages(mHandleParsingHiiHandle
);
100 return (EFI_SUCCESS
);
104 Function to dump information about LoadedImage.
106 This will allocate the return buffer from boot services pool.
108 @param[in] TheHandle The handle that has LoadedImage installed.
109 @param[in] Verbose TRUE for additional information, FALSE otherwise.
111 @retval A poitner to a string containing the information.
115 LoadedImageProtocolDumpInformation(
116 IN CONST EFI_HANDLE TheHandle
,
117 IN CONST BOOLEAN Verbose
120 EFI_LOADED_IMAGE_PROTOCOL
*LoadedImage
;
128 return (CatSPrint(NULL
, L
"LoadedImage"));
131 Temp
= HiiGetString(mHandleParsingHiiHandle
, STRING_TOKEN(STR_LI_DUMP_MAIN
), NULL
);
132 RetVal
= AllocateZeroPool (PcdGet16 (PcdShellPrintBufferSize
));
133 if (Temp
== NULL
|| RetVal
== NULL
) {
134 SHELL_FREE_NON_NULL(Temp
);
135 SHELL_FREE_NON_NULL(RetVal
);
139 Status
= gBS
->OpenProtocol (
141 &gEfiLoadedImageProtocolGuid
,
142 (VOID
**)&LoadedImage
,
145 EFI_OPEN_PROTOCOL_GET_PROTOCOL
148 DataType
= ConvertMemoryType(LoadedImage
->ImageDataType
);
149 CodeType
= ConvertMemoryType(LoadedImage
->ImageCodeType
);
151 RetVal
= CatSPrint(RetVal
,
153 LoadedImage
->Revision
,
154 LoadedImage
->ParentHandle
,
155 LoadedImage
->SystemTable
,
156 LoadedImage
->DeviceHandle
,
157 LoadedImage
->FilePath
,
158 LoadedImage
->LoadOptionsSize
,
159 LoadedImage
->LoadOptions
,
160 LoadedImage
->ImageBase
,
161 LoadedImage
->ImageSize
,
164 LoadedImage
->Unload
);
167 SHELL_FREE_NON_NULL(Temp
);
168 SHELL_FREE_NON_NULL(CodeType
);
169 SHELL_FREE_NON_NULL(DataType
);
175 Function to dump information about PciRootBridgeIo.
177 This will allocate the return buffer from boot services pool.
179 @param[in] TheHandle The handle that has PciRootBridgeIo installed.
180 @param[in] Verbose TRUE for additional information, FALSE otherwise.
182 @retval A poitner to a string containing the information.
186 PciRootBridgeIoDumpInformation(
187 IN CONST EFI_HANDLE TheHandle
,
188 IN CONST BOOLEAN Verbose
191 EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL
*PciRootBridgeIo
;
192 EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR
*Configuration
;
203 return (CatSPrint(NULL
, L
"PciRootBridgeIo"));
206 Status
= gBS
->HandleProtocol(
208 &gEfiPciRootBridgeIoProtocolGuid
,
209 (VOID
**)&PciRootBridgeIo
);
211 if (EFI_ERROR(Status
)) {
215 Temp
= HiiGetString(mHandleParsingHiiHandle
, STRING_TOKEN(STR_PCIRB_DUMP_PH
), NULL
);
216 ASSERT (Temp
!= NULL
);
217 Temp2
= CatSPrint(L
"\r\n", Temp
, PciRootBridgeIo
->ParentHandle
);
222 Temp
= HiiGetString(mHandleParsingHiiHandle
, STRING_TOKEN(STR_PCIRB_DUMP_SEG
), NULL
);
223 ASSERT (Temp
!= NULL
);
224 Temp2
= CatSPrint(RetVal
, Temp
, PciRootBridgeIo
->SegmentNumber
);
232 Status
= PciRootBridgeIo
->GetAttributes (PciRootBridgeIo
, &Supports
, &Attributes
);
233 if (!EFI_ERROR(Status
)) {
234 Temp
= HiiGetString(mHandleParsingHiiHandle
, STRING_TOKEN(STR_PCIRB_DUMP_ATT
), NULL
);
235 ASSERT (Temp
!= NULL
);
236 Temp2
= CatSPrint(RetVal
, Temp
, Attributes
);
242 Temp
= HiiGetString(mHandleParsingHiiHandle
, STRING_TOKEN(STR_PCIRB_DUMP_SUPPORTS
), NULL
);
243 ASSERT (Temp
!= NULL
);
244 Temp2
= CatSPrint(RetVal
, Temp
, Supports
);
251 Configuration
= NULL
;
252 Status
= PciRootBridgeIo
->Configuration (PciRootBridgeIo
, (VOID
**) &Configuration
);
253 if (!EFI_ERROR(Status
) && Configuration
!= NULL
) {
254 Temp
= HiiGetString(mHandleParsingHiiHandle
, STRING_TOKEN(STR_PCIRB_DUMP_TITLE
), NULL
);
255 ASSERT (Temp
!= NULL
);
256 Temp2
= CatSPrint(RetVal
, Temp
, Supports
);
261 while (Configuration
->Desc
== ACPI_ADDRESS_SPACE_DESCRIPTOR
) {
263 switch (Configuration
->ResType
) {
264 case ACPI_ADDRESS_SPACE_TYPE_MEM
:
265 Temp
= HiiGetString(mHandleParsingHiiHandle
, STRING_TOKEN(STR_PCIRB_DUMP_MEM
), NULL
);
267 case ACPI_ADDRESS_SPACE_TYPE_IO
:
268 Temp
= HiiGetString(mHandleParsingHiiHandle
, STRING_TOKEN(STR_PCIRB_DUMP_IO
), NULL
);
270 case ACPI_ADDRESS_SPACE_TYPE_BUS
:
271 Temp
= HiiGetString(mHandleParsingHiiHandle
, STRING_TOKEN(STR_PCIRB_DUMP_BUS
), NULL
);
275 Temp2
= CatSPrint(RetVal
, L
"%s", Temp
);
282 Temp2
= CatSPrint(RetVal
,
283 L
"%H%02x %016lx %016lx %02x%N\r\n",
284 Configuration
->SpecificFlag
,
285 Configuration
->AddrRangeMin
,
286 Configuration
->AddrRangeMax
,
287 Configuration
->AddrSpaceGranularity
299 Function to dump information about SimpleTextOut.
301 This will allocate the return buffer from boot services pool.
303 @param[in] TheHandle The handle that has SimpleTextOut installed.
304 @param[in] Verbose TRUE for additional information, FALSE otherwise.
306 @retval A poitner to a string containing the information.
310 TxtOutProtocolDumpInformation(
311 IN CONST EFI_HANDLE TheHandle
,
312 IN CONST BOOLEAN Verbose
315 EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL
*Dev
;
332 Status
= gBS
->HandleProtocol(
334 &gEfiSimpleTextOutProtocolGuid
,
337 ASSERT_EFI_ERROR(Status
);
338 ASSERT (Dev
!= NULL
&& Dev
->Mode
!= NULL
);
340 Size
= (Dev
->Mode
->MaxMode
+ 1) * 80;
341 RetVal
= AllocateZeroPool(Size
);
343 Temp
= HiiGetString(mHandleParsingHiiHandle
, STRING_TOKEN(STR_TXT_OUT_DUMP_HEADER
), NULL
);
345 UnicodeSPrint(RetVal
, Size
, Temp
, Dev
, Dev
->Mode
->Attribute
);
352 Temp
= HiiGetString(mHandleParsingHiiHandle
, STRING_TOKEN(STR_TXT_OUT_DUMP_LINE
), NULL
);
353 for (Index
= 0; Index
< Dev
->Mode
->MaxMode
; Index
++) {
354 Status
= Dev
->QueryMode (Dev
, Index
, &Col
, &Row
);
355 NewSize
= Size
- StrSize(RetVal
);
357 RetVal
+ StrLen(RetVal
),
359 Temp
== NULL
?L
"":Temp
,
360 Index
== Dev
->Mode
->Mode
? L
'*' : L
' ',
362 !EFI_ERROR(Status
)?(INTN
)Col
:-1,
363 !EFI_ERROR(Status
)?(INTN
)Row
:-1
370 STATIC CONST UINTN VersionStringSize
= 60;
373 Function to dump information about EfiDriverSupportedEfiVersion protocol.
375 This will allocate the return buffer from boot services pool.
377 @param[in] TheHandle The handle that has the protocol installed.
378 @param[in] Verbose TRUE for additional information, FALSE otherwise.
380 @retval A poitner to a string containing the information.
384 DriverEfiVersionProtocolDumpInformation(
385 IN CONST EFI_HANDLE TheHandle
,
386 IN CONST BOOLEAN Verbose
389 EFI_DRIVER_SUPPORTED_EFI_VERSION_PROTOCOL
*DriverEfiVersion
;
393 Status
= gBS
->HandleProtocol(
395 &gEfiDriverSupportedEfiVersionProtocolGuid
,
396 (VOID
**)&DriverEfiVersion
);
398 ASSERT_EFI_ERROR(Status
);
400 RetVal
= AllocateZeroPool(VersionStringSize
);
401 ASSERT(RetVal
!= NULL
);
402 UnicodeSPrint(RetVal
, VersionStringSize
, L
"0x%08x", DriverEfiVersion
->FirmwareVersion
);
407 Function to dump information about DevicePath protocol.
409 This will allocate the return buffer from boot services pool.
411 @param[in] TheHandle The handle that has the protocol installed.
412 @param[in] Verbose TRUE for additional information, FALSE otherwise.
414 @retval A poitner to a string containing the information.
418 DevicePathProtocolDumpInformation(
419 IN CONST EFI_HANDLE TheHandle
,
420 IN CONST BOOLEAN Verbose
423 EFI_DEVICE_PATH_PROTOCOL
*DevPath
;
429 Status
= gBS
->OpenProtocol(TheHandle
, &gEfiDevicePathProtocolGuid
, (VOID
**)&DevPath
, gImageHandle
, NULL
, EFI_OPEN_PROTOCOL_GET_PROTOCOL
);
430 if (!EFI_ERROR(Status
)) {
432 // I cannot decide whether to allow shortcuts here (the second BOOLEAN on the next line)
434 Temp
= ConvertDevicePathToText(DevPath
, TRUE
, TRUE
);
435 gBS
->CloseProtocol(TheHandle
, &gEfiDevicePathProtocolGuid
, gImageHandle
, NULL
);
437 if (!Verbose
&& Temp
!= NULL
&& StrLen(Temp
) > 30) {
439 Temp2
= StrnCatGrow(&Temp2
, NULL
, Temp
+(StrLen(Temp
) - 30), 30);
447 // Put the information on the NT32 protocol GUIDs here so we are not dependant on the Nt32Pkg
449 #define LOCAL_EFI_WIN_NT_THUNK_PROTOCOL_GUID \
451 0x58c518b1, 0x76f3, 0x11d4, { 0xbc, 0xea, 0x0, 0x80, 0xc7, 0x3c, 0x88, 0x81 } \
454 #define LOCAL_EFI_WIN_NT_BUS_DRIVER_IO_PROTOCOL_GUID \
456 0x96eb4ad6, 0xa32a, 0x11d4, { 0xbc, 0xfd, 0x0, 0x80, 0xc7, 0x3c, 0x88, 0x81 } \
459 #define LOCAL_EFI_WIN_NT_SERIAL_PORT_GUID \
461 0xc95a93d, 0xa006, 0x11d4, { 0xbc, 0xfa, 0x0, 0x80, 0xc7, 0x3c, 0x88, 0x81 } \
463 STATIC CONST EFI_GUID WinNtThunkProtocolGuid
= LOCAL_EFI_WIN_NT_THUNK_PROTOCOL_GUID
;
464 STATIC CONST EFI_GUID WinNtIoProtocolGuid
= LOCAL_EFI_WIN_NT_BUS_DRIVER_IO_PROTOCOL_GUID
;
465 STATIC CONST EFI_GUID WinNtSerialPortGuid
= LOCAL_EFI_WIN_NT_SERIAL_PORT_GUID
;
467 STATIC CONST GUID_INFO_BLOCK mGuidStringListNT
[] = {
468 {STRING_TOKEN(STR_WINNT_THUNK
), (EFI_GUID
*)&WinNtThunkProtocolGuid
, NULL
},
469 {STRING_TOKEN(STR_WINNT_DRIVER_IO
), (EFI_GUID
*)&WinNtIoProtocolGuid
, NULL
},
470 {STRING_TOKEN(STR_WINNT_SERIAL_PORT
), (EFI_GUID
*)&WinNtSerialPortGuid
, NULL
},
471 {STRING_TOKEN(STR_UNKNOWN_DEVICE
), NULL
, NULL
},
474 STATIC CONST GUID_INFO_BLOCK mGuidStringList
[] = {
475 {STRING_TOKEN(STR_LOADED_IMAGE
), &gEfiLoadedImageProtocolGuid
, LoadedImageProtocolDumpInformation
},
476 {STRING_TOKEN(STR_DEVICE_PATH
), &gEfiDevicePathProtocolGuid
, DevicePathProtocolDumpInformation
},
477 {STRING_TOKEN(STR_IMAGE_PATH
), &gEfiLoadedImageDevicePathProtocolGuid
, DevicePathProtocolDumpInformation
},
478 {STRING_TOKEN(STR_DEVICE_PATH_UTIL
), &gEfiDevicePathUtilitiesProtocolGuid
, NULL
},
479 {STRING_TOKEN(STR_DEVICE_PATH_TXT
), &gEfiDevicePathToTextProtocolGuid
, NULL
},
480 {STRING_TOKEN(STR_DEVICE_PATH_FTXT
), &gEfiDevicePathFromTextProtocolGuid
, NULL
},
481 {STRING_TOKEN(STR_DEVICE_PATH_PC
), &gEfiPcAnsiGuid
, NULL
},
482 {STRING_TOKEN(STR_DEVICE_PATH_VT100
), &gEfiVT100Guid
, NULL
},
483 {STRING_TOKEN(STR_DEVICE_PATH_VT100P
), &gEfiVT100PlusGuid
, NULL
},
484 {STRING_TOKEN(STR_DEVICE_PATH_VTUTF8
), &gEfiVTUTF8Guid
, NULL
},
485 {STRING_TOKEN(STR_DRIVER_BINDING
), &gEfiDriverBindingProtocolGuid
, NULL
},
486 {STRING_TOKEN(STR_PLATFORM_OVERRIDE
), &gEfiPlatformDriverOverrideProtocolGuid
, NULL
},
487 {STRING_TOKEN(STR_BUS_OVERRIDE
), &gEfiBusSpecificDriverOverrideProtocolGuid
, NULL
},
488 {STRING_TOKEN(STR_DRIVER_DIAG
), &gEfiDriverDiagnosticsProtocolGuid
, NULL
},
489 {STRING_TOKEN(STR_DRIVER_DIAG2
), &gEfiDriverDiagnostics2ProtocolGuid
, NULL
},
490 {STRING_TOKEN(STR_DRIVER_CN
), &gEfiComponentNameProtocolGuid
, NULL
},
491 {STRING_TOKEN(STR_DRIVER_CN2
), &gEfiComponentName2ProtocolGuid
, NULL
},
492 {STRING_TOKEN(STR_PLAT_DRV_CFG
), &gEfiPlatformToDriverConfigurationProtocolGuid
, NULL
},
493 {STRING_TOKEN(STR_DRIVER_VERSION
), &gEfiDriverSupportedEfiVersionProtocolGuid
, DriverEfiVersionProtocolDumpInformation
},
494 {STRING_TOKEN(STR_TXT_IN
), &gEfiSimpleTextInProtocolGuid
, NULL
},
495 {STRING_TOKEN(STR_TXT_IN_EX
), &gEfiSimpleTextInputExProtocolGuid
, NULL
},
496 {STRING_TOKEN(STR_TXT_OUT
), &gEfiSimpleTextOutProtocolGuid
, TxtOutProtocolDumpInformation
},
497 {STRING_TOKEN(STR_SIM_POINTER
), &gEfiSimplePointerProtocolGuid
, NULL
},
498 {STRING_TOKEN(STR_ABS_POINTER
), &gEfiAbsolutePointerProtocolGuid
, NULL
},
499 {STRING_TOKEN(STR_SERIAL_IO
), &gEfiSerialIoProtocolGuid
, NULL
},
500 {STRING_TOKEN(STR_GRAPHICS_OUTPUT
), &gEfiGraphicsOutputProtocolGuid
, NULL
},
501 {STRING_TOKEN(STR_EDID_DISCOVERED
), &gEfiEdidDiscoveredProtocolGuid
, NULL
},
502 {STRING_TOKEN(STR_EDID_ACTIVE
), &gEfiEdidActiveProtocolGuid
, NULL
},
503 {STRING_TOKEN(STR_EDID_OVERRIDE
), &gEfiEdidOverrideProtocolGuid
, NULL
},
504 {STRING_TOKEN(STR_CON_IN
), &gEfiConsoleInDeviceGuid
, NULL
},
505 {STRING_TOKEN(STR_CON_OUT
), &gEfiConsoleOutDeviceGuid
, NULL
},
506 {STRING_TOKEN(STR_STD_ERR
), &gEfiStandardErrorDeviceGuid
, NULL
},
507 {STRING_TOKEN(STR_LOAD_FILE
), &gEfiLoadFileProtocolGuid
, NULL
},
508 {STRING_TOKEN(STR_LOAD_FILE2
), &gEfiLoadFile2ProtocolGuid
, NULL
},
509 {STRING_TOKEN(STR_SIMPLE_FILE_SYS
), &gEfiSimpleFileSystemProtocolGuid
, NULL
},
510 {STRING_TOKEN(STR_TAPE_IO
), &gEfiTapeIoProtocolGuid
, NULL
},
511 {STRING_TOKEN(STR_DISK_IO
), &gEfiDiskIoProtocolGuid
, NULL
},
512 {STRING_TOKEN(STR_BLK_IO
), &gEfiBlockIoProtocolGuid
, NULL
},
513 {STRING_TOKEN(STR_UC
), &gEfiUnicodeCollationProtocolGuid
, NULL
},
514 {STRING_TOKEN(STR_UC2
), &gEfiUnicodeCollation2ProtocolGuid
, NULL
},
515 {STRING_TOKEN(STR_PCIRB_IO
), &gEfiPciRootBridgeIoProtocolGuid
, PciRootBridgeIoDumpInformation
},
516 {STRING_TOKEN(STR_PCI_IO
), &gEfiPciIoProtocolGuid
, NULL
},
517 {STRING_TOKEN(STR_SCSI_PT
), &gEfiScsiPassThruProtocolGuid
, NULL
},
518 {STRING_TOKEN(STR_SCSI_IO
), &gEfiScsiIoProtocolGuid
, NULL
},
519 {STRING_TOKEN(STR_SCSI_PT_EXT
), &gEfiExtScsiPassThruProtocolGuid
, NULL
},
520 {STRING_TOKEN(STR_ISCSI
), &gEfiIScsiInitiatorNameProtocolGuid
, NULL
},
521 {STRING_TOKEN(STR_USB_IO
), &gEfiUsbIoProtocolGuid
, NULL
},
522 {STRING_TOKEN(STR_USB_HC
), &gEfiUsbHcProtocolGuid
, NULL
},
523 {STRING_TOKEN(STR_USB_HC2
), &gEfiUsb2HcProtocolGuid
, NULL
},
524 {STRING_TOKEN(STR_DEBUG_SUPPORT
), &gEfiDebugSupportProtocolGuid
, NULL
},
525 {STRING_TOKEN(STR_DEBUG_PORT
), &gEfiDebugPortProtocolGuid
, NULL
},
526 {STRING_TOKEN(STR_DECOMPRESS
), &gEfiDecompressProtocolGuid
, NULL
},
527 {STRING_TOKEN(STR_ACPI_TABLE
), &gEfiAcpiTableProtocolGuid
, NULL
},
528 {STRING_TOKEN(STR_EBC_INTERPRETER
), &gEfiEbcProtocolGuid
, NULL
},
529 {STRING_TOKEN(STR_SNP
), &gEfiSimpleNetworkProtocolGuid
, NULL
},
530 {STRING_TOKEN(STR_NII
), &gEfiNetworkInterfaceIdentifierProtocolGuid
, NULL
},
531 {STRING_TOKEN(STR_NII_31
), &gEfiNetworkInterfaceIdentifierProtocolGuid_31
, NULL
},
532 {STRING_TOKEN(STR_PXE_BC
), &gEfiPxeBaseCodeProtocolGuid
, NULL
},
533 {STRING_TOKEN(STR_PXE_CB
), &gEfiPxeBaseCodeCallbackProtocolGuid
, NULL
},
534 {STRING_TOKEN(STR_BIS
), &gEfiBisProtocolGuid
, NULL
},
535 {STRING_TOKEN(STR_MNP_SB
), &gEfiManagedNetworkServiceBindingProtocolGuid
, NULL
},
536 {STRING_TOKEN(STR_MNP
), &gEfiManagedNetworkProtocolGuid
, NULL
},
537 {STRING_TOKEN(STR_ARP_SB
), &gEfiArpServiceBindingProtocolGuid
, NULL
},
538 {STRING_TOKEN(STR_ARP
), &gEfiArpProtocolGuid
, NULL
},
539 {STRING_TOKEN(STR_DHCPV4_SB
), &gEfiDhcp4ServiceBindingProtocolGuid
, NULL
},
540 {STRING_TOKEN(STR_DHCPV4
), &gEfiDhcp4ProtocolGuid
, NULL
},
541 {STRING_TOKEN(STR_TCPV4_SB
), &gEfiTcp4ServiceBindingProtocolGuid
, NULL
},
542 {STRING_TOKEN(STR_TCPV4
), &gEfiTcp4ProtocolGuid
, NULL
},
543 {STRING_TOKEN(STR_IPV4_SB
), &gEfiIp4ServiceBindingProtocolGuid
, NULL
},
544 {STRING_TOKEN(STR_IPV4
), &gEfiIp4ProtocolGuid
, NULL
},
545 {STRING_TOKEN(STR_IPV4_CFG
), &gEfiIp4ConfigProtocolGuid
, NULL
},
546 {STRING_TOKEN(STR_SHELL_PARAMETERS
), &gEfiShellParametersProtocolGuid
, NULL
},
547 {STRING_TOKEN(STR_SHELL
), &gEfiShellProtocolGuid
, NULL
},
548 {STRING_TOKEN(STR_UDPV4_SB
), &gEfiUdp4ServiceBindingProtocolGuid
, NULL
},
549 {STRING_TOKEN(STR_UDPV4
), &gEfiUdp4ProtocolGuid
, NULL
},
550 {STRING_TOKEN(STR_MTFTPV4_SB
), &gEfiMtftp4ServiceBindingProtocolGuid
, NULL
},
551 {STRING_TOKEN(STR_MTFTPV4
), &gEfiMtftp4ProtocolGuid
, NULL
},
552 {STRING_TOKEN(STR_AUTH_INFO
), &gEfiAuthenticationInfoProtocolGuid
, NULL
},
553 {STRING_TOKEN(STR_HASH_SB
), &gEfiHashServiceBindingProtocolGuid
, NULL
},
554 {STRING_TOKEN(STR_HASH
), &gEfiHashProtocolGuid
, NULL
},
555 {STRING_TOKEN(STR_HII_FONT
), &gEfiHiiFontProtocolGuid
, NULL
},
556 {STRING_TOKEN(STR_HII_STRING
), &gEfiHiiStringProtocolGuid
, NULL
},
557 {STRING_TOKEN(STR_HII_IMAGE
), &gEfiHiiImageProtocolGuid
, NULL
},
558 {STRING_TOKEN(STR_HII_DATABASE
), &gEfiHiiDatabaseProtocolGuid
, NULL
},
559 {STRING_TOKEN(STR_HII_CONFIG_ROUT
), &gEfiHiiConfigRoutingProtocolGuid
, NULL
},
560 {STRING_TOKEN(STR_HII_CONFIG_ACC
), &gEfiHiiConfigAccessProtocolGuid
, NULL
},
561 {STRING_TOKEN(STR_HII_FORM_BROWSER2
), &gEfiFormBrowser2ProtocolGuid
, NULL
},
562 {STRING_TOKEN(STR_DRIVER_FAM_OVERRIDE
), &gEfiDriverFamilyOverrideProtocolGuid
, NULL
},
563 {STRING_TOKEN(STR_PCD
), &gPcdProtocolGuid
, NULL
},
564 {STRING_TOKEN(STR_TCG
), &gEfiTcgProtocolGuid
, NULL
},
565 {STRING_TOKEN(STR_HII_PACKAGE_LIST
), &gEfiHiiPackageListProtocolGuid
, NULL
},
568 // the ones under this are deprecated by the current UEFI Spec, but may be found anyways...
570 {STRING_TOKEN(STR_SHELL_INTERFACE
), &gEfiShellInterfaceGuid
, NULL
},
571 {STRING_TOKEN(STR_SHELL_ENV2
), &gEfiShellEnvironment2Guid
, NULL
},
572 {STRING_TOKEN(STR_SHELL_ENV
), &gEfiShellEnvironment2Guid
, NULL
},
573 {STRING_TOKEN(STR_DEVICE_IO
), &gEfiDeviceIoProtocolGuid
, NULL
},
574 {STRING_TOKEN(STR_UGA_DRAW
), &gEfiUgaDrawProtocolGuid
, NULL
},
575 {STRING_TOKEN(STR_UGA_IO
), &gEfiUgaIoProtocolGuid
, NULL
},
576 {STRING_TOKEN(STR_ESP
), &gEfiPartTypeSystemPartGuid
, NULL
},
577 {STRING_TOKEN(STR_GPT_NBR
), &gEfiPartTypeLegacyMbrGuid
, NULL
},
578 {STRING_TOKEN(STR_DRIVER_CONFIG
), &gEfiDriverConfigurationProtocolGuid
, NULL
},
579 {STRING_TOKEN(STR_DRIVER_CONFIG2
), &gEfiDriverConfiguration2ProtocolGuid
, NULL
},
582 // the ones under this are GUID identified structs, not protocols
584 {STRING_TOKEN(STR_FILE_INFO
), &gEfiFileInfoGuid
, NULL
},
585 {STRING_TOKEN(STR_FILE_SYS_INFO
), &gEfiFileSystemInfoGuid
, NULL
},
588 // the ones under this are misc GUIDS.
590 {STRING_TOKEN(STR_EFI_GLOBAL_VARIABLE
), &gEfiGlobalVariableGuid
, NULL
},
595 {STRING_TOKEN(STR_IP6_SB
), &gEfiIp6ServiceBindingProtocolGuid
, NULL
},
596 {STRING_TOKEN(STR_IP6
), &gEfiIp6ProtocolGuid
, NULL
},
597 {STRING_TOKEN(STR_IP6_CONFIG
), &gEfiIp6ConfigProtocolGuid
, NULL
},
598 {STRING_TOKEN(STR_MTFTP6_SB
), &gEfiMtftp6ServiceBindingProtocolGuid
, NULL
},
599 {STRING_TOKEN(STR_MTFTP6
), &gEfiMtftp6ProtocolGuid
, NULL
},
600 {STRING_TOKEN(STR_DHCP6_SB
), &gEfiDhcp6ServiceBindingProtocolGuid
, NULL
},
601 {STRING_TOKEN(STR_DHCP6
), &gEfiDhcp6ProtocolGuid
, NULL
},
602 {STRING_TOKEN(STR_UDP6_SB
), &gEfiUdp6ServiceBindingProtocolGuid
, NULL
},
603 {STRING_TOKEN(STR_UDP6
), &gEfiUdp6ProtocolGuid
, NULL
},
604 {STRING_TOKEN(STR_TCP6_SB
), &gEfiTcp6ServiceBindingProtocolGuid
, NULL
},
605 {STRING_TOKEN(STR_TCP6
), &gEfiTcp6ProtocolGuid
, NULL
},
606 {STRING_TOKEN(STR_VLAN_CONFIG
), &gEfiVlanConfigProtocolGuid
, NULL
},
607 {STRING_TOKEN(STR_EAP
), &gEfiEapProtocolGuid
, NULL
},
608 {STRING_TOKEN(STR_EAP_MGMT
), &gEfiEapManagementProtocolGuid
, NULL
},
609 {STRING_TOKEN(STR_FTP4_SB
), &gEfiFtp4ServiceBindingProtocolGuid
, NULL
},
610 {STRING_TOKEN(STR_FTP4
), &gEfiFtp4ProtocolGuid
, NULL
},
611 {STRING_TOKEN(STR_IP_SEC_CONFIG
), &gEfiIpSecConfigProtocolGuid
, NULL
},
612 {STRING_TOKEN(STR_DH
), &gEfiDriverHealthProtocolGuid
, NULL
},
613 {STRING_TOKEN(STR_DEF_IMG_LOAD
), &gEfiDeferredImageLoadProtocolGuid
, NULL
},
614 {STRING_TOKEN(STR_USER_CRED
), &gEfiUserCredentialProtocolGuid
, NULL
},
615 {STRING_TOKEN(STR_USER_MNGR
), &gEfiUserManagerProtocolGuid
, NULL
},
616 {STRING_TOKEN(STR_ATA_PASS_THRU
), &gEfiAtaPassThruProtocolGuid
, NULL
},
621 {STRING_TOKEN(STR_FW_MGMT
), &gEfiFirmwareManagementProtocolGuid
, NULL
},
622 {STRING_TOKEN(STR_IP_SEC
), &gEfiIpSecProtocolGuid
, NULL
},
623 {STRING_TOKEN(STR_IP_SEC2
), &gEfiIpSec2ProtocolGuid
, NULL
},
628 {STRING_TOKEN(STR_KMS
), &gEfiKmsProtocolGuid
, NULL
},
629 {STRING_TOKEN(STR_BLK_IO2
), &gEfiBlockIo2ProtocolGuid
, NULL
},
630 {STRING_TOKEN(STR_SSC
), &gEfiStorageSecurityCommandProtocolGuid
, NULL
},
631 {STRING_TOKEN(STR_UCRED2
), &gEfiUserCredential2ProtocolGuid
, NULL
},
636 {STRING_TOKEN(STR_DISK_IO2
), &gEfiDiskIo2ProtocolGuid
, NULL
},
641 {STRING_TOKEN(STR_IDE_CONT_INIT
), &gEfiIdeControllerInitProtocolGuid
, NULL
},
646 {STRING_TOKEN(STR_UNKNOWN_DEVICE
), NULL
, NULL
},
650 Function to get the node for a protocol or struct from it's GUID.
652 if Guid is NULL, then ASSERT.
654 @param[in] Guid The GUID to look for the name of.
658 CONST GUID_INFO_BLOCK
*
660 InternalShellGetNodeFromGuid(
661 IN CONST EFI_GUID
* Guid
664 CONST GUID_INFO_BLOCK
*ListWalker
;
666 ASSERT(Guid
!= NULL
);
668 if (PcdGetBool(PcdShellIncludeNtGuids
)) {
669 for (ListWalker
= mGuidStringListNT
; ListWalker
!= NULL
&& ListWalker
->GuidId
!= NULL
; ListWalker
++) {
670 if (CompareGuid(ListWalker
->GuidId
, Guid
)) {
675 for (ListWalker
= mGuidStringList
; ListWalker
!= NULL
&& ListWalker
->GuidId
!= NULL
; ListWalker
++) {
676 if (CompareGuid(ListWalker
->GuidId
, Guid
)) {
684 Function to get the name of a protocol or struct from it's GUID.
686 if Guid is NULL, then ASSERT.
688 @param[in] Guid The GUID to look for the name of.
689 @param[in] Lang The language to use.
691 @return pointer to string of the name. The caller
692 is responsible to free this memory.
696 GetStringNameFromGuid(
697 IN CONST EFI_GUID
*Guid
,
698 IN CONST CHAR8
*Lang OPTIONAL
701 CONST GUID_INFO_BLOCK
*Id
;
703 Id
= InternalShellGetNodeFromGuid(Guid
);
704 return (HiiGetString(mHandleParsingHiiHandle
, Id
->StringId
, Lang
));
708 Function to dump protocol information from a handle.
710 This function will return a allocated string buffer containing the
711 information. The caller is responsible for freeing the memory.
713 If Guid is NULL, ASSERT().
714 If TheHandle is NULL, ASSERT().
716 @param[in] TheHandle The handle to dump information from.
717 @param[in] Guid The GUID of the protocol to dump.
718 @param[in] Verbose TRUE for extra info. FALSE otherwise.
720 @return The pointer to string.
721 @retval NULL An error was encountered.
725 GetProtocolInformationDump(
726 IN CONST EFI_HANDLE TheHandle
,
727 IN CONST EFI_GUID
*Guid
,
728 IN CONST BOOLEAN Verbose
731 CONST GUID_INFO_BLOCK
*Id
;
733 ASSERT(TheHandle
!= NULL
);
734 ASSERT(Guid
!= NULL
);
736 if (TheHandle
== NULL
|| Guid
== NULL
) {
740 Id
= InternalShellGetNodeFromGuid(Guid
);
741 if (Id
!= NULL
&& Id
->DumpInfo
!= NULL
) {
742 return (Id
->DumpInfo(TheHandle
, Verbose
));
748 Function to get the Guid for a protocol or struct based on it's string name.
750 @param[in] Name The pointer to the string name.
751 @param[in] Lang The pointer to the language code.
752 @param[in] Guid The pointer to the Guid.
754 @retval EFI_SUCCESS The operation was sucessful.
758 GetGuidFromStringName(
759 IN CONST CHAR16
*Name
,
760 IN CONST CHAR8
*Lang OPTIONAL
,
764 CONST GUID_INFO_BLOCK
*ListWalker
;
767 ASSERT(Guid
!= NULL
);
769 return (EFI_INVALID_PARAMETER
);
773 if (PcdGetBool(PcdShellIncludeNtGuids
)) {
774 for (ListWalker
= mGuidStringListNT
; ListWalker
!= NULL
&& ListWalker
->GuidId
!= NULL
; ListWalker
++) {
775 String
= HiiGetString(mHandleParsingHiiHandle
, ListWalker
->StringId
, Lang
);
776 if (Name
!= NULL
&& String
!= NULL
&& StringNoCaseCompare (&Name
, &String
) == 0) {
777 *Guid
= ListWalker
->GuidId
;
779 SHELL_FREE_NON_NULL(String
);
781 return (EFI_SUCCESS
);
785 for (ListWalker
= mGuidStringList
; ListWalker
!= NULL
&& ListWalker
->GuidId
!= NULL
; ListWalker
++) {
786 String
= HiiGetString(mHandleParsingHiiHandle
, ListWalker
->StringId
, Lang
);
787 if (Name
!= NULL
&& String
!= NULL
&& StringNoCaseCompare (&Name
, &String
) == 0) {
788 *Guid
= ListWalker
->GuidId
;
790 SHELL_FREE_NON_NULL(String
);
792 return (EFI_SUCCESS
);
795 return (EFI_NOT_FOUND
);
799 Get best support language for this driver.
801 First base on the user input language to search, second base on the current
802 platform used language to search, third get the first language from the
803 support language list. The caller need to free the buffer of the best language.
805 @param[in] SupportedLanguages The support languages for this driver.
806 @param[in] InputLanguage The user input language.
807 @param[in] Iso639Language Whether get language for ISO639.
809 @return The best support language for this driver.
813 GetBestLanguageForDriver (
814 IN CONST CHAR8
*SupportedLanguages
,
815 IN CONST CHAR8
*InputLanguage
,
816 IN BOOLEAN Iso639Language
819 CHAR8
*LanguageVariable
;
822 LanguageVariable
= GetVariable (Iso639Language
? L
"Lang" : L
"PlatformLang", &gEfiGlobalVariableGuid
);
824 BestLanguage
= GetBestLanguage(
827 (InputLanguage
!= NULL
) ? InputLanguage
: "",
828 (LanguageVariable
!= NULL
) ? LanguageVariable
: "",
833 if (LanguageVariable
!= NULL
) {
834 FreePool (LanguageVariable
);
841 Function to retrieve the driver name (if possible) from the ComponentName or
842 ComponentName2 protocol
844 @param[in] TheHandle The driver handle to get the name of.
845 @param[in] Language The language to use.
847 @retval NULL The name could not be found.
848 @return A pointer to the string name. Do not de-allocate the memory.
852 GetStringNameFromHandle(
853 IN CONST EFI_HANDLE TheHandle
,
854 IN CONST CHAR8
*Language
857 EFI_COMPONENT_NAME2_PROTOCOL
*CompNameStruct
;
864 Status
= gBS
->OpenProtocol(
866 &gEfiComponentName2ProtocolGuid
,
867 (VOID
**)&CompNameStruct
,
870 EFI_OPEN_PROTOCOL_GET_PROTOCOL
);
871 if (!EFI_ERROR(Status
)) {
872 BestLang
= GetBestLanguageForDriver (CompNameStruct
->SupportedLanguages
, Language
, FALSE
);
873 Status
= CompNameStruct
->GetDriverName(CompNameStruct
, BestLang
, &RetVal
);
874 if (BestLang
!= NULL
) {
878 if (!EFI_ERROR(Status
)) {
882 Status
= gBS
->OpenProtocol(
884 &gEfiComponentNameProtocolGuid
,
885 (VOID
**)&CompNameStruct
,
888 EFI_OPEN_PROTOCOL_GET_PROTOCOL
);
889 if (!EFI_ERROR(Status
)) {
890 BestLang
= GetBestLanguageForDriver (CompNameStruct
->SupportedLanguages
, Language
, FALSE
);
891 Status
= CompNameStruct
->GetDriverName(CompNameStruct
, BestLang
, &RetVal
);
892 if (BestLang
!= NULL
) {
895 if (!EFI_ERROR(Status
)) {
903 Function to initialize the file global mHandleList object for use in
904 vonverting handles to index and index to handle.
906 @retval EFI_SUCCESS The operation was successful.
910 InternalShellInitHandleList(
915 EFI_HANDLE
*HandleBuffer
;
917 HANDLE_LIST
*ListWalker
;
919 if (mHandleList
.NextIndex
!= 0) {
922 InitializeListHead(&mHandleList
.List
.Link
);
923 mHandleList
.NextIndex
= 1;
924 Status
= gBS
->LocateHandleBuffer (
931 ASSERT_EFI_ERROR(Status
);
932 if (EFI_ERROR(Status
)) {
935 for (mHandleList
.NextIndex
= 1 ; mHandleList
.NextIndex
<= HandleCount
; mHandleList
.NextIndex
++){
936 ListWalker
= AllocateZeroPool(sizeof(HANDLE_LIST
));
937 ASSERT(ListWalker
!= NULL
);
938 ListWalker
->TheHandle
= HandleBuffer
[mHandleList
.NextIndex
-1];
939 ListWalker
->TheIndex
= mHandleList
.NextIndex
;
940 InsertTailList(&mHandleList
.List
.Link
,&ListWalker
->Link
);
942 FreePool(HandleBuffer
);
943 return (EFI_SUCCESS
);
947 Function to retrieve the human-friendly index of a given handle. If the handle
948 does not have a index one will be automatically assigned. The index value is valid
949 until the termination of the shell application.
951 @param[in] TheHandle The handle to retrieve an index for.
953 @retval 0 A memory allocation failed.
954 @return The index of the handle.
959 ConvertHandleToHandleIndex(
960 IN CONST EFI_HANDLE TheHandle
964 EFI_GUID
**ProtocolBuffer
;
966 HANDLE_LIST
*ListWalker
;
968 if (TheHandle
== NULL
) {
972 InternalShellInitHandleList();
974 for (ListWalker
= (HANDLE_LIST
*)GetFirstNode(&mHandleList
.List
.Link
)
975 ; !IsNull(&mHandleList
.List
.Link
,&ListWalker
->Link
)
976 ; ListWalker
= (HANDLE_LIST
*)GetNextNode(&mHandleList
.List
.Link
,&ListWalker
->Link
)
978 if (ListWalker
->TheHandle
== TheHandle
) {
980 // Verify that TheHandle is still present in the Handle Database
982 Status
= gBS
->ProtocolsPerHandle(TheHandle
, &ProtocolBuffer
, &ProtocolCount
);
983 if (EFI_ERROR (Status
)) {
985 // TheHandle is not present in the Handle Database, so delete from the handle list
987 RemoveEntryList (&ListWalker
->Link
);
990 FreePool (ProtocolBuffer
);
991 return (ListWalker
->TheIndex
);
996 // Verify that TheHandle is valid handle
998 Status
= gBS
->ProtocolsPerHandle(TheHandle
, &ProtocolBuffer
, &ProtocolCount
);
999 if (EFI_ERROR (Status
)) {
1001 // TheHandle is not valid, so do not add to handle list
1005 FreePool (ProtocolBuffer
);
1007 ListWalker
= AllocateZeroPool(sizeof(HANDLE_LIST
));
1008 ASSERT(ListWalker
!= NULL
);
1009 ListWalker
->TheHandle
= TheHandle
;
1010 ListWalker
->TheIndex
= mHandleList
.NextIndex
++;
1011 InsertTailList(&mHandleList
.List
.Link
,&ListWalker
->Link
);
1012 return (ListWalker
->TheIndex
);
1018 Function to retrieve the EFI_HANDLE from the human-friendly index.
1020 @param[in] TheIndex The index to retrieve the EFI_HANDLE for.
1022 @retval NULL The index was invalid.
1023 @return The EFI_HANDLE that index represents.
1028 ConvertHandleIndexToHandle(
1029 IN CONST UINTN TheIndex
1033 EFI_GUID
**ProtocolBuffer
;
1034 UINTN ProtocolCount
;
1035 HANDLE_LIST
*ListWalker
;
1037 InternalShellInitHandleList();
1039 if (TheIndex
>= mHandleList
.NextIndex
) {
1043 for (ListWalker
= (HANDLE_LIST
*)GetFirstNode(&mHandleList
.List
.Link
)
1044 ; !IsNull(&mHandleList
.List
.Link
,&ListWalker
->Link
)
1045 ; ListWalker
= (HANDLE_LIST
*)GetNextNode(&mHandleList
.List
.Link
,&ListWalker
->Link
)
1047 if (ListWalker
->TheIndex
== TheIndex
&& ListWalker
->TheHandle
!= NULL
) {
1049 // Verify that LinkWalker->TheHandle is valid handle
1051 Status
= gBS
->ProtocolsPerHandle(ListWalker
->TheHandle
, &ProtocolBuffer
, &ProtocolCount
);
1052 if (EFI_ERROR (Status
)) {
1054 // TheHandle is not valid, so do not add to handle list
1056 ListWalker
->TheHandle
= NULL
;
1058 return (ListWalker
->TheHandle
);
1065 Gets all the related EFI_HANDLEs based on the mask supplied.
1067 This function scans all EFI_HANDLES in the UEFI environment's handle database
1068 and returns the ones with the specified relationship (Mask) to the specified
1071 If both DriverBindingHandle and ControllerHandle are NULL, then ASSERT.
1072 If MatchingHandleCount is NULL, then ASSERT.
1074 If MatchingHandleBuffer is not NULL upon a successful return the memory must be
1077 @param[in] DriverBindingHandle The handle with Driver Binding protocol on it.
1078 @param[in] ControllerHandle The handle with Device Path protocol on it.
1079 @param[in] MatchingHandleCount The pointer to UINTN that specifies the number of HANDLES in
1080 MatchingHandleBuffer.
1081 @param[out] MatchingHandleBuffer On a successful return, a buffer of MatchingHandleCount
1082 EFI_HANDLEs with a terminating NULL EFI_HANDLE.
1083 @param[out] HandleType An array of type information.
1085 @retval EFI_SUCCESS The operation was successful, and any related handles
1086 are in MatchingHandleBuffer.
1087 @retval EFI_NOT_FOUND No matching handles were found.
1088 @retval EFI_INVALID_PARAMETER A parameter was invalid or out of range.
1092 ParseHandleDatabaseByRelationshipWithType (
1093 IN CONST EFI_HANDLE DriverBindingHandle OPTIONAL
,
1094 IN CONST EFI_HANDLE ControllerHandle OPTIONAL
,
1095 IN UINTN
*HandleCount
,
1096 OUT EFI_HANDLE
**HandleBuffer
,
1097 OUT UINTN
**HandleType
1102 EFI_GUID
**ProtocolGuidArray
;
1104 UINTN ProtocolIndex
;
1105 EFI_OPEN_PROTOCOL_INFORMATION_ENTRY
*OpenInfo
;
1106 UINTN OpenInfoCount
;
1107 UINTN OpenInfoIndex
;
1109 INTN DriverBindingHandleIndex
;
1111 ASSERT(HandleCount
!= NULL
);
1112 ASSERT(HandleBuffer
!= NULL
);
1113 ASSERT(HandleType
!= NULL
);
1114 ASSERT(DriverBindingHandle
!= NULL
|| ControllerHandle
!= NULL
);
1117 *HandleBuffer
= NULL
;
1121 // Retrieve the list of all handles from the handle database
1123 Status
= gBS
->LocateHandleBuffer (
1130 if (EFI_ERROR (Status
)) {
1134 *HandleType
= AllocateZeroPool (*HandleCount
* sizeof (UINTN
));
1135 ASSERT(*HandleType
!= NULL
);
1137 DriverBindingHandleIndex
= -1;
1138 for (HandleIndex
= 0; HandleIndex
< *HandleCount
; HandleIndex
++) {
1139 if (DriverBindingHandle
!= NULL
&& (*HandleBuffer
)[HandleIndex
] == DriverBindingHandle
) {
1140 DriverBindingHandleIndex
= (INTN
)HandleIndex
;
1144 for (HandleIndex
= 0; HandleIndex
< *HandleCount
; HandleIndex
++) {
1146 // Retrieve the list of all the protocols on each handle
1148 Status
= gBS
->ProtocolsPerHandle (
1149 (*HandleBuffer
)[HandleIndex
],
1153 if (EFI_ERROR (Status
)) {
1157 for (ProtocolIndex
= 0; ProtocolIndex
< ArrayCount
; ProtocolIndex
++) {
1160 // Set the bit describing what this handle has
1162 if (CompareGuid (ProtocolGuidArray
[ProtocolIndex
], &gEfiLoadedImageProtocolGuid
) ) {
1163 (*HandleType
)[HandleIndex
] |= HR_IMAGE_HANDLE
;
1164 } else if (CompareGuid (ProtocolGuidArray
[ProtocolIndex
], &gEfiDriverBindingProtocolGuid
) ) {
1165 (*HandleType
)[HandleIndex
] |= HR_DRIVER_BINDING_HANDLE
;
1166 } else if (CompareGuid (ProtocolGuidArray
[ProtocolIndex
], &gEfiDriverConfiguration2ProtocolGuid
)) {
1167 (*HandleType
)[HandleIndex
] |= HR_DRIVER_CONFIGURATION_HANDLE
;
1168 } else if (CompareGuid (ProtocolGuidArray
[ProtocolIndex
], &gEfiDriverConfigurationProtocolGuid
) ) {
1169 (*HandleType
)[HandleIndex
] |= HR_DRIVER_CONFIGURATION_HANDLE
;
1170 } else if (CompareGuid (ProtocolGuidArray
[ProtocolIndex
], &gEfiDriverDiagnostics2ProtocolGuid
) ) {
1171 (*HandleType
)[HandleIndex
] |= HR_DRIVER_DIAGNOSTICS_HANDLE
;
1172 } else if (CompareGuid (ProtocolGuidArray
[ProtocolIndex
], &gEfiDriverDiagnosticsProtocolGuid
) ) {
1173 (*HandleType
)[HandleIndex
] |= HR_DRIVER_DIAGNOSTICS_HANDLE
;
1174 } else if (CompareGuid (ProtocolGuidArray
[ProtocolIndex
], &gEfiComponentName2ProtocolGuid
) ) {
1175 (*HandleType
)[HandleIndex
] |= HR_COMPONENT_NAME_HANDLE
;
1176 } else if (CompareGuid (ProtocolGuidArray
[ProtocolIndex
], &gEfiComponentNameProtocolGuid
) ) {
1177 (*HandleType
)[HandleIndex
] |= HR_COMPONENT_NAME_HANDLE
;
1178 } else if (CompareGuid (ProtocolGuidArray
[ProtocolIndex
], &gEfiDevicePathProtocolGuid
) ) {
1179 (*HandleType
)[HandleIndex
] |= HR_DEVICE_HANDLE
;
1182 ASSERT((*HandleType
)[HandleIndex
] == (*HandleType
)[HandleIndex
]);
1186 // Retrieve the list of agents that have opened each protocol
1188 Status
= gBS
->OpenProtocolInformation (
1189 (*HandleBuffer
)[HandleIndex
],
1190 ProtocolGuidArray
[ProtocolIndex
],
1194 if (EFI_ERROR (Status
)) {
1198 if (ControllerHandle
== NULL
) {
1200 // ControllerHandle == NULL and DriverBindingHandle != NULL.
1201 // Return information on all the controller handles that the driver specified by DriverBindingHandle is managing
1203 for (OpenInfoIndex
= 0; OpenInfoIndex
< OpenInfoCount
; OpenInfoIndex
++) {
1204 if (OpenInfo
[OpenInfoIndex
].AgentHandle
== DriverBindingHandle
&& (OpenInfo
[OpenInfoIndex
].Attributes
& EFI_OPEN_PROTOCOL_BY_DRIVER
) != 0) {
1205 (*HandleType
)[HandleIndex
] |= (HR_DEVICE_HANDLE
| HR_CONTROLLER_HANDLE
);
1206 if (DriverBindingHandleIndex
!= -1) {
1207 (*HandleType
)[DriverBindingHandleIndex
] |= HR_DEVICE_DRIVER
;
1210 if (OpenInfo
[OpenInfoIndex
].AgentHandle
== DriverBindingHandle
&& (OpenInfo
[OpenInfoIndex
].Attributes
& EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER
) != 0) {
1211 (*HandleType
)[HandleIndex
] |= (HR_DEVICE_HANDLE
| HR_CONTROLLER_HANDLE
);
1212 if (DriverBindingHandleIndex
!= -1) {
1213 (*HandleType
)[DriverBindingHandleIndex
] |= (HR_BUS_DRIVER
| HR_DEVICE_DRIVER
);
1215 for (ChildIndex
= 0; ChildIndex
< *HandleCount
; ChildIndex
++) {
1216 if (OpenInfo
[OpenInfoIndex
].ControllerHandle
== (*HandleBuffer
)[ChildIndex
]) {
1217 (*HandleType
)[ChildIndex
] |= (HR_DEVICE_HANDLE
| HR_CHILD_HANDLE
);
1223 if (DriverBindingHandle
== NULL
&& ControllerHandle
!= NULL
) {
1224 if (ControllerHandle
== (*HandleBuffer
)[HandleIndex
]) {
1225 (*HandleType
)[HandleIndex
] |= (HR_DEVICE_HANDLE
| HR_CONTROLLER_HANDLE
);
1226 for (OpenInfoIndex
= 0; OpenInfoIndex
< OpenInfoCount
; OpenInfoIndex
++) {
1227 if ((OpenInfo
[OpenInfoIndex
].Attributes
& EFI_OPEN_PROTOCOL_BY_DRIVER
) != 0) {
1228 for (ChildIndex
= 0; ChildIndex
< *HandleCount
; ChildIndex
++) {
1229 if (OpenInfo
[OpenInfoIndex
].AgentHandle
== (*HandleBuffer
)[ChildIndex
]) {
1230 (*HandleType
)[ChildIndex
] |= HR_DEVICE_DRIVER
;
1234 if ((OpenInfo
[OpenInfoIndex
].Attributes
& EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER
) != 0) {
1235 for (ChildIndex
= 0; ChildIndex
< *HandleCount
; ChildIndex
++) {
1236 if (OpenInfo
[OpenInfoIndex
].AgentHandle
== (*HandleBuffer
)[ChildIndex
]) {
1237 (*HandleType
)[ChildIndex
] |= (HR_BUS_DRIVER
| HR_DEVICE_DRIVER
);
1239 if (OpenInfo
[OpenInfoIndex
].ControllerHandle
== (*HandleBuffer
)[ChildIndex
]) {
1240 (*HandleType
)[ChildIndex
] |= (HR_DEVICE_HANDLE
| HR_CHILD_HANDLE
);
1246 for (OpenInfoIndex
= 0; OpenInfoIndex
< OpenInfoCount
; OpenInfoIndex
++) {
1247 if ((OpenInfo
[OpenInfoIndex
].Attributes
& EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER
) != 0) {
1248 if (OpenInfo
[OpenInfoIndex
].ControllerHandle
== ControllerHandle
) {
1249 (*HandleType
)[HandleIndex
] |= (HR_DEVICE_HANDLE
| HR_PARENT_HANDLE
);
1255 if (DriverBindingHandle
!= NULL
&& ControllerHandle
!= NULL
) {
1256 if (ControllerHandle
== (*HandleBuffer
)[HandleIndex
]) {
1257 (*HandleType
)[HandleIndex
] |= (HR_DEVICE_HANDLE
| HR_CONTROLLER_HANDLE
);
1258 for (OpenInfoIndex
= 0; OpenInfoIndex
< OpenInfoCount
; OpenInfoIndex
++) {
1259 if ((OpenInfo
[OpenInfoIndex
].Attributes
& EFI_OPEN_PROTOCOL_BY_DRIVER
) != 0) {
1260 if (OpenInfo
[OpenInfoIndex
].AgentHandle
== DriverBindingHandle
) {
1261 if (DriverBindingHandleIndex
!= -1) {
1262 (*HandleType
)[DriverBindingHandleIndex
] |= HR_DEVICE_DRIVER
;
1266 if ((OpenInfo
[OpenInfoIndex
].Attributes
& EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER
) != 0) {
1267 if (OpenInfo
[OpenInfoIndex
].AgentHandle
== DriverBindingHandle
) {
1268 for (ChildIndex
= 0; ChildIndex
< *HandleCount
; ChildIndex
++) {
1269 if (OpenInfo
[OpenInfoIndex
].ControllerHandle
== (*HandleBuffer
)[ChildIndex
]) {
1270 (*HandleType
)[ChildIndex
] |= (HR_DEVICE_HANDLE
| HR_CHILD_HANDLE
);
1275 for (ChildIndex
= 0; ChildIndex
< *HandleCount
; ChildIndex
++) {
1276 if (OpenInfo
[OpenInfoIndex
].AgentHandle
== (*HandleBuffer
)[ChildIndex
]) {
1277 (*HandleType
)[ChildIndex
] |= (HR_BUS_DRIVER
| HR_DEVICE_DRIVER
);
1283 for (OpenInfoIndex
= 0; OpenInfoIndex
< OpenInfoCount
; OpenInfoIndex
++) {
1284 if ((OpenInfo
[OpenInfoIndex
].Attributes
& EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER
) != 0) {
1285 if (OpenInfo
[OpenInfoIndex
].ControllerHandle
== ControllerHandle
) {
1286 (*HandleType
)[HandleIndex
] |= (HR_DEVICE_HANDLE
| HR_PARENT_HANDLE
);
1292 FreePool (OpenInfo
);
1294 FreePool (ProtocolGuidArray
);
1300 Gets all the related EFI_HANDLEs based on the single EFI_HANDLE and the mask
1303 This function will scan all EFI_HANDLES in the UEFI environment's handle database
1304 and return all the ones with the specified relationship (Mask) to the specified
1307 If both DriverBindingHandle and ControllerHandle are NULL, then ASSERT.
1308 If MatchingHandleCount is NULL, then ASSERT.
1310 If MatchingHandleBuffer is not NULL upon a sucessful return the memory must be
1313 @param[in] DriverBindingHandle Handle to a object with Driver Binding protocol
1315 @param[in] ControllerHandle Handle to a device with Device Path protocol on it.
1316 @param[in] Mask Mask of what relationship(s) is desired.
1317 @param[in] MatchingHandleCount Poitner to UINTN specifying number of HANDLES in
1318 MatchingHandleBuffer.
1319 @param[out] MatchingHandleBuffer On a sucessful return a buffer of MatchingHandleCount
1320 EFI_HANDLEs and a terminating NULL EFI_HANDLE.
1322 @retval EFI_SUCCESS The operation was sucessful and any related handles
1323 are in MatchingHandleBuffer;
1324 @retval EFI_NOT_FOUND No matching handles were found.
1325 @retval EFI_INVALID_PARAMETER A parameter was invalid or out of range.
1329 ParseHandleDatabaseByRelationship (
1330 IN CONST EFI_HANDLE DriverBindingHandle OPTIONAL
,
1331 IN CONST EFI_HANDLE ControllerHandle OPTIONAL
,
1332 IN CONST UINTN Mask
,
1333 IN UINTN
*MatchingHandleCount
,
1334 OUT EFI_HANDLE
**MatchingHandleBuffer OPTIONAL
1339 EFI_HANDLE
*HandleBuffer
;
1343 ASSERT(MatchingHandleCount
!= NULL
);
1344 ASSERT(DriverBindingHandle
!= NULL
|| ControllerHandle
!= NULL
);
1346 if ((Mask
& HR_VALID_MASK
) != Mask
) {
1347 return (EFI_INVALID_PARAMETER
);
1350 if ((Mask
& HR_CHILD_HANDLE
) != 0 && DriverBindingHandle
== NULL
) {
1351 return (EFI_INVALID_PARAMETER
);
1354 *MatchingHandleCount
= 0;
1355 if (MatchingHandleBuffer
!= NULL
) {
1356 *MatchingHandleBuffer
= NULL
;
1359 HandleBuffer
= NULL
;
1362 Status
= ParseHandleDatabaseByRelationshipWithType (
1363 DriverBindingHandle
,
1369 if (!EFI_ERROR (Status
)) {
1371 // Count the number of handles that match the attributes in Mask
1373 for (HandleIndex
= 0; HandleIndex
< HandleCount
; HandleIndex
++) {
1374 if ((HandleType
[HandleIndex
] & Mask
) == Mask
) {
1375 (*MatchingHandleCount
)++;
1379 // If no handles match the attributes in Mask then return EFI_NOT_FOUND
1381 if (*MatchingHandleCount
== 0) {
1382 Status
= EFI_NOT_FOUND
;
1385 if (MatchingHandleBuffer
== NULL
) {
1387 // Someone just wanted the count...
1389 Status
= EFI_SUCCESS
;
1392 // Allocate a handle buffer for the number of handles that matched the attributes in Mask
1394 *MatchingHandleBuffer
= AllocateZeroPool ((*MatchingHandleCount
+1)* sizeof (EFI_HANDLE
));
1395 ASSERT(*MatchingHandleBuffer
!= NULL
);
1397 for (HandleIndex
= 0,*MatchingHandleCount
= 0
1398 ; HandleIndex
< HandleCount
1402 // Fill the allocated buffer with the handles that matched the attributes in Mask
1404 if ((HandleType
[HandleIndex
] & Mask
) == Mask
) {
1405 (*MatchingHandleBuffer
)[(*MatchingHandleCount
)++] = HandleBuffer
[HandleIndex
];
1410 // Make the last one NULL
1412 (*MatchingHandleBuffer
)[*MatchingHandleCount
] = NULL
;
1414 Status
= EFI_SUCCESS
;
1415 } // MacthingHandleBuffer == NULL (ELSE)
1416 } // *MatchingHandleCount == 0 (ELSE)
1417 } // no error on ParseHandleDatabaseByRelationshipWithType
1419 if (HandleBuffer
!= NULL
) {
1420 FreePool (HandleBuffer
);
1423 if (HandleType
!= NULL
) {
1424 FreePool (HandleType
);
1431 Gets handles for any child controllers of the passed in controller.
1433 @param[in] ControllerHandle The handle of the "parent controller"
1434 @param[in] MatchingHandleCount Pointer to the number of handles in
1435 MatchingHandleBuffer on return.
1436 @param[out] MatchingHandleBuffer Buffer containing handles on a successful
1440 @retval EFI_SUCCESS The operation was sucessful.
1444 ParseHandleDatabaseForChildControllers(
1445 IN CONST EFI_HANDLE ControllerHandle
,
1446 IN UINTN
*MatchingHandleCount
,
1447 OUT EFI_HANDLE
**MatchingHandleBuffer OPTIONAL
1452 UINTN DriverBindingHandleCount
;
1453 EFI_HANDLE
*DriverBindingHandleBuffer
;
1454 UINTN DriverBindingHandleIndex
;
1455 UINTN ChildControllerHandleCount
;
1456 EFI_HANDLE
*ChildControllerHandleBuffer
;
1457 UINTN ChildControllerHandleIndex
;
1458 EFI_HANDLE
*HandleBufferForReturn
;
1460 if (MatchingHandleCount
== NULL
) {
1461 return (EFI_INVALID_PARAMETER
);
1463 *MatchingHandleCount
= 0;
1465 Status
= PARSE_HANDLE_DATABASE_UEFI_DRIVERS (
1467 &DriverBindingHandleCount
,
1468 &DriverBindingHandleBuffer
1470 if (EFI_ERROR (Status
)) {
1475 // Get a buffer big enough for all the controllers.
1477 HandleBufferForReturn
= GetHandleListByProtocol(NULL
);
1478 if (HandleBufferForReturn
== NULL
) {
1479 FreePool (DriverBindingHandleBuffer
);
1480 return (EFI_NOT_FOUND
);
1483 for (DriverBindingHandleIndex
= 0; DriverBindingHandleIndex
< DriverBindingHandleCount
; DriverBindingHandleIndex
++) {
1484 Status
= PARSE_HANDLE_DATABASE_MANAGED_CHILDREN (
1485 DriverBindingHandleBuffer
[DriverBindingHandleIndex
],
1487 &ChildControllerHandleCount
,
1488 &ChildControllerHandleBuffer
1490 if (EFI_ERROR (Status
)) {
1494 for (ChildControllerHandleIndex
= 0;
1495 ChildControllerHandleIndex
< ChildControllerHandleCount
;
1496 ChildControllerHandleIndex
++
1498 for (HandleIndex
= 0; HandleIndex
< *MatchingHandleCount
; HandleIndex
++) {
1499 if (HandleBufferForReturn
[HandleIndex
] == ChildControllerHandleBuffer
[ChildControllerHandleIndex
]) {
1503 if (HandleIndex
>= *MatchingHandleCount
) {
1504 HandleBufferForReturn
[(*MatchingHandleCount
)++] = ChildControllerHandleBuffer
[ChildControllerHandleIndex
];
1508 FreePool (ChildControllerHandleBuffer
);
1511 FreePool (DriverBindingHandleBuffer
);
1513 if (MatchingHandleBuffer
!= NULL
) {
1514 *MatchingHandleBuffer
= HandleBufferForReturn
;
1516 FreePool(HandleBufferForReturn
);
1519 return (EFI_SUCCESS
);
1523 Appends 1 buffer to another buffer. This will re-allocate the destination buffer
1524 if necessary to fit all of the data.
1526 If DestinationBuffer is NULL, then ASSERT().
1528 @param[in, out] DestinationBuffer The pointer to the pointer to the buffer to append onto.
1529 @param[in, out] DestinationSize The pointer to the size of DestinationBuffer.
1530 @param[in] SourceBuffer The pointer to the buffer to append onto DestinationBuffer.
1531 @param[in] SourceSize The number of bytes of SourceBuffer to append.
1533 @retval NULL A memory allocation failed.
1534 @retval NULL A parameter was invalid.
1535 @return A pointer to (*DestinationBuffer).
1540 IN OUT VOID
**DestinationBuffer
,
1541 IN OUT UINTN
*DestinationSize
,
1542 IN VOID
*SourceBuffer
,
1546 UINTN LocalDestinationSize
;
1547 UINTN LocalDestinationFinalSize
;
1549 ASSERT(DestinationBuffer
!= NULL
);
1551 if (SourceSize
== 0 || SourceBuffer
== NULL
) {
1552 return (*DestinationBuffer
);
1555 if (DestinationSize
== NULL
) {
1556 LocalDestinationSize
= 0;
1558 LocalDestinationSize
= *DestinationSize
;
1561 LocalDestinationFinalSize
= LocalDestinationSize
+ SourceSize
;
1563 if (DestinationSize
!= NULL
) {
1564 *DestinationSize
= LocalDestinationSize
;
1567 if (LocalDestinationSize
== 0) {
1569 *DestinationBuffer
= AllocateZeroPool(LocalDestinationFinalSize
);
1572 *DestinationBuffer
= ReallocatePool(LocalDestinationSize
, LocalDestinationFinalSize
, *DestinationBuffer
);
1575 ASSERT(*DestinationBuffer
!= NULL
);
1578 return (CopyMem(((UINT8
*)(*DestinationBuffer
)) + LocalDestinationSize
, SourceBuffer
, SourceSize
));
1582 Gets handles for any child devices produced by the passed in driver.
1584 @param[in] DriverHandle The handle of the driver.
1585 @param[in] MatchingHandleCount Pointer to the number of handles in
1586 MatchingHandleBuffer on return.
1587 @param[out] MatchingHandleBuffer Buffer containing handles on a successful
1589 @retval EFI_SUCCESS The operation was sucessful.
1590 @sa ParseHandleDatabaseByRelationship
1594 ParseHandleDatabaseForChildDevices(
1595 IN CONST EFI_HANDLE DriverHandle
,
1596 IN UINTN
*MatchingHandleCount
,
1597 OUT EFI_HANDLE
**MatchingHandleBuffer OPTIONAL
1601 EFI_HANDLE
*Buffer2
;
1606 UINTN HandleBufferSize
;
1608 ASSERT(MatchingHandleCount
!= NULL
);
1610 HandleBufferSize
= 0;
1613 *MatchingHandleCount
= 0;
1615 Status
= PARSE_HANDLE_DATABASE_DEVICES (
1620 if (!EFI_ERROR (Status
)) {
1621 for (HandleIndex
= 0; HandleIndex
< Count1
; HandleIndex
++) {
1623 // now find the children
1625 Status
= PARSE_HANDLE_DATABASE_MANAGED_CHILDREN (
1627 Buffer
[HandleIndex
],
1631 if (EFI_ERROR(Status
)) {
1635 // save out required and optional data elements
1637 *MatchingHandleCount
+= Count2
;
1638 if (MatchingHandleBuffer
!= NULL
) {
1639 *MatchingHandleBuffer
= BuffernCatGrow((VOID
**)MatchingHandleBuffer
, &HandleBufferSize
, Buffer2
, Count2
* sizeof(Buffer2
[0]));
1645 if (Buffer2
!= NULL
) {
1651 if (Buffer
!= NULL
) {
1658 Function to get all handles that support a given protocol or all handles.
1660 @param[in] ProtocolGuid The guid of the protocol to get handles for. If NULL
1661 then the function will return all handles.
1663 @retval NULL A memory allocation failed.
1664 @return A NULL terminated list of handles.
1668 GetHandleListByProtocol (
1669 IN CONST EFI_GUID
*ProtocolGuid OPTIONAL
1672 EFI_HANDLE
*HandleList
;
1680 // We cannot use LocateHandleBuffer since we need that NULL item on the ends of the list!
1682 if (ProtocolGuid
== NULL
) {
1683 Status
= gBS
->LocateHandle(AllHandles
, NULL
, NULL
, &Size
, HandleList
);
1684 if (Status
== EFI_BUFFER_TOO_SMALL
) {
1685 HandleList
= AllocateZeroPool(Size
+ sizeof(EFI_HANDLE
));
1686 if (HandleList
== NULL
) {
1689 Status
= gBS
->LocateHandle(AllHandles
, NULL
, NULL
, &Size
, HandleList
);
1690 HandleList
[Size
/sizeof(EFI_HANDLE
)] = NULL
;
1693 Status
= gBS
->LocateHandle(ByProtocol
, (EFI_GUID
*)ProtocolGuid
, NULL
, &Size
, HandleList
);
1694 if (Status
== EFI_BUFFER_TOO_SMALL
) {
1695 HandleList
= AllocateZeroPool(Size
+ sizeof(EFI_HANDLE
));
1696 if (HandleList
== NULL
) {
1699 Status
= gBS
->LocateHandle(ByProtocol
, (EFI_GUID
*)ProtocolGuid
, NULL
, &Size
, HandleList
);
1700 HandleList
[Size
/sizeof(EFI_HANDLE
)] = NULL
;
1703 if (EFI_ERROR(Status
)) {
1704 if (HandleList
!= NULL
) {
1705 FreePool(HandleList
);
1709 return (HandleList
);
1713 Function to get all handles that support some protocols.
1715 @param[in] ProtocolGuids A NULL terminated list of protocol GUIDs.
1717 @retval NULL A memory allocation failed.
1718 @retval NULL ProtocolGuids was NULL.
1719 @return A NULL terminated list of EFI_HANDLEs.
1723 GetHandleListByProtocolList (
1724 IN CONST EFI_GUID
**ProtocolGuids
1727 EFI_HANDLE
*HandleList
;
1732 CONST EFI_GUID
**GuidWalker
;
1733 EFI_HANDLE
*HandleWalker1
;
1734 EFI_HANDLE
*HandleWalker2
;
1738 TotalSize
= sizeof(EFI_HANDLE
);
1740 for (GuidWalker
= ProtocolGuids
; GuidWalker
!= NULL
&& *GuidWalker
!= NULL
; GuidWalker
++,Size
= 0){
1741 Status
= gBS
->LocateHandle(ByProtocol
, (EFI_GUID
*)(*GuidWalker
), NULL
, &Size
, NULL
);
1742 if (Status
== EFI_BUFFER_TOO_SMALL
) {
1748 // No handles were found...
1750 if (TotalSize
== sizeof(EFI_HANDLE
)) {
1754 HandleList
= AllocateZeroPool(TotalSize
);
1755 if (HandleList
== NULL
) {
1760 for (GuidWalker
= ProtocolGuids
; GuidWalker
!= NULL
&& *GuidWalker
!= NULL
; GuidWalker
++){
1761 TempSize
= TotalSize
- Size
;
1762 Status
= gBS
->LocateHandle(ByProtocol
, (EFI_GUID
*)(*GuidWalker
), NULL
, &TempSize
, HandleList
+(Size
/sizeof(EFI_HANDLE
)));
1765 // Allow for missing protocols... Only update the 'used' size upon success.
1767 if (!EFI_ERROR(Status
)) {
1771 ASSERT(HandleList
[(TotalSize
/sizeof(EFI_HANDLE
))-1] == NULL
);
1773 for (HandleWalker1
= HandleList
; HandleWalker1
!= NULL
&& *HandleWalker1
!= NULL
; HandleWalker1
++) {
1774 for (HandleWalker2
= HandleWalker1
+ 1; HandleWalker2
!= NULL
&& *HandleWalker2
!= NULL
; HandleWalker2
++) {
1775 if (*HandleWalker1
== *HandleWalker2
) {
1777 // copy memory back 1 handle width.
1779 CopyMem(HandleWalker2
, HandleWalker2
+ 1, TotalSize
- ((HandleWalker2
-HandleList
+1)*sizeof(EFI_HANDLE
)));
1784 return (HandleList
);