+++ /dev/null
-/*++\r
-\r
-Copyright (c) 2006 - 2007, Intel Corporation\r
-All rights reserved. This program and the accompanying materials\r
-are licensed and made available under the terms and conditions of the BSD License\r
-which accompanies this distribution. The full text of the license may be found at\r
-http://opensource.org/licenses/bsd-license.php\r
-\r
-THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
-WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
-\r
-Module Name:\r
- pxe_bc_udp.c\r
-\r
-Abstract:\r
-\r
---*/\r
-\r
-\r
-#include "Bc.h"\r
-\r
-//\r
-// //////////////////////////////////////////////////////////////////////\r
-//\r
-// Udp Write Routine - called by base code - e.g. TFTP - already locked\r
-//\r
-EFI_STATUS\r
-UdpWrite (\r
- IN PXE_BASECODE_DEVICE *Private,\r
- IN UINT16 OpFlags,\r
- IN EFI_IP_ADDRESS *DestIpPtr,\r
- IN EFI_PXE_BASE_CODE_UDP_PORT *DestPortPtr,\r
- IN EFI_IP_ADDRESS *GatewayIpPtr, OPTIONAL\r
- IN EFI_IP_ADDRESS *SrcIpPtr, OPTIONAL\r
- IN OUT EFI_PXE_BASE_CODE_UDP_PORT *SrcPortPtr, OPTIONAL\r
- IN UINTN *HeaderSizePtr, OPTIONAL\r
- IN VOID *HeaderPtr, OPTIONAL\r
- IN UINTN *BufferSizeptr,\r
- IN VOID *BufferPtr\r
- )\r
-/*++\r
-Routine description:\r
- UDP write packet.\r
-\r
-Parameters:\r
- Private := Pointer to PxeBc interface\r
- OpFlags :=\r
- DestIpPtr :=\r
- DestPortPtr :=\r
- GatewayIpPtr :=\r
- SrcIpPtr :=\r
- SrcPortPtr :=\r
- HeaderSizePtr :=\r
- HeaderPtr :=\r
- BufferSizeptr :=\r
- BufferPtr :=\r
-\r
-Returns:\r
- EFI_SUCCESS :=\r
- EFI_INVALID_PARAMETER :=\r
- other :=\r
---*/\r
-{\r
- UINTN TotalLength;\r
- UINTN HeaderSize;\r
- EFI_PXE_BASE_CODE_UDP_PORT DefaultSrcPort;\r
-\r
- //\r
- //\r
- //\r
- HeaderSize = (HeaderSizePtr != NULL) ? *HeaderSizePtr : 0;\r
- DefaultSrcPort = 0;\r
-\r
- //\r
- // check parameters\r
- //\r
- if (BufferSizeptr == NULL ||\r
- BufferPtr == NULL ||\r
- DestIpPtr == NULL ||\r
- DestPortPtr == NULL ||\r
- (HeaderSizePtr != NULL && *HeaderSizePtr == 0) ||\r
- (HeaderSize != 0 && HeaderPtr == NULL) ||\r
- (GatewayIpPtr != NULL && !IS_INADDR_UNICAST(GatewayIpPtr)) ||\r
- (OpFlags &~(EFI_PXE_BASE_CODE_UDP_OPFLAGS_MAY_FRAGMENT | EFI_PXE_BASE_CODE_UDP_OPFLAGS_ANY_SRC_PORT))\r
- ) {\r
- DEBUG (\r
- (EFI_D_WARN,\r
- "\nUdpWrite() Exit #1 %xh (%r)",\r
- EFI_INVALID_PARAMETER,\r
- EFI_INVALID_PARAMETER)\r
- );\r
-\r
- return EFI_INVALID_PARAMETER;\r
- }\r
-\r
- TotalLength = *BufferSizeptr + HeaderSize + sizeof (UDPV4_HEADER);\r
-\r
- if (TotalLength > 0x0000ffff) {\r
- DEBUG (\r
- (EFI_D_WARN,\r
- "\nUdpWrite() Exit #2 %xh (%r)",\r
- EFI_BAD_BUFFER_SIZE,\r
- EFI_BAD_BUFFER_SIZE)\r
- );\r
-\r
- return EFI_BAD_BUFFER_SIZE;\r
- }\r
-\r
- if (SrcIpPtr == NULL) {\r
- SrcIpPtr = &Private->EfiBc.Mode->StationIp;\r
- }\r
-\r
- if (SrcPortPtr == NULL) {\r
- SrcPortPtr = &DefaultSrcPort;\r
- OpFlags |= EFI_PXE_BASE_CODE_UDP_OPFLAGS_ANY_SRC_PORT;\r
- }\r
-\r
- if (OpFlags & EFI_PXE_BASE_CODE_UDP_OPFLAGS_ANY_SRC_PORT) {\r
- *SrcPortPtr = Private->RandomPort;\r
-\r
- if (++Private->RandomPort == 0) {\r
- Private->RandomPort = PXE_RND_PORT_LOW;\r
- }\r
- }\r
-\r
-#define IpTxBuffer ((IPV4_BUFFER *) Private->TransmitBufferPtr)\r
- //\r
- // build pseudo header and udp header in transmit buffer\r
- //\r
-#define Udpv4Base ((UDPV4_HEADERS *) (IpTxBuffer->u.Data - sizeof (UDPV4_PSEUDO_HEADER)))\r
-\r
- Udpv4Base->Udpv4PseudoHeader.SrcAddr.L = SrcIpPtr->Addr[0];\r
- Udpv4Base->Udpv4PseudoHeader.DestAddr.L = DestIpPtr->Addr[0];\r
- Udpv4Base->Udpv4PseudoHeader.Zero = 0;\r
- Udpv4Base->Udpv4PseudoHeader.Protocol = PROT_UDP;\r
- Udpv4Base->Udpv4PseudoHeader.TotalLength = HTONS (TotalLength);\r
- Udpv4Base->Udpv4Header.SrcPort = HTONS (*SrcPortPtr);\r
- Udpv4Base->Udpv4Header.DestPort = HTONS (*DestPortPtr);\r
- Udpv4Base->Udpv4Header.TotalLength = Udpv4Base->Udpv4PseudoHeader.TotalLength;\r
- Udpv4Base->Udpv4Header.Checksum = 0;\r
-\r
- if (HeaderSize != 0) {\r
- CopyMem (IpTxBuffer->u.Udp.Data, HeaderPtr, HeaderSize);\r
- }\r
-\r
- HeaderSize += sizeof (UDPV4_HEADER);\r
-\r
- Udpv4Base->Udpv4Header.Checksum = IpChecksum2 (\r
- (UINT16 *) Udpv4Base,\r
- HeaderSize + sizeof (UDPV4_PSEUDO_HEADER),\r
- (UINT16 *) BufferPtr,\r
- (UINT16) *BufferSizeptr\r
- );\r
-\r
- if (Udpv4Base->Udpv4Header.Checksum == 0) {\r
- Udpv4Base->Udpv4Header.Checksum = 0xffff;\r
- //\r
- // transmit zero checksum as ones complement\r
- //\r
- }\r
-\r
- return Ip4Send (\r
- Private,\r
- OpFlags,\r
- PROT_UDP,\r
- Udpv4Base->Udpv4PseudoHeader.SrcAddr.L,\r
- Udpv4Base->Udpv4PseudoHeader.DestAddr.L,\r
- (GatewayIpPtr) ? GatewayIpPtr->Addr[0] : 0,\r
- HeaderSize,\r
- BufferPtr,\r
- *BufferSizeptr\r
- );\r
-}\r
-//\r
-// //////////////////////////////////////////////////////////\r
-//\r
-// BC Udp Write Routine\r
-//\r
-EFI_STATUS\r
-EFIAPI\r
-BcUdpWrite (\r
- IN EFI_PXE_BASE_CODE_PROTOCOL *This,\r
- IN UINT16 OpFlags,\r
- IN EFI_IP_ADDRESS *DestIpPtr,\r
- IN EFI_PXE_BASE_CODE_UDP_PORT *DestPortPtr,\r
- IN EFI_IP_ADDRESS *GatewayIpPtr, OPTIONAL\r
- IN EFI_IP_ADDRESS *SrcIpPtr, OPTIONAL\r
- IN OUT EFI_PXE_BASE_CODE_UDP_PORT *SrcPortPtr, OPTIONAL\r
- IN UINTN *HeaderSizePtr, OPTIONAL\r
- IN VOID *HeaderPtr, OPTIONAL\r
- IN UINTN *BufferSizeptr,\r
- IN VOID *BufferPtr\r
- )\r
-/*++\r
-Routine description:\r
- UDP write API entry point.\r
-\r
-Parameters:\r
- This := Pointer to PxeBc interface.\r
- OpFlags :=\r
- DestIpPtr :=\r
- DestPortPtr :=\r
- GatewayIpPtr :=\r
- SrcIpPtr :=\r
- SrcPortPtr :=\r
- HeaderSizePtr :=\r
- HeaderPtr :=\r
- BufferSizeptr :=\r
- BufferPtr :=\r
-\r
-Returns:\r
- EFI_SUCCESS :=\r
- other :=\r
---*/\r
-{\r
- EFI_STATUS StatCode;\r
- PXE_BASECODE_DEVICE *Private;\r
-\r
- //\r
- // Lock the instance data and make sure started\r
- //\r
- StatCode = EFI_SUCCESS;\r
-\r
- if (This == NULL) {\r
- DEBUG ((EFI_D_ERROR, "BC *This pointer == NULL"));\r
- return EFI_INVALID_PARAMETER;\r
- }\r
-\r
- Private = CR (This, PXE_BASECODE_DEVICE, EfiBc, PXE_BASECODE_DEVICE_SIGNATURE);\r
-\r
- if (Private == NULL) {\r
- DEBUG ((EFI_D_ERROR, "PXE_BASECODE_DEVICE poiner == NULL"));\r
- return EFI_INVALID_PARAMETER;\r
- }\r
-\r
- EfiAcquireLock (&Private->Lock);\r
-\r
- if (This->Mode == NULL || !This->Mode->Started) {\r
- DEBUG ((EFI_D_ERROR, "BC was not started."));\r
- EfiReleaseLock (&Private->Lock);\r
- return EFI_NOT_STARTED;\r
- }\r
-\r
- Private->Function = EFI_PXE_BASE_CODE_FUNCTION_UDP_WRITE;\r
-\r
- //\r
- // Issue BC command\r
- //\r
- StatCode = UdpWrite (\r
- Private,\r
- OpFlags,\r
- DestIpPtr,\r
- DestPortPtr,\r
- GatewayIpPtr,\r
- SrcIpPtr,\r
- SrcPortPtr,\r
- HeaderSizePtr,\r
- HeaderPtr,\r
- BufferSizeptr,\r
- BufferPtr\r
- );\r
-\r
- //\r
- // Unlock the instance data\r
- //\r
- EfiReleaseLock (&Private->Lock);\r
- return StatCode;\r
-}\r
-//\r
-// /////////////////////////////////////////////////////////////////////\r
-//\r
-// Udp Read Routine - called by base code - e.g. TFTP - already locked\r
-//\r
-EFI_STATUS\r
-UdpRead (\r
- IN PXE_BASECODE_DEVICE *Private,\r
- IN UINT16 OpFlags,\r
- IN OUT EFI_IP_ADDRESS *DestIpPtr, OPTIONAL\r
- IN OUT EFI_PXE_BASE_CODE_UDP_PORT *DestPortPtr, OPTIONAL\r
- IN OUT EFI_IP_ADDRESS *SrcIpPtr, OPTIONAL\r
- IN OUT EFI_PXE_BASE_CODE_UDP_PORT *SrcPortPtr, OPTIONAL\r
- IN UINTN *HeaderSizePtr, OPTIONAL\r
- IN VOID *HeaderPtr, OPTIONAL\r
- IN OUT UINTN *BufferSizeptr,\r
- IN VOID *BufferPtr,\r
- EFI_EVENT TimeoutEvent\r
- )\r
-/*++\r
-Routine description:\r
- UDP read packet.\r
-\r
-Parameters:\r
- Private := Pointer to PxeBc interface\r
- OpFlags :=\r
- DestIpPtr :=\r
- DestPortPtr :=\r
- SrcIpPtr :=\r
- SrcPortPtr :=\r
- HeaderSizePtr :=\r
- HeaderPtr :=\r
- BufferSizeptr :=\r
- BufferPtr :=\r
- TimeoutEvent :=\r
-\r
-Returns:\r
- EFI_SUCCESS :=\r
- EFI_INVALID_PARAMETER :=\r
- other :=\r
---*/\r
-{\r
- EFI_STATUS StatCode;\r
- EFI_IP_ADDRESS TmpSrcIp;\r
- EFI_IP_ADDRESS TmpDestIp;\r
- UINTN BufferSize;\r
- UINTN HeaderSize;\r
-\r
- //\r
- // combination structure of pseudo header/udp header\r
- //\r
-#pragma pack (1)\r
- struct {\r
- UDPV4_PSEUDO_HEADER Udpv4PseudoHeader;\r
- UDPV4_HEADER Udpv4Header;\r
- UINT8 ProtHdr[64];\r
- } Hdrs;\r
-#pragma pack ()\r
-\r
- HeaderSize = (HeaderSizePtr != NULL) ? *HeaderSizePtr : 0;\r
- //\r
- // read [with filtering]\r
- // check parameters\r
- //\r
- if (BufferSizeptr == NULL ||\r
- BufferPtr == NULL ||\r
- (HeaderSize != 0 && HeaderPtr == NULL) ||\r
- (OpFlags &~UDP_FILTER_MASK)\r
- //\r
- // if filtering on a particular IP/Port, need it\r
- //\r
- ||\r
- (!(OpFlags & EFI_PXE_BASE_CODE_UDP_OPFLAGS_ANY_SRC_IP) && SrcIpPtr == NULL) ||\r
- (!(OpFlags & EFI_PXE_BASE_CODE_UDP_OPFLAGS_ANY_SRC_PORT) && SrcPortPtr == NULL) ||\r
- (!(OpFlags & EFI_PXE_BASE_CODE_UDP_OPFLAGS_ANY_DEST_PORT) && DestPortPtr == NULL)\r
- ) {\r
- DEBUG ((EFI_D_INFO, "\nUdpRead() Exit #1 Invalid Parameter"));\r
- return EFI_INVALID_PARAMETER;\r
- }\r
-\r
- //\r
- // in case we loop\r
- //\r
- BufferSize = *BufferSizeptr;\r
- //\r
- // we need source and dest IPs for pseudo header\r
- //\r
- if (SrcIpPtr == NULL) {\r
- SrcIpPtr = &TmpSrcIp;\r
- }\r
-\r
- if (DestIpPtr == NULL) {\r
- DestIpPtr = &TmpDestIp;\r
- CopyMem (&TmpDestIp, &Private->EfiBc.Mode->StationIp, sizeof (TmpDestIp));\r
- }\r
-\r
- for (;;) {\r
- *BufferSizeptr = BufferSize;\r
-\r
- StatCode = IpReceive (\r
- Private,\r
- OpFlags,\r
- SrcIpPtr,\r
- DestIpPtr,\r
- PROT_UDP,\r
- &Hdrs.Udpv4Header,\r
- HeaderSize + sizeof Hdrs.Udpv4Header,\r
- BufferPtr,\r
- BufferSizeptr,\r
- TimeoutEvent\r
- );\r
-\r
- if (StatCode == EFI_SUCCESS || StatCode == EFI_BUFFER_TOO_SMALL) {\r
- UINT16 SPort;\r
- UINT16 DPort;\r
-\r
- SPort = NTOHS (Hdrs.Udpv4Header.SrcPort);\r
- DPort = NTOHS (Hdrs.Udpv4Header.DestPort);\r
-\r
- //\r
- // do filtering\r
- //\r
- if (!(OpFlags & EFI_PXE_BASE_CODE_UDP_OPFLAGS_ANY_SRC_PORT) && *SrcPortPtr != SPort) {\r
- continue;\r
- }\r
-\r
- if (!(OpFlags & EFI_PXE_BASE_CODE_UDP_OPFLAGS_ANY_DEST_PORT) && *DestPortPtr != DPort) {\r
- continue;\r
- }\r
- //\r
- // check checksum\r
- //\r
- if (StatCode == EFI_SUCCESS && Hdrs.Udpv4Header.Checksum) {\r
- Hdrs.Udpv4PseudoHeader.SrcAddr.L = SrcIpPtr->Addr[0];\r
- Hdrs.Udpv4PseudoHeader.DestAddr.L = DestIpPtr->Addr[0];\r
- Hdrs.Udpv4PseudoHeader.Zero = 0;\r
- Hdrs.Udpv4PseudoHeader.Protocol = PROT_UDP;\r
- Hdrs.Udpv4PseudoHeader.TotalLength = Hdrs.Udpv4Header.TotalLength;\r
-\r
- if (Hdrs.Udpv4Header.Checksum == 0xffff) {\r
- Hdrs.Udpv4Header.Checksum = 0;\r
- }\r
-\r
- if (IpChecksum2 (\r
- (UINT16 *) &Hdrs.Udpv4PseudoHeader,\r
- HeaderSize + sizeof (Hdrs.Udpv4PseudoHeader) + sizeof (Hdrs.Udpv4Header),\r
- (UINT16 *) BufferPtr,\r
- *BufferSizeptr\r
- )) {\r
- DEBUG (\r
- (EFI_D_INFO,\r
- "\nUdpRead() Hdrs.Udpv4PseudoHeader == %Xh",\r
- &Hdrs.Udpv4PseudoHeader)\r
- );\r
- DEBUG (\r
- (EFI_D_INFO,\r
- "\nUdpRead() Header size == %d",\r
- HeaderSize + sizeof (Hdrs.Udpv4PseudoHeader))\r
- );\r
- DEBUG (\r
- (EFI_D_INFO,\r
- "\nUdpRead() BufferPtr == %Xh",\r
- BufferPtr)\r
- );\r
- DEBUG (\r
- (EFI_D_INFO,\r
- "\nUdpRead() Buffer size == %d",\r
- *BufferSizeptr)\r
- );\r
- DEBUG ((EFI_D_INFO, "\nUdpRead() Exit #2 Device Error"));\r
- return EFI_DEVICE_ERROR;\r
- }\r
- }\r
- //\r
- // all passed\r
- //\r
- if (SrcPortPtr != NULL) {\r
- *SrcPortPtr = SPort;\r
- }\r
-\r
- if (DestPortPtr != NULL) {\r
- *DestPortPtr = DPort;\r
- }\r
-\r
- if (HeaderSize != 0) {\r
- CopyMem (HeaderPtr, Hdrs.ProtHdr, HeaderSize);\r
- }\r
- }\r
-\r
- if ((StatCode != EFI_SUCCESS) && (StatCode != EFI_TIMEOUT)) {\r
- DEBUG (\r
- (EFI_D_INFO,\r
- "\nUdpRead() Exit #3 %Xh %r",\r
- StatCode,\r
- StatCode)\r
- );\r
- }\r
-\r
- return StatCode;\r
- }\r
-}\r
-//\r
-// //////////////////////////////////////////////////////////\r
-//\r
-// BC Udp Read Routine\r
-//\r
-EFI_STATUS\r
-EFIAPI\r
-BcUdpRead (\r
- IN EFI_PXE_BASE_CODE_PROTOCOL *This,\r
- IN UINT16 OpFlags,\r
- IN OUT EFI_IP_ADDRESS *DestIp, OPTIONAL\r
- IN OUT EFI_PXE_BASE_CODE_UDP_PORT *DestPort, OPTIONAL\r
- IN OUT EFI_IP_ADDRESS *SrcIp, OPTIONAL\r
- IN OUT EFI_PXE_BASE_CODE_UDP_PORT *SrcPort, OPTIONAL\r
- IN UINTN *HeaderSize, OPTIONAL\r
- IN VOID *HeaderPtr, OPTIONAL\r
- IN OUT UINTN *BufferSize,\r
- IN VOID *BufferPtr\r
- )\r
-/*++\r
-Routine description:\r
- UDP read API entry point.\r
-\r
-Parameters:\r
- This := Pointer to PxeBc interface.\r
- OpFlags :=\r
- DestIpPtr :=\r
- DestPortPtr :=\r
- SrcIpPtr :=\r
- SrcPortPtr :=\r
- HeaderSizePtr :=\r
- HeaderPtr :=\r
- BufferSizeptr :=\r
- BufferPtr :=\r
-\r
-Returns:\r
- EFI_SUCCESS :=\r
- other :=\r
---*/\r
-{\r
- EFI_STATUS StatCode;\r
- PXE_BASECODE_DEVICE *Private;\r
-\r
- //\r
- // Lock the instance data and make sure started\r
- //\r
- StatCode = EFI_SUCCESS;\r
-\r
- if (This == NULL) {\r
- DEBUG ((EFI_D_ERROR, "BC *This pointer == NULL"));\r
- return EFI_INVALID_PARAMETER;\r
- }\r
-\r
- Private = CR (This, PXE_BASECODE_DEVICE, EfiBc, PXE_BASECODE_DEVICE_SIGNATURE);\r
-\r
- if (Private == NULL) {\r
- DEBUG ((EFI_D_ERROR, "PXE_BASECODE_DEVICE poiner == NULL"));\r
- return EFI_INVALID_PARAMETER;\r
- }\r
-\r
- EfiAcquireLock (&Private->Lock);\r
-\r
- if (This->Mode == NULL || !This->Mode->Started) {\r
- DEBUG ((EFI_D_ERROR, "BC was not started."));\r
- EfiReleaseLock (&Private->Lock);\r
- return EFI_NOT_STARTED;\r
- }\r
-\r
- Private->Function = EFI_PXE_BASE_CODE_FUNCTION_UDP_READ;\r
-\r
- //\r
- // Issue BC command\r
- //\r
- StatCode = UdpRead (\r
- Private,\r
- OpFlags,\r
- DestIp,\r
- DestPort,\r
- SrcIp,\r
- SrcPort,\r
- HeaderSize,\r
- HeaderPtr,\r
- BufferSize,\r
- BufferPtr,\r
- 0\r
- );\r
-\r
- //\r
- // Unlock the instance data and return\r
- //\r
- EfiReleaseLock (&Private->Lock);\r
- return StatCode;\r
-}\r
-\r
-/* eof - pxe_bc_udp.c */\r