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