]> git.proxmox.com Git - mirror_edk2.git/blobdiff - NetworkPkg/UefiPxeBcDxe/PxeBcDhcp4.c
MdeModulePkg-DxeCore: rename CoreGetMemoryMapPropertiesTable
[mirror_edk2.git] / NetworkPkg / UefiPxeBcDxe / PxeBcDhcp4.c
index 23682b2451857bb4dc93cda3f268316858b5eb85..818586f9552ff3bbdcbbbbb3bbef0a6901049f7b 100644 (file)
@@ -1,7 +1,7 @@
 /** @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 - 2016, 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
@@ -460,9 +460,11 @@ PxeBcParseDhcp4Packet (
   BOOLEAN                        IsProxyOffer;\r
   BOOLEAN                        IsPxeOffer;\r
   UINT8                          *Ptr8;\r
+  BOOLEAN                        FileFieldOverloaded;\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
@@ -472,6 +474,7 @@ PxeBcParseDhcp4Packet (
 \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
@@ -480,9 +483,39 @@ PxeBcParseDhcp4Packet (
                        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
-  // 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
@@ -506,30 +539,21 @@ PxeBcParseDhcp4Packet (
   }\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
-  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
-    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
-  } 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
@@ -1485,6 +1509,52 @@ PxeBcDhcp4Discover (
   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
@@ -1548,10 +1618,12 @@ PxeBcDhcp4Dora (
   ZeroMem (Private->OfferIndex, sizeof (Private->OfferIndex));\r
 \r
   //\r
-  // Start DHCPv4 D.O.R.A. process to acquire IPv4 address.\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)) {\r
+  if (EFI_ERROR (Status) && Status != EFI_ALREADY_STARTED) {\r
     if (Status == EFI_ICMP_ERROR) {\r
       PxeMode->IcmpErrorReceived = TRUE;\r
     }\r
@@ -1574,7 +1646,7 @@ PxeBcDhcp4Dora (
   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