Add defintions and function to encode FRU record

This patch adds helper API to encode a FRU record taking FRU
fields, record type, record set id, encode type as inputs and appending
the FRU record to the FRU table.

Change-Id: I789b0e3b1eebbc225291de087fa45b0d87d4944f
Signed-off-by: Tom Joseph <tomjoseph@in.ibm.com>
diff --git a/libpldm/fru.c b/libpldm/fru.c
index 82787d7..b5801d7 100644
--- a/libpldm/fru.c
+++ b/libpldm/fru.c
@@ -159,3 +159,35 @@
 
 	return PLDM_SUCCESS;
 }
+
+int encode_fru_record(uint8_t *fru_table, size_t total_size, size_t *curr_size,
+		      uint16_t record_set_id, uint8_t record_type,
+		      uint8_t num_frus, uint8_t encoding, uint8_t *tlvs,
+		      size_t tlvs_size)
+{
+	size_t record_hdr_size = sizeof(struct pldm_fru_record_data_format) -
+				 sizeof(struct pldm_fru_record_tlv);
+
+	if ((*curr_size + record_hdr_size + tlvs_size) != total_size) {
+		return PLDM_ERROR_INVALID_LENGTH;
+	}
+
+	if (fru_table == NULL || curr_size == NULL || !tlvs_size) {
+		return PLDM_ERROR_INVALID_DATA;
+	}
+
+	struct pldm_fru_record_data_format *record =
+	    (struct pldm_fru_record_data_format *)(fru_table + *curr_size);
+	record->record_set_id = htole16(record_set_id);
+	record->record_type = record_type;
+	record->num_fru_fields = num_frus;
+	record->encoding_type = encoding;
+	*curr_size += record_hdr_size;
+
+	if (tlvs) {
+		memcpy(fru_table + *curr_size, tlvs, tlvs_size);
+		*curr_size += tlvs_size;
+	}
+
+	return PLDM_SUCCESS;
+}
diff --git a/libpldm/fru.h b/libpldm/fru.h
index 8e8af25..2b5dd9f 100644
--- a/libpldm/fru.h
+++ b/libpldm/fru.h
@@ -22,6 +22,44 @@
 	PLDM_GET_FRU_RECORD_TABLE = 0X02,
 };
 
+/** @brief FRU record types
+ */
+enum pldm_fru_record_type {
+	PLDM_FRU_RECORD_TYPE_GENERAL = 0X01,
+	PLDM_FRU_RECORD_TYPE_OEM = 0XFE,
+};
+
+/** @brief Encoding type for FRU fields
+ */
+enum pldm_fru_field_encoding {
+	PLDM_FRU_ENCODING_UNSPECIFIED = 0X00,
+	PLDM_FRU_ENCODING_ASCII = 0X01,
+	PLDM_FRU_ENCODING_UTF8 = 0X02,
+	PLDM_FRU_ENCODING_UTF16 = 0X03,
+	PLDM_FRU_ENCODING_UTF16LE = 0X04,
+	PLDM_FRU_ENCODING_UTF16BE = 0X05,
+};
+
+/** @brief FRU field types
+ */
+enum pldm_fru_field_type {
+	PLDM_FRU_FIELD_TYPE_CHASSIS = 0X01,
+	PLDM_FRU_FIELD_TYPE_MODEL = 0X02,
+	PLDM_FRU_FIELD_TYPE_PN = 0X03,
+	PLDM_FRU_FIELD_TYPE_SN = 0X04,
+	PLDM_FRU_FIELD_TYPE_MANUFAC = 0X05,
+	PLDM_FRU_FIELD_TYPE_MANUFAC_DATE = 0X06,
+	PLDM_FRU_FIELD_TYPE_VENDOR = 0X07,
+	PLDM_FRU_FIELD_TYPE_NAME = 0X08,
+	PLDM_FRU_FIELD_TYPE_SKU = 0X09,
+	PLDM_FRU_FIELD_TYPE_VERSION = 0X0A,
+	PLDM_FRU_FIELD_TYPE_ASSET_TAG = 0X0B,
+	PLDM_FRU_FIELD_TYPE_DESC = 0X0C,
+	PLDM_FRU_FIELD_TYPE_EC_LVL = 0X0D,
+	PLDM_FRU_FIELD_TYPE_OTHER = 0X0E,
+	PLDM_FRU_FIELD_TYPE_IANA = 0X0F,
+};
+
 /** @struct pldm_get_fru_record_table_metadata_resp
  *
  *  Structure representing PLDM get FRU table metadata response.
@@ -61,6 +99,28 @@
 	uint8_t fru_record_table_data[1];
 } __attribute__((packed));
 
+/** @struct pldm_fru_record_tlv
+ *
+ *  Structure representing each FRU field entry (type, length, value)
+ */
+struct pldm_fru_record_tlv {
+	uint8_t type;
+	uint8_t length;
+	uint8_t value[1];
+} __attribute__((packed));
+
+/** @struct pldm_fru_record_data_format
+ *
+ *  Structure representing the FRU record data format
+ */
+struct pldm_fru_record_data_format {
+	uint16_t record_set_id;
+	uint8_t record_type;
+	uint8_t num_fru_fields;
+	uint8_t encoding_type;
+	struct pldm_fru_record_tlv tlvs[1];
+} __attribute__((packed));
+
 /* Requester */
 
 /* GetFRURecordTableMetadata */
@@ -163,6 +223,27 @@
 				     uint8_t transfer_flag,
 				     struct pldm_msg *msg);
 
+/** @brief Encode the FRU record in the FRU table
+ *
+ *  @param[in/out] fru_table - Pointer to the FRU table
+ *  @param[in] total_size - The size of the table,including the size of FRU
+ *                          record to be added to the table.
+ *  @param[in/out] curr_size - The size of the table, excluding the size of FRU
+ *                          record to be added to the table.
+ *  @param[in] record_set_id - FRU record set identifier
+ *  @param[in] record_type - FRU record type
+ *  @param[in] num_frus - Number of FRU fields
+ *  @param[in] encoding - Encoding type for FRU fields
+ *  @param[in] tlvs - Pointer to the buffer with all the FRU fields
+ *  @param[in] tlvs_size - Size of the  buffer with all the FRU fields
+ *
+ *  @return pldm_completion_codes
+ */
+int encode_fru_record(uint8_t *fru_table, size_t total_size, size_t *curr_size,
+		      uint16_t record_set_id, uint8_t record_type,
+		      uint8_t num_frus, uint8_t encoding, uint8_t *tlvs,
+		      size_t tlvs_size);
+
 #ifdef __cplusplus
 }
 #endif