Antonio Nino Diaz 09d40e0e08 Sanitise includes across codebase
Enforce full include path for includes. Deprecate old paths.

The following folders inside include/lib have been left unchanged:

- include/lib/cpus/${ARCH}
- include/lib/el3_runtime/${ARCH}

The reason for this change is that having a global namespace for
includes isn't a good idea. It defeats one of the advantages of having
folders and it introduces problems that are sometimes subtle (because
you may not know the header you are actually including if there are two
of them).

For example, this patch had to be created because two headers were
called the same way: e0ea0928d5b7 ("Fix gpio includes of mt8173 platform
to avoid collision."). More recently, this patch has had similar
problems: 46f9b2c3a282 ("drivers: add tzc380 support").

This problem was introduced in commit 4ecca33988b9 ("Move include and
source files to logical locations"). At that time, there weren't too
many headers so it wasn't a real issue. However, time has shown that
this creates problems.

Platforms that want to preserve the way they include headers may add the
removed paths to PLAT_INCLUDES, but this is discouraged.

Change-Id: I39dc53ed98f9e297a5966e723d1936d6ccf2fc8f
Signed-off-by: Antonio Nino Diaz <antonio.ninodiaz@arm.com>
2019-01-04 10:43:17 +00:00

260 lines
6.7 KiB
C

/*
* Copyright (c) 2017, ARM Limited and Contributors. All rights reserved.
*
* SPDX-License-Identifier: BSD-3-Clause
*/
#include <assert.h>
#include <stdint.h>
#include <string.h>
#include <arch_helpers.h>
#include <common/debug.h>
#include <css_def.h>
#include "sds.h"
#include "sds_private.h"
/*
* Variables used to track and maintain the state of the memory region reserved
* for usage by the SDS framework.
*/
/* 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;
/*
* 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)
{
size_t struct_size = GET_SDS_HEADER_STRUCT_SIZE(header);
/* Zero is not a valid identifier */
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)
return SDS_ERR_FAIL;
/* The SDS Structure sizes have to be multiple of 8 */
if ((struct_size == 0) || ((struct_size % 8) != 0))
return SDS_ERR_FAIL;
if (struct_size > sds_mem_size)
return SDS_ERR_FAIL;
return SDS_OK;
}
/*
* Validate the SDS structure headers.
* Returns SDS_OK on success, SDS_ERR_FAIL on error.
*/
static int validate_sds_struct_headers(void)
{
unsigned int i, structure_count;
uintptr_t header;
structure_count = GET_SDS_REGION_STRUCTURE_COUNT(sds_mem_base);
if (structure_count == 0)
return SDS_ERR_FAIL;
header = sds_mem_base + SDS_REGION_DESC_SIZE;
/* Iterate over structure headers and validate each one */
for (i = 0; i < structure_count; i++) {
if (sds_struct_is_valid(header) != SDS_OK) {
WARN("SDS: Invalid structure header detected\n");
return SDS_ERR_FAIL;
}
header += GET_SDS_HEADER_STRUCT_SIZE(header) + SDS_HEADER_SIZE;
}
return SDS_OK;
}
/*
* 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)
{
unsigned int i, structure_count;
uintptr_t current_header;
assert(header);
structure_count = GET_SDS_REGION_STRUCTURE_COUNT(sds_mem_base);
if (structure_count == 0)
return SDS_ERR_STRUCT_NOT_FOUND;
current_header = ((uintptr_t)sds_mem_base) + SDS_REGION_DESC_SIZE;
/* Iterate over structure headers to find one with a matching ID */
for (i = 0; i < structure_count; i++) {
if (GET_SDS_HEADER_ID(current_header) == structure_id) {
*header = (struct_header_t *)current_header;
return SDS_OK;
}
current_header += GET_SDS_HEADER_STRUCT_SIZE(current_header) +
SDS_HEADER_SIZE;
}
*header = NULL;
return SDS_ERR_STRUCT_NOT_FOUND;
}
/*
* Check if a structure header corresponding to the structure ID exists.
* Returns SDS_OK if structure header exists else SDS_ERR_STRUCT_NOT_FOUND
* if not found.
*/
int sds_struct_exists(unsigned int structure_id)
{
struct_header_t *header = NULL;
int ret;
ret = get_struct_header(structure_id, &header);
if (ret == SDS_OK) {
assert(header);
}
return ret;
}
/*
* Read from field in the structure corresponding to `structure_id`.
* `fld_off` is the offset to the field in the structure and `mode`
* indicates whether cache maintenance need to performed prior to the read.
* 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 status;
uintptr_t field_base;
struct_header_t *header = NULL;
if (!data)
return SDS_ERR_INVALID_PARAMS;
/* Check if a structure with this ID exists */
status = get_struct_header(structure_id, &header);
if (status != SDS_OK)
return status;
assert(header);
if (mode == SDS_ACCESS_MODE_CACHED)
inv_dcache_range((uintptr_t)header, SDS_HEADER_SIZE + size);
if (!IS_SDS_HEADER_VALID(header)) {
WARN("SDS: Reading from un-finalized structure 0x%x\n",
structure_id);
return SDS_ERR_STRUCT_NOT_FINALIZED;
}
if ((fld_off + size) > GET_SDS_HEADER_STRUCT_SIZE(header))
return SDS_ERR_FAIL;
field_base = (uintptr_t)header + SDS_HEADER_SIZE + fld_off;
if (check_uptr_overflow(field_base, size - 1))
return SDS_ERR_FAIL;
/* Copy the required field in the struct */
memcpy(data, (void *)field_base, size);
return SDS_OK;
}
/*
* Write to the field in the structure corresponding to `structure_id`.
* `fld_off` is the offset to the field in the structure and `mode`
* indicates whether cache maintenance need to performed for the write.
* 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 status;
uintptr_t field_base;
struct_header_t *header = NULL;
if (!data)
return SDS_ERR_INVALID_PARAMS;
/* Check if a structure with this ID exists */
status = get_struct_header(structure_id, &header);
if (status != SDS_OK)
return status;
assert(header);
if (mode == SDS_ACCESS_MODE_CACHED)
inv_dcache_range((uintptr_t)header, SDS_HEADER_SIZE + size);
if (!IS_SDS_HEADER_VALID(header)) {
WARN("SDS: Writing to un-finalized structure 0x%x\n",
structure_id);
return SDS_ERR_STRUCT_NOT_FINALIZED;
}
if ((fld_off + size) > GET_SDS_HEADER_STRUCT_SIZE(header))
return SDS_ERR_FAIL;
field_base = (uintptr_t)header + SDS_HEADER_SIZE + fld_off;
if (check_uptr_overflow(field_base, size - 1))
return SDS_ERR_FAIL;
/* Copy the required field in the struct */
memcpy((void *)field_base, data, size);
if (mode == SDS_ACCESS_MODE_CACHED)
flush_dcache_range((uintptr_t)field_base, size);
return SDS_OK;
}
/*
* Initialize the SDS driver. Also verifies the SDS version and sanity of
* the SDS structure headers.
* Returns SDS_OK on success, SDS_ERR_FAIL on error.
*/
int sds_init(void)
{
sds_mem_base = (uintptr_t)PLAT_ARM_SDS_MEM_BASE;
if (!IS_SDS_REGION_VALID(sds_mem_base)) {
WARN("SDS: No valid SDS Memory Region found\n");
return SDS_ERR_FAIL;
}
if (GET_SDS_REGION_SCHEMA_VERSION(sds_mem_base)
!= SDS_REGION_SCH_VERSION) {
WARN("SDS: Unsupported SDS schema version\n");
return SDS_ERR_FAIL;
}
sds_mem_size = GET_SDS_REGION_SIZE(sds_mem_base);
if (sds_mem_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);
if (validate_sds_struct_headers() != SDS_OK)
return SDS_ERR_FAIL;
return SDS_OK;
}