]> git.proxmox.com Git - mirror_edk2.git/blame - IntelFrameworkModulePkg/Universal/BdsDxe/DeviceMngr/DeviceManager.c
> When GetHealthStatus() returns NULL FormHiiHandle, DeviceManager shouldn't call...
[mirror_edk2.git] / IntelFrameworkModulePkg / Universal / BdsDxe / DeviceMngr / DeviceManager.c
CommitLineData
5c08e117 1/** @file\r
2 The platform device manager reference implementation\r
3\r
2fde83b1 4Copyright (c) 2004 - 2011, Intel Corporation. All rights reserved.<BR>\r
180a5a35 5This program and the accompanying materials\r
5c08e117 6are licensed and made available under the terms and conditions of the BSD License\r
7which accompanies this distribution. The full text of the license may be found at\r
8http://opensource.org/licenses/bsd-license.php\r
9\r
10THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
11WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
12\r
13**/\r
14\r
15#include "DeviceManager.h"\r
16\r
17DEVICE_MANAGER_CALLBACK_DATA gDeviceManagerPrivate = {\r
18 DEVICE_MANAGER_CALLBACK_DATA_SIGNATURE,\r
19 NULL,\r
20 NULL,\r
ab4da126 21 NULL,\r
22 NULL,\r
5c08e117 23 {\r
24 FakeExtractConfig,\r
25 FakeRouteConfig,\r
26 DeviceManagerCallback\r
ab4da126 27 },\r
28 {\r
29 FakeExtractConfig,\r
30 FakeRouteConfig,\r
31 DriverHealthCallback\r
5c08e117 32 }\r
33};\r
34\r
3c4b1122
ED
35#define MAX_MAC_ADDRESS_NODE_LIST_LEN 10\r
36\r
5c08e117 37EFI_GUID mDeviceManagerGuid = DEVICE_MANAGER_FORMSET_GUID;\r
ab4da126 38EFI_GUID mDriverHealthGuid = DRIVER_HEALTH_FORMSET_GUID;\r
5c08e117 39\r
3c4b1122
ED
40//\r
41// Which Mac Address string is select\r
42// it will decide what menu need to show in the NETWORK_DEVICE_FORM_ID form.\r
43//\r
44EFI_STRING mSelectedMacAddrString;\r
45\r
46//\r
47// Which form Id need to be show.\r
48//\r
49EFI_FORM_ID mNextShowFormId = DEVICE_MANAGER_FORM_ID; \r
50\r
51//\r
52// The Mac Address show in the NETWORK_DEVICE_LIST_FORM_ID\r
53//\r
54MAC_ADDRESS_NODE_LIST mMacDeviceList;\r
55\r
5c08e117 56DEVICE_MANAGER_MENU_ITEM mDeviceManagerMenuItemTable[] = {\r
57 { STRING_TOKEN (STR_DISK_DEVICE), EFI_DISK_DEVICE_CLASS },\r
58 { STRING_TOKEN (STR_VIDEO_DEVICE), EFI_VIDEO_DEVICE_CLASS },\r
59 { STRING_TOKEN (STR_NETWORK_DEVICE), EFI_NETWORK_DEVICE_CLASS },\r
60 { STRING_TOKEN (STR_INPUT_DEVICE), EFI_INPUT_DEVICE_CLASS },\r
61 { STRING_TOKEN (STR_ON_BOARD_DEVICE), EFI_ON_BOARD_DEVICE_CLASS },\r
62 { STRING_TOKEN (STR_OTHER_DEVICE), EFI_OTHER_DEVICE_CLASS }\r
63};\r
64\r
f6f910dd 65HII_VENDOR_DEVICE_PATH mDeviceManagerHiiVendorDevicePath = {\r
66 {\r
67 {\r
68 HARDWARE_DEVICE_PATH,\r
69 HW_VENDOR_DP,\r
70 {\r
71 (UINT8) (sizeof (VENDOR_DEVICE_PATH)),\r
72 (UINT8) ((sizeof (VENDOR_DEVICE_PATH)) >> 8)\r
73 }\r
74 },\r
75 //\r
76 // {102579A0-3686-466e-ACD8-80C087044F4A}\r
77 //\r
78 { 0x102579a0, 0x3686, 0x466e, { 0xac, 0xd8, 0x80, 0xc0, 0x87, 0x4, 0x4f, 0x4a } }\r
79 },\r
80 {\r
81 END_DEVICE_PATH_TYPE,\r
82 END_ENTIRE_DEVICE_PATH_SUBTYPE,\r
83 { \r
84 (UINT8) (END_DEVICE_PATH_LENGTH),\r
85 (UINT8) ((END_DEVICE_PATH_LENGTH) >> 8)\r
86 }\r
87 }\r
88};\r
89\r
61910435
LG
90HII_VENDOR_DEVICE_PATH mDriverHealthHiiVendorDevicePath = {\r
91 {\r
92 {\r
93 HARDWARE_DEVICE_PATH,\r
94 HW_VENDOR_DP,\r
95 {\r
96 (UINT8) (sizeof (VENDOR_DEVICE_PATH)),\r
97 (UINT8) ((sizeof (VENDOR_DEVICE_PATH)) >> 8)\r
98 }\r
99 },\r
100 //\r
101 // {D8F76651-1675-4986-BED4-3824B2F1F4C8}\r
102 //\r
103 { 0xd8f76651, 0x1675, 0x4986, { 0xbe, 0xd4, 0x38, 0x24, 0xb2, 0xf1, 0xf4, 0xc8 } }\r
104 },\r
105 {\r
106 END_DEVICE_PATH_TYPE,\r
107 END_ENTIRE_DEVICE_PATH_SUBTYPE,\r
108 { \r
109 (UINT8) (END_DEVICE_PATH_LENGTH),\r
110 (UINT8) ((END_DEVICE_PATH_LENGTH) >> 8)\r
111 }\r
112 }\r
113};\r
114\r
5c08e117 115/**\r
ab4da126 116 This function is invoked if user selected a interactive opcode from Device Manager's\r
5c08e117 117 Formset. The decision by user is saved to gCallbackKey for later processing. If\r
118 user set VBIOS, the new value is saved to EFI variable.\r
119\r
120 @param This Points to the EFI_HII_CONFIG_ACCESS_PROTOCOL.\r
121 @param Action Specifies the type of action taken by the browser.\r
122 @param QuestionId A unique value which is sent to the original exporting driver\r
123 so that it can identify the type of data to expect.\r
124 @param Type The type of value for the question.\r
125 @param Value A pointer to the data being sent to the original exporting driver.\r
126 @param ActionRequest On return, points to the action requested by the callback function.\r
127\r
128 @retval EFI_SUCCESS The callback successfully handled the action.\r
129 @retval EFI_INVALID_PARAMETER The setup browser call this function with invalid parameters.\r
130\r
131**/\r
132EFI_STATUS\r
133EFIAPI\r
134DeviceManagerCallback (\r
135 IN CONST EFI_HII_CONFIG_ACCESS_PROTOCOL *This,\r
136 IN EFI_BROWSER_ACTION Action,\r
137 IN EFI_QUESTION_ID QuestionId,\r
138 IN UINT8 Type,\r
139 IN EFI_IFR_TYPE_VALUE *Value,\r
140 OUT EFI_BROWSER_ACTION_REQUEST *ActionRequest\r
141 )\r
142{\r
3c4b1122
ED
143 UINTN CurIndex;\r
144 \r
4548fc2a
LG
145 if ((Action == EFI_BROWSER_ACTION_FORM_OPEN) || (Action == EFI_BROWSER_ACTION_FORM_CLOSE)) {\r
146 //\r
147 // Do nothing for UEFI OPEN/CLOSE Action\r
148 //\r
149 return EFI_SUCCESS;\r
150 }\r
151\r
5c08e117 152 if ((Value == NULL) || (ActionRequest == NULL)) {\r
153 return EFI_INVALID_PARAMETER;\r
154 }\r
155\r
6aa22a17 156 gCallbackKey = QuestionId;\r
5c08e117 157\r
3c4b1122
ED
158 if ((QuestionId < MAX_KEY_SECTION_LEN + NETWORK_DEVICE_LIST_KEY_OFFSET) && (QuestionId >= NETWORK_DEVICE_LIST_KEY_OFFSET)) {\r
159 //\r
160 // If user select the mac address, need to record mac address string to support next form show.\r
161 //\r
162 for (CurIndex = 0; CurIndex < mMacDeviceList.CurListLen; CurIndex ++) {\r
163 if (mMacDeviceList.NodeList[CurIndex].QuestionId == QuestionId) {\r
164 mSelectedMacAddrString = HiiGetString (gDeviceManagerPrivate.HiiHandle, mMacDeviceList.NodeList[CurIndex].PromptId, NULL);\r
165 }\r
166 }\r
167 }\r
168 \r
6aa22a17 169 //\r
170 // Request to exit SendForm(), so as to switch to selected form\r
171 //\r
172 *ActionRequest = EFI_BROWSER_ACTION_REQUEST_EXIT;\r
5c08e117 173\r
5c08e117 174 return EFI_SUCCESS;\r
175}\r
176\r
177/**\r
178\r
179 This function registers HII packages to HII database.\r
180\r
cb7d01c0 181 @retval EFI_SUCCESS HII packages for the Device Manager were registered successfully.\r
182 @retval EFI_OUT_OF_RESOURCES HII packages for the Device Manager failed to be registered.\r
5c08e117 183\r
184**/\r
185EFI_STATUS\r
186InitializeDeviceManager (\r
187 VOID\r
188 )\r
189{\r
190 EFI_STATUS Status;\r
5c08e117 191\r
192 //\r
f6f910dd 193 // Install Device Path Protocol and Config Access protocol to driver handle\r
5c08e117 194 //\r
f6f910dd 195 Status = gBS->InstallMultipleProtocolInterfaces (\r
5c08e117 196 &gDeviceManagerPrivate.DriverHandle,\r
f6f910dd 197 &gEfiDevicePathProtocolGuid,\r
198 &mDeviceManagerHiiVendorDevicePath,\r
5c08e117 199 &gEfiHiiConfigAccessProtocolGuid,\r
f6f910dd 200 &gDeviceManagerPrivate.ConfigAccess,\r
201 NULL\r
5c08e117 202 );\r
203 ASSERT_EFI_ERROR (Status);\r
204\r
ab4da126 205 Status = gBS->InstallMultipleProtocolInterfaces (\r
206 &gDeviceManagerPrivate.DriverHealthHandle,\r
61910435
LG
207 &gEfiDevicePathProtocolGuid,\r
208 &mDriverHealthHiiVendorDevicePath,\r
ab4da126 209 &gEfiHiiConfigAccessProtocolGuid,\r
210 &gDeviceManagerPrivate.DriverHealthConfigAccess,\r
211 NULL\r
212 );\r
213 ASSERT_EFI_ERROR (Status);\r
214\r
3c4b1122
ED
215 mMacDeviceList.CurListLen = 0;\r
216 mMacDeviceList.MaxListLen = 0;\r
217\r
5c08e117 218 return Status;\r
219}\r
220\r
75bf9d0e
LG
221/**\r
222 Extract the displayed formset for given HII handle and class guid.\r
223\r
224 @param Handle The HII handle.\r
225 @param SetupClassGuid The class guid specifies which form set will be displayed.\r
226 @param FormSetTitle Formset title string.\r
227 @param FormSetHelp Formset help string.\r
228\r
229 @retval TRUE The formset for given HII handle will be displayed.\r
230 @return FALSE The formset for given HII handle will not be displayed.\r
231\r
232**/\r
233BOOLEAN\r
234ExtractDisplayedHiiFormFromHiiHandle (\r
235 IN EFI_HII_HANDLE Handle,\r
236 IN EFI_GUID *SetupClassGuid,\r
237 OUT EFI_STRING_ID *FormSetTitle,\r
238 OUT EFI_STRING_ID *FormSetHelp\r
239 )\r
240{\r
241 EFI_STATUS Status;\r
242 UINTN BufferSize;\r
243 EFI_HII_PACKAGE_LIST_HEADER *HiiPackageList;\r
244 UINT8 *Package;\r
245 UINT8 *OpCodeData;\r
246 UINT32 Offset;\r
247 UINT32 Offset2;\r
248 UINT32 PackageListLength;\r
249 EFI_HII_PACKAGE_HEADER PackageHeader;\r
250 EFI_GUID *ClassGuid;\r
251 UINT8 ClassGuidNum;\r
252\r
253 ASSERT (Handle != NULL);\r
254 ASSERT (SetupClassGuid != NULL); \r
255 ASSERT (FormSetTitle != NULL);\r
256 ASSERT (FormSetHelp != NULL);\r
257\r
258 *FormSetTitle = 0;\r
259 *FormSetHelp = 0;\r
260 ClassGuidNum = 0;\r
261 ClassGuid = NULL;\r
262\r
263 //\r
264 // Get HII PackageList\r
265 //\r
266 BufferSize = 0;\r
267 HiiPackageList = NULL;\r
268 Status = gHiiDatabase->ExportPackageLists (gHiiDatabase, Handle, &BufferSize, HiiPackageList);\r
269 //\r
270 // Handle is a invalid handle. Check if Handle is corrupted.\r
271 //\r
272 ASSERT (Status != EFI_NOT_FOUND);\r
273 //\r
274 // The return status should always be EFI_BUFFER_TOO_SMALL as input buffer's size is 0.\r
275 //\r
276 ASSERT (Status == EFI_BUFFER_TOO_SMALL);\r
277 \r
278 HiiPackageList = AllocatePool (BufferSize);\r
279 ASSERT (HiiPackageList != NULL);\r
280\r
281 Status = gHiiDatabase->ExportPackageLists (gHiiDatabase, Handle, &BufferSize, HiiPackageList);\r
282 if (EFI_ERROR (Status)) {\r
283 return FALSE;\r
284 }\r
285\r
286 //\r
287 // Get Form package from this HII package List\r
288 //\r
289 Offset = sizeof (EFI_HII_PACKAGE_LIST_HEADER);\r
290 Offset2 = 0;\r
291 PackageListLength = ReadUnaligned32 (&HiiPackageList->PackageLength);\r
292\r
293 while (Offset < PackageListLength) {\r
294 Package = ((UINT8 *) HiiPackageList) + Offset;\r
295 CopyMem (&PackageHeader, Package, sizeof (EFI_HII_PACKAGE_HEADER));\r
296\r
297 if (PackageHeader.Type == EFI_HII_PACKAGE_FORMS) {\r
298 //\r
299 // Search FormSet Opcode in this Form Package\r
300 //\r
301 Offset2 = sizeof (EFI_HII_PACKAGE_HEADER);\r
302 while (Offset2 < PackageHeader.Length) {\r
303 OpCodeData = Package + Offset2;\r
304\r
305 if (((EFI_IFR_OP_HEADER *) OpCodeData)->OpCode == EFI_IFR_FORM_SET_OP) {\r
158bb28a
LG
306 if (((EFI_IFR_OP_HEADER *) OpCodeData)->Length > OFFSET_OF (EFI_IFR_FORM_SET, Flags)) {\r
307 //\r
308 // Find FormSet OpCode\r
309 //\r
5e24f37a 310 ClassGuidNum = (UINT8) (((EFI_IFR_FORM_SET *) OpCodeData)->Flags & 0x3);\r
158bb28a
LG
311 ClassGuid = (EFI_GUID *) (VOID *)(OpCodeData + sizeof (EFI_IFR_FORM_SET));\r
312 while (ClassGuidNum-- > 0) {\r
313 if (CompareGuid (SetupClassGuid, ClassGuid)) {\r
314 CopyMem (FormSetTitle, &((EFI_IFR_FORM_SET *) OpCodeData)->FormSetTitle, sizeof (EFI_STRING_ID));\r
315 CopyMem (FormSetHelp, &((EFI_IFR_FORM_SET *) OpCodeData)->Help, sizeof (EFI_STRING_ID));\r
316 FreePool (HiiPackageList);\r
317 return TRUE;\r
318 }\r
32e9da0c 319 ClassGuid ++;\r
75bf9d0e 320 }\r
158bb28a
LG
321 } else {\r
322 CopyMem (FormSetTitle, &((EFI_IFR_FORM_SET *) OpCodeData)->FormSetTitle, sizeof (EFI_STRING_ID));\r
323 CopyMem (FormSetHelp, &((EFI_IFR_FORM_SET *) OpCodeData)->Help, sizeof (EFI_STRING_ID));\r
324 FreePool (HiiPackageList);\r
325 return TRUE;\r
75bf9d0e
LG
326 }\r
327 }\r
328 \r
329 //\r
330 // Go to next opcode\r
331 //\r
332 Offset2 += ((EFI_IFR_OP_HEADER *) OpCodeData)->Length;\r
333 }\r
334 }\r
335 \r
336 //\r
337 // Go to next package\r
338 //\r
339 Offset += PackageHeader.Length;\r
340 }\r
341\r
342 FreePool (HiiPackageList);\r
343\r
344 return FALSE;\r
345}\r
346\r
3c4b1122
ED
347/**\r
348 Get the mac address string from the device path.\r
349 if the device path has the vlan, get the vanid also.\r
350 \r
351 @param MacAddressNode Device path begin with mac address \r
352 @param PBuffer Output string buffer contain mac address.\r
353\r
354**/\r
355BOOLEAN \r
356GetMacAddressString(\r
357 IN MAC_ADDR_DEVICE_PATH *MacAddressNode,\r
358 OUT CHAR16 **PBuffer\r
359 )\r
360{\r
361 UINTN HwAddressSize;\r
362 UINTN Index;\r
363 UINT8 *HwAddress;\r
364 EFI_DEVICE_PATH_PROTOCOL *Node;\r
365 UINT16 VlanId;\r
366 CHAR16 *String;\r
367 UINTN BufferLen;\r
368\r
369 VlanId = 0;\r
370 String = NULL;\r
371 ASSERT(MacAddressNode != NULL);\r
372\r
373 HwAddressSize = sizeof (EFI_MAC_ADDRESS);\r
374 if (MacAddressNode->IfType == 0x01 || MacAddressNode->IfType == 0x00) {\r
375 HwAddressSize = 6;\r
376 }\r
377\r
378 //\r
379 // The output format is MAC:XX:XX:XX:...\XXXX\r
380 // The size is the Number size + ":" size + Vlan size(\XXXX) + End\r
381 //\r
382 BufferLen = (4 + 2 * HwAddressSize + (HwAddressSize - 1) + 5 + 1) * sizeof (CHAR16);\r
383 String = AllocateZeroPool (BufferLen);\r
384 if (String == NULL) {\r
385 return FALSE;\r
386 }\r
387\r
388 *PBuffer = String;\r
389 StrCpy(String, L"MAC:");\r
390 String += 4;\r
391 \r
392 //\r
393 // Convert the MAC address into a unicode string.\r
394 //\r
395 HwAddress = &MacAddressNode->MacAddress.Addr[0];\r
396 for (Index = 0; Index < HwAddressSize; Index++) {\r
397 String += UnicodeValueToString (String, PREFIX_ZERO | RADIX_HEX, *(HwAddress++), 2);\r
398 if (Index < HwAddressSize - 1) {\r
399 *String++ = L':';\r
400 }\r
401 }\r
402 \r
403 //\r
404 // If VLAN is configured, it will need extra 5 characters like "\0005".\r
405 // Plus one unicode character for the null-terminator.\r
406 //\r
407 Node = (EFI_DEVICE_PATH_PROTOCOL *)MacAddressNode;\r
408 while (!IsDevicePathEnd (Node)) {\r
409 if (Node->Type == MESSAGING_DEVICE_PATH && Node->SubType == MSG_VLAN_DP) {\r
410 VlanId = ((VLAN_DEVICE_PATH *) Node)->VlanId;\r
411 }\r
412 Node = NextDevicePathNode (Node);\r
413 }\r
414\r
415 if (VlanId != 0) {\r
416 *String++ = L'\\';\r
417 String += UnicodeValueToString (String, PREFIX_ZERO | RADIX_HEX, VlanId, 4);\r
418 }\r
419\r
420 //\r
421 // Null terminate the Unicode string\r
422 //\r
423 *String = L'\0';\r
424\r
425 return TRUE;\r
426}\r
427\r
428/**\r
429 Save question id and prompt id to the mac device list.\r
430 If the same mac address has saved yet, no need to add more.\r
431\r
3c4b1122
ED
432 @param MacAddrString Mac address string.\r
433\r
434 @retval EFI_SUCCESS Add the item is successful.\r
435 @return Other values if failed to Add the item.\r
436**/\r
437BOOLEAN \r
438AddIdToMacDeviceList (\r
439 IN EFI_STRING MacAddrString\r
440 )\r
441{\r
442 MENU_INFO_ITEM *TempDeviceList;\r
443 UINTN Index;\r
444 EFI_STRING StoredString;\r
445 EFI_STRING_ID PromptId;\r
446 EFI_HII_HANDLE HiiHandle;\r
447\r
448 HiiHandle = gDeviceManagerPrivate.HiiHandle;\r
449 TempDeviceList = NULL;\r
450\r
451 for (Index = 0; Index < mMacDeviceList.CurListLen; Index ++) {\r
452 StoredString = HiiGetString (HiiHandle, mMacDeviceList.NodeList[Index].PromptId, NULL);\r
453 if (StoredString == NULL) {\r
454 return FALSE;\r
455 }\r
456\r
457 //\r
458 // Already has save the same mac address to the list.\r
459 //\r
460 if (StrCmp (MacAddrString, StoredString) == 0) {\r
461 return FALSE;\r
462 }\r
463 }\r
464\r
465 PromptId = HiiSetString(HiiHandle, 0, MacAddrString, NULL);\r
466 //\r
467 // If not in the list, save it.\r
468 //\r
469 if (mMacDeviceList.MaxListLen > mMacDeviceList.CurListLen + 1) {\r
470 mMacDeviceList.NodeList[mMacDeviceList.CurListLen].PromptId = PromptId;\r
471 mMacDeviceList.NodeList[mMacDeviceList.CurListLen].QuestionId = (EFI_QUESTION_ID) (mMacDeviceList.CurListLen + NETWORK_DEVICE_LIST_KEY_OFFSET);\r
472 } else {\r
473 mMacDeviceList.MaxListLen += MAX_MAC_ADDRESS_NODE_LIST_LEN;\r
474 if (mMacDeviceList.CurListLen != 0) {\r
475 TempDeviceList = (MENU_INFO_ITEM *)AllocateCopyPool (sizeof (MENU_INFO_ITEM) * mMacDeviceList.MaxListLen, (VOID *)mMacDeviceList.NodeList);\r
476 } else {\r
477 TempDeviceList = (MENU_INFO_ITEM *)AllocatePool (sizeof (MENU_INFO_ITEM) * mMacDeviceList.MaxListLen);\r
478 }\r
479 \r
480 if (TempDeviceList == NULL) {\r
481 return FALSE;\r
482 }\r
483 TempDeviceList[mMacDeviceList.CurListLen].PromptId = PromptId; \r
484 TempDeviceList[mMacDeviceList.CurListLen].QuestionId = (EFI_QUESTION_ID) (mMacDeviceList.CurListLen + NETWORK_DEVICE_LIST_KEY_OFFSET);\r
485 \r
486 if (mMacDeviceList.CurListLen > 0) {\r
487 FreePool(mMacDeviceList.NodeList);\r
488 }\r
489 \r
490 mMacDeviceList.NodeList = TempDeviceList;\r
491 }\r
492 mMacDeviceList.CurListLen ++;\r
493\r
494 return TRUE;\r
495}\r
496\r
497/**\r
498 Check the devcie path, try to find whether it has mac address path.\r
499\r
500 In this function, first need to check whether this path has mac address path.\r
501 second, when the mac address device path has find, also need to deicide whether\r
502 need to add this mac address relate info to the menu.\r
503\r
504 @param *Node Input device which need to be check.\r
505 @param *NeedAddItem Whether need to add the menu in the network device list.\r
506 \r
507 @retval TRUE Has mac address device path.\r
508 @retval FALSE NOT Has mac address device path. \r
509\r
510**/\r
511BOOLEAN\r
512IsMacAddressDevicePath (\r
513 IN VOID *Node,\r
514 OUT BOOLEAN *NeedAddItem\r
515 )\r
516{\r
517 EFI_DEVICE_PATH_PROTOCOL *DevicePath;\r
518 CHAR16 *Buffer;\r
519 BOOLEAN ReturnVal;\r
520 \r
521 ASSERT (Node != NULL);\r
522 *NeedAddItem = FALSE;\r
523 ReturnVal = FALSE;\r
524 Buffer = NULL;\r
525\r
526 DevicePath = (EFI_DEVICE_PATH_PROTOCOL *) Node;\r
527\r
528 //\r
529 // find the partition device path node\r
530 //\r
531 while (!IsDevicePathEnd (DevicePath)) {\r
532 if ((DevicePathType (DevicePath) == MESSAGING_DEVICE_PATH) &&\r
533 (DevicePathSubType (DevicePath) == MSG_MAC_ADDR_DP)) {\r
534 ReturnVal = TRUE;\r
535 \r
536 if (DEVICE_MANAGER_FORM_ID == mNextShowFormId) {\r
537 *NeedAddItem = TRUE;\r
538 break;\r
539 } \r
540 \r
541 if (!GetMacAddressString((MAC_ADDR_DEVICE_PATH*)DevicePath, &Buffer)) {\r
542 break;\r
543 }\r
544\r
545 if (NETWORK_DEVICE_FORM_ID == mNextShowFormId) {\r
546 if (StrCmp (Buffer, mSelectedMacAddrString) == 0) {\r
547 *NeedAddItem = TRUE;\r
548 }\r
549 break;\r
550 }\r
551\r
552 if (NETWORK_DEVICE_LIST_FORM_ID == mNextShowFormId) {\r
553 //\r
554 // Same handle may has two network child handle, so the questionid \r
555 // has the offset of SAME_HANDLE_KEY_OFFSET.\r
556 //\r
557 if (AddIdToMacDeviceList (Buffer)) {\r
558 *NeedAddItem = TRUE;\r
559 }\r
560 break;\r
561 }\r
562 } \r
563 DevicePath = NextDevicePathNode (DevicePath);\r
564 }\r
565\r
566 if (Buffer != NULL) {\r
567 FreePool (Buffer);\r
568 }\r
569\r
570 return ReturnVal;\r
571}\r
572\r
573/**\r
574 Check to see if the device path is for the network device.\r
575\r
576 @param Handle The HII handle which include the mac address device path.\r
577 @param ItemCount The new add Mac address item count.\r
578\r
579 @retval TRUE Need to add new item in the menu.\r
580 @return FALSE Do not need to add the menu about the network.\r
581\r
582**/\r
583BOOLEAN \r
584IsNeedAddNetworkMenu (\r
585 IN EFI_HII_HANDLE Handle,\r
586 OUT UINTN *ItemCount\r
587 )\r
588{\r
589 EFI_STATUS Status;\r
590 UINTN EntryCount;\r
591 UINTN Index; \r
592 EFI_HII_HANDLE HiiDeviceManagerHandle;\r
593 EFI_HANDLE DriverHandle;\r
594 EFI_HANDLE ControllerHandle;\r
595 EFI_DEVICE_PATH_PROTOCOL *DevicePath;\r
596 EFI_DEVICE_PATH_PROTOCOL *TmpDevicePath;\r
597 EFI_DEVICE_PATH_PROTOCOL *ChildDevicePath;\r
598 EFI_OPEN_PROTOCOL_INFORMATION_ENTRY *OpenInfoBuffer;\r
599 BOOLEAN IsNeedAdd;\r
600\r
601 HiiDeviceManagerHandle = gDeviceManagerPrivate.HiiHandle;\r
602 IsNeedAdd = FALSE;\r
603 OpenInfoBuffer = NULL;\r
604 if ((Handle == NULL) || (ItemCount == NULL)) {\r
605 return FALSE;\r
606 }\r
607 *ItemCount = 0;\r
608\r
609 Status = gHiiDatabase->GetPackageListHandle (gHiiDatabase, Handle, &DriverHandle);\r
610 if (EFI_ERROR (Status)) {\r
611 return FALSE;\r
612 }\r
613 //\r
614 // Get the device path by the got Driver handle .\r
615 //\r
616 Status = gBS->HandleProtocol (DriverHandle, &gEfiDevicePathProtocolGuid, (VOID **) &DevicePath);\r
617 if (EFI_ERROR (Status)) {\r
618 return FALSE;\r
619 }\r
620 TmpDevicePath = DevicePath;\r
621\r
622 // \r
623 // Check whether this device path include mac address device path.\r
624 // If this path has mac address path, get the value whether need \r
625 // add this info to the menu and return.\r
626 // Else check more about the child handle devcie path.\r
627 //\r
628 if (IsMacAddressDevicePath(TmpDevicePath, &IsNeedAdd)) {\r
629 if ((NETWORK_DEVICE_LIST_FORM_ID == mNextShowFormId) && IsNeedAdd) {\r
630 (*ItemCount) = 1;\r
631 }\r
632 return IsNeedAdd;\r
633 }\r
634\r
635 //\r
636 // Search whether this path is the controller path, not he child handle path.\r
637 // And the child handle has the network devcie connected.\r
638 //\r
639 TmpDevicePath = DevicePath;\r
640 Status = gBS->LocateDevicePath(&gEfiDevicePathProtocolGuid, &TmpDevicePath, &ControllerHandle);\r
641 if (EFI_ERROR (Status)) {\r
642 return FALSE;\r
643 }\r
644\r
645 if (!IsDevicePathEnd (TmpDevicePath)) {\r
646 return FALSE; \r
647 }\r
648\r
649 //\r
650 // Retrieve the list of agents that are consuming the specific protocol\r
651 // on ControllerHandle.\r
652 // The buffer point by OpenInfoBuffer need be free at this function.\r
653 //\r
654 Status = gBS->OpenProtocolInformation (\r
655 ControllerHandle,\r
656 &gEfiPciIoProtocolGuid,\r
657 &OpenInfoBuffer,\r
658 &EntryCount\r
659 );\r
660 if (EFI_ERROR (Status)) {\r
661 return FALSE;\r
662 }\r
663\r
664 //\r
665 // Inspect if ChildHandle is one of the agents.\r
666 //\r
667 Status = EFI_UNSUPPORTED;\r
668 for (Index = 0; Index < EntryCount; Index++) {\r
669 //\r
670 // Query all the children created by the controller handle's driver\r
671 //\r
672 if ((OpenInfoBuffer[Index].Attributes & EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER) != 0) {\r
673 Status = gBS->OpenProtocol (\r
674 OpenInfoBuffer[Index].ControllerHandle,\r
675 &gEfiDevicePathProtocolGuid,\r
676 (VOID **) &ChildDevicePath,\r
677 NULL,\r
678 NULL,\r
679 EFI_OPEN_PROTOCOL_GET_PROTOCOL\r
680 );\r
681 if (EFI_ERROR (Status)) {\r
682 continue;\r
683 }\r
684\r
685 // \r
686 // Check whether this device path include mac address device path.\r
687 //\r
688 if (!IsMacAddressDevicePath(ChildDevicePath, &IsNeedAdd)) {\r
689 //\r
690 // If this path not has mac address path, check the other.\r
691 //\r
692 continue;\r
693 } else {\r
694 //\r
695 // If need to update the NETWORK_DEVICE_LIST_FORM, try to get more.\r
696 //\r
697 if ((NETWORK_DEVICE_LIST_FORM_ID == mNextShowFormId)) {\r
698 if (IsNeedAdd) {\r
699 (*ItemCount) += 1;\r
700 }\r
701 continue;\r
702 } else {\r
703 //\r
704 // If need to update other form, return whether need to add to the menu.\r
705 // \r
706 goto Done;\r
707 }\r
708 }\r
709 }\r
710 }\r
711\r
712Done:\r
713 if (OpenInfoBuffer != NULL) {\r
714 FreePool (OpenInfoBuffer); \r
715 }\r
716 return IsNeedAdd; \r
717}\r
718\r
5c08e117 719/**\r
720 Call the browser and display the device manager to allow user\r
721 to configure the platform.\r
722\r
723 This function create the dynamic content for device manager. It includes\r
724 section header for all class of devices, one-of opcode to set VBIOS.\r
725 \r
726 @retval EFI_SUCCESS Operation is successful.\r
727 @return Other values if failed to clean up the dynamic content from HII\r
728 database.\r
729\r
730**/\r
731EFI_STATUS\r
732CallDeviceManager (\r
733 VOID\r
734 )\r
735{\r
736 EFI_STATUS Status;\r
5c08e117 737 UINTN Index;\r
cb7d01c0 738 EFI_STRING String;\r
5c08e117 739 EFI_STRING_ID Token;\r
740 EFI_STRING_ID TokenHelp;\r
5c08e117 741 EFI_HII_HANDLE *HiiHandles;\r
5c08e117 742 EFI_HII_HANDLE HiiHandle;\r
5c08e117 743 EFI_STRING_ID FormSetTitle;\r
744 EFI_STRING_ID FormSetHelp;\r
745 EFI_BROWSER_ACTION_REQUEST ActionRequest;\r
75bf9d0e
LG
746 VOID *StartOpCodeHandle;\r
747 VOID *EndOpCodeHandle;\r
748 EFI_IFR_GUID_LABEL *StartLabel;\r
749 EFI_IFR_GUID_LABEL *EndLabel;\r
ab4da126 750 UINTN NumHandles;\r
751 EFI_HANDLE *DriverHealthHandles;\r
3c4b1122
ED
752 BOOLEAN AddNetworkMenu;\r
753 UINTN AddItemCount;\r
754 UINTN NewStringLen;\r
755 EFI_STRING NewStringTitle;\r
5c08e117 756\r
75bf9d0e 757 HiiHandles = NULL;\r
5c08e117 758 Status = EFI_SUCCESS;\r
759 gCallbackKey = 0;\r
ab4da126 760 NumHandles = 0;\r
761 DriverHealthHandles = NULL;\r
3c4b1122
ED
762 AddNetworkMenu = FALSE;\r
763 AddItemCount = 0;\r
5c08e117 764\r
765 //\r
766 // Connect all prior to entering the platform setup menu.\r
767 //\r
768 if (!gConnectAllHappened) {\r
769 BdsLibConnectAllDriversToAllControllers ();\r
770 gConnectAllHappened = TRUE;\r
771 }\r
7119d96a 772\r
773 HiiHandle = gDeviceManagerPrivate.HiiHandle;\r
774 if (HiiHandle == NULL) {\r
775 //\r
776 // Publish our HII data.\r
777 //\r
778 HiiHandle = HiiAddPackages (\r
779 &mDeviceManagerGuid,\r
780 gDeviceManagerPrivate.DriverHandle,\r
781 DeviceManagerVfrBin,\r
782 BdsDxeStrings,\r
783 NULL\r
784 );\r
785 if (HiiHandle == NULL) {\r
786 return EFI_OUT_OF_RESOURCES;\r
787 }\r
788\r
789 gDeviceManagerPrivate.HiiHandle = HiiHandle;\r
790 }\r
791\r
5c08e117 792 //\r
3c4b1122
ED
793 // If need show the Network device list form, clear the old save list first.\r
794 //\r
795 if ((mNextShowFormId == NETWORK_DEVICE_LIST_FORM_ID) && (mMacDeviceList.CurListLen > 0)) {\r
796 mMacDeviceList.CurListLen = 0;\r
797 }\r
798\r
5c08e117 799 //\r
3c4b1122
ED
800 // Update the network device form titile.\r
801 //\r
802 if (mNextShowFormId == NETWORK_DEVICE_FORM_ID) {\r
803 String = HiiGetString (HiiHandle, STRING_TOKEN (STR_FORM_NETWORK_DEVICE_TITLE), NULL);\r
d0460875 804 NewStringLen = StrLen(mSelectedMacAddrString) * 2;\r
d3b4af2b 805 NewStringLen += (StrLen(String) + 2) * 2;\r
3c4b1122
ED
806 NewStringTitle = AllocatePool (NewStringLen);\r
807 UnicodeSPrint (NewStringTitle, NewStringLen, L"%s %s", String, mSelectedMacAddrString);\r
808 HiiSetString (HiiHandle, STRING_TOKEN (STR_FORM_NETWORK_DEVICE_TITLE), NewStringTitle, NULL); \r
809 FreePool (String);\r
810 FreePool (NewStringTitle);\r
811 }\r
812\r
75bf9d0e
LG
813 //\r
814 // Allocate space for creation of UpdateData Buffer\r
815 //\r
816 StartOpCodeHandle = HiiAllocateOpCodeHandle ();\r
817 ASSERT (StartOpCodeHandle != NULL);\r
5c08e117 818\r
75bf9d0e
LG
819 EndOpCodeHandle = HiiAllocateOpCodeHandle ();\r
820 ASSERT (EndOpCodeHandle != NULL);\r
821\r
822 //\r
823 // Create Hii Extend Label OpCode as the start opcode\r
824 //\r
825 StartLabel = (EFI_IFR_GUID_LABEL *) HiiCreateGuidOpCode (StartOpCodeHandle, &gEfiIfrTianoGuid, NULL, sizeof (EFI_IFR_GUID_LABEL));\r
826 StartLabel->ExtendOpCode = EFI_IFR_EXTEND_OP_LABEL;\r
3c4b1122
ED
827 //\r
828 // According to the next show Form id(mNextShowFormId) to decide which form need to update.\r
829 //\r
d3b4af2b 830 StartLabel->Number = (UINT16) (LABEL_FORM_ID_OFFSET + mNextShowFormId);\r
75bf9d0e
LG
831\r
832 //\r
833 // Create Hii Extend Label OpCode as the end opcode\r
834 //\r
835 EndLabel = (EFI_IFR_GUID_LABEL *) HiiCreateGuidOpCode (EndOpCodeHandle, &gEfiIfrTianoGuid, NULL, sizeof (EFI_IFR_GUID_LABEL));\r
836 EndLabel->ExtendOpCode = EFI_IFR_EXTEND_OP_LABEL;\r
837 EndLabel->Number = LABEL_END;\r
838\r
5c08e117 839 //\r
840 // Get all the Hii handles\r
841 //\r
cb7d01c0 842 HiiHandles = HiiGetHiiHandles (NULL);\r
843 ASSERT (HiiHandles != NULL);\r
5c08e117 844\r
5c08e117 845 //\r
846 // Search for formset of each class type\r
847 //\r
cb7d01c0 848 for (Index = 0; HiiHandles[Index] != NULL; Index++) {\r
3c4b1122
ED
849 //\r
850 // The QuestionId in the form which will call the driver form has this asssumption.\r
851 // QuestionId = Handle Index + NETWORK_DEVICE_LIST_KEY_OFFSET;\r
852 // Different QuestionId at least has the section of NETWORK_DEVICE_LIST_KEY_OFFSET.\r
853 //\r
854 ASSERT(Index < MAX_KEY_SECTION_LEN);\r
855\r
75bf9d0e 856 if (!ExtractDisplayedHiiFormFromHiiHandle (HiiHandles[Index], &gEfiHiiPlatformSetupFormsetGuid, &FormSetTitle, &FormSetHelp)) {\r
5c08e117 857 continue;\r
858 }\r
859\r
cb7d01c0 860 String = HiiGetString (HiiHandles[Index], FormSetTitle, NULL);\r
0e8e994d 861 if (String == NULL) {\r
862 String = HiiGetString (HiiHandle, STR_MISSING_STRING, NULL);\r
863 ASSERT (String != NULL);\r
864 }\r
cb7d01c0 865 Token = HiiSetString (HiiHandle, 0, String, NULL);\r
866 FreePool (String);\r
5c08e117 867\r
cb7d01c0 868 String = HiiGetString (HiiHandles[Index], FormSetHelp, NULL);\r
0e8e994d 869 if (String == NULL) {\r
870 String = HiiGetString (HiiHandle, STR_MISSING_STRING, NULL);\r
871 ASSERT (String != NULL);\r
872 }\r
cb7d01c0 873 TokenHelp = HiiSetString (HiiHandle, 0, String, NULL);\r
874 FreePool (String);\r
5c08e117 875\r
3c4b1122
ED
876 //\r
877 // Network device process\r
878 // \r
879 if (IsNeedAddNetworkMenu (HiiHandles[Index], &AddItemCount)) {\r
880 if (mNextShowFormId == DEVICE_MANAGER_FORM_ID) {\r
881 //\r
882 // Only show one menu item "Network Config" in the device manger form.\r
883 //\r
884 if (!AddNetworkMenu) {\r
885 AddNetworkMenu = TRUE;\r
c1e2b152 886 HiiCreateGotoOpCode (\r
3c4b1122 887 StartOpCodeHandle,\r
c1e2b152 888 DEVICE_MANAGER_FORM_ID,\r
3c4b1122
ED
889 STRING_TOKEN (STR_FORM_NETWORK_DEVICE_LIST_TITLE),\r
890 STRING_TOKEN (STR_FORM_NETWORK_DEVICE_LIST_HELP),\r
891 EFI_IFR_FLAG_CALLBACK,\r
c1e2b152 892 (EFI_QUESTION_ID) QUESTION_NETWORK_DEVICE_ID\r
3c4b1122
ED
893 );\r
894 }\r
895 } else if (mNextShowFormId == NETWORK_DEVICE_LIST_FORM_ID) {\r
896 //\r
897 // In network device list form, same mac address device only show one menu.\r
898 //\r
899 while (AddItemCount > 0) {\r
c1e2b152 900 HiiCreateGotoOpCode (\r
3c4b1122 901 StartOpCodeHandle,\r
c1e2b152 902 NETWORK_DEVICE_LIST_FORM_ID,\r
3c4b1122
ED
903 mMacDeviceList.NodeList[mMacDeviceList.CurListLen - AddItemCount].PromptId,\r
904 STRING_TOKEN (STR_NETWORK_DEVICE_HELP),\r
905 EFI_IFR_FLAG_CALLBACK,\r
c1e2b152 906 mMacDeviceList.NodeList[mMacDeviceList.CurListLen - AddItemCount].QuestionId\r
3c4b1122
ED
907 );\r
908 AddItemCount -= 1;\r
909 }\r
910 } else if (mNextShowFormId == NETWORK_DEVICE_FORM_ID) {\r
911 //\r
912 // In network device form, only the selected mac address device need to be show.\r
913 //\r
c1e2b152 914 HiiCreateGotoOpCode (\r
3c4b1122 915 StartOpCodeHandle,\r
c1e2b152 916 NETWORK_DEVICE_FORM_ID,\r
3c4b1122
ED
917 Token,\r
918 TokenHelp,\r
919 EFI_IFR_FLAG_CALLBACK,\r
c1e2b152 920 (EFI_QUESTION_ID) (Index + DEVICE_KEY_OFFSET)\r
3c4b1122
ED
921 );\r
922 }\r
923 } else {\r
924 //\r
925 // \r
926 // Not network device process, only need to show at device manger form.\r
927 //\r
928 if (mNextShowFormId == DEVICE_MANAGER_FORM_ID) {\r
c1e2b152 929 HiiCreateGotoOpCode (\r
3c4b1122 930 StartOpCodeHandle,\r
c1e2b152 931 DEVICE_MANAGER_FORM_ID,\r
3c4b1122
ED
932 Token,\r
933 TokenHelp,\r
934 EFI_IFR_FLAG_CALLBACK,\r
c1e2b152 935 (EFI_QUESTION_ID) (Index + DEVICE_KEY_OFFSET)\r
3c4b1122
ED
936 );\r
937 }\r
938 }\r
5c08e117 939 }\r
940\r
ab4da126 941 Status = gBS->LocateHandleBuffer (\r
942 ByProtocol,\r
943 &gEfiDriverHealthProtocolGuid,\r
944 NULL,\r
945 &NumHandles,\r
946 &DriverHealthHandles\r
947 );\r
479e19a6 948\r
ab4da126 949 //\r
479e19a6 950 // If there are no drivers installed driver health protocol, do not create driver health entry in UI\r
ab4da126 951 //\r
479e19a6 952 if (NumHandles != 0) {\r
953 //\r
954 // If driver health protocol is installed, create Driver Health subtitle and entry\r
955 //\r
956 HiiCreateSubTitleOpCode (StartOpCodeHandle, STRING_TOKEN (STR_DM_DRIVER_HEALTH_TITLE), 0, 0, 0);\r
c1e2b152
ED
957 HiiCreateGotoOpCode (\r
958 StartOpCodeHandle,\r
959 DRIVER_HEALTH_FORM_ID,\r
479e19a6 960 STRING_TOKEN(STR_DRIVER_HEALTH_ALL_HEALTHY), // Prompt text\r
961 STRING_TOKEN(STR_DRIVER_HEALTH_STATUS_HELP), // Help text\r
c1e2b152
ED
962 EFI_IFR_FLAG_CALLBACK,\r
963 DEVICE_MANAGER_KEY_DRIVER_HEALTH // Question ID\r
964 );\r
479e19a6 965\r
ab4da126 966 //\r
967 // Check All Driver health status\r
968 //\r
969 if (!PlaformHealthStatusCheck ()) {\r
970 //\r
971 // At least one driver in the platform are not in healthy status\r
972 //\r
973 HiiSetString (HiiHandle, STRING_TOKEN (STR_DRIVER_HEALTH_ALL_HEALTHY), GetStringById (STRING_TOKEN (STR_DRIVER_NOT_HEALTH)), NULL);\r
974 } else {\r
975 //\r
976 // For the string of STR_DRIVER_HEALTH_ALL_HEALTHY previously has been updated and we need to update it while re-entry.\r
977 //\r
978 HiiSetString (HiiHandle, STRING_TOKEN (STR_DRIVER_HEALTH_ALL_HEALTHY), GetStringById (STRING_TOKEN (STR_DRIVER_HEALTH_ALL_HEALTHY)), NULL);\r
979 }\r
980 }\r
981\r
75bf9d0e
LG
982 HiiUpdateForm (\r
983 HiiHandle,\r
984 &mDeviceManagerGuid,\r
3c4b1122 985 mNextShowFormId,\r
75bf9d0e
LG
986 StartOpCodeHandle,\r
987 EndOpCodeHandle\r
988 );\r
989\r
5c08e117 990 ActionRequest = EFI_BROWSER_ACTION_REQUEST_NONE;\r
991 Status = gFormBrowser2->SendForm (\r
992 gFormBrowser2,\r
993 &HiiHandle,\r
994 1,\r
75bf9d0e 995 &mDeviceManagerGuid,\r
3c4b1122 996 mNextShowFormId,\r
5c08e117 997 NULL,\r
998 &ActionRequest\r
999 );\r
1000 if (ActionRequest == EFI_BROWSER_ACTION_REQUEST_RESET) {\r
1001 EnableResetRequired ();\r
1002 }\r
1003\r
1004 //\r
3c4b1122 1005 // We will have returned from processing a callback, selected\r
5c08e117 1006 // a target to display\r
1007 //\r
3c4b1122 1008 if ((gCallbackKey >= DEVICE_KEY_OFFSET)) {\r
5c08e117 1009 ActionRequest = EFI_BROWSER_ACTION_REQUEST_NONE;\r
1010 Status = gFormBrowser2->SendForm (\r
1011 gFormBrowser2,\r
1012 &HiiHandles[gCallbackKey - DEVICE_KEY_OFFSET],\r
1013 1,\r
1014 NULL,\r
1015 0,\r
1016 NULL,\r
1017 &ActionRequest\r
1018 );\r
1019\r
1020 if (ActionRequest == EFI_BROWSER_ACTION_REQUEST_RESET) {\r
1021 EnableResetRequired ();\r
1022 }\r
1023\r
1024 //\r
1025 // Force return to Device Manager\r
1026 //\r
1027 gCallbackKey = FRONT_PAGE_KEY_DEVICE_MANAGER;\r
3c4b1122 1028 goto Done;\r
5c08e117 1029 }\r
1030\r
ab4da126 1031 //\r
1032 // Driver Health item chose. \r
1033 //\r
1034 if (gCallbackKey == DEVICE_MANAGER_KEY_DRIVER_HEALTH) {\r
1035 CallDriverHealth ();\r
bd2057a8 1036 //\r
1037 // Force return to Device Manager\r
1038 //\r
1039 gCallbackKey = FRONT_PAGE_KEY_DEVICE_MANAGER;\r
3c4b1122
ED
1040 goto Done;\r
1041 }\r
1042\r
1043 //\r
1044 // Enter from device manager and into the network device list.\r
1045 //\r
1046 if (gCallbackKey == QUESTION_NETWORK_DEVICE_ID) {\r
1047 mNextShowFormId = NETWORK_DEVICE_LIST_FORM_ID;\r
1048 gCallbackKey = FRONT_PAGE_KEY_DEVICE_MANAGER;\r
1049 goto Done;\r
1050 }\r
1051\r
1052 //\r
1053 // In this case, go from the network device list to the specify device.\r
1054 //\r
1055 if ((gCallbackKey < MAX_KEY_SECTION_LEN + NETWORK_DEVICE_LIST_KEY_OFFSET ) && (gCallbackKey >= NETWORK_DEVICE_LIST_KEY_OFFSET)) {\r
1056 mNextShowFormId = NETWORK_DEVICE_FORM_ID;\r
1057 gCallbackKey = FRONT_PAGE_KEY_DEVICE_MANAGER;\r
1058 goto Done;\r
1059 }\r
1060\r
1061 //\r
1062 // Select the ESC, the gCallbackKey == 0.\r
1063 //\r
1064 if(mNextShowFormId - 1 < DEVICE_MANAGER_FORM_ID) {\r
1065 mNextShowFormId = DEVICE_MANAGER_FORM_ID;\r
1066 } else {\r
d3b4af2b 1067 mNextShowFormId = (UINT16) (mNextShowFormId - 1);\r
3c4b1122 1068 gCallbackKey = FRONT_PAGE_KEY_DEVICE_MANAGER;\r
ab4da126 1069 }\r
1070\r
3c4b1122 1071Done:\r
5c08e117 1072 //\r
7119d96a 1073 // Remove our packagelist from HII database.\r
5c08e117 1074 //\r
cb7d01c0 1075 HiiRemovePackages (HiiHandle);\r
7119d96a 1076 gDeviceManagerPrivate.HiiHandle = NULL;\r
5c08e117 1077\r
75bf9d0e
LG
1078 HiiFreeOpCodeHandle (StartOpCodeHandle);\r
1079 HiiFreeOpCodeHandle (EndOpCodeHandle);\r
5c08e117 1080 FreePool (HiiHandles);\r
1081\r
1082 return Status;\r
1083}\r
ab4da126 1084\r
1085/**\r
1086 This function is invoked if user selected a interactive opcode from Driver Health's\r
1087 Formset. The decision by user is saved to gCallbackKey for later processing.\r
1088\r
1089 @param This Points to the EFI_HII_CONFIG_ACCESS_PROTOCOL.\r
1090 @param Action Specifies the type of action taken by the browser.\r
1091 @param QuestionId A unique value which is sent to the original exporting driver\r
1092 so that it can identify the type of data to expect.\r
1093 @param Type The type of value for the question.\r
1094 @param Value A pointer to the data being sent to the original exporting driver.\r
1095 @param ActionRequest On return, points to the action requested by the callback function.\r
1096\r
1097 @retval EFI_SUCCESS The callback successfully handled the action.\r
1098 @retval EFI_INVALID_PARAMETER The setup browser call this function with invalid parameters.\r
1099\r
1100**/\r
1101EFI_STATUS\r
1102EFIAPI\r
1103DriverHealthCallback (\r
1104 IN CONST EFI_HII_CONFIG_ACCESS_PROTOCOL *This,\r
1105 IN EFI_BROWSER_ACTION Action,\r
1106 IN EFI_QUESTION_ID QuestionId,\r
1107 IN UINT8 Type,\r
1108 IN EFI_IFR_TYPE_VALUE *Value,\r
1109 OUT EFI_BROWSER_ACTION_REQUEST *ActionRequest\r
1110 )\r
1111{\r
4548fc2a
LG
1112 if ((Action == EFI_BROWSER_ACTION_FORM_OPEN) || (Action == EFI_BROWSER_ACTION_FORM_CLOSE)) {\r
1113 //\r
1114 // Do nothing for UEFI OPEN/CLOSE Action\r
1115 //\r
1116 return EFI_SUCCESS;\r
1117 }\r
1118\r
ab4da126 1119 if ((Value == NULL) || (ActionRequest == NULL)) {\r
1120 return EFI_INVALID_PARAMETER;\r
1121 }\r
1122\r
1123 gCallbackKey = QuestionId;\r
1124\r
1125 //\r
1126 // Request to exit SendForm(), so as to switch to selected form\r
1127 //\r
1128 *ActionRequest = EFI_BROWSER_ACTION_REQUEST_EXIT;\r
1129\r
1130 return EFI_SUCCESS;\r
1131}\r
1132\r
1133/**\r
1134 Collect and display the platform's driver health relative information, allow user to do interactive \r
1135 operation while the platform is unhealthy.\r
1136\r
1137 This function display a form which divided into two parts. The one list all modules which has installed \r
1138 driver health protocol. The list usually contain driver name, controller name, and it's health info.\r
1139 While the driver name can't be retrieved, will use device path as backup. The other part of the form provide\r
1140 a choice to the user to repair all platform.\r
1141\r
1142**/\r
1143VOID\r
1144CallDriverHealth (\r
1145 VOID\r
1146 )\r
1147{\r
1148 EFI_STATUS Status; \r
1149 EFI_HII_HANDLE HiiHandle;\r
1150 EFI_BROWSER_ACTION_REQUEST ActionRequest;\r
1151 EFI_IFR_GUID_LABEL *StartLabel;\r
1152 EFI_IFR_GUID_LABEL *StartLabelRepair;\r
1153 EFI_IFR_GUID_LABEL *EndLabel;\r
1154 EFI_IFR_GUID_LABEL *EndLabelRepair;\r
1155 VOID *StartOpCodeHandle;\r
1156 VOID *EndOpCodeHandle;\r
1157 VOID *StartOpCodeHandleRepair;\r
1158 VOID *EndOpCodeHandleRepair;\r
1159 UINTN Index;\r
1160 EFI_STRING_ID Token;\r
1161 EFI_STRING_ID TokenHelp;\r
1162 EFI_STRING String;\r
1163 EFI_STRING TmpString;\r
1164 EFI_STRING DriverName;\r
1165 EFI_STRING ControllerName;\r
1166 LIST_ENTRY DriverHealthList;\r
1167 DRIVER_HEALTH_INFO *DriverHealthInfo;\r
1168 LIST_ENTRY *Link;\r
1169 EFI_DEVICE_PATH_PROTOCOL *DriverDevicePath;\r
1170 UINTN Length;\r
2fde83b1 1171 BOOLEAN RebootRequired;\r
ab4da126 1172\r
ab4da126 1173 Index = 0;\r
1174 Length = 0;\r
1175 DriverHealthInfo = NULL; \r
1176 DriverDevicePath = NULL;\r
1177 InitializeListHead (&DriverHealthList);\r
1178\r
7119d96a 1179 HiiHandle = gDeviceManagerPrivate.DriverHealthHiiHandle;\r
1180 if (HiiHandle == NULL) {\r
1181 //\r
1182 // Publish Driver Health HII data.\r
1183 //\r
1184 HiiHandle = HiiAddPackages (\r
1185 &mDeviceManagerGuid,\r
1186 gDeviceManagerPrivate.DriverHealthHandle,\r
1187 DriverHealthVfrBin,\r
1188 BdsDxeStrings,\r
1189 NULL\r
1190 );\r
1191 if (HiiHandle == NULL) {\r
1192 return;\r
1193 }\r
1194\r
1195 gDeviceManagerPrivate.DriverHealthHiiHandle = HiiHandle;\r
1196 }\r
1197\r
ab4da126 1198 //\r
1199 // Allocate space for creation of UpdateData Buffer\r
1200 //\r
1201 StartOpCodeHandle = HiiAllocateOpCodeHandle ();\r
1202 ASSERT (StartOpCodeHandle != NULL);\r
1203\r
1204 EndOpCodeHandle = HiiAllocateOpCodeHandle ();\r
1205 ASSERT (EndOpCodeHandle != NULL);\r
1206\r
1207 StartOpCodeHandleRepair = HiiAllocateOpCodeHandle ();\r
1208 ASSERT (StartOpCodeHandleRepair != NULL);\r
1209\r
1210 EndOpCodeHandleRepair = HiiAllocateOpCodeHandle ();\r
1211 ASSERT (EndOpCodeHandleRepair != NULL);\r
1212\r
1213 //\r
1214 // Create Hii Extend Label OpCode as the start opcode\r
1215 //\r
1216 StartLabel = (EFI_IFR_GUID_LABEL *) HiiCreateGuidOpCode (StartOpCodeHandle, &gEfiIfrTianoGuid, NULL, sizeof (EFI_IFR_GUID_LABEL));\r
1217 StartLabel->ExtendOpCode = EFI_IFR_EXTEND_OP_LABEL;\r
1218 StartLabel->Number = LABEL_DRIVER_HEALTH;\r
1219\r
1220 //\r
1221 // Create Hii Extend Label OpCode as the start opcode\r
1222 //\r
1223 StartLabelRepair = (EFI_IFR_GUID_LABEL *) HiiCreateGuidOpCode (StartOpCodeHandleRepair, &gEfiIfrTianoGuid, NULL, sizeof (EFI_IFR_GUID_LABEL));\r
1224 StartLabelRepair->ExtendOpCode = EFI_IFR_EXTEND_OP_LABEL;\r
1225 StartLabelRepair->Number = LABEL_DRIVER_HEALTH_REAPIR_ALL;\r
1226\r
1227 //\r
1228 // Create Hii Extend Label OpCode as the end opcode\r
1229 //\r
1230 EndLabel = (EFI_IFR_GUID_LABEL *) HiiCreateGuidOpCode (EndOpCodeHandle, &gEfiIfrTianoGuid, NULL, sizeof (EFI_IFR_GUID_LABEL));\r
1231 EndLabel->ExtendOpCode = EFI_IFR_EXTEND_OP_LABEL;\r
1232 EndLabel->Number = LABEL_DRIVER_HEALTH_END;\r
1233\r
1234 //\r
1235 // Create Hii Extend Label OpCode as the end opcode\r
1236 //\r
1237 EndLabelRepair = (EFI_IFR_GUID_LABEL *) HiiCreateGuidOpCode (EndOpCodeHandleRepair, &gEfiIfrTianoGuid, NULL, sizeof (EFI_IFR_GUID_LABEL));\r
1238 EndLabelRepair->ExtendOpCode = EFI_IFR_EXTEND_OP_LABEL;\r
1239 EndLabelRepair->Number = LABEL_DRIVER_HEALTH_REAPIR_ALL_END;\r
1240\r
1241 HiiCreateSubTitleOpCode (StartOpCodeHandle, STRING_TOKEN (STR_DH_STATUS_LIST), 0, 0, 1);\r
1242\r
1243 Status = GetAllControllersHealthStatus (&DriverHealthList);\r
1244 ASSERT (Status != EFI_OUT_OF_RESOURCES);\r
1245\r
1246 Link = GetFirstNode (&DriverHealthList);\r
1247\r
1248 while (!IsNull (&DriverHealthList, Link)) { \r
1249 DriverHealthInfo = DEVICE_MANAGER_HEALTH_INFO_FROM_LINK (Link);\r
1250 \r
1251 //\r
1252 // Assume no line strings is longer than 512 bytes.\r
1253 //\r
1254 String = (EFI_STRING) AllocateZeroPool (0x200);\r
1255 ASSERT (String != NULL);\r
1256\r
1257 Status = DriverHealthGetDriverName (DriverHealthInfo->DriverHandle, &DriverName);\r
1258 if (EFI_ERROR (Status)) {\r
1259 //\r
1260 // Can not get the Driver name, so use the Device path\r
1261 //\r
1262 DriverDevicePath = DevicePathFromHandle (DriverHealthInfo->DriverHandle);\r
1263 DriverName = DevicePathToStr (DriverDevicePath);\r
1264 }\r
1265 //\r
1266 // Add the Driver name & Controller name into FormSetTitle string\r
1267 // \r
1268 StrnCat (String, DriverName, StrLen (DriverName));\r
1269\r
1270\r
1271 Status = DriverHealthGetControllerName (\r
1272 DriverHealthInfo->DriverHandle, \r
1273 DriverHealthInfo->ControllerHandle, \r
1274 DriverHealthInfo->ChildHandle, \r
1275 &ControllerName\r
1276 );\r
1277\r
1278 if (!EFI_ERROR (Status)) {\r
1279 //\r
1280 // Can not get the Controller name, just let it empty.\r
1281 //\r
1282 StrnCat (String, L" ", StrLen (L" "));\r
1283 StrnCat (String, ControllerName, StrLen (ControllerName)); \r
1284 }\r
1285 \r
1286 //\r
1287 // Add the message of the Module itself provided after the string item.\r
1288 //\r
1289 if ((DriverHealthInfo->MessageList != NULL) && (DriverHealthInfo->MessageList->StringId != 0)) {\r
1290 StrnCat (String, L" ", StrLen (L" "));\r
1291 TmpString = HiiGetString (\r
1292 DriverHealthInfo->MessageList->HiiHandle, \r
1293 DriverHealthInfo->MessageList->StringId, \r
1294 NULL\r
1295 );\r
1296 //\r
1297 // Assert if can not retrieve the message string\r
1298 //\r
1299 ASSERT (TmpString != NULL);\r
1300 StrnCat (String, TmpString, StrLen (TmpString));\r
1301 FreePool (TmpString);\r
1302 } else {\r
1303 //\r
1304 // Update the string will be displayed base on the driver's health status\r
1305 //\r
1306 switch(DriverHealthInfo->HealthStatus) {\r
1307 case EfiDriverHealthStatusRepairRequired:\r
2fde83b1
RN
1308 TmpString = GetStringById (STRING_TOKEN (STR_REPAIR_REQUIRED));\r
1309 StrCat (String, TmpString);\r
ab4da126 1310 break;\r
1311 case EfiDriverHealthStatusConfigurationRequired:\r
2fde83b1
RN
1312 TmpString = GetStringById (STRING_TOKEN (STR_CONFIGURATION_REQUIRED));\r
1313 StrCat (String, TmpString);\r
ab4da126 1314 break;\r
1315 case EfiDriverHealthStatusFailed:\r
2fde83b1
RN
1316 TmpString = GetStringById (STRING_TOKEN (STR_OPERATION_FAILED));\r
1317 StrCat (String, TmpString);\r
ab4da126 1318 break;\r
1319 case EfiDriverHealthStatusReconnectRequired:\r
2fde83b1
RN
1320 TmpString = GetStringById (STRING_TOKEN (STR_RECONNECT_REQUIRED));\r
1321 StrCat (String, TmpString);\r
ab4da126 1322 break;\r
1323 case EfiDriverHealthStatusRebootRequired:\r
2fde83b1
RN
1324 TmpString = GetStringById (STRING_TOKEN (STR_REBOOT_REQUIRED));\r
1325 StrCat (String, TmpString);\r
ab4da126 1326 break;\r
1327 default:\r
2fde83b1
RN
1328 TmpString = GetStringById (STRING_TOKEN (STR_DRIVER_HEALTH_HEALTHY));\r
1329 StrCat (String, TmpString);\r
ab4da126 1330 break;\r
1331 }\r
2fde83b1 1332 FreePool (TmpString);\r
ab4da126 1333 }\r
1334\r
1335 Token = HiiSetString (HiiHandle, 0, String, NULL);\r
1336 FreePool (String);\r
1337\r
1338 TokenHelp = HiiSetString (HiiHandle, 0, GetStringById( STRING_TOKEN (STR_DH_REPAIR_SINGLE_HELP)), NULL);\r
1339\r
1340 HiiCreateActionOpCode (\r
1341 StartOpCodeHandle,\r
1342 (EFI_QUESTION_ID) (Index + DRIVER_HEALTH_KEY_OFFSET),\r
1343 Token,\r
1344 TokenHelp,\r
1345 EFI_IFR_FLAG_CALLBACK,\r
1346 0\r
1347 );\r
1348 Index++;\r
1349 Link = GetNextNode (&DriverHealthList, Link);\r
1350 }\r
1351 \r
1352 //\r
1353 // Add End Opcode for Subtitle\r
1354 // \r
1355 HiiCreateEndOpCode (StartOpCodeHandle);\r
1356\r
1357 HiiCreateSubTitleOpCode (StartOpCodeHandleRepair, STRING_TOKEN (STR_DRIVER_HEALTH_REPAIR_ALL), 0, 0, 1);\r
1358 TokenHelp = HiiSetString (HiiHandle, 0, GetStringById( STRING_TOKEN (STR_DH_REPAIR_ALL_HELP)), NULL); \r
1359\r
1360 if (PlaformHealthStatusCheck ()) {\r
1361 //\r
1362 // No action need to do for the platform\r
1363 //\r
1364 Token = HiiSetString (HiiHandle, 0, GetStringById( STRING_TOKEN (STR_DRIVER_HEALTH_ALL_HEALTHY)), NULL);\r
1365 HiiCreateActionOpCode (\r
1366 StartOpCodeHandleRepair,\r
1367 0,\r
1368 Token,\r
1369 TokenHelp,\r
1370 EFI_IFR_FLAG_READ_ONLY,\r
1371 0\r
1372 );\r
1373 } else {\r
1374 //\r
1375 // Create ActionOpCode only while the platform need to do health related operation.\r
1376 //\r
1377 Token = HiiSetString (HiiHandle, 0, GetStringById( STRING_TOKEN (STR_DH_REPAIR_ALL_TITLE)), NULL);\r
1378 HiiCreateActionOpCode (\r
1379 StartOpCodeHandleRepair,\r
1380 (EFI_QUESTION_ID) DRIVER_HEALTH_REPAIR_ALL_KEY,\r
1381 Token,\r
1382 TokenHelp,\r
1383 EFI_IFR_FLAG_CALLBACK,\r
1384 0\r
1385 );\r
1386 }\r
1387\r
1388 HiiCreateEndOpCode (StartOpCodeHandleRepair);\r
1389\r
1390 Status = HiiUpdateForm (\r
1391 HiiHandle,\r
1392 &mDriverHealthGuid,\r
1393 DRIVER_HEALTH_FORM_ID,\r
1394 StartOpCodeHandle,\r
1395 EndOpCodeHandle\r
1396 );\r
1397 ASSERT (Status != EFI_NOT_FOUND);\r
1398 ASSERT (Status != EFI_BUFFER_TOO_SMALL);\r
1399\r
1400 Status = HiiUpdateForm (\r
1401 HiiHandle,\r
1402 &mDriverHealthGuid,\r
1403 DRIVER_HEALTH_FORM_ID,\r
1404 StartOpCodeHandleRepair,\r
1405 EndOpCodeHandleRepair\r
1406 );\r
1407 ASSERT (Status != EFI_NOT_FOUND);\r
1408 ASSERT (Status != EFI_BUFFER_TOO_SMALL);\r
1409\r
1410 ActionRequest = EFI_BROWSER_ACTION_REQUEST_NONE;\r
1411 Status = gFormBrowser2->SendForm (\r
1412 gFormBrowser2,\r
1413 &HiiHandle,\r
1414 1,\r
1415 &mDriverHealthGuid,\r
1416 DRIVER_HEALTH_FORM_ID,\r
1417 NULL,\r
1418 &ActionRequest\r
1419 );\r
1420 if (ActionRequest == EFI_BROWSER_ACTION_REQUEST_RESET) {\r
1421 EnableResetRequired ();\r
1422 }\r
1423\r
1424 //\r
1425 // We will have returned from processing a callback - user either hit ESC to exit, or selected\r
1426 // a target to display.\r
1427 // Process the diver health status states here.\r
1428 // \r
bd2057a8 1429 if (gCallbackKey >= DRIVER_HEALTH_KEY_OFFSET && gCallbackKey != DRIVER_HEALTH_REPAIR_ALL_KEY) {\r
ab4da126 1430 ActionRequest = EFI_BROWSER_ACTION_REQUEST_NONE;\r
1431\r
1432 Link = GetFirstNode (&DriverHealthList);\r
1433 Index = 0;\r
1434\r
1435 while (!IsNull (&DriverHealthList, Link)) {\r
1436 //\r
1437 // Got the item relative node in the List\r
1438 //\r
1439 if (Index == (gCallbackKey - DRIVER_HEALTH_KEY_OFFSET)) { \r
1440 DriverHealthInfo = DEVICE_MANAGER_HEALTH_INFO_FROM_LINK (Link);\r
1441 //\r
1442 // Process the driver's healthy status for the specify module\r
1443 //\r
2fde83b1 1444 RebootRequired = FALSE;\r
ab4da126 1445 ProcessSingleControllerHealth (\r
1446 DriverHealthInfo->DriverHealth,\r
1447 DriverHealthInfo->ControllerHandle, \r
1448 DriverHealthInfo->ChildHandle,\r
1449 DriverHealthInfo->HealthStatus,\r
1450 &(DriverHealthInfo->MessageList),\r
2fde83b1
RN
1451 DriverHealthInfo->HiiHandle,\r
1452 &RebootRequired\r
1453 );\r
1454 if (RebootRequired) {\r
1455 gRT->ResetSystem (EfiResetWarm, EFI_SUCCESS, 0, NULL);\r
1456 }\r
1457 break;\r
ab4da126 1458 }\r
1459 Index++;\r
1460 Link = GetNextNode (&DriverHealthList, Link);\r
1461 }\r
1462\r
1463 if (ActionRequest == EFI_BROWSER_ACTION_REQUEST_RESET) {\r
1464 EnableResetRequired ();\r
1465 }\r
1466 \r
1467 //\r
1468 // Force return to the form of Driver Health in Device Manager \r
1469 //\r
1470 gCallbackKey = DRIVER_HEALTH_RETURN_KEY;\r
1471 }\r
1472\r
1473 //\r
1474 // Repair the whole platform\r
1475 //\r
1476 if (gCallbackKey == DRIVER_HEALTH_REPAIR_ALL_KEY) {\r
1477 ActionRequest = EFI_BROWSER_ACTION_REQUEST_NONE;\r
1478 \r
1479 PlatformRepairAll (&DriverHealthList);\r
1480\r
1481 gCallbackKey = DRIVER_HEALTH_RETURN_KEY;\r
1482 }\r
1483 \r
1484 //\r
7119d96a 1485 // Remove driver health packagelist from HII database.\r
ab4da126 1486 //\r
ab4da126 1487 HiiRemovePackages (HiiHandle);\r
7119d96a 1488 gDeviceManagerPrivate.DriverHealthHiiHandle = NULL;\r
ab4da126 1489\r
ab4da126 1490 //\r
1491 // Free driver health info list\r
1492 //\r
1493 while (!IsListEmpty (&DriverHealthList)) {\r
1494\r
1495 Link = GetFirstNode(&DriverHealthList);\r
1496 DriverHealthInfo = DEVICE_MANAGER_HEALTH_INFO_FROM_LINK (Link);\r
1497 RemoveEntryList (Link);\r
1498\r
1499 if (DriverHealthInfo->MessageList != NULL) {\r
1500 FreePool(DriverHealthInfo->MessageList);\r
1501 FreePool (DriverHealthInfo);\r
1502 } \r
1503 }\r
1504\r
1505 HiiFreeOpCodeHandle (StartOpCodeHandle);\r
1506 HiiFreeOpCodeHandle (EndOpCodeHandle); \r
1507 HiiFreeOpCodeHandle (StartOpCodeHandleRepair);\r
1508 HiiFreeOpCodeHandle (EndOpCodeHandleRepair); \r
1509\r
1510 if (gCallbackKey == DRIVER_HEALTH_RETURN_KEY) {\r
bd2057a8 1511 //\r
1512 // Force return to Driver Health Form\r
1513 //\r
ab4da126 1514 gCallbackKey = DEVICE_MANAGER_KEY_DRIVER_HEALTH;\r
1515 CallDriverHealth ();\r
1516 }\r
ab4da126 1517}\r
1518\r
1519\r
8e8ae2da 1520/**\r
ab4da126 1521 Check the Driver Health status of a single controller and try to process it if not healthy.\r
1522\r
1523 This function called by CheckAllControllersHealthStatus () function in order to process a specify\r
1524 contoller's health state.\r
1525\r
8e8ae2da 1526 @param DriverHealthList A Pointer to the list contain all of the platform driver health information. \r
1527 @param DriverHandle The handle of driver.\r
ab4da126 1528 @param ControllerHandle The class guid specifies which form set will be displayed.\r
1529 @param ChildHandle The handle of the child controller to retrieve the health \r
8e8ae2da 1530 status on. This is an optional parameter that may be NULL. \r
1531 @param DriverHealth A pointer to the EFI_DRIVER_HEALTH_PROTOCOL instance.\r
ab4da126 1532 @param HealthStatus The health status of the controller.\r
ab4da126 1533\r
1534 @retval EFI_INVALID_PARAMETER HealthStatus or DriverHealth is NULL.\r
1535 @retval HealthStatus The Health status of specify controller.\r
1536 @retval EFI_OUT_OF_RESOURCES The list of Driver Health Protocol handles can not be retrieved.\r
1537 @retval EFI_NOT_FOUND No controller in the platform install Driver Health Protocol.\r
1538 @retval EFI_SUCCESS The Health related operation has been taken successfully.\r
1539\r
8e8ae2da 1540**/\r
ab4da126 1541EFI_STATUS\r
1542EFIAPI\r
1543GetSingleControllerHealthStatus (\r
1544 IN OUT LIST_ENTRY *DriverHealthList,\r
1545 IN EFI_HANDLE DriverHandle,\r
1546 IN EFI_HANDLE ControllerHandle, OPTIONAL\r
1547 IN EFI_HANDLE ChildHandle, OPTIONAL\r
1548 IN EFI_DRIVER_HEALTH_PROTOCOL *DriverHealth,\r
1549 IN EFI_DRIVER_HEALTH_STATUS *HealthStatus\r
1550 )\r
1551{\r
1552 EFI_STATUS Status;\r
1553 EFI_DRIVER_HEALTH_HII_MESSAGE *MessageList;\r
1554 EFI_HII_HANDLE FormHiiHandle;\r
1555 DRIVER_HEALTH_INFO *DriverHealthInfo;\r
1556\r
1557 if (HealthStatus == NULL) {\r
1558 //\r
1559 // If HealthStatus is NULL, then return EFI_INVALID_PARAMETER\r
1560 //\r
1561 return EFI_INVALID_PARAMETER;\r
1562 }\r
1563\r
1564 //\r
1565 // Assume the HealthStatus is healthy\r
1566 //\r
1567 *HealthStatus = EfiDriverHealthStatusHealthy;\r
1568\r
1569 if (DriverHealth == NULL) {\r
1570 //\r
1571 // If DriverHealth is NULL, then return EFI_INVALID_PARAMETER\r
1572 //\r
1573 return EFI_INVALID_PARAMETER;\r
1574 }\r
1575\r
1576 if (ControllerHandle == NULL) {\r
1577 //\r
1578 // If ControllerHandle is NULL, the return the cumulative health status of the driver\r
1579 //\r
1580 Status = DriverHealth->GetHealthStatus (DriverHealth, NULL, NULL, HealthStatus, NULL, NULL);\r
1581 if (*HealthStatus == EfiDriverHealthStatusHealthy) {\r
1582 //\r
1583 // Add the driver health related information into the list\r
1584 //\r
1585 DriverHealthInfo = AllocateZeroPool (sizeof (DRIVER_HEALTH_INFO));\r
1586 if (DriverHealthInfo == NULL) {\r
1587 return EFI_OUT_OF_RESOURCES;\r
1588 }\r
1589\r
1590 DriverHealthInfo->Signature = DEVICE_MANAGER_DRIVER_HEALTH_INFO_SIGNATURE;\r
1591 DriverHealthInfo->DriverHandle = DriverHandle;\r
1592 DriverHealthInfo->ControllerHandle = NULL;\r
1593 DriverHealthInfo->ChildHandle = NULL;\r
1594 DriverHealthInfo->HiiHandle = NULL;\r
1595 DriverHealthInfo->DriverHealth = DriverHealth;\r
1596 DriverHealthInfo->MessageList = NULL;\r
1597 DriverHealthInfo->HealthStatus = *HealthStatus;\r
1598\r
1599 InsertTailList (DriverHealthList, &DriverHealthInfo->Link);\r
1600 }\r
1601 return Status;\r
1602 }\r
1603\r
1604 MessageList = NULL;\r
1605 FormHiiHandle = NULL;\r
1606\r
1607 //\r
1608 // Collect the health status with the optional HII message list\r
1609 //\r
1610 Status = DriverHealth->GetHealthStatus (DriverHealth, ControllerHandle, ChildHandle, HealthStatus, &MessageList, &FormHiiHandle);\r
1611\r
1612 if (EFI_ERROR (Status)) {\r
1613 //\r
1614 // If the health status could not be retrieved, then return immediately\r
1615 //\r
1616 return Status;\r
1617 }\r
1618\r
1619 //\r
1620 // Add the driver health related information into the list\r
1621 //\r
1622 DriverHealthInfo = AllocateZeroPool (sizeof (DRIVER_HEALTH_INFO));\r
1623 if (DriverHealthInfo == NULL) {\r
1624 return EFI_OUT_OF_RESOURCES;\r
1625 }\r
1626\r
1627 DriverHealthInfo->Signature = DEVICE_MANAGER_DRIVER_HEALTH_INFO_SIGNATURE; \r
1628 DriverHealthInfo->DriverHandle = DriverHandle;\r
1629 DriverHealthInfo->ControllerHandle = ControllerHandle;\r
1630 DriverHealthInfo->ChildHandle = ChildHandle;\r
1631 DriverHealthInfo->HiiHandle = FormHiiHandle;\r
1632 DriverHealthInfo->DriverHealth = DriverHealth;\r
1633 DriverHealthInfo->MessageList = MessageList;\r
1634 DriverHealthInfo->HealthStatus = *HealthStatus;\r
1635\r
1636 InsertTailList (DriverHealthList, &DriverHealthInfo->Link);\r
1637\r
1638 return EFI_SUCCESS;\r
1639}\r
1640\r
1641/**\r
1642 Collects all the EFI Driver Health Protocols currently present in the EFI Handle Database, \r
1643 and queries each EFI Driver Health Protocol to determine if one or more of the controllers \r
1644 managed by each EFI Driver Health Protocol instance are not healthy. \r
1645\r
1646 @param DriverHealthList A Pointer to the list contain all of the platform driver health\r
1647 information. \r
1648\r
1649 @retval EFI_NOT_FOUND No controller in the platform install Driver Health Protocol.\r
1650 @retval EFI_SUCCESS All the controllers in the platform are healthy.\r
1651 @retval EFI_OUT_OF_RESOURCES The list of Driver Health Protocol handles can not be retrieved.\r
1652\r
1653**/\r
1654EFI_STATUS\r
1655GetAllControllersHealthStatus (\r
1656 IN OUT LIST_ENTRY *DriverHealthList\r
1657 )\r
1658{\r
1659 EFI_STATUS Status; \r
1660 UINTN NumHandles;\r
1661 EFI_HANDLE *DriverHealthHandles;\r
1662 EFI_DRIVER_HEALTH_PROTOCOL *DriverHealth;\r
1663 EFI_DRIVER_HEALTH_STATUS HealthStatus;\r
1664 UINTN DriverHealthIndex;\r
1665 EFI_HANDLE *Handles;\r
1666 UINTN HandleCount;\r
1667 UINTN ControllerIndex;\r
1668 UINTN ChildIndex;\r
1669 \r
1670 //\r
1671 // Initialize local variables\r
1672 //\r
1673 Handles = NULL;\r
1674 DriverHealthHandles = NULL;\r
1675 NumHandles = 0;\r
1676 HandleCount = 0;\r
1677\r
1678 HealthStatus = EfiDriverHealthStatusHealthy;\r
1679\r
1680 Status = gBS->LocateHandleBuffer (\r
1681 ByProtocol,\r
1682 &gEfiDriverHealthProtocolGuid,\r
1683 NULL,\r
1684 &NumHandles,\r
1685 &DriverHealthHandles\r
1686 );\r
1687\r
1688 if (Status == EFI_NOT_FOUND || NumHandles == 0) {\r
1689 //\r
1690 // If there are no Driver Health Protocols handles, then return EFI_NOT_FOUND\r
1691 //\r
1692 return EFI_NOT_FOUND;\r
1693 }\r
1694\r
1695 if (EFI_ERROR (Status) || DriverHealthHandles == NULL) {\r
1696 //\r
1697 // If the list of Driver Health Protocol handles can not be retrieved, then \r
1698 // return EFI_OUT_OF_RESOURCES\r
1699 //\r
1700 return EFI_OUT_OF_RESOURCES;\r
1701 }\r
1702\r
1703 //\r
1704 // Check the health status of all controllers in the platform\r
1705 // Start by looping through all the Driver Health Protocol handles in the handle database\r
1706 //\r
1707 for (DriverHealthIndex = 0; DriverHealthIndex < NumHandles; DriverHealthIndex++) {\r
1708 //\r
1709 // Skip NULL Driver Health Protocol handles\r
1710 //\r
1711 if (DriverHealthHandles[DriverHealthIndex] == NULL) {\r
1712 continue;\r
1713 }\r
1714\r
1715 //\r
1716 // Retrieve the Driver Health Protocol from DriverHandle\r
1717 //\r
1718 Status = gBS->HandleProtocol ( \r
1719 DriverHealthHandles[DriverHealthIndex],\r
1720 &gEfiDriverHealthProtocolGuid,\r
1721 (VOID **)&DriverHealth\r
1722 );\r
1723 if (EFI_ERROR (Status)) {\r
1724 //\r
1725 // If the Driver Health Protocol can not be retrieved, then skip to the next\r
1726 // Driver Health Protocol handle\r
1727 //\r
1728 continue;\r
1729 }\r
1730\r
1731 //\r
1732 // Check the health of all the controllers managed by a Driver Health Protocol handle\r
1733 //\r
1734 Status = GetSingleControllerHealthStatus (DriverHealthList, DriverHealthHandles[DriverHealthIndex], NULL, NULL, DriverHealth, &HealthStatus);\r
1735\r
1736 //\r
1737 // If Status is an error code, then the health information could not be retrieved, so assume healthy\r
1738 // and skip to the next Driver Health Protocol handle\r
1739 //\r
1740 if (EFI_ERROR (Status)) {\r
1741 continue;\r
1742 }\r
1743\r
1744 //\r
1745 // If all the controllers managed by this Driver Health Protocol are healthy, then skip to the next \r
1746 // Driver Health Protocol handle\r
1747 //\r
1748 if (HealthStatus == EfiDriverHealthStatusHealthy) {\r
1749 continue;\r
1750 }\r
1751\r
1752 //\r
1753 // See if the list of all handles in the handle database has been retrieved\r
1754 //\r
1755 //\r
1756 if (Handles == NULL) {\r
1757 //\r
1758 // Retrieve the list of all handles from the handle database\r
1759 //\r
1760 Status = gBS->LocateHandleBuffer (\r
1761 AllHandles,\r
1762 NULL,\r
1763 NULL,\r
1764 &HandleCount,\r
1765 &Handles\r
1766 );\r
1767 if (EFI_ERROR (Status) || Handles == NULL) {\r
1768 //\r
1769 // If all the handles in the handle database can not be retrieved, then \r
1770 // return EFI_OUT_OF_RESOURCES\r
1771 //\r
1772 Status = EFI_OUT_OF_RESOURCES;\r
1773 goto Done;\r
1774 }\r
1775 }\r
1776 //\r
1777 // Loop through all the controller handles in the handle database\r
1778 //\r
1779 for (ControllerIndex = 0; ControllerIndex < HandleCount; ControllerIndex++) {\r
1780 //\r
1781 // Skip NULL controller handles\r
1782 //\r
1783 if (Handles[ControllerIndex] == NULL) {\r
1784 continue;\r
1785 }\r
1786\r
1787 Status = GetSingleControllerHealthStatus (DriverHealthList, DriverHealthHandles[DriverHealthIndex], Handles[ControllerIndex], NULL, DriverHealth, &HealthStatus);\r
1788 if (EFI_ERROR (Status)) {\r
1789 //\r
1790 // If Status is an error code, then the health information could not be retrieved, so assume healthy\r
1791 //\r
1792 HealthStatus = EfiDriverHealthStatusHealthy;\r
1793 }\r
1794\r
1795 //\r
1796 // If CheckHealthSingleController() returned an error on a terminal state, then do not check the health of child controllers\r
1797 //\r
1798 if (EFI_ERROR (Status)) {\r
1799 continue;\r
1800 }\r
1801\r
1802 //\r
1803 // Loop through all the child handles in the handle database\r
1804 //\r
1805 for (ChildIndex = 0; ChildIndex < HandleCount; ChildIndex++) {\r
1806 //\r
1807 // Skip NULL child handles\r
1808 //\r
1809 if (Handles[ChildIndex] == NULL) {\r
1810 continue;\r
1811 }\r
1812\r
1813 Status = GetSingleControllerHealthStatus (DriverHealthList, DriverHealthHandles[DriverHealthIndex], Handles[ControllerIndex], Handles[ChildIndex], DriverHealth, &HealthStatus);\r
1814 if (EFI_ERROR (Status)) {\r
1815 //\r
1816 // If Status is an error code, then the health information could not be retrieved, so assume healthy\r
1817 //\r
1818 HealthStatus = EfiDriverHealthStatusHealthy;\r
1819 }\r
1820\r
1821 //\r
1822 // If CheckHealthSingleController() returned an error on a terminal state, then skip to the next child\r
1823 //\r
1824 if (EFI_ERROR (Status)) {\r
1825 continue;\r
1826 }\r
1827 }\r
1828 }\r
1829 }\r
1830\r
1831 Status = EFI_SUCCESS;\r
1832\r
1833Done:\r
1834 if (Handles != NULL) {\r
1835 gBS->FreePool (Handles);\r
1836 }\r
1837 if (DriverHealthHandles != NULL) {\r
1838 gBS->FreePool (DriverHealthHandles);\r
1839 }\r
1840\r
1841 return Status;\r
1842}\r
1843\r
1844\r
8e8ae2da 1845/**\r
ab4da126 1846 Check the healthy status of the platform, this function will return immediately while found one driver \r
1847 in the platform are not healthy.\r
1848\r
1849 @retval FALSE at least one driver in the platform are not healthy.\r
1850 @retval TRUE No controller install Driver Health Protocol,\r
1851 or all controllers in the platform are in healthy status.\r
8e8ae2da 1852**/\r
ab4da126 1853BOOLEAN\r
1854PlaformHealthStatusCheck (\r
1855 VOID\r
1856 )\r
1857{\r
1858 EFI_DRIVER_HEALTH_STATUS HealthStatus;\r
1859 EFI_STATUS Status;\r
1860 UINTN Index;\r
1861 UINTN NoHandles;\r
1862 EFI_HANDLE *DriverHealthHandles;\r
1863 EFI_DRIVER_HEALTH_PROTOCOL *DriverHealth;\r
1864 BOOLEAN AllHealthy;\r
1865\r
1866 //\r
1867 // Initialize local variables\r
1868 //\r
1869 DriverHealthHandles = NULL;\r
1870 DriverHealth = NULL;\r
1871\r
1872 HealthStatus = EfiDriverHealthStatusHealthy;\r
1873\r
1874 Status = gBS->LocateHandleBuffer (\r
1875 ByProtocol,\r
1876 &gEfiDriverHealthProtocolGuid,\r
1877 NULL,\r
1878 &NoHandles,\r
1879 &DriverHealthHandles\r
1880 );\r
1881 //\r
1882 // There are no handles match the search for Driver Health Protocol has been installed.\r
1883 //\r
1884 if (Status == EFI_NOT_FOUND) {\r
1885 return TRUE;\r
1886 }\r
1887 //\r
1888 // Assume all modules are healthy.\r
1889 // \r
1890 AllHealthy = TRUE;\r
1891\r
1892 //\r
1893 // Found one or more Handles.\r
1894 //\r
1895 if (!EFI_ERROR (Status)) { \r
1896 for (Index = 0; Index < NoHandles; Index++) {\r
1897 Status = gBS->HandleProtocol (\r
1898 DriverHealthHandles[Index],\r
1899 &gEfiDriverHealthProtocolGuid,\r
1900 (VOID **) &DriverHealth\r
1901 );\r
1902 if (!EFI_ERROR (Status)) {\r
1903 Status = DriverHealth->GetHealthStatus (\r
1904 DriverHealth,\r
1905 NULL,\r
1906 NULL,\r
1907 &HealthStatus,\r
1908 NULL,\r
1909 NULL\r
1910 );\r
1911 }\r
1912 //\r
1913 // Get the healthy status of the module\r
1914 //\r
1915 if (!EFI_ERROR (Status)) {\r
1916 if (HealthStatus != EfiDriverHealthStatusHealthy) {\r
1917 //\r
1918 // Return immediately one driver's status not in healthy.\r
1919 //\r
1920 return FALSE; \r
1921 }\r
1922 }\r
1923 }\r
1924 }\r
1925 return AllHealthy;\r
1926}\r
1927\r
1928/**\r
1929 Processes a single controller using the EFI Driver Health Protocol associated with \r
1930 that controller. This algorithm continues to query the GetHealthStatus() service until\r
1931 one of the legal terminal states of the EFI Driver Health Protocol is reached. This may \r
1932 require the processing of HII Messages, HII Form, and invocation of repair operations.\r
1933\r
1934 @param DriverHealth A pointer to the EFI_DRIVER_HEALTH_PROTOCOL instance.\r
1935 @param ControllerHandle The class guid specifies which form set will be displayed.\r
1936 @param ChildHandle The handle of the child controller to retrieve the health \r
1937 status on. This is an optional parameter that may be NULL. \r
1938 @param HealthStatus The health status of the controller.\r
1939 @param MessageList An array of warning or error messages associated \r
1940 with the controller specified by ControllerHandle and \r
1941 ChildHandle. This is an optional parameter that may be NULL.\r
1942 @param FormHiiHandle The HII handle for an HII form associated with the \r
1943 controller specified by ControllerHandle and ChildHandle.\r
2fde83b1 1944 @param RebootRequired Indicate whether a reboot is required to repair the controller.\r
ab4da126 1945**/\r
1946VOID\r
1947ProcessSingleControllerHealth (\r
2fde83b1
RN
1948 IN EFI_DRIVER_HEALTH_PROTOCOL *DriverHealth,\r
1949 IN EFI_HANDLE ControllerHandle, OPTIONAL\r
1950 IN EFI_HANDLE ChildHandle, OPTIONAL\r
1951 IN EFI_DRIVER_HEALTH_STATUS HealthStatus,\r
1952 IN EFI_DRIVER_HEALTH_HII_MESSAGE **MessageList, OPTIONAL\r
1953 IN EFI_HII_HANDLE FormHiiHandle,\r
1954 IN OUT BOOLEAN *RebootRequired\r
ab4da126 1955 )\r
1956{\r
1957 EFI_STATUS Status;\r
1958 EFI_DRIVER_HEALTH_STATUS LocalHealthStatus;\r
1959 \r
1960 LocalHealthStatus = HealthStatus;\r
1961 //\r
1962 // If the module need to be repaired or reconfiguration, will process it until\r
1963 // reach a terminal status. The status from EfiDriverHealthStatusRepairRequired after repair \r
1964 // will be in (Health, Failed, Configuration Required).\r
1965 //\r
2fde83b1
RN
1966 while(LocalHealthStatus == EfiDriverHealthStatusConfigurationRequired ||\r
1967 LocalHealthStatus == EfiDriverHealthStatusRepairRequired) {\r
ab4da126 1968\r
1969 if (LocalHealthStatus == EfiDriverHealthStatusRepairRequired) {\r
1970 Status = DriverHealth->Repair (\r
1971 DriverHealth,\r
1972 ControllerHandle,\r
1973 ChildHandle,\r
1974 (EFI_DRIVER_HEALTH_REPAIR_PROGRESS_NOTIFY) RepairNotify\r
1975 );\r
1976 }\r
1977 //\r
1978 // Via a form of the driver need to do configuration provided to process of status in \r
1979 // EfiDriverHealthStatusConfigurationRequired. The status after configuration should be in\r
1980 // (Healthy, Reboot Required, Failed, Reconnect Required, Repair Required). \r
1981 //\r
1982 if (LocalHealthStatus == EfiDriverHealthStatusConfigurationRequired) {\r
2fde83b1
RN
1983 if (FormHiiHandle != NULL) {\r
1984 Status = gFormBrowser2->SendForm (\r
1985 gFormBrowser2,\r
1986 &FormHiiHandle,\r
1987 1,\r
1988 &gEfiHiiDriverHealthFormsetGuid,\r
1989 0,\r
1990 NULL,\r
1991 NULL\r
1992 );\r
1993 ASSERT( !EFI_ERROR (Status));\r
1994 } else {\r
1995 //\r
1996 // Exit the loop in case no FormHiiHandle is supplied to prevent dead-loop\r
1997 //\r
1998 break;\r
1999 }\r
ab4da126 2000 }\r
2001\r
2002 Status = DriverHealth->GetHealthStatus (\r
2003 DriverHealth,\r
2004 ControllerHandle,\r
2005 ChildHandle,\r
2006 &LocalHealthStatus,\r
2007 NULL,\r
2008 &FormHiiHandle\r
2009 );\r
2fde83b1 2010 ASSERT_EFI_ERROR (Status);\r
ab4da126 2011\r
2fde83b1 2012 if (*MessageList != NULL) {\r
ab4da126 2013 ProcessMessages (*MessageList);\r
2fde83b1 2014 } \r
ab4da126 2015 }\r
2016 \r
2017 //\r
2018 // Health status in {Healthy, Failed} may also have Messages need to process\r
2019 //\r
2020 if (LocalHealthStatus == EfiDriverHealthStatusHealthy || LocalHealthStatus == EfiDriverHealthStatusFailed) {\r
2021 if (*MessageList != NULL) {\r
2022 ProcessMessages (*MessageList);\r
2023 }\r
2024 }\r
2025 //\r
2026 // Check for RebootRequired or ReconnectRequired\r
2027 //\r
2028 if (LocalHealthStatus == EfiDriverHealthStatusRebootRequired) {\r
2fde83b1 2029 *RebootRequired = TRUE;\r
ab4da126 2030 }\r
2031 \r
2032 //\r
2033 // Do reconnect if need.\r
2034 //\r
2035 if (LocalHealthStatus == EfiDriverHealthStatusReconnectRequired) {\r
2036 Status = gBS->DisconnectController (ControllerHandle, NULL, NULL);\r
2037 if (EFI_ERROR (Status)) {\r
2fde83b1
RN
2038 //\r
2039 // Disconnect failed. Need to promote reconnect to a reboot.\r
2040 //\r
2041 *RebootRequired = TRUE;\r
2042 } else {\r
2043 gBS->ConnectController (ControllerHandle, NULL, NULL, TRUE);\r
ab4da126 2044 }\r
ab4da126 2045 }\r
2046}\r
2047\r
2048\r
2049/**\r
2050 Platform specific notification function for controller repair operations.\r
2051\r
2052 If the driver for a controller support the Driver Health Protocol and the\r
2053 current state of the controller is EfiDriverHealthStatusRepairRequired then\r
2054 when the Repair() service of the Driver Health Protocol is called, this \r
2055 platform specific notification function can display the progress of the repair\r
2056 operation. Some platforms may choose to not display anything, other may choose\r
2057 to show the percentage complete on text consoles, and other may choose to render\r
2058 a progress bar on text and graphical consoles.\r
2059\r
2060 This function displays the percentage of the repair operation that has been\r
2061 completed on text consoles. The percentage is Value / Limit * 100%.\r
2062 \r
2063 @param Value Value in the range 0..Limit the the repair has completed..\r
2064 @param Limit The maximum value of Value\r
2065\r
2066**/\r
2067VOID\r
2068RepairNotify (\r
2069 IN UINTN Value,\r
2070 IN UINTN Limit\r
2071 )\r
2072{\r
2073 UINTN Percent;\r
2074\r
2075 if (Limit == 0) {\r
2076 Print(L"Repair Progress Undefined\n\r");\r
2077 } else {\r
2078 Percent = Value * 100 / Limit;\r
2079 Print(L"Repair Progress = %3d%%\n\r", Percent);\r
2080 }\r
2081}\r
2082\r
2083/**\r
2084 Processes a set of messages returned by the GetHealthStatus ()\r
2085 service of the EFI Driver Health Protocol\r
2086\r
2087 @param MessageList The MessageList point to messages need to processed. \r
2088\r
2089**/\r
2090VOID\r
2091ProcessMessages (\r
2092 IN EFI_DRIVER_HEALTH_HII_MESSAGE *MessageList\r
2093 )\r
2094{\r
2095 UINTN MessageIndex;\r
2096 EFI_STRING MessageString;\r
2097\r
2098 for (MessageIndex = 0;\r
2099 MessageList[MessageIndex].HiiHandle != NULL;\r
2100 MessageIndex++) {\r
2101\r
2102 MessageString = HiiGetString (\r
2103 MessageList[MessageIndex].HiiHandle,\r
2104 MessageList[MessageIndex].StringId,\r
2105 NULL\r
2106 );\r
2107 if (MessageString != NULL) {\r
2108 //\r
2109 // User can customize the output. Just simply print out the MessageString like below. \r
2110 // Also can use the HiiHandle to display message on the front page.\r
2111 // \r
2112 // Print(L"%s\n",MessageString);\r
2113 // gBS->Stall (100000);\r
2114 }\r
2115 }\r
2116\r
2117}\r
2118\r
8e8ae2da 2119/**\r
ab4da126 2120 Repair the whole platform.\r
2121\r
2122 This function is the main entry for user choose "Repair All" in the front page.\r
2123 It will try to do recovery job till all the driver health protocol installed modules \r
2124 reach a terminal state.\r
2125\r
2126 @param DriverHealthList A Pointer to the list contain all of the platform driver health\r
2127 information.\r
2128\r
8e8ae2da 2129**/\r
ab4da126 2130VOID\r
2131PlatformRepairAll (\r
2132 IN LIST_ENTRY *DriverHealthList\r
2133 )\r
2134{ \r
2135 DRIVER_HEALTH_INFO *DriverHealthInfo;\r
2136 LIST_ENTRY *Link;\r
2fde83b1 2137 BOOLEAN RebootRequired;\r
ab4da126 2138\r
2139 ASSERT (DriverHealthList != NULL);\r
2140\r
2fde83b1 2141 RebootRequired = FALSE;\r
ab4da126 2142\r
2fde83b1
RN
2143 for ( Link = GetFirstNode (DriverHealthList)\r
2144 ; !IsNull (DriverHealthList, Link)\r
2145 ; Link = GetNextNode (DriverHealthList, Link)\r
2146 ) {\r
ab4da126 2147 DriverHealthInfo = DEVICE_MANAGER_HEALTH_INFO_FROM_LINK (Link);\r
2148 //\r
2149 // Do driver health status operation by each link node\r
2150 //\r
2151 ASSERT (DriverHealthInfo != NULL);\r
2152\r
2153 ProcessSingleControllerHealth ( \r
2fde83b1
RN
2154 DriverHealthInfo->DriverHealth,\r
2155 DriverHealthInfo->ControllerHandle,\r
2156 DriverHealthInfo->ChildHandle,\r
2157 DriverHealthInfo->HealthStatus,\r
2158 &(DriverHealthInfo->MessageList),\r
2159 DriverHealthInfo->HiiHandle,\r
2160 &RebootRequired\r
2161 );\r
2162 }\r
ab4da126 2163\r
2fde83b1
RN
2164 if (RebootRequired) {\r
2165 gRT->ResetSystem (EfiResetWarm, EFI_SUCCESS, 0, NULL);\r
ab4da126 2166 }\r
2167}\r
2168\r
2169/**\r
2170\r
2171 Select the best matching language according to front page policy for best user experience. \r
2172 \r
2173 This function supports both ISO 639-2 and RFC 4646 language codes, but language \r
2174 code types may not be mixed in a single call to this function. \r
2175\r
2176 @param SupportedLanguages A pointer to a Null-terminated ASCII string that\r
2177 contains a set of language codes in the format \r
2178 specified by Iso639Language.\r
2179 @param Iso639Language If TRUE, then all language codes are assumed to be\r
2180 in ISO 639-2 format. If FALSE, then all language\r
2181 codes are assumed to be in RFC 4646 language format.\r
2182\r
2183 @retval NULL The best matching language could not be found in SupportedLanguages.\r
2184 @retval NULL There are not enough resources available to return the best matching \r
2185 language.\r
2186 @retval Other A pointer to a Null-terminated ASCII string that is the best matching \r
2187 language in SupportedLanguages.\r
2188**/\r
2189CHAR8 *\r
2190DriverHealthSelectBestLanguage (\r
2191 IN CHAR8 *SupportedLanguages,\r
2192 IN BOOLEAN Iso639Language\r
2193 )\r
2194{\r
2195 CHAR8 *LanguageVariable;\r
2196 CHAR8 *BestLanguage;\r
2197\r
2198 LanguageVariable = GetEfiGlobalVariable (Iso639Language ? L"Lang" : L"PlatformLang");\r
2199\r
2200 BestLanguage = GetBestLanguage(\r
2201 SupportedLanguages,\r
2202 Iso639Language,\r
2203 (LanguageVariable != NULL) ? LanguageVariable : "",\r
2204 Iso639Language ? "eng" : "en-US",\r
2205 NULL\r
2206 );\r
2207 if (LanguageVariable != NULL) {\r
2208 FreePool (LanguageVariable);\r
2209 }\r
2210\r
2211 return BestLanguage;\r
2212}\r
2213\r
2214\r
2215\r
2216/**\r
2217\r
2218 This is an internal worker function to get the Component Name (2) protocol interface\r
2219 and the language it supports.\r
2220\r
2221 @param ProtocolGuid A pointer to an EFI_GUID. It points to Component Name (2) protocol GUID.\r
2222 @param DriverBindingHandle The handle on which the Component Name (2) protocol instance is retrieved.\r
2223 @param ComponentName A pointer to the Component Name (2) protocol interface.\r
2224 @param SupportedLanguage The best suitable language that matches the SupportedLangues interface for the \r
2225 located Component Name (2) instance.\r
2226\r
8e8ae2da 2227 @retval EFI_SUCCESS The Component Name (2) protocol instance is successfully located and we find\r
ab4da126 2228 the best matching language it support.\r
8e8ae2da 2229 @retval EFI_UNSUPPORTED The input Language is not supported by the Component Name (2) protocol.\r
2230 @retval Other Some error occurs when locating Component Name (2) protocol instance or finding\r
ab4da126 2231 the supported language.\r
2232\r
2233**/\r
2234EFI_STATUS\r
2235GetComponentNameWorker (\r
2236 IN EFI_GUID *ProtocolGuid,\r
2237 IN EFI_HANDLE DriverBindingHandle,\r
2238 OUT EFI_COMPONENT_NAME_PROTOCOL **ComponentName,\r
2239 OUT CHAR8 **SupportedLanguage\r
2240 )\r
2241{\r
2242 EFI_STATUS Status;\r
2243\r
2244 //\r
2245 // Locate Component Name (2) protocol on the driver binging handle.\r
2246 //\r
2247 Status = gBS->OpenProtocol (\r
2248 DriverBindingHandle,\r
2249 ProtocolGuid,\r
2250 (VOID **) ComponentName,\r
2251 NULL,\r
2252 NULL,\r
2253 EFI_OPEN_PROTOCOL_GET_PROTOCOL\r
2254 );\r
2255 if (EFI_ERROR (Status)) {\r
2256 return Status;\r
2257 }\r
2258\r
2259 //\r
2260 // Apply shell policy to select the best language.\r
2261 //\r
2262 *SupportedLanguage = DriverHealthSelectBestLanguage (\r
2263 (*ComponentName)->SupportedLanguages,\r
2264 (BOOLEAN) (ProtocolGuid == &gEfiComponentNameProtocolGuid)\r
2265 );\r
2266 if (*SupportedLanguage == NULL) {\r
2267 Status = EFI_UNSUPPORTED;\r
2268 }\r
2269\r
2270 return Status;\r
2271}\r
2272\r
2273/**\r
2274\r
2275 This is an internal worker function to get driver name from Component Name (2) protocol interface.\r
2276\r
2277\r
2278 @param ProtocolGuid A pointer to an EFI_GUID. It points to Component Name (2) protocol GUID.\r
2279 @param DriverBindingHandle The handle on which the Component Name (2) protocol instance is retrieved.\r
2280 @param DriverName A pointer to the Unicode string to return. This Unicode string is the name\r
2281 of the driver specified by This.\r
2282\r
2283 @retval EFI_SUCCESS The driver name is successfully retrieved from Component Name (2) protocol\r
2284 interface.\r
2285 @retval Other The driver name cannot be retrieved from Component Name (2) protocol\r
2286 interface.\r
2287\r
2288**/\r
2289EFI_STATUS\r
2290GetDriverNameWorker (\r
2291 IN EFI_GUID *ProtocolGuid,\r
2292 IN EFI_HANDLE DriverBindingHandle,\r
2293 OUT CHAR16 **DriverName\r
2294 )\r
2295{\r
2296 EFI_STATUS Status;\r
2297 CHAR8 *BestLanguage;\r
2298 EFI_COMPONENT_NAME_PROTOCOL *ComponentName;\r
2299\r
2300 //\r
2301 // Retrieve Component Name (2) protocol instance on the driver binding handle and \r
2302 // find the best language this instance supports. \r
2303 //\r
2304 Status = GetComponentNameWorker (\r
2305 ProtocolGuid,\r
2306 DriverBindingHandle,\r
2307 &ComponentName,\r
2308 &BestLanguage\r
2309 );\r
2310 if (EFI_ERROR (Status)) {\r
2311 return Status;\r
2312 }\r
2313 \r
2314 //\r
2315 // Get the driver name from Component Name (2) protocol instance on the driver binging handle.\r
2316 //\r
2317 Status = ComponentName->GetDriverName (\r
2318 ComponentName,\r
2319 BestLanguage,\r
2320 DriverName\r
2321 );\r
2322 FreePool (BestLanguage);\r
2323 \r
2324 return Status;\r
2325}\r
2326\r
2327/**\r
2328\r
2329 This function gets driver name from Component Name 2 protocol interface and Component Name protocol interface\r
2330 in turn. It first tries UEFI 2.0 Component Name 2 protocol interface and try to get the driver name.\r
2331 If the attempt fails, it then gets the driver name from EFI 1.1 Component Name protocol for backward\r
2332 compatibility support. \r
2333\r
2334 @param DriverBindingHandle The handle on which the Component Name (2) protocol instance is retrieved.\r
2335 @param DriverName A pointer to the Unicode string to return. This Unicode string is the name\r
2336 of the driver specified by This.\r
2337\r
2338 @retval EFI_SUCCESS The driver name is successfully retrieved from Component Name (2) protocol\r
2339 interface.\r
2340 @retval Other The driver name cannot be retrieved from Component Name (2) protocol\r
2341 interface.\r
2342\r
2343**/\r
2344EFI_STATUS\r
2345DriverHealthGetDriverName (\r
2346 IN EFI_HANDLE DriverBindingHandle,\r
2347 OUT CHAR16 **DriverName\r
2348 )\r
2349{\r
2350 EFI_STATUS Status;\r
2351\r
2352 //\r
2353 // Get driver name from UEFI 2.0 Component Name 2 protocol interface.\r
2354 //\r
2355 Status = GetDriverNameWorker (&gEfiComponentName2ProtocolGuid, DriverBindingHandle, DriverName);\r
2356 if (EFI_ERROR (Status)) {\r
2357 //\r
2358 // If it fails to get the driver name from Component Name protocol interface, we should fall back on\r
2359 // EFI 1.1 Component Name protocol interface.\r
2360 //\r
2361 Status = GetDriverNameWorker (&gEfiComponentNameProtocolGuid, DriverBindingHandle, DriverName);\r
2362 }\r
2363\r
2364 return Status;\r
2365}\r
2366\r
2367\r
2368\r
2369/**\r
2370 This function gets controller name from Component Name 2 protocol interface and Component Name protocol interface\r
2371 in turn. It first tries UEFI 2.0 Component Name 2 protocol interface and try to get the controller name.\r
2372 If the attempt fails, it then gets the controller name from EFI 1.1 Component Name protocol for backward\r
2373 compatibility support. \r
2374\r
2375 @param ProtocolGuid A pointer to an EFI_GUID. It points to Component Name (2) protocol GUID.\r
2376 @param DriverBindingHandle The handle on which the Component Name (2) protocol instance is retrieved.\r
2377 @param ControllerHandle The handle of a controller that the driver specified by This is managing.\r
2378 This handle specifies the controller whose name is to be returned.\r
2379 @param ChildHandle The handle of the child controller to retrieve the name of. This is an\r
2380 optional parameter that may be NULL. It will be NULL for device drivers.\r
2381 It will also be NULL for bus drivers that attempt to retrieve the name\r
2382 of the bus controller. It will not be NULL for a bus driver that attempts\r
2383 to retrieve the name of a child controller.\r
2384 @param ControllerName A pointer to the Unicode string to return. This Unicode string\r
2385 is the name of the controller specified by ControllerHandle and ChildHandle.\r
2386\r
2387 @retval EFI_SUCCESS The controller name is successfully retrieved from Component Name (2) protocol\r
2388 interface.\r
2389 @retval Other The controller name cannot be retrieved from Component Name (2) protocol.\r
2390\r
2391**/\r
2392EFI_STATUS\r
2393GetControllerNameWorker (\r
2394 IN EFI_GUID *ProtocolGuid,\r
2395 IN EFI_HANDLE DriverBindingHandle,\r
2396 IN EFI_HANDLE ControllerHandle,\r
2397 IN EFI_HANDLE ChildHandle,\r
2398 OUT CHAR16 **ControllerName\r
2399 )\r
2400{\r
2401 EFI_STATUS Status;\r
2402 CHAR8 *BestLanguage;\r
2403 EFI_COMPONENT_NAME_PROTOCOL *ComponentName;\r
2404\r
2405 //\r
2406 // Retrieve Component Name (2) protocol instance on the driver binding handle and \r
2407 // find the best language this instance supports. \r
2408 //\r
2409 Status = GetComponentNameWorker (\r
2410 ProtocolGuid,\r
2411 DriverBindingHandle,\r
2412 &ComponentName,\r
2413 &BestLanguage\r
2414 );\r
2415 if (EFI_ERROR (Status)) {\r
2416 return Status;\r
2417 }\r
2418\r
2419 //\r
2420 // Get the controller name from Component Name (2) protocol instance on the driver binging handle.\r
2421 //\r
2422 Status = ComponentName->GetControllerName (\r
2423 ComponentName,\r
2424 ControllerHandle,\r
2425 ChildHandle,\r
2426 BestLanguage,\r
2427 ControllerName\r
2428 );\r
2429 FreePool (BestLanguage);\r
2430\r
2431 return Status;\r
2432}\r
2433\r
2434/**\r
2435\r
2436 This function gets controller name from Component Name 2 protocol interface and Component Name protocol interface\r
2437 in turn. It first tries UEFI 2.0 Component Name 2 protocol interface and try to get the controller name. \r
2438 If the attempt fails, it then gets the controller name from EFI 1.1 Component Name protocol for backward\r
2439 compatibility support. \r
2440\r
2441 @param DriverBindingHandle The handle on which the Component Name (2) protocol instance is retrieved.\r
2442 @param ControllerHandle The handle of a controller that the driver specified by This is managing.\r
2443 This handle specifies the controller whose name is to be returned.\r
2444 @param ChildHandle The handle of the child controller to retrieve the name of. This is an\r
2445 optional parameter that may be NULL. It will be NULL for device drivers.\r
2446 It will also be NULL for bus drivers that attempt to retrieve the name\r
2447 of the bus controller. It will not be NULL for a bus driver that attempts\r
2448 to retrieve the name of a child controller.\r
ab4da126 2449 @param ControllerName A pointer to the Unicode string to return. This Unicode string\r
2450 is the name of the controller specified by ControllerHandle and ChildHandle.\r
2451\r
2452 @retval EFI_SUCCESS The controller name is successfully retrieved from Component Name (2) protocol\r
2453 interface.\r
2454 @retval Other The controller name cannot be retrieved from Component Name (2) protocol.\r
2455\r
2456**/\r
2457EFI_STATUS\r
2458DriverHealthGetControllerName (\r
2459 IN EFI_HANDLE DriverBindingHandle,\r
2460 IN EFI_HANDLE ControllerHandle,\r
2461 IN EFI_HANDLE ChildHandle,\r
2462 OUT CHAR16 **ControllerName\r
2463 )\r
2464{\r
2465 EFI_STATUS Status;\r
2466\r
2467 //\r
2468 // Get controller name from UEFI 2.0 Component Name 2 protocol interface.\r
2469 //\r
2470 Status = GetControllerNameWorker (\r
2471 &gEfiComponentName2ProtocolGuid,\r
2472 DriverBindingHandle,\r
2473 ControllerHandle,\r
2474 ChildHandle,\r
2475 ControllerName\r
2476 );\r
2477 if (EFI_ERROR (Status)) {\r
2478 //\r
2479 // If it fails to get the controller name from Component Name protocol interface, we should fall back on\r
2480 // EFI 1.1 Component Name protocol interface.\r
2481 //\r
2482 Status = GetControllerNameWorker (\r
2483 &gEfiComponentNameProtocolGuid,\r
2484 DriverBindingHandle,\r
2485 ControllerHandle,\r
2486 ChildHandle,\r
2487 ControllerName\r
2488 );\r
2489 }\r
2490\r
2491 return Status;\r
2492}\r