From patchwork Fri Feb 25 13:46:45 2022 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Christophe Lombard X-Patchwork-Id: 1597681 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Authentication-Results: bilbo.ozlabs.org; dkim=fail reason="signature verification failed" (2048-bit key; unprotected) header.d=ibm.com header.i=@ibm.com header.a=rsa-sha256 header.s=pp1 header.b=SRI5WA0b; dkim-atps=neutral Authentication-Results: ozlabs.org; spf=pass (sender SPF authorized) smtp.mailfrom=lists.ozlabs.org (client-ip=112.213.38.117; helo=lists.ozlabs.org; envelope-from=skiboot-bounces+incoming=patchwork.ozlabs.org@lists.ozlabs.org; receiver=) Received: from lists.ozlabs.org (lists.ozlabs.org [112.213.38.117]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (4096 bits)) (No client certificate requested) by bilbo.ozlabs.org (Postfix) with ESMTPS id 4K4rgY3pjKz9sG2 for ; Sat, 26 Feb 2022 00:47:37 +1100 (AEDT) Received: from boromir.ozlabs.org (localhost [IPv6:::1]) by lists.ozlabs.org (Postfix) with ESMTP id 4K4rgX4ff7z3bY4 for ; Sat, 26 Feb 2022 00:47:36 +1100 (AEDT) Authentication-Results: lists.ozlabs.org; dkim=fail reason="signature verification failed" (2048-bit key; unprotected) header.d=ibm.com header.i=@ibm.com header.a=rsa-sha256 header.s=pp1 header.b=SRI5WA0b; dkim-atps=neutral X-Original-To: skiboot@lists.ozlabs.org Delivered-To: skiboot@lists.ozlabs.org Authentication-Results: lists.ozlabs.org; spf=none (no SPF record) smtp.mailfrom=linux.vnet.ibm.com (client-ip=148.163.158.5; helo=mx0b-001b2d01.pphosted.com; envelope-from=clombard@linux.vnet.ibm.com; receiver=) Authentication-Results: lists.ozlabs.org; dkim=pass (2048-bit key; unprotected) header.d=ibm.com header.i=@ibm.com header.a=rsa-sha256 header.s=pp1 header.b=SRI5WA0b; dkim-atps=neutral Received: from mx0b-001b2d01.pphosted.com (mx0b-001b2d01.pphosted.com [148.163.158.5]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by lists.ozlabs.org (Postfix) with ESMTPS id 4K4rfm4H47z3bN6 for ; Sat, 26 Feb 2022 00:46:56 +1100 (AEDT) Received: from pps.filterd (m0098421.ppops.net [127.0.0.1]) by mx0a-001b2d01.pphosted.com (8.16.1.2/8.16.1.2) with SMTP id 21PCaEkD018948 for ; Fri, 25 Feb 2022 13:46:55 GMT DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=ibm.com; h=from : to : subject : date : message-id : in-reply-to : references : content-transfer-encoding : mime-version; s=pp1; bh=BY4qXIkmEIC4X8TdWRU1ZhJHb27HrvvTf/UdTTg179k=; b=SRI5WA0b6/3xpfqTQa5UoVLTwZC1mR9EbvzSkSuW2ZPA7GCBulasjuC54UdquD5IO7KX +fS1oHxo+OvdGY2hgccuYs45W47OBu4eyM900BSbgXM0yaTVaCmDM9jiZh03r9IZs4IU UV1aguWSHhuzkjrlwHwGPAEAakN6u+K1RFYas2kwfN8DJbrz4M7Dctoq3FVnRwmjZ+k7 uWuCA2xsI7QPl3y/wMP61EloDFgIh/nXfc7uzY8sU8VBlcMidMwa3g9OgBm4DSm2XQNQ zLM5Vk9LWWvixoAN9lvcmW/Jg8+0szCaWRwwqvJ/ZAjfQYFlHr9srkIA7WRgi3vuRvLI iA== Received: from ppma04fra.de.ibm.com (6a.4a.5195.ip4.static.sl-reverse.com [149.81.74.106]) by mx0a-001b2d01.pphosted.com with ESMTP id 3eevtawbkb-1 (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=NOT) for ; Fri, 25 Feb 2022 13:46:54 +0000 Received: from pps.filterd (ppma04fra.de.ibm.com [127.0.0.1]) by ppma04fra.de.ibm.com (8.16.1.2/8.16.1.2) with SMTP id 21PDh9nC009034 for ; Fri, 25 Feb 2022 13:46:52 GMT Received: from b06cxnps3075.portsmouth.uk.ibm.com (d06relay10.portsmouth.uk.ibm.com [9.149.109.195]) by ppma04fra.de.ibm.com with ESMTP id 3ear69xjpc-1 (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=NOT) for ; Fri, 25 Feb 2022 13:46:52 +0000 Received: from d06av23.portsmouth.uk.ibm.com (d06av23.portsmouth.uk.ibm.com [9.149.105.59]) by b06cxnps3075.portsmouth.uk.ibm.com (8.14.9/8.14.9/NCO v10.0) with ESMTP id 21PDko6I49414440 (version=TLSv1/SSLv3 cipher=DHE-RSA-AES256-GCM-SHA384 bits=256 verify=OK) for ; Fri, 25 Feb 2022 13:46:50 GMT Received: from d06av23.portsmouth.uk.ibm.com (unknown [127.0.0.1]) by IMSVA (Postfix) with ESMTP id F3513A404D for ; Fri, 25 Feb 2022 13:46:49 +0000 (GMT) Received: from d06av23.portsmouth.uk.ibm.com (unknown [127.0.0.1]) by IMSVA (Postfix) with ESMTP id C3ED7A4059 for ; Fri, 25 Feb 2022 13:46:49 +0000 (GMT) Received: from li-ed209401-43e8-11cb-8043-c0c0b85d70f7.ibm.com (unknown [9.171.0.236]) by d06av23.portsmouth.uk.ibm.com (Postfix) with ESMTP for ; Fri, 25 Feb 2022 13:46:49 +0000 (GMT) From: Christophe Lombard To: skiboot@lists.ozlabs.org Date: Fri, 25 Feb 2022 14:46:45 +0100 Message-Id: <20220225134645.90308-11-clombard@linux.vnet.ibm.com> X-Mailer: git-send-email 2.35.1 In-Reply-To: <20220225134645.90308-1-clombard@linux.vnet.ibm.com> References: <20220225134645.90308-1-clombard@linux.vnet.ibm.com> X-TM-AS-GCONF: 00 X-Proofpoint-GUID: DT5qTMHVDhN0Cz9_25YHvbr2yYmGW4W9 X-Proofpoint-ORIG-GUID: DT5qTMHVDhN0Cz9_25YHvbr2yYmGW4W9 X-Proofpoint-UnRewURL: 0 URL was un-rewritten MIME-Version: 1.0 X-Proofpoint-Virus-Version: vendor=baseguard engine=ICAP:2.0.205,Aquarius:18.0.816,Hydra:6.0.425,FMLib:17.11.64.514 definitions=2022-02-25_07,2022-02-25_01,2022-02-23_01 X-Proofpoint-Spam-Details: rule=outbound_notspam policy=outbound score=0 mlxscore=0 spamscore=0 phishscore=0 adultscore=0 malwarescore=0 bulkscore=0 mlxlogscore=999 impostorscore=0 suspectscore=0 lowpriorityscore=0 priorityscore=1501 clxscore=1015 classifier=spam adjust=0 reason=mlx scancount=1 engine=8.12.0-2201110000 definitions=main-2202250078 Subject: [Skiboot] [PATCH 10/10] pldm/ibm/libpldm: Import oem IBM libpldm library X-BeenThere: skiboot@lists.ozlabs.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: Mailing list for skiboot development List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: skiboot-bounces+incoming=patchwork.ozlabs.org@lists.ozlabs.org Sender: "Skiboot" This library implements IBM OEM commands support for PLDM and specially encode and decode APIs for in-band readFile and writeFile commands. The source is located here: https://github.com/openbmc/pldm/tree/master/oem/ibm/libpldm and use as is, without any update. The oem IBM libpldm code is integrated into the folder ./pldm/ibm/libpldm as a set of sources, compilated if the compiler flag CONFIG_PLDM is set. Signed-off-by: Christophe Lombard --- Makefile.main | 3 +- pldm/ibm/libpldm/Makefile.inc | 17 + pldm/ibm/libpldm/file_io.c | 841 ++++++++++++++++++++++++++++ pldm/ibm/libpldm/file_io.h | 725 ++++++++++++++++++++++++ pldm/ibm/libpldm/fru.h | 21 + pldm/ibm/libpldm/host.c | 106 ++++ pldm/ibm/libpldm/host.h | 108 ++++ pldm/ibm/libpldm/platform_oem_ibm.c | 50 ++ pldm/ibm/libpldm/platform_oem_ibm.h | 56 ++ 9 files changed, 1926 insertions(+), 1 deletion(-) create mode 100644 pldm/ibm/libpldm/Makefile.inc create mode 100644 pldm/ibm/libpldm/file_io.c create mode 100644 pldm/ibm/libpldm/file_io.h create mode 100644 pldm/ibm/libpldm/fru.h create mode 100644 pldm/ibm/libpldm/host.c create mode 100644 pldm/ibm/libpldm/host.h create mode 100644 pldm/ibm/libpldm/platform_oem_ibm.c create mode 100644 pldm/ibm/libpldm/platform_oem_ibm.h diff --git a/Makefile.main b/Makefile.main index a65220c6..35b8dc00 100644 --- a/Makefile.main +++ b/Makefile.main @@ -308,6 +308,7 @@ include $(SRC)/libstb/Makefile.inc ifeq ($(CONFIG_PLDM),1) include $(SRC)/libmctp/Makefile.inc include $(SRC)/pldm/libpldm/Makefile.inc +include $(SRC)/pldm/ibm/libpldm/Makefile.inc endif # hack for travis-ci and coverity @@ -334,7 +335,7 @@ all: $(TARGET).lid.stb $(TARGET).lid.xz.stb OBJS := $(ASM) $(CORE) $(HW) $(PLATFORMS) $(LIBFDT) $(LIBXZ) $(LIBFLASH) $(LIBSTB) OBJS += $(LIBC) $(CCAN) $(DEVSRC_OBJ) $(LIBPORE) ifeq ($(CONFIG_PLDM),1) -OBJS += $(LIBMCTP) $(LIBPLDM) +OBJS += $(LIBMCTP) $(LIBPLDM) $(LIBPLDM_IBM) endif OBJS_NO_VER = $(OBJS) ALL_OBJS = $(OBJS) version.o diff --git a/pldm/ibm/libpldm/Makefile.inc b/pldm/ibm/libpldm/Makefile.inc new file mode 100644 index 00000000..d8a40ece --- /dev/null +++ b/pldm/ibm/libpldm/Makefile.inc @@ -0,0 +1,17 @@ +# SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later +# Copyright 2022 IBM Corp. + +LIBPLDM_IBM_DIR ?= pldm/ibm/libpldm +SUBDIRS += $(LIBPLDM_IBM_DIR) + +LIBPLDM_IBM_OBJS = file_io.o host.o platform_oem_ibm.o + +CPPFLAGS += -I$(SRC)/pldm/libpldm/ + +CFLAGS_$(LIBPLDM_IBM_DIR)/ = -Wno-error \ + -Wno-declaration-after-statement \ + -Wno-strict-prototypes + +LIBPLDM_IBM = $(LIBPLDM_IBM_DIR)/built-in.a + +$(LIBPLDM_IBM): $(LIBPLDM_IBM_OBJS:%=$(LIBPLDM_IBM_DIR)/%) diff --git a/pldm/ibm/libpldm/file_io.c b/pldm/ibm/libpldm/file_io.c new file mode 100644 index 00000000..262af470 --- /dev/null +++ b/pldm/ibm/libpldm/file_io.c @@ -0,0 +1,841 @@ +#include "file_io.h" +#include +#include + +int decode_rw_file_memory_req(const struct pldm_msg *msg, size_t payload_length, + uint32_t *file_handle, uint32_t *offset, + uint32_t *length, uint64_t *address) +{ + if (msg == NULL || file_handle == NULL || offset == NULL || + length == NULL || address == NULL) { + return PLDM_ERROR_INVALID_DATA; + } + + if (payload_length != PLDM_RW_FILE_MEM_REQ_BYTES) { + return PLDM_ERROR_INVALID_LENGTH; + } + + struct pldm_read_write_file_memory_req *request = + (struct pldm_read_write_file_memory_req *)msg->payload; + + *file_handle = le32toh(request->file_handle); + *offset = le32toh(request->offset); + *length = le32toh(request->length); + *address = le64toh(request->address); + + return PLDM_SUCCESS; +} + +int encode_rw_file_memory_resp(uint8_t instance_id, uint8_t command, + uint8_t completion_code, uint32_t length, + struct pldm_msg *msg) +{ + if (msg == NULL) { + return PLDM_ERROR_INVALID_LENGTH; + } + + struct pldm_header_info header = {0}; + header.msg_type = PLDM_RESPONSE; + header.instance = instance_id; + header.pldm_type = PLDM_OEM; + header.command = command; + uint8_t rc = pack_pldm_header(&header, &(msg->hdr)); + if (rc != PLDM_SUCCESS) { + return rc; + } + + struct pldm_read_write_file_memory_resp *response = + (struct pldm_read_write_file_memory_resp *)msg->payload; + response->completion_code = completion_code; + if (response->completion_code == PLDM_SUCCESS) { + response->length = htole32(length); + } + + return PLDM_SUCCESS; +} + +int encode_rw_file_memory_req(uint8_t instance_id, uint8_t command, + uint32_t file_handle, uint32_t offset, + uint32_t length, uint64_t address, + struct pldm_msg *msg) +{ + if (msg == NULL) { + return PLDM_ERROR_INVALID_DATA; + } + + struct pldm_header_info header = {0}; + header.msg_type = PLDM_REQUEST; + header.instance = instance_id; + header.pldm_type = PLDM_OEM; + header.command = command; + uint8_t rc = pack_pldm_header(&header, &(msg->hdr)); + if (rc != PLDM_SUCCESS) { + return rc; + } + + struct pldm_read_write_file_memory_req *req = + (struct pldm_read_write_file_memory_req *)msg->payload; + req->file_handle = htole32(file_handle); + req->offset = htole32(offset); + req->length = htole32(length); + req->address = htole64(address); + return PLDM_SUCCESS; +} + +int decode_rw_file_memory_resp(const struct pldm_msg *msg, + size_t payload_length, uint8_t *completion_code, + uint32_t *length) +{ + if (msg == NULL || length == NULL || completion_code == NULL) { + return PLDM_ERROR_INVALID_DATA; + } + + if (payload_length != PLDM_RW_FILE_MEM_RESP_BYTES) { + return PLDM_ERROR_INVALID_LENGTH; + } + + struct pldm_read_write_file_memory_resp *response = + (struct pldm_read_write_file_memory_resp *)msg->payload; + *completion_code = response->completion_code; + if (*completion_code == PLDM_SUCCESS) { + *length = le32toh(response->length); + } + + return PLDM_SUCCESS; +} + +int decode_get_file_table_req(const struct pldm_msg *msg, size_t payload_length, + uint32_t *transfer_handle, + uint8_t *transfer_opflag, uint8_t *table_type) +{ + if (msg == NULL || transfer_handle == NULL || transfer_opflag == NULL || + table_type == NULL) { + return PLDM_ERROR_INVALID_DATA; + } + + if (payload_length != PLDM_GET_FILE_TABLE_REQ_BYTES) { + return PLDM_ERROR_INVALID_LENGTH; + } + + struct pldm_get_file_table_req *request = + (struct pldm_get_file_table_req *)msg->payload; + + *transfer_handle = le32toh(request->transfer_handle); + *transfer_opflag = request->operation_flag; + *table_type = request->table_type; + + return PLDM_SUCCESS; +} + +int encode_get_file_table_resp(uint8_t instance_id, uint8_t completion_code, + uint32_t next_transfer_handle, + uint8_t transfer_flag, const uint8_t *table_data, + size_t table_size, struct pldm_msg *msg) +{ + if (msg == NULL) { + return PLDM_ERROR_INVALID_LENGTH; + } + + struct pldm_header_info header = {0}; + header.msg_type = PLDM_RESPONSE; + header.instance = instance_id; + header.pldm_type = PLDM_OEM; + header.command = PLDM_GET_FILE_TABLE; + uint8_t rc = pack_pldm_header(&header, &(msg->hdr)); + if (rc != PLDM_SUCCESS) { + return rc; + } + + struct pldm_get_file_table_resp *response = + (struct pldm_get_file_table_resp *)msg->payload; + response->completion_code = completion_code; + + if (completion_code == PLDM_SUCCESS) { + response->next_transfer_handle = htole32(next_transfer_handle); + response->transfer_flag = transfer_flag; + memcpy(response->table_data, table_data, table_size); + } + + return PLDM_SUCCESS; +} + +int encode_get_file_table_req(uint8_t instance_id, uint32_t transfer_handle, + uint8_t transfer_opflag, uint8_t table_type, + struct pldm_msg *msg) +{ + if (msg == NULL) { + return PLDM_ERROR_INVALID_DATA; + } + + struct pldm_header_info header = {0}; + header.msg_type = PLDM_REQUEST; + header.instance = instance_id; + header.pldm_type = PLDM_OEM; + header.command = PLDM_GET_FILE_TABLE; + uint8_t rc = pack_pldm_header(&header, &(msg->hdr)); + if (rc != PLDM_SUCCESS) { + return rc; + } + + struct pldm_get_file_table_req *request = + (struct pldm_get_file_table_req *)msg->payload; + + request->transfer_handle = htole32(transfer_handle); + request->operation_flag = transfer_opflag; + request->table_type = table_type; + return PLDM_SUCCESS; +} + +int decode_get_file_table_resp(const struct pldm_msg *msg, + size_t payload_length, uint8_t *completion_code, + uint32_t *next_transfer_handle, + uint8_t *transfer_flag, + uint8_t *file_table_data_start_offset, + size_t *file_table_length) +{ + if (msg == NULL || transfer_flag == NULL || + next_transfer_handle == NULL || completion_code == NULL || + file_table_data_start_offset == NULL || file_table_length == NULL) { + return PLDM_ERROR_INVALID_DATA; + } + + if (payload_length <= PLDM_GET_FILE_TABLE_MIN_RESP_BYTES) { + return PLDM_ERROR_INVALID_LENGTH; + } + + *completion_code = msg->payload[0]; + + if (PLDM_SUCCESS != *completion_code) { + return PLDM_SUCCESS; + } + + struct pldm_get_file_table_resp *response = + (struct pldm_get_file_table_resp *)msg->payload; + + *next_transfer_handle = le32toh(response->next_transfer_handle); + *transfer_flag = response->transfer_flag; + *file_table_data_start_offset = sizeof(*completion_code) + + sizeof(*next_transfer_handle) + + sizeof(*transfer_flag); + *file_table_length = + payload_length - PLDM_GET_FILE_TABLE_MIN_RESP_BYTES; + + return PLDM_SUCCESS; +} + +int decode_read_file_req(const struct pldm_msg *msg, size_t payload_length, + uint32_t *file_handle, uint32_t *offset, + uint32_t *length) +{ + if (msg == NULL || file_handle == NULL || offset == NULL || + length == NULL) { + return PLDM_ERROR_INVALID_DATA; + } + + if (payload_length != PLDM_READ_FILE_REQ_BYTES) { + return PLDM_ERROR_INVALID_LENGTH; + } + + struct pldm_read_file_req *request = + (struct pldm_read_file_req *)msg->payload; + + *file_handle = le32toh(request->file_handle); + *offset = le32toh(request->offset); + *length = le32toh(request->length); + + return PLDM_SUCCESS; +} + +int encode_read_file_req(uint8_t instance_id, uint32_t file_handle, + uint32_t offset, uint32_t length, struct pldm_msg *msg) +{ + if (msg == NULL) { + return PLDM_ERROR_INVALID_DATA; + } + + if (length == 0) { + return PLDM_ERROR_INVALID_LENGTH; + } + + struct pldm_header_info header = {0}; + header.msg_type = PLDM_REQUEST; + header.instance = instance_id; + header.pldm_type = PLDM_OEM; + header.command = PLDM_READ_FILE; + uint8_t rc = pack_pldm_header(&header, &(msg->hdr)); + if (rc != PLDM_SUCCESS) { + return rc; + } + + struct pldm_read_file_req *request = + (struct pldm_read_file_req *)msg->payload; + + request->file_handle = htole32(file_handle); + request->offset = htole32(offset); + request->length = htole32(length); + + return PLDM_SUCCESS; +} + +int decode_read_file_resp(const struct pldm_msg *msg, size_t payload_length, + uint8_t *completion_code, uint32_t *length, + size_t *file_data_offset) +{ + if (msg == NULL || completion_code == NULL || length == NULL) { + return PLDM_ERROR_INVALID_DATA; + } + + if (payload_length < PLDM_READ_FILE_RESP_BYTES) { + return PLDM_ERROR_INVALID_LENGTH; + } + + struct pldm_read_file_resp *response = + (struct pldm_read_file_resp *)msg->payload; + + *completion_code = response->completion_code; + if (*completion_code == PLDM_SUCCESS) { + *length = le32toh(response->length); + if (payload_length != PLDM_READ_FILE_RESP_BYTES + *length) { + return PLDM_ERROR_INVALID_LENGTH; + } + *file_data_offset = sizeof(*completion_code) + sizeof(*length); + } + + return PLDM_SUCCESS; +} + +int encode_read_file_resp(uint8_t instance_id, uint8_t completion_code, + uint32_t length, struct pldm_msg *msg) +{ + if (msg == NULL) { + return PLDM_ERROR_INVALID_DATA; + } + + struct pldm_header_info header = {0}; + header.msg_type = PLDM_RESPONSE; + header.instance = instance_id; + header.pldm_type = PLDM_OEM; + header.command = PLDM_READ_FILE; + uint8_t rc = pack_pldm_header(&header, &(msg->hdr)); + if (rc != PLDM_SUCCESS) { + return rc; + } + + struct pldm_read_file_resp *response = + (struct pldm_read_file_resp *)msg->payload; + response->completion_code = completion_code; + + if (response->completion_code == PLDM_SUCCESS) { + response->length = htole32(length); + } + + return PLDM_SUCCESS; +} + +int decode_write_file_req(const struct pldm_msg *msg, size_t payload_length, + uint32_t *file_handle, uint32_t *offset, + uint32_t *length, size_t *file_data_offset) +{ + if (msg == NULL || file_handle == NULL || length == NULL) { + return PLDM_ERROR_INVALID_DATA; + } + + if (payload_length < PLDM_WRITE_FILE_REQ_BYTES) { + return PLDM_ERROR_INVALID_LENGTH; + } + + struct pldm_write_file_req *request = + (struct pldm_write_file_req *)msg->payload; + + *file_handle = le32toh(request->file_handle); + *offset = le32toh(request->offset); + *length = le32toh(request->length); + if (payload_length != PLDM_WRITE_FILE_REQ_BYTES + *length) { + return PLDM_ERROR_INVALID_LENGTH; + } + *file_data_offset = + sizeof(*file_handle) + sizeof(*offset) + sizeof(*length); + + return PLDM_SUCCESS; +} + +int encode_write_file_req(uint8_t instance_id, uint32_t file_handle, + uint32_t offset, uint32_t length, + struct pldm_msg *msg) +{ + if (msg == NULL) { + return PLDM_ERROR_INVALID_DATA; + } + + if (length == 0) { + return PLDM_ERROR_INVALID_LENGTH; + } + + struct pldm_header_info header = {0}; + header.msg_type = PLDM_REQUEST; + header.instance = instance_id; + header.pldm_type = PLDM_OEM; + header.command = PLDM_WRITE_FILE; + uint8_t rc = pack_pldm_header(&header, &(msg->hdr)); + if (rc != PLDM_SUCCESS) { + return rc; + } + + struct pldm_write_file_req *request = + (struct pldm_write_file_req *)msg->payload; + + request->file_handle = htole32(file_handle); + request->offset = htole32(offset); + request->length = htole32(length); + + return PLDM_SUCCESS; +} + +int decode_write_file_resp(const struct pldm_msg *msg, size_t payload_length, + uint8_t *completion_code, uint32_t *length) +{ + if (msg == NULL || completion_code == NULL || length == NULL) { + return PLDM_ERROR_INVALID_DATA; + } + + if (payload_length != PLDM_WRITE_FILE_RESP_BYTES) { + return PLDM_ERROR_INVALID_LENGTH; + } + + struct pldm_write_file_resp *response = + (struct pldm_write_file_resp *)msg->payload; + + *completion_code = le32toh(response->completion_code); + if (response->completion_code == PLDM_SUCCESS) { + *length = le32toh(response->length); + } + + return PLDM_SUCCESS; +} + +int encode_write_file_resp(uint8_t instance_id, uint8_t completion_code, + uint32_t length, struct pldm_msg *msg) +{ + if (msg == NULL) { + return PLDM_ERROR_INVALID_DATA; + } + + struct pldm_header_info header = {0}; + header.msg_type = PLDM_RESPONSE; + header.instance = instance_id; + header.pldm_type = PLDM_OEM; + header.command = PLDM_WRITE_FILE; + uint8_t rc = pack_pldm_header(&header, &(msg->hdr)); + if (rc != PLDM_SUCCESS) { + return rc; + } + + struct pldm_write_file_resp *response = + (struct pldm_write_file_resp *)msg->payload; + response->completion_code = completion_code; + + if (response->completion_code == PLDM_SUCCESS) { + response->length = htole32(length); + } + + return PLDM_SUCCESS; +} + +int decode_rw_file_by_type_memory_req(const struct pldm_msg *msg, + size_t payload_length, + uint16_t *file_type, + uint32_t *file_handle, uint32_t *offset, + uint32_t *length, uint64_t *address) +{ + if (msg == NULL || file_type == NULL || file_handle == NULL || + offset == NULL || length == NULL || address == NULL) { + return PLDM_ERROR_INVALID_DATA; + } + + if (payload_length != PLDM_RW_FILE_BY_TYPE_MEM_REQ_BYTES) { + return PLDM_ERROR_INVALID_LENGTH; + } + + struct pldm_read_write_file_by_type_memory_req *request = + (struct pldm_read_write_file_by_type_memory_req *)msg->payload; + *file_type = le16toh(request->file_type); + *file_handle = le32toh(request->file_handle); + *offset = le32toh(request->offset); + *length = le32toh(request->length); + *address = le64toh(request->address); + + return PLDM_SUCCESS; +} + +int encode_rw_file_by_type_memory_resp(uint8_t instance_id, uint8_t command, + uint8_t completion_code, uint32_t length, + struct pldm_msg *msg) +{ + if (msg == NULL) { + return PLDM_ERROR_INVALID_DATA; + } + + struct pldm_header_info header = {0}; + header.msg_type = PLDM_RESPONSE; + header.instance = instance_id; + header.pldm_type = PLDM_OEM; + header.command = command; + uint8_t rc = pack_pldm_header(&header, &(msg->hdr)); + if (rc != PLDM_SUCCESS) { + return rc; + } + + struct pldm_read_write_file_by_type_memory_resp *response = + (struct pldm_read_write_file_by_type_memory_resp *)msg->payload; + response->completion_code = completion_code; + if (response->completion_code == PLDM_SUCCESS) { + response->length = htole32(length); + } + + return PLDM_SUCCESS; +} + +int encode_rw_file_by_type_memory_req(uint8_t instance_id, uint8_t command, + uint16_t file_type, uint32_t file_handle, + uint32_t offset, uint32_t length, + uint64_t address, struct pldm_msg *msg) +{ + if (msg == NULL) { + return PLDM_ERROR_INVALID_DATA; + } + + struct pldm_header_info header = {0}; + header.msg_type = PLDM_REQUEST; + header.instance = instance_id; + header.pldm_type = PLDM_OEM; + header.command = command; + uint8_t rc = pack_pldm_header(&header, &(msg->hdr)); + if (rc != PLDM_SUCCESS) { + return rc; + } + + struct pldm_read_write_file_by_type_memory_req *req = + (struct pldm_read_write_file_by_type_memory_req *)msg->payload; + req->file_type = htole16(file_type); + req->file_handle = htole32(file_handle); + req->offset = htole32(offset); + req->length = htole32(length); + req->address = htole64(address); + + return PLDM_SUCCESS; +} + +int decode_rw_file_by_type_memory_resp(const struct pldm_msg *msg, + size_t payload_length, + uint8_t *completion_code, + uint32_t *length) +{ + if (msg == NULL || length == NULL || completion_code == NULL) { + return PLDM_ERROR_INVALID_DATA; + } + + if (payload_length != PLDM_RW_FILE_BY_TYPE_MEM_RESP_BYTES) { + return PLDM_ERROR_INVALID_LENGTH; + } + + struct pldm_read_write_file_by_type_memory_resp *response = + (struct pldm_read_write_file_by_type_memory_resp *)msg->payload; + *completion_code = response->completion_code; + if (*completion_code == PLDM_SUCCESS) { + *length = le32toh(response->length); + } + + return PLDM_SUCCESS; +} + +int decode_new_file_req(const struct pldm_msg *msg, size_t payload_length, + uint16_t *file_type, uint32_t *file_handle, + uint64_t *length) +{ + if (msg == NULL || file_type == NULL || file_handle == NULL || + length == NULL) { + return PLDM_ERROR_INVALID_DATA; + } + + if (payload_length != PLDM_NEW_FILE_REQ_BYTES) { + return PLDM_ERROR_INVALID_LENGTH; + } + + struct pldm_new_file_req *request = + (struct pldm_new_file_req *)msg->payload; + *file_type = le16toh(request->file_type); + *file_handle = le32toh(request->file_handle); + *length = le64toh(request->length); + + return PLDM_SUCCESS; +} + +int encode_new_file_resp(uint8_t instance_id, uint8_t completion_code, + struct pldm_msg *msg) +{ + if (msg == NULL) { + return PLDM_ERROR_INVALID_DATA; + } + + struct pldm_header_info header = {0}; + header.msg_type = PLDM_RESPONSE; + header.instance = instance_id; + header.pldm_type = PLDM_OEM; + header.command = PLDM_NEW_FILE_AVAILABLE; + uint8_t rc = pack_pldm_header(&header, &(msg->hdr)); + if (rc != PLDM_SUCCESS) { + return rc; + } + + struct pldm_new_file_resp *response = + (struct pldm_new_file_resp *)msg->payload; + response->completion_code = completion_code; + + return PLDM_SUCCESS; +} + +int encode_new_file_req(uint8_t instance_id, uint16_t file_type, + uint32_t file_handle, uint64_t length, + struct pldm_msg *msg) +{ + if (msg == NULL) { + return PLDM_ERROR_INVALID_DATA; + } + + struct pldm_header_info header = {0}; + header.msg_type = PLDM_REQUEST; + header.instance = instance_id; + header.pldm_type = PLDM_OEM; + header.command = PLDM_NEW_FILE_AVAILABLE; + uint8_t rc = pack_pldm_header(&header, &(msg->hdr)); + if (rc != PLDM_SUCCESS) { + return rc; + } + + struct pldm_new_file_req *req = + (struct pldm_new_file_req *)msg->payload; + req->file_type = htole16(file_type); + req->file_handle = htole32(file_handle); + req->length = htole64(length); + + return PLDM_SUCCESS; +} + +int decode_new_file_resp(const struct pldm_msg *msg, size_t payload_length, + uint8_t *completion_code) +{ + if (msg == NULL || completion_code == NULL) { + return PLDM_ERROR_INVALID_DATA; + } + + if (payload_length != PLDM_NEW_FILE_RESP_BYTES) { + return PLDM_ERROR_INVALID_LENGTH; + } + + struct pldm_new_file_resp *response = + (struct pldm_new_file_resp *)msg->payload; + *completion_code = response->completion_code; + + return PLDM_SUCCESS; +} + +int decode_rw_file_by_type_req(const struct pldm_msg *msg, + size_t payload_length, uint16_t *file_type, + uint32_t *file_handle, uint32_t *offset, + uint32_t *length) +{ + if (msg == NULL || file_type == NULL || file_handle == NULL || + offset == NULL || length == NULL) { + return PLDM_ERROR_INVALID_DATA; + } + + if (payload_length < PLDM_RW_FILE_BY_TYPE_REQ_BYTES) { + return PLDM_ERROR_INVALID_LENGTH; + } + + struct pldm_read_write_file_by_type_req *request = + (struct pldm_read_write_file_by_type_req *)msg->payload; + *file_type = le16toh(request->file_type); + *file_handle = le32toh(request->file_handle); + *offset = le32toh(request->offset); + *length = le32toh(request->length); + + return PLDM_SUCCESS; +} + +int encode_rw_file_by_type_resp(uint8_t instance_id, uint8_t command, + uint8_t completion_code, uint32_t length, + struct pldm_msg *msg) +{ + if (msg == NULL) { + return PLDM_ERROR_INVALID_DATA; + } + if (command != PLDM_READ_FILE_BY_TYPE && + command != PLDM_WRITE_FILE_BY_TYPE) { + return PLDM_ERROR_INVALID_DATA; + } + + struct pldm_header_info header = {0}; + header.msg_type = PLDM_RESPONSE; + header.instance = instance_id; + header.pldm_type = PLDM_OEM; + header.command = command; + uint8_t rc = pack_pldm_header(&header, &(msg->hdr)); + if (rc != PLDM_SUCCESS) { + return rc; + } + + struct pldm_read_write_file_by_type_resp *response = + (struct pldm_read_write_file_by_type_resp *)msg->payload; + response->completion_code = completion_code; + if (response->completion_code == PLDM_SUCCESS) { + response->length = htole32(length); + } + + return PLDM_SUCCESS; +} + +int encode_rw_file_by_type_req(uint8_t instance_id, uint8_t command, + uint16_t file_type, uint32_t file_handle, + uint32_t offset, uint32_t length, + struct pldm_msg *msg) +{ + if (msg == NULL) { + return PLDM_ERROR_INVALID_DATA; + } + if (command != PLDM_READ_FILE_BY_TYPE && + command != PLDM_WRITE_FILE_BY_TYPE) { + return PLDM_ERROR_INVALID_DATA; + } + + struct pldm_header_info header = {0}; + header.msg_type = PLDM_REQUEST; + header.instance = instance_id; + header.pldm_type = PLDM_OEM; + header.command = command; + uint8_t rc = pack_pldm_header(&header, &(msg->hdr)); + if (rc != PLDM_SUCCESS) { + return rc; + } + + struct pldm_read_write_file_by_type_req *req = + (struct pldm_read_write_file_by_type_req *)msg->payload; + req->file_type = htole16(file_type); + req->file_handle = htole32(file_handle); + req->offset = htole32(offset); + req->length = htole32(length); + + return PLDM_SUCCESS; +} + +int decode_rw_file_by_type_resp(const struct pldm_msg *msg, + size_t payload_length, uint8_t *completion_code, + uint32_t *length) +{ + if (msg == NULL || length == NULL || completion_code == NULL) { + return PLDM_ERROR_INVALID_DATA; + } + + if (payload_length != PLDM_RW_FILE_BY_TYPE_RESP_BYTES) { + return PLDM_ERROR_INVALID_LENGTH; + } + + struct pldm_read_write_file_by_type_resp *response = + (struct pldm_read_write_file_by_type_resp *)msg->payload; + *completion_code = response->completion_code; + if (*completion_code == PLDM_SUCCESS) { + *length = le32toh(response->length); + } + + return PLDM_SUCCESS; +} + +int decode_file_ack_req(const struct pldm_msg *msg, size_t payload_length, + uint16_t *file_type, uint32_t *file_handle, + uint8_t *file_status) +{ + if (msg == NULL || file_type == NULL || file_handle == NULL) { + return PLDM_ERROR_INVALID_DATA; + } + + if (payload_length != PLDM_FILE_ACK_REQ_BYTES) { + return PLDM_ERROR_INVALID_LENGTH; + } + + struct pldm_file_ack_req *request = + (struct pldm_file_ack_req *)msg->payload; + *file_type = le16toh(request->file_type); + *file_handle = le32toh(request->file_handle); + *file_status = request->file_status; + + return PLDM_SUCCESS; +} + +int encode_file_ack_resp(uint8_t instance_id, uint8_t completion_code, + struct pldm_msg *msg) +{ + if (msg == NULL) { + return PLDM_ERROR_INVALID_DATA; + } + + struct pldm_header_info header = {0}; + header.msg_type = PLDM_RESPONSE; + header.instance = instance_id; + header.pldm_type = PLDM_OEM; + header.command = PLDM_FILE_ACK; + uint8_t rc = pack_pldm_header(&header, &(msg->hdr)); + if (rc != PLDM_SUCCESS) { + return rc; + } + + struct pldm_file_ack_resp *response = + (struct pldm_file_ack_resp *)msg->payload; + response->completion_code = completion_code; + + return PLDM_SUCCESS; +} + +int encode_file_ack_req(uint8_t instance_id, uint16_t file_type, + uint32_t file_handle, uint8_t file_status, + struct pldm_msg *msg) +{ + if (msg == NULL) { + return PLDM_ERROR_INVALID_DATA; + } + + struct pldm_header_info header = {0}; + header.msg_type = PLDM_REQUEST; + header.instance = instance_id; + header.pldm_type = PLDM_OEM; + header.command = PLDM_FILE_ACK; + uint8_t rc = pack_pldm_header(&header, &(msg->hdr)); + if (rc != PLDM_SUCCESS) { + return rc; + } + + struct pldm_file_ack_req *req = + (struct pldm_file_ack_req *)msg->payload; + req->file_type = htole16(file_type); + req->file_handle = htole32(file_handle); + req->file_status = file_status; + + return PLDM_SUCCESS; +} + +int decode_file_ack_resp(const struct pldm_msg *msg, size_t payload_length, + uint8_t *completion_code) +{ + if (msg == NULL || completion_code == NULL) { + return PLDM_ERROR_INVALID_DATA; + } + + if (payload_length != PLDM_FILE_ACK_RESP_BYTES) { + return PLDM_ERROR_INVALID_LENGTH; + } + + struct pldm_file_ack_resp *response = + (struct pldm_file_ack_resp *)msg->payload; + *completion_code = response->completion_code; + + return PLDM_SUCCESS; +} diff --git a/pldm/ibm/libpldm/file_io.h b/pldm/ibm/libpldm/file_io.h new file mode 100644 index 00000000..07db4ed0 --- /dev/null +++ b/pldm/ibm/libpldm/file_io.h @@ -0,0 +1,725 @@ +#ifndef FILEIO_H +#define FILEIO_H + +#ifdef __cplusplus +extern "C" { +#endif + +#include +#include + +#include "base.h" + +/** @brief PLDM Commands in IBM OEM type + */ +enum pldm_fileio_commands { + PLDM_GET_FILE_TABLE = 0x1, + PLDM_READ_FILE = 0x4, + PLDM_WRITE_FILE = 0x5, + PLDM_READ_FILE_INTO_MEMORY = 0x6, + PLDM_WRITE_FILE_FROM_MEMORY = 0x7, + PLDM_READ_FILE_BY_TYPE_INTO_MEMORY = 0x8, + PLDM_WRITE_FILE_BY_TYPE_FROM_MEMORY = 0x9, + PLDM_NEW_FILE_AVAILABLE = 0xA, + PLDM_READ_FILE_BY_TYPE = 0xB, + PLDM_WRITE_FILE_BY_TYPE = 0xC, + PLDM_FILE_ACK = 0xD, +}; + +/** @brief PLDM Command specific codes + */ +enum pldm_fileio_completion_codes { + PLDM_FILE_TABLE_UNAVAILABLE = 0x83, + PLDM_INVALID_FILE_TABLE_TYPE = 0x85, + PLDM_INVALID_FILE_HANDLE = 0x86, + PLDM_DATA_OUT_OF_RANGE = 0x87, + PLDM_INVALID_FILE_TYPE = 0x89, +}; + +/** @brief PLDM File I/O table types + */ +enum pldm_fileio_table_type { + PLDM_FILE_ATTRIBUTE_TABLE = 0, + PLDM_OEM_FILE_ATTRIBUTE_TABLE = 1, +}; + +/** @brief PLDM File I/O table types + */ +enum pldm_fileio_file_type { + PLDM_FILE_TYPE_PEL = 0x0, + PLDM_FILE_TYPE_LID_PERM = 0x1, + PLDM_FILE_TYPE_LID_TEMP = 0x2, + PLDM_FILE_TYPE_DUMP = 0x3, + PLDM_FILE_TYPE_CERT_SIGNING_REQUEST = 0x4, + PLDM_FILE_TYPE_SIGNED_CERT = 0x5, + PLDM_FILE_TYPE_ROOT_CERT = 0x6, + PLDM_FILE_TYPE_LID_MARKER = 0x7, + PLDM_FILE_TYPE_RESOURCE_DUMP_PARMS = 0x8, + PLDM_FILE_TYPE_RESOURCE_DUMP = 0x9, + PLDM_FILE_TYPE_PROGRESS_SRC = 0xA, +}; + +#define PLDM_RW_FILE_MEM_REQ_BYTES 20 +#define PLDM_RW_FILE_MEM_RESP_BYTES 5 +#define PLDM_GET_FILE_TABLE_REQ_BYTES 6 +#define PLDM_GET_FILE_TABLE_MIN_RESP_BYTES 6 +#define PLDM_READ_FILE_REQ_BYTES 12 +#define PLDM_READ_FILE_RESP_BYTES 5 +#define PLDM_WRITE_FILE_REQ_BYTES 12 +#define PLDM_WRITE_FILE_RESP_BYTES 5 +#define PLDM_RW_FILE_BY_TYPE_MEM_REQ_BYTES 22 +#define PLDM_RW_FILE_BY_TYPE_MEM_RESP_BYTES 5 +#define PLDM_NEW_FILE_REQ_BYTES 14 +#define PLDM_NEW_FILE_RESP_BYTES 1 +#define PLDM_RW_FILE_BY_TYPE_REQ_BYTES 14 +#define PLDM_RW_FILE_BY_TYPE_RESP_BYTES 5 +#define PLDM_FILE_ACK_REQ_BYTES 7 +#define PLDM_FILE_ACK_RESP_BYTES 1 + +/** @struct pldm_read_write_file_memory_req + * + * Structure representing ReadFileIntoMemory request and WriteFileFromMemory + * request + */ +struct pldm_read_write_file_memory_req { + uint32_t file_handle; //!< A Handle to the file + uint32_t offset; //!< Offset to the file + uint32_t length; //!< Number of bytes to be read/write + uint64_t address; //!< Memory address of the file +} __attribute__((packed)); + +/** @struct pldm_read_write_file_memory_resp + * + * Structure representing ReadFileIntoMemory response and WriteFileFromMemory + * response + */ +struct pldm_read_write_file_memory_resp { + uint8_t completion_code; //!< completion code + uint32_t length; //!< Number of bytes read/written +} __attribute__((packed)); + +/** @brief Decode ReadFileIntoMemory and WriteFileFromMemory commands request + * data + * + * @param[in] msg - Pointer to PLDM request message + * @param[in] payload_length - Length of request payload + * @param[out] file_handle - A handle to the file + * @param[out] offset - Offset to the file at which the read should begin + * @param[out] length - Number of bytes to be read + * @param[out] address - Memory address where the file content has to be + * written to + * @return pldm_completion_codes + */ +int decode_rw_file_memory_req(const struct pldm_msg *msg, size_t payload_length, + uint32_t *file_handle, uint32_t *offset, + uint32_t *length, uint64_t *address); + +/** @brief Create a PLDM response for ReadFileIntoMemory and + * WriteFileFromMemory + * + * @param[in] instance_id - Message's instance id + * @param[in] command - PLDM command + * @param[in] completion_code - PLDM completion code + * @param[in] length - Number of bytes read. This could be less than what the + requester asked for. + * @param[in,out] msg - Message will be written to this + * @return pldm_completion_codes + * @note Caller is responsible for memory alloc and dealloc of param 'msg' + */ +int encode_rw_file_memory_resp(uint8_t instance_id, uint8_t command, + uint8_t completion_code, uint32_t length, + struct pldm_msg *msg); + +/** @brief Encode ReadFileIntoMemory and WriteFileFromMemory + * commands request data + * + * @param[in] instance_id - Message's instance id + * @param[in] command - PLDM command + * @param[in] file_handle - A handle to the file + * @param[in] offset - Offset to the file at which the read should begin + * @param[in] length - Number of bytes to be read/written + * @param[in] address - Memory address where the file content has to be + * written to + * @param[out] msg - Message will be written to this + * @return pldm_completion_codes + */ +int encode_rw_file_memory_req(uint8_t instance_id, uint8_t command, + uint32_t file_handle, uint32_t offset, + uint32_t length, uint64_t address, + struct pldm_msg *msg); + +/** @brief Decode ReadFileIntoMemory and WriteFileFromMemory + * commands response data + * + * @param[in] msg - pointer to PLDM response message + * @param[in] payload_length - Length of response payload + * @param[out] completion_code - PLDM completion code + * @param[out] length - Number of bytes to be read/written + * @return pldm_completion_codes + */ +int decode_rw_file_memory_resp(const struct pldm_msg *msg, + size_t payload_length, uint8_t *completion_code, + uint32_t *length); + +/** @struct pldm_get_file_table_req + * + * Structure representing GetFileTable request + */ +struct pldm_get_file_table_req { + uint32_t transfer_handle; //!< Data transfer handle + uint8_t operation_flag; //!< Transfer operation flag + uint8_t table_type; //!< Table type +} __attribute__((packed)); + +/** @struct pldm_get_file_table_resp + * + * Structure representing GetFileTable response fixed data + */ +struct pldm_get_file_table_resp { + uint8_t completion_code; //!< Completion code + uint32_t next_transfer_handle; //!< Next data transfer handle + uint8_t transfer_flag; //!< Transfer flag + uint8_t table_data[1]; //!< Table Data +} __attribute__((packed)); + +/** @struct pldm_file_attr_table_entry + * + * Structure representing File attribute table entry + */ +struct pldm_file_attr_table_entry { + uint32_t file_handle; //!< File Handle + uint16_t file_name_length; //!< File name length + uint8_t file_attr_table_nst[1]; //!< File name size traits +} __attribute__((packed)); + +/** @brief Decode GetFileTable command request data + * + * @param[in] msg - Pointer to PLDM request message + * @param[in] payload_length - Length of request payload + * @param[out] trasnfer_handle - the handle of data + * @param[out] transfer_opflag - Transfer operation flag + * @param[out] table_type - the type of file table + * @return pldm_completion_codes + */ +int decode_get_file_table_req(const struct pldm_msg *msg, size_t payload_length, + uint32_t *transfer_handle, + uint8_t *transfer_opflag, uint8_t *table_type); + +/** @brief Create a PLDM response for GetFileTable command + * + * @param[in] instance_id - Message's instance id + * @param[in] completion_code - PLDM completion code + * @param[in] next_transfer_handle - Handle to identify next portion of + * data transfer + * @param[in] transfer_flag - Represents the part of transfer + * @param[in] table_data - pointer to file table data + * @param[in] table_size - file table size + * @param[in,out] msg - Message will be written to this + * @return pldm_completion_codes + * @note Caller is responsible for memory alloc and dealloc of param 'msg' + */ +int encode_get_file_table_resp(uint8_t instance_id, uint8_t completion_code, + uint32_t next_transfer_handle, + uint8_t transfer_flag, const uint8_t *table_data, + size_t table_size, struct pldm_msg *msg); + +/** @brief Encode GetFileTable command request data + * + * @param[in] instance_id - Message's instance id + * @param[in] transfer_handle - the handle of data + * @param[in] transfer_opflag - Transfer operation flag + * @param[in] table_type - the type of file table + * @param[out] msg - Message will be written to this + * @return pldm_completion_codes + */ +int encode_get_file_table_req(uint8_t instance_id, uint32_t transfer_handle, + uint8_t transfer_opflag, uint8_t table_type, + struct pldm_msg *msg); + +/** @brief Decode GetFileTable command response data + * @param[in] msg - Response message + * @param[in] payload_length - length of response message payload + * @param[out] completion_code - PLDM completion code + * @param[out] next_transfer_handle - Handle to identify next portion of data + * transfer + * @param[out] transfer_flag - Represents the part of transfer + * @param[out] file_table_data_start_offset - This data is a portion of the + * overall File Table + * @param[out] file_table_length - Length of the File table data + * @return pldm_completion_codes + */ +int decode_get_file_table_resp(const struct pldm_msg *msg, + size_t payload_length, uint8_t *completion_code, + uint32_t *next_transfer_handle, + uint8_t *transfer_flag, + uint8_t *file_table_data_start_offset, + size_t *file_table_length); + +/** @struct pldm_read_file_req + * + * Structure representing ReadFile request + */ +struct pldm_read_file_req { + uint32_t file_handle; //!< Handle to file + uint32_t offset; //!< Offset to file where read starts + uint32_t length; //!< Bytes to be read +} __attribute__((packed)); + +/** @struct pldm_read_file_resp + * + * Structure representing ReadFile response data + */ +struct pldm_read_file_resp { + uint8_t completion_code; //!< Completion code + uint32_t length; //!< Number of bytes read + uint8_t file_data[1]; //!< Address of this is where file data starts +} __attribute__((packed)); + +/** @struct pldm_write_file_req + * + * Structure representing WriteFile request + */ +struct pldm_write_file_req { + uint32_t file_handle; //!< Handle to file + uint32_t offset; //!< Offset to file where write starts + uint32_t length; //!< Bytes to be written + uint8_t file_data[1]; //!< Address of this is where file data starts +} __attribute__((packed)); + +/** @struct pldm_write_file_resp + * + * Structure representing WriteFile response data + */ +struct pldm_write_file_resp { + uint8_t completion_code; //!< Completion code + uint32_t length; //!< Bytes written +} __attribute__((packed)); + +/** @brief Decode Read File commands request + * + * @param[in] msg - PLDM request message payload + * @param[in] payload_length - Length of request payload + * @param[out] file_handle - A handle to the file + * @param[out] offset - Offset to the file at which the read should begin + * @param[out] length - Number of bytes read + * @return pldm_completion_codes + */ +int decode_read_file_req(const struct pldm_msg *msg, size_t payload_length, + uint32_t *file_handle, uint32_t *offset, + uint32_t *length); + +/** @brief Encode Read File commands request + * + * @param[in] instance_id - Message's instance id + * @param[in] file_handle - A handle to the file + * @param[in] offset - Offset to the file at which the read should begin + * @param[in] length - Number of bytes read + * @param[in,out] msg - Message will be written to this + * @return pldm_completion_codes + * @note Caller is responsible for memory alloc and dealloc of param 'msg' + */ +int encode_read_file_req(uint8_t instance_id, uint32_t file_handle, + uint32_t offset, uint32_t length, + struct pldm_msg *msg); + +/** @brief Decode Read File commands response + * + * @param[in] msg - PLDM response message payload + * @param[in] payload_length - Length of request payload + * @param[out] completion_code - PLDM completion code + * @param[out] length - Number of bytes read. This could be less than what the + * requester asked for. + * @param[out] file_data_offset - Offset where file data should be read in pldm + * msg. + * @return pldm_completion_codes + */ +int decode_read_file_resp(const struct pldm_msg *msg, size_t payload_length, + uint8_t *completion_code, uint32_t *length, + size_t *file_data_offset); + +/** @brief Create a PLDM response for Read File + * + * @param[in] instance_id - Message's instance id + * @param[in] completion_code - PLDM completion code + * @param[in] length - Number of bytes read. This could be less than what the + * requester asked for. + * @param[in,out] msg - Message will be written to this + * @return pldm_completion_codes + * @note Caller is responsible for memory alloc and dealloc of param 'msg'. + * Although read file command response includes file data, this function + * does not encode the file data to prevent additional copying of the data. + * The position of file data is calculated by caller from address and size + * of other input arguments. + */ +int encode_read_file_resp(uint8_t instance_id, uint8_t completion_code, + uint32_t length, struct pldm_msg *msg); + +/** @brief Decode Write File commands request + * + * @param[in] msg - PLDM request message payload + * @param[in] payload_length - Length of request payload + * @param[out] file_handle - A handle to the file + * @param[out] offset - Offset to the file at which the write should begin + * @param[out] length - Number of bytes to write + * @param[out] file_data_offset - Offset where file data write begins in pldm + * msg. + * @return pldm_completion_codes + */ +int decode_write_file_req(const struct pldm_msg *msg, size_t payload_length, + uint32_t *file_handle, uint32_t *offset, + uint32_t *length, size_t *file_data_offset); + +/** @brief Create a PLDM request for Write File + * + * @param[in] instance_id - Message's instance id + * @param[in] file_handle - A handle to the file + * @param[in] offset - Offset to the file at which the read should begin + * @param[in] length - Number of bytes written. This could be less than what + * the requester asked for. + * @param[in,out] msg - Message will be written to this + * @return pldm_completion_codes + * @note Caller is responsible for memory alloc and dealloc of param 'msg'. + * Although write file command request includes file data, this function + * does not encode the file data to prevent additional copying of the data. + * The position of file data is calculated by caller from address and size + * of other input arguments. + */ +int encode_write_file_req(uint8_t instance_id, uint32_t file_handle, + uint32_t offset, uint32_t length, + struct pldm_msg *msg); + +/** @brief Decode Write File commands response + * + * @param[in] msg - PLDM request message payload + * @param[in] payload_length - Length of request payload + * @param[out] completion_code - PLDM completion code + * @param[out] length - Number of bytes written + * @return pldm_completion_codes + */ +int decode_write_file_resp(const struct pldm_msg *msg, size_t payload_length, + uint8_t *completion_code, uint32_t *length); + +/** @brief Create a PLDM response for Write File + * + * @param[in] instance_id - Message's instance id + * @param[in] completion_code - PLDM completion code + * @param[in] length - Number of bytes written. This could be less than what + * the requester asked for. + * @param[in,out] msg - Message will be written to this + * @return pldm_completion_codes + * @note Caller is responsible for memory alloc and dealloc of param 'msg' + */ +int encode_write_file_resp(uint8_t instance_id, uint8_t completion_code, + uint32_t length, struct pldm_msg *msg); + +/** @struct pldm_read_write_file_by_type_memory_req + * + * Structure representing ReadFileByTypeIntoMemory and + * WriteFileByTypeFromMemory request + */ +struct pldm_read_write_file_by_type_memory_req { + uint16_t file_type; //!< Type of file + uint32_t file_handle; //!< Handle to file + uint32_t offset; //!< Offset to file where read starts + uint32_t length; //!< Bytes to be read + uint64_t address; //!< Memory address of the file +} __attribute__((packed)); + +/** @struct pldm_read_write_file_by_type_memory_resp + * + * Structure representing ReadFileByTypeIntoMemory and + * WriteFileByTypeFromMemory response + */ +struct pldm_read_write_file_by_type_memory_resp { + uint8_t completion_code; //!< Completion code + uint32_t length; //!< Number of bytes read +} __attribute__((packed)); + +/** @brief Decode ReadFileByTypeIntoMemory and WriteFileByTypeFromMemory + * commands request data + * + * @param[in] msg - Pointer to PLDM request message + * @param[in] payload_length - Length of request payload + * @param[in] file_type - Type of the file + * @param[out] file_handle - A handle to the file + * @param[out] offset - Offset to the file at which the read should begin + * @param[out] length - Number of bytes to be read + * @param[out] address - Memory address of the file content + * @return pldm_completion_codes + */ +int decode_rw_file_by_type_memory_req(const struct pldm_msg *msg, + size_t payload_length, + uint16_t *file_type, + uint32_t *file_handle, uint32_t *offset, + uint32_t *length, uint64_t *address); + +/** @brief Create a PLDM response for ReadFileByTypeIntoMemory and + * WriteFileByTypeFromMemory + * + * @param[in] instance_id - Message's instance id + * @param[in] command - PLDM command + * @param[in] completion_code - PLDM completion code + * @param[in] length - Number of bytes read. This could be less than what the + * requester asked for. + * @param[in,out] msg - Message will be written to this + * @return pldm_completion_codes + * @note Caller is responsible for memory alloc and dealloc of param 'msg' + */ +int encode_rw_file_by_type_memory_resp(uint8_t instance_id, uint8_t command, + uint8_t completion_code, uint32_t length, + struct pldm_msg *msg); + +/** @brief Encode ReadFileByTypeIntoMemory and WriteFileByTypeFromMemory + * commands request data + * + * @param[in] instance_id - Message's instance id + * @param[in] command - PLDM command + * @param[in] file_type - Type of the file + * @param[in] file_handle - A handle to the file + * @param[in] offset - Offset to the file at which the read should begin + * @param[in] length - Number of bytes to be read/written + * @param[in] address - Memory address where the file content has to be + * written to + * @param[out] msg - Message will be written to this + * @return pldm_completion_codes + */ +int encode_rw_file_by_type_memory_req(uint8_t instance_id, uint8_t command, + uint16_t file_type, uint32_t file_handle, + uint32_t offset, uint32_t length, + uint64_t address, struct pldm_msg *msg); + +/** @brief Decode ReadFileTypeIntoMemory and WriteFileTypeFromMemory + * commands response data + * + * @param[in] msg - pointer to PLDM response message + * @param[in] payload_length - Length of response payload + * @param[out] completion_code - PLDM completion code + * @param[out] length - Number of bytes to be read/written + * @return pldm_completion_codes + */ +int decode_rw_file_by_type_memory_resp(const struct pldm_msg *msg, + size_t payload_length, + uint8_t *completion_code, + uint32_t *length); + +/** @struct pldm_new_file_req + * + * Structure representing NewFile request + */ +struct pldm_new_file_req { + uint16_t file_type; //!< Type of file + uint32_t file_handle; //!< Handle to file + uint64_t length; //!< Number of bytes in new file +} __attribute__((packed)); + +/** @struct pldm_new_file_resp + * + * Structure representing NewFile response data + */ +struct pldm_new_file_resp { + uint8_t completion_code; //!< Completion code +} __attribute__((packed)); + +/** @brief Decode NewFileAvailable command request data + * + * @param[in] msg - Pointer to PLDM request message + * @param[in] payload_length - Length of request payload + * @param[in] file_type - Type of the file + * @param[out] file_handle - A handle to the file + * @param[out] length - Number of bytes in new file + * @return pldm_completion_codes + */ +int decode_new_file_req(const struct pldm_msg *msg, size_t payload_length, + uint16_t *file_type, uint32_t *file_handle, + uint64_t *length); + +/** @brief Create a PLDM response for NewFileAvailable + * + * @param[in] instance_id - Message's instance id + * @param[in] completion_code - PLDM completion code + * @param[in,out] msg - Message will be written to this + * @return pldm_completion_codes + * @note Caller is responsible for memory alloc and dealloc of param 'msg' + */ +int encode_new_file_resp(uint8_t instance_id, uint8_t completion_code, + struct pldm_msg *msg); + +/** @brief Encode NewFileAvailable command request data + * + * @param[in] instance_id - Message's instance id + * @param[in] file_type - Type of the file + * @param[in] file_handle - A handle to the file + * @param[in] length - Number of bytes in new file + * @param[out] msg - Message will be written to this + * @return pldm_completion_codes + */ +int encode_new_file_req(uint8_t instance_id, uint16_t file_type, + uint32_t file_handle, uint64_t length, + struct pldm_msg *msg); + +/** @brief Decode NewFileAvailable command response data + * + * @param[in] msg - pointer to PLDM response message + * @param[in] payload_length - Length of response payload + * @param[out] completion_code - PLDM completion code + * @return pldm_completion_codes + */ +int decode_new_file_resp(const struct pldm_msg *msg, size_t payload_length, + uint8_t *completion_code); + +/** @struct pldm_read_write_file_by_type_req + * + * Structure representing ReadFileByType and + * WriteFileByType request + */ +struct pldm_read_write_file_by_type_req { + uint16_t file_type; //!< Type of file + uint32_t file_handle; //!< Handle to file + uint32_t offset; //!< Offset to file where read/write starts + uint32_t length; //!< Bytes to be read +} __attribute__((packed)); + +/** @struct pldm_read_write_file_by_type_resp + * + * Structure representing ReadFileByType and + * WriteFileByType response + */ +struct pldm_read_write_file_by_type_resp { + uint8_t completion_code; //!< Completion code + uint32_t length; //!< Number of bytes read +} __attribute__((packed)); + +/** @brief Decode ReadFileByType and WriteFileByType + * commands request data + * + * @param[in] msg - Pointer to PLDM request message + * @param[in] payload_length - Length of request payload + * @param[out] file_type - Type of the file + * @param[out] file_handle - A handle to the file + * @param[out] offset - Offset to the file at which the read/write should begin + * @param[out] length - Number of bytes to be read/written + * @return pldm_completion_codes + */ +int decode_rw_file_by_type_req(const struct pldm_msg *msg, + size_t payload_length, uint16_t *file_type, + uint32_t *file_handle, uint32_t *offset, + uint32_t *length); + +/** @brief Create a PLDM response for ReadFileByType and + * WriteFileByType + * + * @param[in] instance_id - Message's instance id + * @param[in] command - PLDM command + * @param[in] completion_code - PLDM completion code + * @param[in] length - Number of bytes read/written. This could be less than + * what the requester asked for. + * @param[in,out] msg - Message will be written to this + * @return pldm_completion_codes + * @note Caller is responsible for memory alloc and dealloc of param 'msg' + * @note File content has to be copied directly by the caller. + */ +int encode_rw_file_by_type_resp(uint8_t instance_id, uint8_t command, + uint8_t completion_code, uint32_t length, + struct pldm_msg *msg); + +/** @brief Encode ReadFileByType and WriteFileByType + * commands request data + * + * @param[in] instance_id - Message's instance id + * @param[in] command - PLDM command + * @param[in] file_type - Type of the file + * @param[in] file_handle - A handle to the file + * @param[in] offset - Offset to the file at which the read should begin + * @param[in] length - Number of bytes to be read/written + * @param[out] msg - Message will be written to this + * @return pldm_completion_codes + * @note File content has to be read directly by the caller. + */ +int encode_rw_file_by_type_req(uint8_t instance_id, uint8_t command, + uint16_t file_type, uint32_t file_handle, + uint32_t offset, uint32_t length, + struct pldm_msg *msg); + +/** @brief Decode ReadFileByType and WriteFileByType + * commands response data + * + * @param[in] msg - pointer to PLDM response message + * @param[in] payload_length - Length of response payload + * @param[out] completion_code - PLDM completion code + * @param[out] length - Number of bytes to be read/written + * @return pldm_completion_codes + */ +int decode_rw_file_by_type_resp(const struct pldm_msg *msg, + size_t payload_length, uint8_t *completion_code, + uint32_t *length); + +/** @struct pldm_file_ack_req + * + * Structure representing FileAck request + */ +struct pldm_file_ack_req { + uint16_t file_type; //!< Type of file + uint32_t file_handle; //!< Handle to file + uint8_t file_status; //!< Status of file processing +} __attribute__((packed)); + +/** @struct pldm_file_ack_resp + * + * Structure representing NewFile response data + */ +struct pldm_file_ack_resp { + uint8_t completion_code; //!< Completion code +} __attribute__((packed)); + +/** @brief Decode FileAck command request data + * + * @param[in] msg - Pointer to PLDM request message + * @param[in] payload_length - Length of request payload + * @param[out] file_type - Type of the file + * @param[out] file_handle - A handle to the file + * @param[out] file_status - Status of file processing + * @return pldm_completion_codes + */ +int decode_file_ack_req(const struct pldm_msg *msg, size_t payload_length, + uint16_t *file_type, uint32_t *file_handle, + uint8_t *file_status); + +/** @brief Create a PLDM response for FileAck + * + * @param[in] instance_id - Message's instance id + * @param[in] completion_code - PLDM completion code + * @param[in,out] msg - Message will be written to this + * @return pldm_completion_codes + * @note Caller is responsible for memory alloc and dealloc of param 'msg' + */ +int encode_file_ack_resp(uint8_t instance_id, uint8_t completion_code, + struct pldm_msg *msg); + +/** @brief Encode FileAck command request data + * + * @param[in] instance_id - Message's instance id + * @param[in] file_type - Type of the file + * @param[in] file_handle - A handle to the file + * @param[in] file_status - Status of file processing + * @param[out] msg - Message will be written to this + * @return pldm_completion_codes + */ +int encode_file_ack_req(uint8_t instance_id, uint16_t file_type, + uint32_t file_handle, uint8_t file_status, + struct pldm_msg *msg); + +/** @brief Decode FileAck command response data + * + * @param[in] msg - pointer to PLDM response message + * @param[in] payload_length - Length of response payload + * @param[out] completion_code - PLDM completion code + * @return pldm_completion_codes + */ +int decode_file_ack_resp(const struct pldm_msg *msg, size_t payload_length, + uint8_t *completion_code); + +#ifdef __cplusplus +} +#endif + +#endif /* FILEIO_H */ diff --git a/pldm/ibm/libpldm/fru.h b/pldm/ibm/libpldm/fru.h new file mode 100644 index 00000000..c97f8b08 --- /dev/null +++ b/pldm/ibm/libpldm/fru.h @@ -0,0 +1,21 @@ +#ifndef OEM_IBM_FRU_H +#define OEM_IBM_FRU_H + +#ifdef __cplusplus +extern "C" { +#endif + +#include +#include + +enum pldm_oem_ibm_fru_field_type { + PLDM_OEM_FRU_FIELD_TYPE_IANA = 0X01, + PLDM_OEM_FRU_FIELD_TYPE_RT = 0X02, + PLDM_OEM_FRU_FIELD_TYPE_LOCATION_CODE = 0XFE, +}; + +#ifdef __cplusplus +} +#endif + +#endif /* OEM_IBM_FRU_H */ diff --git a/pldm/ibm/libpldm/host.c b/pldm/ibm/libpldm/host.c new file mode 100644 index 00000000..caaaf9e4 --- /dev/null +++ b/pldm/ibm/libpldm/host.c @@ -0,0 +1,106 @@ +#include +#include + +#include "host.h" + +int encode_get_alert_status_req(uint8_t instance_id, uint8_t version_id, + struct pldm_msg *msg, size_t payload_length) +{ + if (msg == NULL) { + return PLDM_ERROR_INVALID_LENGTH; + } + + if (payload_length != PLDM_GET_ALERT_STATUS_REQ_BYTES) { + return PLDM_ERROR_INVALID_LENGTH; + } + + struct pldm_header_info header = {0}; + header.msg_type = PLDM_REQUEST; + header.instance = instance_id; + header.pldm_type = PLDM_OEM; + header.command = PLDM_HOST_GET_ALERT_STATUS; + uint8_t rc = pack_pldm_header(&header, &(msg->hdr)); + if (rc != PLDM_SUCCESS) { + return rc; + } + + msg->payload[0] = version_id; + + return PLDM_SUCCESS; +} + +int decode_get_alert_status_resp(const struct pldm_msg *msg, + size_t payload_length, + uint8_t *completion_code, uint32_t *rack_entry, + uint32_t *pri_cec_node) +{ + if (msg == NULL || completion_code == NULL || rack_entry == NULL || + pri_cec_node == NULL) { + return PLDM_ERROR_INVALID_DATA; + } + + *completion_code = msg->payload[0]; + if (PLDM_SUCCESS != *completion_code) { + return PLDM_SUCCESS; + } + + if (payload_length != PLDM_GET_ALERT_STATUS_RESP_BYTES) { + return PLDM_ERROR_INVALID_LENGTH; + } + + struct pldm_get_alert_status_resp *response = + (struct pldm_get_alert_status_resp *)msg->payload; + + *rack_entry = le32toh(response->rack_entry); + *pri_cec_node = le32toh(response->pri_cec_node); + + return PLDM_SUCCESS; +} + +int decode_get_alert_status_req(const struct pldm_msg *msg, + size_t payload_length, uint8_t *version_id) +{ + if (msg == NULL || version_id == NULL) { + return PLDM_ERROR_INVALID_DATA; + } + + if (payload_length != PLDM_GET_ALERT_STATUS_REQ_BYTES) { + return PLDM_ERROR_INVALID_LENGTH; + } + + *version_id = msg->payload[0]; + + return PLDM_SUCCESS; +} + +int encode_get_alert_status_resp(uint8_t instance_id, uint8_t completion_code, + uint32_t rack_entry, uint32_t pri_cec_node, + struct pldm_msg *msg, size_t payload_length) +{ + if (msg == NULL) { + return PLDM_ERROR_INVALID_LENGTH; + } + + if (payload_length != PLDM_GET_ALERT_STATUS_RESP_BYTES) { + return PLDM_ERROR_INVALID_DATA; + } + + struct pldm_header_info header = {0}; + header.msg_type = PLDM_RESPONSE; + header.instance = instance_id; + header.pldm_type = PLDM_OEM; + header.command = PLDM_HOST_GET_ALERT_STATUS; + uint8_t rc = pack_pldm_header(&header, &(msg->hdr)); + if (rc != PLDM_SUCCESS) { + return rc; + } + + struct pldm_get_alert_status_resp *response = + (struct pldm_get_alert_status_resp *)msg->payload; + + response->completion_code = completion_code; + response->rack_entry = htole32(rack_entry); + response->pri_cec_node = htole32(pri_cec_node); + + return PLDM_SUCCESS; +} diff --git a/pldm/ibm/libpldm/host.h b/pldm/ibm/libpldm/host.h new file mode 100644 index 00000000..ed121ae0 --- /dev/null +++ b/pldm/ibm/libpldm/host.h @@ -0,0 +1,108 @@ +#ifndef OEM_IBM_HOST_H +#define OEM_IBM_HOST_H + +#ifdef __cplusplus +extern "C" { +#endif + +#include +#include + +#include "base.h" + +/* Maximum size for request */ +#define PLDM_GET_ALERT_STATUS_REQ_BYTES 1 + +/* Response lengths are inclusive of completion code */ +#define PLDM_GET_ALERT_STATUS_RESP_BYTES 9 + +enum pldm_host_commands { + PLDM_HOST_GET_ALERT_STATUS = 0xF0 // Custom oem cmd +}; + +/** @brief PLDM Command specific codes + */ +enum pldm_host_completion_codes { PLDM_HOST_UNSUPPORTED_FORMAT_VERSION = 0x81 }; + +/** @struct pldm_get_alert_states_resp + * + * Structure representing GetAlertStatus response packet + */ +struct pldm_get_alert_status_resp { + uint8_t completion_code; + uint32_t rack_entry; + uint32_t pri_cec_node; +} __attribute__((packed)); + +/* Requester */ + +/* GetAlertStatus */ + +/** @brief Create a PLDM request message for GetAlertStatus + * + * @param[in] instance_id - Message's instance id + * @param[in] version_id - The command/response format. 0x00 for this format + * @param[out] msg - Message will be written to this + * @param[in] payload_length - Length of request message payload + * @return pldm_completion_codes + * @note Caller is responsible for memory alloc and dealloc of param + * 'msg.payload' + */ +int encode_get_alert_status_req(uint8_t instance_id, uint8_t version_id, + struct pldm_msg *msg, size_t payload_length); + +/** @brief Decode GetAlertStatus response data + * + * Note: + * * If the return value is not PLDM_SUCCESS, it represents a + * transport layer error. + * * If the completion_code value is not PLDM_SUCCESS, it represents a + * protocol layer error and all the out-parameters are invalid. + * + * @param[in] msg - Request message + * @param[in] payload_length - Length of request message payload + * @param[out] completion_code - PLDM completion code + * @param[out] rack_entry - Enclosure ID, Alert Status, Flags, Config ID + * @param[out] pri_cec_node - Enclosure ID, Alert Status, Flags, Config ID + * @return pldm_completion_codes + */ +int decode_get_alert_status_resp(const struct pldm_msg *msg, + size_t payload_length, + uint8_t *completion_code, uint32_t *rack_entry, + uint32_t *pri_cec_node); + +/* Responder */ + +/* GetAlertStatus */ + +/** @brief Decode GetAlertStatus request data + * + * @param[in] msg - Request message + * @param[in] payload_length - Length of request message payload + * @param[out] version_id - the command/response format. 0x00 for this format + * @return pldm_completion_codes + */ +int decode_get_alert_status_req(const struct pldm_msg *msg, + size_t payload_length, uint8_t *version_id); + +/** @brief Create a PLDM OEM response message for GetAlertStatus + * + * @param[in] instance_id - Message's instance id + * @param[in] completion_code - PLDM completion code + * @param[in] rack_entry - Enclosure ID, Alert Status, Flags, Config ID + * @param[in] pri_cec_node - Enclosure ID, Alert Status, Flags, Config ID + * @param[out] msg - Message will be written to this + * @param[in] payload_length - Length of request message payload + * @return pldm_completion_codes + * @note Caller is responsible for memory alloc and dealloc of param + * 'msg.body.payload' + */ +int encode_get_alert_status_resp(uint8_t instance_id, uint8_t completion_code, + uint32_t rack_entry, uint32_t pri_cec_node, + struct pldm_msg *msg, size_t payload_length); + +#ifdef __cplusplus +} +#endif + +#endif /* OEM_IBM_HOST_H */ diff --git a/pldm/ibm/libpldm/platform_oem_ibm.c b/pldm/ibm/libpldm/platform_oem_ibm.c new file mode 100644 index 00000000..e81a9fd0 --- /dev/null +++ b/pldm/ibm/libpldm/platform_oem_ibm.c @@ -0,0 +1,50 @@ +#include "platform_oem_ibm.h" +#include +#include + +int encode_bios_attribute_update_event_req(uint8_t instance_id, + uint8_t format_version, uint8_t tid, + uint8_t num_handles, + const uint8_t *list_of_handles, + size_t payload_length, + struct pldm_msg *msg) +{ + if (format_version != 1) { + return PLDM_ERROR_INVALID_DATA; + } + + if (msg == NULL || list_of_handles == NULL) { + return PLDM_ERROR_INVALID_DATA; + } + + if (num_handles == 0) { + return PLDM_ERROR_INVALID_DATA; + } + + if (payload_length != + (PLDM_PLATFORM_EVENT_MESSAGE_MIN_REQ_BYTES + sizeof(num_handles) + + (num_handles * sizeof(uint16_t)))) { + return PLDM_ERROR_INVALID_LENGTH; + } + + struct pldm_header_info header = {0}; + header.msg_type = PLDM_REQUEST; + header.instance = instance_id; + header.pldm_type = PLDM_PLATFORM; + header.command = PLDM_PLATFORM_EVENT_MESSAGE; + uint8_t rc = pack_pldm_header(&header, &(msg->hdr)); + if (rc != PLDM_SUCCESS) { + return rc; + } + + struct pldm_bios_attribute_update_event_req *request = + (struct pldm_bios_attribute_update_event_req *)msg->payload; + request->format_version = format_version; + request->tid = tid; + request->event_class = PLDM_EVENT_TYPE_OEM_EVENT_BIOS_ATTRIBUTE_UPDATE; + request->num_handles = num_handles; + memcpy(request->bios_attribute_handles, list_of_handles, + num_handles * sizeof(uint16_t)); + + return PLDM_SUCCESS; +} diff --git a/pldm/ibm/libpldm/platform_oem_ibm.h b/pldm/ibm/libpldm/platform_oem_ibm.h new file mode 100644 index 00000000..f0aafd36 --- /dev/null +++ b/pldm/ibm/libpldm/platform_oem_ibm.h @@ -0,0 +1,56 @@ +#ifndef PLATFORM_OEM_IBM_H +#define PLATFORM_OEM_IBM_H + +#ifdef __cplusplus +extern "C" { +#endif + +#include "base.h" +#include +#include + +enum pldm_event_types_ibm_oem { + PLDM_EVENT_TYPE_OEM_EVENT_BIOS_ATTRIBUTE_UPDATE = 0xF0, +}; + +/** @struct pldm_bios_attribute_update_event_req + * + * Structure representing PlatformEventMessage command request data for OEM + * event type BIOS attribute update. + */ +struct pldm_bios_attribute_update_event_req { + uint8_t format_version; + uint8_t tid; + uint8_t event_class; + uint8_t num_handles; + uint8_t bios_attribute_handles[1]; +} __attribute__((packed)); + +/** @brief Encode PlatformEventMessage request data for BIOS attribute update + * + * @param[in] instance_id - Message's instance id + * @param[in] format_version - Version of the event format + * @param[in] tid - Terminus ID for the terminus that originated the event + * message + * @param[in] num_handles - Number of BIOS handles with an update + * @param[in] list_of_handles - Pointer to the list of BIOS attribute handles + * @param[in] payload_length - Length of request message payload + * @param[out] msg - Message will be written to this + * + * @return pldm_completion_codes + * + * @note Caller is responsible for memory alloc and dealloc of param + * 'msg.payload' + */ +int encode_bios_attribute_update_event_req(uint8_t instance_id, + uint8_t format_version, uint8_t tid, + uint8_t num_handles, + const uint8_t *list_of_handles, + size_t payload_length, + struct pldm_msg *msg); + +#ifdef __cplusplus +} +#endif + +#endif /* PLATFORM_OEM_IBM_H */ \ No newline at end of file