// SPDX-License-Identifier: GPL-2.0-only
/* Copyright(c) 2022 Intel Corporation. All rights reserved. */
#include <linux/libnvdimm.h>
#include <asm/unaligned.h>
#include <linux/module.h>
#include <linux/async.h>
#include <linux/slab.h>
#include <linux/memregion.h>
#include "cxlmem.h"
#include "cxl.h"

static unsigned long cxl_pmem_get_security_flags(struct nvdimm *nvdimm,
						 enum nvdimm_passphrase_type ptype)
{
	struct cxl_nvdimm *cxl_nvd = nvdimm_provider_data(nvdimm);
	struct cxl_memdev *cxlmd = cxl_nvd->cxlmd;
	struct cxl_memdev_state *mds = to_cxl_memdev_state(cxlmd->cxlds);
	unsigned long security_flags = 0;
	struct cxl_get_security_output {
		__le32 flags;
	} out;
	struct cxl_mbox_cmd mbox_cmd;
	u32 sec_out;
	int rc;

	mbox_cmd = (struct cxl_mbox_cmd) {
		.opcode = CXL_MBOX_OP_GET_SECURITY_STATE,
		.size_out = sizeof(out),
		.payload_out = &out,
	};

	rc = cxl_internal_send_cmd(mds, &mbox_cmd);
	if (rc < 0)
		return 0;

	sec_out = le32_to_cpu(out.flags);
	/* cache security state */
	mds->security.state = sec_out;

	if (ptype == NVDIMM_MASTER) {
		if (sec_out & CXL_PMEM_SEC_STATE_MASTER_PASS_SET)
			set_bit(NVDIMM_SECURITY_UNLOCKED, &security_flags);
		else
			set_bit(NVDIMM_SECURITY_DISABLED, &security_flags);
		if (sec_out & CXL_PMEM_SEC_STATE_MASTER_PLIMIT)
			set_bit(NVDIMM_SECURITY_FROZEN, &security_flags);
		return security_flags;
	}

	if (sec_out & CXL_PMEM_SEC_STATE_USER_PASS_SET) {
		if (sec_out & CXL_PMEM_SEC_STATE_FROZEN ||
		    sec_out & CXL_PMEM_SEC_STATE_USER_PLIMIT)
			set_bit(NVDIMM_SECURITY_FROZEN, &security_flags);

		if (sec_out & CXL_PMEM_SEC_STATE_LOCKED)
			set_bit(NVDIMM_SECURITY_LOCKED, &security_flags);
		else
			set_bit(NVDIMM_SECURITY_UNLOCKED, &security_flags);
	} else {
		set_bit(NVDIMM_SECURITY_DISABLED, &security_flags);
	}

	return security_flags;
}

static int cxl_pmem_security_change_key(struct nvdimm *nvdimm,
					const struct nvdimm_key_data *old_data,
					const struct nvdimm_key_data *new_data,
					enum nvdimm_passphrase_type ptype)
{
	struct cxl_nvdimm *cxl_nvd = nvdimm_provider_data(nvdimm);
	struct cxl_memdev *cxlmd = cxl_nvd->cxlmd;
	struct cxl_memdev_state *mds = to_cxl_memdev_state(cxlmd->cxlds);
	struct cxl_mbox_cmd mbox_cmd;
	struct cxl_set_pass set_pass;

	set_pass = (struct cxl_set_pass) {
		.type = ptype == NVDIMM_MASTER ? CXL_PMEM_SEC_PASS_MASTER :
						 CXL_PMEM_SEC_PASS_USER,
	};
	memcpy(set_pass.old_pass, old_data->data, NVDIMM_PASSPHRASE_LEN);
	memcpy(set_pass.new_pass, new_data->data, NVDIMM_PASSPHRASE_LEN);

	mbox_cmd = (struct cxl_mbox_cmd) {
		.opcode = CXL_MBOX_OP_SET_PASSPHRASE,
		.size_in = sizeof(set_pass),
		.payload_in = &set_pass,
	};

	return cxl_internal_send_cmd(mds, &mbox_cmd);
}

static int __cxl_pmem_security_disable(struct nvdimm *nvdimm,
				       const struct nvdimm_key_data *key_data,
				       enum nvdimm_passphrase_type ptype)
{
	struct cxl_nvdimm *cxl_nvd = nvdimm_provider_data(nvdimm);
	struct cxl_memdev *cxlmd = cxl_nvd->cxlmd;
	struct cxl_memdev_state *mds = to_cxl_memdev_state(cxlmd->cxlds);
	struct cxl_disable_pass dis_pass;
	struct cxl_mbox_cmd mbox_cmd;

