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_realloc_inc() - Increment abuf size by a given amount 95 * 96 * @abuf: abuf to adjust 97 * @inc: Size incrmement to use (the buffer size will be increased by this much) 98 * Return: true if OK, false if out of memory 99 */ 100bool abuf_realloc_inc(struct abuf *abuf, size_t inc); 101 102/** 103 * abuf_uninit_move() - Return the allocated contents and uninit the abuf 104 * 105 * This returns the abuf data to the caller, allocating it if necessary, so that 106 * the caller receives data that it can be sure will hang around. The caller is 107 * responsible for freeing the data. 108 * 109 * If the abuf has allocated data, it is returned. If the abuf has data but it 110 * is not allocated, then it is first allocated, then returned. 111 * 112 * If the abuf size is 0, this returns NULL 113 * 114 * The abuf is uninited as part of this, except if the allocation fails, in 115 * which NULL is returned and the abuf remains untouched. 116 * 117 * The abuf must be inited before this can be called. 118 * 119 * @abuf: abuf to uninit 120 * @sizep: if non-NULL, returns the size of the returned data 121 * Return: data contents, allocated with malloc(), or NULL if the data could not 122 * be allocated, or the data size is 0 123 */ 124void *abuf_uninit_move(struct abuf *abuf, size_t *sizep); 125 126/** 127 * abuf_init_move() - Make abuf take over the management of an allocated region 128 * 129 * After this, @data must not be used. All access must be via the abuf. 130 * 131 * @abuf: abuf to init 132 * @data: Existing allocated buffer to place in the abuf 133 * @size: Size of allocated buffer 134 */ 135void abuf_init_move(struct abuf *abuf, void *data, size_t size); 136 137/** 138 * abuf_init_set() - Set up a new abuf 139 * 140 * Inits a new abuf and sets up its (unallocated) data 141 * 142 * @abuf: abuf to set up 143 * @data: New contents of abuf 144 * @size: New size of abuf 145 */ 146void abuf_init_set(struct abuf *abuf, void *data, size_t size); 147 148/** 149 * abuf_uninit() - Free any memory used by an abuf 150 * 151 * The buffer must be inited before this can be called. 152 * 153 * @abuf: abuf to uninit 154 */ 155void abuf_uninit(struct abuf *abuf); 156 157/** 158 * abuf_init() - Set up a new abuf 159 * 160 * This initially has no data and alloced is set to false. This is equivalent to 161 * setting all fields to 0, e.g. with memset(), so callers can do that instead 162 * if desired. 163 * 164 * @abuf: abuf to set up 165 */ 166void abuf_init(struct abuf *abuf); 167 168#endif 169