diff options
Diffstat (limited to 'src/usr/isteps/nvdimm/nvdimm.H')
-rw-r--r-- | src/usr/isteps/nvdimm/nvdimm.H | 344 |
1 files changed, 340 insertions, 4 deletions
diff --git a/src/usr/isteps/nvdimm/nvdimm.H b/src/usr/isteps/nvdimm/nvdimm.H index 4d97a9c66..e66e42470 100644 --- a/src/usr/isteps/nvdimm/nvdimm.H +++ b/src/usr/isteps/nvdimm/nvdimm.H @@ -5,7 +5,7 @@ /* */ /* OpenPOWER HostBoot Project */ /* */ -/* Contributors Listed Below - COPYRIGHT 2014,2019 */ +/* Contributors Listed Below - COPYRIGHT 2014,2020 */ /* [+] International Business Machines Corp. */ /* */ /* */ @@ -27,6 +27,7 @@ #define NVDIMM_H__ #include <usr/errl/errlentry.H> +#include <targeting/common/target.H> #include <targeting/common/commontargeting.H> #include <targeting/common/util.H> #include <targeting/common/utilFilter.H> @@ -40,6 +41,12 @@ extern trace_desc_t* g_trac_nvdimm; namespace NVDIMM { +#define NVDIMM_SET_USER_DATA_1(left_32_ops_id, right_32_huid) \ + TWO_UINT32_TO_UINT64(left_32_ops_id, right_32_huid) + +#define NVDIMM_SET_USER_DATA_2_TIMEOUT(left_32_polled, right_32_timeout) \ + NVDIMM_SET_USER_DATA_1(left_32_polled, right_32_timeout) + // I2C registers for page 0-3, extracted from JEDEC BAEBI spec // Refer to BAEBI spec for details @@ -121,11 +128,13 @@ enum i2cReg : uint16_t SET_ES_POLICY_STATUS = 0x070, FIRMWARE_OPS_STATUS = 0x071, OPERATIONAL_UNIT_OPS_STATUS = 0x072, - RESTORE_FAIL_INFO = 0x088, - OPERATIONAL_UNIT_FAIL_INFO = 0x08F, + ERASE_FAIL_INFO = 0x073, + ARM_FAIL_INFO = 0x076, CSAVE_INFO = 0x080, CSAVE_FAIL_INFO0 = 0x084, CSAVE_FAIL_INFO1 = 0x085, + RESTORE_FAIL_INFO = 0x088, + OPERATIONAL_UNIT_FAIL_INFO = 0x08F, NVM_LIFETIME_ERROR_THRESHOLD = 0x090, ES_LIFETIME_ERROR_THRESHOLD = 0x091, ES_TEMP_ERROR_HIGH_THRESHOLD0 = 0x094, @@ -274,6 +283,45 @@ enum i2cReg : uint16_t TYPED_BLOCK_DATA_BYTE30 = 0x39E, TYPED_BLOCK_DATA_BYTE31 = 0x39F, TYPED_BLOCK_DATA_OFFSET = 0x3E0, + PANIC_CNT = 0x406, + STATUS_EVENT_INT_INFO1 = 0x40A, + STATUS_EVENT_INT_INFO2 = 0x40B, + FLASH_BAD_BLK_PCT = 0x41D, // Read only; Percentage of flash blocks + // in the flash array marked as bad blocks + PARITY_ERROR_COUNT = 0x423, + FLASH_ERROR_COUNT0 = 0x428, // Read only; LSB[7:0] Flash error count + FLASH_ERROR_COUNT1 = 0x429, // Read only; [15:8] + FLASH_ERROR_COUNT2 = 0x42A, // Read only; MSB[23:16] + FLASH_BAD_BLOCK_COUNT0 = 0x42B, + FLASH_BAD_BLOCK_COUNT1 = 0x42C, + BPM_MAGIC_REG1 = 0x430, + BPM_MAGIC_REG2 = 0x431, + SCAP_STATUS = 0x432, + SCAP_REG = 0x434, + SCAP_DATA = 0x435, + I2C_REG_PROTECT = 0x43D, + BPM_REG_CMD = 0x440, + BPM_CMD_STATUS = 0x441, + BPM_PAYLOAD_LENGTH = 0x442, + BPM_REG_ERR_STATUS = 0x443, + BPM_REG_PAYLOAD_START = 0x444, + ERASE_VERIFY_CONTROL = 0x51A, + ERASE_VERIFY_STATUS = 0x51B, + ERASE_VERIFY_RESULT_LSB = 0x51C, + ERASE_VERIFY_RESULT_MSB = 0x51D, + ERASE_VERIFY_TEST = 0x51E, + ENCRYPTION_COMMAND = 0x51F, + ENCRYPTION_CONFIG_STATUS = 0x520, + ENCRYPTION_ACCESS_KEY_SET = 0x521, + ENCRYPTION_ACCESS_KEY_VERIFY = 0x522, + ENCRYPTION_ACCESS_KEY_UNLOCK = 0x523, + ENCRYPTION_RAMDOM_STRING_SET = 0x524, + ENCRYPTION_RANDOM_STRING_VERIFY = 0x525, + ENCRYPTION_ERASE_KEY_SET = 0x526, + ENCRYPTION_ERASE_KEY_VERIFY = 0x527, + ENCRYPTION_ERASE_KEY_TEST = 0x528, + ENCRYPTION_ERASE_KEY_TEST_VERIFY = 0x529, + ENCRYPTION_KEY_VALIDATION = 0x52A, }; // i2cReg macros @@ -292,6 +340,7 @@ enum page : uint8_t TWO = 0x02, THREE = 0x03, FOUR = 0x04, + FIVE = 0x05, }; // Enums for inputs/expected output to/from the i2c registers @@ -306,6 +355,7 @@ enum i2c_in_values : uint8_t RESET_CTRLR = 0x01, VALID_IMAGE = 0x01, RESET_CONTROLLER = 0x01, + FACTORY_DEFAULT = 0x01, }; enum i2c_out_values : uint8_t @@ -317,11 +367,20 @@ enum i2c_out_values : uint8_t CHARGE_IN_PROGRESS = 0x01, SAVE_SUCCESS = 0x01, RSTR_SUCCESS = 0X01, - ARM_SUCCESS = 0X09, + ARM_SUCCESS = 0X01, ERASE_SUCCESS = 0X01, ES_SUCCESS = 0x05, CHARGE_SUCCESS = 0x00, NV_READY = 0xA5, + FACTORY_RESET_IN_PROGRESS = 0x03, + NO_RESET_N = 0x20, + RESET_N_ARMED = 0x08, + ES_POLICY_ERROR = 0x02, + ARM_ERROR = 0X02, + RSTR_ERROR = 0x02, + SAVE_ERROR = 0x02, + ERASE_ERROR = 0x02, + CLEAR_ALL_STATUS = 0x3C, //Clears CAVE, RESTORE, ERASE, and ARM status regs }; // Timeout-related enum @@ -330,6 +389,7 @@ enum timeout : uint32_t OPS_POLL_TIME_MS = 5000, NV_READY_POLL_TIME_MS = 1000, PAGE_SWITCH_POLL_TIME_NS = 100, + KEY_WRITE_DELAY_MS = 100, }; // Assign an id to each of the 6 major ops @@ -354,6 +414,119 @@ enum misc }; /** + * @brief Encryption key data + */ +static constexpr size_t ENC_KEY_SIZE = 32; +struct nvdimmKeyData_t +{ + uint8_t rs[ENC_KEY_SIZE]; // Random String (RS) + uint8_t ek[ENC_KEY_SIZE]; // Erase Key (EK) + uint8_t ak[ENC_KEY_SIZE]; // Access Key (AK) +}; + +struct scap_status_bits +{ + uint8_t Reserved1 : 1; // Bit 7 + uint8_t Bpm_Bsl_Mode : 1; // Bit 6 + uint8_t Reserved2 : 1; // Bit 5 + uint8_t Present : 1; // Bit 4 + uint8_t Delay : 1; // Bit 3 + uint8_t Error : 1; // Bit 2 + uint8_t Busy : 1; // Bit 1 + uint8_t Enable : 1; // Bit 0 +} PACKED; + +/** + * @brief Union simplifying manipulation of SCAP_STATUS bits + */ +union scap_status_union +{ + uint8_t full; + scap_status_bits bit; + + /** + * @brief Constructor + */ + scap_status_union() + : full(0) + {} +} PACKED; + +typedef scap_status_union scap_status_register_t; + +// Bits in Health Status Check Registers +enum health_status : uint8_t +{ + // Module Health Status0 + VOLTAGE_REGULATOR_FAILED = 0x01, + VDD_LOST = 0x02, + VPP_LOST = 0x04, + VTT_LOST = 0x08, + DRAM_NOT_SELF_REFRESH = 0x10, + CONTROLLER_HARDWARE_ERROR = 0x20, + NVM_CONTROLLER_ERROR = 0x40, + NVM_LIFETIME_ERROR = 0x80, + // Module Health Status1 + NOT_ENOUGH_ENERGY_FOR_CSAVE = 0x01, + INVALID_FIRMWARE_ERROR = 0x02, + CONFIG_DATA_ERROR = 0x04, + NO_ES_PRESENT = 0x08, + ES_POLICY_NOT_SET = 0x10, + ES_HARDWARE_FAILURE = 0x20, + ES_HEALTH_ASSESSMENT_ERROR = 0x40, + // Error Threshold Status + ES_LIFETIME_ERROR = 0x02, + ES_TEMP_ERROR = 0x04, +}; + +// Int representation for health status function call +enum health_function : uint8_t +{ + HEALTH_SAVE = 0x01, + HEALTH_RESTORE = 0x02, + HEALTH_UPDATE = 0x03, + HEALTH_PRE_ARM = 0x04, + HEALTH_POST_ARM = 0x05, +}; + +// Event notification register values +enum event_n : uint8_t +{ + PERSISTENCY_NOTIFICATION = 0x01, + SET_EVENT_NOTIFICATION_ERROR = 0x02, + WARNING_THRESHOLD_NOTIFICATION = 0x02, + PERSISTENCY_ENABLED = 0x04, + WARNING_THRESHOLD_ENABLED = 0x08, + ENABLE_NOTIFICATIONS = 0x03, + NOTIFICATIONS_ENABLED = 0x0C, +}; + +// MBACALFIR register addresses +enum mbacal_addresses : uint32_t +{ + MBACALFIR_AND_MASK_REG = 0x07010904, + MBACALFIR_OR_MASK_REG = 0x07010905, + MBACALFIR_ACTION0_REG = 0x07010906, + MBACALFIR_ACTION1_REG = 0x07010907, +}; + +// MBACALFIR bit masks for event n +enum mbacal_bitmask_values : uint64_t +{ + MBACALFIR_EVENTN_AND_BIT = 0xff7fffffffffffff, + MBACALFIR_EVENTN_OR_BIT = 0x0080000000000000, + MBACALFIR_UNMASK_BIT = 0xff7fffffffffffff, +}; + + +/** + * @brief Mask MCBACALFIR Event N to prevent PRD from handling event + * + * @param[in] - i_nvdimm - nvdimm target for operation on its parent MCA + */ +void maskMbacalfir_eventn(TARGETING::Target* i_nvdimm); + +/** * @brief Wrapper to call deviceOp to read the NV controller via I2C * * @param[in] i_nvdimm - nvdimm target with NV controller @@ -434,6 +607,169 @@ errlHndl_t nvdimmPollStatus(TARGETING::Target *i_nvdimm, ops_id i_ops_id, uint32 * the error log. */ errlHndl_t nvdimmSetESPolicy(TARGETING::Target* i_nvdimm); + +/** + * @brief Helper function to handle conflicting attribute keys + * + * @param[in] i_attrKeysFw - firmware key attribute + * + * @param[in] i_attrKeysAnchor - anchor key attribute + * + * @return errlHndl_t - Null if successful, otherwise a pointer to + * the error log + */ +errlHndl_t nvdimm_handleConflictingKeys( + TARGETING::ATTR_NVDIMM_ENCRYPTION_KEYS_FW_typeStdArr& i_attrKeysFw, + TARGETING::ATTR_NVDIMM_ENCRYPTION_KEYS_ANCHOR_typeStdArr& i_attrKeysAnchor); + + +/** + * @brief Helper function to validate attribute keys + * + * @param[in] i_attrData - pointer to attribute key data + * + * @return errlHndl_t - Null if successful, otherwise a pointer to + * the error log + */ +errlHndl_t nvdimm_checkValidAttrKeys( nvdimmKeyData_t* i_attrData ); + + +/** + * @brief Helper function to write encryption key regs (RS/EK/AK) + * + * @param[in] i_nvdimm - nvdimm target + * + * @param[in] i_keyData - data to write to the key reg + * + * @param[in] i_keyReg - enum register to write key + * + * @param[in] i_verifyReg - enum register to verify key written + * + * @param[in] i_secondAttempt - normally false, true if verif check failed + * + * @return errlHndl_t - Null if successful, otherwise a pointer to + * the error log + */ +errlHndl_t nvdimm_setKeyReg(TARGETING::Target* i_nvdimm, + uint8_t* i_keyData, + uint32_t i_keyReg, + uint32_t i_verifyReg, + bool i_secondAttempt); + + +/** + * @brief Helper function to generate randon number for encryption keys + * Generates ENC_KEY_SIZE bytes of data + * Different implementations for boot vs runtime + * + * @param[out] o_genData - pointer to generated data + * + * @return errlHndl_t - Null if successful, otherwise a pointer to + * the error log + */ +errlHndl_t nvdimm_getRandom(uint8_t* o_genData); + + +/** + * @brief Helper function to make a random number valid for keys + * Keys must not contain 0x00 or 0xFF + * - 0x00 KEY_TERMINATE_BYTE terminates a key < 32 bytes + * - 0xFF KEY_ABORT_BYTE aborts the key reg write process + * This function finds invalid bytes in the first random number + * and replaces with bytes from the second random number + * + * @param[out] o_genData - pointer to final generated data + * + * @param[in] i_xtraData - pointer to extra generated data + * + * @return - false if successful, true if failed + * + */ +bool nvdimm_keyifyRandomNumber(uint8_t* o_genData, uint8_t* i_xtraData); + + +/** + * @brief Helper function to validate a random number + * + * @param[in] i_genData - pointer to generated data + * + * @return - true if valid, false if invalid + * + */ +bool nvdimm_validRandomNumber(uint8_t* i_genData); + + +/** + * @brief Helper function to set encryption error + * in ATTR_NVDIMM_ARMED + * + * @param[in] i_nvdimm - nvdimm target + * + */ +void nvdimmSetEncryptionError(TARGETING::Target *i_nvdimm); + + +/** + * @brief Helper function to reset the NVDIMM controller + * + * @param[in] i_nvdimm - nvdimm target + * + * @return errlHndl_t - Null if successful, otherwise a pointer to + * the error log + */ +errlHndl_t nvdimmResetController(TARGETING::Target *i_nvdimm); + + +/** + * @brief Helper function to factory reset NVDIMM + * + * @param[in] i_nvdimm - nvdimm target + * + * @return errlHndl_t - Null if successful, otherwise a pointer to + * the error log + */ +errlHndl_t nvdimm_factory_reset(TARGETING::Target *i_nvdimm); + + +#ifndef __HOSTBOOT_RUNTIME + +/** + * @brief Helper function to get TPM pointer for random number generation + * + * @param[out] - pointer to a functional TPM or nullptr if no TPM found + * + * @return errlHndl_t - Null if successful, otherwise a pointer to + * the error log + */ +errlHndl_t nvdimm_getTPM(TARGETING::Target*& o_tpm); + +#endif + +/** + * @brief This function checks for valid image on the given target + * + * @param[in] i_nvdimm - nvdimm target with NV controller + * + * @param[out] o_imgValid - return true if the target has a valid image + * + * @return errlHndl_t - Null if successful, otherwise a pointer to + * the error log. + */ +errlHndl_t nvdimmValidImage(TARGETING::Target *i_nvdimm, bool &o_imgValid); + + +/** + * @brief This function grabs the current slot NVDIMM code is running + * Slot 0 is the failure slot, Slot 1 is the updateable slot + * + * @param[in] i_nvdimm - nvdimm target with NV controller + * @param[out] o_slot - 0 or 1 + * + * @return errlHndl_t - Null if successful, otherwise a pointer to + * the error log. + */ +errlHndl_t nvdimmGetRunningSlot(TARGETING::Target *i_nvdimm, uint8_t & o_slot); + } //End NVDIMM namespace |