X-Git-Url: https://git.proxmox.com/?a=blobdiff_plain;f=NetworkPkg%2FUefiPxeBcDxe%2FPxeBcSupport.c;h=720287583e5ff12ba8e065fbf005f8ef8cf9b436;hb=673abfb7491b4abd73bb6a770cf8cd293fbbccb4;hp=28383b32aa79c71f826144aa506fb16b198b6237;hpb=76389e18c04833a87811550ed6db06f1790aacde;p=mirror_edk2.git diff --git a/NetworkPkg/UefiPxeBcDxe/PxeBcSupport.c b/NetworkPkg/UefiPxeBcDxe/PxeBcSupport.c index 28383b32aa..720287583e 100644 --- a/NetworkPkg/UefiPxeBcDxe/PxeBcSupport.c +++ b/NetworkPkg/UefiPxeBcDxe/PxeBcSupport.c @@ -1,7 +1,7 @@ /** @file Support functions implementation for UefiPxeBc Driver. - Copyright (c) 2007 - 2011, Intel Corporation. All rights reserved.
+ Copyright (c) 2007 - 2017, 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 @@ -16,128 +16,6 @@ #include "PxeBcImpl.h" - -/** - This function returns SMBIOS string given the string number. - - @param[in] Smbios The pointer to the SMBIOS structure - @param[in] StringNumber String number to return. 0 is used to skip all - strings and point to the next SMBIOS structure. - - @return String The pointer to the next SMBIOS structure if - StringNumber == 0. - -**/ -CHAR8 * -PxeBcGetSmbiosString ( - IN SMBIOS_STRUCTURE_POINTER *Smbios, - IN UINT16 StringNumber - ) -{ - UINT16 Index; - CHAR8 *String; - - // - // Skip over formatted section. - // - String = (CHAR8 *) (Smbios->Raw + Smbios->Hdr->Length); - - // - // Look through unformated section. - // - for (Index = 1; Index <= StringNumber || StringNumber == 0; Index++) { - if (StringNumber == Index) { - return String; - } - - // - // Skip zero string. - // - while (*String != 0) { - String++; - } - String++; - - if (*String == 0) { - // - // If double NULL then we are done. - // Return pointer to next structure in Smbios. - // if you pass in a 0 you will always get here - // - Smbios->Raw = (UINT8 *)++String; - return NULL; - } - } - - return NULL; -} - - -/** - This function obtains the system guid and the serial number from the smbios table. - - @param[out] SystemGuid The pointer of the returned system guid. - - @retval EFI_SUCCESS Successfully obtained the system guid. - @retval EFI_NOT_FOUND Did not find the SMBIOS table. - -**/ -EFI_STATUS -PxeBcGetSystemGuid ( - OUT EFI_GUID *SystemGuid - ) -{ - EFI_STATUS Status; - SMBIOS_TABLE_ENTRY_POINT *SmbiosTable; - SMBIOS_STRUCTURE_POINTER Smbios; - SMBIOS_STRUCTURE_POINTER SmbiosEnd; - UINT16 Index; - - SmbiosTable = NULL; - Status = EfiGetSystemConfigurationTable (&gEfiSmbiosTableGuid, (VOID **) &SmbiosTable); - - if (EFI_ERROR (Status) || SmbiosTable == NULL) { - return EFI_NOT_FOUND; - } - - Smbios.Hdr = (SMBIOS_STRUCTURE *) (UINTN) SmbiosTable->TableAddress; - SmbiosEnd.Raw = (UINT8 *) (UINTN) (SmbiosTable->TableAddress + SmbiosTable->TableLength); - - for (Index = 0; Index < SmbiosTable->TableLength; Index++) { - if (Smbios.Hdr->Type == 1) { - if (Smbios.Hdr->Length < 0x19) { - // - // Older version did not support Guid and Serial number - // - continue; - } - // - // SMBIOS tables are byte packed so we need to do a byte copy to - // prevend alignment faults on Itanium-based platform. - // - CopyMem (SystemGuid, &Smbios.Type1->Uuid, sizeof (EFI_GUID)); - PxeBcGetSmbiosString (&Smbios, Smbios.Type1->SerialNumber); - - return EFI_SUCCESS; - } - // - // Make Smbios point to the next record - // - PxeBcGetSmbiosString (&Smbios, 0); - - if (Smbios.Raw >= SmbiosEnd.Raw) { - // - // SMBIOS 2.1 incorrectly stated the length of SmbiosTable as 0x1e. - // given this we must double check against the length of the structure. - // - return EFI_SUCCESS; - } - } - - return EFI_NOT_FOUND; -} - - /** Flush the previous configration using the new station Ip address. @@ -150,24 +28,24 @@ PxeBcGetSystemGuid ( **/ 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); - Mode = Private->PxeBc.Mode; Status = EFI_SUCCESS; if (Mode->UsingIpv6) { - CopyMem (&Private->Udp6CfgData.StationAddress, StationIp, sizeof (EFI_IPv6_ADDRESS)); - CopyMem (&Private->Ip6CfgData.StationAddress, StationIp, sizeof (EFI_IPv6_ADDRESS)); + if (StationIp != NULL) { + CopyMem (&Private->Udp6CfgData.StationAddress, StationIp, sizeof (EFI_IPv6_ADDRESS)); + CopyMem (&Private->Ip6CfgData.StationAddress, StationIp, sizeof (EFI_IPv6_ADDRESS)); + } // // Reconfigure the Ip6 instance to capture background ICMP6 packets with new station Ip address. @@ -181,16 +59,16 @@ 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) { + CopyMem (&Private->Udp4CfgData.StationAddress, StationIp, sizeof (EFI_IPv4_ADDRESS)); + CopyMem (&Private->Ip4CfgData.StationAddress, StationIp, sizeof (EFI_IPv4_ADDRESS)); + } + + if (SubnetMask != NULL) { + CopyMem (&Private->Udp4CfgData.SubnetMask, SubnetMask, sizeof (EFI_IPv4_ADDRESS)); + CopyMem (&Private->Ip4CfgData.SubnetMask, SubnetMask, sizeof (EFI_IPv4_ADDRESS)); + } // // Reconfigure the Ip4 instance to capture background ICMP packets with new station Ip address. @@ -204,10 +82,6 @@ PxeBcFlushStaionIp ( } Status = Private->Ip4->Receive (Private->Ip4, &Private->IcmpToken); - if (EFI_ERROR (Status)) { - goto ON_EXIT; - } - } ON_EXIT: @@ -388,7 +262,9 @@ PxeBcIcmpErrorDpcHandle ( } 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. // @@ -403,14 +279,11 @@ PxeBcIcmpErrorDpcHandle ( gBS->SignalEvent (RxData->RecycleSignal); goto ON_EXIT; } - - 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); @@ -540,19 +413,16 @@ PxeBcIcmp6ErrorDpcHandle ( goto ON_EXIT; } - 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. @@ -619,6 +489,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. @@ -631,7 +503,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; @@ -641,8 +515,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; @@ -1507,11 +1381,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); } } @@ -1522,6 +1395,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. @@ -1529,7 +1403,8 @@ PxeBcUintnToAscDecWithFormat ( UINTN PxeBcUintnToAscDec ( IN UINTN Number, - IN UINT8 *Buffer + IN UINT8 *Buffer, + IN UINTN BufferSize ) { UINTN Index; @@ -1545,7 +1420,7 @@ PxeBcUintnToAscDec ( Number = (UINTN) (Number / 10); } while (Number != 0); - AsciiStrCpy ((CHAR8 *) Buffer, &TempStr[Index]); + AsciiStrCpyS ((CHAR8 *) Buffer, BufferSize, &TempStr[Index]); Length = AsciiStrLen ((CHAR8 *) Buffer); @@ -1586,3 +1461,56 @@ PxeBcUniHexToUint8 ( return EFI_INVALID_PARAMETER; } + +/** + Calculate the elapsed time. + + @param[in] Private The pointer to PXE private data + +**/ +VOID +CalcElapsedTime ( + IN PXEBC_PRIVATE_DATA *Private + ) +{ + EFI_TIME Time; + UINT64 CurrentStamp; + UINT64 ElapsedTimeValue; + + // + // Generate a time stamp of the centiseconds from 1900/1/1, assume 30day/month. + // + 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) + ); + + // + // Sentinel value of 0 means that this is the first DHCP packet that we are + // sending and that we need to initialize the value. First DHCP Solicit + // gets 0 elapsed-time. Otherwise, calculate based on StartTime. + // + if (Private->ElapsedTime == 0) { + Private->ElapsedTime = CurrentStamp; + } else { + ElapsedTimeValue = CurrentStamp - Private->ElapsedTime; + + // + // If elapsed time cannot fit in two bytes, set it to 0xffff. + // + if (ElapsedTimeValue > 0xffff) { + ElapsedTimeValue = 0xffff; + } + // + // Save the elapsed time + // + Private->ElapsedTime = ElapsedTimeValue; + } +} +