]> git.proxmox.com Git - mirror_edk2.git/blobdiff - NetworkPkg/UefiPxeBcDxe/PxeBcImpl.c
NetworkPkg: Recycle the ICMP error message in PXE driver.
[mirror_edk2.git] / NetworkPkg / UefiPxeBcDxe / PxeBcImpl.c
index cdcf2f0d3eadd6dd15afcd0d1522e823c852f387..dc77d256f8e97afdfe82e7ea06e9d0f9b952d600 100644 (file)
@@ -1,7 +1,7 @@
 /** @file\r
   This implementation of EFI_PXE_BASE_CODE_PROTOCOL and EFI_LOAD_FILE_PROTOCOL.\r
 \r
 /** @file\r
   This implementation of EFI_PXE_BASE_CODE_PROTOCOL and EFI_LOAD_FILE_PROTOCOL.\r
 \r
-  Copyright (c) 2007 - 2015, Intel Corporation. All rights reserved.<BR>\r
+  Copyright (c) 2007 - 2017, 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
 \r
   This program and the accompanying materials\r
   are licensed and made available under the terms and conditions of the BSD License\r
@@ -95,19 +95,19 @@ EfiPxeBcStart (
     //\r
     // Configure block size for TFTP as a default value to handle all link layers.\r
     //\r
     //\r
     // Configure block size for TFTP as a default value to handle all link layers.\r
     //\r
-    Private->BlockSize = (UINTN) (Private->Ip6MaxPacketSize -\r
-                           PXEBC_DEFAULT_UDP_OVERHEAD_SIZE - PXEBC_DEFAULT_TFTP_OVERHEAD_SIZE);\r
+    Private->BlockSize = Private->Ip6MaxPacketSize -\r
+                           PXEBC_DEFAULT_UDP_OVERHEAD_SIZE - PXEBC_DEFAULT_TFTP_OVERHEAD_SIZE;\r
 \r
     //\r
     // PXE over IPv6 starts here, initialize the fields and list header.\r
     //\r
     Private->Ip6Policy                          = PXEBC_IP6_POLICY_MAX;\r
 \r
     //\r
     // PXE over IPv6 starts here, initialize the fields and list header.\r
     //\r
     Private->Ip6Policy                          = PXEBC_IP6_POLICY_MAX;\r
-    Private->ProxyOffer.Dhcp6.Packet.Offer.Size = PXEBC_DHCP6_PACKET_MAX_SIZE;\r
-    Private->DhcpAck.Dhcp6.Packet.Ack.Size      = PXEBC_DHCP6_PACKET_MAX_SIZE;\r
-    Private->PxeReply.Dhcp6.Packet.Ack.Size     = PXEBC_DHCP6_PACKET_MAX_SIZE;\r
+    Private->ProxyOffer.Dhcp6.Packet.Offer.Size = PXEBC_CACHED_DHCP6_PACKET_MAX_SIZE;\r
+    Private->DhcpAck.Dhcp6.Packet.Ack.Size      = PXEBC_CACHED_DHCP6_PACKET_MAX_SIZE;\r
+    Private->PxeReply.Dhcp6.Packet.Ack.Size     = PXEBC_CACHED_DHCP6_PACKET_MAX_SIZE;\r
 \r
     for (Index = 0; Index < PXEBC_OFFER_MAX_NUM; Index++) {\r
 \r
     for (Index = 0; Index < PXEBC_OFFER_MAX_NUM; Index++) {\r
-      Private->OfferBuffer[Index].Dhcp6.Packet.Offer.Size = PXEBC_DHCP6_PACKET_MAX_SIZE;\r
+      Private->OfferBuffer[Index].Dhcp6.Packet.Offer.Size = PXEBC_CACHED_DHCP6_PACKET_MAX_SIZE;\r
     }\r
 \r
     //\r
     }\r
 \r
     //\r
@@ -148,18 +148,18 @@ EfiPxeBcStart (
     //\r
     // Configure block size for TFTP as a default value to handle all link layers.\r
     //\r
     //\r
     // Configure block size for TFTP as a default value to handle all link layers.\r
     //\r
-    Private->BlockSize = (UINTN) (Private->Ip4MaxPacketSize -\r
-                           PXEBC_DEFAULT_UDP_OVERHEAD_SIZE - PXEBC_DEFAULT_TFTP_OVERHEAD_SIZE);\r
+    Private->BlockSize = Private->Ip4MaxPacketSize -\r
+                           PXEBC_DEFAULT_UDP_OVERHEAD_SIZE - PXEBC_DEFAULT_TFTP_OVERHEAD_SIZE;\r
 \r
     //\r
     // PXE over IPv4 starts here, initialize the fields.\r
     //\r
 \r
     //\r
     // PXE over IPv4 starts here, initialize the fields.\r
     //\r
-    Private->ProxyOffer.Dhcp4.Packet.Offer.Size = PXEBC_DHCP4_PACKET_MAX_SIZE;\r
-    Private->DhcpAck.Dhcp4.Packet.Ack.Size      = PXEBC_DHCP4_PACKET_MAX_SIZE;\r
-    Private->PxeReply.Dhcp4.Packet.Ack.Size     = PXEBC_DHCP4_PACKET_MAX_SIZE;\r
+    Private->ProxyOffer.Dhcp4.Packet.Offer.Size = PXEBC_CACHED_DHCP4_PACKET_MAX_SIZE;\r
+    Private->DhcpAck.Dhcp4.Packet.Ack.Size      = PXEBC_CACHED_DHCP4_PACKET_MAX_SIZE;\r
+    Private->PxeReply.Dhcp4.Packet.Ack.Size     = PXEBC_CACHED_DHCP4_PACKET_MAX_SIZE;\r
 \r
     for (Index = 0; Index < PXEBC_OFFER_MAX_NUM; Index++) {\r
 \r
     for (Index = 0; Index < PXEBC_OFFER_MAX_NUM; Index++) {\r
-      Private->OfferBuffer[Index].Dhcp4.Packet.Offer.Size = PXEBC_DHCP4_PACKET_MAX_SIZE;\r
+      Private->OfferBuffer[Index].Dhcp4.Packet.Offer.Size = PXEBC_CACHED_DHCP4_PACKET_MAX_SIZE;\r
     }\r
 \r
     PxeBcSeedDhcp4Packet (&Private->SeedPacket, Private->Udp4Read);\r
     }\r
 \r
     PxeBcSeedDhcp4Packet (&Private->SeedPacket, Private->Udp4Read);\r
@@ -856,8 +856,7 @@ EfiPxeBcMtftp (
       (BufferSize == NULL) ||\r
       (ServerIp == NULL) ||\r
       ((BufferPtr == NULL) && DontUseBuffer) ||\r
       (BufferSize == NULL) ||\r
       (ServerIp == NULL) ||\r
       ((BufferPtr == NULL) && DontUseBuffer) ||\r
-      ((BlockSize != NULL) && (*BlockSize < PXE_MTFTP_DEFAULT_BLOCK_SIZE)) ||\r
-      (!NetIp4IsUnicast (NTOHL (ServerIp->Addr[0]), 0) && !NetIp6IsValidUnicast (&ServerIp->v6))) {\r
+      ((BlockSize != NULL) && (*BlockSize < PXE_MTFTP_DEFAULT_BLOCK_SIZE))) {\r
     return EFI_INVALID_PARAMETER;\r
   }\r
 \r
     return EFI_INVALID_PARAMETER;\r
   }\r
 \r
@@ -866,6 +865,16 @@ EfiPxeBcMtftp (
   Private   = PXEBC_PRIVATE_DATA_FROM_PXEBC (This);\r
   Mode      = Private->PxeBc.Mode;\r
 \r
   Private   = PXEBC_PRIVATE_DATA_FROM_PXEBC (This);\r
   Mode      = Private->PxeBc.Mode;\r
 \r
+  if (Mode->UsingIpv6) {\r
+    if (!NetIp6IsValidUnicast (&ServerIp->v6)) {\r
+      return EFI_INVALID_PARAMETER;\r
+    }\r
+  } else {\r
+    if (IP4_IS_UNSPECIFIED (NTOHL (ServerIp->Addr[0])) || IP4_IS_LOCAL_BROADCAST (NTOHL (ServerIp->Addr[0])))   {\r
+      return EFI_INVALID_PARAMETER;\r
+    }\r
+  }\r
+\r
   if (Mode->UsingIpv6) {\r
     //\r
     // Set configuration data for Mtftp6 instance.\r
   if (Mode->UsingIpv6) {\r
     //\r
     // Set configuration data for Mtftp6 instance.\r
@@ -1076,7 +1085,8 @@ EfiPxeBcUdpWrite (
     DoNotFragment = TRUE;\r
   }\r
 \r
     DoNotFragment = TRUE;\r
   }\r
 \r
-  if (!Mode->UsingIpv6 && GatewayIp != NULL && !NetIp4IsUnicast (NTOHL (GatewayIp->Addr[0]), 0)) {\r
+  if (!Mode->UsingIpv6 && GatewayIp != NULL && Mode->SubnetMask.Addr[0] != 0 && \r
+      !NetIp4IsUnicast (NTOHL (GatewayIp->Addr[0]), EFI_NTOHL(Mode->SubnetMask))) {\r
     //\r
     // Gateway is provided but it's not a unicast IPv4 address, while it will be ignored for IPv6.\r
     //\r
     //\r
     // Gateway is provided but it's not a unicast IPv4 address, while it will be ignored for IPv6.\r
     //\r
@@ -1125,7 +1135,9 @@ EfiPxeBcUdpWrite (
                &Private->SubnetMask.v4,\r
                &Private->GatewayIp.v4,\r
                &Private->CurSrcPort,\r
                &Private->SubnetMask.v4,\r
                &Private->GatewayIp.v4,\r
                &Private->CurSrcPort,\r
-               DoNotFragment\r
+               DoNotFragment,\r
+               Private->Mode.TTL,\r
+               Private->Mode.ToS\r
                );\r
   }\r
 \r
                );\r
   }\r
 \r
@@ -1585,13 +1597,16 @@ EfiPxeBcSetIpFilter (
       //\r
       return EFI_INVALID_PARAMETER;\r
     }\r
       //\r
       return EFI_INVALID_PARAMETER;\r
     }\r
-    if ((NewFilter->Filters & EFI_PXE_BASE_CODE_IP_FILTER_STATION_IP) != 0 &&\r
-        (NetIp4IsUnicast (EFI_IP4 (NewFilter->IpList[Index].v4), 0) ||\r
-         NetIp6IsValidUnicast (&NewFilter->IpList[Index].v6))) {\r
-      //\r
-      // If EFI_PXE_BASE_CODE_IP_FILTER_STATION_IP is set and IPv4/IPv6 address\r
-      // is in IpList, promiscuous mode is needed.\r
-      //\r
+    if (Mode->UsingIpv6) {\r
+      if ((NewFilter->Filters & EFI_PXE_BASE_CODE_IP_FILTER_STATION_IP) != 0 &&\r
+          NetIp6IsValidUnicast (&NewFilter->IpList[Index].v6)) {\r
+        NeedPromiscuous = TRUE;\r
+      }\r
+    } else 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.v4)) &&\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
       NeedPromiscuous = TRUE;\r
     }\r
   }\r
       NeedPromiscuous = TRUE;\r
     }\r
   }\r
@@ -1910,7 +1925,7 @@ EfiPxeBcSetParameters (
       // Update the previous PxeBcCallback protocol.\r
       //\r
       Status = gBS->HandleProtocol (\r
       // Update the previous PxeBcCallback protocol.\r
       //\r
       Status = gBS->HandleProtocol (\r
-                      Private->Controller,\r
+                      Mode->UsingIpv6 ? Private->Ip6Nic->Controller : Private->Ip4Nic->Controller,\r
                       &gEfiPxeBaseCodeCallbackProtocolGuid,\r
                       (VOID **) &Private->PxeBcCallback\r
                       );\r
                       &gEfiPxeBaseCodeCallbackProtocolGuid,\r
                       (VOID **) &Private->PxeBcCallback\r
                       );\r
@@ -1985,9 +2000,7 @@ EfiPxeBcSetStationIP (
     return EFI_INVALID_PARAMETER;\r
   }\r
 \r
     return EFI_INVALID_PARAMETER;\r
   }\r
 \r
-  if (NewStationIp != NULL &&\r
-      (!NetIp4IsUnicast (NTOHL (NewStationIp->Addr[0]), 0) &&\r
-       !NetIp6IsValidUnicast (&NewStationIp->v6))) {\r
+  if (NewStationIp != NULL && !NetIp6IsValidUnicast (&NewStationIp->v6)) {\r
     return EFI_INVALID_PARAMETER;\r
   }\r
 \r
     return EFI_INVALID_PARAMETER;\r
   }\r
 \r
@@ -2001,6 +2014,14 @@ EfiPxeBcSetStationIP (
     return EFI_INVALID_PARAMETER;\r
   }\r
 \r
     return EFI_INVALID_PARAMETER;\r
   }\r
 \r
+  if (!Mode->UsingIpv6 && NewStationIp != NULL) {\r
+    if (IP4_IS_UNSPECIFIED(NTOHL (NewStationIp->Addr[0])) || \r
+        IP4_IS_LOCAL_BROADCAST(NTOHL (NewStationIp->Addr[0])) ||\r
+        (NewSubnetMask != NULL && NewSubnetMask->Addr[0] != 0 && !NetIp4IsUnicast (NTOHL (NewStationIp->Addr[0]), NTOHL (NewSubnetMask->Addr[0])))) {\r
+      return EFI_INVALID_PARAMETER;\r
+    }\r
+  }\r
+  \r
   if (!Mode->Started) {\r
     return EFI_NOT_STARTED;\r
   }\r
   if (!Mode->Started) {\r
     return EFI_NOT_STARTED;\r
   }\r
@@ -2326,8 +2347,12 @@ EfiPxeLoadFile (
   EFI_PXE_BASE_CODE_PROTOCOL  *PxeBc;\r
   BOOLEAN                     UsingIpv6;\r
   EFI_STATUS                  Status;\r
   EFI_PXE_BASE_CODE_PROTOCOL  *PxeBc;\r
   BOOLEAN                     UsingIpv6;\r
   EFI_STATUS                  Status;\r
-  BOOLEAN                     MediaPresent;\r
+  EFI_STATUS                  MediaStatus;\r
 \r
 \r
+  if (FilePath == NULL || !IsDevicePathEnd (FilePath)) {\r
+    return EFI_INVALID_PARAMETER;\r
+  }\r
+  \r
   VirtualNic = PXEBC_VIRTUAL_NIC_FROM_LOADFILE (This);\r
   Private    = VirtualNic->Private;\r
   PxeBc      = &Private->PxeBc;\r
   VirtualNic = PXEBC_VIRTUAL_NIC_FROM_LOADFILE (This);\r
   Private    = VirtualNic->Private;\r
   PxeBc      = &Private->PxeBc;\r
@@ -2348,9 +2373,9 @@ EfiPxeLoadFile (
   //\r
   // Check media status before PXE start\r
   //\r
   //\r
   // Check media status before PXE start\r
   //\r
-  MediaPresent = TRUE;\r
-  NetLibDetectMedia (Private->Controller, &MediaPresent);\r
-  if (!MediaPresent) {\r
+  MediaStatus = EFI_SUCCESS;\r
+  NetLibDetectMediaWaitTimeout (Private->Controller, PXEBC_CHECK_MEDIA_WAITING_TIME, &MediaStatus);\r
+  if (MediaStatus != EFI_SUCCESS) {\r
     return EFI_NO_MEDIA;\r
   }\r
 \r
     return EFI_NO_MEDIA;\r
   }\r
 \r
@@ -2388,6 +2413,16 @@ EfiPxeLoadFile (
     //   3. unsupported.\r
     //\r
     PxeBc->Stop (PxeBc);\r
     //   3. unsupported.\r
     //\r
     PxeBc->Stop (PxeBc);\r
+  } else {\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 these programs which \r
+    // also need to use DHCP4 will be impacted.\r
+    //\r
+    if (!PxeBc->Mode->UsingIpv6) {\r
+      Private->Dhcp4->Stop (Private->Dhcp4);\r
+      Private->Dhcp4->Configure (Private->Dhcp4, NULL);\r
+    }\r
   }\r
 \r
   return Status;\r
   }\r
 \r
   return Status;\r