iPXE
fdt.c File Reference

Flattened Device Tree. More...

#include <string.h>
#include <ctype.h>
#include <errno.h>
#include <assert.h>
#include <byteswap.h>
#include <ipxe/netdevice.h>
#include <ipxe/image.h>
#include <ipxe/uaccess.h>
#include <ipxe/umalloc.h>
#include <ipxe/fdt.h>

Go to the source code of this file.

Macros

#define FDT_INSERT_PAD   1024
 Amount of free space to add whenever we have to reallocate a tree.

Functions

 FILE_LICENCE (GPL2_OR_LATER_OR_UBDL)
 FILE_SECBOOT (PERMITTED)
static int fdt_permitted (char ch)
 Check if character is permitted in a name.
static int fdt_match (const struct fdt_descriptor *desc, const char *name)
 Compare node name.
int fdt_describe (struct fdt *fdt, unsigned int offset, struct fdt_descriptor *desc)
 Describe device tree token.
static int fdt_next (struct fdt *fdt, struct fdt_descriptor *desc)
 Describe next device tree token.
static int fdt_enter (struct fdt *fdt, unsigned int offset, struct fdt_descriptor *desc)
 Enter node.
static int fdt_depth (struct fdt *fdt, unsigned int offset, unsigned int target)
 Find node relative depth.
int fdt_parent (struct fdt *fdt, unsigned int offset, unsigned int *parent)
 Find parent node.
static int fdt_child (struct fdt *fdt, unsigned int offset, const char *name, unsigned int *child)
 Find child node.
static int fdt_end (struct fdt *fdt, unsigned int offset, unsigned int *end)
 Find end of node.
int fdt_path (struct fdt *fdt, const char *path, unsigned int *offset)
 Find node by path.
int fdt_alias (struct fdt *fdt, const char *name, unsigned int *offset)
 Find node by alias.
static int fdt_property (struct fdt *fdt, unsigned int offset, const char *name, struct fdt_descriptor *desc)
 Find property.
const char * fdt_strings (struct fdt *fdt, unsigned int offset, const char *name, unsigned int *count)
 Find strings property.
const char * fdt_string (struct fdt *fdt, unsigned int offset, const char *name)
 Find string property.
int fdt_cells (struct fdt *fdt, unsigned int offset, const char *name, unsigned int index, unsigned int count, uint64_t *value)
 Get integer property.
int fdt_u64 (struct fdt *fdt, unsigned int offset, const char *name, uint64_t *value)
 Get 64-bit integer property.
int fdt_u32 (struct fdt *fdt, unsigned int offset, const char *name, uint32_t *value)
 Get 32-bit integer property.
uint32_t fdt_phandle (struct fdt *fdt, unsigned int offset)
 Get package handle (phandle) property.
void fdt_reg_cells (struct fdt *fdt, unsigned int offset, struct fdt_reg_cells *regs)
 Get region cell size specification.
int fdt_parent_reg_cells (struct fdt *fdt, unsigned int offset, struct fdt_reg_cells *regs)
 Get parent region cell size specification.
int fdt_reg_count (struct fdt *fdt, unsigned int offset, struct fdt_reg_cells *regs)
 Get number of regions.
int fdt_reg_address (struct fdt *fdt, unsigned int offset, struct fdt_reg_cells *regs, unsigned int index, uint64_t *address)
 Get region address.
int fdt_reg_size (struct fdt *fdt, unsigned int offset, struct fdt_reg_cells *regs, unsigned int index, uint64_t *size)
 Get region size.
int fdt_reg (struct fdt *fdt, unsigned int offset, uint64_t *region)
 Get unsized single-entry region address.
int fdt_mac (struct fdt *fdt, unsigned int offset, struct net_device *netdev)
 Get MAC address from property.
int fdt_parse (struct fdt *fdt, struct fdt_header *hdr, size_t max_len)
 Parse device tree.
static int fdt_parse_image (struct fdt *fdt, struct image *image)
 Parse device tree image.
static int fdt_insert (struct fdt *fdt, unsigned int offset, size_t len)
 Insert empty space.
static void fdt_nop (struct fdt *fdt, unsigned int offset, size_t len)
 Fill space in structure block with FDT_NOP.
static int fdt_insert_nop (struct fdt *fdt, unsigned int offset, size_t len)
 Insert FDT_NOP padded space in structure block.
static int fdt_insert_string (struct fdt *fdt, const char *string, unsigned int *offset)
 Insert string in strings block.
static int fdt_ensure_child (struct fdt *fdt, unsigned int offset, const char *name, unsigned int *child)
 Ensure child node exists.
