/* SPARC code for booting linux 2.6
 *
 * (C) Copyright 2007
 * Daniel Hellstrom, Gaisler Research, daniel@gaisler.com.
 *
 * See file CREDITS for list of people who contributed to this
 * project.
 *
 * 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; either version 2 of
 * the License, or (at your option) any later version.
 *
 * 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., 59 Temple Place, Suite 330, Boston,
 * MA 02111-1307 USA
 */

#include <common.h>
#include <command.h>
#include <asm/byteorder.h>
#include <asm/prom.h>
#include <asm/cache.h>

#define PRINT_KERNEL_HEADER

extern image_header_t header;
extern void srmmu_init_cpu(unsigned int entry);
extern void prepare_bootargs(char *bootargs);
extern int do_reset(cmd_tbl_t * cmdtp, int flag, int argc, char *argv[]);

#ifdef CONFIG_USB_UHCI
extern int usb_lowlevel_stop(void);
#endif

/* sparc kernel argument (the ROM vector) */
struct linux_romvec *kernel_arg_promvec;

/* page szie is 4k */
#define PAGE_SIZE 0x1000
#define RAMDISK_IMAGE_START_MASK	0x07FF
#define RAMDISK_PROMPT_FLAG		0x8000
#define RAMDISK_LOAD_FLAG		0x4000
struct __attribute__ ((packed)) {
	char traptable[PAGE_SIZE];
	char swapper_pg_dir[PAGE_SIZE];
	char pg0[PAGE_SIZE];
	char pg1[PAGE_SIZE];
	char pg2[PAGE_SIZE];
	char pg3[PAGE_SIZE];
	char empty_bad_page[PAGE_SIZE];
	char empty_bad_page_table[PAGE_SIZE];
	char empty_zero_page[PAGE_SIZE];
	unsigned char hdr[4];	/* ascii "HdrS" */
	/* 00.02.06.0b is for Linux kernel 2.6.11 */
	unsigned char linuxver_mega_major;
	unsigned char linuxver_major;
	unsigned char linuxver_minor;
	unsigned char linuxver_revision;
	/* header version 0x0203 */
	unsigned short hdr_ver;
	union __attribute__ ((packed)) {
		struct __attribute__ ((packed)) {
			unsigned short root_flags;
			unsigned short root_dev;
			unsigned short ram_flags;
			unsigned int sparc_ramdisk_image;
			unsigned int sparc_ramdisk_size;
			unsigned int reboot_command;
			unsigned int resv[3];
			unsigned int end;
		} ver_0203;
	} hdr_input;
} *linux_hdr;

/* temporary initrd image holder */
image_header_t ihdr;

