Revision: 17857
          http://sourceforge.net/p/edk2/code/17857
Author:   sfu5
Date:     2015-07-07 09:29:28 +0000 (Tue, 07 Jul 2015)
Log Message:
-----------
NetworkPkg: Add UEFI HTTP boot driver.

This patch add the implementation for UEFI HTTP boot driver.

Contributed-under: TianoCore Contribution Agreement 1.0
Signed-off-by: Fu Siyuan <siyuan...@intel.com>
Reviewed-by: Ye Ting <ting...@intel.com>

Added Paths:
-----------
    trunk/edk2/NetworkPkg/HttpBootDxe/
    trunk/edk2/NetworkPkg/HttpBootDxe/HttpBootClient.c
    trunk/edk2/NetworkPkg/HttpBootDxe/HttpBootClient.h
    trunk/edk2/NetworkPkg/HttpBootDxe/HttpBootComponentName.c
    trunk/edk2/NetworkPkg/HttpBootDxe/HttpBootComponentName.h
    trunk/edk2/NetworkPkg/HttpBootDxe/HttpBootDhcp4.c
    trunk/edk2/NetworkPkg/HttpBootDxe/HttpBootDhcp4.h
    trunk/edk2/NetworkPkg/HttpBootDxe/HttpBootDxe.c
    trunk/edk2/NetworkPkg/HttpBootDxe/HttpBootDxe.h
    trunk/edk2/NetworkPkg/HttpBootDxe/HttpBootDxe.inf
    trunk/edk2/NetworkPkg/HttpBootDxe/HttpBootDxe.uni
    trunk/edk2/NetworkPkg/HttpBootDxe/HttpBootDxeExtra.uni
    trunk/edk2/NetworkPkg/HttpBootDxe/HttpBootImpl.c
    trunk/edk2/NetworkPkg/HttpBootDxe/HttpBootImpl.h
    trunk/edk2/NetworkPkg/HttpBootDxe/HttpBootSupport.c
    trunk/edk2/NetworkPkg/HttpBootDxe/HttpBootSupport.h

