/*
 * This file is part of the coreinfo project.
 *
 * Copyright (C) 2009 Uwe Hermann <uwe@hermann-uwe.de>
 *
 * 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.
 */

#include "coreinfo.h"
#include "endian.h"

#if IS_ENABLED(CONFIG_MODULE_CBFS)

#define FILES_VISIBLE		19

#define HEADER_MAGIC		0x4F524243
#define HEADER_ADDR		0xfffffffc
#define LARCHIVE_MAGIC		0x455649484352414cLL	/* "LARCHIVE" */

#define COMPONENT_DELETED	0x00
#define COMPONENT_BOOTBLOCK	0x01
#define COMPONENT_CBFSHEADER	0x02
#define COMPONENT_STAGE		0x10
#define COMPONENT_PAYLOAD	0x20
#define COMPONENT_OPTIONROM	0x30
#define COMPONENT_RAW		0x50
#define COMPONENT_MICROCODE	0x53
#define COMPONENT_CMOS_LAYOUT	0x1aa
#define COMPONENT_NULL		0xffffffff

struct cbheader {
	u32 magic;
	u32 version;
	u32 romsize;
	u32 bootblocksize;
	u32 align;
	u32 offset;
	u32 architecture;
	u32 pad[1];
} __attribute__ ((packed));

struct cbfile {
	u64 magic;
	u32 len;
	u32 type;
	u32 checksum;
	u32 offset;
	char filename[0];
} __attribute__ ((packed));

static int filecount = 0, selected = 0, start_row = 0;
static char **filenames;
static struct cbheader *header = NULL;

static struct cbfile *getfile(struct cbfile *f)
{
	while (1) {
		if (f < (struct cbfile *)(0xffffffff - ntohl(header->romsize)))
			return NULL;
		if (f->magic == 0)
			return NULL;
		if (f->magic == LARCHIVE_MAGIC)
			return f;
		f = (void *)f + ntohl(header->align);
	}
}

static struct cbfile *firstfile(void)
{
	return getfile((void *)(0 - ntohl(header->romsize) +
				ntohl(header->offset)));
}

static struct cbfile *nextfile(struct cbfile *f)
{
	f = (void *)f + ALIGN(ntohl(f->len) + ntohl(f->offset),
			      ntohl(header->align));
	return getfile(f);
}

static struct cbfile *findfile(const char *filename)
{
	struct cbfile *f;
	for (f = firstfile(); f; f = nextfile(f)) {
		if (strcmp(filename, f->filename) == 0)
			return f;
	}
	return NULL;
}

static int cbfs_module_init(void)
{
	struct cbfile *f;
	int index = 0;

	header = *(void **)HEADER_ADDR;
	if (header->magic != ntohl(HEADER_MAGIC)) {
		header = NULL;
		return 0;
	}

	for (f = firstfile(); f; f = nextfile(f))
		filecount++;

	filenames = malloc(filecount * sizeof(char *));
	if (filenames == NULL)
		return 0;

	for (f = firstfile(); f; f = nextfile(f))
		filenames[index++] = strdup((const char *)f->filename);

	return 0;
}

static int cbfs_module_redraw(WINDOW * win)
{
	struct cbfile *f;
	int i, row, frow;

	print_module_title(win, "CBFS Listing");

	if (!header) {
		mvwprintw(win, 11, 61 / 2, "Bad or missing CBFS header");
		return 0;
	}

	/* Draw a line down the middle. */
	for (i = 2; i < 21; i++)
		mvwaddch(win, i, 30, ACS_VLINE);

	/* Draw the names down the left side. */
	for (frow = 0; frow < FILES_VISIBLE; frow++) {
		row = 2 + frow;
		i = start_row + frow;
		if (i >= filecount)
			break;
		if (i == selected)
			wattrset(win, COLOR_PAIR(3) | A_BOLD);
		else
			wattrset(win, COLOR_PAIR(2));

		if (strlen(filenames[i]) == 0) {
			if (findfile(filenames[i])->type == COMPONENT_NULL)
				mvwprintw(win, row, 1, "<free space>");
			else
				mvwprintw(win, row, 1, "<unnamed>");
		} else {
			mvwprintw(win, row, 1, "%.25s", filenames[i]);
		}
		/* show scroll arrows */
		if (frow == 0 && start_row > 0) {
			wattrset(win, COLOR_PAIR(2));
			mvwaddch(win, row, 28, ACS_UARROW);
		}
		if (frow == FILES_VISIBLE - 1 && i != filecount - 1) {
			wattrset(win, COLOR_PAIR(2));
			mvwaddch(win, row, 28, ACS_DARROW);
		}
	}

	f = findfile(filenames[selected]);
	if (!f) {
		mvwprintw(win, 11, 32, "ERROR: CBFS component not found");
		return 0;
	}

	wattrset(win, COLOR_PAIR(2));

	/* Draw the file information */
	row = 2;
	/* mvwprintw(win, row++, 32, "Offset: 0x%x", f->offset); *//* FIXME */
	mvwprintw(win, row, 32, "Type: ");
	switch (ntohl(f->type)) {
	case COMPONENT_BOOTBLOCK:
		mvwprintw(win, row++, 38, "bootblock");
		break;
	case COMPONENT_CBFSHEADER:
		mvwprintw(win, row++, 38, "CBFS header");
		break;
	case COMPONENT_STAGE:
		mvwprintw(win, row++, 38, "stage");
		break;
	case COMPONENT_PAYLOAD:
		mvwprintw(win, row++, 38, "payload");
		break;
	case COMPONENT_OPTIONROM:
		mvwprintw(win, row++, 38, "optionrom");
		break;
	case COMPONENT_RAW:
		mvwprintw(win, row++, 38, "raw");
		break;
	case COMPONENT_MICROCODE:
		mvwprintw(win, row++, 38, "microcode");
		break;
	case COMPONENT_CMOS_LAYOUT:
		mvwprintw(win, row++, 38, "cmos layout");
		break;
	case COMPONENT_NULL:
		mvwprintw(win, row++, 38, "free");
		break;
	case COMPONENT_DELETED:
		mvwprintw(win, row++, 38, "deleted");
		break;
	default:
		mvwprintw(win, row++, 38, "Unknown (0x%x)", ntohl(f->type));
		break;
	}
	mvwprintw(win, row++, 32, "Size: %d", ntohl(f->len));
	mvwprintw(win, row++, 32, "Checksum: 0x%x", ntohl(f->checksum));

	return 0;
}

static int cbfs_module_handle(int key)
{
	int ret = 0;

	if (filecount == 0)
		return 0;

	switch (key) {
	case KEY_DOWN:
		if (selected + 1 < filecount) {
			selected++;
			if (selected >= start_row + FILES_VISIBLE - 1)
				start_row = selected - (FILES_VISIBLE - 1);
			ret = 1;
		}
		break;
	case KEY_UP:
		if (selected > 0) {
			selected--;
			if (selected < start_row)
				start_row = selected;
			ret = 1;
		}
		break;
	}

	return ret;
}

struct coreinfo_module cbfs_module = {
	.name = "CBFS",
	.init = cbfs_module_init,
	.redraw = cbfs_module_redraw,
	.handle = cbfs_module_handle
};

#else

struct coreinfo_module cbfs_module = {
};

#endif
