summaryrefslogtreecommitdiff
path: root/Platform/Intel/AdvancedFeaturePkg/Ipmi/OsWdt/OsWdt.c
blob: c64c70f2a91a7a7ea1dd5c6042d945500d0b93a0 (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
/** @file
  IPMI Os watchdog timer 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 <Uefi.h>
#include <Library/DebugLib.h>
#include <Library/BaseMemoryLib.h>
#include <Library/UefiBootServicesTableLib.h>
#include <Library/IpmiCommandLib.h>
#include <IndustryStandard/Ipmi.h>
#include <IpmiEx.h>

BOOLEAN mOsWdtFlag = FALSE;

EFI_EVENT                   mExitBootServicesEvent;

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

Routine Description:
  Enable the OS Boot Watchdog Timer.
  Is called only on legacy or EFI OS boot.

Arguments:
  Event    - Event type
  *Context - Context for the event

Returns:
  None

--*/
{
  EFI_STATUS                       Status;
  IPMI_SET_WATCHDOG_TIMER_REQUEST  SetWatchdogTimer;
  UINT8                            CompletionCode;
  IPMI_GET_WATCHDOG_TIMER_RESPONSE GetWatchdogTimer;
  static BOOLEAN                   OsWdtEventHandled = FALSE;

  DEBUG((EFI_D_ERROR, "!!! EnableEfiOsBootWdtHandler()!!!\n"));

  //
  // Make sure it processes once only. And proceess it only if OsWdtFlag==TRUE;
  //
  if (OsWdtEventHandled || !mOsWdtFlag) {
    return ;
  }

  OsWdtEventHandled = TRUE;

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

  ZeroMem (&SetWatchdogTimer, sizeof(SetWatchdogTimer));
  //
  // Just flip the Timer Use bit. This should release the timer.
  //
  SetWatchdogTimer.TimerUse.TimerRunning         = 1;
  SetWatchdogTimer.TimerUse.TimerUse             = IPMI_WATCHDOG_TIMER_OS_LOADER;
  SetWatchdogTimer.TimerActions                  = IPMI_WATCHDOG_TIMER_ACTION_HARD_RESET;
  SetWatchdogTimer.TimerUseExpirationFlagsClear &= ~BIT4;
  SetWatchdogTimer.TimerUseExpirationFlagsClear |= BIT1 | BIT2;
  SetWatchdogTimer.InitialCountdownValue         = 600; // 100ms / count

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

EFI_STATUS
EFIAPI
DriverInit (
  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 ASRR Driver.

Arguments:
  As required for DXE driver enrty routine.
  ImageHandle - ImageHandle of the loaded driver
  SystemTable - Pointer to the System Table

Returns:
  EFI_SUCCESS     - Protocol successfully started and installed.

--*/
{
  EFI_STATUS                     Status;

  Status = gBS->CreateEvent (
                  EVT_SIGNAL_EXIT_BOOT_SERVICES,
                  TPL_NOTIFY,
                  EnableEfiOsBootWdtHandler,
                  NULL,
                  &mExitBootServicesEvent
                  );

  return EFI_SUCCESS;
}