Skip to content

Commit

Permalink
Update cmd/rsp endian handling in exp_inband
Browse files Browse the repository at this point in the history
Data written/read from the command/response/data
buffers is done so in transaction sizes of 4 or 8
bytes.  The data in those transactions will be
little endian byte order.  The byte order of those
transactions must be corrected to represent the
data structures stored in the buffers correctly
for extraction of field data.  The fields themselves
will be big endian byte ordering.

This patch also adds two attributes:

ATTR_MSS_OCMB_EXP_STRUCT_MMIO_ENDIAN_CTRL -
Controls whether or not bytes read from and
written two the buffer are swapped.  The default
is to swap the byte order.

ATTR_MSS_OCMB_EXP_STRUCT_ENDIAN -
Controls whether or not the bytes of buffer
structure fields are little endian or not.
The default is big endian.

Change-Id: I734d25dea2a3e4a864a2d35df2576676cad27cfe
Reviewed-on: http://rchgit01.rchland.ibm.com/gerrit1/72314
Tested-by: FSP CI Jenkins <fsp-CI-jenkins+hostboot@us.ibm.com>
Tested-by: Jenkins Server <pfd-jenkins+hostboot@us.ibm.com>
Tested-by: Hostboot CI <hostboot-ci+hostboot@us.ibm.com>
Reviewed-by: Benjamin Gass <bgass@us.ibm.com>
Reviewed-by: Louis Stermole <stermole@us.ibm.com>
Reviewed-by: Jennifer A. Stofer <stofer@us.ibm.com>
Reviewed-on: http://rchgit01.rchland.ibm.com/gerrit1/72920
Tested-by: Jenkins OP Build CI <op-jenkins+hostboot@us.ibm.com>
Tested-by: Jenkins OP HW <op-hw-jenkins+hostboot@us.ibm.com>
Reviewed-by: Christian R. Geddes <crgeddes@us.ibm.com>
  • Loading branch information
BenAtIBM authored and crgeddes committed Mar 28, 2019
1 parent 1564d45 commit 224517a
Show file tree
Hide file tree
Showing 6 changed files with 537 additions and 153 deletions.
486 changes: 345 additions & 141 deletions src/import/chips/ocmb/explorer/procedures/hwp/memory/exp_inband.C

Large diffs are not rendered by default.

