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