You are right, I will update it.

From: Wu, Jiaxin
Sent: Monday, February 29, 2016 3:40 PM
To: Fu, Siyuan <siyuan...@intel.com>; edk2-devel@lists.01.org
Cc: Ye, Ting <ting...@intel.com>
Subject: RE: [Patch] NetworkPkg: Add URI configuration form to HTTP boot driver.

Siyuan,

Seems unreasonable to only accept http and https URI. If the user input Http or 
HTTP or HTTPS, it will failed to add those reasonable URI. How about use the 
ignore case check?

Thanks.
Jiaxin


> -----Original Message-----
> From: Fu, Siyuan
> Sent: Wednesday, February 24, 2016 1:27 PM
> To: edk2-devel@lists.01.org<mailto:edk2-devel@lists.01.org>
> Cc: Wu, Jiaxin <jiaxin...@intel.com<mailto:jiaxin...@intel.com>>; Ye, Ting 
> <ting...@intel.com<mailto:ting...@intel.com>>
> Subject: [Patch] 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<mailto:siyuan...@intel.com>>
> Cc: Wu Jiaxin <jiaxin...@intel.com<mailto:jiaxin...@intel.com>>
> Cc: Ye Ting <ting...@intel.com<mailto:ting...@intel.com>>
> ---
>  NetworkPkg/HttpBootDxe/HttpBootClient.c            |  99 +--
>  NetworkPkg/HttpBootDxe/HttpBootConfig.c            | 711
> +++++++++++++++++++++
>  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           |  55 ++
>  NetworkPkg/HttpBootDxe/HttpBootSupport.h           |  18 +
>  NetworkPkg/Include/Guid/HttpBootConfigHii.h        |  25 +
>  NetworkPkg/NetworkPkg.dec                          |   5 +-
>  17 files changed, 1268 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 dd835c4..37333ee 100644
> --- a/NetworkPkg/HttpBootDxe/HttpBootClient.c
> +++ b/NetworkPkg/HttpBootDxe/HttpBootClient.c
> @@ -167,18 +167,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 (
> @@ -195,8 +212,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) {
> @@ -204,13 +221,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);
> @@ -259,12 +269,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_DHCP4_TAG_INDEX_BOOTFILE]->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;
>    }
>
>    //
> @@ -278,7 +303,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 (
> @@ -296,8 +323,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
>               );
>
> @@ -306,8 +333,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)) {
> @@ -342,8 +369,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) {
> @@ -351,13 +378,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);
> @@ -569,10 +589,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);
>      //
> @@ -606,12 +622,6 @@ HttpBootGetFileFromCache (
>          }
>        }
>        *BufferSize = CopyedSize;
> -
> -      //
> -      // On success, free the cached data to release the memory resource.
> -      //
> -      RemoveEntryList (&Cache->Link);
> -      HttpBootFreeCache (Cache);
>        return EFI_SUCCESS;
>      }
>    }
> @@ -1082,3 +1092,4 @@ ERROR_1:
>
>    return Status;
>  }
> +
> diff --git a/NetworkPkg/HttpBootDxe/HttpBootConfig.c
> b/NetworkPkg/HttpBootDxe/HttpBootConfig.c
> new file mode 100644
> index 0000000..19aaaff
> --- /dev/null
> +++ b/NetworkPkg/HttpBootDxe/HttpBootConfig.c
> @@ -0,0 +1,711 @@
> +/** @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;
> +  }
> +
> +  //
> +  // 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..5001220eb3cc71f1bf7e53e53b
> 142bea34254043
> 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|yg
> 9_39;
> zc&_AW&R7v2fim}6M=ByKJY&bK_?;2vA4o+oT*Or7B_gUmyhhkm^vX2PfG{n
> VtSVm?
> 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%G
> sMnS!
> 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 452c8f4..2a66c3d 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>
>  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,6 +21,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>
> @@ -28,6 +30,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
> @@ -39,6 +43,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>
> @@ -52,6 +58,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
> @@ -78,6 +89,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;
> @@ -92,6 +104,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;
> @@ -129,6 +149,11 @@ struct _HTTP_BOOT_PRIVATE_DATA {
>    UINT32                                    Id;
>
>    //
> +  // HII callback info block
> +  //
> +  HTTP_BOOT_FORM_CALLBACK_INFO              CallbackInfo;
> +
> +  //
>    // Mode data
>    //
>    BOOLEAN                                   UsingIpv6;
> @@ -144,6 +169,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..c9bfa11 100644
> --- a/NetworkPkg/HttpBootDxe/HttpBootSupport.c
> +++ b/NetworkPkg/HttpBootDxe/HttpBootSupport.c
> @@ -977,3 +977,58 @@ 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;
> +
> +  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.
> +      //
> +      Uri = AllocatePool (DevicePathNodeLength (UriDevicePath) -
> sizeof(EFI_DEVICE_PATH_PROTOCOL) + 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

Reply via email to