Merge pull request #33 from hliebel/hl/secure-memory

Hl/secure memory
This commit is contained in:
danh-arm 2014-04-24 19:38:28 +01:00
commit 429421de82
24 changed files with 714 additions and 35 deletions

View File

@ -207,15 +207,17 @@ bits.
#### Platform initialization
BL2 does not perform any platform initialization that affects subsequent
stages of the ARM Trusted Firmware or normal world software. It copies the
information regarding the trusted SRAM populated by BL1 using a
BL2 copies the information regarding the trusted SRAM populated by BL1 using a
platform-specific mechanism. It calculates the limits of DRAM (main memory)
to determine whether there is enough space to load the BL3-3 image. A platform
defined base address is used to specify the load address for the BL3-1 image.
It also defines the extents of memory available for use by the BL3-2 image.
BL2 also initializes UART0 (PL011 console), which enables access to the
`printf` family of functions in BL2
`printf` family of functions in BL2. Platform security is initialized to allow
access to access controlled components. On the Base FVP a TrustZone controller
(TZC-400) is configured to give full access to the platform DRAM. The storage
abstraction layer is initialized which is used to load further bootloader
images.
#### BL3-1 (EL3 Runtime Firmware) image load

View File

@ -630,6 +630,10 @@ The non-secure memory extents used for loading BL3-3 are also initialized in
this function. This information is accessible in the `bl33_meminfo` field in
the `bl31_args` structure pointed to by `bl2_to_bl31_args`.
Platform security components are configured if required. For the Base FVP the
TZC-400 TrustZone controller is configured to grant secure and non-secure access
to DRAM.
This function is also responsible for initializing the storage abstraction layer
which is used to load further bootloader images.

View File

@ -532,9 +532,15 @@ NOTE: The `-C bp.flashloader0.fname` parameter is used to load a Firmware Image
Package at the start of NOR FLASH0 (see the "Building the Trusted Firmware"
section above).
NOTE: Setting the `-C bp.secure_memory` parameter to `1` is only supported on
FVP versions 5.4 and newer. Setting this parameter to `0` is also supported.
The `-C bp.tzc_400.diagnostics=1` parameter is optional. It instructs the FVP to
provide some helpful information if a secure memory violation occurs.
<path-to>/FVP_Base_AEMv8A-AEMv8A \
-C pctl.startup=0.0.0.0 \
-C bp.secure_memory=0 \
-C bp.secure_memory=1 \
-C bp.tzc_400.diagnostics=1 \
-C cluster0.NUM_CORES=4 \
-C cluster1.NUM_CORES=4 \
-C cache_state_modelled=1 \
@ -560,9 +566,15 @@ NOTE: The `-C bp.flashloader0.fname` parameter is used to load a Firmware Image
Package at the start of NOR FLASH0 (see the "Building the Trusted Firmware"
section above).
NOTE: Setting the `-C bp.secure_memory` parameter to `1` is only supported on
FVP versions 5.4 and newer. Setting this parameter to `0` is also supported.
The `-C bp.tzc_400.diagnostics=1` parameter is optional. It instructs the FVP to
provide some helpful information if a secure memory violation occurs.
<path-to>/FVP_Base_Cortex-A57x4-A53x4 \
-C pctl.startup=0.0.0.0 \
-C bp.secure_memory=0 \
-C bp.secure_memory=1 \
-C bp.tzc_400.diagnostics=1 \
-C cache_state_modelled=1 \
-C bp.pl011_uart0.untimed_fifos=1 \
-C bp.secureflashloader.fname="<path-to>/<bl1-binary>" \

View File

