]> git.proxmox.com Git - mirror_edk2.git/blame_incremental - MdeModulePkg/Library/DeviceManagerUiLib/DeviceManager.c
UefiCpuPkg: Move AsmRelocateApLoopStart from Mpfuncs.nasm to AmdSev.nasm
[mirror_edk2.git] / MdeModulePkg / Library / DeviceManagerUiLib / DeviceManager.c
... / ...
CommitLineData
1/** @file\r
2The device manager reference implementation\r
3\r
4Copyright (c) 2004 - 2018, Intel Corporation. All rights reserved.<BR>\r
5SPDX-License-Identifier: BSD-2-Clause-Patent\r
6\r
7**/\r
8\r
9#include "DeviceManager.h"\r
10\r
11DEVICE_MANAGER_CALLBACK_DATA gDeviceManagerPrivate = {\r
12 DEVICE_MANAGER_CALLBACK_DATA_SIGNATURE,\r
13 NULL,\r
14 NULL,\r
15 {\r
16 DeviceManagerExtractConfig,\r
17 DeviceManagerRouteConfig,\r
18 DeviceManagerCallback\r
19 }\r
20};\r
21\r
22#define MAX_MAC_ADDRESS_NODE_LIST_LEN 10\r
23\r
24EFI_GUID mDeviceManagerGuid = DEVICE_MANAGER_FORMSET_GUID;\r
25\r
26//\r
27// Which Mac Address string is select\r
28// it will decide what menu need to show in the NETWORK_DEVICE_FORM_ID form.\r
29//\r
30EFI_STRING mSelectedMacAddrString;\r
31\r
32//\r
33// The Mac Address show in the NETWORK_DEVICE_LIST_FORM_ID\r
34//\r
35MAC_ADDRESS_NODE_LIST mMacDeviceList;\r
36\r
37HII_VENDOR_DEVICE_PATH mDeviceManagerHiiVendorDevicePath = {\r
38 {\r
39 {\r
40 HARDWARE_DEVICE_PATH,\r
41 HW_VENDOR_DP,\r
42 {\r
43 (UINT8)(sizeof (VENDOR_DEVICE_PATH)),\r
44 (UINT8)((sizeof (VENDOR_DEVICE_PATH)) >> 8)\r
45 }\r
46 },\r
47 //\r
48 // {102579A0-3686-466e-ACD8-80C087044F4A}\r
49 //\r
50 { 0x102579a0, 0x3686, 0x466e, { 0xac, 0xd8, 0x80, 0xc0, 0x87, 0x4, 0x4f, 0x4a }\r
51 }\r
52 },\r
53 {\r
54 END_DEVICE_PATH_TYPE,\r
55 END_ENTIRE_DEVICE_PATH_SUBTYPE,\r
56 {\r
57 (UINT8)(END_DEVICE_PATH_LENGTH),\r
58 (UINT8)((END_DEVICE_PATH_LENGTH) >> 8)\r
59 }\r
60 }\r
61};\r
62\r
63/**\r
64 Extract device path for given HII handle and class guid.\r
65\r
66 @param Handle The HII handle.\r
67\r
68 @retval NULL Fail to get the device path string.\r
69 @return PathString Get the device path string.\r
70\r
71**/\r
72CHAR16 *\r
73DmExtractDevicePathFromHiiHandle (\r
74 IN EFI_HII_HANDLE Handle\r
75 )\r
76{\r
77 EFI_STATUS Status;\r
78 EFI_HANDLE DriverHandle;\r
79\r
80 ASSERT (Handle != NULL);\r
81\r
82 if (Handle == NULL) {\r
83 return NULL;\r
84 }\r
85\r
86 Status = gHiiDatabase->GetPackageListHandle (gHiiDatabase, Handle, &DriverHandle);\r
87 if (EFI_ERROR (Status)) {\r
88 return NULL;\r
89 }\r
90\r
91 //\r
92 // Get device path string.\r
93 //\r
94 return ConvertDevicePathToText (DevicePathFromHandle (DriverHandle), FALSE, FALSE);\r
95}\r
96\r
97/**\r
98 Get the mac address string from the device path.\r
99 if the device path has the vlan, get the vanid also.\r
100\r
101 @param MacAddressNode Device path begin with mac address\r
102 @param PBuffer Output string buffer contain mac address.\r
103\r
104**/\r
105BOOLEAN\r
106GetMacAddressString (\r
107 IN MAC_ADDR_DEVICE_PATH *MacAddressNode,\r
108 OUT CHAR16 **PBuffer\r
109 )\r
110{\r
111 UINTN HwAddressSize;\r
112 UINTN Index;\r
113 UINT8 *HwAddress;\r
114 EFI_DEVICE_PATH_PROTOCOL *Node;\r
115 UINT16 VlanId;\r
116 CHAR16 *String;\r
117 UINTN BufferLen;\r
118\r
119 VlanId = 0;\r
120 String = NULL;\r
121 ASSERT (MacAddressNode != NULL);\r
122\r
123 HwAddressSize = sizeof (EFI_MAC_ADDRESS);\r
124 if ((MacAddressNode->IfType == 0x01) || (MacAddressNode->IfType == 0x00)) {\r
125 HwAddressSize = 6;\r
126 }\r
127\r
128 //\r
129 // The output format is MAC:XX:XX:XX:...\XXXX\r
130 // The size is the Number size + ":" size + Vlan size(\XXXX) + End\r
131 //\r
132 BufferLen = (4 + 2 * HwAddressSize + (HwAddressSize - 1) + 5 + 1) * sizeof (CHAR16);\r
133 String = AllocateZeroPool (BufferLen);\r
134 if (String == NULL) {\r
135 return FALSE;\r
136 }\r
137\r
138 *PBuffer = String;\r
139 StrCpyS (String, BufferLen / sizeof (CHAR16), L"MAC:");\r
140 String += 4;\r
141\r
142 //\r
143 // Convert the MAC address into a unicode string.\r
144 //\r
145 HwAddress = &MacAddressNode->MacAddress.Addr[0];\r
146 for (Index = 0; Index < HwAddressSize; Index++) {\r
147 UnicodeValueToStringS (\r
148 String,\r
149 BufferLen - ((UINTN)String - (UINTN)*PBuffer),\r
150 PREFIX_ZERO | RADIX_HEX,\r
151 *(HwAddress++),\r
152 2\r
153 );\r
154 String += StrnLenS (String, (BufferLen - ((UINTN)String - (UINTN)*PBuffer)) / sizeof (CHAR16));\r
155 if (Index < HwAddressSize - 1) {\r
156 *String++ = L':';\r
157 }\r
158 }\r
159\r
160 //\r
161 // If VLAN is configured, it will need extra 5 characters like "\0005".\r
162 // Plus one unicode character for the null-terminator.\r
163 //\r
164 Node = (EFI_DEVICE_PATH_PROTOCOL *)MacAddressNode;\r
165 while (!IsDevicePathEnd (Node)) {\r
166 if ((Node->Type == MESSAGING_DEVICE_PATH) && (Node->SubType == MSG_VLAN_DP)) {\r
167 VlanId = ((VLAN_DEVICE_PATH *)Node)->VlanId;\r
168 }\r
169\r
170 Node = NextDevicePathNode (Node);\r
171 }\r
172\r
173 if (VlanId != 0) {\r
174 *String++ = L'\\';\r
175 UnicodeValueToStringS (\r
176 String,\r
177 BufferLen - ((UINTN)String - (UINTN)*PBuffer),\r
178 PREFIX_ZERO | RADIX_HEX,\r
179 VlanId,\r
180 4\r
181 );\r
182 String += StrnLenS (String, (BufferLen - ((UINTN)String - (UINTN)*PBuffer)) / sizeof (CHAR16));\r
183 }\r
184\r
185 //\r
186 // Null terminate the Unicode string\r
187 //\r
188 *String = L'\0';\r
189\r
190 return TRUE;\r
191}\r
192\r
193/**\r
194 Save question id and prompt id to the mac device list.\r
195 If the same mac address has saved yet, no need to add more.\r
196\r
197 @param MacAddrString Mac address string.\r
198\r
199 @retval EFI_SUCCESS Add the item is successful.\r
200 @return Other values if failed to Add the item.\r
201**/\r
202BOOLEAN\r
203AddIdToMacDeviceList (\r
204 IN EFI_STRING MacAddrString\r
205 )\r
206{\r
207 MENU_INFO_ITEM *TempDeviceList;\r
208 UINTN Index;\r
209 EFI_STRING StoredString;\r
210 EFI_STRING_ID PromptId;\r
211 EFI_HII_HANDLE HiiHandle;\r
212\r
213 HiiHandle = gDeviceManagerPrivate.HiiHandle;\r
214 TempDeviceList = NULL;\r
215\r
216 for (Index = 0; Index < mMacDeviceList.CurListLen; Index++) {\r
217 StoredString = HiiGetString (HiiHandle, mMacDeviceList.NodeList[Index].PromptId, NULL);\r
218 if (StoredString == NULL) {\r
219 return FALSE;\r
220 }\r
221\r
222 //\r
223 // Already has save the same mac address to the list.\r
224 //\r
225 if (StrCmp (MacAddrString, StoredString) == 0) {\r
226 return FALSE;\r
227 }\r
228 }\r
229\r
230 PromptId = HiiSetString (HiiHandle, 0, MacAddrString, NULL);\r
231 //\r
232 // If not in the list, save it.\r
233 //\r
234 if (mMacDeviceList.MaxListLen > mMacDeviceList.CurListLen + 1) {\r
235 mMacDeviceList.NodeList[mMacDeviceList.CurListLen].PromptId = PromptId;\r
236 mMacDeviceList.NodeList[mMacDeviceList.CurListLen].QuestionId = (EFI_QUESTION_ID)(mMacDeviceList.CurListLen + NETWORK_DEVICE_LIST_KEY_OFFSET);\r
237 } else {\r
238 mMacDeviceList.MaxListLen += MAX_MAC_ADDRESS_NODE_LIST_LEN;\r
239 if (mMacDeviceList.CurListLen != 0) {\r
240 TempDeviceList = ReallocatePool (\r
241 sizeof (MENU_INFO_ITEM) * mMacDeviceList.CurListLen,\r
242 sizeof (MENU_INFO_ITEM) * mMacDeviceList.MaxListLen,\r
243 mMacDeviceList.NodeList\r
244 );\r
245 } else {\r
246 TempDeviceList = (MENU_INFO_ITEM *)AllocatePool (sizeof (MENU_INFO_ITEM) * mMacDeviceList.MaxListLen);\r
247 }\r
248\r
249 if (TempDeviceList == NULL) {\r
250 return FALSE;\r
251 }\r
252\r
253 TempDeviceList[mMacDeviceList.CurListLen].PromptId = PromptId;\r
254 TempDeviceList[mMacDeviceList.CurListLen].QuestionId = (EFI_QUESTION_ID)(mMacDeviceList.CurListLen + NETWORK_DEVICE_LIST_KEY_OFFSET);\r
255\r
256 mMacDeviceList.NodeList = TempDeviceList;\r
257 }\r
258\r
259 mMacDeviceList.CurListLen++;\r
260\r
261 return TRUE;\r
262}\r
263\r
264/**\r
265 Check the devcie path, try to find whether it has mac address path.\r
266\r
267 In this function, first need to check whether this path has mac address path.\r
268 second, when the mac address device path has find, also need to deicide whether\r
269 need to add this mac address relate info to the menu.\r
270\r
271 @param *Node Input device which need to be check.\r
272 @param NextShowFormId FormId Which need to be show.\r
273 @param *NeedAddItem Whether need to add the menu in the network device list.\r
274\r
275 @retval TRUE Has mac address device path.\r
276 @retval FALSE NOT Has mac address device path.\r
277\r
278**/\r
279BOOLEAN\r
280IsMacAddressDevicePath (\r
281 IN VOID *Node,\r
282 IN EFI_FORM_ID NextShowFormId,\r
283 OUT BOOLEAN *NeedAddItem\r
284 )\r
285{\r
286 EFI_DEVICE_PATH_PROTOCOL *DevicePath;\r
287 CHAR16 *Buffer;\r
288 BOOLEAN ReturnVal;\r
289\r
290 ASSERT (Node != NULL);\r
291 *NeedAddItem = FALSE;\r
292 ReturnVal = FALSE;\r
293 Buffer = NULL;\r
294\r
295 DevicePath = (EFI_DEVICE_PATH_PROTOCOL *)Node;\r
296\r
297 //\r
298 // find the partition device path node\r
299 //\r
300 while (!IsDevicePathEnd (DevicePath)) {\r
301 if ((DevicePathType (DevicePath) == MESSAGING_DEVICE_PATH) &&\r
302 (DevicePathSubType (DevicePath) == MSG_MAC_ADDR_DP))\r
303 {\r
304 ReturnVal = TRUE;\r
305\r
306 if (DEVICE_MANAGER_FORM_ID == NextShowFormId) {\r
307 *NeedAddItem = TRUE;\r
308 break;\r
309 }\r
310\r
311 if (!GetMacAddressString ((MAC_ADDR_DEVICE_PATH *)DevicePath, &Buffer)) {\r
312 break;\r
313 }\r
314\r
315 if (NETWORK_DEVICE_FORM_ID == NextShowFormId) {\r
316 if (StrCmp (Buffer, mSelectedMacAddrString) == 0) {\r
317 *NeedAddItem = TRUE;\r
318 }\r
319\r
320 break;\r
321 }\r
322\r
323 if (NETWORK_DEVICE_LIST_FORM_ID == NextShowFormId) {\r
324 //\r
325 // Same handle may has two network child handle, so the questionid\r
326 // has the offset of SAME_HANDLE_KEY_OFFSET.\r
327 //\r
328 if (AddIdToMacDeviceList (Buffer)) {\r
329 *NeedAddItem = TRUE;\r
330 }\r
331\r
332 break;\r
333 }\r
334 }\r
335\r
336 DevicePath = NextDevicePathNode (DevicePath);\r
337 }\r
338\r
339 if (Buffer != NULL) {\r
340 FreePool (Buffer);\r
341 }\r
342\r
343 return ReturnVal;\r
344}\r
345\r
346/**\r
347 Check to see if the device path is for the network device.\r
348\r
349 @param Handle The HII handle which include the mac address device path.\r
350 @param NextShowFormId The FormId of the form which will be show next time.\r
351 @param ItemCount The new add Mac address item count.\r
352\r
353 @retval TRUE Need to add new item in the menu.\r
354 @return FALSE Do not need to add the menu about the network.\r
355\r
356**/\r
357BOOLEAN\r
358IsNeedAddNetworkMenu (\r
359 IN EFI_HII_HANDLE Handle,\r
360 IN EFI_FORM_ID NextShowFormId,\r
361 OUT UINTN *ItemCount\r
362 )\r
363{\r
364 EFI_STATUS Status;\r
365 UINTN EntryCount;\r
366 UINTN Index;\r
367 EFI_HANDLE DriverHandle;\r
368 EFI_HANDLE ControllerHandle;\r
369 EFI_DEVICE_PATH_PROTOCOL *DevicePath;\r
370 EFI_DEVICE_PATH_PROTOCOL *TmpDevicePath;\r
371 EFI_DEVICE_PATH_PROTOCOL *ChildDevicePath;\r
372 EFI_OPEN_PROTOCOL_INFORMATION_ENTRY *OpenInfoBuffer;\r
373 BOOLEAN IsNeedAdd;\r
374\r
375 IsNeedAdd = FALSE;\r
376 OpenInfoBuffer = NULL;\r
377 if ((Handle == NULL) || (ItemCount == NULL)) {\r
378 return FALSE;\r
379 }\r
380\r
381 *ItemCount = 0;\r
382\r
383 Status = gHiiDatabase->GetPackageListHandle (gHiiDatabase, Handle, &DriverHandle);\r
384 if (EFI_ERROR (Status)) {\r
385 return FALSE;\r
386 }\r
387\r
388 //\r
389 // Get the device path by the got Driver handle .\r
390 //\r
391 Status = gBS->HandleProtocol (DriverHandle, &gEfiDevicePathProtocolGuid, (VOID **)&DevicePath);\r
392 if (EFI_ERROR (Status)) {\r
393 return FALSE;\r
394 }\r
395\r
396 TmpDevicePath = DevicePath;\r
397\r
398 //\r
399 // Check whether this device path include mac address device path.\r
400 // If this path has mac address path, get the value whether need\r
401 // add this info to the menu and return.\r
402 // Else check more about the child handle devcie path.\r
403 //\r
404 if (IsMacAddressDevicePath (TmpDevicePath, NextShowFormId, &IsNeedAdd)) {\r
405 if ((NETWORK_DEVICE_LIST_FORM_ID == NextShowFormId) && IsNeedAdd) {\r
406 (*ItemCount) = 1;\r
407 }\r
408\r
409 return IsNeedAdd;\r
410 }\r
411\r
412 //\r
413 // Search whether this path is the controller path, not he child handle path.\r
414 // And the child handle has the network devcie connected.\r
415 //\r
416 TmpDevicePath = DevicePath;\r
417 Status = gBS->LocateDevicePath (&gEfiDevicePathProtocolGuid, &TmpDevicePath, &ControllerHandle);\r
418 if (EFI_ERROR (Status)) {\r
419 return FALSE;\r
420 }\r
421\r
422 if (!IsDevicePathEnd (TmpDevicePath)) {\r
423 return FALSE;\r
424 }\r
425\r
426 //\r
427 // Retrieve the list of agents that are consuming the specific protocol\r
428 // on ControllerHandle.\r
429 // The buffer point by OpenInfoBuffer need be free at this function.\r
430 //\r
431 Status = gBS->OpenProtocolInformation (\r
432 ControllerHandle,\r
433 &gEfiPciIoProtocolGuid,\r
434 &OpenInfoBuffer,\r
435 &EntryCount\r
436 );\r
437 if (EFI_ERROR (Status)) {\r
438 return FALSE;\r
439 }\r
440\r
441 //\r
442 // Inspect if ChildHandle is one of the agents.\r
443 //\r
444 Status = EFI_UNSUPPORTED;\r
445 for (Index = 0; Index < EntryCount; Index++) {\r
446 //\r
447 // Query all the children created by the controller handle's driver\r
448 //\r
449 if ((OpenInfoBuffer[Index].Attributes & EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER) != 0) {\r
450 Status = gBS->OpenProtocol (\r
451 OpenInfoBuffer[Index].ControllerHandle,\r
452 &gEfiDevicePathProtocolGuid,\r
453 (VOID **)&ChildDevicePath,\r
454 NULL,\r
455 NULL,\r
456 EFI_OPEN_PROTOCOL_GET_PROTOCOL\r
457 );\r
458 if (EFI_ERROR (Status)) {\r
459 continue;\r
460 }\r
461\r
462 //\r
463 // Check whether this device path include mac address device path.\r
464 //\r
465 if (!IsMacAddressDevicePath (ChildDevicePath, NextShowFormId, &IsNeedAdd)) {\r
466 //\r
467 // If this path not has mac address path, check the other.\r
468 //\r
469 continue;\r
470 } else {\r
471 //\r
472 // If need to update the NETWORK_DEVICE_LIST_FORM, try to get more.\r
473 //\r
474 if ((NETWORK_DEVICE_LIST_FORM_ID == NextShowFormId)) {\r
475 if (IsNeedAdd) {\r
476 (*ItemCount) += 1;\r
477 }\r
478\r
479 continue;\r
480 } else {\r
481 //\r
482 // If need to update other form, return whether need to add to the menu.\r
483 //\r
484 goto Done;\r
485 }\r
486 }\r
487 }\r
488 }\r
489\r
490Done:\r
491 if (OpenInfoBuffer != NULL) {\r
492 FreePool (OpenInfoBuffer);\r
493 }\r
494\r
495 return IsNeedAdd;\r
496}\r
497\r
498/**\r
499 Dynamic create Hii information for Device Manager.\r
500\r
501 @param NextShowFormId The FormId which need to be show.\r
502\r
503**/\r
504VOID\r
505CreateDeviceManagerForm (\r
506 IN EFI_FORM_ID NextShowFormId\r
507 )\r
508{\r
509 UINTN Index;\r
510 EFI_STRING String;\r
511 EFI_STRING_ID Token;\r
512 EFI_STRING_ID TokenHelp;\r
513 EFI_HII_HANDLE *HiiHandles;\r
514 EFI_HII_HANDLE HiiHandle;\r
515 EFI_GUID FormSetGuid;\r
516 VOID *StartOpCodeHandle;\r
517 VOID *EndOpCodeHandle;\r
518 EFI_IFR_GUID_LABEL *StartLabel;\r
519 EFI_IFR_GUID_LABEL *EndLabel;\r
520 BOOLEAN AddNetworkMenu;\r
521 UINTN AddItemCount;\r
522 UINTN NewStringLen;\r
523 EFI_STRING NewStringTitle;\r
524 CHAR16 *DevicePathStr;\r
525 EFI_STRING_ID DevicePathId;\r
526 EFI_IFR_FORM_SET *Buffer;\r
527 UINTN BufferSize;\r
528 UINT8 ClassGuidNum;\r
529 EFI_GUID *ClassGuid;\r
530 UINTN TempSize;\r
531 UINT8 *Ptr;\r
532 EFI_STATUS Status;\r
533\r
534 TempSize = 0;\r
535 BufferSize = 0;\r
536 Buffer = NULL;\r
537\r
538 HiiHandle = gDeviceManagerPrivate.HiiHandle;\r
539 AddNetworkMenu = FALSE;\r
540 AddItemCount = 0;\r
541 //\r
542 // If need show the Network device list form, clear the old save list first.\r
543 //\r
544 if ((NextShowFormId == NETWORK_DEVICE_LIST_FORM_ID) && (mMacDeviceList.CurListLen > 0)) {\r
545 mMacDeviceList.CurListLen = 0;\r
546 }\r
547\r
548 //\r
549 // Update the network device form titile.\r
550 //\r
551 if (NextShowFormId == NETWORK_DEVICE_FORM_ID) {\r
552 String = HiiGetString (HiiHandle, STRING_TOKEN (STR_FORM_NETWORK_DEVICE_TITLE_HEAD), NULL);\r
553 if (String == NULL) {\r
554 return;\r
555 }\r
556\r
557 NewStringLen = StrLen (mSelectedMacAddrString) * 2;\r
558 NewStringLen += (StrLen (String) + 2) * 2;\r
559 NewStringTitle = AllocatePool (NewStringLen);\r
560 UnicodeSPrint (NewStringTitle, NewStringLen, L"%s %s", String, mSelectedMacAddrString);\r
561 HiiSetString (HiiHandle, STRING_TOKEN (STR_FORM_NETWORK_DEVICE_TITLE), NewStringTitle, NULL);\r
562 FreePool (String);\r
563 FreePool (NewStringTitle);\r
564 }\r
565\r
566 //\r
567 // Allocate space for creation of UpdateData Buffer\r
568 //\r
569 StartOpCodeHandle = HiiAllocateOpCodeHandle ();\r
570 ASSERT (StartOpCodeHandle != NULL);\r
571\r
572 EndOpCodeHandle = HiiAllocateOpCodeHandle ();\r
573 ASSERT (EndOpCodeHandle != NULL);\r
574\r
575 //\r
576 // Create Hii Extend Label OpCode as the start opcode\r
577 //\r
578 StartLabel = (EFI_IFR_GUID_LABEL *)HiiCreateGuidOpCode (StartOpCodeHandle, &gEfiIfrTianoGuid, NULL, sizeof (EFI_IFR_GUID_LABEL));\r
579 StartLabel->ExtendOpCode = EFI_IFR_EXTEND_OP_LABEL;\r
580 //\r
581 // According to the next show Form id(mNextShowFormId) to decide which form need to update.\r
582 //\r
583 StartLabel->Number = (UINT16)(LABEL_FORM_ID_OFFSET + NextShowFormId);\r
584\r
585 //\r
586 // Create Hii Extend Label OpCode as the end opcode\r
587 //\r
588 EndLabel = (EFI_IFR_GUID_LABEL *)HiiCreateGuidOpCode (EndOpCodeHandle, &gEfiIfrTianoGuid, NULL, sizeof (EFI_IFR_GUID_LABEL));\r
589 EndLabel->ExtendOpCode = EFI_IFR_EXTEND_OP_LABEL;\r
590 EndLabel->Number = LABEL_END;\r
591\r
592 //\r
593 // Get all the Hii handles\r
594 //\r
595 HiiHandles = HiiGetHiiHandles (NULL);\r
596 ASSERT (HiiHandles != NULL);\r
597\r
598 //\r
599 // Search for formset of each class type\r
600 //\r
601 for (Index = 0; HiiHandles[Index] != NULL; Index++) {\r
602 Status = HiiGetFormSetFromHiiHandle (HiiHandles[Index], &Buffer, &BufferSize);\r
603 if (EFI_ERROR (Status)) {\r
604 continue;\r
605 }\r
606\r
607 Ptr = (UINT8 *)Buffer;\r
608 while (TempSize < BufferSize) {\r
609 TempSize += ((EFI_IFR_OP_HEADER *)Ptr)->Length;\r
610 if (((EFI_IFR_OP_HEADER *)Ptr)->Length <= OFFSET_OF (EFI_IFR_FORM_SET, Flags)) {\r
611 Ptr += ((EFI_IFR_OP_HEADER *)Ptr)->Length;\r
612 continue;\r
613 }\r
614\r
615 ClassGuidNum = (UINT8)(((EFI_IFR_FORM_SET *)Ptr)->Flags & 0x3);\r
616 ClassGuid = (EFI_GUID *)(VOID *)(Ptr + sizeof (EFI_IFR_FORM_SET));\r
617 while (ClassGuidNum-- > 0) {\r
618 if (CompareGuid (&gEfiHiiPlatformSetupFormsetGuid, ClassGuid) == 0) {\r
619 ClassGuid++;\r
620 continue;\r
621 }\r
622\r
623 String = HiiGetString (HiiHandles[Index], ((EFI_IFR_FORM_SET *)Ptr)->FormSetTitle, NULL);\r
624 if (String == NULL) {\r
625 String = HiiGetString (HiiHandle, STRING_TOKEN (STR_MISSING_STRING), NULL);\r
626 ASSERT (String != NULL);\r
627 }\r
628\r
629 Token = HiiSetString (HiiHandle, 0, String, NULL);\r
630 FreePool (String);\r
631\r
632 String = HiiGetString (HiiHandles[Index], ((EFI_IFR_FORM_SET *)Ptr)->Help, NULL);\r
633 if (String == NULL) {\r
634 String = HiiGetString (HiiHandle, STRING_TOKEN (STR_MISSING_STRING), NULL);\r
635 ASSERT (String != NULL);\r
636 }\r
637\r
638 TokenHelp = HiiSetString (HiiHandle, 0, String, NULL);\r
639 FreePool (String);\r
640\r
641 CopyMem (&FormSetGuid, &((EFI_IFR_FORM_SET *)Ptr)->Guid, sizeof (EFI_GUID));\r
642\r
643 //\r
644 // Network device process\r
645 //\r
646 if (IsNeedAddNetworkMenu (HiiHandles[Index], NextShowFormId, &AddItemCount)) {\r
647 if (NextShowFormId == DEVICE_MANAGER_FORM_ID) {\r
648 //\r
649 // Only show one menu item "Network Config" in the device manger form.\r
650 //\r
651 if (!AddNetworkMenu) {\r
652 AddNetworkMenu = TRUE;\r
653 HiiCreateGotoOpCode (\r
654 StartOpCodeHandle,\r
655 NETWORK_DEVICE_LIST_FORM_ID,\r
656 STRING_TOKEN (STR_FORM_NETWORK_DEVICE_LIST_TITLE),\r
657 STRING_TOKEN (STR_FORM_NETWORK_DEVICE_LIST_HELP),\r
658 EFI_IFR_FLAG_CALLBACK,\r
659 (EFI_QUESTION_ID)QUESTION_NETWORK_DEVICE_ID\r
660 );\r
661 }\r
662 } else if (NextShowFormId == NETWORK_DEVICE_LIST_FORM_ID) {\r
663 //\r
664 // In network device list form, same mac address device only show one menu.\r
665 //\r
666 while (AddItemCount > 0) {\r
667 HiiCreateGotoOpCode (\r
668 StartOpCodeHandle,\r
669 NETWORK_DEVICE_FORM_ID,\r
670 mMacDeviceList.NodeList[mMacDeviceList.CurListLen - AddItemCount].PromptId,\r
671 STRING_TOKEN (STR_NETWORK_DEVICE_HELP),\r
672 EFI_IFR_FLAG_CALLBACK,\r
673 mMacDeviceList.NodeList[mMacDeviceList.CurListLen - AddItemCount].QuestionId\r
674 );\r
675 AddItemCount -= 1;\r
676 }\r
677 } else if (NextShowFormId == NETWORK_DEVICE_FORM_ID) {\r
678 //\r
679 // In network device form, only the selected mac address device need to be show.\r
680 //\r
681 DevicePathStr = DmExtractDevicePathFromHiiHandle (HiiHandles[Index]);\r
682 DevicePathId = 0;\r
683 if (DevicePathStr != NULL) {\r
684 DevicePathId = HiiSetString (HiiHandle, 0, DevicePathStr, NULL);\r
685 FreePool (DevicePathStr);\r
686 }\r
687\r
688 HiiCreateGotoExOpCode (\r
689 StartOpCodeHandle,\r
690 0,\r
691 Token,\r
692 TokenHelp,\r
693 0,\r
694 (EFI_QUESTION_ID)(Index + DEVICE_KEY_OFFSET),\r
695 0,\r
696 &FormSetGuid,\r
697 DevicePathId\r
698 );\r
699 }\r
700 } else {\r
701 //\r
702 // Not network device process, only need to show at device manger form.\r
703 //\r
704 if (NextShowFormId == DEVICE_MANAGER_FORM_ID) {\r
705 DevicePathStr = DmExtractDevicePathFromHiiHandle (HiiHandles[Index]);\r
706 DevicePathId = 0;\r
707 if (DevicePathStr != NULL) {\r
708 DevicePathId = HiiSetString (HiiHandle, 0, DevicePathStr, NULL);\r
709 FreePool (DevicePathStr);\r
710 }\r
711\r
712 HiiCreateGotoExOpCode (\r
713 StartOpCodeHandle,\r
714 0,\r
715 Token,\r
716 TokenHelp,\r
717 0,\r
718 (EFI_QUESTION_ID)(Index + DEVICE_KEY_OFFSET),\r
719 0,\r
720 &FormSetGuid,\r
721 DevicePathId\r
722 );\r
723 }\r
724 }\r
725\r
726 break;\r
727 }\r
728\r
729 Ptr += ((EFI_IFR_OP_HEADER *)Ptr)->Length;\r
730 }\r
731\r
732 FreePool (Buffer);\r
733 Buffer = NULL;\r
734 TempSize = 0;\r
735 BufferSize = 0;\r
736 }\r
737\r
738 HiiUpdateForm (\r
739 HiiHandle,\r
740 &mDeviceManagerGuid,\r
741 NextShowFormId,\r
742 StartOpCodeHandle,\r
743 EndOpCodeHandle\r
744 );\r
745\r
746 HiiFreeOpCodeHandle (StartOpCodeHandle);\r
747 HiiFreeOpCodeHandle (EndOpCodeHandle);\r
748 FreePool (HiiHandles);\r
749}\r
750\r
751/**\r
752 This function allows a caller to extract the current configuration for one\r
753 or more named elements from the target driver.\r
754\r
755\r
756 @param This Points to the EFI_HII_CONFIG_ACCESS_PROTOCOL.\r
757 @param Request A null-terminated Unicode string in <ConfigRequest> format.\r
758 @param Progress On return, points to a character in the Request string.\r
759 Points to the string's null terminator if request was successful.\r
760 Points to the most recent '&' before the first failing name/value\r
761 pair (or the beginning of the string if the failure is in the\r
762 first name/value pair) if the request was not successful.\r
763 @param Results A null-terminated Unicode string in <ConfigAltResp> format which\r
764 has all values filled in for the names in the Request string.\r
765 String to be allocated by the called function.\r
766\r
767 @retval EFI_SUCCESS The Results is filled with the requested values.\r
768 @retval EFI_OUT_OF_RESOURCES Not enough memory to store the results.\r
769 @retval EFI_INVALID_PARAMETER Request is illegal syntax, or unknown name.\r
770 @retval EFI_NOT_FOUND Routing data doesn't match any storage in this driver.\r
771\r
772**/\r
773EFI_STATUS\r
774EFIAPI\r
775DeviceManagerExtractConfig (\r
776 IN CONST EFI_HII_CONFIG_ACCESS_PROTOCOL *This,\r
777 IN CONST EFI_STRING Request,\r
778 OUT EFI_STRING *Progress,\r
779 OUT EFI_STRING *Results\r
780 )\r
781{\r
782 if ((Progress == NULL) || (Results == NULL)) {\r
783 return EFI_INVALID_PARAMETER;\r
784 }\r
785\r
786 *Progress = Request;\r
787 return EFI_NOT_FOUND;\r
788}\r
789\r
790/**\r
791 This function processes the results of changes in configuration.\r
792\r
793 @param This Points to the EFI_HII_CONFIG_ACCESS_PROTOCOL.\r
794 @param Configuration A null-terminated Unicode string in <ConfigResp> format.\r
795 @param Progress A pointer to a string filled in with the offset of the most\r
796 recent '&' before the first failing name/value pair (or the\r
797 beginning of the string if the failure is in the first\r
798 name/value pair) or the terminating NULL if all was successful.\r
799\r
800 @retval EFI_SUCCESS The Results is processed successfully.\r
801 @retval EFI_INVALID_PARAMETER Configuration is NULL.\r
802 @retval EFI_NOT_FOUND Routing data doesn't match any storage in this driver.\r
803\r
804**/\r
805EFI_STATUS\r
806EFIAPI\r
807DeviceManagerRouteConfig (\r
808 IN CONST EFI_HII_CONFIG_ACCESS_PROTOCOL *This,\r
809 IN CONST EFI_STRING Configuration,\r
810 OUT EFI_STRING *Progress\r
811 )\r
812{\r
813 if ((Configuration == NULL) || (Progress == NULL)) {\r
814 return EFI_INVALID_PARAMETER;\r
815 }\r
816\r
817 *Progress = Configuration;\r
818\r
819 return EFI_NOT_FOUND;\r
820}\r
821\r
822/**\r
823 This function is invoked if user selected a interactive opcode from Device Manager's\r
824 Formset. If user set VBIOS, the new value is saved to EFI variable.\r
825\r
826 @param This Points to the EFI_HII_CONFIG_ACCESS_PROTOCOL.\r
827 @param Action Specifies the type of action taken by the browser.\r
828 @param QuestionId A unique value which is sent to the original exporting driver\r
829 so that it can identify the type of data to expect.\r
830 @param Type The type of value for the question.\r
831 @param Value A pointer to the data being sent to the original exporting driver.\r
832 @param ActionRequest On return, points to the action requested by the callback function.\r
833\r
834 @retval EFI_SUCCESS The callback successfully handled the action.\r
835 @retval EFI_INVALID_PARAMETER The setup browser call this function with invalid parameters.\r
836\r
837**/\r
838EFI_STATUS\r
839EFIAPI\r
840DeviceManagerCallback (\r
841 IN CONST EFI_HII_CONFIG_ACCESS_PROTOCOL *This,\r
842 IN EFI_BROWSER_ACTION Action,\r
843 IN EFI_QUESTION_ID QuestionId,\r
844 IN UINT8 Type,\r
845 IN EFI_IFR_TYPE_VALUE *Value,\r
846 OUT EFI_BROWSER_ACTION_REQUEST *ActionRequest\r
847 )\r
848{\r
849 UINTN CurIndex;\r
850\r
851 if (Action != EFI_BROWSER_ACTION_CHANGING) {\r
852 //\r
853 // Do nothing for other UEFI Action. Only do call back when data is changed.\r
854 //\r
855 return EFI_UNSUPPORTED;\r
856 }\r
857\r
858 if ((Value == NULL) || (ActionRequest == NULL)) {\r
859 return EFI_INVALID_PARAMETER;\r
860 }\r
861\r
862 if ((QuestionId < MAX_KEY_SECTION_LEN + NETWORK_DEVICE_LIST_KEY_OFFSET) && (QuestionId >= NETWORK_DEVICE_LIST_KEY_OFFSET)) {\r
863 //\r
864 // If user select the mac address, need to record mac address string to support next form show.\r
865 //\r
866 for (CurIndex = 0; CurIndex < mMacDeviceList.CurListLen; CurIndex++) {\r
867 if (mMacDeviceList.NodeList[CurIndex].QuestionId == QuestionId) {\r
868 mSelectedMacAddrString = HiiGetString (gDeviceManagerPrivate.HiiHandle, mMacDeviceList.NodeList[CurIndex].PromptId, NULL);\r
869 }\r
870 }\r
871\r
872 CreateDeviceManagerForm (NETWORK_DEVICE_FORM_ID);\r
873 } else if (QuestionId == QUESTION_NETWORK_DEVICE_ID) {\r
874 CreateDeviceManagerForm (NETWORK_DEVICE_LIST_FORM_ID);\r
875 }\r
876\r
877 return EFI_SUCCESS;\r
878}\r
879\r
880/**\r
881 Install Boot Manager Menu driver.\r
882\r
883 @param ImageHandle The image handle.\r
884 @param SystemTable The system table.\r
885\r
886 @retval EFI_SUCEESS Install Boot manager menu success.\r
887 @retval Other Return error status.\r
888\r
889**/\r
890EFI_STATUS\r
891EFIAPI\r
892DeviceManagerUiLibConstructor (\r
893 IN EFI_HANDLE ImageHandle,\r
894 IN EFI_SYSTEM_TABLE *SystemTable\r
895 )\r
896{\r
897 EFI_STATUS Status;\r
898\r
899 gDeviceManagerPrivate.DriverHandle = NULL;\r
900 Status = gBS->InstallMultipleProtocolInterfaces (\r
901 &gDeviceManagerPrivate.DriverHandle,\r
902 &gEfiDevicePathProtocolGuid,\r
903 &mDeviceManagerHiiVendorDevicePath,\r
904 &gEfiHiiConfigAccessProtocolGuid,\r
905 &gDeviceManagerPrivate.ConfigAccess,\r
906 NULL\r
907 );\r
908 ASSERT_EFI_ERROR (Status);\r
909\r
910 //\r
911 // Publish our HII data.\r
912 //\r
913 gDeviceManagerPrivate.HiiHandle = HiiAddPackages (\r
914 &mDeviceManagerGuid,\r
915 gDeviceManagerPrivate.DriverHandle,\r
916 DeviceManagerVfrBin,\r
917 DeviceManagerUiLibStrings,\r
918 NULL\r
919 );\r
920 ASSERT (gDeviceManagerPrivate.HiiHandle != NULL);\r
921\r
922 //\r
923 // The device manager form contains a page listing all the network\r
924 // controllers in the system. This list can only be populated if all\r
925 // handles have been connected, so do it here.\r
926 //\r
927 EfiBootManagerConnectAll ();\r
928\r
929 //\r
930 // Update boot manager page\r
931 //\r
932 CreateDeviceManagerForm (DEVICE_MANAGER_FORM_ID);\r
933\r
934 return EFI_SUCCESS;\r
935}\r
936\r
937/**\r
938 Unloads the application and its installed protocol.\r
939\r
940 @param ImageHandle Handle that identifies the image to be unloaded.\r
941 @param SystemTable The system table.\r
942\r
943 @retval EFI_SUCCESS The image has been unloaded.\r
944**/\r
945EFI_STATUS\r
946EFIAPI\r
947DeviceManagerUiLibDestructor (\r
948 IN EFI_HANDLE ImageHandle,\r
949 IN EFI_SYSTEM_TABLE *SystemTable\r
950 )\r
951{\r
952 EFI_STATUS Status;\r
953\r
954 Status = gBS->UninstallMultipleProtocolInterfaces (\r
955 gDeviceManagerPrivate.DriverHandle,\r
956 &gEfiDevicePathProtocolGuid,\r
957 &mDeviceManagerHiiVendorDevicePath,\r
958 &gEfiHiiConfigAccessProtocolGuid,\r
959 &gDeviceManagerPrivate.ConfigAccess,\r
960 NULL\r
961 );\r
962 ASSERT_EFI_ERROR (Status);\r
963\r
964 HiiRemovePackages (gDeviceManagerPrivate.HiiHandle);\r
965\r
966 return EFI_SUCCESS;\r
967}\r