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
18STATIC 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
28STATIC 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**/
55EFI_STATUS
56GetDriverName (
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**/
108BOOLEAN
109IsDriverProt (
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**/
140CHAR16*
141GetProtocolInfoString(
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**/
216EFI_STATUS
217GetDriverImageName (
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**/
254EFI_STATUS
255DisplayDriverModelHandle (
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**/
645SHELL_STATUS
646DoDhByHandle(
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**/
725SHELL_STATUS
726DoDhForHandleList(
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**/
767SHELL_STATUS
768DoDhForAll(
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**/
804SHELL_STATUS
805DoDhByProtocol(
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**/
848SHELL_STATUS
849EFIAPI
850ShellCommandRunDh (
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