blob: e315b86a4315b9fe56724bb17801a3de73591e85 [file] [log] [blame]
Laura Abbottdf4c87a2013-08-09 18:17:06 -07001/* Copyright (c) 2013, The Linux Foundation. All rights reserved.
2 *
3 * This program is free software; you can redistribute it and/or modify
4 * it under the terms of the GNU General Public License version 2 and
5 * only version 2 as published by the Free Software Foundation.
6 *
7 * This program is distributed in the hope that it will be useful,
8 * but WITHOUT ANY WARRANTY; without even the implied warranty of
9 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
10 * GNU General Public License for more details.
11 *
12 */
13
14#include <linux/kernel.h>
15
16#include <mach/scm.h>
17
18#include <asm/io.h>
19#include <asm/cacheflush.h>
20
21#define TZ_SVC_CRYPTO 10
22#define PRNG_CMD_ID 0x01
23
24static int use_arch_random = 1;
25struct tz_prng_data {
26 uint8_t *out_buf;
27 uint32_t out_buf_sz;
28} __packed;
29
30DEFINE_SCM_BUFFER(common_scm_buf)
31DEFINE_MUTEX(arch_random_lock);
32#define RANDOM_BUFFER_SIZE PAGE_SIZE
33char random_buffer[RANDOM_BUFFER_SIZE] __aligned(PAGE_SIZE);
34
35int arch_get_random_common(void *v, size_t size)
36{
37 struct tz_prng_data data;
38 int ret;
39 u32 resp;
40
41 if (!use_arch_random)
42 return 0;
43
44 if (size > sizeof(random_buffer))
45 return 0;
46
47 mutex_lock(&arch_random_lock);
48 data.out_buf = (uint8_t *) virt_to_phys(random_buffer);
49 data.out_buf_sz = size;
50
51 ret = scm_call_noalloc(TZ_SVC_CRYPTO, PRNG_CMD_ID, &data,
52 sizeof(data), &resp, sizeof(resp),
53 common_scm_buf, SCM_BUFFER_SIZE(common_scm_buf));
54 if (!ret) {
55 dmac_inv_range(random_buffer, random_buffer +
56 RANDOM_BUFFER_SIZE);
57 outer_inv_range(
58 (unsigned long) virt_to_phys(random_buffer),
59 (unsigned long) virt_to_phys(random_buffer) +
60 RANDOM_BUFFER_SIZE);
61 memcpy(v, random_buffer, size);
62 }
63 mutex_unlock(&arch_random_lock);
64 return !ret;
65}
66
67int arch_get_random_long(unsigned long *v)
68{
69 return arch_get_random_common(v, sizeof(unsigned long));
70}
71
72int arch_get_random_int(unsigned int *v)
73{
74 return arch_get_random_common(v, sizeof(unsigned int));
75}
76
77int arch_random_init(void)
78{
79 use_arch_random = 0;
80
81 return 0;
82}
83module_init(arch_random_init);