]> git.proxmox.com Git - mirror_edk2.git/blame - UefiPayloadPkg/SmmControlRuntimeDxe/SmmControlRuntimeDxe.c
OvmfPkg/PlatformPei: set PcdConfidentialComputingAttr when SEV is active
[mirror_edk2.git] / UefiPayloadPkg / SmmControlRuntimeDxe / SmmControlRuntimeDxe.c
CommitLineData
e7e8ea27
GD
1/** @file\r
2 This module produces the SMM Control2 Protocol\r
3\r
4 Copyright (c) 2021, Intel Corporation. All rights reserved.<BR>\r
5 SPDX-License-Identifier: BSD-2-Clause-Patent\r
6\r
7**/\r
8\r
9#include <PiDxe.h>\r
10#include <Protocol/SmmControl2.h>\r
11#include <Library/DebugLib.h>\r
12#include <Library/UefiBootServicesTableLib.h>\r
13#include <Library/IoLib.h>\r
14#include <Library/HobLib.h>\r
15#include <Library/UefiRuntimeLib.h>\r
16#include <Library/BaseMemoryLib.h>\r
17#include <Guid/SmmRegisterInfoGuid.h>\r
18\r
e5efcf8b
MK
19#define SMM_DATA_PORT 0xB3\r
20#define SMM_CONTROL_PORT 0xB2\r
e7e8ea27
GD
21\r
22typedef struct {\r
e5efcf8b
MK
23 UINT8 GblBitOffset;\r
24 UINT8 ApmBitOffset;\r
25 UINT32 Address;\r
e7e8ea27
GD
26} SMM_CONTROL2_REG;\r
27\r
e5efcf8b 28SMM_CONTROL2_REG mSmiCtrlReg;\r
e7e8ea27
GD
29\r
30/**\r
31 Invokes SMI activation from either the preboot or runtime environment.\r
32\r
33 This function generates an SMI.\r
34\r
35 @param[in] This The EFI_SMM_CONTROL2_PROTOCOL instance.\r
36 @param[in,out] CommandPort The value written to the command port.\r
37 @param[in,out] DataPort The value written to the data port.\r
38 @param[in] Periodic Optional mechanism to engender a periodic stream.\r
39 @param[in] ActivationInterval Optional parameter to repeat at this period one\r
40 time or, if the Periodic Boolean is set, periodically.\r
41\r
42 @retval EFI_SUCCESS The SMI has been engendered.\r
43 @retval EFI_DEVICE_ERROR The timing is unsupported.\r
44 @retval EFI_INVALID_PARAMETER The activation period is unsupported.\r
45 @retval EFI_INVALID_PARAMETER The last periodic activation has not been cleared.\r
46 @retval EFI_NOT_STARTED The MM base service has not been initialized.\r
47**/\r
48EFI_STATUS\r
49EFIAPI\r
50Activate (\r
e5efcf8b
MK
51 IN CONST EFI_SMM_CONTROL2_PROTOCOL *This,\r
52 IN OUT UINT8 *CommandPort OPTIONAL,\r
53 IN OUT UINT8 *DataPort OPTIONAL,\r
54 IN BOOLEAN Periodic OPTIONAL,\r
55 IN EFI_SMM_PERIOD ActivationInterval OPTIONAL\r
e7e8ea27
GD
56 )\r
57{\r
e5efcf8b
MK
58 UINT32 SmiEn;\r
59 UINT32 SmiEnableBits;\r
e7e8ea27
GD
60\r
61 if (Periodic) {\r
62 return EFI_INVALID_PARAMETER;\r
63 }\r
64\r
65 SmiEn = IoRead32 (mSmiCtrlReg.Address);\r
66 SmiEnableBits = (1 << mSmiCtrlReg.GblBitOffset) | (1 << mSmiCtrlReg.ApmBitOffset);\r
67 if ((SmiEn & SmiEnableBits) != SmiEnableBits) {\r
68 //\r
69 // Set the "global SMI enable" bit and APM bit\r
70 //\r
71 IoWrite32 (mSmiCtrlReg.Address, SmiEn | SmiEnableBits);\r
72 }\r
73\r
e5efcf8b 74 IoWrite8 (SMM_DATA_PORT, DataPort == NULL ? 0 : *DataPort);\r
e7e8ea27
GD
75 IoWrite8 (SMM_CONTROL_PORT, CommandPort == NULL ? 0 : *CommandPort);\r
76 return EFI_SUCCESS;\r
77}\r
78\r
79/**\r
80 Clears an SMI.\r
81\r
82 @param This Pointer to an instance of EFI_SMM_CONTROL2_PROTOCOL\r
83 @param Periodic TRUE to indicate a periodical SMI\r
84\r
85 @return Return value from SmmClear ()\r
86\r
87**/\r
88EFI_STATUS\r
89EFIAPI\r
90Deactivate (\r
e5efcf8b
MK
91 IN CONST EFI_SMM_CONTROL2_PROTOCOL *This,\r
92 IN BOOLEAN Periodic\r
e7e8ea27
GD
93 )\r
94{\r
95 if (Periodic) {\r
96 return EFI_INVALID_PARAMETER;\r
97 }\r
98\r
99 //\r
100 // Temporarily do nothing here\r
101 //\r
102 return EFI_SUCCESS;\r
103}\r
104\r
105///\r
106/// SMM COntrol2 Protocol instance\r
107///\r
e5efcf8b 108EFI_SMM_CONTROL2_PROTOCOL mSmmControl2 = {\r
e7e8ea27
GD
109 Activate,\r
110 Deactivate,\r
111 0\r
112};\r
113\r
114/**\r
115 Get specified SMI register based on given register ID\r
116\r
117 @param[in] SmmRegister SMI related register array from bootloader\r
118 @param[in] Id The register ID to get.\r
119\r
120 @retval NULL The register is not found or the format is not expected.\r
121 @return smi register\r
122\r
123**/\r
124PLD_GENERIC_REGISTER *\r
125GetSmmCtrlRegById (\r
e5efcf8b
MK
126 IN PLD_SMM_REGISTERS *SmmRegister,\r
127 IN UINT32 Id\r
e7e8ea27
GD
128 )\r
129{\r
e5efcf8b
MK
130 UINT32 Index;\r
131 PLD_GENERIC_REGISTER *PldReg;\r
e7e8ea27
GD
132\r
133 PldReg = NULL;\r
134 for (Index = 0; Index < SmmRegister->Count; Index++) {\r
135 if (SmmRegister->Registers[Index].Id == Id) {\r
136 PldReg = &SmmRegister->Registers[Index];\r
137 break;\r
138 }\r
139 }\r
140\r
141 if (PldReg == NULL) {\r
142 DEBUG ((DEBUG_INFO, "Register %d not found.\n", Id));\r
143 return NULL;\r
144 }\r
145\r
146 //\r
147 // Checking the register if it is expected.\r
148 //\r
149 if ((PldReg->Address.AccessSize != EFI_ACPI_3_0_DWORD) ||\r
150 (PldReg->Address.Address == 0) ||\r
151 (PldReg->Address.RegisterBitWidth != 1) ||\r
152 (PldReg->Address.AddressSpaceId != EFI_ACPI_3_0_SYSTEM_IO) ||\r
e5efcf8b
MK
153 (PldReg->Value != 1))\r
154 {\r
e7e8ea27
GD
155 DEBUG ((DEBUG_INFO, "Unexpected SMM register.\n"));\r
156 DEBUG ((DEBUG_INFO, "AddressSpaceId= 0x%x\n", PldReg->Address.AddressSpaceId));\r
157 DEBUG ((DEBUG_INFO, "RegBitWidth = 0x%x\n", PldReg->Address.RegisterBitWidth));\r
158 DEBUG ((DEBUG_INFO, "RegBitOffset = 0x%x\n", PldReg->Address.RegisterBitOffset));\r
159 DEBUG ((DEBUG_INFO, "AccessSize = 0x%x\n", PldReg->Address.AccessSize));\r
e5efcf8b 160 DEBUG ((DEBUG_INFO, "Address = 0x%lx\n", PldReg->Address.Address));\r
e7e8ea27
GD
161 return NULL;\r
162 }\r
e5efcf8b 163\r
e7e8ea27
GD
164 return PldReg;\r
165}\r
166\r
e7e8ea27
GD
167/**\r
168 Fixup data pointers so that the services can be called in virtual mode.\r
169\r
170 @param[in] Event The event registered.\r
171 @param[in] Context Event context.\r
172\r
173**/\r
174VOID\r
175EFIAPI\r
176SmmControlVirtualAddressChangeEvent (\r
e5efcf8b
MK
177 IN EFI_EVENT Event,\r
178 IN VOID *Context\r
e7e8ea27
GD
179 )\r
180{\r
e5efcf8b
MK
181 EfiConvertPointer (0x0, (VOID **)&(mSmmControl2.Trigger));\r
182 EfiConvertPointer (0x0, (VOID **)&(mSmmControl2.Clear));\r
e7e8ea27
GD
183}\r
184\r
e7e8ea27
GD
185/**\r
186 This function installs EFI_SMM_CONTROL2_PROTOCOL.\r
187\r
188 @param ImageHandle Handle for the image of this driver\r
189 @param SystemTable Pointer to the EFI System Table\r
190\r
191 @retval EFI_UNSUPPORTED There's no Intel ICH on this platform\r
192 @return The status returned from InstallProtocolInterface().\r
193\r
194**/\r
195EFI_STATUS\r
196EFIAPI\r
197SmmControlEntryPoint (\r
e5efcf8b
MK
198 IN EFI_HANDLE ImageHandle,\r
199 IN EFI_SYSTEM_TABLE *SystemTable\r
e7e8ea27
GD
200 )\r
201{\r
e5efcf8b
MK
202 EFI_STATUS Status;\r
203 EFI_HOB_GUID_TYPE *GuidHob;\r
204 PLD_SMM_REGISTERS *SmmRegister;\r
205 PLD_GENERIC_REGISTER *SmiGblEnReg;\r
206 PLD_GENERIC_REGISTER *SmiApmEnReg;\r
207 EFI_EVENT Event;\r
e7e8ea27
GD
208\r
209 GuidHob = GetFirstGuidHob (&gSmmRegisterInfoGuid);\r
210 if (GuidHob == NULL) {\r
211 return EFI_UNSUPPORTED;\r
212 }\r
213\r
e5efcf8b 214 SmmRegister = (PLD_SMM_REGISTERS *)(GET_GUID_HOB_DATA (GuidHob));\r
e7e8ea27
GD
215 SmiGblEnReg = GetSmmCtrlRegById (SmmRegister, REGISTER_ID_SMI_GBL_EN);\r
216 if (SmiGblEnReg == NULL) {\r
217 DEBUG ((DEBUG_ERROR, "SMI global enable reg not found.\n"));\r
218 return EFI_NOT_FOUND;\r
219 }\r
e5efcf8b 220\r
e7e8ea27
GD
221 mSmiCtrlReg.Address = (UINT32)SmiGblEnReg->Address.Address;\r
222 mSmiCtrlReg.GblBitOffset = SmiGblEnReg->Address.RegisterBitOffset;\r
223\r
224 SmiApmEnReg = GetSmmCtrlRegById (SmmRegister, REGISTER_ID_SMI_APM_EN);\r
225 if (SmiApmEnReg == NULL) {\r
226 DEBUG ((DEBUG_ERROR, "SMI APM enable reg not found.\n"));\r
227 return EFI_NOT_FOUND;\r
228 }\r
229\r
230 if (SmiApmEnReg->Address.Address != mSmiCtrlReg.Address) {\r
231 DEBUG ((DEBUG_ERROR, "SMI APM EN and SMI GBL EN are expected to have same register base\n"));\r
232 DEBUG ((DEBUG_ERROR, "APM:0x%x, GBL:0x%x\n", SmiApmEnReg->Address.Address, mSmiCtrlReg.Address));\r
233 return EFI_UNSUPPORTED;\r
234 }\r
e5efcf8b 235\r
e7e8ea27
GD
236 mSmiCtrlReg.ApmBitOffset = SmiApmEnReg->Address.RegisterBitOffset;\r
237\r
238 //\r
239 // Install our protocol interfaces on the device's handle\r
240 //\r
241 Status = gBS->InstallMultipleProtocolInterfaces (\r
242 &ImageHandle,\r
243 &gEfiSmmControl2ProtocolGuid,\r
244 &mSmmControl2,\r
245 NULL\r
246 );\r
247 ASSERT_EFI_ERROR (Status);\r
248\r
249 Status = gBS->CreateEventEx (\r
250 EVT_NOTIFY_SIGNAL,\r
251 TPL_NOTIFY,\r
252 SmmControlVirtualAddressChangeEvent,\r
253 NULL,\r
254 &gEfiEventVirtualAddressChangeGuid,\r
255 &Event\r
256 );\r
257 return Status;\r
258}\r