/**\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] 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
{\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
+ \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
- 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
} 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
- // Check whether the URI address is specified.\r
+ // Record the specified URI and prepare the URI parser if needed.\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
&Private->FilePathUriParser\r
);\r
if (EFI_ERROR (Status)) {\r
+ FreePool (Private->FilePathUri);\r
return Status;\r
}\r
}\r
return Status;\r
}\r
}\r
- Private->Started = TRUE;\r
+ Private->Started = TRUE;\r
\r
return EFI_SUCCESS;\r
}\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
- @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
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
- 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
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
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
Private,\r
FALSE,\r
BufferSize,\r
- Buffer\r
+ Buffer,\r
+ ImageType\r
);\r
}\r
\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
// 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
// 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
- 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
return Status;\r
}\r
\r