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