diff mbox series

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

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

Commit Message

Christophe Lombard March 18, 2022, 2:36 p.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        |   1 +
 core/pldm/pldm-fru-requests.c | 112 ++++++++++++++++++++++++++++++++++
 core/pldm/pldm.h              |   6 ++
 3 files changed, 119 insertions(+)
 create mode 100644 core/pldm/pldm-fru-requests.c
diff mbox series

Patch

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..a2665c41
--- /dev/null
+++ b/core/pldm/pldm-fru-requests.c
@@ -0,0 +1,112 @@ 
+// 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->length = fsdata.length;
+	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 52b19f03..e75b69ab 100644
--- a/core/pldm/pldm.h
+++ b/core/pldm/pldm.h
@@ -49,6 +49,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);