1b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney/** @file 2b303605e1b7e113b4311daf161c6c3289350447bMichael KinneyThis is the code for Boot Script Executer module. 3b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney 4b303605e1b7e113b4311daf161c6c3289350447bMichael KinneyThis driver is dispatched by Dxe core and the driver will reload itself to ACPI NVS memory 5b303605e1b7e113b4311daf161c6c3289350447bMichael Kinneyin the entry point. The functionality is to interpret and restore the S3 boot script 6b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney 7b303605e1b7e113b4311daf161c6c3289350447bMichael KinneyCopyright (c) 2013-2015 Intel Corporation. 8b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney 9b303605e1b7e113b4311daf161c6c3289350447bMichael KinneyThis program and the accompanying materials 10b303605e1b7e113b4311daf161c6c3289350447bMichael Kinneyare licensed and made available under the terms and conditions of the BSD License 11b303605e1b7e113b4311daf161c6c3289350447bMichael Kinneywhich accompanies this distribution. The full text of the license may be found at 12b303605e1b7e113b4311daf161c6c3289350447bMichael Kinneyhttp://opensource.org/licenses/bsd-license.php 13b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney 14b303605e1b7e113b4311daf161c6c3289350447bMichael KinneyTHE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, 15b303605e1b7e113b4311daf161c6c3289350447bMichael KinneyWITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. 16b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney 17b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney**/ 18b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney 19b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney#include "ScriptExecute.h" 20b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney 21b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney#pragma pack(1) 22b303605e1b7e113b4311daf161c6c3289350447bMichael Kinneytypedef union { 23b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney struct { 24b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney UINT32 LimitLow : 16; 25b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney UINT32 BaseLow : 16; 26b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney UINT32 BaseMid : 8; 27b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney UINT32 Type : 4; 28b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney UINT32 System : 1; 29b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney UINT32 Dpl : 2; 30b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney UINT32 Present : 1; 31b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney UINT32 LimitHigh : 4; 32b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney UINT32 Software : 1; 33b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney UINT32 Reserved : 1; 34b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney UINT32 DefaultSize : 1; 35b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney UINT32 Granularity : 1; 36b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney UINT32 BaseHigh : 8; 37b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney } Bits; 38b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney UINT64 Uint64; 39b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney} IA32_GDT; 40b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney 41b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney#pragma pack() 42b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney 43b303605e1b7e113b4311daf161c6c3289350447bMichael KinneyEFI_GUID mBootScriptExecutorImageGuid = { 44b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney 0x9a8d3433, 0x9fe8, 0x42b6, {0x87, 0xb, 0x1e, 0x31, 0xc8, 0x4e, 0xbe, 0x3b} 45b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney}; 46b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney 47b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney// 48b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney// Global Descriptor Table (GDT) 49b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney// 50b303605e1b7e113b4311daf161c6c3289350447bMichael KinneyGLOBAL_REMOVE_IF_UNREFERENCED IA32_GDT mGdtEntries[] = { 51b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney/* selector { Global Segment Descriptor } */ 52b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney/* 0x00 */ {{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}}, 53b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney/* 0x08 */ {{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}}, 54b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney/* 0x10 */ {{0xFFFF, 0, 0, 0xB, 1, 0, 1, 0xF, 0, 0, 1, 1, 0}}, 55b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney/* 0x18 */ {{0xFFFF, 0, 0, 0x3, 1, 0, 1, 0xF, 0, 0, 1, 1, 0}}, 56b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney/* 0x20 */ {{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}}, 57b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney/* 0x28 */ {{0xFFFF, 0, 0, 0xB, 1, 0, 1, 0xF, 0, 0, 0, 1, 0}}, 58b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney/* 0x30 */ {{0xFFFF, 0, 0, 0x3, 1, 0, 1, 0xF, 0, 0, 0, 1, 0}}, 59b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney/* 0x38 */ {{0xFFFF, 0, 0, 0xB, 1, 0, 1, 0xF, 0, 1, 0, 1, 0}}, 60b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney/* 0x40 */ {{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}}, 61b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney}; 62b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney 63b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney// 64b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney// IA32 Gdt register 65b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney// 66b303605e1b7e113b4311daf161c6c3289350447bMichael KinneyGLOBAL_REMOVE_IF_UNREFERENCED CONST IA32_DESCRIPTOR mGdt = { 67b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney sizeof (mGdtEntries) - 1, 68b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney (UINTN) mGdtEntries 69b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney }; 70b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney 71b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney/** 72b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney Entry function of Boot script exector. This function will be executed in 73b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney S3 boot path. 74b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney This function should not return, because it is invoked by switch stack. 75b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney 76b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney @param AcpiS3Context a pointer to a structure of ACPI_S3_CONTEXT 77b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney @param PeiS3ResumeState a pointer to a structure of PEI_S3_RESUME_STATE 78b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney 79b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney @retval EFI_INVALID_PARAMETER - OS waking vector not found 80b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney @retval EFI_UNSUPPORTED - something wrong when we resume to OS 81b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney**/ 82b303605e1b7e113b4311daf161c6c3289350447bMichael KinneyEFI_STATUS 83b303605e1b7e113b4311daf161c6c3289350447bMichael KinneyEFIAPI 84b303605e1b7e113b4311daf161c6c3289350447bMichael KinneyS3BootScriptExecutorEntryFunction ( 85b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney IN ACPI_S3_CONTEXT *AcpiS3Context, 86b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney IN PEI_S3_RESUME_STATE *PeiS3ResumeState 87b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney ) 88b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney{ 89b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney EFI_STATUS Status; 90b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney 91b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney // 92b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney // Disable interrupt of Debug timer, since new IDT table cannot handle it. 93b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney // 94b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney SaveAndSetDebugTimerInterrupt (FALSE); 95b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney 96b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney // 97b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney // Restore IDT for debug 98b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney // 99b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney SetIdtEntry (AcpiS3Context); 100b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney 101b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney // 102b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney // Initialize Debug Agent to support source level debug in S3 path. 103b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney // 104b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney InitializeDebugAgent (DEBUG_AGENT_INIT_S3, NULL, NULL); 105b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney 106b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney // 107b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney // Because not install BootScriptExecute PPI(used just in this module), So just pass NULL 108b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney // for that parameter. 109b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney // 110b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney Status = S3BootScriptExecute (); 111b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney 112b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney AsmWbinvd (); 113b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney 114b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney // 115b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney // We need turn back to S3Resume - install boot script done ppi and report status code on S3resume. 116b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney // 117b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney if (PeiS3ResumeState != 0) { 118b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney // 119b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney // Need report status back to S3ResumePeim. 120b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney // If boot script execution is failed, S3ResumePeim wil report the error status code. 121b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney // 122b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney PeiS3ResumeState->ReturnStatus = (UINT64)(UINTN)Status; 123b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney // 124b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney // IA32 S3 Resume 125b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney // 126b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney DEBUG ((EFI_D_INFO, "Call SwitchStack() to return to S3 Resume in PEI Phase\n")); 127b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney PeiS3ResumeState->AsmTransferControl = (EFI_PHYSICAL_ADDRESS)(UINTN)PlatformTransferControl16; 128b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney 129b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney SwitchStack ( 130b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney (SWITCH_STACK_ENTRY_POINT)(UINTN)PeiS3ResumeState->ReturnEntryPoint, 131b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney (VOID *)(UINTN)AcpiS3Context, 132b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney (VOID *)(UINTN)PeiS3ResumeState, 133b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney (VOID *)(UINTN)PeiS3ResumeState->ReturnStackPointer 134b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney ); 135b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney 136b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney // 137b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney // Never run to here 138b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney // 139b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney CpuDeadLoop(); 140b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney return EFI_UNSUPPORTED; 141b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney } 142b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney 143b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney // 144b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney // Never run to here 145b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney // 146b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney CpuDeadLoop(); 147b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney return EFI_UNSUPPORTED; 148b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney} 149b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney/** 150b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney Entrypoint of Boot script exector driver, this function will be executed in 151b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney normal boot phase and invoked by DXE dispatch. 152b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney 153b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney @param[in] ImageHandle The firmware allocated handle for the EFI image. 154b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney @param[in] SystemTable A pointer to the EFI System Table. 155b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney 156b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney @retval EFI_SUCCESS The entry point is executed successfully. 157b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney @retval other Some error occurs when executing this entry point. 158b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney**/ 159b303605e1b7e113b4311daf161c6c3289350447bMichael KinneyEFI_STATUS 160b303605e1b7e113b4311daf161c6c3289350447bMichael KinneyEFIAPI 161b303605e1b7e113b4311daf161c6c3289350447bMichael KinneyBootScriptExecutorEntryPoint ( 162b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney IN EFI_HANDLE ImageHandle, 163b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney IN EFI_SYSTEM_TABLE *SystemTable 164b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney ) 165b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney{ 166b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney UINT8 *Buffer; 167b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney UINTN BufferSize; 168b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney UINTN Pages; 169b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney EFI_PHYSICAL_ADDRESS FfsBuffer; 170b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney PE_COFF_LOADER_IMAGE_CONTEXT ImageContext; 171b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney BOOT_SCRIPT_EXECUTOR_VARIABLE *EfiBootScriptExecutorVariable; 172b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney EFI_PHYSICAL_ADDRESS BootScriptExecutorBuffer; 173b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney EFI_STATUS Status; 174b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney VOID *DevicePath; 175b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney EFI_HANDLE NewImageHandle; 176b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney 177b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney // 178b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney // Test if the gEfiCallerIdGuid of this image is already installed. if not, the entry 179b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney // point is loaded by DXE code which is the first time loaded. or else, it is already 180b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney // be reloaded be itself.This is a work-around 181b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney // 182b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney Status = gBS->LocateProtocol (&gEfiCallerIdGuid, NULL, &DevicePath); 183b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney if (EFI_ERROR (Status)) { 184b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney 185b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney // 186b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney // This is the first-time loaded by DXE core. reload itself to NVS mem 187b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney // 188b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney // 189b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney // A workarouond: Here we install a dummy handle 190b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney // 191b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney NewImageHandle = NULL; 192b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney Status = gBS->InstallProtocolInterface ( 193b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney &NewImageHandle, 194b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney &gEfiCallerIdGuid, 195b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney EFI_NATIVE_INTERFACE, 196b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney NULL 197b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney ); 198b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney 199b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney Status = GetSectionFromAnyFv ( 200b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney &gEfiCallerIdGuid, 201b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney EFI_SECTION_PE32, 202b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney 0, 203b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney (VOID **) &Buffer, 204b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney &BufferSize 205b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney ); 206b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney ImageContext.Handle = Buffer; 207b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney ImageContext.ImageRead = PeCoffLoaderImageReadFromMemory; 208b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney // 209b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney // Get information about the image being loaded 210b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney // 211b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney Status = PeCoffLoaderGetImageInfo (&ImageContext); 212b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney if (EFI_ERROR (Status)) { 213b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney return Status; 214b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney } 215b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney Pages = EFI_SIZE_TO_PAGES(BufferSize + ImageContext.SectionAlignment); 216b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney FfsBuffer = 0xFFFFFFFF; 217b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney Status = gBS->AllocatePages ( 218b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney AllocateMaxAddress, 219b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney EfiACPIMemoryNVS, 220b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney Pages, 221b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney &FfsBuffer 222b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney ); 223b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney if (EFI_ERROR (Status)) { 224b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney return EFI_OUT_OF_RESOURCES; 225b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney } 226b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney ImageContext.ImageAddress = (PHYSICAL_ADDRESS)(UINTN)FfsBuffer; 227b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney // 228b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney // Align buffer on section boundry 229b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney // 230b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney ImageContext.ImageAddress += ImageContext.SectionAlignment - 1; 231b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney ImageContext.ImageAddress &= ~(ImageContext.SectionAlignment - 1); 232b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney // 233b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney // Load the image to our new buffer 234b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney // 235b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney Status = PeCoffLoaderLoadImage (&ImageContext); 236b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney if (EFI_ERROR (Status)) { 237b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney gBS->FreePages (FfsBuffer, Pages); 238b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney return Status; 239b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney } 240b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney 241b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney // 242b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney // Relocate the image in our new buffer 243b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney // 244b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney Status = PeCoffLoaderRelocateImage (&ImageContext); 245b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney 246b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney if (EFI_ERROR (Status)) { 247b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney PeCoffLoaderUnloadImage (&ImageContext); 248b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney gBS->FreePages (FfsBuffer, Pages); 249b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney return Status; 250b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney } 251b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney // 252b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney // Flush the instruction cache so the image data is written before we execute it 253b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney // 254b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney InvalidateInstructionCacheRange ((VOID *)(UINTN)ImageContext.ImageAddress, (UINTN)ImageContext.ImageSize); 255b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney Status = ((EFI_IMAGE_ENTRY_POINT)(UINTN)(ImageContext.EntryPoint)) (NewImageHandle, SystemTable); 256b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney if (EFI_ERROR (Status)) { 257b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney gBS->FreePages (FfsBuffer, Pages); 258b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney return Status; 259b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney } 260b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney // 261b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney // Additional step for BootScript integrity 262b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney // Save BootScriptExecutor image 263b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney // 264b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney Status = SaveLockBox ( 265b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney &mBootScriptExecutorImageGuid, 266b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney (VOID *)(UINTN)ImageContext.ImageAddress, 267b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney (UINTN)ImageContext.ImageSize 268b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney ); 269b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney ASSERT_EFI_ERROR (Status); 270b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney 271b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney Status = SetLockBoxAttributes (&mBootScriptExecutorImageGuid, LOCK_BOX_ATTRIBUTE_RESTORE_IN_PLACE); 272b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney ASSERT_EFI_ERROR (Status); 273b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney 274b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney } else { 275b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney // 276b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney // the entry point is invoked after reloading. following code only run in ACPI NVS 277b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney // 278b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney BufferSize = sizeof (BOOT_SCRIPT_EXECUTOR_VARIABLE); 279b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney 280b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney BootScriptExecutorBuffer = 0xFFFFFFFF; 281b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney Pages = EFI_SIZE_TO_PAGES(BufferSize); 282b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney Status = gBS->AllocatePages ( 283b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney AllocateMaxAddress, 284b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney EfiACPIMemoryNVS, 285b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney Pages, 286b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney &BootScriptExecutorBuffer 287b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney ); 288b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney if (EFI_ERROR (Status)) { 289b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney return EFI_OUT_OF_RESOURCES; 290b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney } 291b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney 292b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney EfiBootScriptExecutorVariable = (BOOT_SCRIPT_EXECUTOR_VARIABLE *)(UINTN)BootScriptExecutorBuffer; 293b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney EfiBootScriptExecutorVariable->BootScriptExecutorEntrypoint = (UINTN) S3BootScriptExecutorEntryFunction ; 294b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney 295b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney Status = SaveLockBox ( 296b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney &gEfiBootScriptExecutorVariableGuid, 297b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney &BootScriptExecutorBuffer, 298b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney sizeof(BootScriptExecutorBuffer) 299b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney ); 300b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney ASSERT_EFI_ERROR (Status); 301b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney 302b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney // 303b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney // Additional step for BootScript integrity 304b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney // Save BootScriptExecutor context 305b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney // 306b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney Status = SaveLockBox ( 307b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney &gEfiBootScriptExecutorContextGuid, 308b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney EfiBootScriptExecutorVariable, 309b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney sizeof(*EfiBootScriptExecutorVariable) 310b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney ); 311b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney ASSERT_EFI_ERROR (Status); 312b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney 313b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney Status = SetLockBoxAttributes (&gEfiBootScriptExecutorContextGuid, LOCK_BOX_ATTRIBUTE_RESTORE_IN_PLACE); 314b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney ASSERT_EFI_ERROR (Status); 315b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney 316b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney } 317b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney 318b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney return EFI_SUCCESS; 319b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney} 320b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney 321b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney/** 322b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney Platform specific mechanism to transfer control to 16bit OS waking vector 323b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney 324b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney @param[in] AcpiWakingVector The 16bit OS waking vector 325b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney @param[in] AcpiLowMemoryBase A buffer under 1M which could be used during the transfer 326b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney 327b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney**/ 328b303605e1b7e113b4311daf161c6c3289350447bMichael KinneyVOID 329b303605e1b7e113b4311daf161c6c3289350447bMichael KinneyPlatformTransferControl16 ( 330b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney IN UINT32 AcpiWakingVector, 331b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney IN UINT32 AcpiLowMemoryBase 332b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney ) 333b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney{ 334b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney UINT32 NewValue; 335b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney UINT64 BaseAddress; 336b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney UINT64 SmramLength; 337b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney UINTN Index; 338b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney 339b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney DEBUG (( EFI_D_INFO, "PlatformTransferControl - Entry\r\n")); 340b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney 341b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney // 342b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney // Need to make sure the GDT is loaded with values that support long mode and real mode. 343b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney // 344b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney AsmWriteGdtr (&mGdt); 345b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney 346b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney // 347b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney // Disable eSram block (this will also clear/zero eSRAM) 348b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney // We only use eSRAM in the PEI phase. Disable now that we are resuming the OS 349b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney // 350b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney NewValue = QNCPortRead (QUARK_NC_MEMORY_MANAGER_SB_PORT_ID, QUARK_NC_MEMORY_MANAGER_ESRAMPGCTRL_BLOCK); 351b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney NewValue |= BLOCK_DISABLE_PG; 352b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney QNCPortWrite (QUARK_NC_MEMORY_MANAGER_SB_PORT_ID, QUARK_NC_MEMORY_MANAGER_ESRAMPGCTRL_BLOCK, NewValue); 353b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney 354b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney // 355b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney // Update HMBOUND to top of DDR3 memory and LOCK 356b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney // We disabled eSRAM so now we move HMBOUND down to top of DDR3 357b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney // 358b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney QNCGetTSEGMemoryRange (&BaseAddress, &SmramLength); 359b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney NewValue = (UINT32)(BaseAddress + SmramLength); 360b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney DEBUG ((EFI_D_INFO,"Locking HMBOUND at: = 0x%8x\n",NewValue)); 361b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney QNCPortWrite (QUARK_NC_HOST_BRIDGE_SB_PORT_ID, QUARK_NC_HOST_BRIDGE_HMBOUND_REG, (NewValue | HMBOUND_LOCK)); 362b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney 363b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney // 364b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney // Lock all IMR regions now that HMBOUND is locked 365b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney // 366b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney for (Index = (QUARK_NC_MEMORY_MANAGER_IMR0+QUARK_NC_MEMORY_MANAGER_IMRXL); Index <= (QUARK_NC_MEMORY_MANAGER_IMR7+QUARK_NC_MEMORY_MANAGER_IMRXL); Index += 4) { 367b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney NewValue = QNCPortRead (QUARK_NC_MEMORY_MANAGER_SB_PORT_ID, Index); 368b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney NewValue |= IMR_LOCK; 369b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney QNCPortWrite (QUARK_NC_MEMORY_MANAGER_SB_PORT_ID, Index, NewValue); 370b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney } 371b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney 372b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney // 373b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney // Call ASM routine to switch to real mode and jump to 16bit OS waking vector 374b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney // 375b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney AsmTransferControl(AcpiWakingVector, 0); 376b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney 377b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney // 378b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney // Never run to here 379b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney // 380b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney CpuDeadLoop(); 381b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney} 382b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney 383b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney 384b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney 385b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney 386