@@ -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)/%)
new file mode 100644
@@ -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);
+}
@@ -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);
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