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.
131 GPE0BLK_Base
= PcdGet16 (PcdGpe0blkIoBaseAddress
);
134 // Clear the Power Button Override Status Bit, it gates EOS from being set.
135 // In QuarkNcSocId - Bit is read only. Handled by external SMC, do nothing.
139 // Clear the APM SMI Status Bit
141 IoWrite32 ((GPE0BLK_Base
+ R_QNC_GPE0BLK_SMIS
), B_QNC_GPE0BLK_SMIS_APM
);
146 IoOr32 ((GPE0BLK_Base
+ R_QNC_GPE0BLK_SMIS
), B_QNC_GPE0BLK_SMIS_EOS
);
152 Generates an SMI using the parameters passed in.
154 @param This A pointer to an instance of
155 EFI_SMM_CONTROL_PROTOCOL
156 @param ArgumentBuffer The argument buffer
157 @param ArgumentBufferSize The size of the argument buffer
158 @param Periodic TRUE to indicate a periodical SMI
159 @param ActivationInterval Interval of the periodical SMI
161 @retval EFI_INVALID_PARAMETER Periodic is TRUE or ArgumentBufferSize > 1
162 @retval EFI_SUCCESS SMI generated
168 IN CONST EFI_SMM_CONTROL2_PROTOCOL
*This
,
169 IN OUT UINT8
*CommandPort OPTIONAL
,
170 IN OUT UINT8
*DataPort OPTIONAL
,
171 IN BOOLEAN Periodic OPTIONAL
,
172 IN EFI_SMM_PERIOD ActivationInterval OPTIONAL
181 GPE0BLK_Base
= PcdGet16 (PcdGpe0blkIoBaseAddress
);
184 return EFI_INVALID_PARAMETER
;
188 // Clear any pending the APM SMI
190 if (EFI_ERROR (SmmClear())) {
191 return EFI_DEVICE_ERROR
;
195 // Enable the APMC SMI
197 IoOr32 (GPE0BLK_Base
+ R_QNC_GPE0BLK_SMIE
, B_QNC_GPE0BLK_SMIE_APM
);
200 // Enable SMI globally
202 NewValue
= QNCPortRead (QUARK_NC_HOST_BRIDGE_SB_PORT_ID
, QNC_MSG_FSBIC_REG_HMISC
);
204 QNCPortWrite (QUARK_NC_HOST_BRIDGE_SB_PORT_ID
, QNC_MSG_FSBIC_REG_HMISC
, NewValue
);
210 if (DataPort
== NULL
) {
211 IoWrite8 (PcdGet16 (PcdSmmDataPort
), 0xFF);
213 IoWrite8 (PcdGet16 (PcdSmmDataPort
), *DataPort
);
217 // Generate the APMC SMI
219 if (CommandPort
== NULL
) {
220 IoWrite8 (PcdGet16 (PcdSmmActivationPort
), 0xFF);
222 IoWrite8 (PcdGet16 (PcdSmmActivationPort
), *CommandPort
);
231 @param This Pointer to an instance of EFI_SMM_CONTROL_PROTOCOL
232 @param Periodic TRUE to indicate a periodical SMI
234 @return Return value from SmmClear()
240 IN CONST EFI_SMM_CONTROL2_PROTOCOL
*This
,
245 return EFI_INVALID_PARAMETER
;
252 This is the constructor for the SMM Control protocol.
254 This function installs EFI_SMM_CONTROL2_PROTOCOL.
256 @param ImageHandle Handle for the image of this driver
257 @param SystemTable Pointer to the EFI System Table
259 @retval EFI_UNSUPPORTED There's no Intel ICH on this platform
260 @return The status returned from InstallProtocolInterface().
265 IN EFI_HANDLE ImageHandle
,
266 IN EFI_SYSTEM_TABLE
*SystemTable
277 // Get PM1BLK_Base & GPE0BLK_Base
279 PM1BLK_Base
= PcdGet16 (PcdPm1blkIoBaseAddress
);
280 GPE0BLK_Base
= PcdGet16 (PcdGpe0blkIoBaseAddress
);
283 // Install our protocol interfaces on the device's handle
285 Status
= gBS
->InstallMultipleProtocolInterfaces (
287 &gEfiSmmControl2ProtocolGuid
, &mSmmControl2
,
290 ASSERT_EFI_ERROR (Status
);
293 // Determine whether an ACPI OS is present (via the SCI_EN bit)
295 SciEn
= (BOOLEAN
)((IoRead16 (PM1BLK_Base
+ R_QNC_PM1BLK_PM1C
) & B_QNC_PM1BLK_PM1C_SCIEN
) != 0);
298 // Clear any SMIs that double as SCIs (when SCI_EN==0)
300 IoWrite16 ((PM1BLK_Base
+ R_QNC_PM1BLK_PM1S
), B_QNC_PM1BLK_PM1S_ALL
);
301 IoWrite16 ((PM1BLK_Base
+ R_QNC_PM1BLK_PM1E
), 0x00000000);
302 IoWrite32 ((PM1BLK_Base
+ R_QNC_PM1BLK_PM1C
), 0x00000000);
303 IoWrite32 ((GPE0BLK_Base
+ R_QNC_GPE0BLK_GPE0S
), B_QNC_GPE0BLK_GPE0S_ALL
);
304 IoWrite32 ((GPE0BLK_Base
+ R_QNC_GPE0BLK_GPE0E
), 0x00000000);
308 // Clear and disable all SMIs that are unaffected by SCI_EN
311 IoWrite32 ((GPE0BLK_Base
+ R_QNC_GPE0BLK_SMIE
), 0x00000000);
312 IoWrite32 ((GPE0BLK_Base
+ R_QNC_GPE0BLK_SMIS
), (B_QNC_GPE0BLK_SMIS_EOS
+ B_QNC_GPE0BLK_SMIS_ALL
));
315 // Enable SMI globally
317 NewValue
= QNCPortRead (QUARK_NC_HOST_BRIDGE_SB_PORT_ID
, QNC_MSG_FSBIC_REG_HMISC
);
319 QNCPortWrite (QUARK_NC_HOST_BRIDGE_SB_PORT_ID
, QNC_MSG_FSBIC_REG_HMISC
, NewValue
);
322 // Make sure to write this register last -- EOS re-enables SMIs for the QNC
325 GPE0BLK_Base
+ R_QNC_GPE0BLK_SMIE
,
326 (UINT32
)(~B_QNC_GPE0BLK_SMIE_ALL
),
327 B_QNC_GPE0BLK_SMIE_APM
331 // Make sure EOS bit cleared
334 if (IoRead32 (GPE0BLK_Base
+ R_QNC_GPE0BLK_SMIS
) & B_QNC_GPE0BLK_SMIS_EOS
) {
337 "******************************************************************************\n"
338 "BIG ERROR: SmmControl constructor couldn't properly initialize the ACPI table.\n"
339 " SmmControl->Clear will probably hang. \n"
340 " NOTE: SCI_EN = %d \n"
341 "******************************************************************************\n",
346 // If we want the system to stop, then keep the ASSERT(FALSE).
347 // Otherwise, comment it out.
353 Status
= gBS
->CreateEventEx (
356 SmmControlVirtualddressChangeEvent
,
358 &gEfiEventVirtualAddressChangeGuid
,
361 ASSERT_EFI_ERROR (Status
);