**/\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
+ // Add a new load option.\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
- //\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
+ UINTN Index;\r
+ CHAR16 *Uri;\r
+ HTTP_BOOT_FORM_CALLBACK_INFO *CallbackInfo;\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
+ if (Uri == NULL) {\r
+ return EFI_UNSUPPORTED;\r
+ }\r
+\r
+ //\r
+ // Convert the scheme to all lower case.\r
+ //\r
+ for (Index = 0; Index < StrLen (Uri); Index++) {\r
+ if (Uri[Index] == L':') {\r
+ break;\r
+ }\r
+ if (Uri[Index] >= L'A' && Uri[Index] <= L'Z') {\r
+ Uri[Index] -= (CHAR16)(L'A' - L'a');\r
+ }\r
+ }\r
+\r
+ //\r
+ // Set the converted URI string back\r
+ //\r
+ HiiSetString (CallbackInfo->RegisteredHandle, Value->string, Uri, 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 other unsupported URI.\r
+ //\r
+ if ((StrLen (Uri) != 0) && (StrnCmp (Uri, L"http://", 7) != 0) && (StrnCmp (Uri, L"https://", 8) != 0)) {\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
+ }\r
+\r
+ FreePool (Uri);\r
+ break;\r
+\r
+ default:\r
+ break;\r
+ }\r
+\r
+ return EFI_SUCCESS;\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