/*
 * Copyright 2014 Red Hat Inc.
 *
 * Permission is hereby granted, free of charge, to any person obtaining a
 * copy of this software and associated documentation files (the "Software"),
 * to deal in the Software without restriction, including without limitation
 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
 * and/or sell copies of the Software, and to permit persons to whom the
 * Software is furnished to do so, subject to the following conditions:
 *
 * The above copyright notice and this permission notice shall be included in
 * all copies or substantial portions of the Software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
 * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
 * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
 * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
 * OTHER DEALINGS IN THE SOFTWARE.
 *
 * Authors: Ben Skeggs <bskeggs@redhat.com>
 */
#include "priv.h"

#include <core/option.h>
#include <subdev/bios.h>
#include <subdev/bios/image.h>

struct shadow {
	u32 skip;
	const struct nvbios_source *func;
	void *data;
	u32 size;
	int score;
};

static bool
shadow_fetch(struct nvkm_bios *bios, struct shadow *mthd, u32 upto)
{
	const u32 limit = (upto + 3) & ~3;
	const u32 start = bios->size;
	void *data = mthd->data;
	if (nvbios_extend(bios, limit) > 0) {
		u32 read = mthd->func->read(data, start, limit - start, bios);
		bios->size = start + read;
	}
	return bios->size >= upto;
}

static int
shadow_image(struct nvkm_bios *bios, int idx, u32 offset, struct shadow *mthd)
{
	struct nvkm_subdev *subdev = &bios->subdev;
	struct nvbios_image image;
	int score = 1;

	if (mthd->func->no_pcir) {
		image.base = 0;
		image.type = 0;
		image.size = mthd->func->size(mthd->data);
		image.last = 1;
	} else {
		if (!shadow_fetch(bios, mthd, offset + 0x1000)) {
			nvkm_debug(subdev, "%08x: header fetch failed\n",
				   offset);
			return 0;
		}

		if (!nvbios_image(bios, idx, &image)) {
			nvkm_debug(subdev, "image %d invalid\n", idx);
			return 0;
		}
	}
	nvkm_debug(subdev, "%08x: type %02x, %d bytes\n",
		   image.base, image.type, image.size);

	if (!shadow_fetch(bios, mthd, image.base + image.size)) {
		nvkm_debug(subdev, "%08x: fetch failed\n", image.base);
		return 0;
	}

	switch (image.type) {
	case 0x00:
		if (!mthd->func->ignore_checksum &&
		    nvbios_checksum(&bios->data[image.base], image.size)) {
			nvkm_debug(subdev, "%08x: checksum failed\n",
				   image.base);
			if (!mthd->func->require_checksum) {
				if (mthd->func->rw)
					score += 1;
				score += 1;
			} else
				return 0;
		} else {
			score += 3;
		}
		break;
	default:
		score += 3;
		break;
	}

	if (!image.last)
		score += shadow_image(bios, idx + 1, offset + image.size, mthd);
	return score;
}

static int
shadow_method(struct nvkm_bios *bios, struct shadow *mthd, const char *name)
{
	const struct nvbios_source *func = mthd->func;
	struct nvkm_subdev *subdev = &bios->subdev;
	if (func->name) {
		nvkm_debug(subdev, "trying %s...\n", name ? name : func->name);
		if (func->init) {
			mthd->data = func->init(bios, name);
			if (IS_ERR(mthd->data)) {
				mthd->data = NULL;
				return 0;
			}
		}
		mthd->score = shadow_image(bios, 0, 0, mthd);
		if (func->fini)
			func->fini(mthd->data);
		nvkm_debug(subdev, "scored %d\n", mthd->score);
		mthd->data = bios->data;
		mthd->size = bios->size;
		bios->data  = NULL;
		bios->size  = 0;
	}
	return mthd->score;
}

static u32
shadow_fw_read(void *data, u32 offset, u32 length, struct nvkm_bios *bios)
{
	const struct firmware *fw = data;
	if (offset + length <= fw->size) {
		memcpy(bios->data + offset, fw->data + offset, length);
		return length;
	}
	return 0;
}

static void *
shadow_fw_init(struct nvkm_bios *bios, const char *name)
{
	struct device *dev = bios->subdev.device->dev;
	const struct firmware *fw;
	int ret = request_firmware(&fw, name, dev);
	if (ret)
		return ERR_PTR(-ENOENT);
	return (void *)fw;
}

static const struct nvbios_source
shadow_fw = {
	.name = "firmware",
	.init = shadow_fw_init,
	.fini = (void(*)(void *))release_firmware,
	.read = shadow_fw_read,
	.rw = false,
};

int
nvbios_shadow(struct nvkm_bios *bios)
{
	struct nvkm_subdev *subdev = &bios->subdev;
	struct nvkm_device *device = subdev->device;
	struct shadow mthds[] = {
		{ 0, &nvbios_of },
		{ 0, &nvbios_ramin },
		{ 0, &nvbios_rom },
		{ 0, &nvbios_acpi_fast },
		{ 4, &nvbios_acpi_slow },
		{ 1, &nvbios_pcirom },
		{ 1, &nvbios_platform },
		{}
	}, *mthd, *best = NULL;
	const char *optarg;
	char *source;
	int optlen;

	/* handle user-specified bios source */
	optarg = nvkm_stropt(device->cfgopt, "NvBios", &optlen);
	source = optarg ? kstrndup(optarg, optlen, GFP_KERNEL) : NULL;
	if (source) {
		/* try to match one of the built-in methods */
		for (mthd = mthds; mthd->func; mthd++) {
			if (mthd->func->name &&
			    !strcasecmp(source, mthd->func->name)) {
				best = mthd;
				if (shadow_method(bios, mthd, NULL))
					break;
			}
		}

		/* otherwise, attempt to load as firmware */
		if (!best && (best = mthd)) {
			mthd->func = &shadow_fw;
			shadow_method(bios, mthd, source);
			mthd->func = NULL;
		}

		if (!best->score) {
			nvkm_error(subdev, "%s invalid\n", source);
			kfree(source);
			source = NULL;
		}
	}

	/* scan all potential bios sources, looking for best image */
	if (!best || !best->score) {
		for (mthd = mthds, best = mthd; mthd->func; mthd++) {
			if (!mthd->skip || best->score < mthd->skip) {
				if (shadow_method(bios, mthd, NULL)) {
					if (mthd->score > best->score)
						best = mthd;
				}
			}
		}
	}

	/* cleanup the ones we didn't use */
	for (mthd = mthds; mthd->func; mthd++) {
		if (mthd != best)
			kfree(mthd->data);
	}

	if (!best->score) {
		nvkm_error(subdev, "unable to locate usable image\n");
		return -EINVAL;
	}

	nvkm_debug(subdev, "using image from %s\n", best->func ?
		   best->func->name : source);
	bios->data = best->data;
	bios->size = best->size;
	kfree(source);
	return 0;
}
