sync comments, fix function header, rename variable name to follow coding style.
[mirror_edk2.git] / MdeModulePkg / Universal / Network / SnpDxe / Receive_filters.c
1 /** @file\r
2 Copyright (c) 2004 - 2007, Intel Corporation\r
3 All rights reserved. This program and the accompanying materials\r
4 are licensed and made available under the terms and conditions of the BSD License\r
5 which accompanies this distribution.  The full text of the license may be found at\r
6 http://opensource.org/licenses/bsd-license.php\r
7 \r
8 THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
9 WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
10 \r
11 Module name:\r
12   receive_filters.c\r
13 \r
14 Abstract:\r
15 \r
16 Revision 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
36 EFI_STATUS\r
37 PxeRecvFilterEnable (\r
38   SNP_DRIVER      *Snp,\r
39   UINT32          EnableFlags,\r
40   UINTN           MCastAddressCount,\r
41   EFI_MAC_ADDRESS *MCastAddressList\r
42   )\r
43 {\r
44   Snp->Cdb.OpCode     = PXE_OPCODE_RECEIVE_FILTERS;\r
45   Snp->Cdb.OpFlags    = PXE_OPFLAGS_RECEIVE_FILTER_ENABLE;\r
46   Snp->Cdb.CPBsize    = PXE_CPBSIZE_NOT_USED;\r
47   Snp->Cdb.DBsize     = PXE_DBSIZE_NOT_USED;\r
48   Snp->Cdb.CPBaddr    = PXE_CPBADDR_NOT_USED;\r
49   Snp->Cdb.DBaddr     = PXE_DBADDR_NOT_USED;\r
50   Snp->Cdb.StatCode   = PXE_STATCODE_INITIALIZE;\r
51   Snp->Cdb.StatFlags  = PXE_STATFLAGS_INITIALIZE;\r
52   Snp->Cdb.IFnum      = Snp->IfNum;\r
53   Snp->Cdb.Control    = PXE_CONTROL_LAST_CDB_IN_LIST;\r
54 \r
55   if ((EnableFlags & EFI_SIMPLE_NETWORK_RECEIVE_UNICAST) != 0) {\r
56     Snp->Cdb.OpFlags |= PXE_OPFLAGS_RECEIVE_FILTER_UNICAST;\r
57   }\r
58 \r
59   if ((EnableFlags & EFI_SIMPLE_NETWORK_RECEIVE_BROADCAST) != 0) {\r
60     Snp->Cdb.OpFlags |= PXE_OPFLAGS_RECEIVE_FILTER_BROADCAST;\r
61   }\r
62 \r
63   if ((EnableFlags & EFI_SIMPLE_NETWORK_RECEIVE_PROMISCUOUS) != 0) {\r
64     Snp->Cdb.OpFlags |= PXE_OPFLAGS_RECEIVE_FILTER_PROMISCUOUS;\r
65   }\r
66 \r
67   if ((EnableFlags & EFI_SIMPLE_NETWORK_RECEIVE_PROMISCUOUS_MULTICAST) != 0) {\r
68     Snp->Cdb.OpFlags |= PXE_OPFLAGS_RECEIVE_FILTER_ALL_MULTICAST;\r
69   }\r
70 \r
71   if ((EnableFlags & EFI_SIMPLE_NETWORK_RECEIVE_MULTICAST) != 0) {\r
72     Snp->Cdb.OpFlags |= PXE_OPFLAGS_RECEIVE_FILTER_FILTERED_MULTICAST;\r
73   }\r
74 \r
75   if (MCastAddressCount != 0) {\r
76     Snp->Cdb.CPBsize  = (UINT16) (MCastAddressCount * sizeof (EFI_MAC_ADDRESS));\r
77     Snp->Cdb.CPBaddr  = (UINT64)(UINTN)Snp->Cpb;\r
78     CopyMem (Snp->Cpb, MCastAddressList, Snp->Cdb.CPBsize);\r
79   }\r
80   //\r
81   // Issue UNDI command and check result.\r
82   //\r
83   DEBUG ((EFI_D_NET, "\nsnp->undi.receive_filters()  "));\r
84 \r
85   (*Snp->IssueUndi32Command) ((UINT64)(UINTN) &Snp->Cdb);\r
86 \r
87   if (Snp->Cdb.StatCode != EFI_SUCCESS) {\r
88     //\r
89     // UNDI command failed.  Return UNDI status to caller.\r
90     //\r
91     DEBUG (\r
92       (EFI_D_ERROR,\r
93       "\nsnp->undi.receive_filters()  %xh:%xh\n",\r
94       Snp->Cdb.StatFlags,\r
95       Snp->Cdb.StatCode)\r
96       );\r
97 \r
98     switch (Snp->Cdb.StatCode) {\r
99     case PXE_STATCODE_INVALID_CDB:\r
100     case PXE_STATCODE_INVALID_CPB:\r
101     case PXE_STATCODE_INVALID_PARAMETER:\r
102       return EFI_INVALID_PARAMETER;\r
103 \r
104     case PXE_STATCODE_UNSUPPORTED:\r
105       return EFI_UNSUPPORTED;\r
106     }\r
107 \r
108     return EFI_DEVICE_ERROR;\r
109   }\r
110 \r
111   return EFI_SUCCESS;\r
112 }\r
113 \r
114 /**\r
115   this routine calls undi to disable the receive filters.\r
116 \r
117   @param  Snp                pointer to snp driver structure\r
118   @param  DisableFlags       bit mask for disabling the receive filters\r
119   @param  ResetMCastList     boolean flag to reset/delete the multicast filter list\r
120 \r
121 \r
122 **/\r
123 EFI_STATUS\r
124 PxeRecvFilterDisable (\r
125   SNP_DRIVER *Snp,\r
126   UINT32     DisableFlags,\r
127   BOOLEAN    ResetMCastList\r
128   )\r
129 {\r
130   Snp->Cdb.OpCode     = PXE_OPCODE_RECEIVE_FILTERS;\r
131   Snp->Cdb.CPBsize    = PXE_CPBSIZE_NOT_USED;\r
132   Snp->Cdb.DBsize     = PXE_DBSIZE_NOT_USED;\r
133   Snp->Cdb.CPBaddr    = PXE_CPBADDR_NOT_USED;\r
134   Snp->Cdb.DBaddr     = PXE_DBADDR_NOT_USED;\r
135   Snp->Cdb.StatCode   = PXE_STATCODE_INITIALIZE;\r
136   Snp->Cdb.StatFlags  = PXE_STATFLAGS_INITIALIZE;\r
137   Snp->Cdb.IFnum      = Snp->IfNum;\r
138   Snp->Cdb.Control    = PXE_CONTROL_LAST_CDB_IN_LIST;\r
139 \r
140   Snp->Cdb.OpFlags    = (UINT16) ((DisableFlags != 0) ? PXE_OPFLAGS_RECEIVE_FILTER_DISABLE : PXE_OPFLAGS_NOT_USED);\r
141 \r
142   if (ResetMCastList) {\r
143     Snp->Cdb.OpFlags |= PXE_OPFLAGS_RECEIVE_FILTER_RESET_MCAST_LIST;\r
144   }\r
145 \r
146   if ((DisableFlags & EFI_SIMPLE_NETWORK_RECEIVE_UNICAST) != 0) {\r
147     Snp->Cdb.OpFlags |= PXE_OPFLAGS_RECEIVE_FILTER_UNICAST;\r
148   }\r
149 \r
150   if ((DisableFlags & EFI_SIMPLE_NETWORK_RECEIVE_BROADCAST) != 0) {\r
151     Snp->Cdb.OpFlags |= PXE_OPFLAGS_RECEIVE_FILTER_BROADCAST;\r
152   }\r
153 \r
154   if ((DisableFlags & EFI_SIMPLE_NETWORK_RECEIVE_PROMISCUOUS) != 0) {\r
155     Snp->Cdb.OpFlags |= PXE_OPFLAGS_RECEIVE_FILTER_PROMISCUOUS;\r
156   }\r
157 \r
158   if ((DisableFlags & EFI_SIMPLE_NETWORK_RECEIVE_PROMISCUOUS_MULTICAST) != 0) {\r
159     Snp->Cdb.OpFlags |= PXE_OPFLAGS_RECEIVE_FILTER_ALL_MULTICAST;\r
160   }\r
161 \r
162   if ((DisableFlags & EFI_SIMPLE_NETWORK_RECEIVE_MULTICAST) != 0) {\r
163     Snp->Cdb.OpFlags |= PXE_OPFLAGS_RECEIVE_FILTER_FILTERED_MULTICAST;\r
164   }\r
165   //\r
166   // Issue UNDI command and check result.\r
167   //\r
168   DEBUG ((EFI_D_NET, "\nsnp->undi.receive_filters()  "));\r
169 \r
170   (*Snp->IssueUndi32Command) ((UINT64)(UINTN) &Snp->Cdb);\r
171 \r
172   if (Snp->Cdb.StatCode != EFI_SUCCESS) {\r
173     //\r
174     // UNDI command failed.  Return UNDI status to caller.\r
175     //\r
176     DEBUG (\r
177       (EFI_D_ERROR,\r
178       "\nsnp->undi.receive_filters()  %xh:%xh\n",\r
179       Snp->Cdb.StatFlags,\r
180       Snp->Cdb.StatCode)\r
181       );\r
182 \r
183     return EFI_DEVICE_ERROR;\r
184   }\r
185 \r
186   return EFI_SUCCESS;\r
187 }\r
188 \r
189 /**\r
190   this routine calls undi to read the receive filters.\r
191 \r
192   @param  Snp                pointer to snp driver structure\r
193 \r
194 \r
195 **/\r
196 EFI_STATUS\r
197 PxeRecvFilterRead (\r
198   SNP_DRIVER *Snp\r
199   )\r
200 {\r
201   Snp->Cdb.OpCode   = PXE_OPCODE_RECEIVE_FILTERS;\r
202   Snp->Cdb.OpFlags  = PXE_OPFLAGS_RECEIVE_FILTER_READ;\r
203   Snp->Cdb.CPBsize  = PXE_CPBSIZE_NOT_USED;\r
204   Snp->Cdb.DBsize   = (UINT16) (Snp->Mode.MaxMCastFilterCount * sizeof (EFI_MAC_ADDRESS));\r
205   Snp->Cdb.CPBaddr  = PXE_CPBADDR_NOT_USED;\r
206   if (Snp->Cdb.DBsize == 0) {\r
207     Snp->Cdb.DBaddr = (UINT64)(UINTN) NULL;\r
208   } else {\r
209     Snp->Cdb.DBaddr = (UINT64)(UINTN) Snp->Db;\r
210     ZeroMem (Snp->Db, Snp->Cdb.DBsize);\r
211   }\r
212 \r
213   Snp->Cdb.StatCode   = PXE_STATCODE_INITIALIZE;\r
214   Snp->Cdb.StatFlags  = PXE_STATFLAGS_INITIALIZE;\r
215   Snp->Cdb.IFnum      = Snp->IfNum;\r
216   Snp->Cdb.Control    = PXE_CONTROL_LAST_CDB_IN_LIST;\r
217 \r
218   DEBUG ((EFI_D_NET, "\nsnp->undi.receive_filters()  "));\r
219 \r
220   (*Snp->IssueUndi32Command) ((UINT64)(UINTN) &Snp->Cdb);\r
221 \r
222   if (Snp->Cdb.StatCode != EFI_SUCCESS) {\r
223     //\r
224     // UNDI command failed.  Return UNDI status to caller.\r
225     //\r
226     DEBUG (\r
227       (EFI_D_ERROR,\r
228       "\nsnp->undi.receive_filters()  %xh:%xh\n",\r
229       Snp->Cdb.StatFlags,\r
230       Snp->Cdb.StatCode)\r
231       );\r
232 \r
233     return EFI_DEVICE_ERROR;\r
234   }\r
235   //\r
236   // Convert UNDI32 StatFlags to EFI SNP filter flags.\r
237   //\r
238   Snp->Mode.ReceiveFilterSetting = 0;\r
239 \r
240   if ((Snp->Cdb.StatFlags & PXE_STATFLAGS_RECEIVE_FILTER_UNICAST) != 0) {\r
241     Snp->Mode.ReceiveFilterSetting |= EFI_SIMPLE_NETWORK_RECEIVE_UNICAST;\r
242   }\r
243 \r
244   if ((Snp->Cdb.StatFlags & PXE_STATFLAGS_RECEIVE_FILTER_BROADCAST) != 0) {\r
245     Snp->Mode.ReceiveFilterSetting |= EFI_SIMPLE_NETWORK_RECEIVE_BROADCAST;\r
246   }\r
247 \r
248   if ((Snp->Cdb.StatFlags & PXE_STATFLAGS_RECEIVE_FILTER_PROMISCUOUS) != 0) {\r
249     Snp->Mode.ReceiveFilterSetting |= EFI_SIMPLE_NETWORK_RECEIVE_PROMISCUOUS;\r
250   }\r
251 \r
252   if ((Snp->Cdb.StatFlags & PXE_STATFLAGS_RECEIVE_FILTER_ALL_MULTICAST) != 0) {\r
253     Snp->Mode.ReceiveFilterSetting |= EFI_SIMPLE_NETWORK_RECEIVE_PROMISCUOUS_MULTICAST;\r
254   }\r
255 \r
256   if ((Snp->Cdb.StatFlags & PXE_STATFLAGS_RECEIVE_FILTER_FILTERED_MULTICAST) != 0) {\r
257     Snp->Mode.ReceiveFilterSetting |= EFI_SIMPLE_NETWORK_RECEIVE_MULTICAST;\r
258   }\r
259 \r
260   CopyMem (Snp->Mode.MCastFilter, Snp->Db, Snp->Cdb.DBsize);\r
261 \r
262   //\r
263   // Count number of active entries in multicast filter list.\r
264   //\r
265   {\r
266     EFI_MAC_ADDRESS ZeroMacAddr;\r
267 \r
268     SetMem (&ZeroMacAddr, sizeof ZeroMacAddr, 0);\r
269 \r
270     for (Snp->Mode.MCastFilterCount = 0;\r
271          Snp->Mode.MCastFilterCount < Snp->Mode.MaxMCastFilterCount;\r
272          Snp->Mode.MCastFilterCount++\r
273         ) {\r
274       if (CompareMem (\r
275             &Snp->Mode.MCastFilter[Snp->Mode.MCastFilterCount],\r
276             &ZeroMacAddr,\r
277             sizeof ZeroMacAddr\r
278             ) == 0) {\r
279         break;\r
280       }\r
281     }\r
282   }\r
283 \r
284   return EFI_SUCCESS;\r
285 }\r
286 \r
287 \r
288 /**\r
289   Manages the multicast receive filters of a network interface.\r
290   \r
291   This function is used enable and disable the hardware and software receive \r
292   filters for the underlying network device.\r
293   The receive filter change is broken down into three steps: \r
294   * The filter mask bits that are set (ON) in the Enable parameter are added to \r
295     the current receive filter settings. \r
296   * The filter mask bits that are set (ON) in the Disable parameter are subtracted\r
297     from the updated receive filter settings.\r
298   * If the resulting receive filter setting is not supported by the hardware a\r
299     more liberal setting is selected.\r
300   If the same bits are set in the Enable and Disable parameters, then the bits \r
301   in the Disable parameter takes precedence.\r
302   If the ResetMCastFilter parameter is TRUE, then the multicast address list \r
303   filter is disabled (irregardless of what other multicast bits are set in the \r
304   Enable and Disable parameters). The SNP->Mode->MCastFilterCount field is set \r
305   to zero. The Snp->Mode->MCastFilter contents are undefined.\r
306   After enabling or disabling receive filter settings, software should verify \r
307   the new settings by checking the Snp->Mode->ReceiveFilterSettings, \r
308   Snp->Mode->MCastFilterCount and Snp->Mode->MCastFilter fields.\r
309   Note: Some network drivers and/or devices will automatically promote receive \r
310     filter settings if the requested setting can not be honored. For example, if\r
311     a request for four multicast addresses is made and the underlying hardware \r
312     only supports two multicast addresses the driver might set the promiscuous \r
313     or promiscuous multicast receive filters instead. The receiving software is\r
314     responsible for discarding any extra packets that get through the hardware \r
315     receive filters.\r
316     Note: Note: To disable all receive filter hardware, the network driver must \r
317       be Shutdown() and Stopped(). Calling ReceiveFilters() with Disable set to\r
318       Snp->Mode->ReceiveFilterSettings will make it so no more packets are \r
319       returned by the Receive() function, but the receive hardware may still be \r
320       moving packets into system memory before inspecting and discarding them.\r
321       Unexpected system errors, reboots and hangs can occur if an OS is loaded \r
322       and the network devices are not Shutdown() and Stopped().\r
323   If ResetMCastFilter is TRUE, then the multicast receive filter list on the \r
324   network interface will be reset to the default multicast receive filter list.\r
325   If ResetMCastFilter is FALSE, and this network interface allows the multicast \r
326   receive filter list to be modified, then the MCastFilterCnt and MCastFilter \r
327   are used to update the current multicast receive filter list. The modified \r
328   receive filter list settings can be found in the MCastFilter field of \r
329   EFI_SIMPLE_NETWORK_MODE. If the network interface does not allow the multicast\r
330   receive filter list to be modified, then EFI_INVALID_PARAMETER will be returned.\r
331   If the driver has not been initialized, EFI_DEVICE_ERROR will be returned.\r
332   If the receive filter mask and multicast receive filter list have been \r
333   successfully updated on the network interface, EFI_SUCCESS will be returned.\r
334 \r
335   @param This             A pointer to the EFI_SIMPLE_NETWORK_PROTOCOL instance.\r
336   @param Enable           A bit mask of receive filters to enable on the network\r
337                           interface.\r
338   @param Disable          A bit mask of receive filters to disable on the network\r
339                           interface. For backward compatibility with EFI 1.1 \r
340                           platforms, the EFI_SIMPLE_NETWORK_RECEIVE_MULTICAST bit\r
341                           must be set when the ResetMCastFilter parameter is TRUE.\r
342   @param ResetMCastFilter Set to TRUE to reset the contents of the multicast \r
343                           receive filters on the network interface to their \r
344                           default values. \r
345   @param MCastFilterCnt   Number of multicast HW MAC addresses in the new MCastFilter\r
346                           list. This value must be less than or equal to the \r
347                           MCastFilterCnt field of EFI_SIMPLE_NETWORK_MODE. \r
348                           This field is optional if ResetMCastFilter is TRUE.\r
349   @param MCastFilter      A pointer to a list of new multicast receive filter HW\r
350                           MAC addresses. This list will replace any existing \r
351                           multicast HW MAC address list. This field is optional \r
352                           if ResetMCastFilter is TRUE.\r
353    \r
354   @retval EFI_SUCCESS            The multicast receive filter list was updated.\r
355   @retval EFI_NOT_STARTED        The network interface has not been started.\r
356   @retval EFI_INVALID_PARAMETER  One or more of the following conditions is TRUE:\r
357                                  * This is NULL\r
358                                  * There are bits set in Enable that are not set\r
359                                    in Snp->Mode->ReceiveFilterMask\r
360                                  * There are bits set in Disable that are not set\r
361                                    in Snp->Mode->ReceiveFilterMask\r
362                                  * Multicast is being enabled (the \r
363                                    EFI_SIMPLE_NETWORK_RECEIVE_MULTICAST bit is \r
364                                    set in Enable, it is not set in Disable, and \r
365                                    ResetMCastFilter is FALSE) and MCastFilterCount\r
366                                    is zero\r
367                                  * Multicast is being enabled and MCastFilterCount\r
368                                    is greater than Snp->Mode->MaxMCastFilterCount\r
369                                  * Multicast is being enabled and MCastFilter is NULL\r
370                                  * Multicast is being enabled and one or more of\r
371                                    the addresses in the MCastFilter list are not\r
372                                    valid multicast MAC addresses\r
373   @retval EFI_DEVICE_ERROR       One or more of the following conditions is TRUE:\r
374                                  * The network interface has been started but has\r
375                                    not been initialized\r
376                                  * An unexpected error was returned by the \r
377                                    underlying network driver or device\r
378   @retval EFI_UNSUPPORTED        This function is not supported by the network\r
379                                  interface.\r
380 \r
381 **/\r
382 EFI_STATUS\r
383 EFIAPI\r
384 SnpUndi32ReceiveFilters (\r
385   IN EFI_SIMPLE_NETWORK_PROTOCOL *This,\r
386   IN UINT32                      Enable,\r
387   IN UINT32                      Disable,\r
388   IN BOOLEAN                     ResetMCastFilter,\r
389   IN UINTN                       MCastFilterCnt,  OPTIONAL\r
390   IN EFI_MAC_ADDRESS             *MCastFilter     OPTIONAL\r
391   )\r
392 {\r
393   SNP_DRIVER  *Snp;\r
394   EFI_STATUS  Status;\r
395   EFI_TPL     OldTpl;\r
396 \r
397   if (This == NULL) {\r
398     return EFI_INVALID_PARAMETER;\r
399   }\r
400 \r
401   Snp = EFI_SIMPLE_NETWORK_DEV_FROM_THIS (This);\r
402 \r
403   OldTpl = gBS->RaiseTPL (TPL_CALLBACK);\r
404 \r
405   switch (Snp->Mode.State) {\r
406   case EfiSimpleNetworkInitialized:\r
407     break;\r
408 \r
409   case EfiSimpleNetworkStopped:\r
410     Status = EFI_NOT_STARTED;\r
411     goto ON_EXIT;\r
412 \r
413   default:\r
414     Status = EFI_DEVICE_ERROR;\r
415     goto ON_EXIT;\r
416   }\r
417   //\r
418   // check if we are asked to enable or disable something that the UNDI\r
419   // does not even support!\r
420   //\r
421   if (((Enable &~Snp->Mode.ReceiveFilterMask) != 0) ||\r
422     ((Disable &~Snp->Mode.ReceiveFilterMask) != 0)) {\r
423     Status = EFI_INVALID_PARAMETER;\r
424     goto ON_EXIT;\r
425   }\r
426 \r
427   if (ResetMCastFilter) {\r
428 \r
429     Disable |= EFI_SIMPLE_NETWORK_RECEIVE_MULTICAST & Snp->Mode.ReceiveFilterMask;\r
430     MCastFilterCnt = 0;\r
431     MCastFilter    = NULL;\r
432   } else {\r
433     if (MCastFilterCnt != 0) {\r
434       if ((MCastFilterCnt > Snp->Mode.MaxMCastFilterCount) ||\r
435           (MCastFilter == NULL)) {\r
436 \r
437         Status = EFI_INVALID_PARAMETER;\r
438         goto ON_EXIT;\r
439       }\r
440     }\r
441   }\r
442 \r
443   if (Enable == 0 && Disable == 0 && !ResetMCastFilter && MCastFilterCnt == 0) {\r
444     Status = EFI_SUCCESS;\r
445     goto ON_EXIT;\r
446   }\r
447 \r
448   if ((Enable & EFI_SIMPLE_NETWORK_RECEIVE_MULTICAST) != 0 && MCastFilterCnt == 0) {\r
449     Status = EFI_INVALID_PARAMETER;\r
450     goto ON_EXIT;\r
451   }\r
452 \r
453   if ((Enable != 0) || (MCastFilterCnt != 0)) {\r
454     Status = PxeRecvFilterEnable (\r
455                Snp,\r
456                Enable,\r
457                MCastFilterCnt,\r
458                MCastFilter\r
459                );\r
460 \r
461     if (EFI_ERROR (Status)) {\r
462       goto ON_EXIT;\r
463     }\r
464   }\r
465 \r
466   if ((Disable != 0) || ResetMCastFilter) {\r
467     Status = PxeRecvFilterDisable (Snp, Disable, ResetMCastFilter);\r
468 \r
469     if (EFI_ERROR (Status)) {\r
470       goto ON_EXIT;\r
471     }\r
472   }\r
473 \r
474   Status = PxeRecvFilterRead (Snp);\r
475 \r
476 ON_EXIT:\r
477   gBS->RestoreTPL (OldTpl);\r
478 \r
479   return Status;\r
480 }\r