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