aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAlistair Popple <alistair@popple.id.au>2014-09-09 15:57:27 +1000
committerBenjamin Herrenschmidt <benh@kernel.crashing.org>2014-10-01 14:23:06 +1000
commitf671e7f9decd909afa784f974bbceb07189f38f4 (patch)
tree0480bd455477c242eca06ca49abd284338117c10
parent69a833b6e2fc1636e25539ce58bde6e72f1c3bec (diff)
downloadskiboot-f671e7f9decd909afa784f974bbceb07189f38f4.zip
skiboot-f671e7f9decd909afa784f974bbceb07189f38f4.tar.gz
skiboot-f671e7f9decd909afa784f974bbceb07189f38f4.tar.bz2
ipmi: Refactored ipmi layer to use generic backend
The initial implementation of the ipmi stack was still tightly coupled with the backend (in this case bt). This patch refactors the ipmi code to use a generic backend device. The core ipmi messaging functionality and the implementation of specific commands has also been split into different files. Signed-off-by: Alistair Popple <alistair@popple.id.au> Signed-off-by: Benjamin Herrenschmidt <benh@kernel.crashing.org>
-rw-r--r--core/ipmi.c164
-rw-r--r--hw/Makefile.inc4
-rw-r--r--hw/bt.c48
-rw-r--r--hw/ipmi/Makefile.inc5
-rw-r--r--hw/ipmi/ipmi-power.c40
-rw-r--r--hw/ipmi/ipmi-rtc.c94
-rw-r--r--include/bt.h16
-rw-r--r--include/ipmi.h63
-rw-r--r--platforms/bmc/palmetto.c7
9 files changed, 272 insertions, 169 deletions
diff --git a/core/ipmi.c b/core/ipmi.c
index 1f9dd5f..90d8aaf 100644
--- a/core/ipmi.c
+++ b/core/ipmi.c
@@ -22,151 +22,79 @@
#include <time.h>
#include <time-utils.h>
-/* Sane default (2014/01/01) */
-static time_t time = 1388494800;
+static struct ipmi_backend *ipmi_backend = NULL;
-static void ipmi_process_storage_resp(struct ipmi_msg *msg)
+void ipmi_free_msg(struct ipmi_msg *msg)
{
- uint32_t new_time;
-
- switch (msg->cmd) {
- case IPMI_GET_SEL_TIME_CMD:
- /*
- * I couldn't find any mention of endianess in the IPMI spec,
- * but ipmitool seemed to assume little endian?
- */
- memcpy(&new_time, msg->data, 4);
- time = le32_to_cpu(new_time);
- break;
-
- case IPMI_SET_SEL_TIME_CMD:
- /* Nothing to do in this case */
- break;
-
- default:
- printf("Unsupported/invalid IPMI storage command\n");
- }
+ msg->backend->free_msg(msg);
}
-static int64_t ipmi_get_sel_time(void)
+struct ipmi_msg *ipmi_mkmsg_simple(uint32_t code, void *req_data, size_t req_size)
{
- struct ipmi_msg *msg;
- static uint32_t time_result;
-
- msg = bt_alloc_ipmi_msg(0, 4);
- if (!msg)
- return OPAL_HARDWARE;
-
- msg->cmd = IPMI_GET_SEL_TIME_CMD;
- msg->netfn = IPMI_NETFN_STORAGE_REQUEST;
-
- if (bt_add_ipmi_msg_wait(msg))
- return -1;
-
- memcpy(&time_result, msg->data, sizeof(time_result));
-
- return time_result;
+ return ipmi_mkmsg(IPMI_DEFAULT_INTERFACE, code, ipmi_free_msg, NULL,
+ req_data, req_size, 0);
}
-static int64_t ipmi_set_sel_time(uint32_t tv)
+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)
{
struct ipmi_msg *msg;
- msg = bt_alloc_ipmi_msg(sizeof(tv), 0);
- if (!msg)
- return OPAL_HARDWARE;
-
- msg->cmd = IPMI_SET_SEL_TIME_CMD;
- msg->netfn = IPMI_NETFN_STORAGE_REQUEST;
- memcpy(msg->data, &tv, sizeof(tv));
+ /* We don't actually support multiple interfaces at the moment. */
+ assert(interface == IPMI_DEFAULT_INTERFACE);
- return bt_add_ipmi_msg_wait(msg);
-}
+ msg = ipmi_backend->alloc_msg(req_size, resp_size);
+ if (!msg)
+ return NULL;
-static int64_t ipmi_opal_rtc_read(uint32_t *y_m_d,
- uint64_t *h_m_s_m)
-{
- struct tm tm;
+ msg->backend = ipmi_backend;
+ msg->cmd = IPMI_CMD(code);
+ msg->netfn = IPMI_NETFN(code);
+ msg->req_size = req_size;
+ msg->resp_size = resp_size;
+ msg->complete = complete;
+ msg->user_data = user_data;
- if (ipmi_get_sel_time() < 0)
- return OPAL_HARDWARE;
+ if (req_data)
+ memcpy(msg->data, req_data, req_size);
- gmtime_r(&time, &tm);
- tm_to_datetime(&tm, y_m_d, h_m_s_m);
- return OPAL_SUCCESS;
+ return msg;
}
-static int64_t ipmi_opal_rtc_write(uint32_t year_month_day,
- uint64_t hour_minute_second_millisecond)
+int ipmi_sync_queue_msg(struct ipmi_msg *msg)
{
- time_t t;
- struct tm tm;
+ /* Here we could choose which interface to use if we want to support
+ multiple interfaces. */
- datetime_to_tm(year_month_day, hour_minute_second_millisecond, &tm);
- t = mktime(&tm);
- t = cpu_to_le32(t);
- if (ipmi_set_sel_time(t))
- return OPAL_HARDWARE;
+ /* We should also store the original message cmd/netfn here if we wish
+ to validate it when we get the response. */
- return OPAL_SUCCESS;
+ return msg->backend->queue_msg(msg);
}
-static void ipmi_rtc_init(void)
-{
- struct dt_node *np = dt_new(opal_node, "rtc");
- dt_add_property_strings(np, "compatible", "ibm,opal-rtc");
-
- opal_register(OPAL_RTC_READ, ipmi_opal_rtc_read, 2);
- opal_register(OPAL_RTC_WRITE, ipmi_opal_rtc_write, 2);
-}
-
-static void ipmi_cmd_done(struct ipmi_msg *msg)
+void ipmi_cmd_done(struct ipmi_msg *msg)
{
if (msg->cc != IPMI_CC_NO_ERROR) {
prerror("IPMI: Got error response 0x%02x\n", msg->cc);
- goto out;
- }
-
- switch (msg->netfn) {
- case IPMI_NETFN_STORAGE_RESPONSE:
- ipmi_process_storage_resp(msg);
- break;
-
- case IPMI_NETFN_CHASSIS_RESPONSE:
- break;
- default:
- prerror("IPMI: Invalid IPMI function code in response\n");
- }
-
-out:
- bt_free_ipmi_msg(msg);
-}
-
-int64_t ipmi_opal_chassis_control(uint64_t request)
-{
- struct ipmi_msg *msg;
- uint8_t chassis_control = request;
-
- msg = bt_alloc_ipmi_msg(sizeof(chassis_control), 0);
- if (!msg)
- return OPAL_HARDWARE;
- if (request > IPMI_CHASSIS_SOFT_SHUTDOWN)
- return OPAL_PARAMETER;
+ if (msg->error)
+ msg->error(msg);
+ } else if (msg->complete)
+ msg->complete(msg);
- msg->cmd = IPMI_CHASSIS_CONTROL_CMD;
- msg->netfn = IPMI_NETFN_CHASSIS_REQUEST;
- msg->data[0] = chassis_control;
-
- prlog(PR_INFO, "IPMI: sending chassis control request %llu\n",
- request);
-
- return bt_add_ipmi_msg_wait(msg);
+ /* At this point the message has should have been freed by the
+ completion functions. */
+ msg = NULL;
}
-void ipmi_init(void)
+void ipmi_register_backend(struct ipmi_backend *backend)
{
- bt_init(ipmi_cmd_done);
-
- ipmi_rtc_init();
+ /* We only support one backend at the moment */
+ assert(backend->alloc_msg);
+ assert(backend->free_msg);
+ assert(backend->queue_msg);
+ assert(backend->dequeue_msg);
+ ipmi_backend = backend;
}
diff --git a/hw/Makefile.inc b/hw/Makefile.inc
index 320e33b..3f372b1 100644
--- a/hw/Makefile.inc
+++ b/hw/Makefile.inc
@@ -10,6 +10,6 @@ HW=hw/built-in.o
include $(SRC)/hw/fsp/Makefile.inc
include $(SRC)/hw/ec/Makefile.inc
include $(SRC)/hw/ast-bmc/Makefile.inc
+include $(SRC)/hw/ipmi/Makefile.inc
-$(HW): $(HW_OBJS:%=hw/%) $(FSP) $(EC) $(AST_BMC)
-
+$(HW): $(HW_OBJS:%=hw/%) $(FSP) $(EC) $(AST_BMC) $(IPMI)
diff --git a/hw/bt.c b/hw/bt.c
index da92597..882d72c 100644
--- a/hw/bt.c
+++ b/hw/bt.c
@@ -72,7 +72,6 @@ struct bt {
enum bt_states state;
struct lock lock;
struct list_head msgq;
- void (*ipmi_cmd_done)(struct ipmi_msg *);
};
static struct bt bt;
@@ -151,7 +150,7 @@ static bool bt_try_send_msg(void)
bt_setmask(BT_CTRL_CLR_WR_PTR, BT_CTRL);
/* Byte 1 - Length */
- bt_outb(ipmi_msg->req_data_len + BT_MIN_REQ_LEN, BT_HOST2BMC);
+ bt_outb(ipmi_msg->req_size + BT_MIN_REQ_LEN, BT_HOST2BMC);
/* Byte 2 - NetFn/LUN */
bt_outb((ipmi_msg->netfn << 2) | (bt_msg->lun & 0x3), BT_HOST2BMC);
@@ -163,7 +162,7 @@ static bool bt_try_send_msg(void)
bt_outb(ipmi_msg->cmd, BT_HOST2BMC);
/* Byte 5:N - Data */
- for (i = 0; i < ipmi_msg->req_data_len; i++)
+ for (i = 0; i < ipmi_msg->req_size; i++)
bt_outb(ipmi_msg->data[i], BT_HOST2BMC);
bt_setmask(BT_CTRL_H2B_ATN, BT_CTRL);
@@ -215,12 +214,12 @@ static bool bt_get_resp(void)
* are unsigned we will also trigger this error if
* bt_inb(BT_HOST2BMC) < BT_MIN_RESP_LEN (which should never occur).
*/
- if (resp_len > ipmi_msg->resp_data_len) {
+ if (resp_len > ipmi_msg->resp_size) {
prerror("BT: Invalid resp_len %d for ipmi_msg->cmd = 0x%02x\n", resp_len, ipmi_msg->cmd);
- resp_len = ipmi_msg->resp_data_len;
+ resp_len = ipmi_msg->resp_size;
cc = IPMI_ERR_MSG_TRUNCATED;
}
- ipmi_msg->resp_data_len = resp_len;
+ ipmi_msg->resp_size = resp_len;
/* Byte 2 - NetFn/LUN */
netfn = bt_inb(BT_HOST2BMC);
@@ -253,8 +252,7 @@ static bool bt_get_resp(void)
/*
* Call the IPMI layer to finish processing the message.
*/
- if (bt.ipmi_cmd_done)
- bt.ipmi_cmd_done(ipmi_msg);
+ ipmi_cmd_done(ipmi_msg);
/* Immediately send the next message */
return false;
@@ -307,28 +305,29 @@ static bool bt_wait_state(enum bt_states state)
}
/*
- * Allocate a BT-IPMI message and return the IPMI message struct. Allocates
- * enough space for the request and response data.
+ * Allocate an ipmi message and bt container and return the ipmi
+ * message struct. Allocates enough space for the request and response
+ * data.
*/
-struct ipmi_msg *bt_alloc_ipmi_msg(size_t request_size, size_t response_size)
+static struct ipmi_msg *bt_alloc_ipmi_msg(size_t request_size, size_t response_size)
{
struct bt_msg *bt_msg;
- bt_msg = malloc(sizeof(struct bt_msg) + MAX(request_size, response_size));
+ bt_msg = zalloc(sizeof(struct bt_msg) + MAX(request_size, response_size));
if (!bt_msg)
return NULL;
- bt_msg->ipmi_msg.req_data_len = request_size;
- bt_msg->ipmi_msg.resp_data_len = response_size;
+ bt_msg->ipmi_msg.req_size = request_size;
+ bt_msg->ipmi_msg.resp_size = response_size;
bt_msg->ipmi_msg.data = (uint8_t *) (bt_msg + 1);
return &bt_msg->ipmi_msg;
}
/*
- * Free a previously allocated BT-IPMI message.
+ * Free a previously allocated ipmi message.
*/
-void bt_free_ipmi_msg(struct ipmi_msg *ipmi_msg)
+static void bt_free_ipmi_msg(struct ipmi_msg *ipmi_msg)
{
struct bt_msg *bt_msg = container_of(ipmi_msg, struct bt_msg, ipmi_msg);
@@ -338,7 +337,7 @@ void bt_free_ipmi_msg(struct ipmi_msg *ipmi_msg)
/*
* Add an ipmi message to the queue and wait for a response.
*/
-int bt_add_ipmi_msg_wait(struct ipmi_msg *msg)
+static int bt_add_ipmi_msg_wait(struct ipmi_msg *msg)
{
int ret = 0;
@@ -375,16 +374,24 @@ out:
* will need to be freed by the caller with bt_free_ipmi_msg() as it will no
* longer be in the queue of messages.
*/
-void bt_del_ipmi_msg(struct ipmi_msg *ipmi_msg)
+static int bt_del_ipmi_msg(struct ipmi_msg *ipmi_msg)
{
struct bt_msg *bt_msg = container_of(ipmi_msg, struct bt_msg, ipmi_msg);
lock(&bt.lock);
list_del(&bt_msg->link);
unlock(&bt.lock);
+ return 0;
}
-void bt_init(void (*ipmi_cmd_done)(struct ipmi_msg *))
+struct ipmi_backend bt_backend = {
+ .alloc_msg = bt_alloc_ipmi_msg,
+ .free_msg = bt_free_ipmi_msg,
+ .queue_msg = bt_add_ipmi_msg_wait,
+ .dequeue_msg = bt_del_ipmi_msg,
+};
+
+void bt_init(void)
{
struct dt_node *n;
const struct dt_property *prop;
@@ -413,6 +420,7 @@ void bt_init(void (*ipmi_cmd_done)(struct ipmi_msg *))
* initialised it.
*/
bt_set_state(BT_STATE_B_BUSY);
- bt.ipmi_cmd_done = ipmi_cmd_done;
list_head_init(&bt.msgq);
+
+ ipmi_register_backend(&bt_backend);
}
diff --git a/hw/ipmi/Makefile.inc b/hw/ipmi/Makefile.inc
new file mode 100644
index 0000000..c939f6c
--- /dev/null
+++ b/hw/ipmi/Makefile.inc
@@ -0,0 +1,5 @@
+SUBDIRS += hw/ipmi
+
+IPMI_OBJS = ipmi-rtc.o ipmi-power.o
+IPMI = hw/ipmi/built-in.o
+$(IPMI): $(IPMI_OBJS:%=hw/ipmi/%)
diff --git a/hw/ipmi/ipmi-power.c b/hw/ipmi/ipmi-power.c
new file mode 100644
index 0000000..ac37d14
--- /dev/null
+++ b/hw/ipmi/ipmi-power.c
@@ -0,0 +1,40 @@
+/* Copyright 2013-2014 IBM Corp.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
+ * implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <stdlib.h>
+#include <ipmi.h>
+#include <opal.h>
+
+int64_t ipmi_opal_chassis_control(uint64_t request)
+{
+ struct ipmi_msg *msg;
+ uint8_t chassis_control = request;
+
+ if (chassis_control > IPMI_CHASSIS_SOFT_SHUTDOWN)
+ return OPAL_PARAMETER;
+
+
+ msg = ipmi_mkmsg_simple(IPMI_CHASSIS_CONTROL, &chassis_control,
+ sizeof(chassis_control));
+ if (!msg)
+ return OPAL_HARDWARE;
+
+
+ prlog(PR_INFO, "IPMI: sending chassis control request %llu\n",
+ request);
+
+ return ipmi_sync_queue_msg(msg);
+}
diff --git a/hw/ipmi/ipmi-rtc.c b/hw/ipmi/ipmi-rtc.c
new file mode 100644
index 0000000..5ddfced
--- /dev/null
+++ b/hw/ipmi/ipmi-rtc.c
@@ -0,0 +1,94 @@
+/* Copyright 2013-2014 IBM Corp.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
+ * implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <stdlib.h>
+#include <ipmi.h>
+#include <time.h>
+#include <time-utils.h>
+#include <device.h>
+#include <opal.h>
+
+/* Sane default (2014/01/01) */
+static time_t time = 1388494800;
+
+static void get_sel_time_complete(struct ipmi_msg *msg)
+{
+ uint32_t result;
+
+ memcpy(&result, msg->data, 4);
+ time = le32_to_cpu(result);
+}
+
+
+static int64_t ipmi_get_sel_time(void)
+{
+ struct ipmi_msg *msg;
+
+ msg = ipmi_mkmsg(IPMI_DEFAULT_INTERFACE, IPMI_GET_SEL_TIME,
+ get_sel_time_complete, &time, NULL, 0, 4);
+ if (!msg)
+ return OPAL_HARDWARE;
+
+ return ipmi_sync_queue_msg(msg);
+}
+
+static int64_t ipmi_set_sel_time(uint32_t tv)
+{
+ struct ipmi_msg *msg;
+
+ tv = cpu_to_le32(tv);
+ msg = ipmi_mkmsg_simple(IPMI_SET_SEL_TIME, &tv, sizeof(tv));
+ if (!msg)
+ return OPAL_HARDWARE;
+
+ return ipmi_sync_queue_msg(msg);
+}
+
+static int64_t ipmi_opal_rtc_read(uint32_t *y_m_d,
+ uint64_t *h_m_s_m)
+{
+ struct tm tm;
+
+ if (ipmi_get_sel_time() < 0)
+ return OPAL_HARDWARE;
+
+ gmtime_r(&time, &tm);
+ tm_to_datetime(&tm, y_m_d, h_m_s_m);
+ return OPAL_SUCCESS;
+}
+
+static int64_t ipmi_opal_rtc_write(uint32_t year_month_day,
+ uint64_t hour_minute_second_millisecond)
+{
+ time_t t;
+ struct tm tm;
+
+ datetime_to_tm(year_month_day, hour_minute_second_millisecond, &tm);
+ t = mktime(&tm);
+ if (ipmi_set_sel_time(t))
+ return OPAL_HARDWARE;
+
+ return OPAL_SUCCESS;
+}
+
+void ipmi_rtc_init(void)
+{
+ struct dt_node *np = dt_new(opal_node, "rtc");
+ dt_add_property_strings(np, "compatible", "ibm,opal-rtc");
+
+ opal_register(OPAL_RTC_READ, ipmi_opal_rtc_read, 2);
+ opal_register(OPAL_RTC_WRITE, ipmi_opal_rtc_write, 2);
+}
diff --git a/include/bt.h b/include/bt.h
index 5f8a91e..1763d9f 100644
--- a/include/bt.h
+++ b/include/bt.h
@@ -17,21 +17,7 @@
#ifndef __BT_H
#define __BT_H
-#include <ipmi.h>
-
/* Initialise the BT interface */
-void bt_init(void (*ipmi_cmd_done)(struct ipmi_msg *));
-
-/* Allocate an BT-IPMI message */
-struct ipmi_msg *bt_alloc_ipmi_msg(size_t request_size, size_t response_size);
-
-/* Free a BT-IPMI message */
-void bt_free_ipmi_msg(struct ipmi_msg *ipmi_msg);
-
-/* Add an IPMI message to the BT queue and wait for a resposne */
-int bt_add_ipmi_msg_wait(struct ipmi_msg *msg);
-
-/* Remove an IPMI message from the BT queue */
-void bt_del_ipmi_msg(struct ipmi_msg *ipmi_msg);
+void bt_init(void);
#endif
diff --git a/include/ipmi.h b/include/ipmi.h
index 6181c53..78eb5cd 100644
--- a/include/ipmi.h
+++ b/include/ipmi.h
@@ -22,8 +22,6 @@
/*
* IPMI codes as defined by the standard.
*/
-#define IPMI_NETFN_APP_REQUEST 0x06
-#define IPMI_NETFN_APP_RESPONSE 0x07
#define IPMI_GET_DEVICE_ID_CMD 0x01
#define IPMI_COLD_RESET_CMD 0x02
#define IPMI_WARM_RESET_CMD 0x03
@@ -54,8 +52,6 @@
#define IPMI_CHASSIS_GET_SYS_BOOT_OPT_CMD 0x0b
#define IPMI_CHASSIS_GET_POH_COUNTER_CMD 0x0f
-#define IPMI_NETFN_CHASSIS_REQUEST 0x00
-#define IPMI_NETFN_CHASSIS_RESPONSE 0x01
/* 28.3. Chassis Control Command */
#define IPMI_CHASSIS_PWR_DOWN 0x00
@@ -65,11 +61,18 @@
#define IPMI_CHASSIS_PULSE_DIAG 0x04
#define IPMI_CHASSIS_SOFT_SHUTDOWN 0x05
-#define IPMI_NETFN_STORAGE_REQUEST 0x0a
-#define IPMI_NETFN_STORAGE_RESPONSE 0x0b
-#define IPMI_GET_SEL_INFO_CMD 0x40
-#define IPMI_GET_SEL_TIME_CMD 0x48
-#define IPMI_SET_SEL_TIME_CMD 0x49
+#define IPMI_CODE(netfn, cmd) ((netfn) << 8 | (cmd))
+#define IPMI_CMD(code) ((code) & 0xff)
+#define IPMI_NETFN(code) ((code) >> 8 & 0xff)
+
+#define IPMI_NETFN_CHASSIS 0x00
+#define IPMI_NETFN_STORAGE 0x0a
+#define IPMI_NETFN_APP 0x06
+
+#define IPMI_GET_SEL_INFO IPMI_CODE(IPMI_NETFN_STORAGE, 0x40)
+#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)
/*
* IPMI response codes.
@@ -87,19 +90,57 @@
#define IPMI_NAK_ON_WRITE_ERR 0x83
#define IPMI_ERR_UNSPECIFIED 0xff
+#define IPMI_DEFAULT_INTERFACE 0
+
+struct ipmi_backend;
struct ipmi_msg {
+ struct ipmi_backend *backend;
uint8_t netfn;
uint8_t cmd;
uint8_t cc;
- uint8_t req_data_len;
- uint8_t resp_data_len;
+
+ /* 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 {
+ struct ipmi_msg *(*alloc_msg)(size_t, size_t);
+ void (*free_msg)(struct ipmi_msg *);
+ int (*queue_msg)(struct ipmi_msg *);
+ int (*dequeue_msg)(struct ipmi_msg *);
+};
+
/* Initialise the IPMI interface */
void ipmi_init(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);
+
+int ipmi_sync_queue_msg(struct ipmi_msg *msg);
+
+/* Process a completed message */
+void ipmi_cmd_done(struct ipmi_msg *msg);
+
/* Change the power state of the P8 */
int64_t ipmi_opal_chassis_control(uint64_t request);
+/* Register a backend with the ipmi core. Currently we only support one. */
+void ipmi_register_backend(struct ipmi_backend *backend);
+
+/* Register rtc ipmi commands with as opal callbacks. */
+void ipmi_rtc_init(void);
+
#endif
diff --git a/platforms/bmc/palmetto.c b/platforms/bmc/palmetto.c
index c8ea281..217e542 100644
--- a/platforms/bmc/palmetto.c
+++ b/platforms/bmc/palmetto.c
@@ -23,6 +23,7 @@
#include <xscom.h>
#include <ast.h>
#include <ipmi.h>
+#include <bt.h>
#include "bmc.h"
@@ -203,8 +204,9 @@ static bool palmetto_probe(void)
/* Setup UART and use it as console with interrupts */
uart_init(true);
- /* Setup IPMI */
- ipmi_init();
+ /* Register the BT interface with the IPMI layer */
+ bt_init();
+ ipmi_rtc_init();
return true;
}
@@ -234,4 +236,3 @@ DECLARE_PLATFORM(palmetto) = {
.cec_power_down = palmetto_ipmi_power_down,
.cec_reboot = palmetto_ipmi_reboot,
};
-