/** @file\r
Helper functions for configuring or getting the parameters relating to HTTP Boot.\r
\r
-Copyright (c) 2016, Intel Corporation. All rights reserved.<BR>\r
+Copyright (c) 2016 - 2017, Intel Corporation. All rights reserved.<BR>\r
This program and the accompanying materials\r
are licensed and made available under the terms and conditions of the BSD License\r
which accompanies this distribution. The full text of the license may be found at\r
**/\r
\r
#include "HttpBootDxe.h"\r
+#include <Library/UefiBootManagerLib.h>\r
\r
CHAR16 mHttpBootConfigStorageName[] = L"HTTP_BOOT_CONFIG_IFR_NVDATA";\r
\r
IN CHAR16 *Uri\r
)\r
{\r
- EFI_DEV_PATH *Node;\r
- EFI_DEVICE_PATH_PROTOCOL *TmpDevicePath;\r
- EFI_DEVICE_PATH_PROTOCOL *NewDevicePath;\r
- UINTN Length;\r
- CHAR8 AsciiUri[URI_STR_MAX_SIZE];\r
- CHAR16 *CurrentOrder;\r
- EFI_STATUS Status;\r
- UINTN OrderCount;\r
- UINTN TargetLocation;\r
- BOOLEAN Found;\r
- UINT8 *TempByteBuffer;\r
- UINT8 *TempByteStart;\r
- UINTN DescSize;\r
- UINTN FilePathSize;\r
- CHAR16 OptionStr[10];\r
- UINT16 *NewOrder;\r
- UINTN Index;\r
-\r
- NewOrder = NULL;\r
- TempByteStart = NULL;\r
+ EFI_DEV_PATH *Node;\r
+ EFI_DEVICE_PATH_PROTOCOL *TmpDevicePath;\r
+ EFI_DEVICE_PATH_PROTOCOL *NewDevicePath;\r
+ UINTN Length;\r
+ CHAR8 AsciiUri[URI_STR_MAX_SIZE];\r
+ EFI_STATUS Status;\r
+ UINTN Index;\r
+ EFI_BOOT_MANAGER_LOAD_OPTION NewOption;\r
+\r
NewDevicePath = NULL;\r
- NewOrder = NULL;\r
Node = NULL;\r
TmpDevicePath = NULL;\r
- CurrentOrder = NULL;\r
\r
if (StrLen (Description) == 0) {\r
return EFI_INVALID_PARAMETER;\r
}\r
\r
//\r
- // Only accept http and https URI.\r
+ // Only accept empty URI, or http and https URI.\r
//\r
- if ((StrnCmp (Uri, L"http://", 7) != 0) && (StrnCmp (Uri, L"https://", 7) != 0)) {\r
+ if ((StrLen (Uri) != 0) && (StrnCmp (Uri, L"http://", 7) != 0) && (StrnCmp (Uri, L"https://", 8) != 0)) {\r
return EFI_INVALID_PARAMETER;\r
}\r
\r
//\r
// Update the URI node with the input boot file URI.\r
//\r
- UnicodeStrToAsciiStr (Uri, AsciiUri);\r
+ UnicodeStrToAsciiStrS (Uri, AsciiUri, sizeof (AsciiUri));\r
Length = sizeof (EFI_DEVICE_PATH_PROTOCOL) + AsciiStrSize (AsciiUri);\r
Node = AllocatePool (Length);\r
if (Node == NULL) {\r
}\r
\r
//\r
- // Get current "BootOrder" variable and find a free target.\r
- //\r
- Length = 0;\r
- Status = GetVariable2 (\r
- L"BootOrder",\r
- &gEfiGlobalVariableGuid,\r
- &CurrentOrder,\r
- &Length \r
- );\r
- if (EFI_ERROR (Status) && Status != EFI_NOT_FOUND) {\r
- goto ON_EXIT;\r
- }\r
- OrderCount = Length / sizeof (UINT16);\r
- Found = FALSE;\r
- for (TargetLocation=0; TargetLocation < 0xFFFF; TargetLocation++) {\r
- Found = TRUE;\r
- for (Index = 0; Index < OrderCount; Index++) {\r
- if (CurrentOrder[Index] == TargetLocation) {\r
- Found = FALSE;\r
- break;\r
- }\r
- }\r
- if (Found) {\r
- break;\r
- }\r
- }\r
-\r
- if (TargetLocation == 0xFFFF) {\r
- DEBUG ((EFI_D_ERROR, "Could not find unused target index.\n"));\r
- Status = EFI_OUT_OF_RESOURCES;\r
- goto ON_EXIT;\r
- } else {\r
- DEBUG ((EFI_D_INFO, "TargetIndex = %04x.\n", TargetLocation));\r
- }\r
- \r
- //\r
- // Construct and set the "Boot####" variable\r
+ // Add a new load option.\r
//\r
- DescSize = StrSize(Description);\r
- FilePathSize = GetDevicePathSize (NewDevicePath);\r
- TempByteBuffer = AllocateZeroPool(sizeof(EFI_LOAD_OPTION) + DescSize + FilePathSize);\r
- if (TempByteBuffer == NULL) {\r
- Status = EFI_OUT_OF_RESOURCES;\r
- goto ON_EXIT;\r
- }\r
-\r
- TempByteStart = TempByteBuffer;\r
- *((UINT32 *) TempByteBuffer) = LOAD_OPTION_ACTIVE; // Attributes\r
- TempByteBuffer += sizeof (UINT32);\r
-\r
- *((UINT16 *) TempByteBuffer) = (UINT16)FilePathSize; // FilePathListLength\r
- TempByteBuffer += sizeof (UINT16);\r
-\r
- CopyMem (TempByteBuffer, Description, DescSize);\r
- TempByteBuffer += DescSize;\r
- CopyMem (TempByteBuffer, NewDevicePath, FilePathSize);\r
-\r
- UnicodeSPrint (OptionStr, sizeof(OptionStr), L"%s%04x", L"Boot", TargetLocation);\r
- Status = gRT->SetVariable (\r
- OptionStr,\r
- &gEfiGlobalVariableGuid,\r
- EFI_VARIABLE_NON_VOLATILE | EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_RUNTIME_ACCESS,\r
- sizeof(UINT32) + sizeof(UINT16) + DescSize + FilePathSize,\r
- TempByteStart\r
- );\r
+ Status = EfiBootManagerInitializeLoadOption (\r
+ &NewOption,\r
+ LoadOptionNumberUnassigned,\r
+ LoadOptionTypeBoot,\r
+ LOAD_OPTION_ACTIVE,\r
+ Description,\r
+ NewDevicePath,\r
+ NULL,\r
+ 0\r
+ );\r
if (EFI_ERROR (Status)) {\r
goto ON_EXIT;\r
}\r
\r
- //\r
- // Insert into the order list and set "BootOrder" variable\r
- //\r
- NewOrder = AllocateZeroPool ((OrderCount + 1) * sizeof (UINT16));\r
- if (NewOrder == NULL) {\r
- Status = EFI_OUT_OF_RESOURCES;\r
- goto ON_EXIT;\r
- }\r
- CopyMem(NewOrder, CurrentOrder, OrderCount * sizeof(UINT16));\r
- NewOrder[OrderCount] = (UINT16) TargetLocation;\r
- Status = gRT->SetVariable (\r
- L"BootOrder",\r
- &gEfiGlobalVariableGuid,\r
- EFI_VARIABLE_NON_VOLATILE | EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_RUNTIME_ACCESS,\r
- ((OrderCount + 1) * sizeof (UINT16)),\r
- NewOrder\r
- );\r
- \r
+ Status = EfiBootManagerAddLoadOptionVariable (&NewOption, (UINTN) -1);\r
+ EfiBootManagerFreeLoadOption (&NewOption);\r
\r
ON_EXIT:\r
\r
- if (CurrentOrder != NULL) {\r
- FreePool (CurrentOrder);\r
- }\r
- if (NewOrder != NULL) {\r
- FreePool (NewOrder);\r
- }\r
- if (TempByteStart != NULL) {\r
- FreePool (TempByteStart);\r
- }\r
if (NewDevicePath != NULL) {\r
FreePool (NewDevicePath);\r
}\r
//\r
BufferSize = sizeof (HTTP_BOOT_CONFIG_IFR_NVDATA);\r
ZeroMem (&CallbackInfo->HttpBootNvData, BufferSize);\r
+ StrCpyS (CallbackInfo->HttpBootNvData.Description, DESCRIPTION_STR_MAX_SIZE / sizeof (CHAR16), HTTP_BOOT_DEFAULT_DESCRIPTION_STR);\r
\r
ConfigRequest = Request;\r
if ((Request == NULL) || (StrStr (Request, L"OFFSET") == NULL)) {\r
ConfigRequestHdr = HiiConstructConfigHdr (&gHttpBootConfigGuid, mHttpBootConfigStorageName, CallbackInfo->ChildHandle);\r
Size = (StrLen (ConfigRequestHdr) + 32 + 1) * sizeof (CHAR16);\r
ConfigRequest = AllocateZeroPool (Size);\r
- ASSERT (ConfigRequest != NULL);\r
+ if (ConfigRequest == NULL) {\r
+ return EFI_OUT_OF_RESOURCES;\r
+ }\r
AllocatedRequest = TRUE;\r
UnicodeSPrint (ConfigRequest, Size, L"%s&OFFSET=0&WIDTH=%016LX", ConfigRequestHdr, (UINT64)BufferSize);\r
FreePool (ConfigRequestHdr);\r
Results,\r
Progress\r
);\r
- ASSERT_EFI_ERROR (Status);\r
\r
//\r
// Free the allocated config request string.\r
//\r
// Create a new boot option according to the configuration data.\r
//\r
- Status = HttpBootAddBootOption (\r
- Private,\r
- (CallbackInfo->HttpBootNvData.IpVersion == HTTP_BOOT_IP_VERSION_6) ? TRUE : FALSE,\r
- CallbackInfo->HttpBootNvData.Description,\r
- CallbackInfo->HttpBootNvData.Uri\r
- );\r
+ HttpBootAddBootOption (\r
+ Private,\r
+ (CallbackInfo->HttpBootNvData.IpVersion == HTTP_BOOT_IP_VERSION_6) ? TRUE : FALSE,\r
+ CallbackInfo->HttpBootNvData.Description,\r
+ CallbackInfo->HttpBootNvData.Uri\r
+ );\r
\r
- return Status;\r
+ return EFI_SUCCESS;\r
}\r
\r
/**\r
OUT EFI_BROWSER_ACTION_REQUEST *ActionRequest\r
)\r
{\r
- return EFI_UNSUPPORTED;\r
+ EFI_INPUT_KEY Key;\r
+ CHAR16 *Uri;\r
+ UINTN UriLen;\r
+ CHAR8 *AsciiUri;\r
+ HTTP_BOOT_FORM_CALLBACK_INFO *CallbackInfo;\r
+ EFI_STATUS Status;\r
+\r
+ Uri = NULL;\r
+ UriLen = 0;\r
+ AsciiUri = NULL;\r
+ Status = EFI_SUCCESS;\r
+ \r
+ if (This == NULL || Value == NULL) {\r
+ return EFI_INVALID_PARAMETER;\r
+ }\r
+\r
+ CallbackInfo = HTTP_BOOT_FORM_CALLBACK_INFO_FROM_CONFIG_ACCESS (This);\r
+ \r
+ if (Action != EFI_BROWSER_ACTION_CHANGING) {\r
+ return EFI_UNSUPPORTED;\r
+ }\r
+ \r
+ switch (QuestionId) {\r
+ case KEY_INITIATOR_URI:\r
+ //\r
+ // Get user input URI string\r
+ //\r
+ Uri = HiiGetString (CallbackInfo->RegisteredHandle, Value->string, NULL);\r
+\r
+ //\r
+ // The URI should be either an empty string (for corporate environment) ,or http(s) for home environment.\r
+ // Pop up a message box for the unsupported URI.\r
+ //\r
+ if (StrLen (Uri) != 0) {\r
+ UriLen = StrLen (Uri) + 1;\r
+ AsciiUri = AllocateZeroPool (UriLen);\r
+ if (AsciiUri == NULL) {\r
+ FreePool (Uri);\r
+ return EFI_OUT_OF_RESOURCES;\r
+ }\r
+\r
+ UnicodeStrToAsciiStrS (Uri, AsciiUri, UriLen);\r
+\r
+ Status = HttpBootCheckUriScheme (AsciiUri);\r
+ \r
+ if (Status == EFI_INVALID_PARAMETER) {\r
+\r
+ DEBUG ((EFI_D_ERROR, "HttpBootFormCallback: %r.\n", Status));\r
+\r
+ CreatePopUp (\r
+ EFI_LIGHTGRAY | EFI_BACKGROUND_BLUE,\r
+ &Key,\r
+ L"ERROR: Unsupported URI!",\r
+ L"Only supports HTTP and HTTPS",\r
+ NULL\r
+ ); \r
+ } else if (Status == EFI_ACCESS_DENIED) {\r
+ \r
+ DEBUG ((EFI_D_ERROR, "HttpBootFormCallback: %r.\n", Status));\r
+ \r
+ CreatePopUp (\r
+ EFI_LIGHTGRAY | EFI_BACKGROUND_BLUE,\r
+ &Key,\r
+ L"ERROR: Unsupported URI!",\r
+ L"HTTP is disabled",\r
+ NULL\r
+ );\r
+ }\r
+ }\r
+\r
+ if (Uri != NULL) {\r
+ FreePool (Uri);\r
+ }\r
+\r
+ if (AsciiUri != NULL) {\r
+ FreePool (AsciiUri);\r
+ } \r
+ \r
+ break;\r
+\r
+ default:\r
+ break;\r
+ }\r
+\r
+ return Status;\r
}\r
\r
/**\r
EFI_STATUS Status;\r
HTTP_BOOT_FORM_CALLBACK_INFO *CallbackInfo;\r
VENDOR_DEVICE_PATH VendorDeviceNode;\r
- EFI_SERVICE_BINDING_PROTOCOL *HttpSb;\r
CHAR16 *MacString;\r
CHAR16 *OldMenuString;\r
CHAR16 MenuString[128];\r
&CallbackInfo->ConfigAccess,\r
NULL\r
);\r
- if (!EFI_ERROR (Status)) {\r
- //\r
- // Open the Parent Handle for the child\r
- //\r
- Status = gBS->OpenProtocol (\r
- Private->Controller,\r
- &gEfiHttpServiceBindingProtocolGuid,\r
- (VOID **) &HttpSb,\r
- Private->Image,\r
- CallbackInfo->ChildHandle,\r
- EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER\r
- );\r
- }\r
-\r
if (EFI_ERROR (Status)) {\r
goto Error;\r
}\r
//\r
// Append MAC string in the menu help string\r
//\r
- Status = NetLibGetMacString (Private->Controller, Private->Image, &MacString);\r
+ Status = NetLibGetMacString (Private->Controller, NULL, &MacString);\r
if (!EFI_ERROR (Status)) {\r
OldMenuString = HiiGetString (\r
CallbackInfo->RegisteredHandle, \r
FreePool (MacString);\r
FreePool (OldMenuString);\r
\r
+ CallbackInfo->Initilized = TRUE;\r
return EFI_SUCCESS;\r
}\r
\r
/**\r
Unload the configuration form, this includes: delete all the configuration\r
entries, uninstall the form callback protocol, and free the resources used.\r
+ The form will only be unload completely when both IP4 and IP6 stack are stopped.\r
\r
@param[in] Private Pointer to the driver private data.\r
\r
{\r
HTTP_BOOT_FORM_CALLBACK_INFO *CallbackInfo;\r
\r
- CallbackInfo = &Private->CallbackInfo;\r
- if (CallbackInfo->ChildHandle != NULL) {\r
+ if (Private->Ip4Nic != NULL || Private->Ip6Nic != NULL) {\r
//\r
- // Close the child handle\r
+ // Only unload the configuration form when both IP4 and IP6 stack are stopped.\r
//\r
- gBS->CloseProtocol (\r
- Private->Controller,\r
- &gEfiHttpServiceBindingProtocolGuid,\r
- Private->Image,\r
- CallbackInfo->ChildHandle\r
- );\r
- \r
+ return EFI_SUCCESS;\r
+ }\r
+\r
+ CallbackInfo = &Private->CallbackInfo;\r
+ if (CallbackInfo->ChildHandle != NULL) {\r
//\r
// Uninstall EFI_HII_CONFIG_ACCESS_PROTOCOL\r
//\r