X-Git-Url: https://git.proxmox.com/?a=blobdiff_plain;f=NetworkPkg%2FUefiPxeBcDxe%2FPxeBcImpl.c;h=be3d248fa9f11e4dbb5570b96f584ec168084031;hb=393a3169c2a777e3ed899c85f7827258a13f0755;hp=82fddb169ae0a6e14525cb4130637ffd5331e3ae;hpb=4496ff751f7843fbbedf91f1a58212eb7c9a1ca8;p=mirror_edk2.git diff --git a/NetworkPkg/UefiPxeBcDxe/PxeBcImpl.c b/NetworkPkg/UefiPxeBcDxe/PxeBcImpl.c index 82fddb169a..be3d248fa9 100644 --- a/NetworkPkg/UefiPxeBcDxe/PxeBcImpl.c +++ b/NetworkPkg/UefiPxeBcDxe/PxeBcImpl.c @@ -1,7 +1,7 @@ /** @file This implementation of EFI_PXE_BASE_CODE_PROTOCOL and EFI_LOAD_FILE_PROTOCOL. - Copyright (c) 2007 - 2011, Intel Corporation. All rights reserved.
+ Copyright (c) 2007 - 2014, 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 @@ -81,6 +81,17 @@ EfiPxeBcStart ( if (Mode->UsingIpv6) { AsciiPrint ("\n>>Start PXE over IPv6"); + // + // Configure udp6 instance to receive data. + // + Status = Private->Udp6Read->Configure ( + Private->Udp6Read, + &Private->Udp6CfgData + ); + if (EFI_ERROR (Status)) { + goto ON_ERROR; + } + // // Configure block size for TFTP as a default value to handle all link layers. // @@ -115,6 +126,17 @@ EfiPxeBcStart ( } } else { AsciiPrint ("\n>>Start PXE over IPv4"); + // + // Configure udp4 instance to receive data. + // + Status = Private->Udp4Read->Configure ( + Private->Udp4Read, + &Private->Udp4CfgData + ); + if (EFI_ERROR (Status)) { + goto ON_ERROR; + } + // // Configure block size for TFTP as a default value to handle all link layers. // @@ -323,6 +345,10 @@ EfiPxeBcStop ( Private->BootFileSize = 0; Private->SolicitTimes = 0; Private->ElapsedTime = 0; + ZeroMem (&Private->StationIp, sizeof (EFI_IP_ADDRESS)); + ZeroMem (&Private->SubnetMask, sizeof (EFI_IP_ADDRESS)); + ZeroMem (&Private->GatewayIp, sizeof (EFI_IP_ADDRESS)); + ZeroMem (&Private->ServerIp, sizeof (EFI_IP_ADDRESS)); // // Reset the mode data. @@ -406,15 +432,6 @@ EfiPxeBcDhcp ( // Start S.A.R.R. process to get a IPv6 address and other boot information. // Status = PxeBcDhcp6Sarr (Private, Private->Dhcp6); - - if (EFI_ERROR (Status)) { - return Status; - } - - // - // Configure Udp6Read instance - // - Status = Private->Udp6Read->Configure (Private->Udp6Read, &Private->Udp6CfgData); } else { // @@ -426,17 +443,16 @@ EfiPxeBcDhcp ( // Start D.O.R.A. process to get a IPv4 address and other boot information. // Status = PxeBcDhcp4Dora (Private, Private->Dhcp4); - - if (EFI_ERROR (Status)) { - return Status; - } - - // - // Configure Udp4Read instance - // - Status = Private->Udp4Read->Configure (Private->Udp4Read, &Private->Udp4CfgData); } + // + // Reconfigure the UDP instance with the default configuration. + // + if (Mode->UsingIpv6) { + Private->Udp6Read->Configure (Private->Udp6Read, &Private->Udp6CfgData); + } else { + Private->Udp4Read->Configure (Private->Udp4Read, &Private->Udp4CfgData); + } // // Dhcp(), Discover(), and Mtftp() set the IP filter, and return with the IP // receive filter list emptied and the filter set to EFI_PXE_BASE_CODE_IP_FILTER_STATION_IP. @@ -511,6 +527,7 @@ EfiPxeBcDiscover ( UINT16 Index; EFI_STATUS Status; EFI_PXE_BASE_CODE_IP_FILTER IpFilter; + EFI_PXE_BASE_CODE_DISCOVER_INFO *NewCreatedInfo; if (This == NULL) { return EFI_INVALID_PARAMETER; @@ -523,6 +540,7 @@ EfiPxeBcDiscover ( SrvList = NULL; Status = EFI_DEVICE_ERROR; Private->Function = EFI_PXE_BASE_CODE_FUNCTION_DISCOVER; + NewCreatedInfo = NULL; if (!Mode->Started) { return EFI_NOT_STARTED; @@ -552,6 +570,7 @@ EfiPxeBcDiscover ( // // There are 3 methods to get the information for discover. // + ZeroMem (&DefaultInfo, sizeof (EFI_PXE_BASE_CODE_DISCOVER_INFO)); if (*Layer != EFI_PXE_BASE_CODE_BOOT_LAYER_INITIAL) { // // 1. Take the previous setting as the discover info. @@ -576,12 +595,13 @@ EfiPxeBcDiscover ( // // 2. Extract the discover information from the cached packets if unspecified. // - Info = &DefaultInfo; - Status = PxeBcExtractDiscoverInfo (Private, Type, Info, &BootSvrEntry, &SrvList); + NewCreatedInfo = &DefaultInfo; + Status = PxeBcExtractDiscoverInfo (Private, Type, &NewCreatedInfo, &BootSvrEntry, &SrvList); if (EFI_ERROR (Status)) { goto ON_EXIT; } - + ASSERT (NewCreatedInfo != NULL); + Info = NewCreatedInfo; } else { // // 3. Take the pass-in information as the discover info, and validate the server list. @@ -597,7 +617,7 @@ EfiPxeBcDiscover ( if (Index != Info->IpCnt) { // // It's invalid if the first server doesn't accecpt any response - // and meanwhile any of the rest servers accept any reponse. + // but any of the other servers does accept any response. // Status = EFI_INVALID_PARAMETER; goto ON_EXIT; @@ -616,30 +636,7 @@ EfiPxeBcDiscover ( Private->IsDoDiscover = TRUE; - if (Info->UseUCast) { - // - // Do discover by unicast. - // - for (Index = 0; Index < Info->IpCnt; Index++) { - if (BootSvrEntry == NULL) { - CopyMem (&Private->ServerIp, &SrvList[Index].IpAddr, sizeof (EFI_IP_ADDRESS)); - } else { - ASSERT (!Mode->UsingIpv6); - ZeroMem (&Private->ServerIp, sizeof (EFI_IP_ADDRESS)); - CopyMem (&Private->ServerIp, &BootSvrEntry->IpAddr[Index], sizeof (EFI_IPv4_ADDRESS)); - } - - Status = PxeBcDiscoverBootServer ( - Private, - Type, - Layer, - UseBis, - &SrvList[Index].IpAddr, - 0, - NULL - ); - } - } else if (Info->UseMCast) { + if (Info->UseMCast) { // // Do discover by multicast. // @@ -649,8 +646,8 @@ EfiPxeBcDiscover ( Layer, UseBis, &Info->ServerMCastIp, - 0, - NULL + Info->IpCnt, + SrvList ); } else if (Info->UseBCast) { @@ -667,6 +664,30 @@ EfiPxeBcDiscover ( Info->IpCnt, SrvList ); + + } else if (Info->UseUCast) { + // + // Do discover by unicast. + // + for (Index = 0; Index < Info->IpCnt; Index++) { + if (BootSvrEntry == NULL) { + CopyMem (&Private->ServerIp, &SrvList[Index].IpAddr, sizeof (EFI_IP_ADDRESS)); + } else { + ASSERT (!Mode->UsingIpv6); + ZeroMem (&Private->ServerIp, sizeof (EFI_IP_ADDRESS)); + CopyMem (&Private->ServerIp, &BootSvrEntry->IpAddr[Index], sizeof (EFI_IPv4_ADDRESS)); + } + + Status = PxeBcDiscoverBootServer ( + Private, + Type, + Layer, + UseBis, + &Private->ServerIp, + Info->IpCnt, + SrvList + ); + } } if (!EFI_ERROR (Status)) { @@ -678,8 +699,8 @@ EfiPxeBcDiscover ( if (!EFI_ERROR (Status)) { CopyMem ( &Mode->PxeReply.Dhcpv6, - &Private->PxeReply.Dhcp6.Packet.Offer, - Private->PxeReply.Dhcp6.Packet.Offer.Length + &Private->PxeReply.Dhcp6.Packet.Ack.Dhcp6, + Private->PxeReply.Dhcp6.Packet.Ack.Length ); Mode->PxeReplyReceived = TRUE; Mode->PxeDiscoverValid = TRUE; @@ -689,8 +710,8 @@ EfiPxeBcDiscover ( if (!EFI_ERROR (Status)) { CopyMem ( &Mode->PxeReply.Dhcpv4, - &Private->PxeReply.Dhcp4.Packet.Offer, - Private->PxeReply.Dhcp4.Packet.Offer.Length + &Private->PxeReply.Dhcp4.Packet.Ack.Dhcp4, + Private->PxeReply.Dhcp4.Packet.Ack.Length ); Mode->PxeReplyReceived = TRUE; Mode->PxeDiscoverValid = TRUE; @@ -700,10 +721,14 @@ EfiPxeBcDiscover ( ON_EXIT: + if (NewCreatedInfo != NULL && NewCreatedInfo != &DefaultInfo) { + FreePool (NewCreatedInfo); + } + if (Mode->UsingIpv6) { - Status = Private->Udp6Read->Configure (Private->Udp6Read, &Private->Udp6CfgData); + Private->Udp6Read->Configure (Private->Udp6Read, &Private->Udp6CfgData); } else { - Status = Private->Udp4Read->Configure (Private->Udp4Read, &Private->Udp4CfgData); + Private->Udp4Read->Configure (Private->Udp4Read, &Private->Udp4CfgData); } // @@ -937,12 +962,14 @@ EfiPxeBcMtftp ( Mode->IcmpErrorReceived = TRUE; } + // + // Reconfigure the UDP instance with the default configuration. + // if (Mode->UsingIpv6) { - Status = Private->Udp6Read->Configure (Private->Udp6Read, &Private->Udp6CfgData); + Private->Udp6Read->Configure (Private->Udp6Read, &Private->Udp6CfgData); } else { - Status = Private->Udp4Read->Configure (Private->Udp4Read, &Private->Udp4CfgData); + Private->Udp4Read->Configure (Private->Udp4Read, &Private->Udp4CfgData); } - // // Dhcp(), Discover(), and Mtftp() set the IP filter, and return with the IP // receive filter list emptied and the filter set to EFI_PXE_BASE_CODE_IP_FILTER_STATION_IP. @@ -1222,6 +1249,12 @@ EfiPxeBcUdpRead ( BOOLEAN IsDone; BOOLEAN IsMatched; UINTN CopiedLen; + UINTN HeaderLen; + UINTN HeaderCopiedLen; + UINTN BufferCopiedLen; + UINT32 FragmentLength; + UINTN FragmentIndex; + UINT8 *FragmentBuffer; if (This == NULL || DestIp == NULL || DestPort == NULL) { return EFI_INVALID_PARAMETER; @@ -1336,26 +1369,55 @@ EfiPxeBcUdpRead ( // // Copy the rececived packet to user if matched by filter. // - CopiedLen = 0; if (Mode->UsingIpv6) { Udp6Rx = Udp6Token.Packet.RxData; ASSERT (Udp6Rx != NULL); - // - // Copy the header part of received data. - // + + HeaderLen = 0; if (HeaderSize != NULL) { - CopiedLen = MIN (*HeaderSize, Udp6Rx->DataLength); - *HeaderSize = CopiedLen; - CopyMem (HeaderPtr, Udp6Rx->FragmentTable[0].FragmentBuffer, *HeaderSize); + HeaderLen = MIN (*HeaderSize, Udp6Rx->DataLength); } - // - // Copy the other part of received data. - // - if (Udp6Rx->DataLength - CopiedLen > *BufferSize) { + + if (Udp6Rx->DataLength - HeaderLen > *BufferSize) { Status = EFI_BUFFER_TOO_SMALL; } else { - *BufferSize = Udp6Rx->DataLength - CopiedLen; - CopyMem (BufferPtr, (UINT8 *) Udp6Rx->FragmentTable[0].FragmentBuffer + CopiedLen, *BufferSize); + if (HeaderSize != NULL) { + *HeaderSize = HeaderLen; + } + *BufferSize = Udp6Rx->DataLength - HeaderLen; + + HeaderCopiedLen = 0; + BufferCopiedLen = 0; + for (FragmentIndex = 0; FragmentIndex < Udp6Rx->FragmentCount; FragmentIndex++) { + FragmentLength = Udp6Rx->FragmentTable[FragmentIndex].FragmentLength; + FragmentBuffer = Udp6Rx->FragmentTable[FragmentIndex].FragmentBuffer; + if (HeaderCopiedLen + FragmentLength < HeaderLen) { + // + // Copy the header part of received data. + // + CopyMem ((UINT8 *) HeaderPtr + HeaderCopiedLen, FragmentBuffer, FragmentLength); + HeaderCopiedLen += FragmentLength; + } else if (HeaderCopiedLen < HeaderLen) { + // + // Copy the header part of received data. + // + CopiedLen = HeaderLen - HeaderCopiedLen; + CopyMem ((UINT8 *) HeaderPtr + HeaderCopiedLen, FragmentBuffer, CopiedLen); + HeaderCopiedLen += CopiedLen; + + // + // Copy the other part of received data. + // + CopyMem ((UINT8 *) BufferPtr + BufferCopiedLen, FragmentBuffer + CopiedLen, FragmentLength - CopiedLen); + BufferCopiedLen += (FragmentLength - CopiedLen); + } else { + // + // Copy the other part of received data. + // + CopyMem ((UINT8 *) BufferPtr + BufferCopiedLen, FragmentBuffer, FragmentLength); + BufferCopiedLen += FragmentLength; + } + } } // // Recycle the receiving buffer after copy to user. @@ -1364,22 +1426,52 @@ EfiPxeBcUdpRead ( } else { Udp4Rx = Udp4Token.Packet.RxData; ASSERT (Udp4Rx != NULL); - // - // Copy the header part of received data. - // + + HeaderLen = 0; if (HeaderSize != NULL) { - CopiedLen = MIN (*HeaderSize, Udp4Rx->DataLength); - *HeaderSize = CopiedLen; - CopyMem (HeaderPtr, Udp4Rx->FragmentTable[0].FragmentBuffer, *HeaderSize); + HeaderLen = MIN (*HeaderSize, Udp4Rx->DataLength); } - // - // Copy the other part of received data. - // - if (Udp4Rx->DataLength - CopiedLen > *BufferSize) { + + if (Udp4Rx->DataLength - HeaderLen > *BufferSize) { Status = EFI_BUFFER_TOO_SMALL; } else { - *BufferSize = Udp4Rx->DataLength - CopiedLen; - CopyMem (BufferPtr, (UINT8 *) Udp4Rx->FragmentTable[0].FragmentBuffer + CopiedLen, *BufferSize); + if (HeaderSize != NULL) { + *HeaderSize = HeaderLen; + } + *BufferSize = Udp4Rx->DataLength - HeaderLen; + + HeaderCopiedLen = 0; + BufferCopiedLen = 0; + for (FragmentIndex = 0; FragmentIndex < Udp4Rx->FragmentCount; FragmentIndex++) { + FragmentLength = Udp4Rx->FragmentTable[FragmentIndex].FragmentLength; + FragmentBuffer = Udp4Rx->FragmentTable[FragmentIndex].FragmentBuffer; + if (HeaderCopiedLen + FragmentLength < HeaderLen) { + // + // Copy the header part of received data. + // + CopyMem ((UINT8 *) HeaderPtr + HeaderCopiedLen, FragmentBuffer, FragmentLength); + HeaderCopiedLen += FragmentLength; + } else if (HeaderCopiedLen < HeaderLen) { + // + // Copy the header part of received data. + // + CopiedLen = HeaderLen - HeaderCopiedLen; + CopyMem ((UINT8 *) HeaderPtr + HeaderCopiedLen, FragmentBuffer, CopiedLen); + HeaderCopiedLen += CopiedLen; + + // + // Copy the other part of received data. + // + CopyMem ((UINT8 *) BufferPtr + BufferCopiedLen, FragmentBuffer + CopiedLen, FragmentLength - CopiedLen); + BufferCopiedLen += (FragmentLength - CopiedLen); + } else { + // + // Copy the other part of received data. + // + CopyMem ((UINT8 *) BufferPtr + BufferCopiedLen, FragmentBuffer, FragmentLength); + BufferCopiedLen += FragmentLength; + } + } } // // Recycle the receiving buffer after copy to user. @@ -1933,7 +2025,7 @@ EfiPxeBcSetStationIP ( CopyMem (&Private->SubnetMask ,NewSubnetMask, sizeof (EFI_IP_ADDRESS)); } - Status = PxeBcFlushStaionIp (Private, NewStationIp, NewSubnetMask); + Status = PxeBcFlushStationIp (Private, NewStationIp, NewSubnetMask); ON_EXIT: return Status; } @@ -2252,6 +2344,15 @@ EfiPxeLoadFile ( // Start Pxe Base Code to initialize PXE boot. // Status = PxeBc->Start (PxeBc, UsingIpv6); + if (Status == EFI_ALREADY_STARTED && UsingIpv6 != PxeBc->Mode->UsingIpv6) { + // + // PxeBc protocol has already been started but not on the required IP version, restart it. + // + Status = PxeBc->Stop (PxeBc); + if (!EFI_ERROR (Status)) { + Status = PxeBc->Start (PxeBc, UsingIpv6); + } + } if (Status == EFI_SUCCESS || Status == EFI_ALREADY_STARTED) { Status = PxeBcLoadBootFile (Private, BufferSize, Buffer); }