1 /** @file
2   Main file for devices shell Driver1 function.
3 
4   (C) Copyright 2012-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 /**
19   Get lots of info about a device from its handle.
20 
21   @param[in] TheHandle       The device handle to get info on.
22   @param[in, out] Type       On successful return R, B, or D (root, bus, or
23                              device) will be placed in this buffer.
24   @param[in, out] Cfg        On successful return this buffer will be
25                              TRUE if the handle has configuration, FALSE
26                              otherwise.
27   @param[in, out] Diag       On successful return this buffer will be
28                              TRUE if the handle has disgnostics, FALSE
29                              otherwise.
30   @param[in, out] Parents    On successful return this buffer will be
31                              contain the number of parent handles.
32   @param[in, out] Devices    On successful return this buffer will be
33                              contain the number of devices controlled.
34   @param[in, out] Children   On successful return this buffer will be
35                              contain the number of child handles.
36   @param[out] Name           The pointer to a buffer that will be allocated
37                              and contain the string name of the handle.
38                              The caller must free this memory.
39   @param[in] Language        The language code as defined by the UEFI spec.
40 
41   @retval EFI_SUCCESS           The info is there.
42   @retval EFI_INVALID_PARAMETER A parameter was invalid.
43 **/
44 EFI_STATUS
GetDeviceHandleInfo(IN EFI_HANDLE TheHandle,IN OUT CHAR16 * Type,IN OUT BOOLEAN * Cfg,IN OUT BOOLEAN * Diag,IN OUT UINTN * Parents,IN OUT UINTN * Devices,IN OUT UINTN * Children,OUT CHAR16 ** Name,IN CONST CHAR8 * Language)45 GetDeviceHandleInfo (
46   IN EFI_HANDLE   TheHandle,
47   IN OUT CHAR16   *Type,
48   IN OUT BOOLEAN  *Cfg,
49   IN OUT BOOLEAN  *Diag,
50   IN OUT UINTN    *Parents,
51   IN OUT UINTN    *Devices,
52   IN OUT UINTN    *Children,
53   OUT CHAR16      **Name,
54   IN CONST CHAR8  *Language
55   )
56 {
57   EFI_STATUS    Status;
58   EFI_HANDLE    *HandleBuffer;
59   UINTN         Count;
60 
61   if (TheHandle == NULL
62     || Type == NULL
63     || Cfg == NULL
64     || Diag == NULL
65     || Parents == NULL
66     || Devices == NULL
67     || Children == NULL
68     || Name == NULL ) {
69     return (EFI_INVALID_PARAMETER);
70   }
71 
72   *Cfg          = FALSE;
73   *Diag         = FALSE;
74   *Children     = 0;
75   *Parents      = 0;
76   *Devices      = 0;
77   *Type         = L' ';
78   *Name         = CHAR_NULL;
79   HandleBuffer  = NULL;
80   Status        = EFI_SUCCESS;
81 
82   gEfiShellProtocol->GetDeviceName(TheHandle, EFI_DEVICE_NAME_USE_COMPONENT_NAME|EFI_DEVICE_NAME_USE_DEVICE_PATH, (CHAR8*)Language, Name);
83 
84   Status = ParseHandleDatabaseForChildControllers(TheHandle, Children, NULL);
85 //  if (!EFI_ERROR(Status)) {
86     Status = PARSE_HANDLE_DATABASE_PARENTS(TheHandle, Parents, NULL);
87     if (/*!EFI_ERROR(Status) && */Parents != NULL && Children != NULL) {
88       if (*Parents == 0) {
89         *Type = L'R';
90       } else if (*Children > 0) {
91         *Type = L'B';
92       } else {
93         *Type = L'D';
94       }
95     }
96 //  }
97   Status = PARSE_HANDLE_DATABASE_UEFI_DRIVERS(TheHandle, Devices, &HandleBuffer);
98   if (!EFI_ERROR(Status) && Devices != NULL && HandleBuffer != NULL) {
99     for (Count = 0 ; Count < *Devices ; Count++) {
100       if (!EFI_ERROR(gBS->OpenProtocol(HandleBuffer[Count], &gEfiDriverConfigurationProtocolGuid, NULL, NULL, gImageHandle, EFI_OPEN_PROTOCOL_TEST_PROTOCOL))) {
101         *Cfg = TRUE;
102       }
103       if (!EFI_ERROR(gBS->OpenProtocol(HandleBuffer[Count], &gEfiDriverDiagnosticsProtocolGuid, NULL, NULL, gImageHandle, EFI_OPEN_PROTOCOL_TEST_PROTOCOL))) {
104         *Diag = TRUE;
105       }
106       if (!EFI_ERROR(gBS->OpenProtocol(HandleBuffer[Count], &gEfiDriverDiagnostics2ProtocolGuid, NULL, NULL, gImageHandle, EFI_OPEN_PROTOCOL_TEST_PROTOCOL))) {
107         *Diag = TRUE;
108       }
109     }
110     SHELL_FREE_NON_NULL(HandleBuffer);
111   }
112 
113   return (Status);
114 }
115 
116 STATIC CONST SHELL_PARAM_ITEM ParamList[] = {
117   {L"-sfo", TypeFlag},
118   {L"-l", TypeValue},
119   {NULL, TypeMax}
120   };
121 
122 /**
123   Function for 'devices' command.
124 
125   @param[in] ImageHandle  Handle to the Image (NULL if Internal).
126   @param[in] SystemTable  Pointer to the System Table (NULL if Internal).
127 **/
128 SHELL_STATUS
129 EFIAPI
ShellCommandRunDevices(IN EFI_HANDLE ImageHandle,IN EFI_SYSTEM_TABLE * SystemTable)130 ShellCommandRunDevices (
131   IN EFI_HANDLE        ImageHandle,
132   IN EFI_SYSTEM_TABLE  *SystemTable
133   )
134 {
135   EFI_STATUS          Status;
136   LIST_ENTRY          *Package;
137   CHAR16              *ProblemParam;
138   SHELL_STATUS        ShellStatus;
139   CHAR8               *Language;
140   EFI_HANDLE          *HandleList;
141   EFI_HANDLE          *HandleListWalker;
142   CHAR16              Type;
143   BOOLEAN             Cfg;
144   BOOLEAN             Diag;
145   UINTN               Parents;
146   UINTN               Devices;
147   UINTN               Children;
148   CHAR16              *Name;
149   CONST CHAR16        *Lang;
150   BOOLEAN             SfoFlag;
151 
152   ShellStatus         = SHELL_SUCCESS;
153   Language            = NULL;
154   SfoFlag             = FALSE;
155 
156   //
157   // initialize the shell lib (we must be in non-auto-init...)
158   //
159   Status = ShellInitialize();
160   ASSERT_EFI_ERROR(Status);
161 
162   Status = CommandInit();
163   ASSERT_EFI_ERROR(Status);
164 
165   //
166   // parse the command line
167   //
168   Status = ShellCommandLineParse (ParamList, &Package, &ProblemParam, TRUE);
169   if (EFI_ERROR(Status)) {
170     if (Status == EFI_VOLUME_CORRUPTED && ProblemParam != NULL) {
171       ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_PROBLEM), gShellDriver1HiiHandle, L"devices", ProblemParam);
172       FreePool(ProblemParam);
173       ShellStatus = SHELL_INVALID_PARAMETER;
174     } else {
175       ASSERT(FALSE);
176     }
177   } else {
178     //
179     // if more than 0 'value' parameters  we have too many parameters
180     //
181     if (ShellCommandLineGetRawValue(Package, 1) != NULL){
182       //
183       // error for too many parameters
184       //
185       ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_TOO_MANY), gShellDriver1HiiHandle, L"devices");
186       ShellStatus = SHELL_INVALID_PARAMETER;
187     } else {
188       //
189       // get the language if necessary
190       //
191       Lang = ShellCommandLineGetValue(Package, L"-l");
192       if (Lang != NULL) {
193         Language = AllocateZeroPool(StrSize(Lang));
194         AsciiSPrint(Language, StrSize(Lang), "%S", Lang);
195       } else if (!ShellCommandLineGetFlag(Package, L"-l")){
196         ASSERT(Language == NULL);
197 //        Language = AllocateZeroPool(10);
198 //        AsciiSPrint(Language, 10, "en-us");
199       } else {
200         ASSERT(Language == NULL);
201         ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_NO_VALUE), gShellDriver1HiiHandle, L"devices",  L"-l");
202         ShellCommandLineFreeVarList (Package);
203         return (SHELL_INVALID_PARAMETER);
204       }
205 
206 
207       //
208       // Print Header
209 
210       //
211       if (ShellCommandLineGetFlag (Package, L"-sfo")) {
212         ShellPrintHiiEx (-1, -1, Language, STRING_TOKEN (STR_GEN_SFO_HEADER), gShellDriver1HiiHandle, L"devices");
213         SfoFlag = TRUE;
214       } else {
215         ShellPrintHiiEx (-1, -1, Language, STRING_TOKEN (STR_DEVICES_HEADER_LINES), gShellDriver1HiiHandle);
216       }
217 
218       //
219       // loop through each handle
220       //
221       HandleList = GetHandleListByProtocol(NULL);
222       ASSERT(HandleList != NULL);
223       for (HandleListWalker = HandleList
224         ;  HandleListWalker != NULL && *HandleListWalker != NULL /*&& !EFI_ERROR(Status)*/
225         ;  HandleListWalker++
226        ){
227 
228         //
229         // get all the info on each handle
230         //
231         Name = NULL;
232         Status = GetDeviceHandleInfo(*HandleListWalker, &Type, &Cfg, &Diag, &Parents, &Devices, &Children, &Name, Language);
233         if (Name != NULL && (Parents != 0 || Devices != 0 || Children != 0)) {
234           ShellPrintHiiEx (
235             -1,
236             -1,
237             Language,
238             SfoFlag?STRING_TOKEN (STR_DEVICES_ITEM_LINE_SFO):STRING_TOKEN (STR_DEVICES_ITEM_LINE),
239             gShellDriver1HiiHandle,
240             ConvertHandleToHandleIndex (*HandleListWalker),
241             Type,
242             Cfg?(SfoFlag?L'Y':L'X'):(SfoFlag?L'N':L'-'),
243             Diag?(SfoFlag?L'Y':L'X'):(SfoFlag?L'N':L'-'),
244             Parents,
245             Devices,
246             Children,
247             Name!=NULL?Name:L"<UNKNOWN>");
248         }
249         if (Name != NULL) {
250           FreePool(Name);
251         }
252         if (ShellGetExecutionBreakFlag ()) {
253           ShellStatus = SHELL_ABORTED;
254           break;
255         }
256 
257       }
258 
259       if (HandleList != NULL) {
260         FreePool(HandleList);
261       }
262 
263     }
264     SHELL_FREE_NON_NULL(Language);
265     ShellCommandLineFreeVarList (Package);
266   }
267   return (ShellStatus);
268 }
269 
270