static int fdt_set (struct fdt *fdt, unsigned int offset, const char *name, const void *data, size_t len)
 Set property value.
static int fdt_urealloc (struct fdt *fdt, size_t len)
 Reallocate device tree via urealloc()
static int fdt_bootargs (struct fdt *fdt, const char *cmdline, physaddr_t initrd, size_t initrd_len)
 Populate device tree with boot arguments.
int fdt_create (struct fdt_header **hdr, const char *cmdline, physaddr_t initrd, size_t initrd_len)
 Create device tree.
void fdt_remove (struct fdt_header *hdr)
 Remove device tree.
 REQUIRING_SYMBOL (fdt_describe)
 REQUIRE_OBJECT (config_fdt)

Variables

struct fdt sysfdt
 The system flattened device tree (if present)
struct image_tag fdt_image __image_tag
 The downloaded flattened device tree tag.

Detailed Description

Flattened Device Tree.

Definition in file fdt.c.

Macro Definition Documentation

◆ FDT_INSERT_PAD

#define FDT_INSERT_PAD   1024

Amount of free space to add whenever we have to reallocate a tree.

Definition at line 53 of file fdt.c.

Referenced by fdt_insert().

Function Documentation

◆ FILE_LICENCE()

FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL )

◆ FILE_SECBOOT()

FILE_SECBOOT ( PERMITTED )

◆ fdt_permitted()

int fdt_permitted ( char ch)
static

Check if character is permitted in a name.

Parameters
chCharacter
Return values
is_permittedCharacter is permitted in a name

Definition at line 61 of file fdt.c.

61 {
62 static const char permitted[] = ",._+?#-";
63
64 return ( isalnum ( ch ) || strchr ( permitted, ch ) );
65}
static int isalnum(int character)
Check if character is alphanumeric.
Definition ctype.h:87
uint8_t ch
Definition registers.h:1
char * strchr(const char *src, int character)
Find character within a string.
Definition string.c:272

References ch, isalnum(), and strchr().

Referenced by fdt_match().

◆ fdt_match()

int fdt_match ( const struct fdt_descriptor * desc,
const char * name )
static

Compare node name.

Parameters
descToken descriptor
nameName (terminated by NUL or any non-permitted character)
Return values
is_matchName matches token descriptor

Definition at line 74 of file fdt.c.

74 {
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}
const char * name
Definition ath9k_hw.c:1986
ring len
Length.
Definition dwmac.h:226
struct ena_llq_option desc
Descriptor counts.
Definition ena.h:9
static int fdt_permitted(char ch)
Check if character is permitted in a name.
Definition fdt.c:61
int memcmp(const void *first, const void *second, size_t len)
Compare memory regions.
Definition string.c:115
size_t strlen(const char *src)
Get length of string.
Definition string.c:244

References desc, fdt_permitted(), len, memcmp(), name, and strlen().

Referenced by fdt_child(), and fdt_property().

◆ fdt_describe()

int fdt_describe ( struct fdt * fdt,
unsigned int offset,
struct fdt_descriptor * desc )

Describe device tree token.

Parameters
fdtDevice tree
offsetOffset within structure block
descToken descriptor to fill in
Return values
rcReturn status code

Definition at line 90 of file fdt.c.

91 {
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}
u8 token
Definition CIB_PRM.h:14
#define assert(condition)
Assert a condition at run-time.
Definition assert.h:50
uint16_t offset
Offset to command line.
Definition bzimage.h:3
uint8_t data[48]
Additional event data.
Definition ena.h:11
#define DBGC(...)
Definition compiler.h:505
#define EINVAL
Invalid argument.
Definition errno.h:429
#define be32_to_cpu(value)
Definition byteswap.h:117
#define cpu_to_be32(value)
Definition byteswap.h:111
#define FDT_STRUCTURE_ALIGN
Alignment of structure block.
Definition fdt.h:75
#define FDT_PROP
Property token.
Definition fdt.h:58
#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
uint32_t fdt_token_t
Device tree token.
Definition fdt.h:49
void * memset(void *dest, int character, size_t len) __nonnull
size_t strnlen(const char *src, size_t max)
Get length of string.
Definition string.c:256
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.
Definition fdt.h:89
size_t len
Length of tree.
Definition fdt.h:98
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
unsigned int structure
Offset to structure block.
Definition fdt.h:102

References assert, be32_to_cpu, cpu_to_be32, data, DBGC, desc, EINVAL, FDT_BEGIN_NODE, FDT_END_NODE, FDT_NOP, FDT_PROP, FDT_STRUCTURE_ALIGN, fdt::len, fdt_prop::len, len, memset(), fdt_prop::name_off, offset, fdt::raw, fdt::strings, fdt::strings_len, strnlen(), fdt::structure, and token.

