TianoCore EDK2 master
Loading...
Searching...
No Matches
BmDriverHealth.c
Go to the documentation of this file.
1
11#include "InternalBm.h"
12
14CHAR16 *mBmHealthStatusText[] = {
15 L"Healthy",
16 L"Repair Required",
17 L"Configuration Required",
18 L"Failed",
19 L"Reconnect Required",
20 L"Reboot Required"
21};
22
38CHAR16 *
40 IN EFI_HANDLE DriverHealthHandle,
41 IN EFI_HANDLE ControllerHandle,
42 IN EFI_HANDLE ChildHandle
43 )
44{
45 EFI_STATUS Status;
46 CHAR16 *ControllerName;
47 CHAR8 *LanguageVariable;
48 CHAR8 *BestLanguage;
49 BOOLEAN Iso639Language;
50 EFI_COMPONENT_NAME_PROTOCOL *ComponentName;
51
52 ControllerName = NULL;
53
54 //
55 // Locate Component Name (2) protocol on the driver binging handle.
56 //
57 Iso639Language = FALSE;
58 Status = gBS->HandleProtocol (
59 DriverHealthHandle,
60 &gEfiComponentName2ProtocolGuid,
61 (VOID **)&ComponentName
62 );
63 if (EFI_ERROR (Status)) {
64 Status = gBS->HandleProtocol (
65 DriverHealthHandle,
66 &gEfiComponentNameProtocolGuid,
67 (VOID **)&ComponentName
68 );
69 if (!EFI_ERROR (Status)) {
70 Iso639Language = TRUE;
71 }
72 }
73
74 if (!EFI_ERROR (Status)) {
75 GetEfiGlobalVariable2 (Iso639Language ? L"Lang" : L"PlatformLang", (VOID **)&LanguageVariable, NULL);
76 BestLanguage = GetBestLanguage (
77 ComponentName->SupportedLanguages,
78 Iso639Language,
79 (LanguageVariable != NULL) ? LanguageVariable : "",
80 Iso639Language ? "eng" : "en-US",
81 NULL
82 );
83 if (LanguageVariable != NULL) {
84 FreePool (LanguageVariable);
85 }
86
87 Status = ComponentName->GetControllerName (
88 ComponentName,
89 ControllerHandle,
90 ChildHandle,
91 BestLanguage,
92 &ControllerName
93 );
94 }
95
96 if (!EFI_ERROR (Status)) {
97 return AllocateCopyPool (StrSize (ControllerName), ControllerName);
98 } else {
100 DevicePathFromHandle (ChildHandle != NULL ? ChildHandle : ControllerHandle),
101 FALSE,
102 FALSE
103 );
104 }
105}
106
112VOID
115 )
116{
117 UINTN Index;
118 EFI_STRING String;
119 CHAR16 *ControllerName;
120
121 if ((DriverHealthInfo->MessageList == NULL) ||
122 (DriverHealthInfo->MessageList[0].HiiHandle == NULL))
123 {
124 return;
125 }
126
127 ControllerName = BmGetControllerName (
128 DriverHealthInfo->DriverHealthHandle,
129 DriverHealthInfo->ControllerHandle,
130 DriverHealthInfo->ChildHandle
131 );
132
133 DEBUG ((DEBUG_INFO, "Controller: %s\n", ControllerName));
134 Print (L"Controller: %s\n", ControllerName);
135 for (Index = 0; DriverHealthInfo->MessageList[Index].HiiHandle != NULL; Index++) {
136 String = HiiGetString (
137 DriverHealthInfo->MessageList[Index].HiiHandle,
138 DriverHealthInfo->MessageList[Index].StringId,
139 NULL
140 );
141 if (String != NULL) {
142 Print (L" %s\n", String);
143 DEBUG ((DEBUG_INFO, " %s\n", String));
144 FreePool (String);
145 }
146 }
147
148 if (ControllerName != NULL) {
149 FreePool (ControllerName);
150 }
151}
152
165EFIAPI
167 IN UINTN Value,
168 IN UINTN Limit
169 )
170{
171 DEBUG ((DEBUG_INFO, "[BDS]RepairNotify: %d/%d\n", Value, Limit));
172 Print (L"[BDS]RepairNotify: %d/%d\n", Value, Limit);
173
174 return EFI_SUCCESS;
175}
176
193 IN OUT EFI_BOOT_MANAGER_DRIVER_HEALTH_INFO **DriverHealthInfo,
194 IN OUT UINTN *Count,
195 IN EFI_HANDLE DriverHealthHandle,
196 IN EFI_HANDLE ControllerHandle OPTIONAL,
197 IN EFI_HANDLE ChildHandle OPTIONAL
198 )
199{
200 EFI_STATUS Status;
201 EFI_DRIVER_HEALTH_PROTOCOL *DriverHealth;
203 EFI_HII_HANDLE FormHiiHandle;
204 EFI_DRIVER_HEALTH_STATUS HealthStatus;
205
206 ASSERT (DriverHealthHandle != NULL);
207 //
208 // Retrieve the Driver Health Protocol from DriverHandle
209 //
210 Status = gBS->HandleProtocol (
211 DriverHealthHandle,
212 &gEfiDriverHealthProtocolGuid,
213 (VOID **)&DriverHealth
214 );
215 ASSERT_EFI_ERROR (Status);
216
217 if (ControllerHandle == NULL) {
218 //
219 // If ControllerHandle is NULL, the return the cumulative health status of the driver
220 //
221 Status = DriverHealth->GetHealthStatus (DriverHealth, NULL, NULL, &HealthStatus, NULL, NULL);
222 if (!EFI_ERROR (Status) && (HealthStatus == EfiDriverHealthStatusHealthy)) {
223 *DriverHealthInfo = ReallocatePool (
224 (*Count) * sizeof (EFI_BOOT_MANAGER_DRIVER_HEALTH_INFO),
225 (*Count + 1) * sizeof (EFI_BOOT_MANAGER_DRIVER_HEALTH_INFO),
226 *DriverHealthInfo
227 );
228 ASSERT (*DriverHealthInfo != NULL);
229
230 (*DriverHealthInfo)[*Count].DriverHealthHandle = DriverHealthHandle;
231 (*DriverHealthInfo)[*Count].DriverHealth = DriverHealth;
232 (*DriverHealthInfo)[*Count].HealthStatus = HealthStatus;
233
234 *Count = *Count + 1;
235
236 Status = EFI_ABORTED;
237 }
238
239 return Status;
240 }
241
242 MessageList = NULL;
243 FormHiiHandle = NULL;
244
245 //
246 // Collect the health status with the optional HII message list
247 //
248 Status = DriverHealth->GetHealthStatus (DriverHealth, ControllerHandle, ChildHandle, &HealthStatus, &MessageList, &FormHiiHandle);
249 if (!EFI_ERROR (Status)) {
250 *DriverHealthInfo = ReallocatePool (
251 (*Count) * sizeof (EFI_BOOT_MANAGER_DRIVER_HEALTH_INFO),
252 (*Count + 1) * sizeof (EFI_BOOT_MANAGER_DRIVER_HEALTH_INFO),
253 *DriverHealthInfo
254 );
255 ASSERT (*DriverHealthInfo != NULL);
256 (*DriverHealthInfo)[*Count].DriverHealth = DriverHealth;
257 (*DriverHealthInfo)[*Count].DriverHealthHandle = DriverHealthHandle;
258 (*DriverHealthInfo)[*Count].ControllerHandle = ControllerHandle;
259 (*DriverHealthInfo)[*Count].ChildHandle = ChildHandle;
260 (*DriverHealthInfo)[*Count].HiiHandle = FormHiiHandle;
261 (*DriverHealthInfo)[*Count].MessageList = MessageList;
262 (*DriverHealthInfo)[*Count].HealthStatus = HealthStatus;
263
264 *Count = *Count + 1;
265 }
266
267 return Status;
268}
269
287EFIAPI
289 UINTN *Count
290 )
291{
292 EFI_STATUS Status;
293 UINTN NumHandles;
294 EFI_HANDLE *DriverHealthHandles;
295 UINTN DriverHealthIndex;
296 EFI_HANDLE *Handles;
297 UINTN HandleCount;
298 UINTN ControllerIndex;
299 UINTN ChildIndex;
300 EFI_BOOT_MANAGER_DRIVER_HEALTH_INFO *DriverHealthInfo;
301
302 //
303 // Initialize local variables
304 //
305 *Count = 0;
306 DriverHealthInfo = NULL;
307 Handles = NULL;
308 DriverHealthHandles = NULL;
309 NumHandles = 0;
310 HandleCount = 0;
311
312 Status = gBS->LocateHandleBuffer (
314 &gEfiDriverHealthProtocolGuid,
315 NULL,
316 &NumHandles,
317 &DriverHealthHandles
318 );
319
320 if ((Status == EFI_NOT_FOUND) || (NumHandles == 0)) {
321 //
322 // If there are no Driver Health Protocols handles, then return EFI_NOT_FOUND
323 //
324 return NULL;
325 }
326
327 ASSERT_EFI_ERROR (Status);
328 ASSERT (DriverHealthHandles != NULL);
329
330 //
331 // Check the health status of all controllers in the platform
332 // Start by looping through all the Driver Health Protocol handles in the handle database
333 //
334 for (DriverHealthIndex = 0; DriverHealthIndex < NumHandles; DriverHealthIndex++) {
335 //
336 // Get the cumulative health status of the driver
337 //
338 Status = BmGetSingleControllerHealthStatus (&DriverHealthInfo, Count, DriverHealthHandles[DriverHealthIndex], NULL, NULL);
339 if (EFI_ERROR (Status)) {
340 continue;
341 }
342
343 //
344 // See if the list of all handles in the handle database has been retrieved
345 //
346 //
347 if (Handles == NULL) {
348 //
349 // Retrieve the list of all handles from the handle database
350 //
351 Status = gBS->LocateHandleBuffer (
353 NULL,
354 NULL,
355 &HandleCount,
356 &Handles
357 );
358 ASSERT_EFI_ERROR (Status);
359 }
360
361 //
362 // Loop through all the controller handles in the handle database
363 //
364 for (ControllerIndex = 0; ControllerIndex < HandleCount; ControllerIndex++) {
365 Status = BmGetSingleControllerHealthStatus (&DriverHealthInfo, Count, DriverHealthHandles[DriverHealthIndex], Handles[ControllerIndex], NULL);
366 if (EFI_ERROR (Status)) {
367 continue;
368 }
369
370 //
371 // Loop through all the child handles in the handle database
372 //
373 for (ChildIndex = 0; ChildIndex < HandleCount; ChildIndex++) {
374 Status = BmGetSingleControllerHealthStatus (&DriverHealthInfo, Count, DriverHealthHandles[DriverHealthIndex], Handles[ControllerIndex], Handles[ChildIndex]);
375 if (EFI_ERROR (Status)) {
376 continue;
377 }
378 }
379 }
380 }
381
382 Status = EFI_SUCCESS;
383
384 if (Handles != NULL) {
385 FreePool (Handles);
386 }
387
388 if (DriverHealthHandles != NULL) {
389 FreePool (DriverHealthHandles);
390 }
391
392 return DriverHealthInfo;
393}
394
405EFIAPI
407 EFI_BOOT_MANAGER_DRIVER_HEALTH_INFO *DriverHealthInfo,
408 UINTN Count
409 )
410{
411 UINTN Index;
412
413 for (Index = 0; Index < Count; Index++) {
414 if (DriverHealthInfo[Index].MessageList != NULL) {
415 FreePool (DriverHealthInfo[Index].MessageList);
416 }
417 }
418
419 return gBS->FreePool (DriverHealthInfo);
420}
421
428VOID
430 UINTN ReconnectRepairCount
431 )
432{
433 EFI_STATUS Status;
434 EFI_BOOT_MANAGER_DRIVER_HEALTH_INFO *DriverHealthInfo;
435 EFI_DRIVER_HEALTH_STATUS HealthStatus;
436 UINTN Count;
437 UINTN Index;
438 BOOLEAN RepairRequired;
439 BOOLEAN ConfigurationRequired;
440 BOOLEAN ReconnectRequired;
441 BOOLEAN RebootRequired;
442 EFI_HII_HANDLE *HiiHandles;
443 EFI_FORM_BROWSER2_PROTOCOL *FormBrowser2;
444 UINT32 MaxRepairCount;
445 UINT32 RepairCount;
446
447 //
448 // Configure PcdDriverHealthConfigureForm to ZeroGuid to disable driver health check.
449 //
450 if (IsZeroGuid (PcdGetPtr (PcdDriverHealthConfigureForm))) {
451 return;
452 }
453
454 Status = gBS->LocateProtocol (&gEfiFormBrowser2ProtocolGuid, NULL, (VOID **)&FormBrowser2);
455 ASSERT_EFI_ERROR (Status);
456
457 MaxRepairCount = PcdGet32 (PcdMaxRepairCount);
458 RepairCount = 0;
459
460 do {
461 RepairRequired = FALSE;
462 ConfigurationRequired = FALSE;
463
464 //
465 // Deal with Repair Required
466 //
467 DriverHealthInfo = EfiBootManagerGetDriverHealthInfo (&Count);
468 for (Index = 0; Index < Count; Index++) {
469 if (DriverHealthInfo[Index].HealthStatus == EfiDriverHealthStatusConfigurationRequired) {
470 ConfigurationRequired = TRUE;
471 }
472
473 if (DriverHealthInfo[Index].HealthStatus == EfiDriverHealthStatusRepairRequired) {
474 RepairRequired = TRUE;
475
476 BmDisplayMessages (&DriverHealthInfo[Index]);
477
478 Status = DriverHealthInfo[Index].DriverHealth->Repair (
479 DriverHealthInfo[Index].DriverHealth,
480 DriverHealthInfo[Index].ControllerHandle,
481 DriverHealthInfo[Index].ChildHandle,
483 );
484 if (!EFI_ERROR (Status) && !ConfigurationRequired) {
485 Status = DriverHealthInfo[Index].DriverHealth->GetHealthStatus (
486 DriverHealthInfo[Index].DriverHealth,
487 DriverHealthInfo[Index].ControllerHandle,
488 DriverHealthInfo[Index].ChildHandle,
489 &HealthStatus,
490 NULL,
491 NULL
492 );
493 if (!EFI_ERROR (Status) && (HealthStatus == EfiDriverHealthStatusConfigurationRequired)) {
494 ConfigurationRequired = TRUE;
495 }
496 }
497 }
498 }
499
500 if (ConfigurationRequired) {
501 HiiHandles = HiiGetHiiHandles (NULL);
502 if (HiiHandles != NULL) {
503 for (Index = 0; HiiHandles[Index] != NULL; Index++) {
504 Status = FormBrowser2->SendForm (
505 FormBrowser2,
506 &HiiHandles[Index],
507 1,
508 PcdGetPtr (PcdDriverHealthConfigureForm),
509 0,
510 NULL,
511 NULL
512 );
513 if (!EFI_ERROR (Status)) {
514 break;
515 }
516 }
517
518 FreePool (HiiHandles);
519 }
520 }
521
522 EfiBootManagerFreeDriverHealthInfo (DriverHealthInfo, Count);
523 RepairCount++;
524 } while ((RepairRequired || ConfigurationRequired) && ((MaxRepairCount == 0) || (RepairCount < MaxRepairCount)));
525
526 RebootRequired = FALSE;
527 ReconnectRequired = FALSE;
528 DriverHealthInfo = EfiBootManagerGetDriverHealthInfo (&Count);
529 for (Index = 0; Index < Count; Index++) {
530 BmDisplayMessages (&DriverHealthInfo[Index]);
531
532 if (DriverHealthInfo[Index].HealthStatus == EfiDriverHealthStatusReconnectRequired) {
533 Status = gBS->DisconnectController (DriverHealthInfo[Index].ControllerHandle, NULL, NULL);
534 if (EFI_ERROR (Status)) {
535 //
536 // Disconnect failed. Need to promote reconnect to a reboot.
537 //
538 RebootRequired = TRUE;
539 } else {
540 gBS->ConnectController (DriverHealthInfo[Index].ControllerHandle, NULL, NULL, TRUE);
541 ReconnectRequired = TRUE;
542 }
543 }
544
545 if (DriverHealthInfo[Index].HealthStatus == EfiDriverHealthStatusRebootRequired) {
546 RebootRequired = TRUE;
547 }
548 }
549
550 EfiBootManagerFreeDriverHealthInfo (DriverHealthInfo, Count);
551
553 CHAR16 *ControllerName;
554
555 DriverHealthInfo = EfiBootManagerGetDriverHealthInfo (&Count);
556 for (Index = 0; Index < Count; Index++) {
557 ControllerName = BmGetControllerName (
558 DriverHealthInfo[Index].DriverHealthHandle,
559 DriverHealthInfo[Index].ControllerHandle,
560 DriverHealthInfo[Index].ChildHandle
561 );
562 DEBUG ((
563 DEBUG_INFO,
564 "%02d: %s - %s\n",
565 Index,
566 ControllerName,
567 mBmHealthStatusText[DriverHealthInfo[Index].HealthStatus]
568 ));
569 if (ControllerName != NULL) {
570 FreePool (ControllerName);
571 }
572 }
573
574 EfiBootManagerFreeDriverHealthInfo (DriverHealthInfo, Count);
576
577 if (ReconnectRequired) {
578 if (ReconnectRepairCount < MAX_RECONNECT_REPAIR) {
579 BmRepairAllControllers (ReconnectRepairCount + 1);
580 } else {
581 DEBUG ((
582 DEBUG_ERROR,
583 "[%a:%d] Repair failed after %d retries.\n",
584 __func__,
585 DEBUG_LINE_NUMBER,
586 ReconnectRepairCount
587 ));
588 }
589 }
590
591 if (RebootRequired) {
592 DEBUG ((DEBUG_INFO, "[BDS] One of the Driver Health instances requires rebooting.\n"));
593 gRT->ResetSystem (EfiResetWarm, EFI_SUCCESS, 0, NULL);
594 }
595}
UINT64 UINTN
UINTN EFIAPI StrSize(IN CONST CHAR16 *String)
Definition: String.c:72
BOOLEAN EFIAPI IsZeroGuid(IN CONST GUID *Guid)
Definition: MemLibGuid.c:156
CHAR16 * BmGetControllerName(IN EFI_HANDLE DriverHealthHandle, IN EFI_HANDLE ControllerHandle, IN EFI_HANDLE ChildHandle)
VOID BmDisplayMessages(IN EFI_BOOT_MANAGER_DRIVER_HEALTH_INFO *DriverHealthInfo)
EFI_STATUS EFIAPI EfiBootManagerFreeDriverHealthInfo(EFI_BOOT_MANAGER_DRIVER_HEALTH_INFO *DriverHealthInfo, UINTN Count)
EFI_STATUS EFIAPI BmRepairNotify(IN UINTN Value, IN UINTN Limit)
VOID BmRepairAllControllers(UINTN ReconnectRepairCount)
EFI_STATUS BmGetSingleControllerHealthStatus(IN OUT EFI_BOOT_MANAGER_DRIVER_HEALTH_INFO **DriverHealthInfo, IN OUT UINTN *Count, IN EFI_HANDLE DriverHealthHandle, IN EFI_HANDLE ControllerHandle OPTIONAL, IN EFI_HANDLE ChildHandle OPTIONAL)
EFI_BOOT_MANAGER_DRIVER_HEALTH_INFO *EFIAPI EfiBootManagerGetDriverHealthInfo(UINTN *Count)
EFI_DEVICE_PATH_PROTOCOL *EFIAPI DevicePathFromHandle(IN EFI_HANDLE Handle)
CHAR16 *EFIAPI ConvertDevicePathToText(IN CONST EFI_DEVICE_PATH_PROTOCOL *DevicePath, IN BOOLEAN DisplayOnly, IN BOOLEAN AllowShortcuts)
EFI_DRIVER_HEALTH_STATUS
Definition: DriverHealth.h:45
VOID *EFIAPI ReallocatePool(IN UINTN OldSize, IN UINTN NewSize, IN VOID *OldBuffer OPTIONAL)
VOID EFIAPI FreePool(IN VOID *Buffer)
VOID *EFIAPI AllocateCopyPool(IN UINTN AllocationSize, IN CONST VOID *Buffer)
EFI_HII_HANDLE *EFIAPI HiiGetHiiHandles(IN CONST EFI_GUID *PackageListGuid OPTIONAL)
Definition: HiiLib.c:286
EFI_STRING EFIAPI HiiGetString(IN EFI_HII_HANDLE HiiHandle, IN EFI_STRING_ID StringId, IN CONST CHAR8 *Language OPTIONAL)
Definition: HiiString.c:211
EFI_RUNTIME_SERVICES * gRT
#define NULL
Definition: Base.h:319
#define TRUE
Definition: Base.h:301
#define FALSE
Definition: Base.h:307
#define IN
Definition: Base.h:279
#define OUT
Definition: Base.h:284
#define GLOBAL_REMOVE_IF_UNREFERENCED
Definition: Base.h:48
#define ASSERT_EFI_ERROR(StatusParameter)
Definition: DebugLib.h:462
#define DEBUG_CODE_BEGIN()
Definition: DebugLib.h:564
#define DEBUG(Expression)
Definition: DebugLib.h:434
#define DEBUG_CODE_END()
Definition: DebugLib.h:578
#define PcdGet32(TokenName)
Definition: PcdLib.h:362
#define PcdGetPtr(TokenName)
Definition: PcdLib.h:388
RETURN_STATUS EFI_STATUS
Definition: UefiBaseType.h:29
VOID * EFI_HANDLE
Definition: UefiBaseType.h:33
#define EFI_SUCCESS
Definition: UefiBaseType.h:112
EFI_BOOT_SERVICES * gBS
VOID * EFI_HII_HANDLE
EFI_STATUS EFIAPI GetEfiGlobalVariable2(IN CONST CHAR16 *Name, OUT VOID **Value, OUT UINTN *Size OPTIONAL)
Definition: UefiLib.c:1470
UINTN EFIAPI Print(IN CONST CHAR16 *Format,...)
Definition: UefiLibPrint.c:113
CHAR8 *EFIAPI GetBestLanguage(IN CONST CHAR8 *SupportedLanguages, IN UINTN Iso639Language,...)
Definition: UefiLib.c:1522
@ EfiResetWarm
@ ByProtocol
Definition: UefiSpec.h:1518
@ AllHandles
Definition: UefiSpec.h:1509