/** @file This module provides an implementation of the SMM Control PPI for use with the QNC. Copyright (c) 2013-2015 Intel Corporation. SPDX-License-Identifier: BSD-2-Clause-Patent **/ #include #include #include #include #include #include #include #include #include #include #include /** Generates an SMI using the parameters passed in. @param PeiServices Describes the list of possible PEI Services. @param This A pointer to an instance of EFI_SMM_CONTROL_PPI @param ArgumentBuffer The argument buffer @param ArgumentBufferSize The size of the argument buffer @param Periodic TRUE to indicate a periodical SMI @param ActivationInterval Interval of the periodical SMI @retval EFI_INVALID_PARAMETER Periodic is TRUE or ArgumentBufferSize > 1 @retval EFI_SUCCESS SMI generated **/ EFI_STATUS 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 ); /** Clears an SMI. @param PeiServices Describes the list of possible PEI Services. @param This Pointer to an instance of EFI_SMM_CONTROL_PPI @param Periodic TRUE to indicate a periodical SMI @return Return value from SmmClear() **/ EFI_STATUS EFIAPI PeiDeactivate ( IN EFI_PEI_SERVICES **PeiServices, IN PEI_SMM_CONTROL_PPI *This, IN BOOLEAN Periodic OPTIONAL ); PEI_SMM_CONTROL_PPI mSmmControlPpi = { PeiActivate, PeiDeactivate }; EFI_PEI_PPI_DESCRIPTOR mPpiList = { (EFI_PEI_PPI_DESCRIPTOR_PPI | EFI_PEI_PPI_DESCRIPTOR_TERMINATE_LIST), &gPeiSmmControlPpiGuid, &mSmmControlPpi }; /** Clear SMI related chipset status and re-enable SMI by setting the EOS bit. @retval EFI_SUCCESS The requested operation has been carried out successfully @retval EFI_DEVICE_ERROR The EOS bit could not be set. **/ EFI_STATUS SmmClear ( VOID ) { UINT16 GPE0BLK_Base; // // Get GPE0BLK_Base // GPE0BLK_Base = PcdGet16 (PcdGpe0blkIoBaseAddress); // // Clear the Power Button Override Status Bit, it gates EOS from being set. // In QuarkNcSocId - Bit is read only. Handled by external SMC, do nothing. // // // Clear the APM SMI Status Bit // IoWrite32 ((GPE0BLK_Base + R_QNC_GPE0BLK_SMIS), B_QNC_GPE0BLK_SMIS_APM); // // Set the EOS Bit // IoOr32 ((GPE0BLK_Base + R_QNC_GPE0BLK_SMIS), B_QNC_GPE0BLK_SMIS_EOS); return EFI_SUCCESS; } EFI_STATUS EFIAPI SmmTrigger ( IN UINT8 Data ) /*++ Routine Description: Trigger the software SMI Arguments: Data The value to be set on the software SMI data port Returns: EFI_SUCCESS Function completes successfully --*/ { UINT16 GPE0BLK_Base; UINT32 NewValue; // // Get GPE0BLK_Base // GPE0BLK_Base = PcdGet16 (PcdGpe0blkIoBaseAddress); // // Enable the APMC SMI // IoOr32 (GPE0BLK_Base + R_QNC_GPE0BLK_SMIE, B_QNC_GPE0BLK_SMIE_APM); // // Enable SMI globally // NewValue = QNCPortRead (QUARK_NC_HOST_BRIDGE_SB_PORT_ID, QNC_MSG_FSBIC_REG_HMISC); NewValue |= SMI_EN; QNCPortWrite (QUARK_NC_HOST_BRIDGE_SB_PORT_ID, QNC_MSG_FSBIC_REG_HMISC, NewValue); // // Generate the APMC SMI // IoWrite8 (PcdGet16 (PcdSmmActivationPort), Data); return EFI_SUCCESS; } /** Generates an SMI using the parameters passed in. @param PeiServices Describes the list of possible PEI Services. @param This A pointer to an instance of EFI_SMM_CONTROL_PPI @param ArgumentBuffer The argument buffer @param ArgumentBufferSize The size of the argument buffer @param Periodic TRUE to indicate a periodical SMI @param ActivationInterval Interval of the periodical SMI @retval EFI_INVALID_PARAMETER Periodic is TRUE or ArgumentBufferSize > 1 @retval EFI_SUCCESS SMI generated **/ EFI_STATUS 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 ) { INT8 Data; EFI_STATUS Status; // // Periodic SMI not supported. // if (Periodic) { DEBUG ((DEBUG_WARN, "Invalid parameter\n")); return EFI_INVALID_PARAMETER; } if (ArgumentBuffer == NULL) { Data = 0xFF; } else { if (ArgumentBufferSize == NULL || *ArgumentBufferSize != 1) { return EFI_INVALID_PARAMETER; } Data = *ArgumentBuffer; } // // Clear any pending the APM SMI // Status = SmmClear (); if (EFI_ERROR (Status)) { return Status; } return SmmTrigger (Data); } /** Clears an SMI. @param PeiServices Describes the list of possible PEI Services. @param This Pointer to an instance of EFI_SMM_CONTROL_PPI @param Periodic TRUE to indicate a periodical SMI @return Return value from SmmClear() **/ EFI_STATUS EFIAPI PeiDeactivate ( IN EFI_PEI_SERVICES **PeiServices, IN PEI_SMM_CONTROL_PPI *This, IN BOOLEAN Periodic OPTIONAL ) { if (Periodic) { return EFI_INVALID_PARAMETER; } return SmmClear (); } /** This is the constructor for the SMM Control Ppi. This function installs EFI_SMM_CONTROL_PPI. @param FileHandle Handle of the file being invoked. @param PeiServices Describes the list of possible PEI Services. @retval EFI_UNSUPPORTED There's no Intel ICH on this platform @return The status returned from InstallPpi(). --*/ EFI_STATUS EFIAPI SmmControlPeiEntry ( IN EFI_PEI_FILE_HANDLE FileHandle, IN CONST EFI_PEI_SERVICES **PeiServices ) { EFI_STATUS Status; Status = (**PeiServices).InstallPpi (PeiServices, &mPpiList); ASSERT_EFI_ERROR (Status); return Status; }