/* boot the linux kernel */
void do_bootm_linux(cmd_tbl_t * cmdtp, int flag, int argc, char *argv[],
		    bootm_headers_t * images)
{
	char *bootargs;
	ulong ep, load;
	ulong initrd_start, initrd_end;
	ulong rd_data_start, rd_data_end, rd_len;
	unsigned int data, len, checksum;
	unsigned int initrd_addr, kernend;
	void (*kernel) (struct linux_romvec *, void *);
	struct lmb *lmb = images->lmb;
	int ret;

	if (images->legacy_hdr_valid) {
		ep = image_get_ep(images->legacy_hdr_os);
		load = image_get_load(images->legacy_hdr_os);
#if defined(CONFIG_FIT)
	} else if (images->fit_uname_os) {
		int ret = fit_image_get_entry(images->fit_hdr_os,
					      images->fit_noffset_os, &ep);
		if (ret) {
			puts("Can't get entry point property!\n");
			goto error;
		}

		ret = fit_image_get_load(images->fit_hdr_os,
					 images->fit_noffset_os, &load);
		if (ret) {
			puts("Can't get load address property!\n");
			goto error;
		}
#endif
	} else {
		puts("Could not find kernel entry point!\n");
		goto error;
	}

	/* Get virtual address of kernel start */
	linux_hdr = (void *)load;

	/* */
	kernel = (void (*)(struct linux_romvec *, void *))ep;

	/* check for a SPARC kernel */
	if ((linux_hdr->hdr[0] != 'H') ||
	    (linux_hdr->hdr[1] != 'd') ||
	    (linux_hdr->hdr[2] != 'r') || (linux_hdr->hdr[3] != 'S')) {
		puts("Error reading header of SPARC Linux kernel, aborting\n");
		goto error;
	}
#ifdef PRINT_KERNEL_HEADER
	printf("## Found SPARC Linux kernel %d.%d.%d ...\n",
	       linux_hdr->linuxver_major,
	       linux_hdr->linuxver_minor, linux_hdr->linuxver_revision);
#endif

#ifdef CONFIG_USB_UHCI
	usb_lowlevel_stop();
#endif

	/* set basic boot params in kernel header now that it has been
	 * extracted and is writeable.
	 */

	/*
	 * Are we going to use an initrd image?
	 */
	ret = boot_get_ramdisk(argc, argv, images, IH_ARCH_SPARC,
			       &rd_data_start, &rd_data_end);
	if (ret) {
		/* RAM disk found but was corrupt */
		puts("RAM Disk corrupt\n");
		goto error;
	}

	/* Calc length of RAM disk, if zero no ramdisk available */
	rd_len = rd_data_end - rd_data_start;

	if (rd_len) {

		/* Reserve the space used by PROM and stack. This is done
		 * to avoid that the RAM image is copied over stack or
		 * PROM.
		 */
		lmb_reserve(lmb, CFG_RELOC_MONITOR_BASE, CFG_RAM_END);

		ret = boot_ramdisk_high(lmb, rd_data_start, rd_len,
					&initrd_start, &initrd_end);
		if (ret) {
			puts("### Failed to relocate RAM disk\n");
			goto error;
		}

		/* Update SPARC kernel header so that Linux knows
		 * what is going on and where to find RAM disk.
		 *
		 * Set INITRD Image address relative to RAM Start
		 */
		linux_hdr->hdr_input.ver_0203.sparc_ramdisk_image =
		    initrd_start - CFG_RAM_BASE;
		linux_hdr->hdr_input.ver_0203.sparc_ramdisk_size = rd_len;
		/* Clear READ ONLY flag if set to non-zero */
		linux_hdr->hdr_input.ver_0203.root_flags = 1;
		/* Set root device to: Root_RAM0 */
		linux_hdr->hdr_input.ver_0203.root_dev = 0x100;
		linux_hdr->hdr_input.ver_0203.ram_flags = 0;
	} else {
		/* NOT using RAMDISK image, overwriting kernel defaults */
		linux_hdr->hdr_input.ver_0203.sparc_ramdisk_image = 0;
		linux_hdr->hdr_input.ver_0203.sparc_ramdisk_size = 0;
		/* Leave to kernel defaults
		   linux_hdr->hdr_input.ver_0203.root_flags = 1;
		   linux_hdr->hdr_input.ver_0203.root_dev = 0;
		   linux_hdr->hdr_input.ver_0203.ram_flags = 0;
		 */
	}

	/* Copy bootargs from bootargs variable to kernel readable area */
	bootargs = getenv("bootargs");
	prepare_bootargs(bootargs);

	if (!images->autostart)
		return;

	/* turn on mmu & setup context table & page table for process 0 (kernel) */
	srmmu_init_cpu((unsigned int)kernel);

	/* Enter SPARC Linux kernel
	 * From now on the only code in u-boot that will be
	 * executed is the PROM code.
	 */
	kernel(kernel_arg_promvec, (void *)ep);

	/* It will never come to this... */
	while (1) ;

      error:
	if (images->autostart)
		do_reset(cmdtp, flag, argc, argv);
	return;
}
