"Das U-Boot" Source Tree
at master 146 lines 2.9 kB view raw
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 <malloc.h> 11#include <mapmem.h> 12#include <string.h> 13#endif 14 15#include <abuf.h> 16 17void 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 24#ifndef USE_HOSTCC 25void abuf_map_sysmem(struct abuf *abuf, ulong addr, size_t size) 26{ 27 abuf_set(abuf, map_sysmem(addr, size), size); 28} 29 30ulong abuf_addr(const struct abuf *abuf) 31{ 32 return map_to_sysmem(abuf->data); 33} 34 35#else 36/* copied from lib/string.c for convenience */ 37static 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 50 51bool 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 */ 78 ptr = malloc(new_size); 79 if (!ptr) 80 return false; 81 if (abuf->size) 82 memcpy(ptr, abuf->data, abuf->size); 83 abuf->data = ptr; 84 abuf->size = new_size; 85 abuf->alloced = true; 86 return true; 87 } 88} 89 90bool abuf_realloc_inc(struct abuf *abuf, size_t inc) 91{ 92 return abuf_realloc(abuf, abuf->size + inc); 93} 94 95void *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 116void abuf_init_set(struct abuf *abuf, void *data, size_t size) 117{ 118 abuf_init(abuf); 119 abuf_set(abuf, data, size); 120} 121 122void 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 128void 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 134void abuf_uninit(struct abuf *abuf) 135{ 136 if (abuf->alloced) 137 free(abuf->data); 138 abuf_init(abuf); 139} 140 141void abuf_init(struct abuf *abuf) 142{ 143 abuf->data = NULL; 144 abuf->size = 0; 145 abuf->alloced = false; 146}