// SPDX-License-Identifier: (GPL-2.0-only OR BSD-3-Clause)
//
// This file is provided under a dual BSD/GPLv2 license.  When using or
// redistributing this file, you may do so under either license.
//
// Copyright(c) 2022 Intel Corporation. All rights reserved.

#include <linux/firmware.h>
#include <sound/sof/ext_manifest4.h>
#include <sound/sof/ipc4/header.h>
#include <trace/events/sof.h>
#include "ipc4-priv.h"
#include "sof-audio.h"
#include "sof-priv.h"
#include "ops.h"

/* The module ID includes the id of the library it is part of at offset 12 */
#define SOF_IPC4_MOD_LIB_ID_SHIFT	12

static ssize_t sof_ipc4_fw_parse_ext_man(struct snd_sof_dev *sdev,
					 struct sof_ipc4_fw_library *fw_lib)
{
	struct sof_ipc4_fw_data *ipc4_data = sdev->private;
	const struct firmware *fw = fw_lib->sof_fw.fw;
	struct sof_man4_fw_binary_header *fw_header;
	struct sof_ext_manifest4_hdr *ext_man_hdr;
	struct sof_man4_module_config *fm_config;
	struct sof_ipc4_fw_module *fw_module;
	struct sof_man4_module *fm_entry;
	ssize_t remaining;
	u32 fw_hdr_offset;
	int i;

	if (!ipc4_data) {
		dev_err(sdev->dev, "%s: ipc4_data is not available\n", __func__);
		return -EINVAL;
	}

	remaining = fw->size;
	if (remaining <= sizeof(*ext_man_hdr)) {
		dev_err(sdev->dev, "Firmware size is too small: %zu\n", remaining);
		return -EINVAL;
	}

	ext_man_hdr = (struct sof_ext_manifest4_hdr *)fw->data;

	/*
	 * At the start of the firmware image we must have an extended manifest.
	 * Verify that the magic number is correct.
	 */
	if (ext_man_hdr->id != SOF_EXT_MAN4_MAGIC_NUMBER) {
		dev_err(sdev->dev,
			"Unexpected extended manifest magic number: %#x\n",
			ext_man_hdr->id);
		return -EINVAL;
	}

	fw_hdr_offset = ipc4_data->manifest_fw_hdr_offset;
	if (!fw_hdr_offset)
		return -EINVAL;

	if (remaining <= ext_man_hdr->len + fw_hdr_offset + sizeof(*fw_header)) {
		dev_err(sdev->dev, "Invalid firmware size %zu, should be at least %zu\n",
			remaining, ext_man_hdr->len + fw_hdr_offset + sizeof(*fw_header));
		return -EINVAL;
	}

	fw_header = (struct sof_man4_fw_binary_header *)
				(fw->data + ext_man_hdr->len + fw_hdr_offset);
	remaining -= (ext_man_hdr->len + fw_hdr_offset);

	if (remaining <= fw_header->len) {
		dev_err(sdev->dev, "Invalid fw_header->len %u\n", fw_header->len);
		return -EINVAL;
	}

	dev_info(sdev->dev, "Loaded firmware library: %s, version: %u.%u.%u.%u\n",
		 fw_header->name, fw_header->major_version, fw_header->minor_version,
		 fw_header->hotfix_version, fw_header->build_version);
	dev_dbg(sdev->dev, "Header length: %u, module count: %u\n",
		fw_header->len, fw_header->num_module_entries);

	fw_lib->modules = devm_kmalloc_array(sdev->dev, fw_header->num_module_entries,
					     sizeof(*fw_module), GFP_KERNEL);
	if (!fw_lib->modules)
		return -ENOMEM;

	fw_lib->name = fw_header->name;
	fw_lib->num_modules = fw_header->num_module_entries;
	fw_module = fw_lib->modules;

	fm_entry = (struct sof_man4_module *)((u8 *)fw_header + fw_header->len);
	remaining -= fw_header->len;

	if (remaining < fw_header->num_module_entries * sizeof(*fm_entry)) {
		dev_err(sdev->dev, "Invalid num_module_entries %u\n",
			fw_header->num_module_entries);
		return -EINVAL;
	}

