env: ti: ti_common.env: Fix get_overlaystring for FIT Image
[platform/kernel/u-boot.git] / lib / abuf.c
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 USE_HOSTCC
10 #include <common.h>
11 #include <malloc.h>
12 #include <mapmem.h>
13 #include <string.h>
14 #endif
15
16 #include <abuf.h>
17
18 void 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
25 #ifndef USE_HOSTCC
26 void abuf_map_sysmem(struct abuf *abuf, ulong addr, size_t size)
27 {
28         abuf_set(abuf, map_sysmem(addr, size), size);
29 }
30 #else
31 /* copied from lib/string.c for convenience */
32 static 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
45
46 bool 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                  */
73                 ptr = malloc(new_size);
74                 if (!ptr)
75                         return false;
76                 if (abuf->size)
77                         memcpy(ptr, abuf->data, abuf->size);
78                 abuf->data = ptr;
79                 abuf->size = new_size;
80                 abuf->alloced = true;
81                 return true;
82         }
83 }
84
85 void *abuf_uninit_move(struct abuf *abuf, size_t *sizep)
86 {
87         void *ptr;
88
89         if (sizep)
90                 *sizep = abuf->size;
91         if (!abuf->size)
92                 return NULL;
93         if (abuf->alloced) {
94                 ptr = abuf->data;
95         } else {
96                 ptr = memdup(abuf->data, abuf->size);
97                 if (!ptr)
98                         return NULL;
99         }
100         /* Clear everything out so there is no record of the data */
101         abuf_init(abuf);
102
103         return ptr;
104 }
105
106 void abuf_init_set(struct abuf *abuf, void *data, size_t size)
107 {
108         abuf_init(abuf);
109         abuf_set(abuf, data, size);
110 }
111
112 void abuf_init_move(struct abuf *abuf, void *data, size_t size)
113 {
114         abuf_init_set(abuf, data, size);
115         abuf->alloced = true;
116 }
117
118 void abuf_uninit(struct abuf *abuf)
119 {
120         if (abuf->alloced)
121                 free(abuf->data);
122         abuf_init(abuf);
123 }
124
125 void abuf_init(struct abuf *abuf)
126 {
127         abuf->data = NULL;
128         abuf->size = 0;
129         abuf->alloced = false;
130 }