]> git.proxmox.com Git - mirror_edk2.git/blobdiff - MdeModulePkg/Universal/Network/UefiPxeBcDxe/PxeBcImpl.c
MdeModulePkg: Refine casting expression result to bigger size
[mirror_edk2.git] / MdeModulePkg / Universal / Network / UefiPxeBcDxe / PxeBcImpl.c
index 4ea15a6314f508222b6b33a0ef18e14af78e3c41..cd00f5c52dc35bcfefee1338191e52770b2018dc 100644 (file)
@@ -1,7 +1,7 @@
 /** @file\r
   Interface routines for PxeBc.\r
 \r
-Copyright (c) 2007 - 2011, Intel Corporation. All rights reserved.<BR>\r
+Copyright (c) 2007 - 2017, 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
@@ -176,7 +176,9 @@ IcmpErrorListenHandlerDpc (
   }\r
 \r
   if (EFI_IP4 (RxData->Header->SourceAddress) != 0 &&\r
-      !NetIp4IsUnicast (EFI_NTOHL (RxData->Header->SourceAddress), 0)) {\r
+      (NTOHL (Mode->SubnetMask.Addr[0]) != 0) &&\r
+      IP4_NET_EQUAL (NTOHL(Mode->StationIp.Addr[0]), EFI_NTOHL (RxData->Header->SourceAddress), NTOHL (Mode->SubnetMask.Addr[0])) &&\r
+      !NetIp4IsUnicast (EFI_NTOHL (RxData->Header->SourceAddress), NTOHL (Mode->SubnetMask.Addr[0]))) {\r
     //\r
     // The source address is not zero and it's not a unicast IP address, discard it.\r
     //\r
@@ -351,8 +353,8 @@ EfiPxeBcStart (
   //\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
+  Private->BlockSize   = 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
@@ -410,6 +412,18 @@ EfiPxeBcStart (
     goto ON_EXIT;\r
   }\r
 \r
+  //\r
+  //DHCP4 service allows only one of its children to be configured in  \r
+  //the active state, If the DHCP4 D.O.R.A started by IP4 auto  \r
+  //configuration and has not been completed, the Dhcp4 state machine \r
+  //will not be in the right state for the PXE to start a new round D.O.R.A. \r
+  //so we need to switch it's policy to static.\r
+  //\r
+  Status = PxeBcSetIp4Policy (Private);\r
+  if (EFI_ERROR (Status)) {\r
+    goto ON_EXIT;\r
+  }\r
+    \r
   Status = Private->Ip4->Configure (Private->Ip4, &Private->Ip4ConfigData);\r
   if (EFI_ERROR (Status)) {\r
     goto ON_EXIT;\r
@@ -626,7 +640,7 @@ EfiPxeBcDhcp (
   ZeroMem (Private->ProxyIndex, sizeof (Private->ProxyIndex));\r
 \r
   Status = Dhcp4->Start (Dhcp4, NULL);\r
-  if (EFI_ERROR (Status)) {\r
+  if (EFI_ERROR (Status) && Status != EFI_ALREADY_STARTED) {\r
     if (Status == EFI_ICMP_ERROR) {\r
       Mode->IcmpErrorReceived = TRUE;\r
     }\r
@@ -652,9 +666,6 @@ EfiPxeBcDhcp (
   // finished, set the various Mode members.\r
   //\r
   Status = PxeBcCheckSelectedOffer (Private);\r
-  if (!EFI_ERROR (Status)) {\r
-    goto ON_EXIT;\r
-  }\r
 \r
 ON_EXIT:\r
   if (EFI_ERROR (Status)) {\r
@@ -727,7 +738,7 @@ ON_EXIT:
     }\r
   }\r
 \r
-  Status = Private->Udp4Read->Configure (Private->Udp4Read, &Private->Udp4CfgData);\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
@@ -840,6 +851,7 @@ EfiPxeBcDiscover (
   // If info isn't offered,\r
   //   use the cached DhcpAck and ProxyOffer packets.\r
   //\r
+  ZeroMem (&DefaultInfo, sizeof (EFI_PXE_BASE_CODE_DISCOVER_INFO));\r
   if (*Layer != EFI_PXE_BASE_CODE_BOOT_LAYER_INITIAL) {\r
 \r
     if (!Mode->PxeDiscoverValid || !Mode->PxeReplyReceived || (!Mode->PxeBisReplyReceived && UseBis)) {\r
@@ -1024,6 +1036,7 @@ EfiPxeBcDiscover (
     } else {\r
       Status = EFI_DEVICE_ERROR;\r
     }\r
+    goto ON_EXIT;\r
   } else {\r
     PxeBcParseCachedDhcpPacket (&Private->PxeReply);\r
   }\r
@@ -1042,7 +1055,7 @@ EfiPxeBcDiscover (
 \r
 ON_EXIT:\r
 \r
-  Status = Private->Udp4Read->Configure (Private->Udp4Read, &Private->Udp4CfgData);\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
@@ -1152,7 +1165,9 @@ EfiPxeBcMtftp (
   if ((This == NULL)                                                          ||\r
       (Filename == NULL)                                                      ||\r
       (BufferSize == NULL)                                                    ||\r
-      ((ServerIp == NULL) || !NetIp4IsUnicast (NTOHL (ServerIp->Addr[0]), 0)) ||\r
+      ((ServerIp == NULL) || \r
+       (IP4_IS_UNSPECIFIED (NTOHL (ServerIp->Addr[0])) || \r
+        IP4_IS_LOCAL_BROADCAST (NTOHL (ServerIp->Addr[0]))))                  ||\r
       ((BufferPtr == NULL) && DontUseBuffer)                                  ||\r
       ((BlockSize != NULL) && (*BlockSize < 512))) {\r
 \r
@@ -1278,7 +1293,12 @@ EfiPxeBcMtftp (
     Mode->IcmpErrorReceived = TRUE;\r
   }\r
 \r
-  Status = Private->Udp4Read->Configure (Private->Udp4Read, &Private->Udp4CfgData);\r
+  if (EFI_ERROR (Status)) {\r
+    goto ON_EXIT;\r
+  }\r
+\r
+ON_EXIT:\r
+  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
@@ -1362,7 +1382,7 @@ EfiPxeBcUdpWrite (
     return EFI_INVALID_PARAMETER;\r
   }\r
 \r
-  if ((GatewayIp != NULL) && !NetIp4IsUnicast (NTOHL (GatewayIp->Addr[0]), 0)) {\r
+  if ((GatewayIp != NULL) && (IP4_IS_UNSPECIFIED (NTOHL (GatewayIp->Addr[0])) || IP4_IS_LOCAL_BROADCAST (NTOHL (GatewayIp->Addr[0])))) {\r
     //\r
     // Gateway is provided but it's not a unicast IP address.\r
     //\r
@@ -1419,7 +1439,9 @@ EfiPxeBcUdpWrite (
              &Private->StationIp.v4,\r
              &Private->SubnetMask.v4,\r
              &Private->GatewayIp.v4,\r
-             &Private->CurrentUdpSrcPort\r
+             &Private->CurrentUdpSrcPort,\r
+             Private->Mode.TTL,\r
+             Private->Mode.ToS\r
              );\r
   if (EFI_ERROR (Status)) {\r
     Private->CurrentUdpSrcPort = 0;\r
@@ -1626,7 +1648,13 @@ EfiPxeBcUdpRead (
   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
@@ -1783,26 +1811,51 @@ TRY_AGAIN:
     }\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
@@ -1915,9 +1968,11 @@ EfiPxeBcSetIpFilter (
       DEBUG ((EFI_D_ERROR, "There is broadcast address in NewFilter.\n"));\r
       return EFI_INVALID_PARAMETER;\r
     }\r
-    if (NetIp4IsUnicast (EFI_IP4 (NewFilter->IpList[Index].v4), 0) &&\r
-        ((NewFilter->Filters & EFI_PXE_BASE_CODE_IP_FILTER_STATION_IP) != 0)\r
-       ) {\r
+    if ((EFI_NTOHL(Mode->StationIp) != 0) &&\r
+        (EFI_NTOHL(Mode->SubnetMask) != 0) &&\r
+        IP4_NET_EQUAL(EFI_NTOHL(Mode->StationIp), EFI_NTOHL(NewFilter->IpList[Index].v4), EFI_NTOHL(Mode->SubnetMask)) &&\r
+        NetIp4IsUnicast (EFI_IP4 (NewFilter->IpList[Index].v4), EFI_NTOHL(Mode->SubnetMask)) &&\r
+        ((NewFilter->Filters & EFI_PXE_BASE_CODE_IP_FILTER_STATION_IP) != 0)) {\r
       //\r
       // If EFI_PXE_BASE_CODE_IP_FILTER_STATION_IP is set and IP4 address is in IpList,\r
       // promiscuous mode is needed.\r
@@ -2259,14 +2314,18 @@ EfiPxeBcSetStationIP (
     return EFI_INVALID_PARAMETER;\r
   }\r
 \r
-  if (NewStationIp != NULL && !NetIp4IsUnicast (NTOHL (NewStationIp->Addr[0]), 0)) {\r
-    return EFI_INVALID_PARAMETER;\r
-  }\r
-\r
   if (NewSubnetMask != NULL && !IP4_IS_VALID_NETMASK (NTOHL (NewSubnetMask->Addr[0]))) {\r
     return EFI_INVALID_PARAMETER;\r
   }\r
 \r
+  if (NewStationIp != NULL) {\r
+    if (IP4_IS_UNSPECIFIED(NTOHL (NewStationIp->Addr[0])) || \r
+        IP4_IS_LOCAL_BROADCAST(NTOHL (NewStationIp->Addr[0])) ||\r
+        (NewSubnetMask != NULL && !NetIp4IsUnicast (NTOHL (NewStationIp->Addr[0]), NTOHL (NewSubnetMask->Addr[0])))) {\r
+      return EFI_INVALID_PARAMETER;\r
+    }\r
+  }\r
+  \r
   Private = PXEBC_PRIVATE_DATA_FROM_PXEBC (This);\r
   Mode    = Private->PxeBc.Mode;\r
 \r
@@ -2729,6 +2788,10 @@ EfiPxeLoadFile (
   UINT64                      TmpBufSize;\r
   BOOLEAN                     MediaPresent;\r
 \r
+  if (FilePath == NULL || !IsDevicePathEnd (FilePath)) {\r
+    return EFI_INVALID_PARAMETER;\r
+  }\r
+  \r
   Private         = PXEBC_PRIVATE_DATA_FROM_LOADFILE (This);\r
   PxeBc           = &Private->PxeBc;\r
   NewMakeCallback = FALSE;\r
@@ -2851,9 +2914,14 @@ EfiPxeLoadFile (
   //\r
   if (Status == EFI_SUCCESS) {\r
     //\r
+    // The DHCP4 can have only one configured child instance so we need to stop\r
+    // reset the DHCP4 child before we return. Otherwise the other programs which \r
+    // also need to use DHCP4 will be impacted.\r
     // The functionality of PXE Base Code protocol will not be stopped,\r
     // when downloading is successfully.\r
     //\r
+    Private->Dhcp4->Stop (Private->Dhcp4);\r
+    Private->Dhcp4->Configure (Private->Dhcp4, NULL);\r
     return EFI_SUCCESS;\r
 \r
   } else if (Status == EFI_BUFFER_TOO_SMALL) {\r