	fm_config = (struct sof_man4_module_config *)
				(fm_entry + fw_header->num_module_entries);
	remaining -= (fw_header->num_module_entries * sizeof(*fm_entry));
	for (i = 0; i < fw_header->num_module_entries; i++) {
		memcpy(&fw_module->man4_module_entry, fm_entry, sizeof(*fm_entry));

		if (fm_entry->cfg_count) {
			if (remaining < (fm_entry->cfg_offset + fm_entry->cfg_count) *
			    sizeof(*fm_config)) {
				dev_err(sdev->dev, "Invalid module cfg_offset %u\n",
					fm_entry->cfg_offset);
				return -EINVAL;
			}

			/* a module's config is always the same size */
			fw_module->bss_size = fm_config[fm_entry->cfg_offset].is_bytes;

			dev_dbg(sdev->dev,
				"module %s: UUID %pUL cfg_count: %u, bss_size: %#x\n",
				fm_entry->name, &fm_entry->uuid, fm_entry->cfg_count,
				fw_module->bss_size);
		} else {
			fw_module->bss_size = 0;

			dev_dbg(sdev->dev, "module %s: UUID %pUL\n", fm_entry->name,
				&fm_entry->uuid);
		}

		fw_module->man4_module_entry.id = i;
		ida_init(&fw_module->m_ida);
		fw_module->private = NULL;

		fw_module++;
		fm_entry++;
	}

	return ext_man_hdr->len;
}

static size_t sof_ipc4_fw_parse_basefw_ext_man(struct snd_sof_dev *sdev)
{
	struct sof_ipc4_fw_data *ipc4_data = sdev->private;
	struct sof_ipc4_fw_library *fw_lib;
	ssize_t payload_offset;
	int ret;

	fw_lib = devm_kzalloc(sdev->dev, sizeof(*fw_lib), GFP_KERNEL);
	if (!fw_lib)
		return -ENOMEM;

	fw_lib->sof_fw.fw = sdev->basefw.fw;

	payload_offset = sof_ipc4_fw_parse_ext_man(sdev, fw_lib);
	if (payload_offset > 0) {
		fw_lib->sof_fw.payload_offset = payload_offset;

		/* basefw ID is 0 */
		fw_lib->id = 0;
		ret = xa_insert(&ipc4_data->fw_lib_xa, 0, fw_lib, GFP_KERNEL);
		if (ret)
			return ret;
	}

	return payload_offset;
}

static int sof_ipc4_load_library_by_uuid(struct snd_sof_dev *sdev,
					 unsigned long lib_id, const guid_t *uuid)
{
	struct sof_ipc4_fw_data *ipc4_data = sdev->private;
	struct sof_ipc4_fw_library *fw_lib;
	const char *fw_filename;
	ssize_t payload_offset;
	int ret, i, err;

	if (!sdev->pdata->fw_lib_prefix) {
		dev_err(sdev->dev,
			"Library loading is not supported due to not set library path\n");
		return -EINVAL;
	}

	if (!ipc4_data->load_library) {
		dev_err(sdev->dev, "Library loading is not supported on this platform\n");
		return -EOPNOTSUPP;
	}

	fw_lib = devm_kzalloc(sdev->dev, sizeof(*fw_lib), GFP_KERNEL);
	if (!fw_lib)
		return -ENOMEM;

	fw_filename = kasprintf(GFP_KERNEL, "%s/%pUL.bin",
				sdev->pdata->fw_lib_prefix, uuid);
	if (!fw_filename) {
		ret = -ENOMEM;
		goto free_fw_lib;
	}

	ret = request_firmware(&fw_lib->sof_fw.fw, fw_filename, sdev->dev);
	if (ret < 0) {
		dev_err(sdev->dev, "Library file '%s' is missing\n", fw_filename);
		goto free_filename;
	} else {
		dev_dbg(sdev->dev, "Library file '%s' loaded\n", fw_filename);
	}

	payload_offset = sof_ipc4_fw_parse_ext_man(sdev, fw_lib);
	if (payload_offset <= 0) {
		if (!payload_offset)
			ret = -EINVAL;
		else
			ret = payload_offset;

		goto release;
	}

	fw_lib->sof_fw.payload_offset = payload_offset;
	fw_lib->id = lib_id;

	/* Fix up the module ID numbers within the library */
	for (i = 0; i < fw_lib->num_modules; i++)
		fw_lib->modules[i].man4_module_entry.id |= (lib_id << SOF_IPC4_MOD_LIB_ID_SHIFT);

	/*
	 * Make sure that the DSP is booted and stays up while attempting the
	 * loading the library for the first time
	 */
	ret = pm_runtime_resume_and_get(sdev->dev);
	if (ret < 0 && ret != -EACCES) {
		dev_err_ratelimited(sdev->dev, "%s: pm_runtime resume failed: %d\n",
				    __func__, ret);
		goto release;
	}

	ret = ipc4_data->load_library(sdev, fw_lib, false);

	pm_runtime_mark_last_busy(sdev->dev);
	err = pm_runtime_put_autosuspend(sdev->dev);
	if (err < 0)
		dev_err_ratelimited(sdev->dev, "%s: pm_runtime idle failed: %d\n",
				    __func__, err);

	if (ret)
		goto release;

	ret = xa_insert(&ipc4_data->fw_lib_xa, lib_id, fw_lib, GFP_KERNEL);
	if (unlikely(ret))
		goto release;

	kfree(fw_filename);

	return 0;

release:
	release_firmware(fw_lib->sof_fw.fw);
	/* Allocated within sof_ipc4_fw_parse_ext_man() */
	devm_kfree(sdev->dev, fw_lib->modules);
free_filename:
	kfree(fw_filename);
free_fw_lib:
	devm_kfree(sdev->dev, fw_lib);

	return ret;
}

