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