summaryrefslogtreecommitdiffstats
path: root/src/usr/isteps/nvdimm/bpm_update.H
diff options
context:
space:
mode:
Diffstat (limited to 'src/usr/isteps/nvdimm/bpm_update.H')
-rw-r--r--src/usr/isteps/nvdimm/bpm_update.H175
1 files changed, 168 insertions, 7 deletions
diff --git a/src/usr/isteps/nvdimm/bpm_update.H b/src/usr/isteps/nvdimm/bpm_update.H
index 17517f85d..146ddfcb1 100644
--- a/src/usr/isteps/nvdimm/bpm_update.H
+++ b/src/usr/isteps/nvdimm/bpm_update.H
@@ -40,33 +40,125 @@ namespace NVDIMM
namespace BPM
{
-// All of the various commands used for the BPM update
-// BSL: Bootstrap Loader commands
-// BPM: Backup Power Module
+/*
+ * All of the various commands used for the BPM update. All commands can only be
+ * sent after write protection on the BPM has been disabled and the update magic
+ * values have been written to the BPM's magic registers.
+ *
+ * BSL: Bootstrap Loader commands
+ * BPM: Backup Power Module
+*/
enum COMMAND : uint8_t
{
+ // A payload sent with this command will be interpreted and processed by the
+ // NVDIMM module.
+ BPM_LOCAL = 0xFF,
+
+ /*
+ * These are LOCAL commands. These commands MUST be sent only outside of BSL
+ * BSL mode and must be paired with the BSP command BPM_LOCAL. Otherwise,
+ * unpredicatable errors will occur.
+ *
+ * When using issueCommand() for these commands they should always be sent
+ * with a 0 ms delay. This will ensure that the response packet is not
+ * checked from the BPM. Since these are processed by the NVDIMM it makes
+ * no sense to get a response from the BPM and attempting to do so will
+ * cause errors.
+ */
BCL_ENTER_BSL_MODE = 0x01,
BCL_IS_BSL_MODE = 0x02,
BCL_WRITE_REG = 0x03,
BCL_START_UPDATE = 0x04,
BCL_END_UPDATE = 0x05,
BCL_IS_UPDATE_IN_PROGRESS = 0x06,
+
+ // A payload sent with this command will be sent transparently to the BPM.
+ // This command must only be used while the BPM is in BSL mode.
+ BPM_PASSTHROUGH = 0xFE,
+
+ /*
+ * These are PASSTHROUGH commands. These commands MUST be sent only while in
+ * BSL mode and must be paired with BSP command BPM_PASSTHROUGH. Otherwise,
+ * unpredicatable errors will occur.
+ */
+ // Writes a block of data to the BPM.
+ // Delay 1ms (default)
BSL_RX_DATA_BLOCK = 0x10,
+ // Unlocks the BPM that is in BSL mode so that updates can occur.
+ // Delay 1ms (default)
BSL_RX_PASSWORD = 0x11,
+ // Erases 128 bytes at the given address offset.
+ // WARNING: Due to BSL memory limitations, BSL cannot verify the address
+ // is a valid config segment address offset and will blindly
+ // erase 128 bytes of data starting at that offset. If an invalid
+ // address is sent then the BPM will be bricked in a very
+ // unpredicatable/unrecoverable way.
+ // Delay 250ms
BSL_ERASE_SEGMENT = 0x12,
+ // Unknown, unused.
+ // Delay 0ms
BSL_TOGGLE_INFO = 0x13,
+ // Unknown, unused.
+ // Delay 1ms (default)
BSL_ERASE_BLOCK = 0x14,
+ // Erases the full firmware section on the BPM. The start of the firmware
+ // address must be supplied with this command.
+ // WARNING: Due to BSL memory limitations, BSL cannot verify the address
+ // is a valid firmware address offset and will blindly erase 128
+ // data starting at that offset. If an invalid address is sent
+ // then the BPM will be bricked in a very
+ // unpredicatable/unrecoverable way.
+ // Delay 250ms
BSL_MASS_ERASE = 0x15,
+ // Sends the command to the BPM to perform the final CRC check on the
+ // firmware written to the BPM. If the CRC check doesn't match the expected
+ // CRC in the flash image then the firmware will not load on the BPM and it
+ // will remain in BSL mode until new firmware is loaded onto it.
+ //
+ // Delay 0
+ // The response packet must be checked externally from the issueCommand()
+ // function because the response packet returned from this command is unique
+ // to this command and will return the results of this command. For more
+ // info see the checkFirmwareCrc() function description, implementation, and
+ // the COMMAND_BSL_CRC_CHECK_RESPONSE_CODES enum.
BSL_CRC_CHECK = 0x16,
+ // Unknown, unused.
+ // Delay 1ms (default)
BSL_LOAD_PC = 0x17,
+ // Unknown, unused.
+ // Delay 1ms (default)
BSL_TX_DATA_BLOCK = 0x18,
+ // Checks the Bootstrap Loader mode version on the BPM. Depending on this
+ // version, some parts of the update procedure may have changed.
+ //
+ // Delay 0ms
+ // The response packet must be checked externally from the issueCommand()
+ // function because the response packet returned from this command is unique
+ // to this command and will return the results of this command. For more
+ // info see the readBslVersion() function description and implementation.
BSL_TX_BSL_VERSION = 0x19,
+ // Unknown, unused.
+ // Delay 1ms (default)
BSL_TX_BUFFER_SIZE = 0x1A,
+ // Unknown, unused.
+ // Delay 1ms (default)
BSL_RX_DATA_BLOCK_FAST = 0x1B,
+ // Resets the BPM and exits BSL mode.
+ // Delay 0ms
+ // Never check for a response packet from the BPM after sending the reset
+ // command because the BPM may not be back up and if it is it will not be
+ // in BSL mode anymore. If the response packet is checked then errors will
+ // occur.
BSL_RESET_DEVICE = 0x1C,
+ // Verifies the block of data written to the BPM flash is identical to what
+ // was sent to it in a prior write. For more information see the
+ // verifyBlockWrite() description and implementation.
+ //
+ // Delay 0ms
+ // The response packet must be checked externally from the issueCommand()
+ // function because the response packet returned from this command is unique
+ // to this command and will return the results of this command.
BSL_VERIFY_BLOCK = 0x1D,
- BPM_PASSTHROUGH = 0xFE,
- BPM_LOCAL = 0xFF,
};
// These are the various response codes returned by the BPM after the
@@ -196,6 +288,16 @@ constexpr size_t ALL_SEGMENTS_SIZE = 512;
// Number of magic registers for the BPM
constexpr size_t NUM_MAGIC_REGISTERS = 2;
+// These are the production magic values for the BPM that should be written in
+// BPM_MAGIC_REG1 and BPM_MAGIC_REG2 respectively.
+const uint8_t PRODUCTION_MAGIC_VALUES[NUM_MAGIC_REGISTERS] = {0x55, 0xAA};
+// These magic values to enable nvdimm-bpm interface. They must be written to
+// the magic registers BEFORE writing flash updates to the BPM in BSL mode.
+const uint8_t UPDATE_MODE_MAGIC_VALUES[NUM_MAGIC_REGISTERS] = {0xB0, 0xDA};
+// These are the segment read magic values that allow dumping of the segment
+// data from the BPM.
+const uint8_t SEGMENT_READ_MAGIC_VALUES[NUM_MAGIC_REGISTERS] = {0xBA, 0xAB};
+
typedef std::vector<uint8_t> payload_t;
@@ -409,6 +511,14 @@ public:
bool attemptAnotherUpdate();
/**
+ * @brief Returns if an update has been attempted on this BPM.
+ *
+ * @return bool true if an update has been attempted before.
+ * Otherwise, false.
+ */
+ bool hasAttemptedUpdate();
+
+ /**
* @brief returns the nvdimm that is associated with this BPM.
*/
const TARGETING::TargetHandle_t getNvdimm();
@@ -476,12 +586,20 @@ private:
* @param[in] i_opType The operation type of the command. Must be one
* of the COMMAND_STATUS_REGISTER_OP_TYPES
*
+ * @param[in] i_msDelay How long to wait before the response from the
+ * BPM should be checked. Default 1 ms. If a delay
+ * of 0 ms is given then the response will not be
+ * read and it is the caller's responsibilty to
+ * check the response status. See COMMAND enum for
+ * required delays.
+ *
* @return errlHndl_t nullptr on success. Otherwise, pointer to an
* errlEntry.
*/
errlHndl_t issueCommand(uint8_t i_command,
payload_t i_payload,
- uint8_t i_opType);
+ uint8_t i_opType,
+ int i_msDelay = 1);
/**
* @brief This function issues a BSP command to the BPM by setting up a
@@ -499,12 +617,20 @@ private:
* @param[in] i_opType The operation type of the BSP command. Must
* be a COMMAND_STATUS_REGISTER_OP_TYPES
*
+ * @param[in] i_msDelay How long to wait before the response from the
+ * BPM should be checked. Default 1 ms. If a delay
+ * of 0 ms is given then the response will not be
+ * read and it is the caller's responsibilty to
+ * check the response status. See COMMAND enum for
+ * required delays.
+ *
* @return errlHndl_t nullptr on success. Otherwise, pointer to an
* errlEntry.
*/
errlHndl_t issueCommand(uint8_t i_bspCommand,
uint8_t i_command,
- uint8_t i_opType);
+ uint8_t i_opType,
+ int i_msDelay = 1);
/**
* @brief This function checks if the BPM has entered update mode
@@ -680,6 +806,19 @@ private:
uint8_t const (&i_magicValues)[NUM_MAGIC_REGISTERS]);
/**
+ * @brief Switches the page on the BPM to the given page. This function
+ * must be executed only after the segment read magic values have
+ * been written to the BPM's magic registers.
+ *
+ * @param[in] i_segmentCode The segment code that corresponds to the
+ * page to switch to on the BPM.
+ *
+ * @return errlHndl_t nullptr on success. Otherwise, an error
+ *
+ */
+ errlHndl_t switchBpmPage(uint16_t i_segmentCode);
+
+ /**
* @brief Dumps the given segment data from the BPM. CANNOT be in BSL mode.
*
* @param[in] i_segmentCode The segment code that corresponds to the
@@ -839,6 +978,28 @@ private:
errlHndl_t getResponse(uint8_t * o_responseData,
uint8_t i_responseSize);
+
+ /**
+ * @brief Helper function to handle two potential errors that might occur in a
+ * function that only returns a single error log. If the return error is
+ * not nullptr then the second error will be linked to it and committed
+ * if this is the final update attempt. Otherwise, it will be deleted
+ * since the update procedure will occur again and may be successful.
+ * If the return error is nullptr then the return error will point to
+ * the second's error and the second error will point to nullptr.
+ *
+ * @param[in/out] io_returnErrl A pointer to the error that would be
+ * returned by the function that called
+ * this one. If nullptr, then it will be
+ * set point to the secondary error and
+ * that error will become nullptr.
+ *
+ * @param[in/out] io_secondErrl The secondary error that occurred which
+ * in addition to the usual returned error.
+ */
+ void handleMultipleErrors(errlHndl_t& io_returnErrl,
+ errlHndl_t& io_secondErrl);
+
/**
* @brief Calculates the CRC16 bytes for the BSL payload. This CRC differs
* from the NVDIMM CRC calculation in that the initial value is
OpenPOWER on IntegriCloud