diff --git a/src/include/runtime/hbrt_utilities.H b/src/include/runtime/hbrt_utilities.H index 87a9cc708ee..1764dedb15d 100644 --- a/src/include/runtime/hbrt_utilities.H +++ b/src/include/runtime/hbrt_utilities.H @@ -184,8 +184,8 @@ errlHndl_t sendAttributes(const std::vector // If caller passes in an empty list, then nothing to do if (!i_attributeList.size()) { - TRACFCOMP(g_trac_runtime, "sendAttributes: attribute list is empty," - "nothing to do ..."); + TRACFCOMP(g_trac_runtime, "sendAttributes: attribute list is " + "empty,nothing to do ..."); break; } @@ -210,28 +210,29 @@ errlHndl_t sendAttributes(const std::vector * @custdesc Internal firmware error */ l_err = new ERRORLOG::ErrlEntry(ERRORLOG::ERRL_SEV_UNRECOVERABLE, - RUNTIME::MOD_RT_FIRMWARE_REQUEST, - RUNTIME::RC_FW_REQUEST_RT_NULL_PTR, - i_attributeList.size(), - 0, - ERRORLOG::ErrlEntry::ADD_SW_CALLOUT); + RUNTIME::MOD_RT_FIRMWARE_REQUEST, + RUNTIME::RC_FW_REQUEST_RT_NULL_PTR, + i_attributeList.size(), + 0, + ERRORLOG::ErrlEntry::ADD_SW_CALLOUT); break; } - /// Calculate the size requirements needed to serialize the Attribute info - // Start with the size of 'struct AttributeSetter_t' itself - uint16_t l_dataSize(sizeof(AttributeSetter_t)); - - // Then add in the individual attributes themselves + /// Calculate the size requirements needed to serialize + /// the Attribute info + // Aggregate the size of the incoming Attributes + uint32_t l_aggregatedAttributeSize(0); for (auto l_attribute: i_attributeList) { - // Add in the size of `struct AttributeHeader` - l_dataSize += sizeof(l_attribute.iv_hdr); - // Finally add in the size of the attribute value - l_dataSize += l_attribute.iv_hdr.iv_valSize; + l_aggregatedAttributeSize += l_attribute.getSize(); } + // Combine the size of the AttributeSetter_t itself to the size of + // incoming Attributes to get the full size requirement needed + uint32_t l_dataSize(sizeof(AttributeSetter_t) + + l_aggregatedAttributeSize); + // Create and initialize to zero a few needed variables uint32_t l_fullFspDataSize(0); uint64_t l_fwRequestMsgSize(0), l_fwResponseMsgSize(0); @@ -257,11 +258,11 @@ errlHndl_t sendAttributes(const std::vector * @custdesc Internal firmware error */ l_err = new ERRORLOG::ErrlEntry(ERRORLOG::ERRL_SEV_UNRECOVERABLE, - RUNTIME::MOD_SEND_ATTRIBUTES_TO_FSP, - RUNTIME::RC_NULL_FIRMWARE_MSG_PTR, - i_attributeList.size(), - 0, - ERRORLOG::ErrlEntry::ADD_SW_CALLOUT); + RUNTIME::MOD_SEND_ATTRIBUTES_TO_FSP, + RUNTIME::RC_NULL_FIRMWARE_MSG_PTR, + i_attributeList.size(), + 0, + ERRORLOG::ErrlEntry::ADD_SW_CALLOUT); break; } @@ -269,7 +270,7 @@ errlHndl_t sendAttributes(const std::vector // Populate the 'message queue' and 'message type' for this message l_fwRequestMsg->generic_msg.msgq = MBOX::FSP_NVDIMM_KEYS_MSGQ_ID; l_fwRequestMsg->generic_msg.msgType = - GenericFspMboxMessage_t::MSG_DECONFIG_TARGET; + GenericFspMboxMessage_t::MSG_DECONFIG_TARGET; // Create a useful struct to populate the generic_msg::data field AttributeSetter_t* l_attributeSetter = @@ -286,22 +287,71 @@ errlHndl_t sendAttributes(const std::vector // Retrieve the individual attributes (header and value) // Create a useful struct to poulate attribute data uint8_t* l_attributeData = l_attributeSetter->iv_attrData; + uint32_t l_sizeOfDataCopied(0); for (const auto & l_attribute: i_attributeList) { - // Copy the attribute header - memcpy(l_attributeData, - &(l_attribute.iv_hdr), - sizeof(l_attribute.iv_hdr)); - // Advance pointer, one beyond the attribute header - l_attributeData += sizeof(l_attribute.iv_hdr); - - // Copy the attribute value - memcpy(l_attributeData, - l_attribute.iv_pVal, - l_attribute.iv_hdr.iv_valSize); - // Advance pointer, one beyond the attribute value - l_attributeData += l_attribute.iv_hdr.iv_valSize; - } + if (l_aggregatedAttributeSize >= l_attribute.getSize()) + { + l_sizeOfDataCopied = l_attribute.serialize( + l_attributeData, l_aggregatedAttributeSize); + + if (!l_sizeOfDataCopied) + { + TRACFCOMP(g_trac_runtime, ERR_MRK"sendAttributes: " + "Serialization of an Attribute failed, " + "should never happen") + + /*@ + * @errortype + * @severity ERRL_SEV_UNRECOVERABLE + * @moduleid MOD_SEND_ATTRIBUTES_TO_FSP + * @reasoncode RC_SERIALIZE_ATTRIBUTE_FAILED + * @userdata1 Number of Attributes to serialize and send + * @devdesc Serialization of an Attribute Failed + * @custdesc Internal firmware error + */ + l_err = new ERRORLOG::ErrlEntry( + ERRORLOG::ERRL_SEV_UNRECOVERABLE, + RUNTIME::MOD_SEND_ATTRIBUTES_TO_FSP, + RUNTIME::RC_SERIALIZE_ATTRIBUTE_FAILED, + i_attributeList.size(), + 0, + ERRORLOG::ErrlEntry::ADD_SW_CALLOUT); + + break; + } // end if (!l_sizeOfDataCopied) + } + else + { + TRACFCOMP(g_trac_runtime, ERR_MRK"sendAttributes: " + "Miscalculation of aggregated size of attributes, " + "should never happen") + + /*@ + * @errortype + * @severity ERRL_SEV_UNRECOVERABLE + * @moduleid MOD_SEND_ATTRIBUTES_TO_FSP + * @reasoncode RC_NO_SPACE_FOR_ATTRIBUTE_SERIALIZATION + * @userdata1 Number of Attributes to serialize and send + * @devdesc Serialization data of Attribute to large + * for given buffer + * @custdesc Internal firmware error + */ + l_err = new ERRORLOG::ErrlEntry( + ERRORLOG::ERRL_SEV_UNRECOVERABLE, + RUNTIME::MOD_SEND_ATTRIBUTES_TO_FSP, + RUNTIME::RC_NO_SPACE_FOR_ATTRIBUTE_SERIALIZATION, + i_attributeList.size(), + 0, + ERRORLOG::ErrlEntry::ADD_SW_CALLOUT); + + break; + } + + // Decrement/increment our counters/pointers + l_aggregatedAttributeSize -= l_sizeOfDataCopied; + l_attributeData += l_sizeOfDataCopied; + } // end for (const auto & l_attribute: i_attributeList) // Make the firmware_request call l_err = firmware_request_helper(l_fwRequestMsgSize, diff --git a/src/include/usr/runtime/runtime_reasoncodes.H b/src/include/usr/runtime/runtime_reasoncodes.H index 735a4ec6c59..7aa6a114da1 100644 --- a/src/include/usr/runtime/runtime_reasoncodes.H +++ b/src/include/usr/runtime/runtime_reasoncodes.H @@ -141,6 +141,8 @@ namespace RUNTIME RC_SP_ATTN_AREA1_SIZE_OVERFLOW = RUNTIME_COMP_ID | 0x43, RC_UNKNOWN_LABEL = RUNTIME_COMP_ID | 0x44, RC_NULL_FIRMWARE_MSG_PTR = RUNTIME_COMP_ID | 0x45, + RC_SERIALIZE_ATTRIBUTE_FAILED = RUNTIME_COMP_ID | 0x46, + RC_NO_SPACE_FOR_ATTRIBUTE_SERIALIZATION = RUNTIME_COMP_ID | 0x47, }; enum UserDetailsTypes diff --git a/src/include/usr/targeting/common/attributeTank.H b/src/include/usr/targeting/common/attributeTank.H index ccb56888922..9561b9b8302 100644 --- a/src/include/usr/targeting/common/attributeTank.H +++ b/src/include/usr/targeting/common/attributeTank.H @@ -155,14 +155,314 @@ namespace AttributeTank /** * @brief Constructor */ - Attribute(); + Attribute() + : iv_hdr(), + iv_pVal(NULL) + { + } /** * @brief Destructor. Frees memory */ - ~Attribute(); + ~Attribute() + { + delete[] iv_pVal; + iv_pVal = NULL; + } - // Public data + /** + * @brief Set the Attribute ID + */ + void setId(const uint32_t i_attrId) + { + iv_hdr.iv_attrId = i_attrId; + } + + /** + * @brief Set the Attribute Target Type + */ + void setTargetType(const uint32_t i_targetType) + { + iv_hdr.iv_targetType = i_targetType; + } + + /** + * @brief Set the Attribute Position + */ + void setPosition(const uint16_t i_pos) + { + iv_hdr.iv_pos = i_pos; + } + + /** + * @brief Set the Attribute Unit Position + */ + void setUnitPosition(const uint8_t i_unitPos) + { + iv_hdr.iv_unitPos = i_unitPos; + } + + /** + * @brief Set the Attribute Node + */ + void setNode(const uint8_t i_node) + { + iv_hdr.iv_node = i_node; + } + + /** + * @brief Set the Attribute Flags + */ + void setFlags(const uint8_t i_flags) + { + iv_hdr.iv_flags = i_flags; + } + + /** + * @brief Get the size of all the Attribute's data members, + * aggregated together + * + * return Aggregated size of the Attribute's data members + */ + uint32_t getSize() const + { + return (sizeof(iv_hdr) + iv_hdr.iv_valSize); + } + + /** + * @brief Get a constant reference to the Attribute Header. + * Returning a reference for fast retrieval. + * + * @note Caller should not attempt to modify contents of the + * Attribute Header. Use appropriate Attribute set methods + * + * return A constant reference to the Attribute Header + */ + const AttributeHeader & getHeader() const + { + return iv_hdr; + } + + /** + * @brief Set the Attribute Value to a copy of the given buffer + * + * @pre Passing in nonsensical parameters will produce unpredictable + * results, ie passing in a null buffer with size > 0 + * + * @note Passing in a null buffer with size 0 will clear the value + * + * @param[in] i_buffer The buffer that contains the value to + * be copied + * @param[in] i_bufferSize Size of the given buffer + * + * return The size of the data that was copied + */ + uint32_t setValue(const void * const i_buffer, + const uint32_t i_bufferSize) + + { + // Reuse storage when possible + if (i_bufferSize != iv_hdr.iv_valSize) + { + // Clean up current Attribute Value + delete []iv_pVal; + iv_pVal = NULL; + + // Set size and allocate memory space + iv_hdr.iv_valSize = i_bufferSize; + if (iv_hdr.iv_valSize) + { + iv_pVal = new uint8_t[iv_hdr.iv_valSize]; + } + } + + // Make a copy of the data. Passing in a size of 0 + // or NULL turns this call to no-op + memcpy(iv_pVal, i_buffer, iv_hdr.iv_valSize); + + return iv_hdr.iv_valSize; + } + + /** + * @brief Get a constant pointer to the Attribute Value. + * Returning a constant pointer for fast retrieval. + * + * @note Caller should not attempt to modify the contents nor + * delete the pointer, use method setValue if + * need be. + * + * return A constant pointer to the Attribute Value + */ + const void* const getValue() const + { + return iv_pVal; + } + + /** + * @brief Return a copy of the Attribute Value into caller's bufffer + * + * @param[in] i_buffer The buffer to copy Attribute Value into + * @param[in] i_bufferSize Size of the given buffer + * + * return The size of the Attribute Value that was copied + * or 0 if unable to copy the Attribute Value - buffer + * size to small will cause this + */ + uint32_t cloneValue(void* const o_buffer, + const uint32_t i_bufferSize) const + { + // Return the size of the cloned data + uint32_t l_attributeValueSize(0); + + // Is the buffer large enough to contain the Attribute Value? + if (i_bufferSize >= iv_hdr.iv_valSize) + { + // Buffer is large enough to contain the Attribute Value - + // copy the Attribute Value to given buffer + memcpy(o_buffer, iv_pVal, iv_hdr.iv_valSize); + + // Return the size of the cloned data + l_attributeValueSize = iv_hdr.iv_valSize; + } + + return l_attributeValueSize; + } + + /** + * @brief Serialize the Attribute, if the buffer given is large + * enough to contain the Attribute's data members + * + * @param[out] o_buffer The buffer to contain the serialized + * data members + * @param[in] i_bufferSize Size of the given buffer + * + * return 0 if buffer is to small to contain the data members; + * otherwise the aggregated size of the Attribute's data + * members copied + */ + uint32_t serialize(void* const o_buffer, + const uint32_t i_bufferSize) const + { + // Return the size of the serialized data + uint32_t l_attributeSize(0); + + // If buffer size greater than or equal to the size of the + // Attribute's data members aggregated together then + // copy the data members to buffer + if (i_bufferSize >= getSize()) + { + // Get an Attribute handle to buffer for easy access + uint8_t* l_attribute = static_cast(o_buffer); + + // Copy the Attribute Header + memcpy(l_attribute, &iv_hdr, sizeof(iv_hdr)); + l_attribute += sizeof(iv_hdr); + + // Copy the Attribute Value + memcpy(l_attribute, iv_pVal, iv_hdr.iv_valSize); + + // Return the size of the serialized data + l_attributeSize = sizeof(iv_hdr) + iv_hdr.iv_valSize; + } + + return l_attributeSize; + } + + /** + * @brief Deserialize the buffer, if the buffer given is at least + * the same size as an Attribute + * + * @param[out] i_buffer The buffer to deserialize + * @param[in] i_bufferSize Size of the given buffer + * + * @post If the buffer is large enough to populate the Attribute, then + * the Attribute will be populated, with it's own copy of the + * data. If the buffer is too small, then the Attribute is + * untouched. + * + * return 0 if buffer is to small to populate an Attribute; + * otherwise the aggregated size of the Attribute's data + * members deserialized + */ + uint32_t deserialize(const void* const i_buffer, + const uint32_t i_bufferSize) + { + // Return the size of the Attribute + uint32_t l_attributeSize(0); + + // Get an Attribute handle to buffer for easy access + const Attribute* const l_attribute = + reinterpret_cast(i_buffer); + + // Get the minimum size needed to check for values + uint32_t l_attributeHeaderSize(sizeof(iv_hdr)); + + // Make sure the buffer is not just large enough to inspect the + // Attribute Header but large enough to read Values if they exist + // Need to make sure size is at minimum threshold before calling + // getSize(), because getSize assumes the data is there to read + if ( (i_bufferSize >= l_attributeHeaderSize) && + (i_bufferSize >= (l_attribute->getSize())) ) + { + // Get an uint8_t handle to buffer for easy access + const uint8_t* l_attributeData = + reinterpret_cast(i_buffer); + + // Copy header data + memcpy(&iv_hdr, l_attributeData, l_attributeHeaderSize); + + // Free iv_pVal data, if it currently has data, and set to NULL + delete []iv_pVal; // OK to delete a NULL ptr + iv_pVal = NULL; + + // Populate values if they exist + uint32_t l_valueSize = iv_hdr.iv_valSize; + if (l_valueSize) + { + // Copy the Attribute Value + iv_pVal = new uint8_t[l_valueSize]; + l_attributeData += l_attributeHeaderSize; + memcpy(iv_pVal, l_attributeData, l_valueSize); + } + + // Return the size of the Attribute + l_attributeSize = getSize(); + } + + return l_attributeSize; + } + + + /** + * @brief Assignment operator defined + */ + Attribute& operator=(const Attribute& rhs) + { + // check for self-assignment + if (&rhs != this) + { + // Deep copy the attribute value + setValue(rhs.iv_pVal, rhs.iv_hdr.iv_valSize); + // Copy the Attribute header + iv_hdr = rhs.iv_hdr; + } + + return *this; + } + + /** + * @brief Copy constructor defined + */ + Attribute(const Attribute& rhs) + : iv_hdr(), + iv_pVal(NULL) + { + // Call the assignment operator to do the work + *this = rhs; + } + + // Private data + private: AttributeHeader iv_hdr; uint8_t * iv_pVal; // Pointer to attribute value }; @@ -205,7 +505,7 @@ namespace AttributeTank /** * @brief Destructor. Deletes all Attributes */ - virtual ~AttributeTank(); + ~AttributeTank(); /** * @brief Checks if the platform has enabled synchronization @@ -231,9 +531,8 @@ namespace AttributeTank * specific node (i_node) * @param[in] i_node See i_nodeFilter */ - virtual void clearAllAttributes( - const NodeFilter i_nodeFilter = NODE_FILTER_NONE, - const uint8_t i_node = ATTR_NODE_NA); + void clearAllAttributes(const NodeFilter i_nodeFilter = NODE_FILTER_NONE, + const uint8_t i_node = ATTR_NODE_NA); /** * @brief Clear any non-const attribute for a specified ID and Target @@ -247,11 +546,11 @@ namespace AttributeTank * @param[in] i_unitPos Target Unit Position * @param[in] i_node Target Node */ - virtual void clearNonConstAttribute(const uint32_t i_attrId, - const uint32_t i_targetType, - const uint16_t i_pos, - const uint8_t i_unitPos, - const uint8_t i_node); + void clearNonConstAttribute(const uint32_t i_attrId, + const uint32_t i_targetType, + const uint16_t i_pos, + const uint8_t i_unitPos, + const uint8_t i_node); /** * @brief Set an Attribute @@ -273,14 +572,14 @@ namespace AttributeTank * @param[in] i_valSize Size of attribute value in bytes * @param[in] i_pVal Pointer to attribute value */ - virtual void setAttribute(const uint32_t i_attrId, - const uint32_t i_targetType, - const uint16_t i_pos, - const uint8_t i_unitPos, - const uint8_t i_node, - const uint8_t i_flags, - const uint32_t i_valSize, - const void * i_pVal); + void setAttribute(const uint32_t i_attrId, + const uint32_t i_targetType, + const uint16_t i_pos, + const uint8_t i_unitPos, + const uint8_t i_node, + const uint8_t i_flags, + const uint32_t i_valSize, + const void * i_pVal); /** * @brief Get a copy of an Attribute @@ -288,21 +587,24 @@ namespace AttributeTank * This is called on an OverrideAttributeTank to query/get an Attribute * Override when an attribute is got * + * @note Caller's responsibility to ensure the passed in buffer + * is large enough to contain the Attribute Value. + * * @param[in] i_attrId Attribute ID * @param[in] i_targetType Target Type attribute is for * @param[in] i_pos Target Position * @param[in] i_unitPos Target Unit Position * @param[in] i_node Target Node - * @param[out] o_pVal Pointer to attribute value + * @param[out] o_pVal Pointer to a copy of the attribute value * * return true if attribute exists and a copy was written to o_pVal */ - virtual bool getAttribute(const uint32_t i_attrId, - const uint32_t i_targetType, - const uint16_t i_pos, - const uint8_t i_unitPos, - const uint8_t i_node, - void * o_pVal) const; + bool getAttribute(const uint32_t i_attrId, + const uint32_t i_targetType, + const uint16_t i_pos, + const uint8_t i_unitPos, + const uint8_t i_node, + void * o_pVal) const; /** * @brief Serialize all Attributes into newly allocated memory chunks @@ -332,7 +634,7 @@ namespace AttributeTank * specific node (i_node) * @param[in] i_node See i_nodeFilter */ - virtual void serializeAttributes( + void serializeAttributes( const AllocType i_allocType, const uint32_t i_chunkSize, std::vector & o_attributes, @@ -349,8 +651,7 @@ namespace AttributeTank * @param[in] i_attributes Reference to AttributeSerializedChunk containing * attributes. */ - virtual void deserializeAttributes( - const AttributeSerializedChunk & i_attributes); + void deserializeAttributes(const AttributeSerializedChunk & i_attributes); /** @@ -366,9 +667,8 @@ namespace AttributeTank * * @param[in] i_echoAttributes Select whether or not to echo the attributes */ - virtual void deserializeAttributes( - const AttributeSerializedChunk & i_attributes, - bool i_echoAttributes ); + void deserializeAttributes(const AttributeSerializedChunk & i_attributes, + bool i_echoAttributes ); /** @@ -381,7 +681,7 @@ namespace AttributeTank * * return true if any attributes exist */ - virtual bool attributesExist() const { return iv_attributesExist; } + bool attributesExist() const { return iv_attributesExist; } /** * @brief Check if an attribute exists in the tank @@ -396,7 +696,7 @@ namespace AttributeTank * * return true if any attributes exist */ - virtual bool attributeExists(const uint32_t i_attrId) const; + bool attributeExists(const uint32_t i_attrId) const; /** * @brief This function writes attributes in an AttributeTank to targeting diff --git a/src/usr/targeting/common/attributeTank.C b/src/usr/targeting/common/attributeTank.C index 07ccff9820e..a9718b7890d 100644 --- a/src/usr/targeting/common/attributeTank.C +++ b/src/usr/targeting/common/attributeTank.C @@ -5,7 +5,7 @@ /* */ /* OpenPOWER HostBoot Project */ /* */ -/* Contributors Listed Below - COPYRIGHT 2013,2017 */ +/* Contributors Listed Below - COPYRIGHT 2013,2019 */ /* [+] International Business Machines Corp. */ /* */ /* */ @@ -99,10 +99,12 @@ void AttributeTank::clearAllAttributes( while (l_itr != iv_attributes.end()) { + // Get a copy of the Attribute's node for quick access + uint8_t l_node = (*l_itr)->getHeader().iv_node; if (i_nodeFilter == NODE_FILTER_NOT_ALL_NODES) { // Only clear attributes that are not for all nodes - if ((*l_itr)->iv_hdr.iv_node == ATTR_NODE_NA) + if (l_node == ATTR_NODE_NA) { l_itr++; continue; @@ -111,8 +113,8 @@ void AttributeTank::clearAllAttributes( else if (i_nodeFilter == NODE_FILTER_SPECIFIC_NODE_AND_ALL) { // Only clear attributes associated with i_node or all - if ( ((*l_itr)->iv_hdr.iv_node != ATTR_NODE_NA) && - ((*l_itr)->iv_hdr.iv_node != i_node) ) + if ( (l_node != ATTR_NODE_NA) && + (l_node != i_node) ) { l_itr++; continue; @@ -121,7 +123,7 @@ void AttributeTank::clearAllAttributes( else if (i_nodeFilter == NODE_FILTER_SPECIFIC_NODE) { // Only clear attributes associated with i_node - if ((*l_itr)->iv_hdr.iv_node != i_node) + if (l_node != i_node) { l_itr++; continue; @@ -153,13 +155,18 @@ void AttributeTank::clearNonConstAttribute(const uint32_t i_attrId, for (AttributesItr_t l_itr = iv_attributes.begin(); l_itr != iv_attributes.end(); ++l_itr) { - if ( ((*l_itr)->iv_hdr.iv_attrId == i_attrId) && - ((*l_itr)->iv_hdr.iv_targetType == i_targetType) && - ((*l_itr)->iv_hdr.iv_pos == i_pos) && - ((*l_itr)->iv_hdr.iv_unitPos == i_unitPos) && - ((*l_itr)->iv_hdr.iv_node == i_node) ) + // Get a (constant) reference to the Attribute Header + // for easy access to data members + const AttributeHeader &l_attributeHeader = (*l_itr)->getHeader(); + + // Find attribute that satisfies search criteria + if ( (l_attributeHeader.iv_attrId == i_attrId) && + (l_attributeHeader.iv_targetType == i_targetType) && + (l_attributeHeader.iv_pos == i_pos) && + (l_attributeHeader.iv_unitPos == i_unitPos) && + (l_attributeHeader.iv_node == i_node) ) { - if (!((*l_itr)->iv_hdr.iv_flags & ATTR_FLAG_CONST)) + if (!(l_attributeHeader.iv_flags & ATTR_FLAG_CONST)) { delete (*l_itr); (*l_itr) = NULL; @@ -196,20 +203,25 @@ void AttributeTank::setAttribute(const uint32_t i_attrId, for (AttributesItr_t l_itr = iv_attributes.begin(); l_itr != iv_attributes.end(); ++l_itr) { - if ( ((*l_itr)->iv_hdr.iv_attrId == i_attrId) && - ((*l_itr)->iv_hdr.iv_targetType == i_targetType) && - ((*l_itr)->iv_hdr.iv_pos == i_pos) && - ((*l_itr)->iv_hdr.iv_unitPos == i_unitPos) && - ((*l_itr)->iv_hdr.iv_node == i_node) && - ((*l_itr)->iv_hdr.iv_valSize == i_valSize) ) + // Get a reference to the Attribute Header + // for easy access to data members + const AttributeHeader &l_attributeHeader = (*l_itr)->getHeader(); + + // Find attribute that satisfies search criteria + if ( (l_attributeHeader.iv_attrId == i_attrId) && + (l_attributeHeader.iv_targetType == i_targetType) && + (l_attributeHeader.iv_pos == i_pos) && + (l_attributeHeader.iv_unitPos == i_unitPos) && + (l_attributeHeader.iv_node == i_node) && + (l_attributeHeader.iv_valSize == i_valSize) ) { // Found existing attribute, update it unless the existing attribute // is const and the new attribute is non-const - if (!( ((*l_itr)->iv_hdr.iv_flags & ATTR_FLAG_CONST) && + if (!( (l_attributeHeader.iv_flags & ATTR_FLAG_CONST) && (!(i_flags & ATTR_FLAG_CONST)) ) ) { - (*l_itr)->iv_hdr.iv_flags = i_flags; - memcpy((*l_itr)->iv_pVal, i_pVal, i_valSize); + (*l_itr)->setFlags(i_flags); + (*l_itr)->setValue(i_pVal, i_valSize); } l_found = true; break; @@ -221,15 +233,13 @@ void AttributeTank::setAttribute(const uint32_t i_attrId, // Add a new attribute to the tank Attribute * l_pAttr = new Attribute(); - l_pAttr->iv_hdr.iv_attrId = i_attrId; - l_pAttr->iv_hdr.iv_targetType = i_targetType; - l_pAttr->iv_hdr.iv_pos = i_pos; - l_pAttr->iv_hdr.iv_unitPos = i_unitPos; - l_pAttr->iv_hdr.iv_node = i_node; - l_pAttr->iv_hdr.iv_flags = i_flags; - l_pAttr->iv_hdr.iv_valSize = i_valSize; - l_pAttr->iv_pVal = new uint8_t[i_valSize]; - memcpy(l_pAttr->iv_pVal, i_pVal, i_valSize); + l_pAttr->setId(i_attrId); + l_pAttr->setTargetType(i_targetType); + l_pAttr->setPosition(i_pos); + l_pAttr->setUnitPosition(i_unitPos); + l_pAttr->setNode(i_node); + l_pAttr->setFlags(i_flags); + l_pAttr->setValue(i_pVal, i_valSize); iv_attributesExist = true; iv_attributes.push_back(l_pAttr); @@ -253,18 +263,22 @@ bool AttributeTank::getAttribute(const uint32_t i_attrId, for (AttributesCItr_t l_itr = iv_attributes.begin(); l_itr != iv_attributes.end(); ++l_itr) { - // Allow match if attribute applies to all positions - if ( ((*l_itr)->iv_hdr.iv_attrId == i_attrId) && - ((*l_itr)->iv_hdr.iv_targetType == i_targetType) && - (((*l_itr)->iv_hdr.iv_pos == ATTR_POS_NA) || - ((*l_itr)->iv_hdr.iv_pos == i_pos)) && - (((*l_itr)->iv_hdr.iv_unitPos == ATTR_UNIT_POS_NA) || - ((*l_itr)->iv_hdr.iv_unitPos == i_unitPos)) && - (((*l_itr)->iv_hdr.iv_node == ATTR_NODE_NA) || - ((*l_itr)->iv_hdr.iv_node == i_node)) ) + // Get a (constant) reference to the Attribute Header + // for easy access to data members + const AttributeHeader &l_attributeHeader = (*l_itr)->getHeader(); + + // Find attribute that satisfies search criteria + if ( (l_attributeHeader.iv_attrId == i_attrId) && + (l_attributeHeader.iv_targetType == i_targetType) && + ((l_attributeHeader.iv_pos == ATTR_POS_NA) || + (l_attributeHeader.iv_pos == i_pos)) && + ((l_attributeHeader.iv_unitPos == ATTR_UNIT_POS_NA) || + (l_attributeHeader.iv_unitPos == i_unitPos)) && + ((l_attributeHeader.iv_node == ATTR_NODE_NA) || + (l_attributeHeader.iv_node == i_node)) ) { l_found = true; - memcpy(o_pVal, (*l_itr)->iv_pVal, (*l_itr)->iv_hdr.iv_valSize); + (*l_itr)->cloneValue(o_pVal, l_attributeHeader.iv_valSize); break; } } @@ -293,10 +307,18 @@ void AttributeTank::serializeAttributes( // Fill up the buffer with as many attributes as possible while (l_itr != iv_attributes.end()) { + // Get a (constant) reference to the Attribute Header + // for easy access to data members + const AttributeHeader &l_attributeHeader = + (*l_itr)->getHeader(); + + // Get a copy of the node for quick access + uint8_t l_node = l_attributeHeader.iv_node; + if (i_nodeFilter == NODE_FILTER_NOT_ALL_NODES) { // Only want attributes that are not for all nodes - if ((*l_itr)->iv_hdr.iv_node == ATTR_NODE_NA) + if (l_node == ATTR_NODE_NA) { l_itr++; continue; @@ -305,8 +327,8 @@ void AttributeTank::serializeAttributes( else if (i_nodeFilter == NODE_FILTER_SPECIFIC_NODE_AND_ALL) { // Only want attributes associated with i_node or all - if ( ((*l_itr)->iv_hdr.iv_node != ATTR_NODE_NA) && - ((*l_itr)->iv_hdr.iv_node != i_node) ) + if ( (l_node != ATTR_NODE_NA) && + (l_node != i_node) ) { l_itr++; continue; @@ -315,15 +337,14 @@ void AttributeTank::serializeAttributes( else if (i_nodeFilter == NODE_FILTER_SPECIFIC_NODE) { // Only want attributes associated with i_node - if ((*l_itr)->iv_hdr.iv_node != i_node) + if (l_node != i_node) { l_itr++; continue; } } - if ((l_index + sizeof(AttributeHeader) + - (*l_itr)->iv_hdr.iv_valSize) > i_chunkSize) + if ((l_index + (*l_itr)->getSize()) > i_chunkSize) { // Attribute will not fit into the buffer if (l_index == 0) @@ -334,7 +355,7 @@ void AttributeTank::serializeAttributes( TRACFCOMP(g_trac_targeting, "serializeAttributes: Error, attr too big to serialize " "(0x%x)", - (*l_itr)->iv_hdr.iv_valSize); + l_attributeHeader.iv_valSize); l_itr++; } else @@ -346,17 +367,8 @@ void AttributeTank::serializeAttributes( } else { - // Copy the attribute header to the buffer - AttributeHeader * l_pHeader = - reinterpret_cast(l_pBuffer + l_index); - *l_pHeader = (*l_itr)->iv_hdr; - l_index += sizeof(AttributeHeader); - - // Copy the attribute value to the buffer - memcpy((l_pBuffer + l_index), (*l_itr)->iv_pVal, - (*l_itr)->iv_hdr.iv_valSize); - l_index += (*l_itr)->iv_hdr.iv_valSize; - + l_index += (*l_itr)->serialize(l_pBuffer + l_index, + (*l_itr)->getSize()); l_itr++; } } @@ -404,7 +416,7 @@ bool AttributeTank::attributeExists(const uint32_t i_attrId) const for (AttributesCItr_t l_itr = iv_attributes.begin(); l_itr != iv_attributes.end(); ++l_itr) { - if ((*l_itr)->iv_hdr.iv_attrId == i_attrId) + if ((*l_itr)->getHeader().iv_attrId == i_attrId) { l_found = true; break; @@ -424,60 +436,57 @@ void AttributeTank::deserializeAttributes( uint32_t l_index = 0; + // Get a handle to the serialized Attributes + uint8_t* l_serializedData = + reinterpret_cast(i_attributes.iv_pAttributes); + + // Iterate thru the Attributes while (l_index < i_attributes.iv_size) { - AttributeHeader * l_pAttrHdr = - reinterpret_cast - (i_attributes.iv_pAttributes + l_index); + // Progress the offset to the serialized data + l_serializedData += l_index; - if (sizeof(AttributeHeader) > (i_attributes.iv_size - l_index)) - { - // Remaining chunk smaller than attribute header, quit - TRACFCOMP(g_trac_targeting, - "deserializeAttributes: Error, header too big for chunk " - "(0x%x)", - (i_attributes.iv_size - l_index)); - break; - } + // Create a new Attribute + Attribute * l_pAttribute = new Attribute(); - l_index += sizeof(AttributeHeader); + // Deserialize the data, if possible + uint32_t l_deserializedDataSize = l_pAttribute->deserialize( + l_serializedData, + i_attributes.iv_size - l_index); - if (l_pAttrHdr->iv_valSize > (i_attributes.iv_size - l_index)) + if (!l_deserializedDataSize) { - // Remaining chunk smaller than attribute value, quit + // Unable to deserialize data, delete Attribute + delete l_pAttribute; + l_pAttribute = NULL; + + // Remaining chunk smaller than attribute header, quit TRACFCOMP(g_trac_targeting, - "deserializeAttributes: Error, attr too big for chunk " - "(0x%x:0x%x)", - l_pAttrHdr->iv_valSize, (i_attributes.iv_size - l_index)); + "deserializeAttributes: Error, attribute too big for " + "chunk (0x%x)", + (i_attributes.iv_size - l_index)); break; } - // Create a new Attribute and add it to the tank - Attribute * l_pAttr = new Attribute(); - l_pAttr->iv_hdr = *l_pAttrHdr; - l_pAttr->iv_pVal = new uint8_t[l_pAttrHdr->iv_valSize]; - memcpy(l_pAttr->iv_pVal, (i_attributes.iv_pAttributes + l_index), - l_pAttrHdr->iv_valSize); - - l_index += l_pAttrHdr->iv_valSize; + // Was able to deserialize data, add Attribute to the tank iv_attributesExist = true; - iv_attributes.push_back(l_pAttr); + iv_attributes.push_back(l_pAttribute); - if // attributes should be echo'd - ( i_echoAttributes == true ) + // Increment the index after deserializing an attribute + l_index += l_deserializedDataSize; + + if ( i_echoAttributes == true ) // attributes should be echo'd { // extract individual fields from attribute - uint32_t attrId = l_pAttr->iv_hdr.iv_attrId; - uint32_t targetType = l_pAttr->iv_hdr.iv_targetType; - uint16_t pos = l_pAttr->iv_hdr.iv_pos; - uint8_t unitPos = l_pAttr->iv_hdr.iv_unitPos; - - const uint8_t * pNodeFlags = (&(l_pAttr->iv_hdr.iv_unitPos)) + 1; + uint32_t attrId(l_pAttribute->getHeader().iv_attrId); + uint32_t targetType(l_pAttribute->getHeader().iv_targetType); + uint16_t pos(l_pAttribute->getHeader().iv_pos); + uint8_t unitPos(l_pAttribute->getHeader().iv_unitPos); - uint8_t node = (*pNodeFlags) >> 4; // isolate hi nibble - uint8_t flags = (*pNodeFlags) & 0x0F; // isolate lo nibble + uint8_t node(l_pAttribute->getHeader().iv_node); + uint8_t flags(l_pAttribute->getHeader().iv_flags); - uint32_t valueLen = l_pAttr->iv_hdr.iv_valSize; + uint32_t valueLen(l_pAttribute->getHeader().iv_valSize); TRACFCOMP(g_trac_targeting, "deserializeAttributes: Attribute Hdr: " @@ -488,7 +497,7 @@ void AttributeTank::deserializeAttributes( TRACFBIN(g_trac_targeting, "deserializeAttributes: Parm Value: ", - l_pAttr->iv_pVal, valueLen); + l_pAttribute->getValue(), valueLen); } // end echo attributes } @@ -504,20 +513,6 @@ void AttributeTank::deserializeAttributes( false ); } -//****************************************************************************** -AttributeTank::Attribute::Attribute() : - iv_pVal(NULL) -{ - -} - -//****************************************************************************** -AttributeTank::Attribute::~Attribute() -{ - delete[] iv_pVal; - iv_pVal = NULL; -} - //****************************************************************************** errlHndl_t AttributeTank::writePermAttributes() { @@ -526,8 +521,10 @@ errlHndl_t AttributeTank::writePermAttributes() for(AttributesCItr_t l_attrIter = iv_attributes.begin(); l_attrIter != iv_attributes.end(); ++l_attrIter) { - Attribute* l_attr = *l_attrIter; - AttributeHeader l_attrHdr = l_attr->iv_hdr; + // Get a (constant) reference to the Attribute Header + // for easy access to data members + const AttributeHeader &l_attrHdr = (*l_attrIter)->getHeader(); + PredicatePostfixExpr l_permAttrOverrides; // Predicate to match target type @@ -553,7 +550,7 @@ errlHndl_t AttributeTank::writePermAttributes() bool l_success = (*l_permTargetList)->_trySetAttr( static_cast(l_attrHdr.iv_attrId), l_attrHdr.iv_valSize, - l_attr->iv_pVal ); + (*l_attrIter)->getValue() ); if (l_success) { @@ -561,16 +558,17 @@ errlHndl_t AttributeTank::writePermAttributes() "permanent override of Attr ID:0x%X Value:0x%llX applied " "to target 0x%X", l_attrHdr.iv_attrId, - *reinterpret_cast(l_attr->iv_pVal), + *reinterpret_cast + ((*l_attrIter)->getValue()), (*l_permTargetList)->getAttr() ); } else { - uint8_t * io_pAttrData = NULL; + uint8_t * l_pAttrData(NULL); bool l_found = (*l_permTargetList)->_tryGetAttr( static_cast(l_attrHdr.iv_attrId), l_attrHdr.iv_valSize, - io_pAttrData); + l_pAttrData); if (l_found) { @@ -579,9 +577,10 @@ errlHndl_t AttributeTank::writePermAttributes() "ID:0x%X Value:0x%llX on target 0x%X - current value " "0x%llX", l_attrHdr.iv_attrId, - *reinterpret_cast(l_attr->iv_pVal), + *reinterpret_cast + ((*l_attrIter)->getValue()), (*l_permTargetList)->getAttr(), - *reinterpret_cast(io_pAttrData) ); + *reinterpret_cast(l_pAttrData) ); /*@ * @errortype * @moduleid TARG_WRITE_PERM_ATTR @@ -616,7 +615,7 @@ errlHndl_t AttributeTank::writePermAttributes() * @devdesc Given target does not have given attribute * to apply override */ - UTIL::createTracingError( + UTIL::createTracingError( TARG_WRITE_PERM_ATTR, TARG_RC_WRITE_PERM_ATTR_TARGET_FAIL, (*l_permTargetList)->getAttr(),