/* SPDX-License-Identifier: GPL-2.0-only */
/* This file is part of the coreboot project. */

#include <console/console.h>
#include <commonlib/cbfs.h>
#include <commonlib/endian.h>
#include <commonlib/helpers.h>
#include <string.h>
#include <vb2_sha.h>

#if !defined(LOG)
#define LOG(x...) printk(BIOS_INFO, "CBFS: " x)
#endif
#if defined(CONFIG)

#if CONFIG(DEBUG_CBFS)
#define DEBUG(x...) printk(BIOS_SPEW, "CBFS: " x)
#else
#define DEBUG(x...)
#endif

#elif !defined(DEBUG)
#define DEBUG(x...)
#endif

static size_t cbfs_next_offset(const struct region_device *cbfs,
				const struct cbfsf *f)
{
	size_t offset;

	if (f == NULL)
		return 0;

	/* The region_device objects store absolute offsets over the whole
	 * region. Therefore a relative offset needs to be calculated. */
	offset = rdev_relative_offset(cbfs, &f->data);
	offset += region_device_sz(&f->data);

	return ALIGN_UP(offset, CBFS_ALIGNMENT);
}

static int cbfs_end(const struct region_device *cbfs, size_t offset)
{
	if (offset >= region_device_sz(cbfs))
		return 1;

	return 0;
}

int cbfs_for_each_file(const struct region_device *cbfs,
			const struct cbfsf *prev, struct cbfsf *fh)
{
	size_t offset;

	offset = cbfs_next_offset(cbfs, prev);

	/* Try to scan the entire cbfs region looking for file name. */
	while (1) {
		struct cbfs_file file;
		const size_t fsz = sizeof(file);

		 DEBUG("Checking offset %zx\n", offset);

		/* End of region. */
		if (cbfs_end(cbfs, offset))
			return 1;

		/* Can't read file. Nothing else to do but bail out. */
		if (rdev_readat(cbfs, &file, offset, fsz) != fsz)
			break;

		if (memcmp(file.magic, CBFS_FILE_MAGIC, sizeof(file.magic))) {
			offset++;
			offset = ALIGN_UP(offset, CBFS_ALIGNMENT);
			continue;
		}

		file.len = read_be32(&file.len);
		file.offset = read_be32(&file.offset);

		DEBUG("File @ offset %zx size %x\n", offset, file.len);

		/* Keep track of both the metadata and the data for the file. */
		if (rdev_chain(&fh->metadata, cbfs, offset, file.offset))
			break;

		if (rdev_chain(&fh->data, cbfs, offset + file.offset, file.len))
			break;

		/* Success. */
		return 0;
	}

	return -1;
}

size_t cbfs_for_each_attr(void *metadata, size_t metadata_size,
			  size_t last_offset)
{
	struct cbfs_file_attribute *attr;

	if (!last_offset) {
		struct cbfs_file *file = metadata;
		size_t start_offset = read_be32(&file->attributes_offset);
		if (start_offset <= sizeof(struct cbfs_file) ||
		    start_offset + sizeof(*attr) > metadata_size)
			return 0;
		return start_offset;
	}

	attr = metadata + last_offset;
	size_t next_offset = last_offset + read_be32(&attr->len);

	if (next_offset + sizeof(*attr) > metadata_size)
		return 0;
	return next_offset;
}

int cbfsf_decompression_info(struct cbfsf *fh, uint32_t *algo, size_t *size)
{
	size_t metadata_size = region_device_sz(&fh->metadata);
	void *metadata = rdev_mmap_full(&fh->metadata);
	size_t offs = 0;

	if (!metadata)
		return -1;

	while ((offs = cbfs_for_each_attr(metadata, metadata_size, offs))) {
		struct cbfs_file_attr_compression *attr = metadata + offs;
		if (read_be32(&attr->tag) != CBFS_FILE_ATTR_TAG_COMPRESSION)
			continue;

		*algo = read_be32(&attr->compression);
		*size = read_be32(&attr->decompressed_size);
		rdev_munmap(&fh->metadata, metadata);
		return 0;
	}

	*algo = CBFS_COMPRESS_NONE;
	*size = region_device_sz(&fh->data);
	rdev_munmap(&fh->metadata, metadata);
	return 0;
}

int cbfsf_file_type(struct cbfsf *fh, uint32_t *ftype)
{
	const size_t sz = sizeof(*ftype);

	if (rdev_readat(&fh->metadata, ftype,
			offsetof(struct cbfs_file, type), sz) != sz)
		return -1;

	*ftype = read_be32(ftype);

	return 0;
}

