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