fdt_addresses.c 2.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101
  1. // SPDX-License-Identifier: (GPL-2.0-or-later OR BSD-2-Clause)
  2. /*
  3. * libfdt - Flat Device Tree manipulation
  4. * Copyright (C) 2014 David Gibson <david@gibson.dropbear.id.au>
  5. * Copyright (C) 2018 embedded brains GmbH
  6. */
  7. #include "libfdt_env.h"
  8. #include <fdt.h>
  9. #include <libfdt.h>
  10. #include "libfdt_internal.h"
  11. static int fdt_cells(const void *fdt, int nodeoffset, const char *name)
  12. {
  13. const fdt32_t *c;
  14. uint32_t val;
  15. int len;
  16. c = fdt_getprop(fdt, nodeoffset, name, &len);
  17. if (!c)
  18. return len;
  19. if (len != sizeof(*c))
  20. return -FDT_ERR_BADNCELLS;
  21. val = fdt32_to_cpu(*c);
  22. if (val > FDT_MAX_NCELLS)
  23. return -FDT_ERR_BADNCELLS;
  24. return (int)val;
  25. }
  26. int fdt_address_cells(const void *fdt, int nodeoffset)
  27. {
  28. int val;
  29. val = fdt_cells(fdt, nodeoffset, "#address-cells");
  30. if (val == 0)
  31. return -FDT_ERR_BADNCELLS;
  32. if (val == -FDT_ERR_NOTFOUND)
  33. return 2;
  34. return val;
  35. }
  36. int fdt_size_cells(const void *fdt, int nodeoffset)
  37. {
  38. int val;
  39. val = fdt_cells(fdt, nodeoffset, "#size-cells");
  40. if (val == -FDT_ERR_NOTFOUND)
  41. return 1;
  42. return val;
  43. }
  44. /* This function assumes that [address|size]_cells is 1 or 2 */
  45. int fdt_appendprop_addrrange(void *fdt, int parent, int nodeoffset,
  46. const char *name, uint64_t addr, uint64_t size)
  47. {
  48. int addr_cells, size_cells, ret;
  49. uint8_t data[sizeof(fdt64_t) * 2], *prop;
  50. ret = fdt_address_cells(fdt, parent);
  51. if (ret < 0)
  52. return ret;
  53. addr_cells = ret;
  54. ret = fdt_size_cells(fdt, parent);
  55. if (ret < 0)
  56. return ret;
  57. size_cells = ret;
  58. /* check validity of address */
  59. prop = data;
  60. if (addr_cells == 1) {
  61. if ((addr > UINT32_MAX) || (((uint64_t) UINT32_MAX + 1 - addr) < size))
  62. return -FDT_ERR_BADVALUE;
  63. fdt32_st(prop, (uint32_t)addr);
  64. } else if (addr_cells == 2) {
  65. fdt64_st(prop, addr);
  66. } else {
  67. return -FDT_ERR_BADNCELLS;
  68. }
  69. /* check validity of size */
  70. prop += addr_cells * sizeof(fdt32_t);
  71. if (size_cells == 1) {
  72. if (size > UINT32_MAX)
  73. return -FDT_ERR_BADVALUE;
  74. fdt32_st(prop, (uint32_t)size);
  75. } else if (size_cells == 2) {
  76. fdt64_st(prop, size);
  77. } else {
  78. return -FDT_ERR_BADNCELLS;
  79. }
  80. return fdt_appendprop(fdt, nodeoffset, name, data,
  81. (addr_cells + size_cells) * sizeof(fdt32_t));
  82. }