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