aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorChristophe Lombard <clombard@linux.ibm.com>2023-08-29 11:24:02 +0200
committerReza Arbab <arbab@linux.ibm.com>2023-09-12 14:22:11 -0500
commit1c2de4798d2f1952a83c193717b886ed8ecb6d7a (patch)
treeeb1876ef27c4e648672fd9379d6891b61040ef4a
parent2af83292b3e14b33d8587c711fe61a08fbe1652a (diff)
downloadskiboot-1c2de4798d2f1952a83c193717b886ed8ecb6d7a.zip
skiboot-1c2de4798d2f1952a83c193717b886ed8ecb6d7a.tar.gz
skiboot-1c2de4798d2f1952a83c193717b886ed8ecb6d7a.tar.bz2
core/pldm: Create boot progress and terminus locator in the given repo
The boot progress record will be used to report Opal's progress to the BMC during the boot. The Terminus Locator PDR forms the association between a TID and PLDM Terminus Handle for a terminus. This patch allows to add terminus locator record in the repository. Signed-off-by: Christophe Lombard <clombard@linux.ibm.com> Signed-off-by: Reza Arbab <arbab@linux.ibm.com>
-rw-r--r--core/pldm/pldm-platform-requests.c328
-rw-r--r--core/pldm/pldm.h15
2 files changed, 343 insertions, 0 deletions
diff --git a/core/pldm/pldm-platform-requests.c b/core/pldm/pldm-platform-requests.c
index 1338730..8bd373c 100644
--- a/core/pldm/pldm-platform-requests.c
+++ b/core/pldm/pldm-platform-requests.c
@@ -28,6 +28,9 @@ struct pldm_pdrs {
};
struct pldm_pdrs *pdrs;
+/* assign specific sensor/effecter IDs */
+#define PLDM_SENSOR_SE_ID_RANGE_START 0x6666
+static int sensor_effecter_id = PLDM_SENSOR_SE_ID_RANGE_START;
static void pdr_init_complete(bool success)
{
@@ -260,6 +263,287 @@ int pldm_platform_restart(void)
return set_state_effecter_states_req(effecter_id, &field, true);
}
+static int add_state_sensor_pdr(pldm_pdr *repo,
+ uint32_t *record_handle,
+ uint16_t entity_type,
+ uint16_t state_set_id,
+ uint32_t states)
+{
+ struct state_sensor_possible_states *possible_states;
+ struct pldm_state_sensor_pdr *pdr;
+ uint8_t DEFAULT_CONTAINER_ID = 0;
+ size_t state_size, pdr_size, actual_pdr_size = 0;
+ uint8_t *state_storage;
+ uint32_t swapped;
+ int rc;
+
+ /* fill in possible states structure */
+ state_size = sizeof(struct state_sensor_possible_states)
+ + sizeof(states)
+ - sizeof(bitfield8_t);
+ state_storage = zalloc(state_size);
+ if (!state_storage) {
+ prlog(PR_ERR, "failed to allocate storage data (size: 0x%lx)\n", state_size);
+ return OPAL_NO_MEM;
+ }
+
+ possible_states = (struct state_sensor_possible_states *) state_storage;
+ possible_states->state_set_id = state_set_id;
+ possible_states->possible_states_size = sizeof(states);
+
+ /* need to swap the byte order for little endian order */
+ swapped = htole32(states);
+ memcpy(possible_states->states, &swapped, sizeof(swapped));
+
+ pdr_size = sizeof(struct pldm_state_sensor_pdr) + state_size;
+ pdr = zalloc(pdr_size);
+ if (!pdr) {
+ prlog(PR_ERR, "failed to allocate sensor pdr (size: 0x%lx)\n", pdr_size);
+ free(state_storage);
+ return OPAL_NO_MEM;
+ }
+
+ /* header */
+ pdr->hdr.record_handle = 0; /* ask libpldm to fill this out */
+ pdr->hdr.version = 0; /* will be filled out by the encoder */
+ pdr->hdr.type = 0; /* will be filled out by the encoder */
+ pdr->hdr.record_change_num = 0;
+ pdr->hdr.length = 0; /* will be filled out by the encoder */
+
+ /* body */
+ pdr->terminus_handle = HOST_TID;
+ pdr->sensor_id = sensor_effecter_id++;
+ pdr->entity_type = entity_type;
+ pdr->entity_instance = 1;
+ pdr->container_id = DEFAULT_CONTAINER_ID;
+ pdr->sensor_init = PLDM_NO_INIT;
+ pdr->sensor_auxiliary_names_pdr = false;
+ pdr->composite_sensor_count = 1;
+
+ rc = encode_state_sensor_pdr(pdr, pdr_size,
+ possible_states,
+ state_size,
+ &actual_pdr_size);
+
+ if (rc != PLDM_SUCCESS) {
+ prlog(PR_ERR, "%s - Failed to encode state sensor PDR, rc: %d\n",
+ __func__, rc);
+ free(state_storage);
+ free(pdr);
+ return rc;
+ }
+
+ *record_handle = pldm_pdr_add(repo,
+ (const uint8_t *) pdr,
+ actual_pdr_size,
+ 0, false, HOST_TID);
+
+ free(state_storage);
+ free(pdr);
+
+ return OPAL_SUCCESS;
+}
+
+/*
+ * Add boot progress record in the repository.
+ */
+static uint32_t add_sensor_sw_term_pdr(pldm_pdr *repo,
+ uint32_t *record_handle)
+{
+ int rc;
+
+ rc = add_state_sensor_pdr(
+ repo,
+ record_handle,
+ PLDM_ENTITY_SYSTEM_CHASSIS,
+ PLDM_STATE_SET_SW_TERMINATION_STATUS,
+ enum_bit(PLDM_SW_TERM_NORMAL) |
+ enum_bit(PLDM_SW_TERM_GRACEFUL_SHUTDOWN_REQUESTED) |
+ enum_bit(PLDM_SW_TERM_GRACEFUL_SHUTDOWN));
+ if (rc) {
+ prlog(PR_ERR, "%s - Failed to add states sensor PDR, rc: %d\n",
+ __func__, rc);
+ return rc;
+ }
+
+ prlog(PR_DEBUG, "Add state sensor pdr (record handle: %d)\n",
+ *record_handle);
+
+ return OPAL_SUCCESS;
+}
+
+/*
+ * Add boot progress record in the repository.
+ */
+static uint32_t add_boot_progress_pdr(pldm_pdr *repo,
+ uint32_t *record_handle)
+{
+ int rc;
+
+ rc = add_state_sensor_pdr(
+ repo,
+ record_handle,
+ PLDM_ENTITY_SYS_BOARD,
+ PLDM_STATE_SET_BOOT_PROGRESS,
+ enum_bit(PLDM_STATE_SET_BOOT_PROG_STATE_COMPLETED) |
+ enum_bit(PLDM_STATE_SET_BOOT_PROG_STATE_PCI_RESORUCE_CONFIG) |
+ enum_bit(PLDM_STATE_SET_BOOT_PROG_STATE_STARTING_OP_SYS));
+ if (rc) {
+ prlog(PR_ERR, "%s - Failed to add boot progress PDR, rc: %d\n",
+ __func__, rc);
+ return rc;
+ }
+
+ prlog(PR_DEBUG, "Add boot progress pdr (record handle: %d)\n",
+ *record_handle);
+
+ return OPAL_SUCCESS;
+}
+
+static int add_state_effecter_pdr(pldm_pdr *repo,
+ uint32_t *record_handle,
+ uint16_t entity_type,
+ uint16_t state_set_id,
+ uint32_t states)
+{
+ struct state_effecter_possible_states *possible_states;
+ struct pldm_state_effecter_pdr *pdr;
+ uint8_t DEFAULT_CONTAINER_ID = 0;
+ size_t state_size, pdr_size, actual_pdr_size = 0;
+ uint8_t *state_storage;
+ uint32_t swapped;
+ int rc;
+
+ /* fill in possible states structure */
+ state_size = sizeof(struct state_effecter_possible_states)
+ + sizeof(states)
+ - sizeof(bitfield8_t);
+ state_storage = zalloc(state_size);
+ if (!state_storage) {
+ prlog(PR_ERR, "failed to allocate storage data (size: 0x%lx)\n", state_size);
+ return OPAL_NO_MEM;
+ }
+
+ possible_states = (struct state_effecter_possible_states *) state_storage;
+ possible_states->state_set_id = state_set_id;
+ possible_states->possible_states_size = sizeof(states);
+
+ /* need to swap the byte order for little endian order */
+ swapped = htole32(states);
+ memcpy(possible_states->states, &swapped, sizeof(swapped));
+
+ pdr_size = sizeof(struct pldm_state_effecter_pdr) + state_size;
+ pdr = zalloc(pdr_size);
+ if (!pdr) {
+ prlog(PR_ERR, "failed to allocate sensor pdr (size: 0x%lx)\n", pdr_size);
+ free(state_storage);
+ return OPAL_NO_MEM;
+ }
+
+ /* header */
+ pdr->hdr.record_handle = 0; /* ask libpldm to fill this out */
+ pdr->hdr.version = 0; /* will be filled out by the encoder */
+ pdr->hdr.type = 0; /* will be filled out by the encoder */
+ pdr->hdr.record_change_num = 0;
+ pdr->hdr.length = 0; /* will be filled out by the encoder */
+
+ /* body */
+ pdr->terminus_handle = HOST_TID;
+ pdr->effecter_id = sensor_effecter_id++;
+ pdr->entity_type = entity_type;
+ pdr->entity_instance = 1;
+ pdr->container_id = DEFAULT_CONTAINER_ID;
+ pdr->effecter_semantic_id = 0; /* PLDM defines no semantic IDs yet */
+ pdr->effecter_init = PLDM_NO_INIT;
+ pdr->has_description_pdr = false;
+ pdr->composite_effecter_count = 1;
+
+ rc = encode_state_effecter_pdr(pdr, pdr_size, possible_states,
+ state_size, &actual_pdr_size);
+ if (rc != PLDM_SUCCESS) {
+ prlog(PR_ERR, "%s - Failed to encode state effecter PDR, rc: %d\n",
+ __func__, rc);
+ free(state_storage);
+ free(pdr);
+ return rc;
+ }
+
+ *record_handle = pldm_pdr_add(repo,
+ (const uint8_t *) pdr,
+ actual_pdr_size,
+ 0, false, HOST_TID);
+
+ free(state_storage);
+ free(pdr);
+
+ return OPAL_SUCCESS;
+}
+
+/*
+ * Add state software termination record in the repository.
+ */
+static uint32_t add_state_sw_term_pdr(pldm_pdr *repo,
+ uint32_t *record_handle)
+{
+ int rc;
+
+ rc = add_state_effecter_pdr(
+ repo,
+ record_handle,
+ PLDM_ENTITY_SYSTEM_CHASSIS,
+ PLDM_STATE_SET_SW_TERMINATION_STATUS,
+ enum_bit(PLDM_SW_TERM_GRACEFUL_SHUTDOWN_REQUESTED));
+ if (rc) {
+ prlog(PR_ERR, "%s - Failed to add boot progress PDR, rc: %d\n",
+ __func__, rc);
+ return rc;
+ }
+
+ prlog(PR_DEBUG, "Add state software termination pdr (record handle: %d)\n",
+ *record_handle);
+
+ return OPAL_SUCCESS;
+}
+
+/*
+ * Add terminus locator record in the repository.
+ */
+static int add_terminus_locator_pdr(pldm_pdr *repo,
+ uint32_t *record_handle)
+{
+ struct pldm_terminus_locator_type_mctp_eid *locator_value;
+ struct pldm_terminus_locator_pdr pdr;
+ uint8_t DEFAULT_CONTAINER_ID = 0;
+ uint32_t size;
+
+ pdr.hdr.record_handle = 0; /* record_handle will be generated for us */
+ pdr.hdr.version = 1;
+ pdr.hdr.type = PLDM_TERMINUS_LOCATOR_PDR;
+ pdr.hdr.record_change_num = 0;
+ pdr.hdr.length = htole16(sizeof(struct pldm_terminus_locator_pdr) -
+ sizeof(struct pldm_pdr_hdr));
+ pdr.terminus_handle = htole16(HOST_TID);
+ pdr.validity = PLDM_TL_PDR_VALID;
+ pdr.tid = HOST_TID;
+ pdr.container_id = DEFAULT_CONTAINER_ID;
+ pdr.terminus_locator_type = PLDM_TERMINUS_LOCATOR_TYPE_MCTP_EID;
+ pdr.terminus_locator_value_size = sizeof(struct pldm_terminus_locator_type_mctp_eid);
+ locator_value = (struct pldm_terminus_locator_type_mctp_eid *)pdr.terminus_locator_value;
+ locator_value->eid = HOST_EID;
+
+ size = sizeof(struct pldm_terminus_locator_pdr) +
+ sizeof(struct pldm_terminus_locator_type_mctp_eid);
+
+ *record_handle = pldm_pdr_add(repo,
+ (const uint8_t *)(&pdr), size,
+ 0, false, HOST_TID);
+
+ prlog(PR_DEBUG, "Add terminus locator pdr (record handle: %d)\n",
+ *record_handle);
+
+ return OPAL_SUCCESS;
+}
+
static int send_repository_changed_event(uint32_t num_changed_pdrs,
uint32_t *record_handle)
{
@@ -384,6 +668,45 @@ static int send_repository_changed_event(uint32_t num_changed_pdrs,
return OPAL_SUCCESS;
}
+static int add_hosted_pdrs(pldm_pdr *repo)
+{
+ static uint32_t records_handle[2];
+ uint8_t hosted_pdrs = 0;
+ uint32_t record_handle;
+ int rc = OPAL_SUCCESS;
+
+ rc = add_state_sw_term_pdr(repo, &record_handle);
+ if (!rc) {
+ records_handle[hosted_pdrs] = record_handle;
+ hosted_pdrs++;
+ }
+
+ rc = add_sensor_sw_term_pdr(repo, &record_handle);
+ if (!rc) {
+ records_handle[hosted_pdrs] = record_handle;
+ hosted_pdrs++;
+ }
+
+ rc = add_boot_progress_pdr(repo, &record_handle);
+ if (!rc) {
+ records_handle[hosted_pdrs] = record_handle;
+ hosted_pdrs++;
+ }
+
+ rc = add_terminus_locator_pdr(repo, &record_handle);
+ if (!rc) {
+ records_handle[hosted_pdrs] = record_handle;
+ hosted_pdrs++;
+ }
+
+ /* tell BMC that these PDRs have changed */
+ rc = send_repository_changed_event(hosted_pdrs, records_handle);
+ if (rc)
+ prlog(PR_ERR, "%s - Failed to update hosted PDRs\n", __func__);
+
+ return rc;
+}
+
struct get_pdr_response {
uint8_t completion_code;
uint32_t next_record_hndl;
@@ -629,6 +952,11 @@ int pldm_platform_init(void)
if (rc)
goto err;
+ /* add hosted pdrs */
+ rc = add_hosted_pdrs(pdrs_repo);
+ if (rc)
+ goto err;
+
pdr_init_complete(true);
prlog(PR_DEBUG, "%s - done\n", __func__);
diff --git a/core/pldm/pldm.h b/core/pldm/pldm.h
index ee4d493..df38ce5 100644
--- a/core/pldm/pldm.h
+++ b/core/pldm/pldm.h
@@ -35,6 +35,21 @@ struct pldm_tx_data {
uint8_t data[1];
};
+/* Return an integer with a bit set in the position corresponding to
+ * the given enumeration (starting from 0 = the least significant
+ * bit) and zeroes in the other positions.
+ * Used for libpldm enumeration constants.
+ *
+ *
+ * @example enum_bit(0) = 0x00000001
+ * @example enum_bit(1) = 0x00000002
+ * @example enum_bit(4) = 0x00000010
+ */
+inline uint32_t enum_bit(unsigned int enumeration)
+{
+ return 1 << enumeration;
+}
+
struct pldm_rx_data {
struct pldm_header_info hdrinf; /* parsed message header */