]> git.proxmox.com Git - mirror_edk2.git/blob - QuarkSocPkg/QuarkNorthCluster/Library/QNCSmmLib/QNCSmmLib.c
QuarkSocPkg: MtrrLib: remove set but unused variables
[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-2015 Intel Corporation.
5
6 This program and the accompanying materials
7 are licensed and made available under the terms and conditions of the BSD License
8 which accompanies this distribution. The full text of the license may be found at
9 http://opensource.org/licenses/bsd-license.php
10
11 THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
12 WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
13
14 **/
15
16
17 #include <Base.h>
18 #include <IntelQNCRegs.h>
19 #include <Library/DebugLib.h>
20 #include <Library/PcdLib.h>
21 #include <Library/IoLib.h>
22 #include <Uefi/UefiBaseType.h>
23 #include <Library/QNCAccessLib.h>
24
25 #define BOOT_SERVICE_SOFTWARE_SMI_DATA 0
26 #define RUNTIME_SOFTWARE_SMI_DATA 1
27
28 /**
29 Triggers a run time or boot time SMI.
30
31 This function triggers a software SMM interrupt and set the APMC status with an 8-bit Data.
32
33 @param Data The value to set the APMC status.
34
35 **/
36 VOID
37 InternalTriggerSmi (
38 IN UINT8 Data
39 )
40 {
41 UINT16 PM1BLK_Base;
42 UINT16 GPE0BLK_Base;
43 UINT32 NewValue;
44
45 //
46 // Get PM1BLK_Base & GPE0BLK_Base
47 //
48 PM1BLK_Base = PcdGet16 (PcdPm1blkIoBaseAddress);
49 GPE0BLK_Base = (UINT16)(LpcPciCfg32 (R_QNC_LPC_GPE0BLK) & 0xFFFF);
50
51
52 //
53 // Enable APM SMI
54 //
55 IoOr32 ((GPE0BLK_Base + R_QNC_GPE0BLK_SMIE), B_QNC_GPE0BLK_SMIE_APM);
56
57 //
58 // Enable SMI globally
59 //
60 NewValue = QNCPortRead (QUARK_NC_HOST_BRIDGE_SB_PORT_ID, QNC_MSG_FSBIC_REG_HMISC);
61 NewValue |= SMI_EN;
62 QNCPortWrite (QUARK_NC_HOST_BRIDGE_SB_PORT_ID, QNC_MSG_FSBIC_REG_HMISC, NewValue);
63
64 //
65 // Set APM_STS
66 //
67 IoWrite8 (PcdGet16 (PcdSmmDataPort), Data);
68
69 //
70 // Generate the APM SMI
71 //
72 IoWrite8 (PcdGet16 (PcdSmmActivationPort), PcdGet8 (PcdSmmActivationData));
73
74 //
75 // Clear the APM SMI Status Bit
76 //
77 IoWrite32 ((GPE0BLK_Base + R_QNC_GPE0BLK_SMIS), B_QNC_GPE0BLK_SMIS_APM);
78
79 //
80 // Set the EOS Bit
81 //
82 IoOr32 ((GPE0BLK_Base + R_QNC_GPE0BLK_SMIS), B_QNC_GPE0BLK_SMIS_EOS);
83 }
84
85
86 /**
87 Triggers an SMI at boot time.
88
89 This function triggers a software SMM interrupt at boot time.
90
91 **/
92 VOID
93 EFIAPI
94 TriggerBootServiceSoftwareSmi (
95 VOID
96 )
97 {
98 InternalTriggerSmi (BOOT_SERVICE_SOFTWARE_SMI_DATA);
99 }
100
101
102 /**
103 Triggers an SMI at run time.
104
105 This function triggers a software SMM interrupt at run time.
106
107 **/
108 VOID
109 EFIAPI
110 TriggerRuntimeSoftwareSmi (
111 VOID
112 )
113 {
114 InternalTriggerSmi (RUNTIME_SOFTWARE_SMI_DATA);
115 }
116
117
118 /**
119 Gets the software SMI data.
120
121 This function tests if a software SMM interrupt happens. If a software SMI happens,
122 it retrieves the SMM data and returns it as a non-negative value; otherwise a negative
123 value is returned.
124
125 @return Data The data retrieved from SMM data port in case of a software SMI;
126 otherwise a negative value.
127
128 **/
129 INTN
130 InternalGetSwSmiData (
131 VOID
132 )
133 {
134 UINT8 SmiStatus;
135 UINT8 Data;
136
137 SmiStatus = IoRead8 ((UINT16)(LpcPciCfg32 (R_QNC_LPC_GPE0BLK) & 0xFFFF) + R_QNC_GPE0BLK_SMIS);
138 if (((SmiStatus & B_QNC_GPE0BLK_SMIS_APM) != 0) &&
139 (IoRead8 (PcdGet16 (PcdSmmActivationPort)) == PcdGet8 (PcdSmmActivationData))) {
140 Data = IoRead8 (PcdGet16 (PcdSmmDataPort));
141 return (INTN)(UINTN)Data;
142 }
143
144 return -1;
145 }
146
147
148 /**
149 Test if a boot time software SMI happened.
150
151 This function tests if a software SMM interrupt happened. If a software SMM interrupt happened and
152 it was triggered at boot time, it returns TRUE. Otherwise, it returns FALSE.
153
154 @retval TRUE A software SMI triggered at boot time happened.
155 @retval FLASE No software SMI happened or the software SMI was triggered at run time.
156
157 **/
158 BOOLEAN
159 EFIAPI
160 IsBootServiceSoftwareSmi (
161 VOID
162 )
163 {
164 return (BOOLEAN) (InternalGetSwSmiData () == BOOT_SERVICE_SOFTWARE_SMI_DATA);
165 }
166
167
168 /**
169 Test if a run time software SMI happened.
170
171 This function tests if a software SMM interrupt happened. If a software SMM interrupt happened and
172 it was triggered at run time, it returns TRUE. Otherwise, it returns FALSE.
173
174 @retval TRUE A software SMI triggered at run time happened.
175 @retval FLASE No software SMI happened or the software SMI was triggered at boot time.
176
177 **/
178 BOOLEAN
179 EFIAPI
180 IsRuntimeSoftwareSmi (
181 VOID
182 )
183 {
184 return (BOOLEAN) (InternalGetSwSmiData () == RUNTIME_SOFTWARE_SMI_DATA);
185 }
186
187
188
189 /**
190
191 Clear APM SMI Status Bit; Set the EOS bit.
192
193 **/
194 VOID
195 EFIAPI
196 ClearSmi (
197 VOID
198 )
199 {
200
201 UINT16 GPE0BLK_Base;
202
203 //
204 // Get GpeBase
205 //
206 GPE0BLK_Base = (UINT16)(LpcPciCfg32 (R_QNC_LPC_GPE0BLK) & 0xFFFF);
207
208 //
209 // Clear the APM SMI Status Bit
210 //
211 IoOr16 (GPE0BLK_Base + R_QNC_GPE0BLK_SMIS, B_QNC_GPE0BLK_SMIS_APM);
212
213 //
214 // Set the EOS Bit
215 //
216 IoOr32 (GPE0BLK_Base + R_QNC_GPE0BLK_SMIS, B_QNC_GPE0BLK_SMIS_EOS);
217 }
218
219 /**
220 This routine is the chipset code that accepts a request to "open" a region of SMRAM.
221 The region could be legacy ABSEG, HSEG, or TSEG near top of physical memory.
222 The use of "open" means that the memory is visible from all boot-service
223 and SMM agents.
224
225 @retval FALSE Cannot open a locked SMRAM region
226 @retval TRUE Success to open SMRAM region.
227 **/
228 BOOLEAN
229 EFIAPI
230 QNCOpenSmramRegion (
231 VOID
232 )
233 {
234 UINT32 Smram;
235
236 // Read the SMRAM register
237 Smram = QncHsmmcRead ();
238
239 //
240 // Is the platform locked?
241 //
242 if (Smram & SMM_LOCKED) {
243 // Cannot Open a locked region
244 DEBUG ((EFI_D_WARN, "Cannot open a locked SMRAM region\n"));
245 return FALSE;
246 }
247
248 //
249 // Open all SMRAM regions for Host access only
250 //
251 Smram |= (SMM_WRITE_OPEN | SMM_READ_OPEN); // Open for Host.
252 Smram &= ~(NON_HOST_SMM_WR_OPEN | NON_HOST_SMM_RD_OPEN); // Not for others.
253
254 //
255 // Write the SMRAM register
256 //
257 QncHsmmcWrite (Smram);
258
259 return TRUE;
260 }
261
262 /**
263 This routine is the chipset code that accepts a request to "close" a region of SMRAM.
264 The region could be legacy AB or TSEG near top of physical memory.
265 The use of "close" means that the memory is only visible from SMM agents,
266 not from BS or RT code.
267
268 @retval FALSE Cannot open a locked SMRAM region
269 @retval TRUE Success to open SMRAM region.
270 **/
271 BOOLEAN
272 EFIAPI
273 QNCCloseSmramRegion (
274 VOID
275 )
276 {
277 UINT32 Smram;
278
279 // Read the SMRAM register.
280 Smram = QncHsmmcRead ();
281
282 //
283 // Is the platform locked?
284 //
285 if(Smram & SMM_LOCKED) {
286 // Cannot Open a locked region
287 DEBUG ((EFI_D_WARN, "Cannot close a locked SMRAM region\n"));
288 return FALSE;
289 }
290
291 Smram &= (~(SMM_WRITE_OPEN | SMM_READ_OPEN | NON_HOST_SMM_WR_OPEN | NON_HOST_SMM_RD_OPEN));
292
293 QncHsmmcWrite (Smram);
294
295 return TRUE;
296 }
297
298 /**
299 This routine is the chipset code that accepts a request to "lock" SMRAM.
300 The region could be legacy AB or TSEG near top of physical memory.
301 The use of "lock" means that the memory can no longer be opened
302 to BS state.
303 **/
304 VOID
305 EFIAPI
306 QNCLockSmramRegion (
307 VOID
308 )
309 {
310 UINT32 Smram;
311
312 // Read the SMRAM register.
313 Smram = QncHsmmcRead ();
314 if(Smram & SMM_LOCKED) {
315 DEBUG ((EFI_D_WARN, "SMRAM region already locked!\n"));
316 }
317 Smram |= SMM_LOCKED;
318
319 QncHsmmcWrite (Smram);
320
321 return;
322 }