dtb_get.c 21 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823
  1. /*
  2. * Copyright (c) 2006-2023, RT-Thread Development Team
  3. *
  4. * SPDX-License-Identifier: Apache-2.0
  5. */
  6. #include "libfdt.h"
  7. #include "dtb_node.h"
  8. static struct
  9. {
  10. const char *ptr;
  11. const char *end;
  12. char *cur;
  13. } paths_buf = {NULL, NULL};
  14. static void *current_fdt;
  15. int fdt_exec_status = FDT_RET_GET_OK;
  16. int dtb_node_get_exec_status()
  17. {
  18. return fdt_exec_status;
  19. }
  20. static int _dtb_node_get_dtb_properties_list(struct dtb_property *dtb_property, off_t node_off)
  21. {
  22. /* caller alrealy checked current_fdt */
  23. off_t property_off = fdt_first_property_offset(current_fdt, node_off);
  24. struct fdt_property *fdt_property;
  25. if (property_off < 0)
  26. {
  27. return FDT_RET_GET_EMPTY;
  28. }
  29. for (;;)
  30. {
  31. fdt_property = (struct fdt_property *)fdt_get_property_by_offset(current_fdt, property_off, &dtb_property->size);
  32. if (fdt_property != NULL)
  33. {
  34. dtb_property->name = fdt_string(current_fdt, fdt32_to_cpu(fdt_property->nameoff));
  35. dtb_property->value = fdt_property->data;
  36. dtb_property->size = fdt32_to_cpu(fdt_property->len);
  37. }
  38. property_off = fdt_next_property_offset(current_fdt, property_off);
  39. if (property_off >= 0)
  40. {
  41. dtb_property->next = (struct dtb_property *)malloc(sizeof(struct dtb_property));
  42. if (dtb_property->next == NULL)
  43. {
  44. return FDT_RET_NO_MEMORY;
  45. }
  46. dtb_property = dtb_property->next;
  47. }
  48. else
  49. {
  50. dtb_property->next = NULL;
  51. break;
  52. }
  53. }
  54. return FDT_RET_GET_OK;
  55. }
  56. static int _dtb_node_get_dtb_nodes_list(struct dtb_node *dtb_node_head, struct dtb_node *dtb_node, const char *pathname)
  57. {
  58. off_t root_off;
  59. off_t node_off;
  60. int pathname_sz;
  61. int node_name_sz;
  62. /* caller alrealy checked current_fdt */
  63. if ((root_off = fdt_path_offset(current_fdt, pathname)) >= 0)
  64. {
  65. pathname_sz = strlen(pathname);
  66. node_off = fdt_first_subnode(current_fdt, root_off);
  67. if (node_off < 0)
  68. {
  69. return FDT_RET_GET_EMPTY;
  70. }
  71. for (;;)
  72. {
  73. dtb_node->parent = dtb_node_head;
  74. dtb_node->sibling = NULL;
  75. dtb_node->name = fdt_get_name(current_fdt, node_off, &node_name_sz);
  76. /* parent_path + name + '/' + '\0' */
  77. if (paths_buf.cur + pathname_sz + node_name_sz + 2 < paths_buf.end)
  78. {
  79. dtb_node->path = (const char *)paths_buf.cur;
  80. strncpy(paths_buf.cur, pathname, pathname_sz);
  81. paths_buf.cur += pathname_sz;
  82. strncpy(paths_buf.cur, (char *)dtb_node->name, node_name_sz);
  83. paths_buf.cur += node_name_sz;
  84. *paths_buf.cur++ = '/';
  85. *paths_buf.cur++ = '\0';
  86. dtb_node->level = dtb_node_head->level + 1;
  87. }
  88. else
  89. {
  90. dtb_node->path = NULL;
  91. rt_kprintf("\033[31m\rERROR: `FDT_DTB_ALL_NODES_PATH_SIZE' = %d bytes is configured too low.\033[0m\n", FDT_DTB_ALL_NODES_PATH_SIZE);
  92. return FDT_RET_NO_MEMORY;
  93. }
  94. dtb_node->handle = fdt_get_phandle(current_fdt, node_off);
  95. dtb_node->properties = (struct dtb_property *)malloc(sizeof(struct dtb_property));
  96. dtb_node->child = (struct dtb_node *)malloc(sizeof(struct dtb_node));
  97. if (dtb_node->properties == NULL || dtb_node->child == NULL)
  98. {
  99. return FDT_RET_NO_MEMORY;
  100. }
  101. fdt_exec_status = _dtb_node_get_dtb_properties_list(dtb_node->properties, node_off);
  102. if (fdt_exec_status == FDT_RET_GET_EMPTY)
  103. {
  104. free(dtb_node->properties);
  105. dtb_node->properties = NULL;
  106. }
  107. else if (fdt_exec_status != FDT_RET_GET_OK)
  108. {
  109. return fdt_exec_status;
  110. }
  111. fdt_exec_status = _dtb_node_get_dtb_nodes_list(dtb_node, dtb_node->child, dtb_node->path);
  112. if (fdt_exec_status == FDT_RET_GET_EMPTY)
  113. {
  114. free(dtb_node->child);
  115. dtb_node->child = NULL;
  116. }
  117. else if (fdt_exec_status != FDT_RET_GET_OK)
  118. {
  119. return fdt_exec_status;
  120. }
  121. node_off = fdt_next_subnode(current_fdt, node_off);
  122. if (node_off >= 0)
  123. {
  124. dtb_node->sibling = (struct dtb_node *)malloc(sizeof(struct dtb_node));
  125. if (dtb_node->sibling == NULL)
  126. {
  127. return FDT_RET_NO_MEMORY;
  128. }
  129. dtb_node = dtb_node->sibling;
  130. dtb_node->level--;
  131. }
  132. else
  133. {
  134. break;
  135. }
  136. }
  137. }
  138. return FDT_RET_GET_OK;
  139. }
  140. struct dtb_node *dtb_node_get_dtb_list(void *fdt)
  141. {
  142. int root_off;
  143. struct dtb_node *dtb_node_head = NULL;
  144. if (fdt == NULL)
  145. {
  146. fdt_exec_status = FDT_RET_NO_LOADED;
  147. goto fail;
  148. }
  149. current_fdt = fdt;
  150. if ((dtb_node_head = (struct dtb_node *)malloc(sizeof(struct dtb_node))) == NULL)
  151. {
  152. fdt_exec_status = FDT_RET_NO_MEMORY;
  153. goto fail;
  154. }
  155. if (paths_buf.ptr == NULL)
  156. {
  157. paths_buf.ptr = (char *)malloc(FDT_DTB_ALL_NODES_PATH_SIZE);
  158. if (paths_buf.ptr == NULL)
  159. {
  160. fdt_exec_status = FDT_RET_NO_MEMORY;
  161. goto fail;
  162. }
  163. paths_buf.cur = (char *)paths_buf.ptr;
  164. paths_buf.end = (char *)(paths_buf.ptr + FDT_DTB_ALL_NODES_PATH_SIZE);
  165. }
  166. root_off = fdt_path_offset(fdt, "/");
  167. if ((dtb_node_head->header = (struct dtb_header *)malloc(sizeof(struct dtb_header))) == NULL)
  168. {
  169. fdt_exec_status = FDT_RET_NO_MEMORY;
  170. goto fail;
  171. }
  172. else
  173. {
  174. ((struct dtb_header *)dtb_node_head->header)->root = '/';
  175. ((struct dtb_header *)dtb_node_head->header)->zero = '\0';
  176. ((struct dtb_header *)dtb_node_head->header)->memreserve_sz = fdt_num_mem_rsv(fdt);
  177. if (dtb_node_head->header->memreserve_sz > 0)
  178. {
  179. int i;
  180. int memreserve_sz = dtb_node_head->header->memreserve_sz;
  181. uint32_t off_mem_rsvmap = fdt_off_mem_rsvmap(fdt);
  182. struct fdt_reserve_entry *rsvmap = (struct fdt_reserve_entry *)((char *)fdt + off_mem_rsvmap);
  183. ((struct dtb_header *)dtb_node_head->header)->memreserve = (struct dtb_memreserve *)malloc(sizeof(struct dtb_memreserve) * memreserve_sz);
  184. if (dtb_node_head->header->memreserve == NULL)
  185. {
  186. fdt_exec_status = FDT_RET_NO_MEMORY;
  187. goto fail;
  188. }
  189. for (i = 0; i < memreserve_sz; ++i)
  190. {
  191. ((struct dtb_header *)dtb_node_head->header)->memreserve[i].address = fdt64_to_cpu(rsvmap[i].address);
  192. ((struct dtb_header *)dtb_node_head->header)->memreserve[i].size = fdt64_to_cpu(rsvmap[i].size);
  193. }
  194. }
  195. else
  196. {
  197. ((struct dtb_header *)dtb_node_head->header)->memreserve = NULL;
  198. }
  199. }
  200. dtb_node_head->path = paths_buf.ptr;
  201. *paths_buf.cur++ = '/';
  202. *paths_buf.cur++ = '\0';
  203. dtb_node_head->parent = NULL;
  204. dtb_node_head->sibling = NULL;
  205. dtb_node_head->handle = fdt_get_phandle(fdt, root_off);
  206. dtb_node_head->properties = (struct dtb_property *)malloc(sizeof(struct dtb_property));
  207. dtb_node_head->child = (struct dtb_node *)malloc(sizeof(struct dtb_node));
  208. dtb_node_head->level = 0;
  209. if (dtb_node_head->properties == NULL || dtb_node_head->child == NULL)
  210. {
  211. fdt_exec_status = FDT_RET_NO_MEMORY;
  212. goto fail;
  213. }
  214. if ((fdt_exec_status = _dtb_node_get_dtb_properties_list(dtb_node_head->properties, root_off)) != FDT_RET_GET_OK)
  215. {
  216. goto fail;
  217. }
  218. if ((fdt_exec_status = _dtb_node_get_dtb_nodes_list(dtb_node_head, dtb_node_head->child, dtb_node_head->path)) != FDT_RET_GET_OK)
  219. {
  220. goto fail;
  221. }
  222. /* paths_buf.ptr addr save in the dtb_node_head's path */
  223. paths_buf.ptr = NULL;
  224. paths_buf.cur = NULL;
  225. return dtb_node_head;
  226. fail:
  227. if (dtb_node_head != NULL)
  228. {
  229. dtb_node_free_dtb_list(dtb_node_head);
  230. }
  231. return NULL;
  232. }
  233. static void _dtb_node_free_dtb_node(struct dtb_node *dtb_node)
  234. {
  235. struct dtb_node *dtb_node_last;
  236. struct dtb_property *dtb_property;
  237. struct dtb_property *dtb_property_last;
  238. while (dtb_node != NULL)
  239. {
  240. dtb_property = dtb_node->properties;
  241. while (dtb_property != NULL)
  242. {
  243. dtb_property_last = dtb_property;
  244. dtb_property = dtb_property->next;
  245. free(dtb_property_last);
  246. }
  247. _dtb_node_free_dtb_node(dtb_node->child);
  248. dtb_node_last = dtb_node;
  249. dtb_node = dtb_node->sibling;
  250. free(dtb_node_last);
  251. }
  252. }
  253. void dtb_node_free_dtb_list(struct dtb_node *dtb_node_head)
  254. {
  255. if (dtb_node_head == NULL)
  256. {
  257. return;
  258. }
  259. /* only root node can free all path buffer */
  260. if (dtb_node_head->parent == NULL || (dtb_node_head->path != NULL && !strcmp(dtb_node_head->path, "/")))
  261. {
  262. if (dtb_node_head->path != NULL)
  263. {
  264. free((void *)dtb_node_head->path);
  265. }
  266. if (dtb_node_head->header != NULL)
  267. {
  268. if (dtb_node_head->header->memreserve != NULL)
  269. {
  270. free((void *)dtb_node_head->header->memreserve);
  271. }
  272. free((void *)dtb_node_head->header);
  273. }
  274. }
  275. _dtb_node_free_dtb_node(dtb_node_head);
  276. }
  277. static void _dtb_node_printf_depth(int depth)
  278. {
  279. int i = depth;
  280. while (i --> 0)
  281. {
  282. rt_kputs("\t");
  283. }
  284. }
  285. rt_bool_t _dtb_node_test_string_list(const void *value, int size)
  286. {
  287. const char *str = value;
  288. const char *str_start, *str_end;
  289. if (size == 0)
  290. {
  291. return RT_FALSE;
  292. }
  293. /* string end with '\0' */
  294. if (str[size - 1] != '\0')
  295. {
  296. return RT_FALSE;
  297. }
  298. /* get string list end */
  299. str_end = str + size;
  300. while (str < str_end)
  301. {
  302. str_start = str;
  303. /* before string list end, not '\0' and a printable characters */
  304. while (str < str_end && *str && ((unsigned char)*str >= ' ' && (unsigned char)*str <= '~'))
  305. {
  306. ++str;
  307. }
  308. /* not zero, or not increased */
  309. if (*str != '\0' || str == str_start)
  310. {
  311. return RT_FALSE;
  312. }
  313. /* next string */
  314. ++str;
  315. }
  316. return RT_TRUE;
  317. }
  318. static void _dtb_node_printf_dtb_node_info(struct dtb_node *dtb_node)
  319. {
  320. static int depth = 0;
  321. struct dtb_property *dtb_property;
  322. while (dtb_node != NULL)
  323. {
  324. rt_kputs("\n");
  325. _dtb_node_printf_depth(depth);
  326. rt_kputs(dtb_node->name);
  327. rt_kputs(" {\n");
  328. ++depth;
  329. dtb_property = dtb_node->properties;
  330. while (dtb_property != NULL)
  331. {
  332. _dtb_node_printf_depth(depth);
  333. rt_kputs(dtb_property->name);
  334. if (dtb_property->size > 0)
  335. {
  336. int size = dtb_property->size;
  337. char *value = dtb_property->value;
  338. rt_kputs(" = ");
  339. if (_dtb_node_test_string_list(value, size) == RT_TRUE)
  340. {
  341. /* print string list */
  342. char *str = value;
  343. do
  344. {
  345. rt_kprintf("\"%s\"", str);
  346. str += strlen(str) + 1;
  347. rt_kputs(", ");
  348. } while (str < value + size);
  349. rt_kputs("\b\b");
  350. }
  351. else if ((size % 4) == 0)
  352. {
  353. /* print addr and size cell */
  354. int i;
  355. fdt32_t *cell = (fdt32_t *)value;
  356. rt_kputs("<");
  357. for (i = 0, size /= 4; i < size; ++i)
  358. {
  359. rt_kprintf("0x%x ", fdt32_to_cpu(cell[i]));
  360. }
  361. rt_kputs("\b>");
  362. }
  363. else
  364. {
  365. /* print bytes array */
  366. int i;
  367. uint8_t *byte = (uint8_t *)value;
  368. rt_kputs("[");
  369. for (i = 0; i < size; ++i)
  370. {
  371. rt_kprintf("%02x ", *byte++);
  372. }
  373. rt_kputs("\b]");
  374. }
  375. }
  376. rt_kputs(";\n");
  377. dtb_property = dtb_property->next;
  378. }
  379. _dtb_node_printf_dtb_node_info(dtb_node->child);
  380. dtb_node = dtb_node->sibling;
  381. --depth;
  382. _dtb_node_printf_depth(depth);
  383. rt_kputs("};\n");
  384. }
  385. }
  386. void dtb_node_get_dts_dump(struct dtb_node *dtb_node_head)
  387. {
  388. if (dtb_node_head != NULL)
  389. {
  390. int i = dtb_node_head->header->memreserve_sz;
  391. rt_kputs("/dts-v1/;\n");
  392. while (i --> 0)
  393. {
  394. rt_kprintf("\n/memreserve/\t0x%lx 0x%zx;", dtb_node_head->header->memreserve[i].address, dtb_node_head->header->memreserve[i].size);
  395. }
  396. _dtb_node_printf_dtb_node_info(dtb_node_head);
  397. }
  398. }
  399. static void _dtb_node_get_enum_dtb_node(struct dtb_node *dtb_node, void (callback(struct dtb_node *dtb_node)))
  400. {
  401. while (dtb_node != NULL)
  402. {
  403. callback(dtb_node);
  404. _dtb_node_get_enum_dtb_node(dtb_node->child, callback);
  405. dtb_node = dtb_node->sibling;
  406. }
  407. }
  408. void dtb_node_get_enum_dtb_node(struct dtb_node *dtb_node_head, void (callback(struct dtb_node *dtb_node)))
  409. {
  410. if (dtb_node_head == NULL || callback == NULL)
  411. {
  412. return;
  413. }
  414. _dtb_node_get_enum_dtb_node(dtb_node_head, callback);
  415. }
  416. struct dtb_node *dtb_node_get_dtb_node_by_name_DFS(struct dtb_node *dtb_node, const char *nodename)
  417. {
  418. struct dtb_node *dtb_node_child;
  419. while (dtb_node != NULL)
  420. {
  421. if (!strcmp(nodename, dtb_node->name))
  422. {
  423. return dtb_node;
  424. }
  425. dtb_node_child = dtb_node_get_dtb_node_by_name_DFS(dtb_node->child, nodename);
  426. if (dtb_node_child != NULL)
  427. {
  428. return dtb_node_child;
  429. }
  430. dtb_node = dtb_node->sibling;
  431. }
  432. return NULL;
  433. }
  434. struct dtb_node *dtb_node_get_dtb_node_by_name_BFS(struct dtb_node *dtb_node, const char *nodename)
  435. {
  436. if (dtb_node != NULL)
  437. {
  438. struct dtb_node *dtb_node_child, *dtb_node_head = dtb_node;
  439. while (dtb_node != NULL)
  440. {
  441. if (!strcmp(nodename, dtb_node->name))
  442. {
  443. return dtb_node;
  444. }
  445. dtb_node = dtb_node->sibling;
  446. }
  447. dtb_node = dtb_node_head;
  448. while (dtb_node != NULL)
  449. {
  450. dtb_node_child = dtb_node_get_dtb_node_by_name_BFS(dtb_node->child, nodename);
  451. if (dtb_node_child != NULL)
  452. {
  453. return dtb_node_child;
  454. }
  455. dtb_node = dtb_node->sibling;
  456. }
  457. }
  458. return NULL;
  459. }
  460. struct dtb_node *dtb_node_get_dtb_node_by_path(struct dtb_node *dtb_node, const char *pathname)
  461. {
  462. int i = 0;
  463. char *node_name;
  464. char *pathname_clone;
  465. int pathname_sz;
  466. if (pathname == NULL || dtb_node == NULL)
  467. {
  468. return NULL;
  469. }
  470. /* skip '/' */
  471. if (*pathname == '/')
  472. {
  473. ++pathname;
  474. }
  475. /* root not have sibling, so skip */
  476. if (dtb_node->parent == NULL || !strcmp(dtb_node->path, "/"))
  477. {
  478. dtb_node = dtb_node->child;
  479. }
  480. pathname_sz = strlen(pathname) + 1;
  481. pathname_clone = (char *)malloc(pathname_sz);
  482. if (pathname_clone == NULL)
  483. {
  484. return NULL;
  485. }
  486. strncpy(pathname_clone, pathname, pathname_sz);
  487. node_name = pathname_clone;
  488. while (pathname_clone[i])
  489. {
  490. if (pathname_clone[i] == '/')
  491. {
  492. /* set an end of name that can used to strcmp */
  493. pathname_clone[i] = '\0';
  494. while (dtb_node != NULL)
  495. {
  496. if (!strcmp(dtb_node->name, node_name))
  497. {
  498. break;
  499. }
  500. dtb_node = dtb_node->sibling;
  501. }
  502. if (dtb_node == NULL)
  503. {
  504. free(pathname_clone);
  505. return NULL;
  506. }
  507. dtb_node = dtb_node->child;
  508. node_name = &pathname_clone[i + 1];
  509. }
  510. ++i;
  511. }
  512. /*
  513. * found the end node and it's name:
  514. * (pathname[pathname_sz - 1]) is '\0'
  515. * (&pathname_clone[i] - node_name) is the node_name's length
  516. */
  517. node_name = &((char *)pathname)[(pathname_sz - 1) - (&pathname_clone[i] - node_name)];
  518. free(pathname_clone);
  519. while (dtb_node != NULL)
  520. {
  521. if (!strcmp(dtb_node->name, node_name))
  522. {
  523. return dtb_node;
  524. }
  525. dtb_node = dtb_node->sibling;
  526. }
  527. return NULL;
  528. }
  529. struct dtb_node *dtb_node_get_dtb_node_by_phandle_DFS(struct dtb_node *dtb_node, phandle handle)
  530. {
  531. struct dtb_node *dtb_node_child;
  532. while (dtb_node != NULL)
  533. {
  534. if (dtb_node->handle == handle)
  535. {
  536. return dtb_node;
  537. }
  538. dtb_node_child = dtb_node_get_dtb_node_by_phandle_DFS(dtb_node->child, handle);
  539. if (dtb_node_child != NULL)
  540. {
  541. return dtb_node_child;
  542. }
  543. dtb_node = dtb_node->sibling;
  544. }
  545. return NULL;
  546. }
  547. struct dtb_node *dtb_node_get_dtb_node_by_phandle_BFS(struct dtb_node *dtb_node, phandle handle)
  548. {
  549. if (dtb_node != NULL)
  550. {
  551. struct dtb_node *dtb_node_child, *dtb_node_head = dtb_node;
  552. while (dtb_node != NULL)
  553. {
  554. if (dtb_node->handle == handle)
  555. {
  556. return dtb_node;
  557. }
  558. dtb_node = dtb_node->sibling;
  559. }
  560. dtb_node = dtb_node_head;
  561. while (dtb_node != NULL)
  562. {
  563. dtb_node_child = dtb_node_get_dtb_node_by_phandle_BFS(dtb_node->child, handle);
  564. if (dtb_node_child != NULL)
  565. {
  566. return dtb_node_child;
  567. }
  568. dtb_node = dtb_node->sibling;
  569. }
  570. }
  571. return NULL;
  572. }
  573. void dtb_node_get_dtb_node_cells(struct dtb_node *dtb_node, int *addr_cells, int *size_cells)
  574. {
  575. if (dtb_node != NULL && addr_cells != NULL && size_cells != NULL)
  576. {
  577. struct dtb_property *dtb_property;
  578. *addr_cells = -1;
  579. *size_cells = -1;
  580. /* if couldn't found, check parent */
  581. while ((dtb_node = dtb_node->parent) != NULL)
  582. {
  583. dtb_property = dtb_node->properties;
  584. while (dtb_property != NULL)
  585. {
  586. if (!strcmp(dtb_property->name, "#address-cells"))
  587. {
  588. *addr_cells = fdt32_to_cpu(*(int *)dtb_property->value);
  589. }
  590. else if (!strcmp(dtb_property->name, "#size-cells"))
  591. {
  592. *size_cells = fdt32_to_cpu(*(int *)dtb_property->value);
  593. }
  594. if (*addr_cells != -1 && *size_cells != -1)
  595. {
  596. return;
  597. }
  598. dtb_property = dtb_property->next;
  599. }
  600. }
  601. if (*addr_cells == -1)
  602. {
  603. *addr_cells = FDT_ROOT_ADDR_CELLS_DEFAULT;
  604. }
  605. if (*size_cells == -1)
  606. {
  607. *size_cells = FDT_ROOT_SIZE_CELLS_DEFAULT;
  608. }
  609. }
  610. }
  611. struct dtb_memreserve *dtb_node_get_dtb_memreserve(struct dtb_node *dtb_node, int *memreserve_size)
  612. {
  613. if (dtb_node != NULL && memreserve_size != NULL)
  614. {
  615. struct dtb_node *dtb_node_root = dtb_node;
  616. while (dtb_node_root != NULL)
  617. {
  618. if (!strcmp(dtb_node_root->path, "/"))
  619. {
  620. break;
  621. }
  622. dtb_node_root = dtb_node_root->parent;
  623. }
  624. if(dtb_node_root == NULL) return NULL;
  625. *memreserve_size = dtb_node_root->header->memreserve_sz;
  626. return dtb_node_root->header->memreserve;
  627. }
  628. return NULL;
  629. }
  630. rt_bool_t dtb_node_get_dtb_node_status(const struct dtb_node *dtb_node)
  631. {
  632. if (dtb_node != NULL)
  633. {
  634. char *status = dtb_node_get_dtb_node_property_value(dtb_node, "status", NULL);
  635. if (status != NULL)
  636. {
  637. return (!strcmp(status, "okay") || !strcmp(status, "ok")) ? RT_TRUE : RT_FALSE;
  638. }
  639. return RT_TRUE;
  640. }
  641. return RT_FALSE;
  642. }
  643. rt_bool_t dtb_node_get_dtb_node_compatible_match(const struct dtb_node *dtb_node, const char *compatibles)
  644. {
  645. if (dtb_node != NULL)
  646. {
  647. if (compatibles != NULL)
  648. {
  649. char *str_ptr;
  650. int prop_sz;
  651. for_each_property_string(dtb_node, "compatible", str_ptr, prop_sz)
  652. {
  653. if (!strcmp(compatibles, str_ptr))
  654. {
  655. return RT_TRUE;
  656. }
  657. }
  658. }
  659. }
  660. return RT_FALSE;
  661. }
  662. char *dtb_node_get_dtb_string_list_value(void *value, int size, int index)
  663. {
  664. int i = 0;
  665. char *str = value;
  666. if (str != NULL)
  667. {
  668. do
  669. {
  670. if (i++ == index)
  671. {
  672. return str;
  673. }
  674. str += strlen(str) + 1;
  675. } while (str < (char *)value + size);
  676. }
  677. return NULL;
  678. }
  679. char *dtb_node_get_dtb_string_list_value_next(void *value, void *end)
  680. {
  681. char *str = value;
  682. if (str != NULL)
  683. {
  684. str += strlen(str) + 1;
  685. if (str < (char *)end)
  686. {
  687. return str;
  688. }
  689. }
  690. return NULL;
  691. }
  692. uint32_t dtb_node_get_dtb_cell_value(void *value)
  693. {
  694. return fdt32_to_cpu(*(fdt32_t *)value);
  695. }
  696. uint8_t dtb_node_get_dtb_byte_value(void *value)
  697. {
  698. return *(uint8_t *)value;
  699. }