/*
 * Copyright (c) 2011 The Chromium OS Authors. All rights reserved.
 *
 * SPDX-License-Identifier:	GPL-2.0+
 */

#include <cbfs.h>
#include <malloc.h>
#include <asm/byteorder.h>

enum cbfs_result file_cbfs_result;

const char *file_cbfs_error(void)
{
	switch (file_cbfs_result) {
	case CBFS_SUCCESS:
		return "Success";
	case CBFS_NOT_INITIALIZED:
		return "CBFS not initialized";
	case CBFS_BAD_HEADER:
		return "Bad CBFS header";
	case CBFS_BAD_FILE:
		return "Bad CBFS file";
	case CBFS_FILE_NOT_FOUND:
		return "File not found";
	default:
		return "Unknown";
	}
}


static const u32 good_magic = 0x4f524243;
static const u8 good_file_magic[] = "LARCHIVE";


static int initialized;
static struct cbfs_header cbfs_header;
static struct cbfs_cachenode *file_cache;

/* Do endian conversion on the CBFS header structure. */
static void swap_header(struct cbfs_header *dest, struct cbfs_header *src)
{
	dest->magic = be32_to_cpu(src->magic);
	dest->version = be32_to_cpu(src->version);
	dest->rom_size = be32_to_cpu(src->rom_size);
	dest->boot_block_size = be32_to_cpu(src->boot_block_size);
	dest->align = be32_to_cpu(src->align);
	dest->offset = be32_to_cpu(src->offset);
}

/* Do endian conversion on a CBFS file header. */
static void swap_file_header(struct cbfs_fileheader *dest,
			     const struct cbfs_fileheader *src)
{
	memcpy(&dest->magic, &src->magic, sizeof(dest->magic));
	dest->len = be32_to_cpu(src->len);
	dest->type = be32_to_cpu(src->type);
	dest->checksum = be32_to_cpu(src->checksum);
	dest->offset = be32_to_cpu(src->offset);
}

/*
 * Given a starting position in memory, scan forward, bounded by a size, and
 * find the next valid CBFS file. No memory is allocated by this function. The
 * caller is responsible for allocating space for the new file structure.
 *
 * @param start		The location in memory to start from.
 * @param size		The size of the memory region to search.
 * @param align		The alignment boundaries to check on.
 * @param newNode	A pointer to the file structure to load.
 * @param used		A pointer to the count of of bytes scanned through,
 *			including the file if one is found.
 *
 * @return 1 if a file is found, 0 if one isn't.
 */
static int file_cbfs_next_file(u8 *start, u32 size, u32 align,
			       struct cbfs_cachenode *newNode, u32 *used)
{
	struct cbfs_fileheader header;

	*used = 0;

	while (size >= align) {
		const struct cbfs_fileheader *fileHeader =
			(const struct cbfs_fileheader *)start;
		u32 name_len;
		u32 step;

		/* Check if there's a file here. */
		if (memcmp(good_file_magic, &(fileHeader->magic),
				sizeof(fileHeader->magic))) {
			*used += align;
			size -= align;
			start += align;
			continue;
		}

		swap_file_header(&header, fileHeader);
		if (header.offset < sizeof(const struct cbfs_cachenode *) ||
				header.offset > header.len) {
			file_cbfs_result = CBFS_BAD_FILE;
			return -1;
		}
		newNode->next = NULL;
		newNode->type = header.type;
		newNode->data = start + header.offset;
		newNode->data_length = header.len;
		name_len = header.offset - sizeof(struct cbfs_cachenode *);
		newNode->name = (char *)fileHeader +
				sizeof(struct cbfs_cachenode *);
		newNode->name_length = name_len;
		newNode->checksum = header.checksum;

		step = header.len;
		if (step % align)
			step = step + align - step % align;

		*used += step;
		return 1;
	}
	return 0;
}

/* Look through a CBFS instance and copy file metadata into regular memory. */
static void file_cbfs_fill_cache(u8 *start, u32 size, u32 align)
{
	struct cbfs_cachenode *cache_node;
	struct cbfs_cachenode *newNode;
	struct cbfs_cachenode **cache_tail = &file_cache;

	/* Clear out old information. */
	cache_node = file_cache;
	while (cache_node) {
		struct cbfs_cachenode *oldNode = cache_node;
		cache_node = cache_node->next;
		free(oldNode);
	}
	file_cache = NULL;

	while (size >= align) {
		int result;
		u32 used;

		newNode = (struct cbfs_cachenode *)
				malloc(sizeof(struct cbfs_cachenode));
		result = file_cbfs_next_file(start, size, align,
			newNode, &used);

		if (result < 0) {
			free(newNode);
			return;
		} else if (result == 0) {
			free(newNode);
			break;
		}
		*cache_tail = newNode;
		cache_tail = &newNode->next;

		size -= used;
		start += used;
	}
	file_cbfs_result = CBFS_SUCCESS;
}

