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