[Skiboot] [PATCH V2 16/21] core/pldm: PLDM for FRU data Specification

Christophe Lombard clombard at linux.vnet.ibm.com
Sat Mar 5 00:11:49 AEDT 2022


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 at linux.vnet.ibm.com>
---
 core/pldm/Makefile.inc        |   1 +
 core/pldm/pldm-fru-requests.c | 111 ++++++++++++++++++++++++++++++++++
 core/pldm/pldm.h              |   6 ++
 3 files changed, 118 insertions(+)
 create mode 100644 core/pldm/pldm-fru-requests.c

diff --git a/core/pldm/Makefile.inc b/core/pldm/Makefile.inc
index fcd97a0a..d615a012 100644
--- a/core/pldm/Makefile.inc
+++ b/core/pldm/Makefile.inc
@@ -12,6 +12,7 @@ CFLAGS_$(PLDM_DIR)/pldm-bios-requests.o = -Wno-strict-prototypes
 
 PLDM_OBJS = pldm-common.o pldm-responder.o pldm-requester.o
 PLDM_OBJS += pldm-platform-requests.o pldm-bios-requests.o
+PLDM_OBJS += 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..d6a18d7f
--- /dev/null
+++ b/core/pldm/pldm-fru-requests.c
@@ -0,0 +1,111 @@
+// 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 int get_fru_record_by_option_req(uint16_t fru_table_handle,
+					uint16_t record_set_identifier,
+					uint8_t record_type,
+					uint8_t field_type,
+					struct variable_field *fru_structure_data)
+{
+	char request_msg[PKT_SIZE(struct pldm_get_fru_record_by_option_req)];
+	size_t response_len, payload_len;
+	uint8_t transfer_flag, completion_code;
+	uint32_t next_transfer_handle;
+	struct variable_field fsdata;
+	void *response_msg;
+	int rc;
+
+	struct pldm_get_fru_record_by_option_req fru_record_by_option_req = {
+		.data_transfer_handle = 0, /* (0 if operation op is FIRSTPART) */
+		.fru_table_handle = fru_table_handle,
+		.record_set_identifier = record_set_identifier,
+		.record_type = record_type,
+		.field_type = field_type,
+		.transfer_op_flag = PLDM_GET_FIRSTPART,
+	};
+	payload_len = sizeof(struct pldm_get_fru_record_by_option_req);
+
+	prlog(PR_DEBUG, "%s - handle: 0x%x, record id: 0x%x, record type: 0x%x, "
+			"field type: 0x%x\n",
+			__func__, fru_table_handle, record_set_identifier,
+			record_type, field_type);
+
+	/* Encode the file table request */
+	rc = encode_get_fru_record_by_option_req(
+			DEFAULT_INSTANCE_ID,
+			fru_record_by_option_req.data_transfer_handle,
+			fru_record_by_option_req.fru_table_handle,
+			fru_record_by_option_req.record_set_identifier,
+			fru_record_by_option_req.record_type,
+			fru_record_by_option_req.field_type,
+			fru_record_by_option_req.transfer_op_flag,
+			(struct pldm_msg *)request_msg,
+			payload_len);
+	if (rc != PLDM_SUCCESS) {
+		prlog(PR_ERR, "Encode GetFruRecordByOptionReq Error (rc: %d)\n", rc);
+		return OPAL_PARAMETER;
+	}
+
+	/* Send and get the response message bytes */
+	rc = pldm_do_request(BMC_EID, request_msg, sizeof(request_msg),
+			     &response_msg, &response_len);
+	if (rc) {
+		prlog(PR_ERR, "PLDM: Communication Error (req:"
+			      "GetFruRecordByOptionReq, rc: %d)\n", rc);
+		return OPAL_PARAMETER;
+	}
+
+	/* Decode the message */
+	payload_len = response_len - sizeof(struct pldm_msg_hdr);
+	rc = decode_get_fru_record_by_option_resp(
+				response_msg,
+				payload_len,
+				&completion_code,
+				&next_transfer_handle,
+				&transfer_flag,
+				&fsdata);
+	if (rc != PLDM_SUCCESS || completion_code != PLDM_SUCCESS) {
+		prlog(PR_ERR, "Decode GetFruRecordByOptionReq Error (rc: %d, cc: %d)\n",
+			      rc, completion_code);
+		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 GetFileResp not complete, "
+			      "transfer_hndl: %d, transfer_flag: %d\n",
+			      next_transfer_handle,
+			      transfer_flag);
+	}
+
+	fru_structure_data->ptr = malloc(fsdata.length);
+	memcpy((void *)fru_structure_data->ptr, fsdata.ptr, fsdata.length);
+
+	free(response_msg);
+
+	return OPAL_SUCCESS;
+}
+
+int pldm_fru_get_record_by_option(uint16_t fru_table_handle,
+				  uint16_t record_set_identifier,
+				  uint8_t record_type,
+				  uint8_t field_type,
+				  struct variable_field *fru_structure_data)
+{
+	return get_fru_record_by_option_req(fru_table_handle,
+					    record_set_identifier,
+					    record_type,
+					    field_type,
+					    fru_structure_data);
+}
diff --git a/core/pldm/pldm.h b/core/pldm/pldm.h
index 4f3d262a..bd2cdbf6 100644
--- a/core/pldm/pldm.h
+++ b/core/pldm/pldm.h
@@ -51,6 +51,12 @@ int pldm_rx_handle_request(struct pldm_rx_data *rx);
 int pldm_mctp_responder_init(void);
 
 /* Requester support */
+int pldm_fru_get_record_by_option(uint16_t fru_table_handle,
+				  uint16_t record_set_identifier,
+				  uint8_t record_type,
+				  uint8_t field_type,
+				  struct variable_field *fru_structure_data);
+
 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.35.1



More information about the Skiboot mailing list