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