xref: /openbmc/libpldm/src/msgbuf.h (revision 7a8d932bc3cd30a0869b2e5cfd38c1b87019cffb)
1 /* SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later */
2 #ifndef PLDM_MSGBUF_H
3 #define PLDM_MSGBUF_H
4 
5 #include "msgbuf/core.h"
6 
7 #define PLDM__MSGBUF_DEFINE_P(name, mode)                                      \
8 	struct pldm_msgbuf_##mode _##name LIBPLDM_CC_CLEANUP(                  \
9 		pldm__msgbuf_##mode##_cleanup) = { NULL, INTMAX_MIN };         \
10 	struct pldm_msgbuf_##mode *(name) = &(_##name)
11 
12 #define PLDM_MSGBUF_RO_DEFINE_P(name) PLDM__MSGBUF_DEFINE_P(name, ro)
13 #define PLDM_MSGBUF_RW_DEFINE_P(name) PLDM__MSGBUF_DEFINE_P(name, rw)
14 
15 /*
16  * Use the C11 `_Generic` keyword to keep pldm_msgbuf related function consistent
17  * and to produce compile-time errors when the wrong pldm_msgbuf type is passed.
18  *
19  * Previously we cast away `const` in `pldm_msgbuf_init_error()`, which was a hack.
20  * Instead, introduce:
21  *   - pldm_msgbuf_ro: read-only buffer with a `const` cursor
22  *   - pldm_msgbuf_rw: read-write buffer with a non-const cursor
23  *
24  * `pldm_msgbuf_ro` is used by decode APIs to extract payloads into PLDM
25  * structures. `pldm_msgbuf_rw` is used by encode APIs to insert payloads from
26  * PLDM structures.
27  */
28 
29 #define pldm_msgbuf_init_errno(ctx, minsize, buf, len)                         \
30 	_Generic((ctx),                                                        \
31 		struct pldm_msgbuf_rw *: pldm_msgbuf_rw_init_errno,            \
32 		struct pldm_msgbuf_ro *: pldm_msgbuf_ro_init_errno)(           \
33 		ctx, minsize, buf, len)
34 
35 #define pldm_msgbuf_discard(ctx, error)                                        \
36 	_Generic((ctx),                                                        \
37 		struct pldm_msgbuf_rw *: pldm_msgbuf_rw_discard,               \
38 		struct pldm_msgbuf_ro *: pldm_msgbuf_ro_discard)(ctx, error)
39 
40 #define pldm_msgbuf_complete(ctx)                                              \
41 	_Generic((ctx),                                                        \
42 		struct pldm_msgbuf_rw *: pldm_msgbuf_rw_complete,              \
43 		struct pldm_msgbuf_ro *: pldm_msgbuf_ro_complete)(ctx)
44 
45 #define pldm_msgbuf_complete_consumed(ctx)                                     \
46 	_Generic((ctx),                                                        \
47 		struct pldm_msgbuf_rw *: pldm_msgbuf_rw_complete_consumed,     \
48 		struct pldm_msgbuf_ro *: pldm_msgbuf_ro_complete_consumed)(    \
49 		ctx)
50 
51 #define pldm_msgbuf_validate(ctx)                                              \
52 	_Generic((ctx),                                                        \
53 		struct pldm_msgbuf_rw *: pldm_msgbuf_rw_validate,              \
54 		struct pldm_msgbuf_ro *: pldm_msgbuf_ro_validate)(ctx)
55 
56 #define pldm_msgbuf_consumed(ctx)                                              \
57 	_Generic((ctx),                                                        \
58 		struct pldm_msgbuf_rw *: pldm_msgbuf_rw_consumed,              \
59 		struct pldm_msgbuf_ro *: pldm_msgbuf_ro_consumed)(ctx)
60 
61 #define pldm__msgbuf_invalidate(ctx)                                           \
62 	_Generic((ctx),                                                        \
63 		struct pldm_msgbuf_rw *: pldm__msgbuf_rw_invalidate,           \
64 		struct pldm_msgbuf_ro *: pldm__msgbuf_ro_invalidate)(ctx)
65 
66 #define pldm_msgbuf_span_required(ctx, required, cursor)                       \
67 	_Generic((ctx),                                                        \
68 		struct pldm_msgbuf_rw *: pldm_msgbuf_rw_span_required,         \
69 		struct pldm_msgbuf_ro *: pldm_msgbuf_ro_span_required)(        \
70 		ctx, required, cursor)
71 
72 #define pldm_msgbuf_span_until(ctx, trailer, cursor, length)                   \
73 	_Generic((ctx),                                                        \
74 		struct pldm_msgbuf_rw *: pldm_msgbuf_rw_span_until,            \
75 		struct pldm_msgbuf_ro *: pldm_msgbuf_ro_span_until)(           \
76 		ctx, trailer, cursor, length)
77 
78 #define pldm_msgbuf_span_string_utf16(ctx, cursor, len)                        \
79 	_Generic((ctx),                                                        \
80 		struct pldm_msgbuf_rw *: pldm_msgbuf_rw_span_string_utf16,     \
81 		struct pldm_msgbuf_ro *: pldm_msgbuf_ro_span_string_utf16)(    \
82 		ctx, cursor, len)
83 
84 #define pldm_msgbuf_span_remaining(ctx, cursor, len)                           \
85 	_Generic((ctx),                                                        \
86 		struct pldm_msgbuf_rw *: pldm_msgbuf_rw_span_remaining,        \
87 		struct pldm_msgbuf_ro *: pldm_msgbuf_ro_span_remaining)(       \
88 		ctx, cursor, len)
89 
90 #define pldm_msgbuf_span_string_ascii(ctx, cursor, len)                        \
91 	_Generic((ctx),                                                        \
92 		struct pldm_msgbuf_rw *: pldm_msgbuf_rw_span_string_ascii,     \
93 		struct pldm_msgbuf_ro *: pldm_msgbuf_ro_span_string_ascii)(    \
94 		ctx, cursor, len)
95 
96 #define pldm_msgbuf_extract_typecheck(ty, fn, dst, ...)                        \
97 	(pldm_require_obj_type(dst, ty), fn(__VA_ARGS__))
98 
99 #define pldm_msgbuf_extract_uint8(ctx, dst)                                    \
100 	pldm_msgbuf_extract_typecheck(uint8_t, pldm__msgbuf_extract_uint8,     \
101 				      dst, ctx, (void *)&(dst))
102 
103 #define pldm_msgbuf_extract_int8(ctx, dst)                                     \
104 	pldm_msgbuf_extract_typecheck(int8_t, pldm__msgbuf_extract_int8, dst,  \
105 				      ctx, (void *)&(dst))
106 
107 #define pldm_msgbuf_extract_uint16(ctx, dst)                                   \
108 	pldm_msgbuf_extract_typecheck(uint16_t, pldm__msgbuf_extract_uint16,   \
109 				      dst, ctx, (void *)&(dst))
110 
111 #define pldm_msgbuf_extract_int16(ctx, dst)                                    \
112 	pldm_msgbuf_extract_typecheck(int16_t, pldm__msgbuf_extract_int16,     \
113 				      dst, ctx, (void *)&(dst))
114 
115 #define pldm_msgbuf_extract_uint32(ctx, dst)                                   \
116 	pldm_msgbuf_extract_typecheck(uint32_t, pldm__msgbuf_extract_uint32,   \
117 				      dst, ctx, (void *)&(dst))
118 
119 #define pldm_msgbuf_extract_int32(ctx, dst)                                    \
120 	pldm_msgbuf_extract_typecheck(int32_t, pldm__msgbuf_extract_int32,     \
121 				      dst, ctx, (void *)&(dst))
122 
123 #define pldm_msgbuf_extract_real32(ctx, dst)                                   \
124 	pldm_msgbuf_extract_typecheck(real32_t, pldm__msgbuf_extract_real32,   \
125 				      dst, ctx, (void *)&(dst))
126 
127 /**
128  * Extract the field at the msgbuf cursor into the lvalue named by dst.
129  *
130  * @param ctx The msgbuf context object
131  * @param dst The lvalue into which the field at the msgbuf cursor should be
132  *            extracted
133  *
134  * @return PLDM_SUCCESS on success, otherwise another value on error
135  */
136 #define pldm_msgbuf_extract(ctx, dst)                                          \
137 	_Generic((dst),                                                        \
138 		uint8_t: pldm__msgbuf_extract_uint8,                           \
139 		int8_t: pldm__msgbuf_extract_int8,                             \
140 		uint16_t: pldm__msgbuf_extract_uint16,                         \
141 		int16_t: pldm__msgbuf_extract_int16,                           \
142 		uint32_t: pldm__msgbuf_extract_uint32,                         \
143 		int32_t: pldm__msgbuf_extract_int32,                           \
144 		real32_t: pldm__msgbuf_extract_real32)(ctx, (void *)&(dst))
145 
146 /**
147  * Extract the field at the msgbuf cursor into the object pointed-to by dst.
148  *
149  * @param ctx The msgbuf context object
150  * @param dst The pointer to the object into which the field at the msgbuf
151  *            cursor should be extracted
152  *
153  * @return PLDM_SUCCESS on success, otherwise another value on error
154  */
155 #define pldm_msgbuf_extract_p(ctx, dst)                                        \
156 	_Generic((dst),                                                        \
157 		uint8_t *: pldm__msgbuf_extract_uint8,                         \
158 		int8_t *: pldm__msgbuf_extract_int8,                           \
159 		uint16_t *: pldm__msgbuf_extract_uint16,                       \
160 		int16_t *: pldm__msgbuf_extract_int16,                         \
161 		uint32_t *: pldm__msgbuf_extract_uint32,                       \
162 		int32_t *: pldm__msgbuf_extract_int32,                         \
163 		real32_t *: pldm__msgbuf_extract_real32)(ctx, dst)
164 
165 #define pldm_msgbuf_insert(dst, src)                                           \
166 	_Generic((src),                                                        \
167 		uint8_t: pldm_msgbuf_insert_uint8,                             \
168 		int8_t: pldm_msgbuf_insert_int8,                               \
169 		uint16_t: pldm_msgbuf_insert_uint16,                           \
170 		int16_t: pldm_msgbuf_insert_int16,                             \
171 		uint32_t: pldm_msgbuf_insert_uint32,                           \
172 		int32_t: pldm_msgbuf_insert_int32,                             \
173 		uint64_t: pldm_msgbuf_insert_uint64)(dst, src)
174 
175 /**
176  * Insert an array of data into the msgbuf instance
177  *
178  * @param ctx - The msgbuf instance into which the array of data should be
179  *              inserted
180  * @param count - The number of array elements to insert
181  * @param src - The array object from which elements should be inserted into
182                 @p ctx
183  * @param src_count - The maximum number of elements to insert from @p src
184  *
185  * Note that both @p count and @p src_count can only be counted by `sizeof` for
186  * arrays where `sizeof(*dst) == 1` holds. Specifically, they count the number
187  * of array elements and _not_ the object size of the array.
188  */
189 #define pldm_msgbuf_insert_array(dst, count, src, src_count)                   \
190 	_Generic((*(src)),                                                     \
191 		uint8_t: pldm_msgbuf_insert_array_uint8,                       \
192 		char: pldm_msgbuf_insert_array_char)(dst, count, src,          \
193 						     src_count)
194 
195 #endif /* BUF_H */
196