Added: trunk/edk2/NetworkPkg/HttpBootDxe/HttpBootClient.c
===================================================================
--- trunk/edk2/NetworkPkg/HttpBootDxe/HttpBootClient.c                          
(rev 0)
+++ trunk/edk2/NetworkPkg/HttpBootDxe/HttpBootClient.c  2015-07-07 09:29:28 UTC 
(rev 17857)
@@ -0,0 +1,830 @@
+/** @file
+  Implementation of the boot file download function.
+
+Copyright (c) 2015, Intel Corporation. All rights reserved.<BR>
+This program and the accompanying materials are licensed and made available 
under 
+the terms and conditions of the BSD License that accompanies this 
distribution.  
+The full text of the license may be found at
+http://opensource.org/licenses/bsd-license.php.                                
          
+    
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,          
           
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+**/
+
+#include "HttpBootDxe.h"
+
+/**
+  Update the IP and URL device path node to include the boot resource 
information.
+
+  @param[in]    Private            The pointer to the driver's private data.
+
+  @retval EFI_SUCCESS              Device patch successfully updated.
+  @retval EFI_OUT_OF_RESOURCES     Could not allocate needed resources.
+  @retval Others                   Unexpected error happened.
+  
+**/
+EFI_STATUS
+HttpBootUpdateDevicePath (
+  IN   HTTP_BOOT_PRIVATE_DATA   *Private
+  )
+{
+  EFI_DEV_PATH               *Node;
+  EFI_DEVICE_PATH_PROTOCOL   *TmpDevicePath;
+  EFI_DEVICE_PATH_PROTOCOL   *NewDevicePath;
+  UINTN                      Length;
+  EFI_STATUS                 Status;
+
+  TmpDevicePath = NULL;
+  
+  //
+  // Update the IP node with DHCP assigned information.
+  //
+  if (!Private->UsingIpv6) {
+    Node = AllocateZeroPool (sizeof (IPv4_DEVICE_PATH));
+    if (Node == NULL) {
+      return EFI_OUT_OF_RESOURCES;
+    }
+    Node->Ipv4.Header.Type    = MESSAGING_DEVICE_PATH;
+    Node->Ipv4.Header.SubType = MSG_IPv4_DP;
+    SetDevicePathNodeLength (Node, sizeof (IPv4_DEVICE_PATH));
+    CopyMem (&Node->Ipv4.LocalIpAddress, &Private->StationIp, sizeof 
(EFI_IPv4_ADDRESS));
+    Node->Ipv4.RemotePort      = Private->Port;
+    Node->Ipv4.Protocol        = EFI_IP_PROTO_TCP;
+    Node->Ipv4.StaticIpAddress = FALSE;
+    CopyMem (&Node->Ipv4.GatewayIpAddress, &Private->GatewayIp, sizeof 
(EFI_IPv4_ADDRESS));
+    CopyMem (&Node->Ipv4.SubnetMask, &Private->SubnetMask, sizeof 
(EFI_IPv4_ADDRESS));
+    
+    TmpDevicePath = AppendDevicePathNode (Private->ParentDevicePath, 
(EFI_DEVICE_PATH_PROTOCOL*) Node);
+    FreePool (Node);
+    if (TmpDevicePath == NULL) {
+      return EFI_OUT_OF_RESOURCES;
+    }
+  } else {
+    ASSERT (FALSE);
+  }
+
+  //
+  // Update the URI node with the boot file URI.
+  //
+  Length = sizeof (EFI_DEVICE_PATH_PROTOCOL) + AsciiStrSize 
(Private->BootFileUri);
+  Node = AllocatePool (Length);
+  if (Node == NULL) {
+    FreePool (TmpDevicePath);
+    return EFI_OUT_OF_RESOURCES;
+  }
+  Node->DevPath.Type    = MESSAGING_DEVICE_PATH;
+  Node->DevPath.SubType = MSG_URI_DP;
+  SetDevicePathNodeLength (Node, Length);
+  CopyMem ((UINT8*) Node + sizeof (EFI_DEVICE_PATH_PROTOCOL), 
Private->BootFileUri, AsciiStrSize (Private->BootFileUri));
+  
+  NewDevicePath = AppendDevicePathNode (TmpDevicePath, 
(EFI_DEVICE_PATH_PROTOCOL*) Node);
+  FreePool (Node);
+  FreePool (TmpDevicePath);
+  if (NewDevicePath == NULL) {
+    return EFI_OUT_OF_RESOURCES;
+  }
+
+  //
+  // Reinstall the device path protocol of the child handle.
+  //
+  Status = gBS->ReinstallProtocolInterface (
+                  Private->ChildHandle,
+                  &gEfiDevicePathProtocolGuid,
+                  Private->DevicePath,
+                  NewDevicePath
+                  );
+  if (EFI_ERROR (Status)) {
+    return Status;
+  }
+  
+  FreePool (Private->DevicePath);
+  Private->DevicePath = NewDevicePath;
+  return EFI_SUCCESS;
+}
+
+/**
+  Parse the boot file URI information from the selected Dhcp4 offer packet.
+
+  @param[in]    Private        The pointer to the driver's private data.
+
+  @retval EFI_SUCCESS          Successfully parsed out all the boot 
information.
+  @retval Others               Failed to parse out the boot information.
+
+**/
+EFI_STATUS
+HttpBootExtractUriInfo (
+  IN     HTTP_BOOT_PRIVATE_DATA   *Private
+  )
+{
+  HTTP_BOOT_DHCP4_PACKET_CACHE    *SelectOffer;
+  HTTP_BOOT_DHCP4_PACKET_CACHE    *HttpOffer;
+  UINT32                          SelectIndex;
+  UINT32                          ProxyIndex;
+  EFI_DHCP4_PACKET_OPTION         *Option;
+  EFI_STATUS                      Status;
+
+  ASSERT (Private != NULL);
+  ASSERT (Private->SelectIndex != 0);
+  SelectIndex = Private->SelectIndex - 1;
+  ASSERT (SelectIndex < HTTP_BOOT_OFFER_MAX_NUM);
+
+  Status = EFI_SUCCESS;
+
+  //
+  // SelectOffer contains the IP address configuration and name server 
configuration.
+  // HttpOffer contains the boot file URL.
+  //
+  SelectOffer = &Private->OfferBuffer[SelectIndex].Dhcp4;
+  if ((SelectOffer->OfferType == HttpOfferTypeDhcpIpUri) || 
(SelectOffer->OfferType == HttpOfferTypeDhcpNameUriDns)) {
+    HttpOffer = SelectOffer;
+  } else {
+    ASSERT (Private->SelectProxyType != HttpOfferTypeMax);
+    ProxyIndex = Private->OfferIndex[Private->SelectProxyType][0];
+    HttpOffer = &Private->OfferBuffer[ProxyIndex].Dhcp4;
+  }
+
+  //
+  // Configure the default DNS server if server assigned.
+  //
+  if ((SelectOffer->OfferType == HttpOfferTypeDhcpNameUriDns) || 
(SelectOffer->OfferType == HttpOfferTypeDhcpDns)) {
+    Option = SelectOffer->OptList[HTTP_BOOT_DHCP4_TAG_INDEX_DNS_SERVER];
+    ASSERT (Option != NULL);
+    Status = HttpBootRegisterIp4Dns (
+               Private,
+               Option->Length,
+               Option->Data
+               );
+    if (EFI_ERROR (Status)) {
+      return Status;
+    }
+  }
+
+  //
+  // Extract the port from URL, and use default HTTP port 80 if not provided.
+  //
+  Status = HttpUrlGetPort (
+             (CHAR8*) 
HttpOffer->OptList[HTTP_BOOT_DHCP4_TAG_INDEX_BOOTFILE]->Data,
+             HttpOffer->UriParser,
+             &Private->Port
+             );
+  if (EFI_ERROR (Status) || Private->Port == 0) {
+    Private->Port = 80;
+  }
+  
+  //
+  // Record the URI of boot file from the selected HTTP offer.
+  //
+  Private->BootFileUriParser = HttpOffer->UriParser;
+  Private->BootFileUri = (CHAR8*) 
HttpOffer->OptList[HTTP_BOOT_DHCP4_TAG_INDEX_BOOTFILE]->Data;
+
+  
+  //
+  // All boot informations are valid here.
+  //
+  AsciiPrint ("\n  URI: %a", Private->BootFileUri);
+
+  //
+  // Update the device path to include the IP and boot URI information.
+  //
+  Status = HttpBootUpdateDevicePath (Private);
+
+  return Status;
+}
+
+/**
+  Discover all the boot information for boot file.
+
+  @param[in, out]    Private        The pointer to the driver's private data.
+
+  @retval EFI_SUCCESS          Successfully obtained all the boot information .
+  @retval Others               Failed to retrieve the boot information.
+
+**/
+EFI_STATUS
+HttpBootDiscoverBootInfo (
+  IN OUT HTTP_BOOT_PRIVATE_DATA   *Private
+  )
+{
+  EFI_STATUS              Status;
+  
+  //
+  // Start D.O.R.A/S.A.R.R exchange to acquire station ip address and
+  // other Http boot information.
+  //
+  Status = HttpBootDhcp (Private);
+  if (EFI_ERROR (Status)) {
+    return Status;
+  }
+
+  if (!Private->UsingIpv6) {
+    Status = HttpBootExtractUriInfo (Private);
+  } else {
+    ASSERT (FALSE);
+  }
+
+  return Status;
+}
+
+/**
+  Create a HttpIo instance for the file download.
+
+  @param[in]    Private        The pointer to the driver's private data.
+
+  @retval EFI_SUCCESS          Successfully created.
+  @retval Others               Failed to create HttpIo.
+
+**/
+EFI_STATUS
+HttpBootCreateHttpIo (
+  IN     HTTP_BOOT_PRIVATE_DATA       *Private
+  )
+{
+  HTTP_IO_CONFIG_DATA          ConfigData;
+  EFI_STATUS                   Status;
+
+  ASSERT (Private != NULL);
+
+  ZeroMem (&ConfigData, sizeof (HTTP_IO_CONFIG_DATA));
+  if (!Private->UsingIpv6) {
+    ConfigData.Config4.HttpVersion = HttpVersion11;
+    ConfigData.Config4.RequestTimeOut = HTTP_BOOT_REQUEST_TIMEOUT;
+    IP4_COPY_ADDRESS (&ConfigData.Config4.LocalIp, &Private->StationIp.v4);
+    IP4_COPY_ADDRESS (&ConfigData.Config4.SubnetMask, &Private->SubnetMask.v4);
+  } else {
+    ASSERT (FALSE);
+  }
+
+  Status = HttpIoCreateIo (
+             Private->Image,
+             Private->Controller,
+             Private->UsingIpv6 ? IP_VERSION_6 : IP_VERSION_4,
+             &ConfigData,
+             &Private->HttpIo
+             );
+  if (EFI_ERROR (Status)) {
+    return Status;
+  }
+
+  Private->HttpCreated = TRUE;
+  return EFI_SUCCESS;
+}
+
+/**
+  Get the file content from cached data.
+
+  @param[in]          Private         The pointer to the driver's private data.
+  @param[in]          Uri             Uri of the file to be retrieved from 
cache.
+  @param[in, out]     BufferSize      On input the size of Buffer in bytes. On 
output with a return
+                                      code of EFI_SUCCESS, the amount of data 
transferred to
+                                      Buffer. On output with a return code of 
EFI_BUFFER_TOO_SMALL,
+                                      the size of Buffer required to retrieve 
the requested file.
+  @param[out]         Buffer          The memory buffer to transfer the file 
to. IF Buffer is NULL,
+                                      then the size of the requested file is 
returned in
+                                      BufferSize.
+
+  @retval EFI_SUCCESS          Successfully created.
+  @retval Others               Failed to create HttpIo.
+
+**/
+EFI_STATUS
+HttpBootGetFileFromCache (
+  IN     HTTP_BOOT_PRIVATE_DATA   *Private,
+  IN     CHAR16                   *Uri,
+  IN OUT UINTN                    *BufferSize,
+     OUT UINT8                    *Buffer
+  )
+{
+  LIST_ENTRY                  *Entry;
+  LIST_ENTRY                  *Entry2;
+  HTTP_BOOT_CACHE_CONTENT     *Cache;
+  HTTP_BOOT_ENTITY_DATA       *EntityData;
+  UINTN                       CopyedSize;
+  
+  if (Uri == NULL || BufferSize == 0 || Buffer == NULL) {
+    return EFI_INVALID_PARAMETER;
+  }
+
+  NET_LIST_FOR_EACH (Entry, &Private->CacheList) {
+    Cache = NET_LIST_USER_STRUCT (Entry, HTTP_BOOT_CACHE_CONTENT, Link);
+    //
+    // Compare the URI to see whether we already have a cache for this file.
+    //
+    if ((Cache->RequestData != NULL) &&
+        (Cache->RequestData->Url != NULL) &&
+        (StrCmp (Uri, Cache->RequestData->Url) == 0)) 
+    {
+      //
+      // Hit cache, check buffer size.
+      //
+      if (*BufferSize < Cache->EntityLength) {
+        *BufferSize = Cache->EntityLength;
+        return EFI_BUFFER_TOO_SMALL;
+      }
+
+      //
+      // Fill data to buffer.
+      //
+      CopyedSize = 0;
+      NET_LIST_FOR_EACH (Entry2, &Cache->EntityDataList) {
+        EntityData = NET_LIST_USER_STRUCT (Entry2, HTTP_BOOT_ENTITY_DATA, 
Link);
+        if (*BufferSize > CopyedSize) {
+          CopyMem (
+            Buffer + CopyedSize,
+            EntityData->DataStart,
+            MIN (EntityData->DataLength, *BufferSize - CopyedSize)
+            );
+          CopyedSize += MIN (EntityData->DataLength, *BufferSize - CopyedSize);
+        }
+      }
+      *BufferSize = CopyedSize;
+      return EFI_SUCCESS;
+    }
+  }
+
+  return EFI_NOT_FOUND;
+}
+
+/**
+  Release all the resource of a cache item.
+
+  @param[in]          Cache         The pointer to the cache item.
+
+**/
+VOID
+HttpBootFreeCache (
+  IN  HTTP_BOOT_CACHE_CONTENT    *Cache
+  )
+{
+  UINTN                       Index;
+  LIST_ENTRY                  *Entry;
+  LIST_ENTRY                  *NextEntry;
+  HTTP_BOOT_ENTITY_DATA       *EntityData;
+
+  if (Cache != NULL) {
+    //
+    // Free the request data
+    //
+    if (Cache->RequestData != NULL) {
+      if (Cache->RequestData->Url != NULL) {
+        FreePool (Cache->RequestData->Url);
+      }
+      FreePool (Cache->RequestData);
+    }
+
+    //
+    // Free the response header
+    //
+    if (Cache->ResponseData != NULL) {
+      if (Cache->ResponseData->Headers != NULL) {
+        for (Index = 0; Index < Cache->ResponseData->HeaderCount; Index++) {
+          FreePool (Cache->ResponseData->Headers[Index].FieldName);
+          FreePool (Cache->ResponseData->Headers[Index].FieldValue);
+        }
+        FreePool (Cache->ResponseData->Headers);
+      }
+    }
+
+    //
+    // Free the response body
+    //
+    NET_LIST_FOR_EACH_SAFE (Entry, NextEntry, &Cache->EntityDataList) {
+      EntityData = NET_LIST_USER_STRUCT (Entry, HTTP_BOOT_ENTITY_DATA, Link);
+      if (EntityData->Block != NULL) {
+        FreePool (EntityData->Block);
+      }
+      RemoveEntryList (&EntityData->Link);
+      FreePool (EntityData);
+    }
+
+    FreePool (Cache);
+  }
+}
+
+/**
+  Clean up all cached data.
+
+  @param[in]          Private         The pointer to the driver's private data.
+
+**/
+VOID
+HttpBootFreeCacheList (
+  IN     HTTP_BOOT_PRIVATE_DATA   *Private
+  )
+{
+  LIST_ENTRY                  *Entry;
+  LIST_ENTRY                  *NextEntry;
+  HTTP_BOOT_CACHE_CONTENT     *Cache;
+  
+  NET_LIST_FOR_EACH_SAFE (Entry, NextEntry, &Private->CacheList) {
+    Cache = NET_LIST_USER_STRUCT (Entry, HTTP_BOOT_CACHE_CONTENT, Link);
+    RemoveEntryList (&Cache->Link);
+    HttpBootFreeCache (Cache);
+  }
+}
+
+/**
+  A callback function to intercept events during message parser.
+
+  This function will be invoked during HttpParseMessageBody() with various 
events type. An error
+  return status of the callback function will cause the HttpParseMessageBody() 
aborted.
+
+  @param[in]    EventType          Event type of this callback call.
+  @param[in]    Data               A pointer to data buffer.
+  @param[in]    Length             Length in bytes of the Data.
+  @param[in]    Context            Callback context set by HttpInitMsgParser().
+
+  @retval EFI_SUCCESS              Continue to parser the message body.
+  @retval Others                   Abort the parse.
+ 
+**/
+EFI_STATUS
+EFIAPI
+HttpBootGetBootFileCallback (
+  IN HTTP_BODY_PARSE_EVENT      EventType,
+  IN CHAR8                      *Data,
+  IN UINTN                      Length,
+  IN VOID                       *Context
+  )
+{
+  HTTP_BOOT_CALLBACK_DATA      *CallbackData;
+  HTTP_BOOT_ENTITY_DATA        *NewEntityData;
+
+  //
+  // We only care about the entity data.
+  //
+  if (EventType != BodyParseEventOnData) {
+    return EFI_SUCCESS;
+  }
+
+  CallbackData = (HTTP_BOOT_CALLBACK_DATA *) Context;
+
+  //
+  // Save the data into cache list.
+  //
+  NewEntityData = AllocatePool (sizeof (HTTP_BOOT_ENTITY_DATA));
+  if (NewEntityData == NULL) {
+    return EFI_OUT_OF_RESOURCES;
+  }
+  if (CallbackData->NewBlock) {
+    NewEntityData->Block = CallbackData->Block;
+    CallbackData->Block = NULL;
+  }
+  NewEntityData->DataLength = Length;
+  NewEntityData->DataStart  = (UINT8*) Data;
+  InsertTailList (&CallbackData->Cache->EntityDataList, &NewEntityData->Link);
+
+  //
+  // Copy data if caller has provided a buffer.
+  //
+  if (CallbackData->BufferSize > CallbackData->CopyedSize) {
+    CopyMem (
+      CallbackData->Buffer + CallbackData->CopyedSize,
+      Data,
+      MIN (Length, CallbackData->BufferSize - CallbackData->CopyedSize)
+      );
+    CallbackData->CopyedSize += MIN (Length, CallbackData->BufferSize - 
CallbackData->CopyedSize);
+  }
+
+  return EFI_SUCCESS;
+}
+
+/**
+  This function download the boot file by using UEFI HTTP protocol.
+  
+  @param[in]       Private         The pointer to the driver's private data.
+  @param[in]       HeaderOnly      Only request the response header, it could 
save a lot of time if
+                                   the caller only want to know the size of 
the requested file.
+  @param[in, out]  BufferSize      On input the size of Buffer in bytes. On 
output with a return
+                                   code of EFI_SUCCESS, the amount of data 
transferred to
+                                   Buffer. On output with a return code of 
EFI_BUFFER_TOO_SMALL,
+                                   the size of Buffer required to retrieve the 
requested file.
+  @param[out]      Buffer          The memory buffer to transfer the file to. 
IF Buffer is NULL,
+                                   then the size of the requested file is 
returned in
+                                   BufferSize.
+
+  @retval EFI_SUCCESS              The file was loaded.
+  @retval EFI_INVALID_PARAMETER    BufferSize is NULL or Buffer Size is not 
NULL but Buffer is NULL.
+  @retval EFI_OUT_OF_RESOURCES     Could not allocate needed resources
+  @retval EFI_BUFFER_TOO_SMALL     The BufferSize is too small to read the 
current directory entry.
+                                   BufferSize has been updated with the size 
needed to complete
+                                   the request.
+  @retval Others                   Unexpected error happened.
+
+**/
+EFI_STATUS
+HttpBootGetBootFile (
+  IN     HTTP_BOOT_PRIVATE_DATA   *Private,
+  IN     BOOLEAN                  HeaderOnly,
+  IN OUT UINTN                    *BufferSize,
+     OUT UINT8                    *Buffer
+  )
+{
+  EFI_STATUS                 Status;
+  CHAR8                      *HostName;
+  EFI_HTTP_REQUEST_DATA      *RequestData;
+  HTTP_IO_RESOPNSE_DATA      *ResponseData;
+  HTTP_IO_RESOPNSE_DATA      ResponseBody;
+  HTTP_IO                    *HttpIo;
+  HTTP_IO_HEADER             *HttpIoHeader;
+  VOID                       *Parser;
+  HTTP_BOOT_CALLBACK_DATA    Context;
+  UINTN                      ContentLength;
+  HTTP_BOOT_CACHE_CONTENT    *Cache;
+  UINT8                      *Block;
+  CHAR16                     *Url;
+  
+  ASSERT (Private != NULL);
+  ASSERT (Private->HttpCreated);
+
+  if (BufferSize == NULL) {
+    return EFI_INVALID_PARAMETER;
+  }
+
+  if (*BufferSize != 0 && Buffer == NULL) {
+    return EFI_INVALID_PARAMETER;
+  }
+
+  //
+  // First, check whether we already cached the requested Uri.
+  //
+  Url = AllocatePool ((AsciiStrLen (Private->BootFileUri) + 1) * sizeof 
(CHAR16));
+  if (Url == NULL) {
+    return EFI_OUT_OF_RESOURCES;
+  }
+  AsciiStrToUnicodeStr (Private->BootFileUri, Url);
+  if (!HeaderOnly) {
+    Status = HttpBootGetFileFromCache (Private, Url, BufferSize, Buffer);
+    if (Status != EFI_NOT_FOUND) {
+      FreePool (Url);
+      return Status;
+    }
+  }
+
+  //
+  // Not found in cache, try to download it through HTTP.
+  //
+
+  //
+  // 1. Create a temp cache item for the requested URI.
+  //
+  Cache = NULL;
+  if (!HeaderOnly) {
+    Cache = AllocateZeroPool (sizeof (HTTP_BOOT_CACHE_CONTENT));
+    if (Cache == NULL) {
+      Status = EFI_OUT_OF_RESOURCES;
+      goto ERROR_1;
+    }
+    InitializeListHead (&Cache->EntityDataList);
+  }
+
+  //
+  // 2. Send HTTP request message.
+  //
+
+  //
+  // 2.1 Build HTTP header for the request, 3 header is needed to download a 
boot file:
+  //       Host
+  //       Accept
+  //       User-Agent
+  //
+  HttpIoHeader = HttpBootCreateHeader (3);
+  if (HttpIoHeader == NULL) {
+    Status = EFI_OUT_OF_RESOURCES;
+    goto ERROR_2;
+  }
+
+  //
+  // Add HTTP header field 1: Host
+  //
+  HostName = NULL;
+  Status = HttpUrlGetHostName (
+             Private->BootFileUri,
+             Private->BootFileUriParser,
+             &HostName
+             );
+  if (EFI_ERROR (Status)) {
+    goto ERROR_3;
+  }
+  Status = HttpBootSetHeader (
+             HttpIoHeader,
+             HTTP_FIELD_NAME_HOST,
+             HostName
+             );
+  FreePool (HostName);
+  if (EFI_ERROR (Status)) {
+    goto ERROR_3;
+  }
+
+  //
+  // Add HTTP header field 2: Accept
+  //
+  Status = HttpBootSetHeader (
+             HttpIoHeader,
+             HTTP_FIELD_NAME_ACCEPT,
+             "*/*"
+             );
+  if (EFI_ERROR (Status)) {
+    goto ERROR_3;
+  }
+
+  //
+  // Add HTTP header field 3: User-Agent
+  //
+  Status = HttpBootSetHeader (
+             HttpIoHeader,
+             HTTP_FIELD_NAME_USER_AGENT,
+             HTTP_USER_AGENT_EFI_HTTP_BOOT
+             );
+  if (EFI_ERROR (Status)) {
+    goto ERROR_3;
+  }
+
+  //
+  // 2.2 Build the rest of HTTP request info.
+  //
+  RequestData = AllocatePool (sizeof (EFI_HTTP_REQUEST_DATA));
+  if (RequestData == NULL) {
+    Status = EFI_OUT_OF_RESOURCES;
+    goto ERROR_3;
+  }
+  RequestData->Method = HeaderOnly ? HttpMethodHead : HttpMethodGet;
+  RequestData->Url = Url;
+  if (RequestData->Url == NULL) {
+    Status = EFI_OUT_OF_RESOURCES;
+    goto ERROR_4;
+  }
+  AsciiStrToUnicodeStr (Private->BootFileUri, RequestData->Url);
+
+  //
+  // 2.3 Record the request info in a temp cache item.
+  //
+  if (!HeaderOnly) {
+    Cache->RequestData = RequestData;
+  }
+
+  //
+  // 2.4 Send out the request to HTTP server.
+  //
+  HttpIo = &Private->HttpIo;
+  Status = HttpIoSendRequest (
+             HttpIo,
+             RequestData,
+             HttpIoHeader->HeaderCount,
+             HttpIoHeader->Headers,
+             0,
+             NULL
+            );
+  if (EFI_ERROR (Status)) {
+    goto ERROR_4;
+  }
+
+  //
+  // 3. Receive HTTP response message.
+  //
+
+  //
+  // 3.1 First step, use zero BodyLength to only receive the response headers.
+  //
+  ResponseData = AllocateZeroPool (sizeof(HTTP_IO_RESOPNSE_DATA));
+  if (ResponseData == NULL) {
+    Status = EFI_OUT_OF_RESOURCES;
+    goto ERROR_4;
+  }
+  Status = HttpIoRecvResponse (
+             &Private->HttpIo,
+             TRUE,
+             ResponseData
+             );
+  if (EFI_ERROR (Status)) {
+    goto ERROR_5;
+  }
+
+  //
+  // 3.2 Cache the response header.
+  //
+  if (!HeaderOnly) {
+    Cache->ResponseData = ResponseData;
+  }
+  
+  //
+  // 3.3 Init a message-body parser from the header information.
+  //
+  Parser = NULL;
+  Context.NewBlock   = FALSE;
+  Context.Block      = NULL;
+  Context.CopyedSize = 0;
+  Context.Buffer     = Buffer;
+  Context.BufferSize = *BufferSize;
+  Context.Cache      = Cache;
+  Status = HttpInitMsgParser (
+             HeaderOnly? HttpMethodHead : HttpMethodGet,
+             ResponseData->Response.StatusCode,
+             ResponseData->HeaderCount,
+             ResponseData->Headers,
+             HttpBootGetBootFileCallback,
+             (VOID*) &Context,
+             &Parser
+             );
+  if (EFI_ERROR (Status)) {
+    goto ERROR_6;
+  }
+
+  //
+  // 3.4 Continue to receive and parse message-body if needed.
+  //
+  if (!HeaderOnly) {
+    ZeroMem (&ResponseBody, sizeof (HTTP_IO_RESOPNSE_DATA));
+    while (!HttpIsMessageComplete (Parser)) {
+      //
+      // Allocate a new block to hold the message-body.
+      //
+      Block = AllocatePool (HTTP_BOOT_BLOCK_SIZE);
+      if (Block == NULL) {
+        Status = EFI_OUT_OF_RESOURCES;
+        goto ERROR_6;
+      }
+      ResponseBody.Body       = (CHAR8*) Block;
+      ResponseBody.BodyLength = HTTP_BOOT_BLOCK_SIZE;
+      Status = HttpIoRecvResponse (
+                 &Private->HttpIo,
+                 FALSE,
+                 &ResponseBody
+                 );
+      if (EFI_ERROR (Status)) {
+        goto ERROR_6;
+      }
+
+      //
+      // Parse the new received block of the message-body, the block will be 
saved in cache.
+      //
+      Context.NewBlock = TRUE;
+      Context.Block    = Block;
+      Status = HttpParseMessageBody (
+                 Parser,
+                 ResponseBody.BodyLength,
+                 ResponseBody.Body
+                 );
+      if (EFI_ERROR (Status)) {
+        goto ERROR_6;
+      }
+    }
+  }
+  
+  //
+  // 3.5 Message-body receive & parse is completed, get the file size.
+  //
+  Status = HttpGetEntityLength (Parser, &ContentLength);
+  if (EFI_ERROR (Status)) {
+    goto ERROR_6;
+  }
+
+  if (*BufferSize < ContentLength) {
+    Status = EFI_BUFFER_TOO_SMALL;
+  }
+  *BufferSize = ContentLength;
+
+  //
+  // 4. Save the cache item to driver's cache list and return.
+  //
+  if (!HeaderOnly) {
+    Cache->EntityLength = ContentLength;
+    InsertTailList (&Private->CacheList, &Cache->Link);
+  }
+
+  if (Parser != NULL) {
+    HttpFreeMsgParser (Parser);
+  }
+
+  return EFI_SUCCESS;
+  
+ERROR_6:
+  if (Parser != NULL) {
+    HttpFreeMsgParser (Parser);
+  }
+  if (Context.Block != NULL) {
+    FreePool (Context.Block);
+  }
+  HttpBootFreeCache (Cache);
+  
+ERROR_5:
+  if (ResponseData != NULL) {
+    FreePool (ResponseData);
+  }
+ERROR_4:
+  if (RequestData != NULL) {
+    FreePool (RequestData);
+  }
+ERROR_3:
+  HttpBootFreeHeader (HttpIoHeader);
+ERROR_2:
+  if (Cache != NULL) {
+    FreePool (Cache);
+  }
+ERROR_1:
+  if (Url != NULL) {
+    FreePool (Url);
+  }
+
+  return Status;
+}

