1 /* 2 * Copyright 2024, Rockchip Electronics Co., Ltd 3 * hisping lin, <hisping.lin@rock-chips.com> 4 * 5 * SPDX-License-Identifier: GPL-2.0+ 6 */ 7 #include <common.h> 8 #include <stdlib.h> 9 #include <command.h> 10 #include <mmc.h> 11 #include <optee_include/OpteeClientRPC.h> 12 #include <optee_include/tee_rpc.h> 13 #include <optee_include/tee_rpc_types.h> 14 #include <optee_include/teesmc_v2.h> 15 #include <optee_include/tee_client_api.h> 16 17 /* 18 * Execute an RPMB storage operation. 19 */ 20 #ifdef CONFIG_SUPPORT_EMMC_RPMB 21 22 static int rpmb_data_req(struct s_rpmb *req_frm, 23 size_t req_nfrm, 24 struct s_rpmb *rsp_frm, 25 size_t rsp_nfrm) 26 { 27 struct s_rpmb *req_packets = NULL; 28 uint16_t req_type; 29 int ret; 30 31 req_packets = memalign(CONFIG_SYS_CACHELINE_SIZE, sizeof(struct s_rpmb) * (req_nfrm + rsp_nfrm)); 32 if (!req_packets) 33 return -1; 34 35 memcpy(req_packets, req_frm, sizeof(struct s_rpmb) * req_nfrm); 36 37 req_type = cpu_to_be16(req_packets->request); 38 39 switch (req_type) { 40 case TEE_RPC_RPMB_MSG_TYPE_REQ_AUTH_KEY_PROGRAM: { 41 ret = do_programkey(req_packets); 42 break; 43 } 44 case TEE_RPC_RPMB_MSG_TYPE_REQ_WRITE_COUNTER_VAL_READ: { 45 do_readcounter(req_packets); 46 ret = TEEC_SUCCESS; 47 break; 48 } 49 case TEE_RPC_RPMB_MSG_TYPE_REQ_AUTH_DATA_WRITE: { 50 ret = do_authenticatedwrite(req_packets); 51 break; 52 } 53 case TEE_RPC_RPMB_MSG_TYPE_REQ_AUTH_DATA_READ: { 54 ret = do_authenticatedread(req_packets, rsp_nfrm); 55 break; 56 } 57 default: 58 ret = TEEC_ERROR_BAD_PARAMETERS; 59 break; 60 } 61 62 for (int i = 0; i < rsp_nfrm; i++) 63 memcpy(rsp_frm + i, req_packets + i, sizeof(struct s_rpmb)); 64 65 if (req_packets) 66 free(req_packets); 67 68 return ret; 69 } 70 71 static int rpmb_get_dev_info(struct tee_rpc_rpmb_dev_info *info) 72 { 73 struct mmc *mmc; 74 uint32_t cid_val[4]; 75 76 mmc = do_returnmmc(); 77 if (!mmc) 78 return -1; 79 80 for (int i = 0; i < 4; i++) 81 cid_val[i] = cpu_to_be32(mmc->cid[i]); 82 83 memcpy(info->cid, cid_val, sizeof(info->cid)); 84 85 info->rel_wr_sec_c = 1; 86 info->rpmb_size_mult = (uint8_t)(mmc->capacity_rpmb / (128 * 1024)); 87 info->ret_code = 0; 88 89 return 0; 90 } 91 92 TEEC_Result emmc_rpmb_process(t_teesmc32_arg *smc_arg) 93 { 94 t_teesmc32_param *smc_param; 95 struct tee_rpc_rpmb_cmd *rpmb_req; 96 struct s_rpmb *req_packets = NULL; 97 struct s_rpmb *rsp_packets = NULL; 98 size_t req_num, rsp_num; 99 struct tee_rpc_rpmb_dev_info *dev_info; 100 TEEC_Result result = TEEC_SUCCESS; 101 TEEC_Result status; 102 103 if (smc_arg->num_params != 2) { 104 result = TEEC_ERROR_BAD_PARAMETERS; 105 goto exit; 106 } 107 108 smc_param = TEESMC32_GET_PARAMS(smc_arg); 109 rpmb_req = (struct tee_rpc_rpmb_cmd *)(size_t) 110 smc_param[0].u.memref.buf_ptr; 111 112 switch (rpmb_req->cmd) { 113 case TEE_RPC_RPMB_CMD_DATA_REQ: { 114 req_packets = (struct s_rpmb *)(rpmb_req + 1); 115 rsp_packets = (struct s_rpmb *)(size_t)smc_param[1].u.memref.buf_ptr; 116 req_num = cpu_to_be16(req_packets->block_count); 117 req_num = (req_num == 0 ? 1 : req_num); 118 rsp_num = (rpmb_req->block_count == 0 ? 1 : rpmb_req->block_count); 119 120 status = rpmb_data_req(req_packets, req_num, rsp_packets, rsp_num); 121 if (status != 0) 122 result = TEEC_ERROR_GENERIC; 123 goto exit; 124 } 125 case TEE_RPC_RPMB_CMD_GET_DEV_INFO: { 126 dev_info = (struct tee_rpc_rpmb_dev_info *) 127 (size_t)smc_param[1].u.memref.buf_ptr; 128 129 status = rpmb_get_dev_info(dev_info); 130 if (status != 0) 131 result = TEEC_ERROR_GENERIC; 132 goto exit; 133 } 134 default: 135 result = TEEC_ERROR_BAD_PARAMETERS; 136 goto exit; 137 } 138 139 exit: 140 smc_arg->ret = result; 141 smc_arg->ret_origin = TEEC_ORIGIN_API; 142 143 return result; 144 } 145 146 #else 147 148 TEEC_Result emmc_rpmb_process(t_teesmc32_arg *smc_arg) 149 { 150 smc_arg = smc_arg; 151 return TEEC_ERROR_NOT_IMPLEMENTED; 152 } 153 154 #endif 155