2 The platform device manager reference implementation
4 Copyright (c) 2004 - 2013, 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
= AllocateZeroPool (BufferLen
);
378 if (String
== NULL
) {
383 StrCpy(String
, L
"MAC:");
387 // Convert the MAC address into a unicode string.
389 HwAddress
= &MacAddressNode
->MacAddress
.Addr
[0];
390 for (Index
= 0; Index
< HwAddressSize
; Index
++) {
391 String
+= UnicodeValueToString (String
, PREFIX_ZERO
| RADIX_HEX
, *(HwAddress
++), 2);
392 if (Index
< HwAddressSize
- 1) {
398 // If VLAN is configured, it will need extra 5 characters like "\0005".
399 // Plus one unicode character for the null-terminator.
401 Node
= (EFI_DEVICE_PATH_PROTOCOL
*)MacAddressNode
;
402 while (!IsDevicePathEnd (Node
)) {
403 if (Node
->Type
== MESSAGING_DEVICE_PATH
&& Node
->SubType
== MSG_VLAN_DP
) {
404 VlanId
= ((VLAN_DEVICE_PATH
*) Node
)->VlanId
;
406 Node
= NextDevicePathNode (Node
);
411 String
+= UnicodeValueToString (String
, PREFIX_ZERO
| RADIX_HEX
, VlanId
, 4);
415 // Null terminate the Unicode string
423 Save question id and prompt id to the mac device list.
424 If the same mac address has saved yet, no need to add more.
426 @param MacAddrString Mac address string.
428 @retval EFI_SUCCESS Add the item is successful.
429 @return Other values if failed to Add the item.
432 AddIdToMacDeviceList (
433 IN EFI_STRING MacAddrString
436 MENU_INFO_ITEM
*TempDeviceList
;
438 EFI_STRING StoredString
;
439 EFI_STRING_ID PromptId
;
440 EFI_HII_HANDLE HiiHandle
;
442 HiiHandle
= gDeviceManagerPrivate
.HiiHandle
;
443 TempDeviceList
= NULL
;
445 for (Index
= 0; Index
< mMacDeviceList
.CurListLen
; Index
++) {
446 StoredString
= HiiGetString (HiiHandle
, mMacDeviceList
.NodeList
[Index
].PromptId
, NULL
);
447 if (StoredString
== NULL
) {
452 // Already has save the same mac address to the list.
454 if (StrCmp (MacAddrString
, StoredString
) == 0) {
459 PromptId
= HiiSetString(HiiHandle
, 0, MacAddrString
, NULL
);
461 // If not in the list, save it.
463 if (mMacDeviceList
.MaxListLen
> mMacDeviceList
.CurListLen
+ 1) {
464 mMacDeviceList
.NodeList
[mMacDeviceList
.CurListLen
].PromptId
= PromptId
;
465 mMacDeviceList
.NodeList
[mMacDeviceList
.CurListLen
].QuestionId
= (EFI_QUESTION_ID
) (mMacDeviceList
.CurListLen
+ NETWORK_DEVICE_LIST_KEY_OFFSET
);
467 mMacDeviceList
.MaxListLen
+= MAX_MAC_ADDRESS_NODE_LIST_LEN
;
468 if (mMacDeviceList
.CurListLen
!= 0) {
469 TempDeviceList
= (MENU_INFO_ITEM
*)AllocateCopyPool (sizeof (MENU_INFO_ITEM
) * mMacDeviceList
.MaxListLen
, (VOID
*)mMacDeviceList
.NodeList
);
471 TempDeviceList
= (MENU_INFO_ITEM
*)AllocatePool (sizeof (MENU_INFO_ITEM
) * mMacDeviceList
.MaxListLen
);
474 if (TempDeviceList
== NULL
) {
477 TempDeviceList
[mMacDeviceList
.CurListLen
].PromptId
= PromptId
;
478 TempDeviceList
[mMacDeviceList
.CurListLen
].QuestionId
= (EFI_QUESTION_ID
) (mMacDeviceList
.CurListLen
+ NETWORK_DEVICE_LIST_KEY_OFFSET
);
480 if (mMacDeviceList
.CurListLen
> 0) {
481 FreePool(mMacDeviceList
.NodeList
);
484 mMacDeviceList
.NodeList
= TempDeviceList
;
486 mMacDeviceList
.CurListLen
++;
492 Check the devcie path, try to find whether it has mac address path.
494 In this function, first need to check whether this path has mac address path.
495 second, when the mac address device path has find, also need to deicide whether
496 need to add this mac address relate info to the menu.
498 @param *Node Input device which need to be check.
499 @param *NeedAddItem Whether need to add the menu in the network device list.
501 @retval TRUE Has mac address device path.
502 @retval FALSE NOT Has mac address device path.
506 IsMacAddressDevicePath (
508 OUT BOOLEAN
*NeedAddItem
511 EFI_DEVICE_PATH_PROTOCOL
*DevicePath
;
515 ASSERT (Node
!= NULL
);
516 *NeedAddItem
= FALSE
;
520 DevicePath
= (EFI_DEVICE_PATH_PROTOCOL
*) Node
;
523 // find the partition device path node
525 while (!IsDevicePathEnd (DevicePath
)) {
526 if ((DevicePathType (DevicePath
) == MESSAGING_DEVICE_PATH
) &&
527 (DevicePathSubType (DevicePath
) == MSG_MAC_ADDR_DP
)) {
530 if (DEVICE_MANAGER_FORM_ID
== mNextShowFormId
) {
535 if (!GetMacAddressString((MAC_ADDR_DEVICE_PATH
*)DevicePath
, &Buffer
)) {
539 if (NETWORK_DEVICE_FORM_ID
== mNextShowFormId
) {
540 if (StrCmp (Buffer
, mSelectedMacAddrString
) == 0) {
546 if (NETWORK_DEVICE_LIST_FORM_ID
== mNextShowFormId
) {
548 // Same handle may has two network child handle, so the questionid
549 // has the offset of SAME_HANDLE_KEY_OFFSET.
551 if (AddIdToMacDeviceList (Buffer
)) {
557 DevicePath
= NextDevicePathNode (DevicePath
);
560 if (Buffer
!= NULL
) {
568 Check to see if the device path is for the network device.
570 @param Handle The HII handle which include the mac address device path.
571 @param ItemCount The new add Mac address item count.
573 @retval TRUE Need to add new item in the menu.
574 @return FALSE Do not need to add the menu about the network.
578 IsNeedAddNetworkMenu (
579 IN EFI_HII_HANDLE Handle
,
586 EFI_HANDLE DriverHandle
;
587 EFI_HANDLE ControllerHandle
;
588 EFI_DEVICE_PATH_PROTOCOL
*DevicePath
;
589 EFI_DEVICE_PATH_PROTOCOL
*TmpDevicePath
;
590 EFI_DEVICE_PATH_PROTOCOL
*ChildDevicePath
;
591 EFI_OPEN_PROTOCOL_INFORMATION_ENTRY
*OpenInfoBuffer
;
595 OpenInfoBuffer
= NULL
;
596 if ((Handle
== NULL
) || (ItemCount
== NULL
)) {
601 Status
= gHiiDatabase
->GetPackageListHandle (gHiiDatabase
, Handle
, &DriverHandle
);
602 if (EFI_ERROR (Status
)) {
606 // Get the device path by the got Driver handle .
608 Status
= gBS
->HandleProtocol (DriverHandle
, &gEfiDevicePathProtocolGuid
, (VOID
**) &DevicePath
);
609 if (EFI_ERROR (Status
)) {
612 TmpDevicePath
= DevicePath
;
615 // Check whether this device path include mac address device path.
616 // If this path has mac address path, get the value whether need
617 // add this info to the menu and return.
618 // Else check more about the child handle devcie path.
620 if (IsMacAddressDevicePath(TmpDevicePath
, &IsNeedAdd
)) {
621 if ((NETWORK_DEVICE_LIST_FORM_ID
== mNextShowFormId
) && IsNeedAdd
) {
628 // Search whether this path is the controller path, not he child handle path.
629 // And the child handle has the network devcie connected.
631 TmpDevicePath
= DevicePath
;
632 Status
= gBS
->LocateDevicePath(&gEfiDevicePathProtocolGuid
, &TmpDevicePath
, &ControllerHandle
);
633 if (EFI_ERROR (Status
)) {
637 if (!IsDevicePathEnd (TmpDevicePath
)) {
642 // Retrieve the list of agents that are consuming the specific protocol
643 // on ControllerHandle.
644 // The buffer point by OpenInfoBuffer need be free at this function.
646 Status
= gBS
->OpenProtocolInformation (
648 &gEfiPciIoProtocolGuid
,
652 if (EFI_ERROR (Status
)) {
657 // Inspect if ChildHandle is one of the agents.
659 Status
= EFI_UNSUPPORTED
;
660 for (Index
= 0; Index
< EntryCount
; Index
++) {
662 // Query all the children created by the controller handle's driver
664 if ((OpenInfoBuffer
[Index
].Attributes
& EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER
) != 0) {
665 Status
= gBS
->OpenProtocol (
666 OpenInfoBuffer
[Index
].ControllerHandle
,
667 &gEfiDevicePathProtocolGuid
,
668 (VOID
**) &ChildDevicePath
,
671 EFI_OPEN_PROTOCOL_GET_PROTOCOL
673 if (EFI_ERROR (Status
)) {
678 // Check whether this device path include mac address device path.
680 if (!IsMacAddressDevicePath(ChildDevicePath
, &IsNeedAdd
)) {
682 // If this path not has mac address path, check the other.
687 // If need to update the NETWORK_DEVICE_LIST_FORM, try to get more.
689 if ((NETWORK_DEVICE_LIST_FORM_ID
== mNextShowFormId
)) {
696 // If need to update other form, return whether need to add to the menu.
705 if (OpenInfoBuffer
!= NULL
) {
706 FreePool (OpenInfoBuffer
);
712 Get HiiHandle total number.
714 @param HiiHandles The input HiiHandle array.
716 @retval the Hiihandle count.
721 IN EFI_HII_HANDLE
*HiiHandles
726 for (Index
= 0; HiiHandles
[Index
] != NULL
; Index
++) {
733 Insert the new HiiHandle + FormsetGuid at the NewPair[InsertOffset].
735 @param HiiHandles The input HiiHandle array.
736 @param GuidLists The input form set guid lists.
737 @param ArrayCount The input array count, new array will be arraycount + 1 size.
738 @param Offset The current used HiiHandle's Offset.
739 @param FormSetGuid The new found formset guid.
744 IN OUT EFI_HII_HANDLE
**HiiHandles
,
745 IN OUT EFI_GUID
***GuidLists
,
748 IN EFI_GUID
*FormSetGuid
751 EFI_HII_HANDLE
*NewHiiHandles
;
752 EFI_GUID
**NewGuidLists
;
755 // +2 means include the new HiiHandle and the last empty NULL pointer.
757 NewHiiHandles
= AllocateZeroPool ((ArrayCount
+ 2) * sizeof (EFI_HII_HANDLE
));
758 ASSERT (NewHiiHandles
!= NULL
);
760 CopyMem (NewHiiHandles
, *HiiHandles
, Offset
* sizeof (EFI_HII_HANDLE
));
761 NewHiiHandles
[Offset
] = NewHiiHandles
[Offset
- 1];
762 CopyMem (NewHiiHandles
+ Offset
+ 1, *HiiHandles
+ Offset
, (ArrayCount
- Offset
) * sizeof (EFI_HII_HANDLE
));
764 NewGuidLists
= AllocateZeroPool ((ArrayCount
+ 2) * sizeof (EFI_GUID
*));
765 ASSERT (NewGuidLists
!= NULL
);
767 CopyMem (NewGuidLists
, *GuidLists
, Offset
* sizeof (EFI_GUID
*));
768 NewGuidLists
[Offset
] = FormSetGuid
;
770 FreePool (*HiiHandles
);
771 *HiiHandles
= NewHiiHandles
;
772 FreePool (*GuidLists
);
773 *GuidLists
= NewGuidLists
;
777 Call the browser and display the device manager to allow user
778 to configure the platform.
780 This function create the dynamic content for device manager. It includes
781 section header for all class of devices, one-of opcode to set VBIOS.
783 @retval EFI_SUCCESS Operation is successful.
784 @return Other values if failed to clean up the dynamic content from HII
797 EFI_STRING_ID TokenHelp
;
798 EFI_HII_HANDLE
*HiiHandles
;
799 EFI_HII_HANDLE HiiHandle
;
800 EFI_STRING_ID FormSetTitle
;
801 EFI_STRING_ID FormSetHelp
;
802 EFI_BROWSER_ACTION_REQUEST ActionRequest
;
803 VOID
*StartOpCodeHandle
;
804 VOID
*EndOpCodeHandle
;
805 EFI_IFR_GUID_LABEL
*StartLabel
;
806 EFI_IFR_GUID_LABEL
*EndLabel
;
808 EFI_HANDLE
*DriverHealthHandles
;
809 BOOLEAN AddNetworkMenu
;
812 EFI_STRING NewStringTitle
;
813 EFI_GUID
**GuidLists
;
816 EFI_GUID
*FormSetGuid
;
820 Status
= EFI_SUCCESS
;
823 DriverHealthHandles
= NULL
;
824 AddNetworkMenu
= FALSE
;
830 // Connect all prior to entering the platform setup menu.
832 if (!gConnectAllHappened
) {
833 BdsLibConnectAllDriversToAllControllers ();
834 gConnectAllHappened
= TRUE
;
837 HiiHandle
= gDeviceManagerPrivate
.HiiHandle
;
838 if (HiiHandle
== NULL
) {
840 // Publish our HII data.
842 HiiHandle
= HiiAddPackages (
843 &gDeviceManagerFormSetGuid
,
844 gDeviceManagerPrivate
.DriverHandle
,
849 if (HiiHandle
== NULL
) {
850 return EFI_OUT_OF_RESOURCES
;
853 gDeviceManagerPrivate
.HiiHandle
= HiiHandle
;
857 // If need show the Network device list form, clear the old save list first.
859 if ((mNextShowFormId
== NETWORK_DEVICE_LIST_FORM_ID
) && (mMacDeviceList
.CurListLen
> 0)) {
860 mMacDeviceList
.CurListLen
= 0;
864 // Update the network device form titile.
866 if (mNextShowFormId
== NETWORK_DEVICE_FORM_ID
) {
867 String
= HiiGetString (HiiHandle
, STRING_TOKEN (STR_FORM_NETWORK_DEVICE_TITLE
), NULL
);
868 NewStringLen
= StrLen(mSelectedMacAddrString
) * 2;
869 NewStringLen
+= (StrLen(String
) + 2) * 2;
870 NewStringTitle
= AllocatePool (NewStringLen
);
871 UnicodeSPrint (NewStringTitle
, NewStringLen
, L
"%s %s", String
, mSelectedMacAddrString
);
872 HiiSetString (HiiHandle
, STRING_TOKEN (STR_FORM_NETWORK_DEVICE_TITLE
), NewStringTitle
, NULL
);
874 FreePool (NewStringTitle
);
878 // Allocate space for creation of UpdateData Buffer
880 StartOpCodeHandle
= HiiAllocateOpCodeHandle ();
881 ASSERT (StartOpCodeHandle
!= NULL
);
883 EndOpCodeHandle
= HiiAllocateOpCodeHandle ();
884 ASSERT (EndOpCodeHandle
!= NULL
);
887 // Create Hii Extend Label OpCode as the start opcode
889 StartLabel
= (EFI_IFR_GUID_LABEL
*) HiiCreateGuidOpCode (StartOpCodeHandle
, &gEfiIfrTianoGuid
, NULL
, sizeof (EFI_IFR_GUID_LABEL
));
890 StartLabel
->ExtendOpCode
= EFI_IFR_EXTEND_OP_LABEL
;
892 // According to the next show Form id(mNextShowFormId) to decide which form need to update.
894 StartLabel
->Number
= (UINT16
) (LABEL_FORM_ID_OFFSET
+ mNextShowFormId
);
897 // Create Hii Extend Label OpCode as the end opcode
899 EndLabel
= (EFI_IFR_GUID_LABEL
*) HiiCreateGuidOpCode (EndOpCodeHandle
, &gEfiIfrTianoGuid
, NULL
, sizeof (EFI_IFR_GUID_LABEL
));
900 EndLabel
->ExtendOpCode
= EFI_IFR_EXTEND_OP_LABEL
;
901 EndLabel
->Number
= LABEL_END
;
904 // Get all the Hii handles
906 HiiHandles
= HiiGetHiiHandles (NULL
);
907 ASSERT (HiiHandles
!= NULL
);
909 HandleNum
= GetHiiHandleCount (HiiHandles
);
910 GuidLists
= AllocateZeroPool ((HandleNum
+ 1) * sizeof (EFI_GUID
*));
911 ASSERT (GuidLists
!= NULL
);
914 // Search for formset of each class type
916 for (Index
= 0; HiiHandles
[Index
] != NULL
; Index
++) {
918 // The QuestionId in the form which will call the driver form has this asssumption.
919 // QuestionId = Handle Index + NETWORK_DEVICE_LIST_KEY_OFFSET;
920 // Different QuestionId at least has the section of NETWORK_DEVICE_LIST_KEY_OFFSET.
922 ASSERT(Index
< MAX_KEY_SECTION_LEN
);
924 if (!ExtractDisplayedHiiFormFromHiiHandle (HiiHandles
[Index
], &gEfiHiiPlatformSetupFormsetGuid
, SkipCount
, &FormSetTitle
, &FormSetHelp
, &FormSetGuid
)) {
930 // One HiiHandle has more than one formset can be shown,
931 // Insert a new pair of HiiHandle + Guid to the HiiHandles and GuidLists list.
934 AdjustArrayData (&HiiHandles
, &GuidLists
, HandleNum
, Index
+ 1, FormSetGuid
);
939 String
= HiiGetString (HiiHandles
[Index
], FormSetTitle
, NULL
);
940 if (String
== NULL
) {
941 String
= HiiGetString (HiiHandle
, STR_MISSING_STRING
, NULL
);
942 ASSERT (String
!= NULL
);
944 Token
= HiiSetString (HiiHandle
, 0, String
, NULL
);
947 String
= HiiGetString (HiiHandles
[Index
], FormSetHelp
, NULL
);
948 if (String
== NULL
) {
949 String
= HiiGetString (HiiHandle
, STR_MISSING_STRING
, NULL
);
950 ASSERT (String
!= NULL
);
952 TokenHelp
= HiiSetString (HiiHandle
, 0, String
, NULL
);
956 // Network device process
958 if (IsNeedAddNetworkMenu (HiiHandles
[Index
], &AddItemCount
)) {
959 if (mNextShowFormId
== DEVICE_MANAGER_FORM_ID
) {
961 // Only show one menu item "Network Config" in the device manger form.
963 if (!AddNetworkMenu
) {
964 AddNetworkMenu
= TRUE
;
965 HiiCreateGotoOpCode (
968 STRING_TOKEN (STR_FORM_NETWORK_DEVICE_LIST_TITLE
),
969 STRING_TOKEN (STR_FORM_NETWORK_DEVICE_LIST_HELP
),
970 EFI_IFR_FLAG_CALLBACK
,
971 (EFI_QUESTION_ID
) QUESTION_NETWORK_DEVICE_ID
974 } else if (mNextShowFormId
== NETWORK_DEVICE_LIST_FORM_ID
) {
976 // In network device list form, same mac address device only show one menu.
978 while (AddItemCount
> 0) {
979 HiiCreateGotoOpCode (
982 mMacDeviceList
.NodeList
[mMacDeviceList
.CurListLen
- AddItemCount
].PromptId
,
983 STRING_TOKEN (STR_NETWORK_DEVICE_HELP
),
984 EFI_IFR_FLAG_CALLBACK
,
985 mMacDeviceList
.NodeList
[mMacDeviceList
.CurListLen
- AddItemCount
].QuestionId
989 } else if (mNextShowFormId
== NETWORK_DEVICE_FORM_ID
) {
991 // In network device form, only the selected mac address device need to be show.
993 HiiCreateGotoOpCode (
998 EFI_IFR_FLAG_CALLBACK
,
999 (EFI_QUESTION_ID
) (Index
+ DEVICE_KEY_OFFSET
)
1005 // Not network device process, only need to show at device manger form.
1007 if (mNextShowFormId
== DEVICE_MANAGER_FORM_ID
) {
1008 HiiCreateGotoOpCode (
1013 EFI_IFR_FLAG_CALLBACK
,
1014 (EFI_QUESTION_ID
) (Index
+ DEVICE_KEY_OFFSET
)
1020 // Try to find more formset in this HiiHandle.
1026 Status
= gBS
->LocateHandleBuffer (
1028 &gEfiDriverHealthProtocolGuid
,
1031 &DriverHealthHandles
1035 // If there are no drivers installed driver health protocol, do not create driver health entry in UI
1037 if (NumHandles
!= 0) {
1039 // If driver health protocol is installed, create Driver Health subtitle and entry
1041 HiiCreateSubTitleOpCode (StartOpCodeHandle
, STRING_TOKEN (STR_DM_DRIVER_HEALTH_TITLE
), 0, 0, 0);
1042 HiiCreateGotoOpCode (
1044 DRIVER_HEALTH_FORM_ID
,
1045 STRING_TOKEN(STR_DRIVER_HEALTH_ALL_HEALTHY
), // Prompt text
1046 STRING_TOKEN(STR_DRIVER_HEALTH_STATUS_HELP
), // Help text
1047 EFI_IFR_FLAG_CALLBACK
,
1048 DEVICE_MANAGER_KEY_DRIVER_HEALTH
// Question ID
1052 // Check All Driver health status
1054 if (!PlaformHealthStatusCheck ()) {
1056 // At least one driver in the platform are not in healthy status
1058 HiiSetString (HiiHandle
, STRING_TOKEN (STR_DRIVER_HEALTH_ALL_HEALTHY
), GetStringById (STRING_TOKEN (STR_DRIVER_NOT_HEALTH
)), NULL
);
1061 // For the string of STR_DRIVER_HEALTH_ALL_HEALTHY previously has been updated and we need to update it while re-entry.
1063 HiiSetString (HiiHandle
, STRING_TOKEN (STR_DRIVER_HEALTH_ALL_HEALTHY
), GetStringById (STRING_TOKEN (STR_DRIVER_HEALTH_ALL_HEALTHY
)), NULL
);
1069 &gDeviceManagerFormSetGuid
,
1075 ActionRequest
= EFI_BROWSER_ACTION_REQUEST_NONE
;
1076 Status
= gFormBrowser2
->SendForm (
1080 &gDeviceManagerFormSetGuid
,
1085 if (ActionRequest
== EFI_BROWSER_ACTION_REQUEST_RESET
) {
1086 EnableResetRequired ();
1090 // We will have returned from processing a callback, selected
1091 // a target to display
1093 if ((gCallbackKey
>= DEVICE_KEY_OFFSET
)) {
1094 ActionRequest
= EFI_BROWSER_ACTION_REQUEST_NONE
;
1095 Status
= gFormBrowser2
->SendForm (
1097 &HiiHandles
[gCallbackKey
- DEVICE_KEY_OFFSET
],
1099 GuidLists
[gCallbackKey
- DEVICE_KEY_OFFSET
],
1105 if (ActionRequest
== EFI_BROWSER_ACTION_REQUEST_RESET
) {
1106 EnableResetRequired ();
1110 // Force return to Device Manager
1112 gCallbackKey
= FRONT_PAGE_KEY_DEVICE_MANAGER
;
1117 // Driver Health item chose.
1119 if (gCallbackKey
== DEVICE_MANAGER_KEY_DRIVER_HEALTH
) {
1120 CallDriverHealth ();
1122 // Force return to Device Manager
1124 gCallbackKey
= FRONT_PAGE_KEY_DEVICE_MANAGER
;
1129 // Enter from device manager and into the network device list.
1131 if (gCallbackKey
== QUESTION_NETWORK_DEVICE_ID
) {
1132 mNextShowFormId
= NETWORK_DEVICE_LIST_FORM_ID
;
1133 gCallbackKey
= FRONT_PAGE_KEY_DEVICE_MANAGER
;
1138 // In this case, go from the network device list to the specify device.
1140 if ((gCallbackKey
< MAX_KEY_SECTION_LEN
+ NETWORK_DEVICE_LIST_KEY_OFFSET
) && (gCallbackKey
>= NETWORK_DEVICE_LIST_KEY_OFFSET
)) {
1141 mNextShowFormId
= NETWORK_DEVICE_FORM_ID
;
1142 gCallbackKey
= FRONT_PAGE_KEY_DEVICE_MANAGER
;
1147 // Select the ESC, the gCallbackKey == 0.
1149 if(mNextShowFormId
- 1 < DEVICE_MANAGER_FORM_ID
) {
1150 mNextShowFormId
= DEVICE_MANAGER_FORM_ID
;
1152 mNextShowFormId
= (UINT16
) (mNextShowFormId
- 1);
1153 gCallbackKey
= FRONT_PAGE_KEY_DEVICE_MANAGER
;
1158 // Remove our packagelist from HII database.
1160 HiiRemovePackages (HiiHandle
);
1161 gDeviceManagerPrivate
.HiiHandle
= NULL
;
1163 HiiFreeOpCodeHandle (StartOpCodeHandle
);
1164 HiiFreeOpCodeHandle (EndOpCodeHandle
);
1165 FreePool (HiiHandles
);
1167 for (Index
= 0; Index
< HandleNum
; Index
++) {
1168 if (GuidLists
[Index
] != NULL
) {
1169 FreePool (GuidLists
[Index
]);
1172 FreePool (GuidLists
);
1178 This function is invoked if user selected a interactive opcode from Driver Health's
1179 Formset. The decision by user is saved to gCallbackKey for later processing.
1181 @param This Points to the EFI_HII_CONFIG_ACCESS_PROTOCOL.
1182 @param Action Specifies the type of action taken by the browser.
1183 @param QuestionId A unique value which is sent to the original exporting driver
1184 so that it can identify the type of data to expect.
1185 @param Type The type of value for the question.
1186 @param Value A pointer to the data being sent to the original exporting driver.
1187 @param ActionRequest On return, points to the action requested by the callback function.
1189 @retval EFI_SUCCESS The callback successfully handled the action.
1190 @retval EFI_INVALID_PARAMETER The setup browser call this function with invalid parameters.
1195 DriverHealthCallback (
1196 IN CONST EFI_HII_CONFIG_ACCESS_PROTOCOL
*This
,
1197 IN EFI_BROWSER_ACTION Action
,
1198 IN EFI_QUESTION_ID QuestionId
,
1200 IN EFI_IFR_TYPE_VALUE
*Value
,
1201 OUT EFI_BROWSER_ACTION_REQUEST
*ActionRequest
1204 if (Action
== EFI_BROWSER_ACTION_CHANGED
) {
1205 if ((Value
== NULL
) || (ActionRequest
== NULL
)) {
1206 return EFI_INVALID_PARAMETER
;
1209 gCallbackKey
= QuestionId
;
1212 // Request to exit SendForm(), so as to switch to selected form
1214 *ActionRequest
= EFI_BROWSER_ACTION_REQUEST_EXIT
;
1220 // All other action return unsupported.
1222 return EFI_UNSUPPORTED
;
1226 Collect and display the platform's driver health relative information, allow user to do interactive
1227 operation while the platform is unhealthy.
1229 This function display a form which divided into two parts. The one list all modules which has installed
1230 driver health protocol. The list usually contain driver name, controller name, and it's health info.
1231 While the driver name can't be retrieved, will use device path as backup. The other part of the form provide
1232 a choice to the user to repair all platform.
1241 EFI_HII_HANDLE HiiHandle
;
1242 EFI_BROWSER_ACTION_REQUEST ActionRequest
;
1243 EFI_IFR_GUID_LABEL
*StartLabel
;
1244 EFI_IFR_GUID_LABEL
*StartLabelRepair
;
1245 EFI_IFR_GUID_LABEL
*EndLabel
;
1246 EFI_IFR_GUID_LABEL
*EndLabelRepair
;
1247 VOID
*StartOpCodeHandle
;
1248 VOID
*EndOpCodeHandle
;
1249 VOID
*StartOpCodeHandleRepair
;
1250 VOID
*EndOpCodeHandleRepair
;
1252 EFI_STRING_ID Token
;
1253 EFI_STRING_ID TokenHelp
;
1255 EFI_STRING TmpString
;
1256 EFI_STRING DriverName
;
1257 EFI_STRING ControllerName
;
1258 LIST_ENTRY DriverHealthList
;
1259 DRIVER_HEALTH_INFO
*DriverHealthInfo
;
1261 EFI_DEVICE_PATH_PROTOCOL
*DriverDevicePath
;
1262 BOOLEAN RebootRequired
;
1265 DriverHealthInfo
= NULL
;
1266 DriverDevicePath
= NULL
;
1267 InitializeListHead (&DriverHealthList
);
1269 HiiHandle
= gDeviceManagerPrivate
.DriverHealthHiiHandle
;
1270 if (HiiHandle
== NULL
) {
1272 // Publish Driver Health HII data.
1274 HiiHandle
= HiiAddPackages (
1275 &gDeviceManagerFormSetGuid
,
1276 gDeviceManagerPrivate
.DriverHealthHandle
,
1281 if (HiiHandle
== NULL
) {
1285 gDeviceManagerPrivate
.DriverHealthHiiHandle
= HiiHandle
;
1289 // Allocate space for creation of UpdateData Buffer
1291 StartOpCodeHandle
= HiiAllocateOpCodeHandle ();
1292 ASSERT (StartOpCodeHandle
!= NULL
);
1294 EndOpCodeHandle
= HiiAllocateOpCodeHandle ();
1295 ASSERT (EndOpCodeHandle
!= NULL
);
1297 StartOpCodeHandleRepair
= HiiAllocateOpCodeHandle ();
1298 ASSERT (StartOpCodeHandleRepair
!= NULL
);
1300 EndOpCodeHandleRepair
= HiiAllocateOpCodeHandle ();
1301 ASSERT (EndOpCodeHandleRepair
!= NULL
);
1304 // Create Hii Extend Label OpCode as the start opcode
1306 StartLabel
= (EFI_IFR_GUID_LABEL
*) HiiCreateGuidOpCode (StartOpCodeHandle
, &gEfiIfrTianoGuid
, NULL
, sizeof (EFI_IFR_GUID_LABEL
));
1307 StartLabel
->ExtendOpCode
= EFI_IFR_EXTEND_OP_LABEL
;
1308 StartLabel
->Number
= LABEL_DRIVER_HEALTH
;
1311 // Create Hii Extend Label OpCode as the start opcode
1313 StartLabelRepair
= (EFI_IFR_GUID_LABEL
*) HiiCreateGuidOpCode (StartOpCodeHandleRepair
, &gEfiIfrTianoGuid
, NULL
, sizeof (EFI_IFR_GUID_LABEL
));
1314 StartLabelRepair
->ExtendOpCode
= EFI_IFR_EXTEND_OP_LABEL
;
1315 StartLabelRepair
->Number
= LABEL_DRIVER_HEALTH_REAPIR_ALL
;
1318 // Create Hii Extend Label OpCode as the end opcode
1320 EndLabel
= (EFI_IFR_GUID_LABEL
*) HiiCreateGuidOpCode (EndOpCodeHandle
, &gEfiIfrTianoGuid
, NULL
, sizeof (EFI_IFR_GUID_LABEL
));
1321 EndLabel
->ExtendOpCode
= EFI_IFR_EXTEND_OP_LABEL
;
1322 EndLabel
->Number
= LABEL_DRIVER_HEALTH_END
;
1325 // Create Hii Extend Label OpCode as the end opcode
1327 EndLabelRepair
= (EFI_IFR_GUID_LABEL
*) HiiCreateGuidOpCode (EndOpCodeHandleRepair
, &gEfiIfrTianoGuid
, NULL
, sizeof (EFI_IFR_GUID_LABEL
));
1328 EndLabelRepair
->ExtendOpCode
= EFI_IFR_EXTEND_OP_LABEL
;
1329 EndLabelRepair
->Number
= LABEL_DRIVER_HEALTH_REAPIR_ALL_END
;
1331 HiiCreateSubTitleOpCode (StartOpCodeHandle
, STRING_TOKEN (STR_DH_STATUS_LIST
), 0, 0, 1);
1333 Status
= GetAllControllersHealthStatus (&DriverHealthList
);
1334 ASSERT (Status
!= EFI_OUT_OF_RESOURCES
);
1336 Link
= GetFirstNode (&DriverHealthList
);
1338 while (!IsNull (&DriverHealthList
, Link
)) {
1339 DriverHealthInfo
= DEVICE_MANAGER_HEALTH_INFO_FROM_LINK (Link
);
1342 // Assume no line strings is longer than 512 bytes.
1344 String
= (EFI_STRING
) AllocateZeroPool (0x200);
1345 ASSERT (String
!= NULL
);
1347 Status
= DriverHealthGetDriverName (DriverHealthInfo
->DriverHandle
, &DriverName
);
1348 if (EFI_ERROR (Status
)) {
1350 // Can not get the Driver name, so use the Device path
1352 DriverDevicePath
= DevicePathFromHandle (DriverHealthInfo
->DriverHandle
);
1353 DriverName
= DevicePathToStr (DriverDevicePath
);
1356 // Add the Driver name & Controller name into FormSetTitle string
1358 StrnCat (String
, DriverName
, StrLen (DriverName
));
1361 Status
= DriverHealthGetControllerName (
1362 DriverHealthInfo
->DriverHandle
,
1363 DriverHealthInfo
->ControllerHandle
,
1364 DriverHealthInfo
->ChildHandle
,
1368 if (!EFI_ERROR (Status
)) {
1370 // Can not get the Controller name, just let it empty.
1372 StrnCat (String
, L
" ", StrLen (L
" "));
1373 StrnCat (String
, ControllerName
, StrLen (ControllerName
));
1377 // Add the message of the Module itself provided after the string item.
1379 if ((DriverHealthInfo
->MessageList
!= NULL
) && (DriverHealthInfo
->MessageList
->StringId
!= 0)) {
1380 StrnCat (String
, L
" ", StrLen (L
" "));
1381 TmpString
= HiiGetString (
1382 DriverHealthInfo
->MessageList
->HiiHandle
,
1383 DriverHealthInfo
->MessageList
->StringId
,
1388 // Update the string will be displayed base on the driver's health status
1390 switch(DriverHealthInfo
->HealthStatus
) {
1391 case EfiDriverHealthStatusRepairRequired
:
1392 TmpString
= GetStringById (STRING_TOKEN (STR_REPAIR_REQUIRED
));
1394 case EfiDriverHealthStatusConfigurationRequired
:
1395 TmpString
= GetStringById (STRING_TOKEN (STR_CONFIGURATION_REQUIRED
));
1397 case EfiDriverHealthStatusFailed
:
1398 TmpString
= GetStringById (STRING_TOKEN (STR_OPERATION_FAILED
));
1400 case EfiDriverHealthStatusReconnectRequired
:
1401 TmpString
= GetStringById (STRING_TOKEN (STR_RECONNECT_REQUIRED
));
1403 case EfiDriverHealthStatusRebootRequired
:
1404 TmpString
= GetStringById (STRING_TOKEN (STR_REBOOT_REQUIRED
));
1407 TmpString
= GetStringById (STRING_TOKEN (STR_DRIVER_HEALTH_HEALTHY
));
1412 ASSERT (TmpString
!= NULL
);
1413 StrCat (String
, TmpString
);
1414 FreePool (TmpString
);
1416 Token
= HiiSetString (HiiHandle
, 0, String
, NULL
);
1419 TokenHelp
= HiiSetString (HiiHandle
, 0, GetStringById( STRING_TOKEN (STR_DH_REPAIR_SINGLE_HELP
)), NULL
);
1421 HiiCreateActionOpCode (
1423 (EFI_QUESTION_ID
) (Index
+ DRIVER_HEALTH_KEY_OFFSET
),
1426 EFI_IFR_FLAG_CALLBACK
,
1430 Link
= GetNextNode (&DriverHealthList
, Link
);
1434 // Add End Opcode for Subtitle
1436 HiiCreateEndOpCode (StartOpCodeHandle
);
1438 HiiCreateSubTitleOpCode (StartOpCodeHandleRepair
, STRING_TOKEN (STR_DRIVER_HEALTH_REPAIR_ALL
), 0, 0, 1);
1439 TokenHelp
= HiiSetString (HiiHandle
, 0, GetStringById( STRING_TOKEN (STR_DH_REPAIR_ALL_HELP
)), NULL
);
1441 if (PlaformHealthStatusCheck ()) {
1443 // No action need to do for the platform
1445 Token
= HiiSetString (HiiHandle
, 0, GetStringById( STRING_TOKEN (STR_DRIVER_HEALTH_ALL_HEALTHY
)), NULL
);
1446 HiiCreateActionOpCode (
1447 StartOpCodeHandleRepair
,
1451 EFI_IFR_FLAG_READ_ONLY
,
1456 // Create ActionOpCode only while the platform need to do health related operation.
1458 Token
= HiiSetString (HiiHandle
, 0, GetStringById( STRING_TOKEN (STR_DH_REPAIR_ALL_TITLE
)), NULL
);
1459 HiiCreateActionOpCode (
1460 StartOpCodeHandleRepair
,
1461 (EFI_QUESTION_ID
) DRIVER_HEALTH_REPAIR_ALL_KEY
,
1464 EFI_IFR_FLAG_CALLBACK
,
1469 HiiCreateEndOpCode (StartOpCodeHandleRepair
);
1471 Status
= HiiUpdateForm (
1473 &gDriverHealthFormSetGuid
,
1474 DRIVER_HEALTH_FORM_ID
,
1478 ASSERT (Status
!= EFI_NOT_FOUND
);
1479 ASSERT (Status
!= EFI_BUFFER_TOO_SMALL
);
1481 Status
= HiiUpdateForm (
1483 &gDriverHealthFormSetGuid
,
1484 DRIVER_HEALTH_FORM_ID
,
1485 StartOpCodeHandleRepair
,
1486 EndOpCodeHandleRepair
1488 ASSERT (Status
!= EFI_NOT_FOUND
);
1489 ASSERT (Status
!= EFI_BUFFER_TOO_SMALL
);
1491 ActionRequest
= EFI_BROWSER_ACTION_REQUEST_NONE
;
1492 Status
= gFormBrowser2
->SendForm (
1496 &gDriverHealthFormSetGuid
,
1497 DRIVER_HEALTH_FORM_ID
,
1501 if (ActionRequest
== EFI_BROWSER_ACTION_REQUEST_RESET
) {
1502 EnableResetRequired ();
1506 // We will have returned from processing a callback - user either hit ESC to exit, or selected
1507 // a target to display.
1508 // Process the diver health status states here.
1510 if (gCallbackKey
>= DRIVER_HEALTH_KEY_OFFSET
&& gCallbackKey
!= DRIVER_HEALTH_REPAIR_ALL_KEY
) {
1511 ActionRequest
= EFI_BROWSER_ACTION_REQUEST_NONE
;
1513 Link
= GetFirstNode (&DriverHealthList
);
1516 while (!IsNull (&DriverHealthList
, Link
)) {
1518 // Got the item relative node in the List
1520 if (Index
== (gCallbackKey
- DRIVER_HEALTH_KEY_OFFSET
)) {
1521 DriverHealthInfo
= DEVICE_MANAGER_HEALTH_INFO_FROM_LINK (Link
);
1523 // Process the driver's healthy status for the specify module
1525 RebootRequired
= FALSE
;
1526 ProcessSingleControllerHealth (
1527 DriverHealthInfo
->DriverHealth
,
1528 DriverHealthInfo
->ControllerHandle
,
1529 DriverHealthInfo
->ChildHandle
,
1530 DriverHealthInfo
->HealthStatus
,
1531 &(DriverHealthInfo
->MessageList
),
1532 DriverHealthInfo
->HiiHandle
,
1535 if (RebootRequired
) {
1536 gRT
->ResetSystem (EfiResetWarm
, EFI_SUCCESS
, 0, NULL
);
1541 Link
= GetNextNode (&DriverHealthList
, Link
);
1544 if (ActionRequest
== EFI_BROWSER_ACTION_REQUEST_RESET
) {
1545 EnableResetRequired ();
1549 // Force return to the form of Driver Health in Device Manager
1551 gCallbackKey
= DRIVER_HEALTH_RETURN_KEY
;
1555 // Repair the whole platform
1557 if (gCallbackKey
== DRIVER_HEALTH_REPAIR_ALL_KEY
) {
1558 ActionRequest
= EFI_BROWSER_ACTION_REQUEST_NONE
;
1560 PlatformRepairAll (&DriverHealthList
);
1562 gCallbackKey
= DRIVER_HEALTH_RETURN_KEY
;
1566 // Remove driver health packagelist from HII database.
1568 HiiRemovePackages (HiiHandle
);
1569 gDeviceManagerPrivate
.DriverHealthHiiHandle
= NULL
;
1572 // Free driver health info list
1574 while (!IsListEmpty (&DriverHealthList
)) {
1576 Link
= GetFirstNode(&DriverHealthList
);
1577 DriverHealthInfo
= DEVICE_MANAGER_HEALTH_INFO_FROM_LINK (Link
);
1578 RemoveEntryList (Link
);
1580 if (DriverHealthInfo
->MessageList
!= NULL
) {
1581 FreePool(DriverHealthInfo
->MessageList
);
1582 FreePool (DriverHealthInfo
);
1586 HiiFreeOpCodeHandle (StartOpCodeHandle
);
1587 HiiFreeOpCodeHandle (EndOpCodeHandle
);
1588 HiiFreeOpCodeHandle (StartOpCodeHandleRepair
);
1589 HiiFreeOpCodeHandle (EndOpCodeHandleRepair
);
1591 if (gCallbackKey
== DRIVER_HEALTH_RETURN_KEY
) {
1593 // Force return to Driver Health Form
1595 gCallbackKey
= DEVICE_MANAGER_KEY_DRIVER_HEALTH
;
1596 CallDriverHealth ();
1602 Check the Driver Health status of a single controller and try to process it if not healthy.
1604 This function called by CheckAllControllersHealthStatus () function in order to process a specify
1605 contoller's health state.
1607 @param DriverHealthList A Pointer to the list contain all of the platform driver health information.
1608 @param DriverHandle The handle of driver.
1609 @param ControllerHandle The class guid specifies which form set will be displayed.
1610 @param ChildHandle The handle of the child controller to retrieve the health
1611 status on. This is an optional parameter that may be NULL.
1612 @param DriverHealth A pointer to the EFI_DRIVER_HEALTH_PROTOCOL instance.
1613 @param HealthStatus The health status of the controller.
1615 @retval EFI_INVALID_PARAMETER HealthStatus or DriverHealth is NULL.
1616 @retval HealthStatus The Health status of specify controller.
1617 @retval EFI_OUT_OF_RESOURCES The list of Driver Health Protocol handles can not be retrieved.
1618 @retval EFI_NOT_FOUND No controller in the platform install Driver Health Protocol.
1619 @retval EFI_SUCCESS The Health related operation has been taken successfully.
1624 GetSingleControllerHealthStatus (
1625 IN OUT LIST_ENTRY
*DriverHealthList
,
1626 IN EFI_HANDLE DriverHandle
,
1627 IN EFI_HANDLE ControllerHandle
, OPTIONAL
1628 IN EFI_HANDLE ChildHandle
, OPTIONAL
1629 IN EFI_DRIVER_HEALTH_PROTOCOL
*DriverHealth
,
1630 IN EFI_DRIVER_HEALTH_STATUS
*HealthStatus
1634 EFI_DRIVER_HEALTH_HII_MESSAGE
*MessageList
;
1635 EFI_HII_HANDLE FormHiiHandle
;
1636 DRIVER_HEALTH_INFO
*DriverHealthInfo
;
1638 if (HealthStatus
== NULL
) {
1640 // If HealthStatus is NULL, then return EFI_INVALID_PARAMETER
1642 return EFI_INVALID_PARAMETER
;
1646 // Assume the HealthStatus is healthy
1648 *HealthStatus
= EfiDriverHealthStatusHealthy
;
1650 if (DriverHealth
== NULL
) {
1652 // If DriverHealth is NULL, then return EFI_INVALID_PARAMETER
1654 return EFI_INVALID_PARAMETER
;
1657 if (ControllerHandle
== NULL
) {
1659 // If ControllerHandle is NULL, the return the cumulative health status of the driver
1661 Status
= DriverHealth
->GetHealthStatus (DriverHealth
, NULL
, NULL
, HealthStatus
, NULL
, NULL
);
1662 if (*HealthStatus
== EfiDriverHealthStatusHealthy
) {
1664 // Add the driver health related information into the list
1666 DriverHealthInfo
= AllocateZeroPool (sizeof (DRIVER_HEALTH_INFO
));
1667 if (DriverHealthInfo
== NULL
) {
1668 return EFI_OUT_OF_RESOURCES
;
1671 DriverHealthInfo
->Signature
= DEVICE_MANAGER_DRIVER_HEALTH_INFO_SIGNATURE
;
1672 DriverHealthInfo
->DriverHandle
= DriverHandle
;
1673 DriverHealthInfo
->ControllerHandle
= NULL
;
1674 DriverHealthInfo
->ChildHandle
= NULL
;
1675 DriverHealthInfo
->HiiHandle
= NULL
;
1676 DriverHealthInfo
->DriverHealth
= DriverHealth
;
1677 DriverHealthInfo
->MessageList
= NULL
;
1678 DriverHealthInfo
->HealthStatus
= *HealthStatus
;
1680 InsertTailList (DriverHealthList
, &DriverHealthInfo
->Link
);
1686 FormHiiHandle
= NULL
;
1689 // Collect the health status with the optional HII message list
1691 Status
= DriverHealth
->GetHealthStatus (DriverHealth
, ControllerHandle
, ChildHandle
, HealthStatus
, &MessageList
, &FormHiiHandle
);
1693 if (EFI_ERROR (Status
)) {
1695 // If the health status could not be retrieved, then return immediately
1701 // Add the driver health related information into the list
1703 DriverHealthInfo
= AllocateZeroPool (sizeof (DRIVER_HEALTH_INFO
));
1704 if (DriverHealthInfo
== NULL
) {
1705 return EFI_OUT_OF_RESOURCES
;
1708 DriverHealthInfo
->Signature
= DEVICE_MANAGER_DRIVER_HEALTH_INFO_SIGNATURE
;
1709 DriverHealthInfo
->DriverHandle
= DriverHandle
;
1710 DriverHealthInfo
->ControllerHandle
= ControllerHandle
;
1711 DriverHealthInfo
->ChildHandle
= ChildHandle
;
1712 DriverHealthInfo
->HiiHandle
= FormHiiHandle
;
1713 DriverHealthInfo
->DriverHealth
= DriverHealth
;
1714 DriverHealthInfo
->MessageList
= MessageList
;
1715 DriverHealthInfo
->HealthStatus
= *HealthStatus
;
1717 InsertTailList (DriverHealthList
, &DriverHealthInfo
->Link
);
1723 Collects all the EFI Driver Health Protocols currently present in the EFI Handle Database,
1724 and queries each EFI Driver Health Protocol to determine if one or more of the controllers
1725 managed by each EFI Driver Health Protocol instance are not healthy.
1727 @param DriverHealthList A Pointer to the list contain all of the platform driver health
1730 @retval EFI_NOT_FOUND No controller in the platform install Driver Health Protocol.
1731 @retval EFI_SUCCESS All the controllers in the platform are healthy.
1732 @retval EFI_OUT_OF_RESOURCES The list of Driver Health Protocol handles can not be retrieved.
1736 GetAllControllersHealthStatus (
1737 IN OUT LIST_ENTRY
*DriverHealthList
1742 EFI_HANDLE
*DriverHealthHandles
;
1743 EFI_DRIVER_HEALTH_PROTOCOL
*DriverHealth
;
1744 EFI_DRIVER_HEALTH_STATUS HealthStatus
;
1745 UINTN DriverHealthIndex
;
1746 EFI_HANDLE
*Handles
;
1748 UINTN ControllerIndex
;
1752 // Initialize local variables
1755 DriverHealthHandles
= NULL
;
1759 HealthStatus
= EfiDriverHealthStatusHealthy
;
1761 Status
= gBS
->LocateHandleBuffer (
1763 &gEfiDriverHealthProtocolGuid
,
1766 &DriverHealthHandles
1769 if (Status
== EFI_NOT_FOUND
|| NumHandles
== 0) {
1771 // If there are no Driver Health Protocols handles, then return EFI_NOT_FOUND
1773 return EFI_NOT_FOUND
;
1776 if (EFI_ERROR (Status
) || DriverHealthHandles
== NULL
) {
1778 // If the list of Driver Health Protocol handles can not be retrieved, then
1779 // return EFI_OUT_OF_RESOURCES
1781 return EFI_OUT_OF_RESOURCES
;
1785 // Check the health status of all controllers in the platform
1786 // Start by looping through all the Driver Health Protocol handles in the handle database
1788 for (DriverHealthIndex
= 0; DriverHealthIndex
< NumHandles
; DriverHealthIndex
++) {
1790 // Skip NULL Driver Health Protocol handles
1792 if (DriverHealthHandles
[DriverHealthIndex
] == NULL
) {
1797 // Retrieve the Driver Health Protocol from DriverHandle
1799 Status
= gBS
->HandleProtocol (
1800 DriverHealthHandles
[DriverHealthIndex
],
1801 &gEfiDriverHealthProtocolGuid
,
1802 (VOID
**)&DriverHealth
1804 if (EFI_ERROR (Status
)) {
1806 // If the Driver Health Protocol can not be retrieved, then skip to the next
1807 // Driver Health Protocol handle
1813 // Check the health of all the controllers managed by a Driver Health Protocol handle
1815 Status
= GetSingleControllerHealthStatus (DriverHealthList
, DriverHealthHandles
[DriverHealthIndex
], NULL
, NULL
, DriverHealth
, &HealthStatus
);
1818 // If Status is an error code, then the health information could not be retrieved, so assume healthy
1819 // and skip to the next Driver Health Protocol handle
1821 if (EFI_ERROR (Status
)) {
1826 // If all the controllers managed by this Driver Health Protocol are healthy, then skip to the next
1827 // Driver Health Protocol handle
1829 if (HealthStatus
== EfiDriverHealthStatusHealthy
) {
1834 // See if the list of all handles in the handle database has been retrieved
1837 if (Handles
== NULL
) {
1839 // Retrieve the list of all handles from the handle database
1841 Status
= gBS
->LocateHandleBuffer (
1848 if (EFI_ERROR (Status
) || Handles
== NULL
) {
1850 // If all the handles in the handle database can not be retrieved, then
1851 // return EFI_OUT_OF_RESOURCES
1853 Status
= EFI_OUT_OF_RESOURCES
;
1858 // Loop through all the controller handles in the handle database
1860 for (ControllerIndex
= 0; ControllerIndex
< HandleCount
; ControllerIndex
++) {
1862 // Skip NULL controller handles
1864 if (Handles
[ControllerIndex
] == NULL
) {
1868 Status
= GetSingleControllerHealthStatus (DriverHealthList
, DriverHealthHandles
[DriverHealthIndex
], Handles
[ControllerIndex
], NULL
, DriverHealth
, &HealthStatus
);
1869 if (EFI_ERROR (Status
)) {
1871 // If Status is an error code, then the health information could not be retrieved, so assume healthy
1873 HealthStatus
= EfiDriverHealthStatusHealthy
;
1877 // If CheckHealthSingleController() returned an error on a terminal state, then do not check the health of child controllers
1879 if (EFI_ERROR (Status
)) {
1884 // Loop through all the child handles in the handle database
1886 for (ChildIndex
= 0; ChildIndex
< HandleCount
; ChildIndex
++) {
1888 // Skip NULL child handles
1890 if (Handles
[ChildIndex
] == NULL
) {
1894 Status
= GetSingleControllerHealthStatus (DriverHealthList
, DriverHealthHandles
[DriverHealthIndex
], Handles
[ControllerIndex
], Handles
[ChildIndex
], DriverHealth
, &HealthStatus
);
1895 if (EFI_ERROR (Status
)) {
1897 // If Status is an error code, then the health information could not be retrieved, so assume healthy
1899 HealthStatus
= EfiDriverHealthStatusHealthy
;
1903 // If CheckHealthSingleController() returned an error on a terminal state, then skip to the next child
1905 if (EFI_ERROR (Status
)) {
1912 Status
= EFI_SUCCESS
;
1915 if (Handles
!= NULL
) {
1916 gBS
->FreePool (Handles
);
1918 if (DriverHealthHandles
!= NULL
) {
1919 gBS
->FreePool (DriverHealthHandles
);
1927 Check the healthy status of the platform, this function will return immediately while found one driver
1928 in the platform are not healthy.
1930 @retval FALSE at least one driver in the platform are not healthy.
1931 @retval TRUE No controller install Driver Health Protocol,
1932 or all controllers in the platform are in healthy status.
1935 PlaformHealthStatusCheck (
1939 EFI_DRIVER_HEALTH_STATUS HealthStatus
;
1943 EFI_HANDLE
*DriverHealthHandles
;
1944 EFI_DRIVER_HEALTH_PROTOCOL
*DriverHealth
;
1948 // Initialize local variables
1950 DriverHealthHandles
= NULL
;
1951 DriverHealth
= NULL
;
1953 HealthStatus
= EfiDriverHealthStatusHealthy
;
1955 Status
= gBS
->LocateHandleBuffer (
1957 &gEfiDriverHealthProtocolGuid
,
1960 &DriverHealthHandles
1963 // There are no handles match the search for Driver Health Protocol has been installed.
1965 if (Status
== EFI_NOT_FOUND
) {
1969 // Assume all modules are healthy.
1974 // Found one or more Handles.
1976 if (!EFI_ERROR (Status
)) {
1977 for (Index
= 0; Index
< NoHandles
; Index
++) {
1978 Status
= gBS
->HandleProtocol (
1979 DriverHealthHandles
[Index
],
1980 &gEfiDriverHealthProtocolGuid
,
1981 (VOID
**) &DriverHealth
1983 if (!EFI_ERROR (Status
)) {
1984 Status
= DriverHealth
->GetHealthStatus (
1994 // Get the healthy status of the module
1996 if (!EFI_ERROR (Status
)) {
1997 if (HealthStatus
!= EfiDriverHealthStatusHealthy
) {
1999 // Return immediately one driver's status not in healthy.
2010 Processes a single controller using the EFI Driver Health Protocol associated with
2011 that controller. This algorithm continues to query the GetHealthStatus() service until
2012 one of the legal terminal states of the EFI Driver Health Protocol is reached. This may
2013 require the processing of HII Messages, HII Form, and invocation of repair operations.
2015 @param DriverHealth A pointer to the EFI_DRIVER_HEALTH_PROTOCOL instance.
2016 @param ControllerHandle The class guid specifies which form set will be displayed.
2017 @param ChildHandle The handle of the child controller to retrieve the health
2018 status on. This is an optional parameter that may be NULL.
2019 @param HealthStatus The health status of the controller.
2020 @param MessageList An array of warning or error messages associated
2021 with the controller specified by ControllerHandle and
2022 ChildHandle. This is an optional parameter that may be NULL.
2023 @param FormHiiHandle The HII handle for an HII form associated with the
2024 controller specified by ControllerHandle and ChildHandle.
2025 @param RebootRequired Indicate whether a reboot is required to repair the controller.
2028 ProcessSingleControllerHealth (
2029 IN EFI_DRIVER_HEALTH_PROTOCOL
*DriverHealth
,
2030 IN EFI_HANDLE ControllerHandle
, OPTIONAL
2031 IN EFI_HANDLE ChildHandle
, OPTIONAL
2032 IN EFI_DRIVER_HEALTH_STATUS HealthStatus
,
2033 IN EFI_DRIVER_HEALTH_HII_MESSAGE
**MessageList
, OPTIONAL
2034 IN EFI_HII_HANDLE FormHiiHandle
,
2035 IN OUT BOOLEAN
*RebootRequired
2039 EFI_DRIVER_HEALTH_STATUS LocalHealthStatus
;
2041 LocalHealthStatus
= HealthStatus
;
2043 // If the module need to be repaired or reconfiguration, will process it until
2044 // reach a terminal status. The status from EfiDriverHealthStatusRepairRequired after repair
2045 // will be in (Health, Failed, Configuration Required).
2047 while(LocalHealthStatus
== EfiDriverHealthStatusConfigurationRequired
||
2048 LocalHealthStatus
== EfiDriverHealthStatusRepairRequired
) {
2050 if (LocalHealthStatus
== EfiDriverHealthStatusRepairRequired
) {
2051 Status
= DriverHealth
->Repair (
2059 // Via a form of the driver need to do configuration provided to process of status in
2060 // EfiDriverHealthStatusConfigurationRequired. The status after configuration should be in
2061 // (Healthy, Reboot Required, Failed, Reconnect Required, Repair Required).
2063 if (LocalHealthStatus
== EfiDriverHealthStatusConfigurationRequired
) {
2064 if (FormHiiHandle
!= NULL
) {
2065 Status
= gFormBrowser2
->SendForm (
2069 &gEfiHiiDriverHealthFormsetGuid
,
2074 ASSERT( !EFI_ERROR (Status
));
2077 // Exit the loop in case no FormHiiHandle is supplied to prevent dead-loop
2083 Status
= DriverHealth
->GetHealthStatus (
2091 ASSERT_EFI_ERROR (Status
);
2093 if (*MessageList
!= NULL
) {
2094 ProcessMessages (*MessageList
);
2099 // Health status in {Healthy, Failed} may also have Messages need to process
2101 if (LocalHealthStatus
== EfiDriverHealthStatusHealthy
|| LocalHealthStatus
== EfiDriverHealthStatusFailed
) {
2102 if (*MessageList
!= NULL
) {
2103 ProcessMessages (*MessageList
);
2107 // Check for RebootRequired or ReconnectRequired
2109 if (LocalHealthStatus
== EfiDriverHealthStatusRebootRequired
) {
2110 *RebootRequired
= TRUE
;
2114 // Do reconnect if need.
2116 if (LocalHealthStatus
== EfiDriverHealthStatusReconnectRequired
) {
2117 Status
= gBS
->DisconnectController (ControllerHandle
, NULL
, NULL
);
2118 if (EFI_ERROR (Status
)) {
2120 // Disconnect failed. Need to promote reconnect to a reboot.
2122 *RebootRequired
= TRUE
;
2124 gBS
->ConnectController (ControllerHandle
, NULL
, NULL
, TRUE
);
2131 Reports the progress of a repair operation.
2133 @param[in] Value A value between 0 and Limit that identifies the current
2134 progress of the repair operation.
2136 @param[in] Limit The maximum value of Value for the current repair operation.
2137 For example, a driver that wants to specify progress in
2138 percent would use a Limit value of 100.
2140 @retval EFI_SUCCESS The progress of a repair operation is reported successfully.
2153 Print(L
"Repair Progress Undefined\n\r");
2155 Percent
= Value
* 100 / Limit
;
2156 Print(L
"Repair Progress = %3d%%\n\r", Percent
);
2162 Processes a set of messages returned by the GetHealthStatus ()
2163 service of the EFI Driver Health Protocol
2165 @param MessageList The MessageList point to messages need to processed.
2170 IN EFI_DRIVER_HEALTH_HII_MESSAGE
*MessageList
2174 EFI_STRING MessageString
;
2176 for (MessageIndex
= 0;
2177 MessageList
[MessageIndex
].HiiHandle
!= NULL
;
2180 MessageString
= HiiGetString (
2181 MessageList
[MessageIndex
].HiiHandle
,
2182 MessageList
[MessageIndex
].StringId
,
2185 if (MessageString
!= NULL
) {
2187 // User can customize the output. Just simply print out the MessageString like below.
2188 // Also can use the HiiHandle to display message on the front page.
2190 // Print(L"%s\n",MessageString);
2191 // gBS->Stall (100000);
2198 Repair the whole platform.
2200 This function is the main entry for user choose "Repair All" in the front page.
2201 It will try to do recovery job till all the driver health protocol installed modules
2202 reach a terminal state.
2204 @param DriverHealthList A Pointer to the list contain all of the platform driver health
2210 IN LIST_ENTRY
*DriverHealthList
2213 DRIVER_HEALTH_INFO
*DriverHealthInfo
;
2215 BOOLEAN RebootRequired
;
2217 ASSERT (DriverHealthList
!= NULL
);
2219 RebootRequired
= FALSE
;
2221 for ( Link
= GetFirstNode (DriverHealthList
)
2222 ; !IsNull (DriverHealthList
, Link
)
2223 ; Link
= GetNextNode (DriverHealthList
, Link
)
2225 DriverHealthInfo
= DEVICE_MANAGER_HEALTH_INFO_FROM_LINK (Link
);
2227 // Do driver health status operation by each link node
2229 ASSERT (DriverHealthInfo
!= NULL
);
2231 ProcessSingleControllerHealth (
2232 DriverHealthInfo
->DriverHealth
,
2233 DriverHealthInfo
->ControllerHandle
,
2234 DriverHealthInfo
->ChildHandle
,
2235 DriverHealthInfo
->HealthStatus
,
2236 &(DriverHealthInfo
->MessageList
),
2237 DriverHealthInfo
->HiiHandle
,
2242 if (RebootRequired
) {
2243 gRT
->ResetSystem (EfiResetWarm
, EFI_SUCCESS
, 0, NULL
);
2249 Select the best matching language according to front page policy for best user experience.
2251 This function supports both ISO 639-2 and RFC 4646 language codes, but language
2252 code types may not be mixed in a single call to this function.
2254 @param SupportedLanguages A pointer to a Null-terminated ASCII string that
2255 contains a set of language codes in the format
2256 specified by Iso639Language.
2257 @param Iso639Language If TRUE, then all language codes are assumed to be
2258 in ISO 639-2 format. If FALSE, then all language
2259 codes are assumed to be in RFC 4646 language format.
2261 @retval NULL The best matching language could not be found in SupportedLanguages.
2262 @retval NULL There are not enough resources available to return the best matching
2264 @retval Other A pointer to a Null-terminated ASCII string that is the best matching
2265 language in SupportedLanguages.
2268 DriverHealthSelectBestLanguage (
2269 IN CHAR8
*SupportedLanguages
,
2270 IN BOOLEAN Iso639Language
2273 CHAR8
*LanguageVariable
;
2274 CHAR8
*BestLanguage
;
2276 GetEfiGlobalVariable2 (Iso639Language
? L
"Lang" : L
"PlatformLang", (VOID
**)&LanguageVariable
, NULL
);
2278 BestLanguage
= GetBestLanguage(
2281 (LanguageVariable
!= NULL
) ? LanguageVariable
: "",
2282 Iso639Language
? "eng" : "en-US",
2285 if (LanguageVariable
!= NULL
) {
2286 FreePool (LanguageVariable
);
2289 return BestLanguage
;
2296 This is an internal worker function to get the Component Name (2) protocol interface
2297 and the language it supports.
2299 @param ProtocolGuid A pointer to an EFI_GUID. It points to Component Name (2) protocol GUID.
2300 @param DriverBindingHandle The handle on which the Component Name (2) protocol instance is retrieved.
2301 @param ComponentName A pointer to the Component Name (2) protocol interface.
2302 @param SupportedLanguage The best suitable language that matches the SupportedLangues interface for the
2303 located Component Name (2) instance.
2305 @retval EFI_SUCCESS The Component Name (2) protocol instance is successfully located and we find
2306 the best matching language it support.
2307 @retval EFI_UNSUPPORTED The input Language is not supported by the Component Name (2) protocol.
2308 @retval Other Some error occurs when locating Component Name (2) protocol instance or finding
2309 the supported language.
2313 GetComponentNameWorker (
2314 IN EFI_GUID
*ProtocolGuid
,
2315 IN EFI_HANDLE DriverBindingHandle
,
2316 OUT EFI_COMPONENT_NAME_PROTOCOL
**ComponentName
,
2317 OUT CHAR8
**SupportedLanguage
2323 // Locate Component Name (2) protocol on the driver binging handle.
2325 Status
= gBS
->OpenProtocol (
2326 DriverBindingHandle
,
2328 (VOID
**) ComponentName
,
2331 EFI_OPEN_PROTOCOL_GET_PROTOCOL
2333 if (EFI_ERROR (Status
)) {
2338 // Apply shell policy to select the best language.
2340 *SupportedLanguage
= DriverHealthSelectBestLanguage (
2341 (*ComponentName
)->SupportedLanguages
,
2342 (BOOLEAN
) (ProtocolGuid
== &gEfiComponentNameProtocolGuid
)
2344 if (*SupportedLanguage
== NULL
) {
2345 Status
= EFI_UNSUPPORTED
;
2353 This is an internal worker function to get driver name from Component Name (2) protocol interface.
2356 @param ProtocolGuid A pointer to an EFI_GUID. It points to Component Name (2) protocol GUID.
2357 @param DriverBindingHandle The handle on which the Component Name (2) protocol instance is retrieved.
2358 @param DriverName A pointer to the Unicode string to return. This Unicode string is the name
2359 of the driver specified by This.
2361 @retval EFI_SUCCESS The driver name is successfully retrieved from Component Name (2) protocol
2363 @retval Other The driver name cannot be retrieved from Component Name (2) protocol
2368 GetDriverNameWorker (
2369 IN EFI_GUID
*ProtocolGuid
,
2370 IN EFI_HANDLE DriverBindingHandle
,
2371 OUT CHAR16
**DriverName
2375 CHAR8
*BestLanguage
;
2376 EFI_COMPONENT_NAME_PROTOCOL
*ComponentName
;
2379 // Retrieve Component Name (2) protocol instance on the driver binding handle and
2380 // find the best language this instance supports.
2382 Status
= GetComponentNameWorker (
2384 DriverBindingHandle
,
2388 if (EFI_ERROR (Status
)) {
2393 // Get the driver name from Component Name (2) protocol instance on the driver binging handle.
2395 Status
= ComponentName
->GetDriverName (
2400 FreePool (BestLanguage
);
2407 This function gets driver name from Component Name 2 protocol interface and Component Name protocol interface
2408 in turn. It first tries UEFI 2.0 Component Name 2 protocol interface and try to get the driver name.
2409 If the attempt fails, it then gets the driver name from EFI 1.1 Component Name protocol for backward
2410 compatibility support.
2412 @param DriverBindingHandle The handle on which the Component Name (2) protocol instance is retrieved.
2413 @param DriverName A pointer to the Unicode string to return. This Unicode string is the name
2414 of the driver specified by This.
2416 @retval EFI_SUCCESS The driver name is successfully retrieved from Component Name (2) protocol
2418 @retval Other The driver name cannot be retrieved from Component Name (2) protocol
2423 DriverHealthGetDriverName (
2424 IN EFI_HANDLE DriverBindingHandle
,
2425 OUT CHAR16
**DriverName
2431 // Get driver name from UEFI 2.0 Component Name 2 protocol interface.
2433 Status
= GetDriverNameWorker (&gEfiComponentName2ProtocolGuid
, DriverBindingHandle
, DriverName
);
2434 if (EFI_ERROR (Status
)) {
2436 // If it fails to get the driver name from Component Name protocol interface, we should fall back on
2437 // EFI 1.1 Component Name protocol interface.
2439 Status
= GetDriverNameWorker (&gEfiComponentNameProtocolGuid
, DriverBindingHandle
, DriverName
);
2448 This function gets controller name from Component Name 2 protocol interface and Component Name protocol interface
2449 in turn. It first tries UEFI 2.0 Component Name 2 protocol interface and try to get the controller name.
2450 If the attempt fails, it then gets the controller name from EFI 1.1 Component Name protocol for backward
2451 compatibility support.
2453 @param ProtocolGuid A pointer to an EFI_GUID. It points to Component Name (2) protocol GUID.
2454 @param DriverBindingHandle The handle on which the Component Name (2) protocol instance is retrieved.
2455 @param ControllerHandle The handle of a controller that the driver specified by This is managing.
2456 This handle specifies the controller whose name is to be returned.
2457 @param ChildHandle The handle of the child controller to retrieve the name of. This is an
2458 optional parameter that may be NULL. It will be NULL for device drivers.
2459 It will also be NULL for bus drivers that attempt to retrieve the name
2460 of the bus controller. It will not be NULL for a bus driver that attempts
2461 to retrieve the name of a child controller.
2462 @param ControllerName A pointer to the Unicode string to return. This Unicode string
2463 is the name of the controller specified by ControllerHandle and ChildHandle.
2465 @retval EFI_SUCCESS The controller name is successfully retrieved from Component Name (2) protocol
2467 @retval Other The controller name cannot be retrieved from Component Name (2) protocol.
2471 GetControllerNameWorker (
2472 IN EFI_GUID
*ProtocolGuid
,
2473 IN EFI_HANDLE DriverBindingHandle
,
2474 IN EFI_HANDLE ControllerHandle
,
2475 IN EFI_HANDLE ChildHandle
,
2476 OUT CHAR16
**ControllerName
2480 CHAR8
*BestLanguage
;
2481 EFI_COMPONENT_NAME_PROTOCOL
*ComponentName
;
2484 // Retrieve Component Name (2) protocol instance on the driver binding handle and
2485 // find the best language this instance supports.
2487 Status
= GetComponentNameWorker (
2489 DriverBindingHandle
,
2493 if (EFI_ERROR (Status
)) {
2498 // Get the controller name from Component Name (2) protocol instance on the driver binging handle.
2500 Status
= ComponentName
->GetControllerName (
2507 FreePool (BestLanguage
);
2514 This function gets controller name from Component Name 2 protocol interface and Component Name protocol interface
2515 in turn. It first tries UEFI 2.0 Component Name 2 protocol interface and try to get the controller name.
2516 If the attempt fails, it then gets the controller name from EFI 1.1 Component Name protocol for backward
2517 compatibility support.
2519 @param DriverBindingHandle The handle on which the Component Name (2) protocol instance is retrieved.
2520 @param ControllerHandle The handle of a controller that the driver specified by This is managing.
2521 This handle specifies the controller whose name is to be returned.
2522 @param ChildHandle The handle of the child controller to retrieve the name of. This is an
2523 optional parameter that may be NULL. It will be NULL for device drivers.
2524 It will also be NULL for bus drivers that attempt to retrieve the name
2525 of the bus controller. It will not be NULL for a bus driver that attempts
2526 to retrieve the name of a child controller.
2527 @param ControllerName A pointer to the Unicode string to return. This Unicode string
2528 is the name of the controller specified by ControllerHandle and ChildHandle.
2530 @retval EFI_SUCCESS The controller name is successfully retrieved from Component Name (2) protocol
2532 @retval Other The controller name cannot be retrieved from Component Name (2) protocol.
2536 DriverHealthGetControllerName (
2537 IN EFI_HANDLE DriverBindingHandle
,
2538 IN EFI_HANDLE ControllerHandle
,
2539 IN EFI_HANDLE ChildHandle
,
2540 OUT CHAR16
**ControllerName
2546 // Get controller name from UEFI 2.0 Component Name 2 protocol interface.
2548 Status
= GetControllerNameWorker (
2549 &gEfiComponentName2ProtocolGuid
,
2550 DriverBindingHandle
,
2555 if (EFI_ERROR (Status
)) {
2557 // If it fails to get the controller name from Component Name protocol interface, we should fall back on
2558 // EFI 1.1 Component Name protocol interface.
2560 Status
= GetControllerNameWorker (
2561 &gEfiComponentNameProtocolGuid
,
2562 DriverBindingHandle
,