VirtualBox

source: vbox/trunk/src/VBox/Devices/EFI/FirmwareNew/UefiPayloadPkg/SmmControlRuntimeDxe/SmmControlRuntimeDxe.c@ 99404

Last change on this file since 99404 was 99404, checked in by vboxsync, 22 months ago

Devices/EFI/FirmwareNew: Update to edk2-stable202302 and make it build, bugref:4643

  • Property svn:eol-style set to native
File size: 7.3 KB
Line 
1/** @file
2 This module produces the SMM Control2 Protocol
3
4 Copyright (c) 2021, Intel Corporation. All rights reserved.<BR>
5 SPDX-License-Identifier: BSD-2-Clause-Patent
6
7**/
8
9#include <PiDxe.h>
10#include <Protocol/SmmControl2.h>
11#include <Library/DebugLib.h>
12#include <Library/UefiBootServicesTableLib.h>
13#include <Library/IoLib.h>
14#include <Library/HobLib.h>
15#include <Library/UefiRuntimeLib.h>
16#include <Library/BaseMemoryLib.h>
17#include <Guid/SmmRegisterInfoGuid.h>
18
19#define SMM_DATA_PORT 0xB3
20#define SMM_CONTROL_PORT 0xB2
21
22typedef struct {
23 UINT8 GblBitOffset;
24 UINT8 ApmBitOffset;
25 UINT32 Address;
26} SMM_CONTROL2_REG;
27
28SMM_CONTROL2_REG mSmiCtrlReg;
29
30/**
31 Invokes SMI activation from either the preboot or runtime environment.
32
33 This function generates an SMI.
34
35 @param[in] This The EFI_SMM_CONTROL2_PROTOCOL instance.
36 @param[in,out] CommandPort The value written to the command port.
37 @param[in,out] DataPort The value written to the data port.
38 @param[in] Periodic Optional mechanism to engender a periodic stream.
39 @param[in] ActivationInterval Optional parameter to repeat at this period one
40 time or, if the Periodic Boolean is set, periodically.
41
42 @retval EFI_SUCCESS The SMI has been engendered.
43 @retval EFI_DEVICE_ERROR The timing is unsupported.
44 @retval EFI_INVALID_PARAMETER The activation period is unsupported.
45 @retval EFI_INVALID_PARAMETER The last periodic activation has not been cleared.
46 @retval EFI_NOT_STARTED The MM base service has not been initialized.
47**/
48EFI_STATUS
49EFIAPI
50Activate (
51 IN CONST EFI_SMM_CONTROL2_PROTOCOL *This,
52 IN OUT UINT8 *CommandPort OPTIONAL,
53 IN OUT UINT8 *DataPort OPTIONAL,
54 IN BOOLEAN Periodic OPTIONAL,
55 IN EFI_SMM_PERIOD ActivationInterval OPTIONAL
56 )
57{
58 UINT32 SmiEn;
59 UINT32 SmiEnableBits;
60
61 if (Periodic) {
62 return EFI_INVALID_PARAMETER;
63 }
64
65 SmiEn = IoRead32 (mSmiCtrlReg.Address);
66 SmiEnableBits = (1 << mSmiCtrlReg.GblBitOffset) | (1 << mSmiCtrlReg.ApmBitOffset);
67 if ((SmiEn & SmiEnableBits) != SmiEnableBits) {
68 //
69 // Set the "global SMI enable" bit and APM bit
70 //
71 IoWrite32 (mSmiCtrlReg.Address, SmiEn | SmiEnableBits);
72 }
73
74 IoWrite8 (SMM_DATA_PORT, DataPort == NULL ? 0 : *DataPort);
75 IoWrite8 (SMM_CONTROL_PORT, CommandPort == NULL ? 0 : *CommandPort);
76 return EFI_SUCCESS;
77}
78
79/**
80 Clears an SMI.
81
82 @param This Pointer to an instance of EFI_SMM_CONTROL2_PROTOCOL
83 @param Periodic TRUE to indicate a periodical SMI
84
85 @return Return value from SmmClear ()
86
87**/
88EFI_STATUS
89EFIAPI
90Deactivate (
91 IN CONST EFI_SMM_CONTROL2_PROTOCOL *This,
92 IN BOOLEAN Periodic
93 )
94{
95 if (Periodic) {
96 return EFI_INVALID_PARAMETER;
97 }
98
99 //
100 // Temporarily do nothing here
101 //
102 return EFI_SUCCESS;
103}
104
105///
106/// SMM COntrol2 Protocol instance
107///
108EFI_SMM_CONTROL2_PROTOCOL mSmmControl2 = {
109 Activate,
110 Deactivate,
111 0
112};
113
114/**
115 Get specified SMI register based on given register ID
116
117 @param[in] SmmRegister SMI related register array from bootloader
118 @param[in] Id The register ID to get.
119
120 @retval NULL The register is not found or the format is not expected.
121 @return smi register
122
123**/
124PLD_GENERIC_REGISTER *
125GetSmmCtrlRegById (
126 IN PLD_SMM_REGISTERS *SmmRegister,
127 IN UINT32 Id
128 )
129{
130 UINT32 Index;
131 PLD_GENERIC_REGISTER *PldReg;
132
133 PldReg = NULL;
134 for (Index = 0; Index < SmmRegister->Count; Index++) {
135 if (SmmRegister->Registers[Index].Id == Id) {
136 PldReg = &SmmRegister->Registers[Index];
137 break;
138 }
139 }
140
141 if (PldReg == NULL) {
142 DEBUG ((DEBUG_INFO, "Register %d not found.\n", Id));
143 return NULL;
144 }
145
146 //
147 // Checking the register if it is expected.
148 //
149 if ((PldReg->Address.AccessSize != EFI_ACPI_3_0_DWORD) ||
150 (PldReg->Address.Address == 0) ||
151 (PldReg->Address.RegisterBitWidth != 1) ||
152 (PldReg->Address.AddressSpaceId != EFI_ACPI_3_0_SYSTEM_IO) ||
153 (PldReg->Value != 1))
154 {
155 DEBUG ((DEBUG_INFO, "Unexpected SMM register.\n"));
156 DEBUG ((DEBUG_INFO, "AddressSpaceId= 0x%x\n", PldReg->Address.AddressSpaceId));
157 DEBUG ((DEBUG_INFO, "RegBitWidth = 0x%x\n", PldReg->Address.RegisterBitWidth));
158 DEBUG ((DEBUG_INFO, "RegBitOffset = 0x%x\n", PldReg->Address.RegisterBitOffset));
159 DEBUG ((DEBUG_INFO, "AccessSize = 0x%x\n", PldReg->Address.AccessSize));
160 DEBUG ((DEBUG_INFO, "Address = 0x%lx\n", PldReg->Address.Address));
161 return NULL;
162 }
163
164 return PldReg;
165}
166
167/**
168 Fixup data pointers so that the services can be called in virtual mode.
169
170 @param[in] Event The event registered.
171 @param[in] Context Event context.
172
173**/
174VOID
175EFIAPI
176SmmControlVirtualAddressChangeEvent (
177 IN EFI_EVENT Event,
178 IN VOID *Context
179 )
180{
181 EfiConvertPointer (0x0, (VOID **)&(mSmmControl2.Trigger));
182 EfiConvertPointer (0x0, (VOID **)&(mSmmControl2.Clear));
183}
184
185/**
186 This function installs EFI_SMM_CONTROL2_PROTOCOL.
187
188 @param ImageHandle Handle for the image of this driver
189 @param SystemTable Pointer to the EFI System Table
190
191 @retval EFI_UNSUPPORTED There's no Intel ICH on this platform
192 @return The status returned from InstallProtocolInterface().
193
194**/
195EFI_STATUS
196EFIAPI
197SmmControlEntryPoint (
198 IN EFI_HANDLE ImageHandle,
199 IN EFI_SYSTEM_TABLE *SystemTable
200 )
201{
202 EFI_STATUS Status;
203 EFI_HOB_GUID_TYPE *GuidHob;
204 PLD_SMM_REGISTERS *SmmRegister;
205 PLD_GENERIC_REGISTER *SmiGblEnReg;
206 PLD_GENERIC_REGISTER *SmiApmEnReg;
207 EFI_EVENT Event;
208
209 GuidHob = GetFirstGuidHob (&gSmmRegisterInfoGuid);
210 if (GuidHob == NULL) {
211 return EFI_UNSUPPORTED;
212 }
213
214 SmmRegister = (PLD_SMM_REGISTERS *)(GET_GUID_HOB_DATA (GuidHob));
215 SmiGblEnReg = GetSmmCtrlRegById (SmmRegister, REGISTER_ID_SMI_GBL_EN);
216 if (SmiGblEnReg == NULL) {
217 DEBUG ((DEBUG_ERROR, "SMI global enable reg not found.\n"));
218 return EFI_NOT_FOUND;
219 }
220
221 mSmiCtrlReg.Address = (UINT32)SmiGblEnReg->Address.Address;
222 mSmiCtrlReg.GblBitOffset = SmiGblEnReg->Address.RegisterBitOffset;
223
224 SmiApmEnReg = GetSmmCtrlRegById (SmmRegister, REGISTER_ID_SMI_APM_EN);
225 if (SmiApmEnReg == NULL) {
226 DEBUG ((DEBUG_ERROR, "SMI APM enable reg not found.\n"));
227 return EFI_NOT_FOUND;
228 }
229
230 if (SmiApmEnReg->Address.Address != mSmiCtrlReg.Address) {
231 DEBUG ((DEBUG_ERROR, "SMI APM EN and SMI GBL EN are expected to have same register base\n"));
232 DEBUG ((DEBUG_ERROR, "APM:0x%x, GBL:0x%x\n", SmiApmEnReg->Address.Address, mSmiCtrlReg.Address));
233 return EFI_UNSUPPORTED;
234 }
235
236 mSmiCtrlReg.ApmBitOffset = SmiApmEnReg->Address.RegisterBitOffset;
237
238 //
239 // Install our protocol interfaces on the device's handle
240 //
241 Status = gBS->InstallMultipleProtocolInterfaces (
242 &ImageHandle,
243 &gEfiSmmControl2ProtocolGuid,
244 &mSmmControl2,
245 NULL
246 );
247 ASSERT_EFI_ERROR (Status);
248
249 Status = gBS->CreateEventEx (
250 EVT_NOTIFY_SIGNAL,
251 TPL_NOTIFY,
252 SmmControlVirtualAddressChangeEvent,
253 NULL,
254 &gEfiEventVirtualAddressChangeGuid,
255 &Event
256 );
257 return Status;
258}
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