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