Added: trunk/edk2/NetworkPkg/HttpBootDxe/HttpBootClient.h
===================================================================
--- trunk/edk2/NetworkPkg/HttpBootDxe/HttpBootClient.h                          
(rev 0)
+++ trunk/edk2/NetworkPkg/HttpBootDxe/HttpBootClient.h  2015-07-07 09:29:28 UTC 
(rev 17857)
@@ -0,0 +1,139 @@
+/** @file
+  Declaration of the boot file download function.
+
+Copyright (c) 2015, Intel Corporation. All rights reserved.<BR>
+This program and the accompanying materials are licensed and made available 
under 
+the terms and conditions of the BSD License that accompanies this 
distribution.  
+The full text of the license may be found at
+http://opensource.org/licenses/bsd-license.php.                                
          
+    
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,          
           
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+**/
+
+#ifndef __EFI_HTTP_BOOT_HTTP_H__
+#define __EFI_HTTP_BOOT_HTTP_H__
+
+#define HTTP_BOOT_REQUEST_TIMEOUT            5000      // 5 seconds in uints 
of millisecond.
+#define HTTP_BOOT_BLOCK_SIZE                 1024
+
+#define HTTP_FIELD_NAME_USER_AGENT           "User-Agent"
+#define HTTP_FIELD_NAME_HOST                 "Host"
+#define HTTP_FIELD_NAME_ACCEPT               "Accept"
+
+
+#define HTTP_USER_AGENT_EFI_HTTP_BOOT        "UefiHttpBoot/1.0"
+
+//
+// Record the data length and start address of a data block.
+//
+typedef struct {
+  LIST_ENTRY                 Link;        // Link to the EntityDataList in 
HTTP_BOOT_CACHE_CONTENT
+  UINT8                      *Block;      // If NULL, the data is in previous 
data block.
+  UINT8                      *DataStart;  // Point to somewhere in the Block
+  UINTN                      DataLength;
+} HTTP_BOOT_ENTITY_DATA;
+
+//
+// Structure for a cache item
+//
+typedef struct {
+  LIST_ENTRY                 Link;            // Link to the CacheList in 
driver's private data.
+  EFI_HTTP_REQUEST_DATA      *RequestData;
+  HTTP_IO_RESOPNSE_DATA      *ResponseData;   // Not include any message-body 
data.
+  UINTN                      EntityLength;
+  LIST_ENTRY                 EntityDataList;  // Entity data (message-body)
+} HTTP_BOOT_CACHE_CONTENT;
+
+//
+// Callback data for HTTP_BODY_PARSER_CALLBACK()
+//
+typedef struct {
+  EFI_STATUS                 Status;
+  //
+  // Cache info.
+  //
+  HTTP_BOOT_CACHE_CONTENT    *Cache;
+  BOOLEAN                    NewBlock;
+  UINT8                      *Block;
+
+  //
+  // Caller provided buffer to load the file in.
+  //
+  UINTN                      CopyedSize;
+  UINTN                      BufferSize;
+  UINT8                      *Buffer;
+} HTTP_BOOT_CALLBACK_DATA;
+
+/**
+  Discover all the boot information for boot file.
+
+  @param[in, out]    Private        The pointer to the driver's private data.
+
+  @retval EFI_SUCCESS          Successfully obtained all the boot information .
+  @retval Others               Failed to retrieve the boot information.
+
+**/
+EFI_STATUS
+HttpBootDiscoverBootInfo (
+  IN OUT HTTP_BOOT_PRIVATE_DATA   *Private
+  );
+
+/**
+  Create a HttpIo instance for the file download.
+
+  @param[in]    Private        The pointer to the driver's private data.
+
+  @retval EFI_SUCCESS          Successfully created.
+  @retval Others               Failed to create HttpIo.
+
+**/
+EFI_STATUS
+HttpBootCreateHttpIo (
+  IN     HTTP_BOOT_PRIVATE_DATA       *Private
+  );
+
+/**
+  This function download the boot file by using UEFI HTTP protocol.
+  
+  @param[in]       Private         The pointer to the driver's private data.
+  @param[in]       HeaderOnly      Only request the response header, it could 
save a lot of time if
+                                   the caller only want to know the size of 
the requested file.
+  @param[in, out]  BufferSize      On input the size of Buffer in bytes. On 
output with a return
+                                   code of EFI_SUCCESS, the amount of data 
transferred to
+                                   Buffer. On output with a return code of 
EFI_BUFFER_TOO_SMALL,
+                                   the size of Buffer required to retrieve the 
requested file.
+  @param[out]      Buffer          The memory buffer to transfer the file to. 
IF Buffer is NULL,
+                                   then the size of the requested file is 
returned in
+                                   BufferSize.
+
+  @retval EFI_SUCCESS              The file was loaded.
+  @retval EFI_INVALID_PARAMETER    BufferSize is NULL or Buffer Size is not 
NULL but Buffer is NULL.
+  @retval EFI_OUT_OF_RESOURCES     Could not allocate needed resources
+  @retval EFI_BUFFER_TOO_SMALL     The BufferSize is too small to read the 
current directory entry.
+                                   BufferSize has been updated with the size 
needed to complete
+                                   the request.
+  @retval Others                   Unexpected error happened.
+
+**/
+EFI_STATUS
+HttpBootGetBootFile (
+  IN     HTTP_BOOT_PRIVATE_DATA   *Private,
+  IN     BOOLEAN                  HeaderOnly,
+  IN OUT UINTN                    *BufferSize,
+     OUT UINT8                    *Buffer
+  );
+
+/**
+  Clean up all cached data.
+
+  @param[in]          Private         The pointer to the driver's private data.
+
+**/
+VOID
+HttpBootFreeCacheList (
+  IN     HTTP_BOOT_PRIVATE_DATA   *Private
+  );
+
+#endif

Added: trunk/edk2/NetworkPkg/HttpBootDxe/HttpBootComponentName.c
===================================================================
--- trunk/edk2/NetworkPkg/HttpBootDxe/HttpBootComponentName.c                   
        (rev 0)