Referenced by dt_probe_children(), dt_probe_node(), fdt_enter(), fdt_next(), fdt_test_exec(), fdtmem_update_node(), and REQUIRING_SYMBOL().

◆ fdt_next()

int fdt_next ( struct fdt * fdt,
struct fdt_descriptor * desc )
static

Describe next device tree token.

Parameters
fdtDevice tree
descToken descriptor to update
Return values
rcReturn status code

Definition at line 198 of file fdt.c.

198 {
199
200 /* Describe next token */
201 return fdt_describe ( fdt, desc->next, desc );
202}
int fdt_describe(struct fdt *fdt, unsigned int offset, struct fdt_descriptor *desc)
Describe device tree token.
Definition fdt.c:90

References desc, and fdt_describe().

Referenced by fdt_child(), fdt_depth(), fdt_end(), fdt_parent(), and fdt_property().

◆ fdt_enter()

int fdt_enter ( struct fdt * fdt,
unsigned int offset,
struct fdt_descriptor * desc )
static

Enter node.

Parameters
fdtDevice tree
offsetStarting node offset
descBegin node descriptor to fill in
Return values
rcReturn status code

Definition at line 212 of file fdt.c.

213 {
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}
struct arbelprm_rc_send_wqe rc
Definition arbel.h:3
char * strerror(int errno)
Retrieve string representation of error number.
Definition strerror.c:79

References DBGC, desc, EINVAL, fdt_describe(), offset, rc, and strerror().

Referenced by fdt_child(), fdt_depth(), fdt_end(), fdt_parent(), fdt_property(), and fdt_set().

◆ fdt_depth()

int fdt_depth ( struct fdt * fdt,
unsigned int offset,
unsigned int target )
static

Find node relative depth.

Parameters
fdtDevice tree
offsetStarting node offset
targetTarget node offset
Return values
depthDepth, or negative error

Definition at line 252 of file fdt.c.

253 {
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}
static int fdt_enter(struct fdt *fdt, unsigned int offset, struct fdt_descriptor *desc)
Enter node.
Definition fdt.c:212
static int fdt_next(struct fdt *fdt, struct fdt_descriptor *desc)
Describe next device tree token.
Definition fdt.c:198
#define DBGC2(...)
Definition compiler.h:522
#define ENOENT
No such file or directory.
Definition errno.h:515
A device tree token descriptor.
Definition fdt.h:121
int depth
Depth change.
Definition fdt.h:133

References DBGC, DBGC2, fdt_descriptor::depth, desc, ENOENT, fdt_enter(), fdt_next(), offset, rc, and strerror().

Referenced by fdt_parent().

◆ fdt_parent()

int fdt_parent ( struct fdt * fdt,
unsigned int offset,
unsigned int * parent )

Find parent node.

Parameters
fdtDevice tree
offsetStarting node offset
parentParent node offset to fill in
Return values
rcReturn status code

Definition at line 293 of file fdt.c.

293 {
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}
static int fdt_depth(struct fdt *fdt, unsigned int offset, unsigned int target)
Find node relative depth.
Definition fdt.c:252

References DBGC, DBGC2, fdt_descriptor::depth, desc, ENOENT, fdt_depth(), fdt_enter(), fdt_next(), offset, rc, and strerror().

Referenced by fdt_parent_reg_cells(), and fdt_test_exec().

◆ fdt_child()

int fdt_child ( struct fdt * fdt,
unsigned int offset,
const char * name,
unsigned int * child )
static

Find child node.

Parameters
fdtDevice tree
offsetStarting node offset
nameNode name
childChild node offset to fill in
Return values
rcReturn status code

Definition at line 347 of file fdt.c.

348 {
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}
static int fdt_match(const struct fdt_descriptor *desc, const char *name)
Compare node name.
Definition fdt.c:74

References assert, DBGC, DBGC2, fdt_descriptor::depth, desc, ENOENT, fdt_enter(), fdt_match(), fdt_next(), name, offset, rc, and strerror().

Referenced by fdt_alias(), fdt_ensure_child(), fdt_parse(), and fdt_path().

◆ fdt_end()

int fdt_end ( struct fdt * fdt,
unsigned int offset,
unsigned int * end )
static

Find end of node.

Parameters
fdtDevice tree
offsetStarting node offset
endEnd of node offset to fill in
Return values
rcReturn status code

Definition at line 391 of file fdt.c.

392 {
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}
uint32_t end
Ending offset.
Definition netvsc.h:7

References DBGC, DBGC2, fdt_descriptor::depth, desc, end, fdt_enter(), fdt_next(), offset, rc, and strerror().