struct sof_ipc4_fw_module *sof_ipc4_find_module_by_uuid(struct snd_sof_dev *sdev,
							const guid_t *uuid)
{
	struct sof_ipc4_fw_data *ipc4_data = sdev->private;
	struct sof_ipc4_fw_library *fw_lib;
	unsigned long lib_id;
	int i, ret;

	if (guid_is_null(uuid))
		return NULL;

	xa_for_each(&ipc4_data->fw_lib_xa, lib_id, fw_lib) {
		for (i = 0; i < fw_lib->num_modules; i++) {
			if (guid_equal(uuid, &fw_lib->modules[i].man4_module_entry.uuid))
				return &fw_lib->modules[i];
		}
	}

	/*
	 * Do not attempt to load external library in case the maximum number of
	 * firmware libraries have been already loaded
	 */
	if ((lib_id + 1) == ipc4_data->max_libs_count) {
		dev_err(sdev->dev,
			"%s: Maximum allowed number of libraries reached (%u)\n",
			__func__, ipc4_data->max_libs_count);
		return NULL;
	}

	/* The module cannot be found, try to load it as a library */
	ret = sof_ipc4_load_library_by_uuid(sdev, lib_id + 1, uuid);
	if (ret)
		return NULL;

	/* Look for the module in the newly loaded library, it should be available now */
	xa_for_each_start(&ipc4_data->fw_lib_xa, lib_id, fw_lib, lib_id) {
		for (i = 0; i < fw_lib->num_modules; i++) {
			if (guid_equal(uuid, &fw_lib->modules[i].man4_module_entry.uuid))
				return &fw_lib->modules[i];
		}
	}

	return NULL;
}

static int sof_ipc4_validate_firmware(struct snd_sof_dev *sdev)
{
	struct sof_ipc4_fw_data *ipc4_data = sdev->private;
	u32 fw_hdr_offset = ipc4_data->manifest_fw_hdr_offset;
	struct sof_man4_fw_binary_header *fw_header;
	const struct firmware *fw = sdev->basefw.fw;
	struct sof_ext_manifest4_hdr *ext_man_hdr;

	ext_man_hdr = (struct sof_ext_manifest4_hdr *)fw->data;
	fw_header = (struct sof_man4_fw_binary_header *)
				(fw->data + ext_man_hdr->len + fw_hdr_offset);

	/* TODO: Add firmware verification code here */

	dev_dbg(sdev->dev, "Validated firmware version: %u.%u.%u.%u\n",
		fw_header->major_version, fw_header->minor_version,
		fw_header->hotfix_version, fw_header->build_version);

	return 0;
}

