1 /** @file
2   Main file for Drivers shell Driver1 function.
3 
4   (C) Copyright 2012-2015 Hewlett-Packard Development Company, L.P.<BR>
5   Copyright (c) 2010 - 2015, 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 #define MAX_LEN_DRIVER_NAME 35
19 
20 STATIC CONST SHELL_PARAM_ITEM ParamList[] = {
21   {L"-sfo", TypeFlag},
22   {L"-l", TypeValue},
23   {NULL, TypeMax}
24   };
25 
26 /**
27   Get a device path (in text format) for a given handle.
28 
29   @param[in] TheHandle      The handle to get the device path for.
30 
31   @retval NULL    An error occured.
32   @return         A pointer to the driver path as a string.  The callee must
33                   free this memory.
34 **/
35 CHAR16*
36 EFIAPI
GetDevicePathTextForHandle(IN EFI_HANDLE TheHandle)37 GetDevicePathTextForHandle(
38   IN EFI_HANDLE TheHandle
39   )
40 {
41   EFI_STATUS                Status;
42   EFI_LOADED_IMAGE_PROTOCOL *LoadedImage;
43   EFI_DEVICE_PATH_PROTOCOL  *ImageDevicePath;
44   EFI_DEVICE_PATH_PROTOCOL  *FinalPath;
45   CHAR16                    *RetVal;
46 
47   FinalPath = NULL;
48 
49   Status = gBS->OpenProtocol (
50                 TheHandle,
51                 &gEfiLoadedImageProtocolGuid,
52                 (VOID**)&LoadedImage,
53                 gImageHandle,
54                 NULL,
55                 EFI_OPEN_PROTOCOL_GET_PROTOCOL
56                );
57   if (!EFI_ERROR (Status)) {
58     Status = gBS->OpenProtocol (
59                   LoadedImage->DeviceHandle,
60                   &gEfiDevicePathProtocolGuid,
61                   (VOID**)&ImageDevicePath,
62                   gImageHandle,
63                   NULL,
64                   EFI_OPEN_PROTOCOL_GET_PROTOCOL
65                  );
66     if (!EFI_ERROR (Status)) {
67       FinalPath = AppendDevicePath (ImageDevicePath, LoadedImage->FilePath);
68       gBS->CloseProtocol(
69         LoadedImage->DeviceHandle,
70         &gEfiDevicePathProtocolGuid,
71         gImageHandle,
72         NULL);
73     }
74     gBS->CloseProtocol(
75                 TheHandle,
76                 &gEfiLoadedImageProtocolGuid,
77                 gImageHandle,
78                 NULL);
79   }
80 
81   if (FinalPath == NULL) {
82     return (NULL);
83   }
84   RetVal = gEfiShellProtocol->GetFilePathFromDevicePath(FinalPath);
85   if (RetVal == NULL) {
86     RetVal = ConvertDevicePathToText(FinalPath, TRUE, TRUE);
87   }
88   FreePool(FinalPath);
89   return (RetVal);
90 }
91 
92 /**
93   Determine if the given handle has Driver Configuration protocol.
94 
95   @param[in] TheHandle      The handle to the driver to test.
96 
97   @retval TRUE              The driver does have Driver Configuration.
98   @retval FALSE             The driver does not have Driver Configuration.
99 **/
100 BOOLEAN
101 EFIAPI
ReturnDriverConfig(IN CONST EFI_HANDLE TheHandle)102 ReturnDriverConfig(
103   IN CONST EFI_HANDLE TheHandle
104   )
105 {
106   EFI_STATUS                  Status;
107   Status = gBS->OpenProtocol((EFI_HANDLE)TheHandle, &gEfiDriverConfigurationProtocolGuid, NULL, gImageHandle, NULL, EFI_OPEN_PROTOCOL_TEST_PROTOCOL);
108   if (EFI_ERROR(Status)) {
109     return (FALSE);
110   }
111   return (TRUE);
112 }
113 
114 /**
115   Determine if the given handle has DriverDiagnostics protocol.
116 
117   @param[in] TheHandle      The handle to the driver to test.
118 
119   @retval TRUE              The driver does have Driver Diasgnostics.
120   @retval FALSE             The driver does not have Driver Diagnostics.
121 **/
122 BOOLEAN
123 EFIAPI
ReturnDriverDiag(IN CONST EFI_HANDLE TheHandle)124 ReturnDriverDiag(
125   IN CONST EFI_HANDLE TheHandle
126   )
127 {
128   EFI_STATUS                  Status;
129   Status = gBS->OpenProtocol((EFI_HANDLE)TheHandle, &gEfiDriverDiagnostics2ProtocolGuid, NULL, gImageHandle, NULL, EFI_OPEN_PROTOCOL_TEST_PROTOCOL);
130   if (EFI_ERROR(Status)) {
131     Status = gBS->OpenProtocol((EFI_HANDLE)TheHandle, &gEfiDriverDiagnosticsProtocolGuid, NULL, gImageHandle, NULL, EFI_OPEN_PROTOCOL_TEST_PROTOCOL);
132     if (EFI_ERROR(Status)) {
133       return (FALSE);
134     }
135   }
136   return (TRUE);
137 }
138 
139 /**
140   Finds and returns the version of the driver specified by TheHandle.
141 
142   @param[in] TheHandle      The driver handle to get the version of.
143 
144   @return             The version of the driver.
145   @retval 0xFFFFFFFF  An error ocurred.
146 **/
147 UINT32
148 EFIAPI
ReturnDriverVersion(IN CONST EFI_HANDLE TheHandle)149 ReturnDriverVersion(
150   IN CONST EFI_HANDLE TheHandle
151   )
152 {
153   EFI_DRIVER_BINDING_PROTOCOL *DriverBinding;
154   EFI_STATUS                  Status;
155   UINT32                      RetVal;
156 
157   RetVal = (UINT32)-1;
158 
159   Status = gBS->OpenProtocol((EFI_HANDLE)TheHandle, &gEfiDriverBindingProtocolGuid, (VOID**)&DriverBinding, gImageHandle, NULL, EFI_OPEN_PROTOCOL_GET_PROTOCOL);
160   if (!EFI_ERROR(Status)) {
161     RetVal = DriverBinding->Version;
162     gBS->CloseProtocol(TheHandle, &gEfiDriverBindingProtocolGuid, gImageHandle, NULL);
163   }
164   return (RetVal);
165 }
166 
167 /**
168   Function for 'drivers' command.
169 
170   @param[in] ImageHandle  Handle to the Image (NULL if Internal).
171   @param[in] SystemTable  Pointer to the System Table (NULL if Internal).
172 **/
173 SHELL_STATUS
174 EFIAPI
ShellCommandRunDrivers(IN EFI_HANDLE ImageHandle,IN EFI_SYSTEM_TABLE * SystemTable)175 ShellCommandRunDrivers (
176   IN EFI_HANDLE        ImageHandle,
177   IN EFI_SYSTEM_TABLE  *SystemTable
178   )
179 {
180   EFI_STATUS          Status;
181   LIST_ENTRY          *Package;
182   CHAR16              *ProblemParam;
183   SHELL_STATUS        ShellStatus;
184   CHAR8               *Language;
185   CONST CHAR16        *Lang;
186   EFI_HANDLE          *HandleList;
187   EFI_HANDLE          *HandleWalker;
188   UINTN               ChildCount;
189   UINTN               DeviceCount;
190   CHAR16              *Temp2;
191   CONST CHAR16        *FullDriverName;
192   CHAR16              *TruncatedDriverName;
193   CHAR16              *FormatString;
194   UINT32              DriverVersion;
195   BOOLEAN             DriverConfig;
196   BOOLEAN             DriverDiag;
197   BOOLEAN             SfoFlag;
198 
199   ShellStatus         = SHELL_SUCCESS;
200   Status              = EFI_SUCCESS;
201   Language            = NULL;
202   FormatString        = NULL;
203   SfoFlag             = FALSE;
204 
205   //
206   // initialize the shell lib (we must be in non-auto-init...)
207   //
208   Status = ShellInitialize();
209   ASSERT_EFI_ERROR(Status);
210 
211   Status = CommandInit();
212   ASSERT_EFI_ERROR(Status);
213 
214   //
215   // parse the command line
216   //
217   Status = ShellCommandLineParse (ParamList, &Package, &ProblemParam, TRUE);
218   if (EFI_ERROR(Status)) {
219     if (Status == EFI_VOLUME_CORRUPTED && ProblemParam != NULL) {
220       ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_PROBLEM), gShellDriver1HiiHandle, L"drivers", ProblemParam);
221       FreePool(ProblemParam);
222       ShellStatus = SHELL_INVALID_PARAMETER;
223     } else {
224       ASSERT(FALSE);
225     }
226   } else {
227     if (ShellCommandLineGetCount(Package) > 1) {
228       ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_TOO_MANY), gShellDriver1HiiHandle, L"drivers");
229       ShellStatus = SHELL_INVALID_PARAMETER;
230     } else {
231       if (ShellCommandLineGetFlag(Package, L"-l")){
232         Lang = ShellCommandLineGetValue(Package, L"-l");
233         if (Lang != NULL) {
234           Language = AllocateZeroPool(StrSize(Lang));
235           AsciiSPrint(Language, StrSize(Lang), "%S", Lang);
236         } else {
237           ASSERT(Language == NULL);
238           ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_NO_VALUE), gShellDriver1HiiHandle, L"drivers", L"-l");
239           ShellCommandLineFreeVarList (Package);
240           return (SHELL_INVALID_PARAMETER);
241         }
242       }
243 
244       if (ShellCommandLineGetFlag (Package, L"-sfo")) {
245         SfoFlag = TRUE;
246         FormatString = HiiGetString (gShellDriver1HiiHandle, STRING_TOKEN (STR_DRIVERS_ITEM_LINE_SFO), Language);
247         //
248         // print the SFO header
249         //
250         ShellPrintHiiEx (
251           -1,
252           -1,
253           Language,
254           STRING_TOKEN (STR_GEN_SFO_HEADER),
255           gShellDriver1HiiHandle,
256           L"drivers");
257       } else {
258         FormatString = HiiGetString (gShellDriver1HiiHandle, STRING_TOKEN (STR_DRIVERS_ITEM_LINE), Language);
259         //
260         // print the header row
261         //
262         ShellPrintHiiEx(
263           -1,
264           -1,
265           Language,
266           STRING_TOKEN (STR_DRIVERS_HEADER_LINES),
267           gShellDriver1HiiHandle);
268       }
269 
270       HandleList = GetHandleListByProtocol(&gEfiDriverBindingProtocolGuid);
271       for (HandleWalker = HandleList ; HandleWalker != NULL && *HandleWalker != NULL ; HandleWalker++){
272         ChildCount     = 0;
273         DeviceCount    = 0;
274         Status         = ParseHandleDatabaseForChildDevices (*HandleWalker, &ChildCount , NULL);
275         Status         = PARSE_HANDLE_DATABASE_DEVICES      (*HandleWalker, &DeviceCount, NULL);
276         Temp2          = GetDevicePathTextForHandle(*HandleWalker);
277         DriverVersion  = ReturnDriverVersion(*HandleWalker);
278         DriverConfig   = ReturnDriverConfig(*HandleWalker);
279         DriverDiag     = ReturnDriverDiag  (*HandleWalker);
280         FullDriverName = GetStringNameFromHandle(*HandleWalker, Language);
281 
282         TruncatedDriverName = NULL;
283         if (!SfoFlag && (FullDriverName != NULL)) {
284           TruncatedDriverName = AllocateZeroPool ((MAX_LEN_DRIVER_NAME + 1) * sizeof (CHAR16));
285           StrnCpyS (TruncatedDriverName, MAX_LEN_DRIVER_NAME + 1, FullDriverName, MAX_LEN_DRIVER_NAME);
286         }
287 
288         ShellPrintEx(
289           -1,
290           -1,
291           FormatString,
292           ConvertHandleToHandleIndex(*HandleWalker),
293           DriverVersion,
294           ChildCount > 0?L'B':(DeviceCount > 0?L'D':L'?'),
295           DriverConfig?L'Y':L'N',
296           DriverDiag?L'Y':L'N',
297           DeviceCount,
298           ChildCount,
299           SfoFlag?FullDriverName:TruncatedDriverName,
300           Temp2==NULL?L"":Temp2
301          );
302         if (TruncatedDriverName != NULL) {
303           FreePool (TruncatedDriverName);
304         }
305         if (Temp2 != NULL) {
306           FreePool(Temp2);
307         }
308 
309         if (ShellGetExecutionBreakFlag ()) {
310           ShellStatus = SHELL_ABORTED;
311           break;
312         }
313       }
314     }
315     SHELL_FREE_NON_NULL(Language);
316     ShellCommandLineFreeVarList (Package);
317     SHELL_FREE_NON_NULL(FormatString);
318   }
319 
320   return (ShellStatus);
321 }
322