/*
 * Copyright 2012 Google Inc.
 *
 * See file CREDITS for list of people who contributed to this
 * project.
 *
 * 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; either version 2 of
 * the License, or (at your option) any later version.
 *
 * 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., 59 Temple Place, Suite 330, Boston,
 * MA 02111-1307 USA
 */

#include <endian.h>
#include <stdio.h>
#include <string.h>
#include <vboot_api.h>

#include "arch/cache.h"
#include "base/coreboot/cbfs.h"
#include "base/coreboot/ram_media.h"
#include "base/cleanup.h"
#include "base/lzma/lzma.h"
#include "base/xalloc.h"
#include "drivers/storage/storage.h"
#include "vboot/board.h"

static void load_payload_and_run(struct cbfs_payload *payload);

int VbExLegacy(void)
{
	if (CONFIG_DISABLE_LEGACY_BOOT) {
		printf("Legacy boot disabled.\n");
		return VBERROR_UNKNOWN;
	}

	StorageOps *legacy = board_storage_legacy();
	int size = storage_size(legacy);
	if (size < 0)
		return VBERROR_UNKNOWN;
	void *legacy_buf = xmalloc(size);
	if (storage_read(legacy, legacy_buf, 0, size)) {
		free(legacy_buf);
		return VBERROR_UNKNOWN;
	}

	struct cbfs_media media;
	if (init_cbfs_ram_media(&media, legacy_buf, size)) {
		printf("Could not initialize legacy cbfs.\n");
		free(legacy_buf);
		return VBERROR_UNKNOWN;
	}

	struct cbfs_payload *payload = cbfs_load_payload(&media, "payload");

	if (payload == NULL) {
		printf("Could not find payload in legacy cbfs.\n");
		free(legacy_buf);
		return VBERROR_UNKNOWN;
	}

	load_payload_and_run(payload);

	// Should never return unless there is an error.
	free(legacy_buf);
	return VBERROR_UNKNOWN;
}

static void load_payload_and_run(struct cbfs_payload *payload)
{
	// This is a minimalistic SELF parser.
	struct cbfs_payload_segment *seg = &payload->segments;
	char *base = (void *)seg;

	while (1) {
		void *src = base + be32toh(seg->offset);
		void *dst = (void *)(unsigned long)be64toh(seg->load_addr);
		uint32_t src_len = be32toh(seg->len);
		uint32_t dst_len = be32toh(seg->mem_len);

		typedef void (*EntryFunc)(void);

		switch (seg->type) {
		case PAYLOAD_SEGMENT_CODE:
		case PAYLOAD_SEGMENT_DATA:
			printf("CODE/DATA: dst=%p dst_len=%d src=%p "
				"src_len=%d compression=%d\n", dst, dst_len,
				src, src_len, be32toh(seg->compression));
			if (be32toh(seg->compression) ==
						CBFS_COMPRESS_NONE) {
				if (dst_len < src_len) {
					printf("Output buffer too small.\n");
					return;
				}
				memcpy(dst, src, src_len);
			} else if (be32toh(seg->compression) ==
						CBFS_COMPRESS_LZMA) {
				if (!ulzman(src, src_len, dst, dst_len)) {
					printf("LZMA: Decompression failed.\n");
					return;
				}
			} else {
				printf("Compression type %x not supported\n",
					be32toh(seg->compression));
				return;
			}
			break;
		case PAYLOAD_SEGMENT_BSS:
			printf("BSS: dst=%p len=%d\n", dst, dst_len);
			memset(dst, 0, dst_len);
			break;
		case PAYLOAD_SEGMENT_PARAMS:
			printf("PARAMS: skipped\n");
			break;
		case PAYLOAD_SEGMENT_ENTRY:
			cleanup_trigger(CleanupOnLegacy);
			cache_sync_instructions();
			((EntryFunc)dst)();
		default:
			printf("segment type %x not implemented. Exiting\n",
				seg->type);
			return;
		}
		seg++;
	}
}
