source: rtems/cpukit/libmisc/rtems-fdt/rtems-fdt.c @ 4dc81f65

Last change on this file since 4dc81f65 was 4dc81f65, checked in by Chris Johns <chrisj@…>, on 08/21/21 at 02:46:32

libmisc/fdt: fix node initialise error with RTEMS_DEBUG

  • Property mode set to 100644
File size: 24.4 KB
Line 
1/*
2 *  COPYRIGHT (c) 2013-2017 Chris Johns <chrisj@rtems.org>
3 *
4 *  The license and distribution terms for this file may be
5 *  found in the file LICENSE in this distribution or at
6 *  http://www.rtems.org/license/LICENSE.
7 */
8
9#include <errno.h>
10#include <fcntl.h>
11#include <stdlib.h>
12#include <stdio.h>
13#include <sys/stat.h>
14#include <sys/types.h>
15
16#include <libfdt.h>
17#include <zlib.h>
18
19#include <rtems/rtems-fdt.h>
20#include <rtems/thread.h>
21
22/**
23 * An index for quick access to the FDT by name or offset.
24 */
25
26typedef struct
27{
28  const char *             name;         /**< The full path of the FDT item. */
29  int                      offset;       /**< The offset of the item in the FDT blob. */
30} rtems_fdt_index_entry;
31
32typedef struct
33{
34  int                    num_entries;    /**< The number of entries in this index. */
35  rtems_fdt_index_entry* entries;        /**< An ordered set of entries which we
36                                          *  can binary search. */
37  char*                  names;          /**< Storage allocated for all the path names. */
38} rtems_fdt_index;
39
40
41/**
42 * A blob descriptor.
43 */
44struct rtems_fdt_blob
45{
46  rtems_chain_node node;        /**< The node's link in the chain. */
47  const void*      blob;        /**< The FDT blob. */
48  const char*      name;        /**< The name of the blob. */
49  int              refs;        /**< The number of active references of the blob. */
50  rtems_fdt_index  index;       /**< The index used for quick access to items in the blob. */
51};
52
53/**
54 * The global FDT data. This structure is allocated on the heap when the first
55 * call to load a FDT blob is made and released when all blobs have been
56 * unloaded..
57 */
58typedef struct
59{
60  rtems_mutex         lock;     /**< The FDT lock id */
61  rtems_chain_control blobs;    /**< List if loaded blobs. */
62  const char*         paths;    /**< Search paths for blobs. */
63} rtems_fdt_data;
64
65static void
66rtems_fdt_unlock (rtems_fdt_data *fdt)
67{
68  rtems_mutex_unlock (&fdt->lock);
69}
70
71static rtems_fdt_data*
72rtems_fdt_lock (void)
73{
74  static rtems_fdt_data fdt_instance = {
75    .lock = RTEMS_MUTEX_INITIALIZER ("FDT"),
76    .blobs = RTEMS_CHAIN_INITIALIZER_EMPTY (fdt_instance.blobs)
77  };
78  rtems_fdt_data *fdt = &fdt_instance;
79
80  rtems_mutex_lock (&fdt->lock);
81  return fdt;
82}
83
84/**
85 * Create an index based on the contents of an FDT blob.
86 */
87static int
88rtems_fdt_init_index (rtems_fdt_handle* fdt, rtems_fdt_blob* blob)
89{
90  rtems_fdt_index_entry* entries = NULL;
91  int                    num_entries = 0;
92  int                    entry = 0;
93  size_t                 total_name_memory = 0;
94  char                   node_path[256];
95  int                    depth_path[32];
96  int                    start_offset = 0;
97  int                    start_depth = 0;
98  int                    offset = 0;
99  int                    depth = 0;
100  char*                  names = NULL;
101  char*                  names_pos = NULL;
102
103  /*
104   * Count the number of entries in the blob first.
105   */
106  memset(&node_path, 0, sizeof(node_path));
107  strcpy(node_path, "/");
108  depth_path[0] = strlen(node_path);
109
110  start_offset = fdt_path_offset(fdt->blob->blob, node_path);
111  if (start_offset < 0)
112  {
113    return start_offset;
114  }
115
116  start_offset = fdt_next_node(fdt->blob->blob, start_offset, &start_depth);
117  if (start_offset < 0)
118  {
119    return start_offset;
120  }
121
122  offset = start_offset;
123  depth = start_depth;
124
125  while (depth > 0)
126  {
127    /*
128     * Construct the node path name.
129     */
130    int         namelen = 0;
131    const char* name = fdt_get_name(blob->blob, offset, &namelen);
132    strncpy(&node_path[depth_path[depth-1]],
133            name,
134            sizeof(node_path) - depth_path[depth-1] - 1);
135
136    total_name_memory += strlen(node_path) + 1;
137    num_entries++;
138
139    if (depth_path[depth-1] + namelen + 2 <= (int)sizeof(node_path))
140    {
141      strcpy(&node_path[depth_path[depth-1] + namelen], "/");
142    }
143
144    depth_path[depth] = depth_path[depth-1] + namelen + 1;
145
146    /*
147     * Get the next node.
148     */
149    offset = fdt_next_node(fdt->blob->blob, offset, &depth);
150    if (offset < 0)
151    {
152      return offset;
153    }
154  }
155
156  /*
157   * Create the index.
158   */
159  entries = calloc(num_entries, sizeof(rtems_fdt_index_entry));
160  if (!entries)
161  {
162    return -RTEMS_FDT_ERR_NO_MEMORY;
163  }
164
165  names = calloc(1, total_name_memory);
166  if (!entries)
167  {
168    free(entries);
169    return -RTEMS_FDT_ERR_NO_MEMORY;
170  }
171
172  /*
173   * Populate the index.
174   */
175  offset = start_offset;
176  depth = start_depth;
177  entry = 0;
178  names_pos = names;
179
180  while (depth > 0)
181  {
182    /*
183     * Record this node in an entry.
184     */
185    int         namelen = 0;
186    const char* name = fdt_get_name(blob->blob, offset, &namelen);
187    strncpy(&node_path[depth_path[depth-1]],
188            name,
189            sizeof(node_path) - depth_path[depth-1] - 1);
190    strcpy(names_pos, node_path);
191
192    entries[entry].name = names_pos;
193    entries[entry].offset = offset;
194
195    names_pos += strlen(node_path) + 1;
196    entry++;
197
198    if (depth_path[depth-1] + namelen + 2 <= (int)sizeof(node_path))
199    {
200      strcpy(&node_path[depth_path[depth-1] + namelen], "/");
201    }
202
203    depth_path[depth] = depth_path[depth-1] + namelen + 1;
204
205    /*
206     * Get the next node.
207     */
208    offset = fdt_next_node(fdt->blob->blob, offset, &depth);
209    if (offset < 0)
210    {
211      free(entries);
212      free(names);
213      return offset;
214    }
215  }
216
217  fdt->blob->index.entries = entries;
218  fdt->blob->index.num_entries = num_entries;
219  fdt->blob->index.names = names;
220
221  return 0;
222}
223
224/**
225 * Release the contents of the index, freeing memory.
226 */
227static void
228rtems_fdt_release_index (rtems_fdt_index* index)
229{
230  if (index->entries)
231  {
232    free(index->entries);
233    free(index->names);
234
235    index->num_entries = 0;
236    index->entries = NULL;
237    index->names = NULL;
238  }
239}
240
241/**
242 * For a given FDT path, find the corresponding offset.
243 * Returns -1 if not found;
244 */
245static int
246rtems_fdt_index_find_by_name(rtems_fdt_index* index,
247                             const char*      name)
248{
249  int         min = 0;
250  int         max = index->num_entries;
251  /*
252   * Handle trailing slash case.
253   */
254  size_t namelen = strlen(name);
255  if (namelen > 0 && name[namelen-1] == '/')
256  {
257    namelen--;
258  }
259
260  /* Binary search for the name. */
261  while (min < max)
262  {
263    int middle = (min + max) / 2;
264    int cmp = strncmp(name, index->entries[middle].name, namelen);
265    if (cmp == 0)
266    {
267      /* 'namelen' characters are equal but 'index->entries[middle].name' */
268      /* could have additional characters. */
269      if (index->entries[middle].name[namelen] == '\0')
270      {
271        /* Found it. */
272        return index->entries[middle].offset;
273      }
274      else
275      {
276         /* 'index->entries[middle].name' is longer than 'name'. */
277         cmp = -1;
278      }
279    }
280    if (cmp < 0)
281    {
282      /* Look lower than here. */
283      max = middle;
284    }
285    else
286    {
287      /* Look higher than here. */
288      min = middle + 1;
289    }
290 }
291
292  /* Didn't find it. */
293  return -FDT_ERR_NOTFOUND;
294}
295
296/**
297 * For a given FDT offset, find the corresponding path name.
298 */
299static const char *
300rtems_fdt_index_find_name_by_offset(rtems_fdt_index* index,
301                                    int              offset)
302{
303  int min = 0;
304  int max = index->num_entries;
305
306  /*
307   * Binary search for the offset.
308   */
309  while (min < max)
310  {
311    int middle = (min + max) / 2;
312    if (offset < index->entries[middle].offset)
313    {
314      /* Look lower than here. */
315      max = middle;
316    }
317    else if (offset > index->entries[middle].offset)
318    {
319      /* Look higher than here. */
320      min = middle + 1;
321    }
322    else
323    {
324      /* Found it. */
325      return index->entries[middle].name;
326    }
327  }
328
329  /* Didn't find it. */
330  return NULL;
331}
332
333void
334rtems_fdt_init_handle (rtems_fdt_handle* handle)
335{
336  if (handle)
337    handle->blob = NULL;
338}
339
340void
341rtems_fdt_dup_handle (rtems_fdt_handle* from, rtems_fdt_handle* to)
342{
343  if (from && to)
344  {
345    rtems_fdt_data* fdt;
346
347    fdt = rtems_fdt_lock ();
348    to->blob = from->blob;
349    ++to->blob->refs;
350    rtems_fdt_unlock (fdt);
351  }
352}
353
354void
355rtems_fdt_release_handle (rtems_fdt_handle* handle)
356{
357  if (handle && handle->blob)
358  {
359    rtems_fdt_data*   fdt;
360    rtems_chain_node* node;
361
362    fdt = rtems_fdt_lock ();
363
364    node = rtems_chain_first (&fdt->blobs);
365
366    while (!rtems_chain_is_tail (&fdt->blobs, node))
367    {
368      rtems_fdt_blob* blob = (rtems_fdt_blob*) node;
369      if (handle->blob == blob)
370      {
371        if (blob->refs)
372          --blob->refs;
373        break;
374      }
375      node = rtems_chain_next (node);
376    }
377
378    rtems_fdt_unlock (fdt);
379
380    handle->blob = NULL;
381  }
382}
383
384bool
385rtems_fdt_valid_handle (const rtems_fdt_handle* handle)
386{
387  if (handle && handle->blob)
388  {
389    rtems_fdt_data*   fdt;
390    rtems_chain_node* node;
391
392    fdt = rtems_fdt_lock ();
393
394    node = rtems_chain_first (&fdt->blobs);
395
396    while (!rtems_chain_is_tail (&fdt->blobs, node))
397    {
398      rtems_fdt_blob* blob = (rtems_fdt_blob*) node;
399      if (handle->blob == blob)
400      {
401        rtems_fdt_unlock (fdt);
402        return true;
403      }
404      node = rtems_chain_next (node);
405    }
406
407    rtems_fdt_unlock (fdt);
408  }
409
410  return false;
411}
412
413int
414rtems_fdt_find_path_offset (rtems_fdt_handle* handle, const char* path)
415{
416  rtems_fdt_data*   fdt;
417  rtems_chain_node* node;
418
419  rtems_fdt_release_handle (handle);
420
421  fdt = rtems_fdt_lock ();
422
423  node = rtems_chain_first (&fdt->blobs);
424
425  while (!rtems_chain_is_tail (&fdt->blobs, node))
426  {
427    rtems_fdt_handle temp_handle;
428    int              offset;
429
430    temp_handle.blob = (rtems_fdt_blob*) node;
431
432    offset = rtems_fdt_path_offset (&temp_handle, path);
433
434    if (offset >= 0)
435    {
436      ++temp_handle.blob->refs;
437      handle->blob = temp_handle.blob;
438      rtems_fdt_unlock (fdt);
439      return offset;
440    }
441
442    node = rtems_chain_next (node);
443  }
444
445  rtems_fdt_unlock (fdt);
446
447  return -FDT_ERR_NOTFOUND;
448}
449
450int
451rtems_fdt_load (const char* filename, rtems_fdt_handle* handle)
452{
453  rtems_fdt_data* fdt;
454  rtems_fdt_blob* blob;
455  size_t          bsize;
456  int             bf;
457  ssize_t         r;
458  size_t          name_len;
459  int             fe;
460  struct stat     sb;
461  uint8_t         gzip_id[2];
462  uint8_t*        cdata;
463  size_t          size;
464
465  rtems_fdt_release_handle (handle);
466
467  if (stat (filename, &sb) < 0)
468  {
469    return -RTEMS_FDT_ERR_NOT_FOUND;
470  }
471
472  bf = open(filename, O_RDONLY);
473  if (bf < 0)
474  {
475    return -RTEMS_FDT_ERR_READ_FAIL;
476  }
477
478  r = read(bf, &gzip_id, sizeof(gzip_id));
479  if (r < 0)
480  {
481    close(bf);
482    return -RTEMS_FDT_ERR_READ_FAIL;
483  }
484
485  if ((gzip_id[0] == 0x1f) && (gzip_id[1] == 0x8b))
486  {
487    size_t offset;
488
489    cdata = malloc(sb.st_size);
490    if (!cdata)
491    {
492      close (bf);
493      return -RTEMS_FDT_ERR_NO_MEMORY;
494    }
495
496    if (lseek(bf, 0, SEEK_SET) < 0)
497    {
498      free(cdata);
499      close(bf);
500      return -RTEMS_FDT_ERR_READ_FAIL;
501    }
502
503    size = sb.st_size;
504    offset = 0;
505    while (size)
506    {
507      r = read(bf, cdata + offset, size);
508      if (r < 0)
509      {
510        free(cdata);
511        close(bf);
512        return -RTEMS_FDT_ERR_READ_FAIL;
513      }
514      size -= r;
515      offset += r;
516    }
517
518    offset = sb.st_size - 4;
519    bsize = ((cdata[offset + 3] << 24) | (cdata[offset + 2] << 16) |
520             (cdata[offset + 1] << 8) | cdata[offset + 0]);
521  }
522  else
523  {
524    cdata = NULL;
525    bsize = sb.st_size;
526  }
527
528  name_len = strlen (filename) + 1;
529
530  blob = malloc(sizeof (rtems_fdt_blob) + name_len + bsize);
531  if (!blob)
532  {
533    free(cdata);
534    close (bf);
535    return -RTEMS_FDT_ERR_NO_MEMORY;
536  }
537
538  blob->name = (const char*) (blob + 1);
539  blob->blob = blob->name + name_len + 1;
540
541  strcpy ((char*) blob->name, filename);
542
543  if ((gzip_id[0] == 0x1f) && (gzip_id[1] == 0x8b))
544  {
545    z_stream stream;
546    int      err;
547    stream.next_in = (Bytef*) cdata;
548    stream.avail_in = (uInt) sb.st_size;
549    stream.next_out = (void*) (blob->name + name_len + 1);
550    stream.avail_out = (uInt) bsize;
551    stream.zalloc = (alloc_func) 0;
552    stream.zfree = (free_func) 0;
553    err = inflateInit(&stream);
554    if (err == Z_OK)
555      err = inflateReset2(&stream, 31);
556    if (err == Z_OK)
557      err = inflate(&stream, Z_FINISH);
558    if ((err == Z_OK) || (err == Z_STREAM_END))
559      err = inflateEnd(&stream);
560    if ((err != Z_OK) || (bsize != stream.total_out))
561    {
562      free (blob);
563      free(cdata);
564      close (bf);
565      return -RTEMS_FDT_ERR_READ_FAIL;
566    }
567    free(cdata);
568    cdata = NULL;
569  }
570  else
571  {
572    char* buf = (char*) blob->name + name_len + 1;
573    size = bsize;
574    while (size)
575    {
576      r = read (bf, buf, size);
577      if (r < 0)
578      {
579        free (blob);
580        close (bf);
581        return -RTEMS_FDT_ERR_READ_FAIL;
582      }
583      size -= r;
584      buf += r;
585    }
586  }
587
588  fe = fdt_check_header(blob->blob);
589  if (fe < 0)
590  {
591    free (blob);
592    close (bf);
593    return fe;
594  }
595
596  fdt = rtems_fdt_lock ();
597
598  rtems_chain_append_unprotected (&fdt->blobs, &blob->node);
599
600  blob->refs = 1;
601
602  rtems_fdt_unlock (fdt);
603
604  handle->blob = blob;
605
606  fe = rtems_fdt_init_index(handle, blob);
607  if (fe < 0)
608  {
609    free (blob);
610    close (bf);
611    return fe;
612  }
613
614  return 0;
615}
616
617int
618rtems_fdt_register (const void* dtb, rtems_fdt_handle* handle)
619{
620  rtems_fdt_data* fdt;
621  rtems_fdt_blob* blob;
622  int             fe;
623
624  rtems_fdt_release_handle (handle);
625
626  fe = fdt_check_header(dtb);
627  if (fe < 0)
628  {
629    return fe;
630  }
631
632  blob = malloc(sizeof (rtems_fdt_blob));
633  if (!blob)
634  {
635    return -RTEMS_FDT_ERR_NO_MEMORY;
636  }
637
638  blob->blob = dtb;
639  blob->name = NULL;
640  rtems_chain_initialize_node(&blob->node);
641
642  fdt = rtems_fdt_lock ();
643
644  rtems_chain_append_unprotected (&fdt->blobs, &blob->node);
645
646  blob->refs = 1;
647
648  rtems_fdt_unlock (fdt);
649
650  handle->blob = blob;
651
652  fe = rtems_fdt_init_index(handle, blob);
653  if (fe < 0)
654  {
655    free(blob);
656    return -RTEMS_FDT_ERR_NO_MEMORY;
657  }
658
659  return 0;
660}
661
662int
663rtems_fdt_unload (rtems_fdt_handle* handle)
664{
665  rtems_fdt_data* fdt;
666
667  fdt = rtems_fdt_lock ();
668
669  if (!rtems_fdt_valid_handle (handle))
670  {
671    rtems_fdt_unlock (fdt);
672    return -RTEMS_FDT_ERR_INVALID_HANDLE;
673  }
674
675  if (handle->blob->refs > 1)
676  {
677    rtems_fdt_unlock (fdt);
678    return -RTEMS_FDT_ERR_REFERENCED;
679  }
680
681  rtems_chain_extract_unprotected (&handle->blob->node);
682
683  free (handle->blob);
684
685  handle->blob = NULL;
686
687  rtems_fdt_unlock (fdt);
688
689  rtems_fdt_release_index(&handle->blob->index);
690
691  return 0;
692}
693
694int
695rtems_fdt_num_mem_rsv (rtems_fdt_handle* handle)
696{
697  if (!handle->blob)
698    return -RTEMS_FDT_ERR_INVALID_HANDLE;
699  return fdt_num_mem_rsv (handle->blob->blob);
700}
701
702int
703rtems_fdt_get_mem_rsv (rtems_fdt_handle* handle,
704                       int               n,
705                       uint64_t*         address,
706                       uint64_t*         size)
707{
708  if (!handle->blob)
709    return -RTEMS_FDT_ERR_INVALID_HANDLE;
710  return fdt_get_mem_rsv (handle->blob->blob, n, address, size);
711}
712
713int
714rtems_fdt_subnode_offset_namelen (rtems_fdt_handle* handle,
715                                  int               parentoffset,
716                                  const char*       name,
717                                  int               namelen)
718{
719  if (!handle->blob)
720    return -RTEMS_FDT_ERR_INVALID_HANDLE;
721  return fdt_subnode_offset_namelen (handle->blob->blob,
722                                     parentoffset,
723                                     name,
724                                     namelen);
725}
726
727int
728rtems_fdt_subnode_offset (rtems_fdt_handle* handle,
729                          int               parentoffset,
730                          const char*       name)
731{
732  char full_name[256];
733  const char *path;
734
735  if (!handle->blob)
736    return -RTEMS_FDT_ERR_INVALID_HANDLE;
737
738  path = rtems_fdt_index_find_name_by_offset(&handle->blob->index, parentoffset);
739  snprintf(full_name, sizeof(full_name), "%s/%s", path, name);
740
741  return rtems_fdt_index_find_by_name(&handle->blob->index, full_name);
742}
743
744int
745rtems_fdt_path_offset (rtems_fdt_handle* handle, const char* path)
746{
747  return rtems_fdt_index_find_by_name(&handle->blob->index, path);
748}
749
750const char*
751rtems_fdt_get_name (rtems_fdt_handle* handle, int nodeoffset, int* length)
752{
753  if (!handle->blob)
754    return NULL;
755
756  const char *name = rtems_fdt_index_find_name_by_offset(&handle->blob->index, nodeoffset);
757  if (name && length)
758  {
759    *length = strlen(name);
760  }
761
762  return name;
763}
764
765const void*
766rtems_fdt_getprop_namelen (rtems_fdt_handle* handle,
767                           int               nodeoffset,
768                           const char*       name,
769                           int               namelen,
770                           int*              length)
771{
772  if (!handle->blob)
773    return NULL;
774  return fdt_getprop_namelen (handle->blob->blob,
775                              nodeoffset,
776                              name,
777                              namelen,
778                              length);
779}
780
781const void*
782rtems_fdt_getprop (rtems_fdt_handle* handle,
783                   int               nodeoffset,
784                   const char*       name,
785                   int*              length)
786{
787  if (!handle->blob)
788    return NULL;
789  return fdt_getprop (handle->blob->blob,
790                      nodeoffset,
791                      name,
792                      length);
793}
794
795uint32_t
796rtems_fdt_get_phandle (rtems_fdt_handle* handle, int nodeoffset)
797{
798  if (!handle->blob)
799    return -RTEMS_FDT_ERR_INVALID_HANDLE;
800  return fdt_get_phandle (handle->blob->blob, nodeoffset);
801}
802
803const char*
804rtems_fdt_get_alias_namelen (rtems_fdt_handle* handle,
805                             const char*       name,
806                             int               namelen)
807{
808  if (!handle->blob)
809    return NULL;
810  return fdt_get_alias_namelen (handle->blob->blob, name, namelen);
811}
812
813const char*
814rtems_fdt_get_alias (rtems_fdt_handle* handle, const char* name)
815{
816  if (!handle->blob)
817    return NULL;
818  return fdt_get_alias (handle->blob->blob, name);
819}
820
821int
822rtems_fdt_get_path (rtems_fdt_handle* handle,
823                    int               nodeoffset,
824                    char*             buf,
825                    int               buflen)
826{
827  if (!handle->blob)
828    return -RTEMS_FDT_ERR_INVALID_HANDLE;
829  return fdt_get_path (handle->blob->blob, nodeoffset, buf, buflen);
830}
831
832int
833rtems_fdt_supernode_atdepth_offset (rtems_fdt_handle* handle,
834                                    int               nodeoffset,
835                                    int               supernodedepth,
836                                    int*              nodedepth)
837{
838  if (!handle->blob)
839    return -RTEMS_FDT_ERR_INVALID_HANDLE;
840  return fdt_supernode_atdepth_offset(handle,
841                                      nodeoffset,
842                                      supernodedepth,
843                                      nodedepth);
844}
845
846int
847rtems_fdt_node_depth (rtems_fdt_handle* handle, int nodeoffset)
848{
849  if (!handle->blob)
850    return -RTEMS_FDT_ERR_INVALID_HANDLE;
851  return fdt_node_depth (handle->blob->blob, nodeoffset);
852}
853
854int
855rtems_fdt_parent_offset (rtems_fdt_handle* handle, int nodeoffset)
856{
857  if (!handle->blob)
858    return -RTEMS_FDT_ERR_INVALID_HANDLE;
859  return fdt_parent_offset (handle->blob->blob, nodeoffset);
860}
861
862int
863rtems_fdt_node_offset_by_prop_value (rtems_fdt_handle* handle,
864                                     int               startoffset,
865                                     const char*       propname,
866                                     const void*       propval,
867                                     int               proplen)
868{
869  if (!handle->blob)
870    return -RTEMS_FDT_ERR_INVALID_HANDLE;
871  return fdt_node_offset_by_prop_value (handle,
872                                        startoffset,
873                                        propname,
874                                        propval,
875                                        proplen);
876}
877
878int
879rtems_fdt_node_offset_by_phandle (rtems_fdt_handle* handle, uint32_t phandle)
880{
881  if (!handle->blob)
882    return -RTEMS_FDT_ERR_INVALID_HANDLE;
883  return fdt_node_offset_by_phandle (handle->blob->blob, phandle);
884}
885
886int
887rtems_fdt_node_check_compatible (rtems_fdt_handle* handle,
888                                 int               nodeoffset,
889                                 const char*       compatible)
890{
891  if (!handle->blob)
892    return -RTEMS_FDT_ERR_INVALID_HANDLE;
893  return fdt_node_check_compatible (handle, nodeoffset, compatible);
894}
895
896int
897rtems_fdt_node_offset_by_compatible (rtems_fdt_handle* handle,
898                                     int               startoffset,
899                                     const char*       compatible)
900{
901  if (!handle->blob)
902    return -RTEMS_FDT_ERR_INVALID_HANDLE;
903  return fdt_node_offset_by_compatible (handle->blob->blob,
904                                        startoffset,
905                                        compatible);
906}
907
908int
909rtems_fdt_next_node (rtems_fdt_handle* handle, int offset, int* depth)
910{
911  if (!handle->blob)
912    return -RTEMS_FDT_ERR_INVALID_HANDLE;
913  return fdt_next_node (handle->blob->blob, offset, depth);
914}
915
916const char*
917rtems_fdt_strerror (int errval)
918{
919  const char* errors[] = {
920    "invalid handle",
921    "no memory",
922    "file not found",
923    "DTB read fail",
924    "blob has references"
925  };
926  if (errval > -RTEMS_FDT_ERR_RTEMS_MIN)
927    return fdt_strerror (errval);
928  if (errval < -RTEMS_FDT_ERR_MAX)
929    return "invalid error code";
930  return errors[(-errval) - RTEMS_FDT_ERR_RTEMS_MIN];
931}
932
933int
934rtems_fdt_prop_value(const char* const path,
935                     const char* const propname,
936                     void*             value,
937                     size_t*           size)
938{
939  rtems_fdt_handle fdt;
940  int              node;
941  const void*      prop;
942  int              length;
943
944  rtems_fdt_init_handle (&fdt);
945
946  node = rtems_fdt_find_path_offset (&fdt, path);
947  if (node < 0)
948    return node;
949
950  prop = rtems_fdt_getprop(&fdt, node, propname, &length);
951  if (length < 0)
952  {
953    rtems_fdt_release_handle (&fdt);
954    return length;
955  }
956
957  if (length > (int) *size)
958  {
959    rtems_fdt_release_handle (&fdt);
960    return RTEMS_FDT_ERR_BADPATH;
961  }
962
963  *size = length;
964
965  memcpy (value, prop, length);
966
967  return 0;
968}
969
970int
971rtems_fdt_prop_map(const char* const path,
972                   const char* const propname,
973                   const char* const names[],
974                   uint32_t*         values,
975                   size_t            count)
976{
977  rtems_fdt_handle fdt;
978  int              node;
979  size_t           item;
980
981  rtems_fdt_init_handle (&fdt);
982
983  node = rtems_fdt_find_path_offset (&fdt, path);
984  if (node < 0)
985    return node;
986
987  for (item = 0; item < count; item++)
988  {
989    const void*    prop;
990    const uint8_t* p;
991    int            length;
992    int            subnode;
993
994    subnode = rtems_fdt_subnode_offset (&fdt, node, names[item]);
995    if (subnode < 0)
996    {
997      rtems_fdt_release_handle (&fdt);
998      return subnode;
999    }
1000
1001    prop = rtems_fdt_getprop(&fdt, subnode, propname, &length);
1002    if (length < 0)
1003    {
1004      rtems_fdt_release_handle (&fdt);
1005      return length;
1006    }
1007
1008    if (length != sizeof (uint32_t))
1009    {
1010      rtems_fdt_release_handle (&fdt);
1011      return RTEMS_FDT_ERR_BADPATH;
1012    }
1013
1014    p = prop;
1015
1016    values[item] = ((((uint32_t) p[0]) << 24) |
1017                    (((uint32_t) p[1]) << 16) |
1018                    (((uint32_t) p[2]) << 8)  |
1019                    (uint32_t) p[3]);
1020  }
1021
1022  return 0;
1023}
1024
1025uint32_t
1026rtems_fdt_get_uint32 (const void* prop)
1027{
1028  const uint8_t* p = prop;
1029  uint32_t       value;
1030  value = ((((uint32_t) p[0]) << 24) |
1031           (((uint32_t) p[1]) << 16) |
1032           (((uint32_t) p[2]) << 8)  |
1033           (uint32_t) p[3]);
1034  return value;
1035}
1036
1037int
1038rtems_fdt_get_value (const char* path,
1039                     const char* property,
1040                     size_t      size,
1041                     uint32_t*   value)
1042{
1043  rtems_fdt_handle fdt;
1044  const void*      prop;
1045  int              node;
1046  int              length;
1047
1048  rtems_fdt_init_handle (&fdt);
1049
1050  node = rtems_fdt_find_path_offset (&fdt, path);
1051  if (node < 0)
1052  {
1053    rtems_fdt_release_handle (&fdt);
1054    return node;
1055  }
1056
1057  prop = rtems_fdt_getprop(&fdt, node, property, &length);
1058  if (length < 0)
1059  {
1060    rtems_fdt_release_handle (&fdt);
1061    return length;
1062  }
1063
1064  if (length == sizeof (uint32_t))
1065    *value = rtems_fdt_get_uint32 (prop);
1066  else
1067    *value = 0;
1068
1069  rtems_fdt_release_handle (&fdt);
1070
1071  return 0;
1072}
1073
1074/**
1075 * Get the number of entries in an FDT handle.
1076 */
1077int
1078rtems_fdt_num_entries(rtems_fdt_handle* handle)
1079{
1080  return handle->blob->index.num_entries;
1081}
1082
1083/**
1084 * Get the numbered entry name. Note that the id isn't the same as
1085 * the offset - it's numbered 0, 1, 2 ... num_entries-1
1086 */
1087const char *
1088rtems_fdt_entry_name(rtems_fdt_handle* handle, int id)
1089{
1090  return handle->blob->index.entries[id].name;
1091}
1092
1093/**
1094 * Get the numbered entry offset. Note that the id isn't the same as
1095 * the offset - it's numbered 0, 1, 2 ... num_entries-1
1096 */
1097int
1098rtems_fdt_entry_offset(rtems_fdt_handle* handle, int id)
1099{
1100  return handle->blob->index.entries[id].offset;
1101}
Note: See TracBrowser for help on using the repository browser.