3 Copyright (c) 2004 - 2007, Intel Corporation
4 All rights reserved. This program and the accompanying materials
5 are licensed and made available under the terms and conditions of the BSD License
6 which accompanies this distribution. The full text of the license may be found at
7 http://opensource.org/licenses/bsd-license.php
9 THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
10 WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
23 // //////////////////////////////////////////////////////////////////////
25 // Udp Write Routine - called by base code - e.g. TFTP - already locked
30 @return EFI_SUCCESS :=
31 @return EFI_INVALID_PARAMETER :=
37 IN PXE_BASECODE_DEVICE
*Private
,
39 IN EFI_IP_ADDRESS
*DestIpPtr
,
40 IN EFI_PXE_BASE_CODE_UDP_PORT
*DestPortPtr
,
41 IN EFI_IP_ADDRESS
*GatewayIpPtr
, OPTIONAL
42 IN EFI_IP_ADDRESS
*SrcIpPtr
, OPTIONAL
43 IN OUT EFI_PXE_BASE_CODE_UDP_PORT
*SrcPortPtr
, OPTIONAL
44 IN UINTN
*HeaderSizePtr
, OPTIONAL
45 IN VOID
*HeaderPtr
, OPTIONAL
46 IN UINTN
*BufferSizeptr
,
52 EFI_PXE_BASE_CODE_UDP_PORT DefaultSrcPort
;
57 HeaderSize
= (HeaderSizePtr
!= NULL
) ? *HeaderSizePtr
: 0;
63 if (BufferSizeptr
== NULL
||
66 DestPortPtr
== NULL
||
67 (HeaderSizePtr
!= NULL
&& *HeaderSizePtr
== 0) ||
68 (HeaderSize
!= 0 && HeaderPtr
== NULL
) ||
69 (GatewayIpPtr
!= NULL
&& !IS_INADDR_UNICAST(GatewayIpPtr
)) ||
70 (OpFlags
&~(EFI_PXE_BASE_CODE_UDP_OPFLAGS_MAY_FRAGMENT
| EFI_PXE_BASE_CODE_UDP_OPFLAGS_ANY_SRC_PORT
))
74 "\nUdpWrite() Exit #1 %xh (%r)",
75 EFI_INVALID_PARAMETER
,
76 EFI_INVALID_PARAMETER
)
79 return EFI_INVALID_PARAMETER
;
82 TotalLength
= *BufferSizeptr
+ HeaderSize
+ sizeof (UDPV4_HEADER
);
84 if (TotalLength
> 0x0000ffff) {
87 "\nUdpWrite() Exit #2 %xh (%r)",
92 return EFI_BAD_BUFFER_SIZE
;
95 if (SrcIpPtr
== NULL
) {
96 SrcIpPtr
= &Private
->EfiBc
.Mode
->StationIp
;
99 if (SrcPortPtr
== NULL
) {
100 SrcPortPtr
= &DefaultSrcPort
;
101 OpFlags
|= EFI_PXE_BASE_CODE_UDP_OPFLAGS_ANY_SRC_PORT
;
104 if (OpFlags
& EFI_PXE_BASE_CODE_UDP_OPFLAGS_ANY_SRC_PORT
) {
105 *SrcPortPtr
= Private
->RandomPort
;
107 if (++Private
->RandomPort
== 0) {
108 Private
->RandomPort
= PXE_RND_PORT_LOW
;
112 #define IpTxBuffer ((IPV4_BUFFER *) Private->TransmitBufferPtr)
114 // build pseudo header and udp header in transmit buffer
116 #define Udpv4Base ((UDPV4_HEADERS *) (IpTxBuffer->u.Data - sizeof (UDPV4_PSEUDO_HEADER)))
118 Udpv4Base
->Udpv4PseudoHeader
.SrcAddr
.L
= SrcIpPtr
->Addr
[0];
119 Udpv4Base
->Udpv4PseudoHeader
.DestAddr
.L
= DestIpPtr
->Addr
[0];
120 Udpv4Base
->Udpv4PseudoHeader
.Zero
= 0;
121 Udpv4Base
->Udpv4PseudoHeader
.Protocol
= PROT_UDP
;
122 Udpv4Base
->Udpv4PseudoHeader
.TotalLength
= HTONS (TotalLength
);
123 Udpv4Base
->Udpv4Header
.SrcPort
= HTONS (*SrcPortPtr
);
124 Udpv4Base
->Udpv4Header
.DestPort
= HTONS (*DestPortPtr
);
125 Udpv4Base
->Udpv4Header
.TotalLength
= Udpv4Base
->Udpv4PseudoHeader
.TotalLength
;
126 Udpv4Base
->Udpv4Header
.Checksum
= 0;
128 if (HeaderSize
!= 0) {
129 CopyMem (IpTxBuffer
->u
.Udp
.Data
, HeaderPtr
, HeaderSize
);
132 HeaderSize
+= sizeof (UDPV4_HEADER
);
134 Udpv4Base
->Udpv4Header
.Checksum
= IpChecksum2 (
135 (UINT16
*) Udpv4Base
,
136 HeaderSize
+ sizeof (UDPV4_PSEUDO_HEADER
),
137 (UINT16
*) BufferPtr
,
138 (UINT16
) *BufferSizeptr
141 if (Udpv4Base
->Udpv4Header
.Checksum
== 0) {
142 Udpv4Base
->Udpv4Header
.Checksum
= 0xffff;
144 // transmit zero checksum as ones complement
152 Udpv4Base
->Udpv4PseudoHeader
.SrcAddr
.L
,
153 Udpv4Base
->Udpv4PseudoHeader
.DestAddr
.L
,
154 (GatewayIpPtr
) ? GatewayIpPtr
->Addr
[0] : 0,
161 // //////////////////////////////////////////////////////////
163 // BC Udp Write Routine
168 @return EFI_SUCCESS :=
175 IN EFI_PXE_BASE_CODE_PROTOCOL
*This
,
177 IN EFI_IP_ADDRESS
*DestIpPtr
,
178 IN EFI_PXE_BASE_CODE_UDP_PORT
*DestPortPtr
,
179 IN EFI_IP_ADDRESS
*GatewayIpPtr
, OPTIONAL
180 IN EFI_IP_ADDRESS
*SrcIpPtr
, OPTIONAL
181 IN OUT EFI_PXE_BASE_CODE_UDP_PORT
*SrcPortPtr
, OPTIONAL
182 IN UINTN
*HeaderSizePtr
, OPTIONAL
183 IN VOID
*HeaderPtr
, OPTIONAL
184 IN UINTN
*BufferSizeptr
,
189 PXE_BASECODE_DEVICE
*Private
;
192 // Lock the instance data and make sure started
194 StatCode
= EFI_SUCCESS
;
197 DEBUG ((DEBUG_ERROR
, "BC *This pointer == NULL"));
198 return EFI_INVALID_PARAMETER
;
201 Private
= CR (This
, PXE_BASECODE_DEVICE
, EfiBc
, PXE_BASECODE_DEVICE_SIGNATURE
);
203 if (Private
== NULL
) {
204 DEBUG ((DEBUG_ERROR
, "PXE_BASECODE_DEVICE poiner == NULL"));
205 return EFI_INVALID_PARAMETER
;
208 EfiAcquireLock (&Private
->Lock
);
210 if (This
->Mode
== NULL
|| !This
->Mode
->Started
) {
211 DEBUG ((DEBUG_ERROR
, "BC was not started."));
212 EfiReleaseLock (&Private
->Lock
);
213 return EFI_NOT_STARTED
;
216 Private
->Function
= EFI_PXE_BASE_CODE_FUNCTION_UDP_WRITE
;
221 StatCode
= UdpWrite (
236 // Unlock the instance data
238 EfiReleaseLock (&Private
->Lock
);
242 // /////////////////////////////////////////////////////////////////////
244 // Udp Read Routine - called by base code - e.g. TFTP - already locked
249 @return EFI_SUCCESS :=
250 @return EFI_INVALID_PARAMETER :=
256 IN PXE_BASECODE_DEVICE
*Private
,
258 IN OUT EFI_IP_ADDRESS
*DestIpPtr
, OPTIONAL
259 IN OUT EFI_PXE_BASE_CODE_UDP_PORT
*DestPortPtr
, OPTIONAL
260 IN OUT EFI_IP_ADDRESS
*SrcIpPtr
, OPTIONAL
261 IN OUT EFI_PXE_BASE_CODE_UDP_PORT
*SrcPortPtr
, OPTIONAL
262 IN UINTN
*HeaderSizePtr
, OPTIONAL
263 IN VOID
*HeaderPtr
, OPTIONAL
264 IN OUT UINTN
*BufferSizeptr
,
266 EFI_EVENT TimeoutEvent
270 EFI_IP_ADDRESS TmpSrcIp
;
271 EFI_IP_ADDRESS TmpDestIp
;
276 // combination structure of pseudo header/udp header
280 UDPV4_PSEUDO_HEADER Udpv4PseudoHeader
;
281 UDPV4_HEADER Udpv4Header
;
286 HeaderSize
= (HeaderSizePtr
!= NULL
) ? *HeaderSizePtr
: 0;
288 // read [with filtering]
291 if (BufferSizeptr
== NULL
||
293 (HeaderSize
!= 0 && HeaderPtr
== NULL
) ||
294 (OpFlags
&~UDP_FILTER_MASK
)
296 // if filtering on a particular IP/Port, need it
299 (!(OpFlags
& EFI_PXE_BASE_CODE_UDP_OPFLAGS_ANY_SRC_IP
) && SrcIpPtr
== NULL
) ||
300 (!(OpFlags
& EFI_PXE_BASE_CODE_UDP_OPFLAGS_ANY_SRC_PORT
) && SrcPortPtr
== NULL
) ||
301 (!(OpFlags
& EFI_PXE_BASE_CODE_UDP_OPFLAGS_ANY_DEST_PORT
) && DestPortPtr
== NULL
)
303 DEBUG ((DEBUG_INFO
, "\nUdpRead() Exit #1 Invalid Parameter"));
304 return EFI_INVALID_PARAMETER
;
310 BufferSize
= *BufferSizeptr
;
312 // we need source and dest IPs for pseudo header
314 if (SrcIpPtr
== NULL
) {
315 SrcIpPtr
= &TmpSrcIp
;
318 if (DestIpPtr
== NULL
) {
319 DestIpPtr
= &TmpDestIp
;
320 CopyMem (&TmpDestIp
, &Private
->EfiBc
.Mode
->StationIp
, sizeof (EFI_IP_ADDRESS
));
324 *BufferSizeptr
= BufferSize
;
326 StatCode
= IpReceive (
333 HeaderSize
+ sizeof Hdrs
.Udpv4Header
,
339 if (StatCode
== EFI_SUCCESS
|| StatCode
== EFI_BUFFER_TOO_SMALL
) {
343 SPort
= NTOHS (Hdrs
.Udpv4Header
.SrcPort
);
344 DPort
= NTOHS (Hdrs
.Udpv4Header
.DestPort
);
349 if (!(OpFlags
& EFI_PXE_BASE_CODE_UDP_OPFLAGS_ANY_SRC_PORT
) && *SrcPortPtr
!= SPort
) {
353 if (!(OpFlags
& EFI_PXE_BASE_CODE_UDP_OPFLAGS_ANY_DEST_PORT
) && *DestPortPtr
!= DPort
) {
359 if (StatCode
== EFI_SUCCESS
&& Hdrs
.Udpv4Header
.Checksum
) {
360 Hdrs
.Udpv4PseudoHeader
.SrcAddr
.L
= SrcIpPtr
->Addr
[0];
361 Hdrs
.Udpv4PseudoHeader
.DestAddr
.L
= DestIpPtr
->Addr
[0];
362 Hdrs
.Udpv4PseudoHeader
.Zero
= 0;
363 Hdrs
.Udpv4PseudoHeader
.Protocol
= PROT_UDP
;
364 Hdrs
.Udpv4PseudoHeader
.TotalLength
= Hdrs
.Udpv4Header
.TotalLength
;
366 if (Hdrs
.Udpv4Header
.Checksum
== 0xffff) {
367 Hdrs
.Udpv4Header
.Checksum
= 0;
371 (UINT16
*) &Hdrs
.Udpv4PseudoHeader
,
372 HeaderSize
+ sizeof (Hdrs
.Udpv4PseudoHeader
) + sizeof (Hdrs
.Udpv4Header
),
373 (UINT16
*) BufferPtr
,
378 "\nUdpRead() Hdrs.Udpv4PseudoHeader == %Xh",
379 &Hdrs
.Udpv4PseudoHeader
)
383 "\nUdpRead() Header size == %d",
384 HeaderSize
+ sizeof (Hdrs
.Udpv4PseudoHeader
))
388 "\nUdpRead() BufferPtr == %Xh",
393 "\nUdpRead() Buffer size == %d",
396 DEBUG ((DEBUG_INFO
, "\nUdpRead() Exit #2 Device Error"));
397 return EFI_DEVICE_ERROR
;
403 if (SrcPortPtr
!= NULL
) {
407 if (DestPortPtr
!= NULL
) {
408 *DestPortPtr
= DPort
;
411 if (HeaderSize
!= 0) {
412 CopyMem (HeaderPtr
, Hdrs
.ProtHdr
, HeaderSize
);
416 if ((StatCode
!= EFI_SUCCESS
) && (StatCode
!= EFI_TIMEOUT
)) {
419 "\nUdpRead() Exit #3 %Xh %r",
429 // //////////////////////////////////////////////////////////
431 // BC Udp Read Routine
436 @return EFI_SUCCESS :=
443 IN EFI_PXE_BASE_CODE_PROTOCOL
*This
,
445 IN OUT EFI_IP_ADDRESS
*DestIp
, OPTIONAL
446 IN OUT EFI_PXE_BASE_CODE_UDP_PORT
*DestPort
, OPTIONAL
447 IN OUT EFI_IP_ADDRESS
*SrcIp
, OPTIONAL
448 IN OUT EFI_PXE_BASE_CODE_UDP_PORT
*SrcPort
, OPTIONAL
449 IN UINTN
*HeaderSize
, OPTIONAL
450 IN VOID
*HeaderPtr
, OPTIONAL
451 IN OUT UINTN
*BufferSize
,
456 PXE_BASECODE_DEVICE
*Private
;
459 // Lock the instance data and make sure started
461 StatCode
= EFI_SUCCESS
;
464 DEBUG ((DEBUG_ERROR
, "BC *This pointer == NULL"));
465 return EFI_INVALID_PARAMETER
;
468 Private
= CR (This
, PXE_BASECODE_DEVICE
, EfiBc
, PXE_BASECODE_DEVICE_SIGNATURE
);
470 if (Private
== NULL
) {
471 DEBUG ((DEBUG_ERROR
, "PXE_BASECODE_DEVICE poiner == NULL"));
472 return EFI_INVALID_PARAMETER
;
475 EfiAcquireLock (&Private
->Lock
);
477 if (This
->Mode
== NULL
|| !This
->Mode
->Started
) {
478 DEBUG ((DEBUG_ERROR
, "BC was not started."));
479 EfiReleaseLock (&Private
->Lock
);
480 return EFI_NOT_STARTED
;
483 Private
->Function
= EFI_PXE_BASE_CODE_FUNCTION_UDP_READ
;
503 // Unlock the instance data and return
505 EfiReleaseLock (&Private
->Lock
);
509 /* eof - pxe_bc_udp.c */