/*
 * This file is part of the coreinfo project.
 *
 * Copyright (C) 2008 Advanced Micro Devices, Inc.
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation; version 2 of the License.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program; if not, write to the Free Software
 * Foundation, Inc.
 */

#include "coreinfo.h"
#include <coreboot_tables.h>

#if IS_ENABLED(CONFIG_MODULE_COREBOOT)

#define MAX_MEMORY_COUNT 5

static struct {
	int mem_count;
	int mem_actual;

	struct cb_memory_range range[MAX_MEMORY_COUNT];

	char vendor[32];
	char part[32];

	char strings[10][64];

	struct cb_serial serial;
	struct cb_console console;
} cb_info;

static int tables_good = 0;

int coreboot_module_redraw(WINDOW *win)
{
	int row = 2;
	int i;

	print_module_title(win, "Coreboot Tables");

	if (tables_good) {
		mvwprintw(win, row++, 1, "No Coreboot tables were found");
		return 0;
	}

	mvwprintw(win, row++, 1, "Vendor: %s", cb_info.vendor);
	mvwprintw(win, row++, 1, "Part: %s", cb_info.part);

	mvwprintw(win, row++, 1, "Version: %s%s",
		  cb_info.strings[CB_TAG_VERSION - 0x4],
		  cb_info.strings[CB_TAG_EXTRA_VERSION - 0x4]);

	mvwprintw(win, row++, 1, "Built: %s (%s@%s.%s)",
		  cb_info.strings[CB_TAG_BUILD - 0x4],
		  cb_info.strings[CB_TAG_COMPILE_BY - 0x04],
		  cb_info.strings[CB_TAG_COMPILE_HOST - 0x04],
		  cb_info.strings[CB_TAG_COMPILE_DOMAIN - 0x04]);

	if (cb_info.serial.tag != 0x0) {
		mvwprintw(win, row++, 1, "Serial Port I/O base: 0x%x",
			  cb_info.serial.baseaddr);
	}

	if (cb_info.console.tag != 0x0) {
		mvwprintw(win, row++, 1, "Default Output Console: ");

		switch (cb_info.console.type) {
		case CB_TAG_CONSOLE_SERIAL8250:
			wprintw(win, "Serial Port");
			break;
		case CB_TAG_CONSOLE_VGA:
			wprintw(win, "VGA");
			break;
		case CB_TAG_CONSOLE_BTEXT:
			wprintw(win, "BTEXT");
			break;
		case CB_TAG_CONSOLE_LOGBUF:
			wprintw(win, "Log Buffer");
			break;
		case CB_TAG_CONSOLE_SROM:
			wprintw(win, "Serial ROM");
			break;
		case CB_TAG_CONSOLE_EHCI:
			wprintw(win, "USB Debug");
			break;
		}
	}

	row++;
	mvwprintw(win, row++, 1, "-- Memory Map --");

	for (i = 0; i < cb_info.mem_count; i++) {
		switch (cb_info.range[i].type) {
		case CB_MEM_RAM:
			mvwprintw(win, row++, 3, "     RAM: ");
			break;
		case CB_MEM_RESERVED:
			mvwprintw(win, row++, 3, "Reserved: ");
			break;
		case CB_MEM_TABLE:
			mvwprintw(win, row++, 3, "   Table: ");
		}

		wprintw(win, "%16.16llx - %16.16llx",
			cb_unpack64(cb_info.range[i].start),
			cb_unpack64(cb_info.range[i].start) +
			cb_unpack64(cb_info.range[i].size) - 1);
	}

	return 0;
}

