rpmb.c 4.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185
  1. // SPDX-License-Identifier: BSD-2-Clause
  2. /*
  3. * Copyright (c) 2018 Linaro Limited
  4. */
  5. #include <common.h>
  6. #include <dm.h>
  7. #include <log.h>
  8. #include <tee.h>
  9. #include <mmc.h>
  10. #include <dm/device_compat.h>
  11. #include "optee_msg.h"
  12. #include "optee_private.h"
  13. /*
  14. * Request and response definitions must be in sync with the secure side of
  15. * OP-TEE.
  16. */
  17. /* Request */
  18. struct rpmb_req {
  19. u16 cmd;
  20. #define RPMB_CMD_DATA_REQ 0x00
  21. #define RPMB_CMD_GET_DEV_INFO 0x01
  22. u16 dev_id;
  23. u16 block_count;
  24. /* Optional data frames (rpmb_data_frame) follow */
  25. };
  26. #define RPMB_REQ_DATA(req) ((void *)((struct rpmb_req *)(req) + 1))
  27. /* Response to device info request */
  28. struct rpmb_dev_info {
  29. u8 cid[16];
  30. u8 rpmb_size_mult; /* EXT CSD-slice 168: RPMB Size */
  31. u8 rel_wr_sec_c; /* EXT CSD-slice 222: Reliable Write Sector */
  32. /* Count */
  33. u8 ret_code;
  34. #define RPMB_CMD_GET_DEV_INFO_RET_OK 0x00
  35. #define RPMB_CMD_GET_DEV_INFO_RET_ERROR 0x01
  36. };
  37. static void release_mmc(struct optee_private *priv)
  38. {
  39. int rc;
  40. if (!priv->rpmb_mmc)
  41. return;
  42. rc = blk_select_hwpart_devnum(IF_TYPE_MMC, priv->rpmb_dev_id,
  43. priv->rpmb_original_part);
  44. if (rc)
  45. debug("%s: blk_select_hwpart_devnum() failed: %d\n",
  46. __func__, rc);
  47. priv->rpmb_mmc = NULL;
  48. }
  49. static struct mmc *get_mmc(struct optee_private *priv, int dev_id)
  50. {
  51. struct mmc *mmc;
  52. int rc;
  53. if (priv->rpmb_mmc && priv->rpmb_dev_id == dev_id)
  54. return priv->rpmb_mmc;
  55. release_mmc(priv);
  56. mmc = find_mmc_device(dev_id);
  57. if (!mmc) {
  58. debug("Cannot find RPMB device\n");
  59. return NULL;
  60. }
  61. if (!(mmc->version & MMC_VERSION_MMC)) {
  62. debug("Device id %d is not an eMMC device\n", dev_id);
  63. return NULL;
  64. }
  65. if (mmc->version < MMC_VERSION_4_41) {
  66. debug("Device id %d: RPMB not supported before version 4.41\n",
  67. dev_id);
  68. return NULL;
  69. }
  70. priv->rpmb_original_part = mmc_get_blk_desc(mmc)->hwpart;
  71. rc = blk_select_hwpart_devnum(IF_TYPE_MMC, dev_id, MMC_PART_RPMB);
  72. if (rc) {
  73. debug("Device id %d: cannot select RPMB partition: %d\n",
  74. dev_id, rc);
  75. return NULL;
  76. }
  77. priv->rpmb_mmc = mmc;
  78. priv->rpmb_dev_id = dev_id;
  79. return mmc;
  80. }
  81. static u32 rpmb_get_dev_info(u16 dev_id, struct rpmb_dev_info *info)
  82. {
  83. struct mmc *mmc = find_mmc_device(dev_id);
  84. int i;
  85. if (!mmc)
  86. return TEE_ERROR_ITEM_NOT_FOUND;
  87. if (!mmc->ext_csd)
  88. return TEE_ERROR_GENERIC;
  89. for (i = 0; i < ARRAY_SIZE(mmc->cid); i++)
  90. ((u32 *) info->cid)[i] = cpu_to_be32(mmc->cid[i]);
  91. info->rel_wr_sec_c = mmc->ext_csd[222];
  92. info->rpmb_size_mult = mmc->ext_csd[168];
  93. info->ret_code = RPMB_CMD_GET_DEV_INFO_RET_OK;
  94. return TEE_SUCCESS;
  95. }
  96. static u32 rpmb_process_request(struct optee_private *priv, void *req,
  97. ulong req_size, void *rsp, ulong rsp_size)
  98. {
  99. struct rpmb_req *sreq = req;
  100. struct mmc *mmc;
  101. if (req_size < sizeof(*sreq))
  102. return TEE_ERROR_BAD_PARAMETERS;
  103. switch (sreq->cmd) {
  104. case RPMB_CMD_DATA_REQ:
  105. mmc = get_mmc(priv, sreq->dev_id);
  106. if (!mmc)
  107. return TEE_ERROR_ITEM_NOT_FOUND;
  108. if (mmc_rpmb_route_frames(mmc, RPMB_REQ_DATA(req),
  109. req_size - sizeof(struct rpmb_req),
  110. rsp, rsp_size))
  111. return TEE_ERROR_BAD_PARAMETERS;
  112. return TEE_SUCCESS;
  113. case RPMB_CMD_GET_DEV_INFO:
  114. if (req_size != sizeof(struct rpmb_req) ||
  115. rsp_size != sizeof(struct rpmb_dev_info)) {
  116. debug("Invalid req/rsp size\n");
  117. return TEE_ERROR_BAD_PARAMETERS;
  118. }
  119. return rpmb_get_dev_info(sreq->dev_id, rsp);
  120. default:
  121. debug("Unsupported RPMB command: %d\n", sreq->cmd);
  122. return TEE_ERROR_BAD_PARAMETERS;
  123. }
  124. }
  125. void optee_suppl_cmd_rpmb(struct udevice *dev, struct optee_msg_arg *arg)
  126. {
  127. struct tee_shm *req_shm;
  128. struct tee_shm *rsp_shm;
  129. void *req_buf;
  130. void *rsp_buf;
  131. ulong req_size;
  132. ulong rsp_size;
  133. if (arg->num_params != 2 ||
  134. arg->params[0].attr != OPTEE_MSG_ATTR_TYPE_RMEM_INPUT ||
  135. arg->params[1].attr != OPTEE_MSG_ATTR_TYPE_RMEM_OUTPUT) {
  136. arg->ret = TEE_ERROR_BAD_PARAMETERS;
  137. return;
  138. }
  139. req_shm = (struct tee_shm *)(ulong)arg->params[0].u.rmem.shm_ref;
  140. req_buf = (u8 *)req_shm->addr + arg->params[0].u.rmem.offs;
  141. req_size = arg->params[0].u.rmem.size;
  142. rsp_shm = (struct tee_shm *)(ulong)arg->params[1].u.rmem.shm_ref;
  143. rsp_buf = (u8 *)rsp_shm->addr + arg->params[1].u.rmem.offs;
  144. rsp_size = arg->params[1].u.rmem.size;
  145. arg->ret = rpmb_process_request(dev_get_priv(dev), req_buf, req_size,
  146. rsp_buf, rsp_size);
  147. }
  148. void optee_suppl_rpmb_release(struct udevice *dev)
  149. {
  150. release_mmc(dev_get_priv(dev));
  151. }