secmem.c 18 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790
  1. /*
  2. * Copyright (C) 2015 MediaTek Inc.
  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 as
  6. * 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. #include <linux/kernel.h>
  14. #include <linux/module.h>
  15. #include <linux/init.h>
  16. #include <linux/moduleparam.h>
  17. #include <linux/slab.h>
  18. #include <linux/unistd.h>
  19. #include <linux/sched.h>
  20. #include <linux/fs.h>
  21. #include <linux/uaccess.h>
  22. #include <linux/version.h>
  23. #include <linux/spinlock.h>
  24. #include <linux/semaphore.h>
  25. #include <linux/delay.h>
  26. #include <linux/kthread.h>
  27. #include <linux/errno.h>
  28. #include <linux/cdev.h>
  29. #include <linux/device.h>
  30. #include <linux/mutex.h>
  31. #include <linux/string.h>
  32. #include <linux/io.h>
  33. #include <linux/proc_fs.h>
  34. #include "secmem.h"
  35. /* only available for trustonic */
  36. #include "mobicore_driver_api.h"
  37. #include "tlsecmem_api.h"
  38. #define DEFAULT_HANDLES_NUM (64)
  39. #define MAX_OPEN_SESSIONS (0xffffffff - 1)
  40. /* Debug message event */
  41. #define DBG_EVT_NONE (0) /* No event */
  42. #define DBG_EVT_CMD (1 << 0) /* SEC CMD related event */
  43. #define DBG_EVT_FUNC (1 << 1) /* SEC function event */
  44. #define DBG_EVT_INFO (1 << 2) /* SEC information event */
  45. #define DBG_EVT_WRN (1 << 30) /* Warning event */
  46. #define DBG_EVT_ERR (1 << 31) /* Error event */
  47. #define DBG_EVT_ALL (0xffffffff)
  48. #define DBG_EVT_MASK (DBG_EVT_ALL)
  49. #define MSG(evt, fmt, args...) \
  50. do { \
  51. if ((DBG_EVT_##evt) & DBG_EVT_MASK) { \
  52. pr_debug("[%s] "fmt, SECMEM_NAME, ##args); \
  53. } \
  54. } while (0)
  55. #define MSG_FUNC() MSG(FUNC, "%s\n", __func__)
  56. struct secmem_handle {
  57. u32 id;
  58. u32 type;
  59. };
  60. struct secmem_context {
  61. spinlock_t lock;
  62. struct secmem_handle *handles;
  63. u32 handle_num;
  64. };
  65. static DEFINE_MUTEX(secmem_lock);
  66. static const struct mc_uuid_t secmem_uuid = { TL_SECMEM_UUID };
  67. static struct mc_session_handle secmem_session = { 0 };
  68. static u32 secmem_session_ref;
  69. static u32 secmem_k_session_opened;
  70. static u32 secmem_devid = MC_DEVICE_ID_DEFAULT;
  71. static tciMessage_t *secmem_tci;
  72. static int secmem_execute(u32 cmd, struct secmem_param *param)
  73. {
  74. enum mc_result mc_ret;
  75. #ifdef SECMEM_DEBUG_DUMP
  76. int len;
  77. #endif
  78. mutex_lock(&secmem_lock);
  79. if (NULL == secmem_tci) {
  80. mutex_unlock(&secmem_lock);
  81. MSG(ERR, "secmem_tci not exist\n");
  82. return -ENODEV;
  83. }
  84. secmem_tci->cmd_secmem.header.commandId = (tciCommandId_t) cmd;
  85. secmem_tci->cmd_secmem.len = 0;
  86. secmem_tci->sec_handle = param->sec_handle;
  87. secmem_tci->alignment = param->alignment;
  88. secmem_tci->size = param->size;
  89. secmem_tci->refcount = param->refcount;
  90. #ifdef SECMEM_DEBUG_DUMP
  91. secmem_tci->sender.id = param->id;
  92. secmem_tci->sender.name[0] = 0;
  93. if (param->owner[0] != 0) {
  94. len = param->owner_len > MAX_NAME_SZ ? MAX_NAME_SZ : param->owner_len;
  95. memcpy(secmem_tci->sender.name, param->owner, len);
  96. secmem_tci->sender.name[MAX_NAME_SZ - 1] = 0;
  97. }
  98. #endif
  99. mc_ret = mc_notify(&secmem_session);
  100. if (MC_DRV_OK != mc_ret) {
  101. MSG(ERR, "mc_notify failed: %d\n", mc_ret);
  102. goto exit;
  103. }
  104. mc_ret = mc_wait_notification(&secmem_session, -1);
  105. if (MC_DRV_OK != mc_ret) {
  106. MSG(ERR, "mc_wait_notification failed: %d\n", mc_ret);
  107. goto exit;
  108. }
  109. /* correct handle should be get after return from secure world. */
  110. param->sec_handle = secmem_tci->sec_handle;
  111. param->refcount = secmem_tci->refcount;
  112. param->alignment = secmem_tci->alignment;
  113. param->size = secmem_tci->size;
  114. if (RSP_ID(cmd) != secmem_tci->rsp_secmem.header.responseId) {
  115. MSG(ERR, "trustlet did not send a response: %d\n",
  116. secmem_tci->rsp_secmem.header.responseId);
  117. mc_ret = MC_DRV_ERR_INVALID_RESPONSE;
  118. goto exit;
  119. }
  120. if (MC_DRV_OK != secmem_tci->rsp_secmem.header.returnCode) {
  121. MSG(ERR, "trustlet did not send a valid return code: %d\n",
  122. secmem_tci->rsp_secmem.header.returnCode);
  123. mc_ret = secmem_tci->rsp_secmem.header.returnCode;
  124. }
  125. exit:
  126. mutex_unlock(&secmem_lock);
  127. if (MC_DRV_OK != mc_ret)
  128. return -ENOSPC;
  129. return 0;
  130. }
  131. static int secmem_handle_register(struct secmem_context *ctx, u32 type, u32 id)
  132. {
  133. struct secmem_handle *handle;
  134. u32 i, num, nspace;
  135. spin_lock(&ctx->lock);
  136. num = ctx->handle_num;
  137. handle = ctx->handles;
  138. /* find empty space. */
  139. for (i = 0; i < num; i++, handle++) {
  140. if (handle->id == 0) {
  141. handle->id = id;
  142. handle->type = type;
  143. spin_unlock(&ctx->lock);
  144. return 0;
  145. }
  146. }
  147. /* try grow the space */
  148. nspace = num * 2;
  149. handle = (struct secmem_handle *)krealloc(ctx->handles,
  150. nspace * sizeof(struct secmem_handle),
  151. GFP_KERNEL);
  152. if (handle == NULL) {
  153. spin_unlock(&ctx->lock);
  154. return -ENOMEM;
  155. }
  156. ctx->handle_num = nspace;
  157. ctx->handles = handle;
  158. handle += num;
  159. memset(handle, 0, (nspace - num) * sizeof(struct secmem_handle));
  160. handle->id = id;
  161. handle->type = type;
  162. spin_unlock(&ctx->lock);
  163. return 0;
  164. }
  165. static void secmem_handle_unregister_check(struct secmem_context *ctx, u32 type, u32 id)
  166. {
  167. struct secmem_handle *handle;
  168. u32 i, num;
  169. spin_lock(&ctx->lock);
  170. num = ctx->handle_num;
  171. handle = ctx->handles;
  172. /* find empty space. */
  173. for (i = 0; i < num; i++, handle++) {
  174. if (handle->id == id) {
  175. if (handle->type != type) {
  176. MSG(ERR,
  177. "unref check failed, type mismatched (%d!=%d), handle=0x%x\n",
  178. _IOC_NR(handle->type), _IOC_NR(type), handle->id);
  179. }
  180. break;
  181. }
  182. }
  183. spin_unlock(&ctx->lock);
  184. }
  185. static int secmem_handle_unregister(struct secmem_context *ctx, u32 id)
  186. {
  187. struct secmem_handle *handle;
  188. u32 i, num;
  189. spin_lock(&ctx->lock);
  190. num = ctx->handle_num;
  191. handle = ctx->handles;
  192. /* find empty space. */
  193. for (i = 0; i < num; i++, handle++) {
  194. if (handle->id == id) {
  195. memset(handle, 0, sizeof(struct secmem_handle));
  196. break;
  197. }
  198. }
  199. spin_unlock(&ctx->lock);
  200. return 0;
  201. }
  202. static int secmem_handle_cleanup(struct secmem_context *ctx)
  203. {
  204. int ret = 0;
  205. u32 i, num, cmd = 0;
  206. struct secmem_handle *handle;
  207. struct secmem_param param = { 0 };
  208. spin_lock(&ctx->lock);
  209. num = ctx->handle_num;
  210. handle = ctx->handles;
  211. for (i = 0; i < num; i++, handle++) {
  212. if (handle->id != 0) {
  213. param.sec_handle = handle->id;
  214. switch (handle->type) {
  215. case SECMEM_MEM_ALLOC:
  216. cmd = CMD_SEC_MEM_UNREF;
  217. break;
  218. case SECMEM_MEM_REF:
  219. cmd = CMD_SEC_MEM_UNREF;
  220. break;
  221. case SECMEM_MEM_ALLOC_TBL:
  222. cmd = CMD_SEC_MEM_UNREF_TBL;
  223. break;
  224. default:
  225. MSG(ERR, "secmem_handle_cleanup: incorrect type=%d (ioctl:%d)\n",
  226. handle->type, _IOC_NR(handle->type));
  227. goto error;
  228. }
  229. spin_unlock(&ctx->lock);
  230. ret = secmem_execute(cmd, &param);
  231. MSG(INFO, "secmem_handle_cleanup: id=0x%x type=%d (ioctl:%d)\n",
  232. handle->id, handle->type, _IOC_NR(handle->type));
  233. spin_lock(&ctx->lock);
  234. }
  235. }
  236. error:
  237. spin_unlock(&ctx->lock);
  238. return ret;
  239. }
  240. static int secmem_session_open(void)
  241. {
  242. enum mc_result mc_ret = MC_DRV_OK;
  243. mutex_lock(&secmem_lock);
  244. do {
  245. /* sessions reach max numbers ? */
  246. if (secmem_session_ref > MAX_OPEN_SESSIONS) {
  247. MSG(WRN, "secmem_session > 0x%x\n", MAX_OPEN_SESSIONS);
  248. break;
  249. }
  250. if (secmem_session_ref > 0) {
  251. secmem_session_ref++;
  252. break;
  253. }
  254. /* open device */
  255. mc_ret = mc_open_device(secmem_devid);
  256. if (MC_DRV_OK != mc_ret) {
  257. MSG(ERR, "mc_open_device failed: %d\n", mc_ret);
  258. break;
  259. }
  260. /* allocating WSM for DCI */
  261. mc_ret = mc_malloc_wsm(secmem_devid, 0, sizeof(tciMessage_t),
  262. (uint8_t **) &secmem_tci, 0);
  263. if (MC_DRV_OK != mc_ret) {
  264. mc_close_device(secmem_devid);
  265. MSG(ERR, "mc_malloc_wsm failed: %d\n", mc_ret);
  266. break;
  267. }
  268. /* open session */
  269. secmem_session.device_id = secmem_devid;
  270. mc_ret = mc_open_session(&secmem_session, &secmem_uuid,
  271. (uint8_t *) secmem_tci, sizeof(tciMessage_t));
  272. if (MC_DRV_OK != mc_ret) {
  273. mc_free_wsm(secmem_devid, (uint8_t *) secmem_tci);
  274. mc_close_device(secmem_devid);
  275. secmem_tci = NULL;
  276. MSG(ERR, "mc_open_session failed: %d\n", mc_ret);
  277. break;
  278. }
  279. secmem_session_ref = 1;
  280. } while (0);
  281. MSG(INFO, "secmem_session_open: ret=%d, ref=%d\n", mc_ret, secmem_session_ref);
  282. mutex_unlock(&secmem_lock);
  283. if (MC_DRV_OK != mc_ret)
  284. return -ENXIO;
  285. return 0;
  286. }
  287. static int secmem_session_close(void)
  288. {
  289. enum mc_result mc_ret = MC_DRV_OK;
  290. mutex_lock(&secmem_lock);
  291. do {
  292. /* session is already closed ? */
  293. if (secmem_session_ref == 0) {
  294. MSG(WRN, "secmem_session already closed\n");
  295. break;
  296. }
  297. if (secmem_session_ref > 1) {
  298. secmem_session_ref--;
  299. break;
  300. }
  301. /* close session */
  302. mc_ret = mc_close_session(&secmem_session);
  303. if (MC_DRV_OK != mc_ret) {
  304. MSG(ERR, "mc_close_session failed: %d\n", mc_ret);
  305. break;
  306. }
  307. /* free WSM for DCI */
  308. mc_ret = mc_free_wsm(secmem_devid, (uint8_t *) secmem_tci);
  309. if (MC_DRV_OK != mc_ret) {
  310. MSG(ERR, "mc_free_wsm failed: %d\n", mc_ret);
  311. break;
  312. }
  313. secmem_tci = NULL;
  314. secmem_session_ref = 0;
  315. /* close device */
  316. mc_ret = mc_close_device(secmem_devid);
  317. if (MC_DRV_OK != mc_ret)
  318. MSG(ERR, "mc_close_device failed: %d\n", mc_ret);
  319. } while (0);
  320. MSG(INFO, "secmem_session_close: ret=%d, ref=%d\n", mc_ret, secmem_session_ref);
  321. mutex_unlock(&secmem_lock);
  322. if (MC_DRV_OK != mc_ret)
  323. return -ENXIO;
  324. return 0;
  325. }
  326. static int secmem_open(struct inode *inode, struct file *file)
  327. {
  328. struct secmem_context *ctx;
  329. /* allocate session context */
  330. ctx = kmalloc(sizeof(struct secmem_context), GFP_KERNEL);
  331. if (!ctx)
  332. return -ENOMEM;
  333. ctx->handle_num = DEFAULT_HANDLES_NUM;
  334. ctx->handles = kzalloc(sizeof(struct secmem_handle) * DEFAULT_HANDLES_NUM, GFP_KERNEL);
  335. spin_lock_init(&ctx->lock);
  336. if (!ctx->handles) {
  337. kfree(ctx);
  338. return -ENOMEM;
  339. }
  340. /* open session */
  341. if (secmem_session_open() < 0) {
  342. kfree(ctx->handles);
  343. kfree(ctx);
  344. return -ENXIO;
  345. }
  346. file->private_data = (void *)ctx;
  347. return 0;
  348. }
  349. static int secmem_release(struct inode *inode, struct file *file)
  350. {
  351. int ret = 0;
  352. struct secmem_context *ctx = (struct secmem_context *)file->private_data;
  353. if (ctx) {
  354. /* release session context */
  355. secmem_handle_cleanup(ctx);
  356. kfree(ctx->handles);
  357. kfree(ctx);
  358. file->private_data = NULL;
  359. /* close session */
  360. ret = secmem_session_close();
  361. }
  362. return ret;
  363. }
  364. static long secmem_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
  365. {
  366. int err = 0;
  367. struct secmem_context *ctx = (struct secmem_context *)file->private_data;
  368. struct secmem_param param;
  369. u32 handle;
  370. if (_IOC_TYPE(cmd) != SECMEM_IOC_MAGIC)
  371. return -ENOTTY;
  372. if (_IOC_NR(cmd) > SECMEM_IOC_MAXNR)
  373. return -ENOTTY;
  374. if (_IOC_DIR(cmd) & _IOC_READ)
  375. err = !access_ok(VERIFY_WRITE, (void __user *)arg, _IOC_SIZE(cmd));
  376. if (_IOC_DIR(cmd) & _IOC_WRITE)
  377. err = !access_ok(VERIFY_READ, (void __user *)arg, _IOC_SIZE(cmd));
  378. if (err)
  379. return -EFAULT;
  380. err = copy_from_user(&param, (void *)arg, sizeof(param));
  381. if (err)
  382. return -EFAULT;
  383. switch (cmd) {
  384. case SECMEM_MEM_ALLOC:
  385. if (!(file->f_mode & FMODE_WRITE))
  386. return -EROFS;
  387. err = secmem_execute(CMD_SEC_MEM_ALLOC, &param);
  388. if (!err)
  389. secmem_handle_register(ctx, SECMEM_MEM_ALLOC, param.sec_handle);
  390. break;
  391. case SECMEM_MEM_REF:
  392. err = secmem_execute(CMD_SEC_MEM_REF, &param);
  393. if (!err)
  394. secmem_handle_register(ctx, SECMEM_MEM_REF, param.sec_handle);
  395. break;
  396. case SECMEM_MEM_UNREF:
  397. handle = param.sec_handle;
  398. secmem_handle_unregister_check(ctx, SECMEM_MEM_ALLOC, handle);
  399. err = secmem_execute(CMD_SEC_MEM_UNREF, &param);
  400. if (!err)
  401. secmem_handle_unregister(ctx, handle);
  402. break;
  403. case SECMEM_MEM_ALLOC_TBL:
  404. if (!(file->f_mode & FMODE_WRITE))
  405. return -EROFS;
  406. err = secmem_execute(CMD_SEC_MEM_ALLOC_TBL, &param);
  407. if (!err)
  408. secmem_handle_register(ctx, SECMEM_MEM_ALLOC_TBL, param.sec_handle);
  409. break;
  410. case SECMEM_MEM_UNREF_TBL:
  411. handle = param.sec_handle;
  412. secmem_handle_unregister_check(ctx, SECMEM_MEM_ALLOC_TBL, handle);
  413. err = secmem_execute(CMD_SEC_MEM_UNREF_TBL, &param);
  414. if (!err)
  415. secmem_handle_unregister(ctx, handle);
  416. break;
  417. case SECMEM_MEM_USAGE_DUMP:
  418. if (!(file->f_mode & FMODE_WRITE))
  419. return -EROFS;
  420. err = secmem_execute(CMD_SEC_MEM_USAGE_DUMP, &param);
  421. break;
  422. #ifdef SECMEM_DEBUG_DUMP
  423. case SECMEM_MEM_DUMP_INFO:
  424. if (!(file->f_mode & FMODE_WRITE))
  425. return -EROFS;
  426. err = secmem_execute(CMD_SEC_MEM_DUMP_INFO, &param);
  427. break;
  428. #endif
  429. default:
  430. return -ENOTTY;
  431. }
  432. if (!err)
  433. err = copy_to_user((void *)arg, &param, sizeof(param));
  434. return err;
  435. }
  436. static inline int secmem_kernel_open(void)
  437. {
  438. if (!secmem_k_session_opened) {
  439. if (secmem_session_open() < 0)
  440. return -ENXIO;
  441. secmem_k_session_opened = 1;
  442. }
  443. return 0;
  444. }
  445. #if defined(CONFIG_CMA) && defined(CONFIG_MTK_SVP)
  446. int secmem_api_enable(u32 start, u32 size)
  447. {
  448. int err = 0;
  449. struct secmem_param param = { 0 };
  450. secmem_kernel_open();
  451. param.sec_handle = start;
  452. param.size = size;
  453. err = secmem_execute(CMD_SEC_MEM_ENABLE, &param);
  454. if (err)
  455. MSG(ERR, "secmem_api_enable failed: %d\n", err);
  456. return err;
  457. }
  458. EXPORT_SYMBOL(secmem_api_enable);
  459. int secmem_api_disable(void)
  460. {
  461. int err = 0;
  462. struct secmem_param param = { 0 };
  463. secmem_kernel_open();
  464. err = secmem_execute(CMD_SEC_MEM_DISABLE, &param);
  465. if (err)
  466. MSG(ERR, "secmem_api_disable failed: %d\n", err);
  467. return err;
  468. }
  469. EXPORT_SYMBOL(secmem_api_disable);
  470. int secmem_api_query(u32 *allocate_size)
  471. {
  472. int err = 0;
  473. struct secmem_param param = { 0 };
  474. secmem_kernel_open();
  475. err = secmem_execute(CMD_SEC_MEM_ALLOCATED, &param);
  476. if (err) {
  477. MSG(ERR, "secmem_api_query failed: %d\n", err);
  478. *allocate_size = -1;
  479. } else {
  480. *allocate_size = param.size;
  481. }
  482. if (*allocate_size)
  483. secmem_execute(CMD_SEC_MEM_DUMP_INFO, &param);
  484. return err;
  485. }
  486. EXPORT_SYMBOL(secmem_api_query);
  487. #endif
  488. #ifdef SECMEM_KERNEL_API
  489. int secmem_api_alloc(u32 alignment, u32 size, u32 *refcount, u32 *sec_handle, uint8_t *owner,
  490. uint32_t id)
  491. {
  492. int ret = 0;
  493. struct secmem_param param;
  494. secmem_kernel_open();
  495. memset(&param, 0, sizeof(param));
  496. param.alignment = alignment;
  497. param.size = size;
  498. param.refcount = 0;
  499. param.sec_handle = 0;
  500. param.id = id;
  501. if (owner) {
  502. param.owner_len = strlen(owner) > MAX_NAME_SZ ? MAX_NAME_SZ : strlen(owner);
  503. memcpy(param.owner, owner, param.owner_len);
  504. param.owner[MAX_NAME_SZ - 1] = 0;
  505. }
  506. ret = secmem_execute(CMD_SEC_MEM_ALLOC, &param);
  507. if (ret != 0) {
  508. MSG(ERR, "%s: secmem_execute alloc failed!\n", __func__);
  509. return ret;
  510. }
  511. *refcount = param.refcount;
  512. *sec_handle = param.sec_handle;
  513. return 0;
  514. }
  515. EXPORT_SYMBOL(secmem_api_alloc);
  516. int secmem_api_unref(u32 sec_handle, uint8_t *owner, uint32_t id)
  517. {
  518. int ret = 0;
  519. struct secmem_param param;
  520. secmem_kernel_open();
  521. memset(&param, 0, sizeof(param));
  522. param.sec_handle = sec_handle;
  523. param.id = id;
  524. if (owner) {
  525. param.owner_len = strlen(owner) > MAX_NAME_SZ ? MAX_NAME_SZ : strlen(owner);
  526. memcpy(param.owner, owner, param.owner_len);
  527. param.owner[MAX_NAME_SZ - 1] = 0;
  528. }
  529. ret = secmem_execute(CMD_SEC_MEM_UNREF, &param);
  530. if (ret != 0) {
  531. MSG(ERR, "%s: secmem_execute unref failed!\n", __func__);
  532. return ret;
  533. }
  534. return 0;
  535. }
  536. EXPORT_SYMBOL(secmem_api_unref);
  537. int secmem_api_alloc_pa(u32 alignment, u32 size, u32 *refcount, u32 *sec_handle, uint8_t *owner,
  538. uint32_t id)
  539. {
  540. int ret = 0;
  541. struct secmem_param param;
  542. secmem_kernel_open();
  543. memset(&param, 0, sizeof(param));
  544. param.alignment = alignment;
  545. param.size = size;
  546. param.refcount = 0;
  547. param.sec_handle = 0;
  548. param.id = id;
  549. if (owner) {
  550. param.owner_len = strlen(owner) > MAX_NAME_SZ ? MAX_NAME_SZ : strlen(owner);
  551. memcpy(param.owner, owner, param.owner_len);
  552. param.owner[MAX_NAME_SZ - 1] = 0;
  553. }
  554. ret = secmem_execute(CMD_SEC_MEM_ALLOC_PA, &param);
  555. if (ret != 0) {
  556. MSG(ERR, "%s: secmem_execute alloc failed!\n", __func__);
  557. return ret;
  558. }
  559. *refcount = param.refcount;
  560. *sec_handle = param.sec_handle;
  561. return 0;
  562. }
  563. EXPORT_SYMBOL(secmem_api_alloc_pa);
  564. int secmem_api_unref_pa(u32 sec_handle, uint8_t *owner, uint32_t id)
  565. {
  566. int ret = 0;
  567. struct secmem_param param;
  568. secmem_kernel_open();
  569. memset(&param, 0, sizeof(param));
  570. param.sec_handle = sec_handle;
  571. param.id = id;
  572. if (owner) {
  573. param.owner_len = strlen(owner) > MAX_NAME_SZ ? MAX_NAME_SZ : strlen(owner);
  574. memcpy(param.owner, owner, param.owner_len);
  575. param.owner[MAX_NAME_SZ - 1] = 0;
  576. }
  577. ret = secmem_execute(CMD_SEC_MEM_UNREF_PA, &param);
  578. if (ret != 0) {
  579. MSG(ERR, "%s: secmem_execute unref failed!\n", __func__);
  580. return ret;
  581. }
  582. return 0;
  583. }
  584. EXPORT_SYMBOL(secmem_api_unref_pa);
  585. #endif
  586. #ifdef SECMEM_DEBUG_INTERFACE
  587. #include <mach/emi_mpu.h>
  588. #include <mach/mt_secure_api.h>
  589. static int secmem_write(struct file *file, const char __user *buffer, size_t count, loff_t *data)
  590. {
  591. char desc[32];
  592. int len = 0;
  593. char cmd[10];
  594. len = (count < (sizeof(desc) - 1)) ? count : (sizeof(desc) - 1);
  595. if (copy_from_user(desc, buffer, len))
  596. return 0;
  597. desc[len] = '\0';
  598. if (sscanf(desc, "%s", cmd) == 1) {
  599. if (!strcmp(cmd, "1")) {
  600. pr_debug("[SECMEM] - test for command 1\n");
  601. tbase_trigger_aee_dump();
  602. } else if (!strcmp(cmd, "2")) {
  603. pr_debug("[SECMEM] - test for command 2\n");
  604. }
  605. }
  606. return count;
  607. }
  608. #endif
  609. static const struct file_operations secmem_fops = {
  610. .owner = THIS_MODULE,
  611. .open = secmem_open,
  612. .release = secmem_release,
  613. .unlocked_ioctl = secmem_ioctl,
  614. #ifdef CONFIG_COMPAT
  615. .compat_ioctl = secmem_ioctl,
  616. #endif
  617. #ifdef SECMEM_DEBUG_INTERFACE
  618. .write = secmem_write,
  619. #else
  620. .write = NULL,
  621. #endif
  622. .read = NULL,
  623. };
  624. static int __init secmem_init(void)
  625. {
  626. proc_create("secmem0", (S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP | S_IROTH), NULL,
  627. &secmem_fops);
  628. #ifdef SECMEM_DEBUG_INTERFACE
  629. {
  630. unsigned int sec_mem_mpu_attr =
  631. SET_ACCESS_PERMISSON(FORBIDDEN, SEC_RW, SEC_RW, FORBIDDEN);
  632. unsigned int set_mpu_ret = 0;
  633. set_mpu_ret =
  634. emi_mpu_set_region_protection(0xF6000000, 0xFFFFFFFF, 0, sec_mem_mpu_attr);
  635. pr_debug("[SECMEM] - test for set EMI MPU on region 0, ret:%d\n", set_mpu_ret);
  636. }
  637. #endif
  638. return 0;
  639. }
  640. late_initcall(secmem_init);