arm_fconf_sp.c 4.39 KB
Newer Older
1
2
3
4
5
6
7
8
9
/*
 * Copyright (c) 2020, ARM Limited and Contributors. All rights reserved.
 *
 * SPDX-License-Identifier: BSD-3-Clause
 */

#include <assert.h>

#include <common/debug.h>
10
#include <common/desc_image_load.h>
11
12
13
14
15
16
17
18
19
20
21
22
#include <common/fdt_wrappers.h>
#include <drivers/io/io_storage.h>
#include <lib/object_pool.h>
#include <libfdt.h>
#include <plat/arm/common/arm_fconf_getter.h>
#include <plat/arm/common/arm_fconf_io_storage.h>
#include <plat/arm/common/fconf_arm_sp_getter.h>
#include <platform_def.h>
#include <tools_share/firmware_image_package.h>

#ifdef IMAGE_BL2

23
24
bl_mem_params_node_t sp_mem_params_descs[MAX_SP_IDS];

25
26
27
28
29
30
struct arm_sp_t arm_sp;

int fconf_populate_arm_sp(uintptr_t config)
{
	int sp_node, node, err;
	union uuid_helper_t uuid_helper;
31
	unsigned int index = 0;
32
	uint32_t val32;
33
34
35
36
37
38
39
	bool is_plat_owned = false;
	const unsigned int sip_start = SP_PKG1_ID;
	unsigned int sip_index = sip_start;
	const unsigned int sip_end = sip_start + MAX_SP_IDS / 2;
	const unsigned int plat_start = SP_PKG5_ID;
	unsigned int plat_index = plat_start;
	const unsigned int plat_end = plat_start + MAX_SP_IDS / 2;
40
	unsigned int j;
41
42
43
44
45
46
47
48
49
50
51
52
53
54

	/* As libfdt use void *, we can't avoid this cast */
	const void *dtb = (void *)config;

	/* Assert the node offset point to "arm,sp" compatible property */
	const char *compatible_str = "arm,sp";

	node = fdt_node_offset_by_compatible(dtb, -1, compatible_str);
	if (node < 0) {
		ERROR("FCONF: Can't find %s in dtb\n", compatible_str);
		return node;
	}

	fdt_for_each_subnode(sp_node, dtb, node) {
55
56
		if ((index == MAX_SP_IDS) || (sip_index == sip_end)
		    || (plat_index == plat_end)) {
Manish Pandey's avatar
Manish Pandey committed
57
58
59
60
			ERROR("FCONF: Reached max number of SPs\n");
			return -1;
		}

61
		/* Read UUID */
62
63
		err = fdt_read_uint32_array(dtb, sp_node, "uuid", 4,
					    uuid_helper.word);
64
65
66
67
		if (err < 0) {
			ERROR("FCONF: cannot read SP uuid\n");
			return -1;
		}
68
69
70
71
72
73
74
75
76
77

		/* Convert uuid from big endian to little endian */
		for (j = 0U; j < 4U; j++) {
			uuid_helper.word[j] =
				((uuid_helper.word[j] >> 24U) & 0xff) |
				((uuid_helper.word[j] << 8U) & 0xff0000) |
				((uuid_helper.word[j] >> 8U) & 0xff00) |
				((uuid_helper.word[j] << 24U) & 0xff000000);
		}

78
		arm_sp.uuids[index] = uuid_helper;
79
80
81
82
83
84
		VERBOSE("FCONF: %s UUID %x-%x-%x-%x load_addr=%lx\n",
			__func__,
			uuid_helper.word[0],
			uuid_helper.word[1],
			uuid_helper.word[2],
			uuid_helper.word[3],
85
86
			arm_sp.load_addr[index]);

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
		/* Read Load address */
		err = fdt_read_uint32(dtb, sp_node, "load-address", &val32);
		if (err < 0) {
			ERROR("FCONF: cannot read SP load address\n");
			return -1;
		}
		arm_sp.load_addr[index] = val32;

		/* Read owner field only for dualroot CoT */
#if defined(ARM_COT_dualroot)
		/* Owner is an optional field, no need to catch error */
		fdtw_read_string(dtb, sp_node, "owner",
				arm_sp.owner[index], ARM_SP_OWNER_NAME_LEN);
#endif
		/* If owner is empty mark it as SiP owned */
		if ((strncmp(arm_sp.owner[index], "SiP",
			     ARM_SP_OWNER_NAME_LEN) == 0) ||
		    (strncmp(arm_sp.owner[index], "",
			     ARM_SP_OWNER_NAME_LEN) == 0)) {
			is_plat_owned = false;
		} else if (strcmp(arm_sp.owner[index], "Plat") == 0) {
			is_plat_owned = true;
		} else {
			ERROR("FCONF: %s is not a valid SP owner\n",
			      arm_sp.owner[index]);
			return -1;
		}
		/*
		 * Add SP information in mem param descriptor and IO policies
		 * structure.
		 */
		if (is_plat_owned) {
			sp_mem_params_descs[index].image_id = plat_index;
			policies[plat_index].image_spec =
						(uintptr_t)&arm_sp.uuids[index];
			policies[plat_index].dev_handle = &fip_dev_handle;
			policies[plat_index].check = open_fip;
			plat_index++;
		} else {
			sp_mem_params_descs[index].image_id = sip_index;
			policies[sip_index].image_spec =
						(uintptr_t)&arm_sp.uuids[index];
			policies[sip_index].dev_handle = &fip_dev_handle;
			policies[sip_index].check = open_fip;
			sip_index++;
		}
133
134
135
136
137
138
139
140
141
		SET_PARAM_HEAD(&sp_mem_params_descs[index].image_info,
					PARAM_IMAGE_BINARY, VERSION_2, 0);
		sp_mem_params_descs[index].image_info.image_max_size =
							ARM_SP_MAX_SIZE;
		sp_mem_params_descs[index].next_handoff_image_id =
							INVALID_IMAGE_ID;
		sp_mem_params_descs[index].image_info.image_base =
							arm_sp.load_addr[index];
		index++;
142
143
144
	}

	if ((sp_node < 0) && (sp_node != -FDT_ERR_NOTFOUND)) {
Manish Pandey's avatar
Manish Pandey committed
145
		ERROR("%u: fdt_for_each_subnode(): %d\n", __LINE__, node);
146
147
148
		return sp_node;
	}

149
	arm_sp.number_of_sp = index;
150
151
152
	return 0;
}

153
FCONF_REGISTER_POPULATOR(TB_FW, arm_sp, fconf_populate_arm_sp);
154
155

#endif /* IMAGE_BL2 */