2 <:copyright-BRCM:2019:DUAL/GPL:standard
4 Copyright (c) 2019 Broadcom
7 This program is free software; you can redistribute it and/or modify
8 it under the terms of the GNU General Public License, version 2, as published by
9 the Free Software Foundation (the "GPL").
11 This program is distributed in the hope that it will be useful,
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 GNU General Public License for more details.
17 A copy of the GPL is available at http://www.broadcom.com/licenses/GPLv2.php, or by
18 writing to the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
19 Boston, MA 02111-1307, USA.
23 #if defined(SPD_opteed)
24 #include <arch_helpers.h>
26 #include <bl_common.h>
30 #include <runtime_svc.h>
34 static volatile uint32_t optee_smc_entry
= 0;
36 static uint32_t monitor_stack_pointer
[PLATFORM_MAX_CPUS_PER_CLUSTER
];
37 static uint32_t optee_params_register
[PLATFORM_MAX_CPUS_PER_CLUSTER
][8];
39 extern void save_atf_sysreg(void);
40 extern void restore_atf_sysreg(void);
42 __attribute__((naked
)) void opteed_jump(uint32_t jump
, uint32_t *monitor_stack
, uint32_t *params
)
44 /* Save all GP registers */
45 asm("push {r0-r12, r14}");
47 /* Find OPTEE's entry address and place to save ATF's monitor stack*/
48 asm volatile ("mov r10, %0" "\n\t"
51 : : "r" (params
), "r" (monitor_stack
), "r" (jump
));
53 /* Save ATF's monitor's stack in cache memory */
57 /* Load OPTEE's parameters */
58 asm("ldm r10, {r0-r7}");
60 /* Turn off MMU and Cache needed to initialize OPTEE */
61 asm("mrc p15, 0, r8, c1, c0, 0");
62 asm("bic r8, r8, #0x5"); // (SCTLR_M_BIT | SCTLR_C_BIT) = 0x5
63 asm("mcr p15, 0, r8, c1, c0, 0");
65 /* Save ATF's monitor's stack in non-cache memory */
70 asm("cps #0x13"); // switch to secure MODE_SVC mode (0x13)
73 /* Returned from OPTEE with OPTEE's smc entry point in r12. ** DO NOT corrupt r12 ** */
75 /* Load ATF's monitor stack from non-cached memory */
76 asm("ldr r9,=monitor_stack_pointer");
77 /* Point to the monitor stack pointer for this CPU */
78 asm("mrc p15, 0, r10, c0, c0, 5");
79 asm("and r10, r10, #0xff");
80 asm("lsl r10, r10, #2");
81 asm("add r9, r10, r9");
84 /* Restore ATF's system registers */
88 asm("mrc p15, 0, r8, c1, c0, 0");
89 asm("ldr r9,=0x5"); // SCTLR_M_BIT | SCTLR_C_BIT
90 asm("orr r8, r8, r9");
91 asm("mcr p15, 0, r8, c1, c0, 0");
94 /* Save optee's SMC entry in cached memory */
95 asm("ldr r8,=optee_smc_entry");
97 /* Save the OPTEE's return registers r0-r7 in cached memory */
98 asm("ldr r8,=optee_params_register");
99 asm("lsl r10, r10, #3");
100 asm("add r8, r10, r8");
101 asm("stm r8, {r0-r7}");
102 /* Restore all GP registers */
103 asm("pop {r0-r12, r14}");
107 /*******************************************************************************
108 * OPTEE Dispatcher setup. The OPTEED finds out the OPTEE entrypoint and type
109 * (aarch32/aarch64) if not already known and initialises the context for entry
110 * into OPTEE for its initialization.
111 ******************************************************************************/
112 int32_t opteed_setup(void)
114 entry_point_info_t
*optee_ep_info
;
115 uint32_t cpu_id
= plat_my_core_pos();
116 uint32_t *monitor_stack
= &monitor_stack_pointer
[cpu_id
];
117 uint32_t *optee_params
= &optee_params_register
[cpu_id
][0];
119 * Get information about the Secure Payload (BL32) image. Its
120 * absence is a critical failure. TODO: Add support to
121 * conditionally include the SPD service
124 optee_ep_info
= bl31_plat_get_next_image_ep_info(SECURE
);
125 if (!optee_ep_info
) {
126 WARN("No OPTEE provided by BL2 boot loader, Booting device"
127 " without OPTEE initialization. SMC`s destined for OPTEE"
128 " will return SMC_UNK\n");
133 * If there's no valid entry point for SP, we return a non-zero value
134 * signalling failure initializing the service. We bail out without
135 * registering any handlers
137 if (!optee_ep_info
->pc
)
140 opteed_jump(optee_ep_info
->pc
, monitor_stack
, optee_params
);
147 /*******************************************************************************
148 * This function is responsible for handling all SMCs in the Trusted OS/App
149 * range from the non-secure state as defined in the SMC Calling Convention
150 * Document. It is also responsible for communicating with the Secure
151 * payload to delegate work and return results back to the non-secure
152 * state. Lastly it will also return any information that OPTEE needs to do
153 * the work assigned to it.
154 ******************************************************************************/
155 uintptr_t opteed_smc_handler(uint32_t smc_fid
,
164 uint32_t cpu_id
= plat_my_core_pos();
165 uint32_t *monitor_stack
= &monitor_stack_pointer
[cpu_id
];
166 uint32_t *optee_params
= &optee_params_register
[cpu_id
][0];
171 /* Extract r0-r7 from saved context and pass to OPTEE */
172 optee_params
[0] = ((smc_ctx_t
*)handle
)->r0
; // smc_fid;
173 optee_params
[1] = ((smc_ctx_t
*)handle
)->r1
; // x1;
174 optee_params
[2] = ((smc_ctx_t
*)handle
)->r2
; // x2;
175 optee_params
[3] = ((smc_ctx_t
*)handle
)->r3
; // x3;
176 optee_params
[4] = ((smc_ctx_t
*)handle
)->r4
; // x4;
177 optee_params
[5] = ((smc_ctx_t
*)handle
)->r5
;
178 optee_params
[6] = ((smc_ctx_t
*)handle
)->r6
;
179 optee_params
[7] = ((smc_ctx_t
*)handle
)->r7
;
181 assert(optee_params
[0] == smc_fid
);
183 opteed_jump(optee_smc_entry
, monitor_stack
, optee_params
);
185 /* Return the response from OPTEE */
186 SMC_RET4(handle
, optee_params
[0], optee_params
[1], optee_params
[2], optee_params
[3]);
189 /* Define an OPTEED runtime service descriptor for fast SMC calls */
200 /* Define an OPTEED runtime service descriptor for yielding SMC calls */