]> git.proxmox.com Git - mirror_edk2.git/blobdiff - NetworkPkg/UefiPxeBcDxe/PxeBcDhcp4.c
NetworkPkg: Add warning message for PXE if failed to read system GUID from SMBIOS.
[mirror_edk2.git] / NetworkPkg / UefiPxeBcDxe / PxeBcDhcp4.c
index 44b07143934dfdce53716f522b784629e4db4bd5..bb65445fc9f0f3b95b6285ea9bfb0a46579f927f 100644 (file)
@@ -1,7 +1,7 @@
 /** @file\r
   Functions implementation related with DHCPv4 for UefiPxeBc Driver.\r
 \r
-  Copyright (c) 2009 - 2016, Intel Corporation. All rights reserved.<BR>\r
+  Copyright (c) 2009 - 2018, 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
@@ -320,6 +320,7 @@ PxeBcBuildDhcp4Options (
     //\r
     // Zero the Guid to indicate NOT programable if failed to get system Guid.\r
     //\r
+    DEBUG ((EFI_D_WARN, "PXE: Failed to read system GUID from the smbios table!\n"));\r
     ZeroMem (OptEnt.Uuid->Guid, sizeof (EFI_GUID));\r
   }\r
 \r
@@ -424,17 +425,24 @@ PxeBcSeedDhcp4Packet (
   @param[in]  Dst          Pointer to the cache buffer for DHCPv4 packet.\r
   @param[in]  Src          Pointer to the DHCPv4 packet to be cached.\r
 \r
+  @retval     EFI_SUCCESS                Packet is copied.\r
+  @retval     EFI_BUFFER_TOO_SMALL       Cache buffer is not big enough to hold the packet.\r
+\r
 **/\r
-VOID\r
+EFI_STATUS\r
 PxeBcCacheDhcp4Packet (\r
   IN EFI_DHCP4_PACKET     *Dst,\r
   IN EFI_DHCP4_PACKET     *Src\r
   )\r
 {\r
-  ASSERT (Dst->Size >= Src->Length);\r
-\r
+  if (Dst->Size < Src->Length) {\r
+    return EFI_BUFFER_TOO_SMALL;\r
+  }\r
+  \r
   CopyMem (&Dst->Dhcp4, &Src->Dhcp4, Src->Length);\r
   Dst->Length = Src->Length;\r
+\r
+  return EFI_SUCCESS;\r
 }\r
 \r
 \r
