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