| /* 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 *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 *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 *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 *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 *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 *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 *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 |