2 The platform device manager reference implementation
4 Copyright (c) 2004 - 2018, 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 StrCpyS (String
, BufferLen
/ sizeof (CHAR16
), 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 UnicodeValueToStringS (
393 BufferLen
- ((UINTN
)String
- (UINTN
)*PBuffer
),
394 PREFIX_ZERO
| RADIX_HEX
,
398 String
+= StrnLenS (String
, (BufferLen
- ((UINTN
)String
- (UINTN
)*PBuffer
)) / sizeof (CHAR16
));
399 if (Index
< HwAddressSize
- 1) {
405 // If VLAN is configured, it will need extra 5 characters like "\0005".
406 // Plus one unicode character for the null-terminator.
408 Node
= (EFI_DEVICE_PATH_PROTOCOL
*)MacAddressNode
;
409 while (!IsDevicePathEnd (Node
)) {
410 if (Node
->Type
== MESSAGING_DEVICE_PATH
&& Node
->SubType
== MSG_VLAN_DP
) {
411 VlanId
= ((VLAN_DEVICE_PATH
*) Node
)->VlanId
;
413 Node
= NextDevicePathNode (Node
);
418 UnicodeValueToStringS (
420 BufferLen
- ((UINTN
)String
- (UINTN
)*PBuffer
),
421 PREFIX_ZERO
| RADIX_HEX
,
425 String
+= StrnLenS (String
, (BufferLen
- ((UINTN
)String
- (UINTN
)*PBuffer
)) / sizeof (CHAR16
));
429 // Null terminate the Unicode string
437 Save question id and prompt id to the mac device list.
438 If the same mac address has saved yet, no need to add more.
440 @param MacAddrString Mac address string.
442 @retval EFI_SUCCESS Add the item is successful.
443 @return Other values if failed to Add the item.
446 AddIdToMacDeviceList (
447 IN EFI_STRING MacAddrString
450 MENU_INFO_ITEM
*TempDeviceList
;
452 EFI_STRING StoredString
;
453 EFI_STRING_ID PromptId
;
454 EFI_HII_HANDLE HiiHandle
;
456 HiiHandle
= gDeviceManagerPrivate
.HiiHandle
;
457 TempDeviceList
= NULL
;
459 for (Index
= 0; Index
< mMacDeviceList
.CurListLen
; Index
++) {
460 StoredString
= HiiGetString (HiiHandle
, mMacDeviceList
.NodeList
[Index
].PromptId
, NULL
);
461 if (StoredString
== NULL
) {
466 // Already has save the same mac address to the list.
468 if (StrCmp (MacAddrString
, StoredString
) == 0) {
473 PromptId
= HiiSetString(HiiHandle
, 0, MacAddrString
, NULL
);
475 // If not in the list, save it.
477 if (mMacDeviceList
.MaxListLen
> mMacDeviceList
.CurListLen
+ 1) {
478 mMacDeviceList
.NodeList
[mMacDeviceList
.CurListLen
].PromptId
= PromptId
;
479 mMacDeviceList
.NodeList
[mMacDeviceList
.CurListLen
].QuestionId
= (EFI_QUESTION_ID
) (mMacDeviceList
.CurListLen
+ NETWORK_DEVICE_LIST_KEY_OFFSET
);
481 mMacDeviceList
.MaxListLen
+= MAX_MAC_ADDRESS_NODE_LIST_LEN
;
482 if (mMacDeviceList
.CurListLen
!= 0) {
483 TempDeviceList
= ReallocatePool (
484 sizeof (MENU_INFO_ITEM
) * mMacDeviceList
.CurListLen
,
485 sizeof (MENU_INFO_ITEM
) * mMacDeviceList
.MaxListLen
,
486 mMacDeviceList
.NodeList
489 TempDeviceList
= (MENU_INFO_ITEM
*)AllocatePool (sizeof (MENU_INFO_ITEM
) * mMacDeviceList
.MaxListLen
);
492 if (TempDeviceList
== NULL
) {
495 TempDeviceList
[mMacDeviceList
.CurListLen
].PromptId
= PromptId
;
496 TempDeviceList
[mMacDeviceList
.CurListLen
].QuestionId
= (EFI_QUESTION_ID
) (mMacDeviceList
.CurListLen
+ NETWORK_DEVICE_LIST_KEY_OFFSET
);
498 mMacDeviceList
.NodeList
= TempDeviceList
;
500 mMacDeviceList
.CurListLen
++;
506 Check the devcie path, try to find whether it has mac address path.
508 In this function, first need to check whether this path has mac address path.
509 second, when the mac address device path has find, also need to deicide whether
510 need to add this mac address relate info to the menu.
512 @param *Node Input device which need to be check.
513 @param *NeedAddItem Whether need to add the menu in the network device list.
515 @retval TRUE Has mac address device path.
516 @retval FALSE NOT Has mac address device path.
520 IsMacAddressDevicePath (
522 OUT BOOLEAN
*NeedAddItem
525 EFI_DEVICE_PATH_PROTOCOL
*DevicePath
;
529 ASSERT (Node
!= NULL
);
530 *NeedAddItem
= FALSE
;
534 DevicePath
= (EFI_DEVICE_PATH_PROTOCOL
*) Node
;
537 // find the partition device path node
539 while (!IsDevicePathEnd (DevicePath
)) {
540 if ((DevicePathType (DevicePath
) == MESSAGING_DEVICE_PATH
) &&
541 (DevicePathSubType (DevicePath
) == MSG_MAC_ADDR_DP
)) {
544 if (DEVICE_MANAGER_FORM_ID
== mNextShowFormId
) {
549 if (!GetMacAddressString((MAC_ADDR_DEVICE_PATH
*)DevicePath
, &Buffer
)) {
553 if (NETWORK_DEVICE_FORM_ID
== mNextShowFormId
) {
554 if (StrCmp (Buffer
, mSelectedMacAddrString
) == 0) {
560 if (NETWORK_DEVICE_LIST_FORM_ID
== mNextShowFormId
) {
562 // Same handle may has two network child handle, so the questionid
563 // has the offset of SAME_HANDLE_KEY_OFFSET.
565 if (AddIdToMacDeviceList (Buffer
)) {
571 DevicePath
= NextDevicePathNode (DevicePath
);
574 if (Buffer
!= NULL
) {
582 Check to see if the device path is for the network device.
584 @param Handle The HII handle which include the mac address device path.
585 @param ItemCount The new add Mac address item count.
587 @retval TRUE Need to add new item in the menu.
588 @return FALSE Do not need to add the menu about the network.
592 IsNeedAddNetworkMenu (
593 IN EFI_HII_HANDLE Handle
,
600 EFI_HANDLE DriverHandle
;
601 EFI_HANDLE ControllerHandle
;
602 EFI_DEVICE_PATH_PROTOCOL
*DevicePath
;
603 EFI_DEVICE_PATH_PROTOCOL
*TmpDevicePath
;
604 EFI_DEVICE_PATH_PROTOCOL
*ChildDevicePath
;
605 EFI_OPEN_PROTOCOL_INFORMATION_ENTRY
*OpenInfoBuffer
;
609 OpenInfoBuffer
= NULL
;
610 if ((Handle
== NULL
) || (ItemCount
== NULL
)) {
615 Status
= gHiiDatabase
->GetPackageListHandle (gHiiDatabase
, Handle
, &DriverHandle
);
616 if (EFI_ERROR (Status
)) {
620 // Get the device path by the got Driver handle .
622 Status
= gBS
->HandleProtocol (DriverHandle
, &gEfiDevicePathProtocolGuid
, (VOID
**) &DevicePath
);
623 if (EFI_ERROR (Status
)) {
626 TmpDevicePath
= DevicePath
;
629 // Check whether this device path include mac address device path.
630 // If this path has mac address path, get the value whether need
631 // add this info to the menu and return.
632 // Else check more about the child handle devcie path.
634 if (IsMacAddressDevicePath(TmpDevicePath
, &IsNeedAdd
)) {
635 if ((NETWORK_DEVICE_LIST_FORM_ID
== mNextShowFormId
) && IsNeedAdd
) {
642 // Search whether this path is the controller path, not he child handle path.
643 // And the child handle has the network devcie connected.
645 TmpDevicePath
= DevicePath
;
646 Status
= gBS
->LocateDevicePath(&gEfiDevicePathProtocolGuid
, &TmpDevicePath
, &ControllerHandle
);
647 if (EFI_ERROR (Status
)) {
651 if (!IsDevicePathEnd (TmpDevicePath
)) {
656 // Retrieve the list of agents that are consuming the specific protocol
657 // on ControllerHandle.
658 // The buffer point by OpenInfoBuffer need be free at this function.
660 Status
= gBS
->OpenProtocolInformation (
662 &gEfiPciIoProtocolGuid
,
666 if (EFI_ERROR (Status
)) {
671 // Inspect if ChildHandle is one of the agents.
673 Status
= EFI_UNSUPPORTED
;
674 for (Index
= 0; Index
< EntryCount
; Index
++) {
676 // Query all the children created by the controller handle's driver
678 if ((OpenInfoBuffer
[Index
].Attributes
& EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER
) != 0) {
679 Status
= gBS
->OpenProtocol (
680 OpenInfoBuffer
[Index
].ControllerHandle
,
681 &gEfiDevicePathProtocolGuid
,
682 (VOID
**) &ChildDevicePath
,
685 EFI_OPEN_PROTOCOL_GET_PROTOCOL
687 if (EFI_ERROR (Status
)) {
692 // Check whether this device path include mac address device path.
694 if (!IsMacAddressDevicePath(ChildDevicePath
, &IsNeedAdd
)) {
696 // If this path not has mac address path, check the other.
701 // If need to update the NETWORK_DEVICE_LIST_FORM, try to get more.
703 if ((NETWORK_DEVICE_LIST_FORM_ID
== mNextShowFormId
)) {
710 // If need to update other form, return whether need to add to the menu.
719 if (OpenInfoBuffer
!= NULL
) {
720 FreePool (OpenInfoBuffer
);
726 Get HiiHandle total number.
728 @param HiiHandles The input HiiHandle array.
730 @retval the Hiihandle count.
735 IN EFI_HII_HANDLE
*HiiHandles
740 for (Index
= 0; HiiHandles
[Index
] != NULL
; Index
++) {
747 Insert the new HiiHandle + FormsetGuid at the NewPair[InsertOffset].
749 @param HiiHandles The input HiiHandle array.
750 @param GuidLists The input form set guid lists.
751 @param ArrayCount The input array count, new array will be arraycount + 1 size.
752 @param Offset The current used HiiHandle's Offset.
753 @param FormSetGuid The new found formset guid.
758 IN OUT EFI_HII_HANDLE
**HiiHandles
,
759 IN OUT EFI_GUID
***GuidLists
,
762 IN EFI_GUID
*FormSetGuid
765 EFI_HII_HANDLE
*NewHiiHandles
;
766 EFI_GUID
**NewGuidLists
;
769 // +2 means include the new HiiHandle and the last empty NULL pointer.
771 NewHiiHandles
= AllocateZeroPool ((ArrayCount
+ 2) * sizeof (EFI_HII_HANDLE
));
772 ASSERT (NewHiiHandles
!= NULL
);
774 CopyMem (NewHiiHandles
, *HiiHandles
, Offset
* sizeof (EFI_HII_HANDLE
));
775 NewHiiHandles
[Offset
] = NewHiiHandles
[Offset
- 1];
776 CopyMem (NewHiiHandles
+ Offset
+ 1, *HiiHandles
+ Offset
, (ArrayCount
- Offset
) * sizeof (EFI_HII_HANDLE
));
778 NewGuidLists
= AllocateZeroPool ((ArrayCount
+ 2) * sizeof (EFI_GUID
*));
779 ASSERT (NewGuidLists
!= NULL
);
781 CopyMem (NewGuidLists
, *GuidLists
, Offset
* sizeof (EFI_GUID
*));
782 NewGuidLists
[Offset
] = FormSetGuid
;
784 FreePool (*HiiHandles
);
785 *HiiHandles
= NewHiiHandles
;
786 FreePool (*GuidLists
);
787 *GuidLists
= NewGuidLists
;
791 Call the browser and display the device manager to allow user
792 to configure the platform.
794 This function create the dynamic content for device manager. It includes
795 section header for all class of devices, one-of opcode to set VBIOS.
797 @retval EFI_SUCCESS Operation is successful.
798 @return Other values if failed to clean up the dynamic content from HII
811 EFI_STRING_ID TokenHelp
;
812 EFI_HII_HANDLE
*HiiHandles
;
813 EFI_HII_HANDLE HiiHandle
;
814 EFI_STRING_ID FormSetTitle
;
815 EFI_STRING_ID FormSetHelp
;
816 EFI_BROWSER_ACTION_REQUEST ActionRequest
;
817 VOID
*StartOpCodeHandle
;
818 VOID
*EndOpCodeHandle
;
819 EFI_IFR_GUID_LABEL
*StartLabel
;
820 EFI_IFR_GUID_LABEL
*EndLabel
;
822 EFI_HANDLE
*DriverHealthHandles
;
823 BOOLEAN AddNetworkMenu
;
826 EFI_STRING NewStringTitle
;
827 EFI_GUID
**GuidLists
;
830 EFI_GUID
*FormSetGuid
;
834 Status
= EFI_SUCCESS
;
837 DriverHealthHandles
= NULL
;
838 AddNetworkMenu
= FALSE
;
844 // Connect all prior to entering the platform setup menu.
846 if (!gConnectAllHappened
) {
847 BdsLibConnectAllDriversToAllControllers ();
848 gConnectAllHappened
= TRUE
;
851 HiiHandle
= gDeviceManagerPrivate
.HiiHandle
;
852 if (HiiHandle
== NULL
) {
854 // Publish our HII data.
856 HiiHandle
= HiiAddPackages (
857 &gDeviceManagerFormSetGuid
,
858 gDeviceManagerPrivate
.DriverHandle
,
863 if (HiiHandle
== NULL
) {
864 return EFI_OUT_OF_RESOURCES
;
867 gDeviceManagerPrivate
.HiiHandle
= HiiHandle
;
871 // If need show the Network device list form, clear the old save list first.
873 if ((mNextShowFormId
== NETWORK_DEVICE_LIST_FORM_ID
) && (mMacDeviceList
.CurListLen
> 0)) {
874 mMacDeviceList
.CurListLen
= 0;
878 // Update the network device form titile.
880 if (mNextShowFormId
== NETWORK_DEVICE_FORM_ID
) {
881 String
= HiiGetString (HiiHandle
, STRING_TOKEN (STR_FORM_NETWORK_DEVICE_TITLE
), NULL
);
882 NewStringLen
= StrLen(mSelectedMacAddrString
) * 2;
883 NewStringLen
+= (StrLen(String
) + 2) * 2;
884 NewStringTitle
= AllocatePool (NewStringLen
);
885 UnicodeSPrint (NewStringTitle
, NewStringLen
, L
"%s %s", String
, mSelectedMacAddrString
);
886 HiiSetString (HiiHandle
, STRING_TOKEN (STR_FORM_NETWORK_DEVICE_TITLE
), NewStringTitle
, NULL
);
888 FreePool (NewStringTitle
);
892 // Allocate space for creation of UpdateData Buffer
894 StartOpCodeHandle
= HiiAllocateOpCodeHandle ();
895 ASSERT (StartOpCodeHandle
!= NULL
);
897 EndOpCodeHandle
= HiiAllocateOpCodeHandle ();
898 ASSERT (EndOpCodeHandle
!= NULL
);
901 // Create Hii Extend Label OpCode as the start opcode
903 StartLabel
= (EFI_IFR_GUID_LABEL
*) HiiCreateGuidOpCode (StartOpCodeHandle
, &gEfiIfrTianoGuid
, NULL
, sizeof (EFI_IFR_GUID_LABEL
));
904 StartLabel
->ExtendOpCode
= EFI_IFR_EXTEND_OP_LABEL
;
906 // According to the next show Form id(mNextShowFormId) to decide which form need to update.
908 StartLabel
->Number
= (UINT16
) (LABEL_FORM_ID_OFFSET
+ mNextShowFormId
);
911 // Create Hii Extend Label OpCode as the end opcode
913 EndLabel
= (EFI_IFR_GUID_LABEL
*) HiiCreateGuidOpCode (EndOpCodeHandle
, &gEfiIfrTianoGuid
, NULL
, sizeof (EFI_IFR_GUID_LABEL
));
914 EndLabel
->ExtendOpCode
= EFI_IFR_EXTEND_OP_LABEL
;
915 EndLabel
->Number
= LABEL_END
;
918 // Get all the Hii handles
920 HiiHandles
= HiiGetHiiHandles (NULL
);
921 ASSERT (HiiHandles
!= NULL
);
923 HandleNum
= GetHiiHandleCount (HiiHandles
);
924 GuidLists
= AllocateZeroPool ((HandleNum
+ 1) * sizeof (EFI_GUID
*));
925 ASSERT (GuidLists
!= NULL
);
928 // Search for formset of each class type
930 for (Index
= 0; HiiHandles
[Index
] != NULL
; Index
++) {
932 // The QuestionId in the form which will call the driver form has this asssumption.
933 // QuestionId = Handle Index + NETWORK_DEVICE_LIST_KEY_OFFSET;
934 // Different QuestionId at least has the section of NETWORK_DEVICE_LIST_KEY_OFFSET.
936 ASSERT(Index
< MAX_KEY_SECTION_LEN
);
938 if (!ExtractDisplayedHiiFormFromHiiHandle (HiiHandles
[Index
], &gEfiHiiPlatformSetupFormsetGuid
, SkipCount
, &FormSetTitle
, &FormSetHelp
, &FormSetGuid
)) {
944 // One HiiHandle has more than one formset can be shown,
945 // Insert a new pair of HiiHandle + Guid to the HiiHandles and GuidLists list.
948 AdjustArrayData (&HiiHandles
, &GuidLists
, HandleNum
, Index
+ 1, FormSetGuid
);
953 String
= HiiGetString (HiiHandles
[Index
], FormSetTitle
, NULL
);
954 if (String
== NULL
) {
955 String
= HiiGetString (HiiHandle
, STR_MISSING_STRING
, NULL
);
956 ASSERT (String
!= NULL
);
958 Token
= HiiSetString (HiiHandle
, 0, String
, NULL
);
961 String
= HiiGetString (HiiHandles
[Index
], FormSetHelp
, NULL
);
962 if (String
== NULL
) {
963 String
= HiiGetString (HiiHandle
, STR_MISSING_STRING
, NULL
);
964 ASSERT (String
!= NULL
);
966 TokenHelp
= HiiSetString (HiiHandle
, 0, String
, NULL
);
970 // Network device process
972 if (IsNeedAddNetworkMenu (HiiHandles
[Index
], &AddItemCount
)) {
973 if (mNextShowFormId
== DEVICE_MANAGER_FORM_ID
) {
975 // Only show one menu item "Network Config" in the device manger form.
977 if (!AddNetworkMenu
) {
978 AddNetworkMenu
= TRUE
;
979 HiiCreateGotoOpCode (
982 STRING_TOKEN (STR_FORM_NETWORK_DEVICE_LIST_TITLE
),
983 STRING_TOKEN (STR_FORM_NETWORK_DEVICE_LIST_HELP
),
984 EFI_IFR_FLAG_CALLBACK
,
985 (EFI_QUESTION_ID
) QUESTION_NETWORK_DEVICE_ID
988 } else if (mNextShowFormId
== NETWORK_DEVICE_LIST_FORM_ID
) {
990 // In network device list form, same mac address device only show one menu.
992 while (AddItemCount
> 0) {
993 HiiCreateGotoOpCode (
996 mMacDeviceList
.NodeList
[mMacDeviceList
.CurListLen
- AddItemCount
].PromptId
,
997 STRING_TOKEN (STR_NETWORK_DEVICE_HELP
),
998 EFI_IFR_FLAG_CALLBACK
,
999 mMacDeviceList
.NodeList
[mMacDeviceList
.CurListLen
- AddItemCount
].QuestionId
1003 } else if (mNextShowFormId
== NETWORK_DEVICE_FORM_ID
) {
1005 // In network device form, only the selected mac address device need to be show.
1007 HiiCreateGotoOpCode (
1012 EFI_IFR_FLAG_CALLBACK
,
1013 (EFI_QUESTION_ID
) (Index
+ DEVICE_KEY_OFFSET
)
1019 // Not network device process, only need to show at device manger form.
1021 if (mNextShowFormId
== DEVICE_MANAGER_FORM_ID
) {
1022 HiiCreateGotoOpCode (
1027 EFI_IFR_FLAG_CALLBACK
,
1028 (EFI_QUESTION_ID
) (Index
+ DEVICE_KEY_OFFSET
)
1034 // Try to find more formset in this HiiHandle.
1040 Status
= gBS
->LocateHandleBuffer (
1042 &gEfiDriverHealthProtocolGuid
,
1045 &DriverHealthHandles
1049 // If there are no drivers installed driver health protocol, do not create driver health entry in UI
1051 if (NumHandles
!= 0) {
1053 // If driver health protocol is installed, create Driver Health subtitle and entry
1055 HiiCreateSubTitleOpCode (StartOpCodeHandle
, STRING_TOKEN (STR_DM_DRIVER_HEALTH_TITLE
), 0, 0, 0);
1056 HiiCreateGotoOpCode (
1058 DRIVER_HEALTH_FORM_ID
,
1059 STRING_TOKEN(STR_DRIVER_HEALTH_ALL_HEALTHY
), // Prompt text
1060 STRING_TOKEN(STR_DRIVER_HEALTH_STATUS_HELP
), // Help text
1061 EFI_IFR_FLAG_CALLBACK
,
1062 DEVICE_MANAGER_KEY_DRIVER_HEALTH
// Question ID
1066 // Check All Driver health status
1068 if (!PlaformHealthStatusCheck ()) {
1070 // At least one driver in the platform are not in healthy status
1072 HiiSetString (HiiHandle
, STRING_TOKEN (STR_DRIVER_HEALTH_ALL_HEALTHY
), GetStringById (STRING_TOKEN (STR_DRIVER_NOT_HEALTH
)), NULL
);
1075 // For the string of STR_DRIVER_HEALTH_ALL_HEALTHY previously has been updated and we need to update it while re-entry.
1077 HiiSetString (HiiHandle
, STRING_TOKEN (STR_DRIVER_HEALTH_ALL_HEALTHY
), GetStringById (STRING_TOKEN (STR_DRIVER_HEALTH_ALL_HEALTHY
)), NULL
);
1083 &gDeviceManagerFormSetGuid
,
1089 ActionRequest
= EFI_BROWSER_ACTION_REQUEST_NONE
;
1090 Status
= gFormBrowser2
->SendForm (
1094 &gDeviceManagerFormSetGuid
,
1099 if (ActionRequest
== EFI_BROWSER_ACTION_REQUEST_RESET
) {
1100 EnableResetRequired ();
1104 // We will have returned from processing a callback, selected
1105 // a target to display
1107 if ((gCallbackKey
>= DEVICE_KEY_OFFSET
)) {
1108 ActionRequest
= EFI_BROWSER_ACTION_REQUEST_NONE
;
1109 Status
= gFormBrowser2
->SendForm (
1111 &HiiHandles
[gCallbackKey
- DEVICE_KEY_OFFSET
],
1113 GuidLists
[gCallbackKey
- DEVICE_KEY_OFFSET
],
1119 if (ActionRequest
== EFI_BROWSER_ACTION_REQUEST_RESET
) {
1120 EnableResetRequired ();
1124 // Force return to Device Manager
1126 gCallbackKey
= FRONT_PAGE_KEY_DEVICE_MANAGER
;
1131 // Driver Health item chose.
1133 if (gCallbackKey
== DEVICE_MANAGER_KEY_DRIVER_HEALTH
) {
1134 CallDriverHealth ();
1136 // Force return to Device Manager
1138 gCallbackKey
= FRONT_PAGE_KEY_DEVICE_MANAGER
;
1143 // Enter from device manager and into the network device list.
1145 if (gCallbackKey
== QUESTION_NETWORK_DEVICE_ID
) {
1146 mNextShowFormId
= NETWORK_DEVICE_LIST_FORM_ID
;
1147 gCallbackKey
= FRONT_PAGE_KEY_DEVICE_MANAGER
;
1152 // In this case, go from the network device list to the specify device.
1154 if ((gCallbackKey
< MAX_KEY_SECTION_LEN
+ NETWORK_DEVICE_LIST_KEY_OFFSET
) && (gCallbackKey
>= NETWORK_DEVICE_LIST_KEY_OFFSET
)) {
1155 mNextShowFormId
= NETWORK_DEVICE_FORM_ID
;
1156 gCallbackKey
= FRONT_PAGE_KEY_DEVICE_MANAGER
;
1161 // Select the ESC, the gCallbackKey == 0.
1163 if(mNextShowFormId
- 1 < DEVICE_MANAGER_FORM_ID
) {
1164 mNextShowFormId
= DEVICE_MANAGER_FORM_ID
;
1166 mNextShowFormId
= (UINT16
) (mNextShowFormId
- 1);
1167 gCallbackKey
= FRONT_PAGE_KEY_DEVICE_MANAGER
;
1172 // Remove our packagelist from HII database.
1174 HiiRemovePackages (HiiHandle
);
1175 gDeviceManagerPrivate
.HiiHandle
= NULL
;
1177 HiiFreeOpCodeHandle (StartOpCodeHandle
);
1178 HiiFreeOpCodeHandle (EndOpCodeHandle
);
1179 FreePool (HiiHandles
);
1181 for (Index
= 0; Index
< HandleNum
; Index
++) {
1182 if (GuidLists
[Index
] != NULL
) {
1183 FreePool (GuidLists
[Index
]);
1186 FreePool (GuidLists
);
1192 This function is invoked if user selected a interactive opcode from Driver Health's
1193 Formset. The decision by user is saved to gCallbackKey for later processing.
1195 @param This Points to the EFI_HII_CONFIG_ACCESS_PROTOCOL.
1196 @param Action Specifies the type of action taken by the browser.
1197 @param QuestionId A unique value which is sent to the original exporting driver
1198 so that it can identify the type of data to expect.
1199 @param Type The type of value for the question.
1200 @param Value A pointer to the data being sent to the original exporting driver.
1201 @param ActionRequest On return, points to the action requested by the callback function.
1203 @retval EFI_SUCCESS The callback successfully handled the action.
1204 @retval EFI_INVALID_PARAMETER The setup browser call this function with invalid parameters.
1209 DriverHealthCallback (
1210 IN CONST EFI_HII_CONFIG_ACCESS_PROTOCOL
*This
,
1211 IN EFI_BROWSER_ACTION Action
,
1212 IN EFI_QUESTION_ID QuestionId
,
1214 IN EFI_IFR_TYPE_VALUE
*Value
,
1215 OUT EFI_BROWSER_ACTION_REQUEST
*ActionRequest
1218 if (Action
== EFI_BROWSER_ACTION_CHANGED
) {
1219 if ((Value
== NULL
) || (ActionRequest
== NULL
)) {
1220 return EFI_INVALID_PARAMETER
;
1223 gCallbackKey
= QuestionId
;
1226 // Request to exit SendForm(), so as to switch to selected form
1228 *ActionRequest
= EFI_BROWSER_ACTION_REQUEST_EXIT
;
1234 // All other action return unsupported.
1236 return EFI_UNSUPPORTED
;
1240 Collect and display the platform's driver health relative information, allow user to do interactive
1241 operation while the platform is unhealthy.
1243 This function display a form which divided into two parts. The one list all modules which has installed
1244 driver health protocol. The list usually contain driver name, controller name, and it's health info.
1245 While the driver name can't be retrieved, will use device path as backup. The other part of the form provide
1246 a choice to the user to repair all platform.
1255 EFI_HII_HANDLE HiiHandle
;
1256 EFI_BROWSER_ACTION_REQUEST ActionRequest
;
1257 EFI_IFR_GUID_LABEL
*StartLabel
;
1258 EFI_IFR_GUID_LABEL
*StartLabelRepair
;
1259 EFI_IFR_GUID_LABEL
*EndLabel
;
1260 EFI_IFR_GUID_LABEL
*EndLabelRepair
;
1261 VOID
*StartOpCodeHandle
;
1262 VOID
*EndOpCodeHandle
;
1263 VOID
*StartOpCodeHandleRepair
;
1264 VOID
*EndOpCodeHandleRepair
;
1266 EFI_STRING_ID Token
;
1267 EFI_STRING_ID TokenHelp
;
1269 EFI_STRING TmpString
;
1270 EFI_STRING DriverName
;
1271 EFI_STRING ControllerName
;
1272 LIST_ENTRY DriverHealthList
;
1273 DRIVER_HEALTH_INFO
*DriverHealthInfo
;
1275 EFI_DEVICE_PATH_PROTOCOL
*DriverDevicePath
;
1276 BOOLEAN RebootRequired
;
1277 BOOLEAN IsControllerNameEmpty
;
1281 DriverHealthInfo
= NULL
;
1282 DriverDevicePath
= NULL
;
1283 IsControllerNameEmpty
= FALSE
;
1284 InitializeListHead (&DriverHealthList
);
1286 HiiHandle
= gDeviceManagerPrivate
.DriverHealthHiiHandle
;
1287 if (HiiHandle
== NULL
) {
1289 // Publish Driver Health HII data.
1291 HiiHandle
= HiiAddPackages (
1292 &gDeviceManagerFormSetGuid
,
1293 gDeviceManagerPrivate
.DriverHealthHandle
,
1298 if (HiiHandle
== NULL
) {
1302 gDeviceManagerPrivate
.DriverHealthHiiHandle
= HiiHandle
;
1306 // Allocate space for creation of UpdateData Buffer
1308 StartOpCodeHandle
= HiiAllocateOpCodeHandle ();
1309 ASSERT (StartOpCodeHandle
!= NULL
);
1311 EndOpCodeHandle
= HiiAllocateOpCodeHandle ();
1312 ASSERT (EndOpCodeHandle
!= NULL
);
1314 StartOpCodeHandleRepair
= HiiAllocateOpCodeHandle ();
1315 ASSERT (StartOpCodeHandleRepair
!= NULL
);
1317 EndOpCodeHandleRepair
= HiiAllocateOpCodeHandle ();
1318 ASSERT (EndOpCodeHandleRepair
!= NULL
);
1321 // Create Hii Extend Label OpCode as the start opcode
1323 StartLabel
= (EFI_IFR_GUID_LABEL
*) HiiCreateGuidOpCode (StartOpCodeHandle
, &gEfiIfrTianoGuid
, NULL
, sizeof (EFI_IFR_GUID_LABEL
));
1324 StartLabel
->ExtendOpCode
= EFI_IFR_EXTEND_OP_LABEL
;
1325 StartLabel
->Number
= LABEL_DRIVER_HEALTH
;
1328 // Create Hii Extend Label OpCode as the start opcode
1330 StartLabelRepair
= (EFI_IFR_GUID_LABEL
*) HiiCreateGuidOpCode (StartOpCodeHandleRepair
, &gEfiIfrTianoGuid
, NULL
, sizeof (EFI_IFR_GUID_LABEL
));
1331 StartLabelRepair
->ExtendOpCode
= EFI_IFR_EXTEND_OP_LABEL
;
1332 StartLabelRepair
->Number
= LABEL_DRIVER_HEALTH_REAPIR_ALL
;
1335 // Create Hii Extend Label OpCode as the end opcode
1337 EndLabel
= (EFI_IFR_GUID_LABEL
*) HiiCreateGuidOpCode (EndOpCodeHandle
, &gEfiIfrTianoGuid
, NULL
, sizeof (EFI_IFR_GUID_LABEL
));
1338 EndLabel
->ExtendOpCode
= EFI_IFR_EXTEND_OP_LABEL
;
1339 EndLabel
->Number
= LABEL_DRIVER_HEALTH_END
;
1342 // Create Hii Extend Label OpCode as the end opcode
1344 EndLabelRepair
= (EFI_IFR_GUID_LABEL
*) HiiCreateGuidOpCode (EndOpCodeHandleRepair
, &gEfiIfrTianoGuid
, NULL
, sizeof (EFI_IFR_GUID_LABEL
));
1345 EndLabelRepair
->ExtendOpCode
= EFI_IFR_EXTEND_OP_LABEL
;
1346 EndLabelRepair
->Number
= LABEL_DRIVER_HEALTH_REAPIR_ALL_END
;
1348 HiiCreateSubTitleOpCode (StartOpCodeHandle
, STRING_TOKEN (STR_DH_STATUS_LIST
), 0, 0, 1);
1350 Status
= GetAllControllersHealthStatus (&DriverHealthList
);
1351 ASSERT (Status
!= EFI_OUT_OF_RESOURCES
);
1353 Link
= GetFirstNode (&DriverHealthList
);
1355 while (!IsNull (&DriverHealthList
, Link
)) {
1356 DriverHealthInfo
= DEVICE_MANAGER_HEALTH_INFO_FROM_LINK (Link
);
1358 Status
= DriverHealthGetDriverName (DriverHealthInfo
->DriverHandle
, &DriverName
);
1359 if (EFI_ERROR (Status
)) {
1361 // Can not get the Driver name, so use the Device path
1363 DriverDevicePath
= DevicePathFromHandle (DriverHealthInfo
->DriverHandle
);
1364 DriverName
= DevicePathToStr (DriverDevicePath
);
1366 StringSize
= StrSize (DriverName
);
1368 Status
= DriverHealthGetControllerName (
1369 DriverHealthInfo
->DriverHandle
,
1370 DriverHealthInfo
->ControllerHandle
,
1371 DriverHealthInfo
->ChildHandle
,
1375 if (!EFI_ERROR (Status
)) {
1376 IsControllerNameEmpty
= FALSE
;
1377 StringSize
+= StrLen (L
" ") * sizeof(CHAR16
);
1378 StringSize
+= StrLen (ControllerName
) * sizeof(CHAR16
);
1380 IsControllerNameEmpty
= TRUE
;
1384 // Add the message of the Module itself provided after the string item.
1386 if ((DriverHealthInfo
->MessageList
!= NULL
) && (DriverHealthInfo
->MessageList
->StringId
!= 0)) {
1387 TmpString
= HiiGetString (
1388 DriverHealthInfo
->MessageList
->HiiHandle
,
1389 DriverHealthInfo
->MessageList
->StringId
,
1392 ASSERT (TmpString
!= NULL
);
1394 StringSize
+= StrLen (L
" ") * sizeof(CHAR16
);
1395 StringSize
+= StrLen (TmpString
) * sizeof(CHAR16
);
1397 String
= (EFI_STRING
) AllocateZeroPool (StringSize
);
1398 ASSERT (String
!= NULL
);
1400 StrCpyS (String
, StringSize
/ sizeof(CHAR16
), DriverName
);
1401 if (!IsControllerNameEmpty
) {
1402 StrCatS (String
, StringSize
/ sizeof(CHAR16
), L
" ");
1403 StrCatS (String
, StringSize
/ sizeof(CHAR16
), ControllerName
);
1406 StrCatS (String
, StringSize
/ sizeof(CHAR16
), L
" ");
1407 StrCatS (String
, StringSize
/ sizeof(CHAR16
), TmpString
);
1411 // Update the string will be displayed base on the driver's health status
1413 switch(DriverHealthInfo
->HealthStatus
) {
1414 case EfiDriverHealthStatusRepairRequired
:
1415 TmpString
= GetStringById (STRING_TOKEN (STR_REPAIR_REQUIRED
));
1417 case EfiDriverHealthStatusConfigurationRequired
:
1418 TmpString
= GetStringById (STRING_TOKEN (STR_CONFIGURATION_REQUIRED
));
1420 case EfiDriverHealthStatusFailed
:
1421 TmpString
= GetStringById (STRING_TOKEN (STR_OPERATION_FAILED
));
1423 case EfiDriverHealthStatusReconnectRequired
:
1424 TmpString
= GetStringById (STRING_TOKEN (STR_RECONNECT_REQUIRED
));
1426 case EfiDriverHealthStatusRebootRequired
:
1427 TmpString
= GetStringById (STRING_TOKEN (STR_REBOOT_REQUIRED
));
1430 TmpString
= GetStringById (STRING_TOKEN (STR_DRIVER_HEALTH_HEALTHY
));
1433 ASSERT (TmpString
!= NULL
);
1435 StringSize
+= StrLen (TmpString
) * sizeof(CHAR16
);
1437 String
= (EFI_STRING
) AllocateZeroPool (StringSize
);
1438 ASSERT (String
!= NULL
);
1440 StrCpyS (String
, StringSize
/ sizeof (CHAR16
), DriverName
);
1441 if (!IsControllerNameEmpty
) {
1442 StrCatS (String
, StringSize
/ sizeof (CHAR16
), L
" ");
1443 StrCatS (String
, StringSize
/ sizeof (CHAR16
), ControllerName
);
1446 StrCatS (String
, StringSize
/ sizeof (CHAR16
), TmpString
);
1449 FreePool (TmpString
);
1451 Token
= HiiSetString (HiiHandle
, 0, String
, NULL
);
1454 TokenHelp
= HiiSetString (HiiHandle
, 0, GetStringById( STRING_TOKEN (STR_DH_REPAIR_SINGLE_HELP
)), NULL
);
1456 HiiCreateActionOpCode (
1458 (EFI_QUESTION_ID
) (Index
+ DRIVER_HEALTH_KEY_OFFSET
),
1461 EFI_IFR_FLAG_CALLBACK
,
1465 Link
= GetNextNode (&DriverHealthList
, Link
);
1469 // Add End Opcode for Subtitle
1471 HiiCreateEndOpCode (StartOpCodeHandle
);
1473 HiiCreateSubTitleOpCode (StartOpCodeHandleRepair
, STRING_TOKEN (STR_DRIVER_HEALTH_REPAIR_ALL
), 0, 0, 1);
1474 TokenHelp
= HiiSetString (HiiHandle
, 0, GetStringById( STRING_TOKEN (STR_DH_REPAIR_ALL_HELP
)), NULL
);
1476 if (PlaformHealthStatusCheck ()) {
1478 // No action need to do for the platform
1480 Token
= HiiSetString (HiiHandle
, 0, GetStringById( STRING_TOKEN (STR_DRIVER_HEALTH_ALL_HEALTHY
)), NULL
);
1481 HiiCreateActionOpCode (
1482 StartOpCodeHandleRepair
,
1486 EFI_IFR_FLAG_READ_ONLY
,
1491 // Create ActionOpCode only while the platform need to do health related operation.
1493 Token
= HiiSetString (HiiHandle
, 0, GetStringById( STRING_TOKEN (STR_DH_REPAIR_ALL_TITLE
)), NULL
);
1494 HiiCreateActionOpCode (
1495 StartOpCodeHandleRepair
,
1496 (EFI_QUESTION_ID
) DRIVER_HEALTH_REPAIR_ALL_KEY
,
1499 EFI_IFR_FLAG_CALLBACK
,
1504 HiiCreateEndOpCode (StartOpCodeHandleRepair
);
1506 Status
= HiiUpdateForm (
1508 &gDriverHealthFormSetGuid
,
1509 DRIVER_HEALTH_FORM_ID
,
1513 ASSERT (Status
!= EFI_NOT_FOUND
);
1514 ASSERT (Status
!= EFI_BUFFER_TOO_SMALL
);
1516 Status
= HiiUpdateForm (
1518 &gDriverHealthFormSetGuid
,
1519 DRIVER_HEALTH_FORM_ID
,
1520 StartOpCodeHandleRepair
,
1521 EndOpCodeHandleRepair
1523 ASSERT (Status
!= EFI_NOT_FOUND
);
1524 ASSERT (Status
!= EFI_BUFFER_TOO_SMALL
);
1526 ActionRequest
= EFI_BROWSER_ACTION_REQUEST_NONE
;
1527 Status
= gFormBrowser2
->SendForm (
1531 &gDriverHealthFormSetGuid
,
1532 DRIVER_HEALTH_FORM_ID
,
1536 if (ActionRequest
== EFI_BROWSER_ACTION_REQUEST_RESET
) {
1537 EnableResetRequired ();
1541 // We will have returned from processing a callback - user either hit ESC to exit, or selected
1542 // a target to display.
1543 // Process the diver health status states here.
1545 if (gCallbackKey
>= DRIVER_HEALTH_KEY_OFFSET
&& gCallbackKey
!= DRIVER_HEALTH_REPAIR_ALL_KEY
) {
1546 ActionRequest
= EFI_BROWSER_ACTION_REQUEST_NONE
;
1548 Link
= GetFirstNode (&DriverHealthList
);
1551 while (!IsNull (&DriverHealthList
, Link
)) {
1553 // Got the item relative node in the List
1555 if (Index
== (gCallbackKey
- DRIVER_HEALTH_KEY_OFFSET
)) {
1556 DriverHealthInfo
= DEVICE_MANAGER_HEALTH_INFO_FROM_LINK (Link
);
1558 // Process the driver's healthy status for the specify module
1560 RebootRequired
= FALSE
;
1561 ProcessSingleControllerHealth (
1562 DriverHealthInfo
->DriverHealth
,
1563 DriverHealthInfo
->ControllerHandle
,
1564 DriverHealthInfo
->ChildHandle
,
1565 DriverHealthInfo
->HealthStatus
,
1566 &(DriverHealthInfo
->MessageList
),
1567 DriverHealthInfo
->HiiHandle
,
1570 if (RebootRequired
) {
1571 gRT
->ResetSystem (EfiResetWarm
, EFI_SUCCESS
, 0, NULL
);
1576 Link
= GetNextNode (&DriverHealthList
, Link
);
1579 if (ActionRequest
== EFI_BROWSER_ACTION_REQUEST_RESET
) {
1580 EnableResetRequired ();
1584 // Force return to the form of Driver Health in Device Manager
1586 gCallbackKey
= DRIVER_HEALTH_RETURN_KEY
;
1590 // Repair the whole platform
1592 if (gCallbackKey
== DRIVER_HEALTH_REPAIR_ALL_KEY
) {
1593 ActionRequest
= EFI_BROWSER_ACTION_REQUEST_NONE
;
1595 PlatformRepairAll (&DriverHealthList
);
1597 gCallbackKey
= DRIVER_HEALTH_RETURN_KEY
;
1601 // Remove driver health packagelist from HII database.
1603 HiiRemovePackages (HiiHandle
);
1604 gDeviceManagerPrivate
.DriverHealthHiiHandle
= NULL
;
1607 // Free driver health info list
1609 while (!IsListEmpty (&DriverHealthList
)) {
1611 Link
= GetFirstNode(&DriverHealthList
);
1612 DriverHealthInfo
= DEVICE_MANAGER_HEALTH_INFO_FROM_LINK (Link
);
1613 RemoveEntryList (Link
);
1615 if (DriverHealthInfo
->MessageList
!= NULL
) {
1616 FreePool(DriverHealthInfo
->MessageList
);
1617 FreePool (DriverHealthInfo
);
1621 HiiFreeOpCodeHandle (StartOpCodeHandle
);
1622 HiiFreeOpCodeHandle (EndOpCodeHandle
);
1623 HiiFreeOpCodeHandle (StartOpCodeHandleRepair
);
1624 HiiFreeOpCodeHandle (EndOpCodeHandleRepair
);
1626 if (gCallbackKey
== DRIVER_HEALTH_RETURN_KEY
) {
1628 // Force return to Driver Health Form
1630 gCallbackKey
= DEVICE_MANAGER_KEY_DRIVER_HEALTH
;
1631 CallDriverHealth ();
1637 Check the Driver Health status of a single controller and try to process it if not healthy.
1639 This function called by CheckAllControllersHealthStatus () function in order to process a specify
1640 contoller's health state.
1642 @param DriverHealthList A Pointer to the list contain all of the platform driver health information.
1643 @param DriverHandle The handle of driver.
1644 @param ControllerHandle The class guid specifies which form set will be displayed.
1645 @param ChildHandle The handle of the child controller to retrieve the health
1646 status on. This is an optional parameter that may be NULL.
1647 @param DriverHealth A pointer to the EFI_DRIVER_HEALTH_PROTOCOL instance.
1648 @param HealthStatus The health status of the controller.
1650 @retval EFI_INVALID_PARAMETER HealthStatus or DriverHealth is NULL.
1651 @retval HealthStatus The Health status of specify controller.
1652 @retval EFI_OUT_OF_RESOURCES The list of Driver Health Protocol handles can not be retrieved.
1653 @retval EFI_NOT_FOUND No controller in the platform install Driver Health Protocol.
1654 @retval EFI_SUCCESS The Health related operation has been taken successfully.
1659 GetSingleControllerHealthStatus (
1660 IN OUT LIST_ENTRY
*DriverHealthList
,
1661 IN EFI_HANDLE DriverHandle
,
1662 IN EFI_HANDLE ControllerHandle
, OPTIONAL
1663 IN EFI_HANDLE ChildHandle
, OPTIONAL
1664 IN EFI_DRIVER_HEALTH_PROTOCOL
*DriverHealth
,
1665 IN EFI_DRIVER_HEALTH_STATUS
*HealthStatus
1669 EFI_DRIVER_HEALTH_HII_MESSAGE
*MessageList
;
1670 EFI_HII_HANDLE FormHiiHandle
;
1671 DRIVER_HEALTH_INFO
*DriverHealthInfo
;
1673 if (HealthStatus
== NULL
) {
1675 // If HealthStatus is NULL, then return EFI_INVALID_PARAMETER
1677 return EFI_INVALID_PARAMETER
;
1681 // Assume the HealthStatus is healthy
1683 *HealthStatus
= EfiDriverHealthStatusHealthy
;
1685 if (DriverHealth
== NULL
) {
1687 // If DriverHealth is NULL, then return EFI_INVALID_PARAMETER
1689 return EFI_INVALID_PARAMETER
;
1692 if (ControllerHandle
== NULL
) {
1694 // If ControllerHandle is NULL, the return the cumulative health status of the driver
1696 Status
= DriverHealth
->GetHealthStatus (DriverHealth
, NULL
, NULL
, HealthStatus
, NULL
, NULL
);
1697 if (*HealthStatus
== EfiDriverHealthStatusHealthy
) {
1699 // Add the driver health related information into the list
1701 DriverHealthInfo
= AllocateZeroPool (sizeof (DRIVER_HEALTH_INFO
));
1702 if (DriverHealthInfo
== NULL
) {
1703 return EFI_OUT_OF_RESOURCES
;
1706 DriverHealthInfo
->Signature
= DEVICE_MANAGER_DRIVER_HEALTH_INFO_SIGNATURE
;
1707 DriverHealthInfo
->DriverHandle
= DriverHandle
;
1708 DriverHealthInfo
->ControllerHandle
= NULL
;
1709 DriverHealthInfo
->ChildHandle
= NULL
;
1710 DriverHealthInfo
->HiiHandle
= NULL
;
1711 DriverHealthInfo
->DriverHealth
= DriverHealth
;
1712 DriverHealthInfo
->MessageList
= NULL
;
1713 DriverHealthInfo
->HealthStatus
= *HealthStatus
;
1715 InsertTailList (DriverHealthList
, &DriverHealthInfo
->Link
);
1721 FormHiiHandle
= NULL
;
1724 // Collect the health status with the optional HII message list
1726 Status
= DriverHealth
->GetHealthStatus (DriverHealth
, ControllerHandle
, ChildHandle
, HealthStatus
, &MessageList
, &FormHiiHandle
);
1728 if (EFI_ERROR (Status
)) {
1730 // If the health status could not be retrieved, then return immediately
1736 // Add the driver health related information into the list
1738 DriverHealthInfo
= AllocateZeroPool (sizeof (DRIVER_HEALTH_INFO
));
1739 if (DriverHealthInfo
== NULL
) {
1740 return EFI_OUT_OF_RESOURCES
;
1743 DriverHealthInfo
->Signature
= DEVICE_MANAGER_DRIVER_HEALTH_INFO_SIGNATURE
;
1744 DriverHealthInfo
->DriverHandle
= DriverHandle
;
1745 DriverHealthInfo
->ControllerHandle
= ControllerHandle
;
1746 DriverHealthInfo
->ChildHandle
= ChildHandle
;
1747 DriverHealthInfo
->HiiHandle
= FormHiiHandle
;
1748 DriverHealthInfo
->DriverHealth
= DriverHealth
;
1749 DriverHealthInfo
->MessageList
= MessageList
;
1750 DriverHealthInfo
->HealthStatus
= *HealthStatus
;
1752 InsertTailList (DriverHealthList
, &DriverHealthInfo
->Link
);
1758 Collects all the EFI Driver Health Protocols currently present in the EFI Handle Database,
1759 and queries each EFI Driver Health Protocol to determine if one or more of the controllers
1760 managed by each EFI Driver Health Protocol instance are not healthy.
1762 @param DriverHealthList A Pointer to the list contain all of the platform driver health
1765 @retval EFI_NOT_FOUND No controller in the platform install Driver Health Protocol.
1766 @retval EFI_SUCCESS All the controllers in the platform are healthy.
1767 @retval EFI_OUT_OF_RESOURCES The list of Driver Health Protocol handles can not be retrieved.
1771 GetAllControllersHealthStatus (
1772 IN OUT LIST_ENTRY
*DriverHealthList
1777 EFI_HANDLE
*DriverHealthHandles
;
1778 EFI_DRIVER_HEALTH_PROTOCOL
*DriverHealth
;
1779 EFI_DRIVER_HEALTH_STATUS HealthStatus
;
1780 UINTN DriverHealthIndex
;
1781 EFI_HANDLE
*Handles
;
1783 UINTN ControllerIndex
;
1787 // Initialize local variables
1790 DriverHealthHandles
= NULL
;
1794 HealthStatus
= EfiDriverHealthStatusHealthy
;
1796 Status
= gBS
->LocateHandleBuffer (
1798 &gEfiDriverHealthProtocolGuid
,
1801 &DriverHealthHandles
1804 if (Status
== EFI_NOT_FOUND
|| NumHandles
== 0) {
1806 // If there are no Driver Health Protocols handles, then return EFI_NOT_FOUND
1808 return EFI_NOT_FOUND
;
1811 if (EFI_ERROR (Status
) || DriverHealthHandles
== NULL
) {
1813 // If the list of Driver Health Protocol handles can not be retrieved, then
1814 // return EFI_OUT_OF_RESOURCES
1816 return EFI_OUT_OF_RESOURCES
;
1820 // Check the health status of all controllers in the platform
1821 // Start by looping through all the Driver Health Protocol handles in the handle database
1823 for (DriverHealthIndex
= 0; DriverHealthIndex
< NumHandles
; DriverHealthIndex
++) {
1825 // Skip NULL Driver Health Protocol handles
1827 if (DriverHealthHandles
[DriverHealthIndex
] == NULL
) {
1832 // Retrieve the Driver Health Protocol from DriverHandle
1834 Status
= gBS
->HandleProtocol (
1835 DriverHealthHandles
[DriverHealthIndex
],
1836 &gEfiDriverHealthProtocolGuid
,
1837 (VOID
**)&DriverHealth
1839 if (EFI_ERROR (Status
)) {
1841 // If the Driver Health Protocol can not be retrieved, then skip to the next
1842 // Driver Health Protocol handle
1848 // Check the health of all the controllers managed by a Driver Health Protocol handle
1850 Status
= GetSingleControllerHealthStatus (DriverHealthList
, DriverHealthHandles
[DriverHealthIndex
], NULL
, NULL
, DriverHealth
, &HealthStatus
);
1853 // If Status is an error code, then the health information could not be retrieved, so assume healthy
1854 // and skip to the next Driver Health Protocol handle
1856 if (EFI_ERROR (Status
)) {
1861 // If all the controllers managed by this Driver Health Protocol are healthy, then skip to the next
1862 // Driver Health Protocol handle
1864 if (HealthStatus
== EfiDriverHealthStatusHealthy
) {
1869 // See if the list of all handles in the handle database has been retrieved
1872 if (Handles
== NULL
) {
1874 // Retrieve the list of all handles from the handle database
1876 Status
= gBS
->LocateHandleBuffer (
1883 if (EFI_ERROR (Status
) || Handles
== NULL
) {
1885 // If all the handles in the handle database can not be retrieved, then
1886 // return EFI_OUT_OF_RESOURCES
1888 Status
= EFI_OUT_OF_RESOURCES
;
1893 // Loop through all the controller handles in the handle database
1895 for (ControllerIndex
= 0; ControllerIndex
< HandleCount
; ControllerIndex
++) {
1897 // Skip NULL controller handles
1899 if (Handles
[ControllerIndex
] == NULL
) {
1903 Status
= GetSingleControllerHealthStatus (DriverHealthList
, DriverHealthHandles
[DriverHealthIndex
], Handles
[ControllerIndex
], NULL
, DriverHealth
, &HealthStatus
);
1904 if (EFI_ERROR (Status
)) {
1906 // If Status is an error code, then the health information could not be retrieved, so assume healthy
1908 HealthStatus
= EfiDriverHealthStatusHealthy
;
1912 // If CheckHealthSingleController() returned an error on a terminal state, then do not check the health of child controllers
1914 if (EFI_ERROR (Status
)) {
1919 // Loop through all the child handles in the handle database
1921 for (ChildIndex
= 0; ChildIndex
< HandleCount
; ChildIndex
++) {
1923 // Skip NULL child handles
1925 if (Handles
[ChildIndex
] == NULL
) {
1929 Status
= GetSingleControllerHealthStatus (DriverHealthList
, DriverHealthHandles
[DriverHealthIndex
], Handles
[ControllerIndex
], Handles
[ChildIndex
], DriverHealth
, &HealthStatus
);
1930 if (EFI_ERROR (Status
)) {
1932 // If Status is an error code, then the health information could not be retrieved, so assume healthy
1934 HealthStatus
= EfiDriverHealthStatusHealthy
;
1938 // If CheckHealthSingleController() returned an error on a terminal state, then skip to the next child
1940 if (EFI_ERROR (Status
)) {
1947 Status
= EFI_SUCCESS
;
1950 if (Handles
!= NULL
) {
1951 gBS
->FreePool (Handles
);
1953 if (DriverHealthHandles
!= NULL
) {
1954 gBS
->FreePool (DriverHealthHandles
);
1962 Check the healthy status of the platform, this function will return immediately while found one driver
1963 in the platform are not healthy.
1965 @retval FALSE at least one driver in the platform are not healthy.
1966 @retval TRUE No controller install Driver Health Protocol,
1967 or all controllers in the platform are in healthy status.
1970 PlaformHealthStatusCheck (
1974 EFI_DRIVER_HEALTH_STATUS HealthStatus
;
1978 EFI_HANDLE
*DriverHealthHandles
;
1979 EFI_DRIVER_HEALTH_PROTOCOL
*DriverHealth
;
1983 // Initialize local variables
1985 DriverHealthHandles
= NULL
;
1986 DriverHealth
= NULL
;
1988 HealthStatus
= EfiDriverHealthStatusHealthy
;
1990 Status
= gBS
->LocateHandleBuffer (
1992 &gEfiDriverHealthProtocolGuid
,
1995 &DriverHealthHandles
1998 // There are no handles match the search for Driver Health Protocol has been installed.
2000 if (Status
== EFI_NOT_FOUND
) {
2004 // Assume all modules are healthy.
2009 // Found one or more Handles.
2011 if (!EFI_ERROR (Status
)) {
2012 for (Index
= 0; Index
< NoHandles
; Index
++) {
2013 Status
= gBS
->HandleProtocol (
2014 DriverHealthHandles
[Index
],
2015 &gEfiDriverHealthProtocolGuid
,
2016 (VOID
**) &DriverHealth
2018 if (!EFI_ERROR (Status
)) {
2019 Status
= DriverHealth
->GetHealthStatus (
2029 // Get the healthy status of the module
2031 if (!EFI_ERROR (Status
)) {
2032 if (HealthStatus
!= EfiDriverHealthStatusHealthy
) {
2034 // Return immediately one driver's status not in healthy.
2045 Processes a single controller using the EFI Driver Health Protocol associated with
2046 that controller. This algorithm continues to query the GetHealthStatus() service until
2047 one of the legal terminal states of the EFI Driver Health Protocol is reached. This may
2048 require the processing of HII Messages, HII Form, and invocation of repair operations.
2050 @param DriverHealth A pointer to the EFI_DRIVER_HEALTH_PROTOCOL instance.
2051 @param ControllerHandle The class guid specifies which form set will be displayed.
2052 @param ChildHandle The handle of the child controller to retrieve the health
2053 status on. This is an optional parameter that may be NULL.
2054 @param HealthStatus The health status of the controller.
2055 @param MessageList An array of warning or error messages associated
2056 with the controller specified by ControllerHandle and
2057 ChildHandle. This is an optional parameter that may be NULL.
2058 @param FormHiiHandle The HII handle for an HII form associated with the
2059 controller specified by ControllerHandle and ChildHandle.
2060 @param RebootRequired Indicate whether a reboot is required to repair the controller.
2063 ProcessSingleControllerHealth (
2064 IN EFI_DRIVER_HEALTH_PROTOCOL
*DriverHealth
,
2065 IN EFI_HANDLE ControllerHandle
, OPTIONAL
2066 IN EFI_HANDLE ChildHandle
, OPTIONAL
2067 IN EFI_DRIVER_HEALTH_STATUS HealthStatus
,
2068 IN EFI_DRIVER_HEALTH_HII_MESSAGE
**MessageList
, OPTIONAL
2069 IN EFI_HII_HANDLE FormHiiHandle
,
2070 IN OUT BOOLEAN
*RebootRequired
2074 EFI_DRIVER_HEALTH_STATUS LocalHealthStatus
;
2076 LocalHealthStatus
= HealthStatus
;
2078 // If the module need to be repaired or reconfiguration, will process it until
2079 // reach a terminal status. The status from EfiDriverHealthStatusRepairRequired after repair
2080 // will be in (Health, Failed, Configuration Required).
2082 while(LocalHealthStatus
== EfiDriverHealthStatusConfigurationRequired
||
2083 LocalHealthStatus
== EfiDriverHealthStatusRepairRequired
) {
2085 if (LocalHealthStatus
== EfiDriverHealthStatusRepairRequired
) {
2086 Status
= DriverHealth
->Repair (
2094 // Via a form of the driver need to do configuration provided to process of status in
2095 // EfiDriverHealthStatusConfigurationRequired. The status after configuration should be in
2096 // (Healthy, Reboot Required, Failed, Reconnect Required, Repair Required).
2098 if (LocalHealthStatus
== EfiDriverHealthStatusConfigurationRequired
) {
2099 if (FormHiiHandle
!= NULL
) {
2100 Status
= gFormBrowser2
->SendForm (
2104 &gEfiHiiDriverHealthFormsetGuid
,
2109 ASSERT( !EFI_ERROR (Status
));
2112 // Exit the loop in case no FormHiiHandle is supplied to prevent dead-loop
2118 Status
= DriverHealth
->GetHealthStatus (
2126 ASSERT_EFI_ERROR (Status
);
2128 if (*MessageList
!= NULL
) {
2129 ProcessMessages (*MessageList
);
2134 // Health status in {Healthy, Failed} may also have Messages need to process
2136 if (LocalHealthStatus
== EfiDriverHealthStatusHealthy
|| LocalHealthStatus
== EfiDriverHealthStatusFailed
) {
2137 if (*MessageList
!= NULL
) {
2138 ProcessMessages (*MessageList
);
2142 // Check for RebootRequired or ReconnectRequired
2144 if (LocalHealthStatus
== EfiDriverHealthStatusRebootRequired
) {
2145 *RebootRequired
= TRUE
;
2149 // Do reconnect if need.
2151 if (LocalHealthStatus
== EfiDriverHealthStatusReconnectRequired
) {
2152 Status
= gBS
->DisconnectController (ControllerHandle
, NULL
, NULL
);
2153 if (EFI_ERROR (Status
)) {
2155 // Disconnect failed. Need to promote reconnect to a reboot.
2157 *RebootRequired
= TRUE
;
2159 gBS
->ConnectController (ControllerHandle
, NULL
, NULL
, TRUE
);
2166 Reports the progress of a repair operation.
2168 @param[in] Value A value between 0 and Limit that identifies the current
2169 progress of the repair operation.
2171 @param[in] Limit The maximum value of Value for the current repair operation.
2172 For example, a driver that wants to specify progress in
2173 percent would use a Limit value of 100.
2175 @retval EFI_SUCCESS The progress of a repair operation is reported successfully.
2188 Print(L
"Repair Progress Undefined\n\r");
2190 Percent
= Value
* 100 / Limit
;
2191 Print(L
"Repair Progress = %3d%%\n\r", Percent
);
2197 Processes a set of messages returned by the GetHealthStatus ()
2198 service of the EFI Driver Health Protocol
2200 @param MessageList The MessageList point to messages need to processed.
2205 IN EFI_DRIVER_HEALTH_HII_MESSAGE
*MessageList
2209 EFI_STRING MessageString
;
2211 for (MessageIndex
= 0;
2212 MessageList
[MessageIndex
].HiiHandle
!= NULL
;
2215 MessageString
= HiiGetString (
2216 MessageList
[MessageIndex
].HiiHandle
,
2217 MessageList
[MessageIndex
].StringId
,
2220 if (MessageString
!= NULL
) {
2222 // User can customize the output. Just simply print out the MessageString like below.
2223 // Also can use the HiiHandle to display message on the front page.
2225 // Print(L"%s\n",MessageString);
2226 // gBS->Stall (100000);
2233 Repair the whole platform.
2235 This function is the main entry for user choose "Repair All" in the front page.
2236 It will try to do recovery job till all the driver health protocol installed modules
2237 reach a terminal state.
2239 @param DriverHealthList A Pointer to the list contain all of the platform driver health
2245 IN LIST_ENTRY
*DriverHealthList
2248 DRIVER_HEALTH_INFO
*DriverHealthInfo
;
2250 BOOLEAN RebootRequired
;
2252 ASSERT (DriverHealthList
!= NULL
);
2254 RebootRequired
= FALSE
;
2256 for ( Link
= GetFirstNode (DriverHealthList
)
2257 ; !IsNull (DriverHealthList
, Link
)
2258 ; Link
= GetNextNode (DriverHealthList
, Link
)
2260 DriverHealthInfo
= DEVICE_MANAGER_HEALTH_INFO_FROM_LINK (Link
);
2262 // Do driver health status operation by each link node
2264 ASSERT (DriverHealthInfo
!= NULL
);
2266 ProcessSingleControllerHealth (
2267 DriverHealthInfo
->DriverHealth
,
2268 DriverHealthInfo
->ControllerHandle
,
2269 DriverHealthInfo
->ChildHandle
,
2270 DriverHealthInfo
->HealthStatus
,
2271 &(DriverHealthInfo
->MessageList
),
2272 DriverHealthInfo
->HiiHandle
,
2277 if (RebootRequired
) {
2278 gRT
->ResetSystem (EfiResetWarm
, EFI_SUCCESS
, 0, NULL
);
2284 Select the best matching language according to front page policy for best user experience.
2286 This function supports both ISO 639-2 and RFC 4646 language codes, but language
2287 code types may not be mixed in a single call to this function.
2289 @param SupportedLanguages A pointer to a Null-terminated ASCII string that
2290 contains a set of language codes in the format
2291 specified by Iso639Language.
2292 @param Iso639Language If TRUE, then all language codes are assumed to be
2293 in ISO 639-2 format. If FALSE, then all language
2294 codes are assumed to be in RFC 4646 language format.
2296 @retval NULL The best matching language could not be found in SupportedLanguages.
2297 @retval NULL There are not enough resources available to return the best matching
2299 @retval Other A pointer to a Null-terminated ASCII string that is the best matching
2300 language in SupportedLanguages.
2303 DriverHealthSelectBestLanguage (
2304 IN CHAR8
*SupportedLanguages
,
2305 IN BOOLEAN Iso639Language
2308 CHAR8
*LanguageVariable
;
2309 CHAR8
*BestLanguage
;
2311 GetEfiGlobalVariable2 (Iso639Language
? L
"Lang" : L
"PlatformLang", (VOID
**)&LanguageVariable
, NULL
);
2313 BestLanguage
= GetBestLanguage(
2316 (LanguageVariable
!= NULL
) ? LanguageVariable
: "",
2317 Iso639Language
? "eng" : "en-US",
2320 if (LanguageVariable
!= NULL
) {
2321 FreePool (LanguageVariable
);
2324 return BestLanguage
;
2331 This is an internal worker function to get the Component Name (2) protocol interface
2332 and the language it supports.
2334 @param ProtocolGuid A pointer to an EFI_GUID. It points to Component Name (2) protocol GUID.
2335 @param DriverBindingHandle The handle on which the Component Name (2) protocol instance is retrieved.
2336 @param ComponentName A pointer to the Component Name (2) protocol interface.
2337 @param SupportedLanguage The best suitable language that matches the SupportedLangues interface for the
2338 located Component Name (2) instance.
2340 @retval EFI_SUCCESS The Component Name (2) protocol instance is successfully located and we find
2341 the best matching language it support.
2342 @retval EFI_UNSUPPORTED The input Language is not supported by the Component Name (2) protocol.
2343 @retval Other Some error occurs when locating Component Name (2) protocol instance or finding
2344 the supported language.
2348 GetComponentNameWorker (
2349 IN EFI_GUID
*ProtocolGuid
,
2350 IN EFI_HANDLE DriverBindingHandle
,
2351 OUT EFI_COMPONENT_NAME_PROTOCOL
**ComponentName
,
2352 OUT CHAR8
**SupportedLanguage
2358 // Locate Component Name (2) protocol on the driver binging handle.
2360 Status
= gBS
->OpenProtocol (
2361 DriverBindingHandle
,
2363 (VOID
**) ComponentName
,
2366 EFI_OPEN_PROTOCOL_GET_PROTOCOL
2368 if (EFI_ERROR (Status
)) {
2373 // Apply shell policy to select the best language.
2375 *SupportedLanguage
= DriverHealthSelectBestLanguage (
2376 (*ComponentName
)->SupportedLanguages
,
2377 (BOOLEAN
) (ProtocolGuid
== &gEfiComponentNameProtocolGuid
)
2379 if (*SupportedLanguage
== NULL
) {
2380 Status
= EFI_UNSUPPORTED
;
2388 This is an internal worker function to get driver name from Component Name (2) protocol interface.
2391 @param ProtocolGuid A pointer to an EFI_GUID. It points to Component Name (2) protocol GUID.
2392 @param DriverBindingHandle The handle on which the Component Name (2) protocol instance is retrieved.
2393 @param DriverName A pointer to the Unicode string to return. This Unicode string is the name
2394 of the driver specified by This.
2396 @retval EFI_SUCCESS The driver name is successfully retrieved from Component Name (2) protocol
2398 @retval Other The driver name cannot be retrieved from Component Name (2) protocol
2403 GetDriverNameWorker (
2404 IN EFI_GUID
*ProtocolGuid
,
2405 IN EFI_HANDLE DriverBindingHandle
,
2406 OUT CHAR16
**DriverName
2410 CHAR8
*BestLanguage
;
2411 EFI_COMPONENT_NAME_PROTOCOL
*ComponentName
;
2414 // Retrieve Component Name (2) protocol instance on the driver binding handle and
2415 // find the best language this instance supports.
2417 Status
= GetComponentNameWorker (
2419 DriverBindingHandle
,
2423 if (EFI_ERROR (Status
)) {
2428 // Get the driver name from Component Name (2) protocol instance on the driver binging handle.
2430 Status
= ComponentName
->GetDriverName (
2435 FreePool (BestLanguage
);
2442 This function gets driver name from Component Name 2 protocol interface and Component Name protocol interface
2443 in turn. It first tries UEFI 2.0 Component Name 2 protocol interface and try to get the driver name.
2444 If the attempt fails, it then gets the driver name from EFI 1.1 Component Name protocol for backward
2445 compatibility support.
2447 @param DriverBindingHandle The handle on which the Component Name (2) protocol instance is retrieved.
2448 @param DriverName A pointer to the Unicode string to return. This Unicode string is the name
2449 of the driver specified by This.
2451 @retval EFI_SUCCESS The driver name is successfully retrieved from Component Name (2) protocol
2453 @retval Other The driver name cannot be retrieved from Component Name (2) protocol
2458 DriverHealthGetDriverName (
2459 IN EFI_HANDLE DriverBindingHandle
,
2460 OUT CHAR16
**DriverName
2466 // Get driver name from UEFI 2.0 Component Name 2 protocol interface.
2468 Status
= GetDriverNameWorker (&gEfiComponentName2ProtocolGuid
, DriverBindingHandle
, DriverName
);
2469 if (EFI_ERROR (Status
)) {
2471 // If it fails to get the driver name from Component Name protocol interface, we should fall back on
2472 // EFI 1.1 Component Name protocol interface.
2474 Status
= GetDriverNameWorker (&gEfiComponentNameProtocolGuid
, DriverBindingHandle
, DriverName
);
2483 This function gets controller name from Component Name 2 protocol interface and Component Name protocol interface
2484 in turn. It first tries UEFI 2.0 Component Name 2 protocol interface and try to get the controller name.
2485 If the attempt fails, it then gets the controller name from EFI 1.1 Component Name protocol for backward
2486 compatibility support.
2488 @param ProtocolGuid A pointer to an EFI_GUID. It points to Component Name (2) protocol GUID.
2489 @param DriverBindingHandle The handle on which the Component Name (2) protocol instance is retrieved.
2490 @param ControllerHandle The handle of a controller that the driver specified by This is managing.
2491 This handle specifies the controller whose name is to be returned.
2492 @param ChildHandle The handle of the child controller to retrieve the name of. This is an
2493 optional parameter that may be NULL. It will be NULL for device drivers.
2494 It will also be NULL for bus drivers that attempt to retrieve the name
2495 of the bus controller. It will not be NULL for a bus driver that attempts
2496 to retrieve the name of a child controller.
2497 @param ControllerName A pointer to the Unicode string to return. This Unicode string
2498 is the name of the controller specified by ControllerHandle and ChildHandle.
2500 @retval EFI_SUCCESS The controller name is successfully retrieved from Component Name (2) protocol
2502 @retval Other The controller name cannot be retrieved from Component Name (2) protocol.
2506 GetControllerNameWorker (
2507 IN EFI_GUID
*ProtocolGuid
,
2508 IN EFI_HANDLE DriverBindingHandle
,
2509 IN EFI_HANDLE ControllerHandle
,
2510 IN EFI_HANDLE ChildHandle
,
2511 OUT CHAR16
**ControllerName
2515 CHAR8
*BestLanguage
;
2516 EFI_COMPONENT_NAME_PROTOCOL
*ComponentName
;
2519 // Retrieve Component Name (2) protocol instance on the driver binding handle and
2520 // find the best language this instance supports.
2522 Status
= GetComponentNameWorker (
2524 DriverBindingHandle
,
2528 if (EFI_ERROR (Status
)) {
2533 // Get the controller name from Component Name (2) protocol instance on the driver binging handle.
2535 Status
= ComponentName
->GetControllerName (
2542 FreePool (BestLanguage
);
2549 This function gets controller name from Component Name 2 protocol interface and Component Name protocol interface
2550 in turn. It first tries UEFI 2.0 Component Name 2 protocol interface and try to get the controller name.
2551 If the attempt fails, it then gets the controller name from EFI 1.1 Component Name protocol for backward
2552 compatibility support.
2554 @param DriverBindingHandle The handle on which the Component Name (2) protocol instance is retrieved.
2555 @param ControllerHandle The handle of a controller that the driver specified by This is managing.
2556 This handle specifies the controller whose name is to be returned.
2557 @param ChildHandle The handle of the child controller to retrieve the name of. This is an
2558 optional parameter that may be NULL. It will be NULL for device drivers.
2559 It will also be NULL for bus drivers that attempt to retrieve the name
2560 of the bus controller. It will not be NULL for a bus driver that attempts
2561 to retrieve the name of a child controller.
2562 @param ControllerName A pointer to the Unicode string to return. This Unicode string
2563 is the name of the controller specified by ControllerHandle and ChildHandle.
2565 @retval EFI_SUCCESS The controller name is successfully retrieved from Component Name (2) protocol
2567 @retval Other The controller name cannot be retrieved from Component Name (2) protocol.
2571 DriverHealthGetControllerName (
2572 IN EFI_HANDLE DriverBindingHandle
,
2573 IN EFI_HANDLE ControllerHandle
,
2574 IN EFI_HANDLE ChildHandle
,
2575 OUT CHAR16
**ControllerName
2581 // Get controller name from UEFI 2.0 Component Name 2 protocol interface.
2583 Status
= GetControllerNameWorker (
2584 &gEfiComponentName2ProtocolGuid
,
2585 DriverBindingHandle
,
2590 if (EFI_ERROR (Status
)) {
2592 // If it fails to get the controller name from Component Name protocol interface, we should fall back on
2593 // EFI 1.1 Component Name protocol interface.
2595 Status
= GetControllerNameWorker (
2596 &gEfiComponentNameProtocolGuid
,
2597 DriverBindingHandle
,