/** @file
PCH BIOS Write Protect Driver.
Copyright (c) 2021, Intel Corporation. All rights reserved.
SPDX-License-Identifier: BSD-2-Clause-Patent
**/
#include "PchInitSmm.h"
#include
#include
#include
#include
#include
//
// Global variables
//
GLOBAL_REMOVE_IF_UNREFERENCED PCH_TCO_SMI_DISPATCH_PROTOCOL *mPchTcoSmiDispatchProtocol;
GLOBAL_REMOVE_IF_UNREFERENCED PCH_ESPI_SMI_DISPATCH_PROTOCOL *mEspiSmmDispatchProtocol;
GLOBAL_REMOVE_IF_UNREFERENCED UINT64 mLpcRegBase;
/**
This hardware SMI handler will be run every time the BIOS Write Enable bit is set.
@param[in] DispatchHandle Not used
**/
VOID
EFIAPI
PchSpiBiosWpCallback (
IN EFI_HANDLE DispatchHandle
)
{
SpiClearBiosWriteProtectDisable ();
}
/**
This hardware SMI handler will be run every time the BIOS Write Enable bit is set.
@param[in] DispatchHandle Not used
**/
VOID
EFIAPI
PchLpcBiosWpCallback (
IN EFI_HANDLE DispatchHandle
)
{
//
// Disable BIOSWE bit to protect BIOS
//
PciSegmentAnd8 ((UINTN) (mLpcRegBase + R_LPC_CFG_BC), (UINT8) ~B_LPC_CFG_BC_WPD);
}
/**
Entry point for Pch Bios Write Protect driver.
@param[in] ImageHandle Image handle of this driver.
@param[in] SystemTable Global system service table.
@retval EFI_SUCCESS Initialization complete.
**/
EFI_STATUS
EFIAPI
InstallPchBiosWriteProtect (
IN EFI_HANDLE ImageHandle,
IN EFI_SYSTEM_TABLE *SystemTable
)
{
EFI_STATUS Status;
EFI_HANDLE Handle;
DEBUG ((DEBUG_INFO, "InstallPchBiosWriteProtect()\n"));
if (mPchConfigHob->LockDown.BiosLock != TRUE) {
return EFI_SUCCESS;
}
mLpcRegBase = LpcPciCfgBase ();
DEBUG ((DEBUG_INFO, "Installing BIOS Write Protect SMI handler\n"));
//
// Get the PCH TCO SMM dispatch protocol
//
mPchTcoSmiDispatchProtocol = NULL;
Status = gSmst->SmmLocateProtocol (&gPchTcoSmiDispatchProtocolGuid, NULL, (VOID **) &mPchTcoSmiDispatchProtocol);
ASSERT_EFI_ERROR (Status);
//
// Always register an SPI BiosWp callback function to handle TCO BIOSWR SMI
// NOTE: No matter the BIOS resides behind SPI or not, it needs to handle the SPI BIOS WP SMI
// to avoid SMI deadloop on SPI WPD write.
//
Handle = NULL;
Status = mPchTcoSmiDispatchProtocol->SpiBiosWpRegister (
mPchTcoSmiDispatchProtocol,
PchSpiBiosWpCallback,
&Handle
);
ASSERT_EFI_ERROR (Status);
//
// Always register an LPC/eSPI BiosWp callback function to handle TCO BIOSWR SMI
// NOTE: No matter the BIOS resides behind LPC/eSPI or not, it needs to handle the BIOS WP SMI
// to avoid SMI deadloop on LPC/eSPI WPD write.
//
if (IsEspiEnabled ()) {
//
// Get the PCH ESPI SMM dispatch protocol
//
mEspiSmmDispatchProtocol = NULL;
Status = gSmst->SmmLocateProtocol (&gPchEspiSmiDispatchProtocolGuid, NULL, (VOID **) &mEspiSmmDispatchProtocol);
ASSERT_EFI_ERROR (Status);
//
// Register an ESpiBiosWp callback function to handle BIOSWR SMI
//
Handle = NULL;
Status = mEspiSmmDispatchProtocol->BiosWrProtectRegister (
mEspiSmmDispatchProtocol,
PchLpcBiosWpCallback,
&Handle
);
ASSERT_EFI_ERROR (Status);
} else {
//
// Register an LPC BiosWp callback function to handle TCO BIOSWR SMI
//
Handle = NULL;
Status = mPchTcoSmiDispatchProtocol->LpcBiosWpRegister (
mPchTcoSmiDispatchProtocol,
PchLpcBiosWpCallback,
&Handle
);
ASSERT_EFI_ERROR (Status);
}
return EFI_SUCCESS;
}