@ -0,0 +1,265 @@
/*
* Copyright (c) 2014, ARM Limited and Contributors. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* Redistributions of source code must retain the above copyright notice, this
* list of conditions and the following disclaimer.
*
* Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
*
* Neither the name of ARM nor the names of its contributors may be used
* to endorse or promote products derived from this software without specific
* prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*/
#include <assert.h>
#include "arch_helpers.h"
#include "tzc400.h"
#include "mmio.h"
#include "debug.h"
static uint32_t tzc_read_build_config(uint64_t base)
{
return mmio_read_32(base + BUILD_CONFIG_OFF);
}
static uint32_t tzc_read_gate_keeper(uint64_t base)
{
return mmio_read_32(base + GATE_KEEPER_OFF);
}
static void tzc_write_gate_keeper(uint64_t base, uint32_t val)
{
mmio_write_32(base + GATE_KEEPER_OFF, val);
}
static void tzc_write_action(uint64_t base, enum tzc_action action)
{
mmio_write_32(base + ACTION_OFF, action);
}
static void tzc_write_region_base_low(uint64_t base, uint32_t region, uint32_t val)
{
mmio_write_32(base + REGION_BASE_LOW_OFF + REGION_NUM_OFF(region), val);
}
static void tzc_write_region_base_high(uint64_t base, uint32_t region, uint32_t val)
{
mmio_write_32(base + REGION_BASE_HIGH_OFF + REGION_NUM_OFF(region), val);
}
static void tzc_write_region_top_low(uint64_t base, uint32_t region, uint32_t val)
{
mmio_write_32(base + REGION_TOP_LOW_OFF + REGION_NUM_OFF(region), val);
}
static void tzc_write_region_top_high(uint64_t base, uint32_t region, uint32_t val)
{
mmio_write_32(base + REGION_TOP_HIGH_OFF + REGION_NUM_OFF(region), val);
}
static void tzc_write_region_attributes(uint64_t base, uint32_t region, uint32_t val)
{
mmio_write_32(base + REGION_ATTRIBUTES_OFF + REGION_NUM_OFF(region), val);
}
static void tzc_write_region_id_access(uint64_t base, uint32_t region, uint32_t val)
{
mmio_write_32(base + REGION_ID_ACCESS_OFF + REGION_NUM_OFF(region), val);
}
static uint32_t tzc_read_component_id(uint64_t base)
{
uint32_t id;
id = mmio_read_8(base + CID0_OFF);
id |= (mmio_read_8(base + CID1_OFF) << 8);
id |= (mmio_read_8(base + CID2_OFF) << 16);
id |= (mmio_read_8(base + CID3_OFF) << 24);
return id;
}
static uint32_t tzc_get_gate_keeper(uint64_t base, uint8_t filter)
{
uint32_t tmp;
tmp = (tzc_read_gate_keeper(base) >> GATE_KEEPER_OS_SHIFT) &
GATE_KEEPER_OS_MASK;
return tmp >> filter;
}
/* This function is not MP safe. */
static void tzc_set_gate_keeper(uint64_t base, uint8_t filter, uint32_t val)
{
uint32_t tmp;
/* Upper half is current state. Lower half is requested state. */
tmp = (tzc_read_gate_keeper(base) >> GATE_KEEPER_OS_SHIFT) &
GATE_KEEPER_OS_MASK;
if (val)
tmp |= (1 << filter);
else
tmp &= ~(1 << filter);
tzc_write_gate_keeper(base, (tmp & GATE_KEEPER_OR_MASK) <<
GATE_KEEPER_OR_SHIFT);
/* Wait here until we see the change reflected in the TZC status. */
while (((tzc_read_gate_keeper(base) >> GATE_KEEPER_OS_SHIFT) &
GATE_KEEPER_OS_MASK) != tmp)
;
}
void tzc_init(struct tzc_instance *controller)
{
uint32_t tzc_id, tzc_build;
assert(controller != NULL);
/*
* We expect to see a tzc400. Check component ID. The TZC-400 TRM shows
* component ID is expected to be "0xB105F00D".
*/
tzc_id = tzc_read_component_id(controller->base);
if (tzc_id != TZC400_COMPONENT_ID) {
ERROR("TZC : Wrong device ID (0x%x).\n", tzc_id);
panic();
}
/* Save values we will use later. */
tzc_build = tzc_read_build_config(controller->base);
controller->num_filters = ((tzc_build >> BUILD_CONFIG_NF_SHIFT) &
BUILD_CONFIG_NF_MASK) + 1;
controller->addr_width = ((tzc_build >> BUILD_CONFIG_AW_SHIFT) &
BUILD_CONFIG_AW_MASK) + 1;
controller->num_regions = ((tzc_build >> BUILD_CONFIG_NR_SHIFT) &
BUILD_CONFIG_NR_MASK) + 1;
}
/*
* `tzc_configure_region` is used to program regions into the TrustZone
* controller. A region can be associated with more than one filter. The
* associated filters are passed in as a bitmap (bit0 = filter0).
* NOTE:
* The region 0 covers the whole address space and is enabled on all filters,
* this cannot be changed. It is, however, possible to change some region 0
* permissions.
*/
void tzc_configure_region(const struct tzc_instance *controller,
uint32_t filters,
uint8_t region,
uint64_t region_base,
uint64_t region_top,
enum tzc_region_attributes sec_attr,
uint32_t ns_device_access)
{
uint64_t max_addr;
assert(controller != NULL);
/* Do range checks on filters and regions. */
assert(((filters >> controller->num_filters) == 0) &&
(region < controller->num_regions));
/*
* Do address range check based on TZC configuration. A 64bit address is
* the max and expected case.
*/
max_addr = UINT64_MAX >> (64 - controller->addr_width);
if ((region_top > max_addr) || (region_base >= region_top))
assert(0);
/* region_base and (region_top + 1) must be 4KB aligned */
assert(((region_base | (region_top + 1)) & (4096 - 1)) == 0);
assert(sec_attr <= TZC_REGION_S_RDWR);
/*
* Inputs look ok, start programming registers.
* All the address registers are 32 bits wide and have a LOW and HIGH
* component used to construct a up to a 64bit address.
*/
tzc_write_region_base_low(controller->base, region, (uint32_t)(region_base));
tzc_write_region_base_high(controller->base, region, (uint32_t)(region_base >> 32));
tzc_write_region_top_low(controller->base, region, (uint32_t)(region_top));
tzc_write_region_top_high(controller->base, region, (uint32_t)(region_top >> 32));
/* Assign the region to a filter and set secure attributes */
tzc_write_region_attributes(controller->base, region,
(sec_attr << REGION_ATTRIBUTES_SEC_SHIFT) | filters);
/*
* Specify which non-secure devices have permission to access this
* region.
*/
tzc_write_region_id_access(controller->base, region, ns_device_access);
}
void tzc_set_action(const struct tzc_instance *controller, enum tzc_action action)
{
assert(controller != NULL);
/*
* - Currently no handler is provided to trap an error via interrupt
* or exception.
* - The interrupt action has not been tested.
*/
tzc_write_action(controller->base, action);
}
void tzc_enable_filters(const struct tzc_instance *controller)
{
uint32_t state;
uint32_t filter;
assert(controller != NULL);
for (filter = 0; filter < controller->num_filters; filter++) {
state = tzc_get_gate_keeper(controller->base, filter);
if (state) {
ERROR("TZC : Filter %d Gatekeeper already enabled.\n",
filter);
panic();
}
tzc_set_gate_keeper(controller->base, filter, 1);
}
}
void tzc_disable_filters(const struct tzc_instance *controller)
{
uint32_t filter;
assert(controller != NULL);
/*
* We don't do the same state check as above as the Gatekeepers are
* disabled after reset.
*/
for (filter = 0; filter < controller->num_filters; filter++)
tzc_set_gate_keeper(controller->base, filter, 0);
}

