X-Git-Url: https://git.proxmox.com/?p=mirror_edk2.git;a=blobdiff_plain;f=NetworkPkg%2FUefiPxeBcDxe%2FPxeBcSupport.c;h=8eb1558d30a963301652f95b798186980d53d737;hp=f918d6a29893e1fc24e0e566bde06f86820e852c;hb=5add2c557773a1e07245926e4768c5d69f666213;hpb=f43b7a54120e4fdff62d149f78c244148c20d7a8 diff --git a/NetworkPkg/UefiPxeBcDxe/PxeBcSupport.c b/NetworkPkg/UefiPxeBcDxe/PxeBcSupport.c index f918d6a298..8eb1558d30 100644 --- a/NetworkPkg/UefiPxeBcDxe/PxeBcSupport.c +++ b/NetworkPkg/UefiPxeBcDxe/PxeBcSupport.c @@ -1,15 +1,9 @@ /** @file Support functions implementation for UefiPxeBc Driver. - Copyright (c) 2007 - 2011, Intel Corporation. All rights reserved.
+ Copyright (c) 2007 - 2018, Intel Corporation. All rights reserved.
- This program and the accompanying materials - are licensed and made available under the terms and conditions of the BSD License - which accompanies this distribution. The full text of the license may be found at - http://opensource.org/licenses/bsd-license.php. - - THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, - WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + SPDX-License-Identifier: BSD-2-Clause-Patent **/ @@ -17,7 +11,7 @@ /** - Flush the previous configration using the new station Ip address. + Flush the previous configuration using the new station Ip address. @param[in] Private The pointer to the PxeBc private data. @param[in] StationIp The pointer to the station Ip address. @@ -28,22 +22,24 @@ **/ EFI_STATUS -PxeBcFlushStaionIp ( +PxeBcFlushStationIp ( PXEBC_PRIVATE_DATA *Private, - EFI_IP_ADDRESS *StationIp, + EFI_IP_ADDRESS *StationIp, OPTIONAL EFI_IP_ADDRESS *SubnetMask OPTIONAL ) { EFI_PXE_BASE_CODE_MODE *Mode; EFI_STATUS Status; - - ASSERT (StationIp != NULL); + EFI_ARP_CONFIG_DATA ArpConfigData; Mode = Private->PxeBc.Mode; Status = EFI_SUCCESS; + ZeroMem (&ArpConfigData, sizeof (EFI_ARP_CONFIG_DATA)); - if (Mode->UsingIpv6) { - + if (Mode->UsingIpv6 && StationIp != NULL) { + // + // Overwrite Udp6CfgData/Ip6CfgData StationAddress. + // CopyMem (&Private->Udp6CfgData.StationAddress, StationIp, sizeof (EFI_IPv6_ADDRESS)); CopyMem (&Private->Ip6CfgData.StationAddress, StationIp, sizeof (EFI_IPv6_ADDRESS)); @@ -59,33 +55,57 @@ PxeBcFlushStaionIp ( } Status = Private->Ip6->Receive (Private->Ip6, &Private->Icmp6Token); - if (EFI_ERROR (Status)) { - goto ON_EXIT; - } - } else { - ASSERT (SubnetMask != NULL); - CopyMem (&Private->Udp4CfgData.StationAddress, StationIp, sizeof (EFI_IPv4_ADDRESS)); - CopyMem (&Private->Udp4CfgData.SubnetMask, SubnetMask, sizeof (EFI_IPv4_ADDRESS)); - CopyMem (&Private->Ip4CfgData.StationAddress, StationIp, sizeof (EFI_IPv4_ADDRESS)); - CopyMem (&Private->Ip4CfgData.SubnetMask, SubnetMask, sizeof (EFI_IPv4_ADDRESS)); + if (StationIp != NULL) { + // + // Reconfigure the ARP instance with station Ip address. + // + ArpConfigData.SwAddressType = 0x0800; + ArpConfigData.SwAddressLength = (UINT8) sizeof (EFI_IPv4_ADDRESS); + ArpConfigData.StationAddress = StationIp; - // - // Reconfigure the Ip4 instance to capture background ICMP packets with new station Ip address. - // - Private->Ip4->Cancel (Private->Ip4, &Private->IcmpToken); - Private->Ip4->Configure (Private->Ip4, NULL); + Private->Arp->Configure (Private->Arp, NULL); + Private->Arp->Configure (Private->Arp, &ArpConfigData); - Status = Private->Ip4->Configure (Private->Ip4, &Private->Ip4CfgData); - if (EFI_ERROR (Status)) { - goto ON_EXIT; + // + // Overwrite Udp4CfgData/Ip4CfgData StationAddress. + // + CopyMem (&Private->Udp4CfgData.StationAddress, StationIp, sizeof (EFI_IPv4_ADDRESS)); + CopyMem (&Private->Ip4CfgData.StationAddress, StationIp, sizeof (EFI_IPv4_ADDRESS)); } - Status = Private->Ip4->Receive (Private->Ip4, &Private->IcmpToken); - if (EFI_ERROR (Status)) { - goto ON_EXIT; + if (SubnetMask != NULL) { + // + // Overwrite Udp4CfgData/Ip4CfgData SubnetMask. + // + CopyMem (&Private->Udp4CfgData.SubnetMask, SubnetMask, sizeof (EFI_IPv4_ADDRESS)); + CopyMem (&Private->Ip4CfgData.SubnetMask, SubnetMask, sizeof (EFI_IPv4_ADDRESS)); } + if (StationIp != NULL && SubnetMask != NULL) { + // + // Updated the route table. + // + Mode->RouteTableEntries = 1; + Mode->RouteTable[0].IpAddr.Addr[0] = StationIp->Addr[0] & SubnetMask->Addr[0]; + Mode->RouteTable[0].SubnetMask.Addr[0] = SubnetMask->Addr[0]; + Mode->RouteTable[0].GwAddr.Addr[0] = 0; + } + + if (StationIp != NULL || SubnetMask != NULL) { + // + // Reconfigure the Ip4 instance to capture background ICMP packets with new station Ip address. + // + Private->Ip4->Cancel (Private->Ip4, &Private->IcmpToken); + Private->Ip4->Configure (Private->Ip4, NULL); + + Status = Private->Ip4->Configure (Private->Ip4, &Private->Ip4CfgData); + if (EFI_ERROR (Status)) { + goto ON_EXIT; + } + + Status = Private->Ip4->Receive (Private->Ip4, &Private->IcmpToken); + } } ON_EXIT: @@ -116,7 +136,7 @@ PxeBcCommonNotify ( @param Mode The pointer to EFI_PXE_BASE_CODE_MODE. @param Ip4Addr The Ip4 address for resolution. - @param MacAddress The resoluted MAC address if the resolution is successful. + @param MacAddress The resolved MAC address if the resolution is successful. The value is undefined if the resolution fails. @retval TRUE Found an matched entry. @@ -261,34 +281,30 @@ PxeBcIcmpErrorDpcHandle ( // // The return status should be recognized as EFI_ICMP_ERROR. // - gBS->SignalEvent (RxData->RecycleSignal); - goto ON_EXIT; + goto ON_RECYCLE; } if (EFI_IP4 (RxData->Header->SourceAddress) != 0 && - !NetIp4IsUnicast (EFI_NTOHL (RxData->Header->SourceAddress), 0)) { + (NTOHL (Mode->SubnetMask.Addr[0]) != 0) && + IP4_NET_EQUAL (NTOHL(Mode->StationIp.Addr[0]), EFI_NTOHL (RxData->Header->SourceAddress), NTOHL (Mode->SubnetMask.Addr[0])) && + !NetIp4IsUnicast (EFI_NTOHL (RxData->Header->SourceAddress), NTOHL (Mode->SubnetMask.Addr[0]))) { // // The source address of the received packet should be a valid unicast address. // - gBS->SignalEvent (RxData->RecycleSignal); - goto ON_EXIT; + goto ON_RECYCLE; } if (!EFI_IP4_EQUAL (&RxData->Header->DestinationAddress, &Mode->StationIp.v4)) { // // The destination address of the received packet should be equal to the host address. // - gBS->SignalEvent (RxData->RecycleSignal); - goto ON_EXIT; + goto ON_RECYCLE; } - if (RxData->Header->Protocol != EFI_IP_PROTO_ICMP) { - // - // The protocol value in the header of the receveid packet should be EFI_IP_PROTO_ICMP. - // - gBS->SignalEvent (RxData->RecycleSignal); - goto ON_EXIT; - } + // + // The protocol has been configured to only receive ICMP packet. + // + ASSERT (RxData->Header->Protocol == EFI_IP_PROTO_ICMP); Type = *((UINT8 *) RxData->FragmentTable[0].FragmentBuffer); @@ -300,8 +316,7 @@ PxeBcIcmpErrorDpcHandle ( // // The type of the receveid ICMP message should be ICMP_ERROR_MESSAGE. // - gBS->SignalEvent (RxData->RecycleSignal); - goto ON_EXIT; + goto ON_RECYCLE; } // @@ -328,6 +343,9 @@ PxeBcIcmpErrorDpcHandle ( IcmpError += CopiedLen; } +ON_RECYCLE: + gBS->SignalEvent (RxData->RecycleSignal); + ON_EXIT: Private->IcmpToken.Status = EFI_NOT_READY; Ip4->Receive (Ip4, &Private->IcmpToken); @@ -397,16 +415,14 @@ PxeBcIcmp6ErrorDpcHandle ( // // The return status should be recognized as EFI_ICMP_ERROR. // - gBS->SignalEvent (RxData->RecycleSignal); - goto ON_EXIT; + goto ON_RECYCLE; } if (!NetIp6IsValidUnicast (&RxData->Header->SourceAddress)) { // // The source address of the received packet should be a valid unicast address. // - gBS->SignalEvent (RxData->RecycleSignal); - goto ON_EXIT; + goto ON_RECYCLE; } if (!NetIp6IsUnspecifiedAddr (&Mode->StationIp.v6) && @@ -414,29 +430,24 @@ PxeBcIcmp6ErrorDpcHandle ( // // The destination address of the received packet should be equal to the host address. // - gBS->SignalEvent (RxData->RecycleSignal); - goto ON_EXIT; + goto ON_RECYCLE; } - if (RxData->Header->NextHeader != IP6_ICMP) { - // - // The nextheader in the header of the receveid packet should be IP6_ICMP. - // - gBS->SignalEvent (RxData->RecycleSignal); - goto ON_EXIT; - } + // + // The protocol has been configured to only receive ICMP packet. + // + ASSERT (RxData->Header->NextHeader == IP6_ICMP); Type = *((UINT8 *) RxData->FragmentTable[0].FragmentBuffer); if (Type != ICMP_V6_DEST_UNREACHABLE && Type != ICMP_V6_PACKET_TOO_BIG && - Type != ICMP_V6_PACKET_TOO_BIG && + Type != ICMP_V6_TIME_EXCEEDED && Type != ICMP_V6_PARAMETER_PROBLEM) { // // The type of the receveid packet should be an ICMP6 error message. // - gBS->SignalEvent (RxData->RecycleSignal); - goto ON_EXIT; + goto ON_RECYCLE; } // @@ -463,6 +474,9 @@ PxeBcIcmp6ErrorDpcHandle ( Icmp6Error += CopiedLen; } +ON_RECYCLE: + gBS->SignalEvent (RxData->RecycleSignal); + ON_EXIT: Private->Icmp6Token.Status = EFI_NOT_READY; Ip6->Receive (Ip6, &Private->Icmp6Token); @@ -497,6 +511,8 @@ PxeBcIcmp6ErrorUpdate ( @param[in, out] SrcPort The pointer to the source port. @param[in] DoNotFragment If TRUE, fragment is not enabled. Otherwise, fragment is enabled. + @param[in] Ttl The time to live field of the IP header. + @param[in] ToS The type of service field of the IP header. @retval EFI_SUCCESS Successfully configured this instance. @retval Others Failed to configure this instance. @@ -509,7 +525,9 @@ PxeBcConfigUdp4Write ( IN EFI_IPv4_ADDRESS *SubnetMask, IN EFI_IPv4_ADDRESS *Gateway, IN OUT UINT16 *SrcPort, - IN BOOLEAN DoNotFragment + IN BOOLEAN DoNotFragment, + IN UINT8 Ttl, + IN UINT8 ToS ) { EFI_UDP4_CONFIG_DATA Udp4CfgData; @@ -519,8 +537,8 @@ PxeBcConfigUdp4Write ( Udp4CfgData.TransmitTimeout = PXEBC_DEFAULT_LIFETIME; Udp4CfgData.ReceiveTimeout = PXEBC_DEFAULT_LIFETIME; - Udp4CfgData.TypeOfService = DEFAULT_ToS; - Udp4CfgData.TimeToLive = DEFAULT_TTL; + Udp4CfgData.TypeOfService = ToS; + Udp4CfgData.TimeToLive = Ttl; Udp4CfgData.AllowDuplicatePort = TRUE; Udp4CfgData.DoNotFragment = DoNotFragment; @@ -1158,7 +1176,7 @@ PxeBcUdp4Read ( Token->Status == EFI_NOT_READY && EFI_ERROR (gBS->CheckEvent (TimeoutEvent))) { // - // Poll the token utill reply/ICMPv6 error message received or timeout. + // Poll the token until reply/ICMPv6 error message received or timeout. // Udp4->Poll (Udp4); if (Token->Status == EFI_ICMP_ERROR || @@ -1262,7 +1280,7 @@ PxeBcUdp6Read ( Token->Status == EFI_NOT_READY && EFI_ERROR (gBS->CheckEvent (TimeoutEvent))) { // - // Poll the token utill reply/ICMPv6 error message received or timeout. + // Poll the token until reply/ICMPv6 error message received or timeout. // Udp6->Poll (Udp6); if (Token->Status == EFI_ICMP_ERROR || @@ -1385,11 +1403,10 @@ PxeBcUintnToAscDecWithFormat ( { UINTN Remainder; - while (Length > 0) { - Length--; + for (; Length > 0; Length--) { Remainder = Number % 10; Number /= 10; - Buffer[Length] = (UINT8) ('0' + Remainder); + Buffer[Length - 1] = (UINT8) ('0' + Remainder); } } @@ -1400,6 +1417,7 @@ PxeBcUintnToAscDecWithFormat ( @param[in] Number Numeric value to be converted. @param[in] Buffer The pointer to the buffer for ASCII string. + @param[in] BufferSize The maxsize of the buffer. @return Length The actual length of the ASCII string. @@ -1407,7 +1425,8 @@ PxeBcUintnToAscDecWithFormat ( UINTN PxeBcUintnToAscDec ( IN UINTN Number, - IN UINT8 *Buffer + IN UINT8 *Buffer, + IN UINTN BufferSize ) { UINTN Index; @@ -1423,7 +1442,7 @@ PxeBcUintnToAscDec ( Number = (UINTN) (Number / 10); } while (Number != 0); - AsciiStrCpy ((CHAR8 *) Buffer, &TempStr[Index]); + AsciiStrCpyS ((CHAR8 *) Buffer, BufferSize, &TempStr[Index]); Length = AsciiStrLen ((CHAR8 *) Buffer); @@ -1485,14 +1504,14 @@ CalcElapsedTime ( // ZeroMem (&Time, sizeof (EFI_TIME)); gRT->GetTime (&Time, NULL); - CurrentStamp = (UINT64) - ( - ((((((Time.Year - 1900) * 360 + - (Time.Month - 1)) * 30 + - (Time.Day - 1)) * 24 + Time.Hour) * 60 + - Time.Minute) * 60 + Time.Second) * 100 - + DivU64x32(Time.Nanosecond, 10000000) - ); + CurrentStamp = MultU64x32 ( + ((((UINT32)(Time.Year - 1900) * 360 + (Time.Month - 1) * 30 + (Time.Day - 1)) * 24 + Time.Hour) * 60 + Time.Minute) * 60 + Time.Second, + 100 + ) + + DivU64x32 ( + Time.Nanosecond, + 10000000 + ); // // Sentinel value of 0 means that this is the first DHCP packet that we are