+ if (gCallbackKey == DEVICE_MANAGER_KEY_DRIVER_HEALTH) {\r
+ CallDriverHealth ();\r
+ //\r
+ // Force return to Device Manager\r
+ //\r
+ gCallbackKey = FRONT_PAGE_KEY_DEVICE_MANAGER;\r
+ goto Done;\r
+ }\r
+\r
+ //\r
+ // Enter from device manager and into the network device list.\r
+ //\r
+ if (gCallbackKey == QUESTION_NETWORK_DEVICE_ID) {\r
+ mNextShowFormId = NETWORK_DEVICE_LIST_FORM_ID;\r
+ gCallbackKey = FRONT_PAGE_KEY_DEVICE_MANAGER;\r
+ goto Done;\r
+ }\r
+\r
+ //\r
+ // In this case, go from the network device list to the specify device.\r
+ //\r
+ if ((gCallbackKey < MAX_KEY_SECTION_LEN + NETWORK_DEVICE_LIST_KEY_OFFSET ) && (gCallbackKey >= NETWORK_DEVICE_LIST_KEY_OFFSET)) {\r
+ mNextShowFormId = NETWORK_DEVICE_FORM_ID;\r
+ gCallbackKey = FRONT_PAGE_KEY_DEVICE_MANAGER;\r
+ goto Done;\r
+ }\r
+\r
+ //\r
+ // Select the ESC, the gCallbackKey == 0.\r
+ //\r
+ if(mNextShowFormId - 1 < DEVICE_MANAGER_FORM_ID) {\r
+ mNextShowFormId = DEVICE_MANAGER_FORM_ID;\r
+ } else {\r
+ mNextShowFormId = (UINT16) (mNextShowFormId - 1);\r
+ gCallbackKey = FRONT_PAGE_KEY_DEVICE_MANAGER;\r
+ }\r
+\r
+Done:\r
+ //\r
+ // Remove our packagelist from HII database.\r
+ //\r
+ HiiRemovePackages (HiiHandle);\r
+ gDeviceManagerPrivate.HiiHandle = NULL;\r
+\r
+ HiiFreeOpCodeHandle (StartOpCodeHandle);\r
+ HiiFreeOpCodeHandle (EndOpCodeHandle);\r
+ FreePool (HiiHandles);\r
+\r
+ return Status;\r
+}\r
+\r
+/**\r
+ This function is invoked if user selected a interactive opcode from Driver Health's\r
+ Formset. The decision by user is saved to gCallbackKey for later processing.\r
+\r
+ @param This Points to the EFI_HII_CONFIG_ACCESS_PROTOCOL.\r
+ @param Action Specifies the type of action taken by the browser.\r
+ @param QuestionId A unique value which is sent to the original exporting driver\r
+ so that it can identify the type of data to expect.\r
+ @param Type The type of value for the question.\r
+ @param Value A pointer to the data being sent to the original exporting driver.\r
+ @param ActionRequest On return, points to the action requested by the callback function.\r
+\r
+ @retval EFI_SUCCESS The callback successfully handled the action.\r
+ @retval EFI_INVALID_PARAMETER The setup browser call this function with invalid parameters.\r
+\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+DriverHealthCallback (\r
+ IN CONST EFI_HII_CONFIG_ACCESS_PROTOCOL *This,\r
+ IN EFI_BROWSER_ACTION Action,\r
+ IN EFI_QUESTION_ID QuestionId,\r
+ IN UINT8 Type,\r
+ IN EFI_IFR_TYPE_VALUE *Value,\r
+ OUT EFI_BROWSER_ACTION_REQUEST *ActionRequest\r
+ )\r
+{\r
+ if (Action == EFI_BROWSER_ACTION_CHANGED) {\r
+ if ((Value == NULL) || (ActionRequest == NULL)) {\r
+ return EFI_INVALID_PARAMETER;\r
+ }\r
+\r
+ gCallbackKey = QuestionId;\r
+\r
+ //\r
+ // Request to exit SendForm(), so as to switch to selected form\r
+ //\r
+ *ActionRequest = EFI_BROWSER_ACTION_REQUEST_EXIT;\r
+\r
+ return EFI_SUCCESS;\r
+ }\r
+\r
+ //\r
+ // All other action return unsupported.\r
+ //\r
+ return EFI_UNSUPPORTED;\r
+}\r
+\r
+/**\r
+ Collect and display the platform's driver health relative information, allow user to do interactive \r
+ operation while the platform is unhealthy.\r
+\r
+ This function display a form which divided into two parts. The one list all modules which has installed \r
+ driver health protocol. The list usually contain driver name, controller name, and it's health info.\r
+ While the driver name can't be retrieved, will use device path as backup. The other part of the form provide\r
+ a choice to the user to repair all platform.\r
+\r
+**/\r
+VOID\r
+CallDriverHealth (\r
+ VOID\r
+ )\r
+{\r
+ EFI_STATUS Status; \r
+ EFI_HII_HANDLE HiiHandle;\r
+ EFI_BROWSER_ACTION_REQUEST ActionRequest;\r
+ EFI_IFR_GUID_LABEL *StartLabel;\r
+ EFI_IFR_GUID_LABEL *StartLabelRepair;\r
+ EFI_IFR_GUID_LABEL *EndLabel;\r
+ EFI_IFR_GUID_LABEL *EndLabelRepair;\r
+ VOID *StartOpCodeHandle;\r
+ VOID *EndOpCodeHandle;\r
+ VOID *StartOpCodeHandleRepair;\r
+ VOID *EndOpCodeHandleRepair;\r
+ UINTN Index;\r
+ EFI_STRING_ID Token;\r
+ EFI_STRING_ID TokenHelp;\r
+ EFI_STRING String;\r
+ EFI_STRING TmpString;\r
+ EFI_STRING DriverName;\r
+ EFI_STRING ControllerName;\r
+ LIST_ENTRY DriverHealthList;\r
+ DRIVER_HEALTH_INFO *DriverHealthInfo;\r
+ LIST_ENTRY *Link;\r
+ EFI_DEVICE_PATH_PROTOCOL *DriverDevicePath;\r
+ BOOLEAN RebootRequired;\r
+\r
+ Index = 0;\r
+ DriverHealthInfo = NULL; \r
+ DriverDevicePath = NULL;\r
+ InitializeListHead (&DriverHealthList);\r
+\r
+ HiiHandle = gDeviceManagerPrivate.DriverHealthHiiHandle;\r
+ if (HiiHandle == NULL) {\r
+ //\r
+ // Publish Driver Health HII data.\r
+ //\r
+ HiiHandle = HiiAddPackages (\r
+ &gDeviceManagerFormSetGuid,\r
+ gDeviceManagerPrivate.DriverHealthHandle,\r
+ DriverHealthVfrBin,\r
+ BdsDxeStrings,\r
+ NULL\r
+ );\r
+ if (HiiHandle == NULL) {\r
+ return;\r
+ }\r
+\r
+ gDeviceManagerPrivate.DriverHealthHiiHandle = HiiHandle;\r
+ }\r
+\r
+ //\r
+ // Allocate space for creation of UpdateData Buffer\r
+ //\r
+ StartOpCodeHandle = HiiAllocateOpCodeHandle ();\r
+ ASSERT (StartOpCodeHandle != NULL);\r
+\r
+ EndOpCodeHandle = HiiAllocateOpCodeHandle ();\r
+ ASSERT (EndOpCodeHandle != NULL);\r
+\r
+ StartOpCodeHandleRepair = HiiAllocateOpCodeHandle ();\r
+ ASSERT (StartOpCodeHandleRepair != NULL);\r
+\r
+ EndOpCodeHandleRepair = HiiAllocateOpCodeHandle ();\r
+ ASSERT (EndOpCodeHandleRepair != NULL);\r
+\r
+ //\r
+ // Create Hii Extend Label OpCode as the start opcode\r
+ //\r
+ StartLabel = (EFI_IFR_GUID_LABEL *) HiiCreateGuidOpCode (StartOpCodeHandle, &gEfiIfrTianoGuid, NULL, sizeof (EFI_IFR_GUID_LABEL));\r
+ StartLabel->ExtendOpCode = EFI_IFR_EXTEND_OP_LABEL;\r
+ StartLabel->Number = LABEL_DRIVER_HEALTH;\r
+\r
+ //\r
+ // Create Hii Extend Label OpCode as the start opcode\r
+ //\r
+ StartLabelRepair = (EFI_IFR_GUID_LABEL *) HiiCreateGuidOpCode (StartOpCodeHandleRepair, &gEfiIfrTianoGuid, NULL, sizeof (EFI_IFR_GUID_LABEL));\r
+ StartLabelRepair->ExtendOpCode = EFI_IFR_EXTEND_OP_LABEL;\r
+ StartLabelRepair->Number = LABEL_DRIVER_HEALTH_REAPIR_ALL;\r
+\r
+ //\r
+ // Create Hii Extend Label OpCode as the end opcode\r
+ //\r
+ EndLabel = (EFI_IFR_GUID_LABEL *) HiiCreateGuidOpCode (EndOpCodeHandle, &gEfiIfrTianoGuid, NULL, sizeof (EFI_IFR_GUID_LABEL));\r
+ EndLabel->ExtendOpCode = EFI_IFR_EXTEND_OP_LABEL;\r
+ EndLabel->Number = LABEL_DRIVER_HEALTH_END;\r
+\r
+ //\r
+ // Create Hii Extend Label OpCode as the end opcode\r
+ //\r
+ EndLabelRepair = (EFI_IFR_GUID_LABEL *) HiiCreateGuidOpCode (EndOpCodeHandleRepair, &gEfiIfrTianoGuid, NULL, sizeof (EFI_IFR_GUID_LABEL));\r
+ EndLabelRepair->ExtendOpCode = EFI_IFR_EXTEND_OP_LABEL;\r
+ EndLabelRepair->Number = LABEL_DRIVER_HEALTH_REAPIR_ALL_END;\r
+\r
+ HiiCreateSubTitleOpCode (StartOpCodeHandle, STRING_TOKEN (STR_DH_STATUS_LIST), 0, 0, 1);\r
+\r
+ Status = GetAllControllersHealthStatus (&DriverHealthList);\r
+ ASSERT (Status != EFI_OUT_OF_RESOURCES);\r
+\r
+ Link = GetFirstNode (&DriverHealthList);\r
+\r
+ while (!IsNull (&DriverHealthList, Link)) { \r
+ DriverHealthInfo = DEVICE_MANAGER_HEALTH_INFO_FROM_LINK (Link);\r
+ \r
+ //\r
+ // Assume no line strings is longer than 512 bytes.\r
+ //\r
+ String = (EFI_STRING) AllocateZeroPool (0x200);\r
+ ASSERT (String != NULL);\r
+\r
+ Status = DriverHealthGetDriverName (DriverHealthInfo->DriverHandle, &DriverName);\r
+ if (EFI_ERROR (Status)) {\r
+ //\r
+ // Can not get the Driver name, so use the Device path\r
+ //\r
+ DriverDevicePath = DevicePathFromHandle (DriverHealthInfo->DriverHandle);\r
+ DriverName = DevicePathToStr (DriverDevicePath);\r
+ }\r
+ //\r
+ // Add the Driver name & Controller name into FormSetTitle string\r
+ // \r
+ StrnCat (String, DriverName, StrLen (DriverName));\r
+\r
+\r
+ Status = DriverHealthGetControllerName (\r
+ DriverHealthInfo->DriverHandle, \r
+ DriverHealthInfo->ControllerHandle, \r
+ DriverHealthInfo->ChildHandle, \r
+ &ControllerName\r
+ );\r
+\r
+ if (!EFI_ERROR (Status)) {\r
+ //\r
+ // Can not get the Controller name, just let it empty.\r
+ //\r
+ StrnCat (String, L" ", StrLen (L" "));\r
+ StrnCat (String, ControllerName, StrLen (ControllerName)); \r
+ }\r
+ \r
+ //\r
+ // Add the message of the Module itself provided after the string item.\r
+ //\r
+ if ((DriverHealthInfo->MessageList != NULL) && (DriverHealthInfo->MessageList->StringId != 0)) {\r
+ StrnCat (String, L" ", StrLen (L" "));\r
+ TmpString = HiiGetString (\r
+ DriverHealthInfo->MessageList->HiiHandle, \r
+ DriverHealthInfo->MessageList->StringId, \r
+ NULL\r
+ );\r
+ } else {\r
+ //\r
+ // Update the string will be displayed base on the driver's health status\r
+ //\r
+ switch(DriverHealthInfo->HealthStatus) {\r
+ case EfiDriverHealthStatusRepairRequired:\r
+ TmpString = GetStringById (STRING_TOKEN (STR_REPAIR_REQUIRED));\r
+ break;\r
+ case EfiDriverHealthStatusConfigurationRequired:\r
+ TmpString = GetStringById (STRING_TOKEN (STR_CONFIGURATION_REQUIRED));\r
+ break;\r
+ case EfiDriverHealthStatusFailed:\r
+ TmpString = GetStringById (STRING_TOKEN (STR_OPERATION_FAILED));\r
+ break;\r
+ case EfiDriverHealthStatusReconnectRequired:\r
+ TmpString = GetStringById (STRING_TOKEN (STR_RECONNECT_REQUIRED));\r
+ break;\r
+ case EfiDriverHealthStatusRebootRequired:\r
+ TmpString = GetStringById (STRING_TOKEN (STR_REBOOT_REQUIRED));\r
+ break;\r
+ default:\r
+ TmpString = GetStringById (STRING_TOKEN (STR_DRIVER_HEALTH_HEALTHY));\r
+ break;\r
+ }\r
+ }\r
+\r
+ ASSERT (TmpString != NULL);\r
+ StrCat (String, TmpString);\r
+ FreePool (TmpString);\r
+\r
+ Token = HiiSetString (HiiHandle, 0, String, NULL);\r
+ FreePool (String);\r
+\r
+ TokenHelp = HiiSetString (HiiHandle, 0, GetStringById( STRING_TOKEN (STR_DH_REPAIR_SINGLE_HELP)), NULL);\r
+\r
+ HiiCreateActionOpCode (\r
+ StartOpCodeHandle,\r
+ (EFI_QUESTION_ID) (Index + DRIVER_HEALTH_KEY_OFFSET),\r
+ Token,\r
+ TokenHelp,\r
+ EFI_IFR_FLAG_CALLBACK,\r
+ 0\r
+ );\r
+ Index++;\r
+ Link = GetNextNode (&DriverHealthList, Link);\r
+ }\r
+ \r
+ //\r
+ // Add End Opcode for Subtitle\r
+ // \r
+ HiiCreateEndOpCode (StartOpCodeHandle);\r
+\r
+ HiiCreateSubTitleOpCode (StartOpCodeHandleRepair, STRING_TOKEN (STR_DRIVER_HEALTH_REPAIR_ALL), 0, 0, 1);\r
+ TokenHelp = HiiSetString (HiiHandle, 0, GetStringById( STRING_TOKEN (STR_DH_REPAIR_ALL_HELP)), NULL); \r
+\r
+ if (PlaformHealthStatusCheck ()) {\r
+ //\r
+ // No action need to do for the platform\r
+ //\r
+ Token = HiiSetString (HiiHandle, 0, GetStringById( STRING_TOKEN (STR_DRIVER_HEALTH_ALL_HEALTHY)), NULL);\r
+ HiiCreateActionOpCode (\r
+ StartOpCodeHandleRepair,\r
+ 0,\r
+ Token,\r
+ TokenHelp,\r
+ EFI_IFR_FLAG_READ_ONLY,\r
+ 0\r
+ );\r
+ } else {\r
+ //\r
+ // Create ActionOpCode only while the platform need to do health related operation.\r
+ //\r
+ Token = HiiSetString (HiiHandle, 0, GetStringById( STRING_TOKEN (STR_DH_REPAIR_ALL_TITLE)), NULL);\r
+ HiiCreateActionOpCode (\r
+ StartOpCodeHandleRepair,\r
+ (EFI_QUESTION_ID) DRIVER_HEALTH_REPAIR_ALL_KEY,\r
+ Token,\r
+ TokenHelp,\r
+ EFI_IFR_FLAG_CALLBACK,\r
+ 0\r
+ );\r
+ }\r
+\r
+ HiiCreateEndOpCode (StartOpCodeHandleRepair);\r
+\r
+ Status = HiiUpdateForm (\r
+ HiiHandle,\r
+ &gDriverHealthFormSetGuid,\r
+ DRIVER_HEALTH_FORM_ID,\r
+ StartOpCodeHandle,\r
+ EndOpCodeHandle\r
+ );\r
+ ASSERT (Status != EFI_NOT_FOUND);\r
+ ASSERT (Status != EFI_BUFFER_TOO_SMALL);\r
+\r
+ Status = HiiUpdateForm (\r
+ HiiHandle,\r
+ &gDriverHealthFormSetGuid,\r
+ DRIVER_HEALTH_FORM_ID,\r
+ StartOpCodeHandleRepair,\r
+ EndOpCodeHandleRepair\r
+ );\r
+ ASSERT (Status != EFI_NOT_FOUND);\r
+ ASSERT (Status != EFI_BUFFER_TOO_SMALL);\r
+\r
+ ActionRequest = EFI_BROWSER_ACTION_REQUEST_NONE;\r
+ Status = gFormBrowser2->SendForm (\r
+ gFormBrowser2,\r
+ &HiiHandle,\r
+ 1,\r
+ &gDriverHealthFormSetGuid,\r
+ DRIVER_HEALTH_FORM_ID,\r
+ NULL,\r
+ &ActionRequest\r
+ );\r
+ if (ActionRequest == EFI_BROWSER_ACTION_REQUEST_RESET) {\r
+ EnableResetRequired ();\r
+ }\r
+\r
+ //\r
+ // We will have returned from processing a callback - user either hit ESC to exit, or selected\r
+ // a target to display.\r
+ // Process the diver health status states here.\r
+ // \r
+ if (gCallbackKey >= DRIVER_HEALTH_KEY_OFFSET && gCallbackKey != DRIVER_HEALTH_REPAIR_ALL_KEY) {\r
+ ActionRequest = EFI_BROWSER_ACTION_REQUEST_NONE;\r
+\r
+ Link = GetFirstNode (&DriverHealthList);\r
+ Index = 0;\r
+\r
+ while (!IsNull (&DriverHealthList, Link)) {\r
+ //\r
+ // Got the item relative node in the List\r
+ //\r
+ if (Index == (gCallbackKey - DRIVER_HEALTH_KEY_OFFSET)) { \r
+ DriverHealthInfo = DEVICE_MANAGER_HEALTH_INFO_FROM_LINK (Link);\r
+ //\r
+ // Process the driver's healthy status for the specify module\r
+ //\r
+ RebootRequired = FALSE;\r
+ ProcessSingleControllerHealth (\r
+ DriverHealthInfo->DriverHealth,\r
+ DriverHealthInfo->ControllerHandle, \r
+ DriverHealthInfo->ChildHandle,\r
+ DriverHealthInfo->HealthStatus,\r
+ &(DriverHealthInfo->MessageList),\r
+ DriverHealthInfo->HiiHandle,\r
+ &RebootRequired\r
+ );\r
+ if (RebootRequired) {\r
+ gRT->ResetSystem (EfiResetWarm, EFI_SUCCESS, 0, NULL);\r
+ }\r
+ break;\r
+ }\r
+ Index++;\r
+ Link = GetNextNode (&DriverHealthList, Link);\r
+ }\r
+\r
+ if (ActionRequest == EFI_BROWSER_ACTION_REQUEST_RESET) {\r
+ EnableResetRequired ();\r
+ }\r
+ \r
+ //\r
+ // Force return to the form of Driver Health in Device Manager \r
+ //\r
+ gCallbackKey = DRIVER_HEALTH_RETURN_KEY;\r
+ }\r
+\r
+ //\r
+ // Repair the whole platform\r
+ //\r
+ if (gCallbackKey == DRIVER_HEALTH_REPAIR_ALL_KEY) {\r
+ ActionRequest = EFI_BROWSER_ACTION_REQUEST_NONE;\r
+ \r
+ PlatformRepairAll (&DriverHealthList);\r
+\r
+ gCallbackKey = DRIVER_HEALTH_RETURN_KEY;\r
+ }\r
+ \r
+ //\r
+ // Remove driver health packagelist from HII database.\r
+ //\r
+ HiiRemovePackages (HiiHandle);\r
+ gDeviceManagerPrivate.DriverHealthHiiHandle = NULL;\r
+\r
+ //\r
+ // Free driver health info list\r
+ //\r
+ while (!IsListEmpty (&DriverHealthList)) {\r
+\r
+ Link = GetFirstNode(&DriverHealthList);\r
+ DriverHealthInfo = DEVICE_MANAGER_HEALTH_INFO_FROM_LINK (Link);\r
+ RemoveEntryList (Link);\r
+\r
+ if (DriverHealthInfo->MessageList != NULL) {\r
+ FreePool(DriverHealthInfo->MessageList);\r
+ FreePool (DriverHealthInfo);\r
+ } \r
+ }\r
+\r
+ HiiFreeOpCodeHandle (StartOpCodeHandle);\r
+ HiiFreeOpCodeHandle (EndOpCodeHandle); \r
+ HiiFreeOpCodeHandle (StartOpCodeHandleRepair);\r
+ HiiFreeOpCodeHandle (EndOpCodeHandleRepair); \r
+\r
+ if (gCallbackKey == DRIVER_HEALTH_RETURN_KEY) {\r
+ //\r
+ // Force return to Driver Health Form\r
+ //\r
+ gCallbackKey = DEVICE_MANAGER_KEY_DRIVER_HEALTH;\r
+ CallDriverHealth ();\r
+ }\r
+}\r
+\r
+\r
+/**\r
+ Check the Driver Health status of a single controller and try to process it if not healthy.\r
+\r
+ This function called by CheckAllControllersHealthStatus () function in order to process a specify\r
+ contoller's health state.\r
+\r
+ @param DriverHealthList A Pointer to the list contain all of the platform driver health information. \r
+ @param DriverHandle The handle of driver.\r
+ @param ControllerHandle The class guid specifies which form set will be displayed.\r
+ @param ChildHandle The handle of the child controller to retrieve the health \r
+ status on. This is an optional parameter that may be NULL. \r
+ @param DriverHealth A pointer to the EFI_DRIVER_HEALTH_PROTOCOL instance.\r
+ @param HealthStatus The health status of the controller.\r
+\r
+ @retval EFI_INVALID_PARAMETER HealthStatus or DriverHealth is NULL.\r
+ @retval HealthStatus The Health status of specify controller.\r
+ @retval EFI_OUT_OF_RESOURCES The list of Driver Health Protocol handles can not be retrieved.\r
+ @retval EFI_NOT_FOUND No controller in the platform install Driver Health Protocol.\r
+ @retval EFI_SUCCESS The Health related operation has been taken successfully.\r
+\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+GetSingleControllerHealthStatus (\r
+ IN OUT LIST_ENTRY *DriverHealthList,\r
+ IN EFI_HANDLE DriverHandle,\r
+ IN EFI_HANDLE ControllerHandle, OPTIONAL\r
+ IN EFI_HANDLE ChildHandle, OPTIONAL\r
+ IN EFI_DRIVER_HEALTH_PROTOCOL *DriverHealth,\r
+ IN EFI_DRIVER_HEALTH_STATUS *HealthStatus\r
+ )\r
+{\r
+ EFI_STATUS Status;\r
+ EFI_DRIVER_HEALTH_HII_MESSAGE *MessageList;\r
+ EFI_HII_HANDLE FormHiiHandle;\r
+ DRIVER_HEALTH_INFO *DriverHealthInfo;\r
+\r
+ if (HealthStatus == NULL) {\r
+ //\r
+ // If HealthStatus is NULL, then return EFI_INVALID_PARAMETER\r
+ //\r
+ return EFI_INVALID_PARAMETER;\r
+ }\r
+\r
+ //\r
+ // Assume the HealthStatus is healthy\r
+ //\r
+ *HealthStatus = EfiDriverHealthStatusHealthy;\r
+\r
+ if (DriverHealth == NULL) {\r
+ //\r
+ // If DriverHealth is NULL, then return EFI_INVALID_PARAMETER\r
+ //\r
+ return EFI_INVALID_PARAMETER;\r
+ }\r
+\r
+ if (ControllerHandle == NULL) {\r
+ //\r
+ // If ControllerHandle is NULL, the return the cumulative health status of the driver\r
+ //\r
+ Status = DriverHealth->GetHealthStatus (DriverHealth, NULL, NULL, HealthStatus, NULL, NULL);\r
+ if (*HealthStatus == EfiDriverHealthStatusHealthy) {\r
+ //\r
+ // Add the driver health related information into the list\r
+ //\r
+ DriverHealthInfo = AllocateZeroPool (sizeof (DRIVER_HEALTH_INFO));\r
+ if (DriverHealthInfo == NULL) {\r
+ return EFI_OUT_OF_RESOURCES;\r
+ }\r
+\r
+ DriverHealthInfo->Signature = DEVICE_MANAGER_DRIVER_HEALTH_INFO_SIGNATURE;\r
+ DriverHealthInfo->DriverHandle = DriverHandle;\r
+ DriverHealthInfo->ControllerHandle = NULL;\r
+ DriverHealthInfo->ChildHandle = NULL;\r
+ DriverHealthInfo->HiiHandle = NULL;\r
+ DriverHealthInfo->DriverHealth = DriverHealth;\r
+ DriverHealthInfo->MessageList = NULL;\r
+ DriverHealthInfo->HealthStatus = *HealthStatus;\r
+\r
+ InsertTailList (DriverHealthList, &DriverHealthInfo->Link);\r
+ }\r
+ return Status;\r
+ }\r
+\r
+ MessageList = NULL;\r
+ FormHiiHandle = NULL;\r
+\r
+ //\r
+ // Collect the health status with the optional HII message list\r
+ //\r
+ Status = DriverHealth->GetHealthStatus (DriverHealth, ControllerHandle, ChildHandle, HealthStatus, &MessageList, &FormHiiHandle);\r
+\r
+ if (EFI_ERROR (Status)) {\r
+ //\r
+ // If the health status could not be retrieved, then return immediately\r
+ //\r
+ return Status;\r
+ }\r
+\r
+ //\r
+ // Add the driver health related information into the list\r
+ //\r
+ DriverHealthInfo = AllocateZeroPool (sizeof (DRIVER_HEALTH_INFO));\r
+ if (DriverHealthInfo == NULL) {\r
+ return EFI_OUT_OF_RESOURCES;\r
+ }\r
+\r
+ DriverHealthInfo->Signature = DEVICE_MANAGER_DRIVER_HEALTH_INFO_SIGNATURE; \r
+ DriverHealthInfo->DriverHandle = DriverHandle;\r
+ DriverHealthInfo->ControllerHandle = ControllerHandle;\r
+ DriverHealthInfo->ChildHandle = ChildHandle;\r
+ DriverHealthInfo->HiiHandle = FormHiiHandle;\r
+ DriverHealthInfo->DriverHealth = DriverHealth;\r
+ DriverHealthInfo->MessageList = MessageList;\r
+ DriverHealthInfo->HealthStatus = *HealthStatus;\r
+\r
+ InsertTailList (DriverHealthList, &DriverHealthInfo->Link);\r
+\r
+ return EFI_SUCCESS;\r
+}\r
+\r
+/**\r
+ Collects all the EFI Driver Health Protocols currently present in the EFI Handle Database, \r
+ and queries each EFI Driver Health Protocol to determine if one or more of the controllers \r
+ managed by each EFI Driver Health Protocol instance are not healthy. \r
+\r
+ @param DriverHealthList A Pointer to the list contain all of the platform driver health\r
+ information. \r
+\r
+ @retval EFI_NOT_FOUND No controller in the platform install Driver Health Protocol.\r
+ @retval EFI_SUCCESS All the controllers in the platform are healthy.\r
+ @retval EFI_OUT_OF_RESOURCES The list of Driver Health Protocol handles can not be retrieved.\r
+\r
+**/\r
+EFI_STATUS\r
+GetAllControllersHealthStatus (\r
+ IN OUT LIST_ENTRY *DriverHealthList\r
+ )\r
+{\r
+ EFI_STATUS Status; \r
+ UINTN NumHandles;\r
+ EFI_HANDLE *DriverHealthHandles;\r
+ EFI_DRIVER_HEALTH_PROTOCOL *DriverHealth;\r
+ EFI_DRIVER_HEALTH_STATUS HealthStatus;\r
+ UINTN DriverHealthIndex;\r
+ EFI_HANDLE *Handles;\r
+ UINTN HandleCount;\r
+ UINTN ControllerIndex;\r
+ UINTN ChildIndex;\r
+ \r
+ //\r
+ // Initialize local variables\r
+ //\r
+ Handles = NULL;\r
+ DriverHealthHandles = NULL;\r
+ NumHandles = 0;\r
+ HandleCount = 0;\r
+\r
+ HealthStatus = EfiDriverHealthStatusHealthy;\r
+\r
+ Status = gBS->LocateHandleBuffer (\r
+ ByProtocol,\r
+ &gEfiDriverHealthProtocolGuid,\r
+ NULL,\r
+ &NumHandles,\r
+ &DriverHealthHandles\r
+ );\r
+\r
+ if (Status == EFI_NOT_FOUND || NumHandles == 0) {\r
+ //\r
+ // If there are no Driver Health Protocols handles, then return EFI_NOT_FOUND\r
+ //\r
+ return EFI_NOT_FOUND;\r
+ }\r
+\r
+ if (EFI_ERROR (Status) || DriverHealthHandles == NULL) {\r
+ //\r
+ // If the list of Driver Health Protocol handles can not be retrieved, then \r
+ // return EFI_OUT_OF_RESOURCES\r
+ //\r
+ return EFI_OUT_OF_RESOURCES;\r
+ }\r
+\r
+ //\r
+ // Check the health status of all controllers in the platform\r
+ // Start by looping through all the Driver Health Protocol handles in the handle database\r
+ //\r
+ for (DriverHealthIndex = 0; DriverHealthIndex < NumHandles; DriverHealthIndex++) {\r
+ //\r
+ // Skip NULL Driver Health Protocol handles\r
+ //\r
+ if (DriverHealthHandles[DriverHealthIndex] == NULL) {\r
+ continue;\r
+ }\r
+\r
+ //\r
+ // Retrieve the Driver Health Protocol from DriverHandle\r
+ //\r
+ Status = gBS->HandleProtocol ( \r
+ DriverHealthHandles[DriverHealthIndex],\r
+ &gEfiDriverHealthProtocolGuid,\r
+ (VOID **)&DriverHealth\r
+ );\r
+ if (EFI_ERROR (Status)) {\r
+ //\r
+ // If the Driver Health Protocol can not be retrieved, then skip to the next\r
+ // Driver Health Protocol handle\r
+ //\r
+ continue;\r
+ }\r
+\r
+ //\r
+ // Check the health of all the controllers managed by a Driver Health Protocol handle\r
+ //\r
+ Status = GetSingleControllerHealthStatus (DriverHealthList, DriverHealthHandles[DriverHealthIndex], NULL, NULL, DriverHealth, &HealthStatus);\r
+\r
+ //\r
+ // If Status is an error code, then the health information could not be retrieved, so assume healthy\r
+ // and skip to the next Driver Health Protocol handle\r
+ //\r
+ if (EFI_ERROR (Status)) {\r
+ continue;\r
+ }\r
+\r
+ //\r
+ // If all the controllers managed by this Driver Health Protocol are healthy, then skip to the next \r
+ // Driver Health Protocol handle\r
+ //\r
+ if (HealthStatus == EfiDriverHealthStatusHealthy) {\r
+ continue;\r
+ }\r
+\r
+ //\r
+ // See if the list of all handles in the handle database has been retrieved\r
+ //\r
+ //\r
+ if (Handles == NULL) {\r
+ //\r
+ // Retrieve the list of all handles from the handle database\r
+ //\r
+ Status = gBS->LocateHandleBuffer (\r
+ AllHandles,\r
+ NULL,\r
+ NULL,\r
+ &HandleCount,\r
+ &Handles\r
+ );\r
+ if (EFI_ERROR (Status) || Handles == NULL) {\r
+ //\r
+ // If all the handles in the handle database can not be retrieved, then \r
+ // return EFI_OUT_OF_RESOURCES\r
+ //\r
+ Status = EFI_OUT_OF_RESOURCES;\r
+ goto Done;\r
+ }\r
+ }\r
+ //\r
+ // Loop through all the controller handles in the handle database\r
+ //\r
+ for (ControllerIndex = 0; ControllerIndex < HandleCount; ControllerIndex++) {\r
+ //\r
+ // Skip NULL controller handles\r
+ //\r
+ if (Handles[ControllerIndex] == NULL) {\r
+ continue;\r
+ }\r
+\r
+ Status = GetSingleControllerHealthStatus (DriverHealthList, DriverHealthHandles[DriverHealthIndex], Handles[ControllerIndex], NULL, DriverHealth, &HealthStatus);\r
+ if (EFI_ERROR (Status)) {\r
+ //\r
+ // If Status is an error code, then the health information could not be retrieved, so assume healthy\r
+ //\r
+ HealthStatus = EfiDriverHealthStatusHealthy;\r
+ }\r
+\r
+ //\r
+ // If CheckHealthSingleController() returned an error on a terminal state, then do not check the health of child controllers\r
+ //\r
+ if (EFI_ERROR (Status)) {\r
+ continue;\r
+ }\r
+\r
+ //\r
+ // Loop through all the child handles in the handle database\r
+ //\r
+ for (ChildIndex = 0; ChildIndex < HandleCount; ChildIndex++) {\r
+ //\r
+ // Skip NULL child handles\r
+ //\r
+ if (Handles[ChildIndex] == NULL) {\r
+ continue;\r
+ }\r
+\r
+ Status = GetSingleControllerHealthStatus (DriverHealthList, DriverHealthHandles[DriverHealthIndex], Handles[ControllerIndex], Handles[ChildIndex], DriverHealth, &HealthStatus);\r
+ if (EFI_ERROR (Status)) {\r
+ //\r
+ // If Status is an error code, then the health information could not be retrieved, so assume healthy\r
+ //\r
+ HealthStatus = EfiDriverHealthStatusHealthy;\r
+ }\r
+\r
+ //\r
+ // If CheckHealthSingleController() returned an error on a terminal state, then skip to the next child\r
+ //\r
+ if (EFI_ERROR (Status)) {\r
+ continue;\r
+ }\r
+ }\r
+ }\r
+ }\r
+\r
+ Status = EFI_SUCCESS;\r
+\r
+Done:\r
+ if (Handles != NULL) {\r
+ gBS->FreePool (Handles);\r
+ }\r
+ if (DriverHealthHandles != NULL) {\r
+ gBS->FreePool (DriverHealthHandles);\r
+ }\r
+\r
+ return Status;\r
+}\r
+\r
+\r
+/**\r
+ Check the healthy status of the platform, this function will return immediately while found one driver \r
+ in the platform are not healthy.\r
+\r
+ @retval FALSE at least one driver in the platform are not healthy.\r
+ @retval TRUE No controller install Driver Health Protocol,\r
+ or all controllers in the platform are in healthy status.\r
+**/\r
+BOOLEAN\r
+PlaformHealthStatusCheck (\r
+ VOID\r
+ )\r
+{\r
+ EFI_DRIVER_HEALTH_STATUS HealthStatus;\r
+ EFI_STATUS Status;\r
+ UINTN Index;\r
+ UINTN NoHandles;\r
+ EFI_HANDLE *DriverHealthHandles;\r
+ EFI_DRIVER_HEALTH_PROTOCOL *DriverHealth;\r
+ BOOLEAN AllHealthy;\r
+\r
+ //\r
+ // Initialize local variables\r
+ //\r
+ DriverHealthHandles = NULL;\r
+ DriverHealth = NULL;\r
+\r
+ HealthStatus = EfiDriverHealthStatusHealthy;\r
+\r
+ Status = gBS->LocateHandleBuffer (\r
+ ByProtocol,\r
+ &gEfiDriverHealthProtocolGuid,\r
+ NULL,\r
+ &NoHandles,\r
+ &DriverHealthHandles\r
+ );\r
+ //\r
+ // There are no handles match the search for Driver Health Protocol has been installed.\r
+ //\r
+ if (Status == EFI_NOT_FOUND) {\r
+ return TRUE;\r
+ }\r
+ //\r
+ // Assume all modules are healthy.\r
+ // \r
+ AllHealthy = TRUE;\r
+\r
+ //\r
+ // Found one or more Handles.\r
+ //\r
+ if (!EFI_ERROR (Status)) { \r
+ for (Index = 0; Index < NoHandles; Index++) {\r
+ Status = gBS->HandleProtocol (\r
+ DriverHealthHandles[Index],\r
+ &gEfiDriverHealthProtocolGuid,\r
+ (VOID **) &DriverHealth\r
+ );\r
+ if (!EFI_ERROR (Status)) {\r
+ Status = DriverHealth->GetHealthStatus (\r
+ DriverHealth,\r
+ NULL,\r
+ NULL,\r
+ &HealthStatus,\r
+ NULL,\r
+ NULL\r
+ );\r
+ }\r
+ //\r
+ // Get the healthy status of the module\r
+ //\r
+ if (!EFI_ERROR (Status)) {\r
+ if (HealthStatus != EfiDriverHealthStatusHealthy) {\r
+ //\r
+ // Return immediately one driver's status not in healthy.\r
+ //\r
+ return FALSE; \r
+ }\r
+ }\r
+ }\r
+ }\r
+ return AllHealthy;\r
+}\r
+\r
+/**\r
+ Processes a single controller using the EFI Driver Health Protocol associated with \r
+ that controller. This algorithm continues to query the GetHealthStatus() service until\r
+ one of the legal terminal states of the EFI Driver Health Protocol is reached. This may \r
+ require the processing of HII Messages, HII Form, and invocation of repair operations.\r
+\r
+ @param DriverHealth A pointer to the EFI_DRIVER_HEALTH_PROTOCOL instance.\r
+ @param ControllerHandle The class guid specifies which form set will be displayed.\r
+ @param ChildHandle The handle of the child controller to retrieve the health \r
+ status on. This is an optional parameter that may be NULL. \r
+ @param HealthStatus The health status of the controller.\r
+ @param MessageList An array of warning or error messages associated \r
+ with the controller specified by ControllerHandle and \r
+ ChildHandle. This is an optional parameter that may be NULL.\r
+ @param FormHiiHandle The HII handle for an HII form associated with the \r
+ controller specified by ControllerHandle and ChildHandle.\r
+ @param RebootRequired Indicate whether a reboot is required to repair the controller.\r
+**/\r
+VOID\r
+ProcessSingleControllerHealth (\r
+ IN EFI_DRIVER_HEALTH_PROTOCOL *DriverHealth,\r
+ IN EFI_HANDLE ControllerHandle, OPTIONAL\r
+ IN EFI_HANDLE ChildHandle, OPTIONAL\r
+ IN EFI_DRIVER_HEALTH_STATUS HealthStatus,\r
+ IN EFI_DRIVER_HEALTH_HII_MESSAGE **MessageList, OPTIONAL\r
+ IN EFI_HII_HANDLE FormHiiHandle,\r
+ IN OUT BOOLEAN *RebootRequired\r
+ )\r
+{\r
+ EFI_STATUS Status;\r
+ EFI_DRIVER_HEALTH_STATUS LocalHealthStatus;\r
+ \r
+ LocalHealthStatus = HealthStatus;\r
+ //\r
+ // If the module need to be repaired or reconfiguration, will process it until\r
+ // reach a terminal status. The status from EfiDriverHealthStatusRepairRequired after repair \r
+ // will be in (Health, Failed, Configuration Required).\r
+ //\r
+ while(LocalHealthStatus == EfiDriverHealthStatusConfigurationRequired ||\r
+ LocalHealthStatus == EfiDriverHealthStatusRepairRequired) {\r
+\r
+ if (LocalHealthStatus == EfiDriverHealthStatusRepairRequired) {\r
+ Status = DriverHealth->Repair (\r
+ DriverHealth,\r
+ ControllerHandle,\r
+ ChildHandle,\r
+ (EFI_DRIVER_HEALTH_REPAIR_PROGRESS_NOTIFY) RepairNotify\r
+ );\r
+ }\r
+ //\r
+ // Via a form of the driver need to do configuration provided to process of status in \r
+ // EfiDriverHealthStatusConfigurationRequired. The status after configuration should be in\r
+ // (Healthy, Reboot Required, Failed, Reconnect Required, Repair Required). \r
+ //\r
+ if (LocalHealthStatus == EfiDriverHealthStatusConfigurationRequired) {\r
+ if (FormHiiHandle != NULL) {\r
+ Status = gFormBrowser2->SendForm (\r
+ gFormBrowser2,\r
+ &FormHiiHandle,\r
+ 1,\r
+ &gEfiHiiDriverHealthFormsetGuid,\r
+ 0,\r
+ NULL,\r
+ NULL\r
+ );\r
+ ASSERT( !EFI_ERROR (Status));\r
+ } else {\r
+ //\r
+ // Exit the loop in case no FormHiiHandle is supplied to prevent dead-loop\r
+ //\r
+ break;\r
+ }\r
+ }\r
+\r
+ Status = DriverHealth->GetHealthStatus (\r
+ DriverHealth,\r
+ ControllerHandle,\r
+ ChildHandle,\r
+ &LocalHealthStatus,\r
+ NULL,\r
+ &FormHiiHandle\r
+ );\r
+ ASSERT_EFI_ERROR (Status);\r
+\r
+ if (*MessageList != NULL) {\r
+ ProcessMessages (*MessageList);\r
+ } \r
+ }\r
+ \r
+ //\r
+ // Health status in {Healthy, Failed} may also have Messages need to process\r
+ //\r
+ if (LocalHealthStatus == EfiDriverHealthStatusHealthy || LocalHealthStatus == EfiDriverHealthStatusFailed) {\r
+ if (*MessageList != NULL) {\r
+ ProcessMessages (*MessageList);\r
+ }\r
+ }\r
+ //\r
+ // Check for RebootRequired or ReconnectRequired\r
+ //\r
+ if (LocalHealthStatus == EfiDriverHealthStatusRebootRequired) {\r
+ *RebootRequired = TRUE;\r
+ }\r
+ \r
+ //\r
+ // Do reconnect if need.\r
+ //\r
+ if (LocalHealthStatus == EfiDriverHealthStatusReconnectRequired) {\r
+ Status = gBS->DisconnectController (ControllerHandle, NULL, NULL);\r
+ if (EFI_ERROR (Status)) {\r
+ //\r
+ // Disconnect failed. Need to promote reconnect to a reboot.\r
+ //\r
+ *RebootRequired = TRUE;\r
+ } else {\r
+ gBS->ConnectController (ControllerHandle, NULL, NULL, TRUE);\r
+ }\r
+ }\r
+}\r
+\r
+\r
+/**\r
+ Platform specific notification function for controller repair operations.\r
+\r
+ If the driver for a controller support the Driver Health Protocol and the\r
+ current state of the controller is EfiDriverHealthStatusRepairRequired then\r
+ when the Repair() service of the Driver Health Protocol is called, this \r
+ platform specific notification function can display the progress of the repair\r
+ operation. Some platforms may choose to not display anything, other may choose\r
+ to show the percentage complete on text consoles, and other may choose to render\r
+ a progress bar on text and graphical consoles.\r
+\r
+ This function displays the percentage of the repair operation that has been\r
+ completed on text consoles. The percentage is Value / Limit * 100%.\r
+ \r
+ @param Value Value in the range 0..Limit the the repair has completed..\r
+ @param Limit The maximum value of Value\r
+\r
+**/\r
+VOID\r
+RepairNotify (\r
+ IN UINTN Value,\r
+ IN UINTN Limit\r
+ )\r
+{\r
+ UINTN Percent;\r
+\r
+ if (Limit == 0) {\r
+ Print(L"Repair Progress Undefined\n\r");\r
+ } else {\r
+ Percent = Value * 100 / Limit;\r
+ Print(L"Repair Progress = %3d%%\n\r", Percent);\r
+ }\r
+}\r
+\r
+/**\r
+ Processes a set of messages returned by the GetHealthStatus ()\r
+ service of the EFI Driver Health Protocol\r
+\r
+ @param MessageList The MessageList point to messages need to processed. \r
+\r
+**/\r
+VOID\r
+ProcessMessages (\r
+ IN EFI_DRIVER_HEALTH_HII_MESSAGE *MessageList\r
+ )\r
+{\r
+ UINTN MessageIndex;\r
+ EFI_STRING MessageString;\r
+\r
+ for (MessageIndex = 0;\r
+ MessageList[MessageIndex].HiiHandle != NULL;\r
+ MessageIndex++) {\r
+\r
+ MessageString = HiiGetString (\r
+ MessageList[MessageIndex].HiiHandle,\r
+ MessageList[MessageIndex].StringId,\r
+ NULL\r
+ );\r
+ if (MessageString != NULL) {\r
+ //\r
+ // User can customize the output. Just simply print out the MessageString like below. \r
+ // Also can use the HiiHandle to display message on the front page.\r
+ // \r
+ // Print(L"%s\n",MessageString);\r
+ // gBS->Stall (100000);\r
+ }\r
+ }\r
+\r
+}\r
+\r
+/**\r
+ Repair the whole platform.\r
+\r
+ This function is the main entry for user choose "Repair All" in the front page.\r
+ It will try to do recovery job till all the driver health protocol installed modules \r
+ reach a terminal state.\r
+\r
+ @param DriverHealthList A Pointer to the list contain all of the platform driver health\r
+ information.\r
+\r
+**/\r
+VOID\r
+PlatformRepairAll (\r
+ IN LIST_ENTRY *DriverHealthList\r
+ )\r
+{ \r
+ DRIVER_HEALTH_INFO *DriverHealthInfo;\r
+ LIST_ENTRY *Link;\r
+ BOOLEAN RebootRequired;\r
+\r
+ ASSERT (DriverHealthList != NULL);\r
+\r
+ RebootRequired = FALSE;\r
+\r
+ for ( Link = GetFirstNode (DriverHealthList)\r
+ ; !IsNull (DriverHealthList, Link)\r
+ ; Link = GetNextNode (DriverHealthList, Link)\r
+ ) {\r
+ DriverHealthInfo = DEVICE_MANAGER_HEALTH_INFO_FROM_LINK (Link);\r
+ //\r
+ // Do driver health status operation by each link node\r
+ //\r
+ ASSERT (DriverHealthInfo != NULL);\r
+\r
+ ProcessSingleControllerHealth ( \r
+ DriverHealthInfo->DriverHealth,\r
+ DriverHealthInfo->ControllerHandle,\r
+ DriverHealthInfo->ChildHandle,\r
+ DriverHealthInfo->HealthStatus,\r
+ &(DriverHealthInfo->MessageList),\r
+ DriverHealthInfo->HiiHandle,\r
+ &RebootRequired\r
+ );\r
+ }\r
+\r
+ if (RebootRequired) {\r
+ gRT->ResetSystem (EfiResetWarm, EFI_SUCCESS, 0, NULL);\r
+ }\r
+}\r
+\r
+/**\r
+\r
+ Select the best matching language according to front page policy for best user experience. \r
+ \r
+ This function supports both ISO 639-2 and RFC 4646 language codes, but language \r
+ code types may not be mixed in a single call to this function. \r
+\r
+ @param SupportedLanguages A pointer to a Null-terminated ASCII string that\r
+ contains a set of language codes in the format \r
+ specified by Iso639Language.\r
+ @param Iso639Language If TRUE, then all language codes are assumed to be\r
+ in ISO 639-2 format. If FALSE, then all language\r
+ codes are assumed to be in RFC 4646 language format.\r
+\r
+ @retval NULL The best matching language could not be found in SupportedLanguages.\r
+ @retval NULL There are not enough resources available to return the best matching \r
+ language.\r
+ @retval Other A pointer to a Null-terminated ASCII string that is the best matching \r
+ language in SupportedLanguages.\r
+**/\r
+CHAR8 *\r
+DriverHealthSelectBestLanguage (\r
+ IN CHAR8 *SupportedLanguages,\r
+ IN BOOLEAN Iso639Language\r
+ )\r
+{\r
+ CHAR8 *LanguageVariable;\r
+ CHAR8 *BestLanguage;\r
+\r
+ LanguageVariable = GetEfiGlobalVariable (Iso639Language ? L"Lang" : L"PlatformLang");\r
+\r
+ BestLanguage = GetBestLanguage(\r
+ SupportedLanguages,\r
+ Iso639Language,\r
+ (LanguageVariable != NULL) ? LanguageVariable : "",\r
+ Iso639Language ? "eng" : "en-US",\r
+ NULL\r
+ );\r
+ if (LanguageVariable != NULL) {\r
+ FreePool (LanguageVariable);\r
+ }\r
+\r
+ return BestLanguage;\r
+}\r
+\r
+\r
+\r
+/**\r
+\r
+ This is an internal worker function to get the Component Name (2) protocol interface\r
+ and the language it supports.\r
+\r
+ @param ProtocolGuid A pointer to an EFI_GUID. It points to Component Name (2) protocol GUID.\r
+ @param DriverBindingHandle The handle on which the Component Name (2) protocol instance is retrieved.\r
+ @param ComponentName A pointer to the Component Name (2) protocol interface.\r
+ @param SupportedLanguage The best suitable language that matches the SupportedLangues interface for the \r
+ located Component Name (2) instance.\r
+\r
+ @retval EFI_SUCCESS The Component Name (2) protocol instance is successfully located and we find\r
+ the best matching language it support.\r
+ @retval EFI_UNSUPPORTED The input Language is not supported by the Component Name (2) protocol.\r
+ @retval Other Some error occurs when locating Component Name (2) protocol instance or finding\r
+ the supported language.\r
+\r
+**/\r
+EFI_STATUS\r
+GetComponentNameWorker (\r
+ IN EFI_GUID *ProtocolGuid,\r
+ IN EFI_HANDLE DriverBindingHandle,\r
+ OUT EFI_COMPONENT_NAME_PROTOCOL **ComponentName,\r
+ OUT CHAR8 **SupportedLanguage\r
+ )\r
+{\r
+ EFI_STATUS Status;\r
+\r
+ //\r
+ // Locate Component Name (2) protocol on the driver binging handle.\r
+ //\r
+ Status = gBS->OpenProtocol (\r
+ DriverBindingHandle,\r
+ ProtocolGuid,\r
+ (VOID **) ComponentName,\r
+ NULL,\r
+ NULL,\r
+ EFI_OPEN_PROTOCOL_GET_PROTOCOL\r
+ );\r
+ if (EFI_ERROR (Status)) {\r
+ return Status;\r
+ }\r
+\r
+ //\r
+ // Apply shell policy to select the best language.\r
+ //\r
+ *SupportedLanguage = DriverHealthSelectBestLanguage (\r
+ (*ComponentName)->SupportedLanguages,\r
+ (BOOLEAN) (ProtocolGuid == &gEfiComponentNameProtocolGuid)\r
+ );\r
+ if (*SupportedLanguage == NULL) {\r
+ Status = EFI_UNSUPPORTED;\r
+ }\r
+\r
+ return Status;\r
+}\r
+\r
+/**\r
+\r
+ This is an internal worker function to get driver name from Component Name (2) protocol interface.\r
+\r
+\r
+ @param ProtocolGuid A pointer to an EFI_GUID. It points to Component Name (2) protocol GUID.\r
+ @param DriverBindingHandle The handle on which the Component Name (2) protocol instance is retrieved.\r
+ @param DriverName A pointer to the Unicode string to return. This Unicode string is the name\r
+ of the driver specified by This.\r
+\r
+ @retval EFI_SUCCESS The driver name is successfully retrieved from Component Name (2) protocol\r
+ interface.\r
+ @retval Other The driver name cannot be retrieved from Component Name (2) protocol\r
+ interface.\r
+\r
+**/\r
+EFI_STATUS\r
+GetDriverNameWorker (\r
+ IN EFI_GUID *ProtocolGuid,\r
+ IN EFI_HANDLE DriverBindingHandle,\r
+ OUT CHAR16 **DriverName\r
+ )\r
+{\r
+ EFI_STATUS Status;\r
+ CHAR8 *BestLanguage;\r
+ EFI_COMPONENT_NAME_PROTOCOL *ComponentName;\r
+\r
+ //\r
+ // Retrieve Component Name (2) protocol instance on the driver binding handle and \r
+ // find the best language this instance supports. \r
+ //\r
+ Status = GetComponentNameWorker (\r
+ ProtocolGuid,\r
+ DriverBindingHandle,\r
+ &ComponentName,\r
+ &BestLanguage\r
+ );\r
+ if (EFI_ERROR (Status)) {\r
+ return Status;\r
+ }\r
+ \r
+ //\r
+ // Get the driver name from Component Name (2) protocol instance on the driver binging handle.\r
+ //\r
+ Status = ComponentName->GetDriverName (\r
+ ComponentName,\r
+ BestLanguage,\r
+ DriverName\r
+ );\r
+ FreePool (BestLanguage);\r
+ \r
+ return Status;\r
+}\r
+\r
+/**\r
+\r
+ This function gets driver name from Component Name 2 protocol interface and Component Name protocol interface\r
+ in turn. It first tries UEFI 2.0 Component Name 2 protocol interface and try to get the driver name.\r
+ If the attempt fails, it then gets the driver name from EFI 1.1 Component Name protocol for backward\r
+ compatibility support. \r
+\r
+ @param DriverBindingHandle The handle on which the Component Name (2) protocol instance is retrieved.\r
+ @param DriverName A pointer to the Unicode string to return. This Unicode string is the name\r
+ of the driver specified by This.\r
+\r
+ @retval EFI_SUCCESS The driver name is successfully retrieved from Component Name (2) protocol\r
+ interface.\r
+ @retval Other The driver name cannot be retrieved from Component Name (2) protocol\r
+ interface.\r
+\r
+**/\r
+EFI_STATUS\r
+DriverHealthGetDriverName (\r
+ IN EFI_HANDLE DriverBindingHandle,\r
+ OUT CHAR16 **DriverName\r
+ )\r
+{\r
+ EFI_STATUS Status;\r
+\r
+ //\r
+ // Get driver name from UEFI 2.0 Component Name 2 protocol interface.\r
+ //\r
+ Status = GetDriverNameWorker (&gEfiComponentName2ProtocolGuid, DriverBindingHandle, DriverName);\r
+ if (EFI_ERROR (Status)) {\r
+ //\r
+ // If it fails to get the driver name from Component Name protocol interface, we should fall back on\r
+ // EFI 1.1 Component Name protocol interface.\r
+ //\r
+ Status = GetDriverNameWorker (&gEfiComponentNameProtocolGuid, DriverBindingHandle, DriverName);\r
+ }\r
+\r
+ return Status;\r
+}\r
+\r
+\r
+\r
+/**\r
+ This function gets controller name from Component Name 2 protocol interface and Component Name protocol interface\r
+ in turn. It first tries UEFI 2.0 Component Name 2 protocol interface and try to get the controller name.\r
+ If the attempt fails, it then gets the controller name from EFI 1.1 Component Name protocol for backward\r
+ compatibility support. \r
+\r
+ @param ProtocolGuid A pointer to an EFI_GUID. It points to Component Name (2) protocol GUID.\r
+ @param DriverBindingHandle The handle on which the Component Name (2) protocol instance is retrieved.\r
+ @param ControllerHandle The handle of a controller that the driver specified by This is managing.\r
+ This handle specifies the controller whose name is to be returned.\r
+ @param ChildHandle The handle of the child controller to retrieve the name of. This is an\r
+ optional parameter that may be NULL. It will be NULL for device drivers.\r
+ It will also be NULL for bus drivers that attempt to retrieve the name\r
+ of the bus controller. It will not be NULL for a bus driver that attempts\r
+ to retrieve the name of a child controller.\r
+ @param ControllerName A pointer to the Unicode string to return. This Unicode string\r
+ is the name of the controller specified by ControllerHandle and ChildHandle.\r
+\r
+ @retval EFI_SUCCESS The controller name is successfully retrieved from Component Name (2) protocol\r
+ interface.\r
+ @retval Other The controller name cannot be retrieved from Component Name (2) protocol.\r
+\r
+**/\r
+EFI_STATUS\r
+GetControllerNameWorker (\r
+ IN EFI_GUID *ProtocolGuid,\r
+ IN EFI_HANDLE DriverBindingHandle,\r
+ IN EFI_HANDLE ControllerHandle,\r
+ IN EFI_HANDLE ChildHandle,\r
+ OUT CHAR16 **ControllerName\r
+ )\r
+{\r
+ EFI_STATUS Status;\r
+ CHAR8 *BestLanguage;\r
+ EFI_COMPONENT_NAME_PROTOCOL *ComponentName;\r
+\r
+ //\r
+ // Retrieve Component Name (2) protocol instance on the driver binding handle and \r
+ // find the best language this instance supports. \r
+ //\r
+ Status = GetComponentNameWorker (\r
+ ProtocolGuid,\r
+ DriverBindingHandle,\r
+ &ComponentName,\r
+ &BestLanguage\r
+ );\r
+ if (EFI_ERROR (Status)) {\r
+ return Status;\r
+ }\r
+\r
+ //\r
+ // Get the controller name from Component Name (2) protocol instance on the driver binging handle.\r
+ //\r
+ Status = ComponentName->GetControllerName (\r
+ ComponentName,\r
+ ControllerHandle,\r
+ ChildHandle,\r
+ BestLanguage,\r
+ ControllerName\r
+ );\r
+ FreePool (BestLanguage);\r
+\r
+ return Status;\r
+}\r
+\r
+/**\r
+\r
+ This function gets controller name from Component Name 2 protocol interface and Component Name protocol interface\r
+ in turn. It first tries UEFI 2.0 Component Name 2 protocol interface and try to get the controller name. \r
+ If the attempt fails, it then gets the controller name from EFI 1.1 Component Name protocol for backward\r
+ compatibility support. \r
+\r
+ @param DriverBindingHandle The handle on which the Component Name (2) protocol instance is retrieved.\r
+ @param ControllerHandle The handle of a controller that the driver specified by This is managing.\r
+ This handle specifies the controller whose name is to be returned.\r
+ @param ChildHandle The handle of the child controller to retrieve the name of. This is an\r
+ optional parameter that may be NULL. It will be NULL for device drivers.\r
+ It will also be NULL for bus drivers that attempt to retrieve the name\r
+ of the bus controller. It will not be NULL for a bus driver that attempts\r
+ to retrieve the name of a child controller.\r
+ @param ControllerName A pointer to the Unicode string to return. This Unicode string\r
+ is the name of the controller specified by ControllerHandle and ChildHandle.\r
+\r
+ @retval EFI_SUCCESS The controller name is successfully retrieved from Component Name (2) protocol\r
+ interface.\r
+ @retval Other The controller name cannot be retrieved from Component Name (2) protocol.\r
+\r
+**/\r
+EFI_STATUS\r
+DriverHealthGetControllerName (\r
+ IN EFI_HANDLE DriverBindingHandle,\r
+ IN EFI_HANDLE ControllerHandle,\r
+ IN EFI_HANDLE ChildHandle,\r
+ OUT CHAR16 **ControllerName\r
+ )\r
+{\r
+ EFI_STATUS Status;\r
+\r
+ //\r
+ // Get controller name from UEFI 2.0 Component Name 2 protocol interface.\r
+ //\r
+ Status = GetControllerNameWorker (\r
+ &gEfiComponentName2ProtocolGuid,\r
+ DriverBindingHandle,\r
+ ControllerHandle,\r
+ ChildHandle,\r
+ ControllerName\r
+ );\r
+ if (EFI_ERROR (Status)) {\r
+ //\r
+ // If it fails to get the controller name from Component Name protocol interface, we should fall back on\r
+ // EFI 1.1 Component Name protocol interface.\r
+ //\r
+ Status = GetControllerNameWorker (\r
+ &gEfiComponentNameProtocolGuid,\r
+ DriverBindingHandle,\r
+ ControllerHandle,\r
+ ChildHandle,\r
+ ControllerName\r
+ );\r
+ }\r