+++ trunk/edk2/NetworkPkg/HttpBootDxe/HttpBootComponentName.c   2015-07-07 
09:29:28 UTC (rev 17857)
@@ -0,0 +1,180 @@
+/** @file
+  Implementation of EFI_COMPONENT_NAME_PROTOCOL and 
EFI_COMPONENT_NAME2_PROTOCOL protocol.
+
+Copyright (c) 2015, Intel Corporation. All rights reserved.<BR>
+This program and the accompanying materials are licensed and made available 
under 
+the terms and conditions of the BSD License that accompanies this 
distribution.  
+The full text of the license may be found at
+http://opensource.org/licenses/bsd-license.php.                                
          
+    
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,          
           
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+**/
+
+#include "HttpBootDxe.h"
+
+///
+/// Component Name Protocol instance
+///
+GLOBAL_REMOVE_IF_UNREFERENCED 
+EFI_COMPONENT_NAME_PROTOCOL  gHttpBootDxeComponentName = {
+  (EFI_COMPONENT_NAME_GET_DRIVER_NAME)    
HttpBootDxeComponentNameGetDriverName,
+  
(EFI_COMPONENT_NAME_GET_CONTROLLER_NAME)HttpBootDxeComponentNameGetControllerName,
+  "eng"
+};
+
+///
+/// Component Name 2 Protocol instance
+///
+GLOBAL_REMOVE_IF_UNREFERENCED 
+EFI_COMPONENT_NAME2_PROTOCOL  gHttpBootDxeComponentName2 = {
+  HttpBootDxeComponentNameGetDriverName,
+  HttpBootDxeComponentNameGetControllerName,
+  "en"
+};
+
+///
+/// Table of driver names
+///
+GLOBAL_REMOVE_IF_UNREFERENCED 
+EFI_UNICODE_STRING_TABLE mHttpBootDxeDriverNameTable[] = {
+  { "eng;en", (CHAR16 *)L"UEFI HTTP Boot Driver" },
+  { NULL, NULL }
+};
+
+///
+/// Table of controller names
+///
+GLOBAL_REMOVE_IF_UNREFERENCED 
+EFI_UNICODE_STRING_TABLE mHttpBootDxeControllerNameTable[] = {
+  { "eng;en", (CHAR16 *)L"UEFI Http Boot Controller" },
+  { NULL, NULL }
+};
+
+/**
+  Retrieves a Unicode string that is the user-readable name of the EFI Driver.
+
+  @param  This       A pointer to the EFI_COMPONENT_NAME_PROTOCOL instance.
+  @param  Language   A pointer to a three-character ISO 639-2 language 
identifier.
+                     This is the language of the driver name that that the 
caller
+                     is requesting, and it must match one of the languages 
specified
+                     in SupportedLanguages.  The number of languages supported 
by a
+                     driver is up to the driver writer.
+  @param  DriverName A pointer to the Unicode string to return.  This Unicode 
string
+                     is the name of the driver specified by This in the 
language
+                     specified by Language.
+
+  @retval EFI_SUCCESS           The Unicode string for the Driver specified by 
This
+                                and the language specified by Language was 
returned
+                                in DriverName.
+  @retval EFI_INVALID_PARAMETER Language is NULL.
+  @retval EFI_INVALID_PARAMETER DriverName is NULL.
+  @retval EFI_UNSUPPORTED       The driver specified by This does not support 
the
+                                language specified by Language.
+
+**/
+EFI_STATUS
+EFIAPI
+HttpBootDxeComponentNameGetDriverName (
+  IN EFI_COMPONENT_NAME2_PROTOCOL  *This,
+  IN  CHAR8                        *Language,
+  OUT CHAR16                       **DriverName
+  )
+{
+  return LookupUnicodeString2 (
+           Language,
+           This->SupportedLanguages,
+           mHttpBootDxeDriverNameTable,
+           DriverName,
+           (BOOLEAN) (This != &gHttpBootDxeComponentName2)
+           );
+}
+
+/**
+  Retrieves a Unicode string that is the user readable name of the controller
+  that is being managed by an EFI Driver.
+
+  @param  This             A pointer to the EFI_COMPONENT_NAME_PROTOCOL 
instance.
+  @param  ControllerHandle The handle of a controller that the driver 
specified by
+                           This is managing.  This handle specifies the 
controller
+                           whose name is to be returned.
+  @param  ChildHandle      The handle of the child controller to retrieve the 
name
+                           of.  This is an optional parameter that may be 
NULL.  It
+                           will be NULL for device drivers.  It will also be 
NULL
+                           for a bus drivers that wish to retrieve the name of 
the
+                           bus controller.  It will not be NULL for a bus 
driver
+                           that wishes to retrieve the name of a child 
controller.
+  @param  Language         A pointer to a three character ISO 639-2 language
+                           identifier.  This is the language of the controller 
name
+                           that the caller is requesting, and it must match one
+                           of the languages specified in SupportedLanguages.  
The
+                           number of languages supported by a driver is up to 
the
+                           driver writer.
+  @param  ControllerName   A pointer to the Unicode string to return.  This 
Unicode
+                           string is the name of the controller specified by
+                           ControllerHandle and ChildHandle in the language 
specified
+                           by Language, from the point of view of the driver 
specified
+                           by This.
+
+  @retval EFI_SUCCESS           The Unicode string for the user-readable name 
in the
+                                language specified by Language for the driver
+                                specified by This was returned in DriverName.
+  @retval EFI_INVALID_PARAMETER ControllerHandle is NULL.
+  @retval EFI_INVALID_PARAMETER ChildHandle is not NULL and it is not a valid 
EFI_HANDLE.
+  @retval EFI_INVALID_PARAMETER Language is NULL.
+  @retval EFI_INVALID_PARAMETER ControllerName is NULL.
+  @retval EFI_UNSUPPORTED       The driver specified by This is not currently 
managing
+                                the controller specified by ControllerHandle 
and
+                                ChildHandle.
+  @retval EFI_UNSUPPORTED       The driver specified by This does not support 
the
+                                language specified by Language.
+
+**/
+EFI_STATUS
+EFIAPI
+HttpBootDxeComponentNameGetControllerName (
+  IN  EFI_COMPONENT_NAME2_PROTOCOL  *This,
+  IN  EFI_HANDLE                    ControllerHandle,
+  IN  EFI_HANDLE                    ChildHandle        OPTIONAL,
+  IN  CHAR8                         *Language,
+  OUT CHAR16                        **ControllerName
+  )
+{
+  EFI_STATUS                      Status;
+  EFI_HANDLE                      NicHandle;
+  UINT32                          *Id;
+
+  if (ControllerHandle == NULL || ChildHandle != NULL) {
+    return EFI_UNSUPPORTED;
+  }
+  
+  NicHandle = HttpBootGetNicByIp4Children (ControllerHandle);
+  if (NicHandle == NULL) {
+    return EFI_UNSUPPORTED;
+  }
+
+  //
+  // Try to retrieve the private data by caller ID GUID.
+  //
+  Status = gBS->OpenProtocol (
+                  NicHandle,
+                  &gEfiCallerIdGuid,
+                  (VOID **) &Id,
+                  NULL,
+                  NULL,
+                  EFI_OPEN_PROTOCOL_GET_PROTOCOL
+                  );
+  if (EFI_ERROR (Status)) {
+    return Status;
+  }
+
+  return LookupUnicodeString2 (
+           Language,
+           This->SupportedLanguages,
+           mHttpBootDxeControllerNameTable,
+           ControllerName,
+           (BOOLEAN)(This != &gHttpBootDxeComponentName2)
+           );
+
+}

Added: trunk/edk2/NetworkPkg/HttpBootDxe/HttpBootComponentName.h
===================================================================
--- trunk/edk2/NetworkPkg/HttpBootDxe/HttpBootComponentName.h                   
        (rev 0)
+++ trunk/edk2/NetworkPkg/HttpBootDxe/HttpBootComponentName.h   2015-07-07 
09:29:28 UTC (rev 17857)
@@ -0,0 +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

