| /* |
| * This file is part of the coreboot project. |
| * |
| * Copyright 2017 Google Inc. |
| * |
| * This program is free software; you can redistribute it and/or modify |
| * it under the terms of the GNU General Public License as published by |
| * the Free Software Foundation; version 2 of the License. |
| * |
| * This program is distributed in the hope that it will be useful, |
| * but WITHOUT ANY WARRANTY; without even the implied warranty of |
| * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
| * GNU General Public License for more details. |
| */ |
| |
| #ifndef COMMONLIB_IOBUF_H |
| #define COMMONLIB_IOBUF_H |
| |
| #include <stdint.h> |
| #include <sys/types.h> |
| |
| /* |
| * Two types are provided to aid in dealing with automatic buffer management |
| * for code that deals with serializing and deserializing data structures. |
| * The ibuf (input buffer) is read from while the obuf (output buffer) is |
| * written to. Both keep track of capacity of the buffer as well as current |
| * read or write cursor. |
| * |
| * When splicing or splitting ibufs of obufs the source object doesn't track |
| * reads or writes through the newly created objects back to the source object. |
| * |
| * Any function returning an int encodes the return values as < 0 on error |
| * and 0 on success. Any function returning a pointer returns NULL on error |
| * and non-NULL on success. |
| */ |
| |
| struct ibuf { |
| const uint8_t *b; |
| size_t n_read; |
| size_t capacity; |
| }; |
| |
| struct obuf { |
| uint8_t *b; |
| size_t n_written; |
| size_t capacity; |
| }; |
| |
| /* Helper functions. */ |
| static inline size_t ibuf_capacity(const struct ibuf *ib) |
| { |
| return ib->capacity; |
| } |
| |
| static inline size_t ibuf_nr_read(const struct ibuf *ib) |
| { |
| return ib->n_read; |
| } |
| |
| static inline size_t ibuf_remaining(const struct ibuf *ib) |
| { |
| return ibuf_capacity(ib) - ibuf_nr_read(ib); |
| } |
| |
| static inline size_t obuf_capacity(const struct obuf *ob) |
| { |
| return ob->capacity; |
| } |
| |
| static inline size_t obuf_nr_written(const struct obuf *ob) |
| { |
| return ob->n_written; |
| } |
| |
| static inline size_t obuf_remaining(const struct obuf *ob) |
| { |
| return obuf_capacity(ob) - obuf_nr_written(ob); |
| } |
| |
| /* Initialize an ibuf with buffer and size of data. */ |
| void ibuf_init(struct ibuf *ib, const void *b, size_t sz); |
| |
| /* Create a new ibuf based on a subregion of the src ibuf. */ |
| int ibuf_splice(const struct ibuf *src, struct ibuf *dst, size_t off, |
| size_t sz); |
| |
| /* Same as ibuf_splice(), but start from last read byte offset. */ |
| int ibuf_splice_current(const struct ibuf *src, struct ibuf *dst, size_t sz); |
| |
| /* Split an ibuf into 2 new ibufs at provided boundary. */ |
| int ibuf_split(const struct ibuf *src, struct ibuf *a, struct ibuf *b, |
| size_t boundary); |
| |
| /* Out-of-band drain of ibuf by returning pointer to data of specified size. */ |
| const void *ibuf_oob_drain(struct ibuf *ib, size_t sz); |
| |
| /* Read arbitray data from input buffer. */ |
| int ibuf_read(struct ibuf *ib, void *data, size_t sz); |
| |
| /* Read big endian fixed size values. */ |
| int ibuf_read_be8(struct ibuf *ib, uint8_t *v); |
| int ibuf_read_be16(struct ibuf *ib, uint16_t *v); |
| int ibuf_read_be32(struct ibuf *ib, uint32_t *v); |
| int ibuf_read_be64(struct ibuf *ib, uint64_t *v); |
| |
| /* Read little endian fixed size values. */ |
| int ibuf_read_le8(struct ibuf *ib, uint8_t *v); |
| int ibuf_read_le16(struct ibuf *ib, uint16_t *v); |
| int ibuf_read_le32(struct ibuf *ib, uint32_t *v); |
| int ibuf_read_le64(struct ibuf *ib, uint64_t *v); |
| |
| /* Read native endian fixed size values. */ |
| int ibuf_read_n8(struct ibuf *ib, uint8_t *v); |
| int ibuf_read_n16(struct ibuf *ib, uint16_t *v); |
| int ibuf_read_n32(struct ibuf *ib, uint32_t *v); |
| int ibuf_read_n64(struct ibuf *ib, uint64_t *v); |
| |
| /* Helper to create an ibuf from an obuf after an entity has written data. */ |
| void ibuf_from_obuf(struct ibuf *ib, const struct obuf *ob); |
| |
| /* Initialize an obuf with buffer and maximum capacity. */ |
| void obuf_init(struct obuf *ob, void *b, size_t sz); |
| |
| /* Provide the buffer and size of the written contents. */ |
| const void *obuf_contents(const struct obuf *ob, size_t *sz); |
| |
| /* Create a new obuf based on a subregion of the src obuf. */ |
| int obuf_splice(const struct obuf *src, struct obuf *dst, size_t off, |
| size_t sz); |
| |
| /* Same as obuf_splice(), but start from last written byte offset. */ |
| int obuf_splice_current(const struct obuf *src, struct obuf *dst, size_t sz); |
| |
| /* Split an obuf into 2 new obufs at provided boundary. */ |
| int obuf_split(const struct obuf *src, struct obuf *a, struct obuf *b, |
| size_t boundary); |
| |
| /* Fill the buffer out-of-band. The size is accounted for. */ |
| void *obuf_oob_fill(struct obuf *ob, size_t sz); |
| |
| /* Write arbitray data to output buffer. */ |
| int obuf_write(struct obuf *ob, const void *data, size_t sz); |
| |
| /* Write big endian fixed size values. */ |
| int obuf_write_be8(struct obuf *ob, uint8_t v); |
| int obuf_write_be16(struct obuf *ob, uint16_t v); |
| int obuf_write_be32(struct obuf *ob, uint32_t v); |
| int obuf_write_be64(struct obuf *ob, uint64_t v); |
| |
| /* Write little endian fixed size values. */ |
| int obuf_write_le8(struct obuf *ob, uint8_t v); |
| int obuf_write_le16(struct obuf *ob, uint16_t v); |
| int obuf_write_le32(struct obuf *ob, uint32_t v); |
| int obuf_write_le64(struct obuf *ob, uint64_t v); |
| |
| /* Write native endian fixed size values. */ |
| int obuf_write_n8(struct obuf *ob, uint8_t v); |
| int obuf_write_n16(struct obuf *ob, uint16_t v); |
| int obuf_write_n32(struct obuf *ob, uint32_t v); |
| int obuf_write_n64(struct obuf *ob, uint64_t v); |
| |
| #endif |