Correctly write 'Initialized'. Cc: Jiaxin Wu <jiaxin.wu@intel.com> Cc: Siyuan Fu <siyuan.fu@intel.com> Cc: Maciej Rabeda <maciej.rabeda@intel.com> Reviewed-by: Maciej Rabeda <maciej.rabeda@intel.com> Signed-off-by: Philippe Mathieu-Daude <philmd@redhat.com> Message-Id: <20200207010831.9046-37-philmd@redhat.com>
		
			
				
	
	
		
			701 lines
		
	
	
		
			24 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
			
		
		
	
	
			701 lines
		
	
	
		
			24 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
| /** @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 ((EFI_D_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 ((EFI_D_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;
 | |
| }
 |