blob: ce2cff53dc933bf18e4c87daf8abfeca441abc15 [file] [log] [blame]
Simon Glass143fa862021-09-25 07:03:07 -06001// 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
Simon Glass3c356312023-01-15 14:15:45 -07009#ifndef USE_HOSTCC
Simon Glass143fa862021-09-25 07:03:07 -060010#include <common.h>
Simon Glass143fa862021-09-25 07:03:07 -060011#include <malloc.h>
12#include <mapmem.h>
13#include <string.h>
Simon Glass3c356312023-01-15 14:15:45 -070014#endif
15
16#include <abuf.h>
Simon Glass143fa862021-09-25 07:03:07 -060017
18void abuf_set(struct abuf *abuf, void *data, size_t size)
19{
20 abuf_uninit(abuf);
21 abuf->data = data;
22 abuf->size = size;
23}
24
Simon Glass3c356312023-01-15 14:15:45 -070025#ifndef USE_HOSTCC
Simon Glass143fa862021-09-25 07:03:07 -060026void abuf_map_sysmem(struct abuf *abuf, ulong addr, size_t size)
27{
28 abuf_set(abuf, map_sysmem(addr, size), size);
29}
Simon Glass3c356312023-01-15 14:15:45 -070030#else
31/* copied from lib/string.c for convenience */
32static char *memdup(const void *src, size_t len)
33{
34 char *p;
35
36 p = malloc(len);
37 if (!p)
38 return NULL;
39
40 memcpy(p, src, len);
41
42 return p;
43}
44#endif
Simon Glass143fa862021-09-25 07:03:07 -060045
46bool abuf_realloc(struct abuf *abuf, size_t new_size)
47{
48 void *ptr;
49
50 if (!new_size) {
51 /* easy case, just need to uninit, freeing any allocation */
52 abuf_uninit(abuf);
53 return true;
54 } else if (abuf->alloced) {
55 /* currently allocated, so need to reallocate */
56 ptr = realloc(abuf->data, new_size);
57 if (!ptr)
58 return false;
59 abuf->data = ptr;
60 abuf->size = new_size;
61 return true;
62 } else if (new_size <= abuf->size) {
63 /*
64 * not currently alloced and new size is no larger. Just update
65 * it. Data is lost off the end if new_size < abuf->size
66 */
67 abuf->size = new_size;
68 return true;
69 } else {
70 /* not currently allocated and new size is larger. Alloc and
71 * copy in data. The new space is not inited.
72 */
Simon Glass00a05e22022-02-28 12:08:22 -070073 ptr = malloc(new_size);
Simon Glass143fa862021-09-25 07:03:07 -060074 if (!ptr)
75 return false;
Simon Glass00a05e22022-02-28 12:08:22 -070076 if (abuf->size)
77 memcpy(ptr, abuf->data, abuf->size);
Simon Glass143fa862021-09-25 07:03:07 -060078 abuf->data = ptr;
79 abuf->size = new_size;
80 abuf->alloced = true;
81 return true;
82 }
83}
84
Simon Glass733c2622023-08-14 16:40:22 -060085bool abuf_realloc_inc(struct abuf *abuf, size_t inc)
86{
87 return abuf_realloc(abuf, abuf->size + inc);
88}
89
Simon Glass143fa862021-09-25 07:03:07 -060090void *abuf_uninit_move(struct abuf *abuf, size_t *sizep)
91{
92 void *ptr;
93
94 if (sizep)
95 *sizep = abuf->size;
96 if (!abuf->size)
97 return NULL;
98 if (abuf->alloced) {
99 ptr = abuf->data;
100 } else {
101 ptr = memdup(abuf->data, abuf->size);
102 if (!ptr)
103 return NULL;
104 }
105 /* Clear everything out so there is no record of the data */
106 abuf_init(abuf);
107
108 return ptr;
109}
110
111void abuf_init_set(struct abuf *abuf, void *data, size_t size)
112{
113 abuf_init(abuf);
114 abuf_set(abuf, data, size);
115}
116
117void abuf_init_move(struct abuf *abuf, void *data, size_t size)
118{
119 abuf_init_set(abuf, data, size);
120 abuf->alloced = true;
121}
122
123void abuf_uninit(struct abuf *abuf)
124{
125 if (abuf->alloced)
126 free(abuf->data);
127 abuf_init(abuf);
128}
129
130void abuf_init(struct abuf *abuf)
131{
132 abuf->data = NULL;
133 abuf->size = 0;
134 abuf->alloced = false;
135}