xref: /rk3399_ARM-atf/plat/arm/common/arm_dyn_cfg_helpers.c (revision ff2743e544f0f82381ebb9dff8f14eacb837d2e0)
1 /*
2  * Copyright (c) 2018, ARM Limited and Contributors. All rights reserved.
3  *
4  * SPDX-License-Identifier: BSD-3-Clause
5  */
6 
7 #include <arm_dyn_cfg_helpers.h>
8 #include <assert.h>
9 #include <desc_image_load.h>
10 #include <fdt_wrappers.h>
11 #include <libfdt.h>
12 #include <plat_arm.h>
13 
14 
15 typedef struct config_load_info_prop {
16 	unsigned int config_id;
17 	const char *config_addr;
18 	const char *config_max_size;
19 } config_load_info_prop_t;
20 
21 static const config_load_info_prop_t prop_names[] = {
22 	{HW_CONFIG_ID, "hw_config_addr", "hw_config_max_size"},
23 	{SOC_FW_CONFIG_ID, "soc_fw_config_addr", "soc_fw_config_max_size"},
24 	{TOS_FW_CONFIG_ID, "tos_fw_config_addr", "tos_fw_config_max_size"},
25 	{NT_FW_CONFIG_ID, "nt_fw_config_addr", "nt_fw_config_max_size"}
26 };
27 
28 /*******************************************************************************
29  * Helper to read the load information corresponding to the `config_id` in
30  * TB_FW_CONFIG. This function expects the following properties to be defined :
31  *	<config>_addr		size : 2 cells
32  *	<config>_max_size	size : 1 cell
33  *
34  * Arguments:
35  *	void *dtb		 - pointer to the TB_FW_CONFIG in memory
36  *	int node		 - The node offset to appropriate node in the
37  *					 DTB.
38  *	unsigned int config_id	 - The configuration id
39  *	uint64_t *config_addr	 - Returns the `config` load address if read
40  *					 is successful.
41  *	uint32_t *config_size	 - Returns the `config` size if read is
42  *					 successful.
43  *
44  * Returns 0 on success and -1 on error.
45  ******************************************************************************/
46 int arm_dyn_get_config_load_info(void *dtb, int node, unsigned int config_id,
47 		uint64_t *config_addr, uint32_t *config_size)
48 {
49 	int err;
50 	unsigned int i;
51 
52 	assert(dtb != NULL);
53 	assert(config_addr != NULL);
54 	assert(config_size != NULL);
55 
56 	for (i = 0; i < ARRAY_SIZE(prop_names); i++) {
57 		if (prop_names[i].config_id == config_id)
58 			break;
59 	}
60 
61 	if (i == ARRAY_SIZE(prop_names)) {
62 		WARN("Invalid config id %d\n", config_id);
63 		return -1;
64 	}
65 
66 	/* Check if the pointer to DT is correct */
67 	assert(fdt_check_header(dtb) == 0);
68 
69 	/* Assert the node offset point to "arm,tb_fw" compatible property */
70 	assert(node == fdt_node_offset_by_compatible(dtb, -1, "arm,tb_fw"));
71 
72 	err = fdtw_read_cells(dtb, node, prop_names[i].config_addr, 2,
73 				(void *) config_addr);
74 	if (err < 0) {
75 		WARN("Read cell failed for %s\n", prop_names[i].config_addr);
76 		return -1;
77 	}
78 
79 	err = fdtw_read_cells(dtb, node, prop_names[i].config_max_size, 1,
80 				(void *) config_size);
81 	if (err < 0) {
82 		WARN("Read cell failed for %s\n", prop_names[i].config_max_size);
83 		return -1;
84 	}
85 
86 	VERBOSE("Dyn cfg: Read config_id %d load info from TB_FW_CONFIG 0x%llx 0x%x\n",
87 				config_id, (unsigned long long)*config_addr, *config_size);
88 
89 	return 0;
90 }
91 
92 /*******************************************************************************
93  * Helper to read the `disable_auth` property in config DTB. This function
94  * expects the following properties to be present in the config DTB.
95  *	name : disable_auth		size : 1 cell
96  *
97  * Arguments:
98  *	void *dtb		 - pointer to the TB_FW_CONFIG in memory
99  *	int node		 - The node offset to appropriate node in the
100  *				   DTB.
101  *	uint64_t *disable_auth	 - The value of `disable_auth` property on
102  *				   successful read. Must be 0 or 1.
103  *
104  * Returns 0 on success and -1 on error.
105  ******************************************************************************/
106 int arm_dyn_get_disable_auth(void *dtb, int node, uint32_t *disable_auth)
107 {
108 	int err;
109 
110 	assert(dtb != NULL);
111 	assert(disable_auth != NULL);
112 
113 	/* Check if the pointer to DT is correct */
114 	assert(fdt_check_header(dtb) == 0);
115 
116 	/* Assert the node offset point to "arm,tb_fw" compatible property */
117 	assert(node == fdt_node_offset_by_compatible(dtb, -1, "arm,tb_fw"));
118 
119 	/* Locate the disable_auth cell and read the value */
120 	err = fdtw_read_cells(dtb, node, "disable_auth", 1, disable_auth);
121 	if (err < 0) {
122 		WARN("Read cell failed for `disable_auth`\n");
123 		return -1;
124 	}
125 
126 	/* Check if the value is boolean */
127 	if ((*disable_auth != 0U) && (*disable_auth != 1U)) {
128 		WARN("Invalid value for `disable_auth` cell %d\n", *disable_auth);
129 		return -1;
130 	}
131 
132 	VERBOSE("Dyn cfg: `disable_auth` cell found with value = %d\n",
133 					*disable_auth);
134 	return 0;
135 }
136 
137 /*******************************************************************************
138  * Validate the tb_fw_config is a valid DTB file and returns the node offset
139  * to "arm,tb_fw" property.
140  * Arguments:
141  *	void *dtb - pointer to the TB_FW_CONFIG in memory
142  *	int *node - Returns the node offset to "arm,tb_fw" property if found.
143  *
144  * Returns 0 on success and -1 on error.
145  ******************************************************************************/
146 int arm_dyn_tb_fw_cfg_init(void *dtb, int *node)
147 {
148 	assert(dtb != NULL);
149 	assert(node != NULL);
150 
151 	/* Check if the pointer to DT is correct */
152 	if (fdt_check_header(dtb) != 0) {
153 		WARN("Invalid DTB file passed as TB_FW_CONFIG\n");
154 		return -1;
155 	}
156 
157 	/* Assert the node offset point to "arm,tb_fw" compatible property */
158 	*node = fdt_node_offset_by_compatible(dtb, -1, "arm,tb_fw");
159 	if (*node < 0) {
160 		WARN("The compatible property `arm,tb_fw` not found in the config\n");
161 		return -1;
162 	}
163 
164 	VERBOSE("Dyn cfg: Found \"arm,tb_fw\" in the config\n");
165 	return 0;
166 }
167