2 The platform device manager reference implementation
4 Copyright (c) 2004 - 2010, Intel Corporation. All rights reserved.<BR>
5 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
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.
15 #include "DeviceManager.h"
17 DEVICE_MANAGER_CALLBACK_DATA gDeviceManagerPrivate
= {
18 DEVICE_MANAGER_CALLBACK_DATA_SIGNATURE
,
35 EFI_GUID mDeviceManagerGuid
= DEVICE_MANAGER_FORMSET_GUID
;
36 EFI_GUID mDriverHealthGuid
= DRIVER_HEALTH_FORMSET_GUID
;
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
}
47 HII_VENDOR_DEVICE_PATH mDeviceManagerHiiVendorDevicePath
= {
53 (UINT8
) (sizeof (VENDOR_DEVICE_PATH
)),
54 (UINT8
) ((sizeof (VENDOR_DEVICE_PATH
)) >> 8)
58 // {102579A0-3686-466e-ACD8-80C087044F4A}
60 { 0x102579a0, 0x3686, 0x466e, { 0xac, 0xd8, 0x80, 0xc0, 0x87, 0x4, 0x4f, 0x4a } }
64 END_ENTIRE_DEVICE_PATH_SUBTYPE
,
66 (UINT8
) (END_DEVICE_PATH_LENGTH
),
67 (UINT8
) ((END_DEVICE_PATH_LENGTH
) >> 8)
72 HII_VENDOR_DEVICE_PATH mDriverHealthHiiVendorDevicePath
= {
78 (UINT8
) (sizeof (VENDOR_DEVICE_PATH
)),
79 (UINT8
) ((sizeof (VENDOR_DEVICE_PATH
)) >> 8)
83 // {D8F76651-1675-4986-BED4-3824B2F1F4C8}
85 { 0xd8f76651, 0x1675, 0x4986, { 0xbe, 0xd4, 0x38, 0x24, 0xb2, 0xf1, 0xf4, 0xc8 } }
89 END_ENTIRE_DEVICE_PATH_SUBTYPE
,
91 (UINT8
) (END_DEVICE_PATH_LENGTH
),
92 (UINT8
) ((END_DEVICE_PATH_LENGTH
) >> 8)
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.
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.
110 @retval EFI_SUCCESS The callback successfully handled the action.
111 @retval EFI_INVALID_PARAMETER The setup browser call this function with invalid parameters.
116 DeviceManagerCallback (
117 IN CONST EFI_HII_CONFIG_ACCESS_PROTOCOL
*This
,
118 IN EFI_BROWSER_ACTION Action
,
119 IN EFI_QUESTION_ID QuestionId
,
121 IN EFI_IFR_TYPE_VALUE
*Value
,
122 OUT EFI_BROWSER_ACTION_REQUEST
*ActionRequest
125 if ((Action
== EFI_BROWSER_ACTION_FORM_OPEN
) || (Action
== EFI_BROWSER_ACTION_FORM_CLOSE
)) {
127 // Do nothing for UEFI OPEN/CLOSE Action
132 if ((Value
== NULL
) || (ActionRequest
== NULL
)) {
133 return EFI_INVALID_PARAMETER
;
136 gCallbackKey
= QuestionId
;
139 // Request to exit SendForm(), so as to switch to selected form
141 *ActionRequest
= EFI_BROWSER_ACTION_REQUEST_EXIT
;
148 This function registers HII packages to HII database.
150 @retval EFI_SUCCESS HII packages for the Device Manager were registered successfully.
151 @retval EFI_OUT_OF_RESOURCES HII packages for the Device Manager failed to be registered.
155 InitializeDeviceManager (
162 // Install Device Path Protocol and Config Access protocol to driver handle
164 Status
= gBS
->InstallMultipleProtocolInterfaces (
165 &gDeviceManagerPrivate
.DriverHandle
,
166 &gEfiDevicePathProtocolGuid
,
167 &mDeviceManagerHiiVendorDevicePath
,
168 &gEfiHiiConfigAccessProtocolGuid
,
169 &gDeviceManagerPrivate
.ConfigAccess
,
172 ASSERT_EFI_ERROR (Status
);
174 Status
= gBS
->InstallMultipleProtocolInterfaces (
175 &gDeviceManagerPrivate
.DriverHealthHandle
,
176 &gEfiDevicePathProtocolGuid
,
177 &mDriverHealthHiiVendorDevicePath
,
178 &gEfiHiiConfigAccessProtocolGuid
,
179 &gDeviceManagerPrivate
.DriverHealthConfigAccess
,
182 ASSERT_EFI_ERROR (Status
);
185 // Publish our HII data
187 gDeviceManagerPrivate
.HiiHandle
= HiiAddPackages (
189 gDeviceManagerPrivate
.DriverHandle
,
194 if (gDeviceManagerPrivate
.HiiHandle
== NULL
) {
195 return EFI_OUT_OF_RESOURCES
;
197 Status
= EFI_SUCCESS
;
201 // Publish Driver Health HII data
203 gDeviceManagerPrivate
.DriverHealthHiiHandle
= HiiAddPackages (
205 gDeviceManagerPrivate
.DriverHealthHandle
,
210 if (gDeviceManagerPrivate
.DriverHealthHiiHandle
== NULL
) {
211 Status
= EFI_OUT_OF_RESOURCES
;
213 Status
= EFI_SUCCESS
;
220 Extract the displayed formset for given HII handle and class guid.
222 @param Handle The HII handle.
223 @param SetupClassGuid The class guid specifies which form set will be displayed.
224 @param FormSetTitle Formset title string.
225 @param FormSetHelp Formset help string.
227 @retval TRUE The formset for given HII handle will be displayed.
228 @return FALSE The formset for given HII handle will not be displayed.
232 ExtractDisplayedHiiFormFromHiiHandle (
233 IN EFI_HII_HANDLE Handle
,
234 IN EFI_GUID
*SetupClassGuid
,
235 OUT EFI_STRING_ID
*FormSetTitle
,
236 OUT EFI_STRING_ID
*FormSetHelp
241 EFI_HII_PACKAGE_LIST_HEADER
*HiiPackageList
;
246 UINT32 PackageListLength
;
247 EFI_HII_PACKAGE_HEADER PackageHeader
;
251 ASSERT (Handle
!= NULL
);
252 ASSERT (SetupClassGuid
!= NULL
);
253 ASSERT (FormSetTitle
!= NULL
);
254 ASSERT (FormSetHelp
!= NULL
);
262 // Get HII PackageList
265 HiiPackageList
= NULL
;
266 Status
= gHiiDatabase
->ExportPackageLists (gHiiDatabase
, Handle
, &BufferSize
, HiiPackageList
);
268 // Handle is a invalid handle. Check if Handle is corrupted.
270 ASSERT (Status
!= EFI_NOT_FOUND
);
272 // The return status should always be EFI_BUFFER_TOO_SMALL as input buffer's size is 0.
274 ASSERT (Status
== EFI_BUFFER_TOO_SMALL
);
276 HiiPackageList
= AllocatePool (BufferSize
);
277 ASSERT (HiiPackageList
!= NULL
);
279 Status
= gHiiDatabase
->ExportPackageLists (gHiiDatabase
, Handle
, &BufferSize
, HiiPackageList
);
280 if (EFI_ERROR (Status
)) {
285 // Get Form package from this HII package List
287 Offset
= sizeof (EFI_HII_PACKAGE_LIST_HEADER
);
289 PackageListLength
= ReadUnaligned32 (&HiiPackageList
->PackageLength
);
291 while (Offset
< PackageListLength
) {
292 Package
= ((UINT8
*) HiiPackageList
) + Offset
;
293 CopyMem (&PackageHeader
, Package
, sizeof (EFI_HII_PACKAGE_HEADER
));
295 if (PackageHeader
.Type
== EFI_HII_PACKAGE_FORMS
) {
297 // Search FormSet Opcode in this Form Package
299 Offset2
= sizeof (EFI_HII_PACKAGE_HEADER
);
300 while (Offset2
< PackageHeader
.Length
) {
301 OpCodeData
= Package
+ Offset2
;
303 if (((EFI_IFR_OP_HEADER
*) OpCodeData
)->OpCode
== EFI_IFR_FORM_SET_OP
) {
304 if (((EFI_IFR_OP_HEADER
*) OpCodeData
)->Length
> OFFSET_OF (EFI_IFR_FORM_SET
, Flags
)) {
306 // Find FormSet OpCode
308 ClassGuidNum
= (UINT8
) (((EFI_IFR_FORM_SET
*) OpCodeData
)->Flags
& 0x3);
309 ClassGuid
= (EFI_GUID
*) (VOID
*)(OpCodeData
+ sizeof (EFI_IFR_FORM_SET
));
310 while (ClassGuidNum
-- > 0) {
311 if (CompareGuid (SetupClassGuid
, ClassGuid
)) {
312 CopyMem (FormSetTitle
, &((EFI_IFR_FORM_SET
*) OpCodeData
)->FormSetTitle
, sizeof (EFI_STRING_ID
));
313 CopyMem (FormSetHelp
, &((EFI_IFR_FORM_SET
*) OpCodeData
)->Help
, sizeof (EFI_STRING_ID
));
314 FreePool (HiiPackageList
);
320 CopyMem (FormSetTitle
, &((EFI_IFR_FORM_SET
*) OpCodeData
)->FormSetTitle
, sizeof (EFI_STRING_ID
));
321 CopyMem (FormSetHelp
, &((EFI_IFR_FORM_SET
*) OpCodeData
)->Help
, sizeof (EFI_STRING_ID
));
322 FreePool (HiiPackageList
);
330 Offset2
+= ((EFI_IFR_OP_HEADER
*) OpCodeData
)->Length
;
335 // Go to next package
337 Offset
+= PackageHeader
.Length
;
340 FreePool (HiiPackageList
);
346 Call the browser and display the device manager to allow user
347 to configure the platform.
349 This function create the dynamic content for device manager. It includes
350 section header for all class of devices, one-of opcode to set VBIOS.
352 @retval EFI_SUCCESS Operation is successful.
353 @return Other values if failed to clean up the dynamic content from HII
366 EFI_STRING_ID TokenHelp
;
367 EFI_HII_HANDLE
*HiiHandles
;
368 EFI_HII_HANDLE HiiHandle
;
369 EFI_STRING_ID FormSetTitle
;
370 EFI_STRING_ID FormSetHelp
;
371 EFI_BROWSER_ACTION_REQUEST ActionRequest
;
372 VOID
*StartOpCodeHandle
;
373 VOID
*EndOpCodeHandle
;
374 EFI_IFR_GUID_LABEL
*StartLabel
;
375 EFI_IFR_GUID_LABEL
*EndLabel
;
377 EFI_HANDLE
*DriverHealthHandles
;
380 Status
= EFI_SUCCESS
;
383 DriverHealthHandles
= NULL
;
386 // Connect all prior to entering the platform setup menu.
388 if (!gConnectAllHappened
) {
389 BdsLibConnectAllDriversToAllControllers ();
390 gConnectAllHappened
= TRUE
;
393 // Create Subtitle OpCodes
396 // Allocate space for creation of UpdateData Buffer
398 StartOpCodeHandle
= HiiAllocateOpCodeHandle ();
399 ASSERT (StartOpCodeHandle
!= NULL
);
401 EndOpCodeHandle
= HiiAllocateOpCodeHandle ();
402 ASSERT (EndOpCodeHandle
!= NULL
);
405 // Create Hii Extend Label OpCode as the start opcode
407 StartLabel
= (EFI_IFR_GUID_LABEL
*) HiiCreateGuidOpCode (StartOpCodeHandle
, &gEfiIfrTianoGuid
, NULL
, sizeof (EFI_IFR_GUID_LABEL
));
408 StartLabel
->ExtendOpCode
= EFI_IFR_EXTEND_OP_LABEL
;
409 StartLabel
->Number
= LABEL_DEVICES_LIST
;
412 // Create Hii Extend Label OpCode as the end opcode
414 EndLabel
= (EFI_IFR_GUID_LABEL
*) HiiCreateGuidOpCode (EndOpCodeHandle
, &gEfiIfrTianoGuid
, NULL
, sizeof (EFI_IFR_GUID_LABEL
));
415 EndLabel
->ExtendOpCode
= EFI_IFR_EXTEND_OP_LABEL
;
416 EndLabel
->Number
= LABEL_END
;
418 HiiCreateSubTitleOpCode (StartOpCodeHandle
, STRING_TOKEN (STR_DEVICES_LIST
), 0, 0, 1);
421 // Get all the Hii handles
423 HiiHandles
= HiiGetHiiHandles (NULL
);
424 ASSERT (HiiHandles
!= NULL
);
426 HiiHandle
= gDeviceManagerPrivate
.HiiHandle
;
429 // Search for formset of each class type
431 for (Index
= 0; HiiHandles
[Index
] != NULL
; Index
++) {
432 if (!ExtractDisplayedHiiFormFromHiiHandle (HiiHandles
[Index
], &gEfiHiiPlatformSetupFormsetGuid
, &FormSetTitle
, &FormSetHelp
)) {
436 String
= HiiGetString (HiiHandles
[Index
], FormSetTitle
, NULL
);
437 if (String
== NULL
) {
438 String
= HiiGetString (HiiHandle
, STR_MISSING_STRING
, NULL
);
439 ASSERT (String
!= NULL
);
441 Token
= HiiSetString (HiiHandle
, 0, String
, NULL
);
444 String
= HiiGetString (HiiHandles
[Index
], FormSetHelp
, NULL
);
445 if (String
== NULL
) {
446 String
= HiiGetString (HiiHandle
, STR_MISSING_STRING
, NULL
);
447 ASSERT (String
!= NULL
);
449 TokenHelp
= HiiSetString (HiiHandle
, 0, String
, NULL
);
452 HiiCreateActionOpCode (
454 (EFI_QUESTION_ID
) (Index
+ DEVICE_KEY_OFFSET
),
457 EFI_IFR_FLAG_CALLBACK
,
463 // Add End Opcode for Subtitle
465 HiiCreateEndOpCode (StartOpCodeHandle
);
467 Status
= gBS
->LocateHandleBuffer (
469 &gEfiDriverHealthProtocolGuid
,
476 // If there are no drivers installed driver health protocol, do not create driver health entry in UI
478 if (NumHandles
!= 0) {
480 // If driver health protocol is installed, create Driver Health subtitle and entry
482 HiiCreateSubTitleOpCode (StartOpCodeHandle
, STRING_TOKEN (STR_DM_DRIVER_HEALTH_TITLE
), 0, 0, 0);
483 HiiCreateActionOpCode (
484 StartOpCodeHandle
, // Container for dynamic created opcodes
485 DEVICE_MANAGER_KEY_DRIVER_HEALTH
, // Question ID
486 STRING_TOKEN(STR_DRIVER_HEALTH_ALL_HEALTHY
), // Prompt text
487 STRING_TOKEN(STR_DRIVER_HEALTH_STATUS_HELP
), // Help text
488 EFI_IFR_FLAG_CALLBACK
, // Question flag
489 0 // Action String ID
493 // Check All Driver health status
495 if (!PlaformHealthStatusCheck ()) {
497 // At least one driver in the platform are not in healthy status
499 HiiSetString (HiiHandle
, STRING_TOKEN (STR_DRIVER_HEALTH_ALL_HEALTHY
), GetStringById (STRING_TOKEN (STR_DRIVER_NOT_HEALTH
)), NULL
);
502 // For the string of STR_DRIVER_HEALTH_ALL_HEALTHY previously has been updated and we need to update it while re-entry.
504 HiiSetString (HiiHandle
, STRING_TOKEN (STR_DRIVER_HEALTH_ALL_HEALTHY
), GetStringById (STRING_TOKEN (STR_DRIVER_HEALTH_ALL_HEALTHY
)), NULL
);
511 DEVICE_MANAGER_FORM_ID
,
516 ActionRequest
= EFI_BROWSER_ACTION_REQUEST_NONE
;
517 Status
= gFormBrowser2
->SendForm (
526 if (ActionRequest
== EFI_BROWSER_ACTION_REQUEST_RESET
) {
527 EnableResetRequired ();
531 // We will have returned from processing a callback - user either hit ESC to exit, or selected
532 // a target to display
534 if ((gCallbackKey
!= 0) && (gCallbackKey
!= DEVICE_MANAGER_KEY_DRIVER_HEALTH
)) {
535 ActionRequest
= EFI_BROWSER_ACTION_REQUEST_NONE
;
536 Status
= gFormBrowser2
->SendForm (
538 &HiiHandles
[gCallbackKey
- DEVICE_KEY_OFFSET
],
546 if (ActionRequest
== EFI_BROWSER_ACTION_REQUEST_RESET
) {
547 EnableResetRequired ();
551 // Force return to Device Manager
553 gCallbackKey
= FRONT_PAGE_KEY_DEVICE_MANAGER
;
557 // Driver Health item chose.
559 if (gCallbackKey
== DEVICE_MANAGER_KEY_DRIVER_HEALTH
) {
562 // Force return to Device Manager
564 gCallbackKey
= FRONT_PAGE_KEY_DEVICE_MANAGER
;
568 // Cleanup dynamic created strings in HII database by reinstall the packagelist
570 HiiRemovePackages (HiiHandle
);
572 gDeviceManagerPrivate
.HiiHandle
= HiiAddPackages (
574 gDeviceManagerPrivate
.DriverHandle
,
579 if (gDeviceManagerPrivate
.HiiHandle
== NULL
) {
580 Status
= EFI_OUT_OF_RESOURCES
;
582 Status
= EFI_SUCCESS
;
585 HiiFreeOpCodeHandle (StartOpCodeHandle
);
586 HiiFreeOpCodeHandle (EndOpCodeHandle
);
587 FreePool (HiiHandles
);
593 This function is invoked if user selected a interactive opcode from Driver Health's
594 Formset. The decision by user is saved to gCallbackKey for later processing.
596 @param This Points to the EFI_HII_CONFIG_ACCESS_PROTOCOL.
597 @param Action Specifies the type of action taken by the browser.
598 @param QuestionId A unique value which is sent to the original exporting driver
599 so that it can identify the type of data to expect.
600 @param Type The type of value for the question.
601 @param Value A pointer to the data being sent to the original exporting driver.
602 @param ActionRequest On return, points to the action requested by the callback function.
604 @retval EFI_SUCCESS The callback successfully handled the action.
605 @retval EFI_INVALID_PARAMETER The setup browser call this function with invalid parameters.
610 DriverHealthCallback (
611 IN CONST EFI_HII_CONFIG_ACCESS_PROTOCOL
*This
,
612 IN EFI_BROWSER_ACTION Action
,
613 IN EFI_QUESTION_ID QuestionId
,
615 IN EFI_IFR_TYPE_VALUE
*Value
,
616 OUT EFI_BROWSER_ACTION_REQUEST
*ActionRequest
619 if ((Action
== EFI_BROWSER_ACTION_FORM_OPEN
) || (Action
== EFI_BROWSER_ACTION_FORM_CLOSE
)) {
621 // Do nothing for UEFI OPEN/CLOSE Action
626 if ((Value
== NULL
) || (ActionRequest
== NULL
)) {
627 return EFI_INVALID_PARAMETER
;
630 gCallbackKey
= QuestionId
;
633 // Request to exit SendForm(), so as to switch to selected form
635 *ActionRequest
= EFI_BROWSER_ACTION_REQUEST_EXIT
;
641 Collect and display the platform's driver health relative information, allow user to do interactive
642 operation while the platform is unhealthy.
644 This function display a form which divided into two parts. The one list all modules which has installed
645 driver health protocol. The list usually contain driver name, controller name, and it's health info.
646 While the driver name can't be retrieved, will use device path as backup. The other part of the form provide
647 a choice to the user to repair all platform.
656 EFI_HII_HANDLE HiiHandle
;
657 EFI_BROWSER_ACTION_REQUEST ActionRequest
;
658 EFI_IFR_GUID_LABEL
*StartLabel
;
659 EFI_IFR_GUID_LABEL
*StartLabelRepair
;
660 EFI_IFR_GUID_LABEL
*EndLabel
;
661 EFI_IFR_GUID_LABEL
*EndLabelRepair
;
662 VOID
*StartOpCodeHandle
;
663 VOID
*EndOpCodeHandle
;
664 VOID
*StartOpCodeHandleRepair
;
665 VOID
*EndOpCodeHandleRepair
;
668 EFI_STRING_ID TokenHelp
;
670 EFI_STRING TmpString
;
671 EFI_STRING DriverName
;
672 EFI_STRING ControllerName
;
673 LIST_ENTRY DriverHealthList
;
674 DRIVER_HEALTH_INFO
*DriverHealthInfo
;
676 EFI_DEVICE_PATH_PROTOCOL
*DriverDevicePath
;
679 HiiHandle
= gDeviceManagerPrivate
.DriverHealthHiiHandle
;
682 DriverHealthInfo
= NULL
;
683 DriverDevicePath
= NULL
;
684 InitializeListHead (&DriverHealthList
);
687 // Allocate space for creation of UpdateData Buffer
689 StartOpCodeHandle
= HiiAllocateOpCodeHandle ();
690 ASSERT (StartOpCodeHandle
!= NULL
);
692 EndOpCodeHandle
= HiiAllocateOpCodeHandle ();
693 ASSERT (EndOpCodeHandle
!= NULL
);
695 StartOpCodeHandleRepair
= HiiAllocateOpCodeHandle ();
696 ASSERT (StartOpCodeHandleRepair
!= NULL
);
698 EndOpCodeHandleRepair
= HiiAllocateOpCodeHandle ();
699 ASSERT (EndOpCodeHandleRepair
!= NULL
);
702 // Create Hii Extend Label OpCode as the start opcode
704 StartLabel
= (EFI_IFR_GUID_LABEL
*) HiiCreateGuidOpCode (StartOpCodeHandle
, &gEfiIfrTianoGuid
, NULL
, sizeof (EFI_IFR_GUID_LABEL
));
705 StartLabel
->ExtendOpCode
= EFI_IFR_EXTEND_OP_LABEL
;
706 StartLabel
->Number
= LABEL_DRIVER_HEALTH
;
709 // Create Hii Extend Label OpCode as the start opcode
711 StartLabelRepair
= (EFI_IFR_GUID_LABEL
*) HiiCreateGuidOpCode (StartOpCodeHandleRepair
, &gEfiIfrTianoGuid
, NULL
, sizeof (EFI_IFR_GUID_LABEL
));
712 StartLabelRepair
->ExtendOpCode
= EFI_IFR_EXTEND_OP_LABEL
;
713 StartLabelRepair
->Number
= LABEL_DRIVER_HEALTH_REAPIR_ALL
;
716 // Create Hii Extend Label OpCode as the end opcode
718 EndLabel
= (EFI_IFR_GUID_LABEL
*) HiiCreateGuidOpCode (EndOpCodeHandle
, &gEfiIfrTianoGuid
, NULL
, sizeof (EFI_IFR_GUID_LABEL
));
719 EndLabel
->ExtendOpCode
= EFI_IFR_EXTEND_OP_LABEL
;
720 EndLabel
->Number
= LABEL_DRIVER_HEALTH_END
;
723 // Create Hii Extend Label OpCode as the end opcode
725 EndLabelRepair
= (EFI_IFR_GUID_LABEL
*) HiiCreateGuidOpCode (EndOpCodeHandleRepair
, &gEfiIfrTianoGuid
, NULL
, sizeof (EFI_IFR_GUID_LABEL
));
726 EndLabelRepair
->ExtendOpCode
= EFI_IFR_EXTEND_OP_LABEL
;
727 EndLabelRepair
->Number
= LABEL_DRIVER_HEALTH_REAPIR_ALL_END
;
729 HiiCreateSubTitleOpCode (StartOpCodeHandle
, STRING_TOKEN (STR_DH_STATUS_LIST
), 0, 0, 1);
731 Status
= GetAllControllersHealthStatus (&DriverHealthList
);
732 ASSERT (Status
!= EFI_OUT_OF_RESOURCES
);
734 Link
= GetFirstNode (&DriverHealthList
);
736 while (!IsNull (&DriverHealthList
, Link
)) {
737 DriverHealthInfo
= DEVICE_MANAGER_HEALTH_INFO_FROM_LINK (Link
);
740 // Assume no line strings is longer than 512 bytes.
742 String
= (EFI_STRING
) AllocateZeroPool (0x200);
743 ASSERT (String
!= NULL
);
745 Status
= DriverHealthGetDriverName (DriverHealthInfo
->DriverHandle
, &DriverName
);
746 if (EFI_ERROR (Status
)) {
748 // Can not get the Driver name, so use the Device path
750 DriverDevicePath
= DevicePathFromHandle (DriverHealthInfo
->DriverHandle
);
751 DriverName
= DevicePathToStr (DriverDevicePath
);
754 // Add the Driver name & Controller name into FormSetTitle string
756 StrnCat (String
, DriverName
, StrLen (DriverName
));
759 Status
= DriverHealthGetControllerName (
760 DriverHealthInfo
->DriverHandle
,
761 DriverHealthInfo
->ControllerHandle
,
762 DriverHealthInfo
->ChildHandle
,
766 if (!EFI_ERROR (Status
)) {
768 // Can not get the Controller name, just let it empty.
770 StrnCat (String
, L
" ", StrLen (L
" "));
771 StrnCat (String
, ControllerName
, StrLen (ControllerName
));
775 // Add the message of the Module itself provided after the string item.
777 if ((DriverHealthInfo
->MessageList
!= NULL
) && (DriverHealthInfo
->MessageList
->StringId
!= 0)) {
778 StrnCat (String
, L
" ", StrLen (L
" "));
779 TmpString
= HiiGetString (
780 DriverHealthInfo
->MessageList
->HiiHandle
,
781 DriverHealthInfo
->MessageList
->StringId
,
785 // Assert if can not retrieve the message string
787 ASSERT (TmpString
!= NULL
);
788 StrnCat (String
, TmpString
, StrLen (TmpString
));
789 FreePool (TmpString
);
792 // Update the string will be displayed base on the driver's health status
794 switch(DriverHealthInfo
->HealthStatus
) {
795 case EfiDriverHealthStatusRepairRequired
:
796 Length
= StrLen (GetStringById (STRING_TOKEN (STR_REPAIR_REQUIRED
)));
797 StrnCat (String
, GetStringById (STRING_TOKEN (STR_REPAIR_REQUIRED
)), Length
);
799 case EfiDriverHealthStatusConfigurationRequired
:
800 Length
= StrLen (GetStringById (STRING_TOKEN (STR_CONFIGURATION_REQUIRED
)));
801 StrnCat (String
, GetStringById (STRING_TOKEN (STR_CONFIGURATION_REQUIRED
)), Length
);
803 case EfiDriverHealthStatusFailed
:
804 Length
= StrLen (GetStringById (STRING_TOKEN (STR_OPERATION_FAILED
)));
805 StrnCat (String
, GetStringById (STRING_TOKEN (STR_OPERATION_FAILED
)), Length
);
807 case EfiDriverHealthStatusReconnectRequired
:
808 Length
= StrLen (GetStringById (STRING_TOKEN (STR_RECONNECT_REQUIRED
)));
809 StrnCat (String
, GetStringById (STRING_TOKEN (STR_RECONNECT_REQUIRED
)), Length
);
811 case EfiDriverHealthStatusRebootRequired
:
812 Length
= StrLen (GetStringById (STRING_TOKEN (STR_REBOOT_REQUIRED
)));
813 StrnCat (String
, GetStringById (STRING_TOKEN (STR_REBOOT_REQUIRED
)), Length
);
816 Length
= StrLen (GetStringById (STRING_TOKEN (STR_DRIVER_HEALTH_HEALTHY
)));
817 StrnCat (String
, GetStringById (STRING_TOKEN (STR_DRIVER_HEALTH_HEALTHY
)), Length
);
822 Token
= HiiSetString (HiiHandle
, 0, String
, NULL
);
825 TokenHelp
= HiiSetString (HiiHandle
, 0, GetStringById( STRING_TOKEN (STR_DH_REPAIR_SINGLE_HELP
)), NULL
);
827 HiiCreateActionOpCode (
829 (EFI_QUESTION_ID
) (Index
+ DRIVER_HEALTH_KEY_OFFSET
),
832 EFI_IFR_FLAG_CALLBACK
,
836 Link
= GetNextNode (&DriverHealthList
, Link
);
840 // Add End Opcode for Subtitle
842 HiiCreateEndOpCode (StartOpCodeHandle
);
844 HiiCreateSubTitleOpCode (StartOpCodeHandleRepair
, STRING_TOKEN (STR_DRIVER_HEALTH_REPAIR_ALL
), 0, 0, 1);
845 TokenHelp
= HiiSetString (HiiHandle
, 0, GetStringById( STRING_TOKEN (STR_DH_REPAIR_ALL_HELP
)), NULL
);
847 if (PlaformHealthStatusCheck ()) {
849 // No action need to do for the platform
851 Token
= HiiSetString (HiiHandle
, 0, GetStringById( STRING_TOKEN (STR_DRIVER_HEALTH_ALL_HEALTHY
)), NULL
);
852 HiiCreateActionOpCode (
853 StartOpCodeHandleRepair
,
857 EFI_IFR_FLAG_READ_ONLY
,
862 // Create ActionOpCode only while the platform need to do health related operation.
864 Token
= HiiSetString (HiiHandle
, 0, GetStringById( STRING_TOKEN (STR_DH_REPAIR_ALL_TITLE
)), NULL
);
865 HiiCreateActionOpCode (
866 StartOpCodeHandleRepair
,
867 (EFI_QUESTION_ID
) DRIVER_HEALTH_REPAIR_ALL_KEY
,
870 EFI_IFR_FLAG_CALLBACK
,
875 HiiCreateEndOpCode (StartOpCodeHandleRepair
);
877 Status
= HiiUpdateForm (
880 DRIVER_HEALTH_FORM_ID
,
884 ASSERT (Status
!= EFI_NOT_FOUND
);
885 ASSERT (Status
!= EFI_BUFFER_TOO_SMALL
);
887 Status
= HiiUpdateForm (
890 DRIVER_HEALTH_FORM_ID
,
891 StartOpCodeHandleRepair
,
892 EndOpCodeHandleRepair
894 ASSERT (Status
!= EFI_NOT_FOUND
);
895 ASSERT (Status
!= EFI_BUFFER_TOO_SMALL
);
897 ActionRequest
= EFI_BROWSER_ACTION_REQUEST_NONE
;
898 Status
= gFormBrowser2
->SendForm (
903 DRIVER_HEALTH_FORM_ID
,
907 if (ActionRequest
== EFI_BROWSER_ACTION_REQUEST_RESET
) {
908 EnableResetRequired ();
912 // We will have returned from processing a callback - user either hit ESC to exit, or selected
913 // a target to display.
914 // Process the diver health status states here.
916 if (gCallbackKey
>= DRIVER_HEALTH_KEY_OFFSET
&& gCallbackKey
!= DRIVER_HEALTH_REPAIR_ALL_KEY
) {
917 ActionRequest
= EFI_BROWSER_ACTION_REQUEST_NONE
;
919 Link
= GetFirstNode (&DriverHealthList
);
922 while (!IsNull (&DriverHealthList
, Link
)) {
924 // Got the item relative node in the List
926 if (Index
== (gCallbackKey
- DRIVER_HEALTH_KEY_OFFSET
)) {
927 DriverHealthInfo
= DEVICE_MANAGER_HEALTH_INFO_FROM_LINK (Link
);
929 // Process the driver's healthy status for the specify module
931 ProcessSingleControllerHealth (
932 DriverHealthInfo
->DriverHealth
,
933 DriverHealthInfo
->ControllerHandle
,
934 DriverHealthInfo
->ChildHandle
,
935 DriverHealthInfo
->HealthStatus
,
936 &(DriverHealthInfo
->MessageList
),
937 DriverHealthInfo
->HiiHandle
942 Link
= GetNextNode (&DriverHealthList
, Link
);
945 if (ActionRequest
== EFI_BROWSER_ACTION_REQUEST_RESET
) {
946 EnableResetRequired ();
950 // Force return to the form of Driver Health in Device Manager
952 gCallbackKey
= DRIVER_HEALTH_RETURN_KEY
;
956 // Repair the whole platform
958 if (gCallbackKey
== DRIVER_HEALTH_REPAIR_ALL_KEY
) {
959 ActionRequest
= EFI_BROWSER_ACTION_REQUEST_NONE
;
961 PlatformRepairAll (&DriverHealthList
);
963 gCallbackKey
= DRIVER_HEALTH_RETURN_KEY
;
967 // Cleanup dynamic created strings in HII database by reinstall the packagelist
970 HiiRemovePackages (HiiHandle
);
972 gDeviceManagerPrivate
.DriverHealthHiiHandle
= HiiAddPackages (
974 gDeviceManagerPrivate
.DriverHealthHandle
,
979 if (gDeviceManagerPrivate
.DriverHealthHiiHandle
== NULL
) {
980 Status
= EFI_OUT_OF_RESOURCES
;
982 Status
= EFI_SUCCESS
;
985 // Free driver health info list
987 while (!IsListEmpty (&DriverHealthList
)) {
989 Link
= GetFirstNode(&DriverHealthList
);
990 DriverHealthInfo
= DEVICE_MANAGER_HEALTH_INFO_FROM_LINK (Link
);
991 RemoveEntryList (Link
);
993 if (DriverHealthInfo
->MessageList
!= NULL
) {
994 FreePool(DriverHealthInfo
->MessageList
);
995 FreePool (DriverHealthInfo
);
999 HiiFreeOpCodeHandle (StartOpCodeHandle
);
1000 HiiFreeOpCodeHandle (EndOpCodeHandle
);
1001 HiiFreeOpCodeHandle (StartOpCodeHandleRepair
);
1002 HiiFreeOpCodeHandle (EndOpCodeHandleRepair
);
1004 if (gCallbackKey
== DRIVER_HEALTH_RETURN_KEY
) {
1006 // Force return to Driver Health Form
1008 gCallbackKey
= DEVICE_MANAGER_KEY_DRIVER_HEALTH
;
1009 CallDriverHealth ();
1015 Check the Driver Health status of a single controller and try to process it if not healthy.
1017 This function called by CheckAllControllersHealthStatus () function in order to process a specify
1018 contoller's health state.
1020 @param DriverHealthList A Pointer to the list contain all of the platform driver health information.
1021 @param DriverHandle The handle of driver.
1022 @param ControllerHandle The class guid specifies which form set will be displayed.
1023 @param ChildHandle The handle of the child controller to retrieve the health
1024 status on. This is an optional parameter that may be NULL.
1025 @param DriverHealth A pointer to the EFI_DRIVER_HEALTH_PROTOCOL instance.
1026 @param HealthStatus The health status of the controller.
1028 @retval EFI_INVALID_PARAMETER HealthStatus or DriverHealth is NULL.
1029 @retval HealthStatus The Health status of specify controller.
1030 @retval EFI_OUT_OF_RESOURCES The list of Driver Health Protocol handles can not be retrieved.
1031 @retval EFI_NOT_FOUND No controller in the platform install Driver Health Protocol.
1032 @retval EFI_SUCCESS The Health related operation has been taken successfully.
1037 GetSingleControllerHealthStatus (
1038 IN OUT LIST_ENTRY
*DriverHealthList
,
1039 IN EFI_HANDLE DriverHandle
,
1040 IN EFI_HANDLE ControllerHandle
, OPTIONAL
1041 IN EFI_HANDLE ChildHandle
, OPTIONAL
1042 IN EFI_DRIVER_HEALTH_PROTOCOL
*DriverHealth
,
1043 IN EFI_DRIVER_HEALTH_STATUS
*HealthStatus
1047 EFI_DRIVER_HEALTH_HII_MESSAGE
*MessageList
;
1048 EFI_HII_HANDLE FormHiiHandle
;
1049 DRIVER_HEALTH_INFO
*DriverHealthInfo
;
1051 if (HealthStatus
== NULL
) {
1053 // If HealthStatus is NULL, then return EFI_INVALID_PARAMETER
1055 return EFI_INVALID_PARAMETER
;
1059 // Assume the HealthStatus is healthy
1061 *HealthStatus
= EfiDriverHealthStatusHealthy
;
1063 if (DriverHealth
== NULL
) {
1065 // If DriverHealth is NULL, then return EFI_INVALID_PARAMETER
1067 return EFI_INVALID_PARAMETER
;
1070 if (ControllerHandle
== NULL
) {
1072 // If ControllerHandle is NULL, the return the cumulative health status of the driver
1074 Status
= DriverHealth
->GetHealthStatus (DriverHealth
, NULL
, NULL
, HealthStatus
, NULL
, NULL
);
1075 if (*HealthStatus
== EfiDriverHealthStatusHealthy
) {
1077 // Add the driver health related information into the list
1079 DriverHealthInfo
= AllocateZeroPool (sizeof (DRIVER_HEALTH_INFO
));
1080 if (DriverHealthInfo
== NULL
) {
1081 return EFI_OUT_OF_RESOURCES
;
1084 DriverHealthInfo
->Signature
= DEVICE_MANAGER_DRIVER_HEALTH_INFO_SIGNATURE
;
1085 DriverHealthInfo
->DriverHandle
= DriverHandle
;
1086 DriverHealthInfo
->ControllerHandle
= NULL
;
1087 DriverHealthInfo
->ChildHandle
= NULL
;
1088 DriverHealthInfo
->HiiHandle
= NULL
;
1089 DriverHealthInfo
->DriverHealth
= DriverHealth
;
1090 DriverHealthInfo
->MessageList
= NULL
;
1091 DriverHealthInfo
->HealthStatus
= *HealthStatus
;
1093 InsertTailList (DriverHealthList
, &DriverHealthInfo
->Link
);
1099 FormHiiHandle
= NULL
;
1102 // Collect the health status with the optional HII message list
1104 Status
= DriverHealth
->GetHealthStatus (DriverHealth
, ControllerHandle
, ChildHandle
, HealthStatus
, &MessageList
, &FormHiiHandle
);
1106 if (EFI_ERROR (Status
)) {
1108 // If the health status could not be retrieved, then return immediately
1114 // Add the driver health related information into the list
1116 DriverHealthInfo
= AllocateZeroPool (sizeof (DRIVER_HEALTH_INFO
));
1117 if (DriverHealthInfo
== NULL
) {
1118 return EFI_OUT_OF_RESOURCES
;
1121 DriverHealthInfo
->Signature
= DEVICE_MANAGER_DRIVER_HEALTH_INFO_SIGNATURE
;
1122 DriverHealthInfo
->DriverHandle
= DriverHandle
;
1123 DriverHealthInfo
->ControllerHandle
= ControllerHandle
;
1124 DriverHealthInfo
->ChildHandle
= ChildHandle
;
1125 DriverHealthInfo
->HiiHandle
= FormHiiHandle
;
1126 DriverHealthInfo
->DriverHealth
= DriverHealth
;
1127 DriverHealthInfo
->MessageList
= MessageList
;
1128 DriverHealthInfo
->HealthStatus
= *HealthStatus
;
1130 InsertTailList (DriverHealthList
, &DriverHealthInfo
->Link
);
1136 Collects all the EFI Driver Health Protocols currently present in the EFI Handle Database,
1137 and queries each EFI Driver Health Protocol to determine if one or more of the controllers
1138 managed by each EFI Driver Health Protocol instance are not healthy.
1140 @param DriverHealthList A Pointer to the list contain all of the platform driver health
1143 @retval EFI_NOT_FOUND No controller in the platform install Driver Health Protocol.
1144 @retval EFI_SUCCESS All the controllers in the platform are healthy.
1145 @retval EFI_OUT_OF_RESOURCES The list of Driver Health Protocol handles can not be retrieved.
1149 GetAllControllersHealthStatus (
1150 IN OUT LIST_ENTRY
*DriverHealthList
1155 EFI_HANDLE
*DriverHealthHandles
;
1156 EFI_DRIVER_HEALTH_PROTOCOL
*DriverHealth
;
1157 EFI_DRIVER_HEALTH_STATUS HealthStatus
;
1158 UINTN DriverHealthIndex
;
1159 EFI_HANDLE
*Handles
;
1161 UINTN ControllerIndex
;
1165 // Initialize local variables
1168 DriverHealthHandles
= NULL
;
1172 HealthStatus
= EfiDriverHealthStatusHealthy
;
1174 Status
= gBS
->LocateHandleBuffer (
1176 &gEfiDriverHealthProtocolGuid
,
1179 &DriverHealthHandles
1182 if (Status
== EFI_NOT_FOUND
|| NumHandles
== 0) {
1184 // If there are no Driver Health Protocols handles, then return EFI_NOT_FOUND
1186 return EFI_NOT_FOUND
;
1189 if (EFI_ERROR (Status
) || DriverHealthHandles
== NULL
) {
1191 // If the list of Driver Health Protocol handles can not be retrieved, then
1192 // return EFI_OUT_OF_RESOURCES
1194 return EFI_OUT_OF_RESOURCES
;
1198 // Check the health status of all controllers in the platform
1199 // Start by looping through all the Driver Health Protocol handles in the handle database
1201 for (DriverHealthIndex
= 0; DriverHealthIndex
< NumHandles
; DriverHealthIndex
++) {
1203 // Skip NULL Driver Health Protocol handles
1205 if (DriverHealthHandles
[DriverHealthIndex
] == NULL
) {
1210 // Retrieve the Driver Health Protocol from DriverHandle
1212 Status
= gBS
->HandleProtocol (
1213 DriverHealthHandles
[DriverHealthIndex
],
1214 &gEfiDriverHealthProtocolGuid
,
1215 (VOID
**)&DriverHealth
1217 if (EFI_ERROR (Status
)) {
1219 // If the Driver Health Protocol can not be retrieved, then skip to the next
1220 // Driver Health Protocol handle
1226 // Check the health of all the controllers managed by a Driver Health Protocol handle
1228 Status
= GetSingleControllerHealthStatus (DriverHealthList
, DriverHealthHandles
[DriverHealthIndex
], NULL
, NULL
, DriverHealth
, &HealthStatus
);
1231 // If Status is an error code, then the health information could not be retrieved, so assume healthy
1232 // and skip to the next Driver Health Protocol handle
1234 if (EFI_ERROR (Status
)) {
1239 // If all the controllers managed by this Driver Health Protocol are healthy, then skip to the next
1240 // Driver Health Protocol handle
1242 if (HealthStatus
== EfiDriverHealthStatusHealthy
) {
1247 // See if the list of all handles in the handle database has been retrieved
1250 if (Handles
== NULL
) {
1252 // Retrieve the list of all handles from the handle database
1254 Status
= gBS
->LocateHandleBuffer (
1261 if (EFI_ERROR (Status
) || Handles
== NULL
) {
1263 // If all the handles in the handle database can not be retrieved, then
1264 // return EFI_OUT_OF_RESOURCES
1266 Status
= EFI_OUT_OF_RESOURCES
;
1271 // Loop through all the controller handles in the handle database
1273 for (ControllerIndex
= 0; ControllerIndex
< HandleCount
; ControllerIndex
++) {
1275 // Skip NULL controller handles
1277 if (Handles
[ControllerIndex
] == NULL
) {
1281 Status
= GetSingleControllerHealthStatus (DriverHealthList
, DriverHealthHandles
[DriverHealthIndex
], Handles
[ControllerIndex
], NULL
, DriverHealth
, &HealthStatus
);
1282 if (EFI_ERROR (Status
)) {
1284 // If Status is an error code, then the health information could not be retrieved, so assume healthy
1286 HealthStatus
= EfiDriverHealthStatusHealthy
;
1290 // If CheckHealthSingleController() returned an error on a terminal state, then do not check the health of child controllers
1292 if (EFI_ERROR (Status
)) {
1297 // Loop through all the child handles in the handle database
1299 for (ChildIndex
= 0; ChildIndex
< HandleCount
; ChildIndex
++) {
1301 // Skip NULL child handles
1303 if (Handles
[ChildIndex
] == NULL
) {
1307 Status
= GetSingleControllerHealthStatus (DriverHealthList
, DriverHealthHandles
[DriverHealthIndex
], Handles
[ControllerIndex
], Handles
[ChildIndex
], DriverHealth
, &HealthStatus
);
1308 if (EFI_ERROR (Status
)) {
1310 // If Status is an error code, then the health information could not be retrieved, so assume healthy
1312 HealthStatus
= EfiDriverHealthStatusHealthy
;
1316 // If CheckHealthSingleController() returned an error on a terminal state, then skip to the next child
1318 if (EFI_ERROR (Status
)) {
1325 Status
= EFI_SUCCESS
;
1328 if (Handles
!= NULL
) {
1329 gBS
->FreePool (Handles
);
1331 if (DriverHealthHandles
!= NULL
) {
1332 gBS
->FreePool (DriverHealthHandles
);
1340 Check the healthy status of the platform, this function will return immediately while found one driver
1341 in the platform are not healthy.
1343 @retval FALSE at least one driver in the platform are not healthy.
1344 @retval TRUE No controller install Driver Health Protocol,
1345 or all controllers in the platform are in healthy status.
1348 PlaformHealthStatusCheck (
1352 EFI_DRIVER_HEALTH_STATUS HealthStatus
;
1356 EFI_HANDLE
*DriverHealthHandles
;
1357 EFI_DRIVER_HEALTH_PROTOCOL
*DriverHealth
;
1361 // Initialize local variables
1363 DriverHealthHandles
= NULL
;
1364 DriverHealth
= NULL
;
1366 HealthStatus
= EfiDriverHealthStatusHealthy
;
1368 Status
= gBS
->LocateHandleBuffer (
1370 &gEfiDriverHealthProtocolGuid
,
1373 &DriverHealthHandles
1376 // There are no handles match the search for Driver Health Protocol has been installed.
1378 if (Status
== EFI_NOT_FOUND
) {
1382 // Assume all modules are healthy.
1387 // Found one or more Handles.
1389 if (!EFI_ERROR (Status
)) {
1390 for (Index
= 0; Index
< NoHandles
; Index
++) {
1391 Status
= gBS
->HandleProtocol (
1392 DriverHealthHandles
[Index
],
1393 &gEfiDriverHealthProtocolGuid
,
1394 (VOID
**) &DriverHealth
1396 if (!EFI_ERROR (Status
)) {
1397 Status
= DriverHealth
->GetHealthStatus (
1407 // Get the healthy status of the module
1409 if (!EFI_ERROR (Status
)) {
1410 if (HealthStatus
!= EfiDriverHealthStatusHealthy
) {
1412 // Return immediately one driver's status not in healthy.
1423 Processes a single controller using the EFI Driver Health Protocol associated with
1424 that controller. This algorithm continues to query the GetHealthStatus() service until
1425 one of the legal terminal states of the EFI Driver Health Protocol is reached. This may
1426 require the processing of HII Messages, HII Form, and invocation of repair operations.
1428 @param DriverHealth A pointer to the EFI_DRIVER_HEALTH_PROTOCOL instance.
1429 @param ControllerHandle The class guid specifies which form set will be displayed.
1430 @param ChildHandle The handle of the child controller to retrieve the health
1431 status on. This is an optional parameter that may be NULL.
1432 @param HealthStatus The health status of the controller.
1433 @param MessageList An array of warning or error messages associated
1434 with the controller specified by ControllerHandle and
1435 ChildHandle. This is an optional parameter that may be NULL.
1436 @param FormHiiHandle The HII handle for an HII form associated with the
1437 controller specified by ControllerHandle and ChildHandle.
1440 ProcessSingleControllerHealth (
1441 IN EFI_DRIVER_HEALTH_PROTOCOL
*DriverHealth
,
1442 IN EFI_HANDLE ControllerHandle
, OPTIONAL
1443 IN EFI_HANDLE ChildHandle
, OPTIONAL
1444 IN EFI_DRIVER_HEALTH_STATUS HealthStatus
,
1445 IN EFI_DRIVER_HEALTH_HII_MESSAGE
**MessageList
, OPTIONAL
1446 IN EFI_HII_HANDLE FormHiiHandle
1450 EFI_DRIVER_HEALTH_STATUS LocalHealthStatus
;
1452 LocalHealthStatus
= HealthStatus
;
1454 // If the module need to be repaired or reconfiguration, will process it until
1455 // reach a terminal status. The status from EfiDriverHealthStatusRepairRequired after repair
1456 // will be in (Health, Failed, Configuration Required).
1458 while( LocalHealthStatus
== EfiDriverHealthStatusConfigurationRequired
||
1459 LocalHealthStatus
== EfiDriverHealthStatusRepairRequired
) {
1461 if (LocalHealthStatus
== EfiDriverHealthStatusRepairRequired
) {
1462 Status
= DriverHealth
->Repair (
1466 (EFI_DRIVER_HEALTH_REPAIR_PROGRESS_NOTIFY
) RepairNotify
1470 // Via a form of the driver need to do configuration provided to process of status in
1471 // EfiDriverHealthStatusConfigurationRequired. The status after configuration should be in
1472 // (Healthy, Reboot Required, Failed, Reconnect Required, Repair Required).
1474 if (LocalHealthStatus
== EfiDriverHealthStatusConfigurationRequired
) {
1475 Status
= gFormBrowser2
->SendForm (
1479 &gEfiHiiDriverHealthFormsetGuid
,
1484 ASSERT( !EFI_ERROR (Status
));
1487 Status
= DriverHealth
->GetHealthStatus (
1495 ASSERT_EFI_ERROR (Status
);
1497 if (*MessageList
!= NULL
) {
1498 ProcessMessages (*MessageList
);
1503 // Health status in {Healthy, Failed} may also have Messages need to process
1505 if (LocalHealthStatus
== EfiDriverHealthStatusHealthy
|| LocalHealthStatus
== EfiDriverHealthStatusFailed
) {
1506 if (*MessageList
!= NULL
) {
1507 ProcessMessages (*MessageList
);
1511 // Check for RebootRequired or ReconnectRequired
1513 if (LocalHealthStatus
== EfiDriverHealthStatusRebootRequired
) {
1514 gRT
->ResetSystem (EfiResetWarm
, EFI_SUCCESS
, 0, NULL
);
1518 // Do reconnect if need.
1520 if (LocalHealthStatus
== EfiDriverHealthStatusReconnectRequired
) {
1521 Status
= gBS
->DisconnectController (ControllerHandle
, NULL
, NULL
);
1522 if (EFI_ERROR (Status
)) {
1524 // Disconnect failed. Need to promote reconnect to a reboot.
1526 gRT
->ResetSystem (EfiResetWarm
, EFI_SUCCESS
, 0, NULL
);
1528 gBS
->ConnectController (ControllerHandle
, NULL
, NULL
, TRUE
);
1534 Platform specific notification function for controller repair operations.
1536 If the driver for a controller support the Driver Health Protocol and the
1537 current state of the controller is EfiDriverHealthStatusRepairRequired then
1538 when the Repair() service of the Driver Health Protocol is called, this
1539 platform specific notification function can display the progress of the repair
1540 operation. Some platforms may choose to not display anything, other may choose
1541 to show the percentage complete on text consoles, and other may choose to render
1542 a progress bar on text and graphical consoles.
1544 This function displays the percentage of the repair operation that has been
1545 completed on text consoles. The percentage is Value / Limit * 100%.
1547 @param Value Value in the range 0..Limit the the repair has completed..
1548 @param Limit The maximum value of Value
1560 Print(L
"Repair Progress Undefined\n\r");
1562 Percent
= Value
* 100 / Limit
;
1563 Print(L
"Repair Progress = %3d%%\n\r", Percent
);
1568 Processes a set of messages returned by the GetHealthStatus ()
1569 service of the EFI Driver Health Protocol
1571 @param MessageList The MessageList point to messages need to processed.
1576 IN EFI_DRIVER_HEALTH_HII_MESSAGE
*MessageList
1580 EFI_STRING MessageString
;
1582 for (MessageIndex
= 0;
1583 MessageList
[MessageIndex
].HiiHandle
!= NULL
;
1586 MessageString
= HiiGetString (
1587 MessageList
[MessageIndex
].HiiHandle
,
1588 MessageList
[MessageIndex
].StringId
,
1591 if (MessageString
!= NULL
) {
1593 // User can customize the output. Just simply print out the MessageString like below.
1594 // Also can use the HiiHandle to display message on the front page.
1596 // Print(L"%s\n",MessageString);
1597 // gBS->Stall (100000);
1604 Repair the whole platform.
1606 This function is the main entry for user choose "Repair All" in the front page.
1607 It will try to do recovery job till all the driver health protocol installed modules
1608 reach a terminal state.
1610 @param DriverHealthList A Pointer to the list contain all of the platform driver health
1616 IN LIST_ENTRY
*DriverHealthList
1619 DRIVER_HEALTH_INFO
*DriverHealthInfo
;
1622 ASSERT (DriverHealthList
!= NULL
);
1624 Link
= GetFirstNode (DriverHealthList
);
1626 while (!IsNull (DriverHealthList
, Link
)) {
1627 DriverHealthInfo
= DEVICE_MANAGER_HEALTH_INFO_FROM_LINK (Link
);
1629 // Do driver health status operation by each link node
1631 ASSERT (DriverHealthInfo
!= NULL
);
1633 ProcessSingleControllerHealth (
1634 DriverHealthInfo
->DriverHealth
,
1635 DriverHealthInfo
->ControllerHandle
,
1636 DriverHealthInfo
->ChildHandle
,
1637 DriverHealthInfo
->HealthStatus
,
1638 &(DriverHealthInfo
->MessageList
),
1639 DriverHealthInfo
->HiiHandle
1642 Link
= GetNextNode (DriverHealthList
, Link
);
1648 Select the best matching language according to front page policy for best user experience.
1650 This function supports both ISO 639-2 and RFC 4646 language codes, but language
1651 code types may not be mixed in a single call to this function.
1653 @param SupportedLanguages A pointer to a Null-terminated ASCII string that
1654 contains a set of language codes in the format
1655 specified by Iso639Language.
1656 @param Iso639Language If TRUE, then all language codes are assumed to be
1657 in ISO 639-2 format. If FALSE, then all language
1658 codes are assumed to be in RFC 4646 language format.
1660 @retval NULL The best matching language could not be found in SupportedLanguages.
1661 @retval NULL There are not enough resources available to return the best matching
1663 @retval Other A pointer to a Null-terminated ASCII string that is the best matching
1664 language in SupportedLanguages.
1667 DriverHealthSelectBestLanguage (
1668 IN CHAR8
*SupportedLanguages
,
1669 IN BOOLEAN Iso639Language
1672 CHAR8
*LanguageVariable
;
1673 CHAR8
*BestLanguage
;
1675 LanguageVariable
= GetEfiGlobalVariable (Iso639Language
? L
"Lang" : L
"PlatformLang");
1677 BestLanguage
= GetBestLanguage(
1680 (LanguageVariable
!= NULL
) ? LanguageVariable
: "",
1681 Iso639Language
? "eng" : "en-US",
1684 if (LanguageVariable
!= NULL
) {
1685 FreePool (LanguageVariable
);
1688 return BestLanguage
;
1695 This is an internal worker function to get the Component Name (2) protocol interface
1696 and the language it supports.
1698 @param ProtocolGuid A pointer to an EFI_GUID. It points to Component Name (2) protocol GUID.
1699 @param DriverBindingHandle The handle on which the Component Name (2) protocol instance is retrieved.
1700 @param ComponentName A pointer to the Component Name (2) protocol interface.
1701 @param SupportedLanguage The best suitable language that matches the SupportedLangues interface for the
1702 located Component Name (2) instance.
1704 @retval EFI_SUCCESS The Component Name (2) protocol instance is successfully located and we find
1705 the best matching language it support.
1706 @retval EFI_UNSUPPORTED The input Language is not supported by the Component Name (2) protocol.
1707 @retval Other Some error occurs when locating Component Name (2) protocol instance or finding
1708 the supported language.
1712 GetComponentNameWorker (
1713 IN EFI_GUID
*ProtocolGuid
,
1714 IN EFI_HANDLE DriverBindingHandle
,
1715 OUT EFI_COMPONENT_NAME_PROTOCOL
**ComponentName
,
1716 OUT CHAR8
**SupportedLanguage
1722 // Locate Component Name (2) protocol on the driver binging handle.
1724 Status
= gBS
->OpenProtocol (
1725 DriverBindingHandle
,
1727 (VOID
**) ComponentName
,
1730 EFI_OPEN_PROTOCOL_GET_PROTOCOL
1732 if (EFI_ERROR (Status
)) {
1737 // Apply shell policy to select the best language.
1739 *SupportedLanguage
= DriverHealthSelectBestLanguage (
1740 (*ComponentName
)->SupportedLanguages
,
1741 (BOOLEAN
) (ProtocolGuid
== &gEfiComponentNameProtocolGuid
)
1743 if (*SupportedLanguage
== NULL
) {
1744 Status
= EFI_UNSUPPORTED
;
1752 This is an internal worker function to get driver name from Component Name (2) protocol interface.
1755 @param ProtocolGuid A pointer to an EFI_GUID. It points to Component Name (2) protocol GUID.
1756 @param DriverBindingHandle The handle on which the Component Name (2) protocol instance is retrieved.
1757 @param DriverName A pointer to the Unicode string to return. This Unicode string is the name
1758 of the driver specified by This.
1760 @retval EFI_SUCCESS The driver name is successfully retrieved from Component Name (2) protocol
1762 @retval Other The driver name cannot be retrieved from Component Name (2) protocol
1767 GetDriverNameWorker (
1768 IN EFI_GUID
*ProtocolGuid
,
1769 IN EFI_HANDLE DriverBindingHandle
,
1770 OUT CHAR16
**DriverName
1774 CHAR8
*BestLanguage
;
1775 EFI_COMPONENT_NAME_PROTOCOL
*ComponentName
;
1778 // Retrieve Component Name (2) protocol instance on the driver binding handle and
1779 // find the best language this instance supports.
1781 Status
= GetComponentNameWorker (
1783 DriverBindingHandle
,
1787 if (EFI_ERROR (Status
)) {
1792 // Get the driver name from Component Name (2) protocol instance on the driver binging handle.
1794 Status
= ComponentName
->GetDriverName (
1799 FreePool (BestLanguage
);
1806 This function gets driver name from Component Name 2 protocol interface and Component Name protocol interface
1807 in turn. It first tries UEFI 2.0 Component Name 2 protocol interface and try to get the driver name.
1808 If the attempt fails, it then gets the driver name from EFI 1.1 Component Name protocol for backward
1809 compatibility support.
1811 @param DriverBindingHandle The handle on which the Component Name (2) protocol instance is retrieved.
1812 @param DriverName A pointer to the Unicode string to return. This Unicode string is the name
1813 of the driver specified by This.
1815 @retval EFI_SUCCESS The driver name is successfully retrieved from Component Name (2) protocol
1817 @retval Other The driver name cannot be retrieved from Component Name (2) protocol
1822 DriverHealthGetDriverName (
1823 IN EFI_HANDLE DriverBindingHandle
,
1824 OUT CHAR16
**DriverName
1830 // Get driver name from UEFI 2.0 Component Name 2 protocol interface.
1832 Status
= GetDriverNameWorker (&gEfiComponentName2ProtocolGuid
, DriverBindingHandle
, DriverName
);
1833 if (EFI_ERROR (Status
)) {
1835 // If it fails to get the driver name from Component Name protocol interface, we should fall back on
1836 // EFI 1.1 Component Name protocol interface.
1838 Status
= GetDriverNameWorker (&gEfiComponentNameProtocolGuid
, DriverBindingHandle
, DriverName
);
1847 This function gets controller name from Component Name 2 protocol interface and Component Name protocol interface
1848 in turn. It first tries UEFI 2.0 Component Name 2 protocol interface and try to get the controller name.
1849 If the attempt fails, it then gets the controller name from EFI 1.1 Component Name protocol for backward
1850 compatibility support.
1852 @param ProtocolGuid A pointer to an EFI_GUID. It points to Component Name (2) protocol GUID.
1853 @param DriverBindingHandle The handle on which the Component Name (2) protocol instance is retrieved.
1854 @param ControllerHandle The handle of a controller that the driver specified by This is managing.
1855 This handle specifies the controller whose name is to be returned.
1856 @param ChildHandle The handle of the child controller to retrieve the name of. This is an
1857 optional parameter that may be NULL. It will be NULL for device drivers.
1858 It will also be NULL for bus drivers that attempt to retrieve the name
1859 of the bus controller. It will not be NULL for a bus driver that attempts
1860 to retrieve the name of a child controller.
1861 @param ControllerName A pointer to the Unicode string to return. This Unicode string
1862 is the name of the controller specified by ControllerHandle and ChildHandle.
1864 @retval EFI_SUCCESS The controller name is successfully retrieved from Component Name (2) protocol
1866 @retval Other The controller name cannot be retrieved from Component Name (2) protocol.
1870 GetControllerNameWorker (
1871 IN EFI_GUID
*ProtocolGuid
,
1872 IN EFI_HANDLE DriverBindingHandle
,
1873 IN EFI_HANDLE ControllerHandle
,
1874 IN EFI_HANDLE ChildHandle
,
1875 OUT CHAR16
**ControllerName
1879 CHAR8
*BestLanguage
;
1880 EFI_COMPONENT_NAME_PROTOCOL
*ComponentName
;
1883 // Retrieve Component Name (2) protocol instance on the driver binding handle and
1884 // find the best language this instance supports.
1886 Status
= GetComponentNameWorker (
1888 DriverBindingHandle
,
1892 if (EFI_ERROR (Status
)) {
1897 // Get the controller name from Component Name (2) protocol instance on the driver binging handle.
1899 Status
= ComponentName
->GetControllerName (
1906 FreePool (BestLanguage
);
1913 This function gets controller name from Component Name 2 protocol interface and Component Name protocol interface
1914 in turn. It first tries UEFI 2.0 Component Name 2 protocol interface and try to get the controller name.
1915 If the attempt fails, it then gets the controller name from EFI 1.1 Component Name protocol for backward
1916 compatibility support.
1918 @param DriverBindingHandle The handle on which the Component Name (2) protocol instance is retrieved.
1919 @param ControllerHandle The handle of a controller that the driver specified by This is managing.
1920 This handle specifies the controller whose name is to be returned.
1921 @param ChildHandle The handle of the child controller to retrieve the name of. This is an
1922 optional parameter that may be NULL. It will be NULL for device drivers.
1923 It will also be NULL for bus drivers that attempt to retrieve the name
1924 of the bus controller. It will not be NULL for a bus driver that attempts
1925 to retrieve the name of a child controller.
1926 @param ControllerName A pointer to the Unicode string to return. This Unicode string
1927 is the name of the controller specified by ControllerHandle and ChildHandle.
1929 @retval EFI_SUCCESS The controller name is successfully retrieved from Component Name (2) protocol
1931 @retval Other The controller name cannot be retrieved from Component Name (2) protocol.
1935 DriverHealthGetControllerName (
1936 IN EFI_HANDLE DriverBindingHandle
,
1937 IN EFI_HANDLE ControllerHandle
,
1938 IN EFI_HANDLE ChildHandle
,
1939 OUT CHAR16
**ControllerName
1945 // Get controller name from UEFI 2.0 Component Name 2 protocol interface.
1947 Status
= GetControllerNameWorker (
1948 &gEfiComponentName2ProtocolGuid
,
1949 DriverBindingHandle
,
1954 if (EFI_ERROR (Status
)) {
1956 // If it fails to get the controller name from Component Name protocol interface, we should fall back on
1957 // EFI 1.1 Component Name protocol interface.
1959 Status
= GetControllerNameWorker (
1960 &gEfiComponentNameProtocolGuid
,
1961 DriverBindingHandle
,