Added: trunk/edk2/NetworkPkg/HttpBootDxe/HttpBootDhcp4.c
===================================================================
--- trunk/edk2/NetworkPkg/HttpBootDxe/HttpBootDhcp4.c                           
(rev 0)
+++ trunk/edk2/NetworkPkg/HttpBootDxe/HttpBootDhcp4.c   2015-07-07 09:29:28 UTC 
(rev 17857)
@@ -0,0 +1,829 @@
+/** @file
+  Functions implementation related with DHCPv4 for HTTP boot driver.
+
+Copyright (c) 2015, Intel Corporation. All rights reserved.<BR>
+This program and the accompanying materials are licensed and made available 
under 
+the terms and conditions of the BSD License that accompanies this 
distribution.  
+The full text of the license may be found at
+http://opensource.org/licenses/bsd-license.php.                                
          
+    
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,          
           
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+**/
+
+#include "HttpBootDxe.h"
+
+//
+// This is a map from the interested DHCP4 option tags' index to the tag value.
+//
+UINT8 mInterestedDhcp4Tags[HTTP_BOOT_DHCP4_TAG_INDEX_MAX] = {
+  HTTP_BOOT_DHCP4_TAG_BOOTFILE_LEN,
+  HTTP_BOOT_DHCP4_TAG_OVERLOAD,
+  HTTP_BOOT_DHCP4_TAG_MSG_TYPE,
+  HTTP_BOOT_DHCP4_TAG_SERVER_ID,
+  HTTP_BOOT_DHCP4_TAG_CLASS_ID,
+  HTTP_BOOT_DHCP4_TAG_BOOTFILE,
+  HTTP_BOOT_DHCP4_TAG_DNS_SERVER
+};
+
+//
+// There are 4 times retries with the value of 4, 8, 16 and 32, refers to UEFI 
2.5 spec.
+//
+UINT32 mHttpDhcpTimeout[4] = {4, 8, 16, 32};
+
+/**
+  Build the options buffer for the DHCPv4 request packet.
+
+  @param[in]  Private             Pointer to HTTP boot driver private data.
+  @param[out] OptList             Pointer to the option pointer array.
+  @param[in]  Buffer              Pointer to the buffer to contain the option 
list.
+
+  @return     Index               The count of the built-in options.
+
+**/
+UINT32
+HttpBootBuildDhcp4Options (
+  IN  HTTP_BOOT_PRIVATE_DATA        *Private,
+  OUT EFI_DHCP4_PACKET_OPTION       **OptList,
+  IN  UINT8                         *Buffer
+  )
+{
+  HTTP_BOOT_DHCP4_OPTION_ENTRY  OptEnt;
+  UINT16                        Value;
+  UINT32                        Index;
+
+  Index      = 0;
+  OptList[0] = (EFI_DHCP4_PACKET_OPTION *) Buffer;
+
+  //
+  // Append parameter request list option.
+  //
+  OptList[Index]->OpCode    = HTTP_BOOT_DHCP4_TAG_PARA_LIST;
+  OptList[Index]->Length    = 27;
+  OptEnt.Para               = (HTTP_BOOT_DHCP4_OPTION_PARA *) 
OptList[Index]->Data;
+  OptEnt.Para->ParaList[0]  = HTTP_BOOT_DHCP4_TAG_NETMASK;
+  OptEnt.Para->ParaList[1]  = HTTP_BOOT_DHCP4_TAG_TIME_OFFSET;
+  OptEnt.Para->ParaList[2]  = HTTP_BOOT_DHCP4_TAG_ROUTER;
+  OptEnt.Para->ParaList[3]  = HTTP_BOOT_DHCP4_TAG_TIME_SERVER;
+  OptEnt.Para->ParaList[4]  = HTTP_BOOT_DHCP4_TAG_NAME_SERVER;
+  OptEnt.Para->ParaList[5]  = HTTP_BOOT_DHCP4_TAG_DNS_SERVER;
+  OptEnt.Para->ParaList[6]  = HTTP_BOOT_DHCP4_TAG_HOSTNAME;
+  OptEnt.Para->ParaList[7]  = HTTP_BOOT_DHCP4_TAG_BOOTFILE_LEN;
+  OptEnt.Para->ParaList[8]  = HTTP_BOOT_DHCP4_TAG_DOMAINNAME;
+  OptEnt.Para->ParaList[9]  = HTTP_BOOT_DHCP4_TAG_ROOTPATH;
+  OptEnt.Para->ParaList[10] = HTTP_BOOT_DHCP4_TAG_EXTEND_PATH;
+  OptEnt.Para->ParaList[11] = HTTP_BOOT_DHCP4_TAG_EMTU;
+  OptEnt.Para->ParaList[12] = HTTP_BOOT_DHCP4_TAG_TTL;
+  OptEnt.Para->ParaList[13] = HTTP_BOOT_DHCP4_TAG_BROADCAST;
+  OptEnt.Para->ParaList[14] = HTTP_BOOT_DHCP4_TAG_NIS_DOMAIN;
+  OptEnt.Para->ParaList[15] = HTTP_BOOT_DHCP4_TAG_NIS_SERVER;
+  OptEnt.Para->ParaList[16] = HTTP_BOOT_DHCP4_TAG_NTP_SERVER;
+  OptEnt.Para->ParaList[17] = HTTP_BOOT_DHCP4_TAG_VENDOR;
+  OptEnt.Para->ParaList[18] = HTTP_BOOT_DHCP4_TAG_REQUEST_IP;
+  OptEnt.Para->ParaList[19] = HTTP_BOOT_DHCP4_TAG_LEASE;
+  OptEnt.Para->ParaList[20] = HTTP_BOOT_DHCP4_TAG_SERVER_ID;
+  OptEnt.Para->ParaList[21] = HTTP_BOOT_DHCP4_TAG_T1;
+  OptEnt.Para->ParaList[22] = HTTP_BOOT_DHCP4_TAG_T2;
+  OptEnt.Para->ParaList[23] = HTTP_BOOT_DHCP4_TAG_CLASS_ID;
+  OptEnt.Para->ParaList[25] = HTTP_BOOT_DHCP4_TAG_BOOTFILE;
+  OptEnt.Para->ParaList[26] = HTTP_BOOT_DHCP4_TAG_UUID;
+  Index++;
+  OptList[Index]            = GET_NEXT_DHCP_OPTION (OptList[Index - 1]);
+
+  //
+  // Append UUID/Guid-based client identifier option
+  //
+  OptList[Index]->OpCode  = HTTP_BOOT_DHCP4_TAG_UUID;
+  OptList[Index]->Length  = (UINT8) sizeof (HTTP_BOOT_DHCP4_OPTION_UUID);
+  OptEnt.Uuid             = (HTTP_BOOT_DHCP4_OPTION_UUID *) 
OptList[Index]->Data;
+  OptEnt.Uuid->Type       = 0;
+  if (EFI_ERROR (NetLibGetSystemGuid ((EFI_GUID *) OptEnt.Uuid->Guid))) {
+    //
+    // Zero the Guid to indicate NOT programable if failed to get system Guid.
+    //
+    ZeroMem (OptEnt.Uuid->Guid, sizeof (EFI_GUID));
+  }
+  Index++;
+  OptList[Index]          = GET_NEXT_DHCP_OPTION (OptList[Index - 1]);
+
+  //
+  // Append client network device interface option
+  //
+  OptList[Index]->OpCode  = HTTP_BOOT_DHCP4_TAG_UNDI;
+  OptList[Index]->Length  = (UINT8) sizeof (HTTP_BOOT_DHCP4_OPTION_UNDI);
+  OptEnt.Undi             = (HTTP_BOOT_DHCP4_OPTION_UNDI *) 
OptList[Index]->Data;
+
+  if (Private->Nii != NULL) {
+    OptEnt.Undi->Type     = Private->Nii->Type;
+    OptEnt.Undi->MajorVer = Private->Nii->MajorVer;
+    OptEnt.Undi->MinorVer = Private->Nii->MinorVer;
+  } else {
+    OptEnt.Undi->Type     = DEFAULT_UNDI_TYPE;
+    OptEnt.Undi->MajorVer = DEFAULT_UNDI_MAJOR;
+    OptEnt.Undi->MinorVer = DEFAULT_UNDI_MINOR;
+  }
+
+  Index++;
+  OptList[Index] = GET_NEXT_DHCP_OPTION (OptList[Index - 1]);
+
+  //
+  // Append client system architecture option
+  //
+  OptList[Index]->OpCode  = HTTP_BOOT_DHCP4_TAG_ARCH;
+  OptList[Index]->Length  = (UINT8) sizeof (HTTP_BOOT_DHCP4_OPTION_ARCH);
+  OptEnt.Arch             = (HTTP_BOOT_DHCP4_OPTION_ARCH *) 
OptList[Index]->Data;
+  Value                   = HTONS (EFI_HTTP_BOOT_CLIENT_SYSTEM_ARCHITECTURE);
+  CopyMem (&OptEnt.Arch->Type, &Value, sizeof (UINT16));
+  Index++;
+  OptList[Index]          = GET_NEXT_DHCP_OPTION (OptList[Index - 1]);
+
+  //
+  // Append vendor class identify option
+  //
+  OptList[Index]->OpCode  = HTTP_BOOT_DHCP4_TAG_CLASS_ID;
+  OptList[Index]->Length  = (UINT8) sizeof (HTTP_BOOT_DHCP4_OPTION_CLID);
+  OptEnt.Clid             = (HTTP_BOOT_DHCP4_OPTION_CLID *) 
OptList[Index]->Data;
+  CopyMem (
+    OptEnt.Clid,
+    DEFAULT_CLASS_ID_DATA,
+    sizeof (HTTP_BOOT_DHCP4_OPTION_CLID)
+    );
+  HttpBootUintnToAscDecWithFormat (
+    EFI_HTTP_BOOT_CLIENT_SYSTEM_ARCHITECTURE,
+    OptEnt.Clid->ArchitectureType,
+    sizeof (OptEnt.Clid->ArchitectureType)
+    );
+
+  if (Private->Nii != NULL) {
+    CopyMem (OptEnt.Clid->InterfaceName, Private->Nii->StringId, sizeof 
(OptEnt.Clid->InterfaceName));
+    HttpBootUintnToAscDecWithFormat (Private->Nii->MajorVer, 
OptEnt.Clid->UndiMajor, sizeof (OptEnt.Clid->UndiMajor));
+    HttpBootUintnToAscDecWithFormat (Private->Nii->MinorVer, 
OptEnt.Clid->UndiMinor, sizeof (OptEnt.Clid->UndiMinor));
+  }
+
+  Index++;
+
+  return Index;
+}
+
+/**
+  Parse a certain dhcp4 option by OptTag in Buffer, and return with start 
pointer.
+
+  @param[in]  Buffer              Pointer to the option buffer.
+  @param[in]  Length              Length of the option buffer.
+  @param[in]  OptTag              Tag of the required option.
+
+  @retval     NULL                Failed to find the required option.
+  @retval     Others              The position of the required option.
+
+**/
+EFI_DHCP4_PACKET_OPTION *
+HttpBootParseDhcp4Options (
+  IN UINT8                      *Buffer,
+  IN UINT32                     Length,
+  IN UINT8                      OptTag
+  )
+{
+  EFI_DHCP4_PACKET_OPTION       *Option;
+  UINT32                        Offset;
+
+  Option  = (EFI_DHCP4_PACKET_OPTION *) Buffer;
+  Offset  = 0;
+
+  while (Offset < Length && Option->OpCode != HTTP_BOOT_DHCP4_TAG_EOP) {
+
+    if (Option->OpCode == OptTag) {
+      //
+      // Found the required option.
+      //
+      return Option;
+    }
+
+    //
+    // Skip the current option to the next.
+    //
+    if (Option->OpCode == HTTP_BOOT_DHCP4_TAG_PAD) {
+      Offset++;
+    } else {
+      Offset += Option->Length + 2;
+    }
+
+    Option = (EFI_DHCP4_PACKET_OPTION *) (Buffer + Offset);
+  }
+
+  return NULL;
+}
+
+/**
+  Cache the DHCPv4 packet.
+
+  @param[in]  Dst          Pointer to the cache buffer for DHCPv4 packet.
+  @param[in]  Src          Pointer to the DHCPv4 packet to be cached.
+
+**/
+VOID
+HttpBootCacheDhcp4Packet (
+  IN EFI_DHCP4_PACKET     *Dst,
+  IN EFI_DHCP4_PACKET     *Src
+  )
+{
+  ASSERT (Dst->Size >= Src->Length);
+
+  CopyMem (&Dst->Dhcp4, &Src->Dhcp4, Src->Length);
+  Dst->Length = Src->Length;
+}
+
+/**
+  Parse the cached DHCPv4 packet, including all the options.
+
+  @param[in]  Cache4           Pointer to cached DHCPv4 packet.
+
+  @retval     EFI_SUCCESS      Parsed the DHCPv4 packet successfully.
+  @retval     EFI_DEVICE_ERROR Failed to parse an invalid packet.
+
+**/
+EFI_STATUS
+HttpBootParseDhcp4Packet (
+  IN HTTP_BOOT_DHCP4_PACKET_CACHE    *Cache4
+  )
+{
+  EFI_DHCP4_PACKET               *Offer;
+  EFI_DHCP4_PACKET_OPTION        **Options;
+  UINTN                          Index;
+  EFI_DHCP4_PACKET_OPTION        *Option;
+  BOOLEAN                        IsProxyOffer;
+  BOOLEAN                        IsHttpOffer;
+  BOOLEAN                        IsDnsOffer;
+  BOOLEAN                        IpExpressedUri;
+  UINT8                          *Ptr8;
+  EFI_STATUS                     Status;
+  HTTP_BOOT_OFFER_TYPE           OfferType;
+  EFI_IPv4_ADDRESS               IpAddr;
+  
+  IsDnsOffer     = FALSE;
+  IpExpressedUri = FALSE;
+  IsProxyOffer   = FALSE;
+  IsHttpOffer    = FALSE;
+
+  ZeroMem (Cache4->OptList, sizeof (Cache4->OptList));
+
+  Offer   = &Cache4->Packet.Offer;
+  Options = Cache4->OptList;
+
+  //
+  // Parse DHCPv4 options in this offer, and store the pointers.
+  // First, try to parse DHCPv4 options from the DHCP optional parameters 
field.
+  //
+  for (Index = 0; Index < HTTP_BOOT_DHCP4_TAG_INDEX_MAX; Index++) {
+    Options[Index] = HttpBootParseDhcp4Options (
+                       Offer->Dhcp4.Option,
+                       GET_OPTION_BUFFER_LEN (Offer),
+                       mInterestedDhcp4Tags[Index]
+                       );
+  }
+  //
+  // Second, Check if bootfilename and serverhostname is overloaded to carry 
DHCP options refers to rfc-2132. 
+  // If yes, try to parse options from the BootFileName field, then ServerName 
field.
+  //
+  Option = Options[HTTP_BOOT_DHCP4_TAG_INDEX_OVERLOAD];
+  if (Option != NULL) {
+    if ((Option->Data[0] & HTTP_BOOT_DHCP4_OVERLOAD_FILE) != 0) {
+      for (Index = 0; Index < HTTP_BOOT_DHCP4_TAG_INDEX_MAX; Index++) {
+        if (Options[Index] == NULL) {
+          Options[Index] = HttpBootParseDhcp4Options (
+                             (UINT8 *) Offer->Dhcp4.Header.BootFileName,
+                             sizeof (Offer->Dhcp4.Header.BootFileName),
+                             mInterestedDhcp4Tags[Index]
+                             );
+        }
+      }
+    }
+    if ((Option->Data[0] & HTTP_BOOT_DHCP4_OVERLOAD_SERVER_NAME) != 0) {
+      for (Index = 0; Index < HTTP_BOOT_DHCP4_TAG_INDEX_MAX; Index++) {
+        if (Options[Index] == NULL) {
+          Options[Index] = HttpBootParseDhcp4Options (
+                             (UINT8 *) Offer->Dhcp4.Header.ServerName,
+                             sizeof (Offer->Dhcp4.Header.ServerName),
+                             mInterestedDhcp4Tags[Index]
+                             );
+        }
+      }
+    }
+  }
+
+  //
+  // The offer with "yiaddr" is a proxy offer.
+  //
+  if (Offer->Dhcp4.Header.YourAddr.Addr[0] == 0) {
+    IsProxyOffer = TRUE;
+  }
+
+  //
+  // The offer with "HttpClient" is a Http offer.
+  //
+  Option = Options[HTTP_BOOT_DHCP4_TAG_INDEX_CLASS_ID];
+  if ((Option != NULL) && (Option->Length >= 9) &&
+      (CompareMem (Option->Data, DEFAULT_CLASS_ID_DATA, 9) == 0)) {
+    IsHttpOffer = TRUE;
+  }
+
+  //
+  // The offer with Domain Server is a DNS offer.
+  //
+  Option = Options[HTTP_BOOT_DHCP4_TAG_INDEX_DNS_SERVER];
+  if (Option != NULL) {
+    IsDnsOffer = TRUE;
+  }
+
+  //
+  // Parse boot file name:
+  // Boot URI information is provided thru 'file' field in DHCP Header or 
option 67.
+  // According to RFC 2132, boot file name should be read from DHCP option 67 
(bootfile name) if present.
+  // Otherwise, read from boot file field in DHCP header.
+  //
+  if (Options[HTTP_BOOT_DHCP4_TAG_INDEX_BOOTFILE] != NULL) {
+    //
+    // RFC 2132, Section 9.5 does not strictly state Bootfile name (option 67) 
is null
+    // terminated string. So force to append null terminated character at the 
end of string.
+    //
+    Ptr8 =  (UINT8*)&Options[HTTP_BOOT_DHCP4_TAG_INDEX_BOOTFILE]->Data[0];
+    Ptr8 += Options[HTTP_BOOT_DHCP4_TAG_INDEX_BOOTFILE]->Length;
+    if (*(Ptr8 - 1) != '\0') {
+      *Ptr8 = '\0';
+    }
+  } else if (Offer->Dhcp4.Header.BootFileName[0] != 0) {
+    //
+    // If the bootfile is not present and bootfilename is present in DHCPv4 
packet, just parse it.
+    // Do not count dhcp option header here, or else will destroy the 
serverhostname.
+    //
+    Options[HTTP_BOOT_DHCP4_TAG_INDEX_BOOTFILE] = (EFI_DHCP4_PACKET_OPTION *)
+                                                    
(&Offer->Dhcp4.Header.BootFileName[0] -
+                                                    OFFSET_OF 
(EFI_DHCP4_PACKET_OPTION, Data[0]));
+  }
+
+  //
+  // Http offer must have a boot URI.
+  //
+  if (IsHttpOffer && Options[HTTP_BOOT_DHCP4_TAG_INDEX_BOOTFILE] == NULL) {
+    return EFI_DEVICE_ERROR;
+  }
+
+  //
+  // Try to retrieve the IP of HTTP server from URI. 
+  //
+  if (IsHttpOffer) {
+    Status = HttpParseUrl (
+               (CHAR8*) Options[HTTP_BOOT_DHCP4_TAG_INDEX_BOOTFILE]->Data,
+               (UINT32) AsciiStrLen ((CHAR8*) 
Options[HTTP_BOOT_DHCP4_TAG_INDEX_BOOTFILE]->Data),
+               FALSE,
+               &Cache4->UriParser
+               );
+    if (EFI_ERROR (Status)) {
+      return EFI_DEVICE_ERROR;
+    }
+
+    Status = HttpUrlGetIp4 (
+               (CHAR8*) Options[HTTP_BOOT_DHCP4_TAG_INDEX_BOOTFILE]->Data,
+               Cache4->UriParser,
+               &IpAddr
+               );
+    IpExpressedUri = !EFI_ERROR (Status);
+  }
+
+  //
+  // Determine offer type of the DHCPv4 packet.
+  //
+  if (IsHttpOffer) {
+    if (IpExpressedUri) {
+      OfferType = IsProxyOffer ? HttpOfferTypeProxyIpUri : 
HttpOfferTypeDhcpIpUri;
+    } else {
+      if (!IsProxyOffer) {
+        OfferType = IsDnsOffer ? HttpOfferTypeDhcpNameUriDns : 
HttpOfferTypeDhcpNameUri;
+      } else {
+        OfferType = HttpOfferTypeProxyNameUri;
+      }
+    }
+
+  } else {
+    if (!IsProxyOffer) {
+      OfferType = IsDnsOffer ? HttpOfferTypeDhcpDns : HttpOfferTypeDhcpOnly;
+    } else {
+      return EFI_DEVICE_ERROR;
+    }
+  }
+  
+  Cache4->OfferType = OfferType;
+  return EFI_SUCCESS;
+}
+
+/**
+  Cache all the received DHCPv4 offers, and set OfferIndex and OfferCount.
+
+  @param[in]  Private               Pointer to HTTP boot driver private data.
+  @param[in]  RcvdOffer             Pointer to the received offer packet.
+
+**/
+VOID
+HttpBootCacheDhcp4Offer (
+  IN HTTP_BOOT_PRIVATE_DATA  *Private,
+  IN EFI_DHCP4_PACKET        *RcvdOffer
+  )
+{
+  HTTP_BOOT_DHCP4_PACKET_CACHE  *Cache4;
+  EFI_DHCP4_PACKET              *Offer;
+  HTTP_BOOT_OFFER_TYPE          OfferType;
+
+  ASSERT (Private->OfferNum < HTTP_BOOT_OFFER_MAX_NUM);
+  Cache4 = &Private->OfferBuffer[Private->OfferNum].Dhcp4;
+  Offer  = &Cache4->Packet.Offer;
+
+  //
+  // Cache the content of DHCPv4 packet firstly.
+  //
+  HttpBootCacheDhcp4Packet (Offer, RcvdOffer);
+
+  //
+  // Validate the DHCPv4 packet, and parse the options and offer type.
+  //
+  if (EFI_ERROR (HttpBootParseDhcp4Packet (Cache4))) {
+    return;
+  }
+
+  //
+  // Determine whether cache the current offer by type, and record OfferIndex 
and OfferCount.
+  //
+  OfferType = Cache4->OfferType;
+  ASSERT (OfferType < HttpOfferTypeMax);
+  ASSERT (Private->OfferCount[OfferType] < HTTP_BOOT_OFFER_MAX_NUM);
+  Private->OfferIndex[OfferType][Private->OfferCount[OfferType]] = 
Private->OfferNum;
+  Private->OfferCount[OfferType]++;
+  Private->OfferNum++;
+}
+
+/**
+  Select an DHCPv4 offer, and record SelectIndex and SelectProxyType.
+
+  @param[in]  Private             Pointer to HTTP boot driver private data.
+
+**/
+VOID
+HttpBootSelectDhcp4Offer (
+  IN HTTP_BOOT_PRIVATE_DATA  *Private
+  )
+{
+  Private->SelectIndex = 0;
+  Private->SelectProxyType = HttpOfferTypeMax;
+  
+  //
+  // Priority1: HttpOfferTypeDhcpIpUri                           
+  // Priority2: HttpOfferTypeDhcpNameUriDns                      
+  // Priority3: HttpOfferTypeDhcpOnly + HttpOfferTypeProxyIpUri  
+  // Priority4: HttpOfferTypeDhcpDns  + HttpOfferTypeProxyIpUri  
+  // Priority5: HttpOfferTypeDhcpDns  + HttpOfferTypeProxyNameUri
+  // Priority6: HttpOfferTypeDhcpDns  + HttpOfferTypeDhcpNameUri 
+  //    
+  if (Private->OfferCount[HttpOfferTypeDhcpIpUri] > 0) {
+    
+    Private->SelectIndex = Private->OfferIndex[HttpOfferTypeDhcpIpUri][0] + 1;
+    
+  } else if (Private->OfferCount[HttpOfferTypeDhcpNameUriDns] > 0) {
+  
+    Private->SelectIndex = Private->OfferIndex[HttpOfferTypeDhcpNameUriDns][0] 
+ 1;
+    
+  } else if (Private->OfferCount[HttpOfferTypeDhcpOnly] > 0 &&
+             Private->OfferCount[HttpOfferTypeProxyIpUri] > 0) {
+             
+    Private->SelectIndex     = Private->OfferIndex[HttpOfferTypeDhcpOnly][0] + 
1;
+    Private->SelectProxyType = HttpOfferTypeProxyIpUri;
+    
+  } else if (Private->OfferCount[HttpOfferTypeDhcpDns] > 0 &&
+             Private->OfferCount[HttpOfferTypeProxyIpUri] > 0) {
+             
+    Private->SelectIndex     = Private->OfferIndex[HttpOfferTypeDhcpDns][0] + 
1;
+    Private->SelectProxyType = HttpOfferTypeProxyIpUri;
+    
+  } else if (Private->OfferCount[HttpOfferTypeDhcpDns] > 0 &&
+             Private->OfferCount[HttpOfferTypeProxyNameUri] > 0) {
+             
+    Private->SelectIndex     = Private->OfferIndex[HttpOfferTypeDhcpDns][0] + 
1;
+    Private->SelectProxyType = HttpOfferTypeProxyNameUri;
+    
+  } else if (Private->OfferCount[HttpOfferTypeDhcpDns] > 0 &&
+             Private->OfferCount[HttpOfferTypeDhcpNameUri] > 0) {
+             
+    Private->SelectIndex     = Private->OfferIndex[HttpOfferTypeDhcpDns][0] + 
1;
+    Private->SelectProxyType = HttpOfferTypeDhcpNameUri;
+  }
+}
+
+
+/**
+  EFI_DHCP4_CALLBACK is provided by the consumer of the EFI DHCPv4 Protocol 
driver
+  to intercept events that occurred in the configuration process.
+
+  @param[in]  This              Pointer to the EFI DHCPv4 Protocol.
+  @param[in]  Context           Pointer to the context set by 
EFI_DHCP4_PROTOCOL.Configure().
+  @param[in]  CurrentState      The current operational state of the EFI 
DHCPv4 Protocol driver.
+  @param[in]  Dhcp4Event        The event that occurs in the current state, 
which usually means a
+                                state transition.
+  @param[in]  Packet            The DHCPv4 packet that is going to be sent or 
already received.
+  @param[out] NewPacket         The packet that is used to replace the above 
Packet.
+
+  @retval EFI_SUCCESS           Tells the EFI DHCPv4 Protocol driver to 
continue the DHCP process.
+  @retval EFI_NOT_READY         Only used in the Dhcp4Selecting state. The EFI 
DHCPv4 Protocol
+                                driver will continue to wait for more 
DHCPOFFER packets until the
+                                retry timeout expires.
+  @retval EFI_ABORTED           Tells the EFI DHCPv4 Protocol driver to abort 
the current process
+                                and return to the Dhcp4Init or Dhcp4InitReboot 
state.
+
+**/
+EFI_STATUS
+EFIAPI
+HttpBootDhcp4CallBack (
+  IN  EFI_DHCP4_PROTOCOL               *This,
+  IN  VOID                             *Context,
+  IN  EFI_DHCP4_STATE                  CurrentState,
+  IN  EFI_DHCP4_EVENT                  Dhcp4Event,
+  IN  EFI_DHCP4_PACKET                 *Packet            OPTIONAL,
+  OUT EFI_DHCP4_PACKET                 **NewPacket        OPTIONAL
+  )
+{
+  HTTP_BOOT_PRIVATE_DATA               *Private;
+  EFI_DHCP4_PACKET_OPTION              *MaxMsgSize;
+  UINT16                               Value;
+  EFI_STATUS                           Status;
+
+  if ((Dhcp4Event != Dhcp4RcvdOffer) && (Dhcp4Event != Dhcp4SelectOffer)) {
+    return EFI_SUCCESS;
+  }
+  
+  Private = (HTTP_BOOT_PRIVATE_DATA *) Context;
+
+  //
+  // Override the Maximum DHCP Message Size.
+  //
+  MaxMsgSize = HttpBootParseDhcp4Options (
+                 Packet->Dhcp4.Option,
+                 GET_OPTION_BUFFER_LEN (Packet),
+                 HTTP_BOOT_DHCP4_TAG_MAXMSG
+                 );
+  if (MaxMsgSize != NULL) {
+    Value = HTONS (HTTP_BOOT_DHCP4_PACKET_MAX_SIZE);
+    CopyMem (MaxMsgSize->Data, &Value, sizeof (Value));
+  }
+
+  Status = EFI_SUCCESS;
+  switch (Dhcp4Event) {
+  case Dhcp4RcvdOffer:
+    Status = EFI_NOT_READY;
+    if (Private->OfferNum < HTTP_BOOT_OFFER_MAX_NUM) {
+      //
+      // Cache the DHCPv4 offers to OfferBuffer[] for select later, and record
+      // the OfferIndex and OfferCount.
+      //
+      HttpBootCacheDhcp4Offer (Private, Packet);
+    }
+    break;
+
+  case Dhcp4SelectOffer:
+    //
+    // Select offer according to the priority in UEFI spec, and record the 
SelectIndex 
+    // and SelectProxyType.
+    //
+    HttpBootSelectDhcp4Offer (Private);
+
+    if (Private->SelectIndex == 0) {
+      Status = EFI_ABORTED;
+    } else {
+      *NewPacket = &Private->OfferBuffer[Private->SelectIndex - 
1].Dhcp4.Packet.Offer;
+    }
+    break;
+    
+  default:
+    break;
+  }
+
+  return Status;
+}
+
+/**
+  This function will register the IPv4 gateway address to the network device.
+  
+  @param[in]  Private             The pointer to HTTP_BOOT_PRIVATE_DATA.
+
+  @retval     EFI_SUCCESS         The new IP configuration has been configured 
successfully.
+  @retval     Others              Failed to configure the address.
+
+**/
+EFI_STATUS
+HttpBootRegisterIp4Gateway (
+  IN HTTP_BOOT_PRIVATE_DATA         *Private
+  )
+{
+  EFI_STATUS                      Status;
+  EFI_IP4_CONFIG2_PROTOCOL        *Ip4Config2;
+
+  ASSERT (!Private->UsingIpv6);
+
+  Ip4Config2 = Private->Ip4Config2;
+
+  //
+  // Configure the gateway if valid.
+  //
+  if (!EFI_IP4_EQUAL (&Private->GatewayIp, &mZeroIp4Addr)) {
+    Status = Ip4Config2->SetData (
+                           Ip4Config2,
+                           Ip4Config2DataTypeGateway,
+                           sizeof (EFI_IPv4_ADDRESS),
+                           &Private->GatewayIp
+                           );
+    if (EFI_ERROR (Status)) {
+      return Status;
+    }
+  }
+
+  return EFI_SUCCESS;
+}
+
+/**
+  This function will register the default DNS addresses to the network device.
+  
+  @param[in]  Private             The pointer to HTTP_BOOT_PRIVATE_DATA.
+  @param[in]  DataLength          Size of the buffer pointed to by 
DnsServerData in bytes.
+  @param[in]  DnsServerData       Point a list of DNS server address in an 
array
+                                  of EFI_IPv4_ADDRESS instances.
+
+  @retval     EFI_SUCCESS         The DNS configuration has been configured 
successfully.
+  @retval     Others              Failed to configure the address.
+
+**/
+EFI_STATUS
+HttpBootRegisterIp4Dns (
+  IN HTTP_BOOT_PRIVATE_DATA         *Private,
+  IN UINTN                          DataLength,
+  IN VOID                           *DnsServerData
+  )
+{
+  EFI_IP4_CONFIG2_PROTOCOL        *Ip4Config2;
+  
+  ASSERT (!Private->UsingIpv6);
+
+  Ip4Config2 = Private->Ip4Config2;
+  
+  return Ip4Config2->SetData (
+                       Ip4Config2,
+                       Ip4Config2DataTypeDnsServer,
+                       DataLength,
+                       DnsServerData
+                       );
+}
+
+
+/**
+  This function will switch the IP4 configuration policy to Static.
+
+  @param[in]  Private             Pointer to HTTP boot driver private data.
+
+  @retval     EFI_SUCCESS         The policy is already configured to static.
+  @retval     Others              Other error as indicated..
+
+**/
+EFI_STATUS
+HttpBootSetIpPolicy (
+  IN HTTP_BOOT_PRIVATE_DATA         *Private
+  )
+{
+  EFI_IP4_CONFIG2_POLICY          Policy;
+  EFI_STATUS                      Status;
+  EFI_IP4_CONFIG2_PROTOCOL        *Ip4Config2;
+  UINTN                           DataSize;
+
+  Ip4Config2 = Private->Ip4Config2;
+
+  DataSize = sizeof (EFI_IP4_CONFIG2_POLICY);
+  Status = Ip4Config2->GetData (
+                         Ip4Config2,
+                         Ip4Config2DataTypePolicy,
+                         &DataSize,
+                         &Policy
+                         );
+  if (EFI_ERROR (Status)) {
+    return Status;
+  }
+
+  if (Policy != Ip4Config2PolicyStatic) {
+    Policy = Ip4Config2PolicyStatic;
+    Status= Ip4Config2->SetData (
+                          Ip4Config2,
+                          Ip4Config2DataTypePolicy,
+                          sizeof (EFI_IP4_CONFIG2_POLICY),
+                          &Policy
+                          );
+    if (EFI_ERROR (Status)) {
+      return Status;
+    } 
+  }
+
+  return EFI_SUCCESS;
+}
+
+/**
+  Start the D.O.R.A DHCPv4 process to acquire the IPv4 address and other Http 
boot information.
+
+  @param[in]  Private           Pointer to HTTP boot driver private data.
+
+  @retval EFI_SUCCESS           The D.O.R.A process successfully finished.
+  @retval Others                Failed to finish the D.O.R.A process.
+
+**/
+EFI_STATUS
+HttpBootDhcp4Dora (
+  IN HTTP_BOOT_PRIVATE_DATA         *Private
+  )
+{
+  EFI_DHCP4_PROTOCOL           *Dhcp4;
+  UINT32                       OptCount;
+  EFI_DHCP4_PACKET_OPTION      *OptList[HTTP_BOOT_DHCP4_OPTION_MAX_NUM];
+  UINT8                        Buffer[HTTP_BOOT_DHCP4_OPTION_MAX_SIZE];
+  EFI_DHCP4_CONFIG_DATA        Config;
+  EFI_STATUS                   Status;
+  EFI_DHCP4_MODE_DATA          Mode;
+  
+  Dhcp4 = Private->Dhcp4;
+  ASSERT (Dhcp4 != NULL);
+
+  Status = HttpBootSetIpPolicy (Private);
+  if (EFI_ERROR (Status)) {
+    return Status;
+  }
+
+  //
+  // Build option list for the request packet.
+  //
+  OptCount = HttpBootBuildDhcp4Options (Private, OptList, Buffer);
+  ASSERT (OptCount > 0);
+
+  ZeroMem (&Config, sizeof(Config));
+  Config.OptionCount      = OptCount;
+  Config.OptionList       = OptList;
+  Config.Dhcp4Callback    = HttpBootDhcp4CallBack;
+  Config.CallbackContext  = Private;
+  Config.DiscoverTryCount = HTTP_BOOT_DHCP_RETRIES;
+  Config.DiscoverTimeout  = mHttpDhcpTimeout;
+
+  //
+  // Configure the DHCPv4 instance for HTTP boot.
+  //
+  Status = Dhcp4->Configure (Dhcp4, &Config);
+  if (EFI_ERROR (Status)) {
+    goto ON_EXIT;
+  }
+
+  //
+  // Initialize the record fields for DHCPv4 offer in private data.
+  //
+  Private->OfferNum = 0;
+  ZeroMem (Private->OfferCount, sizeof (Private->OfferCount));
+  ZeroMem (Private->OfferIndex, sizeof (Private->OfferIndex));
+
+  //
+  // Start DHCPv4 D.O.R.A. process to acquire IPv4 address.
+  //
+  Status = Dhcp4->Start (Dhcp4, NULL);
+  if (EFI_ERROR (Status)) {
+    goto ON_EXIT;
+  }
+
+  //
+  // Get the acquired IPv4 address and store them.
+  //
+  Status = Dhcp4->GetModeData (Dhcp4, &Mode);
+  if (EFI_ERROR (Status)) {
+    goto ON_EXIT;
+  }
+
+  ASSERT (Mode.State == Dhcp4Bound);
+  CopyMem (&Private->StationIp, &Mode.ClientAddress, sizeof 
(EFI_IPv4_ADDRESS));
+  CopyMem (&Private->SubnetMask, &Mode.SubnetMask, sizeof (EFI_IPv4_ADDRESS));
+  CopyMem (&Private->GatewayIp, &Mode.RouterAddress, sizeof 
(EFI_IPv4_ADDRESS));
+
+  Status = HttpBootRegisterIp4Gateway (Private);
+  if (EFI_ERROR (Status)) {
+    goto ON_EXIT;
+  }
+
+  AsciiPrint ("\n  Station IP address is ");
+  HttpBootShowIp4Addr (&Private->StationIp.v4);
+  AsciiPrint ("\n");
+
+ON_EXIT:
+  if (EFI_ERROR (Status)) {
+    Dhcp4->Stop (Dhcp4);
+    Dhcp4->Configure (Dhcp4, NULL);
+  } else {
+    ZeroMem (&Config, sizeof (EFI_DHCP4_CONFIG_DATA));
+    Dhcp4->Configure (Dhcp4, &Config);
+  }
+
+  return Status;
+}

