|
|
|
/*
|
|
|
|
* 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>
|
|
|
|
|
|
|
|
/* We currently use FW, TB_FW, SOC_FW, TOS_FW, NS_fw and HW configs */
|
|
|
|
#define MAX_DTB_INFO U(6)
|
|
|
|
|
|
|
|
static struct dyn_cfg_dtb_info_t dtb_infos[MAX_DTB_INFO];
|
|
|
|
static OBJECT_POOL_ARRAY(dtb_info_pool, dtb_infos);
|
|
|
|
|
|
|
|
/*
|
|
|
|
* This function is used to alloc memory for fw config information from
|
|
|
|
* global pool and set fw configuration information.
|
|
|
|
* Specifically used by BL1 to set fw_config information in global array
|
|
|
|
*/
|
|
|
|
void set_fw_config_info(uintptr_t config_addr, uint32_t config_max_size)
|
|
|
|
{
|
|
|
|
struct dyn_cfg_dtb_info_t *dtb_info;
|
|
|
|
|
|
|
|
dtb_info = pool_alloc(&dtb_info_pool);
|
|
|
|
dtb_info->config_addr = config_addr;
|
|
|
|
dtb_info->config_max_size = config_max_size;
|
|
|
|
dtb_info->config_id = FW_CONFIG_ID;
|
|
|
|
}
|
|
|
|
|
|
|
|
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;
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Compile time assert if FW_CONFIG_ID is 0 which is more
|
|
|
|
* unlikely as 0 is a valid image id for FIP as per the current
|
|
|
|
* code but still to avoid code breakage in case of unlikely
|
|
|
|
* event when image ids gets changed.
|
|
|
|
*/
|
|
|
|
CASSERT(FW_CONFIG_ID != 0, assert_invalid_fw_config_id);
|
|
|
|
|
|
|
|
/*
|
|
|
|
* In case of BL1, fw_config dtb information is already
|
|
|
|
* populated in global dtb_infos array by 'set_fw_config_info'
|
|
|
|
* function, Below check is present to avoid re-population of
|
|
|
|
* fw_config information.
|
|
|
|
*
|
|
|
|
* Other BLs, satisfy below check and populate fw_config information
|
|
|
|
* in global dtb_infos array.
|
|
|
|
*/
|
|
|
|
if (dtb_infos[0].config_id == 0) {
|
|
|
|
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;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Find the node offset point to "fconf,dyn_cfg-dtb_registry" compatible property */
|
|
|
|
const char *compatible_str = "fconf,dyn_cfg-dtb_registry";
|
|
|
|
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;
|
|
|
|
}
|
|
|
|
|
|
|
|
fdt_for_each_subnode(child, dtb, node) {
|
fdt/wrappers: Replace fdtw_read_cells() implementation
Our fdtw_read_cells() implementation goes to great lengths to
sanity-check every parameter and result, but leaves a big hole open:
The size of the storage the value pointer points at needs to match the
number of cells given. This can't be easily checked at compile time,
since we lose the size information by using a void pointer.
Regardless the current usage of this function is somewhat wrong anyways,
since we use it on single-element, fixed-length properties only, for
which the DT binding specifies the size.
Typically we use those functions dealing with a number of cells in DT
context to deal with *dynamically* sized properties, which depend on
other properties (#size-cells, #clock-cells, ...), to specify the number
of cells needed.
Another problem with the current implementation is the use of
ambiguously sized types (uintptr_t, size_t) together with a certain
expectation about their size. In general there is no relation between
the length of a DT property and the bitness of the code that parses the
DTB: AArch64 code could encounter 32-bit addresses (where the physical
address space is limited to 4GB [1]), while AArch32 code could read
64-bit sized properties (/memory nodes on LPAE systems, [2]).
To make this more clear, fix the potential issues and also align more
with other DT users (Linux and U-Boot), introduce functions to explicitly
read uint32 and uint64 properties. As the other DT consumers, we do this
based on the generic "read array" function.
Convert all users to use either of those two new functions, and make
sure we never use a pointer to anything other than uint32_t or uint64_t
variables directly.
This reveals (and fixes) a bug in plat_spmd_manifest.c, where we write
4 bytes into a uint16_t variable (passed via a void pointer).
Also we change the implementation of the function to better align with
other libfdt users, by using the right types (fdt32_t) and common
variable names (*prop, prop_names).
[1] https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/tree/arch/arm64/boot/dts/allwinner/sun50i-a64.dtsi#n874
[2] https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/tree/arch/arm/boot/dts/ecx-2000.dts
Change-Id: I718de960515117ac7a3331a1b177d2ec224a3890
Signed-off-by: Andre Przywara <andre.przywara@arm.com>
5 years ago
|
|
|
uint32_t val32;
|
|
|
|
uint64_t val64;
|
|
|
|
|
|
|
|
dtb_info = pool_alloc(&dtb_info_pool);
|
|
|
|
|
|
|
|
/* Read configuration dtb information */
|
fdt/wrappers: Replace fdtw_read_cells() implementation
Our fdtw_read_cells() implementation goes to great lengths to
sanity-check every parameter and result, but leaves a big hole open:
The size of the storage the value pointer points at needs to match the
number of cells given. This can't be easily checked at compile time,
since we lose the size information by using a void pointer.
Regardless the current usage of this function is somewhat wrong anyways,
since we use it on single-element, fixed-length properties only, for
which the DT binding specifies the size.
Typically we use those functions dealing with a number of cells in DT
context to deal with *dynamically* sized properties, which depend on
other properties (#size-cells, #clock-cells, ...), to specify the number
of cells needed.
Another problem with the current implementation is the use of
ambiguously sized types (uintptr_t, size_t) together with a certain
expectation about their size. In general there is no relation between
the length of a DT property and the bitness of the code that parses the
DTB: AArch64 code could encounter 32-bit addresses (where the physical
address space is limited to 4GB [1]), while AArch32 code could read
64-bit sized properties (/memory nodes on LPAE systems, [2]).
To make this more clear, fix the potential issues and also align more
with other DT users (Linux and U-Boot), introduce functions to explicitly
read uint32 and uint64 properties. As the other DT consumers, we do this
based on the generic "read array" function.
Convert all users to use either of those two new functions, and make
sure we never use a pointer to anything other than uint32_t or uint64_t
variables directly.
This reveals (and fixes) a bug in plat_spmd_manifest.c, where we write
4 bytes into a uint16_t variable (passed via a void pointer).
Also we change the implementation of the function to better align with
other libfdt users, by using the right types (fdt32_t) and common
variable names (*prop, prop_names).
[1] https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/tree/arch/arm64/boot/dts/allwinner/sun50i-a64.dtsi#n874
[2] https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/tree/arch/arm/boot/dts/ecx-2000.dts
Change-Id: I718de960515117ac7a3331a1b177d2ec224a3890
Signed-off-by: Andre Przywara <andre.przywara@arm.com>
5 years ago
|
|
|
rc = fdt_read_uint64(dtb, child, "load-address", &val64);
|
|
|
|
if (rc < 0) {
|
|
|
|
ERROR("FCONF: Incomplete configuration property in dtb-registry.\n");
|
|
|
|
return rc;
|
|
|
|
}
|
fdt/wrappers: Replace fdtw_read_cells() implementation
Our fdtw_read_cells() implementation goes to great lengths to
sanity-check every parameter and result, but leaves a big hole open:
The size of the storage the value pointer points at needs to match the
number of cells given. This can't be easily checked at compile time,
since we lose the size information by using a void pointer.
Regardless the current usage of this function is somewhat wrong anyways,
since we use it on single-element, fixed-length properties only, for
which the DT binding specifies the size.
Typically we use those functions dealing with a number of cells in DT
context to deal with *dynamically* sized properties, which depend on
other properties (#size-cells, #clock-cells, ...), to specify the number
of cells needed.
Another problem with the current implementation is the use of
ambiguously sized types (uintptr_t, size_t) together with a certain
expectation about their size. In general there is no relation between
the length of a DT property and the bitness of the code that parses the
DTB: AArch64 code could encounter 32-bit addresses (where the physical
address space is limited to 4GB [1]), while AArch32 code could read
64-bit sized properties (/memory nodes on LPAE systems, [2]).
To make this more clear, fix the potential issues and also align more
with other DT users (Linux and U-Boot), introduce functions to explicitly
read uint32 and uint64 properties. As the other DT consumers, we do this
based on the generic "read array" function.
Convert all users to use either of those two new functions, and make
sure we never use a pointer to anything other than uint32_t or uint64_t
variables directly.
This reveals (and fixes) a bug in plat_spmd_manifest.c, where we write
4 bytes into a uint16_t variable (passed via a void pointer).
Also we change the implementation of the function to better align with
other libfdt users, by using the right types (fdt32_t) and common
variable names (*prop, prop_names).
[1] https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/tree/arch/arm64/boot/dts/allwinner/sun50i-a64.dtsi#n874
[2] https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/tree/arch/arm/boot/dts/ecx-2000.dts
Change-Id: I718de960515117ac7a3331a1b177d2ec224a3890
Signed-off-by: Andre Przywara <andre.przywara@arm.com>
5 years ago
|
|
|
dtb_info->config_addr = (uintptr_t)val64;
|
|
|
|
|
fdt/wrappers: Replace fdtw_read_cells() implementation
Our fdtw_read_cells() implementation goes to great lengths to
sanity-check every parameter and result, but leaves a big hole open:
The size of the storage the value pointer points at needs to match the
number of cells given. This can't be easily checked at compile time,
since we lose the size information by using a void pointer.
Regardless the current usage of this function is somewhat wrong anyways,
since we use it on single-element, fixed-length properties only, for
which the DT binding specifies the size.
Typically we use those functions dealing with a number of cells in DT
context to deal with *dynamically* sized properties, which depend on
other properties (#size-cells, #clock-cells, ...), to specify the number
of cells needed.
Another problem with the current implementation is the use of
ambiguously sized types (uintptr_t, size_t) together with a certain
expectation about their size. In general there is no relation between
the length of a DT property and the bitness of the code that parses the
DTB: AArch64 code could encounter 32-bit addresses (where the physical
address space is limited to 4GB [1]), while AArch32 code could read
64-bit sized properties (/memory nodes on LPAE systems, [2]).
To make this more clear, fix the potential issues and also align more
with other DT users (Linux and U-Boot), introduce functions to explicitly
read uint32 and uint64 properties. As the other DT consumers, we do this
based on the generic "read array" function.
Convert all users to use either of those two new functions, and make
sure we never use a pointer to anything other than uint32_t or uint64_t
variables directly.
This reveals (and fixes) a bug in plat_spmd_manifest.c, where we write
4 bytes into a uint16_t variable (passed via a void pointer).
Also we change the implementation of the function to better align with
other libfdt users, by using the right types (fdt32_t) and common
variable names (*prop, prop_names).
[1] https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/tree/arch/arm64/boot/dts/allwinner/sun50i-a64.dtsi#n874
[2] https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/tree/arch/arm/boot/dts/ecx-2000.dts
Change-Id: I718de960515117ac7a3331a1b177d2ec224a3890
Signed-off-by: Andre Przywara <andre.przywara@arm.com>
5 years ago
|
|
|
rc = fdt_read_uint32(dtb, child, "max-size", &val32);
|
|
|
|
if (rc < 0) {
|
|
|
|
ERROR("FCONF: Incomplete configuration property in dtb-registry.\n");
|
|
|
|
return rc;
|
|
|
|
}
|
fdt/wrappers: Replace fdtw_read_cells() implementation
Our fdtw_read_cells() implementation goes to great lengths to
sanity-check every parameter and result, but leaves a big hole open:
The size of the storage the value pointer points at needs to match the
number of cells given. This can't be easily checked at compile time,
since we lose the size information by using a void pointer.
Regardless the current usage of this function is somewhat wrong anyways,
since we use it on single-element, fixed-length properties only, for
which the DT binding specifies the size.
Typically we use those functions dealing with a number of cells in DT
context to deal with *dynamically* sized properties, which depend on
other properties (#size-cells, #clock-cells, ...), to specify the number
of cells needed.
Another problem with the current implementation is the use of
ambiguously sized types (uintptr_t, size_t) together with a certain
expectation about their size. In general there is no relation between
the length of a DT property and the bitness of the code that parses the
DTB: AArch64 code could encounter 32-bit addresses (where the physical
address space is limited to 4GB [1]), while AArch32 code could read
64-bit sized properties (/memory nodes on LPAE systems, [2]).
To make this more clear, fix the potential issues and also align more
with other DT users (Linux and U-Boot), introduce functions to explicitly
read uint32 and uint64 properties. As the other DT consumers, we do this
based on the generic "read array" function.
Convert all users to use either of those two new functions, and make
sure we never use a pointer to anything other than uint32_t or uint64_t
variables directly.
This reveals (and fixes) a bug in plat_spmd_manifest.c, where we write
4 bytes into a uint16_t variable (passed via a void pointer).
Also we change the implementation of the function to better align with
other libfdt users, by using the right types (fdt32_t) and common
variable names (*prop, prop_names).
[1] https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/tree/arch/arm64/boot/dts/allwinner/sun50i-a64.dtsi#n874
[2] https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/tree/arch/arm/boot/dts/ecx-2000.dts
Change-Id: I718de960515117ac7a3331a1b177d2ec224a3890
Signed-off-by: Andre Przywara <andre.przywara@arm.com>
5 years ago
|
|
|
dtb_info->config_max_size = val32;
|
|
|
|
|
fdt/wrappers: Replace fdtw_read_cells() implementation
Our fdtw_read_cells() implementation goes to great lengths to
sanity-check every parameter and result, but leaves a big hole open:
The size of the storage the value pointer points at needs to match the
number of cells given. This can't be easily checked at compile time,
since we lose the size information by using a void pointer.
Regardless the current usage of this function is somewhat wrong anyways,
since we use it on single-element, fixed-length properties only, for
which the DT binding specifies the size.
Typically we use those functions dealing with a number of cells in DT
context to deal with *dynamically* sized properties, which depend on
other properties (#size-cells, #clock-cells, ...), to specify the number
of cells needed.
Another problem with the current implementation is the use of
ambiguously sized types (uintptr_t, size_t) together with a certain
expectation about their size. In general there is no relation between
the length of a DT property and the bitness of the code that parses the
DTB: AArch64 code could encounter 32-bit addresses (where the physical
address space is limited to 4GB [1]), while AArch32 code could read
64-bit sized properties (/memory nodes on LPAE systems, [2]).
To make this more clear, fix the potential issues and also align more
with other DT users (Linux and U-Boot), introduce functions to explicitly
read uint32 and uint64 properties. As the other DT consumers, we do this
based on the generic "read array" function.
Convert all users to use either of those two new functions, and make
sure we never use a pointer to anything other than uint32_t or uint64_t
variables directly.
This reveals (and fixes) a bug in plat_spmd_manifest.c, where we write
4 bytes into a uint16_t variable (passed via a void pointer).
Also we change the implementation of the function to better align with
other libfdt users, by using the right types (fdt32_t) and common
variable names (*prop, prop_names).
[1] https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/tree/arch/arm64/boot/dts/allwinner/sun50i-a64.dtsi#n874
[2] https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/tree/arch/arm/boot/dts/ecx-2000.dts
Change-Id: I718de960515117ac7a3331a1b177d2ec224a3890
Signed-off-by: Andre Przywara <andre.przywara@arm.com>
5 years ago
|
|
|
rc = fdt_read_uint32(dtb, child, "id", &val32);
|
|
|
|
if (rc < 0) {
|
|
|
|
ERROR("FCONF: Incomplete configuration property in dtb-registry.\n");
|
|
|
|
return rc;
|
|
|
|
}
|
fdt/wrappers: Replace fdtw_read_cells() implementation
Our fdtw_read_cells() implementation goes to great lengths to
sanity-check every parameter and result, but leaves a big hole open:
The size of the storage the value pointer points at needs to match the
number of cells given. This can't be easily checked at compile time,
since we lose the size information by using a void pointer.
Regardless the current usage of this function is somewhat wrong anyways,
since we use it on single-element, fixed-length properties only, for
which the DT binding specifies the size.
Typically we use those functions dealing with a number of cells in DT
context to deal with *dynamically* sized properties, which depend on
other properties (#size-cells, #clock-cells, ...), to specify the number
of cells needed.
Another problem with the current implementation is the use of
ambiguously sized types (uintptr_t, size_t) together with a certain
expectation about their size. In general there is no relation between
the length of a DT property and the bitness of the code that parses the
DTB: AArch64 code could encounter 32-bit addresses (where the physical
address space is limited to 4GB [1]), while AArch32 code could read
64-bit sized properties (/memory nodes on LPAE systems, [2]).
To make this more clear, fix the potential issues and also align more
with other DT users (Linux and U-Boot), introduce functions to explicitly
read uint32 and uint64 properties. As the other DT consumers, we do this
based on the generic "read array" function.
Convert all users to use either of those two new functions, and make
sure we never use a pointer to anything other than uint32_t or uint64_t
variables directly.
This reveals (and fixes) a bug in plat_spmd_manifest.c, where we write
4 bytes into a uint16_t variable (passed via a void pointer).
Also we change the implementation of the function to better align with
other libfdt users, by using the right types (fdt32_t) and common
variable names (*prop, prop_names).
[1] https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/tree/arch/arm64/boot/dts/allwinner/sun50i-a64.dtsi#n874
[2] https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/tree/arch/arm/boot/dts/ecx-2000.dts
Change-Id: I718de960515117ac7a3331a1b177d2ec224a3890
Signed-off-by: Andre Przywara <andre.przywara@arm.com>
5 years ago
|
|
|
dtb_info->config_id = val32;
|
|
|
|
|
|
|
|
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;
|
|
|
|
}
|
|
|
|
|
|
|
|
FCONF_REGISTER_POPULATOR(FW_CONFIG, dyn_cfg, fconf_populate_dtb_registry);
|