/* Copyright (c) 2013 The Chromium OS Authors. All rights reserved.
 * Use of this source code is governed by a BSD-style license that can be
 * found in the LICENSE file.
 *
 * High-level firmware API for loading and verifying rewritable firmware.
 * (Firmware portion)
 */

#include "sysincludes.h"

#include "bmpblk_header.h"
#include "region.h"
#include "gbb_access.h"
#include "gbb_header.h"
#include "load_kernel_fw.h"
#include "utility.h"
#include "vboot_api.h"
#include "vboot_struct.h"

static VbError_t VbRegionReadGbb(VbCommonParams *cparams, uint32_t offset,
				  uint32_t size, void *buf)
{
	return VbRegionReadData(cparams, VB_REGION_GBB, offset, size, buf);
}

VbError_t VbGbbReadBmpHeader(VbCommonParams *cparams, BmpBlockHeader *hdr_ret)
{
	BmpBlockHeader *hdr;
	VbError_t ret;

	if (!cparams)
		return VBERROR_INVALID_GBB;
	if (!cparams->bmp) {
		GoogleBinaryBlockHeader *gbb = cparams->gbb;

		if (0 == gbb->bmpfv_size)
			return VBERROR_INVALID_GBB;

		hdr = VbExMalloc(sizeof(*hdr));
		ret = VbRegionReadGbb(cparams, gbb->bmpfv_offset,
				      sizeof(BmpBlockHeader), hdr);
		if (ret) {
			VbExFree(hdr);
			return ret;
		}

		/* Sanity-check the bitmap block header */
		if ((0 != Memcmp(hdr->signature, BMPBLOCK_SIGNATURE,
				BMPBLOCK_SIGNATURE_SIZE)) ||
		(hdr->major_version > BMPBLOCK_MAJOR_VERSION) ||
		((hdr->major_version == BMPBLOCK_MAJOR_VERSION) &&
		(hdr->minor_version > BMPBLOCK_MINOR_VERSION))) {
			VBDEBUG(("VbGbbReadBmpHeader(): "
				"invalid/too new bitmap header\n"));
			VbExFree(hdr);
			return VBERROR_INVALID_BMPFV;
		}
		cparams->bmp = hdr;
	}

	*hdr_ret = *cparams->bmp;
	return VBERROR_SUCCESS;
}

VbError_t VbRegionReadHWID(VbCommonParams *cparams, char *hwid,
			   uint32_t max_size)
{
	GoogleBinaryBlockHeader *gbb;
	VbError_t ret;

	if (!max_size)
		return VBERROR_INVALID_PARAMETER;
	*hwid = '\0';
	StrnAppend(hwid, "{INVALID}", max_size);
	if (!cparams)
		return VBERROR_INVALID_GBB;

	gbb = cparams->gbb;

	if (0 == gbb->hwid_size) {
		VBDEBUG(("VbHWID(): invalid hwid size\n"));
		return VBERROR_SUCCESS; /* oddly enough! */
	}

	if (gbb->hwid_size > max_size) {
		VBDEBUG(("VbDisplayDebugInfo(): invalid hwid offset/size\n"));
		return VBERROR_INVALID_PARAMETER;
	}
	ret = VbRegionReadGbb(cparams, gbb->hwid_offset, gbb->hwid_size, hwid);
	if (ret)
		return ret;

	return VBERROR_SUCCESS;
}

VbError_t VbGbbReadImage(VbCommonParams *cparams,
			       uint32_t localization, uint32_t screen_index,
			       uint32_t image_num, ScreenLayout *layout,
			       ImageInfo *image_info, char **image_datap,
			       uint32_t *image_data_sizep)
{
	uint32_t layout_offset, image_offset, data_offset, data_size;
	GoogleBinaryBlockHeader *gbb;
	BmpBlockHeader hdr;
	void *data = NULL;
	VbError_t ret;

	if (!cparams)
		return VBERROR_INVALID_GBB;

	ret = VbGbbReadBmpHeader(cparams, &hdr);
	if (ret)
		return ret;

	gbb = cparams->gbb;
	layout_offset = gbb->bmpfv_offset + sizeof(BmpBlockHeader) +
		localization * hdr.number_of_screenlayouts *
			sizeof(ScreenLayout) +
		screen_index * sizeof(ScreenLayout);
	ret = VbRegionReadGbb(cparams, layout_offset, sizeof(*layout), layout);
	if (ret)
		return ret;

	if (!layout->images[image_num].image_info_offset)
		return VBERROR_NO_IMAGE_PRESENT;

	image_offset = gbb->bmpfv_offset +
			layout->images[image_num].image_info_offset;
	ret = VbRegionReadGbb(cparams, image_offset, sizeof(*image_info),
			      image_info);
	if (ret)
		return ret;

	data_offset = image_offset + sizeof(*image_info);
	data_size = image_info->compressed_size;
	if (data_size) {
		void *orig_data;

		data = VbExMalloc(image_info->compressed_size);
		ret = VbRegionReadGbb(cparams, data_offset,
				      image_info->compressed_size, data);
		if (ret) {
			VbExFree(data);
			return ret;
		}
		if (image_info->compression != COMPRESS_NONE) {
			uint32_t inoutsize = image_info->original_size;

			orig_data = VbExMalloc(image_info->original_size);
			ret = VbExDecompress(data,
					     image_info->compressed_size,
					     image_info->compression,
					     orig_data, &inoutsize);
			data_size = inoutsize;
			VbExFree(data);
			data = orig_data;
			if (ret) {
				VbExFree(data);
				return ret;
			}
		}
	}

	*image_datap = data;
	*image_data_sizep = data_size;

	return VBERROR_SUCCESS;
}

#define OUTBUF_LEN 128

void VbRegionCheckVersion(VbCommonParams *cparams)
{
	GoogleBinaryBlockHeader *gbb;

	if (!cparams)
		return;

	gbb = cparams->gbb;

	/*
	 * If GBB flags is nonzero, complain because that's something that the
	 * factory MUST fix before shipping. We only have to do this here,
	 * because it's obvious that something is wrong if we're not displaying
	 * screens from the GBB.
	 */
	if (gbb->major_version == GBB_MAJOR_VER && gbb->minor_version >= 1 &&
	    (gbb->flags != 0)) {
		uint32_t used = 0;
		char outbuf[OUTBUF_LEN];

		*outbuf = '\0';
		used += StrnAppend(outbuf + used, "gbb.flags is nonzero: 0x",
				OUTBUF_LEN - used);
		used += Uint64ToString(outbuf + used, OUTBUF_LEN - used,
				       gbb->flags, 16, 8);
		used += StrnAppend(outbuf + used, "\n", OUTBUF_LEN - used);
		(void)VbExDisplayDebugInfo(outbuf);
	}
}
