]> git.proxmox.com Git - mirror_edk2.git/blobdiff - NetworkPkg/UefiPxeBcDxe/PxeBcImpl.c
1. Fix a bug for PXEv6 when Proxy PXE server and DHCP server are located at the same...
[mirror_edk2.git] / NetworkPkg / UefiPxeBcDxe / PxeBcImpl.c
index 82fddb169ae0a6e14525cb4130637ffd5331e3ae..ba7f9485949ef74f36a8c3b77ab93d2a7d570f4d 100644 (file)
@@ -1,7 +1,7 @@
 /** @file\r
   This implementation of EFI_PXE_BASE_CODE_PROTOCOL and EFI_LOAD_FILE_PROTOCOL.\r
 \r
-  Copyright (c) 2007 - 2011, Intel Corporation. All rights reserved.<BR>\r
+  Copyright (c) 2007 - 2012, Intel Corporation. All rights reserved.<BR>\r
 \r
   This program and the accompanying materials\r
   are licensed and made available under the terms and conditions of the BSD License\r
@@ -81,6 +81,17 @@ EfiPxeBcStart (
 \r
   if (Mode->UsingIpv6) {\r
     AsciiPrint ("\n>>Start PXE over IPv6");\r
+    //\r
+    // Configure udp6 instance to receive data.\r
+    //\r
+    Status = Private->Udp6Read->Configure (\r
+                                  Private->Udp6Read,\r
+                                  &Private->Udp6CfgData\r
+                                  );\r
+    if (EFI_ERROR (Status)) {\r
+      goto ON_ERROR;\r
+    }\r
+    \r
     //\r
     // Configure block size for TFTP as a default value to handle all link layers.\r
     //\r
@@ -115,6 +126,17 @@ EfiPxeBcStart (
     }\r
   } else {\r
     AsciiPrint ("\n>>Start PXE over IPv4");\r
+    //\r
+    // Configure udp4 instance to receive data.\r
+    //\r
+    Status = Private->Udp4Read->Configure (\r
+                                  Private->Udp4Read,\r
+                                  &Private->Udp4CfgData\r
+                                  );\r
+    if (EFI_ERROR (Status)) {\r
+      goto ON_ERROR;\r
+    }\r
+    \r
     //\r
     // Configure block size for TFTP as a default value to handle all link layers.\r
     //\r
@@ -408,13 +430,8 @@ EfiPxeBcDhcp (
     Status = PxeBcDhcp6Sarr (Private, Private->Dhcp6);\r
 \r
     if (EFI_ERROR (Status)) {\r
-      return Status;\r
+      goto ON_EXIT;\r
     }\r
-\r
-    //\r
-    // Configure Udp6Read instance\r
-    //\r
-    Status = Private->Udp6Read->Configure (Private->Udp6Read, &Private->Udp6CfgData);    \r
   } else {\r
 \r
     //\r
@@ -428,15 +445,16 @@ EfiPxeBcDhcp (
     Status = PxeBcDhcp4Dora (Private, Private->Dhcp4);\r
 \r
     if (EFI_ERROR (Status)) {\r
-      return Status;\r
+      goto ON_EXIT;\r
     }\r
-\r
-    //\r
-    // Configure Udp4Read instance\r
-    //\r
-    Status = Private->Udp4Read->Configure (Private->Udp4Read, &Private->Udp4CfgData);\r
   }\r
-\r
+  \r
+ON_EXIT:\r
+  if (Mode->UsingIpv6) {\r
+    Private->Udp6Read->Configure (Private->Udp6Read, &Private->Udp6CfgData);\r
+  } else {\r
+    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
@@ -669,7 +687,9 @@ EfiPxeBcDiscover (
                );\r
   }\r
 \r
-  if (!EFI_ERROR (Status)) {\r
+  if (EFI_ERROR (Status)) {\r
+    goto ON_EXIT;\r
+  } else {\r
     //\r
     // Parse the cached PXE reply packet, and store it into mode data if valid.\r
     //\r
@@ -701,9 +721,9 @@ EfiPxeBcDiscover (
 ON_EXIT:\r
 \r
   if (Mode->UsingIpv6) {\r
-    Status = Private->Udp6Read->Configure (Private->Udp6Read, &Private->Udp6CfgData);    \r
+    Private->Udp6Read->Configure (Private->Udp6Read, &Private->Udp6CfgData);\r
   } else {\r
-    Status = Private->Udp4Read->Configure (Private->Udp4Read, &Private->Udp4CfgData);    \r
+    Private->Udp4Read->Configure (Private->Udp4Read, &Private->Udp4CfgData);\r
   }\r
   \r
   //\r
@@ -937,12 +957,16 @@ EfiPxeBcMtftp (
     Mode->IcmpErrorReceived = TRUE;\r
   }\r
 \r
+  if (EFI_ERROR (Status)) {\r
+    goto ON_EXIT;\r
+  }\r
+  \r
+ON_EXIT:\r
   if (Mode->UsingIpv6) {\r
-    Status = Private->Udp6Read->Configure (Private->Udp6Read, &Private->Udp6CfgData);    \r
+    Private->Udp6Read->Configure (Private->Udp6Read, &Private->Udp6CfgData);\r
   } else {\r
-    Status = Private->Udp4Read->Configure (Private->Udp4Read, &Private->Udp4CfgData);    \r
+    Private->Udp4Read->Configure (Private->Udp4Read, &Private->Udp4CfgData);\r
   }\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
@@ -1222,6 +1246,12 @@ EfiPxeBcUdpRead (
   BOOLEAN                     IsDone;\r
   BOOLEAN                     IsMatched;\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
@@ -1336,26 +1366,55 @@ EfiPxeBcUdpRead (
     //\r
     // Copy the rececived packet to user if matched by filter.\r
     //\r
-    CopiedLen = 0;\r
     if (Mode->UsingIpv6) {\r
       Udp6Rx = Udp6Token.Packet.RxData;\r
       ASSERT (Udp6Rx != NULL);\r
-      //\r
-      // Copy the header part of received data.\r
-      //\r
+\r
+      HeaderLen = 0;\r
       if (HeaderSize != NULL) {\r
-        CopiedLen   = MIN (*HeaderSize, Udp6Rx->DataLength);\r
-        *HeaderSize = CopiedLen;\r
-        CopyMem (HeaderPtr, Udp6Rx->FragmentTable[0].FragmentBuffer, *HeaderSize);\r
+        HeaderLen = MIN (*HeaderSize, Udp6Rx->DataLength);\r
       }\r
-      //\r
-      // Copy the other part of received data.\r
-      //\r
-      if (Udp6Rx->DataLength - CopiedLen > *BufferSize) {\r
+\r
+      if (Udp6Rx->DataLength - HeaderLen > *BufferSize) {\r
         Status = EFI_BUFFER_TOO_SMALL;\r
       } else {\r
-        *BufferSize = Udp6Rx->DataLength - CopiedLen;\r
-        CopyMem (BufferPtr, (UINT8 *) Udp6Rx->FragmentTable[0].FragmentBuffer + CopiedLen, *BufferSize);\r
+        if (HeaderSize != NULL) {\r
+          *HeaderSize = HeaderLen;\r
+        }\r
+        *BufferSize = Udp6Rx->DataLength - HeaderLen;\r
+\r
+        HeaderCopiedLen = 0;\r
+        BufferCopiedLen = 0;\r
+        for (FragmentIndex = 0; FragmentIndex < Udp6Rx->FragmentCount; FragmentIndex++) {\r
+          FragmentLength = Udp6Rx->FragmentTable[FragmentIndex].FragmentLength;\r
+          FragmentBuffer = Udp6Rx->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
       //\r
       // Recycle the receiving buffer after copy to user.\r
@@ -1364,22 +1423,52 @@ EfiPxeBcUdpRead (
     } else {\r
       Udp4Rx = Udp4Token.Packet.RxData;\r
       ASSERT (Udp4Rx != NULL);\r
-      //\r
-      // Copy the header part of received data.\r
-      //\r
+\r
+      HeaderLen = 0;\r
       if (HeaderSize != NULL) {\r
-        CopiedLen   = MIN (*HeaderSize, Udp4Rx->DataLength);\r
-        *HeaderSize = CopiedLen;\r
-        CopyMem (HeaderPtr, Udp4Rx->FragmentTable[0].FragmentBuffer, *HeaderSize);\r
+        HeaderLen = MIN (*HeaderSize, Udp4Rx->DataLength);\r
       }\r
-      //\r
-      // Copy the other part of received data.\r
-      //\r
-      if (Udp4Rx->DataLength - CopiedLen > *BufferSize) {\r
+\r
+      if (Udp4Rx->DataLength - HeaderLen > *BufferSize) {\r
         Status = EFI_BUFFER_TOO_SMALL;\r
       } else {\r
-        *BufferSize = Udp4Rx->DataLength - CopiedLen;\r
-        CopyMem (BufferPtr, (UINT8 *) Udp4Rx->FragmentTable[0].FragmentBuffer + CopiedLen, *BufferSize);\r
+        if (HeaderSize != NULL) {\r
+          *HeaderSize = HeaderLen;\r
+        }\r
+        *BufferSize = Udp4Rx->DataLength - HeaderLen;\r
+\r
+        HeaderCopiedLen = 0;\r
+        BufferCopiedLen = 0;\r
+        for (FragmentIndex = 0; FragmentIndex < Udp4Rx->FragmentCount; FragmentIndex++) {\r
+          FragmentLength = Udp4Rx->FragmentTable[FragmentIndex].FragmentLength;\r
+          FragmentBuffer = Udp4Rx->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
       //\r
       // Recycle the receiving buffer after copy to user.\r