]> git.proxmox.com Git - mirror_edk2.git/blame - MdeModulePkg/Universal/Network/MnpDxe/MnpVlan.c
Update the copyright notice format
[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
e5eed7d3
HT
4Copyright (c) 2009, Intel Corporation. All rights reserved.<BR>\r
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
174 Build the packet to transmit from the TxData passed in.\r
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
200 if (MnpServiceData->VlanId == 0) {\r
201 *ProtocolType = TxData->ProtocolType;\r
202 return ;\r
203 }\r
204\r
205 MnpDeviceData = MnpServiceData->MnpDeviceData;\r
206 SnpMode = MnpDeviceData->Snp->Mode;\r
207\r
208 *ProtocolType = ETHER_TYPE_VLAN;\r
209 *Length = *Length + NET_VLAN_TAG_LEN;\r
210 *Packet = *Packet - NET_VLAN_TAG_LEN;\r
211\r
212 Tpid = (UINT16 *) (*Packet + SnpMode->MediaHeaderSize - sizeof (*ProtocolType));\r
213 VlanTci = (VLAN_TCI *) (UINTN) (Tpid + 1);\r
214 if (TxData->HeaderLength != 0) {\r
215 //\r
216 // Media header is in packet, move DA+SA 4 bytes left\r
217 //\r
218 CopyMem (\r
219 *Packet,\r
220 *Packet + NET_VLAN_TAG_LEN,\r
221 SnpMode->MediaHeaderSize - sizeof (*ProtocolType)\r
222 );\r
223 *Tpid = HTONS (ETHER_TYPE_VLAN);\r
224 } else {\r
225 //\r
226 // Media header not in packet, VLAN TCI and original protocol type becomes payload\r
227 //\r
228 EtherType = (UINT16 *) (UINTN) (VlanTci + 1);\r
229 *EtherType = HTONS (TxData->ProtocolType);\r
230 }\r
231\r
232 VlanTci->Bits.Vid = MnpServiceData->VlanId;\r
233 VlanTci->Bits.Cfi = VLAN_TCI_CFI_CANONICAL_MAC;\r
234 VlanTci->Bits.Priority = MnpServiceData->Priority;\r
235 VlanTci->Uint16 = HTONS (VlanTci->Uint16);\r
236}\r
237\r
238\r
239/**\r
240 Get VLAN configuration variable.\r
241\r
242 @param[in] MnpDeviceData Pointer to the MNP device context data.\r
243 @param[out] NumberOfVlan Pointer to number of VLAN to be returned.\r
244 @param[out] VlanVariable Pointer to the buffer to return requested\r
245 array of VLAN_TCI.\r
246\r
247 @retval EFI_SUCCESS The array of VLAN_TCI was returned in VlanVariable\r
248 and number of VLAN was returned in NumberOfVlan.\r
249 @retval EFI_NOT_FOUND VLAN configuration variable not found.\r
250 @retval EFI_OUT_OF_RESOURCES There is not enough pool memory to store the configuration.\r
251\r
252**/\r
253EFI_STATUS\r
254MnpGetVlanVariable (\r
255 IN MNP_DEVICE_DATA *MnpDeviceData,\r
256 OUT UINTN *NumberOfVlan,\r
257 OUT VLAN_TCI **VlanVariable\r
258 )\r
259{\r
260 UINTN BufferSize;\r
261 EFI_STATUS Status;\r
262 VLAN_TCI *Buffer;\r
263\r
264 //\r
265 // Get VLAN configuration from EFI Variable\r
266 //\r
267 Buffer = NULL;\r
268 BufferSize = 0;\r
269 Status = gRT->GetVariable (\r
270 MnpDeviceData->MacString,\r
271 &gEfiVlanConfigProtocolGuid,\r
272 NULL,\r
273 &BufferSize,\r
274 NULL\r
275 );\r
276 if (Status != EFI_BUFFER_TOO_SMALL) {\r
277 return EFI_NOT_FOUND;\r
278 }\r
279\r
280 //\r
281 // Allocate buffer to read the variable\r
282 //\r
283 Buffer = AllocateZeroPool (BufferSize);\r
284 if (Buffer == NULL) {\r
285 return EFI_OUT_OF_RESOURCES;\r
286 }\r
287\r
288 Status = gRT->GetVariable (\r
289 MnpDeviceData->MacString,\r
290 &gEfiVlanConfigProtocolGuid,\r
291 NULL,\r
292 &BufferSize,\r
293 Buffer\r
294 );\r
295 if (EFI_ERROR (Status)) {\r
296 FreePool (Buffer);\r
297 return Status;\r
298 }\r
299\r
300 *NumberOfVlan = BufferSize / sizeof (VLAN_TCI);\r
301 *VlanVariable = Buffer;\r
302\r
303 return Status;\r
304}\r
305\r
306\r
307/**\r
308 Set VLAN configuration variable.\r
309\r
310 @param[in] MnpDeviceData Pointer to the MNP device context data.\r
311 @param[in] NumberOfVlan Number of VLAN in array VlanVariable.\r
312 @param[in] VlanVariable Pointer to array of VLAN_TCI.\r
313\r
314 @retval EFI_SUCCESS The VLAN variable is successfully set.\r
315 @retval EFI_OUT_OF_RESOURCES There is not enough resource to set the configuration.\r
316\r
317**/\r
318EFI_STATUS\r
319MnpSetVlanVariable (\r
320 IN MNP_DEVICE_DATA *MnpDeviceData,\r
321 IN UINTN NumberOfVlan,\r
322 IN VLAN_TCI *VlanVariable\r
323 )\r
324{\r
325 return gRT->SetVariable (\r
326 MnpDeviceData->MacString,\r
327 &gEfiVlanConfigProtocolGuid,\r
328 EFI_VARIABLE_NON_VOLATILE | EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_RUNTIME_ACCESS,\r
329 NumberOfVlan * sizeof (VLAN_TCI),\r
330 VlanVariable\r
331 );\r
332}\r
333\r
334\r
335/**\r
336 Create a VLAN device or modify the configuration parameter of an\r
337 already-configured VLAN.\r
338\r
339 The Set() function is used to create a new VLAN device or change the VLAN\r
340 configuration parameters. If the VlanId hasn't been configured in the\r
341 physical Ethernet device, a new VLAN device will be created. If a VLAN with\r
342 this VlanId is already configured, then related configuration will be updated\r
343 as the input parameters.\r
344\r
345 If VlanId is zero, the VLAN device will send and receive untagged frames.\r
346 Otherwise, the VLAN device will send and receive VLAN-tagged frames containing the VlanId.\r
347 If VlanId is out of scope of (0-4094), EFI_INVALID_PARAMETER is returned.\r
348 If Priority is out of the scope of (0-7), then EFI_INVALID_PARAMETER is returned.\r
349 If there is not enough system memory to perform the registration, then\r
350 EFI_OUT_OF_RESOURCES is returned.\r
351\r
352 @param[in] This Points to the EFI_VLAN_CONFIG_PROTOCOL.\r
353 @param[in] VlanId A unique identifier (1-4094) of the VLAN which is being created\r
354 or modified, or zero (0).\r
355 @param[in] Priority 3 bit priority in VLAN header. Priority 0 is default value. If\r
356 VlanId is zero (0), Priority is ignored.\r
357\r
358 @retval EFI_SUCCESS The VLAN is successfully configured.\r
359 @retval EFI_INVALID_PARAMETER One or more of following conditions is TRUE:\r
360 - This is NULL.\r
361 - VlanId is an invalid VLAN Identifier.\r
362 - Priority is invalid.\r
363 @retval EFI_OUT_OF_RESOURCES There is not enough system memory to perform the registration.\r
364\r
365**/\r
366EFI_STATUS\r
367EFIAPI\r
368VlanConfigSet (\r
369 IN EFI_VLAN_CONFIG_PROTOCOL *This,\r
370 IN UINT16 VlanId,\r
371 IN UINT8 Priority\r
372 )\r
373{\r
374 EFI_STATUS Status;\r
375 MNP_DEVICE_DATA *MnpDeviceData;\r
376 MNP_SERVICE_DATA *MnpServiceData;\r
377 VLAN_TCI *OldVariable;\r
378 VLAN_TCI *NewVariable;\r
379 UINTN NumberOfVlan;\r
380 UINTN Index;\r
381 BOOLEAN IsAdd;\r
382 LIST_ENTRY *Entry;\r
383\r
384 if ((This == NULL) || (VlanId > 4094) || (Priority > 7)) {\r
385 return EFI_INVALID_PARAMETER;\r
386 }\r
387\r
388 IsAdd = FALSE;\r
389 MnpDeviceData = MNP_DEVICE_DATA_FROM_THIS (This);\r
390 if (MnpDeviceData->NumberOfVlan == 0) {\r
391 //\r
392 // No existing VLAN, this is the first VLAN to add\r
393 //\r
394 IsAdd = TRUE;\r
395 Entry = GetFirstNode (&MnpDeviceData->ServiceList);\r
396 MnpServiceData = MNP_SERVICE_DATA_FROM_LINK (Entry);\r
397\r
398 if (VlanId != 0) {\r
399 //\r
400 // VlanId is not 0, need destroy the default MNP service data\r
401 //\r
402 Status = MnpDestroyServiceChild (MnpServiceData);\r
403 if (EFI_ERROR (Status)) {\r
404 return Status;\r
405 }\r
406\r
407 Status = MnpDestroyServiceData (MnpServiceData);\r
408 if (EFI_ERROR (Status)) {\r
409 return Status;\r
410 }\r
411\r
412 //\r
413 // Create a new MNP service data for this VLAN\r
414 //\r
415 MnpServiceData = MnpCreateServiceData (MnpDeviceData, VlanId, Priority);\r
416 if (MnpServiceData == NULL) {\r
417 return EFI_OUT_OF_RESOURCES;\r
418 }\r
419 }\r
420 } else {\r
421 //\r
422 // Try to find VlanId in existing VLAN list\r
423 //\r
424 MnpServiceData = MnpFindServiceData (MnpDeviceData, VlanId);\r
425 if (MnpServiceData == NULL) {\r
426 //\r
427 // VlanId not found, create a new MNP service data\r
428 //\r
429 IsAdd = TRUE;\r
430 MnpServiceData = MnpCreateServiceData (MnpDeviceData, VlanId, Priority);\r
431 if (MnpServiceData == NULL) {\r
432 return EFI_OUT_OF_RESOURCES;\r
433 }\r
434 }\r
435 }\r
436\r
437 MnpServiceData->VlanId = VlanId;\r
438 MnpServiceData->Priority = Priority;\r
439 if (IsAdd) {\r
440 MnpDeviceData->NumberOfVlan++;\r
441 }\r
442\r
443 //\r
444 // Update VLAN configuration variable\r
445 //\r
446 OldVariable = NULL;\r
447 NewVariable = NULL;\r
448 NumberOfVlan = 0;\r
449 MnpGetVlanVariable (MnpDeviceData, &NumberOfVlan, &OldVariable);\r
450\r
451 if (IsAdd) {\r
452 //\r
453 // VLAN not exist - add\r
454 //\r
455 NewVariable = AllocateZeroPool ((NumberOfVlan + 1) * sizeof (VLAN_TCI));\r
456 if (NewVariable == NULL) {\r
457 Status = EFI_OUT_OF_RESOURCES;\r
458 goto Exit;\r
459 }\r
460\r
461 if (OldVariable != NULL) {\r
462 CopyMem (NewVariable, OldVariable, NumberOfVlan * sizeof (VLAN_TCI));\r
463 }\r
464\r
465 Index = NumberOfVlan++;\r
466 } else {\r
467 //\r
468 // VLAN already exist - update\r
469 //\r
470 for (Index = 0; Index < NumberOfVlan; Index++) {\r
471 if (OldVariable[Index].Bits.Vid == VlanId) {\r
472 break;\r
473 }\r
474 }\r
475 ASSERT (Index < NumberOfVlan);\r
476\r
477 NewVariable = OldVariable;\r
478 OldVariable = NULL;\r
479 }\r
480\r
481 NewVariable[Index].Bits.Vid = VlanId;\r
482 NewVariable[Index].Bits.Priority = Priority;\r
483\r
484 Status = MnpSetVlanVariable (MnpDeviceData, NumberOfVlan, NewVariable);\r
485 FreePool (NewVariable);\r
486\r
487Exit:\r
488 if (OldVariable != NULL) {\r
489 FreePool (OldVariable);\r
490 }\r
491\r
492 return Status;\r
493}\r
494\r
495\r
496/**\r
497 Find configuration information for specified VLAN or all configured VLANs.\r
498\r
499 The Find() function is used to find the configuration information for matching\r
500 VLAN and allocate a buffer into which those entries are copied.\r
501\r
502 @param[in] This Points to the EFI_VLAN_CONFIG_PROTOCOL.\r
503 @param[in] VlanId Pointer to VLAN identifier. Set to NULL to find all\r
504 configured VLANs.\r
505 @param[out] NumberOfVlan The number of VLANs which is found by the specified criteria.\r
506 @param[out] Entries The buffer which receive the VLAN configuration.\r
507\r
508 @retval EFI_SUCCESS The VLAN is successfully found.\r
509 @retval EFI_INVALID_PARAMETER One or more of following conditions is TRUE:\r
510 - This is NULL.\r
511 - Specified VlanId is invalid.\r
512 @retval EFI_NOT_FOUND No matching VLAN is found.\r
513\r
514**/\r
515EFI_STATUS\r
516EFIAPI\r
517VlanConfigFind (\r
518 IN EFI_VLAN_CONFIG_PROTOCOL *This,\r
519 IN UINT16 *VlanId OPTIONAL,\r
520 OUT UINT16 *NumberOfVlan,\r
521 OUT EFI_VLAN_FIND_DATA **Entries\r
522 )\r
523{\r
524 MNP_DEVICE_DATA *MnpDeviceData;\r
525 MNP_SERVICE_DATA *MnpServiceData;\r
526 LIST_ENTRY *Entry;\r
527 EFI_VLAN_FIND_DATA *VlanData;\r
528\r
529 if ((This == NULL) || (VlanId != NULL && *VlanId > 4094) || (NumberOfVlan == NULL) || (Entries == NULL)) {\r
530 return EFI_INVALID_PARAMETER;\r
531 }\r
532\r
533 *NumberOfVlan = 0;\r
534 *Entries = NULL;\r
535\r
536 MnpDeviceData = MNP_DEVICE_DATA_FROM_THIS (This);\r
537 if (MnpDeviceData->NumberOfVlan == 0) {\r
538 return EFI_NOT_FOUND;\r
539 }\r
540\r
541 if (VlanId == NULL) {\r
542 //\r
543 // Return all current VLAN configuration\r
544 //\r
545 *NumberOfVlan = (UINT16) MnpDeviceData->NumberOfVlan;\r
546 VlanData = AllocateZeroPool (*NumberOfVlan * sizeof (EFI_VLAN_FIND_DATA));\r
547 if (VlanData == NULL) {\r
548 return EFI_OUT_OF_RESOURCES;\r
549 }\r
550\r
551 *Entries = VlanData;\r
552 NET_LIST_FOR_EACH (Entry, &MnpDeviceData->ServiceList) {\r
553 MnpServiceData = MNP_SERVICE_DATA_FROM_LINK (Entry);\r
554\r
555 VlanData->VlanId = MnpServiceData->VlanId;\r
556 VlanData->Priority = MnpServiceData->Priority;\r
557 VlanData++;\r
558 }\r
559\r
560 return EFI_SUCCESS;\r
561 }\r
562\r
563 //\r
564 // VlanId is specified, try to find it in current VLAN list\r
565 //\r
566 MnpServiceData = MnpFindServiceData (MnpDeviceData, *VlanId);\r
567 if (MnpServiceData == NULL) {\r
568 return EFI_NOT_FOUND;\r
569 }\r
570\r
571 VlanData = AllocateZeroPool (sizeof (EFI_VLAN_FIND_DATA));\r
572 if (VlanData == NULL) {\r
573 return EFI_OUT_OF_RESOURCES;\r
574 }\r
575 VlanData->VlanId = MnpServiceData->VlanId;\r
576 VlanData->Priority = MnpServiceData->Priority;\r
577\r
578 *NumberOfVlan = 1;\r
579 *Entries = VlanData;\r
580\r
581 return EFI_SUCCESS;\r
582}\r
583\r
584\r
585/**\r
586 Remove the configured VLAN device.\r
587\r
588 The Remove() function is used to remove the specified VLAN device.\r
589 If the VlanId is out of the scope of (0-4094), EFI_INVALID_PARAMETER is returned.\r
590 If specified VLAN hasn't been previously configured, EFI_NOT_FOUND is returned.\r
591\r
592 @param[in] This Points to the EFI_VLAN_CONFIG_PROTOCOL.\r
593 @param[in] VlanId Identifier (0-4094) of the VLAN to be removed.\r
594\r
595 @retval EFI_SUCCESS The VLAN is successfully removed.\r
596 @retval EFI_INVALID_PARAMETER One or more of following conditions is TRUE:\r
597 - This is NULL.\r
598 - VlanId is an invalid parameter.\r
599 @retval EFI_NOT_FOUND The to-be-removed VLAN does not exist.\r
600\r
601**/\r
602EFI_STATUS\r
603EFIAPI\r
604VlanConfigRemove (\r
605 IN EFI_VLAN_CONFIG_PROTOCOL *This,\r
606 IN UINT16 VlanId\r
607 )\r
608{\r
609 EFI_STATUS Status;\r
610 MNP_DEVICE_DATA *MnpDeviceData;\r
611 MNP_SERVICE_DATA *MnpServiceData;\r
612 LIST_ENTRY *Entry;\r
613 VLAN_TCI *VlanVariable;\r
614 VLAN_TCI *VlanData;\r
615\r
616 if ((This == NULL) || (VlanId > 4094)) {\r
617 return EFI_INVALID_PARAMETER;\r
618 }\r
619\r
620 MnpDeviceData = MNP_DEVICE_DATA_FROM_THIS (This);\r
621 if (MnpDeviceData->NumberOfVlan == 0) {\r
622 return EFI_NOT_FOUND;\r
623 }\r
624\r
625 //\r
626 // Try to find the VlanId\r
627 //\r
628 MnpServiceData = MnpFindServiceData (MnpDeviceData, VlanId);\r
629 if (MnpServiceData == NULL) {\r
630 return EFI_NOT_FOUND;\r
631 }\r
632\r
633 MnpDeviceData->NumberOfVlan--;\r
634\r
635 if ((VlanId != 0) || (MnpDeviceData->NumberOfVlan != 0)) {\r
636 //\r
637 // If VlanId is not 0 or VlanId is 0 and it is not the last VLAN to remove,\r
638 // destroy its MNP service data\r
639 //\r
640 Status = MnpDestroyServiceChild (MnpServiceData);\r
641 if (EFI_ERROR (Status)) {\r
642 return Status;\r
643 }\r
644\r
645 Status = MnpDestroyServiceData (MnpServiceData);\r
646 if (EFI_ERROR (Status)) {\r
647 return Status;\r
648 }\r
649 }\r
650\r
651 if ((VlanId != 0) && (MnpDeviceData->NumberOfVlan == 0)) {\r
652 //\r
653 // This is the last VLAN to be removed, restore the default MNP service data\r
654 //\r
655 MnpServiceData = MnpCreateServiceData (MnpDeviceData, 0, 0);\r
656 if (MnpServiceData == NULL) {\r
657 return EFI_OUT_OF_RESOURCES;\r
658 }\r
659 }\r
660\r
661 //\r
662 // Update VLAN configuration variable\r
663 //\r
664 VlanVariable = NULL;\r
665 if (MnpDeviceData->NumberOfVlan != 0) {\r
666 VlanVariable = AllocatePool (MnpDeviceData->NumberOfVlan * sizeof (VLAN_TCI));\r
667 if (VlanVariable == NULL) {\r
668 return EFI_OUT_OF_RESOURCES;\r
669 }\r
670\r
671 VlanData = VlanVariable;\r
672 NET_LIST_FOR_EACH (Entry, &MnpDeviceData->ServiceList) {\r
673 MnpServiceData = MNP_SERVICE_DATA_FROM_LINK (Entry);\r
674\r
675 VlanData->Bits.Vid = MnpServiceData->VlanId;\r
676 VlanData->Bits.Priority = MnpServiceData->Priority;\r
677 VlanData++;\r
678 }\r
679 }\r
680\r
681 Status = MnpSetVlanVariable (MnpDeviceData, MnpDeviceData->NumberOfVlan, VlanVariable);\r
682\r
683 if (VlanVariable != NULL) {\r
684 FreePool (VlanVariable);\r
685 }\r
686\r
687 return Status;\r
688}\r