summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--src/include/usr/ipmi/ipmiif.H7
-rw-r--r--src/include/usr/pnor/pnor_reasoncodes.H7
-rw-r--r--src/usr/ipmibase/ipmirp.C16
-rw-r--r--src/usr/pnor/HBconfig10
-rw-r--r--src/usr/pnor/ast_mboxdd.C8
-rw-r--r--src/usr/pnor/makefile3
-rw-r--r--src/usr/pnor/pnor_ipmidd.C870
-rw-r--r--src/usr/pnor/pnor_ipmidd.H347
-rw-r--r--src/usr/pnor/pnor_mboxdd.H4
-rw-r--r--src/usr/pnor/pnorvalid.C9
-rw-r--r--src/usr/pnor/test/pnorddtest.H10
11 files changed, 1270 insertions, 21 deletions
diff --git a/src/include/usr/ipmi/ipmiif.H b/src/include/usr/ipmi/ipmiif.H
index 1a2296b04..59eee8673 100644
--- a/src/include/usr/ipmi/ipmiif.H
+++ b/src/include/usr/ipmi/ipmiif.H
@@ -291,6 +291,9 @@ namespace IPMI
inline const command_t pnor_response(void)
{ return std::make_pair(NETFUN_IBM, 0x08); }
+ inline const command_t hiomap_event(void)
+ { return std::make_pair(NETFUN_IBM, 0x0f); }
+
// $TODO RTC:123256 - need to add code to get dcmi capabilities
// This is a dcmi message used to request the
// user defined power limit from the BMC.
@@ -307,6 +310,10 @@ namespace IPMI
inline const command_t test_drop(void)
{ return std::make_pair(NETFUN_APP, 0x3e); }
+ // IPMI PNOR
+ inline const command_t pnor_hiomap_request(void)
+ { return std::make_pair(NETFUN_IBM, 0x5a); }
+
/**
* Send message asynchronously
* @param[in] i_cmd, the network function and command
diff --git a/src/include/usr/pnor/pnor_reasoncodes.H b/src/include/usr/pnor/pnor_reasoncodes.H
index c6201a4ab..fb7435a33 100644
--- a/src/include/usr/pnor/pnor_reasoncodes.H
+++ b/src/include/usr/pnor/pnor_reasoncodes.H
@@ -112,6 +112,9 @@ namespace PNOR
// ast_mboxdd.C
MOD_ASTMBOXDD_DO_MESSAGE = 0xE0, /**< astMbox::doMessage */
+
+ // pnor_ipmidd.C
+ MOD_IPMIPNORDD_SEND_MESSAGE = 0xF0, /**< PnorDD::sendMessage */
};
enum PNORReasonCode
@@ -177,8 +180,8 @@ namespace PNOR
RC_BASE_EXT_MISMATCH = PNOR_COMP_ID | 0x2F,
RC_KEY_TRAN_FLAG_UNSET = PNOR_COMP_ID | 0x30,
RC_BAD_SECURE_MAGIC_NUM = PNOR_COMP_ID | 0x31,
- RC_MBOX_BAD_SEQUENCE = PNOR_COMP_ID | 0x32,
- RC_MBOX_ERROR_STATUS = PNOR_COMP_ID | 0x33,
+ RC_HIOMAP_BAD_SEQUENCE = PNOR_COMP_ID | 0x32,
+ RC_HIOMAP_ERROR_STATUS = PNOR_COMP_ID | 0x33,
RC_UNSIGNED_PNOR_SECTION = PNOR_COMP_ID | 0x34,
RC_NOT_A_LOADED_SECTION = PNOR_COMP_ID | 0x35,
RC_NOT_A_SUPPORTED_SECTION = PNOR_COMP_ID | 0x36,
diff --git a/src/usr/ipmibase/ipmirp.C b/src/usr/ipmibase/ipmirp.C
index dabbea218..665b8eb18 100644
--- a/src/usr/ipmibase/ipmirp.C
+++ b/src/usr/ipmibase/ipmirp.C
@@ -598,7 +598,16 @@ void IpmiRP::execute(void)
// bottom of this loop will start the transmit process.
// Be sure to push_back to ensure ordering of transmission.
case IPMI::MSG_STATE_SEND:
- if (!l_shutdown_pending)
+ {
+ IPMI::Message* l_ipmi_msg =
+ static_cast<IPMI::Message*>(msg->extra_data);
+ const IPMI::command_t l_pnor = IPMI::pnor_hiomap_request();
+ bool l_is_pnor = (l_ipmi_msg->iv_netfun == l_pnor.first &&
+ l_ipmi_msg->iv_cmd == l_pnor.second);
+ IPMI_TRAC(WARN_MRK "Got message (0x%x:0x%x): l_is_pnor: %d",
+ l_ipmi_msg->iv_netfun, l_ipmi_msg->iv_cmd, l_is_pnor);
+ /* PNOR requests always allowed, else we hang shutdown */
+ if (!l_shutdown_pending || l_is_pnor)
{
iv_sendq.push_back(msg);
}
@@ -606,15 +615,14 @@ void IpmiRP::execute(void)
else
{
IPMI_TRAC(WARN_MRK "IPMI shutdown pending. Message dropped");
- IPMI::Message* ipmi_msg =
- static_cast<IPMI::Message*>(msg->extra_data);
- response(ipmi_msg, IPMI::CC_BADSTATE);
+ response(l_ipmi_msg, IPMI::CC_BADSTATE);
msg_free(msg);
}
break;
// State changes from the IPMI hardware. These are async
// messages so we get rid of them here.
+ }
case IPMI::MSG_STATE_IDLE:
msg_free(msg);
// No-op - we do it at the bottom of the loop.
diff --git a/src/usr/pnor/HBconfig b/src/usr/pnor/HBconfig
index b256eaf00..d70bb069f 100644
--- a/src/usr/pnor/HBconfig
+++ b/src/usr/pnor/HBconfig
@@ -1,15 +1,21 @@
config PNORDD_IS_SFC
default y
- depends on !PNORDD_IS_BMCMBOX
+ depends on !PNORDD_IS_BMCMBOX && !PNORDD_IS_IPMI
help
The Serial Flash Controller is based on the SFC backends
config PNORDD_IS_BMCMBOX
default n
- depends on !PNORDD_IS_SFC
+ depends on !PNORDD_IS_SFC && !PNORDD_IS_IPMI
help
The Serial Flash Controller is using the MBOX BMC protocol
+config PNORDD_IS_IPMI
+ default n
+ depends on !PNORDD_IS_SFC && !PNORDD_IS_BMCMBOX
+ help
+ The Serial Flash Controller is managed via IPMI
+
config SFC_IS_IBM_DPSS
default n
depends on !SFC_IS_AST2400 && !SFC_IS_FAKE && !SFC_IS_AST2500 && PNORDD_IS_SFC
diff --git a/src/usr/pnor/ast_mboxdd.C b/src/usr/pnor/ast_mboxdd.C
index f8b4768dd..b7504e934 100644
--- a/src/usr/pnor/ast_mboxdd.C
+++ b/src/usr/pnor/ast_mboxdd.C
@@ -241,7 +241,7 @@ errlHndl_t astMbox::doMessage(mboxMessage& io_msg)
/*@
* @errortype
* @moduleid PNOR::MOD_ASTMBOXDD_DO_MESSAGE
- * @reasoncode PNOR::RC_MBOX_BAD_SEQUENCE
+ * @reasoncode PNOR::RC_HIOMAP_BAD_SEQUENCE
* @userdata1[48:55] mbox status 1 reg
* @userdata1[56:63] mbox flag reg
* @userdata2[32:39] original command code
@@ -254,7 +254,7 @@ errlHndl_t astMbox::doMessage(mboxMessage& io_msg)
*/
l_err = new ERRORLOG::ErrlEntry(ERRORLOG::ERRL_SEV_UNRECOVERABLE,
PNOR::MOD_ASTMBOXDD_DO_MESSAGE,
- PNOR::RC_MBOX_BAD_SEQUENCE,
+ PNOR::RC_HIOMAP_BAD_SEQUENCE,
TWO_UINT8_TO_UINT16(l_stat1, l_flags),
FOUR_UINT8_TO_UINT32(old_cmd,
io_msg.iv_cmd,
@@ -282,7 +282,7 @@ errlHndl_t astMbox::doMessage(mboxMessage& io_msg)
/*@
* @errortype
* @moduleid PNOR::MOD_ASTMBOXDD_DO_MESSAGE
- * @reasoncode PNOR::RC_MBOX_ERROR_STATUS
+ * @reasoncode PNOR::RC_HIOMAP_ERROR_STATUS
* @userdata1[48:55] mbox status 1 reg
* @userdata1[56:63] mbox flag reg
* @userdata2[32:39] original command code
@@ -295,7 +295,7 @@ errlHndl_t astMbox::doMessage(mboxMessage& io_msg)
*/
l_err = new ERRORLOG::ErrlEntry(ERRORLOG::ERRL_SEV_UNRECOVERABLE,
PNOR::MOD_ASTMBOXDD_DO_MESSAGE,
- PNOR::RC_MBOX_ERROR_STATUS,
+ PNOR::RC_HIOMAP_ERROR_STATUS,
TWO_UINT8_TO_UINT16(l_stat1, l_flags),
FOUR_UINT8_TO_UINT32(old_cmd,
io_msg.iv_cmd,
diff --git a/src/usr/pnor/makefile b/src/usr/pnor/makefile
index d7609af13..13566f6b3 100644
--- a/src/usr/pnor/makefile
+++ b/src/usr/pnor/makefile
@@ -5,7 +5,7 @@
#
# OpenPOWER HostBoot Project
#
-# Contributors Listed Below - COPYRIGHT 2011,2017
+# Contributors Listed Below - COPYRIGHT 2011,2018
# [+] Google Inc.
# [+] International Business Machines Corp.
#
@@ -33,6 +33,7 @@ OBJS += $(if $(CONFIG_SECUREBOOT),spnorrp.o)
OBJS += $(if $(CONFIG_PNORDD_IS_SFC),pnordd.o)
OBJS += $(if $(CONFIG_PNORDD_IS_BMCMBOX),ast_mboxdd.o)
OBJS += $(if $(CONFIG_PNORDD_IS_BMCMBOX),pnor_mboxdd.o)
+OBJS += $(if $(CONFIG_PNORDD_IS_IPMI),pnor_ipmidd.o)
OBJS += pnor_common.o
OBJS += pnorvalid.o
OBJS += ecc.o
diff --git a/src/usr/pnor/pnor_ipmidd.C b/src/usr/pnor/pnor_ipmidd.C
new file mode 100644
index 000000000..68613eafd
--- /dev/null
+++ b/src/usr/pnor/pnor_ipmidd.C
@@ -0,0 +1,870 @@
+/* IBM_PROLOG_BEGIN_TAG */
+/* This is an automatically generated prolog. */
+/* */
+/* $Source: src/usr/pnor/pnor_ipmidd.C $ */
+/* */
+/* OpenPOWER HostBoot Project */
+/* */
+/* Contributors Listed Below - COPYRIGHT 2018 */
+/* [+] 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 pnor_ipmidd.C
+ *
+ * @brief An implementation of the HIOMAP protocol over IPMI
+ */
+
+/*****************************************************************************/
+// I n c l u d e s
+/*****************************************************************************/
+#include <algorithm>
+#include <arch/ppc.H>
+#include <sys/mmio.h>
+#include <sys/msg.h>
+#include <sys/task.h>
+#include <sys/sync.h>
+#include <sys/time.h>
+#include <string.h>
+#include <stdio.h>
+#include <devicefw/driverif.H>
+#include <trace/interface.H>
+#include <errl/errlentry.H>
+#include <errl/errlmanager.H>
+#include <errl/errludlogregister.H>
+#include <errl/errludstring.H>
+#include <targeting/common/targetservice.H>
+#include <sio/sio.H>
+#include "ast_mboxdd.H"
+#include "pnor_ipmidd.H"
+#include "pnor_common.H"
+#include "pnor_utils.H"
+#include <pnor/pnorif.H>
+#include <pnor/pnor_reasoncodes.H>
+#include <sys/time.h>
+#include <initservice/initserviceif.H>
+#include <util/align.H>
+#include <lpc/lpcif.H>
+#include <config.h>
+#include "sfcdd.H"
+#include <ipmi/ipmiif.H>
+
+#include <kernel/console.H>
+
+/**
+ * @brief HIOMAP commands
+ */
+enum {
+ HIOMAP_C_RESET = 1,
+ HIOMAP_C_GET_INFO = 2,
+ HIOMAP_C_GET_FLASH_INFO = 3,
+ HIOMAP_C_CREATE_READ_WINDOW = 4,
+ HIOMAP_C_CLOSE = 5,
+ HIOMAP_C_CREATE_WRITE_WINDOW = 6,
+ HIOMAP_C_MARK_DIRTY = 7,
+ HIOMAP_C_FLUSH = 8,
+ HIOMAP_C_ACK = 9,
+ HIOMAP_C_ERASE = 10,
+ HIOMAP_C_GET_FLASH_NAME = 11,
+ HIOMAP_C_LOCK = 12,
+};
+
+/**
+ * @brief HIOMAP protocol versions
+ */
+enum {
+ HIOMAP_V_1 = 1,
+ HIOMAP_V_2 = 2,
+};
+
+// Initialized in pnorrp.C
+extern trace_desc_t* g_trac_pnor;
+
+namespace PNOR
+{
+
+/**
+ * @brief Performs an PNOR Read Operation
+ * This function performs a PNOR Read operation. It follows a pre-defined
+ * prototype functions in order to be registered with the device-driver
+ * framework.
+ *
+ * @param[in] i_opType Operation type, see DeviceFW::OperationType
+ * in driverif.H
+ * @param[in] i_target PNOR target
+ * @param[in/out] io_buffer Read: Pointer to output data storage
+ * Write: Pointer to input data storage
+ * @param[in/out] io_buflen Input: size of io_buffer (in bytes)
+ * Output:
+ * Read: Size of output data
+ * Write: Size of data written
+ * @param[in] i_accessType DeviceFW::AccessType enum (usrif.H)
+ * @param[in] i_args This is an argument list for DD framework.
+ * In this function, there's only one argument,
+ * containing the PNOR address and chip select
+ * @return errlHndl_t
+ */
+errlHndl_t ddRead(DeviceFW::OperationType i_opType,
+ TARGETING::Target* i_target,
+ void* io_buffer,
+ size_t& io_buflen,
+ int64_t i_accessType,
+ va_list i_args)
+{
+ errlHndl_t l_err = NULL;
+ uint64_t l_addr = va_arg(i_args, uint64_t);
+
+ do
+ {
+ //@todo (RTC:36951) - add support for unaligned data
+ // Ensure we are operating on a 32-bit (4-byte) boundary
+ assert( reinterpret_cast<uint64_t>(io_buffer) % 4 == 0 );
+ assert( io_buflen % 4 == 0 );
+
+ // The PNOR device driver interface is initialized with the
+ // MASTER_PROCESSOR_CHIP_TARGET_SENTINEL. Other target
+ // access requires a separate PnorDD class created
+ assert( i_target == TARGETING::MASTER_PROCESSOR_CHIP_TARGET_SENTINEL );
+
+ // Read the flash
+ l_err = Singleton<PnorDD>::instance().readFlash(io_buffer,
+ io_buflen,
+ l_addr);
+
+ if(l_err)
+ {
+ break;
+ }
+
+ }
+ while(0);
+
+ return l_err;
+}
+
+/**
+ * @brief Performs an PNOR Write Operation
+ * This function performs a PNOR Write operation. It follows a pre-defined
+ * prototype functions in order to be registered with the device-driver
+ * framework.
+ *
+ * @param[in] i_opType Operation type, see DeviceFW::OperationType
+ * in driverif.H
+ * @param[in] i_target PNOR target
+ * @param[in/out] io_buffer Read: Pointer to output data storage
+ * Write: Pointer to input data storage
+ * @param[in/out] io_buflen Input: size of io_buffer (in bytes)
+ * Output:
+ * Read: Size of output data
+ * Write: Size of data written
+ * @param[in] i_accessType DeviceFW::AccessType enum (usrif.H)
+ * @param[in] i_args This is an argument list for DD framework.
+ * In this function, there's only one argument,
+ * containing the PNOR address and chip select
+ * @return errlHndl_t
+ */
+errlHndl_t ddWrite(DeviceFW::OperationType i_opType,
+ TARGETING::Target* i_target,
+ void* io_buffer,
+ size_t& io_buflen,
+ int64_t i_accessType,
+ va_list i_args)
+{
+ errlHndl_t l_err = NULL;
+ uint64_t l_addr = va_arg(i_args, uint64_t);
+
+ do
+ {
+ //@todo (RTC:36951) - add support for unaligned data
+ // Ensure we are operating on a 32-bit (4-byte) boundary
+ assert( reinterpret_cast<uint64_t>(io_buffer) % 4 == 0 );
+ assert( io_buflen % 4 == 0 );
+
+ // The PNOR device driver interface is initialized with the
+ // MASTER_PROCESSOR_CHIP_TARGET_SENTINEL. Other target
+ // access requires a separate PnorDD class created
+ assert( i_target == TARGETING::MASTER_PROCESSOR_CHIP_TARGET_SENTINEL );
+
+ // Write the flash
+ l_err = Singleton<PnorDD>::instance().writeFlash(io_buffer,
+ io_buflen,
+ l_addr);
+
+ if(l_err)
+ {
+ break;
+ }
+
+ }
+ while(0);
+
+ return l_err;
+}
+
+/**
+ * @brief Informs caller if the driver is using
+ * L3 Cache for fake PNOR or not.
+ *
+ * @return Indicate state of fake PNOR
+ * true = PNOR DD is using L3 Cache for fake PNOR
+ * false = PNOR DD not using L3 Cache for fake PNOR
+ */
+bool usingL3Cache()
+{
+ return false;
+}
+
+/**
+ * @brief Retrieve some information about the PNOR/SFC hardware
+ */
+void getPnorInfo( PnorInfo_t& o_pnorInfo )
+{
+ o_pnorInfo.mmioOffset = LPC_SFC_MMIO_OFFSET | LPC_FW_SPACE;
+ o_pnorInfo.norWorkarounds =
+ Singleton<PnorDD>::instance().getNorWorkarounds();
+ o_pnorInfo.flashSize =
+ Singleton<PnorDD>::instance().getNorSize();
+}
+
+
+
+// Register MBOXDD access functions to DD framework
+DEVICE_REGISTER_ROUTE(DeviceFW::READ,
+ DeviceFW::PNOR,
+ TARGETING::TYPE_PROC,
+ ddRead);
+
+DEVICE_REGISTER_ROUTE(DeviceFW::WRITE,
+ DeviceFW::PNOR,
+ TARGETING::TYPE_PROC,
+ ddWrite);
+
+}; //namespace PNOR
+
+
+///////////////////////////////////////////////////////////////////////////////
+///////////////////////////////////////////////////////////////////////////////
+
+
+/**
+ * @brief Performs a PNOR Read Operation
+ */
+errlHndl_t PnorDD::readFlash(void* o_buffer,
+ size_t& io_buflen,
+ uint64_t i_address)
+{
+ /* We support 256M max */
+ uint32_t l_address = i_address & 0x0fffffff;
+
+ mutex_lock(iv_mutex_ptr);
+ errlHndl_t l_err = _readFlash( l_address, io_buflen, o_buffer );
+ mutex_unlock(iv_mutex_ptr);
+
+ return l_err;
+}
+
+/**
+ * @brief Performs a PNOR Write Operation
+ */
+errlHndl_t PnorDD::writeFlash(const void* i_buffer,
+ size_t& io_buflen,
+ uint64_t i_address)
+{
+ TRACDCOMP(g_trac_pnor, ENTER_MRK"PnorDD::writeFlash(i_address=0x%llx)> ", i_address);
+ errlHndl_t l_err = NULL;
+
+ uint32_t l_address = i_address & 0x0fffffff;
+
+ mutex_lock(iv_mutex_ptr);
+ l_err = _writeFlash( l_address, io_buflen, i_buffer );
+ mutex_unlock(iv_mutex_ptr);
+
+ if( l_err )
+ {
+ io_buflen = 0;
+ }
+
+ TRACDCOMP(g_trac_pnor, EXIT_MRK"PnorDD::writeFlash(i_address=0x%llx)> io_buflen=%.8X", i_address, io_buflen);
+
+ return l_err;
+}
+
+
+/********************
+ Private/Protected Methods
+ ********************/
+mutex_t PnorDD::cv_mutex = MUTEX_INITIALIZER;
+
+/**
+ * LPC FW space accessors
+ */
+errlHndl_t PnorDD::readLpcFw(uint32_t i_offset, size_t i_size, void* o_buf)
+{
+ // Exploit new LPC large read facility
+ return deviceOp(DeviceFW::READ, iv_target, o_buf, i_size,
+ DEVICE_LPC_ADDRESS(LPC::TRANS_FW, i_offset));
+}
+
+errlHndl_t PnorDD::writeLpcFw(uint32_t i_offset, size_t i_size,
+ const void* i_buf)
+{
+ // Exploit new LPC large write facility
+ return deviceOp(DeviceFW::WRITE, iv_target, (void*)i_buf, i_size,
+ DEVICE_LPC_ADDRESS(LPC::TRANS_FW, i_offset));
+}
+
+errlHndl_t PnorDD::adjustWindow(bool i_isWrite, uint32_t i_reqAddr,
+ size_t i_reqSize, uint32_t& o_lpcAddr,
+ size_t& o_chunkLen)
+{
+ errlHndl_t l_err = NULL;
+ uint32_t l_pos, l_reqSize;
+
+ do
+ {
+ /*
+ * Handle the case where the window is already opened, is of
+ * the right type and contains the requested address.
+ */
+ uint32_t l_wEnd = iv_curWindowOffset + iv_curWindowSize;
+
+ /* A read request can be serviced by a write window */
+ if (iv_curWindowOpen &&
+ (iv_curWindowWrite || !i_isWrite) &&
+ i_reqAddr >= iv_curWindowOffset && i_reqAddr < l_wEnd)
+ {
+ size_t l_gap = (l_wEnd - i_reqAddr);
+
+ o_lpcAddr = iv_curWindowLpcOffset +(i_reqAddr - iv_curWindowOffset);
+ o_chunkLen = std::min(i_reqSize, l_gap);
+ TRACDCOMP(g_trac_pnor, "LPC window @ 0x%x (0x%x + (0x%x - 0x%x)) for 0x%x\n",
+ o_lpcAddr, iv_curWindowLpcOffset, i_reqAddr,
+ iv_curWindowOffset, o_chunkLen);
+ return NULL;
+ }
+
+ /*
+ * We need a window change, mark it closed first
+ */
+ iv_curWindowOpen = false;
+
+ /*
+ * Then open the new one at the right position. The required
+ * alignment differs between protocol versions
+ */
+ TRACDCOMP(g_trac_pnor,
+ "astMboxDD::adjustWindow using protocol version: %d",
+ iv_protocolVersion);
+ uint32_t l_blockMask = (1u << iv_blockShift) - 1;
+ l_pos = i_reqAddr & ~l_blockMask;
+ l_reqSize = (((i_reqAddr + i_reqSize) + l_blockMask) & ~l_blockMask)
+ - l_pos;
+
+ TRACDCOMP(g_trac_pnor, "adjustWindow opening %s window at 0x%08x"
+ " for addr 0x%08x req_size 0x%08x",
+ i_isWrite ? "write" : "read", l_pos, i_reqAddr, l_reqSize);
+
+ uint8_t cmd = i_isWrite ? HIOMAP_C_CREATE_WRITE_WINDOW
+ : HIOMAP_C_CREATE_READ_WINDOW;
+ HiomapMessage* winMsg = new HiomapMessage(cmd);
+ winMsg->put16(0, l_pos >> iv_blockShift);
+ winMsg->put16(2, l_reqSize >> iv_blockShift);
+
+ size_t l_len = 4;
+ l_err = sendCommand(winMsg, l_len);
+
+ assert(l_len == 6);
+
+ if (!l_err)
+ {
+ iv_curWindowLpcOffset = winMsg->get16(0) << iv_blockShift;
+ iv_curWindowSize = winMsg->get16(2) << iv_blockShift;
+ iv_curWindowOffset = winMsg->get16(4) << iv_blockShift;
+ }
+
+ delete winMsg;
+
+ if (l_err)
+ {
+ break;
+ }
+
+ iv_curWindowOpen = true;
+ iv_curWindowWrite = i_isWrite;
+
+ TRACDCOMP(g_trac_pnor, " curWindowOffset = %08x", iv_curWindowOffset);
+ TRACDCOMP(g_trac_pnor, " curWindowSize = %08x", iv_curWindowSize);
+ TRACDCOMP(g_trac_pnor, " curWindowLpcOffset = %08x", iv_curWindowLpcOffset);
+
+ }
+ while (true);
+
+ return l_err;
+}
+
+errlHndl_t PnorDD::writeDirty(uint32_t i_addr, size_t i_size)
+{
+ errlHndl_t l_err = NULL;
+
+ /* To pass a correct "size" for both protocol versions, we
+ * calculate the block-aligned start and end.
+ */
+ uint32_t l_blockMask = (1u << iv_blockShift) - 1;
+ uint32_t l_start = i_addr & ~l_blockMask;
+ uint32_t l_end = ((i_addr + i_size) + l_blockMask) & ~l_blockMask;
+
+ HiomapMessage* dirtyMsg = new HiomapMessage(HIOMAP_C_MARK_DIRTY);
+
+ dirtyMsg->put16(0, (i_addr - iv_curWindowOffset) >> iv_blockShift);
+ dirtyMsg->put16(2, (l_end - l_start) >> iv_blockShift);
+
+ size_t l_len = 4;
+ l_err = sendCommand(dirtyMsg, l_len);
+
+ delete dirtyMsg;
+
+ return l_err;
+}
+
+errlHndl_t PnorDD::writeFlush(void)
+{
+ errlHndl_t l_err = NULL;
+ HiomapMessage* flushMsg = new HiomapMessage(HIOMAP_C_FLUSH);
+
+ size_t l_len = 0;
+ l_err = sendCommand(flushMsg, l_len);
+
+ delete flushMsg;
+
+ return l_err;
+}
+
+/**
+ * @brief Write data to PNOR using Mbox LPC windows
+ */
+errlHndl_t PnorDD::_writeFlash( uint32_t i_addr,
+ size_t i_size,
+ const void* i_data )
+{
+ TRACFCOMP(g_trac_pnor, ENTER_MRK"PnorDD::_writeFlash(i_addr=0x%.8X)> ", i_addr);
+ errlHndl_t l_err = NULL, l_flushErr = NULL;
+
+ while (i_size)
+ {
+ uint32_t l_lpcAddr;
+ size_t l_chunkLen;
+
+ l_err = adjustWindow(true, i_addr, i_size, l_lpcAddr, l_chunkLen);
+
+ if (l_err)
+ {
+ break;
+ }
+
+ l_err = writeLpcFw(l_lpcAddr, l_chunkLen, i_data);
+
+ if (l_err)
+ {
+ break;
+ }
+
+ l_err = writeDirty(i_addr, l_chunkLen);
+
+ if (l_err)
+ {
+ break;
+ }
+
+ i_addr += l_chunkLen;
+ i_size -= l_chunkLen;
+ i_data = (char*)i_data + l_chunkLen;
+ }
+
+ /* We flush whether we had an error or not.
+ *
+ * NOTE: It would help the daemon a lot if we moved that out of here
+ * and instead had a single flush call over a series of writes.
+ *
+ * @todo (RTC:173513)
+ * Investigate erasing & re-writing the same pages at least 3 times
+ * in a row during a boot.
+ */
+ l_flushErr = writeFlush();
+
+ if ( l_err == NULL )
+ {
+ l_err = l_flushErr;
+ }
+ else
+ {
+ delete l_flushErr;
+ l_flushErr = NULL;
+ }
+
+ if( l_err )
+ {
+ l_err->collectTrace(PNOR_COMP_NAME);
+ }
+
+ return l_err;
+}
+
+/**
+ * @brief Read data from PNOR using Mbox LPC windows
+ */
+errlHndl_t PnorDD::_readFlash( uint32_t i_addr,
+ size_t i_size,
+ void* o_data )
+{
+ TRACDCOMP(g_trac_pnor, "PnorDD::_readFlash(i_addr=0x%.8X)> ", i_addr);
+ errlHndl_t l_err = NULL;
+
+ while (i_size)
+ {
+ uint32_t l_lpcAddr;
+ size_t l_chunkLen;
+
+ l_err = adjustWindow(false, i_addr, i_size, l_lpcAddr, l_chunkLen);
+ if (l_err)
+ {
+ break;
+ }
+
+ l_err = readLpcFw(l_lpcAddr, l_chunkLen, o_data);
+
+ if (l_err)
+ {
+ break;
+ }
+
+ i_addr += l_chunkLen;
+ i_size -= l_chunkLen;
+ o_data = (char*)o_data + l_chunkLen;
+ }
+
+ if( l_err )
+ {
+ l_err->collectTrace(PNOR_COMP_NAME);
+ }
+
+ return l_err;
+}
+
+/**
+ * @brief Retrieve size of NOR flash
+ */
+uint32_t PnorDD::getNorSize( void )
+{
+ return iv_flashSize;
+}
+
+/**
+ * @brief Retrieve bitstring of NOR workarounds
+ */
+uint32_t PnorDD::getNorWorkarounds( void )
+{
+ return 0;
+}
+
+errlHndl_t PnorDD::sendCommand(HiomapMessage*& io_msg, size_t& io_len)
+{
+ IPMI::completion_code l_cc = IPMI::CC_UNKBAD;
+ errlHndl_t l_err = NULL;
+
+ io_msg->iv_seq = iv_sequence++;
+
+ uint8_t old_cmd = io_msg->iv_cmd;
+ uint8_t old_seq = io_msg->iv_seq;
+ uint8_t* l_data = reinterpret_cast <uint8_t*>((char*)io_msg);
+ size_t l_len = io_len + 2; /* Account for command and sequence number */
+
+ do {
+ l_err = IPMI::sendrecv(
+ IPMI::pnor_hiomap_request(), l_cc, l_len, l_data);
+ if (l_err)
+ {
+ break;
+ }
+
+ if (l_cc != IPMI::CC_OK)
+ {
+ TRACFCOMP( g_trac_pnor, "HIOMAP command failed with err %d", l_cc);
+
+ /*@
+ * @errortype
+ * @moduleid PNOR::MOD_IPMIPNORDD_SEND_MESSAGE
+ * @reasoncode PNOR::RC_HIOMAP_ERROR_STATUS
+ * @userdata1[48:55] mbox status 1 reg
+ * @userdata1[56:63] reserved
+ * @userdata2[32:39] original command code
+ * @userdata2[40:47] reserved
+ * @userdata2[48:55] sequence number
+ * @userdata2[56:63] status code
+ * @devdesc astMbox::doMessage> Timeout waiting for
+ * message response
+ * @custdesc BMC not responding while accessing the flash
+ */
+ l_err = new ERRORLOG::ErrlEntry(ERRORLOG::ERRL_SEV_UNRECOVERABLE,
+ PNOR::MOD_IPMIPNORDD_SEND_MESSAGE,
+ PNOR::RC_HIOMAP_ERROR_STATUS,
+ TWO_UINT8_TO_UINT16(iv_bmcStatus, 0),
+ FOUR_UINT8_TO_UINT32(old_cmd,
+ 0,
+ old_seq,
+ l_cc));
+
+ // Limited in callout: no PNOR target, so calling out
+ // Service Processor
+ l_err->addProcedureCallout(HWAS::EPUB_PRC_SP_CODE,
+ HWAS::SRCI_PRIORITY_HIGH);
+
+ l_err->collectTrace(PNOR_COMP_NAME);
+
+ /* There is no message body */
+ *io_msg = NULL;
+
+ break;
+ }
+
+ /* Don't look too closely, storage size doesn't necessarily match */
+ assert(l_len >= 2);
+ io_msg = reinterpret_cast<HiomapMessage *>((char *)l_data);
+
+ if (old_seq != io_msg->iv_seq)
+ {
+ TRACFCOMP( g_trac_pnor, "bad sequence number in HIOMAP message, got %d want %d",
+ io_msg->iv_seq, old_seq);
+
+ /*@
+ * @errortype
+ * @moduleid PNOR::MOD_IPMIPNORDD_SEND_MESSAGE
+ * @reasoncode PNOR::RC_HIOMAP_BAD_SEQUENCE
+ * @userdata1[48:55] mbox status 1 reg
+ * @userdata1[56:63] reserved
+ * @userdata2[32:39] original command code
+ * @userdata2[40:47] reserved
+ * @userdata2[48:55] sequence wanted
+ * @userdata2[56:63] sequence obtained
+ * @devdesc astMbox::doMessage> Timeout waiting for
+ * message response
+ * @custdesc BMC not responding while accessing the flash
+ */
+ l_err = new ERRORLOG::ErrlEntry(ERRORLOG::ERRL_SEV_UNRECOVERABLE,
+ PNOR::MOD_IPMIPNORDD_SEND_MESSAGE,
+ PNOR::RC_HIOMAP_BAD_SEQUENCE,
+ TWO_UINT8_TO_UINT16(iv_bmcStatus, 0),
+ FOUR_UINT8_TO_UINT32(old_cmd,
+ io_msg->iv_cmd,
+ old_seq,
+ io_msg->iv_seq));
+
+ // Limited in callout: no PNOR target, so calling out
+ // Service Processor
+ l_err->addProcedureCallout(HWAS::EPUB_PRC_SP_CODE,
+ HWAS::SRCI_PRIORITY_HIGH);
+
+ l_err->collectTrace(PNOR_COMP_NAME);
+
+ /*
+ * We're returning an errl, so provide consistency by cleaning up
+ * the response message
+ */
+ delete io_msg;
+ io_msg = NULL;
+
+ // Tell code below that we generated the error (not an LPC error)
+ break;
+ }
+
+ /* Output just the sum of the length of the arguments */
+ io_len = l_len - 2;
+ } while(0);
+
+ /* Shut it down on error for the moment */
+ if (l_err) {
+ l_err->setSev(ERRORLOG::ERRL_SEV_UNRECOVERABLE);
+ ERRORLOG::errlCommit(l_err, PNOR_COMP_ID);
+ INITSERVICE::doShutdown( PNOR::RC_PNOR_INIT_FAILURE );
+ }
+
+ return l_err;
+}
+
+errlHndl_t PnorDD::getInfo( void )
+{
+ errlHndl_t l_err = NULL;
+
+ HiomapMessage* l_msg = new HiomapMessage(HIOMAP_C_GET_INFO);
+ l_msg->put8(0, HIOMAP_V_2); /* Protocol version */
+
+ do {
+ size_t l_len = 1;
+ l_err = sendCommand(l_msg, l_len);
+
+ if (l_err)
+ {
+ break;
+ }
+
+ assert(l_len > 1);
+ iv_protocolVersion = l_msg->get8(0);
+
+ assert(iv_protocolVersion > 1); /* Version check */
+ assert(l_len >= 1 + 1 + 2 );
+
+ iv_blockShift = l_msg->get8(1);
+ } while(0);
+
+ delete l_msg;
+
+ return l_err;
+}
+
+errlHndl_t PnorDD::getFlashInfo( void )
+{
+ errlHndl_t l_err = NULL;
+
+ HiomapMessage* l_flashMsg = new HiomapMessage(HIOMAP_C_GET_FLASH_INFO);
+
+ do {
+ size_t l_len = 0;
+ l_err = sendCommand(l_flashMsg, l_len);
+ if (l_err)
+ {
+ break;
+ }
+ assert(l_len == 4);
+
+ iv_flashSize = l_flashMsg->get16(0) << iv_blockShift;
+ iv_flashEraseSize = l_flashMsg->get16(2) << iv_blockShift;
+ } while (0);
+
+ delete l_flashMsg;
+
+ return l_err;
+}
+
+errlHndl_t PnorDD::initialiseHiomap( void )
+{
+ errlHndl_t l_err = NULL;
+
+ l_err = getInfo();
+ if (l_err)
+ {
+ return l_err;
+ }
+
+ l_err = getFlashInfo();
+ if (l_err)
+ {
+ return l_err;
+ }
+
+ return NULL;
+}
+
+void *hiomap_event_task(void *context)
+{
+ TRACFCOMP(g_trac_pnor, ENTER_MRK "%s", __func__);
+ uint8_t *bmcStatus = static_cast<uint8_t *>(context);
+
+ task_detach();
+
+ msg_q_t msgQ = msg_q_create();
+
+ IPMI::register_for_event(IPMI::hiomap_event(), msgQ);
+
+ while (true) {
+ msg_t* msg = msg_wait(msgQ);
+
+ IPMI::oemSEL* event = reinterpret_cast<IPMI::oemSEL*>(msg->extra_data);
+ *bmcStatus = event->iv_cmd[1];
+ lwsync();
+ TRACFCOMP(g_trac_pnor, "Received HIOMAP event: status is 0x%x",
+ *bmcStatus);
+
+ /* TODO: Improve handling of events */
+ }
+
+ TRACFCOMP(g_trac_pnor, EXIT_MRK "%s", __func__);
+ return NULL;
+}
+
+/**
+ * @brief Constructor
+ */
+PnorDD::PnorDD( TARGETING::Target* i_target )
+{
+ TRACFCOMP(g_trac_pnor, ENTER_MRK "%s: PnorDD::PnorDD()", __FILE__ );
+ printk("Using HIOMAP PNOR with IPMI transport\n");
+
+ errlHndl_t l_err = NULL;
+
+ task_create(&hiomap_event_task, &iv_bmcStatus);
+
+ // Use i_target if all of these apply
+ // 1) not NULL
+ // 2) not MASTER_PROCESSOR_CHIP_TARGET_SENTINEL
+ // 3) i_target does not correspond to Master processor (ie the
+ // same processor as MASTER_PROCESSOR_CHIP_TARGET_SENTINEL)
+ // otherwise, use MASTER_PROCESSOR_CHIP_TARGET_SENTINEL
+ // NOTE: i_target can only be used when targeting is loaded
+ if ( ( i_target != NULL ) &&
+ ( i_target != TARGETING::MASTER_PROCESSOR_CHIP_TARGET_SENTINEL ) )
+ {
+
+ iv_target = i_target;
+
+ // Check if processor is MASTER
+ TARGETING::ATTR_PROC_MASTER_TYPE_type type_enum =
+ iv_target->getAttr<TARGETING::ATTR_PROC_MASTER_TYPE>();
+
+ // Master target could collide and cause deadlocks with PnorDD singleton
+ // used for ddRead/ddWrite with MASTER_PROCESSOR_CHIP_TARGET_SENTINEL
+ assert( type_enum != TARGETING::PROC_MASTER_TYPE_ACTING_MASTER );
+
+ // Initialize and use class-specific mutex
+ iv_mutex_ptr = &iv_mutex;
+ mutex_init(iv_mutex_ptr);
+ TRACFCOMP(g_trac_pnor, "PnorDD::PnorDD()> Using i_target=0x%X (non-master) and iv_mutex_ptr",
+ TARGETING::get_huid(i_target));
+ }
+ else
+ {
+ iv_target = TARGETING::MASTER_PROCESSOR_CHIP_TARGET_SENTINEL;
+ iv_mutex_ptr = &(cv_mutex);
+ }
+
+ l_err = initialiseHiomap();
+ if( l_err )
+ {
+ TRACFCOMP( g_trac_pnor, "Failure to initialize the PNOR logic, shutting down :: RC=%.4X", ERRL_GETRC_SAFE(l_err) );
+ l_err->collectTrace(PNOR_COMP_NAME);
+ ERRORLOG::errlCommit(l_err, PNOR_COMP_ID);
+ INITSERVICE::doShutdown( PNOR::RC_PNOR_INIT_FAILURE );
+ }
+
+ iv_curWindowOpen = false;
+
+ TRACFCOMP(g_trac_pnor, EXIT_MRK "%s: PnorDD::PnorDD()", __FILE__ );
+}
+
+/**
+ * @brief Destructor
+ */
+PnorDD::~PnorDD()
+{
+}
diff --git a/src/usr/pnor/pnor_ipmidd.H b/src/usr/pnor/pnor_ipmidd.H
new file mode 100644
index 000000000..4e267a7c2
--- /dev/null
+++ b/src/usr/pnor/pnor_ipmidd.H
@@ -0,0 +1,347 @@
+/* IBM_PROLOG_BEGIN_TAG */
+/* This is an automatically generated prolog. */
+/* */
+/* $Source: src/usr/pnor/pnor_ipmidd.H $ */
+/* */
+/* OpenPOWER HostBoot Project */
+/* */
+/* Contributors Listed Below - COPYRIGHT 2018 */
+/* [+] 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 __PNOR_IPMIDD_H
+#define __PNOR_IPMIDD_H
+
+/** @file pnor_ipmidd.H
+ * @brief Provides the interfaces to the PNOR via the
+ * HIOMAP protocol
+ */
+
+#include <limits.h>
+#include <config.h>
+namespace PNOR
+{
+class UdPnorDDParms;
+}
+
+//NOTE: Protocol Definition is here:
+// https://github.com/openbmc/mboxbridge/blob/master/Documentation/protocol.md
+
+enum {
+ HIOMAP_MAX_ARGS_SIZE = 11,
+};
+
+/**
+ * @brief Host IO Mapping message class.
+ * Encapsulates a HIOMAP protocol message and provides accessors to
+ * read/write 8, 16 and 32-bit quantities in the right endianness at
+ * specified offsets of the "args" section.
+ */
+class HiomapMessage
+{
+ public:
+
+ HiomapMessage( uint8_t i_cmd )
+ {
+ iv_cmd = i_cmd;
+ }
+
+ uint8_t iv_cmd;
+ uint8_t iv_seq;
+ uint8_t iv_args[HIOMAP_MAX_ARGS_SIZE];
+
+ inline uint8_t get8( uint8_t i_index )
+ {
+ assert( i_index < HIOMAP_MAX_ARGS_SIZE);
+ return iv_args[i_index];
+ }
+
+ inline void put8( uint8_t i_index, uint8_t i_value )
+ {
+ assert( i_index < HIOMAP_MAX_ARGS_SIZE);
+ iv_args[i_index] = i_value;
+ }
+
+ inline uint16_t get16( uint8_t i_index )
+ {
+ assert( i_index < (HIOMAP_MAX_ARGS_SIZE - 1));
+ return iv_args[i_index] | (iv_args[i_index + 1] << 8);
+ }
+
+ inline void put16( uint8_t i_index, uint16_t i_value )
+ {
+ assert( i_index < (HIOMAP_MAX_ARGS_SIZE - 1));
+ iv_args[i_index] = i_value & 0xff;
+ iv_args[i_index + 1] = i_value >> 8;
+ }
+
+ inline uint32_t get32( uint8_t i_index )
+ {
+ assert( i_index < (HIOMAP_MAX_ARGS_SIZE - 3));
+ return iv_args[i_index] |
+ (iv_args[i_index + 1] << 8) |
+ (iv_args[i_index + 2] << 16) |
+ (iv_args[i_index + 3] << 24);
+ }
+
+ inline void put32( uint8_t i_index, uint32_t i_value )
+ {
+ assert( i_index < (HIOMAP_MAX_ARGS_SIZE - 3));
+ iv_args[i_index] = i_value & 0xff;
+ iv_args[i_index + 1] = (i_value >> 8) & 0xff;
+ iv_args[i_index + 2] = (i_value >> 16) & 0xff;
+ iv_args[i_index + 3 ] = i_value >> 24;
+ }
+};
+
+/**
+ * @brief PNOR Device Driver Class
+ * Provides access to the PNOR flash via the LPC MBOX hardware
+ */
+class PnorDD
+{
+
+ public:
+ /**
+ * @brief Performs a PNOR Read Operation
+ *
+ * @parm o_buffer Buffer to read data into
+ * @parm io_buflen Input: Number of bytes to read,
+ * Output: Number of bytes actually read
+ * @parm i_address Offset into flash to read
+ *
+ * @return Error from operation
+ */
+ errlHndl_t readFlash(void* o_buffer,
+ size_t& io_buflen,
+ uint64_t i_address);
+
+ /**
+ * @brief Performs a PNOR Write Operation
+ *
+ * @parm i_buffer Buffer to write data from
+ * @parm io_buflen Input: Number of bytes to write,
+ * Output: Number of bytes actually written
+ * @parm i_address Offset into flash to write
+ *
+ * @return Error from operation
+ */
+ errlHndl_t writeFlash(const void* i_buffer,
+ size_t& io_buflen,
+ uint64_t i_address);
+
+ /**
+ * @brief Informs caller if PNORDD is using
+ * L3 Cache for fake PNOR or not.
+ *
+ * @return Indicate state of fake PNOR
+ * true = PNOR DD is using L3 Cache for fake PNOR
+ * false = PNOR DD not using L3 Cache for fake PNOR
+ */
+ bool usingL3Cache( );
+
+ /**
+ * @brief Retrieve size of NOR flash
+ * @return Size of PNOR in bytes
+ */
+ uint32_t getNorSize( void );
+
+ /**
+ * @brief Retrieve bitstring of NOR workarounds
+ * @return NOR workarounds (see VendorWorkarounds in norflash.H)
+ */
+ uint32_t getNorWorkarounds( void );
+
+ /**
+ * @brief Constructor
+ *
+ * @parm i_target Processor Target connected to PNOR
+ * NOTE: i_target can only be used after targeting is loaded
+ */
+ PnorDD( TARGETING::Target* i_target = NULL );
+
+ /**
+ * @brief Destructor
+ */
+ ~PnorDD();
+
+ protected:
+
+ /**
+ * @brief Write data to PNOR using Mbox LPC windows
+ * @pre Mutex should already be locked before calling
+ *
+ * @parm[in] i_addr PNOR flash Address to write
+ * @parm[in] i_size Amount of data to write, in bytes.
+ * @parm[in] i_data Buffer containing data to write
+ *
+ * @return Error from operation
+ */
+ errlHndl_t _writeFlash( uint32_t i_addr,
+ size_t i_size,
+ const void* i_data );
+
+ /**
+ * @brief Read data from PNOR using Mbox LPC windows
+ * @pre Mutex should already be locked before calling
+ *
+ * @parm[in] i_addr PNOR flash Address to read
+ * @parm[in] i_size Amount of data to read, in bytes.
+ * @parm[out] o_data Buffer to read data into
+ *
+ * @return Error from operation
+ */
+ errlHndl_t _readFlash( uint32_t i_addr,
+ size_t i_size,
+ void* o_data );
+
+ /**
+ * @brief Open a window if necessary and return adjusted
+ * LPC address and chunk size
+ * @parm[in] i_isWrite Write or read window
+ * @parm[in] i_reqAddr Requested flash offset
+ * @parm[in] i_reqSize Requested size
+ * @parm[out] o_lpcAddr LPC offset for the requested offset
+ * @parm[out] o_chunkLen i_reqSize adjusted to fit in the window
+ *
+ * @return Error from operation
+ */
+ errlHndl_t adjustWindow(bool i_isWrite,
+ uint32_t i_reqAddr,
+ size_t i_reqSize,
+ uint32_t& o_lpcAddr,
+ size_t& o_chunkLen);
+
+ /**
+ * @brief Mark a range dirty in a write window
+ * @parm[in] i_addr Flash offset of the range
+ * @parm[in] i_size Size of the range
+ *
+ * @return Error from operation
+ */
+ errlHndl_t writeDirty(uint32_t i_addr, size_t i_size);
+
+ /**
+ * @brief Flush all pending dirty data to the flash
+ *
+ * @return Error from operation
+ */
+ errlHndl_t writeFlush(void);
+
+ /**
+ * @brief Read from LPC FW space
+ *
+ * @parm[in] i_offset LPC offset
+ * @parm[in] i_size Size to read
+ * @parm[out] o_buf Output buffer
+ *
+ * @return Error from operation
+ */
+
+ errlHndl_t readLpcFw(uint32_t i_offset, size_t i_size, void* o_buf);
+ /**
+ * @brief Write to LPC FW space
+ *
+ * @parm[in] i_offset LPC offset
+ * @parm[in] i_size Size to read
+ * @parm[in] i_buf Input buffer
+ *
+ * @return Error from operation
+ */
+ errlHndl_t writeLpcFw(uint32_t i_offset,
+ size_t i_size,
+ const void* i_buf);
+ private: // Methods
+ /**
+ * @brief Send a HIOMAP command using IPMI
+ */
+ errlHndl_t sendCommand(HiomapMessage*& io_msg, size_t& io_len);
+
+ /**
+ * @brief Perform the HIOMAP protocol handshake and fetch flash params
+ */
+ errlHndl_t initialiseHiomap(void);
+
+ /**
+ * @brief Perform the HIOMAP protocol handshake, negotiating version
+ */
+ errlHndl_t getInfo(void);
+
+ /**
+ * @brief Fetch the parameters of the flash exposed by HIOMAP
+ */
+ errlHndl_t getFlashInfo(void);
+
+
+ private: // Variables
+ // Protocol metadata
+ uint8_t iv_sequence;
+ uint8_t iv_bmcStatus;
+ bool iv_initialised;
+ uint32_t iv_protocolVersion;
+ //Block size is either 4k (V1) or BMC defined (V2)
+ // the iv_blockShift parm is a representation of that size
+ // as a power of 2. Most command and response args are specified
+ // in some multiple of block size
+ uint32_t iv_blockShift;
+ uint32_t iv_flashSize;
+ uint32_t iv_flashEraseSize;
+
+ // Current window
+ bool iv_curWindowOpen; // Currently open
+ bool iv_curWindowWrite; // Write vs Read window
+ uint32_t iv_curWindowOffset; // Offset into flash
+ uint32_t iv_curWindowSize; // Size
+ uint32_t iv_curWindowLpcOffset; // Offset into LPC FW space
+
+ // Legacy v1 protocol
+ uint32_t iv_readWindowSize;
+ uint32_t iv_writeWindowSize;
+
+ /**
+ * @brief Global Mutex to prevent concurrent PNOR accesses to Master
+ * Proc. This needs to be static so we can mutex across multiple
+ * instances of PnorDD
+ */
+ static mutex_t cv_mutex;
+
+ /**
+ * @brief Class Mutex used to prevent concurrent PNOR accesses
+ */
+ mutex_t iv_mutex;
+
+ /**
+ * @brief Mutex pointer to either class-specific or global mutex to
+ * prevent concurrent PNOR accesses.
+ * Each class uses a mutex; some share the static cv_mutex
+ */
+ mutex_t* iv_mutex_ptr;
+
+ /**
+ * @brief Processor Target used to access PNOR device
+ *
+ */
+ TARGETING::Target* iv_target;
+
+ // Needed for testcases
+ friend class PnorDdTest;
+
+ // let the UserDetails classes see internal structures
+ friend class PNOR::UdPnorDDParms;
+};
+
+#endif /* __PNOR_IPMIDD_H */
+
diff --git a/src/usr/pnor/pnor_mboxdd.H b/src/usr/pnor/pnor_mboxdd.H
index e92b25f47..7a3be0a9d 100644
--- a/src/usr/pnor/pnor_mboxdd.H
+++ b/src/usr/pnor/pnor_mboxdd.H
@@ -5,7 +5,7 @@
/* */
/* OpenPOWER HostBoot Project */
/* */
-/* Contributors Listed Below - COPYRIGHT 2011,2017 */
+/* Contributors Listed Below - COPYRIGHT 2011,2018 */
/* [+] International Business Machines Corp. */
/* */
/* */
@@ -33,7 +33,7 @@ class UdPnorDDParms;
}
//NOTE: Protocol Definition is here:
-// https://github.com/openbmc/mboxbridge/blob/master/Documentation/mbox_protocol.md
+// https://github.com/openbmc/mboxbridge/blob/master/Documentation/protocol.md
class astMbox;
diff --git a/src/usr/pnor/pnorvalid.C b/src/usr/pnor/pnorvalid.C
index a49dd63ea..6ace7c33d 100644
--- a/src/usr/pnor/pnorvalid.C
+++ b/src/usr/pnor/pnorvalid.C
@@ -5,7 +5,7 @@
/* */
/* OpenPOWER HostBoot Project */
/* */
-/* Contributors Listed Below - COPYRIGHT 2014,2017 */
+/* Contributors Listed Below - COPYRIGHT 2014,2018 */
/* [+] Google Inc. */
/* [+] International Business Machines Corp. */
/* */
@@ -49,11 +49,14 @@
#include <lpc/lpcif.H>
#ifdef CONFIG_PNORDD_IS_SFC
#include "pnordd.H"
-#else
+#elif CONFIG_PNORDD_IS_BMCMBOX
#include "pnor_mboxdd.H"
+#elif CONFIG_PNORDD_IS_IPMI
+#include "pnor_ipmidd.H"
+#else
+#error "No PNOR DD implementation configured"
#endif
-
// Used for creating an Invalid TOC ("PNOR")
#define PNORVALID_FAKE_MAGIC 0x504E4F52
diff --git a/src/usr/pnor/test/pnorddtest.H b/src/usr/pnor/test/pnorddtest.H
index eb444e53d..ff691b345 100644
--- a/src/usr/pnor/test/pnorddtest.H
+++ b/src/usr/pnor/test/pnorddtest.H
@@ -5,7 +5,7 @@
/* */
/* OpenPOWER HostBoot Project */
/* */
-/* Contributors Listed Below - COPYRIGHT 2011,2017 */
+/* Contributors Listed Below - COPYRIGHT 2011,2018 */
/* [+] Google Inc. */
/* [+] International Business Machines Corp. */
/* */
@@ -41,9 +41,13 @@
#include <kernel/console.H>
#include <sys/time.h>
#ifdef CONFIG_PNORDD_IS_SFC
-#include "../pnordd.H"
+#include "pnordd.H"
+#elif CONFIG_PNORDD_IS_BMCMBOX
+#include "pnor_mboxdd.H"
+#elif CONFIG_PNORDD_IS_IPMI
+#include "pnor_ipmidd.H"
#else
-#include "../pnor_mboxdd.H"
+#error "No PNOR DD implementation configured"
#endif
#include "../pnorrp.H"
#include <list>
OpenPOWER on IntegriCloud