blob: 5179e8ead1a5b0645da3ab579ee45f0ec7447667 [file] [log] [blame]
Amit Blayfe23ee22015-01-09 19:09:51 +02001/* Copyright (c) 2011-2015, The Linux Foundation. All rights reserved.
Deepa Dinamani904f8f82012-12-05 16:35:01 -08002 *
Shashank Mittal162244e2011-08-08 19:01:25 -07003 * Redistribution and use in source and binary forms, with or without
4 * modification, are permitted provided that the following conditions are
5 * met:
Deepa Dinamani904f8f82012-12-05 16:35:01 -08006 * * Redistributions of source code must retain the above copyright
7 * notice, this list of conditions and the following disclaimer.
8 * * Redistributions in binary form must reproduce the above
9 * copyright notice, this list of conditions and the following
10 * disclaimer in the documentation and/or other materials provided
11 * with the distribution.
12 * * Neither the name of The Linux Foundation nor the names of its
13 * contributors may be used to endorse or promote products derived
14 * from this software without specific prior written permission.
Shashank Mittal162244e2011-08-08 19:01:25 -070015 *
16 * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
17 * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
18 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
19 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
20 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
21 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
22 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
23 * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
24 * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
25 * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
26 * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27 */
28
29#include <stdlib.h>
30#include <string.h>
31#include <err.h>
Channagoud Kadabi179df0b2013-12-12 14:53:31 -080032#include <asm.h>
33#include <bits.h>
Neeti Desai127b9e02012-03-20 16:11:23 -070034#include <arch/ops.h>
vijay kumar4f4405f2014-08-08 11:49:53 +053035#include <rand.h>
36#include <image_verify.h>
Aparna Mallavarapu664ea772015-02-24 18:44:33 +053037#include <dload_util.h>
38#include <platform/iomap.h>
Shashank Mittal162244e2011-08-08 19:01:25 -070039#include "scm.h"
40
41#pragma GCC optimize ("O0")
42
43/* From Linux Kernel asm/system.h */
44#define __asmeq(x, y) ".ifnc " x "," y " ; .err ; .endif\n\t"
45
46#ifndef offsetof
47# define offsetof(TYPE, MEMBER) ((size_t) &((TYPE *)0)->MEMBER)
48#endif
49
Channagoud Kadabi179df0b2013-12-12 14:53:31 -080050#define SCM_CLASS_REGISTER (0x2 << 8)
51#define SCM_MASK_IRQS BIT(5)
52#define SCM_ATOMIC(svc, cmd, n) ((((((svc) & 0x3f) << 10)|((cmd) & 0x3ff)) << 12) | \
53 SCM_CLASS_REGISTER | \
54 SCM_MASK_IRQS | \
55 ((n) & 0xf))
56
Channagoud Kadabidd85e7f2014-08-05 19:58:37 -070057/* SCM interface as per ARM spec present? */
58bool scm_arm_support;
Aparna Mallavarapu664ea772015-02-24 18:44:33 +053059static uint32_t scm_io_write(uint32_t address, uint32_t val);
Channagoud Kadabidd85e7f2014-08-05 19:58:37 -070060
Dinesh K Garg6bbbb702015-01-30 11:13:31 -080061bool is_scm_armv8_support()
62{
63 return scm_arm_support;
64}
65
Channagoud Kadabidd85e7f2014-08-05 19:58:37 -070066static void scm_arm_support_available(uint32_t svc_id, uint32_t cmd_id)
67{
68 uint32_t ret;
69 scmcall_arg scm_arg = {0};
Veera Sundaram Sankaran00181512014-12-09 11:23:39 -080070 scmcall_ret scm_ret = {0};
Channagoud Kadabidd85e7f2014-08-05 19:58:37 -070071 /* Make a call to check if SCM call available using new interface,
72 * if this returns 0 then scm implementation as per arm spec
73 * otherwise use the old interface for scm calls
74 */
75 scm_arg.x0 = MAKE_SIP_SCM_CMD(SCM_SVC_INFO, IS_CALL_AVAIL_CMD);
76 scm_arg.x1 = MAKE_SCM_ARGS(0x1);
77 scm_arg.x2 = MAKE_SIP_SCM_CMD(svc_id, cmd_id);
78
79 ret = scm_call2(&scm_arg, &scm_ret);
80
81 if (!ret)
82 scm_arm_support = true;
83}
84
85
86void scm_init()
87{
88 scm_arm_support_available(SCM_SVC_INFO, IS_CALL_AVAIL_CMD);
89}
Channagoud Kadabi179df0b2013-12-12 14:53:31 -080090
Shashank Mittal162244e2011-08-08 19:01:25 -070091/**
92 * alloc_scm_command() - Allocate an SCM command
93 * @cmd_size: size of the command buffer
94 * @resp_size: size of the response buffer
95 *
96 * Allocate an SCM command, including enough room for the command
97 * and response headers as well as the command and response buffers.
98 *
99 * Returns a valid &scm_command on success or %NULL if the allocation fails.
100 */
101static struct scm_command *alloc_scm_command(size_t cmd_size, size_t resp_size)
102{
103 struct scm_command *cmd;
104 size_t len = sizeof(*cmd) + sizeof(struct scm_response) + cmd_size +
Ajay Dudanib01e5062011-12-03 23:23:42 -0800105 resp_size;
Shashank Mittal162244e2011-08-08 19:01:25 -0700106
Deepa Dinamani904f8f82012-12-05 16:35:01 -0800107 cmd = memalign(CACHE_LINE, ROUNDUP(len, CACHE_LINE));
Ajay Dudanib01e5062011-12-03 23:23:42 -0800108 if (cmd) {
Pavel Nedev80ce36f2014-01-06 14:26:17 +0200109 memset(cmd, 0, len);
Shashank Mittal162244e2011-08-08 19:01:25 -0700110 cmd->len = len;
111 cmd->buf_offset = offsetof(struct scm_command, buf);
112 cmd->resp_hdr_offset = cmd->buf_offset + cmd_size;
113 }
114 return cmd;
115}
116
117/**
118 * free_scm_command() - Free an SCM command
119 * @cmd: command to free
120 *
121 * Free an SCM command.
122 */
123static inline void free_scm_command(struct scm_command *cmd)
124{
125 free(cmd);
126}
127
128/**
129 * scm_command_to_response() - Get a pointer to a scm_response
130 * @cmd: command
131 *
132 * Returns a pointer to a response for a command.
133 */
Ajay Dudanib01e5062011-12-03 23:23:42 -0800134static inline struct scm_response *scm_command_to_response(const struct
135 scm_command *cmd)
Shashank Mittal162244e2011-08-08 19:01:25 -0700136{
137 return (void *)cmd + cmd->resp_hdr_offset;
138}
139
140/**
141 * scm_get_command_buffer() - Get a pointer to a command buffer
142 * @cmd: command
143 *
144 * Returns a pointer to the command buffer of a command.
145 */
146static inline void *scm_get_command_buffer(const struct scm_command *cmd)
147{
148 return (void *)cmd->buf;
149}
150
151/**
152 * scm_get_response_buffer() - Get a pointer to a response buffer
153 * @rsp: response
154 *
155 * Returns a pointer to a response buffer of a response.
156 */
157static inline void *scm_get_response_buffer(const struct scm_response *rsp)
158{
159 return (void *)rsp + rsp->buf_offset;
160}
161
162static uint32_t smc(uint32_t cmd_addr)
163{
164 uint32_t context_id;
165 register uint32_t r0 __asm__("r0") = 1;
Ajay Dudanib01e5062011-12-03 23:23:42 -0800166 register uint32_t r1 __asm__("r1") = (uint32_t) & context_id;
Shashank Mittal162244e2011-08-08 19:01:25 -0700167 register uint32_t r2 __asm__("r2") = cmd_addr;
Ajay Dudanib01e5062011-12-03 23:23:42 -0800168 __asm__("1:smc #0 @ switch to secure world\n" "cmp r0, #1 \n" "beq 1b \n": "=r"(r0): "r"(r0), "r"(r1), "r"(r2):"r3", "cc");
Shashank Mittal162244e2011-08-08 19:01:25 -0700169 return r0;
170}
171
172/**
Channagoud Kadabi179df0b2013-12-12 14:53:31 -0800173* scm_call_automic: Make scm call with one or no argument
174* @svc: service id
175* @cmd: command id
176* @ arg1: argument
177*/
178
179static int scm_call_atomic(uint32_t svc, uint32_t cmd, uint32_t arg1)
180{
181 uint32_t context_id;
182 register uint32_t r0 __asm__("r0") = SCM_ATOMIC(svc, cmd, 1);
vijay kumar4f4405f2014-08-08 11:49:53 +0530183 register uint32_t r1 __asm__("r1") = (uint32_t)&context_id;
Channagoud Kadabi179df0b2013-12-12 14:53:31 -0800184 register uint32_t r2 __asm__("r2") = arg1;
185
186 __asm__ volatile(
187 __asmeq("%0", "r0")
188 __asmeq("%1", "r0")
189 __asmeq("%2", "r1")
190 __asmeq("%3", "r2")
191 "smc #0 @ switch to secure world\n"
192 : "=r" (r0)
193 : "r" (r0), "r" (r1), "r" (r2)
194 : "r3");
195 return r0;
196}
197
198/**
Aparna Mallavarapu68e233f2014-03-21 19:18:34 +0530199 * scm_call_atomic2() - Send an atomic SCM command with two arguments
200 * @svc_id: service identifier
201 * @cmd_id: command identifier
202 * @arg1: first argument
203 * @arg2: second argument
204 *
205 * This shall only be used with commands that are guaranteed to be
206 * uninterruptable, atomic and SMP safe.
207 */
208int scm_call_atomic2(uint32_t svc, uint32_t cmd, uint32_t arg1, uint32_t arg2)
209{
210 int context_id;
211 register uint32_t r0 __asm__("r0") = SCM_ATOMIC(svc, cmd, 2);
vijay kumar4f4405f2014-08-08 11:49:53 +0530212 register uint32_t r1 __asm__("r1") = (uint32_t)&context_id;
Aparna Mallavarapu68e233f2014-03-21 19:18:34 +0530213 register uint32_t r2 __asm__("r2") = arg1;
214 register uint32_t r3 __asm__("r3") = arg2;
215
216 __asm__ volatile(
217 __asmeq("%0", "r0")
218 __asmeq("%1", "r0")
219 __asmeq("%2", "r1")
220 __asmeq("%3", "r2")
221 __asmeq("%4", "r3")
222 "smc #0 @ switch to secure world\n"
223 : "=r" (r0)
224 : "r" (r0), "r" (r1), "r" (r2), "r" (r3));
225 return r0;
226}
227
228/**
Shashank Mittal162244e2011-08-08 19:01:25 -0700229 * scm_call() - Send an SCM command
230 * @svc_id: service identifier
231 * @cmd_id: command identifier
232 * @cmd_buf: command buffer
233 * @cmd_len: length of the command buffer
234 * @resp_buf: response buffer
235 * @resp_len: length of the response buffer
236 *
237 * Sends a command to the SCM and waits for the command to finish processing.
238 */
Ajay Dudanib01e5062011-12-03 23:23:42 -0800239int
240scm_call(uint32_t svc_id, uint32_t cmd_id, const void *cmd_buf,
241 size_t cmd_len, void *resp_buf, size_t resp_len)
Shashank Mittal162244e2011-08-08 19:01:25 -0700242{
243 int ret;
244 struct scm_command *cmd;
245 struct scm_response *rsp;
Neeti Desai127b9e02012-03-20 16:11:23 -0700246 uint8_t *resp_ptr;
Shashank Mittal162244e2011-08-08 19:01:25 -0700247
248 cmd = alloc_scm_command(cmd_len, resp_len);
249 if (!cmd)
250 return ERR_NO_MEMORY;
251
252 cmd->id = (svc_id << 10) | cmd_id;
253 if (cmd_buf)
254 memcpy(scm_get_command_buffer(cmd), cmd_buf, cmd_len);
255
Neeti Desai127b9e02012-03-20 16:11:23 -0700256 /* Flush command to main memory for TZ */
257 arch_clean_invalidate_cache_range((addr_t) cmd, cmd->len);
258
Ajay Dudanib01e5062011-12-03 23:23:42 -0800259 ret = smc((uint32_t) cmd);
Shashank Mittal162244e2011-08-08 19:01:25 -0700260 if (ret)
261 goto out;
262
Ajay Dudanib01e5062011-12-03 23:23:42 -0800263 if (resp_len) {
Shashank Mittal162244e2011-08-08 19:01:25 -0700264 rsp = scm_command_to_response(cmd);
265
Neeti Desai127b9e02012-03-20 16:11:23 -0700266 do
267 {
268 /* Need to invalidate before each check since TZ will update
269 * the response complete flag in main memory.
270 */
sundarajan srinivasan4dfd4f72013-02-27 14:13:09 -0800271 arch_invalidate_cache_range((addr_t) rsp, sizeof(*rsp));
Neeti Desai127b9e02012-03-20 16:11:23 -0700272 } while (!rsp->is_complete);
273
274
275 resp_ptr = scm_get_response_buffer(rsp);
276
277 /* Invalidate any cached response data */
sundarajan srinivasan4dfd4f72013-02-27 14:13:09 -0800278 arch_invalidate_cache_range((addr_t) resp_ptr, resp_len);
Shashank Mittal162244e2011-08-08 19:01:25 -0700279
280 if (resp_buf)
Neeti Desai127b9e02012-03-20 16:11:23 -0700281 memcpy(resp_buf, resp_ptr, resp_len);
Shashank Mittal162244e2011-08-08 19:01:25 -0700282 }
Ajay Dudanib01e5062011-12-03 23:23:42 -0800283 out:
Shashank Mittal162244e2011-08-08 19:01:25 -0700284 free_scm_command(cmd);
285 return ret;
286}
287
Siddhartha Agrawaleb094c52013-01-28 12:11:43 -0800288int restore_secure_cfg(uint32_t id)
289{
Channagoud Kadabiacaa75e2014-06-09 16:29:29 -0700290 int ret = 0;
Siddhartha Agrawaleb094c52013-01-28 12:11:43 -0800291 tz_secure_cfg secure_cfg;
292
Siddhartha Agrawald4648892013-02-17 18:16:18 -0800293 secure_cfg.id = id;
Siddhartha Agrawaleb094c52013-01-28 12:11:43 -0800294 secure_cfg.spare = 0;
Channagoud Kadabidd85e7f2014-08-05 19:58:37 -0700295 scmcall_arg scm_arg = {0};
Siddhartha Agrawaleb094c52013-01-28 12:11:43 -0800296
Channagoud Kadabidd85e7f2014-08-05 19:58:37 -0700297 if(!scm_arm_support)
298 {
299 ret = scm_call(SVC_MEMORY_PROTECTION, IOMMU_SECURE_CFG, &secure_cfg, sizeof(secure_cfg),
300 NULL, 0);
301 }
302 else
303 {
304 scm_arg.x0 = MAKE_SIP_SCM_CMD(SVC_MEMORY_PROTECTION, IOMMU_SECURE_CFG);
305 scm_arg.x1 = MAKE_SCM_ARGS(0x2);
306 scm_arg.x2 = id;
307 scm_arg.x3 = 0x0; /* Spare unused */
Siddhartha Agrawaleb094c52013-01-28 12:11:43 -0800308
Channagoud Kadabidd85e7f2014-08-05 19:58:37 -0700309 ret = scm_call2(&scm_arg, NULL);
310 }
311
312 if (ret)
313 {
Siddhartha Agrawaleb094c52013-01-28 12:11:43 -0800314 dprintf(CRITICAL, "Secure Config failed\n");
315 ret = 1;
Channagoud Kadabiacaa75e2014-06-09 16:29:29 -0700316 }
Siddhartha Agrawaleb094c52013-01-28 12:11:43 -0800317
318 return ret;
Siddhartha Agrawaleb094c52013-01-28 12:11:43 -0800319}
320
Neeti Desai127b9e02012-03-20 16:11:23 -0700321/* SCM Encrypt Command */
322int encrypt_scm(uint32_t ** img_ptr, uint32_t * img_len_ptr)
Shashank Mittal162244e2011-08-08 19:01:25 -0700323{
Neeti Desai127b9e02012-03-20 16:11:23 -0700324 int ret;
325 img_req cmd;
vijay kumare95092d2014-10-20 19:24:49 +0530326 scmcall_arg scm_arg = {0};
Shashank Mittal162244e2011-08-08 19:01:25 -0700327
Channagoud Kadabidd85e7f2014-08-05 19:58:37 -0700328
Neeti Desai127b9e02012-03-20 16:11:23 -0700329 cmd.img_ptr = (uint32*) img_ptr;
330 cmd.img_len_ptr = img_len_ptr;
Shashank Mittal162244e2011-08-08 19:01:25 -0700331
Neeti Desai127b9e02012-03-20 16:11:23 -0700332 /* Image data is operated upon by TZ, which accesses only the main memory.
333 * It must be flushed/invalidated before and after TZ call.
334 */
335 arch_clean_invalidate_cache_range((addr_t) *img_ptr, *img_len_ptr);
Shashank Mittal162244e2011-08-08 19:01:25 -0700336
vijay kumare95092d2014-10-20 19:24:49 +0530337 if (!scm_arm_support)
338 {
339 ret = scm_call(SCM_SVC_SSD, SSD_ENCRYPT_ID, &cmd, sizeof(cmd), NULL, 0);
340 }
341 else
342 {
343 scm_arg.x0 = MAKE_SIP_SCM_CMD(SCM_SVC_SSD,SSD_ENCRYPT_ID);
vijay kumar83b50d62015-01-09 19:09:59 +0530344 scm_arg.x1 = MAKE_SCM_ARGS(0x2,SMC_PARAM_TYPE_BUFFER_READWRITE,SMC_PARAM_TYPE_BUFFER_READWRITE);
Veera Sundaram Sankaran00181512014-12-09 11:23:39 -0800345 scm_arg.x2 = (uint32_t) cmd.img_ptr;
346 scm_arg.x3 = (uint32_t) cmd.img_len_ptr;
vijay kumare95092d2014-10-20 19:24:49 +0530347
348 ret = scm_call2(&scm_arg, NULL);
349 }
Shashank Mittal162244e2011-08-08 19:01:25 -0700350
Neeti Desai127b9e02012-03-20 16:11:23 -0700351 /* Values at img_ptr and img_len_ptr are updated by TZ. Must be invalidated
352 * before we use them.
Amol Jadi55e58da2011-11-17 14:03:34 -0800353 */
354 arch_clean_invalidate_cache_range((addr_t) img_ptr, sizeof(img_ptr));
Neeti Desai127b9e02012-03-20 16:11:23 -0700355 arch_clean_invalidate_cache_range((addr_t) img_len_ptr, sizeof(img_len_ptr));
Amol Jadi55e58da2011-11-17 14:03:34 -0800356
Neeti Desai127b9e02012-03-20 16:11:23 -0700357 /* Invalidate the updated image data */
358 arch_clean_invalidate_cache_range((addr_t) *img_ptr, *img_len_ptr);
Amol Jadi55e58da2011-11-17 14:03:34 -0800359
Shashank Mittal162244e2011-08-08 19:01:25 -0700360 return ret;
361}
362
Neeti Desai127b9e02012-03-20 16:11:23 -0700363/* SCM Decrypt Command */
364int decrypt_scm(uint32_t ** img_ptr, uint32_t * img_len_ptr)
365{
366 int ret;
367 img_req cmd;
368
Channagoud Kadabidd85e7f2014-08-05 19:58:37 -0700369 if (scm_arm_support)
370 {
371 dprintf(INFO, "%s:SCM call is not supported\n",__func__);
372 return -1;
373 }
374
Neeti Desai127b9e02012-03-20 16:11:23 -0700375 cmd.img_ptr = (uint32*) img_ptr;
376 cmd.img_len_ptr = img_len_ptr;
377
378 /* Image data is operated upon by TZ, which accesses only the main memory.
379 * It must be flushed/invalidated before and after TZ call.
380 */
381 arch_clean_invalidate_cache_range((addr_t) *img_ptr, *img_len_ptr);
382
383 ret = scm_call(SCM_SVC_SSD, SSD_DECRYPT_ID, &cmd, sizeof(cmd), NULL, 0);
384
385 /* Values at img_ptr and img_len_ptr are updated by TZ. Must be invalidated
386 * before we use them.
387 */
388 arch_clean_invalidate_cache_range((addr_t) img_ptr, sizeof(img_ptr));
389 arch_clean_invalidate_cache_range((addr_t) img_len_ptr, sizeof(img_len_ptr));
390
391 /* Invalidate the updated image data */
392 arch_clean_invalidate_cache_range((addr_t) *img_ptr, *img_len_ptr);
393
394 return ret;
395}
396
397
sundarajan srinivasan4dfd4f72013-02-27 14:13:09 -0800398static int ssd_image_is_encrypted(uint32_t ** img_ptr, uint32_t * img_len_ptr, uint32 * ctx_id)
399{
sundarajan srinivasan6173b872013-03-13 17:36:48 -0700400 int ret = 0;
sundarajan srinivasan4dfd4f72013-02-27 14:13:09 -0800401 ssd_parse_md_req parse_req;
402 ssd_parse_md_rsp parse_rsp;
sundarajan srinivasan6173b872013-03-13 17:36:48 -0700403 int prev_len = 0;
vijay kumare95092d2014-10-20 19:24:49 +0530404 scmcall_arg scm_arg = {0};
405 scmcall_ret scm_ret = {0};
sundarajan srinivasan6173b872013-03-13 17:36:48 -0700406 /* Populate meta-data ptr. Here md_len is the meta-data length.
407 * The Code below follows a growing length approach. First send
408 * min(img_len_ptr,SSD_HEADER_MIN_SIZE) say 128 bytes for example.
409 * If parse_rsp.status = PARSING_INCOMPLETE we send md_len = 256.
410 * If subsequent status = PARSING_INCOMPLETE we send md_len = 512,
411 * 1024bytes and so on until we get an valid response(rsp.status) from TZ*/
412
sundarajan srinivasan4dfd4f72013-02-27 14:13:09 -0800413 parse_req.md = (uint32*)*img_ptr;
sundarajan srinivasan6173b872013-03-13 17:36:48 -0700414 parse_req.md_len = ((*img_len_ptr) >= SSD_HEADER_MIN_SIZE) ? SSD_HEADER_MIN_SIZE : (*img_len_ptr);
sundarajan srinivasan4dfd4f72013-02-27 14:13:09 -0800415
sundarajan srinivasan6173b872013-03-13 17:36:48 -0700416 arch_clean_invalidate_cache_range((addr_t) *img_ptr, parse_req.md_len);
sundarajan srinivasan4dfd4f72013-02-27 14:13:09 -0800417
sundarajan srinivasan6173b872013-03-13 17:36:48 -0700418 do
419 {
vijay kumare95092d2014-10-20 19:24:49 +0530420 if (!scm_arm_support)
421 {
422 ret = scm_call(SCM_SVC_SSD,
423 SSD_PARSE_MD_ID,
424 &parse_req,
425 sizeof(parse_req),
426 &parse_rsp,
427 sizeof(parse_rsp));
428 }
429 else
430 {
431 scm_arg.x0 = MAKE_SIP_SCM_CMD(SCM_SVC_SSD, SSD_PARSE_MD_ID);
432 scm_arg.x1 = MAKE_SCM_ARGS(0x2,SMC_PARAM_TYPE_VALUE,SMC_PARAM_TYPE_BUFFER_READWRITE);
433 scm_arg.x2 = parse_req.md_len;
Veera Sundaram Sankaran00181512014-12-09 11:23:39 -0800434 scm_arg.x3 = (uint32_t) parse_req.md;
Aparna Mallavarapud83990a2014-12-24 12:54:35 +0530435 scm_arg.atomic = true;
sundarajan srinivasan6173b872013-03-13 17:36:48 -0700436
vijay kumare95092d2014-10-20 19:24:49 +0530437 ret = scm_call2(&scm_arg, &scm_ret);
438 parse_rsp.status = scm_ret.x1;
439 }
sundarajan srinivasan6173b872013-03-13 17:36:48 -0700440 if(!ret && (parse_rsp.status == SSD_PMD_PARSING_INCOMPLETE))
441 {
442 prev_len = parse_req.md_len;
443
444 parse_req.md_len *= MULTIPLICATION_FACTOR;
445
Venkatesh Yadav Abbarapuaf7bfe02013-11-11 16:56:04 +0530446 arch_clean_invalidate_cache_range((addr_t) (*img_ptr + prev_len),
sundarajan srinivasan6173b872013-03-13 17:36:48 -0700447 (parse_req.md_len - prev_len) );
448
449 continue;
450 }
451 else
452 break;
453
454 } while(true);
sundarajan srinivasan4dfd4f72013-02-27 14:13:09 -0800455
456 if(!ret)
457 {
458 if(parse_rsp.status == SSD_PMD_ENCRYPTED)
459 {
460 *ctx_id = parse_rsp.md_ctx_id;
Sundarajan Srinivasaneb6d2202013-06-04 14:24:10 -0700461 *img_len_ptr = *img_len_ptr - ((uint8_t*)parse_rsp.md_end_ptr - (uint8_t*)*img_ptr);
sundarajan srinivasan4dfd4f72013-02-27 14:13:09 -0800462 *img_ptr = (uint32_t*)parse_rsp.md_end_ptr;
sundarajan srinivasan4dfd4f72013-02-27 14:13:09 -0800463 }
Sundarajan Srinivasaneb6d2202013-06-04 14:24:10 -0700464
465 ret = parse_rsp.status;
sundarajan srinivasan4dfd4f72013-02-27 14:13:09 -0800466 }
sundarajan srinivasan6173b872013-03-13 17:36:48 -0700467 else
468 {
469 dprintf(CRITICAL,"ssd_image_is_encrypted call failed");
470
471 ASSERT(ret == 0);
472 }
sundarajan srinivasan4dfd4f72013-02-27 14:13:09 -0800473
474 return ret;
475}
476
477int decrypt_scm_v2(uint32_t ** img_ptr, uint32_t * img_len_ptr)
478{
479 int ret = 0;
480 uint32 ctx_id = 0;
481 ssd_decrypt_img_frag_req decrypt_req;
482 ssd_decrypt_img_frag_rsp decrypt_rsp;
vijay kumare95092d2014-10-20 19:24:49 +0530483 scmcall_arg scm_arg = {0};
484 scmcall_ret scm_ret = {0};
sundarajan srinivasan4dfd4f72013-02-27 14:13:09 -0800485
Channagoud Kadabidd85e7f2014-08-05 19:58:37 -0700486
Sundarajan Srinivasaneb6d2202013-06-04 14:24:10 -0700487 ret = ssd_image_is_encrypted(img_ptr,img_len_ptr,&ctx_id);
488 switch(ret)
sundarajan srinivasan6173b872013-03-13 17:36:48 -0700489 {
Sundarajan Srinivasaneb6d2202013-06-04 14:24:10 -0700490 case SSD_PMD_ENCRYPTED:
491 /* Image data is operated upon by TZ, which accesses only the main memory.
492 * It must be flushed/invalidated before and after TZ call.
493 */
sundarajan srinivasan4dfd4f72013-02-27 14:13:09 -0800494
Sundarajan Srinivasaneb6d2202013-06-04 14:24:10 -0700495 arch_clean_invalidate_cache_range((addr_t) *img_ptr, *img_len_ptr);
sundarajan srinivasan4dfd4f72013-02-27 14:13:09 -0800496
Sundarajan Srinivasaneb6d2202013-06-04 14:24:10 -0700497 /*decrypt the image here*/
sundarajan srinivasan4dfd4f72013-02-27 14:13:09 -0800498
Sundarajan Srinivasaneb6d2202013-06-04 14:24:10 -0700499 decrypt_req.md_ctx_id = ctx_id;
500 decrypt_req.last_frag = 1;
501 decrypt_req.frag_len = *img_len_ptr;
502 decrypt_req.frag = *img_ptr;
sundarajan srinivasan4dfd4f72013-02-27 14:13:09 -0800503
vijay kumare95092d2014-10-20 19:24:49 +0530504 if (!scm_arm_support)
505 {
506 ret = scm_call(SCM_SVC_SSD,
507 SSD_DECRYPT_IMG_FRAG_ID,
508 &decrypt_req,
509 sizeof(decrypt_req),
510 &decrypt_rsp,
511 sizeof(decrypt_rsp));
512 }
513 else
514 {
515 scm_arg.x0 = MAKE_SIP_SCM_CMD(SCM_SVC_SSD, SSD_DECRYPT_IMG_FRAG_ID);
516 scm_arg.x1 = MAKE_SCM_ARGS(0x4,SMC_PARAM_TYPE_VALUE,SMC_PARAM_TYPE_VALUE,SMC_PARAM_TYPE_VALUE,SMC_PARAM_TYPE_BUFFER_READWRITE);
517 scm_arg.x2 = decrypt_req.md_ctx_id;
518 scm_arg.x3 = decrypt_req.last_frag;
519 scm_arg.x4 = decrypt_req.frag_len;
Veera Sundaram Sankaran00181512014-12-09 11:23:39 -0800520 scm_arg.x5[0] = (uint32_t) decrypt_req.frag;
sundarajan srinivasan4dfd4f72013-02-27 14:13:09 -0800521
vijay kumare95092d2014-10-20 19:24:49 +0530522 ret = scm_call2(&scm_arg, &scm_ret);
523 decrypt_rsp.status = scm_ret.x1;
524 }
Sundarajan Srinivasaneb6d2202013-06-04 14:24:10 -0700525 if(!ret){
526 ret = decrypt_rsp.status;
527 }
sundarajan srinivasan6173b872013-03-13 17:36:48 -0700528
Sundarajan Srinivasaneb6d2202013-06-04 14:24:10 -0700529 /* Values at img_ptr and img_len_ptr are updated by TZ. Must be invalidated
530 * before we use them.
531 */
532 arch_invalidate_cache_range((addr_t) img_ptr, sizeof(img_ptr));
533 arch_invalidate_cache_range((addr_t) img_len_ptr, sizeof(img_len_ptr));
sundarajan srinivasan4dfd4f72013-02-27 14:13:09 -0800534
Sundarajan Srinivasaneb6d2202013-06-04 14:24:10 -0700535 /* Invalidate the updated image data */
536 arch_invalidate_cache_range((addr_t) *img_ptr, *img_len_ptr);
sundarajan srinivasan6173b872013-03-13 17:36:48 -0700537
Sundarajan Srinivasaneb6d2202013-06-04 14:24:10 -0700538 break;
539
540 case SSD_PMD_NOT_ENCRYPTED:
541 case SSD_PMD_NO_MD_FOUND:
542 ret = 0;
543 break;
544
545 case SSD_PMD_BUSY:
546 case SSD_PMD_BAD_MD_PTR_OR_LEN:
547 case SSD_PMD_PARSING_INCOMPLETE:
548 case SSD_PMD_PARSING_FAILED:
549 case SSD_PMD_SETUP_CIPHER_FAILED:
550 dprintf(CRITICAL,"decrypt_scm_v2: failed status %d\n",ret);
551 break;
552
553 default:
554 dprintf(CRITICAL,"decrypt_scm_v2: case default: failed status %d\n",ret);
555 break;
sundarajan srinivasan6173b872013-03-13 17:36:48 -0700556 }
sundarajan srinivasan4dfd4f72013-02-27 14:13:09 -0800557 return ret;
558}
559
560int scm_svc_version(uint32 * major, uint32 * minor)
561{
562 feature_version_req feature_req;
563 feature_version_rsp feature_rsp;
564 int ret = 0;
Channagoud Kadabidd85e7f2014-08-05 19:58:37 -0700565 scmcall_arg scm_arg = {0};
566 scmcall_ret scm_ret = {0};
sundarajan srinivasan4dfd4f72013-02-27 14:13:09 -0800567
568 feature_req.feature_id = TZBSP_FVER_SSD;
569
Channagoud Kadabidd85e7f2014-08-05 19:58:37 -0700570 if (!scm_arm_support)
571 {
572 ret = scm_call(TZBSP_SVC_INFO,
573 TZ_INFO_GET_FEATURE_ID,
574 &feature_req,
575 sizeof(feature_req),
576 &feature_rsp,
577 sizeof(feature_rsp));
578 }
579 else
580 {
581 scm_arg.x0 = MAKE_SIP_SCM_CMD(TZBSP_SVC_INFO, TZ_INFO_GET_FEATURE_ID);
vijay kumare95092d2014-10-20 19:24:49 +0530582 scm_arg.x1 = MAKE_SCM_ARGS(0x1,SMC_PARAM_TYPE_VALUE);
Channagoud Kadabidd85e7f2014-08-05 19:58:37 -0700583 scm_arg.x2 = feature_req.feature_id;
584
585 ret = scm_call2(&scm_arg, &scm_ret);
586 feature_rsp.version = scm_ret.x1;
587 }
588
sundarajan srinivasan4dfd4f72013-02-27 14:13:09 -0800589 if(!ret)
590 *major = TZBSP_GET_FEATURE_VERSION(feature_rsp.version);
591
592 return ret;
593}
594
Amit Blaybdfabc62015-01-29 22:04:13 +0200595int scm_svc_get_secure_state(uint32_t *state_low, uint32_t *state_high)
596{
597 get_secure_state_req req;
598 get_secure_state_rsp rsp;
599
600 int ret = 0;
601
602 scmcall_arg scm_arg = {0};
603 scmcall_ret scm_ret = {0};
604
605 if (!scm_arm_support)
606 {
607 req.status_ptr = (uint32_t*)&rsp;
608 req.status_len = sizeof(rsp);
609
610 ret = scm_call(TZBSP_SVC_INFO,
611 TZ_INFO_GET_SECURE_STATE,
612 &req,
613 sizeof(req),
614 NULL,
615 0);
616 }
617 else
618 {
619 scm_arg.x0 = MAKE_SIP_SCM_CMD(TZBSP_SVC_INFO, TZ_INFO_GET_SECURE_STATE);
620 scm_arg.x1 = MAKE_SCM_ARGS(0x0);
621
622 ret = scm_call2(&scm_arg, &scm_ret);
623
624 rsp.status_low = scm_ret.x1;
625 rsp.status_high = scm_ret.x2;
626 }
627
628 if(!ret)
629 {
630 *state_low = rsp.status_low;
631 *state_high = rsp.status_high;
632 }
633
634 return ret;
635}
636
sundarajan srinivasan4dfd4f72013-02-27 14:13:09 -0800637int scm_protect_keystore(uint32_t * img_ptr, uint32_t img_len)
638{
639 int ret=0;
640 ssd_protect_keystore_req protect_req;
641 ssd_protect_keystore_rsp protect_rsp;
vijay kumare95092d2014-10-20 19:24:49 +0530642 scmcall_arg scm_arg = {0};
643 scmcall_ret scm_ret = {0};
Channagoud Kadabidd85e7f2014-08-05 19:58:37 -0700644
sundarajan srinivasan4dfd4f72013-02-27 14:13:09 -0800645 protect_req.keystore_ptr = img_ptr;
646 protect_req.keystore_len = img_len;
647
648 arch_clean_invalidate_cache_range((addr_t) img_ptr, img_len);
649
vijay kumare95092d2014-10-20 19:24:49 +0530650 if (!scm_arm_support)
651 {
652 ret = scm_call(SCM_SVC_SSD,
653 SSD_PROTECT_KEYSTORE_ID,
654 &protect_req,
655 sizeof(protect_req),
656 &protect_rsp,
657 sizeof(protect_rsp));
658 }
659 else
660 {
661 scm_arg.x0 = MAKE_SIP_SCM_CMD(SCM_SVC_SSD, SSD_PROTECT_KEYSTORE_ID);
662 scm_arg.x1 = MAKE_SCM_ARGS(0x2,SMC_PARAM_TYPE_BUFFER_READWRITE,SMC_PARAM_TYPE_VALUE);
Veera Sundaram Sankaran00181512014-12-09 11:23:39 -0800663 scm_arg.x2 = (uint32_t) protect_req.keystore_ptr;
vijay kumare95092d2014-10-20 19:24:49 +0530664 scm_arg.x3 = protect_req.keystore_len;
665
666 ret = scm_call2(&scm_arg, &scm_ret);
667 protect_rsp.status = scm_ret.x1;
668 }
sundarajan srinivasan4dfd4f72013-02-27 14:13:09 -0800669 if(!ret)
670 {
671 if(protect_rsp.status == TZBSP_SSD_PKS_SUCCESS)
672 dprintf(INFO,"Successfully loaded the keystore ");
673 else
674 {
675 dprintf(INFO,"Loading keystore failed status %d ",protect_rsp.status);
676 ret = protect_rsp.status;
677 }
678 }
679 else
680 dprintf(INFO,"scm_call failed ");
681
682 return ret;
683}
684
Shashank Mittal162244e2011-08-08 19:01:25 -0700685void set_tamper_fuse_cmd()
686{
687 uint32_t svc_id;
688 uint32_t cmd_id;
689 void *cmd_buf;
690 size_t cmd_len;
691 void *resp_buf = NULL;
692 size_t resp_len = 0;
vijay kumare95092d2014-10-20 19:24:49 +0530693 scmcall_arg scm_arg = {0};
Shashank Mittal162244e2011-08-08 19:01:25 -0700694
695 uint32_t fuse_id = HLOS_IMG_TAMPER_FUSE;
696 cmd_buf = (void *)&fuse_id;
697 cmd_len = sizeof(fuse_id);
698
vijay kumare95092d2014-10-20 19:24:49 +0530699 if (!scm_arm_support)
Channagoud Kadabidd85e7f2014-08-05 19:58:37 -0700700 {
vijay kumare95092d2014-10-20 19:24:49 +0530701 /*no response */
702 resp_buf = NULL;
703 resp_len = 0;
704
705 svc_id = SCM_SVC_FUSE;
706 cmd_id = SCM_BLOW_SW_FUSE_ID;
707
708 scm_call(svc_id, cmd_id, cmd_buf, cmd_len, resp_buf, resp_len);
709 }
710 else
711 {
712 scm_arg.x0 = MAKE_SIP_SCM_CMD(SCM_SVC_FUSE, SCM_BLOW_SW_FUSE_ID);
713 scm_arg.x1 = MAKE_SCM_ARGS(0x2,SMC_PARAM_TYPE_BUFFER_READWRITE,SMC_PARAM_TYPE_VALUE);
Veera Sundaram Sankaran00181512014-12-09 11:23:39 -0800714 scm_arg.x2 = (uint32_t) cmd_buf;
vijay kumare95092d2014-10-20 19:24:49 +0530715 scm_arg.x3 = cmd_len;
716
717 scm_call2(&scm_arg, NULL);
718
Channagoud Kadabidd85e7f2014-08-05 19:58:37 -0700719 }
720
Shashank Mittal162244e2011-08-08 19:01:25 -0700721}
722
723uint8_t get_tamper_fuse_cmd()
724{
725 uint32_t svc_id;
726 uint32_t cmd_id;
727 void *cmd_buf;
728 size_t cmd_len;
729 size_t resp_len = 0;
730 uint8_t resp_buf;
731
732 uint32_t fuse_id = HLOS_IMG_TAMPER_FUSE;
vijay kumare95092d2014-10-20 19:24:49 +0530733 scmcall_arg scm_arg = {0};
734 scmcall_ret scm_ret = {0};
Channagoud Kadabidd85e7f2014-08-05 19:58:37 -0700735
Shashank Mittal162244e2011-08-08 19:01:25 -0700736 cmd_buf = (void *)&fuse_id;
737 cmd_len = sizeof(fuse_id);
738
vijay kumare95092d2014-10-20 19:24:49 +0530739 if (!scm_arm_support)
740 {
741 /*response */
742 resp_len = sizeof(resp_buf);
Shashank Mittal162244e2011-08-08 19:01:25 -0700743
vijay kumare95092d2014-10-20 19:24:49 +0530744 svc_id = SCM_SVC_FUSE;
745 cmd_id = SCM_IS_SW_FUSE_BLOWN_ID;
Shashank Mittal162244e2011-08-08 19:01:25 -0700746
vijay kumare95092d2014-10-20 19:24:49 +0530747 scm_call(svc_id, cmd_id, cmd_buf, cmd_len, &resp_buf, resp_len);
748 return resp_buf;
749 }
750 else
751 {
752 scm_arg.x0 = MAKE_SIP_SCM_CMD(SCM_SVC_FUSE, SCM_IS_SW_FUSE_BLOWN_ID);
753 scm_arg.x1 = MAKE_SCM_ARGS(0x2,SMC_PARAM_TYPE_BUFFER_READWRITE,SMC_PARAM_TYPE_VALUE);
Veera Sundaram Sankaran00181512014-12-09 11:23:39 -0800754 scm_arg.x2 = (uint32_t) cmd_buf;
vijay kumare95092d2014-10-20 19:24:49 +0530755 scm_arg.x3 = cmd_len;
756
757 scm_call2(&scm_arg, &scm_ret);
758 return (uint8_t)scm_ret.x1;
759 }
Shashank Mittal162244e2011-08-08 19:01:25 -0700760}
Deepa Dinamani193874e2012-02-07 14:00:04 -0800761
Amir Samuelov4620ad22013-03-13 11:30:05 +0200762/*
763 * struct qseecom_save_partition_hash_req
764 * @partition_id - partition id.
765 * @digest[SHA256_DIGEST_LENGTH] - sha256 digest.
766 */
767struct qseecom_save_partition_hash_req {
768 uint32_t partition_id; /* in */
769 uint8_t digest[SHA256_DIGEST_LENGTH]; /* in */
770};
771
772
773void save_kernel_hash_cmd(void *digest)
774{
775 uint32_t svc_id;
776 uint32_t cmd_id;
777 void *cmd_buf;
778 size_t cmd_len;
779 void *resp_buf = NULL;
780 size_t resp_len = 0;
781 struct qseecom_save_partition_hash_req req;
Channagoud Kadabidd85e7f2014-08-05 19:58:37 -0700782 scmcall_arg scm_arg = {0};
Amir Samuelov4620ad22013-03-13 11:30:05 +0200783
784 /*no response */
785 resp_buf = NULL;
786 resp_len = 0;
787
788 req.partition_id = 0; /* kernel */
789 memcpy(req.digest, digest, sizeof(req.digest));
790
Channagoud Kadabidd85e7f2014-08-05 19:58:37 -0700791 if (!scm_arm_support)
792 {
793 svc_id = SCM_SVC_ES;
794 cmd_id = SCM_SAVE_PARTITION_HASH_ID;
795 cmd_buf = (void *)&req;
796 cmd_len = sizeof(req);
Amir Samuelov4620ad22013-03-13 11:30:05 +0200797
Channagoud Kadabidd85e7f2014-08-05 19:58:37 -0700798 scm_call(svc_id, cmd_id, cmd_buf, cmd_len, resp_buf, resp_len);
799 }
800 else
801 {
802 scm_arg.x0 = MAKE_SIP_SCM_CMD(SCM_SVC_ES, SCM_SAVE_PARTITION_HASH_ID);
803 scm_arg.x1 = MAKE_SCM_ARGS(0x3, 0, SMC_PARAM_TYPE_BUFFER_READWRITE);
804 scm_arg.x2 = req.partition_id;
Veera Sundaram Sankaran00181512014-12-09 11:23:39 -0800805 scm_arg.x3 = (uint32_t) &req.digest;
Channagoud Kadabidd85e7f2014-08-05 19:58:37 -0700806 scm_arg.x4 = sizeof(req.digest);
807
808 if (scm_call2(&scm_arg, NULL))
809 dprintf(CRITICAL, "Failed to Save kernel hash\n");
810 }
Amir Samuelov4620ad22013-03-13 11:30:05 +0200811}
812
Amit Blayfe23ee22015-01-09 19:09:51 +0200813int mdtp_cipher_dip_cmd(uint8_t *in_buf, uint32_t in_buf_size, uint8_t *out_buf,
814 uint32_t out_buf_size, uint32_t direction)
815{
816 uint32_t svc_id;
817 uint32_t cmd_id;
818 void *cmd_buf;
819 void *rsp_buf;
820 size_t cmd_len;
821 size_t rsp_len;
822 mdtp_cipher_dip_req req;
823 scmcall_arg scm_arg = {0};
824 scmcall_ret scm_ret = {0};
825
826 ASSERT(in_buf != NULL);
827 ASSERT(out_buf != NULL);
828
829 req.in_buf = in_buf;
830 req.in_buf_size = in_buf_size;
831 req.out_buf = out_buf;
832 req.out_buf_size = out_buf_size;
833 req.direction = direction;
834
835 if (!scm_arm_support)
836 {
837 svc_id = SCM_SVC_MDTP;
838 cmd_id = SCM_MDTP_CIPHER_DIP;
839 cmd_buf = (void *)&req;
840 cmd_len = sizeof(req);
841 rsp_buf = NULL;
842 rsp_len = 0;
843
844 if (scm_call(svc_id, cmd_id, cmd_buf, cmd_len, rsp_buf, rsp_len))
845 {
846 dprintf(CRITICAL, "Failed to call Cipher DIP SCM\n");
847 return -1;
848 }
849 }
850 else
851 {
852 scm_arg.x0 = MAKE_SIP_SCM_CMD(SCM_SVC_MDTP, SCM_MDTP_CIPHER_DIP);
853 scm_arg.x1 = MAKE_SCM_ARGS(0x5, SMC_PARAM_TYPE_BUFFER_READ, SMC_PARAM_TYPE_VALUE,
854 SMC_PARAM_TYPE_BUFFER_READWRITE, SMC_PARAM_TYPE_VALUE, SMC_PARAM_TYPE_VALUE);
855 scm_arg.x2 = (uint32_t)req.in_buf;
856 scm_arg.x3 = req.in_buf_size;
857 scm_arg.x4 = (uint32_t)req.out_buf;
858 scm_arg.x5[0] = req.out_buf_size;
859 scm_arg.x5[1] = req.direction;
860
861 if (scm_call2(&scm_arg, &scm_ret))
862 {
863 dprintf(CRITICAL, "Failed in Cipher DIP SCM call\n");
864 return -1;
865 }
866 }
867
868 return 0;
869}
870
Amit Blaybdfabc62015-01-29 22:04:13 +0200871int qfprom_read_row_cmd(uint32_t row_address,
872 uint32_t addr_type,
873 uint32_t *row_data,
874 uint32_t *qfprom_api_status)
875{
876 uint32_t svc_id;
877 uint32_t cmd_id;
878 void *cmd_buf;
879 void *rsp_buf;
880 size_t cmd_len;
881 size_t rsp_len;
882 qfprom_read_row_req req;
883 scmcall_arg scm_arg = {0};
884 scmcall_ret scm_ret = {0};
885
886 req.row_address = row_address;
887 req.addr_type = addr_type;
888 req.row_data = row_data;
889 req.qfprom_api_status = qfprom_api_status;
890
891 if (!scm_arm_support)
892 {
893 svc_id = SCM_SVC_FUSE;
894 cmd_id = SCM_QFPROM_READ_ROW_ID;
895 cmd_buf = (void *)&req;
896 cmd_len = sizeof(req);
897 rsp_buf = NULL;
898 rsp_len = 0;
899
900 if (scm_call(svc_id, cmd_id, cmd_buf, cmd_len, rsp_buf, rsp_len))
901 {
902 dprintf(CRITICAL, "Failed to call SCM_SVC_FUSE.SCM_QFPROM_READ_ROW_ID SCM\n");
903 return -1;
904 }
905 }
906 else
907 {
908 scm_arg.x0 = MAKE_SIP_SCM_CMD(SCM_SVC_FUSE, SCM_QFPROM_READ_ROW_ID);
909 scm_arg.x1 = MAKE_SCM_ARGS(0x4, SMC_PARAM_TYPE_VALUE, SMC_PARAM_TYPE_VALUE,
910 SMC_PARAM_TYPE_BUFFER_READWRITE, SMC_PARAM_TYPE_BUFFER_READWRITE);
911 scm_arg.x2 = req.row_address;
912 scm_arg.x3 = req.addr_type;
913 scm_arg.x4 = (uint32_t)req.row_data;
914 scm_arg.x5[0] = (uint32_t)req.qfprom_api_status;
915
916 if (scm_call2(&scm_arg, &scm_ret))
917 {
918 dprintf(CRITICAL, "Failed to call SCM_SVC_FUSE.SCM_QFPROM_READ_ROW_ID SCM\n");
919 return -1;
920 }
921 }
922
923 return 0;
924}
925
Deepa Dinamani193874e2012-02-07 14:00:04 -0800926/*
927 * Switches the CE1 channel between ADM and register usage.
928 * channel : AP_CE_REGISTER_USE, CE1 uses register interface
929 * : AP_CE_ADM_USE, CE1 uses ADM interface
930 */
931uint8_t switch_ce_chn_cmd(enum ap_ce_channel_type channel)
932{
933 uint32_t svc_id;
934 uint32_t cmd_id;
935 void *cmd_buf;
936 size_t cmd_len;
937 size_t resp_len = 0;
938 uint8_t resp_buf;
939
940 struct {
941 uint32_t resource;
942 uint32_t chn_id;
943 }__PACKED switch_ce_chn_buf;
944
Channagoud Kadabidd85e7f2014-08-05 19:58:37 -0700945 if (scm_arm_support)
946 {
947 dprintf(INFO, "%s:SCM call is not supported\n",__func__);
948 return 0;
949 }
950
Deepa Dinamani193874e2012-02-07 14:00:04 -0800951 switch_ce_chn_buf.resource = TZ_RESOURCE_CE_AP;
952 switch_ce_chn_buf.chn_id = channel;
953 cmd_buf = (void *)&switch_ce_chn_buf;
954 cmd_len = sizeof(switch_ce_chn_buf);
955
956 /*response */
957 resp_len = sizeof(resp_buf);
958
959 svc_id = SCM_SVC_CE_CHN_SWITCH_ID;
960 cmd_id = SCM_CE_CHN_SWITCH_ID;
961
962 scm_call(svc_id, cmd_id, cmd_buf, cmd_len, &resp_buf, resp_len);
963 return resp_buf;
964}
965
Channagoud Kadabi179df0b2013-12-12 14:53:31 -0800966int scm_halt_pmic_arbiter()
967{
968 int ret = 0;
Aparna Mallavarapu246c30b2014-12-11 12:07:51 +0530969 scmcall_arg scm_arg = {0};
Channagoud Kadabi179df0b2013-12-12 14:53:31 -0800970
Aparna Mallavarapu246c30b2014-12-11 12:07:51 +0530971 if (scm_arm_support) {
972 scm_arg.x0 = MAKE_SIP_SCM_CMD(SCM_SVC_PWR, SCM_IO_DISABLE_PMIC_ARBITER);
973 scm_arg.x1 = MAKE_SCM_ARGS(0x1);
974 scm_arg.x2 = 0;
975 scm_arg.atomic = true;
976 ret = scm_call2(&scm_arg, NULL);
977 } else {
978 ret = scm_call_atomic(SCM_SVC_PWR, SCM_IO_DISABLE_PMIC_ARBITER, 0);
Channagoud Kadabidd85e7f2014-08-05 19:58:37 -0700979 }
980
Aparna Mallavarapu246c30b2014-12-11 12:07:51 +0530981 /* Retry with the SCM_IO_DISABLE_PMIC_ARBITER1 func ID if the above Func ID fails*/
982 if(ret) {
983 if (scm_arm_support) {
984 scm_arg.x0 = MAKE_SIP_SCM_CMD(SCM_SVC_PWR, SCM_IO_DISABLE_PMIC_ARBITER1);
985 scm_arg.x1 = MAKE_SCM_ARGS(0x1);
986 scm_arg.x2 = 0;
987 scm_arg.atomic = true;
988 ret = scm_call2(&scm_arg, NULL);
989 } else
990 ret = scm_call_atomic(SCM_SVC_PWR, SCM_IO_DISABLE_PMIC_ARBITER1, 0);
991 }
Channagoud Kadabi179df0b2013-12-12 14:53:31 -0800992
993 return ret;
994}
Abhimanyu Kapurb3207fb2014-01-27 21:33:23 -0800995
996/* Execption Level exec secure-os call
997 * Jumps to kernel via secure-os and does not return
998 * on successful jump. System parameters are setup &
999 * passed on to secure-os and are utilized to boot the
1000 * kernel.
1001 *
1002 @ kernel_entry : kernel entry point passed in as link register.
1003 @ dtb_offset : dt blob address passed in as w0.
1004 @ svc_id : indicates direction of switch 32->64 or 64->32
1005 *
1006 * Assumes all sanity checks have been performed on arguments.
1007 */
1008
1009void scm_elexec_call(paddr_t kernel_entry, paddr_t dtb_offset)
1010{
1011 uint32_t svc_id = SCM_SVC_MILESTONE_32_64_ID;
1012 uint32_t cmd_id = SCM_SVC_MILESTONE_CMD_ID;
1013 void *cmd_buf;
1014 size_t cmd_len;
Sridhar Parasuramfc6ea712015-06-30 11:22:49 -07001015 static el1_system_param param __attribute__((aligned(0x1000)));
Channagoud Kadabidd85e7f2014-08-05 19:58:37 -07001016 scmcall_arg scm_arg = {0};
Abhimanyu Kapurb3207fb2014-01-27 21:33:23 -08001017
1018 param.el1_x0 = dtb_offset;
1019 param.el1_elr = kernel_entry;
1020
Abhimanyu Kapurb3207fb2014-01-27 21:33:23 -08001021 /* Response Buffer = Null as no response expected */
1022 dprintf(INFO, "Jumping to kernel via monitor\n");
Channagoud Kadabidd85e7f2014-08-05 19:58:37 -07001023
1024 if (!scm_arm_support)
1025 {
1026 /* Command Buffer */
1027 cmd_buf = (void *)&param;
1028 cmd_len = sizeof(el1_system_param);
1029
1030 scm_call(svc_id, cmd_id, cmd_buf, cmd_len, NULL, 0);
1031 }
1032 else
1033 {
1034 scm_arg.x0 = MAKE_SIP_SCM_CMD(SCM_SVC_MILESTONE_32_64_ID, SCM_SVC_MILESTONE_CMD_ID);
1035 scm_arg.x1 = MAKE_SCM_ARGS(0x2, SMC_PARAM_TYPE_BUFFER_READ);
Veera Sundaram Sankaran00181512014-12-09 11:23:39 -08001036 scm_arg.x2 = (uint32_t ) &param;
Channagoud Kadabidd85e7f2014-08-05 19:58:37 -07001037 scm_arg.x3 = sizeof(el1_system_param);
1038
1039 scm_call2(&scm_arg, NULL);
1040 }
Abhimanyu Kapurb3207fb2014-01-27 21:33:23 -08001041
1042 /* Assert if execution ever reaches here */
1043 dprintf(CRITICAL, "Failed to jump to kernel\n");
1044 ASSERT(0);
1045}
Maria Yubeeeeaf2014-06-30 13:05:43 +08001046
1047/* SCM Random Command */
1048int scm_random(uint32_t * rbuf, uint32_t r_len)
1049{
1050 int ret;
1051 struct tz_prng_data data;
Channagoud Kadabidd85e7f2014-08-05 19:58:37 -07001052 scmcall_arg scm_arg = {0};
Maria Yubeeeeaf2014-06-30 13:05:43 +08001053
Channagoud Kadabidd85e7f2014-08-05 19:58:37 -07001054 if (!scm_arm_support)
1055 {
1056 data.out_buf = (uint8_t*) rbuf;
1057 data.out_buf_size = r_len;
Maria Yubeeeeaf2014-06-30 13:05:43 +08001058
Channagoud Kadabidd85e7f2014-08-05 19:58:37 -07001059 /*
1060 * random buffer must be flushed/invalidated before and after TZ call.
1061 */
1062 arch_clean_invalidate_cache_range((addr_t) rbuf, r_len);
Maria Yubeeeeaf2014-06-30 13:05:43 +08001063
Channagoud Kadabidd85e7f2014-08-05 19:58:37 -07001064 ret = scm_call(TZ_SVC_CRYPTO, PRNG_CMD_ID, &data, sizeof(data), NULL, 0);
Maria Yubeeeeaf2014-06-30 13:05:43 +08001065
Channagoud Kadabidd85e7f2014-08-05 19:58:37 -07001066 /* Invalidate the updated random buffer */
1067 arch_clean_invalidate_cache_range((addr_t) rbuf, r_len);
1068 }
1069 else
1070 {
1071 scm_arg.x0 = MAKE_SIP_SCM_CMD(TZ_SVC_CRYPTO, PRNG_CMD_ID);
1072 scm_arg.x1 = MAKE_SCM_ARGS(0x2,SMC_PARAM_TYPE_BUFFER_READWRITE);
Veera Sundaram Sankaran00181512014-12-09 11:23:39 -08001073 scm_arg.x2 = (uint32_t) rbuf;
Channagoud Kadabidd85e7f2014-08-05 19:58:37 -07001074 scm_arg.x3 = r_len;
1075
1076 ret = scm_call2(&scm_arg, NULL);
1077 if (!ret)
1078 arch_clean_invalidate_cache_range((addr_t) rbuf, r_len);
1079 else
1080 dprintf(CRITICAL, "Secure canary SCM failed: %x\n", ret);
1081 }
Maria Yubeeeeaf2014-06-30 13:05:43 +08001082
1083 return ret;
1084}
1085
1086void * get_canary()
1087{
1088 void * canary;
vijay kumar4f4405f2014-08-08 11:49:53 +05301089 if(scm_random((uint32_t *)&canary, sizeof(canary))) {
Maria Yubeeeeaf2014-06-30 13:05:43 +08001090 dprintf(CRITICAL,"scm_call for random failed !!!");
1091 /*
1092 * fall back to use lib rand API if scm call failed.
1093 */
1094 canary = (void *)rand();
1095 }
1096
1097 return canary;
1098}
Aparna Mallavarapu6875ade2014-06-16 22:15:28 +05301099
1100int scm_xpu_err_fatal_init()
1101{
1102 uint32_t ret = 0;
1103 uint32_t response = 0;
1104 tz_xpu_prot_cmd cmd;
Channagoud Kadabidd85e7f2014-08-05 19:58:37 -07001105 scmcall_arg scm_arg = {0};
1106 scmcall_ret scm_ret = {0};
Aparna Mallavarapu6875ade2014-06-16 22:15:28 +05301107
Channagoud Kadabidd85e7f2014-08-05 19:58:37 -07001108 if (!scm_arm_support)
1109 {
1110 cmd.config = ERR_FATAL_ENABLE;
1111 cmd.spare = 0;
Aparna Mallavarapu6875ade2014-06-16 22:15:28 +05301112
Channagoud Kadabidd85e7f2014-08-05 19:58:37 -07001113 ret = scm_call(SVC_MEMORY_PROTECTION, XPU_ERR_FATAL, &cmd, sizeof(cmd), &response,
1114 sizeof(response));
1115 }
1116 else
1117 {
1118 scm_arg.x0 = MAKE_SIP_SCM_CMD(SVC_MEMORY_PROTECTION, XPU_ERR_FATAL);
1119 scm_arg.x1 = MAKE_SCM_ARGS(0x2);
1120 scm_arg.x2 = ERR_FATAL_ENABLE;
1121 scm_arg.x3 = 0x0;
1122 ret = scm_call2(&scm_arg, &scm_ret);
1123 response = scm_ret.x1;
1124 }
Aparna Mallavarapu6875ade2014-06-16 22:15:28 +05301125
1126 if (ret)
1127 dprintf(CRITICAL, "Failed to set XPU violations as fatal errors: %u\n", response);
1128 else
1129 dprintf(INFO, "Configured XPU violations to be fatal errors\n");
1130
1131 return ret;
1132}
Channagoud Kadabidd85e7f2014-08-05 19:58:37 -07001133
1134static uint32_t scm_call_a32(uint32_t x0, uint32_t x1, uint32_t x2, uint32_t x3, uint32_t x4, uint32_t x5, scmcall_ret *ret)
1135{
1136 register uint32_t r0 __asm__("r0") = x0;
1137 register uint32_t r1 __asm__("r1") = x1;
1138 register uint32_t r2 __asm__("r2") = x2;
1139 register uint32_t r3 __asm__("r3") = x3;
1140 register uint32_t r4 __asm__("r4") = x4;
1141 register uint32_t r5 __asm__("r5") = x5;
Channagoud Kadabie75efb92015-05-19 14:20:05 -07001142 register uint32_t r6 __asm__("r6") = 0;
Channagoud Kadabidd85e7f2014-08-05 19:58:37 -07001143
Dinesh K Garg6bbbb702015-01-30 11:13:31 -08001144 do {
1145 __asm__ volatile(
1146 __asmeq("%0", "r0")
1147 __asmeq("%1", "r1")
1148 __asmeq("%2", "r2")
1149 __asmeq("%3", "r3")
1150 __asmeq("%4", "r0")
1151 __asmeq("%5", "r1")
1152 __asmeq("%6", "r2")
1153 __asmeq("%7", "r3")
1154 __asmeq("%8", "r4")
1155 __asmeq("%9", "r5")
Channagoud Kadabie75efb92015-05-19 14:20:05 -07001156 __asmeq("%10", "r6")
Dinesh K Garg6bbbb702015-01-30 11:13:31 -08001157 "smc #0 @ switch to secure world\n"
1158 : "=r" (r0), "=r" (r1), "=r" (r2), "=r" (r3)
Channagoud Kadabie75efb92015-05-19 14:20:05 -07001159 : "r" (r0), "r" (r1), "r" (r2), "r" (r3), "r" (r4), "r" (r5), "r" (r6));
Dinesh K Garg6bbbb702015-01-30 11:13:31 -08001160 } while(r0 == 1);
Channagoud Kadabidd85e7f2014-08-05 19:58:37 -07001161
1162 if (ret)
1163 {
1164 ret->x1 = r1;
1165 ret->x2 = r2;
1166 ret->x3 = r3;
1167 }
1168
1169 return r0;
1170}
1171
1172uint32_t scm_call2(scmcall_arg *arg, scmcall_ret *ret)
1173{
1174 uint32_t *indir_arg = NULL;
1175 uint32_t x5;
1176 int i;
1177 uint32_t rc;
1178
1179 arg->x0 = arg->atomic ? (arg->x0 | SCM_ATOMIC_BIT) : arg->x0;
1180 x5 = arg->x5[0];
1181
Amit Blayfe23ee22015-01-09 19:09:51 +02001182 if ((arg->x1 & 0xF) > SCM_MAX_ARG_LEN - 1)
Channagoud Kadabidd85e7f2014-08-05 19:58:37 -07001183 {
1184 indir_arg = memalign(CACHE_LINE, (SCM_INDIR_MAX_LEN * sizeof(uint32_t)));
1185 ASSERT(indir_arg);
1186
1187 for (i = 0 ; i < SCM_INDIR_MAX_LEN; i++)
1188 {
1189 indir_arg[i] = arg->x5[i];
1190 }
1191 arch_clean_invalidate_cache_range((addr_t) indir_arg, ROUNDUP((SCM_INDIR_MAX_LEN * sizeof(uint32_t)), CACHE_LINE));
1192 x5 = (addr_t) indir_arg;
1193 }
1194
1195 rc = scm_call_a32(arg->x0, arg->x1, arg->x2, arg->x3, arg->x4, x5, ret);
1196
1197 if (rc)
1198 {
1199 dprintf(CRITICAL, "SCM call: 0x%x failed with :%x\n", arg->x0, rc);
1200 return rc;
1201 }
1202
1203 if (indir_arg)
1204 free(indir_arg);
1205
1206 return 0;
1207}
Aparna Mallavarapu246c30b2014-12-11 12:07:51 +05301208
Aparna Mallavarapu8adbee22015-03-10 19:58:06 +05301209static bool secure_boot_enabled = true;
1210static bool wdog_debug_fuse_disabled = true;
Aparna Mallavarapu246c30b2014-12-11 12:07:51 +05301211
1212void scm_check_boot_fuses()
1213{
1214 uint32_t ret = 0;
Aparna Mallavarapu664ea772015-02-24 18:44:33 +05301215 uint32_t resp;
Aparna Mallavarapu246c30b2014-12-11 12:07:51 +05301216 scmcall_arg scm_arg = {0};
1217 scmcall_ret scm_ret = {0};
1218
1219 if (!scm_arm_support) {
Aparna Mallavarapu664ea772015-02-24 18:44:33 +05301220 ret = scm_call(TZBSP_SVC_INFO, IS_SECURE_BOOT_ENABLED, NULL, 0, &resp, sizeof(resp));
Aparna Mallavarapu246c30b2014-12-11 12:07:51 +05301221 } else {
1222 scm_arg.x0 = MAKE_SIP_SCM_CMD(TZBSP_SVC_INFO, IS_SECURE_BOOT_ENABLED);
1223 ret = scm_call2(&scm_arg, &scm_ret);
Aparna Mallavarapu664ea772015-02-24 18:44:33 +05301224 resp = scm_ret.x1;
Aparna Mallavarapu246c30b2014-12-11 12:07:51 +05301225 }
1226
1227 /* Parse Bit 0 and Bit 2 of the response */
1228 if(!ret) {
1229 /* Bit 0 - SECBOOT_ENABLE_CHECK */
Aparna Mallavarapu664ea772015-02-24 18:44:33 +05301230 if(resp & 0x1)
Aparna Mallavarapu8adbee22015-03-10 19:58:06 +05301231 secure_boot_enabled = false;
Aparna Mallavarapu246c30b2014-12-11 12:07:51 +05301232 /* Bit 2 - DEBUG_DISABLE_CHECK */
Aparna Mallavarapu664ea772015-02-24 18:44:33 +05301233 if(resp & 0x4)
Aparna Mallavarapu8adbee22015-03-10 19:58:06 +05301234 wdog_debug_fuse_disabled = false;
Aparna Mallavarapu246c30b2014-12-11 12:07:51 +05301235 } else
1236 dprintf(CRITICAL, "scm call to check secure boot fuses failed\n");
1237}
1238
1239bool is_secure_boot_enable()
1240{
1241 scm_check_boot_fuses();
Aparna Mallavarapu8adbee22015-03-10 19:58:06 +05301242 return secure_boot_enabled;
Aparna Mallavarapu246c30b2014-12-11 12:07:51 +05301243}
1244
1245static uint32_t scm_io_read(addr_t address)
1246{
1247 uint32_t ret;
1248 scmcall_arg scm_arg = {0};
1249 scmcall_ret scm_ret = {0};
1250
1251 if (!scm_arm_support) {
1252 ret = scm_call_atomic(SCM_SVC_IO, SCM_IO_READ, address);
1253 } else {
1254 scm_arg.x0 = MAKE_SIP_SCM_CMD(SCM_SVC_IO, SCM_IO_READ);
1255 scm_arg.x1 = MAKE_SCM_ARGS(0x1);
1256 scm_arg.x2 = address;
1257 scm_arg.atomic = true;
1258 ret = scm_call2(&scm_arg, &scm_ret);
1259 }
1260 return ret;
1261}
1262
1263static uint32_t scm_io_write(uint32_t address, uint32_t val)
1264{
1265 uint32_t ret;
1266 scmcall_arg scm_arg = {0};
1267 scmcall_ret scm_ret = {0};
1268
1269 if (!scm_arm_support) {
1270 ret = scm_call_atomic2(SCM_SVC_IO, SCM_IO_WRITE, address, val);
1271 } else {
1272 scm_arg.x0 = MAKE_SIP_SCM_CMD(SCM_SVC_IO, SCM_IO_WRITE);
1273 scm_arg.x1 = MAKE_SCM_ARGS(0x2);
1274 scm_arg.x2 = address;
1275 scm_arg.x3 = val;
1276 scm_arg.atomic = true;
1277 ret = scm_call2(&scm_arg, &scm_ret);
1278 }
1279 return ret;
1280}
Aparna Mallavarapu664ea772015-02-24 18:44:33 +05301281
1282static int scm_call2_atomic(uint32_t svc, uint32_t cmd, uint32_t arg1, uint32_t arg2)
1283{
1284 uint32_t ret = 0;
1285 scmcall_arg scm_arg = {0};
1286 scmcall_ret scm_ret = {0};
1287
1288 if (!scm_arm_support)
1289 {
1290 ret = scm_call_atomic2(svc, cmd, arg1, arg2);
1291 } else {
1292 scm_arg.x0 = MAKE_SIP_SCM_CMD(svc, cmd);
1293 scm_arg.x1 = MAKE_SCM_ARGS(0x2);
1294 scm_arg.x2 = arg1;
1295 scm_arg.x3 = arg2;
1296 ret = scm_call2(&scm_arg, &scm_ret);
1297 }
1298 return ret;
1299}
1300
1301#if PLATFORM_USE_SCM_DLOAD
1302int scm_dload_mode(int mode)
1303{
1304 int ret = 0;
1305 uint32_t dload_type;
1306
1307 dprintf(SPEW, "DLOAD mode: %d\n", mode);
1308 if (mode == NORMAL_DLOAD)
1309 dload_type = SCM_DLOAD_MODE;
1310 else if(mode == EMERGENCY_DLOAD)
1311 dload_type = SCM_EDLOAD_MODE;
1312 else
1313 dload_type = 0;
1314
1315 /* Write to the Boot MISC register */
1316 ret = scm_call2_atomic(SCM_SVC_BOOT, SCM_DLOAD_CMD, dload_type, 0);
1317
1318 if (ret) {
1319 ret = scm_io_write(TCSR_BOOT_MISC_DETECT,dload_type);
1320 if(ret) {
1321 dprintf(CRITICAL, "Failed to write to boot misc: %d\n", ret);
1322 return ret;
1323 }
1324 }
1325
1326 scm_check_boot_fuses();
1327
1328 /* Make WDOG_DEBUG DISABLE scm call only in non-secure boot */
Aparna Mallavarapu8adbee22015-03-10 19:58:06 +05301329 if(!(secure_boot_enabled || wdog_debug_fuse_disabled)) {
Aparna Mallavarapu664ea772015-02-24 18:44:33 +05301330 ret = scm_call2_atomic(SCM_SVC_BOOT, WDOG_DEBUG_DISABLE, 1, 0);
1331 if(ret)
1332 dprintf(CRITICAL, "Failed to disable the wdog debug \n");
1333 }
1334
1335 return ret;
1336}
1337#endif