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