xref: /rk3399_ARM-atf/common/fdt_wrappers.c (revision 2747362062d4286e47cb13dbdfddfebc6d355dca)
1e5674e1fSSoby Mathew /*
2e5674e1fSSoby Mathew  * Copyright (c) 2018, ARM Limited and Contributors. All rights reserved.
3e5674e1fSSoby Mathew  *
4e5674e1fSSoby Mathew  * SPDX-License-Identifier: BSD-3-Clause
5e5674e1fSSoby Mathew  */
6e5674e1fSSoby Mathew 
7e5674e1fSSoby Mathew /* Helper functions to offer easier navigation of Device Tree Blob */
8e5674e1fSSoby Mathew 
9e5674e1fSSoby Mathew #include <assert.h>
10e5674e1fSSoby Mathew #include <debug.h>
11e5674e1fSSoby Mathew #include <fdt_wrappers.h>
12e5674e1fSSoby Mathew #include <libfdt.h>
13*27473620SAntonio Nino Diaz #include <string.h>
14e5674e1fSSoby Mathew 
15e5674e1fSSoby Mathew /*
16e5674e1fSSoby Mathew  * Read cells from a given property of the given node. At most 2 cells of the
17e5674e1fSSoby Mathew  * property are read, and pointer is updated. Returns 0 on success, and -1 upon
18e5674e1fSSoby Mathew  * error
19e5674e1fSSoby Mathew  */
20e5674e1fSSoby Mathew int fdtw_read_cells(const void *dtb, int node, const char *prop,
21e5674e1fSSoby Mathew 		unsigned int cells, void *value)
22e5674e1fSSoby Mathew {
23e5674e1fSSoby Mathew 	const uint32_t *value_ptr;
24e5674e1fSSoby Mathew 	uint32_t hi = 0, lo;
25e5674e1fSSoby Mathew 	int value_len;
26e5674e1fSSoby Mathew 
27da5f2745SSoby Mathew 	assert(dtb != NULL);
28da5f2745SSoby Mathew 	assert(prop != NULL);
29da5f2745SSoby Mathew 	assert(value != NULL);
30e5674e1fSSoby Mathew 	assert(node >= 0);
31e5674e1fSSoby Mathew 
32e5674e1fSSoby Mathew 	/* We expect either 1 or 2 cell property */
33da5f2745SSoby Mathew 	assert(cells <= 2U);
34e5674e1fSSoby Mathew 
35e5674e1fSSoby Mathew 	/* Access property and obtain its length (in bytes) */
36da5f2745SSoby Mathew 	value_ptr = fdt_getprop_namelen(dtb, node, prop, (int)strlen(prop),
37e5674e1fSSoby Mathew 			&value_len);
38e5674e1fSSoby Mathew 	if (value_ptr == NULL) {
39e5674e1fSSoby Mathew 		WARN("Couldn't find property %s in dtb\n", prop);
40e5674e1fSSoby Mathew 		return -1;
41e5674e1fSSoby Mathew 	}
42e5674e1fSSoby Mathew 
43e5674e1fSSoby Mathew 
44e5674e1fSSoby Mathew 	/* Verify that property length accords with cell length */
45da5f2745SSoby Mathew 	if (NCELLS((unsigned int)value_len) != cells) {
46e5674e1fSSoby Mathew 		WARN("Property length mismatch\n");
47e5674e1fSSoby Mathew 		return -1;
48e5674e1fSSoby Mathew 	}
49e5674e1fSSoby Mathew 
50da5f2745SSoby Mathew 	if (cells == 2U) {
51e5674e1fSSoby Mathew 		hi = fdt32_to_cpu(*value_ptr);
52e5674e1fSSoby Mathew 		value_ptr++;
53e5674e1fSSoby Mathew 	}
54e5674e1fSSoby Mathew 
55e5674e1fSSoby Mathew 	lo = fdt32_to_cpu(*value_ptr);
56e5674e1fSSoby Mathew 
57da5f2745SSoby Mathew 	if (cells == 2U)
58e5674e1fSSoby Mathew 		*((uint64_t *) value) = ((uint64_t) hi << 32) | lo;
59e5674e1fSSoby Mathew 	else
60e5674e1fSSoby Mathew 		*((uint32_t *) value) = lo;
61e5674e1fSSoby Mathew 
62e5674e1fSSoby Mathew 	return 0;
63e5674e1fSSoby Mathew }
64e5674e1fSSoby Mathew 
65e5674e1fSSoby Mathew /*
66*27473620SAntonio Nino Diaz  * Read string from a given property of the given node. Up to 'size - 1'
67*27473620SAntonio Nino Diaz  * characters are read, and a NUL terminator is added. Returns 0 on success,
68*27473620SAntonio Nino Diaz  * and -1 upon error.
69*27473620SAntonio Nino Diaz  */
70*27473620SAntonio Nino Diaz int fdtw_read_string(const void *dtb, int node, const char *prop,
71*27473620SAntonio Nino Diaz 		char *str, size_t size)
72*27473620SAntonio Nino Diaz {
73*27473620SAntonio Nino Diaz 	const char *ptr;
74*27473620SAntonio Nino Diaz 	size_t len;
75*27473620SAntonio Nino Diaz 
76*27473620SAntonio Nino Diaz 	assert(dtb != NULL);
77*27473620SAntonio Nino Diaz 	assert(node >= 0);
78*27473620SAntonio Nino Diaz 	assert(prop != NULL);
79*27473620SAntonio Nino Diaz 	assert(str != NULL);
80*27473620SAntonio Nino Diaz 	assert(size > 0U);
81*27473620SAntonio Nino Diaz 
82*27473620SAntonio Nino Diaz 	ptr = fdt_getprop_namelen(dtb, node, prop, (int)strlen(prop), NULL);
83*27473620SAntonio Nino Diaz 	if (ptr == NULL) {
84*27473620SAntonio Nino Diaz 		WARN("Couldn't find property %s in dtb\n", prop);
85*27473620SAntonio Nino Diaz 		return -1;
86*27473620SAntonio Nino Diaz 	}
87*27473620SAntonio Nino Diaz 
88*27473620SAntonio Nino Diaz 	len = strlcpy(str, ptr, size);
89*27473620SAntonio Nino Diaz 	if (len >= size) {
90*27473620SAntonio Nino Diaz 		WARN("String of property %s in dtb has been truncated\n", prop);
91*27473620SAntonio Nino Diaz 		return -1;
92*27473620SAntonio Nino Diaz 	}
93*27473620SAntonio Nino Diaz 
94*27473620SAntonio Nino Diaz 	return 0;
95*27473620SAntonio Nino Diaz }
96*27473620SAntonio Nino Diaz 
97*27473620SAntonio Nino Diaz /*
98e5674e1fSSoby Mathew  * Write cells in place to a given property of the given node. At most 2 cells
99e5674e1fSSoby Mathew  * of the property are written. Returns 0 on success, and -1 upon error.
100e5674e1fSSoby Mathew  */
101e5674e1fSSoby Mathew int fdtw_write_inplace_cells(void *dtb, int node, const char *prop,
102e5674e1fSSoby Mathew 		unsigned int cells, void *value)
103e5674e1fSSoby Mathew {
104e5674e1fSSoby Mathew 	int err, len;
105e5674e1fSSoby Mathew 
106da5f2745SSoby Mathew 	assert(dtb != NULL);
107da5f2745SSoby Mathew 	assert(prop != NULL);
108da5f2745SSoby Mathew 	assert(value != NULL);
109e5674e1fSSoby Mathew 	assert(node >= 0);
110e5674e1fSSoby Mathew 
111e5674e1fSSoby Mathew 	/* We expect either 1 or 2 cell property */
112da5f2745SSoby Mathew 	assert(cells <= 2U);
113e5674e1fSSoby Mathew 
114da5f2745SSoby Mathew 	if (cells == 2U)
115e5674e1fSSoby Mathew 		*(uint64_t *)value = cpu_to_fdt64(*(uint64_t *)value);
116e5674e1fSSoby Mathew 	else
117e5674e1fSSoby Mathew 		*(uint32_t *)value = cpu_to_fdt32(*(uint32_t *)value);
118e5674e1fSSoby Mathew 
119da5f2745SSoby Mathew 	len = (int)cells * 4;
120e5674e1fSSoby Mathew 
121e5674e1fSSoby Mathew 	/* Set property value in place */
122e5674e1fSSoby Mathew 	err = fdt_setprop_inplace(dtb, node, prop, value, len);
123e5674e1fSSoby Mathew 	if (err != 0) {
124e5674e1fSSoby Mathew 		WARN("Modify property %s failed with error %d\n", prop, err);
125e5674e1fSSoby Mathew 		return -1;
126e5674e1fSSoby Mathew 	}
127e5674e1fSSoby Mathew 
128e5674e1fSSoby Mathew 	return 0;
129e5674e1fSSoby Mathew }
130