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