Loading...
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 | /* SPDX-License-Identifier: GPL-2.0+ */ /* * Handles a buffer that can be allocated and freed * * Copyright 2021 Google LLC * Written by Simon Glass <sjg@chromium.org> */ #ifndef __ABUF_H #define __ABUF_H #ifdef USE_HOSTCC #include <sys/types.h> #else #include <linux/types.h> #endif /** * struct abuf - buffer that can be allocated and freed * * This is useful for a block of data which may be allocated with malloc(), or * not, so that it needs to be freed correctly when finished with. * * For now it has a very simple purpose. * * Using memset() to zero all fields is guaranteed to be equivalent to * abuf_init(). * * @data: Pointer to data * @size: Size of data in bytes * @alloced: true if allocated with malloc(), so must be freed after use */ struct abuf { void *data; size_t size; bool alloced; }; static inline void *abuf_data(const struct abuf *abuf) { return abuf->data; } static inline size_t abuf_size(const struct abuf *abuf) { return abuf->size; } /** * abuf_addr() - Get the address of a buffer's data * * @abuf: Buffer to check * Return: address of buffer */ ulong abuf_addr(const struct abuf *abuf); /** * abuf_set() - set the (unallocated) data in a buffer * * This simply makes the abuf point to the supplied data, which must be live * for the lifetime of the abuf. It is not alloced. * * Any existing data in the abuf is freed and the alloced member is set to * false. * * @abuf: abuf to adjust * @data: New contents of abuf * @size: New size of abuf */ void abuf_set(struct abuf *abuf, void *data, size_t size); /** * abuf_map_sysmem() - calls map_sysmem() to set up an abuf * * This is equivalent to abuf_set(abuf, map_sysmem(addr, size), size) * * Any existing data in the abuf is freed and the alloced member is set to * false. * * @abuf: abuf to adjust * @addr: Address to set the abuf to * @size: New size of abuf */ void abuf_map_sysmem(struct abuf *abuf, ulong addr, size_t size); /** * abuf_realloc() - Change the size of a buffer * * This uses realloc() to change the size of the buffer, with the same semantics * as that function. If the abuf is not currently alloced, then it will alloc * it if the size needs to increase (i.e. set the alloced member to true) * * @abuf: abuf to adjust * @new_size: new size in bytes. * if 0, the abuf is freed * if greater than the current size, the abuf is extended and the new * space is not inited. The alloced member is set to true * if less than the current size, the abuf is contracted and the data at * the end is lost. If @new_size is 0, this sets the alloced member to * false * Return: true if OK, false if out of memory */ bool abuf_realloc(struct abuf *abuf, size_t new_size); /** * abuf_realloc_inc() - Increment abuf size by a given amount * * @abuf: abuf to adjust * @inc: Size incrmement to use (the buffer size will be increased by this much) * Return: true if OK, false if out of memory */ bool abuf_realloc_inc(struct abuf *abuf, size_t inc); /** * abuf_copy() - Make a copy of an abuf * * Creates an allocated copy of @old in @new * * @old: abuf to copy * @new: new abuf to hold the copy (inited by this function) * Return: true if OK, false if out of memory */ bool abuf_copy(const struct abuf *old, struct abuf *new); /** * abuf_printf() - Format a string and place it in an abuf * * @buf: The buffer to place the result into * @fmt: The format string to use * @...: Arguments for the format string * Return: the number of characters writtenwhich would be * generated for the given input, excluding the trailing null, * as per ISO C99. * * The abuf is expanded as necessary to fit the formated string * * See the vsprintf() documentation for format string extensions over C99. * * Returns: number of characters written (excluding trailing nul) on success, * -E2BIG if the size exceeds 4K, -ENOMEM if out of memory, -EFAULT if there is * an internal bug in the vsnprintf() implementation */ int abuf_printf(struct abuf *buf, const char *fmt, ...) __attribute__ ((format (__printf__, 2, 3))); /** * abuf_uninit_move() - Return the allocated contents and uninit the abuf * * This returns the abuf data to the caller, allocating it if necessary, so that * the caller receives data that it can be sure will hang around. The caller is * responsible for freeing the data. * * If the abuf has allocated data, it is returned. If the abuf has data but it * is not allocated, then it is first allocated, then returned. * * If the abuf size is 0, this returns NULL * * The abuf is uninited as part of this, except if the allocation fails, in * which NULL is returned and the abuf remains untouched. * * The abuf must be inited before this can be called. * * @abuf: abuf to uninit * @sizep: if non-NULL, returns the size of the returned data * Return: data contents, allocated with malloc(), or NULL if the data could not * be allocated, or the data size is 0 */ void *abuf_uninit_move(struct abuf *abuf, size_t *sizep); /** * abuf_init_move() - Make abuf take over the management of an allocated region * * After this, @data must not be used. All access must be via the abuf. * * @abuf: abuf to init * @data: Existing allocated buffer to place in the abuf * @size: Size of allocated buffer */ void abuf_init_move(struct abuf *abuf, void *data, size_t size); /** * abuf_init_set() - Set up a new abuf * * Inits a new abuf and sets up its (unallocated) data * * @abuf: abuf to set up * @data: New contents of abuf * @size: New size of abuf */ void abuf_init_set(struct abuf *abuf, void *data, size_t size); /** * abuf_init_const() - Set up a new const abuf * * Inits a new abuf and sets up its (unallocated) data. The only current * difference between this and abuf_init_set() is the 'data' parameter is a * const pointer. At some point a flag could be used to indicate const-ness. * * @abuf: abuf to set up * @data: New contents of abuf * @size: New size of abuf */ void abuf_init_const(struct abuf *abuf, const void *data, size_t size); /** * abuf_init_const_addr() - Set up a new buffer at a given address * * This is similar to abuf_init_const() except that it takes an address instead * of a pointer. Note that the abuf is unallocated. * * @abuf: abuf to set up * @addr: Address to use * @size: Size of buffer */ void abuf_init_const_addr(struct abuf *abuf, ulong addr, size_t size); /** * abuf_init_size() - Set up an allocated abuf * * Init a new abuf and allocate its size. * * @abuf: abuf to set up * @data: New contents of abuf * @size: New size of abuf */ bool abuf_init_size(struct abuf *buf, size_t size); /** * abuf_uninit() - Free any memory used by an abuf * * The buffer must be inited before this can be called. * * @abuf: abuf to uninit */ void abuf_uninit(struct abuf *abuf); /** * abuf_init() - Set up a new abuf * * This initially has no data and alloced is set to false. This is equivalent to * setting all fields to 0, e.g. with memset(), so callers can do that instead * if desired. * * @abuf: abuf to set up */ void abuf_init(struct abuf *abuf); #endif |