summaryrefslogtreecommitdiff
path: root/Silicon/Intel/LewisburgPkg/Library/PeiDxeSmmPchPcrLib/PchPcrLib.c
diff options
context:
space:
mode:
Diffstat (limited to 'Silicon/Intel/LewisburgPkg/Library/PeiDxeSmmPchPcrLib/PchPcrLib.c')
-rw-r--r--Silicon/Intel/LewisburgPkg/Library/PeiDxeSmmPchPcrLib/PchPcrLib.c459
1 files changed, 459 insertions, 0 deletions
diff --git a/Silicon/Intel/LewisburgPkg/Library/PeiDxeSmmPchPcrLib/PchPcrLib.c b/Silicon/Intel/LewisburgPkg/Library/PeiDxeSmmPchPcrLib/PchPcrLib.c
new file mode 100644
index 0000000000..032349bd4e
--- /dev/null
+++ b/Silicon/Intel/LewisburgPkg/Library/PeiDxeSmmPchPcrLib/PchPcrLib.c
@@ -0,0 +1,459 @@
+/** @file
+
+Copyright (c) 2018, Intel Corporation. All rights reserved.<BR>
+This program and the accompanying materials are licensed and made available under
+the terms and conditions of the BSD License that accompanies this distribution.
+The full text of the license may be found at
+http://opensource.org/licenses/bsd-license.php.
+
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+**/
+
+#include <Base.h>
+#include <Uefi/UefiBaseType.h>
+#include <Library/IoLib.h>
+#include <Library/DebugLib.h>
+#include <Library/BaseLib.h>
+#include <Library/MmPciBaseLib.h>
+#include <PchAccess.h>
+#include <Library/PchInfoLib.h>
+
+/**
+ Read PCR register. (This is internal function)
+ It returns PCR register and size in 1byte/2bytes/4bytes.
+ The Offset should not exceed 0xFFFF and must be aligned with size.
+
+ @param[in] Pid Port ID
+ @param[in] Offset Register offset of this Port ID
+ @param[in] Size Size for read. Must be 1 or 2 or 4.
+ @param[out] OutData Buffer of Output Data. Must be the same size as Size parameter.
+
+ @retval EFI_SUCCESS Successfully completed.
+ @retval EFI_INVALID_PARAMETER Invalid offset passed.
+**/
+STATIC
+EFI_STATUS
+PchPcrRead (
+ IN PCH_SBI_PID Pid,
+ IN UINT16 Offset,
+ IN UINTN Size,
+ OUT UINT32 *OutData
+ )
+{
+ if ((Offset & (Size - 1)) != 0) {
+ DEBUG ((DEBUG_ERROR, "PchPcrRead error. Invalid Offset: %x Size: %x", Offset, Size));
+ ASSERT (FALSE);
+ return EFI_INVALID_PARAMETER;
+ }
+ //
+ // @todo SKL PCH: check PID that not expected to use this routine, such as CAM_FLIS, CSME0
+ //
+
+ switch (Size) {
+ case 4:
+ *(UINT32*)OutData = MmioRead32 (PCH_PCR_ADDRESS (Pid, Offset));
+ break;
+ case 2:
+ *(UINT16*)OutData = MmioRead16 (PCH_PCR_ADDRESS (Pid, Offset));
+ break;
+ case 1:
+ *(UINT8*) OutData = MmioRead8 (PCH_PCR_ADDRESS (Pid, Offset));
+ break;
+ default:
+ break;
+ }
+ return EFI_SUCCESS;
+}
+
+/**
+ Read PCR register.
+ It returns PCR register and size in 4bytes.
+ The Offset should not exceed 0xFFFF and must be aligned with size.
+
+ @param[in] Pid Port ID
+ @param[in] Offset Register offset of this Port ID
+ @param[out] OutData Buffer of Output Data. Must be the same size as Size parameter.
+
+ @retval EFI_SUCCESS Successfully completed.
+ @retval EFI_INVALID_PARAMETER Invalid offset passed.
+**/
+EFI_STATUS
+PchPcrRead32 (
+ IN PCH_SBI_PID Pid,
+ IN UINT16 Offset,
+ OUT UINT32 *OutData
+ )
+{
+ return PchPcrRead (Pid, Offset, 4, (UINT32*) OutData);
+}
+
+/**
+ Read PCR register.
+ It returns PCR register and size in 2bytes.
+ The Offset should not exceed 0xFFFF and must be aligned with size.
+
+ @param[in] Pid Port ID
+ @param[in] Offset Register offset of this Port ID
+ @param[out] OutData Buffer of Output Data. Must be the same size as Size parameter.
+
+ @retval EFI_SUCCESS Successfully completed.
+ @retval EFI_INVALID_PARAMETER Invalid offset passed.
+**/
+EFI_STATUS
+PchPcrRead16 (
+ IN PCH_SBI_PID Pid,
+ IN UINT16 Offset,
+ OUT UINT16 *OutData
+ )
+{
+ return PchPcrRead (Pid, Offset, 2, (UINT32*) OutData);
+}
+
+/**
+ Read PCR register.
+ It returns PCR register and size in 1bytes.
+ The Offset should not exceed 0xFFFF and must be aligned with size.
+
+ @param[in] Pid Port ID
+ @param[in] Offset Register offset of this Port ID
+ @param[out] OutData Buffer of Output Data. Must be the same size as Size parameter.
+
+ @retval EFI_SUCCESS Successfully completed.
+ @retval EFI_INVALID_PARAMETER Invalid offset passed.
+**/
+EFI_STATUS
+PchPcrRead8 (
+ IN PCH_SBI_PID Pid,
+ IN UINT16 Offset,
+ OUT UINT8 *OutData
+ )
+{
+ return PchPcrRead (Pid, Offset, 1, (UINT32*) OutData);
+}
+
+BOOLEAN
+PchPcrWriteMmioCheck (
+ IN PCH_SBI_PID Pid,
+ IN UINT16 Offset
+ )
+{
+DEBUG_CODE_BEGIN();
+ PCH_SERIES PchSeries;
+
+ PchSeries = GetPchSeries ();
+ //
+ // 1. USB2 AFE register must use SBI method
+ //
+
+ //
+ // 2. GPIO unlock register field must use SBI method
+ //
+ if (Pid == PID_GPIOCOM0) {
+ if (((PchSeries == PchLp) &&
+ ((Offset == R_PCH_LP_PCR_GPIO_GPP_A_PADCFGLOCK) ||
+ (Offset == R_PCH_LP_PCR_GPIO_GPP_A_PADCFGLOCKTX) ||
+ (Offset == R_PCH_LP_PCR_GPIO_GPP_B_PADCFGLOCK) ||
+ (Offset == R_PCH_LP_PCR_GPIO_GPP_B_PADCFGLOCKTX))) ||
+ ((PchSeries == PchH) &&
+ ((Offset == R_PCH_H_PCR_GPIO_GPP_A_PADCFGLOCK) ||
+ (Offset == R_PCH_H_PCR_GPIO_GPP_A_PADCFGLOCKTX) ||
+ (Offset == R_PCH_H_PCR_GPIO_GPP_B_PADCFGLOCK) ||
+ (Offset == R_PCH_H_PCR_GPIO_GPP_B_PADCFGLOCKTX))))
+ {
+ return FALSE;
+ }
+ }
+ if (Pid == PID_GPIOCOM1) {
+ if (((PchSeries == PchLp) &&
+ ((Offset == R_PCH_LP_PCR_GPIO_GPP_C_PADCFGLOCK) ||
+ (Offset == R_PCH_LP_PCR_GPIO_GPP_C_PADCFGLOCKTX) ||
+ (Offset == R_PCH_LP_PCR_GPIO_GPP_D_PADCFGLOCK) ||
+ (Offset == R_PCH_LP_PCR_GPIO_GPP_D_PADCFGLOCKTX) ||
+ (Offset == R_PCH_LP_PCR_GPIO_GPP_E_PADCFGLOCK) ||
+ (Offset == R_PCH_LP_PCR_GPIO_GPP_E_PADCFGLOCKTX))) ||
+ ((PchSeries == PchH) &&
+ ((Offset == R_PCH_H_PCR_GPIO_GPP_C_PADCFGLOCK) ||
+ (Offset == R_PCH_H_PCR_GPIO_GPP_C_PADCFGLOCKTX) ||
+ (Offset == R_PCH_H_PCR_GPIO_GPP_D_PADCFGLOCK) ||
+ (Offset == R_PCH_H_PCR_GPIO_GPP_D_PADCFGLOCKTX) ||
+ (Offset == R_PCH_H_PCR_GPIO_GPP_E_PADCFGLOCK) ||
+ (Offset == R_PCH_H_PCR_GPIO_GPP_E_PADCFGLOCKTX) ||
+ (Offset == R_PCH_H_PCR_GPIO_GPP_F_PADCFGLOCK) ||
+ (Offset == R_PCH_H_PCR_GPIO_GPP_F_PADCFGLOCKTX) ||
+ (Offset == R_PCH_H_PCR_GPIO_GPP_G_PADCFGLOCK) ||
+ (Offset == R_PCH_H_PCR_GPIO_GPP_G_PADCFGLOCKTX) ||
+ (Offset == R_PCH_H_PCR_GPIO_GPP_H_PADCFGLOCK) ||
+ (Offset == R_PCH_H_PCR_GPIO_GPP_H_PADCFGLOCKTX))))
+ {
+ return FALSE;
+ }
+ }
+ if (Pid == PID_GPIOCOM2) {
+ if (((PchSeries == PchLp) &&
+ ((Offset == R_PCH_LP_PCR_GPIO_GPD_PADCFGLOCK) ||
+ (Offset == R_PCH_LP_PCR_GPIO_GPD_PADCFGLOCKTX))) ||
+ ((PchSeries == PchH) &&
+ ((Offset == R_PCH_H_PCR_GPIO_GPD_PADCFGLOCK) ||
+ (Offset == R_PCH_H_PCR_GPIO_GPD_PADCFGLOCKTX))))
+ {
+ return FALSE;
+ }
+ }
+ if (Pid == PID_GPIOCOM3) {
+ if (((PchSeries == PchLp) &&
+ ((Offset == R_PCH_LP_PCR_GPIO_GPP_F_PADCFGLOCK) ||
+ (Offset == R_PCH_LP_PCR_GPIO_GPP_F_PADCFGLOCKTX) ||
+ (Offset == R_PCH_LP_PCR_GPIO_GPP_G_PADCFGLOCK) ||
+ (Offset == R_PCH_LP_PCR_GPIO_GPP_G_PADCFGLOCKTX))) ||
+ ((PchSeries == PchH) &&
+ ((Offset == R_PCH_H_PCR_GPIO_GPP_I_PADCFGLOCK) ||
+ (Offset == R_PCH_H_PCR_GPIO_GPP_I_PADCFGLOCKTX))))
+ {
+ return FALSE;
+ }
+ }
+ //
+ // 3. CIO2 FLIS regsiter must use SBI method
+ //
+
+ //
+ // 4. CSME0 based PCR should use the SBI method due to the FID requirement
+ //
+ if (Pid == PID_CSME0) {
+ return FALSE;
+ }
+DEBUG_CODE_END();
+ return TRUE;
+
+}
+
+/**
+ Write PCR register. (This is internal function)
+ It programs PCR register and size in 1byte/2bytes/4bytes.
+ The Offset should not exceed 0xFFFF and must be aligned with size.
+
+ @param[in] Pid Port ID
+ @param[in] Offset Register offset of Port ID.
+ @param[in] Size Size for read. Must be 1 or 2 or 4.
+ @param[in] AndData AND Data. Must be the same size as Size parameter.
+ @param[in] OrData OR Data. Must be the same size as Size parameter.
+
+ @retval EFI_SUCCESS Successfully completed.
+ @retval EFI_INVALID_PARAMETER Invalid offset passed.
+**/
+STATIC
+EFI_STATUS
+PchPcrWrite (
+ IN PCH_SBI_PID Pid,
+ IN UINT16 Offset,
+ IN UINTN Size,
+ IN UINT32 InData
+ )
+{
+ if ((Offset & (Size - 1)) != 0) {
+ DEBUG ((DEBUG_ERROR, "PchPcrWrite error. Invalid Offset: %x Size: %x", Offset, Size));
+ ASSERT (FALSE);
+ return EFI_INVALID_PARAMETER;
+ }
+DEBUG_CODE_BEGIN();
+ if (!PchPcrWriteMmioCheck (Pid, Offset)) {
+ DEBUG ((DEBUG_ERROR, "PchPcrWrite error. Pid: %x Offset: %x should access through SBI interface", Pid, Offset));
+ ASSERT (FALSE);
+ return EFI_INVALID_PARAMETER;
+ }
+DEBUG_CODE_END();
+
+ //
+ // Write the PCR register with provided data
+ // Then read back PCR register to prevent from back to back write.
+ //
+ switch (Size) {
+ case 4:
+ MmioWrite32 (PCH_PCR_ADDRESS (Pid, Offset), (UINT32)InData);
+ break;
+ case 2:
+ MmioWrite16 (PCH_PCR_ADDRESS (Pid, Offset), (UINT16)InData);
+ break;
+ case 1:
+ MmioWrite8 (PCH_PCR_ADDRESS (Pid, Offset), (UINT8) InData);
+ break;
+ default:
+ break;
+ }
+ MmioRead32 (PCH_PCR_ADDRESS (PID_LPC, R_PCH_PCR_LPC_GCFD));
+
+ return EFI_SUCCESS;
+}
+
+/**
+ Write PCR register.
+ It programs PCR register and size in 4bytes.
+ The Offset should not exceed 0xFFFF and must be aligned with size.
+
+ @param[in] Pid Port ID
+ @param[in] Offset Register offset of Port ID.
+ @param[in] InData Input Data. Must be the same size as Size parameter.
+
+ @retval EFI_SUCCESS Successfully completed.
+ @retval EFI_INVALID_PARAMETER Invalid offset passed.
+**/
+EFI_STATUS
+PchPcrWrite32 (
+ IN PCH_SBI_PID Pid,
+ IN UINT16 Offset,
+ IN UINT32 InData
+ )
+{
+ return PchPcrWrite (Pid, Offset, 4, InData);
+}
+
+/**
+ Write PCR register.
+ It programs PCR register and size in 2bytes.
+ The Offset should not exceed 0xFFFF and must be aligned with size.
+
+ @param[in] Pid Port ID
+ @param[in] Offset Register offset of Port ID.
+ @param[in] InData Input Data. Must be the same size as Size parameter.
+
+ @retval EFI_SUCCESS Successfully completed.
+ @retval EFI_INVALID_PARAMETER Invalid offset passed.
+**/
+EFI_STATUS
+PchPcrWrite16 (
+ IN PCH_SBI_PID Pid,
+ IN UINT16 Offset,
+ IN UINT16 InData
+ )
+{
+ return PchPcrWrite (Pid, Offset, 2, InData);
+}
+
+/**
+ Write PCR register.
+ It programs PCR register and size in 1bytes.
+ The Offset should not exceed 0xFFFF and must be aligned with size.
+
+ @param[in] Pid Port ID
+ @param[in] Offset Register offset of Port ID.
+ @param[in] InData Input Data. Must be the same size as Size parameter.
+
+ @retval EFI_SUCCESS Successfully completed.
+ @retval EFI_INVALID_PARAMETER Invalid offset passed.
+**/
+EFI_STATUS
+PchPcrWrite8 (
+ IN PCH_SBI_PID Pid,
+ IN UINT16 Offset,
+ IN UINT8 InData
+ )
+{
+ return PchPcrWrite (Pid, Offset, 1, InData);
+}
+
+/**
+ Write PCR register.
+ It programs PCR register and size in 4bytes.
+ The Offset should not exceed 0xFFFF and must be aligned with size.
+
+ @param[in] Pid Port ID
+ @param[in] Offset Register offset of Port ID.
+ @param[in] AndData AND Data. Must be the same size as Size parameter.
+ @param[in] OrData OR Data. Must be the same size as Size parameter.
+
+ @retval EFI_SUCCESS Successfully completed.
+ @retval EFI_INVALID_PARAMETER Invalid offset passed.
+**/
+EFI_STATUS
+PchPcrAndThenOr32 (
+ IN PCH_SBI_PID Pid,
+ IN UINT16 Offset,
+ IN UINT32 AndData,
+ IN UINT32 OrData
+ )
+{
+ EFI_STATUS Status;
+ UINT32 Data32;
+
+ Data32 = 0x00;
+ Status = PchPcrRead (Pid, Offset, 4, &Data32);
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+ Data32 &= AndData;
+ Data32 |= OrData;
+ Status = PchPcrWrite (Pid, Offset, 4, Data32);
+ return Status;
+}
+
+/**
+ Write PCR register.
+ It programs PCR register and size in 2bytes.
+ The Offset should not exceed 0xFFFF and must be aligned with size.
+
+ @param[in] Pid Port ID
+ @param[in] Offset Register offset of Port ID.
+ @param[in] AndData AND Data. Must be the same size as Size parameter.
+ @param[in] OrData OR Data. Must be the same size as Size parameter.
+
+ @retval EFI_SUCCESS Successfully completed.
+ @retval EFI_INVALID_PARAMETER Invalid offset passed.
+**/
+EFI_STATUS
+PchPcrAndThenOr16 (
+ IN PCH_SBI_PID Pid,
+ IN UINT16 Offset,
+ IN UINT16 AndData,
+ IN UINT16 OrData
+ )
+{
+ EFI_STATUS Status;
+ UINT16 Data16;
+
+ Data16 = 0x00;
+ Status = PchPcrRead (Pid, Offset, 2, (UINT32*) &Data16);
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+ Data16 &= AndData;
+ Data16 |= OrData;
+ Status = PchPcrWrite (Pid, Offset, 2, Data16);
+ return Status;
+}
+
+/**
+ Write PCR register.
+ It programs PCR register and size in 1bytes.
+ The Offset should not exceed 0xFFFF and must be aligned with size.
+
+ @param[in] Pid Port ID
+ @param[in] Offset Register offset of Port ID.
+ @param[in] AndData AND Data. Must be the same size as Size parameter.
+ @param[in] OrData OR Data. Must be the same size as Size parameter.
+
+ @retval EFI_SUCCESS Successfully completed.
+ @retval EFI_INVALID_PARAMETER Invalid offset passed.
+**/
+EFI_STATUS
+PchPcrAndThenOr8 (
+ IN PCH_SBI_PID Pid,
+ IN UINT16 Offset,
+ IN UINT8 AndData,
+ IN UINT8 OrData
+ )
+{
+ EFI_STATUS Status;
+ UINT8 Data8;
+
+ Status = PchPcrRead (Pid, Offset, 1, (UINT32*) &Data8);
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+ Data8 &= AndData;
+ Data8 |= OrData;
+ Status = PchPcrWrite (Pid, Offset, 1, Data8);
+ return Status;
+}
+