tzic.c 8.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312
  1. /*
  2. * Samsung TZIC Driver
  3. *
  4. * This program is free software; you can redistribute it and/or modify
  5. * it under the terms of the GNU General Public License version 2 and
  6. * only version 2 as published by the Free Software Foundation.
  7. *
  8. * This program is distributed in the hope that it will be useful,
  9. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  10. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  11. * GNU General Public License for more details.
  12. */
  13. #define KMSG_COMPONENT "TZIC"
  14. #include <linux/kernel.h>
  15. #include <linux/module.h>
  16. #include <linux/fs.h>
  17. #include <linux/platform_device.h>
  18. #include <linux/debugfs.h>
  19. #include <linux/cdev.h>
  20. #include <linux/uaccess.h>
  21. #include <linux/sched.h>
  22. #include <linux/list.h>
  23. #include <linux/mutex.h>
  24. #include <linux/android_pmem.h>
  25. #include <linux/io.h>
  26. #include <mach/scm.h>
  27. //#include <linux/tzcom.h>
  28. #include <linux/types.h>
  29. #define TZIC_DEV "tzic"
  30. static DEFINE_MUTEX(tzic_mutex);
  31. static struct class *driver_class;
  32. static dev_t tzic_device_no;
  33. static struct cdev tzic_cdev;
  34. #define HLOS_IMG_TAMPER_FUSE 0
  35. typedef enum {
  36. OEMFLAG_MIN_FLAG = 2,
  37. OEMFLAG_TZ_DRM,
  38. OEMFLAG_FIDD,
  39. OEMFLAG_CC,
  40. OEMFLAG_NUM_OF_FLAG,
  41. } Sec_OemFlagID_t;
  42. typedef struct
  43. {
  44. u32 name;
  45. u32 value;
  46. }t_flag;
  47. #ifndef SCM_SVC_FUSE
  48. #define SCM_SVC_FUSE 0x08
  49. #endif
  50. #define SCM_BLOW_SW_FUSE_ID 0x01
  51. #define SCM_IS_SW_FUSE_BLOWN_ID 0x02
  52. #define TZIC_IOC_MAGIC 0x9E
  53. #define TZIC_IOCTL_GET_FUSE_REQ _IO(TZIC_IOC_MAGIC, 0)
  54. #define TZIC_IOCTL_SET_FUSE_REQ _IO(TZIC_IOC_MAGIC, 1)
  55. #define TZIC_IOCTL_SET_FUSE_REQ_DEFAULT _IO(TZIC_IOC_MAGIC, 2)
  56. #define TZIC_IOCTL_GET_FUSE_REQ_NEW _IO(TZIC_IOC_MAGIC, 10)
  57. #define TZIC_IOCTL_SET_FUSE_REQ_NEW _IO(TZIC_IOC_MAGIC, 11)
  58. #define STATE_IC_BAD 1
  59. #define STATE_IC_GOOD 0
  60. #define LOG printk
  61. static int ic = STATE_IC_GOOD;
  62. static int set_tamper_fuse_cmd(void);
  63. static uint8_t get_tamper_fuse_cmd(void);
  64. static int set_tamper_fuse_cmd_new(uint32_t flag);
  65. static uint8_t get_tamper_fuse_cmd_new(uint32_t flag);
  66. static int set_tamper_fuse_cmd()
  67. {
  68. uint32_t fuse_id = HLOS_IMG_TAMPER_FUSE;
  69. return scm_call(SCM_SVC_FUSE, SCM_BLOW_SW_FUSE_ID, &fuse_id,
  70. sizeof(fuse_id), NULL, 0);
  71. }
  72. static int set_tamper_fuse_cmd_new(uint32_t flag)
  73. {
  74. uint32_t fuse_id = flag;
  75. return scm_call(SCM_SVC_FUSE, SCM_BLOW_SW_FUSE_ID, &fuse_id,
  76. sizeof(fuse_id), NULL, 0);
  77. }
  78. static uint8_t get_tamper_fuse_cmd()
  79. {
  80. uint32_t fuse_id = HLOS_IMG_TAMPER_FUSE;
  81. void *cmd_buf;
  82. size_t cmd_len;
  83. size_t resp_len = 0;
  84. uint8_t resp_buf;
  85. cmd_buf = (void *)&fuse_id;
  86. cmd_len = sizeof(fuse_id);
  87. resp_len = sizeof(resp_buf);
  88. scm_call(SCM_SVC_FUSE, SCM_IS_SW_FUSE_BLOWN_ID, cmd_buf,
  89. cmd_len, &resp_buf, resp_len);
  90. ic = resp_buf;
  91. return resp_buf;
  92. }
  93. static uint8_t get_tamper_fuse_cmd_new(uint32_t flag)
  94. {
  95. uint32_t fuse_id = flag;
  96. void *cmd_buf;
  97. size_t cmd_len;
  98. size_t resp_len = 0;
  99. uint8_t resp_buf;
  100. cmd_buf = (void *)&fuse_id;
  101. cmd_len = sizeof(fuse_id);
  102. resp_len = sizeof(resp_buf);
  103. scm_call(SCM_SVC_FUSE, SCM_IS_SW_FUSE_BLOWN_ID, cmd_buf,
  104. cmd_len, &resp_buf, resp_len);
  105. ic = resp_buf;
  106. return resp_buf;
  107. }
  108. static long tzic_ioctl(struct file *file, unsigned cmd,
  109. unsigned long arg)
  110. {
  111. int ret = 0;
  112. int i = 0;
  113. t_flag param;
  114. switch(cmd){
  115. case TZIC_IOCTL_GET_FUSE_REQ:
  116. LOG(KERN_INFO "[oemflag]get_fuse\n");
  117. ret = get_tamper_fuse_cmd();
  118. LOG(KERN_INFO "[oemflag]tamper_fuse value = %x\n", ret);
  119. break;
  120. case TZIC_IOCTL_SET_FUSE_REQ:
  121. LOG(KERN_INFO "[oemflag]set_fuse\n");
  122. ret = get_tamper_fuse_cmd();
  123. LOG(KERN_INFO "[oemflag]tamper_fuse before = %x\n", ret);
  124. LOG(KERN_INFO "[oemflag]ioctl set_fuse\n");
  125. mutex_lock(&tzic_mutex);
  126. ret = set_tamper_fuse_cmd();
  127. mutex_unlock(&tzic_mutex);
  128. if (ret)
  129. LOG(KERN_INFO "[oemflag]failed tzic_set_fuse_cmd: %d\n", ret);
  130. ret = get_tamper_fuse_cmd();
  131. LOG(KERN_INFO "[oemflag]tamper_fuse after = %x\n", ret);
  132. break;
  133. case TZIC_IOCTL_SET_FUSE_REQ_DEFAULT://SET ALL OEM FLAG EXCEPT 0
  134. LOG(KERN_INFO "[oemflag]set_fuse_default\n");
  135. ret=copy_from_user( &param, (void *)arg, sizeof(param) );
  136. if(ret) {
  137. LOG(KERN_INFO "[oemflag]ERROR copy from user\n");
  138. return ret;
  139. }
  140. for (i=OEMFLAG_MIN_FLAG+1;i<OEMFLAG_NUM_OF_FLAG;i++){
  141. param.name=i;
  142. LOG(KERN_INFO "[oemflag]set_fuse_name : %d\n", param.name);
  143. ret = get_tamper_fuse_cmd_new(param.name);
  144. LOG(KERN_INFO "[oemflag]tamper_fuse before = %x\n", ret);
  145. LOG(KERN_INFO "[oemflag]ioctl set_fuse\n");
  146. mutex_lock(&tzic_mutex);
  147. ret = set_tamper_fuse_cmd_new(param.name);
  148. mutex_unlock(&tzic_mutex);
  149. if (ret)
  150. LOG(KERN_INFO "[oemflag]failed tzic_set_fuse_cmd: %d\n", ret);
  151. ret = get_tamper_fuse_cmd_new(param.name);
  152. LOG(KERN_INFO "[oemflag]tamper_fuse after = %x\n", ret);
  153. }
  154. break;
  155. case TZIC_IOCTL_GET_FUSE_REQ_NEW:
  156. LOG(KERN_INFO "[oemflag]get_fuse\n");
  157. ret=copy_from_user( &param, (void *)arg, sizeof(param) );
  158. if(ret) {
  159. LOG(KERN_INFO "[oemflag]ERROR copy from user\n");
  160. return ret;
  161. }
  162. if ((OEMFLAG_MIN_FLAG < param.name) && (param.name < OEMFLAG_NUM_OF_FLAG)){
  163. LOG(KERN_INFO "[oemflag]get_fuse_name : %d\n", param.name);
  164. ret = get_tamper_fuse_cmd_new(param.name);
  165. LOG(KERN_INFO "[oemflag]tamper_fuse value = %x\n", ret);
  166. } else {
  167. LOG(KERN_INFO "[oemflag]command error\n");
  168. return -EINVAL;
  169. }
  170. break;
  171. case TZIC_IOCTL_SET_FUSE_REQ_NEW:
  172. LOG(KERN_INFO "[oemflag]set_fuse\n");
  173. ret=copy_from_user( &param, (void *)arg, sizeof(param) );
  174. if(ret) {
  175. LOG(KERN_INFO "[oemflag]ERROR copy from user\n");
  176. return ret;
  177. }
  178. if ((OEMFLAG_MIN_FLAG < param.name) && (param.name < OEMFLAG_NUM_OF_FLAG)){
  179. LOG(KERN_INFO "[oemflag]set_fuse_name : %d\n", param.name);
  180. ret = get_tamper_fuse_cmd_new(param.name);
  181. LOG(KERN_INFO "[oemflag]tamper_fuse before = %x\n", ret);
  182. LOG(KERN_INFO "[oemflag]ioctl set_fuse\n");
  183. //Qualcomm DRM oemflag only support HLOS_IMG_TAMPER_FUSE
  184. if (param.name == OEMFLAG_TZ_DRM) {
  185. mutex_lock(&tzic_mutex);
  186. ret = set_tamper_fuse_cmd();
  187. mutex_unlock(&tzic_mutex);
  188. if (ret)
  189. LOG(KERN_INFO "[oemflag]failed tzic_set_fuse_cmd: %d\n", ret);
  190. }
  191. mutex_lock(&tzic_mutex);
  192. ret = set_tamper_fuse_cmd_new(param.name);
  193. mutex_unlock(&tzic_mutex);
  194. if (ret)
  195. LOG(KERN_INFO "[oemflag]failed tzic_set_fuse_cmd: %d\n", ret);
  196. ret = get_tamper_fuse_cmd_new(param.name);
  197. LOG(KERN_INFO "[oemflag]tamper_fuse after = %x\n", ret);
  198. } else {
  199. LOG(KERN_INFO "[oemflag]command error\n");
  200. return -EINVAL;
  201. }
  202. break;
  203. default:
  204. LOG(KERN_INFO "[oemflag]command error\n");
  205. return -EINVAL;
  206. }
  207. return ret;
  208. }
  209. static const struct file_operations tzic_fops = {
  210. .owner = THIS_MODULE,
  211. .unlocked_ioctl = tzic_ioctl,
  212. };
  213. static int __init tzic_init(void)
  214. {
  215. int rc;
  216. struct device *class_dev;
  217. LOG(KERN_INFO "init tzic");
  218. rc = alloc_chrdev_region(&tzic_device_no, 0, 1, TZIC_DEV);
  219. if (rc < 0) {
  220. LOG(KERN_INFO "alloc_chrdev_region failed %d", rc);
  221. return rc;
  222. }
  223. driver_class = class_create(THIS_MODULE, TZIC_DEV);
  224. if (IS_ERR(driver_class)) {
  225. rc = -ENOMEM;
  226. LOG(KERN_INFO "class_create failed %d", rc);
  227. goto unregister_chrdev_region;
  228. }
  229. class_dev = device_create(driver_class, NULL, tzic_device_no, NULL,
  230. TZIC_DEV);
  231. if (!class_dev) {
  232. LOG(KERN_INFO "class_device_create failed %d", rc);
  233. rc = -ENOMEM;
  234. goto class_destroy;
  235. }
  236. cdev_init(&tzic_cdev, &tzic_fops);
  237. tzic_cdev.owner = THIS_MODULE;
  238. rc = cdev_add(&tzic_cdev, MKDEV(MAJOR(tzic_device_no), 0), 1);
  239. if (rc < 0) {
  240. LOG(KERN_INFO "cdev_add failed %d", rc);
  241. goto class_device_destroy;
  242. }
  243. return 0;
  244. class_device_destroy:
  245. device_destroy(driver_class, tzic_device_no);
  246. class_destroy:
  247. class_destroy(driver_class);
  248. unregister_chrdev_region:
  249. unregister_chrdev_region(tzic_device_no, 1);
  250. return rc;
  251. }
  252. static void __exit tzic_exit(void)
  253. {
  254. LOG(KERN_INFO "exit tzic");
  255. device_destroy(driver_class, tzic_device_no);
  256. class_destroy(driver_class);
  257. unregister_chrdev_region(tzic_device_no, 1);
  258. }
  259. MODULE_LICENSE("GPL v2");
  260. MODULE_DESCRIPTION("Samsung TZIC Driver");
  261. MODULE_VERSION("1.00");
  262. module_init(tzic_init);
  263. module_exit(tzic_exit);