1 /** @file
2 Main file for DrvDiag shell Driver1 function.
3
4 (C) Copyright 2015 Hewlett-Packard Development Company, L.P.<BR>
5 Copyright (c) 2010 - 2016, 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 EFI_GUID *DiagGuidList[] = {&gEfiDriverDiagnosticsProtocolGuid, &gEfiDriverDiagnostics2ProtocolGuid, NULL};
19 //
20 // We need 1 more item on the list...
21 //
22 typedef enum {
23 TestModeStandard = EfiDriverDiagnosticTypeStandard,
24 TestModeExtended = EfiDriverDiagnosticTypeExtended,
25 TestModeManufacturing = EfiDriverDiagnosticTypeManufacturing,
26 TestModeList,
27 TestModeMax
28 } DRV_DIAG_TEST_MODE;
29
30 /**
31 Do the diagnostics call for some set of handles.
32
33 @param[in] Mode The type of diagnostic test to run.
34 @param[in] Lang The language code to use.
35 @param[in] AllChilds Should the test be on all children.
36 @param[in] DriverHandle The driver handle to test with.
37 @param[in] ControllerHandle The specific controller handle to test.
38 @param[in] ChildHandle The specific child handle to test.
39
40 @retval EFI_SUCCESS The operation was successful.
41 @retval EFI_INVALID_PARAMETER A parameter had an invalid value.
42 @retval EFI_NOT_FOUND No diagnostic handle could be found.
43 **/
44 EFI_STATUS
DoDiagnostics(IN CONST DRV_DIAG_TEST_MODE Mode,IN CONST CHAR8 * Lang,IN CONST BOOLEAN AllChilds,IN CONST EFI_HANDLE DriverHandle,IN CONST EFI_HANDLE ControllerHandle,IN CONST EFI_HANDLE ChildHandle)45 DoDiagnostics (
46 IN CONST DRV_DIAG_TEST_MODE Mode,
47 IN CONST CHAR8 *Lang,
48 IN CONST BOOLEAN AllChilds,
49 IN CONST EFI_HANDLE DriverHandle,
50 IN CONST EFI_HANDLE ControllerHandle,
51 IN CONST EFI_HANDLE ChildHandle
52 )
53 {
54 EFI_DRIVER_DIAGNOSTICS_PROTOCOL *DriverDiagnostics;
55 EFI_DRIVER_DIAGNOSTICS2_PROTOCOL *DriverDiagnostics2;
56 EFI_HANDLE *DriverHandleList;
57 EFI_HANDLE *ControllerHandleList;
58 EFI_HANDLE *ChildHandleList;
59 EFI_HANDLE *Walker;
60 UINTN DriverHandleListCount;
61 UINTN ControllerHandleListCount;
62 UINTN ChildHandleListCount;
63 UINTN DriverHandleListLoop;
64 UINTN ControllerHandleListLoop;
65 UINTN ChildHandleListLoop;
66 EFI_STATUS Status;
67 EFI_STATUS Status2;
68 EFI_GUID *ErrorType;
69 UINTN OutBufferSize;
70 CHAR16 *OutBuffer;
71 UINTN HandleIndex1;
72 UINTN HandleIndex2;
73 CHAR8 *Language;
74 BOOLEAN Found;
75
76 if ((ChildHandle != NULL && AllChilds) || (Mode >= TestModeMax)){
77 return (EFI_INVALID_PARAMETER);
78 }
79
80 DriverDiagnostics = NULL;
81 DriverDiagnostics2 = NULL;
82 Status = EFI_SUCCESS;
83 Status2 = EFI_SUCCESS;
84 DriverHandleList = NULL;
85 ControllerHandleList = NULL;
86 ChildHandleList = NULL;
87 Language = NULL;
88 OutBuffer = NULL;
89 ErrorType = NULL;
90 DriverHandleListCount = 0;
91 ControllerHandleListCount = 0;
92 ChildHandleListCount = 0;
93
94 if (DriverHandle != NULL) {
95 DriverHandleList = AllocateZeroPool(2*sizeof(EFI_HANDLE));
96 if (DriverHandleList == NULL) {
97 return EFI_OUT_OF_RESOURCES;
98 }
99 DriverHandleList[0] = DriverHandle;
100 DriverHandleListCount = 1;
101 } else {
102 DriverHandleList = GetHandleListByProtocolList(DiagGuidList);
103 if (DriverHandleList == NULL) {
104 ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_PROTOCOL_NF), gShellDriver1HiiHandle, L"drvdiag", L"gEfiDriverDiagnosticsProtocolGuid", &gEfiDriverDiagnosticsProtocolGuid);
105 ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_PROTOCOL_NF), gShellDriver1HiiHandle, L"drvdiag", L"gEfiDriverDiagnostics2ProtocolGuid", &gEfiDriverDiagnostics2ProtocolGuid);
106 return (EFI_NOT_FOUND);
107 }
108 for (Walker = DriverHandleList ; Walker != NULL && *Walker != NULL ; DriverHandleListCount++, Walker++);
109 }
110
111 if (ControllerHandle != NULL) {
112 ControllerHandleList = AllocateZeroPool(2*sizeof(EFI_HANDLE));
113 if (ControllerHandleList == NULL) {
114 SHELL_FREE_NON_NULL (DriverHandleList);
115 return EFI_OUT_OF_RESOURCES;
116 }
117 ControllerHandleList[0] = ControllerHandle;
118 ControllerHandleListCount = 1;
119 } else {
120 ControllerHandleList = NULL;
121 }
122
123 if (ChildHandle != NULL) {
124 ChildHandleList = AllocateZeroPool(2*sizeof(EFI_HANDLE));
125 if (ChildHandleList == NULL) {
126 SHELL_FREE_NON_NULL (ControllerHandleList);
127 SHELL_FREE_NON_NULL (DriverHandleList);
128 return EFI_OUT_OF_RESOURCES;
129 }
130 ChildHandleList[0] = ChildHandle;
131 ChildHandleListCount = 1;
132 } else if (AllChilds) {
133 ChildHandleList = NULL;
134 //
135 // This gets handled in the loop below.
136 //
137 } else {
138 ChildHandleList = NULL;
139 }
140
141 if (Mode == TestModeList) {
142 ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_DRVDIAG_HEADER), gShellDriver1HiiHandle);
143 }
144 for (DriverHandleListLoop = 0
145 ; DriverHandleListLoop < DriverHandleListCount
146 ; DriverHandleListLoop++
147 ){
148 if (Mode == TestModeList) {
149 ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_DRVDIAG_DRIVER_HEADER), gShellDriver1HiiHandle, ConvertHandleToHandleIndex(DriverHandleList[DriverHandleListLoop]));
150 }
151 if (ControllerHandle == NULL) {
152 PARSE_HANDLE_DATABASE_DEVICES(DriverHandleList[DriverHandleListLoop], &ControllerHandleListCount, &ControllerHandleList);
153 }
154 if (ControllerHandleListCount == 0) {
155 if (Mode == TestModeList) {
156 ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_DRVDIAG_DRIVER_NO_HANDLES), gShellDriver1HiiHandle);
157 }
158 } else {
159 if (Mode == TestModeList) {
160 ShellPrintEx(-1, -1, L"\r\n");
161 }
162 for (ControllerHandleListLoop = 0
163 ; ControllerHandleListLoop < ControllerHandleListCount
164 ; ControllerHandleListLoop++
165 ){
166 if (AllChilds) {
167 ASSERT(ChildHandleList == NULL);
168 PARSE_HANDLE_DATABASE_MANAGED_CHILDREN(
169 DriverHandleList[DriverHandleListLoop],
170 ControllerHandleList[ControllerHandleListLoop],
171 &ChildHandleListCount,
172 &ChildHandleList);
173 }
174 for (ChildHandleListLoop = 0
175 ; (ChildHandleListLoop < ChildHandleListCount || ChildHandleList == NULL)
176 ; ChildHandleListLoop++
177 ){
178 Found = FALSE;
179 if (Mode != TestModeList) {
180 if (Lang == NULL || Lang[2] == '-') {
181 //
182 // Get the protocol pointer and call the function
183 //
184 Status = gBS->OpenProtocol(
185 DriverHandleList[DriverHandleListLoop],
186 &gEfiDriverDiagnostics2ProtocolGuid,
187 (VOID**)&DriverDiagnostics2,
188 gImageHandle,
189 NULL,
190 EFI_OPEN_PROTOCOL_GET_PROTOCOL);
191 if (!EFI_ERROR(Status) && (DriverDiagnostics2 != NULL)) {
192 Language = GetBestLanguageForDriver(DriverDiagnostics2->SupportedLanguages, Lang, FALSE);
193 Found = TRUE;
194 Status = DriverDiagnostics2->RunDiagnostics(
195 DriverDiagnostics2,
196 ControllerHandleList[ControllerHandleListLoop],
197 ChildHandleList == NULL?NULL:ChildHandleList[ChildHandleListLoop],
198 (EFI_DRIVER_DIAGNOSTIC_TYPE)Mode,
199 Language,
200 &ErrorType,
201 &OutBufferSize,
202 &OutBuffer);
203 FreePool(Language);
204 }
205 }
206 if (!Found && (Lang == NULL||(Lang!=NULL&&(Lang[2]!='-')))){
207 Status = gBS->OpenProtocol(
208 DriverHandleList[DriverHandleListLoop],
209 &gEfiDriverDiagnosticsProtocolGuid,
210 (VOID**)&DriverDiagnostics,
211 gImageHandle,
212 NULL,
213 EFI_OPEN_PROTOCOL_GET_PROTOCOL);
214 if (!EFI_ERROR(Status)) {
215 Language = GetBestLanguageForDriver(DriverDiagnostics->SupportedLanguages, Lang, FALSE);
216 Status = DriverDiagnostics->RunDiagnostics(
217 DriverDiagnostics,
218 ControllerHandleList[ControllerHandleListLoop],
219 ChildHandleList == NULL?NULL:ChildHandleList[ChildHandleListLoop],
220 (EFI_DRIVER_DIAGNOSTIC_TYPE)Mode,
221 Language,
222 &ErrorType,
223 &OutBufferSize,
224 &OutBuffer);
225 FreePool(Language);
226 }
227 }
228 if (EFI_ERROR(Status)) {
229 Status2 = Status;
230 }
231 HandleIndex1 = ConvertHandleToHandleIndex(DriverHandleList[DriverHandleListLoop]);
232 HandleIndex2 = ConvertHandleToHandleIndex(ControllerHandleList[ControllerHandleListLoop]);
233 ShellPrintHiiEx(
234 -1,
235 -1,
236 NULL,
237 STRING_TOKEN (STR_3P_RESULT),
238 gShellDriver1HiiHandle,
239 L"DrvDiag",
240 HandleIndex1,
241 HandleIndex2,
242 ChildHandleList == NULL?0:ConvertHandleToHandleIndex(ChildHandleList[ChildHandleListLoop]),
243 Status);
244 if (OutBuffer!=NULL) {
245 FreePool(OutBuffer);
246 OutBuffer = NULL;
247 }
248 if (ErrorType!=NULL) {
249 FreePool(ErrorType);
250 ErrorType = NULL;
251 }
252 } else {
253 HandleIndex1 = ConvertHandleToHandleIndex(DriverHandleList[DriverHandleListLoop]);
254 HandleIndex2 = ConvertHandleToHandleIndex(ControllerHandleList[ControllerHandleListLoop]);
255 //
256 // Print out the information that this set can be tested
257 //
258 ShellPrintHiiEx(
259 -1,
260 -1,
261 NULL,
262 STRING_TOKEN (STR_DRV_DIAG_ITEM_LINE),
263 gShellDriver1HiiHandle,
264 HandleIndex1,
265 HandleIndex2,
266 ChildHandleList == NULL?0:ConvertHandleToHandleIndex(ChildHandleList[ChildHandleListLoop])
267 );
268 }
269
270 //
271 // If we are doing a single pass with NULL child jump out after a single loop
272 //
273 if (ChildHandleList == NULL) {
274 break;
275 }
276 }
277 if (AllChilds) {
278 SHELL_FREE_NON_NULL(ChildHandleList);
279 ChildHandleList = NULL;
280 ChildHandleListCount = 0;
281 }
282 }
283 if (ControllerHandle == NULL) {
284 SHELL_FREE_NON_NULL(ControllerHandleList);
285 ControllerHandleList = NULL;
286 ControllerHandleListCount = 0;
287 }
288 }
289 }
290
291 if (DriverHandleList != NULL) {
292 FreePool(DriverHandleList);
293 }
294 if (ControllerHandleList != NULL) {
295 FreePool(ControllerHandleList);
296 }
297 if (ChildHandleList != NULL) {
298 FreePool(ChildHandleList);
299 }
300 return (Status2);
301 }
302
303
304 STATIC CONST SHELL_PARAM_ITEM ParamList[] = {
305 {L"-c", TypeFlag},
306 {L"-s", TypeFlag},
307 {L"-e", TypeFlag},
308 {L"-m", TypeFlag},
309 {L"-l", TypeValue},
310 {NULL, TypeMax}
311 };
312
313 /**
314 Function for 'drvdiag' command.
315
316 @param[in] ImageHandle Handle to the Image (NULL if Internal).
317 @param[in] SystemTable Pointer to the System Table (NULL if Internal).
318 **/
319 SHELL_STATUS
320 EFIAPI
ShellCommandRunDrvDiag(IN EFI_HANDLE ImageHandle,IN EFI_SYSTEM_TABLE * SystemTable)321 ShellCommandRunDrvDiag (
322 IN EFI_HANDLE ImageHandle,
323 IN EFI_SYSTEM_TABLE *SystemTable
324 )
325 {
326 EFI_STATUS Status;
327 LIST_ENTRY *Package;
328 CHAR16 *ProblemParam;
329 SHELL_STATUS ShellStatus;
330 DRV_DIAG_TEST_MODE Mode;
331 CHAR8 *Language;
332 CONST CHAR16 *DriverHandleStr;
333 CONST CHAR16 *ControllerHandleStr;
334 CONST CHAR16 *ChildHandleStr;
335 CONST CHAR16 *Lang;
336 EFI_HANDLE Handle1;
337 EFI_HANDLE Handle2;
338 EFI_HANDLE Handle3;
339 UINT64 Intermediate;
340
341 ShellStatus = SHELL_SUCCESS;
342 Mode = TestModeMax;
343 Language = NULL;
344
345 //
346 // initialize the shell lib (we must be in non-auto-init...)
347 //
348 Status = ShellInitialize();
349 ASSERT_EFI_ERROR(Status);
350
351 Status = CommandInit();
352 ASSERT_EFI_ERROR(Status);
353
354 //
355 // parse the command line
356 //
357 Status = ShellCommandLineParse (ParamList, &Package, &ProblemParam, TRUE);
358 if (EFI_ERROR(Status)) {
359 if (Status == EFI_VOLUME_CORRUPTED && ProblemParam != NULL) {
360 ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_PROBLEM), gShellDriver1HiiHandle, L"drvdiag", ProblemParam);
361 FreePool(ProblemParam);
362 ShellStatus = SHELL_INVALID_PARAMETER;
363 } else {
364 ASSERT(FALSE);
365 }
366 } else {
367 //
368 // if more than 3 'value' parameters (plus the name one) or we have any 2 mode flags
369 //
370 if ((ShellCommandLineGetCount(Package) > 4)
371 ||(ShellCommandLineGetFlag(Package, L"-s") && ShellCommandLineGetFlag(Package, L"-e"))
372 ||(ShellCommandLineGetFlag(Package, L"-s") && ShellCommandLineGetFlag(Package, L"-m"))
373 ||(ShellCommandLineGetFlag(Package, L"-e") && ShellCommandLineGetFlag(Package, L"-m"))
374 ){
375 //
376 // error for too many parameters
377 //
378 ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_TOO_MANY), gShellDriver1HiiHandle, L"drvdiag");
379 ShellStatus = SHELL_INVALID_PARAMETER;
380 } else if ((ShellCommandLineGetFlag(Package, L"-s"))
381 || (ShellCommandLineGetFlag(Package, L"-e"))
382 || (ShellCommandLineGetFlag(Package, L"-m"))
383 ){
384 //
385 // Run the appropriate test
386 //
387 if (ShellCommandLineGetFlag(Package, L"-s")) {
388 Mode = TestModeStandard;
389 } else if (ShellCommandLineGetFlag(Package, L"-e")) {
390 Mode = TestModeExtended;
391 } else if (ShellCommandLineGetFlag(Package, L"-m")) {
392 Mode = TestModeManufacturing;
393 } else {
394 ASSERT(FALSE);
395 }
396 } else {
397 //
398 // Do a listing of what's available to test
399 //
400 Mode = TestModeList;
401 }
402
403 Lang = ShellCommandLineGetValue(Package, L"-l");
404 if (ShellCommandLineGetFlag(Package, L"-l") && Lang == NULL) {
405 ASSERT(Language == NULL);
406 ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_NO_VALUE), gShellDriver1HiiHandle, L"drvdiag", L"-l");
407 ShellCommandLineFreeVarList (Package);
408 return (SHELL_INVALID_PARAMETER);
409 } else if (Lang != NULL) {
410 Language = AllocateZeroPool(StrSize(Lang));
411 AsciiSPrint(Language, StrSize(Lang), "%S", Lang);
412 }
413
414 DriverHandleStr = ShellCommandLineGetRawValue(Package, 1);
415 ControllerHandleStr = ShellCommandLineGetRawValue(Package, 2);
416 ChildHandleStr = ShellCommandLineGetRawValue(Package, 3);
417
418 if (DriverHandleStr == NULL) {
419 Handle1 = NULL;
420 } else {
421 ShellConvertStringToUint64(DriverHandleStr, &Intermediate, TRUE, FALSE);
422 Handle1 = ConvertHandleIndexToHandle((UINTN)Intermediate);
423 }
424 if (ControllerHandleStr == NULL) {
425 Handle2 = NULL;
426 } else {
427 ShellConvertStringToUint64(ControllerHandleStr, &Intermediate, TRUE, FALSE);
428 Handle2 = ConvertHandleIndexToHandle((UINTN)Intermediate);
429 }
430 if (ChildHandleStr == NULL) {
431 Handle3 = NULL;
432 } else {
433 ShellConvertStringToUint64(ChildHandleStr, &Intermediate, TRUE, FALSE);
434 Handle3 = ConvertHandleIndexToHandle((UINTN)Intermediate);
435 }
436
437 Status = DoDiagnostics (
438 Mode,
439 Language,
440 ShellCommandLineGetFlag(Package, L"-c"),
441 Handle1,
442 Handle2,
443 Handle3
444 );
445
446 SHELL_FREE_NON_NULL(Language);
447 ShellCommandLineFreeVarList (Package);
448
449 }
450 if (ShellStatus == SHELL_SUCCESS) {
451 if (Status == EFI_SECURITY_VIOLATION) {
452 ShellStatus = SHELL_SECURITY_VIOLATION;
453 } else if (Status == EFI_INVALID_PARAMETER) {
454 ShellStatus = SHELL_INVALID_PARAMETER;
455 } else if (Status == EFI_NOT_FOUND) {
456 ShellStatus = SHELL_NOT_FOUND;
457 } else if (EFI_ERROR(Status)) {
458 ShellStatus = SHELL_NOT_FOUND;
459 }
460 }
461
462 return (ShellStatus);
463 }
464