]> git.proxmox.com Git - mirror_edk2.git/blame - MdeModulePkg/Library/DeviceManagerUiLib/DeviceManager.c
UefiCpuPkg: Move AsmRelocateApLoopStart from Mpfuncs.nasm to AmdSev.nasm
[mirror_edk2.git] / MdeModulePkg / Library / DeviceManagerUiLib / DeviceManager.c
CommitLineData
32465d9a
DB
1/** @file\r
2The device manager reference implementation\r
3\r
d1102dba 4Copyright (c) 2004 - 2018, Intel Corporation. All rights reserved.<BR>\r
9d510e61 5SPDX-License-Identifier: BSD-2-Clause-Patent\r
32465d9a
DB
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
1436aea4 22#define MAX_MAC_ADDRESS_NODE_LIST_LEN 10\r
32465d9a 23\r
1436aea4 24EFI_GUID mDeviceManagerGuid = DEVICE_MANAGER_FORMSET_GUID;\r
32465d9a
DB
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
1436aea4
MK
43 (UINT8)(sizeof (VENDOR_DEVICE_PATH)),\r
44 (UINT8)((sizeof (VENDOR_DEVICE_PATH)) >> 8)\r
32465d9a
DB
45 }\r
46 },\r
47 //\r
48 // {102579A0-3686-466e-ACD8-80C087044F4A}\r
49 //\r
1436aea4
MK
50 { 0x102579a0, 0x3686, 0x466e, { 0xac, 0xd8, 0x80, 0xc0, 0x87, 0x4, 0x4f, 0x4a }\r
51 }\r
32465d9a
DB
52 },\r
53 {\r
54 END_DEVICE_PATH_TYPE,\r
55 END_ENTIRE_DEVICE_PATH_SUBTYPE,\r
d1102dba 56 {\r
1436aea4
MK
57 (UINT8)(END_DEVICE_PATH_LENGTH),\r
58 (UINT8)((END_DEVICE_PATH_LENGTH) >> 8)\r
32465d9a
DB
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
1436aea4 74 IN EFI_HII_HANDLE Handle\r
32465d9a
DB
75 )\r
76{\r
1436aea4
MK
77 EFI_STATUS Status;\r
78 EFI_HANDLE DriverHandle;\r
32465d9a
DB
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
1436aea4 90\r
32465d9a
DB
91 //\r
92 // Get device path string.\r
93 //\r
1436aea4 94 return ConvertDevicePathToText (DevicePathFromHandle (DriverHandle), FALSE, FALSE);\r
32465d9a
DB
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
d1102dba
LG
100\r
101 @param MacAddressNode Device path begin with mac address\r
32465d9a
DB
102 @param PBuffer Output string buffer contain mac address.\r
103\r
104**/\r
d1102dba 105BOOLEAN\r
1436aea4
MK
106GetMacAddressString (\r
107 IN MAC_ADDR_DEVICE_PATH *MacAddressNode,\r
108 OUT CHAR16 **PBuffer\r
32465d9a
DB
109 )\r
110{\r
1436aea4
MK
111 UINTN HwAddressSize;\r
112 UINTN Index;\r
113 UINT8 *HwAddress;\r
32465d9a 114 EFI_DEVICE_PATH_PROTOCOL *Node;\r
1436aea4
MK
115 UINT16 VlanId;\r
116 CHAR16 *String;\r
117 UINTN BufferLen;\r
32465d9a
DB
118\r
119 VlanId = 0;\r
120 String = NULL;\r
1436aea4 121 ASSERT (MacAddressNode != NULL);\r
32465d9a
DB
122\r
123 HwAddressSize = sizeof (EFI_MAC_ADDRESS);\r
1436aea4 124 if ((MacAddressNode->IfType == 0x01) || (MacAddressNode->IfType == 0x00)) {\r
32465d9a
DB
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
1436aea4 133 String = AllocateZeroPool (BufferLen);\r
32465d9a
DB
134 if (String == NULL) {\r
135 return FALSE;\r
136 }\r
137\r
138 *PBuffer = String;\r
1436aea4 139 StrCpyS (String, BufferLen / sizeof (CHAR16), L"MAC:");\r
32465d9a 140 String += 4;\r
d1102dba 141\r
32465d9a
DB
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
9f4048f7
HW
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
32465d9a
DB
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
1436aea4
MK
166 if ((Node->Type == MESSAGING_DEVICE_PATH) && (Node->SubType == MSG_VLAN_DP)) {\r
167 VlanId = ((VLAN_DEVICE_PATH *)Node)->VlanId;\r
32465d9a 168 }\r
1436aea4 169\r
32465d9a
DB
170 Node = NextDevicePathNode (Node);\r
171 }\r
172\r
173 if (VlanId != 0) {\r
174 *String++ = L'\\';\r
9f4048f7
HW
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
32465d9a
DB
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
d1102dba 202BOOLEAN\r
32465d9a 203AddIdToMacDeviceList (\r
1436aea4 204 IN EFI_STRING MacAddrString\r
32465d9a
DB
205 )\r
206{\r
1436aea4
MK
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
32465d9a 212\r
1436aea4 213 HiiHandle = gDeviceManagerPrivate.HiiHandle;\r
32465d9a
DB
214 TempDeviceList = NULL;\r
215\r
1436aea4 216 for (Index = 0; Index < mMacDeviceList.CurListLen; Index++) {\r
32465d9a
DB
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
1436aea4 230 PromptId = HiiSetString (HiiHandle, 0, MacAddrString, NULL);\r
32465d9a
DB
231 //\r
232 // If not in the list, save it.\r
233 //\r
234 if (mMacDeviceList.MaxListLen > mMacDeviceList.CurListLen + 1) {\r
1436aea4
MK
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
32465d9a
DB
237 } else {\r
238 mMacDeviceList.MaxListLen += MAX_MAC_ADDRESS_NODE_LIST_LEN;\r
239 if (mMacDeviceList.CurListLen != 0) {\r
469293f8
JW
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
32465d9a
DB
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
1436aea4
MK
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
32465d9a 255\r
32465d9a
DB
256 mMacDeviceList.NodeList = TempDeviceList;\r
257 }\r
1436aea4
MK
258\r
259 mMacDeviceList.CurListLen++;\r
32465d9a
DB
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
1436aea4
MK
281 IN VOID *Node,\r
282 IN EFI_FORM_ID NextShowFormId,\r
283 OUT BOOLEAN *NeedAddItem\r
32465d9a
DB
284 )\r
285{\r
1436aea4
MK
286 EFI_DEVICE_PATH_PROTOCOL *DevicePath;\r
287 CHAR16 *Buffer;\r
288 BOOLEAN ReturnVal;\r
32465d9a
DB
289\r
290 ASSERT (Node != NULL);\r
291 *NeedAddItem = FALSE;\r
292 ReturnVal = FALSE;\r
1436aea4 293 Buffer = NULL;\r
32465d9a 294\r
1436aea4 295 DevicePath = (EFI_DEVICE_PATH_PROTOCOL *)Node;\r
32465d9a
DB
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
1436aea4
MK
302 (DevicePathSubType (DevicePath) == MSG_MAC_ADDR_DP))\r
303 {\r
32465d9a
DB
304 ReturnVal = TRUE;\r
305\r
306 if (DEVICE_MANAGER_FORM_ID == NextShowFormId) {\r
307 *NeedAddItem = TRUE;\r
308 break;\r
d1102dba
LG
309 }\r
310\r
1436aea4 311 if (!GetMacAddressString ((MAC_ADDR_DEVICE_PATH *)DevicePath, &Buffer)) {\r
32465d9a
DB
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
1436aea4 319\r
32465d9a
DB
320 break;\r
321 }\r
322\r
323 if (NETWORK_DEVICE_LIST_FORM_ID == NextShowFormId) {\r
324 //\r
d1102dba 325 // Same handle may has two network child handle, so the questionid\r
32465d9a
DB
326 // has the offset of SAME_HANDLE_KEY_OFFSET.\r
327 //\r
328 if (AddIdToMacDeviceList (Buffer)) {\r
329 *NeedAddItem = TRUE;\r
330 }\r
1436aea4 331\r
32465d9a
DB
332 break;\r
333 }\r
334 }\r
1436aea4 335\r
32465d9a
DB
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
d1102dba 357BOOLEAN\r
32465d9a 358IsNeedAddNetworkMenu (\r
1436aea4
MK
359 IN EFI_HII_HANDLE Handle,\r
360 IN EFI_FORM_ID NextShowFormId,\r
361 OUT UINTN *ItemCount\r
32465d9a
DB
362 )\r
363{\r
1436aea4
MK
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
32465d9a
DB
376 OpenInfoBuffer = NULL;\r
377 if ((Handle == NULL) || (ItemCount == NULL)) {\r
378 return FALSE;\r
379 }\r
1436aea4 380\r
32465d9a
DB
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
1436aea4 387\r
32465d9a
DB
388 //\r
389 // Get the device path by the got Driver handle .\r
390 //\r
1436aea4 391 Status = gBS->HandleProtocol (DriverHandle, &gEfiDevicePathProtocolGuid, (VOID **)&DevicePath);\r
32465d9a
DB
392 if (EFI_ERROR (Status)) {\r
393 return FALSE;\r
394 }\r
1436aea4 395\r
32465d9a
DB
396 TmpDevicePath = DevicePath;\r
397\r
d1102dba 398 //\r
32465d9a 399 // Check whether this device path include mac address device path.\r
d1102dba 400 // If this path has mac address path, get the value whether need\r
32465d9a
DB
401 // add this info to the menu and return.\r
402 // Else check more about the child handle devcie path.\r
403 //\r
1436aea4 404 if (IsMacAddressDevicePath (TmpDevicePath, NextShowFormId, &IsNeedAdd)) {\r
32465d9a
DB
405 if ((NETWORK_DEVICE_LIST_FORM_ID == NextShowFormId) && IsNeedAdd) {\r
406 (*ItemCount) = 1;\r
407 }\r
1436aea4 408\r
32465d9a
DB
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
1436aea4 417 Status = gBS->LocateDevicePath (&gEfiDevicePathProtocolGuid, &TmpDevicePath, &ControllerHandle);\r
32465d9a
DB
418 if (EFI_ERROR (Status)) {\r
419 return FALSE;\r
420 }\r
421\r
422 if (!IsDevicePathEnd (TmpDevicePath)) {\r
d1102dba 423 return FALSE;\r
32465d9a
DB
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
1436aea4 453 (VOID **)&ChildDevicePath,\r
32465d9a
DB
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
d1102dba 462 //\r
32465d9a
DB
463 // Check whether this device path include mac address device path.\r
464 //\r
1436aea4 465 if (!IsMacAddressDevicePath (ChildDevicePath, NextShowFormId, &IsNeedAdd)) {\r
32465d9a
DB
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
1436aea4 478\r
32465d9a
DB
479 continue;\r
480 } else {\r
481 //\r
482 // If need to update other form, return whether need to add to the menu.\r
d1102dba 483 //\r
32465d9a
DB
484 goto Done;\r
485 }\r
486 }\r
487 }\r
488 }\r
489\r
490Done:\r
491 if (OpenInfoBuffer != NULL) {\r
d1102dba 492 FreePool (OpenInfoBuffer);\r
32465d9a 493 }\r
1436aea4 494\r
d1102dba 495 return IsNeedAdd;\r
32465d9a
DB
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
1436aea4
MK
505CreateDeviceManagerForm (\r
506 IN EFI_FORM_ID NextShowFormId\r
507 )\r
32465d9a 508{\r
1436aea4
MK
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
32465d9a 535 BufferSize = 0;\r
1436aea4 536 Buffer = NULL;\r
32465d9a 537\r
1436aea4 538 HiiHandle = gDeviceManagerPrivate.HiiHandle;\r
32465d9a 539 AddNetworkMenu = FALSE;\r
1436aea4 540 AddItemCount = 0;\r
32465d9a
DB
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
205a4b0c
JW
552 String = HiiGetString (HiiHandle, STRING_TOKEN (STR_FORM_NETWORK_DEVICE_TITLE_HEAD), NULL);\r
553 if (String == NULL) {\r
554 return;\r
555 }\r
1436aea4
MK
556\r
557 NewStringLen = StrLen (mSelectedMacAddrString) * 2;\r
558 NewStringLen += (StrLen (String) + 2) * 2;\r
32465d9a
DB
559 NewStringTitle = AllocatePool (NewStringLen);\r
560 UnicodeSPrint (NewStringTitle, NewStringLen, L"%s %s", String, mSelectedMacAddrString);\r
205a4b0c 561 HiiSetString (HiiHandle, STRING_TOKEN (STR_FORM_NETWORK_DEVICE_TITLE), NewStringTitle, NULL);\r
32465d9a
DB
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
1436aea4 578 StartLabel = (EFI_IFR_GUID_LABEL *)HiiCreateGuidOpCode (StartOpCodeHandle, &gEfiIfrTianoGuid, NULL, sizeof (EFI_IFR_GUID_LABEL));\r
32465d9a
DB
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
1436aea4 583 StartLabel->Number = (UINT16)(LABEL_FORM_ID_OFFSET + NextShowFormId);\r
32465d9a
DB
584\r
585 //\r
586 // Create Hii Extend Label OpCode as the end opcode\r
587 //\r
1436aea4 588 EndLabel = (EFI_IFR_GUID_LABEL *)HiiCreateGuidOpCode (EndOpCodeHandle, &gEfiIfrTianoGuid, NULL, sizeof (EFI_IFR_GUID_LABEL));\r
32465d9a
DB
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
1436aea4
MK
602 Status = HiiGetFormSetFromHiiHandle (HiiHandles[Index], &Buffer, &BufferSize);\r
603 if (EFI_ERROR (Status)) {\r
32465d9a
DB
604 continue;\r
605 }\r
1436aea4 606\r
32465d9a 607 Ptr = (UINT8 *)Buffer;\r
1436aea4
MK
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
32465d9a 612 continue;\r
d1102dba 613 }\r
32465d9a 614\r
1436aea4
MK
615 ClassGuidNum = (UINT8)(((EFI_IFR_FORM_SET *)Ptr)->Flags & 0x3);\r
616 ClassGuid = (EFI_GUID *)(VOID *)(Ptr + sizeof (EFI_IFR_FORM_SET));\r
32465d9a 617 while (ClassGuidNum-- > 0) {\r
1436aea4
MK
618 if (CompareGuid (&gEfiHiiPlatformSetupFormsetGuid, ClassGuid) == 0) {\r
619 ClassGuid++;\r
32465d9a
DB
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
1436aea4 628\r
32465d9a
DB
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
1436aea4 637\r
32465d9a
DB
638 TokenHelp = HiiSetString (HiiHandle, 0, String, NULL);\r
639 FreePool (String);\r
640\r
1436aea4 641 CopyMem (&FormSetGuid, &((EFI_IFR_FORM_SET *)Ptr)->Guid, sizeof (EFI_GUID));\r
32465d9a
DB
642\r
643 //\r
644 // Network device process\r
d1102dba 645 //\r
1436aea4 646 if (IsNeedAddNetworkMenu (HiiHandles[Index], NextShowFormId, &AddItemCount)) {\r
32465d9a
DB
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
1436aea4
MK
659 (EFI_QUESTION_ID)QUESTION_NETWORK_DEVICE_ID\r
660 );\r
32465d9a
DB
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
1436aea4 674 );\r
32465d9a
DB
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
1436aea4 681 DevicePathStr = DmExtractDevicePathFromHiiHandle (HiiHandles[Index]);\r
32465d9a 682 DevicePathId = 0;\r
1436aea4 683 if (DevicePathStr != NULL) {\r
32465d9a 684 DevicePathId = HiiSetString (HiiHandle, 0, DevicePathStr, NULL);\r
1436aea4 685 FreePool (DevicePathStr);\r
32465d9a 686 }\r
1436aea4 687\r
32465d9a
DB
688 HiiCreateGotoExOpCode (\r
689 StartOpCodeHandle,\r
690 0,\r
691 Token,\r
692 TokenHelp,\r
693 0,\r
1436aea4 694 (EFI_QUESTION_ID)(Index + DEVICE_KEY_OFFSET),\r
32465d9a 695 0,\r
d1102dba 696 &FormSetGuid,\r
32465d9a 697 DevicePathId\r
1436aea4 698 );\r
32465d9a
DB
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
1436aea4 705 DevicePathStr = DmExtractDevicePathFromHiiHandle (HiiHandles[Index]);\r
32465d9a 706 DevicePathId = 0;\r
1436aea4 707 if (DevicePathStr != NULL) {\r
32465d9a 708 DevicePathId = HiiSetString (HiiHandle, 0, DevicePathStr, NULL);\r
1436aea4 709 FreePool (DevicePathStr);\r
32465d9a 710 }\r
1436aea4 711\r
32465d9a
DB
712 HiiCreateGotoExOpCode (\r
713 StartOpCodeHandle,\r
714 0,\r
715 Token,\r
716 TokenHelp,\r
717 0,\r
1436aea4 718 (EFI_QUESTION_ID)(Index + DEVICE_KEY_OFFSET),\r
32465d9a
DB
719 0,\r
720 &FormSetGuid,\r
721 DevicePathId\r
1436aea4 722 );\r
32465d9a
DB
723 }\r
724 }\r
1436aea4 725\r
32465d9a
DB
726 break;\r
727 }\r
728\r
1436aea4 729 Ptr += ((EFI_IFR_OP_HEADER *)Ptr)->Length;\r
32465d9a 730 }\r
1436aea4
MK
731\r
732 FreePool (Buffer);\r
733 Buffer = NULL;\r
734 TempSize = 0;\r
32465d9a
DB
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
1436aea4
MK
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
32465d9a
DB
780 )\r
781{\r
1436aea4 782 if ((Progress == NULL) || (Results == NULL)) {\r
32465d9a
DB
783 return EFI_INVALID_PARAMETER;\r
784 }\r
1436aea4 785\r
32465d9a
DB
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
1436aea4
MK
808 IN CONST EFI_HII_CONFIG_ACCESS_PROTOCOL *This,\r
809 IN CONST EFI_STRING Configuration,\r
810 OUT EFI_STRING *Progress\r
32465d9a
DB
811 )\r
812{\r
1436aea4 813 if ((Configuration == NULL) || (Progress == NULL)) {\r
32465d9a
DB
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
1436aea4
MK
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
32465d9a
DB
847 )\r
848{\r
1436aea4 849 UINTN CurIndex;\r
32465d9a
DB
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
1436aea4 857\r
32465d9a
DB
858 if ((Value == NULL) || (ActionRequest == NULL)) {\r
859 return EFI_INVALID_PARAMETER;\r
860 }\r
1436aea4 861\r
32465d9a
DB
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
1436aea4 866 for (CurIndex = 0; CurIndex < mMacDeviceList.CurListLen; CurIndex++) {\r
32465d9a 867 if (mMacDeviceList.NodeList[CurIndex].QuestionId == QuestionId) {\r
1436aea4 868 mSelectedMacAddrString = HiiGetString (gDeviceManagerPrivate.HiiHandle, mMacDeviceList.NodeList[CurIndex].PromptId, NULL);\r
32465d9a
DB
869 }\r
870 }\r
1436aea4
MK
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
32465d9a
DB
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
3910f669 892DeviceManagerUiLibConstructor (\r
1436aea4
MK
893 IN EFI_HANDLE ImageHandle,\r
894 IN EFI_SYSTEM_TABLE *SystemTable\r
895 )\r
32465d9a 896{\r
1436aea4 897 EFI_STATUS Status;\r
32465d9a
DB
898\r
899 gDeviceManagerPrivate.DriverHandle = NULL;\r
1436aea4
MK
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
32465d9a
DB
908 ASSERT_EFI_ERROR (Status);\r
909\r
910 //\r
911 // Publish our HII data.\r
912 //\r
913 gDeviceManagerPrivate.HiiHandle = HiiAddPackages (\r
1436aea4
MK
914 &mDeviceManagerGuid,\r
915 gDeviceManagerPrivate.DriverHandle,\r
916 DeviceManagerVfrBin,\r
917 DeviceManagerUiLibStrings,\r
918 NULL\r
919 );\r
32465d9a
DB
920 ASSERT (gDeviceManagerPrivate.HiiHandle != NULL);\r
921\r
13406bde
AB
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
32465d9a 929 //\r
d1102dba 930 // Update boot manager page\r
32465d9a
DB
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
1436aea4
MK
947DeviceManagerUiLibDestructor (\r
948 IN EFI_HANDLE ImageHandle,\r
949 IN EFI_SYSTEM_TABLE *SystemTable\r
950 )\r
32465d9a 951{\r
1436aea4 952 EFI_STATUS Status;\r
32465d9a
DB
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