]> git.proxmox.com Git - mirror_edk2.git/blob - IntelFrameworkModulePkg/Universal/BdsDxe/DeviceMngr/DeviceManager.c
Add the missing HiiVendor DevicePath for new added DriverHealth Form.
[mirror_edk2.git] / IntelFrameworkModulePkg / Universal / BdsDxe / DeviceMngr / DeviceManager.c
1 /** @file
2 The platform device manager reference implementation
3
4 Copyright (c) 2004 - 2009, Intel Corporation. <BR>
5 All rights reserved. This program and the accompanying materials
6 are licensed and made available under the terms and conditions of the BSD License
7 which accompanies this distribution. The full text of the license may be found at
8 http://opensource.org/licenses/bsd-license.php
9
10 THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
11 WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
12
13 **/
14
15 #include "DeviceManager.h"
16
17 DEVICE_MANAGER_CALLBACK_DATA gDeviceManagerPrivate = {
18 DEVICE_MANAGER_CALLBACK_DATA_SIGNATURE,
19 NULL,
20 NULL,
21 NULL,
22 NULL,
23 {
24 FakeExtractConfig,
25 FakeRouteConfig,
26 DeviceManagerCallback
27 },
28 {
29 FakeExtractConfig,
30 FakeRouteConfig,
31 DriverHealthCallback
32 }
33 };
34
35 EFI_GUID mDeviceManagerGuid = DEVICE_MANAGER_FORMSET_GUID;
36 EFI_GUID mDriverHealthGuid = DRIVER_HEALTH_FORMSET_GUID;
37
38 DEVICE_MANAGER_MENU_ITEM mDeviceManagerMenuItemTable[] = {
39 { STRING_TOKEN (STR_DISK_DEVICE), EFI_DISK_DEVICE_CLASS },
40 { STRING_TOKEN (STR_VIDEO_DEVICE), EFI_VIDEO_DEVICE_CLASS },
41 { STRING_TOKEN (STR_NETWORK_DEVICE), EFI_NETWORK_DEVICE_CLASS },
42 { STRING_TOKEN (STR_INPUT_DEVICE), EFI_INPUT_DEVICE_CLASS },
43 { STRING_TOKEN (STR_ON_BOARD_DEVICE), EFI_ON_BOARD_DEVICE_CLASS },
44 { STRING_TOKEN (STR_OTHER_DEVICE), EFI_OTHER_DEVICE_CLASS }
45 };
46
47 HII_VENDOR_DEVICE_PATH mDeviceManagerHiiVendorDevicePath = {
48 {
49 {
50 HARDWARE_DEVICE_PATH,
51 HW_VENDOR_DP,
52 {
53 (UINT8) (sizeof (VENDOR_DEVICE_PATH)),
54 (UINT8) ((sizeof (VENDOR_DEVICE_PATH)) >> 8)
55 }
56 },
57 //
58 // {102579A0-3686-466e-ACD8-80C087044F4A}
59 //
60 { 0x102579a0, 0x3686, 0x466e, { 0xac, 0xd8, 0x80, 0xc0, 0x87, 0x4, 0x4f, 0x4a } }
61 },
62 {
63 END_DEVICE_PATH_TYPE,
64 END_ENTIRE_DEVICE_PATH_SUBTYPE,
65 {
66 (UINT8) (END_DEVICE_PATH_LENGTH),
67 (UINT8) ((END_DEVICE_PATH_LENGTH) >> 8)
68 }
69 }
70 };
71
72 HII_VENDOR_DEVICE_PATH mDriverHealthHiiVendorDevicePath = {
73 {
74 {
75 HARDWARE_DEVICE_PATH,
76 HW_VENDOR_DP,
77 {
78 (UINT8) (sizeof (VENDOR_DEVICE_PATH)),
79 (UINT8) ((sizeof (VENDOR_DEVICE_PATH)) >> 8)
80 }
81 },
82 //
83 // {D8F76651-1675-4986-BED4-3824B2F1F4C8}
84 //
85 { 0xd8f76651, 0x1675, 0x4986, { 0xbe, 0xd4, 0x38, 0x24, 0xb2, 0xf1, 0xf4, 0xc8 } }
86 },
87 {
88 END_DEVICE_PATH_TYPE,
89 END_ENTIRE_DEVICE_PATH_SUBTYPE,
90 {
91 (UINT8) (END_DEVICE_PATH_LENGTH),
92 (UINT8) ((END_DEVICE_PATH_LENGTH) >> 8)
93 }
94 }
95 };
96
97 /**
98 This function is invoked if user selected a interactive opcode from Device Manager's
99 Formset. The decision by user is saved to gCallbackKey for later processing. If
100 user set VBIOS, the new value is saved to EFI variable.
101
102 @param This Points to the EFI_HII_CONFIG_ACCESS_PROTOCOL.
103 @param Action Specifies the type of action taken by the browser.
104 @param QuestionId A unique value which is sent to the original exporting driver
105 so that it can identify the type of data to expect.
106 @param Type The type of value for the question.
107 @param Value A pointer to the data being sent to the original exporting driver.
108 @param ActionRequest On return, points to the action requested by the callback function.
109
110 @retval EFI_SUCCESS The callback successfully handled the action.
111 @retval EFI_INVALID_PARAMETER The setup browser call this function with invalid parameters.
112
113 **/
114 EFI_STATUS
115 EFIAPI
116 DeviceManagerCallback (
117 IN CONST EFI_HII_CONFIG_ACCESS_PROTOCOL *This,
118 IN EFI_BROWSER_ACTION Action,
119 IN EFI_QUESTION_ID QuestionId,
120 IN UINT8 Type,
121 IN EFI_IFR_TYPE_VALUE *Value,
122 OUT EFI_BROWSER_ACTION_REQUEST *ActionRequest
123 )
124 {
125 if ((Value == NULL) || (ActionRequest == NULL)) {
126 return EFI_INVALID_PARAMETER;
127 }
128
129 gCallbackKey = QuestionId;
130
131 //
132 // Request to exit SendForm(), so as to switch to selected form
133 //
134 *ActionRequest = EFI_BROWSER_ACTION_REQUEST_EXIT;
135
136 return EFI_SUCCESS;
137 }
138
139 /**
140
141 This function registers HII packages to HII database.
142
143 @retval EFI_SUCCESS HII packages for the Device Manager were registered successfully.
144 @retval EFI_OUT_OF_RESOURCES HII packages for the Device Manager failed to be registered.
145
146 **/
147 EFI_STATUS
148 InitializeDeviceManager (
149 VOID
150 )
151 {
152 EFI_STATUS Status;
153
154 //
155 // Install Device Path Protocol and Config Access protocol to driver handle
156 //
157 Status = gBS->InstallMultipleProtocolInterfaces (
158 &gDeviceManagerPrivate.DriverHandle,
159 &gEfiDevicePathProtocolGuid,
160 &mDeviceManagerHiiVendorDevicePath,
161 &gEfiHiiConfigAccessProtocolGuid,
162 &gDeviceManagerPrivate.ConfigAccess,
163 NULL
164 );
165 ASSERT_EFI_ERROR (Status);
166
167 Status = gBS->InstallMultipleProtocolInterfaces (
168 &gDeviceManagerPrivate.DriverHealthHandle,
169 &gEfiDevicePathProtocolGuid,
170 &mDriverHealthHiiVendorDevicePath,
171 &gEfiHiiConfigAccessProtocolGuid,
172 &gDeviceManagerPrivate.DriverHealthConfigAccess,
173 NULL
174 );
175 ASSERT_EFI_ERROR (Status);
176
177 //
178 // Publish our HII data
179 //
180 gDeviceManagerPrivate.HiiHandle = HiiAddPackages (
181 &mDeviceManagerGuid,
182 gDeviceManagerPrivate.DriverHandle,
183 DeviceManagerVfrBin,
184 BdsDxeStrings,
185 NULL
186 );
187 if (gDeviceManagerPrivate.HiiHandle == NULL) {
188 return EFI_OUT_OF_RESOURCES;
189 } else {
190 Status = EFI_SUCCESS;
191 }
192
193 //
194 // Publish Driver Health HII data
195 //
196 gDeviceManagerPrivate.DriverHealthHiiHandle = HiiAddPackages (
197 &mDeviceManagerGuid,
198 gDeviceManagerPrivate.DriverHealthHandle,
199 DriverHealthVfrBin,
200 BdsDxeStrings,
201 NULL
202 );
203 if (gDeviceManagerPrivate.DriverHealthHiiHandle == NULL) {
204 Status = EFI_OUT_OF_RESOURCES;
205 } else {
206 Status = EFI_SUCCESS;
207 }
208
209 return Status;
210 }
211
212 /**
213 Extract the displayed formset for given HII handle and class guid.
214
215 @param Handle The HII handle.
216 @param SetupClassGuid The class guid specifies which form set will be displayed.
217 @param FormSetTitle Formset title string.
218 @param FormSetHelp Formset help string.
219
220 @retval TRUE The formset for given HII handle will be displayed.
221 @return FALSE The formset for given HII handle will not be displayed.
222
223 **/
224 BOOLEAN
225 ExtractDisplayedHiiFormFromHiiHandle (
226 IN EFI_HII_HANDLE Handle,
227 IN EFI_GUID *SetupClassGuid,
228 OUT EFI_STRING_ID *FormSetTitle,
229 OUT EFI_STRING_ID *FormSetHelp
230 )
231 {
232 EFI_STATUS Status;
233 UINTN BufferSize;
234 EFI_HII_PACKAGE_LIST_HEADER *HiiPackageList;
235 UINT8 *Package;
236 UINT8 *OpCodeData;
237 UINT32 Offset;
238 UINT32 Offset2;
239 UINT32 PackageListLength;
240 EFI_HII_PACKAGE_HEADER PackageHeader;
241 EFI_GUID *ClassGuid;
242 UINT8 ClassGuidNum;
243
244 ASSERT (Handle != NULL);
245 ASSERT (SetupClassGuid != NULL);
246 ASSERT (FormSetTitle != NULL);
247 ASSERT (FormSetHelp != NULL);
248
249 *FormSetTitle = 0;
250 *FormSetHelp = 0;
251 ClassGuidNum = 0;
252 ClassGuid = NULL;
253
254 //
255 // Get HII PackageList
256 //
257 BufferSize = 0;
258 HiiPackageList = NULL;
259 Status = gHiiDatabase->ExportPackageLists (gHiiDatabase, Handle, &BufferSize, HiiPackageList);
260 //
261 // Handle is a invalid handle. Check if Handle is corrupted.
262 //
263 ASSERT (Status != EFI_NOT_FOUND);
264 //
265 // The return status should always be EFI_BUFFER_TOO_SMALL as input buffer's size is 0.
266 //
267 ASSERT (Status == EFI_BUFFER_TOO_SMALL);
268
269 HiiPackageList = AllocatePool (BufferSize);
270 ASSERT (HiiPackageList != NULL);
271
272 Status = gHiiDatabase->ExportPackageLists (gHiiDatabase, Handle, &BufferSize, HiiPackageList);
273 if (EFI_ERROR (Status)) {
274 return FALSE;
275 }
276
277 //
278 // Get Form package from this HII package List
279 //
280 Offset = sizeof (EFI_HII_PACKAGE_LIST_HEADER);
281 Offset2 = 0;
282 PackageListLength = ReadUnaligned32 (&HiiPackageList->PackageLength);
283
284 while (Offset < PackageListLength) {
285 Package = ((UINT8 *) HiiPackageList) + Offset;
286 CopyMem (&PackageHeader, Package, sizeof (EFI_HII_PACKAGE_HEADER));
287
288 if (PackageHeader.Type == EFI_HII_PACKAGE_FORMS) {
289 //
290 // Search FormSet Opcode in this Form Package
291 //
292 Offset2 = sizeof (EFI_HII_PACKAGE_HEADER);
293 while (Offset2 < PackageHeader.Length) {
294 OpCodeData = Package + Offset2;
295
296 if (((EFI_IFR_OP_HEADER *) OpCodeData)->OpCode == EFI_IFR_FORM_SET_OP) {
297 //
298 // Find FormSet OpCode
299 //
300 ClassGuidNum = ((EFI_IFR_FORM_SET *) OpCodeData)->Flags;
301 ClassGuid = (EFI_GUID *) (VOID *)(OpCodeData + sizeof (EFI_IFR_FORM_SET));
302 while (ClassGuidNum-- > 0) {
303 if (CompareGuid (SetupClassGuid, ClassGuid)) {
304 CopyMem (FormSetTitle, &((EFI_IFR_FORM_SET *) OpCodeData)->FormSetTitle, sizeof (EFI_STRING_ID));
305 CopyMem (FormSetHelp, &((EFI_IFR_FORM_SET *) OpCodeData)->Help, sizeof (EFI_STRING_ID));
306 FreePool (HiiPackageList);
307 return TRUE;
308 }
309 }
310 }
311
312 //
313 // Go to next opcode
314 //
315 Offset2 += ((EFI_IFR_OP_HEADER *) OpCodeData)->Length;
316 }
317 }
318
319 //
320 // Go to next package
321 //
322 Offset += PackageHeader.Length;
323 }
324
325 FreePool (HiiPackageList);
326
327 return FALSE;
328 }
329
330 /**
331 Call the browser and display the device manager to allow user
332 to configure the platform.
333
334 This function create the dynamic content for device manager. It includes
335 section header for all class of devices, one-of opcode to set VBIOS.
336
337 @retval EFI_SUCCESS Operation is successful.
338 @return Other values if failed to clean up the dynamic content from HII
339 database.
340
341 **/
342 EFI_STATUS
343 CallDeviceManager (
344 VOID
345 )
346 {
347 EFI_STATUS Status;
348 UINTN Index;
349 EFI_STRING String;
350 EFI_STRING_ID Token;
351 EFI_STRING_ID TokenHelp;
352 EFI_HII_HANDLE *HiiHandles;
353 EFI_HII_HANDLE HiiHandle;
354 EFI_STRING_ID FormSetTitle;
355 EFI_STRING_ID FormSetHelp;
356 EFI_BROWSER_ACTION_REQUEST ActionRequest;
357 VOID *StartOpCodeHandle;
358 VOID *EndOpCodeHandle;
359 EFI_IFR_GUID_LABEL *StartLabel;
360 EFI_IFR_GUID_LABEL *EndLabel;
361 UINTN NumHandles;
362 EFI_HANDLE *DriverHealthHandles;
363
364 HiiHandles = NULL;
365 Status = EFI_SUCCESS;
366 gCallbackKey = 0;
367 NumHandles = 0;
368 DriverHealthHandles = NULL;
369
370 //
371 // Connect all prior to entering the platform setup menu.
372 //
373 if (!gConnectAllHappened) {
374 BdsLibConnectAllDriversToAllControllers ();
375 gConnectAllHappened = TRUE;
376 }
377 //
378 // Create Subtitle OpCodes
379 //
380 //
381 // Allocate space for creation of UpdateData Buffer
382 //
383 StartOpCodeHandle = HiiAllocateOpCodeHandle ();
384 ASSERT (StartOpCodeHandle != NULL);
385
386 EndOpCodeHandle = HiiAllocateOpCodeHandle ();
387 ASSERT (EndOpCodeHandle != NULL);
388
389 //
390 // Create Hii Extend Label OpCode as the start opcode
391 //
392 StartLabel = (EFI_IFR_GUID_LABEL *) HiiCreateGuidOpCode (StartOpCodeHandle, &gEfiIfrTianoGuid, NULL, sizeof (EFI_IFR_GUID_LABEL));
393 StartLabel->ExtendOpCode = EFI_IFR_EXTEND_OP_LABEL;
394 StartLabel->Number = LABEL_DEVICES_LIST;
395
396 //
397 // Create Hii Extend Label OpCode as the end opcode
398 //
399 EndLabel = (EFI_IFR_GUID_LABEL *) HiiCreateGuidOpCode (EndOpCodeHandle, &gEfiIfrTianoGuid, NULL, sizeof (EFI_IFR_GUID_LABEL));
400 EndLabel->ExtendOpCode = EFI_IFR_EXTEND_OP_LABEL;
401 EndLabel->Number = LABEL_END;
402
403 HiiCreateSubTitleOpCode (StartOpCodeHandle, STRING_TOKEN (STR_DEVICES_LIST), 0, 0, 1);
404
405 //
406 // Get all the Hii handles
407 //
408 HiiHandles = HiiGetHiiHandles (NULL);
409 ASSERT (HiiHandles != NULL);
410
411 HiiHandle = gDeviceManagerPrivate.HiiHandle;
412
413 //
414 // Search for formset of each class type
415 //
416 for (Index = 0; HiiHandles[Index] != NULL; Index++) {
417 if (!ExtractDisplayedHiiFormFromHiiHandle (HiiHandles[Index], &gEfiHiiPlatformSetupFormsetGuid, &FormSetTitle, &FormSetHelp)) {
418 continue;
419 }
420
421 String = HiiGetString (HiiHandles[Index], FormSetTitle, NULL);
422 if (String == NULL) {
423 String = HiiGetString (HiiHandle, STR_MISSING_STRING, NULL);
424 ASSERT (String != NULL);
425 }
426 Token = HiiSetString (HiiHandle, 0, String, NULL);
427 FreePool (String);
428
429 String = HiiGetString (HiiHandles[Index], FormSetHelp, NULL);
430 if (String == NULL) {
431 String = HiiGetString (HiiHandle, STR_MISSING_STRING, NULL);
432 ASSERT (String != NULL);
433 }
434 TokenHelp = HiiSetString (HiiHandle, 0, String, NULL);
435 FreePool (String);
436
437 HiiCreateActionOpCode (
438 StartOpCodeHandle,
439 (EFI_QUESTION_ID) (Index + DEVICE_KEY_OFFSET),
440 Token,
441 TokenHelp,
442 EFI_IFR_FLAG_CALLBACK,
443 0
444 );
445 }
446
447 //
448 // Add End Opcode for Subtitle
449 //
450 HiiCreateEndOpCode (StartOpCodeHandle);
451
452 Status = gBS->LocateHandleBuffer (
453 ByProtocol,
454 &gEfiDriverHealthProtocolGuid,
455 NULL,
456 &NumHandles,
457 &DriverHealthHandles
458 );
459 //
460 // If there are no drivers installed driver health protocol
461 //
462 if (NumHandles == 0) {
463 HiiSetString (HiiHandle, STRING_TOKEN (STR_DM_DRIVER_HEALTH_TITLE), GetStringById (STRING_TOKEN (STR_EMPTY_STRING)), NULL);
464 HiiSetString (HiiHandle, STRING_TOKEN (STR_DRIVER_HEALTH_ALL_HEALTHY), GetStringById (STRING_TOKEN (STR_EMPTY_STRING)), NULL);
465 } else {
466 //
467 // Check All Driver health status
468 //
469 if (!PlaformHealthStatusCheck ()) {
470 //
471 // At least one driver in the platform are not in healthy status
472 //
473 HiiSetString (HiiHandle, STRING_TOKEN (STR_DRIVER_HEALTH_ALL_HEALTHY), GetStringById (STRING_TOKEN (STR_DRIVER_NOT_HEALTH)), NULL);
474 } else {
475 //
476 // For the string of STR_DRIVER_HEALTH_ALL_HEALTHY previously has been updated and we need to update it while re-entry.
477 //
478 HiiSetString (HiiHandle, STRING_TOKEN (STR_DRIVER_HEALTH_ALL_HEALTHY), GetStringById (STRING_TOKEN (STR_DRIVER_HEALTH_ALL_HEALTHY)), NULL);
479 }
480 }
481
482 HiiUpdateForm (
483 HiiHandle,
484 &mDeviceManagerGuid,
485 DEVICE_MANAGER_FORM_ID,
486 StartOpCodeHandle,
487 EndOpCodeHandle
488 );
489
490 ActionRequest = EFI_BROWSER_ACTION_REQUEST_NONE;
491 Status = gFormBrowser2->SendForm (
492 gFormBrowser2,
493 &HiiHandle,
494 1,
495 &mDeviceManagerGuid,
496 0,
497 NULL,
498 &ActionRequest
499 );
500 if (ActionRequest == EFI_BROWSER_ACTION_REQUEST_RESET) {
501 EnableResetRequired ();
502 }
503
504 //
505 // We will have returned from processing a callback - user either hit ESC to exit, or selected
506 // a target to display
507 //
508 if ((gCallbackKey != 0) && (gCallbackKey != DEVICE_MANAGER_KEY_DRIVER_HEALTH)) {
509 ActionRequest = EFI_BROWSER_ACTION_REQUEST_NONE;
510 Status = gFormBrowser2->SendForm (
511 gFormBrowser2,
512 &HiiHandles[gCallbackKey - DEVICE_KEY_OFFSET],
513 1,
514 NULL,
515 0,
516 NULL,
517 &ActionRequest
518 );
519
520 if (ActionRequest == EFI_BROWSER_ACTION_REQUEST_RESET) {
521 EnableResetRequired ();
522 }
523
524 //
525 // Force return to Device Manager
526 //
527 gCallbackKey = FRONT_PAGE_KEY_DEVICE_MANAGER;
528 }
529
530 //
531 // Driver Health item chose.
532 //
533 if (gCallbackKey == DEVICE_MANAGER_KEY_DRIVER_HEALTH) {
534 CallDriverHealth ();
535 //
536 // Force return to Device Manager
537 //
538 gCallbackKey = FRONT_PAGE_KEY_DEVICE_MANAGER;
539 }
540
541 //
542 // Cleanup dynamic created strings in HII database by reinstall the packagelist
543 //
544 HiiRemovePackages (HiiHandle);
545
546 gDeviceManagerPrivate.HiiHandle = HiiAddPackages (
547 &mDeviceManagerGuid,
548 gDeviceManagerPrivate.DriverHandle,
549 DeviceManagerVfrBin,
550 BdsDxeStrings,
551 NULL
552 );
553 if (gDeviceManagerPrivate.HiiHandle == NULL) {
554 Status = EFI_OUT_OF_RESOURCES;
555 } else {
556 Status = EFI_SUCCESS;
557 }
558
559 HiiFreeOpCodeHandle (StartOpCodeHandle);
560 HiiFreeOpCodeHandle (EndOpCodeHandle);
561 FreePool (HiiHandles);
562
563 return Status;
564 }
565
566 /**
567 This function is invoked if user selected a interactive opcode from Driver Health's
568 Formset. The decision by user is saved to gCallbackKey for later processing.
569
570 @param This Points to the EFI_HII_CONFIG_ACCESS_PROTOCOL.
571 @param Action Specifies the type of action taken by the browser.
572 @param QuestionId A unique value which is sent to the original exporting driver
573 so that it can identify the type of data to expect.
574 @param Type The type of value for the question.
575 @param Value A pointer to the data being sent to the original exporting driver.
576 @param ActionRequest On return, points to the action requested by the callback function.
577
578 @retval EFI_SUCCESS The callback successfully handled the action.
579 @retval EFI_INVALID_PARAMETER The setup browser call this function with invalid parameters.
580
581 **/
582 EFI_STATUS
583 EFIAPI
584 DriverHealthCallback (
585 IN CONST EFI_HII_CONFIG_ACCESS_PROTOCOL *This,
586 IN EFI_BROWSER_ACTION Action,
587 IN EFI_QUESTION_ID QuestionId,
588 IN UINT8 Type,
589 IN EFI_IFR_TYPE_VALUE *Value,
590 OUT EFI_BROWSER_ACTION_REQUEST *ActionRequest
591 )
592 {
593 if ((Value == NULL) || (ActionRequest == NULL)) {
594 return EFI_INVALID_PARAMETER;
595 }
596
597 gCallbackKey = QuestionId;
598
599 //
600 // Request to exit SendForm(), so as to switch to selected form
601 //
602 *ActionRequest = EFI_BROWSER_ACTION_REQUEST_EXIT;
603
604 return EFI_SUCCESS;
605 }
606
607 /**
608 Collect and display the platform's driver health relative information, allow user to do interactive
609 operation while the platform is unhealthy.
610
611 This function display a form which divided into two parts. The one list all modules which has installed
612 driver health protocol. The list usually contain driver name, controller name, and it's health info.
613 While the driver name can't be retrieved, will use device path as backup. The other part of the form provide
614 a choice to the user to repair all platform.
615
616 **/
617 VOID
618 CallDriverHealth (
619 VOID
620 )
621 {
622 EFI_STATUS Status;
623 EFI_HII_HANDLE HiiHandle;
624 EFI_BROWSER_ACTION_REQUEST ActionRequest;
625 EFI_IFR_GUID_LABEL *StartLabel;
626 EFI_IFR_GUID_LABEL *StartLabelRepair;
627 EFI_IFR_GUID_LABEL *EndLabel;
628 EFI_IFR_GUID_LABEL *EndLabelRepair;
629 VOID *StartOpCodeHandle;
630 VOID *EndOpCodeHandle;
631 VOID *StartOpCodeHandleRepair;
632 VOID *EndOpCodeHandleRepair;
633 UINTN Index;
634 EFI_STRING_ID Token;
635 EFI_STRING_ID TokenHelp;
636 EFI_STRING String;
637 EFI_STRING TmpString;
638 EFI_STRING DriverName;
639 EFI_STRING ControllerName;
640 LIST_ENTRY DriverHealthList;
641 DRIVER_HEALTH_INFO *DriverHealthInfo;
642 LIST_ENTRY *Link;
643 EFI_DEVICE_PATH_PROTOCOL *DriverDevicePath;
644 UINTN Length;
645
646 HiiHandle = gDeviceManagerPrivate.DriverHealthHiiHandle;
647 Index = 0;
648 Length = 0;
649 DriverHealthInfo = NULL;
650 DriverDevicePath = NULL;
651 InitializeListHead (&DriverHealthList);
652
653 //
654 // Allocate space for creation of UpdateData Buffer
655 //
656 StartOpCodeHandle = HiiAllocateOpCodeHandle ();
657 ASSERT (StartOpCodeHandle != NULL);
658
659 EndOpCodeHandle = HiiAllocateOpCodeHandle ();
660 ASSERT (EndOpCodeHandle != NULL);
661
662 StartOpCodeHandleRepair = HiiAllocateOpCodeHandle ();
663 ASSERT (StartOpCodeHandleRepair != NULL);
664
665 EndOpCodeHandleRepair = HiiAllocateOpCodeHandle ();
666 ASSERT (EndOpCodeHandleRepair != NULL);
667
668 //
669 // Create Hii Extend Label OpCode as the start opcode
670 //
671 StartLabel = (EFI_IFR_GUID_LABEL *) HiiCreateGuidOpCode (StartOpCodeHandle, &gEfiIfrTianoGuid, NULL, sizeof (EFI_IFR_GUID_LABEL));
672 StartLabel->ExtendOpCode = EFI_IFR_EXTEND_OP_LABEL;
673 StartLabel->Number = LABEL_DRIVER_HEALTH;
674
675 //
676 // Create Hii Extend Label OpCode as the start opcode
677 //
678 StartLabelRepair = (EFI_IFR_GUID_LABEL *) HiiCreateGuidOpCode (StartOpCodeHandleRepair, &gEfiIfrTianoGuid, NULL, sizeof (EFI_IFR_GUID_LABEL));
679 StartLabelRepair->ExtendOpCode = EFI_IFR_EXTEND_OP_LABEL;
680 StartLabelRepair->Number = LABEL_DRIVER_HEALTH_REAPIR_ALL;
681
682 //
683 // Create Hii Extend Label OpCode as the end opcode
684 //
685 EndLabel = (EFI_IFR_GUID_LABEL *) HiiCreateGuidOpCode (EndOpCodeHandle, &gEfiIfrTianoGuid, NULL, sizeof (EFI_IFR_GUID_LABEL));
686 EndLabel->ExtendOpCode = EFI_IFR_EXTEND_OP_LABEL;
687 EndLabel->Number = LABEL_DRIVER_HEALTH_END;
688
689 //
690 // Create Hii Extend Label OpCode as the end opcode
691 //
692 EndLabelRepair = (EFI_IFR_GUID_LABEL *) HiiCreateGuidOpCode (EndOpCodeHandleRepair, &gEfiIfrTianoGuid, NULL, sizeof (EFI_IFR_GUID_LABEL));
693 EndLabelRepair->ExtendOpCode = EFI_IFR_EXTEND_OP_LABEL;
694 EndLabelRepair->Number = LABEL_DRIVER_HEALTH_REAPIR_ALL_END;
695
696 HiiCreateSubTitleOpCode (StartOpCodeHandle, STRING_TOKEN (STR_DH_STATUS_LIST), 0, 0, 1);
697
698 Status = GetAllControllersHealthStatus (&DriverHealthList);
699 ASSERT (Status != EFI_OUT_OF_RESOURCES);
700
701 Link = GetFirstNode (&DriverHealthList);
702
703 while (!IsNull (&DriverHealthList, Link)) {
704 DriverHealthInfo = DEVICE_MANAGER_HEALTH_INFO_FROM_LINK (Link);
705
706 //
707 // Assume no line strings is longer than 512 bytes.
708 //
709 String = (EFI_STRING) AllocateZeroPool (0x200);
710 ASSERT (String != NULL);
711
712 Status = DriverHealthGetDriverName (DriverHealthInfo->DriverHandle, &DriverName);
713 if (EFI_ERROR (Status)) {
714 //
715 // Can not get the Driver name, so use the Device path
716 //
717 DriverDevicePath = DevicePathFromHandle (DriverHealthInfo->DriverHandle);
718 DriverName = DevicePathToStr (DriverDevicePath);
719 }
720 //
721 // Add the Driver name & Controller name into FormSetTitle string
722 //
723 StrnCat (String, DriverName, StrLen (DriverName));
724
725
726 Status = DriverHealthGetControllerName (
727 DriverHealthInfo->DriverHandle,
728 DriverHealthInfo->ControllerHandle,
729 DriverHealthInfo->ChildHandle,
730 &ControllerName
731 );
732
733 if (!EFI_ERROR (Status)) {
734 //
735 // Can not get the Controller name, just let it empty.
736 //
737 StrnCat (String, L" ", StrLen (L" "));
738 StrnCat (String, ControllerName, StrLen (ControllerName));
739 }
740
741 //
742 // Add the message of the Module itself provided after the string item.
743 //
744 if ((DriverHealthInfo->MessageList != NULL) && (DriverHealthInfo->MessageList->StringId != 0)) {
745 StrnCat (String, L" ", StrLen (L" "));
746 TmpString = HiiGetString (
747 DriverHealthInfo->MessageList->HiiHandle,
748 DriverHealthInfo->MessageList->StringId,
749 NULL
750 );
751 //
752 // Assert if can not retrieve the message string
753 //
754 ASSERT (TmpString != NULL);
755 StrnCat (String, TmpString, StrLen (TmpString));
756 FreePool (TmpString);
757 } else {
758 //
759 // Update the string will be displayed base on the driver's health status
760 //
761 switch(DriverHealthInfo->HealthStatus) {
762 case EfiDriverHealthStatusRepairRequired:
763 Length = StrLen (GetStringById (STRING_TOKEN (STR_REPAIR_REQUIRED)));
764 StrnCat (String, GetStringById (STRING_TOKEN (STR_REPAIR_REQUIRED)), Length);
765 break;
766 case EfiDriverHealthStatusConfigurationRequired:
767 Length = StrLen (GetStringById (STRING_TOKEN (STR_CONFIGURATION_REQUIRED)));
768 StrnCat (String, GetStringById (STRING_TOKEN (STR_CONFIGURATION_REQUIRED)), Length);
769 break;
770 case EfiDriverHealthStatusFailed:
771 Length = StrLen (GetStringById (STRING_TOKEN (STR_OPERATION_FAILED)));
772 StrnCat (String, GetStringById (STRING_TOKEN (STR_OPERATION_FAILED)), Length);
773 break;
774 case EfiDriverHealthStatusReconnectRequired:
775 Length = StrLen (GetStringById (STRING_TOKEN (STR_RECONNECT_REQUIRED)));
776 StrnCat (String, GetStringById (STRING_TOKEN (STR_RECONNECT_REQUIRED)), Length);
777 break;
778 case EfiDriverHealthStatusRebootRequired:
779 Length = StrLen (GetStringById (STRING_TOKEN (STR_REBOOT_REQUIRED)));
780 StrnCat (String, GetStringById (STRING_TOKEN (STR_REBOOT_REQUIRED)), Length);
781 break;
782 default:
783 Length = StrLen (GetStringById (STRING_TOKEN (STR_DRIVER_HEALTH_HEALTHY)));
784 StrnCat (String, GetStringById (STRING_TOKEN (STR_DRIVER_HEALTH_HEALTHY)), Length);
785 break;
786 }
787 }
788
789 Token = HiiSetString (HiiHandle, 0, String, NULL);
790 FreePool (String);
791
792 TokenHelp = HiiSetString (HiiHandle, 0, GetStringById( STRING_TOKEN (STR_DH_REPAIR_SINGLE_HELP)), NULL);
793
794 HiiCreateActionOpCode (
795 StartOpCodeHandle,
796 (EFI_QUESTION_ID) (Index + DRIVER_HEALTH_KEY_OFFSET),
797 Token,
798 TokenHelp,
799 EFI_IFR_FLAG_CALLBACK,
800 0
801 );
802 Index++;
803 Link = GetNextNode (&DriverHealthList, Link);
804 }
805
806 //
807 // Add End Opcode for Subtitle
808 //
809 HiiCreateEndOpCode (StartOpCodeHandle);
810
811 HiiCreateSubTitleOpCode (StartOpCodeHandleRepair, STRING_TOKEN (STR_DRIVER_HEALTH_REPAIR_ALL), 0, 0, 1);
812 TokenHelp = HiiSetString (HiiHandle, 0, GetStringById( STRING_TOKEN (STR_DH_REPAIR_ALL_HELP)), NULL);
813
814 if (PlaformHealthStatusCheck ()) {
815 //
816 // No action need to do for the platform
817 //
818 Token = HiiSetString (HiiHandle, 0, GetStringById( STRING_TOKEN (STR_DRIVER_HEALTH_ALL_HEALTHY)), NULL);
819 HiiCreateActionOpCode (
820 StartOpCodeHandleRepair,
821 0,
822 Token,
823 TokenHelp,
824 EFI_IFR_FLAG_READ_ONLY,
825 0
826 );
827 } else {
828 //
829 // Create ActionOpCode only while the platform need to do health related operation.
830 //
831 Token = HiiSetString (HiiHandle, 0, GetStringById( STRING_TOKEN (STR_DH_REPAIR_ALL_TITLE)), NULL);
832 HiiCreateActionOpCode (
833 StartOpCodeHandleRepair,
834 (EFI_QUESTION_ID) DRIVER_HEALTH_REPAIR_ALL_KEY,
835 Token,
836 TokenHelp,
837 EFI_IFR_FLAG_CALLBACK,
838 0
839 );
840 }
841
842 HiiCreateEndOpCode (StartOpCodeHandleRepair);
843
844 Status = HiiUpdateForm (
845 HiiHandle,
846 &mDriverHealthGuid,
847 DRIVER_HEALTH_FORM_ID,
848 StartOpCodeHandle,
849 EndOpCodeHandle
850 );
851 ASSERT (Status != EFI_NOT_FOUND);
852 ASSERT (Status != EFI_BUFFER_TOO_SMALL);
853
854 Status = HiiUpdateForm (
855 HiiHandle,
856 &mDriverHealthGuid,
857 DRIVER_HEALTH_FORM_ID,
858 StartOpCodeHandleRepair,
859 EndOpCodeHandleRepair
860 );
861 ASSERT (Status != EFI_NOT_FOUND);
862 ASSERT (Status != EFI_BUFFER_TOO_SMALL);
863
864 ActionRequest = EFI_BROWSER_ACTION_REQUEST_NONE;
865 Status = gFormBrowser2->SendForm (
866 gFormBrowser2,
867 &HiiHandle,
868 1,
869 &mDriverHealthGuid,
870 DRIVER_HEALTH_FORM_ID,
871 NULL,
872 &ActionRequest
873 );
874 if (ActionRequest == EFI_BROWSER_ACTION_REQUEST_RESET) {
875 EnableResetRequired ();
876 }
877
878 //
879 // We will have returned from processing a callback - user either hit ESC to exit, or selected
880 // a target to display.
881 // Process the diver health status states here.
882 //
883 if (gCallbackKey >= DRIVER_HEALTH_KEY_OFFSET && gCallbackKey != DRIVER_HEALTH_REPAIR_ALL_KEY) {
884 ActionRequest = EFI_BROWSER_ACTION_REQUEST_NONE;
885
886 Link = GetFirstNode (&DriverHealthList);
887 Index = 0;
888
889 while (!IsNull (&DriverHealthList, Link)) {
890 //
891 // Got the item relative node in the List
892 //
893 if (Index == (gCallbackKey - DRIVER_HEALTH_KEY_OFFSET)) {
894 DriverHealthInfo = DEVICE_MANAGER_HEALTH_INFO_FROM_LINK (Link);
895 //
896 // Process the driver's healthy status for the specify module
897 //
898 ProcessSingleControllerHealth (
899 DriverHealthInfo->DriverHealth,
900 DriverHealthInfo->ControllerHandle,
901 DriverHealthInfo->ChildHandle,
902 DriverHealthInfo->HealthStatus,
903 &(DriverHealthInfo->MessageList),
904 DriverHealthInfo->HiiHandle
905 );
906 break;
907 }
908 Index++;
909 Link = GetNextNode (&DriverHealthList, Link);
910 }
911
912 if (ActionRequest == EFI_BROWSER_ACTION_REQUEST_RESET) {
913 EnableResetRequired ();
914 }
915
916 //
917 // Force return to the form of Driver Health in Device Manager
918 //
919 gCallbackKey = DRIVER_HEALTH_RETURN_KEY;
920 }
921
922 //
923 // Repair the whole platform
924 //
925 if (gCallbackKey == DRIVER_HEALTH_REPAIR_ALL_KEY) {
926 ActionRequest = EFI_BROWSER_ACTION_REQUEST_NONE;
927
928 PlatformRepairAll (&DriverHealthList);
929
930 gCallbackKey = DRIVER_HEALTH_RETURN_KEY;
931 }
932
933 //
934 // Cleanup dynamic created strings in HII database by reinstall the packagelist
935 //
936
937 HiiRemovePackages (HiiHandle);
938
939 gDeviceManagerPrivate.DriverHealthHiiHandle = HiiAddPackages (
940 &mDriverHealthGuid,
941 gDeviceManagerPrivate.DriverHealthHandle,
942 DriverHealthVfrBin,
943 BdsDxeStrings,
944 NULL
945 );
946 if (gDeviceManagerPrivate.DriverHealthHiiHandle == NULL) {
947 Status = EFI_OUT_OF_RESOURCES;
948 } else {
949 Status = EFI_SUCCESS;
950 }
951 //
952 // Free driver health info list
953 //
954 while (!IsListEmpty (&DriverHealthList)) {
955
956 Link = GetFirstNode(&DriverHealthList);
957 DriverHealthInfo = DEVICE_MANAGER_HEALTH_INFO_FROM_LINK (Link);
958 RemoveEntryList (Link);
959
960 if (DriverHealthInfo->MessageList != NULL) {
961 FreePool(DriverHealthInfo->MessageList);
962 FreePool (DriverHealthInfo);
963 }
964 }
965
966 HiiFreeOpCodeHandle (StartOpCodeHandle);
967 HiiFreeOpCodeHandle (EndOpCodeHandle);
968 HiiFreeOpCodeHandle (StartOpCodeHandleRepair);
969 HiiFreeOpCodeHandle (EndOpCodeHandleRepair);
970
971 if (gCallbackKey == DRIVER_HEALTH_RETURN_KEY) {
972 //
973 // Force return to Driver Health Form
974 //
975 gCallbackKey = DEVICE_MANAGER_KEY_DRIVER_HEALTH;
976 CallDriverHealth ();
977 }
978 }
979
980
981 /*
982 Check the Driver Health status of a single controller and try to process it if not healthy.
983
984 This function called by CheckAllControllersHealthStatus () function in order to process a specify
985 contoller's health state.
986
987 @param DriverHealth A pointer to the EFI_DRIVER_HEALTH_PROTOCOL instance.
988 @param ControllerHandle The class guid specifies which form set will be displayed.
989 @param ChildHandle The handle of the child controller to retrieve the health
990 status on. This is an optional parameter that may be NULL.
991 @param HealthStatus The health status of the controller.
992 @param MessageList An array of warning or error messages associated
993 with the controller specified by ControllerHandle and
994 ChildHandle. This is an optional parameter that may be NULL.
995 @param FormHiiHandle The HII handle for an HII form associated with the
996 controller specified by ControllerHandle and ChildHandle.
997
998 @retval EFI_INVALID_PARAMETER HealthStatus or DriverHealth is NULL.
999 @retval HealthStatus The Health status of specify controller.
1000 @retval EFI_OUT_OF_RESOURCES The list of Driver Health Protocol handles can not be retrieved.
1001 @retval EFI_NOT_FOUND No controller in the platform install Driver Health Protocol.
1002 @retval EFI_SUCCESS The Health related operation has been taken successfully.
1003
1004 */
1005 EFI_STATUS
1006 EFIAPI
1007 GetSingleControllerHealthStatus (
1008 IN OUT LIST_ENTRY *DriverHealthList,
1009 IN EFI_HANDLE DriverHandle,
1010 IN EFI_HANDLE ControllerHandle, OPTIONAL
1011 IN EFI_HANDLE ChildHandle, OPTIONAL
1012 IN EFI_DRIVER_HEALTH_PROTOCOL *DriverHealth,
1013 IN EFI_DRIVER_HEALTH_STATUS *HealthStatus
1014 )
1015 {
1016 EFI_STATUS Status;
1017 EFI_DRIVER_HEALTH_HII_MESSAGE *MessageList;
1018 EFI_HII_HANDLE FormHiiHandle;
1019 DRIVER_HEALTH_INFO *DriverHealthInfo;
1020
1021 if (HealthStatus == NULL) {
1022 //
1023 // If HealthStatus is NULL, then return EFI_INVALID_PARAMETER
1024 //
1025 return EFI_INVALID_PARAMETER;
1026 }
1027
1028 //
1029 // Assume the HealthStatus is healthy
1030 //
1031 *HealthStatus = EfiDriverHealthStatusHealthy;
1032
1033 if (DriverHealth == NULL) {
1034 //
1035 // If DriverHealth is NULL, then return EFI_INVALID_PARAMETER
1036 //
1037 return EFI_INVALID_PARAMETER;
1038 }
1039
1040 if (ControllerHandle == NULL) {
1041 //
1042 // If ControllerHandle is NULL, the return the cumulative health status of the driver
1043 //
1044 Status = DriverHealth->GetHealthStatus (DriverHealth, NULL, NULL, HealthStatus, NULL, NULL);
1045 if (*HealthStatus == EfiDriverHealthStatusHealthy) {
1046 //
1047 // Add the driver health related information into the list
1048 //
1049 DriverHealthInfo = AllocateZeroPool (sizeof (DRIVER_HEALTH_INFO));
1050 if (DriverHealthInfo == NULL) {
1051 return EFI_OUT_OF_RESOURCES;
1052 }
1053
1054 DriverHealthInfo->Signature = DEVICE_MANAGER_DRIVER_HEALTH_INFO_SIGNATURE;
1055 DriverHealthInfo->DriverHandle = DriverHandle;
1056 DriverHealthInfo->ControllerHandle = NULL;
1057 DriverHealthInfo->ChildHandle = NULL;
1058 DriverHealthInfo->HiiHandle = NULL;
1059 DriverHealthInfo->DriverHealth = DriverHealth;
1060 DriverHealthInfo->MessageList = NULL;
1061 DriverHealthInfo->HealthStatus = *HealthStatus;
1062
1063 InsertTailList (DriverHealthList, &DriverHealthInfo->Link);
1064 }
1065 return Status;
1066 }
1067
1068 MessageList = NULL;
1069 FormHiiHandle = NULL;
1070
1071 //
1072 // Collect the health status with the optional HII message list
1073 //
1074 Status = DriverHealth->GetHealthStatus (DriverHealth, ControllerHandle, ChildHandle, HealthStatus, &MessageList, &FormHiiHandle);
1075
1076 if (EFI_ERROR (Status)) {
1077 //
1078 // If the health status could not be retrieved, then return immediately
1079 //
1080 return Status;
1081 }
1082
1083 //
1084 // Add the driver health related information into the list
1085 //
1086 DriverHealthInfo = AllocateZeroPool (sizeof (DRIVER_HEALTH_INFO));
1087 if (DriverHealthInfo == NULL) {
1088 return EFI_OUT_OF_RESOURCES;
1089 }
1090
1091 DriverHealthInfo->Signature = DEVICE_MANAGER_DRIVER_HEALTH_INFO_SIGNATURE;
1092 DriverHealthInfo->DriverHandle = DriverHandle;
1093 DriverHealthInfo->ControllerHandle = ControllerHandle;
1094 DriverHealthInfo->ChildHandle = ChildHandle;
1095 DriverHealthInfo->HiiHandle = FormHiiHandle;
1096 DriverHealthInfo->DriverHealth = DriverHealth;
1097 DriverHealthInfo->MessageList = MessageList;
1098 DriverHealthInfo->HealthStatus = *HealthStatus;
1099
1100 InsertTailList (DriverHealthList, &DriverHealthInfo->Link);
1101
1102 return EFI_SUCCESS;
1103 }
1104
1105 /**
1106 Collects all the EFI Driver Health Protocols currently present in the EFI Handle Database,
1107 and queries each EFI Driver Health Protocol to determine if one or more of the controllers
1108 managed by each EFI Driver Health Protocol instance are not healthy.
1109
1110 @param DriverHealthList A Pointer to the list contain all of the platform driver health
1111 information.
1112
1113 @retval EFI_NOT_FOUND No controller in the platform install Driver Health Protocol.
1114 @retval EFI_SUCCESS All the controllers in the platform are healthy.
1115 @retval EFI_OUT_OF_RESOURCES The list of Driver Health Protocol handles can not be retrieved.
1116
1117 **/
1118 EFI_STATUS
1119 GetAllControllersHealthStatus (
1120 IN OUT LIST_ENTRY *DriverHealthList
1121 )
1122 {
1123 EFI_STATUS Status;
1124 UINTN NumHandles;
1125 EFI_HANDLE *DriverHealthHandles;
1126 EFI_DRIVER_HEALTH_PROTOCOL *DriverHealth;
1127 EFI_DRIVER_HEALTH_STATUS HealthStatus;
1128 UINTN DriverHealthIndex;
1129 EFI_HANDLE *Handles;
1130 UINTN HandleCount;
1131 UINTN ControllerIndex;
1132 UINTN ChildIndex;
1133
1134 //
1135 // Initialize local variables
1136 //
1137 Handles = NULL;
1138 DriverHealthHandles = NULL;
1139 NumHandles = 0;
1140 HandleCount = 0;
1141
1142 HealthStatus = EfiDriverHealthStatusHealthy;
1143
1144 Status = gBS->LocateHandleBuffer (
1145 ByProtocol,
1146 &gEfiDriverHealthProtocolGuid,
1147 NULL,
1148 &NumHandles,
1149 &DriverHealthHandles
1150 );
1151
1152 if (Status == EFI_NOT_FOUND || NumHandles == 0) {
1153 //
1154 // If there are no Driver Health Protocols handles, then return EFI_NOT_FOUND
1155 //
1156 return EFI_NOT_FOUND;
1157 }
1158
1159 if (EFI_ERROR (Status) || DriverHealthHandles == NULL) {
1160 //
1161 // If the list of Driver Health Protocol handles can not be retrieved, then
1162 // return EFI_OUT_OF_RESOURCES
1163 //
1164 return EFI_OUT_OF_RESOURCES;
1165 }
1166
1167 //
1168 // Check the health status of all controllers in the platform
1169 // Start by looping through all the Driver Health Protocol handles in the handle database
1170 //
1171 for (DriverHealthIndex = 0; DriverHealthIndex < NumHandles; DriverHealthIndex++) {
1172 //
1173 // Skip NULL Driver Health Protocol handles
1174 //
1175 if (DriverHealthHandles[DriverHealthIndex] == NULL) {
1176 continue;
1177 }
1178
1179 //
1180 // Retrieve the Driver Health Protocol from DriverHandle
1181 //
1182 Status = gBS->HandleProtocol (
1183 DriverHealthHandles[DriverHealthIndex],
1184 &gEfiDriverHealthProtocolGuid,
1185 (VOID **)&DriverHealth
1186 );
1187 if (EFI_ERROR (Status)) {
1188 //
1189 // If the Driver Health Protocol can not be retrieved, then skip to the next
1190 // Driver Health Protocol handle
1191 //
1192 continue;
1193 }
1194
1195 //
1196 // Check the health of all the controllers managed by a Driver Health Protocol handle
1197 //
1198 Status = GetSingleControllerHealthStatus (DriverHealthList, DriverHealthHandles[DriverHealthIndex], NULL, NULL, DriverHealth, &HealthStatus);
1199
1200 //
1201 // If Status is an error code, then the health information could not be retrieved, so assume healthy
1202 // and skip to the next Driver Health Protocol handle
1203 //
1204 if (EFI_ERROR (Status)) {
1205 continue;
1206 }
1207
1208 //
1209 // If all the controllers managed by this Driver Health Protocol are healthy, then skip to the next
1210 // Driver Health Protocol handle
1211 //
1212 if (HealthStatus == EfiDriverHealthStatusHealthy) {
1213 continue;
1214 }
1215
1216 //
1217 // See if the list of all handles in the handle database has been retrieved
1218 //
1219 //
1220 if (Handles == NULL) {
1221 //
1222 // Retrieve the list of all handles from the handle database
1223 //
1224 Status = gBS->LocateHandleBuffer (
1225 AllHandles,
1226 NULL,
1227 NULL,
1228 &HandleCount,
1229 &Handles
1230 );
1231 if (EFI_ERROR (Status) || Handles == NULL) {
1232 //
1233 // If all the handles in the handle database can not be retrieved, then
1234 // return EFI_OUT_OF_RESOURCES
1235 //
1236 Status = EFI_OUT_OF_RESOURCES;
1237 goto Done;
1238 }
1239 }
1240 //
1241 // Loop through all the controller handles in the handle database
1242 //
1243 for (ControllerIndex = 0; ControllerIndex < HandleCount; ControllerIndex++) {
1244 //
1245 // Skip NULL controller handles
1246 //
1247 if (Handles[ControllerIndex] == NULL) {
1248 continue;
1249 }
1250
1251 Status = GetSingleControllerHealthStatus (DriverHealthList, DriverHealthHandles[DriverHealthIndex], Handles[ControllerIndex], NULL, DriverHealth, &HealthStatus);
1252 if (EFI_ERROR (Status)) {
1253 //
1254 // If Status is an error code, then the health information could not be retrieved, so assume healthy
1255 //
1256 HealthStatus = EfiDriverHealthStatusHealthy;
1257 }
1258
1259 //
1260 // If CheckHealthSingleController() returned an error on a terminal state, then do not check the health of child controllers
1261 //
1262 if (EFI_ERROR (Status)) {
1263 continue;
1264 }
1265
1266 //
1267 // Loop through all the child handles in the handle database
1268 //
1269 for (ChildIndex = 0; ChildIndex < HandleCount; ChildIndex++) {
1270 //
1271 // Skip NULL child handles
1272 //
1273 if (Handles[ChildIndex] == NULL) {
1274 continue;
1275 }
1276
1277 Status = GetSingleControllerHealthStatus (DriverHealthList, DriverHealthHandles[DriverHealthIndex], Handles[ControllerIndex], Handles[ChildIndex], DriverHealth, &HealthStatus);
1278 if (EFI_ERROR (Status)) {
1279 //
1280 // If Status is an error code, then the health information could not be retrieved, so assume healthy
1281 //
1282 HealthStatus = EfiDriverHealthStatusHealthy;
1283 }
1284
1285 //
1286 // If CheckHealthSingleController() returned an error on a terminal state, then skip to the next child
1287 //
1288 if (EFI_ERROR (Status)) {
1289 continue;
1290 }
1291 }
1292 }
1293 }
1294
1295 Status = EFI_SUCCESS;
1296
1297 Done:
1298 if (Handles != NULL) {
1299 gBS->FreePool (Handles);
1300 }
1301 if (DriverHealthHandles != NULL) {
1302 gBS->FreePool (DriverHealthHandles);
1303 }
1304
1305 return Status;
1306 }
1307
1308
1309 /*
1310 Check the healthy status of the platform, this function will return immediately while found one driver
1311 in the platform are not healthy.
1312
1313 @retval FALSE at least one driver in the platform are not healthy.
1314 @retval TRUE No controller install Driver Health Protocol,
1315 or all controllers in the platform are in healthy status.
1316 */
1317 BOOLEAN
1318 PlaformHealthStatusCheck (
1319 VOID
1320 )
1321 {
1322 EFI_DRIVER_HEALTH_STATUS HealthStatus;
1323 EFI_STATUS Status;
1324 UINTN Index;
1325 UINTN NoHandles;
1326 EFI_HANDLE *DriverHealthHandles;
1327 EFI_DRIVER_HEALTH_PROTOCOL *DriverHealth;
1328 BOOLEAN AllHealthy;
1329
1330 //
1331 // Initialize local variables
1332 //
1333 DriverHealthHandles = NULL;
1334 DriverHealth = NULL;
1335
1336 HealthStatus = EfiDriverHealthStatusHealthy;
1337
1338 Status = gBS->LocateHandleBuffer (
1339 ByProtocol,
1340 &gEfiDriverHealthProtocolGuid,
1341 NULL,
1342 &NoHandles,
1343 &DriverHealthHandles
1344 );
1345 //
1346 // There are no handles match the search for Driver Health Protocol has been installed.
1347 //
1348 if (Status == EFI_NOT_FOUND) {
1349 return TRUE;
1350 }
1351 //
1352 // Assume all modules are healthy.
1353 //
1354 AllHealthy = TRUE;
1355
1356 //
1357 // Found one or more Handles.
1358 //
1359 if (!EFI_ERROR (Status)) {
1360 for (Index = 0; Index < NoHandles; Index++) {
1361 Status = gBS->HandleProtocol (
1362 DriverHealthHandles[Index],
1363 &gEfiDriverHealthProtocolGuid,
1364 (VOID **) &DriverHealth
1365 );
1366 if (!EFI_ERROR (Status)) {
1367 Status = DriverHealth->GetHealthStatus (
1368 DriverHealth,
1369 NULL,
1370 NULL,
1371 &HealthStatus,
1372 NULL,
1373 NULL
1374 );
1375 }
1376 //
1377 // Get the healthy status of the module
1378 //
1379 if (!EFI_ERROR (Status)) {
1380 if (HealthStatus != EfiDriverHealthStatusHealthy) {
1381 //
1382 // Return immediately one driver's status not in healthy.
1383 //
1384 return FALSE;
1385 }
1386 }
1387 }
1388 }
1389 return AllHealthy;
1390 }
1391
1392 /**
1393 Processes a single controller using the EFI Driver Health Protocol associated with
1394 that controller. This algorithm continues to query the GetHealthStatus() service until
1395 one of the legal terminal states of the EFI Driver Health Protocol is reached. This may
1396 require the processing of HII Messages, HII Form, and invocation of repair operations.
1397
1398 @param DriverHealth A pointer to the EFI_DRIVER_HEALTH_PROTOCOL instance.
1399 @param ControllerHandle The class guid specifies which form set will be displayed.
1400 @param ChildHandle The handle of the child controller to retrieve the health
1401 status on. This is an optional parameter that may be NULL.
1402 @param HealthStatus The health status of the controller.
1403 @param MessageList An array of warning or error messages associated
1404 with the controller specified by ControllerHandle and
1405 ChildHandle. This is an optional parameter that may be NULL.
1406 @param FormHiiHandle The HII handle for an HII form associated with the
1407 controller specified by ControllerHandle and ChildHandle.
1408 **/
1409 VOID
1410 ProcessSingleControllerHealth (
1411 IN EFI_DRIVER_HEALTH_PROTOCOL *DriverHealth,
1412 IN EFI_HANDLE ControllerHandle, OPTIONAL
1413 IN EFI_HANDLE ChildHandle, OPTIONAL
1414 IN EFI_DRIVER_HEALTH_STATUS HealthStatus,
1415 IN EFI_DRIVER_HEALTH_HII_MESSAGE **MessageList, OPTIONAL
1416 IN EFI_HII_HANDLE FormHiiHandle
1417 )
1418 {
1419 EFI_STATUS Status;
1420 EFI_DRIVER_HEALTH_STATUS LocalHealthStatus;
1421
1422 LocalHealthStatus = HealthStatus;
1423 //
1424 // If the module need to be repaired or reconfiguration, will process it until
1425 // reach a terminal status. The status from EfiDriverHealthStatusRepairRequired after repair
1426 // will be in (Health, Failed, Configuration Required).
1427 //
1428 while( LocalHealthStatus == EfiDriverHealthStatusConfigurationRequired ||
1429 LocalHealthStatus == EfiDriverHealthStatusRepairRequired) {
1430
1431 if (LocalHealthStatus == EfiDriverHealthStatusRepairRequired) {
1432 Status = DriverHealth->Repair (
1433 DriverHealth,
1434 ControllerHandle,
1435 ChildHandle,
1436 (EFI_DRIVER_HEALTH_REPAIR_PROGRESS_NOTIFY) RepairNotify
1437 );
1438 }
1439 //
1440 // Via a form of the driver need to do configuration provided to process of status in
1441 // EfiDriverHealthStatusConfigurationRequired. The status after configuration should be in
1442 // (Healthy, Reboot Required, Failed, Reconnect Required, Repair Required).
1443 //
1444 if (LocalHealthStatus == EfiDriverHealthStatusConfigurationRequired) {
1445 Status = gFormBrowser2->SendForm (
1446 gFormBrowser2,
1447 &FormHiiHandle,
1448 1,
1449 &gEfiHiiDriverHealthFormsetGuid,
1450 0,
1451 NULL,
1452 NULL
1453 );
1454 ASSERT( !EFI_ERROR (Status));
1455 }
1456
1457 Status = DriverHealth->GetHealthStatus (
1458 DriverHealth,
1459 ControllerHandle,
1460 ChildHandle,
1461 &LocalHealthStatus,
1462 NULL,
1463 &FormHiiHandle
1464 );
1465 ASSERT_EFI_ERROR (Status);
1466
1467 if (*MessageList != NULL) {
1468 ProcessMessages (*MessageList);
1469 }
1470 }
1471
1472 //
1473 // Health status in {Healthy, Failed} may also have Messages need to process
1474 //
1475 if (LocalHealthStatus == EfiDriverHealthStatusHealthy || LocalHealthStatus == EfiDriverHealthStatusFailed) {
1476 if (*MessageList != NULL) {
1477 ProcessMessages (*MessageList);
1478 }
1479 }
1480 //
1481 // Check for RebootRequired or ReconnectRequired
1482 //
1483 if (LocalHealthStatus == EfiDriverHealthStatusRebootRequired) {
1484 gRT->ResetSystem (EfiResetWarm, EFI_SUCCESS, 0, NULL);
1485 }
1486
1487 //
1488 // Do reconnect if need.
1489 //
1490 if (LocalHealthStatus == EfiDriverHealthStatusReconnectRequired) {
1491 Status = gBS->DisconnectController (ControllerHandle, NULL, NULL);
1492 if (EFI_ERROR (Status)) {
1493 //
1494 // Disconnect failed. Need to promote reconnect to a reboot.
1495 //
1496 gRT->ResetSystem (EfiResetWarm, EFI_SUCCESS, 0, NULL);
1497 }
1498 gBS->ConnectController (ControllerHandle, NULL, NULL, TRUE);
1499 }
1500 }
1501
1502
1503 /**
1504 Platform specific notification function for controller repair operations.
1505
1506 If the driver for a controller support the Driver Health Protocol and the
1507 current state of the controller is EfiDriverHealthStatusRepairRequired then
1508 when the Repair() service of the Driver Health Protocol is called, this
1509 platform specific notification function can display the progress of the repair
1510 operation. Some platforms may choose to not display anything, other may choose
1511 to show the percentage complete on text consoles, and other may choose to render
1512 a progress bar on text and graphical consoles.
1513
1514 This function displays the percentage of the repair operation that has been
1515 completed on text consoles. The percentage is Value / Limit * 100%.
1516
1517 @param Value Value in the range 0..Limit the the repair has completed..
1518 @param Limit The maximum value of Value
1519
1520 **/
1521 VOID
1522 RepairNotify (
1523 IN UINTN Value,
1524 IN UINTN Limit
1525 )
1526 {
1527 UINTN Percent;
1528
1529 if (Limit == 0) {
1530 Print(L"Repair Progress Undefined\n\r");
1531 } else {
1532 Percent = Value * 100 / Limit;
1533 Print(L"Repair Progress = %3d%%\n\r", Percent);
1534 }
1535 }
1536
1537 /**
1538 Processes a set of messages returned by the GetHealthStatus ()
1539 service of the EFI Driver Health Protocol
1540
1541 @param MessageList The MessageList point to messages need to processed.
1542
1543 **/
1544 VOID
1545 ProcessMessages (
1546 IN EFI_DRIVER_HEALTH_HII_MESSAGE *MessageList
1547 )
1548 {
1549 UINTN MessageIndex;
1550 EFI_STRING MessageString;
1551
1552 for (MessageIndex = 0;
1553 MessageList[MessageIndex].HiiHandle != NULL;
1554 MessageIndex++) {
1555
1556 MessageString = HiiGetString (
1557 MessageList[MessageIndex].HiiHandle,
1558 MessageList[MessageIndex].StringId,
1559 NULL
1560 );
1561 if (MessageString != NULL) {
1562 //
1563 // User can customize the output. Just simply print out the MessageString like below.
1564 // Also can use the HiiHandle to display message on the front page.
1565 //
1566 // Print(L"%s\n",MessageString);
1567 // gBS->Stall (100000);
1568 }
1569 }
1570
1571 }
1572
1573 /*
1574 Repair the whole platform.
1575
1576 This function is the main entry for user choose "Repair All" in the front page.
1577 It will try to do recovery job till all the driver health protocol installed modules
1578 reach a terminal state.
1579
1580 @param DriverHealthList A Pointer to the list contain all of the platform driver health
1581 information.
1582
1583 */
1584 VOID
1585 PlatformRepairAll (
1586 IN LIST_ENTRY *DriverHealthList
1587 )
1588 {
1589 DRIVER_HEALTH_INFO *DriverHealthInfo;
1590 LIST_ENTRY *Link;
1591
1592 ASSERT (DriverHealthList != NULL);
1593
1594 Link = GetFirstNode (DriverHealthList);
1595
1596 while (!IsNull (DriverHealthList, Link)) {
1597 DriverHealthInfo = DEVICE_MANAGER_HEALTH_INFO_FROM_LINK (Link);
1598 //
1599 // Do driver health status operation by each link node
1600 //
1601 ASSERT (DriverHealthInfo != NULL);
1602
1603 ProcessSingleControllerHealth (
1604 DriverHealthInfo->DriverHealth,
1605 DriverHealthInfo->ControllerHandle,
1606 DriverHealthInfo->ChildHandle,
1607 DriverHealthInfo->HealthStatus,
1608 &(DriverHealthInfo->MessageList),
1609 DriverHealthInfo->HiiHandle
1610 );
1611
1612 Link = GetNextNode (DriverHealthList, Link);
1613 }
1614 }
1615
1616 /**
1617
1618 Select the best matching language according to front page policy for best user experience.
1619
1620 This function supports both ISO 639-2 and RFC 4646 language codes, but language
1621 code types may not be mixed in a single call to this function.
1622
1623 @param SupportedLanguages A pointer to a Null-terminated ASCII string that
1624 contains a set of language codes in the format
1625 specified by Iso639Language.
1626 @param Iso639Language If TRUE, then all language codes are assumed to be
1627 in ISO 639-2 format. If FALSE, then all language
1628 codes are assumed to be in RFC 4646 language format.
1629
1630 @retval NULL The best matching language could not be found in SupportedLanguages.
1631 @retval NULL There are not enough resources available to return the best matching
1632 language.
1633 @retval Other A pointer to a Null-terminated ASCII string that is the best matching
1634 language in SupportedLanguages.
1635 **/
1636 CHAR8 *
1637 DriverHealthSelectBestLanguage (
1638 IN CHAR8 *SupportedLanguages,
1639 IN BOOLEAN Iso639Language
1640 )
1641 {
1642 CHAR8 *LanguageVariable;
1643 CHAR8 *BestLanguage;
1644
1645 LanguageVariable = GetEfiGlobalVariable (Iso639Language ? L"Lang" : L"PlatformLang");
1646
1647 BestLanguage = GetBestLanguage(
1648 SupportedLanguages,
1649 Iso639Language,
1650 (LanguageVariable != NULL) ? LanguageVariable : "",
1651 Iso639Language ? "eng" : "en-US",
1652 NULL
1653 );
1654 if (LanguageVariable != NULL) {
1655 FreePool (LanguageVariable);
1656 }
1657
1658 return BestLanguage;
1659 }
1660
1661
1662
1663 /**
1664
1665 This is an internal worker function to get the Component Name (2) protocol interface
1666 and the language it supports.
1667
1668 @param ProtocolGuid A pointer to an EFI_GUID. It points to Component Name (2) protocol GUID.
1669 @param DriverBindingHandle The handle on which the Component Name (2) protocol instance is retrieved.
1670 @param ComponentName A pointer to the Component Name (2) protocol interface.
1671 @param SupportedLanguage The best suitable language that matches the SupportedLangues interface for the
1672 located Component Name (2) instance.
1673
1674 @param EFI_SUCCESS The Component Name (2) protocol instance is successfully located and we find
1675 the best matching language it support.
1676 @param EFI_UNSUPPORTED The input Language is not supported by the Component Name (2) protocol.
1677 @param Other Some error occurs when locating Component Name (2) protocol instance or finding
1678 the supported language.
1679
1680 **/
1681 EFI_STATUS
1682 GetComponentNameWorker (
1683 IN EFI_GUID *ProtocolGuid,
1684 IN EFI_HANDLE DriverBindingHandle,
1685 OUT EFI_COMPONENT_NAME_PROTOCOL **ComponentName,
1686 OUT CHAR8 **SupportedLanguage
1687 )
1688 {
1689 EFI_STATUS Status;
1690
1691 //
1692 // Locate Component Name (2) protocol on the driver binging handle.
1693 //
1694 Status = gBS->OpenProtocol (
1695 DriverBindingHandle,
1696 ProtocolGuid,
1697 (VOID **) ComponentName,
1698 NULL,
1699 NULL,
1700 EFI_OPEN_PROTOCOL_GET_PROTOCOL
1701 );
1702 if (EFI_ERROR (Status)) {
1703 return Status;
1704 }
1705
1706 //
1707 // Apply shell policy to select the best language.
1708 //
1709 *SupportedLanguage = DriverHealthSelectBestLanguage (
1710 (*ComponentName)->SupportedLanguages,
1711 (BOOLEAN) (ProtocolGuid == &gEfiComponentNameProtocolGuid)
1712 );
1713 if (*SupportedLanguage == NULL) {
1714 Status = EFI_UNSUPPORTED;
1715 }
1716
1717 return Status;
1718 }
1719
1720 /**
1721
1722 This is an internal worker function to get driver name from Component Name (2) protocol interface.
1723
1724
1725 @param ProtocolGuid A pointer to an EFI_GUID. It points to Component Name (2) protocol GUID.
1726 @param DriverBindingHandle The handle on which the Component Name (2) protocol instance is retrieved.
1727 @param DriverName A pointer to the Unicode string to return. This Unicode string is the name
1728 of the driver specified by This.
1729
1730 @retval EFI_SUCCESS The driver name is successfully retrieved from Component Name (2) protocol
1731 interface.
1732 @retval Other The driver name cannot be retrieved from Component Name (2) protocol
1733 interface.
1734
1735 **/
1736 EFI_STATUS
1737 GetDriverNameWorker (
1738 IN EFI_GUID *ProtocolGuid,
1739 IN EFI_HANDLE DriverBindingHandle,
1740 OUT CHAR16 **DriverName
1741 )
1742 {
1743 EFI_STATUS Status;
1744 CHAR8 *BestLanguage;
1745 EFI_COMPONENT_NAME_PROTOCOL *ComponentName;
1746
1747 //
1748 // Retrieve Component Name (2) protocol instance on the driver binding handle and
1749 // find the best language this instance supports.
1750 //
1751 Status = GetComponentNameWorker (
1752 ProtocolGuid,
1753 DriverBindingHandle,
1754 &ComponentName,
1755 &BestLanguage
1756 );
1757 if (EFI_ERROR (Status)) {
1758 return Status;
1759 }
1760
1761 //
1762 // Get the driver name from Component Name (2) protocol instance on the driver binging handle.
1763 //
1764 Status = ComponentName->GetDriverName (
1765 ComponentName,
1766 BestLanguage,
1767 DriverName
1768 );
1769 FreePool (BestLanguage);
1770
1771 return Status;
1772 }
1773
1774 /**
1775
1776 This function gets driver name from Component Name 2 protocol interface and Component Name protocol interface
1777 in turn. It first tries UEFI 2.0 Component Name 2 protocol interface and try to get the driver name.
1778 If the attempt fails, it then gets the driver name from EFI 1.1 Component Name protocol for backward
1779 compatibility support.
1780
1781 @param DriverBindingHandle The handle on which the Component Name (2) protocol instance is retrieved.
1782 @param DriverName A pointer to the Unicode string to return. This Unicode string is the name
1783 of the driver specified by This.
1784
1785 @retval EFI_SUCCESS The driver name is successfully retrieved from Component Name (2) protocol
1786 interface.
1787 @retval Other The driver name cannot be retrieved from Component Name (2) protocol
1788 interface.
1789
1790 **/
1791 EFI_STATUS
1792 DriverHealthGetDriverName (
1793 IN EFI_HANDLE DriverBindingHandle,
1794 OUT CHAR16 **DriverName
1795 )
1796 {
1797 EFI_STATUS Status;
1798
1799 //
1800 // Get driver name from UEFI 2.0 Component Name 2 protocol interface.
1801 //
1802 Status = GetDriverNameWorker (&gEfiComponentName2ProtocolGuid, DriverBindingHandle, DriverName);
1803 if (EFI_ERROR (Status)) {
1804 //
1805 // If it fails to get the driver name from Component Name protocol interface, we should fall back on
1806 // EFI 1.1 Component Name protocol interface.
1807 //
1808 Status = GetDriverNameWorker (&gEfiComponentNameProtocolGuid, DriverBindingHandle, DriverName);
1809 }
1810
1811 return Status;
1812 }
1813
1814
1815
1816 /**
1817 This function gets controller name from Component Name 2 protocol interface and Component Name protocol interface
1818 in turn. It first tries UEFI 2.0 Component Name 2 protocol interface and try to get the controller name.
1819 If the attempt fails, it then gets the controller name from EFI 1.1 Component Name protocol for backward
1820 compatibility support.
1821
1822 @param ProtocolGuid A pointer to an EFI_GUID. It points to Component Name (2) protocol GUID.
1823 @param DriverBindingHandle The handle on which the Component Name (2) protocol instance is retrieved.
1824 @param ControllerHandle The handle of a controller that the driver specified by This is managing.
1825 This handle specifies the controller whose name is to be returned.
1826 @param ChildHandle The handle of the child controller to retrieve the name of. This is an
1827 optional parameter that may be NULL. It will be NULL for device drivers.
1828 It will also be NULL for bus drivers that attempt to retrieve the name
1829 of the bus controller. It will not be NULL for a bus driver that attempts
1830 to retrieve the name of a child controller.
1831 @param ControllerName A pointer to the Unicode string to return. This Unicode string
1832 is the name of the controller specified by ControllerHandle and ChildHandle.
1833
1834 @retval EFI_SUCCESS The controller name is successfully retrieved from Component Name (2) protocol
1835 interface.
1836 @retval Other The controller name cannot be retrieved from Component Name (2) protocol.
1837
1838 **/
1839 EFI_STATUS
1840 GetControllerNameWorker (
1841 IN EFI_GUID *ProtocolGuid,
1842 IN EFI_HANDLE DriverBindingHandle,
1843 IN EFI_HANDLE ControllerHandle,
1844 IN EFI_HANDLE ChildHandle,
1845 OUT CHAR16 **ControllerName
1846 )
1847 {
1848 EFI_STATUS Status;
1849 CHAR8 *BestLanguage;
1850 EFI_COMPONENT_NAME_PROTOCOL *ComponentName;
1851
1852 //
1853 // Retrieve Component Name (2) protocol instance on the driver binding handle and
1854 // find the best language this instance supports.
1855 //
1856 Status = GetComponentNameWorker (
1857 ProtocolGuid,
1858 DriverBindingHandle,
1859 &ComponentName,
1860 &BestLanguage
1861 );
1862 if (EFI_ERROR (Status)) {
1863 return Status;
1864 }
1865
1866 //
1867 // Get the controller name from Component Name (2) protocol instance on the driver binging handle.
1868 //
1869 Status = ComponentName->GetControllerName (
1870 ComponentName,
1871 ControllerHandle,
1872 ChildHandle,
1873 BestLanguage,
1874 ControllerName
1875 );
1876 FreePool (BestLanguage);
1877
1878 return Status;
1879 }
1880
1881 /**
1882
1883 This function gets controller name from Component Name 2 protocol interface and Component Name protocol interface
1884 in turn. It first tries UEFI 2.0 Component Name 2 protocol interface and try to get the controller name.
1885 If the attempt fails, it then gets the controller name from EFI 1.1 Component Name protocol for backward
1886 compatibility support.
1887
1888 @param DriverBindingHandle The handle on which the Component Name (2) protocol instance is retrieved.
1889 @param ControllerHandle The handle of a controller that the driver specified by This is managing.
1890 This handle specifies the controller whose name is to be returned.
1891 @param ChildHandle The handle of the child controller to retrieve the name of. This is an
1892 optional parameter that may be NULL. It will be NULL for device drivers.
1893 It will also be NULL for bus drivers that attempt to retrieve the name
1894 of the bus controller. It will not be NULL for a bus driver that attempts
1895 to retrieve the name of a child controller.
1896 @param Language An ASCII string that represents the language command line option.
1897 @param ControllerName A pointer to the Unicode string to return. This Unicode string
1898 is the name of the controller specified by ControllerHandle and ChildHandle.
1899
1900 @retval EFI_SUCCESS The controller name is successfully retrieved from Component Name (2) protocol
1901 interface.
1902 @retval Other The controller name cannot be retrieved from Component Name (2) protocol.
1903
1904 **/
1905 EFI_STATUS
1906 DriverHealthGetControllerName (
1907 IN EFI_HANDLE DriverBindingHandle,
1908 IN EFI_HANDLE ControllerHandle,
1909 IN EFI_HANDLE ChildHandle,
1910 OUT CHAR16 **ControllerName
1911 )
1912 {
1913 EFI_STATUS Status;
1914
1915 //
1916 // Get controller name from UEFI 2.0 Component Name 2 protocol interface.
1917 //
1918 Status = GetControllerNameWorker (
1919 &gEfiComponentName2ProtocolGuid,
1920 DriverBindingHandle,
1921 ControllerHandle,
1922 ChildHandle,
1923 ControllerName
1924 );
1925 if (EFI_ERROR (Status)) {
1926 //
1927 // If it fails to get the controller name from Component Name protocol interface, we should fall back on
1928 // EFI 1.1 Component Name protocol interface.
1929 //
1930 Status = GetControllerNameWorker (
1931 &gEfiComponentNameProtocolGuid,
1932 DriverBindingHandle,
1933 ControllerHandle,
1934 ChildHandle,
1935 ControllerName
1936 );
1937 }
1938
1939 return Status;
1940 }