]> git.proxmox.com Git - mirror_edk2.git/blobdiff - NetworkPkg/HttpBootDxe/HttpBootImpl.c
NetworkPkg:Enable Http Boot over Ipv6 stack
[mirror_edk2.git] / NetworkPkg / HttpBootDxe / HttpBootImpl.c
index eee63c21d3a907e2415ab7ddfbeb6f4875c9ed1a..9ea0d7f95f93eb26aa7bbd58e59196fe739b696f 100644 (file)
@@ -18,6 +18,9 @@ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
   Enable the use of UEFI HTTP boot function.\r
 \r
   @param[in]    Private            The pointer to the driver's private data.\r
+  @param[in]    UsingIpv6          Specifies the type of IP addresses that are to be\r
+                                   used during the session that is being started.\r
+                                   Set to TRUE for IPv6, and FALSE for IPv4.\r
 \r
   @retval EFI_SUCCESS              HTTP boot was successfully enabled.\r
   @retval EFI_INVALID_PARAMETER    Private is NULL.\r
@@ -26,10 +29,12 @@ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
 **/\r
 EFI_STATUS\r
 HttpBootStart (\r
-  IN HTTP_BOOT_PRIVATE_DATA           *Private\r
+  IN HTTP_BOOT_PRIVATE_DATA           *Private,\r
+  IN BOOLEAN                          UsingIpv6\r
   )\r
 {\r
-  UINTN          Index;\r
+  UINTN                Index;\r
+  EFI_STATUS           Status;\r
 \r
   if (Private == NULL) {\r
     return EFI_INVALID_PARAMETER;\r
@@ -39,25 +44,47 @@ HttpBootStart (
     return EFI_ALREADY_STARTED;\r
   }\r
 \r
+  //\r
+  // Detect whether using ipv6 or not, and set it to the private data.\r
+  //\r
+  if (UsingIpv6 && Private->Ip6Nic != NULL) {\r
+    Private->UsingIpv6 = TRUE;\r
+  } else if (!UsingIpv6 && Private->Ip4Nic != NULL) {\r
+    Private->UsingIpv6 = FALSE;\r
+  } else {\r
+    return EFI_UNSUPPORTED;\r
+  }\r
+  \r
+  //\r
+  // Init the content of cached DHCP offer list.\r
+  //\r
+  ZeroMem (Private->OfferBuffer, sizeof (Private->OfferBuffer));\r
   if (!Private->UsingIpv6) {\r
-    //\r
-    // Init the content of cached DHCP offer list.\r
-    //\r
-    ZeroMem (Private->OfferBuffer, sizeof (Private->OfferBuffer));\r
     for (Index = 0; Index < HTTP_BOOT_OFFER_MAX_NUM; Index++) {\r
       Private->OfferBuffer[Index].Dhcp4.Packet.Offer.Size = HTTP_BOOT_DHCP4_PACKET_MAX_SIZE;\r
     }\r
   } else {\r
-    ASSERT (FALSE);\r
+    for (Index = 0; Index < HTTP_BOOT_OFFER_MAX_NUM; Index++) {\r
+      Private->OfferBuffer[Index].Dhcp6.Packet.Offer.Size = HTTP_BOOT_DHCP6_PACKET_MAX_SIZE;\r
+    }\r
   }\r
 \r
+  if (Private->UsingIpv6) {\r
+    //\r
+    // Set Ip6 policy to Automatic to start the Ip6 router discovery.\r
+    //\r
+    Status = HttpBootSetIp6Policy (Private);\r
+    if (EFI_ERROR (Status)) {\r
+      return Status;\r
+    }\r
+  }\r
   Private->Started = TRUE;\r
 \r
   return EFI_SUCCESS;\r
 }\r
 \r
 /**\r
-  Attempt to complete a DHCPv4 D.O.R.A sequence to retrieve the boot resource information.\r
+  Attempt to complete a DHCPv4 D.O.R.A or DHCPv6 S.R.A.A sequence to retrieve the boot resource information.\r
 \r
   @param[in]    Private            The pointer to the driver's private data.\r
 \r
@@ -86,9 +113,15 @@ HttpBootDhcp (
   Status = EFI_DEVICE_ERROR;\r
 \r
   if (!Private->UsingIpv6) {\r
+    //\r
+    // Start D.O.R.A process to get a IPv4 address and other boot information.\r
+    //\r
     Status = HttpBootDhcp4Dora (Private);\r
   } else {\r
-    ASSERT (FALSE);\r
+     //\r
+    // Start S.A.R.R process to get a IPv6 address and other boot information.\r
+    //\r
+    Status = HttpBootDhcp6Sarr (Private);\r
   }\r
 \r
   return Status;\r
@@ -241,7 +274,7 @@ HttpBootStop (
   Private->BootFileUriParser = NULL;\r
   Private->BootFileSize = 0;\r
   Private->SelectIndex = 0;\r
-  Private->SelectProxyType = HttpOfferTypeMax;\r
+  Private->SelectProxyType = HttpOfferTypeMax; \r
 \r
   if (!Private->UsingIpv6) {\r
     //\r
@@ -256,7 +289,17 @@ HttpBootStop (
       }\r
     }\r
   } else {\r
-    ASSERT (FALSE);\r
+    //\r
+    // Stop and release the DHCP6 child.\r
+    //\r
+    Private->Dhcp6->Stop (Private->Dhcp6);\r
+    Private->Dhcp6->Configure (Private->Dhcp6, NULL);\r
+    \r
+    for (Index = 0; Index < HTTP_BOOT_OFFER_MAX_NUM; Index++) {\r
+      if (Private->OfferBuffer[Index].Dhcp6.UriParser) {\r
+        HttpUrlFreeParser (Private->OfferBuffer[Index].Dhcp6.UriParser);\r
+      }\r
+    }\r
   }\r
   \r
   ZeroMem (Private->OfferBuffer, sizeof (Private->OfferBuffer));\r
@@ -309,7 +352,9 @@ HttpBootDxeLoadFile (
   )\r
 {\r
   HTTP_BOOT_PRIVATE_DATA        *Private;\r
+  HTTP_BOOT_VIRTUAL_NIC         *VirtualNic;\r
   BOOLEAN                       MediaPresent;\r
+  BOOLEAN                       UsingIpv6;\r
   EFI_STATUS                    Status;\r
 \r
   if (This == NULL || BufferSize == NULL) {\r
@@ -323,8 +368,10 @@ HttpBootDxeLoadFile (
     return EFI_UNSUPPORTED;\r
   }\r
 \r
-  Private = HTTP_BOOT_PRIVATE_DATA_FROM_LOADFILE (This);\r
-\r
+  VirtualNic = HTTP_BOOT_VIRTUAL_NIC_FROM_LOADFILE (This);\r
+  Private = VirtualNic->Private;\r
+  UsingIpv6 = FALSE;\r
+  \r
   //\r
   // Check media status before HTTP boot start\r
   //\r
@@ -334,10 +381,26 @@ HttpBootDxeLoadFile (
     return EFI_NO_MEDIA;\r
   }\r
 \r
+  //\r
+  // Check whether the virtual nic is using IPv6 or not.\r
+  //\r
+  if (VirtualNic == Private->Ip6Nic) {\r
+    UsingIpv6 = TRUE;\r
+  }\r
+  \r
   //\r
   // Initialize HTTP boot and load the boot file.\r
   //\r
-  Status = HttpBootStart (Private);\r
+  Status = HttpBootStart (Private, UsingIpv6);\r
+  if (Status == EFI_ALREADY_STARTED && UsingIpv6 != Private->UsingIpv6) {\r
+    //\r
+    // Http boot Driver has already been started but not on the required IP version, restart it.\r
+    //\r
+    Status = HttpBootStop (Private);\r
+    if (!EFI_ERROR (Status)) {\r
+      Status = HttpBootStart (Private, UsingIpv6);\r
+    }\r
+  }\r
   if (Status == EFI_SUCCESS || Status == EFI_ALREADY_STARTED) {\r
     Status = HttpBootLoadFile (Private, BufferSize, Buffer);\r
   }\r
@@ -345,11 +408,19 @@ HttpBootDxeLoadFile (
   if (Status != EFI_SUCCESS && Status != EFI_BUFFER_TOO_SMALL) {\r
     HttpBootStop (Private);\r
   } else {\r
-    //\r
-    // Stop and release the DHCP4 child.\r
-    //\r
-    Private->Dhcp4->Stop (Private->Dhcp4);\r
-    Private->Dhcp4->Configure (Private->Dhcp4, NULL);\r
+    if (!Private->UsingIpv6) {\r
+      //\r
+      // Stop and release the DHCP4 child.\r
+      //\r
+      Private->Dhcp4->Stop (Private->Dhcp4);\r
+      Private->Dhcp4->Configure (Private->Dhcp4, NULL);\r
+    } else {\r
+      //\r
+      // Stop and release the DHCP6 child.\r
+      //\r
+      Private->Dhcp6->Stop (Private->Dhcp6);\r
+      Private->Dhcp6->Configure (Private->Dhcp6, NULL);\r
+    }\r
   }\r
 \r
   return Status;\r