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
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
|
// SPDX-License-Identifier: Apache-2.0
/* Copyright 2013-2019 IBM Corp. */
#ifndef __IPMI_H
#define __IPMI_H
#include <stdint.h>
#include <ccan/list/list.h>
#include <stdbool.h>
#include <types.h>
#define MAX_IPMI_SENSORS 255
/*
* IPMI codes as defined by the standard.
*/
#define IPMI_GET_DEVICE_ID_CMD 0x01
#define IPMI_COLD_RESET_CMD 0x02
#define IPMI_WARM_RESET_CMD 0x03
#define IPMI_CLEAR_MSG_FLAGS_CMD 0x30
#define IPMI_GET_DEVICE_GUID_CMD 0x08
#define IPMI_GET_MSG_FLAGS_CMD 0x31
#define IPMI_SEND_MSG_CMD 0x34
#define IPMI_GET_MSG_CMD 0x33
#define IPMI_SET_BMC_GLOBAL_ENABLES_CMD 0x2e
#define IPMI_GET_BMC_GLOBAL_ENABLES_CMD 0x2f
#define IPMI_READ_EVENT_MSG_BUFFER_CMD 0x35
#define IPMI_GET_CHANNEL_INFO_CMD 0x42
/*
* 28. Chassis Commands
*/
#define IPMI_CHASSIS_GET_CAP_CMD 0x00
#define IPMI_CHASSIS_GET_STATUS_CMD 0x01
#define IPMI_CHASSIS_CONTROL_CMD 0x02
#define IPMI_CHASSIS_RESET_CMD 0x03
#define IPMI_CHASSIS_IDENTIFY_CMD 0x04
#define IPMI_CHASSIS_SET_PANEL_BUTTON_EN_CMD 0x0a
#define IPMI_CHASSIS_SET_CAP_CMD 0x05
#define IPMI_CHASSIS_SET_PWR_RESTORE_CMD 0x06
#define IPMI_CHASSIS_SET_PWR_CYCLE_CMD 0x0b
#define IPMI_CHASSIS_GET_SYS_RESTART_CAUSE_CMD 0x07
#define IPMI_CHASSIS_SET_SYS_BOOT_OPT_CMD 0x08
#define IPMI_CHASSIS_GET_SYS_BOOT_OPT_CMD 0x09
#define IPMI_CHASSIS_GET_POH_COUNTER_CMD 0x0f
/* 28.3. Chassis Control Command */
#define IPMI_CHASSIS_PWR_DOWN 0x00
#define IPMI_CHASSIS_PWR_UP 0x01
#define IPMI_CHASSIS_PWR_CYCLE 0x02
#define IPMI_CHASSIS_HARD_RESET 0x03
#define IPMI_CHASSIS_PULSE_DIAG 0x04
#define IPMI_CHASSIS_SOFT_SHUTDOWN 0x05
/* 20.7. ACPI Power State Command */
#define IPMI_PWR_SYS_S0_WORKING 0x00
#define IPMI_PWR_SYS_S1 0x01
#define IPMI_PWR_SYS_S2 0x02
#define IPMI_PWR_SYS_S3_SUSPEND_TO_RAM 0x03
#define IPMI_PWR_SYS_S4_SUSPEND_TO_DISK 0x04
#define IPMI_PWR_SYS_S5_SOFT_OFF 0x05
#define IPMI_PWR_SYS_SUSPEND 0x06
#define IPMI_PWR_SYS_LEGACY_ON 0x20
#define IPMI_PWR_SYS_LEGACY_OFF 0x21
#define IPMI_PWR_SYS_UNKNOWN 0x2a
#define IPMI_PWR_NOCHANGE 0x7f
/* 22.{3,4} Clear / Get message flags */
#define IPMI_MESSAGE_FLAGS_RX_MESSAGE_QUEUE (1<<0)
#define IPMI_MESSAGE_FLAGS_EVENT_BUFFER (1<<1)
#define IPMI_MESSAGE_FLAGS_WATCHDOG_PRE_TIMEOUT (1<<3)
#define IPMI_MESSAGE_FLAGS_OEM0 (1<<5)
#define IPMI_MESSAGE_FLAGS_OEM1 (1<<6)
#define IPMI_MESSAGE_FLAGS_OEM2 (1<<7)
/* Firmware Progress Sensor states */
#define IPMI_FW_PCI_INIT 0x07
#define IPMI_FW_OS_BOOT 0x13
#define IPMI_FW_MOTHERBOARD_INIT 0x14
#define IPMI_CODE(netfn, cmd) ((netfn) << 8 | (cmd))
#define IPMI_CMD(code) ((code) & 0xff)
#define IPMI_NETFN(code) ((code) >> 8 & 0xff)
#define IPMI_NETFN_RETURN_CODE(netfn) ((netfn) | 0x4)
#define IPMI_NETFN_CHASSIS 0x00
#define IPMI_NETFN_SE 0x04
#define IPMI_NETFN_STORAGE 0x0a
#define IPMI_NETFN_APP 0x06
#define IPMI_WRITE_FRU IPMI_CODE(IPMI_NETFN_STORAGE, 0x12)
#define IPMI_GET_SEL_INFO IPMI_CODE(IPMI_NETFN_STORAGE, 0x40)
#define IPMI_RESERVE_SEL IPMI_CODE(IPMI_NETFN_STORAGE, 0x42)
#define IPMI_ADD_SEL_EVENT IPMI_CODE(IPMI_NETFN_STORAGE, 0x44)
#define IPMI_GET_SEL_TIME IPMI_CODE(IPMI_NETFN_STORAGE, 0x48)
#define IPMI_SET_SEL_TIME IPMI_CODE(IPMI_NETFN_STORAGE, 0x49)
#define IPMI_CHASSIS_CONTROL IPMI_CODE(IPMI_NETFN_CHASSIS, 0x02)
#define IPMI_CHASSIS_GET_BOOT_OPT IPMI_CODE(IPMI_NETFN_CHASSIS, 0x09)
#define IPMI_BMC_GET_DEVICE_ID IPMI_CODE(IPMI_NETFN_APP, 0x01)
#define IPMI_SET_POWER_STATE IPMI_CODE(IPMI_NETFN_APP, 0x06)
#define IPMI_GET_POWER_STATE IPMI_CODE(IPMI_NETFN_APP, 0x07)
#define IPMI_RESET_WDT IPMI_CODE(IPMI_NETFN_APP, 0x22)
#define IPMI_SET_WDT IPMI_CODE(IPMI_NETFN_APP, 0x24)
#define IPMI_SET_ENABLES IPMI_CODE(IPMI_NETFN_APP, 0x2E)
#define IPMI_GET_ENABLES IPMI_CODE(IPMI_NETFN_APP, 0x2F)
#define IPMI_CLEAR_MESSAGE_FLAGS IPMI_CODE(IPMI_NETFN_APP, 0x30)
#define IPMI_GET_MESSAGE_FLAGS IPMI_CODE(IPMI_NETFN_APP, 0x31)
#define IPMI_GET_MESSAGE IPMI_CODE(IPMI_NETFN_APP, 0x33)
#define IPMI_READ_EVENT IPMI_CODE(IPMI_NETFN_APP, 0x35)
#define IPMI_GET_BT_CAPS IPMI_CODE(IPMI_NETFN_APP, 0x36)
#define IPMI_SET_SENSOR_READING IPMI_CODE(IPMI_NETFN_SE, 0x30)
/*
* IPMI response codes.
*/
#define IPMI_CC_NO_ERROR 0x00
#define IPMI_NODE_BUSY_ERR 0xc0
#define IPMI_INVALID_COMMAND_ERR 0xc1
#define IPMI_TIMEOUT_ERR 0xc3
#define IPMI_ERR_MSG_TRUNCATED 0xc6
#define IPMI_REQ_LEN_INVALID_ERR 0xc7
#define IPMI_REQ_LEN_EXCEEDED_ERR 0xc8
#define IPMI_NOT_IN_MY_STATE_ERR 0xd5 /* IPMI 2.0 */
#define IPMI_LOST_ARBITRATION_ERR 0x81
#define IPMI_BUS_ERR 0x82
#define IPMI_NAK_ON_WRITE_ERR 0x83
#define IPMI_ERR_UNSPECIFIED 0xff
#define IPMI_DEFAULT_INTERFACE 0
#define IPMI_MAX_REQ_SIZE 60
#define IPMI_MAX_RESP_SIZE 60
/*
* As far as I can tell the size of PEL record is unbounded (due to
* the possible presence of the user defined section). We chose this
* size because it's what hostboot also uses and most of the OPAL logs
* are few hundred bytes.
*/
#define IPMI_MAX_PEL_SIZE 0x800
struct ipmi_backend;
struct ipmi_msg {
/* Can be used by command implementations to track requests */
struct list_node link;
struct ipmi_backend *backend;
uint8_t netfn;
uint8_t cmd;
uint8_t cc;
/* Called when a response is received to the ipmi message */
void (*complete)(struct ipmi_msg *);
/* Called if non-NULL when the ipmi layer detects an error */
void (*error)(struct ipmi_msg *);
void *user_data;
uint8_t req_size;
uint8_t resp_size;
uint8_t *data;
};
struct ipmi_backend {
uint64_t opal_event_ipmi_recv;
struct ipmi_msg *(*alloc_msg)(size_t, size_t);
void (*free_msg)(struct ipmi_msg *);
int (*queue_msg)(struct ipmi_msg *);
int (*queue_msg_head)(struct ipmi_msg *);
int (*dequeue_msg)(struct ipmi_msg *);
void (*disable_retry)(struct ipmi_msg *);
/*
* When processing a synchronous IPMI message, pollers may not run, and
* neither may timers (as the synchronous IPMI message may be being
* done with locks held, which a timer may then try to also take).
*
* So, ensure we have a way to drive any state machines that an IPMI
* backend may neeed to crank to ensure forward progress.
*/
void (*poll)(void);
};
extern struct ipmi_backend *ipmi_backend;
/* Initialise the IPMI interface */
void ipmi_init(void);
bool ipmi_present(void);
void ipmi_free_msg(struct ipmi_msg *msg);
struct ipmi_msg *ipmi_mkmsg_simple(uint32_t code, void *req_data, size_t req_size);
struct ipmi_msg *ipmi_mkmsg(int interface, uint32_t code,
void (*complete)(struct ipmi_msg *),
void *user_data, void *req_data, size_t req_size,
size_t resp_size);
/* Initialise a previously allocated message with the required
fields. The caller must ensure the message is large enough to hold the
request and response data. */
void ipmi_init_msg(struct ipmi_msg *msg, int interface,
uint32_t code, void (*complete)(struct ipmi_msg *),
void *user_data, size_t req_size, size_t resp_size);
/* called by backend code to indicate a SMS_ATN event */
void ipmi_sms_attention(void);
/* Add an ipmi message to the queue */
int ipmi_queue_msg(struct ipmi_msg *msg);
/* Add an ipmi message to the start of the queue */
int ipmi_queue_msg_head(struct ipmi_msg *msg);
/* Synchronously send an ipmi message. This won't return until the
* messages callback has been called. */
void ipmi_queue_msg_sync(struct ipmi_msg *msg);
/* Removes the message from the list, queued previously */
int ipmi_dequeue_msg(struct ipmi_msg *msg);
/* Process a completed message */
void ipmi_cmd_done(uint8_t cmd, uint8_t netfn, uint8_t cc, struct ipmi_msg *msg);
/* 28.3 Chassis Control Command. Changes the power state of the P8. */
int ipmi_chassis_control(uint8_t request);
/* 20.7 ACPI Power State Command (without the ACPI part). Informative only,
* use chassis control to perform power off and reboot. */
int ipmi_set_power_state(uint8_t system, uint8_t device);
/* 35.17 Set Sensor Reading Command */
int ipmi_set_sensor(uint8_t sensor, uint8_t *reading, size_t len);
int ipmi_set_fw_progress_sensor(uint8_t state);
/* Register a backend with the ipmi core. Currently we only support one. */
void ipmi_register_backend(struct ipmi_backend *backend);
/* Allocate IPMI SEL panic message */
void ipmi_sel_init(void);
/* Register SEL handler with IPMI core */
int ipmi_sel_register(uint8_t oem_cmd,
void (*handler)(uint8_t data, void *context),
void *context);
/* Register rtc ipmi commands with as opal callbacks. */
void ipmi_rtc_init(void);
/* Register ipmi host interface access callbacks */
void ipmi_opal_init(void);
/* Populate fru data */
void ipmi_fru_init(uint8_t fru_dev_id);
/* Commit an error log to the bmc using the OEM add eSEL commands */
struct errorlog;
int ipmi_elog_commit(struct errorlog *elog_buf);
/* Callback to parse an OEM SEL message */
void ipmi_parse_sel(struct ipmi_msg *msg);
/* Starts the watchdog timer */
void ipmi_wdt_init(void);
/* Stop the wdt */
void ipmi_wdt_stop(void);
/* Reset the watchdog timer. Does not return until the timer has been
* reset and does not schedule future resets. */
void ipmi_wdt_final_reset(void);
/* Discover id of settable ipmi sensors */
void ipmi_sensor_init(void);
/* Get sensor number for given sensor type */
uint8_t ipmi_get_sensor_number(uint8_t sensor_type);
/* Set the boot count once the OS is up and running */
int ipmi_set_boot_count(void);
/* Terminate immediate */
void __attribute__((noreturn)) ipmi_terminate(const char *msg);
/* Get BMC firmware info */
extern int ipmi_get_bmc_info_request(void);
/* Add BMC firmware info to device tree */
extern void ipmi_dt_add_bmc_info(void);
/* Get BMC Boot Options info (specifically OEM param 0x62) */
int ipmi_get_chassis_boot_opt_request(void);
/* Get OEM Boot Option 0x62 for SBE validation flag */
int ipmi_chassis_check_sbe_validation(void);
#endif
|