]> git.proxmox.com Git - mirror_edk2.git/commitdiff
NetworkPkg: Convert the UNIX to DOS end of line format
authorJiaxin Wu <jiaxin.wu@intel.com>
Thu, 27 Aug 2015 01:07:31 +0000 (01:07 +0000)
committerjiaxinwu <jiaxinwu@Edk2>
Thu, 27 Aug 2015 01:07:31 +0000 (01:07 +0000)
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

18 files changed:
NetworkPkg/HttpBootDxe/HttpBootClient.c
NetworkPkg/HttpBootDxe/HttpBootClient.h
NetworkPkg/HttpBootDxe/HttpBootComponentName.c
NetworkPkg/HttpBootDxe/HttpBootComponentName.h
NetworkPkg/HttpBootDxe/HttpBootDhcp4.c
NetworkPkg/HttpBootDxe/HttpBootDhcp4.h
NetworkPkg/HttpBootDxe/HttpBootDxe.c
NetworkPkg/HttpBootDxe/HttpBootDxe.h
NetworkPkg/HttpBootDxe/HttpBootDxe.inf
NetworkPkg/HttpBootDxe/HttpBootImpl.c
NetworkPkg/HttpBootDxe/HttpBootImpl.h
NetworkPkg/HttpBootDxe/HttpBootSupport.c
NetworkPkg/HttpBootDxe/HttpBootSupport.h
NetworkPkg/HttpUtilitiesDxe/HttpUtilitiesDxe.c
NetworkPkg/HttpUtilitiesDxe/HttpUtilitiesDxe.h
NetworkPkg/HttpUtilitiesDxe/HttpUtilitiesDxe.inf
NetworkPkg/HttpUtilitiesDxe/HttpUtilitiesImpl.c
NetworkPkg/HttpUtilitiesDxe/HttpUtilitiesProtocol.c

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