// SPDX-License-Identifier: GPL-2.0
/*
 * debug_kinfo.c - backup kernel information for bootloader usage
 *
 * Copyright 2002 Rusty Russell <rusty@rustcorp.com.au> IBM Corporation
 * Copyright 2021 Google LLC
 */

#include <linux/platform_device.h>
#include <linux/kallsyms.h>
#include <linux/vmalloc.h>
#include <linux/module.h>
#include <linux/of_address.h>
#include <linux/of_reserved_mem.h>
#include <linux/pgtable.h>
#include <asm/module.h>
#include "debug_kinfo.h"

/*
 * These will be re-linked against their real values
 * during the second link stage.
 */
extern const unsigned long kallsyms_addresses[] __weak;
extern const int kallsyms_offsets[] __weak;
extern const u8 kallsyms_names[] __weak;

/*
 * Tell the compiler that the count isn't in the small data section if the arch
 * has one (eg: FRV).
 */
extern const unsigned int kallsyms_num_syms __weak
__section(".rodata");

extern const unsigned long kallsyms_relative_base __weak
__section(".rodata");

extern const u8 kallsyms_token_table[] __weak;
extern const u16 kallsyms_token_index[] __weak;

extern const unsigned int kallsyms_markers[] __weak;

static void *all_info_addr;
static u32 all_info_size;

static void update_kernel_all_info(struct kernel_all_info *all_info)
{
	int index;
	struct kernel_info *info;
	u32 *checksum_info;

	all_info->magic_number = DEBUG_KINFO_MAGIC;
	all_info->combined_checksum = 0;

	info = &(all_info->info);
	checksum_info = (u32 *)info;
	for (index = 0; index < sizeof(*info) / sizeof(u32); index++)
		all_info->combined_checksum ^= checksum_info[index];
}

static int build_info_set(const char *str, const struct kernel_param *kp)
{
	struct kernel_all_info *all_info;
	size_t build_info_size;
	int ret = 0;

	if (all_info_addr == 0 || all_info_size == 0) {
		ret = -EPERM;
		goto Exit;
	}

	all_info = (struct kernel_all_info *)all_info_addr;
	build_info_size = sizeof(all_info->info.build_info);

	memcpy(&all_info->info.build_info, str, min(build_info_size - 1, strlen(str)));
	update_kernel_all_info(all_info);

	if (strlen(str) > build_info_size) {
		pr_warn("%s: Build info buffer (len: %zd) can't hold entire string '%s'\n",
				__func__, build_info_size, str);
		ret = -ENOMEM;
	}

Exit:
	return ret;
}

static const struct kernel_param_ops build_info_op = {
	.set = build_info_set,
};

module_param_cb(build_info, &build_info_op, NULL, 0200);
MODULE_PARM_DESC(build_info, "Write build info to field 'build_info' of debug kinfo.");

