]> git.proxmox.com Git - mirror_edk2.git/blob - IntelFrameworkModulePkg/Universal/BdsDxe/DeviceMngr/DeviceManager.c
Fix bug that cursor position will change when enter newly registered HII Form after...
[mirror_edk2.git] / IntelFrameworkModulePkg / Universal / BdsDxe / DeviceMngr / DeviceManager.c
1 /** @file
2 The platform device manager reference implementation
3
4 Copyright (c) 2004 - 2010, 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 EFI_GUID mDeviceManagerGuid = DEVICE_MANAGER_FORMSET_GUID;
36 EFI_GUID mDriverHealthGuid = DRIVER_HEALTH_FORMSET_GUID;
37
38 DEVICE_MANAGER_MENU_ITEM mDeviceManagerMenuItemTable[] = {
39 { STRING_TOKEN (STR_DISK_DEVICE), EFI_DISK_DEVICE_CLASS },
40 { STRING_TOKEN (STR_VIDEO_DEVICE), EFI_VIDEO_DEVICE_CLASS },
41 { STRING_TOKEN (STR_NETWORK_DEVICE), EFI_NETWORK_DEVICE_CLASS },
42 { STRING_TOKEN (STR_INPUT_DEVICE), EFI_INPUT_DEVICE_CLASS },
43 { STRING_TOKEN (STR_ON_BOARD_DEVICE), EFI_ON_BOARD_DEVICE_CLASS },
44 { STRING_TOKEN (STR_OTHER_DEVICE), EFI_OTHER_DEVICE_CLASS }
45 };
46
47 HII_VENDOR_DEVICE_PATH mDeviceManagerHiiVendorDevicePath = {
48 {
49 {
50 HARDWARE_DEVICE_PATH,
51 HW_VENDOR_DP,
52 {
53 (UINT8) (sizeof (VENDOR_DEVICE_PATH)),
54 (UINT8) ((sizeof (VENDOR_DEVICE_PATH)) >> 8)
55 }
56 },
57 //
58 // {102579A0-3686-466e-ACD8-80C087044F4A}
59 //
60 { 0x102579a0, 0x3686, 0x466e, { 0xac, 0xd8, 0x80, 0xc0, 0x87, 0x4, 0x4f, 0x4a } }
61 },
62 {
63 END_DEVICE_PATH_TYPE,
64 END_ENTIRE_DEVICE_PATH_SUBTYPE,
65 {
66 (UINT8) (END_DEVICE_PATH_LENGTH),
67 (UINT8) ((END_DEVICE_PATH_LENGTH) >> 8)
68 }
69 }
70 };
71
72 HII_VENDOR_DEVICE_PATH mDriverHealthHiiVendorDevicePath = {
73 {
74 {
75 HARDWARE_DEVICE_PATH,
76 HW_VENDOR_DP,
77 {
78 (UINT8) (sizeof (VENDOR_DEVICE_PATH)),
79 (UINT8) ((sizeof (VENDOR_DEVICE_PATH)) >> 8)
80 }
81 },
82 //
83 // {D8F76651-1675-4986-BED4-3824B2F1F4C8}
84 //
85 { 0xd8f76651, 0x1675, 0x4986, { 0xbe, 0xd4, 0x38, 0x24, 0xb2, 0xf1, 0xf4, 0xc8 } }
86 },
87 {
88 END_DEVICE_PATH_TYPE,
89 END_ENTIRE_DEVICE_PATH_SUBTYPE,
90 {
91 (UINT8) (END_DEVICE_PATH_LENGTH),
92 (UINT8) ((END_DEVICE_PATH_LENGTH) >> 8)
93 }
94 }
95 };
96
97 /**
98 This function is invoked if user selected a interactive opcode from Device Manager's
99 Formset. The decision by user is saved to gCallbackKey for later processing. If
100 user set VBIOS, the new value is saved to EFI variable.
101
102 @param This Points to the EFI_HII_CONFIG_ACCESS_PROTOCOL.
103 @param Action Specifies the type of action taken by the browser.
104 @param QuestionId A unique value which is sent to the original exporting driver
105 so that it can identify the type of data to expect.
106 @param Type The type of value for the question.
107 @param Value A pointer to the data being sent to the original exporting driver.
108 @param ActionRequest On return, points to the action requested by the callback function.
109
110 @retval EFI_SUCCESS The callback successfully handled the action.
111 @retval EFI_INVALID_PARAMETER The setup browser call this function with invalid parameters.
112
113 **/
114 EFI_STATUS
115 EFIAPI
116 DeviceManagerCallback (
117 IN CONST EFI_HII_CONFIG_ACCESS_PROTOCOL *This,
118 IN EFI_BROWSER_ACTION Action,
119 IN EFI_QUESTION_ID QuestionId,
120 IN UINT8 Type,
121 IN EFI_IFR_TYPE_VALUE *Value,
122 OUT EFI_BROWSER_ACTION_REQUEST *ActionRequest
123 )
124 {
125 if ((Action == EFI_BROWSER_ACTION_FORM_OPEN) || (Action == EFI_BROWSER_ACTION_FORM_CLOSE)) {
126 //
127 // Do nothing for UEFI OPEN/CLOSE Action
128 //
129 return EFI_SUCCESS;
130 }
131
132 if ((Value == NULL) || (ActionRequest == NULL)) {
133 return EFI_INVALID_PARAMETER;
134 }
135
136 gCallbackKey = QuestionId;
137
138 //
139 // Request to exit SendForm(), so as to switch to selected form
140 //
141 *ActionRequest = EFI_BROWSER_ACTION_REQUEST_EXIT;
142
143 return EFI_SUCCESS;
144 }
145
146 /**
147
148 This function registers HII packages to HII database.
149
150 @retval EFI_SUCCESS HII packages for the Device Manager were registered successfully.
151 @retval EFI_OUT_OF_RESOURCES HII packages for the Device Manager failed to be registered.
152
153 **/
154 EFI_STATUS
155 InitializeDeviceManager (
156 VOID
157 )
158 {
159 EFI_STATUS Status;
160
161 //
162 // Install Device Path Protocol and Config Access protocol to driver handle
163 //
164 Status = gBS->InstallMultipleProtocolInterfaces (
165 &gDeviceManagerPrivate.DriverHandle,
166 &gEfiDevicePathProtocolGuid,
167 &mDeviceManagerHiiVendorDevicePath,
168 &gEfiHiiConfigAccessProtocolGuid,
169 &gDeviceManagerPrivate.ConfigAccess,
170 NULL
171 );
172 ASSERT_EFI_ERROR (Status);
173
174 Status = gBS->InstallMultipleProtocolInterfaces (
175 &gDeviceManagerPrivate.DriverHealthHandle,
176 &gEfiDevicePathProtocolGuid,
177 &mDriverHealthHiiVendorDevicePath,
178 &gEfiHiiConfigAccessProtocolGuid,
179 &gDeviceManagerPrivate.DriverHealthConfigAccess,
180 NULL
181 );
182 ASSERT_EFI_ERROR (Status);
183
184 return Status;
185 }
186
187 /**
188 Extract the displayed formset for given HII handle and class guid.
189
190 @param Handle The HII handle.
191 @param SetupClassGuid The class guid specifies which form set will be displayed.
192 @param FormSetTitle Formset title string.
193 @param FormSetHelp Formset help string.
194
195 @retval TRUE The formset for given HII handle will be displayed.
196 @return FALSE The formset for given HII handle will not be displayed.
197
198 **/
199 BOOLEAN
200 ExtractDisplayedHiiFormFromHiiHandle (
201 IN EFI_HII_HANDLE Handle,
202 IN EFI_GUID *SetupClassGuid,
203 OUT EFI_STRING_ID *FormSetTitle,
204 OUT EFI_STRING_ID *FormSetHelp
205 )
206 {
207 EFI_STATUS Status;
208 UINTN BufferSize;
209 EFI_HII_PACKAGE_LIST_HEADER *HiiPackageList;
210 UINT8 *Package;
211 UINT8 *OpCodeData;
212 UINT32 Offset;
213 UINT32 Offset2;
214 UINT32 PackageListLength;
215 EFI_HII_PACKAGE_HEADER PackageHeader;
216 EFI_GUID *ClassGuid;
217 UINT8 ClassGuidNum;
218
219 ASSERT (Handle != NULL);
220 ASSERT (SetupClassGuid != NULL);
221 ASSERT (FormSetTitle != NULL);
222 ASSERT (FormSetHelp != NULL);
223
224 *FormSetTitle = 0;
225 *FormSetHelp = 0;
226 ClassGuidNum = 0;
227 ClassGuid = NULL;
228
229 //
230 // Get HII PackageList
231 //
232 BufferSize = 0;
233 HiiPackageList = NULL;
234 Status = gHiiDatabase->ExportPackageLists (gHiiDatabase, Handle, &BufferSize, HiiPackageList);
235 //
236 // Handle is a invalid handle. Check if Handle is corrupted.
237 //
238 ASSERT (Status != EFI_NOT_FOUND);
239 //
240 // The return status should always be EFI_BUFFER_TOO_SMALL as input buffer's size is 0.
241 //
242 ASSERT (Status == EFI_BUFFER_TOO_SMALL);
243
244 HiiPackageList = AllocatePool (BufferSize);
245 ASSERT (HiiPackageList != NULL);
246
247 Status = gHiiDatabase->ExportPackageLists (gHiiDatabase, Handle, &BufferSize, HiiPackageList);
248 if (EFI_ERROR (Status)) {
249 return FALSE;
250 }
251
252 //
253 // Get Form package from this HII package List
254 //
255 Offset = sizeof (EFI_HII_PACKAGE_LIST_HEADER);
256 Offset2 = 0;
257 PackageListLength = ReadUnaligned32 (&HiiPackageList->PackageLength);
258
259 while (Offset < PackageListLength) {
260 Package = ((UINT8 *) HiiPackageList) + Offset;
261 CopyMem (&PackageHeader, Package, sizeof (EFI_HII_PACKAGE_HEADER));
262
263 if (PackageHeader.Type == EFI_HII_PACKAGE_FORMS) {
264 //
265 // Search FormSet Opcode in this Form Package
266 //
267 Offset2 = sizeof (EFI_HII_PACKAGE_HEADER);
268 while (Offset2 < PackageHeader.Length) {
269 OpCodeData = Package + Offset2;
270
271 if (((EFI_IFR_OP_HEADER *) OpCodeData)->OpCode == EFI_IFR_FORM_SET_OP) {
272 if (((EFI_IFR_OP_HEADER *) OpCodeData)->Length > OFFSET_OF (EFI_IFR_FORM_SET, Flags)) {
273 //
274 // Find FormSet OpCode
275 //
276 ClassGuidNum = (UINT8) (((EFI_IFR_FORM_SET *) OpCodeData)->Flags & 0x3);
277 ClassGuid = (EFI_GUID *) (VOID *)(OpCodeData + sizeof (EFI_IFR_FORM_SET));
278 while (ClassGuidNum-- > 0) {
279 if (CompareGuid (SetupClassGuid, ClassGuid)) {
280 CopyMem (FormSetTitle, &((EFI_IFR_FORM_SET *) OpCodeData)->FormSetTitle, sizeof (EFI_STRING_ID));
281 CopyMem (FormSetHelp, &((EFI_IFR_FORM_SET *) OpCodeData)->Help, sizeof (EFI_STRING_ID));
282 FreePool (HiiPackageList);
283 return TRUE;
284 }
285 ClassGuid ++;
286 }
287 } else {
288 CopyMem (FormSetTitle, &((EFI_IFR_FORM_SET *) OpCodeData)->FormSetTitle, sizeof (EFI_STRING_ID));
289 CopyMem (FormSetHelp, &((EFI_IFR_FORM_SET *) OpCodeData)->Help, sizeof (EFI_STRING_ID));
290 FreePool (HiiPackageList);
291 return TRUE;
292 }
293 }
294
295 //
296 // Go to next opcode
297 //
298 Offset2 += ((EFI_IFR_OP_HEADER *) OpCodeData)->Length;
299 }
300 }
301
302 //
303 // Go to next package
304 //
305 Offset += PackageHeader.Length;
306 }
307
308 FreePool (HiiPackageList);
309
310 return FALSE;
311 }
312
313 /**
314 Call the browser and display the device manager to allow user
315 to configure the platform.
316
317 This function create the dynamic content for device manager. It includes
318 section header for all class of devices, one-of opcode to set VBIOS.
319
320 @retval EFI_SUCCESS Operation is successful.
321 @return Other values if failed to clean up the dynamic content from HII
322 database.
323
324 **/
325 EFI_STATUS
326 CallDeviceManager (
327 VOID
328 )
329 {
330 EFI_STATUS Status;
331 UINTN Index;
332 EFI_STRING String;
333 EFI_STRING_ID Token;
334 EFI_STRING_ID TokenHelp;
335 EFI_HII_HANDLE *HiiHandles;
336 EFI_HII_HANDLE HiiHandle;
337 EFI_STRING_ID FormSetTitle;
338 EFI_STRING_ID FormSetHelp;
339 EFI_BROWSER_ACTION_REQUEST ActionRequest;
340 VOID *StartOpCodeHandle;
341 VOID *EndOpCodeHandle;
342 EFI_IFR_GUID_LABEL *StartLabel;
343 EFI_IFR_GUID_LABEL *EndLabel;
344 UINTN NumHandles;
345 EFI_HANDLE *DriverHealthHandles;
346
347 HiiHandles = NULL;
348 Status = EFI_SUCCESS;
349 gCallbackKey = 0;
350 NumHandles = 0;
351 DriverHealthHandles = NULL;
352
353 //
354 // Connect all prior to entering the platform setup menu.
355 //
356 if (!gConnectAllHappened) {
357 BdsLibConnectAllDriversToAllControllers ();
358 gConnectAllHappened = TRUE;
359 }
360
361 HiiHandle = gDeviceManagerPrivate.HiiHandle;
362 if (HiiHandle == NULL) {
363 //
364 // Publish our HII data.
365 //
366 HiiHandle = HiiAddPackages (
367 &mDeviceManagerGuid,
368 gDeviceManagerPrivate.DriverHandle,
369 DeviceManagerVfrBin,
370 BdsDxeStrings,
371 NULL
372 );
373 if (HiiHandle == NULL) {
374 return EFI_OUT_OF_RESOURCES;
375 }
376
377 gDeviceManagerPrivate.HiiHandle = HiiHandle;
378 }
379
380 //
381 // Create Subtitle OpCodes
382 //
383 //
384 // Allocate space for creation of UpdateData Buffer
385 //
386 StartOpCodeHandle = HiiAllocateOpCodeHandle ();
387 ASSERT (StartOpCodeHandle != NULL);
388
389 EndOpCodeHandle = HiiAllocateOpCodeHandle ();
390 ASSERT (EndOpCodeHandle != NULL);
391
392 //
393 // Create Hii Extend Label OpCode as the start opcode
394 //
395 StartLabel = (EFI_IFR_GUID_LABEL *) HiiCreateGuidOpCode (StartOpCodeHandle, &gEfiIfrTianoGuid, NULL, sizeof (EFI_IFR_GUID_LABEL));
396 StartLabel->ExtendOpCode = EFI_IFR_EXTEND_OP_LABEL;
397 StartLabel->Number = LABEL_DEVICES_LIST;
398
399 //
400 // Create Hii Extend Label OpCode as the end opcode
401 //
402 EndLabel = (EFI_IFR_GUID_LABEL *) HiiCreateGuidOpCode (EndOpCodeHandle, &gEfiIfrTianoGuid, NULL, sizeof (EFI_IFR_GUID_LABEL));
403 EndLabel->ExtendOpCode = EFI_IFR_EXTEND_OP_LABEL;
404 EndLabel->Number = LABEL_END;
405
406 HiiCreateSubTitleOpCode (StartOpCodeHandle, STRING_TOKEN (STR_DEVICES_LIST), 0, 0, 1);
407
408 //
409 // Get all the Hii handles
410 //
411 HiiHandles = HiiGetHiiHandles (NULL);
412 ASSERT (HiiHandles != NULL);
413
414 //
415 // Search for formset of each class type
416 //
417 for (Index = 0; HiiHandles[Index] != NULL; Index++) {
418 if (!ExtractDisplayedHiiFormFromHiiHandle (HiiHandles[Index], &gEfiHiiPlatformSetupFormsetGuid, &FormSetTitle, &FormSetHelp)) {
419 continue;
420 }
421
422 String = HiiGetString (HiiHandles[Index], FormSetTitle, NULL);
423 if (String == NULL) {
424 String = HiiGetString (HiiHandle, STR_MISSING_STRING, NULL);
425 ASSERT (String != NULL);
426 }
427 Token = HiiSetString (HiiHandle, 0, String, NULL);
428 FreePool (String);
429
430 String = HiiGetString (HiiHandles[Index], FormSetHelp, NULL);
431 if (String == NULL) {
432 String = HiiGetString (HiiHandle, STR_MISSING_STRING, NULL);
433 ASSERT (String != NULL);
434 }
435 TokenHelp = HiiSetString (HiiHandle, 0, String, NULL);
436 FreePool (String);
437
438 HiiCreateActionOpCode (
439 StartOpCodeHandle,
440 (EFI_QUESTION_ID) (Index + DEVICE_KEY_OFFSET),
441 Token,
442 TokenHelp,
443 EFI_IFR_FLAG_CALLBACK,
444 0
445 );
446 }
447
448 //
449 // Add End Opcode for Subtitle
450 //
451 HiiCreateEndOpCode (StartOpCodeHandle);
452
453 Status = gBS->LocateHandleBuffer (
454 ByProtocol,
455 &gEfiDriverHealthProtocolGuid,
456 NULL,
457 &NumHandles,
458 &DriverHealthHandles
459 );
460
461 //
462 // If there are no drivers installed driver health protocol, do not create driver health entry in UI
463 //
464 if (NumHandles != 0) {
465 //
466 // If driver health protocol is installed, create Driver Health subtitle and entry
467 //
468 HiiCreateSubTitleOpCode (StartOpCodeHandle, STRING_TOKEN (STR_DM_DRIVER_HEALTH_TITLE), 0, 0, 0);
469 HiiCreateActionOpCode (
470 StartOpCodeHandle, // Container for dynamic created opcodes
471 DEVICE_MANAGER_KEY_DRIVER_HEALTH, // Question ID
472 STRING_TOKEN(STR_DRIVER_HEALTH_ALL_HEALTHY), // Prompt text
473 STRING_TOKEN(STR_DRIVER_HEALTH_STATUS_HELP), // Help text
474 EFI_IFR_FLAG_CALLBACK, // Question flag
475 0 // Action String ID
476 );
477
478 //
479 // Check All Driver health status
480 //
481 if (!PlaformHealthStatusCheck ()) {
482 //
483 // At least one driver in the platform are not in healthy status
484 //
485 HiiSetString (HiiHandle, STRING_TOKEN (STR_DRIVER_HEALTH_ALL_HEALTHY), GetStringById (STRING_TOKEN (STR_DRIVER_NOT_HEALTH)), NULL);
486 } else {
487 //
488 // For the string of STR_DRIVER_HEALTH_ALL_HEALTHY previously has been updated and we need to update it while re-entry.
489 //
490 HiiSetString (HiiHandle, STRING_TOKEN (STR_DRIVER_HEALTH_ALL_HEALTHY), GetStringById (STRING_TOKEN (STR_DRIVER_HEALTH_ALL_HEALTHY)), NULL);
491 }
492 }
493
494 HiiUpdateForm (
495 HiiHandle,
496 &mDeviceManagerGuid,
497 DEVICE_MANAGER_FORM_ID,
498 StartOpCodeHandle,
499 EndOpCodeHandle
500 );
501
502 ActionRequest = EFI_BROWSER_ACTION_REQUEST_NONE;
503 Status = gFormBrowser2->SendForm (
504 gFormBrowser2,
505 &HiiHandle,
506 1,
507 &mDeviceManagerGuid,
508 0,
509 NULL,
510 &ActionRequest
511 );
512 if (ActionRequest == EFI_BROWSER_ACTION_REQUEST_RESET) {
513 EnableResetRequired ();
514 }
515
516 //
517 // We will have returned from processing a callback - user either hit ESC to exit, or selected
518 // a target to display
519 //
520 if ((gCallbackKey != 0) && (gCallbackKey != DEVICE_MANAGER_KEY_DRIVER_HEALTH)) {
521 ActionRequest = EFI_BROWSER_ACTION_REQUEST_NONE;
522 Status = gFormBrowser2->SendForm (
523 gFormBrowser2,
524 &HiiHandles[gCallbackKey - DEVICE_KEY_OFFSET],
525 1,
526 NULL,
527 0,
528 NULL,
529 &ActionRequest
530 );
531
532 if (ActionRequest == EFI_BROWSER_ACTION_REQUEST_RESET) {
533 EnableResetRequired ();
534 }
535
536 //
537 // Force return to Device Manager
538 //
539 gCallbackKey = FRONT_PAGE_KEY_DEVICE_MANAGER;
540 }
541
542 //
543 // Driver Health item chose.
544 //
545 if (gCallbackKey == DEVICE_MANAGER_KEY_DRIVER_HEALTH) {
546 CallDriverHealth ();
547 //
548 // Force return to Device Manager
549 //
550 gCallbackKey = FRONT_PAGE_KEY_DEVICE_MANAGER;
551 }
552
553 //
554 // Remove our packagelist from HII database.
555 //
556 HiiRemovePackages (HiiHandle);
557 gDeviceManagerPrivate.HiiHandle = NULL;
558
559 HiiFreeOpCodeHandle (StartOpCodeHandle);
560 HiiFreeOpCodeHandle (EndOpCodeHandle);
561 FreePool (HiiHandles);
562
563 return Status;
564 }
565
566 /**
567 This function is invoked if user selected a interactive opcode from Driver Health's
568 Formset. The decision by user is saved to gCallbackKey for later processing.
569
570 @param This Points to the EFI_HII_CONFIG_ACCESS_PROTOCOL.
571 @param Action Specifies the type of action taken by the browser.
572 @param QuestionId A unique value which is sent to the original exporting driver
573 so that it can identify the type of data to expect.
574 @param Type The type of value for the question.
575 @param Value A pointer to the data being sent to the original exporting driver.
576 @param ActionRequest On return, points to the action requested by the callback function.
577
578 @retval EFI_SUCCESS The callback successfully handled the action.
579 @retval EFI_INVALID_PARAMETER The setup browser call this function with invalid parameters.
580
581 **/
582 EFI_STATUS
583 EFIAPI
584 DriverHealthCallback (
585 IN CONST EFI_HII_CONFIG_ACCESS_PROTOCOL *This,
586 IN EFI_BROWSER_ACTION Action,
587 IN EFI_QUESTION_ID QuestionId,
588 IN UINT8 Type,
589 IN EFI_IFR_TYPE_VALUE *Value,
590 OUT EFI_BROWSER_ACTION_REQUEST *ActionRequest
591 )
592 {
593 if ((Action == EFI_BROWSER_ACTION_FORM_OPEN) || (Action == EFI_BROWSER_ACTION_FORM_CLOSE)) {
594 //
595 // Do nothing for UEFI OPEN/CLOSE Action
596 //
597 return EFI_SUCCESS;
598 }
599
600 if ((Value == NULL) || (ActionRequest == NULL)) {
601 return EFI_INVALID_PARAMETER;
602 }
603
604 gCallbackKey = QuestionId;
605
606 //
607 // Request to exit SendForm(), so as to switch to selected form
608 //
609 *ActionRequest = EFI_BROWSER_ACTION_REQUEST_EXIT;
610
611 return EFI_SUCCESS;
612 }
613
614 /**
615 Collect and display the platform's driver health relative information, allow user to do interactive
616 operation while the platform is unhealthy.
617
618 This function display a form which divided into two parts. The one list all modules which has installed
619 driver health protocol. The list usually contain driver name, controller name, and it's health info.
620 While the driver name can't be retrieved, will use device path as backup. The other part of the form provide
621 a choice to the user to repair all platform.
622
623 **/
624 VOID
625 CallDriverHealth (
626 VOID
627 )
628 {
629 EFI_STATUS Status;
630 EFI_HII_HANDLE HiiHandle;
631 EFI_BROWSER_ACTION_REQUEST ActionRequest;
632 EFI_IFR_GUID_LABEL *StartLabel;
633 EFI_IFR_GUID_LABEL *StartLabelRepair;
634 EFI_IFR_GUID_LABEL *EndLabel;
635 EFI_IFR_GUID_LABEL *EndLabelRepair;
636 VOID *StartOpCodeHandle;
637 VOID *EndOpCodeHandle;
638 VOID *StartOpCodeHandleRepair;
639 VOID *EndOpCodeHandleRepair;
640 UINTN Index;
641 EFI_STRING_ID Token;
642 EFI_STRING_ID TokenHelp;
643 EFI_STRING String;
644 EFI_STRING TmpString;
645 EFI_STRING DriverName;
646 EFI_STRING ControllerName;
647 LIST_ENTRY DriverHealthList;
648 DRIVER_HEALTH_INFO *DriverHealthInfo;
649 LIST_ENTRY *Link;
650 EFI_DEVICE_PATH_PROTOCOL *DriverDevicePath;
651 UINTN Length;
652
653 Index = 0;
654 Length = 0;
655 DriverHealthInfo = NULL;
656 DriverDevicePath = NULL;
657 InitializeListHead (&DriverHealthList);
658
659 HiiHandle = gDeviceManagerPrivate.DriverHealthHiiHandle;
660 if (HiiHandle == NULL) {
661 //
662 // Publish Driver Health HII data.
663 //
664 HiiHandle = HiiAddPackages (
665 &mDeviceManagerGuid,
666 gDeviceManagerPrivate.DriverHealthHandle,
667 DriverHealthVfrBin,
668 BdsDxeStrings,
669 NULL
670 );
671 if (HiiHandle == NULL) {
672 return;
673 }
674
675 gDeviceManagerPrivate.DriverHealthHiiHandle = HiiHandle;
676 }
677
678 //
679 // Allocate space for creation of UpdateData Buffer
680 //
681 StartOpCodeHandle = HiiAllocateOpCodeHandle ();
682 ASSERT (StartOpCodeHandle != NULL);
683
684 EndOpCodeHandle = HiiAllocateOpCodeHandle ();
685 ASSERT (EndOpCodeHandle != NULL);
686
687 StartOpCodeHandleRepair = HiiAllocateOpCodeHandle ();
688 ASSERT (StartOpCodeHandleRepair != NULL);
689
690 EndOpCodeHandleRepair = HiiAllocateOpCodeHandle ();
691 ASSERT (EndOpCodeHandleRepair != NULL);
692
693 //
694 // Create Hii Extend Label OpCode as the start opcode
695 //
696 StartLabel = (EFI_IFR_GUID_LABEL *) HiiCreateGuidOpCode (StartOpCodeHandle, &gEfiIfrTianoGuid, NULL, sizeof (EFI_IFR_GUID_LABEL));
697 StartLabel->ExtendOpCode = EFI_IFR_EXTEND_OP_LABEL;
698 StartLabel->Number = LABEL_DRIVER_HEALTH;
699
700 //
701 // Create Hii Extend Label OpCode as the start opcode
702 //
703 StartLabelRepair = (EFI_IFR_GUID_LABEL *) HiiCreateGuidOpCode (StartOpCodeHandleRepair, &gEfiIfrTianoGuid, NULL, sizeof (EFI_IFR_GUID_LABEL));
704 StartLabelRepair->ExtendOpCode = EFI_IFR_EXTEND_OP_LABEL;
705 StartLabelRepair->Number = LABEL_DRIVER_HEALTH_REAPIR_ALL;
706
707 //
708 // Create Hii Extend Label OpCode as the end opcode
709 //
710 EndLabel = (EFI_IFR_GUID_LABEL *) HiiCreateGuidOpCode (EndOpCodeHandle, &gEfiIfrTianoGuid, NULL, sizeof (EFI_IFR_GUID_LABEL));
711 EndLabel->ExtendOpCode = EFI_IFR_EXTEND_OP_LABEL;
712 EndLabel->Number = LABEL_DRIVER_HEALTH_END;
713
714 //
715 // Create Hii Extend Label OpCode as the end opcode
716 //
717 EndLabelRepair = (EFI_IFR_GUID_LABEL *) HiiCreateGuidOpCode (EndOpCodeHandleRepair, &gEfiIfrTianoGuid, NULL, sizeof (EFI_IFR_GUID_LABEL));
718 EndLabelRepair->ExtendOpCode = EFI_IFR_EXTEND_OP_LABEL;
719 EndLabelRepair->Number = LABEL_DRIVER_HEALTH_REAPIR_ALL_END;
720
721 HiiCreateSubTitleOpCode (StartOpCodeHandle, STRING_TOKEN (STR_DH_STATUS_LIST), 0, 0, 1);
722
723 Status = GetAllControllersHealthStatus (&DriverHealthList);
724 ASSERT (Status != EFI_OUT_OF_RESOURCES);
725
726 Link = GetFirstNode (&DriverHealthList);
727
728 while (!IsNull (&DriverHealthList, Link)) {
729 DriverHealthInfo = DEVICE_MANAGER_HEALTH_INFO_FROM_LINK (Link);
730
731 //
732 // Assume no line strings is longer than 512 bytes.
733 //
734 String = (EFI_STRING) AllocateZeroPool (0x200);
735 ASSERT (String != NULL);
736
737 Status = DriverHealthGetDriverName (DriverHealthInfo->DriverHandle, &DriverName);
738 if (EFI_ERROR (Status)) {
739 //
740 // Can not get the Driver name, so use the Device path
741 //
742 DriverDevicePath = DevicePathFromHandle (DriverHealthInfo->DriverHandle);
743 DriverName = DevicePathToStr (DriverDevicePath);
744 }
745 //
746 // Add the Driver name & Controller name into FormSetTitle string
747 //
748 StrnCat (String, DriverName, StrLen (DriverName));
749
750
751 Status = DriverHealthGetControllerName (
752 DriverHealthInfo->DriverHandle,
753 DriverHealthInfo->ControllerHandle,
754 DriverHealthInfo->ChildHandle,
755 &ControllerName
756 );
757
758 if (!EFI_ERROR (Status)) {
759 //
760 // Can not get the Controller name, just let it empty.
761 //
762 StrnCat (String, L" ", StrLen (L" "));
763 StrnCat (String, ControllerName, StrLen (ControllerName));
764 }
765
766 //
767 // Add the message of the Module itself provided after the string item.
768 //
769 if ((DriverHealthInfo->MessageList != NULL) && (DriverHealthInfo->MessageList->StringId != 0)) {
770 StrnCat (String, L" ", StrLen (L" "));
771 TmpString = HiiGetString (
772 DriverHealthInfo->MessageList->HiiHandle,
773 DriverHealthInfo->MessageList->StringId,
774 NULL
775 );
776 //
777 // Assert if can not retrieve the message string
778 //
779 ASSERT (TmpString != NULL);
780 StrnCat (String, TmpString, StrLen (TmpString));
781 FreePool (TmpString);
782 } else {
783 //
784 // Update the string will be displayed base on the driver's health status
785 //
786 switch(DriverHealthInfo->HealthStatus) {
787 case EfiDriverHealthStatusRepairRequired:
788 Length = StrLen (GetStringById (STRING_TOKEN (STR_REPAIR_REQUIRED)));
789 StrnCat (String, GetStringById (STRING_TOKEN (STR_REPAIR_REQUIRED)), Length);
790 break;
791 case EfiDriverHealthStatusConfigurationRequired:
792 Length = StrLen (GetStringById (STRING_TOKEN (STR_CONFIGURATION_REQUIRED)));
793 StrnCat (String, GetStringById (STRING_TOKEN (STR_CONFIGURATION_REQUIRED)), Length);
794 break;
795 case EfiDriverHealthStatusFailed:
796 Length = StrLen (GetStringById (STRING_TOKEN (STR_OPERATION_FAILED)));
797 StrnCat (String, GetStringById (STRING_TOKEN (STR_OPERATION_FAILED)), Length);
798 break;
799 case EfiDriverHealthStatusReconnectRequired:
800 Length = StrLen (GetStringById (STRING_TOKEN (STR_RECONNECT_REQUIRED)));
801 StrnCat (String, GetStringById (STRING_TOKEN (STR_RECONNECT_REQUIRED)), Length);
802 break;
803 case EfiDriverHealthStatusRebootRequired:
804 Length = StrLen (GetStringById (STRING_TOKEN (STR_REBOOT_REQUIRED)));
805 StrnCat (String, GetStringById (STRING_TOKEN (STR_REBOOT_REQUIRED)), Length);
806 break;
807 default:
808 Length = StrLen (GetStringById (STRING_TOKEN (STR_DRIVER_HEALTH_HEALTHY)));
809 StrnCat (String, GetStringById (STRING_TOKEN (STR_DRIVER_HEALTH_HEALTHY)), Length);
810 break;
811 }
812 }
813
814 Token = HiiSetString (HiiHandle, 0, String, NULL);
815 FreePool (String);
816
817 TokenHelp = HiiSetString (HiiHandle, 0, GetStringById( STRING_TOKEN (STR_DH_REPAIR_SINGLE_HELP)), NULL);
818
819 HiiCreateActionOpCode (
820 StartOpCodeHandle,
821 (EFI_QUESTION_ID) (Index + DRIVER_HEALTH_KEY_OFFSET),
822 Token,
823 TokenHelp,
824 EFI_IFR_FLAG_CALLBACK,
825 0
826 );
827 Index++;
828 Link = GetNextNode (&DriverHealthList, Link);
829 }
830
831 //
832 // Add End Opcode for Subtitle
833 //
834 HiiCreateEndOpCode (StartOpCodeHandle);
835
836 HiiCreateSubTitleOpCode (StartOpCodeHandleRepair, STRING_TOKEN (STR_DRIVER_HEALTH_REPAIR_ALL), 0, 0, 1);
837 TokenHelp = HiiSetString (HiiHandle, 0, GetStringById( STRING_TOKEN (STR_DH_REPAIR_ALL_HELP)), NULL);
838
839 if (PlaformHealthStatusCheck ()) {
840 //
841 // No action need to do for the platform
842 //
843 Token = HiiSetString (HiiHandle, 0, GetStringById( STRING_TOKEN (STR_DRIVER_HEALTH_ALL_HEALTHY)), NULL);
844 HiiCreateActionOpCode (
845 StartOpCodeHandleRepair,
846 0,
847 Token,
848 TokenHelp,
849 EFI_IFR_FLAG_READ_ONLY,
850 0
851 );
852 } else {
853 //
854 // Create ActionOpCode only while the platform need to do health related operation.
855 //
856 Token = HiiSetString (HiiHandle, 0, GetStringById( STRING_TOKEN (STR_DH_REPAIR_ALL_TITLE)), NULL);
857 HiiCreateActionOpCode (
858 StartOpCodeHandleRepair,
859 (EFI_QUESTION_ID) DRIVER_HEALTH_REPAIR_ALL_KEY,
860 Token,
861 TokenHelp,
862 EFI_IFR_FLAG_CALLBACK,
863 0
864 );
865 }
866
867 HiiCreateEndOpCode (StartOpCodeHandleRepair);
868
869 Status = HiiUpdateForm (
870 HiiHandle,
871 &mDriverHealthGuid,
872 DRIVER_HEALTH_FORM_ID,
873 StartOpCodeHandle,
874 EndOpCodeHandle
875 );
876 ASSERT (Status != EFI_NOT_FOUND);
877 ASSERT (Status != EFI_BUFFER_TOO_SMALL);
878
879 Status = HiiUpdateForm (
880 HiiHandle,
881 &mDriverHealthGuid,
882 DRIVER_HEALTH_FORM_ID,
883 StartOpCodeHandleRepair,
884 EndOpCodeHandleRepair
885 );
886 ASSERT (Status != EFI_NOT_FOUND);
887 ASSERT (Status != EFI_BUFFER_TOO_SMALL);
888
889 ActionRequest = EFI_BROWSER_ACTION_REQUEST_NONE;
890 Status = gFormBrowser2->SendForm (
891 gFormBrowser2,
892 &HiiHandle,
893 1,
894 &mDriverHealthGuid,
895 DRIVER_HEALTH_FORM_ID,
896 NULL,
897 &ActionRequest
898 );
899 if (ActionRequest == EFI_BROWSER_ACTION_REQUEST_RESET) {
900 EnableResetRequired ();
901 }
902
903 //
904 // We will have returned from processing a callback - user either hit ESC to exit, or selected
905 // a target to display.
906 // Process the diver health status states here.
907 //
908 if (gCallbackKey >= DRIVER_HEALTH_KEY_OFFSET && gCallbackKey != DRIVER_HEALTH_REPAIR_ALL_KEY) {
909 ActionRequest = EFI_BROWSER_ACTION_REQUEST_NONE;
910
911 Link = GetFirstNode (&DriverHealthList);
912 Index = 0;
913
914 while (!IsNull (&DriverHealthList, Link)) {
915 //
916 // Got the item relative node in the List
917 //
918 if (Index == (gCallbackKey - DRIVER_HEALTH_KEY_OFFSET)) {
919 DriverHealthInfo = DEVICE_MANAGER_HEALTH_INFO_FROM_LINK (Link);
920 //
921 // Process the driver's healthy status for the specify module
922 //
923 ProcessSingleControllerHealth (
924 DriverHealthInfo->DriverHealth,
925 DriverHealthInfo->ControllerHandle,
926 DriverHealthInfo->ChildHandle,
927 DriverHealthInfo->HealthStatus,
928 &(DriverHealthInfo->MessageList),
929 DriverHealthInfo->HiiHandle
930 );
931 break;
932 }
933 Index++;
934 Link = GetNextNode (&DriverHealthList, Link);
935 }
936
937 if (ActionRequest == EFI_BROWSER_ACTION_REQUEST_RESET) {
938 EnableResetRequired ();
939 }
940
941 //
942 // Force return to the form of Driver Health in Device Manager
943 //
944 gCallbackKey = DRIVER_HEALTH_RETURN_KEY;
945 }
946
947 //
948 // Repair the whole platform
949 //
950 if (gCallbackKey == DRIVER_HEALTH_REPAIR_ALL_KEY) {
951 ActionRequest = EFI_BROWSER_ACTION_REQUEST_NONE;
952
953 PlatformRepairAll (&DriverHealthList);
954
955 gCallbackKey = DRIVER_HEALTH_RETURN_KEY;
956 }
957
958 //
959 // Remove driver health packagelist from HII database.
960 //
961 HiiRemovePackages (HiiHandle);
962 gDeviceManagerPrivate.DriverHealthHiiHandle = NULL;
963
964 //
965 // Free driver health info list
966 //
967 while (!IsListEmpty (&DriverHealthList)) {
968
969 Link = GetFirstNode(&DriverHealthList);
970 DriverHealthInfo = DEVICE_MANAGER_HEALTH_INFO_FROM_LINK (Link);
971 RemoveEntryList (Link);
972
973 if (DriverHealthInfo->MessageList != NULL) {
974 FreePool(DriverHealthInfo->MessageList);
975 FreePool (DriverHealthInfo);
976 }
977 }
978
979 HiiFreeOpCodeHandle (StartOpCodeHandle);
980 HiiFreeOpCodeHandle (EndOpCodeHandle);
981 HiiFreeOpCodeHandle (StartOpCodeHandleRepair);
982 HiiFreeOpCodeHandle (EndOpCodeHandleRepair);
983
984 if (gCallbackKey == DRIVER_HEALTH_RETURN_KEY) {
985 //
986 // Force return to Driver Health Form
987 //
988 gCallbackKey = DEVICE_MANAGER_KEY_DRIVER_HEALTH;
989 CallDriverHealth ();
990 }
991 }
992
993
994 /**
995 Check the Driver Health status of a single controller and try to process it if not healthy.
996
997 This function called by CheckAllControllersHealthStatus () function in order to process a specify
998 contoller's health state.
999
1000 @param DriverHealthList A Pointer to the list contain all of the platform driver health information.
1001 @param DriverHandle The handle of driver.
1002 @param ControllerHandle The class guid specifies which form set will be displayed.
1003 @param ChildHandle The handle of the child controller to retrieve the health
1004 status on. This is an optional parameter that may be NULL.
1005 @param DriverHealth A pointer to the EFI_DRIVER_HEALTH_PROTOCOL instance.
1006 @param HealthStatus The health status of the controller.
1007
1008 @retval EFI_INVALID_PARAMETER HealthStatus or DriverHealth is NULL.
1009 @retval HealthStatus The Health status of specify controller.
1010 @retval EFI_OUT_OF_RESOURCES The list of Driver Health Protocol handles can not be retrieved.
1011 @retval EFI_NOT_FOUND No controller in the platform install Driver Health Protocol.
1012 @retval EFI_SUCCESS The Health related operation has been taken successfully.
1013
1014 **/
1015 EFI_STATUS
1016 EFIAPI
1017 GetSingleControllerHealthStatus (
1018 IN OUT LIST_ENTRY *DriverHealthList,
1019 IN EFI_HANDLE DriverHandle,
1020 IN EFI_HANDLE ControllerHandle, OPTIONAL
1021 IN EFI_HANDLE ChildHandle, OPTIONAL
1022 IN EFI_DRIVER_HEALTH_PROTOCOL *DriverHealth,
1023 IN EFI_DRIVER_HEALTH_STATUS *HealthStatus
1024 )
1025 {
1026 EFI_STATUS Status;
1027 EFI_DRIVER_HEALTH_HII_MESSAGE *MessageList;
1028 EFI_HII_HANDLE FormHiiHandle;
1029 DRIVER_HEALTH_INFO *DriverHealthInfo;
1030
1031 if (HealthStatus == NULL) {
1032 //
1033 // If HealthStatus is NULL, then return EFI_INVALID_PARAMETER
1034 //
1035 return EFI_INVALID_PARAMETER;
1036 }
1037
1038 //
1039 // Assume the HealthStatus is healthy
1040 //
1041 *HealthStatus = EfiDriverHealthStatusHealthy;
1042
1043 if (DriverHealth == NULL) {
1044 //
1045 // If DriverHealth is NULL, then return EFI_INVALID_PARAMETER
1046 //
1047 return EFI_INVALID_PARAMETER;
1048 }
1049
1050 if (ControllerHandle == NULL) {
1051 //
1052 // If ControllerHandle is NULL, the return the cumulative health status of the driver
1053 //
1054 Status = DriverHealth->GetHealthStatus (DriverHealth, NULL, NULL, HealthStatus, NULL, NULL);
1055 if (*HealthStatus == EfiDriverHealthStatusHealthy) {
1056 //
1057 // Add the driver health related information into the list
1058 //
1059 DriverHealthInfo = AllocateZeroPool (sizeof (DRIVER_HEALTH_INFO));
1060 if (DriverHealthInfo == NULL) {
1061 return EFI_OUT_OF_RESOURCES;
1062 }
1063
1064 DriverHealthInfo->Signature = DEVICE_MANAGER_DRIVER_HEALTH_INFO_SIGNATURE;
1065 DriverHealthInfo->DriverHandle = DriverHandle;
1066 DriverHealthInfo->ControllerHandle = NULL;
1067 DriverHealthInfo->ChildHandle = NULL;
1068 DriverHealthInfo->HiiHandle = NULL;
1069 DriverHealthInfo->DriverHealth = DriverHealth;
1070 DriverHealthInfo->MessageList = NULL;
1071 DriverHealthInfo->HealthStatus = *HealthStatus;
1072
1073 InsertTailList (DriverHealthList, &DriverHealthInfo->Link);
1074 }
1075 return Status;
1076 }
1077
1078 MessageList = NULL;
1079 FormHiiHandle = NULL;
1080
1081 //
1082 // Collect the health status with the optional HII message list
1083 //
1084 Status = DriverHealth->GetHealthStatus (DriverHealth, ControllerHandle, ChildHandle, HealthStatus, &MessageList, &FormHiiHandle);
1085
1086 if (EFI_ERROR (Status)) {
1087 //
1088 // If the health status could not be retrieved, then return immediately
1089 //
1090 return Status;
1091 }
1092
1093 //
1094 // Add the driver health related information into the list
1095 //
1096 DriverHealthInfo = AllocateZeroPool (sizeof (DRIVER_HEALTH_INFO));
1097 if (DriverHealthInfo == NULL) {
1098 return EFI_OUT_OF_RESOURCES;
1099 }
1100
1101 DriverHealthInfo->Signature = DEVICE_MANAGER_DRIVER_HEALTH_INFO_SIGNATURE;
1102 DriverHealthInfo->DriverHandle = DriverHandle;
1103 DriverHealthInfo->ControllerHandle = ControllerHandle;
1104 DriverHealthInfo->ChildHandle = ChildHandle;
1105 DriverHealthInfo->HiiHandle = FormHiiHandle;
1106 DriverHealthInfo->DriverHealth = DriverHealth;
1107 DriverHealthInfo->MessageList = MessageList;
1108 DriverHealthInfo->HealthStatus = *HealthStatus;
1109
1110 InsertTailList (DriverHealthList, &DriverHealthInfo->Link);
1111
1112 return EFI_SUCCESS;
1113 }
1114
1115 /**
1116 Collects all the EFI Driver Health Protocols currently present in the EFI Handle Database,
1117 and queries each EFI Driver Health Protocol to determine if one or more of the controllers
1118 managed by each EFI Driver Health Protocol instance are not healthy.
1119
1120 @param DriverHealthList A Pointer to the list contain all of the platform driver health
1121 information.
1122
1123 @retval EFI_NOT_FOUND No controller in the platform install Driver Health Protocol.
1124 @retval EFI_SUCCESS All the controllers in the platform are healthy.
1125 @retval EFI_OUT_OF_RESOURCES The list of Driver Health Protocol handles can not be retrieved.
1126
1127 **/
1128 EFI_STATUS
1129 GetAllControllersHealthStatus (
1130 IN OUT LIST_ENTRY *DriverHealthList
1131 )
1132 {
1133 EFI_STATUS Status;
1134 UINTN NumHandles;
1135 EFI_HANDLE *DriverHealthHandles;
1136 EFI_DRIVER_HEALTH_PROTOCOL *DriverHealth;
1137 EFI_DRIVER_HEALTH_STATUS HealthStatus;
1138 UINTN DriverHealthIndex;
1139 EFI_HANDLE *Handles;
1140 UINTN HandleCount;
1141 UINTN ControllerIndex;
1142 UINTN ChildIndex;
1143
1144 //
1145 // Initialize local variables
1146 //
1147 Handles = NULL;
1148 DriverHealthHandles = NULL;
1149 NumHandles = 0;
1150 HandleCount = 0;
1151
1152 HealthStatus = EfiDriverHealthStatusHealthy;
1153
1154 Status = gBS->LocateHandleBuffer (
1155 ByProtocol,
1156 &gEfiDriverHealthProtocolGuid,
1157 NULL,
1158 &NumHandles,
1159 &DriverHealthHandles
1160 );
1161
1162 if (Status == EFI_NOT_FOUND || NumHandles == 0) {
1163 //
1164 // If there are no Driver Health Protocols handles, then return EFI_NOT_FOUND
1165 //
1166 return EFI_NOT_FOUND;
1167 }
1168
1169 if (EFI_ERROR (Status) || DriverHealthHandles == NULL) {
1170 //
1171 // If the list of Driver Health Protocol handles can not be retrieved, then
1172 // return EFI_OUT_OF_RESOURCES
1173 //
1174 return EFI_OUT_OF_RESOURCES;
1175 }
1176
1177 //
1178 // Check the health status of all controllers in the platform
1179 // Start by looping through all the Driver Health Protocol handles in the handle database
1180 //
1181 for (DriverHealthIndex = 0; DriverHealthIndex < NumHandles; DriverHealthIndex++) {
1182 //
1183 // Skip NULL Driver Health Protocol handles
1184 //
1185 if (DriverHealthHandles[DriverHealthIndex] == NULL) {
1186 continue;
1187 }
1188
1189 //
1190 // Retrieve the Driver Health Protocol from DriverHandle
1191 //
1192 Status = gBS->HandleProtocol (
1193 DriverHealthHandles[DriverHealthIndex],
1194 &gEfiDriverHealthProtocolGuid,
1195 (VOID **)&DriverHealth
1196 );
1197 if (EFI_ERROR (Status)) {
1198 //
1199 // If the Driver Health Protocol can not be retrieved, then skip to the next
1200 // Driver Health Protocol handle
1201 //
1202 continue;
1203 }
1204
1205 //
1206 // Check the health of all the controllers managed by a Driver Health Protocol handle
1207 //
1208 Status = GetSingleControllerHealthStatus (DriverHealthList, DriverHealthHandles[DriverHealthIndex], NULL, NULL, DriverHealth, &HealthStatus);
1209
1210 //
1211 // If Status is an error code, then the health information could not be retrieved, so assume healthy
1212 // and skip to the next Driver Health Protocol handle
1213 //
1214 if (EFI_ERROR (Status)) {
1215 continue;
1216 }
1217
1218 //
1219 // If all the controllers managed by this Driver Health Protocol are healthy, then skip to the next
1220 // Driver Health Protocol handle
1221 //
1222 if (HealthStatus == EfiDriverHealthStatusHealthy) {
1223 continue;
1224 }
1225
1226 //
1227 // See if the list of all handles in the handle database has been retrieved
1228 //
1229 //
1230 if (Handles == NULL) {
1231 //
1232 // Retrieve the list of all handles from the handle database
1233 //
1234 Status = gBS->LocateHandleBuffer (
1235 AllHandles,
1236 NULL,
1237 NULL,
1238 &HandleCount,
1239 &Handles
1240 );
1241 if (EFI_ERROR (Status) || Handles == NULL) {
1242 //
1243 // If all the handles in the handle database can not be retrieved, then
1244 // return EFI_OUT_OF_RESOURCES
1245 //
1246 Status = EFI_OUT_OF_RESOURCES;
1247 goto Done;
1248 }
1249 }
1250 //
1251 // Loop through all the controller handles in the handle database
1252 //
1253 for (ControllerIndex = 0; ControllerIndex < HandleCount; ControllerIndex++) {
1254 //
1255 // Skip NULL controller handles
1256 //
1257 if (Handles[ControllerIndex] == NULL) {
1258 continue;
1259 }
1260
1261 Status = GetSingleControllerHealthStatus (DriverHealthList, DriverHealthHandles[DriverHealthIndex], Handles[ControllerIndex], NULL, DriverHealth, &HealthStatus);
1262 if (EFI_ERROR (Status)) {
1263 //
1264 // If Status is an error code, then the health information could not be retrieved, so assume healthy
1265 //
1266 HealthStatus = EfiDriverHealthStatusHealthy;
1267 }
1268
1269 //
1270 // If CheckHealthSingleController() returned an error on a terminal state, then do not check the health of child controllers
1271 //
1272 if (EFI_ERROR (Status)) {
1273 continue;
1274 }
1275
1276 //
1277 // Loop through all the child handles in the handle database
1278 //
1279 for (ChildIndex = 0; ChildIndex < HandleCount; ChildIndex++) {
1280 //
1281 // Skip NULL child handles
1282 //
1283 if (Handles[ChildIndex] == NULL) {
1284 continue;
1285 }
1286
1287 Status = GetSingleControllerHealthStatus (DriverHealthList, DriverHealthHandles[DriverHealthIndex], Handles[ControllerIndex], Handles[ChildIndex], DriverHealth, &HealthStatus);
1288 if (EFI_ERROR (Status)) {
1289 //
1290 // If Status is an error code, then the health information could not be retrieved, so assume healthy
1291 //
1292 HealthStatus = EfiDriverHealthStatusHealthy;
1293 }
1294
1295 //
1296 // If CheckHealthSingleController() returned an error on a terminal state, then skip to the next child
1297 //
1298 if (EFI_ERROR (Status)) {
1299 continue;
1300 }
1301 }
1302 }
1303 }
1304
1305 Status = EFI_SUCCESS;
1306
1307 Done:
1308 if (Handles != NULL) {
1309 gBS->FreePool (Handles);
1310 }
1311 if (DriverHealthHandles != NULL) {
1312 gBS->FreePool (DriverHealthHandles);
1313 }
1314
1315 return Status;
1316 }
1317
1318
1319 /**
1320 Check the healthy status of the platform, this function will return immediately while found one driver
1321 in the platform are not healthy.
1322
1323 @retval FALSE at least one driver in the platform are not healthy.
1324 @retval TRUE No controller install Driver Health Protocol,
1325 or all controllers in the platform are in healthy status.
1326 **/
1327 BOOLEAN
1328 PlaformHealthStatusCheck (
1329 VOID
1330 )
1331 {
1332 EFI_DRIVER_HEALTH_STATUS HealthStatus;
1333 EFI_STATUS Status;
1334 UINTN Index;
1335 UINTN NoHandles;
1336 EFI_HANDLE *DriverHealthHandles;
1337 EFI_DRIVER_HEALTH_PROTOCOL *DriverHealth;
1338 BOOLEAN AllHealthy;
1339
1340 //
1341 // Initialize local variables
1342 //
1343 DriverHealthHandles = NULL;
1344 DriverHealth = NULL;
1345
1346 HealthStatus = EfiDriverHealthStatusHealthy;
1347
1348 Status = gBS->LocateHandleBuffer (
1349 ByProtocol,
1350 &gEfiDriverHealthProtocolGuid,
1351 NULL,
1352 &NoHandles,
1353 &DriverHealthHandles
1354 );
1355 //
1356 // There are no handles match the search for Driver Health Protocol has been installed.
1357 //
1358 if (Status == EFI_NOT_FOUND) {
1359 return TRUE;
1360 }
1361 //
1362 // Assume all modules are healthy.
1363 //
1364 AllHealthy = TRUE;
1365
1366 //
1367 // Found one or more Handles.
1368 //
1369 if (!EFI_ERROR (Status)) {
1370 for (Index = 0; Index < NoHandles; Index++) {
1371 Status = gBS->HandleProtocol (
1372 DriverHealthHandles[Index],
1373 &gEfiDriverHealthProtocolGuid,
1374 (VOID **) &DriverHealth
1375 );
1376 if (!EFI_ERROR (Status)) {
1377 Status = DriverHealth->GetHealthStatus (
1378 DriverHealth,
1379 NULL,
1380 NULL,
1381 &HealthStatus,
1382 NULL,
1383 NULL
1384 );
1385 }
1386 //
1387 // Get the healthy status of the module
1388 //
1389 if (!EFI_ERROR (Status)) {
1390 if (HealthStatus != EfiDriverHealthStatusHealthy) {
1391 //
1392 // Return immediately one driver's status not in healthy.
1393 //
1394 return FALSE;
1395 }
1396 }
1397 }
1398 }
1399 return AllHealthy;
1400 }
1401
1402 /**
1403 Processes a single controller using the EFI Driver Health Protocol associated with
1404 that controller. This algorithm continues to query the GetHealthStatus() service until
1405 one of the legal terminal states of the EFI Driver Health Protocol is reached. This may
1406 require the processing of HII Messages, HII Form, and invocation of repair operations.
1407
1408 @param DriverHealth A pointer to the EFI_DRIVER_HEALTH_PROTOCOL instance.
1409 @param ControllerHandle The class guid specifies which form set will be displayed.
1410 @param ChildHandle The handle of the child controller to retrieve the health
1411 status on. This is an optional parameter that may be NULL.
1412 @param HealthStatus The health status of the controller.
1413 @param MessageList An array of warning or error messages associated
1414 with the controller specified by ControllerHandle and
1415 ChildHandle. This is an optional parameter that may be NULL.
1416 @param FormHiiHandle The HII handle for an HII form associated with the
1417 controller specified by ControllerHandle and ChildHandle.
1418 **/
1419 VOID
1420 ProcessSingleControllerHealth (
1421 IN EFI_DRIVER_HEALTH_PROTOCOL *DriverHealth,
1422 IN EFI_HANDLE ControllerHandle, OPTIONAL
1423 IN EFI_HANDLE ChildHandle, OPTIONAL
1424 IN EFI_DRIVER_HEALTH_STATUS HealthStatus,
1425 IN EFI_DRIVER_HEALTH_HII_MESSAGE **MessageList, OPTIONAL
1426 IN EFI_HII_HANDLE FormHiiHandle
1427 )
1428 {
1429 EFI_STATUS Status;
1430 EFI_DRIVER_HEALTH_STATUS LocalHealthStatus;
1431
1432 LocalHealthStatus = HealthStatus;
1433 //
1434 // If the module need to be repaired or reconfiguration, will process it until
1435 // reach a terminal status. The status from EfiDriverHealthStatusRepairRequired after repair
1436 // will be in (Health, Failed, Configuration Required).
1437 //
1438 while( LocalHealthStatus == EfiDriverHealthStatusConfigurationRequired ||
1439 LocalHealthStatus == EfiDriverHealthStatusRepairRequired) {
1440
1441 if (LocalHealthStatus == EfiDriverHealthStatusRepairRequired) {
1442 Status = DriverHealth->Repair (
1443 DriverHealth,
1444 ControllerHandle,
1445 ChildHandle,
1446 (EFI_DRIVER_HEALTH_REPAIR_PROGRESS_NOTIFY) RepairNotify
1447 );
1448 }
1449 //
1450 // Via a form of the driver need to do configuration provided to process of status in
1451 // EfiDriverHealthStatusConfigurationRequired. The status after configuration should be in
1452 // (Healthy, Reboot Required, Failed, Reconnect Required, Repair Required).
1453 //
1454 if (LocalHealthStatus == EfiDriverHealthStatusConfigurationRequired) {
1455 Status = gFormBrowser2->SendForm (
1456 gFormBrowser2,
1457 &FormHiiHandle,
1458 1,
1459 &gEfiHiiDriverHealthFormsetGuid,
1460 0,
1461 NULL,
1462 NULL
1463 );
1464 ASSERT( !EFI_ERROR (Status));
1465 }
1466
1467 Status = DriverHealth->GetHealthStatus (
1468 DriverHealth,
1469 ControllerHandle,
1470 ChildHandle,
1471 &LocalHealthStatus,
1472 NULL,
1473 &FormHiiHandle
1474 );
1475 ASSERT_EFI_ERROR (Status);
1476
1477 if (*MessageList != NULL) {
1478 ProcessMessages (*MessageList);
1479 }
1480 }
1481
1482 //
1483 // Health status in {Healthy, Failed} may also have Messages need to process
1484 //
1485 if (LocalHealthStatus == EfiDriverHealthStatusHealthy || LocalHealthStatus == EfiDriverHealthStatusFailed) {
1486 if (*MessageList != NULL) {
1487 ProcessMessages (*MessageList);
1488 }
1489 }
1490 //
1491 // Check for RebootRequired or ReconnectRequired
1492 //
1493 if (LocalHealthStatus == EfiDriverHealthStatusRebootRequired) {
1494 gRT->ResetSystem (EfiResetWarm, EFI_SUCCESS, 0, NULL);
1495 }
1496
1497 //
1498 // Do reconnect if need.
1499 //
1500 if (LocalHealthStatus == EfiDriverHealthStatusReconnectRequired) {
1501 Status = gBS->DisconnectController (ControllerHandle, NULL, NULL);
1502 if (EFI_ERROR (Status)) {
1503 //
1504 // Disconnect failed. Need to promote reconnect to a reboot.
1505 //
1506 gRT->ResetSystem (EfiResetWarm, EFI_SUCCESS, 0, NULL);
1507 }
1508 gBS->ConnectController (ControllerHandle, NULL, NULL, TRUE);
1509 }
1510 }
1511
1512
1513 /**
1514 Platform specific notification function for controller repair operations.
1515
1516 If the driver for a controller support the Driver Health Protocol and the
1517 current state of the controller is EfiDriverHealthStatusRepairRequired then
1518 when the Repair() service of the Driver Health Protocol is called, this
1519 platform specific notification function can display the progress of the repair
1520 operation. Some platforms may choose to not display anything, other may choose
1521 to show the percentage complete on text consoles, and other may choose to render
1522 a progress bar on text and graphical consoles.
1523
1524 This function displays the percentage of the repair operation that has been
1525 completed on text consoles. The percentage is Value / Limit * 100%.
1526
1527 @param Value Value in the range 0..Limit the the repair has completed..
1528 @param Limit The maximum value of Value
1529
1530 **/
1531 VOID
1532 RepairNotify (
1533 IN UINTN Value,
1534 IN UINTN Limit
1535 )
1536 {
1537 UINTN Percent;
1538
1539 if (Limit == 0) {
1540 Print(L"Repair Progress Undefined\n\r");
1541 } else {
1542 Percent = Value * 100 / Limit;
1543 Print(L"Repair Progress = %3d%%\n\r", Percent);
1544 }
1545 }
1546
1547 /**
1548 Processes a set of messages returned by the GetHealthStatus ()
1549 service of the EFI Driver Health Protocol
1550
1551 @param MessageList The MessageList point to messages need to processed.
1552
1553 **/
1554 VOID
1555 ProcessMessages (
1556 IN EFI_DRIVER_HEALTH_HII_MESSAGE *MessageList
1557 )
1558 {
1559 UINTN MessageIndex;
1560 EFI_STRING MessageString;
1561
1562 for (MessageIndex = 0;
1563 MessageList[MessageIndex].HiiHandle != NULL;
1564 MessageIndex++) {
1565
1566 MessageString = HiiGetString (
1567 MessageList[MessageIndex].HiiHandle,
1568 MessageList[MessageIndex].StringId,
1569 NULL
1570 );
1571 if (MessageString != NULL) {
1572 //
1573 // User can customize the output. Just simply print out the MessageString like below.
1574 // Also can use the HiiHandle to display message on the front page.
1575 //
1576 // Print(L"%s\n",MessageString);
1577 // gBS->Stall (100000);
1578 }
1579 }
1580
1581 }
1582
1583 /**
1584 Repair the whole platform.
1585
1586 This function is the main entry for user choose "Repair All" in the front page.
1587 It will try to do recovery job till all the driver health protocol installed modules
1588 reach a terminal state.
1589
1590 @param DriverHealthList A Pointer to the list contain all of the platform driver health
1591 information.
1592
1593 **/
1594 VOID
1595 PlatformRepairAll (
1596 IN LIST_ENTRY *DriverHealthList
1597 )
1598 {
1599 DRIVER_HEALTH_INFO *DriverHealthInfo;
1600 LIST_ENTRY *Link;
1601
1602 ASSERT (DriverHealthList != NULL);
1603
1604 Link = GetFirstNode (DriverHealthList);
1605
1606 while (!IsNull (DriverHealthList, Link)) {
1607 DriverHealthInfo = DEVICE_MANAGER_HEALTH_INFO_FROM_LINK (Link);
1608 //
1609 // Do driver health status operation by each link node
1610 //
1611 ASSERT (DriverHealthInfo != NULL);
1612
1613 ProcessSingleControllerHealth (
1614 DriverHealthInfo->DriverHealth,
1615 DriverHealthInfo->ControllerHandle,
1616 DriverHealthInfo->ChildHandle,
1617 DriverHealthInfo->HealthStatus,
1618 &(DriverHealthInfo->MessageList),
1619 DriverHealthInfo->HiiHandle
1620 );
1621
1622 Link = GetNextNode (DriverHealthList, Link);
1623 }
1624 }
1625
1626 /**
1627
1628 Select the best matching language according to front page policy for best user experience.
1629
1630 This function supports both ISO 639-2 and RFC 4646 language codes, but language
1631 code types may not be mixed in a single call to this function.
1632
1633 @param SupportedLanguages A pointer to a Null-terminated ASCII string that
1634 contains a set of language codes in the format
1635 specified by Iso639Language.
1636 @param Iso639Language If TRUE, then all language codes are assumed to be
1637 in ISO 639-2 format. If FALSE, then all language
1638 codes are assumed to be in RFC 4646 language format.
1639
1640 @retval NULL The best matching language could not be found in SupportedLanguages.
1641 @retval NULL There are not enough resources available to return the best matching
1642 language.
1643 @retval Other A pointer to a Null-terminated ASCII string that is the best matching
1644 language in SupportedLanguages.
1645 **/
1646 CHAR8 *
1647 DriverHealthSelectBestLanguage (
1648 IN CHAR8 *SupportedLanguages,
1649 IN BOOLEAN Iso639Language
1650 )
1651 {
1652 CHAR8 *LanguageVariable;
1653 CHAR8 *BestLanguage;
1654
1655 LanguageVariable = GetEfiGlobalVariable (Iso639Language ? L"Lang" : L"PlatformLang");
1656
1657 BestLanguage = GetBestLanguage(
1658 SupportedLanguages,
1659 Iso639Language,
1660 (LanguageVariable != NULL) ? LanguageVariable : "",
1661 Iso639Language ? "eng" : "en-US",
1662 NULL
1663 );
1664 if (LanguageVariable != NULL) {
1665 FreePool (LanguageVariable);
1666 }
1667
1668 return BestLanguage;
1669 }
1670
1671
1672
1673 /**
1674
1675 This is an internal worker function to get the Component Name (2) protocol interface
1676 and the language it supports.
1677
1678 @param ProtocolGuid A pointer to an EFI_GUID. It points to Component Name (2) protocol GUID.
1679 @param DriverBindingHandle The handle on which the Component Name (2) protocol instance is retrieved.
1680 @param ComponentName A pointer to the Component Name (2) protocol interface.
1681 @param SupportedLanguage The best suitable language that matches the SupportedLangues interface for the
1682 located Component Name (2) instance.
1683
1684 @retval EFI_SUCCESS The Component Name (2) protocol instance is successfully located and we find
1685 the best matching language it support.
1686 @retval EFI_UNSUPPORTED The input Language is not supported by the Component Name (2) protocol.
1687 @retval Other Some error occurs when locating Component Name (2) protocol instance or finding
1688 the supported language.
1689
1690 **/
1691 EFI_STATUS
1692 GetComponentNameWorker (
1693 IN EFI_GUID *ProtocolGuid,
1694 IN EFI_HANDLE DriverBindingHandle,
1695 OUT EFI_COMPONENT_NAME_PROTOCOL **ComponentName,
1696 OUT CHAR8 **SupportedLanguage
1697 )
1698 {
1699 EFI_STATUS Status;
1700
1701 //
1702 // Locate Component Name (2) protocol on the driver binging handle.
1703 //
1704 Status = gBS->OpenProtocol (
1705 DriverBindingHandle,
1706 ProtocolGuid,
1707 (VOID **) ComponentName,
1708 NULL,
1709 NULL,
1710 EFI_OPEN_PROTOCOL_GET_PROTOCOL
1711 );
1712 if (EFI_ERROR (Status)) {
1713 return Status;
1714 }
1715
1716 //
1717 // Apply shell policy to select the best language.
1718 //
1719 *SupportedLanguage = DriverHealthSelectBestLanguage (
1720 (*ComponentName)->SupportedLanguages,
1721 (BOOLEAN) (ProtocolGuid == &gEfiComponentNameProtocolGuid)
1722 );
1723 if (*SupportedLanguage == NULL) {
1724 Status = EFI_UNSUPPORTED;
1725 }
1726
1727 return Status;
1728 }
1729
1730 /**
1731
1732 This is an internal worker function to get driver name from Component Name (2) protocol interface.
1733
1734
1735 @param ProtocolGuid A pointer to an EFI_GUID. It points to Component Name (2) protocol GUID.
1736 @param DriverBindingHandle The handle on which the Component Name (2) protocol instance is retrieved.
1737 @param DriverName A pointer to the Unicode string to return. This Unicode string is the name
1738 of the driver specified by This.
1739
1740 @retval EFI_SUCCESS The driver name is successfully retrieved from Component Name (2) protocol
1741 interface.
1742 @retval Other The driver name cannot be retrieved from Component Name (2) protocol
1743 interface.
1744
1745 **/
1746 EFI_STATUS
1747 GetDriverNameWorker (
1748 IN EFI_GUID *ProtocolGuid,
1749 IN EFI_HANDLE DriverBindingHandle,
1750 OUT CHAR16 **DriverName
1751 )
1752 {
1753 EFI_STATUS Status;
1754 CHAR8 *BestLanguage;
1755 EFI_COMPONENT_NAME_PROTOCOL *ComponentName;
1756
1757 //
1758 // Retrieve Component Name (2) protocol instance on the driver binding handle and
1759 // find the best language this instance supports.
1760 //
1761 Status = GetComponentNameWorker (
1762 ProtocolGuid,
1763 DriverBindingHandle,
1764 &ComponentName,
1765 &BestLanguage
1766 );
1767 if (EFI_ERROR (Status)) {
1768 return Status;
1769 }
1770
1771 //
1772 // Get the driver name from Component Name (2) protocol instance on the driver binging handle.
1773 //
1774 Status = ComponentName->GetDriverName (
1775 ComponentName,
1776 BestLanguage,
1777 DriverName
1778 );
1779 FreePool (BestLanguage);
1780
1781 return Status;
1782 }
1783
1784 /**
1785
1786 This function gets driver name from Component Name 2 protocol interface and Component Name protocol interface
1787 in turn. It first tries UEFI 2.0 Component Name 2 protocol interface and try to get the driver name.
1788 If the attempt fails, it then gets the driver name from EFI 1.1 Component Name protocol for backward
1789 compatibility support.
1790
1791 @param DriverBindingHandle The handle on which the Component Name (2) protocol instance is retrieved.
1792 @param DriverName A pointer to the Unicode string to return. This Unicode string is the name
1793 of the driver specified by This.
1794
1795 @retval EFI_SUCCESS The driver name is successfully retrieved from Component Name (2) protocol
1796 interface.
1797 @retval Other The driver name cannot be retrieved from Component Name (2) protocol
1798 interface.
1799
1800 **/
1801 EFI_STATUS
1802 DriverHealthGetDriverName (
1803 IN EFI_HANDLE DriverBindingHandle,
1804 OUT CHAR16 **DriverName
1805 )
1806 {
1807 EFI_STATUS Status;
1808
1809 //
1810 // Get driver name from UEFI 2.0 Component Name 2 protocol interface.
1811 //
1812 Status = GetDriverNameWorker (&gEfiComponentName2ProtocolGuid, DriverBindingHandle, DriverName);
1813 if (EFI_ERROR (Status)) {
1814 //
1815 // If it fails to get the driver name from Component Name protocol interface, we should fall back on
1816 // EFI 1.1 Component Name protocol interface.
1817 //
1818 Status = GetDriverNameWorker (&gEfiComponentNameProtocolGuid, DriverBindingHandle, DriverName);
1819 }
1820
1821 return Status;
1822 }
1823
1824
1825
1826 /**
1827 This function gets controller name from Component Name 2 protocol interface and Component Name protocol interface
1828 in turn. It first tries UEFI 2.0 Component Name 2 protocol interface and try to get the controller name.
1829 If the attempt fails, it then gets the controller name from EFI 1.1 Component Name protocol for backward
1830 compatibility support.
1831
1832 @param ProtocolGuid A pointer to an EFI_GUID. It points to Component Name (2) protocol GUID.
1833 @param DriverBindingHandle The handle on which the Component Name (2) protocol instance is retrieved.
1834 @param ControllerHandle The handle of a controller that the driver specified by This is managing.
1835 This handle specifies the controller whose name is to be returned.
1836 @param ChildHandle The handle of the child controller to retrieve the name of. This is an
1837 optional parameter that may be NULL. It will be NULL for device drivers.
1838 It will also be NULL for bus drivers that attempt to retrieve the name
1839 of the bus controller. It will not be NULL for a bus driver that attempts
1840 to retrieve the name of a child controller.
1841 @param ControllerName A pointer to the Unicode string to return. This Unicode string
1842 is the name of the controller specified by ControllerHandle and ChildHandle.
1843
1844 @retval EFI_SUCCESS The controller name is successfully retrieved from Component Name (2) protocol
1845 interface.
1846 @retval Other The controller name cannot be retrieved from Component Name (2) protocol.
1847
1848 **/
1849 EFI_STATUS
1850 GetControllerNameWorker (
1851 IN EFI_GUID *ProtocolGuid,
1852 IN EFI_HANDLE DriverBindingHandle,
1853 IN EFI_HANDLE ControllerHandle,
1854 IN EFI_HANDLE ChildHandle,
1855 OUT CHAR16 **ControllerName
1856 )
1857 {
1858 EFI_STATUS Status;
1859 CHAR8 *BestLanguage;
1860 EFI_COMPONENT_NAME_PROTOCOL *ComponentName;
1861
1862 //
1863 // Retrieve Component Name (2) protocol instance on the driver binding handle and
1864 // find the best language this instance supports.
1865 //
1866 Status = GetComponentNameWorker (
1867 ProtocolGuid,
1868 DriverBindingHandle,
1869 &ComponentName,
1870 &BestLanguage
1871 );
1872 if (EFI_ERROR (Status)) {
1873 return Status;
1874 }
1875
1876 //
1877 // Get the controller name from Component Name (2) protocol instance on the driver binging handle.
1878 //
1879 Status = ComponentName->GetControllerName (
1880 ComponentName,
1881 ControllerHandle,
1882 ChildHandle,
1883 BestLanguage,
1884 ControllerName
1885 );
1886 FreePool (BestLanguage);
1887
1888 return Status;
1889 }
1890
1891 /**
1892
1893 This function gets controller name from Component Name 2 protocol interface and Component Name protocol interface
1894 in turn. It first tries UEFI 2.0 Component Name 2 protocol interface and try to get the controller name.
1895 If the attempt fails, it then gets the controller name from EFI 1.1 Component Name protocol for backward
1896 compatibility support.
1897
1898 @param DriverBindingHandle The handle on which the Component Name (2) protocol instance is retrieved.
1899 @param ControllerHandle The handle of a controller that the driver specified by This is managing.
1900 This handle specifies the controller whose name is to be returned.
1901 @param ChildHandle The handle of the child controller to retrieve the name of. This is an
1902 optional parameter that may be NULL. It will be NULL for device drivers.
1903 It will also be NULL for bus drivers that attempt to retrieve the name
1904 of the bus controller. It will not be NULL for a bus driver that attempts
1905 to retrieve the name of a child controller.
1906 @param ControllerName A pointer to the Unicode string to return. This Unicode string
1907 is the name of the controller specified by ControllerHandle and ChildHandle.
1908
1909 @retval EFI_SUCCESS The controller name is successfully retrieved from Component Name (2) protocol
1910 interface.
1911 @retval Other The controller name cannot be retrieved from Component Name (2) protocol.
1912
1913 **/
1914 EFI_STATUS
1915 DriverHealthGetControllerName (
1916 IN EFI_HANDLE DriverBindingHandle,
1917 IN EFI_HANDLE ControllerHandle,
1918 IN EFI_HANDLE ChildHandle,
1919 OUT CHAR16 **ControllerName
1920 )
1921 {
1922 EFI_STATUS Status;
1923
1924 //
1925 // Get controller name from UEFI 2.0 Component Name 2 protocol interface.
1926 //
1927 Status = GetControllerNameWorker (
1928 &gEfiComponentName2ProtocolGuid,
1929 DriverBindingHandle,
1930 ControllerHandle,
1931 ChildHandle,
1932 ControllerName
1933 );
1934 if (EFI_ERROR (Status)) {
1935 //
1936 // If it fails to get the controller name from Component Name protocol interface, we should fall back on
1937 // EFI 1.1 Component Name protocol interface.
1938 //
1939 Status = GetControllerNameWorker (
1940 &gEfiComponentNameProtocolGuid,
1941 DriverBindingHandle,
1942 ControllerHandle,
1943 ChildHandle,
1944 ControllerName
1945 );
1946 }
1947
1948 return Status;
1949 }