]> git.proxmox.com Git - mirror_edk2.git/blame - OvmfPkg/SmmControl2Dxe/SmiFeatures.c
OvmfPkg/Csm/LegacyBiosDxe: Fix Legacy16GetTableAddress call for E820 data
[mirror_edk2.git] / OvmfPkg / SmmControl2Dxe / SmiFeatures.c
CommitLineData
a316d7ac
LE
1/**@file\r
2 Negotiate SMI features with QEMU, and configure UefiCpuPkg/PiSmmCpuDxeSmm\r
3 accordingly.\r
4\r
5 Copyright (C) 2016-2017, Red Hat, Inc.\r
6\r
b26f0cf9 7 SPDX-License-Identifier: BSD-2-Clause-Patent\r
a316d7ac
LE
8**/\r
9\r
10#include <Library/BaseLib.h>\r
11#include <Library/DebugLib.h>\r
12#include <Library/MemoryAllocationLib.h>\r
13#include <Library/PcdLib.h>\r
14#include <Library/QemuFwCfgLib.h>\r
36a6aa6c 15#include <Library/QemuFwCfgS3Lib.h>\r
a316d7ac
LE
16\r
17#include "SmiFeatures.h"\r
18\r
19//\r
20// The following bit value stands for "broadcast SMI" in the\r
21// "etc/smi/supported-features" and "etc/smi/requested-features" fw_cfg files.\r
22//\r
23#define ICH9_LPC_SMI_F_BROADCAST BIT0\r
24\r
25//\r
26// Provides a scratch buffer (allocated in EfiReservedMemoryType type memory)\r
36a6aa6c 27// for the S3 boot script fragment to write to and read from.\r
a316d7ac
LE
28//\r
29#pragma pack (1)\r
36a6aa6c
LE
30typedef union {\r
31 UINT64 Features;\r
32 UINT8 FeaturesOk;\r
a316d7ac
LE
33} SCRATCH_BUFFER;\r
34#pragma pack ()\r
35\r
36//\r
37// These carry the selector keys of the "etc/smi/requested-features" and\r
38// "etc/smi/features-ok" fw_cfg files from NegotiateSmiFeatures() to\r
36a6aa6c 39// AppendFwCfgBootScript().\r
a316d7ac
LE
40//\r
41STATIC FIRMWARE_CONFIG_ITEM mRequestedFeaturesItem;\r
42STATIC FIRMWARE_CONFIG_ITEM mFeaturesOkItem;\r
43\r
44//\r
45// Carries the negotiated SMI features from NegotiateSmiFeatures() to\r
36a6aa6c 46// AppendFwCfgBootScript().\r
a316d7ac
LE
47//\r
48STATIC UINT64 mSmiFeatures;\r
49\r
50/**\r
51 Negotiate SMI features with QEMU.\r
52\r
53 @retval FALSE If SMI feature negotiation is not supported by QEMU. This is\r
54 not an error, it just means that SaveSmiFeatures() should not\r
55 be called.\r
56\r
57 @retval TRUE SMI feature negotiation is supported, and it has completed\r
58 successfully as well. (Failure to negotiate is a fatal error\r
59 and the function never returns in that case.)\r
60**/\r
61BOOLEAN\r
62NegotiateSmiFeatures (\r
63 VOID\r
64 )\r
65{\r
66 FIRMWARE_CONFIG_ITEM SupportedFeaturesItem;\r
67 UINTN SupportedFeaturesSize;\r
68 UINTN RequestedFeaturesSize;\r
69 UINTN FeaturesOkSize;\r
70\r
71 //\r
72 // Look up the fw_cfg files used for feature negotiation. The selector keys\r
73 // of "etc/smi/requested-features" and "etc/smi/features-ok" are saved\r
74 // statically. If the files are missing, then QEMU doesn't support SMI\r
75 // feature negotiation.\r
76 //\r
77 if (RETURN_ERROR (QemuFwCfgFindFile ("etc/smi/supported-features",\r
78 &SupportedFeaturesItem, &SupportedFeaturesSize)) ||\r
79 RETURN_ERROR (QemuFwCfgFindFile ("etc/smi/requested-features",\r
80 &mRequestedFeaturesItem, &RequestedFeaturesSize)) ||\r
81 RETURN_ERROR (QemuFwCfgFindFile ("etc/smi/features-ok",\r
82 &mFeaturesOkItem, &FeaturesOkSize))) {\r
83 DEBUG ((DEBUG_INFO, "%a: SMI feature negotiation unavailable\n",\r
84 __FUNCTION__));\r
85 return FALSE;\r
86 }\r
87\r
88 //\r
89 // If the files are present but their sizes disagree with us, that's a fatal\r
90 // error (we can't trust the behavior of SMIs either way).\r
91 //\r
92 if (SupportedFeaturesSize != sizeof mSmiFeatures ||\r
93 RequestedFeaturesSize != sizeof mSmiFeatures ||\r
94 FeaturesOkSize != sizeof (UINT8)) {\r
95 DEBUG ((DEBUG_ERROR, "%a: size mismatch in feature negotiation\n",\r
96 __FUNCTION__));\r
97 goto FatalError;\r
98 }\r
99\r
100 //\r
101 // Get the features supported by the host.\r
102 //\r
103 QemuFwCfgSelectItem (SupportedFeaturesItem);\r
104 QemuFwCfgReadBytes (sizeof mSmiFeatures, &mSmiFeatures);\r
105\r
106 //\r
107 // We want broadcast SMI and nothing else.\r
108 //\r
109 mSmiFeatures &= ICH9_LPC_SMI_F_BROADCAST;\r
110 QemuFwCfgSelectItem (mRequestedFeaturesItem);\r
111 QemuFwCfgWriteBytes (sizeof mSmiFeatures, &mSmiFeatures);\r
112\r
113 //\r
114 // Invoke feature validation in QEMU. If the selection is accepted, the\r
115 // features will be locked down. If the selection is rejected, feature\r
116 // negotiation remains open; however we don't know what to do in that case,\r
117 // so that's a fatal error.\r
118 //\r
119 QemuFwCfgSelectItem (mFeaturesOkItem);\r
120 if (QemuFwCfgRead8 () != 1) {\r
121 DEBUG ((DEBUG_ERROR, "%a: negotiation failed for feature bitmap 0x%Lx\n",\r
122 __FUNCTION__, mSmiFeatures));\r
123 goto FatalError;\r
124 }\r
125\r
126 if ((mSmiFeatures & ICH9_LPC_SMI_F_BROADCAST) == 0) {\r
127 //\r
128 // If we can't get broadcast SMIs from QEMU, that's acceptable too,\r
129 // although not optimal.\r
130 //\r
131 DEBUG ((DEBUG_INFO, "%a: SMI broadcast unavailable\n", __FUNCTION__));\r
132 } else {\r
133 //\r
134 // Configure the traditional AP sync / SMI delivery mode for\r
135 // PiSmmCpuDxeSmm. Effectively, restore the UefiCpuPkg defaults, from which\r
136 // the original QEMU behavior (i.e., unicast SMI) used to differ.\r
137 //\r
138 if (RETURN_ERROR (PcdSet64S (PcdCpuSmmApSyncTimeout, 1000000)) ||\r
139 RETURN_ERROR (PcdSet8S (PcdCpuSmmSyncMode, 0x00))) {\r
140 DEBUG ((DEBUG_ERROR, "%a: PiSmmCpuDxeSmm PCD configuration failed\n",\r
141 __FUNCTION__));\r
142 goto FatalError;\r
143 }\r
144 DEBUG ((DEBUG_INFO, "%a: using SMI broadcast\n", __FUNCTION__));\r
145 }\r
146\r
147 //\r
148 // Negotiation successful (although we may not have gotten the optimal\r
149 // feature set).\r
150 //\r
151 return TRUE;\r
152\r
153FatalError:\r
154 ASSERT (FALSE);\r
155 CpuDeadLoop ();\r
156 //\r
157 // Keep the compiler happy.\r
158 //\r
159 return FALSE;\r
160}\r
161\r
162/**\r
36a6aa6c 163 FW_CFG_BOOT_SCRIPT_CALLBACK_FUNCTION provided to QemuFwCfgS3Lib.\r
a316d7ac 164**/\r
36a6aa6c 165STATIC\r
a316d7ac 166VOID\r
36a6aa6c
LE
167EFIAPI\r
168AppendFwCfgBootScript (\r
169 IN OUT VOID *Context, OPTIONAL\r
170 IN OUT VOID *ExternalScratchBuffer\r
a316d7ac
LE
171 )\r
172{\r
173 SCRATCH_BUFFER *ScratchBuffer;\r
36a6aa6c 174 RETURN_STATUS Status;\r
a316d7ac 175\r
36a6aa6c 176 ScratchBuffer = ExternalScratchBuffer;\r
a316d7ac
LE
177\r
178 //\r
36a6aa6c 179 // Write the negotiated feature bitmap into "etc/smi/requested-features".\r
a316d7ac 180 //\r
36a6aa6c
LE
181 ScratchBuffer->Features = mSmiFeatures;\r
182 Status = QemuFwCfgS3ScriptWriteBytes (mRequestedFeaturesItem,\r
183 sizeof ScratchBuffer->Features);\r
184 if (RETURN_ERROR (Status)) {\r
a316d7ac
LE
185 goto FatalError;\r
186 }\r
187\r
188 //\r
36a6aa6c
LE
189 // Read back "etc/smi/features-ok". This invokes the feature validation &\r
190 // lockdown. (The validation succeeded at first boot.)\r
a316d7ac 191 //\r
36a6aa6c
LE
192 Status = QemuFwCfgS3ScriptReadBytes (mFeaturesOkItem,\r
193 sizeof ScratchBuffer->FeaturesOk);\r
194 if (RETURN_ERROR (Status)) {\r
a316d7ac
LE
195 goto FatalError;\r
196 }\r
197\r
198 //\r
36a6aa6c
LE
199 // If "etc/smi/features-ok" read as 1, we're good. Otherwise, hang the S3\r
200 // resume process.\r
a316d7ac 201 //\r
36a6aa6c
LE
202 Status = QemuFwCfgS3ScriptCheckValue (&ScratchBuffer->FeaturesOk,\r
203 sizeof ScratchBuffer->FeaturesOk, MAX_UINT8, 1);\r
204 if (RETURN_ERROR (Status)) {\r
a316d7ac
LE
205 goto FatalError;\r
206 }\r
207\r
36a6aa6c
LE
208 DEBUG ((DEBUG_VERBOSE, "%a: SMI feature negotiation boot script saved\n",\r
209 __FUNCTION__));\r
a316d7ac
LE
210 return;\r
211\r
212FatalError:\r
213 ASSERT (FALSE);\r
214 CpuDeadLoop ();\r
215}\r
36a6aa6c
LE
216\r
217\r
218/**\r
219 Append a boot script fragment that will re-select the previously negotiated\r
220 SMI features during S3 resume.\r
221**/\r
222VOID\r
223SaveSmiFeatures (\r
224 VOID\r
225 )\r
226{\r
227 RETURN_STATUS Status;\r
228\r
229 //\r
230 // We are already running at TPL_CALLBACK, on the stack of\r
231 // OnS3SaveStateInstalled(). But that's okay, we can easily queue more\r
232 // notification functions while executing a notification function.\r
233 //\r
234 Status = QemuFwCfgS3CallWhenBootScriptReady (AppendFwCfgBootScript, NULL,\r
235 sizeof (SCRATCH_BUFFER));\r
236 if (RETURN_ERROR (Status)) {\r
237 ASSERT (FALSE);\r
238 CpuDeadLoop ();\r
239 }\r
240}\r