early_random.c 2.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384
  1. /* 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. #include <linux/kernel.h>
  14. #include <mach/scm.h>
  15. #include <asm/io.h>
  16. #include <asm/cacheflush.h>
  17. #define TZ_SVC_CRYPTO 10
  18. #define PRNG_CMD_ID 0x01
  19. static int use_arch_random = 1;
  20. struct tz_prng_data {
  21. uint8_t *out_buf;
  22. uint32_t out_buf_sz;
  23. } __packed;
  24. DEFINE_SCM_BUFFER(common_scm_buf)
  25. DEFINE_MUTEX(arch_random_lock);
  26. #define RANDOM_BUFFER_SIZE PAGE_SIZE
  27. char random_buffer[RANDOM_BUFFER_SIZE] __aligned(PAGE_SIZE);
  28. int arch_get_random_common(void *v, size_t size)
  29. {
  30. struct tz_prng_data data;
  31. int ret;
  32. u32 resp;
  33. if (!use_arch_random)
  34. return 0;
  35. if (size > sizeof(random_buffer))
  36. return 0;
  37. mutex_lock(&arch_random_lock);
  38. data.out_buf = (uint8_t *) virt_to_phys(random_buffer);
  39. data.out_buf_sz = size;
  40. ret = scm_call_noalloc(TZ_SVC_CRYPTO, PRNG_CMD_ID, &data,
  41. sizeof(data), &resp, sizeof(resp),
  42. common_scm_buf, SCM_BUFFER_SIZE(common_scm_buf));
  43. if (!ret) {
  44. dmac_inv_range(random_buffer, random_buffer +
  45. RANDOM_BUFFER_SIZE);
  46. outer_inv_range(
  47. (unsigned long) virt_to_phys(random_buffer),
  48. (unsigned long) virt_to_phys(random_buffer) +
  49. RANDOM_BUFFER_SIZE);
  50. memcpy(v, random_buffer, size);
  51. }
  52. mutex_unlock(&arch_random_lock);
  53. return !ret;
  54. }
  55. int arch_get_random_long(unsigned long *v)
  56. {
  57. return arch_get_random_common(v, sizeof(unsigned long));
  58. }
  59. int arch_get_random_int(unsigned int *v)
  60. {
  61. return arch_get_random_common(v, sizeof(unsigned int));
  62. }
  63. int arch_random_init(void)
  64. {
  65. use_arch_random = 0;
  66. return 0;
  67. }
  68. module_init(arch_random_init);