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