2 The platform device manager reference implementation
4 Copyright (c) 2004 - 2018, Intel Corporation. All rights reserved.<BR>
5 SPDX-License-Identifier: BSD-2-Clause-Patent
9 #include "DeviceManager.h"
11 DEVICE_MANAGER_CALLBACK_DATA gDeviceManagerPrivate
= {
12 DEVICE_MANAGER_CALLBACK_DATA_SIGNATURE
,
29 #define MAX_MAC_ADDRESS_NODE_LIST_LEN 10
32 // Which Mac Address string is select
33 // it will decide what menu need to show in the NETWORK_DEVICE_FORM_ID form.
35 EFI_STRING mSelectedMacAddrString
;
38 // Which form Id need to be show.
40 EFI_FORM_ID mNextShowFormId
= DEVICE_MANAGER_FORM_ID
;
43 // The Mac Address show in the NETWORK_DEVICE_LIST_FORM_ID
45 MAC_ADDRESS_NODE_LIST mMacDeviceList
;
47 DEVICE_MANAGER_MENU_ITEM mDeviceManagerMenuItemTable
[] = {
48 { STRING_TOKEN (STR_DISK_DEVICE
), EFI_DISK_DEVICE_CLASS
},
49 { STRING_TOKEN (STR_VIDEO_DEVICE
), EFI_VIDEO_DEVICE_CLASS
},
50 { STRING_TOKEN (STR_NETWORK_DEVICE
), EFI_NETWORK_DEVICE_CLASS
},
51 { STRING_TOKEN (STR_INPUT_DEVICE
), EFI_INPUT_DEVICE_CLASS
},
52 { STRING_TOKEN (STR_ON_BOARD_DEVICE
), EFI_ON_BOARD_DEVICE_CLASS
},
53 { STRING_TOKEN (STR_OTHER_DEVICE
), EFI_OTHER_DEVICE_CLASS
}
56 HII_VENDOR_DEVICE_PATH mDeviceManagerHiiVendorDevicePath
= {
62 (UINT8
) (sizeof (VENDOR_DEVICE_PATH
)),
63 (UINT8
) ((sizeof (VENDOR_DEVICE_PATH
)) >> 8)
66 DEVICE_MANAGER_FORMSET_GUID
70 END_ENTIRE_DEVICE_PATH_SUBTYPE
,
72 (UINT8
) (END_DEVICE_PATH_LENGTH
),
73 (UINT8
) ((END_DEVICE_PATH_LENGTH
) >> 8)
78 HII_VENDOR_DEVICE_PATH mDriverHealthHiiVendorDevicePath
= {
84 (UINT8
) (sizeof (VENDOR_DEVICE_PATH
)),
85 (UINT8
) ((sizeof (VENDOR_DEVICE_PATH
)) >> 8)
88 DRIVER_HEALTH_FORMSET_GUID
92 END_ENTIRE_DEVICE_PATH_SUBTYPE
,
94 (UINT8
) (END_DEVICE_PATH_LENGTH
),
95 (UINT8
) ((END_DEVICE_PATH_LENGTH
) >> 8)
101 This function is invoked if user selected a interactive opcode from Device Manager's
102 Formset. The decision by user is saved to gCallbackKey for later processing. If
103 user set VBIOS, the new value is saved to EFI variable.
105 @param This Points to the EFI_HII_CONFIG_ACCESS_PROTOCOL.
106 @param Action Specifies the type of action taken by the browser.
107 @param QuestionId A unique value which is sent to the original exporting driver
108 so that it can identify the type of data to expect.
109 @param Type The type of value for the question.
110 @param Value A pointer to the data being sent to the original exporting driver.
111 @param ActionRequest On return, points to the action requested by the callback function.
113 @retval EFI_SUCCESS The callback successfully handled the action.
114 @retval EFI_INVALID_PARAMETER The setup browser call this function with invalid parameters.
119 DeviceManagerCallback (
120 IN CONST EFI_HII_CONFIG_ACCESS_PROTOCOL
*This
,
121 IN EFI_BROWSER_ACTION Action
,
122 IN EFI_QUESTION_ID QuestionId
,
124 IN EFI_IFR_TYPE_VALUE
*Value
,
125 OUT EFI_BROWSER_ACTION_REQUEST
*ActionRequest
130 if (Action
!= EFI_BROWSER_ACTION_CHANGING
) {
132 // All other action return unsupported.
134 return EFI_UNSUPPORTED
;
138 return EFI_INVALID_PARAMETER
;
141 gCallbackKey
= QuestionId
;
142 if ((QuestionId
< MAX_KEY_SECTION_LEN
+ NETWORK_DEVICE_LIST_KEY_OFFSET
) && (QuestionId
>= NETWORK_DEVICE_LIST_KEY_OFFSET
)) {
144 // If user select the mac address, need to record mac address string to support next form show.
146 for (CurIndex
= 0; CurIndex
< mMacDeviceList
.CurListLen
; CurIndex
++) {
147 if (mMacDeviceList
.NodeList
[CurIndex
].QuestionId
== QuestionId
) {
148 mSelectedMacAddrString
= HiiGetString (gDeviceManagerPrivate
.HiiHandle
, mMacDeviceList
.NodeList
[CurIndex
].PromptId
, NULL
);
158 This function registers HII packages to HII database.
160 @retval EFI_SUCCESS HII packages for the Device Manager were registered successfully.
161 @retval EFI_OUT_OF_RESOURCES HII packages for the Device Manager failed to be registered.
165 InitializeDeviceManager (
172 // Install Device Path Protocol and Config Access protocol to driver handle
174 Status
= gBS
->InstallMultipleProtocolInterfaces (
175 &gDeviceManagerPrivate
.DriverHandle
,
176 &gEfiDevicePathProtocolGuid
,
177 &mDeviceManagerHiiVendorDevicePath
,
178 &gEfiHiiConfigAccessProtocolGuid
,
179 &gDeviceManagerPrivate
.ConfigAccess
,
182 ASSERT_EFI_ERROR (Status
);
184 Status
= gBS
->InstallMultipleProtocolInterfaces (
185 &gDeviceManagerPrivate
.DriverHealthHandle
,
186 &gEfiDevicePathProtocolGuid
,
187 &mDriverHealthHiiVendorDevicePath
,
188 &gEfiHiiConfigAccessProtocolGuid
,
189 &gDeviceManagerPrivate
.DriverHealthConfigAccess
,
192 ASSERT_EFI_ERROR (Status
);
194 mMacDeviceList
.CurListLen
= 0;
195 mMacDeviceList
.MaxListLen
= 0;
201 Extract the displayed formset for given HII handle and class guid.
203 @param Handle The HII handle.
204 @param SetupClassGuid The class guid specifies which form set will be displayed.
205 @param SkipCount Skip some formsets which has processed before.
206 @param FormSetTitle Formset title string.
207 @param FormSetHelp Formset help string.
208 @param FormSetGuid Return the formset guid for this formset.
210 @retval TRUE The formset for given HII handle will be displayed.
211 @return FALSE The formset for given HII handle will not be displayed.
215 ExtractDisplayedHiiFormFromHiiHandle (
216 IN EFI_HII_HANDLE Handle
,
217 IN EFI_GUID
*SetupClassGuid
,
219 OUT EFI_STRING_ID
*FormSetTitle
,
220 OUT EFI_STRING_ID
*FormSetHelp
,
221 OUT EFI_GUID
**FormSetGuid
226 EFI_HII_PACKAGE_LIST_HEADER
*HiiPackageList
;
231 UINT32 PackageListLength
;
232 EFI_HII_PACKAGE_HEADER PackageHeader
;
236 ASSERT (Handle
!= NULL
);
237 ASSERT (SetupClassGuid
!= NULL
);
238 ASSERT (FormSetTitle
!= NULL
);
239 ASSERT (FormSetHelp
!= NULL
);
247 // Get HII PackageList
250 HiiPackageList
= NULL
;
251 Status
= gHiiDatabase
->ExportPackageLists (gHiiDatabase
, Handle
, &BufferSize
, HiiPackageList
);
253 // Handle is a invalid handle. Check if Handle is corrupted.
255 ASSERT (Status
!= EFI_NOT_FOUND
);
257 // The return status should always be EFI_BUFFER_TOO_SMALL as input buffer's size is 0.
259 ASSERT (Status
== EFI_BUFFER_TOO_SMALL
);
261 HiiPackageList
= AllocatePool (BufferSize
);
262 ASSERT (HiiPackageList
!= NULL
);
264 Status
= gHiiDatabase
->ExportPackageLists (gHiiDatabase
, Handle
, &BufferSize
, HiiPackageList
);
265 if (EFI_ERROR (Status
)) {
270 // Get Form package from this HII package List
272 Offset
= sizeof (EFI_HII_PACKAGE_LIST_HEADER
);
274 PackageListLength
= ReadUnaligned32 (&HiiPackageList
->PackageLength
);
276 while (Offset
< PackageListLength
) {
277 Package
= ((UINT8
*) HiiPackageList
) + Offset
;
278 CopyMem (&PackageHeader
, Package
, sizeof (EFI_HII_PACKAGE_HEADER
));
280 if (PackageHeader
.Type
== EFI_HII_PACKAGE_FORMS
) {
282 // Search FormSet Opcode in this Form Package
284 Offset2
= sizeof (EFI_HII_PACKAGE_HEADER
);
285 while (Offset2
< PackageHeader
.Length
) {
286 OpCodeData
= Package
+ Offset2
;
287 Offset2
+= ((EFI_IFR_OP_HEADER
*) OpCodeData
)->Length
;
289 if (((EFI_IFR_OP_HEADER
*) OpCodeData
)->OpCode
== EFI_IFR_FORM_SET_OP
) {
290 if (SkipCount
!= 0) {
295 if (((EFI_IFR_OP_HEADER
*) OpCodeData
)->Length
> OFFSET_OF (EFI_IFR_FORM_SET
, Flags
)) {
297 // Find FormSet OpCode
299 ClassGuidNum
= (UINT8
) (((EFI_IFR_FORM_SET
*) OpCodeData
)->Flags
& 0x3);
300 ClassGuid
= (EFI_GUID
*) (VOID
*)(OpCodeData
+ sizeof (EFI_IFR_FORM_SET
));
301 while (ClassGuidNum
-- > 0) {
302 if (CompareGuid (SetupClassGuid
, ClassGuid
)) {
303 CopyMem (FormSetTitle
, &((EFI_IFR_FORM_SET
*) OpCodeData
)->FormSetTitle
, sizeof (EFI_STRING_ID
));
304 CopyMem (FormSetHelp
, &((EFI_IFR_FORM_SET
*) OpCodeData
)->Help
, sizeof (EFI_STRING_ID
));
305 *FormSetGuid
= AllocateCopyPool (sizeof (EFI_GUID
), &((EFI_IFR_FORM_SET
*) OpCodeData
)->Guid
);
306 ASSERT (*FormSetGuid
!= NULL
);
307 FreePool (HiiPackageList
);
313 CopyMem (FormSetTitle
, &((EFI_IFR_FORM_SET
*) OpCodeData
)->FormSetTitle
, sizeof (EFI_STRING_ID
));
314 CopyMem (FormSetHelp
, &((EFI_IFR_FORM_SET
*) OpCodeData
)->Help
, sizeof (EFI_STRING_ID
));
315 *FormSetGuid
= AllocateCopyPool (sizeof (EFI_GUID
), &((EFI_IFR_FORM_SET
*) OpCodeData
)->Guid
);
316 ASSERT (*FormSetGuid
!= NULL
);
317 FreePool (HiiPackageList
);
325 // Go to next package
327 Offset
+= PackageHeader
.Length
;
330 FreePool (HiiPackageList
);
336 Get the mac address string from the device path.
337 if the device path has the vlan, get the vanid also.
339 @param MacAddressNode Device path begin with mac address
340 @param PBuffer Output string buffer contain mac address.
345 IN MAC_ADDR_DEVICE_PATH
*MacAddressNode
,
352 EFI_DEVICE_PATH_PROTOCOL
*Node
;
359 ASSERT(MacAddressNode
!= NULL
);
361 HwAddressSize
= sizeof (EFI_MAC_ADDRESS
);
362 if (MacAddressNode
->IfType
== 0x01 || MacAddressNode
->IfType
== 0x00) {
367 // The output format is MAC:XX:XX:XX:...\XXXX
368 // The size is the Number size + ":" size + Vlan size(\XXXX) + End
370 BufferLen
= (4 + 2 * HwAddressSize
+ (HwAddressSize
- 1) + 5 + 1) * sizeof (CHAR16
);
371 String
= AllocateZeroPool (BufferLen
);
372 if (String
== NULL
) {
377 StrCpyS (String
, BufferLen
/ sizeof (CHAR16
), L
"MAC:");
381 // Convert the MAC address into a unicode string.
383 HwAddress
= &MacAddressNode
->MacAddress
.Addr
[0];
384 for (Index
= 0; Index
< HwAddressSize
; Index
++) {
385 UnicodeValueToStringS (
387 BufferLen
- ((UINTN
)String
- (UINTN
)*PBuffer
),
388 PREFIX_ZERO
| RADIX_HEX
,
392 String
+= StrnLenS (String
, (BufferLen
- ((UINTN
)String
- (UINTN
)*PBuffer
)) / sizeof (CHAR16
));
393 if (Index
< HwAddressSize
- 1) {
399 // If VLAN is configured, it will need extra 5 characters like "\0005".
400 // Plus one unicode character for the null-terminator.
402 Node
= (EFI_DEVICE_PATH_PROTOCOL
*)MacAddressNode
;
403 while (!IsDevicePathEnd (Node
)) {
404 if (Node
->Type
== MESSAGING_DEVICE_PATH
&& Node
->SubType
== MSG_VLAN_DP
) {
405 VlanId
= ((VLAN_DEVICE_PATH
*) Node
)->VlanId
;
407 Node
= NextDevicePathNode (Node
);
412 UnicodeValueToStringS (
414 BufferLen
- ((UINTN
)String
- (UINTN
)*PBuffer
),
415 PREFIX_ZERO
| RADIX_HEX
,
419 String
+= StrnLenS (String
, (BufferLen
- ((UINTN
)String
- (UINTN
)*PBuffer
)) / sizeof (CHAR16
));
423 // Null terminate the Unicode string
431 Save question id and prompt id to the mac device list.
432 If the same mac address has saved yet, no need to add more.
434 @param MacAddrString Mac address string.
436 @retval EFI_SUCCESS Add the item is successful.
437 @return Other values if failed to Add the item.
440 AddIdToMacDeviceList (
441 IN EFI_STRING MacAddrString
444 MENU_INFO_ITEM
*TempDeviceList
;
446 EFI_STRING StoredString
;
447 EFI_STRING_ID PromptId
;
448 EFI_HII_HANDLE HiiHandle
;
450 HiiHandle
= gDeviceManagerPrivate
.HiiHandle
;
451 TempDeviceList
= NULL
;
453 for (Index
= 0; Index
< mMacDeviceList
.CurListLen
; Index
++) {
454 StoredString
= HiiGetString (HiiHandle
, mMacDeviceList
.NodeList
[Index
].PromptId
, NULL
);
455 if (StoredString
== NULL
) {
460 // Already has save the same mac address to the list.
462 if (StrCmp (MacAddrString
, StoredString
) == 0) {
467 PromptId
= HiiSetString(HiiHandle
, 0, MacAddrString
, NULL
);
469 // If not in the list, save it.
471 if (mMacDeviceList
.MaxListLen
> mMacDeviceList
.CurListLen
+ 1) {
472 mMacDeviceList
.NodeList
[mMacDeviceList
.CurListLen
].PromptId
= PromptId
;
473 mMacDeviceList
.NodeList
[mMacDeviceList
.CurListLen
].QuestionId
= (EFI_QUESTION_ID
) (mMacDeviceList
.CurListLen
+ NETWORK_DEVICE_LIST_KEY_OFFSET
);
475 mMacDeviceList
.MaxListLen
+= MAX_MAC_ADDRESS_NODE_LIST_LEN
;
476 if (mMacDeviceList
.CurListLen
!= 0) {
477 TempDeviceList
= ReallocatePool (
478 sizeof (MENU_INFO_ITEM
) * mMacDeviceList
.CurListLen
,
479 sizeof (MENU_INFO_ITEM
) * mMacDeviceList
.MaxListLen
,
480 mMacDeviceList
.NodeList
483 TempDeviceList
= (MENU_INFO_ITEM
*)AllocatePool (sizeof (MENU_INFO_ITEM
) * mMacDeviceList
.MaxListLen
);
486 if (TempDeviceList
== NULL
) {
489 TempDeviceList
[mMacDeviceList
.CurListLen
].PromptId
= PromptId
;
490 TempDeviceList
[mMacDeviceList
.CurListLen
].QuestionId
= (EFI_QUESTION_ID
) (mMacDeviceList
.CurListLen
+ NETWORK_DEVICE_LIST_KEY_OFFSET
);
492 mMacDeviceList
.NodeList
= TempDeviceList
;
494 mMacDeviceList
.CurListLen
++;
500 Check the devcie path, try to find whether it has mac address path.
502 In this function, first need to check whether this path has mac address path.
503 second, when the mac address device path has find, also need to deicide whether
504 need to add this mac address relate info to the menu.
506 @param *Node Input device which need to be check.
507 @param *NeedAddItem Whether need to add the menu in the network device list.
509 @retval TRUE Has mac address device path.
510 @retval FALSE NOT Has mac address device path.
514 IsMacAddressDevicePath (
516 OUT BOOLEAN
*NeedAddItem
519 EFI_DEVICE_PATH_PROTOCOL
*DevicePath
;
523 ASSERT (Node
!= NULL
);
524 *NeedAddItem
= FALSE
;
528 DevicePath
= (EFI_DEVICE_PATH_PROTOCOL
*) Node
;
531 // find the partition device path node
533 while (!IsDevicePathEnd (DevicePath
)) {
534 if ((DevicePathType (DevicePath
) == MESSAGING_DEVICE_PATH
) &&
535 (DevicePathSubType (DevicePath
) == MSG_MAC_ADDR_DP
)) {
538 if (DEVICE_MANAGER_FORM_ID
== mNextShowFormId
) {
543 if (!GetMacAddressString((MAC_ADDR_DEVICE_PATH
*)DevicePath
, &Buffer
)) {
547 if (NETWORK_DEVICE_FORM_ID
== mNextShowFormId
) {
548 if (StrCmp (Buffer
, mSelectedMacAddrString
) == 0) {
554 if (NETWORK_DEVICE_LIST_FORM_ID
== mNextShowFormId
) {
556 // Same handle may has two network child handle, so the questionid
557 // has the offset of SAME_HANDLE_KEY_OFFSET.
559 if (AddIdToMacDeviceList (Buffer
)) {
565 DevicePath
= NextDevicePathNode (DevicePath
);
568 if (Buffer
!= NULL
) {
576 Check to see if the device path is for the network device.
578 @param Handle The HII handle which include the mac address device path.
579 @param ItemCount The new add Mac address item count.
581 @retval TRUE Need to add new item in the menu.
582 @return FALSE Do not need to add the menu about the network.
586 IsNeedAddNetworkMenu (
587 IN EFI_HII_HANDLE Handle
,
594 EFI_HANDLE DriverHandle
;
595 EFI_HANDLE ControllerHandle
;
596 EFI_DEVICE_PATH_PROTOCOL
*DevicePath
;
597 EFI_DEVICE_PATH_PROTOCOL
*TmpDevicePath
;
598 EFI_DEVICE_PATH_PROTOCOL
*ChildDevicePath
;
599 EFI_OPEN_PROTOCOL_INFORMATION_ENTRY
*OpenInfoBuffer
;
603 OpenInfoBuffer
= NULL
;
604 if ((Handle
== NULL
) || (ItemCount
== NULL
)) {
609 Status
= gHiiDatabase
->GetPackageListHandle (gHiiDatabase
, Handle
, &DriverHandle
);
610 if (EFI_ERROR (Status
)) {
614 // Get the device path by the got Driver handle .
616 Status
= gBS
->HandleProtocol (DriverHandle
, &gEfiDevicePathProtocolGuid
, (VOID
**) &DevicePath
);
617 if (EFI_ERROR (Status
)) {
620 TmpDevicePath
= DevicePath
;
623 // Check whether this device path include mac address device path.
624 // If this path has mac address path, get the value whether need
625 // add this info to the menu and return.
626 // Else check more about the child handle devcie path.
628 if (IsMacAddressDevicePath(TmpDevicePath
, &IsNeedAdd
)) {
629 if ((NETWORK_DEVICE_LIST_FORM_ID
== mNextShowFormId
) && IsNeedAdd
) {
636 // Search whether this path is the controller path, not he child handle path.
637 // And the child handle has the network devcie connected.
639 TmpDevicePath
= DevicePath
;
640 Status
= gBS
->LocateDevicePath(&gEfiDevicePathProtocolGuid
, &TmpDevicePath
, &ControllerHandle
);
641 if (EFI_ERROR (Status
)) {
645 if (!IsDevicePathEnd (TmpDevicePath
)) {
650 // Retrieve the list of agents that are consuming the specific protocol
651 // on ControllerHandle.
652 // The buffer point by OpenInfoBuffer need be free at this function.
654 Status
= gBS
->OpenProtocolInformation (
656 &gEfiPciIoProtocolGuid
,
660 if (EFI_ERROR (Status
)) {
665 // Inspect if ChildHandle is one of the agents.
667 Status
= EFI_UNSUPPORTED
;
668 for (Index
= 0; Index
< EntryCount
; Index
++) {
670 // Query all the children created by the controller handle's driver
672 if ((OpenInfoBuffer
[Index
].Attributes
& EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER
) != 0) {
673 Status
= gBS
->OpenProtocol (
674 OpenInfoBuffer
[Index
].ControllerHandle
,
675 &gEfiDevicePathProtocolGuid
,
676 (VOID
**) &ChildDevicePath
,
679 EFI_OPEN_PROTOCOL_GET_PROTOCOL
681 if (EFI_ERROR (Status
)) {
686 // Check whether this device path include mac address device path.
688 if (!IsMacAddressDevicePath(ChildDevicePath
, &IsNeedAdd
)) {
690 // If this path not has mac address path, check the other.
695 // If need to update the NETWORK_DEVICE_LIST_FORM, try to get more.
697 if ((NETWORK_DEVICE_LIST_FORM_ID
== mNextShowFormId
)) {
704 // If need to update other form, return whether need to add to the menu.
713 if (OpenInfoBuffer
!= NULL
) {
714 FreePool (OpenInfoBuffer
);
720 Get HiiHandle total number.
722 @param HiiHandles The input HiiHandle array.
724 @retval the Hiihandle count.
729 IN EFI_HII_HANDLE
*HiiHandles
734 for (Index
= 0; HiiHandles
[Index
] != NULL
; Index
++) {
741 Insert the new HiiHandle + FormsetGuid at the NewPair[InsertOffset].
743 @param HiiHandles The input HiiHandle array.
744 @param GuidLists The input form set guid lists.
745 @param ArrayCount The input array count, new array will be arraycount + 1 size.
746 @param Offset The current used HiiHandle's Offset.
747 @param FormSetGuid The new found formset guid.
752 IN OUT EFI_HII_HANDLE
**HiiHandles
,
753 IN OUT EFI_GUID
***GuidLists
,
756 IN EFI_GUID
*FormSetGuid
759 EFI_HII_HANDLE
*NewHiiHandles
;
760 EFI_GUID
**NewGuidLists
;
763 // +2 means include the new HiiHandle and the last empty NULL pointer.
765 NewHiiHandles
= AllocateZeroPool ((ArrayCount
+ 2) * sizeof (EFI_HII_HANDLE
));
766 ASSERT (NewHiiHandles
!= NULL
);
768 CopyMem (NewHiiHandles
, *HiiHandles
, Offset
* sizeof (EFI_HII_HANDLE
));
769 NewHiiHandles
[Offset
] = NewHiiHandles
[Offset
- 1];
770 CopyMem (NewHiiHandles
+ Offset
+ 1, *HiiHandles
+ Offset
, (ArrayCount
- Offset
) * sizeof (EFI_HII_HANDLE
));
772 NewGuidLists
= AllocateZeroPool ((ArrayCount
+ 2) * sizeof (EFI_GUID
*));
773 ASSERT (NewGuidLists
!= NULL
);
775 CopyMem (NewGuidLists
, *GuidLists
, Offset
* sizeof (EFI_GUID
*));
776 NewGuidLists
[Offset
] = FormSetGuid
;
778 FreePool (*HiiHandles
);
779 *HiiHandles
= NewHiiHandles
;
780 FreePool (*GuidLists
);
781 *GuidLists
= NewGuidLists
;
785 Call the browser and display the device manager to allow user
786 to configure the platform.
788 This function create the dynamic content for device manager. It includes
789 section header for all class of devices, one-of opcode to set VBIOS.
791 @retval EFI_SUCCESS Operation is successful.
792 @return Other values if failed to clean up the dynamic content from HII
805 EFI_STRING_ID TokenHelp
;
806 EFI_HII_HANDLE
*HiiHandles
;
807 EFI_HII_HANDLE HiiHandle
;
808 EFI_STRING_ID FormSetTitle
;
809 EFI_STRING_ID FormSetHelp
;
810 EFI_BROWSER_ACTION_REQUEST ActionRequest
;
811 VOID
*StartOpCodeHandle
;
812 VOID
*EndOpCodeHandle
;
813 EFI_IFR_GUID_LABEL
*StartLabel
;
814 EFI_IFR_GUID_LABEL
*EndLabel
;
816 EFI_HANDLE
*DriverHealthHandles
;
817 BOOLEAN AddNetworkMenu
;
820 EFI_STRING NewStringTitle
;
821 EFI_GUID
**GuidLists
;
824 EFI_GUID
*FormSetGuid
;
828 Status
= EFI_SUCCESS
;
831 DriverHealthHandles
= NULL
;
832 AddNetworkMenu
= FALSE
;
838 // Connect all prior to entering the platform setup menu.
840 if (!gConnectAllHappened
) {
841 BdsLibConnectAllDriversToAllControllers ();
842 gConnectAllHappened
= TRUE
;
845 HiiHandle
= gDeviceManagerPrivate
.HiiHandle
;
846 if (HiiHandle
== NULL
) {
848 // Publish our HII data.
850 HiiHandle
= HiiAddPackages (
851 &gDeviceManagerFormSetGuid
,
852 gDeviceManagerPrivate
.DriverHandle
,
857 if (HiiHandle
== NULL
) {
858 return EFI_OUT_OF_RESOURCES
;
861 gDeviceManagerPrivate
.HiiHandle
= HiiHandle
;
865 // If need show the Network device list form, clear the old save list first.
867 if ((mNextShowFormId
== NETWORK_DEVICE_LIST_FORM_ID
) && (mMacDeviceList
.CurListLen
> 0)) {
868 mMacDeviceList
.CurListLen
= 0;
872 // Update the network device form titile.
874 if (mNextShowFormId
== NETWORK_DEVICE_FORM_ID
) {
875 String
= HiiGetString (HiiHandle
, STRING_TOKEN (STR_FORM_NETWORK_DEVICE_TITLE
), NULL
);
876 NewStringLen
= StrLen(mSelectedMacAddrString
) * 2;
877 NewStringLen
+= (StrLen(String
) + 2) * 2;
878 NewStringTitle
= AllocatePool (NewStringLen
);
879 UnicodeSPrint (NewStringTitle
, NewStringLen
, L
"%s %s", String
, mSelectedMacAddrString
);
880 HiiSetString (HiiHandle
, STRING_TOKEN (STR_FORM_NETWORK_DEVICE_TITLE
), NewStringTitle
, NULL
);
882 FreePool (NewStringTitle
);
886 // Allocate space for creation of UpdateData Buffer
888 StartOpCodeHandle
= HiiAllocateOpCodeHandle ();
889 ASSERT (StartOpCodeHandle
!= NULL
);
891 EndOpCodeHandle
= HiiAllocateOpCodeHandle ();
892 ASSERT (EndOpCodeHandle
!= NULL
);
895 // Create Hii Extend Label OpCode as the start opcode
897 StartLabel
= (EFI_IFR_GUID_LABEL
*) HiiCreateGuidOpCode (StartOpCodeHandle
, &gEfiIfrTianoGuid
, NULL
, sizeof (EFI_IFR_GUID_LABEL
));
898 StartLabel
->ExtendOpCode
= EFI_IFR_EXTEND_OP_LABEL
;
900 // According to the next show Form id(mNextShowFormId) to decide which form need to update.
902 StartLabel
->Number
= (UINT16
) (LABEL_FORM_ID_OFFSET
+ mNextShowFormId
);
905 // Create Hii Extend Label OpCode as the end opcode
907 EndLabel
= (EFI_IFR_GUID_LABEL
*) HiiCreateGuidOpCode (EndOpCodeHandle
, &gEfiIfrTianoGuid
, NULL
, sizeof (EFI_IFR_GUID_LABEL
));
908 EndLabel
->ExtendOpCode
= EFI_IFR_EXTEND_OP_LABEL
;
909 EndLabel
->Number
= LABEL_END
;
912 // Get all the Hii handles
914 HiiHandles
= HiiGetHiiHandles (NULL
);
915 ASSERT (HiiHandles
!= NULL
);
917 HandleNum
= GetHiiHandleCount (HiiHandles
);
918 GuidLists
= AllocateZeroPool ((HandleNum
+ 1) * sizeof (EFI_GUID
*));
919 ASSERT (GuidLists
!= NULL
);
922 // Search for formset of each class type
924 for (Index
= 0; HiiHandles
[Index
] != NULL
; Index
++) {
926 // The QuestionId in the form which will call the driver form has this asssumption.
927 // QuestionId = Handle Index + NETWORK_DEVICE_LIST_KEY_OFFSET;
928 // Different QuestionId at least has the section of NETWORK_DEVICE_LIST_KEY_OFFSET.
930 ASSERT(Index
< MAX_KEY_SECTION_LEN
);
932 if (!ExtractDisplayedHiiFormFromHiiHandle (HiiHandles
[Index
], &gEfiHiiPlatformSetupFormsetGuid
, SkipCount
, &FormSetTitle
, &FormSetHelp
, &FormSetGuid
)) {
938 // One HiiHandle has more than one formset can be shown,
939 // Insert a new pair of HiiHandle + Guid to the HiiHandles and GuidLists list.
942 AdjustArrayData (&HiiHandles
, &GuidLists
, HandleNum
, Index
+ 1, FormSetGuid
);
947 String
= HiiGetString (HiiHandles
[Index
], FormSetTitle
, NULL
);
948 if (String
== NULL
) {
949 String
= HiiGetString (HiiHandle
, STR_MISSING_STRING
, NULL
);
950 ASSERT (String
!= NULL
);
952 Token
= HiiSetString (HiiHandle
, 0, String
, NULL
);
955 String
= HiiGetString (HiiHandles
[Index
], FormSetHelp
, NULL
);
956 if (String
== NULL
) {
957 String
= HiiGetString (HiiHandle
, STR_MISSING_STRING
, NULL
);
958 ASSERT (String
!= NULL
);
960 TokenHelp
= HiiSetString (HiiHandle
, 0, String
, NULL
);
964 // Network device process
966 if (IsNeedAddNetworkMenu (HiiHandles
[Index
], &AddItemCount
)) {
967 if (mNextShowFormId
== DEVICE_MANAGER_FORM_ID
) {
969 // Only show one menu item "Network Config" in the device manger form.
971 if (!AddNetworkMenu
) {
972 AddNetworkMenu
= TRUE
;
973 HiiCreateGotoOpCode (
976 STRING_TOKEN (STR_FORM_NETWORK_DEVICE_LIST_TITLE
),
977 STRING_TOKEN (STR_FORM_NETWORK_DEVICE_LIST_HELP
),
978 EFI_IFR_FLAG_CALLBACK
,
979 (EFI_QUESTION_ID
) QUESTION_NETWORK_DEVICE_ID
982 } else if (mNextShowFormId
== NETWORK_DEVICE_LIST_FORM_ID
) {
984 // In network device list form, same mac address device only show one menu.
986 while (AddItemCount
> 0) {
987 HiiCreateGotoOpCode (
990 mMacDeviceList
.NodeList
[mMacDeviceList
.CurListLen
- AddItemCount
].PromptId
,
991 STRING_TOKEN (STR_NETWORK_DEVICE_HELP
),
992 EFI_IFR_FLAG_CALLBACK
,
993 mMacDeviceList
.NodeList
[mMacDeviceList
.CurListLen
- AddItemCount
].QuestionId
997 } else if (mNextShowFormId
== NETWORK_DEVICE_FORM_ID
) {
999 // In network device form, only the selected mac address device need to be show.
1001 HiiCreateGotoOpCode (
1006 EFI_IFR_FLAG_CALLBACK
,
1007 (EFI_QUESTION_ID
) (Index
+ DEVICE_KEY_OFFSET
)
1013 // Not network device process, only need to show at device manger form.
1015 if (mNextShowFormId
== DEVICE_MANAGER_FORM_ID
) {
1016 HiiCreateGotoOpCode (
1021 EFI_IFR_FLAG_CALLBACK
,
1022 (EFI_QUESTION_ID
) (Index
+ DEVICE_KEY_OFFSET
)
1028 // Try to find more formset in this HiiHandle.
1034 Status
= gBS
->LocateHandleBuffer (
1036 &gEfiDriverHealthProtocolGuid
,
1039 &DriverHealthHandles
1043 // If there are no drivers installed driver health protocol, do not create driver health entry in UI
1045 if (NumHandles
!= 0) {
1047 // If driver health protocol is installed, create Driver Health subtitle and entry
1049 HiiCreateSubTitleOpCode (StartOpCodeHandle
, STRING_TOKEN (STR_DM_DRIVER_HEALTH_TITLE
), 0, 0, 0);
1050 HiiCreateGotoOpCode (
1052 DRIVER_HEALTH_FORM_ID
,
1053 STRING_TOKEN(STR_DRIVER_HEALTH_ALL_HEALTHY
), // Prompt text
1054 STRING_TOKEN(STR_DRIVER_HEALTH_STATUS_HELP
), // Help text
1055 EFI_IFR_FLAG_CALLBACK
,
1056 DEVICE_MANAGER_KEY_DRIVER_HEALTH
// Question ID
1060 // Check All Driver health status
1062 if (!PlaformHealthStatusCheck ()) {
1064 // At least one driver in the platform are not in healthy status
1066 HiiSetString (HiiHandle
, STRING_TOKEN (STR_DRIVER_HEALTH_ALL_HEALTHY
), GetStringById (STRING_TOKEN (STR_DRIVER_NOT_HEALTH
)), NULL
);
1069 // For the string of STR_DRIVER_HEALTH_ALL_HEALTHY previously has been updated and we need to update it while re-entry.
1071 HiiSetString (HiiHandle
, STRING_TOKEN (STR_DRIVER_HEALTH_ALL_HEALTHY
), GetStringById (STRING_TOKEN (STR_DRIVER_HEALTH_ALL_HEALTHY
)), NULL
);
1077 &gDeviceManagerFormSetGuid
,
1083 ActionRequest
= EFI_BROWSER_ACTION_REQUEST_NONE
;
1084 Status
= gFormBrowser2
->SendForm (
1088 &gDeviceManagerFormSetGuid
,
1093 if (ActionRequest
== EFI_BROWSER_ACTION_REQUEST_RESET
) {
1094 EnableResetRequired ();
1098 // We will have returned from processing a callback, selected
1099 // a target to display
1101 if ((gCallbackKey
>= DEVICE_KEY_OFFSET
)) {
1102 ActionRequest
= EFI_BROWSER_ACTION_REQUEST_NONE
;
1103 Status
= gFormBrowser2
->SendForm (
1105 &HiiHandles
[gCallbackKey
- DEVICE_KEY_OFFSET
],
1107 GuidLists
[gCallbackKey
- DEVICE_KEY_OFFSET
],
1113 if (ActionRequest
== EFI_BROWSER_ACTION_REQUEST_RESET
) {
1114 EnableResetRequired ();
1118 // Force return to Device Manager
1120 gCallbackKey
= FRONT_PAGE_KEY_DEVICE_MANAGER
;
1125 // Driver Health item chose.
1127 if (gCallbackKey
== DEVICE_MANAGER_KEY_DRIVER_HEALTH
) {
1128 CallDriverHealth ();
1130 // Force return to Device Manager
1132 gCallbackKey
= FRONT_PAGE_KEY_DEVICE_MANAGER
;
1137 // Enter from device manager and into the network device list.
1139 if (gCallbackKey
== QUESTION_NETWORK_DEVICE_ID
) {
1140 mNextShowFormId
= NETWORK_DEVICE_LIST_FORM_ID
;
1141 gCallbackKey
= FRONT_PAGE_KEY_DEVICE_MANAGER
;
1146 // In this case, go from the network device list to the specify device.
1148 if ((gCallbackKey
< MAX_KEY_SECTION_LEN
+ NETWORK_DEVICE_LIST_KEY_OFFSET
) && (gCallbackKey
>= NETWORK_DEVICE_LIST_KEY_OFFSET
)) {
1149 mNextShowFormId
= NETWORK_DEVICE_FORM_ID
;
1150 gCallbackKey
= FRONT_PAGE_KEY_DEVICE_MANAGER
;
1155 // Select the ESC, the gCallbackKey == 0.
1157 if(mNextShowFormId
- 1 < DEVICE_MANAGER_FORM_ID
) {
1158 mNextShowFormId
= DEVICE_MANAGER_FORM_ID
;
1160 mNextShowFormId
= (UINT16
) (mNextShowFormId
- 1);
1161 gCallbackKey
= FRONT_PAGE_KEY_DEVICE_MANAGER
;
1166 // Remove our packagelist from HII database.
1168 HiiRemovePackages (HiiHandle
);
1169 gDeviceManagerPrivate
.HiiHandle
= NULL
;
1171 HiiFreeOpCodeHandle (StartOpCodeHandle
);
1172 HiiFreeOpCodeHandle (EndOpCodeHandle
);
1173 FreePool (HiiHandles
);
1175 for (Index
= 0; Index
< HandleNum
; Index
++) {
1176 if (GuidLists
[Index
] != NULL
) {
1177 FreePool (GuidLists
[Index
]);
1180 FreePool (GuidLists
);
1186 This function is invoked if user selected a interactive opcode from Driver Health's
1187 Formset. The decision by user is saved to gCallbackKey for later processing.
1189 @param This Points to the EFI_HII_CONFIG_ACCESS_PROTOCOL.
1190 @param Action Specifies the type of action taken by the browser.
1191 @param QuestionId A unique value which is sent to the original exporting driver
1192 so that it can identify the type of data to expect.
1193 @param Type The type of value for the question.
1194 @param Value A pointer to the data being sent to the original exporting driver.
1195 @param ActionRequest On return, points to the action requested by the callback function.
1197 @retval EFI_SUCCESS The callback successfully handled the action.
1198 @retval EFI_INVALID_PARAMETER The setup browser call this function with invalid parameters.
1203 DriverHealthCallback (
1204 IN CONST EFI_HII_CONFIG_ACCESS_PROTOCOL
*This
,
1205 IN EFI_BROWSER_ACTION Action
,
1206 IN EFI_QUESTION_ID QuestionId
,
1208 IN EFI_IFR_TYPE_VALUE
*Value
,
1209 OUT EFI_BROWSER_ACTION_REQUEST
*ActionRequest
1212 if (Action
== EFI_BROWSER_ACTION_CHANGED
) {
1213 if ((Value
== NULL
) || (ActionRequest
== NULL
)) {
1214 return EFI_INVALID_PARAMETER
;
1217 gCallbackKey
= QuestionId
;
1220 // Request to exit SendForm(), so as to switch to selected form
1222 *ActionRequest
= EFI_BROWSER_ACTION_REQUEST_EXIT
;
1228 // All other action return unsupported.
1230 return EFI_UNSUPPORTED
;
1234 Collect and display the platform's driver health relative information, allow user to do interactive
1235 operation while the platform is unhealthy.
1237 This function display a form which divided into two parts. The one list all modules which has installed
1238 driver health protocol. The list usually contain driver name, controller name, and it's health info.
1239 While the driver name can't be retrieved, will use device path as backup. The other part of the form provide
1240 a choice to the user to repair all platform.
1249 EFI_HII_HANDLE HiiHandle
;
1250 EFI_BROWSER_ACTION_REQUEST ActionRequest
;
1251 EFI_IFR_GUID_LABEL
*StartLabel
;
1252 EFI_IFR_GUID_LABEL
*StartLabelRepair
;
1253 EFI_IFR_GUID_LABEL
*EndLabel
;
1254 EFI_IFR_GUID_LABEL
*EndLabelRepair
;
1255 VOID
*StartOpCodeHandle
;
1256 VOID
*EndOpCodeHandle
;
1257 VOID
*StartOpCodeHandleRepair
;
1258 VOID
*EndOpCodeHandleRepair
;
1260 EFI_STRING_ID Token
;
1261 EFI_STRING_ID TokenHelp
;
1263 EFI_STRING TmpString
;
1264 EFI_STRING DriverName
;
1265 EFI_STRING ControllerName
;
1266 LIST_ENTRY DriverHealthList
;
1267 DRIVER_HEALTH_INFO
*DriverHealthInfo
;
1269 EFI_DEVICE_PATH_PROTOCOL
*DriverDevicePath
;
1270 BOOLEAN RebootRequired
;
1271 BOOLEAN IsControllerNameEmpty
;
1275 DriverHealthInfo
= NULL
;
1276 DriverDevicePath
= NULL
;
1277 IsControllerNameEmpty
= FALSE
;
1278 InitializeListHead (&DriverHealthList
);
1280 HiiHandle
= gDeviceManagerPrivate
.DriverHealthHiiHandle
;
1281 if (HiiHandle
== NULL
) {
1283 // Publish Driver Health HII data.
1285 HiiHandle
= HiiAddPackages (
1286 &gDeviceManagerFormSetGuid
,
1287 gDeviceManagerPrivate
.DriverHealthHandle
,
1292 if (HiiHandle
== NULL
) {
1296 gDeviceManagerPrivate
.DriverHealthHiiHandle
= HiiHandle
;
1300 // Allocate space for creation of UpdateData Buffer
1302 StartOpCodeHandle
= HiiAllocateOpCodeHandle ();
1303 ASSERT (StartOpCodeHandle
!= NULL
);
1305 EndOpCodeHandle
= HiiAllocateOpCodeHandle ();
1306 ASSERT (EndOpCodeHandle
!= NULL
);
1308 StartOpCodeHandleRepair
= HiiAllocateOpCodeHandle ();
1309 ASSERT (StartOpCodeHandleRepair
!= NULL
);
1311 EndOpCodeHandleRepair
= HiiAllocateOpCodeHandle ();
1312 ASSERT (EndOpCodeHandleRepair
!= NULL
);
1315 // Create Hii Extend Label OpCode as the start opcode
1317 StartLabel
= (EFI_IFR_GUID_LABEL
*) HiiCreateGuidOpCode (StartOpCodeHandle
, &gEfiIfrTianoGuid
, NULL
, sizeof (EFI_IFR_GUID_LABEL
));
1318 StartLabel
->ExtendOpCode
= EFI_IFR_EXTEND_OP_LABEL
;
1319 StartLabel
->Number
= LABEL_DRIVER_HEALTH
;
1322 // Create Hii Extend Label OpCode as the start opcode
1324 StartLabelRepair
= (EFI_IFR_GUID_LABEL
*) HiiCreateGuidOpCode (StartOpCodeHandleRepair
, &gEfiIfrTianoGuid
, NULL
, sizeof (EFI_IFR_GUID_LABEL
));
1325 StartLabelRepair
->ExtendOpCode
= EFI_IFR_EXTEND_OP_LABEL
;
1326 StartLabelRepair
->Number
= LABEL_DRIVER_HEALTH_REAPIR_ALL
;
1329 // Create Hii Extend Label OpCode as the end opcode
1331 EndLabel
= (EFI_IFR_GUID_LABEL
*) HiiCreateGuidOpCode (EndOpCodeHandle
, &gEfiIfrTianoGuid
, NULL
, sizeof (EFI_IFR_GUID_LABEL
));
1332 EndLabel
->ExtendOpCode
= EFI_IFR_EXTEND_OP_LABEL
;
1333 EndLabel
->Number
= LABEL_DRIVER_HEALTH_END
;
1336 // Create Hii Extend Label OpCode as the end opcode
1338 EndLabelRepair
= (EFI_IFR_GUID_LABEL
*) HiiCreateGuidOpCode (EndOpCodeHandleRepair
, &gEfiIfrTianoGuid
, NULL
, sizeof (EFI_IFR_GUID_LABEL
));
1339 EndLabelRepair
->ExtendOpCode
= EFI_IFR_EXTEND_OP_LABEL
;
1340 EndLabelRepair
->Number
= LABEL_DRIVER_HEALTH_REAPIR_ALL_END
;
1342 HiiCreateSubTitleOpCode (StartOpCodeHandle
, STRING_TOKEN (STR_DH_STATUS_LIST
), 0, 0, 1);
1344 Status
= GetAllControllersHealthStatus (&DriverHealthList
);
1345 ASSERT (Status
!= EFI_OUT_OF_RESOURCES
);
1347 Link
= GetFirstNode (&DriverHealthList
);
1349 while (!IsNull (&DriverHealthList
, Link
)) {
1350 DriverHealthInfo
= DEVICE_MANAGER_HEALTH_INFO_FROM_LINK (Link
);
1352 Status
= DriverHealthGetDriverName (DriverHealthInfo
->DriverHandle
, &DriverName
);
1353 if (EFI_ERROR (Status
)) {
1355 // Can not get the Driver name, so use the Device path
1357 DriverDevicePath
= DevicePathFromHandle (DriverHealthInfo
->DriverHandle
);
1358 DriverName
= DevicePathToStr (DriverDevicePath
);
1360 StringSize
= StrSize (DriverName
);
1362 Status
= DriverHealthGetControllerName (
1363 DriverHealthInfo
->DriverHandle
,
1364 DriverHealthInfo
->ControllerHandle
,
1365 DriverHealthInfo
->ChildHandle
,
1369 if (!EFI_ERROR (Status
)) {
1370 IsControllerNameEmpty
= FALSE
;
1371 StringSize
+= StrLen (L
" ") * sizeof(CHAR16
);
1372 StringSize
+= StrLen (ControllerName
) * sizeof(CHAR16
);
1374 IsControllerNameEmpty
= TRUE
;
1378 // Add the message of the Module itself provided after the string item.
1380 if ((DriverHealthInfo
->MessageList
!= NULL
) && (DriverHealthInfo
->MessageList
->StringId
!= 0)) {
1381 TmpString
= HiiGetString (
1382 DriverHealthInfo
->MessageList
->HiiHandle
,
1383 DriverHealthInfo
->MessageList
->StringId
,
1386 ASSERT (TmpString
!= NULL
);
1388 StringSize
+= StrLen (L
" ") * sizeof(CHAR16
);
1389 StringSize
+= StrLen (TmpString
) * sizeof(CHAR16
);
1391 String
= (EFI_STRING
) AllocateZeroPool (StringSize
);
1392 ASSERT (String
!= NULL
);
1394 StrCpyS (String
, StringSize
/ sizeof(CHAR16
), DriverName
);
1395 if (!IsControllerNameEmpty
) {
1396 StrCatS (String
, StringSize
/ sizeof(CHAR16
), L
" ");
1397 StrCatS (String
, StringSize
/ sizeof(CHAR16
), ControllerName
);
1400 StrCatS (String
, StringSize
/ sizeof(CHAR16
), L
" ");
1401 StrCatS (String
, StringSize
/ sizeof(CHAR16
), TmpString
);
1405 // Update the string will be displayed base on the driver's health status
1407 switch(DriverHealthInfo
->HealthStatus
) {
1408 case EfiDriverHealthStatusRepairRequired
:
1409 TmpString
= GetStringById (STRING_TOKEN (STR_REPAIR_REQUIRED
));
1411 case EfiDriverHealthStatusConfigurationRequired
:
1412 TmpString
= GetStringById (STRING_TOKEN (STR_CONFIGURATION_REQUIRED
));
1414 case EfiDriverHealthStatusFailed
:
1415 TmpString
= GetStringById (STRING_TOKEN (STR_OPERATION_FAILED
));
1417 case EfiDriverHealthStatusReconnectRequired
:
1418 TmpString
= GetStringById (STRING_TOKEN (STR_RECONNECT_REQUIRED
));
1420 case EfiDriverHealthStatusRebootRequired
:
1421 TmpString
= GetStringById (STRING_TOKEN (STR_REBOOT_REQUIRED
));
1424 TmpString
= GetStringById (STRING_TOKEN (STR_DRIVER_HEALTH_HEALTHY
));
1427 ASSERT (TmpString
!= NULL
);
1429 StringSize
+= StrLen (TmpString
) * sizeof(CHAR16
);
1431 String
= (EFI_STRING
) AllocateZeroPool (StringSize
);
1432 ASSERT (String
!= NULL
);
1434 StrCpyS (String
, StringSize
/ sizeof (CHAR16
), DriverName
);
1435 if (!IsControllerNameEmpty
) {
1436 StrCatS (String
, StringSize
/ sizeof (CHAR16
), L
" ");
1437 StrCatS (String
, StringSize
/ sizeof (CHAR16
), ControllerName
);
1440 StrCatS (String
, StringSize
/ sizeof (CHAR16
), TmpString
);
1443 FreePool (TmpString
);
1445 Token
= HiiSetString (HiiHandle
, 0, String
, NULL
);
1448 TokenHelp
= HiiSetString (HiiHandle
, 0, GetStringById( STRING_TOKEN (STR_DH_REPAIR_SINGLE_HELP
)), NULL
);
1450 HiiCreateActionOpCode (
1452 (EFI_QUESTION_ID
) (Index
+ DRIVER_HEALTH_KEY_OFFSET
),
1455 EFI_IFR_FLAG_CALLBACK
,
1459 Link
= GetNextNode (&DriverHealthList
, Link
);
1463 // Add End Opcode for Subtitle
1465 HiiCreateEndOpCode (StartOpCodeHandle
);
1467 HiiCreateSubTitleOpCode (StartOpCodeHandleRepair
, STRING_TOKEN (STR_DRIVER_HEALTH_REPAIR_ALL
), 0, 0, 1);
1468 TokenHelp
= HiiSetString (HiiHandle
, 0, GetStringById( STRING_TOKEN (STR_DH_REPAIR_ALL_HELP
)), NULL
);
1470 if (PlaformHealthStatusCheck ()) {
1472 // No action need to do for the platform
1474 Token
= HiiSetString (HiiHandle
, 0, GetStringById( STRING_TOKEN (STR_DRIVER_HEALTH_ALL_HEALTHY
)), NULL
);
1475 HiiCreateActionOpCode (
1476 StartOpCodeHandleRepair
,
1480 EFI_IFR_FLAG_READ_ONLY
,
1485 // Create ActionOpCode only while the platform need to do health related operation.
1487 Token
= HiiSetString (HiiHandle
, 0, GetStringById( STRING_TOKEN (STR_DH_REPAIR_ALL_TITLE
)), NULL
);
1488 HiiCreateActionOpCode (
1489 StartOpCodeHandleRepair
,
1490 (EFI_QUESTION_ID
) DRIVER_HEALTH_REPAIR_ALL_KEY
,
1493 EFI_IFR_FLAG_CALLBACK
,
1498 HiiCreateEndOpCode (StartOpCodeHandleRepair
);
1500 Status
= HiiUpdateForm (
1502 &gDriverHealthFormSetGuid
,
1503 DRIVER_HEALTH_FORM_ID
,
1507 ASSERT (Status
!= EFI_NOT_FOUND
);
1508 ASSERT (Status
!= EFI_BUFFER_TOO_SMALL
);
1510 Status
= HiiUpdateForm (
1512 &gDriverHealthFormSetGuid
,
1513 DRIVER_HEALTH_FORM_ID
,
1514 StartOpCodeHandleRepair
,
1515 EndOpCodeHandleRepair
1517 ASSERT (Status
!= EFI_NOT_FOUND
);
1518 ASSERT (Status
!= EFI_BUFFER_TOO_SMALL
);
1520 ActionRequest
= EFI_BROWSER_ACTION_REQUEST_NONE
;
1521 Status
= gFormBrowser2
->SendForm (
1525 &gDriverHealthFormSetGuid
,
1526 DRIVER_HEALTH_FORM_ID
,
1530 if (ActionRequest
== EFI_BROWSER_ACTION_REQUEST_RESET
) {
1531 EnableResetRequired ();
1535 // We will have returned from processing a callback - user either hit ESC to exit, or selected
1536 // a target to display.
1537 // Process the diver health status states here.
1539 if (gCallbackKey
>= DRIVER_HEALTH_KEY_OFFSET
&& gCallbackKey
!= DRIVER_HEALTH_REPAIR_ALL_KEY
) {
1540 ActionRequest
= EFI_BROWSER_ACTION_REQUEST_NONE
;
1542 Link
= GetFirstNode (&DriverHealthList
);
1545 while (!IsNull (&DriverHealthList
, Link
)) {
1547 // Got the item relative node in the List
1549 if (Index
== (gCallbackKey
- DRIVER_HEALTH_KEY_OFFSET
)) {
1550 DriverHealthInfo
= DEVICE_MANAGER_HEALTH_INFO_FROM_LINK (Link
);
1552 // Process the driver's healthy status for the specify module
1554 RebootRequired
= FALSE
;
1555 ProcessSingleControllerHealth (
1556 DriverHealthInfo
->DriverHealth
,
1557 DriverHealthInfo
->ControllerHandle
,
1558 DriverHealthInfo
->ChildHandle
,
1559 DriverHealthInfo
->HealthStatus
,
1560 &(DriverHealthInfo
->MessageList
),
1561 DriverHealthInfo
->HiiHandle
,
1564 if (RebootRequired
) {
1565 gRT
->ResetSystem (EfiResetWarm
, EFI_SUCCESS
, 0, NULL
);
1570 Link
= GetNextNode (&DriverHealthList
, Link
);
1573 if (ActionRequest
== EFI_BROWSER_ACTION_REQUEST_RESET
) {
1574 EnableResetRequired ();
1578 // Force return to the form of Driver Health in Device Manager
1580 gCallbackKey
= DRIVER_HEALTH_RETURN_KEY
;
1584 // Repair the whole platform
1586 if (gCallbackKey
== DRIVER_HEALTH_REPAIR_ALL_KEY
) {
1587 ActionRequest
= EFI_BROWSER_ACTION_REQUEST_NONE
;
1589 PlatformRepairAll (&DriverHealthList
);
1591 gCallbackKey
= DRIVER_HEALTH_RETURN_KEY
;
1595 // Remove driver health packagelist from HII database.
1597 HiiRemovePackages (HiiHandle
);
1598 gDeviceManagerPrivate
.DriverHealthHiiHandle
= NULL
;
1601 // Free driver health info list
1603 while (!IsListEmpty (&DriverHealthList
)) {
1605 Link
= GetFirstNode(&DriverHealthList
);
1606 DriverHealthInfo
= DEVICE_MANAGER_HEALTH_INFO_FROM_LINK (Link
);
1607 RemoveEntryList (Link
);
1609 if (DriverHealthInfo
->MessageList
!= NULL
) {
1610 FreePool(DriverHealthInfo
->MessageList
);
1611 FreePool (DriverHealthInfo
);
1615 HiiFreeOpCodeHandle (StartOpCodeHandle
);
1616 HiiFreeOpCodeHandle (EndOpCodeHandle
);
1617 HiiFreeOpCodeHandle (StartOpCodeHandleRepair
);
1618 HiiFreeOpCodeHandle (EndOpCodeHandleRepair
);
1620 if (gCallbackKey
== DRIVER_HEALTH_RETURN_KEY
) {
1622 // Force return to Driver Health Form
1624 gCallbackKey
= DEVICE_MANAGER_KEY_DRIVER_HEALTH
;
1625 CallDriverHealth ();
1631 Check the Driver Health status of a single controller and try to process it if not healthy.
1633 This function called by CheckAllControllersHealthStatus () function in order to process a specify
1634 contoller's health state.
1636 @param DriverHealthList A Pointer to the list contain all of the platform driver health information.
1637 @param DriverHandle The handle of driver.
1638 @param ControllerHandle The class guid specifies which form set will be displayed.
1639 @param ChildHandle The handle of the child controller to retrieve the health
1640 status on. This is an optional parameter that may be NULL.
1641 @param DriverHealth A pointer to the EFI_DRIVER_HEALTH_PROTOCOL instance.
1642 @param HealthStatus The health status of the controller.
1644 @retval EFI_INVALID_PARAMETER HealthStatus or DriverHealth is NULL.
1645 @retval HealthStatus The Health status of specify controller.
1646 @retval EFI_OUT_OF_RESOURCES The list of Driver Health Protocol handles can not be retrieved.
1647 @retval EFI_NOT_FOUND No controller in the platform install Driver Health Protocol.
1648 @retval EFI_SUCCESS The Health related operation has been taken successfully.
1653 GetSingleControllerHealthStatus (
1654 IN OUT LIST_ENTRY
*DriverHealthList
,
1655 IN EFI_HANDLE DriverHandle
,
1656 IN EFI_HANDLE ControllerHandle
, OPTIONAL
1657 IN EFI_HANDLE ChildHandle
, OPTIONAL
1658 IN EFI_DRIVER_HEALTH_PROTOCOL
*DriverHealth
,
1659 IN EFI_DRIVER_HEALTH_STATUS
*HealthStatus
1663 EFI_DRIVER_HEALTH_HII_MESSAGE
*MessageList
;
1664 EFI_HII_HANDLE FormHiiHandle
;
1665 DRIVER_HEALTH_INFO
*DriverHealthInfo
;
1667 if (HealthStatus
== NULL
) {
1669 // If HealthStatus is NULL, then return EFI_INVALID_PARAMETER
1671 return EFI_INVALID_PARAMETER
;
1675 // Assume the HealthStatus is healthy
1677 *HealthStatus
= EfiDriverHealthStatusHealthy
;
1679 if (DriverHealth
== NULL
) {
1681 // If DriverHealth is NULL, then return EFI_INVALID_PARAMETER
1683 return EFI_INVALID_PARAMETER
;
1686 if (ControllerHandle
== NULL
) {
1688 // If ControllerHandle is NULL, the return the cumulative health status of the driver
1690 Status
= DriverHealth
->GetHealthStatus (DriverHealth
, NULL
, NULL
, HealthStatus
, NULL
, NULL
);
1691 if (*HealthStatus
== EfiDriverHealthStatusHealthy
) {
1693 // Add the driver health related information into the list
1695 DriverHealthInfo
= AllocateZeroPool (sizeof (DRIVER_HEALTH_INFO
));
1696 if (DriverHealthInfo
== NULL
) {
1697 return EFI_OUT_OF_RESOURCES
;
1700 DriverHealthInfo
->Signature
= DEVICE_MANAGER_DRIVER_HEALTH_INFO_SIGNATURE
;
1701 DriverHealthInfo
->DriverHandle
= DriverHandle
;
1702 DriverHealthInfo
->ControllerHandle
= NULL
;
1703 DriverHealthInfo
->ChildHandle
= NULL
;
1704 DriverHealthInfo
->HiiHandle
= NULL
;
1705 DriverHealthInfo
->DriverHealth
= DriverHealth
;
1706 DriverHealthInfo
->MessageList
= NULL
;
1707 DriverHealthInfo
->HealthStatus
= *HealthStatus
;
1709 InsertTailList (DriverHealthList
, &DriverHealthInfo
->Link
);
1715 FormHiiHandle
= NULL
;
1718 // Collect the health status with the optional HII message list
1720 Status
= DriverHealth
->GetHealthStatus (DriverHealth
, ControllerHandle
, ChildHandle
, HealthStatus
, &MessageList
, &FormHiiHandle
);
1722 if (EFI_ERROR (Status
)) {
1724 // If the health status could not be retrieved, then return immediately
1730 // Add the driver health related information into the list
1732 DriverHealthInfo
= AllocateZeroPool (sizeof (DRIVER_HEALTH_INFO
));
1733 if (DriverHealthInfo
== NULL
) {
1734 return EFI_OUT_OF_RESOURCES
;
1737 DriverHealthInfo
->Signature
= DEVICE_MANAGER_DRIVER_HEALTH_INFO_SIGNATURE
;
1738 DriverHealthInfo
->DriverHandle
= DriverHandle
;
1739 DriverHealthInfo
->ControllerHandle
= ControllerHandle
;
1740 DriverHealthInfo
->ChildHandle
= ChildHandle
;
1741 DriverHealthInfo
->HiiHandle
= FormHiiHandle
;
1742 DriverHealthInfo
->DriverHealth
= DriverHealth
;
1743 DriverHealthInfo
->MessageList
= MessageList
;
1744 DriverHealthInfo
->HealthStatus
= *HealthStatus
;
1746 InsertTailList (DriverHealthList
, &DriverHealthInfo
->Link
);
1752 Collects all the EFI Driver Health Protocols currently present in the EFI Handle Database,
1753 and queries each EFI Driver Health Protocol to determine if one or more of the controllers
1754 managed by each EFI Driver Health Protocol instance are not healthy.
1756 @param DriverHealthList A Pointer to the list contain all of the platform driver health
1759 @retval EFI_NOT_FOUND No controller in the platform install Driver Health Protocol.
1760 @retval EFI_SUCCESS All the controllers in the platform are healthy.
1761 @retval EFI_OUT_OF_RESOURCES The list of Driver Health Protocol handles can not be retrieved.
1765 GetAllControllersHealthStatus (
1766 IN OUT LIST_ENTRY
*DriverHealthList
1771 EFI_HANDLE
*DriverHealthHandles
;
1772 EFI_DRIVER_HEALTH_PROTOCOL
*DriverHealth
;
1773 EFI_DRIVER_HEALTH_STATUS HealthStatus
;
1774 UINTN DriverHealthIndex
;
1775 EFI_HANDLE
*Handles
;
1777 UINTN ControllerIndex
;
1781 // Initialize local variables
1784 DriverHealthHandles
= NULL
;
1788 HealthStatus
= EfiDriverHealthStatusHealthy
;
1790 Status
= gBS
->LocateHandleBuffer (
1792 &gEfiDriverHealthProtocolGuid
,
1795 &DriverHealthHandles
1798 if (Status
== EFI_NOT_FOUND
|| NumHandles
== 0) {
1800 // If there are no Driver Health Protocols handles, then return EFI_NOT_FOUND
1802 return EFI_NOT_FOUND
;
1805 if (EFI_ERROR (Status
) || DriverHealthHandles
== NULL
) {
1807 // If the list of Driver Health Protocol handles can not be retrieved, then
1808 // return EFI_OUT_OF_RESOURCES
1810 return EFI_OUT_OF_RESOURCES
;
1814 // Check the health status of all controllers in the platform
1815 // Start by looping through all the Driver Health Protocol handles in the handle database
1817 for (DriverHealthIndex
= 0; DriverHealthIndex
< NumHandles
; DriverHealthIndex
++) {
1819 // Skip NULL Driver Health Protocol handles
1821 if (DriverHealthHandles
[DriverHealthIndex
] == NULL
) {
1826 // Retrieve the Driver Health Protocol from DriverHandle
1828 Status
= gBS
->HandleProtocol (
1829 DriverHealthHandles
[DriverHealthIndex
],
1830 &gEfiDriverHealthProtocolGuid
,
1831 (VOID
**)&DriverHealth
1833 if (EFI_ERROR (Status
)) {
1835 // If the Driver Health Protocol can not be retrieved, then skip to the next
1836 // Driver Health Protocol handle
1842 // Check the health of all the controllers managed by a Driver Health Protocol handle
1844 Status
= GetSingleControllerHealthStatus (DriverHealthList
, DriverHealthHandles
[DriverHealthIndex
], NULL
, NULL
, DriverHealth
, &HealthStatus
);
1847 // If Status is an error code, then the health information could not be retrieved, so assume healthy
1848 // and skip to the next Driver Health Protocol handle
1850 if (EFI_ERROR (Status
)) {
1855 // If all the controllers managed by this Driver Health Protocol are healthy, then skip to the next
1856 // Driver Health Protocol handle
1858 if (HealthStatus
== EfiDriverHealthStatusHealthy
) {
1863 // See if the list of all handles in the handle database has been retrieved
1866 if (Handles
== NULL
) {
1868 // Retrieve the list of all handles from the handle database
1870 Status
= gBS
->LocateHandleBuffer (
1877 if (EFI_ERROR (Status
) || Handles
== NULL
) {
1879 // If all the handles in the handle database can not be retrieved, then
1880 // return EFI_OUT_OF_RESOURCES
1882 Status
= EFI_OUT_OF_RESOURCES
;
1887 // Loop through all the controller handles in the handle database
1889 for (ControllerIndex
= 0; ControllerIndex
< HandleCount
; ControllerIndex
++) {
1891 // Skip NULL controller handles
1893 if (Handles
[ControllerIndex
] == NULL
) {
1897 Status
= GetSingleControllerHealthStatus (DriverHealthList
, DriverHealthHandles
[DriverHealthIndex
], Handles
[ControllerIndex
], NULL
, DriverHealth
, &HealthStatus
);
1898 if (EFI_ERROR (Status
)) {
1900 // If Status is an error code, then the health information could not be retrieved, so assume healthy
1902 HealthStatus
= EfiDriverHealthStatusHealthy
;
1906 // If CheckHealthSingleController() returned an error on a terminal state, then do not check the health of child controllers
1908 if (EFI_ERROR (Status
)) {
1913 // Loop through all the child handles in the handle database
1915 for (ChildIndex
= 0; ChildIndex
< HandleCount
; ChildIndex
++) {
1917 // Skip NULL child handles
1919 if (Handles
[ChildIndex
] == NULL
) {
1923 Status
= GetSingleControllerHealthStatus (DriverHealthList
, DriverHealthHandles
[DriverHealthIndex
], Handles
[ControllerIndex
], Handles
[ChildIndex
], DriverHealth
, &HealthStatus
);
1924 if (EFI_ERROR (Status
)) {
1926 // If Status is an error code, then the health information could not be retrieved, so assume healthy
1928 HealthStatus
= EfiDriverHealthStatusHealthy
;
1932 // If CheckHealthSingleController() returned an error on a terminal state, then skip to the next child
1934 if (EFI_ERROR (Status
)) {
1941 Status
= EFI_SUCCESS
;
1944 if (Handles
!= NULL
) {
1945 gBS
->FreePool (Handles
);
1947 if (DriverHealthHandles
!= NULL
) {
1948 gBS
->FreePool (DriverHealthHandles
);
1956 Check the healthy status of the platform, this function will return immediately while found one driver
1957 in the platform are not healthy.
1959 @retval FALSE at least one driver in the platform are not healthy.
1960 @retval TRUE No controller install Driver Health Protocol,
1961 or all controllers in the platform are in healthy status.
1964 PlaformHealthStatusCheck (
1968 EFI_DRIVER_HEALTH_STATUS HealthStatus
;
1972 EFI_HANDLE
*DriverHealthHandles
;
1973 EFI_DRIVER_HEALTH_PROTOCOL
*DriverHealth
;
1977 // Initialize local variables
1979 DriverHealthHandles
= NULL
;
1980 DriverHealth
= NULL
;
1982 HealthStatus
= EfiDriverHealthStatusHealthy
;
1984 Status
= gBS
->LocateHandleBuffer (
1986 &gEfiDriverHealthProtocolGuid
,
1989 &DriverHealthHandles
1992 // There are no handles match the search for Driver Health Protocol has been installed.
1994 if (Status
== EFI_NOT_FOUND
) {
1998 // Assume all modules are healthy.
2003 // Found one or more Handles.
2005 if (!EFI_ERROR (Status
)) {
2006 for (Index
= 0; Index
< NoHandles
; Index
++) {
2007 Status
= gBS
->HandleProtocol (
2008 DriverHealthHandles
[Index
],
2009 &gEfiDriverHealthProtocolGuid
,
2010 (VOID
**) &DriverHealth
2012 if (!EFI_ERROR (Status
)) {
2013 Status
= DriverHealth
->GetHealthStatus (
2023 // Get the healthy status of the module
2025 if (!EFI_ERROR (Status
)) {
2026 if (HealthStatus
!= EfiDriverHealthStatusHealthy
) {
2028 // Return immediately one driver's status not in healthy.
2039 Processes a single controller using the EFI Driver Health Protocol associated with
2040 that controller. This algorithm continues to query the GetHealthStatus() service until
2041 one of the legal terminal states of the EFI Driver Health Protocol is reached. This may
2042 require the processing of HII Messages, HII Form, and invocation of repair operations.
2044 @param DriverHealth A pointer to the EFI_DRIVER_HEALTH_PROTOCOL instance.
2045 @param ControllerHandle The class guid specifies which form set will be displayed.
2046 @param ChildHandle The handle of the child controller to retrieve the health
2047 status on. This is an optional parameter that may be NULL.
2048 @param HealthStatus The health status of the controller.
2049 @param MessageList An array of warning or error messages associated
2050 with the controller specified by ControllerHandle and
2051 ChildHandle. This is an optional parameter that may be NULL.
2052 @param FormHiiHandle The HII handle for an HII form associated with the
2053 controller specified by ControllerHandle and ChildHandle.
2054 @param RebootRequired Indicate whether a reboot is required to repair the controller.
2057 ProcessSingleControllerHealth (
2058 IN EFI_DRIVER_HEALTH_PROTOCOL
*DriverHealth
,
2059 IN EFI_HANDLE ControllerHandle
, OPTIONAL
2060 IN EFI_HANDLE ChildHandle
, OPTIONAL
2061 IN EFI_DRIVER_HEALTH_STATUS HealthStatus
,
2062 IN EFI_DRIVER_HEALTH_HII_MESSAGE
**MessageList
, OPTIONAL
2063 IN EFI_HII_HANDLE FormHiiHandle
,
2064 IN OUT BOOLEAN
*RebootRequired
2068 EFI_DRIVER_HEALTH_STATUS LocalHealthStatus
;
2070 LocalHealthStatus
= HealthStatus
;
2072 // If the module need to be repaired or reconfiguration, will process it until
2073 // reach a terminal status. The status from EfiDriverHealthStatusRepairRequired after repair
2074 // will be in (Health, Failed, Configuration Required).
2076 while(LocalHealthStatus
== EfiDriverHealthStatusConfigurationRequired
||
2077 LocalHealthStatus
== EfiDriverHealthStatusRepairRequired
) {
2079 if (LocalHealthStatus
== EfiDriverHealthStatusRepairRequired
) {
2080 Status
= DriverHealth
->Repair (
2088 // Via a form of the driver need to do configuration provided to process of status in
2089 // EfiDriverHealthStatusConfigurationRequired. The status after configuration should be in
2090 // (Healthy, Reboot Required, Failed, Reconnect Required, Repair Required).
2092 if (LocalHealthStatus
== EfiDriverHealthStatusConfigurationRequired
) {
2093 if (FormHiiHandle
!= NULL
) {
2094 Status
= gFormBrowser2
->SendForm (
2098 &gEfiHiiDriverHealthFormsetGuid
,
2103 ASSERT( !EFI_ERROR (Status
));
2106 // Exit the loop in case no FormHiiHandle is supplied to prevent dead-loop
2112 Status
= DriverHealth
->GetHealthStatus (
2120 ASSERT_EFI_ERROR (Status
);
2122 if (*MessageList
!= NULL
) {
2123 ProcessMessages (*MessageList
);
2128 // Health status in {Healthy, Failed} may also have Messages need to process
2130 if (LocalHealthStatus
== EfiDriverHealthStatusHealthy
|| LocalHealthStatus
== EfiDriverHealthStatusFailed
) {
2131 if (*MessageList
!= NULL
) {
2132 ProcessMessages (*MessageList
);
2136 // Check for RebootRequired or ReconnectRequired
2138 if (LocalHealthStatus
== EfiDriverHealthStatusRebootRequired
) {
2139 *RebootRequired
= TRUE
;
2143 // Do reconnect if need.
2145 if (LocalHealthStatus
== EfiDriverHealthStatusReconnectRequired
) {
2146 Status
= gBS
->DisconnectController (ControllerHandle
, NULL
, NULL
);
2147 if (EFI_ERROR (Status
)) {
2149 // Disconnect failed. Need to promote reconnect to a reboot.
2151 *RebootRequired
= TRUE
;
2153 gBS
->ConnectController (ControllerHandle
, NULL
, NULL
, TRUE
);
2160 Reports the progress of a repair operation.
2162 @param[in] Value A value between 0 and Limit that identifies the current
2163 progress of the repair operation.
2165 @param[in] Limit The maximum value of Value for the current repair operation.
2166 For example, a driver that wants to specify progress in
2167 percent would use a Limit value of 100.
2169 @retval EFI_SUCCESS The progress of a repair operation is reported successfully.
2182 Print(L
"Repair Progress Undefined\n\r");
2184 Percent
= Value
* 100 / Limit
;
2185 Print(L
"Repair Progress = %3d%%\n\r", Percent
);
2191 Processes a set of messages returned by the GetHealthStatus ()
2192 service of the EFI Driver Health Protocol
2194 @param MessageList The MessageList point to messages need to processed.
2199 IN EFI_DRIVER_HEALTH_HII_MESSAGE
*MessageList
2203 EFI_STRING MessageString
;
2205 for (MessageIndex
= 0;
2206 MessageList
[MessageIndex
].HiiHandle
!= NULL
;
2209 MessageString
= HiiGetString (
2210 MessageList
[MessageIndex
].HiiHandle
,
2211 MessageList
[MessageIndex
].StringId
,
2214 if (MessageString
!= NULL
) {
2216 // User can customize the output. Just simply print out the MessageString like below.
2217 // Also can use the HiiHandle to display message on the front page.
2219 // Print(L"%s\n",MessageString);
2220 // gBS->Stall (100000);
2227 Repair the whole platform.
2229 This function is the main entry for user choose "Repair All" in the front page.
2230 It will try to do recovery job till all the driver health protocol installed modules
2231 reach a terminal state.
2233 @param DriverHealthList A Pointer to the list contain all of the platform driver health
2239 IN LIST_ENTRY
*DriverHealthList
2242 DRIVER_HEALTH_INFO
*DriverHealthInfo
;
2244 BOOLEAN RebootRequired
;
2246 ASSERT (DriverHealthList
!= NULL
);
2248 RebootRequired
= FALSE
;
2250 for ( Link
= GetFirstNode (DriverHealthList
)
2251 ; !IsNull (DriverHealthList
, Link
)
2252 ; Link
= GetNextNode (DriverHealthList
, Link
)
2254 DriverHealthInfo
= DEVICE_MANAGER_HEALTH_INFO_FROM_LINK (Link
);
2256 // Do driver health status operation by each link node
2258 ASSERT (DriverHealthInfo
!= NULL
);
2260 ProcessSingleControllerHealth (
2261 DriverHealthInfo
->DriverHealth
,
2262 DriverHealthInfo
->ControllerHandle
,
2263 DriverHealthInfo
->ChildHandle
,
2264 DriverHealthInfo
->HealthStatus
,
2265 &(DriverHealthInfo
->MessageList
),
2266 DriverHealthInfo
->HiiHandle
,
2271 if (RebootRequired
) {
2272 gRT
->ResetSystem (EfiResetWarm
, EFI_SUCCESS
, 0, NULL
);
2278 Select the best matching language according to front page policy for best user experience.
2280 This function supports both ISO 639-2 and RFC 4646 language codes, but language
2281 code types may not be mixed in a single call to this function.
2283 @param SupportedLanguages A pointer to a Null-terminated ASCII string that
2284 contains a set of language codes in the format
2285 specified by Iso639Language.
2286 @param Iso639Language If TRUE, then all language codes are assumed to be
2287 in ISO 639-2 format. If FALSE, then all language
2288 codes are assumed to be in RFC 4646 language format.
2290 @retval NULL The best matching language could not be found in SupportedLanguages.
2291 @retval NULL There are not enough resources available to return the best matching
2293 @retval Other A pointer to a Null-terminated ASCII string that is the best matching
2294 language in SupportedLanguages.
2297 DriverHealthSelectBestLanguage (
2298 IN CHAR8
*SupportedLanguages
,
2299 IN BOOLEAN Iso639Language
2302 CHAR8
*LanguageVariable
;
2303 CHAR8
*BestLanguage
;
2305 GetEfiGlobalVariable2 (Iso639Language
? L
"Lang" : L
"PlatformLang", (VOID
**)&LanguageVariable
, NULL
);
2307 BestLanguage
= GetBestLanguage(
2310 (LanguageVariable
!= NULL
) ? LanguageVariable
: "",
2311 Iso639Language
? "eng" : "en-US",
2314 if (LanguageVariable
!= NULL
) {
2315 FreePool (LanguageVariable
);
2318 return BestLanguage
;
2325 This is an internal worker function to get the Component Name (2) protocol interface
2326 and the language it supports.
2328 @param ProtocolGuid A pointer to an EFI_GUID. It points to Component Name (2) protocol GUID.
2329 @param DriverBindingHandle The handle on which the Component Name (2) protocol instance is retrieved.
2330 @param ComponentName A pointer to the Component Name (2) protocol interface.
2331 @param SupportedLanguage The best suitable language that matches the SupportedLangues interface for the
2332 located Component Name (2) instance.
2334 @retval EFI_SUCCESS The Component Name (2) protocol instance is successfully located and we find
2335 the best matching language it support.
2336 @retval EFI_UNSUPPORTED The input Language is not supported by the Component Name (2) protocol.
2337 @retval Other Some error occurs when locating Component Name (2) protocol instance or finding
2338 the supported language.
2342 GetComponentNameWorker (
2343 IN EFI_GUID
*ProtocolGuid
,
2344 IN EFI_HANDLE DriverBindingHandle
,
2345 OUT EFI_COMPONENT_NAME_PROTOCOL
**ComponentName
,
2346 OUT CHAR8
**SupportedLanguage
2352 // Locate Component Name (2) protocol on the driver binging handle.
2354 Status
= gBS
->OpenProtocol (
2355 DriverBindingHandle
,
2357 (VOID
**) ComponentName
,
2360 EFI_OPEN_PROTOCOL_GET_PROTOCOL
2362 if (EFI_ERROR (Status
)) {
2367 // Apply shell policy to select the best language.
2369 *SupportedLanguage
= DriverHealthSelectBestLanguage (
2370 (*ComponentName
)->SupportedLanguages
,
2371 (BOOLEAN
) (ProtocolGuid
== &gEfiComponentNameProtocolGuid
)
2373 if (*SupportedLanguage
== NULL
) {
2374 Status
= EFI_UNSUPPORTED
;
2382 This is an internal worker function to get driver name from Component Name (2) protocol interface.
2385 @param ProtocolGuid A pointer to an EFI_GUID. It points to Component Name (2) protocol GUID.
2386 @param DriverBindingHandle The handle on which the Component Name (2) protocol instance is retrieved.
2387 @param DriverName A pointer to the Unicode string to return. This Unicode string is the name
2388 of the driver specified by This.
2390 @retval EFI_SUCCESS The driver name is successfully retrieved from Component Name (2) protocol
2392 @retval Other The driver name cannot be retrieved from Component Name (2) protocol
2397 GetDriverNameWorker (
2398 IN EFI_GUID
*ProtocolGuid
,
2399 IN EFI_HANDLE DriverBindingHandle
,
2400 OUT CHAR16
**DriverName
2404 CHAR8
*BestLanguage
;
2405 EFI_COMPONENT_NAME_PROTOCOL
*ComponentName
;
2408 // Retrieve Component Name (2) protocol instance on the driver binding handle and
2409 // find the best language this instance supports.
2411 Status
= GetComponentNameWorker (
2413 DriverBindingHandle
,
2417 if (EFI_ERROR (Status
)) {
2422 // Get the driver name from Component Name (2) protocol instance on the driver binging handle.
2424 Status
= ComponentName
->GetDriverName (
2429 FreePool (BestLanguage
);
2436 This function gets driver name from Component Name 2 protocol interface and Component Name protocol interface
2437 in turn. It first tries UEFI 2.0 Component Name 2 protocol interface and try to get the driver name.
2438 If the attempt fails, it then gets the driver name from EFI 1.1 Component Name protocol for backward
2439 compatibility support.
2441 @param DriverBindingHandle The handle on which the Component Name (2) protocol instance is retrieved.
2442 @param DriverName A pointer to the Unicode string to return. This Unicode string is the name
2443 of the driver specified by This.
2445 @retval EFI_SUCCESS The driver name is successfully retrieved from Component Name (2) protocol
2447 @retval Other The driver name cannot be retrieved from Component Name (2) protocol
2452 DriverHealthGetDriverName (
2453 IN EFI_HANDLE DriverBindingHandle
,
2454 OUT CHAR16
**DriverName
2460 // Get driver name from UEFI 2.0 Component Name 2 protocol interface.
2462 Status
= GetDriverNameWorker (&gEfiComponentName2ProtocolGuid
, DriverBindingHandle
, DriverName
);
2463 if (EFI_ERROR (Status
)) {
2465 // If it fails to get the driver name from Component Name protocol interface, we should fall back on
2466 // EFI 1.1 Component Name protocol interface.
2468 Status
= GetDriverNameWorker (&gEfiComponentNameProtocolGuid
, DriverBindingHandle
, DriverName
);
2477 This function gets controller name from Component Name 2 protocol interface and Component Name protocol interface
2478 in turn. It first tries UEFI 2.0 Component Name 2 protocol interface and try to get the controller name.
2479 If the attempt fails, it then gets the controller name from EFI 1.1 Component Name protocol for backward
2480 compatibility support.
2482 @param ProtocolGuid A pointer to an EFI_GUID. It points to Component Name (2) protocol GUID.
2483 @param DriverBindingHandle The handle on which the Component Name (2) protocol instance is retrieved.
2484 @param ControllerHandle The handle of a controller that the driver specified by This is managing.
2485 This handle specifies the controller whose name is to be returned.
2486 @param ChildHandle The handle of the child controller to retrieve the name of. This is an
2487 optional parameter that may be NULL. It will be NULL for device drivers.
2488 It will also be NULL for bus drivers that attempt to retrieve the name
2489 of the bus controller. It will not be NULL for a bus driver that attempts
2490 to retrieve the name of a child controller.
2491 @param ControllerName A pointer to the Unicode string to return. This Unicode string
2492 is the name of the controller specified by ControllerHandle and ChildHandle.
2494 @retval EFI_SUCCESS The controller name is successfully retrieved from Component Name (2) protocol
2496 @retval Other The controller name cannot be retrieved from Component Name (2) protocol.
2500 GetControllerNameWorker (
2501 IN EFI_GUID
*ProtocolGuid
,
2502 IN EFI_HANDLE DriverBindingHandle
,
2503 IN EFI_HANDLE ControllerHandle
,
2504 IN EFI_HANDLE ChildHandle
,
2505 OUT CHAR16
**ControllerName
2509 CHAR8
*BestLanguage
;
2510 EFI_COMPONENT_NAME_PROTOCOL
*ComponentName
;
2513 // Retrieve Component Name (2) protocol instance on the driver binding handle and
2514 // find the best language this instance supports.
2516 Status
= GetComponentNameWorker (
2518 DriverBindingHandle
,
2522 if (EFI_ERROR (Status
)) {
2527 // Get the controller name from Component Name (2) protocol instance on the driver binging handle.
2529 Status
= ComponentName
->GetControllerName (
2536 FreePool (BestLanguage
);
2543 This function gets controller name from Component Name 2 protocol interface and Component Name protocol interface
2544 in turn. It first tries UEFI 2.0 Component Name 2 protocol interface and try to get the controller name.
2545 If the attempt fails, it then gets the controller name from EFI 1.1 Component Name protocol for backward
2546 compatibility support.
2548 @param DriverBindingHandle The handle on which the Component Name (2) protocol instance is retrieved.
2549 @param ControllerHandle The handle of a controller that the driver specified by This is managing.
2550 This handle specifies the controller whose name is to be returned.
2551 @param ChildHandle The handle of the child controller to retrieve the name of. This is an
2552 optional parameter that may be NULL. It will be NULL for device drivers.
2553 It will also be NULL for bus drivers that attempt to retrieve the name
2554 of the bus controller. It will not be NULL for a bus driver that attempts
2555 to retrieve the name of a child controller.
2556 @param ControllerName A pointer to the Unicode string to return. This Unicode string
2557 is the name of the controller specified by ControllerHandle and ChildHandle.
2559 @retval EFI_SUCCESS The controller name is successfully retrieved from Component Name (2) protocol
2561 @retval Other The controller name cannot be retrieved from Component Name (2) protocol.
2565 DriverHealthGetControllerName (
2566 IN EFI_HANDLE DriverBindingHandle
,
2567 IN EFI_HANDLE ControllerHandle
,
2568 IN EFI_HANDLE ChildHandle
,
2569 OUT CHAR16
**ControllerName
2575 // Get controller name from UEFI 2.0 Component Name 2 protocol interface.
2577 Status
= GetControllerNameWorker (
2578 &gEfiComponentName2ProtocolGuid
,
2579 DriverBindingHandle
,
2584 if (EFI_ERROR (Status
)) {
2586 // If it fails to get the controller name from Component Name protocol interface, we should fall back on
2587 // EFI 1.1 Component Name protocol interface.
2589 Status
= GetControllerNameWorker (
2590 &gEfiComponentNameProtocolGuid
,
2591 DriverBindingHandle
,