]> git.proxmox.com Git - mirror_edk2.git/commitdiff
NetworkPkg: Add RAM disk boot support to HTTP Boot driver.
authorFu Siyuan <siyuan.fu@intel.com>
Tue, 22 Mar 2016 05:30:58 +0000 (13:30 +0800)
committerFu Siyuan <siyuan.fu@intel.com>
Mon, 11 Apr 2016 01:49:05 +0000 (09:49 +0800)
This patch updates the HTTP Boot driver to support the download and boot
a RAM disk image from HTTP server.
The HTTP RAM disk boot is described in section 23.7 "HTTP Boot" in
UEFI 2.6. HTTP server could provide either an UEFI image or a RAM disk image
for the HTTP boot client to use. The RAM disk image must contain a UEFI
compliant file system in it.
HTTP boot driver will identify the image type either by the "Content-Type"
entity header filed or by the file name extension as below:
  "application/efi" or *.efi -> EFI Image
  *.iso                      -> CD/DVD Image
  *.img                      -> Virtual Disk Image

Contributed-under: TianoCore Contribution Agreement 1.0
Signed-off-by: Fu Siyuan <siyuan.fu@intel.com>
Reviewed-by: Ye Ting <ting.ye@intel.com>
Reviewed-by: El-Haj-Mahmoud Samer <samer.el-haj-mahmoud@hpe.com>
NetworkPkg/HttpBootDxe/HttpBootClient.c
NetworkPkg/HttpBootDxe/HttpBootClient.h
NetworkPkg/HttpBootDxe/HttpBootDxe.h
NetworkPkg/HttpBootDxe/HttpBootDxe.inf
NetworkPkg/HttpBootDxe/HttpBootImpl.c
NetworkPkg/HttpBootDxe/HttpBootSupport.c
NetworkPkg/HttpBootDxe/HttpBootSupport.h

