/*
 * Copyright 2020 Advanced Micro Devices, Inc.
 *
 * Permission is hereby granted, free of charge, to any person obtaining a
 * copy of this software and associated documentation files (the "Software"),
 * to deal in the Software without restriction, including without limitation
 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
 * and/or sell copies of the Software, and to permit persons to whom the
 * Software is furnished to do so, subject to the following conditions:
 *
 * The above copyright notice and this permission notice shall be included in
 * all copies or substantial portions of the Software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
 * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
 * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
 * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
 * OTHER DEALINGS IN THE SOFTWARE.
 *
 */

#include <linux/debugfs.h>
#include <linux/firmware.h>
#include <linux/dma-mapping.h>

#include "amdgpu.h"
#include "amdgpu_fw_attestation.h"
#include "amdgpu_psp.h"
#include "amdgpu_ucode.h"
#include "soc15_common.h"

#define FW_ATTESTATION_DB_COOKIE        0x143b6a37
#define FW_ATTESTATION_RECORD_VALID	1
#define FW_ATTESTATION_MAX_SIZE		4096

struct FW_ATT_DB_HEADER {
	uint32_t AttDbVersion;           /* version of the fwar feature */
	uint32_t AttDbCookie;            /* cookie as an extra check for corrupt data */
};

struct FW_ATT_RECORD {
	uint16_t AttFwIdV1;              /* Legacy FW Type field */
	uint16_t AttFwIdV2;              /* V2 FW ID field */
	uint32_t AttFWVersion;           /* FW Version */
	uint16_t AttFWActiveFunctionID;  /* The VF ID (only in VF Attestation Table) */
	uint8_t  AttSource;              /* FW source indicator */
	uint8_t  RecordValid;            /* Indicates whether the record is a valid entry */
	uint32_t AttFwTaId;              /* Ta ID (only in TA Attestation Table) */
};

static ssize_t amdgpu_fw_attestation_debugfs_read(struct file *f,
						  char __user *buf,
						  size_t size,
						  loff_t *pos)
{
	struct amdgpu_device *adev = (struct amdgpu_device *)file_inode(f)->i_private;
	uint64_t records_addr = 0;
	uint64_t vram_pos = 0;
	struct FW_ATT_DB_HEADER fw_att_hdr = {0};
	struct FW_ATT_RECORD fw_att_record = {0};

	if (size < sizeof(struct FW_ATT_RECORD)) {
		drm_warn(adev_to_drm(adev), "FW attestation input buffer not enough memory");
		return -EINVAL;
	}

	if ((*pos + sizeof(struct FW_ATT_DB_HEADER)) >= FW_ATTESTATION_MAX_SIZE) {
		drm_warn(adev_to_drm(adev), "FW attestation out of bounds");
		return 0;
	}

	if (psp_get_fw_attestation_records_addr(&adev->psp, &records_addr)) {
		drm_warn(adev_to_drm(adev), "Failed to get FW attestation record address");
		return -EINVAL;
	}

	vram_pos =  records_addr - adev->gmc.vram_start;

	if (*pos == 0) {
		amdgpu_device_vram_access(adev,
					  vram_pos,
					  (uint32_t *)&fw_att_hdr,
					  sizeof(struct FW_ATT_DB_HEADER),
					  false);

		if (fw_att_hdr.AttDbCookie != FW_ATTESTATION_DB_COOKIE) {
			drm_warn(adev_to_drm(adev), "Invalid FW attestation cookie");
			return -EINVAL;
		}

		drm_info(adev_to_drm(adev), "FW attestation version = 0x%X",
			fw_att_hdr.AttDbVersion);
	}

	amdgpu_device_vram_access(adev,
				  vram_pos + sizeof(struct FW_ATT_DB_HEADER) + *pos,
				  (uint32_t *)&fw_att_record,
				  sizeof(struct FW_ATT_RECORD),
				  false);

	if (fw_att_record.RecordValid != FW_ATTESTATION_RECORD_VALID)
		return 0;

	if (copy_to_user(buf, (void *)&fw_att_record, sizeof(struct FW_ATT_RECORD)))
		return -EINVAL;

	*pos += sizeof(struct FW_ATT_RECORD);

	return sizeof(struct FW_ATT_RECORD);
}

static const struct file_operations amdgpu_fw_attestation_debugfs_ops = {
	.owner = THIS_MODULE,
	.read = amdgpu_fw_attestation_debugfs_read,
	.write = NULL,
	.llseek = default_llseek
};

static int amdgpu_is_fw_attestation_supported(struct amdgpu_device *adev)
{
	if (adev->flags & AMD_IS_APU)
		return 0;

	if (amdgpu_ip_version(adev, MP0_HWIP, 0) == IP_VERSION(14, 0, 2) ||
	    amdgpu_ip_version(adev, MP0_HWIP, 0) == IP_VERSION(14, 0, 3))
		return 0;

	if (adev->asic_type >= CHIP_SIENNA_CICHLID)
		return 1;

	return 0;
}

void amdgpu_fw_attestation_debugfs_init(struct amdgpu_device *adev)
{
	if (!amdgpu_is_fw_attestation_supported(adev))
		return;

	debugfs_create_file("amdgpu_fw_attestation",
			    0400,
			    adev_to_drm(adev)->primary->debugfs_root,
			    adev,
			    &amdgpu_fw_attestation_debugfs_ops);
}
