2 This module produces the SMM COntrol2 Protocol for QNC
4 Copyright (c) 2013-2015 Intel Corporation.
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
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.
17 #include <Protocol/SmmControl2.h>
18 #include <IndustryStandard/Pci.h>
19 #include <Library/DebugLib.h>
20 #include <Library/UefiBootServicesTableLib.h>
21 #include <Library/UefiRuntimeServicesTableLib.h>
22 #include <Library/PcdLib.h>
23 #include <Library/IoLib.h>
24 #include <Library/PciLib.h>
25 #include <IntelQNCDxe.h>
26 #include <Library/QNCAccessLib.h>
27 #include <Uefi/UefiBaseType.h>
29 #define EFI_INTERNAL_POINTER 0x00000004
31 extern EFI_GUID gEfiEventVirtualAddressChangeGuid
;
34 Generates an SMI using the parameters passed in.
36 @param This A pointer to an instance of
37 EFI_SMM_CONTROL2_PROTOCOL
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
43 @retval EFI_INVALID_PARAMETER Periodic is TRUE or ArgumentBufferSize > 1
44 @return Return value from SmmTrigger().
50 IN CONST EFI_SMM_CONTROL2_PROTOCOL
*This
,
51 IN OUT UINT8
*CommandPort OPTIONAL
,
52 IN OUT UINT8
*DataPort OPTIONAL
,
53 IN BOOLEAN Periodic OPTIONAL
,
54 IN EFI_SMM_PERIOD ActivationInterval OPTIONAL
60 @param This Pointer to an instance of EFI_SMM_CONTROL2_PROTOCOL
61 @param Periodic TRUE to indicate a periodical SMI
63 @return Return value from SmmClear()
69 IN CONST EFI_SMM_CONTROL2_PROTOCOL
*This
,
70 IN BOOLEAN Periodic OPTIONAL
74 /// Handle for the SMM Control2 Protocol
76 EFI_HANDLE mSmmControl2Handle
= NULL
;
79 /// SMM COntrol2 Protocol instance
81 EFI_SMM_CONTROL2_PROTOCOL mSmmControl2
= {
89 SmmControlVirtualddressChangeEvent (
97 Fixup internal data pointers so that the services can be called in virtual mode.
101 Event The event registered.
102 Context Event context.
110 gRT
->ConvertPointer (EFI_INTERNAL_POINTER
, (VOID
*) &(mSmmControl2
.Trigger
));
111 gRT
->ConvertPointer (EFI_INTERNAL_POINTER
, (VOID
*) &(mSmmControl2
.Clear
));
115 Clear SMI related chipset status and re-enable SMI by setting the EOS bit.
117 @retval EFI_SUCCESS The requested operation has been carried out successfully
118 @retval EFI_DEVICE_ERROR The EOS bit could not be set.
130 // Get PM1BLK_Base & GPE0BLK_Base
132 PM1BLK_Base
= PcdGet16 (PcdPm1blkIoBaseAddress
);
133 GPE0BLK_Base
= PcdGet16 (PcdGpe0blkIoBaseAddress
);
136 // Clear the Power Button Override Status Bit, it gates EOS from being set.
137 // In QuarkNcSocId - Bit is read only. Handled by external SMC, do nothing.
141 // Clear the APM SMI Status Bit
143 IoWrite32 ((GPE0BLK_Base
+ R_QNC_GPE0BLK_SMIS
), B_QNC_GPE0BLK_SMIS_APM
);
148 IoOr32 ((GPE0BLK_Base
+ R_QNC_GPE0BLK_SMIS
), B_QNC_GPE0BLK_SMIS_EOS
);
154 Generates an SMI using the parameters passed in.
156 @param This A pointer to an instance of
157 EFI_SMM_CONTROL_PROTOCOL
158 @param ArgumentBuffer The argument buffer
159 @param ArgumentBufferSize The size of the argument buffer
160 @param Periodic TRUE to indicate a periodical SMI
161 @param ActivationInterval Interval of the periodical SMI
163 @retval EFI_INVALID_PARAMETER Periodic is TRUE or ArgumentBufferSize > 1
164 @retval EFI_SUCCESS SMI generated
170 IN CONST EFI_SMM_CONTROL2_PROTOCOL
*This
,
171 IN OUT UINT8
*CommandPort OPTIONAL
,
172 IN OUT UINT8
*DataPort OPTIONAL
,
173 IN BOOLEAN Periodic OPTIONAL
,
174 IN EFI_SMM_PERIOD ActivationInterval OPTIONAL
183 GPE0BLK_Base
= PcdGet16 (PcdGpe0blkIoBaseAddress
);
186 return EFI_INVALID_PARAMETER
;
190 // Clear any pending the APM SMI
192 if (EFI_ERROR (SmmClear())) {
193 return EFI_DEVICE_ERROR
;
197 // Enable the APMC SMI
199 IoOr32 (GPE0BLK_Base
+ R_QNC_GPE0BLK_SMIE
, B_QNC_GPE0BLK_SMIE_APM
);
202 // Enable SMI globally
204 NewValue
= QNCPortRead (QUARK_NC_HOST_BRIDGE_SB_PORT_ID
, QNC_MSG_FSBIC_REG_HMISC
);
206 QNCPortWrite (QUARK_NC_HOST_BRIDGE_SB_PORT_ID
, QNC_MSG_FSBIC_REG_HMISC
, NewValue
);
212 if (DataPort
== NULL
) {
213 IoWrite8 (PcdGet16 (PcdSmmDataPort
), 0xFF);
215 IoWrite8 (PcdGet16 (PcdSmmDataPort
), *DataPort
);
219 // Generate the APMC SMI
221 if (CommandPort
== NULL
) {
222 IoWrite8 (PcdGet16 (PcdSmmActivationPort
), 0xFF);
224 IoWrite8 (PcdGet16 (PcdSmmActivationPort
), *CommandPort
);
233 @param This Pointer to an instance of EFI_SMM_CONTROL_PROTOCOL
234 @param Periodic TRUE to indicate a periodical SMI
236 @return Return value from SmmClear()
242 IN CONST EFI_SMM_CONTROL2_PROTOCOL
*This
,
247 return EFI_INVALID_PARAMETER
;
254 This is the constructor for the SMM Control protocol.
256 This function installs EFI_SMM_CONTROL2_PROTOCOL.
258 @param ImageHandle Handle for the image of this driver
259 @param SystemTable Pointer to the EFI System Table
261 @retval EFI_UNSUPPORTED There's no Intel ICH on this platform
262 @return The status returned from InstallProtocolInterface().
267 IN EFI_HANDLE ImageHandle
,
268 IN EFI_SYSTEM_TABLE
*SystemTable
279 // Get PM1BLK_Base & GPE0BLK_Base
281 PM1BLK_Base
= PcdGet16 (PcdPm1blkIoBaseAddress
);
282 GPE0BLK_Base
= PcdGet16 (PcdGpe0blkIoBaseAddress
);
285 // Install our protocol interfaces on the device's handle
287 Status
= gBS
->InstallMultipleProtocolInterfaces (
289 &gEfiSmmControl2ProtocolGuid
, &mSmmControl2
,
292 ASSERT_EFI_ERROR (Status
);
295 // Determine whether an ACPI OS is present (via the SCI_EN bit)
297 SciEn
= (BOOLEAN
)((IoRead16 (PM1BLK_Base
+ R_QNC_PM1BLK_PM1C
) & B_QNC_PM1BLK_PM1C_SCIEN
) != 0);
300 // Clear any SMIs that double as SCIs (when SCI_EN==0)
302 IoWrite16 ((PM1BLK_Base
+ R_QNC_PM1BLK_PM1S
), B_QNC_PM1BLK_PM1S_ALL
);
303 IoWrite16 ((PM1BLK_Base
+ R_QNC_PM1BLK_PM1E
), 0x00000000);
304 IoWrite32 ((PM1BLK_Base
+ R_QNC_PM1BLK_PM1C
), 0x00000000);
305 IoWrite32 ((GPE0BLK_Base
+ R_QNC_GPE0BLK_GPE0S
), B_QNC_GPE0BLK_GPE0S_ALL
);
306 IoWrite32 ((GPE0BLK_Base
+ R_QNC_GPE0BLK_GPE0E
), 0x00000000);
310 // Clear and disable all SMIs that are unaffected by SCI_EN
313 IoWrite32 ((GPE0BLK_Base
+ R_QNC_GPE0BLK_SMIE
), 0x00000000);
314 IoWrite32 ((GPE0BLK_Base
+ R_QNC_GPE0BLK_SMIS
), (B_QNC_GPE0BLK_SMIS_EOS
+ B_QNC_GPE0BLK_SMIS_ALL
));
317 // Enable SMI globally
319 NewValue
= QNCPortRead (QUARK_NC_HOST_BRIDGE_SB_PORT_ID
, QNC_MSG_FSBIC_REG_HMISC
);
321 QNCPortWrite (QUARK_NC_HOST_BRIDGE_SB_PORT_ID
, QNC_MSG_FSBIC_REG_HMISC
, NewValue
);
324 // Make sure to write this register last -- EOS re-enables SMIs for the QNC
327 GPE0BLK_Base
+ R_QNC_GPE0BLK_SMIE
,
328 (UINT32
)(~B_QNC_GPE0BLK_SMIE_ALL
),
329 B_QNC_GPE0BLK_SMIE_APM
333 // Make sure EOS bit cleared
336 if (IoRead32 (GPE0BLK_Base
+ R_QNC_GPE0BLK_SMIS
) & B_QNC_GPE0BLK_SMIS_EOS
) {
339 "******************************************************************************\n"
340 "BIG ERROR: SmmControl constructor couldn't properly initialize the ACPI table.\n"
341 " SmmControl->Clear will probably hang. \n"
342 " NOTE: SCI_EN = %d \n"
343 "******************************************************************************\n",
348 // If we want the system to stop, then keep the ASSERT(FALSE).
349 // Otherwise, comment it out.
355 Status
= gBS
->CreateEventEx (
358 SmmControlVirtualddressChangeEvent
,
360 &gEfiEventVirtualAddressChangeGuid
,
363 ASSERT_EFI_ERROR (Status
);