summaryrefslogtreecommitdiff
path: root/Platform/Intel/AdvancedFeaturePkg/Ipmi/Frb/FrbDxe.c
blob: 42fc6fc2ecda4e2d81fe44626c4bbd44af2e3229 (plain)
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
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
/** @file
    IPMI FRB Driver.

Copyright (c) 2018, Intel Corporation. All rights reserved.<BR>
This program and the accompanying materials are licensed and made available under
the terms and conditions of the BSD License that accompanies this distribution.
The full text of the license may be found at
http://opensource.org/licenses/bsd-license.php.

THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.

**/

#include <PiDxe.h>
#include <Library/UefiBootServicesTableLib.h>
#include <Library/DebugLib.h>
#include <Library/BaseMemoryLib.h>
#include <Library/UefiLib.h>
#include <Library/MemoryAllocationLib.h>
#include <Library/PcdLib.h>
#include <Library/IpmiCommandLib.h>
#include <IndustryStandard/Ipmi.h>
#include <IpmiEx.h>

EFI_STATUS
EfiDisableFrb (
  VOID
  )
/*++

  Routine Description:
    This routine disables the specified FRB timer.

  Arguments:
    This        - This pointer
    FrbType     - Type of FRB timer to get data on

  Returns:
    EFI_SUCCESS     - FRB timer was disabled
    EFI_ABORTED     - Timer was already stopped
    EFI_UNSUPPORTED - This type of FRB timer is not supported.

--*/
{
  EFI_STATUS                       Status;
  IPMI_SET_WATCHDOG_TIMER_REQUEST  SetWatchdogTimer;
  UINT8                            CompletionCode;
  IPMI_GET_WATCHDOG_TIMER_RESPONSE GetWatchdogTimer;

  Status = IpmiGetWatchdogTimer (&GetWatchdogTimer);
  if (EFI_ERROR (Status)) {
    return Status;
  }

  //
  // Check if timer is still running, if not abort disable routine.
  //
  if (GetWatchdogTimer.TimerUse.TimerRunning == 0) {
    return EFI_ABORTED;
  }

  ZeroMem (&SetWatchdogTimer, sizeof(SetWatchdogTimer));
  //
  // Just flip the Timer Use bit. This should release the timer.
  //
  SetWatchdogTimer.TimerUse.TimerRunning         = 0;
  SetWatchdogTimer.TimerUse.TimerUse             = IPMI_WATCHDOG_TIMER_BIOS_FRB2;
  SetWatchdogTimer.TimerUseExpirationFlagsClear &= ~BIT2;
  SetWatchdogTimer.TimerUseExpirationFlagsClear |= BIT1 | BIT4;

  Status = IpmiSetWatchdogTimer (&SetWatchdogTimer, &CompletionCode);
  return Status;
}

VOID
EFIAPI
DisableFRB2Handler (
  IN EFI_EVENT        Event,
  IN VOID             *Context
  )
/*++

  Routine Description:
    Disables FRB2. This function gets called each time the
    EFI_EVENT_SIGNAL_READY_TO_BOOT gets signaled

  Arguments:
    Standard event notification function arguments:
    Event         - the event that is signaled.
    Context       - not used here.

  Returns:

--*/
{
  DEBUG((EFI_D_ERROR, "!!! enter DisableFRB2Handler()!!!\n"));

  EfiDisableFrb ();
}

EFI_STATUS
CheckForAndReportErrors(
  VOID
  )
