diff options
author | Jiaxin Wu <jiaxin.wu@intel.com> | 2015-08-27 01:07:31 +0000 |
---|---|---|
committer | jiaxinwu <jiaxinwu@Edk2> | 2015-08-27 01:07:31 +0000 |
commit | d933e70a9761bf47941ac3d973cc5e7ee44da930 (patch) | |
tree | 02a479006074159f9df05b6f6d5102acab9c1ee6 /NetworkPkg/HttpBootDxe | |
parent | 85d21c18fd2d5a6df9c51cc66737c99bf6049853 (diff) | |
download | edk2-d933e70a9761bf47941ac3d973cc5e7ee44da930.tar.gz edk2-d933e70a9761bf47941ac3d973cc5e7ee44da930.tar.bz2 edk2-d933e70a9761bf47941ac3d973cc5e7ee44da930.zip |
NetworkPkg: Convert the UNIX to DOS end of line format
Convert the UNIX to DOS end of line format.
Contributed-under: TianoCore Contribution Agreement 1.0
Signed-off-by: Jiaxin Wu <jiaxin.wu@intel.com>
git-svn-id: https://svn.code.sf.net/p/edk2/code/trunk/edk2@18326 6f19259b-4bc3-4df7-8a09-765794883524
Diffstat (limited to 'NetworkPkg/HttpBootDxe')
-rw-r--r-- | NetworkPkg/HttpBootDxe/HttpBootClient.c | 1660 | ||||
-rw-r--r-- | NetworkPkg/HttpBootDxe/HttpBootClient.h | 278 | ||||
-rw-r--r-- | NetworkPkg/HttpBootDxe/HttpBootComponentName.c | 360 | ||||
-rw-r--r-- | NetworkPkg/HttpBootDxe/HttpBootComponentName.h | 198 | ||||
-rw-r--r-- | NetworkPkg/HttpBootDxe/HttpBootDhcp4.c | 1658 | ||||
-rw-r--r-- | NetworkPkg/HttpBootDxe/HttpBootDhcp4.h | 562 | ||||
-rw-r--r-- | NetworkPkg/HttpBootDxe/HttpBootDxe.c | 1118 | ||||
-rw-r--r-- | NetworkPkg/HttpBootDxe/HttpBootDxe.h | 606 | ||||
-rw-r--r-- | NetworkPkg/HttpBootDxe/HttpBootDxe.inf | 136 | ||||
-rw-r--r-- | NetworkPkg/HttpBootDxe/HttpBootImpl.c | 728 | ||||
-rw-r--r-- | NetworkPkg/HttpBootDxe/HttpBootImpl.h | 100 | ||||
-rw-r--r-- | NetworkPkg/HttpBootDxe/HttpBootSupport.c | 1180 | ||||
-rw-r--r-- | NetworkPkg/HttpBootDxe/HttpBootSupport.h | 500 |
13 files changed, 4542 insertions, 4542 deletions
diff --git a/NetworkPkg/HttpBootDxe/HttpBootClient.c b/NetworkPkg/HttpBootDxe/HttpBootClient.c index 2bf28c2c4d..3b4afc396f 100644 --- a/NetworkPkg/HttpBootDxe/HttpBootClient.c +++ b/NetworkPkg/HttpBootDxe/HttpBootClient.c @@ -1,830 +1,830 @@ -/** @file - Implementation of the boot file download function. - -Copyright (c) 2015, Intel Corporation. All rights reserved.<BR> -This program and the accompanying materials are licensed and made available under -the terms and conditions of the BSD License that accompanies this distribution. -The full text of the license may be found at -http://opensource.org/licenses/bsd-license.php. - -THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, -WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. - -**/ - -#include "HttpBootDxe.h" - -/** - Update the IP and URL device path node to include the boot resource information. - - @param[in] Private The pointer to the driver's private data. - - @retval EFI_SUCCESS Device patch successfully updated. - @retval EFI_OUT_OF_RESOURCES Could not allocate needed resources. - @retval Others Unexpected error happened. - -**/ -EFI_STATUS -HttpBootUpdateDevicePath ( - IN HTTP_BOOT_PRIVATE_DATA *Private - ) -{ - EFI_DEV_PATH *Node; - EFI_DEVICE_PATH_PROTOCOL *TmpDevicePath; - EFI_DEVICE_PATH_PROTOCOL *NewDevicePath; - UINTN Length; - EFI_STATUS Status; - - TmpDevicePath = NULL; - - // - // Update the IP node with DHCP assigned information. - // - if (!Private->UsingIpv6) { - Node = AllocateZeroPool (sizeof (IPv4_DEVICE_PATH)); - if (Node == NULL) { - return EFI_OUT_OF_RESOURCES; - } - Node->Ipv4.Header.Type = MESSAGING_DEVICE_PATH; - Node->Ipv4.Header.SubType = MSG_IPv4_DP; - SetDevicePathNodeLength (Node, sizeof (IPv4_DEVICE_PATH)); - CopyMem (&Node->Ipv4.LocalIpAddress, &Private->StationIp, sizeof (EFI_IPv4_ADDRESS)); - Node->Ipv4.RemotePort = Private->Port; - Node->Ipv4.Protocol = EFI_IP_PROTO_TCP; - Node->Ipv4.StaticIpAddress = FALSE; - CopyMem (&Node->Ipv4.GatewayIpAddress, &Private->GatewayIp, sizeof (EFI_IPv4_ADDRESS)); - CopyMem (&Node->Ipv4.SubnetMask, &Private->SubnetMask, sizeof (EFI_IPv4_ADDRESS)); - - TmpDevicePath = AppendDevicePathNode (Private->ParentDevicePath, (EFI_DEVICE_PATH_PROTOCOL*) Node); - FreePool (Node); - if (TmpDevicePath == NULL) { - return EFI_OUT_OF_RESOURCES; - } - } else { - ASSERT (FALSE); - } - - // - // Update the URI node with the boot file URI. - // - Length = sizeof (EFI_DEVICE_PATH_PROTOCOL) + AsciiStrSize (Private->BootFileUri); - Node = AllocatePool (Length); - if (Node == NULL) { - FreePool (TmpDevicePath); - return EFI_OUT_OF_RESOURCES; - } - Node->DevPath.Type = MESSAGING_DEVICE_PATH; - Node->DevPath.SubType = MSG_URI_DP; - SetDevicePathNodeLength (Node, Length); - CopyMem ((UINT8*) Node + sizeof (EFI_DEVICE_PATH_PROTOCOL), Private->BootFileUri, AsciiStrSize (Private->BootFileUri)); - - NewDevicePath = AppendDevicePathNode (TmpDevicePath, (EFI_DEVICE_PATH_PROTOCOL*) Node); - FreePool (Node); - FreePool (TmpDevicePath); - if (NewDevicePath == NULL) { - return EFI_OUT_OF_RESOURCES; - } - - // - // Reinstall the device path protocol of the child handle. - // - Status = gBS->ReinstallProtocolInterface ( - Private->ChildHandle, - &gEfiDevicePathProtocolGuid, - Private->DevicePath, - NewDevicePath - ); - if (EFI_ERROR (Status)) { - return Status; - } - - FreePool (Private->DevicePath); - Private->DevicePath = NewDevicePath; - return EFI_SUCCESS; -} - -/** - Parse the boot file URI information from the selected Dhcp4 offer packet. - - @param[in] Private The pointer to the driver's private data. - - @retval EFI_SUCCESS Successfully parsed out all the boot information. - @retval Others Failed to parse out the boot information. - -**/ -EFI_STATUS -HttpBootExtractUriInfo ( - IN HTTP_BOOT_PRIVATE_DATA *Private - ) -{ - HTTP_BOOT_DHCP4_PACKET_CACHE *SelectOffer; - HTTP_BOOT_DHCP4_PACKET_CACHE *HttpOffer; - UINT32 SelectIndex; - UINT32 ProxyIndex; - EFI_DHCP4_PACKET_OPTION *Option; - EFI_STATUS Status; - - ASSERT (Private != NULL); - ASSERT (Private->SelectIndex != 0); - SelectIndex = Private->SelectIndex - 1; - ASSERT (SelectIndex < HTTP_BOOT_OFFER_MAX_NUM); - - Status = EFI_SUCCESS; - - // - // SelectOffer contains the IP address configuration and name server configuration. - // HttpOffer contains the boot file URL. - // - SelectOffer = &Private->OfferBuffer[SelectIndex].Dhcp4; - if ((SelectOffer->OfferType == HttpOfferTypeDhcpIpUri) || (SelectOffer->OfferType == HttpOfferTypeDhcpNameUriDns)) { - HttpOffer = SelectOffer; - } else { - ASSERT (Private->SelectProxyType != HttpOfferTypeMax); - ProxyIndex = Private->OfferIndex[Private->SelectProxyType][0]; - HttpOffer = &Private->OfferBuffer[ProxyIndex].Dhcp4; - } - - // - // Configure the default DNS server if server assigned. - // - if ((SelectOffer->OfferType == HttpOfferTypeDhcpNameUriDns) || (SelectOffer->OfferType == HttpOfferTypeDhcpDns)) { - Option = SelectOffer->OptList[HTTP_BOOT_DHCP4_TAG_INDEX_DNS_SERVER]; - ASSERT (Option != NULL); - Status = HttpBootRegisterIp4Dns ( - Private, - Option->Length, - Option->Data - ); - if (EFI_ERROR (Status)) { - return Status; - } - } - - // - // Extract the port from URL, and use default HTTP port 80 if not provided. - // - Status = HttpUrlGetPort ( - (CHAR8*) HttpOffer->OptList[HTTP_BOOT_DHCP4_TAG_INDEX_BOOTFILE]->Data, - HttpOffer->UriParser, - &Private->Port - ); - if (EFI_ERROR (Status) || Private->Port == 0) { - Private->Port = 80; - } - - // - // Record the URI of boot file from the selected HTTP offer. - // - Private->BootFileUriParser = HttpOffer->UriParser; - Private->BootFileUri = (CHAR8*) HttpOffer->OptList[HTTP_BOOT_DHCP4_TAG_INDEX_BOOTFILE]->Data; - - - // - // All boot informations are valid here. - // - AsciiPrint ("\n URI: %a", Private->BootFileUri); - - // - // Update the device path to include the IP and boot URI information. - // - Status = HttpBootUpdateDevicePath (Private); - - return Status; -} - -/** - Discover all the boot information for boot file. - - @param[in, out] Private The pointer to the driver's private data. - - @retval EFI_SUCCESS Successfully obtained all the boot information . - @retval Others Failed to retrieve the boot information. - -**/ -EFI_STATUS -HttpBootDiscoverBootInfo ( - IN OUT HTTP_BOOT_PRIVATE_DATA *Private - ) -{ - EFI_STATUS Status; - - // - // Start D.O.R.A/S.A.R.R exchange to acquire station ip address and - // other Http boot information. - // - Status = HttpBootDhcp (Private); - if (EFI_ERROR (Status)) { - return Status; - } - - if (!Private->UsingIpv6) { - Status = HttpBootExtractUriInfo (Private); - } else { - ASSERT (FALSE); - } - - return Status; -} - -/** - Create a HttpIo instance for the file download. - - @param[in] Private The pointer to the driver's private data. - - @retval EFI_SUCCESS Successfully created. - @retval Others Failed to create HttpIo. - -**/ -EFI_STATUS -HttpBootCreateHttpIo ( - IN HTTP_BOOT_PRIVATE_DATA *Private - ) -{ - HTTP_IO_CONFIG_DATA ConfigData; - EFI_STATUS Status; - - ASSERT (Private != NULL); - - ZeroMem (&ConfigData, sizeof (HTTP_IO_CONFIG_DATA)); - if (!Private->UsingIpv6) { - ConfigData.Config4.HttpVersion = HttpVersion11; - ConfigData.Config4.RequestTimeOut = HTTP_BOOT_REQUEST_TIMEOUT; - IP4_COPY_ADDRESS (&ConfigData.Config4.LocalIp, &Private->StationIp.v4); - IP4_COPY_ADDRESS (&ConfigData.Config4.SubnetMask, &Private->SubnetMask.v4); - } else { - ASSERT (FALSE); - } - - Status = HttpIoCreateIo ( - Private->Image, - Private->Controller, - Private->UsingIpv6 ? IP_VERSION_6 : IP_VERSION_4, - &ConfigData, - &Private->HttpIo - ); - if (EFI_ERROR (Status)) { - return Status; - } - - Private->HttpCreated = TRUE; - return EFI_SUCCESS; -} - -/** - Get the file content from cached data. - - @param[in] Private The pointer to the driver's private data. - @param[in] Uri Uri of the file to be retrieved from cache. - @param[in, out] BufferSize On input the size of Buffer in bytes. On output with a return - code of EFI_SUCCESS, the amount of data transferred to - Buffer. On output with a return code of EFI_BUFFER_TOO_SMALL, - the size of Buffer required to retrieve the requested file. - @param[out] Buffer The memory buffer to transfer the file to. IF Buffer is NULL, - then the size of the requested file is returned in - BufferSize. - - @retval EFI_SUCCESS Successfully created. - @retval Others Failed to create HttpIo. - -**/ -EFI_STATUS -HttpBootGetFileFromCache ( - IN HTTP_BOOT_PRIVATE_DATA *Private, - IN CHAR16 *Uri, - IN OUT UINTN *BufferSize, - OUT UINT8 *Buffer - ) -{ - LIST_ENTRY *Entry; - LIST_ENTRY *Entry2; - HTTP_BOOT_CACHE_CONTENT *Cache; - HTTP_BOOT_ENTITY_DATA *EntityData; - UINTN CopyedSize; - - if (Uri == NULL || BufferSize == 0 || Buffer == NULL) { - return EFI_INVALID_PARAMETER; - } - - NET_LIST_FOR_EACH (Entry, &Private->CacheList) { - Cache = NET_LIST_USER_STRUCT (Entry, HTTP_BOOT_CACHE_CONTENT, Link); - // - // Compare the URI to see whether we already have a cache for this file. - // - if ((Cache->RequestData != NULL) && - (Cache->RequestData->Url != NULL) && - (StrCmp (Uri, Cache->RequestData->Url) == 0)) - { - // - // Hit cache, check buffer size. - // - if (*BufferSize < Cache->EntityLength) { - *BufferSize = Cache->EntityLength; - return EFI_BUFFER_TOO_SMALL; - } - - // - // Fill data to buffer. - // - CopyedSize = 0; - NET_LIST_FOR_EACH (Entry2, &Cache->EntityDataList) { - EntityData = NET_LIST_USER_STRUCT (Entry2, HTTP_BOOT_ENTITY_DATA, Link); - if (*BufferSize > CopyedSize) { - CopyMem ( - Buffer + CopyedSize, - EntityData->DataStart, - MIN (EntityData->DataLength, *BufferSize - CopyedSize) - ); - CopyedSize += MIN (EntityData->DataLength, *BufferSize - CopyedSize); - } - } - *BufferSize = CopyedSize; - return EFI_SUCCESS; - } - } - - return EFI_NOT_FOUND; -} - -/** - Release all the resource of a cache item. - - @param[in] Cache The pointer to the cache item. - -**/ -VOID -HttpBootFreeCache ( - IN HTTP_BOOT_CACHE_CONTENT *Cache - ) -{ - UINTN Index; - LIST_ENTRY *Entry; - LIST_ENTRY *NextEntry; - HTTP_BOOT_ENTITY_DATA *EntityData; - - if (Cache != NULL) { - // - // Free the request data - // - if (Cache->RequestData != NULL) { - if (Cache->RequestData->Url != NULL) { - FreePool (Cache->RequestData->Url); - } - FreePool (Cache->RequestData); - } - - // - // Free the response header - // - if (Cache->ResponseData != NULL) { - if (Cache->ResponseData->Headers != NULL) { - for (Index = 0; Index < Cache->ResponseData->HeaderCount; Index++) { - FreePool (Cache->ResponseData->Headers[Index].FieldName); - FreePool (Cache->ResponseData->Headers[Index].FieldValue); - } - FreePool (Cache->ResponseData->Headers); - } - } - - // - // Free the response body - // - NET_LIST_FOR_EACH_SAFE (Entry, NextEntry, &Cache->EntityDataList) { - EntityData = NET_LIST_USER_STRUCT (Entry, HTTP_BOOT_ENTITY_DATA, Link); - if (EntityData->Block != NULL) { - FreePool (EntityData->Block); - } - RemoveEntryList (&EntityData->Link); - FreePool (EntityData); - } - - FreePool (Cache); - } -} - -/** - Clean up all cached data. - - @param[in] Private The pointer to the driver's private data. - -**/ -VOID -HttpBootFreeCacheList ( - IN HTTP_BOOT_PRIVATE_DATA *Private - ) -{ - LIST_ENTRY *Entry; - LIST_ENTRY *NextEntry; - HTTP_BOOT_CACHE_CONTENT *Cache; - - NET_LIST_FOR_EACH_SAFE (Entry, NextEntry, &Private->CacheList) { - Cache = NET_LIST_USER_STRUCT (Entry, HTTP_BOOT_CACHE_CONTENT, Link); - RemoveEntryList (&Cache->Link); - HttpBootFreeCache (Cache); - } -} - -/** - A callback function to intercept events during message parser. - - This function will be invoked during HttpParseMessageBody() with various events type. An error - return status of the callback function will cause the HttpParseMessageBody() aborted. - - @param[in] EventType Event type of this callback call. - @param[in] Data A pointer to data buffer. - @param[in] Length Length in bytes of the Data. - @param[in] Context Callback context set by HttpInitMsgParser(). - - @retval EFI_SUCCESS Continue to parser the message body. - @retval Others Abort the parse. - -**/ -EFI_STATUS -EFIAPI -HttpBootGetBootFileCallback ( - IN HTTP_BODY_PARSE_EVENT EventType, - IN CHAR8 *Data, - IN UINTN Length, - IN VOID *Context - ) -{ - HTTP_BOOT_CALLBACK_DATA *CallbackData; - HTTP_BOOT_ENTITY_DATA *NewEntityData; - - // - // We only care about the entity data. - // - if (EventType != BodyParseEventOnData) { - return EFI_SUCCESS; - } - - CallbackData = (HTTP_BOOT_CALLBACK_DATA *) Context; - - // - // Save the data into cache list. - // - NewEntityData = AllocatePool (sizeof (HTTP_BOOT_ENTITY_DATA)); - if (NewEntityData == NULL) { - return EFI_OUT_OF_RESOURCES; - } - if (CallbackData->NewBlock) { - NewEntityData->Block = CallbackData->Block; - CallbackData->Block = NULL; - } - NewEntityData->DataLength = Length; - NewEntityData->DataStart = (UINT8*) Data; - InsertTailList (&CallbackData->Cache->EntityDataList, &NewEntityData->Link); - - // - // Copy data if caller has provided a buffer. - // - if (CallbackData->BufferSize > CallbackData->CopyedSize) { - CopyMem ( - CallbackData->Buffer + CallbackData->CopyedSize, - Data, - MIN (Length, CallbackData->BufferSize - CallbackData->CopyedSize) - ); - CallbackData->CopyedSize += MIN (Length, CallbackData->BufferSize - CallbackData->CopyedSize); - } - - return EFI_SUCCESS; -} - -/** - This function download the boot file by using UEFI HTTP protocol. - - @param[in] Private The pointer to the driver's private data. - @param[in] HeaderOnly Only request the response header, it could save a lot of time if - the caller only want to know the size of the requested file. - @param[in, out] BufferSize On input the size of Buffer in bytes. On output with a return - code of EFI_SUCCESS, the amount of data transferred to - Buffer. On output with a return code of EFI_BUFFER_TOO_SMALL, - the size of Buffer required to retrieve the requested file. - @param[out] Buffer The memory buffer to transfer the file to. IF Buffer is NULL, - then the size of the requested file is returned in - BufferSize. - - @retval EFI_SUCCESS The file was loaded. - @retval EFI_INVALID_PARAMETER BufferSize is NULL or Buffer Size is not NULL but Buffer is NULL. - @retval EFI_OUT_OF_RESOURCES Could not allocate needed resources - @retval EFI_BUFFER_TOO_SMALL The BufferSize is too small to read the current directory entry. - BufferSize has been updated with the size needed to complete - the request. - @retval Others Unexpected error happened. - -**/ -EFI_STATUS -HttpBootGetBootFile ( - IN HTTP_BOOT_PRIVATE_DATA *Private, - IN BOOLEAN HeaderOnly, - IN OUT UINTN *BufferSize, - OUT UINT8 *Buffer - ) -{ - EFI_STATUS Status; - CHAR8 *HostName; - EFI_HTTP_REQUEST_DATA *RequestData; - HTTP_IO_RESOPNSE_DATA *ResponseData; - HTTP_IO_RESOPNSE_DATA ResponseBody; - HTTP_IO *HttpIo; - HTTP_IO_HEADER *HttpIoHeader; - VOID *Parser; - HTTP_BOOT_CALLBACK_DATA Context; - UINTN ContentLength; - HTTP_BOOT_CACHE_CONTENT *Cache; - UINT8 *Block; - CHAR16 *Url; - - ASSERT (Private != NULL); - ASSERT (Private->HttpCreated); - - if (BufferSize == NULL) { - return EFI_INVALID_PARAMETER; - } - - if (*BufferSize != 0 && Buffer == NULL) { - return EFI_INVALID_PARAMETER; - } - - // - // First, check whether we already cached the requested Uri. - // - Url = AllocatePool ((AsciiStrLen (Private->BootFileUri) + 1) * sizeof (CHAR16)); - if (Url == NULL) { - return EFI_OUT_OF_RESOURCES; - } - AsciiStrToUnicodeStr (Private->BootFileUri, Url); - if (!HeaderOnly) { - Status = HttpBootGetFileFromCache (Private, Url, BufferSize, Buffer); - if (Status != EFI_NOT_FOUND) { - FreePool (Url); - return Status; - } - } - - // - // Not found in cache, try to download it through HTTP. - // - - // - // 1. Create a temp cache item for the requested URI. - // - Cache = NULL; - if (!HeaderOnly) { - Cache = AllocateZeroPool (sizeof (HTTP_BOOT_CACHE_CONTENT)); - if (Cache == NULL) { - Status = EFI_OUT_OF_RESOURCES; - goto ERROR_1; - } - InitializeListHead (&Cache->EntityDataList); - } - - // - // 2. Send HTTP request message. - // - - // - // 2.1 Build HTTP header for the request, 3 header is needed to download a boot file: - // Host - // Accept - // User-Agent - // - HttpIoHeader = HttpBootCreateHeader (3); - if (HttpIoHeader == NULL) { - Status = EFI_OUT_OF_RESOURCES; - goto ERROR_2; - } - - // - // Add HTTP header field 1: Host - // - HostName = NULL; - Status = HttpUrlGetHostName ( - Private->BootFileUri, - Private->BootFileUriParser, - &HostName - ); - if (EFI_ERROR (Status)) { - goto ERROR_3; - } - Status = HttpBootSetHeader ( - HttpIoHeader, - HTTP_FIELD_NAME_HOST, - HostName - ); - FreePool (HostName); - if (EFI_ERROR (Status)) { - goto ERROR_3; - } - - // - // Add HTTP header field 2: Accept - // - Status = HttpBootSetHeader ( - HttpIoHeader, - HTTP_FIELD_NAME_ACCEPT, - "*/*" - ); - if (EFI_ERROR (Status)) { - goto ERROR_3; - } - - // - // Add HTTP header field 3: User-Agent - // - Status = HttpBootSetHeader ( - HttpIoHeader, - HTTP_FIELD_NAME_USER_AGENT, - HTTP_USER_AGENT_EFI_HTTP_BOOT - ); - if (EFI_ERROR (Status)) { - goto ERROR_3; - } - - // - // 2.2 Build the rest of HTTP request info. - // - RequestData = AllocatePool (sizeof (EFI_HTTP_REQUEST_DATA)); - if (RequestData == NULL) { - Status = EFI_OUT_OF_RESOURCES; - goto ERROR_3; - } - RequestData->Method = HeaderOnly ? HttpMethodHead : HttpMethodGet; - RequestData->Url = Url; - if (RequestData->Url == NULL) { - Status = EFI_OUT_OF_RESOURCES; - goto ERROR_4; - } - AsciiStrToUnicodeStr (Private->BootFileUri, RequestData->Url); - - // - // 2.3 Record the request info in a temp cache item. - // - if (!HeaderOnly) { - Cache->RequestData = RequestData; - } - - // - // 2.4 Send out the request to HTTP server. - // - HttpIo = &Private->HttpIo; - Status = HttpIoSendRequest ( - HttpIo, - RequestData, - HttpIoHeader->HeaderCount, - HttpIoHeader->Headers, - 0, - NULL - ); - if (EFI_ERROR (Status)) { - goto ERROR_4; - } - - // - // 3. Receive HTTP response message. - // - - // - // 3.1 First step, use zero BodyLength to only receive the response headers. - // - ResponseData = AllocateZeroPool (sizeof(HTTP_IO_RESOPNSE_DATA)); - if (ResponseData == NULL) { - Status = EFI_OUT_OF_RESOURCES; - goto ERROR_4; - } - Status = HttpIoRecvResponse ( - &Private->HttpIo, - TRUE, - ResponseData - ); - if (EFI_ERROR (Status)) { - goto ERROR_5; - } - - // - // 3.2 Cache the response header. - // - if (!HeaderOnly) { - Cache->ResponseData = ResponseData; - } - - // - // 3.3 Init a message-body parser from the header information. - // - Parser = NULL; - Context.NewBlock = FALSE; - Context.Block = NULL; - Context.CopyedSize = 0; - Context.Buffer = Buffer; - Context.BufferSize = *BufferSize; - Context.Cache = Cache; - Status = HttpInitMsgParser ( - HeaderOnly? HttpMethodHead : HttpMethodGet, - ResponseData->Response.StatusCode, - ResponseData->HeaderCount, - ResponseData->Headers, - HttpBootGetBootFileCallback, - (VOID*) &Context, - &Parser - ); - if (EFI_ERROR (Status)) { - goto ERROR_6; - } - - // - // 3.4 Continue to receive and parse message-body if needed. - // - if (!HeaderOnly) { - ZeroMem (&ResponseBody, sizeof (HTTP_IO_RESOPNSE_DATA)); - while (!HttpIsMessageComplete (Parser)) { - // - // Allocate a new block to hold the message-body. - // - Block = AllocatePool (HTTP_BOOT_BLOCK_SIZE); - if (Block == NULL) { - Status = EFI_OUT_OF_RESOURCES; - goto ERROR_6; - } - ResponseBody.Body = (CHAR8*) Block; - ResponseBody.BodyLength = HTTP_BOOT_BLOCK_SIZE; - Status = HttpIoRecvResponse ( - &Private->HttpIo, - FALSE, - &ResponseBody - ); - if (EFI_ERROR (Status)) { - goto ERROR_6; - } - - // - // Parse the new received block of the message-body, the block will be saved in cache. - // - Context.NewBlock = TRUE; - Context.Block = Block; - Status = HttpParseMessageBody ( - Parser, - ResponseBody.BodyLength, - ResponseBody.Body - ); - if (EFI_ERROR (Status)) { - goto ERROR_6; - } - } - } - - // - // 3.5 Message-body receive & parse is completed, get the file size. - // - Status = HttpGetEntityLength (Parser, &ContentLength); - if (EFI_ERROR (Status)) { - goto ERROR_6; - } - - if (*BufferSize < ContentLength) { - Status = EFI_BUFFER_TOO_SMALL; - } - *BufferSize = ContentLength; - - // - // 4. Save the cache item to driver's cache list and return. - // - if (!HeaderOnly) { - Cache->EntityLength = ContentLength; - InsertTailList (&Private->CacheList, &Cache->Link); - } - - if (Parser != NULL) { - HttpFreeMsgParser (Parser); - } - - return EFI_SUCCESS; - -ERROR_6: - if (Parser != NULL) { - HttpFreeMsgParser (Parser); - } - if (Context.Block != NULL) { - FreePool (Context.Block); - } - HttpBootFreeCache (Cache); - -ERROR_5: - if (ResponseData != NULL) { - FreePool (ResponseData); - } -ERROR_4: - if (RequestData != NULL) { - FreePool (RequestData); - } -ERROR_3: - HttpBootFreeHeader (HttpIoHeader); -ERROR_2: - if (Cache != NULL) { - FreePool (Cache); - } -ERROR_1: - if (Url != NULL) { - FreePool (Url); - } - - return Status; -} +/** @file
+ Implementation of the boot file download function.
+
+Copyright (c) 2015, Intel Corporation. All rights reserved.<BR>
+This program and the accompanying materials are licensed and made available under
+the terms and conditions of the BSD License that accompanies this distribution.
+The full text of the license may be found at
+http://opensource.org/licenses/bsd-license.php.
+
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+**/
+
+#include "HttpBootDxe.h"
+
+/**
+ Update the IP and URL device path node to include the boot resource information.
+
+ @param[in] Private The pointer to the driver's private data.
+
+ @retval EFI_SUCCESS Device patch successfully updated.
+ @retval EFI_OUT_OF_RESOURCES Could not allocate needed resources.
+ @retval Others Unexpected error happened.
+
+**/
+EFI_STATUS
+HttpBootUpdateDevicePath (
+ IN HTTP_BOOT_PRIVATE_DATA *Private
+ )
+{
+ EFI_DEV_PATH *Node;
+ EFI_DEVICE_PATH_PROTOCOL *TmpDevicePath;
+ EFI_DEVICE_PATH_PROTOCOL *NewDevicePath;
+ UINTN Length;
+ EFI_STATUS Status;
+
+ TmpDevicePath = NULL;
+
+ //
+ // Update the IP node with DHCP assigned information.
+ //
+ if (!Private->UsingIpv6) {
+ Node = AllocateZeroPool (sizeof (IPv4_DEVICE_PATH));
+ if (Node == NULL) {
+ return EFI_OUT_OF_RESOURCES;
+ }
+ Node->Ipv4.Header.Type = MESSAGING_DEVICE_PATH;
+ Node->Ipv4.Header.SubType = MSG_IPv4_DP;
+ SetDevicePathNodeLength (Node, sizeof (IPv4_DEVICE_PATH));
+ CopyMem (&Node->Ipv4.LocalIpAddress, &Private->StationIp, sizeof (EFI_IPv4_ADDRESS));
+ Node->Ipv4.RemotePort = Private->Port;
+ Node->Ipv4.Protocol = EFI_IP_PROTO_TCP;
+ Node->Ipv4.StaticIpAddress = FALSE;
+ CopyMem (&Node->Ipv4.GatewayIpAddress, &Private->GatewayIp, sizeof (EFI_IPv4_ADDRESS));
+ CopyMem (&Node->Ipv4.SubnetMask, &Private->SubnetMask, sizeof (EFI_IPv4_ADDRESS));
+
+ TmpDevicePath = AppendDevicePathNode (Private->ParentDevicePath, (EFI_DEVICE_PATH_PROTOCOL*) Node);
+ FreePool (Node);
+ if (TmpDevicePath == NULL) {
+ return EFI_OUT_OF_RESOURCES;
+ }
+ } else {
+ ASSERT (FALSE);
+ }
+
+ //
+ // Update the URI node with the boot file URI.
+ //
+ Length = sizeof (EFI_DEVICE_PATH_PROTOCOL) + AsciiStrSize (Private->BootFileUri);
+ Node = AllocatePool (Length);
+ if (Node == NULL) {
+ FreePool (TmpDevicePath);
+ return EFI_OUT_OF_RESOURCES;
+ }
+ Node->DevPath.Type = MESSAGING_DEVICE_PATH;
+ Node->DevPath.SubType = MSG_URI_DP;
+ SetDevicePathNodeLength (Node, Length);
+ CopyMem ((UINT8*) Node + sizeof (EFI_DEVICE_PATH_PROTOCOL), Private->BootFileUri, AsciiStrSize (Private->BootFileUri));
+
+ NewDevicePath = AppendDevicePathNode (TmpDevicePath, (EFI_DEVICE_PATH_PROTOCOL*) Node);
+ FreePool (Node);
+ FreePool (TmpDevicePath);
+ if (NewDevicePath == NULL) {
+ return EFI_OUT_OF_RESOURCES;
+ }
+
+ //
+ // Reinstall the device path protocol of the child handle.
+ //
+ Status = gBS->ReinstallProtocolInterface (
+ Private->ChildHandle,
+ &gEfiDevicePathProtocolGuid,
+ Private->DevicePath,
+ NewDevicePath
+ );
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+
+ FreePool (Private->DevicePath);
+ Private->DevicePath = NewDevicePath;
+ return EFI_SUCCESS;
+}
+
+/**
+ Parse the boot file URI information from the selected Dhcp4 offer packet.
+
+ @param[in] Private The pointer to the driver's private data.
+
+ @retval EFI_SUCCESS Successfully parsed out all the boot information.
+ @retval Others Failed to parse out the boot information.
+
+**/
+EFI_STATUS
+HttpBootExtractUriInfo (
+ IN HTTP_BOOT_PRIVATE_DATA *Private
+ )
+{
+ HTTP_BOOT_DHCP4_PACKET_CACHE *SelectOffer;
+ HTTP_BOOT_DHCP4_PACKET_CACHE *HttpOffer;
+ UINT32 SelectIndex;
+ UINT32 ProxyIndex;
+ EFI_DHCP4_PACKET_OPTION *Option;
+ EFI_STATUS Status;
+
+ ASSERT (Private != NULL);
+ ASSERT (Private->SelectIndex != 0);
+ SelectIndex = Private->SelectIndex - 1;
+ ASSERT (SelectIndex < HTTP_BOOT_OFFER_MAX_NUM);
+
+ Status = EFI_SUCCESS;
+
+ //
+ // SelectOffer contains the IP address configuration and name server configuration.
+ // HttpOffer contains the boot file URL.
+ //
+ SelectOffer = &Private->OfferBuffer[SelectIndex].Dhcp4;
+ if ((SelectOffer->OfferType == HttpOfferTypeDhcpIpUri) || (SelectOffer->OfferType == HttpOfferTypeDhcpNameUriDns)) {
+ HttpOffer = SelectOffer;
+ } else {
+ ASSERT (Private->SelectProxyType != HttpOfferTypeMax);
+ ProxyIndex = Private->OfferIndex[Private->SelectProxyType][0];
+ HttpOffer = &Private->OfferBuffer[ProxyIndex].Dhcp4;
+ }
+
+ //
+ // Configure the default DNS server if server assigned.
+ //
+ if ((SelectOffer->OfferType == HttpOfferTypeDhcpNameUriDns) || (SelectOffer->OfferType == HttpOfferTypeDhcpDns)) {
+ Option = SelectOffer->OptList[HTTP_BOOT_DHCP4_TAG_INDEX_DNS_SERVER];
+ ASSERT (Option != NULL);
+ Status = HttpBootRegisterIp4Dns (
+ Private,
+ Option->Length,
+ Option->Data
+ );
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+ }
+
+ //
+ // Extract the port from URL, and use default HTTP port 80 if not provided.
+ //
+ Status = HttpUrlGetPort (
+ (CHAR8*) HttpOffer->OptList[HTTP_BOOT_DHCP4_TAG_INDEX_BOOTFILE]->Data,
+ HttpOffer->UriParser,
+ &Private->Port
+ );
+ if (EFI_ERROR (Status) || Private->Port == 0) {
+ Private->Port = 80;
+ }
+
+ //
+ // Record the URI of boot file from the selected HTTP offer.
+ //
+ Private->BootFileUriParser = HttpOffer->UriParser;
+ Private->BootFileUri = (CHAR8*) HttpOffer->OptList[HTTP_BOOT_DHCP4_TAG_INDEX_BOOTFILE]->Data;
+
+
+ //
+ // All boot informations are valid here.
+ //
+ AsciiPrint ("\n URI: %a", Private->BootFileUri);
+
+ //
+ // Update the device path to include the IP and boot URI information.
+ //
+ Status = HttpBootUpdateDevicePath (Private);
+
+ return Status;
+}
+
+/**
+ Discover all the boot information for boot file.
+
+ @param[in, out] Private The pointer to the driver's private data.
+
+ @retval EFI_SUCCESS Successfully obtained all the boot information .
+ @retval Others Failed to retrieve the boot information.
+
+**/
+EFI_STATUS
+HttpBootDiscoverBootInfo (
+ IN OUT HTTP_BOOT_PRIVATE_DATA *Private
+ )
+{
+ EFI_STATUS Status;
+
+ //
+ // Start D.O.R.A/S.A.R.R exchange to acquire station ip address and
+ // other Http boot information.
+ //
+ Status = HttpBootDhcp (Private);
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+
+ if (!Private->UsingIpv6) {
+ Status = HttpBootExtractUriInfo (Private);
+ } else {
+ ASSERT (FALSE);
+ }
+
+ return Status;
+}
+
+/**
+ Create a HttpIo instance for the file download.
+
+ @param[in] Private The pointer to the driver's private data.
+
+ @retval EFI_SUCCESS Successfully created.
+ @retval Others Failed to create HttpIo.
+
+**/
+EFI_STATUS
+HttpBootCreateHttpIo (
+ IN HTTP_BOOT_PRIVATE_DATA *Private
+ )
+{
+ HTTP_IO_CONFIG_DATA ConfigData;
+ EFI_STATUS Status;
+
+ ASSERT (Private != NULL);
+
+ ZeroMem (&ConfigData, sizeof (HTTP_IO_CONFIG_DATA));
+ if (!Private->UsingIpv6) {
+ ConfigData.Config4.HttpVersion = HttpVersion11;
+ ConfigData.Config4.RequestTimeOut = HTTP_BOOT_REQUEST_TIMEOUT;
+ IP4_COPY_ADDRESS (&ConfigData.Config4.LocalIp, &Private->StationIp.v4);
+ IP4_COPY_ADDRESS (&ConfigData.Config4.SubnetMask, &Private->SubnetMask.v4);
+ } else {
+ ASSERT (FALSE);
+ }
+
+ Status = HttpIoCreateIo (
+ Private->Image,
+ Private->Controller,
+ Private->UsingIpv6 ? IP_VERSION_6 : IP_VERSION_4,
+ &ConfigData,
+ &Private->HttpIo
+ );
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+
+ Private->HttpCreated = TRUE;
+ return EFI_SUCCESS;
+}
+
+/**
+ Get the file content from cached data.
+
+ @param[in] Private The pointer to the driver's private data.
+ @param[in] Uri Uri of the file to be retrieved from cache.
+ @param[in, out] BufferSize On input the size of Buffer in bytes. On output with a return
+ code of EFI_SUCCESS, the amount of data transferred to
+ Buffer. On output with a return code of EFI_BUFFER_TOO_SMALL,
+ the size of Buffer required to retrieve the requested file.
+ @param[out] Buffer The memory buffer to transfer the file to. IF Buffer is NULL,
+ then the size of the requested file is returned in
+ BufferSize.
+
+ @retval EFI_SUCCESS Successfully created.
+ @retval Others Failed to create HttpIo.
+
+**/
+EFI_STATUS
+HttpBootGetFileFromCache (
+ IN HTTP_BOOT_PRIVATE_DATA *Private,
+ IN CHAR16 *Uri,
+ IN OUT UINTN *BufferSize,
+ OUT UINT8 *Buffer
+ )
+{
+ LIST_ENTRY *Entry;
+ LIST_ENTRY *Entry2;
+ HTTP_BOOT_CACHE_CONTENT *Cache;
+ HTTP_BOOT_ENTITY_DATA *EntityData;
+ UINTN CopyedSize;
+
+ if (Uri == NULL || BufferSize == 0 || Buffer == NULL) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ NET_LIST_FOR_EACH (Entry, &Private->CacheList) {
+ Cache = NET_LIST_USER_STRUCT (Entry, HTTP_BOOT_CACHE_CONTENT, Link);
+ //
+ // Compare the URI to see whether we already have a cache for this file.
+ //
+ if ((Cache->RequestData != NULL) &&
+ (Cache->RequestData->Url != NULL) &&
+ (StrCmp (Uri, Cache->RequestData->Url) == 0))
+ {
+ //
+ // Hit cache, check buffer size.
+ //
+ if (*BufferSize < Cache->EntityLength) {
+ *BufferSize = Cache->EntityLength;
+ return EFI_BUFFER_TOO_SMALL;
+ }
+
+ //
+ // Fill data to buffer.
+ //
+ CopyedSize = 0;
+ NET_LIST_FOR_EACH (Entry2, &Cache->EntityDataList) {
+ EntityData = NET_LIST_USER_STRUCT (Entry2, HTTP_BOOT_ENTITY_DATA, Link);
+ if (*BufferSize > CopyedSize) {
+ CopyMem (
+ Buffer + CopyedSize,
+ EntityData->DataStart,
+ MIN (EntityData->DataLength, *BufferSize - CopyedSize)
+ );
+ CopyedSize += MIN (EntityData->DataLength, *BufferSize - CopyedSize);
+ }
+ }
+ *BufferSize = CopyedSize;
+ return EFI_SUCCESS;
+ }
+ }
+
+ return EFI_NOT_FOUND;
+}
+
+/**
+ Release all the resource of a cache item.
+
+ @param[in] Cache The pointer to the cache item.
+
+**/
+VOID
+HttpBootFreeCache (
+ IN HTTP_BOOT_CACHE_CONTENT *Cache
+ )
+{
+ UINTN Index;
+ LIST_ENTRY *Entry;
+ LIST_ENTRY *NextEntry;
+ HTTP_BOOT_ENTITY_DATA *EntityData;
+
+ if (Cache != NULL) {
+ //
+ // Free the request data
+ //
+ if (Cache->RequestData != NULL) {
+ if (Cache->RequestData->Url != NULL) {
+ FreePool (Cache->RequestData->Url);
+ }
+ FreePool (Cache->RequestData);
+ }
+
+ //
+ // Free the response header
+ //
+ if (Cache->ResponseData != NULL) {
+ if (Cache->ResponseData->Headers != NULL) {
+ for (Index = 0; Index < Cache->ResponseData->HeaderCount; Index++) {
+ FreePool (Cache->ResponseData->Headers[Index].FieldName);
+ FreePool (Cache->ResponseData->Headers[Index].FieldValue);
+ }
+ FreePool (Cache->ResponseData->Headers);
+ }
+ }
+
+ //
+ // Free the response body
+ //
+ NET_LIST_FOR_EACH_SAFE (Entry, NextEntry, &Cache->EntityDataList) {
+ EntityData = NET_LIST_USER_STRUCT (Entry, HTTP_BOOT_ENTITY_DATA, Link);
+ if (EntityData->Block != NULL) {
+ FreePool (EntityData->Block);
+ }
+ RemoveEntryList (&EntityData->Link);
+ FreePool (EntityData);
+ }
+
+ FreePool (Cache);
+ }
+}
+
+/**
+ Clean up all cached data.
+
+ @param[in] Private The pointer to the driver's private data.
+
+**/
+VOID
+HttpBootFreeCacheList (
+ IN HTTP_BOOT_PRIVATE_DATA *Private
+ )
+{
+ LIST_ENTRY *Entry;
+ LIST_ENTRY *NextEntry;
+ HTTP_BOOT_CACHE_CONTENT *Cache;
+
+ NET_LIST_FOR_EACH_SAFE (Entry, NextEntry, &Private->CacheList) {
+ Cache = NET_LIST_USER_STRUCT (Entry, HTTP_BOOT_CACHE_CONTENT, Link);
+ RemoveEntryList (&Cache->Link);
+ HttpBootFreeCache (Cache);
+ }
+}
+
+/**
+ A callback function to intercept events during message parser.
+
+ This function will be invoked during HttpParseMessageBody() with various events type. An error
+ return status of the callback function will cause the HttpParseMessageBody() aborted.
+
+ @param[in] EventType Event type of this callback call.
+ @param[in] Data A pointer to data buffer.
+ @param[in] Length Length in bytes of the Data.
+ @param[in] Context Callback context set by HttpInitMsgParser().
+
+ @retval EFI_SUCCESS Continue to parser the message body.
+ @retval Others Abort the parse.
+
+**/
+EFI_STATUS
+EFIAPI
+HttpBootGetBootFileCallback (
+ IN HTTP_BODY_PARSE_EVENT EventType,
+ IN CHAR8 *Data,
+ IN UINTN Length,
+ IN VOID *Context
+ )
+{
+ HTTP_BOOT_CALLBACK_DATA *CallbackData;
+ HTTP_BOOT_ENTITY_DATA *NewEntityData;
+
+ //
+ // We only care about the entity data.
+ //
+ if (EventType != BodyParseEventOnData) {
+ return EFI_SUCCESS;
+ }
+
+ CallbackData = (HTTP_BOOT_CALLBACK_DATA *) Context;
+
+ //
+ // Save the data into cache list.
+ //
+ NewEntityData = AllocatePool (sizeof (HTTP_BOOT_ENTITY_DATA));
+ if (NewEntityData == NULL) {
+ return EFI_OUT_OF_RESOURCES;
+ }
+ if (CallbackData->NewBlock) {
+ NewEntityData->Block = CallbackData->Block;
+ CallbackData->Block = NULL;
+ }
+ NewEntityData->DataLength = Length;
+ NewEntityData->DataStart = (UINT8*) Data;
+ InsertTailList (&CallbackData->Cache->EntityDataList, &NewEntityData->Link);
+
+ //
+ // Copy data if caller has provided a buffer.
+ //
+ if (CallbackData->BufferSize > CallbackData->CopyedSize) {
+ CopyMem (
+ CallbackData->Buffer + CallbackData->CopyedSize,
+ Data,
+ MIN (Length, CallbackData->BufferSize - CallbackData->CopyedSize)
+ );
+ CallbackData->CopyedSize += MIN (Length, CallbackData->BufferSize - CallbackData->CopyedSize);
+ }
+
+ return EFI_SUCCESS;
+}
+
+/**
+ This function download the boot file by using UEFI HTTP protocol.
+
+ @param[in] Private The pointer to the driver's private data.
+ @param[in] HeaderOnly Only request the response header, it could save a lot of time if
+ the caller only want to know the size of the requested file.
+ @param[in, out] BufferSize On input the size of Buffer in bytes. On output with a return
+ code of EFI_SUCCESS, the amount of data transferred to
+ Buffer. On output with a return code of EFI_BUFFER_TOO_SMALL,
+ the size of Buffer required to retrieve the requested file.
+ @param[out] Buffer The memory buffer to transfer the file to. IF Buffer is NULL,
+ then the size of the requested file is returned in
+ BufferSize.
+
+ @retval EFI_SUCCESS The file was loaded.
+ @retval EFI_INVALID_PARAMETER BufferSize is NULL or Buffer Size is not NULL but Buffer is NULL.
+ @retval EFI_OUT_OF_RESOURCES Could not allocate needed resources
+ @retval EFI_BUFFER_TOO_SMALL The BufferSize is too small to read the current directory entry.
+ BufferSize has been updated with the size needed to complete
+ the request.
+ @retval Others Unexpected error happened.
+
+**/
+EFI_STATUS
+HttpBootGetBootFile (
+ IN HTTP_BOOT_PRIVATE_DATA *Private,
+ IN BOOLEAN HeaderOnly,
+ IN OUT UINTN *BufferSize,
+ OUT UINT8 *Buffer
+ )
+{
+ EFI_STATUS Status;
+ CHAR8 *HostName;
+ EFI_HTTP_REQUEST_DATA *RequestData;
+ HTTP_IO_RESOPNSE_DATA *ResponseData;
+ HTTP_IO_RESOPNSE_DATA ResponseBody;
+ HTTP_IO *HttpIo;
+ HTTP_IO_HEADER *HttpIoHeader;
+ VOID *Parser;
+ HTTP_BOOT_CALLBACK_DATA Context;
+ UINTN ContentLength;
+ HTTP_BOOT_CACHE_CONTENT *Cache;
+ UINT8 *Block;
+ CHAR16 *Url;
+
+ ASSERT (Private != NULL);
+ ASSERT (Private->HttpCreated);
+
+ if (BufferSize == NULL) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ if (*BufferSize != 0 && Buffer == NULL) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ //
+ // First, check whether we already cached the requested Uri.
+ //
+ Url = AllocatePool ((AsciiStrLen (Private->BootFileUri) + 1) * sizeof (CHAR16));
+ if (Url == NULL) {
+ return EFI_OUT_OF_RESOURCES;
+ }
+ AsciiStrToUnicodeStr (Private->BootFileUri, Url);
+ if (!HeaderOnly) {
+ Status = HttpBootGetFileFromCache (Private, Url, BufferSize, Buffer);
+ if (Status != EFI_NOT_FOUND) {
+ FreePool (Url);
+ return Status;
+ }
+ }
+
+ //
+ // Not found in cache, try to download it through HTTP.
+ //
+
+ //
+ // 1. Create a temp cache item for the requested URI.
+ //
+ Cache = NULL;
+ if (!HeaderOnly) {
+ Cache = AllocateZeroPool (sizeof (HTTP_BOOT_CACHE_CONTENT));
+ if (Cache == NULL) {
+ Status = EFI_OUT_OF_RESOURCES;
+ goto ERROR_1;
+ }
+ InitializeListHead (&Cache->EntityDataList);
+ }
+
+ //
+ // 2. Send HTTP request message.
+ //
+
+ //
+ // 2.1 Build HTTP header for the request, 3 header is needed to download a boot file:
+ // Host
+ // Accept
+ // User-Agent
+ //
+ HttpIoHeader = HttpBootCreateHeader (3);
+ if (HttpIoHeader == NULL) {
+ Status = EFI_OUT_OF_RESOURCES;
+ goto ERROR_2;
+ }
+
+ //
+ // Add HTTP header field 1: Host
+ //
+ HostName = NULL;
+ Status = HttpUrlGetHostName (
+ Private->BootFileUri,
+ Private->BootFileUriParser,
+ &HostName
+ );
+ if (EFI_ERROR (Status)) {
+ goto ERROR_3;
+ }
+ Status = HttpBootSetHeader (
+ HttpIoHeader,
+ HTTP_FIELD_NAME_HOST,
+ HostName
+ );
+ FreePool (HostName);
+ if (EFI_ERROR (Status)) {
+ goto ERROR_3;
+ }
+
+ //
+ // Add HTTP header field 2: Accept
+ //
+ Status = HttpBootSetHeader (
+ HttpIoHeader,
+ HTTP_FIELD_NAME_ACCEPT,
+ "*/*"
+ );
+ if (EFI_ERROR (Status)) {
+ goto ERROR_3;
+ }
+
+ //
+ // Add HTTP header field 3: User-Agent
+ //
+ Status = HttpBootSetHeader (
+ HttpIoHeader,
+ HTTP_FIELD_NAME_USER_AGENT,
+ HTTP_USER_AGENT_EFI_HTTP_BOOT
+ );
+ if (EFI_ERROR (Status)) {
+ goto ERROR_3;
+ }
+
+ //
+ // 2.2 Build the rest of HTTP request info.
+ //
+ RequestData = AllocatePool (sizeof (EFI_HTTP_REQUEST_DATA));
+ if (RequestData == NULL) {
+ Status = EFI_OUT_OF_RESOURCES;
+ goto ERROR_3;
+ }
+ RequestData->Method = HeaderOnly ? HttpMethodHead : HttpMethodGet;
+ RequestData->Url = Url;
+ if (RequestData->Url == NULL) {
+ Status = EFI_OUT_OF_RESOURCES;
+ goto ERROR_4;
+ }
+ AsciiStrToUnicodeStr (Private->BootFileUri, RequestData->Url);
+
+ //
+ // 2.3 Record the request info in a temp cache item.
+ //
+ if (!HeaderOnly) {
+ Cache->RequestData = RequestData;
+ }
+
+ //
+ // 2.4 Send out the request to HTTP server.
+ //
+ HttpIo = &Private->HttpIo;
+ Status = HttpIoSendRequest (
+ HttpIo,
+ RequestData,
+ HttpIoHeader->HeaderCount,
+ HttpIoHeader->Headers,
+ 0,
+ NULL
+ );
+ if (EFI_ERROR (Status)) {
+ goto ERROR_4;
+ }
+
+ //
+ // 3. Receive HTTP response message.
+ //
+
+ //
+ // 3.1 First step, use zero BodyLength to only receive the response headers.
+ //
+ ResponseData = AllocateZeroPool (sizeof(HTTP_IO_RESOPNSE_DATA));
+ if (ResponseData == NULL) {
+ Status = EFI_OUT_OF_RESOURCES;
+ goto ERROR_4;
+ }
+ Status = HttpIoRecvResponse (
+ &Private->HttpIo,
+ TRUE,
+ ResponseData
+ );
+ if (EFI_ERROR (Status)) {
+ goto ERROR_5;
+ }
+
+ //
+ // 3.2 Cache the response header.
+ //
+ if (!HeaderOnly) {
+ Cache->ResponseData = ResponseData;
+ }
+
+ //
+ // 3.3 Init a message-body parser from the header information.
+ //
+ Parser = NULL;
+ Context.NewBlock = FALSE;
+ Context.Block = NULL;
+ Context.CopyedSize = 0;
+ Context.Buffer = Buffer;
+ Context.BufferSize = *BufferSize;
+ Context.Cache = Cache;
+ Status = HttpInitMsgParser (
+ HeaderOnly? HttpMethodHead : HttpMethodGet,
+ ResponseData->Response.StatusCode,
+ ResponseData->HeaderCount,
+ ResponseData->Headers,
+ HttpBootGetBootFileCallback,
+ (VOID*) &Context,
+ &Parser
+ );
+ if (EFI_ERROR (Status)) {
+ goto ERROR_6;
+ }
+
+ //
+ // 3.4 Continue to receive and parse message-body if needed.
+ //
+ if (!HeaderOnly) {
+ ZeroMem (&ResponseBody, sizeof (HTTP_IO_RESOPNSE_DATA));
+ while (!HttpIsMessageComplete (Parser)) {
+ //
+ // Allocate a new block to hold the message-body.
+ //
+ Block = AllocatePool (HTTP_BOOT_BLOCK_SIZE);
+ if (Block == NULL) {
+ Status = EFI_OUT_OF_RESOURCES;
+ goto ERROR_6;
+ }
+ ResponseBody.Body = (CHAR8*) Block;
+ ResponseBody.BodyLength = HTTP_BOOT_BLOCK_SIZE;
+ Status = HttpIoRecvResponse (
+ &Private->HttpIo,
+ FALSE,
+ &ResponseBody
+ );
+ if (EFI_ERROR (Status)) {
+ goto ERROR_6;
+ }
+
+ //
+ // Parse the new received block of the message-body, the block will be saved in cache.
+ //
+ Context.NewBlock = TRUE;
+ Context.Block = Block;
+ Status = HttpParseMessageBody (
+ Parser,
+ ResponseBody.BodyLength,
+ ResponseBody.Body
+ );
+ if (EFI_ERROR (Status)) {
+ goto ERROR_6;
+ }
+ }
+ }
+
+ //
+ // 3.5 Message-body receive & parse is completed, get the file size.
+ //
+ Status = HttpGetEntityLength (Parser, &ContentLength);
+ if (EFI_ERROR (Status)) {
+ goto ERROR_6;
+ }
+
+ if (*BufferSize < ContentLength) {
+ Status = EFI_BUFFER_TOO_SMALL;
+ }
+ *BufferSize = ContentLength;
+
+ //
+ // 4. Save the cache item to driver's cache list and return.
+ //
+ if (!HeaderOnly) {
+ Cache->EntityLength = ContentLength;
+ InsertTailList (&Private->CacheList, &Cache->Link);
+ }
+
+ if (Parser != NULL) {
+ HttpFreeMsgParser (Parser);
+ }
+
+ return EFI_SUCCESS;
+
+ERROR_6:
+ if (Parser != NULL) {
+ HttpFreeMsgParser (Parser);
+ }
+ if (Context.Block != NULL) {
+ FreePool (Context.Block);
+ }
+ HttpBootFreeCache (Cache);
+
+ERROR_5:
+ if (ResponseData != NULL) {
+ FreePool (ResponseData);
+ }
+ERROR_4:
+ if (RequestData != NULL) {
+ FreePool (RequestData);
+ }
+ERROR_3:
+ HttpBootFreeHeader (HttpIoHeader);
+ERROR_2:
+ if (Cache != NULL) {
+ FreePool (Cache);
+ }
+ERROR_1:
+ if (Url != NULL) {
+ FreePool (Url);
+ }
+
+ return Status;
+}
diff --git a/NetworkPkg/HttpBootDxe/HttpBootClient.h b/NetworkPkg/HttpBootDxe/HttpBootClient.h index 3f6671333f..2dfafab936 100644 --- a/NetworkPkg/HttpBootDxe/HttpBootClient.h +++ b/NetworkPkg/HttpBootDxe/HttpBootClient.h @@ -1,139 +1,139 @@ -/** @file - Declaration of the boot file download function. - -Copyright (c) 2015, Intel Corporation. All rights reserved.<BR> -This program and the accompanying materials are licensed and made available under -the terms and conditions of the BSD License that accompanies this distribution. -The full text of the license may be found at -http://opensource.org/licenses/bsd-license.php. - -THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, -WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. - -**/ - -#ifndef __EFI_HTTP_BOOT_HTTP_H__ -#define __EFI_HTTP_BOOT_HTTP_H__ - -#define HTTP_BOOT_REQUEST_TIMEOUT 5000 // 5 seconds in uints of millisecond. -#define HTTP_BOOT_BLOCK_SIZE 1024 - -#define HTTP_FIELD_NAME_USER_AGENT "User-Agent" -#define HTTP_FIELD_NAME_HOST "Host" -#define HTTP_FIELD_NAME_ACCEPT "Accept" - - -#define HTTP_USER_AGENT_EFI_HTTP_BOOT "UefiHttpBoot/1.0" - -// -// Record the data length and start address of a data block. -// -typedef struct { - LIST_ENTRY Link; // Link to the EntityDataList in HTTP_BOOT_CACHE_CONTENT - UINT8 *Block; // If NULL, the data is in previous data block. - UINT8 *DataStart; // Point to somewhere in the Block - UINTN DataLength; -} HTTP_BOOT_ENTITY_DATA; - -// -// Structure for a cache item -// -typedef struct { - LIST_ENTRY Link; // Link to the CacheList in driver's private data. - EFI_HTTP_REQUEST_DATA *RequestData; - HTTP_IO_RESOPNSE_DATA *ResponseData; // Not include any message-body data. - UINTN EntityLength; - LIST_ENTRY EntityDataList; // Entity data (message-body) -} HTTP_BOOT_CACHE_CONTENT; - -// -// Callback data for HTTP_BODY_PARSER_CALLBACK() -// -typedef struct { - EFI_STATUS Status; - // - // Cache info. - // - HTTP_BOOT_CACHE_CONTENT *Cache; - BOOLEAN NewBlock; - UINT8 *Block; - - // - // Caller provided buffer to load the file in. - // - UINTN CopyedSize; - UINTN BufferSize; - UINT8 *Buffer; -} HTTP_BOOT_CALLBACK_DATA; - -/** - Discover all the boot information for boot file. - - @param[in, out] Private The pointer to the driver's private data. - - @retval EFI_SUCCESS Successfully obtained all the boot information . - @retval Others Failed to retrieve the boot information. - -**/ -EFI_STATUS -HttpBootDiscoverBootInfo ( - IN OUT HTTP_BOOT_PRIVATE_DATA *Private - ); - -/** - Create a HttpIo instance for the file download. - - @param[in] Private The pointer to the driver's private data. - - @retval EFI_SUCCESS Successfully created. - @retval Others Failed to create HttpIo. - -**/ -EFI_STATUS -HttpBootCreateHttpIo ( - IN HTTP_BOOT_PRIVATE_DATA *Private - ); - -/** - This function download the boot file by using UEFI HTTP protocol. - - @param[in] Private The pointer to the driver's private data. - @param[in] HeaderOnly Only request the response header, it could save a lot of time if - the caller only want to know the size of the requested file. - @param[in, out] BufferSize On input the size of Buffer in bytes. On output with a return - code of EFI_SUCCESS, the amount of data transferred to - Buffer. On output with a return code of EFI_BUFFER_TOO_SMALL, - the size of Buffer required to retrieve the requested file. - @param[out] Buffer The memory buffer to transfer the file to. IF Buffer is NULL, - then the size of the requested file is returned in - BufferSize. - - @retval EFI_SUCCESS The file was loaded. - @retval EFI_INVALID_PARAMETER BufferSize is NULL or Buffer Size is not NULL but Buffer is NULL. - @retval EFI_OUT_OF_RESOURCES Could not allocate needed resources - @retval EFI_BUFFER_TOO_SMALL The BufferSize is too small to read the current directory entry. - BufferSize has been updated with the size needed to complete - the request. - @retval Others Unexpected error happened. - -**/ -EFI_STATUS -HttpBootGetBootFile ( - IN HTTP_BOOT_PRIVATE_DATA *Private, - IN BOOLEAN HeaderOnly, - IN OUT UINTN *BufferSize, - OUT UINT8 *Buffer - ); - -/** - Clean up all cached data. - - @param[in] Private The pointer to the driver's private data. - -**/ -VOID -HttpBootFreeCacheList ( - IN HTTP_BOOT_PRIVATE_DATA *Private - ); - -#endif +/** @file
+ Declaration of the boot file download function.
+
+Copyright (c) 2015, Intel Corporation. All rights reserved.<BR>
+This program and the accompanying materials are licensed and made available under
+the terms and conditions of the BSD License that accompanies this distribution.
+The full text of the license may be found at
+http://opensource.org/licenses/bsd-license.php.
+
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+**/
+
+#ifndef __EFI_HTTP_BOOT_HTTP_H__
+#define __EFI_HTTP_BOOT_HTTP_H__
+
+#define HTTP_BOOT_REQUEST_TIMEOUT 5000 // 5 seconds in uints of millisecond.
+#define HTTP_BOOT_BLOCK_SIZE 1024
+
+#define HTTP_FIELD_NAME_USER_AGENT "User-Agent"
+#define HTTP_FIELD_NAME_HOST "Host"
+#define HTTP_FIELD_NAME_ACCEPT "Accept"
+
+
+#define HTTP_USER_AGENT_EFI_HTTP_BOOT "UefiHttpBoot/1.0"
+
+//
+// Record the data length and start address of a data block.
+//
+typedef struct {
+ LIST_ENTRY Link; // Link to the EntityDataList in HTTP_BOOT_CACHE_CONTENT
+ UINT8 *Block; // If NULL, the data is in previous data block.
+ UINT8 *DataStart; // Point to somewhere in the Block
+ UINTN DataLength;
+} HTTP_BOOT_ENTITY_DATA;
+
+//
+// Structure for a cache item
+//
+typedef struct {
+ LIST_ENTRY Link; // Link to the CacheList in driver's private data.
+ EFI_HTTP_REQUEST_DATA *RequestData;
+ HTTP_IO_RESOPNSE_DATA *ResponseData; // Not include any message-body data.
+ UINTN EntityLength;
+ LIST_ENTRY EntityDataList; // Entity data (message-body)
+} HTTP_BOOT_CACHE_CONTENT;
+
+//
+// Callback data for HTTP_BODY_PARSER_CALLBACK()
+//
+typedef struct {
+ EFI_STATUS Status;
+ //
+ // Cache info.
+ //
+ HTTP_BOOT_CACHE_CONTENT *Cache;
+ BOOLEAN NewBlock;
+ UINT8 *Block;
+
+ //
+ // Caller provided buffer to load the file in.
+ //
+ UINTN CopyedSize;
+ UINTN BufferSize;
+ UINT8 *Buffer;
+} HTTP_BOOT_CALLBACK_DATA;
+
+/**
+ Discover all the boot information for boot file.
+
+ @param[in, out] Private The pointer to the driver's private data.
+
+ @retval EFI_SUCCESS Successfully obtained all the boot information .
+ @retval Others Failed to retrieve the boot information.
+
+**/
+EFI_STATUS
+HttpBootDiscoverBootInfo (
+ IN OUT HTTP_BOOT_PRIVATE_DATA *Private
+ );
+
+/**
+ Create a HttpIo instance for the file download.
+
+ @param[in] Private The pointer to the driver's private data.
+
+ @retval EFI_SUCCESS Successfully created.
+ @retval Others Failed to create HttpIo.
+
+**/
+EFI_STATUS
+HttpBootCreateHttpIo (
+ IN HTTP_BOOT_PRIVATE_DATA *Private
+ );
+
+/**
+ This function download the boot file by using UEFI HTTP protocol.
+
+ @param[in] Private The pointer to the driver's private data.
+ @param[in] HeaderOnly Only request the response header, it could save a lot of time if
+ the caller only want to know the size of the requested file.
+ @param[in, out] BufferSize On input the size of Buffer in bytes. On output with a return
+ code of EFI_SUCCESS, the amount of data transferred to
+ Buffer. On output with a return code of EFI_BUFFER_TOO_SMALL,
+ the size of Buffer required to retrieve the requested file.
+ @param[out] Buffer The memory buffer to transfer the file to. IF Buffer is NULL,
+ then the size of the requested file is returned in
+ BufferSize.
+
+ @retval EFI_SUCCESS The file was loaded.
+ @retval EFI_INVALID_PARAMETER BufferSize is NULL or Buffer Size is not NULL but Buffer is NULL.
+ @retval EFI_OUT_OF_RESOURCES Could not allocate needed resources
+ @retval EFI_BUFFER_TOO_SMALL The BufferSize is too small to read the current directory entry.
+ BufferSize has been updated with the size needed to complete
+ the request.
+ @retval Others Unexpected error happened.
+
+**/
+EFI_STATUS
+HttpBootGetBootFile (
+ IN HTTP_BOOT_PRIVATE_DATA *Private,
+ IN BOOLEAN HeaderOnly,
+ IN OUT UINTN *BufferSize,
+ OUT UINT8 *Buffer
+ );
+
+/**
+ Clean up all cached data.
+
+ @param[in] Private The pointer to the driver's private data.
+
+**/
+VOID
+HttpBootFreeCacheList (
+ IN HTTP_BOOT_PRIVATE_DATA *Private
+ );
+
+#endif
diff --git a/NetworkPkg/HttpBootDxe/HttpBootComponentName.c b/NetworkPkg/HttpBootDxe/HttpBootComponentName.c index 4e4a52a8fa..0708598c4f 100644 --- a/NetworkPkg/HttpBootDxe/HttpBootComponentName.c +++ b/NetworkPkg/HttpBootDxe/HttpBootComponentName.c @@ -1,180 +1,180 @@ -/** @file - Implementation of EFI_COMPONENT_NAME_PROTOCOL and EFI_COMPONENT_NAME2_PROTOCOL protocol. - -Copyright (c) 2015, Intel Corporation. All rights reserved.<BR> -This program and the accompanying materials are licensed and made available under -the terms and conditions of the BSD License that accompanies this distribution. -The full text of the license may be found at -http://opensource.org/licenses/bsd-license.php. - -THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, -WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. - -**/ - -#include "HttpBootDxe.h" - -/// -/// Component Name Protocol instance -/// -GLOBAL_REMOVE_IF_UNREFERENCED -EFI_COMPONENT_NAME_PROTOCOL gHttpBootDxeComponentName = { - (EFI_COMPONENT_NAME_GET_DRIVER_NAME) HttpBootDxeComponentNameGetDriverName, - (EFI_COMPONENT_NAME_GET_CONTROLLER_NAME)HttpBootDxeComponentNameGetControllerName, - "eng" -}; - -/// -/// Component Name 2 Protocol instance -/// -GLOBAL_REMOVE_IF_UNREFERENCED -EFI_COMPONENT_NAME2_PROTOCOL gHttpBootDxeComponentName2 = { - HttpBootDxeComponentNameGetDriverName, - HttpBootDxeComponentNameGetControllerName, - "en" -}; - -/// -/// Table of driver names -/// -GLOBAL_REMOVE_IF_UNREFERENCED -EFI_UNICODE_STRING_TABLE mHttpBootDxeDriverNameTable[] = { - { "eng;en", (CHAR16 *)L"UEFI HTTP Boot Driver" }, - { NULL, NULL } -}; - -/// -/// Table of controller names -/// -GLOBAL_REMOVE_IF_UNREFERENCED -EFI_UNICODE_STRING_TABLE mHttpBootDxeControllerNameTable[] = { - { "eng;en", (CHAR16 *)L"UEFI Http Boot Controller" }, - { NULL, NULL } -}; - -/** - Retrieves a Unicode string that is the user-readable name of the EFI Driver. - - @param This A pointer to the EFI_COMPONENT_NAME_PROTOCOL instance. - @param Language A pointer to a three-character ISO 639-2 language identifier. - This is the language of the driver name that that the caller - is requesting, and it must match one of the languages specified - in SupportedLanguages. The number of languages supported by a - driver is up to the driver writer. - @param DriverName A pointer to the Unicode string to return. This Unicode string - is the name of the driver specified by This in the language - specified by Language. - - @retval EFI_SUCCESS The Unicode string for the Driver specified by This - and the language specified by Language was returned - in DriverName. - @retval EFI_INVALID_PARAMETER Language is NULL. - @retval EFI_INVALID_PARAMETER DriverName is NULL. - @retval EFI_UNSUPPORTED The driver specified by This does not support the - language specified by Language. - -**/ -EFI_STATUS -EFIAPI -HttpBootDxeComponentNameGetDriverName ( - IN EFI_COMPONENT_NAME2_PROTOCOL *This, - IN CHAR8 *Language, - OUT CHAR16 **DriverName - ) -{ - return LookupUnicodeString2 ( - Language, - This->SupportedLanguages, - mHttpBootDxeDriverNameTable, - DriverName, - (BOOLEAN) (This != &gHttpBootDxeComponentName2) - ); -} - -/** - Retrieves a Unicode string that is the user readable name of the controller - that is being managed by an EFI Driver. - - @param This A pointer to the EFI_COMPONENT_NAME_PROTOCOL instance. - @param ControllerHandle The handle of a controller that the driver specified by - This is managing. This handle specifies the controller - whose name is to be returned. - @param ChildHandle The handle of the child controller to retrieve the name - of. This is an optional parameter that may be NULL. It - will be NULL for device drivers. It will also be NULL - for a bus drivers that wish to retrieve the name of the - bus controller. It will not be NULL for a bus driver - that wishes to retrieve the name of a child controller. - @param Language A pointer to a three character ISO 639-2 language - identifier. This is the language of the controller name - that the caller is requesting, and it must match one - of the languages specified in SupportedLanguages. The - number of languages supported by a driver is up to the - driver writer. - @param ControllerName A pointer to the Unicode string to return. This Unicode - string is the name of the controller specified by - ControllerHandle and ChildHandle in the language specified - by Language, from the point of view of the driver specified - by This. - - @retval EFI_SUCCESS The Unicode string for the user-readable name in the - language specified by Language for the driver - specified by This was returned in DriverName. - @retval EFI_INVALID_PARAMETER ControllerHandle is NULL. - @retval EFI_INVALID_PARAMETER ChildHandle is not NULL and it is not a valid EFI_HANDLE. - @retval EFI_INVALID_PARAMETER Language is NULL. - @retval EFI_INVALID_PARAMETER ControllerName is NULL. - @retval EFI_UNSUPPORTED The driver specified by This is not currently managing - the controller specified by ControllerHandle and - ChildHandle. - @retval EFI_UNSUPPORTED The driver specified by This does not support the - language specified by Language. - -**/ -EFI_STATUS -EFIAPI -HttpBootDxeComponentNameGetControllerName ( - IN EFI_COMPONENT_NAME2_PROTOCOL *This, - IN EFI_HANDLE ControllerHandle, - IN EFI_HANDLE ChildHandle OPTIONAL, - IN CHAR8 *Language, - OUT CHAR16 **ControllerName - ) -{ - EFI_STATUS Status; - EFI_HANDLE NicHandle; - UINT32 *Id; - - if (ControllerHandle == NULL || ChildHandle != NULL) { - return EFI_UNSUPPORTED; - } - - NicHandle = HttpBootGetNicByIp4Children (ControllerHandle); - if (NicHandle == NULL) { - return EFI_UNSUPPORTED; - } - - // - // Try to retrieve the private data by caller ID GUID. - // - Status = gBS->OpenProtocol ( - NicHandle, - &gEfiCallerIdGuid, - (VOID **) &Id, - NULL, - NULL, - EFI_OPEN_PROTOCOL_GET_PROTOCOL - ); - if (EFI_ERROR (Status)) { - return Status; - } - - return LookupUnicodeString2 ( - Language, - This->SupportedLanguages, - mHttpBootDxeControllerNameTable, - ControllerName, - (BOOLEAN)(This != &gHttpBootDxeComponentName2) - ); - -} +/** @file
+ Implementation of EFI_COMPONENT_NAME_PROTOCOL and EFI_COMPONENT_NAME2_PROTOCOL protocol.
+
+Copyright (c) 2015, Intel Corporation. All rights reserved.<BR>
+This program and the accompanying materials are licensed and made available under
+the terms and conditions of the BSD License that accompanies this distribution.
+The full text of the license may be found at
+http://opensource.org/licenses/bsd-license.php.
+
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+**/
+
+#include "HttpBootDxe.h"
+
+///
+/// Component Name Protocol instance
+///
+GLOBAL_REMOVE_IF_UNREFERENCED
+EFI_COMPONENT_NAME_PROTOCOL gHttpBootDxeComponentName = {
+ (EFI_COMPONENT_NAME_GET_DRIVER_NAME) HttpBootDxeComponentNameGetDriverName,
+ (EFI_COMPONENT_NAME_GET_CONTROLLER_NAME)HttpBootDxeComponentNameGetControllerName,
+ "eng"
+};
+
+///
+/// Component Name 2 Protocol instance
+///
+GLOBAL_REMOVE_IF_UNREFERENCED
+EFI_COMPONENT_NAME2_PROTOCOL gHttpBootDxeComponentName2 = {
+ HttpBootDxeComponentNameGetDriverName,
+ HttpBootDxeComponentNameGetControllerName,
+ "en"
+};
+
+///
+/// Table of driver names
+///
+GLOBAL_REMOVE_IF_UNREFERENCED
+EFI_UNICODE_STRING_TABLE mHttpBootDxeDriverNameTable[] = {
+ { "eng;en", (CHAR16 *)L"UEFI HTTP Boot Driver" },
+ { NULL, NULL }
+};
+
+///
+/// Table of controller names
+///
+GLOBAL_REMOVE_IF_UNREFERENCED
+EFI_UNICODE_STRING_TABLE mHttpBootDxeControllerNameTable[] = {
+ { "eng;en", (CHAR16 *)L"UEFI Http Boot Controller" },
+ { NULL, NULL }
+};
+
+/**
+ Retrieves a Unicode string that is the user-readable name of the EFI Driver.
+
+ @param This A pointer to the EFI_COMPONENT_NAME_PROTOCOL instance.
+ @param Language A pointer to a three-character ISO 639-2 language identifier.
+ This is the language of the driver name that that the caller
+ is requesting, and it must match one of the languages specified
+ in SupportedLanguages. The number of languages supported by a
+ driver is up to the driver writer.
+ @param DriverName A pointer to the Unicode string to return. This Unicode string
+ is the name of the driver specified by This in the language
+ specified by Language.
+
+ @retval EFI_SUCCESS The Unicode string for the Driver specified by This
+ and the language specified by Language was returned
+ in DriverName.
+ @retval EFI_INVALID_PARAMETER Language is NULL.
+ @retval EFI_INVALID_PARAMETER DriverName is NULL.
+ @retval EFI_UNSUPPORTED The driver specified by This does not support the
+ language specified by Language.
+
+**/
+EFI_STATUS
+EFIAPI
+HttpBootDxeComponentNameGetDriverName (
+ IN EFI_COMPONENT_NAME2_PROTOCOL *This,
+ IN CHAR8 *Language,
+ OUT CHAR16 **DriverName
+ )
+{
+ return LookupUnicodeString2 (
+ Language,
+ This->SupportedLanguages,
+ mHttpBootDxeDriverNameTable,
+ DriverName,
+ (BOOLEAN) (This != &gHttpBootDxeComponentName2)
+ );
+}
+
+/**
+ Retrieves a Unicode string that is the user readable name of the controller
+ that is being managed by an EFI Driver.
+
+ @param This A pointer to the EFI_COMPONENT_NAME_PROTOCOL instance.
+ @param ControllerHandle The handle of a controller that the driver specified by
+ This is managing. This handle specifies the controller
+ whose name is to be returned.
+ @param ChildHandle The handle of the child controller to retrieve the name
+ of. This is an optional parameter that may be NULL. It
+ will be NULL for device drivers. It will also be NULL
+ for a bus drivers that wish to retrieve the name of the
+ bus controller. It will not be NULL for a bus driver
+ that wishes to retrieve the name of a child controller.
+ @param Language A pointer to a three character ISO 639-2 language
+ identifier. This is the language of the controller name
+ that the caller is requesting, and it must match one
+ of the languages specified in SupportedLanguages. The
+ number of languages supported by a driver is up to the
+ driver writer.
+ @param ControllerName A pointer to the Unicode string to return. This Unicode
+ string is the name of the controller specified by
+ ControllerHandle and ChildHandle in the language specified
+ by Language, from the point of view of the driver specified
+ by This.
+
+ @retval EFI_SUCCESS The Unicode string for the user-readable name in the
+ language specified by Language for the driver
+ specified by This was returned in DriverName.
+ @retval EFI_INVALID_PARAMETER ControllerHandle is NULL.
+ @retval EFI_INVALID_PARAMETER ChildHandle is not NULL and it is not a valid EFI_HANDLE.
+ @retval EFI_INVALID_PARAMETER Language is NULL.
+ @retval EFI_INVALID_PARAMETER ControllerName is NULL.
+ @retval EFI_UNSUPPORTED The driver specified by This is not currently managing
+ the controller specified by ControllerHandle and
+ ChildHandle.
+ @retval EFI_UNSUPPORTED The driver specified by This does not support the
+ language specified by Language.
+
+**/
+EFI_STATUS
+EFIAPI
+HttpBootDxeComponentNameGetControllerName (
+ IN EFI_COMPONENT_NAME2_PROTOCOL *This,
+ IN EFI_HANDLE ControllerHandle,
+ IN EFI_HANDLE ChildHandle OPTIONAL,
+ IN CHAR8 *Language,
+ OUT CHAR16 **ControllerName
+ )
+{
+ EFI_STATUS Status;
+ EFI_HANDLE NicHandle;
+ UINT32 *Id;
+
+ if (ControllerHandle == NULL || ChildHandle != NULL) {
+ return EFI_UNSUPPORTED;
+ }
+
+ NicHandle = HttpBootGetNicByIp4Children (ControllerHandle);
+ if (NicHandle == NULL) {
+ return EFI_UNSUPPORTED;
+ }
+
+ //
+ // Try to retrieve the private data by caller ID GUID.
+ //
+ Status = gBS->OpenProtocol (
+ NicHandle,
+ &gEfiCallerIdGuid,
+ (VOID **) &Id,
+ NULL,
+ NULL,
+ EFI_OPEN_PROTOCOL_GET_PROTOCOL
+ );
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+
+ return LookupUnicodeString2 (
+ Language,
+ This->SupportedLanguages,
+ mHttpBootDxeControllerNameTable,
+ ControllerName,
+ (BOOLEAN)(This != &gHttpBootDxeComponentName2)
+ );
+
+}
diff --git a/NetworkPkg/HttpBootDxe/HttpBootComponentName.h b/NetworkPkg/HttpBootDxe/HttpBootComponentName.h index 706fa8da5b..3fce9b75ab 100644 --- a/NetworkPkg/HttpBootDxe/HttpBootComponentName.h +++ b/NetworkPkg/HttpBootDxe/HttpBootComponentName.h @@ -1,99 +1,99 @@ -/** @file - Declaration of HTTP boot driver's EFI_COMPONENT_NAME_PROTOCOL and - EFI_COMPONENT_NAME2_PROTOCOL function. - -Copyright (c) 2015, Intel Corporation. All rights reserved.<BR> -This program and the accompanying materials are licensed and made available under -the terms and conditions of the BSD License that accompanies this distribution. -The full text of the license may be found at -http://opensource.org/licenses/bsd-license.php. - -THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, -WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. - -**/ - -#ifndef __EFI_UEFI_HTTP_BOOT_COM_NAME_H__ -#define __EFI_UEFI_HTTP_BOOT_COM_NAME_H__ - -/** - Retrieves a Unicode string that is the user-readable name of the EFI Driver. - - @param This A pointer to the EFI_COMPONENT_NAME_PROTOCOL instance. - @param Language A pointer to a three-character ISO 639-2 language identifier. - This is the language of the driver name that that the caller - is requesting, and it must match one of the languages specified - in SupportedLanguages. The number of languages supported by a - driver is up to the driver writer. - @param DriverName A pointer to the Unicode string to return. This Unicode string - is the name of the driver specified by This in the language - specified by Language. - - @retval EFI_SUCCESS The Unicode string for the Driver specified by This - and the language specified by Language was returned - in DriverName. - @retval EFI_INVALID_PARAMETER Language is NULL. - @retval EFI_INVALID_PARAMETER DriverName is NULL. - @retval EFI_UNSUPPORTED The driver specified by This does not support the - language specified by Language. - -**/ -EFI_STATUS -EFIAPI -HttpBootDxeComponentNameGetDriverName ( - IN EFI_COMPONENT_NAME2_PROTOCOL *This, - IN CHAR8 *Language, - OUT CHAR16 **DriverName - ); - -/** - Retrieves a Unicode string that is the user readable name of the controller - that is being managed by an EFI Driver. - - @param This A pointer to the EFI_COMPONENT_NAME_PROTOCOL instance. - @param ControllerHandle The handle of a controller that the driver specified by - This is managing. This handle specifies the controller - whose name is to be returned. - @param ChildHandle The handle of the child controller to retrieve the name - of. This is an optional parameter that may be NULL. It - will be NULL for device drivers. It will also be NULL - for a bus drivers that wish to retrieve the name of the - bus controller. It will not be NULL for a bus driver - that wishes to retrieve the name of a child controller. - @param Language A pointer to a three character ISO 639-2 language - identifier. This is the language of the controller name - that the caller is requesting, and it must match one - of the languages specified in SupportedLanguages. The - number of languages supported by a driver is up to the - driver writer. - @param ControllerName A pointer to the Unicode string to return. This Unicode - string is the name of the controller specified by - ControllerHandle and ChildHandle in the language specified - by Language, from the point of view of the driver specified - by This. - - @retval EFI_SUCCESS The Unicode string for the user-readable name in the - language specified by Language for the driver - specified by This was returned in DriverName. - @retval EFI_INVALID_PARAMETER ControllerHandle is NULL. - @retval EFI_INVALID_PARAMETER ChildHandle is not NULL and it is not a valid EFI_HANDLE. - @retval EFI_INVALID_PARAMETER Language is NULL. - @retval EFI_INVALID_PARAMETER ControllerName is NULL. - @retval EFI_UNSUPPORTED The driver specified by This is not currently managing - the controller specified by ControllerHandle and - ChildHandle. - @retval EFI_UNSUPPORTED The driver specified by This does not support the - language specified by Language. - -**/ -EFI_STATUS -EFIAPI -HttpBootDxeComponentNameGetControllerName ( - IN EFI_COMPONENT_NAME2_PROTOCOL *This, - IN EFI_HANDLE ControllerHandle, - IN EFI_HANDLE ChildHandle OPTIONAL, - IN CHAR8 *Language, - OUT CHAR16 **ControllerName - ); - -#endif +/** @file
+ Declaration of HTTP boot driver's EFI_COMPONENT_NAME_PROTOCOL and
+ EFI_COMPONENT_NAME2_PROTOCOL function.
+
+Copyright (c) 2015, Intel Corporation. All rights reserved.<BR>
+This program and the accompanying materials are licensed and made available under
+the terms and conditions of the BSD License that accompanies this distribution.
+The full text of the license may be found at
+http://opensource.org/licenses/bsd-license.php.
+
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+**/
+
+#ifndef __EFI_UEFI_HTTP_BOOT_COM_NAME_H__
+#define __EFI_UEFI_HTTP_BOOT_COM_NAME_H__
+
+/**
+ Retrieves a Unicode string that is the user-readable name of the EFI Driver.
+
+ @param This A pointer to the EFI_COMPONENT_NAME_PROTOCOL instance.
+ @param Language A pointer to a three-character ISO 639-2 language identifier.
+ This is the language of the driver name that that the caller
+ is requesting, and it must match one of the languages specified
+ in SupportedLanguages. The number of languages supported by a
+ driver is up to the driver writer.
+ @param DriverName A pointer to the Unicode string to return. This Unicode string
+ is the name of the driver specified by This in the language
+ specified by Language.
+
+ @retval EFI_SUCCESS The Unicode string for the Driver specified by This
+ and the language specified by Language was returned
+ in DriverName.
+ @retval EFI_INVALID_PARAMETER Language is NULL.
+ @retval EFI_INVALID_PARAMETER DriverName is NULL.
+ @retval EFI_UNSUPPORTED The driver specified by This does not support the
+ language specified by Language.
+
+**/
+EFI_STATUS
+EFIAPI
+HttpBootDxeComponentNameGetDriverName (
+ IN EFI_COMPONENT_NAME2_PROTOCOL *This,
+ IN CHAR8 *Language,
+ OUT CHAR16 **DriverName
+ );
+
+/**
+ Retrieves a Unicode string that is the user readable name of the controller
+ that is being managed by an EFI Driver.
+
+ @param This A pointer to the EFI_COMPONENT_NAME_PROTOCOL instance.
+ @param ControllerHandle The handle of a controller that the driver specified by
+ This is managing. This handle specifies the controller
+ whose name is to be returned.
+ @param ChildHandle The handle of the child controller to retrieve the name
+ of. This is an optional parameter that may be NULL. It
+ will be NULL for device drivers. It will also be NULL
+ for a bus drivers that wish to retrieve the name of the
+ bus controller. It will not be NULL for a bus driver
+ that wishes to retrieve the name of a child controller.
+ @param Language A pointer to a three character ISO 639-2 language
+ identifier. This is the language of the controller name
+ that the caller is requesting, and it must match one
+ of the languages specified in SupportedLanguages. The
+ number of languages supported by a driver is up to the
+ driver writer.
+ @param ControllerName A pointer to the Unicode string to return. This Unicode
+ string is the name of the controller specified by
+ ControllerHandle and ChildHandle in the language specified
+ by Language, from the point of view of the driver specified
+ by This.
+
+ @retval EFI_SUCCESS The Unicode string for the user-readable name in the
+ language specified by Language for the driver
+ specified by This was returned in DriverName.
+ @retval EFI_INVALID_PARAMETER ControllerHandle is NULL.
+ @retval EFI_INVALID_PARAMETER ChildHandle is not NULL and it is not a valid EFI_HANDLE.
+ @retval EFI_INVALID_PARAMETER Language is NULL.
+ @retval EFI_INVALID_PARAMETER ControllerName is NULL.
+ @retval EFI_UNSUPPORTED The driver specified by This is not currently managing
+ the controller specified by ControllerHandle and
+ ChildHandle.
+ @retval EFI_UNSUPPORTED The driver specified by This does not support the
+ language specified by Language.
+
+**/
+EFI_STATUS
+EFIAPI
+HttpBootDxeComponentNameGetControllerName (
+ IN EFI_COMPONENT_NAME2_PROTOCOL *This,
+ IN EFI_HANDLE ControllerHandle,
+ IN EFI_HANDLE ChildHandle OPTIONAL,
+ IN CHAR8 *Language,
+ OUT CHAR16 **ControllerName
+ );
+
+#endif
diff --git a/NetworkPkg/HttpBootDxe/HttpBootDhcp4.c b/NetworkPkg/HttpBootDxe/HttpBootDhcp4.c index 7486d24ead..217c608233 100644 --- a/NetworkPkg/HttpBootDxe/HttpBootDhcp4.c +++ b/NetworkPkg/HttpBootDxe/HttpBootDhcp4.c @@ -1,829 +1,829 @@ -/** @file - Functions implementation related with DHCPv4 for HTTP boot driver. - -Copyright (c) 2015, Intel Corporation. All rights reserved.<BR> -This program and the accompanying materials are licensed and made available under -the terms and conditions of the BSD License that accompanies this distribution. -The full text of the license may be found at -http://opensource.org/licenses/bsd-license.php. - -THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, -WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. - -**/ - -#include "HttpBootDxe.h" - -// -// This is a map from the interested DHCP4 option tags' index to the tag value. -// -UINT8 mInterestedDhcp4Tags[HTTP_BOOT_DHCP4_TAG_INDEX_MAX] = { - HTTP_BOOT_DHCP4_TAG_BOOTFILE_LEN, - HTTP_BOOT_DHCP4_TAG_OVERLOAD, - HTTP_BOOT_DHCP4_TAG_MSG_TYPE, - HTTP_BOOT_DHCP4_TAG_SERVER_ID, - HTTP_BOOT_DHCP4_TAG_CLASS_ID, - HTTP_BOOT_DHCP4_TAG_BOOTFILE, - HTTP_BOOT_DHCP4_TAG_DNS_SERVER -}; - -// -// There are 4 times retries with the value of 4, 8, 16 and 32, refers to UEFI 2.5 spec. -// -UINT32 mHttpDhcpTimeout[4] = {4, 8, 16, 32}; - -/** - Build the options buffer for the DHCPv4 request packet. - - @param[in] Private Pointer to HTTP boot driver private data. - @param[out] OptList Pointer to the option pointer array. - @param[in] Buffer Pointer to the buffer to contain the option list. - - @return Index The count of the built-in options. - -**/ -UINT32 -HttpBootBuildDhcp4Options ( - IN HTTP_BOOT_PRIVATE_DATA *Private, - OUT EFI_DHCP4_PACKET_OPTION **OptList, - IN UINT8 *Buffer - ) -{ - HTTP_BOOT_DHCP4_OPTION_ENTRY OptEnt; - UINT16 Value; - UINT32 Index; - - Index = 0; - OptList[0] = (EFI_DHCP4_PACKET_OPTION *) Buffer; - - // - // Append parameter request list option. - // - OptList[Index]->OpCode = HTTP_BOOT_DHCP4_TAG_PARA_LIST; - OptList[Index]->Length = 27; - OptEnt.Para = (HTTP_BOOT_DHCP4_OPTION_PARA *) OptList[Index]->Data; - OptEnt.Para->ParaList[0] = HTTP_BOOT_DHCP4_TAG_NETMASK; - OptEnt.Para->ParaList[1] = HTTP_BOOT_DHCP4_TAG_TIME_OFFSET; - OptEnt.Para->ParaList[2] = HTTP_BOOT_DHCP4_TAG_ROUTER; - OptEnt.Para->ParaList[3] = HTTP_BOOT_DHCP4_TAG_TIME_SERVER; - OptEnt.Para->ParaList[4] = HTTP_BOOT_DHCP4_TAG_NAME_SERVER; - OptEnt.Para->ParaList[5] = HTTP_BOOT_DHCP4_TAG_DNS_SERVER; - OptEnt.Para->ParaList[6] = HTTP_BOOT_DHCP4_TAG_HOSTNAME; - OptEnt.Para->ParaList[7] = HTTP_BOOT_DHCP4_TAG_BOOTFILE_LEN; - OptEnt.Para->ParaList[8] = HTTP_BOOT_DHCP4_TAG_DOMAINNAME; - OptEnt.Para->ParaList[9] = HTTP_BOOT_DHCP4_TAG_ROOTPATH; - OptEnt.Para->ParaList[10] = HTTP_BOOT_DHCP4_TAG_EXTEND_PATH; - OptEnt.Para->ParaList[11] = HTTP_BOOT_DHCP4_TAG_EMTU; - OptEnt.Para->ParaList[12] = HTTP_BOOT_DHCP4_TAG_TTL; - OptEnt.Para->ParaList[13] = HTTP_BOOT_DHCP4_TAG_BROADCAST; - OptEnt.Para->ParaList[14] = HTTP_BOOT_DHCP4_TAG_NIS_DOMAIN; - OptEnt.Para->ParaList[15] = HTTP_BOOT_DHCP4_TAG_NIS_SERVER; - OptEnt.Para->ParaList[16] = HTTP_BOOT_DHCP4_TAG_NTP_SERVER; - OptEnt.Para->ParaList[17] = HTTP_BOOT_DHCP4_TAG_VENDOR; - OptEnt.Para->ParaList[18] = HTTP_BOOT_DHCP4_TAG_REQUEST_IP; - OptEnt.Para->ParaList[19] = HTTP_BOOT_DHCP4_TAG_LEASE; - OptEnt.Para->ParaList[20] = HTTP_BOOT_DHCP4_TAG_SERVER_ID; - OptEnt.Para->ParaList[21] = HTTP_BOOT_DHCP4_TAG_T1; - OptEnt.Para->ParaList[22] = HTTP_BOOT_DHCP4_TAG_T2; - OptEnt.Para->ParaList[23] = HTTP_BOOT_DHCP4_TAG_CLASS_ID; - OptEnt.Para->ParaList[25] = HTTP_BOOT_DHCP4_TAG_BOOTFILE; - OptEnt.Para->ParaList[26] = HTTP_BOOT_DHCP4_TAG_UUID; - Index++; - OptList[Index] = GET_NEXT_DHCP_OPTION (OptList[Index - 1]); - - // - // Append UUID/Guid-based client identifier option - // - OptList[Index]->OpCode = HTTP_BOOT_DHCP4_TAG_UUID; - OptList[Index]->Length = (UINT8) sizeof (HTTP_BOOT_DHCP4_OPTION_UUID); - OptEnt.Uuid = (HTTP_BOOT_DHCP4_OPTION_UUID *) OptList[Index]->Data; - OptEnt.Uuid->Type = 0; - if (EFI_ERROR (NetLibGetSystemGuid ((EFI_GUID *) OptEnt.Uuid->Guid))) { - // - // Zero the Guid to indicate NOT programable if failed to get system Guid. - // - ZeroMem (OptEnt.Uuid->Guid, sizeof (EFI_GUID)); - } - Index++; - OptList[Index] = GET_NEXT_DHCP_OPTION (OptList[Index - 1]); - - // - // Append client network device interface option - // - OptList[Index]->OpCode = HTTP_BOOT_DHCP4_TAG_UNDI; - OptList[Index]->Length = (UINT8) sizeof (HTTP_BOOT_DHCP4_OPTION_UNDI); - OptEnt.Undi = (HTTP_BOOT_DHCP4_OPTION_UNDI *) OptList[Index]->Data; - - if (Private->Nii != NULL) { - OptEnt.Undi->Type = Private->Nii->Type; - OptEnt.Undi->MajorVer = Private->Nii->MajorVer; - OptEnt.Undi->MinorVer = Private->Nii->MinorVer; - } else { - OptEnt.Undi->Type = DEFAULT_UNDI_TYPE; - OptEnt.Undi->MajorVer = DEFAULT_UNDI_MAJOR; - OptEnt.Undi->MinorVer = DEFAULT_UNDI_MINOR; - } - - Index++; - OptList[Index] = GET_NEXT_DHCP_OPTION (OptList[Index - 1]); - - // - // Append client system architecture option - // - OptList[Index]->OpCode = HTTP_BOOT_DHCP4_TAG_ARCH; - OptList[Index]->Length = (UINT8) sizeof (HTTP_BOOT_DHCP4_OPTION_ARCH); - OptEnt.Arch = (HTTP_BOOT_DHCP4_OPTION_ARCH *) OptList[Index]->Data; - Value = HTONS (EFI_HTTP_BOOT_CLIENT_SYSTEM_ARCHITECTURE); - CopyMem (&OptEnt.Arch->Type, &Value, sizeof (UINT16)); - Index++; - OptList[Index] = GET_NEXT_DHCP_OPTION (OptList[Index - 1]); - - // - // Append vendor class identify option - // - OptList[Index]->OpCode = HTTP_BOOT_DHCP4_TAG_CLASS_ID; - OptList[Index]->Length = (UINT8) sizeof (HTTP_BOOT_DHCP4_OPTION_CLID); - OptEnt.Clid = (HTTP_BOOT_DHCP4_OPTION_CLID *) OptList[Index]->Data; - CopyMem ( - OptEnt.Clid, - DEFAULT_CLASS_ID_DATA, - sizeof (HTTP_BOOT_DHCP4_OPTION_CLID) - ); - HttpBootUintnToAscDecWithFormat ( - EFI_HTTP_BOOT_CLIENT_SYSTEM_ARCHITECTURE, - OptEnt.Clid->ArchitectureType, - sizeof (OptEnt.Clid->ArchitectureType) - ); - - if (Private->Nii != NULL) { - CopyMem (OptEnt.Clid->InterfaceName, Private->Nii->StringId, sizeof (OptEnt.Clid->InterfaceName)); - HttpBootUintnToAscDecWithFormat (Private->Nii->MajorVer, OptEnt.Clid->UndiMajor, sizeof (OptEnt.Clid->UndiMajor)); - HttpBootUintnToAscDecWithFormat (Private->Nii->MinorVer, OptEnt.Clid->UndiMinor, sizeof (OptEnt.Clid->UndiMinor)); - } - - Index++; - - return Index; -} - -/** - Parse a certain dhcp4 option by OptTag in Buffer, and return with start pointer. - - @param[in] Buffer Pointer to the option buffer. - @param[in] Length Length of the option buffer. - @param[in] OptTag Tag of the required option. - - @retval NULL Failed to find the required option. - @retval Others The position of the required option. - -**/ -EFI_DHCP4_PACKET_OPTION * -HttpBootParseDhcp4Options ( - IN UINT8 *Buffer, - IN UINT32 Length, - IN UINT8 OptTag - ) -{ - EFI_DHCP4_PACKET_OPTION *Option; - UINT32 Offset; - - Option = (EFI_DHCP4_PACKET_OPTION *) Buffer; - Offset = 0; - - while (Offset < Length && Option->OpCode != HTTP_BOOT_DHCP4_TAG_EOP) { - - if (Option->OpCode == OptTag) { - // - // Found the required option. - // - return Option; - } - - // - // Skip the current option to the next. - // - if (Option->OpCode == HTTP_BOOT_DHCP4_TAG_PAD) { - Offset++; - } else { - Offset += Option->Length + 2; - } - - Option = (EFI_DHCP4_PACKET_OPTION *) (Buffer + Offset); - } - - return NULL; -} - -/** - Cache the DHCPv4 packet. - - @param[in] Dst Pointer to the cache buffer for DHCPv4 packet. - @param[in] Src Pointer to the DHCPv4 packet to be cached. - -**/ -VOID -HttpBootCacheDhcp4Packet ( - IN EFI_DHCP4_PACKET *Dst, - IN EFI_DHCP4_PACKET *Src - ) -{ - ASSERT (Dst->Size >= Src->Length); - - CopyMem (&Dst->Dhcp4, &Src->Dhcp4, Src->Length); - Dst->Length = Src->Length; -} - -/** - Parse the cached DHCPv4 packet, including all the options. - - @param[in] Cache4 Pointer to cached DHCPv4 packet. - - @retval EFI_SUCCESS Parsed the DHCPv4 packet successfully. - @retval EFI_DEVICE_ERROR Failed to parse an invalid packet. - -**/ -EFI_STATUS -HttpBootParseDhcp4Packet ( - IN HTTP_BOOT_DHCP4_PACKET_CACHE *Cache4 - ) -{ - EFI_DHCP4_PACKET *Offer; - EFI_DHCP4_PACKET_OPTION **Options; - UINTN Index; - EFI_DHCP4_PACKET_OPTION *Option; - BOOLEAN IsProxyOffer; - BOOLEAN IsHttpOffer; - BOOLEAN IsDnsOffer; - BOOLEAN IpExpressedUri; - UINT8 *Ptr8; - EFI_STATUS Status; - HTTP_BOOT_OFFER_TYPE OfferType; - EFI_IPv4_ADDRESS IpAddr; - - IsDnsOffer = FALSE; - IpExpressedUri = FALSE; - IsProxyOffer = FALSE; - IsHttpOffer = FALSE; - - ZeroMem (Cache4->OptList, sizeof (Cache4->OptList)); - - Offer = &Cache4->Packet.Offer; - Options = Cache4->OptList; - - // - // Parse DHCPv4 options in this offer, and store the pointers. - // First, try to parse DHCPv4 options from the DHCP optional parameters field. - // - for (Index = 0; Index < HTTP_BOOT_DHCP4_TAG_INDEX_MAX; Index++) { - Options[Index] = HttpBootParseDhcp4Options ( - Offer->Dhcp4.Option, - GET_OPTION_BUFFER_LEN (Offer), - mInterestedDhcp4Tags[Index] - ); - } - // - // Second, Check if bootfilename and serverhostname is overloaded to carry DHCP options refers to rfc-2132. - // If yes, try to parse options from the BootFileName field, then ServerName field. - // - Option = Options[HTTP_BOOT_DHCP4_TAG_INDEX_OVERLOAD]; - if (Option != NULL) { - if ((Option->Data[0] & HTTP_BOOT_DHCP4_OVERLOAD_FILE) != 0) { - for (Index = 0; Index < HTTP_BOOT_DHCP4_TAG_INDEX_MAX; Index++) { - if (Options[Index] == NULL) { - Options[Index] = HttpBootParseDhcp4Options ( - (UINT8 *) Offer->Dhcp4.Header.BootFileName, - sizeof (Offer->Dhcp4.Header.BootFileName), - mInterestedDhcp4Tags[Index] - ); - } - } - } - if ((Option->Data[0] & HTTP_BOOT_DHCP4_OVERLOAD_SERVER_NAME) != 0) { - for (Index = 0; Index < HTTP_BOOT_DHCP4_TAG_INDEX_MAX; Index++) { - if (Options[Index] == NULL) { - Options[Index] = HttpBootParseDhcp4Options ( - (UINT8 *) Offer->Dhcp4.Header.ServerName, - sizeof (Offer->Dhcp4.Header.ServerName), - mInterestedDhcp4Tags[Index] - ); - } - } - } - } - - // - // The offer with "yiaddr" is a proxy offer. - // - if (Offer->Dhcp4.Header.YourAddr.Addr[0] == 0) { - IsProxyOffer = TRUE; - } - - // - // The offer with "HttpClient" is a Http offer. - // - Option = Options[HTTP_BOOT_DHCP4_TAG_INDEX_CLASS_ID]; - if ((Option != NULL) && (Option->Length >= 9) && - (CompareMem (Option->Data, DEFAULT_CLASS_ID_DATA, 9) == 0)) { - IsHttpOffer = TRUE; - } - - // - // The offer with Domain Server is a DNS offer. - // - Option = Options[HTTP_BOOT_DHCP4_TAG_INDEX_DNS_SERVER]; - if (Option != NULL) { - IsDnsOffer = TRUE; - } - - // - // Parse boot file name: - // Boot URI information is provided thru 'file' field in DHCP Header or option 67. - // According to RFC 2132, boot file name should be read from DHCP option 67 (bootfile name) if present. - // Otherwise, read from boot file field in DHCP header. - // - if (Options[HTTP_BOOT_DHCP4_TAG_INDEX_BOOTFILE] != NULL) { - // - // RFC 2132, Section 9.5 does not strictly state Bootfile name (option 67) is null - // terminated string. So force to append null terminated character at the end of string. - // - Ptr8 = (UINT8*)&Options[HTTP_BOOT_DHCP4_TAG_INDEX_BOOTFILE]->Data[0]; - Ptr8 += Options[HTTP_BOOT_DHCP4_TAG_INDEX_BOOTFILE]->Length; - if (*(Ptr8 - 1) != '\0') { - *Ptr8 = '\0'; - } - } else if (Offer->Dhcp4.Header.BootFileName[0] != 0) { - // - // If the bootfile is not present and bootfilename is present in DHCPv4 packet, just parse it. - // Do not count dhcp option header here, or else will destroy the serverhostname. - // - Options[HTTP_BOOT_DHCP4_TAG_INDEX_BOOTFILE] = (EFI_DHCP4_PACKET_OPTION *) - (&Offer->Dhcp4.Header.BootFileName[0] - - OFFSET_OF (EFI_DHCP4_PACKET_OPTION, Data[0])); - } - - // - // Http offer must have a boot URI. - // - if (IsHttpOffer && Options[HTTP_BOOT_DHCP4_TAG_INDEX_BOOTFILE] == NULL) { - return EFI_DEVICE_ERROR; - } - - // - // Try to retrieve the IP of HTTP server from URI. - // - if (IsHttpOffer) { - Status = HttpParseUrl ( - (CHAR8*) Options[HTTP_BOOT_DHCP4_TAG_INDEX_BOOTFILE]->Data, - (UINT32) AsciiStrLen ((CHAR8*) Options[HTTP_BOOT_DHCP4_TAG_INDEX_BOOTFILE]->Data), - FALSE, - &Cache4->UriParser - ); - if (EFI_ERROR (Status)) { - return EFI_DEVICE_ERROR; - } - - Status = HttpUrlGetIp4 ( - (CHAR8*) Options[HTTP_BOOT_DHCP4_TAG_INDEX_BOOTFILE]->Data, - Cache4->UriParser, - &IpAddr - ); - IpExpressedUri = !EFI_ERROR (Status); - } - - // - // Determine offer type of the DHCPv4 packet. - // - if (IsHttpOffer) { - if (IpExpressedUri) { - OfferType = IsProxyOffer ? HttpOfferTypeProxyIpUri : HttpOfferTypeDhcpIpUri; - } else { - if (!IsProxyOffer) { - OfferType = IsDnsOffer ? HttpOfferTypeDhcpNameUriDns : HttpOfferTypeDhcpNameUri; - } else { - OfferType = HttpOfferTypeProxyNameUri; - } - } - - } else { - if (!IsProxyOffer) { - OfferType = IsDnsOffer ? HttpOfferTypeDhcpDns : HttpOfferTypeDhcpOnly; - } else { - return EFI_DEVICE_ERROR; - } - } - - Cache4->OfferType = OfferType; - return EFI_SUCCESS; -} - -/** - Cache all the received DHCPv4 offers, and set OfferIndex and OfferCount. - - @param[in] Private Pointer to HTTP boot driver private data. - @param[in] RcvdOffer Pointer to the received offer packet. - -**/ -VOID -HttpBootCacheDhcp4Offer ( - IN HTTP_BOOT_PRIVATE_DATA *Private, - IN EFI_DHCP4_PACKET *RcvdOffer - ) -{ - HTTP_BOOT_DHCP4_PACKET_CACHE *Cache4; - EFI_DHCP4_PACKET *Offer; - HTTP_BOOT_OFFER_TYPE OfferType; - - ASSERT (Private->OfferNum < HTTP_BOOT_OFFER_MAX_NUM); - Cache4 = &Private->OfferBuffer[Private->OfferNum].Dhcp4; - Offer = &Cache4->Packet.Offer; - - // - // Cache the content of DHCPv4 packet firstly. - // - HttpBootCacheDhcp4Packet (Offer, RcvdOffer); - - // - // Validate the DHCPv4 packet, and parse the options and offer type. - // - if (EFI_ERROR (HttpBootParseDhcp4Packet (Cache4))) { - return; - } - - // - // Determine whether cache the current offer by type, and record OfferIndex and OfferCount. - // - OfferType = Cache4->OfferType; - ASSERT (OfferType < HttpOfferTypeMax); - ASSERT (Private->OfferCount[OfferType] < HTTP_BOOT_OFFER_MAX_NUM); - Private->OfferIndex[OfferType][Private->OfferCount[OfferType]] = Private->OfferNum; - Private->OfferCount[OfferType]++; - Private->OfferNum++; -} - -/** - Select an DHCPv4 offer, and record SelectIndex and SelectProxyType. - - @param[in] Private Pointer to HTTP boot driver private data. - -**/ -VOID -HttpBootSelectDhcp4Offer ( - IN HTTP_BOOT_PRIVATE_DATA *Private - ) -{ - Private->SelectIndex = 0; - Private->SelectProxyType = HttpOfferTypeMax; - - // - // Priority1: HttpOfferTypeDhcpIpUri - // Priority2: HttpOfferTypeDhcpNameUriDns - // Priority3: HttpOfferTypeDhcpOnly + HttpOfferTypeProxyIpUri - // Priority4: HttpOfferTypeDhcpDns + HttpOfferTypeProxyIpUri - // Priority5: HttpOfferTypeDhcpDns + HttpOfferTypeProxyNameUri - // Priority6: HttpOfferTypeDhcpDns + HttpOfferTypeDhcpNameUri - // - if (Private->OfferCount[HttpOfferTypeDhcpIpUri] > 0) { - - Private->SelectIndex = Private->OfferIndex[HttpOfferTypeDhcpIpUri][0] + 1; - - } else if (Private->OfferCount[HttpOfferTypeDhcpNameUriDns] > 0) { - - Private->SelectIndex = Private->OfferIndex[HttpOfferTypeDhcpNameUriDns][0] + 1; - - } else if (Private->OfferCount[HttpOfferTypeDhcpOnly] > 0 && - Private->OfferCount[HttpOfferTypeProxyIpUri] > 0) { - - Private->SelectIndex = Private->OfferIndex[HttpOfferTypeDhcpOnly][0] + 1; - Private->SelectProxyType = HttpOfferTypeProxyIpUri; - - } else if (Private->OfferCount[HttpOfferTypeDhcpDns] > 0 && - Private->OfferCount[HttpOfferTypeProxyIpUri] > 0) { - - Private->SelectIndex = Private->OfferIndex[HttpOfferTypeDhcpDns][0] + 1; - Private->SelectProxyType = HttpOfferTypeProxyIpUri; - - } else if (Private->OfferCount[HttpOfferTypeDhcpDns] > 0 && - Private->OfferCount[HttpOfferTypeProxyNameUri] > 0) { - - Private->SelectIndex = Private->OfferIndex[HttpOfferTypeDhcpDns][0] + 1; - Private->SelectProxyType = HttpOfferTypeProxyNameUri; - - } else if (Private->OfferCount[HttpOfferTypeDhcpDns] > 0 && - Private->OfferCount[HttpOfferTypeDhcpNameUri] > 0) { - - Private->SelectIndex = Private->OfferIndex[HttpOfferTypeDhcpDns][0] + 1; - Private->SelectProxyType = HttpOfferTypeDhcpNameUri; - } -} - - -/** - EFI_DHCP4_CALLBACK is provided by the consumer of the EFI DHCPv4 Protocol driver - to intercept events that occurred in the configuration process. - - @param[in] This Pointer to the EFI DHCPv4 Protocol. - @param[in] Context Pointer to the context set by EFI_DHCP4_PROTOCOL.Configure(). - @param[in] CurrentState The current operational state of the EFI DHCPv4 Protocol driver. - @param[in] Dhcp4Event The event that occurs in the current state, which usually means a - state transition. - @param[in] Packet The DHCPv4 packet that is going to be sent or already received. - @param[out] NewPacket The packet that is used to replace the above Packet. - - @retval EFI_SUCCESS Tells the EFI DHCPv4 Protocol driver to continue the DHCP process. - @retval EFI_NOT_READY Only used in the Dhcp4Selecting state. The EFI DHCPv4 Protocol - driver will continue to wait for more DHCPOFFER packets until the - retry timeout expires. - @retval EFI_ABORTED Tells the EFI DHCPv4 Protocol driver to abort the current process - and return to the Dhcp4Init or Dhcp4InitReboot state. - -**/ -EFI_STATUS -EFIAPI -HttpBootDhcp4CallBack ( - IN EFI_DHCP4_PROTOCOL *This, - IN VOID *Context, - IN EFI_DHCP4_STATE CurrentState, - IN EFI_DHCP4_EVENT Dhcp4Event, - IN EFI_DHCP4_PACKET *Packet OPTIONAL, - OUT EFI_DHCP4_PACKET **NewPacket OPTIONAL - ) -{ - HTTP_BOOT_PRIVATE_DATA *Private; - EFI_DHCP4_PACKET_OPTION *MaxMsgSize; - UINT16 Value; - EFI_STATUS Status; - - if ((Dhcp4Event != Dhcp4RcvdOffer) && (Dhcp4Event != Dhcp4SelectOffer)) { - return EFI_SUCCESS; - } - - Private = (HTTP_BOOT_PRIVATE_DATA *) Context; - - // - // Override the Maximum DHCP Message Size. - // - MaxMsgSize = HttpBootParseDhcp4Options ( - Packet->Dhcp4.Option, - GET_OPTION_BUFFER_LEN (Packet), - HTTP_BOOT_DHCP4_TAG_MAXMSG - ); - if (MaxMsgSize != NULL) { - Value = HTONS (HTTP_BOOT_DHCP4_PACKET_MAX_SIZE); - CopyMem (MaxMsgSize->Data, &Value, sizeof (Value)); - } - - Status = EFI_SUCCESS; - switch (Dhcp4Event) { - case Dhcp4RcvdOffer: - Status = EFI_NOT_READY; - if (Private->OfferNum < HTTP_BOOT_OFFER_MAX_NUM) { - // - // Cache the DHCPv4 offers to OfferBuffer[] for select later, and record - // the OfferIndex and OfferCount. - // - HttpBootCacheDhcp4Offer (Private, Packet); - } - break; - - case Dhcp4SelectOffer: - // - // Select offer according to the priority in UEFI spec, and record the SelectIndex - // and SelectProxyType. - // - HttpBootSelectDhcp4Offer (Private); - - if (Private->SelectIndex == 0) { - Status = EFI_ABORTED; - } else { - *NewPacket = &Private->OfferBuffer[Private->SelectIndex - 1].Dhcp4.Packet.Offer; - } - break; - - default: - break; - } - - return Status; -} - -/** - This function will register the IPv4 gateway address to the network device. - - @param[in] Private The pointer to HTTP_BOOT_PRIVATE_DATA. - - @retval EFI_SUCCESS The new IP configuration has been configured successfully. - @retval Others Failed to configure the address. - -**/ -EFI_STATUS -HttpBootRegisterIp4Gateway ( - IN HTTP_BOOT_PRIVATE_DATA *Private - ) -{ - EFI_STATUS Status; - EFI_IP4_CONFIG2_PROTOCOL *Ip4Config2; - - ASSERT (!Private->UsingIpv6); - - Ip4Config2 = Private->Ip4Config2; - - // - // Configure the gateway if valid. - // - if (!EFI_IP4_EQUAL (&Private->GatewayIp, &mZeroIp4Addr)) { - Status = Ip4Config2->SetData ( - Ip4Config2, - Ip4Config2DataTypeGateway, - sizeof (EFI_IPv4_ADDRESS), - &Private->GatewayIp - ); - if (EFI_ERROR (Status)) { - return Status; - } - } - - return EFI_SUCCESS; -} - -/** - This function will register the default DNS addresses to the network device. - - @param[in] Private The pointer to HTTP_BOOT_PRIVATE_DATA. - @param[in] DataLength Size of the buffer pointed to by DnsServerData in bytes. - @param[in] DnsServerData Point a list of DNS server address in an array - of EFI_IPv4_ADDRESS instances. - - @retval EFI_SUCCESS The DNS configuration has been configured successfully. - @retval Others Failed to configure the address. - -**/ -EFI_STATUS -HttpBootRegisterIp4Dns ( - IN HTTP_BOOT_PRIVATE_DATA *Private, - IN UINTN DataLength, - IN VOID *DnsServerData - ) -{ - EFI_IP4_CONFIG2_PROTOCOL *Ip4Config2; - - ASSERT (!Private->UsingIpv6); - - Ip4Config2 = Private->Ip4Config2; - - return Ip4Config2->SetData ( - Ip4Config2, - Ip4Config2DataTypeDnsServer, - DataLength, - DnsServerData - ); -} - - -/** - This function will switch the IP4 configuration policy to Static. - - @param[in] Private Pointer to HTTP boot driver private data. - - @retval EFI_SUCCESS The policy is already configured to static. - @retval Others Other error as indicated.. - -**/ -EFI_STATUS -HttpBootSetIpPolicy ( - IN HTTP_BOOT_PRIVATE_DATA *Private - ) -{ - EFI_IP4_CONFIG2_POLICY Policy; - EFI_STATUS Status; - EFI_IP4_CONFIG2_PROTOCOL *Ip4Config2; - UINTN DataSize; - - Ip4Config2 = Private->Ip4Config2; - - DataSize = sizeof (EFI_IP4_CONFIG2_POLICY); - Status = Ip4Config2->GetData ( - Ip4Config2, - Ip4Config2DataTypePolicy, - &DataSize, - &Policy - ); - if (EFI_ERROR (Status)) { - return Status; - } - - if (Policy != Ip4Config2PolicyStatic) { - Policy = Ip4Config2PolicyStatic; - Status= Ip4Config2->SetData ( - Ip4Config2, - Ip4Config2DataTypePolicy, - sizeof (EFI_IP4_CONFIG2_POLICY), - &Policy - ); - if (EFI_ERROR (Status)) { - return Status; - } - } - - return EFI_SUCCESS; -} - -/** - Start the D.O.R.A DHCPv4 process to acquire the IPv4 address and other Http boot information. - - @param[in] Private Pointer to HTTP boot driver private data. - - @retval EFI_SUCCESS The D.O.R.A process successfully finished. - @retval Others Failed to finish the D.O.R.A process. - -**/ -EFI_STATUS -HttpBootDhcp4Dora ( - IN HTTP_BOOT_PRIVATE_DATA *Private - ) -{ - EFI_DHCP4_PROTOCOL *Dhcp4; - UINT32 OptCount; - EFI_DHCP4_PACKET_OPTION *OptList[HTTP_BOOT_DHCP4_OPTION_MAX_NUM]; - UINT8 Buffer[HTTP_BOOT_DHCP4_OPTION_MAX_SIZE]; - EFI_DHCP4_CONFIG_DATA Config; - EFI_STATUS Status; - EFI_DHCP4_MODE_DATA Mode; - - Dhcp4 = Private->Dhcp4; - ASSERT (Dhcp4 != NULL); - - Status = HttpBootSetIpPolicy (Private); - if (EFI_ERROR (Status)) { - return Status; - } - - // - // Build option list for the request packet. - // - OptCount = HttpBootBuildDhcp4Options (Private, OptList, Buffer); - ASSERT (OptCount > 0); - - ZeroMem (&Config, sizeof(Config)); - Config.OptionCount = OptCount; - Config.OptionList = OptList; - Config.Dhcp4Callback = HttpBootDhcp4CallBack; - Config.CallbackContext = Private; - Config.DiscoverTryCount = HTTP_BOOT_DHCP_RETRIES; - Config.DiscoverTimeout = mHttpDhcpTimeout; - - // - // Configure the DHCPv4 instance for HTTP boot. - // - Status = Dhcp4->Configure (Dhcp4, &Config); - if (EFI_ERROR (Status)) { - goto ON_EXIT; - } - - // - // Initialize the record fields for DHCPv4 offer in private data. - // - Private->OfferNum = 0; - ZeroMem (Private->OfferCount, sizeof (Private->OfferCount)); - ZeroMem (Private->OfferIndex, sizeof (Private->OfferIndex)); - - // - // Start DHCPv4 D.O.R.A. process to acquire IPv4 address. - // - Status = Dhcp4->Start (Dhcp4, NULL); - if (EFI_ERROR (Status)) { - goto ON_EXIT; - } - - // - // Get the acquired IPv4 address and store them. - // - Status = Dhcp4->GetModeData (Dhcp4, &Mode); - if (EFI_ERROR (Status)) { - goto ON_EXIT; - } - - ASSERT (Mode.State == Dhcp4Bound); - CopyMem (&Private->StationIp, &Mode.ClientAddress, sizeof (EFI_IPv4_ADDRESS)); - CopyMem (&Private->SubnetMask, &Mode.SubnetMask, sizeof (EFI_IPv4_ADDRESS)); - CopyMem (&Private->GatewayIp, &Mode.RouterAddress, sizeof (EFI_IPv4_ADDRESS)); - - Status = HttpBootRegisterIp4Gateway (Private); - if (EFI_ERROR (Status)) { - goto ON_EXIT; - } - - AsciiPrint ("\n Station IP address is "); - HttpBootShowIp4Addr (&Private->StationIp.v4); - AsciiPrint ("\n"); - -ON_EXIT: - if (EFI_ERROR (Status)) { - Dhcp4->Stop (Dhcp4); - Dhcp4->Configure (Dhcp4, NULL); - } else { - ZeroMem (&Config, sizeof (EFI_DHCP4_CONFIG_DATA)); - Dhcp4->Configure (Dhcp4, &Config); - } - - return Status; -} +/** @file
+ Functions implementation related with DHCPv4 for HTTP boot driver.
+
+Copyright (c) 2015, Intel Corporation. All rights reserved.<BR>
+This program and the accompanying materials are licensed and made available under
+the terms and conditions of the BSD License that accompanies this distribution.
+The full text of the license may be found at
+http://opensource.org/licenses/bsd-license.php.
+
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+**/
+
+#include "HttpBootDxe.h"
+
+//
+// This is a map from the interested DHCP4 option tags' index to the tag value.
+//
+UINT8 mInterestedDhcp4Tags[HTTP_BOOT_DHCP4_TAG_INDEX_MAX] = {
+ HTTP_BOOT_DHCP4_TAG_BOOTFILE_LEN,
+ HTTP_BOOT_DHCP4_TAG_OVERLOAD,
+ HTTP_BOOT_DHCP4_TAG_MSG_TYPE,
+ HTTP_BOOT_DHCP4_TAG_SERVER_ID,
+ HTTP_BOOT_DHCP4_TAG_CLASS_ID,
+ HTTP_BOOT_DHCP4_TAG_BOOTFILE,
+ HTTP_BOOT_DHCP4_TAG_DNS_SERVER
+};
+
+//
+// There are 4 times retries with the value of 4, 8, 16 and 32, refers to UEFI 2.5 spec.
+//
+UINT32 mHttpDhcpTimeout[4] = {4, 8, 16, 32};
+
+/**
+ Build the options buffer for the DHCPv4 request packet.
+
+ @param[in] Private Pointer to HTTP boot driver private data.
+ @param[out] OptList Pointer to the option pointer array.
+ @param[in] Buffer Pointer to the buffer to contain the option list.
+
+ @return Index The count of the built-in options.
+
+**/
+UINT32
+HttpBootBuildDhcp4Options (
+ IN HTTP_BOOT_PRIVATE_DATA *Private,
+ OUT EFI_DHCP4_PACKET_OPTION **OptList,
+ IN UINT8 *Buffer
+ )
+{
+ HTTP_BOOT_DHCP4_OPTION_ENTRY OptEnt;
+ UINT16 Value;
+ UINT32 Index;
+
+ Index = 0;
+ OptList[0] = (EFI_DHCP4_PACKET_OPTION *) Buffer;
+
+ //
+ // Append parameter request list option.
+ //
+ OptList[Index]->OpCode = HTTP_BOOT_DHCP4_TAG_PARA_LIST;
+ OptList[Index]->Length = 27;
+ OptEnt.Para = (HTTP_BOOT_DHCP4_OPTION_PARA *) OptList[Index]->Data;
+ OptEnt.Para->ParaList[0] = HTTP_BOOT_DHCP4_TAG_NETMASK;
+ OptEnt.Para->ParaList[1] = HTTP_BOOT_DHCP4_TAG_TIME_OFFSET;
+ OptEnt.Para->ParaList[2] = HTTP_BOOT_DHCP4_TAG_ROUTER;
+ OptEnt.Para->ParaList[3] = HTTP_BOOT_DHCP4_TAG_TIME_SERVER;
+ OptEnt.Para->ParaList[4] = HTTP_BOOT_DHCP4_TAG_NAME_SERVER;
+ OptEnt.Para->ParaList[5] = HTTP_BOOT_DHCP4_TAG_DNS_SERVER;
+ OptEnt.Para->ParaList[6] = HTTP_BOOT_DHCP4_TAG_HOSTNAME;
+ OptEnt.Para->ParaList[7] = HTTP_BOOT_DHCP4_TAG_BOOTFILE_LEN;
+ OptEnt.Para->ParaList[8] = HTTP_BOOT_DHCP4_TAG_DOMAINNAME;
+ OptEnt.Para->ParaList[9] = HTTP_BOOT_DHCP4_TAG_ROOTPATH;
+ OptEnt.Para->ParaList[10] = HTTP_BOOT_DHCP4_TAG_EXTEND_PATH;
+ OptEnt.Para->ParaList[11] = HTTP_BOOT_DHCP4_TAG_EMTU;
+ OptEnt.Para->ParaList[12] = HTTP_BOOT_DHCP4_TAG_TTL;
+ OptEnt.Para->ParaList[13] = HTTP_BOOT_DHCP4_TAG_BROADCAST;
+ OptEnt.Para->ParaList[14] = HTTP_BOOT_DHCP4_TAG_NIS_DOMAIN;
+ OptEnt.Para->ParaList[15] = HTTP_BOOT_DHCP4_TAG_NIS_SERVER;
+ OptEnt.Para->ParaList[16] = HTTP_BOOT_DHCP4_TAG_NTP_SERVER;
+ OptEnt.Para->ParaList[17] = HTTP_BOOT_DHCP4_TAG_VENDOR;
+ OptEnt.Para->ParaList[18] = HTTP_BOOT_DHCP4_TAG_REQUEST_IP;
+ OptEnt.Para->ParaList[19] = HTTP_BOOT_DHCP4_TAG_LEASE;
+ OptEnt.Para->ParaList[20] = HTTP_BOOT_DHCP4_TAG_SERVER_ID;
+ OptEnt.Para->ParaList[21] = HTTP_BOOT_DHCP4_TAG_T1;
+ OptEnt.Para->ParaList[22] = HTTP_BOOT_DHCP4_TAG_T2;
+ OptEnt.Para->ParaList[23] = HTTP_BOOT_DHCP4_TAG_CLASS_ID;
+ OptEnt.Para->ParaList[25] = HTTP_BOOT_DHCP4_TAG_BOOTFILE;
+ OptEnt.Para->ParaList[26] = HTTP_BOOT_DHCP4_TAG_UUID;
+ Index++;
+ OptList[Index] = GET_NEXT_DHCP_OPTION (OptList[Index - 1]);
+
+ //
+ // Append UUID/Guid-based client identifier option
+ //
+ OptList[Index]->OpCode = HTTP_BOOT_DHCP4_TAG_UUID;
+ OptList[Index]->Length = (UINT8) sizeof (HTTP_BOOT_DHCP4_OPTION_UUID);
+ OptEnt.Uuid = (HTTP_BOOT_DHCP4_OPTION_UUID *) OptList[Index]->Data;
+ OptEnt.Uuid->Type = 0;
+ if (EFI_ERROR (NetLibGetSystemGuid ((EFI_GUID *) OptEnt.Uuid->Guid))) {
+ //
+ // Zero the Guid to indicate NOT programable if failed to get system Guid.
+ //
+ ZeroMem (OptEnt.Uuid->Guid, sizeof (EFI_GUID));
+ }
+ Index++;
+ OptList[Index] = GET_NEXT_DHCP_OPTION (OptList[Index - 1]);
+
+ //
+ // Append client network device interface option
+ //
+ OptList[Index]->OpCode = HTTP_BOOT_DHCP4_TAG_UNDI;
+ OptList[Index]->Length = (UINT8) sizeof (HTTP_BOOT_DHCP4_OPTION_UNDI);
+ OptEnt.Undi = (HTTP_BOOT_DHCP4_OPTION_UNDI *) OptList[Index]->Data;
+
+ if (Private->Nii != NULL) {
+ OptEnt.Undi->Type = Private->Nii->Type;
+ OptEnt.Undi->MajorVer = Private->Nii->MajorVer;
+ OptEnt.Undi->MinorVer = Private->Nii->MinorVer;
+ } else {
+ OptEnt.Undi->Type = DEFAULT_UNDI_TYPE;
+ OptEnt.Undi->MajorVer = DEFAULT_UNDI_MAJOR;
+ OptEnt.Undi->MinorVer = DEFAULT_UNDI_MINOR;
+ }
+
+ Index++;
+ OptList[Index] = GET_NEXT_DHCP_OPTION (OptList[Index - 1]);
+
+ //
+ // Append client system architecture option
+ //
+ OptList[Index]->OpCode = HTTP_BOOT_DHCP4_TAG_ARCH;
+ OptList[Index]->Length = (UINT8) sizeof (HTTP_BOOT_DHCP4_OPTION_ARCH);
+ OptEnt.Arch = (HTTP_BOOT_DHCP4_OPTION_ARCH *) OptList[Index]->Data;
+ Value = HTONS (EFI_HTTP_BOOT_CLIENT_SYSTEM_ARCHITECTURE);
+ CopyMem (&OptEnt.Arch->Type, &Value, sizeof (UINT16));
+ Index++;
+ OptList[Index] = GET_NEXT_DHCP_OPTION (OptList[Index - 1]);
+
+ //
+ // Append vendor class identify option
+ //
+ OptList[Index]->OpCode = HTTP_BOOT_DHCP4_TAG_CLASS_ID;
+ OptList[Index]->Length = (UINT8) sizeof (HTTP_BOOT_DHCP4_OPTION_CLID);
+ OptEnt.Clid = (HTTP_BOOT_DHCP4_OPTION_CLID *) OptList[Index]->Data;
+ CopyMem (
+ OptEnt.Clid,
+ DEFAULT_CLASS_ID_DATA,
+ sizeof (HTTP_BOOT_DHCP4_OPTION_CLID)
+ );
+ HttpBootUintnToAscDecWithFormat (
+ EFI_HTTP_BOOT_CLIENT_SYSTEM_ARCHITECTURE,
+ OptEnt.Clid->ArchitectureType,
+ sizeof (OptEnt.Clid->ArchitectureType)
+ );
+
+ if (Private->Nii != NULL) {
+ CopyMem (OptEnt.Clid->InterfaceName, Private->Nii->StringId, sizeof (OptEnt.Clid->InterfaceName));
+ HttpBootUintnToAscDecWithFormat (Private->Nii->MajorVer, OptEnt.Clid->UndiMajor, sizeof (OptEnt.Clid->UndiMajor));
+ HttpBootUintnToAscDecWithFormat (Private->Nii->MinorVer, OptEnt.Clid->UndiMinor, sizeof (OptEnt.Clid->UndiMinor));
+ }
+
+ Index++;
+
+ return Index;
+}
+
+/**
+ Parse a certain dhcp4 option by OptTag in Buffer, and return with start pointer.
+
+ @param[in] Buffer Pointer to the option buffer.
+ @param[in] Length Length of the option buffer.
+ @param[in] OptTag Tag of the required option.
+
+ @retval NULL Failed to find the required option.
+ @retval Others The position of the required option.
+
+**/
+EFI_DHCP4_PACKET_OPTION *
+HttpBootParseDhcp4Options (
+ IN UINT8 *Buffer,
+ IN UINT32 Length,
+ IN UINT8 OptTag
+ )
+{
+ EFI_DHCP4_PACKET_OPTION *Option;
+ UINT32 Offset;
+
+ Option = (EFI_DHCP4_PACKET_OPTION *) Buffer;
+ Offset = 0;
+
+ while (Offset < Length && Option->OpCode != HTTP_BOOT_DHCP4_TAG_EOP) {
+
+ if (Option->OpCode == OptTag) {
+ //
+ // Found the required option.
+ //
+ return Option;
+ }
+
+ //
+ // Skip the current option to the next.
+ //
+ if (Option->OpCode == HTTP_BOOT_DHCP4_TAG_PAD) {
+ Offset++;
+ } else {
+ Offset += Option->Length + 2;
+ }
+
+ Option = (EFI_DHCP4_PACKET_OPTION *) (Buffer + Offset);
+ }
+
+ return NULL;
+}
+
+/**
+ Cache the DHCPv4 packet.
+
+ @param[in] Dst Pointer to the cache buffer for DHCPv4 packet.
+ @param[in] Src Pointer to the DHCPv4 packet to be cached.
+
+**/
+VOID
+HttpBootCacheDhcp4Packet (
+ IN EFI_DHCP4_PACKET *Dst,
+ IN EFI_DHCP4_PACKET *Src
+ )
+{
+ ASSERT (Dst->Size >= Src->Length);
+
+ CopyMem (&Dst->Dhcp4, &Src->Dhcp4, Src->Length);
+ Dst->Length = Src->Length;
+}
+
+/**
+ Parse the cached DHCPv4 packet, including all the options.
+
+ @param[in] Cache4 Pointer to cached DHCPv4 packet.
+
+ @retval EFI_SUCCESS Parsed the DHCPv4 packet successfully.
+ @retval EFI_DEVICE_ERROR Failed to parse an invalid packet.
+
+**/
+EFI_STATUS
+HttpBootParseDhcp4Packet (
+ IN HTTP_BOOT_DHCP4_PACKET_CACHE *Cache4
+ )
+{
+ EFI_DHCP4_PACKET *Offer;
+ EFI_DHCP4_PACKET_OPTION **Options;
+ UINTN Index;
+ EFI_DHCP4_PACKET_OPTION *Option;
+ BOOLEAN IsProxyOffer;
+ BOOLEAN IsHttpOffer;
+ BOOLEAN IsDnsOffer;
+ BOOLEAN IpExpressedUri;
+ UINT8 *Ptr8;
+ EFI_STATUS Status;
+ HTTP_BOOT_OFFER_TYPE OfferType;
+ EFI_IPv4_ADDRESS IpAddr;
+
+ IsDnsOffer = FALSE;
+ IpExpressedUri = FALSE;
+ IsProxyOffer = FALSE;
+ IsHttpOffer = FALSE;
+
+ ZeroMem (Cache4->OptList, sizeof (Cache4->OptList));
+
+ Offer = &Cache4->Packet.Offer;
+ Options = Cache4->OptList;
+
+ //
+ // Parse DHCPv4 options in this offer, and store the pointers.
+ // First, try to parse DHCPv4 options from the DHCP optional parameters field.
+ //
+ for (Index = 0; Index < HTTP_BOOT_DHCP4_TAG_INDEX_MAX; Index++) {
+ Options[Index] = HttpBootParseDhcp4Options (
+ Offer->Dhcp4.Option,
+ GET_OPTION_BUFFER_LEN (Offer),
+ mInterestedDhcp4Tags[Index]
+ );
+ }
+ //
+ // Second, Check if bootfilename and serverhostname is overloaded to carry DHCP options refers to rfc-2132.
+ // If yes, try to parse options from the BootFileName field, then ServerName field.
+ //
+ Option = Options[HTTP_BOOT_DHCP4_TAG_INDEX_OVERLOAD];
+ if (Option != NULL) {
+ if ((Option->Data[0] & HTTP_BOOT_DHCP4_OVERLOAD_FILE) != 0) {
+ for (Index = 0; Index < HTTP_BOOT_DHCP4_TAG_INDEX_MAX; Index++) {
+ if (Options[Index] == NULL) {
+ Options[Index] = HttpBootParseDhcp4Options (
+ (UINT8 *) Offer->Dhcp4.Header.BootFileName,
+ sizeof (Offer->Dhcp4.Header.BootFileName),
+ mInterestedDhcp4Tags[Index]
+ );
+ }
+ }
+ }
+ if ((Option->Data[0] & HTTP_BOOT_DHCP4_OVERLOAD_SERVER_NAME) != 0) {
+ for (Index = 0; Index < HTTP_BOOT_DHCP4_TAG_INDEX_MAX; Index++) {
+ if (Options[Index] == NULL) {
+ Options[Index] = HttpBootParseDhcp4Options (
+ (UINT8 *) Offer->Dhcp4.Header.ServerName,
+ sizeof (Offer->Dhcp4.Header.ServerName),
+ mInterestedDhcp4Tags[Index]
+ );
+ }
+ }
+ }
+ }
+
+ //
+ // The offer with "yiaddr" is a proxy offer.
+ //
+ if (Offer->Dhcp4.Header.YourAddr.Addr[0] == 0) {
+ IsProxyOffer = TRUE;
+ }
+
+ //
+ // The offer with "HttpClient" is a Http offer.
+ //
+ Option = Options[HTTP_BOOT_DHCP4_TAG_INDEX_CLASS_ID];
+ if ((Option != NULL) && (Option->Length >= 9) &&
+ (CompareMem (Option->Data, DEFAULT_CLASS_ID_DATA, 9) == 0)) {
+ IsHttpOffer = TRUE;
+ }
+
+ //
+ // The offer with Domain Server is a DNS offer.
+ //
+ Option = Options[HTTP_BOOT_DHCP4_TAG_INDEX_DNS_SERVER];
+ if (Option != NULL) {
+ IsDnsOffer = TRUE;
+ }
+
+ //
+ // Parse boot file name:
+ // Boot URI information is provided thru 'file' field in DHCP Header or option 67.
+ // According to RFC 2132, boot file name should be read from DHCP option 67 (bootfile name) if present.
+ // Otherwise, read from boot file field in DHCP header.
+ //
+ if (Options[HTTP_BOOT_DHCP4_TAG_INDEX_BOOTFILE] != NULL) {
+ //
+ // RFC 2132, Section 9.5 does not strictly state Bootfile name (option 67) is null
+ // terminated string. So force to append null terminated character at the end of string.
+ //
+ Ptr8 = (UINT8*)&Options[HTTP_BOOT_DHCP4_TAG_INDEX_BOOTFILE]->Data[0];
+ Ptr8 += Options[HTTP_BOOT_DHCP4_TAG_INDEX_BOOTFILE]->Length;
+ if (*(Ptr8 - 1) != '\0') {
+ *Ptr8 = '\0';
+ }
+ } else if (Offer->Dhcp4.Header.BootFileName[0] != 0) {
+ //
+ // If the bootfile is not present and bootfilename is present in DHCPv4 packet, just parse it.
+ // Do not count dhcp option header here, or else will destroy the serverhostname.
+ //
+ Options[HTTP_BOOT_DHCP4_TAG_INDEX_BOOTFILE] = (EFI_DHCP4_PACKET_OPTION *)
+ (&Offer->Dhcp4.Header.BootFileName[0] -
+ OFFSET_OF (EFI_DHCP4_PACKET_OPTION, Data[0]));
+ }
+
+ //
+ // Http offer must have a boot URI.
+ //
+ if (IsHttpOffer && Options[HTTP_BOOT_DHCP4_TAG_INDEX_BOOTFILE] == NULL) {
+ return EFI_DEVICE_ERROR;
+ }
+
+ //
+ // Try to retrieve the IP of HTTP server from URI.
+ //
+ if (IsHttpOffer) {
+ Status = HttpParseUrl (
+ (CHAR8*) Options[HTTP_BOOT_DHCP4_TAG_INDEX_BOOTFILE]->Data,
+ (UINT32) AsciiStrLen ((CHAR8*) Options[HTTP_BOOT_DHCP4_TAG_INDEX_BOOTFILE]->Data),
+ FALSE,
+ &Cache4->UriParser
+ );
+ if (EFI_ERROR (Status)) {
+ return EFI_DEVICE_ERROR;
+ }
+
+ Status = HttpUrlGetIp4 (
+ (CHAR8*) Options[HTTP_BOOT_DHCP4_TAG_INDEX_BOOTFILE]->Data,
+ Cache4->UriParser,
+ &IpAddr
+ );
+ IpExpressedUri = !EFI_ERROR (Status);
+ }
+
+ //
+ // Determine offer type of the DHCPv4 packet.
+ //
+ if (IsHttpOffer) {
+ if (IpExpressedUri) {
+ OfferType = IsProxyOffer ? HttpOfferTypeProxyIpUri : HttpOfferTypeDhcpIpUri;
+ } else {
+ if (!IsProxyOffer) {
+ OfferType = IsDnsOffer ? HttpOfferTypeDhcpNameUriDns : HttpOfferTypeDhcpNameUri;
+ } else {
+ OfferType = HttpOfferTypeProxyNameUri;
+ }
+ }
+
+ } else {
+ if (!IsProxyOffer) {
+ OfferType = IsDnsOffer ? HttpOfferTypeDhcpDns : HttpOfferTypeDhcpOnly;
+ } else {
+ return EFI_DEVICE_ERROR;
+ }
+ }
+
+ Cache4->OfferType = OfferType;
+ return EFI_SUCCESS;
+}
+
+/**
+ Cache all the received DHCPv4 offers, and set OfferIndex and OfferCount.
+
+ @param[in] Private Pointer to HTTP boot driver private data.
+ @param[in] RcvdOffer Pointer to the received offer packet.
+
+**/
+VOID
+HttpBootCacheDhcp4Offer (
+ IN HTTP_BOOT_PRIVATE_DATA *Private,
+ IN EFI_DHCP4_PACKET *RcvdOffer
+ )
+{
+ HTTP_BOOT_DHCP4_PACKET_CACHE *Cache4;
+ EFI_DHCP4_PACKET *Offer;
+ HTTP_BOOT_OFFER_TYPE OfferType;
+
+ ASSERT (Private->OfferNum < HTTP_BOOT_OFFER_MAX_NUM);
+ Cache4 = &Private->OfferBuffer[Private->OfferNum].Dhcp4;
+ Offer = &Cache4->Packet.Offer;
+
+ //
+ // Cache the content of DHCPv4 packet firstly.
+ //
+ HttpBootCacheDhcp4Packet (Offer, RcvdOffer);
+
+ //
+ // Validate the DHCPv4 packet, and parse the options and offer type.
+ //
+ if (EFI_ERROR (HttpBootParseDhcp4Packet (Cache4))) {
+ return;
+ }
+
+ //
+ // Determine whether cache the current offer by type, and record OfferIndex and OfferCount.
+ //
+ OfferType = Cache4->OfferType;
+ ASSERT (OfferType < HttpOfferTypeMax);
+ ASSERT (Private->OfferCount[OfferType] < HTTP_BOOT_OFFER_MAX_NUM);
+ Private->OfferIndex[OfferType][Private->OfferCount[OfferType]] = Private->OfferNum;
+ Private->OfferCount[OfferType]++;
+ Private->OfferNum++;
+}
+
+/**
+ Select an DHCPv4 offer, and record SelectIndex and SelectProxyType.
+
+ @param[in] Private Pointer to HTTP boot driver private data.
+
+**/
+VOID
+HttpBootSelectDhcp4Offer (
+ IN HTTP_BOOT_PRIVATE_DATA *Private
+ )
+{
+ Private->SelectIndex = 0;
+ Private->SelectProxyType = HttpOfferTypeMax;
+
+ //
+ // Priority1: HttpOfferTypeDhcpIpUri
+ // Priority2: HttpOfferTypeDhcpNameUriDns
+ // Priority3: HttpOfferTypeDhcpOnly + HttpOfferTypeProxyIpUri
+ // Priority4: HttpOfferTypeDhcpDns + HttpOfferTypeProxyIpUri
+ // Priority5: HttpOfferTypeDhcpDns + HttpOfferTypeProxyNameUri
+ // Priority6: HttpOfferTypeDhcpDns + HttpOfferTypeDhcpNameUri
+ //
+ if (Private->OfferCount[HttpOfferTypeDhcpIpUri] > 0) {
+
+ Private->SelectIndex = Private->OfferIndex[HttpOfferTypeDhcpIpUri][0] + 1;
+
+ } else if (Private->OfferCount[HttpOfferTypeDhcpNameUriDns] > 0) {
+
+ Private->SelectIndex = Private->OfferIndex[HttpOfferTypeDhcpNameUriDns][0] + 1;
+
+ } else if (Private->OfferCount[HttpOfferTypeDhcpOnly] > 0 &&
+ Private->OfferCount[HttpOfferTypeProxyIpUri] > 0) {
+
+ Private->SelectIndex = Private->OfferIndex[HttpOfferTypeDhcpOnly][0] + 1;
+ Private->SelectProxyType = HttpOfferTypeProxyIpUri;
+
+ } else if (Private->OfferCount[HttpOfferTypeDhcpDns] > 0 &&
+ Private->OfferCount[HttpOfferTypeProxyIpUri] > 0) {
+
+ Private->SelectIndex = Private->OfferIndex[HttpOfferTypeDhcpDns][0] + 1;
+ Private->SelectProxyType = HttpOfferTypeProxyIpUri;
+
+ } else if (Private->OfferCount[HttpOfferTypeDhcpDns] > 0 &&
+ Private->OfferCount[HttpOfferTypeProxyNameUri] > 0) {
+
+ Private->SelectIndex = Private->OfferIndex[HttpOfferTypeDhcpDns][0] + 1;
+ Private->SelectProxyType = HttpOfferTypeProxyNameUri;
+
+ } else if (Private->OfferCount[HttpOfferTypeDhcpDns] > 0 &&
+ Private->OfferCount[HttpOfferTypeDhcpNameUri] > 0) {
+
+ Private->SelectIndex = Private->OfferIndex[HttpOfferTypeDhcpDns][0] + 1;
+ Private->SelectProxyType = HttpOfferTypeDhcpNameUri;
+ }
+}
+
+
+/**
+ EFI_DHCP4_CALLBACK is provided by the consumer of the EFI DHCPv4 Protocol driver
+ to intercept events that occurred in the configuration process.
+
+ @param[in] This Pointer to the EFI DHCPv4 Protocol.
+ @param[in] Context Pointer to the context set by EFI_DHCP4_PROTOCOL.Configure().
+ @param[in] CurrentState The current operational state of the EFI DHCPv4 Protocol driver.
+ @param[in] Dhcp4Event The event that occurs in the current state, which usually means a
+ state transition.
+ @param[in] Packet The DHCPv4 packet that is going to be sent or already received.
+ @param[out] NewPacket The packet that is used to replace the above Packet.
+
+ @retval EFI_SUCCESS Tells the EFI DHCPv4 Protocol driver to continue the DHCP process.
+ @retval EFI_NOT_READY Only used in the Dhcp4Selecting state. The EFI DHCPv4 Protocol
+ driver will continue to wait for more DHCPOFFER packets until the
+ retry timeout expires.
+ @retval EFI_ABORTED Tells the EFI DHCPv4 Protocol driver to abort the current process
+ and return to the Dhcp4Init or Dhcp4InitReboot state.
+
+**/
+EFI_STATUS
+EFIAPI
+HttpBootDhcp4CallBack (
+ IN EFI_DHCP4_PROTOCOL *This,
+ IN VOID *Context,
+ IN EFI_DHCP4_STATE CurrentState,
+ IN EFI_DHCP4_EVENT Dhcp4Event,
+ IN EFI_DHCP4_PACKET *Packet OPTIONAL,
+ OUT EFI_DHCP4_PACKET **NewPacket OPTIONAL
+ )
+{
+ HTTP_BOOT_PRIVATE_DATA *Private;
+ EFI_DHCP4_PACKET_OPTION *MaxMsgSize;
+ UINT16 Value;
+ EFI_STATUS Status;
+
+ if ((Dhcp4Event != Dhcp4RcvdOffer) && (Dhcp4Event != Dhcp4SelectOffer)) {
+ return EFI_SUCCESS;
+ }
+
+ Private = (HTTP_BOOT_PRIVATE_DATA *) Context;
+
+ //
+ // Override the Maximum DHCP Message Size.
+ //
+ MaxMsgSize = HttpBootParseDhcp4Options (
+ Packet->Dhcp4.Option,
+ GET_OPTION_BUFFER_LEN (Packet),
+ HTTP_BOOT_DHCP4_TAG_MAXMSG
+ );
+ if (MaxMsgSize != NULL) {
+ Value = HTONS (HTTP_BOOT_DHCP4_PACKET_MAX_SIZE);
+ CopyMem (MaxMsgSize->Data, &Value, sizeof (Value));
+ }
+
+ Status = EFI_SUCCESS;
+ switch (Dhcp4Event) {
+ case Dhcp4RcvdOffer:
+ Status = EFI_NOT_READY;
+ if (Private->OfferNum < HTTP_BOOT_OFFER_MAX_NUM) {
+ //
+ // Cache the DHCPv4 offers to OfferBuffer[] for select later, and record
+ // the OfferIndex and OfferCount.
+ //
+ HttpBootCacheDhcp4Offer (Private, Packet);
+ }
+ break;
+
+ case Dhcp4SelectOffer:
+ //
+ // Select offer according to the priority in UEFI spec, and record the SelectIndex
+ // and SelectProxyType.
+ //
+ HttpBootSelectDhcp4Offer (Private);
+
+ if (Private->SelectIndex == 0) {
+ Status = EFI_ABORTED;
+ } else {
+ *NewPacket = &Private->OfferBuffer[Private->SelectIndex - 1].Dhcp4.Packet.Offer;
+ }
+ break;
+
+ default:
+ break;
+ }
+
+ return Status;
+}
+
+/**
+ This function will register the IPv4 gateway address to the network device.
+
+ @param[in] Private The pointer to HTTP_BOOT_PRIVATE_DATA.
+
+ @retval EFI_SUCCESS The new IP configuration has been configured successfully.
+ @retval Others Failed to configure the address.
+
+**/
+EFI_STATUS
+HttpBootRegisterIp4Gateway (
+ IN HTTP_BOOT_PRIVATE_DATA *Private
+ )
+{
+ EFI_STATUS Status;
+ EFI_IP4_CONFIG2_PROTOCOL *Ip4Config2;
+
+ ASSERT (!Private->UsingIpv6);
+
+ Ip4Config2 = Private->Ip4Config2;
+
+ //
+ // Configure the gateway if valid.
+ //
+ if (!EFI_IP4_EQUAL (&Private->GatewayIp, &mZeroIp4Addr)) {
+ Status = Ip4Config2->SetData (
+ Ip4Config2,
+ Ip4Config2DataTypeGateway,
+ sizeof (EFI_IPv4_ADDRESS),
+ &Private->GatewayIp
+ );
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+ }
+
+ return EFI_SUCCESS;
+}
+
+/**
+ This function will register the default DNS addresses to the network device.
+
+ @param[in] Private The pointer to HTTP_BOOT_PRIVATE_DATA.
+ @param[in] DataLength Size of the buffer pointed to by DnsServerData in bytes.
+ @param[in] DnsServerData Point a list of DNS server address in an array
+ of EFI_IPv4_ADDRESS instances.
+
+ @retval EFI_SUCCESS The DNS configuration has been configured successfully.
+ @retval Others Failed to configure the address.
+
+**/
+EFI_STATUS
+HttpBootRegisterIp4Dns (
+ IN HTTP_BOOT_PRIVATE_DATA *Private,
+ IN UINTN DataLength,
+ IN VOID *DnsServerData
+ )
+{
+ EFI_IP4_CONFIG2_PROTOCOL *Ip4Config2;
+
+ ASSERT (!Private->UsingIpv6);
+
+ Ip4Config2 = Private->Ip4Config2;
+
+ return Ip4Config2->SetData (
+ Ip4Config2,
+ Ip4Config2DataTypeDnsServer,
+ DataLength,
+ DnsServerData
+ );
+}
+
+
+/**
+ This function will switch the IP4 configuration policy to Static.
+
+ @param[in] Private Pointer to HTTP boot driver private data.
+
+ @retval EFI_SUCCESS The policy is already configured to static.
+ @retval Others Other error as indicated..
+
+**/
+EFI_STATUS
+HttpBootSetIpPolicy (
+ IN HTTP_BOOT_PRIVATE_DATA *Private
+ )
+{
+ EFI_IP4_CONFIG2_POLICY Policy;
+ EFI_STATUS Status;
+ EFI_IP4_CONFIG2_PROTOCOL *Ip4Config2;
+ UINTN DataSize;
+
+ Ip4Config2 = Private->Ip4Config2;
+
+ DataSize = sizeof (EFI_IP4_CONFIG2_POLICY);
+ Status = Ip4Config2->GetData (
+ Ip4Config2,
+ Ip4Config2DataTypePolicy,
+ &DataSize,
+ &Policy
+ );
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+
+ if (Policy != Ip4Config2PolicyStatic) {
+ Policy = Ip4Config2PolicyStatic;
+ Status= Ip4Config2->SetData (
+ Ip4Config2,
+ Ip4Config2DataTypePolicy,
+ sizeof (EFI_IP4_CONFIG2_POLICY),
+ &Policy
+ );
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+ }
+
+ return EFI_SUCCESS;
+}
+
+/**
+ Start the D.O.R.A DHCPv4 process to acquire the IPv4 address and other Http boot information.
+
+ @param[in] Private Pointer to HTTP boot driver private data.
+
+ @retval EFI_SUCCESS The D.O.R.A process successfully finished.
+ @retval Others Failed to finish the D.O.R.A process.
+
+**/
+EFI_STATUS
+HttpBootDhcp4Dora (
+ IN HTTP_BOOT_PRIVATE_DATA *Private
+ )
+{
+ EFI_DHCP4_PROTOCOL *Dhcp4;
+ UINT32 OptCount;
+ EFI_DHCP4_PACKET_OPTION *OptList[HTTP_BOOT_DHCP4_OPTION_MAX_NUM];
+ UINT8 Buffer[HTTP_BOOT_DHCP4_OPTION_MAX_SIZE];
+ EFI_DHCP4_CONFIG_DATA Config;
+ EFI_STATUS Status;
+ EFI_DHCP4_MODE_DATA Mode;
+
+ Dhcp4 = Private->Dhcp4;
+ ASSERT (Dhcp4 != NULL);
+
+ Status = HttpBootSetIpPolicy (Private);
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+
+ //
+ // Build option list for the request packet.
+ //
+ OptCount = HttpBootBuildDhcp4Options (Private, OptList, Buffer);
+ ASSERT (OptCount > 0);
+
+ ZeroMem (&Config, sizeof(Config));
+ Config.OptionCount = OptCount;
+ Config.OptionList = OptList;
+ Config.Dhcp4Callback = HttpBootDhcp4CallBack;
+ Config.CallbackContext = Private;
+ Config.DiscoverTryCount = HTTP_BOOT_DHCP_RETRIES;
+ Config.DiscoverTimeout = mHttpDhcpTimeout;
+
+ //
+ // Configure the DHCPv4 instance for HTTP boot.
+ //
+ Status = Dhcp4->Configure (Dhcp4, &Config);
+ if (EFI_ERROR (Status)) {
+ goto ON_EXIT;
+ }
+
+ //
+ // Initialize the record fields for DHCPv4 offer in private data.
+ //
+ Private->OfferNum = 0;
+ ZeroMem (Private->OfferCount, sizeof (Private->OfferCount));
+ ZeroMem (Private->OfferIndex, sizeof (Private->OfferIndex));
+
+ //
+ // Start DHCPv4 D.O.R.A. process to acquire IPv4 address.
+ //
+ Status = Dhcp4->Start (Dhcp4, NULL);
+ if (EFI_ERROR (Status)) {
+ goto ON_EXIT;
+ }
+
+ //
+ // Get the acquired IPv4 address and store them.
+ //
+ Status = Dhcp4->GetModeData (Dhcp4, &Mode);
+ if (EFI_ERROR (Status)) {
+ goto ON_EXIT;
+ }
+
+ ASSERT (Mode.State == Dhcp4Bound);
+ CopyMem (&Private->StationIp, &Mode.ClientAddress, sizeof (EFI_IPv4_ADDRESS));
+ CopyMem (&Private->SubnetMask, &Mode.SubnetMask, sizeof (EFI_IPv4_ADDRESS));
+ CopyMem (&Private->GatewayIp, &Mode.RouterAddress, sizeof (EFI_IPv4_ADDRESS));
+
+ Status = HttpBootRegisterIp4Gateway (Private);
+ if (EFI_ERROR (Status)) {
+ goto ON_EXIT;
+ }
+
+ AsciiPrint ("\n Station IP address is ");
+ HttpBootShowIp4Addr (&Private->StationIp.v4);
+ AsciiPrint ("\n");
+
+ON_EXIT:
+ if (EFI_ERROR (Status)) {
+ Dhcp4->Stop (Dhcp4);
+ Dhcp4->Configure (Dhcp4, NULL);
+ } else {
+ ZeroMem (&Config, sizeof (EFI_DHCP4_CONFIG_DATA));
+ Dhcp4->Configure (Dhcp4, &Config);
+ }
+
+ return Status;
+}
diff --git a/NetworkPkg/HttpBootDxe/HttpBootDhcp4.h b/NetworkPkg/HttpBootDxe/HttpBootDhcp4.h index 47e07aaa85..200501666b 100644 --- a/NetworkPkg/HttpBootDxe/HttpBootDhcp4.h +++ b/NetworkPkg/HttpBootDxe/HttpBootDhcp4.h @@ -1,281 +1,281 @@ -/** @file - Functions declaration related with DHCPv4 for HTTP boot driver. - -Copyright (c) 2015, Intel Corporation. All rights reserved.<BR> -This program and the accompanying materials are licensed and made available under -the terms and conditions of the BSD License that accompanies this distribution. -The full text of the license may be found at -http://opensource.org/licenses/bsd-license.php. - -THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, -WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. - -**/ - -#ifndef __EFI_UEFI_HTTP_BOOT_DHCP4_H__ -#define __EFI_UEFI_HTTP_BOOT_DHCP4_H__ - -#define HTTP_BOOT_DHCP4_OPTION_MAX_NUM 16 -#define HTTP_BOOT_DHCP4_OPTION_MAX_SIZE 312 -#define HTTP_BOOT_DHCP4_PACKET_MAX_SIZE 1472 - -#define HTTP_BOOT_DHCP4_OPCODE_REQUEST 1 -#define HTTP_BOOT_DHCP4_OPCODE_REPLY 2 -#define HTTP_BOOT_DHCP4_MSG_TYPE_REQUEST 3 -#define HTTP_BOOT_DHCP4_MAGIC 0x63538263 // network byte order - -// -// Dhcp Options -// -#define HTTP_BOOT_DHCP4_TAG_PAD 0 // Pad Option -#define HTTP_BOOT_DHCP4_TAG_EOP 255 // End Option -#define HTTP_BOOT_DHCP4_TAG_NETMASK 1 // Subnet Mask -#define HTTP_BOOT_DHCP4_TAG_TIME_OFFSET 2 // Time Offset from UTC -#define HTTP_BOOT_DHCP4_TAG_ROUTER 3 // Router option, -#define HTTP_BOOT_DHCP4_TAG_TIME_SERVER 4 // Time Server -#define HTTP_BOOT_DHCP4_TAG_NAME_SERVER 5 // Name Server -#define HTTP_BOOT_DHCP4_TAG_DNS_SERVER 6 // Domain Name Server -#define HTTP_BOOT_DHCP4_TAG_HOSTNAME 12 // Host Name -#define HTTP_BOOT_DHCP4_TAG_BOOTFILE_LEN 13 // Boot File Size -#define HTTP_BOOT_DHCP4_TAG_DUMP 14 // Merit Dump File -#define HTTP_BOOT_DHCP4_TAG_DOMAINNAME 15 // Domain Name -#define HTTP_BOOT_DHCP4_TAG_ROOTPATH 17 // Root path -#define HTTP_BOOT_DHCP4_TAG_EXTEND_PATH 18 // Extensions Path -#define HTTP_BOOT_DHCP4_TAG_EMTU 22 // Maximum Datagram Reassembly Size -#define HTTP_BOOT_DHCP4_TAG_TTL 23 // Default IP Time-to-live -#define HTTP_BOOT_DHCP4_TAG_BROADCAST 28 // Broadcast Address -#define HTTP_BOOT_DHCP4_TAG_NIS_DOMAIN 40 // Network Information Service Domain -#define HTTP_BOOT_DHCP4_TAG_NIS_SERVER 41 // Network Information Servers -#define HTTP_BOOT_DHCP4_TAG_NTP_SERVER 42 // Network Time Protocol Servers -#define HTTP_BOOT_DHCP4_TAG_VENDOR 43 // Vendor Specific Information -#define HTTP_BOOT_DHCP4_TAG_REQUEST_IP 50 // Requested IP Address -#define HTTP_BOOT_DHCP4_TAG_LEASE 51 // IP Address Lease Time -#define HTTP_BOOT_DHCP4_TAG_OVERLOAD 52 // Option Overload -#define HTTP_BOOT_DHCP4_TAG_MSG_TYPE 53 // DHCP Message Type -#define HTTP_BOOT_DHCP4_TAG_SERVER_ID 54 // Server Identifier -#define HTTP_BOOT_DHCP4_TAG_PARA_LIST 55 // Parameter Request List -#define HTTP_BOOT_DHCP4_TAG_MAXMSG 57 // Maximum DHCP Message Size -#define HTTP_BOOT_DHCP4_TAG_T1 58 // Renewal (T1) Time Value -#define HTTP_BOOT_DHCP4_TAG_T2 59 // Rebinding (T2) Time Value -#define HTTP_BOOT_DHCP4_TAG_CLASS_ID 60 // Vendor class identifier -#define HTTP_BOOT_DHCP4_TAG_CLIENT_ID 61 // Client-identifier -#define HTTP_BOOT_DHCP4_TAG_TFTP 66 // TFTP server name -#define HTTP_BOOT_DHCP4_TAG_BOOTFILE 67 // Bootfile name -#define HTTP_BOOT_DHCP4_TAG_ARCH 93 -#define HTTP_BOOT_DHCP4_TAG_UNDI 94 -#define HTTP_BOOT_DHCP4_TAG_UUID 97 - -#define HTTP_BOOT_DHCP4_OVERLOAD_FILE 1 -#define HTTP_BOOT_DHCP4_OVERLOAD_SERVER_NAME 2 - -/// -/// HTTP Tag definition that identifies the processor -/// and programming environment of the client system. -/// These identifiers are defined by IETF: -/// http://www.ietf.org/assignments/dhcpv6-parameters/dhcpv6-parameters.xml -/// -#if defined (MDE_CPU_IA32) -#define EFI_HTTP_BOOT_CLIENT_SYSTEM_ARCHITECTURE 0x000F -#elif defined (MDE_CPU_X64) -#define EFI_HTTP_BOOT_CLIENT_SYSTEM_ARCHITECTURE 0x0010 -#elif defined (MDE_CPU_ARM) -#define EFI_HTTP_BOOT_CLIENT_SYSTEM_ARCHITECTURE 0x0012 -#elif defined (MDE_CPU_AARCH64) -#define EFI_HTTP_BOOT_CLIENT_SYSTEM_ARCHITECTURE 0x0013 -#elif defined (MDE_CPU_EBC) -#define EFI_HTTP_BOOT_CLIENT_SYSTEM_ARCHITECTURE 0x0011 -#endif - -/// DHCP offer types among HTTP boot. -/// Dhcp4 and Dhcp6 share this definition, and corresponding -/// relatioinship is as follows: -/// Dhcp4Discover <> Dhcp6Solicit -/// Dhcp4Offer <> Dhcp6Advertise -/// Dhcp4Request <> Dhcp6Request -/// Dhcp4Ack <> DHcp6Reply -/// -typedef enum { - // - // <IP address, IP expressed URI> or - // <IP address, IP expressed URI, Name-server (will be ignored)> - // - HttpOfferTypeDhcpIpUri, - // - // <IP address, Domain-name expressed URI, Name-server> - // - HttpOfferTypeDhcpNameUriDns, - // - // <IP address, Name-server> - // - HttpOfferTypeDhcpDns, - // - // <IP address> - // - HttpOfferTypeDhcpOnly, - // - // <Domain-name expressed URI> or - // <Domain-name expressed URI, Name-server (will be ignored)> - // - HttpOfferTypeProxyNameUri, - // - // <IP expressed URI> or - // <IP expressed URI, Name-server (will be ignored)> - // - HttpOfferTypeProxyIpUri, - // - // <IP address, Domain-name expressed URI> - // - HttpOfferTypeDhcpNameUri, - HttpOfferTypeMax -} HTTP_BOOT_OFFER_TYPE; - -#define HTTP_BOOT_DHCP_RETRIES 4 -#define HTTP_BOOT_OFFER_MAX_NUM 16 - -// The array index of the DHCP4 option tag interested -// -#define HTTP_BOOT_DHCP4_TAG_INDEX_BOOTFILE_LEN 0 -#define HTTP_BOOT_DHCP4_TAG_INDEX_OVERLOAD 1 -#define HTTP_BOOT_DHCP4_TAG_INDEX_MSG_TYPE 2 -#define HTTP_BOOT_DHCP4_TAG_INDEX_SERVER_ID 3 -#define HTTP_BOOT_DHCP4_TAG_INDEX_CLASS_ID 4 -#define HTTP_BOOT_DHCP4_TAG_INDEX_BOOTFILE 5 -#define HTTP_BOOT_DHCP4_TAG_INDEX_DNS_SERVER 6 -#define HTTP_BOOT_DHCP4_TAG_INDEX_MAX 7 - -#pragma pack(1) - -typedef struct { - UINT8 ParaList[135]; -} HTTP_BOOT_DHCP4_OPTION_PARA; - -typedef struct { - UINT16 Size; -} HTTP_BOOT_DHCP4_OPTION_MAX_MESG_SIZE; - -typedef struct { - UINT8 Type; - UINT8 MajorVer; - UINT8 MinorVer; -} HTTP_BOOT_DHCP4_OPTION_UNDI; - -typedef struct { - UINT8 Type; -} HTTP_BOOT_DHCP4_OPTION_MESG; - -typedef struct { - UINT16 Type; -} HTTP_BOOT_DHCP4_OPTION_ARCH; - -typedef struct { - UINT8 ClassIdentifier[11]; - UINT8 ArchitecturePrefix[5]; - UINT8 ArchitectureType[5]; - UINT8 Lit3[1]; - UINT8 InterfaceName[4]; - UINT8 Lit4[1]; - UINT8 UndiMajor[3]; - UINT8 UndiMinor[3]; -} HTTP_BOOT_DHCP4_OPTION_CLID; - -typedef struct { - UINT8 Type; - UINT8 Guid[16]; -} HTTP_BOOT_DHCP4_OPTION_UUID; - -typedef struct { - UINT16 Type; - UINT16 Layer; -} HTTP_BOOT_OPTION_BOOT_ITEM; - -#pragma pack() - -typedef union { - HTTP_BOOT_DHCP4_OPTION_PARA *Para; - HTTP_BOOT_DHCP4_OPTION_UNDI *Undi; - HTTP_BOOT_DHCP4_OPTION_ARCH *Arch; - HTTP_BOOT_DHCP4_OPTION_CLID *Clid; - HTTP_BOOT_DHCP4_OPTION_UUID *Uuid; - HTTP_BOOT_DHCP4_OPTION_MESG *Mesg; - HTTP_BOOT_DHCP4_OPTION_MAX_MESG_SIZE *MaxMesgSize; -} HTTP_BOOT_DHCP4_OPTION_ENTRY; - -#define GET_NEXT_DHCP_OPTION(Opt) \ - (EFI_DHCP4_PACKET_OPTION *) ((UINT8 *) (Opt) + \ - sizeof (EFI_DHCP4_PACKET_OPTION) + (Opt)->Length - 1) - -#define GET_OPTION_BUFFER_LEN(Pkt) \ - ((Pkt)->Length - sizeof (EFI_DHCP4_HEADER) - 4) - -#define DEFAULT_CLASS_ID_DATA "HTTPClient:Arch:xxxxx:UNDI:003000" -#define DEFAULT_UNDI_TYPE 1 -#define DEFAULT_UNDI_MAJOR 3 -#define DEFAULT_UNDI_MINOR 0 - -typedef struct { - UINT32 Reserved; -} HTTP_BOOT_VENDOR_OPTION; - -typedef union { - EFI_DHCP4_PACKET Offer; - EFI_DHCP4_PACKET Ack; - UINT8 Buffer[HTTP_BOOT_DHCP4_PACKET_MAX_SIZE]; -} HTTP_BOOT_DHCP4_PACKET; - -typedef struct { - // - // URI component - // - CHAR8 *Scheme; - CHAR8 *Authority; - CHAR8 *Path; - CHAR8 *Query; - CHAR8 *Fragment; /// TODO: may not required in HTTP URL - - CHAR8 *RegName; /// Point to somewhere in Authority - BOOLEAN AddrIsOk; - EFI_IP_ADDRESS Address; - UINT16 Port; -} HTTP_BOOT_URI_CONTENT; - -typedef struct { - HTTP_BOOT_DHCP4_PACKET Packet; - HTTP_BOOT_OFFER_TYPE OfferType; - VOID *UriParser; - EFI_DHCP4_PACKET_OPTION *OptList[HTTP_BOOT_DHCP4_TAG_INDEX_MAX]; -} HTTP_BOOT_DHCP4_PACKET_CACHE; - -/** - Start the D.O.R.A DHCPv4 process to acquire the IPv4 address and other Http boot information. - - @param[in] Private Pointer to HTTP_BOOT private data. - - @retval EFI_SUCCESS The D.O.R.A process successfully finished. - @retval Others Failed to finish the D.O.R.A process. - -**/ -EFI_STATUS -HttpBootDhcp4Dora ( - IN HTTP_BOOT_PRIVATE_DATA *Private - ); - -/** - This function will register the default DNS addresses to the network device. - - @param[in] Private The pointer to HTTP_BOOT_PRIVATE_DATA. - @param[in] DataLength Size of the buffer pointed to by DnsServerData in bytes. - @param[in] DnsServerData Point a list of DNS server address in an array - of EFI_IPv4_ADDRESS instances. - - @retval EFI_SUCCESS The DNS configuration has been configured successfully. - @retval Others Failed to configure the address. - -**/ -EFI_STATUS -HttpBootRegisterIp4Dns ( - IN HTTP_BOOT_PRIVATE_DATA *Private, - IN UINTN DataLength, - IN VOID *DnsServerData - ); - -#endif +/** @file
+ Functions declaration related with DHCPv4 for HTTP boot driver.
+
+Copyright (c) 2015, Intel Corporation. All rights reserved.<BR>
+This program and the accompanying materials are licensed and made available under
+the terms and conditions of the BSD License that accompanies this distribution.
+The full text of the license may be found at
+http://opensource.org/licenses/bsd-license.php.
+
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+**/
+
+#ifndef __EFI_UEFI_HTTP_BOOT_DHCP4_H__
+#define __EFI_UEFI_HTTP_BOOT_DHCP4_H__
+
+#define HTTP_BOOT_DHCP4_OPTION_MAX_NUM 16
+#define HTTP_BOOT_DHCP4_OPTION_MAX_SIZE 312
+#define HTTP_BOOT_DHCP4_PACKET_MAX_SIZE 1472
+
+#define HTTP_BOOT_DHCP4_OPCODE_REQUEST 1
+#define HTTP_BOOT_DHCP4_OPCODE_REPLY 2
+#define HTTP_BOOT_DHCP4_MSG_TYPE_REQUEST 3
+#define HTTP_BOOT_DHCP4_MAGIC 0x63538263 // network byte order
+
+//
+// Dhcp Options
+//
+#define HTTP_BOOT_DHCP4_TAG_PAD 0 // Pad Option
+#define HTTP_BOOT_DHCP4_TAG_EOP 255 // End Option
+#define HTTP_BOOT_DHCP4_TAG_NETMASK 1 // Subnet Mask
+#define HTTP_BOOT_DHCP4_TAG_TIME_OFFSET 2 // Time Offset from UTC
+#define HTTP_BOOT_DHCP4_TAG_ROUTER 3 // Router option,
+#define HTTP_BOOT_DHCP4_TAG_TIME_SERVER 4 // Time Server
+#define HTTP_BOOT_DHCP4_TAG_NAME_SERVER 5 // Name Server
+#define HTTP_BOOT_DHCP4_TAG_DNS_SERVER 6 // Domain Name Server
+#define HTTP_BOOT_DHCP4_TAG_HOSTNAME 12 // Host Name
+#define HTTP_BOOT_DHCP4_TAG_BOOTFILE_LEN 13 // Boot File Size
+#define HTTP_BOOT_DHCP4_TAG_DUMP 14 // Merit Dump File
+#define HTTP_BOOT_DHCP4_TAG_DOMAINNAME 15 // Domain Name
+#define HTTP_BOOT_DHCP4_TAG_ROOTPATH 17 // Root path
+#define HTTP_BOOT_DHCP4_TAG_EXTEND_PATH 18 // Extensions Path
+#define HTTP_BOOT_DHCP4_TAG_EMTU 22 // Maximum Datagram Reassembly Size
+#define HTTP_BOOT_DHCP4_TAG_TTL 23 // Default IP Time-to-live
+#define HTTP_BOOT_DHCP4_TAG_BROADCAST 28 // Broadcast Address
+#define HTTP_BOOT_DHCP4_TAG_NIS_DOMAIN 40 // Network Information Service Domain
+#define HTTP_BOOT_DHCP4_TAG_NIS_SERVER 41 // Network Information Servers
+#define HTTP_BOOT_DHCP4_TAG_NTP_SERVER 42 // Network Time Protocol Servers
+#define HTTP_BOOT_DHCP4_TAG_VENDOR 43 // Vendor Specific Information
+#define HTTP_BOOT_DHCP4_TAG_REQUEST_IP 50 // Requested IP Address
+#define HTTP_BOOT_DHCP4_TAG_LEASE 51 // IP Address Lease Time
+#define HTTP_BOOT_DHCP4_TAG_OVERLOAD 52 // Option Overload
+#define HTTP_BOOT_DHCP4_TAG_MSG_TYPE 53 // DHCP Message Type
+#define HTTP_BOOT_DHCP4_TAG_SERVER_ID 54 // Server Identifier
+#define HTTP_BOOT_DHCP4_TAG_PARA_LIST 55 // Parameter Request List
+#define HTTP_BOOT_DHCP4_TAG_MAXMSG 57 // Maximum DHCP Message Size
+#define HTTP_BOOT_DHCP4_TAG_T1 58 // Renewal (T1) Time Value
+#define HTTP_BOOT_DHCP4_TAG_T2 59 // Rebinding (T2) Time Value
+#define HTTP_BOOT_DHCP4_TAG_CLASS_ID 60 // Vendor class identifier
+#define HTTP_BOOT_DHCP4_TAG_CLIENT_ID 61 // Client-identifier
+#define HTTP_BOOT_DHCP4_TAG_TFTP 66 // TFTP server name
+#define HTTP_BOOT_DHCP4_TAG_BOOTFILE 67 // Bootfile name
+#define HTTP_BOOT_DHCP4_TAG_ARCH 93
+#define HTTP_BOOT_DHCP4_TAG_UNDI 94
+#define HTTP_BOOT_DHCP4_TAG_UUID 97
+
+#define HTTP_BOOT_DHCP4_OVERLOAD_FILE 1
+#define HTTP_BOOT_DHCP4_OVERLOAD_SERVER_NAME 2
+
+///
+/// HTTP Tag definition that identifies the processor
+/// and programming environment of the client system.
+/// These identifiers are defined by IETF:
+/// http://www.ietf.org/assignments/dhcpv6-parameters/dhcpv6-parameters.xml
+///
+#if defined (MDE_CPU_IA32)
+#define EFI_HTTP_BOOT_CLIENT_SYSTEM_ARCHITECTURE 0x000F
+#elif defined (MDE_CPU_X64)
+#define EFI_HTTP_BOOT_CLIENT_SYSTEM_ARCHITECTURE 0x0010
+#elif defined (MDE_CPU_ARM)
+#define EFI_HTTP_BOOT_CLIENT_SYSTEM_ARCHITECTURE 0x0012
+#elif defined (MDE_CPU_AARCH64)
+#define EFI_HTTP_BOOT_CLIENT_SYSTEM_ARCHITECTURE 0x0013
+#elif defined (MDE_CPU_EBC)
+#define EFI_HTTP_BOOT_CLIENT_SYSTEM_ARCHITECTURE 0x0011
+#endif
+
+/// DHCP offer types among HTTP boot.
+/// Dhcp4 and Dhcp6 share this definition, and corresponding
+/// relatioinship is as follows:
+/// Dhcp4Discover <> Dhcp6Solicit
+/// Dhcp4Offer <> Dhcp6Advertise
+/// Dhcp4Request <> Dhcp6Request
+/// Dhcp4Ack <> DHcp6Reply
+///
+typedef enum {
+ //
+ // <IP address, IP expressed URI> or
+ // <IP address, IP expressed URI, Name-server (will be ignored)>
+ //
+ HttpOfferTypeDhcpIpUri,
+ //
+ // <IP address, Domain-name expressed URI, Name-server>
+ //
+ HttpOfferTypeDhcpNameUriDns,
+ //
+ // <IP address, Name-server>
+ //
+ HttpOfferTypeDhcpDns,
+ //
+ // <IP address>
+ //
+ HttpOfferTypeDhcpOnly,
+ //
+ // <Domain-name expressed URI> or
+ // <Domain-name expressed URI, Name-server (will be ignored)>
+ //
+ HttpOfferTypeProxyNameUri,
+ //
+ // <IP expressed URI> or
+ // <IP expressed URI, Name-server (will be ignored)>
+ //
+ HttpOfferTypeProxyIpUri,
+ //
+ // <IP address, Domain-name expressed URI>
+ //
+ HttpOfferTypeDhcpNameUri,
+ HttpOfferTypeMax
+} HTTP_BOOT_OFFER_TYPE;
+
+#define HTTP_BOOT_DHCP_RETRIES 4
+#define HTTP_BOOT_OFFER_MAX_NUM 16
+
+// The array index of the DHCP4 option tag interested
+//
+#define HTTP_BOOT_DHCP4_TAG_INDEX_BOOTFILE_LEN 0
+#define HTTP_BOOT_DHCP4_TAG_INDEX_OVERLOAD 1
+#define HTTP_BOOT_DHCP4_TAG_INDEX_MSG_TYPE 2
+#define HTTP_BOOT_DHCP4_TAG_INDEX_SERVER_ID 3
+#define HTTP_BOOT_DHCP4_TAG_INDEX_CLASS_ID 4
+#define HTTP_BOOT_DHCP4_TAG_INDEX_BOOTFILE 5
+#define HTTP_BOOT_DHCP4_TAG_INDEX_DNS_SERVER 6
+#define HTTP_BOOT_DHCP4_TAG_INDEX_MAX 7
+
+#pragma pack(1)
+
+typedef struct {
+ UINT8 ParaList[135];
+} HTTP_BOOT_DHCP4_OPTION_PARA;
+
+typedef struct {
+ UINT16 Size;
+} HTTP_BOOT_DHCP4_OPTION_MAX_MESG_SIZE;
+
+typedef struct {
+ UINT8 Type;
+ UINT8 MajorVer;
+ UINT8 MinorVer;
+} HTTP_BOOT_DHCP4_OPTION_UNDI;
+
+typedef struct {
+ UINT8 Type;
+} HTTP_BOOT_DHCP4_OPTION_MESG;
+
+typedef struct {
+ UINT16 Type;
+} HTTP_BOOT_DHCP4_OPTION_ARCH;
+
+typedef struct {
+ UINT8 ClassIdentifier[11];
+ UINT8 ArchitecturePrefix[5];
+ UINT8 ArchitectureType[5];
+ UINT8 Lit3[1];
+ UINT8 InterfaceName[4];
+ UINT8 Lit4[1];
+ UINT8 UndiMajor[3];
+ UINT8 UndiMinor[3];
+} HTTP_BOOT_DHCP4_OPTION_CLID;
+
+typedef struct {
+ UINT8 Type;
+ UINT8 Guid[16];
+} HTTP_BOOT_DHCP4_OPTION_UUID;
+
+typedef struct {
+ UINT16 Type;
+ UINT16 Layer;
+} HTTP_BOOT_OPTION_BOOT_ITEM;
+
+#pragma pack()
+
+typedef union {
+ HTTP_BOOT_DHCP4_OPTION_PARA *Para;
+ HTTP_BOOT_DHCP4_OPTION_UNDI *Undi;
+ HTTP_BOOT_DHCP4_OPTION_ARCH *Arch;
+ HTTP_BOOT_DHCP4_OPTION_CLID *Clid;
+ HTTP_BOOT_DHCP4_OPTION_UUID *Uuid;
+ HTTP_BOOT_DHCP4_OPTION_MESG *Mesg;
+ HTTP_BOOT_DHCP4_OPTION_MAX_MESG_SIZE *MaxMesgSize;
+} HTTP_BOOT_DHCP4_OPTION_ENTRY;
+
+#define GET_NEXT_DHCP_OPTION(Opt) \
+ (EFI_DHCP4_PACKET_OPTION *) ((UINT8 *) (Opt) + \
+ sizeof (EFI_DHCP4_PACKET_OPTION) + (Opt)->Length - 1)
+
+#define GET_OPTION_BUFFER_LEN(Pkt) \
+ ((Pkt)->Length - sizeof (EFI_DHCP4_HEADER) - 4)
+
+#define DEFAULT_CLASS_ID_DATA "HTTPClient:Arch:xxxxx:UNDI:003000"
+#define DEFAULT_UNDI_TYPE 1
+#define DEFAULT_UNDI_MAJOR 3
+#define DEFAULT_UNDI_MINOR 0
+
+typedef struct {
+ UINT32 Reserved;
+} HTTP_BOOT_VENDOR_OPTION;
+
+typedef union {
+ EFI_DHCP4_PACKET Offer;
+ EFI_DHCP4_PACKET Ack;
+ UINT8 Buffer[HTTP_BOOT_DHCP4_PACKET_MAX_SIZE];
+} HTTP_BOOT_DHCP4_PACKET;
+
+typedef struct {
+ //
+ // URI component
+ //
+ CHAR8 *Scheme;
+ CHAR8 *Authority;
+ CHAR8 *Path;
+ CHAR8 *Query;
+ CHAR8 *Fragment; /// TODO: may not required in HTTP URL
+
+ CHAR8 *RegName; /// Point to somewhere in Authority
+ BOOLEAN AddrIsOk;
+ EFI_IP_ADDRESS Address;
+ UINT16 Port;
+} HTTP_BOOT_URI_CONTENT;
+
+typedef struct {
+ HTTP_BOOT_DHCP4_PACKET Packet;
+ HTTP_BOOT_OFFER_TYPE OfferType;
+ VOID *UriParser;
+ EFI_DHCP4_PACKET_OPTION *OptList[HTTP_BOOT_DHCP4_TAG_INDEX_MAX];
+} HTTP_BOOT_DHCP4_PACKET_CACHE;
+
+/**
+ Start the D.O.R.A DHCPv4 process to acquire the IPv4 address and other Http boot information.
+
+ @param[in] Private Pointer to HTTP_BOOT private data.
+
+ @retval EFI_SUCCESS The D.O.R.A process successfully finished.
+ @retval Others Failed to finish the D.O.R.A process.
+
+**/
+EFI_STATUS
+HttpBootDhcp4Dora (
+ IN HTTP_BOOT_PRIVATE_DATA *Private
+ );
+
+/**
+ This function will register the default DNS addresses to the network device.
+
+ @param[in] Private The pointer to HTTP_BOOT_PRIVATE_DATA.
+ @param[in] DataLength Size of the buffer pointed to by DnsServerData in bytes.
+ @param[in] DnsServerData Point a list of DNS server address in an array
+ of EFI_IPv4_ADDRESS instances.
+
+ @retval EFI_SUCCESS The DNS configuration has been configured successfully.
+ @retval Others Failed to configure the address.
+
+**/
+EFI_STATUS
+HttpBootRegisterIp4Dns (
+ IN HTTP_BOOT_PRIVATE_DATA *Private,
+ IN UINTN DataLength,
+ IN VOID *DnsServerData
+ );
+
+#endif
diff --git a/NetworkPkg/HttpBootDxe/HttpBootDxe.c b/NetworkPkg/HttpBootDxe/HttpBootDxe.c index 0d2c7abd30..49be59b8c8 100644 --- a/NetworkPkg/HttpBootDxe/HttpBootDxe.c +++ b/NetworkPkg/HttpBootDxe/HttpBootDxe.c @@ -1,559 +1,559 @@ -/** @file - Driver Binding functions implementation for UEFI HTTP boot. - -Copyright (c) 2015, Intel Corporation. All rights reserved.<BR> -This program and the accompanying materials are licensed and made available under -the terms and conditions of the BSD License that accompanies this distribution. -The full text of the license may be found at -http://opensource.org/licenses/bsd-license.php. - -THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, -WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. - -**/ - -#include "HttpBootDxe.h" - -/// -/// Driver Binding Protocol instance -/// -EFI_DRIVER_BINDING_PROTOCOL gHttpBootIp4DxeDriverBinding = { - HttpBootIp4DxeDriverBindingSupported, - HttpBootIp4DxeDriverBindingStart, - HttpBootIp4DxeDriverBindingStop, - HTTP_BOOT_DXE_VERSION, - NULL, - NULL -}; - -/** - Destroy the HTTP child based on IPv4 stack. - - @param[in] This Pointer to the EFI_DRIVER_BINDING_PROTOCOL. - @param[in] Private Pointer to HTTP_BOOT_PRIVATE_DATA. - -**/ -VOID -HttpBootDestroyIp4Children ( - IN EFI_DRIVER_BINDING_PROTOCOL *This, - IN HTTP_BOOT_PRIVATE_DATA *Private - ) -{ - ASSERT (This != NULL); - ASSERT (Private != NULL); - ASSERT (Private->UsingIpv6 == FALSE); - - if (Private->Dhcp4Child != NULL) { - gBS->CloseProtocol ( - Private->Dhcp4Child, - &gEfiDhcp4ProtocolGuid, - This->DriverBindingHandle, - Private->Controller - ); - - NetLibDestroyServiceChild ( - Private->Controller, - This->DriverBindingHandle, - &gEfiDhcp4ServiceBindingProtocolGuid, - Private->Dhcp4Child - ); - } - - if (Private->HttpCreated) { - HttpIoDestroyIo (&Private->HttpIo); - Private->HttpCreated = FALSE; - } - - gBS->CloseProtocol ( - Private->Controller, - &gEfiCallerIdGuid, - This->DriverBindingHandle, - Private->ChildHandle - ); - - gBS->UninstallMultipleProtocolInterfaces ( - Private->ChildHandle, - &gEfiLoadFileProtocolGuid, - &Private->LoadFile, - &gEfiDevicePathProtocolGuid, - Private->DevicePath, - NULL - ); - - if (Private->DevicePath != NULL) { - FreePool (Private->DevicePath); - Private->DevicePath = NULL; - } -} - -/** - Tests to see if this driver supports a given controller. If a child device is provided, - it further tests to see if this driver supports creating a handle for the specified child device. - - This function checks to see if the driver specified by This supports the device specified by - ControllerHandle. Drivers will typically use the device path attached to - ControllerHandle and/or the services from the bus I/O abstraction attached to - ControllerHandle to determine if the driver supports ControllerHandle. This function - may be called many times during platform initialization. In order to reduce boot times, the tests - performed by this function must be very small, and take as little time as possible to execute. This - function must not change the state of any hardware devices, and this function must be aware that the - device specified by ControllerHandle may already be managed by the same driver or a - different driver. This function must match its calls to AllocatePages() with FreePages(), - AllocatePool() with FreePool(), and OpenProtocol() with CloseProtocol(). - Because ControllerHandle may have been previously started by the same driver, if a protocol is - already in the opened state, then it must not be closed with CloseProtocol(). This is required - to guarantee the state of ControllerHandle is not modified by this function. - - @param[in] This A pointer to the EFI_DRIVER_BINDING_PROTOCOL instance. - @param[in] ControllerHandle The handle of the controller to test. This handle - must support a protocol interface that supplies - an I/O abstraction to the driver. - @param[in] RemainingDevicePath A pointer to the remaining portion of a device path. This - parameter is ignored by device drivers, and is optional for bus - drivers. For bus drivers, if this parameter is not NULL, then - the bus driver must determine if the bus controller specified - by ControllerHandle and the child controller specified - by RemainingDevicePath are both supported by this - bus driver. - - @retval EFI_SUCCESS The device specified by ControllerHandle and - RemainingDevicePath is supported by the driver specified by This. - @retval EFI_ALREADY_STARTED The device specified by ControllerHandle and - RemainingDevicePath is already being managed by the driver - specified by This. - @retval EFI_ACCESS_DENIED The device specified by ControllerHandle and - RemainingDevicePath is already being managed by a different - driver or an application that requires exclusive access. - Currently not implemented. - @retval EFI_UNSUPPORTED The device specified by ControllerHandle and - RemainingDevicePath is not supported by the driver specified by This. -**/ -EFI_STATUS -EFIAPI -HttpBootIp4DxeDriverBindingSupported ( - IN EFI_DRIVER_BINDING_PROTOCOL *This, - IN EFI_HANDLE ControllerHandle, - IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath OPTIONAL - ) -{ - EFI_STATUS Status; - - // - // Try to open the DHCP4, HTTP4 and Device Path protocol. - // - Status = gBS->OpenProtocol ( - ControllerHandle, - &gEfiDhcp4ServiceBindingProtocolGuid, - NULL, - This->DriverBindingHandle, - ControllerHandle, - EFI_OPEN_PROTOCOL_TEST_PROTOCOL - ); - if (EFI_ERROR (Status)) { - return Status; - } - - Status = gBS->OpenProtocol ( - ControllerHandle, - &gEfiHttpServiceBindingProtocolGuid, - NULL, - This->DriverBindingHandle, - ControllerHandle, - EFI_OPEN_PROTOCOL_TEST_PROTOCOL - ); - if (EFI_ERROR (Status)) { - return Status; - } - - Status = gBS->OpenProtocol ( - ControllerHandle, - &gEfiDevicePathProtocolGuid, - NULL, - This->DriverBindingHandle, - ControllerHandle, - EFI_OPEN_PROTOCOL_TEST_PROTOCOL - ); - - return Status; -} - - -/** - Starts a device controller or a bus controller. - - The Start() function is designed to be invoked from the EFI boot service ConnectController(). - As a result, much of the error checking on the parameters to Start() has been moved into this - common boot service. It is legal to call Start() from other locations, - but the following calling restrictions must be followed, or the system behavior will not be deterministic. - 1. ControllerHandle must be a valid EFI_HANDLE. - 2. If RemainingDevicePath is not NULL, then it must be a pointer to a naturally aligned - EFI_DEVICE_PATH_PROTOCOL. - 3. Prior to calling Start(), the Supported() function for the driver specified by This must - have been called with the same calling parameters, and Supported() must have returned EFI_SUCCESS. - - @param[in] This A pointer to the EFI_DRIVER_BINDING_PROTOCOL instance. - @param[in] ControllerHandle The handle of the controller to start. This handle - must support a protocol interface that supplies - an I/O abstraction to the driver. - @param[in] RemainingDevicePath A pointer to the remaining portion of a device path. This - parameter is ignored by device drivers, and is optional for bus - drivers. For a bus driver, if this parameter is NULL, then handles - for all the children of Controller are created by this driver. - If this parameter is not NULL and the first Device Path Node is - not the End of Device Path Node, then only the handle for the - child device specified by the first Device Path Node of - RemainingDevicePath is created by this driver. - If the first Device Path Node of RemainingDevicePath is - the End of Device Path Node, no child handle is created by this - driver. - - @retval EFI_SUCCESS The device was started. - @retval EFI_DEVICE_ERROR The device could not be started due to a device error.Currently not implemented. - @retval EFI_OUT_OF_RESOURCES The request could not be completed due to a lack of resources. - @retval Others The driver failded to start the device. - -**/ -EFI_STATUS -EFIAPI -HttpBootIp4DxeDriverBindingStart ( - IN EFI_DRIVER_BINDING_PROTOCOL *This, - IN EFI_HANDLE ControllerHandle, - IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath OPTIONAL - ) -{ - EFI_STATUS Status; - HTTP_BOOT_PRIVATE_DATA *Private; - EFI_DEV_PATH *Node; - EFI_DEVICE_PATH_PROTOCOL *DevicePath; - UINT32 *Id; - - Status = gBS->OpenProtocol ( - ControllerHandle, - &gEfiCallerIdGuid, - (VOID **) &Id, - This->DriverBindingHandle, - ControllerHandle, - EFI_OPEN_PROTOCOL_GET_PROTOCOL - ); - if (!EFI_ERROR (Status)) { - return EFI_ALREADY_STARTED; - } - - // - // Initialize the private data structure. - // - Private = AllocateZeroPool (sizeof (HTTP_BOOT_PRIVATE_DATA)); - if (Private == NULL) { - return EFI_OUT_OF_RESOURCES; - } - Private->Signature = HTTP_BOOT_PRIVATE_DATA_SIGNATURE; - Private->Controller = ControllerHandle; - Private->Image = This->ImageHandle; - Private->UsingIpv6 = FALSE; - InitializeListHead (&Private->CacheList); - - // - // Create DHCP child instance. - // - Status = NetLibCreateServiceChild ( - ControllerHandle, - This->DriverBindingHandle, - &gEfiDhcp4ServiceBindingProtocolGuid, - &Private->Dhcp4Child - ); - if (EFI_ERROR (Status)) { - goto ON_ERROR; - } - - Status = gBS->OpenProtocol ( - Private->Dhcp4Child, - &gEfiDhcp4ProtocolGuid, - (VOID **) &Private->Dhcp4, - This->DriverBindingHandle, - ControllerHandle, - EFI_OPEN_PROTOCOL_BY_DRIVER - ); - if (EFI_ERROR (Status)) { - goto ON_ERROR; - } - - // - // Get the Ip4Config2 protocol, it's required to configure the default gateway address. - // - Status = gBS->OpenProtocol ( - ControllerHandle, - &gEfiIp4Config2ProtocolGuid, - (VOID **) &Private->Ip4Config2, - This->DriverBindingHandle, - ControllerHandle, - EFI_OPEN_PROTOCOL_GET_PROTOCOL - ); - if (EFI_ERROR (Status)) { - goto ON_ERROR; - } - - // - // Get the NII interface if it exists, it's not required. - // - Status = gBS->OpenProtocol ( - ControllerHandle, - &gEfiNetworkInterfaceIdentifierProtocolGuid_31, - (VOID **) &Private->Nii, - This->DriverBindingHandle, - ControllerHandle, - EFI_OPEN_PROTOCOL_GET_PROTOCOL - ); - if (EFI_ERROR (Status)) { - Private->Nii = NULL; - } - - // - // Open Device Path Protocol to prepare for appending IP and URI node. - // - Status = gBS->OpenProtocol ( - ControllerHandle, - &gEfiDevicePathProtocolGuid, - (VOID **) &Private->ParentDevicePath, - This->DriverBindingHandle, - ControllerHandle, - EFI_OPEN_PROTOCOL_GET_PROTOCOL - ); - if (EFI_ERROR (Status)) { - goto ON_ERROR; - } - - // - // Append IPv4 device path node. - // - Node = AllocateZeroPool (sizeof (IPv4_DEVICE_PATH)); - if (Node == NULL) { - Status = EFI_OUT_OF_RESOURCES; - goto ON_ERROR; - } - Node->Ipv4.Header.Type = MESSAGING_DEVICE_PATH; - Node->Ipv4.Header.SubType = MSG_IPv4_DP; - SetDevicePathNodeLength (Node, sizeof (IPv4_DEVICE_PATH)); - Node->Ipv4.StaticIpAddress = FALSE; - DevicePath = AppendDevicePathNode (Private->ParentDevicePath, (EFI_DEVICE_PATH_PROTOCOL*) Node); - FreePool (Node); - if (DevicePath == NULL) { - Status = EFI_OUT_OF_RESOURCES; - goto ON_ERROR; - } - - // - // Append URI device path node. - // - Node = AllocateZeroPool (sizeof (EFI_DEVICE_PATH_PROTOCOL)); - if (Node == NULL) { - Status = EFI_OUT_OF_RESOURCES; - goto ON_ERROR; - } - Node->DevPath.Type = MESSAGING_DEVICE_PATH; - Node->DevPath.SubType = MSG_URI_DP; - SetDevicePathNodeLength (Node, sizeof (EFI_DEVICE_PATH_PROTOCOL)); - Private->DevicePath = AppendDevicePathNode (DevicePath, (EFI_DEVICE_PATH_PROTOCOL*) Node); - FreePool (Node); - FreePool (DevicePath); - if (Private->DevicePath == NULL) { - Status = EFI_OUT_OF_RESOURCES; - goto ON_ERROR; - } - - // - // Create a child handle for the HTTP boot and install DevPath and Load file protocol on it. - // - CopyMem (&Private->LoadFile, &gHttpBootDxeLoadFile, sizeof (Private->LoadFile)); - Status = gBS->InstallMultipleProtocolInterfaces ( - &Private->ChildHandle, - &gEfiLoadFileProtocolGuid, - &Private->LoadFile, - &gEfiDevicePathProtocolGuid, - Private->DevicePath, - NULL - ); - if (EFI_ERROR (Status)) { - goto ON_ERROR; - } - - // - // Install a protocol with Caller Id Guid to the NIC, this is just to build the relationship between - // NIC handle and the private data. - // - Status = gBS->InstallProtocolInterface ( - &ControllerHandle, - &gEfiCallerIdGuid, - EFI_NATIVE_INTERFACE, - &Private->Id - ); - if (EFI_ERROR (Status)) { - goto ON_ERROR; - } - - // - // Open the Caller Id child to setup a parent-child relationship between - // real NIC handle and the HTTP boot child handle. - // - Status = gBS->OpenProtocol ( - ControllerHandle, - &gEfiCallerIdGuid, - (VOID **) &Id, - This->DriverBindingHandle, - Private->ChildHandle, - EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER - ); - if (EFI_ERROR (Status)) { - goto ON_ERROR; - } - - return EFI_SUCCESS; - -ON_ERROR: - - HttpBootDestroyIp4Children (This, Private); - FreePool (Private); - - return Status; -} - -/** - Stops a device controller or a bus controller. - - The Stop() function is designed to be invoked from the EFI boot service DisconnectController(). - As a result, much of the error checking on the parameters to Stop() has been moved - into this common boot service. It is legal to call Stop() from other locations, - but the following calling restrictions must be followed, or the system behavior will not be deterministic. - 1. ControllerHandle must be a valid EFI_HANDLE that was used on a previous call to this - same driver's Start() function. - 2. The first NumberOfChildren handles of ChildHandleBuffer must all be a valid - EFI_HANDLE. In addition, all of these handles must have been created in this driver's - Start() function, and the Start() function must have called OpenProtocol() on - ControllerHandle with an Attribute of EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER. - - @param[in] This A pointer to the EFI_DRIVER_BINDING_PROTOCOL instance. - @param[in] ControllerHandle A handle to the device being stopped. The handle must - support a bus specific I/O protocol for the driver - to use to stop the device. - @param[in] NumberOfChildren The number of child device handles in ChildHandleBuffer. - @param[in] ChildHandleBuffer An array of child handles to be freed. May be NULL - if NumberOfChildren is 0. - - @retval EFI_SUCCESS The device was stopped. - @retval EFI_DEVICE_ERROR The device could not be stopped due to a device error. - -**/ -EFI_STATUS -EFIAPI -HttpBootIp4DxeDriverBindingStop ( - IN EFI_DRIVER_BINDING_PROTOCOL *This, - IN EFI_HANDLE ControllerHandle, - IN UINTN NumberOfChildren, - IN EFI_HANDLE *ChildHandleBuffer OPTIONAL - ) -{ - EFI_STATUS Status; - EFI_LOAD_FILE_PROTOCOL *LoadFile; - HTTP_BOOT_PRIVATE_DATA *Private; - EFI_HANDLE NicHandle; - UINT32 *Id; - - // - // Try to get the Load File Protocol from the controller handle. - // - Status = gBS->OpenProtocol ( - ControllerHandle, - &gEfiLoadFileProtocolGuid, - (VOID **) &LoadFile, - This->DriverBindingHandle, - ControllerHandle, - EFI_OPEN_PROTOCOL_GET_PROTOCOL - ); - if (EFI_ERROR (Status)) { - // - // If failed, try to find the NIC handle for this controller. - // - NicHandle = HttpBootGetNicByIp4Children (ControllerHandle); - if (NicHandle == NULL) { - return EFI_SUCCESS; - } - - // - // Try to retrieve the private data by the Caller Id Guid. - // - Status = gBS->OpenProtocol ( - NicHandle, - &gEfiCallerIdGuid, - (VOID **) &Id, - This->DriverBindingHandle, - ControllerHandle, - EFI_OPEN_PROTOCOL_GET_PROTOCOL - ); - if (EFI_ERROR (Status)) { - return Status; - } - Private = HTTP_BOOT_PRIVATE_DATA_FROM_ID (Id); - } else { - Private = HTTP_BOOT_PRIVATE_DATA_FROM_LOADFILE (LoadFile); - NicHandle = Private->Controller; - } - - // - // Disable the HTTP boot function. - // - Status = HttpBootStop (Private); - if (Status != EFI_SUCCESS && Status != EFI_NOT_STARTED) { - return Status; - } - - // - // Destory all child instance and uninstall protocol interface. - // - HttpBootDestroyIp4Children (This, Private); - - // - // Release the cached data. - // - HttpBootFreeCacheList (Private); - - gBS->UninstallProtocolInterface ( - NicHandle, - &gEfiCallerIdGuid, - &Private->Id - ); - FreePool (Private); - - return EFI_SUCCESS; -} - -/** - This is the declaration of an EFI image entry point. This entry point is - the same for UEFI Applications, UEFI OS Loaders, and UEFI Drivers including - both device drivers and bus drivers. - - @param[in] ImageHandle The firmware allocated handle for the UEFI image. - @param[in] SystemTable A pointer to the EFI System Table. - - @retval EFI_SUCCESS The operation completed successfully. - @retval Others An unexpected error occurred. - -**/ -EFI_STATUS -EFIAPI -HttpBootDxeDriverEntryPoint ( - IN EFI_HANDLE ImageHandle, - IN EFI_SYSTEM_TABLE *SystemTable - ) -{ - // - // Install UEFI Driver Model protocol(s). - // - return EfiLibInstallDriverBindingComponentName2 ( - ImageHandle, - SystemTable, - &gHttpBootIp4DxeDriverBinding, - ImageHandle, - &gHttpBootDxeComponentName, - &gHttpBootDxeComponentName2 - ); -} - +/** @file
+ Driver Binding functions implementation for UEFI HTTP boot.
+
+Copyright (c) 2015, Intel Corporation. All rights reserved.<BR>
+This program and the accompanying materials are licensed and made available under
+the terms and conditions of the BSD License that accompanies this distribution.
+The full text of the license may be found at
+http://opensource.org/licenses/bsd-license.php.
+
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+**/
+
+#include "HttpBootDxe.h"
+
+///
+/// Driver Binding Protocol instance
+///
+EFI_DRIVER_BINDING_PROTOCOL gHttpBootIp4DxeDriverBinding = {
+ HttpBootIp4DxeDriverBindingSupported,
+ HttpBootIp4DxeDriverBindingStart,
+ HttpBootIp4DxeDriverBindingStop,
+ HTTP_BOOT_DXE_VERSION,
+ NULL,
+ NULL
+};
+
+/**
+ Destroy the HTTP child based on IPv4 stack.
+
+ @param[in] This Pointer to the EFI_DRIVER_BINDING_PROTOCOL.
+ @param[in] Private Pointer to HTTP_BOOT_PRIVATE_DATA.
+
+**/
+VOID
+HttpBootDestroyIp4Children (
+ IN EFI_DRIVER_BINDING_PROTOCOL *This,
+ IN HTTP_BOOT_PRIVATE_DATA *Private
+ )
+{
+ ASSERT (This != NULL);
+ ASSERT (Private != NULL);
+ ASSERT (Private->UsingIpv6 == FALSE);
+
+ if (Private->Dhcp4Child != NULL) {
+ gBS->CloseProtocol (
+ Private->Dhcp4Child,
+ &gEfiDhcp4ProtocolGuid,
+ This->DriverBindingHandle,
+ Private->Controller
+ );
+
+ NetLibDestroyServiceChild (
+ Private->Controller,
+ This->DriverBindingHandle,
+ &gEfiDhcp4ServiceBindingProtocolGuid,
+ Private->Dhcp4Child
+ );
+ }
+
+ if (Private->HttpCreated) {
+ HttpIoDestroyIo (&Private->HttpIo);
+ Private->HttpCreated = FALSE;
+ }
+
+ gBS->CloseProtocol (
+ Private->Controller,
+ &gEfiCallerIdGuid,
+ This->DriverBindingHandle,
+ Private->ChildHandle
+ );
+
+ gBS->UninstallMultipleProtocolInterfaces (
+ Private->ChildHandle,
+ &gEfiLoadFileProtocolGuid,
+ &Private->LoadFile,
+ &gEfiDevicePathProtocolGuid,
+ Private->DevicePath,
+ NULL
+ );
+
+ if (Private->DevicePath != NULL) {
+ FreePool (Private->DevicePath);
+ Private->DevicePath = NULL;
+ }
+}
+
+/**
+ Tests to see if this driver supports a given controller. If a child device is provided,
+ it further tests to see if this driver supports creating a handle for the specified child device.
+
+ This function checks to see if the driver specified by This supports the device specified by
+ ControllerHandle. Drivers will typically use the device path attached to
+ ControllerHandle and/or the services from the bus I/O abstraction attached to
+ ControllerHandle to determine if the driver supports ControllerHandle. This function
+ may be called many times during platform initialization. In order to reduce boot times, the tests
+ performed by this function must be very small, and take as little time as possible to execute. This
+ function must not change the state of any hardware devices, and this function must be aware that the
+ device specified by ControllerHandle may already be managed by the same driver or a
+ different driver. This function must match its calls to AllocatePages() with FreePages(),
+ AllocatePool() with FreePool(), and OpenProtocol() with CloseProtocol().
+ Because ControllerHandle may have been previously started by the same driver, if a protocol is
+ already in the opened state, then it must not be closed with CloseProtocol(). This is required
+ to guarantee the state of ControllerHandle is not modified by this function.
+
+ @param[in] This A pointer to the EFI_DRIVER_BINDING_PROTOCOL instance.
+ @param[in] ControllerHandle The handle of the controller to test. This handle
+ must support a protocol interface that supplies
+ an I/O abstraction to the driver.
+ @param[in] RemainingDevicePath A pointer to the remaining portion of a device path. This
+ parameter is ignored by device drivers, and is optional for bus
+ drivers. For bus drivers, if this parameter is not NULL, then
+ the bus driver must determine if the bus controller specified
+ by ControllerHandle and the child controller specified
+ by RemainingDevicePath are both supported by this
+ bus driver.
+
+ @retval EFI_SUCCESS The device specified by ControllerHandle and
+ RemainingDevicePath is supported by the driver specified by This.
+ @retval EFI_ALREADY_STARTED The device specified by ControllerHandle and
+ RemainingDevicePath is already being managed by the driver
+ specified by This.
+ @retval EFI_ACCESS_DENIED The device specified by ControllerHandle and
+ RemainingDevicePath is already being managed by a different
+ driver or an application that requires exclusive access.
+ Currently not implemented.
+ @retval EFI_UNSUPPORTED The device specified by ControllerHandle and
+ RemainingDevicePath is not supported by the driver specified by This.
+**/
+EFI_STATUS
+EFIAPI
+HttpBootIp4DxeDriverBindingSupported (
+ IN EFI_DRIVER_BINDING_PROTOCOL *This,
+ IN EFI_HANDLE ControllerHandle,
+ IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath OPTIONAL
+ )
+{
+ EFI_STATUS Status;
+
+ //
+ // Try to open the DHCP4, HTTP4 and Device Path protocol.
+ //
+ Status = gBS->OpenProtocol (
+ ControllerHandle,
+ &gEfiDhcp4ServiceBindingProtocolGuid,
+ NULL,
+ This->DriverBindingHandle,
+ ControllerHandle,
+ EFI_OPEN_PROTOCOL_TEST_PROTOCOL
+ );
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+
+ Status = gBS->OpenProtocol (
+ ControllerHandle,
+ &gEfiHttpServiceBindingProtocolGuid,
+ NULL,
+ This->DriverBindingHandle,
+ ControllerHandle,
+ EFI_OPEN_PROTOCOL_TEST_PROTOCOL
+ );
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+
+ Status = gBS->OpenProtocol (
+ ControllerHandle,
+ &gEfiDevicePathProtocolGuid,
+ NULL,
+ This->DriverBindingHandle,
+ ControllerHandle,
+ EFI_OPEN_PROTOCOL_TEST_PROTOCOL
+ );
+
+ return Status;
+}
+
+
+/**
+ Starts a device controller or a bus controller.
+
+ The Start() function is designed to be invoked from the EFI boot service ConnectController().
+ As a result, much of the error checking on the parameters to Start() has been moved into this
+ common boot service. It is legal to call Start() from other locations,
+ but the following calling restrictions must be followed, or the system behavior will not be deterministic.
+ 1. ControllerHandle must be a valid EFI_HANDLE.
+ 2. If RemainingDevicePath is not NULL, then it must be a pointer to a naturally aligned
+ EFI_DEVICE_PATH_PROTOCOL.
+ 3. Prior to calling Start(), the Supported() function for the driver specified by This must
+ have been called with the same calling parameters, and Supported() must have returned EFI_SUCCESS.
+
+ @param[in] This A pointer to the EFI_DRIVER_BINDING_PROTOCOL instance.
+ @param[in] ControllerHandle The handle of the controller to start. This handle
+ must support a protocol interface that supplies
+ an I/O abstraction to the driver.
+ @param[in] RemainingDevicePath A pointer to the remaining portion of a device path. This
+ parameter is ignored by device drivers, and is optional for bus
+ drivers. For a bus driver, if this parameter is NULL, then handles
+ for all the children of Controller are created by this driver.
+ If this parameter is not NULL and the first Device Path Node is
+ not the End of Device Path Node, then only the handle for the
+ child device specified by the first Device Path Node of
+ RemainingDevicePath is created by this driver.
+ If the first Device Path Node of RemainingDevicePath is
+ the End of Device Path Node, no child handle is created by this
+ driver.
+
+ @retval EFI_SUCCESS The device was started.
+ @retval EFI_DEVICE_ERROR The device could not be started due to a device error.Currently not implemented.
+ @retval EFI_OUT_OF_RESOURCES The request could not be completed due to a lack of resources.
+ @retval Others The driver failded to start the device.
+
+**/
+EFI_STATUS
+EFIAPI
+HttpBootIp4DxeDriverBindingStart (
+ IN EFI_DRIVER_BINDING_PROTOCOL *This,
+ IN EFI_HANDLE ControllerHandle,
+ IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath OPTIONAL
+ )
+{
+ EFI_STATUS Status;
+ HTTP_BOOT_PRIVATE_DATA *Private;
+ EFI_DEV_PATH *Node;
+ EFI_DEVICE_PATH_PROTOCOL *DevicePath;
+ UINT32 *Id;
+
+ Status = gBS->OpenProtocol (
+ ControllerHandle,
+ &gEfiCallerIdGuid,
+ (VOID **) &Id,
+ This->DriverBindingHandle,
+ ControllerHandle,
+ EFI_OPEN_PROTOCOL_GET_PROTOCOL
+ );
+ if (!EFI_ERROR (Status)) {
+ return EFI_ALREADY_STARTED;
+ }
+
+ //
+ // Initialize the private data structure.
+ //
+ Private = AllocateZeroPool (sizeof (HTTP_BOOT_PRIVATE_DATA));
+ if (Private == NULL) {
+ return EFI_OUT_OF_RESOURCES;
+ }
+ Private->Signature = HTTP_BOOT_PRIVATE_DATA_SIGNATURE;
+ Private->Controller = ControllerHandle;
+ Private->Image = This->ImageHandle;
+ Private->UsingIpv6 = FALSE;
+ InitializeListHead (&Private->CacheList);
+
+ //
+ // Create DHCP child instance.
+ //
+ Status = NetLibCreateServiceChild (
+ ControllerHandle,
+ This->DriverBindingHandle,
+ &gEfiDhcp4ServiceBindingProtocolGuid,
+ &Private->Dhcp4Child
+ );
+ if (EFI_ERROR (Status)) {
+ goto ON_ERROR;
+ }
+
+ Status = gBS->OpenProtocol (
+ Private->Dhcp4Child,
+ &gEfiDhcp4ProtocolGuid,
+ (VOID **) &Private->Dhcp4,
+ This->DriverBindingHandle,
+ ControllerHandle,
+ EFI_OPEN_PROTOCOL_BY_DRIVER
+ );
+ if (EFI_ERROR (Status)) {
+ goto ON_ERROR;
+ }
+
+ //
+ // Get the Ip4Config2 protocol, it's required to configure the default gateway address.
+ //
+ Status = gBS->OpenProtocol (
+ ControllerHandle,
+ &gEfiIp4Config2ProtocolGuid,
+ (VOID **) &Private->Ip4Config2,
+ This->DriverBindingHandle,
+ ControllerHandle,
+ EFI_OPEN_PROTOCOL_GET_PROTOCOL
+ );
+ if (EFI_ERROR (Status)) {
+ goto ON_ERROR;
+ }
+
+ //
+ // Get the NII interface if it exists, it's not required.
+ //
+ Status = gBS->OpenProtocol (
+ ControllerHandle,
+ &gEfiNetworkInterfaceIdentifierProtocolGuid_31,
+ (VOID **) &Private->Nii,
+ This->DriverBindingHandle,
+ ControllerHandle,
+ EFI_OPEN_PROTOCOL_GET_PROTOCOL
+ );
+ if (EFI_ERROR (Status)) {
+ Private->Nii = NULL;
+ }
+
+ //
+ // Open Device Path Protocol to prepare for appending IP and URI node.
+ //
+ Status = gBS->OpenProtocol (
+ ControllerHandle,
+ &gEfiDevicePathProtocolGuid,
+ (VOID **) &Private->ParentDevicePath,
+ This->DriverBindingHandle,
+ ControllerHandle,
+ EFI_OPEN_PROTOCOL_GET_PROTOCOL
+ );
+ if (EFI_ERROR (Status)) {
+ goto ON_ERROR;
+ }
+
+ //
+ // Append IPv4 device path node.
+ //
+ Node = AllocateZeroPool (sizeof (IPv4_DEVICE_PATH));
+ if (Node == NULL) {
+ Status = EFI_OUT_OF_RESOURCES;
+ goto ON_ERROR;
+ }
+ Node->Ipv4.Header.Type = MESSAGING_DEVICE_PATH;
+ Node->Ipv4.Header.SubType = MSG_IPv4_DP;
+ SetDevicePathNodeLength (Node, sizeof (IPv4_DEVICE_PATH));
+ Node->Ipv4.StaticIpAddress = FALSE;
+ DevicePath = AppendDevicePathNode (Private->ParentDevicePath, (EFI_DEVICE_PATH_PROTOCOL*) Node);
+ FreePool (Node);
+ if (DevicePath == NULL) {
+ Status = EFI_OUT_OF_RESOURCES;
+ goto ON_ERROR;
+ }
+
+ //
+ // Append URI device path node.
+ //
+ Node = AllocateZeroPool (sizeof (EFI_DEVICE_PATH_PROTOCOL));
+ if (Node == NULL) {
+ Status = EFI_OUT_OF_RESOURCES;
+ goto ON_ERROR;
+ }
+ Node->DevPath.Type = MESSAGING_DEVICE_PATH;
+ Node->DevPath.SubType = MSG_URI_DP;
+ SetDevicePathNodeLength (Node, sizeof (EFI_DEVICE_PATH_PROTOCOL));
+ Private->DevicePath = AppendDevicePathNode (DevicePath, (EFI_DEVICE_PATH_PROTOCOL*) Node);
+ FreePool (Node);
+ FreePool (DevicePath);
+ if (Private->DevicePath == NULL) {
+ Status = EFI_OUT_OF_RESOURCES;
+ goto ON_ERROR;
+ }
+
+ //
+ // Create a child handle for the HTTP boot and install DevPath and Load file protocol on it.
+ //
+ CopyMem (&Private->LoadFile, &gHttpBootDxeLoadFile, sizeof (Private->LoadFile));
+ Status = gBS->InstallMultipleProtocolInterfaces (
+ &Private->ChildHandle,
+ &gEfiLoadFileProtocolGuid,
+ &Private->LoadFile,
+ &gEfiDevicePathProtocolGuid,
+ Private->DevicePath,
+ NULL
+ );
+ if (EFI_ERROR (Status)) {
+ goto ON_ERROR;
+ }
+
+ //
+ // Install a protocol with Caller Id Guid to the NIC, this is just to build the relationship between
+ // NIC handle and the private data.
+ //
+ Status = gBS->InstallProtocolInterface (
+ &ControllerHandle,
+ &gEfiCallerIdGuid,
+ EFI_NATIVE_INTERFACE,
+ &Private->Id
+ );
+ if (EFI_ERROR (Status)) {
+ goto ON_ERROR;
+ }
+
+ //
+ // Open the Caller Id child to setup a parent-child relationship between
+ // real NIC handle and the HTTP boot child handle.
+ //
+ Status = gBS->OpenProtocol (
+ ControllerHandle,
+ &gEfiCallerIdGuid,
+ (VOID **) &Id,
+ This->DriverBindingHandle,
+ Private->ChildHandle,
+ EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER
+ );
+ if (EFI_ERROR (Status)) {
+ goto ON_ERROR;
+ }
+
+ return EFI_SUCCESS;
+
+ON_ERROR:
+
+ HttpBootDestroyIp4Children (This, Private);
+ FreePool (Private);
+
+ return Status;
+}
+
+/**
+ Stops a device controller or a bus controller.
+
+ The Stop() function is designed to be invoked from the EFI boot service DisconnectController().
+ As a result, much of the error checking on the parameters to Stop() has been moved
+ into this common boot service. It is legal to call Stop() from other locations,
+ but the following calling restrictions must be followed, or the system behavior will not be deterministic.
+ 1. ControllerHandle must be a valid EFI_HANDLE that was used on a previous call to this
+ same driver's Start() function.
+ 2. The first NumberOfChildren handles of ChildHandleBuffer must all be a valid
+ EFI_HANDLE. In addition, all of these handles must have been created in this driver's
+ Start() function, and the Start() function must have called OpenProtocol() on
+ ControllerHandle with an Attribute of EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER.
+
+ @param[in] This A pointer to the EFI_DRIVER_BINDING_PROTOCOL instance.
+ @param[in] ControllerHandle A handle to the device being stopped. The handle must
+ support a bus specific I/O protocol for the driver
+ to use to stop the device.
+ @param[in] NumberOfChildren The number of child device handles in ChildHandleBuffer.
+ @param[in] ChildHandleBuffer An array of child handles to be freed. May be NULL
+ if NumberOfChildren is 0.
+
+ @retval EFI_SUCCESS The device was stopped.
+ @retval EFI_DEVICE_ERROR The device could not be stopped due to a device error.
+
+**/
+EFI_STATUS
+EFIAPI
+HttpBootIp4DxeDriverBindingStop (
+ IN EFI_DRIVER_BINDING_PROTOCOL *This,
+ IN EFI_HANDLE ControllerHandle,
+ IN UINTN NumberOfChildren,
+ IN EFI_HANDLE *ChildHandleBuffer OPTIONAL
+ )
+{
+ EFI_STATUS Status;
+ EFI_LOAD_FILE_PROTOCOL *LoadFile;
+ HTTP_BOOT_PRIVATE_DATA *Private;
+ EFI_HANDLE NicHandle;
+ UINT32 *Id;
+
+ //
+ // Try to get the Load File Protocol from the controller handle.
+ //
+ Status = gBS->OpenProtocol (
+ ControllerHandle,
+ &gEfiLoadFileProtocolGuid,
+ (VOID **) &LoadFile,
+ This->DriverBindingHandle,
+ ControllerHandle,
+ EFI_OPEN_PROTOCOL_GET_PROTOCOL
+ );
+ if (EFI_ERROR (Status)) {
+ //
+ // If failed, try to find the NIC handle for this controller.
+ //
+ NicHandle = HttpBootGetNicByIp4Children (ControllerHandle);
+ if (NicHandle == NULL) {
+ return EFI_SUCCESS;
+ }
+
+ //
+ // Try to retrieve the private data by the Caller Id Guid.
+ //
+ Status = gBS->OpenProtocol (
+ NicHandle,
+ &gEfiCallerIdGuid,
+ (VOID **) &Id,
+ This->DriverBindingHandle,
+ ControllerHandle,
+ EFI_OPEN_PROTOCOL_GET_PROTOCOL
+ );
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+ Private = HTTP_BOOT_PRIVATE_DATA_FROM_ID (Id);
+ } else {
+ Private = HTTP_BOOT_PRIVATE_DATA_FROM_LOADFILE (LoadFile);
+ NicHandle = Private->Controller;
+ }
+
+ //
+ // Disable the HTTP boot function.
+ //
+ Status = HttpBootStop (Private);
+ if (Status != EFI_SUCCESS && Status != EFI_NOT_STARTED) {
+ return Status;
+ }
+
+ //
+ // Destory all child instance and uninstall protocol interface.
+ //
+ HttpBootDestroyIp4Children (This, Private);
+
+ //
+ // Release the cached data.
+ //
+ HttpBootFreeCacheList (Private);
+
+ gBS->UninstallProtocolInterface (
+ NicHandle,
+ &gEfiCallerIdGuid,
+ &Private->Id
+ );
+ FreePool (Private);
+
+ return EFI_SUCCESS;
+}
+
+/**
+ This is the declaration of an EFI image entry point. This entry point is
+ the same for UEFI Applications, UEFI OS Loaders, and UEFI Drivers including
+ both device drivers and bus drivers.
+
+ @param[in] ImageHandle The firmware allocated handle for the UEFI image.
+ @param[in] SystemTable A pointer to the EFI System Table.
+
+ @retval EFI_SUCCESS The operation completed successfully.
+ @retval Others An unexpected error occurred.
+
+**/
+EFI_STATUS
+EFIAPI
+HttpBootDxeDriverEntryPoint (
+ IN EFI_HANDLE ImageHandle,
+ IN EFI_SYSTEM_TABLE *SystemTable
+ )
+{
+ //
+ // Install UEFI Driver Model protocol(s).
+ //
+ return EfiLibInstallDriverBindingComponentName2 (
+ ImageHandle,
+ SystemTable,
+ &gHttpBootIp4DxeDriverBinding,
+ ImageHandle,
+ &gHttpBootDxeComponentName,
+ &gHttpBootDxeComponentName2
+ );
+}
+
diff --git a/NetworkPkg/HttpBootDxe/HttpBootDxe.h b/NetworkPkg/HttpBootDxe/HttpBootDxe.h index 8fce03df06..08415f6e0c 100644 --- a/NetworkPkg/HttpBootDxe/HttpBootDxe.h +++ b/NetworkPkg/HttpBootDxe/HttpBootDxe.h @@ -1,303 +1,303 @@ -/** @file - UEFI HTTP boot driver's private data structure and interfaces declaration. - -Copyright (c) 2015, Intel Corporation. All rights reserved.<BR> -This program and the accompanying materials are licensed and made available under -the terms and conditions of the BSD License that accompanies this distribution. -The full text of the license may be found at -http://opensource.org/licenses/bsd-license.php. - -THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, -WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. - -**/ - -#ifndef __EFI_HTTP_BOOT_DXE_H__ -#define __EFI_HTTP_BOOT_DXE_H__ - -#include <Uefi.h> - -// -// Libraries -// -#include <Library/UefiBootServicesTableLib.h> -#include <Library/MemoryAllocationLib.h> -#include <Library/BaseLib.h> -#include <Library/UefiLib.h> -#include <Library/DevicePathLib.h> -#include <Library/DebugLib.h> -#include <Library/NetLib.h> -#include <Library/HttpLib.h> - -// -// UEFI Driver Model Protocols -// -#include <Protocol/DriverBinding.h> -#include <Protocol/ComponentName2.h> -#include <Protocol/ComponentName.h> - -// -// Consumed Protocols -// -#include <Protocol/NetworkInterfaceIdentifier.h> -#include <Protocol/Dhcp4.h> -#include <Protocol/Http.h> -#include <Protocol/Ip4Config2.h> - -// -// Produced Protocols -// -#include <Protocol/LoadFile.h> - -// -// Driver Version -// -#define HTTP_BOOT_DXE_VERSION 0xa - -// -// Protocol instances -// -extern EFI_DRIVER_BINDING_PROTOCOL gHttpBootDxeDriverBinding; -extern EFI_COMPONENT_NAME2_PROTOCOL gHttpBootDxeComponentName2; -extern EFI_COMPONENT_NAME_PROTOCOL gHttpBootDxeComponentName; - -// -// Private data structure -// -typedef struct _HTTP_BOOT_PRIVATE_DATA HTTP_BOOT_PRIVATE_DATA; - -// -// Include files with internal function prototypes -// -#include "HttpBootComponentName.h" -#include "HttpBootDhcp4.h" -#include "HttpBootImpl.h" -#include "HttpBootSupport.h" -#include "HttpBootClient.h" - -typedef union { - HTTP_BOOT_DHCP4_PACKET_CACHE Dhcp4; -} HTTP_BOOT_DHCP_PACKET_CACHE; - -struct _HTTP_BOOT_PRIVATE_DATA { - UINT32 Signature; - EFI_HANDLE Controller; - EFI_HANDLE Image; - - // - // Cousumed children - // - EFI_HANDLE Dhcp4Child; - HTTP_IO HttpIo; - BOOLEAN HttpCreated; - - // - // Consumed protocol - // - EFI_NETWORK_INTERFACE_IDENTIFIER_PROTOCOL *Nii; - EFI_IP4_CONFIG2_PROTOCOL *Ip4Config2; - EFI_DHCP4_PROTOCOL *Dhcp4; - EFI_DEVICE_PATH_PROTOCOL *ParentDevicePath; - - // - // Produced children - // - EFI_HANDLE ChildHandle; - - // - // Produced protocol - // - EFI_LOAD_FILE_PROTOCOL LoadFile; - EFI_DEVICE_PATH_PROTOCOL *DevicePath; - UINT32 Id; - - // - // Mode data - // - BOOLEAN UsingIpv6; - BOOLEAN Started; - EFI_IP_ADDRESS StationIp; - EFI_IP_ADDRESS SubnetMask; - EFI_IP_ADDRESS GatewayIp; - UINT16 Port; - CHAR8 *BootFileUri; - VOID *BootFileUriParser; - UINTN BootFileSize; - - // - // Cached HTTP data - // - LIST_ENTRY CacheList; - - // - // Cached DHCP offer - // - // OfferIndex records the index of DhcpOffer[] buffer, and OfferCount records the num of each type of offer. - // - // It supposed that - // - // OfferNum: 8 - // OfferBuffer: [ProxyNameUri, DhcpNameUri, DhcpIpUri, ProxyNameUri, ProxyIpUri, DhcpOnly, DhcpIpUri, DhcpNameUriDns] - // (OfferBuffer is 0-based.) - // - // And assume that (DhcpIpUri is the first priority actually.) - // - // SelectIndex: 5 - // SelectProxyType: HttpOfferTypeProxyIpUri - // (SelectIndex is 1-based, and 0 means no one is selected.) - // - // So it should be - // - // DhcpIpUri DhcpNameUriDns DhcpDns DhcpOnly ProxyNameUri ProxyIpUri DhcpNameUri - // OfferCount: [ 2, 1, 0, 1, 2, 1, 1] - // - // OfferIndex: {[ 2, 7, 0, 5, 0, *4, 1] - // [ 6, 0, 0, 0, 3, 0, 0] - // [ 0, 0, 0, 0, 0, 0, 0] - // ... ]} - // (OfferIndex is 0-based.) - // - // - UINT32 SelectIndex; - UINT32 SelectProxyType; - HTTP_BOOT_DHCP_PACKET_CACHE OfferBuffer[HTTP_BOOT_OFFER_MAX_NUM]; - UINT32 OfferNum; - UINT32 OfferCount[HttpOfferTypeMax]; - UINT32 OfferIndex[HttpOfferTypeMax][HTTP_BOOT_OFFER_MAX_NUM]; -}; - -#define HTTP_BOOT_PRIVATE_DATA_SIGNATURE SIGNATURE_32 ('H', 'B', 'P', 'D') -#define HTTP_BOOT_PRIVATE_DATA_FROM_LOADFILE(a) CR (a, HTTP_BOOT_PRIVATE_DATA, LoadFile, HTTP_BOOT_PRIVATE_DATA_SIGNATURE) -#define HTTP_BOOT_PRIVATE_DATA_FROM_ID(a) CR (a, HTTP_BOOT_PRIVATE_DATA, Id, HTTP_BOOT_PRIVATE_DATA_SIGNATURE) - -extern EFI_LOAD_FILE_PROTOCOL gHttpBootDxeLoadFile; - -/** - Tests to see if this driver supports a given controller. If a child device is provided, - it further tests to see if this driver supports creating a handle for the specified child device. - - This function checks to see if the driver specified by This supports the device specified by - ControllerHandle. Drivers will typically use the device path attached to - ControllerHandle and/or the services from the bus I/O abstraction attached to - ControllerHandle to determine if the driver supports ControllerHandle. This function - may be called many times during platform initialization. In order to reduce boot times, the tests - performed by this function must be very small, and take as little time as possible to execute. This - function must not change the state of any hardware devices, and this function must be aware that the - device specified by ControllerHandle may already be managed by the same driver or a - different driver. This function must match its calls to AllocatePages() with FreePages(), - AllocatePool() with FreePool(), and OpenProtocol() with CloseProtocol(). - Because ControllerHandle may have been previously started by the same driver, if a protocol is - already in the opened state, then it must not be closed with CloseProtocol(). This is required - to guarantee the state of ControllerHandle is not modified by this function. - - @param[in] This A pointer to the EFI_DRIVER_BINDING_PROTOCOL instance. - @param[in] ControllerHandle The handle of the controller to test. This handle - must support a protocol interface that supplies - an I/O abstraction to the driver. - @param[in] RemainingDevicePath A pointer to the remaining portion of a device path. This - parameter is ignored by device drivers, and is optional for bus - drivers. For bus drivers, if this parameter is not NULL, then - the bus driver must determine if the bus controller specified - by ControllerHandle and the child controller specified - by RemainingDevicePath are both supported by this - bus driver. - - @retval EFI_SUCCESS The device specified by ControllerHandle and - RemainingDevicePath is supported by the driver specified by This. - @retval EFI_ALREADY_STARTED The device specified by ControllerHandle and - RemainingDevicePath is already being managed by the driver - specified by This. - @retval EFI_ACCESS_DENIED The device specified by ControllerHandle and - RemainingDevicePath is already being managed by a different - driver or an application that requires exclusive access. - Currently not implemented. - @retval EFI_UNSUPPORTED The device specified by ControllerHandle and - RemainingDevicePath is not supported by the driver specified by This. -**/ -EFI_STATUS -EFIAPI -HttpBootIp4DxeDriverBindingSupported ( - IN EFI_DRIVER_BINDING_PROTOCOL *This, - IN EFI_HANDLE ControllerHandle, - IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath OPTIONAL - ); - -/** - Starts a device controller or a bus controller. - - The Start() function is designed to be invoked from the EFI boot service ConnectController(). - As a result, much of the error checking on the parameters to Start() has been moved into this - common boot service. It is legal to call Start() from other locations, - but the following calling restrictions must be followed, or the system behavior will not be deterministic. - 1. ControllerHandle must be a valid EFI_HANDLE. - 2. If RemainingDevicePath is not NULL, then it must be a pointer to a naturally aligned - EFI_DEVICE_PATH_PROTOCOL. - 3. Prior to calling Start(), the Supported() function for the driver specified by This must - have been called with the same calling parameters, and Supported() must have returned EFI_SUCCESS. - - @param[in] This A pointer to the EFI_DRIVER_BINDING_PROTOCOL instance. - @param[in] ControllerHandle The handle of the controller to start. This handle - must support a protocol interface that supplies - an I/O abstraction to the driver. - @param[in] RemainingDevicePath A pointer to the remaining portion of a device path. This - parameter is ignored by device drivers, and is optional for bus - drivers. For a bus driver, if this parameter is NULL, then handles - for all the children of Controller are created by this driver. - If this parameter is not NULL and the first Device Path Node is - not the End of Device Path Node, then only the handle for the - child device specified by the first Device Path Node of - RemainingDevicePath is created by this driver. - If the first Device Path Node of RemainingDevicePath is - the End of Device Path Node, no child handle is created by this - driver. - - @retval EFI_SUCCESS The device was started. - @retval EFI_DEVICE_ERROR The device could not be started due to a device error.Currently not implemented. - @retval EFI_OUT_OF_RESOURCES The request could not be completed due to a lack of resources. - @retval Others The driver failded to start the device. - -**/ -EFI_STATUS -EFIAPI -HttpBootIp4DxeDriverBindingStart ( - IN EFI_DRIVER_BINDING_PROTOCOL *This, - IN EFI_HANDLE ControllerHandle, - IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath OPTIONAL - ); - -/** - Stops a device controller or a bus controller. - - The Stop() function is designed to be invoked from the EFI boot service DisconnectController(). - As a result, much of the error checking on the parameters to Stop() has been moved - into this common boot service. It is legal to call Stop() from other locations, - but the following calling restrictions must be followed, or the system behavior will not be deterministic. - 1. ControllerHandle must be a valid EFI_HANDLE that was used on a previous call to this - same driver's Start() function. - 2. The first NumberOfChildren handles of ChildHandleBuffer must all be a valid - EFI_HANDLE. In addition, all of these handles must have been created in this driver's - Start() function, and the Start() function must have called OpenProtocol() on - ControllerHandle with an Attribute of EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER. - - @param[in] This A pointer to the EFI_DRIVER_BINDING_PROTOCOL instance. - @param[in] ControllerHandle A handle to the device being stopped. The handle must - support a bus specific I/O protocol for the driver - to use to stop the device. - @param[in] NumberOfChildren The number of child device handles in ChildHandleBuffer. - @param[in] ChildHandleBuffer An array of child handles to be freed. May be NULL - if NumberOfChildren is 0. - - @retval EFI_SUCCESS The device was stopped. - @retval EFI_DEVICE_ERROR The device could not be stopped due to a device error. - -**/ -EFI_STATUS -EFIAPI -HttpBootIp4DxeDriverBindingStop ( - IN EFI_DRIVER_BINDING_PROTOCOL *This, - IN EFI_HANDLE ControllerHandle, - IN UINTN NumberOfChildren, - IN EFI_HANDLE *ChildHandleBuffer OPTIONAL - ); - -#endif +/** @file
+ UEFI HTTP boot driver's private data structure and interfaces declaration.
+
+Copyright (c) 2015, Intel Corporation. All rights reserved.<BR>
+This program and the accompanying materials are licensed and made available under
+the terms and conditions of the BSD License that accompanies this distribution.
+The full text of the license may be found at
+http://opensource.org/licenses/bsd-license.php.
+
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+**/
+
+#ifndef __EFI_HTTP_BOOT_DXE_H__
+#define __EFI_HTTP_BOOT_DXE_H__
+
+#include <Uefi.h>
+
+//
+// Libraries
+//
+#include <Library/UefiBootServicesTableLib.h>
+#include <Library/MemoryAllocationLib.h>
+#include <Library/BaseLib.h>
+#include <Library/UefiLib.h>
+#include <Library/DevicePathLib.h>
+#include <Library/DebugLib.h>
+#include <Library/NetLib.h>
+#include <Library/HttpLib.h>
+
+//
+// UEFI Driver Model Protocols
+//
+#include <Protocol/DriverBinding.h>
+#include <Protocol/ComponentName2.h>
+#include <Protocol/ComponentName.h>
+
+//
+// Consumed Protocols
+//
+#include <Protocol/NetworkInterfaceIdentifier.h>
+#include <Protocol/Dhcp4.h>
+#include <Protocol/Http.h>
+#include <Protocol/Ip4Config2.h>
+
+//
+// Produced Protocols
+//
+#include <Protocol/LoadFile.h>
+
+//
+// Driver Version
+//
+#define HTTP_BOOT_DXE_VERSION 0xa
+
+//
+// Protocol instances
+//
+extern EFI_DRIVER_BINDING_PROTOCOL gHttpBootDxeDriverBinding;
+extern EFI_COMPONENT_NAME2_PROTOCOL gHttpBootDxeComponentName2;
+extern EFI_COMPONENT_NAME_PROTOCOL gHttpBootDxeComponentName;
+
+//
+// Private data structure
+//
+typedef struct _HTTP_BOOT_PRIVATE_DATA HTTP_BOOT_PRIVATE_DATA;
+
+//
+// Include files with internal function prototypes
+//
+#include "HttpBootComponentName.h"
+#include "HttpBootDhcp4.h"
+#include "HttpBootImpl.h"
+#include "HttpBootSupport.h"
+#include "HttpBootClient.h"
+
+typedef union {
+ HTTP_BOOT_DHCP4_PACKET_CACHE Dhcp4;
+} HTTP_BOOT_DHCP_PACKET_CACHE;
+
+struct _HTTP_BOOT_PRIVATE_DATA {
+ UINT32 Signature;
+ EFI_HANDLE Controller;
+ EFI_HANDLE Image;
+
+ //
+ // Cousumed children
+ //
+ EFI_HANDLE Dhcp4Child;
+ HTTP_IO HttpIo;
+ BOOLEAN HttpCreated;
+
+ //
+ // Consumed protocol
+ //
+ EFI_NETWORK_INTERFACE_IDENTIFIER_PROTOCOL *Nii;
+ EFI_IP4_CONFIG2_PROTOCOL *Ip4Config2;
+ EFI_DHCP4_PROTOCOL *Dhcp4;
+ EFI_DEVICE_PATH_PROTOCOL *ParentDevicePath;
+
+ //
+ // Produced children
+ //
+ EFI_HANDLE ChildHandle;
+
+ //
+ // Produced protocol
+ //
+ EFI_LOAD_FILE_PROTOCOL LoadFile;
+ EFI_DEVICE_PATH_PROTOCOL *DevicePath;
+ UINT32 Id;
+
+ //
+ // Mode data
+ //
+ BOOLEAN UsingIpv6;
+ BOOLEAN Started;
+ EFI_IP_ADDRESS StationIp;
+ EFI_IP_ADDRESS SubnetMask;
+ EFI_IP_ADDRESS GatewayIp;
+ UINT16 Port;
+ CHAR8 *BootFileUri;
+ VOID *BootFileUriParser;
+ UINTN BootFileSize;
+
+ //
+ // Cached HTTP data
+ //
+ LIST_ENTRY CacheList;
+
+ //
+ // Cached DHCP offer
+ //
+ // OfferIndex records the index of DhcpOffer[] buffer, and OfferCount records the num of each type of offer.
+ //
+ // It supposed that
+ //
+ // OfferNum: 8
+ // OfferBuffer: [ProxyNameUri, DhcpNameUri, DhcpIpUri, ProxyNameUri, ProxyIpUri, DhcpOnly, DhcpIpUri, DhcpNameUriDns]
+ // (OfferBuffer is 0-based.)
+ //
+ // And assume that (DhcpIpUri is the first priority actually.)
+ //
+ // SelectIndex: 5
+ // SelectProxyType: HttpOfferTypeProxyIpUri
+ // (SelectIndex is 1-based, and 0 means no one is selected.)
+ //
+ // So it should be
+ //
+ // DhcpIpUri DhcpNameUriDns DhcpDns DhcpOnly ProxyNameUri ProxyIpUri DhcpNameUri
+ // OfferCount: [ 2, 1, 0, 1, 2, 1, 1]
+ //
+ // OfferIndex: {[ 2, 7, 0, 5, 0, *4, 1]
+ // [ 6, 0, 0, 0, 3, 0, 0]
+ // [ 0, 0, 0, 0, 0, 0, 0]
+ // ... ]}
+ // (OfferIndex is 0-based.)
+ //
+ //
+ UINT32 SelectIndex;
+ UINT32 SelectProxyType;
+ HTTP_BOOT_DHCP_PACKET_CACHE OfferBuffer[HTTP_BOOT_OFFER_MAX_NUM];
+ UINT32 OfferNum;
+ UINT32 OfferCount[HttpOfferTypeMax];
+ UINT32 OfferIndex[HttpOfferTypeMax][HTTP_BOOT_OFFER_MAX_NUM];
+};
+
+#define HTTP_BOOT_PRIVATE_DATA_SIGNATURE SIGNATURE_32 ('H', 'B', 'P', 'D')
+#define HTTP_BOOT_PRIVATE_DATA_FROM_LOADFILE(a) CR (a, HTTP_BOOT_PRIVATE_DATA, LoadFile, HTTP_BOOT_PRIVATE_DATA_SIGNATURE)
+#define HTTP_BOOT_PRIVATE_DATA_FROM_ID(a) CR (a, HTTP_BOOT_PRIVATE_DATA, Id, HTTP_BOOT_PRIVATE_DATA_SIGNATURE)
+
+extern EFI_LOAD_FILE_PROTOCOL gHttpBootDxeLoadFile;
+
+/**
+ Tests to see if this driver supports a given controller. If a child device is provided,
+ it further tests to see if this driver supports creating a handle for the specified child device.
+
+ This function checks to see if the driver specified by This supports the device specified by
+ ControllerHandle. Drivers will typically use the device path attached to
+ ControllerHandle and/or the services from the bus I/O abstraction attached to
+ ControllerHandle to determine if the driver supports ControllerHandle. This function
+ may be called many times during platform initialization. In order to reduce boot times, the tests
+ performed by this function must be very small, and take as little time as possible to execute. This
+ function must not change the state of any hardware devices, and this function must be aware that the
+ device specified by ControllerHandle may already be managed by the same driver or a
+ different driver. This function must match its calls to AllocatePages() with FreePages(),
+ AllocatePool() with FreePool(), and OpenProtocol() with CloseProtocol().
+ Because ControllerHandle may have been previously started by the same driver, if a protocol is
+ already in the opened state, then it must not be closed with CloseProtocol(). This is required
+ to guarantee the state of ControllerHandle is not modified by this function.
+
+ @param[in] This A pointer to the EFI_DRIVER_BINDING_PROTOCOL instance.
+ @param[in] ControllerHandle The handle of the controller to test. This handle
+ must support a protocol interface that supplies
+ an I/O abstraction to the driver.
+ @param[in] RemainingDevicePath A pointer to the remaining portion of a device path. This
+ parameter is ignored by device drivers, and is optional for bus
+ drivers. For bus drivers, if this parameter is not NULL, then
+ the bus driver must determine if the bus controller specified
+ by ControllerHandle and the child controller specified
+ by RemainingDevicePath are both supported by this
+ bus driver.
+
+ @retval EFI_SUCCESS The device specified by ControllerHandle and
+ RemainingDevicePath is supported by the driver specified by This.
+ @retval EFI_ALREADY_STARTED The device specified by ControllerHandle and
+ RemainingDevicePath is already being managed by the driver
+ specified by This.
+ @retval EFI_ACCESS_DENIED The device specified by ControllerHandle and
+ RemainingDevicePath is already being managed by a different
+ driver or an application that requires exclusive access.
+ Currently not implemented.
+ @retval EFI_UNSUPPORTED The device specified by ControllerHandle and
+ RemainingDevicePath is not supported by the driver specified by This.
+**/
+EFI_STATUS
+EFIAPI
+HttpBootIp4DxeDriverBindingSupported (
+ IN EFI_DRIVER_BINDING_PROTOCOL *This,
+ IN EFI_HANDLE ControllerHandle,
+ IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath OPTIONAL
+ );
+
+/**
+ Starts a device controller or a bus controller.
+
+ The Start() function is designed to be invoked from the EFI boot service ConnectController().
+ As a result, much of the error checking on the parameters to Start() has been moved into this
+ common boot service. It is legal to call Start() from other locations,
+ but the following calling restrictions must be followed, or the system behavior will not be deterministic.
+ 1. ControllerHandle must be a valid EFI_HANDLE.
+ 2. If RemainingDevicePath is not NULL, then it must be a pointer to a naturally aligned
+ EFI_DEVICE_PATH_PROTOCOL.
+ 3. Prior to calling Start(), the Supported() function for the driver specified by This must
+ have been called with the same calling parameters, and Supported() must have returned EFI_SUCCESS.
+
+ @param[in] This A pointer to the EFI_DRIVER_BINDING_PROTOCOL instance.
+ @param[in] ControllerHandle The handle of the controller to start. This handle
+ must support a protocol interface that supplies
+ an I/O abstraction to the driver.
+ @param[in] RemainingDevicePath A pointer to the remaining portion of a device path. This
+ parameter is ignored by device drivers, and is optional for bus
+ drivers. For a bus driver, if this parameter is NULL, then handles
+ for all the children of Controller are created by this driver.
+ If this parameter is not NULL and the first Device Path Node is
+ not the End of Device Path Node, then only the handle for the
+ child device specified by the first Device Path Node of
+ RemainingDevicePath is created by this driver.
+ If the first Device Path Node of RemainingDevicePath is
+ the End of Device Path Node, no child handle is created by this
+ driver.
+
+ @retval EFI_SUCCESS The device was started.
+ @retval EFI_DEVICE_ERROR The device could not be started due to a device error.Currently not implemented.
+ @retval EFI_OUT_OF_RESOURCES The request could not be completed due to a lack of resources.
+ @retval Others The driver failded to start the device.
+
+**/
+EFI_STATUS
+EFIAPI
+HttpBootIp4DxeDriverBindingStart (
+ IN EFI_DRIVER_BINDING_PROTOCOL *This,
+ IN EFI_HANDLE ControllerHandle,
+ IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath OPTIONAL
+ );
+
+/**
+ Stops a device controller or a bus controller.
+
+ The Stop() function is designed to be invoked from the EFI boot service DisconnectController().
+ As a result, much of the error checking on the parameters to Stop() has been moved
+ into this common boot service. It is legal to call Stop() from other locations,
+ but the following calling restrictions must be followed, or the system behavior will not be deterministic.
+ 1. ControllerHandle must be a valid EFI_HANDLE that was used on a previous call to this
+ same driver's Start() function.
+ 2. The first NumberOfChildren handles of ChildHandleBuffer must all be a valid
+ EFI_HANDLE. In addition, all of these handles must have been created in this driver's
+ Start() function, and the Start() function must have called OpenProtocol() on
+ ControllerHandle with an Attribute of EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER.
+
+ @param[in] This A pointer to the EFI_DRIVER_BINDING_PROTOCOL instance.
+ @param[in] ControllerHandle A handle to the device being stopped. The handle must
+ support a bus specific I/O protocol for the driver
+ to use to stop the device.
+ @param[in] NumberOfChildren The number of child device handles in ChildHandleBuffer.
+ @param[in] ChildHandleBuffer An array of child handles to be freed. May be NULL
+ if NumberOfChildren is 0.
+
+ @retval EFI_SUCCESS The device was stopped.
+ @retval EFI_DEVICE_ERROR The device could not be stopped due to a device error.
+
+**/
+EFI_STATUS
+EFIAPI
+HttpBootIp4DxeDriverBindingStop (
+ IN EFI_DRIVER_BINDING_PROTOCOL *This,
+ IN EFI_HANDLE ControllerHandle,
+ IN UINTN NumberOfChildren,
+ IN EFI_HANDLE *ChildHandleBuffer OPTIONAL
+ );
+
+#endif
diff --git a/NetworkPkg/HttpBootDxe/HttpBootDxe.inf b/NetworkPkg/HttpBootDxe/HttpBootDxe.inf index a60830400c..18f8f796f0 100644 --- a/NetworkPkg/HttpBootDxe/HttpBootDxe.inf +++ b/NetworkPkg/HttpBootDxe/HttpBootDxe.inf @@ -1,68 +1,68 @@ -## @file -# This modules produce the Load File Protocol for UEFI HTTP boot. -# -# Copyright (c) 2015, Intel Corporation. All rights reserved.<BR> -# This program and the accompanying materials -# are licensed and made available under the terms and conditions of the BSD License -# which accompanies this distribution. The full text of the license may be found at -# http://opensource.org/licenses/bsd-license.php -# -# THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, -# WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. -# -## - -[Defines] - INF_VERSION = 0x00010005 - BASE_NAME = HttpBootDxe - FILE_GUID = ecebcb00-d9c8-11e4-af3d-8cdcd426c973 - MODULE_TYPE = UEFI_DRIVER - VERSION_STRING = 1.0 - ENTRY_POINT = HttpBootDxeDriverEntryPoint - UNLOAD_IMAGE = NetLibDefaultUnload - MODULE_UNI_FILE = HttpBootDxe.uni - -[Packages] - MdePkg/MdePkg.dec - MdeModulePkg/MdeModulePkg.dec - -[Sources] - HttpBootDxe.h - HttpBootDxe.c - HttpBootComponentName.h - HttpBootComponentName.c - HttpBootImpl.h - HttpBootImpl.c - HttpBootDhcp4.h - HttpBootDhcp4.c - HttpBootSupport.h - HttpBootSupport.c - HttpBootClient.h - HttpBootClient.c - -[LibraryClasses] - UefiDriverEntryPoint - UefiBootServicesTableLib - MemoryAllocationLib - BaseLib - UefiLib - DevicePathLib - DebugLib - NetLib - HttpLib - -[Protocols] - ## TO_START - ## BY_START - gEfiDevicePathProtocolGuid - - gEfiLoadFileProtocolGuid ## BY_START - gEfiHttpServiceBindingProtocolGuid ## CONSUMES - gEfiHttpProtocolGuid ## CONSUMES - gEfiDhcp4ServiceBindingProtocolGuid ## TO_START - gEfiDhcp4ProtocolGuid ## TO_START - gEfiIp4Config2ProtocolGuid ## TO_START - gEfiNetworkInterfaceIdentifierProtocolGuid_31 ## SOMETIMES_CONSUMES - -[UserExtensions.TianoCore."ExtraFiles"] - HttpBootDxeExtra.uni +## @file
+# This modules produce the Load File Protocol for UEFI HTTP boot.
+#
+# Copyright (c) 2015, Intel Corporation. All rights reserved.<BR>
+# This program and the accompanying materials
+# are licensed and made available under the terms and conditions of the BSD License
+# which accompanies this distribution. The full text of the license may be found at
+# http://opensource.org/licenses/bsd-license.php
+#
+# THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+# WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+#
+##
+
+[Defines]
+ INF_VERSION = 0x00010005
+ BASE_NAME = HttpBootDxe
+ FILE_GUID = ecebcb00-d9c8-11e4-af3d-8cdcd426c973
+ MODULE_TYPE = UEFI_DRIVER
+ VERSION_STRING = 1.0
+ ENTRY_POINT = HttpBootDxeDriverEntryPoint
+ UNLOAD_IMAGE = NetLibDefaultUnload
+ MODULE_UNI_FILE = HttpBootDxe.uni
+
+[Packages]
+ MdePkg/MdePkg.dec
+ MdeModulePkg/MdeModulePkg.dec
+
+[Sources]
+ HttpBootDxe.h
+ HttpBootDxe.c
+ HttpBootComponentName.h
+ HttpBootComponentName.c
+ HttpBootImpl.h
+ HttpBootImpl.c
+ HttpBootDhcp4.h
+ HttpBootDhcp4.c
+ HttpBootSupport.h
+ HttpBootSupport.c
+ HttpBootClient.h
+ HttpBootClient.c
+
+[LibraryClasses]
+ UefiDriverEntryPoint
+ UefiBootServicesTableLib
+ MemoryAllocationLib
+ BaseLib
+ UefiLib
+ DevicePathLib
+ DebugLib
+ NetLib
+ HttpLib
+
+[Protocols]
+ ## TO_START
+ ## BY_START
+ gEfiDevicePathProtocolGuid
+
+ gEfiLoadFileProtocolGuid ## BY_START
+ gEfiHttpServiceBindingProtocolGuid ## CONSUMES
+ gEfiHttpProtocolGuid ## CONSUMES
+ gEfiDhcp4ServiceBindingProtocolGuid ## TO_START
+ gEfiDhcp4ProtocolGuid ## TO_START
+ gEfiIp4Config2ProtocolGuid ## TO_START
+ gEfiNetworkInterfaceIdentifierProtocolGuid_31 ## SOMETIMES_CONSUMES
+
+[UserExtensions.TianoCore."ExtraFiles"]
+ HttpBootDxeExtra.uni
diff --git a/NetworkPkg/HttpBootDxe/HttpBootImpl.c b/NetworkPkg/HttpBootDxe/HttpBootImpl.c index 920761e331..eee63c21d3 100644 --- a/NetworkPkg/HttpBootDxe/HttpBootImpl.c +++ b/NetworkPkg/HttpBootDxe/HttpBootImpl.c @@ -1,364 +1,364 @@ -/** @file - The implementation of EFI_LOAD_FILE_PROTOCOL for UEFI HTTP boot. - -Copyright (c) 2015, Intel Corporation. All rights reserved.<BR> -This program and the accompanying materials are licensed and made available under -the terms and conditions of the BSD License that accompanies this distribution. -The full text of the license may be found at -http://opensource.org/licenses/bsd-license.php. - -THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, -WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. - -**/ - -#include "HttpBootDxe.h" - -/** - Enable the use of UEFI HTTP boot function. - - @param[in] Private The pointer to the driver's private data. - - @retval EFI_SUCCESS HTTP boot was successfully enabled. - @retval EFI_INVALID_PARAMETER Private is NULL. - @retval EFI_ALREADY_STARTED The driver is already in started state. - -**/ -EFI_STATUS -HttpBootStart ( - IN HTTP_BOOT_PRIVATE_DATA *Private - ) -{ - UINTN Index; - - if (Private == NULL) { - return EFI_INVALID_PARAMETER; - } - - if (Private->Started) { - return EFI_ALREADY_STARTED; - } - - if (!Private->UsingIpv6) { - // - // Init the content of cached DHCP offer list. - // - ZeroMem (Private->OfferBuffer, sizeof (Private->OfferBuffer)); - for (Index = 0; Index < HTTP_BOOT_OFFER_MAX_NUM; Index++) { - Private->OfferBuffer[Index].Dhcp4.Packet.Offer.Size = HTTP_BOOT_DHCP4_PACKET_MAX_SIZE; - } - } else { - ASSERT (FALSE); - } - - Private->Started = TRUE; - - return EFI_SUCCESS; -} - -/** - Attempt to complete a DHCPv4 D.O.R.A sequence to retrieve the boot resource information. - - @param[in] Private The pointer to the driver's private data. - - @retval EFI_SUCCESS Boot info was successfully retrieved. - @retval EFI_INVALID_PARAMETER Private is NULL. - @retval EFI_NOT_STARTED The driver is in stopped state. - @retval EFI_DEVICE_ERROR An unexpected network error occurred. - @retval Others Other errors as indicated. - -**/ -EFI_STATUS -HttpBootDhcp ( - IN HTTP_BOOT_PRIVATE_DATA *Private - ) -{ - EFI_STATUS Status; - - if (Private == NULL) { - return EFI_INVALID_PARAMETER; - } - - if (!Private->Started) { - return EFI_NOT_STARTED; - } - - Status = EFI_DEVICE_ERROR; - - if (!Private->UsingIpv6) { - Status = HttpBootDhcp4Dora (Private); - } else { - ASSERT (FALSE); - } - - return Status; -} - -/** - Attempt to download the boot file through HTTP message exchange. - - @param[in] Private The pointer to the driver's private data. - @param[in, out] BufferSize On input the size of Buffer in bytes. On output with a return - code of EFI_SUCCESS, the amount of data transferred to - Buffer. On output with a return code of EFI_BUFFER_TOO_SMALL, - the size of Buffer required to retrieve the requested file. - @param[in] Buffer The memory buffer to transfer the file to. If Buffer is NULL, - then the size of the requested file is returned in - BufferSize. - - @retval EFI_SUCCESS Boot file was loaded successfully. - @retval EFI_INVALID_PARAMETER Private is NULL. - @retval EFI_NOT_STARTED The driver is in stopped state. - @retval EFI_BUFFER_TOO_SMALL The BufferSize is too small to read the boot file. BufferSize has - been updated with the size needed to complete the request. - @retval EFI_DEVICE_ERROR An unexpected network error occurred. - @retval Others Other errors as indicated. - -**/ -EFI_STATUS -HttpBootLoadFile ( - IN HTTP_BOOT_PRIVATE_DATA *Private, - IN OUT UINTN *BufferSize, - IN VOID *Buffer OPTIONAL - ) -{ - EFI_STATUS Status; - - if (Private == NULL) { - return EFI_INVALID_PARAMETER; - } - - if (!Private->Started) { - return EFI_NOT_STARTED; - } - - Status = EFI_DEVICE_ERROR; - - if (Private->BootFileUri == NULL) { - // - // Parse the cached offer to get the boot file URL first. - // - Status = HttpBootDiscoverBootInfo (Private); - if (EFI_ERROR (Status)) { - return Status; - } - } - - if (!Private->HttpCreated) { - // - // Create HTTP child. - // - Status = HttpBootCreateHttpIo (Private); - if (EFI_ERROR (Status)) { - return Status; - } - } - - if (Private->BootFileSize == 0) { - // - // Discover the information about the bootfile if we haven't. - // - - // - // Try to use HTTP HEAD method. - // - Status = HttpBootGetBootFile ( - Private, - TRUE, - &Private->BootFileSize, - NULL - ); - if (EFI_ERROR (Status) && Status != EFI_BUFFER_TOO_SMALL) { - // - // Failed to get file size by HEAD method, may be trunked encoding, try HTTP GET method. - // - ASSERT (Private->BootFileSize == 0); - Status = HttpBootGetBootFile ( - Private, - FALSE, - &Private->BootFileSize, - NULL - ); - if (EFI_ERROR (Status) && Status != EFI_BUFFER_TOO_SMALL) { - return Status; - } - } - } - - if (*BufferSize < Private->BootFileSize) { - *BufferSize = Private->BootFileSize; - return EFI_BUFFER_TOO_SMALL; - } - - // - // Load the boot file into Buffer - // - return HttpBootGetBootFile ( - Private, - FALSE, - BufferSize, - Buffer - ); -} - -/** - Disable the use of UEFI HTTP boot function. - - @param[in] Private The pointer to the driver's private data. - - @retval EFI_SUCCESS HTTP boot was successfully disabled. - @retval EFI_NOT_STARTED The driver is already in stopped state. - @retval EFI_INVALID_PARAMETER Private is NULL. - @retval Others Unexpected error when stop the function. - -**/ -EFI_STATUS -HttpBootStop ( - IN HTTP_BOOT_PRIVATE_DATA *Private - ) -{ - UINTN Index; - - if (Private == NULL) { - return EFI_INVALID_PARAMETER; - } - - if (!Private->Started) { - return EFI_NOT_STARTED; - } - - if (Private->HttpCreated) { - HttpIoDestroyIo (&Private->HttpIo); - Private->HttpCreated = FALSE; - } - - Private->Started = FALSE; - ZeroMem (&Private->StationIp, sizeof (EFI_IP_ADDRESS)); - ZeroMem (&Private->SubnetMask, sizeof (EFI_IP_ADDRESS)); - ZeroMem (&Private->GatewayIp, sizeof (EFI_IP_ADDRESS)); - Private->Port = 0; - Private->BootFileUri = NULL; - Private->BootFileUriParser = NULL; - Private->BootFileSize = 0; - Private->SelectIndex = 0; - Private->SelectProxyType = HttpOfferTypeMax; - - if (!Private->UsingIpv6) { - // - // Stop and release the DHCP4 child. - // - Private->Dhcp4->Stop (Private->Dhcp4); - Private->Dhcp4->Configure (Private->Dhcp4, NULL); - - for (Index = 0; Index < HTTP_BOOT_OFFER_MAX_NUM; Index++) { - if (Private->OfferBuffer[Index].Dhcp4.UriParser) { - HttpUrlFreeParser (Private->OfferBuffer[Index].Dhcp4.UriParser); - } - } - } else { - ASSERT (FALSE); - } - - ZeroMem (Private->OfferBuffer, sizeof (Private->OfferBuffer)); - Private->OfferNum = 0; - ZeroMem (Private->OfferCount, sizeof (Private->OfferCount)); - ZeroMem (Private->OfferIndex, sizeof (Private->OfferIndex)); - - return EFI_SUCCESS; -} - -/** - Causes the driver to load a specified file. - - @param This Protocol instance pointer. - @param FilePath The device specific path of the file to load. - @param BootPolicy If TRUE, indicates that the request originates from the - boot manager is attempting to load FilePath as a boot - selection. If FALSE, then FilePath must match as exact file - to be loaded. - @param BufferSize On input the size of Buffer in bytes. On output with a return - code of EFI_SUCCESS, the amount of data transferred to - Buffer. On output with a return code of EFI_BUFFER_TOO_SMALL, - the size of Buffer required to retrieve the requested file. - @param Buffer The memory buffer to transfer the file to. IF Buffer is NULL, - then the size of the requested file is returned in - BufferSize. - - @retval EFI_SUCCESS The file was loaded. - @retval EFI_UNSUPPORTED The device does not support the provided BootPolicy - @retval EFI_INVALID_PARAMETER FilePath is not a valid device path, or - BufferSize is NULL. - @retval EFI_NO_MEDIA No medium was present to load the file. - @retval EFI_DEVICE_ERROR The file was not loaded due to a device error. - @retval EFI_NO_RESPONSE The remote system did not respond. - @retval EFI_NOT_FOUND The file was not found. - @retval EFI_ABORTED The file load process was manually cancelled. - @retval EFI_BUFFER_TOO_SMALL The BufferSize is too small to read the current directory entry. - BufferSize has been updated with the size needed to complete - the request. - -**/ -EFI_STATUS -EFIAPI -HttpBootDxeLoadFile ( - IN EFI_LOAD_FILE_PROTOCOL *This, - IN EFI_DEVICE_PATH_PROTOCOL *FilePath, - IN BOOLEAN BootPolicy, - IN OUT UINTN *BufferSize, - IN VOID *Buffer OPTIONAL - ) -{ - HTTP_BOOT_PRIVATE_DATA *Private; - BOOLEAN MediaPresent; - EFI_STATUS Status; - - if (This == NULL || BufferSize == NULL) { - return EFI_INVALID_PARAMETER; - } - - // - // Only support BootPolicy - // - if (!BootPolicy) { - return EFI_UNSUPPORTED; - } - - Private = HTTP_BOOT_PRIVATE_DATA_FROM_LOADFILE (This); - - // - // Check media status before HTTP boot start - // - MediaPresent = TRUE; - NetLibDetectMedia (Private->Controller, &MediaPresent); - if (!MediaPresent) { - return EFI_NO_MEDIA; - } - - // - // Initialize HTTP boot and load the boot file. - // - Status = HttpBootStart (Private); - if (Status == EFI_SUCCESS || Status == EFI_ALREADY_STARTED) { - Status = HttpBootLoadFile (Private, BufferSize, Buffer); - } - - if (Status != EFI_SUCCESS && Status != EFI_BUFFER_TOO_SMALL) { - HttpBootStop (Private); - } else { - // - // Stop and release the DHCP4 child. - // - Private->Dhcp4->Stop (Private->Dhcp4); - Private->Dhcp4->Configure (Private->Dhcp4, NULL); - } - - return Status; -} - -/// -/// Load File Protocol instance -/// -GLOBAL_REMOVE_IF_UNREFERENCED -EFI_LOAD_FILE_PROTOCOL gHttpBootDxeLoadFile = { - HttpBootDxeLoadFile -}; +/** @file
+ The implementation of EFI_LOAD_FILE_PROTOCOL for UEFI HTTP boot.
+
+Copyright (c) 2015, Intel Corporation. All rights reserved.<BR>
+This program and the accompanying materials are licensed and made available under
+the terms and conditions of the BSD License that accompanies this distribution.
+The full text of the license may be found at
+http://opensource.org/licenses/bsd-license.php.
+
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+**/
+
+#include "HttpBootDxe.h"
+
+/**
+ Enable the use of UEFI HTTP boot function.
+
+ @param[in] Private The pointer to the driver's private data.
+
+ @retval EFI_SUCCESS HTTP boot was successfully enabled.
+ @retval EFI_INVALID_PARAMETER Private is NULL.
+ @retval EFI_ALREADY_STARTED The driver is already in started state.
+
+**/
+EFI_STATUS
+HttpBootStart (
+ IN HTTP_BOOT_PRIVATE_DATA *Private
+ )
+{
+ UINTN Index;
+
+ if (Private == NULL) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ if (Private->Started) {
+ return EFI_ALREADY_STARTED;
+ }
+
+ if (!Private->UsingIpv6) {
+ //
+ // Init the content of cached DHCP offer list.
+ //
+ ZeroMem (Private->OfferBuffer, sizeof (Private->OfferBuffer));
+ for (Index = 0; Index < HTTP_BOOT_OFFER_MAX_NUM; Index++) {
+ Private->OfferBuffer[Index].Dhcp4.Packet.Offer.Size = HTTP_BOOT_DHCP4_PACKET_MAX_SIZE;
+ }
+ } else {
+ ASSERT (FALSE);
+ }
+
+ Private->Started = TRUE;
+
+ return EFI_SUCCESS;
+}
+
+/**
+ Attempt to complete a DHCPv4 D.O.R.A sequence to retrieve the boot resource information.
+
+ @param[in] Private The pointer to the driver's private data.
+
+ @retval EFI_SUCCESS Boot info was successfully retrieved.
+ @retval EFI_INVALID_PARAMETER Private is NULL.
+ @retval EFI_NOT_STARTED The driver is in stopped state.
+ @retval EFI_DEVICE_ERROR An unexpected network error occurred.
+ @retval Others Other errors as indicated.
+
+**/
+EFI_STATUS
+HttpBootDhcp (
+ IN HTTP_BOOT_PRIVATE_DATA *Private
+ )
+{
+ EFI_STATUS Status;
+
+ if (Private == NULL) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ if (!Private->Started) {
+ return EFI_NOT_STARTED;
+ }
+
+ Status = EFI_DEVICE_ERROR;
+
+ if (!Private->UsingIpv6) {
+ Status = HttpBootDhcp4Dora (Private);
+ } else {
+ ASSERT (FALSE);
+ }
+
+ return Status;
+}
+
+/**
+ Attempt to download the boot file through HTTP message exchange.
+
+ @param[in] Private The pointer to the driver's private data.
+ @param[in, out] BufferSize On input the size of Buffer in bytes. On output with a return
+ code of EFI_SUCCESS, the amount of data transferred to
+ Buffer. On output with a return code of EFI_BUFFER_TOO_SMALL,
+ the size of Buffer required to retrieve the requested file.
+ @param[in] Buffer The memory buffer to transfer the file to. If Buffer is NULL,
+ then the size of the requested file is returned in
+ BufferSize.
+
+ @retval EFI_SUCCESS Boot file was loaded successfully.
+ @retval EFI_INVALID_PARAMETER Private is NULL.
+ @retval EFI_NOT_STARTED The driver is in stopped state.
+ @retval EFI_BUFFER_TOO_SMALL The BufferSize is too small to read the boot file. BufferSize has
+ been updated with the size needed to complete the request.
+ @retval EFI_DEVICE_ERROR An unexpected network error occurred.
+ @retval Others Other errors as indicated.
+
+**/
+EFI_STATUS
+HttpBootLoadFile (
+ IN HTTP_BOOT_PRIVATE_DATA *Private,
+ IN OUT UINTN *BufferSize,
+ IN VOID *Buffer OPTIONAL
+ )
+{
+ EFI_STATUS Status;
+
+ if (Private == NULL) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ if (!Private->Started) {
+ return EFI_NOT_STARTED;
+ }
+
+ Status = EFI_DEVICE_ERROR;
+
+ if (Private->BootFileUri == NULL) {
+ //
+ // Parse the cached offer to get the boot file URL first.
+ //
+ Status = HttpBootDiscoverBootInfo (Private);
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+ }
+
+ if (!Private->HttpCreated) {
+ //
+ // Create HTTP child.
+ //
+ Status = HttpBootCreateHttpIo (Private);
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+ }
+
+ if (Private->BootFileSize == 0) {
+ //
+ // Discover the information about the bootfile if we haven't.
+ //
+
+ //
+ // Try to use HTTP HEAD method.
+ //
+ Status = HttpBootGetBootFile (
+ Private,
+ TRUE,
+ &Private->BootFileSize,
+ NULL
+ );
+ if (EFI_ERROR (Status) && Status != EFI_BUFFER_TOO_SMALL) {
+ //
+ // Failed to get file size by HEAD method, may be trunked encoding, try HTTP GET method.
+ //
+ ASSERT (Private->BootFileSize == 0);
+ Status = HttpBootGetBootFile (
+ Private,
+ FALSE,
+ &Private->BootFileSize,
+ NULL
+ );
+ if (EFI_ERROR (Status) && Status != EFI_BUFFER_TOO_SMALL) {
+ return Status;
+ }
+ }
+ }
+
+ if (*BufferSize < Private->BootFileSize) {
+ *BufferSize = Private->BootFileSize;
+ return EFI_BUFFER_TOO_SMALL;
+ }
+
+ //
+ // Load the boot file into Buffer
+ //
+ return HttpBootGetBootFile (
+ Private,
+ FALSE,
+ BufferSize,
+ Buffer
+ );
+}
+
+/**
+ Disable the use of UEFI HTTP boot function.
+
+ @param[in] Private The pointer to the driver's private data.
+
+ @retval EFI_SUCCESS HTTP boot was successfully disabled.
+ @retval EFI_NOT_STARTED The driver is already in stopped state.
+ @retval EFI_INVALID_PARAMETER Private is NULL.
+ @retval Others Unexpected error when stop the function.
+
+**/
+EFI_STATUS
+HttpBootStop (
+ IN HTTP_BOOT_PRIVATE_DATA *Private
+ )
+{
+ UINTN Index;
+
+ if (Private == NULL) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ if (!Private->Started) {
+ return EFI_NOT_STARTED;
+ }
+
+ if (Private->HttpCreated) {
+ HttpIoDestroyIo (&Private->HttpIo);
+ Private->HttpCreated = FALSE;
+ }
+
+ Private->Started = FALSE;
+ ZeroMem (&Private->StationIp, sizeof (EFI_IP_ADDRESS));
+ ZeroMem (&Private->SubnetMask, sizeof (EFI_IP_ADDRESS));
+ ZeroMem (&Private->GatewayIp, sizeof (EFI_IP_ADDRESS));
+ Private->Port = 0;
+ Private->BootFileUri = NULL;
+ Private->BootFileUriParser = NULL;
+ Private->BootFileSize = 0;
+ Private->SelectIndex = 0;
+ Private->SelectProxyType = HttpOfferTypeMax;
+
+ if (!Private->UsingIpv6) {
+ //
+ // Stop and release the DHCP4 child.
+ //
+ Private->Dhcp4->Stop (Private->Dhcp4);
+ Private->Dhcp4->Configure (Private->Dhcp4, NULL);
+
+ for (Index = 0; Index < HTTP_BOOT_OFFER_MAX_NUM; Index++) {
+ if (Private->OfferBuffer[Index].Dhcp4.UriParser) {
+ HttpUrlFreeParser (Private->OfferBuffer[Index].Dhcp4.UriParser);
+ }
+ }
+ } else {
+ ASSERT (FALSE);
+ }
+
+ ZeroMem (Private->OfferBuffer, sizeof (Private->OfferBuffer));
+ Private->OfferNum = 0;
+ ZeroMem (Private->OfferCount, sizeof (Private->OfferCount));
+ ZeroMem (Private->OfferIndex, sizeof (Private->OfferIndex));
+
+ return EFI_SUCCESS;
+}
+
+/**
+ Causes the driver to load a specified file.
+
+ @param This Protocol instance pointer.
+ @param FilePath The device specific path of the file to load.
+ @param BootPolicy If TRUE, indicates that the request originates from the
+ boot manager is attempting to load FilePath as a boot
+ selection. If FALSE, then FilePath must match as exact file
+ to be loaded.
+ @param BufferSize On input the size of Buffer in bytes. On output with a return
+ code of EFI_SUCCESS, the amount of data transferred to
+ Buffer. On output with a return code of EFI_BUFFER_TOO_SMALL,
+ the size of Buffer required to retrieve the requested file.
+ @param Buffer The memory buffer to transfer the file to. IF Buffer is NULL,
+ then the size of the requested file is returned in
+ BufferSize.
+
+ @retval EFI_SUCCESS The file was loaded.
+ @retval EFI_UNSUPPORTED The device does not support the provided BootPolicy
+ @retval EFI_INVALID_PARAMETER FilePath is not a valid device path, or
+ BufferSize is NULL.
+ @retval EFI_NO_MEDIA No medium was present to load the file.
+ @retval EFI_DEVICE_ERROR The file was not loaded due to a device error.
+ @retval EFI_NO_RESPONSE The remote system did not respond.
+ @retval EFI_NOT_FOUND The file was not found.
+ @retval EFI_ABORTED The file load process was manually cancelled.
+ @retval EFI_BUFFER_TOO_SMALL The BufferSize is too small to read the current directory entry.
+ BufferSize has been updated with the size needed to complete
+ the request.
+
+**/
+EFI_STATUS
+EFIAPI
+HttpBootDxeLoadFile (
+ IN EFI_LOAD_FILE_PROTOCOL *This,
+ IN EFI_DEVICE_PATH_PROTOCOL *FilePath,
+ IN BOOLEAN BootPolicy,
+ IN OUT UINTN *BufferSize,
+ IN VOID *Buffer OPTIONAL
+ )
+{
+ HTTP_BOOT_PRIVATE_DATA *Private;
+ BOOLEAN MediaPresent;
+ EFI_STATUS Status;
+
+ if (This == NULL || BufferSize == NULL) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ //
+ // Only support BootPolicy
+ //
+ if (!BootPolicy) {
+ return EFI_UNSUPPORTED;
+ }
+
+ Private = HTTP_BOOT_PRIVATE_DATA_FROM_LOADFILE (This);
+
+ //
+ // Check media status before HTTP boot start
+ //
+ MediaPresent = TRUE;
+ NetLibDetectMedia (Private->Controller, &MediaPresent);
+ if (!MediaPresent) {
+ return EFI_NO_MEDIA;
+ }
+
+ //
+ // Initialize HTTP boot and load the boot file.
+ //
+ Status = HttpBootStart (Private);
+ if (Status == EFI_SUCCESS || Status == EFI_ALREADY_STARTED) {
+ Status = HttpBootLoadFile (Private, BufferSize, Buffer);
+ }
+
+ if (Status != EFI_SUCCESS && Status != EFI_BUFFER_TOO_SMALL) {
+ HttpBootStop (Private);
+ } else {
+ //
+ // Stop and release the DHCP4 child.
+ //
+ Private->Dhcp4->Stop (Private->Dhcp4);
+ Private->Dhcp4->Configure (Private->Dhcp4, NULL);
+ }
+
+ return Status;
+}
+
+///
+/// Load File Protocol instance
+///
+GLOBAL_REMOVE_IF_UNREFERENCED
+EFI_LOAD_FILE_PROTOCOL gHttpBootDxeLoadFile = {
+ HttpBootDxeLoadFile
+};
diff --git a/NetworkPkg/HttpBootDxe/HttpBootImpl.h b/NetworkPkg/HttpBootDxe/HttpBootImpl.h index 90742dd159..a2e9f5a328 100644 --- a/NetworkPkg/HttpBootDxe/HttpBootImpl.h +++ b/NetworkPkg/HttpBootDxe/HttpBootImpl.h @@ -1,50 +1,50 @@ -/** @file - The declaration of UEFI HTTP boot function. - -Copyright (c) 2015, Intel Corporation. All rights reserved.<BR> -This program and the accompanying materials are licensed and made available under -the terms and conditions of the BSD License that accompanies this distribution. -The full text of the license may be found at -http://opensource.org/licenses/bsd-license.php. - -THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, -WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. - -**/ -#ifndef __EFI_HTTP_BOOT_IMPL_H__ -#define __EFI_HTTP_BOOT_IMPL_H__ - -/** - Attempt to complete a DHCPv4 D.O.R.A sequence to retrieve the boot resource information. - - @param[in] Private The pointer to the driver's private data. - - @retval EFI_SUCCESS Boot info was successfully retrieved. - @retval EFI_INVALID_PARAMETER Private is NULL. - @retval EFI_NOT_STARTED The driver is in stopped state. - @retval EFI_DEVICE_ERROR An unexpected network error occurred. - @retval Others Other errors as indicated. - -**/ -EFI_STATUS -HttpBootDhcp ( - IN HTTP_BOOT_PRIVATE_DATA *Private - ); - -/** - Disable the use of UEFI HTTP boot function. - - @param[in] Private The pointer to the driver's private data. - - @retval EFI_SUCCESS HTTP boot was successfully disabled. - @retval EFI_NOT_STARTED The driver is already in stopped state. - @retval EFI_INVALID_PARAMETER Private is NULL. - @retval Others Unexpected error when stop the function. - -**/ -EFI_STATUS -HttpBootStop ( - IN HTTP_BOOT_PRIVATE_DATA *Private - ); - -#endif +/** @file
+ The declaration of UEFI HTTP boot function.
+
+Copyright (c) 2015, Intel Corporation. All rights reserved.<BR>
+This program and the accompanying materials are licensed and made available under
+the terms and conditions of the BSD License that accompanies this distribution.
+The full text of the license may be found at
+http://opensource.org/licenses/bsd-license.php.
+
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+**/
+#ifndef __EFI_HTTP_BOOT_IMPL_H__
+#define __EFI_HTTP_BOOT_IMPL_H__
+
+/**
+ Attempt to complete a DHCPv4 D.O.R.A sequence to retrieve the boot resource information.
+
+ @param[in] Private The pointer to the driver's private data.
+
+ @retval EFI_SUCCESS Boot info was successfully retrieved.
+ @retval EFI_INVALID_PARAMETER Private is NULL.
+ @retval EFI_NOT_STARTED The driver is in stopped state.
+ @retval EFI_DEVICE_ERROR An unexpected network error occurred.
+ @retval Others Other errors as indicated.
+
+**/
+EFI_STATUS
+HttpBootDhcp (
+ IN HTTP_BOOT_PRIVATE_DATA *Private
+ );
+
+/**
+ Disable the use of UEFI HTTP boot function.
+
+ @param[in] Private The pointer to the driver's private data.
+
+ @retval EFI_SUCCESS HTTP boot was successfully disabled.
+ @retval EFI_NOT_STARTED The driver is already in stopped state.
+ @retval EFI_INVALID_PARAMETER Private is NULL.
+ @retval Others Unexpected error when stop the function.
+
+**/
+EFI_STATUS
+HttpBootStop (
+ IN HTTP_BOOT_PRIVATE_DATA *Private
+ );
+
+#endif
diff --git a/NetworkPkg/HttpBootDxe/HttpBootSupport.c b/NetworkPkg/HttpBootDxe/HttpBootSupport.c index e21b50d066..761643141f 100644 --- a/NetworkPkg/HttpBootDxe/HttpBootSupport.c +++ b/NetworkPkg/HttpBootDxe/HttpBootSupport.c @@ -1,590 +1,590 @@ -/** @file - Support functions implementation for UEFI HTTP boot driver. - -Copyright (c) 2015, Intel Corporation. All rights reserved.<BR> -This program and the accompanying materials are licensed and made available under -the terms and conditions of the BSD License that accompanies this distribution. -The full text of the license may be found at -http://opensource.org/licenses/bsd-license.php. - -THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, -WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. - -**/ - -#include "HttpBootDxe.h" - - -/** - Get the Nic handle using any child handle in the IPv4 stack. - - @param[in] ControllerHandle Pointer to child handle over IPv4. - - @return NicHandle The pointer to the Nic handle. - @return NULL Can't find the Nic handle. - -**/ -EFI_HANDLE -HttpBootGetNicByIp4Children ( - IN EFI_HANDLE ControllerHandle - ) -{ - EFI_HANDLE NicHandle; - - NicHandle = NetLibGetNicHandle (ControllerHandle, &gEfiHttpProtocolGuid); - if (NicHandle == NULL) { - NicHandle = NetLibGetNicHandle (ControllerHandle, &gEfiDhcp4ProtocolGuid); - if (NicHandle == NULL) { - return NULL; - } - } - - return NicHandle; -} - - -/** - This function is to convert UINTN to ASCII string with the required formatting. - - @param[in] Number Numeric value to be converted. - @param[in] Buffer The pointer to the buffer for ASCII string. - @param[in] Length The length of the required format. - -**/ -VOID -HttpBootUintnToAscDecWithFormat ( - IN UINTN Number, - IN UINT8 *Buffer, - IN INTN Length - ) -{ - UINTN Remainder; - - while (Length > 0) { - Length--; - Remainder = Number % 10; - Number /= 10; - Buffer[Length] = (UINT8) ('0' + Remainder); - } -} - -/** - This function is to display the IPv4 address. - - @param[in] Ip The pointer to the IPv4 address. - -**/ -VOID -HttpBootShowIp4Addr ( - IN EFI_IPv4_ADDRESS *Ip - ) -{ - UINTN Index; - - for (Index = 0; Index < 4; Index++) { - AsciiPrint ("%d", Ip->Addr[Index]); - if (Index < 3) { - AsciiPrint ("."); - } - } -} - -/** - Create a HTTP_IO_HEADER to hold the HTTP header items. - - @param[in] MaxHeaderCount The maximun number of HTTP header in this holder. - - @return A pointer of the HTTP header holder or NULL if failed. - -**/ -HTTP_IO_HEADER * -HttpBootCreateHeader ( - UINTN MaxHeaderCount -) -{ - HTTP_IO_HEADER *HttpIoHeader; - - if (MaxHeaderCount == 0) { - return NULL; - } - - HttpIoHeader = AllocateZeroPool (sizeof (HTTP_IO_HEADER) + MaxHeaderCount * sizeof (EFI_HTTP_HEADER)); - if (HttpIoHeader == NULL) { - return NULL; - } - - HttpIoHeader->MaxHeaderCount = MaxHeaderCount; - HttpIoHeader->Headers = (EFI_HTTP_HEADER *) (HttpIoHeader + 1); - - return HttpIoHeader; -} - -/** - Destroy the HTTP_IO_HEADER and release the resouces. - - @param[in] HttpIoHeader Point to the HTTP header holder to be destroyed. - -**/ -VOID -HttpBootFreeHeader ( - IN HTTP_IO_HEADER *HttpIoHeader - ) -{ - UINTN Index; - - if (HttpIoHeader != NULL) { - if (HttpIoHeader->HeaderCount != 0) { - for (Index = 0; Index < HttpIoHeader->HeaderCount; Index++) { - FreePool (HttpIoHeader->Headers[Index].FieldName); - FreePool (HttpIoHeader->Headers[Index].FieldValue); - } - } - FreePool (HttpIoHeader); - } -} - -/** - Find a specified header field according to the field name. - - @param[in] HeaderCount Number of HTTP header structures in Headers list. - @param[in] Headers Array containing list of HTTP headers. - @param[in] FieldName Null terminated string which describes a field name. - - @return Pointer to the found header or NULL. - -**/ -EFI_HTTP_HEADER * -HttpBootFindHeader ( - IN UINTN HeaderCount, - IN EFI_HTTP_HEADER *Headers, - IN CHAR8 *FieldName - ) -{ - UINTN Index; - - if (HeaderCount == 0 || Headers == NULL || FieldName == NULL) { - return NULL; - } - - for (Index = 0; Index < HeaderCount; Index++){ - // - // Field names are case-insensitive (RFC 2616). - // - if (AsciiStriCmp (Headers[Index].FieldName, FieldName) == 0) { - return &Headers[Index]; - } - } - return NULL; -} - -/** - Set or update a HTTP header with the field name and corresponding value. - - @param[in] HttpIoHeader Point to the HTTP header holder. - @param[in] FieldName Null terminated string which describes a field name. - @param[in] FieldValue Null terminated string which describes the corresponding field value. - - @retval EFI_SUCCESS The HTTP header has been set or updated. - @retval EFI_INVALID_PARAMETER Any input parameter is invalid. - @retval EFI_OUT_OF_RESOURCES Insufficient resource to complete the operation. - @retval Other Unexpected error happened. - -**/ -EFI_STATUS -HttpBootSetHeader ( - IN HTTP_IO_HEADER *HttpIoHeader, - IN CHAR8 *FieldName, - IN CHAR8 *FieldValue - ) -{ - EFI_HTTP_HEADER *Header; - UINTN StrSize; - CHAR8 *NewFieldValue; - - if (HttpIoHeader == NULL || FieldName == NULL || FieldValue == NULL) { - return EFI_INVALID_PARAMETER; - } - - Header = HttpBootFindHeader (HttpIoHeader->HeaderCount, HttpIoHeader->Headers, FieldName); - if (Header == NULL) { - // - // Add a new header. - // - if (HttpIoHeader->HeaderCount >= HttpIoHeader->MaxHeaderCount) { - return EFI_OUT_OF_RESOURCES; - } - Header = &HttpIoHeader->Headers[HttpIoHeader->HeaderCount]; - - StrSize = AsciiStrSize (FieldName); - Header->FieldName = AllocatePool (StrSize); - if (Header->FieldName == NULL) { - return EFI_OUT_OF_RESOURCES; - } - CopyMem (Header->FieldName, FieldName, StrSize); - Header->FieldName[StrSize -1] = '\0'; - - StrSize = AsciiStrSize (FieldValue); - Header->FieldValue = AllocatePool (StrSize); - if (Header->FieldValue == NULL) { - FreePool (Header->FieldName); - return EFI_OUT_OF_RESOURCES; - } - CopyMem (Header->FieldValue, FieldValue, StrSize); - Header->FieldValue[StrSize -1] = '\0'; - - HttpIoHeader->HeaderCount++; - } else { - // - // Update an existing one. - // - StrSize = AsciiStrSize (FieldValue); - NewFieldValue = AllocatePool (StrSize); - if (NewFieldValue == NULL) { - return EFI_OUT_OF_RESOURCES; - } - CopyMem (NewFieldValue, FieldValue, StrSize); - NewFieldValue[StrSize -1] = '\0'; - - if (Header->FieldValue != NULL) { - FreePool (Header->FieldValue); - } - Header->FieldValue = NewFieldValue; - } - - return EFI_SUCCESS; -} - -/** - Notify the callback function when an event is triggered. - - @param[in] Event The triggered event. - @param[in] Context The opaque parameter to the function. - -**/ -VOID -EFIAPI -HttpIoCommonNotify ( - IN EFI_EVENT Event, - IN VOID *Context - ) -{ - *((BOOLEAN *) Context) = TRUE; -} - -/** - Create a HTTP_IO to access the HTTP service. It will create and configure - a HTTP child handle. - - @param[in] Image The handle of the driver image. - @param[in] Controller The handle of the controller. - @param[in] IpVersion IP_VERSION_4 or IP_VERSION_6. - @param[in] ConfigData The HTTP_IO configuration data. - @param[out] HttpIo The HTTP_IO. - - @retval EFI_SUCCESS The HTTP_IO is created and configured. - @retval EFI_INVALID_PARAMETER One or more parameters are invalid. - @retval EFI_UNSUPPORTED One or more of the control options are not - supported in the implementation. - @retval EFI_OUT_OF_RESOURCES Failed to allocate memory. - @retval Others Failed to create the HTTP_IO or configure it. - -**/ -EFI_STATUS -HttpIoCreateIo ( - IN EFI_HANDLE Image, - IN EFI_HANDLE Controller, - IN UINT8 IpVersion, - IN HTTP_IO_CONFIG_DATA *ConfigData, - OUT HTTP_IO *HttpIo - ) -{ - EFI_STATUS Status; - EFI_HTTP_CONFIG_DATA HttpConfigData; - EFI_HTTPv4_ACCESS_POINT Http4AccessPoint; - EFI_HTTP_PROTOCOL *Http; - EFI_EVENT Event; - - if ((Image == NULL) || (Controller == NULL) || (ConfigData == NULL) || (HttpIo == NULL)) { - return EFI_INVALID_PARAMETER; - } - - if (IpVersion != IP_VERSION_4 && IpVersion != IP_VERSION_6) { - return EFI_UNSUPPORTED; - } - - ZeroMem (HttpIo, sizeof (HTTP_IO)); - - // - // Create the HTTP child instance and get the HTTP protocol. - // - Status = NetLibCreateServiceChild ( - Controller, - Image, - &gEfiHttpServiceBindingProtocolGuid, - &HttpIo->Handle - ); - if (EFI_ERROR (Status)) { - return Status; - } - - Status = gBS->OpenProtocol ( - HttpIo->Handle, - &gEfiHttpProtocolGuid, - (VOID **) &Http, - Image, - Controller, - EFI_OPEN_PROTOCOL_BY_DRIVER - ); - if (EFI_ERROR (Status) || (Http == NULL)) { - goto ON_ERROR; - } - - // - // Init the configuration data and configure the HTTP child. - // - HttpIo->Image = Image; - HttpIo->Controller = Controller; - HttpIo->IpVersion = IpVersion; - HttpIo->Http = Http; - - ZeroMem (&HttpConfigData, sizeof (EFI_HTTP_CONFIG_DATA)); - HttpConfigData.HttpVersion = HttpVersion11; - HttpConfigData.TimeOutMillisec = ConfigData->Config4.RequestTimeOut; - if (HttpIo->IpVersion == IP_VERSION_4) { - HttpConfigData.LocalAddressIsIPv6 = FALSE; - - Http4AccessPoint.UseDefaultAddress = ConfigData->Config4.UseDefaultAddress; - Http4AccessPoint.LocalPort = ConfigData->Config4.LocalPort; - IP4_COPY_ADDRESS (&Http4AccessPoint.LocalAddress, &ConfigData->Config4.LocalIp); - IP4_COPY_ADDRESS (&Http4AccessPoint.LocalSubnet, &ConfigData->Config4.SubnetMask); - HttpConfigData.AccessPoint.IPv4Node = &Http4AccessPoint; - } else { - ASSERT (FALSE); - } - - Status = Http->Configure (Http, &HttpConfigData); - if (EFI_ERROR (Status)) { - goto ON_ERROR; - } - - // - // Create events for variuos asynchronous operations. - // - Status = gBS->CreateEvent ( - EVT_NOTIFY_SIGNAL, - TPL_NOTIFY, - HttpIoCommonNotify, - &HttpIo->IsTxDone, - &Event - ); - if (EFI_ERROR (Status)) { - goto ON_ERROR; - } - HttpIo->ReqToken.Event = Event; - HttpIo->ReqToken.Message = &HttpIo->ReqMessage; - - Status = gBS->CreateEvent ( - EVT_NOTIFY_SIGNAL, - TPL_NOTIFY, - HttpIoCommonNotify, - &HttpIo->IsRxDone, - &Event - ); - if (EFI_ERROR (Status)) { - goto ON_ERROR; - } - HttpIo->RspToken.Event = Event; - HttpIo->RspToken.Message = &HttpIo->RspMessage; - - return EFI_SUCCESS; - -ON_ERROR: - HttpIoDestroyIo (HttpIo); - - return Status; -} - -/** - Destroy the HTTP_IO and release the resouces. - - @param[in] HttpIo The HTTP_IO which wraps the HTTP service to be destroyed. - -**/ -VOID -HttpIoDestroyIo ( - IN HTTP_IO *HttpIo - ) -{ - EFI_HTTP_PROTOCOL *Http; - EFI_EVENT Event; - - if (HttpIo == NULL) { - return; - } - - Event = HttpIo->ReqToken.Event; - if (Event != NULL) { - gBS->CloseEvent (Event); - } - - Event = HttpIo->RspToken.Event; - if (Event != NULL) { - gBS->CloseEvent (Event); - } - - Http = HttpIo->Http; - if (Http != NULL) { - Http->Configure (Http, NULL); - gBS->CloseProtocol ( - HttpIo->Handle, - &gEfiHttpProtocolGuid, - HttpIo->Image, - HttpIo->Controller - ); - } - - NetLibDestroyServiceChild ( - HttpIo->Controller, - HttpIo->Image, - &gEfiHttpServiceBindingProtocolGuid, - HttpIo->Handle - ); -} - -/** - Synchronously send a HTTP REQUEST message to the server. - - @param[in] HttpIo The HttpIo wrapping the HTTP service. - @param[in] Request A pointer to storage such data as URL and HTTP method. - @param[in] HeaderCount Number of HTTP header structures in Headers list. - @param[in] Headers Array containing list of HTTP headers. - @param[in] BodyLength Length in bytes of the HTTP body. - @param[in] Body Body associated with the HTTP request. - - @retval EFI_SUCCESS The HTTP request is trasmitted. - @retval EFI_INVALID_PARAMETER One or more parameters are invalid. - @retval EFI_OUT_OF_RESOURCES Failed to allocate memory. - @retval EFI_DEVICE_ERROR An unexpected network or system error occurred. - @retval Others Other errors as indicated. - -**/ -EFI_STATUS -HttpIoSendRequest ( - IN HTTP_IO *HttpIo, - IN EFI_HTTP_REQUEST_DATA *Request, - IN UINTN HeaderCount, - IN EFI_HTTP_HEADER *Headers, - IN UINTN BodyLength, - IN VOID *Body - ) -{ - EFI_STATUS Status; - EFI_HTTP_PROTOCOL *Http; - - if (HttpIo == NULL || HttpIo->Http == NULL) { - return EFI_INVALID_PARAMETER; - } - - HttpIo->ReqToken.Status = EFI_NOT_READY; - HttpIo->ReqToken.Message->Data.Request = Request; - HttpIo->ReqToken.Message->HeaderCount = HeaderCount; - HttpIo->ReqToken.Message->Headers = Headers; - HttpIo->ReqToken.Message->BodyLength = BodyLength; - HttpIo->ReqToken.Message->Body = Body; - - // - // Queue the request token to HTTP instances. - // - Http = HttpIo->Http; - HttpIo->IsTxDone = FALSE; - Status = Http->Request ( - Http, - &HttpIo->ReqToken - ); - if (EFI_ERROR (Status)) { - return Status; - } - - // - // Poll the network until transmit finish. - // - while (!HttpIo->IsTxDone) { - Http->Poll (Http); - } - - return HttpIo->ReqToken.Status; -} - -/** - Synchronously receive a HTTP RESPONSE message from the server. - - @param[in] HttpIo The HttpIo wrapping the HTTP service. - @param[in] RecvMsgHeader TRUE to receive a new HTTP response (from message header). - FALSE to continue receive the previous response message. - @param[out] ResponseData Point to a wrapper of the received response data. - - @retval EFI_SUCCESS The HTTP resopnse is received. - @retval EFI_INVALID_PARAMETER One or more parameters are invalid. - @retval EFI_OUT_OF_RESOURCES Failed to allocate memory. - @retval EFI_DEVICE_ERROR An unexpected network or system error occurred. - @retval Others Other errors as indicated. - -**/ -EFI_STATUS -HttpIoRecvResponse ( - IN HTTP_IO *HttpIo, - IN BOOLEAN RecvMsgHeader, - OUT HTTP_IO_RESOPNSE_DATA *ResponseData - ) -{ - EFI_STATUS Status; - EFI_HTTP_PROTOCOL *Http; - - if (HttpIo == NULL || HttpIo->Http == NULL || ResponseData == NULL) { - return EFI_INVALID_PARAMETER; - } - - // - // Queue the response token to HTTP instances. - // - HttpIo->RspToken.Status = EFI_NOT_READY; - if (RecvMsgHeader) { - HttpIo->RspToken.Message->Data.Response = &ResponseData->Response; - } else { - HttpIo->RspToken.Message->Data.Response = NULL; - } - HttpIo->RspToken.Message->HeaderCount = 0; - HttpIo->RspToken.Message->Headers = NULL; - HttpIo->RspToken.Message->BodyLength = ResponseData->BodyLength; - HttpIo->RspToken.Message->Body = ResponseData->Body; - - Http = HttpIo->Http; - HttpIo->IsRxDone = FALSE; - Status = Http->Response ( - Http, - &HttpIo->RspToken - ); - - if (EFI_ERROR (Status)) { - return Status; - } - - // - // Poll the network until transmit finish. - // - while (!HttpIo->IsRxDone) { - Http->Poll (Http); - } - - // - // Store the received data into the wrapper. - // - Status = HttpIo->ReqToken.Status; - if (!EFI_ERROR (Status)) { - ResponseData->HeaderCount = HttpIo->RspToken.Message->HeaderCount; - ResponseData->Headers = HttpIo->RspToken.Message->Headers; - ResponseData->BodyLength = HttpIo->RspToken.Message->BodyLength; - } - - return Status; -} +/** @file
+ Support functions implementation for UEFI HTTP boot driver.
+
+Copyright (c) 2015, Intel Corporation. All rights reserved.<BR>
+This program and the accompanying materials are licensed and made available under
+the terms and conditions of the BSD License that accompanies this distribution.
+The full text of the license may be found at
+http://opensource.org/licenses/bsd-license.php.
+
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+**/
+
+#include "HttpBootDxe.h"
+
+
+/**
+ Get the Nic handle using any child handle in the IPv4 stack.
+
+ @param[in] ControllerHandle Pointer to child handle over IPv4.
+
+ @return NicHandle The pointer to the Nic handle.
+ @return NULL Can't find the Nic handle.
+
+**/
+EFI_HANDLE
+HttpBootGetNicByIp4Children (
+ IN EFI_HANDLE ControllerHandle
+ )
+{
+ EFI_HANDLE NicHandle;
+
+ NicHandle = NetLibGetNicHandle (ControllerHandle, &gEfiHttpProtocolGuid);
+ if (NicHandle == NULL) {
+ NicHandle = NetLibGetNicHandle (ControllerHandle, &gEfiDhcp4ProtocolGuid);
+ if (NicHandle == NULL) {
+ return NULL;
+ }
+ }
+
+ return NicHandle;
+}
+
+
+/**
+ This function is to convert UINTN to ASCII string with the required formatting.
+
+ @param[in] Number Numeric value to be converted.
+ @param[in] Buffer The pointer to the buffer for ASCII string.
+ @param[in] Length The length of the required format.
+
+**/
+VOID
+HttpBootUintnToAscDecWithFormat (
+ IN UINTN Number,
+ IN UINT8 *Buffer,
+ IN INTN Length
+ )
+{
+ UINTN Remainder;
+
+ while (Length > 0) {
+ Length--;
+ Remainder = Number % 10;
+ Number /= 10;
+ Buffer[Length] = (UINT8) ('0' + Remainder);
+ }
+}
+
+/**
+ This function is to display the IPv4 address.
+
+ @param[in] Ip The pointer to the IPv4 address.
+
+**/
+VOID
+HttpBootShowIp4Addr (
+ IN EFI_IPv4_ADDRESS *Ip
+ )
+{
+ UINTN Index;
+
+ for (Index = 0; Index < 4; Index++) {
+ AsciiPrint ("%d", Ip->Addr[Index]);
+ if (Index < 3) {
+ AsciiPrint (".");
+ }
+ }
+}
+
+/**
+ Create a HTTP_IO_HEADER to hold the HTTP header items.
+
+ @param[in] MaxHeaderCount The maximun number of HTTP header in this holder.
+
+ @return A pointer of the HTTP header holder or NULL if failed.
+
+**/
+HTTP_IO_HEADER *
+HttpBootCreateHeader (
+ UINTN MaxHeaderCount
+)
+{
+ HTTP_IO_HEADER *HttpIoHeader;
+
+ if (MaxHeaderCount == 0) {
+ return NULL;
+ }
+
+ HttpIoHeader = AllocateZeroPool (sizeof (HTTP_IO_HEADER) + MaxHeaderCount * sizeof (EFI_HTTP_HEADER));
+ if (HttpIoHeader == NULL) {
+ return NULL;
+ }
+
+ HttpIoHeader->MaxHeaderCount = MaxHeaderCount;
+ HttpIoHeader->Headers = (EFI_HTTP_HEADER *) (HttpIoHeader + 1);
+
+ return HttpIoHeader;
+}
+
+/**
+ Destroy the HTTP_IO_HEADER and release the resouces.
+
+ @param[in] HttpIoHeader Point to the HTTP header holder to be destroyed.
+
+**/
+VOID
+HttpBootFreeHeader (
+ IN HTTP_IO_HEADER *HttpIoHeader
+ )
+{
+ UINTN Index;
+
+ if (HttpIoHeader != NULL) {
+ if (HttpIoHeader->HeaderCount != 0) {
+ for (Index = 0; Index < HttpIoHeader->HeaderCount; Index++) {
+ FreePool (HttpIoHeader->Headers[Index].FieldName);
+ FreePool (HttpIoHeader->Headers[Index].FieldValue);
+ }
+ }
+ FreePool (HttpIoHeader);
+ }
+}
+
+/**
+ Find a specified header field according to the field name.
+
+ @param[in] HeaderCount Number of HTTP header structures in Headers list.
+ @param[in] Headers Array containing list of HTTP headers.
+ @param[in] FieldName Null terminated string which describes a field name.
+
+ @return Pointer to the found header or NULL.
+
+**/
+EFI_HTTP_HEADER *
+HttpBootFindHeader (
+ IN UINTN HeaderCount,
+ IN EFI_HTTP_HEADER *Headers,
+ IN CHAR8 *FieldName
+ )
+{
+ UINTN Index;
+
+ if (HeaderCount == 0 || Headers == NULL || FieldName == NULL) {
+ return NULL;
+ }
+
+ for (Index = 0; Index < HeaderCount; Index++){
+ //
+ // Field names are case-insensitive (RFC 2616).
+ //
+ if (AsciiStriCmp (Headers[Index].FieldName, FieldName) == 0) {
+ return &Headers[Index];
+ }
+ }
+ return NULL;
+}
+
+/**
+ Set or update a HTTP header with the field name and corresponding value.
+
+ @param[in] HttpIoHeader Point to the HTTP header holder.
+ @param[in] FieldName Null terminated string which describes a field name.
+ @param[in] FieldValue Null terminated string which describes the corresponding field value.
+
+ @retval EFI_SUCCESS The HTTP header has been set or updated.
+ @retval EFI_INVALID_PARAMETER Any input parameter is invalid.
+ @retval EFI_OUT_OF_RESOURCES Insufficient resource to complete the operation.
+ @retval Other Unexpected error happened.
+
+**/
+EFI_STATUS
+HttpBootSetHeader (
+ IN HTTP_IO_HEADER *HttpIoHeader,
+ IN CHAR8 *FieldName,
+ IN CHAR8 *FieldValue
+ )
+{
+ EFI_HTTP_HEADER *Header;
+ UINTN StrSize;
+ CHAR8 *NewFieldValue;
+
+ if (HttpIoHeader == NULL || FieldName == NULL || FieldValue == NULL) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ Header = HttpBootFindHeader (HttpIoHeader->HeaderCount, HttpIoHeader->Headers, FieldName);
+ if (Header == NULL) {
+ //
+ // Add a new header.
+ //
+ if (HttpIoHeader->HeaderCount >= HttpIoHeader->MaxHeaderCount) {
+ return EFI_OUT_OF_RESOURCES;
+ }
+ Header = &HttpIoHeader->Headers[HttpIoHeader->HeaderCount];
+
+ StrSize = AsciiStrSize (FieldName);
+ Header->FieldName = AllocatePool (StrSize);
+ if (Header->FieldName == NULL) {
+ return EFI_OUT_OF_RESOURCES;
+ }
+ CopyMem (Header->FieldName, FieldName, StrSize);
+ Header->FieldName[StrSize -1] = '\0';
+
+ StrSize = AsciiStrSize (FieldValue);
+ Header->FieldValue = AllocatePool (StrSize);
+ if (Header->FieldValue == NULL) {
+ FreePool (Header->FieldName);
+ return EFI_OUT_OF_RESOURCES;
+ }
+ CopyMem (Header->FieldValue, FieldValue, StrSize);
+ Header->FieldValue[StrSize -1] = '\0';
+
+ HttpIoHeader->HeaderCount++;
+ } else {
+ //
+ // Update an existing one.
+ //
+ StrSize = AsciiStrSize (FieldValue);
+ NewFieldValue = AllocatePool (StrSize);
+ if (NewFieldValue == NULL) {
+ return EFI_OUT_OF_RESOURCES;
+ }
+ CopyMem (NewFieldValue, FieldValue, StrSize);
+ NewFieldValue[StrSize -1] = '\0';
+
+ if (Header->FieldValue != NULL) {
+ FreePool (Header->FieldValue);
+ }
+ Header->FieldValue = NewFieldValue;
+ }
+
+ return EFI_SUCCESS;
+}
+
+/**
+ Notify the callback function when an event is triggered.
+
+ @param[in] Event The triggered event.
+ @param[in] Context The opaque parameter to the function.
+
+**/
+VOID
+EFIAPI
+HttpIoCommonNotify (
+ IN EFI_EVENT Event,
+ IN VOID *Context
+ )
+{
+ *((BOOLEAN *) Context) = TRUE;
+}
+
+/**
+ Create a HTTP_IO to access the HTTP service. It will create and configure
+ a HTTP child handle.
+
+ @param[in] Image The handle of the driver image.
+ @param[in] Controller The handle of the controller.
+ @param[in] IpVersion IP_VERSION_4 or IP_VERSION_6.
+ @param[in] ConfigData The HTTP_IO configuration data.
+ @param[out] HttpIo The HTTP_IO.
+
+ @retval EFI_SUCCESS The HTTP_IO is created and configured.
+ @retval EFI_INVALID_PARAMETER One or more parameters are invalid.
+ @retval EFI_UNSUPPORTED One or more of the control options are not
+ supported in the implementation.
+ @retval EFI_OUT_OF_RESOURCES Failed to allocate memory.
+ @retval Others Failed to create the HTTP_IO or configure it.
+
+**/
+EFI_STATUS
+HttpIoCreateIo (
+ IN EFI_HANDLE Image,
+ IN EFI_HANDLE Controller,
+ IN UINT8 IpVersion,
+ IN HTTP_IO_CONFIG_DATA *ConfigData,
+ OUT HTTP_IO *HttpIo
+ )
+{
+ EFI_STATUS Status;
+ EFI_HTTP_CONFIG_DATA HttpConfigData;
+ EFI_HTTPv4_ACCESS_POINT Http4AccessPoint;
+ EFI_HTTP_PROTOCOL *Http;
+ EFI_EVENT Event;
+
+ if ((Image == NULL) || (Controller == NULL) || (ConfigData == NULL) || (HttpIo == NULL)) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ if (IpVersion != IP_VERSION_4 && IpVersion != IP_VERSION_6) {
+ return EFI_UNSUPPORTED;
+ }
+
+ ZeroMem (HttpIo, sizeof (HTTP_IO));
+
+ //
+ // Create the HTTP child instance and get the HTTP protocol.
+ //
+ Status = NetLibCreateServiceChild (
+ Controller,
+ Image,
+ &gEfiHttpServiceBindingProtocolGuid,
+ &HttpIo->Handle
+ );
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+
+ Status = gBS->OpenProtocol (
+ HttpIo->Handle,
+ &gEfiHttpProtocolGuid,
+ (VOID **) &Http,
+ Image,
+ Controller,
+ EFI_OPEN_PROTOCOL_BY_DRIVER
+ );
+ if (EFI_ERROR (Status) || (Http == NULL)) {
+ goto ON_ERROR;
+ }
+
+ //
+ // Init the configuration data and configure the HTTP child.
+ //
+ HttpIo->Image = Image;
+ HttpIo->Controller = Controller;
+ HttpIo->IpVersion = IpVersion;
+ HttpIo->Http = Http;
+
+ ZeroMem (&HttpConfigData, sizeof (EFI_HTTP_CONFIG_DATA));
+ HttpConfigData.HttpVersion = HttpVersion11;
+ HttpConfigData.TimeOutMillisec = ConfigData->Config4.RequestTimeOut;
+ if (HttpIo->IpVersion == IP_VERSION_4) {
+ HttpConfigData.LocalAddressIsIPv6 = FALSE;
+
+ Http4AccessPoint.UseDefaultAddress = ConfigData->Config4.UseDefaultAddress;
+ Http4AccessPoint.LocalPort = ConfigData->Config4.LocalPort;
+ IP4_COPY_ADDRESS (&Http4AccessPoint.LocalAddress, &ConfigData->Config4.LocalIp);
+ IP4_COPY_ADDRESS (&Http4AccessPoint.LocalSubnet, &ConfigData->Config4.SubnetMask);
+ HttpConfigData.AccessPoint.IPv4Node = &Http4AccessPoint;
+ } else {
+ ASSERT (FALSE);
+ }
+
+ Status = Http->Configure (Http, &HttpConfigData);
+ if (EFI_ERROR (Status)) {
+ goto ON_ERROR;
+ }
+
+ //
+ // Create events for variuos asynchronous operations.
+ //
+ Status = gBS->CreateEvent (
+ EVT_NOTIFY_SIGNAL,
+ TPL_NOTIFY,
+ HttpIoCommonNotify,
+ &HttpIo->IsTxDone,
+ &Event
+ );
+ if (EFI_ERROR (Status)) {
+ goto ON_ERROR;
+ }
+ HttpIo->ReqToken.Event = Event;
+ HttpIo->ReqToken.Message = &HttpIo->ReqMessage;
+
+ Status = gBS->CreateEvent (
+ EVT_NOTIFY_SIGNAL,
+ TPL_NOTIFY,
+ HttpIoCommonNotify,
+ &HttpIo->IsRxDone,
+ &Event
+ );
+ if (EFI_ERROR (Status)) {
+ goto ON_ERROR;
+ }
+ HttpIo->RspToken.Event = Event;
+ HttpIo->RspToken.Message = &HttpIo->RspMessage;
+
+ return EFI_SUCCESS;
+
+ON_ERROR:
+ HttpIoDestroyIo (HttpIo);
+
+ return Status;
+}
+
+/**
+ Destroy the HTTP_IO and release the resouces.
+
+ @param[in] HttpIo The HTTP_IO which wraps the HTTP service to be destroyed.
+
+**/
+VOID
+HttpIoDestroyIo (
+ IN HTTP_IO *HttpIo
+ )
+{
+ EFI_HTTP_PROTOCOL *Http;
+ EFI_EVENT Event;
+
+ if (HttpIo == NULL) {
+ return;
+ }
+
+ Event = HttpIo->ReqToken.Event;
+ if (Event != NULL) {
+ gBS->CloseEvent (Event);
+ }
+
+ Event = HttpIo->RspToken.Event;
+ if (Event != NULL) {
+ gBS->CloseEvent (Event);
+ }
+
+ Http = HttpIo->Http;
+ if (Http != NULL) {
+ Http->Configure (Http, NULL);
+ gBS->CloseProtocol (
+ HttpIo->Handle,
+ &gEfiHttpProtocolGuid,
+ HttpIo->Image,
+ HttpIo->Controller
+ );
+ }
+
+ NetLibDestroyServiceChild (
+ HttpIo->Controller,
+ HttpIo->Image,
+ &gEfiHttpServiceBindingProtocolGuid,
+ HttpIo->Handle
+ );
+}
+
+/**
+ Synchronously send a HTTP REQUEST message to the server.
+
+ @param[in] HttpIo The HttpIo wrapping the HTTP service.
+ @param[in] Request A pointer to storage such data as URL and HTTP method.
+ @param[in] HeaderCount Number of HTTP header structures in Headers list.
+ @param[in] Headers Array containing list of HTTP headers.
+ @param[in] BodyLength Length in bytes of the HTTP body.
+ @param[in] Body Body associated with the HTTP request.
+
+ @retval EFI_SUCCESS The HTTP request is trasmitted.
+ @retval EFI_INVALID_PARAMETER One or more parameters are invalid.
+ @retval EFI_OUT_OF_RESOURCES Failed to allocate memory.
+ @retval EFI_DEVICE_ERROR An unexpected network or system error occurred.
+ @retval Others Other errors as indicated.
+
+**/
+EFI_STATUS
+HttpIoSendRequest (
+ IN HTTP_IO *HttpIo,
+ IN EFI_HTTP_REQUEST_DATA *Request,
+ IN UINTN HeaderCount,
+ IN EFI_HTTP_HEADER *Headers,
+ IN UINTN BodyLength,
+ IN VOID *Body
+ )
+{
+ EFI_STATUS Status;
+ EFI_HTTP_PROTOCOL *Http;
+
+ if (HttpIo == NULL || HttpIo->Http == NULL) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ HttpIo->ReqToken.Status = EFI_NOT_READY;
+ HttpIo->ReqToken.Message->Data.Request = Request;
+ HttpIo->ReqToken.Message->HeaderCount = HeaderCount;
+ HttpIo->ReqToken.Message->Headers = Headers;
+ HttpIo->ReqToken.Message->BodyLength = BodyLength;
+ HttpIo->ReqToken.Message->Body = Body;
+
+ //
+ // Queue the request token to HTTP instances.
+ //
+ Http = HttpIo->Http;
+ HttpIo->IsTxDone = FALSE;
+ Status = Http->Request (
+ Http,
+ &HttpIo->ReqToken
+ );
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+
+ //
+ // Poll the network until transmit finish.
+ //
+ while (!HttpIo->IsTxDone) {
+ Http->Poll (Http);
+ }
+
+ return HttpIo->ReqToken.Status;
+}
+
+/**
+ Synchronously receive a HTTP RESPONSE message from the server.
+
+ @param[in] HttpIo The HttpIo wrapping the HTTP service.
+ @param[in] RecvMsgHeader TRUE to receive a new HTTP response (from message header).
+ FALSE to continue receive the previous response message.
+ @param[out] ResponseData Point to a wrapper of the received response data.
+
+ @retval EFI_SUCCESS The HTTP resopnse is received.
+ @retval EFI_INVALID_PARAMETER One or more parameters are invalid.
+ @retval EFI_OUT_OF_RESOURCES Failed to allocate memory.
+ @retval EFI_DEVICE_ERROR An unexpected network or system error occurred.
+ @retval Others Other errors as indicated.
+
+**/
+EFI_STATUS
+HttpIoRecvResponse (
+ IN HTTP_IO *HttpIo,
+ IN BOOLEAN RecvMsgHeader,
+ OUT HTTP_IO_RESOPNSE_DATA *ResponseData
+ )
+{
+ EFI_STATUS Status;
+ EFI_HTTP_PROTOCOL *Http;
+
+ if (HttpIo == NULL || HttpIo->Http == NULL || ResponseData == NULL) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ //
+ // Queue the response token to HTTP instances.
+ //
+ HttpIo->RspToken.Status = EFI_NOT_READY;
+ if (RecvMsgHeader) {
+ HttpIo->RspToken.Message->Data.Response = &ResponseData->Response;
+ } else {
+ HttpIo->RspToken.Message->Data.Response = NULL;
+ }
+ HttpIo->RspToken.Message->HeaderCount = 0;
+ HttpIo->RspToken.Message->Headers = NULL;
+ HttpIo->RspToken.Message->BodyLength = ResponseData->BodyLength;
+ HttpIo->RspToken.Message->Body = ResponseData->Body;
+
+ Http = HttpIo->Http;
+ HttpIo->IsRxDone = FALSE;
+ Status = Http->Response (
+ Http,
+ &HttpIo->RspToken
+ );
+
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+
+ //
+ // Poll the network until transmit finish.
+ //
+ while (!HttpIo->IsRxDone) {
+ Http->Poll (Http);
+ }
+
+ //
+ // Store the received data into the wrapper.
+ //
+ Status = HttpIo->ReqToken.Status;
+ if (!EFI_ERROR (Status)) {
+ ResponseData->HeaderCount = HttpIo->RspToken.Message->HeaderCount;
+ ResponseData->Headers = HttpIo->RspToken.Message->Headers;
+ ResponseData->BodyLength = HttpIo->RspToken.Message->BodyLength;
+ }
+
+ return Status;
+}
diff --git a/NetworkPkg/HttpBootDxe/HttpBootSupport.h b/NetworkPkg/HttpBootDxe/HttpBootSupport.h index d1fa287920..bef80e81d8 100644 --- a/NetworkPkg/HttpBootDxe/HttpBootSupport.h +++ b/NetworkPkg/HttpBootDxe/HttpBootSupport.h @@ -1,250 +1,250 @@ -/** @file - Support functions declaration for UEFI HTTP boot driver. - -Copyright (c) 2015, Intel Corporation. All rights reserved.<BR> -This program and the accompanying materials are licensed and made available under -the terms and conditions of the BSD License that accompanies this distribution. -The full text of the license may be found at -http://opensource.org/licenses/bsd-license.php. - -THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, -WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. - -**/ - -#ifndef __EFI_HTTP_BOOT_SUPPORT_H__ -#define __EFI_HTTP_BOOT_SUPPORT_H__ - -/** - Get the Nic handle using any child handle in the IPv4 stack. - - @param[in] ControllerHandle Pointer to child handle over IPv4. - - @return NicHandle The pointer to the Nic handle. - @return NULL Can't find the Nic handle. - -**/ -EFI_HANDLE -HttpBootGetNicByIp4Children ( - IN EFI_HANDLE ControllerHandle - ); - -/** - This function is to convert UINTN to ASCII string with the required formatting. - - @param[in] Number Numeric value to be converted. - @param[in] Buffer The pointer to the buffer for ASCII string. - @param[in] Length The length of the required format. - -**/ -VOID -HttpBootUintnToAscDecWithFormat ( - IN UINTN Number, - IN UINT8 *Buffer, - IN INTN Length - ); - - -/** - This function is to display the IPv4 address. - - @param[in] Ip The pointer to the IPv4 address. - -**/ -VOID -HttpBootShowIp4Addr ( - IN EFI_IPv4_ADDRESS *Ip - ); - -// -// A wrapper structure to hold the HTTP headers. -// -typedef struct { - UINTN MaxHeaderCount; - UINTN HeaderCount; - EFI_HTTP_HEADER *Headers; -} HTTP_IO_HEADER; - -/** - Create a HTTP_IO_HEADER to hold the HTTP header items. - - @param[in] MaxHeaderCount The maximun number of HTTP header in this holder. - - @return A pointer of the HTTP header holder or NULL if failed. - -**/ -HTTP_IO_HEADER * -HttpBootCreateHeader ( - IN UINTN MaxHeaderCount - ); - -/** - Destroy the HTTP_IO_HEADER and release the resouces. - - @param[in] HttpIoHeader Point to the HTTP header holder to be destroyed. - -**/ -VOID -HttpBootFreeHeader ( - IN HTTP_IO_HEADER *HttpIoHeader - ); - -/** - Set or update a HTTP header with the field name and corresponding value. - - @param[in] HttpIoHeader Point to the HTTP header holder. - @param[in] FieldName Null terminated string which describes a field name. - @param[in] FieldValue Null terminated string which describes the corresponding field value. - - @retval EFI_SUCCESS The HTTP header has been set or updated. - @retval EFI_INVALID_PARAMETER Any input parameter is invalid. - @retval EFI_OUT_OF_RESOURCES Insufficient resource to complete the operation. - @retval Other Unexpected error happened. - -**/ -EFI_STATUS -HttpBootSetHeader ( - IN HTTP_IO_HEADER *HttpIoHeader, - IN CHAR8 *FieldName, - IN CHAR8 *FieldValue - ); - -// -// HTTP_IO configuration data for IPv4 -// -typedef struct { - EFI_HTTP_VERSION HttpVersion; - UINT32 RequestTimeOut; // In milliseconds. - UINT32 ResponseTimeOut; // In milliseconds. - BOOLEAN UseDefaultAddress; - EFI_IPv4_ADDRESS LocalIp; - EFI_IPv4_ADDRESS SubnetMask; - UINT16 LocalPort; -} HTTP4_IO_CONFIG_DATA; - -// -// HTTP_IO configuration -// -typedef union { - HTTP4_IO_CONFIG_DATA Config4; -} HTTP_IO_CONFIG_DATA; - -// -// HTTO_IO wrapper of the EFI HTTP service. -// -typedef struct { - UINT8 IpVersion; - EFI_HANDLE Image; - EFI_HANDLE Controller; - EFI_HANDLE Handle; - - EFI_HTTP_PROTOCOL *Http; - - EFI_HTTP_TOKEN ReqToken; - EFI_HTTP_MESSAGE ReqMessage; - EFI_HTTP_TOKEN RspToken; - EFI_HTTP_MESSAGE RspMessage; - - BOOLEAN IsTxDone; - BOOLEAN IsRxDone; -} HTTP_IO; - -// -// A wrapper structure to hold the received HTTP response data. -// -typedef struct { - EFI_HTTP_RESPONSE_DATA Response; - UINTN HeaderCount; - EFI_HTTP_HEADER *Headers; - UINTN BodyLength; - CHAR8 *Body; -} HTTP_IO_RESOPNSE_DATA; - -/** - Create a HTTP_IO to access the HTTP service. It will create and configure - a HTTP child handle. - - @param[in] Image The handle of the driver image. - @param[in] Controller The handle of the controller. - @param[in] IpVersion IP_VERSION_4 or IP_VERSION_6. - @param[in] ConfigData The HTTP_IO configuration data. - @param[out] HttpIo The HTTP_IO. - - @retval EFI_SUCCESS The HTTP_IO is created and configured. - @retval EFI_INVALID_PARAMETER One or more parameters are invalid. - @retval EFI_UNSUPPORTED One or more of the control options are not - supported in the implementation. - @retval EFI_OUT_OF_RESOURCES Failed to allocate memory. - @retval Others Failed to create the HTTP_IO or configure it. - -**/ -EFI_STATUS -HttpIoCreateIo ( - IN EFI_HANDLE Image, - IN EFI_HANDLE Controller, - IN UINT8 IpVersion, - IN HTTP_IO_CONFIG_DATA *ConfigData, - OUT HTTP_IO *HttpIo - ); - -/** - Destroy the HTTP_IO and release the resouces. - - @param[in] HttpIo The HTTP_IO which wraps the HTTP service to be destroyed. - -**/ -VOID -HttpIoDestroyIo ( - IN HTTP_IO *HttpIo - ); - -/** - Synchronously send a HTTP REQUEST message to the server. - - @param[in] HttpIo The HttpIo wrapping the HTTP service. - @param[in] Request A pointer to storage such data as URL and HTTP method. - @param[in] HeaderCount Number of HTTP header structures in Headers list. - @param[in] Headers Array containing list of HTTP headers. - @param[in] BodyLength Length in bytes of the HTTP body. - @param[in] Body Body associated with the HTTP request. - - @retval EFI_SUCCESS The HTTP request is trasmitted. - @retval EFI_INVALID_PARAMETER One or more parameters are invalid. - @retval EFI_OUT_OF_RESOURCES Failed to allocate memory. - @retval EFI_DEVICE_ERROR An unexpected network or system error occurred. - @retval Others Other errors as indicated. - -**/ -EFI_STATUS -HttpIoSendRequest ( - IN HTTP_IO *HttpIo, - IN EFI_HTTP_REQUEST_DATA *Request, OPTIONAL - IN UINTN HeaderCount, - IN EFI_HTTP_HEADER *Headers, OPTIONAL - IN UINTN BodyLength, - IN VOID *Body OPTIONAL - ); - -/** - Synchronously receive a HTTP RESPONSE message from the server. - - @param[in] HttpIo The HttpIo wrapping the HTTP service. - @param[in] RecvMsgHeader TRUE to receive a new HTTP response (from message header). - FALSE to continue receive the previous response message. - @param[out] ResponseData Point to a wrapper of the received response data. - - @retval EFI_SUCCESS The HTTP resopnse is received. - @retval EFI_INVALID_PARAMETER One or more parameters are invalid. - @retval EFI_OUT_OF_RESOURCES Failed to allocate memory. - @retval EFI_DEVICE_ERROR An unexpected network or system error occurred. - @retval Others Other errors as indicated. - -**/ -EFI_STATUS -HttpIoRecvResponse ( - IN HTTP_IO *HttpIo, - IN BOOLEAN RecvMsgHeader, - OUT HTTP_IO_RESOPNSE_DATA *ResponseData - ); - -#endif +/** @file
+ Support functions declaration for UEFI HTTP boot driver.
+
+Copyright (c) 2015, Intel Corporation. All rights reserved.<BR>
+This program and the accompanying materials are licensed and made available under
+the terms and conditions of the BSD License that accompanies this distribution.
+The full text of the license may be found at
+http://opensource.org/licenses/bsd-license.php.
+
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+**/
+
+#ifndef __EFI_HTTP_BOOT_SUPPORT_H__
+#define __EFI_HTTP_BOOT_SUPPORT_H__
+
+/**
+ Get the Nic handle using any child handle in the IPv4 stack.
+
+ @param[in] ControllerHandle Pointer to child handle over IPv4.
+
+ @return NicHandle The pointer to the Nic handle.
+ @return NULL Can't find the Nic handle.
+
+**/
+EFI_HANDLE
+HttpBootGetNicByIp4Children (
+ IN EFI_HANDLE ControllerHandle
+ );
+
+/**
+ This function is to convert UINTN to ASCII string with the required formatting.
+
+ @param[in] Number Numeric value to be converted.
+ @param[in] Buffer The pointer to the buffer for ASCII string.
+ @param[in] Length The length of the required format.
+
+**/
+VOID
+HttpBootUintnToAscDecWithFormat (
+ IN UINTN Number,
+ IN UINT8 *Buffer,
+ IN INTN Length
+ );
+
+
+/**
+ This function is to display the IPv4 address.
+
+ @param[in] Ip The pointer to the IPv4 address.
+
+**/
+VOID
+HttpBootShowIp4Addr (
+ IN EFI_IPv4_ADDRESS *Ip
+ );
+
+//
+// A wrapper structure to hold the HTTP headers.
+//
+typedef struct {
+ UINTN MaxHeaderCount;
+ UINTN HeaderCount;
+ EFI_HTTP_HEADER *Headers;
+} HTTP_IO_HEADER;
+
+/**
+ Create a HTTP_IO_HEADER to hold the HTTP header items.
+
+ @param[in] MaxHeaderCount The maximun number of HTTP header in this holder.
+
+ @return A pointer of the HTTP header holder or NULL if failed.
+
+**/
+HTTP_IO_HEADER *
+HttpBootCreateHeader (
+ IN UINTN MaxHeaderCount
+ );
+
+/**
+ Destroy the HTTP_IO_HEADER and release the resouces.
+
+ @param[in] HttpIoHeader Point to the HTTP header holder to be destroyed.
+
+**/
+VOID
+HttpBootFreeHeader (
+ IN HTTP_IO_HEADER *HttpIoHeader
+ );
+
+/**
+ Set or update a HTTP header with the field name and corresponding value.
+
+ @param[in] HttpIoHeader Point to the HTTP header holder.
+ @param[in] FieldName Null terminated string which describes a field name.
+ @param[in] FieldValue Null terminated string which describes the corresponding field value.
+
+ @retval EFI_SUCCESS The HTTP header has been set or updated.
+ @retval EFI_INVALID_PARAMETER Any input parameter is invalid.
+ @retval EFI_OUT_OF_RESOURCES Insufficient resource to complete the operation.
+ @retval Other Unexpected error happened.
+
+**/
+EFI_STATUS
+HttpBootSetHeader (
+ IN HTTP_IO_HEADER *HttpIoHeader,
+ IN CHAR8 *FieldName,
+ IN CHAR8 *FieldValue
+ );
+
+//
+// HTTP_IO configuration data for IPv4
+//
+typedef struct {
+ EFI_HTTP_VERSION HttpVersion;
+ UINT32 RequestTimeOut; // In milliseconds.
+ UINT32 ResponseTimeOut; // In milliseconds.
+ BOOLEAN UseDefaultAddress;
+ EFI_IPv4_ADDRESS LocalIp;
+ EFI_IPv4_ADDRESS SubnetMask;
+ UINT16 LocalPort;
+} HTTP4_IO_CONFIG_DATA;
+
+//
+// HTTP_IO configuration
+//
+typedef union {
+ HTTP4_IO_CONFIG_DATA Config4;
+} HTTP_IO_CONFIG_DATA;
+
+//
+// HTTO_IO wrapper of the EFI HTTP service.
+//
+typedef struct {
+ UINT8 IpVersion;
+ EFI_HANDLE Image;
+ EFI_HANDLE Controller;
+ EFI_HANDLE Handle;
+
+ EFI_HTTP_PROTOCOL *Http;
+
+ EFI_HTTP_TOKEN ReqToken;
+ EFI_HTTP_MESSAGE ReqMessage;
+ EFI_HTTP_TOKEN RspToken;
+ EFI_HTTP_MESSAGE RspMessage;
+
+ BOOLEAN IsTxDone;
+ BOOLEAN IsRxDone;
+} HTTP_IO;
+
+//
+// A wrapper structure to hold the received HTTP response data.
+//
+typedef struct {
+ EFI_HTTP_RESPONSE_DATA Response;
+ UINTN HeaderCount;
+ EFI_HTTP_HEADER *Headers;
+ UINTN BodyLength;
+ CHAR8 *Body;
+} HTTP_IO_RESOPNSE_DATA;
+
+/**
+ Create a HTTP_IO to access the HTTP service. It will create and configure
+ a HTTP child handle.
+
+ @param[in] Image The handle of the driver image.
+ @param[in] Controller The handle of the controller.
+ @param[in] IpVersion IP_VERSION_4 or IP_VERSION_6.
+ @param[in] ConfigData The HTTP_IO configuration data.
+ @param[out] HttpIo The HTTP_IO.
+
+ @retval EFI_SUCCESS The HTTP_IO is created and configured.
+ @retval EFI_INVALID_PARAMETER One or more parameters are invalid.
+ @retval EFI_UNSUPPORTED One or more of the control options are not
+ supported in the implementation.
+ @retval EFI_OUT_OF_RESOURCES Failed to allocate memory.
+ @retval Others Failed to create the HTTP_IO or configure it.
+
+**/
+EFI_STATUS
+HttpIoCreateIo (
+ IN EFI_HANDLE Image,
+ IN EFI_HANDLE Controller,
+ IN UINT8 IpVersion,
+ IN HTTP_IO_CONFIG_DATA *ConfigData,
+ OUT HTTP_IO *HttpIo
+ );
+
+/**
+ Destroy the HTTP_IO and release the resouces.
+
+ @param[in] HttpIo The HTTP_IO which wraps the HTTP service to be destroyed.
+
+**/
+VOID
+HttpIoDestroyIo (
+ IN HTTP_IO *HttpIo
+ );
+
+/**
+ Synchronously send a HTTP REQUEST message to the server.
+
+ @param[in] HttpIo The HttpIo wrapping the HTTP service.
+ @param[in] Request A pointer to storage such data as URL and HTTP method.
+ @param[in] HeaderCount Number of HTTP header structures in Headers list.
+ @param[in] Headers Array containing list of HTTP headers.
+ @param[in] BodyLength Length in bytes of the HTTP body.
+ @param[in] Body Body associated with the HTTP request.
+
+ @retval EFI_SUCCESS The HTTP request is trasmitted.
+ @retval EFI_INVALID_PARAMETER One or more parameters are invalid.
+ @retval EFI_OUT_OF_RESOURCES Failed to allocate memory.
+ @retval EFI_DEVICE_ERROR An unexpected network or system error occurred.
+ @retval Others Other errors as indicated.
+
+**/
+EFI_STATUS
+HttpIoSendRequest (
+ IN HTTP_IO *HttpIo,
+ IN EFI_HTTP_REQUEST_DATA *Request, OPTIONAL
+ IN UINTN HeaderCount,
+ IN EFI_HTTP_HEADER *Headers, OPTIONAL
+ IN UINTN BodyLength,
+ IN VOID *Body OPTIONAL
+ );
+
+/**
+ Synchronously receive a HTTP RESPONSE message from the server.
+
+ @param[in] HttpIo The HttpIo wrapping the HTTP service.
+ @param[in] RecvMsgHeader TRUE to receive a new HTTP response (from message header).
+ FALSE to continue receive the previous response message.
+ @param[out] ResponseData Point to a wrapper of the received response data.
+
+ @retval EFI_SUCCESS The HTTP resopnse is received.
+ @retval EFI_INVALID_PARAMETER One or more parameters are invalid.
+ @retval EFI_OUT_OF_RESOURCES Failed to allocate memory.
+ @retval EFI_DEVICE_ERROR An unexpected network or system error occurred.
+ @retval Others Other errors as indicated.
+
+**/
+EFI_STATUS
+HttpIoRecvResponse (
+ IN HTTP_IO *HttpIo,
+ IN BOOLEAN RecvMsgHeader,
+ OUT HTTP_IO_RESOPNSE_DATA *ResponseData
+ );
+
+#endif
|