Referenced by fdt_ensure_child().

◆ fdt_path()

int fdt_path ( struct fdt * fdt,
const char * path,
unsigned int * offset )

Find node by path.

Parameters
fdtDevice tree
pathNode path
offsetOffset to fill in
Return values
rcReturn status code

Definition at line 426 of file fdt.c.

426 {
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}
static int fdt_child(struct fdt *fdt, unsigned int offset, const char *name, unsigned int *child)
Find child node.
Definition fdt.c:347
unsigned long tmp
Definition linux_pci.h:65

References DBGC2, fdt_child(), offset, rc, strchr(), and tmp.

Referenced by fdt_alias(), fdt_test_exec(), fdtcon_default(), and fdtmem_update_tree().

◆ fdt_alias()

int fdt_alias ( struct fdt * fdt,
const char * name,
unsigned int * offset )

Find node by alias.

Parameters
fdtDevice tree
nameAlias name
offsetOffset to fill in
Return values
rcReturn status code

Definition at line 466 of file fdt.c.

466 {
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}
#define NULL
NULL pointer (VOID *)
Definition Base.h:322
const char * fdt_string(struct fdt *fdt, unsigned int offset, const char *name)
Find string property.
Definition fdt.c:579
int fdt_path(struct fdt *fdt, const char *path, unsigned int *offset)
Find node by path.
Definition fdt.c:426

References DBGC, ENOENT, fdt_child(), fdt_path(), fdt_string(), name, NULL, offset, and rc.

Referenced by fdt_test_exec(), fdtcon_default(), and smscusb_fdt_fetch_mac().

◆ fdt_property()

int fdt_property ( struct fdt * fdt,
unsigned int offset,
const char * name,
struct fdt_descriptor * desc )
static

Find property.

Parameters
fdtDevice tree
offsetStarting node offset
nameProperty name
descToken descriptor to fill in
Return values
rcReturn status code

Definition at line 495 of file fdt.c.

496 {
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}
#define DBGC2_HDA(...)
Definition compiler.h:523

References assert, DBGC, DBGC2, DBGC2_HDA, fdt_descriptor::depth, desc, ENOENT, fdt_enter(), fdt_match(), fdt_next(), name, offset, rc, and strerror().

Referenced by fdt_cells(), fdt_mac(), fdt_reg_count(), fdt_set(), and fdt_strings().

◆ fdt_strings()

const char * fdt_strings ( struct fdt * fdt,
unsigned int offset,
const char * name,
unsigned int * count )

Find strings property.

Parameters
fdtDevice tree
offsetStarting node offset
nameProperty name
countString count to fill in
Return values
stringString property, or NULL on error

Definition at line 540 of file fdt.c.

541 {
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}
static int fdt_property(struct fdt *fdt, unsigned int offset, const char *name, struct fdt_descriptor *desc)
Find property.
Definition fdt.c:495
static unsigned int count
Number of entries.
Definition dwmac.h:220

References count, data, DBGC, desc, fdt_property(), len, name, NULL, offset, and rc.

Referenced by dt_find_driver(), fdt_string(), and fdt_test_exec().

◆ fdt_string()

const char * fdt_string ( struct fdt * fdt,
unsigned int offset,
const char * name )

Find string property.

Parameters
fdtDevice tree
offsetStarting node offset
nameProperty name
Return values
stringString property, or NULL on error

Definition at line 579 of file fdt.c.

580 {
581 unsigned int count;
582
583 /* Find strings property */
584 return fdt_strings ( fdt, offset, name, &count );
585}
const char * fdt_strings(struct fdt *fdt, unsigned int offset, const char *name, unsigned int *count)
Find strings property.
Definition fdt.c:540

References count, fdt_strings(), name, and offset.

Referenced by fdt_alias(), fdt_parse(), fdt_test_exec(), fdtcon_default(), and fdtmem_update_node().

◆ fdt_cells()

int fdt_cells ( struct fdt * fdt,
unsigned int offset,
const char * name,
unsigned int index,
unsigned int count,
uint64_t * value )

Get integer property.

Parameters
fdtDevice tree
offsetStarting node offset
nameProperty name
indexStarting cell index
countNumber of cells (or 0 to read all remaining cells)
valueInteger value to fill in
Return values
rcReturn status code

Definition at line 598 of file fdt.c.

599 {
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}
pseudo_bit_t value[0x00020]
Definition arbel.h:2
unsigned int uint32_t
Definition stdint.h:12
long index
Definition bigint.h:65
#define ERANGE
Result too large.
Definition errno.h:640

