dtb_get.c 22 KB

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