View File

@ -0,0 +1,211 @@
/*
* Copyright (c) 2014, ARM Limited and Contributors. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* Redistributions of source code must retain the above copyright notice, this
* list of conditions and the following disclaimer.
*
* Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
*
* Neither the name of ARM nor the names of its contributors may be used
* to endorse or promote products derived from this software without specific
* prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*/
#ifndef __TZC400_H__
#define __TZC400_H__
#include <stdint.h>
#define BUILD_CONFIG_OFF 0x000
#define ACTION_OFF 0x004
#define GATE_KEEPER_OFF 0x008
#define SPECULATION_CTRL_OFF 0x00c
#define INT_STATUS 0x010
#define INT_CLEAR 0x014
#define FAIL_ADDRESS_LOW_OFF 0x020
#define FAIL_ADDRESS_HIGH_OFF 0x024
#define FAIL_CONTROL_OFF 0x028
#define FAIL_ID 0x02c
#define REGION_BASE_LOW_OFF 0x100
#define REGION_BASE_HIGH_OFF 0x104
#define REGION_TOP_LOW_OFF 0x108
#define REGION_TOP_HIGH_OFF 0x10c
#define REGION_ATTRIBUTES_OFF 0x110
#define REGION_ID_ACCESS_OFF 0x114
#define REGION_NUM_OFF(region) (0x20 * region)
/* ID Registers */
#define PID0_OFF 0xfe0
#define PID1_OFF 0xfe4
#define PID2_OFF 0xfe8
#define PID3_OFF 0xfec
#define PID4_OFF 0xfd0
#define PID5_OFF 0xfd4
#define PID6_OFF 0xfd8
#define PID7_OFF 0xfdc
#define CID0_OFF 0xff0
#define CID1_OFF 0xff4
#define CID2_OFF 0xff8
#define CID3_OFF 0xffc
#define BUILD_CONFIG_NF_SHIFT 24
#define BUILD_CONFIG_NF_MASK 0x3
#define BUILD_CONFIG_AW_SHIFT 8
#define BUILD_CONFIG_AW_MASK 0x3f
#define BUILD_CONFIG_NR_SHIFT 0
#define BUILD_CONFIG_NR_MASK 0x1f
/* Not describing the case where regions 1 to 8 overlap */
#define ACTION_RV_SHIFT 0
#define ACTION_RV_MASK 0x3
#define ACTION_RV_LOWOK 0x0
#define ACTION_RV_LOWERR 0x1
#define ACTION_RV_HIGHOK 0x2
#define ACTION_RV_HIGHERR 0x3
/*
* Number of gate keepers is implementation defined. But we know the max for
* this device is 4. Get implementation details from BUILD_CONFIG.
*/
#define GATE_KEEPER_OS_SHIFT 16
#define GATE_KEEPER_OS_MASK 0xf
#define GATE_KEEPER_OR_SHIFT 0
#define GATE_KEEPER_OR_MASK 0xf
/* Speculation is enabled by default. */
#define SPECULATION_CTRL_WRITE_DISABLE (1 << 1)
#define SPECULATION_CTRL_READ_DISABLE (1 << 0)
/* Max number of filters allowed is 4. */
#define INT_STATUS_OVERLAP_SHIFT 16
#define INT_STATUS_OVERLAP_MASK 0xf
#define INT_STATUS_OVERRUN_SHIFT 8
#define INT_STATUS_OVERRUN_MASK 0xf
#define INT_STATUS_STATUS_SHIFT 0
#define INT_STATUS_STATUS_MASK 0xf
#define INT_CLEAR_CLEAR_SHIFT 0
#define INT_CLEAR_CLEAR_MASK 0xf
#define FAIL_CONTROL_DIR_SHIFT (1 << 24)
#define FAIL_CONTROL_DIR_READ 0x0
#define FAIL_CONTROL_DIR_WRITE 0x1
#define FAIL_CONTROL_NS_SHIFT (1 << 21)
#define FAIL_CONTROL_NS_SECURE 0x0
#define FAIL_CONTROL_NS_NONSECURE 0x1
#define FAIL_CONTROL_PRIV_SHIFT (1 << 20)
#define FAIL_CONTROL_PRIV_PRIV 0x0
#define FAIL_CONTROL_PRIV_UNPRIV 0x1
/*
* FAIL_ID_ID_MASK depends on AID_WIDTH which is platform specific.
* Platform should provide the value on initialisation.
*/
#define FAIL_ID_VNET_SHIFT 24
#define FAIL_ID_VNET_MASK 0xf
#define FAIL_ID_ID_SHIFT 0
/* Used along with 'tzc_region_attributes_t' below */
#define REGION_ATTRIBUTES_SEC_SHIFT 30
#define REGION_ATTRIBUTES_F_EN_SHIFT 0
#define REGION_ATTRIBUTES_F_EN_MASK 0xf
#define REGION_ID_ACCESS_NSAID_WR_EN_SHIFT 16
#define REGION_ID_ACCESS_NSAID_RD_EN_SHIFT 0
#define REGION_ID_ACCESS_NSAID_ID_MASK 0xf
/* Macros for setting Region ID access permissions based on NSAID */
#define TZC_REGION_ACCESS_RD(id) \
((1 << (id & REGION_ID_ACCESS_NSAID_ID_MASK)) << \
REGION_ID_ACCESS_NSAID_RD_EN_SHIFT)
#define TZC_REGION_ACCESS_WR(id) \
((1 << (id & REGION_ID_ACCESS_NSAID_ID_MASK)) << \
REGION_ID_ACCESS_NSAID_WR_EN_SHIFT)
#define TZC_REGION_ACCESS_RDWR(id) \
(TZC_REGION_ACCESS_RD(id) | TZC_REGION_ACCESS_WR(id))
/* Filters are bit mapped 0 to 3. */
#define TZC400_COMPONENT_ID 0xb105f00d
#ifndef __ASSEMBLY__
/*******************************************************************************
* Function & variable prototypes
******************************************************************************/
/*
* What type of action is expected when an access violation occurs.
* The memory requested is zeroed. But we can also raise and event to
* let the system know it happened.
* We can raise an interrupt(INT) and/or cause an exception(ERR).
* TZC_ACTION_NONE - No interrupt, no Exception
* TZC_ACTION_ERR - No interrupt, raise exception -> sync external
* data abort
* TZC_ACTION_INT - Raise interrupt, no exception
* TZC_ACTION_ERR_INT - Raise interrupt, raise exception -> sync
* external data abort
*/
enum tzc_action {
TZC_ACTION_NONE = 0,
TZC_ACTION_ERR = 1,
TZC_ACTION_INT = 2,
TZC_ACTION_ERR_INT = (TZC_ACTION_ERR | TZC_ACTION_INT)
};
/*
* Controls secure access to a region. If not enabled secure access is not
* allowed to region.
*/
enum tzc_region_attributes {
TZC_REGION_S_NONE = 0,
TZC_REGION_S_RD = 1,
TZC_REGION_S_WR = 2,
TZC_REGION_S_RDWR = (TZC_REGION_S_RD | TZC_REGION_S_WR)
};
/*
* Implementation defined values used to validate inputs later.
* Filters : max of 4 ; 0 to 3
* Regions : max of 9 ; 0 to 8
* Address width : Values between 32 to 64
*/
struct tzc_instance {
uint64_t base;
uint32_t aid_width;
uint8_t addr_width;
uint8_t num_filters;
uint8_t num_regions;
};
void tzc_init(struct tzc_instance *controller);
void tzc_configure_region(const struct tzc_instance *controller, uint32_t filters,
uint8_t region, uint64_t region_base, uint64_t region_top,
enum tzc_region_attributes sec_attr, uint32_t ns_device_access);
void tzc_enable_filters(const struct tzc_instance *controller);
void tzc_disable_filters(const struct tzc_instance *controller);
void tzc_set_action(const struct tzc_instance *controller,
enum tzc_action action);
#endif /*__ASSEMBLY__*/
#endif /* __TZC400__ */

