/** @file\r
Interface routines for PxeBc.\r
\r
-Copyright (c) 2007 - 2010, Intel Corporation. All rights reserved.<BR>\r
+Copyright (c) 2007 - 2011, Intel Corporation. All rights reserved.<BR>\r
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
return Status;\r
}\r
\r
+\r
//\r
// Configure block size for TFTP as a default value to handle all link layers.\r
// \r
Private->BlockSize = (UINTN) (MIN (Private->Ip4MaxPacketSize, PXEBC_DEFAULT_PACKET_SIZE) - \r
PXEBC_DEFAULT_UDP_OVERHEAD_SIZE - PXEBC_DEFAULT_TFTP_OVERHEAD_SIZE);\r
+ //\r
+ // If PcdTftpBlockSize is set to non-zero, override the default value.\r
+ //\r
+ if (PcdGet64 (PcdTftpBlockSize) != 0) {\r
+ Private->BlockSize = (UINTN) PcdGet64 (PcdTftpBlockSize);\r
+ }\r
+ \r
Private->AddressIsOk = FALSE;\r
\r
ZeroMem (Mode, sizeof (EFI_PXE_BASE_CODE_MODE));\r
IN BOOLEAN SortOffers\r
)\r
{\r
- PXEBC_PRIVATE_DATA *Private;\r
- EFI_PXE_BASE_CODE_MODE *Mode;\r
- EFI_DHCP4_PROTOCOL *Dhcp4;\r
- EFI_DHCP4_CONFIG_DATA Dhcp4CfgData;\r
- EFI_DHCP4_MODE_DATA Dhcp4Mode;\r
- EFI_DHCP4_PACKET_OPTION *OptList[PXEBC_DHCP4_MAX_OPTION_NUM];\r
- UINT32 OptCount;\r
- EFI_STATUS Status;\r
- EFI_ARP_CONFIG_DATA ArpConfigData;\r
+ PXEBC_PRIVATE_DATA *Private;\r
+ EFI_PXE_BASE_CODE_MODE *Mode;\r
+ EFI_DHCP4_PROTOCOL *Dhcp4;\r
+ EFI_DHCP4_CONFIG_DATA Dhcp4CfgData;\r
+ EFI_DHCP4_MODE_DATA Dhcp4Mode;\r
+ EFI_DHCP4_PACKET_OPTION *OptList[PXEBC_DHCP4_MAX_OPTION_NUM];\r
+ UINT32 OptCount;\r
+ EFI_STATUS Status;\r
+ EFI_ARP_CONFIG_DATA ArpConfigData;\r
+ EFI_PXE_BASE_CODE_IP_FILTER IpFilter;\r
\r
if (This == NULL) {\r
return EFI_INVALID_PARAMETER;\r
\r
Mode->IcmpErrorReceived = FALSE;\r
\r
+ //\r
+ // Stop Udp4Read instance\r
+ //\r
+ Private->Udp4Read->Configure (Private->Udp4Read, NULL);\r
+\r
//\r
// Initialize the DHCP options and build the option list\r
//\r
ZeroMem (&ArpConfigData, sizeof (EFI_ARP_CONFIG_DATA));\r
\r
ArpConfigData.SwAddressType = 0x0800;\r
- ArpConfigData.SwAddressLength = sizeof (EFI_IPv4_ADDRESS);\r
+ ArpConfigData.SwAddressLength = (UINT8) sizeof (EFI_IPv4_ADDRESS);\r
ArpConfigData.StationAddress = &Private->StationIp.v4;\r
\r
Private->Arp->Configure (Private->Arp, NULL);\r
Mode->RouteTable[1].SubnetMask.Addr[0] = 0;\r
Mode->RouteTable[1].GwAddr.Addr[0] = Private->GatewayIp.Addr[0];\r
}\r
+\r
+ //\r
+ // Flush new station IP address into Udp4CfgData and Ip4ConfigData\r
+ //\r
+ CopyMem (&Private->Udp4CfgData.StationAddress, &Private->StationIp, sizeof (EFI_IPv4_ADDRESS));\r
+ CopyMem (&Private->Udp4CfgData.SubnetMask, &Private->SubnetMask, sizeof (EFI_IPv4_ADDRESS));\r
+ CopyMem (&Private->Ip4ConfigData.StationAddress, &Private->StationIp, sizeof (EFI_IPv4_ADDRESS));\r
+ CopyMem (&Private->Ip4ConfigData.SubnetMask, &Private->SubnetMask, sizeof (EFI_IPv4_ADDRESS));\r
+ \r
+ //\r
+ // Reconfigure the Ip4 instance to capture background ICMP packets with new station Ip address.\r
+ //\r
+ Private->Ip4->Cancel (Private->Ip4, &Private->IcmpErrorRcvToken);\r
+ Private->Ip4->Configure (Private->Ip4, NULL);\r
+ \r
+ Status = Private->Ip4->Configure (Private->Ip4, &Private->Ip4ConfigData);\r
+ if (EFI_ERROR (Status)) {\r
+ goto ON_EXIT;\r
+ }\r
+ \r
+ Status = Private->Ip4->Receive (Private->Ip4, &Private->IcmpErrorRcvToken);\r
+ if (EFI_ERROR (Status)) {\r
+ goto ON_EXIT;\r
+ } \r
}\r
}\r
\r
+ Status = Private->Udp4Read->Configure (Private->Udp4Read, &Private->Udp4CfgData);\r
+\r
+ //\r
+ // Dhcp(), Discover(), and Mtftp() set the IP filter, and return with the IP \r
+ // receive filter list emptied and the filter set to EFI_PXE_BASE_CODE_IP_FILTER_STATION_IP.\r
+ //\r
+ ZeroMem(&IpFilter, sizeof (EFI_PXE_BASE_CODE_IP_FILTER));\r
+ IpFilter.Filters = EFI_PXE_BASE_CODE_IP_FILTER_STATION_IP;\r
+ This->SetIpFilter (This, &IpFilter);\r
+ \r
return Status;\r
}\r
\r
UINT16 Index;\r
EFI_STATUS Status;\r
PXEBC_BOOT_SVR_ENTRY *BootSvrEntry;\r
+ EFI_PXE_BASE_CODE_IP_FILTER IpFilter;\r
\r
if (This == NULL) {\r
return EFI_INVALID_PARAMETER;\r
return EFI_NOT_STARTED;\r
}\r
\r
+ //\r
+ // Stop Udp4Read instance\r
+ //\r
+ Private->Udp4Read->Configure (Private->Udp4Read, NULL);\r
+\r
Mode->IcmpErrorReceived = FALSE;\r
\r
//\r
\r
if (!Mode->PxeDiscoverValid || !Mode->PxeReplyReceived || (!Mode->PxeBisReplyReceived && UseBis)) {\r
\r
- return EFI_INVALID_PARAMETER;\r
+ Status = EFI_INVALID_PARAMETER;\r
+ goto ON_EXIT; \r
}\r
\r
DefaultInfo.IpCnt = 1;\r
//\r
// Address is not acquired or no discovery options.\r
//\r
- return EFI_INVALID_PARAMETER;\r
+ Status = EFI_INVALID_PARAMETER;\r
+ goto ON_EXIT; \r
}\r
\r
DefaultInfo.UseMCast = (BOOLEAN)!IS_DISABLE_MCAST_DISCOVER (VendorOpt->DiscoverCtrl);\r
}\r
\r
if (EFI_ERROR (Status)) {\r
- return Status;\r
+ goto ON_EXIT;\r
}\r
\r
DefaultInfo.IpCnt = BootSvrEntry->IpCnt;\r
if (DefaultInfo.IpCnt >= 1) {\r
CreatedInfo = AllocatePool (sizeof (DefaultInfo) + (DefaultInfo.IpCnt - 1) * sizeof (*SrvList));\r
if (CreatedInfo == NULL) {\r
- return EFI_OUT_OF_RESOURCES;\r
+ Status = EFI_OUT_OF_RESOURCES;\r
+ goto ON_EXIT;\r
+ \r
} \r
\r
CopyMem (CreatedInfo, &DefaultInfo, sizeof (DefaultInfo));\r
}\r
\r
if (Index != Info->IpCnt) {\r
- return EFI_INVALID_PARAMETER;\r
+ Status = EFI_INVALID_PARAMETER;\r
+ goto ON_EXIT; \r
}\r
}\r
}\r
\r
if ((!Info->UseUCast && !Info->UseBCast && !Info->UseMCast) || (Info->MustUseList && Info->IpCnt == 0)) {\r
\r
- return EFI_INVALID_PARAMETER;\r
+ Status = EFI_INVALID_PARAMETER;\r
+ goto ON_EXIT;\r
}\r
//\r
// Execute discover by UniCast/BroadCast/MultiCast\r
} else {\r
Status = EFI_DEVICE_ERROR;\r
}\r
+ return Status;\r
} else {\r
PxeBcParseCachedDhcpPacket (&Private->PxeReply);\r
}\r
if (CreatedInfo != NULL) {\r
FreePool (CreatedInfo);\r
}\r
+\r
+ON_EXIT:\r
+\r
+ Status = Private->Udp4Read->Configure (Private->Udp4Read, &Private->Udp4CfgData);\r
+ \r
+ //\r
+ // Dhcp(), Discover(), and Mtftp() set the IP filter, and return with the IP \r
+ // receive filter list emptied and the filter set to EFI_PXE_BASE_CODE_IP_FILTER_STATION_IP.\r
+ //\r
+ ZeroMem(&IpFilter, sizeof (EFI_PXE_BASE_CODE_IP_FILTER));\r
+ IpFilter.Filters = EFI_PXE_BASE_CODE_IP_FILTER_STATION_IP;\r
+ This->SetIpFilter (This, &IpFilter);\r
\r
return Status;\r
}\r
IN BOOLEAN DontUseBuffer\r
)\r
{\r
- PXEBC_PRIVATE_DATA *Private;\r
- EFI_MTFTP4_CONFIG_DATA Mtftp4Config;\r
- EFI_STATUS Status;\r
- EFI_PXE_BASE_CODE_MODE *Mode;\r
- EFI_MAC_ADDRESS TempMacAddr;\r
+ PXEBC_PRIVATE_DATA *Private;\r
+ EFI_MTFTP4_CONFIG_DATA Mtftp4Config;\r
+ EFI_STATUS Status;\r
+ EFI_PXE_BASE_CODE_MODE *Mode;\r
+ EFI_MAC_ADDRESS TempMacAddr;\r
+ EFI_PXE_BASE_CODE_IP_FILTER IpFilter;\r
\r
if ((This == NULL) ||\r
(Filename == NULL) ||\r
}\r
}\r
\r
+ //\r
+ // Stop Udp4Read instance\r
+ //\r
+ Private->Udp4Read->Configure (Private->Udp4Read, NULL);\r
+\r
Mode->TftpErrorReceived = FALSE;\r
Mode->IcmpErrorReceived = FALSE;\r
\r
Mode->IcmpErrorReceived = TRUE;\r
}\r
\r
+ if (EFI_ERROR (Status)) {\r
+ return Status;\r
+ }\r
+\r
+ Status = Private->Udp4Read->Configure (Private->Udp4Read, &Private->Udp4CfgData);\r
+ //\r
+ // Dhcp(), Discover(), and Mtftp() set the IP filter, and return with the IP \r
+ // receive filter list emptied and the filter set to EFI_PXE_BASE_CODE_IP_FILTER_STATION_IP.\r
+ //\r
+ ZeroMem(&IpFilter, sizeof (EFI_PXE_BASE_CODE_IP_FILTER));\r
+ IpFilter.Filters = EFI_PXE_BASE_CODE_IP_FILTER_STATION_IP;\r
+ This->SetIpFilter (This, &IpFilter);\r
+\r
return Status;\r
}\r
\r
if (SrcPort != NULL) {\r
Private->CurrentUdpSrcPort = *SrcPort;\r
}\r
-\r
- Status = PxeBcConfigureUdpWriteInstance (\r
- Udp4,\r
- &Private->StationIp.v4,\r
- &Private->SubnetMask.v4,\r
- &Private->GatewayIp.v4,\r
- &Private->CurrentUdpSrcPort\r
- );\r
- if (EFI_ERROR (Status)) {\r
- Private->CurrentUdpSrcPort = 0;\r
- return EFI_INVALID_PARAMETER;\r
- }\r
}\r
\r
+ Status = PxeBcConfigureUdpWriteInstance (\r
+ Udp4,\r
+ &Private->StationIp.v4,\r
+ &Private->SubnetMask.v4,\r
+ &Private->GatewayIp.v4,\r
+ &Private->CurrentUdpSrcPort\r
+ );\r
+ if (EFI_ERROR (Status)) {\r
+ Private->CurrentUdpSrcPort = 0;\r
+ return EFI_INVALID_PARAMETER;\r
+ }\r
+ \r
ZeroMem (&Token, sizeof (EFI_UDP4_COMPLETION_TOKEN));\r
ZeroMem (&Udp4Session, sizeof (EFI_UDP4_SESSION_DATA));\r
\r
\r
FreePool (Udp4TxData);\r
\r
+ //\r
+ // Reset the instance.\r
+ //\r
+ Udp4->Configure (Udp4, NULL);\r
return Status;\r
}\r
\r
EFI_STATUS Status;\r
BOOLEAN IsDone;\r
BOOLEAN Matched;\r
- UINTN CopyLen;\r
+ UINTN CopiedLen;\r
+ UINTN HeaderLen;\r
+ UINTN HeaderCopiedLen;\r
+ UINTN BufferCopiedLen;\r
+ UINT32 FragmentLength;\r
+ UINTN FragmentIndex;\r
+ UINT8 *FragmentBuffer;\r
\r
if (This == NULL || DestIp == NULL || DestPort == NULL) {\r
return EFI_INVALID_PARAMETER;\r
}\r
\r
if (Matched) {\r
+ ASSERT (RxData != NULL);\r
\r
- CopyLen = 0;\r
-\r
+ HeaderLen = 0;\r
if (HeaderSize != NULL) {\r
- CopyLen = MIN (*HeaderSize, RxData->DataLength);\r
- CopyMem (HeaderPtr, RxData->FragmentTable[0].FragmentBuffer, CopyLen);\r
- *HeaderSize = CopyLen;\r
+ HeaderLen = MIN (*HeaderSize, RxData->DataLength);\r
}\r
\r
- if (RxData->DataLength - CopyLen > *BufferSize) {\r
-\r
+ if (RxData->DataLength - HeaderLen > *BufferSize) {\r
Status = EFI_BUFFER_TOO_SMALL;\r
} else {\r
-\r
- *BufferSize = RxData->DataLength - CopyLen;\r
- CopyMem (\r
- BufferPtr,\r
- (UINT8 *) RxData->FragmentTable[0].FragmentBuffer + CopyLen,\r
- *BufferSize\r
- );\r
+ *HeaderSize = HeaderLen;\r
+ *BufferSize = RxData->DataLength - HeaderLen;\r
+\r
+ HeaderCopiedLen = 0;\r
+ BufferCopiedLen = 0;\r
+ for (FragmentIndex = 0; FragmentIndex < RxData->FragmentCount; FragmentIndex++) {\r
+ FragmentLength = RxData->FragmentTable[FragmentIndex].FragmentLength;\r
+ FragmentBuffer = RxData->FragmentTable[FragmentIndex].FragmentBuffer;\r
+ if (HeaderCopiedLen + FragmentLength < HeaderLen) {\r
+ //\r
+ // Copy the header part of received data.\r
+ //\r
+ CopyMem ((UINT8 *) HeaderPtr + HeaderCopiedLen, FragmentBuffer, FragmentLength);\r
+ HeaderCopiedLen += FragmentLength;\r
+ } else if (HeaderCopiedLen < HeaderLen) {\r
+ //\r
+ // Copy the header part of received data.\r
+ //\r
+ CopiedLen = HeaderLen - HeaderCopiedLen;\r
+ CopyMem ((UINT8 *) HeaderPtr + HeaderCopiedLen, FragmentBuffer, CopiedLen);\r
+ HeaderCopiedLen += CopiedLen;\r
+\r
+ //\r
+ // Copy the other part of received data.\r
+ //\r
+ CopyMem ((UINT8 *) BufferPtr + BufferCopiedLen, FragmentBuffer + CopiedLen, FragmentLength - CopiedLen);\r
+ BufferCopiedLen += (FragmentLength - CopiedLen);\r
+ } else {\r
+ //\r
+ // Copy the other part of received data.\r
+ //\r
+ CopyMem ((UINT8 *) BufferPtr + BufferCopiedLen, FragmentBuffer, FragmentLength);\r
+ BufferCopiedLen += FragmentLength;\r
+ }\r
+ }\r
}\r
} else {\r
\r
PXEBC_PRIVATE_DATA *Private;\r
EFI_PXE_BASE_CODE_MODE *Mode;\r
UINTN Index;\r
+ EFI_UDP4_CONFIG_DATA *Udp4Cfg;\r
BOOLEAN PromiscuousNeed;\r
+ BOOLEAN AcceptPromiscuous;\r
+ BOOLEAN AcceptBroadcast;\r
+ BOOLEAN MultiCastUpdate;\r
\r
if (This == NULL) {\r
DEBUG ((EFI_D_ERROR, "This == NULL.\n"));\r
return EFI_NOT_STARTED;\r
}\r
\r
+ if (Mode->UsingIpv6) {\r
+ DEBUG ((EFI_D_ERROR, "This driver is PXE for IPv4 Only.\n"));\r
+ return EFI_INVALID_PARAMETER;\r
+ }\r
+\r
PromiscuousNeed = FALSE;\r
\r
for (Index = 0; Index < NewFilter->IpCnt; ++Index) {\r
}\r
}\r
\r
- //\r
- // Clear the UDP instance configuration, all joined groups will be left\r
- // during the operation.\r
- //\r
- Private->Udp4Read->Configure (Private->Udp4Read, NULL);\r
- Private->Udp4CfgData.AcceptPromiscuous = FALSE;\r
- Private->Udp4CfgData.AcceptBroadcast = FALSE;\r
+ AcceptPromiscuous = FALSE;\r
+ AcceptBroadcast = FALSE;\r
+ MultiCastUpdate = FALSE;\r
\r
if (PromiscuousNeed ||\r
((NewFilter->Filters & EFI_PXE_BASE_CODE_IP_FILTER_PROMISCUOUS) != 0) ||\r
((NewFilter->Filters & EFI_PXE_BASE_CODE_IP_FILTER_PROMISCUOUS_MULTICAST) != 0)\r
) {\r
//\r
- // Configure the udp4 filter to receive all packages\r
+ // Configure the udp4 filter to receive all packages.\r
//\r
- Private->Udp4CfgData.AcceptPromiscuous = TRUE;\r
-\r
+ AcceptPromiscuous = TRUE;\r
+ } else if ((NewFilter->Filters & EFI_PXE_BASE_CODE_IP_FILTER_BROADCAST) != 0) {\r
//\r
- // Configure the UDP instance with the new configuration.\r
+ // Configure the udp4 filter to receive all broadcast packages.\r
//\r
- Status = Private->Udp4Read->Configure (Private->Udp4Read, &Private->Udp4CfgData);\r
- if (EFI_ERROR (Status)) {\r
- return Status;\r
- }\r
-\r
- } else {\r
+ AcceptBroadcast = TRUE;\r
+ }\r
\r
- if ((NewFilter->Filters & EFI_PXE_BASE_CODE_IP_FILTER_BROADCAST) != 0) {\r
- //\r
- // Configure the udp4 filter to receive all broadcast packages\r
- //\r
- Private->Udp4CfgData.AcceptBroadcast = TRUE;\r
+ //\r
+ // In multicast condition when Promiscuous FALSE and IpCnt no-zero.\r
+ // Here check if there is any update of the multicast ip address. If yes,\r
+ // we need leave the old multicast group (by Config UDP instance to NULL),\r
+ // and join the new multicast group.\r
+ //\r
+ if (!AcceptPromiscuous) {\r
+ if ((NewFilter->Filters & EFI_PXE_BASE_CODE_IP_FILTER_STATION_IP) != 0) {\r
+ if (Mode->IpFilter.IpCnt != NewFilter->IpCnt) {\r
+ MultiCastUpdate = TRUE;\r
+ } else if (CompareMem (Mode->IpFilter.IpList, NewFilter->IpList, NewFilter->IpCnt * sizeof (EFI_IP_ADDRESS)) != 0 ) {\r
+ MultiCastUpdate = TRUE;\r
+ }\r
}\r
+ }\r
+ \r
+ //\r
+ // Check whether we need reconfigure the UDP instance.\r
+ //\r
+ Udp4Cfg = &Private->Udp4CfgData;\r
+ if ((AcceptPromiscuous != Udp4Cfg->AcceptPromiscuous) ||\r
+ (AcceptBroadcast != Udp4Cfg->AcceptBroadcast) || MultiCastUpdate) {\r
+ //\r
+ // Clear the UDP instance configuration, all joined groups will be left\r
+ // during the operation.\r
+ //\r
+ Private->Udp4Read->Configure (Private->Udp4Read, NULL);\r
\r
//\r
// Configure the UDP instance with the new configuration.\r
//\r
- Status = Private->Udp4Read->Configure (Private->Udp4Read, &Private->Udp4CfgData);\r
+ Udp4Cfg->AcceptPromiscuous = AcceptPromiscuous;\r
+ Udp4Cfg->AcceptBroadcast = AcceptBroadcast;\r
+ Status = Private->Udp4Read->Configure (Private->Udp4Read, Udp4Cfg);\r
if (EFI_ERROR (Status)) {\r
return Status;\r
}\r
\r
- if ((NewFilter->Filters & EFI_PXE_BASE_CODE_IP_FILTER_STATION_IP) != 0) {\r
-\r
+ //\r
+ // In not Promiscuous mode, need to join the new multicast group.\r
+ //\r
+ if (!AcceptPromiscuous) {\r
for (Index = 0; Index < NewFilter->IpCnt; ++Index) {\r
if (IP4_IS_MULTICAST (EFI_NTOHL (NewFilter->IpList[Index].v4))) {\r
//\r
- // Join the mutilcast group\r
+ // Join the mutilcast group.\r
//\r
Status = Private->Udp4Read->Groups (Private->Udp4Read, TRUE, &NewFilter->IpList[Index].v4);\r
if (EFI_ERROR (Status)) {\r
ZeroMem (&ArpConfigData, sizeof (EFI_ARP_CONFIG_DATA));\r
\r
ArpConfigData.SwAddressType = 0x0800;\r
- ArpConfigData.SwAddressLength = sizeof (EFI_IPv4_ADDRESS);\r
+ ArpConfigData.SwAddressLength = (UINT8) sizeof (EFI_IPv4_ADDRESS);\r
ArpConfigData.StationAddress = &Private->StationIp.v4;\r
\r
Private->Arp->Configure (Private->Arp, NULL);\r