3 Copyright (c) 2006, 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
29 IN PXE_BASECODE_DEVICE
*Private
,
31 IN EFI_IP_ADDRESS
*DestIpPtr
,
32 IN EFI_PXE_BASE_CODE_UDP_PORT
*DestPortPtr
,
33 IN EFI_IP_ADDRESS
*GatewayIpPtr
, OPTIONAL
34 IN EFI_IP_ADDRESS
*SrcIpPtr
, OPTIONAL
35 IN OUT EFI_PXE_BASE_CODE_UDP_PORT
*SrcPortPtr
, OPTIONAL
36 IN UINTN
*HeaderSizePtr
, OPTIONAL
37 IN VOID
*HeaderPtr
, OPTIONAL
38 IN UINTN
*BufferSizeptr
,
46 Private := Pointer to PxeBc interface
60 EFI_INVALID_PARAMETER :=
66 EFI_PXE_BASE_CODE_UDP_PORT DefaultSrcPort
;
71 HeaderSize
= (HeaderSizePtr
!= NULL
) ? *HeaderSizePtr
: 0;
77 if (BufferSizeptr
== NULL
||
80 DestPortPtr
== NULL
||
81 (HeaderSizePtr
!= NULL
&& *HeaderSizePtr
== 0) ||
82 (HeaderSize
!= 0 && HeaderPtr
== NULL
) ||
83 (GatewayIpPtr
!= NULL
&& !IS_INADDR_UNICAST(GatewayIpPtr
)) ||
84 (OpFlags
&~(EFI_PXE_BASE_CODE_UDP_OPFLAGS_MAY_FRAGMENT
| EFI_PXE_BASE_CODE_UDP_OPFLAGS_ANY_SRC_PORT
))
88 "\nUdpWrite() Exit #1 %xh (%r)",
89 EFI_INVALID_PARAMETER
,
90 EFI_INVALID_PARAMETER
)
93 return EFI_INVALID_PARAMETER
;
96 TotalLength
= *BufferSizeptr
+ HeaderSize
+ sizeof (UDPV4_HEADER
);
98 if (TotalLength
> 0x0000ffff) {
101 "\nUdpWrite() Exit #2 %xh (%r)",
106 return EFI_BAD_BUFFER_SIZE
;
109 if (SrcIpPtr
== NULL
) {
110 SrcIpPtr
= &Private
->EfiBc
.Mode
->StationIp
;
113 if (SrcPortPtr
== NULL
) {
114 SrcPortPtr
= &DefaultSrcPort
;
115 OpFlags
|= EFI_PXE_BASE_CODE_UDP_OPFLAGS_ANY_SRC_PORT
;
118 if (OpFlags
& EFI_PXE_BASE_CODE_UDP_OPFLAGS_ANY_SRC_PORT
) {
119 *SrcPortPtr
= Private
->RandomPort
;
121 if (++Private
->RandomPort
== 0) {
122 Private
->RandomPort
= PXE_RND_PORT_LOW
;
126 #define IpTxBuffer ((IPV4_BUFFER *) Private->TransmitBufferPtr)
128 // build pseudo header and udp header in transmit buffer
130 #define Udpv4Base ((UDPV4_HEADERS *) (IpTxBuffer->u.Data - sizeof (UDPV4_PSEUDO_HEADER)))
132 Udpv4Base
->Udpv4PseudoHeader
.SrcAddr
.L
= SrcIpPtr
->Addr
[0];
133 Udpv4Base
->Udpv4PseudoHeader
.DestAddr
.L
= DestIpPtr
->Addr
[0];
134 Udpv4Base
->Udpv4PseudoHeader
.Zero
= 0;
135 Udpv4Base
->Udpv4PseudoHeader
.Protocol
= PROT_UDP
;
136 Udpv4Base
->Udpv4PseudoHeader
.TotalLength
= HTONS (TotalLength
);
137 Udpv4Base
->Udpv4Header
.SrcPort
= HTONS (*SrcPortPtr
);
138 Udpv4Base
->Udpv4Header
.DestPort
= HTONS (*DestPortPtr
);
139 Udpv4Base
->Udpv4Header
.TotalLength
= Udpv4Base
->Udpv4PseudoHeader
.TotalLength
;
140 Udpv4Base
->Udpv4Header
.Checksum
= 0;
142 if (HeaderSize
!= 0) {
143 CopyMem (IpTxBuffer
->u
.Udp
.Data
, HeaderPtr
, HeaderSize
);
146 HeaderSize
+= sizeof (UDPV4_HEADER
);
148 Udpv4Base
->Udpv4Header
.Checksum
= IpChecksum2 (
149 (UINT16
*) Udpv4Base
,
150 HeaderSize
+ sizeof (UDPV4_PSEUDO_HEADER
),
151 (UINT16
*) BufferPtr
,
152 (UINT16
) *BufferSizeptr
155 if (Udpv4Base
->Udpv4Header
.Checksum
== 0) {
156 Udpv4Base
->Udpv4Header
.Checksum
= 0xffff;
158 // transmit zero checksum as ones complement
166 Udpv4Base
->Udpv4PseudoHeader
.SrcAddr
.L
,
167 Udpv4Base
->Udpv4PseudoHeader
.DestAddr
.L
,
168 (GatewayIpPtr
) ? GatewayIpPtr
->Addr
[0] : 0,
175 // //////////////////////////////////////////////////////////
177 // BC Udp Write Routine
182 IN EFI_PXE_BASE_CODE_PROTOCOL
*This
,
184 IN EFI_IP_ADDRESS
*DestIpPtr
,
185 IN EFI_PXE_BASE_CODE_UDP_PORT
*DestPortPtr
,
186 IN EFI_IP_ADDRESS
*GatewayIpPtr
, OPTIONAL
187 IN EFI_IP_ADDRESS
*SrcIpPtr
, OPTIONAL
188 IN OUT EFI_PXE_BASE_CODE_UDP_PORT
*SrcPortPtr
, OPTIONAL
189 IN UINTN
*HeaderSizePtr
, OPTIONAL
190 IN VOID
*HeaderPtr
, OPTIONAL
191 IN UINTN
*BufferSizeptr
,
196 UDP write API entry point.
199 This := Pointer to PxeBc interface.
217 PXE_BASECODE_DEVICE
*Private
;
220 // Lock the instance data and make sure started
222 StatCode
= EFI_SUCCESS
;
225 DEBUG ((EFI_D_ERROR
, "BC *This pointer == NULL"));
226 return EFI_INVALID_PARAMETER
;
229 Private
= CR (This
, PXE_BASECODE_DEVICE
, EfiBc
, PXE_BASECODE_DEVICE_SIGNATURE
);
231 if (Private
== NULL
) {
232 DEBUG ((EFI_D_ERROR
, "PXE_BASECODE_DEVICE poiner == NULL"));
233 return EFI_INVALID_PARAMETER
;
236 EfiAcquireLock (&Private
->Lock
);
238 if (This
->Mode
== NULL
|| !This
->Mode
->Started
) {
239 DEBUG ((EFI_D_ERROR
, "BC was not started."));
240 EfiReleaseLock (&Private
->Lock
);
241 return EFI_NOT_STARTED
;
244 Private
->Function
= EFI_PXE_BASE_CODE_FUNCTION_UDP_WRITE
;
249 StatCode
= UdpWrite (
264 // Unlock the instance data
266 EfiReleaseLock (&Private
->Lock
);
270 // /////////////////////////////////////////////////////////////////////
272 // Udp Read Routine - called by base code - e.g. TFTP - already locked
276 IN PXE_BASECODE_DEVICE
*Private
,
278 IN OUT EFI_IP_ADDRESS
*DestIpPtr
, OPTIONAL
279 IN OUT EFI_PXE_BASE_CODE_UDP_PORT
*DestPortPtr
, OPTIONAL
280 IN OUT EFI_IP_ADDRESS
*SrcIpPtr
, OPTIONAL
281 IN OUT EFI_PXE_BASE_CODE_UDP_PORT
*SrcPortPtr
, OPTIONAL
282 IN UINTN
*HeaderSizePtr
, OPTIONAL
283 IN VOID
*HeaderPtr
, OPTIONAL
284 IN OUT UINTN
*BufferSizeptr
,
286 EFI_EVENT TimeoutEvent
293 Private := Pointer to PxeBc interface
307 EFI_INVALID_PARAMETER :=
312 EFI_IP_ADDRESS TmpSrcIp
;
313 EFI_IP_ADDRESS TmpDestIp
;
318 // combination structure of pseudo header/udp header
322 UDPV4_PSEUDO_HEADER Udpv4PseudoHeader
;
323 UDPV4_HEADER Udpv4Header
;
328 HeaderSize
= (HeaderSizePtr
!= NULL
) ? *HeaderSizePtr
: 0;
330 // read [with filtering]
333 if (BufferSizeptr
== NULL
||
335 (HeaderSize
!= 0 && HeaderPtr
== NULL
) ||
336 (OpFlags
&~UDP_FILTER_MASK
)
338 // if filtering on a particular IP/Port, need it
341 (!(OpFlags
& EFI_PXE_BASE_CODE_UDP_OPFLAGS_ANY_SRC_IP
) && SrcIpPtr
== NULL
) ||
342 (!(OpFlags
& EFI_PXE_BASE_CODE_UDP_OPFLAGS_ANY_SRC_PORT
) && SrcPortPtr
== NULL
) ||
343 (!(OpFlags
& EFI_PXE_BASE_CODE_UDP_OPFLAGS_ANY_DEST_PORT
) && DestPortPtr
== NULL
)
345 DEBUG ((EFI_D_INFO
, "\nUdpRead() Exit #1 Invalid Parameter"));
346 return EFI_INVALID_PARAMETER
;
352 BufferSize
= *BufferSizeptr
;
354 // we need source and dest IPs for pseudo header
356 if (SrcIpPtr
== NULL
) {
357 SrcIpPtr
= &TmpSrcIp
;
360 if (DestIpPtr
== NULL
) {
361 DestIpPtr
= &TmpDestIp
;
362 CopyMem (&TmpDestIp
, &Private
->EfiBc
.Mode
->StationIp
, sizeof (TmpDestIp
));
366 if (Private
->EfiBc
.Mode
->UsingIpv6
) {
374 *BufferSizeptr
= BufferSize
;
376 StatCode
= IpReceive (
383 HeaderSize
+ sizeof Hdrs
.Udpv4Header
,
389 if (StatCode
== EFI_SUCCESS
|| StatCode
== EFI_BUFFER_TOO_SMALL
) {
393 SPort
= NTOHS (Hdrs
.Udpv4Header
.SrcPort
);
394 DPort
= NTOHS (Hdrs
.Udpv4Header
.DestPort
);
399 if (!(OpFlags
& EFI_PXE_BASE_CODE_UDP_OPFLAGS_ANY_SRC_PORT
) && *SrcPortPtr
!= SPort
) {
403 if (!(OpFlags
& EFI_PXE_BASE_CODE_UDP_OPFLAGS_ANY_DEST_PORT
) && *DestPortPtr
!= DPort
) {
409 if (StatCode
== EFI_SUCCESS
&& Hdrs
.Udpv4Header
.Checksum
) {
410 Hdrs
.Udpv4PseudoHeader
.SrcAddr
.L
= SrcIpPtr
->Addr
[0];
411 Hdrs
.Udpv4PseudoHeader
.DestAddr
.L
= DestIpPtr
->Addr
[0];
412 Hdrs
.Udpv4PseudoHeader
.Zero
= 0;
413 Hdrs
.Udpv4PseudoHeader
.Protocol
= PROT_UDP
;
414 Hdrs
.Udpv4PseudoHeader
.TotalLength
= Hdrs
.Udpv4Header
.TotalLength
;
416 if (Hdrs
.Udpv4Header
.Checksum
== 0xffff) {
417 Hdrs
.Udpv4Header
.Checksum
= 0;
421 (UINT16
*) &Hdrs
.Udpv4PseudoHeader
,
422 HeaderSize
+ sizeof (Hdrs
.Udpv4PseudoHeader
) + sizeof (Hdrs
.Udpv4Header
),
423 (UINT16
*) BufferPtr
,
428 "\nUdpRead() Hdrs.Udpv4PseudoHeader == %Xh",
429 &Hdrs
.Udpv4PseudoHeader
)
433 "\nUdpRead() Header size == %d",
434 HeaderSize
+ sizeof (Hdrs
.Udpv4PseudoHeader
))
438 "\nUdpRead() BufferPtr == %Xh",
443 "\nUdpRead() Buffer size == %d",
446 DEBUG ((EFI_D_INFO
, "\nUdpRead() Exit #2 Device Error"));
447 return EFI_DEVICE_ERROR
;
453 if (SrcPortPtr
!= NULL
) {
457 if (DestPortPtr
!= NULL
) {
458 *DestPortPtr
= DPort
;
461 if (HeaderSize
!= 0) {
462 CopyMem (HeaderPtr
, Hdrs
.ProtHdr
, HeaderSize
);
474 "\nUdpRead() Exit #3 %Xh %r",
484 // //////////////////////////////////////////////////////////
486 // BC Udp Read Routine
491 IN EFI_PXE_BASE_CODE_PROTOCOL
*This
,
493 IN OUT EFI_IP_ADDRESS
*DestIp
, OPTIONAL
494 IN OUT EFI_PXE_BASE_CODE_UDP_PORT
*DestPort
, OPTIONAL
495 IN OUT EFI_IP_ADDRESS
*SrcIp
, OPTIONAL
496 IN OUT EFI_PXE_BASE_CODE_UDP_PORT
*SrcPort
, OPTIONAL
497 IN UINTN
*HeaderSize
, OPTIONAL
498 IN VOID
*HeaderPtr
, OPTIONAL
499 IN OUT UINTN
*BufferSize
,
504 UDP read API entry point.
507 This := Pointer to PxeBc interface.
524 PXE_BASECODE_DEVICE
*Private
;
527 // Lock the instance data and make sure started
529 StatCode
= EFI_SUCCESS
;
532 DEBUG ((EFI_D_ERROR
, "BC *This pointer == NULL"));
533 return EFI_INVALID_PARAMETER
;
536 Private
= CR (This
, PXE_BASECODE_DEVICE
, EfiBc
, PXE_BASECODE_DEVICE_SIGNATURE
);
538 if (Private
== NULL
) {
539 DEBUG ((EFI_D_ERROR
, "PXE_BASECODE_DEVICE poiner == NULL"));
540 return EFI_INVALID_PARAMETER
;
543 EfiAcquireLock (&Private
->Lock
);
545 if (This
->Mode
== NULL
|| !This
->Mode
->Started
) {
546 DEBUG ((EFI_D_ERROR
, "BC was not started."));
547 EfiReleaseLock (&Private
->Lock
);
548 return EFI_NOT_STARTED
;
551 Private
->Function
= EFI_PXE_BASE_CODE_FUNCTION_UDP_READ
;
571 // Unlock the instance data and return
573 EfiReleaseLock (&Private
->Lock
);
577 /* eof - pxe_bc_udp.c */