@@ -10,6 +10,10 @@ bool get_fru_record_table_in_progress;
int pldm_test_verify_response(void *response_msg, size_t response_len);
int pldm_test_verify_response_fru(void *response_msg, size_t response_len);
int test_fru_table_metadata_request(void);
+int pldm_test_reply_request_fru(void *request_msg, size_t request_len,
+ void **response_msg, size_t *response_len);
+int pldm_test_generate_reply_field_type_version(uint8_t record_type, uint8_t field_type,
+ uint8_t **fru_table, size_t *fru_table_size);
/*
@@ -94,7 +98,69 @@ int pldm_test_verify_response_fru(void *response_msg, size_t response_len)
}
+int pldm_test_reply_request_fru(void *request_msg, size_t request_len,
+ void **response_msg, size_t *response_len)
+{
+ int rc, payload_len = 0;
+ uint32_t transfer_handle;
+ uint16_t fru_table_handle;
+ uint16_t record_set_identifier;
+ uint8_t record_type;
+ uint8_t field_type;
+ uint8_t transfer_op_flag;
+ uint8_t *fru_ds;
+ size_t fru_ds_size;
+
+ /* Check PLDM command and reply with appropriate reply */
+ switch (((struct pldm_msg *)request_msg)->hdr.command) {
+ case PLDM_GET_FRU_RECORD_BY_OPTION:
+ payload_len = request_len - sizeof(struct pldm_msg_hdr);
+ rc = decode_get_fru_record_by_option_req(request_msg, payload_len,
+ &transfer_handle, &fru_table_handle, &record_set_identifier,
+ &record_type, &field_type, &transfer_op_flag);
+ if (rc != PLDM_SUCCESS)
+ return OPAL_PARAMETER;
+ /*
+ * Test if field type and record type is as expected i.e.
+ * field type = PLDM_FRU_FIELD_TYPE_VERSION and
+ * record_type == PLDM_FRU_RECORD_TYPE_GENERAL
+ * else return error
+ */
+ if (field_type == PLDM_FRU_FIELD_TYPE_VERSION &&
+ record_type == PLDM_FRU_RECORD_TYPE_GENERAL) {
+
+ /*
+ * generate the fru data structure to reply request
+ * on behalf on BMC for PLDM self test
+ */
+ rc = pldm_test_generate_reply_field_type_version(
+ PLDM_FRU_RECORD_TYPE_GENERAL,
+ PLDM_FRU_FIELD_TYPE_VERSION, &fru_ds, &fru_ds_size);
+ if (rc != OPAL_SUCCESS)
+ return rc;
+
+ payload_len = fru_ds_size +
+ sizeof(struct pldm_get_fru_record_by_option_resp) - 1;
+ *response_len = sizeof(struct pldm_msg_hdr) + payload_len;
+ *response_msg = malloc(*response_len);
+
+ rc = encode_get_fru_record_by_option_resp(
+ ((struct pldm_msg *)request_msg)->hdr.instance_id,
+ PLDM_SUCCESS, PLDM_GET_NEXTPART, PLDM_START_AND_END,
+ fru_ds, fru_ds_size, *response_msg, payload_len);
+ if (rc != PLDM_SUCCESS)
+ return rc;
+ free(fru_ds);
+ return OPAL_SUCCESS;
+ } else
+ return OPAL_PARAMETER;
+ break;
+ default:
+ return PLDM_ERROR_INVALID_DATA;
+
+ }
+}
/*
* This function duplicates BMC functionality for Pldm self test
@@ -104,12 +170,15 @@ int pldm_test_verify_response_fru(void *response_msg, size_t response_len)
int pldm_test_reply_request(void *request_msg, size_t request_len,
void **response_msg, size_t *response_len)
{
- if (request_msg != NULL && response_msg != NULL) {
- (void)request_len;
- (void)*response_len;
+ switch (((struct pldm_msg *)request_msg)->hdr.type) {
+ case PLDM_FRU:
+ return pldm_test_reply_request_fru(request_msg, request_len,
+ response_msg, response_len);
+ default:
+ printf("PLDM_TEST Failed : hdr type %d not expected\n",
+ ((struct pldm_msg *)request_msg)->hdr.type);
+ return OPAL_PARAMETER;
}
- return OPAL_PARAMETER;
-
}
/*
@@ -156,12 +225,64 @@ int test_fru_table_metadata_request(void)
}
+/*
+ * This function duplicates BMC functionality for Pldm self test
+ * It generate reply for PLDM_GET_FRU_RECORD_BY_OPTION for self test.
+ * It generates fru Dta structure with BMC version tlv
+ */
+int pldm_test_generate_reply_field_type_version(uint8_t record_type, uint8_t field_type,
+ uint8_t **fru_table, size_t *fru_table_size)
+{
+ struct pldm_fru_record_tlv *tlv;
+ int tlv_size, rc;
+ size_t curr_size = 0;
+ size_t pad_bytes = 0;
+ uint32_t checksum;
+
+ if (field_type == PLDM_FRU_FIELD_TYPE_VERSION &&
+ record_type == PLDM_FRU_RECORD_TYPE_GENERAL) {
+
+ tlv_size = sizeof(struct pldm_fru_record_tlv) + strlen(TEST_BMC_VERSION) - 1;
+ tlv = malloc(tlv_size);
+ tlv->type = PLDM_FRU_FIELD_TYPE_VERSION;
+ tlv->length = strlen(TEST_BMC_VERSION);
+ memcpy(tlv->value, TEST_BMC_VERSION, tlv->length);
+
+ *fru_table_size = sizeof(struct pldm_fru_record_data_format) + tlv->length - 1;
+ /* Culculate pad bytes in fru */
+ if (*fru_table_size % 4)
+ pad_bytes = 4 - (*fru_table_size % 4);
+ else
+ pad_bytes = 0;
+
+ *fru_table = malloc(*fru_table_size + pad_bytes + sizeof(uint32_t));
+ rc = encode_fru_record(*fru_table, *fru_table_size, &curr_size, 0,
+ PLDM_FRU_RECORD_TYPE_GENERAL, 1, 1, (uint8_t *)tlv, tlv_size);
+ if (rc != PLDM_SUCCESS)
+ return OPAL_PARAMETER;
+ *fru_table_size += pad_bytes + sizeof(uint32_t);
+
+ /* Pad with 0 */
+ memset(*fru_table + curr_size, 0, pad_bytes);
+
+ checksum = htole32(pldm_crc32(*fru_table, *fru_table_size - sizeof(uint32_t)));
+ memcpy(*fru_table + curr_size + pad_bytes, (void *)&checksum, sizeof(uint32_t));
+ free(tlv);
+ } else
+ return OPAL_PARAMETER;
+
+ return OPAL_SUCCESS;
+}
+
+
+
int main(void)
{
int rc;
void *fru_record_table;
uint32_t fru_record_table_size;
+ struct variable_field fru_structure_data;
/*
* Get fru table when fru table not created
@@ -188,6 +309,19 @@ int main(void)
return rc;
}
+
+ /* retrieve the bmc information with
+ * "FRU Field Type": Version
+ * "FRU Record Set Identifier": 1,
+ * "FRU Record Type": "General(1)"
+ */
+ rc = pldm_fru_get_record_by_option(0, 1, PLDM_FRU_RECORD_TYPE_GENERAL,
+ PLDM_FRU_FIELD_TYPE_VERSION, &fru_structure_data);
+ if (rc != OPAL_SUCCESS) {
+ printf("PLDM_TEST Failed : pldm_fru_get_record_by_option return=%d\n", rc);
+ return rc;
+ }
+
return OPAL_SUCCESS;
}
This patch test PLDM command PLDM_GET_FRU_RECORD_BY_OPTION codeflow by retrieving BMC version information Signed-off-by: Abhishek Singh Tomar <abhishek@linux.ibm.com> --- core/pldm/test/test-pldm-fru.c | 144 +++++++++++++++++++++++++++++++-- 1 file changed, 139 insertions(+), 5 deletions(-)