1 /*
2 * QEMU CBOR helpers
3 *
4 * Copyright (c) 2024 Dorjoy Chowdhury <dorjoychy111@gmail.com>
5 *
6 * This work is licensed under the terms of the GNU GPL, version 2 or
7 * (at your option) any later version. See the COPYING file in the
8 * top-level directory.
9 */
10
11 #include "hw/virtio/cbor-helpers.h"
12
qemu_cbor_map_add(cbor_item_t * map,cbor_item_t * key,cbor_item_t * value)13 bool qemu_cbor_map_add(cbor_item_t *map, cbor_item_t *key, cbor_item_t *value)
14 {
15 bool success = false;
16 struct cbor_pair pair = (struct cbor_pair) {
17 .key = cbor_move(key),
18 .value = cbor_move(value)
19 };
20
21 success = cbor_map_add(map, pair);
22 if (!success) {
23 cbor_incref(pair.key);
24 cbor_incref(pair.value);
25 }
26
27 return success;
28 }
29
qemu_cbor_array_push(cbor_item_t * array,cbor_item_t * value)30 bool qemu_cbor_array_push(cbor_item_t *array, cbor_item_t *value)
31 {
32 bool success = false;
33
34 success = cbor_array_push(array, cbor_move(value));
35 if (!success) {
36 cbor_incref(value);
37 }
38
39 return success;
40 }
41
qemu_cbor_add_bool_to_map(cbor_item_t * map,const char * key,bool value)42 bool qemu_cbor_add_bool_to_map(cbor_item_t *map, const char *key, bool value)
43 {
44 cbor_item_t *key_cbor = NULL;
45 cbor_item_t *value_cbor = NULL;
46
47 key_cbor = cbor_build_string(key);
48 if (!key_cbor) {
49 goto cleanup;
50 }
51 value_cbor = cbor_build_bool(value);
52 if (!value_cbor) {
53 goto cleanup;
54 }
55 if (!qemu_cbor_map_add(map, key_cbor, value_cbor)) {
56 goto cleanup;
57 }
58
59 return true;
60
61 cleanup:
62 if (key_cbor) {
63 cbor_decref(&key_cbor);
64 }
65 if (value_cbor) {
66 cbor_decref(&value_cbor);
67 }
68 return false;
69 }
70
qemu_cbor_add_uint8_to_map(cbor_item_t * map,const char * key,uint8_t value)71 bool qemu_cbor_add_uint8_to_map(cbor_item_t *map, const char *key,
72 uint8_t value)
73 {
74 cbor_item_t *key_cbor = NULL;
75 cbor_item_t *value_cbor = NULL;
76
77 key_cbor = cbor_build_string(key);
78 if (!key_cbor) {
79 goto cleanup;
80 }
81 value_cbor = cbor_build_uint8(value);
82 if (!value_cbor) {
83 goto cleanup;
84 }
85 if (!qemu_cbor_map_add(map, key_cbor, value_cbor)) {
86 goto cleanup;
87 }
88
89 return true;
90
91 cleanup:
92 if (key_cbor) {
93 cbor_decref(&key_cbor);
94 }
95 if (value_cbor) {
96 cbor_decref(&value_cbor);
97 }
98 return false;
99 }
100
qemu_cbor_add_map_to_map(cbor_item_t * map,const char * key,size_t nested_map_size,cbor_item_t ** nested_map)101 bool qemu_cbor_add_map_to_map(cbor_item_t *map, const char *key,
102 size_t nested_map_size,
103 cbor_item_t **nested_map)
104 {
105 cbor_item_t *key_cbor = NULL;
106 cbor_item_t *value_cbor = NULL;
107
108 key_cbor = cbor_build_string(key);
109 if (!key_cbor) {
110 goto cleanup;
111 }
112 value_cbor = cbor_new_definite_map(nested_map_size);
113 if (!value_cbor) {
114 goto cleanup;
115 }
116 if (!qemu_cbor_map_add(map, key_cbor, value_cbor)) {
117 goto cleanup;
118 }
119 *nested_map = value_cbor;
120
121 return true;
122
123 cleanup:
124 if (key_cbor) {
125 cbor_decref(&key_cbor);
126 }
127 if (value_cbor) {
128 cbor_decref(&value_cbor);
129 }
130 return false;
131 }
132
qemu_cbor_add_bytestring_to_map(cbor_item_t * map,const char * key,uint8_t * arr,size_t len)133 bool qemu_cbor_add_bytestring_to_map(cbor_item_t *map, const char *key,
134 uint8_t *arr, size_t len)
135 {
136 cbor_item_t *key_cbor = NULL;
137 cbor_item_t *value_cbor = NULL;
138
139 key_cbor = cbor_build_string(key);
140 if (!key_cbor) {
141 goto cleanup;
142 }
143 value_cbor = cbor_build_bytestring(arr, len);
144 if (!value_cbor) {
145 goto cleanup;
146 }
147 if (!qemu_cbor_map_add(map, key_cbor, value_cbor)) {
148 goto cleanup;
149 }
150
151 return true;
152
153 cleanup:
154 if (key_cbor) {
155 cbor_decref(&key_cbor);
156 }
157 if (value_cbor) {
158 cbor_decref(&value_cbor);
159 }
160 return false;
161 }
162
qemu_cbor_add_null_to_map(cbor_item_t * map,const char * key)163 bool qemu_cbor_add_null_to_map(cbor_item_t *map, const char *key)
164 {
165 cbor_item_t *key_cbor = NULL;
166 cbor_item_t *value_cbor = NULL;
167
168 key_cbor = cbor_build_string(key);
169 if (!key_cbor) {
170 goto cleanup;
171 }
172 value_cbor = cbor_new_null();
173 if (!value_cbor) {
174 goto cleanup;
175 }
176 if (!qemu_cbor_map_add(map, key_cbor, value_cbor)) {
177 goto cleanup;
178 }
179
180 return true;
181
182 cleanup:
183 if (key_cbor) {
184 cbor_decref(&key_cbor);
185 }
186 if (value_cbor) {
187 cbor_decref(&value_cbor);
188 }
189 return false;
190 }
191
qemu_cbor_add_string_to_map(cbor_item_t * map,const char * key,const char * value)192 bool qemu_cbor_add_string_to_map(cbor_item_t *map, const char *key,
193 const char *value)
194 {
195 cbor_item_t *key_cbor = NULL;
196 cbor_item_t *value_cbor = NULL;
197
198 key_cbor = cbor_build_string(key);
199 if (!key_cbor) {
200 goto cleanup;
201 }
202 value_cbor = cbor_build_string(value);
203 if (!value_cbor) {
204 goto cleanup;
205 }
206 if (!qemu_cbor_map_add(map, key_cbor, value_cbor)) {
207 goto cleanup;
208 }
209
210 return true;
211
212 cleanup:
213 if (key_cbor) {
214 cbor_decref(&key_cbor);
215 }
216 if (value_cbor) {
217 cbor_decref(&value_cbor);
218 }
219 return false;
220 }
221
qemu_cbor_add_uint8_array_to_map(cbor_item_t * map,const char * key,uint8_t * arr,size_t len)222 bool qemu_cbor_add_uint8_array_to_map(cbor_item_t *map, const char *key,
223 uint8_t *arr, size_t len)
224 {
225 cbor_item_t *key_cbor = NULL;
226 cbor_item_t *value_cbor = NULL;
227
228 key_cbor = cbor_build_string(key);
229 if (!key_cbor) {
230 goto cleanup;
231 }
232 value_cbor = cbor_new_definite_array(len);
233 if (!value_cbor) {
234 goto cleanup;
235 }
236
237 for (int i = 0; i < len; ++i) {
238 cbor_item_t *tmp = cbor_build_uint8(arr[i]);
239 if (!tmp) {
240 goto cleanup;
241 }
242 if (!qemu_cbor_array_push(value_cbor, tmp)) {
243 cbor_decref(&tmp);
244 goto cleanup;
245 }
246 }
247 if (!qemu_cbor_map_add(map, key_cbor, value_cbor)) {
248 goto cleanup;
249 }
250
251 return true;
252
253 cleanup:
254 if (key_cbor) {
255 cbor_decref(&key_cbor);
256 }
257 if (value_cbor) {
258 cbor_decref(&value_cbor);
259 }
260 return false;
261 }
262
qemu_cbor_add_uint8_key_bytestring_to_map(cbor_item_t * map,uint8_t key,uint8_t * buf,size_t len)263 bool qemu_cbor_add_uint8_key_bytestring_to_map(cbor_item_t *map, uint8_t key,
264 uint8_t *buf, size_t len)
265 {
266 cbor_item_t *key_cbor = NULL;
267 cbor_item_t *value_cbor = NULL;
268
269 key_cbor = cbor_build_uint8(key);
270 if (!key_cbor) {
271 goto cleanup;
272 }
273 value_cbor = cbor_build_bytestring(buf, len);
274 if (!value_cbor) {
275 goto cleanup;
276 }
277 if (!qemu_cbor_map_add(map, key_cbor, value_cbor)) {
278 goto cleanup;
279 }
280
281 return true;
282
283 cleanup:
284 if (key_cbor) {
285 cbor_decref(&key_cbor);
286 }
287 if (value_cbor) {
288 cbor_decref(&value_cbor);
289 }
290 return false;
291 }
292
qemu_cbor_add_uint64_to_map(cbor_item_t * map,const char * key,uint64_t value)293 bool qemu_cbor_add_uint64_to_map(cbor_item_t *map, const char *key,
294 uint64_t value)
295 {
296 cbor_item_t *key_cbor = NULL;
297 cbor_item_t *value_cbor = NULL;
298
299 key_cbor = cbor_build_string(key);
300 if (!key_cbor) {
301 goto cleanup;
302 }
303 value_cbor = cbor_build_uint64(value);
304 if (!value_cbor) {
305 goto cleanup;
306 }
307 if (!qemu_cbor_map_add(map, key_cbor, value_cbor)) {
308 goto cleanup;
309 }
310
311 return true;
312
313 cleanup:
314 if (key_cbor) {
315 cbor_decref(&key_cbor);
316 }
317 if (value_cbor) {
318 cbor_decref(&value_cbor);
319 }
320 return false;
321 }
322