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