static void parse_memory(unsigned char *ptr)
{
	struct cb_memory *mem = (struct cb_memory *)ptr;
	int max = (MEM_RANGE_COUNT(mem) > MAX_MEMORY_COUNT)
	    ? MAX_MEMORY_COUNT : MEM_RANGE_COUNT(mem);
	int i;

	for (i = 0; i < max; i++) {
		struct cb_memory_range *range =
		    (struct cb_memory_range *)MEM_RANGE_PTR(mem, i);

		memcpy(&cb_info.range[i], range, sizeof(*range));
	}

	cb_info.mem_count = max;
	cb_info.mem_actual = MEM_RANGE_COUNT(mem);
}

static void parse_mainboard(unsigned char *ptr)
{
	struct cb_mainboard *mb = (struct cb_mainboard *)ptr;

	strncpy(cb_info.vendor, cb_mb_vendor_string(mb), sizeof(cb_info.vendor) - 1);
	strncpy(cb_info.part, cb_mb_part_string(mb), sizeof(cb_info.part) - 1);
}

static void parse_strings(unsigned char *ptr)
{
	struct cb_string *string = (struct cb_string *)ptr;
	int index = string->tag - CB_TAG_VERSION;

	strncpy(cb_info.strings[index], (const char *)string->string, 63);
	cb_info.strings[index][63] = 0;
}

static void parse_serial(unsigned char *ptr)
{
	memcpy(&cb_info.serial, (struct cb_serial *)ptr,
	       sizeof(struct cb_serial));
}

static void parse_console(unsigned char *ptr)
{
	memcpy(&cb_info.console, (struct cb_console *)ptr,
	       sizeof(struct cb_console));
}

static int parse_header(void *addr, int len)
{
	struct cb_header *header;
	unsigned char *ptr = (unsigned char *)addr;
	int i;

	for (i = 0; i < len; i += 16, ptr += 16) {
		header = (struct cb_header *)ptr;

		if (!strncmp((const char *)header->signature, "LBIO", 4))
			break;
	}

	/* We walked the entire space and didn't find anything. */
	if (i >= len)
		return -1;

	if (!header->table_bytes)
		return 0;

	/* FIXME: Check the checksum. */

	if (cb_checksum(header, sizeof(*header)))
		return -1;

	if (cb_checksum((ptr + sizeof(*header)), header->table_bytes)
	    != header->table_checksum)
		return -1;

	/* Now, walk the tables. */
	ptr += header->header_bytes;

	for (i = 0; i < header->table_entries; i++) {
		struct cb_record *rec = (struct cb_record *)ptr;

		switch (rec->tag) {
		case CB_TAG_FORWARD:
			return parse_header((void *)(unsigned long)((struct cb_forward *)rec)->forward, 1);
			break;
		case CB_TAG_MEMORY:
			parse_memory(ptr);
			break;
		case CB_TAG_MAINBOARD:
			parse_mainboard(ptr);
			break;
		case CB_TAG_VERSION:
		case CB_TAG_EXTRA_VERSION:
		case CB_TAG_BUILD:
		case CB_TAG_COMPILE_TIME:
		case CB_TAG_COMPILE_BY:
		case CB_TAG_COMPILE_HOST:
		case CB_TAG_COMPILE_DOMAIN:
		case CB_TAG_COMPILER:
		case CB_TAG_LINKER:
		case CB_TAG_ASSEMBLER:
			parse_strings(ptr);
			break;
		case CB_TAG_SERIAL:
			parse_serial(ptr);
			break;
		case CB_TAG_CONSOLE:
			parse_console(ptr);
			break;
		default:
			break;
		}

		ptr += rec->size;
	}

	return 1;
}

static int coreboot_module_init(void)
{
	int ret = parse_header((void *)0x00000, 0x1000);

	if (ret != 1)
		ret = parse_header((void *)0xf0000, 0x1000);

	/* Return error if we couldn't find it at either address. */
	tables_good = (ret == 1) ? 0 : -1;
	return tables_good;
}

struct coreinfo_module coreboot_module = {
	.name = "Coreboot",
	.init = coreboot_module_init,
	.redraw = coreboot_module_redraw,
};

#else

struct coreinfo_module coreboot_module = {
};

#endif
