]> git.proxmox.com Git - mirror_edk2.git/blame - MdeModulePkg/Universal/Network/SnpDxe/Receive.c
MdeModulePkg: Replace BSD License with BSD+Patent License
[mirror_edk2.git] / MdeModulePkg / Universal / Network / SnpDxe / Receive.c
CommitLineData
3bb7aff3 1/** @file\r
4140a663 2 Implementation of receiving a packet from a network interface.\r
5fe48e54 3\r
e5eed7d3 4Copyright (c) 2004 - 2010, Intel Corporation. All rights reserved.<BR>\r
9d510e61 5SPDX-License-Identifier: BSD-2-Clause-Patent\r
3bb7aff3 6\r
3bb7aff3 7**/\r
8\r
9\r
10#include "Snp.h"\r
11\r
12/**\r
f3816027 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
5fe48e54 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
f3816027 22 return\r
5fe48e54 23 @param Protocol Pointer to contain the protocol type from the ethernet\r
f3816027 24 header on return\r
25\r
26\r
5fe48e54 27 @retval EFI_SUCCESS The received data was stored in Buffer, and\r
28 BufferSize has been updated to the number of\r
f3816027 29 bytes received.\r
5fe48e54 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
f3816027 32 interface.\r
5fe48e54 33 @retval EFI_BUFFER_TOO_SMALL BufferSize is too small for the received\r
f3816027 34 packets. BufferSize has been updated to the\r
35 required size.\r
3bb7aff3 36\r
37**/\r
3bb7aff3 38EFI_STATUS\r
4cda7726 39PxeReceive (\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
3bb7aff3 47 )\r
48{\r
4cda7726 49 PXE_CPB_RECEIVE *Cpb;\r
50 PXE_DB_RECEIVE *Db;\r
51 UINTN BuffSize;\r
3bb7aff3 52\r
4cda7726 53 Cpb = Snp->Cpb;\r
54 Db = Snp->Db;\r
55 BuffSize = *BufferSize;\r
3bb7aff3 56\r
4cda7726 57 Cpb->BufferAddr = (UINT64)(UINTN) Buffer;\r
58 Cpb->BufferLen = (UINT32) *BufferSize;\r
3bb7aff3 59\r
4cda7726 60 Cpb->reserved = 0;\r
3bb7aff3 61\r
4cda7726 62 Snp->Cdb.OpCode = PXE_OPCODE_RECEIVE;\r
63 Snp->Cdb.OpFlags = PXE_OPFLAGS_NOT_USED;\r
3bb7aff3 64\r
c9325700 65 Snp->Cdb.CPBsize = (UINT16) sizeof (PXE_CPB_RECEIVE);\r
4cda7726 66 Snp->Cdb.CPBaddr = (UINT64)(UINTN) Cpb;\r
3bb7aff3 67\r
c9325700 68 Snp->Cdb.DBsize = (UINT16) sizeof (PXE_DB_RECEIVE);\r
4cda7726 69 Snp->Cdb.DBaddr = (UINT64)(UINTN) Db;\r
3bb7aff3 70\r
4cda7726 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
3bb7aff3 75\r
76 //\r
77 // Issue UNDI command and check result.\r
78 //\r
5fe48e54 79 DEBUG ((EFI_D_NET, "\nsnp->undi.receive () "));\r
3bb7aff3 80\r
4cda7726 81 (*Snp->IssueUndi32Command) ((UINT64)(UINTN) &Snp->Cdb);\r
3bb7aff3 82\r
4cda7726 83 switch (Snp->Cdb.StatCode) {\r
3bb7aff3 84 case PXE_STATCODE_SUCCESS:\r
85 break;\r
86\r
87 case PXE_STATCODE_NO_DATA:\r
88 DEBUG (\r
5fe48e54 89 (EFI_D_NET,\r
3bb7aff3 90 "\nsnp->undi.receive () %xh:%xh\n",\r
4cda7726 91 Snp->Cdb.StatFlags,\r
92 Snp->Cdb.StatCode)\r
3bb7aff3 93 );\r
94\r
95 return EFI_NOT_READY;\r
96\r
97 default:\r
98 DEBUG (\r
9cff2f8d 99 (EFI_D_ERROR,\r
3bb7aff3 100 "\nsnp->undi.receive() %xh:%xh\n",\r
4cda7726 101 Snp->Cdb.StatFlags,\r
102 Snp->Cdb.StatCode)\r
3bb7aff3 103 );\r
104\r
105 return EFI_DEVICE_ERROR;\r
106 }\r
107\r
4cda7726 108 *BufferSize = Db->FrameLen;\r
3bb7aff3 109\r
4cda7726 110 if (HeaderSize != NULL) {\r
111 *HeaderSize = Db->MediaHeaderLen;\r
3bb7aff3 112 }\r
113\r
4cda7726 114 if (SrcAddr != NULL) {\r
115 CopyMem (SrcAddr, &Db->SrcAddr, Snp->Mode.HwAddressSize);\r
3bb7aff3 116 }\r
117\r
4cda7726 118 if (DestAddr != NULL) {\r
119 CopyMem (DestAddr, &Db->DestAddr, Snp->Mode.HwAddressSize);\r
3bb7aff3 120 }\r
121\r
4cda7726 122 if (Protocol != NULL) {\r
f3816027 123 //\r
124 // We need to do the byte swapping\r
125 //\r
126 *Protocol = (UINT16) PXE_SWAP_UINT16 (Db->Protocol);\r
3bb7aff3 127 }\r
128\r
553472f6 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
4cda7726 139 return (*BufferSize <= BuffSize) ? EFI_SUCCESS : EFI_BUFFER_TOO_SMALL;\r
3bb7aff3 140}\r
141\r
3bb7aff3 142/**\r
4cda7726 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
5fe48e54 146 If there are no packets on the receive queue, then EFI_NOT_READY will be\r
4cda7726 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
5fe48e54 151 will be extracted from the media header and returned. EFI_SUCCESS will be\r
4cda7726 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
5fe48e54 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
4cda7726 160 will not be returned.\r
5fe48e54 161 @param BufferSize On entry, the size, in bytes, of Buffer. On exit, the size, in\r
4cda7726 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
5fe48e54 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
4cda7726 169 the media header.\r
5fe48e54 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
4cda7726 172 RFC 1700 section "Ether Types" for examples.\r
173\r
5fe48e54 174 @retval EFI_SUCCESS The received data was stored in Buffer, and\r
175 BufferSize has been updated to the number of\r
4cda7726 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
5fe48e54 179 @retval EFI_BUFFER_TOO_SMALL BufferSize is too small for the received packets.\r
4cda7726 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
5fe48e54 183 * The This parameter does not point to a valid\r
4cda7726 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
3bb7aff3 188\r
189**/\r
190EFI_STATUS\r
191EFIAPI\r
4cda7726 192SnpUndi32Receive (\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
3bb7aff3 200 )\r
201{\r
4cda7726 202 SNP_DRIVER *Snp;\r
3bb7aff3 203 EFI_TPL OldTpl;\r
204 EFI_STATUS Status;\r
205\r
4cda7726 206 if (This == NULL) {\r
3bb7aff3 207 return EFI_INVALID_PARAMETER;\r
208 }\r
209\r
4cda7726 210 Snp = EFI_SIMPLE_NETWORK_DEV_FROM_THIS (This);\r
3bb7aff3 211\r
212 OldTpl = gBS->RaiseTPL (TPL_CALLBACK);\r
213\r
4cda7726 214 switch (Snp->Mode.State) {\r
3bb7aff3 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
4cda7726 227 if ((BufferSize == NULL) || (Buffer == NULL)) {\r
3bb7aff3 228 Status = EFI_INVALID_PARAMETER;\r
229 goto ON_EXIT;\r
230 }\r
231\r
4140a663 232 if (Snp->Mode.ReceiveFilterSetting == 0) {\r
3bb7aff3 233 Status = EFI_DEVICE_ERROR;\r
234 goto ON_EXIT;\r
235 }\r
236\r
4cda7726 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
3bb7aff3 245 );\r
246\r
247ON_EXIT:\r
248 gBS->RestoreTPL (OldTpl);\r
249\r
250 return Status;\r
251}\r