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