/** @file ;****************************************************************************** ;* Copyright (c) 2021, Insyde Software Corporation. All Rights Reserved. ;* ;* You may not reproduce, distribute, publish, display, perform, modify, adapt, ;* transmit, broadcast, present, recite, release, license or otherwise exploit ;* any part of this publication in any form, by any means, without the prior ;* written permission of Insyde Software Corporation. ;* ;****************************************************************************** */ /** @file Intel One Click Recovery Setup Implementation. @copyright INTEL CONFIDENTIAL Copyright 2020 - 2021 Intel Corporation. The source code contained or described herein and all documents related to the source code ("Material") are owned by Intel Corporation or its suppliers or licensors. Title to the Material remains with Intel Corporation or its suppliers and licensors. The Material may contain trade secrets and proprietary and confidential information of Intel Corporation and its suppliers and licensors, and is protected by worldwide copyright and trade secret laws and treaty provisions. No part of the Material may be used, copied, reproduced, modified, published, uploaded, posted, transmitted, distributed, or disclosed in any way without Intel's prior express written permission. No license under any patent, copyright, trade secret or other intellectual property right is granted to or conferred upon you by disclosure or delivery of the Materials, either expressly, by implication, inducement, estoppel or otherwise. Any license under such intellectual property rights must be express and approved by Intel in writing. Unless otherwise agreed by Intel in writing, you may not remove or alter this notice or any other notice embedded in Materials by Intel or Intel's suppliers or licensors in any way. This file contains a 'Sample Driver' and is licensed as such under the terms of your license agreement with Intel or your vendor. This file may be modified by the user, subject to the additional terms of the license agreement. @par Specification Reference: **/ #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include // // One click Recovery Boot Settings GUID // GLOBAL_REMOVE_IF_UNREFERENCED EFI_GUID mOcrBootSettingsGuid = OCR_BOOT_SETTINGS_GUID; // // One Click Recovery Protocol // GLOBAL_REMOVE_IF_UNREFERENCED ONE_CLICK_RECOVERY_PROTOCOL mOneClickRecoveryProtocol = { ONE_CLICK_RECOVERY_PROTOCOL_REVISION, OneClickRecoveryMain, OneClickRecoveryCapabilities, OneClickRecoverySaveUefiBootOption }; // // One Click Recovery String // STATIC CHAR16 *mOcrString = L"One Click Recovery"; // // One Click Recovery Boot Option // OCR_BOOT_OPTION *mOcrBootOption = NULL; // // AMT UEFI Boot Option Parameter // UEFI_BOOT_OPTION_PARAMETER mAmtUefiBootOption; // // OCR Capabilities // ONE_CLICK_RECOVERY_CAP mOcrCap; // // Data for the http boot progress, they are used by http boot callback. // STATIC UINT64 mHttpFileSize = 0; STATIC UINT64 mHttpReceivedSize = 0; STATIC UINT32 mHttpPercentage = 0; // // Flag to indicate if http boot download is complete. // STATIC BOOLEAN mHttpBootDownloadComplete = FALSE; // // Flag to indicate if HTTP Boot callback is invoked. // If current OCR boot is HTTP boot but HTTP Boot callback is not invoked, // it means there is no network connection available. // STATIC BOOLEAN mHttpBootCallbackInvoked = FALSE; // // Handle for EFI_HTTP_BOOT_CALLBACK_PROTOCOL // STATIC EFI_HANDLE mHttpBootCallbackHandle = NULL; // // Handle for EDKII_HTTP_CALLBACK_PROTOCOL // STATIC EFI_HANDLE mHttpCallbackHandle = NULL; STATIC EFI_RSC_HANDLER_PROTOCOL *mRscHandlerProtocol = NULL; /** Callback function that is invoked when HTTP event occurs. @param[in] This Pointer to the EDKII_HTTP_CALLBACK_PROTOCOL instance. @param[in] Event The event that occurs in the current state. @param[in] EventStatus The Status of Event, EFI_SUCCESS or other errors. **/ VOID EFIAPI HttpCallback ( IN EDKII_HTTP_CALLBACK_PROTOCOL *This, IN EDKII_HTTP_CALLBACK_EVENT Event, IN EFI_STATUS EventStatus ); /** Callback function that is invoked when the HTTP Boot driver is about to transmit or has received a packet. This function is invoked when the HTTP Boot driver is about to transmit or has received a packet. Parameters DataType and Received specify the type of event and the format of the buffer pointed to by Data. Due to the polling nature of UEFI device drivers, this callback function should not execute for more than 5 ms. The returned status code determines the behavior of the HTTP Boot driver. @param[in] This Pointer to the EFI_HTTP_BOOT_CALLBACK_PROTOCOL instance. @param[in] DataType The event that occurs in the current state. @param[in] Received TRUE if the callback is being invoked due to a receive event. FALSE if the callback is being invoked due to a transmit event. @param[in] DataLength The length in bytes of the buffer pointed to by Data. @param[in] Data A pointer to the buffer of data, the data type is specified by DataType. @retval EFI_SUCCESS Tells the HTTP Boot driver to continue the HTTP Boot process. **/ EFI_STATUS EFIAPI HttpBootCallback ( IN EFI_HTTP_BOOT_CALLBACK_PROTOCOL *This, IN EFI_HTTP_BOOT_CALLBACK_DATA_TYPE DataType, IN BOOLEAN Received, IN UINT32 DataLength, IN VOID *Data OPTIONAL ); /// /// HTTP Boot Callback Protocol instance /// STATIC EDKII_HTTP_CALLBACK_PROTOCOL mHttpCallback = { HttpCallback }; /// /// HTTP Callback Protocol instance /// STATIC EFI_HTTP_BOOT_CALLBACK_PROTOCOL mHttpBootCallback = { HttpBootCallback }; //[-start-211111-IB09480171-add]// UINT8 GetSecureBootState ( VOID ) { UINT8 Data1; UINT8 Data2; UINT8 SecureBootState; UINT32 VarAttributes; UINTN VarSize; EFI_STATUS Status; Data1 = 0; Data2 = 0; SecureBootState = 0; VarSize = sizeof (UINT8); Status = gRT->GetVariable ( EFI_SECURE_BOOT_ENFORCE_NAME, &gEfiGenericVariableGuid, &VarAttributes, &VarSize, &Data1 ); Status = gRT->GetVariable ( EFI_SECURE_BOOT_MODE_NAME, &gEfiGlobalVariableGuid, NULL, &VarSize, &Data2 ); SecureBootState = Data1 & Data2; return SecureBootState; } //[-end-211111-IB09480171-add]// /** Indicate if the HTTP status code indicates a redirection. @param[in] StatusCode HTTP status code from server. @return TRUE if it's redirection. **/ BOOLEAN IsHttpRedirectStatusCode ( IN EFI_HTTP_STATUS_CODE StatusCode ) { switch (StatusCode) { case HTTP_STATUS_301_MOVED_PERMANENTLY: case HTTP_STATUS_302_FOUND: case HTTP_STATUS_307_TEMPORARY_REDIRECT: case HTTP_STATUS_308_PERMANENT_REDIRECT: return TRUE; default: return FALSE; } } /** Callback function that is invoked when the HTTP Boot driver is about to transmit or has received a packet. This function is invoked when the HTTP Boot driver is about to transmit or has received a packet. Parameters DataType and Received specify the type of event and the format of the buffer pointed to by Data. Due to the polling nature of UEFI device drivers, this callback function should not execute for more than 5 ms. The returned status code determines the behavior of the HTTP Boot driver. @param[in] This Pointer to the EFI_HTTP_BOOT_CALLBACK_PROTOCOL instance. @param[in] DataType The event that occurs in the current state. @param[in] Received TRUE if the callback is being invoked due to a receive event. FALSE if the callback is being invoked due to a transmit event. @param[in] DataLength The length in bytes of the buffer pointed to by Data. @param[in] Data A pointer to the buffer of data, the data type is specified by DataType. @retval EFI_SUCCESS Tells the HTTP Boot driver to continue the HTTP Boot process. **/ EFI_STATUS EFIAPI HttpBootCallback ( IN EFI_HTTP_BOOT_CALLBACK_PROTOCOL *This, IN EFI_HTTP_BOOT_CALLBACK_DATA_TYPE DataType, IN BOOLEAN Received, IN UINT32 DataLength, IN VOID *Data OPTIONAL ) { EFI_HTTP_MESSAGE *HttpMessage; EFI_HTTP_HEADER *HttpHeader; UINT32 Percentage; mHttpBootCallbackInvoked = TRUE; switch (DataType) { case HttpBootDhcp4: case HttpBootDhcp6: Print (L"."); break; case HttpBootHttpRequest: if (Data != NULL) { HttpMessage = (EFI_HTTP_MESSAGE *) Data; if (HttpMessage->Data.Request->Method == HttpMethodGet && HttpMessage->Data.Request->Url != NULL) { Print (L"\n URI: %s\n", HttpMessage->Data.Request->Url); } } break; case HttpBootHttpResponse: if (Data != NULL) { HttpMessage = (EFI_HTTP_MESSAGE *) Data; if (HttpMessage->Data.Response != NULL) { if (IsHttpRedirectStatusCode (HttpMessage->Data.Response->StatusCode)) { // // Server indicates the resource has been redirected to a different URL // according to the section 6.4 of RFC 7231 and the RFC 7538. // Display the redirect information on the screen. // HttpHeader = HttpFindHeader ( HttpMessage->HeaderCount, HttpMessage->Headers, HTTP_HEADER_LOCATION ); if (HttpHeader != NULL) { Print (L"\n HTTP ERROR: Resource Redirected.\n New Location: %a\n", HttpHeader->FieldValue); } break; } if (HttpMessage->Data.Response->StatusCode == HTTP_STATUS_404_NOT_FOUND) { DEBUG ((DEBUG_INFO, "OCR: HTTPS Boot File not found\n")); SendOcrPetEvent ( ASF_EVENT_OFFSET_ONE_CLICK_RECOVERY_ERROR, ASF_OCR_EVENT_DATA3_HTTPS_BOOT_FILE_NOT_FOUND, 0 ); } else if (HttpMessage->Data.Response->StatusCode == HTTP_STATUS_401_UNAUTHORIZED) { DEBUG ((DEBUG_INFO, "OCR: HTTPS Digest Auth failed\n")); SendOcrPetEvent ( ASF_EVENT_OFFSET_ONE_CLICK_RECOVERY_ERROR, ASF_OCR_EVENT_DATA3_HTTPS_DIGEST_AUTH_FAILED, 0 ); } } HttpHeader = HttpFindHeader ( HttpMessage->HeaderCount, HttpMessage->Headers, HTTP_HEADER_CONTENT_LENGTH ); if (HttpHeader != NULL) { mHttpFileSize = AsciiStrDecimalToUintn (HttpHeader->FieldValue); mHttpReceivedSize = 0; mHttpPercentage = 0; } } break; case HttpBootHttpEntityBody: if (DataLength != 0) { if (mHttpFileSize != 0) { // // We already know the file size, print in percentage format. // if (mHttpReceivedSize == 0) { Print (L" File Size: %lu Bytes\n", mHttpFileSize); } mHttpReceivedSize += DataLength; Percentage = (UINT32) DivU64x64Remainder (MultU64x32 (mHttpReceivedSize, 100), mHttpFileSize, NULL); if (mHttpPercentage != Percentage) { mHttpPercentage = Percentage; Print (L"\r Downloading...%d%%", Percentage); if (mHttpPercentage >= 100) { DEBUG ((DEBUG_INFO, "\nOCR: HTTPSBoot download is completed: %d/%d\n", mHttpReceivedSize, mHttpFileSize)); mHttpBootDownloadComplete = TRUE;; SendOcrPetEvent ( ASF_EVENT_OFFSET_ONE_CLICK_RECOVERY_PROGRESS, ASF_OCR_EVENT_DATA3_HTTPS_BOOT_DOWNLOAD, 0 ); } } } else { // // In some case we couldn't get the file size from the HTTP header, so we // just print the downloaded file size. // mHttpReceivedSize += DataLength; Print (L"\r Downloading...%lu Bytes", mHttpReceivedSize); } } break; default: break; } return EFI_SUCCESS; } /** Callback function that is invoked when HTTP event occurs. @param[in] This Pointer to the EDKII_HTTP_CALLBACK_PROTOCOL instance. @param[in] Event The event that occurs in the current state. @param[in] EventStatus The Status of Event, EFI_SUCCESS or other errors. **/ VOID EFIAPI HttpCallback ( IN EDKII_HTTP_CALLBACK_PROTOCOL *This, IN EDKII_HTTP_CALLBACK_EVENT Event, IN EFI_STATUS EventStatus ) { DEBUG ((DEBUG_INFO, "OCR: HttpCallback: %d - %r\n", Event, EventStatus)); switch (Event) { case HttpEventDns: if (EFI_ERROR (EventStatus)) { DEBUG ((DEBUG_INFO, "OCR: Name Resolution of URI failed\n")); SendOcrPetEvent (ASF_EVENT_OFFSET_ONE_CLICK_RECOVERY_ERROR, ASF_OCR_EVENT_DATA3_NAME_RESOLUTION_URI_FAILED, 0); } else { DEBUG ((DEBUG_INFO, "OCR: HTTPS URI Name Resolved\n")); SendOcrPetEvent (ASF_EVENT_OFFSET_ONE_CLICK_RECOVERY_PROGRESS, ASF_OCR_EVENT_DATA3_HTTPS_URI_NAME_RESOLVED, 0); } break; case HttpEventConnectTcp: break; case HttpEventTlsConnectSession: if (EFI_ERROR (EventStatus)) { DEBUG ((DEBUG_INFO, "OCR: HTTPS TLS Auth failed\n")); SendOcrPetEvent (ASF_EVENT_OFFSET_ONE_CLICK_RECOVERY_ERROR, ASF_OCR_EVENT_DATA3_HTTPS_TLS_AUTH_FAILED, 0); } break; case HttpEventInitSession: if (!EFI_ERROR (EventStatus)) { DEBUG ((DEBUG_INFO, "OCR: HTTPS Connected Successfully\n")); SendOcrPetEvent (ASF_EVENT_OFFSET_ONE_CLICK_RECOVERY_PROGRESS, ASF_OCR_EVENT_DATA3_HTTPS_CONNECTED_SUCCESS, 0); } else { DEBUG ((DEBUG_INFO, "OCR: Connect to URI failed\n")); SendOcrPetEvent (ASF_EVENT_OFFSET_ONE_CLICK_RECOVERY_ERROR, ASF_OCR_EVENT_DATA3_CONNECT_TO_URI_FAILED, 0); } break; } } /** Check whether Left and Right are the same without matching the specific device path data in IP device path and URI device path node. @retval TRUE Left and Right are the same. @retval FALSE Left and Right are the different. **/ BOOLEAN MatchHttpBootDevicePath ( IN EFI_DEVICE_PATH_PROTOCOL *Left, IN EFI_DEVICE_PATH_PROTOCOL *Right ) { if ((Left == NULL) || (Right == NULL)) { return FALSE; } for (; !IsDevicePathEnd (Left) && !IsDevicePathEnd (Right) ; Left = NextDevicePathNode (Left), Right = NextDevicePathNode (Right) ) { if (CompareMem (Left, Right, DevicePathNodeLength (Left)) != 0) { if ((DevicePathType (Left) != MESSAGING_DEVICE_PATH) || (DevicePathType (Right) != MESSAGING_DEVICE_PATH)) { return FALSE; } if (DevicePathSubType (Left) == MSG_DNS_DP) { Left = NextDevicePathNode (Left); } if (DevicePathSubType (Right) == MSG_DNS_DP) { Right = NextDevicePathNode (Right); } if (((DevicePathSubType (Left) != MSG_IPv4_DP) || (DevicePathSubType (Right) != MSG_IPv4_DP)) && ((DevicePathSubType (Left) != MSG_IPv6_DP) || (DevicePathSubType (Right) != MSG_IPv6_DP)) && ((DevicePathSubType (Left) != MSG_URI_DP) || (DevicePathSubType (Right) != MSG_URI_DP)) ) { return FALSE; } } } return (BOOLEAN) (IsDevicePathEnd (Left) && IsDevicePathEnd (Right)); } /** Install the network callback, include gEfiHttpBootCallbackProtocolGuid and gEdkiiHttpCallbackProtocolGuid @param[in] DevicePath Device Path. **/ VOID InstallNetworkCallback ( IN CHAR16 *DevicePath ) { EFI_STATUS Status; EFI_HANDLE *Handles; UINTN Index; UINTN HandleCount; EFI_DEVICE_PATH_PROTOCOL *FilePath; EFI_DEVICE_PATH_PROTOCOL *PathFromHandle; DEBUG ((DEBUG_INFO, "InstallNetworkCallback\n")); FilePath = ConvertTextToDevicePath (DevicePath); // // Use wide match algorithm to find the handle. // Status = gBS->LocateHandleBuffer ( ByProtocol, &gEfiLoadFileProtocolGuid, NULL, &HandleCount, &Handles ); if (EFI_ERROR (Status)) { return; } for (Index = 0; Index < HandleCount; Index++) { PathFromHandle = DevicePathFromHandle (Handles[Index]); if (PathFromHandle != NULL) { if (MatchHttpBootDevicePath (PathFromHandle, FilePath)) { mHttpBootCallbackHandle = Handles[Index]; break; } } } if (Handles != NULL) { FreePool (Handles); } // // Install a Http Boot callback // if (mHttpBootCallbackHandle != NULL) { DEBUG ((DEBUG_INFO, "Install gEfiHttpBootCallbackProtocolGuid\n")); Status = gBS->InstallProtocolInterface ( &mHttpBootCallbackHandle, &gEfiHttpBootCallbackProtocolGuid, EFI_NATIVE_INTERFACE, &mHttpBootCallback ); if (EFI_ERROR (Status)) { mHttpBootCallbackHandle = NULL; } // // Install a Http callback for http boot only. // if (mHttpCallbackHandle == NULL) { DEBUG ((DEBUG_INFO, "Install gEdkiiHttpCallbackProtocolGuid\n")); mHttpBootCallbackInvoked = FALSE; mHttpBootDownloadComplete = FALSE;; Status = gBS->InstallProtocolInterface ( &mHttpCallbackHandle, &gEdkiiHttpCallbackProtocolGuid, EFI_NATIVE_INTERFACE, &mHttpCallback ); if (EFI_ERROR (Status)) { mHttpCallbackHandle = NULL; } } } } /** Uninstall the network callback, include gEfiHttpBootCallbackProtocolGuid and gEdkiiHttpCallbackProtocolGuid **/ VOID UninstallNetworkCallback ( VOID ) { DEBUG ((DEBUG_INFO, "UninstallNetworkCallback\n")); if (mHttpBootCallbackHandle != NULL) { DEBUG ((DEBUG_INFO, "Uninstall gEfiHttpBootCallbackProtocolGuid\n")); gBS->UninstallProtocolInterface ( mHttpBootCallbackHandle, &gEfiHttpBootCallbackProtocolGuid, &mHttpBootCallback ); mHttpBootCallbackHandle = NULL; } if (mHttpCallbackHandle != NULL) { DEBUG ((DEBUG_INFO, "Uninstall gEdkiiHttpCallbackProtocolGuid\n")); gBS->UninstallProtocolInterface ( mHttpCallbackHandle, &gEdkiiHttpCallbackProtocolGuid, &mHttpCallback ); mHttpCallbackHandle = NULL; } } /** Report status code listener of FPDT. This is used to collect performance data for OsLoaderLoadImageStart and OsLoaderStartImageStart in FPDT. @param[in] CodeType Indicates the type of status code being reported. @param[in] Value Describes the current status of a hardware or software entity. This included information about the class and subclass that is used to classify the entity as well as an operation. @param[in] Instance The enumeration of a hardware or software entity within the system. Valid instance numbers start with 1. @param[in] CallerId This optional parameter may be used to identify the caller. This parameter allows the status code driver to apply different rules to different callers. @param[in] Data This optional parameter may be used to pass additional data. @retval EFI_SUCCESS Status code is what we expected. @retval EFI_UNSUPPORTED Status code not supported. **/ EFI_STATUS EFIAPI OcrStatusCodeListener ( IN EFI_STATUS_CODE_TYPE CodeType, IN EFI_STATUS_CODE_VALUE Value, IN UINT32 Instance, IN EFI_GUID *CallerId, IN EFI_STATUS_CODE_DATA *Data ) { EFI_RETURN_STATUS_EXTENDED_DATA *ExtendedData; UINT32 ErrorCode; // // Check whether status code is what we are interested in. // if (((CodeType & EFI_STATUS_CODE_TYPE_MASK) != EFI_ERROR_CODE) || (Value & (EFI_STATUS_CODE_CLASS_MASK | EFI_STATUS_CODE_SUBCLASS_MASK)) != EFI_SOFTWARE_DXE_BS_DRIVER) { return EFI_UNSUPPORTED; } ErrorCode = Value & EFI_STATUS_CODE_OPERATION_MASK; if ((ErrorCode == EFI_SW_DXE_BS_EC_BOOT_OPTION_LOAD_ERROR) || (ErrorCode == EFI_SW_DXE_BS_EC_BOOT_OPTION_FAILED)) { ExtendedData = (EFI_RETURN_STATUS_EXTENDED_DATA *)Data; DEBUG ((DEBUG_INFO, "OCR: CodeType %x, Value %x, Status %d - %r\n", CodeType, Value, ExtendedData->ReturnStatus, ExtendedData->ReturnStatus)); switch (ErrorCode) { case EFI_SW_DXE_BS_EC_BOOT_OPTION_LOAD_ERROR: switch (ExtendedData->ReturnStatus) { case EFI_NOT_FOUND: if ((AsfGetSpecialCommand () == ASF_INTEL_OEM_FORCE_PBA_BOOT_CMD)) { DEBUG ((DEBUG_INFO, "OCR: OEM App not found at local URI\n")); SendOcrPetEvent ( ASF_EVENT_OFFSET_ONE_CLICK_RECOVERY_ERROR, ASF_OCR_EVENT_DATA3_FILEPATH_NOT_FOUND, 0 ); } else if ((AsfGetSpecialCommand () == ASF_INTEL_OEM_FORCE_HTTPS_BOOT_CMD)) { if (mHttpBootCallbackInvoked == FALSE) { // // HTTP Boot callback is not invoked, it means there is no network connection available. // DEBUG ((DEBUG_INFO, "OCR: No network connection available\n")); SendOcrPetEvent ( ASF_EVENT_OFFSET_ONE_CLICK_RECOVERY_ERROR, ASF_OCR_EVENT_DATA3_NO_NETWORK_CONNECTION, 0 ); } else if (mHttpBootDownloadComplete == TRUE) { // // it is bad image because Http boot image is downloaded but can't find boot app. // DEBUG ((DEBUG_INFO, "OCR: Verified boot failed (bad image)\n")); SendOcrPetEvent ( ASF_EVENT_OFFSET_ONE_CLICK_RECOVERY_ERROR, ASF_OCR_EVENT_DATA3_VERIFIED_BOOT_FAILED, 0 ); } } break; case EFI_ACCESS_DENIED: case EFI_SECURITY_VIOLATION: DEBUG ((DEBUG_INFO, "OCR: Verified boot failed\n")); SendOcrPetEvent ( ASF_EVENT_OFFSET_ONE_CLICK_RECOVERY_ERROR, ASF_OCR_EVENT_DATA3_VERIFIED_BOOT_FAILED, 0 ); break; } break; case EFI_SW_DXE_BS_EC_BOOT_OPTION_FAILED: if (ExtendedData->ReturnStatus == EFI_SECURITY_VIOLATION) { DEBUG ((DEBUG_INFO, "OCR: Verified boot failed(boot failure)\n")); SendOcrPetEvent ( ASF_EVENT_OFFSET_ONE_CLICK_RECOVERY_ERROR, ASF_OCR_EVENT_DATA3_VERIFIED_BOOT_FAILED, 0 ); } break; } } return EFI_SUCCESS; } /** Is Intel One Click Recovery supported @retval TRUE Intel One Click Recovery is supported @retval FALSE Intel One Click Recovery is not supported **/ BOOLEAN IsOcrSupported ( VOID ) { ME_BIOS_PAYLOAD_HOB *MbpHob; MbpHob = GetFirstGuidHob (&gMeBiosPayloadHobGuid); if (MbpHob == NULL) { return FALSE; } // Check that ME is corporate and supports AMT if (MbpHob->MeBiosPayload.FwPlatType.RuleData.Fields.IntelMeFwImageType != IntelMeCorporateFw || MbpHob->MeBiosPayload.FwFeaturesState.FwFeatures.Fields.Amt != 1 || MbpHob->MeBiosPayload.FwCapsSku.FwCapabilities.Fields.Amt != 1 ) { return FALSE; } // Check that BIOS supports one of boot options: HTTPS, PBA, Win Re if (mOcrCap.Bits.OcrBootHttps == ONE_CLICK_RECOVERY_HTTPS_BOOT_CAPABLE || mOcrCap.Bits.OcrBootPba == ONE_CLICK_RECOVERY_PBA_BOOT_CAPABLE || mOcrCap.Bits.OcrBootWinRe == ONE_CLICK_RECOVERY_WIN_RE_BOOT_CAPABLE) { return TRUE; } else { return FALSE; } } /** Get OCR Boot Setting EFI Variable @retval OCR_BOOT_SETTINGS OCR boot Setting **/ OCR_BOOT_SETTINGS GetOcrBootSettings ( VOID ) { EFI_STATUS Status; UINTN VarSize; OCR_BOOT_SETTINGS OcrBootSettings; VarSize = sizeof (OCR_BOOT_SETTINGS); Status = gRT->GetVariable( OCR_BOOT_SETTINGS_NAME, &mOcrBootSettingsGuid, NULL, &VarSize, &OcrBootSettings ); if (EFI_ERROR (Status)) { OcrBootSettings.BootOptionExists = BOOT_OPTION_EXISTS_NONE; OcrBootSettings.RestoreSecureBootSetting = RESTORE_SECURE_BOOT_NONE; } return OcrBootSettings; } /** Creates OCR Description Title @param[in] Description Title to Append to boot option @param[out] OcrDescription OCR Description @param[in] MaxOcrDescriptionSize Max OCR Description Size @retval EFI_SUCCESS Created OCR Description @retval EFI_INVALID_PARAMETER Pointers are null @retval EFI_BUFFER_TOO_SMALL Description will be larger than max size **/ EFI_STATUS CreateOcrBootOptionDescription ( IN CHAR16* Description, OUT CHAR16* OcrDescription, IN UINT32 MaxOcrDescriptionSize ) { EFI_STATUS Status; UINTN BootOptionSize; if (Description == NULL || OcrDescription == NULL) { return EFI_INVALID_PARAMETER; } BootOptionSize = StrSize (Description) + StrSize (mOcrString) - 1; if (BootOptionSize > MaxOcrDescriptionSize) { return EFI_BUFFER_TOO_SMALL; } Status = StrCpyS (OcrDescription, BootOptionSize, mOcrString); if (!EFI_ERROR (Status)) { Status = StrCatS (OcrDescription, BootOptionSize, Description); } return Status; } /** Frees OCR Boot Option **/ VOID FreeOcrBootOption ( VOID ) { if (mOcrBootOption != NULL) { if (mOcrBootOption->OptionalData != NULL) { FreePool (mOcrBootOption->OptionalData); } FreePool (mOcrBootOption); mOcrBootOption = NULL; } } /** Cancels OCR Boot Option by freeing memory, report bios status failure and perform warm reset if secure boot is disabled **/ VOID CancelOcrBootOption ( VOID ) { OCR_BOOT_SETTINGS OcrBootSettings; EFI_STATUS Status; FreeOcrBootOption (); Status = ReportBiosStatus (AsfRbsGeneralFailure); if (EFI_ERROR (Status)) { DEBUG ((DEBUG_INFO, "OCR failed to report BIOS Status\n")); } OcrBootSettings = GetOcrBootSettings (); // Reset System if secure boot was disabled for OCR HTTPS Boot but current boot is not OCR. if (OcrBootSettings.RestoreSecureBootSetting == RESTORE_SECURE_BOOT_ENABLED) { DEBUG ((DEBUG_INFO, "Secure Boot disabled for OCR HTTPS Boot but not booting to OCR HTTPS - Warm Reset!\n")); gRT->ResetSystem (EfiResetWarm, EFI_SUCCESS, 0, NULL); } } /** Set UEFI Boot Options State @param[in] MeSetup ME Setup Configuration @retval EFI_SUCCESS Set AMT UEFI boot options states **/ EFI_STATUS SetUefiBootOptionsState ( IN ME_SETUP MeSetup ) { EFI_STATUS Status; AMT_BOOT_CONTROL UserAmtBootControl; AMT_BOOT_CONTROL CurrentAmtBootControl; Status = AsfGetUefiBootOptionsState (&CurrentAmtBootControl); if (EFI_ERROR (Status)) { return Status; } UserAmtBootControl.Uint32 = CurrentAmtBootControl.Uint32; UserAmtBootControl.Bits.AmtTrigBootToHttps = (mOcrCap.Bits.OcrBootHttps == ONE_CLICK_RECOVERY_HTTPS_BOOT_CAPABLE) ? MeSetup.OcrBootHttps : 0; UserAmtBootControl.Bits.AmtTrigBootToPba = (mOcrCap.Bits.OcrBootPba == ONE_CLICK_RECOVERY_PBA_BOOT_CAPABLE) ? MeSetup.OcrBootPba : 0; UserAmtBootControl.Bits.AmtTrigBootToWinRe = (mOcrCap.Bits.OcrBootWinRe == ONE_CLICK_RECOVERY_WIN_RE_BOOT_CAPABLE) ? MeSetup.OcrBootWinRe : 0; UserAmtBootControl.Bits.AmtAllowedToDisSecureBoot = (mOcrCap.Bits.OcrAmtDisSecBoot == ONE_CLICK_RECOVERY_DIS_SEC_BOOT_CAPABLE) ? MeSetup.OcrAmtDisSecBoot : 0; if (CurrentAmtBootControl.Uint32 != UserAmtBootControl.Uint32) { Status = AsfSetUefiBootOptionsState (UserAmtBootControl); } DEBUG ((DEBUG_INFO, "OcrBootHttps: %d\n", UserAmtBootControl.Bits.AmtTrigBootToHttps)); DEBUG ((DEBUG_INFO, "OcrBootPba: %d\n", UserAmtBootControl.Bits.AmtTrigBootToPba)); DEBUG ((DEBUG_INFO, "OcrBootWinRe: %d\n", UserAmtBootControl.Bits.AmtTrigBootToWinRe)); DEBUG ((DEBUG_INFO, "OcrAmtDisSecBoot: %d\n", UserAmtBootControl.Bits.AmtAllowedToDisSecureBoot)); return Status; } // List of GUIDs for registering Certificates STATIC EFI_GUID mOcrTlsAuthConfigGuid[MAX_NUM_ROOT_CA_CERTIFICATE] = { { 0xf575f8b1, 0xc4a8, 0x4571, { 0xba, 0xb0, 0x13, 0x5d, 0xbb, 0x09, 0xdb, 0xff }}, { 0x352791b0, 0x2931, 0x4e4e, { 0x91, 0xf8, 0x0b, 0xb4, 0xda, 0x6e, 0xc7, 0x6a }}, { 0xf021cb20, 0xfe1b, 0x4fec, { 0x8a, 0x2e, 0x73, 0x77, 0x4d, 0x18, 0x0c, 0x38 }}, { 0xb801e82a, 0xb794, 0x4f56, { 0xbc, 0x15, 0xb0, 0x78, 0x12, 0xbc, 0x57, 0x32 }} }; /** Get All Root CA Certificates @retval EFI_SUCCESS successful sync CA Certicates **/ EFI_STATUS GetRootCaCertificates ( VOID ) { EFI_STATUS Status; UINT32 Index; ROOT_CA_CERTIFICATE Cert; // Get all Certificates and enroll them for (Index = 0; Index < MAX_NUM_ROOT_CA_CERTIFICATE; Index++) { Status = AsfGetRootCaCertificate (Index, &Cert); if (!EFI_ERROR (Status)) { DEBUG ((DEBUG_ERROR, "Root CA Certificate\n Index: %d\n CertSize: %d\n", Index, Cert.CertSize)); Status = EnrollOcrX509Certificate (Cert.Cert, Cert.CertSize, &mOcrTlsAuthConfigGuid[Index]); } if (EFI_ERROR (Status) || Cert.LastCert) { break; } } return Status; } /** Adds OCR Boot Option to EFI Boot Manager @param[in] BootOption Boot Option @retval EFI_SUCCESS Added OCR Boot Option @retval EFI_INVALID OCR Boot Option is NULL @retval EFI_NOT_FOUND OCR Boot Device Path not found @retval EFI_UNSUPPORTED OCR Boot Option is not supported **/ EFI_STATUS AddOcrBootOption ( IN OCR_BOOT_OPTION *BootOption ) { EFI_STATUS Status; EFI_BOOT_MANAGER_LOAD_OPTION SetupOption; EFI_DEVICE_PATH_PROTOCOL *DevicePath; if (BootOption == NULL) { return EFI_INVALID_PARAMETER; } DevicePath = ConvertTextToDevicePath (BootOption->DevicePath); if (DevicePath == NULL) { return EFI_NOT_FOUND; } Status = EfiBootManagerInitializeLoadOption ( &SetupOption, LoadOptionNumberUnassigned, LoadOptionTypeBoot, LOAD_OPTION_ACTIVE, BootOption->Description, DevicePath, BootOption->OptionalData, BootOption->OptionalDataSize ); if (!EFI_ERROR (Status)) { // Place as default boot option to load Status = EfiBootManagerAddLoadOptionVariable (&SetupOption, 0); DEBUG ((DEBUG_INFO, "OCR EfiBootManagerAddLoadOptionVariable: %x\n", Status)); } return Status; } //[-start-211215-IB09480180-add]// /** Internal function to uninstall all of specific protocols in all of handles. @param[in] Protocol Provides the protocol to remove. @retval EFI_SUCCESS Uninstall all of protcols successfully. @return Other Any other error occurred while uninstalling protocols. **/ STATIC EFI_STATUS UninstallSpecificProtocols ( IN EFI_GUID *Protocol ) { EFI_STATUS Status; UINTN NoHandles; EFI_HANDLE *Buffer; UINTN Index; Status = gBS->LocateHandleBuffer ( ByProtocol, Protocol, NULL, &NoHandles, &Buffer ); if (!EFI_ERROR (Status)) { for (Index = 0; Index < NoHandles; Index++) { Status = gBS->UninstallProtocolInterface ( Buffer[Index], Protocol, NULL ); if (EFI_ERROR (Status)) { FreePool (Buffer); return Status; } } FreePool (Buffer); } return EFI_SUCCESS; } /** Disable BootOrder variable hook mechanism. @retval EFI_SUCCESS Disable BootOrder variable hook mechanism successfully. @return Other Disable BootOrder variable hook mechanism failed. **/ EFI_STATUS BdsLibDisableBootOrderHook ( VOID ) { EFI_STATUS Status; EFI_HANDLE Handle; VOID *Interface; if (!FeaturePcdGet (PcdAutoCreateDummyBootOption)) { return EFI_SUCCESS; } Status = UninstallSpecificProtocols (&gBootOrderHookEnableGuid); if (EFI_ERROR (Status)) { return Status; } Status = gBS->LocateProtocol ( &gBootOrderHookDisableGuid, NULL, (VOID **)&Interface ); if (!EFI_ERROR (Status)) { return EFI_SUCCESS; } Handle = NULL; return gBS->InstallProtocolInterface ( &Handle, &gBootOrderHookDisableGuid, EFI_NATIVE_INTERFACE, NULL ); } /** Enable BootOrder variable hook mechanism. @retval EFI_SUCCESS Enable BootOrder variable hook mechanism successfully. @return Other Enable BootOrder variable hook mechanism failed. **/ EFI_STATUS BdsLibEnableBootOrderHook ( VOID ) { EFI_STATUS Status; EFI_HANDLE Handle; VOID *Interface; if (!FeaturePcdGet (PcdAutoCreateDummyBootOption)) { return EFI_SUCCESS; } Status = UninstallSpecificProtocols (&gBootOrderHookDisableGuid); if (EFI_ERROR (Status)) { return Status; } Status = gBS->LocateProtocol ( &gBootOrderHookEnableGuid, NULL, (VOID **)&Interface ); if (!EFI_ERROR (Status)) { return EFI_SUCCESS; } Handle = NULL; return gBS->InstallProtocolInterface ( &Handle, &gBootOrderHookEnableGuid, EFI_NATIVE_INTERFACE, NULL ); } /** Function uses to check BootOrder variable hook mechanism is whether enabled. @retval TRUE BootOrder variable hook mechanism is enabled. @retval FALSE BootOrder variable hook mechanism is disabled **/ BOOLEAN BdsLibIsBootOrderHookEnabled ( VOID ) { EFI_STATUS Status; VOID *BootOrderHook; Status = gBS->LocateProtocol ( &gBootOrderHookEnableGuid, NULL, (VOID **)&BootOrderHook ); if (!EFI_ERROR (Status)) { return TRUE; } return FALSE; } //[-end-211215-IB09480180-add]// /** Delete One Click Recovery Boot Options if they exist **/ VOID DeleteOcrBootOption ( VOID ) { EFI_BOOT_MANAGER_LOAD_OPTION *BootOptions; UINTN BootOptionCount; UINTN Index; EFI_STATUS Status; OCR_BOOT_SETTINGS OcrBootSettings; //[-start-211215-IB09480180-add]// BOOLEAN IsBootOrderHookEnabled; //[-end-211215-IB09480180-add]// OcrBootSettings = GetOcrBootSettings (); if (OcrBootSettings.BootOptionExists != BOOT_OPTION_EXISTS_NONE) { //[-start-211215-IB09480180-add]// IsBootOrderHookEnabled = BdsLibIsBootOrderHookEnabled (); if (!IsBootOrderHookEnabled) { BdsLibEnableBootOrderHook (); } //[-end-211215-IB09480180-add]// BootOptions = EfiBootManagerGetLoadOptions (&BootOptionCount, LoadOptionTypeBoot); if (BootOptions != NULL) { // Remove OCR boot options from load options for (Index = 0; Index < BootOptionCount; Index++) { if ((StrnCmp(BootOptions[Index].Description, mOcrString, StrLen(mOcrString))) == 0) { EfiBootManagerDeleteLoadOptionVariable (BootOptions[Index].OptionNumber, LoadOptionTypeBoot); } } DEBUG((DEBUG_INFO, "Remove OCR Boot options\n")); EfiBootManagerFreeLoadOptions (BootOptions, BootOptionCount); } // remove all previous certificates for (Index = 0; Index < MAX_NUM_ROOT_CA_CERTIFICATE; Index++) { DeleteOcrX509Certificate (&mOcrTlsAuthConfigGuid[Index]); } // // Update OcrBootSettings variable with Boot Option Exists to None // OcrBootSettings.BootOptionExists = BOOT_OPTION_EXISTS_NONE; Status = gRT->SetVariable ( OCR_BOOT_SETTINGS_NAME, &mOcrBootSettingsGuid, EFI_VARIABLE_NON_VOLATILE | EFI_VARIABLE_BOOTSERVICE_ACCESS, sizeof (OCR_BOOT_SETTINGS), &OcrBootSettings ); ASSERT_EFI_ERROR (Status); //[-start-211215-IB09480180-add]// if (!IsBootOrderHookEnabled) { BdsLibDisableBootOrderHook (); } //[-end-211215-IB09480180-add]// } } /** Is the current Boot Option the One Click Recovery Boot Option @retval TRUE Current Boot Option is One Click Recovery Boot Option @retval False Current Boot Option is not One Click Recovery Boot Option **/ BOOLEAN IsCurrentBootOcrBootOption ( VOID ) { EFI_STATUS Status; BOOLEAN IsOcrBootOption; UINTN VarSize; UINT16 BootCurrent; CHAR16 BootXXXX[16]; EFI_BOOT_MANAGER_LOAD_OPTION CurrentBootOption; CHAR16 *CurrentDevicePath; IsOcrBootOption = FALSE; VarSize = sizeof (UINT16); Status = gRT->GetVariable ( L"BootCurrent", &gEfiGlobalVariableGuid, NULL, &VarSize, &BootCurrent ); if (!EFI_ERROR (Status)) { UnicodeSPrint (BootXXXX, sizeof(BootXXXX), L"Boot%04X", BootCurrent); Status = EfiBootManagerVariableToLoadOption (BootXXXX, &CurrentBootOption); if (!EFI_ERROR (Status)) { CurrentDevicePath = ConvertDevicePathToText (CurrentBootOption.FilePath, TRUE, TRUE); if (CurrentDevicePath != NULL) { DEBUG ((DEBUG_INFO, "Current Boot description: %s\nCurrent Boot DevicePath: %s\n",CurrentBootOption.Description, CurrentBootOption.FilePath)); // Compare Current Boot option and OCR Boot option if ((StrnCmp (mOcrBootOption->Description, CurrentBootOption.Description, MAX_UEFI_BOOT_OPTION_DESC_LENGTH) == 0) && (StrnCmp (mOcrBootOption->DevicePath, CurrentDevicePath, MAX_UEFI_BOOT_OPTION_DEV_PATH_LENGTH) == 0) && (CompareMem(mOcrBootOption->OptionalData, CurrentBootOption.OptionalData, mOcrBootOption->OptionalDataSize) == 0) && (mOcrBootOption->OptionalDataSize == CurrentBootOption.OptionalDataSize)) { IsOcrBootOption = TRUE; } } EfiBootManagerFreeLoadOption (&CurrentBootOption); } } return IsOcrBootOption; } /** During Ready To Boot Event, Removes One Click Recovery from load options and sends status to AMT @param[in] Event Event whose notification function is being invoked @param[in] Context Pointer to the notification function's context **/ VOID EFIAPI OneClickRecoveryReadyToBootService ( IN EFI_EVENT Event, IN VOID *Context ) { EFI_STATUS Status; BOOLEAN IsOcrBootOption; OCR_BOOT_SETTINGS OcrBootSettings; UINT32 AsfBiosStatus; IsOcrBootOption = IsCurrentBootOcrBootOption (); if (IsOcrBootOption) { DEBUG ((DEBUG_INFO, "Booting OCR Boot Option\n")); AsfBiosStatus = AsfRbsSuccess; if (AsfIsFwProgressEnabled ()) { if (mOcrBootOption != NULL) { InstallNetworkCallback (mOcrBootOption->DevicePath); } // // Get Report Status Code Handler Protocol. // Status = gBS->LocateProtocol (&gEfiRscHandlerProtocolGuid, NULL, (VOID **) &mRscHandlerProtocol); ASSERT_EFI_ERROR (Status); // // Register report status code listener for OS Loader load and start. // DEBUG ((DEBUG_INFO, "Register report status code listener\n")); Status = mRscHandlerProtocol->Register (OcrStatusCodeListener, TPL_HIGH_LEVEL); ASSERT_EFI_ERROR (Status); } } else { AsfBiosStatus = AsfRbsGeneralFailure; if (AsfIsFwProgressEnabled ()) { UninstallNetworkCallback (); } // // Unregister report status code listener. // if (mRscHandlerProtocol != NULL) { DEBUG ((DEBUG_INFO, "Unregister report status code listener\n")); mRscHandlerProtocol->Unregister (OcrStatusCodeListener); mRscHandlerProtocol = NULL; } } // report Bios Status to AMT based on if we're going to boot OCR boot option requested Status = ReportBiosStatus (AsfBiosStatus); if (EFI_ERROR (Status)) { DEBUG ((DEBUG_INFO, "OCR failed to report BIOS Status\n")); } // report PET if were booting OCR Boot Optiona and PET are enabled if (AsfIsFwProgressEnabled () && IsOcrBootOption) { Status = SendOcrPetEvent (ASF_EVENT_OFFSET_ONE_CLICK_RECOVERY_PROGRESS, ASF_OCR_EVENT_DATA3_ATTEMPT_TO_BOOT, 0); } if (!IsOcrBootOption) { OcrBootSettings = GetOcrBootSettings (); // Reset System if secure boot was disable for OCR HTTPS Boot but current boot is not OCR. if (OcrBootSettings.RestoreSecureBootSetting == RESTORE_SECURE_BOOT_ENABLED) { DEBUG ((DEBUG_INFO, "Secure Boot disabled for OCR HTTPS Boot but not booting to OCR HTTPS - Warm Reset!\n")); gRT->ResetSystem (EfiResetWarm, EFI_SUCCESS, 0, NULL); } } return; } /** During Exit Boot Event, sends AMT PET on whether OCR Boot Option Booted @param Event Event whose notification function is being invoked @param Context Pointer to the notification function's context **/ VOID EFIAPI OneClickRecoveryExitBootService ( IN EFI_EVENT Event, IN VOID *Context ) { // report PET if were booting OCR Boot Optiona and PET are enabled if (AsfIsFwProgressEnabled () && IsCurrentBootOcrBootOption ()) { DEBUG ((DEBUG_INFO, "OCR Boot Option Booted\n")); UninstallNetworkCallback (); // // Unregister report status code listener. // if (mRscHandlerProtocol != NULL) { DEBUG ((DEBUG_INFO, "Unregister report status code listener\n")); mRscHandlerProtocol->Unregister (OcrStatusCodeListener); mRscHandlerProtocol = NULL; } SendOcrPetEvent (ASF_EVENT_OFFSET_ONE_CLICK_RECOVERY_PROGRESS, ASF_OCR_EVENT_DATA3_EXIT_BOOT_SERVICES, 0); } DeleteOcrBootOption (); gBS->CloseEvent (Event); return; } /** Registers a callback on Exit Boot Service event that will remove One Click Recovery from load options @retval EFI_SUCCESS Callback was successfully registered @retval Others Callback was not registered **/ EFI_STATUS EFIAPI RegisterOneClickRecoveryCallback ( VOID ) { EFI_STATUS Status; EFI_EVENT ReadyToBootServiceEvent; EFI_EVENT ExitBootServiceEvent; // // Register Ready to Boot Event for One Click Recovery // Status = EfiCreateEventReadyToBootEx ( TPL_CALLBACK, OneClickRecoveryReadyToBootService, NULL, &ReadyToBootServiceEvent ); ASSERT_EFI_ERROR (Status); // // Register Exit Boot Services Event for One Click Recovery // Status = gBS->CreateEventEx ( EVT_NOTIFY_SIGNAL, TPL_NOTIFY, OneClickRecoveryExitBootService, NULL, &gEfiEventExitBootServicesGuid, &ExitBootServiceEvent ); ASSERT_EFI_ERROR (Status); return Status; } // List of WinRe Boot option supported Parameter types STATIC UINT32 mWinReBootOptionParamSupport[] = { EfiBootOptionalDataParamType }; // List of PBA Boot option supported Parameter types STATIC UINT32 mPbaBootOptionParamSupport[] = { EfiFileDeviceParamType, BootImageHashSha256ParamType, BootImageHashSha384ParamType, BootImageHashSha512ParamType, EfiBootOptionalDataParamType }; // List of Https Boot option supported Parameter types STATIC UINT32 mHttpsBootOptionParamSupport[] = { EfiNetworkDevicePathParamType, HttpsCertSyncRootCaParamType, HttpsCertServerNameParamType, HttpsServerNameVerifyMethodParamType, HttpsServerCertHashSha256ParamType, HttpsServerCertHashSha384ParamType, HttpsServerCertHashSha512ParamType, HttpsRequestTimeOutParamType, HttpsDigestUserNameParamType, HttpsDigestPasswordParamType }; /** Check if Parameter is supported by OCR Boot Option Type @param[in] BootType OCR Boot Option Type @param[in] ParamType OCR Parameter Type @retval TRUE Parameter is supported @retval FALSE Parameter isn't supported **/ BOOLEAN IsParamSupported ( IN UINT32 BootType, IN UINT32 ParamType ) { UINT32 *SupportedBootParam; UINT32 SupportedBootParamCount; UINT32 Index; switch (BootType) { case WinRe: SupportedBootParam = mWinReBootOptionParamSupport; SupportedBootParamCount = sizeof (mWinReBootOptionParamSupport) / sizeof (UINT32); break; case Pba: SupportedBootParam = mPbaBootOptionParamSupport; SupportedBootParamCount = sizeof (mPbaBootOptionParamSupport) / sizeof (UINT32); case Https: SupportedBootParam = mHttpsBootOptionParamSupport; SupportedBootParamCount = sizeof (mHttpsBootOptionParamSupport) / sizeof (UINT32); break; default: return FALSE; } for (Index = 0; Index < SupportedBootParamCount; Index++) { if (SupportedBootParam[Index] == ParamType) { return TRUE; } } return FALSE; } /** Setups up Http Device Path @param[in] OcrParamTlv OCR Parameter TLV @param[in,out] BootOption OCR Boot Option @retval EFI_SUCCESS Successful consume OCR Param @retval EFI_INVALID_PARAMETER Pointer is NULL or Length is too long @retval EFI_UNSUPPORTED Url is not https **/ EFI_STATUS NetworkDevicePathParam ( IN OCR_PARAMETER_TLV *OcrParamTlv, IN OUT OCR_BOOT_OPTION *BootOption ) { EFI_STATUS Status; CHAR16 *DevicePath; EFI_DEVICE_PATH_PROTOCOL *HttpDevice; UINTN Length; CHAR16 UriPath[MAX_UEFI_BOOT_OPTION_DEV_PATH_LENGTH]; UINTN UriLength; if ((OcrParamTlv == NULL) || (BootOption == NULL) || (OcrParamTlv->Header.Length > MAX_UEFI_BOOT_OPTION_DEV_PATH_LENGTH)) { return EFI_INVALID_PARAMETER; } HttpDevice = AllocateZeroPool (sizeof (EFI_DEVICE_PATH_PROTOCOL)); if (HttpDevice == NULL) { return EFI_OUT_OF_RESOURCES; } Status = SearchHttpDevicePath (&HttpDevice); if (!EFI_ERROR (Status)) { DevicePath = ConvertDevicePathToText (HttpDevice, TRUE, TRUE); if (DevicePath == NULL) { return EFI_NOT_FOUND; } if (!IsHttpsUrl ((CHAR8*)OcrParamTlv->Value, OcrParamTlv->Header.Length)) { return EFI_UNSUPPORTED; } Length = StrnLenS (DevicePath, MAX_UEFI_BOOT_OPTION_DEV_PATH_LENGTH) + StrnLenS (L"/Uri()", MAX_UEFI_BOOT_OPTION_DEV_PATH_LENGTH) + OcrParamTlv->Header.Length; if (Length > MAX_UEFI_BOOT_OPTION_DEV_PATH_LENGTH) { return EFI_INVALID_PARAMETER; } AsciiStrnToUnicodeStrS ( (CHAR8*)OcrParamTlv->Value, OcrParamTlv->Header.Length, UriPath, MAX_UEFI_BOOT_OPTION_DEV_PATH_LENGTH, &UriLength ); UnicodeSPrint ( BootOption->DevicePath, MAX_UEFI_BOOT_OPTION_DEV_PATH_LENGTH*sizeof(CHAR16), L"%s/Uri(%s)", DevicePath, UriPath ); } return Status; } /** Setups up File Device Path @param[in] OcrParamTlv OCR Parameter TLV @param[in,out] BootOption OCR Boot Option @retval EFI_SUCCESS Successful consume OCR Param @retval EFI_INVALID_PARAMETER Pointer are NULL or Length is too long **/ EFI_STATUS FileDeviceParam ( IN OCR_PARAMETER_TLV *OcrParamTlv, IN OUT OCR_BOOT_OPTION *BootOption ) { UINTN Length; if ((OcrParamTlv == NULL) || (BootOption == NULL) || (OcrParamTlv->Header.Length > MAX_UEFI_BOOT_OPTION_DEV_PATH_LENGTH)) { return EFI_INVALID_PARAMETER; } AsciiStrnToUnicodeStrS ( (CHAR8*)OcrParamTlv->Value, OcrParamTlv->Header.Length, BootOption->DevicePath, MAX_UEFI_BOOT_OPTION_DEV_PATH_LENGTH, &Length ); return EFI_SUCCESS; } /** Setups up Optional Data Parameter for Boot Option @param[in] OcrParamTlv OCR Parameter TLV @param[in,out] BootOption OCR Boot Option @retval EFI_SUCCESS Successful consume OCR Param @retval EFI_INVALID_PARAMETER Pointer are NULL or Length is too long @retval EFI_OUT_OF_RESOURCES Out of resources **/ EFI_STATUS OptionalDataParam ( IN OCR_PARAMETER_TLV *OcrParamTlv, IN OUT OCR_BOOT_OPTION *BootOption ) { UINT32 BufferSize; UINT8 *Buffer; if ((OcrParamTlv == NULL) || (BootOption == NULL) || (OcrParamTlv->Header.Length > MAX_UEFI_OPTIONAL_DATA) || (BootOption->OptionalData != NULL && BootOption->OptionalDataSize == 0) || (BootOption->OptionalData == NULL && BootOption->OptionalDataSize != 0)) { return EFI_INVALID_PARAMETER; } if (BootOption->OptionalData == NULL) { BufferSize = OcrParamTlv->Header.Length; Buffer = AllocatePool (BufferSize); } else { BufferSize = BootOption->OptionalDataSize + OcrParamTlv->Header.Length; Buffer = ReallocatePool (BootOption->OptionalDataSize, BufferSize, BootOption->OptionalData); } if (Buffer == NULL) { return EFI_OUT_OF_RESOURCES; } BootOption->OptionalData = Buffer; CopyMem ((BootOption->OptionalData + BootOption->OptionalDataSize), OcrParamTlv->Value, OcrParamTlv->Header.Length); BootOption->OptionalDataSize = BufferSize; return EFI_SUCCESS; } /** Check if Boot Option was requested and add it. @param[in,out] BootOption OCR Boot Option @retval EFI_SUCCESS Successfully consumed OCR Parameters @retval EFI_INVALID_PARAMETER parameter pointer is null **/ EFI_STATUS SetupOcrBootOptionParams ( IN OUT OCR_BOOT_OPTION *BootOption ) { EFI_STATUS Status; OCR_PARAMETER_TLV *OcrParamTlv; UINT32 Index; Status = EFI_SUCCESS; if (BootOption == NULL) { return EFI_INVALID_PARAMETER; } OcrParamTlv = (OCR_PARAMETER_TLV*)mAmtUefiBootOption.ParametersArray; for (Index = 0; Index < mAmtUefiBootOption.NumberOfParams; Index++) { DEBUG ((DEBUG_INFO, "Index:%d ParamTypeId: %d\n length:%d\n", Index, OcrParamTlv->Header.ParamType.ParamTypeId, OcrParamTlv->Header.Length)); if (IsParamSupported (mAmtUefiBootOption.UefiBootOptionType, OcrParamTlv->Header.ParamType.ParamTypeId)) { switch (OcrParamTlv->Header.ParamType.ParamTypeId) { case EfiNetworkDevicePathParamType: Status = NetworkDevicePathParam (OcrParamTlv, BootOption); if (EFI_ERROR (Status)) { return Status; } break; case EfiFileDeviceParamType: Status = FileDeviceParam (OcrParamTlv, BootOption); break; case EfiBootOptionalDataParamType: Status = OptionalDataParam (OcrParamTlv, BootOption); break; case HttpsCertSyncRootCaParamType: if (*OcrParamTlv->Value) { Status = GetRootCaCertificates (); } break; case HttpsRequestTimeOutParamType: Status = SetHttpTimeout (OcrParamTlv); break; case EfiDevicePathLenParamType: case BootImageHashSha256ParamType: case BootImageHashSha384ParamType: case BootImageHashSha512ParamType: case HttpsCertServerNameParamType: case HttpsServerNameVerifyMethodParamType: case HttpsServerCertHashSha256ParamType: case HttpsServerCertHashSha384ParamType: case HttpsServerCertHashSha512ParamType: case HttpsDigestUserNameParamType: case HttpsDigestPasswordParamType: default: break; } } // Increment to next OcrParamTlv OcrParamTlv = (OCR_PARAMETER_TLV*)(((UINT8 *)OcrParamTlv) + sizeof (OCR_PARAMETER_TLV_HEADER) + OcrParamTlv->Header.Length); } return Status; } /** Setup OCR Boot Option if requested from AMT @param[in] ME_SETUP ME Setup Configuration @retval EFI_SUCCESS OCR Boot Option is setup. @retval EFI_NOT_FOUND OCR was not requested. @retval EFI_OUT_OF_RESOURCES Ran out of resources @retval EFI_ABORTED Boot Option requested is not valid @retval EFI_SECURITY_VIOLATION Secure Boot needs to be enable for OCR WinRe and PBA **/ EFI_STATUS OcrBootOptionRequest ( IN ME_SETUP MeSetup ) { EFI_STATUS Status; CHAR16* Description; CHAR16* WinReOptionalData; UINT8 SecureBootState; UINTN VarSize; //[-start-211111-IB09480171-remove]// // UINT32 VarAttributes; //[-end-211111-IB09480171-remove]// OCR_BOOT_SETTINGS OcrBootSettings; AMT_BOOT_CONTROL LoadOptionType; UINT16 SpecialCommand; WinReOptionalData = L"/RecoveryBCD"; LoadOptionType.Uint32 = 0; SpecialCommand = AsfGetSpecialCommand (); if (SpecialCommand != ASF_INTEL_OEM_FORCE_HTTPS_BOOT_CMD && SpecialCommand != ASF_INTEL_OEM_FORCE_PBA_BOOT_CMD) { DEBUG ((DEBUG_INFO, "OCR was not requested.\n")); return EFI_NOT_FOUND; } // report in progress Bios Status to AMT Status = ReportBiosStatus (AsfRbsInProgress); mOcrBootOption = AllocateZeroPool (sizeof (OCR_BOOT_OPTION)); if (mOcrBootOption == NULL) { CancelOcrBootOption (); return EFI_OUT_OF_RESOURCES; } // Check that system supports requested OCR boot option if (SpecialCommand == ASF_INTEL_OEM_FORCE_HTTPS_BOOT_CMD && mAmtUefiBootOption.UefiBootOptionType == Https && MeSetup.OcrBootHttps == 1 && mOcrCap.Bits.OcrBootHttps == ONE_CLICK_RECOVERY_HTTPS_BOOT_CAPABLE) { // OCR HTTPS Boot was requested Description = L" HTTPS"; LoadOptionType.Bits.AmtTrigBootToHttps = 1; } else if (SpecialCommand == ASF_INTEL_OEM_FORCE_PBA_BOOT_CMD && mAmtUefiBootOption.UefiBootOptionType == Pba && MeSetup.OcrBootPba == 1 && mOcrCap.Bits.OcrBootPba == ONE_CLICK_RECOVERY_PBA_BOOT_CAPABLE) { // OCR PBA Boot was requested Description = L" PBA"; LoadOptionType.Bits.AmtTrigBootToPba = 1; } else if (SpecialCommand == ASF_INTEL_OEM_FORCE_PBA_BOOT_CMD && mAmtUefiBootOption.UefiBootOptionType == WinRe && MeSetup.OcrBootWinRe == 1 && mOcrCap.Bits.OcrBootWinRe == ONE_CLICK_RECOVERY_WIN_RE_BOOT_CAPABLE) { // OCR Win Re Boot was requested Description = L" WinRe"; LoadOptionType.Bits.AmtTrigBootToWinRe = 1; // add Optional Data to launch WinRe mOcrBootOption->OptionalDataSize = (UINT32) StrSize (WinReOptionalData); mOcrBootOption->OptionalData = AllocatePool (mOcrBootOption->OptionalDataSize); if (mOcrBootOption->OptionalData == NULL) { CancelOcrBootOption (); return EFI_OUT_OF_RESOURCES; } CopyMem (mOcrBootOption->OptionalData, WinReOptionalData, mOcrBootOption->OptionalDataSize); } else { DEBUG ((DEBUG_INFO, "Boot Option Request is not supported.\n")); CancelOcrBootOption (); return EFI_ABORTED; } // Check to make sure Secure Boot is enabled for PBA or WinRe if (mAmtUefiBootOption.UefiBootOptionType == WinRe || mAmtUefiBootOption.UefiBootOptionType == Pba) { VarSize = sizeof (UINT8); //[-start-211111-IB09480171-modify]// // Status = gRT->GetVariable ( // EFI_SECURE_BOOT_ENABLE_NAME, // &gEfiSecureBootEnableDisableGuid, // &VarAttributes, // &VarSize, // &SecureBootState // ); // if (EFI_ERROR (Status)) { // CancelOcrBootOption (); // return Status; // } SecureBootState = GetSecureBootState(); //[-end-211111-IB09480171-modify]// if (SecureBootState == SECURE_BOOT_DISABLE) { DEBUG ((DEBUG_INFO, "OCR PBA or WinRe cannot be setup without Secure Boot Enabled\n")); CancelOcrBootOption (); return EFI_SECURITY_VIOLATION; } } // Set Boot Option Description Status = CreateOcrBootOptionDescription (Description, mOcrBootOption->Description, MAX_UEFI_BOOT_OPTION_DESC_LENGTH); if (EFI_ERROR (Status)) { CancelOcrBootOption (); return Status; } if (mAmtUefiBootOption.EfiDevicePathLen != 0) { // Convert Device Path back to Unicode Status = AsciiStrToUnicodeStrS ( (CHAR8 *) &mAmtUefiBootOption.EfiDevicePath, mOcrBootOption->DevicePath, MAX_UEFI_BOOT_OPTION_DEV_PATH_LENGTH ); if (EFI_ERROR (Status)) { CancelOcrBootOption (); return Status; } } Status = SetupOcrBootOptionParams (mOcrBootOption); if (EFI_ERROR (Status)) { CancelOcrBootOption (); return Status; } //[-start-211215-IB09480180-add]// if (mAmtUefiBootOption.UefiBootOptionType == Pba) { Status = UpdatePbaDevPath (mOcrBootOption); } //[-end-211215-IB09480180-add]// DEBUG ((DEBUG_INFO, "OCR Boot request\n devicepath: %s\n devicepath len:0x%x\n UEFItype: 0x%x", mOcrBootOption->DevicePath, mAmtUefiBootOption.EfiDevicePathLen, mAmtUefiBootOption.UefiBootOptionType)); DEBUG ((DEBUG_INFO, " numofparam: 0x%x\n length:0x%x\n", mAmtUefiBootOption.NumberOfParams, mAmtUefiBootOption.LengthOfParamsArray)); Status = AddOcrBootOption (mOcrBootOption); if (EFI_ERROR (Status)) { CancelOcrBootOption (); return Status; } if (AsfIsFwProgressEnabled ()) { Status = SendOcrPetEvent ( ASF_EVENT_OFFSET_ONE_CLICK_RECOVERY_PROGRESS, ASF_OCR_EVENT_DATA3_CSME_BOOT_OPTION_ADDED, (UINT8) LoadOptionType.Uint32 ); if (EFI_ERROR (Status)) { DEBUG ((DEBUG_INFO, "OCR failed to report PET event for adding OCR Boot option\n")); } } // // Set variable to delete OCR boot option if system is power off before // OcrBootSettings = GetOcrBootSettings (); OcrBootSettings.BootOptionExists = 1; Status = gRT->SetVariable ( OCR_BOOT_SETTINGS_NAME, &mOcrBootSettingsGuid, EFI_VARIABLE_NON_VOLATILE | EFI_VARIABLE_BOOTSERVICE_ACCESS, sizeof (OCR_BOOT_SETTINGS), &OcrBootSettings ); ASSERT_EFI_ERROR (Status); Status = RegisterOneClickRecoveryCallback (); if (EFI_ERROR (Status)) { CancelOcrBootOption (); return Status; } return Status; } /** This routine disables Secure Boot if requested for One Click Recovery. @param[in] MeSetup ME Setup Configuration @retval EFI_SUCCESS Successful @retval EFI_ABORTED Unable to get Secure Boot EFI Variable **/ EFI_STATUS OcrDisableSecureBootState ( IN ASF_BOOT_OPTIONS AsfBootOptions ) { EFI_STATUS Status; UINTN VarSize; //[-start-211111-IB09480171-remove]// // UINT32 VarAttributes; //[-end-211111-IB09480171-remove]// ME_SETUP MeSetup; UINT8 SecureBootState; OCR_BOOT_SETTINGS OcrBootSettings; BOOLEAN EnforceSecureBoot; BOOLEAN OcrHttpsBoot; OcrBootSettings = GetOcrBootSettings (); EnforceSecureBoot = (AsfBootOptions.SpecialCommandParamLowByte & ENFORCE_SECURE_BOOT) == ENFORCE_SECURE_BOOT;; OcrHttpsBoot = AsfBootOptions.SpecialCommand == ASF_INTEL_OEM_FORCE_HTTPS_BOOT_CMD; VarSize = sizeof (ME_SETUP); Status = gRT->GetVariable ( L"MeSetup", &gMeSetupVariableGuid, NULL, &VarSize, &MeSetup ); if (EFI_ERROR (Status)) { return Status; } VarSize = sizeof (UINT8); //[-start-211111-IB09480171-modify]// // Status = gRT->GetVariable ( // EFI_SECURE_BOOT_ENABLE_NAME, // &gEfiSecureBootEnableDisableGuid, // &VarAttributes, // &VarSize, // &SecureBootState // ); // if (EFI_ERROR (Status)) { // return EFI_ABORTED; // } SecureBootState = GetSecureBootState(); //[-end-211111-IB09480171-modify]// if (mOcrCap.Bits.OcrAmtDisSecBoot == ONE_CLICK_RECOVERY_DIS_SEC_BOOT_CAPABLE && MeSetup.OcrAmtDisSecBoot == 1 && SecureBootState == SECURE_BOOT_ENABLE && OcrHttpsBoot && !EnforceSecureBoot) { // Secure Boot needs to be disabled if were doing One Click Recovery HTTPS Boot and Enforce Secure Boot is not set SecureBootState = SECURE_BOOT_DISABLE; //[-start-211111-IB09480171-modify]// // Status = gRT->SetVariable ( // L"SecureBootEnable", // &gEfiSecureBootEnableDisableGuid, // VarAttributes, // sizeof (UINT8), // &SecureBootState // ); // ASSERT_EFI_ERROR (Status); AsfSecureBootChangedSmiCall(SecureBootState, PcdGet16(PcdSoftwareSmiPort)); //[-end-211111-IB09480171-modify]// // Set variable to restore previous secure boot state OcrBootSettings.RestoreSecureBootSetting = RESTORE_SECURE_BOOT_ENABLED; Status = gRT->SetVariable ( OCR_BOOT_SETTINGS_NAME, &mOcrBootSettingsGuid, EFI_VARIABLE_NON_VOLATILE | EFI_VARIABLE_BOOTSERVICE_ACCESS, sizeof (OCR_BOOT_SETTINGS), &OcrBootSettings ); ASSERT_EFI_ERROR (Status); DEBUG ((DEBUG_INFO, "Secure Boot disabled for OCR HTTPS Boot - Cold Reset!\n")); gRT->ResetSystem (EfiResetCold, EFI_SUCCESS, 0, NULL); } return EFI_SUCCESS; } /** This routine restores Secure Boot for One Click Recovery. @retval EFI_SUCCESS Successful @retval EFI_ABORTED Unable to get Secure Boot EFI Variable **/ EFI_STATUS OcrRestoreSecureBootState ( VOID ) { EFI_STATUS Status; UINTN VarSize; //[-start-211111-IB09480171-remove]// // UINT32 VarAttributes; //[-end-211111-IB09480171-remove]// UINT8 SecureBootState; OCR_BOOT_SETTINGS OcrBootSettings; BOOLEAN EnforceSecureBoot; BOOLEAN OcrHttpsBoot; VarSize = sizeof (UINT8); OcrBootSettings = GetOcrBootSettings (); EnforceSecureBoot = (AsfGetSpecialCmdParamLowByte () & ENFORCE_SECURE_BOOT) == ENFORCE_SECURE_BOOT; OcrHttpsBoot = (AsfGetSpecialCommand () == ASF_INTEL_OEM_FORCE_HTTPS_BOOT_CMD); //[-start-211111-IB09480171-modify]// // Status = gRT->GetVariable ( // EFI_SECURE_BOOT_ENABLE_NAME, // &gEfiSecureBootEnableDisableGuid, // &VarAttributes, // &VarSize, // &SecureBootState // ); // if (EFI_ERROR (Status)) { // return EFI_ABORTED; // } SecureBootState = GetSecureBootState(); //[-end-211111-IB09480171-modify]// if (OcrBootSettings.RestoreSecureBootSetting == RESTORE_SECURE_BOOT_ENABLED && SecureBootState == SECURE_BOOT_DISABLE && !(OcrHttpsBoot && !EnforceSecureBoot)) { // Secure boot need to be re-enable from previous One Click Recovery HTTPS Boot SecureBootState = SECURE_BOOT_ENABLE; OcrBootSettings.RestoreSecureBootSetting = RESTORE_SECURE_BOOT_NONE; //[-start-211111-IB09480171-modify]// // Status = gRT->SetVariable ( // L"SecureBootEnable", // &gEfiSecureBootEnableDisableGuid, // VarAttributes, // VarSize, // &SecureBootState // ); // ASSERT_EFI_ERROR (Status); AsfSecureBootChangedSmiCall(SecureBootState, PcdGet16(PcdSoftwareSmiPort)); //[-end-211111-IB09480171-modify]// Status = gRT->SetVariable ( OCR_BOOT_SETTINGS_NAME, &mOcrBootSettingsGuid, EFI_VARIABLE_NON_VOLATILE | EFI_VARIABLE_BOOTSERVICE_ACCESS, sizeof (OCR_BOOT_SETTINGS), &OcrBootSettings ); ASSERT_EFI_ERROR (Status); DEBUG ((DEBUG_INFO, "Secure Boot settings restored after OCR HTTPS Boot - Cold Reset!\n")); gRT->ResetSystem (EfiResetCold, EFI_SUCCESS, 0, NULL); } return EFI_SUCCESS; } /** The Intel One Click Recovery Setup main function. The function does the necessary work to Setup the One Click Recovery feature. @retval EFI_SUCCESS One Click Recovery tasks have been ran @retval EFI_UNSUPPORTED One Click Recovery is not supported **/ EFI_STATUS EFIAPI OneClickRecoveryMain ( VOID ) { EFI_STATUS Status; UEFI_BOOT_OPTION *UefiBootOptions; UINT16 NumOfUefiBootOptions; ME_SETUP MeSetup; UINTN VariableSize; DEBUG ((DEBUG_INFO, "OneClickRecovery setup\n")); VariableSize = sizeof (ME_SETUP); Status = gRT->GetVariable ( L"MeSetup", &gMeSetupVariableGuid, NULL, &VariableSize, &MeSetup ); if (EFI_ERROR (Status)) { return Status; } // Restore Secure Boot State from pre-existing OCR HTTPS OcrRestoreSecureBootState (); // Delete pre-existing OCR Boot Options DeleteOcrBootOption (); // Check for a pending OCR request and set it up Status = OcrBootOptionRequest (MeSetup); // If OCR boot is setup, skip syncing available boot options and boot states if (EFI_ERROR (Status)) { SetUefiBootOptionsState (MeSetup); // Allocate Boot Options list NumOfUefiBootOptions = 0; UefiBootOptions = AllocateZeroPool (MAX_UEFI_BOOT_OPTIONS * sizeof (UEFI_BOOT_OPTION)); if (UefiBootOptions == NULL) { return EFI_OUT_OF_RESOURCES; } // Add PBA Boot Options if (MeSetup.OcrBootPba == 1 && mOcrCap.Bits.OcrBootPba == ONE_CLICK_RECOVERY_PBA_BOOT_CAPABLE) { AddOemPbaBootOptions (UefiBootOptions, &NumOfUefiBootOptions); } // Add WinRe Boot Options if (MeSetup.OcrBootWinRe == 1 && mOcrCap.Bits.OcrBootWinRe == ONE_CLICK_RECOVERY_WIN_RE_BOOT_CAPABLE) { AddWinReBootOptions (UefiBootOptions, &NumOfUefiBootOptions); } Status = AsfUpdateUefiBootOptions (UefiBootOptions, NumOfUefiBootOptions); if (UefiBootOptions != NULL) { FreePool(UefiBootOptions); } } return EFI_SUCCESS; } /** Saves OCR Uefi Boot Option from AMT. Needs to Be called before Clear Boot Options. @retval EFI_SUCCESS Saved Boot Option **/ EFI_STATUS EFIAPI OneClickRecoverySaveUefiBootOption ( IN ASF_BOOT_OPTIONS AsfBootOptions ) { EFI_STATUS Status; // Disable Secure Boot if requested OcrDisableSecureBootState (AsfBootOptions); // Get Asf UEFI Boot Option Status = AsfGetUefiBootParameters (&mAmtUefiBootOption); if (AsfBootOptions.BootOptionsMaskByte2 & FORCE_PROGRESS_EVENTS) { SendOcrPetEvent (ASF_EVENT_OFFSET_ONE_CLICK_RECOVERY_PROGRESS, ASF_OCR_EVENT_DATA3_BOOT_PARAMETER_RECEIVED, 0); } return Status; } /** Entry point of the Intel One Click Recovery Setup DXE Driver Installs the One Click Recovery Setup Protocol for other functions to locate and use @param[in] ImageHandle Handle for this drivers loaded image protocol. @param[in] SystemTable EFI system table. @retval EFI_SUCCESS The protocol has installed successfully @retval EFI_UNSUPPORTED The protocol is not supported @retval Others The protocol did not install successfully **/ EFI_STATUS EFIAPI OneClickRecoveryEntryPoint ( IN EFI_HANDLE ImageHandle, IN EFI_SYSTEM_TABLE *SystemTable ) { EFI_STATUS Status; mOcrCap = OneClickRecoveryCapabilities (); if (!IsOcrSupported ()) { return EFI_UNSUPPORTED; } ZeroMem ((VOID *) &mAmtUefiBootOption, sizeof (UEFI_BOOT_OPTION_PARAMETER)); Status = gBS->InstallMultipleProtocolInterfaces ( &ImageHandle, &gOneClickRecoveryProtocolGuid, &mOneClickRecoveryProtocol, NULL ); ASSERT_EFI_ERROR (Status); DEBUG ((DEBUG_INFO, "OneClickRecovery Protocol Install Status: %r\n", Status)); return Status; }