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