blob: 6c2e0944f99a9814e8c06f09888b53e200242aac [file] [log] [blame]
Andrew Jeffery9c766792022-08-10 23:12:49 +09301#ifndef BASE_H
2#define BASE_H
3
4#ifdef __cplusplus
5extern "C" {
6#endif
7
8#include <asm/byteorder.h>
9#include <stddef.h>
10#include <stdint.h>
11
12#include "pldm_types.h"
13
14/** @brief PLDM Types
15 */
16enum pldm_supported_types {
17 PLDM_BASE = 0x00,
18 PLDM_PLATFORM = 0x02,
19 PLDM_BIOS = 0x03,
20 PLDM_FRU = 0x04,
21 PLDM_FWUP = 0x05,
22 PLDM_OEM = 0x3F,
23};
24
25/** @brief PLDM Commands
26 */
27enum pldm_supported_commands {
Gilbert Chen6c9c9172022-10-18 17:07:29 +080028 PLDM_SET_TID = 0x1,
Andrew Jeffery9c766792022-08-10 23:12:49 +093029 PLDM_GET_TID = 0x2,
30 PLDM_GET_PLDM_VERSION = 0x3,
31 PLDM_GET_PLDM_TYPES = 0x4,
32 PLDM_GET_PLDM_COMMANDS = 0x5,
33 PLDM_MULTIPART_RECEIVE = 0x9,
34};
35
36/** @brief PLDM base codes
37 */
38enum pldm_completion_codes {
39 PLDM_SUCCESS = 0x00,
40 PLDM_ERROR = 0x01,
41 PLDM_ERROR_INVALID_DATA = 0x02,
42 PLDM_ERROR_INVALID_LENGTH = 0x03,
43 PLDM_ERROR_NOT_READY = 0x04,
44 PLDM_ERROR_UNSUPPORTED_PLDM_CMD = 0x05,
45 PLDM_ERROR_INVALID_PLDM_TYPE = 0x20,
46 PLDM_INVALID_TRANSFER_OPERATION_FLAG = 0x21
47};
48
49enum transfer_op_flag {
50 PLDM_GET_NEXTPART = 0,
51 PLDM_GET_FIRSTPART = 1,
52};
53
54enum transfer_multipart_op_flag {
55 PLDM_XFER_FIRST_PART = 0,
56 PLDM_XFER_NEXT_PART = 1,
57 PLDM_XFER_ABORT = 2,
58 PLDM_XFER_COMPLETE = 3,
59 PLDM_XFER_CURRENT_PART = 4,
60};
61
62enum transfer_resp_flag {
63 PLDM_START = 0x01,
64 PLDM_MIDDLE = 0x02,
65 PLDM_END = 0x04,
66 PLDM_START_AND_END = 0x05,
67};
68
69/** @brief PLDM transport protocol type
70 */
71enum pldm_transport_protocol_type {
72 PLDM_TRANSPORT_PROTOCOL_TYPE_MCTP = 0x00,
73 PLDM_TRANSPORT_PROTOCOL_TYPE_OEM = 0xFF,
74};
75
76/** @enum MessageType
77 *
78 * The different message types supported by the PLDM specification.
79 */
80typedef enum {
81 PLDM_RESPONSE, //!< PLDM response
82 PLDM_REQUEST, //!< PLDM request
83 PLDM_RESERVED, //!< Reserved
84 PLDM_ASYNC_REQUEST_NOTIFY, //!< Unacknowledged PLDM request messages
85} MessageType;
86
87#define PLDM_INSTANCE_MAX 31
88#define PLDM_MAX_TYPES 64
89#define PLDM_MAX_CMDS_PER_TYPE 256
90
91/* Message payload lengths */
92#define PLDM_GET_COMMANDS_REQ_BYTES 5
93#define PLDM_GET_VERSION_REQ_BYTES 6
94
95/* Response lengths are inclusive of completion code */
96#define PLDM_GET_TYPES_RESP_BYTES 9
97#define PLDM_GET_TID_RESP_BYTES 2
Gilbert Chen6c9c9172022-10-18 17:07:29 +080098#define PLDM_SET_TID_RESP_BYTES 1
Andrew Jeffery9c766792022-08-10 23:12:49 +093099#define PLDM_GET_COMMANDS_RESP_BYTES 33
100/* Response data has only one version and does not contain the checksum */
101#define PLDM_GET_VERSION_RESP_BYTES 10
102#define PLDM_MULTIPART_RECEIVE_REQ_BYTES 18
103
104#define PLDM_VERSION_0 0
105#define PLDM_CURRENT_VERSION PLDM_VERSION_0
106
107#define PLDM_TIMESTAMP104_SIZE 13
108
109/** @struct pldm_msg_hdr
110 *
111 * Structure representing PLDM message header fields
112 */
113struct pldm_msg_hdr {
114#if defined(__LITTLE_ENDIAN_BITFIELD)
115 uint8_t instance_id : 5; //!< Instance ID
116 uint8_t reserved : 1; //!< Reserved
117 uint8_t datagram : 1; //!< Datagram bit
118 uint8_t request : 1; //!< Request bit
119#elif defined(__BIG_ENDIAN_BITFIELD)
120 uint8_t request : 1; //!< Request bit
121 uint8_t datagram : 1; //!< Datagram bit
122 uint8_t reserved : 1; //!< Reserved
123 uint8_t instance_id : 5; //!< Instance ID
124#endif
125
126#if defined(__LITTLE_ENDIAN_BITFIELD)
127 uint8_t type : 6; //!< PLDM type
128 uint8_t header_ver : 2; //!< Header version
129#elif defined(__BIG_ENDIAN_BITFIELD)
130 uint8_t header_ver : 2; //!< Header version
131 uint8_t type : 6; //!< PLDM type
132#endif
133 uint8_t command; //!< PLDM command code
134} __attribute__((packed));
135
136// Macros for byte-swapping variables in-place
137#define HTOLE32(X) (X = htole32(X))
138#define HTOLE16(X) (X = htole16(X))
139#define LE32TOH(X) (X = le32toh(X))
140#define LE16TOH(X) (X = le16toh(X))
141
142/** @struct pldm_msg
143 *
144 * Structure representing PLDM message
145 */
146struct pldm_msg {
147 struct pldm_msg_hdr hdr; //!< PLDM message header
148 uint8_t payload[1]; //!< &payload[0] is the beginning of the payload
149} __attribute__((packed));
150
151/** @struct pldm_header_info
152 *
153 * The information needed to prepare PLDM header and this is passed to the
154 * pack_pldm_header and unpack_pldm_header API.
155 */
156struct pldm_header_info {
157 MessageType msg_type; //!< PLDM message type
158 uint8_t instance; //!< PLDM instance id
159 uint8_t pldm_type; //!< PLDM type
160 uint8_t command; //!< PLDM command code
161 uint8_t completion_code; //!< PLDM completion code, applies for response
162};
163
164/** @struct pldm_get_types_resp
165 *
166 * Structure representing PLDM get types response.
167 */
168struct pldm_get_types_resp {
169 uint8_t completion_code; //!< completion code
170 bitfield8_t types[8]; //!< each bit represents whether a given PLDM Type
171 //!< is supported
172} __attribute__((packed));
173
174/** @struct pldm_get_commands_req
175 *
176 * Structure representing PLDM get commands request.
177 */
178struct pldm_get_commands_req {
179 uint8_t type; //!< PLDM Type for which command support information is
180 //!< being requested
181 ver32_t version; //!< version for the specified PLDM Type
182} __attribute__((packed));
183
184/** @struct pldm_get_commands_resp
185 *
186 * Structure representing PLDM get commands response.
187 */
188struct pldm_get_commands_resp {
189 uint8_t completion_code; //!< completion code
190 bitfield8_t commands[32]; //!< each bit represents whether a given PLDM
191 //!< command is supported
192} __attribute__((packed));
193
194/** @struct pldm_get_version_req
195 *
196 * Structure representing PLDM get version request.
197 */
198struct pldm_get_version_req {
199 uint32_t
200 transfer_handle; //!< handle to identify PLDM version data transfer
201 uint8_t transfer_opflag; //!< PLDM GetVersion operation flag
202 uint8_t type; //!< PLDM Type for which version information is being
203 //!< requested
204} __attribute__((packed));
205
206/** @struct pldm_get_version_resp
207 *
208 * Structure representing PLDM get version response.
209 */
210
211struct pldm_get_version_resp {
212 uint8_t completion_code; //!< completion code
213 uint32_t next_transfer_handle; //!< next portion of PLDM version data
214 //!< transfer
215 uint8_t transfer_flag; //!< PLDM GetVersion transfer flag
216 uint8_t version_data[1]; //!< PLDM GetVersion version field
217} __attribute__((packed));
218
Gilbert Chen6c9c9172022-10-18 17:07:29 +0800219/** @struct pldm_set_tid_req
220 *
221 * Structure representing PLDM set tid request.
222 */
223
224struct pldm_set_tid_req {
225 uint8_t tid; //!< PLDM SetTID TID field
226} __attribute__((packed));
227
Andrew Jeffery9c766792022-08-10 23:12:49 +0930228/** @struct pldm_get_tid_resp
229 *
230 * Structure representing PLDM get tid response.
231 */
232
233struct pldm_get_tid_resp {
234 uint8_t completion_code; //!< completion code
235 uint8_t tid; //!< PLDM GetTID TID field
236} __attribute__((packed));
237
238/** @struct pldm_multipart_receive_req
239 *
240 * Structure representing PLDM multipart receive request.
241 */
242struct pldm_multipart_receive_req {
243 uint8_t pldm_type; //!< PLDM Type for the MultipartReceive
244 //!< command.
245 uint8_t transfer_opflag; //!< PLDM MultipartReceive operation flag.
246 uint32_t transfer_ctx; //!< Protocol-specifc context for this
247 //!< transfer.
248 uint32_t transfer_handle; //!< handle to identify the part of data to be
249 //!< received.
250 uint32_t section_offset; //!< The start offset for the requested
251 //!< section.
252 uint32_t section_length; //!< The length (in bytes) of the section
253 //!< requested.
254} __attribute__((packed));
255/**
256 * @brief Populate the PLDM message with the PLDM header.The caller of this API
257 * allocates buffer for the PLDM header when forming the PLDM message.
258 * The buffer is passed to this API to pack the PLDM header.
259 *
260 * @param[in] hdr - Pointer to the PLDM header information
261 * @param[out] msg - Pointer to PLDM message header
262 *
263 * @return 0 on success, otherwise PLDM error codes.
264 * @note Caller is responsible for alloc and dealloc of msg
265 * and hdr params
266 */
267uint8_t pack_pldm_header(const struct pldm_header_info *hdr,
268 struct pldm_msg_hdr *msg);
269
270/**
271 * @brief Unpack the PLDM header from the PLDM message.
272 *
273 * @param[in] msg - Pointer to the PLDM message header
274 * @param[out] hdr - Pointer to the PLDM header information
275 *
276 * @return 0 on success, otherwise PLDM error codes.
277 * @note Caller is responsible for alloc and dealloc of msg
278 * and hdr params
279 */
280uint8_t unpack_pldm_header(const struct pldm_msg_hdr *msg,
281 struct pldm_header_info *hdr);
282
283/* Requester */
284
285/* GetPLDMTypes */
286
287/** @brief Create a PLDM request message for GetPLDMTypes
288 *
289 * @param[in] instance_id - Message's instance id
290 * @param[in,out] msg - Message will be written to this
291 * @return pldm_completion_codes
292 * @note Caller is responsible for memory alloc and dealloc of param
293 * 'msg.payload'
294 */
295int encode_get_types_req(uint8_t instance_id, struct pldm_msg *msg);
296
297/** @brief Decode a GetPLDMTypes response message
298 *
299 * Note:
300 * * If the return value is not PLDM_SUCCESS, it represents a
301 * transport layer error.
302 * * If the completion_code value is not PLDM_SUCCESS, it represents a
303 * protocol layer error and all the out-parameters are invalid.
304 *
305 * @param[in] msg - Response message
306 * @param[in] payload_length - Length of response message payload
307 * @param[out] completion_code - Pointer to response msg's PLDM completion code
308 * @param[out] types - pointer to array bitfield8_t[8] containing supported
309 * types (MAX_TYPES/8) = 8), as per DSP0240
310 * @return pldm_completion_codes
311 */
312int decode_get_types_resp(const struct pldm_msg *msg, size_t payload_length,
313 uint8_t *completion_code, bitfield8_t *types);
314
315/* GetPLDMCommands */
316
317/** @brief Create a PLDM request message for GetPLDMCommands
318 *
319 * @param[in] instance_id - Message's instance id
320 * @param[in] type - PLDM Type
321 * @param[in] version - Version for PLDM Type
322 * @param[in,out] msg - Message will be written to this
323 * @return pldm_completion_codes
324 * @note Caller is responsible for memory alloc and dealloc of param
325 * 'msg.payload'
326 */
327int encode_get_commands_req(uint8_t instance_id, uint8_t type, ver32_t version,
328 struct pldm_msg *msg);
329
330/** @brief Decode a GetPLDMCommands response message
331 *
332 * Note:
333 * * If the return value is not PLDM_SUCCESS, it represents a
334 * transport layer error.
335 * * If the completion_code value is not PLDM_SUCCESS, it represents a
336 * protocol layer error and all the out-parameters are invalid.
337 *
338 * @param[in] msg - Response message
339 * @param[in] payload_length - Length of reponse message payload
340 * @param[out] completion_code - Pointer to response msg's PLDM completion code
341 * @param[in] commands - pointer to array bitfield8_t[32] containing supported
342 * commands (PLDM_MAX_CMDS_PER_TYPE/8) = 32), as per DSP0240
343 * @return pldm_completion_codes
344 */
345int decode_get_commands_resp(const struct pldm_msg *msg, size_t payload_length,
346 uint8_t *completion_code, bitfield8_t *commands);
347
348/* GetPLDMVersion */
349
350/** @brief Create a PLDM request for GetPLDMVersion
351 *
352 * @param[in] instance_id - Message's instance id
353 * @param[in] transfer_handle - Handle to identify PLDM version data transfer.
354 * This handle is ignored by the responder when the
355 * transferop_flag is set to getFirstPart.
356 * @param[in] transfer_opflag - flag to indicate whether it is start of
357 * transfer
358 * @param[in] type - PLDM Type for which version is requested
359 * @param[in,out] msg - Message will be written to this
360 * @return pldm_completion_codes
361 * @note Caller is responsible for memory alloc and dealloc of param
362 * 'msg.payload'
363 */
364int encode_get_version_req(uint8_t instance_id, uint32_t transfer_handle,
365 uint8_t transfer_opflag, uint8_t type,
366 struct pldm_msg *msg);
367
368/** @brief Decode a GetPLDMVersion response message
369 *
370 * Note:
371 * * If the return value is not PLDM_SUCCESS, it represents a
372 * transport layer error.
373 * * If the completion_code value is not PLDM_SUCCESS, it represents a
374 * protocol layer error and all the out-parameters are invalid.
375 *
376 * @param[in] msg - Response message
377 * @param[in] payload_length - Length of reponse message payload
378 * @param[out] completion_code - Pointer to response msg's PLDM completion code
379 * @param[out] next_transfer_handle - the next handle for the next part of data
380 * @param[out] transfer_flag - flag to indicate the part of data
381 * @return pldm_completion_codes
382 */
383int decode_get_version_resp(const struct pldm_msg *msg, size_t payload_length,
384 uint8_t *completion_code,
385 uint32_t *next_transfer_handle,
386 uint8_t *transfer_flag, ver32_t *version);
387
388/* GetTID */
389
390/** @brief Decode a GetTID response message
391 *
392 * Note:
393 * * If the return value is not PLDM_SUCCESS, it represents a
394 * transport layer error.
395 * * If the completion_code value is not PLDM_SUCCESS, it represents a
396 * protocol layer error and all the out-parameters are invalid.
397 *
398 * @param[in] msg - Response message
399 * @param[in] payload_length - Length of response message payload
400 * @param[out] completion_code - Pointer to response msg's PLDM completion code
401 * @param[out] tid - Pointer to the terminus id
402 * @return pldm_completion_codes
403 */
404int decode_get_tid_resp(const struct pldm_msg *msg, size_t payload_length,
405 uint8_t *completion_code, uint8_t *tid);
406
407/* Responder */
408
409/* GetPLDMTypes */
410
411/** @brief Create a PLDM response message for GetPLDMTypes
412 *
413 * @param[in] instance_id - Message's instance id
414 * @param[in] completion_code - PLDM completion code
415 * @param[in] types - pointer to array bitfield8_t[8] containing supported
416 * types (MAX_TYPES/8) = 8), as per DSP0240
417 * @param[in,out] msg - Message will be written to this
418 * @return pldm_completion_codes
419 * @note Caller is responsible for memory alloc and dealloc of param
420 * 'msg.payload'
421 */
422int encode_get_types_resp(uint8_t instance_id, uint8_t completion_code,
423 const bitfield8_t *types, struct pldm_msg *msg);
424
425/* GetPLDMCommands */
426
427/** @brief Decode GetPLDMCommands' request data
428 *
429 * @param[in] msg - Request message
430 * @param[in] payload_length - Length of request message payload
431 * @param[out] type - PLDM Type
432 * @param[out] version - Version for PLDM Type
433 * @return pldm_completion_codes
434 */
435int decode_get_commands_req(const struct pldm_msg *msg, size_t payload_length,
436 uint8_t *type, ver32_t *version);
437
438/** @brief Create a PLDM response message for GetPLDMCommands
439 *
440 * @param[in] instance_id - Message's instance id
441 * @param[in] completion_code - PLDM completion code
442 * @param[in] commands - pointer to array bitfield8_t[32] containing supported
443 * commands (PLDM_MAX_CMDS_PER_TYPE/8) = 32), as per DSP0240
444 * @param[in,out] msg - Message will be written to this
445 * @return pldm_completion_codes
446 * @note Caller is responsible for memory alloc and dealloc of param
447 * 'msg.payload'
448 */
449int encode_get_commands_resp(uint8_t instance_id, uint8_t completion_code,
450 const bitfield8_t *commands, struct pldm_msg *msg);
451
452/* GetPLDMVersion */
453
454/** @brief Create a PLDM response for GetPLDMVersion
455 *
456 * @param[in] instance_id - Message's instance id
457 * @param[in] completion_code - PLDM completion code
458 * @param[in] next_transfer_handle - Handle to identify next portion of
459 * data transfer
460 * @param[in] transfer_flag - Represents the part of transfer
461 * @param[in] version_data - the version data
462 * @param[in] version_size - size of version data
463 * @param[in,out] msg - Message will be written to this
464 * @return pldm_completion_codes
465 * @note Caller is responsible for memory alloc and dealloc of param
466 * 'msg.payload'
467 */
468int encode_get_version_resp(uint8_t instance_id, uint8_t completion_code,
469 uint32_t next_transfer_handle,
470 uint8_t transfer_flag, const ver32_t *version_data,
471 size_t version_size, struct pldm_msg *msg);
472
473/** @brief Decode a GetPLDMVersion request message
474 *
475 * @param[in] msg - Request message
476 * @param[in] payload_length - length of request message payload
477 * @param[out] transfer_handle - the handle of data
478 * @param[out] transfer_opflag - Transfer Flag
479 * @param[out] type - PLDM type for which version is requested
480 * @return pldm_completion_codes
481 */
482int decode_get_version_req(const struct pldm_msg *msg, size_t payload_length,
483 uint32_t *transfer_handle, uint8_t *transfer_opflag,
484 uint8_t *type);
485
486/* Requester */
487
488/* GetTID */
489
490/** @brief Create a PLDM request message for GetTID
491 *
492 * @param[in] instance_id - Message's instance id
493 * @param[in,out] msg - Message will be written to this
494 * @return pldm_completion_codes
495 * @note Caller is responsible for memory alloc and dealloc of param
496 * 'msg.payload'
497 */
498int encode_get_tid_req(uint8_t instance_id, struct pldm_msg *msg);
499
500/** @brief Create a PLDM response message for GetTID
501 *
502 * @param[in] instance_id - Message's instance id
503 * @param[in] completion_code - PLDM completion code
504 * @param[in] tid - Terminus ID
505 * @param[in,out] msg - Message will be written to this
506 * @return pldm_completion_codes
507 * @note Caller is responsible for memory alloc and dealloc of param
508 * 'msg.payload'
509 */
510int encode_get_tid_resp(uint8_t instance_id, uint8_t completion_code,
511 uint8_t tid, struct pldm_msg *msg);
512
Gilbert Chen6c9c9172022-10-18 17:07:29 +0800513/** @brief Create a PLDM request message for SetTID
514 *
515 * @param[in] instance_id - Message's instance id
516 * @param[in] tid - Terminus ID
517 * @param[in,out] msg - Message will be written to this
518 * @return pldm_completion_codes
519 * @note Caller is responsible for memory alloc and dealloc of param
520 * 'msg.payload'
521 */
522int encode_set_tid_req(uint8_t instance_id, uint8_t tid, struct pldm_msg *msg);
523
Andrew Jeffery9c766792022-08-10 23:12:49 +0930524/* Responder */
525
526/* MultipartRecieve */
527
528/** @brief Decode a PLDM MultipartReceive request message
529 *
530 * @param[in] msg - Request message
531 * @param[in] payload_length - length of request message payload
532 * @param[out] pldm_type - PLDM type for which version is requested
533 * @param[out] transfer_opflag - Transfer Flag
534 * @param[out] transfer_ctx - The context of the packet
535 * @param[out] transfer_handle - The handle of data
536 * @param[out] section_offset - The start of the requested section
537 * @param[out] section_length - The length of the requested section
538 * @return pldm_completion_codes
539 */
540int decode_multipart_receive_req(
541 const struct pldm_msg *msg, size_t payload_length, uint8_t *pldm_type,
542 uint8_t *transfer_opflag, uint32_t *transfer_ctx, uint32_t *transfer_handle,
543 uint32_t *section_offset, uint32_t *section_length);
544
545/** @brief Create a PLDM response message containing only cc
546 *
547 * @param[in] instance_id - Message's instance id
548 * @param[in] type - PLDM Type
549 * @param[in] command - PLDM Command
550 * @param[in] cc - PLDM Completion Code
551 * @param[out] msg - Message will be written to this
552 * @return pldm_completion_codes
553 */
554int encode_cc_only_resp(uint8_t instance_id, uint8_t type, uint8_t command,
555 uint8_t cc, struct pldm_msg *msg);
556
557/** @brief Create a PLDM message only with the header
558 *
559 * @param[in] msg_type - PLDM message type
560 * @param[in] instance_id - Message's instance id
561 * @param[in] pldm_type - PLDM Type
562 * @param[in] command - PLDM Command
563 * @param[out] msg - Message will be written to this
564 *
565 * @return pldm_completion_codes
566 */
567int encode_pldm_header_only(uint8_t msg_type, uint8_t instance_id,
568 uint8_t pldm_type, uint8_t command,
569 struct pldm_msg *msg);
570
571#ifdef __cplusplus
572}
573#endif
574
575#endif /* BASE_H */