index 0c472938a068145200089aee59ae25db0a80c17c..9d445e3c8e7c59f8698c029b91a53d4f9e41d498 100644 (file)
@@ -570,6 +570,7 @@ HttpBootFreeCacheList (
   @param[out]         Buffer          The memory buffer to transfer the file to. IF Buffer is NULL,\r
                                       then the size of the requested file is returned in\r
                                       BufferSize.\r
   @param[out]         Buffer          The memory buffer to transfer the file to. IF Buffer is NULL,\r
                                       then the size of the requested file is returned in\r
                                       BufferSize.\r
+  @param[out]         ImageType       The image type of the downloaded file.\r
 \r
   @retval EFI_SUCCESS          Successfully created.\r
   @retval Others               Failed to create HttpIo.\r
 \r
   @retval EFI_SUCCESS          Successfully created.\r
   @retval Others               Failed to create HttpIo.\r
@@ -580,7 +581,8 @@ HttpBootGetFileFromCache (
   IN     HTTP_BOOT_PRIVATE_DATA   *Private,\r
   IN     CHAR16                   *Uri,\r
   IN OUT UINTN                    *BufferSize,\r
   IN     HTTP_BOOT_PRIVATE_DATA   *Private,\r
   IN     CHAR16                   *Uri,\r
   IN OUT UINTN                    *BufferSize,\r
-     OUT UINT8                    *Buffer\r
+     OUT UINT8                    *Buffer,\r
+     OUT HTTP_BOOT_IMAGE_TYPE     *ImageType\r
   )\r
 {\r
   LIST_ENTRY                  *Entry;\r
   )\r
 {\r
   LIST_ENTRY                  *Entry;\r
@@ -589,7 +591,7 @@ HttpBootGetFileFromCache (
   HTTP_BOOT_ENTITY_DATA       *EntityData;\r
   UINTN                       CopyedSize;\r
   \r
   HTTP_BOOT_ENTITY_DATA       *EntityData;\r
   UINTN                       CopyedSize;\r
   \r
-  if (Uri == NULL || BufferSize == 0 || Buffer == NULL) {\r
+  if (Uri == NULL || BufferSize == 0 || Buffer == NULL || ImageType == NULL) {\r
     return EFI_INVALID_PARAMETER;\r
   }\r
 \r
     return EFI_INVALID_PARAMETER;\r
   }\r
 \r
@@ -603,7 +605,12 @@ HttpBootGetFileFromCache (
         (StrCmp (Uri, Cache->RequestData->Url) == 0)) \r
     {\r
       //\r
         (StrCmp (Uri, Cache->RequestData->Url) == 0)) \r
     {\r
       //\r
-      // Hit cache, check buffer size.\r
+      // Hit in cache, record image type.\r
+      //\r
+      *ImageType  = Cache->ImageType;\r
+\r
+      //\r
+      // Check buffer size.\r
       //\r
       if (*BufferSize < Cache->EntityLength) {\r
         *BufferSize = Cache->EntityLength;\r
       //\r
       if (*BufferSize < Cache->EntityLength) {\r
         *BufferSize = Cache->EntityLength;\r
@@ -712,6 +719,7 @@ HttpBootGetBootFileCallback (
   @param[out]      Buffer          The memory buffer to transfer the file to. IF Buffer is NULL,\r
                                    then the size of the requested file is returned in\r
                                    BufferSize.\r
   @param[out]      Buffer          The memory buffer to transfer the file to. IF Buffer is NULL,\r
                                    then the size of the requested file is returned in\r
                                    BufferSize.\r
+  @param[out]      ImageType       The image type of the downloaded file.\r
 \r
   @retval EFI_SUCCESS              The file was loaded.\r
   @retval EFI_INVALID_PARAMETER    BufferSize is NULL or Buffer Size is not NULL but Buffer is NULL.\r
 \r
   @retval EFI_SUCCESS              The file was loaded.\r
   @retval EFI_INVALID_PARAMETER    BufferSize is NULL or Buffer Size is not NULL but Buffer is NULL.\r
@@ -727,7 +735,8 @@ HttpBootGetBootFile (
   IN     HTTP_BOOT_PRIVATE_DATA   *Private,\r
   IN     BOOLEAN                  HeaderOnly,\r
   IN OUT UINTN                    *BufferSize,\r
   IN     HTTP_BOOT_PRIVATE_DATA   *Private,\r
   IN     BOOLEAN                  HeaderOnly,\r
   IN OUT UINTN                    *BufferSize,\r
-     OUT UINT8                    *Buffer\r
+     OUT UINT8                    *Buffer,\r
+     OUT HTTP_BOOT_IMAGE_TYPE     *ImageType\r
   )\r
 {\r
   EFI_STATUS                 Status;\r
   )\r
 {\r
   EFI_STATUS                 Status;\r
@@ -750,7 +759,7 @@ HttpBootGetBootFile (
   ASSERT (Private != NULL);\r
   ASSERT (Private->HttpCreated);\r
 \r
   ASSERT (Private != NULL);\r
   ASSERT (Private->HttpCreated);\r
 \r
-  if (BufferSize == NULL) {\r
+  if (BufferSize == NULL || ImageType == NULL) {\r
     return EFI_INVALID_PARAMETER;\r
   }\r
 \r
     return EFI_INVALID_PARAMETER;\r
   }\r
 \r
@@ -767,7 +776,7 @@ HttpBootGetBootFile (
   }\r
   AsciiStrToUnicodeStr (Private->BootFileUri, Url);\r
   if (!HeaderOnly) {\r
   }\r
   AsciiStrToUnicodeStr (Private->BootFileUri, Url);\r
   if (!HeaderOnly) {\r
-    Status = HttpBootGetFileFromCache (Private, Url, BufferSize, Buffer);\r
+    Status = HttpBootGetFileFromCache (Private, Url, BufferSize, Buffer, ImageType);\r
     if (Status != EFI_NOT_FOUND) {\r
       FreePool (Url);\r
       return Status;\r
     if (Status != EFI_NOT_FOUND) {\r
       FreePool (Url);\r
       return Status;\r
@@ -788,6 +797,7 @@ HttpBootGetBootFile (
       Status = EFI_OUT_OF_RESOURCES;\r
       goto ERROR_1;\r
     }\r
       Status = EFI_OUT_OF_RESOURCES;\r
       goto ERROR_1;\r
     }\r
+    Cache->ImageType = ImageTypeMax;\r
     InitializeListHead (&Cache->EntityDataList);\r
   }\r
 \r
     InitializeListHead (&Cache->EntityDataList);\r
   }\r
 \r
@@ -918,11 +928,26 @@ HttpBootGetBootFile (
     goto ERROR_5;\r
   }\r
 \r
     goto ERROR_5;\r
   }\r
 \r
+  //\r
+  // Check the image type according to server's response.\r
+  //\r
+  Status = HttpBootCheckImageType (\r
+             Private->BootFileUri,\r
+             Private->BootFileUriParser,\r
+             ResponseData->HeaderCount,\r
+             ResponseData->Headers,\r
+             ImageType\r
+             );\r
+  if (EFI_ERROR (Status)) {\r
+    goto ERROR_5;\r
+  }\r
+\r
   //\r
   // 3.2 Cache the response header.\r
   //\r
   if (Cache != NULL) {\r
     Cache->ResponseData = ResponseData;\r
   //\r
   // 3.2 Cache the response header.\r
   //\r
   if (Cache != NULL) {\r
     Cache->ResponseData = ResponseData;\r
+    Cache->ImageType = *ImageType;\r
   }\r
   \r
   //\r
   }\r
   \r
   //\r
index b929fa7dc29329daee69b94ecc5f6d882f4dd718..2fd7dfc7160724ffd3d318ab508bceca09fea572 100644 (file)
@@ -40,6 +40,7 @@ typedef struct {
   LIST_ENTRY                 Link;            // Link to the CacheList in driver's private data.\r
   EFI_HTTP_REQUEST_DATA      *RequestData;\r
   HTTP_IO_RESPONSE_DATA      *ResponseData;   // Not include any message-body data.\r
   LIST_ENTRY                 Link;            // Link to the CacheList in driver's private data.\r
   EFI_HTTP_REQUEST_DATA      *RequestData;\r
   HTTP_IO_RESPONSE_DATA      *ResponseData;   // Not include any message-body data.\r
+  HTTP_BOOT_IMAGE_TYPE       ImageType;\r
   UINTN                      EntityLength;\r
   LIST_ENTRY                 EntityDataList;  // Entity data (message-body)\r
 } HTTP_BOOT_CACHE_CONTENT;\r
   UINTN                      EntityLength;\r
   LIST_ENTRY                 EntityDataList;  // Entity data (message-body)\r
 } HTTP_BOOT_CACHE_CONTENT;\r
@@ -105,6 +106,7 @@ HttpBootCreateHttpIo (
   @param[out]      Buffer          The memory buffer to transfer the file to. IF Buffer is NULL,\r
                                    then the size of the requested file is returned in\r
                                    BufferSize.\r
   @param[out]      Buffer          The memory buffer to transfer the file to. IF Buffer is NULL,\r
                                    then the size of the requested file is returned in\r
                                    BufferSize.\r
+  @param[out]      ImageType       The image type of the downloaded file.\r
 \r
   @retval EFI_SUCCESS              The file was loaded.\r
   @retval EFI_INVALID_PARAMETER    BufferSize is NULL or Buffer Size is not NULL but Buffer is NULL.\r
 \r
   @retval EFI_SUCCESS              The file was loaded.\r
   @retval EFI_INVALID_PARAMETER    BufferSize is NULL or Buffer Size is not NULL but Buffer is NULL.\r
@@ -120,7 +122,8 @@ HttpBootGetBootFile (
   IN     HTTP_BOOT_PRIVATE_DATA   *Private,\r
   IN     BOOLEAN                  HeaderOnly,\r
   IN OUT UINTN                    *BufferSize,\r
   IN     HTTP_BOOT_PRIVATE_DATA   *Private,\r
   IN     BOOLEAN                  HeaderOnly,\r
   IN OUT UINTN                    *BufferSize,\r
-     OUT UINT8                    *Buffer\r
+     OUT UINT8                    *Buffer,\r
+     OUT HTTP_BOOT_IMAGE_TYPE     *ImageType\r
   );\r
 \r
 /**\r
   );\r
 \r
 /**\r
index b3e2576e1e5d079d9a2418707834792fea139ccf..76b794321e83a4de546751e7ee69907447a6d596 100644 (file)
@@ -55,6 +55,7 @@ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
 #include <Protocol/Http.h>\r
 #include <Protocol/Ip4Config2.h>\r
 #include <Protocol/Ip6Config.h>\r
 #include <Protocol/Http.h>\r
 #include <Protocol/Ip4Config2.h>\r
 #include <Protocol/Ip6Config.h>\r
+#include <Protocol/RamDisk.h>\r
 //\r
 // Produced Protocols\r
 //\r
 //\r
 // Produced Protocols\r
 //\r
@@ -70,6 +71,12 @@ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
 //\r
 #define HTTP_BOOT_DXE_VERSION  0xa\r
 \r
 //\r
 #define HTTP_BOOT_DXE_VERSION  0xa\r
 \r
+//\r
+// Provisional Standard Media Types defined in \r
+// http://www.iana.org/assignments/provisional-standard-media-types/provisional-standard-media-types.xhtml\r
+//\r
+#define HTTP_CONTENT_TYPE_APP_EFI           "application/efi"\r
+\r
 //\r
 // Protocol instances\r
 //\r
 //\r
 // Protocol instances\r
 //\r
@@ -83,6 +90,13 @@ extern EFI_COMPONENT_NAME_PROTOCOL  gHttpBootDxeComponentName;
 typedef struct _HTTP_BOOT_PRIVATE_DATA      HTTP_BOOT_PRIVATE_DATA;\r
 typedef struct _HTTP_BOOT_VIRTUAL_NIC       HTTP_BOOT_VIRTUAL_NIC;\r
 \r
 typedef struct _HTTP_BOOT_PRIVATE_DATA      HTTP_BOOT_PRIVATE_DATA;\r
 typedef struct _HTTP_BOOT_VIRTUAL_NIC       HTTP_BOOT_VIRTUAL_NIC;\r
 \r
+typedef enum  {\r
+  ImageTypeEfi,\r
+  ImageTypeVirtualCd,\r
+  ImageTypeVirtualDisk,\r
+  ImageTypeMax\r
+} HTTP_BOOT_IMAGE_TYPE;\r
+\r
 //\r
 // Include files with internal function prototypes\r
 //\r
 //\r
 // Include files with internal function prototypes\r
 //\r
@@ -166,6 +180,11 @@ struct _HTTP_BOOT_PRIVATE_DATA {
   EFI_IP_ADDRESS                            GatewayIp;\r
   EFI_IP_ADDRESS                            ServerIp;\r
   UINT16                                    Port;\r
   EFI_IP_ADDRESS                            GatewayIp;\r
   EFI_IP_ADDRESS                            ServerIp;\r
   UINT16                                    Port;\r
+\r
+  //\r
+  // The URI string attempt to download through HTTP, may point to\r
+  // the memory in cached DHCP offer, or to the memory in FilePathUri.\r
+  //\r
   CHAR8                                     *BootFileUri;\r
   VOID                                      *BootFileUriParser;\r
   UINTN                                     BootFileSize;\r
   CHAR8                                     *BootFileUri;\r
   VOID                                      *BootFileUriParser;\r
   UINTN                                     BootFileSize;\r
index 7393ecd3679c29fe3ce37ad9415df8ddbf9b5e01..d3df5f7d6e51402a8998286d2399c2a384e5e718 100644 (file)
@@ -81,6 +81,7 @@
   gEfiIp6ProtocolGuid                             ## TO_START\r
   gEfiIp6ConfigProtocolGuid                       ## TO_START\r
   gEfiNetworkInterfaceIdentifierProtocolGuid_31   ## SOMETIMES_CONSUMES\r
   gEfiIp6ProtocolGuid                             ## TO_START\r
   gEfiIp6ConfigProtocolGuid                       ## TO_START\r
   gEfiNetworkInterfaceIdentifierProtocolGuid_31   ## SOMETIMES_CONSUMES\r
+  gEfiRamDiskProtocolGuid                         ## SOMETIMES_CONSUMES\r
   gEfiHiiConfigAccessProtocolGuid                 ## BY_START\r
 \r
 [Guids]\r
   gEfiHiiConfigAccessProtocolGuid                 ## BY_START\r
 \r
 [Guids]\r
@@ -89,6 +90,8 @@
   ## SOMETIMES_PRODUCES ## GUID # HiiGetBrowserData     mHttpBootConfigStorageName\r
   ## SOMETIMES_CONSUMES ## HII\r
   gHttpBootConfigGuid\r
   ## SOMETIMES_PRODUCES ## GUID # HiiGetBrowserData     mHttpBootConfigStorageName\r
   ## SOMETIMES_CONSUMES ## HII\r
   gHttpBootConfigGuid\r
+  gEfiVirtualCdGuid            ## SOMETIMES_CONSUMES ## GUID\r
+  gEfiVirtualDiskGuid          ## SOMETIMES_CONSUMES ## GUID\r
 \r
 [UserExtensions.TianoCore."ExtraFiles"]\r
   HttpBootDxeExtra.uni\r
 \r
 [UserExtensions.TianoCore."ExtraFiles"]\r
   HttpBootDxeExtra.uni\r
index c4a3e707fb07c4950ada3955fac5a9ecb55a1b2d..cf643d86bc1936df146739c9ef43bd028445aed9 100644 (file)
@@ -17,6 +17,9 @@ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
 /**\r
   Enable the use of UEFI HTTP boot function.\r
 \r
 /**\r
   Enable the use of UEFI HTTP boot function.\r
 \r
+  If the driver has already been started but not satisfy the requirement (IP stack and \r
+  specified boot file path), this function will stop the driver and start it again.\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
   @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
@@ -24,7 +27,8 @@ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
   @param[in]    FilePath           The device specific path of the file to load.\r
 \r
   @retval EFI_SUCCESS              HTTP boot was successfully enabled.\r
   @param[in]    FilePath           The device specific path of the file to load.\r
 \r
   @retval EFI_SUCCESS              HTTP boot was successfully enabled.\r
-  @retval EFI_INVALID_PARAMETER    Private is NULL.\r
+  @retval EFI_INVALID_PARAMETER    Private is NULL or FilePath is NULL.\r
+  @retval EFI_INVALID_PARAMETER    The FilePath doesn't contain a valid URI device path node.\r
   @retval EFI_ALREADY_STARTED      The driver is already in started state.\r
   @retval EFI_OUT_OF_RESOURCES     There are not enough resources.\r
   \r
   @retval EFI_ALREADY_STARTED      The driver is already in started state.\r
   @retval EFI_OUT_OF_RESOURCES     There are not enough resources.\r
   \r
@@ -38,13 +42,50 @@ HttpBootStart (
 {\r
   UINTN                Index;\r
   EFI_STATUS           Status;\r
 {\r
   UINTN                Index;\r
   EFI_STATUS           Status;\r
+  CHAR8                *Uri;\r
+  \r
 \r
   if (Private == NULL || FilePath == NULL) {\r
     return EFI_INVALID_PARAMETER;\r
   }\r
 \r
   if (Private == NULL || FilePath == NULL) {\r
     return EFI_INVALID_PARAMETER;\r
   }\r
-\r
+  \r
+  //\r
+  // Check the URI in the input FilePath, in order to see whether it is\r
+  // required to boot from a new specified boot file. \r
+  //\r
+  Status = HttpBootParseFilePath (FilePath, &Uri);\r
+  if (EFI_ERROR (Status)) {\r
+    return EFI_INVALID_PARAMETER;\r
+  }\r
+  \r
+  //\r
+  // Check whether we need to stop and restart the HTTP boot driver.\r
+  //\r
   if (Private->Started) {\r
   if (Private->Started) {\r
-    return EFI_ALREADY_STARTED;\r
+    //\r
+    // Restart is needed in 2 cases:\r
+    // 1. Http boot driver has already been started but not on the required IP stack.\r
+    // 2. The specified boot file URI in FilePath is different with the one we have\r
+    // recorded before.\r
+    //\r
+    if ((UsingIpv6 != Private->UsingIpv6) || \r
+        ((Uri != NULL) && (AsciiStrCmp (Private->BootFileUri, Uri) != 0))) {\r
+      //\r
+      // Restart is required, first stop then continue this start function.\r
+      //\r
+      Status = HttpBootStop (Private);\r
+      if (EFI_ERROR (Status)) {\r
+        return Status;\r
+      }\r
+    } else {\r
+      //\r
+      // Restart is not required.\r
+      //\r
+      if (Uri != NULL) {\r
+        FreePool (Uri);\r
+      }\r
+      return EFI_ALREADY_STARTED;\r
+    }\r
   }\r
 \r
   //\r
   }\r
 \r
   //\r
@@ -55,17 +96,16 @@ HttpBootStart (
   } else if (!UsingIpv6 && Private->Ip4Nic != NULL) {\r
     Private->UsingIpv6 = FALSE;\r
   } else {\r
   } else if (!UsingIpv6 && Private->Ip4Nic != NULL) {\r
     Private->UsingIpv6 = FALSE;\r
   } else {\r
+    if (Uri != NULL) {\r
+      FreePool (Uri);\r
+    }\r
     return EFI_UNSUPPORTED;\r
   }\r
 \r
   //\r
     return EFI_UNSUPPORTED;\r
   }\r
 \r
   //\r
-  // Check whether the URI address is specified.\r
+  // Record the specified URI and prepare the URI parser if needed.\r
   //\r
   //\r
-  Status = HttpBootParseFilePath (FilePath, &Private->FilePathUri);\r
-  if (EFI_ERROR (Status)) {\r
-    return EFI_INVALID_PARAMETER;\r
-  }\r
-\r
+  Private->FilePathUri = Uri;\r
   if (Private->FilePathUri != NULL) {\r
     Status = HttpParseUrl (\r
                Private->FilePathUri,\r
   if (Private->FilePathUri != NULL) {\r
     Status = HttpParseUrl (\r
                Private->FilePathUri,\r
@@ -74,6 +114,7 @@ HttpBootStart (
                &Private->FilePathUriParser\r
                );\r
     if (EFI_ERROR (Status)) {\r
                &Private->FilePathUriParser\r
                );\r
     if (EFI_ERROR (Status)) {\r
+      FreePool (Private->FilePathUri);\r
       return Status;\r
     }\r
   }\r
       return Status;\r
     }\r
   }\r
@@ -101,7 +142,7 @@ HttpBootStart (
       return Status;\r
     }\r
   }\r
       return Status;\r
     }\r
   }\r
-  Private->Started = TRUE;\r
+  Private->Started   = TRUE;\r
 \r
   return EFI_SUCCESS;\r
 }\r
 \r
   return EFI_SUCCESS;\r
 }\r
@@ -161,9 +202,11 @@ HttpBootDhcp (
   @param[in]          Buffer          The memory buffer to transfer the file to. If Buffer is NULL,\r
                                       then the size of the requested file is returned in\r
                                       BufferSize.\r
   @param[in]          Buffer          The memory buffer to transfer the file to. If Buffer is NULL,\r
                                       then the size of the requested file is returned in\r
                                       BufferSize.\r
+  @param[out]         ImageType       The image type of the downloaded file.\r
 \r
   @retval EFI_SUCCESS                 Boot file was loaded successfully.\r
 \r
   @retval EFI_SUCCESS                 Boot file was loaded successfully.\r
-  @retval EFI_INVALID_PARAMETER       Private is NULL.\r
+  @retval EFI_INVALID_PARAMETER       Private is NULL, or ImageType is NULL, or BufferSize is NULL.\r
+  @retval EFI_INVALID_PARAMETER       *BufferSize is not zero, and Buffer is NULL.\r
   @retval EFI_NOT_STARTED             The driver is in stopped state.\r
   @retval EFI_BUFFER_TOO_SMALL        The BufferSize is too small to read the boot file. BufferSize has \r
                                       been updated with the size needed to complete the request.\r
   @retval EFI_NOT_STARTED             The driver is in stopped state.\r
   @retval EFI_BUFFER_TOO_SMALL        The BufferSize is too small to read the boot file. BufferSize has \r
                                       been updated with the size needed to complete the request.\r
@@ -175,12 +218,17 @@ EFI_STATUS
 HttpBootLoadFile (\r
   IN     HTTP_BOOT_PRIVATE_DATA       *Private,\r
   IN OUT UINTN                        *BufferSize,\r
 HttpBootLoadFile (\r
   IN     HTTP_BOOT_PRIVATE_DATA       *Private,\r
   IN OUT UINTN                        *BufferSize,\r
-  IN     VOID                         *Buffer       OPTIONAL\r
+  IN     VOID                         *Buffer,       OPTIONAL\r
+     OUT HTTP_BOOT_IMAGE_TYPE         *ImageType\r
   )\r
 {\r
   EFI_STATUS             Status;\r
 \r
   )\r
 {\r
   EFI_STATUS             Status;\r
 \r
-  if (Private == NULL) {\r
+  if (Private == NULL || ImageType == NULL || BufferSize == NULL ) {\r
+    return EFI_INVALID_PARAMETER;\r
+  }\r
+\r
+  if (*BufferSize != 0 && Buffer == NULL) {\r
     return EFI_INVALID_PARAMETER;\r
   }\r
   \r
     return EFI_INVALID_PARAMETER;\r
   }\r
   \r
@@ -222,7 +270,8 @@ HttpBootLoadFile (
                Private,\r
                TRUE,\r
                &Private->BootFileSize,\r
                Private,\r
                TRUE,\r
                &Private->BootFileSize,\r
-               NULL\r
+               NULL,\r
+               ImageType\r
                );\r
     if (EFI_ERROR (Status) && Status != EFI_BUFFER_TOO_SMALL) {\r
       //\r
                );\r
     if (EFI_ERROR (Status) && Status != EFI_BUFFER_TOO_SMALL) {\r
       //\r
@@ -233,7 +282,8 @@ HttpBootLoadFile (
                  Private,\r
                  FALSE,\r
                  &Private->BootFileSize,\r
                  Private,\r
                  FALSE,\r
                  &Private->BootFileSize,\r
-                 NULL\r
+                 NULL,\r
+                 ImageType\r
                  );\r
       if (EFI_ERROR (Status) && Status != EFI_BUFFER_TOO_SMALL) {\r
         return Status;\r
                  );\r
       if (EFI_ERROR (Status) && Status != EFI_BUFFER_TOO_SMALL) {\r
         return Status;\r
@@ -253,7 +303,8 @@ HttpBootLoadFile (
             Private,\r
             FALSE,\r
             BufferSize,\r
             Private,\r
             FALSE,\r
             BufferSize,\r
-            Buffer\r
+            Buffer,\r
+            ImageType\r
             );\r
 }\r
 \r
             );\r
 }\r
 \r
@@ -388,6 +439,7 @@ HttpBootDxeLoadFile (
   BOOLEAN                       MediaPresent;\r
   BOOLEAN                       UsingIpv6;\r
   EFI_STATUS                    Status;\r
   BOOLEAN                       MediaPresent;\r
   BOOLEAN                       UsingIpv6;\r
   EFI_STATUS                    Status;\r
+  HTTP_BOOT_IMAGE_TYPE          ImageType;\r
 \r
   if (This == NULL || BufferSize == NULL || FilePath == NULL) {\r
     return EFI_INVALID_PARAMETER;\r
 \r
   if (This == NULL || BufferSize == NULL || FilePath == NULL) {\r
     return EFI_INVALID_PARAMETER;\r
@@ -424,46 +476,34 @@ HttpBootDxeLoadFile (
   // Initialize HTTP boot.\r
   //\r
   Status = HttpBootStart (Private, UsingIpv6, FilePath);\r
   // Initialize HTTP boot.\r
   //\r
   Status = HttpBootStart (Private, UsingIpv6, FilePath);\r
-  if (Status == EFI_ALREADY_STARTED) {\r
-    //\r
-    // Restart the HTTP boot driver in 2 cases:\r
-    // 1. Http boot Driver has already been started but not on the required IP version.\r
-    // 2. The required boot FilePath is different with the one we produced in the device path\r
-    // protocol.\r
-    //\r
-    if ((UsingIpv6 != Private->UsingIpv6) || ((Private->FilePathUri != NULL) && (AsciiStrCmp (Private->BootFileUri, Private->FilePathUri) != 0))) {\r
-      Status = HttpBootStop (Private);\r
-      if (!EFI_ERROR (Status)) {\r
-        Status = HttpBootStart (Private, UsingIpv6, FilePath);\r
-      }\r
-    }\r
+  if (Status != EFI_SUCCESS && Status != EFI_ALREADY_STARTED) {\r
+    return Status;\r
   }\r
   }\r
-\r
+  \r
   //\r
   // Load the boot file.\r
   //\r
   //\r
   // Load the boot file.\r
   //\r
-  if (Status == EFI_SUCCESS || Status == EFI_ALREADY_STARTED) {\r
-    Status = HttpBootLoadFile (Private, BufferSize, Buffer);\r
+  ImageType = ImageTypeMax;\r
+  Status = HttpBootLoadFile (Private, BufferSize, Buffer, &ImageType);\r
+  if (EFI_ERROR (Status)) {\r
+    if (Status == EFI_BUFFER_TOO_SMALL && (ImageType == ImageTypeVirtualCd || ImageType == ImageTypeVirtualDisk)) {\r
+      Status = EFI_WARN_FILE_SYSTEM;\r
+    } else if (Status != EFI_BUFFER_TOO_SMALL) {\r
+      HttpBootStop (Private);\r
+    }\r
+    return Status;\r
   }\r
 \r
   }\r
 \r
-  if (Status != EFI_SUCCESS && Status != EFI_BUFFER_TOO_SMALL) {\r
-    HttpBootStop (Private);\r
-  } else {\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
+  // Register the RAM Disk to the system if needed.\r
+  //\r
+  if (ImageType == ImageTypeVirtualCd || ImageType == ImageTypeVirtualDisk) {\r
+    Status = HttpBootRegisterRamDisk (Private, *BufferSize, Buffer, ImageType);\r
+    if (!EFI_ERROR (Status)) {\r
+      Status = EFI_WARN_FILE_SYSTEM;\r
     }\r
   }\r
     }\r
   }\r
-\r
+  \r
   return Status;\r
 }\r
 \r
   return Status;\r
 }\r
 \r
index bd99a913c6c8cc166d47b9c8b4dc44a6beaa214c..66eca783af712e13457bc79ab9884b35e5a62b23 100644 (file)
@@ -1007,3 +1007,145 @@ HttpBootParseFilePath (
 \r
   return EFI_SUCCESS;\r
 }\r
 \r
   return EFI_SUCCESS;\r
 }\r
+\r
+/**\r
+  This function returns the image type according to server replied HTTP message\r
+  and also the image's URI info.\r
+\r
+  @param[in]    Uri              The pointer to the image's URI string.\r
+  @param[in]    UriParser        URI Parse result returned by NetHttpParseUrl(). \r
+  @param[in]    HeaderCount      Number of HTTP header structures in Headers list. \r
+  @param[in]    Headers          Array containing list of HTTP headers.\r
+  @param[out]   ImageType        The image type of the downloaded file.\r
+  \r
+  @retval EFI_SUCCESS            The image type is returned in ImageType.\r
+  @retval EFI_INVALID_PARAMETER  ImageType, Uri or UriParser is NULL.\r
+  @retval EFI_INVALID_PARAMETER  HeaderCount is not zero, and Headers is NULL.\r
+  @retval EFI_NOT_FOUND          Failed to identify the image type.\r
+  @retval Others                 Unexpect error happened.\r
+\r
+**/\r
+EFI_STATUS\r
+HttpBootCheckImageType (\r
+  IN      CHAR8                  *Uri,\r
+  IN      VOID                   *UriParser,\r
+  IN      UINTN                  HeaderCount,\r
+  IN      EFI_HTTP_HEADER        *Headers,\r
+     OUT  HTTP_BOOT_IMAGE_TYPE   *ImageType\r
+  )\r
+{\r
+  EFI_STATUS            Status;\r
+  EFI_HTTP_HEADER       *Header;\r
+  CHAR8                 *FilePath;\r
+  CHAR8                 *FilePost;\r
+\r
+  if (Uri == NULL || UriParser == NULL || ImageType == NULL) {\r
+    return EFI_INVALID_PARAMETER;\r
+  }\r
+\r
+  if (HeaderCount != 0 && Headers == NULL) {\r
+    return EFI_INVALID_PARAMETER;\r
+  }\r
+\r
+  //\r
+  // Determine the image type by the HTTP Content-Type header field first.\r
+  //   "application/efi" -> EFI Image\r
+  //\r
+  Header = HttpFindHeader (HeaderCount, Headers, HTTP_HEADER_CONTENT_TYPE);\r
+  if (Header != NULL) {\r
+    if (AsciiStriCmp (Header->FieldValue, HTTP_CONTENT_TYPE_APP_EFI) == 0) {\r
+      *ImageType = ImageTypeEfi;\r
+      return EFI_SUCCESS;\r
+    }\r
+  }\r
+\r
+  //\r
+  // Determine the image type by file extension:\r
+  //   *.efi -> EFI Image\r
+  //   *.iso -> CD/DVD Image\r
+  //   *.img -> Virtual Disk Image\r
+  //\r
+  Status = HttpUrlGetPath (\r
+             Uri,\r
+             UriParser,\r
+             &FilePath\r
+             );\r
+  if (EFI_ERROR (Status)) {\r
+    return Status;\r
+  }\r
+\r
+  FilePost = FilePath + AsciiStrLen (FilePath) - 4;\r
+  if (AsciiStrCmp (FilePost, ".efi") == 0) {\r
+    *ImageType = ImageTypeEfi;\r
+  } else if (AsciiStrCmp (FilePost, ".iso") == 0) {\r
+    *ImageType = ImageTypeVirtualCd;\r
+  } else if (AsciiStrCmp (FilePost, ".img") == 0) {\r
+    *ImageType = ImageTypeVirtualDisk;\r
+  } else {\r
+    *ImageType = ImageTypeMax;\r
+  }\r
+\r
+  FreePool (FilePath);\r
+\r
+  return (*ImageType < ImageTypeMax) ? EFI_SUCCESS : EFI_NOT_FOUND;\r
+}\r
+\r
+/**\r
+  This function register the RAM disk info to the system.\r
+  \r
+  @param[in]       Private         The pointer to the driver's private data.\r
+  @param[in]       BufferSize      The size of Buffer in bytes.\r
+  @param[in]       Buffer          The base address of the RAM disk.\r
+  @param[in]       ImageType       The image type of the file in Buffer.\r
+\r
+  @retval EFI_SUCCESS              The RAM disk has been registered.\r
+  @retval EFI_NOT_FOUND            No RAM disk protocol instances were found.\r
+  @retval EFI_UNSUPPORTED          The ImageType is not supported.\r
+  @retval Others                   Unexpected error happened.\r
+\r
+**/\r
+EFI_STATUS\r
+HttpBootRegisterRamDisk (\r
+  IN  HTTP_BOOT_PRIVATE_DATA       *Private,\r
+  IN  UINTN                        BufferSize,\r
+  IN  VOID                         *Buffer,\r
+  IN  HTTP_BOOT_IMAGE_TYPE         ImageType\r
+  )\r
+{\r
+  EFI_RAM_DISK_PROTOCOL      *RamDisk;\r
+  EFI_STATUS                 Status;\r
+  EFI_DEVICE_PATH_PROTOCOL   *DevicePath;\r
+  EFI_GUID                   *RamDiskType;\r
+  \r
+  ASSERT (Private != NULL);\r
+  ASSERT (Buffer != NULL);\r
+  ASSERT (BufferSize != 0);\r
+\r
+  Status = gBS->LocateProtocol (&gEfiRamDiskProtocolGuid, NULL, (VOID**) &RamDisk);\r
+  if (EFI_ERROR (Status)) {\r
+    DEBUG ((EFI_D_ERROR, "HTTP Boot: Couldn't find the RAM Disk protocol - %r\n", Status));\r
+    return Status;\r
+  }\r
+\r
+  if (ImageType == ImageTypeVirtualCd) {\r
+    RamDiskType = &gEfiVirtualCdGuid;\r
+  } else if (ImageType == ImageTypeVirtualDisk) {\r
+    RamDiskType = &gEfiVirtualDiskGuid;\r
+  } else {\r
+    return EFI_UNSUPPORTED;\r
+  }\r
+  \r
+  Status = RamDisk->Register (\r
+             (UINTN)Buffer,\r
+             (UINT64)BufferSize,\r
+             RamDiskType,\r
+             Private->UsingIpv6 ? Private->Ip6Nic->DevicePath : Private->Ip4Nic->DevicePath,\r
+             &DevicePath\r
+             );\r
+  if (EFI_ERROR (Status)) {\r
+    DEBUG ((EFI_D_ERROR, "HTTP Boot: Failed to register RAM Disk - %r\n", Status));\r
+  }\r
+\r
+  return Status;\r
+}\r
+\r
index f382d6309c25746308ee701a5a5161ccf175779d..28e8005d21585224b0792767fd88fedf7eeeb350 100644 (file)
@@ -347,4 +347,51 @@ HttpBootParseFilePath (
      OUT CHAR8                        **UriAddress\r
   );\r
 \r
      OUT CHAR8                        **UriAddress\r
   );\r
 \r
+/**\r
+  This function returns the image type according to server replied HTTP message\r
+  and also the image's URI info.\r
+\r
+  @param[in]    Uri              The pointer to the image's URI string.\r
+  @param[in]    UriParser        URI Parse result returned by NetHttpParseUrl(). \r
+  @param[in]    HeaderCount      Number of HTTP header structures in Headers list. \r
+  @param[in]    Headers          Array containing list of HTTP headers.\r
+  @param[out]   ImageType        The image type of the downloaded file.\r
+  \r
+  @retval EFI_SUCCESS            The image type is returned in ImageType.\r
+  @retval EFI_INVALID_PARAMETER  ImageType, Uri or UriParser is NULL.\r
+  @retval EFI_INVALID_PARAMETER  HeaderCount is not zero, and Headers is NULL.\r
+  @retval EFI_NOT_FOUND          Failed to identify the image type.\r
+  @retval Others                 Unexpect error happened.\r
+\r
+**/\r
+EFI_STATUS\r
+HttpBootCheckImageType (\r
+  IN      CHAR8                  *Uri,\r
+  IN      VOID                   *UriParser,\r
+  IN      UINTN                  HeaderCount,\r
+  IN      EFI_HTTP_HEADER        *Headers,\r
+     OUT  HTTP_BOOT_IMAGE_TYPE   *ImageType\r
+  );\r
+\r
+/**\r
+  This function register the RAM disk info to the system.\r
+  \r
+  @param[in]       Private         The pointer to the driver's private data.\r
+  @param[in]       BufferSize      The size of Buffer in bytes.\r
+  @param[in]       Buffer          The base address of the RAM disk.\r
+  @param[in]       ImageType       The image type of the file in Buffer.\r
+\r
+  @retval EFI_SUCCESS              The RAM disk has been registered.\r
+  @retval EFI_NOT_FOUND            No RAM disk protocol instances were found.\r
+  @retval EFI_UNSUPPORTED          The ImageType is not supported.\r
+  @retval Others                   Unexpected error happened.\r
+\r
+**/\r
+EFI_STATUS\r
+HttpBootRegisterRamDisk (\r
+  IN  HTTP_BOOT_PRIVATE_DATA       *Private,\r
+  IN  UINTN                        BufferSize,\r
+  IN  VOID                         *Buffer,\r
+  IN  HTTP_BOOT_IMAGE_TYPE         ImageType\r
+  );\r
 #endif\r
 #endif\r