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