// SPDX-License-Identifier: GPL-2.0-only
/* Copyright(c) 2022 Intel Corporation. */

#include <linux/firmware.h>
#include <asm/cpu.h>
#include <linux/slab.h>
#include <asm/microcode_intel.h>

#include "ifs.h"

struct ifs_header {
	u32 header_ver;
	u32 blob_revision;
	u32 date;
	u32 processor_sig;
	u32 check_sum;
	u32 loader_rev;
	u32 processor_flags;
	u32 metadata_size;
	u32 total_size;
	u32 fusa_info;
	u64 reserved;
};

#define IFS_HEADER_SIZE	(sizeof(struct ifs_header))
static struct ifs_header *ifs_header_ptr;	/* pointer to the ifs image header */
static u64 ifs_hash_ptr;			/* Address of ifs metadata (hash) */
static u64 ifs_test_image_ptr;			/* 256B aligned address of test pattern */
static DECLARE_COMPLETION(ifs_done);

static const char * const scan_hash_status[] = {
	[0] = "No error reported",
	[1] = "Attempt to copy scan hashes when copy already in progress",
	[2] = "Secure Memory not set up correctly",
	[3] = "FuSaInfo.ProgramID does not match or ff-mm-ss does not match",
	[4] = "Reserved",
	[5] = "Integrity check failed",
	[6] = "Scan reload or test is in progress"
};

static const char * const scan_authentication_status[] = {
	[0] = "No error reported",
	[1] = "Attempt to authenticate a chunk which is already marked as authentic",
	[2] = "Chunk authentication error. The hash of chunk did not match expected value"
};

/*
 * To copy scan hashes and authenticate test chunks, the initiating cpu must point
 * to the EDX:EAX to the test image in linear address.
 * Run wrmsr(MSR_COPY_SCAN_HASHES) for scan hash copy and run wrmsr(MSR_AUTHENTICATE_AND_COPY_CHUNK)
 * for scan hash copy and test chunk authentication.
 */
static void copy_hashes_authenticate_chunks(struct work_struct *work)
{
	struct ifs_work *local_work = container_of(work, struct ifs_work, w);
	union ifs_scan_hashes_status hashes_status;
	union ifs_chunks_auth_status chunk_status;
	struct device *dev = local_work->dev;
	int i, num_chunks, chunk_size;
	struct ifs_data *ifsd;
	u64 linear_addr, base;
	u32 err_code;

	ifsd = ifs_get_data(dev);
	/* run scan hash copy */
	wrmsrl(MSR_COPY_SCAN_HASHES, ifs_hash_ptr);
	rdmsrl(MSR_SCAN_HASHES_STATUS, hashes_status.data);

	/* enumerate the scan image information */
	num_chunks = hashes_status.num_chunks;
	chunk_size = hashes_status.chunk_size * 1024;
	err_code = hashes_status.error_code;

	if (!hashes_status.valid) {
		ifsd->loading_error = true;
		if (err_code >= ARRAY_SIZE(scan_hash_status)) {
			dev_err(dev, "invalid error code 0x%x for hash copy\n", err_code);
			goto done;
		}
		dev_err(dev, "Hash copy error : %s", scan_hash_status[err_code]);
		goto done;
	}

	/* base linear address to the scan data */
	base = ifs_test_image_ptr;

	/* scan data authentication and copy chunks to secured memory */
	for (i = 0; i < num_chunks; i++) {
		linear_addr = base + i * chunk_size;
		linear_addr |= i;

		wrmsrl(MSR_AUTHENTICATE_AND_COPY_CHUNK, linear_addr);
		rdmsrl(MSR_CHUNKS_AUTHENTICATION_STATUS, chunk_status.data);

		ifsd->valid_chunks = chunk_status.valid_chunks;
		err_code = chunk_status.error_code;

		if (err_code) {
			ifsd->loading_error = true;
			if (err_code >= ARRAY_SIZE(scan_authentication_status)) {
				dev_err(dev,
					"invalid error code 0x%x for authentication\n", err_code);
				goto done;
			}
			dev_err(dev, "Chunk authentication error %s\n",
				scan_authentication_status[err_code]);
			goto done;
		}
	}
done:
	complete(&ifs_done);
}

/*
 * IFS requires scan chunks authenticated per each socket in the platform.
 * Once the test chunk is authenticated, it is automatically copied to secured memory
 * and proceed the authentication for the next chunk.
 */
