// SPDX-License-Identifier: BSD-2-Clause
/*
 * Copyright (c) 2018 Linaro Limited
 */

#include <common.h>
#include <dm.h>
#include <log.h>
#include <tee.h>
#include <mmc.h>

#include "optee_msg.h"
#include "optee_private.h"

/*
 * Request and response definitions must be in sync with the secure side of
 * OP-TEE.
 */

/* Request */
struct rpmb_req {
	u16 cmd;
#define RPMB_CMD_DATA_REQ      0x00
#define RPMB_CMD_GET_DEV_INFO  0x01
	u16 dev_id;
	u16 block_count;
	/* Optional data frames (rpmb_data_frame) follow */
};

#define RPMB_REQ_DATA(req) ((void *)((struct rpmb_req *)(req) + 1))

/* Response to device info request */
struct rpmb_dev_info {
	u8 cid[16];
	u8 rpmb_size_mult;	/* EXT CSD-slice 168: RPMB Size */
	u8 rel_wr_sec_c;	/* EXT CSD-slice 222: Reliable Write Sector */
				/*                    Count */
	u8 ret_code;
#define RPMB_CMD_GET_DEV_INFO_RET_OK     0x00
#define RPMB_CMD_GET_DEV_INFO_RET_ERROR  0x01
};

static void release_mmc(struct optee_private *priv)
{
	int rc;

	if (!priv->rpmb_mmc)
		return;

	rc = blk_select_hwpart_devnum(IF_TYPE_MMC, priv->rpmb_dev_id,
				      priv->rpmb_original_part);
	if (rc)
		debug("%s: blk_select_hwpart_devnum() failed: %d\n",
		      __func__, rc);

	priv->rpmb_mmc = NULL;
}

static struct mmc *get_mmc(struct optee_private *priv, int dev_id)
{
	struct mmc *mmc;
	int rc;

	if (priv->rpmb_mmc && priv->rpmb_dev_id == dev_id)
		return priv->rpmb_mmc;

	release_mmc(priv);

	mmc = find_mmc_device(dev_id);
	if (!mmc) {
		debug("Cannot find RPMB device\n");
		return NULL;
	}
	if (!(mmc->version & MMC_VERSION_MMC)) {
		debug("Device id %d is not an eMMC device\n", dev_id);
		return NULL;
	}
	if (mmc->version < MMC_VERSION_4_41) {
		debug("Device id %d: RPMB not supported before version 4.41\n",
		      dev_id);
		return NULL;
	}

	priv->rpmb_original_part = mmc_get_blk_desc(mmc)->hwpart;

	rc = blk_select_hwpart_devnum(IF_TYPE_MMC, dev_id, MMC_PART_RPMB);
	if (rc) {
		debug("Device id %d: cannot select RPMB partition: %d\n",
		      dev_id, rc);
		return NULL;
	}

	priv->rpmb_mmc = mmc;
	priv->rpmb_dev_id = dev_id;
	return mmc;
}

static u32 rpmb_get_dev_info(u16 dev_id, struct rpmb_dev_info *info)
{
	struct mmc *mmc = find_mmc_device(dev_id);

	if (!mmc)
		return TEE_ERROR_ITEM_NOT_FOUND;

	if (!mmc->ext_csd)
		return TEE_ERROR_GENERIC;

	/*
	 * Reverse each 4 bytes of the 16 bytes CID array, as expected over at
	 * the OP-TEE side in order to derive the correct RPMB key.
	 *
	 * As it turns out, the swaped array also matches the definition of JEDEC
	 * spec, at least for the eMMC part used on newman, which means the original
	 * bytes order from mmc driver is off.
	 *
	 * This is all admittedly very confusing and there is no reliable way to
	 * verify which ordering is correct for a given part. The best we can do
	 * is probably to manually dump out the CID and compare against the spec.
	 */
	u8 *next = info->cid;
	for (int i = 0; i < ARRAY_SIZE(mmc->cid); i++) {
		*(next++) = mmc->cid[i] >> 24;
		*(next++) = mmc->cid[i] >> 16;
		*(next++) = mmc->cid[i] >> 8;
		*(next++) = mmc->cid[i];
	}

	info->rel_wr_sec_c = mmc->ext_csd[222];
	info->rpmb_size_mult = mmc->ext_csd[168];
	info->ret_code = RPMB_CMD_GET_DEV_INFO_RET_OK;

	return TEE_SUCCESS;
}

static u32 rpmb_process_request(struct optee_private *priv, void *req,
				ulong req_size, void *rsp, ulong rsp_size)
{
	struct rpmb_req *sreq = req;
	struct mmc *mmc;

	if (req_size < sizeof(*sreq))
		return TEE_ERROR_BAD_PARAMETERS;

	switch (sreq->cmd) {
	case RPMB_CMD_DATA_REQ:
		mmc = get_mmc(priv, sreq->dev_id);
		if (!mmc)
			return TEE_ERROR_ITEM_NOT_FOUND;
		if (mmc_rpmb_route_frames(mmc, RPMB_REQ_DATA(req),
					  req_size - sizeof(struct rpmb_req),
					  rsp, rsp_size))
			return TEE_ERROR_BAD_PARAMETERS;
		return TEE_SUCCESS;

	case RPMB_CMD_GET_DEV_INFO:
		if (req_size != sizeof(struct rpmb_req) ||
		    rsp_size != sizeof(struct rpmb_dev_info)) {
			debug("Invalid req/rsp size\n");
			return TEE_ERROR_BAD_PARAMETERS;
		}
		return rpmb_get_dev_info(sreq->dev_id, rsp);

	default:
		debug("Unsupported RPMB command: %d\n", sreq->cmd);
		return TEE_ERROR_BAD_PARAMETERS;
	}
}

void optee_suppl_cmd_rpmb(struct udevice *dev, struct optee_msg_arg *arg)
{
	void *req_buf;
	void *rsp_buf;
	ulong req_size;
	ulong rsp_size;

	if (arg->num_params != 2 ||
	    arg->params[0].attr != OPTEE_MSG_ATTR_TYPE_TMEM_INPUT ||
	    arg->params[1].attr != OPTEE_MSG_ATTR_TYPE_TMEM_OUTPUT) {
		arg->ret = TEE_ERROR_BAD_PARAMETERS;
		return;
	}

	req_buf = (u8 *)arg->params[0].u.tmem.buf_ptr;
	req_size = arg->params[0].u.tmem.size;

	rsp_buf = (u8 *)arg->params[1].u.tmem.buf_ptr;
	rsp_size = arg->params[1].u.tmem.size;

	arg->ret = rpmb_process_request(dev_get_priv(dev), req_buf, req_size,
					rsp_buf, rsp_size);
}

void optee_suppl_rpmb_release(struct udevice *dev)
{
	release_mmc(dev_get_priv(dev));
}
