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