summaryrefslogtreecommitdiff
path: root/core
diff options
context:
space:
mode:
Diffstat (limited to 'core')
-rw-r--r--core/arch/arm/include/kernel/mutex.h11
-rw-r--r--core/arch/arm/include/kernel/pseudo_ta.h4
-rw-r--r--core/arch/arm/include/kernel/spinlock.h6
-rw-r--r--core/arch/arm/include/kernel/thread.h64
-rw-r--r--core/arch/arm/include/kernel/thread_defs.h4
-rw-r--r--core/arch/arm/include/kernel/wait_queue.h3
-rw-r--r--core/arch/arm/include/mm/core_memprot.h17
-rw-r--r--core/arch/arm/include/mm/core_mmu.h68
-rw-r--r--core/arch/arm/include/mm/mobj.h5
-rw-r--r--core/arch/arm/include/sm/optee_smc.h12
-rw-r--r--core/arch/arm/include/sm/sm.h14
-rw-r--r--core/arch/arm/kernel/elf_common.h1
-rw-r--r--core/arch/arm/kernel/elf_load.c33
-rw-r--r--core/arch/arm/kernel/generic_boot.c17
-rw-r--r--core/arch/arm/kernel/generic_entry_a32.S18
-rw-r--r--core/arch/arm/kernel/kern.ld.S8
-rw-r--r--core/arch/arm/kernel/mutex.c7
-rw-r--r--core/arch/arm/kernel/pseudo_ta.c45
-rw-r--r--core/arch/arm/kernel/spin_lock_debug.c5
-rw-r--r--core/arch/arm/kernel/tee_time_arm_cntpct.c2
-rw-r--r--core/arch/arm/kernel/thread.c108
-rw-r--r--core/arch/arm/kernel/thread_a32.S8
-rw-r--r--core/arch/arm/kernel/thread_a64.S14
-rw-r--r--core/arch/arm/kernel/trace_ext.c19
-rw-r--r--core/arch/arm/kernel/user_ta.c14
-rw-r--r--core/arch/arm/kernel/wait_queue.c16
-rw-r--r--core/arch/arm/mm/core_mmu.c152
-rw-r--r--core/arch/arm/mm/core_mmu_lpae.c2
-rw-r--r--core/arch/arm/mm/mobj.c27
-rw-r--r--core/arch/arm/mm/tee_pager.c15
-rw-r--r--core/arch/arm/plat-d02/main.c35
-rw-r--r--core/arch/arm/plat-hikey/main.c34
-rw-r--r--core/arch/arm/plat-imx/a9_plat_init.S6
-rw-r--r--core/arch/arm/plat-imx/conf.mk4
-rw-r--r--core/arch/arm/plat-imx/main.c51
-rw-r--r--core/arch/arm/plat-imx/platform_config.h29
-rw-r--r--core/arch/arm/plat-imx/psci.c3
-rw-r--r--core/arch/arm/plat-imx/sub.mk1
-rw-r--r--core/arch/arm/plat-ls/main.c35
-rw-r--r--core/arch/arm/plat-ls/plat_init.S15
-rw-r--r--core/arch/arm/plat-mediatek/main.c35
-rw-r--r--core/arch/arm/plat-rcar/main.c31
-rw-r--r--core/arch/arm/plat-rpi3/conf.mk1
-rw-r--r--core/arch/arm/plat-rpi3/main.c37
-rw-r--r--core/arch/arm/plat-sprd/console.c24
-rw-r--r--core/arch/arm/plat-sprd/main.c2
-rw-r--r--core/arch/arm/plat-stm/asc.S108
-rw-r--r--core/arch/arm/plat-stm/conf.mk1
-rw-r--r--core/arch/arm/plat-stm/main.c34
-rw-r--r--core/arch/arm/plat-stm/platform_config.h31
-rw-r--r--core/arch/arm/plat-stm/sub.mk1
-rw-r--r--core/arch/arm/plat-stm/tz_a9init.S12
-rw-r--r--core/arch/arm/plat-sunxi/main.c56
-rw-r--r--core/arch/arm/plat-sunxi/platform.c8
-rw-r--r--core/arch/arm/plat-sunxi/sub.mk1
-rw-r--r--core/arch/arm/plat-ti/api_monitor_index.h54
-rw-r--r--core/arch/arm/plat-ti/conf.mk1
-rw-r--r--core/arch/arm/plat-ti/main.c19
-rw-r--r--core/arch/arm/plat-ti/platform_config.h25
-rw-r--r--core/arch/arm/plat-ti/sm_platform_handler.c57
-rw-r--r--core/arch/arm/plat-ti/sub.mk2
-rw-r--r--core/arch/arm/plat-vexpress/conf.mk1
-rw-r--r--core/arch/arm/plat-vexpress/main.c39
-rw-r--r--core/arch/arm/plat-vexpress/platform_config.h49
-rw-r--r--core/arch/arm/plat-zynq7k/main.c30
-rw-r--r--core/arch/arm/plat-zynq7k/plat_init.S12
-rw-r--r--core/arch/arm/plat-zynqmp/conf.mk1
-rw-r--r--core/arch/arm/plat-zynqmp/main.c33
-rw-r--r--core/arch/arm/pta/core_fs_htree_tests.c456
-rw-r--r--core/arch/arm/pta/core_self_tests.h3
-rw-r--r--core/arch/arm/pta/interrupt_tests.c2
-rw-r--r--core/arch/arm/pta/pta_invoke_tests.c (renamed from core/arch/arm/pta/pta_self_tests.c)152
-rw-r--r--core/arch/arm/pta/sub.mk9
-rw-r--r--core/arch/arm/pta/tee_fs_key_manager_tests.c375
-rw-r--r--core/arch/arm/sm/psci.c2
-rw-r--r--core/arch/arm/sm/sm.c3
-rw-r--r--core/arch/arm/tee/arch_svc.c6
-rw-r--r--core/arch/arm/tee/cache.c79
-rw-r--r--core/arch/arm/tee/entry_fast.c26
-rw-r--r--core/arch/arm/tee/entry_std.c62
-rw-r--r--core/arch/arm/tee/pta_socket.c32
-rw-r--r--core/arch/arm/tee/sub.mk1
-rw-r--r--core/arch/arm/tee/svc_cache.c83
-rw-r--r--core/drivers/cdns_uart.c79
-rw-r--r--core/drivers/hi16xx_uart.c82
-rw-r--r--core/drivers/imx_uart.c51
-rw-r--r--core/drivers/ns16550.c38
-rw-r--r--core/drivers/pl011.c83
-rw-r--r--core/drivers/pl050.c4
-rw-r--r--core/drivers/scif.c44
-rw-r--r--core/drivers/serial8250_uart.c73
-rw-r--r--core/drivers/sprd_uart.c59
-rw-r--r--core/drivers/stih_asc.c (renamed from core/arch/arm/plat-ti/console.c)60
-rw-r--r--core/drivers/sub.mk1
-rw-r--r--core/drivers/sunxi_uart.c60
-rw-r--r--core/include/console.h3
-rw-r--r--core/include/drivers/cdns_uart.h16
-rw-r--r--core/include/drivers/hi16xx_uart.h16
-rw-r--r--core/include/drivers/imx_uart.h15
-rw-r--r--core/include/drivers/ns16550.h8
-rw-r--r--core/include/drivers/pl011.h16
-rw-r--r--core/include/drivers/scif.h11
-rw-r--r--core/include/drivers/serial.h27
-rw-r--r--core/include/drivers/serial8250_uart.h16
-rw-r--r--core/include/drivers/sprd_uart.h11
-rw-r--r--core/include/drivers/stih_asc.h (renamed from core/include/tee/tee_fs_defs.h)45
-rw-r--r--core/include/drivers/sunxi_uart.h14
-rw-r--r--core/include/io.h6
-rw-r--r--core/include/tee/cache.h (renamed from core/arch/arm/plat-stm/asc.h)13
-rw-r--r--core/include/tee/fs_htree.h186
-rw-r--r--core/include/tee/svc_cache.h (renamed from core/arch/arm/tee/svc_cache.h)0
-rw-r--r--core/include/tee/tee_cryp_utl.h5
-rw-r--r--core/include/tee/tee_fs.h23
-rw-r--r--core/include/tee/tee_fs_key_manager.h53
-rw-r--r--core/include/tee/tee_fs_rpc.h12
-rw-r--r--core/include/tee/tee_obj.h2
-rw-r--r--core/include/tee/tee_pobj.h4
-rw-r--r--core/include/tee/tee_svc_storage.h10
-rw-r--r--core/kernel/console.c (renamed from core/arch/arm/plat-sunxi/console.c)39
-rw-r--r--core/kernel/sub.mk1
-rw-r--r--core/kernel/tee_ta_manager.c59
-rw-r--r--core/lib/libtomcrypt/src/tee_ltc_provider.c2
-rw-r--r--core/tee/fs_htree.c937
-rw-r--r--core/tee/sub.mk2
-rw-r--r--core/tee/tee_cryp_utl.c7
-rw-r--r--core/tee/tee_fs_key_manager.c232
-rw-r--r--core/tee/tee_fs_rpc.c95
-rw-r--r--core/tee/tee_obj.c17
-rw-r--r--core/tee/tee_pobj.c14
-rw-r--r--core/tee/tee_ree_fs.c706
-rw-r--r--core/tee/tee_rpmb_fs.c205
-rw-r--r--core/tee/tee_sql_fs.c419
-rw-r--r--core/tee/tee_svc_storage.c346
133 files changed, 4092 insertions, 3063 deletions
diff --git a/core/arch/arm/include/kernel/mutex.h b/core/arch/arm/include/kernel/mutex.h
index 1698b35..893313e 100644
--- a/core/arch/arm/include/kernel/mutex.h
+++ b/core/arch/arm/include/kernel/mutex.h
@@ -36,6 +36,15 @@ enum mutex_value {
MUTEX_VALUE_LOCKED,
};
+/*
+ * Positive owner ids signifies actual threads, negative ids has special
+ * meanings according to the defines below. Note that only the first of the
+ * defines is allowed in struct mutex::owener_id.
+ */
+#define MUTEX_OWNER_ID_NONE -1
+#define MUTEX_OWNER_ID_CONDVAR_SLEEP -2
+#define MUTEX_OWNER_ID_MUTEX_UNLOCK -3
+
struct mutex {
enum mutex_value value;
unsigned spin_lock; /* used when operating on this struct */
@@ -44,7 +53,7 @@ struct mutex {
TAILQ_ENTRY(mutex) link;
};
#define MUTEX_INITIALIZER \
- { .value = MUTEX_VALUE_UNLOCKED, .owner_id = -1, \
+ { .value = MUTEX_VALUE_UNLOCKED, .owner_id = MUTEX_OWNER_ID_NONE, \
.wq = WAIT_QUEUE_INITIALIZER, }
TAILQ_HEAD(mutex_head, mutex);
diff --git a/core/arch/arm/include/kernel/pseudo_ta.h b/core/arch/arm/include/kernel/pseudo_ta.h
index 98316bd..55d5e2b 100644
--- a/core/arch/arm/include/kernel/pseudo_ta.h
+++ b/core/arch/arm/include/kernel/pseudo_ta.h
@@ -38,7 +38,9 @@
TA_FLAG_MULTI_SESSION | \
TA_FLAG_INSTANCE_KEEP_ALIVE)
-#define PTA_ALLOWED_FLAGS PTA_MANDATORY_FLAGS
+#define PTA_ALLOWED_FLAGS (PTA_MANDATORY_FLAGS | \
+ TA_FLAG_SECURE_DATA_PATH)
+
#define PTA_DEFAULT_FLAGS PTA_MANDATORY_FLAGS
struct pseudo_ta_head {
diff --git a/core/arch/arm/include/kernel/spinlock.h b/core/arch/arm/include/kernel/spinlock.h
index c248673..a19b764 100644
--- a/core/arch/arm/include/kernel/spinlock.h
+++ b/core/arch/arm/include/kernel/spinlock.h
@@ -59,7 +59,7 @@ unsigned int __cpu_spin_trylock(unsigned int *lock);
static inline void cpu_spin_lock(unsigned int *lock)
{
- assert(thread_irq_disabled());
+ assert(thread_foreign_intr_disabled());
__cpu_spin_lock(lock);
spinlock_count_incr();
}
@@ -68,7 +68,7 @@ static inline bool cpu_spin_trylock(unsigned int *lock)
{
unsigned int rc;
- assert(thread_irq_disabled());
+ assert(thread_foreign_intr_disabled());
rc = __cpu_spin_trylock(lock);
if (!rc)
spinlock_count_incr();
@@ -77,7 +77,7 @@ static inline bool cpu_spin_trylock(unsigned int *lock)
static inline void cpu_spin_unlock(unsigned int *lock)
{
- assert(thread_irq_disabled());
+ assert(thread_foreign_intr_disabled());
__cpu_spin_unlock(lock);
spinlock_count_decr();
}
diff --git a/core/arch/arm/include/kernel/thread.h b/core/arch/arm/include/kernel/thread.h
index 175ba77..831b5d6 100644
--- a/core/arch/arm/include/kernel/thread.h
+++ b/core/arch/arm/include/kernel/thread.h
@@ -30,6 +30,7 @@
#define KERNEL_THREAD_H
#ifndef ASM
+#include <arm.h>
#include <types_ext.h>
#include <compiler.h>
#include <optee_msg.h>
@@ -203,7 +204,7 @@ struct thread_svc_regs {
#ifndef ASM
typedef void (*thread_smc_handler_t)(struct thread_smc_args *args);
-typedef void (*thread_fiq_handler_t)(void);
+typedef void (*thread_nintr_handler_t)(void);
typedef unsigned long (*thread_pm_handler_t)(unsigned long a0,
unsigned long a1);
struct thread_handlers {
@@ -218,11 +219,12 @@ struct thread_handlers {
*
* fastcall handles fast calls which can't be preemted. This
* handler is executed with a limited stack. This handler must not
- * cause any aborts or reenenable FIQs which are temporarily masked
- * while executing this handler.
+ * cause any aborts or reenenable native interrupts which are
+ * temporarily masked while executing this handler.
*
- * TODO investigate if we should execute fastcalls and FIQs on
- * different stacks allowing FIQs to be enabled during a fastcall.
+ * TODO investigate if we should execute fastcalls and native interrupts
+ * on different stacks allowing native interrupts to be enabled during
+ * a fastcall.
*/
thread_smc_handler_t std_smc;
thread_smc_handler_t fast_smc;
@@ -231,12 +233,12 @@ struct thread_handlers {
* fiq is called as a regular function and normal ARM Calling
* Convention applies.
*
- * This handler handles FIQs which can't be preemted. This handler
- * is executed with a limited stack. This handler must not cause
- * any aborts or reenenable FIQs which are temporarily masked while
- * executing this handler.
+ * This handler handles native interrupts which can't be preemted. This
+ * handler is executed with a limited stack. This handler must not cause
+ * any aborts or reenenable native interrupts which are temporarily
+ * masked while executing this handler.
*/
- thread_fiq_handler_t fiq;
+ thread_nintr_handler_t nintr;
/*
* Power management handlers triggered from ARM Trusted Firmware.
@@ -285,28 +287,30 @@ int thread_get_id_may_fail(void);
struct thread_specific_data *thread_get_tsd(void);
/*
- * Sets IRQ status for current thread, must only be called from an
- * active thread context.
+ * Sets foreign interrupts status for current thread, must only be called
+ * from an active thread context.
*
- * enable == true -> enable IRQ
- * enable == false -> disable IRQ
+ * enable == true -> enable foreign interrupts
+ * enable == false -> disable foreign interrupts
*/
-void thread_set_irq(bool enable);
+void thread_set_foreign_intr(bool enable);
/*
- * Restores the IRQ status (in CPSR) for current thread, must only be called
- * from an active thread context.
+ * Restores the foreign interrupts status (in CPSR) for current thread, must
+ * only be called from an active thread context.
*/
-void thread_restore_irq(void);
+void thread_restore_foreign_intr(void);
/*
* Defines the bits for the exception mask used the the
* thread_*_exceptions() functions below.
+ * These definitions are compatible with both ARM32 and ARM64.
*/
-#define THREAD_EXCP_FIQ (1 << 0)
-#define THREAD_EXCP_IRQ (1 << 1)
-#define THREAD_EXCP_ABT (1 << 2)
-#define THREAD_EXCP_ALL (THREAD_EXCP_FIQ | THREAD_EXCP_IRQ | THREAD_EXCP_ABT)
+#define THREAD_EXCP_FOREIGN_INTR (ARM32_CPSR_I >> ARM32_CPSR_F_SHIFT)
+#define THREAD_EXCP_NATIVE_INTR (ARM32_CPSR_F >> ARM32_CPSR_F_SHIFT)
+#define THREAD_EXCP_ALL (THREAD_EXCP_FOREIGN_INTR \
+ | THREAD_EXCP_NATIVE_INTR \
+ | (ARM32_CPSR_A >> ARM32_CPSR_F_SHIFT))
/*
* thread_get_exceptions() - return current exception mask
@@ -337,18 +341,18 @@ uint32_t thread_mask_exceptions(uint32_t exceptions);
void thread_unmask_exceptions(uint32_t state);
-static inline bool thread_irq_disabled(void)
+static inline bool thread_foreign_intr_disabled(void)
{
- return !!(thread_get_exceptions() & THREAD_EXCP_IRQ);
+ return !!(thread_get_exceptions() & THREAD_EXCP_FOREIGN_INTR);
}
#ifdef CFG_WITH_VFP
/*
* thread_kernel_enable_vfp() - Temporarily enables usage of VFP
*
- * IRQ is masked while VFP is enabled. User space must not be entered before
- * thread_kernel_disable_vfp() has been called to disable VFP and restore the
- * IRQ status.
+ * Foreign interrupts are masked while VFP is enabled. User space must not be
+ * entered before thread_kernel_disable_vfp() has been called to disable VFP
+ * and restore the foreign interrupt status.
*
* This function may only be called from an active thread context and may
* not be called again before thread_kernel_disable_vfp() has been called.
@@ -364,7 +368,7 @@ uint32_t thread_kernel_enable_vfp(void);
* thread_kernel_disable_vfp() - Disables usage of VFP
* @state: state variable returned by thread_kernel_enable_vfp()
*
- * Disables usage of VFP and restores IRQ status after a call to
+ * Disables usage of VFP and restores foreign interrupt status after a call to
* thread_kernel_enable_vfp().
*
* This function may only be called after a call to
@@ -484,13 +488,13 @@ bool thread_addr_is_in_stack(vaddr_t va);
/*
* Adds a mutex to the list of held mutexes for current thread
- * Requires IRQs to be disabled.
+ * Requires foreign interrupts to be disabled.
*/
void thread_add_mutex(struct mutex *m);
/*
* Removes a mutex from the list of held mutexes for current thread
- * Requires IRQs to be disabled.
+ * Requires foreign interrupts to be disabled.
*/
void thread_rem_mutex(struct mutex *m);
diff --git a/core/arch/arm/include/kernel/thread_defs.h b/core/arch/arm/include/kernel/thread_defs.h
index 0f54569..e081895 100644
--- a/core/arch/arm/include/kernel/thread_defs.h
+++ b/core/arch/arm/include/kernel/thread_defs.h
@@ -29,7 +29,7 @@
#define KERNEL_THREAD_DEFS_H
#define THREAD_FLAGS_COPY_ARGS_ON_RETURN (1 << 0)
-#define THREAD_FLAGS_IRQ_ENABLE (1 << 1)
-#define THREAD_FLAGS_EXIT_ON_IRQ (1 << 2)
+#define THREAD_FLAGS_FOREIGN_INTR_ENABLE (1 << 1)
+#define THREAD_FLAGS_EXIT_ON_FOREIGN_INTR (1 << 2)
#endif /*KERNEL_THREAD_DEFS_H*/
diff --git a/core/arch/arm/include/kernel/wait_queue.h b/core/arch/arm/include/kernel/wait_queue.h
index eb8f881..bb53cb6 100644
--- a/core/arch/arm/include/kernel/wait_queue.h
+++ b/core/arch/arm/include/kernel/wait_queue.h
@@ -67,7 +67,8 @@ static inline void wq_wait_init(struct wait_queue *wq,
/* Waits for the wait queue element to the awakened. */
void wq_wait_final(struct wait_queue *wq, struct wait_queue_elem *wqe,
- const void *sync_obj, const char *fname, int lineno);
+ const void *sync_obj, int owner, const char *fname,
+ int lineno);
/* Wakes up the first wait queue element in the wait queue, if there is one */
void wq_wake_one(struct wait_queue *wq, const void *sync_obj,
diff --git a/core/arch/arm/include/mm/core_memprot.h b/core/arch/arm/include/mm/core_memprot.h
index b7ccd21..99514fd 100644
--- a/core/arch/arm/include/mm/core_memprot.h
+++ b/core/arch/arm/include/mm/core_memprot.h
@@ -45,14 +45,14 @@
/* memory atttributes */
enum buf_is_attr {
- CORE_MEM_SEC,
+ CORE_MEM_CACHED,
+ CORE_MEM_EXTRAM,
+ CORE_MEM_NSEC_SHM,
CORE_MEM_NON_SEC,
+ CORE_MEM_SEC,
CORE_MEM_TEE_RAM,
CORE_MEM_TA_RAM,
- CORE_MEM_NSEC_SHM,
- CORE_MEM_EXTRAM,
- CORE_MEM_INTRAM,
- CORE_MEM_CACHED,
+ CORE_MEM_SDP_MEM,
};
/* redirect legacy tee_vbuf_is() and tee_pbuf_is() to our routines */
@@ -95,6 +95,13 @@ bool core_vbuf_is(uint32_t flags, const void *vbuf, size_t len);
void *phys_to_virt(paddr_t pa, enum teecore_memtypes m);
/*
+ * Translate physical address to virtual address trying MEM_AREA_IO_SEC
+ * first then MEM_AREA_IO_NSEC if not found.
+ * Returns NULL on failure or a valid virtual address on success.
+ */
+void *phys_to_virt_io(paddr_t pa);
+
+/*
* Translate virtual address to physical address
* Returns 0 on failure or a valid physical address on success.
*/
diff --git a/core/arch/arm/include/mm/core_mmu.h b/core/arch/arm/include/mm/core_mmu.h
index 03ad93d..70be5ab 100644
--- a/core/arch/arm/include/mm/core_mmu.h
+++ b/core/arch/arm/include/mm/core_mmu.h
@@ -100,6 +100,7 @@ enum teecore_memtypes {
MEM_AREA_IO_SEC,
MEM_AREA_RES_VASPACE,
MEM_AREA_TA_VASPACE,
+ MEM_AREA_SDP_MEM,
MEM_AREA_MAXTYPE
};
@@ -115,6 +116,13 @@ struct core_mmu_phys_mem {
__used __section("phys_mem_map_section") = \
{ #addr, (type), (addr), (size) }
+#define __register_sdp_mem2(pa, sz, id) \
+ static const struct core_mmu_phys_mem __phys_sdp_mem_ ## id \
+ __used __section("phys_sdp_mem_section") = \
+ { .type = MEM_AREA_SDP_MEM, .addr = (pa), .size = (sz), }
+
+#define __register_sdp_mem1(pa, sz, id) __register_sdp_mem2(pa, sz, id)
+#define register_sdp_mem(pa, sz) __register_sdp_mem1(pa, sz, __COUNTER__)
/* Default NSec shared memory allocated from NSec world */
extern unsigned long default_nsec_shm_paddr;
@@ -350,20 +358,6 @@ bool core_mmu_is_shm_cached(void);
bool core_mmu_add_mapping(enum teecore_memtypes type, paddr_t addr, size_t len);
-/* L1/L2 cache maintenance (op: refer to ???) */
-unsigned int cache_maintenance_l1(int op, void *va, size_t len);
-#ifdef CFG_PL310
-unsigned int cache_maintenance_l2(int op, paddr_t pa, size_t len);
-#else
-static inline unsigned int cache_maintenance_l2(int op __unused,
- paddr_t pa __unused,
- size_t len __unused)
-{
- /* Nothing to do about L2 Cache Maintenance when no PL310 */
- return TEE_SUCCESS;
-}
-#endif
-
/* various invalidate secure TLB */
enum teecore_tlb_op {
TLBINV_UNIFIEDTLB, /* invalidate unified tlb */
@@ -375,25 +369,37 @@ enum teecore_tlb_op {
int core_tlb_maintenance(int op, unsigned int a);
/* Cache maintenance operation type */
-typedef enum {
- DCACHE_CLEAN = 0x1,
- DCACHE_AREA_CLEAN = 0x2,
- DCACHE_INVALIDATE = 0x3,
- DCACHE_AREA_INVALIDATE = 0x4,
- ICACHE_INVALIDATE = 0x5,
- ICACHE_AREA_INVALIDATE = 0x6,
- WRITE_BUFFER_DRAIN = 0x7,
- DCACHE_CLEAN_INV = 0x8,
- DCACHE_AREA_CLEAN_INV = 0x9,
- L2CACHE_INVALIDATE = 0xA,
- L2CACHE_AREA_INVALIDATE = 0xB,
- L2CACHE_CLEAN = 0xC,
- L2CACHE_AREA_CLEAN = 0xD,
- L2CACHE_CLEAN_INV = 0xE,
- L2CACHE_AREA_CLEAN_INV = 0xF
-} t_cache_operation_id;
+enum cache_op {
+ DCACHE_CLEAN,
+ DCACHE_AREA_CLEAN,
+ DCACHE_INVALIDATE,
+ DCACHE_AREA_INVALIDATE,
+ ICACHE_INVALIDATE,
+ ICACHE_AREA_INVALIDATE,
+ DCACHE_CLEAN_INV,
+ DCACHE_AREA_CLEAN_INV,
+};
+
+/* L1/L2 cache maintenance */
+TEE_Result cache_op_inner(enum cache_op op, void *va, size_t len);
+#ifdef CFG_PL310
+TEE_Result cache_op_outer(enum cache_op op, paddr_t pa, size_t len);
+#else
+static inline TEE_Result cache_op_outer(enum cache_op op __unused,
+ paddr_t pa __unused,
+ size_t len __unused)
+{
+ /* Nothing to do about L2 Cache Maintenance when no PL310 */
+ return TEE_SUCCESS;
+}
+#endif
/* Check cpu mmu enabled or not */
bool cpu_mmu_enabled(void);
+#ifdef CFG_SECURE_DATA_PATH
+/* Alloc and fill SDP memory objects table - table is NULL terminated */
+struct mobj **core_sdp_mem_create_mobjs(void);
+#endif
+
#endif /* CORE_MMU_H */
diff --git a/core/arch/arm/include/mm/mobj.h b/core/arch/arm/include/mm/mobj.h
index d5eeb69..1a76149 100644
--- a/core/arch/arm/include/mm/mobj.h
+++ b/core/arch/arm/include/mm/mobj.h
@@ -108,6 +108,11 @@ static inline bool mobj_is_secure(struct mobj *mobj)
return mobj_matches(mobj, CORE_MEM_SEC);
}
+static inline bool mobj_is_sdp_mem(struct mobj *mobj)
+{
+ return mobj_matches(mobj, CORE_MEM_SDP_MEM);
+}
+
struct mobj *mobj_mm_alloc(struct mobj *mobj_parent, size_t size,
tee_mm_pool_t *pool);
diff --git a/core/arch/arm/include/sm/optee_smc.h b/core/arch/arm/include/sm/optee_smc.h
index b6fcd65..c369708 100644
--- a/core/arch/arm/include/sm/optee_smc.h
+++ b/core/arch/arm/include/sm/optee_smc.h
@@ -385,7 +385,7 @@
OPTEE_SMC_FAST_CALL_VAL(OPTEE_SMC_FUNCID_BOOT_SECONDARY)
/*
- * Resume from RPC (for example after processing an IRQ)
+ * Resume from RPC (for example after processing a foreign interrupt)
*
* Call register usage:
* a0 SMC Function ID, OPTEE_SMC_CALL_RETURN_FROM_RPC
@@ -470,19 +470,19 @@
OPTEE_SMC_RPC_VAL(OPTEE_SMC_RPC_FUNC_FREE)
/*
- * Deliver an IRQ in normal world.
+ * Deliver a foreign interrupt in normal world.
*
* "Call" register usage:
- * a0 OPTEE_SMC_RETURN_RPC_IRQ
+ * a0 OPTEE_SMC_RETURN_RPC_FOREIGN_INTR
* a1-7 Resume information, must be preserved
*
* "Return" register usage:
* a0 SMC Function ID, OPTEE_SMC_CALL_RETURN_FROM_RPC.
* a1-7 Preserved
*/
-#define OPTEE_SMC_RPC_FUNC_IRQ 4
-#define OPTEE_SMC_RETURN_RPC_IRQ \
- OPTEE_SMC_RPC_VAL(OPTEE_SMC_RPC_FUNC_IRQ)
+#define OPTEE_SMC_RPC_FUNC_FOREIGN_INTR 4
+#define OPTEE_SMC_RETURN_RPC_FOREIGN_INTR \
+ OPTEE_SMC_RPC_VAL(OPTEE_SMC_RPC_FUNC_FOREIGN_INTR)
/*
* Do an RPC request. The supplied struct optee_msg_arg tells which
diff --git a/core/arch/arm/include/sm/sm.h b/core/arch/arm/include/sm/sm.h
index 6368359..3446506 100644
--- a/core/arch/arm/include/sm/sm.h
+++ b/core/arch/arm/include/sm/sm.h
@@ -29,6 +29,7 @@
#ifndef SM_SM_H
#define SM_SM_H
+#include <compiler.h>
#include <types_ext.h>
struct sm_mode_regs {
@@ -120,4 +121,17 @@ void *sm_get_sp(void);
*/
void sm_init(vaddr_t stack_pointer);
+#ifndef CFG_SM_PLATFORM_HANDLER
+/*
+ * Returns false if we handled the monitor service and should now return
+ * back to the non-secure state
+ */
+static inline bool sm_platform_handler(__unused struct sm_ctx *ctx)
+{
+ return true;
+}
+#else
+bool sm_platform_handler(struct sm_ctx *ctx);
+#endif
+
#endif /*SM_SM_H*/
diff --git a/core/arch/arm/kernel/elf_common.h b/core/arch/arm/kernel/elf_common.h
index dd8cd50..497a902 100644
--- a/core/arch/arm/kernel/elf_common.h
+++ b/core/arch/arm/kernel/elf_common.h
@@ -645,6 +645,7 @@ typedef struct {
#define R_386_TLS_TPOFF32 37 /* GOT entry of -ve static TLS offset */
#define R_386_IRELATIVE 42 /* PLT entry resolved indirectly at runtime */
+#define R_AARCH64_ABS64 257
#define R_AARCH64_RELATIVE 1027
#define R_ARM_NONE 0 /* No relocation. */
diff --git a/core/arch/arm/kernel/elf_load.c b/core/arch/arm/kernel/elf_load.c
index 420ba59..b1d6102 100644
--- a/core/arch/arm/kernel/elf_load.c
+++ b/core/arch/arm/kernel/elf_load.c
@@ -499,9 +499,13 @@ static TEE_Result e32_process_rel(struct elf_load_state *state, size_t rel_sidx,
static TEE_Result e64_process_rel(struct elf_load_state *state,
size_t rel_sidx, vaddr_t vabase)
{
+ Elf64_Ehdr *ehdr = state->ehdr;
Elf64_Shdr *shdr = state->shdr;
Elf64_Rela *rela;
Elf64_Rela *rela_end;
+ size_t sym_tab_idx;
+ Elf64_Sym *sym_tab = NULL;
+ size_t num_syms = 0;
if (shdr[rel_sidx].sh_type != SHT_RELA)
return TEE_ERROR_NOT_IMPLEMENTED;
@@ -509,6 +513,27 @@ static TEE_Result e64_process_rel(struct elf_load_state *state,
if (shdr[rel_sidx].sh_entsize != sizeof(Elf64_Rela))
return TEE_ERROR_BAD_FORMAT;
+ sym_tab_idx = shdr[rel_sidx].sh_link;
+ if (sym_tab_idx) {
+ if (sym_tab_idx >= ehdr->e_shnum)
+ return TEE_ERROR_BAD_FORMAT;
+
+ if (shdr[sym_tab_idx].sh_entsize != sizeof(Elf64_Sym))
+ return TEE_ERROR_BAD_FORMAT;
+
+ /* Check the address is inside TA memory */
+ if (shdr[sym_tab_idx].sh_addr > state->vasize ||
+ (shdr[sym_tab_idx].sh_addr +
+ shdr[sym_tab_idx].sh_size) > state->vasize)
+ return TEE_ERROR_BAD_FORMAT;
+
+ sym_tab = (Elf64_Sym *)(vabase + shdr[sym_tab_idx].sh_addr);
+ if (!ALIGNMENT_IS_OK(sym_tab, Elf64_Sym))
+ return TEE_ERROR_BAD_FORMAT;
+
+ num_syms = shdr[sym_tab_idx].sh_size / sizeof(Elf64_Sym);
+ }
+
/* Check the address is inside TA memory */
if (shdr[rel_sidx].sh_addr >= state->vasize)
return TEE_ERROR_BAD_FORMAT;
@@ -522,6 +547,7 @@ static TEE_Result e64_process_rel(struct elf_load_state *state,
rela_end = rela + shdr[rel_sidx].sh_size / sizeof(Elf64_Rela);
for (; rela < rela_end; rela++) {
Elf64_Addr *where;
+ size_t sym_idx;
/* Check the address is inside TA memory */
if (rela->r_offset >= state->vasize)
@@ -532,6 +558,13 @@ static TEE_Result e64_process_rel(struct elf_load_state *state,
return TEE_ERROR_BAD_FORMAT;
switch (ELF64_R_TYPE(rela->r_info)) {
+ case R_AARCH64_ABS64:
+ sym_idx = ELF64_R_SYM(rela->r_info);
+ if (sym_idx > num_syms)
+ return TEE_ERROR_BAD_FORMAT;
+ *where = rela->r_addend + sym_tab[sym_idx].st_value +
+ vabase;
+ break;
case R_AARCH64_RELATIVE:
*where = rela->r_addend + vabase;
break;
diff --git a/core/arch/arm/kernel/generic_boot.c b/core/arch/arm/kernel/generic_boot.c
index 8f13c36..0d78d40 100644
--- a/core/arch/arm/kernel/generic_boot.c
+++ b/core/arch/arm/kernel/generic_boot.c
@@ -93,12 +93,6 @@ __weak void plat_cpu_reset_late(void)
KEEP_PAGER(plat_cpu_reset_late);
/* May be overridden in plat-$(PLATFORM)/main.c */
-__weak void plat_cpu_reset_early(void)
-{
-}
-KEEP_PAGER(plat_cpu_reset_early);
-
-/* May be overridden in plat-$(PLATFORM)/main.c */
__weak void main_init_gic(void)
{
}
@@ -289,9 +283,8 @@ static void init_runtime(unsigned long pageable_part)
p = (uint8_t *)(((vaddr_t)__init_start + init_size) &
~SMALL_PAGE_MASK);
- cache_maintenance_l1(DCACHE_AREA_CLEAN, p, SMALL_PAGE_SIZE);
- cache_maintenance_l1(ICACHE_AREA_INVALIDATE, p,
- SMALL_PAGE_SIZE);
+ cache_op_inner(DCACHE_AREA_CLEAN, p, SMALL_PAGE_SIZE);
+ cache_op_inner(ICACHE_AREA_INVALIDATE, p, SMALL_PAGE_SIZE);
}
/*
@@ -607,7 +600,8 @@ static void init_primary_helper(unsigned long pageable_part,
* Mask asynchronous exceptions before switch to the thread vector
* as the thread handler requires those to be masked while
* executing with the temporary stack. The thread subsystem also
- * asserts that IRQ is blocked when using most if its functions.
+ * asserts that the foreign interrupts are blocked when using most of
+ * its functions.
*/
thread_set_exceptions(THREAD_EXCP_ALL);
init_vfp_sec();
@@ -634,7 +628,8 @@ static void init_secondary_helper(unsigned long nsec_entry)
* Mask asynchronous exceptions before switch to the thread vector
* as the thread handler requires those to be masked while
* executing with the temporary stack. The thread subsystem also
- * asserts that IRQ is blocked when using most if its functions.
+ * asserts that the foreign interrupts are blocked when using most of
+ * its functions.
*/
thread_set_exceptions(THREAD_EXCP_ALL);
diff --git a/core/arch/arm/kernel/generic_entry_a32.S b/core/arch/arm/kernel/generic_entry_a32.S
index 27717d5..9c2ef41 100644
--- a/core/arch/arm/kernel/generic_entry_a32.S
+++ b/core/arch/arm/kernel/generic_entry_a32.S
@@ -25,16 +25,16 @@
* POSSIBILITY OF SUCH DAMAGE.
*/
-#include <platform_config.h>
-
-#include <asm.S>
#include <arm.h>
#include <arm32_macros.S>
+#include <asm.S>
+#include <platform_config.h>
+#include <keep.h>
+#include <kernel/asan.h>
+#include <kernel/unwind.h>
#include <sm/optee_smc.h>
#include <sm/teesmc_opteed_macros.h>
#include <sm/teesmc_opteed.h>
-#include <kernel/unwind.h>
-#include <kernel/asan.h>
.section .data
.balign 4
@@ -87,6 +87,14 @@ END_FUNC __assert_flat_mapped_range
.endm
#endif /* CFG_PL310 */
+.weak plat_cpu_reset_early
+FUNC plat_cpu_reset_early , :
+UNWIND( .fnstart)
+ bx lr
+UNWIND( .fnend)
+END_FUNC plat_cpu_reset_early
+KEEP_PAGER plat_cpu_reset_early
+
.section .text.boot
FUNC _start , :
b reset
diff --git a/core/arch/arm/kernel/kern.ld.S b/core/arch/arm/kernel/kern.ld.S
index 10dac6e..b761aea 100644
--- a/core/arch/arm/kernel/kern.ld.S
+++ b/core/arch/arm/kernel/kern.ld.S
@@ -107,6 +107,10 @@ SECTIONS
__start_phys_mem_map_section = . ;
KEEP(*(phys_mem_map_section))
__end_phys_mem_map_section = . ;
+ . = ALIGN(8);
+ __start_phys_sdp_mem_section = . ;
+ KEEP(*(phys_sdp_mem_section))
+ __end_phys_sdp_mem_section = . ;
#endif
. = ALIGN(8);
__rodata_end = .;
@@ -254,6 +258,10 @@ SECTIONS
KEEP(*(phys_mem_map_section))
__end_phys_mem_map_section = . ;
. = ALIGN(8);
+ __start_phys_sdp_mem_section = . ;
+ KEEP(*(phys_sdp_mem_section))
+ __end_phys_sdp_mem_section = . ;
+ . = ALIGN(8);
__rodata_init_end = .;
}
__init_start = __text_init_start;
diff --git a/core/arch/arm/kernel/mutex.c b/core/arch/arm/kernel/mutex.c
index 0e1b836..a25ca12 100644
--- a/core/arch/arm/kernel/mutex.c
+++ b/core/arch/arm/kernel/mutex.c
@@ -45,6 +45,7 @@ static void __mutex_lock(struct mutex *m, const char *fname, int lineno)
uint32_t old_itr_status;
enum mutex_value old_value;
struct wait_queue_elem wqe;
+ int owner = MUTEX_OWNER_ID_NONE;
/*
* If the mutex is locked we need to initialize the wqe
@@ -61,6 +62,7 @@ static void __mutex_lock(struct mutex *m, const char *fname, int lineno)
old_value = m->value;
if (old_value == MUTEX_VALUE_LOCKED) {
wq_wait_init(&m->wq, &wqe);
+ owner = m->owner_id;
} else {
m->value = MUTEX_VALUE_LOCKED;
thread_add_mutex(m);
@@ -74,7 +76,7 @@ static void __mutex_lock(struct mutex *m, const char *fname, int lineno)
* Someone else is holding the lock, wait in normal
* world for the lock to become available.
*/
- wq_wait_final(&m->wq, &wqe, m, fname, lineno);
+ wq_wait_final(&m->wq, &wqe, m, owner, fname, lineno);
} else
return;
}
@@ -260,7 +262,8 @@ static void __condvar_wait(struct condvar *cv, struct mutex *m,
/* Wake eventual waiters */
wq_wake_one(&m->wq, m, fname, lineno);
- wq_wait_final(&m->wq, &wqe, m, fname, lineno);
+ wq_wait_final(&m->wq, &wqe,
+ m, MUTEX_OWNER_ID_CONDVAR_SLEEP, fname, lineno);
mutex_lock(m);
}
diff --git a/core/arch/arm/kernel/pseudo_ta.c b/core/arch/arm/kernel/pseudo_ta.c
index 6352a28..78b2bfd 100644
--- a/core/arch/arm/kernel/pseudo_ta.c
+++ b/core/arch/arm/kernel/pseudo_ta.c
@@ -37,9 +37,41 @@
#include <trace.h>
#include <types_ext.h>
+#ifdef CFG_SECURE_DATA_PATH
+static bool client_is_secure(struct tee_ta_session *s)
+{
+ /* rely on core entry to have constrained client IDs */
+ if (s->clnt_id.login == TEE_LOGIN_TRUSTED_APP)
+ return true;
+
+ return false;
+}
+
+static bool validate_in_param(struct tee_ta_session *s, struct mobj *mobj)
+{
+ /* for secure clients, core entry always holds valid memref objects */
+ if (client_is_secure(s))
+ return true;
+
+ /* all non-secure memory references are hanlded by pTAs */
+ if (mobj_is_nonsec(mobj))
+ return true;
+
+ return false;
+}
+#else
+static bool validate_in_param(struct tee_ta_session *s __unused,
+ struct mobj *mobj __unused)
+{
+ /* At this point, core has filled only valid accessible memref mobj */
+ return true;
+}
+#endif
+
/* Maps static TA params */
-static TEE_Result copy_in_param(struct tee_ta_param *param,
- TEE_Param tee_param[TEE_NUM_PARAMS])
+static TEE_Result copy_in_param(struct tee_ta_session *s __maybe_unused,
+ struct tee_ta_param *param,
+ TEE_Param tee_param[TEE_NUM_PARAMS])
{
size_t n;
void *va;
@@ -55,6 +87,9 @@ static TEE_Result copy_in_param(struct tee_ta_param *param,
case TEE_PARAM_TYPE_MEMREF_INPUT:
case TEE_PARAM_TYPE_MEMREF_OUTPUT:
case TEE_PARAM_TYPE_MEMREF_INOUT:
+ if (!validate_in_param(s, param->u[n].mem.mobj))
+ return TEE_ERROR_BAD_PARAMETERS;
+
va = mobj_get_va(param->u[n].mem.mobj,
param->u[n].mem.offs);
if (!va)
@@ -110,7 +145,7 @@ static TEE_Result pseudo_ta_enter_open_session(struct tee_ta_session *s,
}
if (stc->pseudo_ta->open_session_entry_point) {
- res = copy_in_param(param, tee_param);
+ res = copy_in_param(s, param, tee_param);
if (res != TEE_SUCCESS) {
*eo = TEE_ORIGIN_TEE;
goto out;
@@ -136,7 +171,7 @@ static TEE_Result pseudo_ta_enter_invoke_cmd(struct tee_ta_session *s,
TEE_Param tee_param[TEE_NUM_PARAMS];
tee_ta_push_current_session(s);
- res = copy_in_param(param, tee_param);
+ res = copy_in_param(s, param, tee_param);
if (res != TEE_SUCCESS) {
*eo = TEE_ORIGIN_TEE;
goto out;
@@ -224,7 +259,7 @@ TEE_Result tee_ta_init_pseudo_ta_session(const TEE_UUID *uuid,
struct tee_ta_ctx *ctx;
const struct pseudo_ta_head *ta;
- DMSG(" Lookup for Static TA %pUl", (void *)uuid);
+ DMSG(" Lookup for pseudo TA %pUl", (void *)uuid);
ta = &__start_ta_head_section;
while (true) {
diff --git a/core/arch/arm/kernel/spin_lock_debug.c b/core/arch/arm/kernel/spin_lock_debug.c
index 2a450a5..00a2a00 100644
--- a/core/arch/arm/kernel/spin_lock_debug.c
+++ b/core/arch/arm/kernel/spin_lock_debug.c
@@ -49,10 +49,11 @@ bool have_spinlock(void)
{
struct thread_core_local *l;
- if (!thread_irq_disabled()) {
+ if (!thread_foreign_intr_disabled()) {
/*
* Normally we can't be holding a spinlock since doing so would
- * imply IRQ are disabled (or the spinlock logic is flawed).
+ * imply foreign interrupts are disabled (or the spinlock
+ * logic is flawed).
*/
return false;
}
diff --git a/core/arch/arm/kernel/tee_time_arm_cntpct.c b/core/arch/arm/kernel/tee_time_arm_cntpct.c
index 90e7f20..59d6ea4 100644
--- a/core/arch/arm/kernel/tee_time_arm_cntpct.c
+++ b/core/arch/arm/kernel/tee_time_arm_cntpct.c
@@ -93,7 +93,7 @@ void plat_prng_add_jitter_entropy(void)
}
}
if (bytes) {
- DMSG("%s: 0x%02X\n", __func__,
+ FMSG("%s: 0x%02X\n", __func__,
(int)acc & ((1 << (bytes * 8)) - 1));
tee_prng_add_entropy((uint8_t *)&acc, bytes);
}
diff --git a/core/arch/arm/kernel/thread.c b/core/arch/arm/kernel/thread.c
index c988b65..2aaa0e6 100644
--- a/core/arch/arm/kernel/thread.c
+++ b/core/arch/arm/kernel/thread.c
@@ -66,15 +66,11 @@
#endif
#define STACK_THREAD_SIZE 8192
-#if TRACE_LEVEL > 0
#ifdef CFG_CORE_SANITIZE_KADDRESS
#define STACK_ABT_SIZE 3072
#else
#define STACK_ABT_SIZE 2048
#endif
-#else
-#define STACK_ABT_SIZE 1024
-#endif
#endif /*ARM32*/
@@ -140,7 +136,7 @@ KEEP_PAGER(stack_tmp_offset);
thread_smc_handler_t thread_std_smc_handler_ptr;
static thread_smc_handler_t thread_fast_smc_handler_ptr;
-thread_fiq_handler_t thread_fiq_handler_ptr;
+thread_nintr_handler_t thread_nintr_handler_ptr;
thread_pm_handler_t thread_cpu_on_handler_ptr;
thread_pm_handler_t thread_cpu_off_handler_ptr;
thread_pm_handler_t thread_cpu_suspend_handler_ptr;
@@ -234,8 +230,8 @@ void thread_set_exceptions(uint32_t exceptions)
{
uint32_t cpsr = read_cpsr();
- /* IRQ must not be unmasked while holding a spinlock */
- if (!(exceptions & THREAD_EXCP_IRQ))
+ /* Foreign interrupts must not be unmasked while holding a spinlock */
+ if (!(exceptions & THREAD_EXCP_FOREIGN_INTR))
assert_have_no_spinlock();
cpsr &= ~(THREAD_EXCP_ALL << CPSR_F_SHIFT);
@@ -256,8 +252,8 @@ void thread_set_exceptions(uint32_t exceptions)
{
uint32_t daif = read_daif();
- /* IRQ must not be unmasked while holding a spinlock */
- if (!(exceptions & THREAD_EXCP_IRQ))
+ /* Foreign interrupts must not be unmasked while holding a spinlock */
+ if (!(exceptions & THREAD_EXCP_FOREIGN_INTR))
assert_have_no_spinlock();
daif &= ~(THREAD_EXCP_ALL << DAIF_F_SHIFT);
@@ -285,11 +281,11 @@ struct thread_core_local *thread_get_core_local(void)
uint32_t cpu_id = get_core_pos();
/*
- * IRQs must be disabled before playing with core_local since
- * we otherwise may be rescheduled to a different core in the
+ * Foreign interrupts must be disabled before playing with core_local
+ * since we otherwise may be rescheduled to a different core in the
* middle of this function.
*/
- assert(thread_get_exceptions() & THREAD_EXCP_IRQ);
+ assert(thread_get_exceptions() & THREAD_EXCP_FOREIGN_INTR);
assert(cpu_id < CFG_TEE_CORE_NB_CORE);
return &thread_core_local[cpu_id];
@@ -338,11 +334,12 @@ static void init_regs(struct thread_ctx *thread,
thread->regs.pc = (uint32_t)thread_std_smc_entry;
/*
- * Stdcalls starts in SVC mode with masked IRQ, masked Asynchronous
- * abort and unmasked FIQ.
- */
+ * Stdcalls starts in SVC mode with masked foreign interrupts, masked
+ * Asynchronous abort and unmasked native interrupts.
+ */
thread->regs.cpsr = read_cpsr() & ARM32_CPSR_E;
- thread->regs.cpsr |= CPSR_MODE_SVC | CPSR_I | CPSR_A;
+ thread->regs.cpsr |= CPSR_MODE_SVC | CPSR_A |
+ (THREAD_EXCP_FOREIGN_INTR << ARM32_CPSR_F_SHIFT);
/* Enable thumb mode if it's a thumb instruction */
if (thread->regs.pc & 1)
thread->regs.cpsr |= CPSR_T;
@@ -371,11 +368,11 @@ static void init_regs(struct thread_ctx *thread,
thread->regs.pc = (uint64_t)thread_std_smc_entry;
/*
- * Stdcalls starts in SVC mode with masked IRQ, masked Asynchronous
- * abort and unmasked FIQ.
- */
+ * Stdcalls starts in SVC mode with masked foreign interrupts, masked
+ * Asynchronous abort and unmasked native interrupts.
+ */
thread->regs.cpsr = SPSR_64(SPSR_64_MODE_EL1, SPSR_64_MODE_SP_EL0,
- DAIFBIT_IRQ | DAIFBIT_ABT);
+ THREAD_EXCP_FOREIGN_INTR | DAIFBIT_ABT);
/* Reinitialize stack pointer */
thread->regs.sp = thread->stack_va_end;
@@ -556,7 +553,7 @@ static void thread_resume_from_rpc(struct thread_smc_args *args)
core_mmu_set_user_map(&threads[n].user_map);
/*
- * Return from RPC to request service of an IRQ must not
+ * Return from RPC to request service of a foreign interrupt must not
* get parameters from non-secure world.
*/
if (threads[n].flags & THREAD_FLAGS_COPY_ARGS_ON_RETURN) {
@@ -769,8 +766,10 @@ bool thread_init_stack(uint32_t thread_id, vaddr_t sp)
int thread_get_id_may_fail(void)
{
- /* thread_get_core_local() requires IRQs to be disabled */
- uint32_t exceptions = thread_mask_exceptions(THREAD_EXCP_IRQ);
+ /*
+ * thread_get_core_local() requires foreign interrupts to be disabled
+ */
+ uint32_t exceptions = thread_mask_exceptions(THREAD_EXCP_FOREIGN_INTR);
struct thread_core_local *l = thread_get_core_local();
int ct = l->curr_thread;
@@ -790,7 +789,7 @@ static void init_handlers(const struct thread_handlers *handlers)
{
thread_std_smc_handler_ptr = handlers->std_smc;
thread_fast_smc_handler_ptr = handlers->fast_smc;
- thread_fiq_handler_ptr = handlers->fiq;
+ thread_nintr_handler_ptr = handlers->nintr;
thread_cpu_on_handler_ptr = handlers->cpu_on;
thread_cpu_off_handler_ptr = handlers->cpu_off;
thread_cpu_suspend_handler_ptr = handlers->cpu_suspend;
@@ -890,10 +889,10 @@ struct thread_ctx_regs *thread_get_ctx_regs(void)
return &threads[l->curr_thread].regs;
}
-void thread_set_irq(bool enable)
+void thread_set_foreign_intr(bool enable)
{
- /* thread_get_core_local() requires IRQs to be disabled */
- uint32_t exceptions = thread_mask_exceptions(THREAD_EXCP_IRQ);
+ /* thread_get_core_local() requires foreign interrupts to be disabled */
+ uint32_t exceptions = thread_mask_exceptions(THREAD_EXCP_FOREIGN_INTR);
struct thread_core_local *l;
l = thread_get_core_local();
@@ -901,35 +900,37 @@ void thread_set_irq(bool enable)
assert(l->curr_thread != -1);
if (enable) {
- threads[l->curr_thread].flags |= THREAD_FLAGS_IRQ_ENABLE;
- thread_set_exceptions(exceptions & ~THREAD_EXCP_IRQ);
+ threads[l->curr_thread].flags |=
+ THREAD_FLAGS_FOREIGN_INTR_ENABLE;
+ thread_set_exceptions(exceptions & ~THREAD_EXCP_FOREIGN_INTR);
} else {
/*
- * No need to disable IRQ here since it's already disabled
- * above.
+ * No need to disable foreign interrupts here since they're
+ * already disabled above.
*/
- threads[l->curr_thread].flags &= ~THREAD_FLAGS_IRQ_ENABLE;
+ threads[l->curr_thread].flags &=
+ ~THREAD_FLAGS_FOREIGN_INTR_ENABLE;
}
}
-void thread_restore_irq(void)
+void thread_restore_foreign_intr(void)
{
- /* thread_get_core_local() requires IRQs to be disabled */
- uint32_t exceptions = thread_mask_exceptions(THREAD_EXCP_IRQ);
+ /* thread_get_core_local() requires foreign interrupts to be disabled */
+ uint32_t exceptions = thread_mask_exceptions(THREAD_EXCP_FOREIGN_INTR);
struct thread_core_local *l;
l = thread_get_core_local();
assert(l->curr_thread != -1);
- if (threads[l->curr_thread].flags & THREAD_FLAGS_IRQ_ENABLE)
- thread_set_exceptions(exceptions & ~THREAD_EXCP_IRQ);
+ if (threads[l->curr_thread].flags & THREAD_FLAGS_FOREIGN_INTR_ENABLE)
+ thread_set_exceptions(exceptions & ~THREAD_EXCP_FOREIGN_INTR);
}
#ifdef CFG_WITH_VFP
uint32_t thread_kernel_enable_vfp(void)
{
- uint32_t exceptions = thread_mask_exceptions(THREAD_EXCP_IRQ);
+ uint32_t exceptions = thread_mask_exceptions(THREAD_EXCP_FOREIGN_INTR);
struct thread_ctx *thr = threads + thread_get_id();
struct thread_user_vfp_state *tuv = thr->vfp_state.uvfp;
@@ -967,9 +968,9 @@ void thread_kernel_disable_vfp(uint32_t state)
vfp_disable();
exceptions = thread_get_exceptions();
- assert(exceptions & THREAD_EXCP_IRQ);
- exceptions &= ~THREAD_EXCP_IRQ;
- exceptions |= state & THREAD_EXCP_IRQ;
+ assert(exceptions & THREAD_EXCP_FOREIGN_INTR);
+ exceptions &= ~THREAD_EXCP_FOREIGN_INTR;
+ exceptions |= state & THREAD_EXCP_FOREIGN_INTR;
thread_set_exceptions(exceptions);
}
@@ -977,7 +978,7 @@ void thread_kernel_save_vfp(void)
{
struct thread_ctx *thr = threads + thread_get_id();
- assert(thread_get_exceptions() & THREAD_EXCP_IRQ);
+ assert(thread_get_exceptions() & THREAD_EXCP_FOREIGN_INTR);
if (vfp_is_enabled()) {
vfp_lazy_save_state_init(&thr->vfp_state.sec);
thr->vfp_state.sec_lazy_saved = true;
@@ -988,7 +989,7 @@ void thread_kernel_restore_vfp(void)
{
struct thread_ctx *thr = threads + thread_get_id();
- assert(thread_get_exceptions() & THREAD_EXCP_IRQ);
+ assert(thread_get_exceptions() & THREAD_EXCP_FOREIGN_INTR);
assert(!vfp_is_enabled());
if (thr->vfp_state.sec_lazy_saved) {
vfp_lazy_restore_state(&thr->vfp_state.sec,
@@ -1003,7 +1004,7 @@ void thread_user_enable_vfp(struct thread_user_vfp_state *uvfp)
struct thread_ctx *thr = threads + thread_get_id();
struct thread_user_vfp_state *tuv = thr->vfp_state.uvfp;
- assert(thread_get_exceptions() & THREAD_EXCP_IRQ);
+ assert(thread_get_exceptions() & THREAD_EXCP_FOREIGN_INTR);
assert(!vfp_is_enabled());
if (!thr->vfp_state.ns_saved) {
@@ -1030,7 +1031,7 @@ void thread_user_save_vfp(void)
struct thread_ctx *thr = threads + thread_get_id();
struct thread_user_vfp_state *tuv = thr->vfp_state.uvfp;
- assert(thread_get_exceptions() & THREAD_EXCP_IRQ);
+ assert(thread_get_exceptions() & THREAD_EXCP_FOREIGN_INTR);
if (!vfp_is_enabled())
return;
@@ -1110,7 +1111,7 @@ void thread_add_mutex(struct mutex *m)
int ct = l->curr_thread;
assert(ct != -1 && threads[ct].state == THREAD_STATE_ACTIVE);
- assert(m->owner_id == -1);
+ assert(m->owner_id == MUTEX_OWNER_ID_NONE);
m->owner_id = ct;
TAILQ_INSERT_TAIL(&threads[ct].mutexes, m, link);
}
@@ -1122,7 +1123,7 @@ void thread_rem_mutex(struct mutex *m)
assert(ct != -1 && threads[ct].state == THREAD_STATE_ACTIVE);
assert(m->owner_id == ct);
- m->owner_id = -1;
+ m->owner_id = MUTEX_OWNER_ID_NONE;
TAILQ_REMOVE(&threads[ct].mutexes, m, link);
}
@@ -1130,7 +1131,7 @@ bool thread_disable_prealloc_rpc_cache(uint64_t *cookie)
{
bool rv;
size_t n;
- uint32_t exceptions = thread_mask_exceptions(THREAD_EXCP_IRQ);
+ uint32_t exceptions = thread_mask_exceptions(THREAD_EXCP_FOREIGN_INTR);
lock_global();
@@ -1163,7 +1164,7 @@ bool thread_enable_prealloc_rpc_cache(void)
{
bool rv;
size_t n;
- uint32_t exceptions = thread_mask_exceptions(THREAD_EXCP_IRQ);
+ uint32_t exceptions = thread_mask_exceptions(THREAD_EXCP_FOREIGN_INTR);
lock_global();
@@ -1194,7 +1195,14 @@ static uint32_t rpc_cmd_nolock(uint32_t cmd, size_t num_params,
assert(arg && carg && num_params <= THREAD_RPC_MAX_NUM_PARAMS);
- plat_prng_add_jitter_entropy();
+
+ /*
+ * Break recursion in case plat_prng_add_jitter_entropy_norpc()
+ * sleeps on a mutex or unlocks a mutex with a sleeper (contended
+ * mutex).
+ */
+ if (cmd != OPTEE_MSG_RPC_CMD_WAIT_QUEUE)
+ plat_prng_add_jitter_entropy_norpc();
memset(arg, 0, OPTEE_MSG_GET_ARG_SIZE(THREAD_RPC_MAX_NUM_PARAMS));
arg->cmd = cmd;
diff --git a/core/arch/arm/kernel/thread_a32.S b/core/arch/arm/kernel/thread_a32.S
index 6d3ac35..1a1c696 100644
--- a/core/arch/arm/kernel/thread_a32.S
+++ b/core/arch/arm/kernel/thread_a32.S
@@ -75,7 +75,7 @@ UNWIND( .fnstart)
UNWIND( .cantunwind)
/* Secure Monitor received a FIQ and passed control to us. */
bl thread_check_canaries
- ldr lr, =thread_fiq_handler_ptr
+ ldr lr, =thread_nintr_handler_ptr
ldr lr, [lr]
blx lr
mov r1, r0
@@ -392,7 +392,7 @@ UNWIND( .cantunwind)
*/
push {r0-r3, r8-r12, lr}
bl thread_check_canaries
- ldr lr, =thread_fiq_handler_ptr
+ ldr lr, =thread_nintr_handler_ptr
ldr lr, [lr]
blx lr
pop {r0-r3, r8-r12, lr}
@@ -416,7 +416,7 @@ UNWIND( .cantunwind)
bl thread_save_state
- mov r0, #THREAD_FLAGS_EXIT_ON_IRQ
+ mov r0, #THREAD_FLAGS_EXIT_ON_FOREIGN_INTR
mrs r1, spsr
pop {r12}
pop {r2}
@@ -432,7 +432,7 @@ UNWIND( .cantunwind)
mov sp, r0
ldr r0, =TEESMC_OPTEED_RETURN_CALL_DONE
- ldr r1, =OPTEE_SMC_RETURN_RPC_IRQ
+ ldr r1, =OPTEE_SMC_RETURN_RPC_FOREIGN_INTR
mov r2, #0
mov r3, #0
/* r4 is already filled in above */
diff --git a/core/arch/arm/kernel/thread_a64.S b/core/arch/arm/kernel/thread_a64.S
index abd482b..241868a 100644
--- a/core/arch/arm/kernel/thread_a64.S
+++ b/core/arch/arm/kernel/thread_a64.S
@@ -77,7 +77,7 @@ END_FUNC vector_fast_smc_entry
LOCAL_FUNC vector_fiq_entry , :
/* Secure Monitor received a FIQ and passed control to us. */
bl thread_check_canaries
- adr x16, thread_fiq_handler_ptr
+ adr x16, thread_nintr_handler_ptr
ldr x16, [x16]
blr x16
ldr x0, =TEESMC_OPTEED_RETURN_FIQ_DONE
@@ -487,9 +487,9 @@ LOCAL_FUNC el0_svc , :
mov x0, sp
/*
- * Unmask FIQ, Serror, and debug exceptions since we have nothing
- * left in sp_el1. Note that the SVC handler is excepted to
- * re-enable IRQs by itself.
+ * Unmask native interrupts, Serror, and debug exceptions since we have
+ * nothing left in sp_el1. Note that the SVC handler is excepted to
+ * re-enable foreign interrupts by itself.
*/
msr daifclr, #(DAIFBIT_FIQ | DAIFBIT_ABT | DAIFBIT_DBG)
@@ -713,7 +713,7 @@ LOCAL_FUNC elx_irq , :
/*
* Mark current thread as suspended
*/
- mov w0, #THREAD_FLAGS_EXIT_ON_IRQ
+ mov w0, #THREAD_FLAGS_EXIT_ON_FOREIGN_INTR
mrs x1, spsr_el1
mrs x2, elr_el1
bl thread_state_suspend
@@ -734,7 +734,7 @@ LOCAL_FUNC elx_irq , :
*/
ldr w0, =TEESMC_OPTEED_RETURN_CALL_DONE
- ldr w1, =OPTEE_SMC_RETURN_RPC_IRQ
+ ldr w1, =OPTEE_SMC_RETURN_RPC_FOREIGN_INTR
mov w2, #0
mov w3, #0
/* w4 is already filled in above */
@@ -787,7 +787,7 @@ LOCAL_FUNC elx_fiq , :
stp x30, x2, [sp, #ELX_FIQ_REC_LR]
bl thread_check_canaries
- adr x16, thread_fiq_handler_ptr
+ adr x16, thread_nintr_handler_ptr
ldr x16, [x16]
blr x16
diff --git a/core/arch/arm/kernel/trace_ext.c b/core/arch/arm/kernel/trace_ext.c
index 8b8454c..6cedba3 100644
--- a/core/arch/arm/kernel/trace_ext.c
+++ b/core/arch/arm/kernel/trace_ext.c
@@ -27,21 +27,40 @@
#include <stdbool.h>
#include <trace.h>
#include <console.h>
+#include <kernel/spinlock.h>
#include <kernel/thread.h>
+#include <mm/core_mmu.h>
const char trace_ext_prefix[] = "TEE-CORE";
int trace_level = TRACE_LEVEL;
+static unsigned int puts_lock = SPINLOCK_UNLOCK;
void trace_ext_puts(const char *str)
{
+ uint32_t itr_status = thread_mask_exceptions(THREAD_EXCP_ALL);
+ bool mmu_enabled = cpu_mmu_enabled();
+ bool was_contended = false;
const char *p;
+ if (mmu_enabled && !cpu_spin_trylock(&puts_lock)) {
+ was_contended = true;
+ cpu_spin_lock(&puts_lock);
+ }
+
console_flush();
+ if (was_contended)
+ console_putc('*');
+
for (p = str; *p; p++)
console_putc(*p);
console_flush();
+
+ if (mmu_enabled)
+ cpu_spin_unlock(&puts_lock);
+
+ thread_unmask_exceptions(itr_status);
}
int trace_ext_get_thread_id(void)
diff --git a/core/arch/arm/kernel/user_ta.c b/core/arch/arm/kernel/user_ta.c
index a63fb22..5c9aae8 100644
--- a/core/arch/arm/kernel/user_ta.c
+++ b/core/arch/arm/kernel/user_ta.c
@@ -194,8 +194,8 @@ static TEE_Result config_final_paging(struct user_ta_ctx *utc)
size_t vasize = utc->mmu->ta_private_vmem_end -
utc->mmu->ta_private_vmem_start;
- cache_maintenance_l1(DCACHE_AREA_CLEAN, va, vasize);
- cache_maintenance_l1(ICACHE_AREA_INVALIDATE, va, vasize);
+ cache_op_inner(DCACHE_AREA_CLEAN, va, vasize);
+ cache_op_inner(ICACHE_AREA_INVALIDATE, va, vasize);
return TEE_SUCCESS;
}
#endif /*!CFG_PAGED_USER_TA*/
@@ -386,7 +386,7 @@ static TEE_Result ta_load(const TEE_UUID *uuid, const struct shdr *signed_ta,
uint32_t man_flags = TA_FLAG_USER_MODE | TA_FLAG_EXEC_DDR;
/* opt_flags: optional flags */
uint32_t opt_flags = man_flags | TA_FLAG_SINGLE_INSTANCE |
- TA_FLAG_MULTI_SESSION | TA_FLAG_UNSAFE_NW_PARAMS |
+ TA_FLAG_MULTI_SESSION | TA_FLAG_SECURE_DATA_PATH |
TA_FLAG_INSTANCE_KEEP_ALIVE | TA_FLAG_CACHE_MAINTENANCE;
struct user_ta_ctx *utc = NULL;
struct shdr *sec_shdr = NULL;
@@ -748,8 +748,8 @@ static void user_ta_ctx_destroy(struct tee_ta_ctx *ctx)
va = mobj_get_va(utc->mobj_code, 0);
if (va) {
memset(va, 0, utc->mobj_code->size);
- cache_maintenance_l1(DCACHE_AREA_CLEAN, va,
- utc->mobj_code->size);
+ cache_op_inner(DCACHE_AREA_CLEAN, va,
+ utc->mobj_code->size);
}
}
@@ -757,8 +757,8 @@ static void user_ta_ctx_destroy(struct tee_ta_ctx *ctx)
va = mobj_get_va(utc->mobj_stack, 0);
if (va) {
memset(va, 0, utc->mobj_stack->size);
- cache_maintenance_l1(DCACHE_AREA_CLEAN, va,
- utc->mobj_stack->size);
+ cache_op_inner(DCACHE_AREA_CLEAN, va,
+ utc->mobj_stack->size);
}
}
}
diff --git a/core/arch/arm/kernel/wait_queue.c b/core/arch/arm/kernel/wait_queue.c
index a96e0fe..6fb4456 100644
--- a/core/arch/arm/kernel/wait_queue.c
+++ b/core/arch/arm/kernel/wait_queue.c
@@ -43,7 +43,8 @@ void wq_init(struct wait_queue *wq)
}
static void wq_rpc(uint32_t func, int id, const void *sync_obj __maybe_unused,
- const char *fname, int lineno __maybe_unused)
+ int owner __maybe_unused, const char *fname,
+ int lineno __maybe_unused)
{
uint32_t ret;
struct optee_msg_param params;
@@ -51,10 +52,10 @@ static void wq_rpc(uint32_t func, int id, const void *sync_obj __maybe_unused,
func == OPTEE_MSG_RPC_WAIT_QUEUE_SLEEP ? "sleep" : "wake ";
if (fname)
- DMSG("%s thread %u %p %s:%d", cmd_str, id,
- sync_obj, fname, lineno);
+ DMSG("%s thread %u %p %d %s:%d", cmd_str, id,
+ sync_obj, owner, fname, lineno);
else
- DMSG("%s thread %u %p", cmd_str, id, sync_obj);
+ DMSG("%s thread %u %p %d", cmd_str, id, sync_obj, owner);
memset(&params, 0, sizeof(params));
params.attr = OPTEE_MSG_ATTR_TYPE_VALUE_INPUT;
@@ -99,14 +100,15 @@ void wq_wait_init_condvar(struct wait_queue *wq, struct wait_queue_elem *wqe,
}
void wq_wait_final(struct wait_queue *wq, struct wait_queue_elem *wqe,
- const void *sync_obj, const char *fname, int lineno)
+ const void *sync_obj, int owner, const char *fname,
+ int lineno)
{
uint32_t old_itr_status;
unsigned done;
do {
wq_rpc(OPTEE_MSG_RPC_WAIT_QUEUE_SLEEP, wqe->handle,
- sync_obj, fname, lineno);
+ sync_obj, owner, fname, lineno);
old_itr_status = thread_mask_exceptions(THREAD_EXCP_ALL);
cpu_spin_lock(&wq_spin_lock);
@@ -145,7 +147,7 @@ void wq_wake_one(struct wait_queue *wq, const void *sync_obj,
if (do_wakeup)
wq_rpc(OPTEE_MSG_RPC_WAIT_QUEUE_WAKEUP, handle,
- sync_obj, fname, lineno);
+ sync_obj, MUTEX_OWNER_ID_MUTEX_UNLOCK, fname, lineno);
}
void wq_promote_condvar(struct wait_queue *wq, struct condvar *cv,
diff --git a/core/arch/arm/mm/core_mmu.c b/core/arch/arm/mm/core_mmu.c
index 62dda73..f85e496 100644
--- a/core/arch/arm/mm/core_mmu.c
+++ b/core/arch/arm/mm/core_mmu.c
@@ -101,6 +101,10 @@ static struct memaccess_area nsec_shared[] = {
MEMACCESS_AREA(CFG_SHMEM_START, CFG_SHMEM_SIZE),
};
+#ifdef CFG_TEE_SDP_MEM_BASE
+register_sdp_mem(CFG_TEE_SDP_MEM_BASE, CFG_TEE_SDP_MEM_SIZE);
+#endif
+
register_phys_mem(MEM_AREA_TEE_RAM, CFG_TEE_RAM_START, CFG_TEE_RAM_PH_SIZE);
register_phys_mem(MEM_AREA_TA_RAM, CFG_TA_RAM_START, CFG_TA_RAM_SIZE);
register_phys_mem(MEM_AREA_NSEC_SHM, CFG_SHMEM_START, CFG_SHMEM_SIZE);
@@ -222,6 +226,107 @@ static struct tee_mmap_region *find_map_by_pa(unsigned long pa)
return NULL;
}
+#ifdef CFG_SECURE_DATA_PATH
+extern const struct core_mmu_phys_mem __start_phys_sdp_mem_section;
+extern const struct core_mmu_phys_mem __end_phys_sdp_mem_section;
+
+static bool pbuf_is_sdp_mem(paddr_t pbuf, size_t len)
+{
+ const struct core_mmu_phys_mem *mem;
+
+ for (mem = &__start_phys_sdp_mem_section;
+ mem < &__end_phys_sdp_mem_section; mem++)
+ if (core_is_buffer_inside(pbuf, len, mem->addr, mem->size))
+ return true;
+
+ return false;
+}
+
+#define MSG_SDP_INSTERSECT(pa1, sz1, pa2, sz2) \
+ EMSG("[%" PRIxPA " %" PRIxPA "] intersecs [%" PRIxPA " %" PRIxPA "]", \
+ pa1, pa1 + sz1, pa2, pa2 + sz2)
+
+/* Check SDP memories comply with registered memories */
+static void verify_sdp_mem_areas(struct tee_mmap_region *mem_map, size_t len)
+{
+ const struct core_mmu_phys_mem *mem;
+ const struct core_mmu_phys_mem *mem2;
+ const struct core_mmu_phys_mem *start = &__start_phys_sdp_mem_section;
+ const struct core_mmu_phys_mem *end = &__end_phys_sdp_mem_section;
+ struct tee_mmap_region *mmap;
+ size_t n;
+
+ if (start == end) {
+ IMSG("Secure data path enabled without any SDP memory area");
+ return;
+ }
+
+ for (mem = start; mem < end; mem++)
+ DMSG("SDP memory [%" PRIxPA " %" PRIxPA "]",
+ mem->addr, mem->addr + mem->size);
+
+ /* Check SDP memories do not intersect each other */
+ for (mem = start; mem < end - 1; mem++) {
+ for (mem2 = mem + 1; mem2 < end; mem2++) {
+ if (core_is_buffer_intersect(mem2->addr, mem2->size,
+ mem->addr, mem->size)) {
+ MSG_SDP_INSTERSECT(mem2->addr, mem2->size,
+ mem->addr, mem->size);
+ panic("SDP memory intersection");
+ }
+ }
+ }
+
+ /*
+ * Check SDP memories do not intersect any mapped memory.
+ * This is called before reserved VA space is loaded in mem_map.
+ */
+ for (mem = start; mem < end; mem++) {
+ for (mmap = mem_map, n = 0; n < len; mmap++, n++) {
+ if (core_is_buffer_intersect(mem->addr, mem->size,
+ mmap->pa, mmap->size)) {
+ MSG_SDP_INSTERSECT(mem->addr, mem->size,
+ mmap->pa, mmap->size);
+ panic("SDP memory intersection");
+ }
+ }
+ }
+}
+
+struct mobj **core_sdp_mem_create_mobjs(void)
+{
+ const struct core_mmu_phys_mem *mem;
+ struct mobj **mobj_base;
+ struct mobj **mobj;
+ int cnt = &__end_phys_sdp_mem_section - &__start_phys_sdp_mem_section;
+
+ /* SDP mobjs table must end with a NULL entry */
+ mobj_base = calloc(cnt + 1, sizeof(struct mobj *));
+ if (!mobj_base)
+ panic("Out of memory");
+
+ for (mem = &__start_phys_sdp_mem_section, mobj = mobj_base;
+ mem < &__end_phys_sdp_mem_section; mem++, mobj++) {
+ *mobj = mobj_phys_alloc(mem->addr, mem->size,
+ TEE_MATTR_CACHE_CACHED,
+ CORE_MEM_SDP_MEM);
+ if (!*mobj)
+ panic("can't create SDP physical memory object");
+ }
+ return mobj_base;
+}
+#else /* CFG_SECURE_DATA_PATH */
+static bool pbuf_is_sdp_mem(paddr_t pbuf __unused, size_t len __unused)
+{
+ return false;
+}
+
+static void verify_sdp_mem_areas(struct tee_mmap_region *mem_map __unused,
+ size_t len __unused)
+{
+}
+#endif /* CFG_SECURE_DATA_PATH */
+
extern const struct core_mmu_phys_mem __start_phys_mem_map_section;
extern const struct core_mmu_phys_mem __end_phys_mem_map_section;
@@ -353,6 +458,8 @@ static void init_mem_map(struct tee_mmap_region *memory_map, size_t num_elems)
add_phys_mem(memory_map, num_elems, &m, &last);
}
+ verify_sdp_mem_areas(memory_map, num_elems);
+
add_va_space(memory_map, num_elems, MEM_AREA_RES_VASPACE,
RES_VASPACE_SIZE, &last);
@@ -382,7 +489,7 @@ static void init_mem_map(struct tee_mmap_region *memory_map, size_t num_elems)
assert(map->type == MEM_AREA_TEE_RAM);
map->va = map->pa;
#ifdef CFG_WITH_PAGER
- map->region_size = SMALL_PAGE_SIZE,
+ map->region_size = SMALL_PAGE_SIZE;
#endif
map->attr = core_mmu_type_to_attr(map->type);
@@ -393,6 +500,7 @@ static void init_mem_map(struct tee_mmap_region *memory_map, size_t num_elems)
while (map->type != MEM_AREA_NOTYPE) {
map->attr = core_mmu_type_to_attr(map->type);
va -= map->size;
+ va = ROUNDDOWN(va, map->region_size);
map->va = va;
map++;
}
@@ -413,6 +521,7 @@ static void init_mem_map(struct tee_mmap_region *memory_map, size_t num_elems)
map++;
while (map->type != MEM_AREA_NOTYPE) {
map->attr = core_mmu_type_to_attr(map->type);
+ va = ROUNDUP(va, map->region_size);
map->va = va;
va += map->size;
map++;
@@ -541,6 +650,8 @@ bool core_pbuf_is(uint32_t attr, paddr_t pbuf, size_t len)
return pbuf_inside_map_area(pbuf, len, map_ta_ram);
case CORE_MEM_NSEC_SHM:
return pbuf_inside_map_area(pbuf, len, map_nsec_shm);
+ case CORE_MEM_SDP_MEM:
+ return pbuf_is_sdp_mem(pbuf, len);
case CORE_MEM_EXTRAM:
return pbuf_is_inside(ddr, pbuf, len);
case CORE_MEM_CACHED:
@@ -648,7 +759,7 @@ int core_tlb_maintenance(int op, unsigned int a)
return 0;
}
-unsigned int cache_maintenance_l1(int op, void *va, size_t len)
+TEE_Result cache_op_inner(enum cache_op op, void *va, size_t len)
{
switch (op) {
case DCACHE_CLEAN:
@@ -672,10 +783,6 @@ unsigned int cache_maintenance_l1(int op, void *va, size_t len)
if (len)
arm_cl1_i_inv(va, (char *)va + len - 1);
break;
- case WRITE_BUFFER_DRAIN:
- DMSG("unsupported operation 0x%X (WRITE_BUFFER_DRAIN)",
- (unsigned int)op);
- return -1;
case DCACHE_CLEAN_INV:
arm_cl1_d_cleaninvbysetway();
break;
@@ -690,31 +797,31 @@ unsigned int cache_maintenance_l1(int op, void *va, size_t len)
}
#ifdef CFG_PL310
-unsigned int cache_maintenance_l2(int op, paddr_t pa, size_t len)
+TEE_Result cache_op_outer(enum cache_op op, paddr_t pa, size_t len)
{
- unsigned int ret = TEE_SUCCESS;
- uint32_t exceptions = thread_mask_exceptions(THREAD_EXCP_IRQ);
+ TEE_Result ret = TEE_SUCCESS;
+ uint32_t exceptions = thread_mask_exceptions(THREAD_EXCP_FOREIGN_INTR);
tee_l2cc_mutex_lock();
switch (op) {
- case L2CACHE_INVALIDATE:
+ case DCACHE_INVALIDATE:
arm_cl2_invbyway(pl310_base());
break;
- case L2CACHE_AREA_INVALIDATE:
+ case DCACHE_AREA_INVALIDATE:
if (len)
arm_cl2_invbypa(pl310_base(), pa, pa + len - 1);
break;
- case L2CACHE_CLEAN:
+ case DCACHE_CLEAN:
arm_cl2_cleanbyway(pl310_base());
break;
- case L2CACHE_AREA_CLEAN:
+ case DCACHE_AREA_CLEAN:
if (len)
arm_cl2_cleanbypa(pl310_base(), pa, pa + len - 1);
break;
- case L2CACHE_CLEAN_INV:
+ case DCACHE_CLEAN_INV:
arm_cl2_cleaninvbyway(pl310_base());
break;
- case L2CACHE_AREA_CLEAN_INV:
+ case DCACHE_AREA_CLEAN_INV:
if (len)
arm_cl2_cleaninvbypa(pl310_base(), pa, pa + len - 1);
break;
@@ -1163,6 +1270,21 @@ void *phys_to_virt(paddr_t pa, enum teecore_memtypes m)
return va;
}
+void *phys_to_virt_io(paddr_t pa)
+{
+ struct tee_mmap_region *map;
+ void *va;
+
+ map = find_map_by_type_and_pa(MEM_AREA_IO_SEC, pa);
+ if (!map)
+ map = find_map_by_type_and_pa(MEM_AREA_IO_NSEC, pa);
+ if (!map)
+ return NULL;
+ va = map_pa2va(map, pa);
+ check_va_matches_pa(pa, va);
+ return va;
+}
+
bool cpu_mmu_enabled(void)
{
uint32_t sctlr;
diff --git a/core/arch/arm/mm/core_mmu_lpae.c b/core/arch/arm/mm/core_mmu_lpae.c
index eb96c70..7a5d74a 100644
--- a/core/arch/arm/mm/core_mmu_lpae.c
+++ b/core/arch/arm/mm/core_mmu_lpae.c
@@ -640,7 +640,7 @@ bool core_mmu_find_table(vaddr_t va, unsigned max_level,
if (!tbl)
return false;
- va_base += n << level_size_shift;
+ va_base += (vaddr_t)n << level_size_shift;
level++;
num_entries = XLAT_TABLE_ENTRIES;
}
diff --git a/core/arch/arm/mm/mobj.c b/core/arch/arm/mm/mobj.c
index 5458638..6daef50 100644
--- a/core/arch/arm/mm/mobj.c
+++ b/core/arch/arm/mm/mobj.c
@@ -114,12 +114,13 @@ static bool mobj_phys_matches(struct mobj *mobj, enum buf_is_attr attr)
switch (attr) {
case CORE_MEM_SEC:
return a == CORE_MEM_SEC || a == CORE_MEM_TEE_RAM ||
- a == CORE_MEM_TA_RAM;
+ a == CORE_MEM_TA_RAM || a == CORE_MEM_SDP_MEM;
case CORE_MEM_NON_SEC:
return a == CORE_MEM_NSEC_SHM;
case CORE_MEM_TEE_RAM:
case CORE_MEM_TA_RAM:
case CORE_MEM_NSEC_SHM:
+ case CORE_MEM_SDP_MEM:
return attr == a;
default:
return false;
@@ -151,6 +152,7 @@ struct mobj *mobj_phys_alloc(paddr_t pa, size_t size, uint32_t cattr,
enum buf_is_attr battr)
{
struct mobj_phys *moph;
+ enum teecore_memtypes area_type;
void *va;
if ((pa & CORE_MMU_USER_PARAM_MASK) ||
@@ -159,8 +161,27 @@ struct mobj *mobj_phys_alloc(paddr_t pa, size_t size, uint32_t cattr,
return NULL;
}
- va = phys_to_virt(pa, battr);
- if (!va)
+ switch (battr) {
+ case CORE_MEM_TEE_RAM:
+ area_type = MEM_AREA_TEE_RAM;
+ break;
+ case CORE_MEM_TA_RAM:
+ area_type = MEM_AREA_TA_RAM;
+ break;
+ case CORE_MEM_NSEC_SHM:
+ area_type = MEM_AREA_NSEC_SHM;
+ break;
+ case CORE_MEM_SDP_MEM:
+ area_type = MEM_AREA_SDP_MEM;
+ break;
+ default:
+ DMSG("can't allocate with specified attribute");
+ return NULL;
+ }
+
+ /* Only SDP memory may not have a virtual address */
+ va = phys_to_virt(pa, area_type);
+ if (!va && battr != CORE_MEM_SDP_MEM)
return NULL;
moph = calloc(1, sizeof(*moph));
diff --git a/core/arch/arm/mm/tee_pager.c b/core/arch/arm/mm/tee_pager.c
index c7238fe..c75eee8 100644
--- a/core/arch/arm/mm/tee_pager.c
+++ b/core/arch/arm/mm/tee_pager.c
@@ -891,10 +891,10 @@ bool tee_pager_set_uta_area_attr(struct user_ta_ctx *utc, vaddr_t base,
void *va = (void *)area_idx2va(pmem->area,
pmem->pgidx);
- cache_maintenance_l1(DCACHE_AREA_CLEAN, va,
- SMALL_PAGE_SIZE);
- cache_maintenance_l1(ICACHE_AREA_INVALIDATE, va,
- SMALL_PAGE_SIZE);
+ cache_op_inner(DCACHE_AREA_CLEAN, va,
+ SMALL_PAGE_SIZE);
+ cache_op_inner(ICACHE_AREA_INVALIDATE, va,
+ SMALL_PAGE_SIZE);
}
}
@@ -1269,10 +1269,9 @@ bool tee_pager_handle_fault(struct abort_info *ai)
* Doing these operations to LoUIS (Level of
* unification, Inner Shareable) would be enough
*/
- cache_maintenance_l1(DCACHE_AREA_CLEAN,
- pmem->va_alias, SMALL_PAGE_SIZE);
-
- cache_maintenance_l1(ICACHE_INVALIDATE, NULL, 0);
+ cache_op_inner(DCACHE_AREA_CLEAN, pmem->va_alias,
+ SMALL_PAGE_SIZE);
+ cache_op_inner(ICACHE_INVALIDATE, NULL, 0);
}
pmem->area = area;
diff --git a/core/arch/arm/plat-d02/main.c b/core/arch/arm/plat-d02/main.c
index 95161d1..2cd339b 100644
--- a/core/arch/arm/plat-d02/main.c
+++ b/core/arch/arm/plat-d02/main.c
@@ -42,7 +42,7 @@ static void main_fiq(void);
static const struct thread_handlers handlers = {
.std_smc = tee_entry_std,
.fast_smc = tee_entry_fast,
- .fiq = main_fiq,
+ .nintr = main_fiq,
.cpu_on = cpu_on_handler,
.cpu_off = pm_do_nothing,
.cpu_suspend = pm_do_nothing,
@@ -51,6 +51,8 @@ static const struct thread_handlers handlers = {
.system_reset = pm_do_nothing,
};
+static struct hi16xx_uart_data console_data __early_bss;
+
register_phys_mem(MEM_AREA_IO_NSEC, CONSOLE_UART_BASE, HI16XX_UART_REG_SIZE);
const struct thread_handlers *generic_boot_get_handlers(void)
@@ -63,34 +65,9 @@ static void main_fiq(void)
panic();
}
-static vaddr_t console_base(void)
-{
- static void *va;
-
- if (cpu_mmu_enabled()) {
- if (!va)
- va = phys_to_virt(CONSOLE_UART_BASE, MEM_AREA_IO_NSEC);
- return (vaddr_t)va;
- }
- return CONSOLE_UART_BASE;
-}
-
void console_init(void)
{
- hi16xx_uart_init(console_base(), CONSOLE_UART_CLK_IN_HZ,
- CONSOLE_BAUDRATE);
-}
-
-void console_putc(int ch)
-{
- vaddr_t base = console_base();
-
- if (ch == '\n')
- hi16xx_uart_putc('\r', base);
- hi16xx_uart_putc(ch, base);
-}
-
-void console_flush(void)
-{
- hi16xx_uart_flush(console_base());
+ hi16xx_uart_init(&console_data, CONSOLE_UART_BASE,
+ CONSOLE_UART_CLK_IN_HZ, CONSOLE_BAUDRATE);
+ register_serial_console(&console_data.chip);
}
diff --git a/core/arch/arm/plat-hikey/main.c b/core/arch/arm/plat-hikey/main.c
index 36789ce..8d72f38 100644
--- a/core/arch/arm/plat-hikey/main.c
+++ b/core/arch/arm/plat-hikey/main.c
@@ -49,7 +49,7 @@ static void main_fiq(void);
static const struct thread_handlers handlers = {
.std_smc = tee_entry_std,
.fast_smc = tee_entry_fast,
- .fiq = main_fiq,
+ .nintr = main_fiq,
.cpu_on = cpu_on_handler,
.cpu_off = pm_do_nothing,
.cpu_suspend = pm_do_nothing,
@@ -58,6 +58,8 @@ static const struct thread_handlers handlers = {
.system_reset = pm_do_nothing,
};
+static struct pl011_data console_data __early_bss;
+
register_phys_mem(MEM_AREA_IO_NSEC, CONSOLE_UART_BASE, PL011_REG_SIZE);
register_phys_mem(MEM_AREA_IO_NSEC, PMUSSI_BASE, PMUSSI_REG_SIZE);
#ifdef CFG_SPI
@@ -78,35 +80,11 @@ static void main_fiq(void)
panic();
}
-static vaddr_t console_base(void)
-{
- static void *va;
-
- if (cpu_mmu_enabled()) {
- if (!va)
- va = phys_to_virt(CONSOLE_UART_BASE, MEM_AREA_IO_NSEC);
- return (vaddr_t)va;
- }
- return CONSOLE_UART_BASE;
-}
-
void console_init(void)
{
- pl011_init(console_base(), CONSOLE_UART_CLK_IN_HZ, CONSOLE_BAUDRATE);
-}
-
-void console_putc(int ch)
-{
- vaddr_t base = console_base();
-
- if (ch == '\n')
- pl011_putc('\r', base);
- pl011_putc(ch, base);
-}
-
-void console_flush(void)
-{
- pl011_flush(console_base());
+ pl011_init(&console_data, CONSOLE_UART_BASE, CONSOLE_UART_CLK_IN_HZ,
+ CONSOLE_BAUDRATE);
+ register_serial_console(&console_data.chip);
}
vaddr_t nsec_periph_base(paddr_t pa)
diff --git a/core/arch/arm/plat-imx/a9_plat_init.S b/core/arch/arm/plat-imx/a9_plat_init.S
index 64d03f5..db13018 100644
--- a/core/arch/arm/plat-imx/a9_plat_init.S
+++ b/core/arch/arm/plat-imx/a9_plat_init.S
@@ -85,7 +85,7 @@ UNWIND( .fnstart)
* - NSec cannot access PLE (PLE bit16=0)
* - NSec can use SIMD/VFP (CP10/CP11) (bit15:14=2b00, bit11:10=2b11)
*
- * PCR = 0x00000001
+ * PCR
* - no change latency, enable clk gating
*/
movw r0, #0x4000
@@ -100,8 +100,8 @@ UNWIND( .fnstart)
movt r0, #0x0002
write_nsacr r0
- movw r0, #0x0000
- movt r0, #0x0001
+ read_pcr r0
+ orr r0, r0, #0x1
write_pcr r0
mov pc, lr
diff --git a/core/arch/arm/plat-imx/conf.mk b/core/arch/arm/plat-imx/conf.mk
index 785736a..d780228 100644
--- a/core/arch/arm/plat-imx/conf.mk
+++ b/core/arch/arm/plat-imx/conf.mk
@@ -3,7 +3,7 @@ PLATFORM_FLAVOR ?= mx6ulevk
ifeq ($(PLATFORM_FLAVOR),mx6ulevk)
arm32-platform-cpuarch := cortex-a7
endif
-ifeq ($(PLATFORM_FLAVOR),$(filter $(PLATFORM_FLAVOR),mx6qsabrelite mx6qsabresd))
+ifeq ($(PLATFORM_FLAVOR),$(filter $(PLATFORM_FLAVOR),mx6qsabrelite mx6qsabresd mx6dlsabresd))
arm32-platform-cpuarch := cortex-a9
endif
arm32-platform-cflags += -mcpu=$(arm32-platform-cpuarch)
@@ -19,7 +19,7 @@ $(call force,CFG_WITH_SOFTWARE_PRNG,y)
ifeq ($(PLATFORM_FLAVOR),mx6ulevk)
$(call force,CFG_SECURE_TIME_SOURCE_CNTPCT,y)
endif
-ifeq ($(PLATFORM_FLAVOR),$(filter $(PLATFORM_FLAVOR),mx6qsabrelite mx6qsabresd))
+ifeq ($(PLATFORM_FLAVOR),$(filter $(PLATFORM_FLAVOR),mx6qsabrelite mx6qsabresd mx6dlsabresd))
$(call force,CFG_PL310,y)
$(call force,CFG_PL310_LOCKED,y)
$(call force,CFG_SECURE_TIME_SOURCE_REE,y)
diff --git a/core/arch/arm/plat-imx/main.c b/core/arch/arm/plat-imx/main.c
index edfbc37..36750a2 100644
--- a/core/arch/arm/plat-imx/main.c
+++ b/core/arch/arm/plat-imx/main.c
@@ -45,7 +45,8 @@
#include <tee/entry_std.h>
#if defined(PLATFORM_FLAVOR_mx6qsabrelite) || \
- defined(PLATFORM_FLAVOR_mx6qsabresd)
+ defined(PLATFORM_FLAVOR_mx6qsabresd) || \
+ defined(PLATFORM_FLAVOR_mx6dlsabresd)
#include <kernel/tz_ssvce_pl310.h>
#endif
@@ -55,7 +56,7 @@ static struct gic_data gic_data;
static const struct thread_handlers handlers = {
.std_smc = tee_entry_std,
.fast_smc = tee_entry_fast,
- .fiq = main_fiq,
+ .nintr = main_fiq,
.cpu_on = pm_panic,
.cpu_off = pm_panic,
.cpu_suspend = pm_panic,
@@ -64,11 +65,14 @@ static const struct thread_handlers handlers = {
.system_reset = pm_panic,
};
+static struct imx_uart_data console_data __early_bss;
+
register_phys_mem(MEM_AREA_IO_NSEC, CONSOLE_UART_BASE, CORE_MMU_DEVICE_SIZE);
register_phys_mem(MEM_AREA_IO_SEC, GIC_BASE, CORE_MMU_DEVICE_SIZE);
#if defined(PLATFORM_FLAVOR_mx6qsabrelite) || \
- defined(PLATFORM_FLAVOR_mx6qsabresd)
+ defined(PLATFORM_FLAVOR_mx6qsabresd) || \
+ defined(PLATFORM_FLAVOR_mx6dlsabresd)
register_phys_mem(MEM_AREA_IO_SEC, PL310_BASE, CORE_MMU_DEVICE_SIZE);
register_phys_mem(MEM_AREA_IO_SEC, SRC_BASE, CORE_MMU_DEVICE_SIZE);
#endif
@@ -84,7 +88,8 @@ static void main_fiq(void)
}
#if defined(PLATFORM_FLAVOR_mx6qsabrelite) || \
- defined(PLATFORM_FLAVOR_mx6qsabresd)
+ defined(PLATFORM_FLAVOR_mx6qsabresd) || \
+ defined(PLATFORM_FLAVOR_mx6dlsabresd)
void plat_cpu_reset_late(void)
{
uintptr_t addr;
@@ -126,41 +131,10 @@ void plat_cpu_reset_late(void)
}
#endif
-static vaddr_t console_base(void)
-{
- static void *va;
-
- if (cpu_mmu_enabled()) {
- if (!va)
- va = phys_to_virt(CONSOLE_UART_BASE,
- MEM_AREA_IO_NSEC);
- return (vaddr_t)va;
- }
- return CONSOLE_UART_BASE;
-}
-
void console_init(void)
{
- vaddr_t base = console_base();
-
- imx_uart_init(base);
-}
-
-void console_putc(int ch)
-{
- vaddr_t base = console_base();
-
- /* If \n, also do \r */
- if (ch == '\n')
- imx_uart_putc('\r', base);
- imx_uart_putc(ch, base);
-}
-
-void console_flush(void)
-{
- vaddr_t base = console_base();
-
- imx_uart_flush_tx_fifo(base);
+ imx_uart_init(&console_data, CONSOLE_UART_BASE);
+ register_serial_console(&console_data.chip);
}
void main_init_gic(void)
@@ -182,7 +156,8 @@ void main_init_gic(void)
}
#if defined(PLATFORM_FLAVOR_mx6qsabrelite) || \
- defined(PLATFORM_FLAVOR_mx6qsabresd)
+ defined(PLATFORM_FLAVOR_mx6qsabresd) || \
+ defined(PLATFORM_FLAVOR_mx6dlsabresd)
vaddr_t pl310_base(void)
{
static void *va __early_bss;
diff --git a/core/arch/arm/plat-imx/platform_config.h b/core/arch/arm/plat-imx/platform_config.h
index 8e55ee8..b92322e 100644
--- a/core/arch/arm/plat-imx/platform_config.h
+++ b/core/arch/arm/plat-imx/platform_config.h
@@ -113,7 +113,8 @@
/* For i.MX6 Quad SABRE Lite and Smart Device board */
#elif defined(PLATFORM_FLAVOR_mx6qsabrelite) || \
- defined(PLATFORM_FLAVOR_mx6qsabresd)
+ defined(PLATFORM_FLAVOR_mx6qsabresd) || \
+ defined(PLATFORM_FLAVOR_mx6dlsabresd)
#define SCU_BASE 0x00A00000
#define PL310_BASE 0x00A02000
@@ -128,8 +129,16 @@
#define GICD_OFFSET 0x1000
#define GIC_CPU_BASE (GIC_BASE + GICC_OFFSET)
#define GIC_DIST_BASE (GIC_BASE + GICD_OFFSET)
+
+#if defined(PLATFORM_FLAVOR_mx6qsabrelite) || \
+ defined(PLATFORM_FLAVOR_mx6qsabresd)
#define UART1_BASE 0x02020000
#define UART2_BASE 0x021E8000
+#else
+#define UART1_BASE 0x02020000
+#define UART3_BASE 0x021EC000
+#define UART5_BASE 0x021F4000
+#endif
/* Central Security Unit register values */
#define CSU_BASE 0x021C0000
@@ -146,12 +155,20 @@
#if defined(PLATFORM_FLAVOR_mx6qsabresd)
#define CONSOLE_UART_BASE UART1_BASE
#endif
+#if defined(PLATFORM_FLAVOR_mx6dlsabresd)
+#define CONSOLE_UART_BASE UART1_BASE
+#endif
#define DRAM0_BASE 0x10000000
#define DRAM0_SIZE 0x40000000
#define CFG_TEE_RAM_VA_SIZE (1024 * 1024)
+#if defined(PLATFORM_FLAVOR_mx6qsabrelite) || \
+ defined(PLATFORM_FLAVOR_mx6qsabresd)
#define CFG_TEE_CORE_NB_CORE 4
+#else
+#define CFG_TEE_CORE_NB_CORE 2
+#endif
#define DDR_PHYS_START DRAM0_BASE
#define DDR_SIZE DRAM0_SIZE
@@ -200,7 +217,12 @@
* Full Line Zero (FLZ) disabled (bit0=0)
*/
#ifndef PL310_AUX_CTRL_INIT
+#if defined(PLATFORM_FLAVOR_mx6qsabrelite) || \
+ defined(PLATFORM_FLAVOR_mx6qsabresd)
#define PL310_AUX_CTRL_INIT 0x3C470800
+#else
+#define PL310_AUX_CTRL_INIT 0x3C440800
+#endif
#endif
/*
@@ -384,7 +406,12 @@
* Cacheable accesses have high prio (bit10=0)
* Full Line Zero (FLZ) disabled (bit0=0)
*/
+#if defined(PLATFORM_FLAVOR_mx6qsabrelite) || \
+ defined(PLATFORM_FLAVOR_mx6qsabresd)
#define PL310_AUX_CTRL_INIT 0x3C470800
+#else
+#define PL310_AUX_CTRL_INIT 0x3C440800
+#endif
/*
* Prefetch Control Register
diff --git a/core/arch/arm/plat-imx/psci.c b/core/arch/arm/plat-imx/psci.c
index 065555b..12b60fb 100644
--- a/core/arch/arm/plat-imx/psci.c
+++ b/core/arch/arm/plat-imx/psci.c
@@ -43,7 +43,8 @@
static vaddr_t src_base(void)
{
- static void *va __data; /* in case it's used before .bss is cleared */
+ /* in case it's used before .bss is cleared */
+ static void *va __early_bss;
if (cpu_mmu_enabled()) {
if (!va)
diff --git a/core/arch/arm/plat-imx/sub.mk b/core/arch/arm/plat-imx/sub.mk
index d0a2f51..75a2fbc 100644
--- a/core/arch/arm/plat-imx/sub.mk
+++ b/core/arch/arm/plat-imx/sub.mk
@@ -6,4 +6,5 @@ srcs-$(CFG_PSCI_ARM32) += psci.c
srcs-$(PLATFORM_FLAVOR_mx6qsabrelite) += a9_plat_init.S
srcs-$(PLATFORM_FLAVOR_mx6qsabresd) += a9_plat_init.S
+srcs-$(PLATFORM_FLAVOR_mx6dlsabresd) += a9_plat_init.S
srcs-$(PLATFORM_FLAVOR_mx6ulevk) += imx6ul.c
diff --git a/core/arch/arm/plat-ls/main.c b/core/arch/arm/plat-ls/main.c
index 23ac0c6..7f8d523 100644
--- a/core/arch/arm/plat-ls/main.c
+++ b/core/arch/arm/plat-ls/main.c
@@ -48,7 +48,7 @@ static void main_fiq(void);
static const struct thread_handlers handlers = {
.std_smc = tee_entry_std,
.fast_smc = tee_entry_fast,
- .fiq = main_fiq,
+ .nintr = main_fiq,
.cpu_on = pm_panic,
.cpu_off = pm_panic,
.cpu_suspend = pm_panic,
@@ -58,6 +58,7 @@ static const struct thread_handlers handlers = {
};
static struct gic_data gic_data;
+static struct ns16550_data console_data __early_bss;
register_phys_mem(MEM_AREA_IO_NSEC, CONSOLE_UART_BASE, CORE_MMU_DEVICE_SIZE);
register_phys_mem(MEM_AREA_IO_SEC, GIC_BASE, CORE_MMU_DEVICE_SIZE);
@@ -120,38 +121,10 @@ void plat_cpu_reset_late(void)
}
}
-static vaddr_t console_base(void)
-{
- static void *va __early_bss;
-
- if (cpu_mmu_enabled()) {
- if (!va)
- va = phys_to_virt(CONSOLE_UART_BASE, MEM_AREA_IO_NSEC);
- return (vaddr_t)va;
- }
- return CONSOLE_UART_BASE;
-}
-
void console_init(void)
{
- /*
- * Do nothing, uart driver shared with normal world,
- * everything for uart driver intialization is done in bootloader.
- */
-}
-
-void console_putc(int ch)
-{
- vaddr_t base = console_base();
-
- if (ch == '\n')
- ns16550_putc('\r', base);
- ns16550_putc(ch, base);
-}
-
-void console_flush(void)
-{
- ns16550_flush(console_base());
+ ns16550_init(&console_data, CONSOLE_UART_BASE);
+ register_serial_console(&console_data.chip);
}
void main_init_gic(void)
diff --git a/core/arch/arm/plat-ls/plat_init.S b/core/arch/arm/plat-ls/plat_init.S
index 81ba7d7..8813480 100644
--- a/core/arch/arm/plat-ls/plat_init.S
+++ b/core/arch/arm/plat-ls/plat_init.S
@@ -69,23 +69,20 @@ UNWIND( .fnstart)
*
* SCTLR = 0x00000000
*
- * ACTRL = 0x00000041
- * - core always in full SMP (FW bit0=1)
+ * ACTRL = 0x00000040
+ * - core NOT booted in full SMP (FW bit0=0)
*
- * NSACR = 0x00020C00
+ * NSACR = 0x00000C00
* - NSec cannot change ACTRL.SMP (NS_SMP bit18=0)
* - NSec can use SIMD/VFP (CP10/CP11) (bit15:14=2b00, bit11:10=2b11)
*/
- movw r0, #0x0000
- movt r0, #0x0000
+ mov_imm r0, 0x00000000
write_sctlr r0
- movw r0, #0x0040
- movt r0, #0x0000
+ mov_imm r0, 0x00000040
write_actlr r0
- movw r0, #0x0C00
- movt r0, #0x0000
+ mov_imm r0, 0x00000C00
write_nsacr r0
mov pc, lr
diff --git a/core/arch/arm/plat-mediatek/main.c b/core/arch/arm/plat-mediatek/main.c
index 7780591..62180fc 100644
--- a/core/arch/arm/plat-mediatek/main.c
+++ b/core/arch/arm/plat-mediatek/main.c
@@ -41,7 +41,7 @@ static void main_fiq(void);
static const struct thread_handlers handlers = {
.std_smc = tee_entry_std,
.fast_smc = tee_entry_fast,
- .fiq = main_fiq,
+ .nintr = main_fiq,
.cpu_on = cpu_on_handler,
.cpu_off = pm_do_nothing,
.cpu_suspend = pm_do_nothing,
@@ -50,6 +50,8 @@ static const struct thread_handlers handlers = {
.system_reset = pm_do_nothing,
};
+static struct serial8250_uart_data console_data __early_bss;
+
const struct thread_handlers *generic_boot_get_handlers(void)
{
return &handlers;
@@ -60,34 +62,9 @@ static void main_fiq(void)
panic();
}
-static vaddr_t console_base(void)
-{
- static void *va;
-
- if (cpu_mmu_enabled()) {
- if (!va)
- va = phys_to_virt(CONSOLE_UART_BASE, MEM_AREA_IO_NSEC);
- return (vaddr_t)va;
- }
- return CONSOLE_UART_BASE;
-}
-
void console_init(void)
{
- serial8250_uart_init(console_base(), CONSOLE_UART_CLK_IN_HZ,
- CONSOLE_BAUDRATE);
-}
-
-void console_putc(int ch)
-{
- vaddr_t base = console_base();
-
- if (ch == '\n')
- serial8250_uart_putc('\r', base);
- serial8250_uart_putc(ch, base);
-}
-
-void console_flush(void)
-{
- serial8250_uart_flush_tx_fifo(console_base());
+ serial8250_uart_init(&console_data, CONSOLE_UART_BASE,
+ CONSOLE_UART_CLK_IN_HZ, CONSOLE_BAUDRATE);
+ register_serial_console(&console_data.chip);
}
diff --git a/core/arch/arm/plat-rcar/main.c b/core/arch/arm/plat-rcar/main.c
index 8f9482e..6a7e332 100644
--- a/core/arch/arm/plat-rcar/main.c
+++ b/core/arch/arm/plat-rcar/main.c
@@ -46,7 +46,7 @@ static void main_fiq(void);
static const struct thread_handlers handlers = {
.std_smc = tee_entry_std,
.fast_smc = tee_entry_fast,
- .fiq = main_fiq,
+ .nintr = main_fiq,
.cpu_on = cpu_on_handler,
.cpu_off = pm_do_nothing,
.cpu_suspend = pm_do_nothing,
@@ -55,6 +55,8 @@ static const struct thread_handlers handlers = {
.system_reset = pm_do_nothing,
};
+static struct scif_uart_data console_data __early_bss;
+
const struct thread_handlers *generic_boot_get_handlers(void)
{
return &handlers;
@@ -65,31 +67,8 @@ static void main_fiq(void)
panic();
}
-static vaddr_t console_base(void)
-{
- static void *va;
-
- if (cpu_mmu_enabled()) {
- if (!va)
- va = phys_to_virt(CONSOLE_UART_BASE, MEM_AREA_IO_SEC);
- return (vaddr_t)va;
- }
- return CONSOLE_UART_BASE;
-}
-
void console_init(void)
{
- scif_uart_init(console_base());
-}
-
-void console_putc(int ch)
-{
- if (ch == '\n')
- scif_uart_putc('\r', console_base());
- scif_uart_putc(ch, console_base());
-}
-
-void console_flush(void)
-{
- scif_uart_flush(console_base());
+ scif_uart_init(&console_data, CONSOLE_UART_BASE);
+ register_serial_console(&console_data.chip);
}
diff --git a/core/arch/arm/plat-rpi3/conf.mk b/core/arch/arm/plat-rpi3/conf.mk
index 567680a..49fa817 100644
--- a/core/arch/arm/plat-rpi3/conf.mk
+++ b/core/arch/arm/plat-rpi3/conf.mk
@@ -25,7 +25,6 @@ CFG_CRYPTO_WITH_CE ?= n
CFG_WITH_STACK_CANARIES ?= y
CFG_TEE_CORE_EMBED_INTERNAL_TESTS ?= y
-CFG_TEE_FS_KEY_MANAGER_TEST ?= y
CFG_WITH_STACK_CANARIES ?= y
CFG_WITH_STATS ?= y
diff --git a/core/arch/arm/plat-rpi3/main.c b/core/arch/arm/plat-rpi3/main.c
index 9270e19..8a714cb 100644
--- a/core/arch/arm/plat-rpi3/main.c
+++ b/core/arch/arm/plat-rpi3/main.c
@@ -45,7 +45,7 @@ static void main_fiq(void)
static const struct thread_handlers handlers = {
.std_smc = tee_entry_std,
.fast_smc = tee_entry_fast,
- .fiq = main_fiq,
+ .nintr = main_fiq,
.cpu_on = cpu_on_handler,
.cpu_off = pm_do_nothing,
.cpu_suspend = pm_do_nothing,
@@ -54,41 +54,16 @@ static const struct thread_handlers handlers = {
.system_reset = pm_do_nothing,
};
+static struct serial8250_uart_data console_data __early_bss;
+
const struct thread_handlers *generic_boot_get_handlers(void)
{
return &handlers;
}
-static vaddr_t console_base(void)
-{
- static vaddr_t va;
-
- if (cpu_mmu_enabled()) {
- if (!va)
- va = (vaddr_t)phys_to_virt(CONSOLE_UART_BASE,
- MEM_AREA_IO_NSEC);
- return va;
- }
-
- return CONSOLE_UART_BASE;
-}
-
-void console_putc(int ch)
-{
- vaddr_t base = console_base();
-
- if (ch == '\n')
- serial8250_uart_putc('\r', base);
- serial8250_uart_putc(ch, base);
-}
-
void console_init(void)
{
- serial8250_uart_init(console_base(), CONSOLE_UART_CLK_IN_HZ,
- CONSOLE_BAUDRATE);
-}
-
-void console_flush(void)
-{
- serial8250_uart_flush_tx_fifo(console_base());
+ serial8250_uart_init(&console_data, CONSOLE_UART_BASE,
+ CONSOLE_UART_CLK_IN_HZ, CONSOLE_BAUDRATE);
+ register_serial_console(&console_data.chip);
}
diff --git a/core/arch/arm/plat-sprd/console.c b/core/arch/arm/plat-sprd/console.c
index 3263d69..ae56d95 100644
--- a/core/arch/arm/plat-sprd/console.c
+++ b/core/arch/arm/plat-sprd/console.c
@@ -29,30 +29,18 @@
#include <mm/core_memprot.h>
#include <platform_config.h>
-static vaddr_t console_base(void)
-{
- static vaddr_t base;
-
- if (cpu_mmu_enabled())
- base = (vaddr_t)phys_to_virt(CONSOLE_UART_BASE,
- MEM_AREA_IO_SEC);
- else
- base = CONSOLE_UART_BASE;
-
- return base;
-}
+static struct sprd_uart_data console_data __early_bss;
-/* Do nothing in this function */
void console_init(void)
{
+ sprd_uart_init(&console_data, CONSOLE_UART_BASE);
+ register_serial_console(&console_data.chip);
}
void console_putc(int ch)
{
- sprd_uart_putc(console_base(), (unsigned char)(ch & 0xff));
-}
+ struct serial_chip *cons = &console_data.chip;
-void console_flush(void)
-{
- sprd_uart_flush(console_base());
+ cons->ops->putc(cons, ch & 0xff);
}
+
diff --git a/core/arch/arm/plat-sprd/main.c b/core/arch/arm/plat-sprd/main.c
index bf3a62d..ea2c984 100644
--- a/core/arch/arm/plat-sprd/main.c
+++ b/core/arch/arm/plat-sprd/main.c
@@ -40,7 +40,7 @@ static void main_fiq(void);
static const struct thread_handlers handlers = {
.std_smc = tee_entry_std,
.fast_smc = tee_entry_fast,
- .fiq = main_fiq,
+ .nintr = main_fiq,
.cpu_on = cpu_on_handler,
.cpu_off = pm_do_nothing,
.cpu_suspend = pm_do_nothing,
diff --git a/core/arch/arm/plat-stm/asc.S b/core/arch/arm/plat-stm/asc.S
deleted file mode 100644
index 3f2b6aa..0000000
--- a/core/arch/arm/plat-stm/asc.S
+++ /dev/null
@@ -1,108 +0,0 @@
-/*
- * Copyright (c) 2014, STMicroelectronics International N.V.
- * 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 <kernel/unwind.h>
-
-#define ASC_BAUDRATE 0x00
-#define ASC_TXBUFFER 0x04
-#define ASC_RXBUFFER 0x08
-#define ASC_CONTROL 0x0c
-#define ASC_INTENABLE 0x10
-#define ASC_STATUS 0x14
-#define ASC_GUARDTIME 0x18
-#define ASC_TIMEOUT 0x1c
-#define ASC_TXRESET 0x20
-#define ASC_RXRESET 0x24
-#define ASC_RETRIES 0x28
-
-.section .text.asc
-
-
-/*
- * void __asc_flush(vaddr_t base)
- *
- * Clobbers r0-r3
- */
-FUNC __asc_flush , :
-UNWIND( .fnstart)
-
- ADD r3, r0, #ASC_STATUS
-
-flush_wait:
- LDR r1, [r3]
- ANDS r1, r1, #0x02 /* AND TX FIFO EMPTY flag */
- BEQ flush_wait /* ANDS should have set Z bit if zero */
-
- LDR r0, =0
- BX lr
-UNWIND( .fnend)
-END_FUNC __asc_flush
-
-/*
- * int __asc_xmit_char(char p, vaddr_t base) - Transmit a single character.
- *
- * R0 is the 1-byte character to be transmited
- * R1 is the base address of the uart
- * Clobbers r0-r3
- */
-FUNC __asc_xmit_char , :
-UNWIND( .fnstart)
-
- ADD r2, r1, #ASC_TXBUFFER
- ADD r3, r1, #ASC_STATUS
-
- /* Output byte */
-
- /* Spin until TX FIFO ready */
-__asc_char_crwait:
- LDR r1, [r3]
- ANDS r1, r1, #0x04 /* AND TX FIFO HALF EMPTY flag */
- BEQ __asc_char_crwait /* ANDS should have set Z bit if zero */
-
- MOVS r1, r0
- LDR r0, =0xFF
- AND r1, r1, r0
- BEQ __asc_char_exit
- CMP r1, #0xa /* r1 == \n (line feed) ? */
- BNE __asc_char_notlf
-
- /* Transmit character extra carriage return for each line feed */
- LDR r1, =0x0d
- STR r1, [r2]
-
- LDR r1, =0x0a /* replace line feed */
-
-__asc_char_notlf:
- /* Transmit character */
- STR r1, [r2]
-
-__asc_char_exit:
- LDR r0, =0
- BX lr
-UNWIND( .fnend)
-END_FUNC __asc_xmit_char
diff --git a/core/arch/arm/plat-stm/conf.mk b/core/arch/arm/plat-stm/conf.mk
index 4afe256..e34491f 100644
--- a/core/arch/arm/plat-stm/conf.mk
+++ b/core/arch/arm/plat-stm/conf.mk
@@ -22,6 +22,7 @@ CFG_TEE_CORE_EMBED_INTERNAL_TESTS ?= y
CFG_WITH_STACK_CANARIES ?= y
CFG_WITH_STATS ?= y
CFG_WITH_SOFTWARE_PRNG ?= n
+CFG_STIH_UART ?= y
ifeq ($(PLATFORM_FLAVOR),b2260)
CFG_PL310_LOCKED ?= y
diff --git a/core/arch/arm/plat-stm/main.c b/core/arch/arm/plat-stm/main.c
index e569e07..db92680 100644
--- a/core/arch/arm/plat-stm/main.c
+++ b/core/arch/arm/plat-stm/main.c
@@ -26,10 +26,9 @@
*/
#include <arm32.h>
-#include <asc.h>
#include <console.h>
#include <drivers/gic.h>
-#include <drivers/pl011.h>
+#include <drivers/stih_asc.h>
#include <io.h>
#include <kernel/generic_boot.h>
#include <kernel/misc.h>
@@ -50,6 +49,8 @@ register_phys_mem(MEM_AREA_IO_SEC, RNG_BASE, CORE_MMU_DEVICE_SIZE);
register_phys_mem(MEM_AREA_IO_NSEC, UART_CONSOLE_BASE, CORE_MMU_DEVICE_SIZE);
static struct gic_data gic_data;
+static struct stih_asc_pd console_data __early_bss;
+
static void main_fiq(void);
#if defined(PLATFORM_FLAVOR_b2260)
@@ -75,7 +76,7 @@ static void stm_tee_entry_std(struct thread_smc_args *smc_args)
static const struct thread_handlers handlers = {
.std_smc = stm_tee_entry_std,
.fast_smc = tee_entry_fast,
- .fiq = main_fiq,
+ .nintr = main_fiq,
.cpu_on = pm_panic,
.cpu_off = pm_panic,
.cpu_suspend = pm_panic,
@@ -89,35 +90,30 @@ const struct thread_handlers *generic_boot_get_handlers(void)
return &handlers;
}
-static vaddr_t console_base(void)
-{
- static void *va __early_bss;
-
- if (cpu_mmu_enabled()) {
- if (!va)
- va = phys_to_virt(UART_CONSOLE_BASE, MEM_AREA_IO_NSEC);
- return (vaddr_t)va;
- }
- return UART_CONSOLE_BASE;
-}
-
void console_init(void)
{
+ stih_asc_init(&console_data, UART_CONSOLE_BASE);
}
void console_putc(int ch)
{
+
if (ns_resources_ready()) {
+ struct serial_chip *cons = &console_data.chip;
+
if (ch == '\n')
- __asc_xmit_char('\r', console_base());
- __asc_xmit_char((char)ch, console_base());
+ cons->ops->putc(cons, '\r');
+ cons->ops->putc(cons, ch);
}
}
void console_flush(void)
{
- if (ns_resources_ready())
- __asc_flush(console_base());
+ if (ns_resources_ready()) {
+ struct serial_chip *cons = &console_data.chip;
+
+ cons->ops->flush(cons);
+ }
}
vaddr_t pl310_base(void)
diff --git a/core/arch/arm/plat-stm/platform_config.h b/core/arch/arm/plat-stm/platform_config.h
index 407a412..a9afb90 100644
--- a/core/arch/arm/plat-stm/platform_config.h
+++ b/core/arch/arm/plat-stm/platform_config.h
@@ -242,13 +242,16 @@
* | external memory +------------------+ |
* | | TA_RAM | |
* +---------------------------------------+ | CFG_DDR_TEETZ_RESERVED_SIZE
+ * | Secure Data Path test memory (opt.) | |
+ * +---------------------------------------+ |
* | Non secure | SHM | |
* | shared memory | | |
* +---------------------------------------+ v
*
* TEE_RAM : default 1MByte
- * PUB_RAM : default 2MByte
* TA_RAM : all what is left
+ * SDP_RAM : optional default SDP test memory 8MByte
+ * PUB_RAM : default 2MByte
*
* ----------------------------------------------------------------------------
* TEE RAM layout with CFG_WITH_PAGER=y:
@@ -262,12 +265,15 @@
* | TEE private secure | TA_RAM | ^
* | external memory | | |
* +---------------------------------------+ | CFG_DDR_TEETZ_RESERVED_SIZE
+ * | Secure Data Path test memory (opt.) | |
+ * +---------------------------------------+ |
* | Non secure | SHM | |
* | shared memory | | |
* +---------------------------------------+ v
*
* TEE_RAM : default 256kByte
* TA_RAM : all what is left in DDR TEE reserved area
+ * SDP_RAM : optional default SDP test memory 8MByte
* PUB_RAM : default 2MByte
*/
@@ -282,13 +288,30 @@
CFG_SHMEM_SIZE)
#endif
+#if defined(CFG_SECURE_DATA_PATH) && !defined(CFG_TEE_SDP_MEM_BASE)
+/* default locate SDP memory right before the shared memory in DDR */
+#define CFG_TEE_SDP_TEST_MEM_SIZE 0x00300000
+
+#define CFG_TEE_SDP_MEM_SIZE CFG_TEE_SDP_TEST_MEM_SIZE
+#define CFG_TEE_SDP_MEM_BASE (CFG_DDR_TEETZ_RESERVED_START + \
+ CFG_DDR_TEETZ_RESERVED_SIZE - \
+ CFG_SHMEM_SIZE - \
+ CFG_TEE_SDP_MEM_SIZE)
+#endif
+
+#ifndef CFG_TEE_SDP_TEST_MEM_SIZE
+#define CFG_TEE_SDP_TEST_MEM_SIZE 0
+#endif
+
#if defined(CFG_WITH_PAGER)
#define TZSRAM_BASE CFG_CORE_TZSRAM_EMUL_START
#define TZSRAM_SIZE CFG_CORE_TZSRAM_EMUL_SIZE
#define TZDRAM_BASE CFG_DDR_TEETZ_RESERVED_START
-#define TZDRAM_SIZE (CFG_DDR_TEETZ_RESERVED_SIZE - CFG_SHMEM_SIZE)
+#define TZDRAM_SIZE (CFG_DDR_TEETZ_RESERVED_SIZE - \
+ CFG_SHMEM_SIZE - \
+ CFG_TEE_SDP_TEST_MEM_SIZE)
#define CFG_TEE_RAM_START TZSRAM_BASE
#define CFG_TEE_RAM_PH_SIZE TZSRAM_SIZE
@@ -299,7 +322,9 @@
#else /* CFG_WITH_PAGER */
#define TZDRAM_BASE CFG_DDR_TEETZ_RESERVED_START
-#define TZDRAM_SIZE (CFG_DDR_TEETZ_RESERVED_SIZE - CFG_SHMEM_SIZE)
+#define TZDRAM_SIZE (CFG_DDR_TEETZ_RESERVED_SIZE - \
+ CFG_SHMEM_SIZE - \
+ CFG_TEE_SDP_TEST_MEM_SIZE)
#define CFG_TEE_RAM_START TZDRAM_BASE
#ifndef CFG_TEE_RAM_PH_SIZE
diff --git a/core/arch/arm/plat-stm/sub.mk b/core/arch/arm/plat-stm/sub.mk
index d16bb72..4793bfb 100644
--- a/core/arch/arm/plat-stm/sub.mk
+++ b/core/arch/arm/plat-stm/sub.mk
@@ -1,6 +1,5 @@
global-incdirs-y += .
srcs-y += rng_support.c
-srcs-y += asc.S
srcs-y += tz_a9init.S
srcs-y += main.c
diff --git a/core/arch/arm/plat-stm/tz_a9init.S b/core/arch/arm/plat-stm/tz_a9init.S
index aee7dbe..2f78e04 100644
--- a/core/arch/arm/plat-stm/tz_a9init.S
+++ b/core/arch/arm/plat-stm/tz_a9init.S
@@ -78,20 +78,16 @@ END_FUNC arm_cl2_enable
FUNC plat_cpu_reset_early , :
UNWIND( .fnstart)
- movw r0, #(CPU_SCTLR_INIT & 0xFFFF)
- movt r0, #((CPU_SCTLR_INIT >> 16) & 0xFFFF)
+ mov_imm r0, CPU_SCTLR_INIT
write_sctlr r0
- movw r0, #(CPU_ACTLR_INIT & 0xFFFF)
- movt r0, #((CPU_ACTLR_INIT >> 16) & 0xFFFF)
+ mov_imm r0, CPU_ACTLR_INIT
write_actlr r0
- movw r0, #(CPU_NSACR_INIT & 0xFFFF)
- movt r0, #((CPU_NSACR_INIT >> 16) & 0xFFFF)
+ mov_imm r0, CPU_NSACR_INIT
write_nsacr r0
- movw r0, #(CPU_PCR_INIT & 0xFFFF)
- movt r0, #((CPU_PCR_INIT >> 16) & 0xFFFF)
+ mov_imm r0, CPU_PCR_INIT
write_pcr r0
mov pc, lr
diff --git a/core/arch/arm/plat-sunxi/main.c b/core/arch/arm/plat-sunxi/main.c
index 3954d9d..5546c67 100644
--- a/core/arch/arm/plat-sunxi/main.c
+++ b/core/arch/arm/plat-sunxi/main.c
@@ -25,31 +25,30 @@
* POSSIBILITY OF SUCH DAMAGE.
*/
-#include <platform_config.h>
-
-#include <stdint.h>
-#include <string.h>
-#include <assert.h>
-
-#include <sm/sm.h>
-#include <sm/tee_mon.h>
-#include <sm/optee_smc.h>
-#include <optee_msg.h>
-
#include <arm.h>
-#include <kernel/thread.h>
-#include <kernel/time_source.h>
+#include <assert.h>
+#include <console.h>
+#include <drivers/sunxi_uart.h>
+#include <kernel/misc.h>
#include <kernel/panic.h>
#include <kernel/pm_stubs.h>
-#include <kernel/misc.h>
-#include <mm/tee_mmu.h>
+#include <kernel/thread.h>
+#include <kernel/time_source.h>
+#include <malloc.h>
#include <mm/core_mmu.h>
-#include <tee/entry_std.h>
-#include <tee/entry_fast.h>
+#include <mm/tee_mmu.h>
+#include <optee_msg.h>
+#include <platform_config.h>
#include <platform.h>
-#include <util.h>
+#include <sm/optee_smc.h>
+#include <sm/sm.h>
+#include <sm/tee_mon.h>
+#include <stdint.h>
+#include <string.h>
+#include <tee/entry_fast.h>
+#include <tee/entry_std.h>
#include <trace.h>
-#include <malloc.h>
+#include <util.h>
/* teecore heap address/size is defined in scatter file */
extern unsigned char teecore_heap_start;
@@ -62,7 +61,7 @@ static void main_tee_entry_fast(struct thread_smc_args *args);
static const struct thread_handlers handlers = {
.std_smc = main_tee_entry_std,
.fast_smc = main_tee_entry_fast,
- .fiq = main_fiq,
+ .nintr = main_fiq,
.cpu_on = pm_panic,
.cpu_off = pm_panic,
.cpu_suspend = pm_panic,
@@ -78,12 +77,13 @@ void main_init(uint32_t nsec_entry)
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
+ * Mask the interrupts before switch to the thread vector as the
+ * thread handler requires the interrupts to be masked while executing
* with the temporary stack. The thread subsystem also asserts that
- * IRQ is blocked when using most if its functions.
+ * foreign interrupts are blocked when using most if its functions.
*/
- thread_mask_exceptions(THREAD_EXCP_FIQ | THREAD_EXCP_IRQ);
+ thread_mask_exceptions(
+ THREAD_EXCP_NATIVE_INTR | THREAD_EXCP_FOREIGN_INTR);
if (pos == 0) {
thread_init_primary(&handlers);
@@ -175,3 +175,11 @@ void tee_entry_get_api_call_count(struct thread_smc_args *args)
{
args->a0 = tee_entry_generic_get_api_call_count() + 3;
}
+
+static struct sunxi_uart_data console_data __early_bss;
+
+void console_init(void)
+{
+ sunxi_uart_init(&console_data, CONSOLE_UART_BASE);
+ register_serial_console(&console_data.chip);
+}
diff --git a/core/arch/arm/plat-sunxi/platform.c b/core/arch/arm/plat-sunxi/platform.c
index e46541a..34331be 100644
--- a/core/arch/arm/plat-sunxi/platform.c
+++ b/core/arch/arm/plat-sunxi/platform.c
@@ -109,11 +109,11 @@ uint32_t platform_smc_handle(struct thread_smc_args *smc_args)
switch (smc_args->a1) {
case OPTEE_SMC_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));
+ cache_op_inner(DCACHE_AREA_CLEAN,
+ (void *)(&sunxi_secondary_ns_entry),
+ sizeof(uint32_t));
break;
default:
ret = OPTEE_SMC_RETURN_EBADCMD;
diff --git a/core/arch/arm/plat-sunxi/sub.mk b/core/arch/arm/plat-sunxi/sub.mk
index 7c98a65..f3fda2c 100644
--- a/core/arch/arm/plat-sunxi/sub.mk
+++ b/core/arch/arm/plat-sunxi/sub.mk
@@ -6,4 +6,3 @@ 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/arm/plat-ti/api_monitor_index.h b/core/arch/arm/plat-ti/api_monitor_index.h
new file mode 100644
index 0000000..2f8e089
--- /dev/null
+++ b/core/arch/arm/plat-ti/api_monitor_index.h
@@ -0,0 +1,54 @@
+/*
+ * Copyright (c) 2015, Texas Instruments
+ * 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 API_MONITOR_INDEX_H
+#define API_MONITOR_INDEX_H
+
+/* Number of APIs */
+#define NB_MAX_API_MONITOR 10
+
+/* Base Index of APIs */
+#define API_MONITOR_BASE_INDEX 0x00000100
+
+/* HyperVisor Start */
+#define API_MONITOR_HYP_STARTHYPERVISOR_INDEX (API_MONITOR_BASE_INDEX + 0x00000002)
+/* Caches cleaning */
+#define API_MONITOR_CACHES_CLEAN_INDEX (API_MONITOR_BASE_INDEX + 0x00000003)
+/* Write the L2 Cache Controller Auxiliary Control */
+#define API_MONITOR_L2ACTLR_SETREGISTER_INDEX (API_MONITOR_BASE_INDEX + 0x00000004)
+/* Set the Data and Tag RAM Latency */
+#define API_MONITOR_L2CACHE_SETLATENCY_INDEX (API_MONITOR_BASE_INDEX + 0x00000005)
+/* L2 Cache Prefetch Control Register */
+#define API_MONITOR_L2PFR_SETREGISTER_INDEX (API_MONITOR_BASE_INDEX + 0x00000006)
+/* Set Auxiliary Control Register */
+#define API_MONITOR_ACTLR_SETREGISTER_INDEX (API_MONITOR_BASE_INDEX + 0x00000007)
+/* AMBA IF mode */
+#define API_MONITOR_WUGEN_MPU_SETAMBAIF_INDEX (API_MONITOR_BASE_INDEX + 0x00000008)
+/* Timer CNTFRQ register set */
+#define API_MONITOR_TIMER_SETCNTFRQ_INDEX (API_MONITOR_BASE_INDEX + 0x00000009)
+
+#endif /* API_MONITOR_INDEX_H */
diff --git a/core/arch/arm/plat-ti/conf.mk b/core/arch/arm/plat-ti/conf.mk
index 64e499f..231a0b1 100644
--- a/core/arch/arm/plat-ti/conf.mk
+++ b/core/arch/arm/plat-ti/conf.mk
@@ -4,6 +4,7 @@ CFG_WITH_STACK_CANARIES ?= y
CFG_WITH_STATS ?= y
CFG_WITH_SOFTWARE_PRNG ?= n
+$(call force,CFG_SM_PLATFORM_HANDLER,y)
$(call force,CFG_8250_UART,y)
$(call force,CFG_ARM32_core,y)
$(call force,CFG_GENERIC_BOOT,y)
diff --git a/core/arch/arm/plat-ti/main.c b/core/arch/arm/plat-ti/main.c
index c811862..be3bf3a 100644
--- a/core/arch/arm/plat-ti/main.c
+++ b/core/arch/arm/plat-ti/main.c
@@ -26,11 +26,12 @@
*/
#include <platform_config.h>
-
+#include <console.h>
#include <stdint.h>
#include <string.h>
#include <assert.h>
#include <drivers/gic.h>
+#include <drivers/serial8250_uart.h>
#include <arm.h>
#include <kernel/generic_boot.h>
#include <kernel/panic.h>
@@ -47,9 +48,12 @@
#include <sm/sm.h>
static struct gic_data gic_data;
+static struct serial8250_uart_data console_data __early_bss;
register_phys_mem(MEM_AREA_IO_SEC, GICC_BASE, GICC_SIZE);
register_phys_mem(MEM_AREA_IO_SEC, GICD_BASE, GICD_SIZE);
+register_phys_mem(MEM_AREA_IO_NSEC, CONSOLE_UART_BASE,
+ SERIAL8250_UART_REG_SIZE);
void main_init_gic(void)
{
@@ -79,7 +83,7 @@ static void main_fiq(void)
static const struct thread_handlers handlers = {
.std_smc = tee_entry_std,
.fast_smc = tee_entry_fast,
- .fiq = main_fiq,
+ .nintr = main_fiq,
.cpu_on = pm_panic,
.cpu_off = pm_panic,
.cpu_suspend = pm_panic,
@@ -126,8 +130,8 @@ void init_sec_mon(unsigned long nsec_entry)
panic();
/* Invalidate cache to fetch data from external memory */
- cache_maintenance_l1(DCACHE_AREA_INVALIDATE,
- plat_ctx, sizeof(*plat_ctx));
+ cache_op_inner(DCACHE_AREA_INVALIDATE,
+ plat_ctx, sizeof(*plat_ctx));
/* Initialize secure monitor */
nsec_ctx = sm_get_nsec_ctx();
@@ -149,3 +153,10 @@ void init_sec_mon(unsigned long nsec_entry)
nsec_ctx->mon_lr = plat_ctx->mon_lr;
nsec_ctx->mon_spsr = plat_ctx->mon_spsr;
}
+
+void console_init(void)
+{
+ serial8250_uart_init(&console_data, CONSOLE_UART_BASE,
+ CONSOLE_UART_CLK_IN_HZ, CONSOLE_BAUDRATE);
+ register_serial_console(&console_data.chip);
+}
diff --git a/core/arch/arm/plat-ti/platform_config.h b/core/arch/arm/plat-ti/platform_config.h
index c1aaee9..48505a6 100644
--- a/core/arch/arm/plat-ti/platform_config.h
+++ b/core/arch/arm/plat-ti/platform_config.h
@@ -28,7 +28,7 @@
#ifndef PLATFORM_CONFIG_H
#define PLATFORM_CONFIG_H
-#if defined(PLATFORM_FLAVOR_dra7xx)
+#if defined(PLATFORM_FLAVOR_dra7xx) || defined(PLATFORM_FLAVOR_am57xx)
#define DRAM0_BASE 0xbe000000
#define DRAM0_SIZE 0x02000000
@@ -43,10 +43,14 @@
#define CFG_TEE_CORE_NB_CORE 2
+#define UART1_BASE 0x4806A000
+#define UART2_BASE 0x4806C000
+#define UART3_BASE 0x48020000
+
/* UART1 */
-#define CONSOLE_UART_BASE 0x4806A000
+#define CONSOLE_UART_BASE UART1_BASE
+#define CONSOLE_BAUDRATE 115200
#define CONSOLE_UART_CLK_IN_HZ 48000000
-#define UART_BAUDRATE 115200
#define GIC_BASE 0x48210000
#define GICC_OFFSET 0x2000
@@ -65,6 +69,14 @@
#error "Unknown platform flavor"
#endif
+#if defined(PLATFORM_FLAVOR_am57xx)
+
+/* UART3 */
+#undef CONSOLE_UART_BASE
+#define CONSOLE_UART_BASE UART3_BASE
+
+#endif
+
/* Make stacks aligned to data cache line length */
#define STACK_ALIGNMENT 64
@@ -99,11 +111,4 @@
#define DEVICE2_SIZE CORE_MMU_DEVICE_SIZE
#define DEVICE2_TYPE MEM_AREA_IO_SEC
-#ifndef UART_BAUDRATE
-#define UART_BAUDRATE 115200
-#endif
-#ifndef CONSOLE_BAUDRATE
-#define CONSOLE_BAUDRATE UART_BAUDRATE
-#endif
-
#endif /*PLATFORM_CONFIG_H*/
diff --git a/core/arch/arm/plat-ti/sm_platform_handler.c b/core/arch/arm/plat-ti/sm_platform_handler.c
new file mode 100644
index 0000000..23bb48d
--- /dev/null
+++ b/core/arch/arm/plat-ti/sm_platform_handler.c
@@ -0,0 +1,57 @@
+/*
+ * Copyright (c) 2017, Texas Instruments
+ * 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 <arm32.h>
+#include <sm/sm.h>
+#include "api_monitor_index.h"
+
+#define API_HAL_RET_VALUE_OK 0x00000000
+#define API_HAL_RET_VALUE_SERVICE_UNKNWON 0xFFFFFFFF
+
+bool sm_platform_handler(struct sm_ctx *ctx)
+{
+ if (ctx->nsec.r12 == 0x200)
+ return true;
+
+ switch (ctx->nsec.r12) {
+ case API_MONITOR_ACTLR_SETREGISTER_INDEX:
+ write_actlr(ctx->nsec.r0);
+ isb();
+ ctx->nsec.r0 = API_HAL_RET_VALUE_OK;
+ break;
+ case API_MONITOR_TIMER_SETCNTFRQ_INDEX:
+ write_cntfrq(ctx->nsec.r0);
+ isb();
+ ctx->nsec.r0 = API_HAL_RET_VALUE_OK;
+ break;
+ default:
+ ctx->nsec.r0 = API_HAL_RET_VALUE_SERVICE_UNKNWON;
+ break;
+ }
+
+ return false;
+}
diff --git a/core/arch/arm/plat-ti/sub.mk b/core/arch/arm/plat-ti/sub.mk
index 3a8214b..9e195b7 100644
--- a/core/arch/arm/plat-ti/sub.mk
+++ b/core/arch/arm/plat-ti/sub.mk
@@ -1,3 +1,3 @@
global-incdirs-y += .
srcs-y += main.c
-srcs-y += console.c
+srcs-y += sm_platform_handler.c
diff --git a/core/arch/arm/plat-vexpress/conf.mk b/core/arch/arm/plat-vexpress/conf.mk
index 5d7d8c1..5ba0840 100644
--- a/core/arch/arm/plat-vexpress/conf.mk
+++ b/core/arch/arm/plat-vexpress/conf.mk
@@ -46,7 +46,6 @@ else
$(call force,CFG_ARM32_core,y)
endif
-CFG_TEE_FS_KEY_MANAGER_TEST ?= y
CFG_WITH_STACK_CANARIES ?= y
CFG_WITH_STATS ?= y
diff --git a/core/arch/arm/plat-vexpress/main.c b/core/arch/arm/plat-vexpress/main.c
index 85ed9ee..44eef24 100644
--- a/core/arch/arm/plat-vexpress/main.c
+++ b/core/arch/arm/plat-vexpress/main.c
@@ -55,7 +55,7 @@ static void main_fiq(void);
static const struct thread_handlers handlers = {
.std_smc = tee_entry_std,
.fast_smc = tee_entry_fast,
- .fiq = main_fiq,
+ .nintr = main_fiq,
#if defined(CFG_WITH_ARM_TRUSTED_FW)
.cpu_on = cpu_on_handler,
.cpu_off = pm_do_nothing,
@@ -74,6 +74,7 @@ static const struct thread_handlers handlers = {
};
static struct gic_data gic_data;
+static struct pl011_data console_data __early_bss;
register_phys_mem(MEM_AREA_IO_SEC, CONSOLE_UART_BASE, PL011_REG_SIZE);
@@ -116,44 +117,20 @@ static void main_fiq(void)
gic_it_handle(&gic_data);
}
-static vaddr_t console_base(void)
-{
- static void *va;
-
- if (cpu_mmu_enabled()) {
- if (!va)
- va = phys_to_virt(CONSOLE_UART_BASE, MEM_AREA_IO_SEC);
- return (vaddr_t)va;
- }
- return CONSOLE_UART_BASE;
-}
-
void console_init(void)
{
- pl011_init(console_base(), CONSOLE_UART_CLK_IN_HZ, CONSOLE_BAUDRATE);
-}
-
-void console_putc(int ch)
-{
- vaddr_t base = console_base();
-
- if (ch == '\n')
- pl011_putc('\r', base);
- pl011_putc(ch, base);
-}
-
-void console_flush(void)
-{
- pl011_flush(console_base());
+ pl011_init(&console_data, CONSOLE_UART_BASE, CONSOLE_UART_CLK_IN_HZ,
+ CONSOLE_BAUDRATE);
+ register_serial_console(&console_data.chip);
}
#ifdef IT_CONSOLE_UART
static enum itr_return console_itr_cb(struct itr_handler *h __unused)
{
- paddr_t uart_base = console_base();
+ struct serial_chip *cons = &console_data.chip;
- while (pl011_have_rx_data(uart_base)) {
- int ch __maybe_unused = pl011_getchar(uart_base);
+ while (cons->ops->have_rx_data(cons)) {
+ int ch __maybe_unused = cons->ops->getchar(cons);
DMSG("cpu %zu: got 0x%x", get_core_pos(), ch);
}
diff --git a/core/arch/arm/plat-vexpress/platform_config.h b/core/arch/arm/plat-vexpress/platform_config.h
index bd006ca..45d9993 100644
--- a/core/arch/arm/plat-vexpress/platform_config.h
+++ b/core/arch/arm/plat-vexpress/platform_config.h
@@ -39,6 +39,13 @@
#endif
#endif /*ARM64*/
+/* SDP enable but no pool defined: reserve 4MB for SDP tests */
+#if defined(CFG_SECURE_DATA_PATH) && !defined(CFG_TEE_SDP_MEM_BASE)
+#define CFG_TEE_SDP_MEM_TEST_SIZE 0x00400000
+#else
+#define CFG_TEE_SDP_MEM_TEST_SIZE 0
+#endif
+
#if defined(PLATFORM_FLAVOR_fvp)
#define GIC_BASE 0x2c000000
@@ -187,23 +194,25 @@
#define DRAM0_TEERES_BASE (DRAM0_BASE + DRAM0_SIZE)
#define DRAM0_TEERES_SIZE CFG_SHMEM_SIZE
+#define SECRAM_BASE 0x0e000000
+#define SECRAM_SIZE 0x01000000
+
#ifdef CFG_WITH_PAGER
/* Emulated SRAM */
-#define TZSRAM_BASE 0x0e000000
+#define TZSRAM_BASE SECRAM_BASE
#define TZSRAM_SIZE CFG_CORE_TZSRAM_EMUL_SIZE
#define TZDRAM_BASE (TZSRAM_BASE + TZSRAM_SIZE)
-#define TZDRAM_SIZE (0x01000000 - TZSRAM_SIZE)
+#define TZDRAM_SIZE (SECRAM_SIZE - TZSRAM_SIZE)
#else /* CFG_WITH_PAGER */
-#define TZDRAM_BASE 0x0e000000
-#define TZDRAM_SIZE 0x01000000
+#define TZDRAM_BASE SECRAM_BASE
+#define TZDRAM_SIZE SECRAM_SIZE
#endif /* CFG_WITH_PAGER */
-
#define CFG_TEE_CORE_NB_CORE 2
#define CFG_SHMEM_START (DRAM0_TEERES_BASE + \
@@ -226,8 +235,12 @@
#define DRAM0_TEERES_BASE (DRAM0_BASE + DRAM0_SIZE)
#define DRAM0_TEERES_SIZE CFG_SHMEM_SIZE
-#define TZDRAM_BASE 0x0e100000
-#define TZDRAM_SIZE 0x00f00000
+#define SECRAM_BASE 0x0e000000
+#define SECRAM_SIZE 0x01000000
+
+/* First 1MByte of the secure RAM is reserved to ARM-TF runtime services */
+#define TZDRAM_BASE (SECRAM_BASE + 0x00100000)
+#define TZDRAM_SIZE (SECRAM_SIZE - 0x00100000)
#define CFG_TEE_CORE_NB_CORE 2
@@ -254,28 +267,42 @@
* | TZSRAM | TEE_RAM |
* +--------+---------+
* | TZDRAM | TA_RAM |
+ * | +---------+
+ * | | SDP RAM | (SDP test pool, optional)
* +--------+---------+
*/
#define CFG_TEE_RAM_PH_SIZE TZSRAM_SIZE
#define CFG_TEE_RAM_START TZSRAM_BASE
#define CFG_TA_RAM_START ROUNDUP(TZDRAM_BASE, CORE_MMU_DEVICE_SIZE)
-#define CFG_TA_RAM_SIZE ROUNDDOWN(TZDRAM_SIZE, CORE_MMU_DEVICE_SIZE)
+
#else
/*
* Assumes that either TZSRAM isn't large enough or TZSRAM doesn't exist,
* everything is in TZDRAM.
* +------------------+
* | | TEE_RAM |
- * + TZDRAM +---------+
+ * | TZDRAM +---------+
* | | TA_RAM |
+ * | +---------+
+ * | | SDP RAM | (test pool, optional)
* +--------+---------+
*/
#define CFG_TEE_RAM_PH_SIZE CFG_TEE_RAM_VA_SIZE
#define CFG_TEE_RAM_START TZDRAM_BASE
-#define CFG_TA_RAM_START ROUNDUP((TZDRAM_BASE + CFG_TEE_RAM_VA_SIZE), \
+#define CFG_TA_RAM_START ROUNDUP(TZDRAM_BASE + CFG_TEE_RAM_VA_SIZE, \
CORE_MMU_DEVICE_SIZE)
-#define CFG_TA_RAM_SIZE ROUNDDOWN((TZDRAM_SIZE - CFG_TEE_RAM_VA_SIZE), \
+#endif
+
+#define CFG_TA_RAM_SIZE ROUNDDOWN(TZDRAM_SIZE - \
+ (CFG_TA_RAM_START - TZDRAM_BASE) - \
+ CFG_TEE_SDP_MEM_TEST_SIZE, \
CORE_MMU_DEVICE_SIZE)
+
+/* Secure data path test memory pool: located at end of TA RAM */
+#if CFG_TEE_SDP_MEM_TEST_SIZE
+#define CFG_TEE_SDP_MEM_SIZE CFG_TEE_SDP_MEM_TEST_SIZE
+#define CFG_TEE_SDP_MEM_BASE (TZDRAM_BASE + TZDRAM_SIZE - \
+ CFG_TEE_SDP_MEM_SIZE)
#endif
#ifdef GIC_BASE
diff --git a/core/arch/arm/plat-zynq7k/main.c b/core/arch/arm/plat-zynq7k/main.c
index 74bc1ce..2991b94 100644
--- a/core/arch/arm/plat-zynq7k/main.c
+++ b/core/arch/arm/plat-zynq7k/main.c
@@ -51,7 +51,7 @@ static void platform_tee_entry_fast(struct thread_smc_args *args);
static const struct thread_handlers handlers = {
.std_smc = tee_entry_std,
.fast_smc = platform_tee_entry_fast,
- .fiq = main_fiq,
+ .nintr = main_fiq,
.cpu_on = pm_panic,
.cpu_off = pm_panic,
.cpu_suspend = pm_panic,
@@ -61,6 +61,7 @@ static const struct thread_handlers handlers = {
};
static struct gic_data gic_data;
+static struct cdns_uart_data console_data __early_bss;
register_phys_mem(MEM_AREA_IO_NSEC, CONSOLE_UART_BASE, CORE_MMU_DEVICE_SIZE);
register_phys_mem(MEM_AREA_IO_SEC, GIC_BASE, CORE_MMU_DEVICE_SIZE);
@@ -117,33 +118,10 @@ void plat_cpu_reset_late(void)
}
}
-static vaddr_t console_base(void)
-{
- static void *va __early_bss;
-
- if (cpu_mmu_enabled()) {
- if (!va)
- va = phys_to_virt(CONSOLE_UART_BASE,
- MEM_AREA_IO_NSEC);
- return (vaddr_t)va;
- }
- return CONSOLE_UART_BASE;
-}
-
void console_init(void)
{
-}
-
-void console_putc(int ch)
-{
- if (ch == '\n')
- cdns_uart_putc('\r', console_base());
- cdns_uart_putc(ch, console_base());
-}
-
-void console_flush(void)
-{
- cdns_uart_flush(console_base());
+ cdns_uart_init(&console_data, CONSOLE_UART_BASE, 0, 0);
+ register_serial_console(&console_data.chip);
}
vaddr_t pl310_base(void)
diff --git a/core/arch/arm/plat-zynq7k/plat_init.S b/core/arch/arm/plat-zynq7k/plat_init.S
index 6d99a30..8d06c53 100644
--- a/core/arch/arm/plat-zynq7k/plat_init.S
+++ b/core/arch/arm/plat-zynq7k/plat_init.S
@@ -90,20 +90,16 @@ UNWIND( .fnstart)
* PCR = 0x00000001
* - no change latency, enable clk gating
*/
- movw r0, #0x4000
- movt r0, #0x0000
+ mov_imm r0, 0x00004000
write_sctlr r0
- movw r0, #0x0041
- movt r0, #0x0000
+ mov_imm r0, 0x00000041
write_actlr r0
- movw r0, #0x0FFF
- movt r0, #0x0002
+ mov_imm r0, 0x00020C00
write_nsacr r0
- movw r0, #0x0000
- movt r0, #0x0001
+ mov_imm r0, 0x00000001
write_pcr r0
mov pc, lr
diff --git a/core/arch/arm/plat-zynqmp/conf.mk b/core/arch/arm/plat-zynqmp/conf.mk
index 67570bc..5aea3a8 100644
--- a/core/arch/arm/plat-zynqmp/conf.mk
+++ b/core/arch/arm/plat-zynqmp/conf.mk
@@ -23,7 +23,6 @@ else
$(call force,CFG_ARM32_core,y)
endif
-CFG_TEE_FS_KEY_MANAGER_TEST ?= y
CFG_WITH_STACK_CANARIES ?= y
CFG_WITH_STATS ?= y
CFG_CRYPTO_WITH_CE ?= y
diff --git a/core/arch/arm/plat-zynqmp/main.c b/core/arch/arm/plat-zynqmp/main.c
index 31b8475..a00d1ae 100644
--- a/core/arch/arm/plat-zynqmp/main.c
+++ b/core/arch/arm/plat-zynqmp/main.c
@@ -46,11 +46,12 @@
static void main_fiq(void);
static struct gic_data gic_data;
+static struct cdns_uart_data console_data __early_bss;
static const struct thread_handlers handlers = {
.std_smc = tee_entry_std,
.fast_smc = tee_entry_fast,
- .fiq = main_fiq,
+ .nintr = main_fiq,
#if defined(CFG_WITH_ARM_TRUSTED_FW)
.cpu_on = cpu_on_handler,
.cpu_off = pm_do_nothing,
@@ -90,33 +91,9 @@ static void main_fiq(void)
gic_it_handle(&gic_data);
}
-static vaddr_t console_base(void)
-{
- static void *va;
-
- if (cpu_mmu_enabled()) {
- if (!va)
- va = phys_to_virt(CONSOLE_UART_BASE, MEM_AREA_IO_SEC);
- return (vaddr_t)va;
- }
-
- return CONSOLE_UART_BASE;
-}
-
void console_init(void)
{
- cdns_uart_init(console_base(), CONSOLE_UART_CLK_IN_HZ,
- CONSOLE_BAUDRATE);
-}
-
-void console_putc(int ch)
-{
- if (ch == '\n')
- cdns_uart_putc('\r', console_base());
- cdns_uart_putc(ch, console_base());
-}
-
-void console_flush(void)
-{
- cdns_uart_flush(console_base());
+ cdns_uart_init(&console_data, CONSOLE_UART_BASE,
+ CONSOLE_UART_CLK_IN_HZ, CONSOLE_BAUDRATE);
+ register_serial_console(&console_data.chip);
}
diff --git a/core/arch/arm/pta/core_fs_htree_tests.c b/core/arch/arm/pta/core_fs_htree_tests.c
new file mode 100644
index 0000000..23be98c
--- /dev/null
+++ b/core/arch/arm/pta/core_fs_htree_tests.c
@@ -0,0 +1,456 @@
+/*
+ * Copyright (c) 2017, 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.
+ */
+
+#include <assert.h>
+#include <string.h>
+#include <tee/fs_htree.h>
+#include <tee/tee_fs_rpc.h>
+#include <trace.h>
+#include <types_ext.h>
+#include <util.h>
+
+#include "core_self_tests.h"
+
+/*
+ * The smallest blocks size that can hold two struct
+ * tee_fs_htree_node_image or two struct tee_fs_htree_image.
+ */
+#define TEST_BLOCK_SIZE 144
+
+struct test_aux {
+ uint8_t *data;
+ size_t data_len;
+ size_t data_alloced;
+ uint8_t *block;
+};
+
+static TEE_Result test_get_offs_size(enum tee_fs_htree_type type, size_t idx,
+ uint8_t vers, size_t *offs, size_t *size)
+{
+ const size_t node_size = sizeof(struct tee_fs_htree_node_image);
+ const size_t block_nodes = TEST_BLOCK_SIZE / (node_size * 2);
+ size_t pbn;
+ size_t bidx;
+
+ COMPILE_TIME_ASSERT(TEST_BLOCK_SIZE >
+ sizeof(struct tee_fs_htree_node_image) * 2);
+ COMPILE_TIME_ASSERT(TEST_BLOCK_SIZE >
+ sizeof(struct tee_fs_htree_image) * 2);
+
+ assert(vers == 0 || vers == 1);
+
+ /*
+ * File layout
+ *
+ * phys block 0:
+ * tee_fs_htree_image vers 0 @ offs = 0
+ * tee_fs_htree_image vers 1 @ offs = sizeof(tee_fs_htree_image)
+ *
+ * phys block 1:
+ * tee_fs_htree_node_image 0 vers 0 @ offs = 0
+ * tee_fs_htree_node_image 0 vers 1 @ offs = node_size
+ *
+ * phys block 2:
+ * data block 0 vers 0
+ *
+ * phys block 3:
+ * tee_fs_htree_node_image 1 vers 0 @ offs = 0
+ * tee_fs_htree_node_image 1 vers 1 @ offs = node_size
+ *
+ * phys block 4:
+ * data block 0 vers 1
+ *
+ * ...
+ */
+
+ switch (type) {
+ case TEE_FS_HTREE_TYPE_HEAD:
+ *offs = sizeof(struct tee_fs_htree_image) * vers;
+ *size = sizeof(struct tee_fs_htree_image);
+ return TEE_SUCCESS;
+ case TEE_FS_HTREE_TYPE_NODE:
+ pbn = 1 + ((idx / block_nodes) * block_nodes * 2);
+ *offs = pbn * TEST_BLOCK_SIZE +
+ 2 * node_size * (idx % block_nodes) +
+ node_size * vers;
+ *size = node_size;
+ return TEE_SUCCESS;
+ case TEE_FS_HTREE_TYPE_BLOCK:
+ bidx = 2 * idx + vers;
+ pbn = 2 + bidx + bidx / (block_nodes * 2 - 1);
+ *offs = pbn * TEST_BLOCK_SIZE;
+ *size = TEST_BLOCK_SIZE;
+ return TEE_SUCCESS;
+ default:
+ return TEE_ERROR_GENERIC;
+ }
+}
+
+static TEE_Result test_read_init(void *aux, struct tee_fs_rpc_operation *op,
+ enum tee_fs_htree_type type, size_t idx,
+ uint8_t vers, void **data)
+{
+ TEE_Result res;
+ struct test_aux *a = aux;
+ size_t offs;
+ size_t sz;
+
+ res = test_get_offs_size(type, idx, vers, &offs, &sz);
+ if (res == TEE_SUCCESS) {
+ memset(op, 0, sizeof(*op));
+ op->params[0].u.value.a = (vaddr_t)aux;
+ op->params[0].u.value.b = offs;
+ op->params[0].u.value.c = sz;
+ *data = a->block;
+ }
+
+ return res;
+}
+
+static void *uint_to_ptr(uintptr_t p)
+{
+ return (void *)p;
+}
+
+static TEE_Result test_read_final(struct tee_fs_rpc_operation *op,
+ size_t *bytes)
+{
+ struct test_aux *a = uint_to_ptr(op->params[0].u.value.a);
+ size_t offs = op->params[0].u.value.b;
+ size_t sz = op->params[0].u.value.c;
+
+ if (offs + sz <= a->data_len)
+ *bytes = sz;
+ else if (offs <= a->data_len)
+ *bytes = a->data_len - offs;
+ else
+ *bytes = 0;
+
+ memcpy(a->block, a->data + offs, *bytes);
+ return TEE_SUCCESS;
+}
+
+static TEE_Result test_write_init(void *aux, struct tee_fs_rpc_operation *op,
+ enum tee_fs_htree_type type, size_t idx,
+ uint8_t vers, void **data)
+{
+ return test_read_init(aux, op, type, idx, vers, data);
+}
+
+static TEE_Result test_write_final(struct tee_fs_rpc_operation *op)
+{
+ struct test_aux *a = uint_to_ptr(op->params[0].u.value.a);
+ size_t offs = op->params[0].u.value.b;
+ size_t sz = op->params[0].u.value.c;
+ size_t end = offs + sz;
+
+ if (end > a->data_alloced) {
+ EMSG("out of bounds");
+ return TEE_ERROR_GENERIC;
+ }
+
+ memcpy(a->data + offs, a->block, sz);
+ if (end > a->data_len)
+ a->data_len = end;
+ return TEE_SUCCESS;
+
+}
+
+static const struct tee_fs_htree_storage test_htree_ops = {
+ .block_size = TEST_BLOCK_SIZE,
+ .rpc_read_init = test_read_init,
+ .rpc_read_final = test_read_final,
+ .rpc_write_init = test_write_init,
+ .rpc_write_final = test_write_final,
+};
+
+#define CHECK_RES(res, cleanup) \
+ do { \
+ TEE_Result _res = (res); \
+ \
+ if (_res != TEE_SUCCESS) { \
+ EMSG("error: res = %#" PRIx32, _res); \
+ { cleanup; } \
+ } \
+ } while (0)
+
+static uint32_t val_from_bn_n_salt(size_t bn, size_t n, uint8_t salt)
+{
+ assert(bn < UINT16_MAX);
+ assert(n < UINT8_MAX);
+ return SHIFT_U32(n, 16) | SHIFT_U32(bn, 8) | salt;
+}
+
+static TEE_Result write_block(struct tee_fs_htree **ht, size_t bn, uint8_t salt)
+{
+ uint32_t b[TEST_BLOCK_SIZE / sizeof(uint32_t)];
+ size_t n;
+
+ for (n = 0; n < ARRAY_SIZE(b); n++)
+ b[n] = val_from_bn_n_salt(bn, n, salt);
+
+ return tee_fs_htree_write_block(ht, bn, b);
+}
+
+static TEE_Result read_block(struct tee_fs_htree **ht, size_t bn, uint8_t salt)
+{
+ TEE_Result res;
+ uint32_t b[TEST_BLOCK_SIZE / sizeof(uint32_t)];
+ size_t n;
+
+ res = tee_fs_htree_read_block(ht, bn, b);
+ if (res != TEE_SUCCESS)
+ return res;
+
+ for (n = 0; n < ARRAY_SIZE(b); n++) {
+ if (b[n] != val_from_bn_n_salt(bn, n, salt)) {
+ DMSG("Unpected b[%zu] %#" PRIx32
+ "(expected %#" PRIx32 ")",
+ n, b[n], val_from_bn_n_salt(bn, n, salt));
+ return TEE_ERROR_SECURITY;
+ }
+ }
+
+ return TEE_SUCCESS;
+}
+
+static TEE_Result do_range(TEE_Result (*fn)(struct tee_fs_htree **ht,
+ size_t bn, uint8_t salt),
+ struct tee_fs_htree **ht, size_t begin,
+ size_t num_blocks, size_t salt)
+{
+ TEE_Result res = TEE_SUCCESS;
+ size_t n;
+
+ for (n = 0; n < num_blocks; n++) {
+ res = fn(ht, n + begin, salt);
+ CHECK_RES(res, goto out);
+ }
+
+out:
+ return res;
+}
+
+static TEE_Result do_range_backwards(TEE_Result (*fn)(struct tee_fs_htree **ht,
+ size_t bn, uint8_t salt),
+ struct tee_fs_htree **ht, size_t begin,
+ size_t num_blocks, size_t salt)
+{
+ TEE_Result res = TEE_SUCCESS;
+ size_t n;
+
+ for (n = 0; n < num_blocks; n++) {
+ res = fn(ht, num_blocks - 1 - n + begin, salt);
+ CHECK_RES(res, goto out);
+ }
+
+out:
+ return res;
+}
+
+static TEE_Result htree_test_rewrite(struct test_aux *aux, size_t num_blocks,
+ size_t w_unsync_begin, size_t w_unsync_num)
+{
+ TEE_Result res;
+ struct tee_fs_htree *ht = NULL;
+ size_t salt = 23;
+
+ assert((w_unsync_begin + w_unsync_num) <= num_blocks);
+
+ aux->data_len = 0;
+ memset(aux->data, 0xce, aux->data_alloced);
+
+ res = tee_fs_htree_open(true, &test_htree_ops, aux, &ht);
+ CHECK_RES(res, goto out);
+
+ /*
+ * Intialize all blocks and verify that they read back as
+ * expected.
+ */
+ res = do_range(write_block, &ht, 0, num_blocks, salt);
+ CHECK_RES(res, goto out);
+
+ res = do_range(read_block, &ht, 0, num_blocks, salt);
+ CHECK_RES(res, goto out);
+
+ /*
+ * Write all blocks again, but starting from the end using a new
+ * salt, then verify that that read back as expected.
+ */
+ salt++;
+ res = do_range_backwards(write_block, &ht, 0, num_blocks, salt);
+ CHECK_RES(res, goto out);
+
+ res = do_range(read_block, &ht, 0, num_blocks, salt);
+ CHECK_RES(res, goto out);
+
+ /*
+ * Use a new salt to write all blocks once more and verify that
+ * they read back as expected.
+ */
+ salt++;
+ res = do_range(write_block, &ht, 0, num_blocks, salt);
+ CHECK_RES(res, goto out);
+
+ res = do_range(read_block, &ht, 0, num_blocks, salt);
+ CHECK_RES(res, goto out);
+
+ /*
+ * Sync the changes of the nodes to memory, verify that all
+ * blocks are read back as expected.
+ */
+ res = tee_fs_htree_sync_to_storage(&ht);
+ CHECK_RES(res, goto out);
+
+ res = do_range(read_block, &ht, 0, num_blocks, salt);
+ CHECK_RES(res, goto out);
+
+ /*
+ * Close and reopen the hash-tree
+ */
+ tee_fs_htree_close(&ht);
+ res = tee_fs_htree_open(false, &test_htree_ops, aux, &ht);
+ CHECK_RES(res, goto out);
+
+ /*
+ * Verify that all blocks are read as expected.
+ */
+ res = do_range(read_block, &ht, 0, num_blocks, salt);
+ CHECK_RES(res, goto out);
+
+ /*
+ * Rewrite a few blocks and verify that all blocks are read as
+ * expected.
+ */
+ res = do_range_backwards(write_block, &ht, w_unsync_begin, w_unsync_num,
+ salt + 1);
+ CHECK_RES(res, goto out);
+
+ res = do_range(read_block, &ht, 0, w_unsync_begin, salt);
+ CHECK_RES(res, goto out);
+ res = do_range(read_block, &ht, w_unsync_begin, w_unsync_num, salt + 1);
+ CHECK_RES(res, goto out);
+ res = do_range(read_block, &ht, w_unsync_begin + w_unsync_num,
+ num_blocks - (w_unsync_begin + w_unsync_num), salt);
+ CHECK_RES(res, goto out);
+
+ /*
+ * Rewrite the blocks from above again with another salt and
+ * verify that they are read back as expected.
+ */
+ res = do_range(write_block, &ht, w_unsync_begin, w_unsync_num,
+ salt + 2);
+ CHECK_RES(res, goto out);
+
+ res = do_range(read_block, &ht, 0, w_unsync_begin, salt);
+ CHECK_RES(res, goto out);
+ res = do_range(read_block, &ht, w_unsync_begin, w_unsync_num, salt + 2);
+ CHECK_RES(res, goto out);
+ res = do_range(read_block, &ht, w_unsync_begin + w_unsync_num,
+ num_blocks - (w_unsync_begin + w_unsync_num), salt);
+ CHECK_RES(res, goto out);
+
+ /*
+ * Skip tee_fs_htree_sync_to_storage() and call
+ * tee_fs_htree_close() directly to undo the changes since last
+ * call to tee_fs_htree_sync_to_storage(). Reopen the hash-tree
+ * and verify that recent changes indeed was discarded.
+ */
+ tee_fs_htree_close(&ht);
+ res = tee_fs_htree_open(false, &test_htree_ops, aux, &ht);
+ CHECK_RES(res, goto out);
+
+ res = do_range(read_block, &ht, 0, num_blocks, salt);
+ CHECK_RES(res, goto out);
+
+ /*
+ * Close, reopen and verify that all blocks are read as expected
+ * again.
+ */
+ tee_fs_htree_close(&ht);
+ res = tee_fs_htree_open(false, &test_htree_ops, aux, &ht);
+ CHECK_RES(res, goto out);
+
+ res = do_range(read_block, &ht, 0, num_blocks, salt);
+ CHECK_RES(res, goto out);
+
+out:
+ tee_fs_htree_close(&ht);
+ return res;
+}
+
+TEE_Result core_fs_htree_tests(uint32_t nParamTypes,
+ TEE_Param pParams[TEE_NUM_PARAMS] __unused)
+{
+ TEE_Result res;
+ struct test_aux aux;
+ size_t num_blocks = 10;
+ size_t offs;
+ size_t sz;
+ size_t n;
+ size_t m;
+ size_t o;
+
+ if (nParamTypes)
+ return TEE_ERROR_BAD_PARAMETERS;
+
+ res = test_get_offs_size(TEE_FS_HTREE_TYPE_BLOCK, num_blocks, 1,
+ &offs, &sz);
+ CHECK_RES(res, return res);
+
+ aux.data_alloced = offs + sz;
+ aux.data = malloc(aux.data_alloced);
+ aux.block = malloc(TEST_BLOCK_SIZE);
+ if (!aux.data || !aux.block) {
+ res = TEE_ERROR_OUT_OF_MEMORY;
+ goto out;
+ }
+
+ /*
+ * n is the number of block we're going to initialize/use.
+ * m is the offset from where we'll rewrite blocks and expect
+ * the changes to be visible until tee_fs_htree_close() is called
+ * without a call to tee_fs_htree_sync_to_storage() before.
+ * o is the number of blocks we're rewriting starting at m.
+ */
+ for (n = 0; n < num_blocks; n += 3) {
+ for (m = 0; m < n; m += 3) {
+ for (o = 0; o < (n - m); o++) {
+ res = htree_test_rewrite(&aux, n, m, o);
+ CHECK_RES(res, goto out);
+ o += 2;
+ }
+ }
+ }
+
+
+out:
+ free(aux.data);
+ free(aux.block);
+ return res;
+}
+
diff --git a/core/arch/arm/pta/core_self_tests.h b/core/arch/arm/pta/core_self_tests.h
index ed98669..b775430 100644
--- a/core/arch/arm/pta/core_self_tests.h
+++ b/core/arch/arm/pta/core_self_tests.h
@@ -34,4 +34,7 @@
TEE_Result core_self_tests(uint32_t nParamTypes,
TEE_Param pParams[TEE_NUM_PARAMS]);
+TEE_Result core_fs_htree_tests(uint32_t nParamTypes,
+ TEE_Param pParams[TEE_NUM_PARAMS]);
+
#endif /*CORE_SELF_TESTS_H*/
diff --git a/core/arch/arm/pta/interrupt_tests.c b/core/arch/arm/pta/interrupt_tests.c
index bc307a8..2b9ea00 100644
--- a/core/arch/arm/pta/interrupt_tests.c
+++ b/core/arch/arm/pta/interrupt_tests.c
@@ -174,7 +174,7 @@ static TEE_Result test_ppi(void)
itr_add(&ppi_handler);
itr_enable(TEST_PPI_ID);
- exceptions = thread_mask_exceptions(THREAD_EXCP_IRQ);
+ exceptions = thread_mask_exceptions(THREAD_EXCP_FOREIGN_INTR);
expect_ppi_value[get_core_pos()]++;
itr_raise_pi(TEST_PPI_ID);
thread_unmask_exceptions(exceptions);
diff --git a/core/arch/arm/pta/pta_self_tests.c b/core/arch/arm/pta/pta_invoke_tests.c
index 6472356..33691b0 100644
--- a/core/arch/arm/pta/pta_self_tests.c
+++ b/core/arch/arm/pta/pta_invoke_tests.c
@@ -24,23 +24,21 @@
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*/
+
#include <compiler.h>
-#include <types_ext.h>
#include <kernel/pseudo_ta.h>
-#include <trace.h>
-#include <tee_api_types.h>
+#include <mm/core_memprot.h>
+#include <pta_invoke_tests.h>
+#include <string.h>
+#include <tee/cache.h>
#include <tee_api_defines.h>
-#include "core_self_tests.h"
-
-#define TA_NAME "sta_self_tests.ta"
+#include <tee_api_types.h>
+#include <trace.h>
+#include <types_ext.h>
-#define STA_SELF_TEST_UUID \
- { 0xd96a5b40, 0xc3e5, 0x21e3, \
- { 0x87, 0x94, 0x10, 0x02, 0xa5, 0xd5, 0xc6, 0x1b } }
+#include "core_self_tests.h"
-#define CMD_TRACE 0
-#define CMD_PARAMS 1
-#define CMD_SELF_TESTS 2
+#define TA_NAME "invoke_tests.pta"
static TEE_Result test_trace(uint32_t param_types __unused,
TEE_Param params[TEE_NUM_PARAMS] __unused)
@@ -196,6 +194,116 @@ static TEE_Result test_entry_params(uint32_t type, TEE_Param p[TEE_NUM_PARAMS])
}
/*
+ * Test access to Secure Data Path memory from pseudo TAs
+ */
+
+static TEE_Result test_inject_sdp(uint32_t type, TEE_Param p[TEE_NUM_PARAMS])
+{
+ char *src = p[0].memref.buffer;
+ char *dst = p[1].memref.buffer;
+ size_t sz = p[0].memref.size;
+ uint32_t exp_pt = TEE_PARAM_TYPES(TEE_PARAM_TYPE_MEMREF_INPUT,
+ TEE_PARAM_TYPE_MEMREF_OUTPUT,
+ TEE_PARAM_TYPE_NONE,
+ TEE_PARAM_TYPE_NONE);
+
+ if (exp_pt != type) {
+ DMSG("bad parameter types");
+ return TEE_ERROR_BAD_PARAMETERS;
+ }
+
+ if (p[1].memref.size < sz) {
+ p[1].memref.size = sz;
+ return TEE_ERROR_SHORT_BUFFER;
+ }
+
+
+ if (!core_vbuf_is(CORE_MEM_NSEC_SHM, src, sz) ||
+ !core_vbuf_is(CORE_MEM_SDP_MEM, dst, sz)) {
+ DMSG("bad memref secure attribute");
+ return TEE_ERROR_BAD_PARAMETERS;
+ }
+
+ if (cache_operation(TEE_CACHEFLUSH, dst, sz) != TEE_SUCCESS)
+ return TEE_ERROR_GENERIC;
+
+ memcpy(dst, src, sz);
+
+ if (cache_operation(TEE_CACHEFLUSH, dst, sz) != TEE_SUCCESS)
+ return TEE_ERROR_GENERIC;
+
+ return TEE_SUCCESS;
+}
+
+static TEE_Result test_transform_sdp(uint32_t type, TEE_Param p[TEE_NUM_PARAMS])
+{
+ char *buf = p[0].memref.buffer;
+ size_t sz = p[0].memref.size;
+ uint32_t exp_pt = TEE_PARAM_TYPES(TEE_PARAM_TYPE_MEMREF_INOUT,
+ TEE_PARAM_TYPE_NONE,
+ TEE_PARAM_TYPE_NONE,
+ TEE_PARAM_TYPE_NONE);
+
+ if (exp_pt != type) {
+ DMSG("bad parameter types");
+ return TEE_ERROR_BAD_PARAMETERS;
+ }
+
+ if (!core_vbuf_is(CORE_MEM_SDP_MEM, buf, sz)) {
+ DMSG("bad memref secure attribute");
+ return TEE_ERROR_BAD_PARAMETERS;
+ }
+
+ if (cache_operation(TEE_CACHEFLUSH, buf, sz) != TEE_SUCCESS)
+ return TEE_ERROR_GENERIC;
+
+ for (; sz; sz--, buf++)
+ *buf = ~(*buf) + 1;
+
+ if (cache_operation(TEE_CACHEFLUSH, buf, sz) != TEE_SUCCESS)
+ return TEE_ERROR_GENERIC;
+
+ return TEE_SUCCESS;
+}
+
+static TEE_Result test_dump_sdp(uint32_t type, TEE_Param p[TEE_NUM_PARAMS])
+{
+ char *src = p[0].memref.buffer;
+ char *dst = p[1].memref.buffer;
+ size_t sz = p[0].memref.size;
+ uint32_t exp_pt = TEE_PARAM_TYPES(TEE_PARAM_TYPE_MEMREF_INPUT,
+ TEE_PARAM_TYPE_MEMREF_OUTPUT,
+ TEE_PARAM_TYPE_NONE,
+ TEE_PARAM_TYPE_NONE);
+
+ if (exp_pt != type) {
+ DMSG("bad parameter types");
+ return TEE_ERROR_BAD_PARAMETERS;
+ }
+
+ if (p[1].memref.size < sz) {
+ p[1].memref.size = sz;
+ return TEE_ERROR_SHORT_BUFFER;
+ }
+
+ if (!core_vbuf_is(CORE_MEM_SDP_MEM, src, sz) ||
+ !core_vbuf_is(CORE_MEM_NSEC_SHM, dst, sz)) {
+ DMSG("bad memref secure attribute");
+ return TEE_ERROR_BAD_PARAMETERS;
+ }
+
+ if (cache_operation(TEE_CACHEFLUSH, dst, sz) != TEE_SUCCESS)
+ return TEE_ERROR_GENERIC;
+
+ memcpy(dst, src, sz);
+
+ if (cache_operation(TEE_CACHEFLUSH, dst, sz) != TEE_SUCCESS)
+ return TEE_ERROR_GENERIC;
+
+ return TEE_SUCCESS;
+}
+
+/*
* Trusted Application Entry Points
*/
@@ -230,20 +338,30 @@ static TEE_Result invoke_command(void *pSessionContext __unused,
DMSG("command entry point for pseudo ta \"%s\"", TA_NAME);
switch (nCommandID) {
- case CMD_TRACE:
+ case PTA_INVOKE_TESTS_CMD_TRACE:
return test_trace(nParamTypes, pParams);
- case CMD_PARAMS:
+ case PTA_INVOKE_TESTS_CMD_PARAMS:
return test_entry_params(nParamTypes, pParams);
- case CMD_SELF_TESTS:
+ case PTA_INVOKE_TESTS_CMD_COPY_NSEC_TO_SEC:
+ return test_inject_sdp(nParamTypes, pParams);
+ case PTA_INVOKE_TESTS_CMD_READ_MODIFY_SEC:
+ return test_transform_sdp(nParamTypes, pParams);
+ case PTA_INVOKE_TESTS_CMD_COPY_SEC_TO_NSEC:
+ return test_dump_sdp(nParamTypes, pParams);
+ case PTA_INVOKE_TESTS_CMD_SELF_TESTS:
return core_self_tests(nParamTypes, pParams);
+#if defined(CFG_WITH_USER_TA)
+ case PTA_INVOKE_TESTS_CMD_FS_HTREE:
+ return core_fs_htree_tests(nParamTypes, pParams);
+#endif
default:
break;
}
return TEE_ERROR_BAD_PARAMETERS;
}
-pseudo_ta_register(.uuid = STA_SELF_TEST_UUID, .name = TA_NAME,
- .flags = PTA_DEFAULT_FLAGS,
+pseudo_ta_register(.uuid = PTA_INVOKE_TESTS_UUID, .name = TA_NAME,
+ .flags = PTA_DEFAULT_FLAGS | TA_FLAG_SECURE_DATA_PATH,
.create_entry_point = create_ta,
.destroy_entry_point = destroy_ta,
.open_session_entry_point = open_session,
diff --git a/core/arch/arm/pta/sub.mk b/core/arch/arm/pta/sub.mk
index 3d961d4..4333e86 100644
--- a/core/arch/arm/pta/sub.mk
+++ b/core/arch/arm/pta/sub.mk
@@ -1,6 +1,9 @@
-srcs-$(CFG_TEE_CORE_EMBED_INTERNAL_TESTS) += pta_self_tests.c
+srcs-$(CFG_TEE_CORE_EMBED_INTERNAL_TESTS) += pta_invoke_tests.c
srcs-$(CFG_TEE_CORE_EMBED_INTERNAL_TESTS) += core_self_tests.c
srcs-$(CFG_TEE_CORE_EMBED_INTERNAL_TESTS) += interrupt_tests.c
+ifeq ($(CFG_WITH_USER_TA),y)
+srcs-$(CFG_TEE_CORE_EMBED_INTERNAL_TESTS) += core_fs_htree_tests.c
+endif
srcs-$(CFG_WITH_STATS) += stats.c
srcs-$(CFG_TA_GPROF_SUPPORT) += gprof.c
@@ -8,7 +11,3 @@ ifeq ($(CFG_SE_API),y)
srcs-$(CFG_SE_API_SELF_TEST) += se_api_self_tests.c
cppflags-se_api_self_tests.c-y += -Icore/tee/se
endif
-
-ifeq ($(CFG_WITH_USER_TA),y)
-srcs-$(CFG_TEE_FS_KEY_MANAGER_TEST) += tee_fs_key_manager_tests.c
-endif
diff --git a/core/arch/arm/pta/tee_fs_key_manager_tests.c b/core/arch/arm/pta/tee_fs_key_manager_tests.c
deleted file mode 100644
index f9dc714..0000000
--- a/core/arch/arm/pta/tee_fs_key_manager_tests.c
+++ /dev/null
@@ -1,375 +0,0 @@
-/*
- * Copyright (c) 2015, 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.
- */
-
-#include <kernel/pseudo_ta.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include <tee/tee_fs_key_manager.h>
-#include <trace.h>
-
-#define TA_NAME "tee_fs_key_manager_tests.ta"
-
-#define CMD_SELF_TESTS 0
-
-#define ENC_FS_KEY_MANAGER_TEST_UUID \
- { 0x17E5E280, 0xD12E, 0x11E4, \
- { 0xA4, 0x1A, 0x00, 0x02, 0xA5, 0xD5, 0xC5, 0x1B } }
-
-#define DUMP_BUF_MAX 256
-
-static uint8_t test_data[] = {
- 0x00, 0x6E, 0x04, 0x57, 0x08, 0xFB, 0x71, 0x96,
- 0x00, 0x2E, 0x55, 0x3D, 0x02, 0xC3, 0xA6, 0x92,
- 0x00, 0xC3, 0xEF, 0x8A, 0xB2, 0x34, 0x53, 0xE6,
- 0x00, 0x74, 0x9C, 0xD6, 0x36, 0xE7, 0xA8, 0x00
-};
-
-static char *print_buf(char *buf, size_t *remain_size, const char *fmt, ...)
- __attribute__((__format__(__printf__, 3, 4)));
-
-static char *print_buf(char *buf, size_t *remain_size, const char *fmt, ...)
-{
- va_list ap;
- size_t len;
-
- va_start(ap, fmt);
- len = vsnprintf(buf, *remain_size, fmt, ap);
- buf += len;
- *remain_size -= len;
- va_end(ap);
- return buf;
-}
-
-static void dump_hex(char *buf, size_t *remain_size, uint8_t *input_buf,
- size_t input_size)
-{
- size_t i;
-
- for (i = 0; i < input_size; i++)
- buf = print_buf(buf, remain_size, "%02X ", input_buf[i]);
-}
-
-static void print_hex(uint8_t *input_buf, size_t input_size)
-{
- char buf[DUMP_BUF_MAX];
- size_t remain = sizeof(buf);
-
- dump_hex(buf, &remain, input_buf, input_size);
- DMSG("%s", buf);
-}
-
-/*
- * Trusted Application Entry Points
- */
-
-static TEE_Result test_file_decrypt_with_invalid_content(void)
-{
- TEE_Result res = TEE_SUCCESS;
- size_t header_size;
- size_t encrypt_data_out_size;
- uint8_t *encrypt_data_out = NULL;
- size_t decrypt_data_out_size;
- uint8_t *decrypt_data_out = NULL;
- uint8_t tmp_byte;
- uint8_t encrypted_fek[TEE_FS_KM_FEK_SIZE];
-
- DMSG("Start");
-
- /* data encryption */
- header_size = tee_fs_get_header_size(META_FILE);
-
- encrypt_data_out_size = header_size + sizeof(test_data);
- encrypt_data_out = malloc(encrypt_data_out_size);
- if (!encrypt_data_out) {
- EMSG("malloc for encrypt data buffer failed");
- res = TEE_ERROR_OUT_OF_MEMORY;
- goto exit;
- }
-
- res = tee_fs_encrypt_file(META_FILE,
- test_data, sizeof(test_data),
- encrypt_data_out, &encrypt_data_out_size,
- encrypted_fek);
- if (res != TEE_SUCCESS) {
- EMSG("file encryption failed");
- goto exit;
- }
-
- /* data decryption */
- decrypt_data_out_size = sizeof(test_data);
- decrypt_data_out = malloc(decrypt_data_out_size);
- if (!decrypt_data_out) {
- EMSG("malloc for decrypt data buffer failed");
- res = TEE_ERROR_OUT_OF_MEMORY;
- goto exit;
- }
-
- /* case1: data decryption with modified encrypted_key */
- tmp_byte = *(encrypt_data_out + 4);
- *(encrypt_data_out + 4) = ~tmp_byte;
-
- DMSG("case1: decryption with modified encrypted FEK");
-
- res = tee_fs_decrypt_file(META_FILE,
- encrypt_data_out, encrypt_data_out_size,
- decrypt_data_out, &decrypt_data_out_size,
- encrypted_fek);
- if (res == TEE_ERROR_MAC_INVALID) {
- DMSG("case1: passed, return code=%x", res);
- } else {
- EMSG("case1: failed, return code=%x", res);
- res = TEE_ERROR_GENERIC;
- goto exit;
- }
-
- *(encrypt_data_out + 4) = tmp_byte;
-
- /* case2: data decryption with modified iv */
- tmp_byte = *(encrypt_data_out + 20);
- *(encrypt_data_out + 20) = ~tmp_byte;
-
- DMSG("case2: decryption with modified IV");
-
- res = tee_fs_decrypt_file(META_FILE,
- encrypt_data_out, encrypt_data_out_size,
- decrypt_data_out, &decrypt_data_out_size,
- encrypted_fek);
- if (res == TEE_ERROR_MAC_INVALID) {
- DMSG("case2: passed, return code=%x", res);
- } else {
- EMSG("case2: failed, return code=%x", res);
- res = TEE_ERROR_GENERIC;
- goto exit;
- }
-
- *(encrypt_data_out + 20) = tmp_byte;
-
- /* case3: data decryption with modified cipher text */
- tmp_byte = *(encrypt_data_out + encrypt_data_out_size - 5);
- *(encrypt_data_out + encrypt_data_out_size - 5) = ~tmp_byte;
-
- DMSG("case3: decryption with modified cipher text");
-
- res = tee_fs_decrypt_file(META_FILE,
- encrypt_data_out, encrypt_data_out_size,
- decrypt_data_out, &decrypt_data_out_size,
- encrypted_fek);
- if (res == TEE_ERROR_MAC_INVALID) {
- DMSG("case3: passed, return code=%x", res);
- } else {
- EMSG("case3: failed, return code=%x", res);
- res = TEE_ERROR_GENERIC;
- goto exit;
- }
-
- *(encrypt_data_out + encrypt_data_out_size - 5) = tmp_byte;
-
- /* case4: data decryption with shorter cipher text length */
- DMSG("case4: decryption with shorter cipher text length");
-
- res = tee_fs_decrypt_file(META_FILE,
- encrypt_data_out, encrypt_data_out_size - 1,
- decrypt_data_out, &decrypt_data_out_size,
- encrypted_fek);
- if (res == TEE_ERROR_MAC_INVALID) {
- DMSG("case4: passed, return code=%x", res);
- } else {
- EMSG("case4: failed, return code=%x", res);
- res = TEE_ERROR_GENERIC;
- goto exit;
- }
-
- /* case5: data decryption with shorter plain text buffer */
- decrypt_data_out_size = sizeof(test_data) - 1;
-
- DMSG("case5: decryption with shorter plain text buffer");
-
- res = tee_fs_decrypt_file(META_FILE,
- encrypt_data_out, encrypt_data_out_size,
- decrypt_data_out, &decrypt_data_out_size,
- encrypted_fek);
- if (res == TEE_ERROR_SHORT_BUFFER) {
- DMSG("case5: passed, return code=%x", res);
- } else {
- EMSG("case5: failed, return code=%x", res);
- res = TEE_ERROR_GENERIC;
- goto exit;
- }
-
- decrypt_data_out_size = encrypt_data_out_size;
-
- /* data decryption with correct encrypted data */
- DMSG("good path test - decryption with correct data");
-
- res = tee_fs_decrypt_file(META_FILE,
- encrypt_data_out, encrypt_data_out_size,
- decrypt_data_out, &decrypt_data_out_size,
- encrypted_fek);
- if (res != TEE_SUCCESS) {
- EMSG("failed to decrypted data, return code=%x", res);
- goto exit;
- }
-
- /* data comparison */
- if (memcmp(test_data, decrypt_data_out, sizeof(test_data)) != 0) {
- EMSG("decrypted data doest not correct");
- res = TEE_ERROR_GENERIC;
- } else {
- DMSG("good path test - passed");
- }
-
-exit:
- if (encrypt_data_out != NULL)
- free(encrypt_data_out);
-
- if (decrypt_data_out != NULL)
- free(decrypt_data_out);
-
- DMSG("Finish");
-
- return res;
-}
-
-static TEE_Result test_file_decrypt_success(void)
-{
- TEE_Result res = TEE_SUCCESS;
- size_t header_size;
- size_t encrypt_data_out_size;
- uint8_t *encrypt_data_out = NULL;
- size_t decrypt_data_out_size;
- uint8_t *decrypt_data_out = NULL;
- uint8_t encrypted_fek[TEE_FS_KM_FEK_SIZE];
-
- DMSG("Start");
-
- res = tee_fs_generate_fek(encrypted_fek, TEE_FS_KM_FEK_SIZE);
- if (res != TEE_SUCCESS)
- goto exit;
-
- /* data encryption */
- header_size = tee_fs_get_header_size(META_FILE);
-
- encrypt_data_out_size = header_size + sizeof(test_data);
- encrypt_data_out = malloc(encrypt_data_out_size);
- if (!encrypt_data_out) {
- EMSG("malloc for encrypt data buffer failed");
- res = TEE_ERROR_OUT_OF_MEMORY;
- goto exit;
- }
-
- res = tee_fs_encrypt_file(META_FILE,
- test_data, sizeof(test_data),
- encrypt_data_out, &encrypt_data_out_size,
- encrypted_fek);
- if (res != TEE_SUCCESS) {
- EMSG("file encryption failed");
- goto exit;
- }
-
-
- /* data decryption */
- decrypt_data_out_size = sizeof(test_data);
- decrypt_data_out = malloc(decrypt_data_out_size);
- if (!decrypt_data_out) {
- EMSG("malloc for decrypt data buffer failed");
- res = TEE_ERROR_OUT_OF_MEMORY;
- goto exit;
- }
-
- res = tee_fs_decrypt_file(META_FILE,
- encrypt_data_out, encrypt_data_out_size,
- decrypt_data_out, &decrypt_data_out_size,
- encrypted_fek);
- if (res != TEE_SUCCESS)
- goto exit;
-
- /* data comparison */
- if (memcmp(test_data, decrypt_data_out, sizeof(test_data)) != 0) {
- EMSG("Data compare failed");
- res = TEE_ERROR_GENERIC;
- }
-
-exit:
- /* dump data for debug */
- if (res != TEE_SUCCESS)
- DMSG("return code = %x", res);
- else {
- DMSG("Test Data (%zu bytes)", sizeof(test_data));
- print_hex(test_data, sizeof(test_data));
- DMSG("Encrypted Data (%zu bytes)", encrypt_data_out_size);
- print_hex(encrypt_data_out, encrypt_data_out_size);
- DMSG("Decrypted Data (%zu bytes)", decrypt_data_out_size);
- print_hex(decrypt_data_out, decrypt_data_out_size);
- }
-
- if (encrypt_data_out != NULL)
- free(encrypt_data_out);
-
- if (decrypt_data_out != NULL)
- free(decrypt_data_out);
-
- DMSG("Finish");
-
- return res;
-}
-
-static TEE_Result self_tests(
- uint32_t nParamTypes __unused,
- TEE_Param pParams[TEE_NUM_PARAMS] __unused)
-{
- TEE_Result res;
-
- res = test_file_decrypt_success();
- if (res != TEE_SUCCESS)
- return res;
-
- res = test_file_decrypt_with_invalid_content();
- if (res != TEE_SUCCESS)
- return res;
-
- return TEE_SUCCESS;
-}
-
-static TEE_Result invoke_command(void *pSessionContext __unused,
- uint32_t nCommandID, uint32_t nParamTypes,
- TEE_Param pParams[TEE_NUM_PARAMS])
-{
- DMSG("command entry point for static ta \"%s\"", TA_NAME);
-
- switch (nCommandID) {
- case CMD_SELF_TESTS:
- return self_tests(nParamTypes, pParams);
- default:
- break;
- }
- return TEE_ERROR_BAD_PARAMETERS;
-}
-
-pseudo_ta_register(.uuid = ENC_FS_KEY_MANAGER_TEST_UUID, .name = TA_NAME,
- .flags = PTA_DEFAULT_FLAGS,
- .invoke_command_entry_point = invoke_command);
diff --git a/core/arch/arm/sm/psci.c b/core/arch/arm/sm/psci.c
index b2bd645..32a897c 100644
--- a/core/arch/arm/sm/psci.c
+++ b/core/arch/arm/sm/psci.c
@@ -149,7 +149,7 @@ void tee_psci_handler(struct thread_smc_args *args)
;
break;
case PSCI_SYSTEM_RESET:
- psci_system_off();
+ psci_system_reset();
while (1)
;
break;
diff --git a/core/arch/arm/sm/sm.c b/core/arch/arm/sm/sm.c
index 4a0c0f6..f3fa4af 100644
--- a/core/arch/arm/sm/sm.c
+++ b/core/arch/arm/sm/sm.c
@@ -39,6 +39,9 @@ bool sm_from_nsec(struct sm_ctx *ctx)
{
uint32_t *nsec_r0 = (uint32_t *)(&ctx->nsec.r0);
+ if (!sm_platform_handler(ctx))
+ return false;
+
#ifdef CFG_PSCI_ARM32
if (OPTEE_SMC_OWNER_NUM(*nsec_r0) == OPTEE_SMC_OWNER_STANDARD) {
smc_std_handler((struct thread_smc_args *)nsec_r0);
diff --git a/core/arch/arm/tee/arch_svc.c b/core/arch/arm/tee/arch_svc.c
index 8a89ce9..f6767d7 100644
--- a/core/arch/arm/tee/arch_svc.c
+++ b/core/arch/arm/tee/arch_svc.c
@@ -35,12 +35,12 @@
#include <tee/tee_svc_cryp.h>
#include <tee/tee_svc_storage.h>
#include <tee/se/svc.h>
+#include <tee/svc_cache.h>
#include <tee_syscall_numbers.h>
#include <trace.h>
#include <util.h>
#include "arch_svc_private.h"
-#include "svc_cache.h"
#if (TRACE_LEVEL == TRACE_FLOW) && defined(CFG_TEE_CORE_TA_TRACE)
#define TRACE_SYSCALLS
@@ -201,8 +201,8 @@ void tee_svc_handler(struct thread_svc_regs *regs)
/* TA has just entered kernel mode */
tee_ta_update_session_utime_suspend();
- /* Restore IRQ which are disabled on exception entry */
- thread_restore_irq();
+ /* Restore foreign interrupts which are disabled on exception entry */
+ thread_restore_foreign_intr();
get_scn_max_args(regs, &scn, &max_args);
diff --git a/core/arch/arm/tee/cache.c b/core/arch/arm/tee/cache.c
new file mode 100644
index 0000000..ff4bab3
--- /dev/null
+++ b/core/arch/arm/tee/cache.c
@@ -0,0 +1,79 @@
+/*
+ * Copyright (c) 2014, STMicroelectronics International N.V.
+ * Copyright (c) 2015, 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.
+ */
+
+#include <mm/core_memprot.h>
+#include <mm/core_mmu.h>
+#include <tee/cache.h>
+
+/*
+ * tee_uta_cache_operation - dynamic cache clean/inval request from a TA.
+ * It follows ARM recommendation:
+ * http://infocenter.arm.com/help/index.jsp?topic=/com.arm.doc.ddi0246d/Beicdhde.html
+ * Note that this implementation assumes dsb operations are part of
+ * cache_op_inner(), and outer cache sync are part of cache_op_outer().
+ */
+TEE_Result cache_operation(enum utee_cache_operation op, void *va, size_t len)
+{
+ TEE_Result res;
+ paddr_t pa;
+
+ pa = virt_to_phys(va);
+ if (!pa)
+ return TEE_ERROR_ACCESS_DENIED;
+
+ switch (op) {
+ case TEE_CACHEFLUSH:
+#ifdef CFG_PL310 /* prevent initial L1 clean in case there is no outer L2 */
+ /* Clean L1, Flush L2, Flush L1 */
+ res = cache_op_inner(DCACHE_AREA_CLEAN, va, len);
+ if (res != TEE_SUCCESS)
+ return res;
+ res = cache_op_outer(DCACHE_AREA_CLEAN_INV, pa, len);
+ if (res != TEE_SUCCESS)
+ return res;
+#endif
+ return cache_op_inner(DCACHE_AREA_CLEAN_INV, va, len);
+
+ case TEE_CACHECLEAN:
+ /* Clean L1, Clean L2 */
+ res = cache_op_inner(DCACHE_AREA_CLEAN, va, len);
+ if (res != TEE_SUCCESS)
+ return res;
+ return cache_op_outer(DCACHE_AREA_CLEAN, pa, len);
+
+ case TEE_CACHEINVALIDATE:
+ /* Inval L2, Inval L1 */
+ res = cache_op_outer(DCACHE_AREA_INVALIDATE, pa, len);
+ if (res != TEE_SUCCESS)
+ return res;
+ return cache_op_inner(DCACHE_AREA_INVALIDATE, va, len);
+
+ default:
+ return TEE_ERROR_NOT_SUPPORTED;
+ }
+}
diff --git a/core/arch/arm/tee/entry_fast.c b/core/arch/arm/tee/entry_fast.c
index 0e80dc8..da7cd31 100644
--- a/core/arch/arm/tee/entry_fast.c
+++ b/core/arch/arm/tee/entry_fast.c
@@ -82,17 +82,21 @@ static void tee_entry_fastcall_l2cc_mutex(struct thread_smc_args *args)
static void tee_entry_exchange_capabilities(struct thread_smc_args *args)
{
- if (args->a1) {
- /*
- * Either unknown capability or
- * OPTEE_SMC_NSEC_CAP_UNIPROCESSOR, in either case we can't
- * deal with it.
- *
- * The memory mapping of shared memory is defined as normal
- * shared memory for SMP systems and normal memory for UP
- * systems. Currently we map all memory as shared in secure
- * world.
- */
+ /*
+ * Currently we ignore OPTEE_SMC_NSEC_CAP_UNIPROCESSOR.
+ *
+ * The memory mapping of shared memory is defined as normal
+ * shared memory for SMP systems and normal memory for UP
+ * systems. Currently we map all memory as shared in secure
+ * world.
+ *
+ * When translation tables are created with shared bit cleared for
+ * uniprocessor systems we'll need to check
+ * OPTEE_SMC_NSEC_CAP_UNIPROCESSOR.
+ */
+
+ if (args->a1 & ~OPTEE_SMC_NSEC_CAP_UNIPROCESSOR) {
+ /* Unknown capability. */
args->a0 = OPTEE_SMC_RETURN_ENOTAVAIL;
return;
}
diff --git a/core/arch/arm/tee/entry_std.c b/core/arch/arm/tee/entry_std.c
index 29c3b74..233d731 100644
--- a/core/arch/arm/tee/entry_std.c
+++ b/core/arch/arm/tee/entry_std.c
@@ -51,28 +51,45 @@ static struct tee_ta_session_head tee_open_sessions =
TAILQ_HEAD_INITIALIZER(tee_open_sessions);
static struct mobj *shm_mobj;
+#ifdef CFG_SECURE_DATA_PATH
+static struct mobj **sdp_mem_mobjs;
+#endif
-static TEE_Result set_mem_param(const struct optee_msg_param *param,
- struct param_mem *mem)
+static bool param_mem_from_mobj(struct param_mem *mem, struct mobj *mobj,
+ const paddr_t pa, const size_t sz)
{
paddr_t b;
- size_t sz;
- size_t tsz;
- if (mobj_get_pa(shm_mobj, 0, 0, &b) != TEE_SUCCESS)
- panic("Failed to be PA of shared memory MOBJ");
+ if (mobj_get_pa(mobj, 0, 0, &b) != TEE_SUCCESS)
+ panic("mobj_get_pa failed");
- sz = shm_mobj->size;
- tsz = param->u.tmem.size;
- if (param->u.tmem.buf_ptr && !tsz)
- tsz++;
- if (!core_is_buffer_inside(param->u.tmem.buf_ptr, tsz, b, sz))
- return TEE_ERROR_BAD_PARAMETERS;
+ if (!core_is_buffer_inside(pa, MAX(sz, 1UL), b, mobj->size))
+ return false;
- mem->mobj = shm_mobj;
- mem->offs = param->u.tmem.buf_ptr - b;
- mem->size = param->u.tmem.size;
- return TEE_SUCCESS;
+ mem->mobj = mobj;
+ mem->offs = pa - b;
+ mem->size = sz;
+ return true;
+}
+
+/* fill 'struct param_mem' structure if buffer matches a valid memory object */
+static TEE_Result assign_mobj_to_param_mem(const paddr_t pa, const size_t sz,
+ struct param_mem *mem)
+{
+ struct mobj __maybe_unused **mobj;
+
+ /* belongs to nonsecure shared memory ? */
+ if (param_mem_from_mobj(mem, shm_mobj, pa, sz))
+ return TEE_SUCCESS;
+
+#ifdef CFG_SECURE_DATA_PATH
+ /* belongs to SDP memories ? */
+ for (mobj = sdp_mem_mobjs; *mobj; mobj++)
+ if (param_mem_from_mobj(mem, *mobj, pa, sz))
+ return TEE_SUCCESS;
+#endif
+
+ return TEE_ERROR_BAD_PARAMETERS;
}
static TEE_Result copy_in_params(const struct optee_msg_param *params,
@@ -115,7 +132,9 @@ static TEE_Result copy_in_params(const struct optee_msg_param *params,
case OPTEE_MSG_ATTR_TYPE_TMEM_INOUT:
pt[n] = TEE_PARAM_TYPE_MEMREF_INPUT + attr -
OPTEE_MSG_ATTR_TYPE_TMEM_INPUT;
- res = set_mem_param(params + n, &ta_param->u[n].mem);
+ res = assign_mobj_to_param_mem(params[n].u.tmem.buf_ptr,
+ params[n].u.tmem.size,
+ &ta_param->u[n].mem);
if (res != TEE_SUCCESS)
return res;
break;
@@ -346,7 +365,8 @@ void tee_entry_std(struct thread_smc_args *smc_args)
return;
}
- thread_set_irq(true); /* Enable IRQ for STD calls */
+ /* Enable foreign interrupts for STD calls */
+ thread_set_foreign_intr(true);
switch (arg->cmd) {
case OPTEE_MSG_CMD_OPEN_SESSION:
entry_open_session(smc_args, arg, num_params);
@@ -380,6 +400,12 @@ static TEE_Result default_mobj_init(void)
if (!mobj_sec_ddr)
panic("Failed to register secure ta ram");
+#ifdef CFG_SECURE_DATA_PATH
+ sdp_mem_mobjs = core_sdp_mem_create_mobjs();
+ if (!sdp_mem_mobjs)
+ panic("Failed to register SDP memory");
+#endif
+
return TEE_SUCCESS;
}
diff --git a/core/arch/arm/tee/pta_socket.c b/core/arch/arm/tee/pta_socket.c
index d696773..de27c55 100644
--- a/core/arch/arm/tee/pta_socket.c
+++ b/core/arch/arm/tee/pta_socket.c
@@ -38,7 +38,7 @@ static uint32_t get_instance_id(struct tee_ta_session *sess)
return sess->ctx->ops->get_instance_id(sess->ctx);
}
-static TEE_Result socket_open(struct tee_ta_session *sess, uint32_t param_types,
+static TEE_Result socket_open(uint32_t instance_id, uint32_t param_types,
TEE_Param params[TEE_NUM_PARAMS])
{
TEE_Result res;
@@ -65,7 +65,7 @@ static TEE_Result socket_open(struct tee_ta_session *sess, uint32_t param_types,
msg_params[0].attr = OPTEE_MSG_ATTR_TYPE_VALUE_INPUT;
msg_params[0].u.value.a = OPTEE_MRC_SOCKET_OPEN;
- msg_params[0].u.value.b = get_instance_id(sess);
+ msg_params[0].u.value.b = instance_id;
msg_params[1].attr = OPTEE_MSG_ATTR_TYPE_VALUE_INPUT;
msg_params[1].u.value.a = params[0].value.b; /* server port number */
@@ -90,8 +90,7 @@ static TEE_Result socket_open(struct tee_ta_session *sess, uint32_t param_types,
return res;
}
-static TEE_Result socket_close(struct tee_ta_session *sess,
- uint32_t param_types,
+static TEE_Result socket_close(uint32_t instance_id, uint32_t param_types,
TEE_Param params[TEE_NUM_PARAMS])
{
struct optee_msg_param msg_params[1];
@@ -110,13 +109,13 @@ static TEE_Result socket_close(struct tee_ta_session *sess,
msg_params[0].attr = OPTEE_MSG_ATTR_TYPE_VALUE_INPUT;
msg_params[0].u.value.a = OPTEE_MRC_SOCKET_CLOSE;
- msg_params[0].u.value.b = get_instance_id(sess);
+ msg_params[0].u.value.b = instance_id;
msg_params[0].u.value.c = params[0].value.a;
return thread_rpc_cmd(OPTEE_MSG_RPC_CMD_SOCKET, 1, msg_params);
}
-static TEE_Result socket_send(struct tee_ta_session *sess, uint32_t param_types,
+static TEE_Result socket_send(uint32_t instance_id, uint32_t param_types,
TEE_Param params[TEE_NUM_PARAMS])
{
TEE_Result res;
@@ -143,7 +142,7 @@ static TEE_Result socket_send(struct tee_ta_session *sess, uint32_t param_types,
msg_params[0].attr = OPTEE_MSG_ATTR_TYPE_VALUE_INPUT;
msg_params[0].u.value.a = OPTEE_MRC_SOCKET_SEND;
- msg_params[0].u.value.b = get_instance_id(sess);
+ msg_params[0].u.value.b = instance_id;
msg_params[0].u.value.c = params[0].value.a; /* handle */
/* buffer */
@@ -162,7 +161,7 @@ static TEE_Result socket_send(struct tee_ta_session *sess, uint32_t param_types,
return res;
}
-static TEE_Result socket_recv(struct tee_ta_session *sess, uint32_t param_types,
+static TEE_Result socket_recv(uint32_t instance_id, uint32_t param_types,
TEE_Param params[TEE_NUM_PARAMS])
{
TEE_Result res;
@@ -189,7 +188,7 @@ static TEE_Result socket_recv(struct tee_ta_session *sess, uint32_t param_types,
msg_params[0].attr = OPTEE_MSG_ATTR_TYPE_VALUE_INPUT;
msg_params[0].u.value.a = OPTEE_MRC_SOCKET_RECV;
- msg_params[0].u.value.b = get_instance_id(sess);
+ msg_params[0].u.value.b = instance_id;
msg_params[0].u.value.c = params[0].value.a; /* handle */
/* buffer */
@@ -209,8 +208,7 @@ static TEE_Result socket_recv(struct tee_ta_session *sess, uint32_t param_types,
return res;
}
-static TEE_Result socket_ioctl(struct tee_ta_session *sess,
- uint32_t param_types,
+static TEE_Result socket_ioctl(uint32_t instance_id, uint32_t param_types,
TEE_Param params[TEE_NUM_PARAMS])
{
TEE_Result res;
@@ -237,7 +235,7 @@ static TEE_Result socket_ioctl(struct tee_ta_session *sess,
msg_params[0].attr = OPTEE_MSG_ATTR_TYPE_VALUE_INPUT;
msg_params[0].u.value.a = OPTEE_MRC_SOCKET_IOCTL;
- msg_params[0].u.value.b = get_instance_id(sess);
+ msg_params[0].u.value.b = instance_id;
msg_params[0].u.value.c = params[0].value.a; /* handle */
/* buffer */
@@ -257,7 +255,7 @@ static TEE_Result socket_ioctl(struct tee_ta_session *sess,
return res;
}
-typedef TEE_Result (*ta_func)(struct tee_ta_session *sess, uint32_t param_types,
+typedef TEE_Result (*ta_func)(uint32_t instance_id, uint32_t param_types,
TEE_Param params[TEE_NUM_PARAMS]);
static const ta_func ta_funcs[] = {
@@ -274,7 +272,7 @@ static const ta_func ta_funcs[] = {
static TEE_Result pta_socket_open_session(uint32_t param_types __unused,
TEE_Param pParams[TEE_NUM_PARAMS] __unused,
- void **sess_ctx __unused)
+ void **sess_ctx)
{
struct tee_ta_session *s;
@@ -283,7 +281,7 @@ static TEE_Result pta_socket_open_session(uint32_t param_types __unused,
if (!s)
return TEE_ERROR_ACCESS_DENIED;
- *sess_ctx = s;
+ *sess_ctx = (void *)(vaddr_t)get_instance_id(s);
return TEE_SUCCESS;
}
@@ -297,7 +295,7 @@ static void pta_socket_close_session(void *sess_ctx)
msg_params[0].attr = OPTEE_MSG_ATTR_TYPE_VALUE_INPUT;
msg_params[0].u.value.a = OPTEE_MRC_SOCKET_CLOSE_ALL;
- msg_params[0].u.value.b = get_instance_id(sess_ctx);
+ msg_params[0].u.value.b = (vaddr_t)sess_ctx;
res = thread_rpc_cmd(OPTEE_MSG_RPC_CMD_SOCKET, 1, msg_params);
if (res != TEE_SUCCESS)
@@ -308,7 +306,7 @@ static TEE_Result pta_socket_invoke_command(void *sess_ctx, uint32_t cmd_id,
uint32_t param_types, TEE_Param params[TEE_NUM_PARAMS])
{
if (cmd_id < ARRAY_SIZE(ta_funcs) && ta_funcs[cmd_id])
- return ta_funcs[cmd_id](sess_ctx, param_types, params);
+ return ta_funcs[cmd_id]((vaddr_t)sess_ctx, param_types, params);
return TEE_ERROR_NOT_IMPLEMENTED;
}
diff --git a/core/arch/arm/tee/sub.mk b/core/arch/arm/tee/sub.mk
index 0ee9f64..d95c38c 100644
--- a/core/arch/arm/tee/sub.mk
+++ b/core/arch/arm/tee/sub.mk
@@ -10,3 +10,4 @@ endif
srcs-y += entry_std.c
srcs-y += entry_fast.c
srcs-y += init.c
+srcs-y += cache.c
diff --git a/core/arch/arm/tee/svc_cache.c b/core/arch/arm/tee/svc_cache.c
index 88b89a9..49ee3cf 100644
--- a/core/arch/arm/tee/svc_cache.c
+++ b/core/arch/arm/tee/svc_cache.c
@@ -25,32 +25,27 @@
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*/
-#include <types_ext.h>
-#include <utee_types.h>
+
#include <kernel/tee_ta_manager.h>
#include <mm/tee_mmu.h>
-#include <mm/core_memprot.h>
-
-#include "svc_cache.h"
+#include <tee/cache.h>
+#include <tee/svc_cache.h>
-/*
- * tee_uta_cache_operation - dynamic cache clean/inval request from a TA
- * It follows ARM recommendation:
- * http://infocenter.arm.com/help/index.jsp?topic=/com.arm.doc.ddi0246d/Beicdhde.html
- * Note that this implementation assumes dsb operations are part of
- * cache_maintenance_l1(), and L2 cache sync are part of
- * cache_maintenance_l2()
- */
-static TEE_Result cache_operation(struct tee_ta_session *sess,
- enum utee_cache_operation op, void *va, size_t len)
+TEE_Result syscall_cache_operation(void *va, size_t len, unsigned long op)
{
- TEE_Result ret;
- paddr_t pa = 0;
- struct user_ta_ctx *utc = to_user_ta_ctx(sess->ctx);
+ TEE_Result res;
+ struct tee_ta_session *sess;
+ struct user_ta_ctx *utc;
+
+ res = tee_ta_get_current_session(&sess);
+ if (res != TEE_SUCCESS)
+ return res;
if ((sess->ctx->flags & TA_FLAG_CACHE_MAINTENANCE) == 0)
return TEE_ERROR_NOT_SUPPORTED;
+ utc = to_user_ta_ctx(sess->ctx);
+
/*
* TAs are allowed to operate cache maintenance on TA memref parameters
* only, not on the TA private memory.
@@ -58,57 +53,11 @@ static TEE_Result cache_operation(struct tee_ta_session *sess,
if (tee_mmu_is_vbuf_intersect_ta_private(utc, va, len))
return TEE_ERROR_ACCESS_DENIED;
- ret = tee_mmu_check_access_rights(utc, TEE_MEMORY_ACCESS_READ |
+ res = tee_mmu_check_access_rights(utc, TEE_MEMORY_ACCESS_READ |
TEE_MEMORY_ACCESS_ANY_OWNER,
(uaddr_t)va, len);
- if (ret != TEE_SUCCESS)
- return TEE_ERROR_ACCESS_DENIED;
-
- pa = virt_to_phys(va);
- if (!pa)
- return TEE_ERROR_ACCESS_DENIED;
-
- switch (op) {
- case TEE_CACHEFLUSH:
- /* Clean L1, Flush L2, Flush L1 */
- ret = cache_maintenance_l1(DCACHE_AREA_CLEAN, va, len);
- if (ret != TEE_SUCCESS)
- return ret;
- ret = cache_maintenance_l2(L2CACHE_AREA_CLEAN_INV, pa, len);
- if (ret != TEE_SUCCESS)
- return ret;
- return cache_maintenance_l1(DCACHE_AREA_CLEAN_INV, va, len);
-
- case TEE_CACHECLEAN:
- /* Clean L1, Clean L2 */
- ret = cache_maintenance_l1(DCACHE_AREA_CLEAN, va, len);
- if (ret != TEE_SUCCESS)
- return ret;
- return cache_maintenance_l2(L2CACHE_AREA_CLEAN, pa, len);
-
- case TEE_CACHEINVALIDATE:
- /* Inval L2, Inval L1 */
- ret = cache_maintenance_l2(L2CACHE_AREA_INVALIDATE, pa, len);
- if (ret != TEE_SUCCESS)
- return ret;
- return cache_maintenance_l1(DCACHE_AREA_INVALIDATE, va, len);
-
- default:
- return TEE_ERROR_NOT_SUPPORTED;
- }
-}
-
-TEE_Result syscall_cache_operation(void *va, size_t len, unsigned long op)
-{
- TEE_Result res;
- struct tee_ta_session *s = NULL;
-
- res = tee_ta_get_current_session(&s);
if (res != TEE_SUCCESS)
- return res;
-
- if ((s->ctx->flags & TA_FLAG_CACHE_MAINTENANCE) == 0)
- return TEE_ERROR_NOT_SUPPORTED;
+ return TEE_ERROR_ACCESS_DENIED;
- return cache_operation(s, op, va, len);
+ return cache_operation(op, va, len);
}
diff --git a/core/drivers/cdns_uart.c b/core/drivers/cdns_uart.c
index 3b4e4b9..8672093 100644
--- a/core/drivers/cdns_uart.c
+++ b/core/drivers/cdns_uart.c
@@ -24,9 +24,11 @@
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*/
-#include <compiler.h>
+#include <assert.h>
#include <drivers/cdns_uart.h>
#include <io.h>
+#include <keep.h>
+#include <mm/core_mmu.h>
#include <util.h>
#define CDNS_UART_CONTROL 0
@@ -52,31 +54,44 @@
#define CDNS_UART_IRQ_RXTRIG BIT(0)
#define CDNS_UART_IRQ_RXTOUT BIT(8)
-void cdns_uart_flush(vaddr_t base)
+static vaddr_t chip_to_base(struct serial_chip *chip)
{
+ struct cdns_uart_data *pd =
+ container_of(chip, struct cdns_uart_data, chip);
+
+ return io_pa_or_va(&pd->base);
+}
+
+static void cdns_uart_flush(struct serial_chip *chip)
+{
+ vaddr_t base = chip_to_base(chip);
+
while (!(read32(base + CDNS_UART_CHANNEL_STATUS) &
- CDNS_UART_CHANNEL_STATUS_TEMPTY))
+ CDNS_UART_CHANNEL_STATUS_TEMPTY))
;
}
-/*
- * we rely on the bootloader having set up the HW correctly, we just enable
- * transmitter/receiver here, just in case.
- */
-void cdns_uart_init(vaddr_t base, uint32_t uart_clk, uint32_t baud_rate)
+static bool cdns_uart_have_rx_data(struct serial_chip *chip)
{
- if (!base || !uart_clk || !baud_rate)
- return;
+ vaddr_t base = chip_to_base(chip);
- /* Enable UART and RX/TX */
- write32(CDNS_UART_CONTROL_RXEN | CDNS_UART_CONTROL_TXEN,
- base + CDNS_UART_CONTROL);
+ return !(read32(base + CDNS_UART_CHANNEL_STATUS) &
+ CDNS_UART_CHANNEL_STATUS_REMPTY);
+}
+
+static int cdns_uart_getchar(struct serial_chip *chip)
+{
+ vaddr_t base = chip_to_base(chip);
- cdns_uart_flush(base);
+ while (!cdns_uart_have_rx_data(chip))
+ ;
+ return read32(base + CDNS_UART_FIFO) & 0xff;
}
-void cdns_uart_putc(int ch, vaddr_t base)
+static void cdns_uart_putc(struct serial_chip *chip, int ch)
{
+ vaddr_t base = chip_to_base(chip);
+
/* Wait until there is space in the FIFO */
while (read32(base + CDNS_UART_CHANNEL_STATUS) &
CDNS_UART_CHANNEL_STATUS_TFUL)
@@ -86,15 +101,31 @@ void cdns_uart_putc(int ch, vaddr_t base)
write32(ch, base + CDNS_UART_FIFO);
}
-bool cdns_uart_have_rx_data(vaddr_t base)
-{
- return !(read32(base + CDNS_UART_CHANNEL_STATUS) &
- CDNS_UART_CHANNEL_STATUS_REMPTY);
-}
-int cdns_uart_getchar(vaddr_t base)
+static const struct serial_ops cdns_uart_ops = {
+ .flush = cdns_uart_flush,
+ .getchar = cdns_uart_getchar,
+ .have_rx_data = cdns_uart_have_rx_data,
+ .putc = cdns_uart_putc,
+};
+KEEP_PAGER(cdns_uart_ops);
+
+/*
+ * we rely on the bootloader having set up the HW correctly, we just enable
+ * transmitter/receiver here, just in case.
+ */
+void cdns_uart_init(struct cdns_uart_data *pd, paddr_t base, uint32_t uart_clk,
+ uint32_t baud_rate)
{
- while (!cdns_uart_have_rx_data(base))
- ;
- return read32(base + CDNS_UART_FIFO) & 0xff;
+ pd->base.pa = base;
+ pd->chip.ops = &cdns_uart_ops;
+
+ if (!uart_clk || !baud_rate)
+ return;
+
+ /* Enable UART and RX/TX */
+ write32(CDNS_UART_CONTROL_RXEN | CDNS_UART_CONTROL_TXEN,
+ base + CDNS_UART_CONTROL);
+
+ cdns_uart_flush(&pd->chip);
}
diff --git a/core/drivers/hi16xx_uart.c b/core/drivers/hi16xx_uart.c
index 76e769d..3f8a3ca 100644
--- a/core/drivers/hi16xx_uart.c
+++ b/core/drivers/hi16xx_uart.c
@@ -24,8 +24,12 @@
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*/
+#include <assert.h>
#include <drivers/hi16xx_uart.h>
#include <io.h>
+#include <keep.h>
+#include <mm/core_mmu.h>
+#include <util.h>
/* Register offsets */
@@ -76,16 +80,66 @@
#define UART_USR_RFNE_BIT 3 /* Receive FIFO not empty bit */
#define UART_USR_RFF_BIT 4 /* Receive FIFO full bit */
-void hi16xx_uart_flush(vaddr_t base)
+static vaddr_t chip_to_base(struct serial_chip *chip)
{
+ struct hi16xx_uart_data *pd =
+ container_of(chip, struct hi16xx_uart_data, chip);
+
+ return io_pa_or_va(&pd->base);
+}
+
+static void hi16xx_uart_flush(struct serial_chip *chip)
+{
+ vaddr_t base = chip_to_base(chip);
+
+ while (!(read32(base + UART_USR) & UART_USR_TFE_BIT))
+ ;
+}
+
+static void hi16xx_uart_putc(struct serial_chip *chip, int ch)
+{
+ vaddr_t base = chip_to_base(chip);
+
+ /* Wait until TX FIFO is empty */
while (!(read32(base + UART_USR) & UART_USR_TFE_BIT))
;
+
+ /* Put character into TX FIFO */
+ write32(ch & 0xFF, base + UART_THR);
+}
+
+static bool hi16xx_uart_have_rx_data(struct serial_chip *chip)
+{
+ vaddr_t base = chip_to_base(chip);
+
+ return (read32(base + UART_USR) & UART_USR_RFNE_BIT);
+}
+
+static int hi16xx_uart_getchar(struct serial_chip *chip)
+{
+ vaddr_t base = chip_to_base(chip);
+
+ while (!hi16xx_uart_have_rx_data(chip))
+ ;
+ return read32(base + UART_RBR) & 0xFF;
}
-void hi16xx_uart_init(vaddr_t base, uint32_t uart_clk, uint32_t baud_rate)
+static const struct serial_ops hi16xx_uart_ops = {
+ .flush = hi16xx_uart_flush,
+ .getchar = hi16xx_uart_getchar,
+ .have_rx_data = hi16xx_uart_have_rx_data,
+ .putc = hi16xx_uart_putc,
+};
+KEEP_PAGER(hi16xx_uart_ops);
+
+void hi16xx_uart_init(struct hi16xx_uart_data *pd, paddr_t base,
+ uint32_t uart_clk, uint32_t baud_rate)
{
uint16_t freq_div = uart_clk / (16 * baud_rate);
+ pd->base.pa = base;
+ pd->chip.ops = &hi16xx_uart_ops;
+
/* Enable (and clear) FIFOs */
write32(UART_FCR_FIFO_EN, base + UART_FCR);
@@ -104,28 +158,6 @@ void hi16xx_uart_init(vaddr_t base, uint32_t uart_clk, uint32_t baud_rate)
/* Disable interrupt mode */
write32(0, base + UART_IEL);
- hi16xx_uart_flush(base);
-}
-
-void hi16xx_uart_putc(int ch, vaddr_t base)
-{
- /* Wait until TX FIFO is empty */
- while (!(read32(base + UART_USR) & UART_USR_TFE_BIT))
- ;
-
- /* Put character into TX FIFO */
- write32(ch & 0xFF, base + UART_THR);
-}
-
-bool hi16xx_uart_have_rx_data(vaddr_t base)
-{
- return (read32(base + UART_USR) & UART_USR_RFNE_BIT);
-}
-
-int hi16xx_uart_getchar(vaddr_t base)
-{
- while (!hi16xx_uart_have_rx_data(base))
- ;
- return read32(base + UART_RBR) & 0xFF;
+ hi16xx_uart_flush(&pd->chip);
}
diff --git a/core/drivers/imx_uart.c b/core/drivers/imx_uart.c
index b66d905..dd15ddb 100644
--- a/core/drivers/imx_uart.c
+++ b/core/drivers/imx_uart.c
@@ -25,12 +25,11 @@
* POSSIBILITY OF SUCH DAMAGE.
*/
-#include <platform_config.h>
-
+#include <assert.h>
#include <drivers/imx_uart.h>
-#include <console.h>
#include <io.h>
-#include <compiler.h>
+#include <keep.h>
+#include <util.h>
/* Register definitions */
#define URXD 0x0 /* Receiver Register */
@@ -80,33 +79,57 @@
#define UTS_RXFULL (1<<3) /* RxFIFO full */
#define UTS_SOFTRST (1<<0) /* Software reset */
-void imx_uart_init(vaddr_t __unused vbase)
+static vaddr_t chip_to_base(struct serial_chip *chip)
{
- /*
- * Do nothing, debug uart(uart0) share with normal world,
- * everything for uart0 intialization is done in bootloader.
- */
+ struct imx_uart_data *pd =
+ container_of(chip, struct imx_uart_data, chip);
+
+ return io_pa_or_va(&pd->base);
}
-void imx_uart_flush_tx_fifo(vaddr_t base)
+static void imx_uart_flush(struct serial_chip *chip)
{
+ vaddr_t base = chip_to_base(chip);
+
while (!(read32(base + UTS) & UTS_TXEMPTY))
;
}
-int imx_uart_getchar(vaddr_t base)
+static int imx_uart_getchar(struct serial_chip *chip)
{
+ vaddr_t base = chip_to_base(chip);
+
while (read32(base + UTS) & UTS_RXEMPTY)
;
return (read32(base + URXD) & URXD_RX_DATA);
}
-void imx_uart_putc(const char c, vaddr_t base)
+static void imx_uart_putc(struct serial_chip *chip, int ch)
{
- write32(c, base + UTXD);
+ vaddr_t base = chip_to_base(chip);
+
+ write32(ch, base + UTXD);
- /* wait until sent */
+ /* Wait until sent */
while (!(read32(base + UTS) & UTS_TXEMPTY))
;
}
+
+static const struct serial_ops imx_uart_ops = {
+ .flush = imx_uart_flush,
+ .getchar = imx_uart_getchar,
+ .putc = imx_uart_putc,
+};
+KEEP_PAGER(imx_uart_ops);
+
+void imx_uart_init(struct imx_uart_data *pd, paddr_t base)
+{
+ pd->base.pa = base;
+ pd->chip.ops = &imx_uart_ops;
+
+ /*
+ * Do nothing, debug uart(uart0) share with normal world,
+ * everything for uart0 initialization is done in bootloader.
+ */
+}
diff --git a/core/drivers/ns16550.c b/core/drivers/ns16550.c
index 710b351..62c6d7f 100644
--- a/core/drivers/ns16550.c
+++ b/core/drivers/ns16550.c
@@ -1,5 +1,6 @@
/*
* Copyright (C) 2015 Freescale Semiconductor, Inc.
+ * Copyright (c) 2017, Linaro Limited
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -27,6 +28,8 @@
#include <drivers/ns16550.h>
#include <io.h>
+#include <keep.h>
+#include <util.h>
/* uart register defines */
#define UART_RBR 0x0
@@ -42,16 +45,45 @@
/* uart status register bits */
#define UART_LSR_THRE 0x20 /* Transmit-hold-register empty */
-void ns16550_flush(vaddr_t base)
+static vaddr_t chip_to_base(struct serial_chip *chip)
{
+ struct ns16550_data *pd =
+ container_of(chip, struct ns16550_data, chip);
+
+ return io_pa_or_va(&pd->base);
+}
+
+static void ns16550_flush(struct serial_chip *chip)
+{
+ vaddr_t base = chip_to_base(chip);
+
while ((read8(base + UART_LSR) & UART_LSR_THRE) == 0)
;
}
-void ns16550_putc(int ch, vaddr_t base)
+static void ns16550_putc(struct serial_chip *chip, int ch)
{
- ns16550_flush(base);
+ vaddr_t base = chip_to_base(chip);
+
+ ns16550_flush(chip);
/* write out charset to Transmit-hold-register */
write8(ch, base + UART_THR);
}
+
+static const struct serial_ops ns16550_ops = {
+ .flush = ns16550_flush,
+ .putc = ns16550_putc,
+};
+KEEP_PAGER(ns16550_ops);
+
+void ns16550_init(struct ns16550_data *pd, paddr_t base)
+{
+ pd->base.pa = base;
+ pd->chip.ops = &ns16550_ops;
+
+ /*
+ * Do nothing, uart driver shared with normal world,
+ * everything for uart driver initialization is done in bootloader.
+ */
+}
diff --git a/core/drivers/pl011.c b/core/drivers/pl011.c
index 8c03090..7263707 100644
--- a/core/drivers/pl011.c
+++ b/core/drivers/pl011.c
@@ -24,8 +24,11 @@
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*/
+#include <assert.h>
#include <drivers/pl011.h>
#include <io.h>
+#include <keep.h>
+#include <util.h>
#define UART_DR 0x00 /* data register */
#define UART_RSR_ECR 0x04 /* receive status or error clear */
@@ -89,14 +92,64 @@
#define UART_IMSC_RTIM (1 << 6)
#define UART_IMSC_RXIM (1 << 4)
-void pl011_flush(vaddr_t base)
+static vaddr_t chip_to_base(struct serial_chip *chip)
{
+ struct pl011_data *pd =
+ container_of(chip, struct pl011_data, chip);
+
+ return io_pa_or_va(&pd->base);
+}
+
+static void pl011_flush(struct serial_chip *chip)
+{
+ vaddr_t base = chip_to_base(chip);
+
while (!(read32(base + UART_FR) & UART_FR_TXFE))
;
}
-void pl011_init(vaddr_t base, uint32_t uart_clk, uint32_t baud_rate)
+static bool pl011_have_rx_data(struct serial_chip *chip)
+{
+ vaddr_t base = chip_to_base(chip);
+
+ return !(read32(base + UART_FR) & UART_FR_RXFE);
+}
+
+static int pl011_getchar(struct serial_chip *chip)
+{
+ vaddr_t base = chip_to_base(chip);
+
+ while (!pl011_have_rx_data(chip))
+ ;
+ return read32(base + UART_DR) & 0xff;
+}
+
+static void pl011_putc(struct serial_chip *chip, int ch)
+{
+ vaddr_t base = chip_to_base(chip);
+
+ /* Wait until there is space in the FIFO */
+ while (read32(base + UART_FR) & UART_FR_TXFF)
+ ;
+
+ /* Send the character */
+ write32(ch, base + UART_DR);
+}
+
+static const struct serial_ops pl011_ops = {
+ .flush = pl011_flush,
+ .getchar = pl011_getchar,
+ .have_rx_data = pl011_have_rx_data,
+ .putc = pl011_putc,
+};
+KEEP_PAGER(pl011_ops);
+
+void pl011_init(struct pl011_data *pd, paddr_t base, uint32_t uart_clk,
+ uint32_t baud_rate)
{
+ pd->base.pa = base;
+ pd->chip.ops = &pl011_ops;
+
/* Clear all errors */
write32(0, base + UART_RSR_ECR);
/* Disable everything */
@@ -118,30 +171,6 @@ void pl011_init(vaddr_t base, uint32_t uart_clk, uint32_t baud_rate)
/* Enable UART and RX/TX */
write32(UART_CR_UARTEN | UART_CR_TXE | UART_CR_RXE, base + UART_CR);
- pl011_flush(base);
-}
-
-void pl011_putc(int ch, vaddr_t base)
-{
- /*
- * Wait until there is space in the FIFO
- */
- while (read32(base + UART_FR) & UART_FR_TXFF)
- ;
-
- /* Send the character */
- write32(ch, base + UART_DR);
-}
-
-bool pl011_have_rx_data(vaddr_t base)
-{
- return !(read32(base + UART_FR) & UART_FR_RXFE);
-}
-
-int pl011_getchar(vaddr_t base)
-{
- while (!pl011_have_rx_data(base))
- ;
- return read32(base + UART_DR) & 0xff;
+ pl011_flush(&pd->chip);
}
diff --git a/core/drivers/pl050.c b/core/drivers/pl050.c
index fa5feab..aedaf71 100644
--- a/core/drivers/pl050.c
+++ b/core/drivers/pl050.c
@@ -26,8 +26,9 @@
*/
#include <compiler.h>
#include <drivers/pl050.h>
-#include <util.h>
#include <io.h>
+#include <keep.h>
+#include <util.h>
#define KMI_ICR 0x00
#define KMI_STAT 0x04
@@ -91,6 +92,7 @@ static const struct serial_ops pl050_ops = {
.have_rx_data = pl050_have_rx_data,
.getchar = pl050_getchar,
};
+KEEP_PAGER(pl050_ops);
void pl050_init(struct pl050_data *pd, vaddr_t base, uint32_t clk)
{
diff --git a/core/drivers/scif.c b/core/drivers/scif.c
index 02fd49d..ff0cec8 100644
--- a/core/drivers/scif.c
+++ b/core/drivers/scif.c
@@ -1,5 +1,6 @@
/*
* Copyright (c) 2016, GlobalLogic
+ * Copyright (c) 2017, Linaro Limited
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -24,16 +25,18 @@
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*/
-#include <compiler.h>
+#include <drivers/scif.h>
#include <io.h>
+#include <keep.h>
#include <util.h>
-#include <drivers/scif.h>
+#define SCIF_SCSCR (0x08)
#define SCIF_SCFSR (0x10)
#define SCIF_SCFTDR (0x0C)
#define SCIF_SCFCR (0x18)
#define SCIF_SCFDR (0x1C)
+#define SCSCR_TE BIT(5)
#define SCFSR_TDFE BIT(5)
#define SCFSR_TEND BIT(6)
@@ -41,20 +44,26 @@
#define SCIF_TX_FIFO_SIZE 16
-void scif_uart_flush(vaddr_t base)
+static vaddr_t chip_to_base(struct serial_chip *chip)
{
- while (!(read16(base + SCIF_SCFSR) & SCFSR_TEND))
- ;
+ struct scif_uart_data *pd =
+ container_of(chip, struct scif_uart_data, chip);
+
+ return io_pa_or_va(&pd->base);
}
-void scif_uart_init(vaddr_t base)
+static void scif_uart_flush(struct serial_chip *chip)
{
- /* Bootloader should initialize device for us */
- scif_uart_flush(base);
+ vaddr_t base = chip_to_base(chip);
+
+ while (!(read16(base + SCIF_SCFSR) & SCFSR_TEND))
+ ;
}
-void scif_uart_putc(int ch, vaddr_t base)
+static void scif_uart_putc(struct serial_chip *chip, int ch)
{
+ vaddr_t base = chip_to_base(chip);
+
/* Wait until there is space in the FIFO */
while ((read16(base + SCIF_SCFDR) >> SCFDR_T_SHIFT) >=
SCIF_TX_FIFO_SIZE)
@@ -63,3 +72,20 @@ void scif_uart_putc(int ch, vaddr_t base)
write16(read16(base + SCIF_SCFSR) & ~(SCFSR_TEND | SCFSR_TDFE),
base + SCIF_SCFSR);
}
+
+static const struct serial_ops scif_uart_ops = {
+ .flush = scif_uart_flush,
+ .putc = scif_uart_putc,
+};
+KEEP_PAGER(scif_uart_ops);
+
+void scif_uart_init(struct scif_uart_data *pd, paddr_t base)
+{
+ pd->base.pa = base;
+ pd->chip.ops = &scif_uart_ops;
+
+ /* Set Transmit Enable in Control register */
+ write16(read16(base + SCIF_SCSCR) | SCSCR_TE, base + SCIF_SCSCR);
+
+ scif_uart_flush(&pd->chip);
+}
diff --git a/core/drivers/serial8250_uart.c b/core/drivers/serial8250_uart.c
index 1dd21de..5e86158 100644
--- a/core/drivers/serial8250_uart.c
+++ b/core/drivers/serial8250_uart.c
@@ -24,12 +24,13 @@
* 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/serial8250_uart.h>
+#include <compiler.h>
#include <console.h>
+#include <drivers/serial8250_uart.h>
#include <io.h>
-#include <compiler.h>
+#include <keep.h>
+#include <util.h>
/* uart register defines */
#define UART_RHR 0x0
@@ -49,45 +50,73 @@
#define LSR_EMPTY (LSR_TEMT | LSR_THRE)
#define LSR_DR 0x01 /* DATA Ready */
-void serial8250_uart_init(vaddr_t __unused base,
- uint32_t __unused uart_clk, uint32_t __unused baud_rate)
+static vaddr_t chip_to_base(struct serial_chip *chip)
{
- /*
- * do nothing, debug uart(uart0) share with normal world,
- * everything for uart0 is ready now.
- */
+ struct serial8250_uart_data *pd =
+ container_of(chip, struct serial8250_uart_data, chip);
+
+ return io_pa_or_va(&pd->base);
}
-void serial8250_uart_flush_tx_fifo(vaddr_t base)
+static void serial8250_uart_flush(struct serial_chip *chip)
{
+ vaddr_t base = chip_to_base(chip);
+
while (1) {
uint8_t state = read8(base + UART_LSR);
- /* waiting transmit fifo empty */
+ /* Wait until transmit FIFO is empty */
if ((state & LSR_EMPTY) == LSR_EMPTY)
break;
}
}
-bool serial8250_uart_have_rx_data(vaddr_t base)
+static bool serial8250_uart_have_rx_data(struct serial_chip *chip)
{
+ vaddr_t base = chip_to_base(chip);
+
return (read32(base + UART_LSR) & LSR_DR);
}
-void serial8250_uart_putc(int ch, vaddr_t base)
+static int serial8250_uart_getchar(struct serial_chip *chip)
{
- serial8250_uart_flush_tx_fifo(base);
+ vaddr_t base = chip_to_base(chip);
- /* write out charset to transmit fifo */
- write8(ch, base + UART_THR);
-}
-
-int serial8250_uart_getchar(vaddr_t base)
-{
- while (!serial8250_uart_have_rx_data(base)) {
- /* transmit fifo is empty, waiting again. */
+ while (!serial8250_uart_have_rx_data(chip)) {
+ /* Transmit FIFO is empty, waiting again */
;
}
return read8(base + UART_RHR);
}
+static void serial8250_uart_putc(struct serial_chip *chip, int ch)
+{
+ vaddr_t base = chip_to_base(chip);
+
+ serial8250_uart_flush(chip);
+
+ /* Write out character to transmit FIFO */
+ write8(ch, base + UART_THR);
+}
+
+static const struct serial_ops serial8250_uart_ops = {
+ .flush = serial8250_uart_flush,
+ .getchar = serial8250_uart_getchar,
+ .have_rx_data = serial8250_uart_have_rx_data,
+ .putc = serial8250_uart_putc,
+};
+KEEP_PAGER(serial8250_uart_ops);
+
+void serial8250_uart_init(struct serial8250_uart_data *pd, paddr_t base,
+ uint32_t __unused uart_clk,
+ uint32_t __unused baud_rate)
+
+{
+ pd->base.pa = base;
+ pd->chip.ops = &serial8250_uart_ops;
+
+ /*
+ * do nothing, debug uart(uart0) share with normal world,
+ * everything for uart0 is ready now.
+ */
+}
diff --git a/core/drivers/sprd_uart.c b/core/drivers/sprd_uart.c
index fdaa1b6..c77f595 100644
--- a/core/drivers/sprd_uart.c
+++ b/core/drivers/sprd_uart.c
@@ -1,5 +1,6 @@
/*
* Copyright (c) 2016, Spreadtrum Communications Inc.
+ * Copyright (c) 2017, Linaro Limited
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -24,8 +25,10 @@
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*/
-#include <io.h>
#include <drivers/sprd_uart.h>
+#include <io.h>
+#include <keep.h>
+#include <util.h>
/* Register definitions */
#define UART_TXD 0x0000
@@ -36,43 +39,57 @@
#define STS1_RXF_CNT_MASK 0x00ff /* Rx FIFO data counter mask */
#define STS1_TXF_CNT_MASK 0xff00 /* Tx FIFO data counter mask */
-static uint32_t sprd_uart_read(vaddr_t base, uint32_t reg)
+static vaddr_t chip_to_base(struct serial_chip *chip)
{
- return read32(base + reg);
-}
+ struct sprd_uart_data *pd =
+ container_of(chip, struct sprd_uart_data, chip);
-static void sprd_uart_write(vaddr_t base, uint32_t reg, uint32_t value)
-{
- write32(value, base + reg);
+ return io_pa_or_va(&pd->base);
}
-static void sprd_uart_wait_xmit_done(vaddr_t base)
+static void sprd_uart_flush(struct serial_chip *chip)
{
- while (sprd_uart_read(base, UART_STS1) & STS1_TXF_CNT_MASK)
+ vaddr_t base = chip_to_base(chip);
+
+ while (read32(base + UART_STS1) & STS1_TXF_CNT_MASK)
;
}
-static void sprd_uart_wait_rx_data(vaddr_t base)
+static bool sprd_uart_have_rx_data(struct serial_chip *chip)
{
- while (!(sprd_uart_read(base, UART_STS1) & STS1_RXF_CNT_MASK))
- ;
+ vaddr_t base = chip_to_base(chip);
+
+ return !!(read32(base + UART_STS1) & STS1_RXF_CNT_MASK);
}
-void sprd_uart_flush(vaddr_t base)
+static void sprd_uart_putc(struct serial_chip *chip, int ch)
{
- sprd_uart_wait_xmit_done(base);
+ vaddr_t base = chip_to_base(chip);
+
+ sprd_uart_flush(chip);
+ write32(base + UART_TXD, ch);
}
-void sprd_uart_putc(vaddr_t base, unsigned char ch)
+static int sprd_uart_getchar(struct serial_chip *chip)
{
- sprd_uart_wait_xmit_done(base);
+ vaddr_t base = chip_to_base(chip);
+
+ while (!sprd_uart_have_rx_data(chip))
+ ;
- sprd_uart_write(base, UART_TXD, (uint32_t)ch);
+ return read32(base + UART_RXD) & 0xff;
}
-unsigned char sprd_uart_getc(vaddr_t base)
-{
- sprd_uart_wait_rx_data(base);
+static const struct serial_ops sprd_uart_ops = {
+ .flush = sprd_uart_flush,
+ .getchar = sprd_uart_getchar,
+ .have_rx_data = sprd_uart_have_rx_data,
+ .putc = sprd_uart_putc,
+};
+KEEP_PAGER(sprd_uart_ops);
- return sprd_uart_read(base, UART_RXD) & 0xff;
+void sprd_uart_init(struct sprd_uart_data *pd, paddr_t base)
+{
+ pd->base.pa = base;
+ pd->chip.ops = &sprd_uart_ops;
}
diff --git a/core/arch/arm/plat-ti/console.c b/core/drivers/stih_asc.c
index 48f0f65..7f69ce7 100644
--- a/core/arch/arm/plat-ti/console.c
+++ b/core/drivers/stih_asc.c
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2016, Linaro Limited
+ * Copyright (c) 2017, Linaro Limited
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -24,44 +24,52 @@
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*/
+#include <drivers/stih_asc.h>
+#include <io.h>
+#include <keep.h>
+#include <util.h>
-#include <console.h>
-#include <drivers/serial8250_uart.h>
-#include <mm/core_memprot.h>
-#include <platform_config.h>
+#define ASC_BAUDRATE 0x00
+#define ASC_TXBUFFER 0x04
+#define ASC_STATUS 0x14
-register_phys_mem(MEM_AREA_IO_NSEC,
- CONSOLE_UART_BASE,
- SERIAL8250_UART_REG_SIZE);
+#define ASC_STATUS_TX_EMPTY BIT(1)
+#define ASC_STATUS_TX_HALF_EMPTY BIT(2)
-static vaddr_t console_base(void)
+static vaddr_t chip_to_base(struct serial_chip *chip)
{
- static void *va __early_bss;
+ struct stih_asc_pd *pd =
+ container_of(chip, struct stih_asc_pd, chip);
- if (cpu_mmu_enabled()) {
- if (!va)
- va = phys_to_virt(CONSOLE_UART_BASE, MEM_AREA_IO_NSEC);
- return (vaddr_t)va;
- }
- return CONSOLE_UART_BASE;
+ return io_pa_or_va(&pd->base);
}
-void console_init(void)
+static void stih_asc_flush(struct serial_chip *chip)
{
- serial8250_uart_init(console_base(), CONSOLE_UART_CLK_IN_HZ,
- CONSOLE_BAUDRATE);
+ vaddr_t base = chip_to_base(chip);
+
+ while (!(read32(base + ASC_STATUS) & ASC_STATUS_TX_EMPTY))
+ ;
}
-void console_putc(int ch)
+static void stih_asc_putc(struct serial_chip *chip, int ch)
{
- vaddr_t base = console_base();
+ vaddr_t base = chip_to_base(chip);
+
+ while (!(read32(base + ASC_STATUS) & ASC_STATUS_TX_HALF_EMPTY))
+ ;
- if (ch == '\n')
- serial8250_uart_putc('\r', base);
- serial8250_uart_putc(ch, base);
+ write32(ch, base + ASC_TXBUFFER);
}
-void console_flush(void)
+static const struct serial_ops stih_asc_ops = {
+ .flush = stih_asc_flush,
+ .putc = stih_asc_putc,
+};
+KEEP_PAGER(stih_asc_ops);
+
+void stih_asc_init(struct stih_asc_pd *pd, vaddr_t base)
{
- serial8250_uart_flush_tx_fifo(console_base());
+ pd->base.pa = base;
+ pd->chip.ops = &stih_asc_ops;
}
diff --git a/core/drivers/sub.mk b/core/drivers/sub.mk
index 609b378..015f5c3 100644
--- a/core/drivers/sub.mk
+++ b/core/drivers/sub.mk
@@ -17,3 +17,4 @@ srcs-$(CFG_HI16XX_UART) += hi16xx_uart.c
srcs-$(CFG_HI16XX_RNG) += hi16xx_rng.c
srcs-$(CFG_SCIF) += scif.c
srcs-$(CFG_DRA7_RNG) += dra7_rng.c
+srcs-$(CFG_STIH_UART) += stih_asc.c
diff --git a/core/drivers/sunxi_uart.c b/core/drivers/sunxi_uart.c
index 433c423..b83da02 100644
--- a/core/drivers/sunxi_uart.c
+++ b/core/drivers/sunxi_uart.c
@@ -24,11 +24,10 @@
* 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 <io.h>
-#include <compiler.h>
+#include <keep.h>
+#include <util.h>
/* uart register defines */
#define UART_REG_RBR (0x00)
@@ -55,28 +54,46 @@
#define UART_REG_USR_RFNE (0x1 << 0x3)
#define UART_REG_USR_RFF (0x1 << 0x4)
-void sunxi_uart_init(vaddr_t __unused base)
+static vaddr_t chip_to_base(struct serial_chip *chip)
{
- /* do nothing, debug uart(uart0) share with normal world,
- * everything for uart0 is ready now.
- */
+ struct sunxi_uart_data *pd =
+ container_of(chip, struct sunxi_uart_data, chip);
+
+ return io_pa_or_va(&pd->base);
}
-void sunxi_uart_flush(vaddr_t base)
+static void sunxi_uart_flush(struct serial_chip *chip)
{
+ vaddr_t base = chip_to_base(chip);
+
while (read32(base + UART_REG_TFL)) {
/* waiting transmit fifo empty */
;
}
}
-bool sunxi_uart_have_rx_data(vaddr_t base)
+static bool sunxi_uart_have_rx_data(struct serial_chip *chip)
{
+ vaddr_t base = chip_to_base(chip);
+
return read32(base + UART_REG_RFL);
}
-void sunxi_uart_putc(int ch, vaddr_t base)
+static int sunxi_uart_getchar(struct serial_chip *chip)
+{
+ vaddr_t base = chip_to_base(chip);
+
+ while (!sunxi_uart_have_rx_data(chip)) {
+ /* transmit fifo is empty, waiting again. */
+ ;
+ }
+ return read32(base + UART_REG_RBR) & 0xff;
+}
+
+static void sunxi_uart_putc(struct serial_chip *chip, int ch)
{
+ vaddr_t base = chip_to_base(chip);
+
while (!(read32(base + UART_REG_USR) & UART_REG_USR_TFNF)) {
/* transmit fifo is full, waiting again. */
;
@@ -86,12 +103,21 @@ void sunxi_uart_putc(int ch, vaddr_t base)
write8(ch, base + UART_REG_THR);
}
-int sunxi_uart_getchar(vaddr_t base)
+static const struct serial_ops sunxi_uart_ops = {
+ .flush = sunxi_uart_flush,
+ .getchar = sunxi_uart_getchar,
+ .have_rx_data = sunxi_uart_have_rx_data,
+ .putc = sunxi_uart_putc,
+};
+KEEP_PAGER(sunxi_uart_ops);
+
+void sunxi_uart_init(struct sunxi_uart_data *pd, paddr_t base)
{
- while (!sunxi_uart_have_rx_data(base)) {
- /* transmit fifo is empty, waiting again. */
- ;
- }
- return read32(base + UART_REG_RBR) & 0xff;
-}
+ pd->base.pa = base;
+ pd->chip.ops = &sunxi_uart_ops;
+ /*
+ * Do nothing, debug uart(uart0) share with normal world,
+ * everything for uart0 is ready now.
+ */
+}
diff --git a/core/include/console.h b/core/include/console.h
index 0fe8e49..d8df7f1 100644
--- a/core/include/console.h
+++ b/core/include/console.h
@@ -32,5 +32,8 @@ void console_init(void);
void console_putc(int ch);
void console_flush(void);
+struct serial_chip;
+void register_serial_console(struct serial_chip *chip);
+
#endif /* CONSOLE_H */
diff --git a/core/include/drivers/cdns_uart.h b/core/include/drivers/cdns_uart.h
index 6688fd3..d97ee37 100644
--- a/core/include/drivers/cdns_uart.h
+++ b/core/include/drivers/cdns_uart.h
@@ -1,5 +1,6 @@
/*
* Copyright (c) 2016, Xilinx Inc
+ * Copyright (c) 2017, Linaro Limited
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -28,15 +29,14 @@
#define CDNS_UART_H
#include <types_ext.h>
+#include <drivers/serial.h>
-void cdns_uart_init(vaddr_t base, uint32_t uart_clk, uint32_t baud_rate);
+struct cdns_uart_data {
+ struct io_pa_va base;
+ struct serial_chip chip;
+};
-void cdns_uart_putc(int ch, vaddr_t base);
-
-void cdns_uart_flush(vaddr_t base);
-
-bool cdns_uart_have_rx_data(vaddr_t base);
-
-int cdns_uart_getchar(vaddr_t base);
+void cdns_uart_init(struct cdns_uart_data *pd, paddr_t base, uint32_t uart_clk,
+ uint32_t baud_rate);
#endif /* CDNS_UART_H */
diff --git a/core/include/drivers/hi16xx_uart.h b/core/include/drivers/hi16xx_uart.h
index a7d4f0c..d3bd727 100644
--- a/core/include/drivers/hi16xx_uart.h
+++ b/core/include/drivers/hi16xx_uart.h
@@ -33,18 +33,16 @@
#define HI16XX_UART_H
#include <types_ext.h>
+#include <drivers/serial.h>
#define HI16XX_UART_REG_SIZE 0xF8
-void hi16xx_uart_init(vaddr_t base, uint32_t uart_clk, uint32_t baud_rate);
+struct hi16xx_uart_data {
+ struct io_pa_va base;
+ struct serial_chip chip;
+};
-void hi16xx_uart_putc(int ch, vaddr_t base);
-
-void hi16xx_uart_flush(vaddr_t base);
-
-bool hi16xx_uart_have_rx_data(vaddr_t base);
-
-int hi16xx_uart_getchar(vaddr_t base);
+void hi16xx_uart_init(struct hi16xx_uart_data *pd, paddr_t base,
+ uint32_t uart_clk, uint32_t baud_rate);
#endif /* HI16XX_UART_H */
-
diff --git a/core/include/drivers/imx_uart.h b/core/include/drivers/imx_uart.h
index db63227..bbcc953 100644
--- a/core/include/drivers/imx_uart.h
+++ b/core/include/drivers/imx_uart.h
@@ -1,5 +1,6 @@
/*
* Copyright (C) 2015 Freescale Semiconductor, Inc.
+ * Copyright (c) 2017, Linaro Limited
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -28,15 +29,13 @@
#define IMX_UART_H
#include <types_ext.h>
+#include <drivers/serial.h>
-void imx_uart_init(vaddr_t base);
+struct imx_uart_data {
+ struct io_pa_va base;
+ struct serial_chip chip;
+};
-void imx_uart_putc(const char ch, vaddr_t base);
-
-void imx_uart_flush_tx_fifo(vaddr_t base);
-
-bool imx_uart_have_rx_data(vaddr_t base);
-
-int imx_uart_getchar(vaddr_t base);
+void imx_uart_init(struct imx_uart_data *pd, paddr_t base);
#endif /* IMX_UART_H */
diff --git a/core/include/drivers/ns16550.h b/core/include/drivers/ns16550.h
index e865871..b8d1049 100644
--- a/core/include/drivers/ns16550.h
+++ b/core/include/drivers/ns16550.h
@@ -28,9 +28,13 @@
#define NS16550_H
#include <types_ext.h>
+#include <drivers/serial.h>
-void ns16550_putc(int ch, vaddr_t base);
+struct ns16550_data {
+ struct io_pa_va base;
+ struct serial_chip chip;
+};
-void ns16550_flush(vaddr_t base);
+void ns16550_init(struct ns16550_data *pd, paddr_t base);
#endif /* NS16550_H */
diff --git a/core/include/drivers/pl011.h b/core/include/drivers/pl011.h
index b83f2b2..872b7d1 100644
--- a/core/include/drivers/pl011.h
+++ b/core/include/drivers/pl011.h
@@ -28,18 +28,16 @@
#define PL011_H
#include <types_ext.h>
+#include <drivers/serial.h>
#define PL011_REG_SIZE 0x1000
-void pl011_init(vaddr_t base, uint32_t uart_clk, uint32_t baud_rate);
+struct pl011_data {
+ struct io_pa_va base;
+ struct serial_chip chip;
+};
-void pl011_putc(int ch, vaddr_t base);
-
-void pl011_flush(vaddr_t base);
-
-bool pl011_have_rx_data(vaddr_t base);
-
-int pl011_getchar(vaddr_t base);
+void pl011_init(struct pl011_data *pd, paddr_t base, uint32_t uart_clk,
+ uint32_t baud_rate);
#endif /* PL011_H */
-
diff --git a/core/include/drivers/scif.h b/core/include/drivers/scif.h
index d9d1055..f621e6c 100644
--- a/core/include/drivers/scif.h
+++ b/core/include/drivers/scif.h
@@ -1,5 +1,6 @@
/*
* Copyright (c) 2016, GlobalLogic
+ * Copyright (c) 2017, Linaro Limited
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -28,13 +29,15 @@
#define SCIF_H
#include <types_ext.h>
+#include <drivers/serial.h>
#define SCIF_REG_SIZE 0x1000
-void scif_uart_flush(vaddr_t base);
+struct scif_uart_data {
+ struct io_pa_va base;
+ struct serial_chip chip;
+};
-void scif_uart_init(vaddr_t base);
-
-void scif_uart_putc(int ch, vaddr_t base);
+void scif_uart_init(struct scif_uart_data *pd, paddr_t base);
#endif /* SCIF */
diff --git a/core/include/drivers/serial.h b/core/include/drivers/serial.h
index b8f00df..c1e9ebe 100644
--- a/core/include/drivers/serial.h
+++ b/core/include/drivers/serial.h
@@ -27,6 +27,12 @@
#ifndef __DRIVERS_SERIAL_H
#define __DRIVERS_SERIAL_H
+#include <assert.h>
+#include <stdbool.h>
+#include <types_ext.h>
+#include <mm/core_memprot.h>
+#include <mm/core_mmu.h>
+
struct serial_chip {
const struct serial_ops *ops;
};
@@ -38,4 +44,25 @@ struct serial_ops {
int (*getchar)(struct serial_chip *chip);
};
+struct io_pa_va {
+ paddr_t pa;
+ vaddr_t va;
+};
+
+/*
+ * Helper function to return a physical or virtual address for a device,
+ * depending on whether the MMU is enabled or not
+ */
+static inline vaddr_t io_pa_or_va(struct io_pa_va *p)
+{
+ assert(p->pa);
+ if (cpu_mmu_enabled()) {
+ if (!p->va)
+ p->va = (vaddr_t)phys_to_virt_io(p->pa);
+ assert(p->va);
+ return p->va;
+ }
+ return p->pa;
+}
+
#endif /*__DRIVERS_SERIASERIAL_H*/
diff --git a/core/include/drivers/serial8250_uart.h b/core/include/drivers/serial8250_uart.h
index 5b8985d..d8b5051 100644
--- a/core/include/drivers/serial8250_uart.h
+++ b/core/include/drivers/serial8250_uart.h
@@ -28,19 +28,17 @@
#define SERIAL8250_UART_H
#include <types_ext.h>
+#include <drivers/serial.h>
#define SERIAL8250_UART_REG_SIZE 0x20
-void serial8250_uart_init(vaddr_t base,
- uint32_t uart_clk, uint32_t baud_rate);
+struct serial8250_uart_data {
+ struct io_pa_va base;
+ struct serial_chip chip;
+};
-void serial8250_uart_putc(int ch, vaddr_t base);
-
-void serial8250_uart_flush_tx_fifo(vaddr_t base);
-
-bool serial8250_uart_have_rx_data(vaddr_t base);
-
-int serial8250_uart_getchar(vaddr_t base);
+void serial8250_uart_init(struct serial8250_uart_data *pd, paddr_t base,
+ uint32_t uart_clk, uint32_t baud_rate);
#endif /* SERIAL8250_UART_H */
diff --git a/core/include/drivers/sprd_uart.h b/core/include/drivers/sprd_uart.h
index c70bfb9..f89f914 100644
--- a/core/include/drivers/sprd_uart.h
+++ b/core/include/drivers/sprd_uart.h
@@ -1,5 +1,6 @@
/*
* Copyright (c) 2016, Spreadtrum Communications Inc.
+ * Copyright (c) 2017, Linaro Limited
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -28,12 +29,14 @@
#define SPRD_UART_H
#include <types_ext.h>
+#include <drivers/serial.h>
-void sprd_uart_flush(vaddr_t base);
+struct sprd_uart_data {
+ struct io_pa_va base;
+ struct serial_chip chip;
+};
-void sprd_uart_putc(vaddr_t base, unsigned char ch);
-
-unsigned char sprd_uart_getc(vaddr_t base);
+void sprd_uart_init(struct sprd_uart_data *pd, paddr_t base);
#endif /* SPRD_UART_H */
diff --git a/core/include/tee/tee_fs_defs.h b/core/include/drivers/stih_asc.h
index 9c11de9..a7cbee2 100644
--- a/core/include/tee/tee_fs_defs.h
+++ b/core/include/drivers/stih_asc.h
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2014, STMicroelectronics International N.V.
+ * Copyright (c) 2017, Linaro Limited
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -24,41 +24,20 @@
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*/
+#ifndef STIH_ASC_H
+#define STIH_ASC_H
-#ifndef TEE_FS_DEFS_H
-#define TEE_FS_DEFS_H
+#include <drivers/serial.h>
+#include <types_ext.h>
-/*
- * tee_fs_open
- */
-#define TEE_FS_O_RDONLY 0x1
-#define TEE_FS_O_WRONLY 0x2
-#define TEE_FS_O_RDWR 0x4
-#define TEE_FS_O_CREATE 0x8
-#define TEE_FS_O_EXCL 0x10
-#define TEE_FS_O_APPEND 0x20
-#define TEE_FS_O_TRUNC 0x40
+#define STIH_ASC_REG_SIZE 0x1000
-/*
- * tee_fs_lseek
- */
-#define TEE_FS_SEEK_SET 0x1
-#define TEE_FS_SEEK_END 0x2
-#define TEE_FS_SEEK_CUR 0x4
+struct stih_asc_pd {
+ struct io_pa_va base;
+ struct serial_chip chip;
+};
-/*
- * file modes
- */
-#define TEE_FS_S_IWUSR 0x1
-#define TEE_FS_S_IRUSR 0x2
-#define TEE_FS_S_IXUSR 0x4
+void stih_asc_init(struct stih_asc_pd *pb, vaddr_t base);
-/*
- * access modes
- * X_OK is not supported
- */
-#define TEE_FS_R_OK 0x1
-#define TEE_FS_W_OK 0x2
-#define TEE_FS_F_OK 0x4
+#endif /* STIH_ASC_H */
-#endif
diff --git a/core/include/drivers/sunxi_uart.h b/core/include/drivers/sunxi_uart.h
index 2b33641..a5a2b8c 100644
--- a/core/include/drivers/sunxi_uart.h
+++ b/core/include/drivers/sunxi_uart.h
@@ -28,16 +28,14 @@
#define SUNXI_UART_H
#include <types_ext.h>
+#include <drivers/serial.h>
-void sunxi_uart_init(vaddr_t base);
+struct sunxi_uart_data {
+ struct io_pa_va base;
+ struct serial_chip chip;
+};
-void sunxi_uart_putc(int ch, vaddr_t base);
-
-void sunxi_uart_flush(vaddr_t base);
-
-bool sunxi_uart_have_rx_data(vaddr_t base);
-
-int sunxi_uart_getchar(vaddr_t base);
+void sunxi_uart_init(struct sunxi_uart_data *pd, paddr_t base);
#endif /*SUNXI_UART_H*/
diff --git a/core/include/io.h b/core/include/io.h
index 510bf33..83b2efc 100644
--- a/core/include/io.h
+++ b/core/include/io.h
@@ -30,12 +30,6 @@
#include <stdint.h>
#include <types_ext.h>
-/*
- * IO access macro, please avoid using this macro, since it's going to be
- * deprecated.
- */
-#define IO(addr) (*((volatile unsigned long *)(addr)))
-
static inline void write8(uint8_t val, vaddr_t addr)
{
*(volatile uint8_t *)addr = val;
diff --git a/core/arch/arm/plat-stm/asc.h b/core/include/tee/cache.h
index bbf574c..d32e365 100644
--- a/core/arch/arm/plat-stm/asc.h
+++ b/core/include/tee/cache.h
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2014, STMicroelectronics International N.V.
+ * Copyright (c) 2015, Linaro Limited
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -24,12 +24,11 @@
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*/
-#ifndef ASC_H
-#define ASC_H
+#ifndef TEE_CACHE_H
+#define TEE_CACHE_H
-#include <types_ext.h>
+#include <utee_types.h>
-extern int __asc_xmit_char(const char p, vaddr_t base);
-extern void __asc_flush(vaddr_t base);
+TEE_Result cache_operation(enum utee_cache_operation op, void *va, size_t len);
-#endif
+#endif /* TEE_CACHE_H */
diff --git a/core/include/tee/fs_htree.h b/core/include/tee/fs_htree.h
new file mode 100644
index 0000000..3d280db
--- /dev/null
+++ b/core/include/tee/fs_htree.h
@@ -0,0 +1,186 @@
+/*
+ * Copyright (c) 2017, 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 __TEE_FS_HTREE_H
+#define __TEE_FS_HTREE_H
+
+/*
+ * The purpose of this API is to provide file integrity and confidentiality
+ * in order to implement secure storage. On-disk data structures are
+ * duplicated to make updates atomic, an update is finalized to disk with
+ * tee_fs_htree_sync_to_storage().
+ *
+ * This implementation doesn't provide rollback protection, it only
+ * guarantees the integrity and confidentiality of the file.
+ */
+
+#include <tee_api_types.h>
+#include <utee_defines.h>
+
+#define TEE_FS_HTREE_HASH_SIZE TEE_SHA256_HASH_SIZE
+#define TEE_FS_HTREE_IV_SIZE 16
+#define TEE_FS_HTREE_FEK_SIZE 16
+#define TEE_FS_HTREE_TAG_SIZE 16
+
+/* Internal struct provided to let the rpc callbacks know the size if needed */
+struct tee_fs_htree_node_image {
+ /* Note that calc_node_hash() depends on hash first in struct */
+ uint8_t hash[TEE_FS_HTREE_HASH_SIZE];
+ uint8_t iv[TEE_FS_HTREE_IV_SIZE];
+ uint8_t tag[TEE_FS_HTREE_TAG_SIZE];
+ uint16_t flags;
+};
+
+/*
+ * This struct is not interpreted by the hash tree, it's up to the user of
+ * the interface to update etc if needed.
+ */
+struct tee_fs_htree_meta {
+ uint64_t length;
+};
+
+/* Internal struct needed by struct tee_fs_htree_image */
+struct tee_fs_htree_imeta {
+ struct tee_fs_htree_meta meta;
+ uint32_t max_node_id;
+};
+
+/* Internal struct provided to let the rpc callbacks know the size if needed */
+struct tee_fs_htree_image {
+ uint8_t iv[TEE_FS_HTREE_IV_SIZE];
+ uint8_t tag[TEE_FS_HTREE_TAG_SIZE];
+ uint8_t enc_fek[TEE_FS_HTREE_FEK_SIZE];
+ uint8_t imeta[sizeof(struct tee_fs_htree_imeta)];
+ uint32_t counter;
+};
+
+/**
+ * enum tee_fs_htree_type - type of hash tree element
+ * @TEE_FS_HTREE_TYPE_HEAD: indicates a struct tee_fs_htree_image
+ * @TEE_FS_HTREE_TYPE_NODE: indicates a struct tee_fs_htree_node_image
+ * @TEE_FS_HTREE_TYPE_BLOCK: indicates a data block
+ */
+enum tee_fs_htree_type {
+ TEE_FS_HTREE_TYPE_HEAD,
+ TEE_FS_HTREE_TYPE_NODE,
+ TEE_FS_HTREE_TYPE_BLOCK,
+};
+
+struct tee_fs_rpc_operation;
+
+/**
+ * struct tee_fs_htree_storage - storage description supplied by user of
+ * this interface
+ * @block_size: size of data blocks
+ * @rpc_read_init: initialize a struct tee_fs_rpc_operation for an RPC read
+ * operation
+ * @rpc_write_init: initialize a struct tee_fs_rpc_operation for an RPC
+ * write operation
+ *
+ * The @idx arguments starts counting from 0. The @vers arguments are either
+ * 0 or 1. The @data arguments is a pointer to a buffer in non-secure shared
+ * memory where the encrypted data is stored.
+ */
+struct tee_fs_htree_storage {
+ size_t block_size;
+ TEE_Result (*rpc_read_init)(void *aux, struct tee_fs_rpc_operation *op,
+ enum tee_fs_htree_type type, size_t idx,
+ uint8_t vers, void **data);
+ TEE_Result (*rpc_read_final)(struct tee_fs_rpc_operation *op,
+ size_t *bytes);
+ TEE_Result (*rpc_write_init)(void *aux, struct tee_fs_rpc_operation *op,
+ enum tee_fs_htree_type type, size_t idx,
+ uint8_t vers, void **data);
+ TEE_Result (*rpc_write_final)(struct tee_fs_rpc_operation *op);
+};
+
+struct tee_fs_htree;
+
+/**
+ * tee_fs_htree_open() - opens/creates a hash tree
+ * @create: true if a new hash tree is to be created, else the hash tree
+ * is read in and verified
+ * @stor: storage description
+ * @stor_aux: auxilary pointer supplied to callbacks in struct
+ * tee_fs_htree_storage
+ * @ht: returned hash tree on success
+ */
+TEE_Result tee_fs_htree_open(bool create,
+ const struct tee_fs_htree_storage *stor,
+ void *stor_aux, struct tee_fs_htree **ht);
+/**
+ * tee_fs_htree_close() - close a hash tree
+ * @ht: hash tree
+ */
+void tee_fs_htree_close(struct tee_fs_htree **ht);
+
+/**
+ * tee_fs_htree_get_meta() - get a pointer to associated struct
+ * tee_fs_htree_meta
+ * @ht: hash tree
+ */
+struct tee_fs_htree_meta *tee_fs_htree_get_meta(struct tee_fs_htree *ht);
+
+/**
+ * tee_fs_htree_sync_to_storage() - synchronize hash tree to storage
+ * @ht: hash tree
+ *
+ * Frees the hash tree and sets *ht to NULL on failure and returns an error code
+ */
+TEE_Result tee_fs_htree_sync_to_storage(struct tee_fs_htree **ht);
+
+/**
+ * tee_fs_htree_truncate() - truncate a hash tree
+ * @ht: hash tree
+ * @block_num: the number of nodes to truncate to
+ *
+ * Frees the hash tree and sets *ht to NULL on failure and returns an error code
+ */
+TEE_Result tee_fs_htree_truncate(struct tee_fs_htree **ht, size_t block_num);
+
+/**
+ * tee_fs_htree_write_block() - encrypt and write a data block to storage
+ * @ht: hash tree
+ * @block_num: block number
+ * @block: pointer to a block of stor->block_size size
+ *
+ * Frees the hash tree and sets *ht to NULL on failure and returns an error code
+ */
+TEE_Result tee_fs_htree_write_block(struct tee_fs_htree **ht, size_t block_num,
+ const void *block);
+/**
+ * tee_fs_htree_write_block() - read and decrypt a data block from storage
+ * @ht: hash tree
+ * @block_num: block number
+ * @block: pointer to a block of stor->block_size size
+ *
+ * Frees the hash tree and sets *ht to NULL on failure and returns an error code
+ */
+TEE_Result tee_fs_htree_read_block(struct tee_fs_htree **ht, size_t block_num,
+ void *block);
+
+#endif /*__TEE_FS_HTREE_H*/
diff --git a/core/arch/arm/tee/svc_cache.h b/core/include/tee/svc_cache.h
index d5d4972..d5d4972 100644
--- a/core/arch/arm/tee/svc_cache.h
+++ b/core/include/tee/svc_cache.h
diff --git a/core/include/tee/tee_cryp_utl.h b/core/include/tee/tee_cryp_utl.h
index 99304f5..b303a59 100644
--- a/core/include/tee/tee_cryp_utl.h
+++ b/core/include/tee/tee_cryp_utl.h
@@ -50,5 +50,10 @@ TEE_Result tee_aes_cbc_cts_update(void *cbc_ctx, void *ecb_ctx,
TEE_Result tee_prng_add_entropy(const uint8_t *in, size_t len);
void plat_prng_add_jitter_entropy(void);
+/*
+ * The _norpc version must not invoke Normal World, or infinite recursion
+ * may occur. As an exception however, using mutexes is allowed.
+ */
+void plat_prng_add_jitter_entropy_norpc(void);
#endif
diff --git a/core/include/tee/tee_fs.h b/core/include/tee/tee_fs.h
index 299ef74..81253da 100644
--- a/core/include/tee/tee_fs.h
+++ b/core/include/tee/tee_fs.h
@@ -38,30 +38,31 @@ typedef int64_t tee_fs_off_t;
typedef uint32_t tee_fs_mode_t;
struct tee_fs_dirent {
- char *d_name;
+ uint8_t oid[TEE_OBJECT_ID_MAX_LEN];
+ size_t oidlen;
};
struct tee_fs_dir;
struct tee_file_handle;
+struct tee_pobj;
/*
* tee_fs implements a POSIX like secure file system with GP extension
*/
struct tee_file_operations {
- TEE_Result (*open)(const char *name, struct tee_file_handle **fh);
- TEE_Result (*create)(const char *name, struct tee_file_handle **fh);
+ TEE_Result (*open)(struct tee_pobj *po, struct tee_file_handle **fh);
+ TEE_Result (*create)(struct tee_pobj *po, struct tee_file_handle **fh);
void (*close)(struct tee_file_handle **fh);
- TEE_Result (*read)(struct tee_file_handle *fh, void *buf, size_t *len);
- TEE_Result (*write)(struct tee_file_handle *fh, const void *buf,
- size_t len);
- TEE_Result (*seek)(struct tee_file_handle *fh, int32_t offs,
- TEE_Whence whence, int32_t *new_offs);
- TEE_Result (*rename)(const char *old_name, const char *new_name,
+ TEE_Result (*read)(struct tee_file_handle *fh, size_t pos,
+ void *buf, size_t *len);
+ TEE_Result (*write)(struct tee_file_handle *fh, size_t pos,
+ const void *buf, size_t len);
+ TEE_Result (*rename)(struct tee_pobj *old_po, struct tee_pobj *new_po,
bool overwrite);
- TEE_Result (*remove)(const char *name);
+ TEE_Result (*remove)(struct tee_pobj *po);
TEE_Result (*truncate)(struct tee_file_handle *fh, size_t size);
- TEE_Result (*opendir)(const char *name, struct tee_fs_dir **d);
+ TEE_Result (*opendir)(const TEE_UUID *uuid, struct tee_fs_dir **d);
TEE_Result (*readdir)(struct tee_fs_dir *d, struct tee_fs_dirent **ent);
void (*closedir)(struct tee_fs_dir *d);
};
diff --git a/core/include/tee/tee_fs_key_manager.h b/core/include/tee/tee_fs_key_manager.h
index 7f26d26..b7259aa 100644
--- a/core/include/tee/tee_fs_key_manager.h
+++ b/core/include/tee/tee_fs_key_manager.h
@@ -33,62 +33,17 @@
#define TEE_FS_KM_CHIP_ID_LENGTH 32
#define TEE_FS_KM_HMAC_ALG TEE_ALG_HMAC_SHA256
-#define TEE_FS_KM_AUTH_ENC_ALG TEE_ALG_AES_GCM
#define TEE_FS_KM_ENC_FEK_ALG TEE_ALG_AES_ECB_NOPAD
#define TEE_FS_KM_SSK_SIZE TEE_SHA256_HASH_SIZE
#define TEE_FS_KM_TSK_SIZE TEE_SHA256_HASH_SIZE
#define TEE_FS_KM_FEK_SIZE 16 /* bytes */
-#define TEE_FS_KM_IV_LEN 12 /* bytes */
-#define TEE_FS_KM_MAX_TAG_LEN 16 /* bytes */
-
-#define BLOCK_FILE_SHIFT 12
-
-#define BLOCK_FILE_SIZE (1 << BLOCK_FILE_SHIFT)
-
-#define NUM_BLOCKS_PER_FILE 1024
-
-enum tee_fs_file_type {
- META_FILE,
- BLOCK_FILE
-};
-
-struct tee_fs_file_info {
- uint64_t length;
- uint32_t backup_version_table[NUM_BLOCKS_PER_FILE / 32];
-};
-
-struct tee_fs_file_meta {
- struct tee_fs_file_info info;
- uint8_t encrypted_fek[TEE_FS_KM_FEK_SIZE];
- uint32_t counter;
-};
-
-struct common_header {
- uint8_t iv[TEE_FS_KM_IV_LEN];
- uint8_t tag[TEE_FS_KM_MAX_TAG_LEN];
-};
-
-struct meta_header {
- uint8_t encrypted_key[TEE_FS_KM_FEK_SIZE];
- struct common_header common;
-};
-
-struct block_header {
- struct common_header common;
-};
-
-size_t tee_fs_get_header_size(enum tee_fs_file_type type);
TEE_Result tee_fs_generate_fek(uint8_t *encrypted_fek, int fek_size);
-TEE_Result tee_fs_encrypt_file(enum tee_fs_file_type file_type,
- const uint8_t *plaintext, size_t plaintext_size,
- uint8_t *ciphertext, size_t *ciphertext_size,
- const uint8_t *encrypted_fek);
-TEE_Result tee_fs_decrypt_file(enum tee_fs_file_type file_type,
- const uint8_t *data_in, size_t data_in_size,
- uint8_t *plaintext, size_t *plaintext_size,
- uint8_t *encrypted_fek);
TEE_Result tee_fs_crypt_block(uint8_t *out, const uint8_t *in, size_t size,
uint16_t blk_idx, const uint8_t *encrypted_fek,
TEE_OperationMode mode);
+
+TEE_Result tee_fs_fek_crypt(TEE_OperationMode mode, const uint8_t *in_key,
+ size_t size, uint8_t *out_key);
+
#endif
diff --git a/core/include/tee/tee_fs_rpc.h b/core/include/tee/tee_fs_rpc.h
index 4d73c4b..43c7631 100644
--- a/core/include/tee/tee_fs_rpc.h
+++ b/core/include/tee/tee_fs_rpc.h
@@ -44,8 +44,8 @@ struct tee_fs_rpc_operation {
size_t num_params;
};
-TEE_Result tee_fs_rpc_open(uint32_t id, const char *fname, int *fd);
-TEE_Result tee_fs_rpc_create(uint32_t id, const char *fname, int *fd);
+TEE_Result tee_fs_rpc_open(uint32_t id, struct tee_pobj *po, int *fd);
+TEE_Result tee_fs_rpc_create(uint32_t id, struct tee_pobj *po, int *fd);
TEE_Result tee_fs_rpc_close(uint32_t id, int fd);
TEE_Result tee_fs_rpc_read_init(struct tee_fs_rpc_operation *op,
@@ -61,11 +61,11 @@ TEE_Result tee_fs_rpc_write_final(struct tee_fs_rpc_operation *op);
TEE_Result tee_fs_rpc_truncate(uint32_t id, int fd, size_t len);
-TEE_Result tee_fs_rpc_remove(uint32_t id, const char *fname);
-TEE_Result tee_fs_rpc_rename(uint32_t id, const char *old_fname,
- const char *new_fname, bool overwrite);
+TEE_Result tee_fs_rpc_remove(uint32_t id, struct tee_pobj *po);
+TEE_Result tee_fs_rpc_rename(uint32_t id, struct tee_pobj *old,
+ struct tee_pobj *new, bool overwrite);
-TEE_Result tee_fs_rpc_opendir(uint32_t id, const char *name,
+TEE_Result tee_fs_rpc_opendir(uint32_t id, const TEE_UUID *uuid,
struct tee_fs_dir **d);
TEE_Result tee_fs_rpc_closedir(uint32_t id, struct tee_fs_dir *d);
TEE_Result tee_fs_rpc_readdir(uint32_t id, struct tee_fs_dir *d,
diff --git a/core/include/tee/tee_obj.h b/core/include/tee/tee_obj.h
index bb82c9c..2224233 100644
--- a/core/include/tee/tee_obj.h
+++ b/core/include/tee/tee_obj.h
@@ -40,9 +40,9 @@ struct tee_obj {
bool busy; /* true if used by an operation */
uint32_t have_attrs; /* bitfield identifying set properties */
void *attr;
+ size_t ds_pos;
struct tee_pobj *pobj; /* ptr to persistant object */
struct tee_file_handle *fh;
- uint32_t ds_size; /* data stream size */
uint32_t flags; /* permission flags for persistent objects */
};
diff --git a/core/include/tee/tee_pobj.h b/core/include/tee/tee_pobj.h
index db7c9a6..29b7f77 100644
--- a/core/include/tee/tee_pobj.h
+++ b/core/include/tee/tee_pobj.h
@@ -40,12 +40,14 @@ struct tee_pobj {
void *obj_id;
uint32_t obj_id_len;
uint32_t flags;
+ bool temporary;
/* Filesystem handling this object */
const struct tee_file_operations *fops;
};
TEE_Result tee_pobj_get(TEE_UUID *uuid, void *obj_id, uint32_t obj_id_len,
- uint32_t flags, const struct tee_file_operations *fops,
+ uint32_t flags, bool temporary,
+ const struct tee_file_operations *fops,
struct tee_pobj **obj);
TEE_Result tee_pobj_release(struct tee_pobj *obj);
diff --git a/core/include/tee/tee_svc_storage.h b/core/include/tee/tee_svc_storage.h
index 7e4c10e..d3f0858 100644
--- a/core/include/tee/tee_svc_storage.h
+++ b/core/include/tee/tee_svc_storage.h
@@ -82,11 +82,11 @@ void tee_svc_storage_close_all_enum(struct user_ta_ctx *utc);
void tee_svc_storage_init(void);
-char *tee_svc_storage_create_filename(struct tee_ta_session *sess,
- void *object_id,
- uint32_t object_id_len,
- bool transient);
+struct tee_pobj;
+TEE_Result tee_svc_storage_create_filename(void *buf, size_t blen,
+ struct tee_pobj *po, bool transient);
-char *tee_svc_storage_create_dirname(struct tee_ta_session *sess);
+TEE_Result tee_svc_storage_create_dirname(void *buf, size_t blen,
+ const TEE_UUID *uuid);
#endif /* TEE_SVC_STORAGE_H */
diff --git a/core/arch/arm/plat-sunxi/console.c b/core/kernel/console.c
index b985316..2fce361 100644
--- a/core/arch/arm/plat-sunxi/console.c
+++ b/core/kernel/console.c
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2014, Allwinner Technology Co., Ltd.
+ * Copyright (c) 2017, Linaro Limited
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -25,35 +25,32 @@
* POSSIBILITY OF SUCH DAMAGE.
*/
-#include <platform_config.h>
-#include <drivers/sunxi_uart.h>
-#include <mm/core_memprot.h>
#include <console.h>
+#include <compiler.h>
+#include <drivers/serial.h>
+#include <stdlib.h>
-static vaddr_t console_base(void)
+static struct serial_chip *serial_console __early_bss;
+
+void __weak console_putc(int ch)
{
- static void *va;
+ if (!serial_console)
+ return;
- if (cpu_mmu_enabled()) {
- if (!va)
- va = phys_to_virt(CONSOLE_UART_BASE, MEM_AREA_IO_SEC);
- return (vaddr_t)va;
- }
- return CONSOLE_UART_BASE;
+ if (ch == '\n')
+ serial_console->ops->putc(serial_console, '\r');
+ serial_console->ops->putc(serial_console, ch);
}
-
-void console_init(void)
+void __weak console_flush(void)
{
- sunxi_uart_init(console_base());
-}
+ if (!serial_console)
+ return;
-void console_putc(int ch)
-{
- sunxi_uart_putc(ch, console_base());
+ serial_console->ops->flush(serial_console);
}
-void console_flush(void)
+void register_serial_console(struct serial_chip *chip)
{
- sunxi_uart_flush(console_base());
+ serial_console = chip;
}
diff --git a/core/kernel/sub.mk b/core/kernel/sub.mk
index aa00ae5..963e078 100644
--- a/core/kernel/sub.mk
+++ b/core/kernel/sub.mk
@@ -1,4 +1,5 @@
srcs-y += assert.c
+srcs-y += console.c
srcs-y += tee_ta_manager.c
srcs-y += tee_misc.c
srcs-y += panic.c
diff --git a/core/kernel/tee_ta_manager.c b/core/kernel/tee_ta_manager.c
index c0c4545..a3651e5 100644
--- a/core/kernel/tee_ta_manager.c
+++ b/core/kernel/tee_ta_manager.c
@@ -43,6 +43,7 @@
#include <kernel/user_ta.h>
#include <mm/core_mmu.h>
#include <mm/core_memprot.h>
+#include <mm/mobj.h>
#include <mm/tee_mmu.h>
#include <tee/tee_svc_cryp.h>
#include <tee/tee_obj.h>
@@ -277,6 +278,58 @@ static TEE_Result check_client(struct tee_ta_session *s, const TEE_Identity *id)
return TEE_SUCCESS;
}
+/*
+ * Check if invocation parameters matches TA properties
+ *
+ * @s - current session handle
+ * @param - already identified memory references hold a valid 'mobj'.
+ *
+ * Policy:
+ * - All TAs can access 'non-secure' shared memory.
+ * - All TAs can access TEE private memory (seccpy)
+ * - Only SDP flagged TAs can accept SDP memory references.
+ */
+#ifndef CFG_SECURE_DATA_PATH
+static bool check_params(struct tee_ta_session *sess __unused,
+ struct tee_ta_param *param __unused)
+{
+ /*
+ * When CFG_SECURE_DATA_PATH is not enabled, SDP memory references
+ * are rejected at OP-TEE core entry. Hence here all TAs have same
+ * permissions regarding memory reference parameters.
+ */
+ return true;
+}
+#else
+static bool check_params(struct tee_ta_session *sess,
+ struct tee_ta_param *param)
+{
+ int n;
+
+ /*
+ * When CFG_SECURE_DATA_PATH is enabled, OP-TEE entry allows SHM and
+ * SDP memory references. Only TAs flagged SDP can access SDP memory.
+ */
+ if (sess->ctx->flags & TA_FLAG_SECURE_DATA_PATH)
+ return true;
+
+ for (n = 0; n < TEE_NUM_PARAMS; n++) {
+ uint32_t param_type = TEE_PARAM_TYPE_GET(param->types, n);
+ struct param_mem *mem = &param->u[n].mem;
+
+ if (param_type != TEE_PARAM_TYPE_MEMREF_INPUT &&
+ param_type != TEE_PARAM_TYPE_MEMREF_OUTPUT &&
+ param_type != TEE_PARAM_TYPE_MEMREF_INOUT)
+ continue;
+ if (!mem->size)
+ continue;
+ if (mobj_is_sdp_mem(mem->mobj))
+ return false;
+ }
+ return true;
+}
+#endif
+
static void set_invoke_timeout(struct tee_ta_session *sess,
uint32_t cancel_req_to)
{
@@ -481,6 +534,9 @@ TEE_Result tee_ta_open_session(TEE_ErrorOrigin *err,
return res;
}
+ if (!check_params(s, param))
+ return TEE_ERROR_BAD_PARAMETERS;
+
ctx = s->ctx;
if (ctx->panicked) {
@@ -536,6 +592,9 @@ TEE_Result tee_ta_invoke_command(TEE_ErrorOrigin *err,
if (check_client(sess, clnt_id) != TEE_SUCCESS)
return TEE_ERROR_BAD_PARAMETERS; /* intentional generic error */
+ if (!check_params(sess, param))
+ return TEE_ERROR_BAD_PARAMETERS;
+
if (sess->ctx->panicked) {
DMSG(" Panicked !");
*err = TEE_ORIGIN_TEE;
diff --git a/core/lib/libtomcrypt/src/tee_ltc_provider.c b/core/lib/libtomcrypt/src/tee_ltc_provider.c
index 06dc983..a89640b 100644
--- a/core/lib/libtomcrypt/src/tee_ltc_provider.c
+++ b/core/lib/libtomcrypt/src/tee_ltc_provider.c
@@ -171,7 +171,7 @@ static TEE_Result tee_ltc_prng_init(struct tee_ltc_prng *prng)
prng->index = prng_index;
- plat_prng_add_jitter_entropy();
+ plat_prng_add_jitter_entropy_norpc();
return TEE_SUCCESS;
}
diff --git a/core/tee/fs_htree.c b/core/tee/fs_htree.c
new file mode 100644
index 0000000..53cb81e
--- /dev/null
+++ b/core/tee/fs_htree.c
@@ -0,0 +1,937 @@
+/*
+ * Copyright (c) 2017, 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.
+ */
+
+#include <assert.h>
+#include <initcall.h>
+#include <kernel/tee_common_otp.h>
+#include <optee_msg_supplicant.h>
+#include <stdlib.h>
+#include <string_ext.h>
+#include <string.h>
+#include <tee/fs_htree.h>
+#include <tee/tee_cryp_provider.h>
+#include <tee/tee_fs_key_manager.h>
+#include <tee/tee_fs_rpc.h>
+#include <utee_defines.h>
+#include <util.h>
+
+#define TEE_FS_HTREE_CHIP_ID_SIZE 32
+#define TEE_FS_HTREE_HASH_ALG TEE_ALG_SHA256
+#define TEE_FS_HTREE_TSK_SIZE TEE_FS_HTREE_HASH_SIZE
+#define TEE_FS_HTREE_ENC_ALG TEE_ALG_AES_ECB_NOPAD
+#define TEE_FS_HTREE_ENC_SIZE TEE_AES_BLOCK_SIZE
+#define TEE_FS_HTREE_SSK_SIZE TEE_FS_HTREE_HASH_SIZE
+
+#define TEE_FS_HTREE_AUTH_ENC_ALG TEE_ALG_AES_GCM
+#define TEE_FS_HTREE_HMAC_ALG TEE_ALG_HMAC_SHA256
+
+#define BLOCK_NUM_TO_NODE_ID(num) ((num) + 1)
+
+#define NODE_ID_TO_BLOCK_NUM(id) ((id) - 1)
+
+/*
+ * The hash tree is implemented as a binary tree with the purpose to ensure
+ * integrity of the data in the nodes. The data in the nodes their turn
+ * provides both integrity and confidentiality of the data blocks.
+ *
+ * The hash tree is saved in a file as:
+ * +----------------------------+
+ * | htree_image.0 |
+ * | htree_image.1 |
+ * +----------------------------+
+ * | htree_node_image.1.0 |
+ * | htree_node_image.1.1 |
+ * +----------------------------+
+ * | htree_node_image.2.0 |
+ * | htree_node_image.2.1 |
+ * +----------------------------+
+ * | htree_node_image.3.0 |
+ * | htree_node_image.3.1 |
+ * +----------------------------+
+ * | htree_node_image.4.0 |
+ * | htree_node_image.4.1 |
+ * +----------------------------+
+ * ...
+ *
+ * htree_image is the header of the file, there's two instances of it. One
+ * which is committed and the other is used when updating the file. Which
+ * is committed is indicated by the "counter" field, the one with the
+ * largest value is selected.
+ *
+ * htree_node_image is a node in the hash tree, each node has two instances
+ * which is committed is decided by the parent node .flag bit
+ * HTREE_NODE_COMMITTED_CHILD. Which version is the committed version of
+ * node 1 is determined by the by the lowest bit of the counter field in
+ * the header.
+ *
+ * Note that nodes start counting at 1 while blocks at 0, this means that
+ * block 0 is represented by node 1.
+ *
+ * Where different elements are stored in the file is managed by the file
+ * system. In the case of SQL FS the version of the node/block is ignored
+ * as the atomic update is finalized with a call to
+ * tee_fs_rpc_end_transaction().
+ */
+
+#define HTREE_NODE_COMMITTED_BLOCK BIT32(0)
+/* n is 0 or 1 */
+#define HTREE_NODE_COMMITTED_CHILD(n) BIT32(1 + (n))
+
+struct htree_node {
+ size_t id;
+ bool dirty;
+ bool block_updated;
+ struct tee_fs_htree_node_image node;
+ struct htree_node *parent;
+ struct htree_node *child[2];
+};
+
+struct tee_fs_htree {
+ struct htree_node root;
+ struct tee_fs_htree_image head;
+ uint8_t fek[TEE_FS_HTREE_FEK_SIZE];
+ struct tee_fs_htree_imeta imeta;
+ bool dirty;
+ const struct tee_fs_htree_storage *stor;
+ void *stor_aux;
+};
+
+struct traverse_arg;
+typedef TEE_Result (*traverse_cb_t)(struct traverse_arg *targ,
+ struct htree_node *node);
+struct traverse_arg {
+ struct tee_fs_htree *ht;
+ traverse_cb_t cb;
+ void *arg;
+};
+
+static TEE_Result rpc_read(struct tee_fs_htree *ht, enum tee_fs_htree_type type,
+ size_t idx, size_t vers, void *data, size_t dlen)
+{
+ TEE_Result res;
+ struct tee_fs_rpc_operation op;
+ size_t bytes;
+ void *p;
+
+ res = ht->stor->rpc_read_init(ht->stor_aux, &op, type, idx, vers, &p);
+ if (res != TEE_SUCCESS)
+ return res;
+
+ res = ht->stor->rpc_read_final(&op, &bytes);
+ if (res != TEE_SUCCESS)
+ return res;
+
+ if (bytes != dlen)
+ return TEE_ERROR_CORRUPT_OBJECT;
+
+ memcpy(data, p, dlen);
+ return TEE_SUCCESS;
+}
+
+static TEE_Result rpc_read_head(struct tee_fs_htree *ht, size_t vers,
+ struct tee_fs_htree_image *head)
+{
+ return rpc_read(ht, TEE_FS_HTREE_TYPE_HEAD, 0, vers,
+ head, sizeof(*head));
+}
+
+static TEE_Result rpc_read_node(struct tee_fs_htree *ht, size_t node_id,
+ size_t vers,
+ struct tee_fs_htree_node_image *node)
+{
+ return rpc_read(ht, TEE_FS_HTREE_TYPE_NODE, node_id - 1, vers,
+ node, sizeof(*node));
+}
+
+static TEE_Result rpc_write(struct tee_fs_htree *ht,
+ enum tee_fs_htree_type type, size_t idx,
+ size_t vers, const void *data, size_t dlen)
+{
+ TEE_Result res;
+ struct tee_fs_rpc_operation op;
+ void *p;
+
+ res = ht->stor->rpc_write_init(ht->stor_aux, &op, type, idx, vers, &p);
+ if (res != TEE_SUCCESS)
+ return res;
+
+ memcpy(p, data, dlen);
+ return ht->stor->rpc_write_final(&op);
+}
+
+static TEE_Result rpc_write_head(struct tee_fs_htree *ht, size_t vers,
+ const struct tee_fs_htree_image *head)
+{
+ return rpc_write(ht, TEE_FS_HTREE_TYPE_HEAD, 0, vers,
+ head, sizeof(*head));
+}
+
+static TEE_Result rpc_write_node(struct tee_fs_htree *ht, size_t node_id,
+ size_t vers,
+ const struct tee_fs_htree_node_image *node)
+{
+ return rpc_write(ht, TEE_FS_HTREE_TYPE_NODE, node_id - 1, vers,
+ node, sizeof(*node));
+}
+
+static TEE_Result traverse_post_order(struct traverse_arg *targ,
+ struct htree_node *node)
+{
+ TEE_Result res;
+
+ /*
+ * This function is recursing but not very deep, only with Log(N)
+ * maximum depth.
+ */
+
+ if (!node)
+ return TEE_SUCCESS;
+
+ res = traverse_post_order(targ, node->child[0]);
+ if (res != TEE_SUCCESS)
+ return res;
+
+ res = traverse_post_order(targ, node->child[1]);
+ if (res != TEE_SUCCESS)
+ return res;
+
+ return targ->cb(targ, node);
+}
+
+static TEE_Result htree_traverse_post_order(struct tee_fs_htree *ht,
+ traverse_cb_t cb, void *arg)
+{
+ struct traverse_arg targ = { ht, cb, arg };
+
+ return traverse_post_order(&targ, &ht->root);
+}
+
+static size_t node_id_to_level(size_t node_id)
+{
+ assert(node_id && node_id < UINT_MAX);
+ /* Calculate level of the node, root node (1) has level 1 */
+ return sizeof(unsigned int) * 8 - __builtin_clz(node_id);
+}
+
+static struct htree_node *find_closest_node(struct tee_fs_htree *ht,
+ size_t node_id)
+{
+ struct htree_node *node = &ht->root;
+ size_t level = node_id_to_level(node_id);
+ size_t n;
+
+ /* n = 1 because root node is level 1 */
+ for (n = 1; n < level; n++) {
+ struct htree_node *child;
+ size_t bit_idx;
+
+ /*
+ * The difference between levels of the current node and
+ * the node we're looking for tells which bit decides
+ * direction in the tree.
+ *
+ * As the first bit has index 0 we'll subtract 1
+ */
+ bit_idx = level - n - 1;
+ child = node->child[((node_id >> bit_idx) & 1)];
+ if (!child)
+ return node;
+ node = child;
+ }
+
+ return node;
+}
+
+static struct htree_node *find_node(struct tee_fs_htree *ht, size_t node_id)
+{
+ struct htree_node *node = find_closest_node(ht, node_id);
+
+ if (node && node->id == node_id)
+ return node;
+ return NULL;
+}
+
+static TEE_Result get_node(struct tee_fs_htree *ht, bool create,
+ size_t node_id, struct htree_node **node_ret)
+{
+ struct htree_node *node;
+ struct htree_node *nc;
+ size_t n;
+
+ node = find_closest_node(ht, node_id);
+ if (!node)
+ return TEE_ERROR_GENERIC;
+ if (node->id == node_id)
+ goto ret_node;
+
+ /*
+ * Trying to read beyond end of file should be caught earlier than
+ * here.
+ */
+ if (!create)
+ return TEE_ERROR_GENERIC;
+
+ /*
+ * Add missing nodes, some nodes may already be there. When we've
+ * processed the range all nodes up to node_id will be in the tree.
+ */
+ for (n = node->id + 1; n <= node_id; n++) {
+ node = find_closest_node(ht, n);
+ if (node->id == n)
+ continue;
+ /* Node id n should be a child of node */
+ assert((n >> 1) == node->id);
+ assert(!node->child[n & 1]);
+
+ nc = calloc(1, sizeof(*nc));
+ if (!nc)
+ return TEE_ERROR_OUT_OF_MEMORY;
+ nc->id = n;
+ nc->parent = node;
+ node->child[n & 1] = nc;
+ node = nc;
+ }
+
+ if (node->id > ht->imeta.max_node_id)
+ ht->imeta.max_node_id = node->id;
+
+ret_node:
+ *node_ret = node;
+ return TEE_SUCCESS;
+}
+
+static int get_idx_from_counter(uint32_t counter0, uint32_t counter1)
+{
+ if (!(counter0 & 1)) {
+ if (!(counter1 & 1))
+ return 0;
+ if (counter0 > counter1)
+ return 0;
+ else
+ return 1;
+ }
+
+ if (counter1 & 1)
+ return 1;
+ else
+ return -1;
+}
+
+static TEE_Result init_head_from_data(struct tee_fs_htree *ht)
+{
+ TEE_Result res;
+ struct tee_fs_htree_image head[2];
+ int idx;
+
+ for (idx = 0; idx < 2; idx++) {
+ res = rpc_read_head(ht, idx, head + idx);
+ if (res != TEE_SUCCESS)
+ return res;
+ }
+
+ idx = get_idx_from_counter(head[0].counter, head[1].counter);
+ if (idx < 0)
+ return TEE_ERROR_SECURITY;
+
+ res = rpc_read_node(ht, 1, idx, &ht->root.node);
+ if (res != TEE_SUCCESS)
+ return res;
+
+ ht->head = head[idx];
+ ht->root.id = 1;
+
+ return TEE_SUCCESS;
+}
+
+static TEE_Result init_tree_from_data(struct tee_fs_htree *ht)
+{
+ TEE_Result res;
+ struct tee_fs_htree_node_image node_image;
+ struct htree_node *node;
+ struct htree_node *nc;
+ size_t committed_version;
+ size_t node_id = 2;
+
+ while (node_id <= ht->imeta.max_node_id) {
+ node = find_node(ht, node_id >> 1);
+ if (!node)
+ return TEE_ERROR_GENERIC;
+ committed_version = !!(node->node.flags &
+ HTREE_NODE_COMMITTED_CHILD(node_id & 1));
+
+ res = rpc_read_node(ht, node_id, committed_version,
+ &node_image);
+ if (res != TEE_SUCCESS)
+ return res;
+
+ res = get_node(ht, true, node_id, &nc);
+ if (res != TEE_SUCCESS)
+ return res;
+ nc->node = node_image;
+ node_id++;
+ }
+
+ return TEE_SUCCESS;
+}
+
+static TEE_Result calc_node_hash(struct htree_node *node, void *ctx,
+ uint8_t *digest)
+{
+ TEE_Result res;
+ uint32_t alg = TEE_FS_HTREE_HASH_ALG;
+ uint8_t *ndata = (uint8_t *)&node->node + sizeof(node->node.hash);
+ size_t nsize = sizeof(node->node) - sizeof(node->node.hash);
+
+ res = crypto_ops.hash.init(ctx, alg);
+ if (res != TEE_SUCCESS)
+ return res;
+
+ res = crypto_ops.hash.update(ctx, alg, ndata, nsize);
+ if (res != TEE_SUCCESS)
+ return res;
+
+ if (node->child[0]) {
+ res = crypto_ops.hash.update(ctx, alg,
+ node->child[0]->node.hash,
+ sizeof(node->child[0]->node.hash));
+ if (res != TEE_SUCCESS)
+ return res;
+ }
+
+ if (node->child[1]) {
+ res = crypto_ops.hash.update(ctx, alg,
+ node->child[1]->node.hash,
+ sizeof(node->child[1]->node.hash));
+ if (res != TEE_SUCCESS)
+ return res;
+ }
+
+ return crypto_ops.hash.final(ctx, alg, digest, TEE_FS_HTREE_HASH_SIZE);
+}
+
+static TEE_Result authenc_init(void **ctx_ret, TEE_OperationMode mode,
+ struct tee_fs_htree *ht,
+ struct tee_fs_htree_node_image *ni,
+ size_t payload_len)
+{
+ TEE_Result res = TEE_SUCCESS;
+ const uint32_t alg = TEE_FS_HTREE_AUTH_ENC_ALG;
+ uint8_t *ctx;
+ size_t ctx_size;
+ size_t aad_len = TEE_FS_HTREE_FEK_SIZE + TEE_FS_HTREE_IV_SIZE;
+ uint8_t *iv;
+
+ if (ni) {
+ iv = ni->iv;
+ } else {
+ iv = ht->head.iv;
+ aad_len += TEE_FS_HTREE_HASH_SIZE + sizeof(ht->head.counter);
+ }
+
+ if (mode == TEE_MODE_ENCRYPT) {
+ res = crypto_ops.prng.read(iv, TEE_FS_HTREE_IV_SIZE);
+ if (res != TEE_SUCCESS)
+ return res;
+ }
+
+ res = crypto_ops.authenc.get_ctx_size(alg, &ctx_size);
+ if (res != TEE_SUCCESS)
+ return res;
+
+ ctx = malloc(ctx_size);
+ if (!ctx) {
+ EMSG("request memory size %zu failed", ctx_size);
+ return TEE_ERROR_OUT_OF_MEMORY;
+ }
+
+ res = crypto_ops.authenc.init(ctx, alg, mode,
+ ht->fek, TEE_FS_HTREE_FEK_SIZE,
+ iv, TEE_FS_HTREE_IV_SIZE,
+ TEE_FS_HTREE_TAG_SIZE, aad_len,
+ payload_len);
+ if (res != TEE_SUCCESS)
+ goto exit;
+
+ if (!ni) {
+ res = crypto_ops.authenc.update_aad(ctx, alg, mode,
+ ht->root.node.hash,
+ TEE_FS_HTREE_FEK_SIZE);
+ if (res != TEE_SUCCESS)
+ goto exit;
+
+ res = crypto_ops.authenc.update_aad(ctx, alg, mode,
+ (void *)&ht->head.counter,
+ sizeof(ht->head.counter));
+ if (res != TEE_SUCCESS)
+ goto exit;
+ }
+
+ res = crypto_ops.authenc.update_aad(ctx, alg, mode, ht->head.enc_fek,
+ TEE_FS_HTREE_FEK_SIZE);
+ if (res != TEE_SUCCESS)
+ goto exit;
+
+ res = crypto_ops.authenc.update_aad(ctx, alg, mode, iv,
+ TEE_FS_HTREE_IV_SIZE);
+
+exit:
+ if (res == TEE_SUCCESS)
+ *ctx_ret = ctx;
+ else
+ free(ctx);
+
+ return res;
+}
+
+static TEE_Result authenc_decrypt_final(void *ctx, const uint8_t *tag,
+ const void *crypt, size_t len,
+ void *plain)
+{
+ TEE_Result res;
+ size_t out_size = len;
+
+ res = crypto_ops.authenc.dec_final(ctx, TEE_FS_HTREE_AUTH_ENC_ALG,
+ crypt, len, plain, &out_size,
+ tag, TEE_FS_HTREE_TAG_SIZE);
+ crypto_ops.authenc.final(ctx, TEE_FS_HTREE_AUTH_ENC_ALG);
+ free(ctx);
+
+ if (res == TEE_SUCCESS && out_size != len)
+ return TEE_ERROR_GENERIC;
+ if (res == TEE_ERROR_MAC_INVALID)
+ return TEE_ERROR_CORRUPT_OBJECT;
+
+ return res;
+}
+
+static TEE_Result authenc_encrypt_final(void *ctx, uint8_t *tag,
+ const void *plain, size_t len,
+ void *crypt)
+{
+ TEE_Result res;
+ size_t out_size = len;
+ size_t out_tag_size = TEE_FS_HTREE_TAG_SIZE;
+
+ res = crypto_ops.authenc.enc_final(ctx, TEE_FS_HTREE_AUTH_ENC_ALG,
+ plain, len, crypt, &out_size,
+ tag, &out_tag_size);
+ crypto_ops.authenc.final(ctx, TEE_FS_HTREE_AUTH_ENC_ALG);
+ free(ctx);
+
+ if (res == TEE_SUCCESS &&
+ (out_size != len || out_tag_size != TEE_FS_HTREE_TAG_SIZE))
+ return TEE_ERROR_GENERIC;
+
+ return res;
+}
+
+static TEE_Result verify_root(struct tee_fs_htree *ht)
+{
+ TEE_Result res;
+ void *ctx;
+
+ res = tee_fs_fek_crypt(TEE_MODE_DECRYPT, ht->head.enc_fek,
+ sizeof(ht->fek), ht->fek);
+ if (res != TEE_SUCCESS)
+ return res;
+
+ res = authenc_init(&ctx, TEE_MODE_DECRYPT, ht, NULL, sizeof(ht->imeta));
+ if (res != TEE_SUCCESS)
+ return res;
+
+ return authenc_decrypt_final(ctx, ht->head.tag, ht->head.imeta,
+ sizeof(ht->imeta), &ht->imeta);
+}
+
+static TEE_Result verify_node(struct traverse_arg *targ,
+ struct htree_node *node)
+{
+ void *ctx = targ->arg;
+ TEE_Result res;
+ uint8_t digest[TEE_FS_HTREE_HASH_SIZE];
+
+ res = calc_node_hash(node, ctx, digest);
+ if (res == TEE_SUCCESS &&
+ buf_compare_ct(digest, node->node.hash, sizeof(digest)))
+ return TEE_ERROR_CORRUPT_OBJECT;
+
+ return res;
+}
+
+static TEE_Result verify_tree(struct tee_fs_htree *ht)
+{
+ TEE_Result res;
+ size_t size;
+ void *ctx;
+
+ if (!crypto_ops.hash.get_ctx_size || !crypto_ops.hash.init ||
+ !crypto_ops.hash.update || !crypto_ops.hash.final)
+ return TEE_ERROR_NOT_SUPPORTED;
+
+ res = crypto_ops.hash.get_ctx_size(TEE_FS_HTREE_HASH_ALG, &size);
+ if (res != TEE_SUCCESS)
+ return res;
+
+ ctx = malloc(size);
+ if (!ctx)
+ return TEE_ERROR_OUT_OF_MEMORY;
+
+ res = htree_traverse_post_order(ht, verify_node, ctx);
+ free(ctx);
+
+ return res;
+}
+
+static TEE_Result init_root_node(struct tee_fs_htree *ht)
+{
+ TEE_Result res;
+ size_t size;
+ void *ctx;
+
+ res = crypto_ops.hash.get_ctx_size(TEE_FS_HTREE_HASH_ALG, &size);
+ if (res != TEE_SUCCESS)
+ return res;
+ ctx = malloc(size);
+ if (!ctx)
+ return TEE_ERROR_OUT_OF_MEMORY;
+
+ ht->root.id = 1;
+
+ res = calc_node_hash(&ht->root, ctx, ht->root.node.hash);
+ free(ctx);
+
+ return res;
+}
+
+TEE_Result tee_fs_htree_open(bool create,
+ const struct tee_fs_htree_storage *stor,
+ void *stor_aux, struct tee_fs_htree **ht_ret)
+{
+ TEE_Result res;
+ struct tee_fs_htree *ht = calloc(1, sizeof(*ht));
+
+ if (!ht)
+ return TEE_ERROR_OUT_OF_MEMORY;
+
+ ht->stor = stor;
+ ht->stor_aux = stor_aux;
+
+ if (create) {
+ const struct tee_fs_htree_image dummy_head = { .counter = 0 };
+
+ res = crypto_ops.prng.read(ht->fek, sizeof(ht->fek));
+ if (res != TEE_SUCCESS)
+ goto out;
+
+ res = tee_fs_fek_crypt(TEE_MODE_ENCRYPT, ht->fek,
+ sizeof(ht->fek), ht->head.enc_fek);
+ if (res != TEE_SUCCESS)
+ goto out;
+
+ res = init_root_node(ht);
+ if (res != TEE_SUCCESS)
+ goto out;
+
+ ht->dirty = true;
+ res = tee_fs_htree_sync_to_storage(&ht);
+ if (res != TEE_SUCCESS)
+ goto out;
+ res = rpc_write_head(ht, 0, &dummy_head);
+ } else {
+ res = init_head_from_data(ht);
+ if (res != TEE_SUCCESS)
+ goto out;
+
+ res = verify_root(ht);
+ if (res != TEE_SUCCESS)
+ goto out;
+
+ res = init_tree_from_data(ht);
+ if (res != TEE_SUCCESS)
+ goto out;
+
+ res = verify_tree(ht);
+ }
+out:
+ if (res == TEE_SUCCESS)
+ *ht_ret = ht;
+ else
+ tee_fs_htree_close(&ht);
+ return res;
+}
+
+struct tee_fs_htree_meta *tee_fs_htree_get_meta(struct tee_fs_htree *ht)
+{
+ return &ht->imeta.meta;
+}
+
+static TEE_Result free_node(struct traverse_arg *targ __unused,
+ struct htree_node *node)
+{
+ if (node->parent)
+ free(node);
+ return TEE_SUCCESS;
+}
+
+void tee_fs_htree_close(struct tee_fs_htree **ht)
+{
+ if (!*ht)
+ return;
+ htree_traverse_post_order(*ht, free_node, NULL);
+ free(*ht);
+ *ht = NULL;
+}
+
+static TEE_Result htree_sync_node_to_storage(struct traverse_arg *targ,
+ struct htree_node *node)
+{
+ TEE_Result res;
+ uint8_t vers;
+
+ /*
+ * The node can be dirty while the block isn't updated due to
+ * updated children, but if block is updated the node has to be
+ * dirty.
+ */
+ assert(node->dirty >= node->block_updated);
+
+ if (!node->dirty)
+ return TEE_SUCCESS;
+
+ if (node->parent) {
+ uint32_t f = HTREE_NODE_COMMITTED_CHILD(node->id & 1);
+
+ node->parent->dirty = true;
+ node->parent->node.flags ^= f;
+ vers = !!(node->parent->node.flags & f);
+ } else {
+ /*
+ * Counter isn't updated yet, it's increased just before
+ * writing the header.
+ */
+ vers = !(targ->ht->head.counter & 1);
+ }
+
+ res = calc_node_hash(node, targ->arg, node->node.hash);
+ if (res != TEE_SUCCESS)
+ return res;
+
+ node->dirty = false;
+ node->block_updated = false;
+
+ return rpc_write_node(targ->ht, node->id, vers, &node->node);
+}
+
+static TEE_Result update_root(struct tee_fs_htree *ht)
+{
+ TEE_Result res;
+ void *ctx;
+
+ ht->head.counter++;
+
+ res = authenc_init(&ctx, TEE_MODE_ENCRYPT, ht, NULL, sizeof(ht->imeta));
+ if (res != TEE_SUCCESS)
+ return res;
+
+ return authenc_encrypt_final(ctx, ht->head.tag, &ht->imeta,
+ sizeof(ht->imeta), &ht->head.imeta);
+}
+
+TEE_Result tee_fs_htree_sync_to_storage(struct tee_fs_htree **ht_arg)
+{
+ TEE_Result res;
+ struct tee_fs_htree *ht = *ht_arg;
+ size_t size;
+ void *ctx;
+
+ if (!ht)
+ return TEE_ERROR_CORRUPT_OBJECT;
+
+ if (!ht->dirty)
+ return TEE_SUCCESS;
+
+ res = crypto_ops.hash.get_ctx_size(TEE_FS_HTREE_HASH_ALG, &size);
+ if (res != TEE_SUCCESS)
+ return res;
+ ctx = malloc(size);
+ if (!ctx)
+ return TEE_ERROR_OUT_OF_MEMORY;
+
+ res = htree_traverse_post_order(ht, htree_sync_node_to_storage, ctx);
+ if (res != TEE_SUCCESS)
+ goto out;
+
+ /* All the nodes are written to storage now. Time to update root. */
+ res = update_root(ht);
+ if (res != TEE_SUCCESS)
+ goto out;
+
+ res = rpc_write_head(ht, ht->head.counter & 1, &ht->head);
+ if (res != TEE_SUCCESS)
+ goto out;
+
+ ht->dirty = false;
+out:
+ free(ctx);
+ if (res != TEE_SUCCESS)
+ tee_fs_htree_close(ht_arg);
+ return res;
+}
+
+static TEE_Result get_block_node(struct tee_fs_htree *ht, bool create,
+ size_t block_num, struct htree_node **node)
+{
+ TEE_Result res;
+ struct htree_node *nd;
+
+ res = get_node(ht, create, BLOCK_NUM_TO_NODE_ID(block_num), &nd);
+ if (res == TEE_SUCCESS)
+ *node = nd;
+
+ return res;
+}
+
+TEE_Result tee_fs_htree_write_block(struct tee_fs_htree **ht_arg,
+ size_t block_num, const void *block)
+{
+ struct tee_fs_htree *ht = *ht_arg;
+ TEE_Result res;
+ struct tee_fs_rpc_operation op;
+ struct htree_node *node = NULL;
+ uint8_t block_vers;
+ void *ctx;
+ void *enc_block;
+
+ if (!ht)
+ return TEE_ERROR_CORRUPT_OBJECT;
+
+ res = get_block_node(ht, true, block_num, &node);
+ if (res != TEE_SUCCESS)
+ goto out;
+
+ if (!node->block_updated)
+ node->node.flags ^= HTREE_NODE_COMMITTED_BLOCK;
+
+ block_vers = !!(node->node.flags & HTREE_NODE_COMMITTED_BLOCK);
+ res = ht->stor->rpc_write_init(ht->stor_aux, &op,
+ TEE_FS_HTREE_TYPE_BLOCK, block_num,
+ block_vers, &enc_block);
+ if (res != TEE_SUCCESS)
+ goto out;
+
+ res = authenc_init(&ctx, TEE_MODE_ENCRYPT, ht, &node->node,
+ ht->stor->block_size);
+ if (res != TEE_SUCCESS)
+ goto out;
+ res = authenc_encrypt_final(ctx, node->node.tag, block,
+ ht->stor->block_size, enc_block);
+ if (res != TEE_SUCCESS)
+ goto out;
+
+ res = ht->stor->rpc_write_final(&op);
+ if (res != TEE_SUCCESS)
+ goto out;
+
+ node->block_updated = true;
+ node->dirty = true;
+ ht->dirty = true;
+out:
+ if (res != TEE_SUCCESS)
+ tee_fs_htree_close(ht_arg);
+ return res;
+}
+
+TEE_Result tee_fs_htree_read_block(struct tee_fs_htree **ht_arg,
+ size_t block_num, void *block)
+{
+ struct tee_fs_htree *ht = *ht_arg;
+ TEE_Result res;
+ struct tee_fs_rpc_operation op;
+ struct htree_node *node;
+ uint8_t block_vers;
+ size_t len;
+ void *ctx;
+ void *enc_block;
+
+ if (!ht)
+ return TEE_ERROR_CORRUPT_OBJECT;
+
+ res = get_block_node(ht, false, block_num, &node);
+ if (res != TEE_SUCCESS)
+ goto out;
+
+ block_vers = !!(node->node.flags & HTREE_NODE_COMMITTED_BLOCK);
+ res = ht->stor->rpc_read_init(ht->stor_aux, &op,
+ TEE_FS_HTREE_TYPE_BLOCK, block_num,
+ block_vers, &enc_block);
+ if (res != TEE_SUCCESS)
+ goto out;
+
+ res = ht->stor->rpc_read_final(&op, &len);
+ if (res != TEE_SUCCESS)
+ goto out;
+ if (len != ht->stor->block_size) {
+ res = TEE_ERROR_CORRUPT_OBJECT;
+ goto out;
+ }
+
+ res = authenc_init(&ctx, TEE_MODE_DECRYPT, ht, &node->node,
+ ht->stor->block_size);
+ if (res != TEE_SUCCESS)
+ goto out;
+
+ res = authenc_decrypt_final(ctx, node->node.tag, enc_block,
+ ht->stor->block_size, block);
+out:
+ if (res != TEE_SUCCESS)
+ tee_fs_htree_close(ht_arg);
+ return res;
+}
+
+TEE_Result tee_fs_htree_truncate(struct tee_fs_htree **ht_arg, size_t block_num)
+{
+ struct tee_fs_htree *ht = *ht_arg;
+ size_t node_id = BLOCK_NUM_TO_NODE_ID(block_num);
+ struct htree_node *node;
+
+ if (!ht)
+ return TEE_ERROR_CORRUPT_OBJECT;
+
+ while (node_id < ht->imeta.max_node_id) {
+ node = find_closest_node(ht, ht->imeta.max_node_id);
+ assert(node && node->id == ht->imeta.max_node_id);
+ assert(!node->child[0] && !node->child[1]);
+ assert(node->parent);
+ assert(node->parent->child[node->id & 1] == node);
+ node->parent->child[node->id & 1] = NULL;
+ free(node);
+ ht->imeta.max_node_id--;
+ ht->dirty = true;
+ }
+
+ return TEE_SUCCESS;
+}
diff --git a/core/tee/sub.mk b/core/tee/sub.mk
index 32f0f98..97c4b7a 100644
--- a/core/tee/sub.mk
+++ b/core/tee/sub.mk
@@ -31,6 +31,8 @@ srcs-y += tee_svc_storage.c
srcs-$(CFG_RPMB_FS) += tee_rpmb_fs.c
srcs-$(CFG_REE_FS) += tee_ree_fs.c
srcs-$(CFG_SQL_FS) += tee_sql_fs.c
+srcs-$(call cfg-one-enabled,CFG_REE_FS CFG_SQL_FS \
+ CFG_TEE_CORE_EMBED_INTERNAL_TESTS) += fs_htree.c
srcs-$(call cfg-one-enabled,CFG_REE_FS CFG_SQL_FS) += tee_fs_rpc.c
srcs-$(call cfg-one-enabled,CFG_REE_FS CFG_SQL_FS CFG_RPMB_FS) += \
tee_fs_rpc_cache.c
diff --git a/core/tee/tee_cryp_utl.c b/core/tee/tee_cryp_utl.c
index fa01161..b63e790 100644
--- a/core/tee/tee_cryp_utl.c
+++ b/core/tee/tee_cryp_utl.c
@@ -392,6 +392,13 @@ __weak void plat_prng_add_jitter_entropy(void)
tee_prng_add_entropy((uint8_t *)&current, sizeof(current));
}
+__weak void plat_prng_add_jitter_entropy_norpc(void)
+{
+#ifndef CFG_SECURE_TIME_SOURCE_REE
+ plat_prng_add_jitter_entropy();
+#endif
+}
+
static TEE_Result tee_cryp_init(void)
{
if (crypto_ops.init)
diff --git a/core/tee/tee_fs_key_manager.c b/core/tee/tee_fs_key_manager.c
index c827cef..fa579c6 100644
--- a/core/tee/tee_fs_key_manager.c
+++ b/core/tee/tee_fs_key_manager.c
@@ -55,16 +55,6 @@ struct tee_fs_ssk {
uint8_t key[TEE_FS_KM_SSK_SIZE];
};
-struct aad {
- const uint8_t *encrypted_key;
- const uint8_t *iv;
-};
-
-struct km_header {
- struct aad aad;
- uint8_t *tag;
-};
-
static struct tee_fs_ssk tee_fs_ssk;
static uint8_t string_for_ssk_gen[] = "ONLY_FOR_tee_fs_ssk";
@@ -109,17 +99,17 @@ exit:
return res;
}
-static TEE_Result fek_crypt(TEE_OperationMode mode,
- uint8_t *key, int size)
+TEE_Result tee_fs_fek_crypt(TEE_OperationMode mode, const uint8_t *in_key,
+ size_t size, uint8_t *out_key)
{
TEE_Result res;
uint8_t *ctx = NULL;
size_t ctx_size;
uint8_t tsk[TEE_FS_KM_TSK_SIZE];
- uint8_t dst_key[TEE_FS_KM_FEK_SIZE];
+ uint8_t dst_key[size];
struct tee_ta_session *sess;
- if (!key)
+ if (!in_key || !out_key)
return TEE_ERROR_BAD_PARAMETERS;
if (size != TEE_FS_KM_FEK_SIZE)
@@ -151,13 +141,13 @@ static TEE_Result fek_crypt(TEE_OperationMode mode,
goto exit;
res = crypto_ops.cipher.update(ctx, TEE_FS_KM_ENC_FEK_ALG,
- mode, true, key, size, dst_key);
+ mode, true, in_key, size, dst_key);
if (res != TEE_SUCCESS)
goto exit;
crypto_ops.cipher.final(ctx, TEE_FS_KM_ENC_FEK_ALG);
- memcpy(key, dst_key, sizeof(dst_key));
+ memcpy(out_key, dst_key, sizeof(dst_key));
exit:
free(ctx);
@@ -170,11 +160,6 @@ static TEE_Result generate_fek(uint8_t *key, uint8_t len)
return crypto_ops.prng.read(key, len);
}
-static TEE_Result generate_iv(uint8_t *iv, uint8_t len)
-{
- return crypto_ops.prng.read(iv, len);
-}
-
static TEE_Result tee_fs_init_key_manager(void)
{
int res = TEE_SUCCESS;
@@ -204,94 +189,6 @@ static TEE_Result tee_fs_init_key_manager(void)
return res;
}
-static TEE_Result do_auth_enc(TEE_OperationMode mode,
- struct km_header *hdr,
- uint8_t *fek, int fek_len,
- const uint8_t *data_in, size_t in_size,
- uint8_t *data_out, size_t *out_size)
-{
- TEE_Result res = TEE_SUCCESS;
- uint8_t *ctx = NULL;
- size_t ctx_size;
- size_t tag_len = TEE_FS_KM_MAX_TAG_LEN;
-
- if ((mode != TEE_MODE_ENCRYPT) && (mode != TEE_MODE_DECRYPT))
- return TEE_ERROR_BAD_PARAMETERS;
-
- if (*out_size < in_size) {
- EMSG("output buffer(%zd) < input buffer(%zd)",
- *out_size, in_size);
- return TEE_ERROR_SHORT_BUFFER;
- }
-
- res = crypto_ops.authenc.get_ctx_size(TEE_FS_KM_AUTH_ENC_ALG,
- &ctx_size);
- if (res != TEE_SUCCESS)
- return res;
-
- ctx = malloc(ctx_size);
- if (!ctx) {
- EMSG("request memory size %zu failed", ctx_size);
- return TEE_ERROR_OUT_OF_MEMORY;
- }
-
- res = crypto_ops.authenc.init(ctx, TEE_FS_KM_AUTH_ENC_ALG,
- mode, fek, fek_len, hdr->aad.iv,
- TEE_FS_KM_IV_LEN, TEE_FS_KM_MAX_TAG_LEN,
- sizeof(struct aad), in_size);
- if (res != TEE_SUCCESS)
- goto exit;
-
- res = crypto_ops.authenc.update_aad(ctx, TEE_FS_KM_AUTH_ENC_ALG,
- mode, (uint8_t *)hdr->aad.encrypted_key,
- TEE_FS_KM_FEK_SIZE);
- if (res != TEE_SUCCESS)
- goto exit;
-
- res = crypto_ops.authenc.update_aad(ctx, TEE_FS_KM_AUTH_ENC_ALG,
- mode, (uint8_t *)hdr->aad.iv,
- TEE_FS_KM_IV_LEN);
- if (res != TEE_SUCCESS)
- goto exit;
-
- if (mode == TEE_MODE_ENCRYPT) {
- res = crypto_ops.authenc.enc_final(ctx, TEE_FS_KM_AUTH_ENC_ALG,
- data_in, in_size, data_out, out_size,
- hdr->tag, &tag_len);
- } else {
- res = crypto_ops.authenc.dec_final(ctx, TEE_FS_KM_AUTH_ENC_ALG,
- data_in, in_size, data_out, out_size,
- hdr->tag, tag_len);
- }
-
- if (res != TEE_SUCCESS)
- goto exit;
-
- crypto_ops.authenc.final(ctx, TEE_FS_KM_AUTH_ENC_ALG);
-
-exit:
- free(ctx);
- return res;
-}
-
-size_t tee_fs_get_header_size(enum tee_fs_file_type type)
-{
- size_t header_size = 0;
-
- switch (type) {
- case META_FILE:
- header_size = sizeof(struct meta_header);
- break;
- case BLOCK_FILE:
- header_size = sizeof(struct block_header);
- break;
- default:
- panic("Unknown file type");
- }
-
- return header_size;
-}
-
TEE_Result tee_fs_generate_fek(uint8_t *buf, int buf_size)
{
TEE_Result res;
@@ -303,117 +200,7 @@ TEE_Result tee_fs_generate_fek(uint8_t *buf, int buf_size)
if (res != TEE_SUCCESS)
return res;
- return fek_crypt(TEE_MODE_ENCRYPT, buf,
- TEE_FS_KM_FEK_SIZE);
-}
-
-TEE_Result tee_fs_encrypt_file(enum tee_fs_file_type file_type,
- const uint8_t *data_in, size_t data_in_size,
- uint8_t *data_out, size_t *data_out_size,
- const uint8_t *encrypted_fek)
-{
- TEE_Result res = TEE_SUCCESS;
- struct km_header hdr;
- uint8_t iv[TEE_FS_KM_IV_LEN];
- uint8_t tag[TEE_FS_KM_MAX_TAG_LEN];
- uint8_t fek[TEE_FS_KM_FEK_SIZE];
- uint8_t *ciphertext;
- size_t cipher_size;
- size_t header_size = tee_fs_get_header_size(file_type);
-
- /*
- * Meta File Format: |Header|Chipertext|
- * Header Format: |AAD|Tag|
- * AAD Format: |Encrypted_FEK|IV|
- *
- * Block File Format: |Header|Ciphertext|
- * Header Format: |IV|Tag|
- *
- * TSK = HMAC(SSK, TA_UUID)
- * FEK = AES_DECRYPT(TSK, Encrypted_FEK)
- * Chipertext = AES_GCM_ENCRYPT(FEK, IV, Meta_Info, AAD)
- */
-
- if (*data_out_size != (header_size + data_in_size))
- return TEE_ERROR_SHORT_BUFFER;
-
- res = generate_iv(iv, TEE_FS_KM_IV_LEN);
- if (res != TEE_SUCCESS)
- goto fail;
-
- memcpy(fek, encrypted_fek, TEE_FS_KM_FEK_SIZE);
- res = fek_crypt(TEE_MODE_DECRYPT, fek, TEE_FS_KM_FEK_SIZE);
- if (res != TEE_SUCCESS)
- goto fail;
-
- ciphertext = data_out + header_size;
- cipher_size = data_in_size;
-
- hdr.aad.iv = iv;
- hdr.aad.encrypted_key = encrypted_fek;
- hdr.tag = tag;
-
- res = do_auth_enc(TEE_MODE_ENCRYPT, &hdr,
- fek, TEE_FS_KM_FEK_SIZE,
- data_in, data_in_size,
- ciphertext, &cipher_size);
-
- if (res == TEE_SUCCESS) {
- if (file_type == META_FILE) {
- memcpy(data_out, encrypted_fek, TEE_FS_KM_FEK_SIZE);
- data_out += TEE_FS_KM_FEK_SIZE;
- }
-
- memcpy(data_out, iv, TEE_FS_KM_IV_LEN);
- data_out += TEE_FS_KM_IV_LEN;
- memcpy(data_out, tag, TEE_FS_KM_MAX_TAG_LEN);
-
- *data_out_size = header_size + cipher_size;
- }
-
-fail:
- return res;
-}
-
-TEE_Result tee_fs_decrypt_file(enum tee_fs_file_type file_type,
- const uint8_t *data_in, size_t data_in_size,
- uint8_t *plaintext, size_t *plaintext_size,
- uint8_t *encrypted_fek)
-{
- TEE_Result res = TEE_SUCCESS;
- struct km_header km_hdr;
- size_t file_hdr_size = tee_fs_get_header_size(file_type);
- const uint8_t *cipher = data_in + file_hdr_size;
- int cipher_size = data_in_size - file_hdr_size;
- uint8_t fek[TEE_FS_KM_FEK_SIZE];
-
- if (file_type == META_FILE) {
- struct meta_header *hdr = (struct meta_header *)data_in;
-
- km_hdr.aad.encrypted_key = hdr->encrypted_key;
- km_hdr.aad.iv = hdr->common.iv;
- km_hdr.tag = hdr->common.tag;
-
- /* return encrypted FEK to tee_fs which is used for block
- * encryption/decryption */
- memcpy(encrypted_fek, hdr->encrypted_key, TEE_FS_KM_FEK_SIZE);
- } else {
- struct block_header *hdr = (struct block_header *)data_in;
-
- km_hdr.aad.encrypted_key = encrypted_fek;
- km_hdr.aad.iv = hdr->common.iv;
- km_hdr.tag = hdr->common.tag;
- }
-
- memcpy(fek, km_hdr.aad.encrypted_key, TEE_FS_KM_FEK_SIZE);
- res = fek_crypt(TEE_MODE_DECRYPT, fek, TEE_FS_KM_FEK_SIZE);
- if (res != TEE_SUCCESS) {
- EMSG("Failed to decrypt FEK, res=0x%x", res);
- return res;
- }
-
- return do_auth_enc(TEE_MODE_DECRYPT, &km_hdr, fek, TEE_FS_KM_FEK_SIZE,
- cipher, cipher_size, plaintext, plaintext_size);
+ return tee_fs_fek_crypt(TEE_MODE_ENCRYPT, buf, TEE_FS_KM_FEK_SIZE, buf);
}
static TEE_Result sha256(uint8_t *out, size_t out_size, const uint8_t *in,
@@ -518,8 +305,8 @@ TEE_Result tee_fs_crypt_block(uint8_t *out, const uint8_t *in, size_t size,
blk_idx);
/* Decrypt FEK */
- memcpy(fek, encrypted_fek, TEE_FS_KM_FEK_SIZE);
- res = fek_crypt(TEE_MODE_DECRYPT, fek, TEE_FS_KM_FEK_SIZE);
+ res = tee_fs_fek_crypt(TEE_MODE_DECRYPT, encrypted_fek,
+ TEE_FS_KM_FEK_SIZE, fek);
if (res != TEE_SUCCESS)
return res;
@@ -550,4 +337,3 @@ exit:
}
service_init_late(tee_fs_init_key_manager);
-
diff --git a/core/tee/tee_fs_rpc.c b/core/tee/tee_fs_rpc.c
index 5e1078a..3ce1ba8 100644
--- a/core/tee/tee_fs_rpc.c
+++ b/core/tee/tee_fs_rpc.c
@@ -26,14 +26,17 @@
*/
#include <assert.h>
+#include <kernel/tee_misc.h>
#include <kernel/thread.h>
#include <mm/core_memprot.h>
#include <optee_msg_supplicant.h>
#include <stdlib.h>
-#include <string.h>
#include <string_ext.h>
+#include <string.h>
#include <tee/tee_fs.h>
#include <tee/tee_fs_rpc.h>
+#include <tee/tee_pobj.h>
+#include <tee/tee_svc_storage.h>
#include <trace.h>
#include <util.h>
@@ -48,16 +51,15 @@ static TEE_Result operation_commit(struct tee_fs_rpc_operation *op)
}
static TEE_Result operation_open(uint32_t id, unsigned int cmd,
- const char *fname, int *fd)
+ struct tee_pobj *po, int *fd)
{
struct tee_fs_rpc_operation op = { .id = id, .num_params = 3 };
TEE_Result res;
void *va;
paddr_t pa;
uint64_t cookie;
- size_t fname_size = strlen(fname) + 1;
- va = tee_fs_rpc_cache_alloc(fname_size, &pa, &cookie);
+ va = tee_fs_rpc_cache_alloc(TEE_FS_NAME_MAX, &pa, &cookie);
if (!va)
return TEE_ERROR_OUT_OF_MEMORY;
@@ -66,9 +68,12 @@ static TEE_Result operation_open(uint32_t id, unsigned int cmd,
op.params[1].attr = OPTEE_MSG_ATTR_TYPE_TMEM_INPUT;
op.params[1].u.tmem.buf_ptr = pa;
- op.params[1].u.tmem.size = fname_size;
+ op.params[1].u.tmem.size = TEE_FS_NAME_MAX;
op.params[1].u.tmem.shm_ref = cookie;
- strlcpy(va, fname, fname_size);
+ res = tee_svc_storage_create_filename(va, TEE_FS_NAME_MAX,
+ po, po->temporary);
+ if (res != TEE_SUCCESS)
+ return res;
op.params[2].attr = OPTEE_MSG_ATTR_TYPE_VALUE_OUTPUT;
@@ -79,14 +84,14 @@ static TEE_Result operation_open(uint32_t id, unsigned int cmd,
return res;
}
-TEE_Result tee_fs_rpc_open(uint32_t id, const char *fname, int *fd)
+TEE_Result tee_fs_rpc_open(uint32_t id, struct tee_pobj *po, int *fd)
{
- return operation_open(id, OPTEE_MRF_OPEN, fname, fd);
+ return operation_open(id, OPTEE_MRF_OPEN, po, fd);
}
-TEE_Result tee_fs_rpc_create(uint32_t id, const char *fname, int *fd)
+TEE_Result tee_fs_rpc_create(uint32_t id, struct tee_pobj *po, int *fd)
{
- return operation_open(id, OPTEE_MRF_CREATE, fname, fd);
+ return operation_open(id, OPTEE_MRF_CREATE, po, fd);
}
TEE_Result tee_fs_rpc_close(uint32_t id, int fd)
@@ -196,15 +201,15 @@ TEE_Result tee_fs_rpc_truncate(uint32_t id, int fd, size_t len)
return operation_commit(&op);
}
-TEE_Result tee_fs_rpc_remove(uint32_t id, const char *fname)
+TEE_Result tee_fs_rpc_remove(uint32_t id, struct tee_pobj *po)
{
+ TEE_Result res;
struct tee_fs_rpc_operation op = { .id = id, .num_params = 2 };
void *va;
paddr_t pa;
uint64_t cookie;
- size_t name_len = strlen(fname) + 1;
- va = tee_fs_rpc_cache_alloc(name_len, &pa, &cookie);
+ va = tee_fs_rpc_cache_alloc(TEE_FS_NAME_MAX, &pa, &cookie);
if (!va)
return TEE_ERROR_OUT_OF_MEMORY;
@@ -213,25 +218,27 @@ TEE_Result tee_fs_rpc_remove(uint32_t id, const char *fname)
op.params[1].attr = OPTEE_MSG_ATTR_TYPE_TMEM_INPUT;
op.params[1].u.tmem.buf_ptr = pa;
- op.params[1].u.tmem.size = name_len;
+ op.params[1].u.tmem.size = TEE_FS_NAME_MAX;
op.params[1].u.tmem.shm_ref = cookie;
- strlcpy(va, fname, name_len);
+ res = tee_svc_storage_create_filename(va, TEE_FS_NAME_MAX,
+ po, po->temporary);
+ if (res != TEE_SUCCESS)
+ return res;
return operation_commit(&op);
}
-TEE_Result tee_fs_rpc_rename(uint32_t id, const char *old_fname,
- const char *new_fname, bool overwrite)
+TEE_Result tee_fs_rpc_rename(uint32_t id, struct tee_pobj *old,
+ struct tee_pobj *new, bool overwrite)
{
+ TEE_Result res;
struct tee_fs_rpc_operation op = { .id = id, .num_params = 3 };
char *va;
paddr_t pa;
uint64_t cookie;
- size_t old_fname_size = strlen(old_fname) + 1;
- size_t new_fname_size = strlen(new_fname) + 1;
+ bool temp;
- va = tee_fs_rpc_cache_alloc(old_fname_size + new_fname_size,
- &pa, &cookie);
+ va = tee_fs_rpc_cache_alloc(TEE_FS_NAME_MAX * 2, &pa, &cookie);
if (!va)
return TEE_ERROR_OUT_OF_MEMORY;
@@ -241,20 +248,37 @@ TEE_Result tee_fs_rpc_rename(uint32_t id, const char *old_fname,
op.params[1].attr = OPTEE_MSG_ATTR_TYPE_TMEM_INPUT;
op.params[1].u.tmem.buf_ptr = pa;
- op.params[1].u.tmem.size = old_fname_size;
+ op.params[1].u.tmem.size = TEE_FS_NAME_MAX;
op.params[1].u.tmem.shm_ref = cookie;
- strlcpy(va, old_fname, old_fname_size);
+ if (new)
+ temp = old->temporary;
+ else
+ temp = true;
+ res = tee_svc_storage_create_filename(va, TEE_FS_NAME_MAX,
+ old, temp);
+ if (res != TEE_SUCCESS)
+ return res;
op.params[2].attr = OPTEE_MSG_ATTR_TYPE_TMEM_INPUT;
- op.params[2].u.tmem.buf_ptr = pa + old_fname_size;
- op.params[2].u.tmem.size = new_fname_size;
+ op.params[2].u.tmem.buf_ptr = pa + TEE_FS_NAME_MAX;
+ op.params[2].u.tmem.size = TEE_FS_NAME_MAX;
op.params[2].u.tmem.shm_ref = cookie;
- strlcpy(va + old_fname_size, new_fname, new_fname_size);
+ if (new) {
+ res = tee_svc_storage_create_filename(va + TEE_FS_NAME_MAX,
+ TEE_FS_NAME_MAX,
+ new, new->temporary);
+ } else {
+ res = tee_svc_storage_create_filename(va + TEE_FS_NAME_MAX,
+ TEE_FS_NAME_MAX,
+ old, false);
+ }
+ if (res != TEE_SUCCESS)
+ return res;
return operation_commit(&op);
}
-TEE_Result tee_fs_rpc_opendir(uint32_t id, const char *name,
+TEE_Result tee_fs_rpc_opendir(uint32_t id, const TEE_UUID *uuid,
struct tee_fs_dir **d)
{
TEE_Result res;
@@ -262,13 +286,12 @@ TEE_Result tee_fs_rpc_opendir(uint32_t id, const char *name,
void *va;
paddr_t pa;
uint64_t cookie;
- size_t name_len = strlen(name) + 1;
struct tee_fs_dir *dir = calloc(1, sizeof(*dir));
if (!dir)
return TEE_ERROR_OUT_OF_MEMORY;
- va = tee_fs_rpc_cache_alloc(name_len, &pa, &cookie);
+ va = tee_fs_rpc_cache_alloc(TEE_FS_NAME_MAX, &pa, &cookie);
if (!va) {
res = TEE_ERROR_OUT_OF_MEMORY;
goto err_exit;
@@ -279,9 +302,11 @@ TEE_Result tee_fs_rpc_opendir(uint32_t id, const char *name,
op.params[1].attr = OPTEE_MSG_ATTR_TYPE_TMEM_INPUT;
op.params[1].u.tmem.buf_ptr = pa;
- op.params[1].u.tmem.size = name_len;
+ op.params[1].u.tmem.size = TEE_FS_NAME_MAX;
op.params[1].u.tmem.shm_ref = cookie;
- strlcpy(va, name, name_len);
+ res = tee_svc_storage_create_dirname(va, TEE_FS_NAME_MAX, uuid);
+ if (res != TEE_SUCCESS)
+ return res;
op.params[2].attr = OPTEE_MSG_ATTR_TYPE_VALUE_OUTPUT;
@@ -308,8 +333,6 @@ TEE_Result tee_fs_rpc_closedir(uint32_t id, struct tee_fs_dir *d)
op.params[0].u.value.a = OPTEE_MRF_CLOSEDIR;
op.params[0].u.value.b = d->nw_dir;
- if (d)
- free(d->d.d_name);
free(d);
return operation_commit(&op);
}
@@ -344,9 +367,9 @@ TEE_Result tee_fs_rpc_readdir(uint32_t id, struct tee_fs_dir *d,
if (res != TEE_SUCCESS)
return res;
- free(d->d.d_name);
- d->d.d_name = strndup(va, max_name_len);
- if (!d->d.d_name)
+ d->d.oidlen = tee_hs2b(va, d->d.oid, strnlen(va, max_name_len),
+ sizeof(d->d.oid));
+ if (!d->d.oidlen)
return TEE_ERROR_OUT_OF_MEMORY;
*ent = &d->d;
diff --git a/core/tee/tee_obj.c b/core/tee/tee_obj.c
index 78cf937..6dcfbf3 100644
--- a/core/tee/tee_obj.c
+++ b/core/tee/tee_obj.c
@@ -31,7 +31,6 @@
#include <tee_api_defines.h>
#include <mm/tee_mmu.h>
#include <tee/tee_fs.h>
-#include <tee/tee_fs_defs.h>
#include <tee/tee_pobj.h>
#include <trace.h>
#include <tee/tee_svc_storage.h>
@@ -79,32 +78,20 @@ void tee_obj_close_all(struct user_ta_ctx *utc)
TEE_Result tee_obj_verify(struct tee_ta_session *sess, struct tee_obj *o)
{
TEE_Result res;
- char *file = NULL;
const struct tee_file_operations *fops = o->pobj->fops;
struct tee_file_handle *fh = NULL;
if (!fops)
return TEE_ERROR_STORAGE_NOT_AVAILABLE;
- file = tee_svc_storage_create_filename(sess,
- o->pobj->obj_id,
- o->pobj->obj_id_len,
- false);
- if (file == NULL) {
- res = TEE_ERROR_OUT_OF_MEMORY;
- goto exit;
- }
-
- res = fops->open(file, &fh);
+ res = fops->open(o->pobj, &fh);
if (res == TEE_ERROR_CORRUPT_OBJECT) {
EMSG("Object corrupt\n");
+ fops->remove(o->pobj);
tee_obj_close(to_user_ta_ctx(sess->ctx), o);
- fops->remove(file);
}
- free(file);
fops->close(&fh);
-exit:
return res;
}
diff --git a/core/tee/tee_pobj.c b/core/tee/tee_pobj.c
index a7aee31..0f9fb46 100644
--- a/core/tee/tee_pobj.c
+++ b/core/tee/tee_pobj.c
@@ -80,7 +80,8 @@ static TEE_Result tee_pobj_check_access(uint32_t oflags, uint32_t nflags)
}
TEE_Result tee_pobj_get(TEE_UUID *uuid, void *obj_id, uint32_t obj_id_len,
- uint32_t flags, const struct tee_file_operations *fops,
+ uint32_t flags, bool temporary,
+ const struct tee_file_operations *fops,
struct tee_pobj **obj)
{
struct tee_pobj *o;
@@ -100,10 +101,12 @@ TEE_Result tee_pobj_get(TEE_UUID *uuid, void *obj_id, uint32_t obj_id_len,
}
if (*obj) {
+ if (temporary != (*obj)->temporary) {
+ res = TEE_ERROR_ACCESS_CONFLICT;
+ goto out;
+ }
res = tee_pobj_check_access((*obj)->flags, flags);
- if (res != TEE_SUCCESS)
- *obj = NULL;
- else
+ if (res == TEE_SUCCESS)
(*obj)->refcnt++;
goto out;
}
@@ -119,6 +122,7 @@ TEE_Result tee_pobj_get(TEE_UUID *uuid, void *obj_id, uint32_t obj_id_len,
memcpy(&o->uuid, uuid, sizeof(TEE_UUID));
o->flags = flags;
o->fops = fops;
+ o->temporary = temporary;
o->obj_id = malloc(obj_id_len);
if (o->obj_id == NULL) {
@@ -134,6 +138,8 @@ TEE_Result tee_pobj_get(TEE_UUID *uuid, void *obj_id, uint32_t obj_id_len,
res = TEE_SUCCESS;
out:
+ if (res != TEE_SUCCESS)
+ *obj = NULL;
mutex_unlock(&pobjs_mutex);
return res;
}
diff --git a/core/tee/tee_ree_fs.c b/core/tee/tee_ree_fs.c
index 7a82acb..544ed3e 100644
--- a/core/tee/tee_ree_fs.c
+++ b/core/tee/tee_ree_fs.c
@@ -26,125 +26,45 @@
*/
#include <assert.h>
-#include <kernel/thread.h>
#include <kernel/mutex.h>
#include <kernel/panic.h>
+#include <kernel/thread.h>
#include <mm/core_memprot.h>
#include <optee_msg_supplicant.h>
#include <stdio.h>
#include <stdlib.h>
-#include <string.h>
#include <string_ext.h>
+#include <string.h>
#include <sys/queue.h>
+#include <tee/fs_htree.h>
#include <tee/tee_cryp_provider.h>
#include <tee/tee_fs.h>
-#include <tee/tee_fs_defs.h>
#include <tee/tee_fs_rpc.h>
-#include <tee/tee_fs_key_manager.h>
#include <trace.h>
#include <utee_defines.h>
#include <util.h>
-/*
- * This file implements the tee_file_operations structure for a secure
- * filesystem based on single file in normal world.
- *
- * All fields in the REE file are duplicated with two versions 0 and 1. The
- * active meta-data block is selected by the lowest bit in the
- * meta-counter. The active file block is selected by corresponding bit
- * number in struct tee_fs_file_info.backup_version_table.
- *
- * The atomicity of each operation is ensured by updating meta-counter when
- * everything in the secondary blocks (both meta-data and file-data blocks)
- * are successfully written. The main purpose of the code below is to
- * perform block encryption and authentication of the file data, and
- * properly handle seeking through the file. One file (in the sense of
- * struct tee_file_operations) maps to one file in the REE filesystem, and
- * has the following structure:
- *
- * [ 4 bytes meta-counter]
- * [ meta-data version 0][ meta-data version 1 ]
- * [ Block 0 version 0 ][ Block 0 version 1 ]
- * [ Block 1 version 0 ][ Block 1 version 1 ]
- * ...
- * [ Block n version 0 ][ Block n version 1 ]
- *
- * One meta-data block is built up as:
- * [ struct meta_header | struct tee_fs_get_header_size ]
- *
- * One data block is built up as:
- * [ struct block_header | BLOCK_FILE_SIZE bytes ]
- *
- * struct meta_header and struct block_header are defined in
- * tee_fs_key_manager.h.
- *
- */
-
#define BLOCK_SHIFT 12
#define BLOCK_SIZE (1 << BLOCK_SHIFT)
-#define MAX_FILE_SIZE (BLOCK_SIZE * NUM_BLOCKS_PER_FILE)
-
struct tee_fs_fd {
- uint32_t meta_counter;
- struct tee_fs_file_meta meta;
- tee_fs_off_t pos;
- uint32_t flags;
- bool is_new_file;
+ struct tee_fs_htree *ht;
int fd;
};
-static inline int pos_to_block_num(int position)
+static int pos_to_block_num(int position)
{
return position >> BLOCK_SHIFT;
}
-static inline int get_last_block_num(size_t size)
-{
- return pos_to_block_num(size - 1);
-}
-
-static bool get_backup_version_of_block(struct tee_fs_file_meta *meta,
- size_t block_num)
-{
- uint32_t index = (block_num / 32);
- uint32_t block_mask = 1 << (block_num % 32);
-
- return !!(meta->info.backup_version_table[index] & block_mask);
-}
-
-static inline void toggle_backup_version_of_block(
- struct tee_fs_file_meta *meta,
- size_t block_num)
-{
- uint32_t index = (block_num / 32);
- uint32_t block_mask = 1 << (block_num % 32);
-
- meta->info.backup_version_table[index] ^= block_mask;
-}
-
-struct block_operations {
-
- /*
- * Read a block from REE File System which is corresponding
- * to the given block_num.
- */
- struct block *(*read)(struct tee_fs_fd *fdp, int block_num);
-
- /*
- * Write the given block to REE File System
- */
- int (*write)(struct tee_fs_fd *fdp, struct block *b,
- struct tee_fs_file_meta *new_meta);
-};
-
static struct mutex ree_fs_mutex = MUTEX_INITIALIZER;
-static TEE_Result ree_fs_opendir_rpc(const char *name, struct tee_fs_dir **d)
+static TEE_Result ree_fs_opendir_rpc(const TEE_UUID *uuid,
+ struct tee_fs_dir **d)
{
- return tee_fs_rpc_opendir(OPTEE_MSG_RPC_CMD_FS, name, d);
+ return tee_fs_rpc_opendir(OPTEE_MSG_RPC_CMD_FS, uuid, d);
}
static void ree_fs_closedir_rpc(struct tee_fs_dir *d)
@@ -159,330 +79,187 @@ static TEE_Result ree_fs_readdir_rpc(struct tee_fs_dir *d,
return tee_fs_rpc_readdir(OPTEE_MSG_RPC_CMD_FS, d, ent);
}
-static size_t meta_size(void)
-{
- return tee_fs_get_header_size(META_FILE) +
- sizeof(struct tee_fs_file_meta);
-}
-
-static size_t meta_pos_raw(struct tee_fs_fd *fdp, bool active)
-{
- size_t offs = sizeof(uint32_t);
-
- if ((fdp->meta_counter & 1) == active)
- offs += meta_size();
- return offs;
-}
-
-static size_t block_size_raw(void)
-{
- return tee_fs_get_header_size(BLOCK_FILE) + BLOCK_SIZE;
-}
-
-static size_t block_pos_raw(struct tee_fs_file_meta *meta, size_t block_num,
- bool active)
-{
- size_t n = block_num * 2;
-
- if (active == get_backup_version_of_block(meta, block_num))
- n++;
-
- return sizeof(uint32_t) + meta_size() * 2 + n * block_size_raw();
-}
-
-/*
- * encrypted_fek: as input for META_FILE and BLOCK_FILE
- */
-static TEE_Result encrypt_and_write_file(struct tee_fs_fd *fdp,
- enum tee_fs_file_type file_type, size_t offs,
- void *data_in, size_t data_in_size,
- uint8_t *encrypted_fek)
+static TEE_Result out_of_place_write(struct tee_fs_fd *fdp, size_t pos,
+ const void *buf, size_t len)
{
TEE_Result res;
- struct tee_fs_rpc_operation op;
- void *ciphertext;
- size_t header_size = tee_fs_get_header_size(file_type);
- size_t ciphertext_size = header_size + data_in_size;
-
+ size_t start_block_num = pos_to_block_num(pos);
+ size_t end_block_num = pos_to_block_num(pos + len - 1);
+ size_t remain_bytes = len;
+ uint8_t *data_ptr = (uint8_t *)buf;
+ uint8_t *block;
+ struct tee_fs_htree_meta *meta = tee_fs_htree_get_meta(fdp->ht);
- res = tee_fs_rpc_write_init(&op, OPTEE_MSG_RPC_CMD_FS, fdp->fd,
- offs, ciphertext_size, &ciphertext);
- if (res != TEE_SUCCESS)
- return res;
+ block = malloc(BLOCK_SIZE);
+ if (!block)
+ return TEE_ERROR_OUT_OF_MEMORY;
- res = tee_fs_encrypt_file(file_type, data_in, data_in_size,
- ciphertext, &ciphertext_size, encrypted_fek);
- if (res != TEE_SUCCESS)
- return res;
+ while (start_block_num <= end_block_num) {
+ size_t offset = pos % BLOCK_SIZE;
+ size_t size_to_write = MIN(remain_bytes, (size_t)BLOCK_SIZE);
- return tee_fs_rpc_write_final(&op);
-}
+ if (size_to_write + offset > BLOCK_SIZE)
+ size_to_write = BLOCK_SIZE - offset;
-/*
- * encrypted_fek: as output for META_FILE
- * as input for BLOCK_FILE
- */
-static TEE_Result read_and_decrypt_file(struct tee_fs_fd *fdp,
- enum tee_fs_file_type file_type, size_t offs,
- void *data_out, size_t *data_out_size,
- uint8_t *encrypted_fek)
-{
- TEE_Result res;
- struct tee_fs_rpc_operation op;
- size_t bytes;
- void *ciphertext;
+ if (start_block_num * BLOCK_SIZE <
+ ROUNDUP(meta->length, BLOCK_SIZE)) {
+ res = tee_fs_htree_read_block(&fdp->ht,
+ start_block_num, block);
+ if (res != TEE_SUCCESS)
+ goto exit;
+ } else {
+ memset(block, 0, BLOCK_SIZE);
+ }
- bytes = *data_out_size + tee_fs_get_header_size(file_type);
- res = tee_fs_rpc_read_init(&op, OPTEE_MSG_RPC_CMD_FS, fdp->fd, offs,
- bytes, &ciphertext);
- if (res != TEE_SUCCESS)
- return res;
+ if (data_ptr)
+ memcpy(block + offset, data_ptr, size_to_write);
+ else
+ memset(block + offset, 0, size_to_write);
- res = tee_fs_rpc_read_final(&op, &bytes);
- if (res != TEE_SUCCESS)
- return res;
+ res = tee_fs_htree_write_block(&fdp->ht, start_block_num,
+ block);
+ if (res != TEE_SUCCESS)
+ goto exit;
- if (!bytes) {
- *data_out_size = 0;
- return TEE_SUCCESS;
+ if (data_ptr)
+ data_ptr += size_to_write;
+ remain_bytes -= size_to_write;
+ start_block_num++;
+ pos += size_to_write;
}
- res = tee_fs_decrypt_file(file_type, ciphertext, bytes, data_out,
- data_out_size, encrypted_fek);
- if (res != TEE_SUCCESS)
- return TEE_ERROR_CORRUPT_OBJECT;
- return TEE_SUCCESS;
-}
-
-static TEE_Result write_meta_file(struct tee_fs_fd *fdp,
- struct tee_fs_file_meta *meta)
-{
- size_t offs = meta_pos_raw(fdp, false);
-
- return encrypt_and_write_file(fdp, META_FILE, offs,
- (void *)&meta->info, sizeof(meta->info),
- meta->encrypted_fek);
-}
+ if (pos > meta->length)
+ meta->length = pos;
-static TEE_Result write_meta_counter(struct tee_fs_fd *fdp)
-{
- TEE_Result res;
- struct tee_fs_rpc_operation op;
- size_t bytes = sizeof(uint32_t);
- void *data;
-
- res = tee_fs_rpc_write_init(&op, OPTEE_MSG_RPC_CMD_FS, fdp->fd, 0,
- bytes, &data);
- if (res != TEE_SUCCESS)
- return res;
-
- memcpy(data, &fdp->meta_counter, bytes);
-
- return tee_fs_rpc_write_final(&op);
-}
-
-static TEE_Result create_meta(struct tee_fs_fd *fdp, const char *fname)
-{
- TEE_Result res;
-
- memset(fdp->meta.info.backup_version_table, 0xff,
- sizeof(fdp->meta.info.backup_version_table));
- fdp->meta.info.length = 0;
-
- res = tee_fs_generate_fek(fdp->meta.encrypted_fek, TEE_FS_KM_FEK_SIZE);
- if (res != TEE_SUCCESS)
- return res;
-
- res = tee_fs_rpc_create(OPTEE_MSG_RPC_CMD_FS, fname, &fdp->fd);
- if (res != TEE_SUCCESS)
- return res;
-
- fdp->meta.counter = fdp->meta_counter;
-
- res = write_meta_file(fdp, &fdp->meta);
- if (res != TEE_SUCCESS)
- return res;
- return write_meta_counter(fdp);
+exit:
+ free(block);
+ return res;
}
-static TEE_Result commit_meta_file(struct tee_fs_fd *fdp,
- struct tee_fs_file_meta *new_meta)
+static TEE_Result get_offs_size(enum tee_fs_htree_type type, size_t idx,
+ uint8_t vers, size_t *offs, size_t *size)
{
- TEE_Result res;
-
- new_meta->counter = fdp->meta_counter + 1;
+ const size_t node_size = sizeof(struct tee_fs_htree_node_image);
+ const size_t block_nodes = BLOCK_SIZE / (node_size * 2);
+ size_t pbn;
+ size_t bidx;
- res = write_meta_file(fdp, new_meta);
- if (res != TEE_SUCCESS)
- return res;
+ assert(vers == 0 || vers == 1);
/*
- * From now on the new meta is successfully committed,
- * change tee_fs_fd accordingly
+ * File layout
+ *
+ * phys block 0:
+ * tee_fs_htree_image vers 0 @ offs = 0
+ * tee_fs_htree_image vers 1 @ offs = sizeof(tee_fs_htree_image)
+ *
+ * phys block 1:
+ * tee_fs_htree_node_image 0 vers 0 @ offs = 0
+ * tee_fs_htree_node_image 0 vers 1 @ offs = node_size
+ * tee_fs_htree_node_image 1 vers 0 @ offs = node_size * 2
+ * tee_fs_htree_node_image 1 vers 1 @ offs = node_size * 3
+ * ...
+ * tee_fs_htree_node_image 61 vers 0 @ offs = node_size * 122
+ * tee_fs_htree_node_image 61 vers 1 @ offs = node_size * 123
+ *
+ * phys block 2:
+ * data block 0 vers 0
+ *
+ * phys block 3:
+ * data block 0 vers 1
+ *
+ * ...
+ * phys block 63:
+ * data block 61 vers 0
+ *
+ * phys block 64:
+ * data block 61 vers 1
+ *
+ * phys block 65:
+ * tee_fs_htree_node_image 62 vers 0 @ offs = 0
+ * tee_fs_htree_node_image 62 vers 1 @ offs = node_size
+ * tee_fs_htree_node_image 63 vers 0 @ offs = node_size * 2
+ * tee_fs_htree_node_image 63 vers 1 @ offs = node_size * 3
+ * ...
+ * tee_fs_htree_node_image 121 vers 0 @ offs = node_size * 122
+ * tee_fs_htree_node_image 121 vers 1 @ offs = node_size * 123
+ *
+ * ...
*/
- fdp->meta = *new_meta;
- fdp->meta_counter = fdp->meta.counter;
- return write_meta_counter(fdp);
-}
-
-static TEE_Result read_meta_file(struct tee_fs_fd *fdp,
- struct tee_fs_file_meta *meta)
-{
- size_t meta_info_size = sizeof(struct tee_fs_file_info);
- size_t offs = meta_pos_raw(fdp, true);
-
- return read_and_decrypt_file(fdp, META_FILE, offs,
- &meta->info, &meta_info_size,
- meta->encrypted_fek);
+ switch (type) {
+ case TEE_FS_HTREE_TYPE_HEAD:
+ *offs = sizeof(struct tee_fs_htree_image) * vers;
+ *size = sizeof(struct tee_fs_htree_image);
+ return TEE_SUCCESS;
+ case TEE_FS_HTREE_TYPE_NODE:
+ pbn = 1 + ((idx / block_nodes) * block_nodes * 2);
+ *offs = pbn * BLOCK_SIZE +
+ 2 * node_size * (idx % block_nodes) +
+ node_size * vers;
+ *size = node_size;
+ return TEE_SUCCESS;
+ case TEE_FS_HTREE_TYPE_BLOCK:
+ bidx = 2 * idx + vers;
+ pbn = 2 + bidx + bidx / (block_nodes * 2 - 1);
+ *offs = pbn * BLOCK_SIZE;
+ *size = BLOCK_SIZE;
+ return TEE_SUCCESS;
+ default:
+ return TEE_ERROR_GENERIC;
+ }
}
-static TEE_Result read_meta_counter(struct tee_fs_fd *fdp)
+static TEE_Result ree_fs_rpc_read_init(void *aux,
+ struct tee_fs_rpc_operation *op,
+ enum tee_fs_htree_type type, size_t idx,
+ uint8_t vers, void **data)
{
+ struct tee_fs_fd *fdp = aux;
TEE_Result res;
- struct tee_fs_rpc_operation op;
- void *data;
- size_t bytes = sizeof(uint32_t);
-
- res = tee_fs_rpc_read_init(&op, OPTEE_MSG_RPC_CMD_FS, fdp->fd, 0,
- bytes, &data);
- if (res != TEE_SUCCESS)
- return res;
+ size_t offs;
+ size_t size;
- res = tee_fs_rpc_read_final(&op, &bytes);
+ res = get_offs_size(type, idx, vers, &offs, &size);
if (res != TEE_SUCCESS)
return res;
- if (bytes != sizeof(uint32_t))
- return TEE_ERROR_CORRUPT_OBJECT;
-
- memcpy(&fdp->meta_counter, data, bytes);
-
- return TEE_SUCCESS;
+ return tee_fs_rpc_read_init(op, OPTEE_MSG_RPC_CMD_FS, fdp->fd,
+ offs, size, data);
}
-static TEE_Result read_meta(struct tee_fs_fd *fdp, const char *fname)
+static TEE_Result ree_fs_rpc_write_init(void *aux,
+ struct tee_fs_rpc_operation *op,
+ enum tee_fs_htree_type type, size_t idx,
+ uint8_t vers, void **data)
{
+ struct tee_fs_fd *fdp = aux;
TEE_Result res;
+ size_t offs;
+ size_t size;
- res = tee_fs_rpc_open(OPTEE_MSG_RPC_CMD_FS, fname, &fdp->fd);
- if (res != TEE_SUCCESS)
- return res;
-
- res = read_meta_counter(fdp);
- if (res != TEE_SUCCESS)
- return res;
-
- return read_meta_file(fdp, &fdp->meta);
-}
-
-static TEE_Result read_block(struct tee_fs_fd *fdp, int bnum, uint8_t *data)
-{
- TEE_Result res;
- size_t ct_size = block_size_raw();
- size_t out_size = BLOCK_SIZE;
- ssize_t pos = block_pos_raw(&fdp->meta, bnum, true);
- size_t bytes;
- void *ct;
- struct tee_fs_rpc_operation op;
-
- res = tee_fs_rpc_read_init(&op, OPTEE_MSG_RPC_CMD_FS, fdp->fd, pos,
- ct_size, &ct);
- if (res != TEE_SUCCESS)
- return res;
- res = tee_fs_rpc_read_final(&op, &bytes);
+ res = get_offs_size(type, idx, vers, &offs, &size);
if (res != TEE_SUCCESS)
return res;
- if (!bytes) {
- memset(data, 0, BLOCK_SIZE);
- return TEE_SUCCESS; /* Block does not exist */
- }
- return tee_fs_decrypt_file(BLOCK_FILE, ct, bytes, data,
- &out_size, fdp->meta.encrypted_fek);
+ return tee_fs_rpc_write_init(op, OPTEE_MSG_RPC_CMD_FS, fdp->fd,
+ offs, size, data);
}
-static TEE_Result write_block(struct tee_fs_fd *fdp, size_t bnum, uint8_t *data,
- struct tee_fs_file_meta *new_meta)
-{
- TEE_Result res;
- size_t offs = block_pos_raw(new_meta, bnum, false);
-
- res = encrypt_and_write_file(fdp, BLOCK_FILE, offs, data,
- BLOCK_SIZE, new_meta->encrypted_fek);
- if (res == TEE_SUCCESS)
- toggle_backup_version_of_block(new_meta, bnum);
- return res;
-}
-
-static TEE_Result out_of_place_write(struct tee_fs_fd *fdp, const void *buf,
- size_t len, struct tee_fs_file_meta *new_meta)
-{
- TEE_Result res;
- int start_block_num = pos_to_block_num(fdp->pos);
- int end_block_num = pos_to_block_num(fdp->pos + len - 1);
- size_t remain_bytes = len;
- uint8_t *data_ptr = (uint8_t *)buf;
- uint8_t *block;
- int orig_pos = fdp->pos;
-
- block = malloc(BLOCK_SIZE);
- if (!block)
- return TEE_ERROR_OUT_OF_MEMORY;
-
- while (start_block_num <= end_block_num) {
- int offset = fdp->pos % BLOCK_SIZE;
- size_t size_to_write = MIN(remain_bytes, (size_t)BLOCK_SIZE);
-
- if (size_to_write + offset > BLOCK_SIZE)
- size_to_write = BLOCK_SIZE - offset;
-
- res = read_block(fdp, start_block_num, block);
- if (res == TEE_ERROR_ITEM_NOT_FOUND)
- memset(block, 0, BLOCK_SIZE);
- else if (res != TEE_SUCCESS)
- goto exit;
-
- if (data_ptr)
- memcpy(block + offset, data_ptr, size_to_write);
- else
- memset(block + offset, 0, size_to_write);
-
- res = write_block(fdp, start_block_num, block, new_meta);
- if (res != TEE_SUCCESS)
- goto exit;
-
- if (data_ptr)
- data_ptr += size_to_write;
- remain_bytes -= size_to_write;
- start_block_num++;
- fdp->pos += size_to_write;
- }
-
- if (fdp->pos > (tee_fs_off_t)new_meta->info.length)
- new_meta->info.length = fdp->pos;
-
-exit:
- free(block);
- if (res != TEE_SUCCESS)
- fdp->pos = orig_pos;
- return res;
-}
+static const struct tee_fs_htree_storage ree_fs_storage_ops = {
+ .block_size = BLOCK_SIZE,
+ .rpc_read_init = ree_fs_rpc_read_init,
+ .rpc_read_final = tee_fs_rpc_read_final,
+ .rpc_write_init = ree_fs_rpc_write_init,
+ .rpc_write_final = tee_fs_rpc_write_final,
+};
-static TEE_Result open_internal(const char *file, bool create,
+static TEE_Result open_internal(struct tee_pobj *po, bool create,
struct tee_file_handle **fh)
{
TEE_Result res;
- size_t len;
struct tee_fs_fd *fdp = NULL;
- if (!file)
- return TEE_ERROR_BAD_PARAMETERS;
-
- len = strlen(file) + 1;
- if (len > TEE_FS_NAME_MAX)
- return TEE_ERROR_BAD_PARAMETERS;
-
fdp = calloc(1, sizeof(struct tee_fs_fd));
if (!fdp)
return TEE_ERROR_OUT_OF_MEMORY;
@@ -491,17 +268,22 @@ static TEE_Result open_internal(const char *file, bool create,
mutex_lock(&ree_fs_mutex);
if (create)
- res = create_meta(fdp, file);
+ res = tee_fs_rpc_create(OPTEE_MSG_RPC_CMD_FS, po, &fdp->fd);
else
- res = read_meta(fdp, file);
+ res = tee_fs_rpc_open(OPTEE_MSG_RPC_CMD_FS, po, &fdp->fd);
+
+ if (res != TEE_SUCCESS)
+ goto out;
+ res = tee_fs_htree_open(create, &ree_fs_storage_ops, fdp, &fdp->ht);
+out:
if (res == TEE_SUCCESS) {
*fh = (struct tee_file_handle *)fdp;
} else {
if (fdp->fd != -1)
tee_fs_rpc_close(OPTEE_MSG_RPC_CMD_FS, fdp->fd);
if (create)
- tee_fs_rpc_remove(OPTEE_MSG_RPC_CMD_FS, file);
+ tee_fs_rpc_remove(OPTEE_MSG_RPC_CMD_FS, po);
free(fdp);
}
@@ -509,14 +291,15 @@ static TEE_Result open_internal(const char *file, bool create,
return res;
}
-static TEE_Result ree_fs_open(const char *file, struct tee_file_handle **fh)
+static TEE_Result ree_fs_open(struct tee_pobj *po, struct tee_file_handle **fh)
{
- return open_internal(file, false, fh);
+ return open_internal(po, false, fh);
}
-static TEE_Result ree_fs_create(const char *file, struct tee_file_handle **fh)
+static TEE_Result ree_fs_create(struct tee_pobj *po,
+ struct tee_file_handle **fh)
{
- return open_internal(file, true, fh);
+ return open_internal(po, true, fh);
}
static void ree_fs_close(struct tee_file_handle **fh)
@@ -524,106 +307,53 @@ static void ree_fs_close(struct tee_file_handle **fh)
struct tee_fs_fd *fdp = (struct tee_fs_fd *)*fh;
if (fdp) {
+ tee_fs_htree_close(&fdp->ht);
tee_fs_rpc_close(OPTEE_MSG_RPC_CMD_FS, fdp->fd);
free(fdp);
*fh = NULL;
}
}
-static TEE_Result ree_fs_seek(struct tee_file_handle *fh, int32_t offset,
- TEE_Whence whence, int32_t *new_offs)
-{
- TEE_Result res;
- tee_fs_off_t new_pos;
- size_t filelen;
- struct tee_fs_fd *fdp = (struct tee_fs_fd *)fh;
-
- mutex_lock(&ree_fs_mutex);
-
- DMSG("offset=%d, whence=%d", (int)offset, whence);
-
- filelen = fdp->meta.info.length;
-
- switch (whence) {
- case TEE_DATA_SEEK_SET:
- new_pos = offset;
- break;
-
- case TEE_DATA_SEEK_CUR:
- new_pos = fdp->pos + offset;
- break;
-
- case TEE_DATA_SEEK_END:
- new_pos = filelen + offset;
- break;
-
- default:
- res = TEE_ERROR_BAD_PARAMETERS;
- goto exit;
- }
-
- if (new_pos < 0)
- new_pos = 0;
-
- if (new_pos > TEE_DATA_MAX_POSITION) {
- EMSG("Position is beyond TEE_DATA_MAX_POSITION");
- res = TEE_ERROR_BAD_PARAMETERS;
- goto exit;
- }
-
- fdp->pos = new_pos;
- if (new_offs)
- *new_offs = new_pos;
- res = TEE_SUCCESS;
-exit:
- mutex_unlock(&ree_fs_mutex);
- return res;
-}
-
-/*
- * To ensure atomic truncate operation, we can:
- *
- * - update file length to new length
- * - commit new meta
- *
- * To ensure atomic extend operation, we can:
- *
- * - update file length to new length
- * - allocate and fill zero data to new blocks
- * - commit new meta
- *
- * Any failure before committing new meta is considered as
- * update failed, and the file content will not be updated
- */
static TEE_Result ree_fs_ftruncate_internal(struct tee_fs_fd *fdp,
tee_fs_off_t new_file_len)
{
TEE_Result res;
- size_t old_file_len = fdp->meta.info.length;
- struct tee_fs_file_meta new_meta;
+ struct tee_fs_htree_meta *meta = tee_fs_htree_get_meta(fdp->ht);
- if (new_file_len > MAX_FILE_SIZE)
- return TEE_ERROR_BAD_PARAMETERS;
+ if ((size_t)new_file_len > meta->length) {
+ size_t ext_len = new_file_len - meta->length;
- new_meta = fdp->meta;
- new_meta.info.length = new_file_len;
+ res = out_of_place_write(fdp, meta->length, NULL, ext_len);
+ if (res != TEE_SUCCESS)
+ return res;
+ } else {
+ size_t offs;
+ size_t sz;
+
+ res = get_offs_size(TEE_FS_HTREE_TYPE_BLOCK,
+ ROUNDUP(new_file_len, BLOCK_SIZE) /
+ BLOCK_SIZE, 1, &offs, &sz);
+ if (res != TEE_SUCCESS)
+ return res;
- if ((size_t)new_file_len > old_file_len) {
- size_t ext_len = new_file_len - old_file_len;
- int orig_pos = fdp->pos;
+ res = tee_fs_htree_truncate(&fdp->ht,
+ new_file_len / BLOCK_SIZE);
+ if (res != TEE_SUCCESS)
+ return res;
- fdp->pos = old_file_len;
- res = out_of_place_write(fdp, NULL, ext_len, &new_meta);
- fdp->pos = orig_pos;
+ res = tee_fs_rpc_truncate(OPTEE_MSG_RPC_CMD_FS, fdp->fd,
+ offs + sz);
if (res != TEE_SUCCESS)
return res;
+
+ meta->length = new_file_len;
}
- return commit_meta_file(fdp, &new_meta);
+ return tee_fs_htree_sync_to_storage(&fdp->ht);
}
-static TEE_Result ree_fs_read(struct tee_file_handle *fh, void *buf,
- size_t *len)
+static TEE_Result ree_fs_read(struct tee_file_handle *fh, size_t pos,
+ void *buf, size_t *len)
{
TEE_Result res;
int start_block_num;
@@ -632,16 +362,15 @@ static TEE_Result ree_fs_read(struct tee_file_handle *fh, void *buf,
uint8_t *data_ptr = buf;
uint8_t *block = NULL;
struct tee_fs_fd *fdp = (struct tee_fs_fd *)fh;
+ struct tee_fs_htree_meta *meta = tee_fs_htree_get_meta(fdp->ht);
mutex_lock(&ree_fs_mutex);
remain_bytes = *len;
- if ((fdp->pos + remain_bytes) < remain_bytes ||
- fdp->pos > (tee_fs_off_t)fdp->meta.info.length)
+ if ((pos + remain_bytes) < remain_bytes || pos > meta->length)
remain_bytes = 0;
- else if (fdp->pos + (tee_fs_off_t)remain_bytes >
- (tee_fs_off_t)fdp->meta.info.length)
- remain_bytes = fdp->meta.info.length - fdp->pos;
+ else if (pos + remain_bytes > meta->length)
+ remain_bytes = meta->length - pos;
*len = remain_bytes;
@@ -650,8 +379,8 @@ static TEE_Result ree_fs_read(struct tee_file_handle *fh, void *buf,
goto exit;
}
- start_block_num = pos_to_block_num(fdp->pos);
- end_block_num = pos_to_block_num(fdp->pos + remain_bytes - 1);
+ start_block_num = pos_to_block_num(pos);
+ end_block_num = pos_to_block_num(pos + remain_bytes - 1);
block = malloc(BLOCK_SIZE);
if (!block) {
@@ -660,24 +389,21 @@ static TEE_Result ree_fs_read(struct tee_file_handle *fh, void *buf,
}
while (start_block_num <= end_block_num) {
- tee_fs_off_t offset = fdp->pos % BLOCK_SIZE;
+ size_t offset = pos % BLOCK_SIZE;
size_t size_to_read = MIN(remain_bytes, (size_t)BLOCK_SIZE);
if (size_to_read + offset > BLOCK_SIZE)
size_to_read = BLOCK_SIZE - offset;
- res = read_block(fdp, start_block_num, block);
- if (res != TEE_SUCCESS) {
- if (res == TEE_ERROR_MAC_INVALID)
- res = TEE_ERROR_CORRUPT_OBJECT;
+ res = tee_fs_htree_read_block(&fdp->ht, start_block_num, block);
+ if (res != TEE_SUCCESS)
goto exit;
- }
memcpy(data_ptr, block + offset, size_to_read);
data_ptr += size_to_read;
remain_bytes -= size_to_read;
- fdp->pos += size_to_read;
+ pos += size_to_read;
start_block_num++;
}
@@ -688,27 +414,10 @@ exit:
return res;
}
-/*
- * To ensure atomicity of write operation, we need to
- * do the following steps:
- * (The sequence of operations is very important)
- *
- * - Create a new backup version of meta file as a copy
- * of current meta file.
- * - For each blocks to write:
- * - Create new backup version for current block.
- * - Write data to new backup version.
- * - Update the new meta file accordingly.
- * - Write the new meta file.
- *
- * (Any failure in above steps is considered as update failed,
- * and the file content will not be updated)
- */
-static TEE_Result ree_fs_write(struct tee_file_handle *fh, const void *buf,
- size_t len)
+static TEE_Result ree_fs_write(struct tee_file_handle *fh, size_t pos,
+ const void *buf, size_t len)
{
TEE_Result res;
- struct tee_fs_file_meta new_meta;
struct tee_fs_fd *fdp = (struct tee_fs_fd *)fh;
size_t file_size;
@@ -717,31 +426,31 @@ static TEE_Result ree_fs_write(struct tee_file_handle *fh, const void *buf,
mutex_lock(&ree_fs_mutex);
- file_size = fdp->meta.info.length;
+ file_size = tee_fs_htree_get_meta(fdp->ht)->length;
- if ((fdp->pos + len) > MAX_FILE_SIZE || (fdp->pos + len) < len) {
+ if ((pos + len) < len) {
res = TEE_ERROR_BAD_PARAMETERS;
goto exit;
}
- if (file_size < (size_t)fdp->pos) {
- res = ree_fs_ftruncate_internal(fdp, fdp->pos);
+ if (file_size < pos) {
+ res = ree_fs_ftruncate_internal(fdp, pos);
if (res != TEE_SUCCESS)
goto exit;
}
- new_meta = fdp->meta;
- res = out_of_place_write(fdp, buf, len, &new_meta);
+ res = out_of_place_write(fdp, pos, buf, len);
if (res != TEE_SUCCESS)
goto exit;
- res = commit_meta_file(fdp, &new_meta);
exit:
+ if (res == TEE_SUCCESS)
+ res = tee_fs_htree_sync_to_storage(&fdp->ht);
mutex_unlock(&ree_fs_mutex);
return res;
}
-static TEE_Result ree_fs_rename(const char *old, const char *new,
+static TEE_Result ree_fs_rename(struct tee_pobj *old, struct tee_pobj *new,
bool overwrite)
{
TEE_Result res;
@@ -753,12 +462,12 @@ static TEE_Result ree_fs_rename(const char *old, const char *new,
return res;
}
-static TEE_Result ree_fs_remove(const char *file)
+static TEE_Result ree_fs_remove(struct tee_pobj *po)
{
TEE_Result res;
mutex_lock(&ree_fs_mutex);
- res = tee_fs_rpc_remove(OPTEE_MSG_RPC_CMD_FS, file);
+ res = tee_fs_rpc_remove(OPTEE_MSG_RPC_CMD_FS, po);
mutex_unlock(&ree_fs_mutex);
return res;
@@ -782,7 +491,6 @@ const struct tee_file_operations ree_fs_ops = {
.close = ree_fs_close,
.read = ree_fs_read,
.write = ree_fs_write,
- .seek = ree_fs_seek,
.truncate = ree_fs_truncate,
.rename = ree_fs_rename,
.remove = ree_fs_remove,
diff --git a/core/tee/tee_rpmb_fs.c b/core/tee/tee_rpmb_fs.c
index 229bce7..dcac98b 100644
--- a/core/tee/tee_rpmb_fs.c
+++ b/core/tee/tee_rpmb_fs.c
@@ -26,22 +26,24 @@
*/
#include <assert.h>
-#include <kernel/tee_common.h>
#include <kernel/mutex.h>
#include <kernel/panic.h>
+#include <kernel/tee_common.h>
#include <kernel/tee_common_otp.h>
+#include <kernel/tee_misc.h>
#include <kernel/thread.h>
#include <mm/core_memprot.h>
#include <mm/tee_mm.h>
#include <optee_msg_supplicant.h>
#include <stdlib.h>
-#include <string.h>
#include <string_ext.h>
+#include <string.h>
#include <sys/queue.h>
#include <tee/tee_cryp_provider.h>
-#include <tee/tee_fs_defs.h>
#include <tee/tee_fs.h>
#include <tee/tee_fs_key_manager.h>
+#include <tee/tee_pobj.h>
+#include <tee/tee_svc_storage.h>
#include <trace.h>
#include <util.h>
@@ -89,8 +91,6 @@ struct rpmb_file_handle {
char filename[TEE_RPMB_FS_FILENAME_LENGTH];
/* Address for current entry in RPMB */
uint32_t rpmb_fat_address;
- /* Current position */
- uint32_t pos;
};
/**
@@ -106,13 +106,10 @@ struct rpmb_fs_partition {
};
/**
- * A node in a list of directory entries. entry->name is a
- * pointer to name here.
+ * A node in a list of directory entries.
*/
struct tee_rpmb_fs_dirent {
struct tee_fs_dirent entry;
- char name[TEE_RPMB_FS_FILENAME_LENGTH];
- /* */
SIMPLEQ_ENTRY(tee_rpmb_fs_dirent) link;
};
@@ -1581,7 +1578,6 @@ out:
static void dump_fh(struct rpmb_file_handle *fh)
{
DMSG("fh->filename=%s", fh->filename);
- DMSG("fh->pos=%u", fh->pos);
DMSG("fh->rpmb_fat_address=%u", fh->rpmb_fat_address);
DMSG("fh->fat_entry.start_address=%u", fh->fat_entry.start_address);
DMSG("fh->fat_entry.data_size=%u", fh->fat_entry.data_size);
@@ -1592,7 +1588,8 @@ static void dump_fh(struct rpmb_file_handle *fh __unused)
}
#endif
-static struct rpmb_file_handle *alloc_file_handle(const char *filename)
+static struct rpmb_file_handle *alloc_file_handle(struct tee_pobj *po,
+ bool temporary)
{
struct rpmb_file_handle *fh = NULL;
@@ -1600,8 +1597,10 @@ static struct rpmb_file_handle *alloc_file_handle(const char *filename)
if (!fh)
return NULL;
- if (filename)
- strlcpy(fh->filename, filename, sizeof(fh->filename));
+ if (po)
+ tee_svc_storage_create_filename(fh->filename,
+ sizeof(fh->filename), po,
+ temporary);
return fh;
}
@@ -1696,7 +1695,7 @@ static TEE_Result rpmb_fs_setup(void)
partition_data->fat_start_address = RPMB_FS_FAT_START_ADDRESS;
/* Initial FAT entry with FILE_IS_LAST_ENTRY flag set. */
- fh = alloc_file_handle(NULL);
+ fh = alloc_file_handle(NULL, false);
if (!fh) {
res = TEE_ERROR_OUT_OF_MEMORY;
goto out;
@@ -1924,29 +1923,17 @@ again:
return res;
}
-static TEE_Result rpmb_fs_open_internal(const char *file, bool create,
+static TEE_Result rpmb_fs_open_internal(struct tee_pobj *po, bool create,
struct tee_file_handle **ret_fh)
{
struct rpmb_file_handle *fh = NULL;
- size_t filelen;
tee_mm_pool_t p;
bool pool_result;
TEE_Result res = TEE_ERROR_GENERIC;
mutex_lock(&rpmb_mutex);
- filelen = strlen(file);
- if (filelen >= TEE_RPMB_FS_FILENAME_LENGTH - 1 || filelen == 0) {
- res = TEE_ERROR_BAD_PARAMETERS;
- goto out;
- }
-
- if (file[filelen - 1] == '/') {
- res = TEE_ERROR_BAD_PARAMETERS;
- goto out;
- }
-
- fh = alloc_file_handle(file);
+ fh = alloc_file_handle(po, po->temporary);
if (!fh) {
res = TEE_ERROR_OUT_OF_MEMORY;
goto out;
@@ -1988,7 +1975,8 @@ static TEE_Result rpmb_fs_open_internal(const char *file, bool create,
if ((fh->fat_entry.flags & FILE_IS_ACTIVE) == 0) {
memset(&fh->fat_entry, 0,
sizeof(struct rpmb_fat_entry));
- memcpy(fh->fat_entry.filename, file, strlen(file));
+ memcpy(fh->fat_entry.filename, fh->filename,
+ strlen(fh->filename));
/* Start address and size are 0 */
fh->fat_entry.flags = FILE_IS_ACTIVE;
@@ -2025,8 +2013,8 @@ static void rpmb_fs_close(struct tee_file_handle **tfh)
*tfh = NULL;
}
-static TEE_Result rpmb_fs_read(struct tee_file_handle *tfh, void *buf,
- size_t *len)
+static TEE_Result rpmb_fs_read(struct tee_file_handle *tfh, size_t pos,
+ void *buf, size_t *len)
{
TEE_Result res;
struct rpmb_file_handle *fh = (struct rpmb_file_handle *)tfh;
@@ -2043,29 +2031,28 @@ static TEE_Result rpmb_fs_read(struct tee_file_handle *tfh, void *buf,
if (res != TEE_SUCCESS)
goto out;
- if (fh->pos >= fh->fat_entry.data_size) {
+ if (pos >= fh->fat_entry.data_size) {
*len = 0;
goto out;
}
- size = MIN(size, fh->fat_entry.data_size - fh->pos);
+ size = MIN(size, fh->fat_entry.data_size - pos);
if (size) {
res = tee_rpmb_read(CFG_RPMB_FS_DEV_ID,
- fh->fat_entry.start_address + fh->pos, buf,
+ fh->fat_entry.start_address + pos, buf,
size, fh->fat_entry.fek);
if (res != TEE_SUCCESS)
goto out;
}
*len = size;
- fh->pos += size;
out:
mutex_unlock(&rpmb_mutex);
return res;
}
-static TEE_Result rpmb_fs_write(struct tee_file_handle *tfh, const void *buf,
- size_t size)
+static TEE_Result rpmb_fs_write(struct tee_file_handle *tfh, size_t pos,
+ const void *buf, size_t size)
{
TEE_Result res;
struct rpmb_file_handle *fh = (struct rpmb_file_handle *)tfh;
@@ -2108,8 +2095,8 @@ static TEE_Result rpmb_fs_write(struct tee_file_handle *tfh, const void *buf,
if (fh->fat_entry.flags & FILE_IS_LAST_ENTRY)
panic("invalid last entry flag");
- end = fh->pos + size;
- start_addr = fh->fat_entry.start_address + fh->pos;
+ end = pos + size;
+ start_addr = fh->fat_entry.start_address + pos;
if (end <= fh->fat_entry.data_size &&
tee_rpmb_write_is_atomic(CFG_RPMB_FS_DEV_ID, start_addr, size)) {
@@ -2143,7 +2130,7 @@ static TEE_Result rpmb_fs_write(struct tee_file_handle *tfh, const void *buf,
goto out;
}
- memcpy(newbuf + fh->pos, buf, size);
+ memcpy(newbuf + pos, buf, size);
newaddr = tee_mm_get_smem(mm);
res = tee_rpmb_write(CFG_RPMB_FS_DEV_ID, newaddr, newbuf,
@@ -2158,7 +2145,6 @@ static TEE_Result rpmb_fs_write(struct tee_file_handle *tfh, const void *buf,
goto out;
}
- fh->pos += size;
out:
mutex_unlock(&rpmb_mutex);
if (pool_result)
@@ -2169,68 +2155,14 @@ out:
return res;
}
-static TEE_Result rpmb_fs_seek(struct tee_file_handle *tfh, int32_t offset,
- TEE_Whence whence, int32_t *new_offs)
-
-{
- struct rpmb_file_handle *fh = (struct rpmb_file_handle *)tfh;
- TEE_Result res;
- tee_fs_off_t new_pos;
-
- mutex_lock(&rpmb_mutex);
-
- res = read_fat(fh, NULL);
- if (res != TEE_SUCCESS)
- goto out;
-
- switch (whence) {
- case TEE_DATA_SEEK_SET:
- new_pos = offset;
- break;
-
- case TEE_DATA_SEEK_CUR:
- new_pos = fh->pos + offset;
- break;
-
- case TEE_DATA_SEEK_END:
- new_pos = fh->fat_entry.data_size + offset;
- break;
-
- default:
- res = TEE_ERROR_BAD_PARAMETERS;
- goto out;
- }
-
- if (new_pos < 0)
- new_pos = 0;
-
- if (new_pos > TEE_DATA_MAX_POSITION) {
- EMSG("Position is beyond TEE_DATA_MAX_POSITION");
- res = TEE_ERROR_BAD_PARAMETERS;
- goto out;
- }
-
- fh->pos = new_pos;
- if (new_offs)
- *new_offs = new_pos;
-out:
- mutex_unlock(&rpmb_mutex);
- return res;
-}
-
-static TEE_Result rpmb_fs_remove(const char *filename)
+static TEE_Result rpmb_fs_remove(struct tee_pobj *po)
{
TEE_Result res = TEE_ERROR_GENERIC;
struct rpmb_file_handle *fh = NULL;
mutex_lock(&rpmb_mutex);
- if (!filename || strlen(filename) >= TEE_RPMB_FS_FILENAME_LENGTH - 1) {
- res = TEE_ERROR_BAD_PARAMETERS;
- goto out;
- }
-
- fh = alloc_file_handle(filename);
+ fh = alloc_file_handle(po, po->temporary);
if (!fh) {
res = TEE_ERROR_OUT_OF_MEMORY;
goto out;
@@ -2250,39 +2182,33 @@ out:
return res;
}
-static TEE_Result rpmb_fs_rename(const char *old_name, const char *new_name,
+static TEE_Result rpmb_fs_rename(struct tee_pobj *old, struct tee_pobj *new,
bool overwrite)
{
TEE_Result res = TEE_ERROR_GENERIC;
struct rpmb_file_handle *fh_old = NULL;
struct rpmb_file_handle *fh_new = NULL;
- uint32_t old_len;
- uint32_t new_len;
mutex_lock(&rpmb_mutex);
- if (!old_name || !new_name) {
+ if (!old) {
res = TEE_ERROR_BAD_PARAMETERS;
goto out;
}
- old_len = strlen(old_name);
- new_len = strlen(new_name);
-
- if ((old_len >= TEE_RPMB_FS_FILENAME_LENGTH - 1) ||
- (new_len >= TEE_RPMB_FS_FILENAME_LENGTH - 1) || (new_len == 0)) {
-
- res = TEE_ERROR_BAD_PARAMETERS;
- goto out;
- }
-
- fh_old = alloc_file_handle(old_name);
+ if (new)
+ fh_old = alloc_file_handle(old, old->temporary);
+ else
+ fh_old = alloc_file_handle(old, true);
if (!fh_old) {
res = TEE_ERROR_OUT_OF_MEMORY;
goto out;
}
- fh_new = alloc_file_handle(new_name);
+ if (new)
+ fh_new = alloc_file_handle(new, new->temporary);
+ else
+ fh_new = alloc_file_handle(old, false);
if (!fh_new) {
res = TEE_ERROR_OUT_OF_MEMORY;
goto out;
@@ -2307,7 +2233,8 @@ static TEE_Result rpmb_fs_rename(const char *old_name, const char *new_name,
}
memset(fh_old->fat_entry.filename, 0, TEE_RPMB_FS_FILENAME_LENGTH);
- memcpy(fh_old->fat_entry.filename, new_name, new_len);
+ memcpy(fh_old->fat_entry.filename, fh_new->filename,
+ strlen(fh_new->filename));
res = write_fat_entry(fh_old, false);
@@ -2477,15 +2404,20 @@ static TEE_Result rpmb_fs_dir_populate(const char *path,
goto out;
}
- memset(next, 0, sizeof(*next));
- next->entry.d_name = next->name;
- memcpy(next->name,
- &filename[pathlen],
- filelen - pathlen);
+ next->entry.oidlen = tee_hs2b(
+ (uint8_t *)&filename[pathlen],
+ next->entry.oid,
+ filelen - pathlen,
+ sizeof(next->entry.oid));
+ if (next->entry.oidlen) {
+ SIMPLEQ_INSERT_TAIL(&dir->next,
+ next, link);
+ current = next;
+ } else {
+ free(next);
+ next = NULL;
+ }
- SIMPLEQ_INSERT_TAIL(&dir->next, next,
- link);
- current = next;
}
}
@@ -2514,32 +2446,25 @@ out:
return res;
}
-static TEE_Result rpmb_fs_opendir(const char *path, struct tee_fs_dir **dir)
+static TEE_Result rpmb_fs_opendir(const TEE_UUID *uuid, struct tee_fs_dir **dir)
{
uint32_t len;
- uint32_t max_size;
char path_local[TEE_RPMB_FS_FILENAME_LENGTH];
TEE_Result res = TEE_ERROR_GENERIC;
struct tee_fs_dir *rpmb_dir = NULL;
- if (!path || !dir) {
+ if (!uuid || !dir) {
res = TEE_ERROR_BAD_PARAMETERS;
goto out;
}
- /*
- * There must be room for at least the NULL char and a char for the
- * filename after the path.
- */
- max_size = TEE_RPMB_FS_FILENAME_LENGTH - 2;
- len = strlen(path);
- if (len > max_size || len == 0) {
+ memset(path_local, 0, sizeof(path_local));
+ if (tee_svc_storage_create_dirname(path_local, sizeof(path_local) - 1,
+ uuid) != TEE_SUCCESS) {
res = TEE_ERROR_BAD_PARAMETERS;
goto out;
}
-
- memset(path_local, 0, sizeof(path_local));
- memcpy(path_local, path, len);
+ len = strlen(path_local);
/* Add a slash to correctly match the full directory name. */
if (path_local[len - 1] != '/')
@@ -2591,14 +2516,15 @@ static void rpmb_fs_closedir(struct tee_fs_dir *dir)
}
}
-static TEE_Result rpmb_fs_open(const char *file, struct tee_file_handle **fh)
+static TEE_Result rpmb_fs_open(struct tee_pobj *po, struct tee_file_handle **fh)
{
- return rpmb_fs_open_internal(file, false, fh);
+ return rpmb_fs_open_internal(po, false, fh);
}
-static TEE_Result rpmb_fs_create(const char *file, struct tee_file_handle **fh)
+static TEE_Result rpmb_fs_create(struct tee_pobj *po,
+ struct tee_file_handle **fh)
{
- return rpmb_fs_open_internal(file, true, fh);
+ return rpmb_fs_open_internal(po, true, fh);
}
const struct tee_file_operations rpmb_fs_ops = {
@@ -2607,7 +2533,6 @@ const struct tee_file_operations rpmb_fs_ops = {
.close = rpmb_fs_close,
.read = rpmb_fs_read,
.write = rpmb_fs_write,
- .seek = rpmb_fs_seek,
.truncate = rpmb_fs_truncate,
.rename = rpmb_fs_rename,
.remove = rpmb_fs_remove,
diff --git a/core/tee/tee_sql_fs.c b/core/tee/tee_sql_fs.c
index e38e1bc..bfc04f6 100644
--- a/core/tee/tee_sql_fs.c
+++ b/core/tee/tee_sql_fs.c
@@ -29,15 +29,6 @@
* This file implements the tee_file_operations structure for a secure
* filesystem based on an SQLite database in normal world.
* The atomicity of each operation is ensured by using SQL transactions.
- * The main purpose of the code below is to perform block encryption and
- * authentication of the file data, and properly handle seeking through the
- * file. One file (in the sense of struct tee_file_operations) maps to one
- * file in the SQL filesystem, and has the following structure:
- *
- * [ File meta-data ][ Block #0 ][Block #1]...
- * [meta_header|sql_fs_file_meta][block_header|user data][ ]...
- *
- * meta_header and block_header are defined in tee_fs_key_manager.h.
*/
#include <assert.h>
@@ -45,13 +36,12 @@
#include <optee_msg_supplicant.h>
#include <stdio.h>
#include <stdlib.h>
-#include <string.h>
#include <string_ext.h>
+#include <string.h>
#include <sys/queue.h>
+#include <tee/fs_htree.h>
#include <tee/tee_cryp_provider.h>
#include <tee/tee_fs.h>
-#include <tee/tee_fs_defs.h>
-#include <tee/tee_fs_key_manager.h>
#include <tee/tee_fs_rpc.h>
#include <trace.h>
#include <utee_defines.h>
@@ -61,22 +51,10 @@
#define BLOCK_SHIFT 12
#define BLOCK_SIZE (1 << BLOCK_SHIFT)
-struct sql_fs_file_meta {
- size_t length;
-};
-
/* File descriptor */
struct sql_fs_fd {
- struct sql_fs_file_meta meta;
- uint8_t encrypted_fek[TEE_FS_KM_FEK_SIZE];
- tee_fs_off_t pos;
+ struct tee_fs_htree *ht;
int fd; /* returned by normal world */
- int flags; /* open flags */
-};
-
-struct tee_fs_dir {
- int nw_dir;
- struct tee_fs_dirent d;
};
static struct mutex sql_fs_mutex = MUTEX_INITIALIZER;
@@ -96,9 +74,10 @@ static TEE_Result sql_fs_end_transaction_rpc(bool rollback)
rollback);
}
-static TEE_Result sql_fs_opendir_rpc(const char *name, struct tee_fs_dir **d)
+static TEE_Result sql_fs_opendir_rpc(const TEE_UUID *uuid,
+ struct tee_fs_dir **d)
{
- return tee_fs_rpc_opendir(OPTEE_MSG_RPC_CMD_SQL_FS, name, d);
+ return tee_fs_rpc_opendir(OPTEE_MSG_RPC_CMD_SQL_FS, uuid, d);
}
static TEE_Result sql_fs_readdir_rpc(struct tee_fs_dir *d,
@@ -107,15 +86,15 @@ static TEE_Result sql_fs_readdir_rpc(struct tee_fs_dir *d,
return tee_fs_rpc_readdir(OPTEE_MSG_RPC_CMD_SQL_FS, d, ent);
}
-static TEE_Result sql_fs_remove_rpc(const char *file)
+static TEE_Result sql_fs_remove_rpc(struct tee_pobj *po)
{
- return tee_fs_rpc_remove(OPTEE_MSG_RPC_CMD_SQL_FS, file);
+ return tee_fs_rpc_remove(OPTEE_MSG_RPC_CMD_SQL_FS, po);
}
-static TEE_Result sql_fs_rename_rpc(const char *old, const char *nw,
+static TEE_Result sql_fs_rename_rpc(struct tee_pobj *old, struct tee_pobj *new,
bool overwrite)
{
- return tee_fs_rpc_rename(OPTEE_MSG_RPC_CMD_SQL_FS, old, nw, overwrite);
+ return tee_fs_rpc_rename(OPTEE_MSG_RPC_CMD_SQL_FS, old, new, overwrite);
}
static void sql_fs_closedir_rpc(struct tee_fs_dir *d)
@@ -128,21 +107,6 @@ static void sql_fs_closedir_rpc(struct tee_fs_dir *d)
* End of interface with tee-supplicant
*/
-static size_t meta_size(void)
-{
- return tee_fs_get_header_size(META_FILE) +
- sizeof(struct sql_fs_file_meta);
-}
-
-static size_t block_header_size(void)
-{
- return tee_fs_get_header_size(BLOCK_FILE);
-}
-
-static size_t block_size_raw(void)
-{
- return block_header_size() + BLOCK_SIZE;
-}
/* Return the block number from a position in the user data */
static ssize_t block_num(tee_fs_off_t pos)
@@ -150,131 +114,108 @@ static ssize_t block_num(tee_fs_off_t pos)
return pos / BLOCK_SIZE;
}
-/* Return the position of a block in the DB file */
-static ssize_t block_pos_raw(size_t block_num)
+static TEE_Result get_offs_size(enum tee_fs_htree_type type, size_t idx,
+ size_t *offs, size_t *size)
{
- return meta_size() + block_num * block_size_raw();
-}
-
-static TEE_Result write_meta(struct sql_fs_fd *fdp)
-{
- TEE_Result res;
- size_t ct_size = meta_size();
- void *ct;
- struct tee_fs_rpc_operation op;
-
- res = tee_fs_rpc_write_init(&op, OPTEE_MSG_RPC_CMD_SQL_FS, fdp->fd, 0,
- ct_size, &ct);
- if (res != TEE_SUCCESS)
- return res;
-
-
- res = tee_fs_encrypt_file(META_FILE,
- (const uint8_t *)&fdp->meta,
- sizeof(fdp->meta), ct, &ct_size,
- fdp->encrypted_fek);
- if (res != TEE_SUCCESS)
- return res;
-
- return tee_fs_rpc_write_final(&op);
+ const size_t node_size = sizeof(struct tee_fs_htree_node_image);
+ const size_t block_nodes = BLOCK_SIZE / node_size;
+ size_t pbn;
+ size_t bidx;
+
+
+ /*
+ * File layout
+ *
+ * phys block 0:
+ * tee_fs_htree_image @ offs = 0
+ *
+ * phys block 1:
+ * tee_fs_htree_node_image 0 @ offs = 0
+ * tee_fs_htree_node_image 1 @ offs = node_size * 2
+ * ...
+ * tee_fs_htree_node_image 61 @ offs = node_size * 122
+ *
+ * phys block 2:
+ * data block 0
+ *
+ * ...
+ *
+ * phys block 64:
+ * data block 61
+ *
+ * phys block 65:
+ * tee_fs_htree_node_image 62 @ offs = 0
+ * tee_fs_htree_node_image 63 @ offs = node_size * 2
+ * ...
+ * tee_fs_htree_node_image 121 @ offs = node_size * 123
+ *
+ * ...
+ */
+
+ switch (type) {
+ case TEE_FS_HTREE_TYPE_HEAD:
+ *offs = 0;
+ *size = sizeof(struct tee_fs_htree_image);
+ return TEE_SUCCESS;
+ case TEE_FS_HTREE_TYPE_NODE:
+ pbn = 1 + ((idx / block_nodes) * block_nodes);
+ *offs = pbn * BLOCK_SIZE + node_size * (idx % block_nodes);
+ *size = node_size;
+ return TEE_SUCCESS;
+ case TEE_FS_HTREE_TYPE_BLOCK:
+ bidx = idx;
+ pbn = 2 + bidx + bidx / (block_nodes - 1);
+ *offs = pbn * BLOCK_SIZE;
+ *size = BLOCK_SIZE;
+ return TEE_SUCCESS;
+ default:
+ return TEE_ERROR_GENERIC;
+ }
}
-static TEE_Result create_meta(struct sql_fs_fd *fdp, const char *fname)
+static TEE_Result sql_fs_rpc_read_init(void *aux,
+ struct tee_fs_rpc_operation *op,
+ enum tee_fs_htree_type type, size_t idx,
+ uint8_t vers __unused, void **data)
{
+ struct sql_fs_fd *fdp = aux;
TEE_Result res;
+ size_t offs;
+ size_t size;
- memset(&fdp->meta, 0, sizeof(fdp->meta));
-
- res = tee_fs_generate_fek(fdp->encrypted_fek, TEE_FS_KM_FEK_SIZE);
- if (res != TEE_SUCCESS)
- return res;
-
- res = tee_fs_rpc_create(OPTEE_MSG_RPC_CMD_SQL_FS, fname, &fdp->fd);
+ res = get_offs_size(type, idx, &offs, &size);
if (res != TEE_SUCCESS)
return res;
- return write_meta(fdp);
+ return tee_fs_rpc_read_init(op, OPTEE_MSG_RPC_CMD_SQL_FS, fdp->fd,
+ offs, size, data);
}
-static TEE_Result read_meta(struct sql_fs_fd *fdp, const char *fname)
+static TEE_Result sql_fs_rpc_write_init(void *aux,
+ struct tee_fs_rpc_operation *op,
+ enum tee_fs_htree_type type, size_t idx,
+ uint8_t vers __unused, void **data)
{
+ struct sql_fs_fd *fdp = aux;
TEE_Result res;
- size_t msize = meta_size();
- size_t out_size = sizeof(fdp->meta);
- void *meta;
- size_t bytes;
- struct tee_fs_rpc_operation op;
-
- res = tee_fs_rpc_open(OPTEE_MSG_RPC_CMD_SQL_FS, fname, &fdp->fd);
- if (res != TEE_SUCCESS)
- return res;
-
- res = tee_fs_rpc_read_init(&op, OPTEE_MSG_RPC_CMD_SQL_FS, fdp->fd, 0,
- msize, &meta);
- if (res != TEE_SUCCESS)
- return res;
-
- res = tee_fs_rpc_read_final(&op, &bytes);
- if (res != TEE_SUCCESS)
- return res;
+ size_t offs;
+ size_t size;
- return tee_fs_decrypt_file(META_FILE, meta, msize,
- (uint8_t *)&fdp->meta, &out_size,
- fdp->encrypted_fek);
-}
-
-/*
- * Read one block of user data.
- * Returns:
- * < 0: read error
- * 0: block does not exist (reading past last block)
- * > 0: success
- */
-static TEE_Result read_block(struct sql_fs_fd *fdp, size_t bnum, uint8_t *data)
-{
- TEE_Result res;
- size_t ct_size = block_size_raw();
- size_t out_size = BLOCK_SIZE;
- ssize_t pos = block_pos_raw(bnum);
- size_t bytes;
- void *ct;
- struct tee_fs_rpc_operation op;
-
- res = tee_fs_rpc_read_init(&op, OPTEE_MSG_RPC_CMD_SQL_FS, fdp->fd, pos,
- ct_size, &ct);
+ res = get_offs_size(type, idx, &offs, &size);
if (res != TEE_SUCCESS)
return res;
- res = tee_fs_rpc_read_final(&op, &bytes);
- if (res != TEE_SUCCESS)
- return res;
- if (!bytes)
- return TEE_SUCCESS; /* Block does not exist */
- return tee_fs_decrypt_file(BLOCK_FILE, ct, bytes, data,
- &out_size, fdp->encrypted_fek);
+ return tee_fs_rpc_write_init(op, OPTEE_MSG_RPC_CMD_SQL_FS, fdp->fd,
+ offs, size, data);
}
-/* Write one block of user data */
-static TEE_Result write_block(struct sql_fs_fd *fdp, size_t bnum, uint8_t *data)
-{
- TEE_Result res;
- size_t ct_size = block_size_raw();
- ssize_t pos = block_pos_raw(bnum);
- void *ct;
- struct tee_fs_rpc_operation op;
-
- res = tee_fs_rpc_write_init(&op, OPTEE_MSG_RPC_CMD_SQL_FS, fdp->fd, pos,
- ct_size, &ct);
- if (res != TEE_SUCCESS)
- return res;
-
- res = tee_fs_encrypt_file(BLOCK_FILE, data, BLOCK_SIZE, ct,
- &ct_size, fdp->encrypted_fek);
- if (res != TEE_SUCCESS)
- return res;
-
- return tee_fs_rpc_write_final(&op);
-}
+static const struct tee_fs_htree_storage sql_fs_storage_ops = {
+ .block_size = BLOCK_SIZE,
+ .rpc_read_init = sql_fs_rpc_read_init,
+ .rpc_read_final = tee_fs_rpc_read_final,
+ .rpc_write_init = sql_fs_rpc_write_init,
+ .rpc_write_final = tee_fs_rpc_write_final,
+};
/*
* Partial write (< BLOCK_SIZE) into a block: read/update/write
@@ -296,16 +237,21 @@ static TEE_Result write_block_partial(struct sql_fs_fd *fdp, size_t bnum,
if (!buf)
return TEE_ERROR_OUT_OF_MEMORY;
- res = read_block(fdp, bnum, buf);
- if (res != TEE_SUCCESS)
- goto exit;
+ if (bnum * BLOCK_SIZE <
+ ROUNDUP(tee_fs_htree_get_meta(fdp->ht)->length, BLOCK_SIZE)) {
+ res = tee_fs_htree_read_block(&fdp->ht, bnum, buf);
+ if (res != TEE_SUCCESS)
+ goto exit;
+ } else {
+ memset(buf, 0, BLOCK_SIZE);
+ }
if (data)
memcpy(buf + offset, data, len);
else
memset(buf + offset, 0, len);
- res = write_block(fdp, bnum, buf);
+ res = tee_fs_htree_write_block(&fdp->ht, bnum, buf);
exit:
free(buf);
return res;
@@ -315,32 +261,42 @@ static TEE_Result sql_fs_ftruncate_internal(struct sql_fs_fd *fdp,
tee_fs_off_t new_length)
{
TEE_Result res;
- tee_fs_off_t old_length;
-
- old_length = (tee_fs_off_t)fdp->meta.length;
+ struct tee_fs_htree_meta *meta = tee_fs_htree_get_meta(fdp->ht);
- if (new_length == old_length)
+ if ((size_t)new_length == meta->length)
return TEE_SUCCESS;
sql_fs_begin_transaction_rpc();
- if (new_length < old_length) {
+ if ((size_t)new_length < meta->length) {
/* Trim unused blocks */
- int old_last_block = block_num(old_length);
+ int old_last_block = block_num(meta->length);
int last_block = block_num(new_length);
- tee_fs_off_t off;
if (last_block < old_last_block) {
- off = block_pos_raw(last_block);
+ size_t offs;
+ size_t sz;
+
+ res = get_offs_size(TEE_FS_HTREE_TYPE_BLOCK,
+ ROUNDUP(new_length, BLOCK_SIZE) /
+ BLOCK_SIZE, &offs, &sz);
+ if (res != TEE_SUCCESS)
+ goto exit;
+
+ res = tee_fs_htree_truncate(&fdp->ht,
+ new_length / BLOCK_SIZE);
+ if (res != TEE_SUCCESS)
+ goto exit;
+
res = tee_fs_rpc_truncate(OPTEE_MSG_RPC_CMD_SQL_FS,
- fdp->fd, off);
+ fdp->fd, offs + sz);
if (res != TEE_SUCCESS)
goto exit;
}
} else {
/* Extend file with zeroes */
- tee_fs_off_t off = old_length % BLOCK_SIZE;
- size_t bnum = block_num(old_length);
+ tee_fs_off_t off = meta->length % BLOCK_SIZE;
+ size_t bnum = block_num(meta->length);
size_t end_bnum = block_num(new_length);
while (bnum <= end_bnum) {
@@ -354,70 +310,28 @@ static TEE_Result sql_fs_ftruncate_internal(struct sql_fs_fd *fdp,
}
}
- fdp->meta.length = new_length;
- res = write_meta(fdp);
+ meta->length = new_length;
+ res = TEE_SUCCESS;
exit:
+ if (res == TEE_SUCCESS)
+ res = tee_fs_htree_sync_to_storage(&fdp->ht);
sql_fs_end_transaction_rpc(res != TEE_SUCCESS);
return res;
}
-static TEE_Result sql_fs_seek(struct tee_file_handle *fh, int32_t offset,
- TEE_Whence whence, int32_t *new_offs)
-{
- TEE_Result res;
- struct sql_fs_fd *fdp = (struct sql_fs_fd *)fh;
- tee_fs_off_t pos;
-
- mutex_lock(&sql_fs_mutex);
-
- switch (whence) {
- case TEE_DATA_SEEK_SET:
- pos = offset;
- break;
-
- case TEE_DATA_SEEK_CUR:
- pos = fdp->pos + offset;
- break;
-
- case TEE_DATA_SEEK_END:
- pos = fdp->meta.length + offset;
- break;
-
- default:
- res = TEE_ERROR_BAD_PARAMETERS;
- goto exit_ret;
- }
-
- if (pos > TEE_DATA_MAX_POSITION) {
- EMSG("Position is beyond TEE_DATA_MAX_POSITION");
- res = TEE_ERROR_BAD_PARAMETERS;
- goto exit_ret;
- }
-
- if (pos < 0)
- pos = 0;
-
- fdp->pos = pos;
- if (new_offs)
- *new_offs = pos;
- res = TEE_SUCCESS;
-exit_ret:
- mutex_unlock(&sql_fs_mutex);
- return res;
-}
-
static void sql_fs_close(struct tee_file_handle **fh)
{
struct sql_fs_fd *fdp = (struct sql_fs_fd *)*fh;
if (fdp) {
- tee_fs_rpc_close(OPTEE_MSG_RPC_CMD_SQL_FS, fdp->fd);
+ tee_fs_htree_close(&fdp->ht);
+ tee_fs_rpc_close(OPTEE_MSG_RPC_CMD_SQL_FS, fdp->fd);
free(fdp);
*fh = NULL;
}
}
-static TEE_Result open_internal(const char *file, bool create,
+static TEE_Result open_internal(struct tee_pobj *po, bool create,
struct tee_file_handle **fh)
{
TEE_Result res;
@@ -432,36 +346,41 @@ static TEE_Result open_internal(const char *file, bool create,
mutex_lock(&sql_fs_mutex);
if (create)
- res = create_meta(fdp, file);
+ res = tee_fs_rpc_create(OPTEE_MSG_RPC_CMD_SQL_FS, po, &fdp->fd);
else
- res = read_meta(fdp, file);
+ res = tee_fs_rpc_open(OPTEE_MSG_RPC_CMD_SQL_FS, po, &fdp->fd);
+ if (res != TEE_SUCCESS)
+ goto out;
+ res = tee_fs_htree_open(create, &sql_fs_storage_ops, fdp, &fdp->ht);
+out:
if (res == TEE_SUCCESS) {
*fh = (struct tee_file_handle *)fdp;
} else {
if (fdp && fdp->fd != -1)
tee_fs_rpc_close(OPTEE_MSG_RPC_CMD_SQL_FS, fdp->fd);
if (created)
- tee_fs_rpc_remove(OPTEE_MSG_RPC_CMD_SQL_FS, file);
+ tee_fs_rpc_remove(OPTEE_MSG_RPC_CMD_SQL_FS, po);
free(fdp);
}
mutex_unlock(&sql_fs_mutex);
return res;
}
-static TEE_Result sql_fs_open(const char *file, struct tee_file_handle **fh)
+static TEE_Result sql_fs_open(struct tee_pobj *po, struct tee_file_handle **fh)
{
- return open_internal(file, false, fh);
+ return open_internal(po, false, fh);
}
-static TEE_Result sql_fs_create(const char *file, struct tee_file_handle **fh)
+static TEE_Result sql_fs_create(struct tee_pobj *po,
+ struct tee_file_handle **fh)
{
- return open_internal(file, true, fh);
+ return open_internal(po, true, fh);
}
-static TEE_Result sql_fs_read(struct tee_file_handle *fh, void *buf,
- size_t *len)
+static TEE_Result sql_fs_read(struct tee_file_handle *fh, size_t pos,
+ void *buf, size_t *len)
{
TEE_Result res;
struct sql_fs_fd *fdp = (struct sql_fs_fd *)fh;
@@ -470,14 +389,15 @@ static TEE_Result sql_fs_read(struct tee_file_handle *fh, void *buf,
uint8_t *block = NULL;
int start_block_num;
int end_block_num;
+ size_t file_size;
mutex_lock(&sql_fs_mutex);
- if ((fdp->pos + remain_bytes) < remain_bytes ||
- fdp->pos > (tee_fs_off_t)fdp->meta.length)
+ file_size = tee_fs_htree_get_meta(fdp->ht)->length;
+ if ((pos + remain_bytes) < remain_bytes || pos > file_size)
remain_bytes = 0;
- else if (fdp->pos + remain_bytes > fdp->meta.length)
- remain_bytes = fdp->meta.length - fdp->pos;
+ else if (pos + remain_bytes > file_size)
+ remain_bytes = file_size - pos;
*len = remain_bytes;
@@ -486,8 +406,8 @@ static TEE_Result sql_fs_read(struct tee_file_handle *fh, void *buf,
goto exit;
}
- start_block_num = block_num(fdp->pos);
- end_block_num = block_num(fdp->pos + remain_bytes - 1);
+ start_block_num = block_num(pos);
+ end_block_num = block_num(pos + remain_bytes - 1);
block = malloc(BLOCK_SIZE);
if (!block) {
@@ -496,17 +416,13 @@ static TEE_Result sql_fs_read(struct tee_file_handle *fh, void *buf,
}
while (start_block_num <= end_block_num) {
- tee_fs_off_t offset = fdp->pos % BLOCK_SIZE;
+ size_t offset = pos % BLOCK_SIZE;
size_t size_to_read = MIN(remain_bytes, (size_t)BLOCK_SIZE);
if (size_to_read + offset > BLOCK_SIZE)
size_to_read = BLOCK_SIZE - offset;
- /*
- * REVISIT: implement read_block_partial() since we have
- * write_block_partial()?
- */
- res = read_block(fdp, start_block_num, block);
+ res = tee_fs_htree_read_block(&fdp->ht, start_block_num, block);
if (res != TEE_SUCCESS)
goto exit;
@@ -514,7 +430,7 @@ static TEE_Result sql_fs_read(struct tee_file_handle *fh, void *buf,
data_ptr += size_to_read;
remain_bytes -= size_to_read;
- fdp->pos += size_to_read;
+ pos += size_to_read;
start_block_num++;
}
@@ -525,11 +441,12 @@ exit:
return res;
}
-static TEE_Result sql_fs_write(struct tee_file_handle *fh, const void *buf,
- size_t len)
+static TEE_Result sql_fs_write(struct tee_file_handle *fh, size_t pos,
+ const void *buf, size_t len)
{
TEE_Result res;
struct sql_fs_fd *fdp = (struct sql_fs_fd *)fh;
+ struct tee_fs_htree_meta *meta = tee_fs_htree_get_meta(fdp->ht);
size_t remain_bytes = len;
const uint8_t *data_ptr = buf;
int start_block_num;
@@ -542,18 +459,18 @@ static TEE_Result sql_fs_write(struct tee_file_handle *fh, const void *buf,
sql_fs_begin_transaction_rpc();
- if (fdp->meta.length < (size_t)fdp->pos) {
+ if (meta->length < pos) {
/* Fill hole */
- res = sql_fs_ftruncate_internal(fdp, fdp->pos);
+ res = sql_fs_ftruncate_internal(fdp, pos);
if (res != TEE_SUCCESS)
goto exit;
}
- start_block_num = block_num(fdp->pos);
- end_block_num = block_num(fdp->pos + len - 1);
+ start_block_num = block_num(pos);
+ end_block_num = block_num(pos + len - 1);
while (start_block_num <= end_block_num) {
- tee_fs_off_t offset = fdp->pos % BLOCK_SIZE;
+ size_t offset = pos % BLOCK_SIZE;
size_t size_to_write = MIN(remain_bytes, (size_t)BLOCK_SIZE);
if (size_to_write + offset > BLOCK_SIZE)
@@ -566,16 +483,17 @@ static TEE_Result sql_fs_write(struct tee_file_handle *fh, const void *buf,
data_ptr += size_to_write;
remain_bytes -= size_to_write;
- fdp->pos += size_to_write;
+ pos += size_to_write;
start_block_num++;
}
- if (fdp->meta.length < (size_t)fdp->pos) {
- fdp->meta.length = fdp->pos;
- res = write_meta(fdp);
- }
+ if (pos > meta->length)
+ meta->length = pos;
+
exit:
+ if (res == TEE_SUCCESS)
+ res = tee_fs_htree_sync_to_storage(&fdp->ht);
sql_fs_end_transaction_rpc(res != TEE_SUCCESS);
mutex_unlock(&sql_fs_mutex);
return res;
@@ -599,7 +517,6 @@ const struct tee_file_operations sql_fs_ops = {
.close = sql_fs_close,
.read = sql_fs_read,
.write = sql_fs_write,
- .seek = sql_fs_seek,
.truncate = sql_fs_truncate,
.opendir = sql_fs_opendir_rpc,
diff --git a/core/tee/tee_svc_storage.c b/core/tee/tee_svc_storage.c
index 916ddca..d852be1 100644
--- a/core/tee/tee_svc_storage.c
+++ b/core/tee/tee_svc_storage.c
@@ -32,7 +32,6 @@
#include <string.h>
#include <tee_api_defines_extensions.h>
#include <tee_api_defines.h>
-#include <tee/tee_fs_defs.h>
#include <tee/tee_fs.h>
#include <tee/tee_obj.h>
#include <tee/tee_pobj.h>
@@ -99,12 +98,6 @@ struct tee_storage_enum {
const struct tee_file_operations *fops;
};
-/*
- * Protect TA storage directory: avoid race conditions between (create
- * directory + create file) and (remove directory)
- */
-static struct mutex ta_dir_mutex = MUTEX_INITIALIZER;
-
static TEE_Result tee_svc_storage_get_enum(struct user_ta_ctx *utc,
uint32_t enum_id,
struct tee_storage_enum **e_out)
@@ -140,114 +133,77 @@ static TEE_Result tee_svc_close_enum(struct user_ta_ctx *utc,
}
/* "/TA_uuid/object_id" or "/TA_uuid/.object_id" */
-char *tee_svc_storage_create_filename(struct tee_ta_session *sess,
- void *object_id,
- uint32_t object_id_len,
- bool transient)
+TEE_Result tee_svc_storage_create_filename(void *buf, size_t blen,
+ struct tee_pobj *po, bool transient)
{
- uint8_t *file;
+ uint8_t *file = buf;
uint32_t pos = 0;
uint32_t hslen = 1 /* Leading slash */
- + TEE_B2HS_HSBUF_SIZE(sizeof(TEE_UUID) + object_id_len)
+ + TEE_B2HS_HSBUF_SIZE(sizeof(TEE_UUID) + po->obj_id_len)
+ 1; /* Intermediate slash */
/* +1 for the '.' (temporary persistent object) */
if (transient)
hslen++;
- file = malloc(hslen);
- if (!file)
- return NULL;
+ if (blen < hslen)
+ return TEE_ERROR_SHORT_BUFFER;
file[pos++] = '/';
- pos += tee_b2hs((uint8_t *)&sess->ctx->uuid, &file[pos],
+ pos += tee_b2hs((uint8_t *)&po->uuid, &file[pos],
sizeof(TEE_UUID), hslen);
file[pos++] = '/';
if (transient)
file[pos++] = '.';
- tee_b2hs(object_id, file + pos, object_id_len, hslen - pos);
+ tee_b2hs(po->obj_id, file + pos, po->obj_id_len, hslen - pos);
- return (char *)file;
+ return TEE_SUCCESS;
}
/* "/TA_uuid" */
-char *tee_svc_storage_create_dirname(struct tee_ta_session *sess)
+TEE_Result tee_svc_storage_create_dirname(void *buf, size_t blen,
+ const TEE_UUID *uuid)
{
- uint8_t *dir;
+ uint8_t *dir = buf;
uint32_t hslen = TEE_B2HS_HSBUF_SIZE(sizeof(TEE_UUID)) + 1;
- dir = malloc(hslen);
- if (!dir)
- return NULL;
+ if (blen < hslen)
+ return TEE_ERROR_SHORT_BUFFER;
dir[0] = '/';
- tee_b2hs((uint8_t *)&sess->ctx->uuid, dir + 1, sizeof(TEE_UUID),
- hslen);
+ tee_b2hs((uint8_t *)uuid, dir + 1, sizeof(TEE_UUID), hslen);
- return (char *)dir;
+ return TEE_SUCCESS;
}
static TEE_Result tee_svc_storage_remove_corrupt_obj(
struct tee_ta_session *sess,
struct tee_obj *o)
{
- TEE_Result res;
- char *file = NULL;
- const struct tee_file_operations *fops = o->pobj->fops;
-
- file = tee_svc_storage_create_filename(sess,
- o->pobj->obj_id,
- o->pobj->obj_id_len,
- false);
- if (file == NULL) {
- res = TEE_ERROR_OUT_OF_MEMORY;
- goto exit;
- }
-
+ o->pobj->fops->remove(o->pobj);
tee_obj_close(to_user_ta_ctx(sess->ctx), o);
- fops->remove(file);
- free(file);
- res = TEE_SUCCESS;
-
-exit:
- return res;
+ return TEE_SUCCESS;
}
-static TEE_Result tee_svc_storage_read_head(struct tee_ta_session *sess,
- struct tee_obj *o)
+static TEE_Result tee_svc_storage_read_head(struct tee_obj *o)
{
TEE_Result res = TEE_SUCCESS;
size_t bytes;
struct tee_svc_storage_head head;
- char *file = NULL;
- const struct tee_file_operations *fops;
+ const struct tee_file_operations *fops = o->pobj->fops;
void *attr = NULL;
- if (o == NULL || o->pobj == NULL)
- return TEE_ERROR_BAD_PARAMETERS;
-
- fops = o->pobj->fops;
-
- file = tee_svc_storage_create_filename(sess,
- o->pobj->obj_id,
- o->pobj->obj_id_len,
- false);
- if (file == NULL) {
- res = TEE_ERROR_OUT_OF_MEMORY;
- goto exit;
- }
-
assert(!o->fh);
- res = fops->open(file, &o->fh);
+ res = fops->open(o->pobj, &o->fh);
if (res != TEE_SUCCESS)
goto exit;
/* read head */
bytes = sizeof(struct tee_svc_storage_head);
- res = fops->read(o->fh, &head, &bytes);
+ res = fops->read(o->fh, 0, &head, &bytes);
if (res != TEE_SUCCESS) {
if (res == TEE_ERROR_CORRUPT_OBJECT)
EMSG("Head corrupt\n");
@@ -263,6 +219,7 @@ static TEE_Result tee_svc_storage_read_head(struct tee_ta_session *sess,
if (res != TEE_SUCCESS)
goto exit;
+ o->ds_pos = sizeof(struct tee_svc_storage_head) + head.meta_size;
if (head.meta_size) {
attr = malloc(head.meta_size);
if (!attr) {
@@ -272,7 +229,8 @@ static TEE_Result tee_svc_storage_read_head(struct tee_ta_session *sess,
/* read meta */
bytes = head.meta_size;
- res = fops->read(o->fh, attr, &bytes);
+ res = fops->read(o->fh, sizeof(struct tee_svc_storage_head),
+ attr, &bytes);
if (res != TEE_SUCCESS || bytes != head.meta_size) {
res = TEE_ERROR_CORRUPT_OBJECT;
goto exit;
@@ -291,7 +249,6 @@ static TEE_Result tee_svc_storage_read_head(struct tee_ta_session *sess,
exit:
free(attr);
- free(file);
return res;
}
@@ -299,63 +256,22 @@ exit:
static TEE_Result tee_svc_storage_update_head(struct tee_obj *o,
uint32_t ds_size)
{
- TEE_Result res;
- const struct tee_file_operations *fops;
- int32_t old_off;
+ size_t pos = offsetof(struct tee_svc_storage_head, ds_size);
- fops = o->pobj->fops;
-
- /* save original offset */
- res = fops->seek(o->fh, 0, TEE_DATA_SEEK_CUR, &old_off);
- if (res != TEE_SUCCESS)
- return res;
-
- /* update head.ds_size */
- res = fops->seek(o->fh, offsetof(struct tee_svc_storage_head,
- ds_size), TEE_DATA_SEEK_SET, NULL);
- if (res != TEE_SUCCESS)
- return res;
-
- res = fops->write(o->fh, &ds_size, sizeof(uint32_t));
- if (res != TEE_SUCCESS)
- return res;
-
- /* restore original offset */
- res = fops->seek(o->fh, old_off, TEE_DATA_SEEK_SET, NULL);
- return res;
+ return o->pobj->fops->write(o->fh, pos, &ds_size, sizeof(uint32_t));
}
-static TEE_Result tee_svc_storage_init_file(struct tee_ta_session *sess,
- struct tee_obj *o,
+static TEE_Result tee_svc_storage_init_file(struct tee_obj *o,
struct tee_obj *attr_o, void *data,
uint32_t len)
{
TEE_Result res = TEE_SUCCESS;
struct tee_svc_storage_head head;
- char *tmpfile = NULL;
- const struct tee_file_operations *fops;
+ const struct tee_file_operations *fops = o->pobj->fops;
void *attr = NULL;
size_t attr_size = 0;
- if (o == NULL || o->pobj == NULL)
- return TEE_ERROR_BAD_PARAMETERS;
-
- fops = o->pobj->fops;
-
- /* create temporary persistent object filename */
- tmpfile = tee_svc_storage_create_filename(sess,
- o->pobj->obj_id,
- o->pobj->obj_id_len,
- true);
-
- if (tmpfile == NULL) {
- res = TEE_ERROR_OUT_OF_MEMORY;
- goto exit;
- }
-
- mutex_lock(&ta_dir_mutex);
- res = fops->create(tmpfile, &o->fh);
- mutex_unlock(&ta_dir_mutex);
+ res = fops->create(o->pobj, &o->fh);
if (res != TEE_SUCCESS)
goto exit;
@@ -389,6 +305,8 @@ static TEE_Result tee_svc_storage_init_file(struct tee_ta_session *sess,
goto exit;
}
+ o->ds_pos = sizeof(struct tee_svc_storage_head) + attr_size;
+
/* write head */
head.magic = TEE_SVC_STORAGE_MAGIC;
head.head_size = sizeof(struct tee_svc_storage_head);
@@ -401,12 +319,13 @@ static TEE_Result tee_svc_storage_init_file(struct tee_ta_session *sess,
head.have_attrs = o->have_attrs;
/* write head */
- res = fops->write(o->fh, &head, sizeof(struct tee_svc_storage_head));
+ res = fops->write(o->fh, 0, &head, sizeof(struct tee_svc_storage_head));
if (res != TEE_SUCCESS)
goto exit;
/* write meta */
- res = fops->write(o->fh, attr, attr_size);
+ res = fops->write(o->fh, sizeof(struct tee_svc_storage_head),
+ attr, attr_size);
if (res != TEE_SUCCESS)
goto exit;
@@ -415,11 +334,10 @@ static TEE_Result tee_svc_storage_init_file(struct tee_ta_session *sess,
/* write data to fs if needed */
if (data && len)
- res = fops->write(o->fh, data, len);
+ res = fops->write(o->fh, o->ds_pos, data, len);
exit:
free(attr);
- free(tmpfile);
fops->close(&o->fh);
return res;
@@ -462,7 +380,7 @@ TEE_Result syscall_storage_obj_open(unsigned long storage_id, void *object_id,
goto err;
res = tee_pobj_get((void *)&sess->ctx->uuid, object_id,
- object_id_len, flags, fops, &po);
+ object_id_len, flags, false, fops, &po);
if (res != TEE_SUCCESS)
goto err;
@@ -479,7 +397,7 @@ TEE_Result syscall_storage_obj_open(unsigned long storage_id, void *object_id,
o->pobj = po;
tee_obj_add(utc, o);
- res = tee_svc_storage_read_head(sess, o);
+ res = tee_svc_storage_read_head(o);
if (res != TEE_SUCCESS) {
if (res == TEE_ERROR_CORRUPT_OBJECT) {
EMSG("Object corrupt");
@@ -496,11 +414,6 @@ TEE_Result syscall_storage_obj_open(unsigned long storage_id, void *object_id,
if (res != TEE_SUCCESS)
goto oclose;
- res = fops->seek(o->fh, sizeof(struct tee_svc_storage_head) + attr_size,
- TEE_DATA_SEEK_SET, NULL);
- if (res != TEE_SUCCESS)
- goto err;
-
goto exit;
oclose:
@@ -528,9 +441,7 @@ TEE_Result syscall_storage_obj_create(unsigned long storage_id, void *object_id,
struct tee_ta_session *sess;
struct tee_obj *o = NULL;
struct tee_obj *attr_o = NULL;
- char *file = NULL;
struct tee_pobj *po = NULL;
- char *tmpfile = NULL;
struct user_ta_ctx *utc;
const struct tee_file_operations *fops = file_ops(storage_id);
size_t attr_size;
@@ -555,7 +466,7 @@ TEE_Result syscall_storage_obj_create(unsigned long storage_id, void *object_id,
goto err;
res = tee_pobj_get((void *)&sess->ctx->uuid, object_id,
- object_id_len, flags, fops, &po);
+ object_id_len, flags, true, fops, &po);
if (res != TEE_SUCCESS)
goto err;
@@ -588,33 +499,17 @@ TEE_Result syscall_storage_obj_create(unsigned long storage_id, void *object_id,
goto err;
}
- res = tee_svc_storage_init_file(sess, o, attr_o, data, len);
+ res = tee_svc_storage_init_file(o, attr_o, data, len);
if (res != TEE_SUCCESS)
goto err;
- /* create persistent object filename */
- file = tee_svc_storage_create_filename(sess, object_id,
- object_id_len, false);
- if (file == NULL) {
- res = TEE_ERROR_OUT_OF_MEMORY;
- goto err;
- }
-
- /* create temporary persistent object filename */
- tmpfile = tee_svc_storage_create_filename(sess, object_id,
- object_id_len,
- true);
- if (tmpfile == NULL) {
- res = TEE_ERROR_OUT_OF_MEMORY;
- goto err;
- }
-
/* rename temporary persistent object filename */
- res = fops->rename(tmpfile, file, !!(flags & TEE_DATA_FLAG_OVERWRITE));
+ po->temporary = false;
+ res = fops->rename(po, NULL, !!(flags & TEE_DATA_FLAG_OVERWRITE));
if (res != TEE_SUCCESS)
goto rmfile;
- res = fops->open(file, &o->fh);
+ res = fops->open(po, &o->fh);
if (res != TEE_SUCCESS)
goto err;
@@ -628,35 +523,26 @@ TEE_Result syscall_storage_obj_create(unsigned long storage_id, void *object_id,
if (res != TEE_SUCCESS)
goto oclose;
- res = fops->seek(o->fh, sizeof(struct tee_svc_storage_head) + attr_size,
- TEE_DATA_SEEK_SET, NULL);
- if (res != TEE_SUCCESS)
- goto oclose;
-
- goto exit;
+ return TEE_SUCCESS;
oclose:
tee_obj_close(utc, o);
- goto exit;
+ return res;
rmfile:
- fops->remove(tmpfile);
+ fops->remove(po);
err:
if (res == TEE_ERROR_NO_DATA || res == TEE_ERROR_BAD_FORMAT)
res = TEE_ERROR_CORRUPT_OBJECT;
- if (res == TEE_ERROR_CORRUPT_OBJECT && file)
- fops->remove(file);
+ if (res == TEE_ERROR_CORRUPT_OBJECT && po)
+ fops->remove(po);
if (o)
fops->close(&o->fh);
if (po)
tee_pobj_release(po);
free(o);
-exit:
- free(file);
- free(tmpfile);
-
return res;
}
@@ -665,9 +551,7 @@ TEE_Result syscall_storage_obj_del(unsigned long obj)
TEE_Result res;
struct tee_ta_session *sess;
struct tee_obj *o;
- char *file;
struct user_ta_ctx *utc;
- const struct tee_file_operations *fops;
res = tee_ta_get_current_session(&sess);
if (res != TEE_SUCCESS)
@@ -684,16 +568,9 @@ TEE_Result syscall_storage_obj_del(unsigned long obj)
if (o->pobj == NULL || o->pobj->obj_id == NULL)
return TEE_ERROR_BAD_STATE;
- file = tee_svc_storage_create_filename(sess, o->pobj->obj_id,
- o->pobj->obj_id_len, false);
- if (file == NULL)
- return TEE_ERROR_OUT_OF_MEMORY;
-
- fops = o->pobj->fops;
+ res = o->pobj->fops->remove(o->pobj);
tee_obj_close(utc, o);
- res = fops->remove(file);
- free(file);
return res;
}
@@ -743,31 +620,16 @@ TEE_Result syscall_storage_obj_rename(unsigned long obj, void *object_id,
if (res != TEE_SUCCESS)
goto exit;
- /* get new ds name */
- new_file = tee_svc_storage_create_filename(sess, object_id,
- object_id_len, false);
- if (new_file == NULL) {
- res = TEE_ERROR_OUT_OF_MEMORY;
- goto exit;
- }
-
- old_file = tee_svc_storage_create_filename(sess, o->pobj->obj_id,
- o->pobj->obj_id_len, false);
- if (old_file == NULL) {
- res = TEE_ERROR_OUT_OF_MEMORY;
- goto exit;
- }
-
/* reserve dest name */
fops = o->pobj->fops;
res = tee_pobj_get((void *)&sess->ctx->uuid, object_id,
object_id_len, TEE_DATA_FLAG_ACCESS_WRITE_META,
- fops, &po);
+ false, fops, &po);
if (res != TEE_SUCCESS)
goto exit;
/* move */
- res = fops->rename(old_file, new_file, false /* no overwrite */);
+ res = fops->rename(o->pobj, po, false /* no overwrite */);
if (res == TEE_ERROR_GENERIC)
goto exit;
@@ -843,48 +705,39 @@ TEE_Result syscall_storage_reset_enum(unsigned long obj_enum)
if (res != TEE_SUCCESS)
return res;
- e->fops->closedir(e->dir);
- e->fops = NULL;
- e->dir = NULL;
+ if (e->fops) {
+ e->fops->closedir(e->dir);
+ e->fops = NULL;
+ e->dir = NULL;
+ }
+ assert(!e->dir);
return TEE_SUCCESS;
}
-static TEE_Result tee_svc_storage_set_enum(char *d_name,
+static TEE_Result tee_svc_storage_set_enum(struct tee_fs_dirent *d,
const struct tee_file_operations *fops,
struct tee_obj *o)
{
- TEE_Result res;
- uint32_t blen;
- uint32_t hslen;
-
o->info.handleFlags =
TEE_HANDLE_FLAG_PERSISTENT | TEE_HANDLE_FLAG_INITIALIZED;
o->info.objectUsage = TEE_USAGE_DEFAULT;
- hslen = strlen(d_name);
- blen = TEE_HS2B_BBUF_SIZE(hslen);
- o->pobj->obj_id = malloc(blen);
- if (!o->pobj->obj_id) {
- res = TEE_ERROR_OUT_OF_MEMORY;
- goto exit;
- }
- tee_hs2b((uint8_t *)d_name, o->pobj->obj_id, hslen, blen);
- o->pobj->obj_id_len = blen;
- o->pobj->fops = fops;
-
- res = TEE_SUCCESS;
+ o->pobj->obj_id = malloc(d->oidlen);
+ if (!o->pobj->obj_id)
+ return TEE_ERROR_OUT_OF_MEMORY;
-exit:
- return res;
+ memcpy(o->pobj->obj_id, d->oid, d->oidlen);
+ o->pobj->obj_id_len = d->oidlen;
+ o->pobj->fops = fops;
+ return TEE_SUCCESS;
}
TEE_Result syscall_storage_start_enum(unsigned long obj_enum,
unsigned long storage_id)
{
struct tee_storage_enum *e;
- char *dir;
TEE_Result res;
struct tee_ta_session *sess;
const struct tee_file_operations *fops = file_ops(storage_id);
@@ -902,17 +755,8 @@ TEE_Result syscall_storage_start_enum(unsigned long obj_enum,
return TEE_ERROR_ITEM_NOT_FOUND;
e->fops = fops;
- dir = tee_svc_storage_create_dirname(sess);
- if (dir == NULL) {
- res = TEE_ERROR_OUT_OF_MEMORY;
- goto exit;
- }
-
assert(!e->dir);
- res = fops->opendir(dir, &e->dir);
- free(dir);
-exit:
- return res;
+ return fops->opendir(&sess->ctx->uuid, &e->dir);
}
TEE_Result syscall_storage_next_enum(unsigned long obj_enum,
@@ -975,11 +819,12 @@ TEE_Result syscall_storage_next_enum(unsigned long obj_enum,
goto exit;
}
- res = tee_svc_storage_set_enum(d->d_name, e->fops, o);
+ o->pobj->uuid = sess->ctx->uuid;
+ res = tee_svc_storage_set_enum(d, e->fops, o);
if (res != TEE_SUCCESS)
goto exit;
- res = tee_svc_storage_read_head(sess, o);
+ res = tee_svc_storage_read_head(o);
if (res != TEE_SUCCESS)
goto exit;
@@ -1040,7 +885,8 @@ TEE_Result syscall_storage_obj_read(unsigned long obj, void *data, size_t len,
goto exit;
bytes = len;
- res = o->pobj->fops->read(o->fh, data, &bytes);
+ res = o->pobj->fops->read(o->fh, o->ds_pos + o->info.dataPosition,
+ data, &bytes);
if (res != TEE_SUCCESS) {
EMSG("Error code=%x\n", (uint32_t)res);
if (res == TEE_ERROR_CORRUPT_OBJECT) {
@@ -1092,7 +938,8 @@ TEE_Result syscall_storage_obj_write(unsigned long obj, void *data, size_t len)
if (res != TEE_SUCCESS)
goto exit;
- res = o->pobj->fops->write(o->fh, data, len);
+ res = o->pobj->fops->write(o->fh, o->ds_pos + o->info.dataPosition,
+ data, len);
if (res != TEE_SUCCESS)
goto exit;
@@ -1163,39 +1010,50 @@ TEE_Result syscall_storage_obj_seek(unsigned long obj, int32_t offset,
TEE_Result res;
struct tee_ta_session *sess;
struct tee_obj *o;
- int32_t off;
size_t attr_size;
+ tee_fs_off_t new_pos;
res = tee_ta_get_current_session(&sess);
if (res != TEE_SUCCESS)
- goto exit;
+ return res;
res = tee_obj_get(to_user_ta_ctx(sess->ctx),
tee_svc_uref_to_vaddr(obj), &o);
if (res != TEE_SUCCESS)
- goto exit;
+ return res;
- if (!(o->info.handleFlags & TEE_HANDLE_FLAG_PERSISTENT)) {
- res = TEE_ERROR_BAD_STATE;
- goto exit;
- }
+ if (!(o->info.handleFlags & TEE_HANDLE_FLAG_PERSISTENT))
+ return TEE_ERROR_BAD_STATE;
res = tee_obj_attr_to_binary(o, NULL, &attr_size);
if (res != TEE_SUCCESS)
- goto exit;
+ return res;
- off = offset;
- if (whence == TEE_DATA_SEEK_SET)
- off += sizeof(struct tee_svc_storage_head) + attr_size;
+ switch (whence) {
+ case TEE_DATA_SEEK_SET:
+ new_pos = offset;
+ break;
+ case TEE_DATA_SEEK_CUR:
+ new_pos = o->info.dataPosition + offset;
+ break;
+ case TEE_DATA_SEEK_END:
+ new_pos = o->info.dataSize + offset;
+ break;
+ default:
+ return TEE_ERROR_BAD_PARAMETERS;
+ }
- res = o->pobj->fops->seek(o->fh, off, whence, &off);
- if (res != TEE_SUCCESS)
- goto exit;
- o->info.dataPosition = off - (sizeof(struct tee_svc_storage_head) +
- attr_size);
+ if (new_pos < 0)
+ new_pos = 0;
-exit:
- return res;
+ if (new_pos > TEE_DATA_MAX_POSITION) {
+ EMSG("Position is beyond TEE_DATA_MAX_POSITION");
+ return TEE_ERROR_BAD_PARAMETERS;
+ }
+
+ o->info.dataPosition = new_pos;
+
+ return TEE_SUCCESS;
}
void tee_svc_storage_close_all_enum(struct user_ta_ctx *utc)