raw.c 5.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199
  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. break;
  80. }
  81. }
  82. if (cells < 0)
  83. {
  84. cells = fdt_address_cells(fdt, nodeoffset);
  85. }
  86. return cells;
  87. }
  88. int fdt_io_size_cells(void *fdt, int nodeoffset)
  89. {
  90. int cells = -1;
  91. int parentoffset = fdt_parent_offset(fdt, nodeoffset);
  92. for (; parentoffset >= 0 ; parentoffset = fdt_parent_offset(fdt, parentoffset))
  93. {
  94. const fdt32_t *cells_tmp = fdt_getprop(fdt, parentoffset, "#size-cells", NULL);
  95. if (cells_tmp)
  96. {
  97. cells = fdt32_to_cpu(*cells_tmp);
  98. break;
  99. }
  100. }
  101. if (cells < 0)
  102. {
  103. cells = fdt_size_cells(fdt, nodeoffset);
  104. }
  105. return cells;
  106. }
  107. int fdt_install_initrd(void *fdt, char *os_name, size_t initrd_addr, size_t initrd_size)
  108. {
  109. int err = -FDT_ERR_NOTFOUND;
  110. int chosen_offset = -1, root_off = fdt_path_offset(fdt, "/");
  111. if (root_off >= 0)
  112. {
  113. chosen_offset = fdt_subnode_offset(fdt, root_off, "chosen");
  114. if (chosen_offset == -FDT_ERR_NOTFOUND)
  115. {
  116. chosen_offset = fdt_add_subnode_possible(fdt, root_off, "chosen");
  117. }
  118. }
  119. if (chosen_offset >= 0)
  120. {
  121. uint64_t addr, size;
  122. err = 0;
  123. /* Update the entry */
  124. for (int i = fdt_num_mem_rsv(fdt) - 1; i >= 0; --i)
  125. {
  126. fdt_get_mem_rsv(fdt, i, &addr, &size);
  127. if (addr == initrd_addr)
  128. {
  129. fdt_del_mem_rsv(fdt, i);
  130. break;
  131. }
  132. }
  133. /* Add the memory */
  134. if (fdt_add_mem_rsv(fdt, initrd_addr, initrd_size) < 0)
  135. {
  136. /* Move the memory */
  137. fdt_open_into(fdt, fdt, fdt_totalsize(fdt) + FDT_PADDING_SIZE);
  138. if (fdt_add_mem_rsv(fdt, initrd_addr, initrd_size) < 0)
  139. {
  140. err = -FDT_ERR_NOSPACE;
  141. }
  142. }
  143. if (!err)
  144. {
  145. size_t name_len;
  146. char initrd_name[64];
  147. bool is_u64 = (fdt_io_addr_cells(fdt, root_off) == 2);
  148. if (!os_name)
  149. {
  150. os_name = "rt-thread";
  151. }
  152. name_len = strlen(initrd_name);
  153. strncpy(&initrd_name[name_len], ",initrd-start", sizeof(initrd_name) - name_len);
  154. fdt_setprop_uxx(fdt, chosen_offset, initrd_name, initrd_addr, is_u64);
  155. strncpy(&initrd_name[name_len], ",initrd-end", sizeof(initrd_name) - name_len);
  156. fdt_setprop_uxx(fdt, chosen_offset, initrd_name, initrd_addr + initrd_size, is_u64);
  157. }
  158. }
  159. return err;
  160. }