/** Entry function of Boot script exector. This function will be executed in S3 boot path. This function should not return, because it is invoked by switch stack. @param AcpiS3Context a pointer to a structure of ACPI_S3_CONTEXT @param PeiS3ResumeState a pointer to a structure of PEI_S3_RESUME_STATE @retval EFI_INVALID_PARAMETER - OS waking vector not found @retval EFI_UNSUPPORTED - something wrong when we resume to OS **/ EFI_STATUS EFIAPI S3BootScriptExecutorEntryFunction ( IN ACPI_S3_CONTEXT *AcpiS3Context, IN PEI_S3_RESUME_STATE *PeiS3ResumeState ) { EFI_ACPI_4_0_FIRMWARE_ACPI_CONTROL_STRUCTURE *Facs; EFI_STATUS Status; UINTN TempStackTop; UINTN TempStack[0x10]; UINTN AsmTransferControl16Address; IA32_DESCRIPTOR IdtDescriptor; // // Disable interrupt of Debug timer, since new IDT table cannot handle it. // SaveAndSetDebugTimerInterrupt (FALSE); AsmReadIdtr (&IdtDescriptor); // // Restore IDT for debug // SetIdtEntry (AcpiS3Context); // // Initialize Debug Agent to support source level debug in S3 path, it will disable interrupt and Debug Timer. // InitializeDebugAgent (DEBUG_AGENT_INIT_S3, (VOID *)&IdtDescriptor, NULL); // // Because not install BootScriptExecute PPI(used just in this module), So just pass NULL // for that parameter. // Status = S3BootScriptExecute (); // // If invalid script table or opcode in S3 boot script table. // ASSERT_EFI_ERROR (Status); if (EFI_ERROR (Status)) { CpuDeadLoop (); return Status; } AsmWbinvd (); // // Get ACPI Table Address // Facs = (EFI_ACPI_4_0_FIRMWARE_ACPI_CONTROL_STRUCTURE *) ((UINTN) (AcpiS3Context->AcpiFacsTable)); // // We need turn back to S3Resume - install boot script done ppi and report status code on S3resume. // if (PeiS3ResumeState != 0) { // // Need report status back to S3ResumePeim. // If boot script execution is failed, S3ResumePeim wil report the error status code. // PeiS3ResumeState->ReturnStatus = (UINT64)(UINTN)Status; if (FeaturePcdGet (PcdDxeIplSwitchToLongMode)) { // // X64 S3 Resume // DEBUG ((EFI_D_ERROR, "Call AsmDisablePaging64() to return to S3 Resume in PEI Phase\n")); PeiS3ResumeState->AsmTransferControl = (EFI_PHYSICAL_ADDRESS)(UINTN)AsmTransferControl32; if ((Facs != NULL) && (Facs->Signature == EFI_ACPI_4_0_FIRMWARE_ACPI_CONTROL_STRUCTURE_SIGNATURE) && (Facs->FirmwareWakingVector != 0) ) { // // more step needed - because relative address is handled differently between X64 and IA32. // AsmTransferControl16Address = (UINTN)AsmTransferControl16; AsmFixAddress16 = (UINT32)AsmTransferControl16Address; AsmJmpAddr32 = (UINT32)((Facs->FirmwareWakingVector & 0xF) | ((Facs->FirmwareWakingVector & 0xFFFF0) << 12)); } AsmDisablePaging64 ( PeiS3ResumeState->ReturnCs, (UINT32)PeiS3ResumeState->ReturnEntryPoint, (UINT32)(UINTN)AcpiS3Context, (UINT32)(UINTN)PeiS3ResumeState, (UINT32)PeiS3ResumeState->ReturnStackPointer ); } else { // // IA32 S3 Resume // DEBUG ((EFI_D_ERROR, "Call SwitchStack() to return to S3 Resume in PEI Phase\n")); PeiS3ResumeState->AsmTransferControl = (EFI_PHYSICAL_ADDRESS)(UINTN)AsmTransferControl; SwitchStack ( (SWITCH_STACK_ENTRY_POINT)(UINTN)PeiS3ResumeState->ReturnEntryPoint, (VOID *)(UINTN)AcpiS3Context, (VOID *)(UINTN)PeiS3ResumeState, (VOID *)(UINTN)PeiS3ResumeState->ReturnStackPointer ); } // // Never run to here // CpuDeadLoop(); return EFI_UNSUPPORTED; } // // S3ResumePeim does not provide a way to jump back to itself, so resume to OS here directly // if (Facs->XFirmwareWakingVector != 0) { // // Switch to native waking vector // TempStackTop = (UINTN)&TempStack + sizeof(TempStack); if ((Facs->Version == EFI_ACPI_4_0_FIRMWARE_ACPI_CONTROL_STRUCTURE_VERSION) && ((Facs->Flags & EFI_ACPI_4_0_64BIT_WAKE_SUPPORTED_F) != 0) && ((Facs->Flags & EFI_ACPI_4_0_OSPM_64BIT_WAKE__F) != 0)) { // // X64 long mode waking vector // DEBUG (( EFI_D_ERROR, "Transfer to 64bit OS waking vector - %x\r\n", (UINTN)Facs->XFirmwareWakingVector)); if (FeaturePcdGet (PcdDxeIplSwitchToLongMode)) { SwitchStack ( (SWITCH_STACK_ENTRY_POINT)(UINTN)Facs->XFirmwareWakingVector, NULL, NULL, (VOID *)(UINTN)TempStackTop ); } else { // Unsupported for 32bit DXE, 64bit OS vector DEBUG (( EFI_D_ERROR, "Unsupported for 32bit DXE transfer to 64bit OS waking vector!\r\n")); ASSERT (FALSE); } } else { // // IA32 protected mode waking vector (Page disabled) // DEBUG (( EFI_D_ERROR, "Transfer to 32bit OS waking vector - %x\r\n", (UINTN)Facs->XFirmwareWakingVector)); if (FeaturePcdGet (PcdDxeIplSwitchToLongMode)) { AsmDisablePaging64 ( 0x10, (UINT32)Facs->XFirmwareWakingVector, 0, 0, (UINT32)TempStackTop ); } else { SwitchStack ( (SWITCH_STACK_ENTRY_POINT)(UINTN)Facs->XFirmwareWakingVector, NULL, NULL, (VOID *)(UINTN)TempStackTop ); } } } else { // // 16bit Realmode waking vector // DEBUG (( EFI_D_ERROR, "Transfer to 16bit OS waking vector - %x\r\n", (UINTN)Facs->FirmwareWakingVector)); AsmTransferControl (Facs->FirmwareWakingVector, 0x0); } // // Never run to here // CpuDeadLoop(); return EFI_UNSUPPORTED; }
/** Entry function of Boot script exector. This function will be executed in S3 boot path. This function should not return, because it is invoked by switch stack. @param AcpiS3Context a pointer to a structure of ACPI_S3_CONTEXT @param PeiS3ResumeState a pointer to a structure of PEI_S3_RESUME_STATE @retval EFI_INVALID_PARAMETER - OS waking vector not found @retval EFI_UNSUPPORTED - something wrong when we resume to OS **/ EFI_STATUS EFIAPI S3BootScriptExecutorEntryFunction ( IN ACPI_S3_CONTEXT *AcpiS3Context, IN PEI_S3_RESUME_STATE *PeiS3ResumeState ) { EFI_STATUS Status; // // Disable interrupt of Debug timer, since new IDT table cannot handle it. // SaveAndSetDebugTimerInterrupt (FALSE); // // Restore IDT for debug // SetIdtEntry (AcpiS3Context); // // Initialize Debug Agent to support source level debug in S3 path. // InitializeDebugAgent (DEBUG_AGENT_INIT_S3, NULL, NULL); // // Because not install BootScriptExecute PPI(used just in this module), So just pass NULL // for that parameter. // Status = S3BootScriptExecute (); AsmWbinvd (); // // We need turn back to S3Resume - install boot script done ppi and report status code on S3resume. // if (PeiS3ResumeState != 0) { // // Need report status back to S3ResumePeim. // If boot script execution is failed, S3ResumePeim wil report the error status code. // PeiS3ResumeState->ReturnStatus = (UINT64)(UINTN)Status; // // IA32 S3 Resume // DEBUG ((EFI_D_INFO, "Call SwitchStack() to return to S3 Resume in PEI Phase\n")); PeiS3ResumeState->AsmTransferControl = (EFI_PHYSICAL_ADDRESS)(UINTN)PlatformTransferControl16; SwitchStack ( (SWITCH_STACK_ENTRY_POINT)(UINTN)PeiS3ResumeState->ReturnEntryPoint, (VOID *)(UINTN)AcpiS3Context, (VOID *)(UINTN)PeiS3ResumeState, (VOID *)(UINTN)PeiS3ResumeState->ReturnStackPointer ); // // Never run to here // CpuDeadLoop(); return EFI_UNSUPPORTED; } // // Never run to here // CpuDeadLoop(); return EFI_UNSUPPORTED; }