diff options
author | raywu <raywu0301@gmail.com> | 2018-06-15 00:00:50 +0800 |
---|---|---|
committer | raywu <raywu0301@gmail.com> | 2018-06-15 00:00:50 +0800 |
commit | b7c51c9cf4864df6aabb99a1ae843becd577237c (patch) | |
tree | eebe9b0d0ca03062955223097e57da84dd618b9a /Core/EM/BootScriptHide/BootScriptHidePei.c | |
download | zprj-b7c51c9cf4864df6aabb99a1ae843becd577237c.tar.xz |
Diffstat (limited to 'Core/EM/BootScriptHide/BootScriptHidePei.c')
-rw-r--r-- | Core/EM/BootScriptHide/BootScriptHidePei.c | 266 |
1 files changed, 266 insertions, 0 deletions
diff --git a/Core/EM/BootScriptHide/BootScriptHidePei.c b/Core/EM/BootScriptHide/BootScriptHidePei.c new file mode 100644 index 0000000..9b2c820 --- /dev/null +++ b/Core/EM/BootScriptHide/BootScriptHidePei.c @@ -0,0 +1,266 @@ +//********************************************************************** +//********************************************************************** +//** ** +//** (C)Copyright 1985-2016, American Megatrends, Inc. ** +//** ** +//** All Rights Reserved. ** +//** ** +//** 5555 Oakbrook Pkwy, Norcross, GA 30093 ** +//** ** +//** Phone: (770)-246-8600 ** +//** ** +//********************************************************************** +//********************************************************************** + +//********************************************************************** +// $Header: /Alaska/SOURCE/Modules/BootScriptHide/BootScriptHidePei.c 3 5/24/16 4:28p Robert $ +// +// $Revision: 3 $ +// +// $Date: 5/24/16 4:28p $ +//********************************************************************** +// Revision History +// ---------------- +// $Log: /Alaska/SOURCE/Modules/BootScriptHide/BootScriptHidePei.c $ +// +// 3 5/24/16 4:28p Robert +// [TAG] EIP268161 +// [Category] Improvement +// [Description] updated copyrights +// +// 2 5/20/16 12:10p Robert +// [TAG] EIP268161 +// [Category] Improvement +// [Description] Update BootScriptHide to comply with Security +// Vulnerability related to saving other memory regions at the same time +// as the boot scripts +// +// 1 9/10/14 6:31p Aaronp +// First addition of BootScriptHide emodule. +//********************************************************************** + +//********************************************************************** +//<AMI_FHDR_START> +// +// Name: BootScriptHidePei.c +// +// Description: Source file for the PEI driver. This file contains the +// code to trigger the SWSMI that will restore the boot +// scripts into regular memory from inside of SMM. +// +//<AMI_FHDR_END> +//********************************************************************** + +#include <AmiPeiLib.h> +#include <Token.h> +#include <AcpiS3.h> +#include <Ppi/SmmControl.h> +#include <Ppi/S3Resume2.h> + +typedef struct{ + EFI_PEI_S3_RESUME2_PPI Ppi; + EFI_PEI_S3_RESUME2_PPI *OriginalPpi; +} S3_RESUME2_PRIVATE; + +//PPI to be installed +EFI_PEI_PPI_DESCRIPTOR S3ResumePpiListTemplate = { + EFI_PEI_PPI_DESCRIPTOR_PPI | EFI_PEI_PPI_DESCRIPTOR_TERMINATE_LIST, + &gEfiPeiS3Resume2PpiGuid, + NULL +}; + +//<AMI_PHDR_START> +//---------------------------------------------------------------------------- +// Procedure: TriggerSwSmi +// +// Description: Function that attempts to trigger a SWSMI to restore the boot +// script tables from SMM memory into regular system memory. This +// function is called only when the system is resuming from S3. +// +// Input: +// IN EFI_PEI_SERVICES **PeiServices - Pointer to the PEI services table +// +// Output: +// EFI_STATUS - The status of attempting to trigger a SWSMI +//---------------------------------------------------------------------------- +//<AMI_PHDR_END> +EFI_STATUS TriggerSwSmi(IN EFI_PEI_SERVICES **PeiServices){ + EFI_STATUS Status; + PEI_SMM_CONTROL_PPI *SmmControl; + INT8 SmiCommand; + UINTN Size; + + // Trigger boot script restoring SMI + + // What's the best method of SW SMI generation in PEI? + // We're sticking with SmmControl PPI. + // If it's not available in your project, replace the code below... + Status = (*PeiServices)->LocatePpi( + PeiServices, &gPeiSmmControlPpiGuid, 0, NULL, (VOID **)&SmmControl + ); + if (EFI_ERROR (Status)){ + PEI_TRACE((TRACE_ALWAYS,PeiServices,"BootScriptHide: ERROR: SmmControl PPI not found. Can't restore the boot script.\n")); + PEI_TRACE((TRACE_ALWAYS,PeiServices,"If PPI is not available in the project, replace code of the TriggerSwSmi function in BootScriptHidePei.c with the chipset specific SW SMI trigerring code.\n")); + PEI_TRACE((TRACE_ALWAYS,PeiServices," NOTE: Simple write to 0xB2 may not work. You may have to enable SW SMI in one of the SB registers.\n")); + PEI_TRACE((TRACE_ALWAYS,PeiServices," If SW SMI generation succeeds, you should see \"Boot script has been restored\" debug message.\n")); + ASSERT_PEI_ERROR(PeiServices,EFI_ABORTED); + return Status; + } + SmiCommand = BOOT_SCRIPT_RESTORE_SW_SMI_VALUE; + Size = sizeof(SmiCommand); + Status = SmmControl->Trigger(PeiServices, SmmControl, &SmiCommand, &Size, FALSE, 0); + if (EFI_ERROR (Status)){ + PEI_TRACE((TRACE_ALWAYS,PeiServices,"BootScriptHide: ERROR: SmmControl->Trigger failed with status %r. Can't restore the boot script.\n",Status)); + ASSERT_PEI_ERROR(PeiServices,EFI_ABORTED); + return Status; + } + return EFI_SUCCESS; +} + +//<AMI_PHDR_START> +//---------------------------------------------------------------------------- +// Procedure: ErrorHandler +// +// Description: Function called when the system encounters an error while +// trying to restore the boot scripts into regular system memory. +// If this function is called, it is because there is an error +// in the system, and S3 resume cannot be completed +// +// Input: +// IN EFI_PEI_SERVICES **PeiServices - Pointer to the PEI services table +// +// Output: +// None +//---------------------------------------------------------------------------- +//<AMI_PHDR_END> +VOID ErrorHandler(IN EFI_PEI_SERVICES **PeiServices){ + // If something went wrong and we were unable to restore the boot script, system is vulnerable. + // One one to go back to safety is to issue a system reset, which will change boot path from S3 resume to a normal boot. + PEI_TRACE((TRACE_ALWAYS,PeiServices,"BootScriptHide: Couldn't restore the boot script. Resetting...\n")); + (*PeiServices)->ResetSystem(PeiServices); + PEI_TRACE((TRACE_ALWAYS,PeiServices,"BootScriptHide: Couldn't reset. Dead-looping...\n")); + ASSERT_PEI_ERROR(PeiServices,EFI_ABORTED); + EFI_DEADLOOP(); +} + +//<AMI_PHDR_START> +//---------------------------------------------------------------------------- +// Procedure: S3RestoreConfig2 +// +// Description: This function can be considered a hook. This function is used to replace the +// S3Resume PPI's RestoreConfig function. The original S3Resume PPI's RestoreConfig +// is saved, and is called at the end of this function. This function will be +// attempt to trigger the SWSMI to restore the boot script tables into regular +// system memory. +// +// Input: +// IN EFI_PEI_S3_RESUME2_PPI *This - Pointer to the S3 resume PPI. +// +// Output: +// EFI_STATUS Status - the status of attempting to restore the configuration +//---------------------------------------------------------------------------- +//<AMI_PHDR_END> +EFI_STATUS EFIAPI S3RestoreConfig2(IN EFI_PEI_S3_RESUME2_PPI *This){ + const CHAR16 AcpiGlobalVariable[] = ACPI_GLOBAL_VARIABLE; + const EFI_GUID EfiAcpiVariableGuid = EFI_ACPI_VARIABLE_GUID; + EFI_STATUS Status; + S3_RESUME2_PRIVATE *S3Resume2Ppi = (S3_RESUME2_PRIVATE*)This; + EFI_PEI_SERVICES **PeiServices = GetPeiServicesTablePointer(); + ACPI_VARIABLE_SET *AcpiVariableSet; + UINTN VariableSize = sizeof(AcpiVariableSet); + EFI_PHYSICAL_ADDRESS AcpiReservedMemoryBase; + + PEI_TRACE((TRACE_ALWAYS,PeiServices,"BootScriptHide: Successfully trapped S3RestoreConfig2 call.\n")); + + Status = PeiGetVariable(PeiServices,AcpiGlobalVariable,&EfiAcpiVariableGuid,NULL,&VariableSize, &AcpiVariableSet); + if (EFI_ERROR (Status)){ + PEI_TRACE((TRACE_ALWAYS,PeiServices,"BootScriptHide: Can't read variable %S. Status = %r.\n", AcpiGlobalVariable, Status)); + ErrorHandler(PeiServices); + } + // We are using AcpiReservedMemoryBase field as a communication mail box between this PEIM + // and boot script restoring SMI handler. + // We are setting the field to BOOT_SCRIPT_SAVE_SW_SMI_VALUE and SMI handler if succeeds sets it to BOOT_SCRIPT_RESTORE_SW_SMI_VALUE. + // Preserve original AcpiReservedMemoryBase value to restore it once we are done. + AcpiReservedMemoryBase = AcpiVariableSet->AcpiReservedMemoryBase; + AcpiVariableSet->AcpiReservedMemoryBase = ~(AcpiVariableSet->AcpiReservedMemoryBase); + Status = TriggerSwSmi(GetPeiServicesTablePointer()); + if (EFI_ERROR (Status)) ErrorHandler(PeiServices); + if (AcpiVariableSet->AcpiReservedMemoryBase != BOOT_SCRIPT_RESTORE_SW_SMI_VALUE){ + PEI_TRACE((TRACE_ALWAYS,PeiServices,"BootScriptHide: Something went wrong. SW SMI handler failed to restore the boot script.\n")); + ErrorHandler(PeiServices); + } + + // Restore original AcpiReservedMemoryBase value. + AcpiVariableSet->AcpiReservedMemoryBase = AcpiReservedMemoryBase; + + PEI_TRACE((TRACE_ALWAYS,PeiServices,"BootScriptHide: Calling original S3RestoreConfig2\n")); + return S3Resume2Ppi->OriginalPpi->S3RestoreConfig2(S3Resume2Ppi->OriginalPpi); +} + +//<AMI_PHDR_START> +//---------------------------------------------------------------------------- +// Procedure: BootScriptHidePeiEntryPoint +// +// Description: Module entry point for the BootScripeHidePei module. This module +// does nothing if the system is not in the S3 resume path. +// If the system is in the S3 resume path, then the module will use the +// installed S3Resume PPI to populate a new copy of the S3Resume PPI that +// will contain the S3RestoreConfig2 function instead of the original S3RestoreConfig2 function. +// +// +// Input: +// IN EFI_PEI_FILE_HANDLE FileHandle - The file handle associated with this PEIM +// IN EFI_PEI_SERVICES **PeiServices - Pointer to the PEI Services table +// +// Output: +// EFI_STATUS Status - the status of registering the callbacks and hooking the S3ResumePpi functions +//---------------------------------------------------------------------------- +//<AMI_PHDR_END> +EFI_STATUS EFIAPI BootScriptHidePeiEntryPoint (IN EFI_PEI_FILE_HANDLE FileHandle, IN EFI_PEI_SERVICES **PeiServices){ + + EFI_STATUS Status; + EFI_BOOT_MODE BootMode; + EFI_PEI_PPI_DESCRIPTOR *S3ResumePpiList; + S3_RESUME2_PRIVATE *S3Resume2Ppi; + EFI_PEI_S3_RESUME2_PPI *OriginalS3Resume2Ppi; + EFI_PEI_PPI_DESCRIPTOR *OrignalS3Resume2PpiDescriptor; + + Status = (*PeiServices)->GetBootMode( PeiServices, &BootMode ); + if ( EFI_ERROR(Status) || BootMode != BOOT_ON_S3_RESUME) return EFI_UNSUPPORTED; + // We can't trigger SW SMI just yet because we can't be sure that it will work. + // Perhaps SMM initialization is yet to be done by other PEIMs. + // We need to delay SW SMI generation to a latter point. + // One one to do it is S3Resume2 PPI hijacking. + Status = (*PeiServices)->LocatePpi( + PeiServices, &gEfiPeiS3Resume2PpiGuid, 0, &OrignalS3Resume2PpiDescriptor, (VOID **)&OriginalS3Resume2Ppi + ); + if ( EFI_ERROR(Status) ) return Status; + + Status = (*PeiServices)->AllocatePool(PeiServices, sizeof(S3ResumePpiListTemplate)+sizeof(*S3Resume2Ppi), &S3ResumePpiList); + if (EFI_ERROR(Status)) return Status; + *S3ResumePpiList=S3ResumePpiListTemplate; + S3Resume2Ppi = (S3_RESUME2_PRIVATE*)(S3ResumePpiList+1); + S3Resume2Ppi->Ppi.S3RestoreConfig2 = S3RestoreConfig2; + S3ResumePpiList->Ppi = &S3Resume2Ppi->Ppi; + S3Resume2Ppi->OriginalPpi = OriginalS3Resume2Ppi; + + Status = (*PeiServices)->ReInstallPpi(PeiServices,OrignalS3Resume2PpiDescriptor,S3ResumePpiList); + if (EFI_ERROR(Status)){ + PEI_TRACE((TRACE_ALWAYS,PeiServices,"BootScriptHide: Can't replace S3Resume2 PPI.\n")); + ErrorHandler(PeiServices); + } + return Status; +} +//********************************************************************** +//********************************************************************** +//** ** +//** (C)Copyright 1985-2016, American Megatrends, Inc. ** +//** ** +//** All Rights Reserved. ** +//** ** +//** 5555 Oakbrook Pkwy, Norcross, GA 30093 ** +//** ** +//** Phone: (770)-246-8600 ** +//** ** +//********************************************************************** +//**********************************************************************
\ No newline at end of file |