1 /** @file
2 PCH BIOS Write Protect Driver.
3
4 Copyright (c) 2021, Intel Corporation. All rights reserved.<BR>
5 SPDX-License-Identifier: BSD-2-Clause-Patent
6 **/
7 #include "PchInitSmm.h"
8 #include <Register/PchRegs.h>
9 #include <Register/PchRegsLpc.h>
10 #include <Register/SpiRegs.h>
11 #include <Library/SpiAccessPrivateLib.h>
12 #include <Library/PchPciBdfLib.h>
13
14 //
15 // Global variables
16 //
17 GLOBAL_REMOVE_IF_UNREFERENCED PCH_TCO_SMI_DISPATCH_PROTOCOL *mPchTcoSmiDispatchProtocol;
18 GLOBAL_REMOVE_IF_UNREFERENCED PCH_ESPI_SMI_DISPATCH_PROTOCOL *mEspiSmmDispatchProtocol;
19 GLOBAL_REMOVE_IF_UNREFERENCED UINT64 mLpcRegBase;
20
21 /**
22 This hardware SMI handler will be run every time the BIOS Write Enable bit is set.
23
24 @param[in] DispatchHandle Not used
25 **/
26 VOID
27 EFIAPI
PchSpiBiosWpCallback(IN EFI_HANDLE DispatchHandle)28 PchSpiBiosWpCallback (
29 IN EFI_HANDLE DispatchHandle
30 )
31 {
32 SpiClearBiosWriteProtectDisable ();
33 }
34
35 /**
36 This hardware SMI handler will be run every time the BIOS Write Enable bit is set.
37
38 @param[in] DispatchHandle Not used
39
40 **/
41 VOID
42 EFIAPI
PchLpcBiosWpCallback(IN EFI_HANDLE DispatchHandle)43 PchLpcBiosWpCallback (
44 IN EFI_HANDLE DispatchHandle
45 )
46 {
47 //
48 // Disable BIOSWE bit to protect BIOS
49 //
50 PciSegmentAnd8 ((UINTN) (mLpcRegBase + R_LPC_CFG_BC), (UINT8) ~B_LPC_CFG_BC_WPD);
51 }
52
53 /**
54 Entry point for Pch Bios Write Protect driver.
55
56 @param[in] ImageHandle Image handle of this driver.
57 @param[in] SystemTable Global system service table.
58
59 @retval EFI_SUCCESS Initialization complete.
60 **/
61 EFI_STATUS
62 EFIAPI
InstallPchBiosWriteProtect(IN EFI_HANDLE ImageHandle,IN EFI_SYSTEM_TABLE * SystemTable)63 InstallPchBiosWriteProtect (
64 IN EFI_HANDLE ImageHandle,
65 IN EFI_SYSTEM_TABLE *SystemTable
66 )
67 {
68 EFI_STATUS Status;
69 EFI_HANDLE Handle;
70
71 DEBUG ((DEBUG_INFO, "InstallPchBiosWriteProtect()\n"));
72
73 if (mPchConfigHob->LockDown.BiosLock != TRUE) {
74 return EFI_SUCCESS;
75 }
76
77 mLpcRegBase = LpcPciCfgBase ();
78
79 DEBUG ((DEBUG_INFO, "Installing BIOS Write Protect SMI handler\n"));
80 //
81 // Get the PCH TCO SMM dispatch protocol
82 //
83 mPchTcoSmiDispatchProtocol = NULL;
84 Status = gSmst->SmmLocateProtocol (&gPchTcoSmiDispatchProtocolGuid, NULL, (VOID **) &mPchTcoSmiDispatchProtocol);
85 ASSERT_EFI_ERROR (Status);
86 //
87 // Always register an SPI BiosWp callback function to handle TCO BIOSWR SMI
88 // NOTE: No matter the BIOS resides behind SPI or not, it needs to handle the SPI BIOS WP SMI
89 // to avoid SMI deadloop on SPI WPD write.
90 //
91 Handle = NULL;
92 Status = mPchTcoSmiDispatchProtocol->SpiBiosWpRegister (
93 mPchTcoSmiDispatchProtocol,
94 PchSpiBiosWpCallback,
95 &Handle
96 );
97 ASSERT_EFI_ERROR (Status);
98
99 //
100 // Always register an LPC/eSPI BiosWp callback function to handle TCO BIOSWR SMI
101 // NOTE: No matter the BIOS resides behind LPC/eSPI or not, it needs to handle the BIOS WP SMI
102 // to avoid SMI deadloop on LPC/eSPI WPD write.
103 //
104 if (IsEspiEnabled ()) {
105 //
106 // Get the PCH ESPI SMM dispatch protocol
107 //
108 mEspiSmmDispatchProtocol = NULL;
109 Status = gSmst->SmmLocateProtocol (&gPchEspiSmiDispatchProtocolGuid, NULL, (VOID **) &mEspiSmmDispatchProtocol);
110 ASSERT_EFI_ERROR (Status);
111
112 //
113 // Register an ESpiBiosWp callback function to handle BIOSWR SMI
114 //
115 Handle = NULL;
116 Status = mEspiSmmDispatchProtocol->BiosWrProtectRegister (
117 mEspiSmmDispatchProtocol,
118 PchLpcBiosWpCallback,
119 &Handle
120 );
121 ASSERT_EFI_ERROR (Status);
122 } else {
123 //
124 // Register an LPC BiosWp callback function to handle TCO BIOSWR SMI
125 //
126 Handle = NULL;
127 Status = mPchTcoSmiDispatchProtocol->LpcBiosWpRegister (
128 mPchTcoSmiDispatchProtocol,
129 PchLpcBiosWpCallback,
130 &Handle
131 );
132 ASSERT_EFI_ERROR (Status);
133 }
134
135 return EFI_SUCCESS;
136 }
137
138