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