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