@@ -1,6 +1,7 @@
# -*-Makefile-*-
PLDM_TEST := core/pldm/test/test_pldm-fileio \
core/pldm/test/test_pldm-bios \
+ core/pldm/test/test_pldm-platform \
LCOV_EXCLUDE += $(PLDM_TEST:%=%.c)
@@ -132,12 +132,15 @@ int ast_mctp_message_tx(uint8_t eid, uint8_t *msg, int len)
&response_msg, &response_len);
if (ret != PLDM_SUCCESS)
return ret;
- vmsg = malloc(response_len+1);
- // TYPE: PLDM = 0x01 (000_0001b) as per MCTP - DSP0240
- vmsg[0] = 0x01;
- memcpy(vmsg + 1, response_msg, response_len);
-
- pldm_rx_message(BMC_EID, 0, 0, NULL, vmsg, response_len+1);
+ // If response length > 0 then response back
+ if (response_len > 0) {
+ vmsg = malloc(response_len+1);
+
+ // TYPE: PLDM = 0x01 (000_0001b) as per MCTP - DSP0240
+ vmsg[0] = 0x01;
+ memcpy(vmsg + 1, response_msg, response_len);
+ pldm_rx_message(BMC_EID, 0, 0, NULL, vmsg, response_len+1);
+ }
}
return PLDM_SUCCESS;
new file mode 100644
@@ -0,0 +1,353 @@
+#include "common/test_pldm-common.c"
+
+
+#define EFFECTER1_RECORD_HANDLE 120
+#define EFFECTER1_POSSIBLE_STATES PLDM_SW_TERM_GRACEFUL_RESTART_REQUESTED
+#define EFFECTER2_RECORD_HANDLE 160
+#define EFFECTER2_POSSIBLE_STATES PLDM_STATE_SET_SYSTEM_POWER_STATE
+
+
+/*
+ * These stucturs duplicate BMC functionality for Pldm self test
+ * It include PDR 1st entry to be send on behalf of BMC
+ */
+struct pldm_state_effecter_pdr effecter_test_1 = {
+ .hdr = {
+ .record_handle = EFFECTER1_RECORD_HANDLE
+ },
+ .terminus_handle = 1,
+ .effecter_id = 38,
+ .entity_type = PLDM_ENTITY_SYS_FIRMWARE,
+ .entity_instance = 1,
+ .container_id = 1,
+ .effecter_semantic_id = 0,
+ .effecter_init = 0,
+ .has_description_pdr = 0,
+ .composite_effecter_count = 1
+};
+struct state_effecter_possible_states possible_states_effecter_1_test = {
+ .state_set_id = PLDM_STATE_SET_SW_TERMINATION_STATUS,
+ .possible_states_size = 1,
+ .states = {
+ {.byte = PLDM_SW_TERM_GRACEFUL_RESTART_REQUESTED}
+ }
+
+};
+
+
+/*
+ * These stucturs duplicate BMC functionality for Pldm self test
+ * It include PDR 2nd entry to be send on behalf of BMC
+ */
+struct pldm_state_effecter_pdr effecter_test_2 = {
+ .hdr = {
+ .record_handle = EFFECTER2_RECORD_HANDLE
+ },
+ .terminus_handle = 1,
+ .effecter_id = 38,
+ .entity_type = PLDM_ENTITY_SYSTEM_CHASSIS,
+ .entity_instance = 1,
+ .container_id = 1,
+ .effecter_semantic_id = 0,
+ .effecter_init = 0,
+ .has_description_pdr = 0,
+ .composite_effecter_count = 1
+};
+struct state_effecter_possible_states possible_states_effecter_2_test = {
+ .state_set_id = PLDM_STATE_SET_SYSTEM_POWER_STATE,
+ .possible_states_size = 1,
+ .states = {
+ {.byte = PLDM_STATE_SET_SYS_POWER_STATE_OFF_SOFT_GRACEFUL}
+ }
+};
+
+
+int pldm_test_reply_request(void *request_msg, size_t request_len,
+ void **response_msg, size_t *response_len);
+int pldm_test_reply_request_platform(void *request_msg, size_t request_len,
+ void **response_msg, size_t *response_len);
+uint32_t test_pdr_entry_generate(uint8_t **pdr, uint32_t record_hndl);
+
+
+/*
+ * This function tries to duplicate BMC functionality for Pldm self test
+ * It will handle pldm response message
+ * For now we don't have any response
+ */
+int pldm_test_verify_response(void *response_msg, size_t response_len)
+{
+ if (response_len > 0 || response_msg != NULL)
+ return OPAL_PARAMETER;
+ return OPAL_PARAMETER;
+
+}
+
+/*
+ * This function tries to duplicate BMC functionality for Pldm self test
+ * This Genrate pdr entry for self test
+ */
+uint32_t test_pdr_entry_generate(uint8_t **pdr,
+ uint32_t record_hndl)
+{
+ int size;
+ size_t possible_states_size = 0;
+ struct pldm_state_effecter_pdr *effecter = NULL;
+ size_t actual_size;
+ struct pldm_state_effecter_pdr *effecter_test;
+ struct state_effecter_possible_states *possible_states_effecter_test;
+
+
+ // calculate sizeof whole struct
+ size = sizeof(struct pldm_state_effecter_pdr)
+ + sizeof(struct state_effecter_possible_states) - 1;
+
+ if (record_hndl == 0) {
+ effecter_test = &effecter_test_1;
+ possible_states_effecter_test = &possible_states_effecter_1_test;
+ } else if (record_hndl == effecter_test_1.hdr.record_handle) {
+ effecter_test = &effecter_test_1;
+ possible_states_effecter_test = &possible_states_effecter_1_test;
+ } else if (record_hndl == effecter_test_2.hdr.record_handle) {
+ effecter_test = &effecter_test_2;
+ possible_states_effecter_test = &possible_states_effecter_2_test;
+ } else
+ return OPAL_PARAMETER;
+
+
+ *pdr = malloc(size);
+ memset(*pdr, 0, size);
+ effecter = (struct pldm_state_effecter_pdr *)(*pdr);
+ if (effecter == NULL) {
+ perror("malloc");
+ exit(EXIT_FAILURE);
+ }
+ effecter->terminus_handle = effecter_test->terminus_handle;
+ effecter->effecter_id = effecter_test->effecter_id;
+ effecter->entity_type = effecter_test->entity_type;
+ effecter->entity_instance = effecter_test->entity_instance;
+ effecter->container_id = effecter_test->container_id;
+ effecter->effecter_semantic_id = effecter_test->effecter_semantic_id;
+ effecter->effecter_init = effecter_test->effecter_init;
+ effecter->has_description_pdr = effecter_test->has_description_pdr;
+ effecter->composite_effecter_count = effecter_test->composite_effecter_count;
+
+ // consider only 1 possible state
+ possible_states_size = sizeof(struct state_effecter_possible_states)
+ + possible_states_effecter_test->possible_states_size - 1;
+ encode_state_effecter_pdr(effecter, size,
+ possible_states_effecter_test,
+ possible_states_size, &actual_size);
+
+ return actual_size;
+
+}
+
+/*
+ * This function tries to duplicate BMC functionality for Pldm self test
+ * it tries to handle PLDM_REQUEST for PLDM_PLATFORM and reply with appropriate
+ * PLDM_RESPONSE message
+ * As pldm platfom test it will have only pldm request of type = PLDM_BIOS
+ */
+int pldm_test_reply_request(void *request_msg, size_t request_len,
+ void **response_msg, size_t *response_len)
+{
+
+ switch (((struct pldm_msg *)request_msg)->hdr.type) {
+ case PLDM_PLATFORM:
+ return pldm_test_reply_request_platform(request_msg, request_len,
+ response_msg, response_len);
+
+ default:
+ printf("PLDM_TEST: Not equal to PLDM_PLATFORM\n");
+ return OPAL_PARAMETER;
+ }
+
+
+}
+
+
+
+/*
+ * This function tries to duplicate BMC functionality for Pldm self test
+ * it tries to handle PLDM_REQUEST for PLDM_PLATFORM and reply with appropriate
+ * PLDM_RESPONSE message
+ */
+int pldm_test_reply_request_platform(void *request_msg, size_t request_len,
+ void **response_msg, size_t *response_len)
+{
+ //int size = 0;
+ uint8_t *pdr = NULL;
+ int ret = 0;
+ int payload_len = 0;
+ uint32_t transfer_handle;
+ uint8_t transfer_opflag;
+ uint16_t request_cnt;
+ uint16_t record_chg_num;
+ uint32_t record_hndl;
+ uint16_t effecter_id;
+ uint8_t comp_effecter_count;
+ set_effecter_state_field field;
+ uint8_t format_version, tid, event_class;
+ size_t event_data_offset;
+
+// check pldm command received and reply with appropriate pldm response message
+ switch (((struct pldm_msg *)request_msg)->hdr.command) {
+ case PLDM_GET_PDR:
+
+ payload_len = request_len - sizeof(struct pldm_msg_hdr);
+ ret = decode_get_pdr_req(request_msg, payload_len, &record_hndl, &transfer_handle,
+ &transfer_opflag, &request_cnt, &record_chg_num);
+ if (ret != PLDM_SUCCESS)
+ return ret;
+
+ // Generate pdr entry for self test
+ ret = test_pdr_entry_generate(&pdr, record_hndl);
+ if (ret < PLDM_SUCCESS)
+ return ret;
+ payload_len = (sizeof(struct pldm_get_pdr_resp) - 1)
+ + ret;
+ *response_len = sizeof(struct pldm_msg_hdr)
+ + payload_len;
+ *response_msg = malloc(*response_len);
+
+ // if record_handle is equal to first record handle or 0
+ // the encode next data transfer handle with 2nd record handle
+ if (record_hndl == EFFECTER1_RECORD_HANDLE || record_hndl == 0) {
+ ret = encode_get_pdr_resp(((struct pldm_msg *)request_msg)->hdr.instance_id,
+ PLDM_SUCCESS, EFFECTER2_RECORD_HANDLE,
+ PLDM_GET_NEXTPART, PLDM_START_AND_END, ret, pdr, 0,
+ *response_msg);
+ }
+ // if record_handle is equal to last record handle
+ // the encode next data transfer handle with 0
+ else if (record_hndl == EFFECTER2_RECORD_HANDLE) {
+ ret = encode_get_pdr_resp(((struct pldm_msg *)request_msg)->hdr.instance_id,
+ PLDM_SUCCESS, 0, PLDM_GET_NEXTPART, PLDM_START_AND_END,
+ ret, pdr, 0, *response_msg);
+ } else
+ return OPAL_PARAMETER;
+
+ free(pdr);
+ if (ret != PLDM_SUCCESS)
+ return ret;
+ break;
+ case PLDM_SET_STATE_EFFECTER_STATES:
+
+ payload_len = request_len - sizeof(struct pldm_msg_hdr);
+ ret = decode_set_state_effecter_states_req(request_msg, payload_len, &effecter_id,
+ &comp_effecter_count, &field);
+
+ // Test if request received from same effecter id passed
+ // and also check field struct same as expected
+ if (
+ (
+ effecter_id == effecter_test_1.effecter_id &&
+ field.effecter_state ==
+ possible_states_effecter_1_test.states->byte &&
+ field.set_request == PLDM_REQUEST_SET &&
+ field.effecter_state == PLDM_SW_TERM_GRACEFUL_RESTART_REQUESTED
+
+ ) ||
+ (
+ effecter_id == effecter_test_2.effecter_id &&
+ field.effecter_state ==
+ possible_states_effecter_2_test.states->byte &&
+ field.set_request == PLDM_REQUEST_SET &&
+ field.effecter_state ==
+ PLDM_STATE_SET_SYS_POWER_STATE_OFF_SOFT_GRACEFUL
+ )
+ ) {
+ // BMC doesn't answer for these specific effecter states
+ // (PLDM_SW_TERM_GRACEFUL_RESTART and PLDM_STATE_SET_SYS_POWER_STATE_OFF)
+ // hence *response len = 0
+ *response_len = 0;
+ return PLDM_SUCCESS;
+ } else
+ return OPAL_PARAMETER;
+ return PLDM_SUCCESS;
+
+ case PLDM_PLATFORM_EVENT_MESSAGE:
+ payload_len = request_len - sizeof(struct pldm_msg_hdr);
+ ret = decode_platform_event_message_req(request_msg, payload_len, &format_version,
+ &tid, &event_class, &event_data_offset);
+
+ // Test: if tid and event class same as that expected
+ if (tid != HOST_TID || event_class != PLDM_PDR_REPOSITORY_CHG_EVENT)
+ return OPAL_PARAMETER;
+
+ *response_len = sizeof(struct pldm_msg_hdr) +
+ sizeof(struct pldm_platform_event_message_resp);
+ *response_msg = malloc(*response_len);
+ ret = encode_platform_event_message_resp(
+ ((struct pldm_msg *)request_msg)->hdr.instance_id,
+ PLDM_SUCCESS, 0, *response_msg);
+ return PLDM_SUCCESS;
+
+
+
+ default:
+ return PLDM_ERROR_INVALID_DATA;
+
+ }
+
+ return PLDM_SUCCESS;
+
+
+
+}
+
+
+int main(void)
+{
+ int ret;
+
+// Attempt to call pldm_platform_restart()
+// before pldm_platform_init() return error
+// OPAL_HARDWARE
+ ret = pldm_platform_restart();
+ printf("pldm_platform_restart ends with %d\n", ret);
+ if (ret != OPAL_HARDWARE) {
+ perror("pldm_platform_restart");
+ return ret;
+ }
+
+
+// Attempt to call pldm_platform_power_off()
+// before pldm_platform_init() return error
+// OPAL_HARDWARE
+ ret = pldm_platform_power_off();
+ printf("pldm_platform_power_off ends with %d\n", ret);
+ if (ret != OPAL_HARDWARE) {
+ perror("pldm_platform_restart");
+ return ret;
+ }
+
+// Inittialize pldm platform
+ ret = pldm_platform_init();
+ printf("pldm_platform_init ends with %d\n", ret);
+ if (ret != PLDM_SUCCESS) {
+ perror("pldm_platform_init");
+ return ret;
+ }
+
+
+// Attempt to call pldm_platform_restart()
+// after pldm_platform_init() return PLDM_SUCCESS
+ ret = pldm_platform_restart();
+ printf("pldm_platform_restart ends with %d\n", ret);
+ if (ret != PLDM_SUCCESS) {
+ perror("pldm_platform_restart");
+ return ret;
+ }
+
+// Attempt to call pldm_platform_power_off()
+// after pldm_platform_init() return PLDM_SUCCESS
+ ret = pldm_platform_power_off();
+ printf("pldm_platform_power_off ends with %d\n", ret);
+ if (ret != PLDM_SUCCESS) {
+ perror("pldm_platform_restart");
+ return ret;
+ }
+}
+
+
The self test for PLDM platform message implementation Signed-off-by: Abhishek Singh Tomar <abhishek@linux.ibm.com> --- core/pldm/test/Makefile.check | 1 + core/pldm/test/common/test_pldm-common.c | 15 +- core/pldm/test/test_pldm-platform.c | 353 +++++++++++++++++++++++ 3 files changed, 363 insertions(+), 6 deletions(-) create mode 100644 core/pldm/test/test_pldm-platform.c