1 /** @file 2 File to contain all the hardware specific stuff for the Smm Sw dispatch protocol. 3 4 Copyright (c) 2017, Intel Corporation. All rights reserved.<BR> 5 SPDX-License-Identifier: BSD-2-Clause-Patent 6 7 **/ 8 #include "PchSmmHelpers.h" 9 10 #include <Protocol/SmmCpu.h> 11 // 12 // There is only one instance for SwCommBuffer. 13 // It's safe in SMM since there is no re-entry for the function. 14 // 15 GLOBAL_REMOVE_IF_UNREFERENCED EFI_SMM_SW_CONTEXT mPchSwCommBuffer; 16 GLOBAL_REMOVE_IF_UNREFERENCED EFI_SMM_CPU_PROTOCOL *mSmmCpuProtocol; 17 18 GLOBAL_REMOVE_IF_UNREFERENCED CONST PCH_SMM_SOURCE_DESC SW_SOURCE_DESC = { 19 PCH_SMM_NO_FLAGS, 20 { 21 { 22 { 23 ACPI_ADDR_TYPE, 24 {R_PCH_SMI_EN} 25 }, 26 S_PCH_SMI_EN, 27 N_PCH_SMI_EN_APMC 28 }, 29 NULL_BIT_DESC_INITIALIZER 30 }, 31 { 32 { 33 { 34 ACPI_ADDR_TYPE, 35 {R_PCH_SMI_STS} 36 }, 37 S_PCH_SMI_STS, 38 N_PCH_SMI_STS_APM 39 } 40 }, 41 { 42 { 43 ACPI_ADDR_TYPE, 44 {R_PCH_SMI_STS} 45 }, 46 S_PCH_SMI_STS, 47 N_PCH_SMI_STS_APM 48 } 49 }; 50 51 /** 52 Get the Software Smi value 53 54 @param[in] Record No use 55 @param[out] Context The context that includes Software Smi value to be filled 56 57 **/ 58 VOID 59 EFIAPI 60 SwGetContext ( 61 IN DATABASE_RECORD *Record, 62 OUT PCH_SMM_CONTEXT *Context 63 ) 64 { 65 UINT8 ApmCnt; 66 67 ApmCnt = IoRead8 ((UINTN) R_PCH_APM_CNT); 68 69 Context->Sw.SwSmiInputValue = ApmCnt; 70 } 71 72 /** 73 Check whether software SMI value of two contexts match 74 75 @param[in] Context1 Context 1 that includes software SMI value 1 76 @param[in] Context2 Context 2 that includes software SMI value 2 77 78 @retval FALSE Software SMI value match 79 @retval TRUE Software SMI value don't match 80 **/ 81 BOOLEAN 82 EFIAPI 83 SwCmpContext ( 84 IN PCH_SMM_CONTEXT *Context1, 85 IN PCH_SMM_CONTEXT *Context2 86 ) 87 { 88 return (BOOLEAN) (Context1->Sw.SwSmiInputValue == Context2->Sw.SwSmiInputValue); 89 } 90 91 /** 92 Gather the CommBuffer information of SmmSwDispatch2. 93 94 @param[in] Record No use 95 @param[out] CommBuffer Point to the CommBuffer structure 96 @param[out] CommBufferSize Point to the Size of CommBuffer structure 97 98 **/ 99 VOID 100 EFIAPI 101 SwGetCommBuffer ( 102 IN DATABASE_RECORD *Record, 103 OUT VOID **CommBuffer, 104 OUT UINTN *CommBufferSize 105 ) 106 { 107 EFI_STATUS Status; 108 EFI_SMM_SAVE_STATE_IO_INFO SmiIoInfo; 109 UINTN Index; 110 111 ASSERT (Record->ProtocolType == SwType); 112 113 mPchSwCommBuffer.CommandPort = IoRead8 (R_PCH_APM_CNT); 114 mPchSwCommBuffer.DataPort = IoRead8 (R_PCH_APM_STS); 115 116 // 117 // Try to find which CPU trigger SWSMI 118 // 119 mPchSwCommBuffer.SwSmiCpuIndex = 0; 120 for (Index = 0; Index < gSmst->NumberOfCpus; Index++) { 121 Status = mSmmCpuProtocol->ReadSaveState ( 122 mSmmCpuProtocol, 123 sizeof (EFI_SMM_SAVE_STATE_IO_INFO), 124 EFI_SMM_SAVE_STATE_REGISTER_IO, 125 Index, 126 &SmiIoInfo 127 ); 128 if (EFI_ERROR (Status)) { 129 continue; 130 } 131 if (SmiIoInfo.IoPort == R_PCH_APM_CNT) { 132 // 133 // Find matched CPU. 134 // 135 mPchSwCommBuffer.SwSmiCpuIndex = Index; 136 break; 137 } 138 } 139 140 /// 141 /// Return the CommBuffer 142 /// 143 *CommBuffer = (VOID *) &mPchSwCommBuffer; 144 *CommBufferSize = sizeof (EFI_SMM_SW_CONTEXT); 145 } 146 147 /** 148 Init required protocol for Pch Sw Dispatch protocol. 149 150 151 **/ 152 VOID 153 PchSwDispatchInit ( 154 VOID 155 ) 156 { 157 EFI_STATUS Status; 158 // 159 // Locate PI SMM CPU protocol 160 // 161 Status = gSmst->SmmLocateProtocol (&gEfiSmmCpuProtocolGuid, NULL, (VOID **)&mSmmCpuProtocol); 162 ASSERT_EFI_ERROR (Status); 163 } 164