BaseTools:Change the path of the file that Binary Cache
[mirror_edk2.git] / MdeModulePkg / Universal / Network / SnpDxe / Receive.c
1 /** @file\r
2   Implementation of receiving a packet from a network interface.\r
3 \r
4 Copyright (c) 2004 - 2010, Intel Corporation. All rights reserved.<BR>\r
5 SPDX-License-Identifier: BSD-2-Clause-Patent\r
6 \r
7 **/\r
8 \r
9 \r
10 #include "Snp.h"\r
11 \r
12 /**\r
13   Call UNDI to receive a packet and fills in the data in the input pointers.\r
14 \r
15   @param  Snp          Pointer to snp driver structure\r
16   @param  Buffer       Pointer to the memory for the received data\r
17   @param  BufferSize   Pointer to the length of the buffer on entry and contains\r
18                        the length of the received data on return\r
19   @param  HeaderSize   Pointer to the header portion of the data received.\r
20   @param  SrcAddr      Pointer to contain the source ethernet address on return\r
21   @param  DestAddr     Pointer to contain the destination ethernet address on\r
22                        return\r
23   @param  Protocol     Pointer to contain the protocol type from the ethernet\r
24                        header on return\r
25 \r
26 \r
27   @retval EFI_SUCCESS           The received data was stored in Buffer, and\r
28                                 BufferSize has been updated to the number of\r
29                                 bytes received.\r
30   @retval EFI_DEVICE_ERROR      Fail to execute UNDI command.\r
31   @retval EFI_NOT_READY         No packets have been received on the network\r
32                                 interface.\r
33   @retval EFI_BUFFER_TOO_SMALL  BufferSize is too small for the received\r
34                                 packets. BufferSize has been updated to the\r
35                                 required size.\r
36 \r
37 **/\r
38 EFI_STATUS\r
39 PxeReceive (\r
40   SNP_DRIVER      *Snp,\r
41   VOID            *Buffer,\r
42   UINTN           *BufferSize,\r
43   UINTN           *HeaderSize,\r
44   EFI_MAC_ADDRESS *SrcAddr,\r
45   EFI_MAC_ADDRESS *DestAddr,\r
46   UINT16          *Protocol\r
47   )\r
48 {\r
49   PXE_CPB_RECEIVE *Cpb;\r
50   PXE_DB_RECEIVE  *Db;\r
51   UINTN           BuffSize;\r
52 \r
53   Cpb       = Snp->Cpb;\r
54   Db        = Snp->Db;\r
55   BuffSize  = *BufferSize;\r
56 \r
57   Cpb->BufferAddr = (UINT64)(UINTN) Buffer;\r
58   Cpb->BufferLen  = (UINT32) *BufferSize;\r
59 \r
60   Cpb->reserved       = 0;\r
61 \r
62   Snp->Cdb.OpCode     = PXE_OPCODE_RECEIVE;\r
63   Snp->Cdb.OpFlags    = PXE_OPFLAGS_NOT_USED;\r
64 \r
65   Snp->Cdb.CPBsize    = (UINT16) sizeof (PXE_CPB_RECEIVE);\r
66   Snp->Cdb.CPBaddr    = (UINT64)(UINTN) Cpb;\r
67 \r
68   Snp->Cdb.DBsize     = (UINT16) sizeof (PXE_DB_RECEIVE);\r
69   Snp->Cdb.DBaddr     = (UINT64)(UINTN) Db;\r
70 \r
71   Snp->Cdb.StatCode   = PXE_STATCODE_INITIALIZE;\r
72   Snp->Cdb.StatFlags  = PXE_STATFLAGS_INITIALIZE;\r
73   Snp->Cdb.IFnum      = Snp->IfNum;\r
74   Snp->Cdb.Control    = PXE_CONTROL_LAST_CDB_IN_LIST;\r
75 \r
76   //\r
77   // Issue UNDI command and check result.\r
78   //\r
79   DEBUG ((EFI_D_NET, "\nsnp->undi.receive ()  "));\r
80 \r
81   (*Snp->IssueUndi32Command) ((UINT64)(UINTN) &Snp->Cdb);\r
82 \r
83   switch (Snp->Cdb.StatCode) {\r
84   case PXE_STATCODE_SUCCESS:\r
85     break;\r
86 \r
87   case PXE_STATCODE_NO_DATA:\r
88     DEBUG (\r
89       (EFI_D_NET,\r
90       "\nsnp->undi.receive ()  %xh:%xh\n",\r
91       Snp->Cdb.StatFlags,\r
92       Snp->Cdb.StatCode)\r
93       );\r
94 \r
95     return EFI_NOT_READY;\r
96 \r
97   default:\r
98     DEBUG (\r
99       (EFI_D_ERROR,\r
100       "\nsnp->undi.receive()  %xh:%xh\n",\r
101       Snp->Cdb.StatFlags,\r
102       Snp->Cdb.StatCode)\r
103       );\r
104 \r
105     return EFI_DEVICE_ERROR;\r
106   }\r
107 \r
108   *BufferSize = Db->FrameLen;\r
109 \r
110   if (HeaderSize != NULL) {\r
111     *HeaderSize = Db->MediaHeaderLen;\r
112   }\r
113 \r
114   if (SrcAddr != NULL) {\r
115     CopyMem (SrcAddr, &Db->SrcAddr, Snp->Mode.HwAddressSize);\r
116   }\r
117 \r
118   if (DestAddr != NULL) {\r
119     CopyMem (DestAddr, &Db->DestAddr, Snp->Mode.HwAddressSize);\r
120   }\r
121 \r
122   if (Protocol != NULL) {\r
123     //\r
124     // We need to do the byte swapping\r
125     //\r
126     *Protocol = (UINT16) PXE_SWAP_UINT16 (Db->Protocol);\r
127   }\r
128 \r
129   //\r
130   // We have received a packet from network interface, which implies that the\r
131   // network cable should be present. While, some UNDI driver may not report\r
132   // correct media status during Snp->Initialize(). So, we need ensure\r
133   // MediaPresent in SNP mode data is set to correct value.\r
134   //\r
135   if (Snp->Mode.MediaPresentSupported && !Snp->Mode.MediaPresent) {\r
136     Snp->Mode.MediaPresent = TRUE;\r
137   }\r
138 \r
139   return (*BufferSize <= BuffSize) ? EFI_SUCCESS : EFI_BUFFER_TOO_SMALL;\r
140 }\r
141 \r
142 /**\r
143   Receives a packet from a network interface.\r
144 \r
145   This function retrieves one packet from the receive queue of a network interface.\r
146   If there are no packets on the receive queue, then EFI_NOT_READY will be\r
147   returned. If there is a packet on the receive queue, and the size of the packet\r
148   is smaller than BufferSize, then the contents of the packet will be placed in\r
149   Buffer, and BufferSize will be updated with the actual size of the packet.\r
150   In addition, if SrcAddr, DestAddr, and Protocol are not NULL, then these values\r
151   will be extracted from the media header and returned. EFI_SUCCESS will be\r
152   returned if a packet was successfully received.\r
153   If BufferSize is smaller than the received packet, then the size of the receive\r
154   packet will be placed in BufferSize and EFI_BUFFER_TOO_SMALL will be returned.\r
155   If the driver has not been initialized, EFI_DEVICE_ERROR will be returned.\r
156 \r
157   @param This       A pointer to the EFI_SIMPLE_NETWORK_PROTOCOL instance.\r
158   @param HeaderSize The size, in bytes, of the media header received on the network\r
159                     interface. If this parameter is NULL, then the media header size\r
160                     will not be returned.\r
161   @param BufferSize On entry, the size, in bytes, of Buffer. On exit, the size, in\r
162                     bytes, of the packet that was received on the network interface.\r
163   @param Buffer     A pointer to the data buffer to receive both the media\r
164                     header and the data.\r
165   @param SrcAddr    The source HW MAC address. If this parameter is NULL, the HW\r
166                     MAC source address will not be extracted from the media header.\r
167   @param DestAddr   The destination HW MAC address. If this parameter is NULL,\r
168                     the HW MAC destination address will not be extracted from\r
169                     the media header.\r
170   @param Protocol   The media header type. If this parameter is NULL, then the\r
171                     protocol will not be extracted from the media header. See\r
172                     RFC 1700 section "Ether Types" for examples.\r
173 \r
174   @retval EFI_SUCCESS           The received data was stored in Buffer, and\r
175                                 BufferSize has been updated to the number of\r
176                                 bytes received.\r
177   @retval EFI_NOT_STARTED       The network interface has not been started.\r
178   @retval EFI_NOT_READY         No packets have been received on the network interface.\r
179   @retval EFI_BUFFER_TOO_SMALL  BufferSize is too small for the received packets.\r
180                                 BufferSize has been updated to the required size.\r
181   @retval EFI_INVALID_PARAMETER One or more of the following conditions is TRUE:\r
182                                 * The This parameter is NULL\r
183                                 * The This parameter does not point to a valid\r
184                                   EFI_SIMPLE_NETWORK_PROTOCOL structure.\r
185                                 * The BufferSize parameter is NULL\r
186                                 * The Buffer parameter is NULL\r
187   @retval EFI_DEVICE_ERROR      The command could not be sent to the network interface.\r
188 \r
189 **/\r
190 EFI_STATUS\r
191 EFIAPI\r
192 SnpUndi32Receive (\r
193   IN EFI_SIMPLE_NETWORK_PROTOCOL *This,\r
194   OUT UINTN                      *HeaderSize OPTIONAL,\r
195   IN OUT UINTN                   *BufferSize,\r
196   OUT VOID                       *Buffer,\r
197   OUT EFI_MAC_ADDRESS            *SrcAddr OPTIONAL,\r
198   OUT EFI_MAC_ADDRESS            *DestAddr OPTIONAL,\r
199   OUT UINT16                     *Protocol OPTIONAL\r
200   )\r
201 {\r
202   SNP_DRIVER  *Snp;\r
203   EFI_TPL     OldTpl;\r
204   EFI_STATUS  Status;\r
205 \r
206   if (This == NULL) {\r
207     return EFI_INVALID_PARAMETER;\r
208   }\r
209 \r
210   Snp = EFI_SIMPLE_NETWORK_DEV_FROM_THIS (This);\r
211 \r
212   OldTpl = gBS->RaiseTPL (TPL_CALLBACK);\r
213 \r
214   switch (Snp->Mode.State) {\r
215   case EfiSimpleNetworkInitialized:\r
216     break;\r
217 \r
218   case EfiSimpleNetworkStopped:\r
219     Status = EFI_NOT_STARTED;\r
220     goto ON_EXIT;\r
221 \r
222   default:\r
223     Status = EFI_DEVICE_ERROR;\r
224     goto ON_EXIT;\r
225   }\r
226 \r
227   if ((BufferSize == NULL) || (Buffer == NULL)) {\r
228     Status = EFI_INVALID_PARAMETER;\r
229     goto ON_EXIT;\r
230   }\r
231 \r
232   if (Snp->Mode.ReceiveFilterSetting == 0) {\r
233     Status = EFI_DEVICE_ERROR;\r
234     goto ON_EXIT;\r
235   }\r
236 \r
237   Status = PxeReceive (\r
238              Snp,\r
239              Buffer,\r
240              BufferSize,\r
241              HeaderSize,\r
242              SrcAddr,\r
243              DestAddr,\r
244              Protocol\r
245              );\r
246 \r
247 ON_EXIT:\r
248   gBS->RestoreTPL (OldTpl);\r
249 \r
250   return Status;\r
251 }\r