TianoCore EDK2 master
Loading...
Searching...
No Matches
MnpVlan.c
Go to the documentation of this file.
1
9#include "MnpImpl.h"
10#include "MnpVlan.h"
11
12VLAN_DEVICE_PATH mVlanDevicePathTemplate = {
13 {
16 {
17 (UINT8)(sizeof (VLAN_DEVICE_PATH)),
18 (UINT8)((sizeof (VLAN_DEVICE_PATH)) >> 8)
19 }
20 },
21 0
22};
23
24EFI_VLAN_CONFIG_PROTOCOL mVlanConfigProtocolTemplate = {
28};
29
43 IN EFI_HANDLE ImageHandle,
44 IN EFI_HANDLE ControllerHandle,
45 IN UINT16 VlanId,
46 OUT EFI_DEVICE_PATH_PROTOCOL **Devicepath OPTIONAL
47 )
48{
49 EFI_HANDLE ChildHandle;
50 VLAN_DEVICE_PATH VlanNode;
51 EFI_DEVICE_PATH_PROTOCOL *ParentDevicePath;
52 EFI_DEVICE_PATH_PROTOCOL *VlanDevicePath;
53 EFI_STATUS Status;
54
55 //
56 // Try to get parent device path
57 //
58 Status = gBS->OpenProtocol (
59 ControllerHandle,
60 &gEfiDevicePathProtocolGuid,
61 (VOID **)&ParentDevicePath,
62 ImageHandle,
63 ControllerHandle,
64 EFI_OPEN_PROTOCOL_GET_PROTOCOL
65 );
66 if (EFI_ERROR (Status)) {
67 return NULL;
68 }
69
70 //
71 // Construct device path for child handle: MAC + VLAN
72 //
73 CopyMem (&VlanNode, &mVlanDevicePathTemplate, sizeof (VLAN_DEVICE_PATH));
74 VlanNode.VlanId = VlanId;
75 VlanDevicePath = AppendDevicePathNode (
76 ParentDevicePath,
77 (EFI_DEVICE_PATH_PROTOCOL *)&VlanNode
78 );
79 if (VlanDevicePath == NULL) {
80 return NULL;
81 }
82
83 //
84 // Create child VLAN handle by installing DevicePath protocol
85 //
86 ChildHandle = NULL;
87 Status = gBS->InstallMultipleProtocolInterfaces (
88 &ChildHandle,
89 &gEfiDevicePathProtocolGuid,
90 VlanDevicePath,
91 NULL
92 );
93 if (EFI_ERROR (Status)) {
94 FreePool (VlanDevicePath);
95 return NULL;
96 }
97
98 if (Devicepath != NULL) {
99 *Devicepath = VlanDevicePath;
100 }
101
102 return ChildHandle;
103}
104
116BOOLEAN
118 IN OUT MNP_DEVICE_DATA *MnpDeviceData,
119 IN OUT NET_BUF *Nbuf,
120 OUT UINT16 *VlanId
121 )
122{
123 UINT8 *Packet;
124 UINTN ProtocolOffset;
125 UINT16 ProtocolType;
126 VLAN_TCI VlanTag;
127
128 ProtocolOffset = MnpDeviceData->Snp->Mode->HwAddressSize * 2;
129
130 //
131 // Get the packet buffer.
132 //
133 Packet = NetbufGetByte (Nbuf, 0, NULL);
134 ASSERT (Packet != NULL);
135
136 //
137 // Check whether this is VLAN tagged frame by Ether Type
138 //
139 *VlanId = 0;
140 ProtocolType = NTOHS (*(UINT16 *)(Packet + ProtocolOffset));
141 if (ProtocolType != ETHER_TYPE_VLAN) {
142 //
143 // Not a VLAN tagged frame
144 //
145 return FALSE;
146 }
147
148 VlanTag.Uint16 = NTOHS (*(UINT16 *)(Packet + ProtocolOffset + sizeof (ProtocolType)));
149 *VlanId = VlanTag.Bits.Vid;
150
151 //
152 // Move hardware address (DA + SA) 4 bytes right to override VLAN tag
153 //
154 CopyMem (Packet + NET_VLAN_TAG_LEN, Packet, ProtocolOffset);
155
156 //
157 // Remove VLAN tag from the Nbuf
158 //
159 NetbufTrim (Nbuf, NET_VLAN_TAG_LEN, NET_BUF_HEAD);
160
161 return TRUE;
162}
163
176VOID
178 IN MNP_SERVICE_DATA *MnpServiceData,
180 OUT UINT16 *ProtocolType,
181 IN OUT UINT8 **Packet,
182 IN OUT UINT32 *Length
183 )
184{
185 VLAN_TCI *VlanTci;
186 UINT16 *Tpid;
187 UINT16 *EtherType;
188 MNP_DEVICE_DATA *MnpDeviceData;
190
191 MnpDeviceData = MnpServiceData->MnpDeviceData;
192 SnpMode = MnpDeviceData->Snp->Mode;
193
194 *ProtocolType = ETHER_TYPE_VLAN;
195 *Length = *Length + NET_VLAN_TAG_LEN;
196 *Packet = *Packet - NET_VLAN_TAG_LEN;
197
198 Tpid = (UINT16 *)(*Packet + SnpMode->MediaHeaderSize - sizeof (*ProtocolType));
199 VlanTci = (VLAN_TCI *)(UINTN)(Tpid + 1);
200 if (TxData->HeaderLength != 0) {
201 //
202 // Media header is in packet, move DA+SA 4 bytes left
203 //
204 CopyMem (
205 *Packet,
206 *Packet + NET_VLAN_TAG_LEN,
207 SnpMode->MediaHeaderSize - sizeof (*ProtocolType)
208 );
209 *Tpid = HTONS (ETHER_TYPE_VLAN);
210 } else {
211 //
212 // Media header not in packet, VLAN TCI and original protocol type becomes payload
213 //
214 EtherType = (UINT16 *)(UINTN)(VlanTci + 1);
215 *EtherType = HTONS (TxData->ProtocolType);
216 }
217
218 VlanTci->Bits.Vid = MnpServiceData->VlanId;
219 VlanTci->Bits.Cfi = VLAN_TCI_CFI_CANONICAL_MAC;
220 VlanTci->Bits.Priority = MnpServiceData->Priority;
221 VlanTci->Uint16 = HTONS (VlanTci->Uint16);
222}
223
238 IN MNP_DEVICE_DATA *MnpDeviceData,
239 IN VLAN_TCI *Buffer,
240 IN UINTN NumberOfVlan,
241 OUT UINTN *NewNumberOfVlan
242 )
243{
244 UINTN Index;
245 UINTN Index2;
246 UINTN Count;
247 BOOLEAN FoundDuplicateItem;
248 EFI_STATUS Status;
249
250 Count = 0;
251 FoundDuplicateItem = FALSE;
252 Status = EFI_SUCCESS;
253
254 for (Index = 0; Index < NumberOfVlan; Index++) {
255 for (Index2 = Index + 1; Index2 < NumberOfVlan; Index2++) {
256 if (Buffer[Index].Bits.Vid == Buffer[Index2].Bits.Vid) {
257 FoundDuplicateItem = TRUE;
258 Count++;
259 break;
260 }
261 }
262
263 if (FoundDuplicateItem) {
264 for (Index2 = Index +1; Index2 < NumberOfVlan; Index++, Index2++) {
265 CopyMem (Buffer + Index, Buffer + Index2, sizeof (VLAN_TCI));
266 }
267 }
268
269 FoundDuplicateItem = FALSE;
270 }
271
272 *NewNumberOfVlan = NumberOfVlan - Count;
273 if (Count != 0) {
274 Status = MnpSetVlanVariable (MnpDeviceData, *NewNumberOfVlan, Buffer);
275 }
276
277 return Status;
278}
279
296 IN MNP_DEVICE_DATA *MnpDeviceData,
297 OUT UINTN *NumberOfVlan,
298 OUT VLAN_TCI **VlanVariable
299 )
300{
301 UINTN BufferSize;
302 EFI_STATUS Status;
303 VLAN_TCI *Buffer;
304 UINTN NewNumberOfVlan;
305
306 //
307 // Get VLAN configuration from EFI Variable
308 //
309 Buffer = NULL;
310 BufferSize = 0;
311 Status = gRT->GetVariable (
312 MnpDeviceData->MacString,
313 &gEfiVlanConfigProtocolGuid,
314 NULL,
315 &BufferSize,
316 NULL
317 );
318 if (Status != EFI_BUFFER_TOO_SMALL) {
319 return EFI_NOT_FOUND;
320 }
321
322 //
323 // Allocate buffer to read the variable
324 //
325 Buffer = AllocateZeroPool (BufferSize);
326 if (Buffer == NULL) {
327 return EFI_OUT_OF_RESOURCES;
328 }
329
330 Status = gRT->GetVariable (
331 MnpDeviceData->MacString,
332 &gEfiVlanConfigProtocolGuid,
333 NULL,
334 &BufferSize,
335 Buffer
336 );
337 if (EFI_ERROR (Status)) {
338 FreePool (Buffer);
339 return Status;
340 }
341
342 Status = MnpCheckVlanVariable (MnpDeviceData, Buffer, BufferSize / sizeof (VLAN_TCI), &NewNumberOfVlan);
343 if (!EFI_ERROR (Status)) {
344 *NumberOfVlan = NewNumberOfVlan;
345 *VlanVariable = Buffer;
346 }
347
348 return Status;
349}
350
364 IN MNP_DEVICE_DATA *MnpDeviceData,
365 IN UINTN NumberOfVlan,
366 IN VLAN_TCI *VlanVariable
367 )
368{
369 return gRT->SetVariable (
370 MnpDeviceData->MacString,
371 &gEfiVlanConfigProtocolGuid,
372 EFI_VARIABLE_NON_VOLATILE | EFI_VARIABLE_BOOTSERVICE_ACCESS,
373 NumberOfVlan * sizeof (VLAN_TCI),
374 VlanVariable
375 );
376}
377
410EFIAPI
413 IN UINT16 VlanId,
414 IN UINT8 Priority
415 )
416{
417 EFI_STATUS Status;
418 MNP_DEVICE_DATA *MnpDeviceData;
419 MNP_SERVICE_DATA *MnpServiceData;
420 VLAN_TCI *OldVariable;
421 VLAN_TCI *NewVariable;
422 UINTN NumberOfVlan;
423 UINTN Index;
424 BOOLEAN IsAdd;
425 LIST_ENTRY *Entry;
426
427 if ((This == NULL) || (VlanId > 4094) || (Priority > 7)) {
428 return EFI_INVALID_PARAMETER;
429 }
430
431 IsAdd = FALSE;
432 MnpDeviceData = MNP_DEVICE_DATA_FROM_THIS (This);
433 if (MnpDeviceData->NumberOfVlan == 0) {
434 //
435 // No existing VLAN, this is the first VLAN to add
436 //
437 IsAdd = TRUE;
438 Entry = GetFirstNode (&MnpDeviceData->ServiceList);
439 MnpServiceData = MNP_SERVICE_DATA_FROM_LINK (Entry);
440
441 if (VlanId != 0) {
442 //
443 // VlanId is not 0, need destroy the default MNP service data
444 //
445 Status = MnpDestroyServiceChild (MnpServiceData);
446 if (EFI_ERROR (Status)) {
447 return Status;
448 }
449
450 Status = MnpDestroyServiceData (MnpServiceData);
451 if (EFI_ERROR (Status)) {
452 return Status;
453 }
454
455 //
456 // Create a new MNP service data for this VLAN
457 //
458 MnpServiceData = MnpCreateServiceData (MnpDeviceData, VlanId, Priority);
459 if (MnpServiceData == NULL) {
460 return EFI_OUT_OF_RESOURCES;
461 }
462 }
463 } else {
464 //
465 // Try to find VlanId in existing VLAN list
466 //
467 MnpServiceData = MnpFindServiceData (MnpDeviceData, VlanId);
468 if (MnpServiceData == NULL) {
469 //
470 // VlanId not found, create a new MNP service data
471 //
472 IsAdd = TRUE;
473 MnpServiceData = MnpCreateServiceData (MnpDeviceData, VlanId, Priority);
474 if (MnpServiceData == NULL) {
475 return EFI_OUT_OF_RESOURCES;
476 }
477 }
478 }
479
480 MnpServiceData->VlanId = VlanId;
481 MnpServiceData->Priority = Priority;
482 if (IsAdd) {
483 MnpDeviceData->NumberOfVlan++;
484 }
485
486 //
487 // Update VLAN configuration variable
488 //
489 OldVariable = NULL;
490 NewVariable = NULL;
491 NumberOfVlan = 0;
492 MnpGetVlanVariable (MnpDeviceData, &NumberOfVlan, &OldVariable);
493
494 if (IsAdd) {
495 //
496 // VLAN not exist - add
497 //
498 NewVariable = AllocateZeroPool ((NumberOfVlan + 1) * sizeof (VLAN_TCI));
499 if (NewVariable == NULL) {
500 Status = EFI_OUT_OF_RESOURCES;
501 goto Exit;
502 }
503
504 if (OldVariable != NULL) {
505 CopyMem (NewVariable, OldVariable, NumberOfVlan * sizeof (VLAN_TCI));
506 }
507
508 Index = NumberOfVlan++;
509 } else {
510 //
511 // VLAN already exist - update
512 //
513 for (Index = 0; Index < NumberOfVlan; Index++) {
514 if (OldVariable[Index].Bits.Vid == VlanId) {
515 break;
516 }
517 }
518
519 ASSERT (Index < NumberOfVlan);
520
521 NewVariable = OldVariable;
522 OldVariable = NULL;
523 }
524
525 NewVariable[Index].Bits.Vid = VlanId;
526 NewVariable[Index].Bits.Priority = Priority;
527
528 Status = MnpSetVlanVariable (MnpDeviceData, NumberOfVlan, NewVariable);
529 FreePool (NewVariable);
530
531Exit:
532 if (OldVariable != NULL) {
533 FreePool (OldVariable);
534 }
535
536 return Status;
537}
538
559EFIAPI
562 IN UINT16 *VlanId OPTIONAL,
563 OUT UINT16 *NumberOfVlan,
564 OUT EFI_VLAN_FIND_DATA **Entries
565 )
566{
567 MNP_DEVICE_DATA *MnpDeviceData;
568 MNP_SERVICE_DATA *MnpServiceData;
569 LIST_ENTRY *Entry;
570 EFI_VLAN_FIND_DATA *VlanData;
571
572 if ((This == NULL) || ((VlanId != NULL) && (*VlanId > 4094)) || (NumberOfVlan == NULL) || (Entries == NULL)) {
573 return EFI_INVALID_PARAMETER;
574 }
575
576 *NumberOfVlan = 0;
577 *Entries = NULL;
578
579 MnpDeviceData = MNP_DEVICE_DATA_FROM_THIS (This);
580 if (MnpDeviceData->NumberOfVlan == 0) {
581 return EFI_NOT_FOUND;
582 }
583
584 if (VlanId == NULL) {
585 //
586 // Return all current VLAN configuration
587 //
588 *NumberOfVlan = (UINT16)MnpDeviceData->NumberOfVlan;
589 VlanData = AllocateZeroPool (*NumberOfVlan * sizeof (EFI_VLAN_FIND_DATA));
590 if (VlanData == NULL) {
591 return EFI_OUT_OF_RESOURCES;
592 }
593
594 *Entries = VlanData;
595 NET_LIST_FOR_EACH (Entry, &MnpDeviceData->ServiceList) {
596 MnpServiceData = MNP_SERVICE_DATA_FROM_LINK (Entry);
597
598 VlanData->VlanId = MnpServiceData->VlanId;
599 VlanData->Priority = MnpServiceData->Priority;
600 VlanData++;
601 }
602
603 return EFI_SUCCESS;
604 }
605
606 //
607 // VlanId is specified, try to find it in current VLAN list
608 //
609 MnpServiceData = MnpFindServiceData (MnpDeviceData, *VlanId);
610 if (MnpServiceData == NULL) {
611 return EFI_NOT_FOUND;
612 }
613
614 VlanData = AllocateZeroPool (sizeof (EFI_VLAN_FIND_DATA));
615 if (VlanData == NULL) {
616 return EFI_OUT_OF_RESOURCES;
617 }
618
619 VlanData->VlanId = MnpServiceData->VlanId;
620 VlanData->Priority = MnpServiceData->Priority;
621
622 *NumberOfVlan = 1;
623 *Entries = VlanData;
624
625 return EFI_SUCCESS;
626}
627
646EFIAPI
649 IN UINT16 VlanId
650 )
651{
652 EFI_STATUS Status;
653 MNP_DEVICE_DATA *MnpDeviceData;
654 MNP_SERVICE_DATA *MnpServiceData;
655 LIST_ENTRY *Entry;
656 VLAN_TCI *VlanVariable;
657 VLAN_TCI *VlanData;
658
659 if ((This == NULL) || (VlanId > 4094)) {
660 return EFI_INVALID_PARAMETER;
661 }
662
663 MnpDeviceData = MNP_DEVICE_DATA_FROM_THIS (This);
664 if (MnpDeviceData->NumberOfVlan == 0) {
665 return EFI_NOT_FOUND;
666 }
667
668 //
669 // Try to find the VlanId
670 //
671 MnpServiceData = MnpFindServiceData (MnpDeviceData, VlanId);
672 if (MnpServiceData == NULL) {
673 return EFI_NOT_FOUND;
674 }
675
676 MnpDeviceData->NumberOfVlan--;
677
678 if ((VlanId != 0) || (MnpDeviceData->NumberOfVlan != 0)) {
679 //
680 // If VlanId is not 0 or VlanId is 0 and it is not the last VLAN to remove,
681 // destroy its MNP service data
682 //
683 Status = MnpDestroyServiceChild (MnpServiceData);
684 if (EFI_ERROR (Status)) {
685 return Status;
686 }
687
688 Status = MnpDestroyServiceData (MnpServiceData);
689 if (EFI_ERROR (Status)) {
690 return Status;
691 }
692 }
693
694 if ((VlanId != 0) && (MnpDeviceData->NumberOfVlan == 0)) {
695 //
696 // This is the last VLAN to be removed, restore the default MNP service data
697 //
698 MnpServiceData = MnpCreateServiceData (MnpDeviceData, 0, 0);
699 if (MnpServiceData == NULL) {
700 return EFI_OUT_OF_RESOURCES;
701 }
702 }
703
704 //
705 // Update VLAN configuration variable
706 //
707 VlanVariable = NULL;
708 if (MnpDeviceData->NumberOfVlan != 0) {
709 VlanVariable = AllocatePool (MnpDeviceData->NumberOfVlan * sizeof (VLAN_TCI));
710 if (VlanVariable == NULL) {
711 return EFI_OUT_OF_RESOURCES;
712 }
713
714 VlanData = VlanVariable;
715 NET_LIST_FOR_EACH (Entry, &MnpDeviceData->ServiceList) {
716 MnpServiceData = MNP_SERVICE_DATA_FROM_LINK (Entry);
717
718 VlanData->Bits.Vid = MnpServiceData->VlanId;
719 VlanData->Bits.Priority = MnpServiceData->Priority;
720 VlanData++;
721 }
722 }
723
724 Status = MnpSetVlanVariable (MnpDeviceData, MnpDeviceData->NumberOfVlan, VlanVariable);
725
726 if (VlanVariable != NULL) {
727 FreePool (VlanVariable);
728 }
729
730 return Status;
731}
UINT64 UINTN
LIST_ENTRY *EFIAPI GetFirstNode(IN CONST LIST_ENTRY *List)
Definition: LinkedList.c:298
VOID *EFIAPI CopyMem(OUT VOID *DestinationBuffer, IN CONST VOID *SourceBuffer, IN UINTN Length)
#define MSG_VLAN_DP
Definition: DevicePath.h:964
#define MESSAGING_DEVICE_PATH
Definition: DevicePath.h:321
EFI_DEVICE_PATH_PROTOCOL *EFIAPI AppendDevicePathNode(IN CONST EFI_DEVICE_PATH_PROTOCOL *DevicePath OPTIONAL, IN CONST EFI_DEVICE_PATH_PROTOCOL *DevicePathNode OPTIONAL)
VOID *EFIAPI AllocateZeroPool(IN UINTN AllocationSize)
VOID EFIAPI FreePool(IN VOID *Buffer)
EFI_RUNTIME_SERVICES * gRT
#define NULL
Definition: Base.h:319
#define TRUE
Definition: Base.h:301
#define FALSE
Definition: Base.h:307
#define IN
Definition: Base.h:279
#define OUT
Definition: Base.h:284
MNP_SERVICE_DATA * MnpFindServiceData(IN MNP_DEVICE_DATA *MnpDeviceData, IN UINT16 VlanId)
Definition: MnpConfig.c:936
EFI_STATUS MnpDestroyServiceChild(IN OUT MNP_SERVICE_DATA *MnpServiceData)
Definition: MnpConfig.c:903
EFI_STATUS MnpDestroyServiceData(IN OUT MNP_SERVICE_DATA *MnpServiceData)
Definition: MnpConfig.c:807
MNP_SERVICE_DATA * MnpCreateServiceData(IN MNP_DEVICE_DATA *MnpDeviceData, IN UINT16 VlanId, IN UINT8 Priority OPTIONAL)
Definition: MnpConfig.c:690
EFI_STATUS MnpCheckVlanVariable(IN MNP_DEVICE_DATA *MnpDeviceData, IN VLAN_TCI *Buffer, IN UINTN NumberOfVlan, OUT UINTN *NewNumberOfVlan)
Definition: MnpVlan.c:237
BOOLEAN MnpRemoveVlanTag(IN OUT MNP_DEVICE_DATA *MnpDeviceData, IN OUT NET_BUF *Nbuf, OUT UINT16 *VlanId)
Definition: MnpVlan.c:117
EFI_STATUS EFIAPI VlanConfigSet(IN EFI_VLAN_CONFIG_PROTOCOL *This, IN UINT16 VlanId, IN UINT8 Priority)
Definition: MnpVlan.c:411
EFI_STATUS EFIAPI VlanConfigFind(IN EFI_VLAN_CONFIG_PROTOCOL *This, IN UINT16 *VlanId OPTIONAL, OUT UINT16 *NumberOfVlan, OUT EFI_VLAN_FIND_DATA **Entries)
Definition: MnpVlan.c:560
EFI_HANDLE MnpCreateVlanChild(IN EFI_HANDLE ImageHandle, IN EFI_HANDLE ControllerHandle, IN UINT16 VlanId, OUT EFI_DEVICE_PATH_PROTOCOL **Devicepath OPTIONAL)
Definition: MnpVlan.c:42
EFI_STATUS EFIAPI VlanConfigRemove(IN EFI_VLAN_CONFIG_PROTOCOL *This, IN UINT16 VlanId)
Definition: MnpVlan.c:647
EFI_STATUS MnpGetVlanVariable(IN MNP_DEVICE_DATA *MnpDeviceData, OUT UINTN *NumberOfVlan, OUT VLAN_TCI **VlanVariable)
Definition: MnpVlan.c:295
EFI_STATUS MnpSetVlanVariable(IN MNP_DEVICE_DATA *MnpDeviceData, IN UINTN NumberOfVlan, IN VLAN_TCI *VlanVariable)
Definition: MnpVlan.c:363
VOID MnpInsertVlanTag(IN MNP_SERVICE_DATA *MnpServiceData, IN EFI_MANAGED_NETWORK_TRANSMIT_DATA *TxData, OUT UINT16 *ProtocolType, IN OUT UINT8 **Packet, IN OUT UINT32 *Length)
Definition: MnpVlan.c:177
UINT32 EFIAPI NetbufTrim(IN OUT NET_BUF *Nbuf, IN UINT32 Len, IN BOOLEAN FromHead)
Definition: NetBuffer.c:1134
UINT8 *EFIAPI NetbufGetByte(IN NET_BUF *Nbuf, IN UINT32 Offset, OUT UINT32 *Index OPTIONAL)
Definition: NetBuffer.c:359
VOID *EFIAPI AllocatePool(IN UINTN AllocationSize)
VOID EFIAPI Exit(IN EFI_STATUS Status)
RETURN_STATUS EFI_STATUS
Definition: UefiBaseType.h:29
VOID * EFI_HANDLE
Definition: UefiBaseType.h:33
#define EFI_SUCCESS
Definition: UefiBaseType.h:112
EFI_BOOT_SERVICES * gBS
#define EFI_VARIABLE_NON_VOLATILE
EFI_SIMPLE_NETWORK_MODE * Mode
UINT8 Priority
Priority of this VLAN.
Definition: VlanConfig.h:27
UINT16 VlanId
Vlan Identifier.
Definition: VlanConfig.h:26