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