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