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