	dis_pass = (struct cxl_disable_pass) {
		.type = ptype == NVDIMM_MASTER ? CXL_PMEM_SEC_PASS_MASTER :
						 CXL_PMEM_SEC_PASS_USER,
	};
	memcpy(dis_pass.pass, key_data->data, NVDIMM_PASSPHRASE_LEN);

	mbox_cmd = (struct cxl_mbox_cmd) {
		.opcode = CXL_MBOX_OP_DISABLE_PASSPHRASE,
		.size_in = sizeof(dis_pass),
		.payload_in = &dis_pass,
	};

	return cxl_internal_send_cmd(mds, &mbox_cmd);
}

static int cxl_pmem_security_disable(struct nvdimm *nvdimm,
				     const struct nvdimm_key_data *key_data)
{
	return __cxl_pmem_security_disable(nvdimm, key_data, NVDIMM_USER);
}

static int cxl_pmem_security_disable_master(struct nvdimm *nvdimm,
					    const struct nvdimm_key_data *key_data)
{
	return __cxl_pmem_security_disable(nvdimm, key_data, NVDIMM_MASTER);
}

static int cxl_pmem_security_freeze(struct nvdimm *nvdimm)
{
	struct cxl_nvdimm *cxl_nvd = nvdimm_provider_data(nvdimm);
	struct cxl_memdev *cxlmd = cxl_nvd->cxlmd;
	struct cxl_memdev_state *mds = to_cxl_memdev_state(cxlmd->cxlds);
	struct cxl_mbox_cmd mbox_cmd = {
		.opcode = CXL_MBOX_OP_FREEZE_SECURITY,
	};

	return cxl_internal_send_cmd(mds, &mbox_cmd);
}

static int cxl_pmem_security_unlock(struct nvdimm *nvdimm,
				    const struct nvdimm_key_data *key_data)
{
	struct cxl_nvdimm *cxl_nvd = nvdimm_provider_data(nvdimm);
	struct cxl_memdev *cxlmd = cxl_nvd->cxlmd;
	struct cxl_memdev_state *mds = to_cxl_memdev_state(cxlmd->cxlds);
	u8 pass[NVDIMM_PASSPHRASE_LEN];
	struct cxl_mbox_cmd mbox_cmd;
	int rc;

	memcpy(pass, key_data->data, NVDIMM_PASSPHRASE_LEN);
	mbox_cmd = (struct cxl_mbox_cmd) {
		.opcode = CXL_MBOX_OP_UNLOCK,
		.size_in = NVDIMM_PASSPHRASE_LEN,
		.payload_in = pass,
	};

	rc = cxl_internal_send_cmd(mds, &mbox_cmd);
	if (rc < 0)
		return rc;

	return 0;
}

static int cxl_pmem_security_passphrase_erase(struct nvdimm *nvdimm,
					      const struct nvdimm_key_data *key,
					      enum nvdimm_passphrase_type ptype)
{
	struct cxl_nvdimm *cxl_nvd = nvdimm_provider_data(nvdimm);
	struct cxl_memdev *cxlmd = cxl_nvd->cxlmd;
	struct cxl_memdev_state *mds = to_cxl_memdev_state(cxlmd->cxlds);
	struct cxl_mbox_cmd mbox_cmd;
	struct cxl_pass_erase erase;
	int rc;

	erase = (struct cxl_pass_erase) {
		.type = ptype == NVDIMM_MASTER ? CXL_PMEM_SEC_PASS_MASTER :
						 CXL_PMEM_SEC_PASS_USER,
	};
	memcpy(erase.pass, key->data, NVDIMM_PASSPHRASE_LEN);
	mbox_cmd = (struct cxl_mbox_cmd) {
		.opcode = CXL_MBOX_OP_PASSPHRASE_SECURE_ERASE,
		.size_in = sizeof(erase),
		.payload_in = &erase,
	};

	rc = cxl_internal_send_cmd(mds, &mbox_cmd);
	if (rc < 0)
		return rc;

	return 0;
}

static const struct nvdimm_security_ops __cxl_security_ops = {
	.get_flags = cxl_pmem_get_security_flags,
	.change_key = cxl_pmem_security_change_key,
	.disable = cxl_pmem_security_disable,
	.freeze = cxl_pmem_security_freeze,
	.unlock = cxl_pmem_security_unlock,
	.erase = cxl_pmem_security_passphrase_erase,
	.disable_master = cxl_pmem_security_disable_master,
};

const struct nvdimm_security_ops *cxl_security_ops = &__cxl_security_ops;
