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 <endian.h>
+#include <string.h>
+
+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 <stddef.h>
+#include <stdint.h>
+
+#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 <stddef.h>
+#include <stdint.h>
+
+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 <endian.h>
+#include <string.h>
+
+#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 <stddef.h>
+#include <stdint.h>
+
+#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 <pldm/libpldm/platform.h>
+#include <string.h>
+
+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 <stddef.h>
+#include <stdint.h>
+
+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
