1 /** @file
2 This module provides an implementation of the SMM Control PPI for use with
3 the QNC.
4
5 Copyright (c) 2013-2015 Intel Corporation.
6
7 This program and the accompanying materials
8 are licensed and made available under the terms and conditions of the BSD License
9 which accompanies this distribution. The full text of the license may be found at
10 http://opensource.org/licenses/bsd-license.php
11
12 THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
13 WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
14
15 **/
16
17 #include <PiPei.h>
18
19 #include <Ppi/SmmControl.h>
20
21 #include <Library/DebugLib.h>
22 #include <Library/HobLib.h>
23 #include <Library/PeiServicesLib.h>
24 #include <Library/PcdLib.h>
25 #include <Library/IoLib.h>
26 #include <Library/PciLib.h>
27
28 #include <IntelQNCPeim.h>
29 #include <Library/QNCAccessLib.h>
30 #include <Uefi/UefiBaseType.h>
31
32 /**
33 Generates an SMI using the parameters passed in.
34
35 @param PeiServices Describes the list of possible PEI Services.
36 @param This A pointer to an instance of
37 EFI_SMM_CONTROL_PPI
38 @param ArgumentBuffer The argument buffer
39 @param ArgumentBufferSize The size of the argument buffer
40 @param Periodic TRUE to indicate a periodical SMI
41 @param ActivationInterval Interval of the periodical SMI
42
43 @retval EFI_INVALID_PARAMETER Periodic is TRUE or ArgumentBufferSize > 1
44 @retval EFI_SUCCESS SMI generated
45
46 **/
47 EFI_STATUS
48 EFIAPI
49 PeiActivate (
50 IN EFI_PEI_SERVICES **PeiServices,
51 IN PEI_SMM_CONTROL_PPI *This,
52 IN OUT INT8 *ArgumentBuffer OPTIONAL,
53 IN OUT UINTN *ArgumentBufferSize OPTIONAL,
54 IN BOOLEAN Periodic OPTIONAL,
55 IN UINTN ActivationInterval OPTIONAL
56 );
57
58 /**
59 Clears an SMI.
60
61 @param PeiServices Describes the list of possible PEI Services.
62 @param This Pointer to an instance of EFI_SMM_CONTROL_PPI
63 @param Periodic TRUE to indicate a periodical SMI
64
65 @return Return value from SmmClear()
66
67 **/
68 EFI_STATUS
69 EFIAPI
70 PeiDeactivate (
71 IN EFI_PEI_SERVICES **PeiServices,
72 IN PEI_SMM_CONTROL_PPI *This,
73 IN BOOLEAN Periodic OPTIONAL
74 );
75
76 PEI_SMM_CONTROL_PPI mSmmControlPpi = {
77 PeiActivate,
78 PeiDeactivate
79 };
80
81 EFI_PEI_PPI_DESCRIPTOR mPpiList = {
82 (EFI_PEI_PPI_DESCRIPTOR_PPI | EFI_PEI_PPI_DESCRIPTOR_TERMINATE_LIST),
83 &gPeiSmmControlPpiGuid,
84 &mSmmControlPpi
85 };
86
87 /**
88 Clear SMI related chipset status and re-enable SMI by setting the EOS bit.
89
90 @retval EFI_SUCCESS The requested operation has been carried out successfully
91 @retval EFI_DEVICE_ERROR The EOS bit could not be set.
92
93 **/
94 EFI_STATUS
SmmClear(VOID)95 SmmClear (
96 VOID
97 )
98 {
99 UINT16 GPE0BLK_Base;
100
101 //
102 // Get GPE0BLK_Base
103 //
104 GPE0BLK_Base = PcdGet16 (PcdGpe0blkIoBaseAddress);
105
106 //
107 // Clear the Power Button Override Status Bit, it gates EOS from being set.
108 // In QuarkNcSocId - Bit is read only. Handled by external SMC, do nothing.
109 //
110
111 //
112 // Clear the APM SMI Status Bit
113 //
114 IoWrite32 ((GPE0BLK_Base + R_QNC_GPE0BLK_SMIS), B_QNC_GPE0BLK_SMIS_APM);
115
116 //
117 // Set the EOS Bit
118 //
119 IoOr32 ((GPE0BLK_Base + R_QNC_GPE0BLK_SMIS), B_QNC_GPE0BLK_SMIS_EOS);
120
121 return EFI_SUCCESS;
122 }
123
124
125 EFI_STATUS
126 EFIAPI
SmmTrigger(IN UINT8 Data)127 SmmTrigger (
128 IN UINT8 Data
129 )
130 /*++
131
132 Routine Description:
133
134 Trigger the software SMI
135
136 Arguments:
137
138 Data The value to be set on the software SMI data port
139
140 Returns:
141
142 EFI_SUCCESS Function completes successfully
143
144 --*/
145 {
146 UINT16 GPE0BLK_Base;
147 UINT32 NewValue;
148
149 //
150 // Get GPE0BLK_Base
151 //
152 GPE0BLK_Base = PcdGet16 (PcdGpe0blkIoBaseAddress);
153
154 //
155 // Enable the APMC SMI
156 //
157 IoOr32 (GPE0BLK_Base + R_QNC_GPE0BLK_SMIE, B_QNC_GPE0BLK_SMIE_APM);
158
159 //
160 // Enable SMI globally
161 //
162 NewValue = QNCPortRead (QUARK_NC_HOST_BRIDGE_SB_PORT_ID, QNC_MSG_FSBIC_REG_HMISC);
163 NewValue |= SMI_EN;
164 QNCPortWrite (QUARK_NC_HOST_BRIDGE_SB_PORT_ID, QNC_MSG_FSBIC_REG_HMISC, NewValue);
165
166
167 //
168 // Generate the APMC SMI
169 //
170 IoWrite8 (PcdGet16 (PcdSmmActivationPort), Data);
171
172 return EFI_SUCCESS;
173 }
174
175 /**
176 Generates an SMI using the parameters passed in.
177
178 @param PeiServices Describes the list of possible PEI Services.
179 @param This A pointer to an instance of
180 EFI_SMM_CONTROL_PPI
181 @param ArgumentBuffer The argument buffer
182 @param ArgumentBufferSize The size of the argument buffer
183 @param Periodic TRUE to indicate a periodical SMI
184 @param ActivationInterval Interval of the periodical SMI
185
186 @retval EFI_INVALID_PARAMETER Periodic is TRUE or ArgumentBufferSize > 1
187 @retval EFI_SUCCESS SMI generated
188
189 **/
190 EFI_STATUS
191 EFIAPI
PeiActivate(IN EFI_PEI_SERVICES ** PeiServices,IN PEI_SMM_CONTROL_PPI * This,IN OUT INT8 * ArgumentBuffer OPTIONAL,IN OUT UINTN * ArgumentBufferSize OPTIONAL,IN BOOLEAN Periodic OPTIONAL,IN UINTN ActivationInterval OPTIONAL)192 PeiActivate (
193 IN EFI_PEI_SERVICES **PeiServices,
194 IN PEI_SMM_CONTROL_PPI *This,
195 IN OUT INT8 *ArgumentBuffer OPTIONAL,
196 IN OUT UINTN *ArgumentBufferSize OPTIONAL,
197 IN BOOLEAN Periodic OPTIONAL,
198 IN UINTN ActivationInterval OPTIONAL
199 )
200 {
201 INT8 Data;
202 EFI_STATUS Status;
203 //
204 // Periodic SMI not supported.
205 //
206 if (Periodic) {
207 DEBUG ((DEBUG_WARN, "Invalid parameter\n"));
208 return EFI_INVALID_PARAMETER;
209 }
210
211 if (ArgumentBuffer == NULL) {
212 Data = 0xFF;
213 } else {
214 if (ArgumentBufferSize == NULL || *ArgumentBufferSize != 1) {
215 return EFI_INVALID_PARAMETER;
216 }
217
218 Data = *ArgumentBuffer;
219 }
220 //
221 // Clear any pending the APM SMI
222 //
223 Status = SmmClear ();
224 if (EFI_ERROR (Status)) {
225 return Status;
226 }
227
228 return SmmTrigger (Data);
229 }
230
231 /**
232 Clears an SMI.
233
234 @param PeiServices Describes the list of possible PEI Services.
235 @param This Pointer to an instance of EFI_SMM_CONTROL_PPI
236 @param Periodic TRUE to indicate a periodical SMI
237
238 @return Return value from SmmClear()
239
240 **/
241 EFI_STATUS
242 EFIAPI
PeiDeactivate(IN EFI_PEI_SERVICES ** PeiServices,IN PEI_SMM_CONTROL_PPI * This,IN BOOLEAN Periodic OPTIONAL)243 PeiDeactivate (
244 IN EFI_PEI_SERVICES **PeiServices,
245 IN PEI_SMM_CONTROL_PPI *This,
246 IN BOOLEAN Periodic OPTIONAL
247 )
248 {
249 if (Periodic) {
250 return EFI_INVALID_PARAMETER;
251 }
252 return SmmClear ();
253 }
254
255 /**
256 This is the constructor for the SMM Control Ppi.
257
258 This function installs EFI_SMM_CONTROL_PPI.
259
260 @param FileHandle Handle of the file being invoked.
261 @param PeiServices Describes the list of possible PEI Services.
262
263 @retval EFI_UNSUPPORTED There's no Intel ICH on this platform
264 @return The status returned from InstallPpi().
265
266 --*/
267 EFI_STATUS
268 EFIAPI
SmmControlPeiEntry(IN EFI_PEI_FILE_HANDLE FileHandle,IN CONST EFI_PEI_SERVICES ** PeiServices)269 SmmControlPeiEntry (
270 IN EFI_PEI_FILE_HANDLE FileHandle,
271 IN CONST EFI_PEI_SERVICES **PeiServices
272 )
273 {
274 EFI_STATUS Status;
275
276 Status = (**PeiServices).InstallPpi (PeiServices, &mPpiList);
277 ASSERT_EFI_ERROR (Status);
278
279 return Status;
280 }
281