hc
2024-03-25 edb30157bad0c0001c32b854271ace01d3b9a16a
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
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
/** @file
  This is the driver that initializes the Intel System Agent.
 
  Copyright (c) 2021, Intel Corporation. All rights reserved.<BR>
  SPDX-License-Identifier: BSD-2-Clause-Patent
**/
#include "SaInitDxe.h"
#include "SaInit.h"
#include <SaConfigHob.h>
#include <Protocol/PciEnumerationComplete.h>
#include <MemInfoHob.h>
#include <Protocol/SaIotrapSmi.h>
 
GLOBAL_REMOVE_IF_UNREFERENCED UINT16                   mPcieIoTrapAddress;
 
///
/// Global Variables
///
extern SA_CONFIG_HOB         *mSaConfigHob;
 
 
/**
  SystemAgent Dxe Initialization.
 
  @param[in] ImageHandle             Handle for the image of this driver
  @param[in] SystemTable             Pointer to the EFI System Table
 
  @retval EFI_SUCCESS             The function completed successfully
  @retval EFI_OUT_OF_RESOURCES    No enough buffer to allocate
**/
EFI_STATUS
EFIAPI
SaInitEntryPointDxe (
  IN EFI_HANDLE         ImageHandle,
  IN EFI_SYSTEM_TABLE   *SystemTable
  )
{
  EFI_STATUS                Status;
  VOID                      *Registration;
  EFI_EVENT                 ReadyToBoot;
 
 
  DEBUG ((DEBUG_INFO, "SaInitDxe Start\n"));
 
  SaInitEntryPoint ();
 
  Status = SaAcpiInit (ImageHandle);
  ///
  /// Create PCI Enumeration Completed callback for CPU PCIe
  ///
  EfiCreateProtocolNotifyEvent (
    &gEfiPciEnumerationCompleteProtocolGuid,
    TPL_CALLBACK,
    CpuPciEnumCompleteCallback,
    NULL,
    &Registration
    );
 
  //
  // Register a Ready to boot event to config PCIE power management setting after OPROM executed
  //
  Status = EfiCreateEventReadyToBootEx (
             TPL_CALLBACK,
             SaOnReadyToBoot,
             NULL,
             &ReadyToBoot
             );
  ASSERT_EFI_ERROR (Status);
 
  DEBUG ((DEBUG_INFO, "SaInitDxe End\n"));
 
  return EFI_SUCCESS;
}
 
/**
  Do PCIE power management while resume from S3
**/
VOID
ReconfigureCpuPciePowerManagementForS3 (
  VOID
  )
{
  EFI_STATUS                            Status;
  UINT32                                Data32;
  SA_IOTRAP_SMI_PROTOCOL                *CpuPcieIoTrapProtocol;
 
  Status = gBS->LocateProtocol (&gCpuPcieIoTrapProtocolGuid, NULL, (VOID **) &CpuPcieIoTrapProtocol);
  if (EFI_ERROR (Status)) {
    return;
  }
  mPcieIoTrapAddress = CpuPcieIoTrapProtocol->SaIotrapSmiAddress;
  DEBUG ((DEBUG_INFO, "PcieIoTrapAddress: %0x\n", mPcieIoTrapAddress));
 
  if (mPcieIoTrapAddress != 0) {
    //
    // Save PCH PCIE IoTrap address to re-config PCIE power management setting after resume from S3
    //
    Data32 = CpuPciePmTrap;
    S3BootScriptSaveIoWrite (
      S3BootScriptWidthUint32,
      (UINTN) (mPcieIoTrapAddress),
      1,
      &Data32
      );
  } else {
    ASSERT (FALSE);
  }
}
 
 
/**
  SA initialization before boot to OS
 
  @param[in] Event                A pointer to the Event that triggered the callback.
  @param[in] Context              A pointer to private data registered with the callback function.
**/
VOID
EFIAPI
SaOnReadyToBoot (
  IN EFI_EVENT    Event,
  IN VOID         *Context
  )
{
  DEBUG ((DEBUG_INFO, "Uefi SaOnReadyToBoot() Start\n"));
 
  if (Event != NULL) {
    gBS->CloseEvent (Event);
  }
 
  //
  // Trigger an Iotrap SMI to config PCIE power management setting after PCI enumrate is done
  //
#if FixedPcdGetBool(PcdCpuPcieEnable) == 1
  if (mPcieIoTrapAddress != 0) {
    IoWrite32 ((UINTN) mPcieIoTrapAddress, CpuPciePmTrap);
  } else {
    ASSERT (FALSE);
  }
#endif
  DEBUG ((DEBUG_INFO, "Uefi SaOnReadyToBoot() End\n"));
}
 
 
/**
  This function gets registered as a callback to perform CPU PCIe initialization before EndOfDxe
 
  @param[in] Event     - A pointer to the Event that triggered the callback.
  @param[in] Context   - A pointer to private data registered with the callback function.
**/
VOID
EFIAPI
CpuPciEnumCompleteCallback (
  IN EFI_EVENT    Event,
  IN VOID         *Context
  )
{
  EFI_STATUS          Status;
  VOID                *ProtocolPointer;
 
  DEBUG ((DEBUG_INFO, "CpuPciEnumCompleteCallback Start\n"));
  ///
  /// Check if this is first time called by EfiCreateProtocolNotifyEvent() or not,
  /// if it is, we will skip it until real event is triggered
  ///
  Status = gBS->LocateProtocol (&gEfiPciEnumerationCompleteProtocolGuid, NULL, (VOID **) &ProtocolPointer);
  if (EFI_SUCCESS != Status) {
    return;
  }
 
  gBS->CloseEvent (Event);
 
  ReconfigureCpuPciePowerManagementForS3();
  //
  // Routine for update DMAR
  //
  UpdateDmarEndOfPcieEnum ();
 
  UpdateSaGnvsForMmioResourceBaseLength ();
  DEBUG ((DEBUG_INFO, "CpuPciEnumCompleteCallback End\n"));
  return;
}