raw.c 5.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197
  1. /*
  2. * Copyright (c) 2006-2022, RT-Thread Development Team
  3. *
  4. * SPDX-License-Identifier: Apache-2.0
  5. *
  6. * Change Logs:
  7. * Date Author Notes
  8. * 2022-10-19 GuEe-GUI first version
  9. */
  10. #include <drivers/ofw_raw.h>
  11. int fdt_add_subnode_possible(void *fdt, int parentoffset, const char *name)
  12. {
  13. int nodeoffset;
  14. if ((nodeoffset = fdt_add_subnode(fdt, parentoffset, name)) < 0)
  15. {
  16. fdt_open_into(fdt, fdt, fdt_totalsize(fdt) + FDT_PADDING_SIZE);
  17. nodeoffset = fdt_add_subnode(fdt, parentoffset, name);
  18. }
  19. return nodeoffset;
  20. }
  21. int fdt_add_mem_rsv_possible(void *fdt, size_t addr, size_t size)
  22. {
  23. int err = 0;
  24. if (fdt_add_mem_rsv(fdt, addr, size) < 0)
  25. {
  26. fdt_open_into(fdt, fdt, fdt_totalsize(fdt) + FDT_PADDING_SIZE);
  27. err = fdt_add_mem_rsv(fdt, addr, size);
  28. }
  29. return err;
  30. }
  31. int fdt_setprop_uxx(void *fdt, int nodeoffset, const char *name, uint64_t val, bool is_u64)
  32. {
  33. int err;
  34. if (is_u64)
  35. {
  36. err = fdt_setprop_u64(fdt, nodeoffset, name, val);
  37. }
  38. else
  39. {
  40. err = fdt_setprop_u32(fdt, nodeoffset, name, (uint32_t)val);
  41. }
  42. return err;
  43. }
  44. #define FDT_RAW_GET_VAL_FLAG(std_type, s, sz) \
  45. int fdt_getprop_##std_type##sz(void *fdt, int nodeoffset, \
  46. const char *name, s##int##sz##_t *out_value, int *lenp) \
  47. { \
  48. int err = -FDT_ERR_NOTFOUND; \
  49. if (fdt && nodeoffset >= 0 && name && out_value) \
  50. { \
  51. const fdt##sz##_t *ptr; \
  52. if ((ptr = fdt_getprop(fdt, nodeoffset, name, lenp))) \
  53. { \
  54. *out_value = fdt##sz##_to_cpu(*ptr); \
  55. err = 0; \
  56. } \
  57. } \
  58. return err; \
  59. }
  60. #define FDT_RAW_GET_VAL(size) \
  61. FDT_RAW_GET_VAL_FLAG(u, u, size) \
  62. FDT_RAW_GET_VAL_FLAG(s, , size)
  63. FDT_RAW_GET_VAL(64)
  64. FDT_RAW_GET_VAL(32)
  65. FDT_RAW_GET_VAL(16)
  66. FDT_RAW_GET_VAL(8)
  67. #undef FDT_RAW_GET_VAL
  68. #undef FDT_RAW_GET_VAL_FLAG
  69. int fdt_io_addr_cells(void *fdt, int nodeoffset)
  70. {
  71. int cells = -1;
  72. int parentoffset = fdt_parent_offset(fdt, nodeoffset);
  73. for (; parentoffset >= 0 ; parentoffset = fdt_parent_offset(fdt, parentoffset))
  74. {
  75. const fdt32_t *cells_tmp = fdt_getprop(fdt, parentoffset, "#address-cells", NULL);
  76. if (cells_tmp)
  77. {
  78. cells = fdt32_to_cpu(*cells_tmp);
  79. }
  80. }
  81. if (cells < 0)
  82. {
  83. cells = fdt_address_cells(fdt, nodeoffset);
  84. }
  85. return cells;
  86. }
  87. int fdt_io_size_cells(void *fdt, int nodeoffset)
  88. {
  89. int cells = -1;
  90. int parentoffset = fdt_parent_offset(fdt, nodeoffset);
  91. for (; parentoffset >= 0 ; parentoffset = fdt_parent_offset(fdt, parentoffset))
  92. {
  93. const fdt32_t *cells_tmp = fdt_getprop(fdt, parentoffset, "#size-cells", NULL);
  94. if (cells_tmp)
  95. {
  96. cells = fdt32_to_cpu(*cells_tmp);
  97. }
  98. }
  99. if (cells < 0)
  100. {
  101. cells = fdt_size_cells(fdt, nodeoffset);
  102. }
  103. return cells;
  104. }
  105. int fdt_install_initrd(void *fdt, char *os_name, size_t initrd_addr, size_t initrd_size)
  106. {
  107. int err = -FDT_ERR_NOTFOUND;
  108. int chosen_offset = -1, root_off = fdt_path_offset(fdt, "/");
  109. if (root_off >= 0)
  110. {
  111. chosen_offset = fdt_subnode_offset(fdt, root_off, "chosen");
  112. if (chosen_offset == -FDT_ERR_NOTFOUND)
  113. {
  114. chosen_offset = fdt_add_subnode_possible(fdt, root_off, "chosen");
  115. }
  116. }
  117. if (chosen_offset >= 0)
  118. {
  119. uint64_t addr, size;
  120. err = 0;
  121. /* Update the entry */
  122. for (int i = fdt_num_mem_rsv(fdt) - 1; i >= 0; --i)
  123. {
  124. fdt_get_mem_rsv(fdt, i, &addr, &size);
  125. if (addr == initrd_addr)
  126. {
  127. fdt_del_mem_rsv(fdt, i);
  128. break;
  129. }
  130. }
  131. /* Add the memory */
  132. if (fdt_add_mem_rsv(fdt, initrd_addr, initrd_size) < 0)
  133. {
  134. /* Move the memory */
  135. fdt_open_into(fdt, fdt, fdt_totalsize(fdt) + FDT_PADDING_SIZE);
  136. if (fdt_add_mem_rsv(fdt, initrd_addr, initrd_size) < 0)
  137. {
  138. err = -FDT_ERR_NOSPACE;
  139. }
  140. }
  141. if (!err)
  142. {
  143. size_t name_len;
  144. char initrd_name[64];
  145. bool is_u64 = (fdt_io_addr_cells(fdt, root_off) == 2);
  146. if (!os_name)
  147. {
  148. os_name = "rt-thread";
  149. }
  150. name_len = strlen(initrd_name);
  151. strncpy(&initrd_name[name_len], ",initrd-start", sizeof(initrd_name) - name_len);
  152. fdt_setprop_uxx(fdt, chosen_offset, initrd_name, initrd_addr, is_u64);
  153. strncpy(&initrd_name[name_len], ",initrd-end", sizeof(initrd_name) - name_len);
  154. fdt_setprop_uxx(fdt, chosen_offset, initrd_name, initrd_addr + initrd_size, is_u64);
  155. }
  156. }
  157. return err;
  158. }