blob: 1635d58682c4d7a404f54ca99f2f55076e095888 [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
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 */
Simon Glass00a05e22022-02-28 12:08:22 -070054 ptr = malloc(new_size);
Simon Glass143fa862021-09-25 07:03:07 -060055 if (!ptr)
56 return false;
Simon Glass00a05e22022-02-28 12:08:22 -070057 if (abuf->size)
58 memcpy(ptr, abuf->data, abuf->size);
Simon Glass143fa862021-09-25 07:03:07 -060059 abuf->data = ptr;
60 abuf->size = new_size;
61 abuf->alloced = true;
62 return true;
63 }
64}
65
66void *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
87void abuf_init_set(struct abuf *abuf, void *data, size_t size)
88{
89 abuf_init(abuf);
90 abuf_set(abuf, data, size);
91}
92
93void 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
99void abuf_uninit(struct abuf *abuf)
100{
101 if (abuf->alloced)
102 free(abuf->data);
103 abuf_init(abuf);
104}
105
106void abuf_init(struct abuf *abuf)
107{
108 abuf->data = NULL;
109 abuf->size = 0;
110 abuf->alloced = false;
111}