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