/*
 * (C) Copyright 2007 Schindler Lift Inc.
 * (C) Copyright 2007 DENX Software Engineering
 *
 * Author: Michel Marti <mma@objectxp.com>
 * Adapted for U-Boot 1.2 by Piotr Kruszynski <ppk@semihalf.com>:
 *   - code clean-up
 *   - bugfix for overwriting bootargs by user
 *
 * 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 <malloc.h>
#include <image.h>
#include <usb.h>
#include <fat.h>

#include "fwupdate.h"

extern int do_bootm(cmd_tbl_t *, int, int, char *[]);
extern long do_fat_read(const char *, void *, unsigned long, int);
extern int do_fat_fsload(cmd_tbl_t *, int, int, char *[]);

static int load_rescue_image(ulong);

void cm5200_fwupdate(void)
{
	cmd_tbl_t *bcmd;
	char *rsargs;
	char *tmp = NULL;
	char ka[16];
	char *argv[3] = { "bootm", ka, NULL };

	/* Check if rescue system is disabled... */
	if (getenv("norescue")) {
		printf(LOG_PREFIX "Rescue System disabled.\n");
		return;
	}

	/* Check if we have a USB storage device and load image */
	if (load_rescue_image(LOAD_ADDR))
		return;

	bcmd = find_cmd("bootm");
	if (!bcmd)
		return;

	sprintf(ka, "%lx", (ulong)LOAD_ADDR);

	/* prepare our bootargs */
	rsargs = getenv("rs-args");
	if (!rsargs)
		rsargs = RS_BOOTARGS;
	else {
		tmp = malloc(strlen(rsargs+1));
		if (!tmp) {
			printf(LOG_PREFIX "Memory allocation failed\n");
			return;
		}
		strcpy(tmp, rsargs);
		rsargs = tmp;
	}

	setenv("bootargs", rsargs);

	if (rsargs == tmp)
		free(rsargs);

	printf(LOG_PREFIX "Starting update system (bootargs=%s)...\n", rsargs);
	do_bootm(bcmd, 0, 2, argv);
}

static int load_rescue_image(ulong addr)
{
	disk_partition_t info;
	int devno;
	int partno;
	int i;
	char fwdir[64];
	char nxri[128];
	char *tmp;
	char dev[7];
	char addr_str[16];
	char *argv[6] = { "fatload", "usb", dev, addr_str, nxri, NULL };
	block_dev_desc_t *stor_dev = NULL;
	cmd_tbl_t *bcmd;

	/* Get name of firmware directory */
	tmp = getenv("fw-dir");

	/* Copy it into fwdir */
	strncpy(fwdir, tmp ? tmp : FW_DIR, sizeof(fwdir));
	fwdir[sizeof(fwdir) - 1] = 0; /* Terminate string */

	printf(LOG_PREFIX "Checking for firmware image directory '%s' on USB"
		" storage...\n", fwdir);
	usb_stop();
	if (usb_init() != 0)
		return 1;

	/* Check for storage device */
	if (usb_stor_scan(1) != 0) {
		usb_stop();
		return 1;
	}

	/* Detect storage device */
	for (devno = 0; devno < USB_MAX_STOR_DEV; devno++) {
		stor_dev = usb_stor_get_dev(devno);
		if (stor_dev->type != DEV_TYPE_UNKNOWN)
			break;
	}
	if (!stor_dev || stor_dev->type == DEV_TYPE_UNKNOWN) {
		printf(LOG_PREFIX "No valid storage device found...\n");
		usb_stop();
		return 1;
	}

	/* Detect partition */
	for (partno = -1, i = 0; i < 6; i++) {
		if (get_partition_info(stor_dev, i, &info) == 0) {
			if (fat_register_device(stor_dev, i) == 0) {
				/* Check if rescue image is present */
				FW_DEBUG("Looking for firmware directory '%s'"
					" on partition %d\n", fwdir, i);
				if (do_fat_read(fwdir, NULL, 0, LS_NO) == -1) {
					FW_DEBUG("No NX rescue image on "
						"partition %d.\n", i);
					partno = -2;
				} else {
					partno = i;
					FW_DEBUG("Partition %d contains "
						"firmware directory\n", partno);
					break;
				}
			}
		}
	}

	if (partno < 0) {
		switch (partno) {
		case -1:
			printf(LOG_PREFIX "Error: No valid (FAT) partition "
				"detected\n");
			break;
		case -2:
			printf(LOG_PREFIX "Error: No NX rescue image on FAT "
				"partition\n");
			break;
		default:
			printf(LOG_PREFIX "Error: Failed with code %d\n",
				partno);
		}
		usb_stop();
		return 1;
	}

	/* Load the rescue image */
	bcmd = find_cmd("fatload");
	if (!bcmd) {
		printf(LOG_PREFIX "Error - 'fatload' command not present.\n");
		usb_stop();
		return 1;
	}

	tmp = getenv("nx-rescue-image");
	sprintf(nxri, "%s/%s", fwdir, tmp ? tmp : RESCUE_IMAGE);
	sprintf(dev, "%d:%d", devno, partno);
	sprintf(addr_str, "%lx", addr);

	FW_DEBUG("fat_fsload device='%s', addr='%s', file: %s\n",
		dev, addr_str, nxri);

	if (do_fat_fsload(bcmd, 0, 5, argv) != 0) {
		usb_stop();
		return 1;
	}

	/* Stop USB */
	usb_stop();
	return 0;
}
