]>
Commit | Line | Data |
---|---|---|
67bc59df SG |
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 <[email protected]> | |
7 | */ | |
8 | ||
90ad4e28 | 9 | #ifndef USE_HOSTCC |
67bc59df SG |
10 | #include <malloc.h> |
11 | #include <mapmem.h> | |
12 | #include <string.h> | |
90ad4e28 SG |
13 | #endif |
14 | ||
15 | #include <abuf.h> | |
67bc59df SG |
16 | |
17 | void 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 | ||
90ad4e28 | 24 | #ifndef USE_HOSTCC |
67bc59df SG |
25 | void abuf_map_sysmem(struct abuf *abuf, ulong addr, size_t size) |
26 | { | |
27 | abuf_set(abuf, map_sysmem(addr, size), size); | |
28 | } | |
c487381d SG |
29 | |
30 | ulong abuf_addr(const struct abuf *abuf) | |
31 | { | |
32 | return map_to_sysmem(abuf->data); | |
33 | } | |
34 | ||
90ad4e28 SG |
35 | #else |
36 | /* copied from lib/string.c for convenience */ | |
37 | static char *memdup(const void *src, size_t len) | |
38 | { | |
39 | char *p; | |
40 | ||
41 | p = malloc(len); | |
42 | if (!p) | |
43 | return NULL; | |
44 | ||
45 | memcpy(p, src, len); | |
46 | ||
47 | return p; | |
48 | } | |
49 | #endif | |
67bc59df SG |
50 | |
51 | bool abuf_realloc(struct abuf *abuf, size_t new_size) | |
52 | { | |
53 | void *ptr; | |
54 | ||
55 | if (!new_size) { | |
56 | /* easy case, just need to uninit, freeing any allocation */ | |
57 | abuf_uninit(abuf); | |
58 | return true; | |
59 | } else if (abuf->alloced) { | |
60 | /* currently allocated, so need to reallocate */ | |
61 | ptr = realloc(abuf->data, new_size); | |
62 | if (!ptr) | |
63 | return false; | |
64 | abuf->data = ptr; | |
65 | abuf->size = new_size; | |
66 | return true; | |
67 | } else if (new_size <= abuf->size) { | |
68 | /* | |
69 | * not currently alloced and new size is no larger. Just update | |
70 | * it. Data is lost off the end if new_size < abuf->size | |
71 | */ | |
72 | abuf->size = new_size; | |
73 | return true; | |
74 | } else { | |
75 | /* not currently allocated and new size is larger. Alloc and | |
76 | * copy in data. The new space is not inited. | |
77 | */ | |
99aca9ef | 78 | ptr = malloc(new_size); |
67bc59df SG |
79 | if (!ptr) |
80 | return false; | |
99aca9ef SG |
81 | if (abuf->size) |
82 | memcpy(ptr, abuf->data, abuf->size); | |
67bc59df SG |
83 | abuf->data = ptr; |
84 | abuf->size = new_size; | |
85 | abuf->alloced = true; | |
86 | return true; | |
87 | } | |
88 | } | |
89 | ||
34ecba1f SG |
90 | bool abuf_realloc_inc(struct abuf *abuf, size_t inc) |
91 | { | |
92 | return abuf_realloc(abuf, abuf->size + inc); | |
93 | } | |
94 | ||
67bc59df SG |
95 | void *abuf_uninit_move(struct abuf *abuf, size_t *sizep) |
96 | { | |
97 | void *ptr; | |
98 | ||
99 | if (sizep) | |
100 | *sizep = abuf->size; | |
101 | if (!abuf->size) | |
102 | return NULL; | |
103 | if (abuf->alloced) { | |
104 | ptr = abuf->data; | |
105 | } else { | |
106 | ptr = memdup(abuf->data, abuf->size); | |
107 | if (!ptr) | |
108 | return NULL; | |
109 | } | |
110 | /* Clear everything out so there is no record of the data */ | |
111 | abuf_init(abuf); | |
112 | ||
113 | return ptr; | |
114 | } | |
115 | ||
116 | void abuf_init_set(struct abuf *abuf, void *data, size_t size) | |
117 | { | |
118 | abuf_init(abuf); | |
119 | abuf_set(abuf, data, size); | |
120 | } | |
121 | ||
7ba7c1dd SG |
122 | void abuf_init_const(struct abuf *abuf, const void *data, size_t size) |
123 | { | |
124 | /* for now there is no flag indicating that the abuf data is constant */ | |
125 | abuf_init_set(abuf, (void *)data, size); | |
126 | } | |
127 | ||
67bc59df SG |
128 | void abuf_init_move(struct abuf *abuf, void *data, size_t size) |
129 | { | |
130 | abuf_init_set(abuf, data, size); | |
131 | abuf->alloced = true; | |
132 | } | |
133 | ||
134 | void abuf_uninit(struct abuf *abuf) | |
135 | { | |
136 | if (abuf->alloced) | |
137 | free(abuf->data); | |
138 | abuf_init(abuf); | |
139 | } | |
140 | ||
141 | void abuf_init(struct abuf *abuf) | |
142 | { | |
143 | abuf->data = NULL; | |
144 | abuf->size = 0; | |
145 | abuf->alloced = false; | |
146 | } |