summaryrefslogtreecommitdiffstats
path: root/src/include/ipxe/fdt.h
blob: 6aa078ff6fc456488955f8243971dbea0cb5f3f5 (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
#ifndef _IPXE_FDT_H
#define _IPXE_FDT_H

/** @file
 *
 * Flattened Device Tree
 *
 */

FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL );
FILE_SECBOOT ( PERMITTED );

#include <stdint.h>
#include <ipxe/image.h>

struct net_device;

/** Device tree header */
struct fdt_header {
	/** Magic signature */
	uint32_t magic;
	/** Total size of device tree */
	uint32_t totalsize;
	/** Offset to structure block */
	uint32_t off_dt_struct;
	/** Offset to strings block */
	uint32_t off_dt_strings;
	/** Offset to memory reservation block */
	uint32_t off_mem_rsvmap;
	/** Version of this data structure */
	uint32_t version;
	/** Lowest version to which this structure is compatible */
	uint32_t last_comp_version;
	/** Physical ID of the boot CPU */
	uint32_t boot_cpuid_phys;
	/** Length of string block */
	uint32_t size_dt_strings;
	/** Length of structure block */
	uint32_t size_dt_struct;
} __attribute__ (( packed ));

/** Magic signature */
#define FDT_MAGIC 0xd00dfeed

/** Expected device tree version */
#define FDT_VERSION 16

/** Device tree token */
typedef uint32_t fdt_token_t;

/** Begin node token */
#define FDT_BEGIN_NODE 0x00000001

/** End node token */
#define FDT_END_NODE 0x00000002

/** Property token */
#define FDT_PROP 0x00000003

/** Property fragment */
struct fdt_prop {
	/** Data length */
	uint32_t len;
	/** Name offset */
	uint32_t name_off;
} __attribute__ (( packed ));

/** NOP token */
#define FDT_NOP 0x00000004

/** End of structure block */
#define FDT_END 0x00000009

/** Alignment of structure block */
#define FDT_STRUCTURE_ALIGN ( sizeof ( fdt_token_t ) )

/** Maximum alignment of any block */
#define FDT_MAX_ALIGN 8

/** A memory reservation */
struct fdt_reservation {
	/** Starting address */
	uint64_t start;
	/** Length of reservation */
	uint64_t size;
} __attribute__ (( packed ));

/** A device tree */
struct fdt {
	/** Tree data */
	union {
		/** Tree header */
		struct fdt_header *hdr;
		/** Raw data */
		void *raw;
	};
	/** Length of tree */
	size_t len;
	/** Used length of tree */
	size_t used;
	/** Offset to structure block */
	unsigned int structure;
	/** Length of structure block */
	size_t structure_len;
	/** Offset to strings block */
	unsigned int strings;
	/** Length of strings block */
	size_t strings_len;
	/** Offset to memory reservation block */
	unsigned int reservations;
	/** Reallocate device tree
	 *
	 * @v fdt		Device tree
	 * @v len		New length
	 * @ret rc		Return status code
	 */
	int ( * realloc ) ( struct fdt *fdt, size_t len );
};

/** A device tree token descriptor */
struct fdt_descriptor {
	/** Offset within structure block */
	unsigned int offset;
	/** Next offset within structure block */
	unsigned int next;
	/** Node or property name (if applicable) */
	const char *name;
	/** Property data (if applicable) */
	const void *data;
	/** Length of property data (if applicable) */
	size_t len;
	/** Depth change */
	int depth;
};

/** A device tree region cell size specification */
struct fdt_reg_cells {
	/** Number of address cells */
	uint32_t address_cells;
	/** Number of size cells */
	uint32_t size_cells;
	/** Number of address cells plus number of size cells */
	unsigned int stride;
};

/** Default number of address cells, if not specified */
#define FDT_DEFAULT_ADDRESS_CELLS 2

/** Default number of size cells, if not specified */
#define FDT_DEFAULT_SIZE_CELLS 1

extern struct image_tag fdt_image __image_tag;
extern struct fdt sysfdt;

/**
 * Get memory reservations
 *
 * @v fdt		Device tree
 * @ret rsv		Memory reservations
 */
static inline const struct fdt_reservation *
fdt_reservations ( struct fdt *fdt ) {

	return ( fdt->raw + fdt->reservations );
}

/** Iterate over memory reservations */
#define for_each_fdt_reservation( rsv, fdt )			\
	for ( rsv = fdt_reservations ( (fdt) ) ;		\
	      ( (rsv)->start || (rsv)->size ) ; rsv++ )

extern int fdt_describe ( struct fdt *fdt, unsigned int offset,
			  struct fdt_descriptor *desc );
extern int fdt_parent ( struct fdt *fdt, unsigned int offset,
			unsigned int *parent );
extern int fdt_path ( struct fdt *fdt, const char *path,
		      unsigned int *offset );
extern int fdt_alias ( struct fdt *fdt, const char *name,
		       unsigned int *offset );
extern const char * fdt_strings ( struct fdt *fdt, unsigned int offset,
				  const char *name, unsigned int *count );
extern const char * fdt_string ( struct fdt *fdt, unsigned int offset,
				 const char *name );
extern int fdt_cells ( struct fdt *fdt, unsigned int offset, const char *name,
		       unsigned int index, unsigned int count,
		       uint64_t *value );
extern int fdt_u64 ( struct fdt *fdt, unsigned int offset, const char *name,
		     uint64_t *value );
extern int fdt_u32 ( struct fdt *fdt, unsigned int offset, const char *name,
		     uint32_t *value );
extern uint32_t fdt_phandle ( struct fdt *fdt, unsigned int offset );
extern void fdt_reg_cells ( struct fdt *fdt, unsigned int offset,
			    struct fdt_reg_cells *regs );
extern int fdt_parent_reg_cells ( struct fdt *fdt, unsigned int offset,
				  struct fdt_reg_cells *regs );
extern int fdt_reg_count ( struct fdt *fdt, unsigned int offset,
			   struct fdt_reg_cells *regs );
extern int fdt_reg_address ( struct fdt *fdt, unsigned int offset,
			     struct fdt_reg_cells *regs, unsigned int index,
			     uint64_t *address );
extern int fdt_reg_size ( struct fdt *fdt, unsigned int offset,
			  struct fdt_reg_cells *regs, unsigned int index,
			  uint64_t *size );
extern int fdt_reg ( struct fdt *fdt, unsigned int offset, uint64_t *region );
extern int fdt_mac ( struct fdt *fdt, unsigned int offset,
		     struct net_device *netdev );
extern int fdt_parse ( struct fdt *fdt, struct fdt_header *hdr,
		       size_t max_len );
extern int fdt_create ( struct fdt_header **hdr, const char *cmdline,
			physaddr_t initrd, size_t initrd_len );
extern void fdt_remove ( struct fdt_header *hdr );

#endif /* _IPXE_FDT_H */