blob: 4b17e0b8c0dfe949f4edf7fddb2a0db6f915c025 [file] [log] [blame]
Simon Glass67bc59d2021-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
9#include <common.h>
10#include <abuf.h>
11#include <malloc.h>
12#include <mapmem.h>
13#include <string.h>
14
15void 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
22void abuf_map_sysmem(struct abuf *abuf, ulong addr, size_t size)
23{
24 abuf_set(abuf, map_sysmem(addr, size), size);
25}
26
27bool 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 = memdup(abuf->data, new_size);
55 if (!ptr)
56 return false;
57 abuf->data = ptr;
58 abuf->size = new_size;
59 abuf->alloced = true;
60 return true;
61 }
62}
63
64void *abuf_uninit_move(struct abuf *abuf, size_t *sizep)
65{
66 void *ptr;
67
68 if (sizep)
69 *sizep = abuf->size;
70 if (!abuf->size)
71 return NULL;
72 if (abuf->alloced) {
73 ptr = abuf->data;
74 } else {
75 ptr = memdup(abuf->data, abuf->size);
76 if (!ptr)
77 return NULL;
78 }
79 /* Clear everything out so there is no record of the data */
80 abuf_init(abuf);
81
82 return ptr;
83}
84
85void abuf_init_set(struct abuf *abuf, void *data, size_t size)
86{
87 abuf_init(abuf);
88 abuf_set(abuf, data, size);
89}
90
91void abuf_init_move(struct abuf *abuf, void *data, size_t size)
92{
93 abuf_init_set(abuf, data, size);
94 abuf->alloced = true;
95}
96
97void abuf_uninit(struct abuf *abuf)
98{
99 if (abuf->alloced)
100 free(abuf->data);
101 abuf_init(abuf);
102}
103
104void abuf_init(struct abuf *abuf)
105{
106 abuf->data = NULL;
107 abuf->size = 0;
108 abuf->alloced = false;
109}