// SPDX-License-Identifier: GPL-2.0+

#include <linux/efi.h>
#include <linux/module.h>
#include <linux/pstore.h>
#include <linux/slab.h>
#include <linux/ucs2_string.h>

MODULE_IMPORT_NS(EFIVAR);

#define DUMP_NAME_LEN 66

static unsigned int record_size = 1024;
module_param(record_size, uint, 0444);
MODULE_PARM_DESC(record_size, "size of each pstore UEFI var (in bytes, min/default=1024)");

#define PSTORE_EFI_ATTRIBUTES \
	(EFI_VARIABLE_NON_VOLATILE | \
	 EFI_VARIABLE_BOOTSERVICE_ACCESS | \
	 EFI_VARIABLE_RUNTIME_ACCESS)

static bool pstore_disable = IS_ENABLED(CONFIG_EFI_VARS_PSTORE_DEFAULT_DISABLE);

static int efivars_pstore_init(void);
static void efivars_pstore_exit(void);

static int efi_pstore_disable_set(const char *val, const struct kernel_param *kp)
{
	int err;
	bool old_pstore_disable = pstore_disable;

	err = param_set_bool(val, kp);
	if (err)
		return err;

	if (old_pstore_disable != pstore_disable) {
		if (pstore_disable)
			efivars_pstore_exit();
		else
			efivars_pstore_init();
	}

	return 0;
}

static const struct kernel_param_ops pstore_disable_ops = {
	.set	= efi_pstore_disable_set,
	.get	= param_get_bool,
};

module_param_cb(pstore_disable, &pstore_disable_ops, &pstore_disable, 0644);
__MODULE_PARM_TYPE(pstore_disable, "bool");

static int efi_pstore_open(struct pstore_info *psi)
{
	int err;

	err = efivar_lock();
	if (err)
		return err;

	psi->data = kzalloc(record_size, GFP_KERNEL);
	if (!psi->data)
		return -ENOMEM;

	return 0;
}

static int efi_pstore_close(struct pstore_info *psi)
{
	efivar_unlock();
	kfree(psi->data);
	return 0;
}

static inline u64 generic_id(u64 timestamp, unsigned int part, int count)
{
	return (timestamp * 100 + part) * 1000 + count;
}

static int efi_pstore_read_func(struct pstore_record *record,
				efi_char16_t *varname)
{
	unsigned long wlen, size = record_size;
	char name[DUMP_NAME_LEN], data_type;
	efi_status_t status;
	int cnt;
	unsigned int part;
	u64 time;

	ucs2_as_utf8(name, varname, DUMP_NAME_LEN);

	if (sscanf(name, "dump-type%u-%u-%d-%llu-%c",
		   &record->type, &part, &cnt, &time, &data_type) == 5) {
		record->id = generic_id(time, part, cnt);
		record->part = part;
		record->count = cnt;
		record->time.tv_sec = time;
		record->time.tv_nsec = 0;
		if (data_type == 'C')
			record->compressed = true;
		else
			record->compressed = false;
		record->ecc_notice_size = 0;
	} else if (sscanf(name, "dump-type%u-%u-%d-%llu",
		   &record->type, &part, &cnt, &time) == 4) {
		record->id = generic_id(time, part, cnt);
		record->part = part;
		record->count = cnt;
		record->time.tv_sec = time;
		record->time.tv_nsec = 0;
		record->compressed = false;
		record->ecc_notice_size = 0;
	} else if (sscanf(name, "dump-type%u-%u-%llu",
			  &record->type, &part, &time) == 3) {
		/*
		 * Check if an old format,
		 * which doesn't support holding
		 * multiple logs, remains.
		 */
		record->id = generic_id(time, part, 0);
		record->part = part;
		record->count = 0;
		record->time.tv_sec = time;
		record->time.tv_nsec = 0;
		record->compressed = false;
		record->ecc_notice_size = 0;
	} else
		return 0;

	record->buf = kmalloc(size, GFP_KERNEL);
	if (!record->buf)
		return -ENOMEM;

	status = efivar_get_variable(varname, &LINUX_EFI_CRASH_GUID, NULL,
				     &size, record->buf);
	if (status != EFI_SUCCESS) {
		kfree(record->buf);
		return efi_status_to_err(status);
	}

	/*
	 * Store the name of the variable in the pstore_record priv field, so
	 * we can reuse it later if we need to delete the EFI variable from the
	 * variable store.
	 */
	wlen = (ucs2_strnlen(varname, DUMP_NAME_LEN) + 1) * sizeof(efi_char16_t);
	record->priv = kmemdup(varname, wlen, GFP_KERNEL);
	if (!record->priv) {
		kfree(record->buf);
		return -ENOMEM;
	}

	return size;
}

