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