diff mbox series

[V6,16/21] core/pldm: PLDM for FRU data Specification

Message ID 20220913102705.65506-17-clombard@linux.vnet.ibm.com
State Superseded
Headers show
Series Implement MCTP and PLDM features | expand

Commit Message

Christophe Lombard Sept. 13, 2022, 10:27 a.m. UTC
Specification, defines a FRU data format that provides platform asset
information including part number, serial number and manufacturer.

Use the GetFruRecordByOptionReq command to get specific FRU (Field
Replaceable Unit) record according the Record Set Identifier, the Record
Type and the field Type.

Signed-off-by: Christophe Lombard <clombard@linux.vnet.ibm.com>
---
 core/pldm/Makefile.inc        |   2 +-
 core/pldm/pldm-fru-requests.c | 136 ++++++++++++++++++++++++++++++++++
 core/pldm/pldm-mctp.c         |   9 ++-
 core/pldm/pldm.h              |   2 +
 4 files changed, 147 insertions(+), 2 deletions(-)
 create mode 100644 core/pldm/pldm-fru-requests.c

Comments

Abhishek Singh Tomar Sept. 29, 2022, 5:07 p.m. UTC | #1
On Tue, Sep 13, 2022 at 12:27:00PM +0200, Christophe Lombard wrote:
> Specification, defines a FRU data format that provides platform asset
> information including part number, serial number and manufacturer.
> 
> Use the GetFruRecordByOptionReq command to get specific FRU (Field
> Replaceable Unit) record according the Record Set Identifier, the Record
> Type and the field Type.
> 
> Signed-off-by: Christophe Lombard <clombard@linux.vnet.ibm.com>
Reviewed-by: Abhishek Singh Tomar <abhishek@linux.ibm.com>
> ---
>  core/pldm/Makefile.inc        |   2 +-
>  core/pldm/pldm-fru-requests.c | 136 ++++++++++++++++++++++++++++++++++
>  core/pldm/pldm-mctp.c         |   9 ++-
>  core/pldm/pldm.h              |   2 +
>  4 files changed, 147 insertions(+), 2 deletions(-)
>  create mode 100644 core/pldm/pldm-fru-requests.c
> 
> diff --git a/core/pldm/Makefile.inc b/core/pldm/Makefile.inc
> index 42645427..4d08e371 100644
> --- a/core/pldm/Makefile.inc
> +++ b/core/pldm/Makefile.inc
> @@ -12,7 +12,7 @@ CFLAGS_$(PLDM_DIR)/pldm-bios-requests.o = -Wno-strict-prototypes
> 
>  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 00000000..02c9b968
> --- /dev/null
> +++ b/core/pldm/pldm-fru-requests.c
> @@ -0,0 +1,136 @@
> +// 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 <pldm/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)
> +{
> +	char request_msg[PKT_SIZE(struct pldm_get_fru_record_table_req)];
> +	uint8_t transfer_flag, completion_code;
> +	size_t response_len, payload_len;
> +	uint32_t next_transfer_handle;
> +	uint8_t *table_data;
> +	size_t table_length;
> +	void *response_msg;
> +	int rc;
> +
> +	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 */
> +	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 *)request_msg,
> +			payload_len);
> +	if (rc != PLDM_SUCCESS) {
> +		prlog(PR_ERR, "Encode GetFruRecordTableReq Error, rc: %d\n", rc);
> +		return OPAL_PARAMETER;
> +	}
> +
> +	/* Send and get the response message bytes */
> +	rc = pldm_requester_queue_and_wait(request_msg, sizeof(request_msg),
> +					   &response_msg, &response_len);
> +	if (rc) {
> +		prlog(PR_ERR, "Communication Error, req: GetFruRecordTableReq, rc: %d\n", rc);
> +		return rc;
> +	}
> +
> +	/* Decode the message */
> +	payload_len = response_len - sizeof(struct pldm_msg_hdr);
> +	table_data = zalloc(payload_len);
> +
> +	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);
> +
> +		free(table_data);
> +		free(response_msg);
> +		return OPAL_PARAMETER;
> +	}
> +
> +	/* 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);
> +
> +		free(table_data);
> +		free(response_msg);
> +		return OPAL_PARAMETER;
> +	}
> +
> +	*record_table_length = table_length;
> +	*record_table_data = zalloc(table_length);
> +	memcpy(*record_table_data, table_data, table_length);
> +
> +	free(table_data);
> +	free(response_msg);
> +
> +	return OPAL_SUCCESS;
> +}
> +
> +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 ff4f71c3..542edc27 100644
> --- a/core/pldm/pldm-mctp.c
> +++ b/core/pldm/pldm-mctp.c
> @@ -148,8 +148,15 @@ int pldm_mctp_init(uint8_t mode)
> 
>  	/* Get Bios data */
>  	rc = pldm_bios_init();
> -	if (rc)
> +	if (rc) {
>  		prlog(PR_ERR, "Failed to retrieve Bios data\n");
> +		goto out;
> +	}
> +
> +	/* Get Fru data */
> +	rc = pldm_fru_init();
> +	if (rc)
> +		prlog(PR_ERR, "Failed to retrieve Fru data\n");
> 
>  out:
>  	prlog(PR_NOTICE, "%s - done, rc: %d\n", __func__, rc);
> diff --git a/core/pldm/pldm.h b/core/pldm/pldm.h
> index db2f9dcd..f9e9db40 100644
> --- a/core/pldm/pldm.h
> +++ b/core/pldm/pldm.h
> @@ -47,6 +47,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);
> -- 
> 2.37.3
> 
> _______________________________________________
> Skiboot mailing list
> Skiboot@lists.ozlabs.org
> https://lists.ozlabs.org/listinfo/skiboot
diff mbox series

