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