2 The platform device manager reference implementation
4 Copyright (c) 2004 - 2015, 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 #define MAX_MAC_ADDRESS_NODE_LIST_LEN 10
38 // Which Mac Address string is select
39 // it will decide what menu need to show in the NETWORK_DEVICE_FORM_ID form.
41 EFI_STRING mSelectedMacAddrString
;
44 // Which form Id need to be show.
46 EFI_FORM_ID mNextShowFormId
= DEVICE_MANAGER_FORM_ID
;
49 // The Mac Address show in the NETWORK_DEVICE_LIST_FORM_ID
51 MAC_ADDRESS_NODE_LIST mMacDeviceList
;
53 DEVICE_MANAGER_MENU_ITEM mDeviceManagerMenuItemTable
[] = {
54 { STRING_TOKEN (STR_DISK_DEVICE
), EFI_DISK_DEVICE_CLASS
},
55 { STRING_TOKEN (STR_VIDEO_DEVICE
), EFI_VIDEO_DEVICE_CLASS
},
56 { STRING_TOKEN (STR_NETWORK_DEVICE
), EFI_NETWORK_DEVICE_CLASS
},
57 { STRING_TOKEN (STR_INPUT_DEVICE
), EFI_INPUT_DEVICE_CLASS
},
58 { STRING_TOKEN (STR_ON_BOARD_DEVICE
), EFI_ON_BOARD_DEVICE_CLASS
},
59 { STRING_TOKEN (STR_OTHER_DEVICE
), EFI_OTHER_DEVICE_CLASS
}
62 HII_VENDOR_DEVICE_PATH mDeviceManagerHiiVendorDevicePath
= {
68 (UINT8
) (sizeof (VENDOR_DEVICE_PATH
)),
69 (UINT8
) ((sizeof (VENDOR_DEVICE_PATH
)) >> 8)
72 DEVICE_MANAGER_FORMSET_GUID
76 END_ENTIRE_DEVICE_PATH_SUBTYPE
,
78 (UINT8
) (END_DEVICE_PATH_LENGTH
),
79 (UINT8
) ((END_DEVICE_PATH_LENGTH
) >> 8)
84 HII_VENDOR_DEVICE_PATH mDriverHealthHiiVendorDevicePath
= {
90 (UINT8
) (sizeof (VENDOR_DEVICE_PATH
)),
91 (UINT8
) ((sizeof (VENDOR_DEVICE_PATH
)) >> 8)
94 DRIVER_HEALTH_FORMSET_GUID
98 END_ENTIRE_DEVICE_PATH_SUBTYPE
,
100 (UINT8
) (END_DEVICE_PATH_LENGTH
),
101 (UINT8
) ((END_DEVICE_PATH_LENGTH
) >> 8)
107 This function is invoked if user selected a interactive opcode from Device Manager's
108 Formset. The decision by user is saved to gCallbackKey for later processing. If
109 user set VBIOS, the new value is saved to EFI variable.
111 @param This Points to the EFI_HII_CONFIG_ACCESS_PROTOCOL.
112 @param Action Specifies the type of action taken by the browser.
113 @param QuestionId A unique value which is sent to the original exporting driver
114 so that it can identify the type of data to expect.
115 @param Type The type of value for the question.
116 @param Value A pointer to the data being sent to the original exporting driver.
117 @param ActionRequest On return, points to the action requested by the callback function.
119 @retval EFI_SUCCESS The callback successfully handled the action.
120 @retval EFI_INVALID_PARAMETER The setup browser call this function with invalid parameters.
125 DeviceManagerCallback (
126 IN CONST EFI_HII_CONFIG_ACCESS_PROTOCOL
*This
,
127 IN EFI_BROWSER_ACTION Action
,
128 IN EFI_QUESTION_ID QuestionId
,
130 IN EFI_IFR_TYPE_VALUE
*Value
,
131 OUT EFI_BROWSER_ACTION_REQUEST
*ActionRequest
136 if (Action
!= EFI_BROWSER_ACTION_CHANGING
) {
138 // All other action return unsupported.
140 return EFI_UNSUPPORTED
;
144 return EFI_INVALID_PARAMETER
;
147 gCallbackKey
= QuestionId
;
148 if ((QuestionId
< MAX_KEY_SECTION_LEN
+ NETWORK_DEVICE_LIST_KEY_OFFSET
) && (QuestionId
>= NETWORK_DEVICE_LIST_KEY_OFFSET
)) {
150 // If user select the mac address, need to record mac address string to support next form show.
152 for (CurIndex
= 0; CurIndex
< mMacDeviceList
.CurListLen
; CurIndex
++) {
153 if (mMacDeviceList
.NodeList
[CurIndex
].QuestionId
== QuestionId
) {
154 mSelectedMacAddrString
= HiiGetString (gDeviceManagerPrivate
.HiiHandle
, mMacDeviceList
.NodeList
[CurIndex
].PromptId
, NULL
);
164 This function registers HII packages to HII database.
166 @retval EFI_SUCCESS HII packages for the Device Manager were registered successfully.
167 @retval EFI_OUT_OF_RESOURCES HII packages for the Device Manager failed to be registered.
171 InitializeDeviceManager (
178 // Install Device Path Protocol and Config Access protocol to driver handle
180 Status
= gBS
->InstallMultipleProtocolInterfaces (
181 &gDeviceManagerPrivate
.DriverHandle
,
182 &gEfiDevicePathProtocolGuid
,
183 &mDeviceManagerHiiVendorDevicePath
,
184 &gEfiHiiConfigAccessProtocolGuid
,
185 &gDeviceManagerPrivate
.ConfigAccess
,
188 ASSERT_EFI_ERROR (Status
);
190 Status
= gBS
->InstallMultipleProtocolInterfaces (
191 &gDeviceManagerPrivate
.DriverHealthHandle
,
192 &gEfiDevicePathProtocolGuid
,
193 &mDriverHealthHiiVendorDevicePath
,
194 &gEfiHiiConfigAccessProtocolGuid
,
195 &gDeviceManagerPrivate
.DriverHealthConfigAccess
,
198 ASSERT_EFI_ERROR (Status
);
200 mMacDeviceList
.CurListLen
= 0;
201 mMacDeviceList
.MaxListLen
= 0;
207 Extract the displayed formset for given HII handle and class guid.
209 @param Handle The HII handle.
210 @param SetupClassGuid The class guid specifies which form set will be displayed.
211 @param SkipCount Skip some formsets which has processed before.
212 @param FormSetTitle Formset title string.
213 @param FormSetHelp Formset help string.
214 @param FormSetGuid Return the formset guid for this formset.
216 @retval TRUE The formset for given HII handle will be displayed.
217 @return FALSE The formset for given HII handle will not be displayed.
221 ExtractDisplayedHiiFormFromHiiHandle (
222 IN EFI_HII_HANDLE Handle
,
223 IN EFI_GUID
*SetupClassGuid
,
225 OUT EFI_STRING_ID
*FormSetTitle
,
226 OUT EFI_STRING_ID
*FormSetHelp
,
227 OUT EFI_GUID
**FormSetGuid
232 EFI_HII_PACKAGE_LIST_HEADER
*HiiPackageList
;
237 UINT32 PackageListLength
;
238 EFI_HII_PACKAGE_HEADER PackageHeader
;
242 ASSERT (Handle
!= NULL
);
243 ASSERT (SetupClassGuid
!= NULL
);
244 ASSERT (FormSetTitle
!= NULL
);
245 ASSERT (FormSetHelp
!= NULL
);
253 // Get HII PackageList
256 HiiPackageList
= NULL
;
257 Status
= gHiiDatabase
->ExportPackageLists (gHiiDatabase
, Handle
, &BufferSize
, HiiPackageList
);
259 // Handle is a invalid handle. Check if Handle is corrupted.
261 ASSERT (Status
!= EFI_NOT_FOUND
);
263 // The return status should always be EFI_BUFFER_TOO_SMALL as input buffer's size is 0.
265 ASSERT (Status
== EFI_BUFFER_TOO_SMALL
);
267 HiiPackageList
= AllocatePool (BufferSize
);
268 ASSERT (HiiPackageList
!= NULL
);
270 Status
= gHiiDatabase
->ExportPackageLists (gHiiDatabase
, Handle
, &BufferSize
, HiiPackageList
);
271 if (EFI_ERROR (Status
)) {
276 // Get Form package from this HII package List
278 Offset
= sizeof (EFI_HII_PACKAGE_LIST_HEADER
);
280 PackageListLength
= ReadUnaligned32 (&HiiPackageList
->PackageLength
);
282 while (Offset
< PackageListLength
) {
283 Package
= ((UINT8
*) HiiPackageList
) + Offset
;
284 CopyMem (&PackageHeader
, Package
, sizeof (EFI_HII_PACKAGE_HEADER
));
286 if (PackageHeader
.Type
== EFI_HII_PACKAGE_FORMS
) {
288 // Search FormSet Opcode in this Form Package
290 Offset2
= sizeof (EFI_HII_PACKAGE_HEADER
);
291 while (Offset2
< PackageHeader
.Length
) {
292 OpCodeData
= Package
+ Offset2
;
293 Offset2
+= ((EFI_IFR_OP_HEADER
*) OpCodeData
)->Length
;
295 if (((EFI_IFR_OP_HEADER
*) OpCodeData
)->OpCode
== EFI_IFR_FORM_SET_OP
) {
296 if (SkipCount
!= 0) {
301 if (((EFI_IFR_OP_HEADER
*) OpCodeData
)->Length
> OFFSET_OF (EFI_IFR_FORM_SET
, Flags
)) {
303 // Find FormSet OpCode
305 ClassGuidNum
= (UINT8
) (((EFI_IFR_FORM_SET
*) OpCodeData
)->Flags
& 0x3);
306 ClassGuid
= (EFI_GUID
*) (VOID
*)(OpCodeData
+ sizeof (EFI_IFR_FORM_SET
));
307 while (ClassGuidNum
-- > 0) {
308 if (CompareGuid (SetupClassGuid
, ClassGuid
)) {
309 CopyMem (FormSetTitle
, &((EFI_IFR_FORM_SET
*) OpCodeData
)->FormSetTitle
, sizeof (EFI_STRING_ID
));
310 CopyMem (FormSetHelp
, &((EFI_IFR_FORM_SET
*) OpCodeData
)->Help
, sizeof (EFI_STRING_ID
));
311 *FormSetGuid
= AllocateCopyPool (sizeof (EFI_GUID
), &((EFI_IFR_FORM_SET
*) OpCodeData
)->Guid
);
312 ASSERT (*FormSetGuid
!= NULL
);
313 FreePool (HiiPackageList
);
319 CopyMem (FormSetTitle
, &((EFI_IFR_FORM_SET
*) OpCodeData
)->FormSetTitle
, sizeof (EFI_STRING_ID
));
320 CopyMem (FormSetHelp
, &((EFI_IFR_FORM_SET
*) OpCodeData
)->Help
, sizeof (EFI_STRING_ID
));
321 *FormSetGuid
= AllocateCopyPool (sizeof (EFI_GUID
), &((EFI_IFR_FORM_SET
*) OpCodeData
)->Guid
);
322 ASSERT (*FormSetGuid
!= NULL
);
323 FreePool (HiiPackageList
);
331 // Go to next package
333 Offset
+= PackageHeader
.Length
;
336 FreePool (HiiPackageList
);
342 Get the mac address string from the device path.
343 if the device path has the vlan, get the vanid also.
345 @param MacAddressNode Device path begin with mac address
346 @param PBuffer Output string buffer contain mac address.
351 IN MAC_ADDR_DEVICE_PATH
*MacAddressNode
,
358 EFI_DEVICE_PATH_PROTOCOL
*Node
;
365 ASSERT(MacAddressNode
!= NULL
);
367 HwAddressSize
= sizeof (EFI_MAC_ADDRESS
);
368 if (MacAddressNode
->IfType
== 0x01 || MacAddressNode
->IfType
== 0x00) {
373 // The output format is MAC:XX:XX:XX:...\XXXX
374 // The size is the Number size + ":" size + Vlan size(\XXXX) + End
376 BufferLen
= (4 + 2 * HwAddressSize
+ (HwAddressSize
- 1) + 5 + 1) * sizeof (CHAR16
);
377 String
= AllocateCopyPool (BufferLen
, L
"MAC:");
378 if (String
== NULL
) {
386 // Convert the MAC address into a unicode string.
388 HwAddress
= &MacAddressNode
->MacAddress
.Addr
[0];
389 for (Index
= 0; Index
< HwAddressSize
; Index
++) {
390 String
+= UnicodeValueToString (String
, PREFIX_ZERO
| RADIX_HEX
, *(HwAddress
++), 2);
391 if (Index
< HwAddressSize
- 1) {
397 // If VLAN is configured, it will need extra 5 characters like "\0005".
398 // Plus one unicode character for the null-terminator.
400 Node
= (EFI_DEVICE_PATH_PROTOCOL
*)MacAddressNode
;
401 while (!IsDevicePathEnd (Node
)) {
402 if (Node
->Type
== MESSAGING_DEVICE_PATH
&& Node
->SubType
== MSG_VLAN_DP
) {
403 VlanId
= ((VLAN_DEVICE_PATH
*) Node
)->VlanId
;
405 Node
= NextDevicePathNode (Node
);
410 String
+= UnicodeValueToString (String
, PREFIX_ZERO
| RADIX_HEX
, VlanId
, 4);
414 // Null terminate the Unicode string
422 Save question id and prompt id to the mac device list.
423 If the same mac address has saved yet, no need to add more.
425 @param MacAddrString Mac address string.
427 @retval EFI_SUCCESS Add the item is successful.
428 @return Other values if failed to Add the item.
431 AddIdToMacDeviceList (
432 IN EFI_STRING MacAddrString
435 MENU_INFO_ITEM
*TempDeviceList
;
437 EFI_STRING StoredString
;
438 EFI_STRING_ID PromptId
;
439 EFI_HII_HANDLE HiiHandle
;
441 HiiHandle
= gDeviceManagerPrivate
.HiiHandle
;
442 TempDeviceList
= NULL
;
444 for (Index
= 0; Index
< mMacDeviceList
.CurListLen
; Index
++) {
445 StoredString
= HiiGetString (HiiHandle
, mMacDeviceList
.NodeList
[Index
].PromptId
, NULL
);
446 if (StoredString
== NULL
) {
451 // Already has save the same mac address to the list.
453 if (StrCmp (MacAddrString
, StoredString
) == 0) {
458 PromptId
= HiiSetString(HiiHandle
, 0, MacAddrString
, NULL
);
460 // If not in the list, save it.
462 if (mMacDeviceList
.MaxListLen
> mMacDeviceList
.CurListLen
+ 1) {
463 mMacDeviceList
.NodeList
[mMacDeviceList
.CurListLen
].PromptId
= PromptId
;
464 mMacDeviceList
.NodeList
[mMacDeviceList
.CurListLen
].QuestionId
= (EFI_QUESTION_ID
) (mMacDeviceList
.CurListLen
+ NETWORK_DEVICE_LIST_KEY_OFFSET
);
466 mMacDeviceList
.MaxListLen
+= MAX_MAC_ADDRESS_NODE_LIST_LEN
;
467 if (mMacDeviceList
.CurListLen
!= 0) {
468 TempDeviceList
= (MENU_INFO_ITEM
*)AllocateCopyPool (sizeof (MENU_INFO_ITEM
) * mMacDeviceList
.MaxListLen
, (VOID
*)mMacDeviceList
.NodeList
);
470 TempDeviceList
= (MENU_INFO_ITEM
*)AllocatePool (sizeof (MENU_INFO_ITEM
) * mMacDeviceList
.MaxListLen
);
473 if (TempDeviceList
== NULL
) {
476 TempDeviceList
[mMacDeviceList
.CurListLen
].PromptId
= PromptId
;
477 TempDeviceList
[mMacDeviceList
.CurListLen
].QuestionId
= (EFI_QUESTION_ID
) (mMacDeviceList
.CurListLen
+ NETWORK_DEVICE_LIST_KEY_OFFSET
);
479 if (mMacDeviceList
.CurListLen
> 0) {
480 FreePool(mMacDeviceList
.NodeList
);
483 mMacDeviceList
.NodeList
= TempDeviceList
;
485 mMacDeviceList
.CurListLen
++;
491 Check the devcie path, try to find whether it has mac address path.
493 In this function, first need to check whether this path has mac address path.
494 second, when the mac address device path has find, also need to deicide whether
495 need to add this mac address relate info to the menu.
497 @param *Node Input device which need to be check.
498 @param *NeedAddItem Whether need to add the menu in the network device list.
500 @retval TRUE Has mac address device path.
501 @retval FALSE NOT Has mac address device path.
505 IsMacAddressDevicePath (
507 OUT BOOLEAN
*NeedAddItem
510 EFI_DEVICE_PATH_PROTOCOL
*DevicePath
;
514 ASSERT (Node
!= NULL
);
515 *NeedAddItem
= FALSE
;
519 DevicePath
= (EFI_DEVICE_PATH_PROTOCOL
*) Node
;
522 // find the partition device path node
524 while (!IsDevicePathEnd (DevicePath
)) {
525 if ((DevicePathType (DevicePath
) == MESSAGING_DEVICE_PATH
) &&
526 (DevicePathSubType (DevicePath
) == MSG_MAC_ADDR_DP
)) {
529 if (DEVICE_MANAGER_FORM_ID
== mNextShowFormId
) {
534 if (!GetMacAddressString((MAC_ADDR_DEVICE_PATH
*)DevicePath
, &Buffer
)) {
538 if (NETWORK_DEVICE_FORM_ID
== mNextShowFormId
) {
539 if (StrCmp (Buffer
, mSelectedMacAddrString
) == 0) {
545 if (NETWORK_DEVICE_LIST_FORM_ID
== mNextShowFormId
) {
547 // Same handle may has two network child handle, so the questionid
548 // has the offset of SAME_HANDLE_KEY_OFFSET.
550 if (AddIdToMacDeviceList (Buffer
)) {
556 DevicePath
= NextDevicePathNode (DevicePath
);
559 if (Buffer
!= NULL
) {
567 Check to see if the device path is for the network device.
569 @param Handle The HII handle which include the mac address device path.
570 @param ItemCount The new add Mac address item count.
572 @retval TRUE Need to add new item in the menu.
573 @return FALSE Do not need to add the menu about the network.
577 IsNeedAddNetworkMenu (
578 IN EFI_HII_HANDLE Handle
,
585 EFI_HANDLE DriverHandle
;
586 EFI_HANDLE ControllerHandle
;
587 EFI_DEVICE_PATH_PROTOCOL
*DevicePath
;
588 EFI_DEVICE_PATH_PROTOCOL
*TmpDevicePath
;
589 EFI_DEVICE_PATH_PROTOCOL
*ChildDevicePath
;
590 EFI_OPEN_PROTOCOL_INFORMATION_ENTRY
*OpenInfoBuffer
;
594 OpenInfoBuffer
= NULL
;
595 if ((Handle
== NULL
) || (ItemCount
== NULL
)) {
600 Status
= gHiiDatabase
->GetPackageListHandle (gHiiDatabase
, Handle
, &DriverHandle
);
601 if (EFI_ERROR (Status
)) {
605 // Get the device path by the got Driver handle .
607 Status
= gBS
->HandleProtocol (DriverHandle
, &gEfiDevicePathProtocolGuid
, (VOID
**) &DevicePath
);
608 if (EFI_ERROR (Status
)) {
611 TmpDevicePath
= DevicePath
;
614 // Check whether this device path include mac address device path.
615 // If this path has mac address path, get the value whether need
616 // add this info to the menu and return.
617 // Else check more about the child handle devcie path.
619 if (IsMacAddressDevicePath(TmpDevicePath
, &IsNeedAdd
)) {
620 if ((NETWORK_DEVICE_LIST_FORM_ID
== mNextShowFormId
) && IsNeedAdd
) {
627 // Search whether this path is the controller path, not he child handle path.
628 // And the child handle has the network devcie connected.
630 TmpDevicePath
= DevicePath
;
631 Status
= gBS
->LocateDevicePath(&gEfiDevicePathProtocolGuid
, &TmpDevicePath
, &ControllerHandle
);
632 if (EFI_ERROR (Status
)) {
636 if (!IsDevicePathEnd (TmpDevicePath
)) {
641 // Retrieve the list of agents that are consuming the specific protocol
642 // on ControllerHandle.
643 // The buffer point by OpenInfoBuffer need be free at this function.
645 Status
= gBS
->OpenProtocolInformation (
647 &gEfiPciIoProtocolGuid
,
651 if (EFI_ERROR (Status
)) {
656 // Inspect if ChildHandle is one of the agents.
658 Status
= EFI_UNSUPPORTED
;
659 for (Index
= 0; Index
< EntryCount
; Index
++) {
661 // Query all the children created by the controller handle's driver
663 if ((OpenInfoBuffer
[Index
].Attributes
& EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER
) != 0) {
664 Status
= gBS
->OpenProtocol (
665 OpenInfoBuffer
[Index
].ControllerHandle
,
666 &gEfiDevicePathProtocolGuid
,
667 (VOID
**) &ChildDevicePath
,
670 EFI_OPEN_PROTOCOL_GET_PROTOCOL
672 if (EFI_ERROR (Status
)) {
677 // Check whether this device path include mac address device path.
679 if (!IsMacAddressDevicePath(ChildDevicePath
, &IsNeedAdd
)) {
681 // If this path not has mac address path, check the other.
686 // If need to update the NETWORK_DEVICE_LIST_FORM, try to get more.
688 if ((NETWORK_DEVICE_LIST_FORM_ID
== mNextShowFormId
)) {
695 // If need to update other form, return whether need to add to the menu.
704 if (OpenInfoBuffer
!= NULL
) {
705 FreePool (OpenInfoBuffer
);
711 Get HiiHandle total number.
713 @param HiiHandles The input HiiHandle array.
715 @retval the Hiihandle count.
720 IN EFI_HII_HANDLE
*HiiHandles
725 for (Index
= 0; HiiHandles
[Index
] != NULL
; Index
++) {
732 Insert the new HiiHandle + FormsetGuid at the NewPair[InsertOffset].
734 @param HiiHandles The input HiiHandle array.
735 @param GuidLists The input form set guid lists.
736 @param ArrayCount The input array count, new array will be arraycount + 1 size.
737 @param Offset The current used HiiHandle's Offset.
738 @param FormSetGuid The new found formset guid.
743 IN OUT EFI_HII_HANDLE
**HiiHandles
,
744 IN OUT EFI_GUID
***GuidLists
,
747 IN EFI_GUID
*FormSetGuid
750 EFI_HII_HANDLE
*NewHiiHandles
;
751 EFI_GUID
**NewGuidLists
;
754 // +2 means include the new HiiHandle and the last empty NULL pointer.
756 NewHiiHandles
= AllocateZeroPool ((ArrayCount
+ 2) * sizeof (EFI_HII_HANDLE
));
757 ASSERT (NewHiiHandles
!= NULL
);
759 CopyMem (NewHiiHandles
, *HiiHandles
, Offset
* sizeof (EFI_HII_HANDLE
));
760 NewHiiHandles
[Offset
] = NewHiiHandles
[Offset
- 1];
761 CopyMem (NewHiiHandles
+ Offset
+ 1, *HiiHandles
+ Offset
, (ArrayCount
- Offset
) * sizeof (EFI_HII_HANDLE
));
763 NewGuidLists
= AllocateZeroPool ((ArrayCount
+ 2) * sizeof (EFI_GUID
*));
764 ASSERT (NewGuidLists
!= NULL
);
766 CopyMem (NewGuidLists
, *GuidLists
, Offset
* sizeof (EFI_GUID
*));
767 NewGuidLists
[Offset
] = FormSetGuid
;
769 FreePool (*HiiHandles
);
770 *HiiHandles
= NewHiiHandles
;
771 FreePool (*GuidLists
);
772 *GuidLists
= NewGuidLists
;
776 Call the browser and display the device manager to allow user
777 to configure the platform.
779 This function create the dynamic content for device manager. It includes
780 section header for all class of devices, one-of opcode to set VBIOS.
782 @retval EFI_SUCCESS Operation is successful.
783 @return Other values if failed to clean up the dynamic content from HII
796 EFI_STRING_ID TokenHelp
;
797 EFI_HII_HANDLE
*HiiHandles
;
798 EFI_HII_HANDLE HiiHandle
;
799 EFI_STRING_ID FormSetTitle
;
800 EFI_STRING_ID FormSetHelp
;
801 EFI_BROWSER_ACTION_REQUEST ActionRequest
;
802 VOID
*StartOpCodeHandle
;
803 VOID
*EndOpCodeHandle
;
804 EFI_IFR_GUID_LABEL
*StartLabel
;
805 EFI_IFR_GUID_LABEL
*EndLabel
;
807 EFI_HANDLE
*DriverHealthHandles
;
808 BOOLEAN AddNetworkMenu
;
811 EFI_STRING NewStringTitle
;
812 EFI_GUID
**GuidLists
;
815 EFI_GUID
*FormSetGuid
;
819 Status
= EFI_SUCCESS
;
822 DriverHealthHandles
= NULL
;
823 AddNetworkMenu
= FALSE
;
829 // Connect all prior to entering the platform setup menu.
831 if (!gConnectAllHappened
) {
832 BdsLibConnectAllDriversToAllControllers ();
833 gConnectAllHappened
= TRUE
;
836 HiiHandle
= gDeviceManagerPrivate
.HiiHandle
;
837 if (HiiHandle
== NULL
) {
839 // Publish our HII data.
841 HiiHandle
= HiiAddPackages (
842 &gDeviceManagerFormSetGuid
,
843 gDeviceManagerPrivate
.DriverHandle
,
848 if (HiiHandle
== NULL
) {
849 return EFI_OUT_OF_RESOURCES
;
852 gDeviceManagerPrivate
.HiiHandle
= HiiHandle
;
856 // If need show the Network device list form, clear the old save list first.
858 if ((mNextShowFormId
== NETWORK_DEVICE_LIST_FORM_ID
) && (mMacDeviceList
.CurListLen
> 0)) {
859 mMacDeviceList
.CurListLen
= 0;
863 // Update the network device form titile.
865 if (mNextShowFormId
== NETWORK_DEVICE_FORM_ID
) {
866 String
= HiiGetString (HiiHandle
, STRING_TOKEN (STR_FORM_NETWORK_DEVICE_TITLE
), NULL
);
867 NewStringLen
= StrLen(mSelectedMacAddrString
) * 2;
868 NewStringLen
+= (StrLen(String
) + 2) * 2;
869 NewStringTitle
= AllocatePool (NewStringLen
);
870 UnicodeSPrint (NewStringTitle
, NewStringLen
, L
"%s %s", String
, mSelectedMacAddrString
);
871 HiiSetString (HiiHandle
, STRING_TOKEN (STR_FORM_NETWORK_DEVICE_TITLE
), NewStringTitle
, NULL
);
873 FreePool (NewStringTitle
);
877 // Allocate space for creation of UpdateData Buffer
879 StartOpCodeHandle
= HiiAllocateOpCodeHandle ();
880 ASSERT (StartOpCodeHandle
!= NULL
);
882 EndOpCodeHandle
= HiiAllocateOpCodeHandle ();
883 ASSERT (EndOpCodeHandle
!= NULL
);
886 // Create Hii Extend Label OpCode as the start opcode
888 StartLabel
= (EFI_IFR_GUID_LABEL
*) HiiCreateGuidOpCode (StartOpCodeHandle
, &gEfiIfrTianoGuid
, NULL
, sizeof (EFI_IFR_GUID_LABEL
));
889 StartLabel
->ExtendOpCode
= EFI_IFR_EXTEND_OP_LABEL
;
891 // According to the next show Form id(mNextShowFormId) to decide which form need to update.
893 StartLabel
->Number
= (UINT16
) (LABEL_FORM_ID_OFFSET
+ mNextShowFormId
);
896 // Create Hii Extend Label OpCode as the end opcode
898 EndLabel
= (EFI_IFR_GUID_LABEL
*) HiiCreateGuidOpCode (EndOpCodeHandle
, &gEfiIfrTianoGuid
, NULL
, sizeof (EFI_IFR_GUID_LABEL
));
899 EndLabel
->ExtendOpCode
= EFI_IFR_EXTEND_OP_LABEL
;
900 EndLabel
->Number
= LABEL_END
;
903 // Get all the Hii handles
905 HiiHandles
= HiiGetHiiHandles (NULL
);
906 ASSERT (HiiHandles
!= NULL
);
908 HandleNum
= GetHiiHandleCount (HiiHandles
);
909 GuidLists
= AllocateZeroPool ((HandleNum
+ 1) * sizeof (EFI_GUID
*));
910 ASSERT (GuidLists
!= NULL
);
913 // Search for formset of each class type
915 for (Index
= 0; HiiHandles
[Index
] != NULL
; Index
++) {
917 // The QuestionId in the form which will call the driver form has this asssumption.
918 // QuestionId = Handle Index + NETWORK_DEVICE_LIST_KEY_OFFSET;
919 // Different QuestionId at least has the section of NETWORK_DEVICE_LIST_KEY_OFFSET.
921 ASSERT(Index
< MAX_KEY_SECTION_LEN
);
923 if (!ExtractDisplayedHiiFormFromHiiHandle (HiiHandles
[Index
], &gEfiHiiPlatformSetupFormsetGuid
, SkipCount
, &FormSetTitle
, &FormSetHelp
, &FormSetGuid
)) {
929 // One HiiHandle has more than one formset can be shown,
930 // Insert a new pair of HiiHandle + Guid to the HiiHandles and GuidLists list.
933 AdjustArrayData (&HiiHandles
, &GuidLists
, HandleNum
, Index
+ 1, FormSetGuid
);
938 String
= HiiGetString (HiiHandles
[Index
], FormSetTitle
, NULL
);
939 if (String
== NULL
) {
940 String
= HiiGetString (HiiHandle
, STR_MISSING_STRING
, NULL
);
941 ASSERT (String
!= NULL
);
943 Token
= HiiSetString (HiiHandle
, 0, String
, NULL
);
946 String
= HiiGetString (HiiHandles
[Index
], FormSetHelp
, NULL
);
947 if (String
== NULL
) {
948 String
= HiiGetString (HiiHandle
, STR_MISSING_STRING
, NULL
);
949 ASSERT (String
!= NULL
);
951 TokenHelp
= HiiSetString (HiiHandle
, 0, String
, NULL
);
955 // Network device process
957 if (IsNeedAddNetworkMenu (HiiHandles
[Index
], &AddItemCount
)) {
958 if (mNextShowFormId
== DEVICE_MANAGER_FORM_ID
) {
960 // Only show one menu item "Network Config" in the device manger form.
962 if (!AddNetworkMenu
) {
963 AddNetworkMenu
= TRUE
;
964 HiiCreateGotoOpCode (
967 STRING_TOKEN (STR_FORM_NETWORK_DEVICE_LIST_TITLE
),
968 STRING_TOKEN (STR_FORM_NETWORK_DEVICE_LIST_HELP
),
969 EFI_IFR_FLAG_CALLBACK
,
970 (EFI_QUESTION_ID
) QUESTION_NETWORK_DEVICE_ID
973 } else if (mNextShowFormId
== NETWORK_DEVICE_LIST_FORM_ID
) {
975 // In network device list form, same mac address device only show one menu.
977 while (AddItemCount
> 0) {
978 HiiCreateGotoOpCode (
981 mMacDeviceList
.NodeList
[mMacDeviceList
.CurListLen
- AddItemCount
].PromptId
,
982 STRING_TOKEN (STR_NETWORK_DEVICE_HELP
),
983 EFI_IFR_FLAG_CALLBACK
,
984 mMacDeviceList
.NodeList
[mMacDeviceList
.CurListLen
- AddItemCount
].QuestionId
988 } else if (mNextShowFormId
== NETWORK_DEVICE_FORM_ID
) {
990 // In network device form, only the selected mac address device need to be show.
992 HiiCreateGotoOpCode (
997 EFI_IFR_FLAG_CALLBACK
,
998 (EFI_QUESTION_ID
) (Index
+ DEVICE_KEY_OFFSET
)
1004 // Not network device process, only need to show at device manger form.
1006 if (mNextShowFormId
== DEVICE_MANAGER_FORM_ID
) {
1007 HiiCreateGotoOpCode (
1012 EFI_IFR_FLAG_CALLBACK
,
1013 (EFI_QUESTION_ID
) (Index
+ DEVICE_KEY_OFFSET
)
1019 // Try to find more formset in this HiiHandle.
1025 Status
= gBS
->LocateHandleBuffer (
1027 &gEfiDriverHealthProtocolGuid
,
1030 &DriverHealthHandles
1034 // If there are no drivers installed driver health protocol, do not create driver health entry in UI
1036 if (NumHandles
!= 0) {
1038 // If driver health protocol is installed, create Driver Health subtitle and entry
1040 HiiCreateSubTitleOpCode (StartOpCodeHandle
, STRING_TOKEN (STR_DM_DRIVER_HEALTH_TITLE
), 0, 0, 0);
1041 HiiCreateGotoOpCode (
1043 DRIVER_HEALTH_FORM_ID
,
1044 STRING_TOKEN(STR_DRIVER_HEALTH_ALL_HEALTHY
), // Prompt text
1045 STRING_TOKEN(STR_DRIVER_HEALTH_STATUS_HELP
), // Help text
1046 EFI_IFR_FLAG_CALLBACK
,
1047 DEVICE_MANAGER_KEY_DRIVER_HEALTH
// Question ID
1051 // Check All Driver health status
1053 if (!PlaformHealthStatusCheck ()) {
1055 // At least one driver in the platform are not in healthy status
1057 HiiSetString (HiiHandle
, STRING_TOKEN (STR_DRIVER_HEALTH_ALL_HEALTHY
), GetStringById (STRING_TOKEN (STR_DRIVER_NOT_HEALTH
)), NULL
);
1060 // For the string of STR_DRIVER_HEALTH_ALL_HEALTHY previously has been updated and we need to update it while re-entry.
1062 HiiSetString (HiiHandle
, STRING_TOKEN (STR_DRIVER_HEALTH_ALL_HEALTHY
), GetStringById (STRING_TOKEN (STR_DRIVER_HEALTH_ALL_HEALTHY
)), NULL
);
1068 &gDeviceManagerFormSetGuid
,
1074 ActionRequest
= EFI_BROWSER_ACTION_REQUEST_NONE
;
1075 Status
= gFormBrowser2
->SendForm (
1079 &gDeviceManagerFormSetGuid
,
1084 if (ActionRequest
== EFI_BROWSER_ACTION_REQUEST_RESET
) {
1085 EnableResetRequired ();
1089 // We will have returned from processing a callback, selected
1090 // a target to display
1092 if ((gCallbackKey
>= DEVICE_KEY_OFFSET
)) {
1093 ActionRequest
= EFI_BROWSER_ACTION_REQUEST_NONE
;
1094 Status
= gFormBrowser2
->SendForm (
1096 &HiiHandles
[gCallbackKey
- DEVICE_KEY_OFFSET
],
1098 GuidLists
[gCallbackKey
- DEVICE_KEY_OFFSET
],
1104 if (ActionRequest
== EFI_BROWSER_ACTION_REQUEST_RESET
) {
1105 EnableResetRequired ();
1109 // Force return to Device Manager
1111 gCallbackKey
= FRONT_PAGE_KEY_DEVICE_MANAGER
;
1116 // Driver Health item chose.
1118 if (gCallbackKey
== DEVICE_MANAGER_KEY_DRIVER_HEALTH
) {
1119 CallDriverHealth ();
1121 // Force return to Device Manager
1123 gCallbackKey
= FRONT_PAGE_KEY_DEVICE_MANAGER
;
1128 // Enter from device manager and into the network device list.
1130 if (gCallbackKey
== QUESTION_NETWORK_DEVICE_ID
) {
1131 mNextShowFormId
= NETWORK_DEVICE_LIST_FORM_ID
;
1132 gCallbackKey
= FRONT_PAGE_KEY_DEVICE_MANAGER
;
1137 // In this case, go from the network device list to the specify device.
1139 if ((gCallbackKey
< MAX_KEY_SECTION_LEN
+ NETWORK_DEVICE_LIST_KEY_OFFSET
) && (gCallbackKey
>= NETWORK_DEVICE_LIST_KEY_OFFSET
)) {
1140 mNextShowFormId
= NETWORK_DEVICE_FORM_ID
;
1141 gCallbackKey
= FRONT_PAGE_KEY_DEVICE_MANAGER
;
1146 // Select the ESC, the gCallbackKey == 0.
1148 if(mNextShowFormId
- 1 < DEVICE_MANAGER_FORM_ID
) {
1149 mNextShowFormId
= DEVICE_MANAGER_FORM_ID
;
1151 mNextShowFormId
= (UINT16
) (mNextShowFormId
- 1);
1152 gCallbackKey
= FRONT_PAGE_KEY_DEVICE_MANAGER
;
1157 // Remove our packagelist from HII database.
1159 HiiRemovePackages (HiiHandle
);
1160 gDeviceManagerPrivate
.HiiHandle
= NULL
;
1162 HiiFreeOpCodeHandle (StartOpCodeHandle
);
1163 HiiFreeOpCodeHandle (EndOpCodeHandle
);
1164 FreePool (HiiHandles
);
1166 for (Index
= 0; Index
< HandleNum
; Index
++) {
1167 if (GuidLists
[Index
] != NULL
) {
1168 FreePool (GuidLists
[Index
]);
1171 FreePool (GuidLists
);
1177 This function is invoked if user selected a interactive opcode from Driver Health's
1178 Formset. The decision by user is saved to gCallbackKey for later processing.
1180 @param This Points to the EFI_HII_CONFIG_ACCESS_PROTOCOL.
1181 @param Action Specifies the type of action taken by the browser.
1182 @param QuestionId A unique value which is sent to the original exporting driver
1183 so that it can identify the type of data to expect.
1184 @param Type The type of value for the question.
1185 @param Value A pointer to the data being sent to the original exporting driver.
1186 @param ActionRequest On return, points to the action requested by the callback function.
1188 @retval EFI_SUCCESS The callback successfully handled the action.
1189 @retval EFI_INVALID_PARAMETER The setup browser call this function with invalid parameters.
1194 DriverHealthCallback (
1195 IN CONST EFI_HII_CONFIG_ACCESS_PROTOCOL
*This
,
1196 IN EFI_BROWSER_ACTION Action
,
1197 IN EFI_QUESTION_ID QuestionId
,
1199 IN EFI_IFR_TYPE_VALUE
*Value
,
1200 OUT EFI_BROWSER_ACTION_REQUEST
*ActionRequest
1203 if (Action
== EFI_BROWSER_ACTION_CHANGED
) {
1204 if ((Value
== NULL
) || (ActionRequest
== NULL
)) {
1205 return EFI_INVALID_PARAMETER
;
1208 gCallbackKey
= QuestionId
;
1211 // Request to exit SendForm(), so as to switch to selected form
1213 *ActionRequest
= EFI_BROWSER_ACTION_REQUEST_EXIT
;
1219 // All other action return unsupported.
1221 return EFI_UNSUPPORTED
;
1225 Collect and display the platform's driver health relative information, allow user to do interactive
1226 operation while the platform is unhealthy.
1228 This function display a form which divided into two parts. The one list all modules which has installed
1229 driver health protocol. The list usually contain driver name, controller name, and it's health info.
1230 While the driver name can't be retrieved, will use device path as backup. The other part of the form provide
1231 a choice to the user to repair all platform.
1240 EFI_HII_HANDLE HiiHandle
;
1241 EFI_BROWSER_ACTION_REQUEST ActionRequest
;
1242 EFI_IFR_GUID_LABEL
*StartLabel
;
1243 EFI_IFR_GUID_LABEL
*StartLabelRepair
;
1244 EFI_IFR_GUID_LABEL
*EndLabel
;
1245 EFI_IFR_GUID_LABEL
*EndLabelRepair
;
1246 VOID
*StartOpCodeHandle
;
1247 VOID
*EndOpCodeHandle
;
1248 VOID
*StartOpCodeHandleRepair
;
1249 VOID
*EndOpCodeHandleRepair
;
1251 EFI_STRING_ID Token
;
1252 EFI_STRING_ID TokenHelp
;
1254 EFI_STRING TmpString
;
1255 EFI_STRING DriverName
;
1256 EFI_STRING ControllerName
;
1257 LIST_ENTRY DriverHealthList
;
1258 DRIVER_HEALTH_INFO
*DriverHealthInfo
;
1260 EFI_DEVICE_PATH_PROTOCOL
*DriverDevicePath
;
1261 BOOLEAN RebootRequired
;
1262 BOOLEAN IsControllerNameEmpty
;
1266 DriverHealthInfo
= NULL
;
1267 DriverDevicePath
= NULL
;
1268 IsControllerNameEmpty
= FALSE
;
1269 InitializeListHead (&DriverHealthList
);
1271 HiiHandle
= gDeviceManagerPrivate
.DriverHealthHiiHandle
;
1272 if (HiiHandle
== NULL
) {
1274 // Publish Driver Health HII data.
1276 HiiHandle
= HiiAddPackages (
1277 &gDeviceManagerFormSetGuid
,
1278 gDeviceManagerPrivate
.DriverHealthHandle
,
1283 if (HiiHandle
== NULL
) {
1287 gDeviceManagerPrivate
.DriverHealthHiiHandle
= HiiHandle
;
1291 // Allocate space for creation of UpdateData Buffer
1293 StartOpCodeHandle
= HiiAllocateOpCodeHandle ();
1294 ASSERT (StartOpCodeHandle
!= NULL
);
1296 EndOpCodeHandle
= HiiAllocateOpCodeHandle ();
1297 ASSERT (EndOpCodeHandle
!= NULL
);
1299 StartOpCodeHandleRepair
= HiiAllocateOpCodeHandle ();
1300 ASSERT (StartOpCodeHandleRepair
!= NULL
);
1302 EndOpCodeHandleRepair
= HiiAllocateOpCodeHandle ();
1303 ASSERT (EndOpCodeHandleRepair
!= NULL
);
1306 // Create Hii Extend Label OpCode as the start opcode
1308 StartLabel
= (EFI_IFR_GUID_LABEL
*) HiiCreateGuidOpCode (StartOpCodeHandle
, &gEfiIfrTianoGuid
, NULL
, sizeof (EFI_IFR_GUID_LABEL
));
1309 StartLabel
->ExtendOpCode
= EFI_IFR_EXTEND_OP_LABEL
;
1310 StartLabel
->Number
= LABEL_DRIVER_HEALTH
;
1313 // Create Hii Extend Label OpCode as the start opcode
1315 StartLabelRepair
= (EFI_IFR_GUID_LABEL
*) HiiCreateGuidOpCode (StartOpCodeHandleRepair
, &gEfiIfrTianoGuid
, NULL
, sizeof (EFI_IFR_GUID_LABEL
));
1316 StartLabelRepair
->ExtendOpCode
= EFI_IFR_EXTEND_OP_LABEL
;
1317 StartLabelRepair
->Number
= LABEL_DRIVER_HEALTH_REAPIR_ALL
;
1320 // Create Hii Extend Label OpCode as the end opcode
1322 EndLabel
= (EFI_IFR_GUID_LABEL
*) HiiCreateGuidOpCode (EndOpCodeHandle
, &gEfiIfrTianoGuid
, NULL
, sizeof (EFI_IFR_GUID_LABEL
));
1323 EndLabel
->ExtendOpCode
= EFI_IFR_EXTEND_OP_LABEL
;
1324 EndLabel
->Number
= LABEL_DRIVER_HEALTH_END
;
1327 // Create Hii Extend Label OpCode as the end opcode
1329 EndLabelRepair
= (EFI_IFR_GUID_LABEL
*) HiiCreateGuidOpCode (EndOpCodeHandleRepair
, &gEfiIfrTianoGuid
, NULL
, sizeof (EFI_IFR_GUID_LABEL
));
1330 EndLabelRepair
->ExtendOpCode
= EFI_IFR_EXTEND_OP_LABEL
;
1331 EndLabelRepair
->Number
= LABEL_DRIVER_HEALTH_REAPIR_ALL_END
;
1333 HiiCreateSubTitleOpCode (StartOpCodeHandle
, STRING_TOKEN (STR_DH_STATUS_LIST
), 0, 0, 1);
1335 Status
= GetAllControllersHealthStatus (&DriverHealthList
);
1336 ASSERT (Status
!= EFI_OUT_OF_RESOURCES
);
1338 Link
= GetFirstNode (&DriverHealthList
);
1340 while (!IsNull (&DriverHealthList
, Link
)) {
1341 DriverHealthInfo
= DEVICE_MANAGER_HEALTH_INFO_FROM_LINK (Link
);
1343 Status
= DriverHealthGetDriverName (DriverHealthInfo
->DriverHandle
, &DriverName
);
1344 if (EFI_ERROR (Status
)) {
1346 // Can not get the Driver name, so use the Device path
1348 DriverDevicePath
= DevicePathFromHandle (DriverHealthInfo
->DriverHandle
);
1349 DriverName
= DevicePathToStr (DriverDevicePath
);
1351 StringSize
= StrSize (DriverName
);
1353 Status
= DriverHealthGetControllerName (
1354 DriverHealthInfo
->DriverHandle
,
1355 DriverHealthInfo
->ControllerHandle
,
1356 DriverHealthInfo
->ChildHandle
,
1360 if (!EFI_ERROR (Status
)) {
1361 IsControllerNameEmpty
= FALSE
;
1362 StringSize
+= StrLen (L
" ") * sizeof(CHAR16
);
1363 StringSize
+= StrLen (ControllerName
) * sizeof(CHAR16
);
1365 IsControllerNameEmpty
= TRUE
;
1369 // Add the message of the Module itself provided after the string item.
1371 if ((DriverHealthInfo
->MessageList
!= NULL
) && (DriverHealthInfo
->MessageList
->StringId
!= 0)) {
1372 TmpString
= HiiGetString (
1373 DriverHealthInfo
->MessageList
->HiiHandle
,
1374 DriverHealthInfo
->MessageList
->StringId
,
1377 ASSERT (TmpString
!= NULL
);
1379 StringSize
+= StrLen (L
" ") * sizeof(CHAR16
);
1380 StringSize
+= StrLen (TmpString
) * sizeof(CHAR16
);
1382 String
= (EFI_STRING
) AllocateZeroPool (StringSize
);
1383 ASSERT (String
!= NULL
);
1385 StrCpyS (String
, StringSize
/ sizeof(CHAR16
), DriverName
);
1386 if (!IsControllerNameEmpty
) {
1387 StrCatS (String
, StringSize
/ sizeof(CHAR16
), L
" ");
1388 StrCatS (String
, StringSize
/ sizeof(CHAR16
), ControllerName
);
1391 StrCatS (String
, StringSize
/ sizeof(CHAR16
), L
" ");
1392 StrCatS (String
, StringSize
/ sizeof(CHAR16
), TmpString
);
1396 // Update the string will be displayed base on the driver's health status
1398 switch(DriverHealthInfo
->HealthStatus
) {
1399 case EfiDriverHealthStatusRepairRequired
:
1400 TmpString
= GetStringById (STRING_TOKEN (STR_REPAIR_REQUIRED
));
1402 case EfiDriverHealthStatusConfigurationRequired
:
1403 TmpString
= GetStringById (STRING_TOKEN (STR_CONFIGURATION_REQUIRED
));
1405 case EfiDriverHealthStatusFailed
:
1406 TmpString
= GetStringById (STRING_TOKEN (STR_OPERATION_FAILED
));
1408 case EfiDriverHealthStatusReconnectRequired
:
1409 TmpString
= GetStringById (STRING_TOKEN (STR_RECONNECT_REQUIRED
));
1411 case EfiDriverHealthStatusRebootRequired
:
1412 TmpString
= GetStringById (STRING_TOKEN (STR_REBOOT_REQUIRED
));
1415 TmpString
= GetStringById (STRING_TOKEN (STR_DRIVER_HEALTH_HEALTHY
));
1418 ASSERT (TmpString
!= NULL
);
1420 StringSize
+= StrLen (TmpString
) * sizeof(CHAR16
);
1422 String
= (EFI_STRING
) AllocateZeroPool (StringSize
);
1423 ASSERT (String
!= NULL
);
1425 StrCpyS (String
, StringSize
/ sizeof (CHAR16
), DriverName
);
1426 if (!IsControllerNameEmpty
) {
1427 StrCatS (String
, StringSize
/ sizeof (CHAR16
), L
" ");
1428 StrCatS (String
, StringSize
/ sizeof (CHAR16
), ControllerName
);
1431 StrCatS (String
, StringSize
/ sizeof (CHAR16
), TmpString
);
1434 FreePool (TmpString
);
1436 Token
= HiiSetString (HiiHandle
, 0, String
, NULL
);
1439 TokenHelp
= HiiSetString (HiiHandle
, 0, GetStringById( STRING_TOKEN (STR_DH_REPAIR_SINGLE_HELP
)), NULL
);
1441 HiiCreateActionOpCode (
1443 (EFI_QUESTION_ID
) (Index
+ DRIVER_HEALTH_KEY_OFFSET
),
1446 EFI_IFR_FLAG_CALLBACK
,
1450 Link
= GetNextNode (&DriverHealthList
, Link
);
1454 // Add End Opcode for Subtitle
1456 HiiCreateEndOpCode (StartOpCodeHandle
);
1458 HiiCreateSubTitleOpCode (StartOpCodeHandleRepair
, STRING_TOKEN (STR_DRIVER_HEALTH_REPAIR_ALL
), 0, 0, 1);
1459 TokenHelp
= HiiSetString (HiiHandle
, 0, GetStringById( STRING_TOKEN (STR_DH_REPAIR_ALL_HELP
)), NULL
);
1461 if (PlaformHealthStatusCheck ()) {
1463 // No action need to do for the platform
1465 Token
= HiiSetString (HiiHandle
, 0, GetStringById( STRING_TOKEN (STR_DRIVER_HEALTH_ALL_HEALTHY
)), NULL
);
1466 HiiCreateActionOpCode (
1467 StartOpCodeHandleRepair
,
1471 EFI_IFR_FLAG_READ_ONLY
,
1476 // Create ActionOpCode only while the platform need to do health related operation.
1478 Token
= HiiSetString (HiiHandle
, 0, GetStringById( STRING_TOKEN (STR_DH_REPAIR_ALL_TITLE
)), NULL
);
1479 HiiCreateActionOpCode (
1480 StartOpCodeHandleRepair
,
1481 (EFI_QUESTION_ID
) DRIVER_HEALTH_REPAIR_ALL_KEY
,
1484 EFI_IFR_FLAG_CALLBACK
,
1489 HiiCreateEndOpCode (StartOpCodeHandleRepair
);
1491 Status
= HiiUpdateForm (
1493 &gDriverHealthFormSetGuid
,
1494 DRIVER_HEALTH_FORM_ID
,
1498 ASSERT (Status
!= EFI_NOT_FOUND
);
1499 ASSERT (Status
!= EFI_BUFFER_TOO_SMALL
);
1501 Status
= HiiUpdateForm (
1503 &gDriverHealthFormSetGuid
,
1504 DRIVER_HEALTH_FORM_ID
,
1505 StartOpCodeHandleRepair
,
1506 EndOpCodeHandleRepair
1508 ASSERT (Status
!= EFI_NOT_FOUND
);
1509 ASSERT (Status
!= EFI_BUFFER_TOO_SMALL
);
1511 ActionRequest
= EFI_BROWSER_ACTION_REQUEST_NONE
;
1512 Status
= gFormBrowser2
->SendForm (
1516 &gDriverHealthFormSetGuid
,
1517 DRIVER_HEALTH_FORM_ID
,
1521 if (ActionRequest
== EFI_BROWSER_ACTION_REQUEST_RESET
) {
1522 EnableResetRequired ();
1526 // We will have returned from processing a callback - user either hit ESC to exit, or selected
1527 // a target to display.
1528 // Process the diver health status states here.
1530 if (gCallbackKey
>= DRIVER_HEALTH_KEY_OFFSET
&& gCallbackKey
!= DRIVER_HEALTH_REPAIR_ALL_KEY
) {
1531 ActionRequest
= EFI_BROWSER_ACTION_REQUEST_NONE
;
1533 Link
= GetFirstNode (&DriverHealthList
);
1536 while (!IsNull (&DriverHealthList
, Link
)) {
1538 // Got the item relative node in the List
1540 if (Index
== (gCallbackKey
- DRIVER_HEALTH_KEY_OFFSET
)) {
1541 DriverHealthInfo
= DEVICE_MANAGER_HEALTH_INFO_FROM_LINK (Link
);
1543 // Process the driver's healthy status for the specify module
1545 RebootRequired
= FALSE
;
1546 ProcessSingleControllerHealth (
1547 DriverHealthInfo
->DriverHealth
,
1548 DriverHealthInfo
->ControllerHandle
,
1549 DriverHealthInfo
->ChildHandle
,
1550 DriverHealthInfo
->HealthStatus
,
1551 &(DriverHealthInfo
->MessageList
),
1552 DriverHealthInfo
->HiiHandle
,
1555 if (RebootRequired
) {
1556 gRT
->ResetSystem (EfiResetWarm
, EFI_SUCCESS
, 0, NULL
);
1561 Link
= GetNextNode (&DriverHealthList
, Link
);
1564 if (ActionRequest
== EFI_BROWSER_ACTION_REQUEST_RESET
) {
1565 EnableResetRequired ();
1569 // Force return to the form of Driver Health in Device Manager
1571 gCallbackKey
= DRIVER_HEALTH_RETURN_KEY
;
1575 // Repair the whole platform
1577 if (gCallbackKey
== DRIVER_HEALTH_REPAIR_ALL_KEY
) {
1578 ActionRequest
= EFI_BROWSER_ACTION_REQUEST_NONE
;
1580 PlatformRepairAll (&DriverHealthList
);
1582 gCallbackKey
= DRIVER_HEALTH_RETURN_KEY
;
1586 // Remove driver health packagelist from HII database.
1588 HiiRemovePackages (HiiHandle
);
1589 gDeviceManagerPrivate
.DriverHealthHiiHandle
= NULL
;
1592 // Free driver health info list
1594 while (!IsListEmpty (&DriverHealthList
)) {
1596 Link
= GetFirstNode(&DriverHealthList
);
1597 DriverHealthInfo
= DEVICE_MANAGER_HEALTH_INFO_FROM_LINK (Link
);
1598 RemoveEntryList (Link
);
1600 if (DriverHealthInfo
->MessageList
!= NULL
) {
1601 FreePool(DriverHealthInfo
->MessageList
);
1602 FreePool (DriverHealthInfo
);
1606 HiiFreeOpCodeHandle (StartOpCodeHandle
);
1607 HiiFreeOpCodeHandle (EndOpCodeHandle
);
1608 HiiFreeOpCodeHandle (StartOpCodeHandleRepair
);
1609 HiiFreeOpCodeHandle (EndOpCodeHandleRepair
);
1611 if (gCallbackKey
== DRIVER_HEALTH_RETURN_KEY
) {
1613 // Force return to Driver Health Form
1615 gCallbackKey
= DEVICE_MANAGER_KEY_DRIVER_HEALTH
;
1616 CallDriverHealth ();
1622 Check the Driver Health status of a single controller and try to process it if not healthy.
1624 This function called by CheckAllControllersHealthStatus () function in order to process a specify
1625 contoller's health state.
1627 @param DriverHealthList A Pointer to the list contain all of the platform driver health information.
1628 @param DriverHandle The handle of driver.
1629 @param ControllerHandle The class guid specifies which form set will be displayed.
1630 @param ChildHandle The handle of the child controller to retrieve the health
1631 status on. This is an optional parameter that may be NULL.
1632 @param DriverHealth A pointer to the EFI_DRIVER_HEALTH_PROTOCOL instance.
1633 @param HealthStatus The health status of the controller.
1635 @retval EFI_INVALID_PARAMETER HealthStatus or DriverHealth is NULL.
1636 @retval HealthStatus The Health status of specify controller.
1637 @retval EFI_OUT_OF_RESOURCES The list of Driver Health Protocol handles can not be retrieved.
1638 @retval EFI_NOT_FOUND No controller in the platform install Driver Health Protocol.
1639 @retval EFI_SUCCESS The Health related operation has been taken successfully.
1644 GetSingleControllerHealthStatus (
1645 IN OUT LIST_ENTRY
*DriverHealthList
,
1646 IN EFI_HANDLE DriverHandle
,
1647 IN EFI_HANDLE ControllerHandle
, OPTIONAL
1648 IN EFI_HANDLE ChildHandle
, OPTIONAL
1649 IN EFI_DRIVER_HEALTH_PROTOCOL
*DriverHealth
,
1650 IN EFI_DRIVER_HEALTH_STATUS
*HealthStatus
1654 EFI_DRIVER_HEALTH_HII_MESSAGE
*MessageList
;
1655 EFI_HII_HANDLE FormHiiHandle
;
1656 DRIVER_HEALTH_INFO
*DriverHealthInfo
;
1658 if (HealthStatus
== NULL
) {
1660 // If HealthStatus is NULL, then return EFI_INVALID_PARAMETER
1662 return EFI_INVALID_PARAMETER
;
1666 // Assume the HealthStatus is healthy
1668 *HealthStatus
= EfiDriverHealthStatusHealthy
;
1670 if (DriverHealth
== NULL
) {
1672 // If DriverHealth is NULL, then return EFI_INVALID_PARAMETER
1674 return EFI_INVALID_PARAMETER
;
1677 if (ControllerHandle
== NULL
) {
1679 // If ControllerHandle is NULL, the return the cumulative health status of the driver
1681 Status
= DriverHealth
->GetHealthStatus (DriverHealth
, NULL
, NULL
, HealthStatus
, NULL
, NULL
);
1682 if (*HealthStatus
== EfiDriverHealthStatusHealthy
) {
1684 // Add the driver health related information into the list
1686 DriverHealthInfo
= AllocateZeroPool (sizeof (DRIVER_HEALTH_INFO
));
1687 if (DriverHealthInfo
== NULL
) {
1688 return EFI_OUT_OF_RESOURCES
;
1691 DriverHealthInfo
->Signature
= DEVICE_MANAGER_DRIVER_HEALTH_INFO_SIGNATURE
;
1692 DriverHealthInfo
->DriverHandle
= DriverHandle
;
1693 DriverHealthInfo
->ControllerHandle
= NULL
;
1694 DriverHealthInfo
->ChildHandle
= NULL
;
1695 DriverHealthInfo
->HiiHandle
= NULL
;
1696 DriverHealthInfo
->DriverHealth
= DriverHealth
;
1697 DriverHealthInfo
->MessageList
= NULL
;
1698 DriverHealthInfo
->HealthStatus
= *HealthStatus
;
1700 InsertTailList (DriverHealthList
, &DriverHealthInfo
->Link
);
1706 FormHiiHandle
= NULL
;
1709 // Collect the health status with the optional HII message list
1711 Status
= DriverHealth
->GetHealthStatus (DriverHealth
, ControllerHandle
, ChildHandle
, HealthStatus
, &MessageList
, &FormHiiHandle
);
1713 if (EFI_ERROR (Status
)) {
1715 // If the health status could not be retrieved, then return immediately
1721 // Add the driver health related information into the list
1723 DriverHealthInfo
= AllocateZeroPool (sizeof (DRIVER_HEALTH_INFO
));
1724 if (DriverHealthInfo
== NULL
) {
1725 return EFI_OUT_OF_RESOURCES
;
1728 DriverHealthInfo
->Signature
= DEVICE_MANAGER_DRIVER_HEALTH_INFO_SIGNATURE
;
1729 DriverHealthInfo
->DriverHandle
= DriverHandle
;
1730 DriverHealthInfo
->ControllerHandle
= ControllerHandle
;
1731 DriverHealthInfo
->ChildHandle
= ChildHandle
;
1732 DriverHealthInfo
->HiiHandle
= FormHiiHandle
;
1733 DriverHealthInfo
->DriverHealth
= DriverHealth
;
1734 DriverHealthInfo
->MessageList
= MessageList
;
1735 DriverHealthInfo
->HealthStatus
= *HealthStatus
;
1737 InsertTailList (DriverHealthList
, &DriverHealthInfo
->Link
);
1743 Collects all the EFI Driver Health Protocols currently present in the EFI Handle Database,
1744 and queries each EFI Driver Health Protocol to determine if one or more of the controllers
1745 managed by each EFI Driver Health Protocol instance are not healthy.
1747 @param DriverHealthList A Pointer to the list contain all of the platform driver health
1750 @retval EFI_NOT_FOUND No controller in the platform install Driver Health Protocol.
1751 @retval EFI_SUCCESS All the controllers in the platform are healthy.
1752 @retval EFI_OUT_OF_RESOURCES The list of Driver Health Protocol handles can not be retrieved.
1756 GetAllControllersHealthStatus (
1757 IN OUT LIST_ENTRY
*DriverHealthList
1762 EFI_HANDLE
*DriverHealthHandles
;
1763 EFI_DRIVER_HEALTH_PROTOCOL
*DriverHealth
;
1764 EFI_DRIVER_HEALTH_STATUS HealthStatus
;
1765 UINTN DriverHealthIndex
;
1766 EFI_HANDLE
*Handles
;
1768 UINTN ControllerIndex
;
1772 // Initialize local variables
1775 DriverHealthHandles
= NULL
;
1779 HealthStatus
= EfiDriverHealthStatusHealthy
;
1781 Status
= gBS
->LocateHandleBuffer (
1783 &gEfiDriverHealthProtocolGuid
,
1786 &DriverHealthHandles
1789 if (Status
== EFI_NOT_FOUND
|| NumHandles
== 0) {
1791 // If there are no Driver Health Protocols handles, then return EFI_NOT_FOUND
1793 return EFI_NOT_FOUND
;
1796 if (EFI_ERROR (Status
) || DriverHealthHandles
== NULL
) {
1798 // If the list of Driver Health Protocol handles can not be retrieved, then
1799 // return EFI_OUT_OF_RESOURCES
1801 return EFI_OUT_OF_RESOURCES
;
1805 // Check the health status of all controllers in the platform
1806 // Start by looping through all the Driver Health Protocol handles in the handle database
1808 for (DriverHealthIndex
= 0; DriverHealthIndex
< NumHandles
; DriverHealthIndex
++) {
1810 // Skip NULL Driver Health Protocol handles
1812 if (DriverHealthHandles
[DriverHealthIndex
] == NULL
) {
1817 // Retrieve the Driver Health Protocol from DriverHandle
1819 Status
= gBS
->HandleProtocol (
1820 DriverHealthHandles
[DriverHealthIndex
],
1821 &gEfiDriverHealthProtocolGuid
,
1822 (VOID
**)&DriverHealth
1824 if (EFI_ERROR (Status
)) {
1826 // If the Driver Health Protocol can not be retrieved, then skip to the next
1827 // Driver Health Protocol handle
1833 // Check the health of all the controllers managed by a Driver Health Protocol handle
1835 Status
= GetSingleControllerHealthStatus (DriverHealthList
, DriverHealthHandles
[DriverHealthIndex
], NULL
, NULL
, DriverHealth
, &HealthStatus
);
1838 // If Status is an error code, then the health information could not be retrieved, so assume healthy
1839 // and skip to the next Driver Health Protocol handle
1841 if (EFI_ERROR (Status
)) {
1846 // If all the controllers managed by this Driver Health Protocol are healthy, then skip to the next
1847 // Driver Health Protocol handle
1849 if (HealthStatus
== EfiDriverHealthStatusHealthy
) {
1854 // See if the list of all handles in the handle database has been retrieved
1857 if (Handles
== NULL
) {
1859 // Retrieve the list of all handles from the handle database
1861 Status
= gBS
->LocateHandleBuffer (
1868 if (EFI_ERROR (Status
) || Handles
== NULL
) {
1870 // If all the handles in the handle database can not be retrieved, then
1871 // return EFI_OUT_OF_RESOURCES
1873 Status
= EFI_OUT_OF_RESOURCES
;
1878 // Loop through all the controller handles in the handle database
1880 for (ControllerIndex
= 0; ControllerIndex
< HandleCount
; ControllerIndex
++) {
1882 // Skip NULL controller handles
1884 if (Handles
[ControllerIndex
] == NULL
) {
1888 Status
= GetSingleControllerHealthStatus (DriverHealthList
, DriverHealthHandles
[DriverHealthIndex
], Handles
[ControllerIndex
], NULL
, DriverHealth
, &HealthStatus
);
1889 if (EFI_ERROR (Status
)) {
1891 // If Status is an error code, then the health information could not be retrieved, so assume healthy
1893 HealthStatus
= EfiDriverHealthStatusHealthy
;
1897 // If CheckHealthSingleController() returned an error on a terminal state, then do not check the health of child controllers
1899 if (EFI_ERROR (Status
)) {
1904 // Loop through all the child handles in the handle database
1906 for (ChildIndex
= 0; ChildIndex
< HandleCount
; ChildIndex
++) {
1908 // Skip NULL child handles
1910 if (Handles
[ChildIndex
] == NULL
) {
1914 Status
= GetSingleControllerHealthStatus (DriverHealthList
, DriverHealthHandles
[DriverHealthIndex
], Handles
[ControllerIndex
], Handles
[ChildIndex
], DriverHealth
, &HealthStatus
);
1915 if (EFI_ERROR (Status
)) {
1917 // If Status is an error code, then the health information could not be retrieved, so assume healthy
1919 HealthStatus
= EfiDriverHealthStatusHealthy
;
1923 // If CheckHealthSingleController() returned an error on a terminal state, then skip to the next child
1925 if (EFI_ERROR (Status
)) {
1932 Status
= EFI_SUCCESS
;
1935 if (Handles
!= NULL
) {
1936 gBS
->FreePool (Handles
);
1938 if (DriverHealthHandles
!= NULL
) {
1939 gBS
->FreePool (DriverHealthHandles
);
1947 Check the healthy status of the platform, this function will return immediately while found one driver
1948 in the platform are not healthy.
1950 @retval FALSE at least one driver in the platform are not healthy.
1951 @retval TRUE No controller install Driver Health Protocol,
1952 or all controllers in the platform are in healthy status.
1955 PlaformHealthStatusCheck (
1959 EFI_DRIVER_HEALTH_STATUS HealthStatus
;
1963 EFI_HANDLE
*DriverHealthHandles
;
1964 EFI_DRIVER_HEALTH_PROTOCOL
*DriverHealth
;
1968 // Initialize local variables
1970 DriverHealthHandles
= NULL
;
1971 DriverHealth
= NULL
;
1973 HealthStatus
= EfiDriverHealthStatusHealthy
;
1975 Status
= gBS
->LocateHandleBuffer (
1977 &gEfiDriverHealthProtocolGuid
,
1980 &DriverHealthHandles
1983 // There are no handles match the search for Driver Health Protocol has been installed.
1985 if (Status
== EFI_NOT_FOUND
) {
1989 // Assume all modules are healthy.
1994 // Found one or more Handles.
1996 if (!EFI_ERROR (Status
)) {
1997 for (Index
= 0; Index
< NoHandles
; Index
++) {
1998 Status
= gBS
->HandleProtocol (
1999 DriverHealthHandles
[Index
],
2000 &gEfiDriverHealthProtocolGuid
,
2001 (VOID
**) &DriverHealth
2003 if (!EFI_ERROR (Status
)) {
2004 Status
= DriverHealth
->GetHealthStatus (
2014 // Get the healthy status of the module
2016 if (!EFI_ERROR (Status
)) {
2017 if (HealthStatus
!= EfiDriverHealthStatusHealthy
) {
2019 // Return immediately one driver's status not in healthy.
2030 Processes a single controller using the EFI Driver Health Protocol associated with
2031 that controller. This algorithm continues to query the GetHealthStatus() service until
2032 one of the legal terminal states of the EFI Driver Health Protocol is reached. This may
2033 require the processing of HII Messages, HII Form, and invocation of repair operations.
2035 @param DriverHealth A pointer to the EFI_DRIVER_HEALTH_PROTOCOL instance.
2036 @param ControllerHandle The class guid specifies which form set will be displayed.
2037 @param ChildHandle The handle of the child controller to retrieve the health
2038 status on. This is an optional parameter that may be NULL.
2039 @param HealthStatus The health status of the controller.
2040 @param MessageList An array of warning or error messages associated
2041 with the controller specified by ControllerHandle and
2042 ChildHandle. This is an optional parameter that may be NULL.
2043 @param FormHiiHandle The HII handle for an HII form associated with the
2044 controller specified by ControllerHandle and ChildHandle.
2045 @param RebootRequired Indicate whether a reboot is required to repair the controller.
2048 ProcessSingleControllerHealth (
2049 IN EFI_DRIVER_HEALTH_PROTOCOL
*DriverHealth
,
2050 IN EFI_HANDLE ControllerHandle
, OPTIONAL
2051 IN EFI_HANDLE ChildHandle
, OPTIONAL
2052 IN EFI_DRIVER_HEALTH_STATUS HealthStatus
,
2053 IN EFI_DRIVER_HEALTH_HII_MESSAGE
**MessageList
, OPTIONAL
2054 IN EFI_HII_HANDLE FormHiiHandle
,
2055 IN OUT BOOLEAN
*RebootRequired
2059 EFI_DRIVER_HEALTH_STATUS LocalHealthStatus
;
2061 LocalHealthStatus
= HealthStatus
;
2063 // If the module need to be repaired or reconfiguration, will process it until
2064 // reach a terminal status. The status from EfiDriverHealthStatusRepairRequired after repair
2065 // will be in (Health, Failed, Configuration Required).
2067 while(LocalHealthStatus
== EfiDriverHealthStatusConfigurationRequired
||
2068 LocalHealthStatus
== EfiDriverHealthStatusRepairRequired
) {
2070 if (LocalHealthStatus
== EfiDriverHealthStatusRepairRequired
) {
2071 Status
= DriverHealth
->Repair (
2079 // Via a form of the driver need to do configuration provided to process of status in
2080 // EfiDriverHealthStatusConfigurationRequired. The status after configuration should be in
2081 // (Healthy, Reboot Required, Failed, Reconnect Required, Repair Required).
2083 if (LocalHealthStatus
== EfiDriverHealthStatusConfigurationRequired
) {
2084 if (FormHiiHandle
!= NULL
) {
2085 Status
= gFormBrowser2
->SendForm (
2089 &gEfiHiiDriverHealthFormsetGuid
,
2094 ASSERT( !EFI_ERROR (Status
));
2097 // Exit the loop in case no FormHiiHandle is supplied to prevent dead-loop
2103 Status
= DriverHealth
->GetHealthStatus (
2111 ASSERT_EFI_ERROR (Status
);
2113 if (*MessageList
!= NULL
) {
2114 ProcessMessages (*MessageList
);
2119 // Health status in {Healthy, Failed} may also have Messages need to process
2121 if (LocalHealthStatus
== EfiDriverHealthStatusHealthy
|| LocalHealthStatus
== EfiDriverHealthStatusFailed
) {
2122 if (*MessageList
!= NULL
) {
2123 ProcessMessages (*MessageList
);
2127 // Check for RebootRequired or ReconnectRequired
2129 if (LocalHealthStatus
== EfiDriverHealthStatusRebootRequired
) {
2130 *RebootRequired
= TRUE
;
2134 // Do reconnect if need.
2136 if (LocalHealthStatus
== EfiDriverHealthStatusReconnectRequired
) {
2137 Status
= gBS
->DisconnectController (ControllerHandle
, NULL
, NULL
);
2138 if (EFI_ERROR (Status
)) {
2140 // Disconnect failed. Need to promote reconnect to a reboot.
2142 *RebootRequired
= TRUE
;
2144 gBS
->ConnectController (ControllerHandle
, NULL
, NULL
, TRUE
);
2151 Reports the progress of a repair operation.
2153 @param[in] Value A value between 0 and Limit that identifies the current
2154 progress of the repair operation.
2156 @param[in] Limit The maximum value of Value for the current repair operation.
2157 For example, a driver that wants to specify progress in
2158 percent would use a Limit value of 100.
2160 @retval EFI_SUCCESS The progress of a repair operation is reported successfully.
2173 Print(L
"Repair Progress Undefined\n\r");
2175 Percent
= Value
* 100 / Limit
;
2176 Print(L
"Repair Progress = %3d%%\n\r", Percent
);
2182 Processes a set of messages returned by the GetHealthStatus ()
2183 service of the EFI Driver Health Protocol
2185 @param MessageList The MessageList point to messages need to processed.
2190 IN EFI_DRIVER_HEALTH_HII_MESSAGE
*MessageList
2194 EFI_STRING MessageString
;
2196 for (MessageIndex
= 0;
2197 MessageList
[MessageIndex
].HiiHandle
!= NULL
;
2200 MessageString
= HiiGetString (
2201 MessageList
[MessageIndex
].HiiHandle
,
2202 MessageList
[MessageIndex
].StringId
,
2205 if (MessageString
!= NULL
) {
2207 // User can customize the output. Just simply print out the MessageString like below.
2208 // Also can use the HiiHandle to display message on the front page.
2210 // Print(L"%s\n",MessageString);
2211 // gBS->Stall (100000);
2218 Repair the whole platform.
2220 This function is the main entry for user choose "Repair All" in the front page.
2221 It will try to do recovery job till all the driver health protocol installed modules
2222 reach a terminal state.
2224 @param DriverHealthList A Pointer to the list contain all of the platform driver health
2230 IN LIST_ENTRY
*DriverHealthList
2233 DRIVER_HEALTH_INFO
*DriverHealthInfo
;
2235 BOOLEAN RebootRequired
;
2237 ASSERT (DriverHealthList
!= NULL
);
2239 RebootRequired
= FALSE
;
2241 for ( Link
= GetFirstNode (DriverHealthList
)
2242 ; !IsNull (DriverHealthList
, Link
)
2243 ; Link
= GetNextNode (DriverHealthList
, Link
)
2245 DriverHealthInfo
= DEVICE_MANAGER_HEALTH_INFO_FROM_LINK (Link
);
2247 // Do driver health status operation by each link node
2249 ASSERT (DriverHealthInfo
!= NULL
);
2251 ProcessSingleControllerHealth (
2252 DriverHealthInfo
->DriverHealth
,
2253 DriverHealthInfo
->ControllerHandle
,
2254 DriverHealthInfo
->ChildHandle
,
2255 DriverHealthInfo
->HealthStatus
,
2256 &(DriverHealthInfo
->MessageList
),
2257 DriverHealthInfo
->HiiHandle
,
2262 if (RebootRequired
) {
2263 gRT
->ResetSystem (EfiResetWarm
, EFI_SUCCESS
, 0, NULL
);
2269 Select the best matching language according to front page policy for best user experience.
2271 This function supports both ISO 639-2 and RFC 4646 language codes, but language
2272 code types may not be mixed in a single call to this function.
2274 @param SupportedLanguages A pointer to a Null-terminated ASCII string that
2275 contains a set of language codes in the format
2276 specified by Iso639Language.
2277 @param Iso639Language If TRUE, then all language codes are assumed to be
2278 in ISO 639-2 format. If FALSE, then all language
2279 codes are assumed to be in RFC 4646 language format.
2281 @retval NULL The best matching language could not be found in SupportedLanguages.
2282 @retval NULL There are not enough resources available to return the best matching
2284 @retval Other A pointer to a Null-terminated ASCII string that is the best matching
2285 language in SupportedLanguages.
2288 DriverHealthSelectBestLanguage (
2289 IN CHAR8
*SupportedLanguages
,
2290 IN BOOLEAN Iso639Language
2293 CHAR8
*LanguageVariable
;
2294 CHAR8
*BestLanguage
;
2296 GetEfiGlobalVariable2 (Iso639Language
? L
"Lang" : L
"PlatformLang", (VOID
**)&LanguageVariable
, NULL
);
2298 BestLanguage
= GetBestLanguage(
2301 (LanguageVariable
!= NULL
) ? LanguageVariable
: "",
2302 Iso639Language
? "eng" : "en-US",
2305 if (LanguageVariable
!= NULL
) {
2306 FreePool (LanguageVariable
);
2309 return BestLanguage
;
2316 This is an internal worker function to get the Component Name (2) protocol interface
2317 and the language it supports.
2319 @param ProtocolGuid A pointer to an EFI_GUID. It points to Component Name (2) protocol GUID.
2320 @param DriverBindingHandle The handle on which the Component Name (2) protocol instance is retrieved.
2321 @param ComponentName A pointer to the Component Name (2) protocol interface.
2322 @param SupportedLanguage The best suitable language that matches the SupportedLangues interface for the
2323 located Component Name (2) instance.
2325 @retval EFI_SUCCESS The Component Name (2) protocol instance is successfully located and we find
2326 the best matching language it support.
2327 @retval EFI_UNSUPPORTED The input Language is not supported by the Component Name (2) protocol.
2328 @retval Other Some error occurs when locating Component Name (2) protocol instance or finding
2329 the supported language.
2333 GetComponentNameWorker (
2334 IN EFI_GUID
*ProtocolGuid
,
2335 IN EFI_HANDLE DriverBindingHandle
,
2336 OUT EFI_COMPONENT_NAME_PROTOCOL
**ComponentName
,
2337 OUT CHAR8
**SupportedLanguage
2343 // Locate Component Name (2) protocol on the driver binging handle.
2345 Status
= gBS
->OpenProtocol (
2346 DriverBindingHandle
,
2348 (VOID
**) ComponentName
,
2351 EFI_OPEN_PROTOCOL_GET_PROTOCOL
2353 if (EFI_ERROR (Status
)) {
2358 // Apply shell policy to select the best language.
2360 *SupportedLanguage
= DriverHealthSelectBestLanguage (
2361 (*ComponentName
)->SupportedLanguages
,
2362 (BOOLEAN
) (ProtocolGuid
== &gEfiComponentNameProtocolGuid
)
2364 if (*SupportedLanguage
== NULL
) {
2365 Status
= EFI_UNSUPPORTED
;
2373 This is an internal worker function to get driver name from Component Name (2) protocol interface.
2376 @param ProtocolGuid A pointer to an EFI_GUID. It points to Component Name (2) protocol GUID.
2377 @param DriverBindingHandle The handle on which the Component Name (2) protocol instance is retrieved.
2378 @param DriverName A pointer to the Unicode string to return. This Unicode string is the name
2379 of the driver specified by This.
2381 @retval EFI_SUCCESS The driver name is successfully retrieved from Component Name (2) protocol
2383 @retval Other The driver name cannot be retrieved from Component Name (2) protocol
2388 GetDriverNameWorker (
2389 IN EFI_GUID
*ProtocolGuid
,
2390 IN EFI_HANDLE DriverBindingHandle
,
2391 OUT CHAR16
**DriverName
2395 CHAR8
*BestLanguage
;
2396 EFI_COMPONENT_NAME_PROTOCOL
*ComponentName
;
2399 // Retrieve Component Name (2) protocol instance on the driver binding handle and
2400 // find the best language this instance supports.
2402 Status
= GetComponentNameWorker (
2404 DriverBindingHandle
,
2408 if (EFI_ERROR (Status
)) {
2413 // Get the driver name from Component Name (2) protocol instance on the driver binging handle.
2415 Status
= ComponentName
->GetDriverName (
2420 FreePool (BestLanguage
);
2427 This function gets driver name from Component Name 2 protocol interface and Component Name protocol interface
2428 in turn. It first tries UEFI 2.0 Component Name 2 protocol interface and try to get the driver name.
2429 If the attempt fails, it then gets the driver name from EFI 1.1 Component Name protocol for backward
2430 compatibility support.
2432 @param DriverBindingHandle The handle on which the Component Name (2) protocol instance is retrieved.
2433 @param DriverName A pointer to the Unicode string to return. This Unicode string is the name
2434 of the driver specified by This.
2436 @retval EFI_SUCCESS The driver name is successfully retrieved from Component Name (2) protocol
2438 @retval Other The driver name cannot be retrieved from Component Name (2) protocol
2443 DriverHealthGetDriverName (
2444 IN EFI_HANDLE DriverBindingHandle
,
2445 OUT CHAR16
**DriverName
2451 // Get driver name from UEFI 2.0 Component Name 2 protocol interface.
2453 Status
= GetDriverNameWorker (&gEfiComponentName2ProtocolGuid
, DriverBindingHandle
, DriverName
);
2454 if (EFI_ERROR (Status
)) {
2456 // If it fails to get the driver name from Component Name protocol interface, we should fall back on
2457 // EFI 1.1 Component Name protocol interface.
2459 Status
= GetDriverNameWorker (&gEfiComponentNameProtocolGuid
, DriverBindingHandle
, DriverName
);
2468 This function gets controller name from Component Name 2 protocol interface and Component Name protocol interface
2469 in turn. It first tries UEFI 2.0 Component Name 2 protocol interface and try to get the controller name.
2470 If the attempt fails, it then gets the controller name from EFI 1.1 Component Name protocol for backward
2471 compatibility support.
2473 @param ProtocolGuid A pointer to an EFI_GUID. It points to Component Name (2) protocol GUID.
2474 @param DriverBindingHandle The handle on which the Component Name (2) protocol instance is retrieved.
2475 @param ControllerHandle The handle of a controller that the driver specified by This is managing.
2476 This handle specifies the controller whose name is to be returned.
2477 @param ChildHandle The handle of the child controller to retrieve the name of. This is an
2478 optional parameter that may be NULL. It will be NULL for device drivers.
2479 It will also be NULL for bus drivers that attempt to retrieve the name
2480 of the bus controller. It will not be NULL for a bus driver that attempts
2481 to retrieve the name of a child controller.
2482 @param ControllerName A pointer to the Unicode string to return. This Unicode string
2483 is the name of the controller specified by ControllerHandle and ChildHandle.
2485 @retval EFI_SUCCESS The controller name is successfully retrieved from Component Name (2) protocol
2487 @retval Other The controller name cannot be retrieved from Component Name (2) protocol.
2491 GetControllerNameWorker (
2492 IN EFI_GUID
*ProtocolGuid
,
2493 IN EFI_HANDLE DriverBindingHandle
,
2494 IN EFI_HANDLE ControllerHandle
,
2495 IN EFI_HANDLE ChildHandle
,
2496 OUT CHAR16
**ControllerName
2500 CHAR8
*BestLanguage
;
2501 EFI_COMPONENT_NAME_PROTOCOL
*ComponentName
;
2504 // Retrieve Component Name (2) protocol instance on the driver binding handle and
2505 // find the best language this instance supports.
2507 Status
= GetComponentNameWorker (
2509 DriverBindingHandle
,
2513 if (EFI_ERROR (Status
)) {
2518 // Get the controller name from Component Name (2) protocol instance on the driver binging handle.
2520 Status
= ComponentName
->GetControllerName (
2527 FreePool (BestLanguage
);
2534 This function gets controller name from Component Name 2 protocol interface and Component Name protocol interface
2535 in turn. It first tries UEFI 2.0 Component Name 2 protocol interface and try to get the controller name.
2536 If the attempt fails, it then gets the controller name from EFI 1.1 Component Name protocol for backward
2537 compatibility support.
2539 @param DriverBindingHandle The handle on which the Component Name (2) protocol instance is retrieved.
2540 @param ControllerHandle The handle of a controller that the driver specified by This is managing.
2541 This handle specifies the controller whose name is to be returned.
2542 @param ChildHandle The handle of the child controller to retrieve the name of. This is an
2543 optional parameter that may be NULL. It will be NULL for device drivers.
2544 It will also be NULL for bus drivers that attempt to retrieve the name
2545 of the bus controller. It will not be NULL for a bus driver that attempts
2546 to retrieve the name of a child controller.
2547 @param ControllerName A pointer to the Unicode string to return. This Unicode string
2548 is the name of the controller specified by ControllerHandle and ChildHandle.
2550 @retval EFI_SUCCESS The controller name is successfully retrieved from Component Name (2) protocol
2552 @retval Other The controller name cannot be retrieved from Component Name (2) protocol.
2556 DriverHealthGetControllerName (
2557 IN EFI_HANDLE DriverBindingHandle
,
2558 IN EFI_HANDLE ControllerHandle
,
2559 IN EFI_HANDLE ChildHandle
,
2560 OUT CHAR16
**ControllerName
2566 // Get controller name from UEFI 2.0 Component Name 2 protocol interface.
2568 Status
= GetControllerNameWorker (
2569 &gEfiComponentName2ProtocolGuid
,
2570 DriverBindingHandle
,
2575 if (EFI_ERROR (Status
)) {
2577 // If it fails to get the controller name from Component Name protocol interface, we should fall back on
2578 // EFI 1.1 Component Name protocol interface.
2580 Status
= GetControllerNameWorker (
2581 &gEfiComponentNameProtocolGuid
,
2582 DriverBindingHandle
,