hc
2024-03-22 a0752693d998599af469473b8dc239ef973a012f
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
/** @file
  SPI library for abstraction of SPI HW registers accesses
 
  Copyright (c) 2021, Intel Corporation. All rights reserved.<BR>
  SPDX-License-Identifier: BSD-2-Clause-Patent
**/
 
#include <Base.h>
#include <Uefi/UefiBaseType.h>
#include <Library/SpiAccessLib.h>
#include <Library/PciSegmentLib.h>
#include <Library/DebugLib.h>
#include <Library/S3BootScriptLib.h>
#include <Register/SpiRegs.h>
#include <Register/PchRegs.h>
#include <Register/PchPcrRegs.h>
#include <Library/PchPciBdfLib.h>
 
/**
  Disable EISS (Enable InSMM.STS)
**/
VOID
SpiDisableEiss (
  VOID
  )
{
  UINT64  SpiBaseAddress;
  SpiBaseAddress = SpiPciCfgBase ();
 
  ASSERT ((PciSegmentRead8 (SpiBaseAddress + R_SPI_CFG_BC) & B_SPI_CFG_BC_LE) == 0);
 
  PciSegmentAnd8 (SpiBaseAddress + R_SPI_CFG_BC, (UINT8) ~(B_SPI_CFG_BC_EISS));
}
 
/**
  Configure BiosLockEnable bit and BiosInterfaceLock bit according to policy setting.
 
  @param[in] BiosLockEnable     Policy for BiosLockEnable bit programming
  @param[in] BiosInterfaceLock  Policy for BiosInterfaceLock bit programming
 
**/
VOID
SpiBiosLockEnableAndBiosInterfaceLockWithS3BootScript (
  IN BOOLEAN  BiosLockEnable,
  IN BOOLEAN  BiosInterfaceLock
  )
{
  UINT64                   SpiBaseAddress;
  UINT8                    SpiData8;
 
  if (!BiosLockEnable && !BiosInterfaceLock) {
    return;
  }
 
  SpiBaseAddress = SpiPciCfgBase ();
 
  ///
  /// PCH BIOS Spec Flash Security Recommendation
  ///
  /// BIOS needs to enable the BIOS Lock Enable (BLE) feature of the PCH by setting
  /// SPI/eSPI/LPC PCI offset DCh[1] = 1b.
  /// When this bit is set, attempts to write the Write Protect Disable (WPD) bit
  /// in PCH will cause a SMI which will allow the BIOS to verify that the write is
  /// from a valid source.
  /// Remember that BIOS needs to set SPI/LPC/eSPI PCI Offset DC [0] = 0b to enable
  /// BIOS region protection before exiting the SMI handler.
  /// Also, TCO_EN bit needs to be set (SMI_EN Register, ABASE + 30h[13] = 1b) to keep
  /// BLE feature enabled after booting to the OS.
  /// Intel requires that BIOS enables the Lock Enable (LE) feature of the PCH to
  /// ensure SMM protection of flash.
  /// RC installs a default SMI handler that clears WPD.
  /// There could be additional SMI handler to log such attempt if desired.
  ///
  /// BIOS needs to enable the "Enable in SMM.STS" (EISS) feature of the PCH by setting
  /// SPI PCI offset DCh[5] = 1b for SPI or setting eSPI PCI offset DCh[5] = 1b for eSPI.
  /// When this bit is set, the BIOS region is not writable until SMM sets the InSMM.STS bit,
  /// to ensure BIOS can only be modified from SMM. Please refer to CPU BWG for more details
  /// on InSMM.STS bit.
  /// Intel requires that BIOS enables the Lock Enable (LE) feature of the PCH to ensure
  /// SMM protection of flash.
  /// SPI PCI offset DCh[1] = 1b for SPI or setting eSPI PCI offset DCh[1] = 1b for eSPI.
  /// When this bit is set, EISS is locked down.
  ///
  SpiData8 = 0;
  if (BiosLockEnable) {
    SpiData8 |= B_SPI_CFG_BC_EISS | B_SPI_CFG_BC_LE;
  }
  ///
  /// BIOS also needs to set the BIOS Interface Lock Down bit in multiple locations
  /// (PCR[DMI] + 274Ch[0], LPC/eSPI PCI offset DCh[7] and SPI PCI offset DCh[7]).
  /// (done in PchInit/Dxe/PchInit.c by PchDmiSetBiosLockDownWithS3BootScript ()) for PCR[DMI] 274Ch)
  /// Setting these bits will prevent writes to the Top Swap bit (under their respective locations)
  /// and the Boot BIOS Straps. Enabling this bit will mitigate malicious software
  /// attempts to replace the system BIOS option ROM with its own code.
  ///
  if (BiosInterfaceLock) {
    SpiData8 |= B_SPI_CFG_BC_BILD;
  }
 
  PciSegmentOr8 (SpiBaseAddress + R_SPI_CFG_BC, SpiData8);
  S3BootScriptSaveMemWrite (
    S3BootScriptWidthUint8,
    PcdGet64 (PcdPciExpressBaseAddress) + SpiBaseAddress + R_SPI_CFG_BC,
    1,
    (VOID *) (UINTN) (PcdGet64 (PcdPciExpressBaseAddress) + SpiBaseAddress + R_SPI_CFG_BC)
    );
  //
  // Reads back for posted write to take effect
  //
  SpiData8 = PciSegmentRead8 (SpiBaseAddress + R_SPI_CFG_BC);
  S3BootScriptSaveMemPoll  (
    S3BootScriptWidthUint8,
    PcdGet64 (PcdPciExpressBaseAddress) + SpiBaseAddress + R_SPI_CFG_BC,
    &SpiData8,
    &SpiData8,
    1,
    1
    );
}
 
/**
  Clears BIOS Write Protect Disable bit
**/
VOID
SpiClearBiosWriteProtectDisable (
  VOID
  )
{
  //
  // Disable BIOSWE bit to protect BIOS
  //
  PciSegmentAnd8 (SpiPciCfgBase () + R_SPI_CFG_BC, (UINT8) ~B_SPI_CFG_BC_WPD);
}