fconf_dyn_cfg_getter.c 3.25 KB
Newer Older
1
2
3
4
5
6
7
8
9
10
11
12
13
14
/*
 * Copyright (c) 2019-2020, Arm Limited. All rights reserved.
 *
 * SPDX-License-Identifier: BSD-3-Clause
 */

#include <assert.h>

#include <common/debug.h>
#include <common/fdt_wrappers.h>
#include <lib/fconf/fconf_dyn_cfg_getter.h>
#include <lib/object_pool.h>
#include <libfdt.h>

15
16
/* We currently use FW, TB_FW, SOC_FW, TOS_FW, NS_fw and HW configs  */
#define MAX_DTB_INFO	U(6)
17

18
19
20
21
22
23
24
25
26
27
28
29
30
#ifdef IMAGE_BL1
static struct dyn_cfg_dtb_info_t dtb_infos[MAX_DTB_INFO] = {
	[0] = {
		.config_addr = ARM_FW_CONFIG_BASE,
		.config_max_size = (uint32_t)
				(ARM_FW_CONFIG_LIMIT - ARM_FW_CONFIG_BASE),
		.config_id = FW_CONFIG_ID
	},
};
/* Create an object pool starting at the second element */
static OBJECT_POOL(dtb_info_pool, &dtb_infos[1],
		sizeof(struct dyn_cfg_dtb_info_t), MAX_DTB_INFO-1);
#else
31
32
static struct dyn_cfg_dtb_info_t dtb_infos[MAX_DTB_INFO];
static OBJECT_POOL_ARRAY(dtb_info_pool, dtb_infos);
33
#endif
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64

struct dyn_cfg_dtb_info_t *dyn_cfg_dtb_info_getter(unsigned int config_id)
{
	unsigned int index;
	struct dyn_cfg_dtb_info_t *info;

	/* Positions index to the proper config-id */
	for (index = 0; index < MAX_DTB_INFO; index++) {
		if (dtb_infos[index].config_id == config_id) {
			info = &dtb_infos[index];
			break;
		}
	}

	if (index == MAX_DTB_INFO) {
		WARN("FCONF: Invalid config id %u\n", config_id);
		info = NULL;
	}

	return info;
}

int fconf_populate_dtb_registry(uintptr_t config)
{
	int rc;
	int node, child;
	struct dyn_cfg_dtb_info_t *dtb_info;

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

65
66
	/* Find the node offset point to "fconf,dyn_cfg-dtb_registry" compatible property */
	const char *compatible_str = "fconf,dyn_cfg-dtb_registry";
67
68
69
70
71
72
	node = fdt_node_offset_by_compatible(dtb, -1, compatible_str);
	if (node < 0) {
		ERROR("FCONF: Can't find %s compatible in dtb\n", compatible_str);
		return node;
	}

73
74
75
76
77
78
79
80
81
#ifndef IMAGE_BL1
	/* Save config dtb information */
	dtb_info = pool_alloc(&dtb_info_pool);

	dtb_info->config_addr = config;
	dtb_info->config_max_size = fdt_totalsize(dtb);
	dtb_info->config_id = FW_CONFIG_ID;
#endif

82
	fdt_for_each_subnode(child, dtb, node) {
83
84
85
		uint32_t val32;
		uint64_t val64;

86
87
88
		dtb_info = pool_alloc(&dtb_info_pool);

		/* Read configuration dtb information */
89
		rc = fdt_read_uint64(dtb, child, "load-address", &val64);
90
91
92
93
		if (rc < 0) {
			ERROR("FCONF: Incomplete configuration property in dtb-registry.\n");
			return rc;
		}
94
		dtb_info->config_addr = (uintptr_t)val64;
95

96
		rc = fdt_read_uint32(dtb, child, "max-size", &val32);
97
98
99
100
		if (rc < 0) {
			ERROR("FCONF: Incomplete configuration property in dtb-registry.\n");
			return rc;
		}
101
		dtb_info->config_max_size = val32;
102

103
		rc = fdt_read_uint32(dtb, child, "id", &val32);
104
105
106
107
		if (rc < 0) {
			ERROR("FCONF: Incomplete configuration property in dtb-registry.\n");
			return rc;
		}
108
		dtb_info->config_id = val32;
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123

		VERBOSE("FCONF: dyn_cfg.dtb_registry cell found with:\n");
		VERBOSE("\tload-address = %lx\n", dtb_info->config_addr);
		VERBOSE("\tmax-size = 0x%zx\n", dtb_info->config_max_size);
		VERBOSE("\tconfig-id = %u\n", dtb_info->config_id);
	}

	if ((child < 0) && (child != -FDT_ERR_NOTFOUND)) {
		ERROR("%d: fdt_for_each_subnode(): %d\n", __LINE__, node);
		return child;
	}

	return 0;
}

124
FCONF_REGISTER_POPULATOR(FW_CONFIG, dyn_cfg, fconf_populate_dtb_registry);