]> 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 23682b2451857bb4dc93cda3f268316858b5eb85..bb65445fc9f0f3b95b6285ea9bfb0a46579f927f 100644 (file)
@@ -1,7 +1,7 @@
 /** @file\r
   Functions implementation related with DHCPv4 for UefiPxeBc Driver.\r
 \r
 /** @file\r
   Functions implementation related with DHCPv4 for UefiPxeBc Driver.\r
 \r
-  Copyright (c) 2009 - 2012, 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
 \r
   This program and the accompanying materials\r
   are licensed and made available under the terms and conditions of the BSD License\r
 // This is a map from the interested DHCP4 option tags' index to the tag value.\r
 //\r
 UINT8 mInterestedDhcp4Tags[PXEBC_DHCP4_TAG_INDEX_MAX] = {\r
 // This is a map from the interested DHCP4 option tags' index to the tag value.\r
 //\r
 UINT8 mInterestedDhcp4Tags[PXEBC_DHCP4_TAG_INDEX_MAX] = {\r
-  PXEBC_DHCP4_TAG_BOOTFILE_LEN,\r
-  PXEBC_DHCP4_TAG_VENDOR,\r
-  PXEBC_DHCP4_TAG_OVERLOAD,\r
-  PXEBC_DHCP4_TAG_MSG_TYPE,\r
-  PXEBC_DHCP4_TAG_SERVER_ID,\r
-  PXEBC_DHCP4_TAG_CLASS_ID,\r
-  PXEBC_DHCP4_TAG_BOOTFILE\r
+  DHCP4_TAG_BOOTFILE_LEN,\r
+  DHCP4_TAG_VENDOR,\r
+  DHCP4_TAG_OVERLOAD,\r
+  DHCP4_TAG_MSG_TYPE,\r
+  DHCP4_TAG_SERVER_ID,\r
+  DHCP4_TAG_VENDOR_CLASS_ID,\r
+  DHCP4_TAG_BOOTFILE\r
 };\r
 \r
 //\r
 };\r
 \r
 //\r
@@ -58,7 +58,7 @@ PxeBcParseDhcp4Options (
   Option  = (EFI_DHCP4_PACKET_OPTION *) Buffer;\r
   Offset  = 0;\r
 \r
   Option  = (EFI_DHCP4_PACKET_OPTION *) Buffer;\r
   Offset  = 0;\r
 \r
-  while (Offset < Length && Option->OpCode != PXEBC_DHCP4_TAG_EOP) {\r
+  while (Offset < Length && Option->OpCode != DHCP4_TAG_EOP) {\r
 \r
     if (Option->OpCode == OptTag) {\r
       //\r
 \r
     if (Option->OpCode == OptTag) {\r
       //\r
@@ -70,7 +70,7 @@ PxeBcParseDhcp4Options (
     //\r
     // Skip the current option to the next.\r
     //\r
     //\r
     // Skip the current option to the next.\r
     //\r
-    if (Option->OpCode == PXEBC_DHCP4_TAG_PAD) {\r
+    if (Option->OpCode == DHCP4_TAG_PAD) {\r
       Offset++;\r
     } else {\r
       Offset += Option->Length + 2;\r
       Offset++;\r
     } else {\r
       Offset += Option->Length + 2;\r
@@ -108,7 +108,7 @@ PxeBcParseVendorOptions (
 \r
   ASSERT (PxeOption != NULL);\r
 \r
 \r
   ASSERT (PxeOption != NULL);\r
 \r
-  while ((Offset < VendorOptionLen) && (PxeOption->OpCode != PXEBC_DHCP4_TAG_EOP)) {\r
+  while ((Offset < VendorOptionLen) && (PxeOption->OpCode != DHCP4_TAG_EOP)) {\r
     //\r
     // Parse all the interesting PXE vendor options one by one.\r
     //\r
     //\r
     // Parse all the interesting PXE vendor options one by one.\r
     //\r
@@ -201,7 +201,7 @@ PxeBcParseVendorOptions (
     //\r
     // Continue to the next option.\r
     //\r
     //\r
     // Continue to the next option.\r
     //\r
-    if (PxeOption->OpCode == PXEBC_DHCP4_TAG_PAD) {\r
+    if (PxeOption->OpCode == DHCP4_TAG_PAD) {\r
       Offset++;\r
     } else {\r
       Offset = (UINT8) (Offset + PxeOption->Length + 2);\r
       Offset++;\r
     } else {\r
       Offset = (UINT8) (Offset + PxeOption->Length + 2);\r
@@ -243,7 +243,7 @@ PxeBcBuildDhcp4Options (
     //\r
     // Append message type.\r
     //\r
     //\r
     // Append message type.\r
     //\r
-    OptList[Index]->OpCode  = PXEBC_DHCP4_TAG_MSG_TYPE;\r
+    OptList[Index]->OpCode  = DHCP4_TAG_MSG_TYPE;\r
     OptList[Index]->Length  = 1;\r
     OptEnt.Mesg             = (PXEBC_DHCP4_OPTION_MESG *) OptList[Index]->Data;\r
     OptEnt.Mesg->Type       = PXEBC_DHCP4_MSG_TYPE_REQUEST;\r
     OptList[Index]->Length  = 1;\r
     OptEnt.Mesg             = (PXEBC_DHCP4_OPTION_MESG *) OptList[Index]->Data;\r
     OptEnt.Mesg->Type       = PXEBC_DHCP4_MSG_TYPE_REQUEST;\r
@@ -253,10 +253,10 @@ PxeBcBuildDhcp4Options (
     //\r
     // Append max message size.\r
     //\r
     //\r
     // Append max message size.\r
     //\r
-    OptList[Index]->OpCode  = PXEBC_DHCP4_TAG_MAXMSG;\r
+    OptList[Index]->OpCode  = DHCP4_TAG_MAXMSG;\r
     OptList[Index]->Length  = (UINT8) sizeof (PXEBC_DHCP4_OPTION_MAX_MESG_SIZE);\r
     OptEnt.MaxMesgSize      = (PXEBC_DHCP4_OPTION_MAX_MESG_SIZE *) OptList[Index]->Data;\r
     OptList[Index]->Length  = (UINT8) sizeof (PXEBC_DHCP4_OPTION_MAX_MESG_SIZE);\r
     OptEnt.MaxMesgSize      = (PXEBC_DHCP4_OPTION_MAX_MESG_SIZE *) OptList[Index]->Data;\r
-    Value                   = NTOHS (PXEBC_DHCP4_PACKET_MAX_SIZE - 8);\r
+    Value                   = NTOHS (PXEBC_DHCP4_PACKET_MAX_SIZE);\r
     CopyMem (&OptEnt.MaxMesgSize->Size, &Value, sizeof (UINT16));\r
     Index++;\r
     OptList[Index]          = GET_NEXT_DHCP_OPTION (OptList[Index - 1]);\r
     CopyMem (&OptEnt.MaxMesgSize->Size, &Value, sizeof (UINT16));\r
     Index++;\r
     OptList[Index]          = GET_NEXT_DHCP_OPTION (OptList[Index - 1]);\r
@@ -265,36 +265,36 @@ PxeBcBuildDhcp4Options (
   //\r
   // Append parameter request list option.\r
   //\r
   //\r
   // Append parameter request list option.\r
   //\r
-  OptList[Index]->OpCode    = PXEBC_DHCP4_TAG_PARA_LIST;\r
+  OptList[Index]->OpCode    = DHCP4_TAG_PARA_LIST;\r
   OptList[Index]->Length    = 35;\r
   OptEnt.Para               = (PXEBC_DHCP4_OPTION_PARA *) OptList[Index]->Data;\r
   OptList[Index]->Length    = 35;\r
   OptEnt.Para               = (PXEBC_DHCP4_OPTION_PARA *) OptList[Index]->Data;\r
-  OptEnt.Para->ParaList[0]  = PXEBC_DHCP4_TAG_NETMASK;\r
-  OptEnt.Para->ParaList[1]  = PXEBC_DHCP4_TAG_TIME_OFFSET;\r
-  OptEnt.Para->ParaList[2]  = PXEBC_DHCP4_TAG_ROUTER;\r
-  OptEnt.Para->ParaList[3]  = PXEBC_DHCP4_TAG_TIME_SERVER;\r
-  OptEnt.Para->ParaList[4]  = PXEBC_DHCP4_TAG_NAME_SERVER;\r
-  OptEnt.Para->ParaList[5]  = PXEBC_DHCP4_TAG_DNS_SERVER;\r
-  OptEnt.Para->ParaList[6]  = PXEBC_DHCP4_TAG_HOSTNAME;\r
-  OptEnt.Para->ParaList[7]  = PXEBC_DHCP4_TAG_BOOTFILE_LEN;\r
-  OptEnt.Para->ParaList[8]  = PXEBC_DHCP4_TAG_DOMAINNAME;\r
-  OptEnt.Para->ParaList[9]  = PXEBC_DHCP4_TAG_ROOTPATH;\r
-  OptEnt.Para->ParaList[10] = PXEBC_DHCP4_TAG_EXTEND_PATH;\r
-  OptEnt.Para->ParaList[11] = PXEBC_DHCP4_TAG_EMTU;\r
-  OptEnt.Para->ParaList[12] = PXEBC_DHCP4_TAG_TTL;\r
-  OptEnt.Para->ParaList[13] = PXEBC_DHCP4_TAG_BROADCAST;\r
-  OptEnt.Para->ParaList[14] = PXEBC_DHCP4_TAG_NIS_DOMAIN;\r
-  OptEnt.Para->ParaList[15] = PXEBC_DHCP4_TAG_NIS_SERVER;\r
-  OptEnt.Para->ParaList[16] = PXEBC_DHCP4_TAG_NTP_SERVER;\r
-  OptEnt.Para->ParaList[17] = PXEBC_DHCP4_TAG_VENDOR;\r
-  OptEnt.Para->ParaList[18] = PXEBC_DHCP4_TAG_REQUEST_IP;\r
-  OptEnt.Para->ParaList[19] = PXEBC_DHCP4_TAG_LEASE;\r
-  OptEnt.Para->ParaList[20] = PXEBC_DHCP4_TAG_SERVER_ID;\r
-  OptEnt.Para->ParaList[21] = PXEBC_DHCP4_TAG_T1;\r
-  OptEnt.Para->ParaList[22] = PXEBC_DHCP4_TAG_T2;\r
-  OptEnt.Para->ParaList[23] = PXEBC_DHCP4_TAG_CLASS_ID;\r
-  OptEnt.Para->ParaList[24] = PXEBC_DHCP4_TAG_TFTP;\r
-  OptEnt.Para->ParaList[25] = PXEBC_DHCP4_TAG_BOOTFILE;\r
-  OptEnt.Para->ParaList[26] = PXEBC_PXE_DHCP4_TAG_UUID;\r
+  OptEnt.Para->ParaList[0]  = DHCP4_TAG_NETMASK;\r
+  OptEnt.Para->ParaList[1]  = DHCP4_TAG_TIME_OFFSET;\r
+  OptEnt.Para->ParaList[2]  = DHCP4_TAG_ROUTER;\r
+  OptEnt.Para->ParaList[3]  = DHCP4_TAG_TIME_SERVER;\r
+  OptEnt.Para->ParaList[4]  = DHCP4_TAG_NAME_SERVER;\r
+  OptEnt.Para->ParaList[5]  = DHCP4_TAG_DNS_SERVER;\r
+  OptEnt.Para->ParaList[6]  = DHCP4_TAG_HOSTNAME;\r
+  OptEnt.Para->ParaList[7]  = DHCP4_TAG_BOOTFILE_LEN;\r
+  OptEnt.Para->ParaList[8]  = DHCP4_TAG_DOMAINNAME;\r
+  OptEnt.Para->ParaList[9]  = DHCP4_TAG_ROOTPATH;\r
+  OptEnt.Para->ParaList[10] = DHCP4_TAG_EXTEND_PATH;\r
+  OptEnt.Para->ParaList[11] = DHCP4_TAG_EMTU;\r
+  OptEnt.Para->ParaList[12] = DHCP4_TAG_TTL;\r
+  OptEnt.Para->ParaList[13] = DHCP4_TAG_BROADCAST;\r
+  OptEnt.Para->ParaList[14] = DHCP4_TAG_NIS_DOMAIN;\r
+  OptEnt.Para->ParaList[15] = DHCP4_TAG_NIS_SERVER;\r
+  OptEnt.Para->ParaList[16] = DHCP4_TAG_NTP_SERVER;\r
+  OptEnt.Para->ParaList[17] = DHCP4_TAG_VENDOR;\r
+  OptEnt.Para->ParaList[18] = DHCP4_TAG_REQUEST_IP;\r
+  OptEnt.Para->ParaList[19] = DHCP4_TAG_LEASE;\r
+  OptEnt.Para->ParaList[20] = DHCP4_TAG_SERVER_ID;\r
+  OptEnt.Para->ParaList[21] = DHCP4_TAG_T1;\r
+  OptEnt.Para->ParaList[22] = DHCP4_TAG_T2;\r
+  OptEnt.Para->ParaList[23] = DHCP4_TAG_VENDOR_CLASS_ID;\r
+  OptEnt.Para->ParaList[24] = DHCP4_TAG_TFTP;\r
+  OptEnt.Para->ParaList[25] = DHCP4_TAG_BOOTFILE;\r
+  OptEnt.Para->ParaList[26] = DHCP4_TAG_UUID;\r
   OptEnt.Para->ParaList[27] = 0x80;\r
   OptEnt.Para->ParaList[28] = 0x81;\r
   OptEnt.Para->ParaList[29] = 0x82;\r
   OptEnt.Para->ParaList[27] = 0x80;\r
   OptEnt.Para->ParaList[28] = 0x81;\r
   OptEnt.Para->ParaList[29] = 0x82;\r
@@ -309,7 +309,7 @@ PxeBcBuildDhcp4Options (
   //\r
   // Append UUID/Guid-based client identifier option\r
   //\r
   //\r
   // Append UUID/Guid-based client identifier option\r
   //\r
-  OptList[Index]->OpCode  = PXEBC_PXE_DHCP4_TAG_UUID;\r
+  OptList[Index]->OpCode  = DHCP4_TAG_UUID;\r
   OptList[Index]->Length  = (UINT8) sizeof (PXEBC_DHCP4_OPTION_UUID);\r
   OptEnt.Uuid             = (PXEBC_DHCP4_OPTION_UUID *) OptList[Index]->Data;\r
   OptEnt.Uuid->Type       = 0;\r
   OptList[Index]->Length  = (UINT8) sizeof (PXEBC_DHCP4_OPTION_UUID);\r
   OptEnt.Uuid             = (PXEBC_DHCP4_OPTION_UUID *) OptList[Index]->Data;\r
   OptEnt.Uuid->Type       = 0;\r
@@ -320,13 +320,14 @@ PxeBcBuildDhcp4Options (
     //\r
     // Zero the Guid to indicate NOT programable if failed to get system Guid.\r
     //\r
     //\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
   //\r
   // Append client network device interface option\r
   //\r
     ZeroMem (OptEnt.Uuid->Guid, sizeof (EFI_GUID));\r
   }\r
 \r
   //\r
   // Append client network device interface option\r
   //\r
-  OptList[Index]->OpCode  = PXEBC_PXE_DHCP4_TAG_UNDI;\r
+  OptList[Index]->OpCode  = DHCP4_TAG_UNDI;\r
   OptList[Index]->Length  = (UINT8) sizeof (PXEBC_DHCP4_OPTION_UNDI);\r
   OptEnt.Undi             = (PXEBC_DHCP4_OPTION_UNDI *) OptList[Index]->Data;\r
 \r
   OptList[Index]->Length  = (UINT8) sizeof (PXEBC_DHCP4_OPTION_UNDI);\r
   OptEnt.Undi             = (PXEBC_DHCP4_OPTION_UNDI *) OptList[Index]->Data;\r
 \r
@@ -346,7 +347,7 @@ PxeBcBuildDhcp4Options (
   //\r
   // Append client system architecture option\r
   //\r
   //\r
   // Append client system architecture option\r
   //\r
-  OptList[Index]->OpCode  = PXEBC_PXE_DHCP4_TAG_ARCH;\r
+  OptList[Index]->OpCode  = DHCP4_TAG_ARCH;\r
   OptList[Index]->Length  = (UINT8) sizeof (PXEBC_DHCP4_OPTION_ARCH);\r
   OptEnt.Arch             = (PXEBC_DHCP4_OPTION_ARCH *) OptList[Index]->Data;\r
   Value                   = HTONS (EFI_PXE_CLIENT_SYSTEM_ARCHITECTURE);\r
   OptList[Index]->Length  = (UINT8) sizeof (PXEBC_DHCP4_OPTION_ARCH);\r
   OptEnt.Arch             = (PXEBC_DHCP4_OPTION_ARCH *) OptList[Index]->Data;\r
   Value                   = HTONS (EFI_PXE_CLIENT_SYSTEM_ARCHITECTURE);\r
@@ -357,7 +358,7 @@ PxeBcBuildDhcp4Options (
   //\r
   // Append vendor class identify option\r
   //\r
   //\r
   // Append vendor class identify option\r
   //\r
-  OptList[Index]->OpCode  = PXEBC_DHCP4_TAG_CLASS_ID;\r
+  OptList[Index]->OpCode  = DHCP4_TAG_VENDOR_CLASS_ID;\r
   OptList[Index]->Length  = (UINT8) sizeof (PXEBC_DHCP4_OPTION_CLID);\r
   OptEnt.Clid             = (PXEBC_DHCP4_OPTION_CLID *) OptList[Index]->Data;\r
   CopyMem (\r
   OptList[Index]->Length  = (UINT8) sizeof (PXEBC_DHCP4_OPTION_CLID);\r
   OptEnt.Clid             = (PXEBC_DHCP4_OPTION_CLID *) OptList[Index]->Data;\r
   CopyMem (\r
@@ -414,7 +415,7 @@ PxeBcSeedDhcp4Packet (
   CopyMem (Header->ClientHwAddr, &Mode.CurrentAddress, Header->HwAddrLen);\r
 \r
   Seed->Dhcp4.Magik     = PXEBC_DHCP4_MAGIC;\r
   CopyMem (Header->ClientHwAddr, &Mode.CurrentAddress, Header->HwAddrLen);\r
 \r
   Seed->Dhcp4.Magik     = PXEBC_DHCP4_MAGIC;\r
-  Seed->Dhcp4.Option[0] = PXEBC_DHCP4_TAG_EOP;\r
+  Seed->Dhcp4.Option[0] = DHCP4_TAG_EOP;\r
 }\r
 \r
 \r
 }\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
   @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
 **/\r
