xref: /openbmc/libpldm/include/libpldm/base.h (revision cf26f2a32939c0d0f5d4826f5dbb014981c5b173)
1 /* SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later */
2 #ifndef BASE_H
3 #define BASE_H
4 
5 #ifdef __cplusplus
6 extern "C" {
7 #endif
8 
9 #include <libpldm/compiler.h>
10 #include <libpldm/pldm_types.h>
11 #include <libpldm/utils.h>
12 
13 #include <asm/byteorder.h>
14 #include <stdalign.h>
15 #include <stdbool.h>
16 #include <stddef.h>
17 #include <stdint.h>
18 
19 typedef uint8_t pldm_tid_t;
20 
21 /** @brief PLDM Types
22  */
23 enum pldm_supported_types {
24 	PLDM_BASE = 0x00,
25 	PLDM_SMBIOS = 0x01,
26 	PLDM_PLATFORM = 0x02,
27 	PLDM_BIOS = 0x03,
28 	PLDM_FRU = 0x04,
29 	PLDM_FWUP = 0x05,
30 	PLDM_RDE = 0x06,
31 	PLDM_FILE = 0x07,
32 	PLDM_OEM = 0x3f,
33 };
34 
35 /** @brief PLDM Commands
36  */
37 enum pldm_supported_commands {
38 	PLDM_SET_TID = 0x1,
39 	PLDM_GET_TID = 0x2,
40 	PLDM_GET_PLDM_VERSION = 0x3,
41 	PLDM_GET_PLDM_TYPES = 0x4,
42 	PLDM_GET_PLDM_COMMANDS = 0x5,
43 	PLDM_SELECT_PLDM_VERSION = 0x6,
44 	PLDM_NEGOTIATE_TRANSFER_PARAMETERS = 0x7,
45 	PLDM_MULTIPART_SEND = 0x8,
46 	PLDM_MULTIPART_RECEIVE = 0x9,
47 	PLDM_GET_MULTIPART_TRANSFER_SUPPORT = 0xa,
48 };
49 
50 /** @brief PLDM base codes
51  */
52 enum pldm_completion_codes {
53 	PLDM_SUCCESS = 0x00,
54 	PLDM_ERROR = 0x01,
55 	PLDM_ERROR_INVALID_DATA = 0x02,
56 	PLDM_ERROR_INVALID_LENGTH = 0x03,
57 	PLDM_ERROR_NOT_READY = 0x04,
58 	PLDM_ERROR_UNSUPPORTED_PLDM_CMD = 0x05,
59 	PLDM_ERROR_INVALID_PLDM_TYPE = 0x20,
60 	PLDM_INVALID_TRANSFER_OPERATION_FLAG = 0x21
61 };
62 
63 enum transfer_op_flag {
64 	PLDM_GET_NEXTPART = 0,
65 	PLDM_GET_FIRSTPART = 1,
66 	PLDM_ACKNOWLEDGEMENT_ONLY = 2,
67 };
68 
69 enum transfer_multipart_op_flag {
70 	PLDM_XFER_FIRST_PART = 0,
71 	PLDM_XFER_NEXT_PART = 1,
72 	PLDM_XFER_ABORT = 2,
73 	PLDM_XFER_COMPLETE = 3,
74 	PLDM_XFER_CURRENT_PART = 4,
75 };
76 
77 enum pldm_base_multipart_receive_transfer_flag {
78 	PLDM_BASE_MULTIPART_RECEIVE_TRANSFER_FLAG_START = 0x01,
79 	PLDM_BASE_MULTIPART_RECEIVE_TRANSFER_FLAG_MIDDLE = 0x02,
80 	PLDM_BASE_MULTIPART_RECEIVE_TRANSFER_FLAG_END = 0x04,
81 	PLDM_BASE_MULTIPART_RECEIVE_TRANSFER_FLAG_START_AND_END = 0x05,
82 	PLDM_BASE_MULTIPART_RECEIVE_TRANSFER_FLAG_ACK_COMPLETION = 0x08,
83 };
84 
85 enum transfer_resp_flag {
86 	PLDM_START = 0x01,
87 	PLDM_MIDDLE = 0x02,
88 	PLDM_END = 0x04,
89 	PLDM_START_AND_END = 0x05,
90 };
91 
92 /** @brief PLDM transport protocol type
93  */
94 enum pldm_transport_protocol_type {
95 	PLDM_TRANSPORT_PROTOCOL_TYPE_MCTP = 0x00,
96 	PLDM_TRANSPORT_PROTOCOL_TYPE_OEM = 0xff,
97 };
98 
99 /** @enum MessageType
100  *
101  *  The different message types supported by the PLDM specification.
102  */
103 typedef enum {
104 	PLDM_RESPONSE,		   //!< PLDM response
105 	PLDM_REQUEST,		   //!< PLDM request
106 	PLDM_RESERVED,		   //!< Reserved
107 	PLDM_ASYNC_REQUEST_NOTIFY, //!< Unacknowledged PLDM request messages
108 } MessageType;
109 
110 #define PLDM_INSTANCE_MAX      31
111 #define PLDM_MAX_TYPES	       64
112 #define PLDM_MAX_CMDS_PER_TYPE 256
113 #define PLDM_MAX_TIDS	       256
114 #define PLDM_TID_UNASSIGNED    0x00
115 #define PLDM_TID_RESERVED      0xff
116 
117 /* Message payload lengths */
118 #define PLDM_GET_COMMANDS_REQ_BYTES 5
119 #define PLDM_GET_VERSION_REQ_BYTES  6
120 
121 /* Response lengths are inclusive of completion code */
122 #define PLDM_GET_TYPES_REQ_BYTES     0
123 #define PLDM_GET_TYPES_RESP_BYTES    9
124 #define PLDM_GET_TID_REQ_BYTES	     0
125 #define PLDM_GET_TID_RESP_BYTES	     2
126 #define PLDM_SET_TID_REQ_BYTES	     1
127 #define PLDM_SET_TID_RESP_BYTES	     1
128 #define PLDM_GET_COMMANDS_RESP_BYTES 33
129 /* Response data has only one version and does not contain the checksum */
130 #define PLDM_GET_VERSION_RESP_BYTES		   10
131 #define PLDM_MULTIPART_RECEIVE_REQ_BYTES	   18
132 #define PLDM_BASE_MULTIPART_RECEIVE_RESP_MIN_BYTES 10
133 
134 #define PLDM_VERSION_0	     0
135 #define PLDM_CURRENT_VERSION PLDM_VERSION_0
136 
137 #define PLDM_TIMESTAMP104_SIZE 13
138 
139 /** @brief Minimum length of response for a optional PLDM command
140  *
141  *  For a optional PLDM command, the command handler might not be
142  *  implemented in a device's firmware, a response contains only CC
143  *  might come in, such as ERROR_UNSUPPORTED_PLDM_CMD.
144  *
145  *  The description can be found in DSP0240:
146  *  > For an unsupported PLDM command, the ERROR_UNSUPPORTED_PLDM_CMD
147  *  > completion code shall be returned unless the responder is in a
148  *  > transient state (not ready), in which it cannot process the PLDM
149  *  > command. If the responder is in a transient state, it may return
150  *  > the ERROR_NOT_READY completion code.
151  */
152 #define PLDM_OPTIONAL_COMMAND_RESP_MIN_LEN 1
153 
154 /** @struct pldm_msg_hdr
155  *
156  * Structure representing PLDM message header fields
157  */
158 struct pldm_msg_hdr {
159 #if defined(__LITTLE_ENDIAN_BITFIELD)
160 	uint8_t instance_id : 5; //!< Instance ID
161 	uint8_t reserved : 1;	 //!< Reserved
162 	uint8_t datagram : 1;	 //!< Datagram bit
163 	uint8_t request : 1;	 //!< Request bit
164 #elif defined(__BIG_ENDIAN_BITFIELD)
165 	uint8_t request : 1;	 //!< Request bit
166 	uint8_t datagram : 1;	 //!< Datagram bit
167 	uint8_t reserved : 1;	 //!< Reserved
168 	uint8_t instance_id : 5; //!< Instance ID
169 #endif
170 
171 #if defined(__LITTLE_ENDIAN_BITFIELD)
172 	uint8_t type : 6;	//!< PLDM type
173 	uint8_t header_ver : 2; //!< Header version
174 #elif defined(__BIG_ENDIAN_BITFIELD)
175 	uint8_t header_ver : 2; //!< Header version
176 	uint8_t type : 6;	//!< PLDM type
177 #endif
178 	uint8_t command; //!< PLDM command code
179 } __attribute__((packed));
180 
181 // Macros for byte-swapping variables in-place
182 #define HTOLE32(X) ((X) = htole32(X))
183 #define HTOLE16(X) ((X) = htole16(X))
184 #define LE32TOH(X) ((X) = le32toh(X))
185 #define LE16TOH(X) ((X) = le16toh(X))
186 
187 /** @struct pldm_msg
188  *
189  * Structure representing PLDM message
190  */
191 struct pldm_msg {
192 	struct pldm_msg_hdr hdr; //!< PLDM message header
193 	uint8_t payload[1]; //!< &payload[0] is the beginning of the payload
194 } __attribute__((packed));
195 
196 /** @brief Determine the underlying object size for a @struct pldm_msg
197  *
198  * @pre @p size must be a constant expression
199  *
200  * @note Providing an expression for @p size that is not an integer constant
201  *       expression will force a compilation failure.
202  *
203  * @param size The desired size of the @struct pldm_msg payload
204  */
205 #define PLDM_MSG_SIZE(size)                                                    \
206 	(sizeof(char[(__builtin_constant_p(size)) ? 1 : -1])) *                \
207 		(sizeof(struct pldm_msg) -                                     \
208 		 sizeof(((struct pldm_msg *)NULL)->payload) + (size))
209 
210 /** @brief Stack-allocate a buffer to hold a @struct pldm_msg
211  *
212  * Allocate an appropriately aligned array named @p name of type unsigned char
213  * with the necessary length to hold a payload of the requested size.
214  *
215  * @param name - The variable name used to define the buffer
216  * @param size - The desired payload length for the intended @struct pldm_msg
217  */
218 #define PLDM_MSG_BUFFER(name, size)                                            \
219 	alignas(struct pldm_msg) unsigned char(name)[PLDM_MSG_SIZE(size)]
220 
221 /** @brief Create a pointer to a stack-allocated @struct pldm_msg
222  *
223  * Define a pointer named @p name of type @struct pldm_msg to an object on the
224  * stack of appropriate alignment and length to hold a @struct pldm_msg with a
225  * payload of @p size.
226  *
227  * @param name - The variable name for pointer
228  * @param size - The desired payload length for the underlying @struct pldm_msg
229  *        buffer
230  */
231 #ifdef __cplusplus
232 #define PLDM_MSG_DEFINE_P(name, size)                                          \
233 	PLDM_MSG_BUFFER(name##_buf, size);                                     \
234 	auto *(name) = new (name##_buf) pldm_msg
235 #endif
236 
237 /**
238  * @brief Compare the headers from two PLDM messages to determine if the latter
239  * is a message representing a response to the former, where the former must be
240  * a request.
241  *
242  * @param[in] req - A pointer to a PLDM header object, which must represent a
243  *                  request
244  * @param[in] resp - A pointer to a PLDM header object, which may represent a
245  *		     response to the provided request.
246  *
247  * @return true if the header pointed to by resp represents a message that is a
248  *	   response to the header pointed to by req, otherwise false.
249  */
250 bool pldm_msg_hdr_correlate_response(const struct pldm_msg_hdr *req,
251 				     const struct pldm_msg_hdr *resp);
252 
253 /** @struct pldm_header_info
254  *
255  *  The information needed to prepare PLDM header and this is passed to the
256  *  pack_pldm_header and unpack_pldm_header API.
257  */
258 struct pldm_header_info {
259 	MessageType msg_type;	 //!< PLDM message type
260 	uint8_t instance;	 //!< PLDM instance id
261 	uint8_t pldm_type;	 //!< PLDM type
262 	uint8_t command;	 //!< PLDM command code
263 	uint8_t completion_code; //!< PLDM completion code, applies for response
264 };
265 
266 /** @struct pldm_get_types_resp
267  *
268  *  Structure representing PLDM get types response.
269  */
270 struct pldm_get_types_resp {
271 	uint8_t completion_code; //!< completion code
272 	bitfield8_t types[8]; //!< each bit represents whether a given PLDM Type
273 			      //!< is supported
274 } __attribute__((packed));
275 
276 /** @struct pldm_get_commands_req
277  *
278  *  Structure representing PLDM get commands request.
279  */
280 struct pldm_get_commands_req {
281 	uint8_t type;	 //!< PLDM Type for which command support information is
282 			 //!< being requested
283 	ver32_t version; //!< version for the specified PLDM Type
284 } __attribute__((packed));
285 
286 /** @struct pldm_get_commands_resp
287  *
288  *  Structure representing PLDM get commands response.
289  */
290 struct pldm_get_commands_resp {
291 	uint8_t completion_code;  //!< completion code
292 	bitfield8_t commands[32]; //!< each bit represents whether a given PLDM
293 				  //!< command is supported
294 } __attribute__((packed));
295 
296 /** @struct pldm_get_version_req
297  *
298  *  Structure representing PLDM get version request.
299  */
300 struct pldm_get_version_req {
301 	uint32_t transfer_handle; //!< handle to identify PLDM version data transfer
302 	uint8_t transfer_opflag; //!< PLDM GetVersion operation flag
303 	uint8_t type; //!< PLDM Type for which version information is being requested
304 } __attribute__((packed));
305 
306 /** @struct pldm_get_version_resp
307  *
308  *  Structure representing PLDM get version response.
309  */
310 
311 struct pldm_get_version_resp {
312 	uint8_t completion_code;       //!< completion code
313 	uint32_t next_transfer_handle; //!< next portion of PLDM version data
314 				       //!< transfer
315 	uint8_t transfer_flag;	       //!< PLDM GetVersion transfer flag
316 	uint8_t version_data[1];       //!< PLDM GetVersion version field
317 } __attribute__((packed));
318 
319 /** @struct pldm_set_tid_req
320  *
321  *  Structure representing PLDM set tid request.
322  */
323 
324 struct pldm_set_tid_req {
325 	uint8_t tid; //!< PLDM SetTID TID field
326 } __attribute__((packed));
327 
328 /** @struct pldm_get_tid_resp
329  *
330  *  Structure representing PLDM get tid response.
331  */
332 
333 struct pldm_get_tid_resp {
334 	uint8_t completion_code; //!< completion code
335 	uint8_t tid;		 //!< PLDM GetTID TID field
336 } __attribute__((packed));
337 
338 /** @struct pldm_multipart_receive_req
339  *
340  * Structure representing PLDM multipart receive request.
341  */
342 struct pldm_multipart_receive_req {
343 	uint8_t pldm_type;	  //!< PLDM Type for the MultipartReceive
344 				  //!< command.
345 	uint8_t transfer_opflag;  //!< PLDM MultipartReceive operation flag.
346 	uint32_t transfer_ctx;	  //!< Protocol-specifc context for this
347 				  //!< transfer.
348 	uint32_t transfer_handle; //!< handle to identify the part of data to be
349 				  //!< received.
350 	uint32_t section_offset;  //!< The start offset for the requested
351 				  //!< section.
352 	uint32_t section_length;  //!< The length (in bytes) of the section
353 				  //!< requested.
354 } __attribute__((packed));
355 
356 /** @struct pldm_multipart_receive_resp
357  *
358  * Structure representing PLDM multipart receive request.
359  */
360 struct pldm_multipart_receive_resp {
361 	uint8_t completion_code;       //!< Completion code of the command.
362 	uint8_t transfer_flag;	       //!< PLDM MultipartReceive transfer flag.
363 	uint32_t next_transfer_handle; //!< The handle for the next part of
364 				       //!< data for this section transfer.
365 	struct variable_field data;
366 };
367 
368 /**
369  * @brief Populate the PLDM message with the PLDM header.The caller of this API
370  *        allocates buffer for the PLDM header when forming the PLDM message.
371  *        The buffer is passed to this API to pack the PLDM header.
372  *
373  * @param[in] hdr - Pointer to the PLDM header information
374  * @param[out] msg - Pointer to PLDM message header
375  *
376  * @return 0 on success, otherwise PLDM error codes.
377  * @note   Caller is responsible for alloc and dealloc of msg
378  *         and hdr params
379  */
380 uint8_t pack_pldm_header(const struct pldm_header_info *hdr,
381 			 struct pldm_msg_hdr *msg);
382 
383 /**
384  * @brief Unpack the PLDM header from the PLDM message.
385  *
386  * @param[in] msg - Pointer to the PLDM message header
387  * @param[out] hdr - Pointer to the PLDM header information
388  *
389  * @return 0 on success, otherwise PLDM error codes.
390  * @note   Caller is responsible for alloc and dealloc of msg
391  *         and hdr params
392  */
393 uint8_t unpack_pldm_header(const struct pldm_msg_hdr *msg,
394 			   struct pldm_header_info *hdr);
395 
396 /* Requester */
397 
398 /* GetPLDMTypes */
399 
400 /** @brief Create a PLDM request message for GetPLDMTypes
401  *
402  *  @param[in] instance_id - Message's instance id
403  *  @param[in,out] msg - Message will be written to this
404  *  @return pldm_completion_codes
405  *  @note  Caller is responsible for memory alloc and dealloc of param
406  *         'msg.payload'
407  */
408 int encode_get_types_req(uint8_t instance_id, struct pldm_msg *msg);
409 
410 /** @brief Decode a GetPLDMTypes response message
411  *
412  *  Note:
413  *  * If the return value is not PLDM_SUCCESS, it represents a
414  * transport layer error.
415  *  * If the completion_code value is not PLDM_SUCCESS, it represents a
416  * protocol layer error and all the out-parameters are invalid.
417  *
418  *  @param[in] msg - Response message
419  *  @param[in] payload_length - Length of response message payload
420  *  @param[out] completion_code - Pointer to response msg's PLDM completion code
421  *  @param[out] types - pointer to array bitfield8_t[8] containing supported
422  *              types (MAX_TYPES/8) = 8), as per DSP0240
423  *  @return pldm_completion_codes
424  */
425 int decode_get_types_resp(const struct pldm_msg *msg, size_t payload_length,
426 			  uint8_t *completion_code, bitfield8_t *types);
427 
428 /* GetPLDMCommands */
429 
430 /** @brief Create a PLDM request message for GetPLDMCommands
431  *
432  *  @param[in] instance_id - Message's instance id
433  *  @param[in] type - PLDM Type
434  *  @param[in] version - Version for PLDM Type
435  *  @param[in,out] msg - Message will be written to this
436  *  @return pldm_completion_codes
437  *  @note  Caller is responsible for memory alloc and dealloc of param
438  *         'msg.payload'
439  */
440 int encode_get_commands_req(uint8_t instance_id, uint8_t type, ver32_t version,
441 			    struct pldm_msg *msg);
442 
443 /** @brief Decode a GetPLDMCommands response message
444  *
445  *  Note:
446  *  * If the return value is not PLDM_SUCCESS, it represents a
447  * transport layer error.
448  *  * If the completion_code value is not PLDM_SUCCESS, it represents a
449  * protocol layer error and all the out-parameters are invalid.
450  *
451  *  @param[in] msg - Response message
452  *  @param[in] payload_length - Length of response message payload
453  *  @param[out] completion_code - Pointer to response msg's PLDM completion code
454  *  @param[in] commands - pointer to array bitfield8_t[32] containing supported
455  *             commands (PLDM_MAX_CMDS_PER_TYPE/8) = 32), as per DSP0240
456  *  @return pldm_completion_codes
457  */
458 int decode_get_commands_resp(const struct pldm_msg *msg, size_t payload_length,
459 			     uint8_t *completion_code, bitfield8_t *commands);
460 
461 /* GetPLDMVersion */
462 
463 /** @brief Create a PLDM request for GetPLDMVersion
464  *
465  *  @param[in] instance_id - Message's instance id
466  *  @param[in] transfer_handle - Handle to identify PLDM version data transfer.
467  *         This handle is ignored by the responder when the
468  *         transferop_flag is set to getFirstPart.
469  *  @param[in] transfer_opflag - flag to indicate whether it is start of
470  *         transfer
471  *  @param[in] type -  PLDM Type for which version is requested
472  *  @param[in,out] msg - Message will be written to this
473  *  @return pldm_completion_codes
474  *  @note  Caller is responsible for memory alloc and dealloc of param
475  *         'msg.payload'
476  */
477 int encode_get_version_req(uint8_t instance_id, uint32_t transfer_handle,
478 			   uint8_t transfer_opflag, uint8_t type,
479 			   struct pldm_msg *msg);
480 
481 /** @brief Decode a GetPLDMVersion response message
482  *
483  *  Note:
484  *  * If the return value is not PLDM_SUCCESS, it represents a
485  * transport layer error.
486  *  * If the completion_code value is not PLDM_SUCCESS, it represents a
487  * protocol layer error and all the out-parameters are invalid.
488  *
489  *  @param[in] msg - Response message
490  *  @param[in] payload_length - Length of response message payload
491  *  @param[out] completion_code - Pointer to response msg's PLDM completion code
492  *  @param[out] next_transfer_handle - the next handle for the next part of data
493  *  @param[out] transfer_flag - flag to indicate the part of data
494  *  @return pldm_completion_codes
495  */
496 int decode_get_version_resp(const struct pldm_msg *msg, size_t payload_length,
497 			    uint8_t *completion_code,
498 			    uint32_t *next_transfer_handle,
499 			    uint8_t *transfer_flag, ver32_t *version);
500 
501 /* GetTID */
502 
503 /** @brief Decode a GetTID response message
504  *
505  *  Note:
506  *  * If the return value is not PLDM_SUCCESS, it represents a
507  * transport layer error.
508  *  * If the completion_code value is not PLDM_SUCCESS, it represents a
509  * protocol layer error and all the out-parameters are invalid.
510  *
511  *  @param[in] msg - Response message
512  *  @param[in] payload_length - Length of response message payload
513  *  @param[out] completion_code - Pointer to response msg's PLDM completion code
514  *  @param[out] tid - Pointer to the terminus id
515  *  @return pldm_completion_codes
516  */
517 int decode_get_tid_resp(const struct pldm_msg *msg, size_t payload_length,
518 			uint8_t *completion_code, uint8_t *tid);
519 
520 /* Responder */
521 
522 /* GetPLDMTypes */
523 
524 /** @brief Create a PLDM response message for GetPLDMTypes
525  *
526  *  @param[in] instance_id - Message's instance id
527  *  @param[in] completion_code - PLDM completion code
528  *  @param[in] types - pointer to array bitfield8_t[8] containing supported
529  *             types (MAX_TYPES/8) = 8), as per DSP0240
530  *  @param[in,out] msg - Message will be written to this
531  *  @return pldm_completion_codes
532  *  @note  Caller is responsible for memory alloc and dealloc of param
533  *         'msg.payload'
534  */
535 int encode_get_types_resp(uint8_t instance_id, uint8_t completion_code,
536 			  const bitfield8_t *types, struct pldm_msg *msg);
537 
538 /* GetPLDMCommands */
539 
540 /** @brief Decode GetPLDMCommands' request data
541  *
542  *  @param[in] msg - Request message
543  *  @param[in] payload_length - Length of request message payload
544  *  @param[out] type - PLDM Type
545  *  @param[out] version - Version for PLDM Type
546  *  @return pldm_completion_codes
547  */
548 int decode_get_commands_req(const struct pldm_msg *msg, size_t payload_length,
549 			    uint8_t *type, ver32_t *version);
550 
551 /** @brief Create a PLDM response message for GetPLDMCommands
552  *
553  *  @param[in] instance_id - Message's instance id
554  *  @param[in] completion_code - PLDM completion code
555  *  @param[in] commands - pointer to array bitfield8_t[32] containing supported
556  *             commands (PLDM_MAX_CMDS_PER_TYPE/8) = 32), as per DSP0240
557  *  @param[in,out] msg - Message will be written to this
558  *  @return pldm_completion_codes
559  *  @note  Caller is responsible for memory alloc and dealloc of param
560  *         'msg.payload'
561  */
562 int encode_get_commands_resp(uint8_t instance_id, uint8_t completion_code,
563 			     const bitfield8_t *commands, struct pldm_msg *msg);
564 
565 /* GetPLDMVersion */
566 
567 /** @brief Create a PLDM response for GetPLDMVersion
568  *
569  *  @param[in] instance_id - Message's instance id
570  *  @param[in] completion_code - PLDM completion code
571  *  @param[in] next_transfer_handle - Handle to identify next portion of
572  *              data transfer
573  *  @param[in] transfer_flag - Represents the part of transfer
574  *  @param[in] version_data - the version data
575  *  @param[in] version_size - size of version data
576  *  @param[in,out] msg - Message will be written to this
577  *  @return pldm_completion_codes
578  *  @note  Caller is responsible for memory alloc and dealloc of param
579  *         'msg.payload'
580  */
581 int encode_get_version_resp(uint8_t instance_id, uint8_t completion_code,
582 			    uint32_t next_transfer_handle,
583 			    uint8_t transfer_flag, const ver32_t *version_data,
584 			    size_t version_size, struct pldm_msg *msg);
585 
586 /** @brief Decode a GetPLDMVersion request message
587  *
588  *  @param[in] msg - Request message
589  *  @param[in] payload_length - length of request message payload
590  *  @param[out] transfer_handle - the handle of data
591  *  @param[out] transfer_opflag - Transfer Flag
592  *  @param[out] type - PLDM type for which version is requested
593  *  @return pldm_completion_codes
594  */
595 int decode_get_version_req(const struct pldm_msg *msg, size_t payload_length,
596 			   uint32_t *transfer_handle, uint8_t *transfer_opflag,
597 			   uint8_t *type);
598 
599 /* Requester */
600 
601 /* GetTID */
602 
603 /** @brief Create a PLDM request message for GetTID
604  *
605  *  @param[in] instance_id - Message's instance id
606  *  @param[in,out] msg - Message will be written to this
607  *  @return pldm_completion_codes
608  *  @note  Caller is responsible for memory alloc and dealloc of param
609  *         'msg.payload'
610  */
611 int encode_get_tid_req(uint8_t instance_id, struct pldm_msg *msg);
612 
613 /** @brief Create a PLDM response message for GetTID
614  *
615  *  @param[in] instance_id - Message's instance id
616  *  @param[in] completion_code - PLDM completion code
617  *  @param[in] tid - Terminus ID
618  *  @param[in,out] msg - Message will be written to this
619  *  @return pldm_completion_codes
620  *  @note  Caller is responsible for memory alloc and dealloc of param
621  *         'msg.payload'
622  */
623 int encode_get_tid_resp(uint8_t instance_id, uint8_t completion_code,
624 			uint8_t tid, struct pldm_msg *msg);
625 
626 /** @brief Create a PLDM request message for SetTID
627  *
628  *  @param[in] instance_id - Message's instance id
629  *  @param[in] tid - Terminus ID
630  *  @param[in,out] msg - Message will be written to this
631  *  @return pldm_completion_codes
632  *  @note  Caller is responsible for memory alloc and dealloc of param
633  *         'msg.payload'
634  */
635 int encode_set_tid_req(uint8_t instance_id, uint8_t tid, struct pldm_msg *msg);
636 
637 /* Responder */
638 
639 /* MultipartRecieve */
640 
641 /** @brief Decode a PLDM MultipartReceive request message
642  *
643  *  @param[in] msg - Request message
644  *  @param[in] payload_length - length of request message payload
645  *  @param[out] pldm_type - PLDM type for which version is requested
646  *  @param[out] transfer_opflag - Transfer Flag
647  *  @param[out] transfer_ctx - The context of the packet
648  *  @param[out] transfer_handle - The handle of data
649  *  @param[out] section_offset - The start of the requested section
650  *  @param[out] section_length - The length of the requested section
651  *  @return pldm_completion_codes
652  */
653 int decode_multipart_receive_req(const struct pldm_msg *msg,
654 				 size_t payload_length, uint8_t *pldm_type,
655 				 uint8_t *transfer_opflag,
656 				 uint32_t *transfer_ctx,
657 				 uint32_t *transfer_handle,
658 				 uint32_t *section_offset,
659 				 uint32_t *section_length);
660 
661 /** @brief Encode a PLDM MultipartReceive request message
662  *
663  *  @param[in] instance_id - Message's instance id
664  *  @param[in] req - The pointer to the request message to be encoded
665  *  @param[in,out] msg - Message will be written to this
666  *  @param[in] payload_length - length of request message payload
667  *  @return 0 on success
668  *          -EINVAL if the input parameters' memory are not allocated,
669  *          or message type or instance in request header is invalid
670  *          -ENOMSG if the PLDM type in the request header is invalid
671  *          -EOVERFLOW if the input message length is invalid
672  */
673 int encode_base_multipart_receive_req(
674 	uint8_t instance_id, const struct pldm_multipart_receive_req *req,
675 	struct pldm_msg *msg, size_t payload_length);
676 
677 /** @brief Decode a PLDM MultipartReceive response message
678  *
679  *  @param[in] msg - Response message
680  *  @param[in] payload_length - length of request message payload
681  *  @param[out] resp - pointer to the decoded response message,
682  *         excluding the data integrity checksum
683  *  @param[out] data_integrity_checksum - The checksum of data field
684  *         of the decoded response message
685  *  @return 0 on success
686  *          -EINVAL if the input parameters' memory are not allocated
687  *          -EOVERFLOW if the input message buffer is too short for the output
688  *          response struct
689  *          -EBADMSG if the input message buffer is too large for the output
690  *          response struct
691  *  @note  Caller is responsible for memory alloc and dealloc of param
692  *         'msg.payload'
693  */
694 int decode_base_multipart_receive_resp(const struct pldm_msg *msg,
695 				       size_t payload_length,
696 				       struct pldm_multipart_receive_resp *resp,
697 				       uint32_t *data_integrity_checksum);
698 
699 /** @brief Create a PLDM response message containing only cc
700  *
701  *  @param[in] instance_id - Message's instance id
702  *  @param[in] type - PLDM Type
703  *  @param[in] command - PLDM Command
704  *  @param[in] cc - PLDM Completion Code
705  *  @param[out] msg - Message will be written to this
706  *  @return pldm_completion_codes
707  */
708 int encode_cc_only_resp(uint8_t instance_id, uint8_t type, uint8_t command,
709 			uint8_t cc, struct pldm_msg *msg);
710 
711 /** @brief Create a PLDM message only with the header
712  *
713  *	@param[in] msg_type - PLDM message type
714  *	@param[in] instance_id - Message's instance id
715  *	@param[in] pldm_type - PLDM Type
716  *	@param[in] command - PLDM Command
717  *	@param[out] msg - Message will be written to this
718  *
719  *	@return pldm_completion_codes
720  */
721 int encode_pldm_header_only(uint8_t msg_type, uint8_t instance_id,
722 			    uint8_t pldm_type, uint8_t command,
723 			    struct pldm_msg *msg);
724 
725 #ifdef __cplusplus
726 }
727 #endif
728 
729 #endif /* BASE_H */
730