// SPDX-License-Identifier: GPL-2.0+
/*
 * Copyright (C) 2015, Bin Meng <bmeng.cn@gmail.com>
 */

#define LOG_CATEGORY LOGC_ACPI

#include <common.h>
#include <bloblist.h>
#include <log.h>
#include <malloc.h>
#include <smbios.h>
#include <acpi/acpi_table.h>
#include <asm/global_data.h>
#include <asm/sfi.h>
#include <asm/mpspec.h>
#include <asm/tables.h>
#include <asm/coreboot_tables.h>

DECLARE_GLOBAL_DATA_PTR;

/**
 * Function prototype to write a specific configuration table
 *
 * @addr:	start address to write the table
 * @return:	end address of the table
 */
typedef ulong (*table_write)(ulong addr);

/**
 * struct table_info - Information about each table to write
 *
 * @name: Name of table (for debugging)
 * @write: Function to call to write this table
 * @tag: Bloblist tag if using CONFIG_BLOBLIST_TABLES
 * @size: Maximum table size
 * @align: Table alignment in bytes
 */
struct table_info {
	const char *name;
	table_write write;
	enum bloblist_tag_t tag;
	int size;
	int align;
};

static struct table_info table_list[] = {
#ifdef CONFIG_GENERATE_PIRQ_TABLE
	{ "pirq", write_pirq_routing_table },
#endif
#ifdef CONFIG_GENERATE_SFI_TABLE
	{ "sfi", write_sfi_table, },
#endif
#ifdef CONFIG_GENERATE_MP_TABLE
	{ "mp", write_mp_table, },
#endif
	/*
	 * tables which can go in the bloblist must be last in this list, so
	 * that the calculation of gd->table_end works properly
	 */
#ifdef CONFIG_GENERATE_ACPI_TABLE
	{ "acpi", write_acpi_tables, BLOBLISTT_ACPI_TABLES, 0x10000, 0x1000},
#endif
#ifdef CONFIG_GENERATE_SMBIOS_TABLE
	{ "smbios", write_smbios_table, BLOBLISTT_SMBIOS_TABLES, 0x1000, 0x100},
#endif
};

void table_fill_string(char *dest, const char *src, size_t n, char pad)
{
	int start, len;
	int i;

	strncpy(dest, src, n);

	/* Fill the remaining bytes with pad */
	len = strlen(src);
	start = len < n ? len : n;
	for (i = start; i < n; i++)
		dest[i] = pad;
}

int write_tables(void)
{
	u32 high_table, table_size;
	struct memory_area cfg_tables[ARRAY_SIZE(table_list) + 1];
	bool use_high = false;
	u32 rom_addr;
	int i;

	gd->arch.table_start = ROM_TABLE_ADDR;
	rom_addr = gd->arch.table_start;

	debug("Writing tables to %x:\n", rom_addr);
	for (i = 0; i < ARRAY_SIZE(table_list); i++) {
		const struct table_info *table = &table_list[i];
		int size = table->size ? : CONFIG_ROM_TABLE_SIZE;
		u32 rom_table_end;

		if (!strcmp("smbios", table->name))
			gd->arch.smbios_start = rom_addr;

		if (IS_ENABLED(CONFIG_BLOBLIST_TABLES) && table->tag) {
			if (!gd->arch.table_end)
				gd->arch.table_end = rom_addr;
			rom_addr = (ulong)bloblist_add(table->tag, size,
						       table->align);
			if (!rom_addr)
				return log_msg_ret("bloblist", -ENOBUFS);

			/* the bloblist is always in high memory */
			use_high = true;
			if (!gd->arch.table_start_high)
				gd->arch.table_start_high = rom_addr;
		}
		rom_table_end = table->write(rom_addr);
		if (!rom_table_end) {
			log_err("Can't create configuration table %d\n", i);
			return -EINTR;
		}

		if (IS_ENABLED(CONFIG_SEABIOS)) {
			table_size = rom_table_end - rom_addr;
			high_table = (u32)(ulong)high_table_malloc(table_size);
			if (high_table) {
				if (!table->write(high_table)) {
					log_err("Can't create configuration table %d\n",
						i);
					return -EINTR;
				}

				cfg_tables[i].start = high_table;
				cfg_tables[i].size = table_size;
			} else {
				printf("%d: no memory for configuration tables\n",
				       i);
				return -ENOSPC;
			}
		}

		debug("- wrote '%s' to %x, end %x\n", table->name,
		      rom_addr, rom_table_end);
		if (rom_table_end - rom_addr > size) {
			log_err("Out of space for configuration tables: need %x, have %x\n",
				rom_table_end - rom_addr, size);
			return log_msg_ret("bloblist", -ENOSPC);
		}
		rom_addr = rom_table_end;
	}

	if (use_high)
		gd->arch.table_end_high = rom_addr;
	else
		gd->arch.table_end = rom_addr;

	if (IS_ENABLED(CONFIG_SEABIOS)) {
		/* make sure the last item is zero */
		cfg_tables[i].size = 0;
		write_coreboot_table(CB_TABLE_ADDR, cfg_tables);
	}

	if (IS_ENABLED(CONFIG_BLOBLIST_TABLES)) {
		void *ptr = (void *)CONFIG_ROM_TABLE_ADDR;

		/* Write an RSDP pointing to the tables */
		if (IS_ENABLED(CONFIG_GENERATE_ACPI_TABLE)) {
			struct acpi_ctx *ctx = gd_acpi_ctx();

			acpi_write_rsdp(ptr, ctx->rsdt, ctx->xsdt);
			ptr += ALIGN(sizeof(struct acpi_rsdp), 16);
		}
		if (IS_ENABLED(CONFIG_GENERATE_SMBIOS_TABLE)) {
			void *smbios;

			smbios = bloblist_find(BLOBLISTT_SMBIOS_TABLES, 0);
			if (!smbios)
				return log_msg_ret("smbios", -ENOENT);
			memcpy(ptr, smbios, sizeof(struct smbios_entry));
		}
	}

	debug("- done writing tables\n");

	return 0;
}
