1/* SPDX-License-Identifier: GPL-2.0+ */ 2/* 3 * Handles a buffer that can be allocated and freed 4 * 5 * Copyright 2021 Google LLC 6 * Written by Simon Glass <sjg@chromium.org> 7 */ 8 9#ifndef __ABUF_H 10#define __ABUF_H 11 12#include <linux/types.h> 13 14/** 15 * struct abuf - buffer that can be allocated and freed 16 * 17 * This is useful for a block of data which may be allocated with malloc(), or 18 * not, so that it needs to be freed correctly when finished with. 19 * 20 * For now it has a very simple purpose. 21 * 22 * Using memset() to zero all fields is guaranteed to be equivalent to 23 * abuf_init(). 24 * 25 * @data: Pointer to data 26 * @size: Size of data in bytes 27 * @alloced: true if allocated with malloc(), so must be freed after use 28 */ 29struct abuf { 30 void *data; 31 size_t size; 32 bool alloced; 33}; 34 35static inline void *abuf_data(const struct abuf *abuf) 36{ 37 return abuf->data; 38} 39 40static inline size_t abuf_size(const struct abuf *abuf) 41{ 42 return abuf->size; 43} 44 45/** 46 * abuf_set() - set the (unallocated) data in a buffer 47 * 48 * This simply makes the abuf point to the supplied data, which must be live 49 * for the lifetime of the abuf. It is not alloced. 50 * 51 * Any existing data in the abuf is freed and the alloced member is set to 52 * false. 53 * 54 * @abuf: abuf to adjust 55 * @data: New contents of abuf 56 * @size: New size of abuf 57 */ 58void abuf_set(struct abuf *abuf, void *data, size_t size); 59 60/** 61 * abuf_map_sysmem() - calls map_sysmem() to set up an abuf 62 * 63 * This is equivalent to abuf_set(abuf, map_sysmem(addr, size), size) 64 * 65 * Any existing data in the abuf is freed and the alloced member is set to 66 * false. 67 * 68 * @abuf: abuf to adjust 69 * @addr: Address to set the abuf to 70 * @size: New size of abuf 71 */ 72void abuf_map_sysmem(struct abuf *abuf, ulong addr, size_t size); 73 74/** 75 * abuf_realloc() - Change the size of a buffer 76 * 77 * This uses realloc() to change the size of the buffer, with the same semantics 78 * as that function. If the abuf is not currently alloced, then it will alloc 79 * it if the size needs to increase (i.e. set the alloced member to true) 80 * 81 * @abuf: abuf to adjust 82 * @new_size: new size in bytes. 83 * if 0, the abuf is freed 84 * if greater than the current size, the abuf is extended and the new 85 * space is not inited. The alloced member is set to true 86 * if less than the current size, the abuf is contracted and the data at 87 * the end is lost. If @new_size is 0, this sets the alloced member to 88 * false 89 * @return true if OK, false if out of memory 90 */ 91bool abuf_realloc(struct abuf *abuf, size_t new_size); 92 93/** 94 * abuf_uninit_move() - Return the allocated contents and uninit the abuf 95 * 96 * This returns the abuf data to the caller, allocating it if necessary, so that 97 * the caller receives data that it can be sure will hang around. The caller is 98 * responsible for freeing the data. 99 * 100 * If the abuf has allocated data, it is returned. If the abuf has data but it 101 * is not allocated, then it is first allocated, then returned. 102 * 103 * If the abuf size is 0, this returns NULL 104 * 105 * The abuf is uninited as part of this, except if the allocation fails, in 106 * which NULL is returned and the abuf remains untouched. 107 * 108 * The abuf must be inited before this can be called. 109 * 110 * @abuf: abuf to uninit 111 * @sizep: if non-NULL, returns the size of the returned data 112 * @return data contents, allocated with malloc(), or NULL if the data could not 113 * be allocated, or the data size is 0 114 */ 115void *abuf_uninit_move(struct abuf *abuf, size_t *sizep); 116 117/** 118 * abuf_init_move() - Make abuf take over the management of an allocated region 119 * 120 * After this, @data must not be used. All access must be via the abuf. 121 * 122 * @abuf: abuf to init 123 * @data: Existing allocated buffer to place in the abuf 124 * @size: Size of allocated buffer 125 */ 126void abuf_init_move(struct abuf *abuf, void *data, size_t size); 127 128/** 129 * abuf_init_set() - Set up a new abuf 130 * 131 * Inits a new abuf and sets up its (unallocated) data 132 * 133 * @abuf: abuf to set up 134 * @data: New contents of abuf 135 * @size: New size of abuf 136 */ 137void abuf_init_set(struct abuf *abuf, void *data, size_t size); 138 139/** 140 * abuf_uninit() - Free any memory used by an abuf 141 * 142 * The buffer must be inited before this can be called. 143 * 144 * @abuf: abuf to uninit 145 */ 146void abuf_uninit(struct abuf *abuf); 147 148/** 149 * abuf_init() - Set up a new abuf 150 * 151 * This initially has no data and alloced is set to false. This is equivalent to 152 * setting all fields to 0, e.g. with memset(), so callers can do that instead 153 * if desired. 154 * 155 * @abuf: abuf to set up 156 */ 157void abuf_init(struct abuf *abuf); 158 159#endif 160