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.H377
1 files changed, 374 insertions, 3 deletions
diff --git a/src/usr/isteps/nvdimm/bpm_update.H b/src/usr/isteps/nvdimm/bpm_update.H
index a1ed79c05..f602968fe 100644
--- a/src/usr/isteps/nvdimm/bpm_update.H
+++ b/src/usr/isteps/nvdimm/bpm_update.H
@@ -69,6 +69,41 @@ enum COMMAND : uint8_t
BPM_LOCAL = 0xFF,
};
+// These are the various response codes returned by the BPM after the
+// BSL_CRC_CHECK command is sent at the end of the update procedure.
+enum COMMAND_BSL_CRC_CHECK_RESPONSE_CODES : uint16_t
+{
+ // The updated firmware is set up with all necessary loading parameters to
+ // load and execute upon reset.
+ SUCCESSFUL_OPERATION = 0x00,
+
+ // Error setting up the necessary loading parameters for the updated
+ // firmware image.
+ MEMORY_WRITE_CHECK_FAILED = 0x01,
+
+ // The command was attempted without unlocking the BSL with the password.
+ BSL_LOCKED = 0x04,
+
+ // Error setting up the necessary loading parameters for the updated
+ // firmware image.
+ WRITE_FORBIDDEN = 0x06,
+
+ // The checksum validation of the updated firmware image failed. The
+ // calculated checksum doesn't match the checksum data provided @FF7A in the
+ // firmware image file.
+ VERIFY_MISMATCH = 0x09,
+
+ // The firmware image start address given for the command is wrong.
+ PARAMETER_ERROR = 0x0A,
+
+ // Firmware image file used for the update doesn't hae the checksum data
+ // defined @FF7A
+ MAIN_FW_NOT_SUPPORT_CRC_CHECK = 0x0B,
+};
+
+// BSL versions that this code supports.
+const uint8_t BSL_VERSION_1_4 = 0x14;
+
// The operator types for the BPM_CMD_STATUS register
enum COMMAND_STATUS_REGISTER_OP_TYPES : uint8_t
{
@@ -98,6 +133,24 @@ struct firmware_image_block
typedef firmware_image_block firmware_image_block_t;
+// Used to overlay onto the LID image
+struct config_image_fragment
+{
+ // The fragment size is the size of iv_data.
+ uint8_t iv_fragmentSize;
+
+ // The offset where the first byte in iv_data should begin overwritting the
+ // BPM config data in the BPM configuration segment dump buffer.
+ uint16_t iv_offset;
+
+ // A variable sized array of config segment data.
+ char iv_data[0];
+
+} PACKED;
+
+typedef config_image_fragment config_image_fragment_t;
+
+
/* Max payload size is 26 bytes
* 4 bytes: header
* 1 byte: sync byte
@@ -125,6 +178,15 @@ extern const uint8_t PAYLOAD_HEADER_SIZE;
// automatically sends the sync byte ahead of the payload.
extern const uint8_t SYNC_BYTE;
+// Maximum size of any segment in the config data section
+constexpr size_t SEGMENT_SIZE = 128;
+
+// Maximum size of the config data section.
+constexpr size_t ALL_SEGMENTS_SIZE = 512;
+
+// Number of magic registers for the BPM
+constexpr size_t NUM_MAGIC_REGISTERS = 2;
+
typedef std::vector<uint8_t> payload_t;
@@ -223,8 +285,90 @@ private:
size_t iv_lidImageSize;
};
+
+class BpmConfigLidImage
+{
+public:
+
+ /**
+ * @brief Constructor that sets access to LID information
+ *
+ * @param[in] i_lidImageAddr virtual address where LID was loaded
+ * @param[in] i_size size of the loaded LID
+ */
+ BpmConfigLidImage(void * const i_lidImageAddr, size_t i_size);
+
+ /**
+ * @brief Returns the version of the config binary as a uint16_t. There isn't
+ * a way to check the version of the config data on the BPM but the
+ * config binary still has the version of the flash image it
+ * originally came from.
+ *
+ * @return uint16_t version of the firmware image as MMmm.
+ * MM = major version, mm = minor.
+ */
+ uint16_t getVersion() const;
+
+ /**
+ * @brief Returns the number of fragments in the LID image.
+ *
+ */
+ uint16_t getNumberOfFragments() const;
+
+ /**
+ * @brief Returns a pointer to the first fragment in LID image.
+ */
+ void const * getFirstFragment() const;
+
+ /* The binary will be organized in the following way:
+ * Byte 1: Major version number (MM)
+ * Byte 2: Minor version number (mm)
+ * Byte 3: N number of fragments in the file (NN)
+ * Byte 4-EOF: Fragments of the form:
+ * FRAGMENT_SIZE Byte 1: X number of bytes in fragment data
+ * section. (XX)
+ * INDEX_OFFSET Byte 2-3: Each BPM's config section is unique
+ * to itself. So, during the update
+ * the contents of a BPM's config data
+ * will be dumped into a buffer.
+ * These two bytes will be used as an
+ * offset into that buffer from which
+ * overwritting will take place.
+ * (IN DX)
+ * DATA_BYTES Byte 4-X: Fragment data bytes to be written
+ * at the INDEX_OFFSET in the dumped
+ * config data buffer. (DD)
+ *
+ * Example file output:
+ * 01 05 01 04 01 28 6a 14 31 80
+ * MM mm NN XX IN DX DD DD DD DD
+ */
+ typedef struct config_image_header
+ {
+ uint8_t iv_versionMajor;
+ uint8_t iv_versionMinor;
+ uint16_t iv_numberOfFragments;
+ } config_image_header_t;
+
+private:
+
+ // Pointer to the LID image allocated outside of the class
+ void * const iv_lidImage;
+
+ // The size of the LID image.
+ size_t iv_lidImageSize;
+};
+
class Bpm
{
+ /*
+ * The Bpm can either be in Bootstrap Loader (BSL) mode or not. Many of
+ * member functions utilize BSL mode for the update procedure and must
+ * therefore be in BSL mode to succeed. Other functions perform operations
+ * that will not work in BSL mode since that mode is strictly for updating
+ * the device and turns of some functionality while in that mode. The "mode"
+ * the BPM must be in is given in the function brief description.
+ */
public:
@@ -241,7 +385,24 @@ public:
* @return errlHndl_t nullptr on success. Otherwise, pointer to an
* errlEntry.
*/
- errlHndl_t runUpdate(BpmFirmwareLidImage i_image);
+ errlHndl_t runUpdate(BpmFirmwareLidImage i_fwImage,
+ BpmConfigLidImage i_configImage);
+
+ /**
+ * @brief At most, one full update retry should occur in some
+ * circumstances. If one of those occurances happens then the
+ * member iv_attemptAnotherUpdate will be set to true. Otherwise, it
+ * will remain false.
+ *
+ * @return bool true if another update should be attempted.
+ * Otherwise, false.
+ */
+ bool attemptAnotherUpdate();
+
+ /**
+ * @brief returns the nvdimm that is associated with this BPM.
+ */
+ const TARGETING::TargetHandle_t getNvdimm();
private:
@@ -250,6 +411,21 @@ private:
// The Bootstrap Loader version of the BPM
uint8_t iv_bslVersion;
+ uint16_t iv_firmwareStartAddress;
+
+ // Keeps track of if the update should be attempted again.
+ bool iv_attemptAnotherUpdate;
+
+ // Buffers for the segment data in case another update attempt is needed.
+ // If the first update fails there won't be any running firmware on the
+ // device which is required to dump the segment data.
+ uint8_t iv_segmentD[SEGMENT_SIZE];
+ uint8_t iv_segmentB[SEGMENT_SIZE];
+
+ // Keeps track if the segments have been merged with the flash image data
+ // yet.
+ bool iv_segmentDMerged;
+ bool iv_segmentBMerged;
/**
* @brief Gets the BSL version from the BPM and sets the iv_bslVersion
@@ -288,11 +464,11 @@ private:
uint8_t i_opType);
/**
- * @brief This function issues a BCL command to the BPM by setting up a
+ * @brief This function issues a BSP command to the BPM by setting up a
* payload containing only that command and then calling the
* issueCommand function that accepts a payload as an argument.
*
- * NOTE: Since the BCL command is not a BSL command, it doesn't need
+ * NOTE: Since the BSP command is not a BSL command, it doesn't need
* to be formatted as a BSL payload but it still must be written to
* the BPM_REG_PAYLOAD_START register.
*
@@ -345,6 +521,13 @@ private:
errlHndl_t updateFirmware(BpmFirmwareLidImage i_image);
/**
+ * @brief Executes the config portion of the BPM update.
+ *
+ * @return errlHndl_t nullptr on success. Otherwise, an Error.
+ */
+ errlHndl_t updateConfig();
+
+ /**
* @brief Commands the BPM to enter BSL mode to allow for BSL commands to be
* executed.
*
@@ -409,6 +592,129 @@ private:
errlHndl_t resetDevice();
/**
+ * @brief Write to the BPM register via the SCAP registers
+ *
+ * @param[in] i_reg The BPM register to write to.
+ *
+ * @param[in] i_data The data to write to the given register.
+ *
+ * @return errlHndl_t nullptr on success. Otherwise, an error.
+ */
+ errlHndl_t writeViaScapRegister(uint8_t i_reg, uint8_t i_data);
+
+ /**
+ * @brief Reads the BPM register via the SCAP registers
+ *
+ * @param[in] i_reg The BPM register to read from.
+ *
+ * @param[in/out] io_data The data that was in the given register.
+ *
+ * @return errlHndl_t nullptr on success. Otherwise, an error.
+ */
+ errlHndl_t readViaScapRegister(uint8_t i_reg, uint8_t & io_data);
+
+ /**
+ * @brief Disables write protection on the BPM by sending the password
+ * sequence to I2C_REG_PROTECT
+ *
+ * @return errlHndl_t nullptr on success. Otherwise, an error.
+ */
+ errlHndl_t disableWriteProtection();
+
+ /**
+ * @brief Many operations performed on the BPM require the magic registers
+ * to have specific values written in them. This function acts as a
+ * helper to facilitate that process.
+ *
+ * NOTE: Write protection on the BPM must be disabled, otherwise
+ * this function will fail.
+ *
+ * @param[in] i_magicValues The pair of magic values to be written to
+ * BPM_MAGIC_REG1 and BPM_MAGIC_REG2
+ * respectively.
+ *
+ * @return errlHndl_t nullptr on success. Otherwise, an error.
+ */
+ errlHndl_t writeToMagicRegisters(
+ uint8_t const (&i_magicValues)[NUM_MAGIC_REGISTERS]);
+
+ /**
+ * @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
+ * segment to dump from the BPM.
+ *
+ * @param[out] o_buffer A pointer to the buffer to fill with segment
+ * data. Must be SEGMENT_SIZE in size.
+ *
+ * @return errlHndl_t nullptr on success. Otherwise, an error
+ *
+ */
+ errlHndl_t dumpSegment(uint16_t i_segmentCode,
+ uint8_t (&o_buffer)[SEGMENT_SIZE]);
+
+ /**
+ * @brief Merges the segment data dumped from the BPM with the segment data
+ * fragments present in the BpmConfigLidImage that correspond to the
+ * given segment code.
+ *
+ * @param[in] i_configImage The image that holds the fragments of
+ * segment data.
+ *
+ * @param[in] i_segmentCode The segment code that corresponds to the
+ * segment to dump from the BPM.
+ *
+ * @param[out] o_buffer The merged segment data for the BPM.
+ * Must be SEGMENT_SIZE in length.
+ *
+ * @return errlHndl_t nullptr on success. Otherwise, an error.
+ */
+ errlHndl_t mergeSegment(BpmConfigLidImage i_configImage,
+ uint16_t i_segmentCode,
+ uint8_t (&o_buffer)[SEGMENT_SIZE]);
+
+ /**
+ * @brief Commands the BPM to erase the segment data on the BPM using the
+ * given segment code to tell it which to erase.
+ * The BPM must be in BSL mode for this function to work.
+ *
+ * @param[in] i_segmentCode The segment from the config data section to
+ * erase.
+ *
+ * @return errlHndl_t nullptr on success. Otherwise, an error.
+ */
+ errlHndl_t eraseSegment(uint16_t i_segmentCode);
+
+ /**
+ * @brief Writes the segment data from the buffer to the BPM using the
+ * given segment code to determine which segment the data belongs
+ * to. The BPM must be in BSL mode for this function to work.
+ *
+ * @param[in] i_buffer The segment data to write to the BPM.
+ *
+ * @param[in] i_segmentCode The segment from the config data section the
+ * data belongs to.
+ *
+ * @return errlHndl_t nullptr on success. Otherwise, an error.
+ */
+ errlHndl_t writeSegment(uint8_t const (&i_buffer)[SEGMENT_SIZE],
+ uint16_t i_segmentCode);
+
+ /**
+ * @brief Dumps segment D and B data from the BPM and merges it with the
+ * data from the config image to create the unique updated segments
+ * for this BPM. The BPM CANNOT be in BSL mode for this function to
+ * work because the data is dumped using SCAP registers. There must
+ * also be working firmware on the device otherwise this will fail.
+ *
+ * @param[in] i_configImage The config image that has the fragments to
+ * merge into the BPM's existing segment data.
+ *
+ * @return errlHndl_t nullptr on success. Otherwise, an error.
+ */
+ errlHndl_t preprocessSegments(BpmConfigLidImage i_configImage);
+
+ /**
* @brief A helper function used to wait for the command status bit to reset
* after a command is executed.
*
@@ -422,6 +728,41 @@ private:
command_status_register_t i_commandStatus);
/**
+ * @brief Helper function for the SCAP register functions that will poll
+ * the busy bit in SCAP_STATUS until it is zero.
+ *
+ * @return errlHndl_t nullptr on success. Otherwise, an error.
+ */
+ errlHndl_t waitForBusyBit();
+
+ /**
+ * @brief Starting with BSL version 1.4 it is necessary to check the CRC of
+ * the firmware image once it has been written to the BPM. If this
+ * is not done or fails to succeed then the firmware image will not
+ * be loaded and executed by the BPM. If the CRC check fails then
+ * the update must be attempted again.
+ * Must be in BSL mode.
+ *
+ * @return errlHndl_t nullptr on success. Otherwise, an error.
+ */
+ errlHndl_t checkFirmwareCrc();
+
+ /**
+ * @brief After a command is sent to the BPM to request info from it this
+ * function processes the response and returns it to the caller.
+ * Must be in BSL mode.
+ *
+ * @param[in] o_responseData The buffer to be filled with the
+ * response data from the BPM.
+ *
+ * @param[in] i_responseSize The size of the buffer to be filled.
+ *
+ * @return errlHndl_t nullptr on success. Otherwise, an error.
+ */
+ errlHndl_t getResponse(uint8_t * o_responseData,
+ uint8_t i_responseSize);
+
+ /**
* @brief Calculates the CRC16 bytes for the BSL payload. This CRC differs
* from the NVDIMM CRC calculation in that the initial value is
* 0xFFFF instead of 0x0000.
@@ -442,6 +783,36 @@ private:
};
+typedef std::vector<Bpm> bpmList_t;
+
+/**
+ * @brief Runs the firmware and config updates on the list of BPMs given.
+ *
+ * @param[in] i_16gb_BPMs The list of BPMs sitting on 16gb NVDIMMs that
+ * potentially need to be updated.
+ *
+ * @param[in] i_32gb_BPMs The list of BPMs sitting on 32gb NVDIMMs that
+ * potentially need to be updated.
+ *
+ * @param[in] i_16gb_fwImage The firmware image associated with BPMs sitting
+ * on 16gb NVDIMMs.
+ *
+ * @param[in] i_32gb_fwImage The firmware image associated with BPMs sitting
+ * on 32gb NVDIMMs.
+ *
+ * @param[in] i_16gb_configImage The configuration data associated with BPMs
+ * sitting on 16gb NVDIMMs.
+ *
+ * @param[in] i_32gb_configImage The configuration data associated with BPMs
+ * sitting on 32gb NVDIMMs.
+ *
+ */
+void runBpmUpdates(bpmList_t * const i_16gb_BPMs,
+ bpmList_t * const i_32gb_BPMs,
+ BpmFirmwareLidImage * const i_16gb_fwImage,
+ BpmFirmwareLidImage * const i_32gb_fwImage,
+ BpmConfigLidImage * const i_16gb_configImage,
+ BpmConfigLidImage * const i_32gb_configImage);
}; // end of BPM namespace
}; // end of NVDIMM namespace
OpenPOWER on IntegriCloud