| /* SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later */ | 
 | #ifndef PLDM_MSGBUF_PLATFORM_H | 
 | #define PLDM_MSGBUF_PLATFORM_H | 
 |  | 
 | #include "../compiler.h" | 
 | #include "../msgbuf.h" | 
 | #include <libpldm/base.h> | 
 | #include <libpldm/platform.h> | 
 |  | 
 | LIBPLDM_CC_NONNULL | 
 | LIBPLDM_CC_ALWAYS_INLINE int | 
 | pldm_msgbuf_extract_value_pdr_hdr(struct pldm_msgbuf_ro *ctx, | 
 | 				  struct pldm_value_pdr_hdr *hdr, size_t lower, | 
 | 				  size_t upper) | 
 | { | 
 | 	int rc; | 
 |  | 
 | 	pldm_msgbuf_extract(ctx, hdr->record_handle); | 
 | 	pldm_msgbuf_extract(ctx, hdr->version); | 
 | 	pldm_msgbuf_extract(ctx, hdr->type); | 
 | 	pldm_msgbuf_extract(ctx, hdr->record_change_num); | 
 | 	rc = pldm_msgbuf_extract(ctx, hdr->length); | 
 | 	if (rc) { | 
 | 		return rc; | 
 | 	} | 
 |  | 
 | 	if (hdr->length + sizeof(*ctx) < lower) { | 
 | 		return -EOVERFLOW; | 
 | 	} | 
 |  | 
 | 	if (hdr->length > upper) { | 
 | 		return -EOVERFLOW; | 
 | 	} | 
 |  | 
 | 	return 0; | 
 | } | 
 |  | 
 | LIBPLDM_CC_ALWAYS_INLINE int | 
 | pldm_msgbuf_extract_sensor_data(struct pldm_msgbuf_ro *ctx, | 
 | 				enum pldm_sensor_readings_data_type tag, | 
 | 				union_sensor_data_size *dst) | 
 | { | 
 | 	switch (tag) { | 
 | 	case PLDM_SENSOR_DATA_SIZE_UINT8: | 
 | 		return pldm_msgbuf_extract(ctx, dst->value_u8); | 
 | 	case PLDM_SENSOR_DATA_SIZE_SINT8: | 
 | 		return pldm_msgbuf_extract(ctx, dst->value_s8); | 
 | 	case PLDM_SENSOR_DATA_SIZE_UINT16: | 
 | 		return pldm_msgbuf_extract(ctx, dst->value_u16); | 
 | 	case PLDM_SENSOR_DATA_SIZE_SINT16: | 
 | 		return pldm_msgbuf_extract(ctx, dst->value_s16); | 
 | 	case PLDM_SENSOR_DATA_SIZE_UINT32: | 
 | 		return pldm_msgbuf_extract(ctx, dst->value_u32); | 
 | 	case PLDM_SENSOR_DATA_SIZE_SINT32: | 
 | 		return pldm_msgbuf_extract(ctx, dst->value_s32); | 
 | 	} | 
 |  | 
 | 	return -PLDM_ERROR_INVALID_DATA; | 
 | } | 
 |  | 
 | /* | 
 |  * This API is bad, but it's because the caller's APIs are also bad. They should | 
 |  * have used the approach used by callers of pldm_msgbuf_extract_sensor_data() | 
 |  * above | 
 |  */ | 
 | LIBPLDM_CC_ALWAYS_INLINE int | 
 | pldm_msgbuf_extract_sensor_value(struct pldm_msgbuf_ro *ctx, | 
 | 				 enum pldm_sensor_readings_data_type tag, | 
 | 				 void *val) | 
 | { | 
 | 	switch (tag) { | 
 | 	case PLDM_SENSOR_DATA_SIZE_UINT8: | 
 | 		return pldm__msgbuf_extract_uint8(ctx, val); | 
 | 	case PLDM_SENSOR_DATA_SIZE_SINT8: | 
 | 		return pldm__msgbuf_extract_int8(ctx, val); | 
 | 	case PLDM_SENSOR_DATA_SIZE_UINT16: | 
 | 		return pldm__msgbuf_extract_uint16(ctx, val); | 
 | 	case PLDM_SENSOR_DATA_SIZE_SINT16: | 
 | 		return pldm__msgbuf_extract_int16(ctx, val); | 
 | 	case PLDM_SENSOR_DATA_SIZE_UINT32: | 
 | 		return pldm__msgbuf_extract_uint32(ctx, val); | 
 | 	case PLDM_SENSOR_DATA_SIZE_SINT32: | 
 | 		return pldm__msgbuf_extract_int32(ctx, val); | 
 | 	} | 
 |  | 
 | 	return -PLDM_ERROR_INVALID_DATA; | 
 | } | 
 |  | 
 | #define pldm_msgbuf_extract_range_field_format(ctx, tag, dst)                  \ | 
 | 	pldm_msgbuf_extract_typecheck(union_range_field_format,                \ | 
 | 				      pldm__msgbuf_extract_range_field_format, \ | 
 | 				      dst, ctx, tag, (void *)&(dst)) | 
 | LIBPLDM_CC_ALWAYS_INLINE int pldm__msgbuf_extract_range_field_format( | 
 | 	struct pldm_msgbuf_ro *ctx, enum pldm_range_field_format tag, void *rff) | 
 | { | 
 | 	switch (tag) { | 
 | 	case PLDM_RANGE_FIELD_FORMAT_UINT8: | 
 | 		return pldm__msgbuf_extract_uint8( | 
 | 			ctx, ((char *)rff) + offsetof(union_range_field_format, | 
 | 						      value_u8)); | 
 | 	case PLDM_RANGE_FIELD_FORMAT_SINT8: | 
 | 		return pldm__msgbuf_extract_int8( | 
 | 			ctx, ((char *)rff) + offsetof(union_range_field_format, | 
 | 						      value_s8)); | 
 | 	case PLDM_RANGE_FIELD_FORMAT_UINT16: | 
 | 		return pldm__msgbuf_extract_uint16( | 
 | 			ctx, ((char *)rff) + offsetof(union_range_field_format, | 
 | 						      value_u16)); | 
 | 	case PLDM_RANGE_FIELD_FORMAT_SINT16: | 
 | 		return pldm__msgbuf_extract_int16( | 
 | 			ctx, ((char *)rff) + offsetof(union_range_field_format, | 
 | 						      value_s16)); | 
 | 	case PLDM_RANGE_FIELD_FORMAT_UINT32: | 
 | 		return pldm__msgbuf_extract_uint32( | 
 | 			ctx, ((char *)rff) + offsetof(union_range_field_format, | 
 | 						      value_u32)); | 
 | 	case PLDM_RANGE_FIELD_FORMAT_SINT32: | 
 | 		return pldm__msgbuf_extract_int32( | 
 | 			ctx, ((char *)rff) + offsetof(union_range_field_format, | 
 | 						      value_s32)); | 
 | 	case PLDM_RANGE_FIELD_FORMAT_REAL32: | 
 | 		return pldm__msgbuf_extract_real32( | 
 | 			ctx, ((char *)rff) + offsetof(union_range_field_format, | 
 | 						      value_f32)); | 
 | 	} | 
 |  | 
 | 	return -PLDM_ERROR_INVALID_DATA; | 
 | } | 
 |  | 
 | /* This API is bad, but it's because the caller's APIs are also bad */ | 
 | LIBPLDM_CC_ALWAYS_INLINE int | 
 | pldm_msgbuf_extract_effecter_value(struct pldm_msgbuf_ro *ctx, | 
 | 				   enum pldm_effecter_data_size tag, void *dst) | 
 | { | 
 | 	switch (tag) { | 
 | 	case PLDM_EFFECTER_DATA_SIZE_UINT8: | 
 | 		return pldm__msgbuf_extract_uint8(ctx, dst); | 
 | 	case PLDM_EFFECTER_DATA_SIZE_SINT8: | 
 | 		return pldm__msgbuf_extract_int8(ctx, dst); | 
 | 	case PLDM_EFFECTER_DATA_SIZE_UINT16: | 
 | 		return pldm__msgbuf_extract_uint16(ctx, dst); | 
 | 	case PLDM_EFFECTER_DATA_SIZE_SINT16: | 
 | 		return pldm__msgbuf_extract_int16(ctx, dst); | 
 | 	case PLDM_EFFECTER_DATA_SIZE_UINT32: | 
 | 		return pldm__msgbuf_extract_uint32(ctx, dst); | 
 | 	case PLDM_EFFECTER_DATA_SIZE_SINT32: | 
 | 		return pldm__msgbuf_extract_int32(ctx, dst); | 
 | 	} | 
 |  | 
 | 	return -PLDM_ERROR_INVALID_DATA; | 
 | } | 
 |  | 
 | #define pldm_msgbuf_extract_effecter_data(ctx, tag, dst)                       \ | 
 | 	pldm_msgbuf_extract_typecheck(union_effecter_data_size,                \ | 
 | 				      pldm__msgbuf_extract_range_field_format, \ | 
 | 				      dst, ctx, tag, (void *)&(dst)) | 
 | LIBPLDM_CC_ALWAYS_INLINE int | 
 | pldm__msgbuf_extract_effecter_data(struct pldm_msgbuf_ro *ctx, | 
 | 				   enum pldm_effecter_data_size tag, void *ed) | 
 | { | 
 | 	switch (tag) { | 
 | 	case PLDM_EFFECTER_DATA_SIZE_UINT8: | 
 | 		return pldm__msgbuf_extract_uint8( | 
 | 			ctx, ((char *)ed) + offsetof(union_effecter_data_size, | 
 | 						     value_u8)); | 
 | 	case PLDM_EFFECTER_DATA_SIZE_SINT8: | 
 | 		return pldm__msgbuf_extract_int8( | 
 | 			ctx, ((char *)ed) + offsetof(union_effecter_data_size, | 
 | 						     value_s8)); | 
 | 	case PLDM_EFFECTER_DATA_SIZE_UINT16: | 
 | 		return pldm__msgbuf_extract_uint16( | 
 | 			ctx, ((char *)ed) + offsetof(union_effecter_data_size, | 
 | 						     value_u16)); | 
 | 	case PLDM_EFFECTER_DATA_SIZE_SINT16: | 
 | 		return pldm__msgbuf_extract_int16( | 
 | 			ctx, ((char *)ed) + offsetof(union_effecter_data_size, | 
 | 						     value_s16)); | 
 | 	case PLDM_EFFECTER_DATA_SIZE_UINT32: | 
 | 		return pldm__msgbuf_extract_uint32( | 
 | 			ctx, ((char *)ed) + offsetof(union_effecter_data_size, | 
 | 						     value_u32)); | 
 | 	case PLDM_EFFECTER_DATA_SIZE_SINT32: | 
 | 		return pldm__msgbuf_extract_int32( | 
 | 			ctx, ((char *)ed) + offsetof(union_effecter_data_size, | 
 | 						     value_s32)); | 
 | 	} | 
 |  | 
 | 	return -PLDM_ERROR_INVALID_DATA; | 
 | } | 
 |  | 
 | #ifdef __cplusplus | 
 | #include <type_traits> | 
 |  | 
 | template <typename T> | 
 | static inline int | 
 | pldm_msgbuf_typecheck_range_field_format(struct pldm_msgbuf_ro *ctx, | 
 | 					 enum pldm_range_field_format tag, | 
 | 					 void *_rff) | 
 | { | 
 | 	static_assert(std::is_same<union_range_field_format, T>::value); | 
 | 	return pldm__msgbuf_extract_range_field_format(ctx, tag, _rff); | 
 | } | 
 | #endif | 
 |  | 
 | #endif |