iPXE
fdt.c
Go to the documentation of this file.
1 /*
2  * Copyright (C) 2019 Michael Brown <mbrown@fensystems.co.uk>.
3  *
4  * This program is free software; you can redistribute it and/or
5  * modify it under the terms of the GNU General Public License as
6  * published by the Free Software Foundation; either version 2 of the
7  * License, or (at your option) any later version.
8  *
9  * This program is distributed in the hope that it will be useful, but
10  * WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12  * General Public License for more details.
13  *
14  * You should have received a copy of the GNU General Public License
15  * along with this program; if not, write to the Free Software
16  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
17  * 02110-1301, USA.
18  *
19  * You can also choose to distribute this program under the terms of
20  * the Unmodified Binary Distribution Licence (as given in the file
21  * COPYING.UBDL), provided that you have satisfied its requirements.
22  */
23 
24 FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL );
25 
26 #include <string.h>
27 #include <ctype.h>
28 #include <errno.h>
29 #include <assert.h>
30 #include <byteswap.h>
31 #include <ipxe/netdevice.h>
32 #include <ipxe/image.h>
33 #include <ipxe/uaccess.h>
34 #include <ipxe/umalloc.h>
35 #include <ipxe/fdt.h>
36 
37 /** @file
38  *
39  * Flattened Device Tree
40  *
41  */
42 
43 /** The system flattened device tree (if present) */
44 struct fdt sysfdt;
45 
46 /** The downloaded flattened device tree tag */
47 struct image_tag fdt_image __image_tag = {
48  .name = "FDT",
49 };
50 
51 /** Amount of free space to add whenever we have to reallocate a tree */
52 #define FDT_INSERT_PAD 1024
53 
54 /**
55  * Check if character is permitted in a name
56  *
57  * @v ch Character
58  * @ret is_permitted Character is permitted in a name
59  */
60 static int fdt_permitted ( char ch ) {
61  static const char permitted[] = ",._+?#-";
62 
63  return ( isalnum ( ch ) || strchr ( permitted, ch ) );
64 }
65 
66 /**
67  * Compare node name
68  *
69  * @v desc Token descriptor
70  * @v name Name (terminated by NUL or any non-permitted character)
71  * @ret is_match Name matches token descriptor
72  */
73 static int fdt_match ( const struct fdt_descriptor *desc, const char *name ) {
74  size_t len = strlen ( desc->name );
75 
76  /* Check name and terminator */
77  return ( ( memcmp ( desc->name, name, len ) == 0 ) &&
78  ( ! ( name[len] && fdt_permitted ( name[len] ) ) ) );
79 }
80 
81 /**
82  * Describe device tree token
83  *
84  * @v fdt Device tree
85  * @v offset Offset within structure block
86  * @v desc Token descriptor to fill in
87  * @ret rc Return status code
88  */
89 int fdt_describe ( struct fdt *fdt, unsigned int offset,
90  struct fdt_descriptor *desc ) {
91  const fdt_token_t *token;
92  const void *data;
93  const struct fdt_prop *prop;
94  unsigned int name_off;
95  size_t remaining;
96  size_t len;
97 
98  /* Sanity checks */
99  assert ( offset <= fdt->len );
100  assert ( ( offset & ( FDT_STRUCTURE_ALIGN - 1 ) ) == 0 );
101 
102  /* Initialise descriptor */
103  memset ( desc, 0, sizeof ( *desc ) );
104  desc->offset = offset;
105 
106  /* Locate token and calculate remaining space */
107  token = ( fdt->raw + fdt->structure + offset );
108  remaining = ( fdt->len - offset );
109  if ( remaining < sizeof ( *token ) ) {
110  DBGC ( fdt, "FDT truncated tree at +%#04x\n", offset );
111  return -EINVAL;
112  }
113  remaining -= sizeof ( *token );
114  data = ( ( ( const void * ) token ) + sizeof ( *token ) );
115  len = 0;
116 
117  /* Handle token */
118  switch ( *token ) {
119 
120  case cpu_to_be32 ( FDT_BEGIN_NODE ):
121 
122  /* Start of node */
123  desc->name = data;
124  len = ( strnlen ( desc->name, remaining ) + 1 /* NUL */ );
125  if ( remaining < len ) {
126  DBGC ( fdt, "FDT unterminated node name at +%#04x\n",
127  offset );
128  return -EINVAL;
129  }
130  desc->depth = +1;
131  break;
132 
133  case cpu_to_be32 ( FDT_END_NODE ):
134 
135  /* End of node */
136  desc->depth = -1;
137  break;
138 
139  case cpu_to_be32 ( FDT_PROP ):
140 
141  /* Property */
142  prop = data;
143  if ( remaining < sizeof ( *prop ) ) {
144  DBGC ( fdt, "FDT truncated property at +%#04x\n",
145  offset );
146  return -EINVAL;
147  }
148  desc->data = ( ( ( const void * ) prop ) + sizeof ( *prop ) );
149  desc->len = be32_to_cpu ( prop->len );
150  len = ( sizeof ( *prop ) + desc->len );
151  if ( remaining < len ) {
152  DBGC ( fdt, "FDT overlength property at +%#04x\n",
153  offset );
154  return -EINVAL;
155  }
156  name_off = be32_to_cpu ( prop->name_off );
157  if ( name_off > fdt->strings_len ) {
158  DBGC ( fdt, "FDT property name outside strings "
159  "block at +%#04x\n", offset );
160  return -EINVAL;
161  }
162  desc->name = ( fdt->raw + fdt->strings + name_off );
163  break;
164 
165  case cpu_to_be32 ( FDT_NOP ):
166 
167  /* Do nothing */
168  break;
169 
170  default:
171 
172  /* Unrecognised or unexpected token */
173  DBGC ( fdt, "FDT unexpected token %#08x at +%#04x\n",
174  be32_to_cpu ( *token ), offset );
175  return -EINVAL;
176  }
177 
178  /* Calculate offset to next token */
179  len = ( ( len + FDT_STRUCTURE_ALIGN - 1 ) &
180  ~( FDT_STRUCTURE_ALIGN - 1 ) );
181  offset += ( sizeof ( *token ) + len );
182  desc->next = offset;
183 
184  /* Sanity checks */
185  assert ( offset <= fdt->len );
186 
187  return 0;
188 }
189 
190 /**
191  * Describe next device tree token
192  *
193  * @v fdt Device tree
194  * @v desc Token descriptor to update
195  * @ret rc Return status code
196  */
197 static int fdt_next ( struct fdt *fdt, struct fdt_descriptor *desc ) {
198 
199  /* Describe next token */
200  return fdt_describe ( fdt, desc->next, desc );
201 }
202 
203 /**
204  * Enter node
205  *
206  * @v fdt Device tree
207  * @v offset Starting node offset
208  * @v desc Begin node descriptor to fill in
209  * @ret rc Return status code
210  */
211 static int fdt_enter ( struct fdt *fdt, unsigned int offset,
212  struct fdt_descriptor *desc ) {
213  int rc;
214 
215  /* Find begin node token */
216  for ( ; ; offset = desc->next ) {
217 
218  /* Describe token */
219  if ( ( rc = fdt_describe ( fdt, offset, desc ) ) != 0 ) {
220  DBGC ( fdt, "FDT +%#04x has malformed node: %s\n",
221  offset, strerror ( rc ) );
222  return rc;
223  }
224 
225  /* Check for begin node token */
226  if ( desc->depth > 0 )
227  return 0;
228 
229  /* Check for non-NOPs */
230  if ( desc->depth ) {
231  DBGC ( fdt, "FDT +%#04x has spurious node end at "
232  "+%#04x\n", offset, desc->offset );
233  return -EINVAL;
234  }
235  if ( desc->name ) {
236  DBGC ( fdt, "FDT +%#04x has spurious property at "
237  "+%#04x\n", offset, desc->offset );
238  return -EINVAL;
239  }
240  }
241 }
242 
243 /**
244  * Find node relative depth
245  *
246  * @v fdt Device tree
247  * @v offset Starting node offset
248  * @v target Target node offset
249  * @ret depth Depth, or negative error
250  */
251 static int fdt_depth ( struct fdt *fdt, unsigned int offset,
252  unsigned int target ) {
253  struct fdt_descriptor desc;
254  int depth;
255  int rc;
256 
257  /* Enter node */
258  if ( ( rc = fdt_enter ( fdt, offset, &desc ) ) != 0 )
259  return rc;
260 
261  /* Find target node */
262  for ( depth = 0 ; depth >= 0 ; depth += desc.depth ) {
263 
264  /* Describe token */
265  if ( ( rc = fdt_next ( fdt, &desc ) ) != 0 ) {
266  DBGC ( fdt, "FDT +%#04x has malformed node: %s\n",
267  offset, strerror ( rc ) );
268  return rc;
269  }
270 
271  /* Check for target node */
272  if ( desc.offset == target ) {
273  DBGC2 ( fdt, "FDT +%#04x has descendant node +%#04x "
274  "at depth +%d\n", offset, target, depth );
275  return depth;
276  }
277  }
278 
279  DBGC ( fdt, "FDT +#%04x has no descendant node +%#04x\n",
280  offset, target );
281  return -ENOENT;
282 }
283 
284 /**
285  * Find parent node
286  *
287  * @v fdt Device tree
288  * @v offset Starting node offset
289  * @v parent Parent node offset to fill in
290  * @ret rc Return status code
291  */
292 int fdt_parent ( struct fdt *fdt, unsigned int offset, unsigned int *parent ) {
293  struct fdt_descriptor desc;
294  int pdepth;
295  int depth;
296  int rc;
297 
298  /* Find depth from root of tree */
299  depth = fdt_depth ( fdt, 0, offset );
300  if ( depth < 0 ) {
301  rc = depth;
302  return rc;
303  }
304  pdepth = ( depth - 1 );
305 
306  /* Enter root node */
307  if ( ( rc = fdt_enter ( fdt, 0, &desc ) ) != 0 )
308  return rc;
309  *parent = desc.offset;
310 
311  /* Find parent node */
312  for ( depth = 0 ; depth >= 0 ; depth += desc.depth ) {
313 
314  /* Describe token */
315  if ( ( rc = fdt_next ( fdt, &desc ) ) != 0 ) {
316  DBGC ( fdt, "FDT +%#04x has malformed node: %s\n",
317  offset, strerror ( rc ) );
318  return rc;
319  }
320 
321  /* Record possible parent node */
322  if ( ( depth == pdepth ) && desc.name && ( ! desc.data ) )
323  *parent = desc.offset;
324 
325  /* Check for target node */
326  if ( desc.offset == offset ) {
327  DBGC2 ( fdt, "FDT +%#04x has parent node at +%#04x\n",
328  offset, *parent );
329  return 0;
330  }
331  }
332 
333  DBGC ( fdt, "FDT +#%04x has no parent node\n", offset );
334  return -ENOENT;
335 }
336 
337 /**
338  * Find child node
339  *
340  * @v fdt Device tree
341  * @v offset Starting node offset
342  * @v name Node name
343  * @v child Child node offset to fill in
344  * @ret rc Return status code
345  */
346 static int fdt_child ( struct fdt *fdt, unsigned int offset, const char *name,
347  unsigned int *child ) {
348  struct fdt_descriptor desc;
349  int depth;
350  int rc;
351 
352  /* Enter node */
353  if ( ( rc = fdt_enter ( fdt, offset, &desc ) ) != 0 )
354  return rc;
355 
356  /* Find child node */
357  for ( depth = 0 ; depth >= 0 ; depth += desc.depth ) {
358 
359  /* Describe token */
360  if ( ( rc = fdt_next ( fdt, &desc ) ) != 0 ) {
361  DBGC ( fdt, "FDT +%#04x has malformed node: %s\n",
362  offset, strerror ( rc ) );
363  return rc;
364  }
365 
366  /* Check for matching immediate child node */
367  if ( ( depth == 0 ) && desc.name && ( ! desc.data ) ) {
368  DBGC2 ( fdt, "FDT +%#04x has child node \"%s\" at "
369  "+%#04x\n", offset, desc.name, desc.offset );
370  assert ( desc.depth > 0 );
371  if ( fdt_match ( &desc, name ) ) {
372  *child = desc.offset;
373  return 0;
374  }
375  }
376  }
377 
378  DBGC2 ( fdt, "FDT +%#04x has no child node \"%s\"\n", offset, name );
379  return -ENOENT;
380 }
381 
382 /**
383  * Find end of node
384  *
385  * @v fdt Device tree
386  * @v offset Starting node offset
387  * @v end End of node offset to fill in
388  * @ret rc Return status code
389  */
390 static int fdt_end ( struct fdt *fdt, unsigned int offset,
391  unsigned int *end ) {
392  struct fdt_descriptor desc;
393  int depth;
394  int rc;
395 
396  /* Enter node */
397  if ( ( rc = fdt_enter ( fdt, offset, &desc ) ) != 0 )
398  return rc;
399 
400  /* Find end of this node */
401  for ( depth = 0 ; depth >= 0 ; depth += desc.depth ) {
402 
403  /* Describe token */
404  if ( ( rc = fdt_next ( fdt, &desc ) ) != 0 ) {
405  DBGC ( fdt, "FDT +%#04x has malformed node: %s\n",
406  offset, strerror ( rc ) );
407  return rc;
408  }
409  }
410 
411  /* Record end offset */
412  *end = desc.offset;
413  DBGC2 ( fdt, "FDT +%#04x has end at +%#04x\n", offset, *end );
414  return 0;
415 }
416 
417 /**
418  * Find node by path
419  *
420  * @v fdt Device tree
421  * @v path Node path
422  * @v offset Offset to fill in
423  * @ret rc Return status code
424  */
425 int fdt_path ( struct fdt *fdt, const char *path, unsigned int *offset ) {
426  const char *tmp = path;
427  int rc;
428 
429  /* Initialise offset */
430  *offset = 0;
431 
432  /* Traverse tree one path segment at a time */
433  while ( 1 ) {
434 
435  /* Skip any leading '/' */
436  while ( *tmp == '/' )
437  tmp++;
438 
439  /* Terminate if there are no more path components */
440  if ( ! *tmp )
441  break;
442 
443  /* Find child */
444  if ( ( rc = fdt_child ( fdt, *offset, tmp, offset ) ) != 0 )
445  return rc;
446 
447  /* Move to next path component, if any */
448  tmp = strchr ( tmp, '/' );
449  if ( ! tmp )
450  break;
451  }
452 
453  DBGC2 ( fdt, "FDT found path \"%s\" at +%#04x\n", path, *offset );
454  return 0;
455 }
456 
457 /**
458  * Find node by alias
459  *
460  * @v fdt Device tree
461  * @v name Alias name
462  * @v offset Offset to fill in
463  * @ret rc Return status code
464  */
465 int fdt_alias ( struct fdt *fdt, const char *name, unsigned int *offset ) {
466  const char *alias;
467  int rc;
468 
469  /* Locate "/aliases" node */
470  if ( ( rc = fdt_child ( fdt, 0, "aliases", offset ) ) != 0 )
471  return rc;
472 
473  /* Locate alias property */
474  if ( ( alias = fdt_string ( fdt, *offset, name ) ) == NULL )
475  return -ENOENT;
476  DBGC ( fdt, "FDT alias \"%s\" is \"%s\"\n", name, alias );
477 
478  /* Locate aliased node */
479  if ( ( rc = fdt_path ( fdt, alias, offset ) ) != 0 )
480  return rc;
481 
482  return 0;
483 }
484 
485 /**
486  * Find property
487  *
488  * @v fdt Device tree
489  * @v offset Starting node offset
490  * @v name Property name
491  * @v desc Token descriptor to fill in
492  * @ret rc Return status code
493  */
494 static int fdt_property ( struct fdt *fdt, unsigned int offset,
495  const char *name, struct fdt_descriptor *desc ) {
496  int depth;
497  int rc;
498 
499  /* Enter node */
500  if ( ( rc = fdt_enter ( fdt, offset, desc ) ) != 0 )
501  return rc;
502 
503  /* Find property */
504  for ( depth = 0 ; depth == 0 ; depth += desc->depth ) {
505 
506  /* Describe token */
507  if ( ( rc = fdt_next ( fdt, desc ) ) != 0 ) {
508  DBGC ( fdt, "FDT +%#04x has malformed node: %s\n",
509  offset, strerror ( rc ) );
510  return rc;
511  }
512 
513  /* Check for matching immediate child property */
514  if ( desc->data ) {
515  DBGC2 ( fdt, "FDT +%#04x has property \"%s\" at "
516  "+%#04x len %#zx\n", offset, desc->name,
517  desc->offset, desc->len );
518  assert ( desc->depth == 0 );
519  if ( fdt_match ( desc, name ) ) {
520  DBGC2_HDA ( fdt, 0, desc->data, desc->len );
521  return 0;
522  }
523  }
524  }
525 
526  DBGC2 ( fdt, "FDT +%#04x has no property \"%s\"\n", offset, name );
527  return -ENOENT;
528 }
529 
530 /**
531  * Find strings property
532  *
533  * @v fdt Device tree
534  * @v offset Starting node offset
535  * @v name Property name
536  * @v count String count to fill in
537  * @ret string String property, or NULL on error
538  */
539 const char * fdt_strings ( struct fdt *fdt, unsigned int offset,
540  const char *name, unsigned int *count ) {
541  struct fdt_descriptor desc;
542  const char *data;
543  size_t len;
544  int rc;
545 
546  /* Return a zero count on error */
547  *count = 0;
548 
549  /* Find property */
550  if ( ( rc = fdt_property ( fdt, offset, name, &desc ) ) != 0 )
551  return NULL;
552 
553  /* Check NUL termination */
554  data = desc.data;
555  if ( desc.len && ( data[ desc.len - 1 ] != '\0' ) ) {
556  DBGC ( fdt, "FDT unterminated string property \"%s\"\n",
557  name );
558  return NULL;
559  }
560 
561  /* Count number of strings */
562  for ( len = desc.len ; len-- ; ) {
563  if ( data[len] == '\0' )
564  (*count)++;
565  }
566 
567  return data;
568 }
569 
570 /**
571  * Find string property
572  *
573  * @v fdt Device tree
574  * @v offset Starting node offset
575  * @v name Property name
576  * @ret string String property, or NULL on error
577  */
578 const char * fdt_string ( struct fdt *fdt, unsigned int offset,
579  const char *name ) {
580  unsigned int count;
581 
582  /* Find strings property */
583  return fdt_strings ( fdt, offset, name, &count );
584 }
585 
586 /**
587  * Get integer property
588  *
589  * @v fdt Device tree
590  * @v offset Starting node offset
591  * @v name Property name
592  * @v index Starting cell index
593  * @v count Number of cells (or 0 to read all remaining cells)
594  * @v value Integer value to fill in
595  * @ret rc Return status code
596  */
597 int fdt_cells ( struct fdt *fdt, unsigned int offset, const char *name,
598  unsigned int index, unsigned int count, uint64_t *value ) {
599  struct fdt_descriptor desc;
600  const uint32_t *cell;
601  unsigned int total;
602  int rc;
603 
604  /* Clear value */
605  *value = 0;
606 
607  /* Find property */
608  if ( ( rc = fdt_property ( fdt, offset, name, &desc ) ) != 0 )
609  return rc;
610  cell = desc.data;
611 
612  /* Determine number of cells */
613  total = ( desc.len / sizeof ( *cell ) );
614  if ( ( index > total ) || ( count > ( total - index ) ) ) {
615  DBGC ( fdt, "FDT truncated integer \"%s\"\n", name );
616  return -ERANGE;
617  }
618  if ( ! count )
619  count = ( total - index );
620  if ( count > ( sizeof ( *value ) / sizeof ( *cell ) ) ) {
621  DBGC ( fdt, "FDT overlength integer \"%s\"\n", name );
622  return -ERANGE;
623  }
624 
625  /* Read value */
626  for ( cell += index ; count ; cell++, count-- ) {
627  *value <<= 32;
628  *value |= be32_to_cpu ( *cell );
629  }
630 
631  return 0;
632 }
633 
634 /**
635  * Get 64-bit integer property
636  *
637  * @v fdt Device tree
638  * @v offset Starting node offset
639  * @v name Property name
640  * @v value Integer value to fill in
641  * @ret rc Return status code
642  */
643 int fdt_u64 ( struct fdt *fdt, unsigned int offset, const char *name,
644  uint64_t *value ) {
645  int rc;
646 
647  /* Read value */
648  if ( ( rc = fdt_cells ( fdt, offset, name, 0, 0, value ) ) != 0 )
649  return rc;
650 
651  return 0;
652 }
653 
654 /**
655  * Get 32-bit integer property
656  *
657  * @v fdt Device tree
658  * @v offset Starting node offset
659  * @v name Property name
660  * @v value Integer value to fill in
661  * @ret rc Return status code
662  */
663 int fdt_u32 ( struct fdt *fdt, unsigned int offset, const char *name,
664  uint32_t *value ) {
665  uint64_t value64;
666  int rc;
667 
668  /* Read value */
669  if ( ( rc = fdt_u64 ( fdt, offset, name, &value64 ) ) != 0 )
670  return rc;
671 
672  /* Check range */
673  *value = value64;
674  if ( *value != value64 ) {
675  DBGC ( fdt, "FDT overlength 32-bit integer \"%s\"\n", name );
676  return -ERANGE;
677  }
678 
679  return 0;
680 }
681 
682 /**
683  * Get package handle (phandle) property
684  *
685  * @v fdt Device tree
686  * @v offset Starting node offset
687  * @ret phandle Package handle, or 0 on error
688  */
689 uint32_t fdt_phandle ( struct fdt *fdt, unsigned int offset ) {
690  uint32_t phandle;
691  int rc;
692 
693  /* Get "phandle" or "linux,phandle" property */
694  if ( ( ( rc = fdt_u32 ( fdt, offset, "phandle", &phandle ) ) == 0 ) ||
695  ( ( rc = fdt_u32 ( fdt, offset, "linux,phandle",
696  &phandle ) ) == 0 ) ) {
697  assert ( phandle != 0 );
698  return phandle;
699  }
700 
701  return 0;
702 }
703 
704 /**
705  * Get region cell size specification
706  *
707  * @v fdt Device tree
708  * @v offset Starting (parent) node offset
709  * @v regs Region cell size specification to fill in
710  *
711  * Note that #address-cells and #size-cells are defined on the
712  * immediate parent node, rather than on the node with the "reg"
713  * property itself.
714  */
715 void fdt_reg_cells ( struct fdt *fdt, unsigned int offset,
716  struct fdt_reg_cells *regs ) {
717  int rc;
718 
719  /* Read #address-cells, if present */
720  if ( ( rc = fdt_u32 ( fdt, offset, "#address-cells",
721  &regs->address_cells ) ) != 0 ) {
722  regs->address_cells = FDT_DEFAULT_ADDRESS_CELLS;
723  }
724 
725  /* Read #size-cells, if present */
726  if ( ( rc = fdt_u32 ( fdt, offset, "#size-cells",
727  &regs->size_cells ) ) != 0 ) {
728  regs->size_cells = FDT_DEFAULT_SIZE_CELLS;
729  }
730 
731  /* Calculate stride */
732  regs->stride = ( regs->address_cells + regs->size_cells );
733 }
734 
735 /**
736  * Get parent region cell size specification
737  *
738  * @v fdt Device tree
739  * @v offset Starting node offset
740  * @v regs Region cell size specification to fill in
741  * @ret rc Return status code
742  */
743 int fdt_parent_reg_cells ( struct fdt *fdt, unsigned int offset,
744  struct fdt_reg_cells *regs ) {
745  unsigned int parent;
746  int rc;
747 
748  /* Get parent node */
749  if ( ( rc = fdt_parent ( fdt, offset, &parent ) ) != 0 )
750  return rc;
751 
752  /* Read #address-cells and #size-cells, if present */
753  fdt_reg_cells ( fdt, parent, regs );
754 
755  return 0;
756 }
757 
758 /**
759  * Get number of regions
760  *
761  * @v fdt Device tree
762  * @v offset Starting node offset
763  * @v regs Region cell size specification
764  * @ret count Number of regions, or negative error
765  */
766 int fdt_reg_count ( struct fdt *fdt, unsigned int offset,
767  struct fdt_reg_cells *regs ) {
768  struct fdt_descriptor desc;
769  const uint32_t *cell;
770  unsigned int count;
771  int rc;
772 
773  /* Find property */
774  if ( ( rc = fdt_property ( fdt, offset, "reg", &desc ) ) != 0 )
775  return rc;
776 
777  /* Determine number of regions */
778  count = ( desc.len / ( regs->stride * sizeof ( *cell ) ) );
779  return count;
780 }
781 
782 /**
783  * Get region address
784  *
785  * @v fdt Device tree
786  * @v offset Starting node offset
787  * @v regs Region cell size specification
788  * @v index Region index
789  * @v address Region starting address to fill in
790  * @ret rc Return status code
791  */
792 int fdt_reg_address ( struct fdt *fdt, unsigned int offset,
793  struct fdt_reg_cells *regs, unsigned int index,
794  uint64_t *address ) {
795  unsigned int cell = ( index * regs->stride );
796  int rc;
797 
798  /* Read relevant portion of region array */
799  if ( ( rc = fdt_cells ( fdt, offset, "reg", cell, regs->address_cells,
800  address ) ) != 0 ) {
801  return rc;
802  }
803 
804  return 0;
805 }
806 
807 /**
808  * Get region size
809  *
810  * @v fdt Device tree
811  * @v offset Starting node offset
812  * @v regs Region cell size specification
813  * @v index Region index
814  * @v size Region size to fill in
815  * @ret rc Return status code
816  */
817 int fdt_reg_size ( struct fdt *fdt, unsigned int offset,
818  struct fdt_reg_cells *regs, unsigned int index,
819  uint64_t *size ) {
820  unsigned int cell = ( ( index * regs->stride ) + regs->address_cells );
821  int rc;
822 
823  /* Read relevant portion of region array */
824  if ( ( rc = fdt_cells ( fdt, offset, "reg", cell, regs->size_cells,
825  size ) ) != 0 ) {
826  return rc;
827  }
828 
829  return 0;
830 }
831 
832 /**
833  * Get unsized single-entry region address
834  *
835  * @v fdt Device tree
836  * @v offset Starting node offset
837  * @v address Region address to fill in
838  * @ret rc Return status code
839  *
840  * Many region types (e.g. I2C bus addresses) can only ever contain a
841  * single region with no size cells specified.
842  */
843 int fdt_reg ( struct fdt *fdt, unsigned int offset, uint64_t *region ) {
844  struct fdt_reg_cells regs;
845  int rc;
846 
847  /* Get parent region cell size specification */
848  if ( ( rc = fdt_parent_reg_cells ( fdt, offset, &regs ) ) != 0 )
849  return rc;
850 
851  /* Get first region address */
852  if ( ( rc = fdt_reg_address ( fdt, offset, &regs, 0, region ) ) != 0 )
853  return rc;
854 
855  return 0;
856 }
857 
858 /**
859  * Get MAC address from property
860  *
861  * @v fdt Device tree
862  * @v offset Starting node offset
863  * @v netdev Network device
864  * @ret rc Return status code
865  */
866 int fdt_mac ( struct fdt *fdt, unsigned int offset,
867  struct net_device *netdev ) {
868  struct fdt_descriptor desc;
869  size_t len;
870  int rc;
871 
872  /* Find applicable MAC address property */
873  if ( ( ( rc = fdt_property ( fdt, offset, "mac-address",
874  &desc ) ) != 0 ) &&
875  ( ( rc = fdt_property ( fdt, offset, "local-mac-address",
876  &desc ) ) != 0 ) ) {
877  return rc;
878  }
879 
880  /* Check length */
882  if ( len != desc.len ) {
883  DBGC ( fdt, "FDT malformed MAC address \"%s\":\n",
884  desc.name );
885  DBGC_HDA ( fdt, 0, desc.data, desc.len );
886  return -ERANGE;
887  }
888 
889  /* Fill in MAC address */
890  memcpy ( netdev->hw_addr, desc.data, len );
891 
892  return 0;
893 }
894 
895 /**
896  * Parse device tree
897  *
898  * @v fdt Device tree
899  * @v hdr Device tree header
900  * @v max_len Maximum device tree length
901  * @ret rc Return status code
902  */
903 int fdt_parse ( struct fdt *fdt, struct fdt_header *hdr, size_t max_len ) {
904  const uint8_t *nul;
905  unsigned int chosen;
906  size_t end;
907 
908  /* Sanity check */
909  if ( sizeof ( *hdr ) > max_len ) {
910  DBGC ( fdt, "FDT length %#zx too short for header\n",
911  max_len );
912  goto err;
913  }
914 
915  /* Record device tree location */
916  fdt->hdr = hdr;
917  fdt->len = be32_to_cpu ( hdr->totalsize );
918  fdt->used = sizeof ( *hdr );
919  if ( fdt->len > max_len ) {
920  DBGC ( fdt, "FDT has invalid length %#zx / %#zx\n",
921  fdt->len, max_len );
922  goto err;
923  }
924  DBGC ( fdt, "FDT version %d at %p+%#04zx (phys %#08lx)\n",
925  be32_to_cpu ( hdr->version ), fdt->hdr, fdt->len,
926  virt_to_phys ( hdr ) );
927 
928  /* Check signature */
929  if ( hdr->magic != cpu_to_be32 ( FDT_MAGIC ) ) {
930  DBGC ( fdt, "FDT has invalid magic value %#08x\n",
931  be32_to_cpu ( hdr->magic ) );
932  goto err;
933  }
934 
935  /* Check version */
936  if ( hdr->last_comp_version != cpu_to_be32 ( FDT_VERSION ) ) {
937  DBGC ( fdt, "FDT unsupported version %d\n",
938  be32_to_cpu ( hdr->last_comp_version ) );
939  goto err;
940  }
941 
942  /* Record structure block location */
943  fdt->structure = be32_to_cpu ( hdr->off_dt_struct );
944  fdt->structure_len = be32_to_cpu ( hdr->size_dt_struct );
945  DBGC ( fdt, "FDT structure block at +[%#04x,%#04zx)\n",
947  if ( ( fdt->structure > fdt->len ) ||
948  ( fdt->structure_len > ( fdt->len - fdt->structure ) ) ) {
949  DBGC ( fdt, "FDT structure block exceeds table\n" );
950  goto err;
951  }
952  if ( ( fdt->structure | fdt->structure_len ) &
953  ( FDT_STRUCTURE_ALIGN - 1 ) ) {
954  DBGC ( fdt, "FDT structure block is misaligned\n" );
955  goto err;
956  }
957  end = ( fdt->structure + fdt->structure_len );
958  if ( fdt->used < end )
959  fdt->used = end;
960 
961  /* Record strings block location */
962  fdt->strings = be32_to_cpu ( hdr->off_dt_strings );
963  fdt->strings_len = be32_to_cpu ( hdr->size_dt_strings );
964  DBGC ( fdt, "FDT strings block at +[%#04x,%#04zx)\n",
965  fdt->strings, ( fdt->strings + fdt->strings_len ) );
966  if ( ( fdt->strings > fdt->len ) ||
967  ( fdt->strings_len > ( fdt->len - fdt->strings ) ) ) {
968  DBGC ( fdt, "FDT strings block exceeds table\n" );
969  goto err;
970  }
971  end = ( fdt->strings + fdt->strings_len );
972  if ( fdt->used < end )
973  fdt->used = end;
974 
975  /* Shrink strings block to ensure NUL termination safety */
976  nul = ( fdt->raw + fdt->strings + fdt->strings_len );
977  for ( ; fdt->strings_len ; fdt->strings_len-- ) {
978  if ( *(--nul) == '\0' )
979  break;
980  }
981  if ( fdt->strings_len != be32_to_cpu ( hdr->size_dt_strings ) ) {
982  DBGC ( fdt, "FDT strings block shrunk to +[%#04x,%#04zx)\n",
983  fdt->strings, ( fdt->strings + fdt->strings_len ) );
984  }
985 
986  /* Record memory reservation block location */
987  fdt->reservations = be32_to_cpu ( hdr->off_mem_rsvmap );
988  DBGC ( fdt, "FDT memory reservations at +[%#04x,...)\n",
989  fdt->reservations );
990  if ( fdt->used <= fdt->reservations ) {
991  /* No size field exists: assume whole table is used */
992  fdt->used = fdt->len;
993  }
994 
995  /* Identify free space (if any) */
996  if ( fdt->used < fdt->len ) {
997  DBGC ( fdt, "FDT free space at +[%#04zx,%#04zx)\n",
998  fdt->used, fdt->len );
999  }
1000 
1001  /* Print model name and boot arguments (for debugging) */
1002  if ( DBG_LOG ) {
1003  DBGC ( fdt, "FDT model is \"%s\"\n",
1004  fdt_string ( fdt, 0, "model" ) );
1005  if ( fdt_child ( fdt, 0, "chosen", &chosen ) == 0 ) {
1006  DBGC ( fdt, "FDT boot arguments \"%s\"\n",
1007  fdt_string ( fdt, chosen, "bootargs" ) );
1008  }
1009  }
1010 
1011  return 0;
1012 
1013  err:
1014  DBGC_HDA ( fdt, 0, hdr, sizeof ( *hdr ) );
1015  memset ( fdt, 0, sizeof ( *fdt ) );
1016  return -EINVAL;
1017 }
1018 
1019 /**
1020  * Parse device tree image
1021  *
1022  * @v fdt Device tree
1023  * @v image Image
1024  * @ret rc Return status code
1025  */
1026 static int fdt_parse_image ( struct fdt *fdt, struct image *image ) {
1027  int rc;
1028 
1029  /* Parse image */
1030  if ( ( rc = fdt_parse ( fdt, image->rwdata, image->len ) ) != 0 ) {
1031  DBGC ( fdt, "FDT image \"%s\" is invalid: %s\n",
1032  image->name, strerror ( rc ) );
1033  return rc;
1034  }
1035 
1036  DBGC ( fdt, "FDT image is \"%s\"\n", image->name );
1037  return 0;
1038 }
1039 
1040 /**
1041  * Insert empty space
1042  *
1043  * @v fdt Device tree
1044  * @v offset Offset at which to insert space
1045  * @v len Length to insert (must be a multiple of FDT_MAX_ALIGN)
1046  * @ret rc Return status code
1047  */
1048 static int fdt_insert ( struct fdt *fdt, unsigned int offset, size_t len ) {
1049  size_t free;
1050  size_t new;
1051  int rc;
1052 
1053  /* Sanity checks */
1054  assert ( offset <= fdt->used );
1055  assert ( fdt->used <= fdt->len );
1056  assert ( ( len % FDT_MAX_ALIGN ) == 0 );
1057 
1058  /* Reallocate tree if necessary */
1059  free = ( fdt->len - fdt->used );
1060  if ( free < len ) {
1061  if ( ! fdt->realloc ) {
1062  DBGC ( fdt, "FDT is not reallocatable\n" );
1063  return -ENOTSUP;
1064  }
1065  new = ( fdt->len + ( len - free ) + FDT_INSERT_PAD );
1066  if ( ( rc = fdt->realloc ( fdt, new ) ) != 0 )
1067  return rc;
1068  }
1069  assert ( ( fdt->used + len ) <= fdt->len );
1070 
1071  /* Insert empty space */
1072  memmove ( ( fdt->raw + offset + len ), ( fdt->raw + offset ),
1073  ( fdt->used - offset ) );
1074  memset ( ( fdt->raw + offset ), 0, len );
1075  fdt->used += len;
1076 
1077  /* Update offsets
1078  *
1079  * We assume that we never need to legitimately insert data at
1080  * the start of a block, and therefore can unambiguously
1081  * determine which block offsets need to be updated.
1082  *
1083  * It is the caller's responsibility to update the length (and
1084  * contents) of the block into which it has inserted space.
1085  */
1086  if ( fdt->structure >= offset ) {
1087  fdt->structure += len;
1089  DBGC ( fdt, "FDT structure block now at +[%#04x,%#04zx)\n",
1090  fdt->structure,
1091  ( fdt->structure + fdt->structure_len ) );
1092  }
1093  if ( fdt->strings >= offset ) {
1094  fdt->strings += len;
1096  DBGC ( fdt, "FDT strings block now at +[%#04x,%#04zx)\n",
1097  fdt->strings, ( fdt->strings + fdt->strings_len ) );
1098  }
1099  if ( fdt->reservations >= offset ) {
1100  fdt->reservations += len;
1102  DBGC ( fdt, "FDT memory reservations now at +[%#04x,...)\n",
1103  fdt->reservations );
1104  }
1105 
1106  return 0;
1107 }
1108 
1109 /**
1110  * Fill space in structure block with FDT_NOP
1111  *
1112  * @v fdt Device tree
1113  * @v offset Starting offset
1114  * @v len Length (must be a multiple of FDT_STRUCTURE_ALIGN)
1115  */
1116 static void fdt_nop ( struct fdt *fdt, unsigned int offset, size_t len ) {
1117  fdt_token_t *token;
1118  unsigned int count;
1119 
1120  /* Sanity check */
1121  assert ( ( len % FDT_STRUCTURE_ALIGN ) == 0 );
1122 
1123  /* Fill with FDT_NOP */
1124  token = ( fdt->raw + fdt->structure + offset );
1125  count = ( len / sizeof ( *token ) );
1126  while ( count-- )
1127  *(token++) = cpu_to_be32 ( FDT_NOP );
1128 }
1129 
1130 /**
1131  * Insert FDT_NOP padded space in structure block
1132  *
1133  * @v fdt Device tree
1134  * @v offset Offset at which to insert space
1135  * @v len Minimal length to insert
1136  * @ret rc Return status code
1137  */
1138 static int fdt_insert_nop ( struct fdt *fdt, unsigned int offset,
1139  size_t len ) {
1140  int rc;
1141 
1142  /* Sanity check */
1143  assert ( ( offset % FDT_STRUCTURE_ALIGN ) == 0 );
1144 
1145  /* Round up inserted length to maximal alignment */
1146  len = ( ( len + FDT_MAX_ALIGN - 1 ) & ~( FDT_MAX_ALIGN - 1 ) );
1147 
1148  /* Insert empty space in structure block */
1149  if ( ( rc = fdt_insert ( fdt, ( fdt->structure + offset ),
1150  len ) ) != 0 )
1151  return rc;
1152 
1153  /* Fill with NOPs */
1154  fdt_nop ( fdt, offset, len );
1155 
1156  /* Update structure block size */
1157  fdt->structure_len += len;
1159  DBGC ( fdt, "FDT structure block now at +[%#04x,%#04zx)\n",
1161 
1162  return 0;
1163 }
1164 
1165 /**
1166  * Insert string in strings block
1167  *
1168  * @v fdt Device tree
1169  * @v string String
1170  * @v offset String offset to fill in
1171  * @ret rc Return status code
1172  */
1173 static int fdt_insert_string ( struct fdt *fdt, const char *string,
1174  unsigned int *offset ) {
1175  size_t len = ( strlen ( string ) + 1 /* NUL */ );
1176  int rc;
1177 
1178  /* Round up inserted length to maximal alignment */
1179  len = ( ( len + FDT_MAX_ALIGN - 1 ) & ~( FDT_MAX_ALIGN - 1 ) );
1180 
1181  /* Insert space at end of strings block */
1182  if ( ( rc = fdt_insert ( fdt, ( fdt->strings + fdt->strings_len ),
1183  len ) ) != 0 )
1184  return rc;
1185 
1186  /* Append string to strings block */
1187  *offset = fdt->strings_len;
1188  strcpy ( ( fdt->raw + fdt->strings + *offset ), string );
1189 
1190  /* Update strings block size */
1191  fdt->strings_len += len;
1193  DBGC ( fdt, "FDT strings block now at +[%#04x,%#04zx)\n",
1194  fdt->strings, ( fdt->strings + fdt->strings_len ) );
1195 
1196  return 0;
1197 }
1198 
1199 /**
1200  * Ensure child node exists
1201  *
1202  * @v fdt Device tree
1203  * @v offset Starting node offset
1204  * @v name New node name
1205  * @v child Child node offset to fill in
1206  * @ret rc Return status code
1207  */
1208 static int fdt_ensure_child ( struct fdt *fdt, unsigned int offset,
1209  const char *name, unsigned int *child ) {
1210  size_t name_len = ( strlen ( name ) + 1 /* NUL */ );
1211  fdt_token_t *token;
1212  size_t len;
1213  int rc;
1214 
1215  /* Find existing child node, if any */
1216  if ( ( rc = fdt_child ( fdt, offset, name, child ) ) == 0 )
1217  return 0;
1218 
1219  /* Find end of parent node */
1220  if ( ( rc = fdt_end ( fdt, offset, child ) ) != 0 )
1221  return rc;
1222 
1223  /* Insert space for child node (with maximal alignment) */
1224  len = ( sizeof ( fdt_token_t ) /* BEGIN_NODE */ + name_len +
1225  sizeof ( fdt_token_t ) /* END_NODE */ );
1226  if ( ( rc = fdt_insert_nop ( fdt, *child, len ) ) != 0 )
1227  return rc;
1228 
1229  /* Construct node */
1230  token = ( fdt->raw + fdt->structure + *child );
1231  *(token++) = cpu_to_be32 ( FDT_BEGIN_NODE );
1232  memcpy ( token, name, name_len );
1233  name_len = ( ( name_len + FDT_STRUCTURE_ALIGN - 1 ) &
1234  ~( FDT_STRUCTURE_ALIGN - 1 ) );
1235  token = ( ( ( void * ) token ) + name_len );
1236  *(token++) = cpu_to_be32 ( FDT_END_NODE );
1237  DBGC2 ( fdt, "FDT +%#04x created child \"%s\" at +%#04x\n",
1238  offset, name, *child );
1239 
1240  return 0;
1241 }
1242 
1243 /**
1244  * Set property value
1245  *
1246  * @v fdt Device tree
1247  * @v offset Starting node offset
1248  * @v name Property name
1249  * @v data Property data, or NULL to delete property
1250  * @v len Length of property data
1251  * @ret rc Return status code
1252  */
1253 static int fdt_set ( struct fdt *fdt, unsigned int offset, const char *name,
1254  const void *data, size_t len ) {
1255  struct fdt_descriptor desc;
1256  struct {
1258  struct fdt_prop prop;
1259  uint8_t data[0];
1260  } __attribute__ (( packed )) *hdr;
1261  unsigned int string;
1262  size_t erase;
1263  size_t insert;
1264  int rc;
1265 
1266  /* Find and reuse existing property, if any */
1267  if ( ( rc = fdt_property ( fdt, offset, name, &desc ) ) == 0 ) {
1268 
1269  /* Reuse existing name */
1270  hdr = ( fdt->raw + fdt->structure + desc.offset );
1271  string = be32_to_cpu ( hdr->prop.name_off );
1272 
1273  /* Erase existing property */
1274  erase = ( sizeof ( *hdr ) + desc.len );
1275  erase = ( ( erase + FDT_STRUCTURE_ALIGN - 1 ) &
1276  ~( FDT_STRUCTURE_ALIGN - 1 ) );
1277  fdt_nop ( fdt, desc.offset, erase );
1278  DBGC2 ( fdt, "FDT +%#04x erased property \"%s\"\n",
1279  offset, name );
1280 
1281  /* Calculate insertion position and length */
1282  insert = ( ( desc.len < len ) ? ( len - desc.len ) : 0 );
1283 
1284  } else {
1285 
1286  /* Create name */
1287  if ( ( rc = fdt_insert_string ( fdt, name, &string ) ) != 0 )
1288  return rc;
1289 
1290  /* Enter node */
1291  if ( ( rc = fdt_enter ( fdt, offset, &desc ) ) != 0 )
1292  return rc;
1293  assert ( desc.depth > 0 );
1294  desc.offset = desc.next;
1295 
1296  /* Calculate insertion length */
1297  insert = ( sizeof ( *hdr ) + len );
1298  }
1299 
1300  /* Leave property erased if applicable */
1301  if ( ! data )
1302  return 0;
1303 
1304  /* Insert space */
1305  if ( ( rc = fdt_insert_nop ( fdt, desc.offset, insert ) ) != 0 )
1306  return rc;
1307 
1308  /* Construct property */
1309  hdr = ( fdt->raw + fdt->structure + desc.offset );
1310  hdr->token = cpu_to_be32 ( FDT_PROP );
1311  hdr->prop.len = cpu_to_be32 ( len );
1312  hdr->prop.name_off = cpu_to_be32 ( string );
1313  memset ( hdr->data, 0, ( ( len + FDT_STRUCTURE_ALIGN - 1 ) &
1314  ~( FDT_STRUCTURE_ALIGN - 1 ) ) );
1315  memcpy ( hdr->data, data, len );
1316  DBGC2 ( fdt, "FDT +%#04x created property \"%s\"\n", offset, name );
1317  DBGC2_HDA ( fdt, 0, hdr->data, len );
1318 
1319  return 0;
1320 }
1321 
1322 /**
1323  * Reallocate device tree via urealloc()
1324  *
1325  * @v fdt Device tree
1326  * @v len New total length
1327  * @ret rc Return status code
1328  */
1329 static int fdt_urealloc ( struct fdt *fdt, size_t len ) {
1330  void *new;
1331 
1332  /* Sanity check */
1333  assert ( len >= fdt->used );
1334 
1335  /* Attempt reallocation */
1336  new = urealloc ( fdt->raw, len );
1337  if ( ! new ) {
1338  DBGC ( fdt, "FDT could not reallocate from +%#04zx to "
1339  "+%#04zx\n", fdt->len, len );
1340  return -ENOMEM;
1341  }
1342  DBGC ( fdt, "FDT reallocated from +%#04zx to +%#04zx\n",
1343  fdt->len, len );
1344 
1345  /* Update device tree */
1346  fdt->raw = new;
1347  fdt->len = len;
1348  fdt->hdr->totalsize = cpu_to_be32 ( len );
1349 
1350  return 0;
1351 }
1352 
1353 /**
1354  * Populate device tree with boot arguments
1355  *
1356  * @v fdt Device tree
1357  * @v cmdline Command line, or NULL
1358  * @v initrd Initial ramdisk address (or 0 for no initrd)
1359  * @v initrd_len Initial ramdisk length (or 0 for no initrd)
1360  * @ret rc Return status code
1361  */
1362 static int fdt_bootargs ( struct fdt *fdt, const char *cmdline,
1363  physaddr_t initrd, size_t initrd_len ) {
1364  unsigned int chosen;
1365  physaddr_t addr;
1366  const void *data;
1367  size_t len;
1368  int rc;
1369 
1370  /* Ensure "chosen" node exists */
1371  if ( ( rc = fdt_ensure_child ( fdt, 0, "chosen", &chosen ) ) != 0 )
1372  return rc;
1373 
1374  /* Set or clear "bootargs" property */
1375  len = ( cmdline ? ( strlen ( cmdline ) + 1 /* NUL */ ) : 0 );
1376  if ( ( rc = fdt_set ( fdt, chosen, "bootargs", cmdline, len ) ) != 0 )
1377  return rc;
1378 
1379  /* Set or clear initrd properties */
1380  data = ( initrd_len ? &addr : NULL );
1381  len = ( initrd_len ? sizeof ( addr ) : 0 );
1382  addr = initrd;
1383  addr = ( ( sizeof ( addr ) == sizeof ( uint64_t ) ) ?
1384  cpu_to_be64 ( addr ) : cpu_to_be32 ( addr ) );
1385  if ( ( rc = fdt_set ( fdt, chosen, "linux,initrd-start", data,
1386  len ) ) != 0 )
1387  return rc;
1388  addr = ( initrd + initrd_len );
1389  addr = ( ( sizeof ( addr ) == sizeof ( uint64_t ) ) ?
1390  cpu_to_be64 ( addr ) : cpu_to_be32 ( addr ) );
1391  if ( ( rc = fdt_set ( fdt, chosen, "linux,initrd-end", data,
1392  len ) ) != 0 )
1393  return rc;
1394 
1395  return 0;
1396 }
1397 
1398 /**
1399  * Create device tree
1400  *
1401  * @v hdr Device tree header to fill in (may be set to NULL)
1402  * @v cmdline Command line, or NULL
1403  * @v initrd Initial ramdisk address (or 0 for no initrd)
1404  * @v initrd_len Initial ramdisk length (or 0 for no initrd)
1405  * @ret rc Return status code
1406  */
1407 int fdt_create ( struct fdt_header **hdr, const char *cmdline,
1408  physaddr_t initrd, size_t initrd_len ) {
1409  struct image *image;
1410  struct fdt fdt;
1411  void *copy;
1412  int rc;
1413 
1414  /* Use system FDT as the base by default */
1415  memcpy ( &fdt, &sysfdt, sizeof ( fdt ) );
1416 
1417  /* If an FDT image exists, use this instead */
1418  image = find_image_tag ( &fdt_image );
1419  if ( image && ( ( rc = fdt_parse_image ( &fdt, image ) ) != 0 ) )
1420  goto err_image;
1421 
1422  /* Exit successfully if we have no base FDT */
1423  if ( ! fdt.len ) {
1424  DBGC ( &fdt, "FDT has no base tree\n" );
1425  goto no_fdt;
1426  }
1427 
1428  /* Create modifiable copy */
1429  copy = umalloc ( fdt.len );
1430  if ( ! copy ) {
1431  rc = -ENOMEM;
1432  goto err_alloc;
1433  }
1434  memcpy ( copy, fdt.raw, fdt.len );
1435  fdt.raw = copy;
1437 
1438  /* Populate boot arguments */
1439  if ( ( rc = fdt_bootargs ( &fdt, cmdline, initrd, initrd_len ) ) != 0 )
1440  goto err_bootargs;
1441 
1442  no_fdt:
1443  *hdr = fdt.raw;
1444  return 0;
1445 
1446  err_bootargs:
1447  ufree ( fdt.raw );
1448  err_alloc:
1449  err_image:
1450  return rc;
1451 }
1452 
1453 /**
1454  * Remove device tree
1455  *
1456  * @v hdr Device tree header, or NULL
1457  */
1458 void fdt_remove ( struct fdt_header *hdr ) {
1459 
1460  /* Free modifiable copy */
1461  ufree ( hdr );
1462 }
1463 
1464 /* Drag in objects via fdt_describe() */
1466 
1467 /* Drag in device tree configuration */
1468 REQUIRE_OBJECT ( config_fdt );
int fdt_parent(struct fdt *fdt, unsigned int offset, unsigned int *parent)
Find parent node.
Definition: fdt.c:292
#define __attribute__(x)
Definition: compiler.h:10
static __always_inline void ufree(void *ptr)
Free external memory.
Definition: umalloc.h:67
#define EINVAL
Invalid argument.
Definition: errno.h:428
struct arbelprm_rc_send_wqe rc
Definition: arbel.h:14
const char * name
Definition: ath9k_hw.c:1984
int depth
Depth change.
Definition: fdt.h:132
static int fdt_match(const struct fdt_descriptor *desc, const char *name)
Compare node name.
Definition: fdt.c:73
#define FDT_STRUCTURE_ALIGN
Alignment of structure block.
Definition: fdt.h:74
#define FDT_NOP
NOP token.
Definition: fdt.h:68
unsigned int reservations
Offset to memory reservation block.
Definition: fdt.h:109
int erase(void)
Completely clear the screen.
Definition: clear.c:97
int fdt_alias(struct fdt *fdt, const char *name, unsigned int *offset)
Find node by alias.
Definition: fdt.c:465
An image tag.
Definition: image.h:172
int(* realloc)(struct fdt *fdt, size_t len)
Reallocate device tree.
Definition: fdt.h:116
static int fdt_urealloc(struct fdt *fdt, size_t len)
Reallocate device tree via urealloc()
Definition: fdt.c:1329
Error codes.
size_t len
Length of tree.
Definition: fdt.h:97
int fdt_parse(struct fdt *fdt, struct fdt_header *hdr, size_t max_len)
Parse device tree.
Definition: fdt.c:903
Device tree header.
Definition: fdt.h:18
struct golan_inbox_hdr hdr
Message header.
Definition: CIB_PRM.h:28
static int fdt_enter(struct fdt *fdt, unsigned int offset, struct fdt_descriptor *desc)
Enter node.
Definition: fdt.c:211
static int fdt_set(struct fdt *fdt, unsigned int offset, const char *name, const void *data, size_t len)
Set property value.
Definition: fdt.c:1253
uint64_t address
Base address.
Definition: ena.h:24
void * raw
Raw data.
Definition: fdt.h:94
uint16_t size
Buffer size.
Definition: dwmac.h:14
int fdt_describe(struct fdt *fdt, unsigned int offset, struct fdt_descriptor *desc)
Describe device tree token.
Definition: fdt.c:89
int fdt_path(struct fdt *fdt, const char *path, unsigned int *offset)
Find node by path.
Definition: fdt.c:425
#define DBGC(...)
Definition: compiler.h:505
A device tree region cell size specification.
Definition: fdt.h:136
const char * fdt_strings(struct fdt *fdt, unsigned int offset, const char *name, unsigned int *count)
Find strings property.
Definition: fdt.c:539
long index
Definition: bigint.h:62
#define ENOENT
No such file or directory.
Definition: errno.h:514
unsigned long long uint64_t
Definition: stdint.h:13
uint32_t string
Definition: multiboot.h:14
An executable image.
Definition: image.h:23
Character types.
struct image_tag fdt_image __image_tag
The downloaded flattened device tree tag.
Definition: fdt.c:47
size_t strings_len
Length of strings block.
Definition: fdt.h:107
int fdt_mac(struct fdt *fdt, unsigned int offset, struct net_device *netdev)
Get MAC address from property.
Definition: fdt.c:866
uint32_t fdt_token_t
Device tree token.
Definition: fdt.h:48
struct fdt_header * hdr
Tree header.
Definition: fdt.h:92
REQUIRING_SYMBOL(fdt_describe)
uint32_t off_dt_struct
Offset to structure block.
Definition: fdt.h:24
#define ENOTSUP
Operation not supported.
Definition: errno.h:589
struct image * find_image_tag(struct image_tag *tag)
Find image by tag.
Definition: image.c:392
uint32_t len
Data length.
Definition: fdt.h:62
uint8_t ch
Definition: registers.h:83
unsigned long tmp
Definition: linux_pci.h:64
struct ena_llq_option desc
Descriptor counts.
Definition: ena.h:20
#define ENOMEM
Not enough space.
Definition: errno.h:534
void * memcpy(void *dest, const void *src, size_t len) __nonnull
static int fdt_insert_string(struct fdt *fdt, const char *string, unsigned int *offset)
Insert string in strings block.
Definition: fdt.c:1173
uint32_t fdt_phandle(struct fdt *fdt, unsigned int offset)
Get package handle (phandle) property.
Definition: fdt.c:689
static int fdt_bootargs(struct fdt *fdt, const char *cmdline, physaddr_t initrd, size_t initrd_len)
Populate device tree with boot arguments.
Definition: fdt.c:1362
uint32_t off_dt_strings
Offset to strings block.
Definition: fdt.h:26
Assertions.
#define be32_to_cpu(value)
Definition: byteswap.h:116
assert((readw(&hdr->flags) &(GTF_reading|GTF_writing))==0)
Access to external ("user") memory.
Executable images.
uint8_t hw_addr_len
Hardware address length.
Definition: netdevice.h:196
int fdt_u32(struct fdt *fdt, unsigned int offset, const char *name, uint32_t *value)
Get 32-bit integer property.
Definition: fdt.c:663
static int isalnum(int character)
Check if character is alphanumeric.
Definition: ctype.h:86
#define FDT_MAGIC
Magic signature.
Definition: fdt.h:42
pseudo_bit_t value[0x00020]
Definition: arbel.h:13
#define DBGC_HDA(...)
Definition: compiler.h:506
static int fdt_property(struct fdt *fdt, unsigned int offset, const char *name, struct fdt_descriptor *desc)
Find property.
Definition: fdt.c:494
ring len
Length.
Definition: dwmac.h:231
void fdt_remove(struct fdt_header *hdr)
Remove device tree.
Definition: fdt.c:1458
static struct net_device * netdev
Definition: gdbudp.c:52
static unsigned int count
Number of entries.
Definition: dwmac.h:225
char * strcpy(char *dest, const char *src)
Copy string.
Definition: string.c:346
void fdt_reg_cells(struct fdt *fdt, unsigned int offset, struct fdt_reg_cells *regs)
Get region cell size specification.
Definition: fdt.c:715
const char * fdt_string(struct fdt *fdt, unsigned int offset, const char *name)
Find string property.
Definition: fdt.c:578
unsigned int structure
Offset to structure block.
Definition: fdt.h:101
#define FDT_VERSION
Expected device tree version.
Definition: fdt.h:45
#define DBGC2_HDA(...)
Definition: compiler.h:523
static int fdt_child(struct fdt *fdt, unsigned int offset, const char *name, unsigned int *child)
Find child node.
Definition: fdt.c:346
static int fdt_permitted(char ch)
Check if character is permitted in a name.
Definition: fdt.c:60
#define ERANGE
Result too large.
Definition: errno.h:639
char * strerror(int errno)
Retrieve string representation of error number.
Definition: strerror.c:78
static void(* free)(struct refcnt *refcnt))
Definition: refcnt.h:54
size_t len
Length of raw file image.
Definition: image.h:55
FILE_LICENCE(GPL2_OR_LATER_OR_UBDL)
char * strchr(const char *src, int character)
Find character within a string.
Definition: string.c:271
uint32_t size_dt_strings
Length of string block.
Definition: fdt.h:36
uint32_t addr
Buffer address.
Definition: dwmac.h:20
User memory allocation.
int fdt_reg_count(struct fdt *fdt, unsigned int offset, struct fdt_reg_cells *regs)
Get number of regions.
Definition: fdt.c:766
Property fragment.
Definition: fdt.h:60
A network device.
Definition: netdevice.h:352
size_t strlen(const char *src)
Get length of string.
Definition: string.c:243
int fdt_reg_address(struct fdt *fdt, unsigned int offset, struct fdt_reg_cells *regs, unsigned int index, uint64_t *address)
Get region address.
Definition: fdt.c:792
static int fdt_insert_nop(struct fdt *fdt, unsigned int offset, size_t len)
Insert FDT_NOP padded space in structure block.
Definition: fdt.c:1138
static int fdt_next(struct fdt *fdt, struct fdt_descriptor *desc)
Describe next device tree token.
Definition: fdt.c:197
unsigned char uint8_t
Definition: stdint.h:10
size_t strnlen(const char *src, size_t max)
Get length of string.
Definition: string.c:255
size_t used
Used length of tree.
Definition: fdt.h:99
uint32_t off_mem_rsvmap
Offset to memory reservation block.
Definition: fdt.h:28
unsigned int uint32_t
Definition: stdint.h:12
void * memmove(void *dest, const void *src, size_t len) __nonnull
struct i386_regs regs
Definition: registers.h:15
u8 token
Definition: CIB_PRM.h:42
int fdt_reg(struct fdt *fdt, unsigned int offset, uint64_t *region)
Get unsized single-entry region address.
Definition: fdt.c:843
REQUIRE_OBJECT(config_fdt)
size_t structure_len
Length of structure block.
Definition: fdt.h:103
#define FDT_PROP
Property token.
Definition: fdt.h:57
Network device management.
unsigned long physaddr_t
Definition: stdint.h:20
static int fdt_depth(struct fdt *fdt, unsigned int offset, unsigned int target)
Find node relative depth.
Definition: fdt.c:251
#define cpu_to_be32(value)
Definition: byteswap.h:110
A device tree.
Definition: fdt.h:88
uint32_t size_dt_struct
Length of structure block.
Definition: fdt.h:38
#define DBGC2(...)
Definition: compiler.h:522
uint32_t totalsize
Total size of device tree.
Definition: fdt.h:22
uint32_t name_off
Name offset.
Definition: fdt.h:64
#define FDT_END_NODE
End node token.
Definition: fdt.h:54
static __always_inline void * umalloc(size_t size)
Allocate external memory.
Definition: umalloc.h:56
void * rwdata
Writable data.
Definition: image.h:52
Flattened Device Tree.
uint32_t end
Ending offset.
Definition: netvsc.h:18
#define cpu_to_be64(value)
Definition: byteswap.h:111
uint8_t data[48]
Additional event data.
Definition: ena.h:22
static void fdt_nop(struct fdt *fdt, unsigned int offset, size_t len)
Fill space in structure block with FDT_NOP.
Definition: fdt.c:1116
#define FDT_INSERT_PAD
Amount of free space to add whenever we have to reallocate a tree.
Definition: fdt.c:52
static int fdt_insert(struct fdt *fdt, unsigned int offset, size_t len)
Insert empty space.
Definition: fdt.c:1048
#define FDT_BEGIN_NODE
Begin node token.
Definition: fdt.h:51
int fdt_parent_reg_cells(struct fdt *fdt, unsigned int offset, struct fdt_reg_cells *regs)
Get parent region cell size specification.
Definition: fdt.c:743
static int fdt_end(struct fdt *fdt, unsigned int offset, unsigned int *end)
Find end of node.
Definition: fdt.c:390
A device tree token descriptor.
Definition: fdt.h:120
void * urealloc(void *ptr, size_t new_size)
Reallocate external memory.
uint16_t offset
Offset to command line.
Definition: bzimage.h:8
uint32_t cmdline
Definition: multiboot.h:16
#define FDT_DEFAULT_SIZE_CELLS
Default number of size cells, if not specified.
Definition: fdt.h:149
#define DBG_LOG
Definition: compiler.h:317
int fdt_reg_size(struct fdt *fdt, unsigned int offset, struct fdt_reg_cells *regs, unsigned int index, uint64_t *size)
Get region size.
Definition: fdt.c:817
int fdt_create(struct fdt_header **hdr, const char *cmdline, physaddr_t initrd, size_t initrd_len)
Create device tree.
Definition: fdt.c:1407
int fdt_u64(struct fdt *fdt, unsigned int offset, const char *name, uint64_t *value)
Get 64-bit integer property.
Definition: fdt.c:643
int memcmp(const void *first, const void *second, size_t len)
Compare memory regions.
Definition: string.c:114
char * name
Name.
Definition: image.h:37
uint8_t hw_addr[MAX_HW_ADDR_LEN]
Hardware address.
Definition: netdevice.h:381
#define NULL
NULL pointer (VOID *)
Definition: Base.h:321
static int fdt_ensure_child(struct fdt *fdt, unsigned int offset, const char *name, unsigned int *child)
Ensure child node exists.
Definition: fdt.c:1208
String functions.
int fdt_cells(struct fdt *fdt, unsigned int offset, const char *name, unsigned int index, unsigned int count, uint64_t *value)
Get integer property.
Definition: fdt.c:597
const char * name
Name.
Definition: image.h:174
const void * data
Property data (if applicable)
Definition: fdt.h:128
#define FDT_DEFAULT_ADDRESS_CELLS
Default number of address cells, if not specified.
Definition: fdt.h:146
struct ll_protocol * ll_protocol
Link-layer protocol.
Definition: netdevice.h:372
#define FDT_MAX_ALIGN
Maximum alignment of any block.
Definition: fdt.h:77
unsigned int strings
Offset to strings block.
Definition: fdt.h:105
static int fdt_parse_image(struct fdt *fdt, struct image *image)
Parse device tree image.
Definition: fdt.c:1026
void * memset(void *dest, int character, size_t len) __nonnull
#define initrd_len
Definition: runtime.c:63
struct fdt sysfdt
The system flattened device tree (if present)
Definition: fdt.c:44