]> git.proxmox.com Git - mirror_edk2.git/blob - MdeModulePkg/Universal/Network/SnpDxe/Receive_filters.c
3886d2078d45f268caa0f3f8ff7662de9677e973
[mirror_edk2.git] / MdeModulePkg / Universal / Network / SnpDxe / Receive_filters.c
1 /** @file
2 Copyright (c) 2004 - 2007, Intel Corporation
3 All rights reserved. This program and the accompanying materials
4 are licensed and made available under the terms and conditions of the BSD License
5 which accompanies this distribution. The full text of the license may be found at
6 http://opensource.org/licenses/bsd-license.php
7
8 THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
9 WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
10
11 Module name:
12 receive_filters.c
13
14 Abstract:
15
16 Revision history:
17 2000-Feb-17 M(f)J Genesis.
18
19 **/
20
21
22
23 #include "Snp.h"
24
25 /**
26 this routine calls undi to enable the receive filters.
27
28 @param snp pointer to snp driver structure
29 @param EnableFlags bit mask for enabling the receive filters
30 @param MCastAddressCount multicast address count for a new multicast address
31 list
32 @param MCastAddressList list of new multicast addresses
33
34
35 **/
36 STATIC
37 EFI_STATUS
38 pxe_rcvfilter_enable (
39 SNP_DRIVER *snp,
40 UINT32 EnableFlags,
41 UINTN MCastAddressCount,
42 EFI_MAC_ADDRESS *MCastAddressList
43 )
44 {
45 snp->cdb.OpCode = PXE_OPCODE_RECEIVE_FILTERS;
46 snp->cdb.OpFlags = PXE_OPFLAGS_RECEIVE_FILTER_ENABLE;
47 snp->cdb.CPBsize = PXE_CPBSIZE_NOT_USED;
48 snp->cdb.DBsize = PXE_DBSIZE_NOT_USED;
49 snp->cdb.CPBaddr = PXE_CPBADDR_NOT_USED;
50 snp->cdb.DBaddr = PXE_DBADDR_NOT_USED;
51 snp->cdb.StatCode = PXE_STATCODE_INITIALIZE;
52 snp->cdb.StatFlags = PXE_STATFLAGS_INITIALIZE;
53 snp->cdb.IFnum = snp->if_num;
54 snp->cdb.Control = PXE_CONTROL_LAST_CDB_IN_LIST;
55
56 if ((EnableFlags & EFI_SIMPLE_NETWORK_RECEIVE_UNICAST) != 0) {
57 snp->cdb.OpFlags |= PXE_OPFLAGS_RECEIVE_FILTER_UNICAST;
58 }
59
60 if ((EnableFlags & EFI_SIMPLE_NETWORK_RECEIVE_BROADCAST) != 0) {
61 snp->cdb.OpFlags |= PXE_OPFLAGS_RECEIVE_FILTER_BROADCAST;
62 }
63
64 if ((EnableFlags & EFI_SIMPLE_NETWORK_RECEIVE_PROMISCUOUS) != 0) {
65 snp->cdb.OpFlags |= PXE_OPFLAGS_RECEIVE_FILTER_PROMISCUOUS;
66 }
67
68 if ((EnableFlags & EFI_SIMPLE_NETWORK_RECEIVE_PROMISCUOUS_MULTICAST) != 0) {
69 snp->cdb.OpFlags |= PXE_OPFLAGS_RECEIVE_FILTER_ALL_MULTICAST;
70 }
71
72 if ((EnableFlags & EFI_SIMPLE_NETWORK_RECEIVE_MULTICAST) != 0) {
73 snp->cdb.OpFlags |= PXE_OPFLAGS_RECEIVE_FILTER_FILTERED_MULTICAST;
74 }
75
76 if (MCastAddressCount != 0) {
77 snp->cdb.CPBsize = (UINT16) (MCastAddressCount * sizeof (EFI_MAC_ADDRESS));
78 snp->cdb.CPBaddr = (UINT64)(UINTN) snp->cpb;
79 CopyMem (snp->cpb, MCastAddressList, snp->cdb.CPBsize);
80 }
81 //
82 // Issue UNDI command and check result.
83 //
84 DEBUG ((EFI_D_NET, "\nsnp->undi.receive_filters() "));
85
86 (*snp->issue_undi32_command) ((UINT64)(UINTN) &snp->cdb);
87
88 if (snp->cdb.StatCode != EFI_SUCCESS) {
89 //
90 // UNDI command failed. Return UNDI status to caller.
91 //
92 DEBUG (
93 (EFI_D_ERROR,
94 "\nsnp->undi.receive_filters() %xh:%xh\n",
95 snp->cdb.StatFlags,
96 snp->cdb.StatCode)
97 );
98
99 switch (snp->cdb.StatCode) {
100 case PXE_STATCODE_INVALID_CDB:
101 case PXE_STATCODE_INVALID_CPB:
102 case PXE_STATCODE_INVALID_PARAMETER:
103 return EFI_INVALID_PARAMETER;
104
105 case PXE_STATCODE_UNSUPPORTED:
106 return EFI_UNSUPPORTED;
107 }
108
109 return EFI_DEVICE_ERROR;
110 }
111
112 return EFI_SUCCESS;
113 }
114
115 /**
116 this routine calls undi to disable the receive filters.
117
118 @param snp pointer to snp driver structure
119 @param DisableFlags bit mask for disabling the receive filters
120 @param ResetMCastList boolean flag to reset/delete the multicast filter list
121
122
123 **/
124 STATIC
125 EFI_STATUS
126 pxe_rcvfilter_disable (
127 SNP_DRIVER *snp,
128 UINT32 DisableFlags,
129 BOOLEAN ResetMCastList
130 )
131 {
132 snp->cdb.OpCode = PXE_OPCODE_RECEIVE_FILTERS;
133 snp->cdb.CPBsize = PXE_CPBSIZE_NOT_USED;
134 snp->cdb.DBsize = PXE_DBSIZE_NOT_USED;
135 snp->cdb.CPBaddr = PXE_CPBADDR_NOT_USED;
136 snp->cdb.DBaddr = PXE_DBADDR_NOT_USED;
137 snp->cdb.StatCode = PXE_STATCODE_INITIALIZE;
138 snp->cdb.StatFlags = PXE_STATFLAGS_INITIALIZE;
139 snp->cdb.IFnum = snp->if_num;
140 snp->cdb.Control = PXE_CONTROL_LAST_CDB_IN_LIST;
141
142 snp->cdb.OpFlags = (UINT16) (DisableFlags ? PXE_OPFLAGS_RECEIVE_FILTER_DISABLE : PXE_OPFLAGS_NOT_USED);
143
144 if (ResetMCastList) {
145 snp->cdb.OpFlags |= PXE_OPFLAGS_RECEIVE_FILTER_RESET_MCAST_LIST;
146 }
147
148 if ((DisableFlags & EFI_SIMPLE_NETWORK_RECEIVE_UNICAST) != 0) {
149 snp->cdb.OpFlags |= PXE_OPFLAGS_RECEIVE_FILTER_UNICAST;
150 }
151
152 if ((DisableFlags & EFI_SIMPLE_NETWORK_RECEIVE_BROADCAST) != 0) {
153 snp->cdb.OpFlags |= PXE_OPFLAGS_RECEIVE_FILTER_BROADCAST;
154 }
155
156 if ((DisableFlags & EFI_SIMPLE_NETWORK_RECEIVE_PROMISCUOUS) != 0) {
157 snp->cdb.OpFlags |= PXE_OPFLAGS_RECEIVE_FILTER_PROMISCUOUS;
158 }
159
160 if ((DisableFlags & EFI_SIMPLE_NETWORK_RECEIVE_PROMISCUOUS_MULTICAST) != 0) {
161 snp->cdb.OpFlags |= PXE_OPFLAGS_RECEIVE_FILTER_ALL_MULTICAST;
162 }
163
164 if ((DisableFlags & EFI_SIMPLE_NETWORK_RECEIVE_MULTICAST) != 0) {
165 snp->cdb.OpFlags |= PXE_OPFLAGS_RECEIVE_FILTER_FILTERED_MULTICAST;
166 }
167 //
168 // Issue UNDI command and check result.
169 //
170 DEBUG ((EFI_D_NET, "\nsnp->undi.receive_filters() "));
171
172 (*snp->issue_undi32_command) ((UINT64)(UINTN) &snp->cdb);
173
174 if (snp->cdb.StatCode != EFI_SUCCESS) {
175 //
176 // UNDI command failed. Return UNDI status to caller.
177 //
178 DEBUG (
179 (EFI_D_ERROR,
180 "\nsnp->undi.receive_filters() %xh:%xh\n",
181 snp->cdb.StatFlags,
182 snp->cdb.StatCode)
183 );
184
185 return EFI_DEVICE_ERROR;
186 }
187
188 return EFI_SUCCESS;
189 }
190
191 /**
192 this routine calls undi to read the receive filters.
193
194 @param snp pointer to snp driver structure
195
196
197 **/
198 STATIC
199 EFI_STATUS
200 pxe_rcvfilter_read (
201 SNP_DRIVER *snp
202 )
203 {
204 snp->cdb.OpCode = PXE_OPCODE_RECEIVE_FILTERS;
205 snp->cdb.OpFlags = PXE_OPFLAGS_RECEIVE_FILTER_READ;
206 snp->cdb.CPBsize = PXE_CPBSIZE_NOT_USED;
207 snp->cdb.DBsize = (UINT16) (snp->mode.MaxMCastFilterCount * sizeof (EFI_MAC_ADDRESS));
208 snp->cdb.CPBaddr = PXE_CPBADDR_NOT_USED;
209 if (snp->cdb.DBsize == 0) {
210 snp->cdb.DBaddr = (UINT64)(UINTN) NULL;
211 } else {
212 snp->cdb.DBaddr = (UINT64)(UINTN) snp->db;
213 ZeroMem (snp->db, snp->cdb.DBsize);
214 }
215
216 snp->cdb.StatCode = PXE_STATCODE_INITIALIZE;
217 snp->cdb.StatFlags = PXE_STATFLAGS_INITIALIZE;
218 snp->cdb.IFnum = snp->if_num;
219 snp->cdb.Control = PXE_CONTROL_LAST_CDB_IN_LIST;
220
221 DEBUG ((EFI_D_NET, "\nsnp->undi.receive_filters() "));
222
223 (*snp->issue_undi32_command) ((UINT64)(UINTN) &snp->cdb);
224
225 if (snp->cdb.StatCode != EFI_SUCCESS) {
226 //
227 // UNDI command failed. Return UNDI status to caller.
228 //
229 DEBUG (
230 (EFI_D_ERROR,
231 "\nsnp->undi.receive_filters() %xh:%xh\n",
232 snp->cdb.StatFlags,
233 snp->cdb.StatCode)
234 );
235
236 return EFI_DEVICE_ERROR;
237 }
238 //
239 // Convert UNDI32 StatFlags to EFI SNP filter flags.
240 //
241 snp->mode.ReceiveFilterSetting = 0;
242
243 if ((snp->cdb.StatFlags & PXE_STATFLAGS_RECEIVE_FILTER_UNICAST) != 0) {
244 snp->mode.ReceiveFilterSetting |= EFI_SIMPLE_NETWORK_RECEIVE_UNICAST;
245 }
246
247 if ((snp->cdb.StatFlags & PXE_STATFLAGS_RECEIVE_FILTER_BROADCAST) != 0) {
248 snp->mode.ReceiveFilterSetting |= EFI_SIMPLE_NETWORK_RECEIVE_BROADCAST;
249 }
250
251 if ((snp->cdb.StatFlags & PXE_STATFLAGS_RECEIVE_FILTER_PROMISCUOUS) != 0) {
252 snp->mode.ReceiveFilterSetting |= EFI_SIMPLE_NETWORK_RECEIVE_PROMISCUOUS;
253 }
254
255 if ((snp->cdb.StatFlags & PXE_STATFLAGS_RECEIVE_FILTER_ALL_MULTICAST) != 0) {
256 snp->mode.ReceiveFilterSetting |= EFI_SIMPLE_NETWORK_RECEIVE_PROMISCUOUS_MULTICAST;
257 }
258
259 if ((snp->cdb.StatFlags & PXE_STATFLAGS_RECEIVE_FILTER_FILTERED_MULTICAST) != 0) {
260 snp->mode.ReceiveFilterSetting |= EFI_SIMPLE_NETWORK_RECEIVE_MULTICAST;
261 }
262
263 CopyMem (snp->mode.MCastFilter, snp->db, snp->cdb.DBsize);
264
265 //
266 // Count number of active entries in multicast filter list.
267 //
268 {
269 EFI_MAC_ADDRESS ZeroMacAddr;
270
271 SetMem (&ZeroMacAddr, sizeof ZeroMacAddr, 0);
272
273 for (snp->mode.MCastFilterCount = 0;
274 snp->mode.MCastFilterCount < snp->mode.MaxMCastFilterCount;
275 snp->mode.MCastFilterCount++
276 ) {
277 if (CompareMem (
278 &snp->mode.MCastFilter[snp->mode.MCastFilterCount],
279 &ZeroMacAddr,
280 sizeof ZeroMacAddr
281 ) == 0) {
282 break;
283 }
284 }
285 }
286
287 return EFI_SUCCESS;
288 }
289
290
291 /**
292 This is the SNP interface routine for reading/enabling/disabling the
293 receive filters.
294 This routine basically retrieves snp structure, checks the SNP state and
295 checks the parameter validity, calls one of the above routines to actually
296 do the work
297
298 @param this context pointer
299 @param EnableFlags bit mask for enabling the receive filters
300 @param DisableFlags bit mask for disabling the receive filters
301 @param ResetMCastList boolean flag to reset/delete the multicast filter list
302 @param MCastAddressCount multicast address count for a new multicast address
303 list
304 @param MCastAddressList list of new multicast addresses
305
306
307 **/
308 EFI_STATUS
309 EFIAPI
310 snp_undi32_receive_filters (
311 IN EFI_SIMPLE_NETWORK_PROTOCOL * this,
312 IN UINT32 EnableFlags,
313 IN UINT32 DisableFlags,
314 IN BOOLEAN ResetMCastList,
315 IN UINTN MCastAddressCount OPTIONAL,
316 IN EFI_MAC_ADDRESS * MCastAddressList OPTIONAL
317 )
318 {
319 SNP_DRIVER *snp;
320 EFI_STATUS Status;
321 EFI_TPL OldTpl;
322
323 if (this == NULL) {
324 return EFI_INVALID_PARAMETER;
325 }
326
327 snp = EFI_SIMPLE_NETWORK_DEV_FROM_THIS (this);
328
329 OldTpl = gBS->RaiseTPL (TPL_CALLBACK);
330
331 switch (snp->mode.State) {
332 case EfiSimpleNetworkInitialized:
333 break;
334
335 case EfiSimpleNetworkStopped:
336 Status = EFI_NOT_STARTED;
337 goto ON_EXIT;
338
339 default:
340 Status = EFI_DEVICE_ERROR;
341 goto ON_EXIT;
342 }
343 //
344 // check if we are asked to enable or disable something that the UNDI
345 // does not even support!
346 //
347 if (((EnableFlags &~snp->mode.ReceiveFilterMask) != 0) ||
348 ((DisableFlags &~snp->mode.ReceiveFilterMask) != 0)) {
349 Status = EFI_INVALID_PARAMETER;
350 goto ON_EXIT;
351 }
352
353 if (ResetMCastList) {
354
355 DisableFlags |= EFI_SIMPLE_NETWORK_RECEIVE_MULTICAST & snp->mode.ReceiveFilterMask;
356 MCastAddressCount = 0;
357 MCastAddressList = NULL;
358 } else {
359 if (MCastAddressCount != 0) {
360 if ((MCastAddressCount > snp->mode.MaxMCastFilterCount) ||
361 (MCastAddressList == NULL)) {
362
363 Status = EFI_INVALID_PARAMETER;
364 goto ON_EXIT;
365 }
366 }
367 }
368
369 if (EnableFlags == 0 && DisableFlags == 0 && !ResetMCastList && MCastAddressCount == 0) {
370 Status = EFI_SUCCESS;
371 goto ON_EXIT;
372 }
373
374 if ((EnableFlags & EFI_SIMPLE_NETWORK_RECEIVE_MULTICAST) != 0 && MCastAddressCount == 0) {
375 Status = EFI_INVALID_PARAMETER;
376 goto ON_EXIT;
377 }
378
379 if ((EnableFlags != 0) || (MCastAddressCount != 0)) {
380 Status = pxe_rcvfilter_enable (
381 snp,
382 EnableFlags,
383 MCastAddressCount,
384 MCastAddressList
385 );
386
387 if (EFI_ERROR (Status)) {
388 goto ON_EXIT;
389 }
390 }
391
392 if ((DisableFlags != 0) || ResetMCastList) {
393 Status = pxe_rcvfilter_disable (snp, DisableFlags, ResetMCastList);
394
395 if (EFI_ERROR (Status)) {
396 goto ON_EXIT;
397 }
398 }
399
400 Status = pxe_rcvfilter_read (snp);
401
402 ON_EXIT:
403 gBS->RestoreTPL (OldTpl);
404
405 return Status;
406 }