2 QNC Smm Library Services that implements SMM Region access, S/W SMI generation and detection.
4 Copyright (c) 2013-2016 Intel Corporation.
6 SPDX-License-Identifier: BSD-2-Clause-Patent
12 #include <IntelQNCRegs.h>
13 #include <Library/DebugLib.h>
14 #include <Library/PcdLib.h>
15 #include <Library/IoLib.h>
16 #include <Library/QNCAccessLib.h>
18 #define BOOT_SERVICE_SOFTWARE_SMI_DATA 0
19 #define RUNTIME_SOFTWARE_SMI_DATA 1
22 Triggers a run time or boot time SMI.
24 This function triggers a software SMM interrupt and set the APMC status with an 8-bit Data.
26 @param Data The value to set the APMC status.
40 GPE0BLK_Base
= (UINT16
)(LpcPciCfg32 (R_QNC_LPC_GPE0BLK
) & 0xFFFF);
46 IoOr32 ((GPE0BLK_Base
+ R_QNC_GPE0BLK_SMIE
), B_QNC_GPE0BLK_SMIE_APM
);
49 // Enable SMI globally
51 NewValue
= QNCPortRead (QUARK_NC_HOST_BRIDGE_SB_PORT_ID
, QNC_MSG_FSBIC_REG_HMISC
);
53 QNCPortWrite (QUARK_NC_HOST_BRIDGE_SB_PORT_ID
, QNC_MSG_FSBIC_REG_HMISC
, NewValue
);
58 IoWrite8 (PcdGet16 (PcdSmmDataPort
), Data
);
61 // Generate the APM SMI
63 IoWrite8 (PcdGet16 (PcdSmmActivationPort
), PcdGet8 (PcdSmmActivationData
));
66 // Clear the APM SMI Status Bit
68 IoWrite32 ((GPE0BLK_Base
+ R_QNC_GPE0BLK_SMIS
), B_QNC_GPE0BLK_SMIS_APM
);
73 IoOr32 ((GPE0BLK_Base
+ R_QNC_GPE0BLK_SMIS
), B_QNC_GPE0BLK_SMIS_EOS
);
78 Triggers an SMI at boot time.
80 This function triggers a software SMM interrupt at boot time.
85 TriggerBootServiceSoftwareSmi (
89 InternalTriggerSmi (BOOT_SERVICE_SOFTWARE_SMI_DATA
);
94 Triggers an SMI at run time.
96 This function triggers a software SMM interrupt at run time.
101 TriggerRuntimeSoftwareSmi (
105 InternalTriggerSmi (RUNTIME_SOFTWARE_SMI_DATA
);
110 Gets the software SMI data.
112 This function tests if a software SMM interrupt happens. If a software SMI happens,
113 it retrieves the SMM data and returns it as a non-negative value; otherwise a negative
116 @return Data The data retrieved from SMM data port in case of a software SMI;
117 otherwise a negative value.
121 InternalGetSwSmiData (
128 SmiStatus
= IoRead8 ((UINT16
)(LpcPciCfg32 (R_QNC_LPC_GPE0BLK
) & 0xFFFF) + R_QNC_GPE0BLK_SMIS
);
129 if (((SmiStatus
& B_QNC_GPE0BLK_SMIS_APM
) != 0) &&
130 (IoRead8 (PcdGet16 (PcdSmmActivationPort
)) == PcdGet8 (PcdSmmActivationData
))) {
131 Data
= IoRead8 (PcdGet16 (PcdSmmDataPort
));
132 return (INTN
)(UINTN
)Data
;
140 Test if a boot time software SMI happened.
142 This function tests if a software SMM interrupt happened. If a software SMM interrupt happened and
143 it was triggered at boot time, it returns TRUE. Otherwise, it returns FALSE.
145 @retval TRUE A software SMI triggered at boot time happened.
146 @retval FLASE No software SMI happened or the software SMI was triggered at run time.
151 IsBootServiceSoftwareSmi (
155 return (BOOLEAN
) (InternalGetSwSmiData () == BOOT_SERVICE_SOFTWARE_SMI_DATA
);
160 Test if a run time software SMI happened.
162 This function tests if a software SMM interrupt happened. If a software SMM interrupt happened and
163 it was triggered at run time, it returns TRUE. Otherwise, it returns FALSE.
165 @retval TRUE A software SMI triggered at run time happened.
166 @retval FLASE No software SMI happened or the software SMI was triggered at boot time.
171 IsRuntimeSoftwareSmi (
175 return (BOOLEAN
) (InternalGetSwSmiData () == RUNTIME_SOFTWARE_SMI_DATA
);
182 Clear APM SMI Status Bit; Set the EOS bit.
197 GPE0BLK_Base
= (UINT16
)(LpcPciCfg32 (R_QNC_LPC_GPE0BLK
) & 0xFFFF);
200 // Clear the APM SMI Status Bit
202 IoOr16 (GPE0BLK_Base
+ R_QNC_GPE0BLK_SMIS
, B_QNC_GPE0BLK_SMIS_APM
);
207 IoOr32 (GPE0BLK_Base
+ R_QNC_GPE0BLK_SMIS
, B_QNC_GPE0BLK_SMIS_EOS
);
211 This routine is the chipset code that accepts a request to "open" a region of SMRAM.
212 The region could be legacy ABSEG, HSEG, or TSEG near top of physical memory.
213 The use of "open" means that the memory is visible from all boot-service
216 @retval FALSE Cannot open a locked SMRAM region
217 @retval TRUE Success to open SMRAM region.
227 // Read the SMRAM register
228 Smram
= QncHsmmcRead ();
231 // Is the platform locked?
233 if (Smram
& SMM_LOCKED
) {
234 // Cannot Open a locked region
235 DEBUG ((EFI_D_WARN
, "Cannot open a locked SMRAM region\n"));
240 // Open all SMRAM regions for Host access only
242 Smram
|= (SMM_WRITE_OPEN
| SMM_READ_OPEN
); // Open for Host.
243 Smram
&= ~(NON_HOST_SMM_WR_OPEN
| NON_HOST_SMM_RD_OPEN
); // Not for others.
246 // Write the SMRAM register
248 QncHsmmcWrite (Smram
);
254 This routine is the chipset code that accepts a request to "close" a region of SMRAM.
255 The region could be legacy AB or TSEG near top of physical memory.
256 The use of "close" means that the memory is only visible from SMM agents,
257 not from BS or RT code.
259 @retval FALSE Cannot open a locked SMRAM region
260 @retval TRUE Success to open SMRAM region.
264 QNCCloseSmramRegion (
270 // Read the SMRAM register.
271 Smram
= QncHsmmcRead ();
274 // Is the platform locked?
276 if(Smram
& SMM_LOCKED
) {
277 // Cannot Open a locked region
278 DEBUG ((EFI_D_WARN
, "Cannot close a locked SMRAM region\n"));
282 Smram
&= (~(SMM_WRITE_OPEN
| SMM_READ_OPEN
| NON_HOST_SMM_WR_OPEN
| NON_HOST_SMM_RD_OPEN
));
284 QncHsmmcWrite (Smram
);
290 This routine is the chipset code that accepts a request to "lock" SMRAM.
291 The region could be legacy AB or TSEG near top of physical memory.
292 The use of "lock" means that the memory can no longer be opened
303 // Read the SMRAM register.
304 Smram
= QncHsmmcRead ();
305 if(Smram
& SMM_LOCKED
) {
306 DEBUG ((EFI_D_WARN
, "SMRAM region already locked!\n"));
310 QncHsmmcWrite (Smram
);