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