779ae357 |
1 | /** @file\r |
2 | VLAN Config Protocol implementation and VLAN packet process routine.\r |
3 | \r |
bdebd2ce |
4 | Copyright (c) 2009 - 2013, Intel Corporation. All rights reserved.<BR>\r |
e5eed7d3 |
5 | This program and the accompanying materials\r |
779ae357 |
6 | are licensed and made available under the terms and conditions\r |
7 | of the BSD License which accompanies this distribution. The full\r |
8 | text of the license may be found at<BR>\r |
9 | http://opensource.org/licenses/bsd-license.php\r |
10 | \r |
11 | THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r |
12 | WITHOUT 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 |
19 | VLAN_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 |
31 | EFI_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 |
49 | EFI_HANDLE\r |
50 | MnpCreateVlanChild (\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 |
124 | BOOLEAN\r |
125 | MnpRemoveVlanTag (\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 |
185 | VOID\r |
186 | MnpInsertVlanTag (\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 |
248 | EFI_STATUS\r |
249 | MnpGetVlanVariable (\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 |
313 | EFI_STATUS\r |
314 | MnpSetVlanVariable (\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 |
323 | EFI_VARIABLE_NON_VOLATILE | EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_RUNTIME_ACCESS,\r |
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 |
361 | EFI_STATUS\r |
362 | EFIAPI\r |
363 | VlanConfigSet (\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 |
482 | Exit:\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 |
510 | EFI_STATUS\r |
511 | EFIAPI\r |
512 | VlanConfigFind (\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 |
597 | EFI_STATUS\r |
598 | EFIAPI\r |
599 | VlanConfigRemove (\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 |