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