References be32_to_cpu, count, DBGC, desc, ERANGE, fdt_property(), index, name, offset, rc, and value.

Referenced by fdt_reg_address(), fdt_reg_size(), fdt_test_exec(), and fdt_u64().

◆ fdt_u64()

int fdt_u64 ( struct fdt * fdt,
unsigned int offset,
const char * name,
uint64_t * value )

Get 64-bit integer property.

Parameters
fdtDevice tree
offsetStarting node offset
nameProperty name
valueInteger value to fill in
Return values
rcReturn status code

Definition at line 644 of file fdt.c.

645 {
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}
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

References fdt_cells(), name, offset, rc, and value.

Referenced by fdt_test_exec(), and fdt_u32().

◆ fdt_u32()

int fdt_u32 ( struct fdt * fdt,
unsigned int offset,
const char * name,
uint32_t * value )

Get 32-bit integer property.

Parameters
fdtDevice tree
offsetStarting node offset
nameProperty name
valueInteger value to fill in
Return values
rcReturn status code

Definition at line 664 of file fdt.c.

665 {
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}
unsigned long long uint64_t
Definition stdint.h:13
int fdt_u64(struct fdt *fdt, unsigned int offset, const char *name, uint64_t *value)
Get 64-bit integer property.
Definition fdt.c:644

References DBGC, ERANGE, fdt_u64(), name, offset, rc, and value.

Referenced by dwgpio_probe(), dwuart_probe(), fdt_phandle(), fdt_reg_cells(), and fdt_test_exec().

◆ fdt_phandle()

uint32_t fdt_phandle ( struct fdt * fdt,
unsigned int offset )

Get package handle (phandle) property.

Parameters
fdtDevice tree
offsetStarting node offset
Return values
phandlePackage handle, or 0 on error

Definition at line 690 of file fdt.c.

690 {
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}
int fdt_u32(struct fdt *fdt, unsigned int offset, const char *name, uint32_t *value)
Get 32-bit integer property.
Definition fdt.c:664

References assert, fdt_u32(), offset, and rc.

Referenced by dt_probe_node(), and fdt_test_exec().

◆ fdt_reg_cells()

void fdt_reg_cells ( struct fdt * fdt,
unsigned int offset,
struct fdt_reg_cells * regs )

Get region cell size specification.

Parameters
fdtDevice tree
offsetStarting (parent) node offset
regsRegion cell size specification to fill in

Note that address-cells and size-cells are defined on the immediate parent node, rather than on the node with the "reg" property itself.

Definition at line 716 of file fdt.c.

717 {
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}
#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
struct i386_regs regs
Definition registers.h:1

References FDT_DEFAULT_ADDRESS_CELLS, FDT_DEFAULT_SIZE_CELLS, fdt_u32(), offset, rc, and regs.

Referenced by fdt_parent_reg_cells(), and fdtmem_update_node().

◆ fdt_parent_reg_cells()

int fdt_parent_reg_cells ( struct fdt * fdt,
unsigned int offset,
struct fdt_reg_cells * regs )

Get parent region cell size specification.

Parameters
fdtDevice tree
offsetStarting node offset
regsRegion cell size specification to fill in
Return values
rcReturn status code

Definition at line 744 of file fdt.c.

745 {
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}
void fdt_reg_cells(struct fdt *fdt, unsigned int offset, struct fdt_reg_cells *regs)
Get region cell size specification.
Definition fdt.c:716
int fdt_parent(struct fdt *fdt, unsigned int offset, unsigned int *parent)
Find parent node.
Definition fdt.c:293

References fdt_parent(), fdt_reg_cells(), offset, rc, and regs.

Referenced by dt_ioremap(), and fdt_reg().

◆ fdt_reg_count()

int fdt_reg_count ( struct fdt * fdt,
unsigned int offset,
struct fdt_reg_cells * regs )

Get number of regions.

Parameters
fdtDevice tree
offsetStarting node offset
regsRegion cell size specification
Return values
countNumber of regions, or negative error

Definition at line 767 of file fdt.c.

768 {
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}

References count, desc, fdt_property(), offset, rc, and regs.

Referenced by fdtmem_update_node().

◆ fdt_reg_address()

int fdt_reg_address ( struct fdt * fdt,
unsigned int offset,
struct fdt_reg_cells * regs,
unsigned int index,
uint64_t * address )

Get region address.

Parameters
fdtDevice tree
offsetStarting node offset
regsRegion cell size specification
indexRegion index
addressRegion starting address to fill in
Return values
rcReturn status code

Definition at line 793 of file fdt.c.

795 {
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}
uint64_t address
Base address.
Definition ena.h:13

