xref: /rk3399_ARM-atf/plat/arm/common/arm_dyn_cfg_helpers.c (revision 1d71ba141d32c9e8974d4e3e973a90fd0c6bf458)
1cab0b5b0SSoby Mathew /*
2cab0b5b0SSoby Mathew  * Copyright (c) 2018, ARM Limited and Contributors. All rights reserved.
3cab0b5b0SSoby Mathew  *
4cab0b5b0SSoby Mathew  * SPDX-License-Identifier: BSD-3-Clause
5cab0b5b0SSoby Mathew  */
6cab0b5b0SSoby Mathew 
735a3eeb6SRoberto Vargas #include <arm_dyn_cfg_helpers.h>
8cab0b5b0SSoby Mathew #include <assert.h>
9cab0b5b0SSoby Mathew #include <desc_image_load.h>
10cab0b5b0SSoby Mathew #include <fdt_wrappers.h>
11cab0b5b0SSoby Mathew #include <libfdt.h>
12da5f2745SSoby Mathew #include <plat_arm.h>
13cab0b5b0SSoby Mathew 
14*1d71ba14SSoby Mathew 
15*1d71ba14SSoby Mathew typedef struct config_load_info_prop {
16*1d71ba14SSoby Mathew 	unsigned int config_id;
17*1d71ba14SSoby Mathew 	const char *config_addr;
18*1d71ba14SSoby Mathew 	const char *config_max_size;
19*1d71ba14SSoby Mathew } config_load_info_prop_t;
20*1d71ba14SSoby Mathew 
21*1d71ba14SSoby Mathew static const config_load_info_prop_t prop_names[] = {
22*1d71ba14SSoby Mathew 	{HW_CONFIG_ID, "hw_config_addr", "hw_config_max_size"},
23*1d71ba14SSoby Mathew 	{SOC_FW_CONFIG_ID, "soc_fw_config_addr", "soc_fw_config_max_size"},
24*1d71ba14SSoby Mathew 	{TOS_FW_CONFIG_ID, "tos_fw_config_addr", "tos_fw_config_max_size"},
25*1d71ba14SSoby Mathew 	{NT_FW_CONFIG_ID, "nt_fw_config_addr", "nt_fw_config_max_size"}
26*1d71ba14SSoby Mathew };
27*1d71ba14SSoby Mathew 
28cab0b5b0SSoby Mathew /*******************************************************************************
29*1d71ba14SSoby Mathew  * Helper to read the load information corresponding to the `config_id` in
30*1d71ba14SSoby Mathew  * TB_FW_CONFIG. This function expects the following properties to be defined :
31*1d71ba14SSoby Mathew  *	<config>_addr		size : 2 cells
32*1d71ba14SSoby Mathew  *	<config>_max_size	size : 1 cell
33cab0b5b0SSoby Mathew  *
34cab0b5b0SSoby Mathew  * Arguments:
35cab0b5b0SSoby Mathew  *	void *dtb		 - pointer to the TB_FW_CONFIG in memory
36cab0b5b0SSoby Mathew  *	int node		 - The node offset to appropriate node in the
37cab0b5b0SSoby Mathew  *					 DTB.
38*1d71ba14SSoby Mathew  *	unsigned int config_id	 - The configuration id
39*1d71ba14SSoby Mathew  *	uint64_t *config_addr	 - Returns the `config` load address if read
40cab0b5b0SSoby Mathew  *					 is successful.
41*1d71ba14SSoby Mathew  *	uint32_t *config_size	 - Returns the `config` size if read is
42cab0b5b0SSoby Mathew  *					 successful.
43cab0b5b0SSoby Mathew  *
44cab0b5b0SSoby Mathew  * Returns 0 on success and -1 on error.
45cab0b5b0SSoby Mathew  ******************************************************************************/
46*1d71ba14SSoby Mathew int arm_dyn_get_config_load_info(void *dtb, int node, unsigned int config_id,
47*1d71ba14SSoby Mathew 		uint64_t *config_addr, uint32_t *config_size)
48cab0b5b0SSoby Mathew {
49cab0b5b0SSoby Mathew 	int err;
50*1d71ba14SSoby Mathew 	unsigned int i;
51cab0b5b0SSoby Mathew 
52da5f2745SSoby Mathew 	assert(dtb != NULL);
53*1d71ba14SSoby Mathew 	assert(config_addr != NULL);
54*1d71ba14SSoby Mathew 	assert(config_size != NULL);
55*1d71ba14SSoby Mathew 
56*1d71ba14SSoby Mathew 	for (i = 0; i < ARRAY_SIZE(prop_names); i++) {
57*1d71ba14SSoby Mathew 		if (prop_names[i].config_id == config_id)
58*1d71ba14SSoby Mathew 			break;
59*1d71ba14SSoby Mathew 	}
60*1d71ba14SSoby Mathew 
61*1d71ba14SSoby Mathew 	if (i == ARRAY_SIZE(prop_names)) {
62*1d71ba14SSoby Mathew 		WARN("Invalid config id %d\n", config_id);
63*1d71ba14SSoby Mathew 		return -1;
64*1d71ba14SSoby Mathew 	}
65cab0b5b0SSoby Mathew 
66cab0b5b0SSoby Mathew 	/* Check if the pointer to DT is correct */
67cab0b5b0SSoby Mathew 	assert(fdt_check_header(dtb) == 0);
68cab0b5b0SSoby Mathew 
69cab0b5b0SSoby Mathew 	/* Assert the node offset point to "arm,tb_fw" compatible property */
70cab0b5b0SSoby Mathew 	assert(node == fdt_node_offset_by_compatible(dtb, -1, "arm,tb_fw"));
71cab0b5b0SSoby Mathew 
72*1d71ba14SSoby Mathew 	err = fdtw_read_cells(dtb, node, prop_names[i].config_addr, 2,
73*1d71ba14SSoby Mathew 				(void *) config_addr);
74cab0b5b0SSoby Mathew 	if (err < 0) {
75*1d71ba14SSoby Mathew 		WARN("Read cell failed for %s\n", prop_names[i].config_addr);
76cab0b5b0SSoby Mathew 		return -1;
77cab0b5b0SSoby Mathew 	}
78cab0b5b0SSoby Mathew 
79*1d71ba14SSoby Mathew 	err = fdtw_read_cells(dtb, node, prop_names[i].config_max_size, 1,
80*1d71ba14SSoby Mathew 				(void *) config_size);
81cab0b5b0SSoby Mathew 	if (err < 0) {
82*1d71ba14SSoby Mathew 		WARN("Read cell failed for %s\n", prop_names[i].config_max_size);
83cab0b5b0SSoby Mathew 		return -1;
84cab0b5b0SSoby Mathew 	}
85cab0b5b0SSoby Mathew 
86*1d71ba14SSoby Mathew 	VERBOSE("Dyn cfg: Read config_id %d load info from TB_FW_CONFIG 0x%llx 0x%x\n",
87*1d71ba14SSoby Mathew 				config_id, (unsigned long long)*config_addr, *config_size);
88cab0b5b0SSoby Mathew 
89cab0b5b0SSoby Mathew 	return 0;
90cab0b5b0SSoby Mathew }
91cab0b5b0SSoby Mathew 
92cab0b5b0SSoby Mathew /*******************************************************************************
936e79f9fdSSoby Mathew  * Helper to read the `disable_auth` property in config DTB. This function
946e79f9fdSSoby Mathew  * expects the following properties to be present in the config DTB.
956e79f9fdSSoby Mathew  *	name : disable_auth		size : 1 cell
966e79f9fdSSoby Mathew  *
976e79f9fdSSoby Mathew  * Arguments:
986e79f9fdSSoby Mathew  *	void *dtb		 - pointer to the TB_FW_CONFIG in memory
996e79f9fdSSoby Mathew  *	int node		 - The node offset to appropriate node in the
1006e79f9fdSSoby Mathew  *				   DTB.
1016e79f9fdSSoby Mathew  *	uint64_t *disable_auth	 - The value of `disable_auth` property on
1026e79f9fdSSoby Mathew  *				   successful read. Must be 0 or 1.
1036e79f9fdSSoby Mathew  *
1046e79f9fdSSoby Mathew  * Returns 0 on success and -1 on error.
1056e79f9fdSSoby Mathew  ******************************************************************************/
1066e79f9fdSSoby Mathew int arm_dyn_get_disable_auth(void *dtb, int node, uint32_t *disable_auth)
1076e79f9fdSSoby Mathew {
1086e79f9fdSSoby Mathew 	int err;
1096e79f9fdSSoby Mathew 
1106e79f9fdSSoby Mathew 	assert(dtb != NULL);
1116e79f9fdSSoby Mathew 	assert(disable_auth != NULL);
1126e79f9fdSSoby Mathew 
1136e79f9fdSSoby Mathew 	/* Check if the pointer to DT is correct */
1146e79f9fdSSoby Mathew 	assert(fdt_check_header(dtb) == 0);
1156e79f9fdSSoby Mathew 
1166e79f9fdSSoby Mathew 	/* Assert the node offset point to "arm,tb_fw" compatible property */
1176e79f9fdSSoby Mathew 	assert(node == fdt_node_offset_by_compatible(dtb, -1, "arm,tb_fw"));
1186e79f9fdSSoby Mathew 
1196e79f9fdSSoby Mathew 	/* Locate the disable_auth cell and read the value */
1206e79f9fdSSoby Mathew 	err = fdtw_read_cells(dtb, node, "disable_auth", 1, disable_auth);
1216e79f9fdSSoby Mathew 	if (err < 0) {
1226e79f9fdSSoby Mathew 		WARN("Read cell failed for `disable_auth`\n");
1236e79f9fdSSoby Mathew 		return -1;
1246e79f9fdSSoby Mathew 	}
1256e79f9fdSSoby Mathew 
1266e79f9fdSSoby Mathew 	/* Check if the value is boolean */
127*1d71ba14SSoby Mathew 	if ((*disable_auth != 0U) && (*disable_auth != 1U)) {
1286e79f9fdSSoby Mathew 		WARN("Invalid value for `disable_auth` cell %d\n", *disable_auth);
1296e79f9fdSSoby Mathew 		return -1;
1306e79f9fdSSoby Mathew 	}
1316e79f9fdSSoby Mathew 
1326e79f9fdSSoby Mathew 	VERBOSE("Dyn cfg: `disable_auth` cell found with value = %d\n",
1336e79f9fdSSoby Mathew 					*disable_auth);
1346e79f9fdSSoby Mathew 	return 0;
1356e79f9fdSSoby Mathew }
1366e79f9fdSSoby Mathew 
1376e79f9fdSSoby Mathew /*******************************************************************************
138cab0b5b0SSoby Mathew  * Validate the tb_fw_config is a valid DTB file and returns the node offset
139cab0b5b0SSoby Mathew  * to "arm,tb_fw" property.
140cab0b5b0SSoby Mathew  * Arguments:
141cab0b5b0SSoby Mathew  *	void *dtb - pointer to the TB_FW_CONFIG in memory
142cab0b5b0SSoby Mathew  *	int *node - Returns the node offset to "arm,tb_fw" property if found.
143cab0b5b0SSoby Mathew  *
144cab0b5b0SSoby Mathew  * Returns 0 on success and -1 on error.
145cab0b5b0SSoby Mathew  ******************************************************************************/
146cab0b5b0SSoby Mathew int arm_dyn_tb_fw_cfg_init(void *dtb, int *node)
147cab0b5b0SSoby Mathew {
148da5f2745SSoby Mathew 	assert(dtb != NULL);
149da5f2745SSoby Mathew 	assert(node != NULL);
150cab0b5b0SSoby Mathew 
151cab0b5b0SSoby Mathew 	/* Check if the pointer to DT is correct */
152cab0b5b0SSoby Mathew 	if (fdt_check_header(dtb) != 0) {
153cab0b5b0SSoby Mathew 		WARN("Invalid DTB file passed as TB_FW_CONFIG\n");
154cab0b5b0SSoby Mathew 		return -1;
155cab0b5b0SSoby Mathew 	}
156cab0b5b0SSoby Mathew 
157cab0b5b0SSoby Mathew 	/* Assert the node offset point to "arm,tb_fw" compatible property */
158cab0b5b0SSoby Mathew 	*node = fdt_node_offset_by_compatible(dtb, -1, "arm,tb_fw");
159cab0b5b0SSoby Mathew 	if (*node < 0) {
160cab0b5b0SSoby Mathew 		WARN("The compatible property `arm,tb_fw` not found in the config\n");
161cab0b5b0SSoby Mathew 		return -1;
162cab0b5b0SSoby Mathew 	}
163cab0b5b0SSoby Mathew 
164cab0b5b0SSoby Mathew 	VERBOSE("Dyn cfg: Found \"arm,tb_fw\" in the config\n");
165cab0b5b0SSoby Mathew 	return 0;
166cab0b5b0SSoby Mathew }
167