xref: /openbmc/libpldm/src/msgbuf/platform.h (revision 329176a88cd44ed2d80e03fb9ef3bfa1386901b5)
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
pldm_msgbuf_extract_value_pdr_hdr(struct pldm_msgbuf * ctx,struct pldm_value_pdr_hdr * hdr,size_t lower,size_t upper)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
pldm_msgbuf_extract_sensor_data(struct pldm_msgbuf * ctx,enum pldm_sensor_readings_data_type tag,union_sensor_data_size * dst)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
pldm_msgbuf_extract_sensor_value(struct pldm_msgbuf * ctx,enum pldm_sensor_readings_data_type tag,void * val)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))
pldm__msgbuf_extract_range_field_format(struct pldm_msgbuf * ctx,enum pldm_range_field_format tag,void * rff)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
pldm_msgbuf_extract_effecter_value(struct pldm_msgbuf * ctx,enum pldm_effecter_data_size tag,void * dst)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
pldm__msgbuf_extract_effecter_data(struct pldm_msgbuf * ctx,enum pldm_effecter_data_size tag,void * ed)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>
pldm_msgbuf_typecheck_range_field_format(struct pldm_msgbuf * ctx,enum pldm_range_field_format tag,void * _rff)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