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