/*++

  Routine Description:
    Check the Watchdog timer expiration flags and report the kind of watchdog
    timeout occurred to the Error Manager.

  Arguments:

  Returns:
    EFI_SUCCESS     - Errors retrieved and reported

--*/
{
  EFI_STATUS                          Status;
  IPMI_GET_WATCHDOG_TIMER_RESPONSE    GetWatchdogTimer;
  IPMI_SET_WATCHDOG_TIMER_REQUEST     SetWatchdogTimer;
  UINT8                               CompletionCode;

  //
  // Get the Watchdog timer info to find out what kind of timer expiration occurred.
  //
  Status = IpmiGetWatchdogTimer (&GetWatchdogTimer);
  if (EFI_ERROR (Status)) {
    return Status;
  }
  //
  // If FRB2 Failure occurred, report it to the error manager and log a SEL.
  //
  if ((GetWatchdogTimer.TimerUseExpirationFlagsClear & BIT1) != 0) {
    //
    // Report the FRB2 time-out error
    //
  } else if ((GetWatchdogTimer.TimerUseExpirationFlagsClear & BIT3) != 0) {
    //
    // Report the OS Watchdog timer failure
    //
  }

  //
  // Need to clear Timer expiration flags after checking.
  //
  ZeroMem (&SetWatchdogTimer, sizeof(SetWatchdogTimer));
  SetWatchdogTimer.TimerUse                       = GetWatchdogTimer.TimerUse;
  SetWatchdogTimer.TimerActions                   = GetWatchdogTimer.TimerActions;
  SetWatchdogTimer.PretimeoutInterval             = GetWatchdogTimer.PretimeoutInterval;
  SetWatchdogTimer.TimerUseExpirationFlagsClear   = GetWatchdogTimer.TimerUseExpirationFlagsClear;
  SetWatchdogTimer.InitialCountdownValue          = GetWatchdogTimer.InitialCountdownValue;
  SetWatchdogTimer.TimerUse.TimerRunning          = 1;
  SetWatchdogTimer.TimerUseExpirationFlagsClear  |= BIT1 | BIT2 | BIT3;

  Status = IpmiSetWatchdogTimer (&SetWatchdogTimer, &CompletionCode);

  return Status;
}

EFI_STATUS
ReportFrb2Status (
  VOID
  )
/*++

  Routine Description:
    This routine is built only when DEBUG_MODE is enabled.  It is used
    to report the status of FRB2 when the FRB2 driver is installed.

  Arguments:
    none

  Returns:
    EFI_SUCCESS: All info was retrieved and reported
    EFI_ERROR:   There was an error during info retrieval

--*/
{
  EFI_STATUS                          Status;
  IPMI_GET_WATCHDOG_TIMER_RESPONSE    GetWatchdogTimer;

  //
  // Get the Watchdog timer info to find out what kind of timer expiration occurred.
  //
  Status = IpmiGetWatchdogTimer (&GetWatchdogTimer);
  if (EFI_ERROR (Status)) {
    DEBUG ((DEBUG_INFO, "Failed to get Watchdog Timer info from BMC.\n"));
    return Status;
  }

  //
  // Check if timer is running, report status to DEBUG_MODE output.
  //
  if (GetWatchdogTimer.TimerUse.TimerRunning == 1) {
    DEBUG ((DEBUG_INFO, "FRB2 Timer is running.\n"));
  } else {
    DEBUG ((DEBUG_INFO, "FRB2 Timer is not running.\n"));
  }

  return EFI_SUCCESS;
}

EFI_STATUS
EFIAPI
FrbDxeEntryPoint (
  IN EFI_HANDLE         ImageHandle,
  IN EFI_SYSTEM_TABLE   *SystemTable
  )
/*++

  Routine Description:
    This is the standard EFI driver point. This function intitializes
    the private data required for creating FRB Driver.

  Arguments:
    ImageHandle     - Handle for the image of this driver
    SystemTable     - Pointer to the EFI System Table

  Returns:
    EFI_SUCCESS     - Protocol successfully started and installed
    EFI_UNSUPPORTED - Protocol can't be started

--*/
{
  EFI_EVENT   ReadyToBootEvent;
  EFI_STATUS  Status;

  CheckForAndReportErrors();
  ReportFrb2Status ();

  //
  // Register the event to Disable FRB2 before Boot.
  //
  Status = EfiCreateEventReadyToBootEx (
            TPL_NOTIFY,
            DisableFRB2Handler,
            NULL,
            &ReadyToBootEvent
            );

  return Status;
}