-VOID\r
+EFI_STATUS\r
 PxeBcCacheDhcp4Packet (\r
   IN EFI_DHCP4_PACKET     *Dst,\r
   IN EFI_DHCP4_PACKET     *Src\r
   )\r
 {\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
   CopyMem (&Dst->Dhcp4, &Src->Dhcp4, Src->Length);\r
   Dst->Length = Src->Length;\r
+\r
+  return EFI_SUCCESS;\r
 }\r
 \r
 \r
 }\r
 \r
 \r
@@ -460,9 +468,11 @@ PxeBcParseDhcp4Packet (
   BOOLEAN                        IsProxyOffer;\r
   BOOLEAN                        IsPxeOffer;\r
   UINT8                          *Ptr8;\r
   BOOLEAN                        IsProxyOffer;\r
   BOOLEAN                        IsPxeOffer;\r
   UINT8                          *Ptr8;\r
+  BOOLEAN                        FileFieldOverloaded;\r
 \r
   IsProxyOffer = FALSE;\r
   IsPxeOffer   = FALSE;\r
 \r
   IsProxyOffer = FALSE;\r
   IsPxeOffer   = FALSE;\r
+  FileFieldOverloaded = FALSE;\r
 \r
   ZeroMem (Cache4->OptList, sizeof (Cache4->OptList));\r
   ZeroMem (&Cache4->VendorOpt, sizeof (Cache4->VendorOpt));\r
 \r
   ZeroMem (Cache4->OptList, sizeof (Cache4->OptList));\r
   ZeroMem (&Cache4->VendorOpt, sizeof (Cache4->VendorOpt));\r
@@ -472,6 +482,7 @@ PxeBcParseDhcp4Packet (
 \r
   //\r
   // Parse DHCPv4 options in this offer, and store the pointers.\r
 \r
   //\r
   // Parse DHCPv4 options in this offer, and store the pointers.\r
+  // First, try to parse DHCPv4 options from the DHCP optional parameters field.\r
   //\r
   for (Index = 0; Index < PXEBC_DHCP4_TAG_INDEX_MAX; Index++) {\r
     Options[Index] = PxeBcParseDhcp4Options (\r
   //\r
   for (Index = 0; Index < PXEBC_DHCP4_TAG_INDEX_MAX; Index++) {\r
     Options[Index] = PxeBcParseDhcp4Options (\r
@@ -480,9 +491,39 @@ PxeBcParseDhcp4Packet (
                        mInterestedDhcp4Tags[Index]\r
                        );\r
   }\r
                        mInterestedDhcp4Tags[Index]\r
                        );\r
   }\r
+  //\r
+  // Second, Check if bootfilename and serverhostname is overloaded to carry DHCP options refers to rfc-2132. \r
+  // If yes, try to parse options from the BootFileName field, then ServerName field.\r
+  //\r
+  Option = Options[PXEBC_DHCP4_TAG_INDEX_OVERLOAD];\r
+  if (Option != NULL) {\r
+    if ((Option->Data[0] & PXEBC_DHCP4_OVERLOAD_FILE) != 0) {\r
+      FileFieldOverloaded = TRUE;\r
+      for (Index = 0; Index < PXEBC_DHCP4_TAG_INDEX_MAX; Index++) {\r
+        if (Options[Index] == NULL) {\r
+          Options[Index] = PxeBcParseDhcp4Options (\r
+                             (UINT8 *) Offer->Dhcp4.Header.BootFileName,\r
+                             sizeof (Offer->Dhcp4.Header.BootFileName),\r
+                             mInterestedDhcp4Tags[Index]\r
+                             );\r
+        }\r
+      }\r
+    }\r
+    if ((Option->Data[0] & PXEBC_DHCP4_OVERLOAD_SERVER_NAME) != 0) {\r
+      for (Index = 0; Index < PXEBC_DHCP4_TAG_INDEX_MAX; Index++) {\r
+        if (Options[Index] == NULL) {\r
+          Options[Index] = PxeBcParseDhcp4Options (\r
+                             (UINT8 *) Offer->Dhcp4.Header.ServerName,\r
+                             sizeof (Offer->Dhcp4.Header.ServerName),\r
+                             mInterestedDhcp4Tags[Index]\r
+                             );\r
+        }\r
+      }\r
+    }\r
+  }\r
 \r
   //\r
 \r
   //\r
-  // The offer with "yiaddr" is a proxy offer.\r
+  // The offer with zero "yiaddr" is a proxy offer.\r
   //\r
   if (Offer->Dhcp4.Header.YourAddr.Addr[0] == 0) {\r
     IsProxyOffer = TRUE;\r
   //\r
   if (Offer->Dhcp4.Header.YourAddr.Addr[0] == 0) {\r
     IsProxyOffer = TRUE;\r
@@ -506,30 +547,21 @@ PxeBcParseDhcp4Packet (
   }\r
 \r
   //\r
   }\r
 \r
   //\r
-  // Check whether bootfilename and serverhostname overloaded, refers to rfc-2132 in details.\r
-  // If overloaded, parse the buffer as nested DHCPv4 options, or else just parse as bootfilename\r
-  // and serverhostname option.\r
+  // Parse PXE boot file name:\r
+  // According to PXE spec, boot file name should be read from DHCP option 67 (bootfile name) if present.\r
+  // Otherwise, read from boot file field in DHCP header.\r
   //\r
   //\r
-  Option = Options[PXEBC_DHCP4_TAG_INDEX_OVERLOAD];\r
-  if (Option != NULL && (Option->Data[0] & PXEBC_DHCP4_OVERLOAD_FILE) != 0) {\r
-\r
-    Options[PXEBC_DHCP4_TAG_INDEX_BOOTFILE] = PxeBcParseDhcp4Options (\r
-                                                (UINT8 *) Offer->Dhcp4.Header.BootFileName,\r
-                                                sizeof (Offer->Dhcp4.Header.BootFileName),\r
-                                                PXEBC_DHCP4_TAG_BOOTFILE\r
-                                                );\r
+  if (Options[PXEBC_DHCP4_TAG_INDEX_BOOTFILE] != NULL) {\r
     //\r
     // RFC 2132, Section 9.5 does not strictly state Bootfile name (option 67) is null\r
     // terminated string. So force to append null terminated character at the end of string.\r
     //\r
     //\r
     // RFC 2132, Section 9.5 does not strictly state Bootfile name (option 67) is null\r
     // terminated string. So force to append null terminated character at the end of string.\r
     //\r
-    if (Options[PXEBC_DHCP4_TAG_INDEX_BOOTFILE] != NULL) {\r
-      Ptr8 =  (UINT8*)&Options[PXEBC_DHCP4_TAG_INDEX_BOOTFILE]->Data[0];\r
-      Ptr8 += Options[PXEBC_DHCP4_TAG_INDEX_BOOTFILE]->Length;\r
-      *Ptr8 =  '\0';\r
+    Ptr8 =  (UINT8*)&Options[PXEBC_DHCP4_TAG_INDEX_BOOTFILE]->Data[0];\r
+    Ptr8 += Options[PXEBC_DHCP4_TAG_INDEX_BOOTFILE]->Length;\r
+    if (*(Ptr8 - 1) != '\0') {\r
+      *Ptr8 = '\0';\r
     }\r
     }\r
-\r
-  } else if ((Options[PXEBC_DHCP4_TAG_INDEX_BOOTFILE] == NULL) &&\r
-            (Offer->Dhcp4.Header.BootFileName[0] != 0)) {\r
+  } else if (!FileFieldOverloaded && Offer->Dhcp4.Header.BootFileName[0] != 0) {\r
     //\r
     // If the bootfile is not present and bootfilename is present in DHCPv4 packet, just parse it.\r
     // Do not count dhcp option header here, or else will destroy the serverhostname.\r
     //\r
     // If the bootfile is not present and bootfilename is present in DHCPv4 packet, just parse it.\r
     // Do not count dhcp option header here, or else will destroy the serverhostname.\r
@@ -596,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
   @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
 **/\r
-VOID\r
+EFI_STATUS\r
 PxeBcCopyDhcp4Ack (\r
   IN PXEBC_PRIVATE_DATA   *Private,\r
   IN EFI_DHCP4_PACKET     *Ack,\r
 PxeBcCopyDhcp4Ack (\r
   IN PXEBC_PRIVATE_DATA   *Private,\r
   IN EFI_DHCP4_PACKET     *Ack,\r
@@ -605,10 +640,14 @@ PxeBcCopyDhcp4Ack (
   )\r
 {\r
   EFI_PXE_BASE_CODE_MODE  *Mode;\r
   )\r
 {\r
   EFI_PXE_BASE_CODE_MODE  *Mode;\r
+  EFI_STATUS              Status;\r
 \r
   Mode = Private->PxeBc.Mode;\r
 \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
 \r
   if (Verified) {\r
     //\r
@@ -618,6 +657,8 @@ PxeBcCopyDhcp4Ack (
     CopyMem (&Mode->DhcpAck.Dhcpv4, &Ack->Dhcp4, Ack->Length);\r
     Mode->DhcpAckReceived = TRUE;\r
   }\r
     CopyMem (&Mode->DhcpAck.Dhcpv4, &Ack->Dhcp4, Ack->Length);\r
     Mode->DhcpAckReceived = TRUE;\r
   }\r
+  \r
+  return EFI_SUCCESS;\r
 }\r
 \r
 \r
 }\r
 \r
 \r
@@ -627,8 +668,11 @@ PxeBcCopyDhcp4Ack (
   @param[in]  Private               Pointer to PxeBc private data.\r
   @param[in]  OfferIndex            The received order of offer packets.\r
 \r
   @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
 **/\r
-VOID\r
+EFI_STATUS\r
 PxeBcCopyProxyOffer (\r
   IN PXEBC_PRIVATE_DATA   *Private,\r
   IN UINT32               OfferIndex\r
 PxeBcCopyProxyOffer (\r
   IN PXEBC_PRIVATE_DATA   *Private,\r
   IN UINT32               OfferIndex\r
@@ -636,6 +680,7 @@ PxeBcCopyProxyOffer (
 {\r
   EFI_PXE_BASE_CODE_MODE  *Mode;\r
   EFI_DHCP4_PACKET        *Offer;\r
 {\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
 \r
   ASSERT (OfferIndex < Private->OfferNum);\r
   ASSERT (OfferIndex < PXEBC_OFFER_MAX_NUM);\r
@@ -646,7 +691,11 @@ PxeBcCopyProxyOffer (
   //\r
   // Cache the proxy offer packet and parse it.\r
   //\r
   //\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
   PxeBcParseDhcp4Packet (&Private->ProxyOffer.Dhcp4);\r
 \r
   //\r
@@ -654,6 +703,8 @@ PxeBcCopyProxyOffer (
   //\r
   CopyMem (&Mode->ProxyOffer.Dhcpv4, &Offer->Dhcp4, Offer->Length);\r
   Mode->ProxyOfferReceived = TRUE;\r
   //\r
   CopyMem (&Mode->ProxyOffer.Dhcpv4, &Offer->Dhcp4, Offer->Length);\r
   Mode->ProxyOfferReceived = TRUE;\r
+\r
+  return EFI_SUCCESS;\r
 }\r
 \r
 \r
 }\r
 \r
 \r
@@ -756,8 +807,11 @@ PxeBcRetryBinlOffer (
   @param[in]  Private               Pointer to PxeBc private data.\r
   @param[in]  RcvdOffer             Pointer to the received offer packet.\r
 \r
   @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
 **/\r
-VOID\r
+EFI_STATUS\r
 PxeBcCacheDhcp4Offer (\r
   IN PXEBC_PRIVATE_DATA     *Private,\r
   IN EFI_DHCP4_PACKET       *RcvdOffer\r
 PxeBcCacheDhcp4Offer (\r
   IN PXEBC_PRIVATE_DATA     *Private,\r
   IN EFI_DHCP4_PACKET       *RcvdOffer\r
@@ -766,6 +820,7 @@ PxeBcCacheDhcp4Offer (
   PXEBC_DHCP4_PACKET_CACHE  *Cache4;\r
   EFI_DHCP4_PACKET          *Offer;\r
   PXEBC_OFFER_TYPE          OfferType;\r
   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
 \r
   ASSERT (Private->OfferNum < PXEBC_OFFER_MAX_NUM);\r
   Cache4 = &Private->OfferBuffer[Private->OfferNum].Dhcp4;\r
@@ -774,13 +829,16 @@ PxeBcCacheDhcp4Offer (
   //\r
   // Cache the content of DHCPv4 packet firstly.\r
   //\r
   //\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
 \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
   }\r
 \r
   //\r
@@ -797,7 +855,7 @@ PxeBcCacheDhcp4Offer (
       Private->OfferIndex[OfferType][0] = Private->OfferNum;\r
       Private->OfferCount[OfferType]    = 1;\r
     } else {\r
       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
     }\r
   } else {\r
     ASSERT (Private->OfferCount[OfferType] < PXEBC_OFFER_MAX_NUM);\r
@@ -813,14 +871,15 @@ PxeBcCacheDhcp4Offer (
         //\r
         Private->OfferIndex[OfferType][Private->OfferCount[OfferType]] = Private->OfferNum;\r
         Private->OfferCount[OfferType]++;\r
         //\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
         //\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
       }\r
     } else {\r
       //\r
@@ -832,6 +891,8 @@ PxeBcCacheDhcp4Offer (
   }\r
 \r
   Private->OfferNum++;\r
   }\r
 \r
   Private->OfferNum++;\r
+\r
+  return EFI_SUCCESS;\r
 }\r
 \r
 \r
 }\r
 \r
 \r
@@ -956,11 +1017,12 @@ PxeBcSelectDhcp4Offer (
 /**\r
   Handle the DHCPv4 offer packet.\r
 \r
 /**\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
 \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
 \r
 **/\r
 EFI_STATUS\r
@@ -1065,7 +1127,7 @@ PxeBcHandleDhcp4Offer (
         //\r
         // Success to try to request by a ProxyPxe10 or ProxyWfm11a offer, copy and parse it.\r
         //\r
         //\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
       }\r
     } else {\r
       //\r
@@ -1092,7 +1154,10 @@ PxeBcHandleDhcp4Offer (
       Ack = Offer;\r
     }\r
 \r
       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
     Mode->DhcpDiscoverValid = TRUE;\r
   }\r
 \r
@@ -1146,6 +1211,8 @@ PxeBcDhcp4CallBack (
     return EFI_SUCCESS;\r
   }\r
 \r
     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
   Private   = (PXEBC_PRIVATE_DATA *) Context;\r
   Mode      = Private->PxeBc.Mode;\r
   Callback  = Private->PxeBcCallback;\r
@@ -1156,10 +1223,10 @@ PxeBcDhcp4CallBack (
   MaxMsgSize = PxeBcParseDhcp4Options (\r
                  Packet->Dhcp4.Option,\r
                  GET_OPTION_BUFFER_LEN (Packet),\r
   MaxMsgSize = PxeBcParseDhcp4Options (\r
                  Packet->Dhcp4.Option,\r
                  GET_OPTION_BUFFER_LEN (Packet),\r
-                 PXEBC_DHCP4_TAG_MAXMSG\r
+                 DHCP4_TAG_MAXMSG\r
                  );\r
   if (MaxMsgSize != NULL) {\r
                  );\r
   if (MaxMsgSize != NULL) {\r
-    Value = HTONS (PXEBC_DHCP4_PACKET_MAX_SIZE - 8);\r
+    Value = HTONS (PXEBC_DHCP4_PACKET_MAX_SIZE);\r
     CopyMem (MaxMsgSize->Data, &Value, sizeof (Value));\r
   }\r
 \r
     CopyMem (MaxMsgSize->Data, &Value, sizeof (Value));\r
   }\r
 \r
@@ -1185,6 +1252,14 @@ PxeBcDhcp4CallBack (
   switch (Dhcp4Event) {\r
 \r
   case Dhcp4SendDiscover:\r
   switch (Dhcp4Event) {\r
 \r
   case Dhcp4SendDiscover:\r
+    if (Packet->Length > PXEBC_DHCP4_PACKET_MAX_SIZE) {\r
+      //\r
+      // If the to be sent packet exceeds the maximum length, abort the DHCP process.\r
+      //\r
+      Status = EFI_ABORTED;\r
+      break;\r
+    }\r
+\r
     //\r
     // Cache the DHCPv4 discover packet to mode data directly.\r
     // It need to check SendGuid as well as Dhcp4SendRequest.\r
     //\r
     // Cache the DHCPv4 discover packet to mode data directly.\r
     // It need to check SendGuid as well as Dhcp4SendRequest.\r
@@ -1192,6 +1267,14 @@ PxeBcDhcp4CallBack (
     CopyMem (&Mode->DhcpDiscover.Dhcpv4, &Packet->Dhcp4, Packet->Length);\r
 \r
   case Dhcp4SendRequest:\r
     CopyMem (&Mode->DhcpDiscover.Dhcpv4, &Packet->Dhcp4, Packet->Length);\r
 \r
   case Dhcp4SendRequest:\r
+    if (Packet->Length > PXEBC_DHCP4_PACKET_MAX_SIZE) {\r
+      //\r
+      // If the to be sent packet exceeds the maximum length, abort the DHCP process.\r
+      //\r
+      Status = EFI_ABORTED;\r
+      break;\r
+    }\r
+    \r
     if (Mode->SendGUID) {\r
       //\r
       // Send the system Guid instead of the MAC address as the hardware address if required.\r
     if (Mode->SendGUID) {\r
       //\r
       // Send the system Guid instead of the MAC address as the hardware address if required.\r
@@ -1200,6 +1283,7 @@ PxeBcDhcp4CallBack (
         //\r
         // Zero the Guid to indicate NOT programable if failed to get system Guid.\r
         //\r
         //\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
         ZeroMem (Packet->Dhcp4.Header.ClientHwAddr, sizeof (EFI_GUID));\r
       }\r
       Packet->Dhcp4.Header.HwAddrLen = (UINT8) sizeof (EFI_GUID);\r
@@ -1208,16 +1292,25 @@ PxeBcDhcp4CallBack (
 \r
   case Dhcp4RcvdOffer:\r
     Status = EFI_NOT_READY;\r
 \r
   case Dhcp4RcvdOffer:\r
     Status = EFI_NOT_READY;\r
+    if (Packet->Length > PXEBC_DHCP4_PACKET_MAX_SIZE) {\r
+      //\r
+      // Ignore the incoming packets which exceed the maximum length.\r
+      //\r
+      break;\r
+    }\r
     if (Private->OfferNum < PXEBC_OFFER_MAX_NUM) {\r
       //\r
       // Cache the DHCPv4 offers to OfferBuffer[] for select later, and record\r
       // the OfferIndex and OfferCount.\r
     if (Private->OfferNum < PXEBC_OFFER_MAX_NUM) {\r
       //\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
       //\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
     //\r
     // Select offer by the default policy or by order, and record the SelectIndex\r
     // and SelectProxyType.\r
@@ -1238,7 +1331,10 @@ PxeBcDhcp4CallBack (
     //\r
     ASSERT (Private->SelectIndex != 0);\r
 \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
     break;\r
 \r
   default:\r
@@ -1332,14 +1428,14 @@ PxeBcDhcp4Discover (
       return EFI_OUT_OF_RESOURCES;\r
     }\r
 \r
       return EFI_OUT_OF_RESOURCES;\r
     }\r
 \r
-    OptList[OptCount]->OpCode     = PXEBC_DHCP4_TAG_VENDOR;\r
+    OptList[OptCount]->OpCode     = DHCP4_TAG_VENDOR;\r
     OptList[OptCount]->Length     = (UINT8) (VendorOptLen - 2);\r
     PxeOpt                        = (EFI_DHCP4_PACKET_OPTION *) OptList[OptCount]->Data;\r
     PxeOpt->OpCode                = PXEBC_VENDOR_TAG_BOOT_ITEM;\r
     PxeOpt->Length                = (UINT8) sizeof (PXEBC_OPTION_BOOT_ITEM);\r
     PxeBootItem                   = (PXEBC_OPTION_BOOT_ITEM *) PxeOpt->Data;\r
     PxeBootItem->Type             = HTONS (Type);\r
     OptList[OptCount]->Length     = (UINT8) (VendorOptLen - 2);\r
     PxeOpt                        = (EFI_DHCP4_PACKET_OPTION *) OptList[OptCount]->Data;\r
     PxeOpt->OpCode                = PXEBC_VENDOR_TAG_BOOT_ITEM;\r
     PxeOpt->Length                = (UINT8) sizeof (PXEBC_OPTION_BOOT_ITEM);\r
     PxeBootItem                   = (PXEBC_OPTION_BOOT_ITEM *) PxeOpt->Data;\r
     PxeBootItem->Type             = HTONS (Type);\r
-    PxeOpt->Data[PxeOpt->Length]  = PXEBC_DHCP4_TAG_EOP;\r
+    PxeOpt->Data[PxeOpt->Length]  = DHCP4_TAG_EOP;\r
 \r
     if (Layer != NULL) {\r
       PxeBootItem->Layer          = HTONS (*Layer);\r
 \r
     if (Layer != NULL) {\r
       PxeBootItem->Layer          = HTONS (*Layer);\r
@@ -1376,6 +1472,7 @@ PxeBcDhcp4Discover (
       //\r
       // Zero the Guid to indicate NOT programable if failed to get system Guid.\r
       //\r
       //\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
       ZeroMem (Token.Packet->Dhcp4.Header.ClientHwAddr, sizeof (EFI_GUID));\r
     }\r
     Token.Packet->Dhcp4.Header.HwAddrLen = (UINT8)  sizeof (EFI_GUID);\r
@@ -1437,6 +1534,12 @@ PxeBcDhcp4Discover (
     // Find the right PXE Reply according to server address.\r
     //\r
     while (RepIndex < Token.ResponseCount) {\r
     // 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
 \r
       while (SrvIndex < IpCount) {\r
         if (SrvList[SrvIndex].AcceptAnyResponse) {\r
@@ -1455,7 +1558,6 @@ PxeBcDhcp4Discover (
 \r
       SrvIndex = 0;\r
       RepIndex++;\r
 \r
       SrvIndex = 0;\r
       RepIndex++;\r
-\r
       Response = (EFI_DHCP4_PACKET *) ((UINT8 *) Response + Response->Size);\r
     }\r
 \r
       Response = (EFI_DHCP4_PACKET *) ((UINT8 *) Response + Response->Size);\r
     }\r
 \r
@@ -1465,10 +1567,16 @@ PxeBcDhcp4Discover (
       // Especially for PXE discover packet, store it into mode data here.\r
       //\r
       if (Private->IsDoDiscover) {\r
       // 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
         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
       }\r
     } else {\r
       //\r
@@ -1476,15 +1584,64 @@ PxeBcDhcp4Discover (
       //\r
       Status = EFI_NOT_FOUND;\r
     }\r
       //\r
       Status = EFI_NOT_FOUND;\r
     }\r
-    if (Token.ResponseList != NULL) {\r
-      FreePool (Token.ResponseList);\r
-    }\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
   return Status;\r
 }\r
 \r
+/**\r
+  Switch the Ip4 policy to static.\r
+\r
+  @param[in]  Private             The pointer to PXEBC_PRIVATE_DATA.\r
+\r
+  @retval     EFI_SUCCESS         The policy is already configured to static.\r
+  @retval     Others              Other error as indicated..\r
+\r
+**/\r
+EFI_STATUS\r
+PxeBcSetIp4Policy (   \r
+  IN PXEBC_PRIVATE_DATA            *Private\r
+  )\r
+{\r
+  EFI_STATUS                   Status;\r
+  EFI_IP4_CONFIG2_PROTOCOL     *Ip4Config2;\r
+  EFI_IP4_CONFIG2_POLICY       Policy;\r
+  UINTN                        DataSize;\r
+\r
+  Ip4Config2 = Private->Ip4Config2;\r
+  DataSize = sizeof (EFI_IP4_CONFIG2_POLICY);\r
+  Status = Ip4Config2->GetData (\r
+                       Ip4Config2,\r
+                       Ip4Config2DataTypePolicy,\r
+                       &DataSize,\r
+                       &Policy\r
+                       );\r
+  if (EFI_ERROR (Status)) {\r
+    return Status;\r
+  }\r
+  \r
+  if (Policy != Ip4Config2PolicyStatic) {\r
+    Policy = Ip4Config2PolicyStatic;\r
+    Status= Ip4Config2->SetData (\r
+                          Ip4Config2,\r
+                          Ip4Config2DataTypePolicy,\r
+                          sizeof (EFI_IP4_CONFIG2_POLICY),\r
+                          &Policy\r
+                          );\r
+    if (EFI_ERROR (Status)) {\r
+      return Status;\r
+    } \r
+  }\r
+\r
+  return  EFI_SUCCESS;\r
+}\r
 \r
 /**\r
   Start the D.O.R.A DHCPv4 process to acquire the IPv4 address and other PXE boot information.\r
 \r
 /**\r
   Start the D.O.R.A DHCPv4 process to acquire the IPv4 address and other PXE boot information.\r
@@ -1547,14 +1704,16 @@ PxeBcDhcp4Dora (
   ZeroMem (Private->OfferCount, sizeof (Private->OfferCount));\r
   ZeroMem (Private->OfferIndex, sizeof (Private->OfferIndex));\r
 \r
   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.\r
-  //\r
   Status = Dhcp4->Start (Dhcp4, NULL);\r
   if (EFI_ERROR (Status)) {\r
     if (Status == EFI_ICMP_ERROR) {\r
       PxeMode->IcmpErrorReceived = TRUE;\r
     }\r
   Status = Dhcp4->Start (Dhcp4, NULL);\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
     goto ON_EXIT;\r
   }\r
 \r
@@ -1574,7 +1733,7 @@ PxeBcDhcp4Dora (
   CopyMem (&PxeMode->StationIp, &Private->StationIp, sizeof (EFI_IPv4_ADDRESS));\r
   CopyMem (&PxeMode->SubnetMask, &Private->SubnetMask, sizeof (EFI_IPv4_ADDRESS));\r
 \r
   CopyMem (&PxeMode->StationIp, &Private->StationIp, sizeof (EFI_IPv4_ADDRESS));\r
   CopyMem (&PxeMode->SubnetMask, &Private->SubnetMask, sizeof (EFI_IPv4_ADDRESS));\r
 \r
-  Status = PxeBcFlushStaionIp (Private, &Private->StationIp, &Private->SubnetMask);\r
+  Status = PxeBcFlushStationIp (Private, &Private->StationIp, &Private->SubnetMask);\r
   if (EFI_ERROR (Status)) {\r
     goto ON_EXIT;\r
   }\r
   if (EFI_ERROR (Status)) {\r
     goto ON_EXIT;\r
   }\r