// SPDX-License-Identifier: GPL-2.0+
/*
 * Copyright 2019 Google LLC
 * Written by Simon Glass <sjg@chromium.org>
 */
#include <command.h>
#include <display_options.h>
#include <log.h>
#include <mapmem.h>
#include <acpi/acpi_table.h>
#include <asm/acpi_table.h>
#include <asm/global_data.h>
#include <linux/errno.h>
#include <dm/acpi.h>

DECLARE_GLOBAL_DATA_PTR;

/**
 * dump_hdr() - Dump an ACPI header
 *
 * Except for the Firmware ACPI Control Structure (FACS)
 * additionally show the revision information.
 *
 * @hdr: ACPI header to dump
 */
static void dump_hdr(struct acpi_table_header *hdr)
{
	bool has_hdr = memcmp(hdr->signature, "FACS", ACPI_NAME_LEN);

	printf("%.*s  %16lx  %5x", ACPI_NAME_LEN, hdr->signature,
	       (ulong)map_to_sysmem(hdr), hdr->length);
	if (has_hdr) {
		printf("  v%02d %.6s %.8s %x %.4s %x\n", hdr->revision,
		       hdr->oem_id, hdr->oem_table_id, hdr->oem_revision,
		       hdr->creator_id, hdr->creator_revision);
	} else {
		printf("\n");
	}
}

static int dump_table_name(const char *sig)
{
	struct acpi_table_header *hdr;

	hdr = acpi_find_table(sig);
	if (!hdr)
		return -ENOENT;
	printf("%.*s @ %16lx\n", ACPI_NAME_LEN, hdr->signature,
	       (ulong)nomap_to_sysmem(hdr));
	print_buffer(0, hdr, 1, hdr->length, 0);

	return 0;
}

static void list_fadt(struct acpi_fadt *fadt)
{
	if (fadt->header.revision >= 3 && fadt->x_dsdt)
		dump_hdr(nomap_sysmem(fadt->x_dsdt, 0));
	else if (fadt->dsdt)
		dump_hdr(nomap_sysmem(fadt->dsdt, 0));
	if (!IS_ENABLED(CONFIG_X86) &&
	    !(fadt->flags & ACPI_FADT_HW_REDUCED_ACPI))
		log_err("FADT not ACPI-hardware-reduced-compliant\n");
	if (fadt->header.revision >= 3 && fadt->x_firmware_ctrl)
		dump_hdr(nomap_sysmem(fadt->x_firmware_ctrl, 0));
	else if (fadt->firmware_ctrl)
		dump_hdr(nomap_sysmem(fadt->firmware_ctrl, 0));
}

static void list_rsdt(struct acpi_rsdp *rsdp)
{
	int len, i, count;
	struct acpi_rsdt *rsdt;
	struct acpi_xsdt *xsdt;

	if (rsdp->rsdt_address) {
		rsdt = nomap_sysmem(rsdp->rsdt_address, 0);
		dump_hdr(&rsdt->header);
	}
	if (rsdp->xsdt_address) {
		xsdt = nomap_sysmem(rsdp->xsdt_address, 0);
		dump_hdr(&xsdt->header);
		len = xsdt->header.length - sizeof(xsdt->header);
		count = len / sizeof(u64);
	} else if (rsdp->rsdt_address) {
		len = rsdt->header.length - sizeof(rsdt->header);
		count = len / sizeof(u32);
	} else {
		return;
	}

	for (i = 0; i < count; i++) {
		struct acpi_table_header *hdr;
		u64 entry;

		if (rsdp->xsdt_address)
			entry = xsdt->entry[i];
		else
			entry = rsdt->entry[i];
		if (!entry)
			break;
		hdr = nomap_sysmem(entry, 0);
		dump_hdr(hdr);
		if (!memcmp(hdr->signature, "FACP", ACPI_NAME_LEN))
			list_fadt((struct acpi_fadt *)hdr);
	}
}

static void list_rsdp(struct acpi_rsdp *rsdp)
{
	printf("RSDP  %16lx  %5x  v%02d %.6s\n", (ulong)map_to_sysmem(rsdp),
	       rsdp->length, rsdp->revision, rsdp->oem_id);
	list_rsdt(rsdp);
}

static int do_acpi_list(struct cmd_tbl *cmdtp, int flag, int argc,
			char *const argv[])
{
	struct acpi_rsdp *rsdp;

	rsdp = map_sysmem(gd_acpi_start(), 0);
	if (!rsdp) {
		printf("No ACPI tables present\n");
		return 0;
	}
	printf("Name              Base   Size  Detail\n"
	       "----  ----------------  -----  ----------------------------\n");
	list_rsdp(rsdp);

	return 0;
}

static int do_acpi_set(struct cmd_tbl *cmdtp, int flag, int argc,
		       char *const argv[])
{
	ulong val;

	if (argc < 2) {
		printf("ACPI pointer: %lx\n", gd_acpi_start());
	} else {
		val = hextoul(argv[1], NULL);
		printf("Setting ACPI pointer to %lx\n", val);
		gd_set_acpi_start(val);
	}

	return 0;
}

static int do_acpi_items(struct cmd_tbl *cmdtp, int flag, int argc,
			 char *const argv[])
{
	bool dump_contents;

	dump_contents = argc >= 2 && !strcmp("-d", argv[1]);
	if (!IS_ENABLED(CONFIG_ACPIGEN)) {
		printf("Not supported (enable ACPIGEN)\n");
		return CMD_RET_FAILURE;
	}
	acpi_dump_items(dump_contents ? ACPI_DUMP_CONTENTS : ACPI_DUMP_LIST);

	return 0;
}

static int do_acpi_dump(struct cmd_tbl *cmdtp, int flag, int argc,
			char *const argv[])
{
	const char *name;
	char sig[ACPI_NAME_LEN];
	int ret;

	if (argc < 2)
		return CMD_RET_USAGE;

	name = argv[1];
	if (strlen(name) != ACPI_NAME_LEN) {
		printf("Table name '%s' must be four characters\n", name);
		return CMD_RET_FAILURE;
	}
	str_to_upper(name, sig, ACPI_NAME_LEN);
	ret = dump_table_name(sig);
	if (ret) {
		printf("Table '%.*s' not found\n", ACPI_NAME_LEN, sig);
		return CMD_RET_FAILURE;
	}

	return 0;
}

U_BOOT_LONGHELP(acpi,
	"list  - list ACPI tables\n"
	"acpi items [-d]   - List/dump each piece of ACPI data from devices\n"
	"acpi set [<addr>] - Set or show address of ACPI tables\n"
	"acpi dump <name>  - Dump ACPI table");

U_BOOT_CMD_WITH_SUBCMDS(acpi, "ACPI tables", acpi_help_text,
	U_BOOT_SUBCMD_MKENT(list, 1, 1, do_acpi_list),
	U_BOOT_SUBCMD_MKENT(items, 2, 1, do_acpi_items),
	U_BOOT_SUBCMD_MKENT(set, 2, 1, do_acpi_set),
	U_BOOT_SUBCMD_MKENT(dump, 2, 1, do_acpi_dump));
