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