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