abuf.c 2.2 KB

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