Binary file not shown.

View File

@ -147,10 +147,10 @@
#address-cells = <2>;
#size-cells = <2>;
ranges;
frame@2a820000 {
frame-number = <0>;
interrupts = <0 25 4>;
reg = <0x0 0x2a820000 0x0 0x10000>;
frame@2a830000 {
frame-number = <1>;
interrupts = <0 26 4>;
reg = <0x0 0x2a830000 0x0 0x10000>;
};
};

Binary file not shown.

View File

@ -147,10 +147,10 @@
#address-cells = <2>;
#size-cells = <2>;
ranges;
frame@2a820000 {
frame-number = <0>;
interrupts = <0 25 4>;
reg = <0x0 0x2a820000 0x0 0x10000>;
frame@2a830000 {
frame-number = <1>;
interrupts = <0 26 4>;
reg = <0x0 0x2a830000 0x0 0x10000>;
};
};

Binary file not shown.

View File

@ -156,10 +156,10 @@
#address-cells = <2>;
#size-cells = <2>;
ranges;
frame@2a820000 {
frame-number = <0>;
interrupts = <0 25 4>;
reg = <0x0 0x2a820000 0x0 0x10000>;
frame@2a830000 {
frame-number = <1>;
interrupts = <0 26 4>;
reg = <0x0 0x2a830000 0x0 0x10000>;
};
};

