VirtualBox

source: vbox/trunk/src/VBox/Devices/EFI/FirmwareNew/MdeModulePkg/Universal/DriverHealthManagerDxe/DriverHealthManagerDxe.c@ 108794

Last change on this file since 108794 was 108794, checked in by vboxsync, 2 weeks ago

Devices/EFI/FirmwareNew: Merge edk2-stable202502 from the vendor branch and make it build for the important platforms, bugref:4643

  • Property svn:eol-style set to native
File size: 36.5 KB
Line 
1/** @file
2 This module produces two driver health manager forms.
3 One will be used by BDS core to configure the Configured Required
4 driver health instances, the other will be automatically included by
5 firmware setup (UI).
6
7Copyright (c) 2013 - 2018, Intel Corporation. All rights reserved.<BR>
8(C) Copyright 2018 Hewlett Packard Enterprise Development LP<BR>
9SPDX-License-Identifier: BSD-2-Clause-Patent
10
11**/
12
13#include "DriverHealthManagerDxe.h"
14#include "DriverHealthManagerVfr.h"
15
16EFI_HII_CONFIG_ACCESS_PROTOCOL mDriverHealthManagerConfigAccess = {
17 DriverHealthManagerFakeExtractConfig,
18 DriverHealthManagerFakeRouteConfig,
19 DriverHealthManagerCallback
20};
21
22EFI_GUID mDriverHealthManagerForm = DRIVER_HEALTH_MANAGER_FORMSET_GUID;
23
24FORM_DEVICE_PATH mDriverHealthManagerFormDevicePath = {
25 {
26 {
27 HARDWARE_DEVICE_PATH,
28 HW_VENDOR_DP,
29 {
30 (UINT8)(sizeof (VENDOR_DEVICE_PATH)),
31 (UINT8)((sizeof (VENDOR_DEVICE_PATH)) >> 8)
32 }
33 },
34 EFI_CALLER_ID_GUID
35 },
36 {
37 END_DEVICE_PATH_TYPE,
38 END_ENTIRE_DEVICE_PATH_SUBTYPE,
39 {
40 (UINT8)(END_DEVICE_PATH_LENGTH),
41 (UINT8)((END_DEVICE_PATH_LENGTH) >> 8)
42 }
43 }
44};
45
46EFI_HII_HANDLE mDriverHealthManagerHiiHandle;
47EFI_BOOT_MANAGER_DRIVER_HEALTH_INFO *mDriverHealthManagerHealthInfo = NULL;
48UINTN mDriverHealthManagerHealthInfoCount = 0;
49EFI_HII_DATABASE_PROTOCOL *mDriverHealthManagerDatabase;
50
51extern UINT8 DriverHealthManagerVfrBin[];
52extern UINT8 DriverHealthConfigureVfrBin[];
53
54/**
55 This function allows a caller to extract the current configuration for one
56 or more named elements from the target driver.
57
58
59 @param This Points to the EFI_HII_CONFIG_ACCESS_PROTOCOL.
60 @param Request A null-terminated Unicode string in <ConfigRequest> format.
61 @param Progress On return, points to a character in the Request string.
62 Points to the string's null terminator if request was successful.
63 Points to the most recent '&' before the first failing name/value
64 pair (or the beginning of the string if the failure is in the
65 first name/value pair) if the request was not successful.
66 @param Results A null-terminated Unicode string in <ConfigAltResp> format which
67 has all values filled in for the names in the Request string.
68 String to be allocated by the called function.
69
70 @retval EFI_SUCCESS The Results is filled with the requested values.
71 @retval EFI_OUT_OF_RESOURCES Not enough memory to store the results.
72 @retval EFI_INVALID_PARAMETER Request is illegal syntax, or unknown name.
73 @retval EFI_NOT_FOUND Routing data doesn't match any storage in this driver.
74
75**/
76EFI_STATUS
77EFIAPI
78DriverHealthManagerFakeExtractConfig (
79 IN CONST EFI_HII_CONFIG_ACCESS_PROTOCOL *This,
80 IN CONST EFI_STRING Request,
81 OUT EFI_STRING *Progress,
82 OUT EFI_STRING *Results
83 )
84{
85 if ((Progress == NULL) || (Results == NULL)) {
86 return EFI_INVALID_PARAMETER;
87 }
88
89 *Progress = Request;
90 return EFI_NOT_FOUND;
91}
92
93/**
94 This function processes the results of changes in configuration.
95
96
97 @param This Points to the EFI_HII_CONFIG_ACCESS_PROTOCOL.
98 @param Configuration A null-terminated Unicode string in <ConfigResp> format.
99 @param Progress A pointer to a string filled in with the offset of the most
100 recent '&' before the first failing name/value pair (or the
101 beginning of the string if the failure is in the first
102 name/value pair) or the terminating NULL if all was successful.
103
104 @retval EFI_SUCCESS The Results is processed successfully.
105 @retval EFI_INVALID_PARAMETER Configuration is NULL.
106 @retval EFI_NOT_FOUND Routing data doesn't match any storage in this driver.
107
108**/
109EFI_STATUS
110EFIAPI
111DriverHealthManagerFakeRouteConfig (
112 IN CONST EFI_HII_CONFIG_ACCESS_PROTOCOL *This,
113 IN CONST EFI_STRING Configuration,
114 OUT EFI_STRING *Progress
115 )
116{
117 if ((Configuration == NULL) || (Progress == NULL)) {
118 return EFI_INVALID_PARAMETER;
119 }
120
121 *Progress = Configuration;
122
123 return EFI_NOT_FOUND;
124}
125
126/**
127
128 Install the health manager forms.
129 One will be used by BDS core to configure the Configured Required
130 driver health instances, the other will be automatically included by
131 firmware setup (UI).
132
133 @param ImageHandle The image handle.
134 @param SystemTable The system table.
135
136 @retval EFI_SUCEESS The health manager forms are successfully installed.
137
138**/
139EFI_STATUS
140EFIAPI
141InitializeDriverHealthManager (
142 EFI_HANDLE ImageHandle,
143 EFI_SYSTEM_TABLE *SystemTable
144 )
145{
146 EFI_STATUS Status;
147 EFI_HANDLE Handle;
148
149 Status = gBS->LocateProtocol (
150 &gEfiHiiDatabaseProtocolGuid,
151 NULL,
152 (VOID **)&mDriverHealthManagerDatabase
153 );
154 ASSERT_EFI_ERROR (Status);
155
156 Handle = NULL;
157 Status = gBS->InstallMultipleProtocolInterfaces (
158 &Handle,
159 &gEfiDevicePathProtocolGuid,
160 &mDriverHealthManagerFormDevicePath,
161 &gEfiHiiConfigAccessProtocolGuid,
162 &mDriverHealthManagerConfigAccess,
163 NULL
164 );
165 ASSERT_EFI_ERROR (Status);
166
167 //
168 // Publish Driver Health HII data.
169 //
170 mDriverHealthManagerHiiHandle = HiiAddPackages (
171 &gEfiCallerIdGuid,
172 Handle,
173 DriverHealthManagerVfrBin,
174 DriverHealthConfigureVfrBin,
175 STRING_ARRAY_NAME,
176 NULL
177 );
178 ASSERT (mDriverHealthManagerHiiHandle != NULL);
179
180 return EFI_SUCCESS;
181}
182
183/**
184
185 Select the best matching language according to front page policy for best user experience.
186
187 This function supports both ISO 639-2 and RFC 4646 language codes, but language
188 code types may not be mixed in a single call to this function.
189
190 @param SupportedLanguages A pointer to a Null-terminated ASCII string that
191 contains a set of language codes in the format
192 specified by Iso639Language.
193 @param Iso639Language If TRUE, then all language codes are assumed to be
194 in ISO 639-2 format. If FALSE, then all language
195 codes are assumed to be in RFC 4646 language format.
196
197 @retval NULL The best matching language could not be found in SupportedLanguages.
198 @retval NULL There are not enough resources available to return the best matching
199 language.
200 @retval Other A pointer to a Null-terminated ASCII string that is the best matching
201 language in SupportedLanguages.
202**/
203CHAR8 *
204DriverHealthManagerSelectBestLanguage (
205 IN CHAR8 *SupportedLanguages,
206 IN BOOLEAN Iso639Language
207 )
208{
209 CHAR8 *LanguageVariable;
210 CHAR8 *BestLanguage;
211
212 GetEfiGlobalVariable2 (Iso639Language ? L"Lang" : L"PlatformLang", (VOID **)&LanguageVariable, NULL);
213
214 BestLanguage = GetBestLanguage (
215 SupportedLanguages,
216 Iso639Language,
217 (LanguageVariable != NULL) ? LanguageVariable : "",
218 Iso639Language ? "eng" : "en-US",
219 NULL
220 );
221 if (LanguageVariable != NULL) {
222 FreePool (LanguageVariable);
223 }
224
225 return BestLanguage;
226}
227
228/**
229
230 This is an internal worker function to get the Component Name (2) protocol interface
231 and the language it supports.
232
233 @param ProtocolGuid A pointer to an EFI_GUID. It points to Component Name (2) protocol GUID.
234 @param DriverBindingHandle The handle on which the Component Name (2) protocol instance is retrieved.
235 @param ComponentName A pointer to the Component Name (2) protocol interface.
236 @param SupportedLanguage The best suitable language that matches the SupportedLangues interface for the
237 located Component Name (2) instance.
238
239 @retval EFI_SUCCESS The Component Name (2) protocol instance is successfully located and we find
240 the best matching language it support.
241 @retval EFI_UNSUPPORTED The input Language is not supported by the Component Name (2) protocol.
242 @retval Other Some error occurs when locating Component Name (2) protocol instance or finding
243 the supported language.
244
245**/
246EFI_STATUS
247DriverHealthManagerGetComponentNameWorker (
248 IN EFI_GUID *ProtocolGuid,
249 IN EFI_HANDLE DriverBindingHandle,
250 OUT EFI_COMPONENT_NAME_PROTOCOL **ComponentName,
251 OUT CHAR8 **SupportedLanguage
252 )
253{
254 EFI_STATUS Status;
255
256 //
257 // Locate Component Name (2) protocol on the driver binging handle.
258 //
259 Status = gBS->OpenProtocol (
260 DriverBindingHandle,
261 ProtocolGuid,
262 (VOID **)ComponentName,
263 NULL,
264 NULL,
265 EFI_OPEN_PROTOCOL_GET_PROTOCOL
266 );
267 if (EFI_ERROR (Status)) {
268 return Status;
269 }
270
271 //
272 // Apply shell policy to select the best language.
273 //
274 *SupportedLanguage = DriverHealthManagerSelectBestLanguage (
275 (*ComponentName)->SupportedLanguages,
276 (BOOLEAN)(ProtocolGuid == &gEfiComponentNameProtocolGuid)
277 );
278 if (*SupportedLanguage == NULL) {
279 Status = EFI_UNSUPPORTED;
280 }
281
282 return Status;
283}
284
285/**
286
287 This is an internal worker function to get driver name from Component Name (2) protocol interface.
288
289 @param ProtocolGuid A pointer to an EFI_GUID. It points to Component Name (2) protocol GUID.
290 @param DriverBindingHandle The handle on which the Component Name (2) protocol instance is retrieved.
291 @param DriverName A pointer to the Unicode string to return. This Unicode string is the name
292 of the driver specified by This.
293
294 @retval EFI_SUCCESS The driver name is successfully retrieved from Component Name (2) protocol
295 interface.
296 @retval Other The driver name cannot be retrieved from Component Name (2) protocol
297 interface.
298
299**/
300EFI_STATUS
301DriverHealthManagerGetDriverNameWorker (
302 IN EFI_GUID *ProtocolGuid,
303 IN EFI_HANDLE DriverBindingHandle,
304 OUT CHAR16 **DriverName
305 )
306{
307 EFI_STATUS Status;
308 CHAR8 *BestLanguage;
309 EFI_COMPONENT_NAME_PROTOCOL *ComponentName;
310
311 //
312 // Retrieve Component Name (2) protocol instance on the driver binding handle and
313 // find the best language this instance supports.
314 //
315 Status = DriverHealthManagerGetComponentNameWorker (
316 ProtocolGuid,
317 DriverBindingHandle,
318 &ComponentName,
319 &BestLanguage
320 );
321 if (EFI_ERROR (Status)) {
322 return Status;
323 }
324
325 //
326 // Get the driver name from Component Name (2) protocol instance on the driver binging handle.
327 //
328 Status = ComponentName->GetDriverName (
329 ComponentName,
330 BestLanguage,
331 DriverName
332 );
333 FreePool (BestLanguage);
334
335 return Status;
336}
337
338/**
339 This function gets driver name from Component Name 2 protocol interface and Component Name protocol interface
340 in turn. It first tries UEFI 2.0 Component Name 2 protocol interface and try to get the driver name.
341 If the attempt fails, it then gets the driver name from EFI 1.1 Component Name protocol for backward
342 compatibility support.
343
344 @param DriverBindingHandle The handle on which the Component Name (2) protocol instance is retrieved.
345
346 @return A pointer to the Unicode string to return. This Unicode string is the name of the controller
347 specified by ControllerHandle and ChildHandle.
348
349
350**/
351CHAR16 *
352DriverHealthManagerGetDriverName (
353 IN EFI_HANDLE DriverBindingHandle
354 )
355{
356 EFI_STATUS Status;
357 CHAR16 *DriverName;
358
359 //
360 // Get driver name from UEFI 2.0 Component Name 2 protocol interface.
361 //
362 Status = DriverHealthManagerGetDriverNameWorker (&gEfiComponentName2ProtocolGuid, DriverBindingHandle, &DriverName);
363 if (EFI_ERROR (Status)) {
364 //
365 // If it fails to get the driver name from Component Name protocol interface, we should fall back on
366 // EFI 1.1 Component Name protocol interface.
367 //
368 Status = DriverHealthManagerGetDriverNameWorker (&gEfiComponentNameProtocolGuid, DriverBindingHandle, &DriverName);
369 }
370
371 if (!EFI_ERROR (Status)) {
372 return AllocateCopyPool (StrSize (DriverName), DriverName);
373 } else {
374 return ConvertDevicePathToText (DevicePathFromHandle (DriverBindingHandle), FALSE, TRUE);
375 }
376}
377
378/**
379 This function gets controller name from Component Name 2 protocol interface and Component Name protocol interface
380 in turn. It first tries UEFI 2.0 Component Name 2 protocol interface and try to get the controller name.
381 If the attempt fails, it then gets the controller name from EFI 1.1 Component Name protocol for backward
382 compatibility support.
383
384 @param ProtocolGuid A pointer to an EFI_GUID. It points to Component Name (2) protocol GUID.
385 @param DriverBindingHandle The handle on which the Component Name (2) protocol instance is retrieved.
386 @param ControllerHandle The handle of a controller that the driver specified by This is managing.
387 This handle specifies the controller whose name is to be returned.
388 @param ChildHandle The handle of the child controller to retrieve the name of. This is an
389 optional parameter that may be NULL. It will be NULL for device drivers.
390 It will also be NULL for bus drivers that attempt to retrieve the name
391 of the bus controller. It will not be NULL for a bus driver that attempts
392 to retrieve the name of a child controller.
393 @param ControllerName A pointer to the Unicode string to return. This Unicode string
394 is the name of the controller specified by ControllerHandle and ChildHandle.
395
396 @retval EFI_SUCCESS The controller name is successfully retrieved from Component Name (2) protocol
397 interface.
398 @retval Other The controller name cannot be retrieved from Component Name (2) protocol.
399
400**/
401EFI_STATUS
402DriverHealthManagerGetControllerNameWorker (
403 IN EFI_GUID *ProtocolGuid,
404 IN EFI_HANDLE DriverBindingHandle,
405 IN EFI_HANDLE ControllerHandle,
406 IN EFI_HANDLE ChildHandle,
407 OUT CHAR16 **ControllerName
408 )
409{
410 EFI_STATUS Status;
411 CHAR8 *BestLanguage;
412 EFI_COMPONENT_NAME_PROTOCOL *ComponentName;
413
414 //
415 // Retrieve Component Name (2) protocol instance on the driver binding handle and
416 // find the best language this instance supports.
417 //
418 Status = DriverHealthManagerGetComponentNameWorker (
419 ProtocolGuid,
420 DriverBindingHandle,
421 &ComponentName,
422 &BestLanguage
423 );
424 if (EFI_ERROR (Status)) {
425 return Status;
426 }
427
428 //
429 // Get the controller name from Component Name (2) protocol instance on the driver binging handle.
430 //
431 Status = ComponentName->GetControllerName (
432 ComponentName,
433 ControllerHandle,
434 ChildHandle,
435 BestLanguage,
436 ControllerName
437 );
438 FreePool (BestLanguage);
439
440 return Status;
441}
442
443/**
444
445 This function gets controller name from Component Name 2 protocol interface and Component Name protocol interface
446 in turn. It first tries UEFI 2.0 Component Name 2 protocol interface and try to get the controller name.
447 If the attempt fails, it then gets the controller name from EFI 1.1 Component Name protocol for backward
448 compatibility support.
449
450 @param DriverBindingHandle The handle on which the Component Name (2) protocol instance is retrieved.
451 @param ControllerHandle The handle of a controller that the driver specified by DriverBindingHandle is managing.
452 This handle specifies the controller whose name is to be returned.
453 @param ChildHandle The handle of the child controller to retrieve the name of. This is an
454 optional parameter that may be NULL. It will be NULL for device drivers.
455 It will also be NULL for bus drivers that attempt to retrieve the name
456 of the bus controller. It will not be NULL for a bus driver that attempts
457 to retrieve the name of a child controller.
458
459 @return A pointer to the Unicode string to return. This Unicode string is the name of the controller
460 specified by ControllerHandle and ChildHandle.
461**/
462CHAR16 *
463DriverHealthManagerGetControllerName (
464 IN EFI_HANDLE DriverBindingHandle,
465 IN EFI_HANDLE ControllerHandle,
466 IN EFI_HANDLE ChildHandle
467 )
468{
469 EFI_STATUS Status;
470 CHAR16 *ControllerName;
471
472 //
473 // Get controller name from UEFI 2.0 Component Name 2 protocol interface.
474 //
475 Status = DriverHealthManagerGetControllerNameWorker (
476 &gEfiComponentName2ProtocolGuid,
477 DriverBindingHandle,
478 ControllerHandle,
479 ChildHandle,
480 &ControllerName
481 );
482 if (EFI_ERROR (Status)) {
483 //
484 // If it fails to get the controller name from Component Name protocol interface, we should fall back on
485 // EFI 1.1 Component Name protocol interface.
486 //
487 Status = DriverHealthManagerGetControllerNameWorker (
488 &gEfiComponentNameProtocolGuid,
489 DriverBindingHandle,
490 ControllerHandle,
491 ChildHandle,
492 &ControllerName
493 );
494 }
495
496 if (!EFI_ERROR (Status)) {
497 return AllocateCopyPool (StrSize (ControllerName), ControllerName);
498 } else {
499 return ConvertDevicePathToText (DevicePathFromHandle (ChildHandle != NULL ? ChildHandle : ControllerHandle), FALSE, TRUE);
500 }
501}
502
503/**
504 The repair notify function.
505 @param Value A value between 0 and Limit that identifies the current progress
506 of the repair operation.
507 @param Limit The maximum value of Value for the current repair operation.
508 If Limit is 0, then the completion progress is indeterminate.
509 For example, a driver that wants to specify progress in percent
510 would use a Limit value of 100.
511
512 @retval EFI_SUCCESS Successfully return from the notify function.
513**/
514EFI_STATUS
515EFIAPI
516DriverHealthManagerRepairNotify (
517 IN UINTN Value,
518 IN UINTN Limit
519 )
520{
521 DEBUG ((DEBUG_INFO, "[DriverHealthManagement]RepairNotify: %d/%d\n", Value, Limit));
522 return EFI_SUCCESS;
523}
524
525/**
526 Look for the formset GUID which has the gEfiHiiDriverHealthFormsetGuid class GUID in the specified HII package list.
527
528 @param Handle Handle to the HII package list.
529 @param FormsetGuid Return the formset GUID.
530
531 @retval EFI_SUCCESS The formset is found successfully.
532 @retval EFI_NOT_FOUND The formset cannot be found.
533**/
534EFI_STATUS
535DriverHealthManagerGetFormsetId (
536 IN EFI_HII_HANDLE Handle,
537 OUT EFI_GUID *FormsetGuid
538 )
539{
540 EFI_STATUS Status;
541 EFI_HII_PACKAGE_LIST_HEADER *HiiPackageList;
542 UINTN BufferSize;
543 UINT8 *Package;
544 UINT8 *OpCodeData;
545 UINT32 Offset;
546 UINT32 Offset2;
547 EFI_HII_PACKAGE_HEADER PackageHeader;
548 UINT8 Index;
549 UINT8 NumberOfClassGuid;
550 EFI_GUID *ClassGuid;
551
552 //
553 // Get HII PackageList
554 //
555 BufferSize = 0;
556 HiiPackageList = NULL;
557 Status = mDriverHealthManagerDatabase->ExportPackageLists (mDriverHealthManagerDatabase, Handle, &BufferSize, HiiPackageList);
558 if (Status == EFI_BUFFER_TOO_SMALL) {
559 HiiPackageList = AllocatePool (BufferSize);
560 ASSERT (HiiPackageList != NULL);
561
562 Status = mDriverHealthManagerDatabase->ExportPackageLists (mDriverHealthManagerDatabase, Handle, &BufferSize, HiiPackageList);
563 }
564
565 if (EFI_ERROR (Status)) {
566 return Status;
567 }
568
569 ASSERT (HiiPackageList != NULL);
570
571 //
572 // Get Form package from this HII package List
573 //
574 for (Offset = sizeof (EFI_HII_PACKAGE_LIST_HEADER); Offset < ReadUnaligned32 (&HiiPackageList->PackageLength); Offset += PackageHeader.Length) {
575 Package = ((UINT8 *)HiiPackageList) + Offset;
576 CopyMem (&PackageHeader, Package, sizeof (EFI_HII_PACKAGE_HEADER));
577
578 if (PackageHeader.Type == EFI_HII_PACKAGE_FORMS) {
579 //
580 // Search FormSet in this Form Package
581 //
582
583 for (Offset2 = sizeof (EFI_HII_PACKAGE_HEADER); Offset2 < PackageHeader.Length; Offset2 += ((EFI_IFR_OP_HEADER *)OpCodeData)->Length) {
584 OpCodeData = Package + Offset2;
585
586 if ((((EFI_IFR_OP_HEADER *)OpCodeData)->OpCode == EFI_IFR_FORM_SET_OP) &&
587 (((EFI_IFR_OP_HEADER *)OpCodeData)->Length > OFFSET_OF (EFI_IFR_FORM_SET, Flags)))
588 {
589 //
590 // Try to compare against formset class GUID
591 //
592 NumberOfClassGuid = (UINT8)(((EFI_IFR_FORM_SET *)OpCodeData)->Flags & 0x3);
593 ClassGuid = (EFI_GUID *)(OpCodeData + sizeof (EFI_IFR_FORM_SET));
594 for (Index = 0; Index < NumberOfClassGuid; Index++) {
595 if (CompareGuid (&gEfiHiiDriverHealthFormsetGuid, &ClassGuid[Index])) {
596 CopyMem (FormsetGuid, &((EFI_IFR_FORM_SET *)OpCodeData)->Guid, sizeof (EFI_GUID));
597 FreePool (HiiPackageList);
598 return EFI_SUCCESS;
599 }
600 }
601 }
602 }
603 }
604 }
605
606 //
607 // Form package not found in this Package List
608 //
609 FreePool (HiiPackageList);
610 return EFI_NOT_FOUND;
611}
612
613/**
614 Processes a single controller using the EFI Driver Health Protocol associated with
615 that controller.
616
617 @param DriverHealth A pointer to the EFI_DRIVER_HEALTH_PROTOCOL instance.
618 @param ControllerHandle The class guid specifies which form set will be displayed.
619 @param ChildHandle The handle of the child controller to retrieve the health
620 status on. This is an optional parameter that may be NULL.
621 @param HealthStatus The health status of the controller.
622 @param MessageList An array of warning or error messages associated
623 with the controller specified by ControllerHandle and
624 ChildHandle. This is an optional parameter that may be NULL.
625 @param FormHiiHandle The HII handle for an HII form associated with the
626 controller specified by ControllerHandle and ChildHandle.
627**/
628VOID
629DriverHealthManagerProcessSingleControllerHealth (
630 IN EFI_DRIVER_HEALTH_PROTOCOL *DriverHealth,
631 IN EFI_HANDLE ControllerHandle OPTIONAL,
632 IN EFI_HANDLE ChildHandle OPTIONAL,
633 IN EFI_DRIVER_HEALTH_STATUS HealthStatus,
634 IN EFI_DRIVER_HEALTH_HII_MESSAGE **MessageList OPTIONAL,
635 IN EFI_HII_HANDLE FormHiiHandle
636 )
637{
638 EFI_STATUS Status;
639
640 ASSERT (HealthStatus != EfiDriverHealthStatusConfigurationRequired);
641 //
642 // If the module need to be repaired or reconfiguration, will process it until
643 // reach a terminal status. The status from EfiDriverHealthStatusRepairRequired after repair
644 // will be in (Health, Failed, Configuration Required).
645 //
646 switch (HealthStatus) {
647 case EfiDriverHealthStatusRepairRequired:
648 Status = DriverHealth->Repair (
649 DriverHealth,
650 ControllerHandle,
651 ChildHandle,
652 DriverHealthManagerRepairNotify
653 );
654 break;
655
656 case EfiDriverHealthStatusRebootRequired:
657 gRT->ResetSystem (EfiResetWarm, EFI_SUCCESS, 0, NULL);
658 break;
659
660 case EfiDriverHealthStatusReconnectRequired:
661 Status = gBS->DisconnectController (ControllerHandle, NULL, NULL);
662 if (EFI_ERROR (Status)) {
663 //
664 // Disconnect failed. Need to promote reconnect to a reboot.
665 //
666 gRT->ResetSystem (EfiResetWarm, EFI_SUCCESS, 0, NULL);
667 } else {
668 gBS->ConnectController (ControllerHandle, NULL, NULL, TRUE);
669 }
670
671 break;
672
673 default:
674 break;
675 }
676}
677
678/**
679 Update the form to include the driver health instances.
680
681 @param ConfigureOnly Only include the configure required driver health instances
682 when TRUE, include all the driver health instances otherwise.
683**/
684VOID
685DriverHealthManagerUpdateForm (
686 BOOLEAN ConfigureOnly
687 )
688{
689 EFI_STATUS Status;
690 EFI_IFR_GUID_LABEL *StartLabel;
691 EFI_IFR_GUID_LABEL *EndLabel;
692 VOID *StartOpCodeHandle;
693 VOID *EndOpCodeHandle;
694 UINTN Index;
695 EFI_STRING_ID Prompt;
696 EFI_STRING_ID Help;
697 EFI_STRING_ID TextTwo;
698 CHAR16 String[512];
699 UINTN StringCount;
700 EFI_STRING TmpString;
701 EFI_STRING DriverName;
702 EFI_STRING ControllerName;
703 UINTN MessageIndex;
704 EFI_HANDLE DriverHandle;
705 EFI_STRING_ID DevicePath;
706 EFI_GUID FormsetGuid;
707
708 EfiBootManagerFreeDriverHealthInfo (mDriverHealthManagerHealthInfo, mDriverHealthManagerHealthInfoCount);
709 mDriverHealthManagerHealthInfo = EfiBootManagerGetDriverHealthInfo (&mDriverHealthManagerHealthInfoCount);
710
711 //
712 // Allocate space for creation of UpdateData Buffer
713 //
714 StartOpCodeHandle = HiiAllocateOpCodeHandle ();
715 ASSERT (StartOpCodeHandle != NULL);
716
717 EndOpCodeHandle = HiiAllocateOpCodeHandle ();
718 ASSERT (EndOpCodeHandle != NULL);
719
720 //
721 // Create Hii Extend Label OpCode as the start opcode
722 //
723 StartLabel = (EFI_IFR_GUID_LABEL *)HiiCreateGuidOpCode (StartOpCodeHandle, &gEfiIfrTianoGuid, NULL, sizeof (EFI_IFR_GUID_LABEL));
724 StartLabel->ExtendOpCode = EFI_IFR_EXTEND_OP_LABEL;
725 StartLabel->Number = LABEL_BEGIN;
726
727 //
728 // Create Hii Extend Label OpCode as the end opcode
729 //
730 EndLabel = (EFI_IFR_GUID_LABEL *)HiiCreateGuidOpCode (EndOpCodeHandle, &gEfiIfrTianoGuid, NULL, sizeof (EFI_IFR_GUID_LABEL));
731 EndLabel->ExtendOpCode = EFI_IFR_EXTEND_OP_LABEL;
732 EndLabel->Number = LABEL_END;
733
734 for (Index = 0; Index < mDriverHealthManagerHealthInfoCount; Index++) {
735 if (ConfigureOnly && (mDriverHealthManagerHealthInfo[Index].HealthStatus != EfiDriverHealthStatusConfigurationRequired)) {
736 continue;
737 }
738
739 DriverName = DriverHealthManagerGetDriverName (mDriverHealthManagerHealthInfo[Index].DriverHealthHandle);
740 ASSERT (DriverName != NULL);
741
742 if (mDriverHealthManagerHealthInfo[Index].ControllerHandle == NULL) {
743 //
744 // The ControllerHandle is set to NULL and the HealthStatus is set to EfiDriverHealthStatusHealthy
745 // if all the controllers managed by the driver are in healthy state.
746 //
747 ASSERT (mDriverHealthManagerHealthInfo[Index].HealthStatus == EfiDriverHealthStatusHealthy);
748 UnicodeSPrint (String, sizeof (String), L"%s", DriverName);
749 } else {
750 ControllerName = DriverHealthManagerGetControllerName (
751 mDriverHealthManagerHealthInfo[Index].DriverHealthHandle,
752 mDriverHealthManagerHealthInfo[Index].ControllerHandle,
753 mDriverHealthManagerHealthInfo[Index].ChildHandle
754 );
755 ASSERT (ControllerName != NULL);
756 UnicodeSPrint (String, sizeof (String), L"%s %s", DriverName, ControllerName);
757 FreePool (ControllerName);
758 }
759
760 FreePool (DriverName);
761
762 Prompt = HiiSetString (mDriverHealthManagerHiiHandle, 0, String, NULL);
763
764 switch (mDriverHealthManagerHealthInfo[Index].HealthStatus) {
765 case EfiDriverHealthStatusRepairRequired:
766 TmpString = HiiGetString (mDriverHealthManagerHiiHandle, STRING_TOKEN (STR_REPAIR_REQUIRED), NULL);
767 break;
768 case EfiDriverHealthStatusConfigurationRequired:
769 TmpString = HiiGetString (mDriverHealthManagerHiiHandle, STRING_TOKEN (STR_CONFIGURATION_REQUIRED), NULL);
770 break;
771 case EfiDriverHealthStatusFailed:
772 TmpString = HiiGetString (mDriverHealthManagerHiiHandle, STRING_TOKEN (STR_FAILED), NULL);
773 break;
774 case EfiDriverHealthStatusReconnectRequired:
775 TmpString = HiiGetString (mDriverHealthManagerHiiHandle, STRING_TOKEN (STR_RECONNECT_REQUIRED), NULL);
776 break;
777 case EfiDriverHealthStatusRebootRequired:
778 TmpString = HiiGetString (mDriverHealthManagerHiiHandle, STRING_TOKEN (STR_REBOOT_REQUIRED), NULL);
779 break;
780 default:
781 ASSERT (mDriverHealthManagerHealthInfo[Index].HealthStatus == EfiDriverHealthStatusHealthy);
782 TmpString = HiiGetString (mDriverHealthManagerHiiHandle, STRING_TOKEN (STR_HEALTHY), NULL);
783 break;
784 }
785
786 StringCount = UnicodeSPrint (String, sizeof (String), L"%s\n", TmpString);
787 FreePool (TmpString);
788
789 //
790 // Add the message of the Module itself provided as the help.
791 //
792 if (mDriverHealthManagerHealthInfo[Index].MessageList != NULL) {
793 for (MessageIndex = 0; mDriverHealthManagerHealthInfo[Index].MessageList[MessageIndex].HiiHandle != NULL; MessageIndex++) {
794 TmpString = HiiGetString (
795 mDriverHealthManagerHealthInfo[Index].MessageList[MessageIndex].HiiHandle,
796 mDriverHealthManagerHealthInfo[Index].MessageList[MessageIndex].StringId,
797 NULL
798 );
799 StringCount += UnicodeSPrint (String + StringCount, sizeof (String) - sizeof (String[0]) * StringCount, L"\n%s", TmpString);
800 FreePool (TmpString);
801 }
802 }
803
804 Help = HiiSetString (mDriverHealthManagerHiiHandle, 0, String, NULL);
805
806 switch (mDriverHealthManagerHealthInfo[Index].HealthStatus) {
807 case EfiDriverHealthStatusConfigurationRequired:
808 Status = mDriverHealthManagerDatabase->GetPackageListHandle (
809 mDriverHealthManagerDatabase,
810 mDriverHealthManagerHealthInfo[Index].HiiHandle,
811 &DriverHandle
812 );
813 ASSERT_EFI_ERROR (Status);
814 TmpString = ConvertDevicePathToText (DevicePathFromHandle (DriverHandle), FALSE, TRUE);
815 DevicePath = HiiSetString (mDriverHealthManagerHiiHandle, 0, TmpString, NULL);
816 FreePool (TmpString);
817
818 Status = DriverHealthManagerGetFormsetId (mDriverHealthManagerHealthInfo[Index].HiiHandle, &FormsetGuid);
819 ASSERT_EFI_ERROR (Status);
820
821 HiiCreateGotoExOpCode (
822 StartOpCodeHandle,
823 0,
824 Prompt,
825 Help,
826 0,
827 0,
828 0,
829 &FormsetGuid,
830 DevicePath
831 );
832 break;
833
834 case EfiDriverHealthStatusRepairRequired:
835 case EfiDriverHealthStatusReconnectRequired:
836 case EfiDriverHealthStatusRebootRequired:
837 HiiCreateActionOpCode (
838 StartOpCodeHandle,
839 (EFI_QUESTION_ID)(Index + QUESTION_ID_DRIVER_HEALTH_BASE),
840 Prompt,
841 Help,
842 EFI_IFR_FLAG_CALLBACK,
843 0
844 );
845 break;
846
847 default:
848 ASSERT (
849 mDriverHealthManagerHealthInfo[Index].HealthStatus == EfiDriverHealthStatusHealthy ||
850 mDriverHealthManagerHealthInfo[Index].HealthStatus == EfiDriverHealthStatusFailed
851 );
852 TextTwo = Help;
853 HiiCreateTextOpCode (
854 StartOpCodeHandle,
855 Prompt,
856 0,
857 TextTwo
858 );
859 break;
860 }
861 }
862
863 Status = HiiUpdateForm (
864 mDriverHealthManagerHiiHandle,
865 ConfigureOnly ? PcdGetPtr (PcdDriverHealthConfigureForm) : &mDriverHealthManagerForm,
866 DRIVER_HEALTH_FORM_ID,
867 StartOpCodeHandle,
868 EndOpCodeHandle
869 );
870 ASSERT_EFI_ERROR (Status);
871
872 HiiFreeOpCodeHandle (StartOpCodeHandle);
873 HiiFreeOpCodeHandle (EndOpCodeHandle);
874}
875
876/**
877 Called when the form is closing to remove the dynamicly added string from the HII package list.
878**/
879VOID
880DriverHealthManagerCleanDynamicString (
881 VOID
882 )
883{
884 EFI_STATUS Status;
885 EFI_HII_PACKAGE_LIST_HEADER *HiiPackageList;
886 UINTN BufferSize;
887 EFI_HII_PACKAGE_HEADER *PackageHeader;
888 UINT32 FixedStringSize;
889
890 FixedStringSize = *(UINT32 *)&STRING_ARRAY_NAME - sizeof (UINT32);
891 BufferSize = sizeof (EFI_HII_PACKAGE_LIST_HEADER) + FixedStringSize + sizeof (EFI_HII_PACKAGE_HEADER);
892 HiiPackageList = AllocatePool (BufferSize);
893 ASSERT (HiiPackageList != NULL);
894
895 HiiPackageList->PackageLength = (UINT32)BufferSize;
896 CopyMem (&HiiPackageList->PackageListGuid, &gEfiCallerIdGuid, sizeof (EFI_GUID));
897
898 PackageHeader = (EFI_HII_PACKAGE_HEADER *)(HiiPackageList + 1);
899 CopyMem (PackageHeader, STRING_ARRAY_NAME + sizeof (UINT32), FixedStringSize);
900
901 PackageHeader = (EFI_HII_PACKAGE_HEADER *)((UINT8 *)PackageHeader + PackageHeader->Length);
902 PackageHeader->Type = EFI_HII_PACKAGE_END;
903 PackageHeader->Length = sizeof (EFI_HII_PACKAGE_HEADER);
904
905 Status = mDriverHealthManagerDatabase->UpdatePackageList (
906 mDriverHealthManagerDatabase,
907 mDriverHealthManagerHiiHandle,
908 HiiPackageList
909 );
910 ASSERT_EFI_ERROR (Status);
911
912 //
913 // Form package not found in this Package List
914 //
915 FreePool (HiiPackageList);
916}
917
918/**
919 This function is invoked if user selected a interactive opcode from Driver Health's
920 Formset.
921
922 @param This Points to the EFI_HII_CONFIG_ACCESS_PROTOCOL.
923 @param Action Specifies the type of action taken by the browser.
924 @param QuestionId A unique value which is sent to the original exporting driver
925 so that it can identify the type of data to expect.
926 @param Type The type of value for the question.
927 @param Value A pointer to the data being sent to the original exporting driver.
928 @param ActionRequest On return, points to the action requested by the callback function.
929
930 @retval EFI_SUCCESS The callback successfully handled the action.
931 @retval EFI_INVALID_PARAMETER The setup browser call this function with invalid parameters.
932
933**/
934EFI_STATUS
935EFIAPI
936DriverHealthManagerCallback (
937 IN CONST EFI_HII_CONFIG_ACCESS_PROTOCOL *This,
938 IN EFI_BROWSER_ACTION Action,
939 IN EFI_QUESTION_ID QuestionId,
940 IN UINT8 Type,
941 IN EFI_IFR_TYPE_VALUE *Value,
942 OUT EFI_BROWSER_ACTION_REQUEST *ActionRequest
943 )
944{
945 UINTN Index;
946
947 if ((QuestionId == QUESTION_ID_REFRESH_MANAGER) || (QuestionId == QUESTION_ID_REFRESH_CONFIGURE)) {
948 if (Action == EFI_BROWSER_ACTION_FORM_OPEN) {
949 DriverHealthManagerUpdateForm ((BOOLEAN)(QuestionId == QUESTION_ID_REFRESH_CONFIGURE));
950 } else if (Action == EFI_BROWSER_ACTION_FORM_CLOSE) {
951 DriverHealthManagerCleanDynamicString ();
952 }
953
954 return EFI_SUCCESS;
955 }
956
957 if (Action != EFI_BROWSER_ACTION_CHANGED) {
958 //
959 // Do nothing for other UEFI Action. Only do call back when data is changed.
960 //
961 return EFI_UNSUPPORTED;
962 }
963
964 if ((Value == NULL) || (ActionRequest == NULL)) {
965 return EFI_INVALID_PARAMETER;
966 }
967
968 DEBUG ((DEBUG_ERROR, "QuestionId = %x\n", QuestionId));
969
970 //
971 // We will have returned from processing a callback - user either hit ESC to exit, or selected
972 // a target to display.
973 // Process the diver health status states here.
974 //
975 Index = QuestionId - QUESTION_ID_DRIVER_HEALTH_BASE;
976 ASSERT (Index < mDriverHealthManagerHealthInfoCount);
977 //
978 // Process the driver's healthy status for the specify module
979 //
980 DriverHealthManagerProcessSingleControllerHealth (
981 mDriverHealthManagerHealthInfo[Index].DriverHealth,
982 mDriverHealthManagerHealthInfo[Index].ControllerHandle,
983 mDriverHealthManagerHealthInfo[Index].ChildHandle,
984 mDriverHealthManagerHealthInfo[Index].HealthStatus,
985 &(mDriverHealthManagerHealthInfo[Index].MessageList),
986 mDriverHealthManagerHealthInfo[Index].HiiHandle
987 );
988
989 DriverHealthManagerUpdateForm ((BOOLEAN)(QuestionId == QUESTION_ID_REFRESH_CONFIGURE));
990
991 return EFI_SUCCESS;
992}
Note: See TracBrowser for help on using the repository browser.

© 2025 Oracle Support Privacy / Do Not Sell My Info Terms of Use Trademark Policy Automated Access Etiquette