int cbfs_locate(struct cbfsf *fh, const struct region_device *cbfs,
		const char *name, uint32_t *type)
{
	struct cbfsf *prev;

	LOG("Locating '%s'\n", name);

	prev = NULL;

	while (1) {
		int ret;
		char *fname;
		int name_match;
		const size_t fsz = sizeof(struct cbfs_file);

		ret = cbfs_for_each_file(cbfs, prev, fh);
		prev = fh;

		/* Either failed to read or hit the end of the region. */
		if (ret < 0 || ret > 0)
			break;

		fname = rdev_mmap(&fh->metadata, fsz,
				region_device_sz(&fh->metadata) - fsz);

		if (fname == NULL)
			break;

		name_match = !strcmp(fname, name);
		rdev_munmap(&fh->metadata, fname);

		if (!name_match) {
			DEBUG(" Unmatched '%s' at %zx\n", fname,
				rdev_relative_offset(cbfs, &fh->metadata));
			continue;
		}

		if (type != NULL) {
			uint32_t ftype;

			if (cbfsf_file_type(fh, &ftype))
				break;

			if (*type != 0 && *type != ftype) {
				DEBUG(" Unmatched type %x at %zx\n", ftype,
					rdev_relative_offset(cbfs,
							&fh->metadata));
				continue;
			}
			// *type being 0 means we want to know ftype.
			// We could just do a blind assignment but
			// if type is pointing to read-only memory
			// that might be bad.
			if (*type == 0)
				*type = ftype;
		}

		LOG("Found @ offset %zx size %zx\n",
			rdev_relative_offset(cbfs, &fh->metadata),
			region_device_sz(&fh->data));

		/* Success. */
		return 0;
	}

	LOG("'%s' not found.\n", name);
	return -1;
}

static int cbfs_extend_hash_buffer(struct vb2_digest_context *ctx,
					void *buf, size_t sz)
{
	return vb2_digest_extend(ctx, buf, sz);
}

static int cbfs_extend_hash(struct vb2_digest_context *ctx,
				const struct region_device *rdev)
{
	uint8_t buffer[1024];
	size_t sz_left;
	size_t offset;

	sz_left = region_device_sz(rdev);
	offset = 0;

	while (sz_left) {
		int rv;
		size_t block_sz = MIN(sz_left, sizeof(buffer));

		if (rdev_readat(rdev, buffer, offset, block_sz) != block_sz)
			return VB2_ERROR_UNKNOWN;

		rv = cbfs_extend_hash_buffer(ctx, buffer, block_sz);

		if (rv)
			return rv;

		sz_left -= block_sz;
		offset += block_sz;
	}

	return VB2_SUCCESS;
}

/* Include offsets of child regions within the parent into the hash. */
static int cbfs_extend_hash_with_offset(struct vb2_digest_context *ctx,
					const struct region_device *p,
					const struct region_device *c)
{
	int32_t soffset;
	int rv;

	soffset = rdev_relative_offset(p, c);

	if (soffset < 0)
		return VB2_ERROR_UNKNOWN;

	/* All offsets in big endian format. */
	write_be32(&soffset, soffset);

	rv = cbfs_extend_hash_buffer(ctx, &soffset, sizeof(soffset));

	if (rv)
		return rv;

	return cbfs_extend_hash(ctx, c);
}

/* Hash in the potential CBFS header sitting at the beginning of the CBFS
 * region as well as relative offset at the end. */
static int cbfs_extend_hash_master_header(struct vb2_digest_context *ctx,
					const struct region_device *cbfs)
{
	struct region_device rdev;
	int rv;

	if (rdev_chain(&rdev, cbfs, 0, sizeof(struct cbfs_header)))
		return VB2_ERROR_UNKNOWN;

	rv = cbfs_extend_hash_with_offset(ctx, cbfs, &rdev);

	if (rv)
		return rv;

	/* Include potential relative offset at end of region. */
	if (rdev_chain(&rdev, cbfs, region_device_sz(cbfs) - sizeof(int32_t),
			sizeof(int32_t)))
		return VB2_ERROR_UNKNOWN;

	return cbfs_extend_hash_with_offset(ctx, cbfs, &rdev);
}

int cbfs_vb2_hash_contents(const struct region_device *cbfs,
				enum vb2_hash_algorithm hash_alg, void *digest,
				size_t digest_sz)
{
	struct vb2_digest_context ctx;
	int rv;
	struct cbfsf f;
	struct cbfsf *prev;
	struct cbfsf *fh;

	rv = vb2_digest_init(&ctx, hash_alg);

	if (rv)
		return rv;

	rv = cbfs_extend_hash_master_header(&ctx, cbfs);
	if (rv)
		return rv;

	prev = NULL;
	fh = &f;

	while (1) {
		uint32_t ftype;

		rv = cbfs_for_each_file(cbfs, prev, fh);
		prev = fh;

		if (rv < 0)
			return VB2_ERROR_UNKNOWN;

		/* End of CBFS. */
		if (rv > 0)
			break;

		rv = cbfs_extend_hash_with_offset(&ctx, cbfs, &fh->metadata);

		if (rv)
			return rv;

		/* Include data contents in hash if file is non-empty. */
		if (cbfsf_file_type(fh, &ftype))
			return VB2_ERROR_UNKNOWN;

		if (ftype == CBFS_TYPE_DELETED || ftype == CBFS_TYPE_DELETED2)
			continue;

		rv = cbfs_extend_hash_with_offset(&ctx, cbfs, &fh->data);

		if (rv)
			return rv;
	}

	return vb2_digest_finalize(&ctx, digest, digest_sz);
}
