1 /** @file 2 The platform device manager reference implementation 3 4 Copyright (c) 2004 - 2015, Intel Corporation. All rights reserved.<BR> 5 This program and the accompanying materials 6 are licensed and made available under the terms and conditions of the BSD License 7 which accompanies this distribution. The full text of the license may be found at 8 http://opensource.org/licenses/bsd-license.php 9 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. 12 13 **/ 14 15 #include "DeviceManager.h" 16 17 DEVICE_MANAGER_CALLBACK_DATA gDeviceManagerPrivate = { 18 DEVICE_MANAGER_CALLBACK_DATA_SIGNATURE, 19 NULL, 20 NULL, 21 NULL, 22 NULL, 23 { 24 FakeExtractConfig, 25 FakeRouteConfig, 26 DeviceManagerCallback 27 }, 28 { 29 FakeExtractConfig, 30 FakeRouteConfig, 31 DriverHealthCallback 32 } 33 }; 34 35 #define MAX_MAC_ADDRESS_NODE_LIST_LEN 10 36 37 // 38 // Which Mac Address string is select 39 // it will decide what menu need to show in the NETWORK_DEVICE_FORM_ID form. 40 // 41 EFI_STRING mSelectedMacAddrString; 42 43 // 44 // Which form Id need to be show. 45 // 46 EFI_FORM_ID mNextShowFormId = DEVICE_MANAGER_FORM_ID; 47 48 // 49 // The Mac Address show in the NETWORK_DEVICE_LIST_FORM_ID 50 // 51 MAC_ADDRESS_NODE_LIST mMacDeviceList; 52 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 } 60 }; 61 62 HII_VENDOR_DEVICE_PATH mDeviceManagerHiiVendorDevicePath = { 63 { 64 { 65 HARDWARE_DEVICE_PATH, 66 HW_VENDOR_DP, 67 { 68 (UINT8) (sizeof (VENDOR_DEVICE_PATH)), 69 (UINT8) ((sizeof (VENDOR_DEVICE_PATH)) >> 8) 70 } 71 }, 72 DEVICE_MANAGER_FORMSET_GUID 73 }, 74 { 75 END_DEVICE_PATH_TYPE, 76 END_ENTIRE_DEVICE_PATH_SUBTYPE, 77 { 78 (UINT8) (END_DEVICE_PATH_LENGTH), 79 (UINT8) ((END_DEVICE_PATH_LENGTH) >> 8) 80 } 81 } 82 }; 83 84 HII_VENDOR_DEVICE_PATH mDriverHealthHiiVendorDevicePath = { 85 { 86 { 87 HARDWARE_DEVICE_PATH, 88 HW_VENDOR_DP, 89 { 90 (UINT8) (sizeof (VENDOR_DEVICE_PATH)), 91 (UINT8) ((sizeof (VENDOR_DEVICE_PATH)) >> 8) 92 } 93 }, 94 DRIVER_HEALTH_FORMSET_GUID 95 }, 96 { 97 END_DEVICE_PATH_TYPE, 98 END_ENTIRE_DEVICE_PATH_SUBTYPE, 99 { 100 (UINT8) (END_DEVICE_PATH_LENGTH), 101 (UINT8) ((END_DEVICE_PATH_LENGTH) >> 8) 102 } 103 } 104 }; 105 106 /** 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. 110 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. 118 119 @retval EFI_SUCCESS The callback successfully handled the action. 120 @retval EFI_INVALID_PARAMETER The setup browser call this function with invalid parameters. 121 122 **/ 123 EFI_STATUS 124 EFIAPI 125 DeviceManagerCallback ( 126 IN CONST EFI_HII_CONFIG_ACCESS_PROTOCOL *This, 127 IN EFI_BROWSER_ACTION Action, 128 IN EFI_QUESTION_ID QuestionId, 129 IN UINT8 Type, 130 IN EFI_IFR_TYPE_VALUE *Value, 131 OUT EFI_BROWSER_ACTION_REQUEST *ActionRequest 132 ) 133 { 134 UINTN CurIndex; 135 136 if (Action != EFI_BROWSER_ACTION_CHANGING) { 137 // 138 // All other action return unsupported. 139 // 140 return EFI_UNSUPPORTED; 141 } 142 143 if (Value == NULL) { 144 return EFI_INVALID_PARAMETER; 145 } 146 147 gCallbackKey = QuestionId; 148 if ((QuestionId < MAX_KEY_SECTION_LEN + NETWORK_DEVICE_LIST_KEY_OFFSET) && (QuestionId >= NETWORK_DEVICE_LIST_KEY_OFFSET)) { 149 // 150 // If user select the mac address, need to record mac address string to support next form show. 151 // 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); 155 } 156 } 157 } 158 159 return EFI_SUCCESS; 160 } 161 162 /** 163 164 This function registers HII packages to HII database. 165 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. 168 169 **/ 170 EFI_STATUS 171 InitializeDeviceManager ( 172 VOID 173 ) 174 { 175 EFI_STATUS Status; 176 177 // 178 // Install Device Path Protocol and Config Access protocol to driver handle 179 // 180 Status = gBS->InstallMultipleProtocolInterfaces ( 181 &gDeviceManagerPrivate.DriverHandle, 182 &gEfiDevicePathProtocolGuid, 183 &mDeviceManagerHiiVendorDevicePath, 184 &gEfiHiiConfigAccessProtocolGuid, 185 &gDeviceManagerPrivate.ConfigAccess, 186 NULL 187 ); 188 ASSERT_EFI_ERROR (Status); 189 190 Status = gBS->InstallMultipleProtocolInterfaces ( 191 &gDeviceManagerPrivate.DriverHealthHandle, 192 &gEfiDevicePathProtocolGuid, 193 &mDriverHealthHiiVendorDevicePath, 194 &gEfiHiiConfigAccessProtocolGuid, 195 &gDeviceManagerPrivate.DriverHealthConfigAccess, 196 NULL 197 ); 198 ASSERT_EFI_ERROR (Status); 199 200 mMacDeviceList.CurListLen = 0; 201 mMacDeviceList.MaxListLen = 0; 202 203 return Status; 204 } 205 206 /** 207 Extract the displayed formset for given HII handle and class guid. 208 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. 215 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. 218 219 **/ 220 BOOLEAN 221 ExtractDisplayedHiiFormFromHiiHandle ( 222 IN EFI_HII_HANDLE Handle, 223 IN EFI_GUID *SetupClassGuid, 224 IN UINTN SkipCount, 225 OUT EFI_STRING_ID *FormSetTitle, 226 OUT EFI_STRING_ID *FormSetHelp, 227 OUT EFI_GUID **FormSetGuid 228 ) 229 { 230 EFI_STATUS Status; 231 UINTN BufferSize; 232 EFI_HII_PACKAGE_LIST_HEADER *HiiPackageList; 233 UINT8 *Package; 234 UINT8 *OpCodeData; 235 UINT32 Offset; 236 UINT32 Offset2; 237 UINT32 PackageListLength; 238 EFI_HII_PACKAGE_HEADER PackageHeader; 239 EFI_GUID *ClassGuid; 240 UINT8 ClassGuidNum; 241 242 ASSERT (Handle != NULL); 243 ASSERT (SetupClassGuid != NULL); 244 ASSERT (FormSetTitle != NULL); 245 ASSERT (FormSetHelp != NULL); 246 247 *FormSetTitle = 0; 248 *FormSetHelp = 0; 249 ClassGuidNum = 0; 250 ClassGuid = NULL; 251 252 // 253 // Get HII PackageList 254 // 255 BufferSize = 0; 256 HiiPackageList = NULL; 257 Status = gHiiDatabase->ExportPackageLists (gHiiDatabase, Handle, &BufferSize, HiiPackageList); 258 // 259 // Handle is a invalid handle. Check if Handle is corrupted. 260 // 261 ASSERT (Status != EFI_NOT_FOUND); 262 // 263 // The return status should always be EFI_BUFFER_TOO_SMALL as input buffer's size is 0. 264 // 265 ASSERT (Status == EFI_BUFFER_TOO_SMALL); 266 267 HiiPackageList = AllocatePool (BufferSize); 268 ASSERT (HiiPackageList != NULL); 269 270 Status = gHiiDatabase->ExportPackageLists (gHiiDatabase, Handle, &BufferSize, HiiPackageList); 271 if (EFI_ERROR (Status)) { 272 return FALSE; 273 } 274 275 // 276 // Get Form package from this HII package List 277 // 278 Offset = sizeof (EFI_HII_PACKAGE_LIST_HEADER); 279 Offset2 = 0; 280 PackageListLength = ReadUnaligned32 (&HiiPackageList->PackageLength); 281 282 while (Offset < PackageListLength) { 283 Package = ((UINT8 *) HiiPackageList) + Offset; 284 CopyMem (&PackageHeader, Package, sizeof (EFI_HII_PACKAGE_HEADER)); 285 286 if (PackageHeader.Type == EFI_HII_PACKAGE_FORMS) { 287 // 288 // Search FormSet Opcode in this Form Package 289 // 290 Offset2 = sizeof (EFI_HII_PACKAGE_HEADER); 291 while (Offset2 < PackageHeader.Length) { 292 OpCodeData = Package + Offset2; 293 Offset2 += ((EFI_IFR_OP_HEADER *) OpCodeData)->Length; 294 295 if (((EFI_IFR_OP_HEADER *) OpCodeData)->OpCode == EFI_IFR_FORM_SET_OP) { 296 if (SkipCount != 0) { 297 SkipCount --; 298 continue; 299 } 300 301 if (((EFI_IFR_OP_HEADER *) OpCodeData)->Length > OFFSET_OF (EFI_IFR_FORM_SET, Flags)) { 302 // 303 // Find FormSet OpCode 304 // 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); 314 return TRUE; 315 } 316 ClassGuid ++; 317 } 318 } else { 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); 324 return TRUE; 325 } 326 } 327 } 328 } 329 330 // 331 // Go to next package 332 // 333 Offset += PackageHeader.Length; 334 } 335 336 FreePool (HiiPackageList); 337 338 return FALSE; 339 } 340 341 /** 342 Get the mac address string from the device path. 343 if the device path has the vlan, get the vanid also. 344 345 @param MacAddressNode Device path begin with mac address 346 @param PBuffer Output string buffer contain mac address. 347 348 **/ 349 BOOLEAN 350 GetMacAddressString( 351 IN MAC_ADDR_DEVICE_PATH *MacAddressNode, 352 OUT CHAR16 **PBuffer 353 ) 354 { 355 UINTN HwAddressSize; 356 UINTN Index; 357 UINT8 *HwAddress; 358 EFI_DEVICE_PATH_PROTOCOL *Node; 359 UINT16 VlanId; 360 CHAR16 *String; 361 UINTN BufferLen; 362 363 VlanId = 0; 364 String = NULL; 365 ASSERT(MacAddressNode != NULL); 366 367 HwAddressSize = sizeof (EFI_MAC_ADDRESS); 368 if (MacAddressNode->IfType == 0x01 || MacAddressNode->IfType == 0x00) { 369 HwAddressSize = 6; 370 } 371 372 // 373 // The output format is MAC:XX:XX:XX:...\XXXX 374 // The size is the Number size + ":" size + Vlan size(\XXXX) + End 375 // 376 BufferLen = (4 + 2 * HwAddressSize + (HwAddressSize - 1) + 5 + 1) * sizeof (CHAR16); 377 String = AllocateZeroPool (BufferLen); 378 if (String == NULL) { 379 return FALSE; 380 } 381 382 *PBuffer = String; 383 StrCpyS (String, BufferLen / sizeof (CHAR16), L"MAC:"); 384 String += 4; 385 386 // 387 // Convert the MAC address into a unicode string. 388 // 389 HwAddress = &MacAddressNode->MacAddress.Addr[0]; 390 for (Index = 0; Index < HwAddressSize; Index++) { 391 String += UnicodeValueToString (String, PREFIX_ZERO | RADIX_HEX, *(HwAddress++), 2); 392 if (Index < HwAddressSize - 1) { 393 *String++ = L':'; 394 } 395 } 396 397 // 398 // If VLAN is configured, it will need extra 5 characters like "\0005". 399 // Plus one unicode character for the null-terminator. 400 // 401 Node = (EFI_DEVICE_PATH_PROTOCOL *)MacAddressNode; 402 while (!IsDevicePathEnd (Node)) { 403 if (Node->Type == MESSAGING_DEVICE_PATH && Node->SubType == MSG_VLAN_DP) { 404 VlanId = ((VLAN_DEVICE_PATH *) Node)->VlanId; 405 } 406 Node = NextDevicePathNode (Node); 407 } 408 409 if (VlanId != 0) { 410 *String++ = L'\\'; 411 String += UnicodeValueToString (String, PREFIX_ZERO | RADIX_HEX, VlanId, 4); 412 } 413 414 // 415 // Null terminate the Unicode string 416 // 417 *String = L'\0'; 418 419 return TRUE; 420 } 421 422 /** 423 Save question id and prompt id to the mac device list. 424 If the same mac address has saved yet, no need to add more. 425 426 @param MacAddrString Mac address string. 427 428 @retval EFI_SUCCESS Add the item is successful. 429 @return Other values if failed to Add the item. 430 **/ 431 BOOLEAN 432 AddIdToMacDeviceList ( 433 IN EFI_STRING MacAddrString 434 ) 435 { 436 MENU_INFO_ITEM *TempDeviceList; 437 UINTN Index; 438 EFI_STRING StoredString; 439 EFI_STRING_ID PromptId; 440 EFI_HII_HANDLE HiiHandle; 441 442 HiiHandle = gDeviceManagerPrivate.HiiHandle; 443 TempDeviceList = NULL; 444 445 for (Index = 0; Index < mMacDeviceList.CurListLen; Index ++) { 446 StoredString = HiiGetString (HiiHandle, mMacDeviceList.NodeList[Index].PromptId, NULL); 447 if (StoredString == NULL) { 448 return FALSE; 449 } 450 451 // 452 // Already has save the same mac address to the list. 453 // 454 if (StrCmp (MacAddrString, StoredString) == 0) { 455 return FALSE; 456 } 457 } 458 459 PromptId = HiiSetString(HiiHandle, 0, MacAddrString, NULL); 460 // 461 // If not in the list, save it. 462 // 463 if (mMacDeviceList.MaxListLen > mMacDeviceList.CurListLen + 1) { 464 mMacDeviceList.NodeList[mMacDeviceList.CurListLen].PromptId = PromptId; 465 mMacDeviceList.NodeList[mMacDeviceList.CurListLen].QuestionId = (EFI_QUESTION_ID) (mMacDeviceList.CurListLen + NETWORK_DEVICE_LIST_KEY_OFFSET); 466 } else { 467 mMacDeviceList.MaxListLen += MAX_MAC_ADDRESS_NODE_LIST_LEN; 468 if (mMacDeviceList.CurListLen != 0) { 469 TempDeviceList = (MENU_INFO_ITEM *)AllocateCopyPool (sizeof (MENU_INFO_ITEM) * mMacDeviceList.MaxListLen, (VOID *)mMacDeviceList.NodeList); 470 } else { 471 TempDeviceList = (MENU_INFO_ITEM *)AllocatePool (sizeof (MENU_INFO_ITEM) * mMacDeviceList.MaxListLen); 472 } 473 474 if (TempDeviceList == NULL) { 475 return FALSE; 476 } 477 TempDeviceList[mMacDeviceList.CurListLen].PromptId = PromptId; 478 TempDeviceList[mMacDeviceList.CurListLen].QuestionId = (EFI_QUESTION_ID) (mMacDeviceList.CurListLen + NETWORK_DEVICE_LIST_KEY_OFFSET); 479 480 if (mMacDeviceList.CurListLen > 0) { 481 FreePool(mMacDeviceList.NodeList); 482 } 483 484 mMacDeviceList.NodeList = TempDeviceList; 485 } 486 mMacDeviceList.CurListLen ++; 487 488 return TRUE; 489 } 490 491 /** 492 Check the devcie path, try to find whether it has mac address path. 493 494 In this function, first need to check whether this path has mac address path. 495 second, when the mac address device path has find, also need to deicide whether 496 need to add this mac address relate info to the menu. 497 498 @param *Node Input device which need to be check. 499 @param *NeedAddItem Whether need to add the menu in the network device list. 500 501 @retval TRUE Has mac address device path. 502 @retval FALSE NOT Has mac address device path. 503 504 **/ 505 BOOLEAN 506 IsMacAddressDevicePath ( 507 IN VOID *Node, 508 OUT BOOLEAN *NeedAddItem 509 ) 510 { 511 EFI_DEVICE_PATH_PROTOCOL *DevicePath; 512 CHAR16 *Buffer; 513 BOOLEAN ReturnVal; 514 515 ASSERT (Node != NULL); 516 *NeedAddItem = FALSE; 517 ReturnVal = FALSE; 518 Buffer = NULL; 519 520 DevicePath = (EFI_DEVICE_PATH_PROTOCOL *) Node; 521 522 // 523 // find the partition device path node 524 // 525 while (!IsDevicePathEnd (DevicePath)) { 526 if ((DevicePathType (DevicePath) == MESSAGING_DEVICE_PATH) && 527 (DevicePathSubType (DevicePath) == MSG_MAC_ADDR_DP)) { 528 ReturnVal = TRUE; 529 530 if (DEVICE_MANAGER_FORM_ID == mNextShowFormId) { 531 *NeedAddItem = TRUE; 532 break; 533 } 534 535 if (!GetMacAddressString((MAC_ADDR_DEVICE_PATH*)DevicePath, &Buffer)) { 536 break; 537 } 538 539 if (NETWORK_DEVICE_FORM_ID == mNextShowFormId) { 540 if (StrCmp (Buffer, mSelectedMacAddrString) == 0) { 541 *NeedAddItem = TRUE; 542 } 543 break; 544 } 545 546 if (NETWORK_DEVICE_LIST_FORM_ID == mNextShowFormId) { 547 // 548 // Same handle may has two network child handle, so the questionid 549 // has the offset of SAME_HANDLE_KEY_OFFSET. 550 // 551 if (AddIdToMacDeviceList (Buffer)) { 552 *NeedAddItem = TRUE; 553 } 554 break; 555 } 556 } 557 DevicePath = NextDevicePathNode (DevicePath); 558 } 559 560 if (Buffer != NULL) { 561 FreePool (Buffer); 562 } 563 564 return ReturnVal; 565 } 566 567 /** 568 Check to see if the device path is for the network device. 569 570 @param Handle The HII handle which include the mac address device path. 571 @param ItemCount The new add Mac address item count. 572 573 @retval TRUE Need to add new item in the menu. 574 @return FALSE Do not need to add the menu about the network. 575 576 **/ 577 BOOLEAN 578 IsNeedAddNetworkMenu ( 579 IN EFI_HII_HANDLE Handle, 580 OUT UINTN *ItemCount 581 ) 582 { 583 EFI_STATUS Status; 584 UINTN EntryCount; 585 UINTN Index; 586 EFI_HANDLE DriverHandle; 587 EFI_HANDLE ControllerHandle; 588 EFI_DEVICE_PATH_PROTOCOL *DevicePath; 589 EFI_DEVICE_PATH_PROTOCOL *TmpDevicePath; 590 EFI_DEVICE_PATH_PROTOCOL *ChildDevicePath; 591 EFI_OPEN_PROTOCOL_INFORMATION_ENTRY *OpenInfoBuffer; 592 BOOLEAN IsNeedAdd; 593 594 IsNeedAdd = FALSE; 595 OpenInfoBuffer = NULL; 596 if ((Handle == NULL) || (ItemCount == NULL)) { 597 return FALSE; 598 } 599 *ItemCount = 0; 600 601 Status = gHiiDatabase->GetPackageListHandle (gHiiDatabase, Handle, &DriverHandle); 602 if (EFI_ERROR (Status)) { 603 return FALSE; 604 } 605 // 606 // Get the device path by the got Driver handle . 607 // 608 Status = gBS->HandleProtocol (DriverHandle, &gEfiDevicePathProtocolGuid, (VOID **) &DevicePath); 609 if (EFI_ERROR (Status)) { 610 return FALSE; 611 } 612 TmpDevicePath = DevicePath; 613 614 // 615 // Check whether this device path include mac address device path. 616 // If this path has mac address path, get the value whether need 617 // add this info to the menu and return. 618 // Else check more about the child handle devcie path. 619 // 620 if (IsMacAddressDevicePath(TmpDevicePath, &IsNeedAdd)) { 621 if ((NETWORK_DEVICE_LIST_FORM_ID == mNextShowFormId) && IsNeedAdd) { 622 (*ItemCount) = 1; 623 } 624 return IsNeedAdd; 625 } 626 627 // 628 // Search whether this path is the controller path, not he child handle path. 629 // And the child handle has the network devcie connected. 630 // 631 TmpDevicePath = DevicePath; 632 Status = gBS->LocateDevicePath(&gEfiDevicePathProtocolGuid, &TmpDevicePath, &ControllerHandle); 633 if (EFI_ERROR (Status)) { 634 return FALSE; 635 } 636 637 if (!IsDevicePathEnd (TmpDevicePath)) { 638 return FALSE; 639 } 640 641 // 642 // Retrieve the list of agents that are consuming the specific protocol 643 // on ControllerHandle. 644 // The buffer point by OpenInfoBuffer need be free at this function. 645 // 646 Status = gBS->OpenProtocolInformation ( 647 ControllerHandle, 648 &gEfiPciIoProtocolGuid, 649 &OpenInfoBuffer, 650 &EntryCount 651 ); 652 if (EFI_ERROR (Status)) { 653 return FALSE; 654 } 655 656 // 657 // Inspect if ChildHandle is one of the agents. 658 // 659 Status = EFI_UNSUPPORTED; 660 for (Index = 0; Index < EntryCount; Index++) { 661 // 662 // Query all the children created by the controller handle's driver 663 // 664 if ((OpenInfoBuffer[Index].Attributes & EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER) != 0) { 665 Status = gBS->OpenProtocol ( 666 OpenInfoBuffer[Index].ControllerHandle, 667 &gEfiDevicePathProtocolGuid, 668 (VOID **) &ChildDevicePath, 669 NULL, 670 NULL, 671 EFI_OPEN_PROTOCOL_GET_PROTOCOL 672 ); 673 if (EFI_ERROR (Status)) { 674 continue; 675 } 676 677 // 678 // Check whether this device path include mac address device path. 679 // 680 if (!IsMacAddressDevicePath(ChildDevicePath, &IsNeedAdd)) { 681 // 682 // If this path not has mac address path, check the other. 683 // 684 continue; 685 } else { 686 // 687 // If need to update the NETWORK_DEVICE_LIST_FORM, try to get more. 688 // 689 if ((NETWORK_DEVICE_LIST_FORM_ID == mNextShowFormId)) { 690 if (IsNeedAdd) { 691 (*ItemCount) += 1; 692 } 693 continue; 694 } else { 695 // 696 // If need to update other form, return whether need to add to the menu. 697 // 698 goto Done; 699 } 700 } 701 } 702 } 703 704 Done: 705 if (OpenInfoBuffer != NULL) { 706 FreePool (OpenInfoBuffer); 707 } 708 return IsNeedAdd; 709 } 710 711 /** 712 Get HiiHandle total number. 713 714 @param HiiHandles The input HiiHandle array. 715 716 @retval the Hiihandle count. 717 718 **/ 719 UINTN 720 GetHiiHandleCount ( 721 IN EFI_HII_HANDLE *HiiHandles 722 ) 723 { 724 UINTN Index; 725 726 for (Index = 0; HiiHandles[Index] != NULL; Index++) { 727 } 728 729 return Index; 730 } 731 732 /** 733 Insert the new HiiHandle + FormsetGuid at the NewPair[InsertOffset]. 734 735 @param HiiHandles The input HiiHandle array. 736 @param GuidLists The input form set guid lists. 737 @param ArrayCount The input array count, new array will be arraycount + 1 size. 738 @param Offset The current used HiiHandle's Offset. 739 @param FormSetGuid The new found formset guid. 740 741 **/ 742 VOID 743 AdjustArrayData ( 744 IN OUT EFI_HII_HANDLE **HiiHandles, 745 IN OUT EFI_GUID ***GuidLists, 746 IN UINTN ArrayCount, 747 IN UINTN Offset, 748 IN EFI_GUID *FormSetGuid 749 ) 750 { 751 EFI_HII_HANDLE *NewHiiHandles; 752 EFI_GUID **NewGuidLists; 753 754 // 755 // +2 means include the new HiiHandle and the last empty NULL pointer. 756 // 757 NewHiiHandles = AllocateZeroPool ((ArrayCount + 2) * sizeof (EFI_HII_HANDLE)); 758 ASSERT (NewHiiHandles != NULL); 759 760 CopyMem (NewHiiHandles, *HiiHandles, Offset * sizeof (EFI_HII_HANDLE)); 761 NewHiiHandles[Offset] = NewHiiHandles[Offset - 1]; 762 CopyMem (NewHiiHandles + Offset + 1, *HiiHandles + Offset, (ArrayCount - Offset) * sizeof (EFI_HII_HANDLE)); 763 764 NewGuidLists = AllocateZeroPool ((ArrayCount + 2) * sizeof (EFI_GUID *)); 765 ASSERT (NewGuidLists != NULL); 766 767 CopyMem (NewGuidLists, *GuidLists, Offset * sizeof (EFI_GUID *)); 768 NewGuidLists[Offset] = FormSetGuid; 769 770 FreePool (*HiiHandles); 771 *HiiHandles = NewHiiHandles; 772 FreePool (*GuidLists); 773 *GuidLists = NewGuidLists; 774 } 775 776 /** 777 Call the browser and display the device manager to allow user 778 to configure the platform. 779 780 This function create the dynamic content for device manager. It includes 781 section header for all class of devices, one-of opcode to set VBIOS. 782 783 @retval EFI_SUCCESS Operation is successful. 784 @return Other values if failed to clean up the dynamic content from HII 785 database. 786 787 **/ 788 EFI_STATUS 789 CallDeviceManager ( 790 VOID 791 ) 792 { 793 EFI_STATUS Status; 794 UINTN Index; 795 EFI_STRING String; 796 EFI_STRING_ID Token; 797 EFI_STRING_ID TokenHelp; 798 EFI_HII_HANDLE *HiiHandles; 799 EFI_HII_HANDLE HiiHandle; 800 EFI_STRING_ID FormSetTitle; 801 EFI_STRING_ID FormSetHelp; 802 EFI_BROWSER_ACTION_REQUEST ActionRequest; 803 VOID *StartOpCodeHandle; 804 VOID *EndOpCodeHandle; 805 EFI_IFR_GUID_LABEL *StartLabel; 806 EFI_IFR_GUID_LABEL *EndLabel; 807 UINTN NumHandles; 808 EFI_HANDLE *DriverHealthHandles; 809 BOOLEAN AddNetworkMenu; 810 UINTN AddItemCount; 811 UINTN NewStringLen; 812 EFI_STRING NewStringTitle; 813 EFI_GUID **GuidLists; 814 UINTN HandleNum; 815 UINTN SkipCount; 816 EFI_GUID *FormSetGuid; 817 818 GuidLists = NULL; 819 HiiHandles = NULL; 820 Status = EFI_SUCCESS; 821 gCallbackKey = 0; 822 NumHandles = 0; 823 DriverHealthHandles = NULL; 824 AddNetworkMenu = FALSE; 825 AddItemCount = 0; 826 SkipCount = 0; 827 FormSetGuid = NULL; 828 829 // 830 // Connect all prior to entering the platform setup menu. 831 // 832 if (!gConnectAllHappened) { 833 BdsLibConnectAllDriversToAllControllers (); 834 gConnectAllHappened = TRUE; 835 } 836 837 HiiHandle = gDeviceManagerPrivate.HiiHandle; 838 if (HiiHandle == NULL) { 839 // 840 // Publish our HII data. 841 // 842 HiiHandle = HiiAddPackages ( 843 &gDeviceManagerFormSetGuid, 844 gDeviceManagerPrivate.DriverHandle, 845 DeviceManagerVfrBin, 846 BdsDxeStrings, 847 NULL 848 ); 849 if (HiiHandle == NULL) { 850 return EFI_OUT_OF_RESOURCES; 851 } 852 853 gDeviceManagerPrivate.HiiHandle = HiiHandle; 854 } 855 856 // 857 // If need show the Network device list form, clear the old save list first. 858 // 859 if ((mNextShowFormId == NETWORK_DEVICE_LIST_FORM_ID) && (mMacDeviceList.CurListLen > 0)) { 860 mMacDeviceList.CurListLen = 0; 861 } 862 863 // 864 // Update the network device form titile. 865 // 866 if (mNextShowFormId == NETWORK_DEVICE_FORM_ID) { 867 String = HiiGetString (HiiHandle, STRING_TOKEN (STR_FORM_NETWORK_DEVICE_TITLE), NULL); 868 NewStringLen = StrLen(mSelectedMacAddrString) * 2; 869 NewStringLen += (StrLen(String) + 2) * 2; 870 NewStringTitle = AllocatePool (NewStringLen); 871 UnicodeSPrint (NewStringTitle, NewStringLen, L"%s %s", String, mSelectedMacAddrString); 872 HiiSetString (HiiHandle, STRING_TOKEN (STR_FORM_NETWORK_DEVICE_TITLE), NewStringTitle, NULL); 873 FreePool (String); 874 FreePool (NewStringTitle); 875 } 876 877 // 878 // Allocate space for creation of UpdateData Buffer 879 // 880 StartOpCodeHandle = HiiAllocateOpCodeHandle (); 881 ASSERT (StartOpCodeHandle != NULL); 882 883 EndOpCodeHandle = HiiAllocateOpCodeHandle (); 884 ASSERT (EndOpCodeHandle != NULL); 885 886 // 887 // Create Hii Extend Label OpCode as the start opcode 888 // 889 StartLabel = (EFI_IFR_GUID_LABEL *) HiiCreateGuidOpCode (StartOpCodeHandle, &gEfiIfrTianoGuid, NULL, sizeof (EFI_IFR_GUID_LABEL)); 890 StartLabel->ExtendOpCode = EFI_IFR_EXTEND_OP_LABEL; 891 // 892 // According to the next show Form id(mNextShowFormId) to decide which form need to update. 893 // 894 StartLabel->Number = (UINT16) (LABEL_FORM_ID_OFFSET + mNextShowFormId); 895 896 // 897 // Create Hii Extend Label OpCode as the end opcode 898 // 899 EndLabel = (EFI_IFR_GUID_LABEL *) HiiCreateGuidOpCode (EndOpCodeHandle, &gEfiIfrTianoGuid, NULL, sizeof (EFI_IFR_GUID_LABEL)); 900 EndLabel->ExtendOpCode = EFI_IFR_EXTEND_OP_LABEL; 901 EndLabel->Number = LABEL_END; 902 903 // 904 // Get all the Hii handles 905 // 906 HiiHandles = HiiGetHiiHandles (NULL); 907 ASSERT (HiiHandles != NULL); 908 909 HandleNum = GetHiiHandleCount (HiiHandles); 910 GuidLists = AllocateZeroPool ((HandleNum + 1) * sizeof (EFI_GUID *)); 911 ASSERT (GuidLists != NULL); 912 913 // 914 // Search for formset of each class type 915 // 916 for (Index = 0; HiiHandles[Index] != NULL; Index++) { 917 // 918 // The QuestionId in the form which will call the driver form has this asssumption. 919 // QuestionId = Handle Index + NETWORK_DEVICE_LIST_KEY_OFFSET; 920 // Different QuestionId at least has the section of NETWORK_DEVICE_LIST_KEY_OFFSET. 921 // 922 ASSERT(Index < MAX_KEY_SECTION_LEN); 923 924 if (!ExtractDisplayedHiiFormFromHiiHandle (HiiHandles[Index], &gEfiHiiPlatformSetupFormsetGuid, SkipCount, &FormSetTitle, &FormSetHelp, &FormSetGuid)) { 925 SkipCount = 0; 926 continue; 927 } 928 929 // 930 // One HiiHandle has more than one formset can be shown, 931 // Insert a new pair of HiiHandle + Guid to the HiiHandles and GuidLists list. 932 // 933 if (SkipCount > 0) { 934 AdjustArrayData (&HiiHandles, &GuidLists, HandleNum, Index + 1, FormSetGuid); 935 HandleNum ++; 936 Index ++; 937 } 938 939 String = HiiGetString (HiiHandles[Index], FormSetTitle, NULL); 940 if (String == NULL) { 941 String = HiiGetString (HiiHandle, STR_MISSING_STRING, NULL); 942 ASSERT (String != NULL); 943 } 944 Token = HiiSetString (HiiHandle, 0, String, NULL); 945 FreePool (String); 946 947 String = HiiGetString (HiiHandles[Index], FormSetHelp, NULL); 948 if (String == NULL) { 949 String = HiiGetString (HiiHandle, STR_MISSING_STRING, NULL); 950 ASSERT (String != NULL); 951 } 952 TokenHelp = HiiSetString (HiiHandle, 0, String, NULL); 953 FreePool (String); 954 955 // 956 // Network device process 957 // 958 if (IsNeedAddNetworkMenu (HiiHandles[Index], &AddItemCount)) { 959 if (mNextShowFormId == DEVICE_MANAGER_FORM_ID) { 960 // 961 // Only show one menu item "Network Config" in the device manger form. 962 // 963 if (!AddNetworkMenu) { 964 AddNetworkMenu = TRUE; 965 HiiCreateGotoOpCode ( 966 StartOpCodeHandle, 967 INVALID_FORM_ID, 968 STRING_TOKEN (STR_FORM_NETWORK_DEVICE_LIST_TITLE), 969 STRING_TOKEN (STR_FORM_NETWORK_DEVICE_LIST_HELP), 970 EFI_IFR_FLAG_CALLBACK, 971 (EFI_QUESTION_ID) QUESTION_NETWORK_DEVICE_ID 972 ); 973 } 974 } else if (mNextShowFormId == NETWORK_DEVICE_LIST_FORM_ID) { 975 // 976 // In network device list form, same mac address device only show one menu. 977 // 978 while (AddItemCount > 0) { 979 HiiCreateGotoOpCode ( 980 StartOpCodeHandle, 981 INVALID_FORM_ID, 982 mMacDeviceList.NodeList[mMacDeviceList.CurListLen - AddItemCount].PromptId, 983 STRING_TOKEN (STR_NETWORK_DEVICE_HELP), 984 EFI_IFR_FLAG_CALLBACK, 985 mMacDeviceList.NodeList[mMacDeviceList.CurListLen - AddItemCount].QuestionId 986 ); 987 AddItemCount -= 1; 988 } 989 } else if (mNextShowFormId == NETWORK_DEVICE_FORM_ID) { 990 // 991 // In network device form, only the selected mac address device need to be show. 992 // 993 HiiCreateGotoOpCode ( 994 StartOpCodeHandle, 995 INVALID_FORM_ID, 996 Token, 997 TokenHelp, 998 EFI_IFR_FLAG_CALLBACK, 999 (EFI_QUESTION_ID) (Index + DEVICE_KEY_OFFSET) 1000 ); 1001 } 1002 } else { 1003 // 1004 // 1005 // Not network device process, only need to show at device manger form. 1006 // 1007 if (mNextShowFormId == DEVICE_MANAGER_FORM_ID) { 1008 HiiCreateGotoOpCode ( 1009 StartOpCodeHandle, 1010 INVALID_FORM_ID, 1011 Token, 1012 TokenHelp, 1013 EFI_IFR_FLAG_CALLBACK, 1014 (EFI_QUESTION_ID) (Index + DEVICE_KEY_OFFSET) 1015 ); 1016 } 1017 } 1018 1019 // 1020 // Try to find more formset in this HiiHandle. 1021 // 1022 SkipCount++; 1023 Index--; 1024 } 1025 1026 Status = gBS->LocateHandleBuffer ( 1027 ByProtocol, 1028 &gEfiDriverHealthProtocolGuid, 1029 NULL, 1030 &NumHandles, 1031 &DriverHealthHandles 1032 ); 1033 1034 // 1035 // If there are no drivers installed driver health protocol, do not create driver health entry in UI 1036 // 1037 if (NumHandles != 0) { 1038 // 1039 // If driver health protocol is installed, create Driver Health subtitle and entry 1040 // 1041 HiiCreateSubTitleOpCode (StartOpCodeHandle, STRING_TOKEN (STR_DM_DRIVER_HEALTH_TITLE), 0, 0, 0); 1042 HiiCreateGotoOpCode ( 1043 StartOpCodeHandle, 1044 DRIVER_HEALTH_FORM_ID, 1045 STRING_TOKEN(STR_DRIVER_HEALTH_ALL_HEALTHY), // Prompt text 1046 STRING_TOKEN(STR_DRIVER_HEALTH_STATUS_HELP), // Help text 1047 EFI_IFR_FLAG_CALLBACK, 1048 DEVICE_MANAGER_KEY_DRIVER_HEALTH // Question ID 1049 ); 1050 1051 // 1052 // Check All Driver health status 1053 // 1054 if (!PlaformHealthStatusCheck ()) { 1055 // 1056 // At least one driver in the platform are not in healthy status 1057 // 1058 HiiSetString (HiiHandle, STRING_TOKEN (STR_DRIVER_HEALTH_ALL_HEALTHY), GetStringById (STRING_TOKEN (STR_DRIVER_NOT_HEALTH)), NULL); 1059 } else { 1060 // 1061 // For the string of STR_DRIVER_HEALTH_ALL_HEALTHY previously has been updated and we need to update it while re-entry. 1062 // 1063 HiiSetString (HiiHandle, STRING_TOKEN (STR_DRIVER_HEALTH_ALL_HEALTHY), GetStringById (STRING_TOKEN (STR_DRIVER_HEALTH_ALL_HEALTHY)), NULL); 1064 } 1065 } 1066 1067 HiiUpdateForm ( 1068 HiiHandle, 1069 &gDeviceManagerFormSetGuid, 1070 mNextShowFormId, 1071 StartOpCodeHandle, 1072 EndOpCodeHandle 1073 ); 1074 1075 ActionRequest = EFI_BROWSER_ACTION_REQUEST_NONE; 1076 Status = gFormBrowser2->SendForm ( 1077 gFormBrowser2, 1078 &HiiHandle, 1079 1, 1080 &gDeviceManagerFormSetGuid, 1081 mNextShowFormId, 1082 NULL, 1083 &ActionRequest 1084 ); 1085 if (ActionRequest == EFI_BROWSER_ACTION_REQUEST_RESET) { 1086 EnableResetRequired (); 1087 } 1088 1089 // 1090 // We will have returned from processing a callback, selected 1091 // a target to display 1092 // 1093 if ((gCallbackKey >= DEVICE_KEY_OFFSET)) { 1094 ActionRequest = EFI_BROWSER_ACTION_REQUEST_NONE; 1095 Status = gFormBrowser2->SendForm ( 1096 gFormBrowser2, 1097 &HiiHandles[gCallbackKey - DEVICE_KEY_OFFSET], 1098 1, 1099 GuidLists[gCallbackKey - DEVICE_KEY_OFFSET], 1100 0, 1101 NULL, 1102 &ActionRequest 1103 ); 1104 1105 if (ActionRequest == EFI_BROWSER_ACTION_REQUEST_RESET) { 1106 EnableResetRequired (); 1107 } 1108 1109 // 1110 // Force return to Device Manager 1111 // 1112 gCallbackKey = FRONT_PAGE_KEY_DEVICE_MANAGER; 1113 goto Done; 1114 } 1115 1116 // 1117 // Driver Health item chose. 1118 // 1119 if (gCallbackKey == DEVICE_MANAGER_KEY_DRIVER_HEALTH) { 1120 CallDriverHealth (); 1121 // 1122 // Force return to Device Manager 1123 // 1124 gCallbackKey = FRONT_PAGE_KEY_DEVICE_MANAGER; 1125 goto Done; 1126 } 1127 1128 // 1129 // Enter from device manager and into the network device list. 1130 // 1131 if (gCallbackKey == QUESTION_NETWORK_DEVICE_ID) { 1132 mNextShowFormId = NETWORK_DEVICE_LIST_FORM_ID; 1133 gCallbackKey = FRONT_PAGE_KEY_DEVICE_MANAGER; 1134 goto Done; 1135 } 1136 1137 // 1138 // In this case, go from the network device list to the specify device. 1139 // 1140 if ((gCallbackKey < MAX_KEY_SECTION_LEN + NETWORK_DEVICE_LIST_KEY_OFFSET ) && (gCallbackKey >= NETWORK_DEVICE_LIST_KEY_OFFSET)) { 1141 mNextShowFormId = NETWORK_DEVICE_FORM_ID; 1142 gCallbackKey = FRONT_PAGE_KEY_DEVICE_MANAGER; 1143 goto Done; 1144 } 1145 1146 // 1147 // Select the ESC, the gCallbackKey == 0. 1148 // 1149 if(mNextShowFormId - 1 < DEVICE_MANAGER_FORM_ID) { 1150 mNextShowFormId = DEVICE_MANAGER_FORM_ID; 1151 } else { 1152 mNextShowFormId = (UINT16) (mNextShowFormId - 1); 1153 gCallbackKey = FRONT_PAGE_KEY_DEVICE_MANAGER; 1154 } 1155 1156 Done: 1157 // 1158 // Remove our packagelist from HII database. 1159 // 1160 HiiRemovePackages (HiiHandle); 1161 gDeviceManagerPrivate.HiiHandle = NULL; 1162 1163 HiiFreeOpCodeHandle (StartOpCodeHandle); 1164 HiiFreeOpCodeHandle (EndOpCodeHandle); 1165 FreePool (HiiHandles); 1166 1167 for (Index = 0; Index < HandleNum; Index++) { 1168 if (GuidLists[Index] != NULL) { 1169 FreePool (GuidLists[Index]); 1170 } 1171 } 1172 FreePool (GuidLists); 1173 1174 return Status; 1175 } 1176 1177 /** 1178 This function is invoked if user selected a interactive opcode from Driver Health's 1179 Formset. The decision by user is saved to gCallbackKey for later processing. 1180 1181 @param This Points to the EFI_HII_CONFIG_ACCESS_PROTOCOL. 1182 @param Action Specifies the type of action taken by the browser. 1183 @param QuestionId A unique value which is sent to the original exporting driver 1184 so that it can identify the type of data to expect. 1185 @param Type The type of value for the question. 1186 @param Value A pointer to the data being sent to the original exporting driver. 1187 @param ActionRequest On return, points to the action requested by the callback function. 1188 1189 @retval EFI_SUCCESS The callback successfully handled the action. 1190 @retval EFI_INVALID_PARAMETER The setup browser call this function with invalid parameters. 1191 1192 **/ 1193 EFI_STATUS 1194 EFIAPI 1195 DriverHealthCallback ( 1196 IN CONST EFI_HII_CONFIG_ACCESS_PROTOCOL *This, 1197 IN EFI_BROWSER_ACTION Action, 1198 IN EFI_QUESTION_ID QuestionId, 1199 IN UINT8 Type, 1200 IN EFI_IFR_TYPE_VALUE *Value, 1201 OUT EFI_BROWSER_ACTION_REQUEST *ActionRequest 1202 ) 1203 { 1204 if (Action == EFI_BROWSER_ACTION_CHANGED) { 1205 if ((Value == NULL) || (ActionRequest == NULL)) { 1206 return EFI_INVALID_PARAMETER; 1207 } 1208 1209 gCallbackKey = QuestionId; 1210 1211 // 1212 // Request to exit SendForm(), so as to switch to selected form 1213 // 1214 *ActionRequest = EFI_BROWSER_ACTION_REQUEST_EXIT; 1215 1216 return EFI_SUCCESS; 1217 } 1218 1219 // 1220 // All other action return unsupported. 1221 // 1222 return EFI_UNSUPPORTED; 1223 } 1224 1225 /** 1226 Collect and display the platform's driver health relative information, allow user to do interactive 1227 operation while the platform is unhealthy. 1228 1229 This function display a form which divided into two parts. The one list all modules which has installed 1230 driver health protocol. The list usually contain driver name, controller name, and it's health info. 1231 While the driver name can't be retrieved, will use device path as backup. The other part of the form provide 1232 a choice to the user to repair all platform. 1233 1234 **/ 1235 VOID 1236 CallDriverHealth ( 1237 VOID 1238 ) 1239 { 1240 EFI_STATUS Status; 1241 EFI_HII_HANDLE HiiHandle; 1242 EFI_BROWSER_ACTION_REQUEST ActionRequest; 1243 EFI_IFR_GUID_LABEL *StartLabel; 1244 EFI_IFR_GUID_LABEL *StartLabelRepair; 1245 EFI_IFR_GUID_LABEL *EndLabel; 1246 EFI_IFR_GUID_LABEL *EndLabelRepair; 1247 VOID *StartOpCodeHandle; 1248 VOID *EndOpCodeHandle; 1249 VOID *StartOpCodeHandleRepair; 1250 VOID *EndOpCodeHandleRepair; 1251 UINTN Index; 1252 EFI_STRING_ID Token; 1253 EFI_STRING_ID TokenHelp; 1254 EFI_STRING String; 1255 EFI_STRING TmpString; 1256 EFI_STRING DriverName; 1257 EFI_STRING ControllerName; 1258 LIST_ENTRY DriverHealthList; 1259 DRIVER_HEALTH_INFO *DriverHealthInfo; 1260 LIST_ENTRY *Link; 1261 EFI_DEVICE_PATH_PROTOCOL *DriverDevicePath; 1262 BOOLEAN RebootRequired; 1263 BOOLEAN IsControllerNameEmpty; 1264 UINTN StringSize; 1265 1266 Index = 0; 1267 DriverHealthInfo = NULL; 1268 DriverDevicePath = NULL; 1269 IsControllerNameEmpty = FALSE; 1270 InitializeListHead (&DriverHealthList); 1271 1272 HiiHandle = gDeviceManagerPrivate.DriverHealthHiiHandle; 1273 if (HiiHandle == NULL) { 1274 // 1275 // Publish Driver Health HII data. 1276 // 1277 HiiHandle = HiiAddPackages ( 1278 &gDeviceManagerFormSetGuid, 1279 gDeviceManagerPrivate.DriverHealthHandle, 1280 DriverHealthVfrBin, 1281 BdsDxeStrings, 1282 NULL 1283 ); 1284 if (HiiHandle == NULL) { 1285 return; 1286 } 1287 1288 gDeviceManagerPrivate.DriverHealthHiiHandle = HiiHandle; 1289 } 1290 1291 // 1292 // Allocate space for creation of UpdateData Buffer 1293 // 1294 StartOpCodeHandle = HiiAllocateOpCodeHandle (); 1295 ASSERT (StartOpCodeHandle != NULL); 1296 1297 EndOpCodeHandle = HiiAllocateOpCodeHandle (); 1298 ASSERT (EndOpCodeHandle != NULL); 1299 1300 StartOpCodeHandleRepair = HiiAllocateOpCodeHandle (); 1301 ASSERT (StartOpCodeHandleRepair != NULL); 1302 1303 EndOpCodeHandleRepair = HiiAllocateOpCodeHandle (); 1304 ASSERT (EndOpCodeHandleRepair != NULL); 1305 1306 // 1307 // Create Hii Extend Label OpCode as the start opcode 1308 // 1309 StartLabel = (EFI_IFR_GUID_LABEL *) HiiCreateGuidOpCode (StartOpCodeHandle, &gEfiIfrTianoGuid, NULL, sizeof (EFI_IFR_GUID_LABEL)); 1310 StartLabel->ExtendOpCode = EFI_IFR_EXTEND_OP_LABEL; 1311 StartLabel->Number = LABEL_DRIVER_HEALTH; 1312 1313 // 1314 // Create Hii Extend Label OpCode as the start opcode 1315 // 1316 StartLabelRepair = (EFI_IFR_GUID_LABEL *) HiiCreateGuidOpCode (StartOpCodeHandleRepair, &gEfiIfrTianoGuid, NULL, sizeof (EFI_IFR_GUID_LABEL)); 1317 StartLabelRepair->ExtendOpCode = EFI_IFR_EXTEND_OP_LABEL; 1318 StartLabelRepair->Number = LABEL_DRIVER_HEALTH_REAPIR_ALL; 1319 1320 // 1321 // Create Hii Extend Label OpCode as the end opcode 1322 // 1323 EndLabel = (EFI_IFR_GUID_LABEL *) HiiCreateGuidOpCode (EndOpCodeHandle, &gEfiIfrTianoGuid, NULL, sizeof (EFI_IFR_GUID_LABEL)); 1324 EndLabel->ExtendOpCode = EFI_IFR_EXTEND_OP_LABEL; 1325 EndLabel->Number = LABEL_DRIVER_HEALTH_END; 1326 1327 // 1328 // Create Hii Extend Label OpCode as the end opcode 1329 // 1330 EndLabelRepair = (EFI_IFR_GUID_LABEL *) HiiCreateGuidOpCode (EndOpCodeHandleRepair, &gEfiIfrTianoGuid, NULL, sizeof (EFI_IFR_GUID_LABEL)); 1331 EndLabelRepair->ExtendOpCode = EFI_IFR_EXTEND_OP_LABEL; 1332 EndLabelRepair->Number = LABEL_DRIVER_HEALTH_REAPIR_ALL_END; 1333 1334 HiiCreateSubTitleOpCode (StartOpCodeHandle, STRING_TOKEN (STR_DH_STATUS_LIST), 0, 0, 1); 1335 1336 Status = GetAllControllersHealthStatus (&DriverHealthList); 1337 ASSERT (Status != EFI_OUT_OF_RESOURCES); 1338 1339 Link = GetFirstNode (&DriverHealthList); 1340 1341 while (!IsNull (&DriverHealthList, Link)) { 1342 DriverHealthInfo = DEVICE_MANAGER_HEALTH_INFO_FROM_LINK (Link); 1343 1344 Status = DriverHealthGetDriverName (DriverHealthInfo->DriverHandle, &DriverName); 1345 if (EFI_ERROR (Status)) { 1346 // 1347 // Can not get the Driver name, so use the Device path 1348 // 1349 DriverDevicePath = DevicePathFromHandle (DriverHealthInfo->DriverHandle); 1350 DriverName = DevicePathToStr (DriverDevicePath); 1351 } 1352 StringSize = StrSize (DriverName); 1353 1354 Status = DriverHealthGetControllerName ( 1355 DriverHealthInfo->DriverHandle, 1356 DriverHealthInfo->ControllerHandle, 1357 DriverHealthInfo->ChildHandle, 1358 &ControllerName 1359 ); 1360 1361 if (!EFI_ERROR (Status)) { 1362 IsControllerNameEmpty = FALSE; 1363 StringSize += StrLen (L" ") * sizeof(CHAR16); 1364 StringSize += StrLen (ControllerName) * sizeof(CHAR16); 1365 } else { 1366 IsControllerNameEmpty = TRUE; 1367 } 1368 1369 // 1370 // Add the message of the Module itself provided after the string item. 1371 // 1372 if ((DriverHealthInfo->MessageList != NULL) && (DriverHealthInfo->MessageList->StringId != 0)) { 1373 TmpString = HiiGetString ( 1374 DriverHealthInfo->MessageList->HiiHandle, 1375 DriverHealthInfo->MessageList->StringId, 1376 NULL 1377 ); 1378 ASSERT (TmpString != NULL); 1379 1380 StringSize += StrLen (L" ") * sizeof(CHAR16); 1381 StringSize += StrLen (TmpString) * sizeof(CHAR16); 1382 1383 String = (EFI_STRING) AllocateZeroPool (StringSize); 1384 ASSERT (String != NULL); 1385 1386 StrCpyS (String, StringSize / sizeof(CHAR16), DriverName); 1387 if (!IsControllerNameEmpty) { 1388 StrCatS (String, StringSize / sizeof(CHAR16), L" "); 1389 StrCatS (String, StringSize / sizeof(CHAR16), ControllerName); 1390 } 1391 1392 StrCatS (String, StringSize / sizeof(CHAR16), L" "); 1393 StrCatS (String, StringSize / sizeof(CHAR16), TmpString); 1394 1395 } else { 1396 // 1397 // Update the string will be displayed base on the driver's health status 1398 // 1399 switch(DriverHealthInfo->HealthStatus) { 1400 case EfiDriverHealthStatusRepairRequired: 1401 TmpString = GetStringById (STRING_TOKEN (STR_REPAIR_REQUIRED)); 1402 break; 1403 case EfiDriverHealthStatusConfigurationRequired: 1404 TmpString = GetStringById (STRING_TOKEN (STR_CONFIGURATION_REQUIRED)); 1405 break; 1406 case EfiDriverHealthStatusFailed: 1407 TmpString = GetStringById (STRING_TOKEN (STR_OPERATION_FAILED)); 1408 break; 1409 case EfiDriverHealthStatusReconnectRequired: 1410 TmpString = GetStringById (STRING_TOKEN (STR_RECONNECT_REQUIRED)); 1411 break; 1412 case EfiDriverHealthStatusRebootRequired: 1413 TmpString = GetStringById (STRING_TOKEN (STR_REBOOT_REQUIRED)); 1414 break; 1415 default: 1416 TmpString = GetStringById (STRING_TOKEN (STR_DRIVER_HEALTH_HEALTHY)); 1417 break; 1418 } 1419 ASSERT (TmpString != NULL); 1420 1421 StringSize += StrLen (TmpString) * sizeof(CHAR16); 1422 1423 String = (EFI_STRING) AllocateZeroPool (StringSize); 1424 ASSERT (String != NULL); 1425 1426 StrCpyS (String, StringSize / sizeof (CHAR16), DriverName); 1427 if (!IsControllerNameEmpty) { 1428 StrCatS (String, StringSize / sizeof (CHAR16), L" "); 1429 StrCatS (String, StringSize / sizeof (CHAR16), ControllerName); 1430 } 1431 1432 StrCatS (String, StringSize / sizeof (CHAR16), TmpString); 1433 } 1434 1435 FreePool (TmpString); 1436 1437 Token = HiiSetString (HiiHandle, 0, String, NULL); 1438 FreePool (String); 1439 1440 TokenHelp = HiiSetString (HiiHandle, 0, GetStringById( STRING_TOKEN (STR_DH_REPAIR_SINGLE_HELP)), NULL); 1441 1442 HiiCreateActionOpCode ( 1443 StartOpCodeHandle, 1444 (EFI_QUESTION_ID) (Index + DRIVER_HEALTH_KEY_OFFSET), 1445 Token, 1446 TokenHelp, 1447 EFI_IFR_FLAG_CALLBACK, 1448 0 1449 ); 1450 Index++; 1451 Link = GetNextNode (&DriverHealthList, Link); 1452 } 1453 1454 // 1455 // Add End Opcode for Subtitle 1456 // 1457 HiiCreateEndOpCode (StartOpCodeHandle); 1458 1459 HiiCreateSubTitleOpCode (StartOpCodeHandleRepair, STRING_TOKEN (STR_DRIVER_HEALTH_REPAIR_ALL), 0, 0, 1); 1460 TokenHelp = HiiSetString (HiiHandle, 0, GetStringById( STRING_TOKEN (STR_DH_REPAIR_ALL_HELP)), NULL); 1461 1462 if (PlaformHealthStatusCheck ()) { 1463 // 1464 // No action need to do for the platform 1465 // 1466 Token = HiiSetString (HiiHandle, 0, GetStringById( STRING_TOKEN (STR_DRIVER_HEALTH_ALL_HEALTHY)), NULL); 1467 HiiCreateActionOpCode ( 1468 StartOpCodeHandleRepair, 1469 0, 1470 Token, 1471 TokenHelp, 1472 EFI_IFR_FLAG_READ_ONLY, 1473 0 1474 ); 1475 } else { 1476 // 1477 // Create ActionOpCode only while the platform need to do health related operation. 1478 // 1479 Token = HiiSetString (HiiHandle, 0, GetStringById( STRING_TOKEN (STR_DH_REPAIR_ALL_TITLE)), NULL); 1480 HiiCreateActionOpCode ( 1481 StartOpCodeHandleRepair, 1482 (EFI_QUESTION_ID) DRIVER_HEALTH_REPAIR_ALL_KEY, 1483 Token, 1484 TokenHelp, 1485 EFI_IFR_FLAG_CALLBACK, 1486 0 1487 ); 1488 } 1489 1490 HiiCreateEndOpCode (StartOpCodeHandleRepair); 1491 1492 Status = HiiUpdateForm ( 1493 HiiHandle, 1494 &gDriverHealthFormSetGuid, 1495 DRIVER_HEALTH_FORM_ID, 1496 StartOpCodeHandle, 1497 EndOpCodeHandle 1498 ); 1499 ASSERT (Status != EFI_NOT_FOUND); 1500 ASSERT (Status != EFI_BUFFER_TOO_SMALL); 1501 1502 Status = HiiUpdateForm ( 1503 HiiHandle, 1504 &gDriverHealthFormSetGuid, 1505 DRIVER_HEALTH_FORM_ID, 1506 StartOpCodeHandleRepair, 1507 EndOpCodeHandleRepair 1508 ); 1509 ASSERT (Status != EFI_NOT_FOUND); 1510 ASSERT (Status != EFI_BUFFER_TOO_SMALL); 1511 1512 ActionRequest = EFI_BROWSER_ACTION_REQUEST_NONE; 1513 Status = gFormBrowser2->SendForm ( 1514 gFormBrowser2, 1515 &HiiHandle, 1516 1, 1517 &gDriverHealthFormSetGuid, 1518 DRIVER_HEALTH_FORM_ID, 1519 NULL, 1520 &ActionRequest 1521 ); 1522 if (ActionRequest == EFI_BROWSER_ACTION_REQUEST_RESET) { 1523 EnableResetRequired (); 1524 } 1525 1526 // 1527 // We will have returned from processing a callback - user either hit ESC to exit, or selected 1528 // a target to display. 1529 // Process the diver health status states here. 1530 // 1531 if (gCallbackKey >= DRIVER_HEALTH_KEY_OFFSET && gCallbackKey != DRIVER_HEALTH_REPAIR_ALL_KEY) { 1532 ActionRequest = EFI_BROWSER_ACTION_REQUEST_NONE; 1533 1534 Link = GetFirstNode (&DriverHealthList); 1535 Index = 0; 1536 1537 while (!IsNull (&DriverHealthList, Link)) { 1538 // 1539 // Got the item relative node in the List 1540 // 1541 if (Index == (gCallbackKey - DRIVER_HEALTH_KEY_OFFSET)) { 1542 DriverHealthInfo = DEVICE_MANAGER_HEALTH_INFO_FROM_LINK (Link); 1543 // 1544 // Process the driver's healthy status for the specify module 1545 // 1546 RebootRequired = FALSE; 1547 ProcessSingleControllerHealth ( 1548 DriverHealthInfo->DriverHealth, 1549 DriverHealthInfo->ControllerHandle, 1550 DriverHealthInfo->ChildHandle, 1551 DriverHealthInfo->HealthStatus, 1552 &(DriverHealthInfo->MessageList), 1553 DriverHealthInfo->HiiHandle, 1554 &RebootRequired 1555 ); 1556 if (RebootRequired) { 1557 gRT->ResetSystem (EfiResetWarm, EFI_SUCCESS, 0, NULL); 1558 } 1559 break; 1560 } 1561 Index++; 1562 Link = GetNextNode (&DriverHealthList, Link); 1563 } 1564 1565 if (ActionRequest == EFI_BROWSER_ACTION_REQUEST_RESET) { 1566 EnableResetRequired (); 1567 } 1568 1569 // 1570 // Force return to the form of Driver Health in Device Manager 1571 // 1572 gCallbackKey = DRIVER_HEALTH_RETURN_KEY; 1573 } 1574 1575 // 1576 // Repair the whole platform 1577 // 1578 if (gCallbackKey == DRIVER_HEALTH_REPAIR_ALL_KEY) { 1579 ActionRequest = EFI_BROWSER_ACTION_REQUEST_NONE; 1580 1581 PlatformRepairAll (&DriverHealthList); 1582 1583 gCallbackKey = DRIVER_HEALTH_RETURN_KEY; 1584 } 1585 1586 // 1587 // Remove driver health packagelist from HII database. 1588 // 1589 HiiRemovePackages (HiiHandle); 1590 gDeviceManagerPrivate.DriverHealthHiiHandle = NULL; 1591 1592 // 1593 // Free driver health info list 1594 // 1595 while (!IsListEmpty (&DriverHealthList)) { 1596 1597 Link = GetFirstNode(&DriverHealthList); 1598 DriverHealthInfo = DEVICE_MANAGER_HEALTH_INFO_FROM_LINK (Link); 1599 RemoveEntryList (Link); 1600 1601 if (DriverHealthInfo->MessageList != NULL) { 1602 FreePool(DriverHealthInfo->MessageList); 1603 FreePool (DriverHealthInfo); 1604 } 1605 } 1606 1607 HiiFreeOpCodeHandle (StartOpCodeHandle); 1608 HiiFreeOpCodeHandle (EndOpCodeHandle); 1609 HiiFreeOpCodeHandle (StartOpCodeHandleRepair); 1610 HiiFreeOpCodeHandle (EndOpCodeHandleRepair); 1611 1612 if (gCallbackKey == DRIVER_HEALTH_RETURN_KEY) { 1613 // 1614 // Force return to Driver Health Form 1615 // 1616 gCallbackKey = DEVICE_MANAGER_KEY_DRIVER_HEALTH; 1617 CallDriverHealth (); 1618 } 1619 } 1620 1621 1622 /** 1623 Check the Driver Health status of a single controller and try to process it if not healthy. 1624 1625 This function called by CheckAllControllersHealthStatus () function in order to process a specify 1626 contoller's health state. 1627 1628 @param DriverHealthList A Pointer to the list contain all of the platform driver health information. 1629 @param DriverHandle The handle of driver. 1630 @param ControllerHandle The class guid specifies which form set will be displayed. 1631 @param ChildHandle The handle of the child controller to retrieve the health 1632 status on. This is an optional parameter that may be NULL. 1633 @param DriverHealth A pointer to the EFI_DRIVER_HEALTH_PROTOCOL instance. 1634 @param HealthStatus The health status of the controller. 1635 1636 @retval EFI_INVALID_PARAMETER HealthStatus or DriverHealth is NULL. 1637 @retval HealthStatus The Health status of specify controller. 1638 @retval EFI_OUT_OF_RESOURCES The list of Driver Health Protocol handles can not be retrieved. 1639 @retval EFI_NOT_FOUND No controller in the platform install Driver Health Protocol. 1640 @retval EFI_SUCCESS The Health related operation has been taken successfully. 1641 1642 **/ 1643 EFI_STATUS 1644 EFIAPI 1645 GetSingleControllerHealthStatus ( 1646 IN OUT LIST_ENTRY *DriverHealthList, 1647 IN EFI_HANDLE DriverHandle, 1648 IN EFI_HANDLE ControllerHandle, OPTIONAL 1649 IN EFI_HANDLE ChildHandle, OPTIONAL 1650 IN EFI_DRIVER_HEALTH_PROTOCOL *DriverHealth, 1651 IN EFI_DRIVER_HEALTH_STATUS *HealthStatus 1652 ) 1653 { 1654 EFI_STATUS Status; 1655 EFI_DRIVER_HEALTH_HII_MESSAGE *MessageList; 1656 EFI_HII_HANDLE FormHiiHandle; 1657 DRIVER_HEALTH_INFO *DriverHealthInfo; 1658 1659 if (HealthStatus == NULL) { 1660 // 1661 // If HealthStatus is NULL, then return EFI_INVALID_PARAMETER 1662 // 1663 return EFI_INVALID_PARAMETER; 1664 } 1665 1666 // 1667 // Assume the HealthStatus is healthy 1668 // 1669 *HealthStatus = EfiDriverHealthStatusHealthy; 1670 1671 if (DriverHealth == NULL) { 1672 // 1673 // If DriverHealth is NULL, then return EFI_INVALID_PARAMETER 1674 // 1675 return EFI_INVALID_PARAMETER; 1676 } 1677 1678 if (ControllerHandle == NULL) { 1679 // 1680 // If ControllerHandle is NULL, the return the cumulative health status of the driver 1681 // 1682 Status = DriverHealth->GetHealthStatus (DriverHealth, NULL, NULL, HealthStatus, NULL, NULL); 1683 if (*HealthStatus == EfiDriverHealthStatusHealthy) { 1684 // 1685 // Add the driver health related information into the list 1686 // 1687 DriverHealthInfo = AllocateZeroPool (sizeof (DRIVER_HEALTH_INFO)); 1688 if (DriverHealthInfo == NULL) { 1689 return EFI_OUT_OF_RESOURCES; 1690 } 1691 1692 DriverHealthInfo->Signature = DEVICE_MANAGER_DRIVER_HEALTH_INFO_SIGNATURE; 1693 DriverHealthInfo->DriverHandle = DriverHandle; 1694 DriverHealthInfo->ControllerHandle = NULL; 1695 DriverHealthInfo->ChildHandle = NULL; 1696 DriverHealthInfo->HiiHandle = NULL; 1697 DriverHealthInfo->DriverHealth = DriverHealth; 1698 DriverHealthInfo->MessageList = NULL; 1699 DriverHealthInfo->HealthStatus = *HealthStatus; 1700 1701 InsertTailList (DriverHealthList, &DriverHealthInfo->Link); 1702 } 1703 return Status; 1704 } 1705 1706 MessageList = NULL; 1707 FormHiiHandle = NULL; 1708 1709 // 1710 // Collect the health status with the optional HII message list 1711 // 1712 Status = DriverHealth->GetHealthStatus (DriverHealth, ControllerHandle, ChildHandle, HealthStatus, &MessageList, &FormHiiHandle); 1713 1714 if (EFI_ERROR (Status)) { 1715 // 1716 // If the health status could not be retrieved, then return immediately 1717 // 1718 return Status; 1719 } 1720 1721 // 1722 // Add the driver health related information into the list 1723 // 1724 DriverHealthInfo = AllocateZeroPool (sizeof (DRIVER_HEALTH_INFO)); 1725 if (DriverHealthInfo == NULL) { 1726 return EFI_OUT_OF_RESOURCES; 1727 } 1728 1729 DriverHealthInfo->Signature = DEVICE_MANAGER_DRIVER_HEALTH_INFO_SIGNATURE; 1730 DriverHealthInfo->DriverHandle = DriverHandle; 1731 DriverHealthInfo->ControllerHandle = ControllerHandle; 1732 DriverHealthInfo->ChildHandle = ChildHandle; 1733 DriverHealthInfo->HiiHandle = FormHiiHandle; 1734 DriverHealthInfo->DriverHealth = DriverHealth; 1735 DriverHealthInfo->MessageList = MessageList; 1736 DriverHealthInfo->HealthStatus = *HealthStatus; 1737 1738 InsertTailList (DriverHealthList, &DriverHealthInfo->Link); 1739 1740 return EFI_SUCCESS; 1741 } 1742 1743 /** 1744 Collects all the EFI Driver Health Protocols currently present in the EFI Handle Database, 1745 and queries each EFI Driver Health Protocol to determine if one or more of the controllers 1746 managed by each EFI Driver Health Protocol instance are not healthy. 1747 1748 @param DriverHealthList A Pointer to the list contain all of the platform driver health 1749 information. 1750 1751 @retval EFI_NOT_FOUND No controller in the platform install Driver Health Protocol. 1752 @retval EFI_SUCCESS All the controllers in the platform are healthy. 1753 @retval EFI_OUT_OF_RESOURCES The list of Driver Health Protocol handles can not be retrieved. 1754 1755 **/ 1756 EFI_STATUS 1757 GetAllControllersHealthStatus ( 1758 IN OUT LIST_ENTRY *DriverHealthList 1759 ) 1760 { 1761 EFI_STATUS Status; 1762 UINTN NumHandles; 1763 EFI_HANDLE *DriverHealthHandles; 1764 EFI_DRIVER_HEALTH_PROTOCOL *DriverHealth; 1765 EFI_DRIVER_HEALTH_STATUS HealthStatus; 1766 UINTN DriverHealthIndex; 1767 EFI_HANDLE *Handles; 1768 UINTN HandleCount; 1769 UINTN ControllerIndex; 1770 UINTN ChildIndex; 1771 1772 // 1773 // Initialize local variables 1774 // 1775 Handles = NULL; 1776 DriverHealthHandles = NULL; 1777 NumHandles = 0; 1778 HandleCount = 0; 1779 1780 HealthStatus = EfiDriverHealthStatusHealthy; 1781 1782 Status = gBS->LocateHandleBuffer ( 1783 ByProtocol, 1784 &gEfiDriverHealthProtocolGuid, 1785 NULL, 1786 &NumHandles, 1787 &DriverHealthHandles 1788 ); 1789 1790 if (Status == EFI_NOT_FOUND || NumHandles == 0) { 1791 // 1792 // If there are no Driver Health Protocols handles, then return EFI_NOT_FOUND 1793 // 1794 return EFI_NOT_FOUND; 1795 } 1796 1797 if (EFI_ERROR (Status) || DriverHealthHandles == NULL) { 1798 // 1799 // If the list of Driver Health Protocol handles can not be retrieved, then 1800 // return EFI_OUT_OF_RESOURCES 1801 // 1802 return EFI_OUT_OF_RESOURCES; 1803 } 1804 1805 // 1806 // Check the health status of all controllers in the platform 1807 // Start by looping through all the Driver Health Protocol handles in the handle database 1808 // 1809 for (DriverHealthIndex = 0; DriverHealthIndex < NumHandles; DriverHealthIndex++) { 1810 // 1811 // Skip NULL Driver Health Protocol handles 1812 // 1813 if (DriverHealthHandles[DriverHealthIndex] == NULL) { 1814 continue; 1815 } 1816 1817 // 1818 // Retrieve the Driver Health Protocol from DriverHandle 1819 // 1820 Status = gBS->HandleProtocol ( 1821 DriverHealthHandles[DriverHealthIndex], 1822 &gEfiDriverHealthProtocolGuid, 1823 (VOID **)&DriverHealth 1824 ); 1825 if (EFI_ERROR (Status)) { 1826 // 1827 // If the Driver Health Protocol can not be retrieved, then skip to the next 1828 // Driver Health Protocol handle 1829 // 1830 continue; 1831 } 1832 1833 // 1834 // Check the health of all the controllers managed by a Driver Health Protocol handle 1835 // 1836 Status = GetSingleControllerHealthStatus (DriverHealthList, DriverHealthHandles[DriverHealthIndex], NULL, NULL, DriverHealth, &HealthStatus); 1837 1838 // 1839 // If Status is an error code, then the health information could not be retrieved, so assume healthy 1840 // and skip to the next Driver Health Protocol handle 1841 // 1842 if (EFI_ERROR (Status)) { 1843 continue; 1844 } 1845 1846 // 1847 // If all the controllers managed by this Driver Health Protocol are healthy, then skip to the next 1848 // Driver Health Protocol handle 1849 // 1850 if (HealthStatus == EfiDriverHealthStatusHealthy) { 1851 continue; 1852 } 1853 1854 // 1855 // See if the list of all handles in the handle database has been retrieved 1856 // 1857 // 1858 if (Handles == NULL) { 1859 // 1860 // Retrieve the list of all handles from the handle database 1861 // 1862 Status = gBS->LocateHandleBuffer ( 1863 AllHandles, 1864 NULL, 1865 NULL, 1866 &HandleCount, 1867 &Handles 1868 ); 1869 if (EFI_ERROR (Status) || Handles == NULL) { 1870 // 1871 // If all the handles in the handle database can not be retrieved, then 1872 // return EFI_OUT_OF_RESOURCES 1873 // 1874 Status = EFI_OUT_OF_RESOURCES; 1875 goto Done; 1876 } 1877 } 1878 // 1879 // Loop through all the controller handles in the handle database 1880 // 1881 for (ControllerIndex = 0; ControllerIndex < HandleCount; ControllerIndex++) { 1882 // 1883 // Skip NULL controller handles 1884 // 1885 if (Handles[ControllerIndex] == NULL) { 1886 continue; 1887 } 1888 1889 Status = GetSingleControllerHealthStatus (DriverHealthList, DriverHealthHandles[DriverHealthIndex], Handles[ControllerIndex], NULL, DriverHealth, &HealthStatus); 1890 if (EFI_ERROR (Status)) { 1891 // 1892 // If Status is an error code, then the health information could not be retrieved, so assume healthy 1893 // 1894 HealthStatus = EfiDriverHealthStatusHealthy; 1895 } 1896 1897 // 1898 // If CheckHealthSingleController() returned an error on a terminal state, then do not check the health of child controllers 1899 // 1900 if (EFI_ERROR (Status)) { 1901 continue; 1902 } 1903 1904 // 1905 // Loop through all the child handles in the handle database 1906 // 1907 for (ChildIndex = 0; ChildIndex < HandleCount; ChildIndex++) { 1908 // 1909 // Skip NULL child handles 1910 // 1911 if (Handles[ChildIndex] == NULL) { 1912 continue; 1913 } 1914 1915 Status = GetSingleControllerHealthStatus (DriverHealthList, DriverHealthHandles[DriverHealthIndex], Handles[ControllerIndex], Handles[ChildIndex], DriverHealth, &HealthStatus); 1916 if (EFI_ERROR (Status)) { 1917 // 1918 // If Status is an error code, then the health information could not be retrieved, so assume healthy 1919 // 1920 HealthStatus = EfiDriverHealthStatusHealthy; 1921 } 1922 1923 // 1924 // If CheckHealthSingleController() returned an error on a terminal state, then skip to the next child 1925 // 1926 if (EFI_ERROR (Status)) { 1927 continue; 1928 } 1929 } 1930 } 1931 } 1932 1933 Status = EFI_SUCCESS; 1934 1935 Done: 1936 if (Handles != NULL) { 1937 gBS->FreePool (Handles); 1938 } 1939 if (DriverHealthHandles != NULL) { 1940 gBS->FreePool (DriverHealthHandles); 1941 } 1942 1943 return Status; 1944 } 1945 1946 1947 /** 1948 Check the healthy status of the platform, this function will return immediately while found one driver 1949 in the platform are not healthy. 1950 1951 @retval FALSE at least one driver in the platform are not healthy. 1952 @retval TRUE No controller install Driver Health Protocol, 1953 or all controllers in the platform are in healthy status. 1954 **/ 1955 BOOLEAN 1956 PlaformHealthStatusCheck ( 1957 VOID 1958 ) 1959 { 1960 EFI_DRIVER_HEALTH_STATUS HealthStatus; 1961 EFI_STATUS Status; 1962 UINTN Index; 1963 UINTN NoHandles; 1964 EFI_HANDLE *DriverHealthHandles; 1965 EFI_DRIVER_HEALTH_PROTOCOL *DriverHealth; 1966 BOOLEAN AllHealthy; 1967 1968 // 1969 // Initialize local variables 1970 // 1971 DriverHealthHandles = NULL; 1972 DriverHealth = NULL; 1973 1974 HealthStatus = EfiDriverHealthStatusHealthy; 1975 1976 Status = gBS->LocateHandleBuffer ( 1977 ByProtocol, 1978 &gEfiDriverHealthProtocolGuid, 1979 NULL, 1980 &NoHandles, 1981 &DriverHealthHandles 1982 ); 1983 // 1984 // There are no handles match the search for Driver Health Protocol has been installed. 1985 // 1986 if (Status == EFI_NOT_FOUND) { 1987 return TRUE; 1988 } 1989 // 1990 // Assume all modules are healthy. 1991 // 1992 AllHealthy = TRUE; 1993 1994 // 1995 // Found one or more Handles. 1996 // 1997 if (!EFI_ERROR (Status)) { 1998 for (Index = 0; Index < NoHandles; Index++) { 1999 Status = gBS->HandleProtocol ( 2000 DriverHealthHandles[Index], 2001 &gEfiDriverHealthProtocolGuid, 2002 (VOID **) &DriverHealth 2003 ); 2004 if (!EFI_ERROR (Status)) { 2005 Status = DriverHealth->GetHealthStatus ( 2006 DriverHealth, 2007 NULL, 2008 NULL, 2009 &HealthStatus, 2010 NULL, 2011 NULL 2012 ); 2013 } 2014 // 2015 // Get the healthy status of the module 2016 // 2017 if (!EFI_ERROR (Status)) { 2018 if (HealthStatus != EfiDriverHealthStatusHealthy) { 2019 // 2020 // Return immediately one driver's status not in healthy. 2021 // 2022 return FALSE; 2023 } 2024 } 2025 } 2026 } 2027 return AllHealthy; 2028 } 2029 2030 /** 2031 Processes a single controller using the EFI Driver Health Protocol associated with 2032 that controller. This algorithm continues to query the GetHealthStatus() service until 2033 one of the legal terminal states of the EFI Driver Health Protocol is reached. This may 2034 require the processing of HII Messages, HII Form, and invocation of repair operations. 2035 2036 @param DriverHealth A pointer to the EFI_DRIVER_HEALTH_PROTOCOL instance. 2037 @param ControllerHandle The class guid specifies which form set will be displayed. 2038 @param ChildHandle The handle of the child controller to retrieve the health 2039 status on. This is an optional parameter that may be NULL. 2040 @param HealthStatus The health status of the controller. 2041 @param MessageList An array of warning or error messages associated 2042 with the controller specified by ControllerHandle and 2043 ChildHandle. This is an optional parameter that may be NULL. 2044 @param FormHiiHandle The HII handle for an HII form associated with the 2045 controller specified by ControllerHandle and ChildHandle. 2046 @param RebootRequired Indicate whether a reboot is required to repair the controller. 2047 **/ 2048 VOID 2049 ProcessSingleControllerHealth ( 2050 IN EFI_DRIVER_HEALTH_PROTOCOL *DriverHealth, 2051 IN EFI_HANDLE ControllerHandle, OPTIONAL 2052 IN EFI_HANDLE ChildHandle, OPTIONAL 2053 IN EFI_DRIVER_HEALTH_STATUS HealthStatus, 2054 IN EFI_DRIVER_HEALTH_HII_MESSAGE **MessageList, OPTIONAL 2055 IN EFI_HII_HANDLE FormHiiHandle, 2056 IN OUT BOOLEAN *RebootRequired 2057 ) 2058 { 2059 EFI_STATUS Status; 2060 EFI_DRIVER_HEALTH_STATUS LocalHealthStatus; 2061 2062 LocalHealthStatus = HealthStatus; 2063 // 2064 // If the module need to be repaired or reconfiguration, will process it until 2065 // reach a terminal status. The status from EfiDriverHealthStatusRepairRequired after repair 2066 // will be in (Health, Failed, Configuration Required). 2067 // 2068 while(LocalHealthStatus == EfiDriverHealthStatusConfigurationRequired || 2069 LocalHealthStatus == EfiDriverHealthStatusRepairRequired) { 2070 2071 if (LocalHealthStatus == EfiDriverHealthStatusRepairRequired) { 2072 Status = DriverHealth->Repair ( 2073 DriverHealth, 2074 ControllerHandle, 2075 ChildHandle, 2076 RepairNotify 2077 ); 2078 } 2079 // 2080 // Via a form of the driver need to do configuration provided to process of status in 2081 // EfiDriverHealthStatusConfigurationRequired. The status after configuration should be in 2082 // (Healthy, Reboot Required, Failed, Reconnect Required, Repair Required). 2083 // 2084 if (LocalHealthStatus == EfiDriverHealthStatusConfigurationRequired) { 2085 if (FormHiiHandle != NULL) { 2086 Status = gFormBrowser2->SendForm ( 2087 gFormBrowser2, 2088 &FormHiiHandle, 2089 1, 2090 &gEfiHiiDriverHealthFormsetGuid, 2091 0, 2092 NULL, 2093 NULL 2094 ); 2095 ASSERT( !EFI_ERROR (Status)); 2096 } else { 2097 // 2098 // Exit the loop in case no FormHiiHandle is supplied to prevent dead-loop 2099 // 2100 break; 2101 } 2102 } 2103 2104 Status = DriverHealth->GetHealthStatus ( 2105 DriverHealth, 2106 ControllerHandle, 2107 ChildHandle, 2108 &LocalHealthStatus, 2109 NULL, 2110 &FormHiiHandle 2111 ); 2112 ASSERT_EFI_ERROR (Status); 2113 2114 if (*MessageList != NULL) { 2115 ProcessMessages (*MessageList); 2116 } 2117 } 2118 2119 // 2120 // Health status in {Healthy, Failed} may also have Messages need to process 2121 // 2122 if (LocalHealthStatus == EfiDriverHealthStatusHealthy || LocalHealthStatus == EfiDriverHealthStatusFailed) { 2123 if (*MessageList != NULL) { 2124 ProcessMessages (*MessageList); 2125 } 2126 } 2127 // 2128 // Check for RebootRequired or ReconnectRequired 2129 // 2130 if (LocalHealthStatus == EfiDriverHealthStatusRebootRequired) { 2131 *RebootRequired = TRUE; 2132 } 2133 2134 // 2135 // Do reconnect if need. 2136 // 2137 if (LocalHealthStatus == EfiDriverHealthStatusReconnectRequired) { 2138 Status = gBS->DisconnectController (ControllerHandle, NULL, NULL); 2139 if (EFI_ERROR (Status)) { 2140 // 2141 // Disconnect failed. Need to promote reconnect to a reboot. 2142 // 2143 *RebootRequired = TRUE; 2144 } else { 2145 gBS->ConnectController (ControllerHandle, NULL, NULL, TRUE); 2146 } 2147 } 2148 } 2149 2150 2151 /** 2152 Reports the progress of a repair operation. 2153 2154 @param[in] Value A value between 0 and Limit that identifies the current 2155 progress of the repair operation. 2156 2157 @param[in] Limit The maximum value of Value for the current repair operation. 2158 For example, a driver that wants to specify progress in 2159 percent would use a Limit value of 100. 2160 2161 @retval EFI_SUCCESS The progress of a repair operation is reported successfully. 2162 2163 **/ 2164 EFI_STATUS 2165 EFIAPI 2166 RepairNotify ( 2167 IN UINTN Value, 2168 IN UINTN Limit 2169 ) 2170 { 2171 UINTN Percent; 2172 2173 if (Limit == 0) { 2174 Print(L"Repair Progress Undefined\n\r"); 2175 } else { 2176 Percent = Value * 100 / Limit; 2177 Print(L"Repair Progress = %3d%%\n\r", Percent); 2178 } 2179 return EFI_SUCCESS; 2180 } 2181 2182 /** 2183 Processes a set of messages returned by the GetHealthStatus () 2184 service of the EFI Driver Health Protocol 2185 2186 @param MessageList The MessageList point to messages need to processed. 2187 2188 **/ 2189 VOID 2190 ProcessMessages ( 2191 IN EFI_DRIVER_HEALTH_HII_MESSAGE *MessageList 2192 ) 2193 { 2194 UINTN MessageIndex; 2195 EFI_STRING MessageString; 2196 2197 for (MessageIndex = 0; 2198 MessageList[MessageIndex].HiiHandle != NULL; 2199 MessageIndex++) { 2200 2201 MessageString = HiiGetString ( 2202 MessageList[MessageIndex].HiiHandle, 2203 MessageList[MessageIndex].StringId, 2204 NULL 2205 ); 2206 if (MessageString != NULL) { 2207 // 2208 // User can customize the output. Just simply print out the MessageString like below. 2209 // Also can use the HiiHandle to display message on the front page. 2210 // 2211 // Print(L"%s\n",MessageString); 2212 // gBS->Stall (100000); 2213 } 2214 } 2215 2216 } 2217 2218 /** 2219 Repair the whole platform. 2220 2221 This function is the main entry for user choose "Repair All" in the front page. 2222 It will try to do recovery job till all the driver health protocol installed modules 2223 reach a terminal state. 2224 2225 @param DriverHealthList A Pointer to the list contain all of the platform driver health 2226 information. 2227 2228 **/ 2229 VOID 2230 PlatformRepairAll ( 2231 IN LIST_ENTRY *DriverHealthList 2232 ) 2233 { 2234 DRIVER_HEALTH_INFO *DriverHealthInfo; 2235 LIST_ENTRY *Link; 2236 BOOLEAN RebootRequired; 2237 2238 ASSERT (DriverHealthList != NULL); 2239 2240 RebootRequired = FALSE; 2241 2242 for ( Link = GetFirstNode (DriverHealthList) 2243 ; !IsNull (DriverHealthList, Link) 2244 ; Link = GetNextNode (DriverHealthList, Link) 2245 ) { 2246 DriverHealthInfo = DEVICE_MANAGER_HEALTH_INFO_FROM_LINK (Link); 2247 // 2248 // Do driver health status operation by each link node 2249 // 2250 ASSERT (DriverHealthInfo != NULL); 2251 2252 ProcessSingleControllerHealth ( 2253 DriverHealthInfo->DriverHealth, 2254 DriverHealthInfo->ControllerHandle, 2255 DriverHealthInfo->ChildHandle, 2256 DriverHealthInfo->HealthStatus, 2257 &(DriverHealthInfo->MessageList), 2258 DriverHealthInfo->HiiHandle, 2259 &RebootRequired 2260 ); 2261 } 2262 2263 if (RebootRequired) { 2264 gRT->ResetSystem (EfiResetWarm, EFI_SUCCESS, 0, NULL); 2265 } 2266 } 2267 2268 /** 2269 2270 Select the best matching language according to front page policy for best user experience. 2271 2272 This function supports both ISO 639-2 and RFC 4646 language codes, but language 2273 code types may not be mixed in a single call to this function. 2274 2275 @param SupportedLanguages A pointer to a Null-terminated ASCII string that 2276 contains a set of language codes in the format 2277 specified by Iso639Language. 2278 @param Iso639Language If TRUE, then all language codes are assumed to be 2279 in ISO 639-2 format. If FALSE, then all language 2280 codes are assumed to be in RFC 4646 language format. 2281 2282 @retval NULL The best matching language could not be found in SupportedLanguages. 2283 @retval NULL There are not enough resources available to return the best matching 2284 language. 2285 @retval Other A pointer to a Null-terminated ASCII string that is the best matching 2286 language in SupportedLanguages. 2287 **/ 2288 CHAR8 * 2289 DriverHealthSelectBestLanguage ( 2290 IN CHAR8 *SupportedLanguages, 2291 IN BOOLEAN Iso639Language 2292 ) 2293 { 2294 CHAR8 *LanguageVariable; 2295 CHAR8 *BestLanguage; 2296 2297 GetEfiGlobalVariable2 (Iso639Language ? L"Lang" : L"PlatformLang", (VOID**)&LanguageVariable, NULL); 2298 2299 BestLanguage = GetBestLanguage( 2300 SupportedLanguages, 2301 Iso639Language, 2302 (LanguageVariable != NULL) ? LanguageVariable : "", 2303 Iso639Language ? "eng" : "en-US", 2304 NULL 2305 ); 2306 if (LanguageVariable != NULL) { 2307 FreePool (LanguageVariable); 2308 } 2309 2310 return BestLanguage; 2311 } 2312 2313 2314 2315 /** 2316 2317 This is an internal worker function to get the Component Name (2) protocol interface 2318 and the language it supports. 2319 2320 @param ProtocolGuid A pointer to an EFI_GUID. It points to Component Name (2) protocol GUID. 2321 @param DriverBindingHandle The handle on which the Component Name (2) protocol instance is retrieved. 2322 @param ComponentName A pointer to the Component Name (2) protocol interface. 2323 @param SupportedLanguage The best suitable language that matches the SupportedLangues interface for the 2324 located Component Name (2) instance. 2325 2326 @retval EFI_SUCCESS The Component Name (2) protocol instance is successfully located and we find 2327 the best matching language it support. 2328 @retval EFI_UNSUPPORTED The input Language is not supported by the Component Name (2) protocol. 2329 @retval Other Some error occurs when locating Component Name (2) protocol instance or finding 2330 the supported language. 2331 2332 **/ 2333 EFI_STATUS 2334 GetComponentNameWorker ( 2335 IN EFI_GUID *ProtocolGuid, 2336 IN EFI_HANDLE DriverBindingHandle, 2337 OUT EFI_COMPONENT_NAME_PROTOCOL **ComponentName, 2338 OUT CHAR8 **SupportedLanguage 2339 ) 2340 { 2341 EFI_STATUS Status; 2342 2343 // 2344 // Locate Component Name (2) protocol on the driver binging handle. 2345 // 2346 Status = gBS->OpenProtocol ( 2347 DriverBindingHandle, 2348 ProtocolGuid, 2349 (VOID **) ComponentName, 2350 NULL, 2351 NULL, 2352 EFI_OPEN_PROTOCOL_GET_PROTOCOL 2353 ); 2354 if (EFI_ERROR (Status)) { 2355 return Status; 2356 } 2357 2358 // 2359 // Apply shell policy to select the best language. 2360 // 2361 *SupportedLanguage = DriverHealthSelectBestLanguage ( 2362 (*ComponentName)->SupportedLanguages, 2363 (BOOLEAN) (ProtocolGuid == &gEfiComponentNameProtocolGuid) 2364 ); 2365 if (*SupportedLanguage == NULL) { 2366 Status = EFI_UNSUPPORTED; 2367 } 2368 2369 return Status; 2370 } 2371 2372 /** 2373 2374 This is an internal worker function to get driver name from Component Name (2) protocol interface. 2375 2376 2377 @param ProtocolGuid A pointer to an EFI_GUID. It points to Component Name (2) protocol GUID. 2378 @param DriverBindingHandle The handle on which the Component Name (2) protocol instance is retrieved. 2379 @param DriverName A pointer to the Unicode string to return. This Unicode string is the name 2380 of the driver specified by This. 2381 2382 @retval EFI_SUCCESS The driver name is successfully retrieved from Component Name (2) protocol 2383 interface. 2384 @retval Other The driver name cannot be retrieved from Component Name (2) protocol 2385 interface. 2386 2387 **/ 2388 EFI_STATUS 2389 GetDriverNameWorker ( 2390 IN EFI_GUID *ProtocolGuid, 2391 IN EFI_HANDLE DriverBindingHandle, 2392 OUT CHAR16 **DriverName 2393 ) 2394 { 2395 EFI_STATUS Status; 2396 CHAR8 *BestLanguage; 2397 EFI_COMPONENT_NAME_PROTOCOL *ComponentName; 2398 2399 // 2400 // Retrieve Component Name (2) protocol instance on the driver binding handle and 2401 // find the best language this instance supports. 2402 // 2403 Status = GetComponentNameWorker ( 2404 ProtocolGuid, 2405 DriverBindingHandle, 2406 &ComponentName, 2407 &BestLanguage 2408 ); 2409 if (EFI_ERROR (Status)) { 2410 return Status; 2411 } 2412 2413 // 2414 // Get the driver name from Component Name (2) protocol instance on the driver binging handle. 2415 // 2416 Status = ComponentName->GetDriverName ( 2417 ComponentName, 2418 BestLanguage, 2419 DriverName 2420 ); 2421 FreePool (BestLanguage); 2422 2423 return Status; 2424 } 2425 2426 /** 2427 2428 This function gets driver name from Component Name 2 protocol interface and Component Name protocol interface 2429 in turn. It first tries UEFI 2.0 Component Name 2 protocol interface and try to get the driver name. 2430 If the attempt fails, it then gets the driver name from EFI 1.1 Component Name protocol for backward 2431 compatibility support. 2432 2433 @param DriverBindingHandle The handle on which the Component Name (2) protocol instance is retrieved. 2434 @param DriverName A pointer to the Unicode string to return. This Unicode string is the name 2435 of the driver specified by This. 2436 2437 @retval EFI_SUCCESS The driver name is successfully retrieved from Component Name (2) protocol 2438 interface. 2439 @retval Other The driver name cannot be retrieved from Component Name (2) protocol 2440 interface. 2441 2442 **/ 2443 EFI_STATUS 2444 DriverHealthGetDriverName ( 2445 IN EFI_HANDLE DriverBindingHandle, 2446 OUT CHAR16 **DriverName 2447 ) 2448 { 2449 EFI_STATUS Status; 2450 2451 // 2452 // Get driver name from UEFI 2.0 Component Name 2 protocol interface. 2453 // 2454 Status = GetDriverNameWorker (&gEfiComponentName2ProtocolGuid, DriverBindingHandle, DriverName); 2455 if (EFI_ERROR (Status)) { 2456 // 2457 // If it fails to get the driver name from Component Name protocol interface, we should fall back on 2458 // EFI 1.1 Component Name protocol interface. 2459 // 2460 Status = GetDriverNameWorker (&gEfiComponentNameProtocolGuid, DriverBindingHandle, DriverName); 2461 } 2462 2463 return Status; 2464 } 2465 2466 2467 2468 /** 2469 This function gets controller name from Component Name 2 protocol interface and Component Name protocol interface 2470 in turn. It first tries UEFI 2.0 Component Name 2 protocol interface and try to get the controller name. 2471 If the attempt fails, it then gets the controller name from EFI 1.1 Component Name protocol for backward 2472 compatibility support. 2473 2474 @param ProtocolGuid A pointer to an EFI_GUID. It points to Component Name (2) protocol GUID. 2475 @param DriverBindingHandle The handle on which the Component Name (2) protocol instance is retrieved. 2476 @param ControllerHandle The handle of a controller that the driver specified by This is managing. 2477 This handle specifies the controller whose name is to be returned. 2478 @param ChildHandle The handle of the child controller to retrieve the name of. This is an 2479 optional parameter that may be NULL. It will be NULL for device drivers. 2480 It will also be NULL for bus drivers that attempt to retrieve the name 2481 of the bus controller. It will not be NULL for a bus driver that attempts 2482 to retrieve the name of a child controller. 2483 @param ControllerName A pointer to the Unicode string to return. This Unicode string 2484 is the name of the controller specified by ControllerHandle and ChildHandle. 2485 2486 @retval EFI_SUCCESS The controller name is successfully retrieved from Component Name (2) protocol 2487 interface. 2488 @retval Other The controller name cannot be retrieved from Component Name (2) protocol. 2489 2490 **/ 2491 EFI_STATUS 2492 GetControllerNameWorker ( 2493 IN EFI_GUID *ProtocolGuid, 2494 IN EFI_HANDLE DriverBindingHandle, 2495 IN EFI_HANDLE ControllerHandle, 2496 IN EFI_HANDLE ChildHandle, 2497 OUT CHAR16 **ControllerName 2498 ) 2499 { 2500 EFI_STATUS Status; 2501 CHAR8 *BestLanguage; 2502 EFI_COMPONENT_NAME_PROTOCOL *ComponentName; 2503 2504 // 2505 // Retrieve Component Name (2) protocol instance on the driver binding handle and 2506 // find the best language this instance supports. 2507 // 2508 Status = GetComponentNameWorker ( 2509 ProtocolGuid, 2510 DriverBindingHandle, 2511 &ComponentName, 2512 &BestLanguage 2513 ); 2514 if (EFI_ERROR (Status)) { 2515 return Status; 2516 } 2517 2518 // 2519 // Get the controller name from Component Name (2) protocol instance on the driver binging handle. 2520 // 2521 Status = ComponentName->GetControllerName ( 2522 ComponentName, 2523 ControllerHandle, 2524 ChildHandle, 2525 BestLanguage, 2526 ControllerName 2527 ); 2528 FreePool (BestLanguage); 2529 2530 return Status; 2531 } 2532 2533 /** 2534 2535 This function gets controller name from Component Name 2 protocol interface and Component Name protocol interface 2536 in turn. It first tries UEFI 2.0 Component Name 2 protocol interface and try to get the controller name. 2537 If the attempt fails, it then gets the controller name from EFI 1.1 Component Name protocol for backward 2538 compatibility support. 2539 2540 @param DriverBindingHandle The handle on which the Component Name (2) protocol instance is retrieved. 2541 @param ControllerHandle The handle of a controller that the driver specified by This is managing. 2542 This handle specifies the controller whose name is to be returned. 2543 @param ChildHandle The handle of the child controller to retrieve the name of. This is an 2544 optional parameter that may be NULL. It will be NULL for device drivers. 2545 It will also be NULL for bus drivers that attempt to retrieve the name 2546 of the bus controller. It will not be NULL for a bus driver that attempts 2547 to retrieve the name of a child controller. 2548 @param ControllerName A pointer to the Unicode string to return. This Unicode string 2549 is the name of the controller specified by ControllerHandle and ChildHandle. 2550 2551 @retval EFI_SUCCESS The controller name is successfully retrieved from Component Name (2) protocol 2552 interface. 2553 @retval Other The controller name cannot be retrieved from Component Name (2) protocol. 2554 2555 **/ 2556 EFI_STATUS 2557 DriverHealthGetControllerName ( 2558 IN EFI_HANDLE DriverBindingHandle, 2559 IN EFI_HANDLE ControllerHandle, 2560 IN EFI_HANDLE ChildHandle, 2561 OUT CHAR16 **ControllerName 2562 ) 2563 { 2564 EFI_STATUS Status; 2565 2566 // 2567 // Get controller name from UEFI 2.0 Component Name 2 protocol interface. 2568 // 2569 Status = GetControllerNameWorker ( 2570 &gEfiComponentName2ProtocolGuid, 2571 DriverBindingHandle, 2572 ControllerHandle, 2573 ChildHandle, 2574 ControllerName 2575 ); 2576 if (EFI_ERROR (Status)) { 2577 // 2578 // If it fails to get the controller name from Component Name protocol interface, we should fall back on 2579 // EFI 1.1 Component Name protocol interface. 2580 // 2581 Status = GetControllerNameWorker ( 2582 &gEfiComponentNameProtocolGuid, 2583 DriverBindingHandle, 2584 ControllerHandle, 2585 ChildHandle, 2586 ControllerName 2587 ); 2588 } 2589 2590 return Status; 2591 } 2592