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