]> git.proxmox.com Git - mirror_edk2.git/blame - MdeModulePkg/Universal/Network/VlanConfigDxe/VlanConfigImpl.c
1. Correct File header to ## @file
[mirror_edk2.git] / MdeModulePkg / Universal / Network / VlanConfigDxe / VlanConfigImpl.c
CommitLineData
779ae357 1/** @file\r
2 HII Config Access protocol implementation of VLAN configuration module.\r
3\r
e2851998 4Copyright (c) 2009 - 2010, Intel Corporation.<BR>\r
779ae357 5All rights reserved. This program and the accompanying materials\r
6are licensed and made available under the terms and conditions\r
7of the BSD License which accompanies this distribution. The full\r
8text of the license may be found at<BR>\r
9http://opensource.org/licenses/bsd-license.php\r
10\r
11THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
12WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
13\r
14**/\r
15\r
16#include "VlanConfigImpl.h"\r
17\r
18EFI_GUID mVlanFormSetGuid = VLAN_CONFIG_PRIVATE_GUID;\r
19CHAR16 mVlanStorageName[] = L"VlanNvData";\r
20EFI_HII_CONFIG_ROUTING_PROTOCOL *mHiiConfigRouting = NULL;\r
21\r
22VLAN_CONFIG_PRIVATE_DATA mVlanConfigPrivateDateTemplate = {\r
23 VLAN_CONFIG_PRIVATE_DATA_SIGNATURE,\r
24 {\r
25 VlanExtractConfig,\r
26 VlanRouteConfig,\r
27 VlanCallback\r
28 }\r
29};\r
30\r
31VENDOR_DEVICE_PATH mHiiVendorDevicePathNode = {\r
32 {\r
33 HARDWARE_DEVICE_PATH,\r
34 HW_VENDOR_DP,\r
35 {\r
36 (UINT8) (sizeof (VENDOR_DEVICE_PATH)),\r
37 (UINT8) ((sizeof (VENDOR_DEVICE_PATH)) >> 8)\r
38 }\r
39 },\r
40 VLAN_CONFIG_PRIVATE_GUID\r
41};\r
42\r
43/**\r
44 This function allows a caller to extract the current configuration for one\r
45 or more named elements from the target driver.\r
46\r
47 @param[in] This Points to the EFI_HII_CONFIG_ACCESS_PROTOCOL.\r
48 @param[in] Request A null-terminated Unicode string in\r
49 <ConfigRequest> format.\r
50 @param[out] Progress On return, points to a character in the Request\r
51 string. Points to the string's null terminator if\r
52 request was successful. Points to the most recent\r
53 '&' before the first failing name/value pair (or\r
54 the beginning of the string if the failure is in\r
55 the first name/value pair) if the request was not\r
56 successful.\r
57 @param[out] Results A null-terminated Unicode string in\r
58 <ConfigAltResp> format which has all values filled\r
59 in for the names in the Request string. String to\r
60 be allocated by the called function.\r
61\r
62 @retval EFI_SUCCESS The Results is filled with the requested values.\r
63 @retval EFI_OUT_OF_RESOURCES Not enough memory to store the results.\r
64 @retval EFI_INVALID_PARAMETER Request is NULL, illegal syntax, or unknown name.\r
65 @retval EFI_NOT_FOUND Routing data doesn't match any storage in this\r
66 driver.\r
67\r
68**/\r
69EFI_STATUS\r
70EFIAPI\r
71VlanExtractConfig (\r
72 IN CONST EFI_HII_CONFIG_ACCESS_PROTOCOL *This,\r
73 IN CONST EFI_STRING Request,\r
74 OUT EFI_STRING *Progress,\r
75 OUT EFI_STRING *Results\r
76 )\r
77{\r
78 EFI_STATUS Status;\r
79 UINTN BufferSize;\r
80 VLAN_CONFIGURATION Configuration;\r
81\r
82 if (Request == NULL) {\r
83 return EFI_INVALID_PARAMETER;\r
84 }\r
85\r
86 //\r
87 // Retrieve the pointer to the UEFI HII Config Routing Protocol\r
88 //\r
89 if (mHiiConfigRouting == NULL) {\r
90 gBS->LocateProtocol (&gEfiHiiConfigRoutingProtocolGuid, NULL, (VOID **) &mHiiConfigRouting);\r
91 }\r
92 ASSERT (mHiiConfigRouting != NULL);\r
93\r
94 //\r
95 // Convert buffer data to <ConfigResp> by helper function BlockToConfig()\r
96 //\r
97 ZeroMem (&Configuration, sizeof (VLAN_CONFIGURATION));\r
98 BufferSize = sizeof (VLAN_CONFIG_PRIVATE_DATA);\r
99 Status = mHiiConfigRouting->BlockToConfig (\r
100 mHiiConfigRouting,\r
101 Request,\r
102 (UINT8 *) &Configuration,\r
103 BufferSize,\r
104 Results,\r
105 Progress\r
106 );\r
107 return Status;\r
108}\r
109\r
110\r
111/**\r
112 This function processes the results of changes in configuration.\r
113\r
114 @param[in] This Points to the EFI_HII_CONFIG_ACCESS_PROTOCOL.\r
115 @param[in] Configuration A null-terminated Unicode string in <ConfigResp>\r
116 format.\r
117 @param[out] Progress A pointer to a string filled in with the offset of\r
118 the most recent '&' before the first failing\r
119 name/value pair (or the beginning of the string if\r
120 the failure is in the first name/value pair) or\r
121 the terminating NULL if all was successful.\r
122\r
123 @retval EFI_SUCCESS The Results is processed successfully.\r
124 @retval EFI_INVALID_PARAMETER Configuration is NULL.\r
125 @retval EFI_NOT_FOUND Routing data doesn't match any storage in this\r
126 driver.\r
127\r
128**/\r
129EFI_STATUS\r
130EFIAPI\r
131VlanRouteConfig (\r
132 IN CONST EFI_HII_CONFIG_ACCESS_PROTOCOL *This,\r
133 IN CONST EFI_STRING Configuration,\r
134 OUT EFI_STRING *Progress\r
135 )\r
136{\r
137 if (Configuration == NULL || Progress == NULL) {\r
138 return EFI_INVALID_PARAMETER;\r
139 }\r
140\r
141 *Progress = Configuration;\r
142 if (!HiiIsConfigHdrMatch (Configuration, &mVlanFormSetGuid, mVlanStorageName)) {\r
143 return EFI_NOT_FOUND;\r
144 }\r
145\r
146 *Progress = Configuration + StrLen (Configuration);\r
147 return EFI_SUCCESS;\r
148}\r
149\r
150/**\r
151 This function processes the results of changes in configuration.\r
152\r
153 @param[in] This Points to the EFI_HII_CONFIG_ACCESS_PROTOCOL.\r
154 @param[in] Action Specifies the type of action taken by the browser.\r
155 @param[in] QuestionId A unique value which is sent to the original\r
156 exporting driver so that it can identify the type\r
157 of data to expect.\r
158 @param[in] Type The type of value for the question.\r
159 @param[in] Value A pointer to the data being sent to the original\r
160 exporting driver.\r
161 @param[out] ActionRequest On return, points to the action requested by the\r
162 callback function.\r
163\r
164 @retval EFI_SUCCESS The callback successfully handled the action.\r
165 @retval EFI_OUT_OF_RESOURCES Not enough storage is available to hold the\r
166 variable and its data.\r
167 @retval EFI_DEVICE_ERROR The variable could not be saved.\r
168 @retval EFI_UNSUPPORTED The specified Action is not supported by the\r
169 callback.\r
170\r
171**/\r
172EFI_STATUS\r
173EFIAPI\r
174VlanCallback (\r
175 IN CONST EFI_HII_CONFIG_ACCESS_PROTOCOL *This,\r
176 IN EFI_BROWSER_ACTION Action,\r
177 IN EFI_QUESTION_ID QuestionId,\r
178 IN UINT8 Type,\r
179 IN EFI_IFR_TYPE_VALUE *Value,\r
180 OUT EFI_BROWSER_ACTION_REQUEST *ActionRequest\r
181 )\r
182{\r
183 VLAN_CONFIG_PRIVATE_DATA *PrivateData;\r
184 VLAN_CONFIGURATION *Configuration;\r
185 EFI_VLAN_CONFIG_PROTOCOL *VlanConfig;\r
186 UINTN Index;\r
187 EFI_HANDLE VlanHandle;\r
188\r
189 PrivateData = VLAN_CONFIG_PRIVATE_DATA_FROM_THIS (This);\r
190\r
191 if (Action == EFI_BROWSER_ACTION_FORM_OPEN) {\r
192 //\r
193 // On FORM_OPEN event, update current VLAN list\r
194 //\r
195 VlanUpdateForm (PrivateData);\r
196\r
197 return EFI_SUCCESS;\r
198 }\r
199\r
200 //\r
201 // Get Browser data\r
202 //\r
203 Configuration = AllocateZeroPool (sizeof (VLAN_CONFIGURATION));\r
204 ASSERT (Configuration != NULL);\r
205 HiiGetBrowserData (&mVlanFormSetGuid, mVlanStorageName, sizeof (VLAN_CONFIGURATION), (UINT8 *) Configuration);\r
206\r
207 VlanConfig = PrivateData->VlanConfig;\r
208\r
209 switch (QuestionId) {\r
210 case VLAN_ADD_QUESTION_ID:\r
211 //\r
212 // Add a VLAN\r
213 //\r
214 VlanConfig->Set (VlanConfig, Configuration->VlanId, Configuration->Priority);\r
215 VlanUpdateForm (PrivateData);\r
216\r
217 //\r
218 // Connect the newly created VLAN device\r
219 //\r
220 VlanHandle = NetLibGetVlanHandle (PrivateData->ControllerHandle, Configuration->VlanId);\r
221 if (VlanHandle == NULL) {\r
222 //\r
223 // There may be no child handle created for VLAN ID 0, connect the parent handle\r
224 //\r
225 VlanHandle = PrivateData->ControllerHandle;\r
226 }\r
227 gBS->ConnectController (VlanHandle, NULL, NULL, TRUE);\r
228\r
229 //\r
230 // Clear UI data\r
231 //\r
232 *ActionRequest = EFI_BROWSER_ACTION_REQUEST_SUBMIT;\r
233 Configuration->VlanId = 0;\r
234 Configuration->Priority = 0;\r
235 break;\r
236\r
237 case VLAN_REMOVE_QUESTION_ID:\r
238 //\r
239 // Remove VLAN\r
240 //\r
e2851998 241 ASSERT (PrivateData->NumberOfVlan <= MAX_VLAN_NUMBER);\r
779ae357 242 for (Index = 0; Index < PrivateData->NumberOfVlan; Index++) {\r
243 if (Configuration->VlanList[Index] != 0) {\r
244 //\r
245 // Checkbox is selected, need remove this VLAN\r
246 //\r
247 VlanConfig->Remove (VlanConfig, PrivateData->VlanId[Index]);\r
248 }\r
249 }\r
250\r
251 VlanUpdateForm (PrivateData);\r
252 if (PrivateData->NumberOfVlan == 0) {\r
253 //\r
254 // No VLAN device now, connect the physical NIC handle.\r
255 // Note: PrivateData->NumberOfVlan has been updated by VlanUpdateForm()\r
256 //\r
257 gBS->ConnectController (PrivateData->ControllerHandle, NULL, NULL, TRUE);\r
258 }\r
259\r
260 *ActionRequest = EFI_BROWSER_ACTION_REQUEST_SUBMIT;\r
261 ZeroMem (Configuration->VlanList, MAX_VLAN_NUMBER);\r
262 break;\r
263\r
264 default:\r
265 break;\r
266 }\r
267\r
268 HiiSetBrowserData (&mVlanFormSetGuid, mVlanStorageName, sizeof (VLAN_CONFIGURATION), (UINT8 *) Configuration, NULL);\r
269 FreePool (Configuration);\r
270 return EFI_SUCCESS;\r
271}\r
272\r
273\r
274/**\r
275 This function update VLAN list in the VLAN configuration Form.\r
276\r
277 @param[in, out] PrivateData Points to VLAN configuration private data.\r
278\r
279**/\r
280VOID\r
281VlanUpdateForm (\r
282 IN OUT VLAN_CONFIG_PRIVATE_DATA *PrivateData\r
283 )\r
284{\r
285 EFI_VLAN_CONFIG_PROTOCOL *VlanConfig;\r
286 UINT16 NumberOfVlan;\r
287 UINTN Index;\r
288 EFI_VLAN_FIND_DATA *VlanData;\r
289 VOID *StartOpCodeHandle;\r
290 EFI_IFR_GUID_LABEL *StartLabel;\r
291 VOID *EndOpCodeHandle;\r
292 EFI_IFR_GUID_LABEL *EndLabel;\r
293 CHAR16 *String;\r
294 CHAR16 VlanStr[30];\r
295 CHAR16 VlanIdStr[6];\r
296 UINTN DigitalCount;\r
297 EFI_STRING_ID StringId;\r
298\r
299 //\r
300 // Find current VLAN configuration\r
301 //\r
302 VlanData = NULL;\r
303 NumberOfVlan = 0;\r
304 VlanConfig = PrivateData->VlanConfig;\r
305 VlanConfig->Find (VlanConfig, NULL, &NumberOfVlan, &VlanData);\r
306\r
307 //\r
308 // Update VLAN configuration in PrivateData\r
309 //\r
310 if (NumberOfVlan > MAX_VLAN_NUMBER) {\r
311 NumberOfVlan = MAX_VLAN_NUMBER;\r
312 }\r
313 PrivateData->NumberOfVlan = NumberOfVlan;\r
314\r
315 //\r
316 // Init OpCode Handle\r
317 //\r
318 StartOpCodeHandle = HiiAllocateOpCodeHandle ();\r
319 ASSERT (StartOpCodeHandle != NULL);\r
320\r
321 EndOpCodeHandle = HiiAllocateOpCodeHandle ();\r
322 ASSERT (EndOpCodeHandle != NULL);\r
323\r
324 //\r
325 // Create Hii Extend Label OpCode as the start opcode\r
326 //\r
327 StartLabel = (EFI_IFR_GUID_LABEL *) HiiCreateGuidOpCode (\r
328 StartOpCodeHandle,\r
329 &gEfiIfrTianoGuid,\r
330 NULL,\r
331 sizeof (EFI_IFR_GUID_LABEL)\r
332 );\r
333 StartLabel->ExtendOpCode = EFI_IFR_EXTEND_OP_LABEL;\r
334 StartLabel->Number = LABEL_VLAN_LIST;\r
335\r
336 //\r
337 // Create Hii Extend Label OpCode as the end opcode\r
338 //\r
339 EndLabel = (EFI_IFR_GUID_LABEL *) HiiCreateGuidOpCode (\r
340 EndOpCodeHandle,\r
341 &gEfiIfrTianoGuid,\r
342 NULL,\r
343 sizeof (EFI_IFR_GUID_LABEL)\r
344 );\r
345 EndLabel->ExtendOpCode = EFI_IFR_EXTEND_OP_LABEL;\r
346 EndLabel->Number = LABEL_END;\r
347\r
348 ZeroMem (PrivateData->VlanId, MAX_VLAN_NUMBER);\r
349 for (Index = 0; Index < NumberOfVlan; Index++) {\r
350 String = VlanStr;\r
351\r
352 StrCpy (String, L" VLAN ID:");\r
353 String += 10;\r
354 //\r
355 // Pad VlanId string up to 4 characters with space\r
356 //\r
357 DigitalCount = UnicodeValueToString (VlanIdStr, 0, VlanData[Index].VlanId, 5);\r
358 SetMem16 (String, (4 - DigitalCount) * sizeof (CHAR16), L' ');\r
359 StrCpy (String + 4 - DigitalCount, VlanIdStr);\r
360 String += 4;\r
361\r
362 StrCpy (String, L", Priority:");\r
363 String += 11;\r
364 String += UnicodeValueToString (String, 0, VlanData[Index].Priority, 4);\r
365 *String = 0;\r
366\r
367 StringId = HiiSetString (PrivateData->HiiHandle, 0, VlanStr, NULL);\r
368 ASSERT (StringId != 0);\r
369\r
370 HiiCreateCheckBoxOpCode (\r
371 StartOpCodeHandle,\r
372 (EFI_QUESTION_ID) (VLAN_LIST_VAR_OFFSET + Index),\r
373 VLAN_CONFIGURATION_VARSTORE_ID,\r
374 (UINT16) (VLAN_LIST_VAR_OFFSET + Index),\r
375 StringId,\r
376 STRING_TOKEN (STR_VLAN_VLAN_LIST_HELP),\r
377 0,\r
378 0,\r
379 NULL\r
380 );\r
381\r
382 //\r
383 // Save VLAN id to private data\r
384 //\r
385 PrivateData->VlanId[Index] = VlanData[Index].VlanId;\r
386 }\r
387\r
388 HiiUpdateForm (\r
389 PrivateData->HiiHandle, // HII handle\r
390 &mVlanFormSetGuid, // Formset GUID\r
391 VLAN_CONFIGURATION_FORM_ID, // Form ID\r
392 StartOpCodeHandle, // Label for where to insert opcodes\r
393 EndOpCodeHandle // Replace data\r
394 );\r
395\r
396 HiiFreeOpCodeHandle (StartOpCodeHandle);\r
397 HiiFreeOpCodeHandle (EndOpCodeHandle);\r
398\r
399 if (VlanData != NULL) {\r
400 FreePool (VlanData);\r
401 }\r
402}\r
403\r
404\r
405/**\r
406 This function publish the VLAN configuration Form for a network device. The\r
407 HII Config Access protocol will be installed on a child handle of the network\r
408 device.\r
409\r
410 @param[in, out] PrivateData Points to VLAN configuration private data.\r
411\r
412 @retval EFI_SUCCESS HII Form is installed for this network device.\r
413 @retval EFI_OUT_OF_RESOURCES Not enough resource for HII Form installation.\r
414 @retval Others Other errors as indicated.\r
415\r
416**/\r
417EFI_STATUS\r
418InstallVlanConfigForm (\r
419 IN OUT VLAN_CONFIG_PRIVATE_DATA *PrivateData\r
420 )\r
421{\r
422 EFI_STATUS Status;\r
423 EFI_HII_HANDLE HiiHandle;\r
424 EFI_HANDLE DriverHandle;\r
e2851998 425 CHAR16 Str[26 + sizeof (EFI_MAC_ADDRESS) * 2 + 1];\r
779ae357 426 CHAR16 *MacString;\r
427 EFI_DEVICE_PATH_PROTOCOL *ChildDevicePath;\r
428 EFI_HII_CONFIG_ACCESS_PROTOCOL *ConfigAccess;\r
429\r
430 //\r
431 // Create child handle and install HII Config Access Protocol\r
432 //\r
433 ChildDevicePath = AppendDevicePathNode (\r
434 PrivateData->ParentDevicePath,\r
435 (CONST EFI_DEVICE_PATH_PROTOCOL *) &mHiiVendorDevicePathNode\r
436 );\r
437 if (ChildDevicePath == NULL) {\r
438 return EFI_OUT_OF_RESOURCES;\r
439 }\r
440 PrivateData->ChildDevicePath = ChildDevicePath;\r
441\r
442 DriverHandle = NULL;\r
443 ConfigAccess = &PrivateData->ConfigAccess;\r
444 Status = gBS->InstallMultipleProtocolInterfaces (\r
445 &DriverHandle,\r
446 &gEfiDevicePathProtocolGuid,\r
447 ChildDevicePath,\r
448 &gEfiHiiConfigAccessProtocolGuid,\r
449 ConfigAccess,\r
450 NULL\r
451 );\r
452 if (EFI_ERROR (Status)) {\r
453 return Status;\r
454 }\r
455 PrivateData->DriverHandle = DriverHandle;\r
456\r
457 //\r
458 // Publish the HII package list\r
459 //\r
460 HiiHandle = HiiAddPackages (\r
461 &mVlanFormSetGuid,\r
462 DriverHandle,\r
463 VlanConfigDxeStrings,\r
464 VlanConfigBin,\r
465 NULL\r
466 );\r
467 if (HiiHandle == NULL) {\r
468 return EFI_OUT_OF_RESOURCES;\r
469 }\r
470 PrivateData->HiiHandle = HiiHandle;\r
471\r
472 //\r
473 // Update formset title\r
474 //\r
475 MacString = NULL;\r
476 Status = NetLibGetMacString (PrivateData->ControllerHandle, PrivateData->ImageHandle, &MacString);\r
477 if (EFI_ERROR (Status)) {\r
478 return Status;\r
479 }\r
480 PrivateData->MacString = MacString;\r
481\r
482 StrCpy (Str, L"VLAN Configuration (MAC:");\r
1b2bf3ca 483 StrnCat (Str, MacString, sizeof (EFI_MAC_ADDRESS) * 2);\r
779ae357 484 StrCat (Str, L")");\r
485 HiiSetString (\r
486 HiiHandle,\r
487 STRING_TOKEN (STR_VLAN_FORM_SET_TITLE),\r
488 Str,\r
489 NULL\r
490 );\r
491\r
492 //\r
493 // Update form title\r
494 //\r
495 HiiSetString (\r
496 HiiHandle,\r
497 STRING_TOKEN (STR_VLAN_FORM_TITLE),\r
498 Str,\r
499 NULL\r
500 );\r
501\r
502 return EFI_SUCCESS;\r
503}\r
504\r
505/**\r
506 This function remove the VLAN configuration Form for a network device. The\r
507 child handle for HII Config Access protocol will be destroyed.\r
508\r
509 @param[in, out] PrivateData Points to VLAN configuration private data.\r
510\r
511**/\r
512VOID\r
513UninstallVlanConfigForm (\r
514 IN OUT VLAN_CONFIG_PRIVATE_DATA *PrivateData\r
515 )\r
516{\r
517 //\r
518 // Free MAC string\r
519 //\r
520 if (PrivateData->MacString != NULL) {\r
521 FreePool (PrivateData->MacString);\r
522 PrivateData->MacString = NULL;\r
523 }\r
524\r
525 //\r
526 // Uninstall HII package list\r
527 //\r
528 if (PrivateData->HiiHandle != NULL) {\r
529 HiiRemovePackages (PrivateData->HiiHandle);\r
530 PrivateData->HiiHandle = NULL;\r
531 }\r
532\r
533 //\r
534 // Uninstall HII Config Access Protocol\r
535 //\r
536 if (PrivateData->DriverHandle != NULL) {\r
537 gBS->UninstallMultipleProtocolInterfaces (\r
538 PrivateData->DriverHandle,\r
539 &gEfiDevicePathProtocolGuid,\r
540 PrivateData->ChildDevicePath,\r
541 &gEfiHiiConfigAccessProtocolGuid,\r
542 &PrivateData->ConfigAccess,\r
543 NULL\r
544 );\r
545 PrivateData->DriverHandle = NULL;\r
546\r
547 if (PrivateData->ChildDevicePath != NULL) {\r
548 FreePool (PrivateData->ChildDevicePath);\r
549 PrivateData->ChildDevicePath = NULL;\r
550 }\r
551 }\r
552}\r