94 changes: 82 additions & 12 deletions src/import/chips/ocmb/explorer/procedures/hwp/memory/exp_inband.H
Original file line number Diff line number Diff line change
Expand Up @@ -98,6 +98,8 @@ namespace exp
namespace ib
{

static const size_t BUFFER_TRANSACTION_SIZE = 8;

static const uint64_t EXPLR_IB_CONFIG_OFFSET = 0x0000000000000000ull;
static const uint64_t EXPLR_IB_MMIO_OFFSET = 0x0000000100000000ull; // 4GB

Expand Down Expand Up @@ -128,28 +130,32 @@ static const uint64_t EXPLR_IB_SENSOR_CACHE_ADDR = EXPLR_IB_MMIO_OFFSET | 0x4008
//--------------------------------------------------------------------------------

///
/// @brief Converts user_input_msdg to little endian
/// @brief Converts user_input_msdg to little endian and calculates the crc
/// @param[in] i_input user_input_msdg structure to convert
/// @return vector of little endian data
/// @param[out] o_data vector of bytes for mmio
/// @param[out] o_crc the calculated crc of the data
/// @return fapi2::ReturnCode. FAPI2_RC_SUCCESS if success, else error code.
///
std::vector<uint8_t> user_input_msdg_to_little_endian(const user_input_msdg& i_input);
fapi2::ReturnCode user_input_msdg_to_little_endian(const user_input_msdg& i_input, std::vector<uint8_t>& o_data,
uint32_t& o_crc);

///
/// @brief Converts host_fw_command_struct to little endian
/// @param[in] i_input user_input_msdg structure to convert
/// @return vector of little endian data
/// @param[out] o_data vector of bytes for mmio.
/// @return fapi2::ReturnCode. FAPI2_RC_SUCCESS if success, else error code.
///
std::vector<uint8_t> host_fw_command_struct_to_little_endian(const host_fw_command_struct& i_input);
fapi2::ReturnCode host_fw_command_struct_to_little_endian(const host_fw_command_struct& i_input,
std::vector<uint8_t>& o_data);

///
/// @brief Converts a little endian data array to a host_fw_response_struct
/// @param[in] i_data little endian data to process
/// @param[out] o_crc computed CRC
/// @param[out] o_response response structure
/// @return true if success false if failure
/// @note helper function - returning a bool and will have true FFDC in a separate function
/// @return fapi2::ReturnCode. FAPI2_RC_SUCCESS if success, else error code.
///
bool host_fw_response_struct_from_little_endian(const std::vector<uint8_t>& i_data,
fapi2::ReturnCode host_fw_response_struct_from_little_endian(std::vector<uint8_t>& i_data,
uint32_t& o_crc,
host_fw_response_struct& o_response);

Expand All @@ -163,17 +169,17 @@ bool host_fw_response_struct_from_little_endian(const std::vector<uint8_t>& i_da
///
fapi2::ReturnCode host_fw_response_struct_from_little_endian(const fapi2::Target<fapi2::TARGET_TYPE_OCMB_CHIP>&
i_target,
const std::vector<uint8_t>& i_data,
std::vector<uint8_t>& i_data,
host_fw_response_struct& o_response);

///
/// @brief Converts a little endian data array to a sensor_cache_struct
/// @param[in] i_data little endian data to process
/// @param[out] o_data sensor cache structure
/// @return true if success false if failure
/// @return fapi2::ReturnCode. FAPI2_RC_SUCCESS if success, else error code.
/// @note helper function - returning a bool and will have true FFDC in a separate function
///
bool sensor_cache_struct_from_little_endian(const std::vector<uint8_t>& i_data,
fapi2::ReturnCode sensor_cache_struct_from_little_endian(std::vector<uint8_t>& i_data,
sensor_cache_struct& o_data);

///
Expand All @@ -186,7 +192,7 @@ bool sensor_cache_struct_from_little_endian(const std::vector<uint8_t>& i_data,
///
fapi2::ReturnCode sensor_cache_struct_from_little_endian(const fapi2::Target<fapi2::TARGET_TYPE_OCMB_CHIP>&
i_target,
const std::vector<uint8_t>& i_data,
std::vector<uint8_t>& i_data,
sensor_cache_struct& o_data);

//--------------------------------------------------------------------------------
Expand Down Expand Up @@ -369,6 +375,70 @@ fapi2::ReturnCode getSensorCache(
const fapi2::Target<fapi2::TARGET_TYPE_OCMB_CHIP>& i_target,
sensor_cache_struct& o_data) ;

//--------------------------------------------------------------------------------
// Command/Response/Data structure Endian handling
//--------------------------------------------------------------------------------

/// @brief We will use 4 or 8 byte reads via fapi2::put/getMMIO for buffer
/// data structures. The byte order of the 4 or 8 byte reads should be little
/// endian. In order to represent the data structure in its proper layout
/// the endianness of each 4 or 8 byte read must be corrected.
///
/// @param[inout] io_data Either data structure in proper byte order that we
/// want to swizzle prior to writing to the buffer, or the data returned
/// from reading the buffer that we want to unsizzle.
///
/// @return fapi2::ReturnCode. FAPI2_RC_SUCCESS if success, else error code.
fapi2::ReturnCode correctMMIOEndianForStruct(std::vector<uint8_t>& io_data);

///
/// @brief Forces native data into the correct endianness necessary for Explorer
/// buffer data structures.
/// @tparam T the data type to process
/// @param[in] i_input inputted data to process
/// @param[in,out] io_data vector to append data to
/// @return fapi2::ReturnCode. FAPI2_RC_SUCCESS if success, else error code.
///
template < typename T >
fapi2::ReturnCode forceCrctEndian(const T& i_input, std::vector<uint8_t>& io_data);

///
/// @brief Forces native data into the correct endianness for an array buffer
/// data structures.
/// @tparam T the data type to process
/// @param[in] i_input inputted data to process
/// @param[in] i_size size of the array
/// @param[in,out] io_data vector to append data to
/// @return fapi2::ReturnCode. FAPI2_RC_SUCCESS if success, else error code.
///
template < typename T >
fapi2::ReturnCode forceCrctEndianArray(const T* i_input, const uint64_t i_size, std::vector<uint8_t>& io_data);

///
/// @brief Converts endianness of data read from Explorer buffer data structures
// into native order.
/// @tparam T the data type to output to
/// @param[in] i_input inputted data to process
/// @param[in,out] io_idx current index
/// @param[out] o_data data that has been converted into native endianness
/// @return fapi2::ReturnCode. FAPI2_RC_SUCCESS if success, else error code.
///
template < typename T >
fapi2::ReturnCode readCrctEndian(const std::vector<uint8_t>& i_input, uint32_t& io_idx, T& o_data);

///
/// @brief Converts endianness of data read from Explorer buffer data structures
/// into native order.
/// @tparam T the data type to output to
/// @param[in] i_input inputted data to process
/// @param[in] i_size size of the array
/// @param[in,out] io_idx current index
/// @param[out] o_data data that has been converted into native endianness
/// @return fapi2::ReturnCode. FAPI2_RC_SUCCESS if success, else error code.
///
template < typename T >
fapi2::ReturnCode readCrctEndianArray(const std::vector<uint8_t>& i_input, const uint32_t i_size, uint32_t& io_idx,
T* o_data);

//--------------------------------------------------------------------------------

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -90,6 +90,7 @@ enum ffdc_codes
EXP_I2C_SET_FIELD = 0x0001,
READ_HOST_FW_RESPONSE_STRUCT = 0x0003,
READ_SENSOR_CACHE_STRUCT = 0x0004,
READ_CRCT_ENDIAN = 0x0005,

SET_BYTE_ENABLES = 0x1041,
SET_NIBBLE_ENABLES = 0x1042,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -260,4 +260,38 @@
<mssAccessorName>exp_firmware_emulation_mode</mssAccessorName>
</attribute>

<attribute>
<id>ATTR_MSS_OCMB_EXP_STRUCT_MMIO_ENDIAN_CTRL</id>
<targetType>TARGET_TYPE_SYSTEM</targetType>
<description>
Controls whether or not transaction bytes are
swapped before and after mmio accesses to
the buffer.
</description>
<valueType>uint8</valueType>
<initToZero></initToZero>
<enum>
SWAP = 0,
NO_SWAP = 1
</enum>
<writeable/>
</attribute>

<attribute>
<id>ATTR_MSS_OCMB_EXP_STRUCT_ENDIAN</id>
<targetType>TARGET_TYPE_SYSTEM</targetType>
<description>
Controls whether the structure fields written
and read to and from the buffer are big
or little endian.
</description>
<valueType>uint8</valueType>
<initToZero></initToZero>
<enum>
BIG_ENDIAN = 0,
LITTLE_ENDIAN = 1
</enum>
<writeable/>
</attribute>

</attributes>
Original file line number Diff line number Diff line change
Expand Up @@ -55,4 +55,19 @@
</callout>
</hwpError>

<hwpError>
<rc>RC_EXP_INBAND_BE_DATA_RANGE</rc>
<description>
Data is not long enough for big endian conversion
</description>
<ffdc>TARGET</ffdc>
<ffdc>FUNCTION</ffdc>
<ffdc>DATA_SIZE</ffdc>
<ffdc>MAX_INDEX</ffdc>
<callout>
<procedure>CODE</procedure>
<priority>MEDIUM</priority>
</callout>
</hwpError>

</hwpErrors>
60 changes: 60 additions & 0 deletions src/import/generic/memory/lib/utils/endian_utils.H
Original file line number Diff line number Diff line change
Expand Up @@ -189,6 +189,66 @@ bool readLEArray(const std::vector<uint8_t>& i_input, const uint32_t i_size, uin
return l_passing;
}

///
/// @brief Converts BE data into native order
/// @tparam T the data type to output to
/// @param[in] i_input inputted data to process
/// @param[in,out] io_idx current index
/// @param[out] o_data data that has been converted into native endianness
/// @return bool true if passing false if failing
/// @note Real FFDC will be handled outside
///
template < typename T >
bool readBE(const std::vector<uint8_t>& i_input, uint32_t& io_idx, T& o_data)
{
const uint32_t l_sz = static_cast<uint32_t>(sizeof(o_data));
uint64_t l_idx = io_idx;
io_idx = l_sz + io_idx;

// Checks that our final index is within the data range
// Note: we decrement the index prior, so equal to is ok
if(io_idx > i_input.size())
{
return false;
}

o_data = 0;

for(uint64_t i = 0; i < l_sz; i++)
{
uint8_t v = i_input[l_idx];
o_data <<= BITS_PER_BYTE;
o_data |= v;
l_idx++;
}

return true;
}

///
/// @brief Converts BE data into native order
/// @tparam T the data type to output to
/// @param[in] i_input inputted data to process
/// @param[in] i_size size of the array
/// @param[in,out] io_idx current index
/// @param[out] o_data data that has been converted into native endianness
/// @return bool true if passing false if failing
/// @note Real FFDC will be handled outside
///
template < typename T >
bool readBEArray(const std::vector<uint8_t>& i_input, const uint32_t i_size, uint32_t& io_idx, T* o_data)
{
// Loop while the readLE is still passing and we haven't looped through the array's boundaries
bool l_passing = true;

for(uint32_t i = 0; i < i_size && l_passing; ++i)
{
l_passing = readBE(i_input, io_idx, o_data[i]);
}

return l_passing;
}

}

#endif

0 comments on commit 224517a

Please sign in to comment.