VirtualBox

source: vbox/trunk/src/VBox/Devices/EFI/Firmware/UefiCpuPkg/Library/MmSaveStateLib/IntelMmSaveState.c

Last change on this file was 101291, checked in by vboxsync, 12 months ago

EFI/FirmwareNew: Make edk2-stable202308 build on all supported platforms (using gcc at least, msvc not tested yet), bugref:4643

  • Property svn:eol-style set to native
File size: 18.5 KB
Line 
1/** @file
2Provides services to access SMRAM Save State Map
3
4Copyright (c) 2010 - 2019, Intel Corporation. All rights reserved.<BR>
5Copyright (C) 2023 Advanced Micro Devices, Inc. All rights reserved.<BR>
6SPDX-License-Identifier: BSD-2-Clause-Patent
7
8**/
9
10#include "MmSaveState.h"
11#include <Register/Intel/SmramSaveStateMap.h>
12#include <Register/Intel/Cpuid.h>
13#include <Library/BaseLib.h>
14
15#define INTEL_MM_SAVE_STATE_REGISTER_SMMREVID_INDEX 1
16#define INTEL_MM_SAVE_STATE_REGISTER_IOMISC_INDEX 2
17#define INTEL_MM_SAVE_STATE_REGISTER_IOMEMADDR_INDEX 3
18#define INTEL_MM_SAVE_STATE_REGISTER_MAX_INDEX 4
19
20///
21/// Macro used to simplify the lookup table entries of type CPU_MM_SAVE_STATE_LOOKUP_ENTRY
22///
23#define MM_CPU_OFFSET(Field) OFFSET_OF (SMRAM_SAVE_STATE_MAP, Field)
24
25///
26/// Lookup table used to retrieve the widths and offsets associated with each
27/// supported EFI_MM_SAVE_STATE_REGISTER value
28///
29CONST CPU_MM_SAVE_STATE_LOOKUP_ENTRY mCpuWidthOffset[] = {
30 { 0, 0, 0, 0, 0, FALSE }, // Reserved
31
32 //
33 // Internally defined CPU Save State Registers. Not defined in PI SMM CPU Protocol.
34 //
35 { 4, 4, MM_CPU_OFFSET (x86.SMMRevId), MM_CPU_OFFSET (x64.SMMRevId), 0, FALSE }, // INTEL_MM_SAVE_STATE_REGISTER_SMMREVID_INDEX = 1
36 { 4, 4, MM_CPU_OFFSET (x86.IOMisc), MM_CPU_OFFSET (x64.IOMisc), 0, FALSE }, // INTEL_MM_SAVE_STATE_REGISTER_IOMISC_INDEX = 2
37 { 4, 8, MM_CPU_OFFSET (x86.IOMemAddr), MM_CPU_OFFSET (x64.IOMemAddr), MM_CPU_OFFSET (x64.IOMemAddr) + 4, FALSE }, // INTEL_MM_SAVE_STATE_REGISTER_IOMEMADDR_INDEX = 3
38
39 //
40 // CPU Save State registers defined in PI SMM CPU Protocol.
41 //
42 { 0, 8, 0, MM_CPU_OFFSET (x64.GdtBaseLoDword), MM_CPU_OFFSET (x64.GdtBaseHiDword), FALSE }, // EFI_MM_SAVE_STATE_REGISTER_GDTBASE = 4
43 { 0, 8, 0, MM_CPU_OFFSET (x64.IdtBaseLoDword), MM_CPU_OFFSET (x64.IdtBaseHiDword), FALSE }, // EFI_MM_SAVE_STATE_REGISTER_IDTBASE = 5
44 { 0, 8, 0, MM_CPU_OFFSET (x64.LdtBaseLoDword), MM_CPU_OFFSET (x64.LdtBaseHiDword), FALSE }, // EFI_MM_SAVE_STATE_REGISTER_LDTBASE = 6
45 { 0, 0, 0, 0, 0, FALSE }, // EFI_MM_SAVE_STATE_REGISTER_GDTLIMIT = 7
46 { 0, 0, 0, 0, 0, FALSE }, // EFI_MM_SAVE_STATE_REGISTER_IDTLIMIT = 8
47 { 0, 0, 0, 0, 0, FALSE }, // EFI_MM_SAVE_STATE_REGISTER_LDTLIMIT = 9
48 { 0, 0, 0, 0, 0, FALSE }, // EFI_MM_SAVE_STATE_REGISTER_LDTINFO = 10
49
50 { 4, 4, MM_CPU_OFFSET (x86._ES), MM_CPU_OFFSET (x64._ES), 0, FALSE }, // EFI_MM_SAVE_STATE_REGISTER_ES = 20
51 { 4, 4, MM_CPU_OFFSET (x86._CS), MM_CPU_OFFSET (x64._CS), 0, FALSE }, // EFI_MM_SAVE_STATE_REGISTER_CS = 21
52 { 4, 4, MM_CPU_OFFSET (x86._SS), MM_CPU_OFFSET (x64._SS), 0, FALSE }, // EFI_MM_SAVE_STATE_REGISTER_SS = 22
53 { 4, 4, MM_CPU_OFFSET (x86._DS), MM_CPU_OFFSET (x64._DS), 0, FALSE }, // EFI_MM_SAVE_STATE_REGISTER_DS = 23
54 { 4, 4, MM_CPU_OFFSET (x86._FS), MM_CPU_OFFSET (x64._FS), 0, FALSE }, // EFI_MM_SAVE_STATE_REGISTER_FS = 24
55 { 4, 4, MM_CPU_OFFSET (x86._GS), MM_CPU_OFFSET (x64._GS), 0, FALSE }, // EFI_MM_SAVE_STATE_REGISTER_GS = 25
56 { 0, 4, 0, MM_CPU_OFFSET (x64._LDTR), 0, FALSE }, // EFI_MM_SAVE_STATE_REGISTER_LDTR_SEL = 26
57 { 4, 4, MM_CPU_OFFSET (x86._TR), MM_CPU_OFFSET (x64._TR), 0, FALSE }, // EFI_MM_SAVE_STATE_REGISTER_TR_SEL = 27
58 { 4, 8, MM_CPU_OFFSET (x86._DR7), MM_CPU_OFFSET (x64._DR7), MM_CPU_OFFSET (x64._DR7) + 4, FALSE }, // EFI_MM_SAVE_STATE_REGISTER_DR7 = 28
59 { 4, 8, MM_CPU_OFFSET (x86._DR6), MM_CPU_OFFSET (x64._DR6), MM_CPU_OFFSET (x64._DR6) + 4, FALSE }, // EFI_MM_SAVE_STATE_REGISTER_DR6 = 29
60 { 0, 8, 0, MM_CPU_OFFSET (x64._R8), MM_CPU_OFFSET (x64._R8) + 4, TRUE }, // EFI_MM_SAVE_STATE_REGISTER_R8 = 30
61 { 0, 8, 0, MM_CPU_OFFSET (x64._R9), MM_CPU_OFFSET (x64._R9) + 4, TRUE }, // EFI_MM_SAVE_STATE_REGISTER_R9 = 31
62 { 0, 8, 0, MM_CPU_OFFSET (x64._R10), MM_CPU_OFFSET (x64._R10) + 4, TRUE }, // EFI_MM_SAVE_STATE_REGISTER_R10 = 32
63 { 0, 8, 0, MM_CPU_OFFSET (x64._R11), MM_CPU_OFFSET (x64._R11) + 4, TRUE }, // EFI_MM_SAVE_STATE_REGISTER_R11 = 33
64 { 0, 8, 0, MM_CPU_OFFSET (x64._R12), MM_CPU_OFFSET (x64._R12) + 4, TRUE }, // EFI_MM_SAVE_STATE_REGISTER_R12 = 34
65 { 0, 8, 0, MM_CPU_OFFSET (x64._R13), MM_CPU_OFFSET (x64._R13) + 4, TRUE }, // EFI_MM_SAVE_STATE_REGISTER_R13 = 35
66 { 0, 8, 0, MM_CPU_OFFSET (x64._R14), MM_CPU_OFFSET (x64._R14) + 4, TRUE }, // EFI_MM_SAVE_STATE_REGISTER_R14 = 36
67 { 0, 8, 0, MM_CPU_OFFSET (x64._R15), MM_CPU_OFFSET (x64._R15) + 4, TRUE }, // EFI_MM_SAVE_STATE_REGISTER_R15 = 37
68 { 4, 8, MM_CPU_OFFSET (x86._EAX), MM_CPU_OFFSET (x64._RAX), MM_CPU_OFFSET (x64._RAX) + 4, TRUE }, // EFI_MM_SAVE_STATE_REGISTER_RAX = 38
69 { 4, 8, MM_CPU_OFFSET (x86._EBX), MM_CPU_OFFSET (x64._RBX), MM_CPU_OFFSET (x64._RBX) + 4, TRUE }, // EFI_MM_SAVE_STATE_REGISTER_RBX = 39
70 { 4, 8, MM_CPU_OFFSET (x86._ECX), MM_CPU_OFFSET (x64._RCX), MM_CPU_OFFSET (x64._RCX) + 4, TRUE }, // EFI_MM_SAVE_STATE_REGISTER_RCX = 40
71 { 4, 8, MM_CPU_OFFSET (x86._EDX), MM_CPU_OFFSET (x64._RDX), MM_CPU_OFFSET (x64._RDX) + 4, TRUE }, // EFI_MM_SAVE_STATE_REGISTER_RDX = 41
72 { 4, 8, MM_CPU_OFFSET (x86._ESP), MM_CPU_OFFSET (x64._RSP), MM_CPU_OFFSET (x64._RSP) + 4, TRUE }, // EFI_MM_SAVE_STATE_REGISTER_RSP = 42
73 { 4, 8, MM_CPU_OFFSET (x86._EBP), MM_CPU_OFFSET (x64._RBP), MM_CPU_OFFSET (x64._RBP) + 4, TRUE }, // EFI_MM_SAVE_STATE_REGISTER_RBP = 43
74 { 4, 8, MM_CPU_OFFSET (x86._ESI), MM_CPU_OFFSET (x64._RSI), MM_CPU_OFFSET (x64._RSI) + 4, TRUE }, // EFI_MM_SAVE_STATE_REGISTER_RSI = 44
75 { 4, 8, MM_CPU_OFFSET (x86._EDI), MM_CPU_OFFSET (x64._RDI), MM_CPU_OFFSET (x64._RDI) + 4, TRUE }, // EFI_MM_SAVE_STATE_REGISTER_RDI = 45
76 { 4, 8, MM_CPU_OFFSET (x86._EIP), MM_CPU_OFFSET (x64._RIP), MM_CPU_OFFSET (x64._RIP) + 4, TRUE }, // EFI_MM_SAVE_STATE_REGISTER_RIP = 46
77
78 { 4, 8, MM_CPU_OFFSET (x86._EFLAGS), MM_CPU_OFFSET (x64._RFLAGS), MM_CPU_OFFSET (x64._RFLAGS) + 4, TRUE }, // EFI_MM_SAVE_STATE_REGISTER_RFLAGS = 51
79 { 4, 8, MM_CPU_OFFSET (x86._CR0), MM_CPU_OFFSET (x64._CR0), MM_CPU_OFFSET (x64._CR0) + 4, FALSE }, // EFI_MM_SAVE_STATE_REGISTER_CR0 = 52
80 { 4, 8, MM_CPU_OFFSET (x86._CR3), MM_CPU_OFFSET (x64._CR3), MM_CPU_OFFSET (x64._CR3) + 4, FALSE }, // EFI_MM_SAVE_STATE_REGISTER_CR3 = 53
81 { 0, 4, 0, MM_CPU_OFFSET (x64._CR4), 0, FALSE }, // EFI_MM_SAVE_STATE_REGISTER_CR4 = 54
82};
83
84///
85/// Structure used to build a lookup table for the IOMisc width information
86///
87typedef struct {
88 UINT8 Width;
89 EFI_MM_SAVE_STATE_IO_WIDTH IoWidth;
90} CPU_MM_SAVE_STATE_IO_WIDTH;
91
92///
93/// Lookup table for the IOMisc width information
94///
95STATIC CONST CPU_MM_SAVE_STATE_IO_WIDTH mSmmCpuIoWidth[] = {
96 { 0, EFI_MM_SAVE_STATE_IO_WIDTH_UINT8 }, // Undefined = 0
97 { 1, EFI_MM_SAVE_STATE_IO_WIDTH_UINT8 }, // SMM_IO_LENGTH_BYTE = 1
98 { 2, EFI_MM_SAVE_STATE_IO_WIDTH_UINT16 }, // SMM_IO_LENGTH_WORD = 2
99 { 0, EFI_MM_SAVE_STATE_IO_WIDTH_UINT8 }, // Undefined = 3
100 { 4, EFI_MM_SAVE_STATE_IO_WIDTH_UINT32 }, // SMM_IO_LENGTH_DWORD = 4
101 { 0, EFI_MM_SAVE_STATE_IO_WIDTH_UINT8 }, // Undefined = 5
102 { 0, EFI_MM_SAVE_STATE_IO_WIDTH_UINT8 }, // Undefined = 6
103 { 0, EFI_MM_SAVE_STATE_IO_WIDTH_UINT8 } // Undefined = 7
104};
105
106///
107/// Lookup table for the IOMisc type information
108///
109STATIC CONST EFI_MM_SAVE_STATE_IO_TYPE mSmmCpuIoType[] = {
110 EFI_MM_SAVE_STATE_IO_TYPE_OUTPUT, // SMM_IO_TYPE_OUT_DX = 0
111 EFI_MM_SAVE_STATE_IO_TYPE_INPUT, // SMM_IO_TYPE_IN_DX = 1
112 EFI_MM_SAVE_STATE_IO_TYPE_STRING, // SMM_IO_TYPE_OUTS = 2
113 EFI_MM_SAVE_STATE_IO_TYPE_STRING, // SMM_IO_TYPE_INS = 3
114 (EFI_MM_SAVE_STATE_IO_TYPE)0, // Undefined = 4
115 (EFI_MM_SAVE_STATE_IO_TYPE)0, // Undefined = 5
116 EFI_MM_SAVE_STATE_IO_TYPE_REP_PREFIX, // SMM_IO_TYPE_REP_OUTS = 6
117 EFI_MM_SAVE_STATE_IO_TYPE_REP_PREFIX, // SMM_IO_TYPE_REP_INS = 7
118 EFI_MM_SAVE_STATE_IO_TYPE_OUTPUT, // SMM_IO_TYPE_OUT_IMMEDIATE = 8
119 EFI_MM_SAVE_STATE_IO_TYPE_INPUT, // SMM_IO_TYPE_OUT_IMMEDIATE = 9
120 (EFI_MM_SAVE_STATE_IO_TYPE)0, // Undefined = 10
121 (EFI_MM_SAVE_STATE_IO_TYPE)0, // Undefined = 11
122 (EFI_MM_SAVE_STATE_IO_TYPE)0, // Undefined = 12
123 (EFI_MM_SAVE_STATE_IO_TYPE)0, // Undefined = 13
124 (EFI_MM_SAVE_STATE_IO_TYPE)0, // Undefined = 14
125 (EFI_MM_SAVE_STATE_IO_TYPE)0 // Undefined = 15
126};
127
128/**
129 Read an SMM Save State register on the target processor. If this function
130 returns EFI_UNSUPPORTED, then the caller is responsible for reading the
131 SMM Save Sate register.
132
133 @param[in] CpuIndex The index of the CPU to read the SMM Save State. The
134 value must be between 0 and the NumberOfCpus field in
135 the System Management System Table (SMST).
136 @param[in] Register The SMM Save State register to read.
137 @param[in] Width The number of bytes to read from the CPU save state.
138 @param[out] Buffer Upon return, this holds the CPU register value read
139 from the save state.
140
141 @retval EFI_SUCCESS The register was read from Save State.
142 @retval EFI_INVALID_PARAMTER Buffer is NULL.
143 @retval EFI_UNSUPPORTED This function does not support reading Register.
144 @retval EFI_NOT_FOUND If desired Register not found.
145**/
146EFI_STATUS
147EFIAPI
148MmSaveStateReadRegister (
149 IN UINTN CpuIndex,
150 IN EFI_MM_SAVE_STATE_REGISTER Register,
151 IN UINTN Width,
152 OUT VOID *Buffer
153 )
154{
155 UINT32 SmmRevId;
156 SMRAM_SAVE_STATE_IOMISC IoMisc;
157 EFI_MM_SAVE_STATE_IO_INFO *IoInfo;
158
159 //
160 // Check for special EFI_MM_SAVE_STATE_REGISTER_LMA
161 //
162 if (Register == EFI_MM_SAVE_STATE_REGISTER_LMA) {
163 //
164 // Only byte access is supported for this register
165 //
166 if (Width != 1) {
167 return EFI_INVALID_PARAMETER;
168 }
169
170 *(UINT8 *)Buffer = MmSaveStateGetRegisterLma ();
171
172 return EFI_SUCCESS;
173 }
174
175 //
176 // Check for special EFI_MM_SAVE_STATE_REGISTER_IO
177 //
178 if (Register == EFI_MM_SAVE_STATE_REGISTER_IO) {
179 //
180 // Get SMM Revision ID
181 //
182 MmSaveStateReadRegisterByIndex (CpuIndex, INTEL_MM_SAVE_STATE_REGISTER_SMMREVID_INDEX, sizeof (SmmRevId), &SmmRevId);
183
184 //
185 // See if the CPU supports the IOMisc register in the save state
186 //
187 if (SmmRevId < SMRAM_SAVE_STATE_MIN_REV_ID_IOMISC) {
188 return EFI_NOT_FOUND;
189 }
190
191 //
192 // Get the IOMisc register value
193 //
194 MmSaveStateReadRegisterByIndex (CpuIndex, INTEL_MM_SAVE_STATE_REGISTER_IOMISC_INDEX, sizeof (IoMisc.Uint32), &IoMisc.Uint32);
195
196 //
197 // Check for the SMI_FLAG in IOMisc
198 //
199 if (IoMisc.Bits.SmiFlag == 0) {
200 return EFI_NOT_FOUND;
201 }
202
203 //
204 // Only support IN/OUT, but not INS/OUTS/REP INS/REP OUTS.
205 //
206 if ((mSmmCpuIoType[IoMisc.Bits.Type] != EFI_MM_SAVE_STATE_IO_TYPE_INPUT) &&
207 (mSmmCpuIoType[IoMisc.Bits.Type] != EFI_MM_SAVE_STATE_IO_TYPE_OUTPUT))
208 {
209 return EFI_NOT_FOUND;
210 }
211
212 //
213 // Compute index for the I/O Length and I/O Type lookup tables
214 //
215 if ((mSmmCpuIoWidth[IoMisc.Bits.Length].Width == 0) || (mSmmCpuIoType[IoMisc.Bits.Type] == 0)) {
216 return EFI_NOT_FOUND;
217 }
218
219 //
220 // Make sure the incoming buffer is large enough to hold IoInfo before accessing
221 //
222 if (Width < sizeof (EFI_MM_SAVE_STATE_IO_INFO)) {
223 return EFI_INVALID_PARAMETER;
224 }
225
226 //
227 // Zero the IoInfo structure that will be returned in Buffer
228 //
229 IoInfo = (EFI_MM_SAVE_STATE_IO_INFO *)Buffer;
230 ZeroMem (IoInfo, sizeof (EFI_MM_SAVE_STATE_IO_INFO));
231
232 //
233 // Use lookup tables to help fill in all the fields of the IoInfo structure
234 //
235 IoInfo->IoPort = (UINT16)IoMisc.Bits.Port;
236 IoInfo->IoWidth = mSmmCpuIoWidth[IoMisc.Bits.Length].IoWidth;
237 IoInfo->IoType = mSmmCpuIoType[IoMisc.Bits.Type];
238 MmSaveStateReadRegister (CpuIndex, EFI_MM_SAVE_STATE_REGISTER_RAX, mSmmCpuIoWidth[IoMisc.Bits.Length].Width, &IoInfo->IoData);
239 return EFI_SUCCESS;
240 }
241
242 //
243 // Convert Register to a register lookup table index
244 //
245 return MmSaveStateReadRegisterByIndex (CpuIndex, MmSaveStateGetRegisterIndex (Register, INTEL_MM_SAVE_STATE_REGISTER_MAX_INDEX), Width, Buffer);
246}
247
248/**
249 Writes an SMM Save State register on the target processor. If this function
250 returns EFI_UNSUPPORTED, then the caller is responsible for writing the
251 SMM Save Sate register.
252
253 @param[in] CpuIndex The index of the CPU to write the SMM Save State. The
254 value must be between 0 and the NumberOfCpus field in
255 the System Management System Table (SMST).
256 @param[in] Register The SMM Save State register to write.
257 @param[in] Width The number of bytes to write to the CPU save state.
258 @param[in] Buffer Upon entry, this holds the new CPU register value.
259
260 @retval EFI_SUCCESS The register was written to Save State.
261 @retval EFI_INVALID_PARAMTER Buffer is NULL.
262 @retval EFI_UNSUPPORTED This function does not support writing Register.
263 @retval EFI_NOT_FOUND If desired Register not found.
264**/
265EFI_STATUS
266EFIAPI
267MmSaveStateWriteRegister (
268 IN UINTN CpuIndex,
269 IN EFI_MM_SAVE_STATE_REGISTER Register,
270 IN UINTN Width,
271 IN CONST VOID *Buffer
272 )
273{
274 UINTN RegisterIndex;
275 SMRAM_SAVE_STATE_MAP *CpuSaveState;
276
277 //
278 // Writes to EFI_MM_SAVE_STATE_REGISTER_LMA are ignored
279 //
280 if (Register == EFI_MM_SAVE_STATE_REGISTER_LMA) {
281 return EFI_SUCCESS;
282 }
283
284 //
285 // Writes to EFI_MM_SAVE_STATE_REGISTER_IO are not supported
286 //
287 if (Register == EFI_MM_SAVE_STATE_REGISTER_IO) {
288 return EFI_NOT_FOUND;
289 }
290
291 //
292 // Convert Register to a register lookup table index
293 //
294 RegisterIndex = MmSaveStateGetRegisterIndex (Register, INTEL_MM_SAVE_STATE_REGISTER_MAX_INDEX);
295 if (RegisterIndex == 0) {
296 return EFI_NOT_FOUND;
297 }
298
299 CpuSaveState = gMmst->CpuSaveState[CpuIndex];
300
301 //
302 // Do not write non-writable SaveState, because it will cause exception.
303 //
304 if (!mCpuWidthOffset[RegisterIndex].Writeable) {
305 return EFI_UNSUPPORTED;
306 }
307
308 //
309 // Check CPU mode
310 //
311 if (MmSaveStateGetRegisterLma () == EFI_MM_SAVE_STATE_REGISTER_LMA_32BIT) {
312 //
313 // If 32-bit mode width is zero, then the specified register can not be accessed
314 //
315 if (mCpuWidthOffset[RegisterIndex].Width32 == 0) {
316 return EFI_NOT_FOUND;
317 }
318
319 //
320 // If Width is bigger than the 32-bit mode width, then the specified register can not be accessed
321 //
322 if (Width > mCpuWidthOffset[RegisterIndex].Width32) {
323 return EFI_INVALID_PARAMETER;
324 }
325
326 //
327 // Write SMM State register
328 //
329 ASSERT (CpuSaveState != NULL);
330 CopyMem ((UINT8 *)CpuSaveState + mCpuWidthOffset[RegisterIndex].Offset32, Buffer, Width);
331 } else {
332 //
333 // If 64-bit mode width is zero, then the specified register can not be accessed
334 //
335 if (mCpuWidthOffset[RegisterIndex].Width64 == 0) {
336 return EFI_NOT_FOUND;
337 }
338
339 //
340 // If Width is bigger than the 64-bit mode width, then the specified register can not be accessed
341 //
342 if (Width > mCpuWidthOffset[RegisterIndex].Width64) {
343 return EFI_INVALID_PARAMETER;
344 }
345
346 //
347 // Write at most 4 of the lower bytes of SMM State register
348 //
349 CopyMem ((UINT8 *)CpuSaveState + mCpuWidthOffset[RegisterIndex].Offset64Lo, Buffer, MIN (4, Width));
350 if (Width > 4) {
351 //
352 // Write at most 4 of the upper bytes of SMM State register
353 //
354 CopyMem ((UINT8 *)CpuSaveState + mCpuWidthOffset[RegisterIndex].Offset64Hi, (UINT8 *)Buffer + 4, Width - 4);
355 }
356 }
357
358 return EFI_SUCCESS;
359}
360
361/**
362 Returns LMA value of the Processor.
363
364 @retval UINT8 returns LMA bit value.
365**/
366UINT8
367MmSaveStateGetRegisterLma (
368 VOID
369 )
370{
371 UINT32 RegEax;
372 UINT32 RegEdx;
373 UINTN FamilyId;
374 UINTN ModelId;
375 UINT8 SmmSaveStateRegisterLma;
376
377 //
378 // Retrieve CPU Family
379 //
380 AsmCpuid (CPUID_VERSION_INFO, &RegEax, NULL, NULL, NULL);
381 FamilyId = (RegEax >> 8) & 0xf;
382 ModelId = (RegEax >> 4) & 0xf;
383 if ((FamilyId == 0x06) || (FamilyId == 0x0f)) {
384 ModelId = ModelId | ((RegEax >> 12) & 0xf0);
385 }
386
387 RegEdx = 0;
388 AsmCpuid (CPUID_EXTENDED_FUNCTION, &RegEax, NULL, NULL, NULL);
389 if (RegEax >= CPUID_EXTENDED_CPU_SIG) {
390 AsmCpuid (CPUID_EXTENDED_CPU_SIG, NULL, NULL, NULL, &RegEdx);
391 }
392
393 //
394 // Determine the mode of the CPU at the time an SMI occurs
395 // Intel(R) 64 and IA-32 Architectures Software Developer's Manual
396 // Volume 3C, Section 34.4.1.1
397 //
398 SmmSaveStateRegisterLma = EFI_MM_SAVE_STATE_REGISTER_LMA_32BIT;
399 if ((RegEdx & BIT29) != 0) {
400 SmmSaveStateRegisterLma = EFI_MM_SAVE_STATE_REGISTER_LMA_64BIT;
401 }
402
403 if (FamilyId == 0x06) {
404 if ((ModelId == 0x17) || (ModelId == 0x0f) || (ModelId == 0x1c)) {
405 SmmSaveStateRegisterLma = EFI_MM_SAVE_STATE_REGISTER_LMA_64BIT;
406 }
407 }
408
409 return SmmSaveStateRegisterLma;
410}
Note: See TracBrowser for help on using the repository browser.

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