1 | /** @file
|
---|
2 | Config SMRAM Save State for SmmBases Relocation.
|
---|
3 |
|
---|
4 | Copyright (C) 2023 Advanced Micro Devices, Inc. All rights reserved.<BR>
|
---|
5 | Copyright (c) 2024, Intel Corporation. All rights reserved.<BR>
|
---|
6 | SPDX-License-Identifier: BSD-2-Clause-Patent
|
---|
7 |
|
---|
8 | **/
|
---|
9 | #include "InternalSmmRelocationLib.h"
|
---|
10 | #include <Register/Amd/SmramSaveStateMap.h>
|
---|
11 |
|
---|
12 | #define EFER_ADDRESS 0XC0000080ul
|
---|
13 |
|
---|
14 | /**
|
---|
15 | Get the mode of the CPU at the time an SMI occurs
|
---|
16 |
|
---|
17 | @retval EFI_MM_SAVE_STATE_REGISTER_LMA_32BIT 32 bit.
|
---|
18 | @retval EFI_MM_SAVE_STATE_REGISTER_LMA_64BIT 64 bit.
|
---|
19 |
|
---|
20 | **/
|
---|
21 | UINT8
|
---|
22 | GetMmSaveStateRegisterLma (
|
---|
23 | VOID
|
---|
24 | )
|
---|
25 | {
|
---|
26 | UINT8 SmmSaveStateRegisterLma;
|
---|
27 | UINT32 LMAValue;
|
---|
28 |
|
---|
29 | SmmSaveStateRegisterLma = (UINT8)EFI_MM_SAVE_STATE_REGISTER_LMA_32BIT;
|
---|
30 |
|
---|
31 | LMAValue = (UINT32)AsmReadMsr64 (EFER_ADDRESS) & LMA;
|
---|
32 | if (LMAValue) {
|
---|
33 | SmmSaveStateRegisterLma = (UINT8)EFI_MM_SAVE_STATE_REGISTER_LMA_64BIT;
|
---|
34 | }
|
---|
35 |
|
---|
36 | return SmmSaveStateRegisterLma;
|
---|
37 | }
|
---|
38 |
|
---|
39 | /**
|
---|
40 | This function configures the SmBase on the currently executing CPU.
|
---|
41 |
|
---|
42 | @param[in] SmBase The SmBase on the currently executing CPU.
|
---|
43 |
|
---|
44 | **/
|
---|
45 | VOID
|
---|
46 | EFIAPI
|
---|
47 | ConfigureSmBase (
|
---|
48 | IN UINT64 SmBase
|
---|
49 | )
|
---|
50 | {
|
---|
51 | AMD_SMRAM_SAVE_STATE_MAP *AmdCpuState;
|
---|
52 |
|
---|
53 | AmdCpuState = (AMD_SMRAM_SAVE_STATE_MAP *)(UINTN)(SMM_DEFAULT_SMBASE + SMRAM_SAVE_STATE_MAP_OFFSET);
|
---|
54 |
|
---|
55 | AmdCpuState->x64.SMBASE = (UINT32)SmBase;
|
---|
56 | }
|
---|
57 |
|
---|
58 | /**
|
---|
59 | This function updates the SMRAM save state on the currently executing CPU
|
---|
60 | to resume execution at a specific address after an RSM instruction. This
|
---|
61 | function must evaluate the SMRAM save state to determine the execution mode
|
---|
62 | the RSM instruction resumes and update the resume execution address with
|
---|
63 | either NewInstructionPointer32 or NewInstructionPoint. The auto HALT restart
|
---|
64 | flag in the SMRAM save state must always be cleared. This function returns
|
---|
65 | the value of the instruction pointer from the SMRAM save state that was
|
---|
66 | replaced. If this function returns 0, then the SMRAM save state was not
|
---|
67 | modified.
|
---|
68 |
|
---|
69 | This function is called during the very first SMI on each CPU after
|
---|
70 | SmmCpuFeaturesInitializeProcessor() to set a flag in normal execution mode
|
---|
71 | to signal that the SMBASE of each CPU has been updated before the default
|
---|
72 | SMBASE address is used for the first SMI to the next CPU.
|
---|
73 |
|
---|
74 | @param[in,out] CpuState Pointer to SMRAM Save State Map for the
|
---|
75 | currently executing CPU.
|
---|
76 | @param[in] NewInstructionPointer32 Instruction pointer to use if resuming to
|
---|
77 | 32-bit mode from 64-bit SMM.
|
---|
78 | @param[in] NewInstructionPointer Instruction pointer to use if resuming to
|
---|
79 | same mode as SMM.
|
---|
80 |
|
---|
81 | @retval The value of the original instruction pointer before it was hooked.
|
---|
82 |
|
---|
83 | **/
|
---|
84 | UINT64
|
---|
85 | EFIAPI
|
---|
86 | HookReturnFromSmm (
|
---|
87 | IN OUT SMRAM_SAVE_STATE_MAP *CpuState,
|
---|
88 | IN UINT64 NewInstructionPointer32,
|
---|
89 | IN UINT64 NewInstructionPointer
|
---|
90 | )
|
---|
91 | {
|
---|
92 | UINT64 OriginalInstructionPointer;
|
---|
93 | AMD_SMRAM_SAVE_STATE_MAP *AmdCpuState;
|
---|
94 |
|
---|
95 | AmdCpuState = (AMD_SMRAM_SAVE_STATE_MAP *)CpuState;
|
---|
96 |
|
---|
97 | if (GetMmSaveStateRegisterLma () == EFI_MM_SAVE_STATE_REGISTER_LMA_32BIT) {
|
---|
98 | OriginalInstructionPointer = (UINT64)AmdCpuState->x86._EIP;
|
---|
99 | AmdCpuState->x86._EIP = (UINT32)NewInstructionPointer;
|
---|
100 | //
|
---|
101 | // Clear the auto HALT restart flag so the RSM instruction returns
|
---|
102 | // program control to the instruction following the HLT instruction.
|
---|
103 | //
|
---|
104 | if ((AmdCpuState->x86.AutoHALTRestart & BIT0) != 0) {
|
---|
105 | AmdCpuState->x86.AutoHALTRestart &= ~BIT0;
|
---|
106 | }
|
---|
107 | } else {
|
---|
108 | OriginalInstructionPointer = AmdCpuState->x64._RIP;
|
---|
109 | if ((AmdCpuState->x64.EFER & LMA) == 0) {
|
---|
110 | AmdCpuState->x64._RIP = (UINT32)NewInstructionPointer32;
|
---|
111 | } else {
|
---|
112 | AmdCpuState->x64._RIP = (UINT32)NewInstructionPointer;
|
---|
113 | }
|
---|
114 |
|
---|
115 | //
|
---|
116 | // Clear the auto HALT restart flag so the RSM instruction returns
|
---|
117 | // program control to the instruction following the HLT instruction.
|
---|
118 | //
|
---|
119 | if ((AmdCpuState->x64.AutoHALTRestart & BIT0) != 0) {
|
---|
120 | AmdCpuState->x64.AutoHALTRestart &= ~BIT0;
|
---|
121 | }
|
---|
122 | }
|
---|
123 |
|
---|
124 | return OriginalInstructionPointer;
|
---|
125 | }
|
---|