secwidevine.c 9.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375
  1. #include <linux/kernel.h>
  2. #include <linux/module.h>
  3. #include <linux/init.h>
  4. #include <linux/moduleparam.h>
  5. #include <linux/slab.h>
  6. #include <linux/unistd.h>
  7. #include <linux/sched.h>
  8. #include <linux/fs.h>
  9. #include <linux/uaccess.h>
  10. #include <linux/version.h>
  11. #include <linux/spinlock.h>
  12. #include <linux/semaphore.h>
  13. #include <linux/delay.h>
  14. #include <linux/kthread.h>
  15. #include <linux/errno.h>
  16. #include <linux/cdev.h>
  17. #include <linux/device.h>
  18. #include <linux/mutex.h>
  19. #include <linux/string.h>
  20. /*#include <mach/memory.h>*/
  21. #include <linux/io.h>
  22. #include <linux/proc_fs.h>
  23. /* only available for trustonic */
  24. #include "mobicore_driver_api.h"
  25. #include "secwidevine.h"
  26. #define SECWIDEVINE_NAME "secwidevine"
  27. #define DEFAULT_HANDLES_NUM (64)
  28. #define MAX_OPEN_SESSIONS 10
  29. /* Debug message event */
  30. #define DBG_EVT_NONE (0) /* No event */
  31. #define DBG_EVT_CMD (1 << 0) /* SEC CMD related event */
  32. #define DBG_EVT_FUNC (1 << 1) /* SEC function event */
  33. #define DBG_EVT_INFO (1 << 2) /* SEC information event */
  34. #define DBG_EVT_WRN (1 << 30) /* Warning event */
  35. #define DBG_EVT_ERR (1 << 31) /* Error event */
  36. #define DBG_EVT_ALL (0xffffffff)
  37. #define DBG_EVT_MASK (DBG_EVT_ALL)
  38. #define MSG(evt, fmt, args...) \
  39. do { \
  40. if ((DBG_EVT_##evt) & DBG_EVT_MASK) { \
  41. pr_debug("[secwidevine][%s] "fmt, SECWIDEVINE_NAME, ##args); \
  42. } \
  43. } while (0)
  44. #define MSG_FUNC() MSG(FUNC, "%s\n", __func__)
  45. /**
  46. * Overall TCI structure.
  47. */
  48. #define TCI_PAYLOAD_LEN 1024
  49. struct tci_t {
  50. u8 message[TCI_PAYLOAD_LEN]; /**< TCI message */
  51. };
  52. struct secwidevine_param {
  53. struct tci_t tci_data;
  54. u32 refcount; /* INOUT */
  55. struct mc_session_handle session_handle; /* OUT */
  56. };
  57. static DEFINE_MUTEX(secwidevine_lock);
  58. /* This version just load secure driver */
  59. /* #define TL_secwidevine_UUID {0x37, 0xb4, 0x04, 0xdb, 0x11, 0xdb, 0x4f,
  60. * 0xd4, 0xaf, 0x5e, 0x84, 0x61, 0x06, 0xb1, 0xc3, 0xd0} */
  61. #define DR_secwidevine_UUID {0x37, 0x5d, 0xc3, 0xaa, 0x77, 0x68, 0x11, \
  62. 0xe3, 0x8c, 0x99, 0x2c, 0x27, 0xd7, 0x44, 0xd6, 0x6e}
  63. /* static const struct mc_uuid_t secwidevine_uuid = {TL_secwidevine_UUID}; */
  64. static const struct mc_uuid_t secwidevinedr_uuid = {DR_secwidevine_UUID};
  65. static struct mc_session_handle secwidevinedr_session = {0};
  66. static u32 secwidevine_session_ref;
  67. static u32 secwidevine_devid = MC_DEVICE_ID_DEFAULT;
  68. /*static struct tci_t *secwidevine_tci;*/
  69. static struct tci_t *secwidevinedr_tci;
  70. /*
  71. static int secwidevine_handle_register(struct secwidevine_context *ctx, u32 type, u32 id)
  72. {
  73. return 0;
  74. }
  75. static void secwidevine_handle_unregister_check(struct secwidevine_context *ctx, u32 type, u32 id)
  76. {
  77. }
  78. static int secwidevine_handle_unregister(struct secwidevine_context *ctx, u32 id)
  79. {
  80. return 0;
  81. }
  82. static int secwidevine_handle_cleanup(struct secwidevine_context *ctx)
  83. {
  84. return 0;
  85. }*/
  86. /* Open driver in open */
  87. static int secwidevine_session_open(void)
  88. {
  89. enum mc_result mc_ret = MC_DRV_OK;
  90. mutex_lock(&secwidevine_lock);
  91. do {
  92. /* sessions reach max numbers ? */
  93. if (secwidevine_session_ref > MAX_OPEN_SESSIONS) {
  94. MSG(WRN, "secwidevine_session > 0x%x\n", MAX_OPEN_SESSIONS);
  95. break;
  96. }
  97. if (secwidevine_session_ref > 0) {
  98. secwidevine_session_ref++;
  99. break;
  100. }
  101. /* open device */
  102. mc_ret = mc_open_device(secwidevine_devid);
  103. if (MC_DRV_OK != mc_ret) {
  104. MSG(ERR, "mc_open_device failed: %d\n", mc_ret);
  105. break;
  106. }
  107. /* allocating WSM for DCI */
  108. /*//open trustlet
  109. mc_ret = mc_malloc_wsm(secwidevine_devid, 0, sizeof(struct tci_t),
  110. (uint8_t **)&secwidevine_tci, 0);
  111. if (MC_DRV_OK != mc_ret) {
  112. mc_close_device(secwidevine_devid);
  113. MSG(ERR, "mc_malloc_wsm failed: %d\n", mc_ret);
  114. break;
  115. }
  116. // open session
  117. secwidevine_session.device_id = secwidevine_devid;
  118. mc_ret = mc_open_session(&secwidevine_session, &secwidevine_uuid,
  119. (uint8_t *)secwidevine_tci, sizeof(struct tci_t));
  120. if (MC_DRV_OK != mc_ret)
  121. {
  122. mc_free_wsm(secwidevine_devid, (uint8_t *)secwidevine_tci);
  123. secwidevine_tci = NULL;
  124. mc_close_device(secwidevine_devid);
  125. MSG(ERR, "mc_open_session failed: %d\n", mc_ret);
  126. break;
  127. }*/
  128. /* open driver */
  129. mc_ret = mc_malloc_wsm(secwidevine_devid, 0, sizeof(struct tci_t), (uint8_t **) &secwidevinedr_tci,
  130. 0);
  131. if (MC_DRV_OK != mc_ret) {
  132. /*mc_free_wsm(secwidevine_devid, (uint8_t *) secwidevine_tci);
  133. secwidevine_tci = NULL;*/
  134. mc_close_device(secwidevine_devid);
  135. MSG(ERR, "2.mc_malloc_wsm failed: %d\n", mc_ret);
  136. break;
  137. }
  138. /* open session */
  139. secwidevinedr_session.device_id = secwidevine_devid;
  140. mc_ret = mc_open_session(&secwidevinedr_session, &secwidevinedr_uuid,
  141. (uint8_t *) secwidevinedr_tci, sizeof(struct tci_t));
  142. if (MC_DRV_OK != mc_ret) {
  143. /* mc_free_wsm(secwidevine_devid, (uint8_t *) secwidevine_tci);
  144. * secwidevine_tci = NULL;*/
  145. mc_free_wsm(secwidevine_devid, (uint8_t *) secwidevinedr_tci);
  146. secwidevinedr_tci = NULL;
  147. mc_close_device(secwidevine_devid);
  148. MSG(ERR, "2.mc_open_session failed: %d\n", mc_ret);
  149. break;
  150. }
  151. secwidevine_session_ref = 1;
  152. } while (0);
  153. MSG(INFO, "secwidevine_session_open: ret=%d, ref=%d\n", mc_ret, secwidevine_session_ref);
  154. MSG(INFO, "driver sessionId = %d, deviceId = %d\n",
  155. secwidevinedr_session.session_id, secwidevinedr_session.device_id);
  156. mutex_unlock(&secwidevine_lock);
  157. if (MC_DRV_OK != mc_ret) {
  158. MSG(ERR, "secwidevine_session_open fail");
  159. return -ENXIO;
  160. }
  161. return 0;
  162. }
  163. /* Close trustlet and driver */
  164. static int secwidevine_session_close(void)
  165. {
  166. enum mc_result mc_ret = MC_DRV_OK;
  167. mutex_lock(&secwidevine_lock);
  168. do {
  169. /* session is already closed ? */
  170. if (secwidevine_session_ref == 0) {
  171. MSG(WRN, "secwidevine_session already closed\n");
  172. break;
  173. }
  174. if (secwidevine_session_ref > 1) {
  175. secwidevine_session_ref--;
  176. break;
  177. }
  178. /* close session
  179. mc_ret = mc_close_session(&secwidevine_session);
  180. if (MC_DRV_OK != mc_ret)
  181. {
  182. MSG(ERR, "mc_close_session failed: %d\n", mc_ret);
  183. break;
  184. }
  185. free WSM for DCI
  186. mc_ret = mc_free_wsm(secwidevine_devid, (uint8_t*) secwidevine_tci);
  187. if (MC_DRV_OK != mc_ret)
  188. {
  189. MSG(ERR, "mc_free_wsm failed: %d\n", mc_ret);
  190. break;
  191. }
  192. secwidevine_tci = NULL;*/
  193. /* close session */
  194. mc_ret = mc_close_session(&secwidevinedr_session);
  195. if (MC_DRV_OK != mc_ret) {
  196. MSG(ERR, "2.mc_close_session failed: %d\n", mc_ret);
  197. break;
  198. }
  199. /* free WSM for DCI */
  200. mc_ret = mc_free_wsm(secwidevine_devid, (uint8_t *) secwidevinedr_tci);
  201. if (MC_DRV_OK != mc_ret) {
  202. MSG(ERR, "2.mc_free_wsm failed: %d\n", mc_ret);
  203. break;
  204. }
  205. secwidevinedr_tci = NULL;
  206. secwidevine_session_ref = 0;
  207. /* close device */
  208. mc_ret = mc_close_device(secwidevine_devid);
  209. if (MC_DRV_OK != mc_ret)
  210. MSG(ERR, "mc_close_device failed: %d\n", mc_ret);
  211. } while (0);
  212. MSG(INFO, "secwidevine_session_close: ret=%d, ref=%d\n", mc_ret, secwidevine_session_ref);
  213. mutex_unlock(&secwidevine_lock);
  214. if (MC_DRV_OK != mc_ret)
  215. return -ENXIO;
  216. return 0;
  217. }
  218. static int secwidevine_open(struct inode *inode, struct file *file)
  219. {
  220. /* open session */
  221. if (secwidevine_session_open() < 0) {
  222. MSG(ERR, "secwidevine_open fail - secwidevine_session_open fail");
  223. return -ENXIO;
  224. }
  225. return 0;
  226. }
  227. static int secwidevine_release(struct inode *inode, struct file *file)
  228. {
  229. int ret = 0;
  230. ret = secwidevine_session_close();
  231. return ret;
  232. }
  233. static long secwidevine_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
  234. {
  235. int err = 0;
  236. struct secwidevine_param param;
  237. if (_IOC_TYPE(cmd) != SECWIDEVINE_IOC_MAGIC) {
  238. MSG(ERR, "Bad magic\n");
  239. return -ENOTTY;
  240. }
  241. if (_IOC_NR(cmd) > SECWIDEVINE_IOC_MAXNR) {
  242. MSG(ERR, "Bad ioc number\n");
  243. return -ENOTTY;
  244. }
  245. if (_IOC_DIR(cmd) & _IOC_READ)
  246. err = !access_ok(VERIFY_WRITE, (void __user *)arg, _IOC_SIZE(cmd));
  247. if (_IOC_DIR(cmd) & _IOC_WRITE)
  248. err = !access_ok(VERIFY_READ, (void __user *)arg, _IOC_SIZE(cmd));
  249. if (err) {
  250. MSG(ERR, "verify read/write fail\n");
  251. return -EFAULT;
  252. }
  253. err = copy_from_user(&param, (void *)arg, sizeof(param));
  254. if (err) {
  255. MSG(ERR, "copy_from_user fail\n");
  256. return -EFAULT;
  257. }
  258. switch (cmd) {
  259. /*case SECWIDEVINE_GET_SESSION:
  260. if (!(file->f_mode & FMODE_WRITE))
  261. {
  262. MSG(ERR, "verify FMODE_WRITE fail\n");
  263. return -EROFS;
  264. }
  265. err = secwidevine_execute(CMD_SEC_WIDEVINE_GET_SESSION, &param);
  266. break;*/
  267. default:
  268. return -ENOTTY;
  269. }
  270. if (!err)
  271. err = copy_to_user((void *)arg, &param, sizeof(param));
  272. MSG(INFO, "copy_to_user result = %d\n", err);
  273. MSG(INFO, "sessionId = %d, deviceId = %d\n",
  274. param.session_handle.session_id, param.session_handle.device_id);
  275. return err;
  276. }
  277. static const struct file_operations secwidevine_fops = {
  278. .owner = THIS_MODULE,
  279. .open = secwidevine_open,
  280. .release = secwidevine_release,
  281. .unlocked_ioctl = secwidevine_ioctl,
  282. .write = NULL,
  283. .read = NULL,
  284. };
  285. static int __init secwidevine_init(void)
  286. {
  287. #if 0
  288. struct proc_dir_entry *secwidevine_proc;
  289. secwidevine_proc = create_proc_entry("secwidevine0",
  290. (S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP | S_IROTH), NULL);
  291. if (IS_ERR(secwidevine_proc))
  292. goto error;
  293. secwidevine_proc->proc_fops = &secwidevine_fops;
  294. #else
  295. proc_create("secwidevine0", (S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP | S_IROTH), NULL, &secwidevine_fops);
  296. #endif
  297. return 0;
  298. #if 0
  299. error:
  300. return -1;
  301. #endif
  302. }
  303. late_initcall(secwidevine_init);