#ifndef __TLK_H__
#define __TLK_H__
+/*
+ * Generate function IDs for the Trusted OS/Apps
+ */
+#define TLK_TOS_STD_FID(fid) ((fid) | 0x72000000 | (0 << 31))
+
+/*
+ * Trusted OS specific function IDs
+ */
+#define TLK_REGISTER_LOGBUF TLK_TOS_STD_FID(0x1)
+#define TLK_REGISTER_REQBUF TLK_TOS_STD_FID(0x2)
+
/*
* SMC function IDs that TLK uses to signal various forms of completions
* to the secure payload dispatcher.
*/
+#define TLK_REQUEST_DONE (0x32000001 | (1 << 31))
#define TLK_ENTRY_DONE (0x32000003 | (1 << 31))
#define TLK_FID_SHARED_MEMBUF (0x32000005 | (1 << 31))
void *handle,
uint64_t flags)
{
+ cpu_context_t *ns_cpu_context;
uint32_t ns;
/* Passing a NULL context is a critical programming error */
switch (smc_fid) {
+ /*
+ * This is a request from the non-secure context to:
+ *
+ * a. register shared memory with the SP for storing it's
+ * activity logs.
+ * b. register shared memory with the SP for passing args
+ * required for maintaining sessions with the Trusted
+ * Applications.
+ */
+ case TLK_REGISTER_LOGBUF:
+ case TLK_REGISTER_REQBUF:
+ if (!ns || !tlk_args_results_buf)
+ SMC_RET1(handle, SMC_UNK);
+
+ /*
+ * This is a fresh request from the non-secure client.
+ * The parameters are in x1 and x2. Figure out which
+ * registers need to be preserved, save the non-secure
+ * state and send the request to the secure payload.
+ */
+ assert(handle == cm_get_context(NON_SECURE));
+
+ /* Check if we are already preempted */
+ if (get_std_smc_active_flag(tlk_ctx.state))
+ SMC_RET1(handle, SMC_UNK);
+
+ cm_el1_sysregs_context_save(NON_SECURE);
+
+ /*
+ * Verify if there is a valid context to use.
+ */
+ assert(&tlk_ctx.cpu_ctx == cm_get_context(SECURE));
+
+ /*
+ * Mark the SP state as active.
+ */
+ set_std_smc_active_flag(tlk_ctx.state);
+
+ /* Save args for use by the SP on return */
+ store_tlk_args_results(smc_fid, x1, x2, x3);
+
+ /*
+ * We are done stashing the non-secure context. Ask the
+ * secure payload to do the work now.
+ */
+ cm_el1_sysregs_context_restore(SECURE);
+ cm_set_next_eret_context(SECURE);
+ SMC_RET0(&tlk_ctx.cpu_ctx);
+
+ /*
+ * This is a request from the SP to mark completion of
+ * a standard function ID.
+ */
+ case TLK_REQUEST_DONE:
+ if (ns || !tlk_args_results_buf)
+ SMC_RET1(handle, SMC_UNK);
+
+ /*
+ * Mark the SP state as inactive.
+ */
+ clr_std_smc_active_flag(tlk_ctx.state);
+
+ /* Get a reference to the non-secure context */
+ ns_cpu_context = cm_get_context(NON_SECURE);
+ assert(ns_cpu_context);
+
+ /*
+ * This is a request completion SMC and we must switch to
+ * the non-secure world to pass the result.
+ */
+ cm_el1_sysregs_context_save(SECURE);
+
+ /*
+ * We are done stashing the secure context. Switch to the
+ * non-secure context and return the result.
+ */
+ cm_el1_sysregs_context_restore(NON_SECURE);
+ cm_set_next_eret_context(NON_SECURE);
+ SMC_RET1(ns_cpu_context, tlk_args_results_buf->args[0]);
+
/*
* This function ID is used only by the SP to indicate it has
* finished initialising itself after a cold boot
*/
case TLK_ENTRY_DONE:
- if (ns)
+ if (ns || !tlk_args_results_buf)
SMC_RET1(handle, SMC_UNK);
/*