xref: /aosp_15_r20/external/coreboot/src/commonlib/iobuf.c (revision b9411a12aaaa7e1e6a6fb7c5e057f44ee179a49c)
1 /* SPDX-License-Identifier: GPL-2.0-only */
2 
3 #include <commonlib/endian.h>
4 #include <commonlib/iobuf.h>
5 #include <string.h>
6 #include <stdint.h>
7 
ibuf_check_size(const struct ibuf * ib,size_t sz)8 static int ibuf_check_size(const struct ibuf *ib, size_t sz)
9 {
10 	if (ibuf_remaining(ib) < sz)
11 		return -1;
12 
13 	return 0;
14 }
15 
ibuf_init(struct ibuf * ib,const void * b,size_t sz)16 void ibuf_init(struct ibuf *ib, const void *b, size_t sz)
17 {
18 	ib->b = b;
19 	ib->n_read = 0;
20 	ib->capacity = sz;
21 }
22 
ibuf_from_obuf(struct ibuf * ib,const struct obuf * ob)23 void ibuf_from_obuf(struct ibuf *ib, const struct obuf *ob)
24 {
25 	ibuf_init(ib, ob->b, ob->n_written);
26 }
27 
ibuf_splice(const struct ibuf * src,struct ibuf * dst,size_t off,size_t sz)28 int ibuf_splice(const struct ibuf *src, struct ibuf *dst, size_t off, size_t sz)
29 {
30 	size_t end = off + sz;
31 	size_t capacity = ibuf_capacity(src);
32 	size_t nr_read = ibuf_nr_read(src);
33 
34 	if (end < off || end < sz || end > capacity)
35 		return -1;
36 
37 	ibuf_init(dst, &src->b[off], sz);
38 
39 	/* Handle previously read data in src. */
40 	if (off < nr_read)
41 		dst->n_read = nr_read - off;
42 
43 	return 0;
44 }
45 
ibuf_splice_current(const struct ibuf * src,struct ibuf * dst,size_t sz)46 int ibuf_splice_current(const struct ibuf *src, struct ibuf *dst, size_t sz)
47 {
48 	return ibuf_splice(src, dst, ibuf_nr_read(src), sz);
49 }
50 
ibuf_split(const struct ibuf * src,struct ibuf * a,struct ibuf * b,size_t boundary)51 int ibuf_split(const struct ibuf *src, struct ibuf *a, struct ibuf *b,
52 		size_t boundary)
53 {
54 	if (ibuf_splice(src, a, 0, boundary))
55 		return -1;
56 
57 	return ibuf_splice(src, b, boundary, ibuf_capacity(src) - boundary);
58 }
59 
ibuf_oob_drain(struct ibuf * ib,size_t sz)60 const void *ibuf_oob_drain(struct ibuf *ib, size_t sz)
61 {
62 	const void *b;
63 
64 	if (ibuf_check_size(ib, sz))
65 		return NULL;
66 
67 	b = &ib->b[ib->n_read];
68 	ib->n_read += sz;
69 
70 	return b;
71 }
72 
ibuf_read(struct ibuf * ib,void * data,size_t sz)73 int ibuf_read(struct ibuf *ib, void *data, size_t sz)
74 {
75 	const void *b = ibuf_oob_drain(ib, sz);
76 
77 	if (b == NULL)
78 		return -1;
79 
80 	memcpy(data, b, sz);
81 
82 	return 0;
83 }
84 
ibuf_read_be8(struct ibuf * ib,uint8_t * v)85 int ibuf_read_be8(struct ibuf *ib, uint8_t *v)
86 {
87 	size_t sz = sizeof(*v);
88 
89 	if (ibuf_check_size(ib, sz))
90 		return -1;
91 
92 	*v = read_at_be8(ib->b, ib->n_read);
93 	ib->n_read += sz;
94 
95 	return 0;
96 }
97 
ibuf_read_be16(struct ibuf * ib,uint16_t * v)98 int ibuf_read_be16(struct ibuf *ib, uint16_t *v)
99 {
100 	size_t sz = sizeof(*v);
101 
102 	if (ibuf_check_size(ib, sz))
103 		return -1;
104 
105 	*v = read_at_be16(ib->b, ib->n_read);
106 	ib->n_read += sz;
107 
108 	return 0;
109 }
110 
ibuf_read_be32(struct ibuf * ib,uint32_t * v)111 int ibuf_read_be32(struct ibuf *ib, uint32_t *v)
112 {
113 	size_t sz = sizeof(*v);
114 
115 	if (ibuf_check_size(ib, sz))
116 		return -1;
117 
118 	*v = read_at_be32(ib->b, ib->n_read);
119 	ib->n_read += sz;
120 
121 	return 0;
122 }
123 
ibuf_read_be64(struct ibuf * ib,uint64_t * v)124 int ibuf_read_be64(struct ibuf *ib, uint64_t *v)
125 {
126 	size_t sz = sizeof(*v);
127 
128 	if (ibuf_check_size(ib, sz))
129 		return -1;
130 
131 	*v = read_at_be64(ib->b, ib->n_read);
132 	ib->n_read += sz;
133 
134 	return 0;
135 }
136 
ibuf_read_le8(struct ibuf * ib,uint8_t * v)137 int ibuf_read_le8(struct ibuf *ib, uint8_t *v)
138 {
139 	size_t sz = sizeof(*v);
140 
141 	if (ibuf_check_size(ib, sz))
142 		return -1;
143 
144 	*v = read_at_le8(ib->b, ib->n_read);
145 	ib->n_read += sz;
146 
147 	return 0;
148 }
149 
ibuf_read_le16(struct ibuf * ib,uint16_t * v)150 int ibuf_read_le16(struct ibuf *ib, uint16_t *v)
151 {
152 	size_t sz = sizeof(*v);
153 
154 	if (ibuf_check_size(ib, sz))
155 		return -1;
156 
157 	*v = read_at_le16(ib->b, ib->n_read);
158 	ib->n_read += sz;
159 
160 	return 0;
161 }
162 
ibuf_read_le32(struct ibuf * ib,uint32_t * v)163 int ibuf_read_le32(struct ibuf *ib, uint32_t *v)
164 {
165 	size_t sz = sizeof(*v);
166 
167 	if (ibuf_check_size(ib, sz))
168 		return -1;
169 
170 	*v = read_at_le32(ib->b, ib->n_read);
171 	ib->n_read += sz;
172 
173 	return 0;
174 }
175 
ibuf_read_le64(struct ibuf * ib,uint64_t * v)176 int ibuf_read_le64(struct ibuf *ib, uint64_t *v)
177 {
178 	size_t sz = sizeof(*v);
179 
180 	if (ibuf_check_size(ib, sz))
181 		return -1;
182 
183 	*v = read_at_le64(ib->b, ib->n_read);
184 	ib->n_read += sz;
185 
186 	return 0;
187 }
188 
ibuf_read_n8(struct ibuf * ib,uint8_t * v)189 int ibuf_read_n8(struct ibuf *ib, uint8_t *v)
190 {
191 	return ibuf_read(ib, v, sizeof(*v));
192 }
193 
ibuf_read_n16(struct ibuf * ib,uint16_t * v)194 int ibuf_read_n16(struct ibuf *ib, uint16_t *v)
195 {
196 	return ibuf_read(ib, v, sizeof(*v));
197 }
198 
ibuf_read_n32(struct ibuf * ib,uint32_t * v)199 int ibuf_read_n32(struct ibuf *ib, uint32_t *v)
200 {
201 	return ibuf_read(ib, v, sizeof(*v));
202 }
203 
ibuf_read_n64(struct ibuf * ib,uint64_t * v)204 int ibuf_read_n64(struct ibuf *ib, uint64_t *v)
205 {
206 	return ibuf_read(ib, v, sizeof(*v));
207 }
208 
obuf_check_size(const struct obuf * ob,size_t sz)209 static int obuf_check_size(const struct obuf *ob, size_t sz)
210 {
211 	if (obuf_remaining(ob) < sz)
212 		return -1;
213 
214 	return 0;
215 }
216 
obuf_init(struct obuf * ob,void * b,size_t sz)217 void obuf_init(struct obuf *ob, void *b, size_t sz)
218 {
219 	ob->b = b;
220 	ob->n_written = 0;
221 	ob->capacity = sz;
222 }
223 
obuf_splice(const struct obuf * src,struct obuf * dst,size_t off,size_t sz)224 int obuf_splice(const struct obuf *src, struct obuf *dst, size_t off, size_t sz)
225 {
226 	size_t end = off + sz;
227 	size_t capacity = obuf_capacity(src);
228 	size_t nr_written = obuf_nr_written(src);
229 
230 	if (end < off || end < sz || end > capacity)
231 		return -1;
232 
233 	obuf_init(dst, &src->b[off], sz);
234 
235 	/* Handle previously written data in src. */
236 	if (off < nr_written)
237 		dst->n_written = nr_written - off;
238 
239 	return 0;
240 }
241 
obuf_splice_current(const struct obuf * src,struct obuf * dst,size_t sz)242 int obuf_splice_current(const struct obuf *src, struct obuf *dst, size_t sz)
243 {
244 	return obuf_splice(src, dst, obuf_nr_written(src), sz);
245 }
246 
obuf_split(const struct obuf * src,struct obuf * a,struct obuf * b,size_t boundary)247 int obuf_split(const struct obuf *src, struct obuf *a, struct obuf *b,
248 		size_t boundary)
249 {
250 	if (obuf_splice(src, a, 0, boundary))
251 		return -1;
252 
253 	return obuf_splice(src, b, boundary, obuf_capacity(src) - boundary);
254 }
255 
obuf_oob_fill(struct obuf * ob,size_t sz)256 void *obuf_oob_fill(struct obuf *ob, size_t sz)
257 {
258 	void *b;
259 
260 	if (obuf_check_size(ob, sz))
261 		return NULL;
262 
263 	b = &ob->b[ob->n_written];
264 	ob->n_written += sz;
265 
266 	return b;
267 }
268 
obuf_write(struct obuf * ob,const void * data,size_t sz)269 int obuf_write(struct obuf *ob, const void *data, size_t sz)
270 {
271 	void *b;
272 
273 	b = obuf_oob_fill(ob, sz);
274 	if (b == NULL)
275 		return -1;
276 
277 	memcpy(b, data, sz);
278 
279 	return 0;
280 }
281 
obuf_write_be8(struct obuf * ob,uint8_t v)282 int obuf_write_be8(struct obuf *ob, uint8_t v)
283 {
284 	size_t sz = sizeof(v);
285 
286 	if (obuf_check_size(ob, sz))
287 		return -1;
288 
289 	write_at_be8(ob->b, v, ob->n_written);
290 	ob->n_written += sz;
291 
292 	return 0;
293 }
294 
obuf_write_be16(struct obuf * ob,uint16_t v)295 int obuf_write_be16(struct obuf *ob, uint16_t v)
296 {
297 	size_t sz = sizeof(v);
298 
299 	if (obuf_check_size(ob, sz))
300 		return -1;
301 
302 	write_at_be16(ob->b, v, ob->n_written);
303 	ob->n_written += sz;
304 
305 	return 0;
306 }
307 
obuf_write_be32(struct obuf * ob,uint32_t v)308 int obuf_write_be32(struct obuf *ob, uint32_t v)
309 {
310 	size_t sz = sizeof(v);
311 
312 	if (obuf_check_size(ob, sz))
313 		return -1;
314 
315 	write_at_be32(ob->b, v, ob->n_written);
316 	ob->n_written += sz;
317 
318 	return 0;
319 }
320 
obuf_write_be64(struct obuf * ob,uint64_t v)321 int obuf_write_be64(struct obuf *ob, uint64_t v)
322 {
323 	size_t sz = sizeof(v);
324 
325 	if (obuf_check_size(ob, sz))
326 		return -1;
327 
328 	write_at_be64(ob->b, v, ob->n_written);
329 	ob->n_written += sz;
330 
331 	return 0;
332 }
333 
obuf_write_le8(struct obuf * ob,uint8_t v)334 int obuf_write_le8(struct obuf *ob, uint8_t v)
335 {
336 	size_t sz = sizeof(v);
337 
338 	if (obuf_check_size(ob, sz))
339 		return -1;
340 
341 	write_at_le8(ob->b, v, ob->n_written);
342 	ob->n_written += sz;
343 
344 	return 0;
345 }
346 
obuf_write_le16(struct obuf * ob,uint16_t v)347 int obuf_write_le16(struct obuf *ob, uint16_t v)
348 {
349 	size_t sz = sizeof(v);
350 
351 	if (obuf_check_size(ob, sz))
352 		return -1;
353 
354 	write_at_le16(ob->b, v, ob->n_written);
355 	ob->n_written += sz;
356 
357 	return 0;
358 }
359 
obuf_write_le32(struct obuf * ob,uint32_t v)360 int obuf_write_le32(struct obuf *ob, uint32_t v)
361 {
362 	size_t sz = sizeof(v);
363 
364 	if (obuf_check_size(ob, sz))
365 		return -1;
366 
367 	write_at_le32(ob->b, v, ob->n_written);
368 	ob->n_written += sz;
369 
370 	return 0;
371 }
372 
obuf_write_le64(struct obuf * ob,uint64_t v)373 int obuf_write_le64(struct obuf *ob, uint64_t v)
374 {
375 	size_t sz = sizeof(v);
376 
377 	if (obuf_check_size(ob, sz))
378 		return -1;
379 
380 	write_at_le64(ob->b, v, ob->n_written);
381 	ob->n_written += sz;
382 
383 	return 0;
384 }
385 
obuf_write_n8(struct obuf * ob,uint8_t v)386 int obuf_write_n8(struct obuf *ob, uint8_t v)
387 {
388 	return obuf_write(ob, &v, sizeof(v));
389 }
390 
obuf_write_n16(struct obuf * ob,uint16_t v)391 int obuf_write_n16(struct obuf *ob, uint16_t v)
392 {
393 	return obuf_write(ob, &v, sizeof(v));
394 }
395 
obuf_write_n32(struct obuf * ob,uint32_t v)396 int obuf_write_n32(struct obuf *ob, uint32_t v)
397 {
398 	return obuf_write(ob, &v, sizeof(v));
399 }
400 
obuf_write_n64(struct obuf * ob,uint64_t v)401 int obuf_write_n64(struct obuf *ob, uint64_t v)
402 {
403 	return obuf_write(ob, &v, sizeof(v));
404 }
405 
obuf_contents(const struct obuf * ob,size_t * sz)406 const void *obuf_contents(const struct obuf *ob, size_t *sz)
407 {
408 	*sz = obuf_nr_written(ob);
409 	return ob->b;
410 }
411