Binary file not shown.

View File

@ -36,7 +36,7 @@
};
/ {
model = "FVP Base";
model = "FVP Foundation";
compatible = "arm,fvp-base", "arm,vexpress";
interrupt-parent = <&gic>;
#address-cells = <2>;
@ -123,10 +123,10 @@
#address-cells = <2>;
#size-cells = <2>;
ranges;
frame@2a820000 {
frame-number = <0>;
interrupts = <0 25 4>;
reg = <0x0 0x2a820000 0x0 0x10000>;
frame@2a830000 {
frame-number = <1>;
interrupts = <0 26 4>;
reg = <0x0 0x2a830000 0x0 0x10000>;
};
};

View File

@ -36,7 +36,7 @@
};
/ {
model = "FVP Base";
model = "FVP Foundation";
compatible = "arm,fvp-base", "arm,vexpress";
interrupt-parent = <&gic>;
#address-cells = <2>;
@ -123,10 +123,10 @@
#address-cells = <2>;
#size-cells = <2>;
ranges;
frame@2a820000 {
frame-number = <0>;
interrupts = <0 25 4>;
reg = <0x0 0x2a820000 0x0 0x10000>;
frame@2a830000 {
frame-number = <1>;
interrupts = <0 26 4>;
reg = <0x0 0x2a830000 0x0 0x10000>;
};
};

Binary file not shown.

View File

@ -36,7 +36,7 @@
};
/ {
model = "FVP Base";
model = "FVP Foundation";
compatible = "arm,fvp-base", "arm,vexpress";
interrupt-parent = <&gic>;
#address-cells = <2>;
@ -132,10 +132,10 @@
#address-cells = <2>;
#size-cells = <2>;
ranges;
frame@2a820000 {
frame-number = <0>;
interrupts = <0 25 4>;
reg = <0x0 0x2a820000 0x0 0x10000>;
frame@2a830000 {
frame-number = <1>;
interrupts = <0 26 4>;
reg = <0x0 0x2a830000 0x0 0x10000>;
};
};

View File

@ -35,6 +35,9 @@
#include <stdint.h>
extern void mmio_write_8(uintptr_t addr, uint8_t value);
extern uint8_t mmio_read_8(uintptr_t addr);
extern void mmio_write_32(uintptr_t addr, uint32_t value);
extern uint32_t mmio_read_32(uintptr_t addr);

View File

@ -30,6 +30,16 @@
#include <stdint.h>
void mmio_write_8(uintptr_t addr, uint8_t value)
{
*(volatile uint8_t*)addr = value;
}
uint8_t mmio_read_8(uintptr_t addr)
{
return *(volatile uint8_t*)addr;
}
void mmio_write_32(uintptr_t addr, uint32_t value)
{
*(volatile uint32_t*)addr = value;

View File

@ -220,6 +220,7 @@ int platform_config_setup(void)
platform_config[CONFIG_CPU_SETUP] = 0;
platform_config[CONFIG_BASE_MMAP] = 0;
platform_config[CONFIG_HAS_CCI] = 0;
platform_config[CONFIG_HAS_TZC] = 0;
break;
case HBI_FVP_BASE:
midr_pn = (read_midr() >> MIDR_PN_SHIFT) & MIDR_PN_MASK;
@ -232,6 +233,7 @@ int platform_config_setup(void)
platform_config[CONFIG_MAX_AFF1] = 2;
platform_config[CONFIG_BASE_MMAP] = 1;
platform_config[CONFIG_HAS_CCI] = 1;
platform_config[CONFIG_HAS_TZC] = 1;
break;
default:
assert(0);

View File

@ -122,6 +122,14 @@ void bl2_early_platform_setup(meminfo *mem_layout,
******************************************************************************/
void bl2_platform_setup()
{
/*
* Do initial security configuration to allow DRAM/device access. On
* Base FVP only DRAM security is programmable (via TrustZone), but
* other platforms might have more programmable security devices
* present.
*/
plat_security_setup();
/* Initialise the IO layer and register platform IO devices */
io_setup();

131
plat/fvp/plat_security.c Normal file
View File

@ -0,0 +1,131 @@
/*
* Copyright (c) 2014, ARM Limited and Contributors. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* Redistributions of source code must retain the above copyright notice, this
* list of conditions and the following disclaimer.
*
* Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
*
* Neither the name of ARM nor the names of its contributors may be used
* to endorse or promote products derived from this software without specific
* prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*/
#include <assert.h>
#include "platform.h"
#include "tzc400.h"
#include "debug.h"
/* Used to improve readability for configuring regions. */
#define FILTER_SHIFT(filter) (1 << filter)
/*
* For the moment we assume that all security programming is done by the
* primary core.
* TODO:
* Might want to enable interrupt on violations when supported?
*/
void plat_security_setup(void)
{
struct tzc_instance controller;
/*
* The Base FVP has a TrustZone address space controller, the Foundation
* FVP does not. Trying to program the device on the foundation FVP will
* cause an abort.
*
* If the platform had additional peripheral specific security
* configurations, those would be configured here.
*/
if (!platform_get_cfgvar(CONFIG_HAS_TZC))
return;
/*
* The TrustZone controller controls access to main DRAM. Give
* full NS access for the moment to use with OS.
*/
INFO("Configuring TrustZone Controller\n");
/*
* The driver does some error checking and will assert.
* - Provide base address of device on platform.
* - Provide width of ACE-Lite IDs on platform.
*/
controller.base = TZC400_BASE;
controller.aid_width = FVP_AID_WIDTH;
tzc_init(&controller);
/*
* Currently only filters 0 and 2 are connected on Base FVP.
* Filter 0 : CPU clusters (no access to DRAM by default)
* Filter 1 : not connected
* Filter 2 : LCDs (access to VRAM allowed by default)
* Filter 3 : not connected
* Programming unconnected filters will have no effect at the
* moment. These filter could, however, be connected in future.
* So care should be taken not to configure the unused filters.
*/
/* Disable all filters before programming. */
tzc_disable_filters(&controller);
/*
* Allow full access to all DRAM to supported devices for the
* moment. Give access to the CPUs and Virtio. Some devices
* would normally use the default ID so allow that too. We use
* three different regions to cover the three separate blocks of
* memory in the FVPs. We allow secure access to DRAM to load NS
* software.
* FIXME: In current models Virtio uses a reserved ID. This is
* not correct and will be fixed.
*/
/* Set to cover 2GB block of DRAM */
tzc_configure_region(&controller, FILTER_SHIFT(0), 1,
DRAM_BASE, 0xFFFFFFFF, TZC_REGION_S_RDWR,
TZC_REGION_ACCESS_RDWR(FVP_NSAID_AP) |
TZC_REGION_ACCESS_RDWR(FVP_NSAID_DEFAULT) |
TZC_REGION_ACCESS_RDWR(FVP_NSAID_RES5));
/* Set to cover the 30GB block */
tzc_configure_region(&controller, FILTER_SHIFT(0), 2,
0x880000000, 0xFFFFFFFFF, TZC_REGION_S_RDWR,
TZC_REGION_ACCESS_RDWR(FVP_NSAID_AP) |
TZC_REGION_ACCESS_RDWR(FVP_NSAID_DEFAULT) |
TZC_REGION_ACCESS_RDWR(FVP_NSAID_RES5));
/* Set to cover 480GB block */
tzc_configure_region(&controller, FILTER_SHIFT(0), 3,
0x8800000000, 0xFFFFFFFFFF, TZC_REGION_S_RDWR,
TZC_REGION_ACCESS_RDWR(FVP_NSAID_AP) |
TZC_REGION_ACCESS_RDWR(FVP_NSAID_DEFAULT) |
TZC_REGION_ACCESS_RDWR(FVP_NSAID_RES5));
/*
* TODO: Interrupts are not currently supported. The only
* options we have are for access errors to occur quietly or to
* cause an exception. We choose to cause an exception.
*/
tzc_set_action(&controller, TZC_ACTION_ERR);
/* Enable filters. */
tzc_enable_filters(&controller);
}

View File

@ -99,7 +99,8 @@
#define CONFIG_BASE_MMAP 7
/* Indicates whether CCI should be enabled on the platform. */
#define CONFIG_HAS_CCI 8
#define CONFIG_LIMIT 9
#define CONFIG_HAS_TZC 9
#define CONFIG_LIMIT 10
/*******************************************************************************
* Platform memory map related constants
@ -303,6 +304,28 @@
#define PL011_UART3_BASE 0x1c0c0000
#define PL011_BASE PL011_UART0_BASE
/*******************************************************************************
* TrustZone address space controller related constants
******************************************************************************/
#define TZC400_BASE 0x2a4a0000
/*
* The NSAIDs for this platform as used to program the TZC400.
* TODO:
* This list and the numbers in it is still changing on the Base FVP.
* For now only specify the NSAIDs we actually use.
*/
/* The FVP has 4 bits of NSAIDs. Used with TZC FAIL_ID (ACE Lite ID width) */
#define FVP_AID_WIDTH 4
#define FVP_NSAID_DEFAULT 0
#define FVP_NSAID_AP 9 /* Application Processors */
/* FIXME: Currently incorrectly used by Virtio */
#define FVP_NSAID_RES5 15
/*******************************************************************************
* Declarations and constants to access the mailboxes safely. Each mailbox is
* aligned on the biggest cache line size in the platform. This is known only
@ -374,6 +397,10 @@ extern void io_setup(void);
extern int plat_get_image_source(const char *image_name,
io_dev_handle *dev_handle, void **image_spec);
/* Declarations for plat_security.c */
extern void plat_security_setup(void);
#endif /*__ASSEMBLY__*/
#endif /* __PLATFORM_H__ */

View File

@ -29,6 +29,7 @@
#
PLAT_INCLUDES := -Idrivers/arm/interconnect/cci-400 \
-Idrivers/arm/interconnect/tzc-400 \
-Idrivers/console \
-Idrivers/arm/peripherals/pl011 \
-Idrivers/power
@ -43,6 +44,7 @@ PLAT_BL1_C_VPATH := drivers/arm/interconnect/cci-400 \
PLAT_BL1_S_VPATH := lib/semihosting/${ARCH}
PLAT_BL2_C_VPATH := drivers/arm/interconnect/cci-400 \
drivers/arm/interconnect/tzc-400 \
drivers/arm/peripherals/pl011 \
lib/arch/${ARCH} \
lib/stdlib \
@ -82,7 +84,9 @@ BL1_SOURCES += bl1_plat_setup.c \
BL2_SOURCES += bl2_plat_setup.c \
platform_up_stack.S \
plat_common.c
plat_common.c \
plat_security.c \
tzc400.c
BL31_SOURCES += bl31_plat_setup.c \
plat_helpers.S \