References address, fdt_cells(), index, offset, rc, and regs.

Referenced by dt_ioremap(), fdt_reg(), and fdtmem_update_node().

◆ fdt_reg_size()

int fdt_reg_size ( struct fdt * fdt,
unsigned int offset,
struct fdt_reg_cells * regs,
unsigned int index,
uint64_t * size )

Get region size.

Parameters
fdtDevice tree
offsetStarting node offset
regsRegion cell size specification
indexRegion index
sizeRegion size to fill in
Return values
rcReturn status code

Definition at line 818 of file fdt.c.

820 {
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}
uint16_t size
Buffer size.
Definition dwmac.h:3

References fdt_cells(), index, offset, rc, regs, and size.

Referenced by dt_ioremap(), and fdtmem_update_node().

◆ fdt_reg()

int fdt_reg ( struct fdt * fdt,
unsigned int offset,
uint64_t * region )

Get unsized single-entry region address.

Parameters
fdtDevice tree
offsetStarting node offset
addressRegion address to fill in
Return values
rcReturn status code

Many region types (e.g. I2C bus addresses) can only ever contain a single region with no size cells specified.

Definition at line 844 of file fdt.c.

844 {
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}
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
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
A device tree region cell size specification.
Definition fdt.h:137

References fdt_parent_reg_cells(), fdt_reg_address(), offset, rc, and regs.

Referenced by dwgpio_probe().

◆ fdt_mac()

int fdt_mac ( struct fdt * fdt,
unsigned int offset,
struct net_device * netdev )

Get MAC address from property.

Parameters
fdtDevice tree
offsetStarting node offset
netdevNetwork device
Return values
rcReturn status code

Definition at line 867 of file fdt.c.

868 {
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}
static struct net_device * netdev
Definition gdbudp.c:53
#define DBGC_HDA(...)
Definition compiler.h:506
void * memcpy(void *dest, const void *src, size_t len) __nonnull

References DBGC, DBGC_HDA, desc, ERANGE, fdt_property(), len, memcpy(), netdev, offset, and rc.

Referenced by cgem_probe(), dwmac_probe(), and smscusb_fdt_fetch_mac().

◆ fdt_parse()

int fdt_parse ( struct fdt * fdt,
struct fdt_header * hdr,
size_t max_len )

Parse device tree.

Parameters
fdtDevice tree
hdrDevice tree header
max_lenMaximum device tree length
Return values
rcReturn status code

Definition at line 904 of file fdt.c.

904 {
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}
struct golan_inbox_hdr hdr
Message header.
Definition CIB_PRM.h:0
unsigned char uint8_t
Definition stdint.h:10
#define DBG_LOG
Definition compiler.h:317
#define FDT_VERSION
Expected device tree version.
Definition fdt.h:46
#define FDT_MAGIC
Magic signature.
Definition fdt.h:43
size_t structure_len
Length of structure block.
Definition fdt.h:104
struct fdt_header * hdr
Tree header.
Definition fdt.h:93
size_t used
Used length of tree.
Definition fdt.h:100
unsigned int reservations
Offset to memory reservation block.
Definition fdt.h:110

References be32_to_cpu, cpu_to_be32, DBG_LOG, DBGC, DBGC_HDA, EINVAL, end, fdt_child(), FDT_MAGIC, fdt_string(), FDT_STRUCTURE_ALIGN, FDT_VERSION, fdt::hdr, hdr, fdt::len, memset(), fdt::raw, fdt::reservations, fdt::strings, fdt::strings_len, fdt::structure, fdt::structure_len, and fdt::used.

Referenced by efi_fdt_init(), fdt_parse_image(), fdt_test_exec(), fdtmem_register(), and fdtmem_relocate().

◆ fdt_parse_image()

int fdt_parse_image ( struct fdt * fdt,
struct image * image )
static

Parse device tree image.

Parameters
fdtDevice tree
imageImage
Return values
rcReturn status code

Definition at line 1027 of file fdt.c.

1027 {
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}
int fdt_parse(struct fdt *fdt, struct fdt_header *hdr, size_t max_len)
Parse device tree.
Definition fdt.c:904
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

References DBGC, fdt_parse(), image::len, image::name, rc, image::rwdata, and strerror().

Referenced by fdt_create().

◆ fdt_insert()

int fdt_insert ( struct fdt * fdt,
unsigned int offset,
size_t len )
static

Insert empty space.

Parameters
fdtDevice tree
offsetOffset at which to insert space
lenLength to insert (must be a multiple of FDT_MAX_ALIGN)
Return values
rcReturn status code

Definition at line 1049 of file fdt.c.

