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