diff options
-rw-r--r-- | core/pldm/Makefile.inc | 2 | ||||
-rw-r--r-- | core/pldm/pldm-fru-requests.c | 147 | ||||
-rw-r--r-- | core/pldm/pldm-mctp.c | 4 | ||||
-rw-r--r-- | core/pldm/pldm.h | 2 |
4 files changed, 153 insertions, 2 deletions
diff --git a/core/pldm/Makefile.inc b/core/pldm/Makefile.inc index e4135ac..0b54b7e 100644 --- a/core/pldm/Makefile.inc +++ b/core/pldm/Makefile.inc @@ -9,7 +9,7 @@ CPPFLAGS += -I$(SRC)/pldm/include/libpldm/oem/ibm/ PLDM_OBJS = pldm-mctp.o pldm-responder.o pldm-requester.o PLDM_OBJS += pldm-base-requests.o pldm-platform-requests.o -PLDM_OBJS += pldm-bios-requests.o +PLDM_OBJS += pldm-bios-requests.o pldm-fru-requests.o PLDM = $(PLDM_DIR)/built-in.a $(PLDM): $(PLDM_OBJS:%=$(PLDM_DIR)/%) diff --git a/core/pldm/pldm-fru-requests.c b/core/pldm/pldm-fru-requests.c new file mode 100644 index 0000000..ae1d9fa --- /dev/null +++ b/core/pldm/pldm-fru-requests.c @@ -0,0 +1,147 @@ +// SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later +// Copyright 2022 IBM Corp. + +#define pr_fmt(fmt) "PLDM: " fmt + +#include <cpu.h> +#include <opal.h> +#include <stdio.h> +#include <string.h> +#include <inttypes.h> +#include <libpldm/fru.h> +#include "pldm.h" + +static void *fru_record_table; +static size_t fru_record_length; + +static bool fru_ready; + +static void fru_init_complete(bool success) +{ + /* Read not successful, error out and free the buffer */ + if (!success) { + fru_ready = false; + + if (fru_record_table != NULL) { + free(fru_record_table); + fru_record_length = 0; + } + return; + } + + /* Mark ready */ + fru_ready = true; +} + +static int get_fru_record_table_req(void **record_table_data, + size_t *record_table_length) +{ + size_t data_size = PLDM_MSG_SIZE(struct pldm_get_fru_record_table_req); + uint8_t transfer_flag, completion_code; + size_t response_len, payload_len; + struct pldm_tx_data *tx = NULL; + uint32_t next_transfer_handle; + uint8_t *table_data; + size_t table_length; + void *response_msg; + int rc = OPAL_SUCCESS; + + struct pldm_get_fru_record_table_req fru_record_table_req = { + .data_transfer_handle = 0, /* (0 if operation op is FIRSTPART) */ + .transfer_operation_flag = PLDM_GET_FIRSTPART, + }; + payload_len = sizeof(struct pldm_get_fru_record_table_req); + + /* Encode the file table request */ + tx = zalloc(sizeof(struct pldm_tx_data) + data_size); + if (!tx) + return OPAL_NO_MEM; + tx->data_size = data_size; + + rc = encode_get_fru_record_table_req( + DEFAULT_INSTANCE_ID, + fru_record_table_req.data_transfer_handle, + fru_record_table_req.transfer_operation_flag, + (struct pldm_msg *)tx->data, + payload_len); + if (rc != PLDM_SUCCESS) { + prlog(PR_ERR, "Encode GetFruRecordTableReq Error, rc: %d\n", rc); + free(tx); + return OPAL_PARAMETER; + } + + /* Send and get the response message bytes */ + rc = pldm_requester_queue_and_wait(tx, &response_msg, &response_len); + if (rc) { + prlog(PR_ERR, "Communication Error, req: GetFruRecordTableReq, rc: %d\n", rc); + free(tx); + return rc; + } + + /* Decode the message */ + payload_len = response_len - sizeof(struct pldm_msg_hdr); + table_data = zalloc(payload_len); + if (!table_data) { + free(tx); + return OPAL_NO_MEM; + } + + rc = decode_get_fru_record_table_resp( + response_msg, + payload_len, + &completion_code, + &next_transfer_handle, + &transfer_flag, + table_data, + &table_length); + if (rc != PLDM_SUCCESS || completion_code != PLDM_SUCCESS) { + prlog(PR_ERR, "Decode GetFruRecordTableReq Error, rc: %d, cc: %d\n", + rc, completion_code); + rc = OPAL_PARAMETER; + goto out; + } + + /* we do not support multipart transfer */ + if ((next_transfer_handle != PLDM_GET_NEXTPART) || + (transfer_flag != PLDM_START_AND_END)) { + prlog(PR_ERR, "Transfert GetFruRecordTableReq not complete, " + "transfer_hndl: %d, transfer_flag: %d\n", + next_transfer_handle, + transfer_flag); + rc = OPAL_PARAMETER; + goto out; + } + + *record_table_length = table_length; + *record_table_data = zalloc(table_length); + if (!record_table_data) + rc = OPAL_NO_MEM; + else + memcpy(*record_table_data, table_data, table_length); + +out: + free(tx); + free(table_data); + free(response_msg); + return rc; +} + +int pldm_fru_init(void) +{ + int rc; + + /* get fru record table */ + rc = get_fru_record_table_req(&fru_record_table, + &fru_record_length); + if (rc) + goto err; + + fru_init_complete(true); + prlog(PR_DEBUG, "%s - done\n", __func__); + + return OPAL_SUCCESS; + +err: + fru_init_complete(false); + return rc; +} diff --git a/core/pldm/pldm-mctp.c b/core/pldm/pldm-mctp.c index 6003b66..b31587f 100644 --- a/core/pldm/pldm-mctp.c +++ b/core/pldm/pldm-mctp.c @@ -74,7 +74,7 @@ out: int pldm_mctp_init(void) { - int nbr_elt = 6, rc = OPAL_SUCCESS; + int nbr_elt = 7, rc = OPAL_SUCCESS; int (*pldm_config[])(void) = { ast_mctp_init, /* MCTP Binding */ @@ -83,6 +83,7 @@ int pldm_mctp_init(void) pldm_base_get_tid_req, /* Get BMC tid */ pldm_platform_init, /* Get PDRs data */ pldm_bios_init, /* Get Bios data */ + pldm_fru_init, /* Get Fru data */ }; const char *pldm_config_error[] = { @@ -92,6 +93,7 @@ int pldm_mctp_init(void) "Failed to retrieve BMC Tid", "Failed to retrieve Data Records", "Failed to retrieve Bios data", + "Failed to retrieve Fru data", }; prlog(PR_NOTICE, "%s - Getting PLDM data\n", __func__); diff --git a/core/pldm/pldm.h b/core/pldm/pldm.h index 0601349..dbc19ab 100644 --- a/core/pldm/pldm.h +++ b/core/pldm/pldm.h @@ -52,6 +52,8 @@ int pldm_responder_handle_request(struct pldm_rx_data *rx); int pldm_responder_init(void); /* Requester support */ +int pldm_fru_init(void); + int pldm_bios_find_lid_by_attr_name(const char *name, char **lid); int pldm_bios_get_lids_id(char **lid_ids_string); int pldm_bios_init(void); |