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