]> git.proxmox.com Git - mirror_edk2.git/blob - QuarkSocPkg/QuarkNorthCluster/Library/QNCSmmLib/QNCSmmLib.c
QuarkSocPkg: Replace BSD License with BSD+Patent License
[mirror_edk2.git] / QuarkSocPkg / QuarkNorthCluster / Library / QNCSmmLib / QNCSmmLib.c
1 /** @file
2 QNC Smm Library Services that implements SMM Region access, S/W SMI generation and detection.
3
4 Copyright (c) 2013-2016 Intel Corporation.
5
6 SPDX-License-Identifier: BSD-2-Clause-Patent
7
8 **/
9
10
11 #include <Base.h>
12 #include <IntelQNCRegs.h>
13 #include <Library/DebugLib.h>
14 #include <Library/PcdLib.h>
15 #include <Library/IoLib.h>
16 #include <Library/QNCAccessLib.h>
17
18 #define BOOT_SERVICE_SOFTWARE_SMI_DATA 0
19 #define RUNTIME_SOFTWARE_SMI_DATA 1
20
21 /**
22 Triggers a run time or boot time SMI.
23
24 This function triggers a software SMM interrupt and set the APMC status with an 8-bit Data.
25
26 @param Data The value to set the APMC status.
27
28 **/
29 VOID
30 InternalTriggerSmi (
31 IN UINT8 Data
32 )
33 {
34 UINT16 GPE0BLK_Base;
35 UINT32 NewValue;
36
37 //
38 // Get GPE0BLK_Base
39 //
40 GPE0BLK_Base = (UINT16)(LpcPciCfg32 (R_QNC_LPC_GPE0BLK) & 0xFFFF);
41
42
43 //
44 // Enable APM SMI
45 //
46 IoOr32 ((GPE0BLK_Base + R_QNC_GPE0BLK_SMIE), B_QNC_GPE0BLK_SMIE_APM);
47
48 //
49 // Enable SMI globally
50 //
51 NewValue = QNCPortRead (QUARK_NC_HOST_BRIDGE_SB_PORT_ID, QNC_MSG_FSBIC_REG_HMISC);
52 NewValue |= SMI_EN;
53 QNCPortWrite (QUARK_NC_HOST_BRIDGE_SB_PORT_ID, QNC_MSG_FSBIC_REG_HMISC, NewValue);
54
55 //
56 // Set APM_STS
57 //
58 IoWrite8 (PcdGet16 (PcdSmmDataPort), Data);
59
60 //
61 // Generate the APM SMI
62 //
63 IoWrite8 (PcdGet16 (PcdSmmActivationPort), PcdGet8 (PcdSmmActivationData));
64
65 //
66 // Clear the APM SMI Status Bit
67 //
68 IoWrite32 ((GPE0BLK_Base + R_QNC_GPE0BLK_SMIS), B_QNC_GPE0BLK_SMIS_APM);
69
70 //
71 // Set the EOS Bit
72 //
73 IoOr32 ((GPE0BLK_Base + R_QNC_GPE0BLK_SMIS), B_QNC_GPE0BLK_SMIS_EOS);
74 }
75
76
77 /**
78 Triggers an SMI at boot time.
79
80 This function triggers a software SMM interrupt at boot time.
81
82 **/
83 VOID
84 EFIAPI
85 TriggerBootServiceSoftwareSmi (
86 VOID
87 )
88 {
89 InternalTriggerSmi (BOOT_SERVICE_SOFTWARE_SMI_DATA);
90 }
91
92
93 /**
94 Triggers an SMI at run time.
95
96 This function triggers a software SMM interrupt at run time.
97
98 **/
99 VOID
100 EFIAPI
101 TriggerRuntimeSoftwareSmi (
102 VOID
103 )
104 {
105 InternalTriggerSmi (RUNTIME_SOFTWARE_SMI_DATA);
106 }
107
108
109 /**
110 Gets the software SMI data.
111
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
114 value is returned.
115
116 @return Data The data retrieved from SMM data port in case of a software SMI;
117 otherwise a negative value.
118
119 **/
120 INTN
121 InternalGetSwSmiData (
122 VOID
123 )
124 {
125 UINT8 SmiStatus;
126 UINT8 Data;
127
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;
133 }
134
135 return -1;
136 }
137
138
139 /**
140 Test if a boot time software SMI happened.
141
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.
144
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.
147
148 **/
149 BOOLEAN
150 EFIAPI
151 IsBootServiceSoftwareSmi (
152 VOID
153 )
154 {
155 return (BOOLEAN) (InternalGetSwSmiData () == BOOT_SERVICE_SOFTWARE_SMI_DATA);
156 }
157
158
159 /**
160 Test if a run time software SMI happened.
161
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.
164
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.
167
168 **/
169 BOOLEAN
170 EFIAPI
171 IsRuntimeSoftwareSmi (
172 VOID
173 )
174 {
175 return (BOOLEAN) (InternalGetSwSmiData () == RUNTIME_SOFTWARE_SMI_DATA);
176 }
177
178
179
180 /**
181
182 Clear APM SMI Status Bit; Set the EOS bit.
183
184 **/
185 VOID
186 EFIAPI
187 ClearSmi (
188 VOID
189 )
190 {
191
192 UINT16 GPE0BLK_Base;
193
194 //
195 // Get GpeBase
196 //
197 GPE0BLK_Base = (UINT16)(LpcPciCfg32 (R_QNC_LPC_GPE0BLK) & 0xFFFF);
198
199 //
200 // Clear the APM SMI Status Bit
201 //
202 IoOr16 (GPE0BLK_Base + R_QNC_GPE0BLK_SMIS, B_QNC_GPE0BLK_SMIS_APM);
203
204 //
205 // Set the EOS Bit
206 //
207 IoOr32 (GPE0BLK_Base + R_QNC_GPE0BLK_SMIS, B_QNC_GPE0BLK_SMIS_EOS);
208 }
209
210 /**
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
214 and SMM agents.
215
216 @retval FALSE Cannot open a locked SMRAM region
217 @retval TRUE Success to open SMRAM region.
218 **/
219 BOOLEAN
220 EFIAPI
221 QNCOpenSmramRegion (
222 VOID
223 )
224 {
225 UINT32 Smram;
226
227 // Read the SMRAM register
228 Smram = QncHsmmcRead ();
229
230 //
231 // Is the platform locked?
232 //
233 if (Smram & SMM_LOCKED) {
234 // Cannot Open a locked region
235 DEBUG ((EFI_D_WARN, "Cannot open a locked SMRAM region\n"));
236 return FALSE;
237 }
238
239 //
240 // Open all SMRAM regions for Host access only
241 //
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.
244
245 //
246 // Write the SMRAM register
247 //
248 QncHsmmcWrite (Smram);
249
250 return TRUE;
251 }
252
253 /**
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.
258
259 @retval FALSE Cannot open a locked SMRAM region
260 @retval TRUE Success to open SMRAM region.
261 **/
262 BOOLEAN
263 EFIAPI
264 QNCCloseSmramRegion (
265 VOID
266 )
267 {
268 UINT32 Smram;
269
270 // Read the SMRAM register.
271 Smram = QncHsmmcRead ();
272
273 //
274 // Is the platform locked?
275 //
276 if(Smram & SMM_LOCKED) {
277 // Cannot Open a locked region
278 DEBUG ((EFI_D_WARN, "Cannot close a locked SMRAM region\n"));
279 return FALSE;
280 }
281
282 Smram &= (~(SMM_WRITE_OPEN | SMM_READ_OPEN | NON_HOST_SMM_WR_OPEN | NON_HOST_SMM_RD_OPEN));
283
284 QncHsmmcWrite (Smram);
285
286 return TRUE;
287 }
288
289 /**
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
293 to BS state.
294 **/
295 VOID
296 EFIAPI
297 QNCLockSmramRegion (
298 VOID
299 )
300 {
301 UINT32 Smram;
302
303 // Read the SMRAM register.
304 Smram = QncHsmmcRead ();
305 if(Smram & SMM_LOCKED) {
306 DEBUG ((EFI_D_WARN, "SMRAM region already locked!\n"));
307 }
308 Smram |= SMM_LOCKED;
309
310 QncHsmmcWrite (Smram);
311
312 return;
313 }