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
164
165
166
167
168
169
170
171
/** @file
  This file will perform SA PCIE Root Complex initialization.
 
  Copyright (c) 2019 Intel Corporation. All rights reserved. <BR>
 
  SPDX-License-Identifier: BSD-2-Clause-Patent
**/
 
#include "PciExpressInit.h"
#include <Private/Library/SaPcieLib.h>
#include "PcieComplex.h"
#include <Private/Protocol/SaIotrapSmi.h>
#include "SaInit.h"
 
///
/// Global variables
///
UINT16                                 mSaIotrapSmiAddress;
extern SA_CONFIG_HOB                   *mSaConfigHob;
 
///
/// Functions
///
/**
    This function gets registered as a callback to perform all SA late initialization
 
    @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
SaLateInitSmiCallback (
  IN EFI_EVENT    Event,
  IN VOID         *Context
  )
{
  EFI_STATUS                 Status;
  SA_IOTRAP_SMI_PROTOCOL     *SaIotrapSmiProtocol;
 
  if (mSaIotrapSmiAddress == 0) {
    //
    // Use global variable instead of protocol data since it maybe tampered in unsecure environment
    // Get IOTrap address when first time this routine calling (gEfiPciEnumerationCompleteProtocolGuid callback)
    //
    SaIotrapSmiProtocol = NULL;
    Status = gBS->LocateProtocol (&gSaIotrapSmiProtocolGuid, NULL, (VOID **) &SaIotrapSmiProtocol);
    ASSERT_EFI_ERROR (Status);
    if (SaIotrapSmiProtocol != NULL) {
      mSaIotrapSmiAddress = SaIotrapSmiProtocol->SaIotrapSmiAddress;
    }
  }
 
  ASSERT (mSaIotrapSmiAddress != 0);
  if (mSaIotrapSmiAddress != 0) {
    //
    // Generate IOTRAP SMI immediately
    //
    DEBUG ((DEBUG_INFO, "[SA] Issue IOTRAP SMI %X\n", mSaIotrapSmiAddress));
    IoWrite8 (mSaIotrapSmiAddress, 0);
  }
  if (Event != NULL) {
    gBS->CloseEvent (Event);
  }
  return;
}
 
/**
  This function performs Peg initialization before EndOfDxe.
  @note This function will be executed as gEfiPciEnumerationCompleteProtocolGuid protocol callback and assumed SA DXE/SMM drivers have been dispatched.
 
  @retval EFI_SUCCESS   - Always.
**/
EFI_STATUS
PegInitBeforeEndOfDxe (
  VOID
  )
{
  EFI_EVENT                       ReadyToBoot;
  EFI_STATUS                      Status;
  BOOLEAN                         AspmHasBeenHandled;
 
  DEBUG ((DEBUG_INFO, "[SA] Pcie before EndOfDxe callback.\n"));
  AspmHasBeenHandled = FALSE;
  ///
  /// SMM mode ASPM handling
  /// Check if supported and enabled
  ///
  if ((mSaConfigHob != NULL) && (mSaConfigHob->InitPcieAspmAfterOprom == TRUE)) {
    ///
    /// Do the Phase 1 SMI callback
    /// This will enumerate PCIe downstream devices
    ///
    SaLateInitSmiCallback (NULL, NULL);
 
    if (mSaIotrapSmiAddress != 0) {
      ///
      /// Create an ReadyToBoot call back event to do the Phase 3 SMI callback
      /// This will handle PEG ASPM programming after OROM execution
      /// Note: Phase 2 SMI callback will be triggered in EndOfDxe callback
      ///       to initialize rest of PCIe settings prior to OPROM
      ///
      Status = EfiCreateEventReadyToBootEx (
                 TPL_NOTIFY,
                 (EFI_EVENT_NOTIFY) SaLateInitSmiCallback,
                 NULL,
                 &ReadyToBoot
                 );
      ASSERT_EFI_ERROR (Status);
      AspmHasBeenHandled = TRUE;
    }
  }
 
  ///
  /// DXE mode ASPM handling
  /// Check if SMM mode already taken care all things
  /// TRUE to skip DXE mode task. Otherwise do DXE mode ASPM initialization
  ///
  if (AspmHasBeenHandled == FALSE) {
 
  }
 
  return EFI_SUCCESS;
}
 
/**
  This function performs SA registers Saving/Restoring in EndOfDxe callback
 
  @retval EFI_SUCCESS     - Save/restore has done
  @retval EFI_UNSUPPORTED - Save/restore not done successfully
**/
EFI_STATUS
SaSaveRestore (
  VOID
  )
{
  BOOLEAN                         SaveRestoreHasBeenHandled;
  UINT8                           SmiData;
 
  SaveRestoreHasBeenHandled = FALSE;
 
  if ((mSaConfigHob != NULL) && (mSaConfigHob->InitPcieAspmAfterOprom == TRUE)) {
    ///
    /// Generate the Phase 2 of SA SMI to do SA chipset save/restore and security lock
    ///
    SaLateInitSmiCallback (NULL, NULL);
 
    if (mSaIotrapSmiAddress != 0) {
      ///
      /// Store IOTRAP SMI address into Boot Script save table
      /// This is required to trigger this IOTRAP during S3 resume to restore all settings
      ///
      SmiData = 0;
      S3BootScriptSaveIoWrite (
        S3BootScriptWidthUint8,
        (UINTN) mSaIotrapSmiAddress,
        1,
        &SmiData
        );
      SaveRestoreHasBeenHandled = TRUE;
    }
  }
 
  ///
  /// Check if SMM mode already taken care this task
  ///
  if (SaveRestoreHasBeenHandled == TRUE) {
    return EFI_SUCCESS;
  } else {
    return EFI_UNSUPPORTED;
  }
}