coreboot
coreboot is an Open Source project aimed at replacing the proprietary BIOS found in most computers.
ipmi_ops.c
Go to the documentation of this file.
1 /* SPDX-License-Identifier: GPL-2.0-only */
2 
3 #include <console/console.h>
4 #include "ipmi_ops.h"
5 #include <string.h>
6 #include <types.h>
7 
8 enum cb_err ipmi_init_and_start_bmc_wdt(const int port, uint16_t countdown,
9  uint8_t action)
10 {
11  int ret;
12  struct ipmi_wdt_req req = {0};
13  struct ipmi_rsp rsp;
14  printk(BIOS_INFO, "Initializing IPMI BMC watchdog timer\n");
15  /* BIOS FRB2 */
16  req.timer_use = 1;
17  req.timer_actions = action;
18  /* clear BIOS FRB2 expiration flag */
20  req.initial_countdown_val = countdown;
23  (const unsigned char *) &req, sizeof(req),
24  (unsigned char *) &rsp, sizeof(rsp));
25 
26  if (ret < sizeof(struct ipmi_rsp) || rsp.completion_code) {
27  printk(BIOS_ERR, "IPMI: %s set wdt command failed "
28  "(ret=%d resp=0x%x), failed to initialize and start "
29  "IPMI BMC watchdog timer\n", __func__,
30  ret, rsp.completion_code);
31  return CB_ERR;
32  }
33 
34  /* Reset command to start timer */
37  (unsigned char *) &rsp, sizeof(rsp));
38 
39  if (ret < sizeof(struct ipmi_rsp) || rsp.completion_code) {
40  printk(BIOS_ERR, "IPMI: %s reset wdt command failed "
41  "(ret=%d resp=0x%x), failed to initialize and start "
42  "IPMI BMC watchdog timer\n", __func__,
43  ret, rsp.completion_code);
44  return CB_ERR;
45  }
46 
47  printk(BIOS_INFO, "IPMI BMC watchdog initialized and started.\n");
48  return CB_SUCCESS;
49 }
50 
51 enum cb_err ipmi_stop_bmc_wdt(const int port)
52 {
53  int ret;
54  struct ipmi_wdt_req req;
55  struct ipmi_wdt_rsp rsp = {0};
56  struct ipmi_rsp resp;
57 
58  /* Get current timer first */
61  (unsigned char *) &rsp, sizeof(rsp));
62 
63  if (ret < sizeof(struct ipmi_rsp) || rsp.resp.completion_code) {
64  printk(BIOS_ERR, "IPMI: %s get wdt command failed "
65  "(ret=%d resp=0x%x), IPMI BMC watchdog timer may still "
66  "be running\n", __func__, ret,
67  rsp.resp.completion_code);
68  return CB_ERR;
69  }
70  /* If bit 6 in timer_use is 0 then it's already stopped. */
71  if (!(rsp.data.timer_use & (1 << 6))) {
72  printk(BIOS_DEBUG, "IPMI BMC watchdog is already stopped\n");
73  return CB_SUCCESS;
74  }
75  /* Set timer stop running by clearing bit 6. */
76  rsp.data.timer_use &= ~(1 << 6);
77  rsp.data.initial_countdown_val = 0;
78  req = rsp.data;
81  (const unsigned char *) &req, sizeof(req),
82  (unsigned char *) &resp, sizeof(resp));
83 
84  if (ret < sizeof(struct ipmi_rsp) || resp.completion_code) {
85  printk(BIOS_ERR, "IPMI: %s set wdt command stop timer failed "
86  "(ret=%d resp=0x%x), failed to stop IPMI "
87  "BMC watchdog timer\n", __func__, ret,
88  resp.completion_code);
89  return CB_ERR;
90  }
91  printk(BIOS_DEBUG, "IPMI BMC watchdog is stopped\n");
92 
93  return CB_SUCCESS;
94 }
95 
96 enum cb_err ipmi_get_system_guid(const int port, uint8_t *uuid)
97 {
98  int ret;
99  struct ipmi_get_system_guid_rsp rsp;
100 
101  if (uuid == NULL) {
102  printk(BIOS_ERR, "%s failed, null pointer parameter\n",
103  __func__);
104  return CB_ERR;
105  }
106 
109  (unsigned char *) &rsp, sizeof(rsp));
110 
111  if (ret < sizeof(struct ipmi_rsp) || rsp.resp.completion_code) {
112  printk(BIOS_ERR, "IPMI: %s command failed (ret=%d resp=0x%x)\n",
113  __func__, ret, rsp.resp.completion_code);
114  return CB_ERR;
115  }
116 
117  memcpy(uuid, rsp.data, 16);
118  return CB_SUCCESS;
119 }
120 
121 enum cb_err ipmi_add_sel(const int port, struct sel_event_record *sel)
122 {
123  int ret;
124  struct ipmi_add_sel_rsp rsp;
125 
126  if (sel == NULL) {
127  printk(BIOS_ERR, "%s failed, system evnt log is not present.\n", __func__);
128  return CB_ERR;
129  }
130 
132  IPMI_ADD_SEL_ENTRY, (const unsigned char *) sel,
133  16, (unsigned char *) &rsp, sizeof(rsp));
134 
135  if (ret < sizeof(struct ipmi_rsp) || rsp.resp.completion_code) {
136  printk(BIOS_ERR, "IPMI: %s command failed (ret=%d resp=0x%x)\n",
137  __func__, ret, rsp.resp.completion_code);
138  return CB_ERR;
139  }
140  return CB_SUCCESS;
141 }
void * memcpy(void *dest, const void *src, size_t n)
Definition: memcpy.c:7
cb_err
coreboot error codes
Definition: cb_err.h:15
@ CB_ERR
Generic error code.
Definition: cb_err.h:17
@ CB_SUCCESS
Call completed successfully.
Definition: cb_err.h:16
#define printk(level,...)
Definition: stdlib.h:16
port
Definition: i915.h:29
int ipmi_kcs_message(int port, int netfn, int lun, int cmd, const unsigned char *inmsg, int inlen, unsigned char *outmsg, int outlen)
Definition: ipmi_kcs.c:222
#define IPMI_NETFN_APPLICATION
Definition: ipmi_kcs.h:9
#define IPMI_NETFN_STORAGE
Definition: ipmi_kcs.h:21
#define IPMI_ADD_SEL_ENTRY
Definition: ipmi_kcs.h:23
enum cb_err ipmi_get_system_guid(const int port, uint8_t *uuid)
Definition: ipmi_ops.c:96
enum cb_err ipmi_add_sel(const int port, struct sel_event_record *sel)
Definition: ipmi_ops.c:121
enum cb_err ipmi_init_and_start_bmc_wdt(const int port, uint16_t countdown, uint8_t action)
Definition: ipmi_ops.c:8
enum cb_err ipmi_stop_bmc_wdt(const int port)
Definition: ipmi_ops.c:51
#define IPMI_BMC_GET_SYSTEM_GUID
Definition: ipmi_ops.h:11
#define IPMI_BMC_SET_WDG_TIMER
Definition: ipmi_ops.h:9
#define IPMI_BMC_GET_WDG_TIMER
Definition: ipmi_ops.h:10
#define IPMI_BMC_RESET_WDG_TIMER
Definition: ipmi_ops.h:8
#define BIOS_INFO
BIOS_INFO - Expected events.
Definition: loglevel.h:113
#define BIOS_DEBUG
BIOS_DEBUG - Verbose output.
Definition: loglevel.h:128
#define BIOS_ERR
BIOS_ERR - System in incomplete state.
Definition: loglevel.h:72
#define NULL
Definition: stddef.h:19
unsigned short uint16_t
Definition: stdint.h:11
unsigned char uint8_t
Definition: stdint.h:8
uint8_t completion_code
Definition: ipmi_kcs.h:41
uint16_t initial_countdown_val
Definition: ipmi_ops.h:26
uint8_t timer_actions
Definition: ipmi_ops.h:23
uint8_t timer_use
Definition: ipmi_ops.h:22
uint8_t timer_use_expiration_flags_clr
Definition: ipmi_ops.h:25