blob: df4b136637eab5e2c88409d037762247e8c7ddf6 [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;
59
Dinesh K Garg6bbbb702015-01-30 11:13:31 -080060bool is_scm_armv8_support()
61{
62 return scm_arm_support;
63}
64
Channagoud Kadabi77f46a32015-08-05 16:13:13 -070065int is_scm_call_available(uint32_t svc_id, uint32_t cmd_id)
Channagoud Kadabidd85e7f2014-08-05 19:58:37 -070066{
vijay kumar496a2ff2015-07-22 21:22:48 +053067 int ret;
Channagoud Kadabidd85e7f2014-08-05 19:58:37 -070068 scmcall_arg scm_arg = {0};
Veera Sundaram Sankaran00181512014-12-09 11:23:39 -080069 scmcall_ret scm_ret = {0};
Channagoud Kadabia2184b82015-07-07 10:09:32 -070070
Channagoud Kadabidd85e7f2014-08-05 19:58:37 -070071 scm_arg.x0 = MAKE_SIP_SCM_CMD(SCM_SVC_INFO, IS_CALL_AVAIL_CMD);
72 scm_arg.x1 = MAKE_SCM_ARGS(0x1);
73 scm_arg.x2 = MAKE_SIP_SCM_CMD(svc_id, cmd_id);
74
75 ret = scm_call2(&scm_arg, &scm_ret);
76
77 if (!ret)
Channagoud Kadabia2184b82015-07-07 10:09:32 -070078 return scm_ret.x1;
79
80 return ret;
Channagoud Kadabidd85e7f2014-08-05 19:58:37 -070081}
82
Channagoud Kadabia2184b82015-07-07 10:09:32 -070083static int scm_arm_support_available(uint32_t svc_id, uint32_t cmd_id)
84{
vijay kumar496a2ff2015-07-22 21:22:48 +053085 int ret;
Channagoud Kadabia2184b82015-07-07 10:09:32 -070086
87 ret = is_scm_call_available(SCM_SVC_INFO, IS_CALL_AVAIL_CMD);
88
89 if (ret > 0)
90 scm_arm_support = true;
91
92 return ret;
93}
Channagoud Kadabidd85e7f2014-08-05 19:58:37 -070094
95void scm_init()
96{
Channagoud Kadabia2184b82015-07-07 10:09:32 -070097 int ret;
98
99 ret = scm_arm_support_available(SCM_SVC_INFO, IS_CALL_AVAIL_CMD);
100
vijay kumar496a2ff2015-07-22 21:22:48 +0530101 if (ret < 0)
Channagoud Kadabia2184b82015-07-07 10:09:32 -0700102 dprintf(CRITICAL, "Failed to initialize SCM\n");
Channagoud Kadabidd85e7f2014-08-05 19:58:37 -0700103}
Channagoud Kadabi179df0b2013-12-12 14:53:31 -0800104
Shashank Mittal162244e2011-08-08 19:01:25 -0700105/**
106 * alloc_scm_command() - Allocate an SCM command
107 * @cmd_size: size of the command buffer
108 * @resp_size: size of the response buffer
109 *
110 * Allocate an SCM command, including enough room for the command
111 * and response headers as well as the command and response buffers.
112 *
113 * Returns a valid &scm_command on success or %NULL if the allocation fails.
114 */
115static struct scm_command *alloc_scm_command(size_t cmd_size, size_t resp_size)
116{
117 struct scm_command *cmd;
118 size_t len = sizeof(*cmd) + sizeof(struct scm_response) + cmd_size +
Ajay Dudanib01e5062011-12-03 23:23:42 -0800119 resp_size;
Shashank Mittal162244e2011-08-08 19:01:25 -0700120
Deepa Dinamani904f8f82012-12-05 16:35:01 -0800121 cmd = memalign(CACHE_LINE, ROUNDUP(len, CACHE_LINE));
Ajay Dudanib01e5062011-12-03 23:23:42 -0800122 if (cmd) {
Pavel Nedev80ce36f2014-01-06 14:26:17 +0200123 memset(cmd, 0, len);
Shashank Mittal162244e2011-08-08 19:01:25 -0700124 cmd->len = len;
125 cmd->buf_offset = offsetof(struct scm_command, buf);
126 cmd->resp_hdr_offset = cmd->buf_offset + cmd_size;
127 }
128 return cmd;
129}
130
131/**
132 * free_scm_command() - Free an SCM command
133 * @cmd: command to free
134 *
135 * Free an SCM command.
136 */
137static inline void free_scm_command(struct scm_command *cmd)
138{
139 free(cmd);
140}
141
142/**
143 * scm_command_to_response() - Get a pointer to a scm_response
144 * @cmd: command
145 *
146 * Returns a pointer to a response for a command.
147 */
Ajay Dudanib01e5062011-12-03 23:23:42 -0800148static inline struct scm_response *scm_command_to_response(const struct
149 scm_command *cmd)
Shashank Mittal162244e2011-08-08 19:01:25 -0700150{
151 return (void *)cmd + cmd->resp_hdr_offset;
152}
153
154/**
155 * scm_get_command_buffer() - Get a pointer to a command buffer
156 * @cmd: command
157 *
158 * Returns a pointer to the command buffer of a command.
159 */
160static inline void *scm_get_command_buffer(const struct scm_command *cmd)
161{
162 return (void *)cmd->buf;
163}
164
165/**
166 * scm_get_response_buffer() - Get a pointer to a response buffer
167 * @rsp: response
168 *
169 * Returns a pointer to a response buffer of a response.
170 */
171static inline void *scm_get_response_buffer(const struct scm_response *rsp)
172{
173 return (void *)rsp + rsp->buf_offset;
174}
175
176static uint32_t smc(uint32_t cmd_addr)
177{
178 uint32_t context_id;
179 register uint32_t r0 __asm__("r0") = 1;
Ajay Dudanib01e5062011-12-03 23:23:42 -0800180 register uint32_t r1 __asm__("r1") = (uint32_t) & context_id;
Shashank Mittal162244e2011-08-08 19:01:25 -0700181 register uint32_t r2 __asm__("r2") = cmd_addr;
Ajay Dudanib01e5062011-12-03 23:23:42 -0800182 __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 -0700183 return r0;
184}
185
186/**
Channagoud Kadabi179df0b2013-12-12 14:53:31 -0800187* scm_call_automic: Make scm call with one or no argument
188* @svc: service id
189* @cmd: command id
190* @ arg1: argument
191*/
192
193static int scm_call_atomic(uint32_t svc, uint32_t cmd, uint32_t arg1)
194{
195 uint32_t context_id;
196 register uint32_t r0 __asm__("r0") = SCM_ATOMIC(svc, cmd, 1);
vijay kumar4f4405f2014-08-08 11:49:53 +0530197 register uint32_t r1 __asm__("r1") = (uint32_t)&context_id;
Channagoud Kadabi179df0b2013-12-12 14:53:31 -0800198 register uint32_t r2 __asm__("r2") = arg1;
199
200 __asm__ volatile(
201 __asmeq("%0", "r0")
202 __asmeq("%1", "r0")
203 __asmeq("%2", "r1")
204 __asmeq("%3", "r2")
205 "smc #0 @ switch to secure world\n"
206 : "=r" (r0)
207 : "r" (r0), "r" (r1), "r" (r2)
208 : "r3");
209 return r0;
210}
211
212/**
Aparna Mallavarapu68e233f2014-03-21 19:18:34 +0530213 * scm_call_atomic2() - Send an atomic SCM command with two arguments
214 * @svc_id: service identifier
215 * @cmd_id: command identifier
216 * @arg1: first argument
217 * @arg2: second argument
218 *
219 * This shall only be used with commands that are guaranteed to be
220 * uninterruptable, atomic and SMP safe.
221 */
222int scm_call_atomic2(uint32_t svc, uint32_t cmd, uint32_t arg1, uint32_t arg2)
223{
224 int context_id;
225 register uint32_t r0 __asm__("r0") = SCM_ATOMIC(svc, cmd, 2);
vijay kumar4f4405f2014-08-08 11:49:53 +0530226 register uint32_t r1 __asm__("r1") = (uint32_t)&context_id;
Aparna Mallavarapu68e233f2014-03-21 19:18:34 +0530227 register uint32_t r2 __asm__("r2") = arg1;
228 register uint32_t r3 __asm__("r3") = arg2;
229
230 __asm__ volatile(
231 __asmeq("%0", "r0")
232 __asmeq("%1", "r0")
233 __asmeq("%2", "r1")
234 __asmeq("%3", "r2")
235 __asmeq("%4", "r3")
236 "smc #0 @ switch to secure world\n"
237 : "=r" (r0)
238 : "r" (r0), "r" (r1), "r" (r2), "r" (r3));
239 return r0;
240}
241
242/**
Shashank Mittal162244e2011-08-08 19:01:25 -0700243 * scm_call() - Send an SCM command
244 * @svc_id: service identifier
245 * @cmd_id: command identifier
246 * @cmd_buf: command buffer
247 * @cmd_len: length of the command buffer
248 * @resp_buf: response buffer
249 * @resp_len: length of the response buffer
250 *
251 * Sends a command to the SCM and waits for the command to finish processing.
252 */
Ajay Dudanib01e5062011-12-03 23:23:42 -0800253int
254scm_call(uint32_t svc_id, uint32_t cmd_id, const void *cmd_buf,
255 size_t cmd_len, void *resp_buf, size_t resp_len)
Shashank Mittal162244e2011-08-08 19:01:25 -0700256{
257 int ret;
258 struct scm_command *cmd;
259 struct scm_response *rsp;
Neeti Desai127b9e02012-03-20 16:11:23 -0700260 uint8_t *resp_ptr;
Shashank Mittal162244e2011-08-08 19:01:25 -0700261
262 cmd = alloc_scm_command(cmd_len, resp_len);
263 if (!cmd)
264 return ERR_NO_MEMORY;
265
266 cmd->id = (svc_id << 10) | cmd_id;
267 if (cmd_buf)
268 memcpy(scm_get_command_buffer(cmd), cmd_buf, cmd_len);
269
Neeti Desai127b9e02012-03-20 16:11:23 -0700270 /* Flush command to main memory for TZ */
271 arch_clean_invalidate_cache_range((addr_t) cmd, cmd->len);
272
Ajay Dudanib01e5062011-12-03 23:23:42 -0800273 ret = smc((uint32_t) cmd);
Shashank Mittal162244e2011-08-08 19:01:25 -0700274 if (ret)
275 goto out;
276
Ajay Dudanib01e5062011-12-03 23:23:42 -0800277 if (resp_len) {
Shashank Mittal162244e2011-08-08 19:01:25 -0700278 rsp = scm_command_to_response(cmd);
279
Neeti Desai127b9e02012-03-20 16:11:23 -0700280 do
281 {
282 /* Need to invalidate before each check since TZ will update
283 * the response complete flag in main memory.
284 */
sundarajan srinivasan4dfd4f72013-02-27 14:13:09 -0800285 arch_invalidate_cache_range((addr_t) rsp, sizeof(*rsp));
Neeti Desai127b9e02012-03-20 16:11:23 -0700286 } while (!rsp->is_complete);
287
288
289 resp_ptr = scm_get_response_buffer(rsp);
290
291 /* Invalidate any cached response data */
sundarajan srinivasan4dfd4f72013-02-27 14:13:09 -0800292 arch_invalidate_cache_range((addr_t) resp_ptr, resp_len);
Shashank Mittal162244e2011-08-08 19:01:25 -0700293
294 if (resp_buf)
Neeti Desai127b9e02012-03-20 16:11:23 -0700295 memcpy(resp_buf, resp_ptr, resp_len);
Shashank Mittal162244e2011-08-08 19:01:25 -0700296 }
Ajay Dudanib01e5062011-12-03 23:23:42 -0800297 out:
Shashank Mittal162244e2011-08-08 19:01:25 -0700298 free_scm_command(cmd);
299 return ret;
300}
301
Siddhartha Agrawaleb094c52013-01-28 12:11:43 -0800302int restore_secure_cfg(uint32_t id)
303{
Channagoud Kadabiacaa75e2014-06-09 16:29:29 -0700304 int ret = 0;
Siddhartha Agrawaleb094c52013-01-28 12:11:43 -0800305 tz_secure_cfg secure_cfg;
306
Siddhartha Agrawald4648892013-02-17 18:16:18 -0800307 secure_cfg.id = id;
Siddhartha Agrawaleb094c52013-01-28 12:11:43 -0800308 secure_cfg.spare = 0;
Channagoud Kadabidd85e7f2014-08-05 19:58:37 -0700309 scmcall_arg scm_arg = {0};
Siddhartha Agrawaleb094c52013-01-28 12:11:43 -0800310
Channagoud Kadabidd85e7f2014-08-05 19:58:37 -0700311 if(!scm_arm_support)
312 {
313 ret = scm_call(SVC_MEMORY_PROTECTION, IOMMU_SECURE_CFG, &secure_cfg, sizeof(secure_cfg),
314 NULL, 0);
315 }
316 else
317 {
318 scm_arg.x0 = MAKE_SIP_SCM_CMD(SVC_MEMORY_PROTECTION, IOMMU_SECURE_CFG);
319 scm_arg.x1 = MAKE_SCM_ARGS(0x2);
320 scm_arg.x2 = id;
321 scm_arg.x3 = 0x0; /* Spare unused */
Siddhartha Agrawaleb094c52013-01-28 12:11:43 -0800322
Channagoud Kadabidd85e7f2014-08-05 19:58:37 -0700323 ret = scm_call2(&scm_arg, NULL);
324 }
325
326 if (ret)
327 {
Siddhartha Agrawaleb094c52013-01-28 12:11:43 -0800328 dprintf(CRITICAL, "Secure Config failed\n");
329 ret = 1;
Channagoud Kadabiacaa75e2014-06-09 16:29:29 -0700330 }
Siddhartha Agrawaleb094c52013-01-28 12:11:43 -0800331
332 return ret;
Siddhartha Agrawaleb094c52013-01-28 12:11:43 -0800333}
334
Neeti Desai127b9e02012-03-20 16:11:23 -0700335/* SCM Encrypt Command */
336int encrypt_scm(uint32_t ** img_ptr, uint32_t * img_len_ptr)
Shashank Mittal162244e2011-08-08 19:01:25 -0700337{
Neeti Desai127b9e02012-03-20 16:11:23 -0700338 int ret;
339 img_req cmd;
vijay kumare95092d2014-10-20 19:24:49 +0530340 scmcall_arg scm_arg = {0};
Shashank Mittal162244e2011-08-08 19:01:25 -0700341
Channagoud Kadabidd85e7f2014-08-05 19:58:37 -0700342
Neeti Desai127b9e02012-03-20 16:11:23 -0700343 cmd.img_ptr = (uint32*) img_ptr;
344 cmd.img_len_ptr = img_len_ptr;
Shashank Mittal162244e2011-08-08 19:01:25 -0700345
Neeti Desai127b9e02012-03-20 16:11:23 -0700346 /* Image data is operated upon by TZ, which accesses only the main memory.
347 * It must be flushed/invalidated before and after TZ call.
348 */
349 arch_clean_invalidate_cache_range((addr_t) *img_ptr, *img_len_ptr);
Shashank Mittal162244e2011-08-08 19:01:25 -0700350
vijay kumare95092d2014-10-20 19:24:49 +0530351 if (!scm_arm_support)
352 {
353 ret = scm_call(SCM_SVC_SSD, SSD_ENCRYPT_ID, &cmd, sizeof(cmd), NULL, 0);
354 }
355 else
356 {
357 scm_arg.x0 = MAKE_SIP_SCM_CMD(SCM_SVC_SSD,SSD_ENCRYPT_ID);
vijay kumar83b50d62015-01-09 19:09:59 +0530358 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 -0800359 scm_arg.x2 = (uint32_t) cmd.img_ptr;
360 scm_arg.x3 = (uint32_t) cmd.img_len_ptr;
vijay kumare95092d2014-10-20 19:24:49 +0530361
362 ret = scm_call2(&scm_arg, NULL);
363 }
Shashank Mittal162244e2011-08-08 19:01:25 -0700364
Neeti Desai127b9e02012-03-20 16:11:23 -0700365 /* Values at img_ptr and img_len_ptr are updated by TZ. Must be invalidated
366 * before we use them.
Amol Jadi55e58da2011-11-17 14:03:34 -0800367 */
368 arch_clean_invalidate_cache_range((addr_t) img_ptr, sizeof(img_ptr));
Neeti Desai127b9e02012-03-20 16:11:23 -0700369 arch_clean_invalidate_cache_range((addr_t) img_len_ptr, sizeof(img_len_ptr));
Amol Jadi55e58da2011-11-17 14:03:34 -0800370
Neeti Desai127b9e02012-03-20 16:11:23 -0700371 /* Invalidate the updated image data */
372 arch_clean_invalidate_cache_range((addr_t) *img_ptr, *img_len_ptr);
Amol Jadi55e58da2011-11-17 14:03:34 -0800373
Shashank Mittal162244e2011-08-08 19:01:25 -0700374 return ret;
375}
376
Neeti Desai127b9e02012-03-20 16:11:23 -0700377/* SCM Decrypt Command */
378int decrypt_scm(uint32_t ** img_ptr, uint32_t * img_len_ptr)
379{
380 int ret;
381 img_req cmd;
382
Channagoud Kadabidd85e7f2014-08-05 19:58:37 -0700383 if (scm_arm_support)
384 {
385 dprintf(INFO, "%s:SCM call is not supported\n",__func__);
386 return -1;
387 }
388
Neeti Desai127b9e02012-03-20 16:11:23 -0700389 cmd.img_ptr = (uint32*) img_ptr;
390 cmd.img_len_ptr = img_len_ptr;
391
392 /* Image data is operated upon by TZ, which accesses only the main memory.
393 * It must be flushed/invalidated before and after TZ call.
394 */
395 arch_clean_invalidate_cache_range((addr_t) *img_ptr, *img_len_ptr);
396
397 ret = scm_call(SCM_SVC_SSD, SSD_DECRYPT_ID, &cmd, sizeof(cmd), NULL, 0);
398
399 /* Values at img_ptr and img_len_ptr are updated by TZ. Must be invalidated
400 * before we use them.
401 */
402 arch_clean_invalidate_cache_range((addr_t) img_ptr, sizeof(img_ptr));
403 arch_clean_invalidate_cache_range((addr_t) img_len_ptr, sizeof(img_len_ptr));
404
405 /* Invalidate the updated image data */
406 arch_clean_invalidate_cache_range((addr_t) *img_ptr, *img_len_ptr);
407
408 return ret;
409}
410
411
sundarajan srinivasan4dfd4f72013-02-27 14:13:09 -0800412static int ssd_image_is_encrypted(uint32_t ** img_ptr, uint32_t * img_len_ptr, uint32 * ctx_id)
413{
sundarajan srinivasan6173b872013-03-13 17:36:48 -0700414 int ret = 0;
sundarajan srinivasan4dfd4f72013-02-27 14:13:09 -0800415 ssd_parse_md_req parse_req;
416 ssd_parse_md_rsp parse_rsp;
sundarajan srinivasan6173b872013-03-13 17:36:48 -0700417 int prev_len = 0;
vijay kumare95092d2014-10-20 19:24:49 +0530418 scmcall_arg scm_arg = {0};
419 scmcall_ret scm_ret = {0};
sundarajan srinivasan6173b872013-03-13 17:36:48 -0700420 /* Populate meta-data ptr. Here md_len is the meta-data length.
421 * The Code below follows a growing length approach. First send
422 * min(img_len_ptr,SSD_HEADER_MIN_SIZE) say 128 bytes for example.
423 * If parse_rsp.status = PARSING_INCOMPLETE we send md_len = 256.
424 * If subsequent status = PARSING_INCOMPLETE we send md_len = 512,
425 * 1024bytes and so on until we get an valid response(rsp.status) from TZ*/
426
sundarajan srinivasan4dfd4f72013-02-27 14:13:09 -0800427 parse_req.md = (uint32*)*img_ptr;
sundarajan srinivasan6173b872013-03-13 17:36:48 -0700428 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 -0800429
sundarajan srinivasan6173b872013-03-13 17:36:48 -0700430 arch_clean_invalidate_cache_range((addr_t) *img_ptr, parse_req.md_len);
sundarajan srinivasan4dfd4f72013-02-27 14:13:09 -0800431
sundarajan srinivasan6173b872013-03-13 17:36:48 -0700432 do
433 {
vijay kumare95092d2014-10-20 19:24:49 +0530434 if (!scm_arm_support)
435 {
436 ret = scm_call(SCM_SVC_SSD,
437 SSD_PARSE_MD_ID,
438 &parse_req,
439 sizeof(parse_req),
440 &parse_rsp,
441 sizeof(parse_rsp));
442 }
443 else
444 {
445 scm_arg.x0 = MAKE_SIP_SCM_CMD(SCM_SVC_SSD, SSD_PARSE_MD_ID);
446 scm_arg.x1 = MAKE_SCM_ARGS(0x2,SMC_PARAM_TYPE_VALUE,SMC_PARAM_TYPE_BUFFER_READWRITE);
447 scm_arg.x2 = parse_req.md_len;
Veera Sundaram Sankaran00181512014-12-09 11:23:39 -0800448 scm_arg.x3 = (uint32_t) parse_req.md;
Aparna Mallavarapud83990a2014-12-24 12:54:35 +0530449 scm_arg.atomic = true;
sundarajan srinivasan6173b872013-03-13 17:36:48 -0700450
vijay kumare95092d2014-10-20 19:24:49 +0530451 ret = scm_call2(&scm_arg, &scm_ret);
452 parse_rsp.status = scm_ret.x1;
453 }
sundarajan srinivasan6173b872013-03-13 17:36:48 -0700454 if(!ret && (parse_rsp.status == SSD_PMD_PARSING_INCOMPLETE))
455 {
456 prev_len = parse_req.md_len;
457
458 parse_req.md_len *= MULTIPLICATION_FACTOR;
459
Venkatesh Yadav Abbarapuaf7bfe02013-11-11 16:56:04 +0530460 arch_clean_invalidate_cache_range((addr_t) (*img_ptr + prev_len),
sundarajan srinivasan6173b872013-03-13 17:36:48 -0700461 (parse_req.md_len - prev_len) );
462
463 continue;
464 }
465 else
466 break;
467
468 } while(true);
sundarajan srinivasan4dfd4f72013-02-27 14:13:09 -0800469
470 if(!ret)
471 {
472 if(parse_rsp.status == SSD_PMD_ENCRYPTED)
473 {
474 *ctx_id = parse_rsp.md_ctx_id;
Sundarajan Srinivasaneb6d2202013-06-04 14:24:10 -0700475 *img_len_ptr = *img_len_ptr - ((uint8_t*)parse_rsp.md_end_ptr - (uint8_t*)*img_ptr);
sundarajan srinivasan4dfd4f72013-02-27 14:13:09 -0800476 *img_ptr = (uint32_t*)parse_rsp.md_end_ptr;
sundarajan srinivasan4dfd4f72013-02-27 14:13:09 -0800477 }
Sundarajan Srinivasaneb6d2202013-06-04 14:24:10 -0700478
479 ret = parse_rsp.status;
sundarajan srinivasan4dfd4f72013-02-27 14:13:09 -0800480 }
sundarajan srinivasan6173b872013-03-13 17:36:48 -0700481 else
482 {
483 dprintf(CRITICAL,"ssd_image_is_encrypted call failed");
484
485 ASSERT(ret == 0);
486 }
sundarajan srinivasan4dfd4f72013-02-27 14:13:09 -0800487
488 return ret;
489}
490
491int decrypt_scm_v2(uint32_t ** img_ptr, uint32_t * img_len_ptr)
492{
493 int ret = 0;
494 uint32 ctx_id = 0;
495 ssd_decrypt_img_frag_req decrypt_req;
496 ssd_decrypt_img_frag_rsp decrypt_rsp;
vijay kumare95092d2014-10-20 19:24:49 +0530497 scmcall_arg scm_arg = {0};
498 scmcall_ret scm_ret = {0};
sundarajan srinivasan4dfd4f72013-02-27 14:13:09 -0800499
Channagoud Kadabidd85e7f2014-08-05 19:58:37 -0700500
Sundarajan Srinivasaneb6d2202013-06-04 14:24:10 -0700501 ret = ssd_image_is_encrypted(img_ptr,img_len_ptr,&ctx_id);
502 switch(ret)
sundarajan srinivasan6173b872013-03-13 17:36:48 -0700503 {
Sundarajan Srinivasaneb6d2202013-06-04 14:24:10 -0700504 case SSD_PMD_ENCRYPTED:
505 /* Image data is operated upon by TZ, which accesses only the main memory.
506 * It must be flushed/invalidated before and after TZ call.
507 */
sundarajan srinivasan4dfd4f72013-02-27 14:13:09 -0800508
Sundarajan Srinivasaneb6d2202013-06-04 14:24:10 -0700509 arch_clean_invalidate_cache_range((addr_t) *img_ptr, *img_len_ptr);
sundarajan srinivasan4dfd4f72013-02-27 14:13:09 -0800510
Sundarajan Srinivasaneb6d2202013-06-04 14:24:10 -0700511 /*decrypt the image here*/
sundarajan srinivasan4dfd4f72013-02-27 14:13:09 -0800512
Sundarajan Srinivasaneb6d2202013-06-04 14:24:10 -0700513 decrypt_req.md_ctx_id = ctx_id;
514 decrypt_req.last_frag = 1;
515 decrypt_req.frag_len = *img_len_ptr;
516 decrypt_req.frag = *img_ptr;
sundarajan srinivasan4dfd4f72013-02-27 14:13:09 -0800517
vijay kumare95092d2014-10-20 19:24:49 +0530518 if (!scm_arm_support)
519 {
520 ret = scm_call(SCM_SVC_SSD,
521 SSD_DECRYPT_IMG_FRAG_ID,
522 &decrypt_req,
523 sizeof(decrypt_req),
524 &decrypt_rsp,
525 sizeof(decrypt_rsp));
526 }
527 else
528 {
529 scm_arg.x0 = MAKE_SIP_SCM_CMD(SCM_SVC_SSD, SSD_DECRYPT_IMG_FRAG_ID);
530 scm_arg.x1 = MAKE_SCM_ARGS(0x4,SMC_PARAM_TYPE_VALUE,SMC_PARAM_TYPE_VALUE,SMC_PARAM_TYPE_VALUE,SMC_PARAM_TYPE_BUFFER_READWRITE);
531 scm_arg.x2 = decrypt_req.md_ctx_id;
532 scm_arg.x3 = decrypt_req.last_frag;
533 scm_arg.x4 = decrypt_req.frag_len;
Veera Sundaram Sankaran00181512014-12-09 11:23:39 -0800534 scm_arg.x5[0] = (uint32_t) decrypt_req.frag;
sundarajan srinivasan4dfd4f72013-02-27 14:13:09 -0800535
vijay kumare95092d2014-10-20 19:24:49 +0530536 ret = scm_call2(&scm_arg, &scm_ret);
537 decrypt_rsp.status = scm_ret.x1;
538 }
Sundarajan Srinivasaneb6d2202013-06-04 14:24:10 -0700539 if(!ret){
540 ret = decrypt_rsp.status;
541 }
sundarajan srinivasan6173b872013-03-13 17:36:48 -0700542
Sundarajan Srinivasaneb6d2202013-06-04 14:24:10 -0700543 /* Values at img_ptr and img_len_ptr are updated by TZ. Must be invalidated
544 * before we use them.
545 */
546 arch_invalidate_cache_range((addr_t) img_ptr, sizeof(img_ptr));
547 arch_invalidate_cache_range((addr_t) img_len_ptr, sizeof(img_len_ptr));
sundarajan srinivasan4dfd4f72013-02-27 14:13:09 -0800548
Sundarajan Srinivasaneb6d2202013-06-04 14:24:10 -0700549 /* Invalidate the updated image data */
550 arch_invalidate_cache_range((addr_t) *img_ptr, *img_len_ptr);
sundarajan srinivasan6173b872013-03-13 17:36:48 -0700551
Sundarajan Srinivasaneb6d2202013-06-04 14:24:10 -0700552 break;
553
554 case SSD_PMD_NOT_ENCRYPTED:
555 case SSD_PMD_NO_MD_FOUND:
556 ret = 0;
557 break;
558
559 case SSD_PMD_BUSY:
560 case SSD_PMD_BAD_MD_PTR_OR_LEN:
561 case SSD_PMD_PARSING_INCOMPLETE:
562 case SSD_PMD_PARSING_FAILED:
563 case SSD_PMD_SETUP_CIPHER_FAILED:
564 dprintf(CRITICAL,"decrypt_scm_v2: failed status %d\n",ret);
565 break;
566
567 default:
568 dprintf(CRITICAL,"decrypt_scm_v2: case default: failed status %d\n",ret);
569 break;
sundarajan srinivasan6173b872013-03-13 17:36:48 -0700570 }
sundarajan srinivasan4dfd4f72013-02-27 14:13:09 -0800571 return ret;
572}
573
574int scm_svc_version(uint32 * major, uint32 * minor)
575{
576 feature_version_req feature_req;
577 feature_version_rsp feature_rsp;
578 int ret = 0;
Channagoud Kadabidd85e7f2014-08-05 19:58:37 -0700579 scmcall_arg scm_arg = {0};
580 scmcall_ret scm_ret = {0};
sundarajan srinivasan4dfd4f72013-02-27 14:13:09 -0800581
582 feature_req.feature_id = TZBSP_FVER_SSD;
583
Channagoud Kadabidd85e7f2014-08-05 19:58:37 -0700584 if (!scm_arm_support)
585 {
586 ret = scm_call(TZBSP_SVC_INFO,
587 TZ_INFO_GET_FEATURE_ID,
588 &feature_req,
589 sizeof(feature_req),
590 &feature_rsp,
591 sizeof(feature_rsp));
592 }
593 else
594 {
595 scm_arg.x0 = MAKE_SIP_SCM_CMD(TZBSP_SVC_INFO, TZ_INFO_GET_FEATURE_ID);
vijay kumare95092d2014-10-20 19:24:49 +0530596 scm_arg.x1 = MAKE_SCM_ARGS(0x1,SMC_PARAM_TYPE_VALUE);
Channagoud Kadabidd85e7f2014-08-05 19:58:37 -0700597 scm_arg.x2 = feature_req.feature_id;
598
599 ret = scm_call2(&scm_arg, &scm_ret);
600 feature_rsp.version = scm_ret.x1;
601 }
602
sundarajan srinivasan4dfd4f72013-02-27 14:13:09 -0800603 if(!ret)
604 *major = TZBSP_GET_FEATURE_VERSION(feature_rsp.version);
605
606 return ret;
607}
608
Amit Blaybdfabc62015-01-29 22:04:13 +0200609int scm_svc_get_secure_state(uint32_t *state_low, uint32_t *state_high)
610{
611 get_secure_state_req req;
612 get_secure_state_rsp rsp;
613
614 int ret = 0;
615
616 scmcall_arg scm_arg = {0};
617 scmcall_ret scm_ret = {0};
618
619 if (!scm_arm_support)
620 {
621 req.status_ptr = (uint32_t*)&rsp;
622 req.status_len = sizeof(rsp);
623
624 ret = scm_call(TZBSP_SVC_INFO,
625 TZ_INFO_GET_SECURE_STATE,
626 &req,
627 sizeof(req),
628 NULL,
629 0);
630 }
631 else
632 {
633 scm_arg.x0 = MAKE_SIP_SCM_CMD(TZBSP_SVC_INFO, TZ_INFO_GET_SECURE_STATE);
634 scm_arg.x1 = MAKE_SCM_ARGS(0x0);
635
636 ret = scm_call2(&scm_arg, &scm_ret);
637
638 rsp.status_low = scm_ret.x1;
639 rsp.status_high = scm_ret.x2;
640 }
641
642 if(!ret)
643 {
644 *state_low = rsp.status_low;
645 *state_high = rsp.status_high;
646 }
647
648 return ret;
649}
650
sundarajan srinivasan4dfd4f72013-02-27 14:13:09 -0800651int scm_protect_keystore(uint32_t * img_ptr, uint32_t img_len)
652{
653 int ret=0;
654 ssd_protect_keystore_req protect_req;
655 ssd_protect_keystore_rsp protect_rsp;
vijay kumare95092d2014-10-20 19:24:49 +0530656 scmcall_arg scm_arg = {0};
657 scmcall_ret scm_ret = {0};
Channagoud Kadabidd85e7f2014-08-05 19:58:37 -0700658
sundarajan srinivasan4dfd4f72013-02-27 14:13:09 -0800659 protect_req.keystore_ptr = img_ptr;
660 protect_req.keystore_len = img_len;
661
662 arch_clean_invalidate_cache_range((addr_t) img_ptr, img_len);
663
vijay kumare95092d2014-10-20 19:24:49 +0530664 if (!scm_arm_support)
665 {
666 ret = scm_call(SCM_SVC_SSD,
667 SSD_PROTECT_KEYSTORE_ID,
668 &protect_req,
669 sizeof(protect_req),
670 &protect_rsp,
671 sizeof(protect_rsp));
672 }
673 else
674 {
675 scm_arg.x0 = MAKE_SIP_SCM_CMD(SCM_SVC_SSD, SSD_PROTECT_KEYSTORE_ID);
676 scm_arg.x1 = MAKE_SCM_ARGS(0x2,SMC_PARAM_TYPE_BUFFER_READWRITE,SMC_PARAM_TYPE_VALUE);
Veera Sundaram Sankaran00181512014-12-09 11:23:39 -0800677 scm_arg.x2 = (uint32_t) protect_req.keystore_ptr;
vijay kumare95092d2014-10-20 19:24:49 +0530678 scm_arg.x3 = protect_req.keystore_len;
679
680 ret = scm_call2(&scm_arg, &scm_ret);
681 protect_rsp.status = scm_ret.x1;
682 }
sundarajan srinivasan4dfd4f72013-02-27 14:13:09 -0800683 if(!ret)
684 {
685 if(protect_rsp.status == TZBSP_SSD_PKS_SUCCESS)
686 dprintf(INFO,"Successfully loaded the keystore ");
687 else
688 {
689 dprintf(INFO,"Loading keystore failed status %d ",protect_rsp.status);
690 ret = protect_rsp.status;
691 }
692 }
693 else
694 dprintf(INFO,"scm_call failed ");
695
696 return ret;
697}
698
Shashank Mittal162244e2011-08-08 19:01:25 -0700699void set_tamper_fuse_cmd()
700{
701 uint32_t svc_id;
702 uint32_t cmd_id;
703 void *cmd_buf;
704 size_t cmd_len;
705 void *resp_buf = NULL;
706 size_t resp_len = 0;
vijay kumare95092d2014-10-20 19:24:49 +0530707 scmcall_arg scm_arg = {0};
Shashank Mittal162244e2011-08-08 19:01:25 -0700708
709 uint32_t fuse_id = HLOS_IMG_TAMPER_FUSE;
710 cmd_buf = (void *)&fuse_id;
711 cmd_len = sizeof(fuse_id);
712
vijay kumare95092d2014-10-20 19:24:49 +0530713 if (!scm_arm_support)
Channagoud Kadabidd85e7f2014-08-05 19:58:37 -0700714 {
vijay kumare95092d2014-10-20 19:24:49 +0530715 /*no response */
716 resp_buf = NULL;
717 resp_len = 0;
718
719 svc_id = SCM_SVC_FUSE;
720 cmd_id = SCM_BLOW_SW_FUSE_ID;
721
722 scm_call(svc_id, cmd_id, cmd_buf, cmd_len, resp_buf, resp_len);
723 }
724 else
725 {
726 scm_arg.x0 = MAKE_SIP_SCM_CMD(SCM_SVC_FUSE, SCM_BLOW_SW_FUSE_ID);
727 scm_arg.x1 = MAKE_SCM_ARGS(0x2,SMC_PARAM_TYPE_BUFFER_READWRITE,SMC_PARAM_TYPE_VALUE);
Veera Sundaram Sankaran00181512014-12-09 11:23:39 -0800728 scm_arg.x2 = (uint32_t) cmd_buf;
vijay kumare95092d2014-10-20 19:24:49 +0530729 scm_arg.x3 = cmd_len;
730
731 scm_call2(&scm_arg, NULL);
732
Channagoud Kadabidd85e7f2014-08-05 19:58:37 -0700733 }
734
Shashank Mittal162244e2011-08-08 19:01:25 -0700735}
736
737uint8_t get_tamper_fuse_cmd()
738{
739 uint32_t svc_id;
740 uint32_t cmd_id;
741 void *cmd_buf;
742 size_t cmd_len;
743 size_t resp_len = 0;
744 uint8_t resp_buf;
745
746 uint32_t fuse_id = HLOS_IMG_TAMPER_FUSE;
vijay kumare95092d2014-10-20 19:24:49 +0530747 scmcall_arg scm_arg = {0};
748 scmcall_ret scm_ret = {0};
Channagoud Kadabidd85e7f2014-08-05 19:58:37 -0700749
Shashank Mittal162244e2011-08-08 19:01:25 -0700750 cmd_buf = (void *)&fuse_id;
751 cmd_len = sizeof(fuse_id);
752
vijay kumare95092d2014-10-20 19:24:49 +0530753 if (!scm_arm_support)
754 {
755 /*response */
756 resp_len = sizeof(resp_buf);
Shashank Mittal162244e2011-08-08 19:01:25 -0700757
vijay kumare95092d2014-10-20 19:24:49 +0530758 svc_id = SCM_SVC_FUSE;
759 cmd_id = SCM_IS_SW_FUSE_BLOWN_ID;
Shashank Mittal162244e2011-08-08 19:01:25 -0700760
vijay kumare95092d2014-10-20 19:24:49 +0530761 scm_call(svc_id, cmd_id, cmd_buf, cmd_len, &resp_buf, resp_len);
762 return resp_buf;
763 }
764 else
765 {
766 scm_arg.x0 = MAKE_SIP_SCM_CMD(SCM_SVC_FUSE, SCM_IS_SW_FUSE_BLOWN_ID);
767 scm_arg.x1 = MAKE_SCM_ARGS(0x2,SMC_PARAM_TYPE_BUFFER_READWRITE,SMC_PARAM_TYPE_VALUE);
Veera Sundaram Sankaran00181512014-12-09 11:23:39 -0800768 scm_arg.x2 = (uint32_t) cmd_buf;
vijay kumare95092d2014-10-20 19:24:49 +0530769 scm_arg.x3 = cmd_len;
770
771 scm_call2(&scm_arg, &scm_ret);
772 return (uint8_t)scm_ret.x1;
773 }
Shashank Mittal162244e2011-08-08 19:01:25 -0700774}
Deepa Dinamani193874e2012-02-07 14:00:04 -0800775
Amir Samuelov4620ad22013-03-13 11:30:05 +0200776/*
777 * struct qseecom_save_partition_hash_req
778 * @partition_id - partition id.
779 * @digest[SHA256_DIGEST_LENGTH] - sha256 digest.
780 */
781struct qseecom_save_partition_hash_req {
782 uint32_t partition_id; /* in */
783 uint8_t digest[SHA256_DIGEST_LENGTH]; /* in */
784};
785
786
787void save_kernel_hash_cmd(void *digest)
788{
789 uint32_t svc_id;
790 uint32_t cmd_id;
791 void *cmd_buf;
792 size_t cmd_len;
793 void *resp_buf = NULL;
794 size_t resp_len = 0;
795 struct qseecom_save_partition_hash_req req;
Channagoud Kadabidd85e7f2014-08-05 19:58:37 -0700796 scmcall_arg scm_arg = {0};
Amir Samuelov4620ad22013-03-13 11:30:05 +0200797
798 /*no response */
799 resp_buf = NULL;
800 resp_len = 0;
801
802 req.partition_id = 0; /* kernel */
803 memcpy(req.digest, digest, sizeof(req.digest));
804
Channagoud Kadabidd85e7f2014-08-05 19:58:37 -0700805 if (!scm_arm_support)
806 {
807 svc_id = SCM_SVC_ES;
808 cmd_id = SCM_SAVE_PARTITION_HASH_ID;
809 cmd_buf = (void *)&req;
810 cmd_len = sizeof(req);
Amir Samuelov4620ad22013-03-13 11:30:05 +0200811
Channagoud Kadabidd85e7f2014-08-05 19:58:37 -0700812 scm_call(svc_id, cmd_id, cmd_buf, cmd_len, resp_buf, resp_len);
813 }
814 else
815 {
816 scm_arg.x0 = MAKE_SIP_SCM_CMD(SCM_SVC_ES, SCM_SAVE_PARTITION_HASH_ID);
817 scm_arg.x1 = MAKE_SCM_ARGS(0x3, 0, SMC_PARAM_TYPE_BUFFER_READWRITE);
818 scm_arg.x2 = req.partition_id;
Veera Sundaram Sankaran00181512014-12-09 11:23:39 -0800819 scm_arg.x3 = (uint32_t) &req.digest;
Channagoud Kadabidd85e7f2014-08-05 19:58:37 -0700820 scm_arg.x4 = sizeof(req.digest);
821
822 if (scm_call2(&scm_arg, NULL))
823 dprintf(CRITICAL, "Failed to Save kernel hash\n");
824 }
Amir Samuelov4620ad22013-03-13 11:30:05 +0200825}
826
Amit Blayfe23ee22015-01-09 19:09:51 +0200827int mdtp_cipher_dip_cmd(uint8_t *in_buf, uint32_t in_buf_size, uint8_t *out_buf,
828 uint32_t out_buf_size, uint32_t direction)
829{
830 uint32_t svc_id;
831 uint32_t cmd_id;
832 void *cmd_buf;
833 void *rsp_buf;
834 size_t cmd_len;
835 size_t rsp_len;
836 mdtp_cipher_dip_req req;
837 scmcall_arg scm_arg = {0};
838 scmcall_ret scm_ret = {0};
839
840 ASSERT(in_buf != NULL);
841 ASSERT(out_buf != NULL);
842
843 req.in_buf = in_buf;
844 req.in_buf_size = in_buf_size;
845 req.out_buf = out_buf;
846 req.out_buf_size = out_buf_size;
847 req.direction = direction;
848
849 if (!scm_arm_support)
850 {
851 svc_id = SCM_SVC_MDTP;
852 cmd_id = SCM_MDTP_CIPHER_DIP;
853 cmd_buf = (void *)&req;
854 cmd_len = sizeof(req);
855 rsp_buf = NULL;
856 rsp_len = 0;
857
858 if (scm_call(svc_id, cmd_id, cmd_buf, cmd_len, rsp_buf, rsp_len))
859 {
860 dprintf(CRITICAL, "Failed to call Cipher DIP SCM\n");
861 return -1;
862 }
863 }
864 else
865 {
866 scm_arg.x0 = MAKE_SIP_SCM_CMD(SCM_SVC_MDTP, SCM_MDTP_CIPHER_DIP);
867 scm_arg.x1 = MAKE_SCM_ARGS(0x5, SMC_PARAM_TYPE_BUFFER_READ, SMC_PARAM_TYPE_VALUE,
868 SMC_PARAM_TYPE_BUFFER_READWRITE, SMC_PARAM_TYPE_VALUE, SMC_PARAM_TYPE_VALUE);
869 scm_arg.x2 = (uint32_t)req.in_buf;
870 scm_arg.x3 = req.in_buf_size;
871 scm_arg.x4 = (uint32_t)req.out_buf;
872 scm_arg.x5[0] = req.out_buf_size;
873 scm_arg.x5[1] = req.direction;
874
875 if (scm_call2(&scm_arg, &scm_ret))
876 {
877 dprintf(CRITICAL, "Failed in Cipher DIP SCM call\n");
878 return -1;
879 }
880 }
881
882 return 0;
883}
884
Amit Blaybdfabc62015-01-29 22:04:13 +0200885int qfprom_read_row_cmd(uint32_t row_address,
886 uint32_t addr_type,
887 uint32_t *row_data,
888 uint32_t *qfprom_api_status)
889{
890 uint32_t svc_id;
891 uint32_t cmd_id;
892 void *cmd_buf;
893 void *rsp_buf;
894 size_t cmd_len;
895 size_t rsp_len;
896 qfprom_read_row_req req;
897 scmcall_arg scm_arg = {0};
898 scmcall_ret scm_ret = {0};
899
900 req.row_address = row_address;
901 req.addr_type = addr_type;
902 req.row_data = row_data;
903 req.qfprom_api_status = qfprom_api_status;
904
905 if (!scm_arm_support)
906 {
907 svc_id = SCM_SVC_FUSE;
908 cmd_id = SCM_QFPROM_READ_ROW_ID;
909 cmd_buf = (void *)&req;
910 cmd_len = sizeof(req);
911 rsp_buf = NULL;
912 rsp_len = 0;
913
914 if (scm_call(svc_id, cmd_id, cmd_buf, cmd_len, rsp_buf, rsp_len))
915 {
916 dprintf(CRITICAL, "Failed to call SCM_SVC_FUSE.SCM_QFPROM_READ_ROW_ID SCM\n");
917 return -1;
918 }
919 }
920 else
921 {
922 scm_arg.x0 = MAKE_SIP_SCM_CMD(SCM_SVC_FUSE, SCM_QFPROM_READ_ROW_ID);
923 scm_arg.x1 = MAKE_SCM_ARGS(0x4, SMC_PARAM_TYPE_VALUE, SMC_PARAM_TYPE_VALUE,
924 SMC_PARAM_TYPE_BUFFER_READWRITE, SMC_PARAM_TYPE_BUFFER_READWRITE);
925 scm_arg.x2 = req.row_address;
926 scm_arg.x3 = req.addr_type;
927 scm_arg.x4 = (uint32_t)req.row_data;
928 scm_arg.x5[0] = (uint32_t)req.qfprom_api_status;
929
930 if (scm_call2(&scm_arg, &scm_ret))
931 {
932 dprintf(CRITICAL, "Failed to call SCM_SVC_FUSE.SCM_QFPROM_READ_ROW_ID SCM\n");
933 return -1;
934 }
935 }
936
937 return 0;
938}
939
Deepa Dinamani193874e2012-02-07 14:00:04 -0800940/*
941 * Switches the CE1 channel between ADM and register usage.
942 * channel : AP_CE_REGISTER_USE, CE1 uses register interface
943 * : AP_CE_ADM_USE, CE1 uses ADM interface
944 */
945uint8_t switch_ce_chn_cmd(enum ap_ce_channel_type channel)
946{
947 uint32_t svc_id;
948 uint32_t cmd_id;
949 void *cmd_buf;
950 size_t cmd_len;
951 size_t resp_len = 0;
952 uint8_t resp_buf;
953
954 struct {
955 uint32_t resource;
956 uint32_t chn_id;
957 }__PACKED switch_ce_chn_buf;
958
Channagoud Kadabidd85e7f2014-08-05 19:58:37 -0700959 if (scm_arm_support)
960 {
961 dprintf(INFO, "%s:SCM call is not supported\n",__func__);
962 return 0;
963 }
964
Deepa Dinamani193874e2012-02-07 14:00:04 -0800965 switch_ce_chn_buf.resource = TZ_RESOURCE_CE_AP;
966 switch_ce_chn_buf.chn_id = channel;
967 cmd_buf = (void *)&switch_ce_chn_buf;
968 cmd_len = sizeof(switch_ce_chn_buf);
969
970 /*response */
971 resp_len = sizeof(resp_buf);
972
973 svc_id = SCM_SVC_CE_CHN_SWITCH_ID;
974 cmd_id = SCM_CE_CHN_SWITCH_ID;
975
976 scm_call(svc_id, cmd_id, cmd_buf, cmd_len, &resp_buf, resp_len);
977 return resp_buf;
978}
979
Channagoud Kadabi179df0b2013-12-12 14:53:31 -0800980int scm_halt_pmic_arbiter()
981{
982 int ret = 0;
Aparna Mallavarapu246c30b2014-12-11 12:07:51 +0530983 scmcall_arg scm_arg = {0};
Channagoud Kadabi179df0b2013-12-12 14:53:31 -0800984
Aparna Mallavarapu246c30b2014-12-11 12:07:51 +0530985 if (scm_arm_support) {
986 scm_arg.x0 = MAKE_SIP_SCM_CMD(SCM_SVC_PWR, SCM_IO_DISABLE_PMIC_ARBITER);
987 scm_arg.x1 = MAKE_SCM_ARGS(0x1);
988 scm_arg.x2 = 0;
989 scm_arg.atomic = true;
990 ret = scm_call2(&scm_arg, NULL);
991 } else {
992 ret = scm_call_atomic(SCM_SVC_PWR, SCM_IO_DISABLE_PMIC_ARBITER, 0);
Channagoud Kadabidd85e7f2014-08-05 19:58:37 -0700993 }
994
Aparna Mallavarapu246c30b2014-12-11 12:07:51 +0530995 /* Retry with the SCM_IO_DISABLE_PMIC_ARBITER1 func ID if the above Func ID fails*/
996 if(ret) {
997 if (scm_arm_support) {
998 scm_arg.x0 = MAKE_SIP_SCM_CMD(SCM_SVC_PWR, SCM_IO_DISABLE_PMIC_ARBITER1);
999 scm_arg.x1 = MAKE_SCM_ARGS(0x1);
1000 scm_arg.x2 = 0;
1001 scm_arg.atomic = true;
1002 ret = scm_call2(&scm_arg, NULL);
1003 } else
1004 ret = scm_call_atomic(SCM_SVC_PWR, SCM_IO_DISABLE_PMIC_ARBITER1, 0);
1005 }
Channagoud Kadabi179df0b2013-12-12 14:53:31 -08001006
1007 return ret;
1008}
Abhimanyu Kapurb3207fb2014-01-27 21:33:23 -08001009
1010/* Execption Level exec secure-os call
1011 * Jumps to kernel via secure-os and does not return
1012 * on successful jump. System parameters are setup &
1013 * passed on to secure-os and are utilized to boot the
1014 * kernel.
1015 *
1016 @ kernel_entry : kernel entry point passed in as link register.
1017 @ dtb_offset : dt blob address passed in as w0.
1018 @ svc_id : indicates direction of switch 32->64 or 64->32
1019 *
1020 * Assumes all sanity checks have been performed on arguments.
1021 */
1022
1023void scm_elexec_call(paddr_t kernel_entry, paddr_t dtb_offset)
1024{
1025 uint32_t svc_id = SCM_SVC_MILESTONE_32_64_ID;
1026 uint32_t cmd_id = SCM_SVC_MILESTONE_CMD_ID;
1027 void *cmd_buf;
1028 size_t cmd_len;
Sridhar Parasuramfc6ea712015-06-30 11:22:49 -07001029 static el1_system_param param __attribute__((aligned(0x1000)));
Channagoud Kadabidd85e7f2014-08-05 19:58:37 -07001030 scmcall_arg scm_arg = {0};
Abhimanyu Kapurb3207fb2014-01-27 21:33:23 -08001031
1032 param.el1_x0 = dtb_offset;
1033 param.el1_elr = kernel_entry;
1034
Abhimanyu Kapurb3207fb2014-01-27 21:33:23 -08001035 /* Response Buffer = Null as no response expected */
1036 dprintf(INFO, "Jumping to kernel via monitor\n");
Channagoud Kadabidd85e7f2014-08-05 19:58:37 -07001037
1038 if (!scm_arm_support)
1039 {
1040 /* Command Buffer */
1041 cmd_buf = (void *)&param;
1042 cmd_len = sizeof(el1_system_param);
1043
1044 scm_call(svc_id, cmd_id, cmd_buf, cmd_len, NULL, 0);
1045 }
1046 else
1047 {
1048 scm_arg.x0 = MAKE_SIP_SCM_CMD(SCM_SVC_MILESTONE_32_64_ID, SCM_SVC_MILESTONE_CMD_ID);
1049 scm_arg.x1 = MAKE_SCM_ARGS(0x2, SMC_PARAM_TYPE_BUFFER_READ);
Veera Sundaram Sankaran00181512014-12-09 11:23:39 -08001050 scm_arg.x2 = (uint32_t ) &param;
Channagoud Kadabidd85e7f2014-08-05 19:58:37 -07001051 scm_arg.x3 = sizeof(el1_system_param);
1052
1053 scm_call2(&scm_arg, NULL);
1054 }
Abhimanyu Kapurb3207fb2014-01-27 21:33:23 -08001055
1056 /* Assert if execution ever reaches here */
1057 dprintf(CRITICAL, "Failed to jump to kernel\n");
1058 ASSERT(0);
1059}
Maria Yubeeeeaf2014-06-30 13:05:43 +08001060
1061/* SCM Random Command */
1062int scm_random(uint32_t * rbuf, uint32_t r_len)
1063{
1064 int ret;
1065 struct tz_prng_data data;
Channagoud Kadabidd85e7f2014-08-05 19:58:37 -07001066 scmcall_arg scm_arg = {0};
Maria Yubeeeeaf2014-06-30 13:05:43 +08001067
Channagoud Kadabidd85e7f2014-08-05 19:58:37 -07001068 if (!scm_arm_support)
1069 {
1070 data.out_buf = (uint8_t*) rbuf;
1071 data.out_buf_size = r_len;
Maria Yubeeeeaf2014-06-30 13:05:43 +08001072
Channagoud Kadabidd85e7f2014-08-05 19:58:37 -07001073 /*
1074 * random buffer must be flushed/invalidated before and after TZ call.
1075 */
1076 arch_clean_invalidate_cache_range((addr_t) rbuf, r_len);
Maria Yubeeeeaf2014-06-30 13:05:43 +08001077
Channagoud Kadabidd85e7f2014-08-05 19:58:37 -07001078 ret = scm_call(TZ_SVC_CRYPTO, PRNG_CMD_ID, &data, sizeof(data), NULL, 0);
Maria Yubeeeeaf2014-06-30 13:05:43 +08001079
Channagoud Kadabidd85e7f2014-08-05 19:58:37 -07001080 /* Invalidate the updated random buffer */
1081 arch_clean_invalidate_cache_range((addr_t) rbuf, r_len);
1082 }
1083 else
1084 {
1085 scm_arg.x0 = MAKE_SIP_SCM_CMD(TZ_SVC_CRYPTO, PRNG_CMD_ID);
1086 scm_arg.x1 = MAKE_SCM_ARGS(0x2,SMC_PARAM_TYPE_BUFFER_READWRITE);
Veera Sundaram Sankaran00181512014-12-09 11:23:39 -08001087 scm_arg.x2 = (uint32_t) rbuf;
Channagoud Kadabidd85e7f2014-08-05 19:58:37 -07001088 scm_arg.x3 = r_len;
1089
1090 ret = scm_call2(&scm_arg, NULL);
1091 if (!ret)
1092 arch_clean_invalidate_cache_range((addr_t) rbuf, r_len);
1093 else
1094 dprintf(CRITICAL, "Secure canary SCM failed: %x\n", ret);
1095 }
Maria Yubeeeeaf2014-06-30 13:05:43 +08001096
1097 return ret;
1098}
1099
1100void * get_canary()
1101{
1102 void * canary;
vijay kumar4f4405f2014-08-08 11:49:53 +05301103 if(scm_random((uint32_t *)&canary, sizeof(canary))) {
Maria Yubeeeeaf2014-06-30 13:05:43 +08001104 dprintf(CRITICAL,"scm_call for random failed !!!");
1105 /*
1106 * fall back to use lib rand API if scm call failed.
1107 */
1108 canary = (void *)rand();
1109 }
1110
1111 return canary;
1112}
Aparna Mallavarapu6875ade2014-06-16 22:15:28 +05301113
1114int scm_xpu_err_fatal_init()
1115{
1116 uint32_t ret = 0;
1117 uint32_t response = 0;
1118 tz_xpu_prot_cmd cmd;
Channagoud Kadabidd85e7f2014-08-05 19:58:37 -07001119 scmcall_arg scm_arg = {0};
1120 scmcall_ret scm_ret = {0};
Aparna Mallavarapu6875ade2014-06-16 22:15:28 +05301121
Channagoud Kadabidd85e7f2014-08-05 19:58:37 -07001122 if (!scm_arm_support)
1123 {
1124 cmd.config = ERR_FATAL_ENABLE;
1125 cmd.spare = 0;
Aparna Mallavarapu6875ade2014-06-16 22:15:28 +05301126
Channagoud Kadabidd85e7f2014-08-05 19:58:37 -07001127 ret = scm_call(SVC_MEMORY_PROTECTION, XPU_ERR_FATAL, &cmd, sizeof(cmd), &response,
1128 sizeof(response));
1129 }
1130 else
1131 {
1132 scm_arg.x0 = MAKE_SIP_SCM_CMD(SVC_MEMORY_PROTECTION, XPU_ERR_FATAL);
1133 scm_arg.x1 = MAKE_SCM_ARGS(0x2);
1134 scm_arg.x2 = ERR_FATAL_ENABLE;
1135 scm_arg.x3 = 0x0;
1136 ret = scm_call2(&scm_arg, &scm_ret);
1137 response = scm_ret.x1;
1138 }
Aparna Mallavarapu6875ade2014-06-16 22:15:28 +05301139
1140 if (ret)
1141 dprintf(CRITICAL, "Failed to set XPU violations as fatal errors: %u\n", response);
1142 else
1143 dprintf(INFO, "Configured XPU violations to be fatal errors\n");
1144
1145 return ret;
1146}
Channagoud Kadabidd85e7f2014-08-05 19:58:37 -07001147
1148static 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)
1149{
1150 register uint32_t r0 __asm__("r0") = x0;
1151 register uint32_t r1 __asm__("r1") = x1;
1152 register uint32_t r2 __asm__("r2") = x2;
1153 register uint32_t r3 __asm__("r3") = x3;
1154 register uint32_t r4 __asm__("r4") = x4;
1155 register uint32_t r5 __asm__("r5") = x5;
Channagoud Kadabie75efb92015-05-19 14:20:05 -07001156 register uint32_t r6 __asm__("r6") = 0;
Channagoud Kadabidd85e7f2014-08-05 19:58:37 -07001157
Dinesh K Garg6bbbb702015-01-30 11:13:31 -08001158 do {
1159 __asm__ volatile(
1160 __asmeq("%0", "r0")
1161 __asmeq("%1", "r1")
1162 __asmeq("%2", "r2")
1163 __asmeq("%3", "r3")
1164 __asmeq("%4", "r0")
1165 __asmeq("%5", "r1")
1166 __asmeq("%6", "r2")
1167 __asmeq("%7", "r3")
1168 __asmeq("%8", "r4")
1169 __asmeq("%9", "r5")
Channagoud Kadabie75efb92015-05-19 14:20:05 -07001170 __asmeq("%10", "r6")
Dinesh K Garg6bbbb702015-01-30 11:13:31 -08001171 "smc #0 @ switch to secure world\n"
1172 : "=r" (r0), "=r" (r1), "=r" (r2), "=r" (r3)
Channagoud Kadabie75efb92015-05-19 14:20:05 -07001173 : "r" (r0), "r" (r1), "r" (r2), "r" (r3), "r" (r4), "r" (r5), "r" (r6));
Dinesh K Garg6bbbb702015-01-30 11:13:31 -08001174 } while(r0 == 1);
Channagoud Kadabidd85e7f2014-08-05 19:58:37 -07001175
1176 if (ret)
1177 {
1178 ret->x1 = r1;
1179 ret->x2 = r2;
1180 ret->x3 = r3;
1181 }
1182
1183 return r0;
1184}
1185
1186uint32_t scm_call2(scmcall_arg *arg, scmcall_ret *ret)
1187{
1188 uint32_t *indir_arg = NULL;
1189 uint32_t x5;
1190 int i;
1191 uint32_t rc;
1192
1193 arg->x0 = arg->atomic ? (arg->x0 | SCM_ATOMIC_BIT) : arg->x0;
1194 x5 = arg->x5[0];
1195
Amit Blayfe23ee22015-01-09 19:09:51 +02001196 if ((arg->x1 & 0xF) > SCM_MAX_ARG_LEN - 1)
Channagoud Kadabidd85e7f2014-08-05 19:58:37 -07001197 {
1198 indir_arg = memalign(CACHE_LINE, (SCM_INDIR_MAX_LEN * sizeof(uint32_t)));
1199 ASSERT(indir_arg);
1200
1201 for (i = 0 ; i < SCM_INDIR_MAX_LEN; i++)
1202 {
1203 indir_arg[i] = arg->x5[i];
1204 }
Channagoud Kadabicf3afe42015-08-07 16:08:08 -07001205 arch_clean_invalidate_cache_range((addr_t) indir_arg, (SCM_INDIR_MAX_LEN * sizeof(uint32_t)));
Channagoud Kadabidd85e7f2014-08-05 19:58:37 -07001206 x5 = (addr_t) indir_arg;
1207 }
1208
1209 rc = scm_call_a32(arg->x0, arg->x1, arg->x2, arg->x3, arg->x4, x5, ret);
1210
1211 if (rc)
1212 {
1213 dprintf(CRITICAL, "SCM call: 0x%x failed with :%x\n", arg->x0, rc);
1214 return rc;
1215 }
1216
1217 if (indir_arg)
1218 free(indir_arg);
1219
1220 return 0;
1221}
Aparna Mallavarapu246c30b2014-12-11 12:07:51 +05301222
Aparna Mallavarapu8adbee22015-03-10 19:58:06 +05301223static bool secure_boot_enabled = true;
1224static bool wdog_debug_fuse_disabled = true;
Aparna Mallavarapu246c30b2014-12-11 12:07:51 +05301225
1226void scm_check_boot_fuses()
1227{
1228 uint32_t ret = 0;
Aparna Mallavarapu664ea772015-02-24 18:44:33 +05301229 uint32_t resp;
Aparna Mallavarapu246c30b2014-12-11 12:07:51 +05301230 scmcall_arg scm_arg = {0};
1231 scmcall_ret scm_ret = {0};
1232
1233 if (!scm_arm_support) {
Aparna Mallavarapu664ea772015-02-24 18:44:33 +05301234 ret = scm_call(TZBSP_SVC_INFO, IS_SECURE_BOOT_ENABLED, NULL, 0, &resp, sizeof(resp));
Aparna Mallavarapu246c30b2014-12-11 12:07:51 +05301235 } else {
1236 scm_arg.x0 = MAKE_SIP_SCM_CMD(TZBSP_SVC_INFO, IS_SECURE_BOOT_ENABLED);
1237 ret = scm_call2(&scm_arg, &scm_ret);
Aparna Mallavarapu664ea772015-02-24 18:44:33 +05301238 resp = scm_ret.x1;
Aparna Mallavarapu246c30b2014-12-11 12:07:51 +05301239 }
1240
1241 /* Parse Bit 0 and Bit 2 of the response */
1242 if(!ret) {
1243 /* Bit 0 - SECBOOT_ENABLE_CHECK */
Aparna Mallavarapu664ea772015-02-24 18:44:33 +05301244 if(resp & 0x1)
Aparna Mallavarapu8adbee22015-03-10 19:58:06 +05301245 secure_boot_enabled = false;
Aparna Mallavarapu246c30b2014-12-11 12:07:51 +05301246 /* Bit 2 - DEBUG_DISABLE_CHECK */
Aparna Mallavarapu664ea772015-02-24 18:44:33 +05301247 if(resp & 0x4)
Aparna Mallavarapu8adbee22015-03-10 19:58:06 +05301248 wdog_debug_fuse_disabled = false;
Aparna Mallavarapu246c30b2014-12-11 12:07:51 +05301249 } else
1250 dprintf(CRITICAL, "scm call to check secure boot fuses failed\n");
1251}
1252
1253bool is_secure_boot_enable()
1254{
1255 scm_check_boot_fuses();
Aparna Mallavarapu8adbee22015-03-10 19:58:06 +05301256 return secure_boot_enabled;
Aparna Mallavarapu246c30b2014-12-11 12:07:51 +05301257}
1258
1259static uint32_t scm_io_read(addr_t address)
1260{
1261 uint32_t ret;
1262 scmcall_arg scm_arg = {0};
1263 scmcall_ret scm_ret = {0};
1264
1265 if (!scm_arm_support) {
1266 ret = scm_call_atomic(SCM_SVC_IO, SCM_IO_READ, address);
1267 } else {
1268 scm_arg.x0 = MAKE_SIP_SCM_CMD(SCM_SVC_IO, SCM_IO_READ);
1269 scm_arg.x1 = MAKE_SCM_ARGS(0x1);
1270 scm_arg.x2 = address;
1271 scm_arg.atomic = true;
1272 ret = scm_call2(&scm_arg, &scm_ret);
1273 }
1274 return ret;
1275}
1276
Aparna Mallavarapuda91ea92015-07-10 12:03:46 +05301277uint32_t scm_io_write(uint32_t address, uint32_t val)
Aparna Mallavarapu246c30b2014-12-11 12:07:51 +05301278{
1279 uint32_t ret;
1280 scmcall_arg scm_arg = {0};
1281 scmcall_ret scm_ret = {0};
1282
1283 if (!scm_arm_support) {
1284 ret = scm_call_atomic2(SCM_SVC_IO, SCM_IO_WRITE, address, val);
1285 } else {
1286 scm_arg.x0 = MAKE_SIP_SCM_CMD(SCM_SVC_IO, SCM_IO_WRITE);
1287 scm_arg.x1 = MAKE_SCM_ARGS(0x2);
1288 scm_arg.x2 = address;
1289 scm_arg.x3 = val;
1290 scm_arg.atomic = true;
1291 ret = scm_call2(&scm_arg, &scm_ret);
1292 }
1293 return ret;
1294}
Aparna Mallavarapu664ea772015-02-24 18:44:33 +05301295
Aparna Mallavarapuda91ea92015-07-10 12:03:46 +05301296int scm_call2_atomic(uint32_t svc, uint32_t cmd, uint32_t arg1, uint32_t arg2)
Aparna Mallavarapu664ea772015-02-24 18:44:33 +05301297{
1298 uint32_t ret = 0;
1299 scmcall_arg scm_arg = {0};
1300 scmcall_ret scm_ret = {0};
1301
1302 if (!scm_arm_support)
1303 {
1304 ret = scm_call_atomic2(svc, cmd, arg1, arg2);
1305 } else {
1306 scm_arg.x0 = MAKE_SIP_SCM_CMD(svc, cmd);
1307 scm_arg.x1 = MAKE_SCM_ARGS(0x2);
1308 scm_arg.x2 = arg1;
1309 scm_arg.x3 = arg2;
1310 ret = scm_call2(&scm_arg, &scm_ret);
1311 }
1312 return ret;
1313}
1314
1315#if PLATFORM_USE_SCM_DLOAD
1316int scm_dload_mode(int mode)
1317{
1318 int ret = 0;
1319 uint32_t dload_type;
1320
1321 dprintf(SPEW, "DLOAD mode: %d\n", mode);
1322 if (mode == NORMAL_DLOAD)
1323 dload_type = SCM_DLOAD_MODE;
1324 else if(mode == EMERGENCY_DLOAD)
1325 dload_type = SCM_EDLOAD_MODE;
1326 else
1327 dload_type = 0;
1328
1329 /* Write to the Boot MISC register */
Channagoud Kadabia2184b82015-07-07 10:09:32 -07001330 ret = is_scm_call_available(SCM_SVC_BOOT, SCM_DLOAD_CMD);
Aparna Mallavarapu664ea772015-02-24 18:44:33 +05301331
Channagoud Kadabia2184b82015-07-07 10:09:32 -07001332 if (ret > 0)
1333 ret = scm_call2_atomic(SCM_SVC_BOOT, SCM_DLOAD_CMD, dload_type, 0);
1334 else
Aparna Mallavarapu664ea772015-02-24 18:44:33 +05301335 ret = scm_io_write(TCSR_BOOT_MISC_DETECT,dload_type);
Channagoud Kadabia2184b82015-07-07 10:09:32 -07001336
1337 if(ret) {
1338 dprintf(CRITICAL, "Failed to write to boot misc: %d\n", ret);
1339 return ret;
Aparna Mallavarapu664ea772015-02-24 18:44:33 +05301340 }
1341
1342 scm_check_boot_fuses();
1343
1344 /* Make WDOG_DEBUG DISABLE scm call only in non-secure boot */
Aparna Mallavarapu8adbee22015-03-10 19:58:06 +05301345 if(!(secure_boot_enabled || wdog_debug_fuse_disabled)) {
Aparna Mallavarapu664ea772015-02-24 18:44:33 +05301346 ret = scm_call2_atomic(SCM_SVC_BOOT, WDOG_DEBUG_DISABLE, 1, 0);
1347 if(ret)
1348 dprintf(CRITICAL, "Failed to disable the wdog debug \n");
1349 }
1350
1351 return ret;
1352}
Channagoud Kadabi6479ce32015-06-17 17:30:40 -07001353
1354bool scm_device_enter_dload()
1355{
1356 uint32_t ret = 0;
1357
1358 scmcall_arg scm_arg = {0};
1359 scmcall_ret scm_ret = {0};
1360
1361 scm_arg.x0 = MAKE_SIP_SCM_CMD(TZ_SVC_DLOAD_MODE, SCM_DLOAD_CMD);
1362 ret = scm_call2(&scm_arg, &scm_ret);
1363 if (ret)
1364 dprintf(CRITICAL, "SCM call to check dload mode failed: %x\n", ret);
1365
1366 if (!ret && (scm_io_read(TCSR_BOOT_MISC_DETECT) == SCM_DLOAD_MODE))
1367 return true;
1368
1369 return false;
1370}
Aparna Mallavarapu664ea772015-02-24 18:44:33 +05301371#endif