abuf.c 2.4 KB

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