summaryrefslogtreecommitdiff
path: root/Platform/Intel/AdvancedFeaturePkg/Ipmi/IpmiInit/DxeIpmiInit.c
blob: 0a49b8785991692ddfa9257548ef3f58dfdc6e05 (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
/** @file
    IPMI stack initialization.

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/BaseLib.h>
#include <Library/DebugLib.h>
#include <Library/TimerLib.h>
#include <Library/IpmiCommandLib.h>

#define BMC_TIMEOUT          30  // [s] How long shall BIOS wait for BMC
#define BMC_KCS_TIMEOUT      5   // [s] Single KSC request timeout

EFI_STATUS
GetSelfTest (
  VOID
  )
/*++

Routine Description:

  Execute the Get Self Test results command to determine whether or not the BMC self tests
  have passed

Arguments:

  mIpmiInstance   - Data structure describing BMC variables and used for sending commands
  StatusCodeValue - An array used to accumulate error codes for later reporting.
  ErrorCount      - Counter used to keep track of error codes in StatusCodeValue

Returns: 

  EFI_SUCCESS       - BMC Self test results are retrieved and saved into BmcStatus
  EFI_DEVICE_ERROR  - BMC failed to return self test results.

--*/
{
  EFI_STATUS                       Status;
  IPMI_SELF_TEST_RESULT_RESPONSE   TestResult;

  //
  // Get the SELF TEST Results.
  //
  Status = IpmiGetSelfTestResult (&TestResult);
  if (EFI_ERROR(Status)) {
    DEBUG((DEBUG_ERROR, "\n[IPMI] BMC does not respond (status: %r)!\n\n", Status));
    return Status;
  }

  DEBUG((DEBUG_INFO, "[IPMI] BMC self-test result: %02X-%02X\n", TestResult.Result, TestResult.Param));

  return EFI_SUCCESS;
}

EFI_STATUS
GetDeviceId (
  OUT BOOLEAN *UpdateMode
  )
/*++

Routine Description:
  Execute the Get Device ID command to determine whether or not the BMC is in Force Update
  Mode.  If it is, then report it to the error manager.

Arguments:

Returns: 
  Status

--*/
{
  EFI_STATUS                   Status;
  IPMI_GET_DEVICE_ID_RESPONSE  BmcInfo;
  UINT32                       Retries;
  
  //
  // Set up a loop to retry for up to 30 seconds. Calculate retries not timeout
  // so that in case KCS is not enabled and EfiIpmiSendCommand() returns
  // immediately we will not wait all the 30 seconds.
  //
  Retries = BMC_TIMEOUT / BMC_KCS_TIMEOUT + 1;
  //
  // Get the device ID information for the BMC.
  //
  do {
    Status = IpmiGetDeviceId (&BmcInfo);
    if (!EFI_ERROR(Status)) {
      break;
    }
    DEBUG ((DEBUG_ERROR, "[IPMI] BMC does not respond (status: %r), %d retries left\n", Status, Retries));
    MicroSecondDelay(50 * 1000);
    if (Retries-- == 0) {
      return Status;
    }
  } while (TRUE);

  DEBUG((DEBUG_INFO, "[IPMI] BMC Device ID: 0x%02X, firmware version: %d.%02X\n", BmcInfo.DeviceId, BmcInfo.MajorFirmwareRev, BmcInfo.MinorFirmwareRev));
  *UpdateMode = (BOOLEAN)BmcInfo.UpdateMode;
  return Status;
}

/**
  The entry point of the Ipmi DXE.

@param[in] ImageHandle - Handle of this driver image
@param[in] SystemTable - Table containing standard EFI services

@retval EFI_SUCCESS - Always success is returned even if KCS does not function

 **/
EFI_STATUS
EFIAPI
IpmiInterfaceInit (
  IN EFI_HANDLE             ImageHandle,
  IN EFI_SYSTEM_TABLE       *SystemTable
  )
{
  BOOLEAN      UpdateMode;
  EFI_STATUS   Status;

  DEBUG((EFI_D_ERROR,"IPMI Dxe:Get BMC Device Id\n"));

  //
  // Get the Device ID and check if the system is in Force Update mode.
  //
  Status = GetDeviceId (&UpdateMode);
  //
  // Do not continue initialization if the BMC is in Force Update Mode.
  //
  if (!EFI_ERROR(Status) && !UpdateMode) {
    //
    // Get the SELF TEST Results.
    //
    GetSelfTest ();
  }

  return EFI_SUCCESS;
}