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