oem: meta: Add decode_oem_meta_file_io_write_req()

Add decode_oem_meta_file_io_write_req function.
Deprecate decode_oem_meta_file_io_req function.

The difference between functions decode_oem_meta_file_io_req and
decode_oem_meta_file_io_write_req:

- decode_oem_meta_file_io_write_req:
  - return 0 on success and return a negative errno value on failure.
  - input parameters is structure.
  - add req_length parameter to check whether the total length of
    the request is buffer overflow.
- decode_oem_meta_file_io_req:
  - return PLDM_SUCCESS on success and return another PLDM completion
    code on failure.
  - input parameters is passing individual pointers.

Change-Id: Iae3c7f24128bc25c5af6951f34fdc6d8a7b90381
Signed-off-by: Delphine CC Chiu <Delphine_CC_Chiu@wiwynn.com>
Signed-off-by: Lora Lin <lora.lin.wiwynn@gmail.com>
Signed-off-by: Andrew Jeffery <andrew@codeconstruct.com.au>
diff --git a/src/api.h b/src/api.h
index 3f1fed0..f99f3ed 100644
--- a/src/api.h
+++ b/src/api.h
@@ -32,6 +32,10 @@
 	case -ENOMSG:
 		rc = PLDM_ERROR_INVALID_PLDM_TYPE;
 		break;
+	case -EBADMSG:
+	case -EOVERFLOW:
+		rc = PLDM_ERROR_INVALID_LENGTH;
+		break;
 	default:
 		assert(false);
 		rc = PLDM_ERROR;
diff --git a/src/oem/meta/file_io.c b/src/oem/meta/file_io.c
index 9df6263..ce7d9e3 100644
--- a/src/oem/meta/file_io.c
+++ b/src/oem/meta/file_io.c
@@ -1,41 +1,91 @@
 /* SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later */
 #include <libpldm/oem/meta/file_io.h>
 #include <endian.h>
+#include <stdlib.h>
 #include <string.h>
 #include <stdio.h>
-#include "msgbuf.h"
 
-#define PLDM_OEM_META_DECODE_WRITE_FILE_IO_MIN_SIZE 6
-LIBPLDM_ABI_STABLE
-int decode_oem_meta_file_io_req(const struct pldm_msg *msg,
-				size_t payload_length, uint8_t *file_handle,
-				uint32_t *length, uint8_t *data)
+#include "api.h"
+#include "msgbuf.h"
+#include "dsp/base.h"
+
+LIBPLDM_ABI_TESTING
+void *pldm_oem_meta_file_io_write_req_data(
+	struct pldm_oem_meta_file_io_write_req *req)
+{
+	return req->data;
+}
+
+LIBPLDM_ABI_TESTING
+int decode_oem_meta_file_io_write_req(
+	const struct pldm_msg *msg, size_t payload_length,
+	struct pldm_oem_meta_file_io_write_req *req, size_t req_length)
 {
 	struct pldm_msgbuf _buf;
 	struct pldm_msgbuf *buf = &_buf;
 	int rc;
 
-	if (msg == NULL || file_handle == NULL || length == NULL ||
-	    data == NULL) {
-		return PLDM_ERROR_INVALID_DATA;
+	if (msg == NULL || req == NULL) {
+		return -EINVAL;
 	}
 
-	rc = pldm_msgbuf_init_cc(buf,
-				 PLDM_OEM_META_DECODE_WRITE_FILE_IO_MIN_SIZE,
-				 msg->payload, payload_length);
+	if (req_length < sizeof(*req)) {
+		return -EINVAL;
+	}
+
+	rc = pldm_msgbuf_init_errno(buf,
+				    PLDM_OEM_META_FILE_IO_WRITE_REQ_MIN_LENGTH,
+				    msg->payload, payload_length);
 	if (rc) {
 		return rc;
 	}
 
-	pldm_msgbuf_extract_p(buf, file_handle);
-	pldm_msgbuf_extract_p(buf, length);
+	pldm_msgbuf_extract(buf, req->handle);
+	rc = pldm_msgbuf_extract(buf, req->length);
+	if (rc) {
+		return rc;
+	}
 
-	/* NOTE: Memory safety failure */
-	rc = pldm_msgbuf_extract_array_uint8(buf, (size_t)(*length), data,
-					     UINT32_MAX);
+	rc = pldm_msgbuf_extract_array(buf, req->length, req->data,
+				       req_length - sizeof(*req));
 	if (rc) {
 		return rc;
 	}
 
 	return pldm_msgbuf_destroy_consumed(buf);
 }
+
+LIBPLDM_ABI_DEPRECATED
+int decode_oem_meta_file_io_req(const struct pldm_msg *msg,
+				size_t payload_length, uint8_t *file_handle,
+				uint32_t *length, uint8_t *data)
+{
+	struct pldm_oem_meta_file_io_write_req *request_msg;
+	size_t request_msg_len;
+	int rc;
+
+	if (msg == NULL || file_handle == NULL || length == NULL ||
+	    data == NULL) {
+		return pldm_xlate_errno(-EINVAL);
+	}
+
+	request_msg_len = sizeof(*request_msg) + payload_length;
+	request_msg = malloc(request_msg_len);
+
+	rc = decode_oem_meta_file_io_write_req(msg, payload_length, request_msg,
+					       request_msg_len);
+	if (rc < 0) {
+		free(request_msg);
+		return pldm_xlate_errno(rc);
+	}
+
+	*file_handle = request_msg->handle;
+	*length = request_msg->length;
+
+	/* NOTE: Unsafe, memory safety is not possible due to API constraints. */
+	memcpy(data, request_msg->data, request_msg->length);
+
+	free(request_msg);
+
+	return 0;
+}