static int debug_kinfo_probe(struct platform_device *pdev)
{
	struct device_node *mem_region;
	struct reserved_mem *rmem;
	struct kernel_all_info *all_info;
	struct kernel_info *info;

	mem_region = of_parse_phandle(pdev->dev.of_node, "memory-region", 0);
	if (!mem_region) {
		dev_warn(&pdev->dev, "no such memory-region\n");
		return -ENODEV;
	}

	rmem = of_reserved_mem_lookup(mem_region);
	if (!rmem) {
		dev_warn(&pdev->dev, "no such reserved mem of node name %s\n",
				pdev->dev.of_node->name);
		return -ENODEV;
	}

	/* Need to wait for reserved memory to be mapped */
	if (!rmem->priv) {
		return -EPROBE_DEFER;
	}

	if (!rmem->base || !rmem->size) {
		dev_warn(&pdev->dev, "unexpected reserved memory\n");
		return -EINVAL;
	}

	if (rmem->size < sizeof(struct kernel_all_info)) {
		dev_warn(&pdev->dev, "unexpected reserved memory size\n");
		return -EINVAL;
	}

	all_info_addr = rmem->priv;
	all_info_size = rmem->size;

	memset(all_info_addr, 0, sizeof(struct kernel_all_info));
	all_info = (struct kernel_all_info *)all_info_addr;
	info = &(all_info->info);
	info->enabled_all = IS_ENABLED(CONFIG_KALLSYMS_ALL);
	info->enabled_base_relative = IS_ENABLED(CONFIG_KALLSYMS_BASE_RELATIVE);
	info->enabled_absolute_percpu = IS_ENABLED(CONFIG_KALLSYMS_ABSOLUTE_PERCPU);
	info->enabled_cfi_clang = IS_ENABLED(CONFIG_CFI_CLANG);
	info->num_syms = kallsyms_num_syms;
	info->name_len = KSYM_NAME_LEN;
	info->bit_per_long = BITS_PER_LONG;
	info->module_name_len = MODULE_NAME_LEN;
	info->symbol_len = KSYM_SYMBOL_LEN;
	if (!info->enabled_base_relative)
		info->_addresses_pa = (u64)__pa_symbol((volatile void *)kallsyms_addresses);
	else {
		info->_relative_pa = (u64)__pa_symbol((volatile void *)kallsyms_relative_base);
		info->_offsets_pa = (u64)__pa_symbol((volatile void *)kallsyms_offsets);
	}
	info->_stext_pa = (u64)__pa_symbol(_stext);
	info->_etext_pa = (u64)__pa_symbol(_etext);
	info->_sinittext_pa = (u64)__pa_symbol(_sinittext);
	info->_einittext_pa = (u64)__pa_symbol(_einittext);
	info->_end_pa = (u64)__pa_symbol(_end);
	info->_names_pa = (u64)__pa_symbol((volatile void *)kallsyms_names);
	info->_token_table_pa = (u64)__pa_symbol((volatile void *)kallsyms_token_table);
	info->_token_index_pa = (u64)__pa_symbol((volatile void *)kallsyms_token_index);
	info->_markers_pa = (u64)__pa_symbol((volatile void *)kallsyms_markers);
	info->thread_size = THREAD_SIZE;
	info->swapper_pg_dir_pa = (u64)__pa_symbol(swapper_pg_dir);
	strlcpy(info->last_uts_release, init_utsname()->release, sizeof(info->last_uts_release));
	info->enabled_modules_tree_lookup = IS_ENABLED(CONFIG_MODULES_TREE_LOOKUP);
	info->mod_core_layout_offset = offsetof(struct module, core_layout);
	info->mod_init_layout_offset = offsetof(struct module, init_layout);
	info->mod_kallsyms_offset = offsetof(struct module, kallsyms);
#if defined(CONFIG_RANDOMIZE_BASE) && defined(MODULES_VSIZE)
	info->module_start_va = module_alloc_base;
	info->module_end_va = info->module_start_va + MODULES_VSIZE;
#elif defined(CONFIG_MODULES) && defined(MODULES_VADDR)
	info->module_start_va = MODULES_VADDR;
	info->module_end_va = MODULES_END;
#else
	info->module_start_va = VMALLOC_START;
	info->module_end_va = VMALLOC_END;
#endif
	update_kernel_all_info(all_info);

	return 0;
}

static const struct of_device_id debug_kinfo_of_match[] = {
	{ .compatible	= "google,debug-kinfo" },
	{},
};
MODULE_DEVICE_TABLE(of, debug_kinfo_of_match);

static struct platform_driver debug_kinfo_driver = {
	.probe = debug_kinfo_probe,
	.driver = {
		.name = "debug-kinfo",
		.of_match_table = of_match_ptr(debug_kinfo_of_match),
	},
};
module_platform_driver(debug_kinfo_driver);

MODULE_AUTHOR("Jone Chou <jonechou@google.com>");
MODULE_DESCRIPTION("Debug Kinfo Driver");
MODULE_LICENSE("GPL v2");