static ssize_t efi_pstore_read(struct pstore_record *record)
{
	efi_char16_t *varname = record->psi->data;
	efi_guid_t guid = LINUX_EFI_CRASH_GUID;
	unsigned long varname_size;
	efi_status_t status;

	for (;;) {
		/*
		 * A small set of old UEFI implementations reject sizes
		 * above a certain threshold, the lowest seen in the wild
		 * is 512.
		 *
		 * TODO: Commonize with the iteration implementation in
		 *       fs/efivarfs to keep all the quirks in one place.
		 */
		varname_size = 512;

		/*
		 * If this is the first read() call in the pstore enumeration,
		 * varname will be the empty string, and the GetNextVariable()
		 * runtime service call will return the first EFI variable in
		 * its own enumeration order, ignoring the guid argument.
		 *
		 * Subsequent calls to GetNextVariable() must pass the name and
		 * guid values returned by the previous call, which is why we
		 * store varname in record->psi->data. Given that we only
		 * enumerate variables with the efi-pstore GUID, there is no
		 * need to record the guid return value.
		 */
		status = efivar_get_next_variable(&varname_size, varname, &guid);
		if (status == EFI_NOT_FOUND)
			return 0;

		if (status != EFI_SUCCESS)
			return efi_status_to_err(status);

		/* skip variables that don't concern us */
		if (efi_guidcmp(guid, LINUX_EFI_CRASH_GUID))
			continue;

		return efi_pstore_read_func(record, varname);
	}
}

static int efi_pstore_write(struct pstore_record *record)
{
	char name[DUMP_NAME_LEN];
	efi_char16_t efi_name[DUMP_NAME_LEN];
	efi_status_t status;
	int i;

	record->id = generic_id(record->time.tv_sec, record->part,
				record->count);

	/* Since we copy the entire length of name, make sure it is wiped. */
	memset(name, 0, sizeof(name));

	snprintf(name, sizeof(name), "dump-type%u-%u-%d-%lld-%c",
		 record->type, record->part, record->count,
		 (long long)record->time.tv_sec,
		 record->compressed ? 'C' : 'D');

	for (i = 0; i < DUMP_NAME_LEN; i++)
		efi_name[i] = name[i];

	if (efivar_trylock())
		return -EBUSY;
	status = efivar_set_variable_locked(efi_name, &LINUX_EFI_CRASH_GUID,
					    PSTORE_EFI_ATTRIBUTES,
					    record->size, record->psi->buf,
					    true);
	efivar_unlock();
	return efi_status_to_err(status);
};

static int efi_pstore_erase(struct pstore_record *record)
{
	efi_status_t status;

	status = efivar_set_variable(record->priv, &LINUX_EFI_CRASH_GUID,
				     PSTORE_EFI_ATTRIBUTES, 0, NULL);

	if (status != EFI_SUCCESS && status != EFI_NOT_FOUND)
		return efi_status_to_err(status);
	return 0;
}

static struct pstore_info efi_pstore_info = {
	.owner		= THIS_MODULE,
	.name		= KBUILD_MODNAME,
	.flags		= PSTORE_FLAGS_DMESG,
	.open		= efi_pstore_open,
	.close		= efi_pstore_close,
	.read		= efi_pstore_read,
	.write		= efi_pstore_write,
	.erase		= efi_pstore_erase,
};

static int efivars_pstore_init(void)
{
	if (!efivar_supports_writes())
		return 0;

	if (pstore_disable)
		return 0;

	/*
	 * Notice that 1024 is the minimum here to prevent issues with
	 * decompression algorithms that were spotted during tests;
	 * even in the case of not using compression, smaller values would
	 * just pollute more the pstore FS with many small collected files.
	 */
	if (record_size < 1024)
		record_size = 1024;

	efi_pstore_info.buf = kmalloc(record_size, GFP_KERNEL);
	if (!efi_pstore_info.buf)
		return -ENOMEM;

	efi_pstore_info.bufsize = record_size;

	if (pstore_register(&efi_pstore_info)) {
		kfree(efi_pstore_info.buf);
		efi_pstore_info.buf = NULL;
		efi_pstore_info.bufsize = 0;
	}

	return 0;
}

static void efivars_pstore_exit(void)
{
	if (!efi_pstore_info.bufsize)
		return;

	pstore_unregister(&efi_pstore_info);
	kfree(efi_pstore_info.buf);
	efi_pstore_info.buf = NULL;
	efi_pstore_info.bufsize = 0;
}

module_init(efivars_pstore_init);
module_exit(efivars_pstore_exit);

MODULE_DESCRIPTION("EFI variable backend for pstore");
MODULE_LICENSE("GPL");
MODULE_ALIAS("platform:efivars");