static int scan_chunks_sanity_check(struct device *dev)
{
	int metadata_size, curr_pkg, cpu, ret = -ENOMEM;
	struct ifs_data *ifsd = ifs_get_data(dev);
	bool *package_authenticated;
	struct ifs_work local_work;
	char *test_ptr;

	package_authenticated = kcalloc(topology_max_packages(), sizeof(bool), GFP_KERNEL);
	if (!package_authenticated)
		return ret;

	metadata_size = ifs_header_ptr->metadata_size;

	/* Spec says that if the Meta Data Size = 0 then it should be treated as 2000 */
	if (metadata_size == 0)
		metadata_size = 2000;

	/* Scan chunk start must be 256 byte aligned */
	if ((metadata_size + IFS_HEADER_SIZE) % 256) {
		dev_err(dev, "Scan pattern offset within the binary is not 256 byte aligned\n");
		return -EINVAL;
	}

	test_ptr = (char *)ifs_header_ptr + IFS_HEADER_SIZE + metadata_size;
	ifsd->loading_error = false;

	ifs_test_image_ptr = (u64)test_ptr;
	ifsd->loaded_version = ifs_header_ptr->blob_revision;

	/* copy the scan hash and authenticate per package */
	cpus_read_lock();
	for_each_online_cpu(cpu) {
		curr_pkg = topology_physical_package_id(cpu);
		if (package_authenticated[curr_pkg])
			continue;
		reinit_completion(&ifs_done);
		local_work.dev = dev;
		INIT_WORK(&local_work.w, copy_hashes_authenticate_chunks);
		schedule_work_on(cpu, &local_work.w);
		wait_for_completion(&ifs_done);
		if (ifsd->loading_error)
			goto out;
		package_authenticated[curr_pkg] = 1;
	}
	ret = 0;
out:
	cpus_read_unlock();
	kfree(package_authenticated);

	return ret;
}

static int ifs_sanity_check(struct device *dev,
			    const struct microcode_header_intel *mc_header)
{
	unsigned long total_size, data_size;
	u32 sum, *mc;

	total_size = get_totalsize(mc_header);
	data_size = get_datasize(mc_header);

	if ((data_size + MC_HEADER_SIZE > total_size) || (total_size % sizeof(u32))) {
		dev_err(dev, "bad ifs data file size.\n");
		return -EINVAL;
	}

	if (mc_header->ldrver != 1 || mc_header->hdrver != 1) {
		dev_err(dev, "invalid/unknown ifs update format.\n");
		return -EINVAL;
	}

	mc = (u32 *)mc_header;
	sum = 0;
	for (int i = 0; i < total_size / sizeof(u32); i++)
		sum += mc[i];

	if (sum) {
		dev_err(dev, "bad ifs data checksum, aborting.\n");
		return -EINVAL;
	}

	return 0;
}

static bool find_ifs_matching_signature(struct device *dev, struct ucode_cpu_info *uci,
					const struct microcode_header_intel *shdr)
{
	unsigned int mc_size;

	mc_size = get_totalsize(shdr);

	if (!mc_size || ifs_sanity_check(dev, shdr) < 0) {
		dev_err(dev, "ifs sanity check failure\n");
		return false;
	}

	if (!intel_cpu_signatures_match(uci->cpu_sig.sig, uci->cpu_sig.pf, shdr->sig, shdr->pf)) {
		dev_err(dev, "ifs signature, pf not matching\n");
		return false;
	}

	return true;
}

static bool ifs_image_sanity_check(struct device *dev, const struct microcode_header_intel *data)
{
	struct ucode_cpu_info uci;

	intel_cpu_collect_info(&uci);

	return find_ifs_matching_signature(dev, &uci, data);
}

/*
 * Load ifs image. Before loading ifs module, the ifs image must be located
 * in /lib/firmware/intel/ifs and named as {family/model/stepping}.{testname}.
 */
void ifs_load_firmware(struct device *dev)
{
	struct ifs_data *ifsd = ifs_get_data(dev);
	const struct firmware *fw;
	char scan_path[32];
	int ret;

	snprintf(scan_path, sizeof(scan_path), "intel/ifs/%02x-%02x-%02x.scan",
		 boot_cpu_data.x86, boot_cpu_data.x86_model, boot_cpu_data.x86_stepping);

	ret = request_firmware_direct(&fw, scan_path, dev);
	if (ret) {
		dev_err(dev, "ifs file %s load failed\n", scan_path);
		goto done;
	}

	if (!ifs_image_sanity_check(dev, (struct microcode_header_intel *)fw->data)) {
		dev_err(dev, "ifs header sanity check failed\n");
		goto release;
	}

	ifs_header_ptr = (struct ifs_header *)fw->data;
	ifs_hash_ptr = (u64)(ifs_header_ptr + 1);

	ret = scan_chunks_sanity_check(dev);
release:
	release_firmware(fw);
done:
	ifsd->loaded = (ret == 0);
}