@@ -620,8 +628,11 @@ PxeBcParseDhcp4Packet (
   @param[in]  Ack                 Pointer to the DHCPv4 ack packet.\r
   @param[in]  Verified            If TRUE, parse the ACK packet and store info into mode data.\r
 \r
+  @retval     EFI_SUCCESS                Cache and parse the packet successfully.\r
+  @retval     EFI_BUFFER_TOO_SMALL       Cache buffer is not big enough to hold the packet.\r
+\r
 **/\r
-VOID\r
+EFI_STATUS\r
 PxeBcCopyDhcp4Ack (\r
   IN PXEBC_PRIVATE_DATA   *Private,\r
   IN EFI_DHCP4_PACKET     *Ack,\r
@@ -629,10 +640,14 @@ PxeBcCopyDhcp4Ack (
   )\r
 {\r
   EFI_PXE_BASE_CODE_MODE  *Mode;\r
+  EFI_STATUS              Status;\r
 \r
   Mode = Private->PxeBc.Mode;\r
 \r
-  PxeBcCacheDhcp4Packet (&Private->DhcpAck.Dhcp4.Packet.Ack, Ack);\r
+  Status = PxeBcCacheDhcp4Packet (&Private->DhcpAck.Dhcp4.Packet.Ack, Ack);\r
+  if (EFI_ERROR (Status)) {\r
+    return Status;\r
+  }\r
 \r
   if (Verified) {\r
     //\r
@@ -642,6 +657,8 @@ PxeBcCopyDhcp4Ack (
     CopyMem (&Mode->DhcpAck.Dhcpv4, &Ack->Dhcp4, Ack->Length);\r
     Mode->DhcpAckReceived = TRUE;\r
   }\r
+  \r
+  return EFI_SUCCESS;\r
 }\r
 \r
 \r
@@ -651,8 +668,11 @@ PxeBcCopyDhcp4Ack (
   @param[in]  Private               Pointer to PxeBc private data.\r
   @param[in]  OfferIndex            The received order of offer packets.\r
 \r
+  @retval     EFI_SUCCESS                Cache and parse the packet successfully.\r
+  @retval     EFI_BUFFER_TOO_SMALL       Cache buffer is not big enough to hold the packet.\r
+\r
 **/\r
-VOID\r
+EFI_STATUS\r
 PxeBcCopyProxyOffer (\r
   IN PXEBC_PRIVATE_DATA   *Private,\r
   IN UINT32               OfferIndex\r
@@ -660,6 +680,7 @@ PxeBcCopyProxyOffer (
 {\r
   EFI_PXE_BASE_CODE_MODE  *Mode;\r
   EFI_DHCP4_PACKET        *Offer;\r
+  EFI_STATUS              Status;\r
 \r
   ASSERT (OfferIndex < Private->OfferNum);\r
   ASSERT (OfferIndex < PXEBC_OFFER_MAX_NUM);\r
@@ -670,7 +691,11 @@ PxeBcCopyProxyOffer (
   //\r
   // Cache the proxy offer packet and parse it.\r
   //\r
-  PxeBcCacheDhcp4Packet (&Private->ProxyOffer.Dhcp4.Packet.Offer, Offer);\r
+  Status = PxeBcCacheDhcp4Packet (&Private->ProxyOffer.Dhcp4.Packet.Offer, Offer);\r
+  if (EFI_ERROR(Status)) {\r
+    return Status;\r
+  }\r
+  \r
   PxeBcParseDhcp4Packet (&Private->ProxyOffer.Dhcp4);\r
 \r
   //\r
@@ -678,6 +703,8 @@ PxeBcCopyProxyOffer (
   //\r
   CopyMem (&Mode->ProxyOffer.Dhcpv4, &Offer->Dhcp4, Offer->Length);\r
   Mode->ProxyOfferReceived = TRUE;\r
+\r
+  return EFI_SUCCESS;\r
 }\r
 \r
 \r
@@ -780,8 +807,11 @@ PxeBcRetryBinlOffer (
   @param[in]  Private               Pointer to PxeBc private data.\r
   @param[in]  RcvdOffer             Pointer to the received offer packet.\r
 \r
+  @retval     EFI_SUCCESS      Cache and parse the packet successfully.\r
+  @retval     Others           Operation failed.\r
+\r
 **/\r
-VOID\r
+EFI_STATUS\r
 PxeBcCacheDhcp4Offer (\r
   IN PXEBC_PRIVATE_DATA     *Private,\r
   IN EFI_DHCP4_PACKET       *RcvdOffer\r
@@ -790,6 +820,7 @@ PxeBcCacheDhcp4Offer (
   PXEBC_DHCP4_PACKET_CACHE  *Cache4;\r
   EFI_DHCP4_PACKET          *Offer;\r
   PXEBC_OFFER_TYPE          OfferType;\r
+  EFI_STATUS                Status;\r
 \r
   ASSERT (Private->OfferNum < PXEBC_OFFER_MAX_NUM);\r
   Cache4 = &Private->OfferBuffer[Private->OfferNum].Dhcp4;\r
@@ -798,13 +829,16 @@ PxeBcCacheDhcp4Offer (
   //\r
   // Cache the content of DHCPv4 packet firstly.\r
   //\r
-  PxeBcCacheDhcp4Packet (Offer, RcvdOffer);\r
+  Status = PxeBcCacheDhcp4Packet (Offer, RcvdOffer);\r
+  if (EFI_ERROR(Status)) {\r
+    return Status;\r
+  }\r
 \r
   //\r
   // Validate the DHCPv4 packet, and parse the options and offer type.\r
   //\r
   if (EFI_ERROR (PxeBcParseDhcp4Packet (Cache4))) {\r
-    return;\r
+    return EFI_ABORTED;\r
   }\r
 \r
   //\r
@@ -821,7 +855,7 @@ PxeBcCacheDhcp4Offer (
       Private->OfferIndex[OfferType][0] = Private->OfferNum;\r
       Private->OfferCount[OfferType]    = 1;\r
     } else {\r
-      return;\r
+      return EFI_ABORTED;\r
     }\r
   } else {\r
     ASSERT (Private->OfferCount[OfferType] < PXEBC_OFFER_MAX_NUM);\r
@@ -837,14 +871,15 @@ PxeBcCacheDhcp4Offer (
         //\r
         Private->OfferIndex[OfferType][Private->OfferCount[OfferType]] = Private->OfferNum;\r
         Private->OfferCount[OfferType]++;\r
-      } else if (Private->OfferCount[OfferType] > 0) {\r
+      } else if ((OfferType == PxeOfferTypeProxyPxe10 || OfferType == PxeOfferTypeProxyWfm11a) && \r
+                 Private->OfferCount[OfferType] < 1) {\r
         //\r
         // Only cache the first PXE10/WFM11a offer, and discard the others.\r
         //\r
         Private->OfferIndex[OfferType][0] = Private->OfferNum;\r
         Private->OfferCount[OfferType]    = 1;\r
       } else {\r
-        return ;\r
+        return EFI_ABORTED;\r
       }\r
     } else {\r
       //\r
@@ -856,6 +891,8 @@ PxeBcCacheDhcp4Offer (
   }\r
 \r
   Private->OfferNum++;\r
+\r
+  return EFI_SUCCESS;\r
 }\r
 \r
 \r
@@ -980,11 +1017,12 @@ PxeBcSelectDhcp4Offer (
 /**\r
   Handle the DHCPv4 offer packet.\r
 \r
-  @param[in]  Private             Pointer to PxeBc private data.\r
+  @param[in]  Private               Pointer to PxeBc private data.\r
 \r
-  @retval     EFI_SUCCESS         Handled the DHCPv4 offer packet successfully.\r
-  @retval     EFI_NO_RESPONSE     No response to the following request packet.\r
-  @retval     EFI_NOT_FOUND       No boot filename received.\r
+  @retval     EFI_SUCCESS           Handled the DHCPv4 offer packet successfully.\r
+  @retval     EFI_NO_RESPONSE       No response to the following request packet.\r
+  @retval     EFI_NOT_FOUND         No boot filename received.\r
+  @retval     EFI_BUFFER_TOO_SMALL  Can't cache the offer pacet.\r
 \r
 **/\r
 EFI_STATUS\r
@@ -1089,7 +1127,7 @@ PxeBcHandleDhcp4Offer (
         //\r
         // Success to try to request by a ProxyPxe10 or ProxyWfm11a offer, copy and parse it.\r
         //\r
-        PxeBcCopyProxyOffer (Private, ProxyIndex);\r
+        Status = PxeBcCopyProxyOffer (Private, ProxyIndex);\r
       }\r
     } else {\r
       //\r
@@ -1116,7 +1154,10 @@ PxeBcHandleDhcp4Offer (
       Ack = Offer;\r
     }\r
 \r
-    PxeBcCopyDhcp4Ack (Private, Ack, TRUE);\r
+    Status = PxeBcCopyDhcp4Ack (Private, Ack, TRUE);\r
+    if (EFI_ERROR (Status)) {\r
+      return Status;\r
+    }\r
     Mode->DhcpDiscoverValid = TRUE;\r
   }\r
 \r
@@ -1170,6 +1211,8 @@ PxeBcDhcp4CallBack (
     return EFI_SUCCESS;\r
   }\r
 \r
+  ASSERT (Packet != NULL);\r
+\r
   Private   = (PXEBC_PRIVATE_DATA *) Context;\r
   Mode      = Private->PxeBc.Mode;\r
   Callback  = Private->PxeBcCallback;\r
@@ -1240,6 +1283,7 @@ PxeBcDhcp4CallBack (
         //\r
         // Zero the Guid to indicate NOT programable if failed to get system Guid.\r
         //\r
+        DEBUG ((EFI_D_WARN, "PXE: Failed to read system GUID from the smbios table!\n"));\r
         ZeroMem (Packet->Dhcp4.Header.ClientHwAddr, sizeof (EFI_GUID));\r
       }\r
       Packet->Dhcp4.Header.HwAddrLen = (UINT8) sizeof (EFI_GUID);\r
@@ -1258,12 +1302,15 @@ PxeBcDhcp4CallBack (
       //\r
       // Cache the DHCPv4 offers to OfferBuffer[] for select later, and record\r
       // the OfferIndex and OfferCount.\r
+      // If error happens, just ignore this packet and continue to wait more offer.\r
       //\r
       PxeBcCacheDhcp4Offer (Private, Packet);\r
     }\r
     break;\r
 \r
   case Dhcp4SelectOffer:\r
+    ASSERT (NewPacket != NULL);\r
+    \r
     //\r
     // Select offer by the default policy or by order, and record the SelectIndex\r
     // and SelectProxyType.\r
@@ -1278,21 +1325,16 @@ PxeBcDhcp4CallBack (
     break;\r
 \r
   case Dhcp4RcvdAck:\r
-    if (Packet->Length > PXEBC_DHCP4_PACKET_MAX_SIZE) {\r
-      //\r
-      // Abort the DHCP if the ACK packet exceeds the maximum length.\r
-      //\r
-         Status = EFI_ABORTED;\r
-         break;\r
-    }\r
-\r
     //\r
     // Cache the DHCPv4 ack to Private->Dhcp4Ack, but it's not the final ack in mode data\r
     // without verification.\r
     //\r
     ASSERT (Private->SelectIndex != 0);\r
 \r
-    PxeBcCopyDhcp4Ack (Private, Packet, FALSE);\r
+    Status = PxeBcCopyDhcp4Ack (Private, Packet, FALSE);\r
+    if (EFI_ERROR (Status)) {\r
+      Status = EFI_ABORTED;\r
+    }\r
     break;\r
 \r
   default:\r
@@ -1430,6 +1472,7 @@ PxeBcDhcp4Discover (
       //\r
       // Zero the Guid to indicate NOT programable if failed to get system Guid.\r
       //\r
+      DEBUG ((EFI_D_WARN, "PXE: Failed to read system GUID from the smbios table!\n"));\r
       ZeroMem (Token.Packet->Dhcp4.Header.ClientHwAddr, sizeof (EFI_GUID));\r
     }\r
     Token.Packet->Dhcp4.Header.HwAddrLen = (UINT8)  sizeof (EFI_GUID);\r
@@ -1491,6 +1534,12 @@ PxeBcDhcp4Discover (
     // Find the right PXE Reply according to server address.\r
     //\r
     while (RepIndex < Token.ResponseCount) {\r
+      if (Response->Length > PXEBC_DHCP4_PACKET_MAX_SIZE) {\r
+        SrvIndex = 0;\r
+        RepIndex++;\r
+        Response = (EFI_DHCP4_PACKET *) ((UINT8 *) Response + Response->Size);\r
+        continue;\r
+      }\r
 \r
       while (SrvIndex < IpCount) {\r
         if (SrvList[SrvIndex].AcceptAnyResponse) {\r
@@ -1509,7 +1558,6 @@ PxeBcDhcp4Discover (
 \r
       SrvIndex = 0;\r
       RepIndex++;\r
-\r
       Response = (EFI_DHCP4_PACKET *) ((UINT8 *) Response + Response->Size);\r
     }\r
 \r
@@ -1519,10 +1567,16 @@ PxeBcDhcp4Discover (
       // Especially for PXE discover packet, store it into mode data here.\r
       //\r
       if (Private->IsDoDiscover) {\r
-        PxeBcCacheDhcp4Packet (&Private->PxeReply.Dhcp4.Packet.Ack, Response);\r
+        Status = PxeBcCacheDhcp4Packet (&Private->PxeReply.Dhcp4.Packet.Ack, Response);\r
+        if (EFI_ERROR(Status)) {\r
+          goto ON_EXIT;\r
+        }\r
         CopyMem (&Mode->PxeDiscover, &Token.Packet->Dhcp4, Token.Packet->Length);\r
       } else {\r
-        PxeBcCacheDhcp4Packet (&Private->ProxyOffer.Dhcp4.Packet.Offer, Response);\r
+        Status = PxeBcCacheDhcp4Packet (&Private->ProxyOffer.Dhcp4.Packet.Offer, Response);\r
+        if (EFI_ERROR(Status)) {\r
+          goto ON_EXIT;\r
+        }\r
       }\r
     } else {\r
       //\r
@@ -1530,12 +1584,15 @@ PxeBcDhcp4Discover (
       //\r
       Status = EFI_NOT_FOUND;\r
     }\r
-    if (Token.ResponseList != NULL) {\r
-      FreePool (Token.ResponseList);\r
-    }\r
   }\r
-\r
-  FreePool (Token.Packet);\r
+ON_EXIT:\r
+  \r
+  if (Token.ResponseList != NULL) {\r
+    FreePool (Token.ResponseList);\r
+  }\r
+  if (Token.Packet != NULL) {\r
+    FreePool (Token.Packet);\r
+  }\r
   return Status;\r
 }\r
 \r
@@ -1647,16 +1704,16 @@ PxeBcDhcp4Dora (
   ZeroMem (Private->OfferCount, sizeof (Private->OfferCount));\r
   ZeroMem (Private->OfferIndex, sizeof (Private->OfferIndex));\r
 \r
-  //\r
-  // Start DHCPv4 D.O.R.A. process to acquire IPv4 address. This may \r
-  // have already been done, thus do not leave in error if the return\r
-  // code is EFI_ALREADY_STARTED.\r
-  //\r
   Status = Dhcp4->Start (Dhcp4, NULL);\r
-  if (EFI_ERROR (Status) && Status != EFI_ALREADY_STARTED) {\r
+  if (EFI_ERROR (Status)) {\r
     if (Status == EFI_ICMP_ERROR) {\r
       PxeMode->IcmpErrorReceived = TRUE;\r
     }\r
+\r
+    if (Status == EFI_TIMEOUT && Private->OfferNum > 0) {\r
+      Status = EFI_NO_RESPONSE;\r
+    }\r
+    \r
     goto ON_EXIT;\r
   }\r
 \r