| /** @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; | |
| } | |
| // | |
| // 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 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, | |
| (VOID **)&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; | |
| 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)) { | |
| 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->Initilized = 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; | |
| } |