Looks good to me.
Reviewed-by: Ye Ting <ting...@intel.com> 

-----Original Message-----
From: Fu, Siyuan 
Sent: Friday, March 04, 2016 4:40 PM
To: Fu, Siyuan <siyuan...@intel.com>; edk2-devel@lists.01.org
Cc: Ye, Ting <ting...@intel.com>; Wu, Jiaxin <jiaxin...@intel.com>
Subject: RE: [edk2] [PATCH v3] NetworkPkg: Add URI configuration form to HTTP 
boot driver.

V3 changes:
Update the driver to handle an empty URI device node.


> -----Original Message-----
> From: edk2-devel [mailto:edk2-devel-boun...@lists.01.org] On Behalf Of Fu
> Siyuan
> Sent: Friday, March 4, 2016 4:38 PM
> To: edk2-devel@lists.01.org
> Cc: Ye, Ting <ting...@intel.com>; Wu, Jiaxin <jiaxin...@intel.com>
> Subject: [edk2] [PATCH v3] NetworkPkg: Add URI configuration form to HTTP
> boot driver.
> 
> This patch updates the HTTP boot driver to produce a setup page for the boot
> file URI configuration. A new boot option will be created for the manual
> configured URI address. This change is made to support the HTTP boot usage
> in home environment.
> 
> Contributed-under: TianoCore Contribution Agreement 1.0
> Signed-off-by: Fu Siyuan <siyuan...@intel.com>
> Cc: Wu Jiaxin <jiaxin...@intel.com>
> Cc: Ye Ting <ting...@intel.com>
> ---
>  NetworkPkg/HttpBootDxe/HttpBootClient.c            |  99 +--
>  NetworkPkg/HttpBootDxe/HttpBootConfig.c            | 723
> +++++++++++++++++++++
>  NetworkPkg/HttpBootDxe/HttpBootConfig.h            |  78 +++
>  NetworkPkg/HttpBootDxe/HttpBootConfigNVDataStruc.h |  43 ++
>  NetworkPkg/HttpBootDxe/HttpBootConfigStrings.uni   | Bin 0 -> 2926 bytes
>  NetworkPkg/HttpBootDxe/HttpBootConfigVfr.vfr       |  53 ++
>  NetworkPkg/HttpBootDxe/HttpBootDhcp4.c             | 111 +++-
>  NetworkPkg/HttpBootDxe/HttpBootDhcp4.h             |   9 +-
>  NetworkPkg/HttpBootDxe/HttpBootDhcp6.c             |   6 +-
>  NetworkPkg/HttpBootDxe/HttpBootDxe.c               |  44 +-
>  NetworkPkg/HttpBootDxe/HttpBootDxe.h               |  33 +-
>  NetworkPkg/HttpBootDxe/HttpBootDxe.inf             |  17 +-
>  NetworkPkg/HttpBootDxe/HttpBootImpl.c              |  71 +-
>  NetworkPkg/HttpBootDxe/HttpBootSupport.c           |  63 ++
>  NetworkPkg/HttpBootDxe/HttpBootSupport.h           |  18 +
>  NetworkPkg/Include/Guid/HttpBootConfigHii.h        |  25 +
>  NetworkPkg/NetworkPkg.dec                          |   5 +-
>  17 files changed, 1288 insertions(+), 110 deletions(-)
>  create mode 100644 NetworkPkg/HttpBootDxe/HttpBootConfig.c
>  create mode 100644 NetworkPkg/HttpBootDxe/HttpBootConfig.h
>  create mode 100644
> NetworkPkg/HttpBootDxe/HttpBootConfigNVDataStruc.h
>  create mode 100644 NetworkPkg/HttpBootDxe/HttpBootConfigStrings.uni
>  create mode 100644 NetworkPkg/HttpBootDxe/HttpBootConfigVfr.vfr
>  create mode 100644 NetworkPkg/Include/Guid/HttpBootConfigHii.h
> 
> diff --git a/NetworkPkg/HttpBootDxe/HttpBootClient.c
> b/NetworkPkg/HttpBootDxe/HttpBootClient.c
> index 2ccac8c..aae4527 100644
> --- a/NetworkPkg/HttpBootDxe/HttpBootClient.c
> +++ b/NetworkPkg/HttpBootDxe/HttpBootClient.c
> @@ -168,18 +168,35 @@ HttpBootDhcp4ExtractUriInfo (
>    // HttpOffer contains the boot file URL.
>    //
>    SelectOffer = &Private->OfferBuffer[SelectIndex].Dhcp4;
> -  if ((SelectOffer->OfferType == HttpOfferTypeDhcpIpUri) || (SelectOffer-
> >OfferType == HttpOfferTypeDhcpNameUriDns)) {
> -    HttpOffer = SelectOffer;
> +  if (Private->FilePathUri == NULL) {
> +    //
> +    // In Corporate environment, we need a HttpOffer.
> +    //
> +    if ((SelectOffer->OfferType == HttpOfferTypeDhcpIpUri) ||
> +        (SelectOffer->OfferType == HttpOfferTypeDhcpIpUriDns) ||
> +        (SelectOffer->OfferType == HttpOfferTypeDhcpNameUriDns)) {
> +      HttpOffer = SelectOffer;
> +    } else {
> +      ASSERT (Private->SelectProxyType != HttpOfferTypeMax);
> +      ProxyIndex = Private->OfferIndex[Private->SelectProxyType][0];
> +      HttpOffer = &Private->OfferBuffer[ProxyIndex].Dhcp4;
> +    }
> +    Private->BootFileUriParser = HttpOffer->UriParser;
> +    Private->BootFileUri = (CHAR8*) HttpOffer-
> >OptList[HTTP_BOOT_DHCP4_TAG_INDEX_BOOTFILE]->Data;
>    } else {
> -    ASSERT (Private->SelectProxyType != HttpOfferTypeMax);
> -    ProxyIndex = Private->OfferIndex[Private->SelectProxyType][0];
> -    HttpOffer = &Private->OfferBuffer[ProxyIndex].Dhcp4;
> +    //
> +    // In Home environment the BootFileUri comes from the FilePath.
> +    //
> +    Private->BootFileUriParser = Private->FilePathUriParser;
> +    Private->BootFileUri = Private->FilePathUri;
>    }
> 
>    //
>    // Configure the default DNS server if server assigned.
>    //
> -  if ((SelectOffer->OfferType == HttpOfferTypeDhcpNameUriDns) ||
> (SelectOffer->OfferType == HttpOfferTypeDhcpDns)) {
> +  if ((SelectOffer->OfferType == HttpOfferTypeDhcpNameUriDns) ||
> +      (SelectOffer->OfferType == HttpOfferTypeDhcpDns) ||
> +      (SelectOffer->OfferType == HttpOfferTypeDhcpIpUriDns)) {
>      Option = SelectOffer-
> >OptList[HTTP_BOOT_DHCP4_TAG_INDEX_DNS_SERVER];
>      ASSERT (Option != NULL);
>      Status = HttpBootRegisterIp4Dns (
> @@ -196,8 +213,8 @@ HttpBootDhcp4ExtractUriInfo (
>    // 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->BootFileUri,
> +             Private->BootFileUriParser,
>               &Private->Port
>               );
>    if (EFI_ERROR (Status) || Private->Port == 0) {
> @@ -205,13 +222,6 @@ HttpBootDhcp4ExtractUriInfo (
>    }
> 
>    //
> -  // 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);
> @@ -260,12 +270,27 @@ HttpBootDhcp6ExtractUriInfo (
>    // HttpOffer contains the boot file URL.
>    //
>    SelectOffer = &Private->OfferBuffer[SelectIndex].Dhcp6;
> -  if ((SelectOffer->OfferType == HttpOfferTypeDhcpIpUri) || (SelectOffer-
> >OfferType == HttpOfferTypeDhcpNameUriDns)) {
> -    HttpOffer = SelectOffer;
> +  if (Private->FilePathUri == NULL) {
> +    //
> +    // In Corporate environment, we need a HttpOffer.
> +    //
> +    if ((SelectOffer->OfferType == HttpOfferTypeDhcpIpUri) ||
> +        (SelectOffer->OfferType == HttpOfferTypeDhcpIpUriDns) ||
> +        (SelectOffer->OfferType == HttpOfferTypeDhcpNameUriDns)) {
> +      HttpOffer = SelectOffer;
> +    } else {
> +      ASSERT (Private->SelectProxyType != HttpOfferTypeMax);
> +      ProxyIndex = Private->OfferIndex[Private->SelectProxyType][0];
> +      HttpOffer = &Private->OfferBuffer[ProxyIndex].Dhcp6;
> +    }
> +    Private->BootFileUriParser = HttpOffer->UriParser;
> +    Private->BootFileUri = (CHAR8*) HttpOffer-
> >OptList[HTTP_BOOT_DHCP6_IDX_BOOT_FILE_URL]->Data;
>    } else {
> -    ASSERT (Private->SelectProxyType != HttpOfferTypeMax);
> -    ProxyIndex = Private->OfferIndex[Private->SelectProxyType][0];
> -    HttpOffer = &Private->OfferBuffer[ProxyIndex].Dhcp6;
> +    //
> +    // In Home environment the BootFileUri comes from the FilePath.
> +    //
> +    Private->BootFileUriParser = Private->FilePathUriParser;
> +    Private->BootFileUri = Private->FilePathUri;
>    }
> 
>    //
> @@ -279,7 +304,9 @@ HttpBootDhcp6ExtractUriInfo (
>    //
>    // Configure the default DNS server if server assigned.
>    //
> -  if ((SelectOffer->OfferType == HttpOfferTypeDhcpNameUriDns) ||
> (SelectOffer->OfferType == HttpOfferTypeDhcpDns)) {
> +  if ((SelectOffer->OfferType == HttpOfferTypeDhcpNameUriDns) ||
> +      (SelectOffer->OfferType == HttpOfferTypeDhcpDns) ||
> +      (SelectOffer->OfferType == HttpOfferTypeDhcpIpUriDns)) {
>      Option = SelectOffer->OptList[HTTP_BOOT_DHCP6_IDX_DNS_SERVER];
>      ASSERT (Option != NULL);
>      Status = HttpBootSetIp6Dns (
> @@ -297,8 +324,8 @@ HttpBootDhcp6ExtractUriInfo (
>    // whether can send message to HTTP Server Ip through the GateWay.
>    //
>    Status = HttpUrlGetIp6 (
> -             (CHAR8*) HttpOffer-
> >OptList[HTTP_BOOT_DHCP6_IDX_BOOT_FILE_URL]->Data,
> -             HttpOffer->UriParser,
> +             Private->BootFileUri,
> +             Private->BootFileUriParser,
>               &IpAddr
>               );
> 
> @@ -307,8 +334,8 @@ HttpBootDhcp6ExtractUriInfo (
>      // The Http server address is expressed by Name Ip, so perform DNS
> resolution
>      //
>      Status = HttpUrlGetHostName (
> -               (CHAR8*) HttpOffer-
> >OptList[HTTP_BOOT_DHCP6_IDX_BOOT_FILE_URL]->Data,
> -               HttpOffer->UriParser,
> +               Private->BootFileUri,
> +               Private->BootFileUriParser,
>                 &HostName
>                 );
>      if (EFI_ERROR (Status)) {
> @@ -343,8 +370,8 @@ HttpBootDhcp6ExtractUriInfo (
>    // Extract the port from URL, and use default HTTP port 80 if not provided.
>    //
>    Status = HttpUrlGetPort (
> -             (CHAR8*) HttpOffer-
> >OptList[HTTP_BOOT_DHCP6_IDX_BOOT_FILE_URL]->Data,
> -             HttpOffer->UriParser,
> +             Private->BootFileUri,
> +             Private->BootFileUriParser,
>               &Private->Port
>               );
>    if (EFI_ERROR (Status) || Private->Port == 0) {
> @@ -352,13 +379,6 @@ HttpBootDhcp6ExtractUriInfo (
>    }
> 
>    //
> -  // Record the URI of boot file from the selected HTTP offer.
> -  //
> -  Private->BootFileUriParser = HttpOffer->UriParser;
> -  Private->BootFileUri = (CHAR8*) HttpOffer-
> >OptList[HTTP_BOOT_DHCP6_IDX_BOOT_FILE_URL]->Data;
> -
> -
> -  //
>    // All boot informations are valid here.
>    //
>    AsciiPrint ("\n  URI: %a", Private->BootFileUri);
> @@ -570,10 +590,6 @@ HttpBootGetFileFromCache (
>      return EFI_INVALID_PARAMETER;
>    }
> 
> -  //
> -  // Search file in the cache list, the cache entry will be released upon a
> successful
> -  // match.
> -  //
>    NET_LIST_FOR_EACH (Entry, &Private->CacheList) {
>      Cache = NET_LIST_USER_STRUCT (Entry, HTTP_BOOT_CACHE_CONTENT,
> Link);
>      //
> @@ -607,12 +623,6 @@ HttpBootGetFileFromCache (
>          }
>        }
>        *BufferSize = CopyedSize;
> -
> -      //
> -      // On success, free the cached data to release the memory resource.
> -      //
> -      RemoveEntryList (&Cache->Link);
> -      HttpBootFreeCache (Cache);
>        return EFI_SUCCESS;
>      }
>    }
> @@ -1083,3 +1093,4 @@ ERROR_1:
> 
>    return Status;
>  }
> +
> diff --git a/NetworkPkg/HttpBootDxe/HttpBootConfig.c
> b/NetworkPkg/HttpBootDxe/HttpBootConfig.c
> new file mode 100644
> index 0000000..db14da0
> --- /dev/null
> +++ b/NetworkPkg/HttpBootDxe/HttpBootConfig.c
> @@ -0,0 +1,723 @@
> +/** @file
> +  Helper functions for configuring or getting the parameters relating to HTTP
> Boot.
> +
> +Copyright (c) 2016, Intel Corporation. All rights reserved.<BR>
> +This program and the accompanying materials
> +are licensed and made available under the terms and conditions of the BSD
> License
> +which accompanies this distribution.  The full text of the license may be
> found at
> +http://opensource.org/licenses/bsd-license.php
> +
> +THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS"
> BASIS,
> +WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER
> EXPRESS OR IMPLIED.
> +
> +**/
> +
> +#include "HttpBootDxe.h"
> +
> +CHAR16  mHttpBootConfigStorageName[]     =
> L"HTTP_BOOT_CONFIG_IFR_NVDATA";
> +
> +/**
> +  Add new boot option for HTTP boot.
> +
> +  @param[in]  Private             Pointer to the driver private data.
> +  @param[in]  UsingIpv6           Set to TRUE if creating boot option for 
> IPv6.
> +  @param[in]  Description         The description text of the boot option.
> +  @param[in]  Uri                 The URI string of the boot file.
> +
> +  @retval EFI_SUCCESS             The boot option is created successfully.
> +  @retval Others                  Failed to create new boot option.
> +
> +**/
> +EFI_STATUS
> +HttpBootAddBootOption (
> +  IN   HTTP_BOOT_PRIVATE_DATA   *Private,
> +  IN   BOOLEAN                  UsingIpv6,
> +  IN   CHAR16                   *Description,
> +  IN   CHAR16                   *Uri
> +  )
> +{
> +  EFI_DEV_PATH               *Node;
> +  EFI_DEVICE_PATH_PROTOCOL   *TmpDevicePath;
> +  EFI_DEVICE_PATH_PROTOCOL   *NewDevicePath;
> +  UINTN                      Length;
> +  CHAR8                      AsciiUri[URI_STR_MAX_SIZE];
> +  CHAR16                     *CurrentOrder;
> +  EFI_STATUS                 Status;
> +  UINTN                      OrderCount;
> +  UINTN                      TargetLocation;
> +  BOOLEAN                    Found;
> +  UINT8                      *TempByteBuffer;
> +  UINT8                      *TempByteStart;
> +  UINTN                      DescSize;
> +  UINTN                      FilePathSize;
> +  CHAR16                     OptionStr[10];
> +  UINT16                     *NewOrder;
> +  UINTN                      Index;
> +
> +  NewOrder      = NULL;
> +  TempByteStart = NULL;
> +  NewDevicePath = NULL;
> +  NewOrder      = NULL;
> +  Node          = NULL;
> +  TmpDevicePath = NULL;
> +  CurrentOrder  = NULL;
> +
> +  if (StrLen (Description) == 0) {
> +    return EFI_INVALID_PARAMETER;
> +  }
> +
> +  //
> +  // Convert the scheme to all lower case.
> +  //
> +  for (Index = 0; Index < StrLen (Uri); Index++) {
> +    if (Uri[Index] == L':') {
> +      break;
> +    }
> +    if (Uri[Index] >= L'A' && Uri[Index] <= L'Z') {
> +      Uri[Index] -= (CHAR16)(L'A' - L'a');
> +    }
> +  }
> +
> +  //
> +  // Only accept http and https URI.
> +  //
> +  if ((StrnCmp (Uri, L"http://";, 7) != 0) && (StrnCmp (Uri, L"https://";, 7) 
> != 0)) {
> +    return EFI_INVALID_PARAMETER;
> +  }
> +
> +  //
> +  // Create a new device path by appending the IP node and URI node to
> +  // the driver's parent device path
> +  //
> +  if (!UsingIpv6) {
> +    Node = AllocateZeroPool (sizeof (IPv4_DEVICE_PATH));
> +    if (Node == NULL) {
> +      Status = EFI_OUT_OF_RESOURCES;
> +      goto ON_EXIT;
> +    }
> +    Node->Ipv4.Header.Type    = MESSAGING_DEVICE_PATH;
> +    Node->Ipv4.Header.SubType = MSG_IPv4_DP;
> +    SetDevicePathNodeLength (Node, sizeof (IPv4_DEVICE_PATH));
> +  } else {
> +    Node = AllocateZeroPool (sizeof (IPv6_DEVICE_PATH));
> +    if (Node == NULL) {
> +      Status = EFI_OUT_OF_RESOURCES;
> +      goto ON_EXIT;
> +    }
> +    Node->Ipv6.Header.Type     = MESSAGING_DEVICE_PATH;
> +    Node->Ipv6.Header.SubType  = MSG_IPv6_DP;
> +    SetDevicePathNodeLength (Node, sizeof (IPv6_DEVICE_PATH));
> +  }
> +  TmpDevicePath = AppendDevicePathNode (Private->ParentDevicePath,
> (EFI_DEVICE_PATH_PROTOCOL*) Node);
> +  FreePool (Node);
> +  if (TmpDevicePath == NULL) {
> +    return EFI_OUT_OF_RESOURCES;
> +  }
> +  //
> +  // Update the URI node with the input boot file URI.
> +  //
> +  UnicodeStrToAsciiStr (Uri, AsciiUri);
> +  Length = sizeof (EFI_DEVICE_PATH_PROTOCOL) + AsciiStrSize (AsciiUri);
> +  Node = AllocatePool (Length);
> +  if (Node == NULL) {
> +    Status = EFI_OUT_OF_RESOURCES;
> +    FreePool (TmpDevicePath);
> +    goto ON_EXIT;
> +  }
> +  Node->DevPath.Type    = MESSAGING_DEVICE_PATH;
> +  Node->DevPath.SubType = MSG_URI_DP;
> +  SetDevicePathNodeLength (Node, Length);
> +  CopyMem ((UINT8*) Node + sizeof (EFI_DEVICE_PATH_PROTOCOL), AsciiUri,
> AsciiStrSize (AsciiUri));
> +  NewDevicePath = AppendDevicePathNode (TmpDevicePath,
> (EFI_DEVICE_PATH_PROTOCOL*) Node);
> +  FreePool (Node);
> +  FreePool (TmpDevicePath);
> +  if (NewDevicePath == NULL) {
> +    Status = EFI_OUT_OF_RESOURCES;
> +    goto ON_EXIT;
> +  }
> +
> +  //
> +  // Get current "BootOrder" variable and find a free target.
> +  //
> +  Length = 0;
> +  Status = GetVariable2 (
> +             L"BootOrder",
> +             &gEfiGlobalVariableGuid,
> +             &CurrentOrder,
> +             &Length
> +             );
> +  if (EFI_ERROR (Status) && Status != EFI_NOT_FOUND) {
> +    goto ON_EXIT;
> +  }
> +  OrderCount = Length / sizeof (UINT16);
> +  Found = FALSE;
> +  for (TargetLocation=0; TargetLocation < 0xFFFF; TargetLocation++) {
> +    Found = TRUE;
> +    for (Index = 0; Index < OrderCount; Index++) {
> +      if (CurrentOrder[Index] == TargetLocation) {
> +        Found = FALSE;
> +        break;
> +      }
> +    }
> +    if (Found) {
> +      break;
> +    }
> +  }
> +
> +  if (TargetLocation == 0xFFFF) {
> +    DEBUG ((EFI_D_ERROR, "Could not find unused target index.\n"));
> +    Status = EFI_OUT_OF_RESOURCES;
> +    goto ON_EXIT;
> +  } else {
> +    DEBUG ((EFI_D_INFO, "TargetIndex = %04x.\n", TargetLocation));
> +  }
> +
> +  //
> +  // Construct and set the "Boot####" variable
> +  //
> +  DescSize = StrSize(Description);
> +  FilePathSize = GetDevicePathSize (NewDevicePath);
> +  TempByteBuffer = AllocateZeroPool(sizeof(EFI_LOAD_OPTION) + DescSize +
> FilePathSize);
> +  if (TempByteBuffer == NULL) {
> +    Status = EFI_OUT_OF_RESOURCES;
> +    goto ON_EXIT;
> +  }
> +
> +  TempByteStart = TempByteBuffer;
> +  *((UINT32 *) TempByteBuffer) = LOAD_OPTION_ACTIVE;      // Attributes
> +  TempByteBuffer += sizeof (UINT32);
> +
> +  *((UINT16 *) TempByteBuffer) = (UINT16)FilePathSize;    //
> FilePathListLength
> +  TempByteBuffer += sizeof (UINT16);
> +
> +  CopyMem (TempByteBuffer, Description, DescSize);
> +  TempByteBuffer += DescSize;
> +  CopyMem (TempByteBuffer, NewDevicePath, FilePathSize);
> +
> +  UnicodeSPrint (OptionStr, sizeof(OptionStr), L"%s%04x", L"Boot",
> TargetLocation);
> +  Status = gRT->SetVariable (
> +                  OptionStr,
> +                  &gEfiGlobalVariableGuid,
> +                  EFI_VARIABLE_NON_VOLATILE |
> EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_RUNTIME_ACCESS,
> +                  sizeof(UINT32) + sizeof(UINT16) + DescSize + FilePathSize,
> +                  TempByteStart
> +                  );
> +  if (EFI_ERROR (Status)) {
> +    goto ON_EXIT;
> +  }
> +
> +  //
> +  // Insert into the order list and set "BootOrder" variable
> +  //
> +  NewOrder = AllocateZeroPool ((OrderCount + 1) * sizeof (UINT16));
> +  if (NewOrder == NULL) {
> +    Status = EFI_OUT_OF_RESOURCES;
> +    goto ON_EXIT;
> +  }
> +  CopyMem(NewOrder, CurrentOrder, OrderCount * sizeof(UINT16));
> +  NewOrder[OrderCount] = (UINT16) TargetLocation;
> +  Status = gRT->SetVariable (
> +                  L"BootOrder",
> +                  &gEfiGlobalVariableGuid,
> +                  EFI_VARIABLE_NON_VOLATILE |
> EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_RUNTIME_ACCESS,
> +                  ((OrderCount + 1) * sizeof (UINT16)),
> +                  NewOrder
> +                  );
> +
> +
> +ON_EXIT:
> +
> +  if (CurrentOrder != NULL) {
> +    FreePool (CurrentOrder);
> +  }
> +  if (NewOrder != NULL) {
> +    FreePool (NewOrder);
> +  }
> +  if (TempByteStart != NULL) {
> +    FreePool (TempByteStart);
> +  }
> +  if (NewDevicePath != NULL) {
> +    FreePool (NewDevicePath);
> +  }
> +
> +  return Status;
> +}
> +
> +/**
> +
> +  This function allows the caller to request the current
> +  configuration for one or more named elements. The resulting
> +  string is in <ConfigAltResp> format. Also, any and all alternative
> +  configuration strings shall be appended to the end of the
> +  current configuration string. If they are, they must appear
> +  after the current configuration. They must contain the same
> +  routing (GUID, NAME, PATH) as the current configuration string.
> +  They must have an additional description indicating the type of
> +  alternative configuration the string represents,
> +  "ALTCFG=<StringToken>". That <StringToken> (when
> +  converted from Hex UNICODE to binary) is a reference to a
> +  string in the associated string pack.
> +
> +  @param[in]  This       Points to the EFI_HII_CONFIG_ACCESS_PROTOCOL.
> +
> +  @param[in]  Request    A null-terminated Unicode string in
> +                         <ConfigRequest> format. Note that this
> +                         includes the routing information as well as
> +                         the configurable name / value pairs. It is
> +                         invalid for this string to be in
> +                         <MultiConfigRequest> format.
> +
> +  @param[out] Progress   On return, points to a character in the
> +                         Request string. Points to the string's null
> +                         terminator if request was successful. Points
> +                         to the most recent "&" before the first
> +                         failing name / value pair (or the beginning
> +                         of the string if the failure is in the first
> +                         name / value pair) if the request was not 
> successful.
> +
> +  @param[out] Results    A null-terminated Unicode string in
> +                         <ConfigAltResp> format which has all values
> +                         filled in for the names in the Request string.
> +                         String to be allocated by the called function.
> +
> +  @retval EFI_SUCCESS             The Results string is filled with the
> +                                  values corresponding to all requested
> +                                  names.
> +
> +  @retval EFI_OUT_OF_RESOURCES    Not enough memory to store the
> +                                  parts of the results that must be
> +                                  stored awaiting possible future
> +                                  protocols.
> +
> +  @retval EFI_INVALID_PARAMETER   For example, passing in a NULL
> +                                  for the Request parameter
> +                                  would result in this type of
> +                                  error. In this case, the
> +                                  Progress parameter would be
> +                                  set to NULL.
> +
> +  @retval EFI_NOT_FOUND           Routing data doesn't match any
> +                                  known driver. Progress set to the
> +                                  first character in the routing header.
> +                                  Note: There is no requirement that the
> +                                  driver validate the routing data. It
> +                                  must skip the <ConfigHdr> in order to
> +                                  process the names.
> +
> +  @retval EFI_INVALID_PARAMETER   Illegal syntax. Progress set
> +                                  to most recent "&" before the
> +                                  error or the beginning of the
> +                                  string.
> +
> +  @retval EFI_INVALID_PARAMETER   Unknown name. Progress points
> +                                  to the & before the name in
> +                                  question.
> +
> +**/
> +EFI_STATUS
> +EFIAPI
> +HttpBootFormExtractConfig (
> +  IN  CONST EFI_HII_CONFIG_ACCESS_PROTOCOL   *This,
> +  IN  CONST EFI_STRING                       Request,
> +  OUT EFI_STRING                             *Progress,
> +  OUT EFI_STRING                             *Results
> +  )
> +{
> +  EFI_STATUS                       Status;
> +  UINTN                            BufferSize;
> +  HTTP_BOOT_FORM_CALLBACK_INFO     *CallbackInfo;
> +  EFI_STRING                       ConfigRequestHdr;
> +  EFI_STRING                       ConfigRequest;
> +  BOOLEAN                          AllocatedRequest;
> +  UINTN                            Size;
> +
> +  if (Progress == NULL || Results == NULL) {
> +    return EFI_INVALID_PARAMETER;
> +  }
> +
> +  *Progress = Request;
> +  if ((Request != NULL) && !HiiIsConfigHdrMatch (Request,
> &gHttpBootConfigGuid, mHttpBootConfigStorageName)) {
> +    return EFI_NOT_FOUND;
> +  }
> +
> +  ConfigRequestHdr = NULL;
> +  ConfigRequest    = NULL;
> +  AllocatedRequest = FALSE;
> +  Size             = 0;
> +
> +  CallbackInfo =
> HTTP_BOOT_FORM_CALLBACK_INFO_FROM_CONFIG_ACCESS (This);
> +  //
> +  // Convert buffer data to <ConfigResp> by helper function BlockToConfig()
> +  //
> +  BufferSize = sizeof (HTTP_BOOT_CONFIG_IFR_NVDATA);
> +  ZeroMem (&CallbackInfo->HttpBootNvData, BufferSize);
> +
> +  ConfigRequest = Request;
> +  if ((Request == NULL) || (StrStr (Request, L"OFFSET") == NULL)) {
> +    //
> +    // Request has no request element, construct full request string.
> +    // Allocate and fill a buffer large enough to hold the <ConfigHdr> 
> template
> +    // followed by "&OFFSET=0&WIDTH=WWWWWWWWWWWWWWWW"
> followed by a Null-terminator
> +    //
> +    ConfigRequestHdr = HiiConstructConfigHdr (&gHttpBootConfigGuid,
> mHttpBootConfigStorageName, CallbackInfo->ChildHandle);
> +    Size = (StrLen (ConfigRequestHdr) + 32 + 1) * sizeof (CHAR16);
> +    ConfigRequest = AllocateZeroPool (Size);
> +    ASSERT (ConfigRequest != NULL);
> +    AllocatedRequest = TRUE;
> +    UnicodeSPrint (ConfigRequest, Size, L"%s&OFFSET=0&WIDTH=%016LX",
> ConfigRequestHdr, (UINT64)BufferSize);
> +    FreePool (ConfigRequestHdr);
> +  }
> +
> +  Status = gHiiConfigRouting->BlockToConfig (
> +                                gHiiConfigRouting,
> +                                ConfigRequest,
> +                                (UINT8 *) &CallbackInfo->HttpBootNvData,
> +                                BufferSize,
> +                                Results,
> +                                Progress
> +                                );
> +  ASSERT_EFI_ERROR (Status);
> +
> +  //
> +  // Free the allocated config request string.
> +  //
> +  if (AllocatedRequest) {
> +    FreePool (ConfigRequest);
> +    ConfigRequest = NULL;
> +  }
> +  //
> +  // Set Progress string to the original request string.
> +  //
> +  if (Request == NULL) {
> +    *Progress = NULL;
> +  } else if (StrStr (Request, L"OFFSET") == NULL) {
> +    *Progress = Request + StrLen (Request);
> +  }
> +
> +  return Status;
> +}
> +
> +/**
> +
> +  This function applies changes in a driver's configuration.
> +  Input is a Configuration, which has the routing data for this
> +  driver followed by name / value configuration pairs. The driver
> +  must apply those pairs to its configurable storage. If the
> +  driver's configuration is stored in a linear block of data
> +  and the driver's name / value pairs are in <BlockConfig>
> +  format, it may use the ConfigToBlock helper function (above) to
> +  simplify the job.
> +
> +  @param[in]  This           Points to the EFI_HII_CONFIG_ACCESS_PROTOCOL.
> +
> +  @param[in]  Configuration  A null-terminated Unicode string in
> +                             <ConfigString> format.
> +
> +  @param[out] Progress       A pointer to a string filled in with the
> +                             offset of the most recent '&' before the
> +                             first failing name / value pair (or the
> +                             beginning of the string if the failure
> +                             is in the first name / value pair) or
> +                             the terminating NULL if all was
> +                             successful.
> +
> +  @retval EFI_SUCCESS             The results have been distributed or are
> +                                  awaiting distribution.
> +
> +  @retval EFI_OUT_OF_RESOURCES    Not enough memory to store the
> +                                  parts of the results that must be
> +                                  stored awaiting possible future
> +                                  protocols.
> +
> +  @retval EFI_INVALID_PARAMETERS  Passing in a NULL for the
> +                                  Results parameter would result
> +                                  in this type of error.
> +
> +  @retval EFI_NOT_FOUND           Target for the specified routing data
> +                                  was not found.
> +
> +**/
> +EFI_STATUS
> +EFIAPI
> +HttpBootFormRouteConfig (
> +  IN  CONST EFI_HII_CONFIG_ACCESS_PROTOCOL   *This,
> +  IN  CONST EFI_STRING                       Configuration,
> +  OUT EFI_STRING                             *Progress
> +  )
> +{
> +  EFI_STATUS                       Status;
> +  UINTN                            BufferSize;
> +  HTTP_BOOT_FORM_CALLBACK_INFO     *CallbackInfo;
> +  HTTP_BOOT_PRIVATE_DATA           *Private;
> +
> +  if (Progress == NULL) {
> +    return EFI_INVALID_PARAMETER;
> +  }
> +  *Progress = Configuration;
> +
> +  if (Configuration == NULL) {
> +    return EFI_INVALID_PARAMETER;
> +  }
> +
> +  //
> +  // Check routing data in <ConfigHdr>.
> +  // Note: there is no name for Name/Value storage, only GUID will be
> checked
> +  //
> +  if (!HiiIsConfigHdrMatch (Configuration, &gHttpBootConfigGuid,
> mHttpBootConfigStorageName)) {
> +    return EFI_NOT_FOUND;
> +  }
> +
> +  CallbackInfo =
> HTTP_BOOT_FORM_CALLBACK_INFO_FROM_CONFIG_ACCESS (This);
> +  Private      = HTTP_BOOT_PRIVATE_DATA_FROM_CALLBACK_INFO
> (CallbackInfo);
> +
> +  BufferSize = sizeof (HTTP_BOOT_CONFIG_IFR_NVDATA);
> +  ZeroMem (&CallbackInfo->HttpBootNvData, BufferSize);
> +
> +  Status = gHiiConfigRouting->ConfigToBlock (
> +                            gHiiConfigRouting,
> +                            Configuration,
> +                            (UINT8 *) &CallbackInfo->HttpBootNvData,
> +                            &BufferSize,
> +                            Progress
> +                            );
> +  if (EFI_ERROR (Status)) {
> +    return Status;
> +  }
> +
> +  //
> +  // Create a new boot option according to the configuration data.
> +  //
> +  Status = HttpBootAddBootOption (
> +             Private,
> +             (CallbackInfo->HttpBootNvData.IpVersion ==
> HTTP_BOOT_IP_VERSION_6) ? TRUE : FALSE,
> +             CallbackInfo->HttpBootNvData.Description,
> +             CallbackInfo->HttpBootNvData.Uri
> +             );
> +
> +  return Status;
> +}
> +
> +/**
> +
> +  This function is called to provide results data to the driver.
> +  This data consists of a unique key that is used to identify
> +  which data is either being passed back or being asked for.
> +
> +  @param[in]       This          Points to the 
> EFI_HII_CONFIG_ACCESS_PROTOCOL.
> +  @param[in]       Action        Specifies the type of action taken by the 
> browser.
> +  @param[in]       QuestionId    A unique value which is sent to the original
> +                                 exporting driver so that it can identify 
> the type
> +                                 of data to expect. The format of the data 
> tends to
> +                                 vary based on the opcode that generated the 
> callback.
> +  @param[in]       Type          The type of value for the question.
> +  @param[in, out]  Value         A pointer to the data being sent to the 
> original
> +                                 exporting driver.
> +  @param[out]      ActionRequest On return, points to the action requested
> by the
> +                                 callback function.
> +
> +  @retval EFI_SUCCESS            The callback successfully handled the 
> action.
> +  @retval EFI_OUT_OF_RESOURCES   Not enough storage is available to hold
> the
> +                                 variable and its data.
> +  @retval EFI_DEVICE_ERROR       The variable could not be saved.
> +  @retval EFI_UNSUPPORTED        The specified Action is not supported by
> the
> +                                 callback.
> +**/
> +EFI_STATUS
> +EFIAPI
> +HttpBootFormCallback (
> +  IN CONST  EFI_HII_CONFIG_ACCESS_PROTOCOL   *This,
> +  IN        EFI_BROWSER_ACTION               Action,
> +  IN        EFI_QUESTION_ID                  QuestionId,
> +  IN        UINT8                            Type,
> +  IN OUT    EFI_IFR_TYPE_VALUE               *Value,
> +  OUT       EFI_BROWSER_ACTION_REQUEST       *ActionRequest
> +  )
> +{
> +  return EFI_UNSUPPORTED;
> +}
> +
> +/**
> +  Initialize the configuration form.
> +
> +  @param[in]  Private             Pointer to the driver private data.
> +
> +  @retval EFI_SUCCESS             The configuration form is initialized.
> +  @retval EFI_OUT_OF_RESOURCES    Failed to allocate memory.
> +
> +**/
> +EFI_STATUS
> +HttpBootConfigFormInit (
> +  IN HTTP_BOOT_PRIVATE_DATA     *Private
> +  )
> +{
> +  EFI_STATUS                        Status;
> +  HTTP_BOOT_FORM_CALLBACK_INFO      *CallbackInfo;
> +  VENDOR_DEVICE_PATH                VendorDeviceNode;
> +  EFI_SERVICE_BINDING_PROTOCOL      *HttpSb;
> +  CHAR16                            *MacString;
> +  CHAR16                            *OldMenuString;
> +  CHAR16                            MenuString[128];
> +
> +  CallbackInfo = &Private->CallbackInfo;
> +
> +  if (CallbackInfo->Initilized) {
> +    return EFI_SUCCESS;
> +  }
> +
> +  CallbackInfo->Signature =
> HTTP_BOOT_FORM_CALLBACK_INFO_SIGNATURE;
> +
> +  //
> +  // Construct device path node for EFI HII Config Access protocol,
> +  // which consists of controller physical device path and one hardware
> +  // vendor guid node.
> +  //
> +  ZeroMem (&VendorDeviceNode, sizeof (VENDOR_DEVICE_PATH));
> +  VendorDeviceNode.Header.Type    = HARDWARE_DEVICE_PATH;
> +  VendorDeviceNode.Header.SubType = HW_VENDOR_DP;
> +  CopyGuid (&VendorDeviceNode.Guid, &gEfiCallerIdGuid);
> +  SetDevicePathNodeLength (&VendorDeviceNode.Header, sizeof
> (VENDOR_DEVICE_PATH));
> +  CallbackInfo->HiiVendorDevicePath = AppendDevicePathNode (
> +                                        Private->ParentDevicePath,
> +                                        (EFI_DEVICE_PATH_PROTOCOL *) 
> &VendorDeviceNode
> +                                        );
> +  if (CallbackInfo->HiiVendorDevicePath == NULL) {
> +    Status = EFI_OUT_OF_RESOURCES;
> +    goto Error;
> +  }
> +
> +  CallbackInfo->ConfigAccess.ExtractConfig = HttpBootFormExtractConfig;
> +  CallbackInfo->ConfigAccess.RouteConfig   = HttpBootFormRouteConfig;
> +  CallbackInfo->ConfigAccess.Callback      = HttpBootFormCallback;
> +
> +  //
> +  // Install Device Path Protocol and Config Access protocol to driver 
> handle.
> +  //
> +  Status = gBS->InstallMultipleProtocolInterfaces (
> +                  &CallbackInfo->ChildHandle,
> +                  &gEfiDevicePathProtocolGuid,
> +                  CallbackInfo->HiiVendorDevicePath,
> +                  &gEfiHiiConfigAccessProtocolGuid,
> +                  &CallbackInfo->ConfigAccess,
> +                  NULL
> +                  );
> +  if (!EFI_ERROR (Status)) {
> +    //
> +    // Open the Parent Handle for the child
> +    //
> +    Status = gBS->OpenProtocol (
> +                    Private->Controller,
> +                    &gEfiHttpServiceBindingProtocolGuid,
> +                    (VOID **) &HttpSb,
> +                    Private->Image,
> +                    CallbackInfo->ChildHandle,
> +                    EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER
> +                    );
> +  }
> +
> +  if (EFI_ERROR (Status)) {
> +    goto Error;
> +  }
> +
> +  //
> +  // Publish our HII data.
> +  //
> +  CallbackInfo->RegisteredHandle = HiiAddPackages (
> +                                     &gHttpBootConfigGuid,
> +                                     CallbackInfo->ChildHandle,
> +                                     HttpBootDxeStrings,
> +                                     HttpBootConfigVfrBin,
> +                                     NULL
> +                                     );
> +  if (CallbackInfo->RegisteredHandle == NULL) {
> +    Status = EFI_OUT_OF_RESOURCES;
> +    goto Error;
> +  }
> +
> +  //
> +  // Append MAC string in the menu help string
> +  //
> +  Status = NetLibGetMacString (Private->Controller, Private->Image,
> &MacString);
> +  if (!EFI_ERROR (Status)) {
> +    OldMenuString = HiiGetString (
> +                      CallbackInfo->RegisteredHandle,
> +                      STRING_TOKEN (STR_HTTP_BOOT_CONFIG_FORM_HELP),
> +                      NULL
> +                      );
> +    UnicodeSPrint (MenuString, 128, L"%s (MAC:%s)", OldMenuString,
> MacString);
> +    HiiSetString (
> +      CallbackInfo->RegisteredHandle,
> +      STRING_TOKEN (STR_HTTP_BOOT_CONFIG_FORM_HELP),
> +      MenuString,
> +      NULL
> +      );
> +
> +    FreePool (MacString);
> +    FreePool (OldMenuString);
> +
> +    return EFI_SUCCESS;
> +  }
> +
> +Error:
> +
> +  HttpBootConfigFormUnload (Private);
> +  return Status;
> +}
> +
> +/**
> +  Unload the configuration form, this includes: delete all the configuration
> +  entries, uninstall the form callback protocol, and free the resources used.
> +
> +  @param[in]  Private             Pointer to the driver private data.
> +
> +  @retval EFI_SUCCESS             The configuration form is unloaded.
> +  @retval Others                  Failed to unload the form.
> +
> +**/
> +EFI_STATUS
> +HttpBootConfigFormUnload (
> +  IN HTTP_BOOT_PRIVATE_DATA     *Private
> +  )
> +{
> +  HTTP_BOOT_FORM_CALLBACK_INFO      *CallbackInfo;
> +
> +  CallbackInfo = &Private->CallbackInfo;
> +  if (CallbackInfo->ChildHandle != NULL) {
> +    //
> +    // Close the child handle
> +    //
> +    gBS->CloseProtocol (
> +           Private->Controller,
> +           &gEfiHttpServiceBindingProtocolGuid,
> +           Private->Image,
> +           CallbackInfo->ChildHandle
> +           );
> +
> +    //
> +    // Uninstall EFI_HII_CONFIG_ACCESS_PROTOCOL
> +    //
> +    gBS->UninstallMultipleProtocolInterfaces (
> +           CallbackInfo->ChildHandle,
> +           &gEfiDevicePathProtocolGuid,
> +           CallbackInfo->HiiVendorDevicePath,
> +           &gEfiHiiConfigAccessProtocolGuid,
> +           &CallbackInfo->ConfigAccess,
> +           NULL
> +           );
> +    CallbackInfo->ChildHandle = NULL;
> +  }
> +
> +  if (CallbackInfo->HiiVendorDevicePath != NULL) {
> +    FreePool (CallbackInfo->HiiVendorDevicePath);
> +    CallbackInfo->HiiVendorDevicePath = NULL;
> +  }
> +
> +  if (CallbackInfo->RegisteredHandle != NULL) {
> +    //
> +    // Remove HII package list
> +    //
> +    HiiRemovePackages (CallbackInfo->RegisteredHandle);
> +    CallbackInfo->RegisteredHandle = NULL;
> +  }
> +
> +  return EFI_SUCCESS;
> +}
> diff --git a/NetworkPkg/HttpBootDxe/HttpBootConfig.h
> b/NetworkPkg/HttpBootDxe/HttpBootConfig.h
> new file mode 100644
> index 0000000..a2afd18
> --- /dev/null
> +++ b/NetworkPkg/HttpBootDxe/HttpBootConfig.h
> @@ -0,0 +1,78 @@
> +/** @file
> +  The header file of functions for configuring or getting the parameters
> +  relating to HTTP Boot.
> +
> +Copyright (c) 2016, Intel Corporation. All rights reserved.<BR>
> +This program and the accompanying materials
> +are licensed and made available under the terms and conditions of the BSD
> License
> +which accompanies this distribution.  The full text of the license may be
> found at
> +http://opensource.org/licenses/bsd-license.php
> +
> +THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS"
> BASIS,
> +WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER
> EXPRESS OR IMPLIED.
> +
> +**/
> +
> +#ifndef _HTTP_BOOT_CONFIG_H_
> +#define _HTTP_BOOT_CONFIG_H_
> +
> +
> +#include "HttpBootConfigNVDataStruc.h"
> +
> +typedef struct _HTTP_BOOT_FORM_CALLBACK_INFO
> HTTP_BOOT_FORM_CALLBACK_INFO;
> +
> +extern   UINT8                            HttpBootDxeStrings[];
> +extern   UINT8                            HttpBootConfigVfrBin[];
> +
> +#pragma pack()
> +
> +#define HTTP_BOOT_FORM_CALLBACK_INFO_SIGNATURE  SIGNATURE_32
> ('H', 'B', 'f', 'c')
> +
> +#define
> HTTP_BOOT_FORM_CALLBACK_INFO_FROM_CONFIG_ACCESS(Callback) \
> +  CR ( \
> +  Callback, \
> +  HTTP_BOOT_FORM_CALLBACK_INFO, \
> +  ConfigAccess, \
> +  HTTP_BOOT_FORM_CALLBACK_INFO_SIGNATURE \
> +  )
> +
> +struct _HTTP_BOOT_FORM_CALLBACK_INFO {
> +  UINT32                           Signature;
> +  BOOLEAN                          Initilized;
> +  EFI_HANDLE                       ChildHandle;
> +  EFI_DEVICE_PATH_PROTOCOL         *HiiVendorDevicePath;
> +  EFI_HII_HANDLE                   RegisteredHandle;
> +  EFI_HII_CONFIG_ACCESS_PROTOCOL   ConfigAccess;
> +  HTTP_BOOT_CONFIG_IFR_NVDATA      HttpBootNvData;
> +};
> +
> +/**
> +  Initialize the configuration form.
> +
> +  @param[in]  Private             Pointer to the driver private data.
> +
> +  @retval EFI_SUCCESS             The configuration form is initialized.
> +  @retval EFI_OUT_OF_RESOURCES    Failed to allocate memory.
> +
> +**/
> +EFI_STATUS
> +HttpBootConfigFormInit (
> +  IN HTTP_BOOT_PRIVATE_DATA     *Private
> +  );
> +
> +/**
> +  Unload the configuration form, this includes: delete all the configuration
> +  entries, uninstall the form callback protocol, and free the resources used.
> +
> +  @param[in]  Private             Pointer to the driver private data.
> +
> +  @retval EFI_SUCCESS             The configuration form is unloaded.
> +  @retval Others                  Failed to unload the form.
> +
> +**/
> +EFI_STATUS
> +HttpBootConfigFormUnload (
> +  IN HTTP_BOOT_PRIVATE_DATA     *Private
> +  );
> +
> +#endif
> diff --git a/NetworkPkg/HttpBootDxe/HttpBootConfigNVDataStruc.h
> b/NetworkPkg/HttpBootDxe/HttpBootConfigNVDataStruc.h
> new file mode 100644
> index 0000000..07043e7
> --- /dev/null
> +++ b/NetworkPkg/HttpBootDxe/HttpBootConfigNVDataStruc.h
> @@ -0,0 +1,43 @@
> +/** @file
> +  Define NVData structures used by the HTTP Boot configuration component.
> +
> +Copyright (c) 2016, Intel Corporation. All rights reserved.<BR>
> +This program and the accompanying materials
> +are licensed and made available under the terms and conditions of the BSD
> License
> +which accompanies this distribution.  The full text of the license may be
> found at
> +http://opensource.org/licenses/bsd-license.php
> +
> +THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS"
> BASIS,
> +WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER
> EXPRESS OR IMPLIED.
> +
> +**/
> +
> +#ifndef _HTTP_BOOT_NVDATA_STRUC_H_
> +#define _HTTP_BOOT_NVDATA_STRUC_H_
> +
> +#include <Guid/HttpBootConfigHii.h>
> +
> +#define HTTP_BOOT_IP_VERSION_4         0
> +#define HTTP_BOOT_IP_VERSION_6         1
> +
> +//
> +// Macros used for an IPv4 or an IPv6 address.
> +//
> +#define URI_STR_MIN_SIZE           8
> +#define URI_STR_MAX_SIZE           255
> +
> +#define CONFIGURATION_VARSTORE_ID    0x1234
> +
> +#define FORMID_MAIN_FORM    1
> +
> +#pragma pack(1)
> +typedef struct _HTTP_BOOT_CONFIG_IFR_NVDATA {
> +  UINT8     IpVersion;
> +  UINT8     Padding;
> +  CHAR16    Description[URI_STR_MAX_SIZE];
> +  CHAR16    Uri[URI_STR_MAX_SIZE];
> +} HTTP_BOOT_CONFIG_IFR_NVDATA;
> +#pragma pack()
> +
> +
> +#endif
> diff --git a/NetworkPkg/HttpBootDxe/HttpBootConfigStrings.uni
> b/NetworkPkg/HttpBootDxe/HttpBootConfigStrings.uni
> new file mode 100644
> index
> 0000000000000000000000000000000000000000..5001220eb3cc71f1bf7e53e
> 53b142bea34254043
> GIT binary patch
> literal 2926
> zcmb`JT~8B16o${WiT`0!Zq#6_hHznw5v1To>^AKpdexM+lqQ9eZ2|f7>hsRHo!
> #=W
> zsARJ{U+3dJ@0>ZazkW9C1y5uj?ARtYwUIrwCyXQO+QKsC&TPzR$ciM+co)1gd
> UNKF
> z>1DK^Eahp_+h%5lOk@KmC9SbtAk|-L)}5E!(?{ga?b>-
> 8+lkYChW2x8ys=mI+BR*S
> zevHorIHvTalcA+=(Qag0tV=@Jy*1&?(3|sScFA{Wb$bWWj=e7-
> N%1~$ah)SMLtoZU
> z(eLAXNV`B{<i-OR-
> zgZhc8#8A>eS(prwP3&*77*}%t?33%7C626qaCJx?);0m%Q4M
> zz8&$^+=as+%K?Y@$UvwVbBvz%A=<^Anz2_wZ=3zyVZ2|$k|VuxJPi2CYB|yg9
> _39;
> zc&_AW&R7v2fim}6M=ByKJY&bK_?;2vA4o+oT*Or7B_gUmyhhkm^vX2PfG{nV
> tSVm?
> z?7~}X@F<f!vy#pn&vj-
> q_Oh|U{G6F1kPq$U%1Rw8C%ol6P08{mNZRC0VtahI><i-<
> zE+g1fn=%`dSqJo*j^P7q(KeYE7v4f(KPHo#NOYa$gq|{3-
> x{s#%4&^v+l@6^U&emO
> zs%$3CUu1{KbR4c0^D#DMA#uJtjD%cs@|Yqk8Ts^5yU5D-
> ciPXa2)E8%^N$xFL({%3
> z?F8#FOti@+`P?b+rs~pIp0PD}R+f%kmTT{|S1&;?OEq-0raYL#f32XG=a)ZYp6A}O
> z>hxeI;YqCrpNeP~Bzuf@8Fj$cbFro%)D9M(fawBkW0z}XRJYYO)t@tR@@8%Gs
> MnS!
> z;@=S~SN37Gh*te-#H;9Zer}6GwaZty5obu1WX|6GeFQNmd-
> fH)9d^>^RL^Be;_@P0
> ziJ>}zyw+#1ENnV;s>lmo)wk)Rp}dRbhw$75n`-mGA<XXv-7sR(-;#NitB&aLnBQ38
> zJ7my9m~Y$0qp`dBpGY<<kc4x8K<>q4p|8%WMypvDSSa_ZISKzX-
> pl<b<R+%ObF7Rc
> zjH)qh!K}{46>Y$maBJoFZ^WAZAoMrn@6Z8xIdZpW{@<ayUFS-
> 7xUW<?Va3}$*!Hnk
> zWod|Bw_cZetbNgLRM&+({_5y;n$F$7M);@EpVQpMGbyle|6aAYd-
> i#HAoX{5i+dx-
> L@vycUt;g^iZoj(&
> 
> literal 0
> HcmV?d00001
> 
> diff --git a/NetworkPkg/HttpBootDxe/HttpBootConfigVfr.vfr
> b/NetworkPkg/HttpBootDxe/HttpBootConfigVfr.vfr
> new file mode 100644
> index 0000000..e47c6af
> --- /dev/null
> +++ b/NetworkPkg/HttpBootDxe/HttpBootConfigVfr.vfr
> @@ -0,0 +1,53 @@
> +/** @file
> +  VFR file used by the HTTP Boot configuration component.
> +
> +  Copyright (c) 2016, Intel Corporation. All rights reserved.<BR>
> +
> +  This program and the accompanying materials
> +  are licensed and made available under the terms and conditions of the BSD
> License
> +  which accompanies this distribution.  The full text of the license may be
> found at
> +  http://opensource.org/licenses/bsd-license.php.
> +
> +  THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS"
> BASIS,
> +  WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER
> EXPRESS OR IMPLIED.
> +
> +**/
> +
> +#include "HttpBootConfigNVDataStruc.h"
> +
> +
> +formset
> +  guid   = HTTP_BOOT_CONFIG_GUID,
> +  title  = STRING_TOKEN(STR_HTTP_BOOT_CONFIG_FORM_TITLE),
> +  help   = STRING_TOKEN(STR_HTTP_BOOT_CONFIG_FORM_HELP),
> +
> +  varstore HTTP_BOOT_CONFIG_IFR_NVDATA,
> +    name = HTTP_BOOT_CONFIG_IFR_NVDATA,
> +    guid = HTTP_BOOT_CONFIG_GUID;
> +
> +  form formid = FORMID_MAIN_FORM,
> +    title  = STRING_TOKEN(STR_HTTP_BOOT_CONFIG_FORM_TITLE);
> +
> +    string  varid   = HTTP_BOOT_CONFIG_IFR_NVDATA.Description,
> +            prompt  = STRING_TOKEN(STR_BOOT_DESCRIPTION_PROMPT),
> +            help    = STRING_TOKEN(STR_NULL_STRING),
> +            minsize = 6,
> +            maxsize = 75,
> +    endstring;
> +
> +    oneof varid  = HTTP_BOOT_CONFIG_IFR_NVDATA.IpVersion,
> +          prompt = STRING_TOKEN(STR_HTTP_BOOT_IP_VERSION_PROMPT),
> +          help   = STRING_TOKEN(STR_HTTP_BOOT_IP_VERSION_HELP),
> +          option text = STRING_TOKEN(STR_HTTP_BOOT_IP_VERSION_4),   value
> = HTTP_BOOT_IP_VERSION_4,   flags = DEFAULT;
> +          option text = STRING_TOKEN(STR_HTTP_BOOT_IP_VERSION_6),   value
> = HTTP_BOOT_IP_VERSION_6,   flags = 0;
> +    endoneof;
> +
> +    string  varid   = HTTP_BOOT_CONFIG_IFR_NVDATA.Uri,
> +            prompt  = STRING_TOKEN(STR_BOOT_URI_PROMPT),
> +            help    = STRING_TOKEN(STR_BOOT_URI_HELP),
> +            minsize = URI_STR_MIN_SIZE,
> +            maxsize = URI_STR_MAX_SIZE,
> +    endstring;
> +  endform;
> +
> +endformset;
> diff --git a/NetworkPkg/HttpBootDxe/HttpBootDhcp4.c
> b/NetworkPkg/HttpBootDxe/HttpBootDhcp4.c
> index 9a947a6..b9c8084 100644
> --- a/NetworkPkg/HttpBootDxe/HttpBootDhcp4.c
> +++ b/NetworkPkg/HttpBootDxe/HttpBootDhcp4.c
> @@ -1,7 +1,7 @@
>  /** @file
>    Functions implementation related with DHCPv4 for HTTP boot driver.
> 
> -Copyright (c) 2015, Intel Corporation. All rights reserved.<BR>
> +Copyright (c) 2015 - 2016, 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
> @@ -395,7 +395,11 @@ HttpBootParseDhcp4Packet (
>    //
>    if (IsHttpOffer) {
>      if (IpExpressedUri) {
> -      OfferType = IsProxyOffer ? HttpOfferTypeProxyIpUri :
> HttpOfferTypeDhcpIpUri;
> +      if (IsProxyOffer) {
> +        OfferType = HttpOfferTypeProxyIpUri;
> +      } else {
> +        OfferType = IsDnsOffer ? HttpOfferTypeDhcpIpUriDns :
> HttpOfferTypeDhcpIpUri;
> +      }
>      } else {
>        if (!IsProxyOffer) {
>          OfferType = IsDnsOffer ? HttpOfferTypeDhcpNameUriDns :
> HttpOfferTypeDhcpNameUri;
> @@ -473,46 +477,81 @@ HttpBootSelectDhcpOffer (
>  {
>    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) {
> +
> +  if (Private->FilePathUri != NULL) {
> +    //
> +    // We are in home environment, the URI is already specified.
> +    // Just need to choose a DHCP offer.
> +    // The offer with DNS server address takes priority here.
> +    //
> +    if (Private->OfferCount[HttpOfferTypeDhcpDns] > 0) {
> +
> +      Private->SelectIndex = Private->OfferIndex[HttpOfferTypeDhcpDns][0] + 
> 1;
> +
> +    } else if (Private->OfferCount[HttpOfferTypeDhcpIpUriDns] > 0) {
> 
> -    Private->SelectIndex = Private->OfferIndex[HttpOfferTypeDhcpIpUri][0] + 
> 1;
> +      Private->SelectIndex = Private-
> >OfferIndex[HttpOfferTypeDhcpIpUriDns][0] + 1;
> +
> +    } else if (Private->OfferCount[HttpOfferTypeDhcpNameUriDns] > 0) {
> 
> -  } else if (Private->OfferCount[HttpOfferTypeDhcpNameUriDns] > 0) {
> -
> -    Private->SelectIndex = Private-
> >OfferIndex[HttpOfferTypeDhcpNameUriDns][0] + 1;
> +      Private->SelectIndex = Private-
> >OfferIndex[HttpOfferTypeDhcpNameUriDns][0] + 1;
> +
> +    }  else if (Private->OfferCount[HttpOfferTypeDhcpOnly] > 0) {
> 
> -  } else if (Private->OfferCount[HttpOfferTypeDhcpOnly] > 0 &&
> -             Private->OfferCount[HttpOfferTypeProxyIpUri] > 0) {
> -
> -    Private->SelectIndex     = Private->OfferIndex[HttpOfferTypeDhcpOnly][0] 
> +
> 1;
> -    Private->SelectProxyType = HttpOfferTypeProxyIpUri;
> +      Private->SelectIndex = Private->OfferIndex[HttpOfferTypeDhcpOnly][0] +
> 1;
> +
> +    }  else if (Private->OfferCount[HttpOfferTypeDhcpIpUri] > 0) {
> 
> -  } else if (Private->OfferCount[HttpOfferTypeDhcpDns] > 0 &&
> -             Private->OfferCount[HttpOfferTypeProxyIpUri] > 0) {
> -
> -    Private->SelectIndex     = Private->OfferIndex[HttpOfferTypeDhcpDns][0] +
> 1;
> -    Private->SelectProxyType = HttpOfferTypeProxyIpUri;
> +      Private->SelectIndex = Private->OfferIndex[HttpOfferTypeDhcpIpUri][0] +
> 1;
> +    }
> 
> -  } else if (Private->OfferCount[HttpOfferTypeDhcpDns] > 0 &&
> -             Private->OfferCount[HttpOfferTypeProxyNameUri] > 0) {
> -
> -    Private->SelectIndex     = Private->OfferIndex[HttpOfferTypeDhcpDns][0] +
> 1;
> -    Private->SelectProxyType = HttpOfferTypeProxyNameUri;
> +  } else {
> +    //
> +    // We are in corporate environment.
> +    //
> +    // Priority1: HttpOfferTypeDhcpIpUri or HttpOfferTypeDhcpIpUriDns
> +    // 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[HttpOfferTypeDhcpIpUriDns] > 0) {
> +
> +      Private->SelectIndex = Private-
> >OfferIndex[HttpOfferTypeDhcpIpUriDns][0] + 1;
> +
> +    }else if (Private->OfferCount[HttpOfferTypeDhcpNameUriDns] > 0) {
> 
> -  } else if (Private->OfferCount[HttpOfferTypeDhcpDns] > 0 &&
> -             Private->OfferCount[HttpOfferTypeDhcpNameUri] > 0) {
> -
> -    Private->SelectIndex     = Private->OfferIndex[HttpOfferTypeDhcpDns][0] +
> 1;
> -    Private->SelectProxyType = HttpOfferTypeDhcpNameUri;
> +      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;
> +    }
>    }
>  }
> 
> diff --git a/NetworkPkg/HttpBootDxe/HttpBootDhcp4.h
> b/NetworkPkg/HttpBootDxe/HttpBootDhcp4.h
> index 2bc46de..5ac7f71 100644
> --- a/NetworkPkg/HttpBootDxe/HttpBootDhcp4.h
> +++ b/NetworkPkg/HttpBootDxe/HttpBootDhcp4.h
> @@ -1,7 +1,7 @@
>  /** @file
>    Functions declaration related with DHCPv4 for HTTP boot driver.
> 
> -Copyright (c) 2015, Intel Corporation. All rights reserved.<BR>
> +Copyright (c) 2015 - 2016, 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
> @@ -96,11 +96,14 @@ WITHOUT WARRANTIES OR REPRESENTATIONS OF
> ANY KIND, EITHER EXPRESS OR IMPLIED.
>  ///
>  typedef enum {
>    //
> -  // <IP address, IP expressed URI> or
> -  // <IP address, IP expressed URI, Name-server (will be ignored)>
> +  // <IP address, IP expressed URI>
>    //
>    HttpOfferTypeDhcpIpUri,
>    //
> +  // <IP address, IP expressed URI, Name-server>
> +  //
> +  HttpOfferTypeDhcpIpUriDns,
> +  //
>    // <IP address, Domain-name expressed URI, Name-server>
>    //
>    HttpOfferTypeDhcpNameUriDns,
> diff --git a/NetworkPkg/HttpBootDxe/HttpBootDhcp6.c
> b/NetworkPkg/HttpBootDxe/HttpBootDhcp6.c
> index 2538bd1..d2960e4 100644
> --- a/NetworkPkg/HttpBootDxe/HttpBootDhcp6.c
> +++ b/NetworkPkg/HttpBootDxe/HttpBootDhcp6.c
> @@ -298,7 +298,11 @@ HttpBootParseDhcp6Packet (
>    //
>    if (IsHttpOffer) {
>      if (IpExpressedUri) {
> -      OfferType = IsProxyOffer ? HttpOfferTypeProxyIpUri :
> HttpOfferTypeDhcpIpUri;
> +      if (IsProxyOffer) {
> +        OfferType = HttpOfferTypeProxyIpUri;
> +      } else {
> +        OfferType = IsDnsOffer ? HttpOfferTypeDhcpIpUriDns :
> HttpOfferTypeDhcpIpUri;
> +      }
>      } else {
>        if (!IsProxyOffer) {
>          OfferType = IsDnsOffer ? HttpOfferTypeDhcpNameUriDns :
> HttpOfferTypeDhcpNameUri;
> diff --git a/NetworkPkg/HttpBootDxe/HttpBootDxe.c
> b/NetworkPkg/HttpBootDxe/HttpBootDxe.c
> index 9fb33bb..6a3033d 100644
> --- a/NetworkPkg/HttpBootDxe/HttpBootDxe.c
> +++ b/NetworkPkg/HttpBootDxe/HttpBootDxe.c
> @@ -1,7 +1,7 @@
>  /** @file
>    Driver Binding functions implementation for UEFI HTTP boot.
> 
> -Copyright (c) 2015, Intel Corporation. All rights reserved.<BR>
> +Copyright (c) 2015 - 2016, 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
> @@ -365,6 +365,14 @@ HttpBootIp4DxeDriverBindingStart (
>      }
> 
>      //
> +    // Initialize the HII configuration form.
> +    //
> +    Status = HttpBootConfigFormInit (Private);
> +    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.
>      //
> @@ -508,8 +516,9 @@ HttpBootIp4DxeDriverBindingStart (
> 
> 
>  ON_ERROR:
> -
> +
>    HttpBootDestroyIp4Children (This, Private);
> +  HttpBootConfigFormUnload (Private);
>    FreePool (Private);
> 
>    return Status;
> @@ -615,6 +624,11 @@ HttpBootIp4DxeDriverBindingStop (
>      // Release the cached data.
>      //
>      HttpBootFreeCacheList (Private);
> +
> +    //
> +    // Unload the config form.
> +    //
> +    HttpBootConfigFormUnload (Private);
> 
>      gBS->UninstallProtocolInterface (
>             NicHandle,
> @@ -823,6 +837,14 @@ HttpBootIp6DxeDriverBindingStart (
>      }
> 
>      //
> +    // Initialize the HII configuration form.
> +    //
> +    Status = HttpBootConfigFormInit (Private);
> +    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.
>      //
> @@ -989,12 +1011,12 @@ HttpBootIp6DxeDriverBindingStart (
>    return EFI_SUCCESS;
> 
>  ON_ERROR:
> -
> - HttpBootDestroyIp6Children(This, Private);
> - FreePool (Private);
> 
> - return Status;
> -
> +  HttpBootDestroyIp6Children(This, Private);
> +  HttpBootConfigFormUnload (Private);
> +  FreePool (Private);
> +
> +  return Status;
>  }
> 
>  /**
> @@ -1096,7 +1118,12 @@ HttpBootIp6DxeDriverBindingStop (
>      // Release the cached data.
>      //
>      HttpBootFreeCacheList (Private);
> -
> +
> +    //
> +    // Unload the config form.
> +    //
> +    HttpBootConfigFormUnload (Private);
> +
>      gBS->UninstallProtocolInterface (
>             NicHandle,
>             &gEfiCallerIdGuid,
> @@ -1128,6 +1155,7 @@ HttpBootDxeDriverEntryPoint (
>    )
>  {
>    EFI_STATUS   Status;
> +
>    //
>    // Install UEFI Driver Model protocol(s).
>    //
> diff --git a/NetworkPkg/HttpBootDxe/HttpBootDxe.h
> b/NetworkPkg/HttpBootDxe/HttpBootDxe.h
> index 08f88c5..7cb4b2c 100644
> --- a/NetworkPkg/HttpBootDxe/HttpBootDxe.h
> +++ b/NetworkPkg/HttpBootDxe/HttpBootDxe.h
> @@ -1,7 +1,7 @@
>  /** @file
>    UEFI HTTP boot driver's private data structure and interfaces declaration.
> 
> -Copyright (c) 2015, Intel Corporation. All rights reserved.<BR>
> +Copyright (c) 2015 - 2016, Intel Corporation. All rights reserved.<BR>
>  (C) Copyright 2016 Hewlett Packard Enterprise Development LP<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.
> @@ -24,6 +24,8 @@ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY
> KIND, EITHER EXPRESS OR IMPLIED.
>  // Libraries
>  //
>  #include <Library/UefiBootServicesTableLib.h>
> +#include <Library/UefiHiiServicesLib.h>
> +#include <Library/UefiRuntimeServicesTableLib.h>
>  #include <Library/MemoryAllocationLib.h>
>  #include <Library/BaseLib.h>
>  #include <Library/UefiLib.h>
> @@ -31,6 +33,8 @@ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY
> KIND, EITHER EXPRESS OR IMPLIED.
>  #include <Library/DebugLib.h>
>  #include <Library/NetLib.h>
>  #include <Library/HttpLib.h>
> +#include <Library/HiiLib.h>
> +#include <Library/PrintLib.h>
> 
>  //
>  // UEFI Driver Model Protocols
> @@ -42,6 +46,8 @@ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY
> KIND, EITHER EXPRESS OR IMPLIED.
>  //
>  // Consumed Protocols
>  //
> +#include <Protocol/ServiceBinding.h>
> +#include <Protocol/HiiConfigAccess.h>
>  #include <Protocol/NetworkInterfaceIdentifier.h>
>  #include <Protocol/Dhcp4.h>
>  #include <Protocol/Dhcp6.h>
> @@ -55,6 +61,11 @@ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY
> KIND, EITHER EXPRESS OR IMPLIED.
>  #include <Protocol/LoadFile.h>
> 
>  //
> +// Consumed Guids
> +//
> +#include <Guid/HttpBootConfigHii.h>
> +
> +//
>  // Driver Version
>  //
>  #define HTTP_BOOT_DXE_VERSION  0xa
> @@ -81,6 +92,7 @@ typedef struct _HTTP_BOOT_VIRTUAL_NIC
> HTTP_BOOT_VIRTUAL_NIC;
>  #include "HttpBootImpl.h"
>  #include "HttpBootSupport.h"
>  #include "HttpBootClient.h"
> +#include "HttpBootConfig.h"
> 
>  typedef union {
>    HTTP_BOOT_DHCP4_PACKET_CACHE              Dhcp4;
> @@ -95,6 +107,14 @@ struct _HTTP_BOOT_VIRTUAL_NIC {
>    HTTP_BOOT_PRIVATE_DATA                    *Private;
>  };
> 
> +#define HTTP_BOOT_PRIVATE_DATA_FROM_CALLBACK_INFO(Callback) \
> +  CR ( \
> +  Callback, \
> +  HTTP_BOOT_PRIVATE_DATA, \
> +  CallbackInfo, \
> +  HTTP_BOOT_PRIVATE_DATA_SIGNATURE \
> +  )
> +
>  struct _HTTP_BOOT_PRIVATE_DATA {
>    UINT32                                    Signature;
>    EFI_HANDLE                                Controller;
> @@ -132,6 +152,11 @@ struct _HTTP_BOOT_PRIVATE_DATA {
>    UINT32                                    Id;
> 
>    //
> +  // HII callback info block
> +  //
> +  HTTP_BOOT_FORM_CALLBACK_INFO              CallbackInfo;
> +
> +  //
>    // Mode data
>    //
>    BOOLEAN                                   UsingIpv6;
> @@ -147,6 +172,12 @@ struct _HTTP_BOOT_PRIVATE_DATA {
>    BOOLEAN                                   NoGateway;
> 
>    //
> +  // URI string extracted from the input FilePath parameter.
> +  //
> +  CHAR8                                     *FilePathUri;
> +  VOID                                      *FilePathUriParser;
> +
> +  //
>    // Cached HTTP data
>    //
>    LIST_ENTRY                                CacheList;
> diff --git a/NetworkPkg/HttpBootDxe/HttpBootDxe.inf
> b/NetworkPkg/HttpBootDxe/HttpBootDxe.inf
> index e24b568..8b4219c 100644
> --- a/NetworkPkg/HttpBootDxe/HttpBootDxe.inf
> +++ b/NetworkPkg/HttpBootDxe/HttpBootDxe.inf
> @@ -1,7 +1,7 @@
>  ## @file
>  #  This modules produce the Load File Protocol for UEFI HTTP boot.
>  #
> -#  Copyright (c) 2015, Intel Corporation. All rights reserved.<BR>
> +#  Copyright (c) 2015 - 2016, Intel Corporation. All rights reserved.<BR>
>  #  This program and the accompanying materials
>  #  are licensed and made available under the terms and conditions of the
> BSD License
>  #  which accompanies this distribution.  The full text of the license may be
> found at
> @@ -25,10 +25,12 @@
>  [Packages]
>    MdePkg/MdePkg.dec
>    MdeModulePkg/MdeModulePkg.dec
> +  NetworkPkg/NetworkPkg.dec
> 
>  [Sources]
>    HttpBootDxe.h
>    HttpBootDxe.c
> +  HttpBootConfig.c
>    HttpBootComponentName.h
>    HttpBootComponentName.c
>    HttpBootImpl.h
> @@ -41,6 +43,8 @@
>    HttpBootSupport.c
>    HttpBootClient.h
>    HttpBootClient.c
> +  HttpBootConfigVfr.vfr
> +  HttpBootConfigStrings.uni
> 
>  [LibraryClasses]
>    UefiDriverEntryPoint
> @@ -52,6 +56,9 @@
>    DebugLib
>    NetLib
>    HttpLib
> +  HiiLib
> +  PrintLib
> +  UefiHiiServicesLib
> 
>  [Protocols]
>    ## TO_START
> @@ -72,6 +79,14 @@
>    gEfiIp6ProtocolGuid                             ## TO_START
>    gEfiIp6ConfigProtocolGuid                       ## TO_START
>    gEfiNetworkInterfaceIdentifierProtocolGuid_31   ##
> SOMETIMES_CONSUMES
> +  gEfiHiiConfigAccessProtocolGuid                 ## BY_START
> +
> +[Guids]
> +  ## SOMETIMES_CONSUMES ## GUID # HiiIsConfigHdrMatch
> mHttpBootConfigStorageName
> +  ## SOMETIMES_PRODUCES ## GUID # HiiConstructConfigHdr
> mHttpBootConfigStorageName
> +  ## SOMETIMES_PRODUCES ## GUID # HiiGetBrowserData
> mHttpBootConfigStorageName
> +  ## SOMETIMES_CONSUMES ## HII
> +  gHttpBootConfigGuid
> 
>  [UserExtensions.TianoCore."ExtraFiles"]
>    HttpBootDxeExtra.uni
> diff --git a/NetworkPkg/HttpBootDxe/HttpBootImpl.c
> b/NetworkPkg/HttpBootDxe/HttpBootImpl.c
> index 9ea0d7f..3adb08d 100644
> --- a/NetworkPkg/HttpBootDxe/HttpBootImpl.c
> +++ b/NetworkPkg/HttpBootDxe/HttpBootImpl.c
> @@ -1,7 +1,7 @@
>  /** @file
>    The implementation of EFI_LOAD_FILE_PROTOCOL for UEFI HTTP boot.
> 
> -Copyright (c) 2015, Intel Corporation. All rights reserved.<BR>
> +Copyright (c) 2015 - 2016, 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
> @@ -21,22 +21,25 @@ WITHOUT WARRANTIES OR REPRESENTATIONS OF
> ANY KIND, EITHER EXPRESS OR IMPLIED.
>    @param[in]    UsingIpv6          Specifies the type of IP addresses that 
> are to be
>                                     used during the session that is being 
> started.
>                                     Set to TRUE for IPv6, and FALSE for IPv4.
> +  @param[in]    FilePath           The device specific path of the file to 
> load.
> 
>    @retval EFI_SUCCESS              HTTP boot was successfully enabled.
>    @retval EFI_INVALID_PARAMETER    Private is NULL.
>    @retval EFI_ALREADY_STARTED      The driver is already in started state.
> +  @retval EFI_OUT_OF_RESOURCES     There are not enough resources.
> 
>  **/
>  EFI_STATUS
>  HttpBootStart (
>    IN HTTP_BOOT_PRIVATE_DATA           *Private,
> -  IN BOOLEAN                          UsingIpv6
> +  IN BOOLEAN                          UsingIpv6,
> +  IN EFI_DEVICE_PATH_PROTOCOL         *FilePath
>    )
>  {
>    UINTN                Index;
>    EFI_STATUS           Status;
> 
> -  if (Private == NULL) {
> +  if (Private == NULL || FilePath == NULL) {
>      return EFI_INVALID_PARAMETER;
>    }
> 
> @@ -54,6 +57,26 @@ HttpBootStart (
>    } else {
>      return EFI_UNSUPPORTED;
>    }
> +
> +  //
> +  // Check whether the URI address is specified.
> +  //
> +  Status = HttpBootParseFilePath (FilePath, &Private->FilePathUri);
> +  if (EFI_ERROR (Status)) {
> +    return EFI_INVALID_PARAMETER;
> +  }
> +
> +  if (Private->FilePathUri != NULL) {
> +    Status = HttpParseUrl (
> +               Private->FilePathUri,
> +               (UINT32) AsciiStrLen (Private->FilePathUri),
> +               FALSE,
> +               &Private->FilePathUriParser
> +               );
> +    if (EFI_ERROR (Status)) {
> +      return Status;
> +    }
> +  }
> 
>    //
>    // Init the content of cached DHCP offer list.
> @@ -301,12 +324,21 @@ HttpBootStop (
>        }
>      }
>    }
> +
> +  if (Private->FilePathUri!= NULL) {
> +    FreePool (Private->FilePathUri);
> +    HttpUrlFreeParser (Private->FilePathUriParser);
> +    Private->FilePathUri = NULL;
> +    Private->FilePathUriParser = NULL;
> +  }
> 
>    ZeroMem (Private->OfferBuffer, sizeof (Private->OfferBuffer));
>    Private->OfferNum = 0;
>    ZeroMem (Private->OfferCount, sizeof (Private->OfferCount));
>    ZeroMem (Private->OfferIndex, sizeof (Private->OfferIndex));
> -
> +
> +  HttpBootFreeCacheList (Private);
> +
>    return EFI_SUCCESS;
>  }
> 
> @@ -357,7 +389,7 @@ HttpBootDxeLoadFile (
>    BOOLEAN                       UsingIpv6;
>    EFI_STATUS                    Status;
> 
> -  if (This == NULL || BufferSize == NULL) {
> +  if (This == NULL || BufferSize == NULL || FilePath == NULL) {
>      return EFI_INVALID_PARAMETER;
>    }
> 
> @@ -370,7 +402,6 @@ HttpBootDxeLoadFile (
> 
>    VirtualNic = HTTP_BOOT_VIRTUAL_NIC_FROM_LOADFILE (This);
>    Private = VirtualNic->Private;
> -  UsingIpv6 = FALSE;
> 
>    //
>    // Check media status before HTTP boot start
> @@ -380,27 +411,37 @@ HttpBootDxeLoadFile (
>    if (!MediaPresent) {
>      return EFI_NO_MEDIA;
>    }
> -
> +
>    //
>    // Check whether the virtual nic is using IPv6 or not.
>    //
> +  UsingIpv6 = FALSE;
>    if (VirtualNic == Private->Ip6Nic) {
>      UsingIpv6 = TRUE;
>    }
> -
> +
>    //
> -  // Initialize HTTP boot and load the boot file.
> +  // Initialize HTTP boot.
>    //
> -  Status = HttpBootStart (Private, UsingIpv6);
> -  if (Status == EFI_ALREADY_STARTED && UsingIpv6 != Private->UsingIpv6) {
> +  Status = HttpBootStart (Private, UsingIpv6, FilePath);
> +  if (Status == EFI_ALREADY_STARTED) {
>      //
> -    // Http boot Driver has already been started but not on the required IP
> version, restart it.
> +    // Restart the HTTP boot driver in 2 cases:
> +    // 1. Http boot Driver has already been started but not on the required 
> IP
> version.
> +    // 2. The required boot FilePath is different with the one we produced in
> the device path
> +    // protocol.
>      //
> -    Status = HttpBootStop (Private);
> -    if (!EFI_ERROR (Status)) {
> -      Status = HttpBootStart (Private, UsingIpv6);
> +    if ((UsingIpv6 != Private->UsingIpv6) || !IsDevicePathEnd(FilePath)) {
> +      Status = HttpBootStop (Private);
> +      if (!EFI_ERROR (Status)) {
> +        Status = HttpBootStart (Private, UsingIpv6, FilePath);
> +      }
>      }
>    }
> +
> +  //
> +  // Load the boot file.
> +  //
>    if (Status == EFI_SUCCESS || Status == EFI_ALREADY_STARTED) {
>      Status = HttpBootLoadFile (Private, BufferSize, Buffer);
>    }
> diff --git a/NetworkPkg/HttpBootDxe/HttpBootSupport.c
> b/NetworkPkg/HttpBootDxe/HttpBootSupport.c
> index db2af78..f30d9f7 100644
> --- a/NetworkPkg/HttpBootDxe/HttpBootSupport.c
> +++ b/NetworkPkg/HttpBootDxe/HttpBootSupport.c
> @@ -977,3 +977,66 @@ HttpIoRecvResponse (
> 
>    return Status;
>  }
> +
> +/**
> +  Get the URI address string from the input device path.
> +
> +  Caller need to free the buffer in the UriAddress pointer.
> +
> +  @param[in]   FilePath         Pointer to the device path which contains a 
> URI
> device path node.
> +  @param[in]   UriAddress       The URI address string extract from the 
> device
> path.
> +
> +  @retval EFI_SUCCESS            The URI string is returned.
> +  @retval EFI_OUT_OF_RESOURCES   Failed to allocate memory.
> +
> +**/
> +EFI_STATUS
> +HttpBootParseFilePath (
> +  IN     EFI_DEVICE_PATH_PROTOCOL     *FilePath,
> +     OUT CHAR8                        **UriAddress
> +  )
> +{
> +  EFI_DEVICE_PATH_PROTOCOL  *TempDevicePath;
> +  URI_DEVICE_PATH           *UriDevicePath;
> +  CHAR8                     *Uri;
> +  UINTN                     UriStrLength;
> +
> +  if (FilePath == NULL) {
> +    return EFI_INVALID_PARAMETER;
> +  }
> +
> +  *UriAddress = NULL;
> +
> +  //
> +  // Extract the URI address from the FilePath
> +  //
> +  TempDevicePath = FilePath;
> +  while (!IsDevicePathEnd (TempDevicePath)) {
> +    if ((DevicePathType (TempDevicePath) == MESSAGING_DEVICE_PATH) &&
> +        (DevicePathSubType (TempDevicePath) == MSG_URI_DP)) {
> +      UriDevicePath = (URI_DEVICE_PATH*) TempDevicePath;
> +      //
> +      // UEFI Spec doesn't require the URI to be a NULL-terminated string
> +      // So we allocate a new buffer and always append a '\0' to it.
> +      //
> +      UriStrLength = DevicePathNodeLength (UriDevicePath) -
> sizeof(EFI_DEVICE_PATH_PROTOCOL);
> +      if (UriStrLength == 0) {
> +        //
> +        // return a NULL UriAddress if it's a empty URI device path node.
> +        //
> +        break;
> +      }
> +      Uri = AllocatePool (UriStrLength + 1);
> +      if (Uri == NULL) {
> +        return EFI_OUT_OF_RESOURCES;
> +      }
> +      CopyMem (Uri, UriDevicePath->Uri, DevicePathNodeLength
> (UriDevicePath) - sizeof(EFI_DEVICE_PATH_PROTOCOL));
> +      Uri[DevicePathNodeLength (UriDevicePath) -
> sizeof(EFI_DEVICE_PATH_PROTOCOL)] = '\0';
> +
> +      *UriAddress = Uri;
> +    }
> +    TempDevicePath = NextDevicePathNode (TempDevicePath);
> +  }
> +
> +  return EFI_SUCCESS;
> +}
> diff --git a/NetworkPkg/HttpBootDxe/HttpBootSupport.h
> b/NetworkPkg/HttpBootDxe/HttpBootSupport.h
> index 8e0fc37..3edea61 100644
> --- a/NetworkPkg/HttpBootDxe/HttpBootSupport.h
> +++ b/NetworkPkg/HttpBootDxe/HttpBootSupport.h
> @@ -329,4 +329,22 @@ HttpIoRecvResponse (
>       OUT  HTTP_IO_RESPONSE_DATA    *ResponseData
>    );
> 
> +/**
> +  Get the URI address string from the input device path.
> +
> +  Caller need to free the buffer in the UriAddress pointer.
> +
> +  @param[in]   FilePath         Pointer to the device path which contains a 
> URI
> device path node.
> +  @param[in]   UriAddress       The URI address string extract from the 
> device
> path.
> +
> +  @retval EFI_SUCCESS            The URI string is returned.
> +  @retval EFI_OUT_OF_RESOURCES   Failed to allocate memory.
> +
> +**/
> +EFI_STATUS
> +HttpBootParseFilePath (
> +  IN     EFI_DEVICE_PATH_PROTOCOL     *FilePath,
> +     OUT CHAR8                        **UriAddress
> +  );
> +
>  #endif
> diff --git a/NetworkPkg/Include/Guid/HttpBootConfigHii.h
> b/NetworkPkg/Include/Guid/HttpBootConfigHii.h
> new file mode 100644
> index 0000000..7e44436
> --- /dev/null
> +++ b/NetworkPkg/Include/Guid/HttpBootConfigHii.h
> @@ -0,0 +1,25 @@
> +/** @file
> +  GUIDs used as HII FormSet and HII Package list GUID in HTTP boot driver.
> +
> +Copyright (c) 2016, 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 __HTTP_BOOT_HII_GUID_H__
> +#define __HTTP_BOOT_HII_GUID_H__
> +
> +#define HTTP_BOOT_CONFIG_GUID \
> +  { \
> +    0x4d20583a, 0x7765, 0x4e7a, { 0x8a, 0x67, 0xdc, 0xde, 0x74, 0xee, 0x3e,
> 0xc5 } \
> +  }
> +
> +extern EFI_GUID gHttpBootConfigGuid;
> +
> +#endif
> diff --git a/NetworkPkg/NetworkPkg.dec b/NetworkPkg/NetworkPkg.dec
> index 288d1aa..268188a 100644
> --- a/NetworkPkg/NetworkPkg.dec
> +++ b/NetworkPkg/NetworkPkg.dec
> @@ -4,7 +4,7 @@
>  # This package provides network modules that conform to UEFI 2.4
> specification.
>  #
>  # (C) Copyright 2015 Hewlett-Packard Development Company, L.P.<BR>
> -# Copyright (c) 2009 - 2015, Intel Corporation. All rights reserved.<BR>
> +# Copyright (c) 2009 - 2016, Intel Corporation. All rights reserved.<BR>
>  #
>  # This program and the accompanying materials are licensed and made
> available under
>  # the terms and conditions of the BSD License which accompanies this
> distribution.
> @@ -37,6 +37,9 @@
>    # Include/Guid/IscsiConfigHii.h
>    gIScsiConfigGuid              = { 0x4b47d616, 0xa8d6, 0x4552, { 0x9d, 
> 0x44, 0xcc,
> 0xad, 0x2e, 0xf, 0x4c, 0xf9}}
> 
> +  # Include/Guid/HttpBootConfigHii.h
> +  gHttpBootConfigGuid           = { 0x4d20583a, 0x7765, 0x4e7a, { 0x8a, 0x67,
> 0xdc, 0xde, 0x74, 0xee, 0x3e, 0xc5 }}
> +
>  [PcdsFeatureFlag]
>    ## Indicates if the IPsec IKEv2 Certificate Authentication feature is 
> enabled
> or not.<BR><BR>
>    #   TRUE  - Certificate Authentication feature is enabled.<BR>
> --
> 2.7.0.windows.2
> 
> _______________________________________________
> edk2-devel mailing list
> edk2-devel@lists.01.org
> https://lists.01.org/mailman/listinfo/edk2-devel
_______________________________________________
edk2-devel mailing list
edk2-devel@lists.01.org
https://lists.01.org/mailman/listinfo/edk2-devel

Reply via email to