Added: trunk/edk2/NetworkPkg/HttpBootDxe/HttpBootDhcp4.h
===================================================================
--- trunk/edk2/NetworkPkg/HttpBootDxe/HttpBootDhcp4.h                           
(rev 0)
+++ trunk/edk2/NetworkPkg/HttpBootDxe/HttpBootDhcp4.h   2015-07-07 09:29:28 UTC 
(rev 17857)
@@ -0,0 +1,279 @@
+/** @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
+#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

Added: trunk/edk2/NetworkPkg/HttpBootDxe/HttpBootDxe.c
===================================================================
--- trunk/edk2/NetworkPkg/HttpBootDxe/HttpBootDxe.c                             
(rev 0)
+++ trunk/edk2/NetworkPkg/HttpBootDxe/HttpBootDxe.c     2015-07-07 09:29:28 UTC 
(rev 17857)
@@ -0,0 +1,559 @@
+/** @file
+  Driver Binding functions implementation for UEFI HTTP boot.
+
+Copyright (c) 2015, Intel Corporation. All rights reserved.<BR>
+This program and the accompanying materials are licensed and made available 
under 
+the terms and conditions of the BSD License that accompanies this 
distribution.  
+The full text of the license may be found at
+http://opensource.org/licenses/bsd-license.php.                                
          
+    
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,          
           
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.  
           
+
+**/
+
+#include "HttpBootDxe.h"
+
+///
+/// Driver Binding Protocol instance
+///
+EFI_DRIVER_BINDING_PROTOCOL gHttpBootIp4DxeDriverBinding = {
+  HttpBootIp4DxeDriverBindingSupported,
+  HttpBootIp4DxeDriverBindingStart,
+  HttpBootIp4DxeDriverBindingStop,
+  HTTP_BOOT_DXE_VERSION,
+  NULL,
+  NULL
+};
+
+/**
+  Destroy the HTTP child based on IPv4 stack.
+
+  @param[in]  This              Pointer to the EFI_DRIVER_BINDING_PROTOCOL.
+  @param[in]  Private           Pointer to HTTP_BOOT_PRIVATE_DATA.
+
+**/
+VOID
+HttpBootDestroyIp4Children (
+  IN EFI_DRIVER_BINDING_PROTOCOL  *This,
+  IN HTTP_BOOT_PRIVATE_DATA       *Private
+  )
+{
+  ASSERT (This != NULL);
+  ASSERT (Private != NULL);
+  ASSERT (Private->UsingIpv6 == FALSE);
+
+  if (Private->Dhcp4Child != NULL) {
+    gBS->CloseProtocol (
+          Private->Dhcp4Child,
+          &gEfiDhcp4ProtocolGuid,
+          This->DriverBindingHandle,
+          Private->Controller
+          );
+
+    NetLibDestroyServiceChild (
+      Private->Controller,
+      This->DriverBindingHandle,
+      &gEfiDhcp4ServiceBindingProtocolGuid,
+      Private->Dhcp4Child
+      );
+  }
+
+  if (Private->HttpCreated) {
+    HttpIoDestroyIo (&Private->HttpIo);
+    Private->HttpCreated = FALSE;
+  }
+
+  gBS->CloseProtocol (
+         Private->Controller,
+         &gEfiCallerIdGuid,
+         This->DriverBindingHandle,
+         Private->ChildHandle
+         );
+
+  gBS->UninstallMultipleProtocolInterfaces (
+         Private->ChildHandle,
+         &gEfiLoadFileProtocolGuid,
+         &Private->LoadFile,
+         &gEfiDevicePathProtocolGuid,
+         Private->DevicePath,
+         NULL
+         );
+
+  if (Private->DevicePath != NULL) {
+    FreePool (Private->DevicePath);
+    Private->DevicePath = NULL;
+  }
+}
+
+/**
+  Tests to see if this driver supports a given controller. If a child device 
is provided, 
+  it further tests to see if this driver supports creating a handle for the 
specified child device.
+
+  This function checks to see if the driver specified by This supports the 
device specified by 
+  ControllerHandle. Drivers will typically use the device path attached to 
+  ControllerHandle and/or the services from the bus I/O abstraction attached 
to 
+  ControllerHandle to determine if the driver supports ControllerHandle. This 
function 
+  may be called many times during platform initialization. In order to reduce 
boot times, the tests 
+  performed by this function must be very small, and take as little time as 
possible to execute. This 
+  function must not change the state of any hardware devices, and this 
function must be aware that the 
+  device specified by ControllerHandle may already be managed by the same 
driver or a 
+  different driver. This function must match its calls to AllocatePages() with 
FreePages(), 
+  AllocatePool() with FreePool(), and OpenProtocol() with CloseProtocol().  
+  Because ControllerHandle may have been previously started by the same 
driver, if a protocol is 
+  already in the opened state, then it must not be closed with 
CloseProtocol(). This is required 
+  to guarantee the state of ControllerHandle is not modified by this function.
+
+  @param[in]  This                 A pointer to the 
EFI_DRIVER_BINDING_PROTOCOL instance.
+  @param[in]  ControllerHandle     The handle of the controller to test. This 
handle 
+                                   must support a protocol interface that 
supplies 
+                                   an I/O abstraction to the driver.
+  @param[in]  RemainingDevicePath  A pointer to the remaining portion of a 
device path.  This 
+                                   parameter is ignored by device drivers, and 
is optional for bus 
+                                   drivers. For bus drivers, if this parameter 
is not NULL, then 
+                                   the bus driver must determine if the bus 
controller specified 
+                                   by ControllerHandle and the child 
controller specified 
+                                   by RemainingDevicePath are both supported 
by this 
+                                   bus driver.
+
+  @retval EFI_SUCCESS              The device specified by ControllerHandle and
+                                   RemainingDevicePath is supported by the 
driver specified by This.
+  @retval EFI_ALREADY_STARTED      The device specified by ControllerHandle and
+                                   RemainingDevicePath is already being 
managed by the driver
+                                   specified by This.
+  @retval EFI_ACCESS_DENIED        The device specified by ControllerHandle and
+                                   RemainingDevicePath is already being 
managed by a different
+                                   driver or an application that requires 
exclusive access.
+                                   Currently not implemented.
+  @retval EFI_UNSUPPORTED          The device specified by ControllerHandle and
+                                   RemainingDevicePath is not supported by the 
driver specified by This.
+**/
+EFI_STATUS
+EFIAPI
+HttpBootIp4DxeDriverBindingSupported (
+  IN EFI_DRIVER_BINDING_PROTOCOL  *This,
+  IN EFI_HANDLE                   ControllerHandle,
+  IN EFI_DEVICE_PATH_PROTOCOL     *RemainingDevicePath OPTIONAL
+  )
+{
+  EFI_STATUS                    Status;
+  
+  //
+  // Try to open the DHCP4, HTTP4 and Device Path protocol.
+  //
+  Status = gBS->OpenProtocol (
+                   ControllerHandle,
+                   &gEfiDhcp4ServiceBindingProtocolGuid,
+                   NULL,
+                   This->DriverBindingHandle,
+                   ControllerHandle,
+                   EFI_OPEN_PROTOCOL_TEST_PROTOCOL
+                   );
+  if (EFI_ERROR (Status)) {
+    return Status;
+  }
+
+  Status = gBS->OpenProtocol (
+                   ControllerHandle,
+                   &gEfiHttpServiceBindingProtocolGuid,
+                   NULL,
+                   This->DriverBindingHandle,
+                   ControllerHandle,
+                   EFI_OPEN_PROTOCOL_TEST_PROTOCOL
+                   );
+  if (EFI_ERROR (Status)) {
+    return Status;
+  }
+
+  Status = gBS->OpenProtocol (
+                   ControllerHandle,
+                   &gEfiDevicePathProtocolGuid,
+                   NULL,
+                   This->DriverBindingHandle,
+                   ControllerHandle,
+                   EFI_OPEN_PROTOCOL_TEST_PROTOCOL
+                   );
+
+  return Status;
+}
+
+
+/**
+  Starts a device controller or a bus controller.
+
+  The Start() function is designed to be invoked from the EFI boot service 
ConnectController().
+  As a result, much of the error checking on the parameters to Start() has 
been moved into this 
+  common boot service. It is legal to call Start() from other locations, 
+  but the following calling restrictions must be followed, or the system 
behavior will not be deterministic.
+  1. ControllerHandle must be a valid EFI_HANDLE.
+  2. If RemainingDevicePath is not NULL, then it must be a pointer to a 
naturally aligned
+     EFI_DEVICE_PATH_PROTOCOL.
+  3. Prior to calling Start(), the Supported() function for the driver 
specified by This must
+     have been called with the same calling parameters, and Supported() must 
have returned EFI_SUCCESS.  
+
+  @param[in]  This                 A pointer to the 
EFI_DRIVER_BINDING_PROTOCOL instance.
+  @param[in]  ControllerHandle     The handle of the controller to start. This 
handle 
+                                   must support a protocol interface that 
supplies 
+                                   an I/O abstraction to the driver.
+  @param[in]  RemainingDevicePath  A pointer to the remaining portion of a 
device path.  This 
+                                   parameter is ignored by device drivers, and 
is optional for bus 
+                                   drivers. For a bus driver, if this 
parameter is NULL, then handles 
+                                   for all the children of Controller are 
created by this driver.  
+                                   If this parameter is not NULL and the first 
Device Path Node is 
+                                   not the End of Device Path Node, then only 
the handle for the 
+                                   child device specified by the first Device 
Path Node of 
+                                   RemainingDevicePath is created by this 
driver.
+                                   If the first Device Path Node of 
RemainingDevicePath is 
+                                   the End of Device Path Node, no child 
handle is created by this
+                                   driver.
+
+  @retval EFI_SUCCESS              The device was started.
+  @retval EFI_DEVICE_ERROR         The device could not be started due to a 
device error.Currently not implemented.
+  @retval EFI_OUT_OF_RESOURCES     The request could not be completed due to a 
lack of resources.
+  @retval Others                   The driver failded to start the device.
+
+**/
+EFI_STATUS
+EFIAPI
+HttpBootIp4DxeDriverBindingStart (
+  IN EFI_DRIVER_BINDING_PROTOCOL  *This,
+  IN EFI_HANDLE                   ControllerHandle,
+  IN EFI_DEVICE_PATH_PROTOCOL     *RemainingDevicePath OPTIONAL
+  )
+{
+  EFI_STATUS                 Status;
+  HTTP_BOOT_PRIVATE_DATA     *Private;
+  EFI_DEV_PATH               *Node;
+  EFI_DEVICE_PATH_PROTOCOL   *DevicePath;
+  UINT32                     *Id;
+
+  Status = gBS->OpenProtocol (
+                  ControllerHandle,
+                  &gEfiCallerIdGuid,
+                  (VOID **) &Id,
+                  This->DriverBindingHandle,
+                  ControllerHandle,
+                  EFI_OPEN_PROTOCOL_GET_PROTOCOL
+                  );
+  if (!EFI_ERROR (Status)) {
+    return EFI_ALREADY_STARTED;
+  }
+
+  //
+  // Initialize the private data structure.
+  //
+  Private = AllocateZeroPool (sizeof (HTTP_BOOT_PRIVATE_DATA));
+  if (Private == NULL) {
+    return EFI_OUT_OF_RESOURCES;
+  }
+  Private->Signature = HTTP_BOOT_PRIVATE_DATA_SIGNATURE;
+  Private->Controller = ControllerHandle;
+  Private->Image = This->ImageHandle;
+  Private->UsingIpv6 = FALSE;
+  InitializeListHead (&Private->CacheList);
+
+  //
+  // Create DHCP child instance.
+  //
+  Status = NetLibCreateServiceChild (
+             ControllerHandle,
+             This->DriverBindingHandle,
+             &gEfiDhcp4ServiceBindingProtocolGuid,
+             &Private->Dhcp4Child
+             );
+  if (EFI_ERROR (Status)) {
+    goto ON_ERROR;
+  }
+
+  Status = gBS->OpenProtocol (
+                  Private->Dhcp4Child,
+                  &gEfiDhcp4ProtocolGuid,
+                  (VOID **) &Private->Dhcp4,
+                  This->DriverBindingHandle,
+                  ControllerHandle,
+                  EFI_OPEN_PROTOCOL_BY_DRIVER
+                  );
+  if (EFI_ERROR (Status)) {
+    goto ON_ERROR;
+  }
+
+  //
+  // Get the Ip4Config2 protocol, it's required to configure the default 
gateway address.
+  //
+  Status = gBS->OpenProtocol (
+                  ControllerHandle,
+                  &gEfiIp4Config2ProtocolGuid,
+                  (VOID **) &Private->Ip4Config2,
+                  This->DriverBindingHandle,
+                  ControllerHandle,
+                  EFI_OPEN_PROTOCOL_GET_PROTOCOL
+                  );
+  if (EFI_ERROR (Status)) {
+    goto ON_ERROR;
+  }
+
+  //
+  // Get the NII interface if it exists, it's not required.
+  //
+  Status = gBS->OpenProtocol (
+                  ControllerHandle,
+                  &gEfiNetworkInterfaceIdentifierProtocolGuid_31,
+                  (VOID **) &Private->Nii,
+                  This->DriverBindingHandle,
+                  ControllerHandle,
+                  EFI_OPEN_PROTOCOL_GET_PROTOCOL
+                  );
+  if (EFI_ERROR (Status)) {
+    Private->Nii = NULL;
+  }
+
+  //
+  // Open Device Path Protocol to prepare for appending IP and URI node.
+  //
+  Status = gBS->OpenProtocol (
+                  ControllerHandle,
+                  &gEfiDevicePathProtocolGuid,
+                  (VOID **) &Private->ParentDevicePath,
+                  This->DriverBindingHandle,
+                  ControllerHandle,
+                  EFI_OPEN_PROTOCOL_GET_PROTOCOL
+                  );
+  if (EFI_ERROR (Status)) {
+    goto ON_ERROR;
+  }
+
+  //
+  // Append IPv4 device path node.
+  //
+  Node = AllocateZeroPool (sizeof (IPv4_DEVICE_PATH));
+  if (Node == NULL) {
+    Status = EFI_OUT_OF_RESOURCES;
+    goto ON_ERROR;
+  }
+  Node->Ipv4.Header.Type = MESSAGING_DEVICE_PATH;
+  Node->Ipv4.Header.SubType = MSG_IPv4_DP;
+  SetDevicePathNodeLength (Node, sizeof (IPv4_DEVICE_PATH));
+  Node->Ipv4.StaticIpAddress = FALSE;
+  DevicePath = AppendDevicePathNode (Private->ParentDevicePath, 
(EFI_DEVICE_PATH_PROTOCOL*) Node);
+  FreePool (Node);
+  if (DevicePath == NULL) {
+    Status = EFI_OUT_OF_RESOURCES;
+    goto ON_ERROR;
+  }
+
+  //
+  // Append URI device path node.
+  //
+  Node = AllocateZeroPool (sizeof (EFI_DEVICE_PATH_PROTOCOL));
+  if (Node == NULL) {
+    Status = EFI_OUT_OF_RESOURCES;
+    goto ON_ERROR;
+  }
+  Node->DevPath.Type = MESSAGING_DEVICE_PATH;
+  Node->DevPath.SubType = MSG_URI_DP;
+  SetDevicePathNodeLength (Node, sizeof (EFI_DEVICE_PATH_PROTOCOL));
+  Private->DevicePath = AppendDevicePathNode (DevicePath, 
(EFI_DEVICE_PATH_PROTOCOL*) Node);
+  FreePool (Node);
+  FreePool (DevicePath);
+  if (Private->DevicePath == NULL) {
+    Status = EFI_OUT_OF_RESOURCES;
+    goto ON_ERROR;
+  }
+
+  //
+  // Create a child handle for the HTTP boot and install DevPath and Load file 
protocol on it.
+  //
+  CopyMem (&Private->LoadFile, &gHttpBootDxeLoadFile, sizeof 
(Private->LoadFile));
+  Status = gBS->InstallMultipleProtocolInterfaces (
+                  &Private->ChildHandle,
+                  &gEfiLoadFileProtocolGuid,
+                  &Private->LoadFile,
+                  &gEfiDevicePathProtocolGuid,
+                  Private->DevicePath,
+                  NULL
+                  );
+  if (EFI_ERROR (Status)) {
+    goto ON_ERROR;
+  }
+
+  //
+  // Install a protocol with Caller Id Guid to the NIC, this is just to build 
the relationship between
+  // NIC handle and the private data.
+  //
+  Status = gBS->InstallProtocolInterface (
+                  &ControllerHandle,
+                  &gEfiCallerIdGuid,
+                  EFI_NATIVE_INTERFACE,
+                  &Private->Id
+                  );
+  if (EFI_ERROR (Status)) {
+    goto ON_ERROR;
+  }
+
+  //
+  // Open the Caller Id child to setup a parent-child relationship between
+  // real NIC handle and the HTTP boot child handle.
+  //
+  Status = gBS->OpenProtocol (
+                  ControllerHandle,
+                  &gEfiCallerIdGuid,
+                  (VOID **) &Id,
+                  This->DriverBindingHandle,
+                  Private->ChildHandle,
+                  EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER
+                  );
+  if (EFI_ERROR (Status)) {
+    goto ON_ERROR;
+  }
+
+  return EFI_SUCCESS;
+
+ON_ERROR:
+  
+  HttpBootDestroyIp4Children (This, Private);
+  FreePool (Private);
+
+  return Status;
+}
+
+/**
+  Stops a device controller or a bus controller.
+  
+  The Stop() function is designed to be invoked from the EFI boot service 
DisconnectController(). 
+  As a result, much of the error checking on the parameters to Stop() has been 
moved 
+  into this common boot service. It is legal to call Stop() from other 
locations, 
+  but the following calling restrictions must be followed, or the system 
behavior will not be deterministic.
+  1. ControllerHandle must be a valid EFI_HANDLE that was used on a previous 
call to this
+     same driver's Start() function.
+  2. The first NumberOfChildren handles of ChildHandleBuffer must all be a 
valid
+     EFI_HANDLE. In addition, all of these handles must have been created in 
this driver's
+     Start() function, and the Start() function must have called 
OpenProtocol() on
+     ControllerHandle with an Attribute of 
EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER.
+  
+  @param[in]  This              A pointer to the EFI_DRIVER_BINDING_PROTOCOL 
instance.
+  @param[in]  ControllerHandle  A handle to the device being stopped. The 
handle must 
+                                support a bus specific I/O protocol for the 
driver 
+                                to use to stop the device.
+  @param[in]  NumberOfChildren  The number of child device handles in 
ChildHandleBuffer.
+  @param[in]  ChildHandleBuffer An array of child handles to be freed. May be 
NULL 
+                                if NumberOfChildren is 0.
+
+  @retval EFI_SUCCESS           The device was stopped.
+  @retval EFI_DEVICE_ERROR      The device could not be stopped due to a 
device error.
+
+**/
+EFI_STATUS
+EFIAPI
+HttpBootIp4DxeDriverBindingStop (
+  IN EFI_DRIVER_BINDING_PROTOCOL  *This,
+  IN EFI_HANDLE                   ControllerHandle,
+  IN UINTN                        NumberOfChildren,
+  IN EFI_HANDLE                   *ChildHandleBuffer OPTIONAL
+  )
+{
+  EFI_STATUS                      Status;
+  EFI_LOAD_FILE_PROTOCOL          *LoadFile;
+  HTTP_BOOT_PRIVATE_DATA          *Private;
+  EFI_HANDLE                      NicHandle;
+  UINT32                          *Id;
+
+  //
+  // Try to get the Load File Protocol from the controller handle.
+  //
+  Status = gBS->OpenProtocol (
+                  ControllerHandle,
+                  &gEfiLoadFileProtocolGuid,
+                  (VOID **) &LoadFile,
+                  This->DriverBindingHandle,
+                  ControllerHandle,
+                  EFI_OPEN_PROTOCOL_GET_PROTOCOL
+                  );
+  if (EFI_ERROR (Status)) {
+    //
+    // If failed, try to find the NIC handle for this controller.
+    //
+    NicHandle = HttpBootGetNicByIp4Children (ControllerHandle);
+    if (NicHandle == NULL) {
+      return EFI_SUCCESS;
+    }
+
+    //
+    // Try to retrieve the private data by the Caller Id Guid.
+    //
+    Status = gBS->OpenProtocol (
+                    NicHandle,
+                    &gEfiCallerIdGuid,
+                    (VOID **) &Id,
+                    This->DriverBindingHandle,
+                    ControllerHandle,
+                    EFI_OPEN_PROTOCOL_GET_PROTOCOL
+                    );
+    if (EFI_ERROR (Status)) {
+      return Status;
+    }
+    Private = HTTP_BOOT_PRIVATE_DATA_FROM_ID (Id);
+  } else {
+    Private = HTTP_BOOT_PRIVATE_DATA_FROM_LOADFILE (LoadFile);
+    NicHandle = Private->Controller;
+  }
+
+  //
+  // Disable the HTTP boot function.
+  //
+  Status = HttpBootStop (Private);
+  if (Status != EFI_SUCCESS && Status != EFI_NOT_STARTED) {
+    return Status;
+  }
+
+  //
+  // Destory all child instance and uninstall protocol interface.
+  //
+  HttpBootDestroyIp4Children (This, Private);
+
+  //
+  // Release the cached data.
+  //
+  HttpBootFreeCacheList (Private);
+
+  gBS->UninstallProtocolInterface (
+         NicHandle,
+         &gEfiCallerIdGuid,
+         &Private->Id
+         );
+  FreePool (Private);
+
+  return EFI_SUCCESS;
+}
+
+/**
+  This is the declaration of an EFI image entry point. This entry point is
+  the same for UEFI Applications, UEFI OS Loaders, and UEFI Drivers including
+  both device drivers and bus drivers.
+
+  @param[in]  ImageHandle       The firmware allocated handle for the UEFI 
image.
+  @param[in]  SystemTable       A pointer to the EFI System Table.
+
+  @retval EFI_SUCCESS           The operation completed successfully.
+  @retval Others                An unexpected error occurred.
+
+**/
+EFI_STATUS
+EFIAPI
+HttpBootDxeDriverEntryPoint (
+  IN EFI_HANDLE        ImageHandle,
+  IN EFI_SYSTEM_TABLE  *SystemTable
+  )
+{
+  //
+  // Install UEFI Driver Model protocol(s).
+  //
+  return EfiLibInstallDriverBindingComponentName2 (
+           ImageHandle,
+           SystemTable,

@@ Diff output truncated at 100000 characters. @@

------------------------------------------------------------------------------
Don't Limit Your Business. Reach for the Cloud.
GigeNET's Cloud Solutions provide you with the tools and support that
you need to offload your IT needs and focus on growing your business.
Configured For All Businesses. Start Your Cloud Today.
https://www.gigenetcloud.com/
_______________________________________________
edk2-commits mailing list
edk2-commits@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/edk2-commits

Reply via email to