summaryrefslogtreecommitdiff
path: root/src/include/device_tree.h
blob: 02fcaa7234c3403be74f7f232e6dc81c5d40274a (plain)
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
/* Taken from depthcharge: src/base/device_tree.h */
/* SPDX-License-Identifier: GPL-2.0-or-later */

#ifndef __DEVICE_TREE_H__
#define __DEVICE_TREE_H__

#include <stddef.h>
#include <stdint.h>
#include <list.h>

/*
 * Flattened device tree structures/constants.
 */

struct fdt_header {
	uint32_t magic;
	uint32_t totalsize;
	uint32_t structure_offset;
	uint32_t strings_offset;
	uint32_t reserve_map_offset;

	uint32_t version;
	uint32_t last_comp_version;

	uint32_t boot_cpuid_phys;

	uint32_t strings_size;
	uint32_t structure_size;
};

#define FDT_HEADER_MAGIC	0xd00dfeed
#define FDT_SUPPORTED_VERSION	17
#define FDT_TOKEN_BEGIN_NODE	1
#define FDT_TOKEN_END_NODE	2
#define FDT_TOKEN_PROPERTY	3
#define FDT_TOKEN_END		9
#define FDT_PHANDLE_ILLEGAL	0xdeadbeef

struct fdt_property
{
	const char *name;
	void *data;
	uint32_t size;
};

/*
 * Unflattened device tree structures.
 */

struct device_tree_property
{
	struct fdt_property prop;

	struct list_node list_node;
};

struct device_tree_node
{
	const char *name;
	uint32_t phandle;

	/* List of struct device_tree_property-s. */
	struct list_node properties;
	/* List of struct device_tree_nodes. */
	struct list_node children;

	struct list_node list_node;
};

struct device_tree_reserve_map_entry
{
	uint64_t start;
	uint64_t size;

	struct list_node list_node;
};

struct device_tree
{
	const void *header;
	uint32_t header_size;
	uint32_t max_phandle;

	struct list_node reserve_map;

	struct device_tree_node *root;
};

/*
 * Flattened device tree functions. These generally return the number of bytes
 * which were consumed reading the requested value.
 */

/* Read the property at offset, if any exists. */
int fdt_next_property(const void *blob, uint32_t offset,
		      struct fdt_property *prop);
/* Read the name of the node at offset, if any exists. */
int fdt_node_name(const void *blob, uint32_t offset, const char **name);

void fdt_print_node(const void *blob, uint32_t offset);
int fdt_skip_node(const void *blob, uint32_t offset);

/* Read a flattened device tree into a hierarchical structure which refers to
   the contents of the flattened tree in place. Modifying the flat tree
   invalidates the unflattened one. */
struct device_tree *fdt_unflatten(const void *blob);

/*
 * Unflattened device tree functions.
 */

/* Figure out how big a device tree would be if it were flattened. */
uint32_t dt_flat_size(const struct device_tree *tree);
/* Flatten a device tree into the buffer pointed to by dest. */
void dt_flatten(const struct device_tree *tree, void *dest);
void dt_print_node(const struct device_tree_node *node);
/* Read #address-cells and #size-cells properties from a node. */
void dt_read_cell_props(const struct device_tree_node *node, u32 *addrcp,
			u32 *sizecp);
/* Look up or create a node relative to a parent node, through its path
   represented as an array of strings. */
struct device_tree_node *dt_find_node(struct device_tree_node *parent, const char **path,
			     u32 *addrcp, u32 *sizecp, int create);
struct device_tree_node *dt_find_node_by_phandle(struct device_tree_node *root,
						 uint32_t phandle);
/* Look up or create a node in the tree, through its path
   represented as a string of '/' separated node names. */
struct device_tree_node *dt_find_node_by_path(struct device_tree *tree,
			const char *path, u32 *addrcp, u32 *sizecp, int create);
/* Look up a node through an alias. */
struct device_tree_node *dt_find_node_by_alias(struct device_tree *tree,
					       const char *alias);
/* Look up a node relative to a parent node, through its compatible string. */
struct device_tree_node *dt_find_compat(struct device_tree_node *parent, const char *compatible);
/* Look up the next child of a parent node, through its compatible string. It
   uses child pointer as the marker to find next. */
struct device_tree_node *dt_find_next_compat_child(struct device_tree_node *parent,
					  struct device_tree_node *child,
					  const char *compat);
/* Look up a node relative to a parent node, through its property value. */
struct device_tree_node *dt_find_prop_value(struct device_tree_node *parent, const char *name,
				   void *data, size_t size);
/* Write src into *dest as a 'length'-byte big-endian integer. */
void dt_write_int(u8 *dest, u64 src, size_t length);
/* Delete a property */
void dt_delete_prop(struct device_tree_node *node, const char *name);
/* Add different kinds of properties to a node, or update existing ones. */
void dt_add_bin_prop(struct device_tree_node *node, const char *name,
		     void *data, size_t size);
void dt_add_string_prop(struct device_tree_node *node, const char *name,
			const char *str);
void dt_add_u32_prop(struct device_tree_node *node, const char *name, u32 val);
void dt_add_u64_prop(struct device_tree_node *node, const char *name, u64 val);
void dt_add_reg_prop(struct device_tree_node *node, u64 *addrs, u64 *sizes,
		     int count, u32 addr_cells, u32 size_cells);
int dt_set_bin_prop_by_path(struct device_tree *tree, const char *path,
			    void *data, size_t size, int create);

void dt_find_bin_prop(const struct device_tree_node *node, const char *name,
		      const void **data, size_t *size);
const char *dt_find_string_prop(const struct device_tree_node *node,
				const char *name);

/* Apply an overlay to a base device tree. Ownership of the overlay data passes
   to the newly combined base tree -- do not free() or access it afterwards! */
int dt_apply_overlay(struct device_tree *tree, struct device_tree *overlay);

/*
 * Fixups to apply to a kernel's device tree before booting it.
 */

struct device_tree_fixup
{
	/**
	 * The function which does the fixing.
	 * 0 on success, non-zero on error.
	 */
	int (*fixup)(struct device_tree_fixup *fixup,
		struct device_tree *tree);

	struct list_node list_node;
};

extern struct list_node device_tree_fixups;

/**
 * Function to apply fixups.
 * 0 on success, non-zero on error.
 */
int dt_apply_fixups(struct device_tree *tree);

/*
 * Init/retrieve the /reserved-memory/ node.
 */
struct device_tree_node *dt_init_reserved_memory_node(struct device_tree *tree);

#endif /* __DEVICE_TREE_H__ */