source: rtems/cpukit/libmisc/rtems-fdt/rtems-fdt.c @ 98ab693

Last change on this file since 98ab693 was 98ab693, checked in by Ryan Long <ryan.long@…>, on 12/16/21 at 20:36:19

libmisc/rtems-fdt: close() file 'bf'

close() file 'bf' to avoid leaking descriptor.

CID 1437645: Resource leak in rtems_fdt_load().

Closes #4297

  • 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  close (bf);
615  return 0;
616}
617
618int
619rtems_fdt_register (const void* dtb, rtems_fdt_handle* handle)
620{
621  rtems_fdt_data* fdt;
622  rtems_fdt_blob* blob;
623  int             fe;
624
625  rtems_fdt_release_handle (handle);
626
627  fe = fdt_check_header(dtb);
628  if (fe < 0)
629  {
630    return fe;
631  }
632
633  blob = malloc(sizeof (rtems_fdt_blob));
634  if (!blob)
635  {
636    return -RTEMS_FDT_ERR_NO_MEMORY;
637  }
638
639  blob->blob = dtb;
640  blob->name = NULL;
641  rtems_chain_initialize_node(&blob->node);
642
643  fdt = rtems_fdt_lock ();
644
645  rtems_chain_append_unprotected (&fdt->blobs, &blob->node);
646
647  blob->refs = 1;
648
649  rtems_fdt_unlock (fdt);
650
651  handle->blob = blob;
652
653  fe = rtems_fdt_init_index(handle, blob);
654  if (fe < 0)
655  {
656    free(blob);
657    return -RTEMS_FDT_ERR_NO_MEMORY;
658  }
659
660  return 0;
661}
662
663int
664rtems_fdt_unload (rtems_fdt_handle* handle)
665{
666  rtems_fdt_data* fdt;
667
668  fdt = rtems_fdt_lock ();
669
670  if (!rtems_fdt_valid_handle (handle))
671  {
672    rtems_fdt_unlock (fdt);
673    return -RTEMS_FDT_ERR_INVALID_HANDLE;
674  }
675
676  if (handle->blob->refs > 1)
677  {
678    rtems_fdt_unlock (fdt);
679    return -RTEMS_FDT_ERR_REFERENCED;
680  }
681
682  rtems_chain_extract_unprotected (&handle->blob->node);
683
684  free (handle->blob);
685
686  handle->blob = NULL;
687
688  rtems_fdt_unlock (fdt);
689
690  rtems_fdt_release_index(&handle->blob->index);
691
692  return 0;
693}
694
695int
696rtems_fdt_num_mem_rsv (rtems_fdt_handle* handle)
697{
698  if (!handle->blob)
699    return -RTEMS_FDT_ERR_INVALID_HANDLE;
700  return fdt_num_mem_rsv (handle->blob->blob);
701}
702
703int
704rtems_fdt_get_mem_rsv (rtems_fdt_handle* handle,
705                       int               n,
706                       uint64_t*         address,
707                       uint64_t*         size)
708{
709  if (!handle->blob)
710    return -RTEMS_FDT_ERR_INVALID_HANDLE;
711  return fdt_get_mem_rsv (handle->blob->blob, n, address, size);
712}
713
714int
715rtems_fdt_subnode_offset_namelen (rtems_fdt_handle* handle,
716                                  int               parentoffset,
717                                  const char*       name,
718                                  int               namelen)
719{
720  if (!handle->blob)
721    return -RTEMS_FDT_ERR_INVALID_HANDLE;
722  return fdt_subnode_offset_namelen (handle->blob->blob,
723                                     parentoffset,
724                                     name,
725                                     namelen);
726}
727
728int
729rtems_fdt_subnode_offset (rtems_fdt_handle* handle,
730                          int               parentoffset,
731                          const char*       name)
732{
733  char full_name[256];
734  const char *path;
735
736  if (!handle->blob)
737    return -RTEMS_FDT_ERR_INVALID_HANDLE;
738
739  path = rtems_fdt_index_find_name_by_offset(&handle->blob->index, parentoffset);
740  snprintf(full_name, sizeof(full_name), "%s/%s", path, name);
741
742  return rtems_fdt_index_find_by_name(&handle->blob->index, full_name);
743}
744
745int
746rtems_fdt_path_offset (rtems_fdt_handle* handle, const char* path)
747{
748  return rtems_fdt_index_find_by_name(&handle->blob->index, path);
749}
750
751const char*
752rtems_fdt_get_name (rtems_fdt_handle* handle, int nodeoffset, int* length)
753{
754  if (!handle->blob)
755    return NULL;
756
757  const char *name = rtems_fdt_index_find_name_by_offset(&handle->blob->index, nodeoffset);
758  if (name && length)
759  {
760    *length = strlen(name);
761  }
762
763  return name;
764}
765
766const void*
767rtems_fdt_getprop_namelen (rtems_fdt_handle* handle,
768                           int               nodeoffset,
769                           const char*       name,
770                           int               namelen,
771                           int*              length)
772{
773  if (!handle->blob)
774    return NULL;
775  return fdt_getprop_namelen (handle->blob->blob,
776                              nodeoffset,
777                              name,
778                              namelen,
779                              length);
780}
781
782const void*
783rtems_fdt_getprop (rtems_fdt_handle* handle,
784                   int               nodeoffset,
785                   const char*       name,
786                   int*              length)
787{
788  if (!handle->blob)
789    return NULL;
790  return fdt_getprop (handle->blob->blob,
791                      nodeoffset,
792                      name,
793                      length);
794}
795
796uint32_t
797rtems_fdt_get_phandle (rtems_fdt_handle* handle, int nodeoffset)
798{
799  if (!handle->blob)
800    return -RTEMS_FDT_ERR_INVALID_HANDLE;
801  return fdt_get_phandle (handle->blob->blob, nodeoffset);
802}
803
804const char*
805rtems_fdt_get_alias_namelen (rtems_fdt_handle* handle,
806                             const char*       name,
807                             int               namelen)
808{
809  if (!handle->blob)
810    return NULL;
811  return fdt_get_alias_namelen (handle->blob->blob, name, namelen);
812}
813
814const char*
815rtems_fdt_get_alias (rtems_fdt_handle* handle, const char* name)
816{
817  if (!handle->blob)
818    return NULL;
819  return fdt_get_alias (handle->blob->blob, name);
820}
821
822int
823rtems_fdt_get_path (rtems_fdt_handle* handle,
824                    int               nodeoffset,
825                    char*             buf,
826                    int               buflen)
827{
828  if (!handle->blob)
829    return -RTEMS_FDT_ERR_INVALID_HANDLE;
830  return fdt_get_path (handle->blob->blob, nodeoffset, buf, buflen);
831}
832
833int
834rtems_fdt_supernode_atdepth_offset (rtems_fdt_handle* handle,
835                                    int               nodeoffset,
836                                    int               supernodedepth,
837                                    int*              nodedepth)
838{
839  if (!handle->blob)
840    return -RTEMS_FDT_ERR_INVALID_HANDLE;
841  return fdt_supernode_atdepth_offset(handle,
842                                      nodeoffset,
843                                      supernodedepth,
844                                      nodedepth);
845}
846
847int
848rtems_fdt_node_depth (rtems_fdt_handle* handle, int nodeoffset)
849{
850  if (!handle->blob)
851    return -RTEMS_FDT_ERR_INVALID_HANDLE;
852  return fdt_node_depth (handle->blob->blob, nodeoffset);
853}
854
855int
856rtems_fdt_parent_offset (rtems_fdt_handle* handle, int nodeoffset)
857{
858  if (!handle->blob)
859    return -RTEMS_FDT_ERR_INVALID_HANDLE;
860  return fdt_parent_offset (handle->blob->blob, nodeoffset);
861}
862
863int
864rtems_fdt_node_offset_by_prop_value (rtems_fdt_handle* handle,
865                                     int               startoffset,
866                                     const char*       propname,
867                                     const void*       propval,
868                                     int               proplen)
869{
870  if (!handle->blob)
871    return -RTEMS_FDT_ERR_INVALID_HANDLE;
872  return fdt_node_offset_by_prop_value (handle,
873                                        startoffset,
874                                        propname,
875                                        propval,
876                                        proplen);
877}
878
879int
880rtems_fdt_node_offset_by_phandle (rtems_fdt_handle* handle, uint32_t phandle)
881{
882  if (!handle->blob)
883    return -RTEMS_FDT_ERR_INVALID_HANDLE;
884  return fdt_node_offset_by_phandle (handle->blob->blob, phandle);
885}
886
887int
888rtems_fdt_node_check_compatible (rtems_fdt_handle* handle,
889                                 int               nodeoffset,
890                                 const char*       compatible)
891{
892  if (!handle->blob)
893    return -RTEMS_FDT_ERR_INVALID_HANDLE;
894  return fdt_node_check_compatible (handle, nodeoffset, compatible);
895}
896
897int
898rtems_fdt_node_offset_by_compatible (rtems_fdt_handle* handle,
899                                     int               startoffset,
900                                     const char*       compatible)
901{
902  if (!handle->blob)
903    return -RTEMS_FDT_ERR_INVALID_HANDLE;
904  return fdt_node_offset_by_compatible (handle->blob->blob,
905                                        startoffset,
906                                        compatible);
907}
908
909int
910rtems_fdt_next_node (rtems_fdt_handle* handle, int offset, int* depth)
911{
912  if (!handle->blob)
913    return -RTEMS_FDT_ERR_INVALID_HANDLE;
914  return fdt_next_node (handle->blob->blob, offset, depth);
915}
916
917const char*
918rtems_fdt_strerror (int errval)
919{
920  const char* errors[] = {
921    "invalid handle",
922    "no memory",
923    "file not found",
924    "DTB read fail",
925    "blob has references"
926  };
927  if (errval > -RTEMS_FDT_ERR_RTEMS_MIN)
928    return fdt_strerror (errval);
929  if (errval < -RTEMS_FDT_ERR_MAX)
930    return "invalid error code";
931  return errors[(-errval) - RTEMS_FDT_ERR_RTEMS_MIN];
932}
933
934int
935rtems_fdt_prop_value(const char* const path,
936                     const char* const propname,
937                     void*             value,
938                     size_t*           size)
939{
940  rtems_fdt_handle fdt;
941  int              node;
942  const void*      prop;
943  int              length;
944
945  rtems_fdt_init_handle (&fdt);
946
947  node = rtems_fdt_find_path_offset (&fdt, path);
948  if (node < 0)
949    return node;
950
951  prop = rtems_fdt_getprop(&fdt, node, propname, &length);
952  if (length < 0)
953  {
954    rtems_fdt_release_handle (&fdt);
955    return length;
956  }
957
958  if (length > (int) *size)
959  {
960    rtems_fdt_release_handle (&fdt);
961    return RTEMS_FDT_ERR_BADPATH;
962  }
963
964  *size = length;
965
966  memcpy (value, prop, length);
967
968  return 0;
969}
970
971int
972rtems_fdt_prop_map(const char* const path,
973                   const char* const propname,
974                   const char* const names[],
975                   uint32_t*         values,
976                   size_t            count)
977{
978  rtems_fdt_handle fdt;
979  int              node;
980  size_t           item;
981
982  rtems_fdt_init_handle (&fdt);
983
984  node = rtems_fdt_find_path_offset (&fdt, path);
985  if (node < 0)
986    return node;
987
988  for (item = 0; item < count; item++)
989  {
990    const void*    prop;
991    const uint8_t* p;
992    int            length;
993    int            subnode;
994
995    subnode = rtems_fdt_subnode_offset (&fdt, node, names[item]);
996    if (subnode < 0)
997    {
998      rtems_fdt_release_handle (&fdt);
999      return subnode;
1000    }
1001
1002    prop = rtems_fdt_getprop(&fdt, subnode, propname, &length);
1003    if (length < 0)
1004    {
1005      rtems_fdt_release_handle (&fdt);
1006      return length;
1007    }
1008
1009    if (length != sizeof (uint32_t))
1010    {
1011      rtems_fdt_release_handle (&fdt);
1012      return RTEMS_FDT_ERR_BADPATH;
1013    }
1014
1015    p = prop;
1016
1017    values[item] = ((((uint32_t) p[0]) << 24) |
1018                    (((uint32_t) p[1]) << 16) |
1019                    (((uint32_t) p[2]) << 8)  |
1020                    (uint32_t) p[3]);
1021  }
1022
1023  return 0;
1024}
1025
1026uint32_t
1027rtems_fdt_get_uint32 (const void* prop)
1028{
1029  const uint8_t* p = prop;
1030  uint32_t       value;
1031  value = ((((uint32_t) p[0]) << 24) |
1032           (((uint32_t) p[1]) << 16) |
1033           (((uint32_t) p[2]) << 8)  |
1034           (uint32_t) p[3]);
1035  return value;
1036}
1037
1038int
1039rtems_fdt_get_value (const char* path,
1040                     const char* property,
1041                     size_t      size,
1042                     uint32_t*   value)
1043{
1044  rtems_fdt_handle fdt;
1045  const void*      prop;
1046  int              node;
1047  int              length;
1048
1049  rtems_fdt_init_handle (&fdt);
1050
1051  node = rtems_fdt_find_path_offset (&fdt, path);
1052  if (node < 0)
1053  {
1054    rtems_fdt_release_handle (&fdt);
1055    return node;
1056  }
1057
1058  prop = rtems_fdt_getprop(&fdt, node, property, &length);
1059  if (length < 0)
1060  {
1061    rtems_fdt_release_handle (&fdt);
1062    return length;
1063  }
1064
1065  if (length == sizeof (uint32_t))
1066    *value = rtems_fdt_get_uint32 (prop);
1067  else
1068    *value = 0;
1069
1070  rtems_fdt_release_handle (&fdt);
1071
1072  return 0;
1073}
1074
1075/**
1076 * Get the number of entries in an FDT handle.
1077 */
1078int
1079rtems_fdt_num_entries(rtems_fdt_handle* handle)
1080{
1081  return handle->blob->index.num_entries;
1082}
1083
1084/**
1085 * Get the numbered entry name. Note that the id isn't the same as
1086 * the offset - it's numbered 0, 1, 2 ... num_entries-1
1087 */
1088const char *
1089rtems_fdt_entry_name(rtems_fdt_handle* handle, int id)
1090{
1091  return handle->blob->index.entries[id].name;
1092}
1093
1094/**
1095 * Get the numbered entry offset. Note that the id isn't the same as
1096 * the offset - it's numbered 0, 1, 2 ... num_entries-1
1097 */
1098int
1099rtems_fdt_entry_offset(rtems_fdt_handle* handle, int id)
1100{
1101  return handle->blob->index.entries[id].offset;
1102}
Note: See TracBrowser for help on using the repository browser.