Patch

diff --git a/core/pldm/Makefile.inc b/core/pldm/Makefile.inc
index 42645427..4d08e371 100644
--- a/core/pldm/Makefile.inc
+++ b/core/pldm/Makefile.inc
@@ -12,7 +12,7 @@  CFLAGS_$(PLDM_DIR)/pldm-bios-requests.o = -Wno-strict-prototypes
 
 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 00000000..02c9b968
--- /dev/null
+++ b/core/pldm/pldm-fru-requests.c
@@ -0,0 +1,136 @@ 
+// 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 <pldm/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)
+{
+	char request_msg[PKT_SIZE(struct pldm_get_fru_record_table_req)];
+	uint8_t transfer_flag, completion_code;
+	size_t response_len, payload_len;
+	uint32_t next_transfer_handle;
+	uint8_t *table_data;
+	size_t table_length;
+	void *response_msg;
+	int rc;
+
+	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 */
+	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 *)request_msg,
+			payload_len);
+	if (rc != PLDM_SUCCESS) {
+		prlog(PR_ERR, "Encode GetFruRecordTableReq Error, rc: %d\n", rc);
+		return OPAL_PARAMETER;
+	}
+
+	/* Send and get the response message bytes */
+	rc = pldm_requester_queue_and_wait(request_msg, sizeof(request_msg),
+					   &response_msg, &response_len);
+	if (rc) {
+		prlog(PR_ERR, "Communication Error, req: GetFruRecordTableReq, rc: %d\n", rc);
+		return rc;
+	}
+
+	/* Decode the message */
+	payload_len = response_len - sizeof(struct pldm_msg_hdr);
+	table_data = zalloc(payload_len);
+
+	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);
+
+		free(table_data);
+		free(response_msg);
+		return OPAL_PARAMETER;
+	}
+
+	/* 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);
+
+		free(table_data);
+		free(response_msg);
+		return OPAL_PARAMETER;
+	}
+
+	*record_table_length = table_length;
+	*record_table_data = zalloc(table_length);
+	memcpy(*record_table_data, table_data, table_length);
+
+	free(table_data);
+	free(response_msg);
+
+	return OPAL_SUCCESS;
+}
+
+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 ff4f71c3..542edc27 100644
--- a/core/pldm/pldm-mctp.c
+++ b/core/pldm/pldm-mctp.c
@@ -148,8 +148,15 @@  int pldm_mctp_init(uint8_t mode)
 
 	/* Get Bios data */
 	rc = pldm_bios_init();
-	if (rc)
+	if (rc) {
 		prlog(PR_ERR, "Failed to retrieve Bios data\n");
+		goto out;
+	}
+
+	/* Get Fru data */
+	rc = pldm_fru_init();
+	if (rc)
+		prlog(PR_ERR, "Failed to retrieve Fru data\n");
 
 out:
 	prlog(PR_NOTICE, "%s - done, rc: %d\n", __func__, rc);
diff --git a/core/pldm/pldm.h b/core/pldm/pldm.h
index db2f9dcd..f9e9db40 100644
--- a/core/pldm/pldm.h
+++ b/core/pldm/pldm.h
@@ -47,6 +47,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);