1 | /** @file
|
---|
2 | Provides common supporting function to access SMRAM Save State Map
|
---|
3 |
|
---|
4 | Copyright (c) 2010 - 2019, Intel Corporation. All rights reserved.<BR>
|
---|
5 | Copyright (C) 2023 Advanced Micro Devices, Inc. All rights reserved.<BR>
|
---|
6 |
|
---|
7 | SPDX-License-Identifier: BSD-2-Clause-Patent
|
---|
8 |
|
---|
9 | **/
|
---|
10 |
|
---|
11 | #include "MmSaveState.h"
|
---|
12 |
|
---|
13 | // Table used by MmSaveStateGetRegisterIndex() to convert an EFI_MM_SAVE_STATE_REGISTER
|
---|
14 | // value to an index into a table of type CPU_MM_SAVE_STATE_LOOKUP_ENTRY
|
---|
15 | CONST CPU_MM_SAVE_STATE_REGISTER_RANGE mCpuRegisterRanges[] = {
|
---|
16 | MM_REGISTER_RANGE (EFI_MM_SAVE_STATE_REGISTER_GDTBASE, EFI_MM_SAVE_STATE_REGISTER_LDTINFO),
|
---|
17 | MM_REGISTER_RANGE (EFI_MM_SAVE_STATE_REGISTER_ES, EFI_MM_SAVE_STATE_REGISTER_RIP),
|
---|
18 | MM_REGISTER_RANGE (EFI_MM_SAVE_STATE_REGISTER_RFLAGS, EFI_MM_SAVE_STATE_REGISTER_CR4),
|
---|
19 | { (EFI_MM_SAVE_STATE_REGISTER)0, (EFI_MM_SAVE_STATE_REGISTER)0, 0}
|
---|
20 | };
|
---|
21 |
|
---|
22 | extern CONST CPU_MM_SAVE_STATE_LOOKUP_ENTRY mCpuWidthOffset[];
|
---|
23 |
|
---|
24 | /**
|
---|
25 | Read information from the CPU save state.
|
---|
26 |
|
---|
27 | @param Register Specifies the CPU register to read form the save state.
|
---|
28 | @param RegOffset Offset for the next register index.
|
---|
29 |
|
---|
30 | @retval 0 Register is not valid
|
---|
31 | @retval >0 Index into mCpuWidthOffset[] associated with Register
|
---|
32 |
|
---|
33 | **/
|
---|
34 | UINTN
|
---|
35 | MmSaveStateGetRegisterIndex (
|
---|
36 | IN EFI_MM_SAVE_STATE_REGISTER Register,
|
---|
37 | IN UINTN RegOffset
|
---|
38 | )
|
---|
39 | {
|
---|
40 | UINTN Index;
|
---|
41 | UINTN Offset;
|
---|
42 |
|
---|
43 | for (Index = 0, Offset = RegOffset; mCpuRegisterRanges[Index].Length != 0; Index++) {
|
---|
44 | if ((Register >= mCpuRegisterRanges[Index].Start) && (Register <= mCpuRegisterRanges[Index].End)) {
|
---|
45 | return Register - mCpuRegisterRanges[Index].Start + Offset;
|
---|
46 | }
|
---|
47 |
|
---|
48 | Offset += mCpuRegisterRanges[Index].Length;
|
---|
49 | }
|
---|
50 |
|
---|
51 | return 0;
|
---|
52 | }
|
---|
53 |
|
---|
54 | /**
|
---|
55 | Read a CPU Save State register on the target processor.
|
---|
56 |
|
---|
57 | This function abstracts the differences that whether the CPU Save State register is in the
|
---|
58 | IA32 CPU Save State Map or X64 CPU Save State Map.
|
---|
59 |
|
---|
60 | This function supports reading a CPU Save State register in SMBase relocation handler.
|
---|
61 |
|
---|
62 | @param[in] CpuIndex Specifies the zero-based index of the CPU save state.
|
---|
63 | @param[in] RegisterIndex Index into mCpuWidthOffset[] look up table.
|
---|
64 | @param[in] Width The number of bytes to read from the CPU save state.
|
---|
65 | @param[out] Buffer Upon return, this holds the CPU register value read from the save state.
|
---|
66 |
|
---|
67 | @retval EFI_SUCCESS The register was read from Save State.
|
---|
68 | @retval EFI_NOT_FOUND The register is not defined for the Save State of Processor.
|
---|
69 | @retval EFI_INVALID_PARAMTER This or Buffer is NULL.
|
---|
70 |
|
---|
71 | **/
|
---|
72 | EFI_STATUS
|
---|
73 | MmSaveStateReadRegisterByIndex (
|
---|
74 | IN UINTN CpuIndex,
|
---|
75 | IN UINTN RegisterIndex,
|
---|
76 | IN UINTN Width,
|
---|
77 | OUT VOID *Buffer
|
---|
78 | )
|
---|
79 | {
|
---|
80 | if (RegisterIndex == 0) {
|
---|
81 | return EFI_NOT_FOUND;
|
---|
82 | }
|
---|
83 |
|
---|
84 | if (MmSaveStateGetRegisterLma () == EFI_MM_SAVE_STATE_REGISTER_LMA_32BIT) {
|
---|
85 | //
|
---|
86 | // If 32-bit mode width is zero, then the specified register can not be accessed
|
---|
87 | //
|
---|
88 | if (mCpuWidthOffset[RegisterIndex].Width32 == 0) {
|
---|
89 | return EFI_NOT_FOUND;
|
---|
90 | }
|
---|
91 |
|
---|
92 | //
|
---|
93 | // If Width is bigger than the 32-bit mode width, then the specified register can not be accessed
|
---|
94 | //
|
---|
95 | if (Width > mCpuWidthOffset[RegisterIndex].Width32) {
|
---|
96 | return EFI_INVALID_PARAMETER;
|
---|
97 | }
|
---|
98 |
|
---|
99 | //
|
---|
100 | // Write return buffer
|
---|
101 | //
|
---|
102 | ASSERT (gMmst->CpuSaveState[CpuIndex] != NULL);
|
---|
103 | CopyMem (Buffer, (UINT8 *)gMmst->CpuSaveState[CpuIndex] + mCpuWidthOffset[RegisterIndex].Offset32, Width);
|
---|
104 | } else {
|
---|
105 | //
|
---|
106 | // If 64-bit mode width is zero, then the specified register can not be accessed
|
---|
107 | //
|
---|
108 | if (mCpuWidthOffset[RegisterIndex].Width64 == 0) {
|
---|
109 | return EFI_NOT_FOUND;
|
---|
110 | }
|
---|
111 |
|
---|
112 | //
|
---|
113 | // If Width is bigger than the 64-bit mode width, then the specified register can not be accessed
|
---|
114 | //
|
---|
115 | if (Width > mCpuWidthOffset[RegisterIndex].Width64) {
|
---|
116 | return EFI_INVALID_PARAMETER;
|
---|
117 | }
|
---|
118 |
|
---|
119 | //
|
---|
120 | // Write lower 32-bits of return buffer
|
---|
121 | //
|
---|
122 | CopyMem (Buffer, (UINT8 *)gMmst->CpuSaveState[CpuIndex] + mCpuWidthOffset[RegisterIndex].Offset64Lo, MIN (4, Width));
|
---|
123 | if (Width > 4) {
|
---|
124 | //
|
---|
125 | // Write upper 32-bits of return buffer
|
---|
126 | //
|
---|
127 | CopyMem ((UINT8 *)Buffer + 4, (UINT8 *)gMmst->CpuSaveState[CpuIndex] + mCpuWidthOffset[RegisterIndex].Offset64Hi, Width - 4);
|
---|
128 | }
|
---|
129 | }
|
---|
130 |
|
---|
131 | return EFI_SUCCESS;
|
---|
132 | }
|
---|