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