xref: /rk3399_ARM-atf/common/fdt_wrappers.c (revision 09d40e0e08283a249e7dce0e106c07c5141f9b7e)
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>
1027473620SAntonio Nino Diaz #include <string.h>
11e5674e1fSSoby Mathew 
12*09d40e0eSAntonio Nino Diaz #include <libfdt.h>
13*09d40e0eSAntonio Nino Diaz 
14*09d40e0eSAntonio Nino Diaz #include <common/debug.h>
15*09d40e0eSAntonio Nino Diaz #include <common/fdt_wrappers.h>
16*09d40e0eSAntonio Nino Diaz 
17e5674e1fSSoby Mathew /*
18e5674e1fSSoby Mathew  * Read cells from a given property of the given node. At most 2 cells of the
19e5674e1fSSoby Mathew  * property are read, and pointer is updated. Returns 0 on success, and -1 upon
20e5674e1fSSoby Mathew  * error
21e5674e1fSSoby Mathew  */
22e5674e1fSSoby Mathew int fdtw_read_cells(const void *dtb, int node, const char *prop,
23e5674e1fSSoby Mathew 		unsigned int cells, void *value)
24e5674e1fSSoby Mathew {
25e5674e1fSSoby Mathew 	const uint32_t *value_ptr;
26e5674e1fSSoby Mathew 	uint32_t hi = 0, lo;
27e5674e1fSSoby Mathew 	int value_len;
28e5674e1fSSoby Mathew 
29da5f2745SSoby Mathew 	assert(dtb != NULL);
30da5f2745SSoby Mathew 	assert(prop != NULL);
31da5f2745SSoby Mathew 	assert(value != NULL);
32e5674e1fSSoby Mathew 	assert(node >= 0);
33e5674e1fSSoby Mathew 
34e5674e1fSSoby Mathew 	/* We expect either 1 or 2 cell property */
35da5f2745SSoby Mathew 	assert(cells <= 2U);
36e5674e1fSSoby Mathew 
37e5674e1fSSoby Mathew 	/* Access property and obtain its length (in bytes) */
38da5f2745SSoby Mathew 	value_ptr = fdt_getprop_namelen(dtb, node, prop, (int)strlen(prop),
39e5674e1fSSoby Mathew 			&value_len);
40e5674e1fSSoby Mathew 	if (value_ptr == NULL) {
41e5674e1fSSoby Mathew 		WARN("Couldn't find property %s in dtb\n", prop);
42e5674e1fSSoby Mathew 		return -1;
43e5674e1fSSoby Mathew 	}
44e5674e1fSSoby Mathew 
45e5674e1fSSoby Mathew 	/* Verify that property length accords with cell length */
46da5f2745SSoby Mathew 	if (NCELLS((unsigned int)value_len) != cells) {
47e5674e1fSSoby Mathew 		WARN("Property length mismatch\n");
48e5674e1fSSoby Mathew 		return -1;
49e5674e1fSSoby Mathew 	}
50e5674e1fSSoby Mathew 
51da5f2745SSoby Mathew 	if (cells == 2U) {
52e5674e1fSSoby Mathew 		hi = fdt32_to_cpu(*value_ptr);
53e5674e1fSSoby Mathew 		value_ptr++;
54e5674e1fSSoby Mathew 	}
55e5674e1fSSoby Mathew 
56e5674e1fSSoby Mathew 	lo = fdt32_to_cpu(*value_ptr);
57e5674e1fSSoby Mathew 
58da5f2745SSoby Mathew 	if (cells == 2U)
59e5674e1fSSoby Mathew 		*((uint64_t *) value) = ((uint64_t) hi << 32) | lo;
60e5674e1fSSoby Mathew 	else
61e5674e1fSSoby Mathew 		*((uint32_t *) value) = lo;
62e5674e1fSSoby Mathew 
63e5674e1fSSoby Mathew 	return 0;
64e5674e1fSSoby Mathew }
65e5674e1fSSoby Mathew 
66e5674e1fSSoby Mathew /*
6773f1ac6cSAntonio Nino Diaz  * Read cells from a given property of the given node. Any number of 32-bit
6873f1ac6cSAntonio Nino Diaz  * cells of the property can be read. The fdt pointer is updated. Returns 0 on
6973f1ac6cSAntonio Nino Diaz  * success, and -1 on error.
7073f1ac6cSAntonio Nino Diaz  */
7173f1ac6cSAntonio Nino Diaz int fdtw_read_array(const void *dtb, int node, const char *prop,
7273f1ac6cSAntonio Nino Diaz 		unsigned int cells, void *value)
7373f1ac6cSAntonio Nino Diaz {
7473f1ac6cSAntonio Nino Diaz 	const uint32_t *value_ptr;
7573f1ac6cSAntonio Nino Diaz 	int value_len;
7673f1ac6cSAntonio Nino Diaz 
7773f1ac6cSAntonio Nino Diaz 	assert(dtb != NULL);
7873f1ac6cSAntonio Nino Diaz 	assert(prop != NULL);
7973f1ac6cSAntonio Nino Diaz 	assert(value != NULL);
8073f1ac6cSAntonio Nino Diaz 	assert(node >= 0);
8173f1ac6cSAntonio Nino Diaz 
8273f1ac6cSAntonio Nino Diaz 	/* Access property and obtain its length (in bytes) */
8373f1ac6cSAntonio Nino Diaz 	value_ptr = fdt_getprop_namelen(dtb, node, prop, (int)strlen(prop),
8473f1ac6cSAntonio Nino Diaz 			&value_len);
8573f1ac6cSAntonio Nino Diaz 	if (value_ptr == NULL) {
8673f1ac6cSAntonio Nino Diaz 		WARN("Couldn't find property %s in dtb\n", prop);
8773f1ac6cSAntonio Nino Diaz 		return -1;
8873f1ac6cSAntonio Nino Diaz 	}
8973f1ac6cSAntonio Nino Diaz 
9073f1ac6cSAntonio Nino Diaz 	/* Verify that property length accords with cell length */
9173f1ac6cSAntonio Nino Diaz 	if (NCELLS((unsigned int)value_len) != cells) {
9273f1ac6cSAntonio Nino Diaz 		WARN("Property length mismatch\n");
9373f1ac6cSAntonio Nino Diaz 		return -1;
9473f1ac6cSAntonio Nino Diaz 	}
9573f1ac6cSAntonio Nino Diaz 
9673f1ac6cSAntonio Nino Diaz 	uint32_t *dst = value;
9773f1ac6cSAntonio Nino Diaz 
9873f1ac6cSAntonio Nino Diaz 	for (unsigned int i = 0U; i < cells; i++) {
9973f1ac6cSAntonio Nino Diaz 		dst[i] = fdt32_to_cpu(value_ptr[i]);
10073f1ac6cSAntonio Nino Diaz 	}
10173f1ac6cSAntonio Nino Diaz 
10273f1ac6cSAntonio Nino Diaz 	return 0;
10373f1ac6cSAntonio Nino Diaz }
10473f1ac6cSAntonio Nino Diaz 
10573f1ac6cSAntonio Nino Diaz /*
10627473620SAntonio Nino Diaz  * Read string from a given property of the given node. Up to 'size - 1'
10727473620SAntonio Nino Diaz  * characters are read, and a NUL terminator is added. Returns 0 on success,
10827473620SAntonio Nino Diaz  * and -1 upon error.
10927473620SAntonio Nino Diaz  */
11027473620SAntonio Nino Diaz int fdtw_read_string(const void *dtb, int node, const char *prop,
11127473620SAntonio Nino Diaz 		char *str, size_t size)
11227473620SAntonio Nino Diaz {
11327473620SAntonio Nino Diaz 	const char *ptr;
11427473620SAntonio Nino Diaz 	size_t len;
11527473620SAntonio Nino Diaz 
11627473620SAntonio Nino Diaz 	assert(dtb != NULL);
11727473620SAntonio Nino Diaz 	assert(node >= 0);
11827473620SAntonio Nino Diaz 	assert(prop != NULL);
11927473620SAntonio Nino Diaz 	assert(str != NULL);
12027473620SAntonio Nino Diaz 	assert(size > 0U);
12127473620SAntonio Nino Diaz 
12227473620SAntonio Nino Diaz 	ptr = fdt_getprop_namelen(dtb, node, prop, (int)strlen(prop), NULL);
12327473620SAntonio Nino Diaz 	if (ptr == NULL) {
12427473620SAntonio Nino Diaz 		WARN("Couldn't find property %s in dtb\n", prop);
12527473620SAntonio Nino Diaz 		return -1;
12627473620SAntonio Nino Diaz 	}
12727473620SAntonio Nino Diaz 
12827473620SAntonio Nino Diaz 	len = strlcpy(str, ptr, size);
12927473620SAntonio Nino Diaz 	if (len >= size) {
13027473620SAntonio Nino Diaz 		WARN("String of property %s in dtb has been truncated\n", prop);
13127473620SAntonio Nino Diaz 		return -1;
13227473620SAntonio Nino Diaz 	}
13327473620SAntonio Nino Diaz 
13427473620SAntonio Nino Diaz 	return 0;
13527473620SAntonio Nino Diaz }
13627473620SAntonio Nino Diaz 
13727473620SAntonio Nino Diaz /*
138e5674e1fSSoby Mathew  * Write cells in place to a given property of the given node. At most 2 cells
139e5674e1fSSoby Mathew  * of the property are written. Returns 0 on success, and -1 upon error.
140e5674e1fSSoby Mathew  */
141e5674e1fSSoby Mathew int fdtw_write_inplace_cells(void *dtb, int node, const char *prop,
142e5674e1fSSoby Mathew 		unsigned int cells, void *value)
143e5674e1fSSoby Mathew {
144e5674e1fSSoby Mathew 	int err, len;
145e5674e1fSSoby Mathew 
146da5f2745SSoby Mathew 	assert(dtb != NULL);
147da5f2745SSoby Mathew 	assert(prop != NULL);
148da5f2745SSoby Mathew 	assert(value != NULL);
149e5674e1fSSoby Mathew 	assert(node >= 0);
150e5674e1fSSoby Mathew 
151e5674e1fSSoby Mathew 	/* We expect either 1 or 2 cell property */
152da5f2745SSoby Mathew 	assert(cells <= 2U);
153e5674e1fSSoby Mathew 
154da5f2745SSoby Mathew 	if (cells == 2U)
155e5674e1fSSoby Mathew 		*(uint64_t *)value = cpu_to_fdt64(*(uint64_t *)value);
156e5674e1fSSoby Mathew 	else
157e5674e1fSSoby Mathew 		*(uint32_t *)value = cpu_to_fdt32(*(uint32_t *)value);
158e5674e1fSSoby Mathew 
159da5f2745SSoby Mathew 	len = (int)cells * 4;
160e5674e1fSSoby Mathew 
161e5674e1fSSoby Mathew 	/* Set property value in place */
162e5674e1fSSoby Mathew 	err = fdt_setprop_inplace(dtb, node, prop, value, len);
163e5674e1fSSoby Mathew 	if (err != 0) {
164e5674e1fSSoby Mathew 		WARN("Modify property %s failed with error %d\n", prop, err);
165e5674e1fSSoby Mathew 		return -1;
166e5674e1fSSoby Mathew 	}
167e5674e1fSSoby Mathew 
168e5674e1fSSoby Mathew 	return 0;
169e5674e1fSSoby Mathew }
170