1 /** @file
2   Main file for Dh shell Driver1 function.
3 
4   (C) Copyright 2014-2015 Hewlett-Packard Development Company, L.P.<BR>
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 "UefiShellDriver1CommandsLib.h"
17 
18 STATIC CONST SHELL_PARAM_ITEM ParamList[] = {
19   {L"-p", TypeValue},
20   {L"-d", TypeFlag},
21   {L"-v", TypeFlag},
22   {L"-verbose", TypeFlag},
23   {L"-sfo", TypeFlag},
24   {L"-l", TypeValue},
25   {NULL, TypeMax}
26   };
27 
28 STATIC CONST EFI_GUID *UefiDriverModelProtocolsGuidArray[] = {
29   &gEfiDriverBindingProtocolGuid,
30   &gEfiPlatformDriverOverrideProtocolGuid,
31   &gEfiBusSpecificDriverOverrideProtocolGuid,
32   &gEfiDriverDiagnosticsProtocolGuid,
33   &gEfiDriverDiagnostics2ProtocolGuid,
34   &gEfiComponentNameProtocolGuid,
35   &gEfiComponentName2ProtocolGuid,
36   &gEfiPlatformToDriverConfigurationProtocolGuid,
37   &gEfiDriverSupportedEfiVersionProtocolGuid,
38   &gEfiDriverFamilyOverrideProtocolGuid,
39   &gEfiDriverHealthProtocolGuid,
40   &gEfiLoadedImageProtocolGuid,
41   NULL
42 };
43 
44 /**
45   Get the name of a driver by it's handle.
46 
47   If a name is found the memory must be callee freed.
48 
49   @param[in] TheHandle    The driver's handle.
50   @param[in] Language     The language to use.
51   @param[in] NameFound    Upon a successful return the name found.
52 
53   @retval EFI_SUCCESS     The name was found.
54 **/
55 EFI_STATUS
GetDriverName(IN EFI_HANDLE TheHandle,IN CONST CHAR8 * Language,IN CHAR16 ** NameFound)56 GetDriverName (
57   IN EFI_HANDLE   TheHandle,
58   IN CONST CHAR8  *Language,
59   IN CHAR16       **NameFound
60   )
61 {
62   CHAR8                             *Lang;
63   EFI_STATUS                        Status;
64   EFI_COMPONENT_NAME2_PROTOCOL      *CompName2;
65   CHAR16                            *NameToReturn;
66   //
67   // Go through those handles until we get one that passes for GetComponentName
68   //
69   Status = gBS->OpenProtocol(
70     TheHandle,
71     &gEfiComponentName2ProtocolGuid,
72     (VOID**)&CompName2,
73     gImageHandle,
74     NULL,
75     EFI_OPEN_PROTOCOL_GET_PROTOCOL);
76   if (EFI_ERROR(Status)) {
77     Status = gBS->OpenProtocol(
78       TheHandle,
79       &gEfiComponentNameProtocolGuid,
80       (VOID**)&CompName2,
81       gImageHandle,
82       NULL,
83       EFI_OPEN_PROTOCOL_GET_PROTOCOL);
84   }
85 
86   if (EFI_ERROR(Status)) {
87     return (EFI_NOT_FOUND);
88   }
89   Lang = GetBestLanguageForDriver (CompName2->SupportedLanguages, Language, FALSE);
90   Status = CompName2->GetDriverName(CompName2, Lang, &NameToReturn);
91   FreePool(Lang);
92 
93   if (!EFI_ERROR(Status) && NameToReturn != NULL) {
94     *NameFound = NULL;
95     StrnCatGrow(NameFound, NULL, NameToReturn, 0);
96   }
97   return (Status);
98 }
99 
100 /**
101   Discover if a protocol guid is one of the UEFI Driver Model Protocols.
102 
103   @param[in] Guid   The guid to test.
104 
105   @retval TRUE      The guid does represent a driver model protocol.
106   @retval FALSE     The guid does not represent a driver model protocol.
107 **/
108 BOOLEAN
IsDriverProt(IN CONST EFI_GUID * Guid)109 IsDriverProt (
110   IN CONST EFI_GUID *Guid
111   )
112 {
113   CONST EFI_GUID            **GuidWalker;
114   BOOLEAN                   GuidFound;
115   GuidFound = FALSE;
116   for (GuidWalker = UefiDriverModelProtocolsGuidArray
117     ;  GuidWalker != NULL && *GuidWalker != NULL
118     ;  GuidWalker++
119    ){
120     if (CompareGuid(*GuidWalker, Guid)) {
121       GuidFound = TRUE;
122       break;
123     }
124   }
125   return (GuidFound);
126 }
127 
128 /**
129   Get information for a handle.
130 
131   @param[in] TheHandle        The handles to show info on.
132   @param[in] Language         Language string per UEFI specification.
133   @param[in] Separator        Separator string between information blocks.
134   @param[in] Verbose          TRUE for extra info, FALSE otherwise.
135   @param[in] ExtraInfo        TRUE for extra info, FALSE otherwise.
136 
137   @retval SHELL_SUCCESS           The operation was successful.
138   @retval SHELL_INVALID_PARAMETER ProtocolName was NULL or invalid.
139 **/
140 CHAR16*
GetProtocolInfoString(IN CONST EFI_HANDLE TheHandle,IN CONST CHAR8 * Language,IN CONST CHAR16 * Separator,IN CONST BOOLEAN Verbose,IN CONST BOOLEAN ExtraInfo)141 GetProtocolInfoString(
142   IN CONST EFI_HANDLE TheHandle,
143   IN CONST CHAR8      *Language,
144   IN CONST CHAR16     *Separator,
145   IN CONST BOOLEAN    Verbose,
146   IN CONST BOOLEAN    ExtraInfo
147   )
148 {
149   EFI_GUID                  **ProtocolGuidArray;
150   UINTN                     ArrayCount;
151   UINTN                     ProtocolIndex;
152   EFI_STATUS                Status;
153   CHAR16                    *RetVal;
154   UINTN                     Size;
155   CHAR16                    *Temp;
156 
157   ProtocolGuidArray = NULL;
158   RetVal            = NULL;
159   Size              = 0;
160 
161   Status = gBS->ProtocolsPerHandle (
162                 TheHandle,
163                 &ProtocolGuidArray,
164                 &ArrayCount
165                );
166   if (!EFI_ERROR (Status)) {
167     for (ProtocolIndex = 0; ProtocolIndex < ArrayCount; ProtocolIndex++) {
168       Temp = GetStringNameFromGuid(ProtocolGuidArray[ProtocolIndex], Language);
169       if (Temp != NULL) {
170         ASSERT((RetVal == NULL && Size == 0) || (RetVal != NULL));
171         if (Size != 0) {
172           StrnCatGrow(&RetVal, &Size, Separator, 0);
173         }
174         StrnCatGrow(&RetVal, &Size, L"%H", 0);
175         StrnCatGrow(&RetVal, &Size, Temp, 0);
176         StrnCatGrow(&RetVal, &Size, L"%N", 0);
177         FreePool(Temp);
178       }
179       if (ExtraInfo) {
180         Temp = GetProtocolInformationDump(TheHandle, ProtocolGuidArray[ProtocolIndex], Verbose);
181         if (Temp != NULL) {
182           ASSERT((RetVal == NULL && Size == 0) || (RetVal != NULL));
183           if (!Verbose) {
184             StrnCatGrow(&RetVal, &Size, L"(", 0);
185             StrnCatGrow(&RetVal, &Size, Temp, 0);
186             StrnCatGrow(&RetVal, &Size, L")\r\n", 0);
187           } else {
188             StrnCatGrow(&RetVal, &Size, Separator, 0);
189             StrnCatGrow(&RetVal, &Size, Temp, 0);
190           }
191           FreePool(Temp);
192         }
193       }
194     }
195   }
196 
197   SHELL_FREE_NON_NULL(ProtocolGuidArray);
198 
199   if (RetVal == NULL) {
200     return (NULL);
201   }
202 
203   ASSERT((RetVal == NULL && Size == 0) || (RetVal != NULL));
204   StrnCatGrow(&RetVal, &Size, Separator, 0);
205   return (RetVal);
206 }
207 
208 /**
209   Gets the name of the loaded image.
210 
211   @param[in] TheHandle    The handle of the driver to get info on.
212   @param[out] Name        The pointer to the pointer.  Valid upon a successful return.
213 
214   @retval EFI_SUCCESS     The operation was successful.
215 **/
216 EFI_STATUS
GetDriverImageName(IN EFI_HANDLE TheHandle,OUT CHAR16 ** Name)217 GetDriverImageName (
218   IN EFI_HANDLE   TheHandle,
219   OUT CHAR16      **Name
220   )
221 {
222   // get loaded image and devicepathtotext on image->Filepath
223   EFI_LOADED_IMAGE_PROTOCOL *LoadedImage;
224   EFI_STATUS                Status;
225   EFI_DEVICE_PATH_PROTOCOL  *DevicePath;
226 
227   if (TheHandle == NULL || Name == NULL) {
228     return (EFI_INVALID_PARAMETER);
229   }
230 
231   Status = gBS->OpenProtocol (
232                 TheHandle,
233                 &gEfiLoadedImageProtocolGuid,
234                 (VOID **) &LoadedImage,
235                 gImageHandle,
236                 NULL,
237                 EFI_OPEN_PROTOCOL_GET_PROTOCOL
238                );
239   if (EFI_ERROR(Status)) {
240     return (Status);
241   }
242   DevicePath = LoadedImage->FilePath;
243   *Name = ConvertDevicePathToText(DevicePath, TRUE, TRUE);
244   return (EFI_SUCCESS);
245 }
246 
247 /**
248   Display driver model information for a given handle.
249 
250   @param[in] Handle     The handle to display info on.
251   @param[in] BestName   Use the best name?
252   @param[in] Language   The language to output in.
253 **/
254 EFI_STATUS
DisplayDriverModelHandle(IN EFI_HANDLE Handle,IN BOOLEAN BestName,IN CONST CHAR8 * Language OPTIONAL)255 DisplayDriverModelHandle (
256   IN EFI_HANDLE  Handle,
257   IN BOOLEAN     BestName,
258   IN CONST CHAR8 *Language OPTIONAL
259   )
260 {
261   EFI_STATUS                  Status;
262   BOOLEAN                     ConfigurationStatus;
263   BOOLEAN                     DiagnosticsStatus;
264   UINTN                       DriverBindingHandleCount;
265   EFI_HANDLE                  *DriverBindingHandleBuffer;
266   UINTN                       ParentControllerHandleCount;
267   EFI_HANDLE                  *ParentControllerHandleBuffer;
268   UINTN                       ChildControllerHandleCount;
269   EFI_HANDLE                  *ChildControllerHandleBuffer;
270   CHAR16                      *TempStringPointer;
271   EFI_DEVICE_PATH_PROTOCOL    *DevicePath;
272   UINTN                       Index;
273   CHAR16                      *DriverName;
274   EFI_DRIVER_BINDING_PROTOCOL *DriverBinding;
275   UINTN                       NumberOfChildren;
276   UINTN                       HandleIndex;
277   UINTN                       ControllerHandleCount;
278   EFI_HANDLE                  *ControllerHandleBuffer;
279   UINTN                       ChildIndex;
280   BOOLEAN                     Image;
281 
282   DriverName = NULL;
283 
284   //
285   // See if Handle is a device handle and display its details.
286   //
287   DriverBindingHandleBuffer = NULL;
288   Status = PARSE_HANDLE_DATABASE_UEFI_DRIVERS (
289             Handle,
290             &DriverBindingHandleCount,
291             &DriverBindingHandleBuffer
292             );
293 
294   ParentControllerHandleBuffer = NULL;
295   Status = PARSE_HANDLE_DATABASE_PARENTS (
296             Handle,
297             &ParentControllerHandleCount,
298             &ParentControllerHandleBuffer
299             );
300 
301   ChildControllerHandleBuffer = NULL;
302   Status = ParseHandleDatabaseForChildControllers (
303             Handle,
304             &ChildControllerHandleCount,
305             &ChildControllerHandleBuffer
306             );
307 
308   DiagnosticsStatus = FALSE;
309   ConfigurationStatus = FALSE;
310 
311   if (!EFI_ERROR(gBS->OpenProtocol(Handle, &gEfiDriverConfigurationProtocolGuid, NULL, NULL, gImageHandle, EFI_OPEN_PROTOCOL_TEST_PROTOCOL))) {
312     ConfigurationStatus = TRUE;
313   }
314   if (!EFI_ERROR(gBS->OpenProtocol(Handle, &gEfiDriverConfiguration2ProtocolGuid, NULL, NULL, gImageHandle, EFI_OPEN_PROTOCOL_TEST_PROTOCOL))) {
315     ConfigurationStatus = TRUE;
316   }
317   if (!EFI_ERROR(gBS->OpenProtocol(Handle, &gEfiDriverDiagnosticsProtocolGuid, NULL, NULL, gImageHandle, EFI_OPEN_PROTOCOL_TEST_PROTOCOL))) {
318     DiagnosticsStatus = TRUE;
319   }
320   if (!EFI_ERROR(gBS->OpenProtocol(Handle, &gEfiDriverDiagnostics2ProtocolGuid, NULL, NULL, gImageHandle, EFI_OPEN_PROTOCOL_TEST_PROTOCOL))) {
321     DiagnosticsStatus = TRUE;
322   }
323 
324   Status = EFI_SUCCESS;
325 
326   if (DriverBindingHandleCount > 0 || ParentControllerHandleCount > 0 || ChildControllerHandleCount > 0) {
327 
328 
329 
330     DevicePath          = NULL;
331     TempStringPointer   = NULL;
332     Status              = gBS->HandleProtocol (Handle, &gEfiDevicePathProtocolGuid, (VOID**)&DevicePath);
333 
334     Status = gEfiShellProtocol->GetDeviceName(Handle, EFI_DEVICE_NAME_USE_COMPONENT_NAME|EFI_DEVICE_NAME_USE_DEVICE_PATH, (CHAR8*)Language, &TempStringPointer);
335     ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_DH_OUTPUT_DRIVER1), gShellDriver1HiiHandle, TempStringPointer!=NULL?TempStringPointer:L"<Unknown>");
336     SHELL_FREE_NON_NULL(TempStringPointer);
337 
338     TempStringPointer = ConvertDevicePathToText(DevicePath, TRUE, FALSE);
339     ShellPrintHiiEx(
340       -1,
341       -1,
342       NULL,
343       STRING_TOKEN (STR_DH_OUTPUT_DRIVER2),
344       gShellDriver1HiiHandle,
345       TempStringPointer!=NULL?TempStringPointer:L"<None>",
346       ParentControllerHandleCount == 0?L"ROOT":(ChildControllerHandleCount > 0)?L"BUS":L"DEVICE",
347       ConfigurationStatus?L"YES":L"NO",
348       DiagnosticsStatus?L"YES":L"NO"
349       );
350 
351     SHELL_FREE_NON_NULL(TempStringPointer);
352 
353     if (DriverBindingHandleCount == 0) {
354       ShellPrintHiiEx(
355         -1,
356         -1,
357         NULL,
358         STRING_TOKEN (STR_DH_OUTPUT_DRIVER3),
359         gShellDriver1HiiHandle,
360         L"<None>"
361         );
362     } else {
363       ShellPrintHiiEx(
364         -1,
365         -1,
366         NULL,
367         STRING_TOKEN (STR_DH_OUTPUT_DRIVER3),
368         gShellDriver1HiiHandle,
369         L""
370         );
371       for (Index = 0; Index < DriverBindingHandleCount; Index++) {
372         Image = FALSE;
373         Status = GetDriverName (
374                   DriverBindingHandleBuffer[Index],
375                   Language,
376                   &DriverName
377                   );
378         if (EFI_ERROR (Status)) {
379           Status = GetDriverImageName (
380                     DriverBindingHandleBuffer[Index],
381                     &DriverName
382                     );
383           if (EFI_ERROR (Status)) {
384             DriverName = NULL;
385           }
386         }
387 
388         if (Image) {
389           ShellPrintHiiEx(
390             -1,
391             -1,
392             NULL,
393             STRING_TOKEN (STR_DH_OUTPUT_DRIVER4A),
394             gShellDriver1HiiHandle,
395             ConvertHandleToHandleIndex (DriverBindingHandleBuffer[Index]),
396             DriverName!=NULL?DriverName:L"<Unknown>"
397             );
398         } else {
399           ShellPrintHiiEx(
400             -1,
401             -1,
402             NULL,
403             STRING_TOKEN (STR_DH_OUTPUT_DRIVER4B),
404             gShellDriver1HiiHandle,
405             ConvertHandleToHandleIndex (DriverBindingHandleBuffer[Index]),
406             DriverName!=NULL?DriverName:L"<Unknown>"
407             );
408         }
409         SHELL_FREE_NON_NULL(DriverName);
410       }
411     }
412 
413     if (ParentControllerHandleCount == 0) {
414       ShellPrintHiiEx(
415         -1,
416         -1,
417         NULL,
418         STRING_TOKEN (STR_DH_OUTPUT_DRIVER5),
419         gShellDriver1HiiHandle,
420         L"<None>"
421         );
422     } else {
423       ShellPrintHiiEx(
424         -1,
425         -1,
426         NULL,
427         STRING_TOKEN (STR_DH_OUTPUT_DRIVER5),
428         gShellDriver1HiiHandle,
429         L""
430         );
431       for (Index = 0; Index < ParentControllerHandleCount; Index++) {
432         Status = gEfiShellProtocol->GetDeviceName(ParentControllerHandleBuffer[Index], EFI_DEVICE_NAME_USE_COMPONENT_NAME|EFI_DEVICE_NAME_USE_DEVICE_PATH, (CHAR8*)Language, &TempStringPointer);
433         ShellPrintHiiEx(
434           -1,
435           -1,
436           NULL,
437           STRING_TOKEN (STR_DH_OUTPUT_DRIVER5B),
438           gShellDriver1HiiHandle,
439           ConvertHandleToHandleIndex (ParentControllerHandleBuffer[Index]),
440           TempStringPointer!=NULL?TempStringPointer:L"<Unknown>"
441           );
442         SHELL_FREE_NON_NULL(TempStringPointer);
443       }
444     }
445 
446     if (ChildControllerHandleCount == 0) {
447       ShellPrintHiiEx(
448         -1,
449         -1,
450         NULL,
451         STRING_TOKEN (STR_DH_OUTPUT_DRIVER6),
452         gShellDriver1HiiHandle,
453         L"<None>"
454         );
455     } else {
456       ShellPrintHiiEx(
457         -1,
458         -1,
459         NULL,
460         STRING_TOKEN (STR_DH_OUTPUT_DRIVER6),
461         gShellDriver1HiiHandle,
462         L""
463         );
464       for (Index = 0; Index < ChildControllerHandleCount; Index++) {
465         Status = gEfiShellProtocol->GetDeviceName(ChildControllerHandleBuffer[Index], EFI_DEVICE_NAME_USE_COMPONENT_NAME|EFI_DEVICE_NAME_USE_DEVICE_PATH, (CHAR8*)Language, &TempStringPointer);
466         ShellPrintHiiEx(
467           -1,
468           -1,
469           NULL,
470           STRING_TOKEN (STR_DH_OUTPUT_DRIVER6B),
471           gShellDriver1HiiHandle,
472           ConvertHandleToHandleIndex (ChildControllerHandleBuffer[Index]),
473           TempStringPointer!=NULL?TempStringPointer:L"<Unknown>"
474           );
475         SHELL_FREE_NON_NULL(TempStringPointer);
476       }
477     }
478   }
479 
480   SHELL_FREE_NON_NULL(DriverBindingHandleBuffer);
481 
482   SHELL_FREE_NON_NULL(ParentControllerHandleBuffer);
483 
484   SHELL_FREE_NON_NULL(ChildControllerHandleBuffer);
485 
486   if (EFI_ERROR (Status)) {
487     return Status;
488   }
489   //
490   // See if Handle is a driver binding handle and display its details.
491   //
492   Status = gBS->OpenProtocol (
493                 Handle,
494                 &gEfiDriverBindingProtocolGuid,
495                 (VOID **) &DriverBinding,
496                 NULL,
497                 NULL,
498                 EFI_OPEN_PROTOCOL_GET_PROTOCOL
499                 );
500   if (EFI_ERROR (Status)) {
501     return EFI_SUCCESS;
502   }
503 
504   NumberOfChildren        = 0;
505   ControllerHandleBuffer  = NULL;
506   Status = PARSE_HANDLE_DATABASE_DEVICES (
507             Handle,
508             &ControllerHandleCount,
509             &ControllerHandleBuffer
510             );
511   if (ControllerHandleCount > 0) {
512     for (HandleIndex = 0; HandleIndex < ControllerHandleCount; HandleIndex++) {
513       Status = PARSE_HANDLE_DATABASE_MANAGED_CHILDREN (
514                 Handle,
515                 ControllerHandleBuffer[HandleIndex],
516                 &ChildControllerHandleCount,
517                 NULL
518                 );
519       NumberOfChildren += ChildControllerHandleCount;
520     }
521   }
522 
523   Status = GetDriverName (Handle, Language, &DriverName);
524   if (EFI_ERROR (Status)) {
525     DriverName = NULL;
526   }
527 
528   ShellPrintHiiEx(
529     -1,
530     -1,
531     NULL,
532     STRING_TOKEN (STR_DH_OUTPUT_DRIVER6B),
533     gShellDriver1HiiHandle,
534     ConvertHandleToHandleIndex(Handle),
535     DriverName!=NULL?DriverName:L"<Unknown>"
536     );
537   SHELL_FREE_NON_NULL(DriverName);
538   Status = GetDriverImageName (
539             Handle,
540             &DriverName
541             );
542   if (EFI_ERROR (Status)) {
543     DriverName = NULL;
544   }
545   ShellPrintHiiEx(
546     -1,
547     -1,
548     NULL,
549     STRING_TOKEN (STR_DH_OUTPUT_DRIVER7B),
550     gShellDriver1HiiHandle,
551     DriverName!=NULL?DriverName:L"<Unknown>"
552     );
553   SHELL_FREE_NON_NULL(DriverName);
554 
555   ShellPrintHiiEx(
556     -1,
557     -1,
558     NULL,
559     STRING_TOKEN (STR_DH_OUTPUT_DRIVER8),
560     gShellDriver1HiiHandle,
561     DriverBinding->Version,
562     NumberOfChildren > 0?L"Bus":ControllerHandleCount > 0?L"Device":L"<Unknown>",
563     ConfigurationStatus?L"YES":L"NO",
564     DiagnosticsStatus?L"YES":L"NO"
565     );
566 
567   if (ControllerHandleCount == 0) {
568       ShellPrintHiiEx(
569         -1,
570         -1,
571         NULL,
572         STRING_TOKEN (STR_DH_OUTPUT_DRIVER6),
573         gShellDriver1HiiHandle,
574         L"None"
575         );
576   } else {
577     ShellPrintHiiEx(
578       -1,
579       -1,
580       NULL,
581       STRING_TOKEN (STR_DH_OUTPUT_DRIVER6),
582       gShellDriver1HiiHandle,
583       L""
584       );
585     for (HandleIndex = 0; HandleIndex < ControllerHandleCount; HandleIndex++) {
586       Status = gEfiShellProtocol->GetDeviceName(ControllerHandleBuffer[HandleIndex], EFI_DEVICE_NAME_USE_COMPONENT_NAME|EFI_DEVICE_NAME_USE_DEVICE_PATH, (CHAR8*)Language, &TempStringPointer);
587 
588       ShellPrintHiiEx(
589         -1,
590         -1,
591         NULL,
592         STRING_TOKEN (STR_DH_OUTPUT_DRIVER9B),
593         gShellDriver1HiiHandle,
594         ConvertHandleToHandleIndex(ControllerHandleBuffer[HandleIndex]),
595         TempStringPointer!=NULL?TempStringPointer:L"<Unknown>"
596         );
597       SHELL_FREE_NON_NULL(TempStringPointer);
598 
599       Status = PARSE_HANDLE_DATABASE_MANAGED_CHILDREN (
600                 Handle,
601                 ControllerHandleBuffer[HandleIndex],
602                 &ChildControllerHandleCount,
603                 &ChildControllerHandleBuffer
604                 );
605       if (!EFI_ERROR (Status)) {
606         for (ChildIndex = 0; ChildIndex < ChildControllerHandleCount; ChildIndex++) {
607           Status = gEfiShellProtocol->GetDeviceName(ChildControllerHandleBuffer[ChildIndex], EFI_DEVICE_NAME_USE_COMPONENT_NAME|EFI_DEVICE_NAME_USE_DEVICE_PATH, (CHAR8*)Language, &TempStringPointer);
608 
609           ShellPrintHiiEx(
610             -1,
611             -1,
612             NULL,
613             STRING_TOKEN (STR_DH_OUTPUT_DRIVER6B),
614             gShellDriver1HiiHandle,
615             ConvertHandleToHandleIndex(ChildControllerHandleBuffer[ChildIndex]),
616             TempStringPointer!=NULL?TempStringPointer:L"<Unknown>"
617             );
618           SHELL_FREE_NON_NULL(TempStringPointer);
619         }
620 
621         SHELL_FREE_NON_NULL (ChildControllerHandleBuffer);
622       }
623     }
624 
625     SHELL_FREE_NON_NULL (ControllerHandleBuffer);
626   }
627 
628   return EFI_SUCCESS;
629 }
630 
631 /**
632   Display information for a handle.
633 
634   @param[in] TheHandle        The handles to show info on.
635   @param[in] Verbose          TRUE for extra info, FALSE otherwise.
636   @param[in] Sfo              TRUE to output in standard format output (spec).
637   @param[in] Language         Language string per UEFI specification.
638   @param[in] DriverInfo       TRUE to show all info about the handle.
639   @param[in] Multiple         TRUE indicates more than  will be output,
640                               FALSE for a single one.
641 
642   @retval SHELL_SUCCESS           The operation was successful.
643   @retval SHELL_INVALID_PARAMETER ProtocolName was NULL or invalid.
644 **/
645 SHELL_STATUS
DoDhByHandle(IN CONST EFI_HANDLE TheHandle,IN CONST BOOLEAN Verbose,IN CONST BOOLEAN Sfo,IN CONST CHAR8 * Language,IN CONST BOOLEAN DriverInfo,IN CONST BOOLEAN Multiple)646 DoDhByHandle(
647   IN CONST EFI_HANDLE TheHandle,
648   IN CONST BOOLEAN    Verbose,
649   IN CONST BOOLEAN    Sfo,
650   IN CONST CHAR8      *Language,
651   IN CONST BOOLEAN    DriverInfo,
652   IN CONST BOOLEAN    Multiple
653   )
654 {
655   CHAR16              *ProtocolInfoString;
656   SHELL_STATUS        ShellStatus;
657 
658   ShellStatus         = SHELL_SUCCESS;
659   ProtocolInfoString  = NULL;
660 
661   if (!Sfo) {
662     if (Multiple) {
663       ProtocolInfoString = GetProtocolInfoString(TheHandle, Language, L" ", Verbose, TRUE);
664       ShellPrintHiiEx(
665         -1,
666         -1,
667         NULL,
668         STRING_TOKEN (STR_DH_OUTPUT),
669         gShellDriver1HiiHandle,
670         ConvertHandleToHandleIndex(TheHandle),
671         ProtocolInfoString==NULL?L"":ProtocolInfoString);
672     } else {
673       ProtocolInfoString = GetProtocolInfoString(TheHandle, Language, L"\r\n", Verbose, TRUE);
674       ShellPrintHiiEx(
675         -1,
676         -1,
677         NULL,
678         STRING_TOKEN (STR_DH_OUTPUT_SINGLE),
679         gShellDriver1HiiHandle,
680         ConvertHandleToHandleIndex(TheHandle),
681         TheHandle,
682         ProtocolInfoString==NULL?L"":ProtocolInfoString);
683     }
684 
685     if (DriverInfo) {
686       DisplayDriverModelHandle ((EFI_HANDLE)TheHandle, TRUE, Language);
687     }
688   } else {
689       ProtocolInfoString = GetProtocolInfoString(TheHandle, Language, L";", FALSE, FALSE);
690       ShellPrintHiiEx(
691         -1,
692         -1,
693         NULL,
694         STRING_TOKEN (STR_DH_OUTPUT_SFO),
695         gShellDriver1HiiHandle,
696         Multiple ?L"HandlesInfo":L"HandleInfo",
697         L"DriverName",
698         L"ControllerName",
699         ConvertHandleToHandleIndex(TheHandle),
700         L"DevPath",
701         ProtocolInfoString==NULL?L"":ProtocolInfoString);
702 
703 
704   }
705 
706 
707   if (ProtocolInfoString != NULL) {
708     FreePool(ProtocolInfoString);
709   }
710   return (ShellStatus);
711 }
712 
713 /**
714   Display information for all handles on a list.
715 
716   @param[in] HandleList       The NULL-terminated list of handles.
717   @param[in] Verbose          TRUE for extra info, FALSE otherwise.
718   @param[in] Sfo              TRUE to output in standard format output (spec).
719   @param[in] Language         Language string per UEFI specification.
720   @param[in] DriverInfo       TRUE to show all info about the handle.
721 
722   @retval SHELL_SUCCESS           The operation was successful.
723   @retval SHELL_INVALID_PARAMETER ProtocolName was NULL or invalid.
724 **/
725 SHELL_STATUS
DoDhForHandleList(IN CONST EFI_HANDLE * HandleList,IN CONST BOOLEAN Verbose,IN CONST BOOLEAN Sfo,IN CONST CHAR8 * Language,IN CONST BOOLEAN DriverInfo)726 DoDhForHandleList(
727   IN CONST EFI_HANDLE *HandleList,
728   IN CONST BOOLEAN    Verbose,
729   IN CONST BOOLEAN    Sfo,
730   IN CONST CHAR8      *Language,
731   IN CONST BOOLEAN    DriverInfo
732   )
733 {
734   CONST EFI_HANDLE  *HandleWalker;
735   SHELL_STATUS      ShellStatus;
736 
737   ShellStatus       = SHELL_SUCCESS;
738 
739   for (HandleWalker = HandleList ; HandleWalker != NULL && *HandleWalker != NULL && ShellStatus == SHELL_SUCCESS; HandleWalker++) {
740     ShellStatus = DoDhByHandle(
741           *HandleWalker,
742           Verbose,
743           Sfo,
744           Language,
745           DriverInfo,
746           TRUE
747          );
748     if (ShellGetExecutionBreakFlag ()) {
749       ShellStatus = SHELL_ABORTED;
750       break;
751     }
752   }
753   return (ShellStatus);
754 }
755 
756 /**
757   Display information for all handles.
758 
759   @param[in] Sfo              TRUE to output in standard format output (spec).
760   @param[in] Verbose          TRUE for extra info, FALSE otherwise.
761   @param[in] Language         Language string per UEFI specification.
762   @param[in] DriverInfo       TRUE to show all info about the handle.
763 
764   @retval SHELL_SUCCESS           The operation was successful.
765   @retval SHELL_INVALID_PARAMETER ProtocolName was NULL or invalid.
766 **/
767 SHELL_STATUS
DoDhForAll(IN CONST BOOLEAN Sfo,IN CONST BOOLEAN Verbose,IN CONST CHAR8 * Language,IN CONST BOOLEAN DriverInfo)768 DoDhForAll(
769   IN CONST BOOLEAN  Sfo,
770   IN CONST BOOLEAN  Verbose,
771   IN CONST CHAR8    *Language,
772   IN CONST BOOLEAN  DriverInfo
773   )
774 {
775   EFI_HANDLE    *HandleList;
776   SHELL_STATUS  ShellStatus;
777 
778   HandleList = GetHandleListByProtocol(NULL);
779 
780   ShellStatus = DoDhForHandleList(
781     HandleList,
782     Verbose,
783     Sfo,
784     Language,
785     DriverInfo);
786 
787   FreePool(HandleList);
788 
789   return (ShellStatus);
790 }
791 
792 /**
793   Display information for all handles which have a specific protocol.
794 
795   @param[in] ProtocolName     The pointer to the name of the protocol.
796   @param[in] Verbose          TRUE for extra info, FALSE otherwise.
797   @param[in] Sfo              TRUE to output in standard format output (spec).
798   @param[in] Language         Language string per UEFI specification.
799   @param[in] DriverInfo       TRUE to show all info about the handle.
800 
801   @retval SHELL_SUCCESS           The operation was successful.
802   @retval SHELL_INVALID_PARAMETER ProtocolName was NULL or invalid.
803 **/
804 SHELL_STATUS
DoDhByProtocol(IN CONST CHAR16 * ProtocolName,IN CONST BOOLEAN Verbose,IN CONST BOOLEAN Sfo,IN CONST CHAR8 * Language,IN CONST BOOLEAN DriverInfo)805 DoDhByProtocol(
806   IN CONST CHAR16   *ProtocolName,
807   IN CONST BOOLEAN  Verbose,
808   IN CONST BOOLEAN  Sfo,
809   IN CONST CHAR8    *Language,
810   IN CONST BOOLEAN  DriverInfo
811   )
812 {
813   EFI_GUID      *Guid;
814   EFI_STATUS    Status;
815   EFI_HANDLE    *HandleList;
816   SHELL_STATUS  ShellStatus;
817 
818   if (ProtocolName == NULL) {
819     return (SHELL_INVALID_PARAMETER);
820   }
821 
822   Status = GetGuidFromStringName(ProtocolName, Language, &Guid);
823   if (EFI_ERROR(Status)) {
824     ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_DH_NO_GUID_FOUND), gShellDriver1HiiHandle, ProtocolName);
825     return (SHELL_INVALID_PARAMETER);
826   }
827 
828   HandleList = GetHandleListByProtocol(Guid);
829 
830   ShellStatus = DoDhForHandleList(
831     HandleList,
832     Verbose,
833     Sfo,
834     Language,
835     DriverInfo);
836 
837   SHELL_FREE_NON_NULL(HandleList);
838 
839   return (ShellStatus);
840 }
841 
842 /**
843   Function for 'dh' command.
844 
845   @param[in] ImageHandle  Handle to the Image (NULL if Internal).
846   @param[in] SystemTable  Pointer to the System Table (NULL if Internal).
847 **/
848 SHELL_STATUS
849 EFIAPI
ShellCommandRunDh(IN EFI_HANDLE ImageHandle,IN EFI_SYSTEM_TABLE * SystemTable)850 ShellCommandRunDh (
851   IN EFI_HANDLE        ImageHandle,
852   IN EFI_SYSTEM_TABLE  *SystemTable
853   )
854 {
855   EFI_STATUS          Status;
856   LIST_ENTRY          *Package;
857   CHAR16              *ProblemParam;
858   SHELL_STATUS        ShellStatus;
859   CHAR8               *Language;
860   CONST CHAR16        *Lang;
861   CONST CHAR16        *Temp2;
862   BOOLEAN             SfoMode;
863   BOOLEAN             FlagD;
864   BOOLEAN             Verbose;
865   UINT64              Intermediate;
866 
867   ShellStatus         = SHELL_SUCCESS;
868   Status              = EFI_SUCCESS;
869   Language            = NULL;
870 
871   //
872   // initialize the shell lib (we must be in non-auto-init...)
873   //
874   Status = ShellInitialize();
875   ASSERT_EFI_ERROR(Status);
876 
877   Status = CommandInit();
878   ASSERT_EFI_ERROR(Status);
879 
880   //
881   // parse the command line
882   //
883   Status = ShellCommandLineParse (ParamList, &Package, &ProblemParam, TRUE);
884   if (EFI_ERROR(Status)) {
885     if (Status == EFI_VOLUME_CORRUPTED && ProblemParam != NULL) {
886       ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_PROBLEM), gShellDriver1HiiHandle, L"dh", ProblemParam);
887       FreePool(ProblemParam);
888       ShellStatus = SHELL_INVALID_PARAMETER;
889     } else {
890       ASSERT(FALSE);
891     }
892   } else {
893     if (ShellCommandLineGetCount(Package) > 2) {
894       ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_TOO_MANY), gShellDriver1HiiHandle, L"dh");
895       ShellCommandLineFreeVarList (Package);
896       return (SHELL_INVALID_PARAMETER);
897     }
898 
899     Lang = ShellCommandLineGetValue(Package, L"-l");
900     if (Lang != NULL) {
901       Language = AllocateZeroPool(StrSize(Lang));
902       AsciiSPrint(Language, StrSize(Lang), "%S", Lang);
903     } else if (!ShellCommandLineGetFlag(Package, L"-l")){
904       Language = AllocateZeroPool(10);
905       AsciiSPrint(Language, 10, "en-us");
906     } else {
907       ASSERT(Language == NULL);
908       ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_NO_VALUE), gShellDriver1HiiHandle, L"dh",  L"-l");
909       ShellCommandLineFreeVarList (Package);
910       return (SHELL_INVALID_PARAMETER);
911     }
912 
913     SfoMode = ShellCommandLineGetFlag(Package, L"-sfo");
914     FlagD   = ShellCommandLineGetFlag(Package, L"-d");
915     Verbose = (BOOLEAN)(ShellCommandLineGetFlag(Package, L"-v") || ShellCommandLineGetFlag(Package, L"-verbose"));
916 
917     if (ShellCommandLineGetFlag(Package, L"-p")) {
918       if (ShellCommandLineGetCount(Package) > 1) {
919         ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_TOO_MANY), gShellDriver1HiiHandle, L"dh");
920         ShellStatus = SHELL_INVALID_PARAMETER;
921       } else if (ShellCommandLineGetValue(Package, L"-p") == NULL) {
922         ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_NO_VALUE), gShellDriver1HiiHandle, L"dh",  L"-p");
923         ShellStatus = SHELL_INVALID_PARAMETER;
924       } else {
925         //
926         // print by protocol
927         //
928         ShellStatus = DoDhByProtocol(
929           ShellCommandLineGetValue(Package, L"-p"),
930           Verbose,
931           SfoMode,
932           Lang==NULL?NULL:Language,
933           FlagD
934          );
935       }
936     } else {
937       Temp2 = ShellCommandLineGetRawValue(Package, 1);
938       if (Temp2 == NULL) {
939         //
940         // Print everything
941         //
942         ShellStatus = DoDhForAll(
943           SfoMode,
944           Verbose,
945           Lang==NULL?NULL:Language,
946           FlagD
947          );
948       } else {
949         Status = ShellConvertStringToUint64(Temp2, &Intermediate, TRUE, FALSE);
950         if (EFI_ERROR(Status) || ConvertHandleIndexToHandle((UINTN)Intermediate) == NULL) {
951           ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_INV_HANDLE), gShellDriver1HiiHandle, L"dh", Temp2);
952           ShellStatus = SHELL_INVALID_PARAMETER;
953         } else {
954           //
955           // print 1 handle
956           //
957           ShellStatus = DoDhByHandle(
958             ConvertHandleIndexToHandle((UINTN)Intermediate),
959             Verbose,
960             SfoMode,
961             Lang==NULL?NULL:Language,
962             FlagD,
963             FALSE
964            );
965         }
966       }
967     }
968 
969 
970     ShellCommandLineFreeVarList (Package);
971     SHELL_FREE_NON_NULL(Language);
972   }
973 
974   return (ShellStatus);
975 }
976