VirtualBox

source: vbox/trunk/src/VBox/Devices/EFI/Firmware/OvmfPkg/SmmControl2Dxe/SmiFeatures.c@ 85801

Last change on this file since 85801 was 80721, checked in by vboxsync, 6 years ago

Devices/EFI/FirmwareNew: Start upgrade process to edk2-stable201908 (compiles on Windows and works to some extent), bugref:4643

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

© 2025 Oracle Support Privacy / Do Not Sell My Info Terms of Use Trademark Policy Automated Access Etiquette