1049 {
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}
#define FDT_INSERT_PAD
Amount of free space to add whenever we have to reallocate a tree.
Definition fdt.c:53
#define ENOTSUP
Operation not supported.
Definition errno.h:590
#define FDT_MAX_ALIGN
Maximum alignment of any block.
Definition fdt.h:78
void * memmove(void *dest, const void *src, size_t len) __nonnull
static void(* free)(struct refcnt *refcnt))
Definition refcnt.h:55
uint32_t off_dt_strings
Offset to strings block.
Definition fdt.h:27
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
int(* realloc)(struct fdt *fdt, size_t len)
Reallocate device tree.
Definition fdt.h:117

References assert, cpu_to_be32, DBGC, ENOTSUP, FDT_INSERT_PAD, FDT_MAX_ALIGN, free, fdt::hdr, fdt::len, len, memmove(), memset(), fdt_header::off_dt_strings, fdt_header::off_dt_struct, fdt_header::off_mem_rsvmap, offset, fdt::raw, rc, fdt::realloc, fdt::reservations, fdt::strings, fdt::strings_len, fdt::structure, fdt::structure_len, and fdt::used.

Referenced by fdt_insert_nop(), and fdt_insert_string().

◆ fdt_nop()

void fdt_nop ( struct fdt * fdt,
unsigned int offset,
size_t len )
static

Fill space in structure block with FDT_NOP.

Parameters
fdtDevice tree
offsetStarting offset
lenLength (must be a multiple of FDT_STRUCTURE_ALIGN)

Definition at line 1117 of file fdt.c.

1117 {
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}

References assert, count, cpu_to_be32, FDT_NOP, FDT_STRUCTURE_ALIGN, len, offset, fdt::raw, fdt::structure, and token.

Referenced by fdt_insert_nop(), and fdt_set().

◆ fdt_insert_nop()

int fdt_insert_nop ( struct fdt * fdt,
unsigned int offset,
size_t len )
static

Insert FDT_NOP padded space in structure block.

Parameters
fdtDevice tree
offsetOffset at which to insert space
lenMinimal length to insert
Return values
rcReturn status code

Definition at line 1139 of file fdt.c.

1140 {
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}
static int fdt_insert(struct fdt *fdt, unsigned int offset, size_t len)
Insert empty space.
Definition fdt.c:1049
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
uint32_t size_dt_struct
Length of structure block.
Definition fdt.h:39

References assert, cpu_to_be32, DBGC, fdt_insert(), FDT_MAX_ALIGN, fdt_nop(), FDT_STRUCTURE_ALIGN, fdt::hdr, len, offset, rc, fdt_header::size_dt_struct, fdt::structure, and fdt::structure_len.

Referenced by fdt_ensure_child(), and fdt_set().

◆ fdt_insert_string()

int fdt_insert_string ( struct fdt * fdt,
const char * string,
unsigned int * offset )
static

Insert string in strings block.

Parameters
fdtDevice tree
stringString
offsetString offset to fill in
Return values
rcReturn status code

Definition at line 1174 of file fdt.c.

1175 {
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}
char * strcpy(char *dest, const char *src)
Copy string.
Definition string.c:347
uint32_t size_dt_strings
Length of string block.
Definition fdt.h:37

References cpu_to_be32, DBGC, fdt_insert(), FDT_MAX_ALIGN, fdt::hdr, len, offset, fdt::raw, rc, fdt_header::size_dt_strings, strcpy(), fdt::strings, fdt::strings_len, and strlen().

Referenced by fdt_set().

◆ fdt_ensure_child()

int fdt_ensure_child ( struct fdt * fdt,
unsigned int offset,
const char * name,
unsigned int * child )
static

Ensure child node exists.

Parameters
fdtDevice tree
offsetStarting node offset
nameNew node name
childChild node offset to fill in
Return values
rcReturn status code

Definition at line 1209 of file fdt.c.

1210 {
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}
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
static int fdt_end(struct fdt *fdt, unsigned int offset, unsigned int *end)
Find end of node.
Definition fdt.c:391

References cpu_to_be32, DBGC2, FDT_BEGIN_NODE, fdt_child(), fdt_end(), FDT_END_NODE, fdt_insert_nop(), FDT_STRUCTURE_ALIGN, len, memcpy(), name, offset, fdt::raw, rc, strlen(), fdt::structure, and token.

Referenced by fdt_bootargs().

◆ fdt_set()

int fdt_set ( struct fdt * fdt,
unsigned int offset,
const char * name,
const void * data,
size_t len )
static

Set property value.

Parameters
fdtDevice tree
offsetStarting node offset
nameProperty name
dataProperty data, or NULL to delete property
lenLength of property data
Return values
rcReturn status code

