2 This module produces the SMM COntrol2 Protocol for QNC
4 Copyright (c) 2013-2015 Intel Corporation.
6 SPDX-License-Identifier: BSD-2-Clause-Patent
11 #include <Protocol/SmmControl2.h>
12 #include <IndustryStandard/Pci.h>
13 #include <Library/DebugLib.h>
14 #include <Library/UefiBootServicesTableLib.h>
15 #include <Library/UefiRuntimeServicesTableLib.h>
16 #include <Library/PcdLib.h>
17 #include <Library/IoLib.h>
18 #include <Library/PciLib.h>
19 #include <IntelQNCDxe.h>
20 #include <Library/QNCAccessLib.h>
21 #include <Uefi/UefiBaseType.h>
23 #define EFI_INTERNAL_POINTER 0x00000004
25 extern EFI_GUID gEfiEventVirtualAddressChangeGuid
;
28 Generates an SMI using the parameters passed in.
30 @param This A pointer to an instance of
31 EFI_SMM_CONTROL2_PROTOCOL
32 @param ArgumentBuffer The argument buffer
33 @param ArgumentBufferSize The size of the argument buffer
34 @param Periodic TRUE to indicate a periodical SMI
35 @param ActivationInterval Interval of the periodical SMI
37 @retval EFI_INVALID_PARAMETER Periodic is TRUE or ArgumentBufferSize > 1
38 @return Return value from SmmTrigger().
44 IN CONST EFI_SMM_CONTROL2_PROTOCOL
*This
,
45 IN OUT UINT8
*CommandPort OPTIONAL
,
46 IN OUT UINT8
*DataPort OPTIONAL
,
47 IN BOOLEAN Periodic OPTIONAL
,
48 IN EFI_SMM_PERIOD ActivationInterval OPTIONAL
54 @param This Pointer to an instance of EFI_SMM_CONTROL2_PROTOCOL
55 @param Periodic TRUE to indicate a periodical SMI
57 @return Return value from SmmClear()
63 IN CONST EFI_SMM_CONTROL2_PROTOCOL
*This
,
64 IN BOOLEAN Periodic OPTIONAL
68 /// Handle for the SMM Control2 Protocol
70 EFI_HANDLE mSmmControl2Handle
= NULL
;
73 /// SMM COntrol2 Protocol instance
75 EFI_SMM_CONTROL2_PROTOCOL mSmmControl2
= {
83 SmmControlVirtualddressChangeEvent (
91 Fixup internal data pointers so that the services can be called in virtual mode.
95 Event The event registered.
96 Context Event context.
104 gRT
->ConvertPointer (EFI_INTERNAL_POINTER
, (VOID
*) &(mSmmControl2
.Trigger
));
105 gRT
->ConvertPointer (EFI_INTERNAL_POINTER
, (VOID
*) &(mSmmControl2
.Clear
));
109 Clear SMI related chipset status and re-enable SMI by setting the EOS bit.
111 @retval EFI_SUCCESS The requested operation has been carried out successfully
112 @retval EFI_DEVICE_ERROR The EOS bit could not be set.
125 GPE0BLK_Base
= PcdGet16 (PcdGpe0blkIoBaseAddress
);
128 // Clear the Power Button Override Status Bit, it gates EOS from being set.
129 // In QuarkNcSocId - Bit is read only. Handled by external SMC, do nothing.
133 // Clear the APM SMI Status Bit
135 IoWrite32 ((GPE0BLK_Base
+ R_QNC_GPE0BLK_SMIS
), B_QNC_GPE0BLK_SMIS_APM
);
140 IoOr32 ((GPE0BLK_Base
+ R_QNC_GPE0BLK_SMIS
), B_QNC_GPE0BLK_SMIS_EOS
);
146 Generates an SMI using the parameters passed in.
148 @param This A pointer to an instance of
149 EFI_SMM_CONTROL_PROTOCOL
150 @param ArgumentBuffer The argument buffer
151 @param ArgumentBufferSize The size of the argument buffer
152 @param Periodic TRUE to indicate a periodical SMI
153 @param ActivationInterval Interval of the periodical SMI
155 @retval EFI_INVALID_PARAMETER Periodic is TRUE or ArgumentBufferSize > 1
156 @retval EFI_SUCCESS SMI generated
162 IN CONST EFI_SMM_CONTROL2_PROTOCOL
*This
,
163 IN OUT UINT8
*CommandPort OPTIONAL
,
164 IN OUT UINT8
*DataPort OPTIONAL
,
165 IN BOOLEAN Periodic OPTIONAL
,
166 IN EFI_SMM_PERIOD ActivationInterval OPTIONAL
175 GPE0BLK_Base
= PcdGet16 (PcdGpe0blkIoBaseAddress
);
178 return EFI_INVALID_PARAMETER
;
182 // Clear any pending the APM SMI
184 if (EFI_ERROR (SmmClear())) {
185 return EFI_DEVICE_ERROR
;
189 // Enable the APMC SMI
191 IoOr32 (GPE0BLK_Base
+ R_QNC_GPE0BLK_SMIE
, B_QNC_GPE0BLK_SMIE_APM
);
194 // Enable SMI globally
196 NewValue
= QNCPortRead (QUARK_NC_HOST_BRIDGE_SB_PORT_ID
, QNC_MSG_FSBIC_REG_HMISC
);
198 QNCPortWrite (QUARK_NC_HOST_BRIDGE_SB_PORT_ID
, QNC_MSG_FSBIC_REG_HMISC
, NewValue
);
204 if (DataPort
== NULL
) {
205 IoWrite8 (PcdGet16 (PcdSmmDataPort
), 0xFF);
207 IoWrite8 (PcdGet16 (PcdSmmDataPort
), *DataPort
);
211 // Generate the APMC SMI
213 if (CommandPort
== NULL
) {
214 IoWrite8 (PcdGet16 (PcdSmmActivationPort
), 0xFF);
216 IoWrite8 (PcdGet16 (PcdSmmActivationPort
), *CommandPort
);
225 @param This Pointer to an instance of EFI_SMM_CONTROL_PROTOCOL
226 @param Periodic TRUE to indicate a periodical SMI
228 @return Return value from SmmClear()
234 IN CONST EFI_SMM_CONTROL2_PROTOCOL
*This
,
239 return EFI_INVALID_PARAMETER
;
246 This is the constructor for the SMM Control protocol.
248 This function installs EFI_SMM_CONTROL2_PROTOCOL.
250 @param ImageHandle Handle for the image of this driver
251 @param SystemTable Pointer to the EFI System Table
253 @retval EFI_UNSUPPORTED There's no Intel ICH on this platform
254 @return The status returned from InstallProtocolInterface().
259 IN EFI_HANDLE ImageHandle
,
260 IN EFI_SYSTEM_TABLE
*SystemTable
271 // Get PM1BLK_Base & GPE0BLK_Base
273 PM1BLK_Base
= PcdGet16 (PcdPm1blkIoBaseAddress
);
274 GPE0BLK_Base
= PcdGet16 (PcdGpe0blkIoBaseAddress
);
277 // Install our protocol interfaces on the device's handle
279 Status
= gBS
->InstallMultipleProtocolInterfaces (
281 &gEfiSmmControl2ProtocolGuid
, &mSmmControl2
,
284 ASSERT_EFI_ERROR (Status
);
287 // Determine whether an ACPI OS is present (via the SCI_EN bit)
289 SciEn
= (BOOLEAN
)((IoRead16 (PM1BLK_Base
+ R_QNC_PM1BLK_PM1C
) & B_QNC_PM1BLK_PM1C_SCIEN
) != 0);
292 // Clear any SMIs that double as SCIs (when SCI_EN==0)
294 IoWrite16 ((PM1BLK_Base
+ R_QNC_PM1BLK_PM1S
), B_QNC_PM1BLK_PM1S_ALL
);
295 IoWrite16 ((PM1BLK_Base
+ R_QNC_PM1BLK_PM1E
), 0x00000000);
296 IoWrite32 ((PM1BLK_Base
+ R_QNC_PM1BLK_PM1C
), 0x00000000);
297 IoWrite32 ((GPE0BLK_Base
+ R_QNC_GPE0BLK_GPE0S
), B_QNC_GPE0BLK_GPE0S_ALL
);
298 IoWrite32 ((GPE0BLK_Base
+ R_QNC_GPE0BLK_GPE0E
), 0x00000000);
302 // Clear and disable all SMIs that are unaffected by SCI_EN
305 IoWrite32 ((GPE0BLK_Base
+ R_QNC_GPE0BLK_SMIE
), 0x00000000);
306 IoWrite32 ((GPE0BLK_Base
+ R_QNC_GPE0BLK_SMIS
), (B_QNC_GPE0BLK_SMIS_EOS
+ B_QNC_GPE0BLK_SMIS_ALL
));
309 // Enable SMI globally
311 NewValue
= QNCPortRead (QUARK_NC_HOST_BRIDGE_SB_PORT_ID
, QNC_MSG_FSBIC_REG_HMISC
);
313 QNCPortWrite (QUARK_NC_HOST_BRIDGE_SB_PORT_ID
, QNC_MSG_FSBIC_REG_HMISC
, NewValue
);
316 // Make sure to write this register last -- EOS re-enables SMIs for the QNC
319 GPE0BLK_Base
+ R_QNC_GPE0BLK_SMIE
,
320 (UINT32
)(~B_QNC_GPE0BLK_SMIE_ALL
),
321 B_QNC_GPE0BLK_SMIE_APM
325 // Make sure EOS bit cleared
328 if (IoRead32 (GPE0BLK_Base
+ R_QNC_GPE0BLK_SMIS
) & B_QNC_GPE0BLK_SMIS_EOS
) {
331 "******************************************************************************\n"
332 "BIG ERROR: SmmControl constructor couldn't properly initialize the ACPI table.\n"
333 " SmmControl->Clear will probably hang. \n"
334 " NOTE: SCI_EN = %d \n"
335 "******************************************************************************\n",
340 // If we want the system to stop, then keep the ASSERT(FALSE).
341 // Otherwise, comment it out.
347 Status
= gBS
->CreateEventEx (
350 SmmControlVirtualddressChangeEvent
,
352 &gEfiEventVirtualAddressChangeGuid
,
355 ASSERT_EFI_ERROR (Status
);