]> git.proxmox.com Git - mirror_edk2.git/blame - MdeModulePkg/Universal/Network/MnpDxe/MnpVlan.c
Removes MacString Rt attribute in Ip4Config/Mnp driver.
[mirror_edk2.git] / MdeModulePkg / Universal / Network / MnpDxe / MnpVlan.c
CommitLineData
779ae357 1/** @file\r
2 VLAN Config Protocol implementation and VLAN packet process routine.\r
3\r
d120b462 4Copyright (c) 2009 - 2014, Intel Corporation. All rights reserved.<BR>\r
e5eed7d3 5This program and the accompanying materials\r
779ae357 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 "MnpImpl.h"\r
17#include "MnpVlan.h"\r
18\r
19VLAN_DEVICE_PATH mVlanDevicePathTemplate = {\r
20 {\r
21 MESSAGING_DEVICE_PATH,\r
22 MSG_VLAN_DP,\r
23 {\r
24 (UINT8) (sizeof (VLAN_DEVICE_PATH)),\r
25 (UINT8) ((sizeof (VLAN_DEVICE_PATH)) >> 8)\r
26 }\r
27 },\r
28 0\r
29};\r
30\r
31EFI_VLAN_CONFIG_PROTOCOL mVlanConfigProtocolTemplate = {\r
32 VlanConfigSet,\r
33 VlanConfigFind,\r
34 VlanConfigRemove\r
35};\r
36\r
37\r
38/**\r
39 Create a child handle for the VLAN ID.\r
40\r
41 @param[in] ImageHandle The driver image handle.\r
42 @param[in] ControllerHandle Handle of device to bind driver to.\r
43 @param[in] VlanId The VLAN ID.\r
44 @param[out] Devicepath Pointer to returned device path for child handle.\r
45\r
46 @return The handle of VLAN child or NULL if failed to create VLAN child.\r
47\r
48**/\r
49EFI_HANDLE\r
50MnpCreateVlanChild (\r
51 IN EFI_HANDLE ImageHandle,\r
52 IN EFI_HANDLE ControllerHandle,\r
53 IN UINT16 VlanId,\r
54 OUT EFI_DEVICE_PATH_PROTOCOL **Devicepath OPTIONAL\r
55 )\r
56{\r
57 EFI_HANDLE ChildHandle;\r
58 VLAN_DEVICE_PATH VlanNode;\r
59 EFI_DEVICE_PATH_PROTOCOL *ParentDevicePath;\r
60 EFI_DEVICE_PATH_PROTOCOL *VlanDevicePath;\r
61 EFI_STATUS Status;\r
62\r
63 //\r
64 // Try to get parent device path\r
65 //\r
66 Status = gBS->OpenProtocol (\r
67 ControllerHandle,\r
68 &gEfiDevicePathProtocolGuid,\r
69 (VOID **) &ParentDevicePath,\r
70 ImageHandle,\r
71 ControllerHandle,\r
72 EFI_OPEN_PROTOCOL_GET_PROTOCOL\r
73 );\r
74 if (EFI_ERROR (Status)) {\r
75 return NULL;\r
76 }\r
77\r
78 //\r
79 // Construct device path for child handle: MAC + VLAN\r
80 //\r
81 CopyMem (&VlanNode, &mVlanDevicePathTemplate, sizeof (VLAN_DEVICE_PATH));\r
82 VlanNode.VlanId = VlanId;\r
83 VlanDevicePath = AppendDevicePathNode (\r
84 ParentDevicePath,\r
85 (EFI_DEVICE_PATH_PROTOCOL *) &VlanNode\r
86 );\r
87 if (VlanDevicePath == NULL) {\r
88 return NULL;\r
89 }\r
90\r
91 //\r
92 // Create child VLAN handle by installing DevicePath protocol\r
93 //\r
94 ChildHandle = NULL;\r
95 Status = gBS->InstallMultipleProtocolInterfaces (\r
96 &ChildHandle,\r
97 &gEfiDevicePathProtocolGuid,\r
98 VlanDevicePath,\r
99 NULL\r
100 );\r
101 if (EFI_ERROR (Status)) {\r
102 FreePool (VlanDevicePath);\r
103 return NULL;\r
104 }\r
105\r
106 if (Devicepath != NULL) {\r
107 *Devicepath = VlanDevicePath;\r
108 }\r
109\r
110 return ChildHandle;\r
111}\r
112\r
113/**\r
114 Remove VLAN tag from a packet.\r
115\r
116 @param[in, out] MnpDeviceData Pointer to the mnp device context data.\r
117 @param[in, out] Nbuf Pointer to the NET_BUF to remove VLAN tag.\r
118 @param[out] VlanId Pointer to the returned VLAN ID.\r
119\r
120 @retval TRUE VLAN tag is removed from this packet.\r
121 @retval FALSE There is no VLAN tag in this packet.\r
122\r
123**/\r
124BOOLEAN\r
125MnpRemoveVlanTag (\r
126 IN OUT MNP_DEVICE_DATA *MnpDeviceData,\r
127 IN OUT NET_BUF *Nbuf,\r
128 OUT UINT16 *VlanId\r
129 )\r
130{\r
131 UINT8 *Packet;\r
132 UINTN ProtocolOffset;\r
133 UINT16 ProtocolType;\r
134 VLAN_TCI VlanTag;\r
135\r
136 ProtocolOffset = MnpDeviceData->Snp->Mode->HwAddressSize * 2;\r
137\r
138 //\r
139 // Get the packet buffer.\r
140 //\r
141 Packet = NetbufGetByte (Nbuf, 0, NULL);\r
142 ASSERT (Packet != NULL);\r
143\r
144 //\r
145 // Check whether this is VLAN tagged frame by Ether Type\r
146 //\r
147 *VlanId = 0;\r
148 ProtocolType = NTOHS (*(UINT16 *) (Packet + ProtocolOffset));\r
149 if (ProtocolType != ETHER_TYPE_VLAN) {\r
150 //\r
151 // Not a VLAN tagged frame\r
152 //\r
153 return FALSE;\r
154 }\r
155\r
156 VlanTag.Uint16 = NTOHS (*(UINT16 *) (Packet + ProtocolOffset + sizeof (ProtocolType)));\r
157 *VlanId = VlanTag.Bits.Vid;\r
158\r
159 //\r
160 // Move hardware address (DA + SA) 4 bytes right to override VLAN tag\r
161 //\r
162 CopyMem (Packet + NET_VLAN_TAG_LEN, Packet, ProtocolOffset);\r
163\r
164 //\r
165 // Remove VLAN tag from the Nbuf\r
166 //\r
167 NetbufTrim (Nbuf, NET_VLAN_TAG_LEN, NET_BUF_HEAD);\r
168\r
169 return TRUE;\r
170}\r
171\r
172\r
173/**\r
bdebd2ce 174 Build the vlan packet to transmit from the TxData passed in.\r
779ae357 175\r
176 @param MnpServiceData Pointer to the mnp service context data.\r
177 @param TxData Pointer to the transmit data containing the\r
178 information to build the packet.\r
179 @param ProtocolType Pointer to the Ethernet protocol type.\r
180 @param Packet Pointer to record the address of the packet.\r
181 @param Length Pointer to a UINT32 variable used to record the\r
182 packet's length.\r
183\r
184**/\r
185VOID\r
186MnpInsertVlanTag (\r
187 IN MNP_SERVICE_DATA *MnpServiceData,\r
188 IN EFI_MANAGED_NETWORK_TRANSMIT_DATA *TxData,\r
189 OUT UINT16 *ProtocolType,\r
190 IN OUT UINT8 **Packet,\r
191 IN OUT UINT32 *Length\r
192 )\r
193{\r
194 VLAN_TCI *VlanTci;\r
195 UINT16 *Tpid;\r
196 UINT16 *EtherType;\r
197 MNP_DEVICE_DATA *MnpDeviceData;\r
198 EFI_SIMPLE_NETWORK_MODE *SnpMode;\r
199\r
779ae357 200 MnpDeviceData = MnpServiceData->MnpDeviceData;\r
201 SnpMode = MnpDeviceData->Snp->Mode;\r
202\r
203 *ProtocolType = ETHER_TYPE_VLAN;\r
204 *Length = *Length + NET_VLAN_TAG_LEN;\r
205 *Packet = *Packet - NET_VLAN_TAG_LEN;\r
206\r
207 Tpid = (UINT16 *) (*Packet + SnpMode->MediaHeaderSize - sizeof (*ProtocolType));\r
208 VlanTci = (VLAN_TCI *) (UINTN) (Tpid + 1);\r
209 if (TxData->HeaderLength != 0) {\r
210 //\r
211 // Media header is in packet, move DA+SA 4 bytes left\r
212 //\r
213 CopyMem (\r
214 *Packet,\r
215 *Packet + NET_VLAN_TAG_LEN,\r
216 SnpMode->MediaHeaderSize - sizeof (*ProtocolType)\r
217 );\r
218 *Tpid = HTONS (ETHER_TYPE_VLAN);\r
219 } else {\r
220 //\r
221 // Media header not in packet, VLAN TCI and original protocol type becomes payload\r
222 //\r
223 EtherType = (UINT16 *) (UINTN) (VlanTci + 1);\r
224 *EtherType = HTONS (TxData->ProtocolType);\r
225 }\r
226\r
227 VlanTci->Bits.Vid = MnpServiceData->VlanId;\r
228 VlanTci->Bits.Cfi = VLAN_TCI_CFI_CANONICAL_MAC;\r
229 VlanTci->Bits.Priority = MnpServiceData->Priority;\r
230 VlanTci->Uint16 = HTONS (VlanTci->Uint16);\r
231}\r
232\r
233\r
234/**\r
235 Get VLAN configuration variable.\r
236\r
237 @param[in] MnpDeviceData Pointer to the MNP device context data.\r
238 @param[out] NumberOfVlan Pointer to number of VLAN to be returned.\r
239 @param[out] VlanVariable Pointer to the buffer to return requested\r
240 array of VLAN_TCI.\r
241\r
242 @retval EFI_SUCCESS The array of VLAN_TCI was returned in VlanVariable\r
243 and number of VLAN was returned in NumberOfVlan.\r
244 @retval EFI_NOT_FOUND VLAN configuration variable not found.\r
245 @retval EFI_OUT_OF_RESOURCES There is not enough pool memory to store the configuration.\r
246\r
247**/\r
248EFI_STATUS\r
249MnpGetVlanVariable (\r
250 IN MNP_DEVICE_DATA *MnpDeviceData,\r
251 OUT UINTN *NumberOfVlan,\r
252 OUT VLAN_TCI **VlanVariable\r
253 )\r
254{\r
255 UINTN BufferSize;\r
256 EFI_STATUS Status;\r
257 VLAN_TCI *Buffer;\r
258\r
259 //\r
260 // Get VLAN configuration from EFI Variable\r
261 //\r
262 Buffer = NULL;\r
263 BufferSize = 0;\r
264 Status = gRT->GetVariable (\r
265 MnpDeviceData->MacString,\r
266 &gEfiVlanConfigProtocolGuid,\r
267 NULL,\r
268 &BufferSize,\r
269 NULL\r
270 );\r
271 if (Status != EFI_BUFFER_TOO_SMALL) {\r
272 return EFI_NOT_FOUND;\r
273 }\r
274\r
275 //\r
276 // Allocate buffer to read the variable\r
277 //\r
278 Buffer = AllocateZeroPool (BufferSize);\r
279 if (Buffer == NULL) {\r
280 return EFI_OUT_OF_RESOURCES;\r
281 }\r
282\r
283 Status = gRT->GetVariable (\r
284 MnpDeviceData->MacString,\r
285 &gEfiVlanConfigProtocolGuid,\r
286 NULL,\r
287 &BufferSize,\r
288 Buffer\r
289 );\r
290 if (EFI_ERROR (Status)) {\r
291 FreePool (Buffer);\r
292 return Status;\r
293 }\r
294\r
295 *NumberOfVlan = BufferSize / sizeof (VLAN_TCI);\r
296 *VlanVariable = Buffer;\r
297\r
298 return Status;\r
299}\r
300\r
301\r
302/**\r
303 Set VLAN configuration variable.\r
304\r
305 @param[in] MnpDeviceData Pointer to the MNP device context data.\r
306 @param[in] NumberOfVlan Number of VLAN in array VlanVariable.\r
307 @param[in] VlanVariable Pointer to array of VLAN_TCI.\r
308\r
309 @retval EFI_SUCCESS The VLAN variable is successfully set.\r
310 @retval EFI_OUT_OF_RESOURCES There is not enough resource to set the configuration.\r
311\r
312**/\r
313EFI_STATUS\r
314MnpSetVlanVariable (\r
315 IN MNP_DEVICE_DATA *MnpDeviceData,\r
316 IN UINTN NumberOfVlan,\r
317 IN VLAN_TCI *VlanVariable\r
318 )\r
319{\r
320 return gRT->SetVariable (\r
321 MnpDeviceData->MacString,\r
322 &gEfiVlanConfigProtocolGuid,\r
d120b462 323 EFI_VARIABLE_NON_VOLATILE | EFI_VARIABLE_BOOTSERVICE_ACCESS,\r
779ae357 324 NumberOfVlan * sizeof (VLAN_TCI),\r
325 VlanVariable\r
326 );\r
327}\r
328\r
329\r
330/**\r
331 Create a VLAN device or modify the configuration parameter of an\r
332 already-configured VLAN.\r
333\r
334 The Set() function is used to create a new VLAN device or change the VLAN\r
335 configuration parameters. If the VlanId hasn't been configured in the\r
336 physical Ethernet device, a new VLAN device will be created. If a VLAN with\r
337 this VlanId is already configured, then related configuration will be updated\r
338 as the input parameters.\r
339\r
340 If VlanId is zero, the VLAN device will send and receive untagged frames.\r
341 Otherwise, the VLAN device will send and receive VLAN-tagged frames containing the VlanId.\r
342 If VlanId is out of scope of (0-4094), EFI_INVALID_PARAMETER is returned.\r
343 If Priority is out of the scope of (0-7), then EFI_INVALID_PARAMETER is returned.\r
344 If there is not enough system memory to perform the registration, then\r
345 EFI_OUT_OF_RESOURCES is returned.\r
346\r
347 @param[in] This Points to the EFI_VLAN_CONFIG_PROTOCOL.\r
348 @param[in] VlanId A unique identifier (1-4094) of the VLAN which is being created\r
349 or modified, or zero (0).\r
350 @param[in] Priority 3 bit priority in VLAN header. Priority 0 is default value. If\r
351 VlanId is zero (0), Priority is ignored.\r
352\r
353 @retval EFI_SUCCESS The VLAN is successfully configured.\r
354 @retval EFI_INVALID_PARAMETER One or more of following conditions is TRUE:\r
355 - This is NULL.\r
356 - VlanId is an invalid VLAN Identifier.\r
357 - Priority is invalid.\r
358 @retval EFI_OUT_OF_RESOURCES There is not enough system memory to perform the registration.\r
359\r
360**/\r
361EFI_STATUS\r
362EFIAPI\r
363VlanConfigSet (\r
364 IN EFI_VLAN_CONFIG_PROTOCOL *This,\r
365 IN UINT16 VlanId,\r
366 IN UINT8 Priority\r
367 )\r
368{\r
369 EFI_STATUS Status;\r
370 MNP_DEVICE_DATA *MnpDeviceData;\r
371 MNP_SERVICE_DATA *MnpServiceData;\r
372 VLAN_TCI *OldVariable;\r
373 VLAN_TCI *NewVariable;\r
374 UINTN NumberOfVlan;\r
375 UINTN Index;\r
376 BOOLEAN IsAdd;\r
377 LIST_ENTRY *Entry;\r
378\r
379 if ((This == NULL) || (VlanId > 4094) || (Priority > 7)) {\r
380 return EFI_INVALID_PARAMETER;\r
381 }\r
382\r
383 IsAdd = FALSE;\r
384 MnpDeviceData = MNP_DEVICE_DATA_FROM_THIS (This);\r
385 if (MnpDeviceData->NumberOfVlan == 0) {\r
386 //\r
387 // No existing VLAN, this is the first VLAN to add\r
388 //\r
389 IsAdd = TRUE;\r
390 Entry = GetFirstNode (&MnpDeviceData->ServiceList);\r
391 MnpServiceData = MNP_SERVICE_DATA_FROM_LINK (Entry);\r
392\r
393 if (VlanId != 0) {\r
394 //\r
395 // VlanId is not 0, need destroy the default MNP service data\r
396 //\r
397 Status = MnpDestroyServiceChild (MnpServiceData);\r
398 if (EFI_ERROR (Status)) {\r
399 return Status;\r
400 }\r
401\r
402 Status = MnpDestroyServiceData (MnpServiceData);\r
403 if (EFI_ERROR (Status)) {\r
404 return Status;\r
405 }\r
406\r
407 //\r
408 // Create a new MNP service data for this VLAN\r
409 //\r
410 MnpServiceData = MnpCreateServiceData (MnpDeviceData, VlanId, Priority);\r
411 if (MnpServiceData == NULL) {\r
412 return EFI_OUT_OF_RESOURCES;\r
413 }\r
414 }\r
415 } else {\r
416 //\r
417 // Try to find VlanId in existing VLAN list\r
418 //\r
419 MnpServiceData = MnpFindServiceData (MnpDeviceData, VlanId);\r
420 if (MnpServiceData == NULL) {\r
421 //\r
422 // VlanId not found, create a new MNP service data\r
423 //\r
424 IsAdd = TRUE;\r
425 MnpServiceData = MnpCreateServiceData (MnpDeviceData, VlanId, Priority);\r
426 if (MnpServiceData == NULL) {\r
427 return EFI_OUT_OF_RESOURCES;\r
428 }\r
429 }\r
430 }\r
431\r
432 MnpServiceData->VlanId = VlanId;\r
433 MnpServiceData->Priority = Priority;\r
434 if (IsAdd) {\r
435 MnpDeviceData->NumberOfVlan++;\r
436 }\r
437\r
438 //\r
439 // Update VLAN configuration variable\r
440 //\r
441 OldVariable = NULL;\r
442 NewVariable = NULL;\r
443 NumberOfVlan = 0;\r
444 MnpGetVlanVariable (MnpDeviceData, &NumberOfVlan, &OldVariable);\r
445\r
446 if (IsAdd) {\r
447 //\r
448 // VLAN not exist - add\r
449 //\r
450 NewVariable = AllocateZeroPool ((NumberOfVlan + 1) * sizeof (VLAN_TCI));\r
451 if (NewVariable == NULL) {\r
452 Status = EFI_OUT_OF_RESOURCES;\r
453 goto Exit;\r
454 }\r
455\r
456 if (OldVariable != NULL) {\r
457 CopyMem (NewVariable, OldVariable, NumberOfVlan * sizeof (VLAN_TCI));\r
458 }\r
459\r
460 Index = NumberOfVlan++;\r
461 } else {\r
462 //\r
463 // VLAN already exist - update\r
464 //\r
465 for (Index = 0; Index < NumberOfVlan; Index++) {\r
466 if (OldVariable[Index].Bits.Vid == VlanId) {\r
467 break;\r
468 }\r
469 }\r
470 ASSERT (Index < NumberOfVlan);\r
471\r
472 NewVariable = OldVariable;\r
473 OldVariable = NULL;\r
474 }\r
475\r
476 NewVariable[Index].Bits.Vid = VlanId;\r
477 NewVariable[Index].Bits.Priority = Priority;\r
478\r
479 Status = MnpSetVlanVariable (MnpDeviceData, NumberOfVlan, NewVariable);\r
480 FreePool (NewVariable);\r
481\r
482Exit:\r
483 if (OldVariable != NULL) {\r
484 FreePool (OldVariable);\r
485 }\r
486\r
487 return Status;\r
488}\r
489\r
490\r
491/**\r
492 Find configuration information for specified VLAN or all configured VLANs.\r
493\r
494 The Find() function is used to find the configuration information for matching\r
495 VLAN and allocate a buffer into which those entries are copied.\r
496\r
497 @param[in] This Points to the EFI_VLAN_CONFIG_PROTOCOL.\r
498 @param[in] VlanId Pointer to VLAN identifier. Set to NULL to find all\r
499 configured VLANs.\r
500 @param[out] NumberOfVlan The number of VLANs which is found by the specified criteria.\r
501 @param[out] Entries The buffer which receive the VLAN configuration.\r
502\r
503 @retval EFI_SUCCESS The VLAN is successfully found.\r
504 @retval EFI_INVALID_PARAMETER One or more of following conditions is TRUE:\r
505 - This is NULL.\r
506 - Specified VlanId is invalid.\r
507 @retval EFI_NOT_FOUND No matching VLAN is found.\r
508\r
509**/\r
510EFI_STATUS\r
511EFIAPI\r
512VlanConfigFind (\r
513 IN EFI_VLAN_CONFIG_PROTOCOL *This,\r
514 IN UINT16 *VlanId OPTIONAL,\r
515 OUT UINT16 *NumberOfVlan,\r
516 OUT EFI_VLAN_FIND_DATA **Entries\r
517 )\r
518{\r
519 MNP_DEVICE_DATA *MnpDeviceData;\r
520 MNP_SERVICE_DATA *MnpServiceData;\r
521 LIST_ENTRY *Entry;\r
522 EFI_VLAN_FIND_DATA *VlanData;\r
523\r
524 if ((This == NULL) || (VlanId != NULL && *VlanId > 4094) || (NumberOfVlan == NULL) || (Entries == NULL)) {\r
525 return EFI_INVALID_PARAMETER;\r
526 }\r
527\r
528 *NumberOfVlan = 0;\r
529 *Entries = NULL;\r
530\r
531 MnpDeviceData = MNP_DEVICE_DATA_FROM_THIS (This);\r
532 if (MnpDeviceData->NumberOfVlan == 0) {\r
533 return EFI_NOT_FOUND;\r
534 }\r
535\r
536 if (VlanId == NULL) {\r
537 //\r
538 // Return all current VLAN configuration\r
539 //\r
540 *NumberOfVlan = (UINT16) MnpDeviceData->NumberOfVlan;\r
541 VlanData = AllocateZeroPool (*NumberOfVlan * sizeof (EFI_VLAN_FIND_DATA));\r
542 if (VlanData == NULL) {\r
543 return EFI_OUT_OF_RESOURCES;\r
544 }\r
545\r
546 *Entries = VlanData;\r
547 NET_LIST_FOR_EACH (Entry, &MnpDeviceData->ServiceList) {\r
548 MnpServiceData = MNP_SERVICE_DATA_FROM_LINK (Entry);\r
549\r
550 VlanData->VlanId = MnpServiceData->VlanId;\r
551 VlanData->Priority = MnpServiceData->Priority;\r
552 VlanData++;\r
553 }\r
554\r
555 return EFI_SUCCESS;\r
556 }\r
557\r
558 //\r
559 // VlanId is specified, try to find it in current VLAN list\r
560 //\r
561 MnpServiceData = MnpFindServiceData (MnpDeviceData, *VlanId);\r
562 if (MnpServiceData == NULL) {\r
563 return EFI_NOT_FOUND;\r
564 }\r
565\r
566 VlanData = AllocateZeroPool (sizeof (EFI_VLAN_FIND_DATA));\r
567 if (VlanData == NULL) {\r
568 return EFI_OUT_OF_RESOURCES;\r
569 }\r
570 VlanData->VlanId = MnpServiceData->VlanId;\r
571 VlanData->Priority = MnpServiceData->Priority;\r
572\r
573 *NumberOfVlan = 1;\r
574 *Entries = VlanData;\r
575\r
576 return EFI_SUCCESS;\r
577}\r
578\r
579\r
580/**\r
581 Remove the configured VLAN device.\r
582\r
583 The Remove() function is used to remove the specified VLAN device.\r
584 If the VlanId is out of the scope of (0-4094), EFI_INVALID_PARAMETER is returned.\r
585 If specified VLAN hasn't been previously configured, EFI_NOT_FOUND is returned.\r
586\r
587 @param[in] This Points to the EFI_VLAN_CONFIG_PROTOCOL.\r
588 @param[in] VlanId Identifier (0-4094) of the VLAN to be removed.\r
589\r
590 @retval EFI_SUCCESS The VLAN is successfully removed.\r
591 @retval EFI_INVALID_PARAMETER One or more of following conditions is TRUE:\r
592 - This is NULL.\r
593 - VlanId is an invalid parameter.\r
594 @retval EFI_NOT_FOUND The to-be-removed VLAN does not exist.\r
595\r
596**/\r
597EFI_STATUS\r
598EFIAPI\r
599VlanConfigRemove (\r
600 IN EFI_VLAN_CONFIG_PROTOCOL *This,\r
601 IN UINT16 VlanId\r
602 )\r
603{\r
604 EFI_STATUS Status;\r
605 MNP_DEVICE_DATA *MnpDeviceData;\r
606 MNP_SERVICE_DATA *MnpServiceData;\r
607 LIST_ENTRY *Entry;\r
608 VLAN_TCI *VlanVariable;\r
609 VLAN_TCI *VlanData;\r
610\r
611 if ((This == NULL) || (VlanId > 4094)) {\r
612 return EFI_INVALID_PARAMETER;\r
613 }\r
614\r
615 MnpDeviceData = MNP_DEVICE_DATA_FROM_THIS (This);\r
616 if (MnpDeviceData->NumberOfVlan == 0) {\r
617 return EFI_NOT_FOUND;\r
618 }\r
619\r
620 //\r
621 // Try to find the VlanId\r
622 //\r
623 MnpServiceData = MnpFindServiceData (MnpDeviceData, VlanId);\r
624 if (MnpServiceData == NULL) {\r
625 return EFI_NOT_FOUND;\r
626 }\r
627\r
628 MnpDeviceData->NumberOfVlan--;\r
629\r
630 if ((VlanId != 0) || (MnpDeviceData->NumberOfVlan != 0)) {\r
631 //\r
632 // If VlanId is not 0 or VlanId is 0 and it is not the last VLAN to remove,\r
633 // destroy its MNP service data\r
634 //\r
635 Status = MnpDestroyServiceChild (MnpServiceData);\r
636 if (EFI_ERROR (Status)) {\r
637 return Status;\r
638 }\r
639\r
640 Status = MnpDestroyServiceData (MnpServiceData);\r
641 if (EFI_ERROR (Status)) {\r
642 return Status;\r
643 }\r
644 }\r
645\r
646 if ((VlanId != 0) && (MnpDeviceData->NumberOfVlan == 0)) {\r
647 //\r
648 // This is the last VLAN to be removed, restore the default MNP service data\r
649 //\r
650 MnpServiceData = MnpCreateServiceData (MnpDeviceData, 0, 0);\r
651 if (MnpServiceData == NULL) {\r
652 return EFI_OUT_OF_RESOURCES;\r
653 }\r
654 }\r
655\r
656 //\r
657 // Update VLAN configuration variable\r
658 //\r
659 VlanVariable = NULL;\r
660 if (MnpDeviceData->NumberOfVlan != 0) {\r
661 VlanVariable = AllocatePool (MnpDeviceData->NumberOfVlan * sizeof (VLAN_TCI));\r
662 if (VlanVariable == NULL) {\r
663 return EFI_OUT_OF_RESOURCES;\r
664 }\r
665\r
666 VlanData = VlanVariable;\r
667 NET_LIST_FOR_EACH (Entry, &MnpDeviceData->ServiceList) {\r
668 MnpServiceData = MNP_SERVICE_DATA_FROM_LINK (Entry);\r
669\r
670 VlanData->Bits.Vid = MnpServiceData->VlanId;\r
671 VlanData->Bits.Priority = MnpServiceData->Priority;\r
672 VlanData++;\r
673 }\r
674 }\r
675\r
676 Status = MnpSetVlanVariable (MnpDeviceData, MnpDeviceData->NumberOfVlan, VlanVariable);\r
677\r
678 if (VlanVariable != NULL) {\r
679 FreePool (VlanVariable);\r
680 }\r
681\r
682 return Status;\r
683}\r