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