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