diff mbox series

[v3,6/9] core/pldm/test : Initialize pldm platform specification test

Message ID 20220518074304.42497-7-abhishek@linux.ibm.com
State New
Headers show
Series Implement PLDM self test | expand

Commit Message

Abhishek Singh Tomar May 18, 2022, 7:43 a.m. UTC
PLDM Platform specification defines the functions and data
structures used for discovering, describing, initializing,
and accessing sensors and effecters within the management
controllers and management devices of a platform management
subsystem.

This patch test PLDM platform Init implementation
using commands
1. PLDM_PLATFORM_EVENT_MESSAGE
2. PLDM_GET_PDR

Signed-off-by: Abhishek Singh Tomar<abhishek@linux.ibm.com>
---
 core/pldm/test/Makefile.check       |   3 +-
 core/pldm/test/test-pldm-platform.c | 298 ++++++++++++++++++++++++++++
 2 files changed, 300 insertions(+), 1 deletion(-)
 create mode 100644 core/pldm/test/test-pldm-platform.c
diff mbox series

Patch

diff --git a/core/pldm/test/Makefile.check b/core/pldm/test/Makefile.check
index c63b3eeb..0e5706a2 100644
--- a/core/pldm/test/Makefile.check
+++ b/core/pldm/test/Makefile.check
@@ -1,6 +1,7 @@ 
 # -*-Makefile-*-
 PLDM_TEST := core/pldm/test/test-pldm-fileio \
-	     core/pldm/test/test-pldm-bios
+	     core/pldm/test/test-pldm-bios \
+	     core/pldm/test/test-pldm-platform
 
 LCOV_EXCLUDE += $(PLDM_TEST:%=%.c)
 
diff --git a/core/pldm/test/test-pldm-platform.c b/core/pldm/test/test-pldm-platform.c
new file mode 100644
index 00000000..8c852ad7
--- /dev/null
+++ b/core/pldm/test/test-pldm-platform.c
@@ -0,0 +1,298 @@ 
+// SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later
+// Copyright 2022 IBM Corp.
+
+#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 structure duplicates 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 structure duplicates 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);
+
+/*
+ * This function duplicates 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 duplicates BMC functionality for Pldm self test
+ * This generate pdr entry for self test
+ */
+int get_test_pdr_entry(uint32_t record_hndl, uint8_t **pdr, size_t *pdr_len)
+{
+	int size;
+	int rc;
+	size_t possible_states_size = 0;
+	struct pldm_state_effecter_pdr *effecter = NULL;
+	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);
+	if (*pdr == NULL) {
+		perror("PLDM_TEST malloc");
+		return OPAL_RESOURCE;
+	}
+	memset(*pdr, 0, size);
+	effecter = (struct pldm_state_effecter_pdr *)(*pdr);
+	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;
+
+	/* For PLDM Test consider only 1 possible state */
+	possible_states_size = sizeof(struct state_effecter_possible_states)
+		+ possible_states_effecter_test->possible_states_size - 1;
+
+	rc = encode_state_effecter_pdr(effecter, size, possible_states_effecter_test,
+			possible_states_size, pdr_len);
+	if (rc != PLDM_SUCCESS)
+		return OPAL_PARAMETER;
+
+	return OPAL_SUCCESS;
+
+}
+
+/*
+ * This function duplicates BMC functionality for Pldm self test
+ * it 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_PLATFORM
+ */
+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 : hdr type %d not expected\n",
+				 ((struct pldm_msg *)request_msg)->hdr.type);
+		return OPAL_PARAMETER;
+	}
+
+
+}
+
+
+
+/*
+ * This function duplicates BMC functionality for Pldm self test
+ * it 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)
+{
+	uint8_t *pdr = NULL;
+	size_t pdr_len;
+	int rc = 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;
+	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);
+		rc = decode_get_pdr_req(request_msg, payload_len, &record_hndl, &transfer_handle,
+				&transfer_opflag, &request_cnt, &record_chg_num);
+		if (rc != PLDM_SUCCESS)
+			return rc;
+
+		/* Get pdr entry for self test */
+		rc = get_test_pdr_entry(record_hndl, &pdr, &pdr_len);
+		if (rc != OPAL_SUCCESS)
+			return rc;
+
+		payload_len = (sizeof(struct pldm_get_pdr_resp) - 1)
+			+ pdr_len;
+		*response_len = sizeof(struct pldm_msg_hdr)
+			+ payload_len;
+
+		*response_msg = malloc(*response_len);
+		if (*response_msg == NULL) {
+			perror("PLDM_TEST malloc");
+			return OPAL_RESOURCE;
+		}
+
+		/*
+		 * if record_handle is equal to first record handle or 0
+		 * then encode next data transfer handle with 2nd record handle
+		 */
+		if (record_hndl == EFFECTER1_RECORD_HANDLE || record_hndl == 0) {
+			rc = encode_get_pdr_resp(((struct pldm_msg *)request_msg)->hdr.instance_id,
+					PLDM_SUCCESS, EFFECTER2_RECORD_HANDLE,
+					PLDM_GET_NEXTPART, PLDM_START_AND_END, pdr_len, 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) {
+			rc = encode_get_pdr_resp(((struct pldm_msg *)request_msg)->hdr.instance_id,
+					PLDM_SUCCESS, 0, PLDM_GET_NEXTPART, PLDM_START_AND_END,
+					pdr_len, pdr, 0, *response_msg);
+		} else
+			return OPAL_PARAMETER;
+
+		if (rc != PLDM_SUCCESS)
+			return OPAL_PARAMETER;
+		free(pdr);
+		break;
+
+	case PLDM_PLATFORM_EVENT_MESSAGE:
+		payload_len = request_len - sizeof(struct pldm_msg_hdr);
+		rc = decode_platform_event_message_req(request_msg, payload_len, &format_version,
+				&tid, &event_class, &event_data_offset);
+		if (rc != PLDM_SUCCESS)
+			return OPAL_PARAMETER;
+
+		/* 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);
+		if (*response_msg == NULL) {
+			perror("PLDM_TEST malloc");
+			return OPAL_RESOURCE;
+		}
+
+		rc = encode_platform_event_message_resp(
+				((struct pldm_msg *)request_msg)->hdr.instance_id,
+				PLDM_SUCCESS, 0, *response_msg);
+		if (rc != PLDM_SUCCESS)
+			return OPAL_PARAMETER;
+
+		return PLDM_SUCCESS;
+
+	default:
+		return OPAL_PARAMETER;
+
+	}
+
+	return OPAL_SUCCESS;
+
+}
+
+
+int main(void)
+{
+	int rc;
+
+
+	/* Inittialize pldm platform */
+	rc = pldm_platform_init();
+	if (rc != OPAL_SUCCESS) {
+		printf("PLDM_TEST failed : pldm_platform_init ends with %d\n", rc);
+		return rc;
+	}
+
+
+	return PLDM_SUCCESS;
+}
+
+