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