int sof_ipc4_query_fw_configuration(struct snd_sof_dev *sdev)
{
	struct sof_ipc4_fw_data *ipc4_data = sdev->private;
	const struct sof_ipc_ops *iops = sdev->ipc->ops;
	struct sof_ipc4_fw_version *fw_ver;
	struct sof_ipc4_tuple *tuple;
	struct sof_ipc4_msg msg;
	size_t offset = 0;
	int ret;

	/* Get the firmware configuration */
	msg.primary = SOF_IPC4_MSG_TARGET(SOF_IPC4_MODULE_MSG);
	msg.primary |= SOF_IPC4_MSG_DIR(SOF_IPC4_MSG_REQUEST);
	msg.primary |= SOF_IPC4_MOD_ID(SOF_IPC4_MOD_INIT_BASEFW_MOD_ID);
	msg.primary |= SOF_IPC4_MOD_INSTANCE(SOF_IPC4_MOD_INIT_BASEFW_INSTANCE_ID);
	msg.extension = SOF_IPC4_MOD_EXT_MSG_PARAM_ID(SOF_IPC4_FW_PARAM_FW_CONFIG);

	msg.data_size = sdev->ipc->max_payload_size;
	msg.data_ptr = kzalloc(msg.data_size, GFP_KERNEL);
	if (!msg.data_ptr)
		return -ENOMEM;

	ret = iops->set_get_data(sdev, &msg, msg.data_size, false);
	if (ret)
		goto out;

	while (offset < msg.data_size) {
		tuple = (struct sof_ipc4_tuple *)((u8 *)msg.data_ptr + offset);

		switch (tuple->type) {
		case SOF_IPC4_FW_CFG_FW_VERSION:
			fw_ver = (struct sof_ipc4_fw_version *)tuple->value;

			dev_info(sdev->dev,
				 "Booted firmware version: %u.%u.%u.%u\n",
				 fw_ver->major, fw_ver->minor, fw_ver->hotfix,
				 fw_ver->build);
			break;
		case SOF_IPC4_FW_CFG_DL_MAILBOX_BYTES:
			trace_sof_ipc4_fw_config(sdev, "DL mailbox size", *tuple->value);
			break;
		case SOF_IPC4_FW_CFG_UL_MAILBOX_BYTES:
			trace_sof_ipc4_fw_config(sdev, "UL mailbox size", *tuple->value);
			break;
		case SOF_IPC4_FW_CFG_TRACE_LOG_BYTES:
			trace_sof_ipc4_fw_config(sdev, "Trace log size", *tuple->value);
			ipc4_data->mtrace_log_bytes = *tuple->value;
			break;
		case SOF_IPC4_FW_CFG_MAX_LIBS_COUNT:
			trace_sof_ipc4_fw_config(sdev, "maximum number of libraries",
						 *tuple->value);
			ipc4_data->max_libs_count = *tuple->value;
			if (!ipc4_data->max_libs_count)
				ipc4_data->max_libs_count = 1;
			break;
		case SOF_IPC4_FW_CFG_MAX_PPL_COUNT:
			ipc4_data->max_num_pipelines = *tuple->value;
			trace_sof_ipc4_fw_config(sdev, "Max PPL count %d",
						 ipc4_data->max_num_pipelines);
			if (ipc4_data->max_num_pipelines <= 0) {
				dev_err(sdev->dev, "Invalid max_num_pipelines %d",
					ipc4_data->max_num_pipelines);
				ret = -EINVAL;
				goto out;
			}
			break;
		default:
			break;
		}

		offset += sizeof(*tuple) + tuple->size;
	}

out:
	kfree(msg.data_ptr);

	return ret;
}

int sof_ipc4_reload_fw_libraries(struct snd_sof_dev *sdev)
{
	struct sof_ipc4_fw_data *ipc4_data = sdev->private;
	struct sof_ipc4_fw_library *fw_lib;
	unsigned long lib_id;
	int ret = 0;

	xa_for_each_start(&ipc4_data->fw_lib_xa, lib_id, fw_lib, 1) {
		ret = ipc4_data->load_library(sdev, fw_lib, true);
		if (ret) {
			dev_err(sdev->dev, "%s: Failed to reload library: %s, %d\n",
				__func__, fw_lib->name, ret);
			break;
		}
	}

	return ret;
}

const struct sof_ipc_fw_loader_ops ipc4_loader_ops = {
	.validate = sof_ipc4_validate_firmware,
	.parse_ext_manifest = sof_ipc4_fw_parse_basefw_ext_man,
};
