/** @file
  Helper functions for configuring or getting the parameters relating to HTTP Boot.

Copyright (c) 2016 - 2018, Intel Corporation. All rights reserved.<BR>
SPDX-License-Identifier: BSD-2-Clause-Patent

**/

#include "HttpBootDxe.h"
#include <Library/UefiBootManagerLib.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];
  EFI_STATUS                    Status;
  UINTN                         Index;
  EFI_BOOT_MANAGER_LOAD_OPTION  NewOption;

  NewDevicePath = NULL;
  Node          = NULL;
  TmpDevicePath = 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 empty URI, or http and https URI.
  //
  if ((StrLen (Uri) != 0) && (StrnCmp (Uri, L"http://", 7) != 0) && (StrnCmp (Uri, L"https://", 8) != 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.
  //
  UnicodeStrToAsciiStrS (Uri, AsciiUri, sizeof (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;
  }

  //
  // Add a new load option.
  //
  Status = EfiBootManagerInitializeLoadOption (
             &NewOption,
             LoadOptionNumberUnassigned,
             LoadOptionTypeBoot,
             LOAD_OPTION_ACTIVE,
             Description,
             NewDevicePath,
             NULL,
             0
             );
  if (EFI_ERROR (Status)) {
    goto ON_EXIT;
  }

  Status = EfiBootManagerAddLoadOptionVariable (&NewOption, (UINTN)-1);
  EfiBootManagerFreeLoadOption (&NewOption);

ON_EXIT:

  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);
  StrCpyS (CallbackInfo->HttpBootNvData.Description, DESCRIPTION_STR_MAX_SIZE / sizeof (CHAR16), HTTP_BOOT_DEFAULT_DESCRIPTION_STR);

  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);
    if (ConfigRequest == NULL) {
      return EFI_OUT_OF_RESOURCES;
    }

    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
                                );

  //
  // 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.
  //
  HttpBootAddBootOption (
    Private,
    (CallbackInfo->HttpBootNvData.IpVersion == HTTP_BOOT_IP_VERSION_6) ? TRUE : FALSE,
    CallbackInfo->HttpBootNvData.Description,
    CallbackInfo->HttpBootNvData.Uri
    );

  return EFI_SUCCESS;
}

/**

  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
  )
{
  EFI_INPUT_KEY                 Key;
  CHAR16                        *Uri;
  UINTN                         UriLen;
  CHAR8                         *AsciiUri;
  HTTP_BOOT_FORM_CALLBACK_INFO  *CallbackInfo;
  EFI_STATUS                    Status;

  Uri      = NULL;
  UriLen   = 0;
  AsciiUri = NULL;
  Status   = EFI_SUCCESS;

  if ((This == NULL) || (Value == NULL)) {
    return EFI_INVALID_PARAMETER;
  }

  CallbackInfo = HTTP_BOOT_FORM_CALLBACK_INFO_FROM_CONFIG_ACCESS (This);

  if (Action != EFI_BROWSER_ACTION_CHANGING) {
    return EFI_UNSUPPORTED;
  }

  switch (QuestionId) {
    case KEY_INITIATOR_URI:
      //
      // Get user input URI string
      //
      Uri = HiiGetString (CallbackInfo->RegisteredHandle, Value->string, NULL);
      if (Uri == NULL) {
        return EFI_INVALID_PARAMETER;
      }

      //
      // The URI should be either an empty string (for corporate environment) ,or http(s) for home environment.
      // Pop up a message box for the unsupported URI.
      //
      if (StrLen (Uri) != 0) {
        UriLen   = StrLen (Uri) + 1;
        AsciiUri = AllocateZeroPool (UriLen);
        if (AsciiUri == NULL) {
          FreePool (Uri);
          return EFI_OUT_OF_RESOURCES;
        }

        UnicodeStrToAsciiStrS (Uri, AsciiUri, UriLen);

        Status = HttpBootCheckUriScheme (AsciiUri);

        if (Status == EFI_INVALID_PARAMETER) {
          DEBUG ((DEBUG_ERROR, "HttpBootFormCallback: %r.\n", Status));

          CreatePopUp (
            EFI_LIGHTGRAY | EFI_BACKGROUND_BLUE,
            &Key,
            L"ERROR: Unsupported URI!",
            L"Only supports HTTP and HTTPS",
            NULL
            );
        } else if (Status == EFI_ACCESS_DENIED) {
          DEBUG ((DEBUG_ERROR, "HttpBootFormCallback: %r.\n", Status));

          CreatePopUp (
            EFI_LIGHTGRAY | EFI_BACKGROUND_BLUE,
            &Key,
            L"ERROR: Unsupported URI!",
            L"HTTP is disabled",
            NULL
            );
        }
      }

      if (Uri != NULL) {
        FreePool (Uri);
      }

      if (AsciiUri != NULL) {
        FreePool (AsciiUri);
      }

      break;

    default:
      break;
  }

  return Status;
}

/**
  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;
  CHAR16                        *MacString;
  CHAR16                        *OldMenuString;
  CHAR16                        MenuString[128];

  CallbackInfo = &Private->CallbackInfo;

  if (CallbackInfo->Initialized) {
    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)) {
    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, NULL, &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);

    CallbackInfo->Initialized = TRUE;
    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.
  The form will only be unload completely when both IP4 and IP6 stack are stopped.

  @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;

  if ((Private->Ip4Nic != NULL) || (Private->Ip6Nic != NULL)) {
    //
    // Only unload the configuration form when both IP4 and IP6 stack are stopped.
    //
    return EFI_SUCCESS;
  }

  CallbackInfo = &Private->CallbackInfo;
  if (CallbackInfo->ChildHandle != NULL) {
    //
    // 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;
}
