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