/*
 * cbfs-mkstage
 *
 * Copyright (C) 2008 Jordan Crouse <jordan@cosmicpenguin.net>
 *               2009 coresystems GmbH
 *                 written by Patrick Georgi <patrick.georgi@coresystems.de>
 * Copyright (C) 2012 Google, Inc.
 *
 * 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; version 2 of the License.
 *
 * 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., 51 Franklin St, Fifth Floor, Boston, MA, 02110-1301 USA
 */

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

#include "common.h"
#include "cbfs.h"
#include "elf.h"

static unsigned int idemp(unsigned int x)
{
	return x;
}

/* This is a wrapper around the swab32() macro to make it
 * usable for the current implementation of parse_elf_to_stage()
 */
static unsigned int swap32(unsigned int x)
{
	return swab32(x);
}

unsigned int (*elf32_to_native) (unsigned int) = idemp;

/* returns size of result, or -1 if error */
int parse_elf_to_stage(const struct buffer *input, struct buffer *output,
		       comp_algo algo, uint32_t *location)
{
	Elf32_Phdr *phdr;
	Elf32_Ehdr *ehdr = (Elf32_Ehdr *)input->data;
	char *header, *buffer;

	int headers;
	int i;
	struct cbfs_stage *stage;
	unsigned int data_start, data_end, mem_end;

	int elf_bigendian = 0;

	comp_func_ptr compress = compression_function(algo);
	if (!compress)
		return -1;

	DEBUG("start: parse_elf_to_stage(location=0x%x)\n", *location);
	if (!iself((unsigned char *)input->data)) {
		ERROR("The stage file is not in ELF format!\n");
		return -1;
	}

	// The tool may work in architecture-independent way.
	if (arch != CBFS_ARCHITECTURE_UNKNOWN &&
	    !((ehdr->e_machine == EM_ARM) && (arch == CBFS_ARCHITECTURE_ARM)) &&
	    !((ehdr->e_machine == EM_386) && (arch == CBFS_ARCHITECTURE_X86))) {
		ERROR("The stage file has the wrong architecture\n");
		return -1;
	}

	if (ehdr->e_ident[EI_DATA] == ELFDATA2MSB) {
		elf_bigendian = 1;
	}
	if (elf_bigendian != is_big_endian()) {
		elf32_to_native = swap32;
	}

	headers = ehdr->e_phnum;
	header = (char *)ehdr;

	phdr = (Elf32_Phdr *) & header[elf32_to_native(ehdr->e_phoff)];

	/* Now, regular headers - we only care about PT_LOAD headers,
	 * because thats what we're actually going to load
	 */

	data_start = 0xFFFFFFFF;
	data_end = 0;
	mem_end = 0;

	for (i = 0; i < headers; i++) {
		unsigned int start, mend, rend;

		if (elf32_to_native(phdr[i].p_type) != PT_LOAD)
			continue;

		/* Empty segments are never interesting */
		if (elf32_to_native(phdr[i].p_memsz) == 0)
			continue;

		/* BSS */

		start = elf32_to_native(phdr[i].p_paddr);

		mend = start + elf32_to_native(phdr[i].p_memsz);
		rend = start + elf32_to_native(phdr[i].p_filesz);

		if (start < data_start)
			data_start = start;

		if (rend > data_end)
			data_end = rend;

		if (mend > mem_end)
			mem_end = mend;
	}

	if (data_start < *location) {
		data_start = *location;
	}

	if (data_end <= data_start) {
		ERROR("data ends before it starts. Make sure the "
			"ELF file is correct and resides in ROM space.\n");
		exit(1);
	}

	/* allocate an intermediate buffer for the data */
	buffer = calloc(data_end - data_start, 1);

	if (buffer == NULL) {
		ERROR("Unable to allocate memory: %m\n");
		return -1;
	}

	/* Copy the file data into the buffer */

	for (i = 0; i < headers; i++) {
		unsigned int l_start, l_offset = 0;

		if (elf32_to_native(phdr[i].p_type) != PT_LOAD)
			continue;

		if (elf32_to_native(phdr[i].p_memsz) == 0)
			continue;

		l_start = elf32_to_native(phdr[i].p_paddr);
		if (l_start < *location) {
			l_offset = *location - l_start;
			l_start = *location;
		}

		memcpy(buffer + (l_start - data_start),
		       &header[elf32_to_native(phdr[i].p_offset)+l_offset],
		       elf32_to_native(phdr[i].p_filesz)-l_offset);
	}

	/* Now make the output buffer */
	if (buffer_create(output, sizeof(*stage) + data_end - data_start,
			  input->name) != 0) {
		ERROR("Unable to allocate memory: %m\n");
		return -1;
	}
	memset(output->data, 0, output->size);

	stage = (struct cbfs_stage *)output->data;

	stage->load = data_start; /* FIXME: htonll */
	stage->memlen = mem_end - data_start;
	stage->compression = algo;
	stage->entry = ehdr->e_entry; /* FIXME: htonll */

	compress(buffer, data_end - data_start, (output->data + sizeof(*stage)),
		 (int *)&stage->len);
	free(buffer);

	if (*location)
		*location -= sizeof(struct cbfs_stage);
	output->size = sizeof(*stage) + stage->len;
	return 0;
}
