diff --git a/drivers/arm/css/scp/css_sds.c b/drivers/arm/css/scp/css_sds.c index e42ee10d7..d9965c671 100644 --- a/drivers/arm/css/scp/css_sds.c +++ b/drivers/arm/css/scp/css_sds.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2014-2017, ARM Limited and Contributors. All rights reserved. + * Copyright (c) 2014-2024, Arm Limited and Contributors. All rights reserved. * * SPDX-License-Identifier: BSD-3-Clause */ @@ -20,7 +20,7 @@ int css_scp_boot_image_xfer(void *image, unsigned int image_size) int ret; unsigned int image_offset, image_flags; - ret = sds_init(); + ret = sds_init(SDS_SCP_AP_REGION_ID); if (ret != SDS_OK) { ERROR("SCP SDS initialization failed\n"); panic(); @@ -28,13 +28,15 @@ int css_scp_boot_image_xfer(void *image, unsigned int image_size) VERBOSE("Writing SCP image metadata\n"); image_offset = (uintptr_t) image - ARM_TRUSTED_SRAM_BASE; - ret = sds_struct_write(SDS_SCP_IMG_STRUCT_ID, SDS_SCP_IMG_ADDR_OFFSET, + ret = sds_struct_write(SDS_SCP_AP_REGION_ID, + SDS_SCP_IMG_STRUCT_ID, SDS_SCP_IMG_ADDR_OFFSET, &image_offset, SDS_SCP_IMG_ADDR_SIZE, SDS_ACCESS_MODE_NON_CACHED); if (ret != SDS_OK) goto sds_fail; - ret = sds_struct_write(SDS_SCP_IMG_STRUCT_ID, SDS_SCP_IMG_SIZE_OFFSET, + ret = sds_struct_write(SDS_SCP_AP_REGION_ID, + SDS_SCP_IMG_STRUCT_ID, SDS_SCP_IMG_SIZE_OFFSET, &image_size, SDS_SCP_IMG_SIZE_SIZE, SDS_ACCESS_MODE_NON_CACHED); if (ret != SDS_OK) @@ -42,7 +44,8 @@ int css_scp_boot_image_xfer(void *image, unsigned int image_size) VERBOSE("Marking SCP image metadata as valid\n"); image_flags = SDS_SCP_IMG_VALID_FLAG_BIT; - ret = sds_struct_write(SDS_SCP_IMG_STRUCT_ID, SDS_SCP_IMG_FLAG_OFFSET, + ret = sds_struct_write(SDS_SCP_AP_REGION_ID, + SDS_SCP_IMG_STRUCT_ID, SDS_SCP_IMG_FLAG_OFFSET, &image_flags, SDS_SCP_IMG_FLAG_SIZE, SDS_ACCESS_MODE_NON_CACHED); if (ret != SDS_OK) @@ -68,7 +71,8 @@ int css_scp_boot_ready(void) /* Wait for the SCP RAM Firmware to complete its initialization process */ while (retry > 0) { - ret = sds_struct_read(SDS_FEATURE_AVAIL_STRUCT_ID, 0, + ret = sds_struct_read(SDS_SCP_AP_REGION_ID, + SDS_FEATURE_AVAIL_STRUCT_ID, 0, &scp_feature_availability_flags, SDS_FEATURE_AVAIL_SIZE, SDS_ACCESS_MODE_NON_CACHED); diff --git a/drivers/arm/css/sds/sds.c b/drivers/arm/css/sds/sds.c index 1fb196c70..a5e638939 100644 --- a/drivers/arm/css/sds/sds.c +++ b/drivers/arm/css/sds/sds.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2017, ARM Limited and Contributors. All rights reserved. + * Copyright (c) 2017-2024, Arm Limited and Contributors. All rights reserved. * * SPDX-License-Identifier: BSD-3-Clause */ @@ -15,40 +15,39 @@ #include "sds_private.h" -/* - * Variables used to track and maintain the state of the memory region reserved - * for usage by the SDS framework. - */ +/* Array of SDS memory region descriptions */ +static sds_region_desc_t *sds_regions; -/* Pointer to the base of the SDS memory region */ -static uintptr_t sds_mem_base; - -/* Size of the SDS memory region in bytes */ -static size_t sds_mem_size; +/* Total count of SDS memory regions */ +static unsigned int sds_region_cnt; /* * Perform some non-exhaustive tests to determine whether any of the fields * within a Structure Header contain obviously invalid data. * Returns SDS_OK on success, SDS_ERR_FAIL on error. */ -static int sds_struct_is_valid(uintptr_t header) +static int sds_struct_is_valid(unsigned int region_id, uintptr_t header) { size_t struct_size = GET_SDS_HEADER_STRUCT_SIZE(header); /* Zero is not a valid identifier */ - if (GET_SDS_HEADER_ID(header) == 0) + if (GET_SDS_HEADER_ID(header) == 0) { return SDS_ERR_FAIL; + } /* Check SDS Schema version */ - if (GET_SDS_HEADER_VERSION(header) == SDS_REGION_SCH_VERSION) + if (GET_SDS_HEADER_VERSION(header) == SDS_REGION_SCH_VERSION) { return SDS_ERR_FAIL; + } /* The SDS Structure sizes have to be multiple of 8 */ - if ((struct_size == 0) || ((struct_size % 8) != 0)) + if ((struct_size == 0) || ((struct_size % 8) != 0)) { return SDS_ERR_FAIL; + } - if (struct_size > sds_mem_size) + if (struct_size > sds_regions[region_id].size) { return SDS_ERR_FAIL; + } return SDS_OK; } @@ -57,10 +56,11 @@ static int sds_struct_is_valid(uintptr_t header) * Validate the SDS structure headers. * Returns SDS_OK on success, SDS_ERR_FAIL on error. */ -static int validate_sds_struct_headers(void) +static int validate_sds_struct_headers(unsigned int region_id) { unsigned int i, structure_count; uintptr_t header; + uintptr_t sds_mem_base = sds_regions[region_id].base; structure_count = GET_SDS_REGION_STRUCTURE_COUNT(sds_mem_base); @@ -71,7 +71,7 @@ static int validate_sds_struct_headers(void) /* Iterate over structure headers and validate each one */ for (i = 0; i < structure_count; i++) { - if (sds_struct_is_valid(header) != SDS_OK) { + if (sds_struct_is_valid(region_id, header) != SDS_OK) { WARN("SDS: Invalid structure header detected\n"); return SDS_ERR_FAIL; } @@ -84,10 +84,12 @@ static int validate_sds_struct_headers(void) * Get the structure header pointer corresponding to the structure ID. * Returns SDS_OK on success, SDS_ERR_STRUCT_NOT_FOUND on error. */ -static int get_struct_header(uint32_t structure_id, struct_header_t **header) +static int get_struct_header(unsigned int region_id, uint32_t structure_id, + struct_header_t **header) { unsigned int i, structure_count; uintptr_t current_header; + uintptr_t sds_mem_base = sds_regions[region_id].base; assert(header); @@ -116,12 +118,14 @@ static int get_struct_header(uint32_t structure_id, struct_header_t **header) * Returns SDS_OK if structure header exists else SDS_ERR_STRUCT_NOT_FOUND * if not found. */ -int sds_struct_exists(unsigned int structure_id) +int sds_struct_exists(unsigned int region_id, unsigned int structure_id) { struct_header_t *header = NULL; int ret; - ret = get_struct_header(structure_id, &header); + assert(region_id < sds_region_cnt); + + ret = get_struct_header(region_id, structure_id, &header); if (ret == SDS_OK) { assert(header); } @@ -136,18 +140,21 @@ int sds_struct_exists(unsigned int structure_id) * The `data` is the pointer to store the read data of size specified by `size`. * Returns SDS_OK on success or corresponding error codes on failure. */ -int sds_struct_read(uint32_t structure_id, unsigned int fld_off, - void *data, size_t size, sds_access_mode_t mode) +int sds_struct_read(unsigned int region_id, uint32_t structure_id, + unsigned int fld_off, void *data, size_t size, + sds_access_mode_t mode) { int status; uintptr_t field_base; struct_header_t *header = NULL; + assert(region_id < sds_region_cnt); + if (!data) return SDS_ERR_INVALID_PARAMS; /* Check if a structure with this ID exists */ - status = get_struct_header(structure_id, &header); + status = get_struct_header(region_id, structure_id, &header); if (status != SDS_OK) return status; @@ -182,18 +189,21 @@ int sds_struct_read(uint32_t structure_id, unsigned int fld_off, * The `data` is the pointer to data of size specified by `size`. * Returns SDS_OK on success or corresponding error codes on failure. */ -int sds_struct_write(uint32_t structure_id, unsigned int fld_off, - void *data, size_t size, sds_access_mode_t mode) +int sds_struct_write(unsigned int region_id, uint32_t structure_id, + unsigned int fld_off, void *data, size_t size, + sds_access_mode_t mode) { int status; uintptr_t field_base; struct_header_t *header = NULL; + assert(region_id < sds_region_cnt); + if (!data) return SDS_ERR_INVALID_PARAMS; /* Check if a structure with this ID exists */ - status = get_struct_header(structure_id, &header); + status = get_struct_header(region_id, structure_id, &header); if (status != SDS_OK) return status; @@ -226,12 +236,18 @@ int sds_struct_write(uint32_t structure_id, unsigned int fld_off, /* * Initialize the SDS driver. Also verifies the SDS version and sanity of - * the SDS structure headers. + * the SDS structure headers in the given SDS region. * Returns SDS_OK on success, SDS_ERR_FAIL on error. */ -int sds_init(void) +int sds_init(unsigned int region_id) { - sds_mem_base = (uintptr_t)PLAT_ARM_SDS_MEM_BASE; + if (sds_regions == NULL) { + sds_regions = plat_sds_get_regions(&sds_region_cnt); + } + + assert(region_id < sds_region_cnt); + + uintptr_t sds_mem_base = sds_regions[region_id].base; if (!IS_SDS_REGION_VALID(sds_mem_base)) { WARN("SDS: No valid SDS Memory Region found\n"); @@ -244,15 +260,16 @@ int sds_init(void) return SDS_ERR_FAIL; } - sds_mem_size = GET_SDS_REGION_SIZE(sds_mem_base); - if (sds_mem_size > PLAT_ARM_SDS_MEM_SIZE_MAX) { + sds_regions[region_id].size = GET_SDS_REGION_SIZE(sds_mem_base); + if (sds_regions[region_id].size > PLAT_ARM_SDS_MEM_SIZE_MAX) { WARN("SDS: SDS Memory Region exceeds size limit\n"); return SDS_ERR_FAIL; } - INFO("SDS: Detected SDS Memory Region (%zu bytes)\n", sds_mem_size); + INFO("SDS: Detected SDS Memory Region (%zu bytes)\n", + sds_regions[region_id].size); - if (validate_sds_struct_headers() != SDS_OK) + if (validate_sds_struct_headers(region_id) != SDS_OK) return SDS_ERR_FAIL; return SDS_OK; diff --git a/include/drivers/arm/css/sds.h b/include/drivers/arm/css/sds.h index db4cbaaf5..ab9577512 100644 --- a/include/drivers/arm/css/sds.h +++ b/include/drivers/arm/css/sds.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2017, ARM Limited and Contributors. All rights reserved. + * Copyright (c) 2017-2024, Arm Limited and Contributors. All rights reserved. * * SPDX-License-Identifier: BSD-3-Clause */ @@ -79,12 +79,33 @@ typedef enum { SDS_ACCESS_MODE_CACHED, } sds_access_mode_t; -int sds_init(void); -int sds_struct_exists(unsigned int structure_id); -int sds_struct_read(uint32_t structure_id, unsigned int fld_off, void *data, - size_t size, sds_access_mode_t mode); -int sds_struct_write(uint32_t structure_id, unsigned int fld_off, void *data, - size_t size, sds_access_mode_t mode); +/* + * The following structure describes a SDS memory region. Its items are used + * to track and maintain the state of the memory region reserved for usage + * by the SDS framework. + * + * The base address of the SDS memory region is platform specific. The + * SDS description structure must already contain the address when it is + * returned by the plat_sds_get_regions() platform API during SDS region + * initialization. + * The size of the SDS memory region is dynamically discovered during the + * initialization of the region and written into the 'size' item of the + * SDS description structure. + */ +typedef struct { + uintptr_t base; /* Pointer to the base of the SDS memory region */ + size_t size; /* Size of the SDS memory region in bytes */ +} sds_region_desc_t; + +/* API to get the platform specific SDS region description(s) */ +sds_region_desc_t *plat_sds_get_regions(unsigned int *region_count); + +int sds_init(unsigned int region_id); +int sds_struct_exists(unsigned int region_id, unsigned int structure_id); +int sds_struct_read(unsigned int region_id, uint32_t structure_id, + unsigned int fld_off, void *data, size_t size, sds_access_mode_t mode); +int sds_struct_write(unsigned int region_id, uint32_t structure_id, + unsigned int fld_off, void *data, size_t size, sds_access_mode_t mode); #endif /*__ASSEMBLER__ */ #endif /* SDS_H */