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