]> git.proxmox.com Git - mirror_edk2.git/blob - ShellPkg/Library/UefiHandleParsingLib/UefiHandleParsingLib.c
e9e3d8204d651b2b46870c50d5f1618d41cce4a2
[mirror_edk2.git] / ShellPkg / Library / UefiHandleParsingLib / UefiHandleParsingLib.c
1 /** @file
2 Provides interface to advanced shell functionality for parsing both handle and protocol database.
3
4 Copyright (c) 2010 - 2012, Intel Corporation. All rights reserved.<BR>
5 This program and the accompanying materials
6 are licensed and made available under the terms and conditions of the BSD License
7 which accompanies this distribution. The full text of the license may be found at
8 http://opensource.org/licenses/bsd-license.php
9
10 THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
11 WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
12
13 **/
14
15 #include "UefiHandleParsingLib.h"
16 #include "IndustryStandard/Acpi10.h"
17
18 EFI_HANDLE mHandleParsingHiiHandle;
19 HANDLE_INDEX_LIST mHandleList = {{{NULL,NULL},0,0},0};
20
21 /**
22 Constructor for the library.
23
24 @param[in] ImageHandle Ignored.
25 @param[in] SystemTable Ignored.
26
27 @retval EFI_SUCCESS The operation was successful.
28 **/
29 EFI_STATUS
30 EFIAPI
31 HandleParsingLibConstructor (
32 IN EFI_HANDLE ImageHandle,
33 IN EFI_SYSTEM_TABLE *SystemTable
34 )
35 {
36 mHandleParsingHiiHandle = HiiAddPackages (&gHandleParsingHiiGuid, gImageHandle, UefiHandleParsingLibStrings, NULL);
37 if (mHandleParsingHiiHandle == NULL) {
38 return (EFI_DEVICE_ERROR);
39 }
40
41 return (EFI_SUCCESS);
42 }
43
44 /**
45 Destructor for the library. free any resources.
46
47 @param[in] ImageHandle Ignored.
48 @param[in] SystemTable Ignored.
49
50 @retval EFI_SUCCESS The operation was successful.
51 **/
52 EFI_STATUS
53 EFIAPI
54 HandleParsingLibDestructor (
55 IN EFI_HANDLE ImageHandle,
56 IN EFI_SYSTEM_TABLE *SystemTable
57 )
58 {
59 if (mHandleParsingHiiHandle != NULL) {
60 HiiRemovePackages(mHandleParsingHiiHandle);
61 }
62 return (EFI_SUCCESS);
63 }
64
65 /*
66 CHAR16*
67 EFIAPI
68 LoadedImageProtocolDumpInformation(
69 IN CONST EFI_HANDLE TheHandle,
70 IN CONST BOOLEAN Verbose
71 )
72 {
73 EFI_LOADED_IMAGE_PROTOCOL *Image;
74 EFI_STATUS Status;
75 EFI_DEVICE_PATH_PROTOCOL *DevPath;
76 EFI_DEVICE_PATH_PROTOCOL *DevPathNode;
77 VOID *Buffer;
78 UINTN BufferSize;
79 UINT32 AuthenticationStatus;
80 EFI_GUID *NameGuid;
81 EFI_FIRMWARE_VOLUME_PROTOCOL *FV;
82 EFI_FIRMWARE_VOLUME2_PROTOCOL *FV2;
83
84 FV = NULL;
85 FV2 = NULL;
86 Buffer = NULL;
87 BufferSize = 0;
88
89 Status = HandleProtocol (
90 TheHandle,
91 &gEfiLoadedImageProtocolGuid,
92 &Image);
93 ASSERT_EFI_ERROR(Status);
94
95 DevPath = UnpackDevicePath (Image->FilePath);
96
97 if (DevPath == NULL) {
98 return NULL;
99 }
100
101 DevPathNode = DevPath;
102
103 while (!IsDevicePathEnd (DevPathNode)) {
104 //
105 // Find the Fv File path
106 //
107 NameGuid = GetNameGuidFromFwVolDevicePathNode ((MEDIA_FW_VOL_FILEPATH_DEVICE_PATH *)DevPathNode);
108 if (NameGuid != NULL) {
109 Status = BS->HandleProtocol (
110 Image->DeviceHandle,
111 &gEfiFirmwareVolumeProtocolGuid,
112 &FV
113 );
114 if (!EFI_ERROR (Status)) {
115 Status = FV->ReadSection (
116 FV,
117 NameGuid,
118 EFI_SECTION_USER_INTERFACE,
119 0,
120 &Buffer,
121 &BufferSize,
122 &AuthenticationStatus
123 );
124 if (!EFI_ERROR (Status)) {
125 break;
126 }
127
128 Buffer = NULL;
129 } else {
130 Status = BS->HandleProtocol (
131 Image->DeviceHandle,
132 &gEfiFirmwareVolume2ProtocolGuid,
133 &FV2
134 );
135 if (!EFI_ERROR (Status)) {
136 Status = FV2->ReadSection (
137 FV2,
138 NameGuid,
139 EFI_SECTION_USER_INTERFACE,
140 0,
141 &Buffer,
142 &BufferSize,
143 &AuthenticationStatus
144 );
145 if (!EFI_ERROR (Status)) {
146 break;
147 }
148
149 Buffer = NULL;
150 }
151 }
152 }
153 //
154 // Next device path node
155 //
156 DevPathNode = NextDevicePathNode (DevPathNode);
157 }
158
159 FreePool (DevPath);
160 return Buffer;
161 }
162 */
163
164 /**
165 Function to dump information about PciRootBridgeIo.
166
167 This will allocate the return buffer from boot services pool.
168
169 @param[in] TheHandle The handle that has PciRootBridgeIo installed.
170 @param[in] Verbose TRUE for additional information, FALSE otherwise.
171
172 @retval A poitner to a string containing the information.
173 **/
174 CHAR16*
175 EFIAPI
176 PciRootBridgeIoDumpInformation(
177 IN CONST EFI_HANDLE TheHandle,
178 IN CONST BOOLEAN Verbose
179 )
180 {
181 EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *PciRootBridgeIo;
182 EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR *Configuration;
183 UINT64 Supports;
184 UINT64 Attributes;
185 CHAR16 *Temp;
186 CHAR16 *Temp2;
187 CHAR16 *RetVal;
188 EFI_STATUS Status;
189
190 RetVal = NULL;
191
192 if (!Verbose) {
193 return (CatSPrint(NULL, L"PciRootBridgeIo"));
194 }
195
196 Status = gBS->HandleProtocol(
197 TheHandle,
198 &gEfiPciRootBridgeIoProtocolGuid,
199 (VOID**)&PciRootBridgeIo);
200
201 if (EFI_ERROR(Status)) {
202 return NULL;
203 }
204
205 Temp = HiiGetString(mHandleParsingHiiHandle, STRING_TOKEN(STR_PCIRB_DUMP_PH), NULL);
206 ASSERT (Temp != NULL);
207 Temp2 = CatSPrint(L"\r\n", Temp, PciRootBridgeIo->ParentHandle);
208 FreePool(Temp);
209 RetVal = Temp2;
210 Temp2 = NULL;
211
212 Temp = HiiGetString(mHandleParsingHiiHandle, STRING_TOKEN(STR_PCIRB_DUMP_SEG), NULL);
213 ASSERT (Temp != NULL);
214 Temp2 = CatSPrint(RetVal, Temp, PciRootBridgeIo->SegmentNumber);
215 FreePool(Temp);
216 FreePool(RetVal);
217 RetVal = Temp2;
218 Temp2 = NULL;
219
220 Supports = 0;
221 Attributes = 0;
222 Status = PciRootBridgeIo->GetAttributes (PciRootBridgeIo, &Supports, &Attributes);
223 if (!EFI_ERROR(Status)) {
224 Temp = HiiGetString(mHandleParsingHiiHandle, STRING_TOKEN(STR_PCIRB_DUMP_ATT), NULL);
225 ASSERT (Temp != NULL);
226 Temp2 = CatSPrint(RetVal, Temp, Attributes);
227 FreePool(Temp);
228 FreePool(RetVal);
229 RetVal = Temp2;
230 Temp2 = NULL;
231
232 Temp = HiiGetString(mHandleParsingHiiHandle, STRING_TOKEN(STR_PCIRB_DUMP_SUPPORTS), NULL);
233 ASSERT (Temp != NULL);
234 Temp2 = CatSPrint(RetVal, Temp, Supports);
235 FreePool(Temp);
236 FreePool(RetVal);
237 RetVal = Temp2;
238 Temp2 = NULL;
239 }
240
241 Configuration = NULL;
242 Status = PciRootBridgeIo->Configuration (PciRootBridgeIo, (VOID **) &Configuration);
243 if (!EFI_ERROR(Status) && Configuration != NULL) {
244 Temp = HiiGetString(mHandleParsingHiiHandle, STRING_TOKEN(STR_PCIRB_DUMP_TITLE), NULL);
245 ASSERT (Temp != NULL);
246 Temp2 = CatSPrint(RetVal, Temp, Supports);
247 FreePool(Temp);
248 FreePool(RetVal);
249 RetVal = Temp2;
250 Temp2 = NULL;
251 while (Configuration->Desc == ACPI_ADDRESS_SPACE_DESCRIPTOR) {
252 Temp = NULL;
253 switch (Configuration->ResType) {
254 case ACPI_ADDRESS_SPACE_TYPE_MEM:
255 Temp = HiiGetString(mHandleParsingHiiHandle, STRING_TOKEN(STR_PCIRB_DUMP_MEM), NULL);
256 break;
257 case ACPI_ADDRESS_SPACE_TYPE_IO:
258 Temp = HiiGetString(mHandleParsingHiiHandle, STRING_TOKEN(STR_PCIRB_DUMP_IO), NULL);
259 break;
260 case ACPI_ADDRESS_SPACE_TYPE_BUS:
261 Temp = HiiGetString(mHandleParsingHiiHandle, STRING_TOKEN(STR_PCIRB_DUMP_BUS), NULL);
262 break;
263 }
264 if (Temp != NULL) {
265 Temp2 = CatSPrint(RetVal, L"%s", Temp);
266 FreePool(Temp);
267 FreePool(RetVal);
268 RetVal = Temp2;
269 Temp2 = NULL;
270 }
271
272 Temp2 = CatSPrint(RetVal,
273 L"%H%02x %016lx %016lx %02x%N\r\n",
274 Configuration->SpecificFlag,
275 Configuration->AddrRangeMin,
276 Configuration->AddrRangeMax,
277 Configuration->AddrSpaceGranularity
278 );
279 FreePool(RetVal);
280 RetVal = Temp2;
281 Temp2 = NULL;
282 Configuration++;
283 }
284 }
285 return (RetVal);
286 }
287
288 /**
289 Function to dump information about SimpleTextOut.
290
291 This will allocate the return buffer from boot services pool.
292
293 @param[in] TheHandle The handle that has SimpleTextOut installed.
294 @param[in] Verbose TRUE for additional information, FALSE otherwise.
295
296 @retval A poitner to a string containing the information.
297 **/
298 CHAR16*
299 EFIAPI
300 TxtOutProtocolDumpInformation(
301 IN CONST EFI_HANDLE TheHandle,
302 IN CONST BOOLEAN Verbose
303 )
304 {
305 EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL *Dev;
306 INTN Index;
307 UINTN Col;
308 UINTN Row;
309 EFI_STATUS Status;
310 CHAR16 *RetVal;
311 UINTN Size;
312 CHAR16 *Temp;
313 UINTN NewSize;
314
315 if (!Verbose) {
316 return (NULL);
317 }
318
319 RetVal = NULL;
320 Size = 0;
321
322 Status = gBS->HandleProtocol(
323 TheHandle,
324 &gEfiSimpleTextOutProtocolGuid,
325 (VOID**)&Dev);
326
327 ASSERT_EFI_ERROR(Status);
328 ASSERT (Dev != NULL && Dev->Mode != NULL);
329
330 Size = (Dev->Mode->MaxMode + 1) * 80;
331 RetVal = AllocateZeroPool(Size);
332
333 Temp = HiiGetString(mHandleParsingHiiHandle, STRING_TOKEN(STR_TXT_OUT_DUMP_HEADER), NULL);
334 if (Temp != NULL) {
335 UnicodeSPrint(RetVal, Size, Temp, Dev, Dev->Mode->Attribute);
336 FreePool(Temp);
337 }
338
339 //
340 // Dump TextOut Info
341 //
342 Temp = HiiGetString(mHandleParsingHiiHandle, STRING_TOKEN(STR_TXT_OUT_DUMP_LINE), NULL);
343 for (Index = 0; Index < Dev->Mode->MaxMode; Index++) {
344 Status = Dev->QueryMode (Dev, Index, &Col, &Row);
345 NewSize = Size - StrSize(RetVal);
346 UnicodeSPrint(
347 RetVal + StrLen(RetVal),
348 NewSize,
349 Temp == NULL?L"":Temp,
350 Index == Dev->Mode->Mode ? L'*' : L' ',
351 Index,
352 !EFI_ERROR(Status)?Col:-1,
353 !EFI_ERROR(Status)?Row:-1
354 );
355 }
356 FreePool(Temp);
357 return (RetVal);
358 }
359
360 STATIC CONST UINTN VersionStringSize = 60;
361
362 /**
363 Function to dump information about EfiDriverSupportedEfiVersion protocol.
364
365 This will allocate the return buffer from boot services pool.
366
367 @param[in] TheHandle The handle that has the protocol installed.
368 @param[in] Verbose TRUE for additional information, FALSE otherwise.
369
370 @retval A poitner to a string containing the information.
371 **/
372 CHAR16*
373 EFIAPI
374 DriverEfiVersionProtocolDumpInformation(
375 IN CONST EFI_HANDLE TheHandle,
376 IN CONST BOOLEAN Verbose
377 )
378 {
379 EFI_DRIVER_SUPPORTED_EFI_VERSION_PROTOCOL *DriverEfiVersion;
380 EFI_STATUS Status;
381 CHAR16 *RetVal;
382
383 Status = gBS->HandleProtocol(
384 TheHandle,
385 &gEfiDriverSupportedEfiVersionProtocolGuid,
386 (VOID**)&DriverEfiVersion);
387
388 ASSERT_EFI_ERROR(Status);
389
390 RetVal = AllocateZeroPool(VersionStringSize);
391 ASSERT(RetVal != NULL);
392 UnicodeSPrint(RetVal, VersionStringSize, L"0x%08x", DriverEfiVersion->FirmwareVersion);
393 return (RetVal);
394 }
395
396 /**
397 Function to dump information about DevicePath protocol.
398
399 This will allocate the return buffer from boot services pool.
400
401 @param[in] TheHandle The handle that has the protocol installed.
402 @param[in] Verbose TRUE for additional information, FALSE otherwise.
403
404 @retval A poitner to a string containing the information.
405 **/
406 CHAR16*
407 EFIAPI
408 DevicePathProtocolDumpInformation(
409 IN CONST EFI_HANDLE TheHandle,
410 IN CONST BOOLEAN Verbose
411 )
412 {
413 EFI_DEVICE_PATH_PROTOCOL *DevPath;
414 CHAR16 *Temp;
415 CHAR16 *Temp2;
416 EFI_STATUS Status;
417 EFI_DEVICE_PATH_TO_TEXT_PROTOCOL *DevPathToText;
418 Temp = NULL;
419
420 Status = gBS->LocateProtocol(&gEfiDevicePathToTextProtocolGuid, NULL, (VOID**)&DevPathToText);
421 if (!EFI_ERROR(Status)) {
422 Status = gBS->OpenProtocol(TheHandle, &gEfiDevicePathProtocolGuid, (VOID**)&DevPath, gImageHandle, NULL, EFI_OPEN_PROTOCOL_GET_PROTOCOL);
423 if (!EFI_ERROR(Status)) {
424 //
425 // I cannot decide whether to allow shortcuts here (the second BOOLEAN on the next line)
426 //
427 Temp = DevPathToText->ConvertDevicePathToText(DevPath, TRUE, TRUE);
428 gBS->CloseProtocol(TheHandle, &gEfiDevicePathProtocolGuid, gImageHandle, NULL);
429 }
430 }
431 if (!Verbose && Temp != NULL && StrLen(Temp) > 30) {
432 Temp2 = NULL;
433 Temp2 = StrnCatGrow(&Temp2, NULL, Temp+(StrLen(Temp) - 30), 30);
434 FreePool(Temp);
435 Temp = Temp2;
436 }
437 return (Temp);
438 }
439
440 //
441 // Put the information on the NT32 protocol GUIDs here so we are not dependant on the Nt32Pkg
442 //
443 #define LOCAL_EFI_WIN_NT_THUNK_PROTOCOL_GUID \
444 { \
445 0x58c518b1, 0x76f3, 0x11d4, 0xbc, 0xea, 0x0, 0x80, 0xc7, 0x3c, 0x88, 0x81 \
446 }
447
448 #define LOCAL_EFI_WIN_NT_BUS_DRIVER_IO_PROTOCOL_GUID \
449 { \
450 0x96eb4ad6, 0xa32a, 0x11d4, 0xbc, 0xfd, 0x0, 0x80, 0xc7, 0x3c, 0x88, 0x81 \
451 }
452
453 #define LOCAL_EFI_WIN_NT_SERIAL_PORT_GUID \
454 { \
455 0xc95a93d, 0xa006, 0x11d4, 0xbc, 0xfa, 0x0, 0x80, 0xc7, 0x3c, 0x88, 0x81 \
456 }
457 STATIC CONST EFI_GUID WinNtThunkProtocolGuid = LOCAL_EFI_WIN_NT_THUNK_PROTOCOL_GUID;
458 STATIC CONST EFI_GUID WinNtIoProtocolGuid = LOCAL_EFI_WIN_NT_BUS_DRIVER_IO_PROTOCOL_GUID;
459 STATIC CONST EFI_GUID WinNtSerialPortGuid = LOCAL_EFI_WIN_NT_SERIAL_PORT_GUID;
460
461 STATIC CONST GUID_INFO_BLOCK mGuidStringListNT[] = {
462 {STRING_TOKEN(STR_WINNT_THUNK), (EFI_GUID*)&WinNtThunkProtocolGuid, NULL},
463 {STRING_TOKEN(STR_WINNT_DRIVER_IO), (EFI_GUID*)&WinNtIoProtocolGuid, NULL},
464 {STRING_TOKEN(STR_WINNT_SERIAL_PORT), (EFI_GUID*)&WinNtSerialPortGuid, NULL},
465 {STRING_TOKEN(STR_UNKNOWN_DEVICE), NULL, NULL},
466 };
467
468 STATIC CONST GUID_INFO_BLOCK mGuidStringList[] = {
469 {STRING_TOKEN(STR_LOADED_IMAGE), &gEfiLoadedImageProtocolGuid, NULL},
470 {STRING_TOKEN(STR_DEVICE_PATH), &gEfiDevicePathProtocolGuid, DevicePathProtocolDumpInformation},
471 {STRING_TOKEN(STR_IMAGE_PATH), &gEfiLoadedImageDevicePathProtocolGuid, DevicePathProtocolDumpInformation},
472 {STRING_TOKEN(STR_DEVICE_PATH_UTIL), &gEfiDevicePathUtilitiesProtocolGuid, NULL},
473 {STRING_TOKEN(STR_DEVICE_PATH_TXT), &gEfiDevicePathToTextProtocolGuid, NULL},
474 {STRING_TOKEN(STR_DEVICE_PATH_FTXT), &gEfiDevicePathFromTextProtocolGuid, NULL},
475 {STRING_TOKEN(STR_DEVICE_PATH_PC), &gEfiPcAnsiGuid, NULL},
476 {STRING_TOKEN(STR_DEVICE_PATH_VT100), &gEfiVT100Guid, NULL},
477 {STRING_TOKEN(STR_DEVICE_PATH_VT100P), &gEfiVT100PlusGuid, NULL},
478 {STRING_TOKEN(STR_DEVICE_PATH_VTUTF8), &gEfiVTUTF8Guid, NULL},
479 {STRING_TOKEN(STR_DRIVER_BINDING), &gEfiDriverBindingProtocolGuid, NULL},
480 {STRING_TOKEN(STR_PLATFORM_OVERRIDE), &gEfiPlatformDriverOverrideProtocolGuid, NULL},
481 {STRING_TOKEN(STR_BUS_OVERRIDE), &gEfiBusSpecificDriverOverrideProtocolGuid, NULL},
482 {STRING_TOKEN(STR_DRIVER_DIAG), &gEfiDriverDiagnosticsProtocolGuid, NULL},
483 {STRING_TOKEN(STR_DRIVER_DIAG2), &gEfiDriverDiagnostics2ProtocolGuid, NULL},
484 {STRING_TOKEN(STR_DRIVER_CN), &gEfiComponentNameProtocolGuid, NULL},
485 {STRING_TOKEN(STR_DRIVER_CN2), &gEfiComponentName2ProtocolGuid, NULL},
486 {STRING_TOKEN(STR_PLAT_DRV_CFG), &gEfiPlatformToDriverConfigurationProtocolGuid, NULL},
487 {STRING_TOKEN(STR_DRIVER_VERSION), &gEfiDriverSupportedEfiVersionProtocolGuid, DriverEfiVersionProtocolDumpInformation},
488 {STRING_TOKEN(STR_TXT_IN), &gEfiSimpleTextInProtocolGuid, NULL},
489 {STRING_TOKEN(STR_TXT_IN_EX), &gEfiSimpleTextInputExProtocolGuid, NULL},
490 {STRING_TOKEN(STR_TXT_OUT), &gEfiSimpleTextOutProtocolGuid, TxtOutProtocolDumpInformation},
491 {STRING_TOKEN(STR_SIM_POINTER), &gEfiSimplePointerProtocolGuid, NULL},
492 {STRING_TOKEN(STR_ABS_POINTER), &gEfiAbsolutePointerProtocolGuid, NULL},
493 {STRING_TOKEN(STR_SERIAL_IO), &gEfiSerialIoProtocolGuid, NULL},
494 {STRING_TOKEN(STR_GRAPHICS_OUTPUT), &gEfiGraphicsOutputProtocolGuid, NULL},
495 {STRING_TOKEN(STR_EDID_DISCOVERED), &gEfiEdidDiscoveredProtocolGuid, NULL},
496 {STRING_TOKEN(STR_EDID_ACTIVE), &gEfiEdidActiveProtocolGuid, NULL},
497 {STRING_TOKEN(STR_EDID_OVERRIDE), &gEfiEdidOverrideProtocolGuid, NULL},
498 {STRING_TOKEN(STR_CON_IN), &gEfiConsoleInDeviceGuid, NULL},
499 {STRING_TOKEN(STR_CON_OUT), &gEfiConsoleOutDeviceGuid, NULL},
500 {STRING_TOKEN(STR_STD_ERR), &gEfiStandardErrorDeviceGuid, NULL},
501 {STRING_TOKEN(STR_LOAD_FILE), &gEfiLoadFileProtocolGuid, NULL},
502 {STRING_TOKEN(STR_LOAD_FILE2), &gEfiLoadFile2ProtocolGuid, NULL},
503 {STRING_TOKEN(STR_SIMPLE_FILE_SYS), &gEfiSimpleFileSystemProtocolGuid, NULL},
504 {STRING_TOKEN(STR_TAPE_IO), &gEfiTapeIoProtocolGuid, NULL},
505 {STRING_TOKEN(STR_DISK_IO), &gEfiDiskIoProtocolGuid, NULL},
506 {STRING_TOKEN(STR_BLK_IO), &gEfiBlockIoProtocolGuid, NULL},
507 {STRING_TOKEN(STR_UC), &gEfiUnicodeCollationProtocolGuid, NULL},
508 {STRING_TOKEN(STR_UC2), &gEfiUnicodeCollation2ProtocolGuid, NULL},
509 {STRING_TOKEN(STR_PCIRB_IO), &gEfiPciRootBridgeIoProtocolGuid, PciRootBridgeIoDumpInformation},
510 {STRING_TOKEN(STR_PCI_IO), &gEfiPciIoProtocolGuid, NULL},
511 {STRING_TOKEN(STR_SCSI_PT), &gEfiScsiPassThruProtocolGuid, NULL},
512 {STRING_TOKEN(STR_SCSI_IO), &gEfiScsiIoProtocolGuid, NULL},
513 {STRING_TOKEN(STR_SCSI_PT_EXT), &gEfiExtScsiPassThruProtocolGuid, NULL},
514 {STRING_TOKEN(STR_ISCSI), &gEfiIScsiInitiatorNameProtocolGuid, NULL},
515 {STRING_TOKEN(STR_USB_IO), &gEfiUsbIoProtocolGuid, NULL},
516 {STRING_TOKEN(STR_USB_HC), &gEfiUsbHcProtocolGuid, NULL},
517 {STRING_TOKEN(STR_USB_HC2), &gEfiUsb2HcProtocolGuid, NULL},
518 {STRING_TOKEN(STR_DEBUG_SUPPORT), &gEfiDebugSupportProtocolGuid, NULL},
519 {STRING_TOKEN(STR_DEBUG_PORT), &gEfiDebugPortProtocolGuid, NULL},
520 {STRING_TOKEN(STR_DECOMPRESS), &gEfiDecompressProtocolGuid, NULL},
521 {STRING_TOKEN(STR_ACPI_TABLE), &gEfiAcpiTableProtocolGuid, NULL},
522 {STRING_TOKEN(STR_EBC_INTERPRETER), &gEfiEbcProtocolGuid, NULL},
523 {STRING_TOKEN(STR_SNP), &gEfiSimpleNetworkProtocolGuid, NULL},
524 {STRING_TOKEN(STR_NII), &gEfiNetworkInterfaceIdentifierProtocolGuid, NULL},
525 {STRING_TOKEN(STR_NII_31), &gEfiNetworkInterfaceIdentifierProtocolGuid_31, NULL},
526 {STRING_TOKEN(STR_PXE_BC), &gEfiPxeBaseCodeProtocolGuid, NULL},
527 {STRING_TOKEN(STR_PXE_CB), &gEfiPxeBaseCodeCallbackProtocolGuid, NULL},
528 {STRING_TOKEN(STR_BIS), &gEfiBisProtocolGuid, NULL},
529 {STRING_TOKEN(STR_MNP_SB), &gEfiManagedNetworkServiceBindingProtocolGuid, NULL},
530 {STRING_TOKEN(STR_MNP), &gEfiManagedNetworkProtocolGuid, NULL},
531 {STRING_TOKEN(STR_ARP_SB), &gEfiArpServiceBindingProtocolGuid, NULL},
532 {STRING_TOKEN(STR_ARP), &gEfiArpProtocolGuid, NULL},
533 {STRING_TOKEN(STR_DHCPV4_SB), &gEfiDhcp4ServiceBindingProtocolGuid, NULL},
534 {STRING_TOKEN(STR_DHCPV4), &gEfiDhcp4ProtocolGuid, NULL},
535 {STRING_TOKEN(STR_TCPV4_SB), &gEfiTcp4ServiceBindingProtocolGuid, NULL},
536 {STRING_TOKEN(STR_TCPV4), &gEfiTcp4ProtocolGuid, NULL},
537 {STRING_TOKEN(STR_IPV4_SB), &gEfiIp4ServiceBindingProtocolGuid, NULL},
538 {STRING_TOKEN(STR_IPV4), &gEfiIp4ProtocolGuid, NULL},
539 {STRING_TOKEN(STR_IPV4_CFG), &gEfiIp4ConfigProtocolGuid, NULL},
540 {STRING_TOKEN(STR_SHELL_PARAMETERS), &gEfiShellParametersProtocolGuid, NULL},
541 {STRING_TOKEN(STR_SHELL), &gEfiShellProtocolGuid, NULL},
542 {STRING_TOKEN(STR_UDPV4_SB), &gEfiUdp4ServiceBindingProtocolGuid, NULL},
543 {STRING_TOKEN(STR_UDPV4), &gEfiUdp4ProtocolGuid, NULL},
544 {STRING_TOKEN(STR_MTFTPV4_SB), &gEfiMtftp4ServiceBindingProtocolGuid, NULL},
545 {STRING_TOKEN(STR_MTFTPV4), &gEfiMtftp4ProtocolGuid, NULL},
546 {STRING_TOKEN(STR_AUTH_INFO), &gEfiAuthenticationInfoProtocolGuid, NULL},
547 {STRING_TOKEN(STR_HASH_SB), &gEfiHashServiceBindingProtocolGuid, NULL},
548 {STRING_TOKEN(STR_HASH), &gEfiHashProtocolGuid, NULL},
549 {STRING_TOKEN(STR_HII_FONT), &gEfiHiiFontProtocolGuid, NULL},
550 {STRING_TOKEN(STR_HII_STRING), &gEfiHiiStringProtocolGuid, NULL},
551 {STRING_TOKEN(STR_HII_IMAGE), &gEfiHiiImageProtocolGuid, NULL},
552 {STRING_TOKEN(STR_HII_DATABASE), &gEfiHiiDatabaseProtocolGuid, NULL},
553 {STRING_TOKEN(STR_HII_CONFIG_ROUT), &gEfiHiiConfigRoutingProtocolGuid, NULL},
554 {STRING_TOKEN(STR_HII_CONFIG_ACC), &gEfiHiiConfigAccessProtocolGuid, NULL},
555 {STRING_TOKEN(STR_HII_FORM_BROWSER2), &gEfiFormBrowser2ProtocolGuid, NULL},
556 {STRING_TOKEN(STR_DRIVER_FAM_OVERRIDE), &gEfiDriverFamilyOverrideProtocolGuid, NULL},
557 {STRING_TOKEN(STR_PCD), &gPcdProtocolGuid, NULL},
558 {STRING_TOKEN(STR_TCG), &gEfiTcgProtocolGuid, NULL},
559 {STRING_TOKEN(STR_HII_PACKAGE_LIST), &gEfiHiiPackageListProtocolGuid, NULL},
560
561 //
562 // the ones under this are deprecated by the current UEFI Spec, but may be found anyways...
563 //
564 {STRING_TOKEN(STR_SHELL_INTERFACE), &gEfiShellInterfaceGuid, NULL},
565 {STRING_TOKEN(STR_SHELL_ENV2), &gEfiShellEnvironment2Guid, NULL},
566 {STRING_TOKEN(STR_SHELL_ENV), &gEfiShellEnvironment2Guid, NULL},
567 {STRING_TOKEN(STR_DEVICE_IO), &gEfiDeviceIoProtocolGuid, NULL},
568 {STRING_TOKEN(STR_UGA_DRAW), &gEfiUgaDrawProtocolGuid, NULL},
569 {STRING_TOKEN(STR_UGA_IO), &gEfiUgaIoProtocolGuid, NULL},
570 {STRING_TOKEN(STR_ESP), &gEfiPartTypeSystemPartGuid, NULL},
571 {STRING_TOKEN(STR_GPT_NBR), &gEfiPartTypeLegacyMbrGuid, NULL},
572 {STRING_TOKEN(STR_DRIVER_CONFIG), &gEfiDriverConfigurationProtocolGuid, NULL},
573 {STRING_TOKEN(STR_DRIVER_CONFIG2), &gEfiDriverConfiguration2ProtocolGuid, NULL},
574
575 //
576 // the ones under this are GUID identified structs, not protocols
577 //
578 {STRING_TOKEN(STR_FILE_INFO), &gEfiFileInfoGuid, NULL},
579 {STRING_TOKEN(STR_FILE_SYS_INFO), &gEfiFileSystemInfoGuid, NULL},
580
581 //
582 // the ones under this are misc GUIDS.
583 //
584 {STRING_TOKEN(STR_EFI_GLOBAL_VARIABLE), &gEfiGlobalVariableGuid, NULL},
585
586 //
587 // UEFI 2.2
588 //
589 {STRING_TOKEN(STR_IP6_SB), &gEfiIp6ServiceBindingProtocolGuid, NULL},
590 {STRING_TOKEN(STR_IP6), &gEfiIp6ProtocolGuid, NULL},
591 {STRING_TOKEN(STR_IP6_CONFIG), &gEfiIp6ConfigProtocolGuid, NULL},
592 {STRING_TOKEN(STR_MTFTP6_SB), &gEfiMtftp6ServiceBindingProtocolGuid, NULL},
593 {STRING_TOKEN(STR_MTFTP6), &gEfiMtftp6ProtocolGuid, NULL},
594 {STRING_TOKEN(STR_DHCP6_SB), &gEfiDhcp6ServiceBindingProtocolGuid, NULL},
595 {STRING_TOKEN(STR_DHCP6), &gEfiDhcp6ProtocolGuid, NULL},
596 {STRING_TOKEN(STR_UDP6_SB), &gEfiUdp6ServiceBindingProtocolGuid, NULL},
597 {STRING_TOKEN(STR_UDP6), &gEfiUdp6ProtocolGuid, NULL},
598 {STRING_TOKEN(STR_TCP6_SB), &gEfiTcp6ServiceBindingProtocolGuid, NULL},
599 {STRING_TOKEN(STR_TCP6), &gEfiTcp6ProtocolGuid, NULL},
600 {STRING_TOKEN(STR_VLAN_CONFIG), &gEfiVlanConfigProtocolGuid, NULL},
601 {STRING_TOKEN(STR_EAP), &gEfiEapProtocolGuid, NULL},
602 {STRING_TOKEN(STR_EAP_MGMT), &gEfiEapManagementProtocolGuid, NULL},
603 {STRING_TOKEN(STR_FTP4_SB), &gEfiFtp4ServiceBindingProtocolGuid, NULL},
604 {STRING_TOKEN(STR_FTP4), &gEfiFtp4ProtocolGuid, NULL},
605 {STRING_TOKEN(STR_IP_SEC_CONFIG), &gEfiIpSecConfigProtocolGuid, NULL},
606 {STRING_TOKEN(STR_DH), &gEfiDriverHealthProtocolGuid, NULL},
607 {STRING_TOKEN(STR_DEF_IMG_LOAD), &gEfiDeferredImageLoadProtocolGuid, NULL},
608 {STRING_TOKEN(STR_USER_CRED), &gEfiUserCredentialProtocolGuid, NULL},
609 {STRING_TOKEN(STR_USER_MNGR), &gEfiUserManagerProtocolGuid, NULL},
610 {STRING_TOKEN(STR_ATA_PASS_THRU), &gEfiAtaPassThruProtocolGuid, NULL},
611
612 //
613 // UEFI 2.3
614 //
615 {STRING_TOKEN(STR_FW_MGMT), &gEfiFirmwareManagementProtocolGuid, NULL},
616 {STRING_TOKEN(STR_IP_SEC), &gEfiIpSecProtocolGuid, NULL},
617 {STRING_TOKEN(STR_IP_SEC2), &gEfiIpSec2ProtocolGuid, NULL},
618
619 //
620 // UEFI 2.3.1
621 //
622 {STRING_TOKEN(STR_KMS), &gEfiKmsProtocolGuid, NULL},
623 {STRING_TOKEN(STR_BLK_IO2), &gEfiBlockIo2ProtocolGuid, NULL},
624 {STRING_TOKEN(STR_SSC), &gEfiStorageSecurityCommandProtocolGuid, NULL},
625 {STRING_TOKEN(STR_UC2), &gEfiUserCredential2ProtocolGuid, NULL},
626
627 //
628 // terminator
629 //
630 {STRING_TOKEN(STR_UNKNOWN_DEVICE), NULL, NULL},
631 };
632
633 /**
634 Function to get the node for a protocol or struct from it's GUID.
635
636 if Guid is NULL, then ASSERT.
637
638 @param[in] Guid The GUID to look for the name of.
639
640 @return The node.
641 **/
642 CONST GUID_INFO_BLOCK *
643 EFIAPI
644 InternalShellGetNodeFromGuid(
645 IN CONST EFI_GUID* Guid
646 )
647 {
648 CONST GUID_INFO_BLOCK *ListWalker;
649
650 ASSERT(Guid != NULL);
651
652 if (PcdGetBool(PcdShellIncludeNtGuids)) {
653 for (ListWalker = mGuidStringListNT ; ListWalker != NULL && ListWalker->GuidId != NULL ; ListWalker++) {
654 if (CompareGuid(ListWalker->GuidId, Guid)) {
655 return (ListWalker);
656 }
657 }
658 }
659 for (ListWalker = mGuidStringList ; ListWalker != NULL && ListWalker->GuidId != NULL ; ListWalker++) {
660 if (CompareGuid(ListWalker->GuidId, Guid)) {
661 return (ListWalker);
662 }
663 }
664 return (ListWalker);
665 }
666
667 /**
668 Function to get the name of a protocol or struct from it's GUID.
669
670 if Guid is NULL, then ASSERT.
671
672 @param[in] Guid The GUID to look for the name of.
673 @param[in] Lang The language to use.
674
675 @return pointer to string of the name. The caller
676 is responsible to free this memory.
677 **/
678 CHAR16*
679 EFIAPI
680 GetStringNameFromGuid(
681 IN CONST EFI_GUID *Guid,
682 IN CONST CHAR8 *Lang OPTIONAL
683 )
684 {
685 CONST GUID_INFO_BLOCK *Id;
686
687 Id = InternalShellGetNodeFromGuid(Guid);
688 return (HiiGetString(mHandleParsingHiiHandle, Id->StringId, Lang));
689 }
690
691 /**
692 Function to dump protocol information from a handle.
693
694 This function will return a allocated string buffer containing the
695 information. The caller is responsible for freeing the memory.
696
697 If Guid is NULL, ASSERT().
698 If TheHandle is NULL, ASSERT().
699
700 @param[in] TheHandle The handle to dump information from.
701 @param[in] Guid The GUID of the protocol to dump.
702 @param[in] Verbose TRUE for extra info. FALSE otherwise.
703
704 @return The pointer to string.
705 @retval NULL An error was encountered.
706 **/
707 CHAR16*
708 EFIAPI
709 GetProtocolInformationDump(
710 IN CONST EFI_HANDLE TheHandle,
711 IN CONST EFI_GUID *Guid,
712 IN CONST BOOLEAN Verbose
713 )
714 {
715 CONST GUID_INFO_BLOCK *Id;
716
717 ASSERT(TheHandle != NULL);
718 ASSERT(Guid != NULL);
719
720 if (TheHandle == NULL || Guid == NULL) {
721 return (NULL);
722 }
723
724 Id = InternalShellGetNodeFromGuid(Guid);
725 if (Id != NULL && Id->DumpInfo != NULL) {
726 return (Id->DumpInfo(TheHandle, Verbose));
727 }
728 return (NULL);
729 }
730
731 /**
732 Function to get the Guid for a protocol or struct based on it's string name.
733
734 @param[in] Name The pointer to the string name.
735 @param[in] Lang The pointer to the language code.
736 @param[in] Guid The pointer to the Guid.
737
738 @retval EFI_SUCCESS The operation was sucessful.
739 **/
740 EFI_STATUS
741 EFIAPI
742 GetGuidFromStringName(
743 IN CONST CHAR16 *Name,
744 IN CONST CHAR8 *Lang OPTIONAL,
745 IN EFI_GUID **Guid
746 )
747 {
748 CONST GUID_INFO_BLOCK *ListWalker;
749 CHAR16 *String;
750
751 ASSERT(Guid != NULL);
752 if (Guid == NULL) {
753 return (EFI_INVALID_PARAMETER);
754 }
755 *Guid = NULL;
756
757 if (PcdGetBool(PcdShellIncludeNtGuids)) {
758 for (ListWalker = mGuidStringListNT ; ListWalker != NULL && ListWalker->GuidId != NULL ; ListWalker++) {
759 String = HiiGetString(mHandleParsingHiiHandle, ListWalker->StringId, Lang);
760 if (Name != NULL && String != NULL && StrCmp(Name, String)==0) {
761 *Guid = ListWalker->GuidId;
762 }
763 SHELL_FREE_NON_NULL(String);
764 if (*Guid != NULL) {
765 return (EFI_SUCCESS);
766 }
767 }
768 }
769 for (ListWalker = mGuidStringList ; ListWalker != NULL && ListWalker->GuidId != NULL ; ListWalker++) {
770 String = HiiGetString(mHandleParsingHiiHandle, ListWalker->StringId, Lang);
771 if (Name != NULL && String != NULL && StrCmp(Name, String)==0) {
772 *Guid = ListWalker->GuidId;
773 }
774 SHELL_FREE_NON_NULL(String);
775 if (*Guid != NULL) {
776 return (EFI_SUCCESS);
777 }
778 }
779 return (EFI_NOT_FOUND);
780 }
781
782 /**
783 Get best support language for this driver.
784
785 First base on the current platform used language to search,Second base on the
786 default language to search. The caller need to free the buffer of the best
787 language.
788
789 @param[in] SupportedLanguages The support languages for this driver.
790 @param[in] Iso639Language Whether get language for ISO639.
791
792 @return The best support language for this driver.
793 **/
794 CHAR8 *
795 GetBestLanguageForDriver (
796 IN CONST CHAR8 *SupportedLanguages,
797 IN BOOLEAN Iso639Language
798 )
799 {
800 CHAR8 *LanguageVariable;
801 CHAR8 *BestLanguage;
802
803 LanguageVariable = GetVariable (Iso639Language ? L"Lang" : L"PlatformLang", &gEfiGlobalVariableGuid);
804
805 BestLanguage = GetBestLanguage(
806 SupportedLanguages,
807 Iso639Language,
808 (LanguageVariable != NULL) ? LanguageVariable : "",
809 Iso639Language ? "en" : "en-US",
810 NULL
811 );
812
813 if (LanguageVariable != NULL) {
814 FreePool (LanguageVariable);
815 }
816
817 return BestLanguage;
818 }
819
820 /**
821 Function to retrieve the driver name (if possible) from the ComponentName or
822 ComponentName2 protocol
823
824 @param[in] TheHandle The driver handle to get the name of.
825 @param[in] Language The language to use.
826
827 @retval NULL The name could not be found.
828 @return A pointer to the string name. Do not de-allocate the memory.
829 **/
830 CONST CHAR16*
831 EFIAPI
832 GetStringNameFromHandle(
833 IN CONST EFI_HANDLE TheHandle,
834 IN CONST CHAR8 *Language
835 )
836 {
837 EFI_COMPONENT_NAME2_PROTOCOL *CompNameStruct;
838 EFI_STATUS Status;
839 CHAR16 *RetVal;
840 CHAR8 *BestLang;
841
842 BestLang = NULL;
843
844 Status = gBS->OpenProtocol(
845 TheHandle,
846 &gEfiComponentName2ProtocolGuid,
847 (VOID**)&CompNameStruct,
848 gImageHandle,
849 NULL,
850 EFI_OPEN_PROTOCOL_GET_PROTOCOL);
851 if (!EFI_ERROR(Status)) {
852 if (Language == NULL) {
853 BestLang = GetBestLanguageForDriver (CompNameStruct->SupportedLanguages, FALSE);
854 Language = BestLang;
855 }
856 Status = CompNameStruct->GetDriverName(CompNameStruct, (CHAR8*)Language, &RetVal);
857
858 if (BestLang != NULL) {
859 FreePool (BestLang);
860 BestLang = NULL;
861 }
862 if (!EFI_ERROR(Status)) {
863 return (RetVal);
864 }
865 }
866 Status = gBS->OpenProtocol(
867 TheHandle,
868 &gEfiComponentNameProtocolGuid,
869 (VOID**)&CompNameStruct,
870 gImageHandle,
871 NULL,
872 EFI_OPEN_PROTOCOL_GET_PROTOCOL);
873 if (!EFI_ERROR(Status)) {
874 if (Language == NULL) {
875 BestLang = GetBestLanguageForDriver (CompNameStruct->SupportedLanguages, FALSE);
876 Language = BestLang;
877 }
878 Status = CompNameStruct->GetDriverName(CompNameStruct, (CHAR8*)Language, &RetVal);
879
880 if (BestLang != NULL) {
881 FreePool (BestLang);
882 }
883 if (!EFI_ERROR(Status)) {
884 return (RetVal);
885 }
886 }
887 return (NULL);
888 }
889
890 /**
891 Function to initialize the file global mHandleList object for use in
892 vonverting handles to index and index to handle.
893
894 @retval EFI_SUCCESS The operation was successful.
895 **/
896 EFI_STATUS
897 EFIAPI
898 InternalShellInitHandleList(
899 VOID
900 )
901 {
902 EFI_STATUS Status;
903 EFI_HANDLE *HandleBuffer;
904 UINTN HandleCount;
905 HANDLE_LIST *ListWalker;
906
907 if (mHandleList.NextIndex != 0) {
908 return EFI_SUCCESS;
909 }
910 InitializeListHead(&mHandleList.List.Link);
911 mHandleList.NextIndex = 1;
912 Status = gBS->LocateHandleBuffer (
913 AllHandles,
914 NULL,
915 NULL,
916 &HandleCount,
917 &HandleBuffer
918 );
919 ASSERT_EFI_ERROR(Status);
920 if (EFI_ERROR(Status)) {
921 return (Status);
922 }
923 for (mHandleList.NextIndex = 1 ; mHandleList.NextIndex <= HandleCount ; mHandleList.NextIndex++){
924 ListWalker = AllocateZeroPool(sizeof(HANDLE_LIST));
925 ASSERT(ListWalker != NULL);
926 ListWalker->TheHandle = HandleBuffer[mHandleList.NextIndex-1];
927 ListWalker->TheIndex = mHandleList.NextIndex;
928 InsertTailList(&mHandleList.List.Link,&ListWalker->Link);
929 }
930 FreePool(HandleBuffer);
931 return (EFI_SUCCESS);
932 }
933
934 /**
935 Function to retrieve the human-friendly index of a given handle. If the handle
936 does not have a index one will be automatically assigned. The index value is valid
937 until the termination of the shell application.
938
939 @param[in] TheHandle The handle to retrieve an index for.
940
941 @retval 0 A memory allocation failed.
942 @return The index of the handle.
943
944 **/
945 UINTN
946 EFIAPI
947 ConvertHandleToHandleIndex(
948 IN CONST EFI_HANDLE TheHandle
949 )
950 {
951 HANDLE_LIST *ListWalker;
952 if (TheHandle == NULL) {
953 return 0;
954 }
955
956 InternalShellInitHandleList();
957
958 for (ListWalker = (HANDLE_LIST*)GetFirstNode(&mHandleList.List.Link)
959 ; !IsNull(&mHandleList.List.Link,&ListWalker->Link)
960 ; ListWalker = (HANDLE_LIST*)GetNextNode(&mHandleList.List.Link,&ListWalker->Link)
961 ){
962 if (ListWalker->TheHandle == TheHandle) {
963 return (ListWalker->TheIndex);
964 }
965 }
966 ListWalker = AllocateZeroPool(sizeof(HANDLE_LIST));
967 ASSERT(ListWalker != NULL);
968 ListWalker->TheHandle = TheHandle;
969 ListWalker->TheIndex = mHandleList.NextIndex++;
970 InsertTailList(&mHandleList.List.Link,&ListWalker->Link);
971 return (ListWalker->TheIndex);
972 }
973
974
975
976 /**
977 Function to retrieve the EFI_HANDLE from the human-friendly index.
978
979 @param[in] TheIndex The index to retrieve the EFI_HANDLE for.
980
981 @retval NULL The index was invalid.
982 @return The EFI_HANDLE that index represents.
983
984 **/
985 EFI_HANDLE
986 EFIAPI
987 ConvertHandleIndexToHandle(
988 IN CONST UINTN TheIndex
989 )
990 {
991 HANDLE_LIST *ListWalker;
992
993 InternalShellInitHandleList();
994
995 if (TheIndex >= mHandleList.NextIndex) {
996 return (NULL);
997 }
998
999 for (ListWalker = (HANDLE_LIST*)GetFirstNode(&mHandleList.List.Link)
1000 ; !IsNull(&mHandleList.List.Link,&ListWalker->Link)
1001 ; ListWalker = (HANDLE_LIST*)GetNextNode(&mHandleList.List.Link,&ListWalker->Link)
1002 ){
1003 if (ListWalker->TheIndex == TheIndex) {
1004 return (ListWalker->TheHandle);
1005 }
1006 }
1007 return (NULL);
1008 }
1009
1010 /**
1011 Gets all the related EFI_HANDLEs based on the mask supplied.
1012
1013 This function scans all EFI_HANDLES in the UEFI environment's handle database
1014 and returns the ones with the specified relationship (Mask) to the specified
1015 controller handle.
1016
1017 If both DriverBindingHandle and ControllerHandle are NULL, then ASSERT.
1018 If MatchingHandleCount is NULL, then ASSERT.
1019
1020 If MatchingHandleBuffer is not NULL upon a successful return the memory must be
1021 caller freed.
1022
1023 @param[in] DriverBindingHandle The handle with Driver Binding protocol on it.
1024 @param[in] ControllerHandle The handle with Device Path protocol on it.
1025 @param[in] MatchingHandleCount The pointer to UINTN that specifies the number of HANDLES in
1026 MatchingHandleBuffer.
1027 @param[out] MatchingHandleBuffer On a successful return, a buffer of MatchingHandleCount
1028 EFI_HANDLEs with a terminating NULL EFI_HANDLE.
1029 @param[out] HandleType An array of type information.
1030
1031 @retval EFI_SUCCESS The operation was successful, and any related handles
1032 are in MatchingHandleBuffer.
1033 @retval EFI_NOT_FOUND No matching handles were found.
1034 @retval EFI_INVALID_PARAMETER A parameter was invalid or out of range.
1035 **/
1036 EFI_STATUS
1037 EFIAPI
1038 ParseHandleDatabaseByRelationshipWithType (
1039 IN CONST EFI_HANDLE DriverBindingHandle OPTIONAL,
1040 IN CONST EFI_HANDLE ControllerHandle OPTIONAL,
1041 IN UINTN *HandleCount,
1042 OUT EFI_HANDLE **HandleBuffer,
1043 OUT UINTN **HandleType
1044 )
1045 {
1046 EFI_STATUS Status;
1047 UINTN HandleIndex;
1048 EFI_GUID **ProtocolGuidArray;
1049 UINTN ArrayCount;
1050 UINTN ProtocolIndex;
1051 EFI_OPEN_PROTOCOL_INFORMATION_ENTRY *OpenInfo;
1052 UINTN OpenInfoCount;
1053 UINTN OpenInfoIndex;
1054 UINTN ChildIndex;
1055
1056 ASSERT(HandleCount != NULL);
1057 ASSERT(HandleBuffer != NULL);
1058 ASSERT(HandleType != NULL);
1059 ASSERT(DriverBindingHandle != NULL || ControllerHandle != NULL);
1060
1061 *HandleCount = 0;
1062 *HandleBuffer = NULL;
1063 *HandleType = NULL;
1064
1065 //
1066 // Retrieve the list of all handles from the handle database
1067 //
1068 Status = gBS->LocateHandleBuffer (
1069 AllHandles,
1070 NULL,
1071 NULL,
1072 HandleCount,
1073 HandleBuffer
1074 );
1075 if (EFI_ERROR (Status)) {
1076 return (Status);
1077 }
1078
1079 *HandleType = AllocateZeroPool (*HandleCount * sizeof (UINTN));
1080 ASSERT(*HandleType != NULL);
1081
1082 for (HandleIndex = 0; HandleIndex < *HandleCount; HandleIndex++) {
1083 //
1084 // Retrieve the list of all the protocols on each handle
1085 //
1086 Status = gBS->ProtocolsPerHandle (
1087 (*HandleBuffer)[HandleIndex],
1088 &ProtocolGuidArray,
1089 &ArrayCount
1090 );
1091 if (!EFI_ERROR (Status)) {
1092
1093 for (ProtocolIndex = 0; ProtocolIndex < ArrayCount; ProtocolIndex++) {
1094
1095 //
1096 // Set the bit describing what this handle has
1097 //
1098 if (CompareGuid (ProtocolGuidArray[ProtocolIndex], &gEfiLoadedImageProtocolGuid) ) {
1099 (*HandleType)[HandleIndex] |= HR_IMAGE_HANDLE;
1100 } else if (CompareGuid (ProtocolGuidArray[ProtocolIndex], &gEfiDriverBindingProtocolGuid) ) {
1101 (*HandleType)[HandleIndex] |= HR_DRIVER_BINDING_HANDLE;
1102 } else if (CompareGuid (ProtocolGuidArray[ProtocolIndex], &gEfiDriverConfiguration2ProtocolGuid)) {
1103 (*HandleType)[HandleIndex] |= HR_DRIVER_CONFIGURATION_HANDLE;
1104 } else if (CompareGuid (ProtocolGuidArray[ProtocolIndex], &gEfiDriverConfigurationProtocolGuid) ) {
1105 (*HandleType)[HandleIndex] |= HR_DRIVER_CONFIGURATION_HANDLE;
1106 } else if (CompareGuid (ProtocolGuidArray[ProtocolIndex], &gEfiDriverDiagnostics2ProtocolGuid) ) {
1107 (*HandleType)[HandleIndex] |= HR_DRIVER_DIAGNOSTICS_HANDLE;
1108 } else if (CompareGuid (ProtocolGuidArray[ProtocolIndex], &gEfiDriverDiagnosticsProtocolGuid) ) {
1109 (*HandleType)[HandleIndex] |= HR_DRIVER_DIAGNOSTICS_HANDLE;
1110 } else if (CompareGuid (ProtocolGuidArray[ProtocolIndex], &gEfiComponentName2ProtocolGuid) ) {
1111 (*HandleType)[HandleIndex] |= HR_COMPONENT_NAME_HANDLE;
1112 } else if (CompareGuid (ProtocolGuidArray[ProtocolIndex], &gEfiComponentNameProtocolGuid) ) {
1113 (*HandleType)[HandleIndex] |= HR_COMPONENT_NAME_HANDLE;
1114 } else if (CompareGuid (ProtocolGuidArray[ProtocolIndex], &gEfiDevicePathProtocolGuid) ) {
1115 (*HandleType)[HandleIndex] |= HR_DEVICE_HANDLE;
1116 } else {
1117 DEBUG_CODE_BEGIN();
1118 ASSERT((*HandleType)[HandleIndex] == (*HandleType)[HandleIndex]);
1119 DEBUG_CODE_END();
1120 }
1121 //
1122 // Retrieve the list of agents that have opened each protocol
1123 //
1124 Status = gBS->OpenProtocolInformation (
1125 (*HandleBuffer)[HandleIndex],
1126 ProtocolGuidArray[ProtocolIndex],
1127 &OpenInfo,
1128 &OpenInfoCount
1129 );
1130 if (!EFI_ERROR (Status)) {
1131 for (OpenInfoIndex = 0; OpenInfoIndex < OpenInfoCount; OpenInfoIndex++) {
1132 if (DriverBindingHandle != NULL && OpenInfo[OpenInfoIndex].AgentHandle == DriverBindingHandle) {
1133 if ((OpenInfo[OpenInfoIndex].Attributes & EFI_OPEN_PROTOCOL_BY_DRIVER) == EFI_OPEN_PROTOCOL_BY_DRIVER) {
1134 (*HandleType)[HandleIndex] |= (HR_DEVICE_HANDLE | HR_CONTROLLER_HANDLE);
1135 }
1136 if (ControllerHandle != NULL && (*HandleBuffer)[HandleIndex] == ControllerHandle) {
1137 if ((OpenInfo[OpenInfoIndex].Attributes & EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER) == EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER) {
1138 for (ChildIndex = 0; ChildIndex < *HandleCount; ChildIndex++) {
1139 if ((*HandleBuffer)[ChildIndex] == OpenInfo[OpenInfoIndex].ControllerHandle) {
1140 (*HandleType)[ChildIndex] |= (HR_DEVICE_HANDLE | HR_CHILD_HANDLE);
1141 }
1142 }
1143 }
1144 }
1145 }
1146 if (DriverBindingHandle == NULL && OpenInfo[OpenInfoIndex].ControllerHandle == ControllerHandle) {
1147 if ((OpenInfo[OpenInfoIndex].Attributes & EFI_OPEN_PROTOCOL_BY_DRIVER) == EFI_OPEN_PROTOCOL_BY_DRIVER) {
1148 for (ChildIndex = 0; ChildIndex < *HandleCount; ChildIndex++) {
1149 if ((*HandleBuffer)[ChildIndex] == OpenInfo[OpenInfoIndex].AgentHandle) {
1150 (*HandleType)[ChildIndex] |= HR_DEVICE_DRIVER;
1151 }
1152 }
1153 }
1154 if ((OpenInfo[OpenInfoIndex].Attributes & EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER) == EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER) {
1155 (*HandleType)[HandleIndex] |= HR_PARENT_HANDLE;
1156 for (ChildIndex = 0; ChildIndex < *HandleCount; ChildIndex++) {
1157 if ((*HandleBuffer)[ChildIndex] == OpenInfo[OpenInfoIndex].AgentHandle) {
1158 (*HandleType)[ChildIndex] |= HR_BUS_DRIVER;
1159 }
1160 }
1161 }
1162 }
1163 }
1164
1165 FreePool (OpenInfo);
1166 }
1167 }
1168
1169 FreePool (ProtocolGuidArray);
1170 }
1171 }
1172
1173 if (EFI_ERROR(Status)) {
1174 if (*HandleType != NULL) {
1175 FreePool (*HandleType);
1176 }
1177 if (*HandleBuffer != NULL) {
1178 FreePool (*HandleBuffer);
1179 }
1180
1181 *HandleCount = 0;
1182 *HandleBuffer = NULL;
1183 *HandleType = NULL;
1184 }
1185
1186 return Status;
1187 }
1188
1189 /**
1190 Gets all the related EFI_HANDLEs based on the single EFI_HANDLE and the mask
1191 supplied.
1192
1193 This function will scan all EFI_HANDLES in the UEFI environment's handle database
1194 and return all the ones with the specified relationship (Mask) to the specified
1195 controller handle.
1196
1197 If both DriverBindingHandle and ControllerHandle are NULL, then ASSERT.
1198 If MatchingHandleCount is NULL, then ASSERT.
1199
1200 If MatchingHandleBuffer is not NULL upon a sucessful return the memory must be
1201 caller freed.
1202
1203 @param[in] DriverBindingHandle Handle to a object with Driver Binding protocol
1204 on it.
1205 @param[in] ControllerHandle Handle to a device with Device Path protocol on it.
1206 @param[in] Mask Mask of what relationship(s) is desired.
1207 @param[in] MatchingHandleCount Poitner to UINTN specifying number of HANDLES in
1208 MatchingHandleBuffer.
1209 @param[out] MatchingHandleBuffer On a sucessful return a buffer of MatchingHandleCount
1210 EFI_HANDLEs and a terminating NULL EFI_HANDLE.
1211
1212 @retval EFI_SUCCESS The operation was sucessful and any related handles
1213 are in MatchingHandleBuffer;
1214 @retval EFI_NOT_FOUND No matching handles were found.
1215 @retval EFI_INVALID_PARAMETER A parameter was invalid or out of range.
1216 **/
1217 EFI_STATUS
1218 EFIAPI
1219 ParseHandleDatabaseByRelationship (
1220 IN CONST EFI_HANDLE DriverBindingHandle OPTIONAL,
1221 IN CONST EFI_HANDLE ControllerHandle OPTIONAL,
1222 IN CONST UINTN Mask,
1223 IN UINTN *MatchingHandleCount,
1224 OUT EFI_HANDLE **MatchingHandleBuffer OPTIONAL
1225 )
1226 {
1227 EFI_STATUS Status;
1228 UINTN HandleCount;
1229 EFI_HANDLE *HandleBuffer;
1230 UINTN *HandleType;
1231 UINTN HandleIndex;
1232
1233 ASSERT(MatchingHandleCount != NULL);
1234 ASSERT(DriverBindingHandle != NULL || ControllerHandle != NULL);
1235
1236 if ((Mask & HR_VALID_MASK) != Mask) {
1237 return (EFI_INVALID_PARAMETER);
1238 }
1239
1240 if ((Mask & HR_CHILD_HANDLE) != 0 && DriverBindingHandle == NULL) {
1241 return (EFI_INVALID_PARAMETER);
1242 }
1243
1244 *MatchingHandleCount = 0;
1245 if (MatchingHandleBuffer != NULL) {
1246 *MatchingHandleBuffer = NULL;
1247 }
1248
1249 HandleBuffer = NULL;
1250 HandleType = NULL;
1251
1252 Status = ParseHandleDatabaseByRelationshipWithType (
1253 DriverBindingHandle,
1254 ControllerHandle,
1255 &HandleCount,
1256 &HandleBuffer,
1257 &HandleType
1258 );
1259 if (!EFI_ERROR (Status)) {
1260 //
1261 // Count the number of handles that match the attributes in Mask
1262 //
1263 for (HandleIndex = 0; HandleIndex < HandleCount; HandleIndex++) {
1264 if ((HandleType[HandleIndex] & Mask) == Mask) {
1265 (*MatchingHandleCount)++;
1266 }
1267 }
1268 //
1269 // If no handles match the attributes in Mask then return EFI_NOT_FOUND
1270 //
1271 if (*MatchingHandleCount == 0) {
1272 Status = EFI_NOT_FOUND;
1273 } else {
1274
1275 if (MatchingHandleBuffer == NULL) {
1276 //
1277 // Someone just wanted the count...
1278 //
1279 Status = EFI_SUCCESS;
1280 } else {
1281 //
1282 // Allocate a handle buffer for the number of handles that matched the attributes in Mask
1283 //
1284 *MatchingHandleBuffer = AllocateZeroPool ((*MatchingHandleCount +1)* sizeof (EFI_HANDLE));
1285 ASSERT(*MatchingHandleBuffer != NULL);
1286
1287 for (HandleIndex = 0,*MatchingHandleCount = 0
1288 ; HandleIndex < HandleCount
1289 ; HandleIndex++
1290 ){
1291 //
1292 // Fill the allocated buffer with the handles that matched the attributes in Mask
1293 //
1294 if ((HandleType[HandleIndex] & Mask) == Mask) {
1295 (*MatchingHandleBuffer)[(*MatchingHandleCount)++] = HandleBuffer[HandleIndex];
1296 }
1297 }
1298
1299 //
1300 // Make the last one NULL
1301 //
1302 (*MatchingHandleBuffer)[*MatchingHandleCount] = NULL;
1303
1304 Status = EFI_SUCCESS;
1305 } // MacthingHandleBuffer == NULL (ELSE)
1306 } // *MatchingHandleCount == 0 (ELSE)
1307 } // no error on ParseHandleDatabaseByRelationshipWithType
1308
1309 if (HandleBuffer != NULL) {
1310 FreePool (HandleBuffer);
1311 }
1312
1313 if (HandleType != NULL) {
1314 FreePool (HandleType);
1315 }
1316
1317 return Status;
1318 }
1319
1320 /**
1321 Gets handles for any child controllers of the passed in controller.
1322
1323 @param[in] ControllerHandle The handle of the "parent controller"
1324 @param[in] MatchingHandleCount Pointer to the number of handles in
1325 MatchingHandleBuffer on return.
1326 @param[out] MatchingHandleBuffer Buffer containing handles on a successful
1327 return.
1328
1329
1330 @retval EFI_SUCCESS The operation was sucessful.
1331 **/
1332 EFI_STATUS
1333 EFIAPI
1334 ParseHandleDatabaseForChildControllers(
1335 IN CONST EFI_HANDLE ControllerHandle,
1336 IN UINTN *MatchingHandleCount,
1337 OUT EFI_HANDLE **MatchingHandleBuffer OPTIONAL
1338 )
1339 {
1340 EFI_STATUS Status;
1341 // UINTN HandleIndex;
1342 UINTN DriverBindingHandleCount;
1343 EFI_HANDLE *DriverBindingHandleBuffer;
1344 UINTN DriverBindingHandleIndex;
1345 UINTN ChildControllerHandleCount;
1346 EFI_HANDLE *ChildControllerHandleBuffer;
1347 UINTN ChildControllerHandleIndex;
1348 // BOOLEAN Found;
1349 EFI_HANDLE *HandleBufferForReturn;
1350
1351 if (MatchingHandleCount == NULL) {
1352 return (EFI_INVALID_PARAMETER);
1353 }
1354 *MatchingHandleCount = 0;
1355
1356 Status = PARSE_HANDLE_DATABASE_UEFI_DRIVERS (
1357 ControllerHandle,
1358 &DriverBindingHandleCount,
1359 &DriverBindingHandleBuffer
1360 );
1361 if (EFI_ERROR (Status)) {
1362 return Status;
1363 }
1364
1365 //
1366 // Get a buffer big enough for all the controllers.
1367 //
1368 HandleBufferForReturn = GetHandleListByProtocol(&gEfiDevicePathProtocolGuid);
1369 if (HandleBufferForReturn == NULL) {
1370 FreePool (DriverBindingHandleBuffer);
1371 return (EFI_NOT_FOUND);
1372 }
1373
1374 for (DriverBindingHandleIndex = 0; DriverBindingHandleIndex < DriverBindingHandleCount; DriverBindingHandleIndex++) {
1375 Status = PARSE_HANDLE_DATABASE_MANAGED_CHILDREN (
1376 DriverBindingHandleBuffer[DriverBindingHandleIndex],
1377 ControllerHandle,
1378 &ChildControllerHandleCount,
1379 &ChildControllerHandleBuffer
1380 );
1381 if (EFI_ERROR (Status)) {
1382 continue;
1383 }
1384
1385 for (ChildControllerHandleIndex = 0;
1386 ChildControllerHandleIndex < ChildControllerHandleCount;
1387 ChildControllerHandleIndex++
1388 ) {
1389 // Found = FALSE;
1390 HandleBufferForReturn[(*MatchingHandleCount)++] = ChildControllerHandleBuffer[ChildControllerHandleIndex];
1391 // for (HandleIndex = 0; HandleBufferForReturn[HandleIndex] != NULL; HandleIndex++) {
1392 // if (HandleBufferForReturn[HandleIndex] == ChildControllerHandleBuffer[ChildControllerHandleIndex]) {
1393 // Found = TRUE;
1394 // break;
1395 // }
1396 // }
1397
1398 // if (Found) {
1399 // HandleBufferForReturn[(*MatchingHandleCount)++] = ChildControllerHandleBuffer[ChildControllerHandleIndex];
1400 // }
1401 }
1402
1403 FreePool (ChildControllerHandleBuffer);
1404 }
1405
1406 FreePool (DriverBindingHandleBuffer);
1407
1408 if (MatchingHandleBuffer != NULL) {
1409 *MatchingHandleBuffer = HandleBufferForReturn;
1410 } else {
1411 FreePool(HandleBufferForReturn);
1412 }
1413
1414 return (EFI_SUCCESS);
1415 }
1416
1417 /**
1418 Appends 1 buffer to another buffer. This will re-allocate the destination buffer
1419 if necessary to fit all of the data.
1420
1421 If DestinationBuffer is NULL, then ASSERT().
1422
1423 @param[in, out] DestinationBuffer The pointer to the pointer to the buffer to append onto.
1424 @param[in, out] DestinationSize The pointer to the size of DestinationBuffer.
1425 @param[in] SourceBuffer The pointer to the buffer to append onto DestinationBuffer.
1426 @param[in] SourceSize The number of bytes of SourceBuffer to append.
1427
1428 @retval NULL A memory allocation failed.
1429 @retval NULL A parameter was invalid.
1430 @return A pointer to (*DestinationBuffer).
1431 **/
1432 VOID*
1433 EFIAPI
1434 BuffernCatGrow (
1435 IN OUT VOID **DestinationBuffer,
1436 IN OUT UINTN *DestinationSize,
1437 IN VOID *SourceBuffer,
1438 IN UINTN SourceSize
1439 )
1440 {
1441 UINTN LocalDestinationSize;
1442 UINTN LocalDestinationFinalSize;
1443
1444 ASSERT(DestinationBuffer != NULL);
1445
1446 if (SourceSize == 0 || SourceBuffer == NULL) {
1447 return (*DestinationBuffer);
1448 }
1449
1450 if (DestinationSize == NULL) {
1451 LocalDestinationSize = 0;
1452 } else {
1453 LocalDestinationSize = *DestinationSize;
1454 }
1455
1456 LocalDestinationFinalSize = LocalDestinationSize + SourceSize;
1457
1458 if (DestinationSize != NULL) {
1459 *DestinationSize = LocalDestinationSize;
1460 }
1461
1462 if (LocalDestinationSize == 0) {
1463 // allcoate
1464 *DestinationBuffer = AllocateZeroPool(LocalDestinationFinalSize);
1465 } else {
1466 // reallocate
1467 *DestinationBuffer = ReallocatePool(LocalDestinationSize, LocalDestinationFinalSize, *DestinationBuffer);
1468 }
1469
1470 ASSERT(*DestinationBuffer != NULL);
1471
1472 // copy
1473 return (CopyMem(((UINT8*)(*DestinationBuffer)) + LocalDestinationSize, SourceBuffer, SourceSize));
1474 }
1475
1476 /**
1477 Gets handles for any child devices produced by the passed in driver.
1478
1479 @param[in] DriverHandle The handle of the driver.
1480 @param[in] MatchingHandleCount Pointer to the number of handles in
1481 MatchingHandleBuffer on return.
1482 @param[out] MatchingHandleBuffer Buffer containing handles on a successful
1483 return.
1484 @retval EFI_SUCCESS The operation was sucessful.
1485 @sa ParseHandleDatabaseByRelationship
1486 **/
1487 EFI_STATUS
1488 EFIAPI
1489 ParseHandleDatabaseForChildDevices(
1490 IN CONST EFI_HANDLE DriverHandle,
1491 IN UINTN *MatchingHandleCount,
1492 OUT EFI_HANDLE **MatchingHandleBuffer OPTIONAL
1493 )
1494 {
1495 EFI_HANDLE *Buffer;
1496 EFI_HANDLE *Buffer2;
1497 UINTN Count1;
1498 UINTN Count2;
1499 UINTN HandleIndex;
1500 EFI_STATUS Status;
1501 UINTN HandleBufferSize;
1502
1503 ASSERT(MatchingHandleCount != NULL);
1504
1505 HandleBufferSize = 0;
1506 Buffer = NULL;
1507 Buffer2 = NULL;
1508 *MatchingHandleCount = 0;
1509
1510 Status = PARSE_HANDLE_DATABASE_DEVICES (
1511 DriverHandle,
1512 &Count1,
1513 &Buffer
1514 );
1515 if (!EFI_ERROR (Status)) {
1516 for (HandleIndex = 0; HandleIndex < Count1; HandleIndex++) {
1517 //
1518 // now find the children
1519 //
1520 Status = PARSE_HANDLE_DATABASE_MANAGED_CHILDREN (
1521 DriverHandle,
1522 Buffer[HandleIndex],
1523 &Count2,
1524 &Buffer2
1525 );
1526 if (EFI_ERROR(Status)) {
1527 break;
1528 }
1529 //
1530 // save out required and optional data elements
1531 //
1532 *MatchingHandleCount += Count2;
1533 if (MatchingHandleBuffer != NULL) {
1534 *MatchingHandleBuffer = BuffernCatGrow((VOID**)MatchingHandleBuffer, &HandleBufferSize, Buffer2, Count2 * sizeof(Buffer2[0]));
1535 }
1536
1537 //
1538 // free the memory
1539 //
1540 if (Buffer2 != NULL) {
1541 FreePool(Buffer2);
1542 }
1543 }
1544 }
1545
1546 if (Buffer != NULL) {
1547 FreePool(Buffer);
1548 }
1549 return (Status);
1550 }
1551
1552 /**
1553 Function to get all handles that support a given protocol or all handles.
1554
1555 @param[in] ProtocolGuid The guid of the protocol to get handles for. If NULL
1556 then the function will return all handles.
1557
1558 @retval NULL A memory allocation failed.
1559 @return A NULL terminated list of handles.
1560 **/
1561 EFI_HANDLE*
1562 EFIAPI
1563 GetHandleListByProtocol (
1564 IN CONST EFI_GUID *ProtocolGuid OPTIONAL
1565 )
1566 {
1567 EFI_HANDLE *HandleList;
1568 UINTN Size;
1569 EFI_STATUS Status;
1570
1571 Size = 0;
1572 HandleList = NULL;
1573
1574 //
1575 // We cannot use LocateHandleBuffer since we need that NULL item on the ends of the list!
1576 //
1577 if (ProtocolGuid == NULL) {
1578 Status = gBS->LocateHandle(AllHandles, NULL, NULL, &Size, HandleList);
1579 if (Status == EFI_BUFFER_TOO_SMALL) {
1580 HandleList = AllocateZeroPool(Size + sizeof(EFI_HANDLE));
1581 if (HandleList == NULL) {
1582 return (NULL);
1583 }
1584 Status = gBS->LocateHandle(AllHandles, NULL, NULL, &Size, HandleList);
1585 HandleList[Size/sizeof(EFI_HANDLE)] = NULL;
1586 }
1587 } else {
1588 Status = gBS->LocateHandle(ByProtocol, (EFI_GUID*)ProtocolGuid, NULL, &Size, HandleList);
1589 if (Status == EFI_BUFFER_TOO_SMALL) {
1590 HandleList = AllocateZeroPool(Size + sizeof(EFI_HANDLE));
1591 if (HandleList == NULL) {
1592 return (NULL);
1593 }
1594 Status = gBS->LocateHandle(ByProtocol, (EFI_GUID*)ProtocolGuid, NULL, &Size, HandleList);
1595 HandleList[Size/sizeof(EFI_HANDLE)] = NULL;
1596 }
1597 }
1598 if (EFI_ERROR(Status)) {
1599 if (HandleList != NULL) {
1600 FreePool(HandleList);
1601 }
1602 return (NULL);
1603 }
1604 return (HandleList);
1605 }
1606
1607 /**
1608 Function to get all handles that support some protocols.
1609
1610 @param[in] ProtocolGuids A NULL terminated list of protocol GUIDs.
1611
1612 @retval NULL A memory allocation failed.
1613 @retval NULL ProtocolGuids was NULL.
1614 @return A NULL terminated list of EFI_HANDLEs.
1615 **/
1616 EFI_HANDLE*
1617 EFIAPI
1618 GetHandleListByProtocolList (
1619 IN CONST EFI_GUID **ProtocolGuids
1620 )
1621 {
1622 EFI_HANDLE *HandleList;
1623 UINTN Size;
1624 UINTN TotalSize;
1625 UINTN TempSize;
1626 EFI_STATUS Status;
1627 CONST EFI_GUID **GuidWalker;
1628 EFI_HANDLE *HandleWalker1;
1629 EFI_HANDLE *HandleWalker2;
1630
1631 Size = 0;
1632 HandleList = NULL;
1633 TotalSize = sizeof(EFI_HANDLE);
1634
1635 for (GuidWalker = ProtocolGuids ; GuidWalker != NULL && *GuidWalker != NULL ; GuidWalker++,Size = 0){
1636 Status = gBS->LocateHandle(ByProtocol, (EFI_GUID*)(*GuidWalker), NULL, &Size, NULL);
1637 if (Status == EFI_BUFFER_TOO_SMALL) {
1638 TotalSize += Size;
1639 }
1640 }
1641
1642 //
1643 // No handles were found...
1644 //
1645 if (TotalSize == sizeof(EFI_HANDLE)) {
1646 return (NULL);
1647 }
1648
1649 HandleList = AllocateZeroPool(TotalSize);
1650 if (HandleList == NULL) {
1651 return (NULL);
1652 }
1653
1654 Size = 0;
1655 for (GuidWalker = ProtocolGuids ; GuidWalker != NULL && *GuidWalker != NULL ; GuidWalker++){
1656 TempSize = TotalSize - Size;
1657 Status = gBS->LocateHandle(ByProtocol, (EFI_GUID*)(*GuidWalker), NULL, &TempSize, HandleList+(Size/sizeof(EFI_HANDLE)));
1658
1659 //
1660 // Allow for missing protocols... Only update the 'used' size upon success.
1661 //
1662 if (!EFI_ERROR(Status)) {
1663 Size += TempSize;
1664 }
1665 }
1666 ASSERT(HandleList[(TotalSize/sizeof(EFI_HANDLE))-1] == NULL);
1667
1668 for (HandleWalker1 = HandleList ; HandleWalker1 != NULL && *HandleWalker1 != NULL ; HandleWalker1++) {
1669 for (HandleWalker2 = HandleWalker1 + 1; HandleWalker2 != NULL && *HandleWalker2 != NULL ; HandleWalker2++) {
1670 if (*HandleWalker1 == *HandleWalker2) {
1671 //
1672 // copy memory back 1 handle width.
1673 //
1674 CopyMem(HandleWalker2, HandleWalker2 + 1, TotalSize - ((HandleWalker2-HandleList+1)*sizeof(EFI_HANDLE)));
1675 }
1676 }
1677 }
1678
1679 return (HandleList);
1680 }
1681
1682
1683
1684
1685
1686
1687
1688
1689
1690