/* Get the CBFS header out of the ROM and do endian conversion. */
static int file_cbfs_load_header(uintptr_t end_of_rom,
				 struct cbfs_header *header)
{
	struct cbfs_header *header_in_rom;

	header_in_rom = (struct cbfs_header *)(uintptr_t)
			*(u32 *)(end_of_rom - 3);
	swap_header(header, header_in_rom);

	if (header->magic != good_magic || header->offset >
			header->rom_size - header->boot_block_size) {
		file_cbfs_result = CBFS_BAD_HEADER;
		return 1;
	}
	return 0;
}

void file_cbfs_init(uintptr_t end_of_rom)
{
	u8 *start_of_rom;
	initialized = 0;

	if (file_cbfs_load_header(end_of_rom, &cbfs_header))
		return;

	start_of_rom = (u8 *)(end_of_rom + 1 - cbfs_header.rom_size);

	file_cbfs_fill_cache(start_of_rom + cbfs_header.offset,
			     cbfs_header.rom_size, cbfs_header.align);
	if (file_cbfs_result == CBFS_SUCCESS)
		initialized = 1;
}

const struct cbfs_header *file_cbfs_get_header(void)
{
	if (initialized) {
		file_cbfs_result = CBFS_SUCCESS;
		return &cbfs_header;
	} else {
		file_cbfs_result = CBFS_NOT_INITIALIZED;
		return NULL;
	}
}

const struct cbfs_cachenode *file_cbfs_get_first(void)
{
	if (!initialized) {
		file_cbfs_result = CBFS_NOT_INITIALIZED;
		return NULL;
	} else {
		file_cbfs_result = CBFS_SUCCESS;
		return file_cache;
	}
}

void file_cbfs_get_next(const struct cbfs_cachenode **file)
{
	if (!initialized) {
		file_cbfs_result = CBFS_NOT_INITIALIZED;
		file = NULL;
		return;
	}

	if (*file)
		*file = (*file)->next;
	file_cbfs_result = CBFS_SUCCESS;
}

const struct cbfs_cachenode *file_cbfs_find(const char *name)
{
	struct cbfs_cachenode *cache_node = file_cache;

	if (!initialized) {
		file_cbfs_result = CBFS_NOT_INITIALIZED;
		return NULL;
	}

	while (cache_node) {
		if (!strcmp(name, cache_node->name))
			break;
		cache_node = cache_node->next;
	}
	if (!cache_node)
		file_cbfs_result = CBFS_FILE_NOT_FOUND;
	else
		file_cbfs_result = CBFS_SUCCESS;

	return cache_node;
}

const struct cbfs_cachenode *file_cbfs_find_uncached(uintptr_t end_of_rom,
						     const char *name)
{
	u8 *start;
	u32 size;
	u32 align;
	static struct cbfs_cachenode node;

	if (file_cbfs_load_header(end_of_rom, &cbfs_header))
		return NULL;

	start = (u8 *)(end_of_rom + 1 - cbfs_header.rom_size);
	size = cbfs_header.rom_size;
	align = cbfs_header.align;

	while (size >= align) {
		int result;
		u32 used;

		result = file_cbfs_next_file(start, size, align, &node, &used);

		if (result < 0)
			return NULL;
		else if (result == 0)
			break;

		if (!strcmp(name, node.name))
			return &node;

		size -= used;
		start += used;
	}
	file_cbfs_result = CBFS_FILE_NOT_FOUND;
	return NULL;
}

const char *file_cbfs_name(const struct cbfs_cachenode *file)
{
	file_cbfs_result = CBFS_SUCCESS;
	return file->name;
}

u32 file_cbfs_size(const struct cbfs_cachenode *file)
{
	file_cbfs_result = CBFS_SUCCESS;
	return file->data_length;
}

u32 file_cbfs_type(const struct cbfs_cachenode *file)
{
	file_cbfs_result = CBFS_SUCCESS;
	return file->type;
}

long file_cbfs_read(const struct cbfs_cachenode *file, void *buffer,
		    unsigned long maxsize)
{
	u32 size;

	size = file->data_length;
	if (maxsize && size > maxsize)
		size = maxsize;

	memcpy(buffer, file->data, size);

	file_cbfs_result = CBFS_SUCCESS;
	return size;
}
