source: rtems/cpukit/libmisc/rtems-fdt/rtems-fdt.c @ 08f807e

5
Last change on this file since 08f807e was 08f807e, checked in by G S Niteesh Babu <niteesh.gs@…>, on 03/18/21 at 02:50:56

rtems-fdt/rtems-fdt.c: Fix bug in loop termination

The while loop, loops infinitely in case of raw FDT data.
The loop condition (size) is not modified during iterations.

Fixes #4350

  • Property mode set to 100644
File size: 24.2 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  char        path[256];
252  const char* cmp_name = name;
253
254  /*
255   * Handle trailing slash case.
256   */
257  int namelen = strlen(name);
258  if (namelen > 0 && name[namelen-1] == '/')
259  {
260    namelen--;
261
262    if (namelen >= (int)sizeof(path) - 1)
263    {
264      namelen = sizeof(path) - 1;
265    }
266
267    strncpy(path, name, namelen);
268    path[namelen] = 0;
269    cmp_name = path;
270  }
271
272  /* Binary search for the name. */
273  while (min < max)
274  {
275    int middle = (min + max) / 2;
276    int cmp = strcmp(cmp_name, index->entries[middle].name);
277    if (cmp < 0)
278    {
279      /* Look lower than here. */
280      max = middle;
281    }
282    else if (cmp > 0)
283    {
284      /* Look higher than here. */
285      min = middle + 1;
286    }
287    else
288    {
289      /* Found it. */
290      return index->entries[middle].offset;
291    }
292  }
293
294  /* Didn't find it. */
295  return -FDT_ERR_NOTFOUND;
296}
297
298/**
299 * For a given FDT offset, find the corresponding path name.
300 */
301static const char *
302rtems_fdt_index_find_name_by_offset(rtems_fdt_index* index,
303                                    int              offset)
304{
305  int min = 0;
306  int max = index->num_entries;
307
308  /*
309   * Binary search for the offset.
310   */
311  while (min < max)
312  {
313    int middle = (min + max) / 2;
314    if (offset < index->entries[middle].offset)
315    {
316      /* Look lower than here. */
317      max = middle;
318    }
319    else if (offset > index->entries[middle].offset)
320    {
321      /* Look higher than here. */
322      min = middle + 1;
323    }
324    else
325    {
326      /* Found it. */
327      return index->entries[middle].name;
328    }
329  }
330
331  /* Didn't find it. */
332  return NULL;
333}
334
335void
336rtems_fdt_init_handle (rtems_fdt_handle* handle)
337{
338  if (handle)
339    handle->blob = NULL;
340}
341
342void
343rtems_fdt_dup_handle (rtems_fdt_handle* from, rtems_fdt_handle* to)
344{
345  if (from && to)
346  {
347    rtems_fdt_data* fdt;
348
349    fdt = rtems_fdt_lock ();
350    to->blob = from->blob;
351    ++to->blob->refs;
352    rtems_fdt_unlock (fdt);
353  }
354}
355
356void
357rtems_fdt_release_handle (rtems_fdt_handle* handle)
358{
359  if (handle && handle->blob)
360  {
361    rtems_fdt_data*   fdt;
362    rtems_chain_node* node;
363
364    fdt = rtems_fdt_lock ();
365
366    node = rtems_chain_first (&fdt->blobs);
367
368    while (!rtems_chain_is_tail (&fdt->blobs, node))
369    {
370      rtems_fdt_blob* blob = (rtems_fdt_blob*) node;
371      if (handle->blob == blob)
372      {
373        if (blob->refs)
374          --blob->refs;
375        break;
376      }
377      node = rtems_chain_next (node);
378    }
379
380    rtems_fdt_unlock (fdt);
381
382    handle->blob = NULL;
383  }
384}
385
386bool
387rtems_fdt_valid_handle (const rtems_fdt_handle* handle)
388{
389  if (handle && handle->blob)
390  {
391    rtems_fdt_data*   fdt;
392    rtems_chain_node* node;
393
394    fdt = rtems_fdt_lock ();
395
396    node = rtems_chain_first (&fdt->blobs);
397
398    while (!rtems_chain_is_tail (&fdt->blobs, node))
399    {
400      rtems_fdt_blob* blob = (rtems_fdt_blob*) node;
401      if (handle->blob == blob)
402      {
403        rtems_fdt_unlock (fdt);
404        return true;
405      }
406      node = rtems_chain_next (node);
407    }
408
409    rtems_fdt_unlock (fdt);
410  }
411
412  return false;
413}
414
415int
416rtems_fdt_find_path_offset (rtems_fdt_handle* handle, const char* path)
417{
418  rtems_fdt_data*   fdt;
419  rtems_chain_node* node;
420
421  rtems_fdt_release_handle (handle);
422
423  fdt = rtems_fdt_lock ();
424
425  node = rtems_chain_first (&fdt->blobs);
426
427  while (!rtems_chain_is_tail (&fdt->blobs, node))
428  {
429    rtems_fdt_handle temp_handle;
430    int              offset;
431
432    temp_handle.blob = (rtems_fdt_blob*) node;
433
434    offset = rtems_fdt_path_offset (&temp_handle, path);
435
436    if (offset >= 0)
437    {
438      ++temp_handle.blob->refs;
439      handle->blob = temp_handle.blob;
440      rtems_fdt_unlock (fdt);
441      return offset;
442    }
443
444    node = rtems_chain_next (node);
445  }
446
447  rtems_fdt_unlock (fdt);
448
449  return -FDT_ERR_NOTFOUND;
450}
451
452int
453rtems_fdt_load (const char* filename, rtems_fdt_handle* handle)
454{
455  rtems_fdt_data* fdt;
456  rtems_fdt_blob* blob;
457  size_t          bsize;
458  int             bf;
459  ssize_t         r;
460  size_t          name_len;
461  int             fe;
462  struct stat     sb;
463  uint8_t         gzip_id[2];
464  uint8_t*        cdata;
465  size_t          size;
466
467  rtems_fdt_release_handle (handle);
468
469  if (stat (filename, &sb) < 0)
470  {
471    return -RTEMS_FDT_ERR_NOT_FOUND;
472  }
473
474  bf = open(filename, O_RDONLY);
475  if (bf < 0)
476  {
477    return -RTEMS_FDT_ERR_READ_FAIL;
478  }
479
480  r = read(bf, &gzip_id, sizeof(gzip_id));
481  if (r < 0)
482  {
483    close(bf);
484    return -RTEMS_FDT_ERR_READ_FAIL;
485  }
486
487  if ((gzip_id[0] == 0x1f) && (gzip_id[1] == 0x8b))
488  {
489    size_t offset;
490
491    cdata = malloc(sb.st_size);
492    if (!cdata)
493    {
494      close (bf);
495      return -RTEMS_FDT_ERR_NO_MEMORY;
496    }
497
498    if (lseek(bf, 0, SEEK_SET) < 0)
499    {
500      free(cdata);
501      close(bf);
502      return -RTEMS_FDT_ERR_READ_FAIL;
503    }
504
505    size = sb.st_size;
506    offset = 0;
507    while (size)
508    {
509      r = read(bf, cdata + offset, size);
510      if (r < 0)
511      {
512        free(cdata);
513        close(bf);
514        return -RTEMS_FDT_ERR_READ_FAIL;
515      }
516      size -= r;
517      offset += r;
518    }
519
520    offset = sb.st_size - 4;
521    bsize = ((cdata[offset + 3] << 24) | (cdata[offset + 2] << 16) |
522             (cdata[offset + 1] << 8) | cdata[offset + 0]);
523  }
524  else
525  {
526    cdata = NULL;
527    bsize = sb.st_size;
528  }
529
530  name_len = strlen (filename) + 1;
531
532  blob = malloc(sizeof (rtems_fdt_blob) + name_len + bsize);
533  if (!blob)
534  {
535    free(cdata);
536    close (bf);
537    return -RTEMS_FDT_ERR_NO_MEMORY;
538  }
539
540  blob->name = (const char*) (blob + 1);
541  blob->blob = blob->name + name_len + 1;
542
543  strcpy ((char*) blob->name, filename);
544
545  if ((gzip_id[0] == 0x1f) && (gzip_id[1] == 0x8b))
546  {
547    z_stream stream;
548    int      err;
549    stream.next_in = (Bytef*) cdata;
550    stream.avail_in = (uInt) sb.st_size;
551    stream.next_out = (void*) (blob->name + name_len + 1);
552    stream.avail_out = (uInt) bsize;
553    stream.zalloc = (alloc_func) 0;
554    stream.zfree = (free_func) 0;
555    err = inflateInit(&stream);
556    if (err == Z_OK)
557      err = inflateReset2(&stream, 31);
558    if (err == Z_OK)
559      err = inflate(&stream, Z_FINISH);
560    if ((err == Z_OK) || (err == Z_STREAM_END))
561      err = inflateEnd(&stream);
562    if ((err != Z_OK) || (bsize != stream.total_out))
563    {
564      free (blob);
565      free(cdata);
566      close (bf);
567      return -RTEMS_FDT_ERR_READ_FAIL;
568    }
569    free(cdata);
570    cdata = NULL;
571  }
572  else
573  {
574    char* buf = (char*) blob->name + name_len + 1;
575    size = bsize;
576    while (size)
577    {
578      r = read (bf, buf, size);
579      if (r < 0)
580      {
581        free (blob);
582        close (bf);
583        return -RTEMS_FDT_ERR_READ_FAIL;
584      }
585      size -= r;
586      buf += r;
587    }
588  }
589
590  fe = fdt_check_header(blob->blob);
591  if (fe < 0)
592  {
593    free (blob);
594    close (bf);
595    return fe;
596  }
597
598  fdt = rtems_fdt_lock ();
599
600  rtems_chain_append_unprotected (&fdt->blobs, &blob->node);
601
602  blob->refs = 1;
603
604  rtems_fdt_unlock (fdt);
605
606  handle->blob = blob;
607
608  fe = rtems_fdt_init_index(handle, blob);
609  if (fe < 0)
610  {
611    free (blob);
612    close (bf);
613    return fe;
614  }
615
616  return 0;
617}
618
619int
620rtems_fdt_register (const void* dtb, rtems_fdt_handle* handle)
621{
622  rtems_fdt_data* fdt;
623  rtems_fdt_blob* blob;
624  int             fe;
625
626  rtems_fdt_release_handle (handle);
627
628  fe = fdt_check_header(dtb);
629  if (fe < 0)
630  {
631    return fe;
632  }
633
634  blob = malloc(sizeof (rtems_fdt_blob));
635  if (!blob)
636  {
637    return -RTEMS_FDT_ERR_NO_MEMORY;
638  }
639
640  blob->blob = dtb;
641  blob->name = NULL;
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.