]> git.proxmox.com Git - mirror_edk2.git/blame_incremental - IntelFrameworkModulePkg/Universal/BdsDxe/DeviceMngr/DeviceManager.c
IntelFrameworkModulePkg: Replace BSD License with BSD+Patent License
[mirror_edk2.git] / IntelFrameworkModulePkg / Universal / BdsDxe / DeviceMngr / DeviceManager.c
... / ...
CommitLineData
1/** @file\r
2 The platform device manager reference implementation\r
3\r
4Copyright (c) 2004 - 2018, Intel Corporation. All rights reserved.<BR>\r
5SPDX-License-Identifier: BSD-2-Clause-Patent\r
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
15 NULL,\r
16 NULL,\r
17 {\r
18 FakeExtractConfig,\r
19 FakeRouteConfig,\r
20 DeviceManagerCallback\r
21 },\r
22 {\r
23 FakeExtractConfig,\r
24 FakeRouteConfig,\r
25 DriverHealthCallback\r
26 }\r
27};\r
28\r
29#define MAX_MAC_ADDRESS_NODE_LIST_LEN 10\r
30\r
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
40EFI_FORM_ID mNextShowFormId = DEVICE_MANAGER_FORM_ID;\r
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
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
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
66 DEVICE_MANAGER_FORMSET_GUID\r
67 },\r
68 {\r
69 END_DEVICE_PATH_TYPE,\r
70 END_ENTIRE_DEVICE_PATH_SUBTYPE,\r
71 {\r
72 (UINT8) (END_DEVICE_PATH_LENGTH),\r
73 (UINT8) ((END_DEVICE_PATH_LENGTH) >> 8)\r
74 }\r
75 }\r
76};\r
77\r
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
88 DRIVER_HEALTH_FORMSET_GUID\r
89 },\r
90 {\r
91 END_DEVICE_PATH_TYPE,\r
92 END_ENTIRE_DEVICE_PATH_SUBTYPE,\r
93 {\r
94 (UINT8) (END_DEVICE_PATH_LENGTH),\r
95 (UINT8) ((END_DEVICE_PATH_LENGTH) >> 8)\r
96 }\r
97 }\r
98};\r
99\r
100/**\r
101 This function is invoked if user selected a interactive opcode from Device Manager's\r
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
128 UINTN CurIndex;\r
129\r
130 if (Action != EFI_BROWSER_ACTION_CHANGING) {\r
131 //\r
132 // All other action return unsupported.\r
133 //\r
134 return EFI_UNSUPPORTED;\r
135 }\r
136\r
137 if (Value == NULL) {\r
138 return EFI_INVALID_PARAMETER;\r
139 }\r
140\r
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
154}\r
155\r
156/**\r
157\r
158 This function registers HII packages to HII database.\r
159\r
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
162\r
163**/\r
164EFI_STATUS\r
165InitializeDeviceManager (\r
166 VOID\r
167 )\r
168{\r
169 EFI_STATUS Status;\r
170\r
171 //\r
172 // Install Device Path Protocol and Config Access protocol to driver handle\r
173 //\r
174 Status = gBS->InstallMultipleProtocolInterfaces (\r
175 &gDeviceManagerPrivate.DriverHandle,\r
176 &gEfiDevicePathProtocolGuid,\r
177 &mDeviceManagerHiiVendorDevicePath,\r
178 &gEfiHiiConfigAccessProtocolGuid,\r
179 &gDeviceManagerPrivate.ConfigAccess,\r
180 NULL\r
181 );\r
182 ASSERT_EFI_ERROR (Status);\r
183\r
184 Status = gBS->InstallMultipleProtocolInterfaces (\r
185 &gDeviceManagerPrivate.DriverHealthHandle,\r
186 &gEfiDevicePathProtocolGuid,\r
187 &mDriverHealthHiiVendorDevicePath,\r
188 &gEfiHiiConfigAccessProtocolGuid,\r
189 &gDeviceManagerPrivate.DriverHealthConfigAccess,\r
190 NULL\r
191 );\r
192 ASSERT_EFI_ERROR (Status);\r
193\r
194 mMacDeviceList.CurListLen = 0;\r
195 mMacDeviceList.MaxListLen = 0;\r
196\r
197 return Status;\r
198}\r
199\r
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
205 @param SkipCount Skip some formsets which has processed before.\r
206 @param FormSetTitle Formset title string.\r
207 @param FormSetHelp Formset help string.\r
208 @param FormSetGuid Return the formset guid for this formset.\r
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
218 IN UINTN SkipCount,\r
219 OUT EFI_STRING_ID *FormSetTitle,\r
220 OUT EFI_STRING_ID *FormSetHelp,\r
221 OUT EFI_GUID **FormSetGuid\r
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
237 ASSERT (SetupClassGuid != NULL);\r
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
260\r
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
287 Offset2 += ((EFI_IFR_OP_HEADER *) OpCodeData)->Length;\r
288\r
289 if (((EFI_IFR_OP_HEADER *) OpCodeData)->OpCode == EFI_IFR_FORM_SET_OP) {\r
290 if (SkipCount != 0) {\r
291 SkipCount --;\r
292 continue;\r
293 }\r
294\r
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
299 ClassGuidNum = (UINT8) (((EFI_IFR_FORM_SET *) OpCodeData)->Flags & 0x3);\r
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
305 *FormSetGuid = AllocateCopyPool (sizeof (EFI_GUID), &((EFI_IFR_FORM_SET *) OpCodeData)->Guid);\r
306 ASSERT (*FormSetGuid != NULL);\r
307 FreePool (HiiPackageList);\r
308 return TRUE;\r
309 }\r
310 ClassGuid ++;\r
311 }\r
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
315 *FormSetGuid = AllocateCopyPool (sizeof (EFI_GUID), &((EFI_IFR_FORM_SET *) OpCodeData)->Guid);\r
316 ASSERT (*FormSetGuid != NULL);\r
317 FreePool (HiiPackageList);\r
318 return TRUE;\r
319 }\r
320 }\r
321 }\r
322 }\r
323\r
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
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
338\r
339 @param MacAddressNode Device path begin with mac address\r
340 @param PBuffer Output string buffer contain mac address.\r
341\r
342**/\r
343BOOLEAN\r
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
371 String = AllocateZeroPool (BufferLen);\r
372 if (String == NULL) {\r
373 return FALSE;\r
374 }\r
375\r
376 *PBuffer = String;\r
377 StrCpyS (String, BufferLen / sizeof (CHAR16), L"MAC:");\r
378 String += 4;\r
379\r
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
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
393 if (Index < HwAddressSize - 1) {\r
394 *String++ = L':';\r
395 }\r
396 }\r
397\r
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
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
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
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
439BOOLEAN\r
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
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
482 } else {\r
483 TempDeviceList = (MENU_INFO_ITEM *)AllocatePool (sizeof (MENU_INFO_ITEM) * mMacDeviceList.MaxListLen);\r
484 }\r
485\r
486 if (TempDeviceList == NULL) {\r
487 return FALSE;\r
488 }\r
489 TempDeviceList[mMacDeviceList.CurListLen].PromptId = PromptId;\r
490 TempDeviceList[mMacDeviceList.CurListLen].QuestionId = (EFI_QUESTION_ID) (mMacDeviceList.CurListLen + NETWORK_DEVICE_LIST_KEY_OFFSET);\r
491\r
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
508\r
509 @retval TRUE Has mac address device path.\r
510 @retval FALSE NOT Has mac address device path.\r
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
522\r
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
537\r
538 if (DEVICE_MANAGER_FORM_ID == mNextShowFormId) {\r
539 *NeedAddItem = TRUE;\r
540 break;\r
541 }\r
542\r
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
556 // Same handle may has two network child handle, so the questionid\r
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
564 }\r
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
585BOOLEAN\r
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
593 UINTN Index;\r
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
602 IsNeedAdd = FALSE;\r
603 OpenInfoBuffer = NULL;\r
604 if ((Handle == NULL) || (ItemCount == NULL)) {\r
605 return FALSE;\r
606 }\r
607 *ItemCount = 0;\r
608\r
609 Status = gHiiDatabase->GetPackageListHandle (gHiiDatabase, Handle, &DriverHandle);\r
610 if (EFI_ERROR (Status)) {\r
611 return FALSE;\r
612 }\r
613 //\r
614 // Get the device path by the got Driver handle .\r
615 //\r
616 Status = gBS->HandleProtocol (DriverHandle, &gEfiDevicePathProtocolGuid, (VOID **) &DevicePath);\r
617 if (EFI_ERROR (Status)) {\r
618 return FALSE;\r
619 }\r
620 TmpDevicePath = DevicePath;\r
621\r
622 //\r
623 // Check whether this device path include mac address device path.\r
624 // If this path has mac address path, get the value whether need\r
625 // add this info to the menu and return.\r
626 // Else check more about the child handle devcie path.\r
627 //\r
628 if (IsMacAddressDevicePath(TmpDevicePath, &IsNeedAdd)) {\r
629 if ((NETWORK_DEVICE_LIST_FORM_ID == mNextShowFormId) && IsNeedAdd) {\r
630 (*ItemCount) = 1;\r
631 }\r
632 return IsNeedAdd;\r
633 }\r
634\r
635 //\r
636 // Search whether this path is the controller path, not he child handle path.\r
637 // And the child handle has the network devcie connected.\r
638 //\r
639 TmpDevicePath = DevicePath;\r
640 Status = gBS->LocateDevicePath(&gEfiDevicePathProtocolGuid, &TmpDevicePath, &ControllerHandle);\r
641 if (EFI_ERROR (Status)) {\r
642 return FALSE;\r
643 }\r
644\r
645 if (!IsDevicePathEnd (TmpDevicePath)) {\r
646 return FALSE;\r
647 }\r
648\r
649 //\r
650 // Retrieve the list of agents that are consuming the specific protocol\r
651 // on ControllerHandle.\r
652 // The buffer point by OpenInfoBuffer need be free at this function.\r
653 //\r
654 Status = gBS->OpenProtocolInformation (\r
655 ControllerHandle,\r
656 &gEfiPciIoProtocolGuid,\r
657 &OpenInfoBuffer,\r
658 &EntryCount\r
659 );\r
660 if (EFI_ERROR (Status)) {\r
661 return FALSE;\r
662 }\r
663\r
664 //\r
665 // Inspect if ChildHandle is one of the agents.\r
666 //\r
667 Status = EFI_UNSUPPORTED;\r
668 for (Index = 0; Index < EntryCount; Index++) {\r
669 //\r
670 // Query all the children created by the controller handle's driver\r
671 //\r
672 if ((OpenInfoBuffer[Index].Attributes & EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER) != 0) {\r
673 Status = gBS->OpenProtocol (\r
674 OpenInfoBuffer[Index].ControllerHandle,\r
675 &gEfiDevicePathProtocolGuid,\r
676 (VOID **) &ChildDevicePath,\r
677 NULL,\r
678 NULL,\r
679 EFI_OPEN_PROTOCOL_GET_PROTOCOL\r
680 );\r
681 if (EFI_ERROR (Status)) {\r
682 continue;\r
683 }\r
684\r
685 //\r
686 // Check whether this device path include mac address device path.\r
687 //\r
688 if (!IsMacAddressDevicePath(ChildDevicePath, &IsNeedAdd)) {\r
689 //\r
690 // If this path not has mac address path, check the other.\r
691 //\r
692 continue;\r
693 } else {\r
694 //\r
695 // If need to update the NETWORK_DEVICE_LIST_FORM, try to get more.\r
696 //\r
697 if ((NETWORK_DEVICE_LIST_FORM_ID == mNextShowFormId)) {\r
698 if (IsNeedAdd) {\r
699 (*ItemCount) += 1;\r
700 }\r
701 continue;\r
702 } else {\r
703 //\r
704 // If need to update other form, return whether need to add to the menu.\r
705 //\r
706 goto Done;\r
707 }\r
708 }\r
709 }\r
710 }\r
711\r
712Done:\r
713 if (OpenInfoBuffer != NULL) {\r
714 FreePool (OpenInfoBuffer);\r
715 }\r
716 return IsNeedAdd;\r
717}\r
718\r
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
746 @param Offset The current used HiiHandle's Offset.\r
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
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
790\r
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
802 UINTN Index;\r
803 EFI_STRING String;\r
804 EFI_STRING_ID Token;\r
805 EFI_STRING_ID TokenHelp;\r
806 EFI_HII_HANDLE *HiiHandles;\r
807 EFI_HII_HANDLE HiiHandle;\r
808 EFI_STRING_ID FormSetTitle;\r
809 EFI_STRING_ID FormSetHelp;\r
810 EFI_BROWSER_ACTION_REQUEST ActionRequest;\r
811 VOID *StartOpCodeHandle;\r
812 VOID *EndOpCodeHandle;\r
813 EFI_IFR_GUID_LABEL *StartLabel;\r
814 EFI_IFR_GUID_LABEL *EndLabel;\r
815 UINTN NumHandles;\r
816 EFI_HANDLE *DriverHealthHandles;\r
817 BOOLEAN AddNetworkMenu;\r
818 UINTN AddItemCount;\r
819 UINTN NewStringLen;\r
820 EFI_STRING NewStringTitle;\r
821 EFI_GUID **GuidLists;\r
822 UINTN HandleNum;\r
823 UINTN SkipCount;\r
824 EFI_GUID *FormSetGuid;\r
825\r
826 GuidLists = NULL;\r
827 HiiHandles = NULL;\r
828 Status = EFI_SUCCESS;\r
829 gCallbackKey = 0;\r
830 NumHandles = 0;\r
831 DriverHealthHandles = NULL;\r
832 AddNetworkMenu = FALSE;\r
833 AddItemCount = 0;\r
834 SkipCount = 0;\r
835 FormSetGuid = NULL;\r
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
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
851 &gDeviceManagerFormSetGuid,\r
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
864 //\r
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
871 //\r
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
876 NewStringLen = StrLen(mSelectedMacAddrString) * 2;\r
877 NewStringLen += (StrLen(String) + 2) * 2;\r
878 NewStringTitle = AllocatePool (NewStringLen);\r
879 UnicodeSPrint (NewStringTitle, NewStringLen, L"%s %s", String, mSelectedMacAddrString);\r
880 HiiSetString (HiiHandle, STRING_TOKEN (STR_FORM_NETWORK_DEVICE_TITLE), NewStringTitle, NULL);\r
881 FreePool (String);\r
882 FreePool (NewStringTitle);\r
883 }\r
884\r
885 //\r
886 // Allocate space for creation of UpdateData Buffer\r
887 //\r
888 StartOpCodeHandle = HiiAllocateOpCodeHandle ();\r
889 ASSERT (StartOpCodeHandle != NULL);\r
890\r
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
899 //\r
900 // According to the next show Form id(mNextShowFormId) to decide which form need to update.\r
901 //\r
902 StartLabel->Number = (UINT16) (LABEL_FORM_ID_OFFSET + mNextShowFormId);\r
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
911 //\r
912 // Get all the Hii handles\r
913 //\r
914 HiiHandles = HiiGetHiiHandles (NULL);\r
915 ASSERT (HiiHandles != NULL);\r
916\r
917 HandleNum = GetHiiHandleCount (HiiHandles);\r
918 GuidLists = AllocateZeroPool ((HandleNum + 1) * sizeof (EFI_GUID *));\r
919 ASSERT (GuidLists != NULL);\r
920\r
921 //\r
922 // Search for formset of each class type\r
923 //\r
924 for (Index = 0; HiiHandles[Index] != NULL; Index++) {\r
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
932 if (!ExtractDisplayedHiiFormFromHiiHandle (HiiHandles[Index], &gEfiHiiPlatformSetupFormsetGuid, SkipCount, &FormSetTitle, &FormSetHelp, &FormSetGuid)) {\r
933 SkipCount = 0;\r
934 continue;\r
935 }\r
936\r
937 //\r
938 // One HiiHandle has more than one formset can be shown,\r
939 // Insert a new pair of HiiHandle + Guid to the HiiHandles and GuidLists list.\r
940 //\r
941 if (SkipCount > 0) {\r
942 AdjustArrayData (&HiiHandles, &GuidLists, HandleNum, Index + 1, FormSetGuid);\r
943 HandleNum ++;\r
944 Index ++;\r
945 }\r
946\r
947 String = HiiGetString (HiiHandles[Index], FormSetTitle, NULL);\r
948 if (String == NULL) {\r
949 String = HiiGetString (HiiHandle, STR_MISSING_STRING, NULL);\r
950 ASSERT (String != NULL);\r
951 }\r
952 Token = HiiSetString (HiiHandle, 0, String, NULL);\r
953 FreePool (String);\r
954\r
955 String = HiiGetString (HiiHandles[Index], FormSetHelp, NULL);\r
956 if (String == NULL) {\r
957 String = HiiGetString (HiiHandle, STR_MISSING_STRING, NULL);\r
958 ASSERT (String != NULL);\r
959 }\r
960 TokenHelp = HiiSetString (HiiHandle, 0, String, NULL);\r
961 FreePool (String);\r
962\r
963 //\r
964 // Network device process\r
965 //\r
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
973 HiiCreateGotoOpCode (\r
974 StartOpCodeHandle,\r
975 INVALID_FORM_ID,\r
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
979 (EFI_QUESTION_ID) QUESTION_NETWORK_DEVICE_ID\r
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
987 HiiCreateGotoOpCode (\r
988 StartOpCodeHandle,\r
989 INVALID_FORM_ID,\r
990 mMacDeviceList.NodeList[mMacDeviceList.CurListLen - AddItemCount].PromptId,\r
991 STRING_TOKEN (STR_NETWORK_DEVICE_HELP),\r
992 EFI_IFR_FLAG_CALLBACK,\r
993 mMacDeviceList.NodeList[mMacDeviceList.CurListLen - AddItemCount].QuestionId\r
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
1001 HiiCreateGotoOpCode (\r
1002 StartOpCodeHandle,\r
1003 INVALID_FORM_ID,\r
1004 Token,\r
1005 TokenHelp,\r
1006 EFI_IFR_FLAG_CALLBACK,\r
1007 (EFI_QUESTION_ID) (Index + DEVICE_KEY_OFFSET)\r
1008 );\r
1009 }\r
1010 } else {\r
1011 //\r
1012 //\r
1013 // Not network device process, only need to show at device manger form.\r
1014 //\r
1015 if (mNextShowFormId == DEVICE_MANAGER_FORM_ID) {\r
1016 HiiCreateGotoOpCode (\r
1017 StartOpCodeHandle,\r
1018 INVALID_FORM_ID,\r
1019 Token,\r
1020 TokenHelp,\r
1021 EFI_IFR_FLAG_CALLBACK,\r
1022 (EFI_QUESTION_ID) (Index + DEVICE_KEY_OFFSET)\r
1023 );\r
1024 }\r
1025 }\r
1026\r
1027 //\r
1028 // Try to find more formset in this HiiHandle.\r
1029 //\r
1030 SkipCount++;\r
1031 Index--;\r
1032 }\r
1033\r
1034 Status = gBS->LocateHandleBuffer (\r
1035 ByProtocol,\r
1036 &gEfiDriverHealthProtocolGuid,\r
1037 NULL,\r
1038 &NumHandles,\r
1039 &DriverHealthHandles\r
1040 );\r
1041\r
1042 //\r
1043 // If there are no drivers installed driver health protocol, do not create driver health entry in UI\r
1044 //\r
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
1050 HiiCreateGotoOpCode (\r
1051 StartOpCodeHandle,\r
1052 DRIVER_HEALTH_FORM_ID,\r
1053 STRING_TOKEN(STR_DRIVER_HEALTH_ALL_HEALTHY), // Prompt text\r
1054 STRING_TOKEN(STR_DRIVER_HEALTH_STATUS_HELP), // Help text\r
1055 EFI_IFR_FLAG_CALLBACK,\r
1056 DEVICE_MANAGER_KEY_DRIVER_HEALTH // Question ID\r
1057 );\r
1058\r
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
1075 HiiUpdateForm (\r
1076 HiiHandle,\r
1077 &gDeviceManagerFormSetGuid,\r
1078 mNextShowFormId,\r
1079 StartOpCodeHandle,\r
1080 EndOpCodeHandle\r
1081 );\r
1082\r
1083 ActionRequest = EFI_BROWSER_ACTION_REQUEST_NONE;\r
1084 Status = gFormBrowser2->SendForm (\r
1085 gFormBrowser2,\r
1086 &HiiHandle,\r
1087 1,\r
1088 &gDeviceManagerFormSetGuid,\r
1089 mNextShowFormId,\r
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
1098 // We will have returned from processing a callback, selected\r
1099 // a target to display\r
1100 //\r
1101 if ((gCallbackKey >= DEVICE_KEY_OFFSET)) {\r
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
1107 GuidLists[gCallbackKey - DEVICE_KEY_OFFSET],\r
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
1121 goto Done;\r
1122 }\r
1123\r
1124 //\r
1125 // Driver Health item chose.\r
1126 //\r
1127 if (gCallbackKey == DEVICE_MANAGER_KEY_DRIVER_HEALTH) {\r
1128 CallDriverHealth ();\r
1129 //\r
1130 // Force return to Device Manager\r
1131 //\r
1132 gCallbackKey = FRONT_PAGE_KEY_DEVICE_MANAGER;\r
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
1149 mNextShowFormId = NETWORK_DEVICE_FORM_ID;\r
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
1160 mNextShowFormId = (UINT16) (mNextShowFormId - 1);\r
1161 gCallbackKey = FRONT_PAGE_KEY_DEVICE_MANAGER;\r
1162 }\r
1163\r
1164Done:\r
1165 //\r
1166 // Remove our packagelist from HII database.\r
1167 //\r
1168 HiiRemovePackages (HiiHandle);\r
1169 gDeviceManagerPrivate.HiiHandle = NULL;\r
1170\r
1171 HiiFreeOpCodeHandle (StartOpCodeHandle);\r
1172 HiiFreeOpCodeHandle (EndOpCodeHandle);\r
1173 FreePool (HiiHandles);\r
1174\r
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
1182 return Status;\r
1183}\r
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
1212 if (Action == EFI_BROWSER_ACTION_CHANGED) {\r
1213 if ((Value == NULL) || (ActionRequest == NULL)) {\r
1214 return EFI_INVALID_PARAMETER;\r
1215 }\r
1216\r
1217 gCallbackKey = QuestionId;\r
1218\r
1219 //\r
1220 // Request to exit SendForm(), so as to switch to selected form\r
1221 //\r
1222 *ActionRequest = EFI_BROWSER_ACTION_REQUEST_EXIT;\r
1223\r
1224 return EFI_SUCCESS;\r
1225 }\r
1226\r
1227 //\r
1228 // All other action return unsupported.\r
1229 //\r
1230 return EFI_UNSUPPORTED;\r
1231}\r
1232\r
1233/**\r
1234 Collect and display the platform's driver health relative information, allow user to do interactive\r
1235 operation while the platform is unhealthy.\r
1236\r
1237 This function display a form which divided into two parts. The one list all modules which has installed\r
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
1248 EFI_STATUS Status;\r
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
1270 BOOLEAN RebootRequired;\r
1271 BOOLEAN IsControllerNameEmpty;\r
1272 UINTN StringSize;\r
1273\r
1274 Index = 0;\r
1275 DriverHealthInfo = NULL;\r
1276 DriverDevicePath = NULL;\r
1277 IsControllerNameEmpty = FALSE;\r
1278 InitializeListHead (&DriverHealthList);\r
1279\r
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
1286 &gDeviceManagerFormSetGuid,\r
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
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
1349 while (!IsNull (&DriverHealthList, Link)) {\r
1350 DriverHealthInfo = DEVICE_MANAGER_HEALTH_INFO_FROM_LINK (Link);\r
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
1360 StringSize = StrSize (DriverName);\r
1361\r
1362 Status = DriverHealthGetControllerName (\r
1363 DriverHealthInfo->DriverHandle,\r
1364 DriverHealthInfo->ControllerHandle,\r
1365 DriverHealthInfo->ChildHandle,\r
1366 &ControllerName\r
1367 );\r
1368\r
1369 if (!EFI_ERROR (Status)) {\r
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
1375 }\r
1376\r
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
1381 TmpString = HiiGetString (\r
1382 DriverHealthInfo->MessageList->HiiHandle,\r
1383 DriverHealthInfo->MessageList->StringId,\r
1384 NULL\r
1385 );\r
1386 ASSERT (TmpString != NULL);\r
1387\r
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
1393\r
1394 StrCpyS (String, StringSize / sizeof(CHAR16), DriverName);\r
1395 if (!IsControllerNameEmpty) {\r
1396 StrCatS (String, StringSize / sizeof(CHAR16), L" ");\r
1397 StrCatS (String, StringSize / sizeof(CHAR16), ControllerName);\r
1398 }\r
1399\r
1400 StrCatS (String, StringSize / sizeof(CHAR16), L" ");\r
1401 StrCatS (String, StringSize / sizeof(CHAR16), TmpString);\r
1402\r
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
1409 TmpString = GetStringById (STRING_TOKEN (STR_REPAIR_REQUIRED));\r
1410 break;\r
1411 case EfiDriverHealthStatusConfigurationRequired:\r
1412 TmpString = GetStringById (STRING_TOKEN (STR_CONFIGURATION_REQUIRED));\r
1413 break;\r
1414 case EfiDriverHealthStatusFailed:\r
1415 TmpString = GetStringById (STRING_TOKEN (STR_OPERATION_FAILED));\r
1416 break;\r
1417 case EfiDriverHealthStatusReconnectRequired:\r
1418 TmpString = GetStringById (STRING_TOKEN (STR_RECONNECT_REQUIRED));\r
1419 break;\r
1420 case EfiDriverHealthStatusRebootRequired:\r
1421 TmpString = GetStringById (STRING_TOKEN (STR_REBOOT_REQUIRED));\r
1422 break;\r
1423 default:\r
1424 TmpString = GetStringById (STRING_TOKEN (STR_DRIVER_HEALTH_HEALTHY));\r
1425 break;\r
1426 }\r
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
1433\r
1434 StrCpyS (String, StringSize / sizeof (CHAR16), DriverName);\r
1435 if (!IsControllerNameEmpty) {\r
1436 StrCatS (String, StringSize / sizeof (CHAR16), L" ");\r
1437 StrCatS (String, StringSize / sizeof (CHAR16), ControllerName);\r
1438 }\r
1439\r
1440 StrCatS (String, StringSize / sizeof (CHAR16), TmpString);\r
1441 }\r
1442\r
1443 FreePool (TmpString);\r
1444\r
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
1461\r
1462 //\r
1463 // Add End Opcode for Subtitle\r
1464 //\r
1465 HiiCreateEndOpCode (StartOpCodeHandle);\r
1466\r
1467 HiiCreateSubTitleOpCode (StartOpCodeHandleRepair, STRING_TOKEN (STR_DRIVER_HEALTH_REPAIR_ALL), 0, 0, 1);\r
1468 TokenHelp = HiiSetString (HiiHandle, 0, GetStringById( STRING_TOKEN (STR_DH_REPAIR_ALL_HELP)), NULL);\r
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
1502 &gDriverHealthFormSetGuid,\r
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
1512 &gDriverHealthFormSetGuid,\r
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
1525 &gDriverHealthFormSetGuid,\r
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
1538 //\r
1539 if (gCallbackKey >= DRIVER_HEALTH_KEY_OFFSET && gCallbackKey != DRIVER_HEALTH_REPAIR_ALL_KEY) {\r
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
1549 if (Index == (gCallbackKey - DRIVER_HEALTH_KEY_OFFSET)) {\r
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
1554 RebootRequired = FALSE;\r
1555 ProcessSingleControllerHealth (\r
1556 DriverHealthInfo->DriverHealth,\r
1557 DriverHealthInfo->ControllerHandle,\r
1558 DriverHealthInfo->ChildHandle,\r
1559 DriverHealthInfo->HealthStatus,\r
1560 &(DriverHealthInfo->MessageList),\r
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
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
1576\r
1577 //\r
1578 // Force return to the form of Driver Health in Device Manager\r
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
1588\r
1589 PlatformRepairAll (&DriverHealthList);\r
1590\r
1591 gCallbackKey = DRIVER_HEALTH_RETURN_KEY;\r
1592 }\r
1593\r
1594 //\r
1595 // Remove driver health packagelist from HII database.\r
1596 //\r
1597 HiiRemovePackages (HiiHandle);\r
1598 gDeviceManagerPrivate.DriverHealthHiiHandle = NULL;\r
1599\r
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
1612 }\r
1613 }\r
1614\r
1615 HiiFreeOpCodeHandle (StartOpCodeHandle);\r
1616 HiiFreeOpCodeHandle (EndOpCodeHandle);\r
1617 HiiFreeOpCodeHandle (StartOpCodeHandleRepair);\r
1618 HiiFreeOpCodeHandle (EndOpCodeHandleRepair);\r
1619\r
1620 if (gCallbackKey == DRIVER_HEALTH_RETURN_KEY) {\r
1621 //\r
1622 // Force return to Driver Health Form\r
1623 //\r
1624 gCallbackKey = DEVICE_MANAGER_KEY_DRIVER_HEALTH;\r
1625 CallDriverHealth ();\r
1626 }\r
1627}\r
1628\r
1629\r
1630/**\r
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
1636 @param DriverHealthList A Pointer to the list contain all of the platform driver health information.\r
1637 @param DriverHandle The handle of driver.\r
1638 @param ControllerHandle The class guid specifies which form set will be displayed.\r
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
1641 @param DriverHealth A pointer to the EFI_DRIVER_HEALTH_PROTOCOL instance.\r
1642 @param HealthStatus The health status of the controller.\r
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
1650**/\r
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
1737 DriverHealthInfo->Signature = DEVICE_MANAGER_DRIVER_HEALTH_INFO_SIGNATURE;\r
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
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
1755\r
1756 @param DriverHealthList A Pointer to the list contain all of the platform driver health\r
1757 information.\r
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
1769 EFI_STATUS Status;\r
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
1779\r
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
1807 // If the list of Driver Health Protocol handles can not be retrieved, then\r
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
1828 Status = gBS->HandleProtocol (\r
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
1855 // If all the controllers managed by this Driver Health Protocol are healthy, then skip to the next\r
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
1879 // If all the handles in the handle database can not be retrieved, then\r
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
1955/**\r
1956 Check the healthy status of the platform, this function will return immediately while found one driver\r
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
1962**/\r
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
1999 //\r
2000 AllHealthy = TRUE;\r
2001\r
2002 //\r
2003 // Found one or more Handles.\r
2004 //\r
2005 if (!EFI_ERROR (Status)) {\r
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
2030 return FALSE;\r
2031 }\r
2032 }\r
2033 }\r
2034 }\r
2035 return AllHealthy;\r
2036}\r
2037\r
2038/**\r
2039 Processes a single controller using the EFI Driver Health Protocol associated with\r
2040 that controller. This algorithm continues to query the GetHealthStatus() service until\r
2041 one of the legal terminal states of the EFI Driver Health Protocol is reached. This may\r
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
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
2048 @param HealthStatus The health status of the controller.\r
2049 @param MessageList An array of warning or error messages associated\r
2050 with the controller specified by ControllerHandle and\r
2051 ChildHandle. This is an optional parameter that may be NULL.\r
2052 @param FormHiiHandle The HII handle for an HII form associated with the\r
2053 controller specified by ControllerHandle and ChildHandle.\r
2054 @param RebootRequired Indicate whether a reboot is required to repair the controller.\r
2055**/\r
2056VOID\r
2057ProcessSingleControllerHealth (\r
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
2065 )\r
2066{\r
2067 EFI_STATUS Status;\r
2068 EFI_DRIVER_HEALTH_STATUS LocalHealthStatus;\r
2069\r
2070 LocalHealthStatus = HealthStatus;\r
2071 //\r
2072 // If the module need to be repaired or reconfiguration, will process it until\r
2073 // reach a terminal status. The status from EfiDriverHealthStatusRepairRequired after repair\r
2074 // will be in (Health, Failed, Configuration Required).\r
2075 //\r
2076 while(LocalHealthStatus == EfiDriverHealthStatusConfigurationRequired ||\r
2077 LocalHealthStatus == EfiDriverHealthStatusRepairRequired) {\r
2078\r
2079 if (LocalHealthStatus == EfiDriverHealthStatusRepairRequired) {\r
2080 Status = DriverHealth->Repair (\r
2081 DriverHealth,\r
2082 ControllerHandle,\r
2083 ChildHandle,\r
2084 RepairNotify\r
2085 );\r
2086 }\r
2087 //\r
2088 // Via a form of the driver need to do configuration provided to process of status in\r
2089 // EfiDriverHealthStatusConfigurationRequired. The status after configuration should be in\r
2090 // (Healthy, Reboot Required, Failed, Reconnect Required, Repair Required).\r
2091 //\r
2092 if (LocalHealthStatus == EfiDriverHealthStatusConfigurationRequired) {\r
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
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
2120 ASSERT_EFI_ERROR (Status);\r
2121\r
2122 if (*MessageList != NULL) {\r
2123 ProcessMessages (*MessageList);\r
2124 }\r
2125 }\r
2126\r
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
2139 *RebootRequired = TRUE;\r
2140 }\r
2141\r
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
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
2154 }\r
2155 }\r
2156}\r
2157\r
2158\r
2159/**\r
2160 Reports the progress of a repair operation.\r
2161\r
2162 @param[in] Value A value between 0 and Limit that identifies the current\r
2163 progress of the repair operation.\r
2164\r
2165 @param[in] Limit The maximum value of Value for the current repair operation.\r
2166 For example, a driver that wants to specify progress in\r
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
2170\r
2171**/\r
2172EFI_STATUS\r
2173EFIAPI\r
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
2187 return EFI_SUCCESS;\r
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
2194 @param MessageList The MessageList point to messages need to processed.\r
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
2216 // User can customize the output. Just simply print out the MessageString like below.\r
2217 // Also can use the HiiHandle to display message on the front page.\r
2218 //\r
2219 // Print(L"%s\n",MessageString);\r
2220 // gBS->Stall (100000);\r
2221 }\r
2222 }\r
2223\r
2224}\r
2225\r
2226/**\r
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
2230 It will try to do recovery job till all the driver health protocol installed modules\r
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
2236**/\r
2237VOID\r
2238PlatformRepairAll (\r
2239 IN LIST_ENTRY *DriverHealthList\r
2240 )\r
2241{\r
2242 DRIVER_HEALTH_INFO *DriverHealthInfo;\r
2243 LIST_ENTRY *Link;\r
2244 BOOLEAN RebootRequired;\r
2245\r
2246 ASSERT (DriverHealthList != NULL);\r
2247\r
2248 RebootRequired = FALSE;\r
2249\r
2250 for ( Link = GetFirstNode (DriverHealthList)\r
2251 ; !IsNull (DriverHealthList, Link)\r
2252 ; Link = GetNextNode (DriverHealthList, Link)\r
2253 ) {\r
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
2260 ProcessSingleControllerHealth (\r
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
2270\r
2271 if (RebootRequired) {\r
2272 gRT->ResetSystem (EfiResetWarm, EFI_SUCCESS, 0, NULL);\r
2273 }\r
2274}\r
2275\r
2276/**\r
2277\r
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
2282\r
2283 @param SupportedLanguages A pointer to a Null-terminated ASCII string that\r
2284 contains a set of language codes in the format\r
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
2291 @retval NULL There are not enough resources available to return the best matching\r
2292 language.\r
2293 @retval Other A pointer to a Null-terminated ASCII string that is the best matching\r
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
2305 GetEfiGlobalVariable2 (Iso639Language ? L"Lang" : L"PlatformLang", (VOID**)&LanguageVariable, NULL);\r
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
2331 @param SupportedLanguage The best suitable language that matches the SupportedLangues interface for the\r
2332 located Component Name (2) instance.\r
2333\r
2334 @retval EFI_SUCCESS The Component Name (2) protocol instance is successfully located and we find\r
2335 the best matching language it support.\r
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
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
2408 // Retrieve Component Name (2) protocol instance on the driver binding handle and\r
2409 // find the best language this instance supports.\r
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
2420\r
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
2430\r
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
2439 compatibility support.\r
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
2480 compatibility support.\r
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
2513 // Retrieve Component Name (2) protocol instance on the driver binding handle and\r
2514 // find the best language this instance supports.\r
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
2544 in turn. It first tries UEFI 2.0 Component Name 2 protocol interface and try to get the controller name.\r
2545 If the attempt fails, it then gets the controller name from EFI 1.1 Component Name protocol for backward\r
2546 compatibility support.\r
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
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