Convert CONFIG_SPL_COMMON_INIT_DDR to Kconfig
[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 #include <common.h>
10 #include <abuf.h>
11 #include <malloc.h>
12 #include <mapmem.h>
13 #include <string.h>
14
15 void abuf_set(struct abuf *abuf, void *data, size_t size)
16 {
17         abuf_uninit(abuf);
18         abuf->data = data;
19         abuf->size = size;
20 }
21
22 void abuf_map_sysmem(struct abuf *abuf, ulong addr, size_t size)
23 {
24         abuf_set(abuf, map_sysmem(addr, size), size);
25 }
26
27 bool abuf_realloc(struct abuf *abuf, size_t new_size)
28 {
29         void *ptr;
30
31         if (!new_size) {
32                 /* easy case, just need to uninit, freeing any allocation */
33                 abuf_uninit(abuf);
34                 return true;
35         } else if (abuf->alloced) {
36                 /* currently allocated, so need to reallocate */
37                 ptr = realloc(abuf->data, new_size);
38                 if (!ptr)
39                         return false;
40                 abuf->data = ptr;
41                 abuf->size = new_size;
42                 return true;
43         } else if (new_size <= abuf->size) {
44                 /*
45                  * not currently alloced and new size is no larger. Just update
46                  * it. Data is lost off the end if new_size < abuf->size
47                  */
48                 abuf->size = new_size;
49                 return true;
50         } else {
51                 /* not currently allocated and new size is larger. Alloc and
52                  * copy in data. The new space is not inited.
53                  */
54                 ptr = malloc(new_size);
55                 if (!ptr)
56                         return false;
57                 if (abuf->size)
58                         memcpy(ptr, abuf->data, abuf->size);
59                 abuf->data = ptr;
60                 abuf->size = new_size;
61                 abuf->alloced = true;
62                 return true;
63         }
64 }
65
66 void *abuf_uninit_move(struct abuf *abuf, size_t *sizep)
67 {
68         void *ptr;
69
70         if (sizep)
71                 *sizep = abuf->size;
72         if (!abuf->size)
73                 return NULL;
74         if (abuf->alloced) {
75                 ptr = abuf->data;
76         } else {
77                 ptr = memdup(abuf->data, abuf->size);
78                 if (!ptr)
79                         return NULL;
80         }
81         /* Clear everything out so there is no record of the data */
82         abuf_init(abuf);
83
84         return ptr;
85 }
86
87 void abuf_init_set(struct abuf *abuf, void *data, size_t size)
88 {
89         abuf_init(abuf);
90         abuf_set(abuf, data, size);
91 }
92
93 void abuf_init_move(struct abuf *abuf, void *data, size_t size)
94 {
95         abuf_init_set(abuf, data, size);
96         abuf->alloced = true;
97 }
98
99 void abuf_uninit(struct abuf *abuf)
100 {
101         if (abuf->alloced)
102                 free(abuf->data);
103         abuf_init(abuf);
104 }
105
106 void abuf_init(struct abuf *abuf)
107 {
108         abuf->data = NULL;
109         abuf->size = 0;
110         abuf->alloced = false;
111 }