1 /* SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later */ 2 #ifndef PLDM_MSGBUF_PLATFORM_H 3 #define PLDM_MSGBUF_PLATFORM_H 4 5 #include "../msgbuf.h" 6 #include <libpldm/base.h> 7 #include <libpldm/platform.h> 8 9 static inline int 10 pldm_msgbuf_extract_value_pdr_hdr(struct pldm_msgbuf *ctx, 11 struct pldm_value_pdr_hdr *hdr) 12 { 13 pldm_msgbuf_extract(ctx, hdr->record_handle); 14 pldm_msgbuf_extract(ctx, hdr->version); 15 pldm_msgbuf_extract(ctx, hdr->type); 16 pldm_msgbuf_extract(ctx, hdr->record_change_num); 17 pldm_msgbuf_extract(ctx, hdr->length); 18 19 return pldm_msgbuf_validate(ctx); 20 } 21 22 /* 23 * We use __attribute__((always_inline)) below so the compiler has visibility of 24 * the switch() at the call site. It is often the case that the size of multiple 25 * fields depends on the tag. Inlining thus gives the compiler visibility to 26 * hoist one tag-based code-path condition to cover all invocations. 27 */ 28 29 __attribute__((always_inline)) static inline int 30 pldm_msgbuf_extract_sensor_data(struct pldm_msgbuf *ctx, 31 enum pldm_sensor_readings_data_type tag, 32 union_sensor_data_size *dst) 33 { 34 switch (tag) { 35 case PLDM_SENSOR_DATA_SIZE_UINT8: 36 return pldm_msgbuf_extract(ctx, dst->value_u8); 37 case PLDM_SENSOR_DATA_SIZE_SINT8: 38 return pldm_msgbuf_extract(ctx, dst->value_s8); 39 case PLDM_SENSOR_DATA_SIZE_UINT16: 40 return pldm_msgbuf_extract(ctx, dst->value_u16); 41 case PLDM_SENSOR_DATA_SIZE_SINT16: 42 return pldm_msgbuf_extract(ctx, dst->value_s16); 43 case PLDM_SENSOR_DATA_SIZE_UINT32: 44 return pldm_msgbuf_extract(ctx, dst->value_u32); 45 case PLDM_SENSOR_DATA_SIZE_SINT32: 46 return pldm_msgbuf_extract(ctx, dst->value_s32); 47 } 48 49 return -PLDM_ERROR_INVALID_DATA; 50 } 51 52 /* 53 * This API is bad, but it's because the caller's APIs are also bad. They should 54 * have used the approach used by callers of pldm_msgbuf_extract_sensor_data() 55 * above 56 */ 57 __attribute__((always_inline)) static inline int 58 pldm_msgbuf_extract_sensor_value(struct pldm_msgbuf *ctx, 59 enum pldm_sensor_readings_data_type tag, 60 void *val) 61 { 62 switch (tag) { 63 case PLDM_SENSOR_DATA_SIZE_UINT8: 64 return pldm__msgbuf_extract_uint8(ctx, val); 65 case PLDM_SENSOR_DATA_SIZE_SINT8: 66 return pldm__msgbuf_extract_int8(ctx, val); 67 case PLDM_SENSOR_DATA_SIZE_UINT16: 68 return pldm__msgbuf_extract_uint16(ctx, val); 69 case PLDM_SENSOR_DATA_SIZE_SINT16: 70 return pldm__msgbuf_extract_int16(ctx, val); 71 case PLDM_SENSOR_DATA_SIZE_UINT32: 72 return pldm__msgbuf_extract_uint32(ctx, val); 73 case PLDM_SENSOR_DATA_SIZE_SINT32: 74 return pldm__msgbuf_extract_int32(ctx, val); 75 } 76 77 return -PLDM_ERROR_INVALID_DATA; 78 } 79 80 #define pldm_msgbuf_extract_range_field_format(ctx, tag, dst) \ 81 pldm_msgbuf_extract_typecheck(union_range_field_format, \ 82 pldm__msgbuf_extract_range_field_format, \ 83 dst, ctx, tag, (void *)&(dst)) 84 __attribute__((always_inline)) static inline int 85 pldm__msgbuf_extract_range_field_format(struct pldm_msgbuf *ctx, 86 enum pldm_range_field_format tag, 87 void *rff) 88 { 89 switch (tag) { 90 case PLDM_RANGE_FIELD_FORMAT_UINT8: 91 return pldm__msgbuf_extract_uint8( 92 ctx, ((char *)rff) + offsetof(union_range_field_format, 93 value_u8)); 94 case PLDM_RANGE_FIELD_FORMAT_SINT8: 95 return pldm__msgbuf_extract_int8( 96 ctx, ((char *)rff) + offsetof(union_range_field_format, 97 value_s8)); 98 case PLDM_RANGE_FIELD_FORMAT_UINT16: 99 return pldm__msgbuf_extract_uint16( 100 ctx, ((char *)rff) + offsetof(union_range_field_format, 101 value_u16)); 102 case PLDM_RANGE_FIELD_FORMAT_SINT16: 103 return pldm__msgbuf_extract_int16( 104 ctx, ((char *)rff) + offsetof(union_range_field_format, 105 value_s16)); 106 case PLDM_RANGE_FIELD_FORMAT_UINT32: 107 return pldm__msgbuf_extract_uint32( 108 ctx, ((char *)rff) + offsetof(union_range_field_format, 109 value_u32)); 110 case PLDM_RANGE_FIELD_FORMAT_SINT32: 111 return pldm__msgbuf_extract_int32( 112 ctx, ((char *)rff) + offsetof(union_range_field_format, 113 value_s32)); 114 case PLDM_RANGE_FIELD_FORMAT_REAL32: 115 return pldm__msgbuf_extract_real32( 116 ctx, ((char *)rff) + offsetof(union_range_field_format, 117 value_f32)); 118 } 119 120 return -PLDM_ERROR_INVALID_DATA; 121 } 122 123 /* This API is bad, but it's because the caller's APIs are also bad */ 124 __attribute__((always_inline)) static inline int 125 pldm_msgbuf_extract_effecter_value(struct pldm_msgbuf *ctx, 126 enum pldm_effecter_data_size tag, void *dst) 127 { 128 switch (tag) { 129 case PLDM_EFFECTER_DATA_SIZE_UINT8: 130 return pldm__msgbuf_extract_uint8(ctx, dst); 131 case PLDM_EFFECTER_DATA_SIZE_SINT8: 132 return pldm__msgbuf_extract_int8(ctx, dst); 133 case PLDM_EFFECTER_DATA_SIZE_UINT16: 134 return pldm__msgbuf_extract_uint16(ctx, dst); 135 case PLDM_EFFECTER_DATA_SIZE_SINT16: 136 return pldm__msgbuf_extract_int16(ctx, dst); 137 case PLDM_EFFECTER_DATA_SIZE_UINT32: 138 return pldm__msgbuf_extract_uint32(ctx, dst); 139 case PLDM_EFFECTER_DATA_SIZE_SINT32: 140 return pldm__msgbuf_extract_int32(ctx, dst); 141 } 142 143 return -PLDM_ERROR_INVALID_DATA; 144 } 145 146 #define pldm_msgbuf_extract_effecter_data(ctx, tag, dst) \ 147 pldm_msgbuf_extract_typecheck(union_effecter_data_size, \ 148 pldm__msgbuf_extract_range_field_format, \ 149 dst, ctx, tag, (void *)&(dst)) 150 __attribute__((always_inline)) static inline int 151 pldm__msgbuf_extract_effecter_data(struct pldm_msgbuf *ctx, 152 enum pldm_effecter_data_size tag, void *ed) 153 { 154 switch (tag) { 155 case PLDM_EFFECTER_DATA_SIZE_UINT8: 156 return pldm__msgbuf_extract_uint8( 157 ctx, ((char *)ed) + offsetof(union_effecter_data_size, 158 value_u8)); 159 case PLDM_EFFECTER_DATA_SIZE_SINT8: 160 return pldm__msgbuf_extract_int8( 161 ctx, ((char *)ed) + offsetof(union_effecter_data_size, 162 value_s8)); 163 case PLDM_EFFECTER_DATA_SIZE_UINT16: 164 return pldm__msgbuf_extract_uint16( 165 ctx, ((char *)ed) + offsetof(union_effecter_data_size, 166 value_u16)); 167 case PLDM_EFFECTER_DATA_SIZE_SINT16: 168 return pldm__msgbuf_extract_int16( 169 ctx, ((char *)ed) + offsetof(union_effecter_data_size, 170 value_s16)); 171 case PLDM_EFFECTER_DATA_SIZE_UINT32: 172 return pldm__msgbuf_extract_uint32( 173 ctx, ((char *)ed) + offsetof(union_effecter_data_size, 174 value_u32)); 175 case PLDM_EFFECTER_DATA_SIZE_SINT32: 176 return pldm__msgbuf_extract_int32( 177 ctx, ((char *)ed) + offsetof(union_effecter_data_size, 178 value_s32)); 179 } 180 181 return -PLDM_ERROR_INVALID_DATA; 182 } 183 184 #ifdef __cplusplus 185 #include <type_traits> 186 187 template <typename T> 188 static inline int pldm_msgbuf_typecheck_range_field_format( 189 struct pldm_msgbuf *ctx, enum pldm_range_field_format tag, void *_rff) 190 { 191 static_assert(std::is_same<union_range_field_format, T>::value); 192 return pldm__msgbuf_extract_range_field_format(ctx, tag, _rff); 193 } 194 #endif 195 196 #endif 197