| From 0827b337f8d9a6ebc8ec0404b825352f603f5f2b Mon Sep 17 00:00:00 2001 |
| From: Harsh Tyagi <harshtya@google.com> |
| Date: Tue, 13 Jun 2023 01:30:34 +0000 |
| Subject: [PATCH] Add encoders and decoders for RDE support |
| |
| Tested: |
| |
| Tested on a dev board that supported MCTP over PLDM communication by |
| connecting multiple PLDM devices |
| |
| Patch Tracking Bug: 290104814 |
| Upstream-Status: Pending |
| Upstream info / review: https://gerrit.openbmc.org/c/openbmc/libpldm/+/65087 |
| Justification: This change will be supported under AF_MCTP topic upstream |
| https://gerrit.openbmc.org/q/topic:AF_MCTP (If not the above code will be |
| reviewed) |
| --- |
| include/libpldm/meson.build | 1 + |
| include/libpldm/pldm_rde.h | 827 +++++++++++++++++++++++++++++++++ |
| src/meson.build | 3 +- |
| src/pldm_rde.c | 892 ++++++++++++++++++++++++++++++++++++ |
| tests/libpldm_rde_test.cpp | 889 +++++++++++++++++++++++++++++++++++ |
| tests/meson.build | 1 + |
| 6 files changed, 2612 insertions(+), 1 deletion(-) |
| create mode 100644 include/libpldm/pldm_rde.h |
| create mode 100644 src/pldm_rde.c |
| create mode 100644 tests/libpldm_rde_test.cpp |
| |
| diff --git a/include/libpldm/meson.build b/include/libpldm/meson.build |
| index 22f6295..9e94156 100644 |
| --- a/include/libpldm/meson.build |
| +++ b/include/libpldm/meson.build |
| @@ -17,6 +17,7 @@ libpldm_headers = files( |
| 'transport/mctp-demux.h', |
| 'utils.h', |
| 'requester/pldm_base_requester.h', |
| + 'pldm_rde.h', |
| ) |
| |
| if get_option('oem-ibm').allowed() |
| diff --git a/include/libpldm/pldm_rde.h b/include/libpldm/pldm_rde.h |
| new file mode 100644 |
| index 0000000..462c395 |
| --- /dev/null |
| +++ b/include/libpldm/pldm_rde.h |
| @@ -0,0 +1,827 @@ |
| +#ifndef PLDM_RDE_H |
| +#define PLDM_RDE_H |
| + |
| +#include "libpldm/base.h" |
| +#include "libpldm/pldm_types.h" |
| +#include <stdbool.h> |
| +#include <stddef.h> |
| +#include <stdint.h> |
| + |
| +#ifdef __cplusplus |
| +extern "C" { |
| +#endif |
| + |
| +// Minimum transfer size allowed is 64 bytes. |
| +#define PLDM_RDE_MIN_TRANSFER_SIZE_BYTES 64 |
| +// Dictionary VersionTag for DSP0218 v1.0.0, v1.1.0, v1.1.1. |
| +#define PLDM_RDE_DICT_VERSION_TAG 0x00 |
| +#define PLDM_RDE_NOT_A_OPERATION 0x00 |
| +#define PLD_RDE_NULL_TRANSFER_HANDLE 0 |
| +#define PLD_RDE_OP_PENDING_TRANSFER_HANDLE 0xFFFFFFFF |
| +#define PLDM_RDE_COMP_TIME_NOT_SUPPORTED 0xFFFFFFFF |
| +#define PLDM_RDE_COMP_PERCENTAGE_NOT_SUPPORTED 254 |
| +// Variable struct header sizes |
| +#define PLDM_RDE_MULTIPART_RECEIVE_RESP_HDR_SIZE 10 |
| +#define PLDM_RDE_OPERATION_INIT_REQ_HDR_SIZE 17 |
| +#define PLDM_RDE_OPERATION_INIT_RESP_HDR_SIZE 17 |
| +#define PLDM_RDE_OPERATION_STATUS_RESP_HDR_SIZE 17 |
| + |
| +#define PLDM_RDE 0x06 /*Response should support PLDM_PLATFORM and PLDM_RDE*/ |
| +#define RDE_NEGOTIATE_REDFISH_PARAMETERS_RESP_BYTES 12 |
| +#define RDE_NEGOTIATE_MEDIUM_PARAMETERS_RESP_BYTES 5 |
| +#define RDE_GET_DICTIONARY_SCHEMA_RESP_BYTES 6 |
| +#define RDE_MULTIPART_RECV_MINIMUM_RESP_BYTES 6 |
| +#define RDE_READ_OPERATION_INIT_MIN_BYTES 13 |
| +#define RESOURCE_ID_ANY 0xFFFFFFFF |
| +#define IGNORE(x) (void)(x) |
| + |
| +/** @brief RDE Supported Commands |
| + */ |
| +enum pldm_rde_commands { |
| + PLDM_NEGOTIATE_REDFISH_PARAMETERS = 0x01, |
| + PLDM_NEGOTIATE_MEDIUM_PARAMETERS = 0x02, |
| + PLDM_GET_SCHEMA_DICTIONARY = 0x03, |
| + PLDM_GET_SCHEMA_FILE = 0x0C, |
| + PLDM_RDE_OPERATION_INIT = 0x10, |
| + PLDM_RDE_OPERATION_COMPLETE = 0x13, |
| + PLDM_RDE_OPERATION_STATUS = 0x14, |
| + PLDM_RDE_MULTIPART_SEND = 0x30, |
| + PLDM_RDE_MULTIPART_RECEIVE = 0x31, |
| +}; |
| + |
| +typedef enum pldm_rde_varstring_format { |
| + PLDM_RDE_VARSTRING_UNKNOWN = 0, |
| + PLDM_RDE_VARSTRING_ASCII = 1, |
| + PLDM_RDE_VARSTRING_UTF_8 = 2, |
| + PLDM_RDE_VARSTRING_UTF_16 = 3, |
| + PLDM_RDE_VARSTRING_UTF_16LE = 4, |
| + PLDM_RDE_VARSTRING_UTF_16BE = 5, |
| +} pldm_rde_varstring_format; |
| + |
| +enum pldm_rde_schema_type { |
| + PLDM_RDE_SCHEMA_MAJOR = 0, |
| + PLDM_RDE_SCHEMA_EVENT = 1, |
| + PLDM_RDE_SCHEMA_ANNOTATION = 2, |
| + PLDM_RDE_SCHEMA_COLLECTION_MEMBER_TYPE = 3, |
| + PLDM_RDE_SCHEMA_ERROR = 4, |
| + PLDM_RDE_SCHEMA_REGISTRY = 5, |
| +}; |
| + |
| +enum pldm_rde_completion_codes { |
| + PLDM_RDE_ERROR_CANNOT_CREATE_OPERATION = 0x81, |
| + PLDM_RDE_ERROR_NOT_ALLOWED = 0x82, |
| + PLDM_RDE_ERROR_WRONG_LOCATION_TYPE = 0x83, |
| + PLDM_RDE_ERROR_OPERATION_ABANDONED = 0x84, |
| + PLDM_RDE_ERROR_OPERATION_EXISTS = 0x86, |
| + PLDM_RDE_ERROR_OPERATION_FAILED = 0x87, |
| + PLDM_RDE_ERROR_UNEXPECTED = 0x88, |
| + PLDM_RDE_ERROR_UNSUPPORTED = 0x89, |
| + PLDM_RDE_ERROR_NO_SUCH_RESOURCE = 0x92, |
| +}; |
| + |
| +// TODO: Do we need this because base.h already has this |
| +/** |
| + * @brief Transfer operation flags. |
| + */ |
| +enum pldm_rde_transfer_operation { |
| + PLDM_RDE_XFER_FIRST_PART = 0, |
| + PLDM_RDE_XFER_NEXT_PART = 1, |
| + PLDM_RDE_XFER_ABORT = 2, |
| +}; |
| +// TODO: Do we need this because base.h already has this |
| +enum pldm_rde_transfer_flag { |
| + PLDM_RDE_START = 0, |
| + PLDM_RDE_MIDDLE = 1, |
| + PLDM_RDE_END = 2, |
| + PLDM_RDE_START_AND_END = 3, |
| +}; |
| + |
| +enum pldm_rde_operation_type { |
| + PLDM_RDE_OPERATION_HEAD = 0, |
| + PLDM_RDE_OPERATION_READ = 1, |
| + PLDM_RDE_OPERATION_CREATE = 2, |
| + PLDM_RDE_OPERATION_DELETE = 3, |
| + PLDM_RDE_OPERATION_UPDATE = 4, |
| + PLDM_RDE_OPERATION_REPLACE = 5, |
| + PLDM_RDE_OPERATION_ACTION = 6, |
| +}; |
| + |
| +enum pldm_rde_operation_status { |
| + PLDM_RDE_OPERATION_INACTIVE = 0, |
| + PLDM_RDE_OPERATION_NEEDS_INPUT = 1, |
| + PLDM_RDE_OPERATION_TRIGGERED = 2, |
| + PLDM_RDE_OPERATION_RUNNING = 3, |
| + PLDM_RDE_OPERATION_HAVE_RESULTS = 4, |
| + PLDM_RDE_OPERATION_COMPLETED = 5, |
| + PLDM_RDE_OPERATION_FAILED = 6, |
| + PLDM_RDE_OPERATION_ABANDONED = 7, |
| +}; |
| + |
| +/** |
| + * @brief MC feature support. |
| + * |
| + * The flags can be OR'd together to build the feature support for a MC. |
| + */ |
| +enum pldm_rde_mc_feature { |
| + PLDM_RDE_MC_HEAD_SUPPORTED = 1, |
| + PLDM_RDE_MC_READ_SUPPORTED = 2, |
| + PLDM_RDE_MC_CREATE_SUPPORTED = 4, |
| + PLDM_RDE_MC_DELETE_SUPPORTED = 8, |
| + PLDM_RDE_MC_UPDATE_SUPPORTED = 16, |
| + PLDM_RDE_MC_REPLACE_SUPPORTED = 32, |
| + PLDM_RDE_MC_ACTION_SUPPORTED = 64, |
| + PLDM_RDE_MC_EVENTS_SUPPORTED = 128, |
| + PLDM_RDE_MC_BEJ_1_1_SUPPORTED = 256, |
| +}; |
| +/** |
| + * @brief Device capability flags. |
| + * |
| + * The flags can be OR'd together to build capabilities of a device. |
| + */ |
| +enum pldm_rde_device_capability { |
| + PLDM_RDE_DEVICE_ATOMIC_RESOURCE_READ_SUPPORT = 1, |
| + PLDM_RDE_DEVICE_EXPAND_SUPPORT = 2, |
| + PLDM_RDE_DEVICE_BEJ_1_1_SUPPORT = 4, |
| +}; |
| +/** |
| + * @brief Device feature support. |
| + * |
| + * The flags can be OR'd together to build features of a RDE device. |
| + */ |
| +enum pldm_rde_device_feature { |
| + PLDM_RDE_DEVICE_HEAD_SUPPORTED = 1, |
| + PLDM_RDE_DEVICE_READ_SUPPORTED = 2, |
| + PLDM_RDE_DEVICE_CREATE_SUPPORTED = 4, |
| + PLDM_RDE_DEVICE_DELETE_SUPPORTED = 8, |
| + PLDM_RDE_DEVICE_UPDATE_SUPPORTED = 16, |
| + PLDM_RDE_DEVICE_REPLACE_SUPPORTED = 32, |
| + PLDM_RDE_DEVICE_ACTION_SUPPORTED = 64, |
| + PLDM_RDE_DEVICE_EVENTS_SUPPORTED = 128, |
| +}; |
| + |
| +/** |
| + * @brief NegotiateRedfishParameters request data structure. |
| + */ |
| +struct pldm_rde_negotiate_redfish_parameters_req { |
| + uint8_t mc_concurrency_support; |
| + bitfield16_t mc_feature_support; |
| +} __attribute__((packed)); |
| +/** |
| + * @brief varstring PLDM data type. |
| + * |
| + * sizeof(struct pldm_rde_varstring) will include the space for the NULL |
| + * character. |
| + */ |
| +struct pldm_rde_varstring { |
| + uint8_t string_format; |
| + // Includes NULL terminator. |
| + uint8_t string_length_bytes; |
| + // String data should be NULL terminated. |
| + uint8_t string_data[1]; |
| +} __attribute__((packed)); |
| +/** |
| + * @brief NegotiateRedfishParameters response data structure. |
| + */ |
| +struct pldm_rde_negotiate_redfish_parameters_resp { |
| + uint8_t completion_code; |
| + uint8_t device_concurrency_support; |
| + bitfield8_t device_capabilities_flags; |
| + bitfield16_t device_feature_support; |
| + uint32_t device_configuration_signature; |
| + struct pldm_rde_varstring device_provider_name; |
| +} __attribute__((packed)); |
| +/** |
| + * @brief NegotiateMediumParameters request data structure. |
| + */ |
| +struct pldm_rde_negotiate_medium_parameters_req { |
| + uint32_t mc_maximum_transfer_chunk_size_bytes; |
| +} __attribute__((packed)); |
| +/** |
| + * @brief NegotiateMediumParameters response data structure. |
| + */ |
| +struct pldm_rde_negotiate_medium_parameters_resp { |
| + uint8_t completion_code; |
| + uint32_t device_maximum_transfer_chunk_size_bytes; |
| +} __attribute__((packed)); |
| +/** |
| + * @brief GetSchemaDictionary request data structure. |
| + */ |
| +struct pldm_rde_get_schema_dictionary_req { |
| + uint32_t resource_id; |
| + uint8_t requested_schema_class; |
| +} __attribute__((packed)); |
| +/** |
| + * @brief GetSchemaDictionary response data structure. |
| + */ |
| +struct pldm_rde_get_schema_dictionary_resp { |
| + uint8_t completion_code; |
| + uint8_t dictionary_format; |
| + uint32_t transfer_handle; |
| +} __attribute__((packed)); |
| +/** |
| + * @brief RDEMultipartReceive request data structure. |
| + */ |
| +struct pldm_rde_multipart_receive_req { |
| + uint32_t data_transfer_handle; |
| + uint16_t operation_id; |
| + uint8_t transfer_operation; |
| +} __attribute__((packed)); |
| +/** |
| + * @brief RDEMultipartReceive response data structure. |
| + */ |
| +struct pldm_rde_multipart_receive_resp { |
| + uint8_t completion_code; |
| + uint8_t transfer_flag; |
| + uint32_t next_data_transfer_handle; |
| + uint32_t data_length_bytes; |
| + uint8_t payload[1]; |
| +} __attribute__((packed)); |
| +/** |
| + * @brief OperationFlags used in RDEOperationInit request data structure. |
| + */ |
| +union pldm_rde_operation_flags { |
| + uint8_t byte; |
| + struct { |
| + uint8_t locator_valid : 1; |
| + uint8_t contains_request_payload : 1; |
| + uint8_t contains_custom_request_parameters : 1; |
| + uint8_t excerpt_flag : 1; |
| + uint8_t reserved : 4; |
| + } __attribute__((packed)) bits; |
| +}; |
| +/** |
| + * @brief RDEOperationInit request data structure. |
| + */ |
| +struct pldm_rde_operation_init_req { |
| + uint32_t resource_id; |
| + uint16_t operation_id; |
| + uint8_t operation_type; |
| + union pldm_rde_operation_flags operation_flags; |
| + uint32_t send_data_transfer_handle; |
| + uint8_t operation_locator_length; |
| + uint32_t request_payload_length; |
| + // Variable length data: bejLocator and the payload. |
| + uint8_t var_data[1]; |
| +} __attribute__((packed)); |
| +/** |
| + * @brief OperationExecutionFlags used in RDEOperationInit and |
| + * RDEOperationStatus response data structures. |
| + */ |
| +union pldm_rde_op_execution_flags { |
| + uint8_t byte; |
| + struct { |
| + uint8_t task_spawned : 1; |
| + uint8_t have_custom_response_parameters : 1; |
| + uint8_t have_result_payload : 1; |
| + uint8_t cache_allowed : 1; |
| + uint8_t reserved : 4; |
| + } __attribute__((packed)) bits; |
| +}; |
| +/** |
| + * @brief PermissionFlags used in RDEOperationInit and RDEOperationStatus |
| + * response data structures. |
| + */ |
| +union pldm_rde_permission_flags { |
| + uint8_t byte; |
| + struct { |
| + uint8_t read_allowed : 1; |
| + uint8_t update_allowed : 1; |
| + uint8_t replace_allowed : 1; |
| + uint8_t create_allowed : 1; |
| + uint8_t delete_allowed : 1; |
| + uint8_t head_allowed : 1; |
| + uint8_t reserved : 2; |
| + } __attribute__((packed)) bits; |
| +}; |
| +/** |
| + * @brief RDEOperationInit response data structure. |
| + */ |
| +struct pldm_rde_operation_init_resp { |
| + uint8_t completion_code; |
| + uint8_t operation_status; |
| + uint8_t completion_percentage; |
| + uint32_t completion_time_seconds; |
| + union pldm_rde_op_execution_flags operation_execution_flags; |
| + uint32_t result_transfer_handle; |
| + union pldm_rde_permission_flags permission_flags; |
| + uint32_t response_payload_length; |
| + // Variable length data: varstring and the payload. |
| + uint8_t var_data[1]; |
| +} __attribute__((packed)); |
| +/** |
| + * @brief RDEOperationComplete request data structure. |
| + */ |
| +struct pldm_rde_operation_complete_req { |
| + uint32_t resource_id; |
| + uint16_t operation_id; |
| +} __attribute__((packed)); |
| +/** |
| + * @brief RDEOperationComplete response data structure. |
| + */ |
| +struct pldm_rde_operation_complete_resp { |
| + uint8_t completion_code; |
| +} __attribute__((packed)); |
| +/** |
| + * @brief RDEOperationStatus request data structure. |
| + */ |
| +struct pldm_rde_operation_status_req { |
| + uint32_t resource_id; |
| + uint16_t operation_id; |
| +} __attribute__((packed)); |
| +/** |
| + * @brief RDEOperationStatus response data structure. |
| + */ |
| +struct pldm_rde_operation_status_resp { |
| + uint8_t completion_code; |
| + uint8_t operation_status; |
| + uint8_t completion_percentage; |
| + uint32_t completion_time_seconds; |
| + union pldm_rde_op_execution_flags operation_execution_flags; |
| + uint32_t result_transfer_handle; |
| + union pldm_rde_permission_flags permission_flags; |
| + uint32_t response_payload_length; |
| + // Variable length data: varstring and the payload. |
| + uint8_t var_data[1]; |
| +} __attribute__((packed)); |
| + |
| +struct pldm_rde_device_info { |
| + uint8_t device_concurrency; |
| + bitfield8_t device_capabilities_flag; |
| + bitfield16_t device_feature_support; |
| + uint32_t device_configuration_signature; |
| + struct pldm_rde_varstring device_provider_name; |
| + uint32_t device_maximum_transfer_chunk_size; // in bytes |
| +}; |
| +/** |
| + * @brief Encode NegotiateRedfishParameters request. |
| + * |
| + * @param[in] instance_id - Message's instance id. |
| + * @param[in] concurrency_support - MC concurrency support. |
| + * @param[in] feature_support - MC feature support flags. |
| + * @param[out] msg - Request message. |
| + * @return pldm_completion_codes. |
| + */ |
| +int encode_negotiate_redfish_parameters_req(uint8_t instance_id, |
| + uint8_t concurrency_support, |
| + bitfield16_t *feature_support, |
| + struct pldm_msg *msg); |
| +/** |
| + * @brief Decode NegotiateRedfishParameters request. |
| + * |
| + * @param[in] msg - Request message. |
| + * @param[in] payload_length - Length of request message payload. |
| + * @param[out] mc_concurrency_support - Pointer to a uint8_t variable. |
| + * @param[out] mc_feature_support - Pointer to a bitfield16_t variable. |
| + * @return pldm_completion_codes. |
| + */ |
| +int decode_negotiate_redfish_parameters_req(const struct pldm_msg *msg, |
| + size_t payload_length, |
| + uint8_t *mc_concurrency_support, |
| + bitfield16_t *mc_feature_support); |
| +/** |
| + * @brief Create a PLDM response message for NegotiateRedfishParameters. |
| + * |
| + * @param[in] instance_id - Message's instance id. |
| + * @param[in] completion_code - PLDM completion code. |
| + * @param[in] device_concurrency_support - Concurrency support. |
| + * @param[in] device_capabilities_flags - Capabilities flags. |
| + * @param[in] device_feature_support - Feature support flags. |
| + * @param[in] device_configuration_signature - RDE device signature. |
| + * @param[in] device_provider_name - Null terminated device provider name. |
| + * @param[in] name_format - String format of the device_provider_name. |
| + * @param[out] msg - Response message will be written to this. |
| + * @return pldm_completion_codes. |
| + */ |
| +int encode_negotiate_redfish_parameters_resp( |
| + uint8_t instance_id, uint8_t completion_code, |
| + uint8_t device_concurrency_support, bitfield8_t device_capabilities_flags, |
| + bitfield16_t device_feature_support, |
| + uint32_t device_configuration_signature, const char *device_provider_name, |
| + enum pldm_rde_varstring_format name_format, struct pldm_msg *msg); |
| + |
| +/** |
| + * @brief Decode NegotiateRedfishParameters Response. |
| + * |
| + * @param[in] msg - Request message. |
| + * @param[in] payload_length - Length of request message payload. |
| + * @param[out] completion_code - Completion code as set by the responder. |
| + * @param[out] device - Device Info as sent in the response (Memory to be |
| + * manager by the caller). |
| + * @return pldm_completion_codes. |
| + */ |
| +int decode_negotiate_redfish_parameters_resp( |
| + const struct pldm_msg *msg, size_t payload_length, uint8_t *completion_code, |
| + struct pldm_rde_device_info *device); |
| + |
| +/** |
| + * @brief Encode NegotiateMediumParameters request. |
| + * |
| + * @param[in] instance_id - Message's instance id. |
| + * @param[in] maximum_transfer_size - Maximum amount of data the MC can |
| + * support for a single message transfer. |
| + * @param[out] msg - Request message. |
| + * @return pldm_completion_codes. |
| + */ |
| +int encode_negotiate_medium_parameters_req(uint8_t instance_id, |
| + uint32_t maximum_transfer_size, |
| + struct pldm_msg *msg); |
| +/** |
| + * @brief Decode NegotiateMediumParameters request. |
| + * |
| + * @param[in] msg - Request message. |
| + * @param[in] payload_length - Length of request message payload. |
| + * @param[out] mc_maximum_transfer_size - Pointer to a uint32_t variable. |
| + * @return pldm_completion_codes. |
| + */ |
| +int decode_negotiate_medium_parameters_req(const struct pldm_msg *msg, |
| + size_t payload_length, |
| + uint32_t *mc_maximum_transfer_size); |
| +/** |
| + * @brief Create a PLDM response message for NegotiateMediumParameters. |
| + * |
| + * @param[in] instance_id - Message's instance id. |
| + * @param[in] completion_code - PLDM completion code. |
| + * @param[in] device_maximum_transfer_bytes - Device maximum transfer byte |
| + * support. |
| + * @param[out] msg - Response message will be written to this. |
| + * @return pldm_completion_codes. |
| + */ |
| +int encode_negotiate_medium_parameters_resp( |
| + uint8_t instance_id, uint8_t completion_code, |
| + uint32_t device_maximum_transfer_bytes, struct pldm_msg *msg); |
| +/** |
| + * @brief Decode Negotiate Medium Parameters response |
| + * |
| + * @param[in] msg: PLDM Msg byte array received from the responder |
| + * @param[in] payload_length: Length of the payload |
| + * @param[out] completion_code: Completion code as set by the responder |
| + * @param[out] device_maximum_transfer_bytes: Max bytes device can transfer |
| + */ |
| +int decode_negotiate_medium_parameters_resp( |
| + const struct pldm_msg *msg, size_t payload_length, uint8_t *completion_code, |
| + uint32_t *device_maximum_transfer_bytes); |
| +/** |
| + * @brief Encode GetSchemaDictionary request. |
| + * |
| + * @param[in] instance_id - Message's instance id. |
| + * @param[in] resource_id - The ResourceID of any resource in the Redfish |
| + * Resource PDR. |
| + * @param[in] schema_class - The class of schema being requested. |
| + * @param[out] msg - Request message. |
| + * @return pldm_completion_codes. |
| + */ |
| +int encode_get_schema_dictionary_req(uint8_t instance_id, uint32_t resource_id, |
| + uint8_t schema_class, |
| + struct pldm_msg *msg); |
| +/** |
| + * @brief Decode GetSchemaDictionary request. |
| + * |
| + * @param[in] msg - Request message. |
| + * @param[in] payload_length - Length of request message payload. |
| + * @param[out] resource_id - Pointer to a uint32_t variable. |
| + * @param[out] requested_schema_class - Pointer to a uint8_t variable. |
| + * @return pldm_completion_codes. |
| + */ |
| +int decode_get_schema_dictionary_req(const struct pldm_msg *msg, |
| + size_t payload_length, |
| + uint32_t *resource_id, |
| + uint8_t *requested_schema_class); |
| +/** |
| + * @brief Encode GetSchemaDictionary response. |
| + * |
| + * @param[in] instance_id - Message's instance id. |
| + * @param[in] completion_code - PLDM completion code. |
| + * @param[in] dictionary_format - The format of the dictionary. |
| + * @param[in] transfer_handle - A data transfer handle that the MC shall |
| + * use. |
| + * @param[out] msg - Response message will be written to this. |
| + * @return pldm_completion_codes. |
| + */ |
| +int encode_get_schema_dictionary_resp(uint8_t instance_id, |
| + uint8_t completion_code, |
| + uint8_t dictionary_format, |
| + uint32_t transfer_handle, |
| + struct pldm_msg *msg); |
| +/** |
| + * @brief Decode Get Schema Dictionary Response |
| + * |
| + * @param[in] msg - Response Message |
| + * @param[in] payload_length - Length of the payload |
| + * @param[out] completion_code - Completion Code |
| + * @param[out] dictionary_format - Dictionary Format for the particular resource |
| + * id |
| + * @param[out] transfer_handle - Transfer Handle to be used to get dictionary |
| + */ |
| +int decode_get_schema_dictionary_resp(const struct pldm_msg *msg, |
| + size_t payload_length, |
| + uint8_t *completion_code, |
| + uint8_t *dictionary_format, |
| + uint32_t *transfer_handle); |
| +/** |
| + * @brief Encode RDEMultipartReceive request. |
| + * |
| + * @param[in] instance_id - Message's instance id. |
| + * @param[in] data_transfer_handle - A handle to uniquely identify the chunk |
| + * of data to be retrieved. |
| + * @param[in] operation_id - Identification number for this operation. |
| + * @param[in] transfer_operation - The portion of data requested for the |
| + * transfer. |
| + * @param[out] msg - Request will be written to this. |
| + * @return pldm_completion_codes. |
| + */ |
| +int encode_rde_multipart_receive_req(uint8_t instance_id, |
| + uint32_t data_transfer_handle, |
| + uint16_t operation_id, |
| + uint8_t transfer_operation, |
| + struct pldm_msg *msg); |
| +/** |
| + * @brief Decode RDEMultipartReceive request. |
| + * |
| + * @param[in] msg - Request message. |
| + * @param[in] payload_length - Length of request message payload. |
| + * @param[out] data_transfer_handle - A handle to uniquely identify the |
| + * chunk of data to be retrieved. |
| + * @param[out] operation_id - Identification number for this operation. |
| + * @param[out] transfer_operation - The portion of data requested for the |
| + * transfer. |
| + * @return pldm_completion_codes. |
| + */ |
| +int decode_rde_multipart_receive_req(const struct pldm_msg *msg, |
| + size_t payload_length, |
| + uint32_t *data_transfer_handle, |
| + uint16_t *operation_id, |
| + uint8_t *transfer_operation); |
| +/** |
| + * @brief Encode RDEMultipartReceive response. |
| + * |
| + * @param[in] instance_id - Message's instance id. |
| + * @param[in] completion_code - PLDM completion code. |
| + * @param[in] transfer_flag - The portion of data being sent to MC. |
| + * @param[in] next_data_transfer_handle - A handle to uniquely identify the |
| + * next chunk of data to be retrieved. |
| + * @param[in] data_length_bytes - Length of the payload. |
| + * @param[in] add_checksum - Indicate whether the payload needs to include |
| + * the provided checksum. |
| + * @param[in] checksum - Checksum. |
| + * @param[in] payload - Pointer to the payload. |
| + * @param[out] msg - Response message will be written to this. |
| + * @return pldm_completion_codes. |
| + */ |
| +int encode_rde_multipart_receive_resp( |
| + uint8_t instance_id, uint8_t completion_code, uint8_t transfer_flag, |
| + uint32_t next_data_transfer_handle, uint32_t data_length_bytes, |
| + bool add_checksum, uint32_t checksum, const uint8_t *payload, |
| + struct pldm_msg *msg); |
| +/** |
| + * @brief Decode RDE Multipart Receive Response |
| + * |
| + * @param[in] msg - Response message |
| + * @param[in] payload_length - Expected length of the response, since the |
| + * response could be equal to the negotiated transfer chunk size, the requester |
| + * should usually set it to the negotiated transfer size |
| + * @param[out] completion_code - Completion code of the response set by RDE |
| + * @param[out] ret_transfer_flag - Transfer flag returned by RDE |
| + * @param[out] ret_transfer_operation - Transfer operation returned by RDE |
| + * @param[out] data_length_bytes - The length of the payload in response |
| + * @param[out] payload - Pointer to the payload |
| + */ |
| +int decode_rde_multipart_receive_resp( |
| + const struct pldm_msg *msg, size_t payload_length, uint8_t *completion_code, |
| + uint8_t *ret_transfer_flag, uint32_t *ret_data_transfer_handle, |
| + uint32_t *data_length_bytes, uint8_t **payload); |
| +/** |
| + * @brief Encode RDEOperationInit request. |
| + * |
| + * @param[in] instance_id - Message's instance id. |
| + * @param[in] resource_id - The ResourceID. |
| + * @param[in] operation_id - Identification number for this operation. |
| + * @param[in] operation_type - The type of Redfish Operation being |
| + * performed. |
| + * @param[in] operation_flags - Flags associated with this Operation. |
| + * @param[in] send_data_transfer_handle - Handle to be used with the first |
| + * RDEMultipartSend command. |
| + * @param[in] operation_locator_length - Length of the OperationLocator for |
| + * this Operation. |
| + * @param[in] request_payload_length - Length of the request payload in this |
| + * message. |
| + * @param[in] operation_locator - BEJ locator indicating where the new |
| + * Operation is to take place within the resource. |
| + * @param[in] request_payload - The request payload. |
| + * @param[out] msg - Request will be written to this. |
| + * @return pldm_completion_codes. |
| + */ |
| +int encode_rde_operation_init_req( |
| + uint8_t instance_id, uint32_t resource_id, uint16_t operation_id, |
| + uint8_t operation_type, |
| + const union pldm_rde_operation_flags *operation_flags, |
| + uint32_t send_data_transfer_handle, uint8_t operation_locator_length, |
| + uint32_t request_payload_length, const uint8_t *operation_locator, |
| + uint8_t *request_payload, struct pldm_msg *msg); |
| +/** |
| + * @brief Decode RDEOperationInit request. |
| + * |
| + * @param[in] msg - Request message. |
| + * @param[in] payload_length - Length of request message payload. |
| + * @param[out] resource_id - The ResourceID. |
| + * @param[out] operation_id - Identification number for this operation. |
| + * @param[out] operation_type - The type of Redfish Operation being |
| + * performed. |
| + * @param[out] operation_flags - Flags associated with this Operation. |
| + * @param[out] send_data_transfer_handle - Handle to be used with the first |
| + * RDEMultipartSend command. |
| + * @param[out] operation_locator_length - Length of the OperationLocator for |
| + * this Operation. |
| + * @param[out] request_payload_length - Length of the request payload in |
| + * this message. |
| + * @param[out] operation_locator - BEJ locator indicating where the new |
| + * Operation is to take place within the resource. |
| + * @param[out] request_payload - The request payload. |
| + * @return pldm_completion_codes. |
| + */ |
| +int decode_rde_operation_init_req( |
| + const struct pldm_msg *msg, size_t payload_length, uint32_t *resource_id, |
| + uint16_t *operation_id, uint8_t *operation_type, |
| + union pldm_rde_operation_flags *operation_flags, |
| + uint32_t *send_data_transfer_handle, uint8_t *operation_locator_length, |
| + uint32_t *request_payload_length, uint8_t **operation_locator, |
| + uint8_t **request_payload); |
| +/** |
| + * @brief Encode RDEOperationInit response. |
| + * |
| + * @param[in] instance_id - Message's instance id. |
| + * @param[in] completion_code - PLDM completion code. |
| + * @param[in] operation_status - Status of the operation. |
| + * @param[in] completion_percentage - Percentage complete. |
| + * @param[in] completion_time_seconds - An estimate of the number of seconds |
| + * remaining before the Operation is completed. |
| + * @param[in] operation_execution_flags - Explains the result of operation. |
| + * @param[in] result_transfer_handle - A data transfer handle that the MC |
| + * may use to retrieve a larger response payload. |
| + * @param[in] permission_flags - Indicates the access level granted to the |
| + * resource targeted by the Operation. |
| + * @param[in] response_payload_length - Length of the response payload. |
| + * @param[in] etag_format - Format of the etag string. |
| + * @param[in] etag - ETag. |
| + * @param[in] response_payload - The response payload if the payload fits. |
| + * @param[out] msg - Response message will be written to this. |
| + * @return pldm_completion_codes. |
| + */ |
| +int encode_rde_operation_init_resp( |
| + uint8_t instance_id, uint8_t completion_code, uint8_t operation_status, |
| + uint8_t completion_percentage, uint32_t completion_time_seconds, |
| + const union pldm_rde_op_execution_flags *operation_execution_flags, |
| + uint32_t result_transfer_handle, |
| + const union pldm_rde_permission_flags *permission_flags, |
| + uint32_t response_payload_length, |
| + enum pldm_rde_varstring_format etag_format, const char *etag, |
| + const uint8_t *response_payload, struct pldm_msg *msg); |
| +/** |
| + * @brief Decode RDEOperationInit Resp |
| + */ |
| +int decode_rde_operation_init_resp( |
| + const struct pldm_msg *msg, size_t payload_length, uint8_t *completion_code, |
| + uint8_t *completion_percentage, uint8_t *operation_status, |
| + uint32_t *completion_time_seconds, uint32_t *result_transfer_handle, |
| + uint32_t *response_payload_length, |
| + union pldm_rde_permission_flags **permission_flags, |
| + union pldm_rde_op_execution_flags **operation_execution_flags, |
| + struct pldm_rde_varstring **resp_etag, uint8_t **response_payload); |
| +/** |
| + * @brief Encode RDEOperationComplete request. |
| + * |
| + * @param[in] instance_id - Message's instance id. |
| + * @param[in] resource_id - The ResourceID. |
| + * @param[in] operation_id - Identification number for this operation. |
| + * @param[out] msg - Request will be written to this. |
| + * @return pldm_completion_codes. |
| + */ |
| +int encode_rde_operation_complete_req(uint8_t instance_id, uint32_t resource_id, |
| + uint16_t operation_id, |
| + struct pldm_msg *msg); |
| +/** |
| + * @brief Decode RDEOperationComplete request. |
| + * |
| + * @param[in] msg - Request message. |
| + * @param[in] payload_length - Length of request message payload. |
| + * @param[out] resource_id - The ResourceID. |
| + * @param[out] operation_id - Identification number for this operation. |
| + * @return pldm_completion_codes. |
| + */ |
| +int decode_rde_operation_complete_req(const struct pldm_msg *msg, |
| + size_t payload_length, |
| + uint32_t *resource_id, |
| + uint16_t *operation_id); |
| +/** |
| + * @brief Encode RDEOperationComplete response. |
| + * |
| + * @param[in] instance_id - Message's instance id. |
| + * @param[in] completion_code - PLDM completion code. |
| + * @param[out] msg - Response message will be written to this. |
| + * @return pldm_completion_codes. |
| + */ |
| +int encode_rde_operation_complete_resp(uint8_t instance_id, |
| + uint8_t completion_code, |
| + struct pldm_msg *msg); |
| + |
| +/** |
| + * @brief Encode RDEOperationComplete response. |
| + * |
| + * @param[in] instance_id - Message's instance id. |
| + * @param[in] completion_code - PLDM completion code. |
| + * @param[out] msg - Response message will be written to this. |
| + * @return pldm_completion_codes. |
| + */ |
| +int decode_rde_operation_complete_resp(const struct pldm_msg *msg, |
| + size_t payload_length, |
| + uint8_t *completion_code); |
| +/** |
| + * @brief Encode RDEOperationStatus request. |
| + * |
| + * @param[in] instance_id - Message's instance id. |
| + * @param[in] resource_id - The ResourceID. |
| + * @param[in] operation_id - Identification number for this operation. |
| + * @param[out] msg - Request will be written to this. |
| + * @return pldm_completion_codes. |
| + */ |
| +int encode_rde_operation_status_req(uint8_t instance_id, uint32_t resource_id, |
| + uint16_t operation_id, |
| + struct pldm_msg *msg); |
| +/** |
| + * @brief Decode RDEOperationStatus request. |
| + * |
| + * @param[in] msg - Request message. |
| + * @param[in] payload_length - Length of request message payload. |
| + * @param[out] resource_id - The ResourceID. |
| + * @param[out] operation_id - Identification number for this operation. |
| + * @return pldm_completion_codes. |
| + */ |
| +int decode_rde_operation_status_req(const struct pldm_msg *msg, |
| + size_t payload_length, |
| + uint32_t *resource_id, |
| + uint16_t *operation_id); |
| +/** |
| + * @brief Encode RDEOperationStatus response. |
| + * |
| + * @param[in] instance_id - Message's instance id. |
| + * @param[in] completion_code - PLDM completion code. |
| + * @param[in] operation_status - Status of the operation. |
| + * @param[in] completion_percentage - Percentage complete. |
| + * @param[in] completion_time_seconds - An estimate of the number of seconds |
| + * remaining before the Operation is completed. |
| + * @param[in] operation_execution_flags - Explains the result of operation. |
| + * @param[in] result_transfer_handle - A data transfer handle that the MC |
| + * may use to retrieve a larger response payload. |
| + * @param[in] permission_flags - Indicates the access level granted to the |
| + * resource targeted by the Operation. |
| + * @param[in] response_payload_length - Length of the response payload. |
| + * @param[in] etag_format - Format of the etag string. |
| + * @param[in] etag - ETag. |
| + * @param[in] response_payload - The response payload if the payload fits. |
| + * @param[out] msg - Response message will be written to this. |
| + * @return pldm_completion_codes. |
| + */ |
| +int encode_rde_operation_status_resp( |
| + uint8_t instance_id, uint8_t completion_code, uint8_t operation_status, |
| + uint8_t completion_percentage, uint32_t completion_time_seconds, |
| + const union pldm_rde_op_execution_flags *operation_execution_flags, |
| + uint32_t result_transfer_handle, |
| + const union pldm_rde_permission_flags *permission_flags, |
| + uint32_t response_payload_length, |
| + enum pldm_rde_varstring_format etag_format, const char *etag, |
| + const uint8_t *response_payload, struct pldm_msg *msg); |
| + |
| +/** |
| + * @brief Encode RDEOperationStatus response. |
| + * |
| + * @param[in] instance_id - Message's instance id. |
| + * @param[in] completion_code - PLDM completion code. |
| + * @param[in] operation_status - Status of the operation. |
| + * @param[in] completion_percentage - Percentage complete. |
| + * @param[in] completion_time_seconds - An estimate of the number of seconds |
| + * remaining before the Operation is completed. |
| + * @param[in] operation_execution_flags - Explains the result of operation. |
| + * @param[in] result_transfer_handle - A data transfer handle that the MC |
| + * may use to retrieve a larger response payload. |
| + * @param[in] permission_flags - Indicates the access level granted to the |
| + * resource targeted by the Operation. |
| + * @param[in] response_payload_length - Length of the response payload. |
| + * @param[in] etag_format - Format of the etag string. |
| + * @param[in] etag - ETag. |
| + * @param[in] response_payload - The response payload if the payload fits. |
| + * @param[out] msg - Response message will be written to this. |
| + * @return pldm_completion_codes. |
| + */ |
| +int decode_rde_operation_status_resp( |
| + const struct pldm_msg *msg, size_t payload_length, uint8_t *completion_code, |
| + uint8_t *completion_percentage, uint8_t *operation_status, |
| + uint32_t *completion_time_seconds, uint32_t *result_transfer_handle, |
| + uint32_t *response_payload_length, |
| + union pldm_rde_permission_flags **permission_flags, |
| + union pldm_rde_op_execution_flags **operation_execution_flags, |
| + struct pldm_rde_varstring **resp_etag, uint8_t **payload); |
| + |
| +#ifdef __cplusplus |
| +} |
| +#endif |
| + |
| +#endif /* PLDM_RDE_H */ |
| \ No newline at end of file |
| diff --git a/src/meson.build b/src/meson.build |
| index 9f4487c..57583b2 100644 |
| --- a/src/meson.build |
| +++ b/src/meson.build |
| @@ -7,7 +7,8 @@ libpldm_sources = files( |
| 'fru.c', |
| 'pdr.c', |
| 'responder.c', |
| - 'utils.c' |
| + 'utils.c', |
| + 'pldm_rde.c', |
| ) |
| |
| subdir('requester') |
| diff --git a/src/pldm_rde.c b/src/pldm_rde.c |
| new file mode 100644 |
| index 0000000..90d31cc |
| --- /dev/null |
| +++ b/src/pldm_rde.c |
| @@ -0,0 +1,892 @@ |
| +#include "libpldm/pldm_rde.h" |
| +#include "libpldm/base.h" |
| +#include <endian.h> |
| +#include <stdio.h> |
| +#include <stdlib.h> |
| +#include <string.h> |
| + |
| +int encode_negotiate_redfish_parameters_resp( |
| + uint8_t instance_id, uint8_t completion_code, |
| + uint8_t device_concurrency_support, bitfield8_t device_capabilities_flags, |
| + bitfield16_t device_feature_support, |
| + uint32_t device_configuration_signature, const char *device_provider_name, |
| + enum pldm_rde_varstring_format name_format, struct pldm_msg *msg) |
| +{ |
| + if ((NULL == msg) || (NULL == device_provider_name)) { |
| + return PLDM_ERROR_INVALID_DATA; |
| + } |
| + struct pldm_header_info header = {0}; |
| + header.msg_type = PLDM_RESPONSE; |
| + header.instance = instance_id; |
| + header.pldm_type = PLDM_RDE; |
| + header.command = PLDM_NEGOTIATE_REDFISH_PARAMETERS; |
| + uint8_t rc = pack_pldm_header(&header, &(msg->hdr)); |
| + if (rc != PLDM_SUCCESS) { |
| + return rc; |
| + } |
| + struct pldm_rde_negotiate_redfish_parameters_resp *response = |
| + (struct pldm_rde_negotiate_redfish_parameters_resp *)msg->payload; |
| + response->completion_code = completion_code; |
| + if (response->completion_code != PLDM_SUCCESS) { |
| + return PLDM_SUCCESS; |
| + } |
| + response->device_concurrency_support = device_concurrency_support; |
| + response->device_capabilities_flags.byte = |
| + device_capabilities_flags.byte; |
| + response->device_feature_support.value = |
| + htole16(device_feature_support.value); |
| + response->device_configuration_signature = |
| + htole32(device_configuration_signature); |
| + response->device_provider_name.string_format = name_format; |
| + // length should include NULL terminator. |
| + response->device_provider_name.string_length_bytes = |
| + strlen(device_provider_name) + 1; |
| + // Copy including NULL terminator. |
| + memcpy(response->device_provider_name.string_data, device_provider_name, |
| + response->device_provider_name.string_length_bytes); |
| + return PLDM_SUCCESS; |
| +} |
| + |
| +int encode_negotiate_redfish_parameters_req(uint8_t instance_id, |
| + uint8_t concurrency_support, |
| + bitfield16_t *feature_support, |
| + struct pldm_msg *msg) |
| +{ |
| + if ((msg == NULL) || (feature_support == NULL) || |
| + (concurrency_support == 0)) { |
| + return PLDM_ERROR_INVALID_DATA; |
| + } |
| + struct pldm_header_info header = {0}; |
| + header.instance = instance_id; |
| + header.pldm_type = PLDM_RDE; |
| + header.msg_type = PLDM_REQUEST; |
| + header.command = PLDM_NEGOTIATE_REDFISH_PARAMETERS; |
| + uint8_t rc = pack_pldm_header(&header, &(msg->hdr)); |
| + if (rc != PLDM_SUCCESS) { |
| + return rc; |
| + } |
| + struct pldm_rde_negotiate_redfish_parameters_req *req = |
| + (struct pldm_rde_negotiate_redfish_parameters_req *)msg->payload; |
| + req->mc_concurrency_support = concurrency_support; |
| + req->mc_feature_support.value = htole16(feature_support->value); |
| + return PLDM_SUCCESS; |
| +} |
| + |
| +int decode_negotiate_redfish_parameters_req(const struct pldm_msg *msg, |
| + size_t payload_length, |
| + uint8_t *mc_concurrency_support, |
| + bitfield16_t *mc_feature_support) |
| +{ |
| + if ((msg == NULL) || (mc_concurrency_support == NULL) || |
| + (mc_feature_support == NULL)) { |
| + return PLDM_ERROR_INVALID_DATA; |
| + } |
| + if (payload_length != |
| + sizeof(struct pldm_rde_negotiate_redfish_parameters_req)) { |
| + return PLDM_ERROR_INVALID_LENGTH; |
| + } |
| + struct pldm_rde_negotiate_redfish_parameters_req *request = |
| + (struct pldm_rde_negotiate_redfish_parameters_req *)msg->payload; |
| + if (request->mc_concurrency_support == 0) { |
| + fprintf(stderr, "Concurrency support is 0\n"); |
| + return PLDM_ERROR_INVALID_DATA; |
| + } |
| + *mc_concurrency_support = request->mc_concurrency_support; |
| + mc_feature_support->value = le16toh(request->mc_feature_support.value); |
| + return PLDM_SUCCESS; |
| +} |
| + |
| +int encode_negotiate_medium_parameters_resp( |
| + uint8_t instance_id, uint8_t completion_code, |
| + uint32_t device_maximum_transfer_bytes, struct pldm_msg *msg) |
| +{ |
| + if (NULL == msg) { |
| + return PLDM_ERROR_INVALID_DATA; |
| + } |
| + struct pldm_header_info header = {0}; |
| + header.msg_type = PLDM_RESPONSE; |
| + header.instance = instance_id; |
| + header.pldm_type = PLDM_RDE; |
| + header.command = PLDM_NEGOTIATE_MEDIUM_PARAMETERS; |
| + uint8_t rc = pack_pldm_header(&header, &(msg->hdr)); |
| + if (rc != PLDM_SUCCESS) { |
| + return rc; |
| + } |
| + struct pldm_rde_negotiate_medium_parameters_resp *response = |
| + (struct pldm_rde_negotiate_medium_parameters_resp *)msg->payload; |
| + response->completion_code = completion_code; |
| + if (response->completion_code != PLDM_SUCCESS) { |
| + return PLDM_SUCCESS; |
| + } |
| + response->device_maximum_transfer_chunk_size_bytes = |
| + htole32(device_maximum_transfer_bytes); |
| + return PLDM_SUCCESS; |
| +} |
| + |
| +int decode_negotiate_redfish_parameters_resp( |
| + const struct pldm_msg *msg, size_t payload_length, uint8_t *completion_code, |
| + struct pldm_rde_device_info *device) |
| +{ |
| + if ((msg == NULL) || (device == NULL) || (completion_code == NULL)) { |
| + return PLDM_ERROR_INVALID_DATA; |
| + } |
| + |
| + *completion_code = msg->payload[0]; |
| + |
| + if (PLDM_SUCCESS != *completion_code) { |
| + return PLDM_SUCCESS; |
| + } |
| + |
| + if (payload_length < RDE_NEGOTIATE_REDFISH_PARAMETERS_RESP_BYTES) { |
| + return PLDM_ERROR_INVALID_LENGTH; |
| + } |
| + |
| + struct pldm_rde_negotiate_redfish_parameters_resp *response = |
| + (struct pldm_rde_negotiate_redfish_parameters_resp *)msg->payload; |
| + |
| + device->device_concurrency = response->device_concurrency_support; |
| + device->device_capabilities_flag = response->device_capabilities_flags; |
| + device->device_configuration_signature = |
| + le32toh(response->device_configuration_signature); |
| + device->device_feature_support.value = |
| + le16toh(response->device_feature_support.value); |
| + device->device_provider_name = response->device_provider_name; |
| + return PLDM_SUCCESS; |
| +} |
| + |
| +int decode_negotiate_medium_parameters_resp( |
| + const struct pldm_msg *msg, size_t payload_length, uint8_t *completion_code, |
| + uint32_t *device_maximum_transfer_bytes) |
| +{ |
| + if ((msg == NULL) || (device_maximum_transfer_bytes == NULL) || |
| + (completion_code == NULL)) { |
| + return PLDM_ERROR_INVALID_DATA; |
| + } |
| + |
| + *completion_code = msg->payload[0]; |
| + |
| + if (PLDM_SUCCESS != *completion_code) { |
| + return PLDM_SUCCESS; |
| + } |
| + |
| + if (payload_length < RDE_NEGOTIATE_MEDIUM_PARAMETERS_RESP_BYTES) { |
| + return PLDM_ERROR_INVALID_LENGTH; |
| + } |
| + |
| + struct pldm_rde_negotiate_medium_parameters_resp *response = |
| + (struct pldm_rde_negotiate_medium_parameters_resp *)msg->payload; |
| + |
| + *device_maximum_transfer_bytes = |
| + le32toh(response->device_maximum_transfer_chunk_size_bytes); |
| + |
| + return PLDM_SUCCESS; |
| +} |
| + |
| +int encode_negotiate_medium_parameters_req(uint8_t instance_id, |
| + uint32_t maximum_transfer_size, |
| + struct pldm_msg *msg) |
| +{ |
| + if (msg == NULL) { |
| + return PLDM_ERROR_INVALID_DATA; |
| + } |
| + struct pldm_header_info header = {0}; |
| + header.instance = instance_id; |
| + header.pldm_type = PLDM_RDE; |
| + header.msg_type = PLDM_REQUEST; |
| + header.command = PLDM_NEGOTIATE_MEDIUM_PARAMETERS; |
| + uint8_t rc = pack_pldm_header(&header, &(msg->hdr)); |
| + if (rc != PLDM_SUCCESS) { |
| + return rc; |
| + } |
| + struct pldm_rde_negotiate_medium_parameters_req *req = |
| + (struct pldm_rde_negotiate_medium_parameters_req *)msg->payload; |
| + req->mc_maximum_transfer_chunk_size_bytes = |
| + htole32(maximum_transfer_size); |
| + return PLDM_SUCCESS; |
| +} |
| + |
| +int decode_negotiate_medium_parameters_req(const struct pldm_msg *msg, |
| + size_t payload_length, |
| + uint32_t *mc_maximum_transfer_size) |
| +{ |
| + if ((msg == NULL) || (mc_maximum_transfer_size == NULL)) { |
| + return PLDM_ERROR_INVALID_DATA; |
| + } |
| + if (payload_length != |
| + sizeof(struct pldm_rde_negotiate_medium_parameters_req)) { |
| + return PLDM_ERROR_INVALID_LENGTH; |
| + } |
| + struct pldm_rde_negotiate_medium_parameters_req *request = |
| + (struct pldm_rde_negotiate_medium_parameters_req *)msg->payload; |
| + *mc_maximum_transfer_size = |
| + le32toh(request->mc_maximum_transfer_chunk_size_bytes); |
| + if (*mc_maximum_transfer_size < PLDM_RDE_MIN_TRANSFER_SIZE_BYTES) { |
| + return PLDM_ERROR_INVALID_DATA; |
| + } |
| + return PLDM_SUCCESS; |
| +} |
| + |
| +int encode_get_schema_dictionary_req(uint8_t instance_id, uint32_t resource_id, |
| + uint8_t schema_class, struct pldm_msg *msg) |
| +{ |
| + if (msg == NULL) { |
| + return PLDM_ERROR_INVALID_DATA; |
| + } |
| + struct pldm_header_info header = {0}; |
| + header.instance = instance_id; |
| + header.pldm_type = PLDM_RDE; |
| + header.msg_type = PLDM_REQUEST; |
| + header.command = PLDM_GET_SCHEMA_DICTIONARY; |
| + uint8_t rc = pack_pldm_header(&header, &(msg->hdr)); |
| + if (rc != PLDM_SUCCESS) { |
| + return rc; |
| + } |
| + struct pldm_rde_get_schema_dictionary_req *req = |
| + (struct pldm_rde_get_schema_dictionary_req *)msg->payload; |
| + req->resource_id = htole32(resource_id); |
| + req->requested_schema_class = schema_class; |
| + return PLDM_SUCCESS; |
| +} |
| + |
| +int decode_get_schema_dictionary_req(const struct pldm_msg *msg, |
| + size_t payload_length, |
| + uint32_t *resource_id, |
| + uint8_t *requested_schema_class) |
| +{ |
| + if ((msg == NULL) || (resource_id == NULL) || |
| + (requested_schema_class == NULL)) { |
| + return PLDM_ERROR_INVALID_DATA; |
| + } |
| + if (payload_length != |
| + sizeof(struct pldm_rde_get_schema_dictionary_req)) { |
| + return PLDM_ERROR_INVALID_LENGTH; |
| + } |
| + struct pldm_rde_get_schema_dictionary_req *request = |
| + (struct pldm_rde_get_schema_dictionary_req *)msg->payload; |
| + *resource_id = le32toh(request->resource_id); |
| + *requested_schema_class = request->requested_schema_class; |
| + if (*requested_schema_class > PLDM_RDE_SCHEMA_REGISTRY) { |
| + return PLDM_ERROR_INVALID_DATA; |
| + } |
| + return PLDM_SUCCESS; |
| +} |
| + |
| +int encode_get_schema_dictionary_resp(uint8_t instance_id, |
| + uint8_t completion_code, |
| + uint8_t dictionary_format, |
| + uint32_t transfer_handle, |
| + struct pldm_msg *msg) |
| +{ |
| + if (NULL == msg) { |
| + return PLDM_ERROR_INVALID_DATA; |
| + } |
| + struct pldm_header_info header = {0}; |
| + header.msg_type = PLDM_RESPONSE; |
| + header.instance = instance_id; |
| + header.pldm_type = PLDM_RDE; |
| + header.command = PLDM_GET_SCHEMA_DICTIONARY; |
| + uint8_t rc = pack_pldm_header(&header, &(msg->hdr)); |
| + if (rc != PLDM_SUCCESS) { |
| + return rc; |
| + } |
| + struct pldm_rde_get_schema_dictionary_resp *response = |
| + (struct pldm_rde_get_schema_dictionary_resp *)msg->payload; |
| + response->completion_code = completion_code; |
| + if (response->completion_code != PLDM_SUCCESS) { |
| + return PLDM_SUCCESS; |
| + } |
| + response->dictionary_format = dictionary_format; |
| + response->transfer_handle = htole32(transfer_handle); |
| + return PLDM_SUCCESS; |
| +} |
| + |
| +int decode_get_schema_dictionary_resp(const struct pldm_msg *msg, |
| + size_t payload_length, |
| + uint8_t *completion_code, |
| + uint8_t *dictionary_format, |
| + uint32_t *transfer_handle) |
| +{ |
| + if ((msg == NULL) || (dictionary_format == NULL) || |
| + (completion_code == NULL) || (transfer_handle == NULL)) { |
| + return PLDM_ERROR_INVALID_DATA; |
| + } |
| + |
| + *completion_code = msg->payload[0]; |
| + |
| + if (PLDM_SUCCESS != *completion_code) { |
| + fprintf(stderr, "COMPLETION CODE ERROR\n"); |
| + return PLDM_SUCCESS; |
| + } |
| + |
| + if (payload_length < RDE_GET_DICTIONARY_SCHEMA_RESP_BYTES) { |
| + fprintf(stderr, "RESPONSE INVALID LEN CODE ERROR\n"); |
| + return PLDM_ERROR_INVALID_LENGTH; |
| + } |
| + |
| + struct pldm_rde_get_schema_dictionary_resp *response = |
| + (struct pldm_rde_get_schema_dictionary_resp *)msg->payload; |
| + *dictionary_format = response->dictionary_format; |
| + *transfer_handle = le32toh(response->transfer_handle); |
| + return PLDM_SUCCESS; |
| +} |
| + |
| +int encode_rde_multipart_receive_req(uint8_t instance_id, |
| + uint32_t data_transfer_handle, |
| + uint16_t operation_id, |
| + uint8_t transfer_operation, |
| + struct pldm_msg *msg) |
| +{ |
| + if (msg == NULL) { |
| + return PLDM_ERROR_INVALID_DATA; |
| + } |
| + struct pldm_header_info header = {0}; |
| + header.instance = instance_id; |
| + header.pldm_type = PLDM_RDE; |
| + header.msg_type = PLDM_REQUEST; |
| + header.command = PLDM_RDE_MULTIPART_RECEIVE; |
| + uint8_t rc = pack_pldm_header(&header, &(msg->hdr)); |
| + if (rc != PLDM_SUCCESS) { |
| + return rc; |
| + } |
| + struct pldm_rde_multipart_receive_req *req = |
| + (struct pldm_rde_multipart_receive_req *)msg->payload; |
| + req->data_transfer_handle = htole32(data_transfer_handle); |
| + req->operation_id = htole16(operation_id); |
| + req->transfer_operation = transfer_operation; |
| + return PLDM_SUCCESS; |
| +} |
| + |
| +int decode_rde_multipart_receive_req(const struct pldm_msg *msg, |
| + size_t payload_length, |
| + uint32_t *data_transfer_handle, |
| + uint16_t *operation_id, |
| + uint8_t *transfer_operation) |
| +{ |
| + if ((msg == NULL) || (data_transfer_handle == NULL) || |
| + (operation_id == NULL) || (transfer_operation == NULL)) { |
| + return PLDM_ERROR_INVALID_DATA; |
| + } |
| + if (payload_length != sizeof(struct pldm_rde_multipart_receive_req)) { |
| + return PLDM_ERROR_INVALID_LENGTH; |
| + } |
| + struct pldm_rde_multipart_receive_req *request = |
| + (struct pldm_rde_multipart_receive_req *)msg->payload; |
| + *data_transfer_handle = le32toh(request->data_transfer_handle); |
| + *operation_id = le16toh(request->operation_id); |
| + *transfer_operation = request->transfer_operation; |
| + if (*transfer_operation > PLDM_RDE_XFER_ABORT) { |
| + return PLDM_ERROR_INVALID_DATA; |
| + } |
| + return PLDM_SUCCESS; |
| +} |
| + |
| +int encode_rde_multipart_receive_resp( |
| + uint8_t instance_id, uint8_t completion_code, uint8_t transfer_flag, |
| + uint32_t next_data_transfer_handle, uint32_t data_length_bytes, |
| + bool add_checksum, uint32_t checksum, const uint8_t *payload, |
| + struct pldm_msg *msg) |
| +{ |
| + if (NULL == msg) { |
| + return PLDM_ERROR_INVALID_DATA; |
| + } |
| + struct pldm_header_info header = {0}; |
| + header.msg_type = PLDM_RESPONSE; |
| + header.instance = instance_id; |
| + header.pldm_type = PLDM_RDE; |
| + header.command = PLDM_RDE_MULTIPART_RECEIVE; |
| + uint8_t rc = pack_pldm_header(&header, &(msg->hdr)); |
| + if (rc != PLDM_SUCCESS) { |
| + return rc; |
| + } |
| + struct pldm_rde_multipart_receive_resp *response = |
| + (struct pldm_rde_multipart_receive_resp *)msg->payload; |
| + response->completion_code = completion_code; |
| + if (response->completion_code != PLDM_SUCCESS) { |
| + return PLDM_SUCCESS; |
| + } |
| + response->transfer_flag = transfer_flag; |
| + response->next_data_transfer_handle = |
| + htole32(next_data_transfer_handle); |
| + memcpy(response->payload, (uint8_t *)payload, data_length_bytes); |
| + uint32_t tot_length = data_length_bytes; |
| + if (add_checksum) { |
| + tot_length += 4; |
| + checksum = htole32(checksum); |
| + memcpy(response->payload + data_length_bytes, &checksum, |
| + sizeof(uint32_t)); |
| + } |
| + response->data_length_bytes = htole32(tot_length); |
| + return PLDM_SUCCESS; |
| +} |
| + |
| +int decode_rde_multipart_receive_resp( |
| + const struct pldm_msg *msg, size_t payload_length, uint8_t *completion_code, |
| + uint8_t *ret_transfer_flag, uint32_t *ret_data_transfer_handle, |
| + uint32_t *data_length_bytes, uint8_t **payload) |
| +{ |
| + if ((msg == NULL) || (completion_code == NULL) || |
| + (ret_transfer_flag == NULL) || (ret_data_transfer_handle == NULL) || |
| + (data_length_bytes == NULL) || (payload == NULL)) { |
| + return PLDM_ERROR_INVALID_DATA; |
| + } |
| + |
| + *completion_code = msg->payload[0]; |
| + |
| + if (PLDM_SUCCESS != *completion_code) { |
| + fprintf(stderr, "Decoded successfully with failed completion " |
| + "code in multipart\n"); |
| + return PLDM_ERROR; |
| + } |
| + |
| + if (payload_length < RDE_MULTIPART_RECV_MINIMUM_RESP_BYTES) { |
| + fprintf(stderr, "Decoded successfully with invalid payload " |
| + "length in multipart\n"); |
| + return PLDM_ERROR_INVALID_LENGTH; |
| + } |
| + |
| + struct pldm_rde_multipart_receive_resp *response = |
| + (struct pldm_rde_multipart_receive_resp *)msg->payload; |
| + *ret_transfer_flag = response->transfer_flag; |
| + *ret_data_transfer_handle = |
| + le32toh(response->next_data_transfer_handle); |
| + *data_length_bytes = le32toh(response->data_length_bytes); |
| + *payload = &response->payload[0]; |
| + return PLDM_SUCCESS; |
| +} |
| + |
| +int encode_rde_operation_init_req( |
| + uint8_t instance_id, uint32_t resource_id, uint16_t operation_id, |
| + uint8_t operation_type, |
| + const union pldm_rde_operation_flags *operation_flags, |
| + uint32_t send_data_transfer_handle, uint8_t operation_locator_length, |
| + uint32_t request_payload_length, const uint8_t *operation_locator, |
| + uint8_t *request_payload, struct pldm_msg *msg) |
| +{ |
| + if ((msg == NULL) || (operation_flags == NULL)) { |
| + return PLDM_ERROR_INVALID_DATA; |
| + } |
| + if ((operation_locator_length > 0) && (operation_locator == NULL)) { |
| + return PLDM_ERROR_INVALID_DATA; |
| + } |
| + if ((request_payload_length > 0) && (request_payload == NULL)) { |
| + return PLDM_ERROR_INVALID_DATA; |
| + } |
| + struct pldm_header_info header = {0}; |
| + header.instance = instance_id; |
| + header.pldm_type = PLDM_RDE; |
| + header.msg_type = PLDM_REQUEST; |
| + header.command = PLDM_RDE_OPERATION_INIT; |
| + uint8_t rc = pack_pldm_header(&header, &(msg->hdr)); |
| + if (rc != PLDM_SUCCESS) { |
| + return rc; |
| + } |
| + struct pldm_rde_operation_init_req *req = |
| + (struct pldm_rde_operation_init_req *)msg->payload; |
| + req->resource_id = htole32(resource_id); |
| + req->operation_id = htole16(operation_id); |
| + req->operation_type = operation_type; |
| + req->operation_flags.byte = operation_flags->byte; |
| + req->send_data_transfer_handle = htole32(send_data_transfer_handle); |
| + req->operation_locator_length = operation_locator_length; |
| + req->request_payload_length = htole32(request_payload_length); |
| + if (operation_locator_length > 0) { |
| + memcpy(req->var_data, (uint8_t *)operation_locator, |
| + operation_locator_length); |
| + } |
| + if (request_payload_length > 0) { |
| + memcpy(req->var_data + operation_locator_length, |
| + (uint8_t *)request_payload, request_payload_length); |
| + request_payload = NULL; |
| + } |
| + return PLDM_SUCCESS; |
| +} |
| + |
| +static bool pldm_rde_is_valid_mc_op_id(uint16_t operation_id) |
| +{ |
| + // Operation identifiers with the MSBit set are reserved for use by the |
| + // MC. Operation identifiers with the MSBit clear are reserved for use |
| + // by the RDE Device. The value 0x0000 is reserved to indicate no |
| + // Operation. |
| + if ((operation_id == 0) || ((operation_id >> 15) == 0)) { |
| + return false; |
| + } |
| + return true; |
| +} |
| + |
| +int decode_rde_operation_init_req( |
| + const struct pldm_msg *msg, size_t payload_length, uint32_t *resource_id, |
| + uint16_t *operation_id, uint8_t *operation_type, |
| + union pldm_rde_operation_flags *operation_flags, |
| + uint32_t *send_data_transfer_handle, uint8_t *operation_locator_length, |
| + uint32_t *request_payload_length, uint8_t **operation_locator, |
| + uint8_t **request_payload) |
| +{ |
| + if ((msg == NULL) || (resource_id == NULL) || (operation_id == NULL) || |
| + (operation_type == NULL) || (operation_flags == NULL) || |
| + (send_data_transfer_handle == NULL) || |
| + (operation_locator_length == NULL) || |
| + (request_payload_length == NULL)) { |
| + return PLDM_ERROR_INVALID_DATA; |
| + } |
| + if (payload_length < PLDM_RDE_OPERATION_INIT_REQ_HDR_SIZE) { |
| + return PLDM_ERROR_INVALID_LENGTH; |
| + } |
| + struct pldm_rde_operation_init_req *request = |
| + (struct pldm_rde_operation_init_req *)msg->payload; |
| + *operation_id = le16toh(request->operation_id); |
| + if (!pldm_rde_is_valid_mc_op_id(*operation_id)) { |
| + return PLDM_ERROR_INVALID_DATA; |
| + } |
| + *resource_id = le32toh(request->resource_id); |
| + *operation_type = request->operation_type; |
| + operation_flags->byte = request->operation_flags.byte; |
| + *send_data_transfer_handle = |
| + le32toh(request->send_data_transfer_handle); |
| + *operation_locator_length = request->operation_locator_length; |
| + *request_payload_length = le32toh(request->request_payload_length); |
| + if (*operation_locator_length > 0) { |
| + *operation_locator = request->var_data; |
| + } else { |
| + *operation_locator = NULL; |
| + } |
| + if (*request_payload_length > 0) { |
| + *request_payload = |
| + request->var_data + *operation_locator_length; |
| + } else { |
| + *request_payload = NULL; |
| + } |
| + return PLDM_SUCCESS; |
| +} |
| + |
| +int encode_rde_operation_init_resp( |
| + uint8_t instance_id, uint8_t completion_code, uint8_t operation_status, |
| + uint8_t completion_percentage, uint32_t completion_time_seconds, |
| + const union pldm_rde_op_execution_flags *operation_execution_flags, |
| + uint32_t result_transfer_handle, |
| + const union pldm_rde_permission_flags *permission_flags, |
| + uint32_t response_payload_length, |
| + enum pldm_rde_varstring_format etag_format, const char *etag, |
| + const uint8_t *response_payload, struct pldm_msg *msg) |
| +{ |
| + if ((msg == NULL) || (operation_execution_flags == NULL) || |
| + (permission_flags == NULL)) { |
| + return PLDM_ERROR_INVALID_DATA; |
| + } |
| + if ((response_payload_length > 0) && (response_payload == 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_RDE; |
| + header.command = PLDM_RDE_OPERATION_INIT; |
| + uint8_t rc = pack_pldm_header(&header, &(msg->hdr)); |
| + if (rc != PLDM_SUCCESS) { |
| + return rc; |
| + } |
| + struct pldm_rde_operation_init_resp *response = |
| + (struct pldm_rde_operation_init_resp *)msg->payload; |
| + response->completion_code = completion_code; |
| + if (response->completion_code != PLDM_SUCCESS) { |
| + return PLDM_SUCCESS; |
| + } |
| + response->operation_status = operation_status; |
| + response->completion_percentage = completion_percentage; |
| + response->completion_time_seconds = htole32(completion_time_seconds); |
| + response->operation_execution_flags.byte = |
| + operation_execution_flags->byte; |
| + response->result_transfer_handle = htole32(result_transfer_handle); |
| + response->permission_flags.byte = permission_flags->byte; |
| + response->response_payload_length = htole32(response_payload_length); |
| + struct pldm_rde_varstring *resp_etag = |
| + (struct pldm_rde_varstring *)response->var_data; |
| + resp_etag->string_format = etag_format; |
| + // length should include NULL terminator. |
| + size_t etag_len_wo_null = strlen(etag); |
| + resp_etag->string_length_bytes = etag_len_wo_null + 1; |
| + // Copy including NULL terminator. |
| + memcpy(resp_etag->string_data, etag, resp_etag->string_length_bytes); |
| + // Copy the payload. |
| + if (response_payload_length > 0) { |
| + memcpy(response->var_data + sizeof(struct pldm_rde_varstring) + |
| + etag_len_wo_null, |
| + (uint8_t *)response_payload, response_payload_length); |
| + } |
| + return PLDM_SUCCESS; |
| +} |
| + |
| +int decode_rde_operation_init_resp( |
| + const struct pldm_msg *msg, size_t payload_length, uint8_t *completion_code, |
| + uint8_t *completion_percentage, uint8_t *operation_status, |
| + uint32_t *completion_time_seconds, uint32_t *result_transfer_handle, |
| + uint32_t *response_payload_length, |
| + union pldm_rde_permission_flags **permission_flags, |
| + union pldm_rde_op_execution_flags **operation_execution_flags, |
| + struct pldm_rde_varstring **resp_etag, uint8_t **response_payload) |
| +{ |
| + if (msg == NULL) { |
| + return PLDM_ERROR_INVALID_DATA; |
| + } |
| + *completion_code = msg->payload[0]; |
| + if (PLDM_SUCCESS != *completion_code) { |
| + fprintf(stderr, |
| + "Decoded successfully with failed completion code\n"); |
| + return PLDM_SUCCESS; |
| + } |
| + |
| + if (payload_length < RDE_READ_OPERATION_INIT_MIN_BYTES) { |
| + fprintf(stderr, |
| + "Decoded successfully with failed payload length\n"); |
| + return PLDM_ERROR_INVALID_LENGTH; |
| + } |
| + |
| + struct pldm_rde_operation_init_resp *response = |
| + (struct pldm_rde_operation_init_resp *)msg->payload; |
| + |
| + *operation_status = response->operation_status; |
| + *completion_percentage = response->completion_percentage; |
| + *completion_time_seconds = le32toh(response->completion_time_seconds); |
| + (*operation_execution_flags)->byte = |
| + response->operation_execution_flags.byte; |
| + *result_transfer_handle = le32toh(response->result_transfer_handle); |
| + (*permission_flags)->byte = response->permission_flags.byte; |
| + *response_payload_length = le32toh(response->response_payload_length); |
| + |
| + *resp_etag = (struct pldm_rde_varstring *)response->var_data; |
| + |
| + if (*operation_status == PLDM_RDE_OPERATION_COMPLETED) { |
| + *response_payload = &(*resp_etag)->string_data[0] + |
| + (*resp_etag)->string_length_bytes; |
| + } |
| + return 0; |
| +} |
| + |
| +int encode_rde_operation_complete_req(uint8_t instance_id, uint32_t resource_id, |
| + uint16_t operation_id, |
| + struct pldm_msg *msg) |
| +{ |
| + if (msg == NULL) { |
| + return PLDM_ERROR_INVALID_DATA; |
| + } |
| + struct pldm_header_info header = {0}; |
| + header.instance = instance_id; |
| + header.pldm_type = PLDM_RDE; |
| + header.msg_type = PLDM_REQUEST; |
| + header.command = PLDM_RDE_OPERATION_COMPLETE; |
| + uint8_t rc = pack_pldm_header(&header, &(msg->hdr)); |
| + if (rc != PLDM_SUCCESS) { |
| + return rc; |
| + } |
| + struct pldm_rde_operation_complete_req *req = |
| + (struct pldm_rde_operation_complete_req *)msg->payload; |
| + req->resource_id = htole32(resource_id); |
| + req->operation_id = htole16(operation_id); |
| + return PLDM_SUCCESS; |
| +} |
| + |
| +int decode_rde_operation_complete_req(const struct pldm_msg *msg, |
| + size_t payload_length, |
| + uint32_t *resource_id, |
| + uint16_t *operation_id) |
| +{ |
| + if ((msg == NULL) || (resource_id == NULL) || (operation_id == NULL)) { |
| + return PLDM_ERROR_INVALID_DATA; |
| + } |
| + if (payload_length < sizeof(struct pldm_rde_operation_complete_req)) { |
| + return PLDM_ERROR_INVALID_LENGTH; |
| + } |
| + struct pldm_rde_operation_complete_req *request = |
| + (struct pldm_rde_operation_complete_req *)msg->payload; |
| + *resource_id = le32toh(request->resource_id); |
| + *operation_id = le16toh(request->operation_id); |
| + return PLDM_SUCCESS; |
| +} |
| + |
| +int encode_rde_operation_complete_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_RDE; |
| + header.command = PLDM_RDE_OPERATION_COMPLETE; |
| + uint8_t rc = pack_pldm_header(&header, &(msg->hdr)); |
| + if (rc != PLDM_SUCCESS) { |
| + return rc; |
| + } |
| + struct pldm_rde_operation_complete_resp *response = |
| + (struct pldm_rde_operation_complete_resp *)msg->payload; |
| + response->completion_code = completion_code; |
| + return PLDM_SUCCESS; |
| +} |
| + |
| +int decode_rde_operation_complete_resp(const struct pldm_msg *msg, |
| + size_t payload_length, |
| + uint8_t *completion_code) |
| +{ |
| + if (msg == NULL) { |
| + fprintf(stderr, "Invalid message object\n"); |
| + return PLDM_ERROR_INVALID_DATA; |
| + } |
| + if (payload_length < 1) { |
| + fprintf(stderr, "Invalid payload length\n"); |
| + return PLDM_ERROR_INVALID_LENGTH; |
| + } |
| + |
| + *completion_code = msg->payload[0]; |
| + |
| + if (PLDM_SUCCESS != *completion_code) { |
| + fprintf(stderr, |
| + "Decoded successfully with failed completion code\n"); |
| + return PLDM_SUCCESS; |
| + } |
| + return PLDM_SUCCESS; |
| +} |
| + |
| +int encode_rde_operation_status_req(uint8_t instance_id, uint32_t resource_id, |
| + uint16_t operation_id, struct pldm_msg *msg) |
| +{ |
| + if (msg == NULL) { |
| + return PLDM_ERROR_INVALID_DATA; |
| + } |
| + struct pldm_header_info header = {0}; |
| + header.instance = instance_id; |
| + header.pldm_type = PLDM_RDE; |
| + header.msg_type = PLDM_REQUEST; |
| + header.command = PLDM_RDE_OPERATION_STATUS; |
| + uint8_t rc = pack_pldm_header(&header, &(msg->hdr)); |
| + if (rc != PLDM_SUCCESS) { |
| + return rc; |
| + } |
| + struct pldm_rde_operation_status_req *req = |
| + (struct pldm_rde_operation_status_req *)msg->payload; |
| + req->resource_id = htole32(resource_id); |
| + req->operation_id = htole16(operation_id); |
| + return PLDM_SUCCESS; |
| +} |
| + |
| +int decode_rde_operation_status_req(const struct pldm_msg *msg, |
| + size_t payload_length, |
| + uint32_t *resource_id, |
| + uint16_t *operation_id) |
| +{ |
| + if ((msg == NULL) || (resource_id == NULL) || (operation_id == NULL)) { |
| + return PLDM_ERROR_INVALID_DATA; |
| + } |
| + if (payload_length < sizeof(struct pldm_rde_operation_status_req)) { |
| + return PLDM_ERROR_INVALID_LENGTH; |
| + } |
| + struct pldm_rde_operation_status_req *request = |
| + (struct pldm_rde_operation_status_req *)msg->payload; |
| + *resource_id = le32toh(request->resource_id); |
| + *operation_id = le16toh(request->operation_id); |
| + return PLDM_SUCCESS; |
| +} |
| + |
| +int encode_rde_operation_status_resp( |
| + uint8_t instance_id, uint8_t completion_code, uint8_t operation_status, |
| + uint8_t completion_percentage, uint32_t completion_time_seconds, |
| + const union pldm_rde_op_execution_flags *operation_execution_flags, |
| + uint32_t result_transfer_handle, |
| + const union pldm_rde_permission_flags *permission_flags, |
| + uint32_t response_payload_length, |
| + enum pldm_rde_varstring_format etag_format, const char *etag, |
| + const uint8_t *response_payload, struct pldm_msg *msg) |
| +{ |
| + if ((msg == NULL) || (operation_execution_flags == NULL) || |
| + (permission_flags == NULL)) { |
| + return PLDM_ERROR_INVALID_DATA; |
| + } |
| + if ((response_payload_length > 0) && (response_payload == 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_RDE; |
| + header.command = PLDM_RDE_OPERATION_STATUS; |
| + uint8_t rc = pack_pldm_header(&header, &(msg->hdr)); |
| + if (rc != PLDM_SUCCESS) { |
| + return rc; |
| + } |
| + struct pldm_rde_operation_status_resp *response = |
| + (struct pldm_rde_operation_status_resp *)msg->payload; |
| + response->completion_code = completion_code; |
| + if (response->completion_code != PLDM_SUCCESS) { |
| + return PLDM_SUCCESS; |
| + } |
| + response->operation_status = operation_status; |
| + response->completion_percentage = completion_percentage; |
| + response->completion_time_seconds = htole32(completion_time_seconds); |
| + response->operation_execution_flags.byte = |
| + operation_execution_flags->byte; |
| + response->result_transfer_handle = htole32(result_transfer_handle); |
| + response->permission_flags.byte = permission_flags->byte; |
| + response->response_payload_length = htole32(response_payload_length); |
| + struct pldm_rde_varstring *resp_etag = |
| + (struct pldm_rde_varstring *)response->var_data; |
| + resp_etag->string_format = etag_format; |
| + // length should include NULL terminator. |
| + size_t etag_len_wo_null = strlen(etag); |
| + resp_etag->string_length_bytes = etag_len_wo_null + 1; |
| + // Copy including NULL terminator. |
| + memcpy(resp_etag->string_data, etag, resp_etag->string_length_bytes); |
| + // Copy the payload. |
| + if (response_payload_length > 0) { |
| + memcpy(response->var_data + sizeof(struct pldm_rde_varstring) + |
| + etag_len_wo_null, |
| + (uint8_t *)response_payload, response_payload_length); |
| + } |
| + return PLDM_SUCCESS; |
| +} |
| + |
| +int decode_rde_operation_status_resp( |
| + const struct pldm_msg *msg, size_t payload_length, uint8_t *completion_code, |
| + uint8_t *completion_percentage, uint8_t *operation_status, |
| + uint32_t *completion_time_seconds, uint32_t *result_transfer_handle, |
| + uint32_t *response_payload_length, |
| + union pldm_rde_permission_flags **permission_flags, |
| + union pldm_rde_op_execution_flags **operation_execution_flags, |
| + struct pldm_rde_varstring **resp_etag, uint8_t **response_payload) |
| +{ |
| + if (msg == NULL) { |
| + fprintf(stderr, "Invalid msg object\n"); |
| + return PLDM_ERROR_INVALID_DATA; |
| + } |
| + |
| + *completion_code = msg->payload[0]; |
| + if (PLDM_SUCCESS != *completion_code) { |
| + fprintf(stderr, |
| + "Decoded successfully with failed completion code\n"); |
| + return PLDM_SUCCESS; |
| + } |
| + |
| + if (payload_length < RDE_READ_OPERATION_INIT_MIN_BYTES) { |
| + fprintf(stderr, |
| + "Decoded sucessfully with failed payload length\n"); |
| + return PLDM_ERROR_INVALID_LENGTH; |
| + } |
| + |
| + struct pldm_rde_operation_init_resp *response = |
| + (struct pldm_rde_operation_init_resp *)msg->payload; |
| + |
| + *operation_status = response->operation_status; |
| + *completion_percentage = response->completion_percentage; |
| + *completion_time_seconds = le32toh(response->completion_time_seconds); |
| + (*operation_execution_flags)->byte = |
| + response->operation_execution_flags.byte; |
| + *result_transfer_handle = le32toh(response->result_transfer_handle); |
| + (*permission_flags)->byte = response->permission_flags.byte; |
| + *response_payload_length = le32toh(response->response_payload_length); |
| + |
| + *resp_etag = (struct pldm_rde_varstring *)response->var_data; |
| + if (*operation_status == PLDM_RDE_OPERATION_COMPLETED) { |
| + *response_payload = &(*resp_etag)->string_data[0] + |
| + (*resp_etag)->string_length_bytes; |
| + } |
| + return 0; |
| +} |
| diff --git a/tests/libpldm_rde_test.cpp b/tests/libpldm_rde_test.cpp |
| new file mode 100644 |
| index 0000000..56e322b |
| --- /dev/null |
| +++ b/tests/libpldm_rde_test.cpp |
| @@ -0,0 +1,889 @@ |
| +#include <endian.h> |
| + |
| +#include "libpldm/pldm_rde.h" |
| + |
| +#include <gmock/gmock-matchers.h> |
| +#include <gmock/gmock.h> |
| +#include <gtest/gtest.h> |
| +TEST(NegotiateRedfishParametersTest, EncodeResponseSuccess) |
| +{ |
| + uint8_t completionCode = 0; |
| + uint8_t instanceId = 11; |
| + uint8_t deviceConcurrencySupport = 1; |
| + bitfield8_t deviceCapabilitiesFlags = {.byte = 0x3F}; |
| + bitfield16_t deviceFeatureSupport = {.value = 0x7389}; |
| + uint32_t deviceConfigurationSignature = 0xABCDEF12; |
| + constexpr const char* device = "This is a test"; |
| + // Already has the space for the null character in sizeof(struct |
| + // pldm_rde_negotiate_redfish_parameters_resp). |
| + std::array<uint8_t, |
| + sizeof(struct pldm_msg_hdr) + |
| + sizeof(struct pldm_rde_negotiate_redfish_parameters_resp) + |
| + 14> |
| + responseMsg{}; |
| + auto response = reinterpret_cast<pldm_msg*>(responseMsg.data()); |
| + EXPECT_EQ(encode_negotiate_redfish_parameters_resp( |
| + instanceId, completionCode, deviceConcurrencySupport, |
| + deviceCapabilitiesFlags, deviceFeatureSupport, |
| + deviceConfigurationSignature, device, |
| + PLDM_RDE_VARSTRING_ASCII, response), |
| + PLDM_SUCCESS); |
| + // verify header. |
| + EXPECT_EQ(response->hdr.instance_id, instanceId); |
| + EXPECT_EQ(response->hdr.request, 0); |
| + EXPECT_EQ(response->hdr.type, PLDM_RDE); |
| + EXPECT_EQ(response->hdr.command, PLDM_NEGOTIATE_REDFISH_PARAMETERS); |
| + // verify payload. |
| + auto resp_payload = |
| + reinterpret_cast<pldm_rde_negotiate_redfish_parameters_resp*>( |
| + response->payload); |
| + EXPECT_EQ(resp_payload->completion_code, completionCode); |
| + EXPECT_EQ(resp_payload->device_concurrency_support, |
| + deviceConcurrencySupport); |
| + EXPECT_EQ(resp_payload->device_capabilities_flags.byte, |
| + deviceCapabilitiesFlags.byte); |
| + EXPECT_EQ(le16toh(resp_payload->device_feature_support.value), |
| + deviceFeatureSupport.value); |
| + EXPECT_EQ(le32toh(resp_payload->device_configuration_signature), |
| + deviceConfigurationSignature); |
| + EXPECT_EQ(resp_payload->device_provider_name.string_format, |
| + PLDM_RDE_VARSTRING_ASCII); |
| + EXPECT_EQ(resp_payload->device_provider_name.string_length_bytes, |
| + strlen(device) + 1); |
| + EXPECT_EQ(memcmp(resp_payload->device_provider_name.string_data, device, |
| + strlen(device) + 1), |
| + 0); |
| +} |
| +TEST(NegotiateRedfishParametersTest, EncodeRequestSuccess) |
| +{ |
| + uint8_t instanceId = 11; |
| + uint8_t mcConcurrencySupport = 13; |
| + bitfield16_t mcFeatureSupport = {.value = 0x7389}; |
| + std::array<uint8_t, |
| + sizeof(struct pldm_msg_hdr) + |
| + sizeof(struct pldm_rde_negotiate_redfish_parameters_req)> |
| + requestMsg{}; |
| + auto request = reinterpret_cast<pldm_msg*>(requestMsg.data()); |
| + auto req_payload = |
| + reinterpret_cast<pldm_rde_negotiate_redfish_parameters_req*>( |
| + request->payload); |
| + EXPECT_EQ(encode_negotiate_redfish_parameters_req( |
| + instanceId, mcConcurrencySupport, &mcFeatureSupport, request), |
| + PLDM_SUCCESS); |
| + EXPECT_EQ(request->hdr.instance_id, instanceId); |
| + EXPECT_EQ(request->hdr.type, PLDM_RDE); |
| + EXPECT_EQ(request->hdr.request, 1); |
| + EXPECT_EQ(request->hdr.command, PLDM_NEGOTIATE_REDFISH_PARAMETERS); |
| + EXPECT_EQ(req_payload->mc_concurrency_support, mcConcurrencySupport); |
| + EXPECT_EQ(le16toh(req_payload->mc_feature_support.value), |
| + mcFeatureSupport.value); |
| +} |
| +TEST(NegotiateRedfishParametersTest, DecodeRequestSuccess) |
| +{ |
| + uint8_t mcConcurrencySupport = 1; |
| + bitfield16_t mcFeatureSupport = {.value = 0x7389}; |
| + std::array<uint8_t, |
| + sizeof(struct pldm_msg_hdr) + |
| + sizeof(struct pldm_rde_negotiate_redfish_parameters_req)> |
| + requestMsg{}; |
| + auto request = reinterpret_cast<pldm_msg*>(requestMsg.data()); |
| + auto req_payload = |
| + reinterpret_cast<pldm_rde_negotiate_redfish_parameters_req*>( |
| + request->payload); |
| + req_payload->mc_concurrency_support = mcConcurrencySupport; |
| + req_payload->mc_feature_support.value = htole16(mcFeatureSupport.value); |
| + uint8_t decodedMcConcurrencySupport; |
| + bitfield16_t decodedMcFeatureSupport; |
| + EXPECT_EQ(decode_negotiate_redfish_parameters_req( |
| + request, |
| + sizeof(struct pldm_rde_negotiate_redfish_parameters_req), |
| + &decodedMcConcurrencySupport, &decodedMcFeatureSupport), |
| + PLDM_SUCCESS); |
| + EXPECT_EQ(decodedMcConcurrencySupport, mcConcurrencySupport); |
| + EXPECT_EQ(decodedMcFeatureSupport.value, mcFeatureSupport.value); |
| +} |
| +TEST(NegotiateMediumParametersTest, EncodeRequestSuccess) |
| +{ |
| + uint8_t instanceId = 11; |
| + uint32_t maxTranferSize = 0xABCDEF18; |
| + std::array<uint8_t, |
| + sizeof(struct pldm_msg_hdr) + |
| + sizeof(struct pldm_rde_negotiate_medium_parameters_req)> |
| + requestMsg{}; |
| + auto request = reinterpret_cast<pldm_msg*>(requestMsg.data()); |
| + auto req_payload = |
| + reinterpret_cast<pldm_rde_negotiate_medium_parameters_req*>( |
| + request->payload); |
| + EXPECT_EQ(encode_negotiate_medium_parameters_req(instanceId, maxTranferSize, |
| + request), |
| + PLDM_SUCCESS); |
| + EXPECT_EQ(request->hdr.instance_id, instanceId); |
| + EXPECT_EQ(request->hdr.type, PLDM_RDE); |
| + EXPECT_EQ(request->hdr.request, 1); |
| + EXPECT_EQ(request->hdr.command, PLDM_NEGOTIATE_MEDIUM_PARAMETERS); |
| + EXPECT_EQ(le32toh(req_payload->mc_maximum_transfer_chunk_size_bytes), |
| + maxTranferSize); |
| +} |
| +TEST(NegotiateMediumParametersTest, DecodeRequestSuccess) |
| +{ |
| + uint32_t mcSize = 0x10000000; |
| + std::array<uint8_t, |
| + sizeof(struct pldm_msg_hdr) + |
| + sizeof(struct pldm_rde_negotiate_medium_parameters_req)> |
| + requestMsg{}; |
| + auto request = reinterpret_cast<pldm_msg*>(requestMsg.data()); |
| + auto req_payload = |
| + reinterpret_cast<pldm_rde_negotiate_medium_parameters_req*>( |
| + request->payload); |
| + req_payload->mc_maximum_transfer_chunk_size_bytes = htole32(mcSize); |
| + uint32_t decodedMcSize; |
| + EXPECT_EQ(decode_negotiate_medium_parameters_req( |
| + request, |
| + sizeof(struct pldm_rde_negotiate_medium_parameters_req), |
| + &decodedMcSize), |
| + PLDM_SUCCESS); |
| + EXPECT_EQ(decodedMcSize, mcSize); |
| +} |
| +TEST(NegotiateMediumParametersTest, EncodeResponseSuccess) |
| +{ |
| + uint8_t completionCode = 0; |
| + uint8_t instanceId = 11; |
| + uint32_t deviceSize = 0x10000000; |
| + std::array<uint8_t, |
| + sizeof(struct pldm_msg_hdr) + |
| + sizeof(struct pldm_rde_negotiate_medium_parameters_resp)> |
| + responseMsg{}; |
| + auto response = reinterpret_cast<pldm_msg*>(responseMsg.data()); |
| + EXPECT_EQ(encode_negotiate_medium_parameters_resp( |
| + instanceId, completionCode, deviceSize, response), |
| + PLDM_SUCCESS); |
| + // verify header. |
| + EXPECT_EQ(response->hdr.instance_id, instanceId); |
| + EXPECT_EQ(response->hdr.request, 0); |
| + EXPECT_EQ(response->hdr.type, PLDM_RDE); |
| + EXPECT_EQ(response->hdr.command, PLDM_NEGOTIATE_MEDIUM_PARAMETERS); |
| + // verify payload. |
| + auto resp_payload = |
| + reinterpret_cast<pldm_rde_negotiate_medium_parameters_resp*>( |
| + response->payload); |
| + EXPECT_EQ(resp_payload->completion_code, completionCode); |
| + EXPECT_EQ(le32toh(resp_payload->device_maximum_transfer_chunk_size_bytes), |
| + deviceSize); |
| +} |
| +TEST(GetSchemaDictionaryTest, EncodeRequestSuccess) |
| +{ |
| + uint8_t instanceId = 11; |
| + uint8_t schema_class = 1; |
| + uint32_t resourceId = 0xABCDEF18; |
| + std::array<uint8_t, sizeof(struct pldm_msg_hdr) + |
| + sizeof(struct pldm_rde_get_schema_dictionary_req)> |
| + requestMsg{}; |
| + auto request = reinterpret_cast<pldm_msg*>(requestMsg.data()); |
| + auto req_payload = |
| + reinterpret_cast<pldm_rde_get_schema_dictionary_req*>(request->payload); |
| + EXPECT_EQ(encode_get_schema_dictionary_req(instanceId, resourceId, |
| + schema_class, request), |
| + PLDM_SUCCESS); |
| + EXPECT_EQ(request->hdr.instance_id, instanceId); |
| + EXPECT_EQ(request->hdr.type, PLDM_RDE); |
| + EXPECT_EQ(request->hdr.request, 1); |
| + EXPECT_EQ(request->hdr.command, PLDM_GET_SCHEMA_DICTIONARY); |
| + EXPECT_EQ(le32toh(req_payload->resource_id), resourceId); |
| + EXPECT_EQ(req_payload->requested_schema_class, schema_class); |
| +} |
| +TEST(GetSchemaDictionaryTest, DecodeRequestSuccess) |
| +{ |
| + uint32_t resourceId = 0xABCDEF12; |
| + std::array<uint8_t, sizeof(struct pldm_msg_hdr) + |
| + sizeof(struct pldm_rde_get_schema_dictionary_req)> |
| + requestMsg{}; |
| + auto request = reinterpret_cast<pldm_msg*>(requestMsg.data()); |
| + auto req_payload = |
| + reinterpret_cast<pldm_rde_get_schema_dictionary_req*>(request->payload); |
| + req_payload->resource_id = htole32(resourceId); |
| + req_payload->requested_schema_class = PLDM_RDE_SCHEMA_ANNOTATION; |
| + uint32_t decodedResourceId; |
| + uint8_t decodedSchemaClass; |
| + EXPECT_EQ(decode_get_schema_dictionary_req( |
| + request, sizeof(struct pldm_rde_get_schema_dictionary_req), |
| + &decodedResourceId, &decodedSchemaClass), |
| + PLDM_SUCCESS); |
| + EXPECT_EQ(decodedResourceId, resourceId); |
| + EXPECT_EQ(decodedSchemaClass, PLDM_RDE_SCHEMA_ANNOTATION); |
| +} |
| +TEST(GetSchemaDictionaryTest, EncodeResponseSuccess) |
| +{ |
| + uint8_t completionCode = 0; |
| + uint8_t instanceId = 11; |
| + uint8_t dictionaryFormat = 0x00; |
| + uint32_t transferHandle = 0xABCDEF12; |
| + std::array<uint8_t, sizeof(struct pldm_msg_hdr) + |
| + sizeof(struct pldm_rde_get_schema_dictionary_resp)> |
| + responseMsg{}; |
| + auto response = reinterpret_cast<pldm_msg*>(responseMsg.data()); |
| + EXPECT_EQ(encode_get_schema_dictionary_resp(instanceId, completionCode, |
| + dictionaryFormat, |
| + transferHandle, response), |
| + PLDM_SUCCESS); |
| + // verify header. |
| + EXPECT_EQ(response->hdr.instance_id, instanceId); |
| + EXPECT_EQ(response->hdr.request, 0); |
| + EXPECT_EQ(response->hdr.type, PLDM_RDE); |
| + EXPECT_EQ(response->hdr.command, PLDM_GET_SCHEMA_DICTIONARY); |
| + // verify payload. |
| + auto resp_payload = reinterpret_cast<pldm_rde_get_schema_dictionary_resp*>( |
| + response->payload); |
| + EXPECT_EQ(resp_payload->completion_code, completionCode); |
| + EXPECT_EQ(resp_payload->dictionary_format, dictionaryFormat); |
| + EXPECT_EQ(le32toh(resp_payload->transfer_handle), transferHandle); |
| +} |
| +TEST(NegotiateRedfishParamsTest, DecodeResponseSuccess) |
| +{ |
| + uint8_t completionCode = 0; |
| + uint8_t instanceId = 11; |
| + uint8_t deviceConcurrencySupport = 1; |
| + bitfield8_t deviceCapabilitiesFlags = {.byte = 0x3F}; |
| + bitfield16_t deviceFeatureSupport = {.value = 0x7389}; |
| + uint32_t deviceConfigurationSignature = 0xABCDEF12; |
| + constexpr const char* device = "This is a test"; |
| + |
| + std::array<uint8_t, |
| + sizeof(struct pldm_msg_hdr) + |
| + sizeof(struct pldm_rde_negotiate_redfish_parameters_resp) + |
| + 14> |
| + responseMsg{}; |
| + auto response = reinterpret_cast<pldm_msg*>(responseMsg.data()); |
| + auto deviceInfo = std::make_unique<pldm_rde_device_info>(); |
| + uint8_t cc; |
| + encode_negotiate_redfish_parameters_resp( |
| + instanceId, completionCode, deviceConcurrencySupport, |
| + deviceCapabilitiesFlags, deviceFeatureSupport, |
| + deviceConfigurationSignature, device, PLDM_RDE_VARSTRING_ASCII, |
| + response); |
| + EXPECT_EQ( |
| + decode_negotiate_redfish_parameters_resp( |
| + response, |
| + sizeof(struct pldm_rde_negotiate_redfish_parameters_resp) + 14, &cc, |
| + deviceInfo.get()), |
| + PLDM_SUCCESS); |
| + |
| + EXPECT_EQ(deviceInfo.get()->device_capabilities_flag.byte, |
| + deviceCapabilitiesFlags.byte); |
| + EXPECT_EQ(deviceInfo.get()->device_feature_support.value, |
| + deviceFeatureSupport.value); |
| + EXPECT_EQ(deviceInfo.get()->device_configuration_signature, |
| + deviceConfigurationSignature); |
| + EXPECT_EQ(cc, completionCode); |
| + EXPECT_EQ(deviceInfo.get()->device_concurrency, deviceConcurrencySupport); |
| +} |
| +TEST(NegotiateMediumParams, DecodeResponseSuccess) |
| +{ |
| + uint8_t completionCode = 0; |
| + uint8_t instanceId = 11; |
| + uint32_t deviceSize = 0x10000000; |
| + std::array<uint8_t, |
| + sizeof(struct pldm_msg_hdr) + |
| + sizeof(struct pldm_rde_negotiate_medium_parameters_resp)> |
| + responseMsg{}; |
| + auto response = reinterpret_cast<pldm_msg*>(responseMsg.data()); |
| + EXPECT_EQ(encode_negotiate_medium_parameters_resp( |
| + instanceId, completionCode, deviceSize, response), |
| + PLDM_SUCCESS); |
| + |
| + // verify payload. |
| + auto resp_payload = |
| + reinterpret_cast<pldm_rde_negotiate_medium_parameters_resp*>( |
| + response->payload); |
| + EXPECT_EQ(resp_payload->completion_code, completionCode); |
| + EXPECT_EQ(le32toh(resp_payload->device_maximum_transfer_chunk_size_bytes), |
| + deviceSize); |
| + |
| + uint8_t cc; |
| + uint32_t deviceMaxTransferBytes; |
| + EXPECT_EQ(decode_negotiate_medium_parameters_resp( |
| + response, |
| + sizeof(struct pldm_msg_hdr) + |
| + sizeof(struct pldm_rde_negotiate_medium_parameters_resp), |
| + &cc, &deviceMaxTransferBytes), |
| + PLDM_SUCCESS); |
| + EXPECT_EQ(deviceMaxTransferBytes, deviceSize); |
| +} |
| +TEST(GetSchemaDictionary, DecodeResponseSuccess) |
| +{ |
| + uint8_t completionCode = 0; |
| + uint8_t instanceId = 11; |
| + uint8_t dictionaryFormat = 0x00; |
| + uint32_t transferHandle = 0xABCDEF12; |
| + constexpr int payloadLength = |
| + sizeof(struct pldm_msg_hdr) + |
| + sizeof(struct pldm_rde_get_schema_dictionary_resp); |
| + std::array<uint8_t, payloadLength> responseMsg{}; |
| + auto response = reinterpret_cast<pldm_msg*>(responseMsg.data()); |
| + EXPECT_EQ(encode_get_schema_dictionary_resp(instanceId, completionCode, |
| + dictionaryFormat, |
| + transferHandle, response), |
| + PLDM_SUCCESS); |
| + uint8_t cc, returnDictionaryFormat; |
| + uint32_t returnTransferHandle; |
| + EXPECT_EQ(decode_get_schema_dictionary_resp(response, payloadLength, &cc, |
| + &returnDictionaryFormat, |
| + &returnTransferHandle), |
| + PLDM_SUCCESS); |
| + EXPECT_EQ(cc, completionCode); |
| + EXPECT_EQ(returnDictionaryFormat, dictionaryFormat); |
| + EXPECT_EQ(returnTransferHandle, transferHandle); |
| +} |
| +TEST(MultipartReceive, EncodeRequestSuccess) |
| +{ |
| + uint8_t instanceId = 11; |
| + uint32_t transferHandle = 0xABCDEF12; |
| + uint16_t operationId = 0x01; |
| + uint8_t transferOperation = PLDM_XFER_FIRST_PART; |
| + constexpr int reqLength = |
| + sizeof(struct pldm_msg_hdr) + PLDM_MULTIPART_RECEIVE_REQ_BYTES; |
| + std::array<uint8_t, reqLength> requestMsg{}; |
| + auto request = reinterpret_cast<pldm_msg*>(requestMsg.data()); |
| + auto reqPayload = |
| + reinterpret_cast<pldm_rde_multipart_receive_req*>(request->payload); |
| + EXPECT_EQ(encode_rde_multipart_receive_req(instanceId, transferHandle, |
| + operationId, transferOperation, |
| + request), |
| + PLDM_SUCCESS); |
| + EXPECT_EQ(request->hdr.instance_id, instanceId); |
| + EXPECT_EQ(request->hdr.type, PLDM_RDE); |
| + EXPECT_EQ(request->hdr.request, 1); |
| + EXPECT_EQ(request->hdr.command, PLDM_RDE_MULTIPART_RECEIVE); |
| + EXPECT_EQ(reqPayload->operation_id, operationId); |
| + EXPECT_EQ(reqPayload->data_transfer_handle, transferHandle); |
| + EXPECT_EQ(reqPayload->transfer_operation, transferOperation); |
| +} |
| +TEST(MultipartReceive, DecodeRequestSuccess) |
| +{ |
| + uint8_t instanceId = 11; |
| + uint32_t transferHandle = 0xABCDEF12; |
| + uint16_t operationId = 0x01; |
| + uint8_t transferOperation = PLDM_XFER_FIRST_PART; |
| + constexpr int reqLength = |
| + sizeof(struct pldm_msg_hdr) + PLDM_MULTIPART_RECEIVE_REQ_BYTES; |
| + std::array<uint8_t, reqLength> requestMsg{}; |
| + auto request = reinterpret_cast<pldm_msg*>(requestMsg.data()); |
| + EXPECT_EQ(encode_rde_multipart_receive_req(instanceId, transferHandle, |
| + operationId, transferOperation, |
| + request), |
| + PLDM_SUCCESS); |
| + |
| + uint32_t returnTransferHandle; |
| + uint16_t returnOperationId; |
| + uint8_t returnTransferOperation; |
| + EXPECT_EQ(decode_rde_multipart_receive_req( |
| + request, sizeof(struct pldm_rde_multipart_receive_req), |
| + &returnTransferHandle, &returnOperationId, |
| + &returnTransferOperation), |
| + PLDM_SUCCESS); |
| + EXPECT_EQ(returnOperationId, operationId); |
| + EXPECT_EQ(returnTransferHandle, transferHandle); |
| + EXPECT_EQ(returnTransferOperation, transferOperation); |
| +} |
| +TEST(MultipartReceive, EncodeResponseSuccess) |
| +{ |
| + uint8_t completionCode = 0; |
| + uint8_t instanceId = 11; |
| + uint8_t transferOperation = PLDM_XFER_FIRST_PART; |
| + uint32_t transferHandle = 0xABCDEF12; |
| + |
| + uint8_t payload[] = {0x01, 0x02, 0x03}; |
| + constexpr int payloadSize = sizeof(struct pldm_msg_hdr) + |
| + sizeof(struct pldm_rde_multipart_receive_resp) + |
| + /*payload array size*/ 3; |
| + std::array<uint8_t, payloadSize> responseMsg{}; |
| + auto response = reinterpret_cast<pldm_msg*>(responseMsg.data()); |
| + |
| + EXPECT_EQ(encode_rde_multipart_receive_resp( |
| + instanceId, completionCode, transferOperation, transferHandle, |
| + /*payload array size*/ 3, |
| + /*addChecksum*/ false, /*checksum*/ 0x00, &payload[0], |
| + response), |
| + PLDM_SUCCESS); |
| + |
| + // // verify header. |
| + EXPECT_EQ(response->hdr.instance_id, instanceId); |
| + EXPECT_EQ(response->hdr.request, 0); |
| + EXPECT_EQ(response->hdr.type, PLDM_RDE); |
| + EXPECT_EQ(response->hdr.command, PLDM_RDE_MULTIPART_RECEIVE); |
| + // // verify payload. |
| + auto resp_payload = |
| + reinterpret_cast<pldm_rde_multipart_receive_resp*>(response->payload); |
| + EXPECT_EQ(resp_payload->completion_code, completionCode); |
| + EXPECT_EQ(resp_payload->transfer_flag, transferOperation); |
| + EXPECT_EQ(resp_payload->next_data_transfer_handle, transferHandle); |
| + EXPECT_EQ(resp_payload->data_length_bytes, /*payload array size*/ 3); |
| +} |
| +TEST(MultipartReceive, DecodeResponseSuccess) |
| +{ |
| + uint8_t completionCode = 0; |
| + uint8_t instanceId = 11; |
| + uint8_t transferOperation = PLDM_XFER_FIRST_PART; |
| + uint32_t transferHandle = 0xABCDEF12; |
| + |
| + uint8_t payload[] = {0x01, 0x02, 0x03}; |
| + constexpr size_t payloadSize = 3; |
| + constexpr int responseSize = |
| + sizeof(struct pldm_msg_hdr) + |
| + sizeof(struct pldm_rde_multipart_receive_resp) + |
| + /*payload array size*/ payloadSize; |
| + std::array<uint8_t, responseSize> responseMsg{}; |
| + auto response = reinterpret_cast<pldm_msg*>(responseMsg.data()); |
| + |
| + EXPECT_EQ(encode_rde_multipart_receive_resp( |
| + instanceId, completionCode, transferOperation, transferHandle, |
| + /*payload array size*/ payloadSize, |
| + /*addChecksum*/ false, /*checksum*/ 0x00, &payload[0], |
| + response), |
| + PLDM_SUCCESS); |
| + |
| + uint8_t cc; |
| + uint8_t returnTransferFlag; |
| + uint32_t returnTransferHandle; |
| + uint32_t returnDataLenBytes; |
| + |
| + uint8_t* returnPayload; |
| + EXPECT_EQ(decode_rde_multipart_receive_resp( |
| + response, /*ASSUME_MAX_SIZE*/ 256, &cc, &returnTransferFlag, |
| + &returnTransferHandle, &returnDataLenBytes, &returnPayload), |
| + PLDM_SUCCESS); |
| + EXPECT_EQ(cc, completionCode); |
| + EXPECT_EQ(returnTransferFlag, transferOperation); |
| + EXPECT_EQ(returnDataLenBytes, payloadSize); |
| +} |
| + |
| +TEST(RDEOperationInit, EncodeRequestSuccess) |
| +{ |
| + uint8_t instanceId = 11; |
| + uint32_t resourceId = 0x0001000; |
| + uint16_t operationId = 32770; |
| + uint8_t operationType = PLDM_RDE_OPERATION_READ; |
| + auto operationFlags = std::make_unique<union pldm_rde_operation_flags>(); |
| + operationFlags.get()->byte = 0x00; |
| + uint32_t transferHandle = 0xABCDEF12; |
| + constexpr size_t requestSize = sizeof(struct pldm_msg_hdr) + |
| + sizeof(struct pldm_rde_operation_init_req); |
| + std::array<uint8_t, requestSize> requestMsg{}; |
| + auto request = reinterpret_cast<pldm_msg*>(requestMsg.data()); |
| + |
| + EXPECT_EQ(encode_rde_operation_init_req(instanceId, resourceId, operationId, |
| + operationType, operationFlags.get(), |
| + transferHandle, 0, 0, NULL, NULL, |
| + request), |
| + PLDM_SUCCESS); |
| + |
| + // Test Header values |
| + EXPECT_EQ(request->hdr.instance_id, instanceId); |
| + EXPECT_EQ(request->hdr.request, PLDM_REQUEST); |
| + EXPECT_EQ(request->hdr.type, PLDM_RDE); |
| + EXPECT_EQ(request->hdr.command, PLDM_RDE_OPERATION_INIT); |
| + |
| + // Test payload values |
| + auto reqPayload = |
| + reinterpret_cast<pldm_rde_operation_init_req*>(request->payload); |
| + EXPECT_EQ(reqPayload->resource_id, resourceId); |
| + EXPECT_EQ(reqPayload->operation_id, operationId); |
| + EXPECT_EQ(reqPayload->operation_type, operationType); |
| + EXPECT_EQ(reqPayload->operation_flags.byte, operationFlags.get()->byte); |
| + EXPECT_EQ(reqPayload->operation_locator_length, 0); |
| + EXPECT_EQ(reqPayload->request_payload_length, 0); |
| +} |
| + |
| +TEST(RDEOperationInit, DecodeRequestSuccess) |
| +{ |
| + uint8_t instanceId = 11; |
| + uint32_t resourceId = 0x0001000; |
| + uint16_t operationId = 32770; |
| + uint8_t operationType = PLDM_RDE_OPERATION_READ; |
| + auto operationFlags = std::make_unique<union pldm_rde_operation_flags>(); |
| + operationFlags.get()->byte = 0x00; |
| + uint32_t transferHandle = 0xABCDEF12; |
| + constexpr size_t requestSize = sizeof(struct pldm_msg_hdr) + |
| + sizeof(struct pldm_rde_operation_init_req); |
| + std::array<uint8_t, requestSize> requestMsg{}; |
| + auto request = reinterpret_cast<pldm_msg*>(requestMsg.data()); |
| + |
| + encode_rde_operation_init_req(instanceId, resourceId, operationId, |
| + operationType, operationFlags.get(), |
| + transferHandle, 0, 0, NULL, NULL, request); |
| + |
| + uint32_t returnResourceId; |
| + uint16_t returnOperationId; |
| + uint8_t returnOperationType; |
| + uint32_t returnSendTransferHandle; |
| + uint8_t returnOperationLocatorLength; |
| + uint32_t returnRequestPayloadLength; |
| + uint8_t* returnOperationLocator = std::make_unique<uint8_t>().get(); |
| + uint8_t* returnRequestPayload = std::make_unique<uint8_t>().get(); |
| + union pldm_rde_operation_flags returnOperationFlags; |
| + |
| + EXPECT_EQ(decode_rde_operation_init_req( |
| + request, sizeof(struct pldm_rde_operation_init_req), |
| + &returnResourceId, &returnOperationId, &returnOperationType, |
| + &returnOperationFlags, &returnSendTransferHandle, |
| + &returnOperationLocatorLength, &returnRequestPayloadLength, |
| + &returnOperationLocator, &returnRequestPayload), |
| + PLDM_SUCCESS); |
| + EXPECT_EQ(returnResourceId, resourceId); |
| + EXPECT_EQ(returnOperationId, operationId); |
| + EXPECT_EQ(returnOperationType, operationType); |
| + EXPECT_EQ(returnSendTransferHandle, transferHandle); |
| + EXPECT_EQ(returnOperationFlags.byte, operationFlags.get()->byte); |
| + EXPECT_EQ(returnOperationLocatorLength, 0); |
| + EXPECT_EQ(returnRequestPayloadLength, 0); |
| +} |
| + |
| +TEST(RDEOperationInit, EncodeResponseSuccess) |
| +{ |
| + uint8_t completionCode = 0; |
| + uint8_t instanceId = 11; |
| + uint8_t operationStatus = PLDM_RDE_OPERATION_COMPLETED; |
| + uint8_t completionPercentage = 100; |
| + uint32_t completionTimeSeconds = 1; |
| + union pldm_rde_op_execution_flags operationExecutionFlags; |
| + operationExecutionFlags.byte = 0x01; |
| + uint32_t resultTransferHandle = 0x01; |
| + union pldm_rde_permission_flags permissionFlags; |
| + permissionFlags.byte = 0x02; |
| + enum pldm_rde_varstring_format etagFormat = PLDM_RDE_VARSTRING_UTF_8; |
| + const char etag[] = "etag"; |
| + |
| + constexpr size_t responsePayloadLength = |
| + sizeof(struct pldm_msg_hdr) + |
| + sizeof(struct pldm_rde_operation_init_resp) + 4; |
| + std::array<uint8_t, responsePayloadLength> responseMsg{}; |
| + auto response = reinterpret_cast<pldm_msg*>(responseMsg.data()); |
| + EXPECT_EQ(encode_rde_operation_init_resp( |
| + instanceId, completionCode, operationStatus, |
| + completionPercentage, completionTimeSeconds, |
| + &operationExecutionFlags, resultTransferHandle, |
| + &permissionFlags, 0, etagFormat, etag, NULL, response), |
| + PLDM_SUCCESS); |
| + // verify header. |
| + EXPECT_EQ(response->hdr.instance_id, instanceId); |
| + EXPECT_EQ(response->hdr.request, 0); |
| + EXPECT_EQ(response->hdr.type, PLDM_RDE); |
| + EXPECT_EQ(response->hdr.command, PLDM_RDE_OPERATION_INIT); |
| + // verify payload. |
| + auto respPayload = |
| + reinterpret_cast<pldm_rde_operation_init_resp*>(response->payload); |
| + EXPECT_EQ(respPayload->completion_code, completionCode); |
| + EXPECT_EQ(respPayload->operation_status, operationStatus); |
| + EXPECT_EQ(respPayload->completion_percentage, completionPercentage); |
| + EXPECT_EQ(respPayload->completion_time_seconds, completionTimeSeconds); |
| + EXPECT_EQ(respPayload->operation_execution_flags.byte, |
| + operationExecutionFlags.byte); |
| + EXPECT_EQ(respPayload->permission_flags.byte, permissionFlags.byte); |
| +} |
| + |
| +TEST(RDEOperationInit, DecodeResponseSuccess) |
| +{ |
| + uint8_t completionCode = 0; |
| + uint8_t instanceId = 11; |
| + uint8_t operationStatus = PLDM_RDE_OPERATION_COMPLETED; |
| + uint8_t completionPercentage = 100; |
| + uint32_t completionTimeSeconds = 1; |
| + union pldm_rde_op_execution_flags operationExecutionFlags; |
| + operationExecutionFlags.byte = 0x01; |
| + uint32_t resultTransferHandle = 0x01; |
| + union pldm_rde_permission_flags permissionFlags; |
| + permissionFlags.byte = 0x02; |
| + enum pldm_rde_varstring_format etagFormat = PLDM_RDE_VARSTRING_UTF_8; |
| + const char etag[] = "etag"; |
| + |
| + constexpr size_t responsePayloadLength = |
| + sizeof(struct pldm_msg_hdr) + |
| + sizeof(struct pldm_rde_operation_init_resp) + 4; |
| + std::array<uint8_t, responsePayloadLength> responseMsg{}; |
| + auto response = reinterpret_cast<pldm_msg*>(responseMsg.data()); |
| + EXPECT_EQ(encode_rde_operation_init_resp( |
| + instanceId, completionCode, operationStatus, |
| + completionPercentage, completionTimeSeconds, |
| + &operationExecutionFlags, resultTransferHandle, |
| + &permissionFlags, 0, etagFormat, etag, NULL, response), |
| + PLDM_SUCCESS); |
| + |
| + uint8_t returnCompletionCode; |
| + uint8_t returnOperationStatus; |
| + uint8_t returnCompletionPercentage; |
| + uint32_t returnCompletionTimeSeconds; |
| + uint32_t returnTransferHandle; |
| + uint32_t returnResponsePayloadLength; |
| + |
| + union pldm_rde_op_execution_flags* returnExecutionFlags = |
| + (union pldm_rde_op_execution_flags*)malloc( |
| + sizeof(union pldm_rde_op_execution_flags)); |
| + union pldm_rde_permission_flags* returnPermissionFlags = |
| + (union pldm_rde_permission_flags*)malloc( |
| + sizeof(union pldm_rde_permission_flags)); |
| + |
| + auto returnEtag = std::make_unique<pldm_rde_varstring>().get(); |
| + auto responsePayload = std::make_unique<uint8_t>().get(); |
| + EXPECT_EQ(decode_rde_operation_init_resp( |
| + response, responsePayloadLength, &returnCompletionCode, |
| + &returnCompletionPercentage, &returnOperationStatus, |
| + &returnCompletionTimeSeconds, &returnTransferHandle, |
| + &returnResponsePayloadLength, &returnPermissionFlags, |
| + &returnExecutionFlags, &returnEtag, &responsePayload), |
| + PLDM_SUCCESS); |
| + |
| + EXPECT_EQ(returnCompletionCode, completionCode); |
| + EXPECT_EQ(returnCompletionPercentage, completionPercentage); |
| + EXPECT_EQ(returnOperationStatus, operationStatus); |
| + EXPECT_EQ(returnCompletionTimeSeconds, completionTimeSeconds); |
| + EXPECT_EQ(returnTransferHandle, resultTransferHandle); |
| + EXPECT_EQ(returnResponsePayloadLength, 0); |
| + EXPECT_EQ(returnPermissionFlags->byte, permissionFlags.byte); |
| + EXPECT_EQ(returnExecutionFlags->byte, operationExecutionFlags.byte); |
| + EXPECT_EQ(returnEtag->string_length_bytes, |
| + std::end(etag) - std::begin(etag)); |
| +} |
| +TEST(RDEOperationComplete, EncodeRequestSuccess) |
| +{ |
| + uint8_t instanceId = 11; |
| + uint32_t resourceId = 0x0001000; |
| + uint16_t operationId = 32770; |
| + constexpr size_t requestSize = |
| + sizeof(struct pldm_msg_hdr) + |
| + sizeof(struct pldm_rde_operation_complete_req); |
| + std::array<uint8_t, requestSize> requestMsg{}; |
| + auto request = reinterpret_cast<pldm_msg*>(requestMsg.data()); |
| + |
| + EXPECT_EQ(encode_rde_operation_complete_req(instanceId, resourceId, |
| + operationId, request), |
| + PLDM_SUCCESS); |
| + // Test Headers |
| + EXPECT_EQ(request->hdr.instance_id, instanceId); |
| + EXPECT_EQ(request->hdr.type, PLDM_RDE); |
| + EXPECT_EQ(request->hdr.request, PLDM_REQUEST); |
| + EXPECT_EQ(request->hdr.command, PLDM_RDE_OPERATION_COMPLETE); |
| + |
| + auto reqPayload = |
| + reinterpret_cast<pldm_rde_operation_complete_req*>(request->payload); |
| + EXPECT_EQ(reqPayload->resource_id, resourceId); |
| + EXPECT_EQ(reqPayload->operation_id, operationId); |
| +} |
| + |
| +TEST(RDEOperationComplete, DecodeRequestSuccess) |
| +{ |
| + uint8_t instanceId = 11; |
| + uint32_t resourceId = 0x0001000; |
| + uint16_t operationId = 32770; |
| + constexpr size_t requestSize = |
| + sizeof(struct pldm_msg_hdr) + |
| + sizeof(struct pldm_rde_operation_complete_req); |
| + std::array<uint8_t, requestSize> requestMsg{}; |
| + auto request = reinterpret_cast<pldm_msg*>(requestMsg.data()); |
| + |
| + EXPECT_EQ(encode_rde_operation_complete_req(instanceId, resourceId, |
| + operationId, request), |
| + PLDM_SUCCESS); |
| + |
| + uint16_t returnOperationId; |
| + uint32_t returnResourceId; |
| + EXPECT_EQ(decode_rde_operation_status_req( |
| + request, requestSize, &returnResourceId, &returnOperationId), |
| + PLDM_SUCCESS); |
| + |
| + EXPECT_EQ(returnOperationId, operationId); |
| + EXPECT_EQ(returnResourceId, resourceId); |
| +} |
| + |
| +TEST(RDEOperationComplete, EncodeResponseSuccess) |
| +{ |
| + uint8_t instanceId = 11; |
| + uint32_t completionCode = 0; |
| + constexpr size_t responseSize = |
| + sizeof(struct pldm_msg_hdr) + |
| + sizeof(struct pldm_rde_operation_complete_resp); |
| + std::array<uint8_t, responseSize> responseMsg{}; |
| + auto response = reinterpret_cast<pldm_msg*>(responseMsg.data()); |
| + |
| + EXPECT_EQ(encode_rde_operation_complete_resp(instanceId, completionCode, |
| + response), |
| + PLDM_SUCCESS); |
| + |
| + EXPECT_EQ(response->hdr.instance_id, instanceId); |
| + EXPECT_EQ(response->hdr.request, PLDM_RESPONSE); |
| + EXPECT_EQ(response->hdr.type, PLDM_RDE); |
| + EXPECT_EQ(response->hdr.command, PLDM_RDE_OPERATION_COMPLETE); |
| + |
| + auto respPayload = |
| + reinterpret_cast<pldm_rde_operation_init_resp*>(response->payload); |
| + |
| + EXPECT_EQ(respPayload->completion_code, completionCode); |
| +} |
| + |
| +TEST(RDEOperationComplete, DecodeResponseSuccess) |
| +{ |
| + uint8_t instanceId = 11; |
| + uint32_t completionCode = 0; |
| + constexpr size_t responseSize = |
| + sizeof(struct pldm_msg_hdr) + |
| + sizeof(struct pldm_rde_operation_complete_resp); |
| + std::array<uint8_t, responseSize> responseMsg{}; |
| + auto response = reinterpret_cast<pldm_msg*>(responseMsg.data()); |
| + |
| + encode_rde_operation_complete_resp(instanceId, completionCode, response); |
| + |
| + uint8_t cc; |
| + EXPECT_EQ(decode_rde_operation_complete_resp(response, responseSize, &cc), |
| + PLDM_SUCCESS); |
| + EXPECT_EQ(cc, PLDM_SUCCESS); |
| +} |
| +TEST(RDEOperationStatus, EncodeRequestSuccess) |
| +{ |
| + uint8_t instanceId = 11; |
| + uint32_t resourceId = 0x0001000; |
| + uint16_t operationId = 32770; |
| + |
| + constexpr size_t requestSize = sizeof(struct pldm_msg_hdr) + |
| + sizeof(struct pldm_rde_operation_status_req); |
| + std::array<uint8_t, requestSize> requestMsg{}; |
| + auto request = reinterpret_cast<pldm_msg*>(requestMsg.data()); |
| + |
| + EXPECT_EQ(encode_rde_operation_status_req(instanceId, resourceId, |
| + operationId, request), |
| + PLDM_SUCCESS); |
| + |
| + // Test Header values |
| + EXPECT_EQ(request->hdr.instance_id, instanceId); |
| + EXPECT_EQ(request->hdr.request, PLDM_REQUEST); |
| + EXPECT_EQ(request->hdr.type, PLDM_RDE); |
| + EXPECT_EQ(request->hdr.command, PLDM_RDE_OPERATION_STATUS); |
| + |
| + // Test payload values |
| + auto reqPayload = |
| + reinterpret_cast<pldm_rde_operation_status_req*>(request->payload); |
| + EXPECT_EQ(reqPayload->resource_id, resourceId); |
| + EXPECT_EQ(reqPayload->operation_id, operationId); |
| +} |
| +TEST(RDEOperationStatus, DecodeRequestSuccess) |
| +{ |
| + uint8_t instanceId = 11; |
| + uint32_t resourceId = 0x0001000; |
| + uint16_t operationId = 32770; |
| + |
| + constexpr size_t requestSize = sizeof(struct pldm_msg_hdr) + |
| + sizeof(struct pldm_rde_operation_status_req); |
| + std::array<uint8_t, requestSize> requestMsg{}; |
| + auto request = reinterpret_cast<pldm_msg*>(requestMsg.data()); |
| + |
| + encode_rde_operation_status_req(instanceId, resourceId, operationId, |
| + request); |
| + uint32_t returnResourceId; |
| + uint16_t returnOperationId; |
| + EXPECT_EQ(decode_rde_operation_status_req( |
| + request, requestSize, &returnResourceId, &returnOperationId), |
| + PLDM_SUCCESS); |
| + EXPECT_EQ(returnResourceId, resourceId); |
| + EXPECT_EQ(returnOperationId, operationId); |
| +} |
| +TEST(RDEOperationStatus, EncodeResponseSuccess) |
| +{ |
| + uint8_t completionCode = 0; |
| + uint8_t instanceId = 11; |
| + uint8_t operationStatus = PLDM_RDE_OPERATION_COMPLETED; |
| + uint8_t completionPercentage = 100; |
| + uint32_t completionTimeSeconds = 1; |
| + union pldm_rde_op_execution_flags operationExecutionFlags; |
| + operationExecutionFlags.byte = 0x01; |
| + uint32_t resultTransferHandle = 0x01; |
| + union pldm_rde_permission_flags permissionFlags; |
| + permissionFlags.byte = 0x02; |
| + enum pldm_rde_varstring_format etagFormat = PLDM_RDE_VARSTRING_UTF_8; |
| + const char etag[] = "etag"; |
| + |
| + constexpr size_t responsePayloadLength = |
| + sizeof(struct pldm_msg_hdr) + |
| + sizeof(struct pldm_rde_operation_status_resp) + 4; |
| + std::array<uint8_t, responsePayloadLength> responseMsg{}; |
| + auto response = reinterpret_cast<pldm_msg*>(responseMsg.data()); |
| + EXPECT_EQ(encode_rde_operation_status_resp( |
| + instanceId, completionCode, operationStatus, |
| + completionPercentage, completionTimeSeconds, |
| + &operationExecutionFlags, resultTransferHandle, |
| + &permissionFlags, 0, etagFormat, etag, NULL, response), |
| + PLDM_SUCCESS); |
| + // verify header. |
| + EXPECT_EQ(response->hdr.instance_id, instanceId); |
| + EXPECT_EQ(response->hdr.request, 0); |
| + EXPECT_EQ(response->hdr.type, PLDM_RDE); |
| + EXPECT_EQ(response->hdr.command, PLDM_RDE_OPERATION_STATUS); |
| + // verify payload. |
| + auto respPayload = |
| + reinterpret_cast<pldm_rde_operation_status_resp*>(response->payload); |
| + EXPECT_EQ(respPayload->completion_code, completionCode); |
| + EXPECT_EQ(respPayload->operation_status, operationStatus); |
| + EXPECT_EQ(respPayload->completion_percentage, completionPercentage); |
| + EXPECT_EQ(respPayload->completion_time_seconds, completionTimeSeconds); |
| + EXPECT_EQ(respPayload->operation_execution_flags.byte, |
| + operationExecutionFlags.byte); |
| + EXPECT_EQ(respPayload->permission_flags.byte, permissionFlags.byte); |
| +} |
| +TEST(RDEOperationStatus, DecodeResponseSuccess) |
| +{ |
| + uint8_t completionCode = 0; |
| + uint8_t instanceId = 11; |
| + uint8_t operationStatus = PLDM_RDE_OPERATION_COMPLETED; |
| + uint8_t completionPercentage = 100; |
| + uint32_t completionTimeSeconds = 1; |
| + union pldm_rde_op_execution_flags operationExecutionFlags; |
| + operationExecutionFlags.byte = 0x01; |
| + uint32_t resultTransferHandle = 0x01; |
| + union pldm_rde_permission_flags permissionFlags; |
| + permissionFlags.byte = 0x02; |
| + enum pldm_rde_varstring_format etagFormat = PLDM_RDE_VARSTRING_UTF_8; |
| + const char etag[] = "etag"; |
| + |
| + constexpr size_t responsePayloadLength = |
| + sizeof(struct pldm_msg_hdr) + |
| + sizeof(struct pldm_rde_operation_status_resp) + 4; |
| + std::array<uint8_t, responsePayloadLength> responseMsg{}; |
| + auto response = reinterpret_cast<pldm_msg*>(responseMsg.data()); |
| + EXPECT_EQ(encode_rde_operation_status_resp( |
| + instanceId, completionCode, operationStatus, |
| + completionPercentage, completionTimeSeconds, |
| + &operationExecutionFlags, resultTransferHandle, |
| + &permissionFlags, 0, etagFormat, etag, NULL, response), |
| + PLDM_SUCCESS); |
| + |
| + uint8_t returnCompletionCode; |
| + uint8_t returnOperationStatus; |
| + uint8_t returnCompletionPercentage; |
| + uint32_t returnCompletionTimeSeconds; |
| + uint32_t returnTransferHandle; |
| + uint32_t returnResponsePayloadLength; |
| + |
| + union pldm_rde_op_execution_flags* returnExecutionFlags = |
| + (union pldm_rde_op_execution_flags*)malloc( |
| + sizeof(union pldm_rde_op_execution_flags)); |
| + union pldm_rde_permission_flags* returnPermissionFlags = |
| + (union pldm_rde_permission_flags*)malloc( |
| + sizeof(union pldm_rde_permission_flags)); |
| + |
| + auto returnEtag = std::make_unique<pldm_rde_varstring>().get(); |
| + auto responsePayload = std::make_unique<uint8_t>().get(); |
| + EXPECT_EQ(decode_rde_operation_status_resp( |
| + response, responsePayloadLength, &returnCompletionCode, |
| + &returnCompletionPercentage, &returnOperationStatus, |
| + &returnCompletionTimeSeconds, &returnTransferHandle, |
| + &returnResponsePayloadLength, &returnPermissionFlags, |
| + &returnExecutionFlags, &returnEtag, &responsePayload), |
| + PLDM_SUCCESS); |
| + |
| + EXPECT_EQ(returnCompletionCode, completionCode); |
| + EXPECT_EQ(returnCompletionPercentage, completionPercentage); |
| + EXPECT_EQ(returnOperationStatus, operationStatus); |
| + EXPECT_EQ(returnCompletionTimeSeconds, completionTimeSeconds); |
| + EXPECT_EQ(returnTransferHandle, resultTransferHandle); |
| + EXPECT_EQ(returnResponsePayloadLength, 0); |
| + EXPECT_EQ(returnPermissionFlags->byte, permissionFlags.byte); |
| + EXPECT_EQ(returnExecutionFlags->byte, operationExecutionFlags.byte); |
| + EXPECT_EQ(returnEtag->string_length_bytes, |
| + std::end(etag) - std::begin(etag)); |
| +} |
| diff --git a/tests/meson.build b/tests/meson.build |
| index a15e7ec..0449c3d 100644 |
| --- a/tests/meson.build |
| +++ b/tests/meson.build |
| @@ -26,6 +26,7 @@ tests = [ |
| 'msgbuf', |
| 'responder', |
| 'requester/base_requester_test', |
| + 'libpldm_rde_test', |
| ] |
| |
| if get_option('abi').contains('testing') |
| -- |
| 2.43.0.rc2.451.g8631bc7472-goog |
| |