Definition at line 1254 of file fdt.c.

1255 {
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}
int erase(void)
Completely clear the screen.
Definition clear.c:98
static int fdt_insert_string(struct fdt *fdt, const char *string, unsigned int *offset)
Insert string in strings block.
Definition fdt.c:1174
#define __attribute__(x)
Definition compiler.h:10
uint32_t string
Definition multiboot.h:2
const void * data
Property data (if applicable)
Definition fdt.h:129

References __attribute__, assert, be32_to_cpu, cpu_to_be32, data, DBGC2, DBGC2_HDA, desc, erase(), fdt_enter(), fdt_insert_nop(), fdt_insert_string(), fdt_nop(), FDT_PROP, fdt_property(), FDT_STRUCTURE_ALIGN, hdr, len, memcpy(), memset(), name, offset, fdt::raw, rc, string, fdt::structure, and token.

Referenced by fdt_bootargs().

◆ fdt_urealloc()

int fdt_urealloc ( struct fdt * fdt,
size_t len )
static

Reallocate device tree via urealloc()

Parameters
fdtDevice tree
lenNew total length
Return values
rcReturn status code

Definition at line 1330 of file fdt.c.

1330 {
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}
#define ENOMEM
Not enough space.
Definition errno.h:535
void * urealloc(void *ptr, size_t new_size)
Reallocate external memory.
uint32_t totalsize
Total size of device tree.
Definition fdt.h:23

References assert, cpu_to_be32, DBGC, ENOMEM, fdt::hdr, fdt::len, len, fdt::raw, fdt_header::totalsize, urealloc(), and fdt::used.

Referenced by fdt_create().

◆ fdt_bootargs()

int fdt_bootargs ( struct fdt * fdt,
const char * cmdline,
physaddr_t initrd,
size_t initrd_len )
static

Populate device tree with boot arguments.

Parameters
fdtDevice tree
cmdlineCommand line, or NULL
initrdInitial ramdisk address (or 0 for no initrd)
initrd_lenInitial ramdisk length (or 0 for no initrd)
Return values
rcReturn status code

Definition at line 1363 of file fdt.c.

1364 {
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}
unsigned long physaddr_t
Definition stdint.h:20
uint32_t addr
Buffer address.
Definition dwmac.h:9
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
#define cpu_to_be64(value)
Definition byteswap.h:112
uint32_t cmdline
Definition multiboot.h:4
#define initrd_len
Definition runtime.c:63

References addr, cmdline, cpu_to_be32, cpu_to_be64, data, fdt_ensure_child(), fdt_set(), initrd_len, len, NULL, rc, and strlen().

Referenced by fdt_create().

◆ fdt_create()

int fdt_create ( struct fdt_header ** hdr,
const char * cmdline,
physaddr_t initrd,
size_t initrd_len )

Create device tree.

Parameters
hdrDevice tree header to fill in (may be set to NULL)
cmdlineCommand line, or NULL
initrdInitial ramdisk address (or 0 for no initrd)
initrd_lenInitial ramdisk length (or 0 for no initrd)
Return values
rcReturn status code

Definition at line 1408 of file fdt.c.

1409 {
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}
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
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
struct image * find_image_tag(struct image_tag *tag)
Find image by tag.
Definition image.c:393
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

References cmdline, DBGC, ENOMEM, fdt_bootargs(), fdt_parse_image(), fdt_urealloc(), find_image_tag(), hdr, initrd_len, fdt::len, memcpy(), fdt::raw, rc, fdt::realloc, sysfdt, ufree(), and umalloc().

Referenced by efi_fdt_install(), fdt_test_exec(), and lkrn_exec().

◆ fdt_remove()

void fdt_remove ( struct fdt_header * hdr)

Remove device tree.

Parameters
hdrDevice tree header, or NULL

Definition at line 1459 of file fdt.c.

1459 {
1460
1461 /* Free modifiable copy */
1462 ufree ( hdr );
1463}

References hdr, and ufree().

Referenced by efi_fdt_install(), efi_fdt_uninstall(), fdt_test_exec(), and lkrn_exec().

◆ REQUIRING_SYMBOL()

REQUIRING_SYMBOL ( fdt_describe )

References fdt_describe().

◆ REQUIRE_OBJECT()

REQUIRE_OBJECT ( config_fdt )

Variable Documentation

◆ sysfdt

◆ __image_tag

struct image_tag fdt_image __image_tag
Initial value:
= {
.name = "FDT",
}

The downloaded flattened device tree tag.

Definition at line 48 of file fdt.c.

48 {
49 .name = "FDT",
50};