aboutsummaryrefslogtreecommitdiff
path: root/core
diff options
context:
space:
mode:
authorsunny <sunny@allwinnertech.com>2014-11-07 14:23:34 +0800
committersunny <sunny@allwinnertech.com>2015-01-16 19:25:33 -0800
commit056cd73a3901d0187d936e6f0e8d2917e96526df (patch)
tree94c5ec1cbb57e09926059f55831e18f4a5d04ff5 /core
parentbedc2b9fafb3fe78e8176d5e0879ffd6eab52ea1 (diff)
Add plat-sunxi
Initial version support for Allwinner A80 platform. Allwinner A80 is big.little archtecture with 4*A7 + 4*A15, Support Trustzone tech and secureboot inside hardware. plat-sunxi support features: 1.Clone plat-sunxi from plat-vexpress; 2.Secure bootloader reserved 64MB secure DRAM for optee_os; 3.Support SMP secondary cpu secure stage bootup; 4.Add uart driver to core/driver/*; 5.Support GIC driver initialization. The porting work test on Optimus board, with allwinner A80 chip. Signed-off-by: sunny <sunny@allwinnertech.com> Reviewed-by: Joakim Bech <joakim.bech@linaro.org> Reviewed-by: Jens Wiklander <jens.wiklander@linaro.org> Reviewed-by: Pascal Brand <pascal.brand@linaro.org>
Diffstat (limited to 'core')
-rw-r--r--core/arch/arm32/include/arm32.h51
-rw-r--r--core/arch/arm32/include/arm32_macros.S9
-rw-r--r--core/arch/arm32/plat-sunxi/conf.mk41
-rw-r--r--core/arch/arm32/plat-sunxi/console.c40
-rw-r--r--core/arch/arm32/plat-sunxi/core_bootcfg.c267
-rw-r--r--core/arch/arm32/plat-sunxi/core_chip.c33
-rw-r--r--core/arch/arm32/plat-sunxi/entry.S100
-rw-r--r--core/arch/arm32/plat-sunxi/head.c60
-rw-r--r--core/arch/arm32/plat-sunxi/kern.ld.S174
-rw-r--r--core/arch/arm32/plat-sunxi/link.mk54
-rw-r--r--core/arch/arm32/plat-sunxi/main.c413
-rw-r--r--core/arch/arm32/plat-sunxi/platform.c106
-rw-r--r--core/arch/arm32/plat-sunxi/platform.h84
-rw-r--r--core/arch/arm32/plat-sunxi/platform_config.h84
-rw-r--r--core/arch/arm32/plat-sunxi/platform_flags.mk24
-rw-r--r--core/arch/arm32/plat-sunxi/rng_support.c43
-rw-r--r--core/arch/arm32/plat-sunxi/smp_boot.S96
-rw-r--r--core/arch/arm32/plat-sunxi/smp_fixup.S111
-rw-r--r--core/arch/arm32/plat-sunxi/sub.mk15
-rw-r--r--core/arch/arm32/plat-sunxi/tee_common_otp.c64
-rw-r--r--core/drivers/sub.mk1
-rw-r--r--core/drivers/sunxi_uart.c99
-rw-r--r--core/include/drivers/sunxi_uart.h43
23 files changed, 2012 insertions, 0 deletions
diff --git a/core/arch/arm32/include/arm32.h b/core/arch/arm32/include/arm32.h
index 108c4fe..093ed79 100644
--- a/core/arch/arm32/include/arm32.h
+++ b/core/arch/arm32/include/arm32.h
@@ -86,6 +86,21 @@
#define SCTLR_AFE (1 << 29)
#define SCTLR_TE (1 << 30)
+#define ACTLR_SMP (1 << 6)
+#define ACTLR_DODMBS (1 << 10)
+#define ACTLR_L2RADIS (1 << 11)
+#define ACTLR_L1RADIS (1 << 12)
+#define ACTLR_L1PCTL (1 << 13)
+#define ACTLR_DDVM (1 << 15)
+#define ACTLR_DDI (1 << 28)
+
+#define NSACR_CP10 (1 << 10)
+#define NSACR_CP11 (1 << 11)
+#define NSACR_NSD32DIS (1 << 14)
+#define NSACR_NSASEDIS (1 << 15)
+#define NSACR_NS_L2ERR (1 << 17)
+#define NSACR_NS_SMP (1 << 18)
+
#define DACR_DOMAIN(num, perm) ((perm) << ((num) * 2))
#define DACR_DOMAIN_PERM_NO_ACCESS 0x0
#define DACR_DOMAIN_PERM_CLIENT 0x1
@@ -276,6 +291,42 @@ static inline uint32_t read_spsr(void)
return spsr;
}
+static inline uint32_t read_actlr(void)
+{
+ uint32_t actlr;
+
+ asm volatile ("mrc p15, 0, %[actlr], c1, c0, 1"
+ : [actlr] "=r" (actlr)
+ );
+
+ return actlr;
+}
+
+static inline void write_actlr(uint32_t actlr)
+{
+ asm volatile ("mcr p15, 0, %[actlr], c1, c0, 1"
+ : : [actlr] "r" (actlr)
+ );
+}
+
+static inline uint32_t read_nsacr(void)
+{
+ uint32_t nsacr;
+
+ asm volatile ("mrc p15, 0, %[nsacr], c1, c1, 2"
+ : [nsacr] "=r" (nsacr)
+ );
+
+ return nsacr;
+}
+
+static inline void write_nsacr(uint32_t nsacr)
+{
+ asm volatile ("mcr p15, 0, %[nsacr], c1, c1, 2"
+ : : [nsacr] "r" (nsacr)
+ );
+}
+
#endif
#endif /*ARM32_H*/
diff --git a/core/arch/arm32/include/arm32_macros.S b/core/arch/arm32/include/arm32_macros.S
index 62d94eb..20a5991 100644
--- a/core/arch/arm32/include/arm32_macros.S
+++ b/core/arch/arm32/include/arm32_macros.S
@@ -110,3 +110,12 @@
.macro write_pcr reg
mcr p15, 0, \reg, c15, c0, 0
.endm
+
+ .macro read_actlr reg
+ mrc p15, 0, \reg, c1, c0, 1
+ .endm
+
+ .macro read_nsacr reg
+ mrc p15, 0, \reg, c1, c1, 2
+ .endm
+
diff --git a/core/arch/arm32/plat-sunxi/conf.mk b/core/arch/arm32/plat-sunxi/conf.mk
new file mode 100644
index 0000000..7b94bab
--- /dev/null
+++ b/core/arch/arm32/plat-sunxi/conf.mk
@@ -0,0 +1,41 @@
+include core/arch/$(ARCH)/plat-$(PLATFORM)/platform_flags.mk
+
+CROSS_PREFIX ?= arm-linux-gnueabihf
+CROSS_COMPILE ?= $(CROSS_PREFIX)-
+include mk/gcc.mk
+
+core-platform-cppflags = -I$(arch-dir)/include
+core-platform-cppflags += -DNUM_THREADS=4
+core-platform-cppflags += -DWITH_STACK_CANARIES=1
+core-platform-subdirs += \
+ $(addprefix $(arch-dir)/, kernel mm tee sta) $(platform-dir)
+core-platform-subdirs += $(arch-dir)/sm
+core-platform-cppflags += -DWITH_SEC_MON=1
+
+CFG_PM_DEBUG ?= 0
+ifeq ($(CFG_PM_DEBUG),1)
+core-platform-cppflags += \
+ -DCFG_PM_DEBUG
+endif
+
+libutil_with_isoc := y
+WITH_SECURE_TIME_SOURCE_CNTPCT := y
+
+include mk/config.mk
+
+CFG_TEE_CORE_EMBED_INTERNAL_TESTS ?= 1
+core-platform-cppflags += \
+ -DCFG_TEE_CORE_EMBED_INTERNAL_TESTS=$(CFG_TEE_CORE_EMBED_INTERNAL_TESTS)
+
+core-platform-cppflags += -DTEE_USE_DLMALLOC
+core-platform-cppflags += -D_USE_SLAPORT_LIB
+
+
+# Several CPU suppoorted
+core-platform-cppflags += -DTEE_MULTI_CPU
+# define flag to support booting from GDB
+core-platform-cppflags += -DCONFIG_TEE_GDB_BOOT
+core-platform-cppflags += -DCFG_NO_TA_HASH_SIGN
+core-platform-cppflags += -DWITH_UART_DRV=1
+WITH_SUNXI_UART := y
+WITH_GIC_DRV := y
diff --git a/core/arch/arm32/plat-sunxi/console.c b/core/arch/arm32/plat-sunxi/console.c
new file mode 100644
index 0000000..8b1f6e1
--- /dev/null
+++ b/core/arch/arm32/plat-sunxi/console.c
@@ -0,0 +1,40 @@
+/*
+ * Copyright (c) 2014, Allwinner Technology Co., Ltd.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice,
+ * this list of conditions and the following disclaimer.
+ *
+ * 2. 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.
+ *
+ * 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 <platform_config.h>
+#include <drivers/sunxi_uart.h>
+#include <console.h>
+
+void console_putc(int ch)
+{
+ sunxi_uart_putc(ch, CONSOLE_UART_BASE);
+}
+
+void console_flush_tx_fifo(void)
+{
+ sunxi_uart_flush_tx_fifo(CONSOLE_UART_BASE);
+}
diff --git a/core/arch/arm32/plat-sunxi/core_bootcfg.c b/core/arch/arm32/plat-sunxi/core_bootcfg.c
new file mode 100644
index 0000000..b79bb6e
--- /dev/null
+++ b/core/arch/arm32/plat-sunxi/core_bootcfg.c
@@ -0,0 +1,267 @@
+/*
+ * Copyright (c) 2014, Allwinner Technology Co., Ltd.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice,
+ * this list of conditions and the following disclaimer.
+ *
+ * 2. 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.
+ *
+ * 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 <platform_config.h>
+
+#include <mm/core_mmu.h>
+#include <mm/core_memprot.h>
+#include <util.h>
+#include <kernel/tee_misc.h>
+#include <trace.h>
+
+#ifndef CFG_DDR_TEETZ_RESERVED_START
+#error "TEETZ reserved DDR start address undef: CFG_DDR_TEETZ_RESERVED_START"
+#endif
+#ifndef CFG_DDR_TEETZ_RESERVED_SIZE
+#error "TEETZ reserved DDR siez undefined: CFG_DDR_TEETZ_RESERVED_SIZE"
+#endif
+
+/*
+ * TEE/TZ RAM layout:
+ *
+ * +-----------------------------------------+ <- CFG_DDR_TEETZ_RESERVED_START
+ * | TEETZ private RAM | TEE_RAM | ^
+ * | +--------------------+ |
+ * | | TA_RAM | |
+ * +-----------------------------------------+ | CFG_DDR_TEETZ_RESERVED_SIZE
+ * | | teecore alloc | |
+ * | TEE/TZ and NSec | PUB_RAM --------| |
+ * | shared memory | NSec alloc | |
+ * +-----------------------------------------+ v
+ *
+ * TEE_RAM : 1MByte
+ * PUB_RAM : 1MByte
+ * TA_RAM : all what is left (at least 2MByte !)
+ */
+
+/* define the several memory area sizes */
+#if (CFG_DDR_TEETZ_RESERVED_SIZE < (4 * 1024 * 1024))
+#error "Invalid CFG_DDR_TEETZ_RESERVED_SIZE: at least 4MB expected"
+#endif
+
+#define CFG_PUB_RAM_SIZE (1 * 1024 * 1024)
+#define CFG_TEE_RAM_SIZE (1 * 1024 * 1024)
+#define CFG_TA_RAM_SIZE (CFG_DDR_TEETZ_RESERVED_SIZE - \
+ CFG_TEE_RAM_SIZE - CFG_PUB_RAM_SIZE)
+
+/* define the secure/unsecure memory areas */
+#define CFG_DDR_ARMTZ_ONLY_START (CFG_DDR_TEETZ_RESERVED_START)
+#define CFG_DDR_ARMTZ_ONLY_SIZE (CFG_TEE_RAM_SIZE + CFG_TA_RAM_SIZE)
+
+#define CFG_DDR_ARM_ARMTZ_START \
+ (CFG_DDR_ARMTZ_ONLY_START + CFG_DDR_ARMTZ_ONLY_SIZE)
+#define CFG_DDR_ARM_ARMTZ_SIZE (CFG_PUB_RAM_SIZE)
+
+/* define the memory areas (TEE_RAM must start at reserved DDR start addr */
+#define CFG_TEE_RAM_START (CFG_DDR_ARMTZ_ONLY_START)
+#define CFG_TA_RAM_START (CFG_TEE_RAM_START + CFG_TEE_RAM_SIZE)
+#define CFG_PUB_RAM_START (CFG_TA_RAM_START + CFG_TA_RAM_SIZE)
+
+
+/*
+ * define the platform memory Secure layout
+ */
+struct memaccess_area {
+ unsigned long paddr;
+ size_t size;
+};
+#define MEMACCESS_AREA(a, s) { .paddr = a, .size = s }
+
+static struct memaccess_area ddr[] = {
+ MEMACCESS_AREA(CFG_DDR_START, CFG_DDR_SIZE),
+};
+
+static struct memaccess_area secure_only =
+MEMACCESS_AREA(CFG_DDR_ARMTZ_ONLY_START, CFG_DDR_ARMTZ_ONLY_SIZE);
+
+static struct memaccess_area nsec_shared =
+MEMACCESS_AREA(CFG_DDR_ARM_ARMTZ_START, CFG_DDR_ARM_ARMTZ_SIZE);
+
+/* pbuf_is_ddr - return true is buffer is inside the DDR */
+static bool pbuf_is_ddr(unsigned long paddr, size_t size)
+{
+ int i = sizeof(ddr) / sizeof(*ddr);
+
+ while (i--) {
+ if (core_is_buffer_inside(paddr, size,
+ ddr[i].paddr, ddr[i].size))
+ return true;
+ }
+ return false;
+}
+
+/*
+ * pbuf_is_multipurpose - return true is buffer is inside unsafe DDR
+ *
+ * Unsafe DDR (or multipurpose DDR) is DDR that is under a firewalling
+ * reconfigured at run-time: there is no static information that can
+ * tell wether this RAM is tagged secured or not.
+ */
+static bool pbuf_is_multipurpose(unsigned long paddr, size_t size)
+{
+ if (core_is_buffer_intersect(paddr, size,
+ secure_only.paddr, secure_only.size))
+ return false;
+ if (core_is_buffer_intersect(paddr, size,
+ nsec_shared.paddr, nsec_shared.size))
+ return false;
+
+ return pbuf_is_ddr(paddr, size);
+}
+
+/*
+ * Wrapper for the platform specific pbuf_is() service.
+ */
+static bool pbuf_is(enum buf_is_attr attr, unsigned long paddr, size_t size)
+{
+ switch (attr) {
+ case CORE_MEM_SEC:
+ return core_is_buffer_inside(paddr, size,
+ secure_only.paddr, secure_only.size);
+
+ case CORE_MEM_NON_SEC:
+ return core_is_buffer_inside(paddr, size,
+ nsec_shared.paddr, nsec_shared.size);
+
+ case CORE_MEM_MULTPURPOSE:
+ return pbuf_is_multipurpose(paddr, size);
+
+ case CORE_MEM_EXTRAM:
+ return pbuf_is_ddr(paddr, size);
+
+ default:
+ EMSG("unpexted request: attr=%X", attr);
+ return false;
+ }
+}
+
+static struct map_area bootcfg_memory[] = {
+ { /* teecore execution RAM */
+ .type = MEM_AREA_TEE_RAM,
+ .pa = CFG_TEE_RAM_START, .size = CFG_TEE_RAM_SIZE,
+ .cached = true, .secure = true, .rw = true, .exec = true,
+ },
+
+ { /* teecore TA load/exec RAM - Secure, exec user only! */
+ .type = MEM_AREA_TA_RAM,
+ .pa = CFG_TA_RAM_START, .size = CFG_TA_RAM_SIZE,
+ .cached = true, .secure = true, .rw = true, .exec = false,
+ },
+
+ { /* teecore public RAM - NonSecure, non-exec. */
+ .type = MEM_AREA_NSEC_SHM,
+ .pa = CFG_PUB_RAM_START, .size = SECTION_SIZE,
+ .cached = true, .secure = false, .rw = true, .exec = false,
+ },
+
+ { /* AHB0 devices */
+ .type = MEM_AREA_IO_NSEC,
+ .pa = 0x01400000 & ~SECTION_MASK, .size = 0x00900000,
+ .device = true, .secure = true, .rw = true,
+ },
+
+ { /* AHB1 devices */
+ .type = MEM_AREA_IO_NSEC,
+ .pa = (0x00800000) & ~SECTION_MASK, .size = 0x00300000,
+ .device = true, .secure = true, .rw = true,
+ },
+ { /* AHB2 devices */
+ .type = MEM_AREA_IO_NSEC,
+ .pa = (0x03000000) & ~SECTION_MASK, .size = 0x01000000,
+ .device = true, .secure = true, .rw = true,
+ },
+ { /* AHBS devices */
+ .type = MEM_AREA_IO_NSEC,
+ .pa = (0x06000000) & ~SECTION_MASK, .size = 0x02200000,
+ .device = true, .secure = true, .rw = true,
+ },
+
+ {.type = MEM_AREA_NOTYPE}
+};
+
+/*
+ * bootcfg_get_pbuf_is_handler - return the platform specfic pbuf_is
+ */
+unsigned long bootcfg_get_pbuf_is_handler(void)
+{
+ return (unsigned long)pbuf_is;
+}
+
+/*
+ * This routine is called while MMU and core memory management are not init.
+ */
+struct map_area *bootcfg_get_memory(void)
+{
+ struct map_area *map;
+ struct memaccess_area *a, *a2;
+ struct map_area *ret = bootcfg_memory;
+
+ /* check defined memory access layout */
+ a = (struct memaccess_area *)&secure_only;
+ a2 = (struct memaccess_area *)&nsec_shared;
+ if (core_is_buffer_intersect(a->paddr, a->size, a2->paddr, a2->size)) {
+ EMSG("invalid memory access configuration: sec/nsec");
+ return NULL;
+ }
+
+ /* check defined mapping (overlapping will be tested later) */
+ map = bootcfg_memory;
+ while (map->type != MEM_AREA_NOTYPE) {
+ switch (map->type) {
+ case MEM_AREA_TEE_RAM:
+ a = (struct memaccess_area *)&secure_only;
+ if (!core_is_buffer_inside(map->pa, map->size,
+ a->paddr, a->size)) {
+ EMSG("TEE_RAM does not fit in secure_only");
+ ret = NULL;
+ }
+ break;
+ case MEM_AREA_TA_RAM:
+ a = (struct memaccess_area *)&secure_only;
+ if (!core_is_buffer_inside(map->pa, map->size,
+ a->paddr, a->size)) {
+ EMSG("TA_RAM does not fit in secure_only");
+ ret = NULL;
+ }
+ break;
+ case MEM_AREA_NSEC_SHM:
+ a = (struct memaccess_area *)&nsec_shared;
+ if (!core_is_buffer_inside(map->pa, map->size,
+ a->paddr, a->size)) {
+ EMSG("NSEC_RAM does not fit in nsec_shared");
+ ret = NULL;
+ }
+ break;
+ default:
+ /* other mapped areas are not checked */
+ break;
+ }
+ map++;
+ }
+
+ return ret;
+}
+
diff --git a/core/arch/arm32/plat-sunxi/core_chip.c b/core/arch/arm32/plat-sunxi/core_chip.c
new file mode 100644
index 0000000..0a54f76
--- /dev/null
+++ b/core/arch/arm32/plat-sunxi/core_chip.c
@@ -0,0 +1,33 @@
+/*
+ * Copyright (c) 2014, Allwinner Technology Co., Ltd.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice,
+ * this list of conditions and the following disclaimer.
+ *
+ * 2. 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.
+ *
+ * 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 <kernel/tee_misc_unpg.h>
+
+uint32_t tee_get_cutid(void)
+{
+ return 0;
+}
diff --git a/core/arch/arm32/plat-sunxi/entry.S b/core/arch/arm32/plat-sunxi/entry.S
new file mode 100644
index 0000000..882837c
--- /dev/null
+++ b/core/arch/arm32/plat-sunxi/entry.S
@@ -0,0 +1,100 @@
+/*
+ * Copyright (c) 2014, Allwinner Technology Co., Ltd.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice,
+ * this list of conditions and the following disclaimer.
+ *
+ * 2. 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.
+ *
+ * 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 <platform_config.h>
+
+#include <asm.S>
+#include <arm32.h>
+#include <arm32_macros.S>
+#include <sm/teesmc.h>
+#include <sm/teesmc_opteed_macros.h>
+#include <sm/teesmc_opteed.h>
+
+.section .text.boot
+.align 5
+FUNC _start , :
+ b reset
+ b . /* Undef */
+ b . /* Syscall */
+ b . /* Prefetch abort */
+ b . /* Data abort */
+ b . /* Reserved */
+ b . /* IRQ */
+ b . /* FIQ */
+END_FUNC _start
+
+LOCAL_FUNC reset , :
+ read_sctlr r0
+ orr r0, r0, #SCTLR_A
+ write_sctlr r0
+
+ ldr r0, =_start
+ write_vbar r0
+
+ mov r4, r1
+ bl get_core_pos
+ lsl r0, #2
+ ldr r1, =stack_tmp_top
+ ldr sp, [r1, r0]
+
+ /* NSACR configuration */
+ read_nsacr r1
+ orr r1, r1, #NSACR_CP10
+ orr r1, r1, #NSACR_CP11
+ orr r1, r1, #NSACR_NS_SMP
+ write_nsacr r1
+
+ /* Enable SMP bit */
+ read_actlr r0
+ orr r0, r0, #ACTLR_SMP
+ write_actlr r0
+
+ bl core_init_mmu_tables
+ bl core_init_mmu_regs
+ bl cpu_mmu_enable
+ bl cpu_mmu_enable_icache
+ bl cpu_mmu_enable_dcache
+
+ /* init BSS section */
+ ldr r0, =__bss_start
+ ldr r2, =__bss_end
+ sub r2, r2, r0
+ ldr r1, =0
+ bl memset
+
+ /* r4: the return address of normal world */
+ mov r0, r4
+ bl main_init
+
+ mov r1, #0
+ mov r2, #0
+ mov r3, #0
+ mov r0, #TEESMC_OPTEED_RETURN_ENTRY_DONE
+ smc #0
+ b . /* SMC should never return */
+END_FUNC reset
+
diff --git a/core/arch/arm32/plat-sunxi/head.c b/core/arch/arm32/plat-sunxi/head.c
new file mode 100644
index 0000000..838dbf4
--- /dev/null
+++ b/core/arch/arm32/plat-sunxi/head.c
@@ -0,0 +1,60 @@
+/*
+ * Copyright (c) 2014, Allwinner Technology Co., Ltd.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice,
+ * this list of conditions and the following disclaimer.
+ *
+ * 2. 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.
+ *
+ * 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.
+ */
+
+/**
+ * Header for optee, use for secure bootloader.
+ **/
+
+#include <platform_config.h>
+
+/******************************************************************************/
+/* the control information stored in file head */
+/******************************************************************************/
+struct spare_boot_ctrl_head {
+ unsigned int jump_instruction; /* one intruction jumping to real code */
+ unsigned char magic[8]; /* ="optee" */
+ unsigned int check_sum; /* generated by PC */
+ unsigned int align_size; /* align size in byte */
+ unsigned int length; /* the size of all file */
+ unsigned int optee_length; /* the size of optee */
+ unsigned char version[8]; /* optee version */
+ unsigned char platform[8]; /* platform information */
+ int reserved[1]; /* stamp space, 16bytes align */
+};
+
+const struct spare_boot_ctrl_head tee_spare_head
+ __attribute__ ((section(".text.head"))) = {
+ (0xEA000000 | (((sizeof(struct spare_boot_ctrl_head) + sizeof(int) - 1) / sizeof(int) - 2) & 0x00FFFFFF)),
+ "optee",
+ 0,
+ 0,
+ 0,
+ 0,
+ "2.0",
+ "optee",
+ {TZDRAM_BASE}
+};
diff --git a/core/arch/arm32/plat-sunxi/kern.ld.S b/core/arch/arm32/plat-sunxi/kern.ld.S
new file mode 100644
index 0000000..674b145
--- /dev/null
+++ b/core/arch/arm32/plat-sunxi/kern.ld.S
@@ -0,0 +1,174 @@
+/*
+ * Copyright (c) 2014, Allwinner Technology Co., Ltd.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice,
+ * this list of conditions and the following disclaimer.
+ *
+ * 2. 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.
+ *
+ * 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.
+ */
+
+/*
+ * Copyright (c) 2008-2010 Travis Geiselbrecht
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining
+ * a copy of this software and associated documentation files
+ * (the "Software"), to deal in the Software without restriction,
+ * including without limitation the rights to use, copy, modify, merge,
+ * publish, distribute, sublicense, and/or sell copies of the Software,
+ * and to permit persons to whom the Software is furnished to do so,
+ * subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+ * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
+ * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+ * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+ * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+#include <platform_config.h>
+
+OUTPUT_FORMAT(PLATFORM_LINKER_FORMAT)
+OUTPUT_ARCH(PLATFORM_LINKER_ARCH)
+
+ENTRY(_start)
+SECTIONS
+{
+ . = TEE_RAM_START;
+
+ /* text/read-only data */
+ .text : {
+ __text_start = .;
+ KEEP(*(.text.head))
+ KEEP(*(.text.boot.vectab1))
+ KEEP(*(.text.boot.vectab2))
+ KEEP(*(.text.boot))
+ *(.text* .sram.text.glue_7* .gnu.linkonce.t.*)
+ __text_end = .;
+ }
+
+ .interp : { *(.interp) }
+ .hash : { *(.hash) }
+ .dynsym : { *(.dynsym) }
+ .dynstr : { *(.dynstr) }
+ .rel.text : { *(.rel.text) *(.rel.gnu.linkonce.t*) }
+ .rela.text : { *(.rela.text) *(.rela.gnu.linkonce.t*) }
+ .rel.data : { *(.rel.data) *(.rel.gnu.linkonce.d*) }
+ .rela.data : { *(.rela.data) *(.rela.gnu.linkonce.d*) }
+ .rel.rodata : { *(.rel.rodata) *(.rel.gnu.linkonce.r*) }
+ .rela.rodata : { *(.rela.rodata) *(.rela.gnu.linkonce.r*) }
+ .rel.got : { *(.rel.got) }
+ .rela.got : { *(.rela.got) }
+ .rel.ctors : { *(.rel.ctors) }
+ .rela.ctors : { *(.rela.ctors) }
+ .rel.dtors : { *(.rel.dtors) }
+ .rela.dtors : { *(.rela.dtors) }
+ .rel.init : { *(.rel.init) }
+ .rela.init : { *(.rela.init) }
+ .rel.fini : { *(.rel.fini) }
+ .rela.fini : { *(.rela.fini) }
+ .rel.bss : { *(.rel.bss) }
+ .rela.bss : { *(.rela.bss) }
+ .rel.plt : { *(.rel.plt) }
+ .rela.plt : { *(.rela.plt) }
+ .init : { *(.init) } =0x9090
+ .plt : { *(.plt) }
+
+ /* .ARM.exidx is sorted, so has to go in its own output section. */
+ __exidx_start = .;
+ .ARM.exidx : { *(.ARM.exidx* .gnu.linkonce.armexidx.*) }
+ __exidx_end = .;
+
+ .rodata : ALIGN(4) {
+ __rodata_start = .;
+ *(.rodata .rodata.* .gnu.linkonce.r.*)
+
+ __start_ta_head_section = . ;
+ *(ta_head_section)
+ __stop_ta_head_section = . ;
+
+ . = ALIGN(4);
+ __rodata_end = .;
+ }
+
+
+ .data : ALIGN(4) {
+ /* writable data */
+ __data_start_rom = .;
+ /* in one segment binaries, the rom data address is on top of the ram data address */
+ __data_start = .;
+ *(.data .data.* .gnu.linkonce.d.*)
+ }
+
+ .ctors : ALIGN(4) {
+ __ctor_list = .;
+ *(.ctors)
+ __ctor_end = .;
+ }
+ .dtors : ALIGN(4) {
+ __dtor_list = .;
+ *(.dtors)
+ __dtor_end = .;
+ }
+ .got : { *(.got.plt) *(.got) }
+ .dynamic : { *(.dynamic) }
+
+ __data_end = .;
+
+ /* unintialized data (in same segment as writable data) */
+ .bss : ALIGN(4) {
+ KEEP(*(.bss.prebss.*))
+ . = ALIGN(4);
+ __bss_start = .;
+ *(.bss .bss.*)
+ *(.gnu.linkonce.b.*)
+ *(COMMON)
+ . = ALIGN(4);
+ __bss_end = .;
+ }
+
+ /*
+ * Uninitialized data that shouldn't be zero initialized at
+ * runtime.
+ *
+ * L1 mmu table requires 16 KiB alignment
+ */
+ .nozi : ALIGN(16 * 1024) {
+ __nozi_pad_end = .;
+ KEEP(*(.nozi .nozi.*))
+ }
+
+ teecore_heap_start = .;
+ . += 0x40000 /*256KiB*/;
+ teecore_heap_end = .;
+
+ _end = .;
+
+ . = TEE_RAM_START + TEE_RAM_SIZE;
+ _end_of_ram = .;
+
+ /* Strip unnecessary stuff */
+ /DISCARD/ : { *(.comment .note .eh_frame) }
+}
diff --git a/core/arch/arm32/plat-sunxi/link.mk b/core/arch/arm32/plat-sunxi/link.mk
new file mode 100644
index 0000000..3ff1f05
--- /dev/null
+++ b/core/arch/arm32/plat-sunxi/link.mk
@@ -0,0 +1,54 @@
+link-out-dir = $(out-dir)/core
+
+link-script = $(platform-dir)/kern.ld.S
+link-script-pp = $(link-out-dir)/kern.ld
+link-script-dep = $(link-out-dir)/.kern.ld.d
+
+AWK = awk
+
+all: $(link-out-dir)/tee.elf $(link-out-dir)/tee.dmp $(link-out-dir)/tee.bin
+all: $(link-out-dir)/tee.symb_sizes
+cleanfiles += $(link-out-dir)/tee.elf $(link-out-dir)/tee.dmp $(link-out-dir)/tee.map
+cleanfiles += $(link-out-dir)/tee.bin
+cleanfiles += $(link-out-dir)/tee.symb_sizes
+cleanfiles += $(link-script-pp) $(link-script-dep)
+
+link-ldflags = $(LDFLAGS)
+link-ldflags += -T $(link-script-pp) -Map=$(link-out-dir)/tee.map
+link-ldflags += --sort-section=alignment
+
+link-ldadd = $(LDADD)
+link-ldadd += $(addprefix -L,$(libdirs))
+link-ldadd += $(addprefix -l,$(libnames))
+ldargs-tee.elf := $(link-ldflags) $(objs) $(link-ldadd) $(libgcc)
+
+link-script-cppflags := \
+ $(filter-out $(CPPFLAGS_REMOVE) $(cppflags-remove), \
+ $(nostdinc) $(CPPFLAGS) \
+ $(addprefix -I,$(incdirs$(sm))) $(cppflags$(sm)))
+
+
+-include $(link-script-dep)
+
+$(link-script-pp): $(link-script)
+ @echo ' CPP $@'
+ @mkdir -p $(dir $@)
+ $(q)$(CPP) -Wp,-P,-MT,$@,-MD,$(link-script-dep) \
+ $(link-script-cppflags) $< > $@
+
+
+$(link-out-dir)/tee.elf: $(objs) $(libdeps) $(link-script-pp)
+ @echo ' LD $@'
+ $(q)$(LD) $(ldargs-tee.elf) -o $@
+
+$(link-out-dir)/tee.dmp: $(link-out-dir)/tee.elf
+ @echo ' OBJDUMP $@'
+ $(q)$(OBJDUMP) -l -x -d $< > $@
+
+$(link-out-dir)/tee.bin: $(link-out-dir)/tee.elf
+ @echo ' OBJCOPY $@'
+ $(q)$(OBJCOPY) -O binary $< $@
+
+$(link-out-dir)/tee.symb_sizes: $(link-out-dir)/tee.elf
+ @echo ' GEN $@'
+ $(q)$(NM) --print-size --reverse-sort --size-sort $< > $@
diff --git a/core/arch/arm32/plat-sunxi/main.c b/core/arch/arm32/plat-sunxi/main.c
new file mode 100644
index 0000000..5a4f783
--- /dev/null
+++ b/core/arch/arm32/plat-sunxi/main.c
@@ -0,0 +1,413 @@
+/*
+ * Copyright (c) 2014, Allwinner Technology Co., Ltd.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice,
+ * this list of conditions and the following disclaimer.
+ *
+ * 2. 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.
+ *
+ * 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 <platform_config.h>
+
+#include <stdint.h>
+#include <string.h>
+#include <assert.h>
+
+#include <sm/sm.h>
+#include <sm/sm_defs.h>
+#include <sm/tee_mon.h>
+#include <sm/teesmc.h>
+#include <sm/teesmc_optee.h>
+
+#include <arm32.h>
+#include <kernel/arch_debug.h>
+#include <kernel/thread.h>
+#include <kernel/time_source.h>
+#include <kernel/panic.h>
+#include <kernel/misc.h>
+#include <mm/tee_pager.h>
+#include <mm/tee_mmu.h>
+#include <mm/core_mmu.h>
+#include <mm/tee_mmu_defs.h>
+#include <tee/entry.h>
+#include <tee/arch_svc.h>
+#include <platform.h>
+#include <util.h>
+#include <trace.h>
+#include <malloc.h>
+
+#ifdef WITH_STACK_CANARIES
+#define STACK_CANARY_SIZE (4 * sizeof(uint32_t))
+#define START_CANARY_VALUE 0xdededede
+#define END_CANARY_VALUE 0xabababab
+#define GET_START_CANARY(name, stack_num) name[stack_num][0]
+#define GET_END_CANARY(name, stack_num) \
+ name[stack_num][sizeof(name[stack_num]) / sizeof(uint32_t) - 1]
+#else
+#define STACK_CANARY_SIZE 0
+#endif
+
+#define STACK_ALIGNMENT 8
+
+#define DECLARE_STACK(name, num_stacks, stack_size) \
+ static uint32_t name[num_stacks][(stack_size + STACK_CANARY_SIZE) / \
+ sizeof(uint32_t)] \
+ __attribute__((section(".bss.prebss.stack"), \
+ aligned(STACK_ALIGNMENT)))
+
+#define GET_STACK(stack) \
+ ((vaddr_t)(stack) + sizeof(stack) - STACK_CANARY_SIZE / 2)
+
+
+DECLARE_STACK(stack_tmp, CFG_TEE_CORE_NB_CORE, STACK_TMP_SIZE);
+DECLARE_STACK(stack_abt, CFG_TEE_CORE_NB_CORE, STACK_ABT_SIZE);
+DECLARE_STACK(stack_sm, CFG_TEE_CORE_NB_CORE, SM_STACK_SIZE);
+DECLARE_STACK(stack_thread, NUM_THREADS, STACK_THREAD_SIZE);
+
+const vaddr_t stack_tmp_top[CFG_TEE_CORE_NB_CORE] = {
+ GET_STACK(stack_tmp[0]),
+#if CFG_TEE_CORE_NB_CORE > 1
+ GET_STACK(stack_tmp[1]),
+#endif
+#if CFG_TEE_CORE_NB_CORE > 2
+ GET_STACK(stack_tmp[2]),
+#endif
+#if CFG_TEE_CORE_NB_CORE > 3
+ GET_STACK(stack_tmp[3]),
+#endif
+#if CFG_TEE_CORE_NB_CORE > 4
+ GET_STACK(stack_tmp[4]),
+#endif
+#if CFG_TEE_CORE_NB_CORE > 5
+ GET_STACK(stack_tmp[5]),
+#endif
+#if CFG_TEE_CORE_NB_CORE > 6
+ GET_STACK(stack_tmp[6]),
+#endif
+#if CFG_TEE_CORE_NB_CORE > 7
+ GET_STACK(stack_tmp[7]),
+#endif
+#if CFG_TEE_CORE_NB_CORE > 8
+#error "Top of tmp stacks aren't defined for more than 8 CPUS"
+#endif
+};
+
+/* teecore heap address/size is defined in scatter file */
+extern unsigned char teecore_heap_start;
+extern unsigned char teecore_heap_end;
+
+/* Main MMU L1 table for teecore */
+static uint32_t main_mmu_l1_ttb[TEE_MMU_L1_NUM_ENTRIES]
+ __attribute__((section(".nozi.mmu.l1"),
+ aligned(TEE_MMU_L1_ALIGNMENT)));
+
+/* Main MMU L2 table for teecore */
+static uint32_t main_mmu_l2_ttb[TEE_MMU_L2_NUM_ENTRIES]
+ __attribute__((section(".nozi.mmu.l2"),
+ aligned(TEE_MMU_L2_ALIGNMENT)));
+
+/* MMU L1 table for TAs, one for each Core */
+static uint32_t main_mmu_ul1_ttb[NUM_THREADS][TEE_MMU_UL1_NUM_ENTRIES]
+ __attribute__((section(".nozi.mmu.ul1"),
+ aligned(TEE_MMU_UL1_ALIGNMENT)));
+
+static void main_fiq(void);
+static void main_tee_entry(struct thread_smc_args *args);
+static uint32_t main_default_pm_handler(uint32_t a0, uint32_t a1);
+
+static void init_canaries(void)
+{
+ size_t n;
+#define INIT_CANARY(name) \
+ for (n = 0; n < ARRAY_SIZE(name); n++) { \
+ uint32_t *start_canary = &GET_START_CANARY(name, n); \
+ uint32_t *end_canary = &GET_END_CANARY(name, n); \
+ \
+ *start_canary = START_CANARY_VALUE; \
+ *end_canary = END_CANARY_VALUE; \
+ }
+
+ INIT_CANARY(stack_tmp);
+ INIT_CANARY(stack_abt);
+ INIT_CANARY(stack_sm);
+ INIT_CANARY(stack_thread);
+}
+
+void check_canaries(void)
+{
+#ifdef WITH_STACK_CANARIES
+ size_t n;
+
+#define ASSERT_STACK_CANARIES(name) \
+ for (n = 0; n < ARRAY_SIZE(name); n++) { \
+ assert(GET_START_CANARY(name, n) == START_CANARY_VALUE);\
+ assert(GET_END_CANARY(name, n) == END_CANARY_VALUE); \
+ } while (0)
+
+ ASSERT_STACK_CANARIES(stack_tmp);
+ ASSERT_STACK_CANARIES(stack_abt);
+ ASSERT_STACK_CANARIES(stack_sm);
+ ASSERT_STACK_CANARIES(stack_thread);
+#endif /*WITH_STACK_CANARIES*/
+}
+
+static const struct thread_handlers handlers = {
+ .std_smc = main_tee_entry,
+ .fast_smc = main_tee_entry,
+ .fiq = main_fiq,
+ .svc = tee_svc_handler,
+ .abort = tee_pager_abort_handler,
+ .cpu_on = main_default_pm_handler,
+ .cpu_off = main_default_pm_handler,
+ .cpu_suspend = main_default_pm_handler,
+ .cpu_resume = main_default_pm_handler,
+ .system_off = main_default_pm_handler,
+ .system_reset = main_default_pm_handler,
+};
+
+void main_init(uint32_t nsec_entry); /* called from assembly only */
+void main_init(uint32_t nsec_entry)
+{
+ struct sm_nsec_ctx *nsec_ctx;
+ size_t pos = get_core_pos();
+
+ /*
+ * Mask IRQ and FIQ before switch to the thread vector as the
+ * thread handler requires IRQ and FIQ to be masked while executing
+ * with the temporary stack. The thread subsystem also asserts that
+ * IRQ is blocked when using most if its functions.
+ */
+ write_cpsr(read_cpsr() | CPSR_F | CPSR_I);
+
+ if (pos == 0) {
+ size_t n;
+
+ /* Initialize canries around the stacks */
+ init_canaries();
+
+ /* Assign the thread stacks */
+ for (n = 0; n < NUM_THREADS; n++) {
+ if (!thread_init_stack(n, GET_STACK(stack_thread[n])))
+ panic();
+ }
+ thread_init_handlers(&handlers);
+
+ /* initialize platform */
+ platform_init();
+ }
+
+ if (!thread_init_stack(THREAD_TMP_STACK, GET_STACK(stack_tmp[pos])))
+ panic();
+ if (!thread_init_stack(THREAD_ABT_STACK, GET_STACK(stack_abt[pos])))
+ panic();
+
+ thread_init_per_cpu();
+
+ /* Initialize secure monitor */
+ sm_init(GET_STACK(stack_sm[pos]));
+ nsec_ctx = sm_get_nsec_ctx();
+ nsec_ctx->mon_lr = nsec_entry;
+ nsec_ctx->mon_spsr = CPSR_MODE_SVC | CPSR_I;
+ sm_set_entry_vector(thread_vector_table);
+
+ if (pos == 0) {
+ unsigned long a, s;
+ /* core malloc pool init */
+#ifdef CFG_TEE_MALLOC_START
+ a = CFG_TEE_MALLOC_START;
+ s = CFG_TEE_MALLOC_SIZE;
+#else
+ a = (unsigned long)&teecore_heap_start;
+ s = (unsigned long)&teecore_heap_end;
+ a = ((a + 1) & ~0x0FFFF) + 0x10000; /* 64kB aligned */
+ s = s & ~0x0FFFF; /* 64kB aligned */
+ s = s - a;
+#endif
+ malloc_init((void *)a, s);
+
+ teecore_init_ta_ram();
+
+ if (init_teecore() != TEE_SUCCESS) {
+ panic();
+ }
+ }
+
+ IMSG("optee initialize finished\n");
+}
+
+static void main_fiq(void)
+{
+ panic();
+}
+
+static uint32_t main_default_pm_handler(uint32_t a0, uint32_t a1)
+{
+ /*
+ * This function is not supported in this configuration, and
+ * should never be called. Panic to catch unintended calls.
+ */
+ (void)&a0;
+ (void)&a1;
+ panic();
+ return 1;
+}
+
+static void main_tee_entry(struct thread_smc_args *args)
+{
+ /* TODO move to main_init() */
+ if (init_teecore() != TEE_SUCCESS)
+ panic();
+
+ /*
+ * This function first catches platform specific SMC functions
+ * if none matches, the generic tee_entry is called.
+ */
+ if (args->a0 == TEESMC32_OPTEE_FASTCALL_GET_SHM_CONFIG) {
+ args->a0 = TEESMC_RETURN_OK;
+ args->a1 = default_nsec_shm_paddr;
+ args->a2 = default_nsec_shm_size;
+ /* Should this be TEESMC cache attributes instead? */
+ args->a3 = core_mmu_is_shm_cached();
+ return;
+ }
+
+ if (args->a0 == TEESMC32_OPTEE_FASTCALL_L2CC_MUTEX) {
+ switch (args->a1) {
+ case TEESMC_OPTEE_L2CC_MUTEX_GET_ADDR:
+ case TEESMC_OPTEE_L2CC_MUTEX_SET_ADDR:
+ case TEESMC_OPTEE_L2CC_MUTEX_ENABLE:
+ case TEESMC_OPTEE_L2CC_MUTEX_DISABLE:
+ /* A80 platform not support L2CC_MUTEX */
+ args->a0 = TEESMC_RETURN_UNKNOWN_FUNCTION;
+ return;
+ default:
+ args->a0 = TEESMC_RETURN_EBADCMD;
+ return;
+ }
+ }
+
+ /* SiP Service Call Count */
+ if (args->a0 == TEESMC32_SIP_SUNXI_CALLS_COUNT) {
+ args->a0 = 1;
+ return;
+ }
+
+ /* SiP Service Call UID */
+ if (args->a0 == TEESMC32_SIP_SUNXI_CALLS_UID) {
+ args->a0 = TEESMC_SIP_SUNXI_UID_R0;
+ args->a1 = TEESMC_SIP_SUNXI_UID_R1;
+ args->a2 = TEESMC_SIP_SUNXI_UID_R2;
+ args->a3 = TEESMC_SIP_SUNXI_UID_R3;
+ return;
+ }
+
+ /* SiP Service Calls */
+ if (args->a0 == TEESMC32_OPTEE_FAST_CALL_SIP_SUNXI) {
+ platform_smc_handle(args);
+ return;
+ }
+
+ tee_entry(args);
+}
+
+
+/* Override weak function in tee/entry.c */
+void tee_entry_get_api_call_count(struct thread_smc_args *args)
+{
+ args->a0 = tee_entry_generic_get_api_call_count() + 2;
+}
+
+/* Override weak function in tee/entry.c */
+void tee_entry_get_api_uuid(struct thread_smc_args *args)
+{
+ args->a0 = TEESMC_OPTEE_UID_R0;
+ args->a1 = TEESMC_OPTEE_UID_R1;
+ args->a2 = TEESMC_OPTEE_UID_R2;
+ args->a3 = TEESMC_OPTEE_UID32_R3;
+}
+
+/* Override weak function in tee/entry.c */
+void tee_entry_get_api_revision(struct thread_smc_args *args)
+{
+ args->a0 = TEESMC_OPTEE_REVISION_MAJOR;
+ args->a1 = TEESMC_OPTEE_REVISION_MINOR;
+}
+
+/* Override weak function in tee/entry.c */
+void tee_entry_get_os_uuid(struct thread_smc_args *args)
+{
+ args->a0 = TEESMC_OS_OPTEE_UUID_R0;
+ args->a1 = TEESMC_OS_OPTEE_UUID_R1;
+ args->a2 = TEESMC_OS_OPTEE_UUID_R2;
+ args->a3 = TEESMC_OS_OPTEE_UUID_R3;
+}
+
+/* Override weak function in tee/entry.c */
+void tee_entry_get_os_revision(struct thread_smc_args *args)
+{
+ args->a0 = TEESMC_OS_OPTEE_REVISION_MAJOR;
+ args->a1 = TEESMC_OS_OPTEE_REVISION_MINOR;
+}
+
+paddr_t core_mmu_get_main_ttb_pa(void)
+{
+ /* Note that this depends on flat mapping of TEE Core */
+ paddr_t pa = (paddr_t)core_mmu_get_main_ttb_va();
+
+ TEE_ASSERT(!(pa & ~TEE_MMU_TTB_L1_MASK));
+ return pa;
+}
+
+vaddr_t core_mmu_get_main_ttb_va(void)
+{
+ return (vaddr_t)main_mmu_l1_ttb;
+}
+
+paddr_t core_mmu_get_ul1_ttb_pa(void)
+{
+ /* Note that this depends on flat mapping of TEE Core */
+ paddr_t pa = (paddr_t)core_mmu_get_ul1_ttb_va();
+
+ TEE_ASSERT(!(pa & ~TEE_MMU_TTB_UL1_MASK));
+ return pa;
+}
+
+vaddr_t core_mmu_get_ul1_ttb_va(void)
+{
+ return (vaddr_t)main_mmu_ul1_ttb[thread_get_id()];
+}
+
+void *core_mmu_alloc_l2(struct map_area *map)
+{
+ /* Can't have this in .bss since it's not initialized yet */
+ static size_t l2_offs __attribute__((section(".data")));
+ size_t l2_va_space = ((sizeof(main_mmu_l2_ttb) - l2_offs) /
+ TEE_MMU_L2_SIZE) * SECTION_SIZE;
+
+ if (l2_offs)
+ return NULL;
+ if (map->type != MEM_AREA_TEE_RAM)
+ return NULL;
+ if (map->size > l2_va_space)
+ return NULL;
+ l2_offs += ROUNDUP(map->size, SECTION_SIZE) / SECTION_SIZE;
+ return main_mmu_l2_ttb;
+}
diff --git a/core/arch/arm32/plat-sunxi/platform.c b/core/arch/arm32/plat-sunxi/platform.c
new file mode 100644
index 0000000..576d9a5
--- /dev/null
+++ b/core/arch/arm32/plat-sunxi/platform.c
@@ -0,0 +1,106 @@
+/*
+ * Copyright (c) 2014, Allwinner Technology Co., Ltd.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice,
+ * this list of conditions and the following disclaimer.
+ *
+ * 2. 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.
+ *
+ * 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 <platform_config.h>
+
+#include <sm/sm.h>
+#include <sm/sm_defs.h>
+#include <sm/tee_mon.h>
+#include <sm/teesmc.h>
+#include <sm/teesmc_optee.h>
+
+#include <arm32.h>
+#include <kernel/thread.h>
+#include <kernel/time_source.h>
+#include <kernel/panic.h>
+#include <kernel/misc.h>
+#include <mm/tee_pager.h>
+#include <mm/core_mmu.h>
+#include <tee/entry.h>
+
+#include <drivers/gic.h>
+#include <drivers/sunxi_uart.h>
+
+#include <trace.h>
+#include <io.h>
+#include <assert.h>
+#include <util.h>
+#include <platform.h>
+
+void sunxi_secondary_entry(void);
+
+uint32_t sunxi_secondary_ns_entry;
+
+static int platform_smp_init(void)
+{
+ write32((uint32_t)sunxi_secondary_entry, (PRCM_BASE + PRCM_CPU_SOFT_ENTRY_REG));
+
+ return 0;
+}
+
+void platform_init(void)
+{
+ /*
+ * GIC configuration is initialized in Secure bootloader,
+ * Initialize GIC base address here for debugging.
+ */
+ gic_init_base_addr(GIC_BASE + GICC_OFFSET, GIC_BASE + GICD_OFFSET);
+
+ /* platform smp initialize */
+ platform_smp_init();
+
+ /* enable non-secure access cci-400 registers */
+ write32(0x1, CCI400_BASE + CCI400_SECURE_ACCESS_REG);
+
+ /* Initialize uart with physical address */
+ sunxi_uart_init(UART0_BASE);
+
+ return ;
+}
+
+/**
+ * handle platform special smc commands.
+ */
+uint32_t platform_smc_handle(struct thread_smc_args *smc_args)
+{
+ uint32_t ret = TEE_SUCCESS;
+ switch (smc_args->a1) {
+ case TEESMC_OPTEE_SIP_SUNXI_SET_SMP_BOOTENTRY:
+ sunxi_secondary_ns_entry = smc_args->a2;
+
+ /* in order to sync with secondary up cpu */
+ cache_maintenance_l1(DCACHE_AREA_CLEAN,
+ (void *)(&sunxi_secondary_ns_entry),
+ sizeof(uint32_t));
+ break;
+ default:
+ ret = TEESMC_RETURN_EBADCMD;
+ break;
+ }
+ smc_args->a0 = ret;
+ return ret;
+}
+
diff --git a/core/arch/arm32/plat-sunxi/platform.h b/core/arch/arm32/plat-sunxi/platform.h
new file mode 100644
index 0000000..962317f
--- /dev/null
+++ b/core/arch/arm32/plat-sunxi/platform.h
@@ -0,0 +1,84 @@
+/*
+ * Copyright (c) 2014, Allwinner Technology Co., Ltd.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice,
+ * this list of conditions and the following disclaimer.
+ *
+ * 2. 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.
+ *
+ * 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 PLATFORM_H
+#define PLATFORM_H
+
+/*
+ * Function specified by SMC Calling convention.
+ *
+ * SiP Service Calls
+ *
+ * Call register usage:
+ * r0 SMC Function ID, TEESMC_OPTEE_FUNCID_SIP_SUNXI
+ * r1 TEESMC_OPTEE_SIP_SUNXI_SET_SMP_BOOTENTRY set smp bootup entry
+ */
+#define TEESMC_OPTEE_SIP_SUNXI_SET_SMP_BOOTENTRY (0xFFFF0000)
+
+#define TEESMC_OPTEE_FUNCID_SIP_SUNXI 0x8000
+#define TEESMC32_OPTEE_FAST_CALL_SIP_SUNXI \
+ TEESMC_CALL_VAL(TEESMC_32, TEESMC_FAST_CALL, TEESMC_OWNER_SIP, \
+ TEESMC_OPTEE_FUNCID_SIP_SUNXI)
+
+
+/*
+ * Function specified by SMC Calling convention.
+ *
+ * SiP Service Call Count
+ *
+ * This call returns a 32-bit count of the available
+ * Service Calls. A return value of zero means no
+ * services are available.
+ */
+#define TEESMC32_FUNCID_SIP_CALLS_COUNT 0xFF00
+#define TEESMC32_SIP_SUNXI_CALLS_COUNT \
+ TEESMC_CALL_VAL(TEESMC_32, TEESMC_FAST_CALL, \
+ TEESMC_OWNER_SIP, \
+ TEESMC32_FUNCID_CALLS_COUNT)
+
+/*
+ * Function specified by SMC Calling convention
+ *
+ * SiP Service Call UID
+ *
+ * Return the implementation of SiP Service Calls UID.
+ *
+ */
+#define TEESMC_SIP_SUNXI_UID_R0 0xa5d5c51b
+#define TEESMC_SIP_SUNXI_UID_R1 0x8d6c0002
+#define TEESMC_SIP_SUNXI_UID_R2 0x6f8611e4
+#define TEESMC_SIP_SUNXI_UID_R3 0x12b7e560
+#define TEESMC32_FUNCID_SIP_SUNXI_CALLS_UID 0xFF01
+#define TEESMC32_SIP_SUNXI_CALLS_UID \
+ TEESMC_CALL_VAL(TEESMC_32, TEESMC_FAST_CALL, \
+ TEESMC_OWNER_SIP, \
+ TEESMC32_FUNCID_SIP_SUNXI_CALLS_UID)
+
+void platform_init(void);
+uint32_t platform_smc_handle(struct thread_smc_args *smc_args);
+
+#endif /*PLATFORM_H*/
diff --git a/core/arch/arm32/plat-sunxi/platform_config.h b/core/arch/arm32/plat-sunxi/platform_config.h
new file mode 100644
index 0000000..ae98a42
--- /dev/null
+++ b/core/arch/arm32/plat-sunxi/platform_config.h
@@ -0,0 +1,84 @@
+/*
+ * Copyright (c) 2014, Allwinner Technology Co., Ltd.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice,
+ * this list of conditions and the following disclaimer.
+ *
+ * 2. 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.
+ *
+ * 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 PLATFORM_CONFIG_H
+#define PLATFORM_CONFIG_H
+
+#define STACK_ALIGNMENT 8
+
+#define PLATFORM_LINKER_FORMAT "elf32-littlearm"
+#define PLATFORM_LINKER_ARCH arm
+
+#define GIC_BASE 0x01c40000
+#define GICC_OFFSET 0x2000
+#define GICD_OFFSET 0x1000
+#define UART0_BASE 0x07000000
+#define UART1_BASE 0x07000400
+#define UART2_BASE 0x07000800
+#define UART3_BASE 0x07000c00
+#define CCI400_BASE 0x01c90000
+#define SMC_BASE 0x01c0b000
+#define PRCM_BASE 0x08001400
+
+/* CCI-400 register defines */
+#define CCI400_SECURE_ACCESS_REG (0x8)
+
+/* PRCM register defines */
+#define PRCM_CPU_SOFT_ENTRY_REG (0x164)
+
+/* console uart define */
+#define CONSOLE_UART_BASE UART0_BASE
+
+#define STACK_TMP_SIZE 1024
+#define STACK_ABT_SIZE 1024
+#define STACK_THREAD_SIZE 8192
+
+#define DRAM0_BASE 0x20000000
+#define DRAM0_SIZE 0x80000000
+
+/* Location of trusted dram on sunxi */
+#define TZDRAM_BASE 0x9C000000
+#define TZDRAM_SIZE 0x04000000
+
+#define CFG_TEE_CORE_NB_CORE 8
+
+#define DDR_PHYS_START DRAM0_BASE
+#define DDR_SIZE DRAM0_SIZE
+
+#define CFG_DDR_START DDR_PHYS_START
+#define CFG_DDR_SIZE DDR_SIZE
+
+#define CFG_DDR_TEETZ_RESERVED_START TZDRAM_BASE
+#define CFG_DDR_TEETZ_RESERVED_SIZE TZDRAM_SIZE
+
+#define TEE_RAM_START (TZDRAM_BASE)
+#define TEE_RAM_SIZE (1 * 1024 * 1024)
+
+#define CFG_SHMEM_START (DDR_PHYS_START + 0x1000000)
+#define CFG_SHMEM_SIZE 0x100000
+
+#endif /*PLATFORM_CONFIG_H*/
diff --git a/core/arch/arm32/plat-sunxi/platform_flags.mk b/core/arch/arm32/plat-sunxi/platform_flags.mk
new file mode 100644
index 0000000..68945ee
--- /dev/null
+++ b/core/arch/arm32/plat-sunxi/platform_flags.mk
@@ -0,0 +1,24 @@
+platform-cpuarch = cortex-a15
+platform-cflags = -mcpu=$(platform-cpuarch) -mthumb
+platform-cflags += -pipe -mthumb-interwork -mlong-calls
+platform-cflags += -fno-short-enums -mno-apcs-float -fno-common
+platform-cflags += -mfloat-abi=soft
+platform-cflags += -mno-unaligned-access
+platform-aflags = -mcpu=$(platform-cpuarch)
+
+platform-cflags += -ffunction-sections -fdata-sections
+
+DEBUG ?= 1
+ifeq ($(DEBUG),1)
+platform-cflags += -O0
+else
+platform-cflags += -Os
+endif
+
+platform-cflags += -g
+platform-aflags += -g
+
+platform-cflags += -g3
+platform-aflags += -g3
+
+user_ta-platform-cflags = -fpie
diff --git a/core/arch/arm32/plat-sunxi/rng_support.c b/core/arch/arm32/plat-sunxi/rng_support.c
new file mode 100644
index 0000000..434b104
--- /dev/null
+++ b/core/arch/arm32/plat-sunxi/rng_support.c
@@ -0,0 +1,43 @@
+/*
+ * Copyright (c) 2014, Allwinner Technology Co., Ltd.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice,
+ * this list of conditions and the following disclaimer.
+ *
+ * 2. 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.
+ *
+ * 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 <stdlib.h>
+#include <rng_support.h>
+#include <trace.h>
+
+/* Bad software version */
+uint8_t hw_get_random_byte(void)
+{
+ static uint32_t lcg_state;
+ static uint32_t nb_soft = 9876543;
+#define MAX_SOFT_RNG 1024
+ static const uint32_t a = 1664525;
+ static const uint32_t c = 1013904223;
+
+ nb_soft = (nb_soft + 1) % MAX_SOFT_RNG;
+ lcg_state = (a * lcg_state + c);
+ return (uint8_t) (lcg_state >> 24);
+}
diff --git a/core/arch/arm32/plat-sunxi/smp_boot.S b/core/arch/arm32/plat-sunxi/smp_boot.S
new file mode 100644
index 0000000..4d04a04
--- /dev/null
+++ b/core/arch/arm32/plat-sunxi/smp_boot.S
@@ -0,0 +1,96 @@
+/*
+ * Copyright (c) 2014, Allwinner Technology Co., Ltd.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice,
+ * this list of conditions and the following disclaimer.
+ *
+ * 2. 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.
+ *
+ * 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 <asm.S>
+#include <arm32.h>
+#include <arm32_macros.S>
+#include <sm/teesmc.h>
+#include <sm/teesmc_opteed_macros.h>
+#include <sm/teesmc_opteed.h>
+
+FUNC smp_init_vector , :
+ b . /* Reset */
+ b . /* Undef */
+ b . /* Syscall */
+ b . /* Prefetch abort */
+ b . /* Data abort */
+ b . /* Reserved */
+ b . /* IRQ */
+ b . /* FIQ */
+END_FUNC smp_init_vector
+
+FUNC sunxi_secondary_entry , :
+ /* secondary CPUs internal initialization */
+ read_sctlr r0
+ orr r0, r0, #SCTLR_A
+ write_sctlr r0
+
+ /* install smp initialization vector */
+ ldr r0, =smp_init_vector
+ write_vbar r0
+
+ /* Setup tmp stack */
+ bl get_core_pos
+ lsl r0, #2
+ ldr r1, =stack_tmp_top
+ ldr sp, [r1, r0]
+
+ /* NSACR configuration */
+ read_nsacr r1
+ orr r1, r1, #NSACR_CP10
+ orr r1, r1, #NSACR_CP11
+ orr r1, r1, #NSACR_NS_SMP
+ write_nsacr r1
+ mcr p15, 0, r1, c1, c1, 2
+
+ /* Enable SMP bit */
+ read_actlr r0
+ orr r0, r0, #ACTLR_SMP
+ write_actlr r0
+
+ /* fixup some platform limits */
+ bl sunxi_secondary_fixup
+
+ /* initialize gic cpu interface */
+ bl gic_cpu_init
+
+ /* secure env initialization */
+ bl core_init_mmu_regs
+ bl cpu_mmu_enable
+ bl cpu_mmu_enable_icache
+ bl cpu_mmu_enable_dcache
+
+ /* Initialize thread handling and secure monitor */
+ ldr r0, =sunxi_secondary_ns_entry
+ ldr r0, [r0]
+ bl main_init
+
+ mov r0, #TEESMC_OPTEED_RETURN_ENTRY_DONE
+ smc #0
+ b . /* SMC should not return */
+
+END_FUNC sunxi_secondary_entry
diff --git a/core/arch/arm32/plat-sunxi/smp_fixup.S b/core/arch/arm32/plat-sunxi/smp_fixup.S
new file mode 100644
index 0000000..18701cc
--- /dev/null
+++ b/core/arch/arm32/plat-sunxi/smp_fixup.S
@@ -0,0 +1,111 @@
+/*
+ * Copyright (c) 2014, Allwinner Technology Co., Ltd.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice,
+ * this list of conditions and the following disclaimer.
+ *
+ * 2. 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.
+ *
+ * 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.
+ */
+#define SLAVE_SNOOPCTL_OFFSET 0
+#define SNOOPCTL_SNOOP_ENABLE (1 << 0)
+#define SNOOPCTL_DVM_ENABLE (1 << 1)
+
+#define CCI_STATUS_OFFSET 0xc
+#define STATUS_CHANGE_PENDING (1 << 0)
+
+#define CCI_SLAVE_OFFSET(n) (0x1000 + 0x1000 * (n))
+
+#define SUNXI_CCI_PHYS_BASE 0x01c90000
+#define SUNXI_CCI_SLAVE_A7 3
+#define SUNXI_CCI_SLAVE_A15 4
+#define SUNXI_CCI_A15_OFFSET CCI_SLAVE_OFFSET(SUNXI_CCI_SLAVE_A15)
+#define SUNXI_CCI_A7_OFFSET CCI_SLAVE_OFFSET(SUNXI_CCI_SLAVE_A7)
+
+#define SUNXI_CCU_PHYS_BASE (0x06000000)
+#define SUNXI_CCU_C0_CFG_OFFSET (0x54)
+#define SUNXI_CCU_C1_CFG_OFFSET (0x58)
+
+.globl sunxi_secondary_fixup
+sunxi_secondary_fixup:
+ mrc p15, 0, r0, c0, c0, 5 /* MPIDR */
+ ubfx r0, r0, #8, #4 /* cluster */
+
+ ldr r3, =SUNXI_CCU_PHYS_BASE + SUNXI_CCU_C0_CFG_OFFSET
+ cmp r0, #0 /* A7 cluster? */
+ addne r3, r3, #SUNXI_CCU_C1_CFG_OFFSET - SUNXI_CCU_C0_CFG_OFFSET
+ ldr r1, [r3]
+ bic r1, r1, #(0x3<<8) /* a15 atb div */
+ orr r1, r1, #(0x1<<8) /* div = 2 */
+ bic r1, r1, #(0x7<<0) /* a15 atb div */
+ orr r1, r1, #(0x2<<0) /* div = value + 1 */
+ str r1, [r3] /* set atb div to 2, axi div to 3 */
+ dsb /* Synchronise side-effects of axi config */
+ ldr r1, [r3]
+ bic r1, r1, #(0x3<<8) /* a15 atb div */
+ orr r1, r1, #(0x2<<8) /* div = 4 */
+ bic r1, r1, #(0x7<<0) /* a15 atb div */
+ orr r1, r1, #(0x3<<0) /* div = value + 1 */
+ str r1, [r3] /* set atb div to 4, axi div to 4 */
+ dsb /* Synchronise side-effects of axi config */
+
+ /* Enable CCI snoops. */
+ ldr r3, =SUNXI_CCI_PHYS_BASE + SUNXI_CCI_A7_OFFSET
+ cmp r0, #0 /* A7 cluster? */
+ addne r3, r3, #SUNXI_CCI_A15_OFFSET - SUNXI_CCI_A7_OFFSET
+
+ @ r3 now points to the correct CCI slave register block
+ ldr r1, [r3, #SLAVE_SNOOPCTL_OFFSET]
+ orr r1, r1, #SNOOPCTL_SNOOP_ENABLE
+ orr r1, r1, #SNOOPCTL_DVM_ENABLE
+ str r1, [r3, #SLAVE_SNOOPCTL_OFFSET] /* enable CCI snoops */
+
+ /* Wait for snoop control change to complete */
+ ldr r3, =SUNXI_CCI_PHYS_BASE
+1:
+ ldr r1, [r3, #CCI_STATUS_OFFSET]
+ tst r1, #STATUS_CHANGE_PENDING
+ bne 1b
+ dsb /* Synchronise side-effects of enabling CCI */
+
+ cmp r0, #1 /* A15 cluster ? */
+ bne 2f
+
+ /* a80 platform-specific Cortex-A15 setup */
+ mrc p15, 1, r1, c15, c0, 4 /* ACTLR2 */
+ orr r1, r1, #(0x1<<31) /* Enable CPU regional clock gates */
+ mcr p15, 1, r1, c15, c0, 4
+
+ mrc p15, 1, r1, c15, c0, 0 /* L2ACTLR */
+ orr r1, r1, #(0x1<<26) /* Enables L2, GIC, and Timer regional clock gates */
+ mcr p15, 1, r1, c15, c0, 0
+
+ mrc p15, 1, r1, c15, c0, 0 /* L2ACTLR */
+ orr r1, r1, #(0x1<<3) /* Disables clean/evict from being pushed to external */
+ mcr p15, 1, r1, c15, c0, 0
+
+ mrc p15, 1, r1, c9, c0, 2
+ bic r1, r1, #(0x7<<0) /* L2 data ram latency */
+ orr r1, r1, #(0x3<<0)
+ mcr p15, 1, r1, c9, c0, 2
+
+2:
+ /* a80 platform-specific operations porcess done. */
+ bx lr
diff --git a/core/arch/arm32/plat-sunxi/sub.mk b/core/arch/arm32/plat-sunxi/sub.mk
new file mode 100644
index 0000000..b36e4bd
--- /dev/null
+++ b/core/arch/arm32/plat-sunxi/sub.mk
@@ -0,0 +1,15 @@
+global-incdirs-y += .
+srcs-y += entry.S
+srcs-y += main.c
+
+srcs-y += tee_common_otp.c
+cflags-tee_common_otp.c-y += -Wno-unused-parameter
+
+srcs-y += core_bootcfg.c
+srcs-y += core_chip.c
+srcs-y += rng_support.c
+srcs-y += platform.c
+srcs-y += smp_boot.S
+srcs-y += smp_fixup.S
+srcs-y += head.c
+srcs-y += console.c
diff --git a/core/arch/arm32/plat-sunxi/tee_common_otp.c b/core/arch/arm32/plat-sunxi/tee_common_otp.c
new file mode 100644
index 0000000..b281b8e
--- /dev/null
+++ b/core/arch/arm32/plat-sunxi/tee_common_otp.c
@@ -0,0 +1,64 @@
+/*
+ * Copyright (c) 2014 Allwinner Technology Co., Ltd.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice,
+ * this list of conditions and the following disclaimer.
+ *
+ * 2. 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.
+ *
+ * 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 <stddef.h>
+#include <string.h>
+#include <trace.h>
+#include <kernel/tee_common_otp.h>
+
+#define SHA256_HASH_SIZE 32
+uint8_t hw_key_digest[SHA256_HASH_SIZE];
+
+/*---------------------------------------------------------------------------*/
+/* tee_otp_get_hw_unique_key */
+/*---------------------------------------------------------------------------*/
+/*
+ This function reads out a hw unique key.
+
+ \param[in] hwkey data place holder for the key data read
+ \param[out] None.
+ \return None.
+
+ */
+/*---------------------------------------------------------------------------*/
+void tee_otp_get_hw_unique_key(struct tee_hw_unique_key *hwkey)
+{
+ /* Copy the first part of the new hw key */
+ memcpy(&hwkey->data[0], &hw_key_digest[0],
+ sizeof(struct tee_hw_unique_key));
+}
+
+int tee_otp_get_die_id(uint8_t *buffer, size_t len)
+{
+ size_t i;
+
+ char pattern[4] = { 'B', 'E', 'E', 'F' };
+ for (i = 0; i < len; i++)
+ buffer[i] = pattern[i % 4];
+
+ return 0;
+}
diff --git a/core/drivers/sub.mk b/core/drivers/sub.mk
index 435b29c..c16f9d3 100644
--- a/core/drivers/sub.mk
+++ b/core/drivers/sub.mk
@@ -1,2 +1,3 @@
srcs-$(WITH_UART_DRV) += uart.c
srcs-$(WITH_GIC_DRV) += gic.c
+srcs-$(WITH_SUNXI_UART) += sunxi_uart.c
diff --git a/core/drivers/sunxi_uart.c b/core/drivers/sunxi_uart.c
new file mode 100644
index 0000000..6f45bd0
--- /dev/null
+++ b/core/drivers/sunxi_uart.c
@@ -0,0 +1,99 @@
+/*
+ * Copyright (c) 2014, Allwinner Technology Co., Ltd.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice,
+ * this list of conditions and the following disclaimer.
+ *
+ * 2. 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.
+ *
+ * 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 <platform_config.h>
+
+#include <drivers/sunxi_uart.h>
+#include <console.h>
+#include <io.h>
+#include <assert.h>
+#include <compiler.h>
+
+/* uart register defines */
+#define UART_REG_RBR (0x00)
+#define UART_REG_THR (0x00)
+#define UART_REG_DLL (0x00)
+#define UART_REG_DLH (0x04)
+#define UART_REG_IER (0x04)
+#define UART_REG_IIR (0x08)
+#define UART_REG_FCR (0x08)
+#define UART_REG_LCR (0x0c)
+#define UART_REG_MCR (0x10)
+#define UART_REG_LSR (0x14)
+#define UART_REG_MSR (0x18)
+#define UART_REG_SCH (0x1c)
+#define UART_REG_USR (0x7c)
+#define UART_REG_TFL (0x80)
+#define UART_REG_RFL (0x84)
+#define UART_REG_HALT (0xa4)
+
+/* uart status register bits */
+#define UART_REG_USR_BUSY (0x1 << 0x0)
+#define UART_REG_USR_TFNF (0x1 << 0x1)
+#define UART_REG_USR_TFE (0x1 << 0x2)
+#define UART_REG_USR_RFNE (0x1 << 0x3)
+#define UART_REG_USR_RFF (0x1 << 0x4)
+
+void sunxi_uart_init(vaddr_t __unused base)
+{
+ /* do nothing, debug uart(uart0) share with normal world,
+ * everything for uart0 is ready now.
+ */
+}
+
+void sunxi_uart_flush_tx_fifo(vaddr_t base)
+{
+ while (read32(base + UART_REG_TFL)) {
+ /* waiting transmit fifo empty */
+ ;
+ }
+}
+
+bool sunxi_uart_have_rx_data(vaddr_t base)
+{
+ return read32(base + UART_REG_RFL);
+}
+
+void sunxi_uart_putc(int ch, vaddr_t base)
+{
+ while (!(read32(base + UART_REG_USR) & UART_REG_USR_TFNF)) {
+ /* transmit fifo is full, waiting again. */
+ ;
+ }
+
+ /* write out charset to transmit fifo */
+ write8(ch, base + UART_REG_THR);
+}
+
+int sunxi_uart_getchar(vaddr_t base)
+{
+ while (!sunxi_uart_have_rx_data(base)) {
+ /* transmit fifo is empty, waiting again. */
+ ;
+ }
+ return read32(base + UART_REG_RBR) & 0xff;
+}
+
diff --git a/core/include/drivers/sunxi_uart.h b/core/include/drivers/sunxi_uart.h
new file mode 100644
index 0000000..36091a7
--- /dev/null
+++ b/core/include/drivers/sunxi_uart.h
@@ -0,0 +1,43 @@
+/*
+ * Copyright (c) 2014, Linaro Limited
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice,
+ * this list of conditions and the following disclaimer.
+ *
+ * 2. 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.
+ *
+ * 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 SUNXI_UART_H
+#define SUNXI_UART_H
+
+#include <types_ext.h>
+
+void sunxi_uart_init(vaddr_t base);
+
+void sunxi_uart_putc(int ch, vaddr_t base);
+
+void sunxi_uart_flush_tx_fifo(vaddr_t base);
+
+bool sunxi_uart_have_rx_data(vaddr_t base);
+
+int sunxi_uart_getchar(vaddr_t base);
+
+#endif /*SUNXI_UART_H*/
+