summaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/include/runtime/interface.h98
-rw-r--r--src/include/usr/ipmi/ipmi_reasoncodes.H1
-rw-r--r--src/include/usr/ipmi/ipmisel.H35
-rw-r--r--src/makefile2
-rw-r--r--src/usr/ipmi/ipmirp.C2
-rw-r--r--src/usr/ipmi/ipmisel.C277
-rw-r--r--src/usr/ipmi/makefile1
-rw-r--r--src/usr/ipmi/runtime/makefile37
-rw-r--r--src/usr/ipmi/runtime/rt_ipmirp.C142
-rw-r--r--src/usr/ipmi/runtime/test/makefile31
-rw-r--r--src/usr/ipmi/runtime/test/rt_ipmitest.H102
-rw-r--r--src/usr/testcore/rtloader/loader.H29
12 files changed, 606 insertions, 151 deletions
diff --git a/src/include/runtime/interface.h b/src/include/runtime/interface.h
index 9ade9a07d..5279cb892 100644
--- a/src/include/runtime/interface.h
+++ b/src/include/runtime/interface.h
@@ -42,8 +42,29 @@
#include <stdint.h>
#include <time.h>
+/** Memory error types defined for memory_error() interface. */
+enum MemoryError_t
+{
+ /** Hardware has reported a solid memory CE that is correctable, but
+ * continues to report errors on subsequent reads. A second CE on that
+ * cache line will result in memory UE. Therefore, it is advised to migrate
+ * off of the address range as soon as possible. */
+ MEMORY_ERROR_CE,
+
+ /** Hardware has reported an uncorrectable error in memory (memory UE,
+ * channel failure, etc). The hypervisor should migrate any partitions off
+ * this address range as soon as possible. Note that these kind of errors
+ * will most likely result in partition failures. It is advised that the
+ * hypervisor waits some time for PRD to handle hardware attentions so that
+ * the hypervisor will know all areas of memory that are impacted by the
+ * failure. */
+ MEMORY_ERROR_UE,
+};
+
+
+
/**
- * i2c master description: chip, engine and port packed into
+ * I2C Master Description: chip, engine and port packed into
* a single 64-bit argument
*
* ---------------------------------------------------
@@ -51,12 +72,12 @@
* | (32) | (16) | (8) | (8) |
* ---------------------------------------------------
*/
-#define HBRT_I2C_MASTER_CHIP_SHIFT 32
-#define HBRT_I2C_MASTER_CHIP_MASK (0xfffffffful << 32)
-#define HBRT_I2C_MASTER_ENGINE_SHIFT 8
-#define HBRT_I2C_MASTER_ENGINE_MASK (0xfful << 8)
-#define HBRT_I2C_MASTER_PORT_SHIFT 0
-#define HBRT_I2C_MASTER_PORT_MASK (0xfful)
+#define HBRT_I2C_MASTER_CHIP_SHIFT 32
+#define HBRT_I2C_MASTER_CHIP_MASK (0xfffffffful << 32)
+#define HBRT_I2C_MASTER_ENGINE_SHIFT 8
+#define HBRT_I2C_MASTER_ENGINE_MASK (0xfful << 8)
+#define HBRT_I2C_MASTER_PORT_SHIFT 0
+#define HBRT_I2C_MASTER_PORT_MASK (0xfful)
/** @typedef hostInterfaces_t
@@ -154,9 +175,10 @@ typedef struct hostInterfaces
void (*nanosleep)(uint64_t i_seconds, uint64_t i_nano_seconds);
/**
- * @brief Report an error to the host
+ * @brief Report an OCC error to the host
* @param[in] Failing status that identifies the nature of the fail
* @param[in] Identifier that specifies the failing part
+ * @platform FSP
*/
void (*report_failure)( uint64_t i_status, uint64_t i_partId );
@@ -197,15 +219,21 @@ typedef struct hostInterfaces
int (*pnor_write) (uint32_t i_proc, const char* i_partitionName,
uint64_t i_offset, void* i_data, size_t i_sizeBytes);
+
/**
* @brief Read data from an i2c device
- * @param[in] i_master - Chip/engine/port of i2c bus
+ * @param[in] i_master - chip, engine and port packed into
+ * a single 64-bit argument
+ * ---------------------------------------------------
+ * | chip | reserved | eng | port |
+ * | (32) | (16) | (8) | (8) |
+ * ---------------------------------------------------
* @param[in] i_devAddr - I2C address of device
* @param[in] i_offsetSize - Length of offset (in bytes)
* @param[in] i_offset - Offset within device to read
* @param[in] i_length - Number of bytes to read
* @param[out] o_data - Data that was read
- * @return 0 on success else return code
+ * @return 0 on success else return code
* @platform OpenPOWER
*/
int (*i2c_read)( uint64_t i_master, uint16_t i_devAddr,
@@ -214,7 +242,12 @@ typedef struct hostInterfaces
/**
* @brief Write data to an i2c device
- * @param[in] i_master - Chip/engine/port of i2c bus
+ * @param[in] i_master - chip, engine and port packed into
+ * a single 64-bit argument
+ * ---------------------------------------------------
+ * | chip | reserved | eng | port |
+ * | (32) | (16) | (8) | (8) |
+ * ---------------------------------------------------
* @param[in] i_devAddr - I2C address of device
* @param[in] i_offsetSize - Length of offset (in bytes)
* @param[in] i_offset - Offset within device to write
@@ -227,7 +260,50 @@ typedef struct hostInterfaces
uint32_t i_offsetSize, uint32_t i_offset,
uint32_t i_length, void* i_data );
+ /**
+ * @brief Perform an IPMI transaction
+ * @param[in] netfn The IPMI netfn byte
+ * @param[in] cmd The IPMI cmd byte
+ * @param[in] tx_buf The IPMI packet to send to the host
+ * @param[in] tx_size The number of bytes to send
+ * @param[in] rx_buf A buffer to be populated with the IPMI
+ * response. First bytes will be the
+ * IPMI completion code.
+ * @param[inout] rx_size The allocated size of the rx buffer on input
+ * updated to the size of the response on output.
+ * @retval rc - non-zero on error
+ * @platform OpenPower
+ */
+ int (*ipmi_msg)(uint8_t netfn, uint8_t cmd,
+ void *tx_buf, size_t tx_size,
+ void *rx_buf, size_t *rx_size);
+
+
+ /**
+ * @brief Hardware has reported a memory error. This function requests the
+ * hypervisor to remove the all addresses within the address range given
+ * (including endpoints) from the available memory space.
+ *
+ * It is understood that the hypervisor may not be able to immediately
+ * deallocate the memory because it may be in use by a partition. Therefore, the
+ * hypervisor should cache all requests and deallocate the memory once it has
+ * been freed.
+ *
+ * @param i_startAddr The beginning address of the range.
+ * @param i_endAddr The end address of the range.
+ * @param i_errorType See enum MemoryError_t.
+ *
+ * @return 0 if the request is successfully received. Any value other than 0 on
+ * failure. The hypervisor should cache the request and return
+ * immediately. It should not wait for the request to be applied. See
+ * note above.
+ */
+ int32_t memory_error( uint64_t i_startAddr, uint64_t i_endAddr,
+ MemoryError_t i_errorType );
+
+
// Reserve some space for future growth.
+ // do NOT ever change this number, even if you add functions.
void (*reserved[32])(void);
} hostInterfaces_t;
diff --git a/src/include/usr/ipmi/ipmi_reasoncodes.H b/src/include/usr/ipmi/ipmi_reasoncodes.H
index 6244b2d00..8040f934b 100644
--- a/src/include/usr/ipmi/ipmi_reasoncodes.H
+++ b/src/include/usr/ipmi/ipmi_reasoncodes.H
@@ -35,6 +35,7 @@ namespace IPMI
MOD_IPMISRV_REPLY = 0x02, // IPMI::respond
MOD_IPMISENSOR = 0x03, // IPMI::sensor
MOD_IPMIDCMI = 0x04, // IPMI::sensor
+ MOD_IPMIRT = 0x05, // rt IPMI::send/IPMI::sendrecv
};
enum IPMIReasonCode
diff --git a/src/include/usr/ipmi/ipmisel.H b/src/include/usr/ipmi/ipmisel.H
index 82d86bf6f..de2dd3218 100644
--- a/src/include/usr/ipmi/ipmisel.H
+++ b/src/include/usr/ipmi/ipmisel.H
@@ -202,8 +202,26 @@ namespace IPMISEL
delete eSelExtra;
}
};
+
+ /**
+ * @brief parse the msg and call send_esel to send the esel (handles if
+ * the SEL reservation is lost)
+ * @param[in] i_msg
+ */
+ void process_esel(msg_t *i_msg);
+
+ /**
+ * @brief do the actual ipmi calls to send the esel data to the bmc
+ * @param[in] i_data esel data
+ * @param[in] o_err any error generated during the send
+ * @param[in] o_cc ipmi completion code from last sendrecv
+ */
+ void send_esel(IPMISEL::eselInitData * i_data,
+ errlHndl_t &o_err, IPMI::completion_code &o_cc);
+
} // namespace IPMISEL
+#ifndef __HOSTBOOT_RUNTIME
class IpmiSEL
{
public:
@@ -238,27 +256,12 @@ class IpmiSEL
*/
void execute(void);
- /**
- * @brief parse the msg and call send_esel to send the esel (handles if
- * the SEL reservation is lost)
- * @param[in] i_msg
- */
- void process_esel(msg_t *i_msg) const;
-
- /**
- * @brief do the actual ipmi calls to send the esel data to the bmc
- * @param[in] i_data esel data
- * @param[in] o_err any error generated during the send
- * @param[in] o_cc ipmi completion code from last sendrecv
- */
- void send_esel(IPMISEL::eselInitData * i_data,
- errlHndl_t &o_err, IPMI::completion_code &o_cc) const;
-
msg_q_t iv_msgQ; //!< ipmi message queue
//Disallow copying of this class.
IpmiSEL& operator=(const IpmiSEL&);
IpmiSEL(const IpmiSEL&);
};
+#endif
#endif
diff --git a/src/makefile b/src/makefile
index 97dbc3e39..6fdb8c6e6 100644
--- a/src/makefile
+++ b/src/makefile
@@ -236,6 +236,7 @@ RUNTIME_MODULES += $(if $(CONFIG_HTMGT),htmgt_rt)
RUNTIME_MODULES += $(if $(CONFIG_HBRT_PRD),bus_training_rt)
RUNTIME_MODULES += $(if $(CONFIG_HBRT_PRD),attn_rt)
RUNTIME_MODULES += $(if $(CONFIG_HBRT_PRD),prdf_rt)
+RUNTIME_MODULES += $(if $(CONFIG_BMC_IPMI),ipmi_rt)
RUNTIME_MODULES += pnor_rt
RUNTIME_DATA_MODULES +=
@@ -251,6 +252,7 @@ RUNTIME_TESTCASE_MODULES += testvpd_rt
RUNTIME_TESTCASE_MODULES += testhwpf_rt
RUNTIME_TESTCASE_MODULES += $(if $(CONFIG_HBRT_PRD),testprdf_rt)
RUNTIME_TESTCASE_MODULES += $(if $(CONFIG_HBRT_PRD),testattn_rt)
+RUNTIME_TESTCASE_MODULES += $(if $(CONFIG_BMC_IPMI),testipmi_rt)
RUNTIME_TESTCASE_MODULES += testpnor_rt
RELOCATABLE_IMAGE_LDFLAGS = -pie --export-dynamic
diff --git a/src/usr/ipmi/ipmirp.C b/src/usr/ipmi/ipmirp.C
index 51b943ab0..50f8ef2b5 100644
--- a/src/usr/ipmi/ipmirp.C
+++ b/src/usr/ipmi/ipmirp.C
@@ -865,7 +865,7 @@ namespace IPMI
IPMI_TRAC("queuing sync %x:%x", ipmi_msg->iv_netfun, ipmi_msg->iv_cmd);
int rc = msg_sendrecv(mq, ipmi_msg->iv_msg);
- // If the kernel didn't give a hassle about he message, check to see if
+ // If the kernel didn't give a hassle about the message, check to see if
// there was an error reported back from the other end of the queue. If
// this message made it to the other end of the queue, then our memory
// (io_data) is in the proper state.
diff --git a/src/usr/ipmi/ipmisel.C b/src/usr/ipmi/ipmisel.C
index df746f011..92a70faa5 100644
--- a/src/usr/ipmi/ipmisel.C
+++ b/src/usr/ipmi/ipmisel.C
@@ -44,125 +44,7 @@ extern trace_desc_t * g_trac_ipmi;
#define IPMI_TRAC(printf_string,args...) \
TRACFCOMP(g_trac_ipmi,"sel: "printf_string,##args)
-namespace IPMISEL
-{
- void sendESEL(uint8_t* i_eselData, uint32_t i_dataSize,
- uint32_t i_eid, uint8_t i_eventDirType,
- uint8_t i_sensorType, uint8_t i_sensorNumber)
- {
- IPMI_TRAC(ENTER_MRK "sendESEL()");
-
- // one message queue to the SEL thread
- static msg_q_t mq = Singleton<IpmiSEL>::instance().msgQueue();
-
- msg_t *msg = msg_allocate();
- msg->type = MSG_SEND_ESEL;
- msg->data[0] = i_eid;
-
- // create the sel record of information
- IPMISEL::selRecord l_sel;
- l_sel.record_type = IPMISEL::record_type_ami_esel;
- l_sel.generator_id = IPMISEL::generator_id_ami;
- l_sel.evm_format_version = IPMISEL::format_ipmi_version_2_0;
- l_sel.sensor_type = i_sensorType;
- l_sel.sensor_number = i_sensorNumber;
- l_sel.event_dir_type = i_eventDirType;
- l_sel.event_data1 = IPMISEL::event_data1_ami;
-
- eselInitData *eselData =
- new eselInitData(&l_sel, i_eselData, i_dataSize);
-
- msg->extra_data = eselData;
-
- //Send the msg to the sel thread
- int rc = msg_send(mq,msg);
- if(rc)
- {
- IPMI_TRAC(ERR_MRK "Failed (rc=%d) to send message",rc);
- delete eselData;
- }
- IPMI_TRAC(EXIT_MRK "sendESEL");
- return;
- } // sendESEL
-} // IPMISEL
-
-
-/**
- * @brief Constructor
- */
-IpmiSEL::IpmiSEL(void):
- iv_msgQ(msg_q_create())
-{
- IPMI_TRAC(ENTER_MRK "IpmiSEL ctor");
- task_create(&IpmiSEL::start,NULL);
-}
-
-/**
- * @brief Destructor
- */
-IpmiSEL::~IpmiSEL(void)
-{
- msg_q_destroy(iv_msgQ);
-}
-
-void* IpmiSEL::start(void* unused)
-{
- Singleton<IpmiSEL>::instance().execute();
- return NULL;
-}
-
-/**
- * @brief Entry point of the sel ipmi thread
- */
-//@todo: RTC 119832
-void IpmiSEL::execute(void)
-{
- //Mark as an independent daemon so if it crashes we terminate.
- task_detach();
-
- // Register shutdown events with init service.
- // Done at the "end" of shutdown processesing.
- // This will flush out any IPMI messages which were sent as
- // part of the shutdown processing. We chose MBOX priority
- // as we don't want to accidentally get this message after
- // interrupt processing has stopped in case we need intr to
- // finish flushing the pipe.
- INITSERVICE::registerShutdownEvent(iv_msgQ, IPMISEL::MSG_STATE_SHUTDOWN,
- INITSERVICE::MBOX_PRIORITY);
-
- while(true)
- {
- msg_t* msg = msg_wait(iv_msgQ);
-
- const IPMISEL::msg_type msg_type =
- static_cast<IPMISEL::msg_type>(msg->type);
-
- // Invert the "default" by checking here. This allows the compiler
- // to warn us if the enum has an unhadled case but still catch
- // runtime errors where msg_type is set out of bounds.
- assert(msg_type <= IPMISEL::MSG_LAST_TYPE,
- "msg_type %d not handled", msg_type);
-
- switch(msg_type)
- {
- case IPMISEL::MSG_SEND_ESEL:
- process_esel(msg);
- //done with msg
- msg_free(msg);
- break;
-
- case IPMISEL::MSG_STATE_SHUTDOWN:
- IPMI_TRAC(INFO_MRK "ipmisel shutdown event");
-
- //Respond that we are done shutting down.
- msg_respond(iv_msgQ, msg);
- break;
- }
- } // while(1)
- IPMI_TRAC(EXIT_MRK "message loop");
- return;
-} // execute
-
+// local functions
/*
* @brief Store either Record/Reserve ID from given data
*/
@@ -196,10 +78,63 @@ enum esel_retry
SLEEP_BASE = 2 * NS_PER_MSEC,
};
+
+namespace IPMISEL
+{
+void sendESEL(uint8_t* i_eselData, uint32_t i_dataSize,
+ uint32_t i_eid, uint8_t i_eventDirType,
+ uint8_t i_sensorType, uint8_t i_sensorNumber)
+{
+ IPMI_TRAC(ENTER_MRK "sendESEL()");
+
+#ifdef __HOSTBOOT_RUNTIME
+ // HBRT doesn't send a msg, but use the msg structure to pass the data
+ msg_t l_msg;
+ msg_t *msg = &l_msg;
+ memset(msg, 0, sizeof(msg_t));
+#else
+ msg_t *msg = msg_allocate();
+#endif
+ msg->type = MSG_SEND_ESEL;
+ msg->data[0] = i_eid;
+
+ // create the sel record of information
+ IPMISEL::selRecord l_sel;
+ l_sel.record_type = IPMISEL::record_type_ami_esel;
+ l_sel.generator_id = IPMISEL::generator_id_ami;
+ l_sel.evm_format_version = IPMISEL::format_ipmi_version_2_0;
+ l_sel.sensor_type = i_sensorType;
+ l_sel.sensor_number = i_sensorNumber;
+ l_sel.event_dir_type = i_eventDirType;
+ l_sel.event_data1 = IPMISEL::event_data1_ami;
+
+ eselInitData *eselData =
+ new eselInitData(&l_sel, i_eselData, i_dataSize);
+
+ msg->extra_data = eselData;
+
+#ifdef __HOSTBOOT_RUNTIME
+ process_esel(msg);
+#else
+ // one message queue to the SEL thread
+ static msg_q_t mq = Singleton<IpmiSEL>::instance().msgQueue();
+
+ //Send the msg to the sel thread
+ int rc = msg_send(mq,msg);
+ if(rc)
+ {
+ IPMI_TRAC(ERR_MRK "Failed (rc=%d) to send message",rc);
+ delete eselData;
+ }
+#endif
+ IPMI_TRAC(EXIT_MRK "sendESEL");
+ return;
+} // sendESEL
+
/*
* @brief process esel msg
*/
-void IpmiSEL::process_esel(msg_t *i_msg) const
+void process_esel(msg_t *i_msg)
{
errlHndl_t l_err = NULL;
IPMI::completion_code l_cc = IPMI::CC_UNKBAD;
@@ -212,7 +147,7 @@ void IpmiSEL::process_esel(msg_t *i_msg) const
while (l_send_count > 0)
{
// try to send the eles to the bmc
- send_esel(l_data, l_err, l_cc);
+ IPMISEL::send_esel(l_data, l_err, l_cc);
// if no error but last completion code was:
if ((l_err == NULL) &&
@@ -240,15 +175,31 @@ void IpmiSEL::process_esel(msg_t *i_msg) const
if(l_err)
{
+#ifdef __HOSTBOOT_RUNTIME
+ // HBRT can't commit an error, since this could already be in the
+ // errlCommit path since HBRT is single threaded
+ IPMI_TRAC(ERR_MRK "DELETING l_err 0x%.8X", l_err->eid());
+ delete l_err;
+ l_err = NULL;
+
+ // TODO RTC: 123419 investigate adding a 'iv_isIpmiEnabled' flag and setting
+ // that to false somehow, so that we can commit error logs in this path
+ // and future calls wont try to send them down.
+#else
l_err->collectTrace(IPMI_COMP_NAME);
errlCommit(l_err, IPMI_COMP_ID);
+#endif
}
else if((l_cc == IPMI::CC_OK) && // no error
(l_eid != 0)) // and it's an errorlog
{
+#ifdef __HOSTBOOT_RUNTIME
+ // TODO RTC: 123419 story to add storing errlog to PNOR in HBRT if IPMI
+#else
// eSEL successfully sent to the BMC - send an ack to the errlmanager
IPMI_TRAC(INFO_MRK "Sending ack for eid 0x%.8X", l_eid);
ERRORLOG::ErrlManager::errlAckErrorlog(l_eid);
+#endif
}
delete l_data;
@@ -260,8 +211,8 @@ void IpmiSEL::process_esel(msg_t *i_msg) const
/*
* @brief Send esel data to bmc
*/
-void IpmiSEL::send_esel(IPMISEL::eselInitData * i_data,
- errlHndl_t &o_err, IPMI::completion_code &o_cc) const
+void send_esel(IPMISEL::eselInitData * i_data,
+ errlHndl_t &o_err, IPMI::completion_code &o_cc)
{
IPMI_TRAC(ENTER_MRK "send_esel");
uint8_t* data = NULL;
@@ -402,3 +353,83 @@ void IpmiSEL::send_esel(IPMISEL::eselInitData * i_data,
return;
} // send_esel
+} // IPMISEL
+
+#ifndef __HOSTBOOT_RUNTIME
+/**
+ * @brief Constructor
+ */
+IpmiSEL::IpmiSEL(void)
+ :iv_msgQ(msg_q_create())
+{
+ IPMI_TRAC(ENTER_MRK "IpmiSEL ctor");
+ task_create(&IpmiSEL::start,NULL);
+}
+
+/**
+ * @brief Destructor
+ */
+IpmiSEL::~IpmiSEL(void)
+{
+ msg_q_destroy(iv_msgQ);
+}
+
+void* IpmiSEL::start(void* unused)
+{
+ Singleton<IpmiSEL>::instance().execute();
+ return NULL;
+}
+
+/**
+ * @brief Entry point of the sel ipmi thread
+ */
+//@todo: RTC 119832
+void IpmiSEL::execute(void)
+{
+ //Mark as an independent daemon so if it crashes we terminate.
+ task_detach();
+
+ // Register shutdown events with init service.
+ // Done at the "end" of shutdown processesing.
+ // This will flush out any IPMI messages which were sent as
+ // part of the shutdown processing. We chose MBOX priority
+ // as we don't want to accidentally get this message after
+ // interrupt processing has stopped in case we need intr to
+ // finish flushing the pipe.
+ INITSERVICE::registerShutdownEvent(iv_msgQ, IPMISEL::MSG_STATE_SHUTDOWN,
+ INITSERVICE::MBOX_PRIORITY);
+
+ while(true)
+ {
+ msg_t* msg = msg_wait(iv_msgQ);
+
+ const IPMISEL::msg_type msg_type =
+ static_cast<IPMISEL::msg_type>(msg->type);
+
+ // Invert the "default" by checking here. This allows the compiler
+ // to warn us if the enum has an unhadled case but still catch
+ // runtime errors where msg_type is set out of bounds.
+ assert(msg_type <= IPMISEL::MSG_LAST_TYPE,
+ "msg_type %d not handled", msg_type);
+
+ switch(msg_type)
+ {
+ case IPMISEL::MSG_SEND_ESEL:
+ IPMISEL::process_esel(msg);
+ //done with msg
+ msg_free(msg);
+ break;
+
+ case IPMISEL::MSG_STATE_SHUTDOWN:
+ IPMI_TRAC(INFO_MRK "ipmisel shutdown event");
+
+ //Respond that we are done shutting down.
+ msg_respond(iv_msgQ, msg);
+ break;
+ }
+ } // while(1)
+ IPMI_TRAC(EXIT_MRK "message loop");
+ return;
+} // execute
+#endif
+
diff --git a/src/usr/ipmi/makefile b/src/usr/ipmi/makefile
index 8dad57f3e..fb6a249a4 100644
--- a/src/usr/ipmi/makefile
+++ b/src/usr/ipmi/makefile
@@ -39,6 +39,7 @@ OBJS += ipmipowerstate.o
OBJS += ipmiselrecord.o
OBJS += ipmidcmi.o
+SUBDIRS += runtime.d
#SUBDIRS += test.d
include ${ROOTPATH}/config.mk
diff --git a/src/usr/ipmi/runtime/makefile b/src/usr/ipmi/runtime/makefile
new file mode 100644
index 000000000..21ab138ff
--- /dev/null
+++ b/src/usr/ipmi/runtime/makefile
@@ -0,0 +1,37 @@
+# IBM_PROLOG_BEGIN_TAG
+# This is an automatically generated prolog.
+#
+# $Source: src/usr/ipmi/runtime/makefile $
+#
+# OpenPOWER HostBoot Project
+#
+# Contributors Listed Below - COPYRIGHT 2015
+# [+] International Business Machines 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.
+#
+# IBM_PROLOG_END_TAG
+HOSTBOOT_RUNTIME = 1
+ROOTPATH = ../../../..
+MODULE = ipmi_rt
+
+OBJS += ipmisel.o
+OBJS += ipmisensor.o
+OBJS += rt_ipmirp.o
+
+SUBDIRS += test.d
+
+VPATH += ..
+include $(ROOTPATH)/config.mk
+
diff --git a/src/usr/ipmi/runtime/rt_ipmirp.C b/src/usr/ipmi/runtime/rt_ipmirp.C
new file mode 100644
index 000000000..7184c85f7
--- /dev/null
+++ b/src/usr/ipmi/runtime/rt_ipmirp.C
@@ -0,0 +1,142 @@
+/* IBM_PROLOG_BEGIN_TAG */
+/* This is an automatically generated prolog. */
+/* */
+/* $Source: src/usr/ipmi/runtime/rt_ipmirp.C $ */
+/* */
+/* OpenPOWER HostBoot Project */
+/* */
+/* Contributors Listed Below - COPYRIGHT 2015 */
+/* [+] International Business Machines 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. */
+/* */
+/* IBM_PROLOG_END_TAG */
+/**
+ * @file rt_ipmirp.C
+ * @brief IPMI resource provider definition for runtime
+ */
+
+#include "../ipmirp.H"
+#include "../ipmiconfig.H"
+#include "../ipmidd.H"
+#include <ipmi/ipmi_reasoncodes.H>
+#include <ipmi/ipmiif.H>
+
+#include <config.h>
+#include <sys/task.h>
+#include <initservice/taskargs.H>
+#include <initservice/initserviceif.H>
+#include <sys/vfs.h>
+
+#include <targeting/common/commontargeting.H>
+#include <kernel/ipc.H>
+#include <arch/ppc.H>
+#include <errl/errlmanager.H>
+#include <sys/time.h>
+#include <sys/misc.h>
+#include <errno.h>
+#include <runtime/interface.h>
+
+trace_desc_t * g_trac_ipmi;
+#define IPMI_TRAC(printf_string,args...) \
+ TRACFCOMP(g_trac_ipmi,"rt: "printf_string,##args)
+
+namespace IPMI
+{
+ // TODO RTC: 124099 move to a _hb attribute
+ // ATTR_IPMI_MAX_BUFFER_SEND_SIZE
+ static const size_t g_max_buffer = 61;
+ size_t max_buffer(void)
+ {
+ return g_max_buffer;
+ }
+
+ ///
+ /// @brief Synchronus message send
+ ///
+ errlHndl_t sendrecv(const IPMI::command_t& i_cmd,
+ IPMI::completion_code& o_completion_code,
+ size_t& io_len, uint8_t*& io_data)
+ {
+ errlHndl_t err = NULL;
+ int rc = 0;
+
+ // if the buffer is too large this is a programming error.
+ assert(io_len <= g_max_buffer);
+
+ IPMI_TRAC("calling sync %x:%x len=%d",
+ i_cmd.first, i_cmd.second, io_len);
+
+ if(g_hostInterfaces && g_hostInterfaces->ipmi_msg)
+ {
+ size_t l_len = g_max_buffer; // max size the BMC can return
+ uint8_t *l_data = new uint8_t[l_len];
+
+ rc = g_hostInterfaces->ipmi_msg(
+ i_cmd.first, i_cmd.second,
+ io_data, io_len,
+ l_data, &l_len);
+
+ if(rc)
+ {
+ IPMI_TRAC(ERR_MRK
+ "Failed sending ipmi msg (%x:%x) to bmc rc: %d. ",
+ i_cmd.first, i_cmd.second, rc);
+
+ /* @errorlog tag
+ * @errortype ERRL_SEV_UNRECOVERABLE
+ * @moduleid IPMI::MOD_IPMIRT
+ * @reasoncode IPMI::RC_INVALID_SENDRECV
+ * @userdata1[0:31] rc from ipmi_msg()
+ * @userdata1[32:46] netfn of failing msg
+ * @userdata1[47:63] cmd of failing msg
+ * @userdata2 length of failing msg
+ * @devdesc ipmi_msg() failed
+ * @custdesc Firmware error
+ */
+ err = new ERRORLOG::ErrlEntry(
+ ERRORLOG::ERRL_SEV_UNRECOVERABLE,
+ IPMI::MOD_IPMIRT,
+ IPMI::RC_INVALID_SENDRECV,
+ TWO_UINT32_TO_UINT64(rc,
+ TWO_UINT16_TO_UINT32(i_cmd.first, i_cmd.second)),
+ io_len,
+ true);
+ err->collectTrace(IPMI_COMP_NAME);
+ delete[] io_data;
+ io_data = NULL;
+ io_len = 0;
+ }
+ else
+ {
+ // clean up the memory for the caller
+ o_completion_code = static_cast<IPMI::completion_code>(io_data[0]);
+
+ // now need to create the buffer to return
+ io_len = l_len - 1; // get rid of the completion_code
+ delete[] io_data;
+ io_data = new uint8_t[io_len];
+ memcpy(io_data, &l_data[1], io_len); // data after CC
+ }
+ delete[] l_data;
+ }
+ else
+ {
+ IPMI_TRAC(ERR_MRK
+ "Host interfaces not initialized; ipmi msg not sent. ");
+ }
+
+ return err;
+ } // sendrecv
+};
diff --git a/src/usr/ipmi/runtime/test/makefile b/src/usr/ipmi/runtime/test/makefile
new file mode 100644
index 000000000..a12933112
--- /dev/null
+++ b/src/usr/ipmi/runtime/test/makefile
@@ -0,0 +1,31 @@
+# IBM_PROLOG_BEGIN_TAG
+# This is an automatically generated prolog.
+#
+# $Source: src/usr/ipmi/runtime/test/makefile $
+#
+# OpenPOWER HostBoot Project
+#
+# Contributors Listed Below - COPYRIGHT 2015
+# [+] International Business Machines 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.
+#
+# IBM_PROLOG_END_TAG
+HOSTBOOT_RUNTIME = 1
+ROOTPATH = ../../../../..
+
+MODULE = testipmi_rt
+TESTS = *.H
+
+include ${ROOTPATH}/config.mk
diff --git a/src/usr/ipmi/runtime/test/rt_ipmitest.H b/src/usr/ipmi/runtime/test/rt_ipmitest.H
new file mode 100644
index 000000000..b3a252e31
--- /dev/null
+++ b/src/usr/ipmi/runtime/test/rt_ipmitest.H
@@ -0,0 +1,102 @@
+/* IBM_PROLOG_BEGIN_TAG */
+/* This is an automatically generated prolog. */
+/* */
+/* $Source: src/usr/ipmi/runtime/test/rt_ipmitest.H $ */
+/* */
+/* OpenPOWER HostBoot Project */
+/* */
+/* Contributors Listed Below - COPYRIGHT 2015 */
+/* [+] International Business Machines 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. */
+/* */
+/* IBM_PROLOG_END_TAG */
+#ifndef __RT_IPMITEST_H
+#define __RT_IPMITEST_H
+
+/**
+ * @file ipmitest.H
+ *
+ * @brief Test case for IPMI messages
+*/
+
+#include <cxxtest/TestSuite.H>
+
+#include "../../../trace/entry.H"
+
+#include <ipmi/ipmiif.H>
+#include <ipmi/ipmisensor.H>
+
+
+class RT_IpmiTest: public CxxTest::TestSuite
+{
+public:
+
+
+ /**
+ * @brief call sendrecv directly
+ */
+ void testIpmi1(void)
+ {
+ do
+ {
+ IPMI::completion_code cc = IPMI::CC_UNKBAD;
+ size_t len = 0;
+ uint8_t* data = NULL;
+ errlHndl_t err = IPMI::sendrecv(IPMI::get_capabilities(), cc, len, data);
+
+ TS_WARN("testIpmi1: cc x%x, len %d", cc, len);
+
+ if ( err != NULL )
+ {
+ TS_FAIL("testIpmi1: get_capabilities() failed");
+ break;
+ }
+ if (cc != IPMI::CC_OK)
+ {
+ TS_FAIL("testIpmi1: get_capabilities() failed with cc 0x%x", cc);
+ break;
+ }
+ if (len != 5)
+ {
+ TS_FAIL("testIpmi1: get_capabilities() returned len %d instead of 5",
+ len);
+ break;
+ }
+
+ TS_WARN("testIpmi1: get_capabilities x%x, x%x x%x x%x x%x",
+ data[0], data[1], data[2], data[3], data[4]);
+
+ }
+ while(0);
+ }
+
+ /**
+ * @brief call IPMI::sensor function
+ */
+ void testIpmi2(void)
+ {
+ do
+ {
+ uint8_t l_sensorNumber = SENSOR::getFaultSensorNumber(
+ TARGETING::MASTER_PROCESSOR_CHIP_TARGET_SENTINEL);
+
+ TS_WARN("testIpmi2: getFaultSensorNumber x%x",
+ l_sensorNumber);
+ }
+ while(0);
+ }
+};
+
+#endif
diff --git a/src/usr/testcore/rtloader/loader.H b/src/usr/testcore/rtloader/loader.H
index 041337118..9ac9c5ebc 100644
--- a/src/usr/testcore/rtloader/loader.H
+++ b/src/usr/testcore/rtloader/loader.H
@@ -41,6 +41,7 @@
#include <string.h>
#include <devicefw/userif.H>
#include <pnor/ecc.H>
+#include <ipmi/ipmiif.H>
trace_desc_t* g_trac_hbrt = NULL;
TRAC_INIT(&g_trac_hbrt, "HBRT_TEST", 2*KILOBYTE);
@@ -122,6 +123,7 @@ class RuntimeLoaderTest : public CxxTest::TestSuite
intf->get_reserved_mem = rt_get_reserved_mem;
intf->pnor_read = rt_pnor_read;
intf->pnor_write= rt_pnor_write;
+ intf->ipmi_msg= rt_ipmi_msg;
// Call init.
runtimeInterfaces_t* rtInterface =
@@ -518,6 +520,33 @@ class RuntimeLoaderTest : public CxxTest::TestSuite
return cv_targ_addr;
}
+ static int rt_ipmi_msg(uint8_t netfn, uint8_t cmd,
+ void *tx_buf, size_t tx_size,
+ void *rx_buf, size_t *rx_size)
+ {
+ TRACFCOMP(g_trac_hbrt, ENTER_MRK
+ "rt_ipmi_msg: tx_buf:%x/%x, size:%d, rx_buf:%p, size:%d",
+ netfn, cmd, tx_size,
+ rx_buf, *rx_size);
+
+ errlHndl_t l_err = NULL;
+ do {
+ ((uint8_t*)rx_buf)[0] = IPMI::CC_OK;
+ rx_size = 0;
+ } while (0);
+
+ //commit the error
+ uint32_t l_plid = 0;
+ if (l_err)
+ {
+ l_plid = l_err->plid();
+ errlCommit (l_err, CXXTEST_COMP_ID);
+ }
+ TRACFCOMP(g_trac_hbrt, EXIT_MRK"rt_ipmi_msg");
+ return l_plid;
+ }
+
+
static uint64_t cv_vpd_addr;
static uint64_t cv_vpd_phys_addr;
static uint64_t cv_targ_addr;
OpenPOWER on IntegriCloud