summaryrefslogtreecommitdiff
path: root/src/include/device_tree.h
blob: 7a2cfb20be785e11abdd56716f2e06d6d4904877 (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
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
/*
 * Copyright 2013 Google Inc.
 *
 * See file CREDITS for list of people who contributed to this
 * project.
 *
 * This program is free software; you can redistribute it and/or
 * modify it under the terms of the GNU General Public License as
 * published by the Free Software Foundation; either version 2 of
 * the License, or (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but without any warranty; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 */

#ifndef __BASE_DEVICE_TREE_H__
#define __BASE_DEVICE_TREE_H__

#include <stdint.h>

#include "base/list.h"

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

typedef struct FdtHeader {
	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_compatible_version;

	uint32_t boot_cpuid_phys;

	uint32_t strings_size;
	uint32_t structure_size;
} FdtHeader;

static const uint32_t FdtMagic = 0xd00dfeed;

static const uint32_t TokenBeginNode = 1;
static const uint32_t TokenEndNode = 2;
static const uint32_t TokenProperty = 3;
static const uint32_t TokenEnd = 9;

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



/*
 * Unflattened device tree structures.
 */

typedef struct DeviceTreeProperty
{
	FdtProperty prop;

	ListNode list_node;
} DeviceTreeProperty;

typedef struct DeviceTreeNode
{
	const char *name;
	// List of DeviceTreeProperty-s.
	ListNode properties;
	// List of DeviceTreeNodes.
	ListNode children;

	ListNode list_node;
} DeviceTreeNode;

typedef struct DeviceTreeReserveMapEntry
{
	uint64_t start;
	uint64_t size;

	ListNode list_node;
} DeviceTreeReserveMapEntry;

typedef struct DeviceTree
{
	void *header;
	uint32_t header_size;

	ListNode reserve_map;

	DeviceTreeNode *root;
} DeviceTree;



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

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

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

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



/*
 * Unflattened device tree functions.
 */

// Figure out how big a device tree would be if it were flattened.
uint32_t dt_flat_size(DeviceTree *tree);
// Flatten a device tree into the buffer pointed to by dest.
void dt_flatten(DeviceTree *tree, void *dest);
void dt_print_node(DeviceTreeNode *node);
// Read #address-cells and #size-cells properties from a node.
void dt_read_cell_props(DeviceTreeNode *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.
DeviceTreeNode *dt_find_node(DeviceTreeNode *parent, const char **path,
			     u32 *addrcp, u32 *sizecp, int create);
// Look up or create a node relative to a parent node, through its path
// represented as a string of '/' separated node names.
DeviceTreeNode *dt_find_node_by_path(DeviceTreeNode *parent, const char *path,
				     u32 *addrcp, u32 *sizecp, int create);
// Look up a node relative to a parent node, through its compatible string.
DeviceTreeNode *dt_find_compat(DeviceTreeNode *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.
DeviceTreeNode *dt_find_next_compat_child(DeviceTreeNode *parent,
					  DeviceTreeNode *child,
					  const char *compat);
// Look up a node relative to a parent node, through its property value.
DeviceTreeNode *dt_find_prop_value(DeviceTreeNode *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);
// Add different kinds of properties to a node, or update existing ones.
void dt_add_bin_prop(DeviceTreeNode *node, char *name, void *data, size_t size);
void dt_add_string_prop(DeviceTreeNode *node, char *name, char *str);
void dt_add_u32_prop(DeviceTreeNode *node, char *name, u32 val);
void dt_add_reg_prop(DeviceTreeNode *node, u64 *addrs, u64 *sizes,
		     int count, u32 addr_cells, u32 size_cells);
int dt_set_bin_prop_by_path(DeviceTree *tree, const char *path,
			    void *data, size_t size, int create);

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

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

typedef struct DeviceTreeFixup
{
	// The function which does the fixing.
	int (*fixup)(struct DeviceTreeFixup *fixup, DeviceTree *tree);

	ListNode list_node;
} DeviceTreeFixup;

extern ListNode device_tree_fixups;

int dt_apply_fixups(DeviceTree *tree);

/*
 * Structure defining mapping between arbitrary objects and the device tree
 * path to the property corresponding to the object.
 */
typedef struct {
	int force_create; /* If false - do not create a new node. */
	const char *dt_path;
	const char *key;
} DtPathMap;

/*
 * Copy mac addresses from sysinfo table into the device tree. The mapping
 * between the dt_maps entries and sysinfo mac address table elements is
 * implicit, i.e. the device tree node found in the maps entry, gets assinged
 * the mac address found in the sysinfo table, in the same order.
  */
int dt_set_mac_addresses(DeviceTree *tree, const DtPathMap *dt_maps);

/*
 * Copy WIFI calibration data from sysinfo table into the device tree. Each
 * WIFI calibration blob stored the sysinfo table contains key and data. The
 * key is used for mapping into the device tree path. The data becomes the
 * contents of the device tree property at that path.
 */
int dt_set_wifi_calibration(DeviceTree *tree, const DtPathMap *maps);

/*
 * Retrieve Country Code data from VPD and add it into the device tree.
 */
int dt_set_wifi_country_code(DeviceTree *tree, const DtPathMap *maps);

/*
 * Init/retrieve the /reserved-memory/ node.
 */
DeviceTreeNode *dt_init_reserved_memory_node(DeviceTree *tree);

#endif /* __BASE_DEVICE_TREE_H__ */