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 95 SmmClear ( 96 VOID 97 ) 98 { 99 UINT16 PM1BLK_Base; 100 UINT16 GPE0BLK_Base; 101 102 // 103 // Get PM1BLK_Base & GPE0BLK_Base 104 // 105 PM1BLK_Base = PcdGet16 (PcdPm1blkIoBaseAddress); 106 GPE0BLK_Base = PcdGet16 (PcdGpe0blkIoBaseAddress); 107 108 // 109 // Clear the Power Button Override Status Bit, it gates EOS from being set. 110 // In QuarkNcSocId - Bit is read only. Handled by external SMC, do nothing. 111 // 112 113 // 114 // Clear the APM SMI Status Bit 115 // 116 IoWrite32 ((GPE0BLK_Base + R_QNC_GPE0BLK_SMIS), B_QNC_GPE0BLK_SMIS_APM); 117 118 // 119 // Set the EOS Bit 120 // 121 IoOr32 ((GPE0BLK_Base + R_QNC_GPE0BLK_SMIS), B_QNC_GPE0BLK_SMIS_EOS); 122 123 return EFI_SUCCESS; 124 } 125 126 127 EFI_STATUS 128 EFIAPI 129 SmmTrigger ( 130 IN UINT8 Data 131 ) 132 /*++ 133 134 Routine Description: 135 136 Trigger the software SMI 137 138 Arguments: 139 140 Data The value to be set on the software SMI data port 141 142 Returns: 143 144 EFI_SUCCESS Function completes successfully 145 146 --*/ 147 { 148 UINT16 GPE0BLK_Base; 149 UINT32 NewValue; 150 151 // 152 // Get GPE0BLK_Base 153 // 154 GPE0BLK_Base = PcdGet16 (PcdGpe0blkIoBaseAddress); 155 156 // 157 // Enable the APMC SMI 158 // 159 IoOr32 (GPE0BLK_Base + R_QNC_GPE0BLK_SMIE, B_QNC_GPE0BLK_SMIE_APM); 160 161 // 162 // Enable SMI globally 163 // 164 NewValue = QNCPortRead (QUARK_NC_HOST_BRIDGE_SB_PORT_ID, QNC_MSG_FSBIC_REG_HMISC); 165 NewValue |= SMI_EN; 166 QNCPortWrite (QUARK_NC_HOST_BRIDGE_SB_PORT_ID, QNC_MSG_FSBIC_REG_HMISC, NewValue); 167 168 169 // 170 // Generate the APMC SMI 171 // 172 IoWrite8 (PcdGet16 (PcdSmmActivationPort), Data); 173 174 return EFI_SUCCESS; 175 } 176 177 /** 178 Generates an SMI using the parameters passed in. 179 180 @param PeiServices Describes the list of possible PEI Services. 181 @param This A pointer to an instance of 182 EFI_SMM_CONTROL_PPI 183 @param ArgumentBuffer The argument buffer 184 @param ArgumentBufferSize The size of the argument buffer 185 @param Periodic TRUE to indicate a periodical SMI 186 @param ActivationInterval Interval of the periodical SMI 187 188 @retval EFI_INVALID_PARAMETER Periodic is TRUE or ArgumentBufferSize > 1 189 @retval EFI_SUCCESS SMI generated 190 191 **/ 192 EFI_STATUS 193 EFIAPI 194 PeiActivate ( 195 IN EFI_PEI_SERVICES **PeiServices, 196 IN PEI_SMM_CONTROL_PPI *This, 197 IN OUT INT8 *ArgumentBuffer OPTIONAL, 198 IN OUT UINTN *ArgumentBufferSize OPTIONAL, 199 IN BOOLEAN Periodic OPTIONAL, 200 IN UINTN ActivationInterval OPTIONAL 201 ) 202 { 203 INT8 Data; 204 EFI_STATUS Status; 205 // 206 // Periodic SMI not supported. 207 // 208 if (Periodic) { 209 DEBUG ((DEBUG_WARN, "Invalid parameter\n")); 210 return EFI_INVALID_PARAMETER; 211 } 212 213 if (ArgumentBuffer == NULL) { 214 Data = 0xFF; 215 } else { 216 if (ArgumentBufferSize == NULL || *ArgumentBufferSize != 1) { 217 return EFI_INVALID_PARAMETER; 218 } 219 220 Data = *ArgumentBuffer; 221 } 222 // 223 // Clear any pending the APM SMI 224 // 225 Status = SmmClear (); 226 if (EFI_ERROR (Status)) { 227 return Status; 228 } 229 230 return SmmTrigger (Data); 231 } 232 233 /** 234 Clears an SMI. 235 236 @param PeiServices Describes the list of possible PEI Services. 237 @param This Pointer to an instance of EFI_SMM_CONTROL_PPI 238 @param Periodic TRUE to indicate a periodical SMI 239 240 @return Return value from SmmClear() 241 242 **/ 243 EFI_STATUS 244 EFIAPI 245 PeiDeactivate ( 246 IN EFI_PEI_SERVICES **PeiServices, 247 IN PEI_SMM_CONTROL_PPI *This, 248 IN BOOLEAN Periodic OPTIONAL 249 ) 250 { 251 if (Periodic) { 252 return EFI_INVALID_PARAMETER; 253 } 254 return SmmClear (); 255 } 256 257 /** 258 This is the constructor for the SMM Control Ppi. 259 260 This function installs EFI_SMM_CONTROL_PPI. 261 262 @param FileHandle Handle of the file being invoked. 263 @param PeiServices Describes the list of possible PEI Services. 264 265 @retval EFI_UNSUPPORTED There's no Intel ICH on this platform 266 @return The status returned from InstallPpi(). 267 268 --*/ 269 EFI_STATUS 270 EFIAPI 271 SmmControlPeiEntry ( 272 IN EFI_PEI_FILE_HANDLE FileHandle, 273 IN CONST EFI_PEI_SERVICES **PeiServices 274 ) 275 { 276 EFI_STATUS Status; 277 278 Status = (**PeiServices).InstallPpi (PeiServices, &mPpiList); 279 ASSERT_EFI_ERROR (Status); 280 281 return Status; 282 } 283