int setup_waveform_file(ulong waveform_buf)
{
	char *fs_argv[5];
	char addr[17];
	ulong file_len, mmc_dev;

	if (!check_mmc_autodetect())
		mmc_dev = getenv_ulong("mmcdev", 10, 0);
	else
		mmc_dev = mmc_get_env_devno();

	sprintf(addr, "%lx", waveform_buf);

	fs_argv[0] = "fatload";
	fs_argv[1] = "mmc";
	fs_argv[2] = simple_itoa(mmc_dev);
	fs_argv[3] = addr;
	fs_argv[4] = getenv("epdc_waveform");

	if (!fs_argv[4])
		fs_argv[4] = "epdc_splash.bin";

	if (do_fat_fsload(NULL, 0, 5, fs_argv)) {
		printf("MMC Device %lu not found\n", mmc_dev);
		return -1;
	}

	file_len = getenv_hex("filesize", 0);
	if (!file_len)
		return -1;

	flush_cache((ulong)addr, file_len);

	return 0;
}
int sunxi_bmp_display(char *name)
{
	sunxi_bmp_store_t bmp_info;
	char  bmp_name[32];
	char *const bmp_argv[6] = { "fatload", "sunxi_flash", "0", "40000000", bmp_name, NULL };

	memset(bmp_name, 0, 32);
	strcpy(bmp_name, name);
    if(do_fat_fsload(0, 0, 5, bmp_argv))
	{
	   printf("sunxi bmp info error : unable to open logo file %s\n", bmp_argv[4]);

	   return -1;
    }
	//bmp_info.buffer = (void *)SUNXI_DISPLAY_FRAME_BUFFER_ADDR;
#if defined(CONFIG_SUNXI_LOGBUFFER)
	bmp_info.buffer = (void *)(CONFIG_SYS_SDRAM_BASE + gd->ram_size - SUNXI_DISPLAY_FRAME_BUFFER_SIZE);
#else
	bmp_info.buffer = (void *)(SUNXI_DISPLAY_FRAME_BUFFER_ADDR);
#endif
	if(!sunxi_bmp_decode(0x40000000, &bmp_info))
	{
		debug("decode bmp ok\n");

		return sunxi_bmp_show(bmp_info);
	}

	return -1;
}
static int do_sunxi_bmp_info(cmd_tbl_t * cmdtp, int flag, int argc, char * const argv[])
{
	uint addr;

	if(argc == 2)
	{
		/* use argument only*/
		addr = simple_strtoul(argv[1], NULL, 16);
		debug("bmp addr=%x\n", addr);
	}
	else if(argc == 3)
	{
		char  load_addr[8];
		char  filename[32];
		char *const bmp_argv[6] = { "fatload", "sunxi_flash", "0", load_addr, filename, NULL };

		addr = simple_strtoul(argv[1], NULL, 16);
		memcpy(load_addr, argv[1], 8);
		memset(filename, 0, 32);
		memcpy(filename, argv[2], strlen(argv[2]));
#ifdef DEBUG
	    int i;

		for(i=0;i<6;i++)
		{
	        printf("argv[%d] = %s\n", i, argv[i]);
		}
#endif
	    if(do_fat_fsload(0, 0, 5, bmp_argv))
		{
		   printf("sunxi bmp info error : unable to open bmp file %s\n", argv[2]);

		   return cmd_usage(cmdtp);
	    }
	}
	else
	{
		return cmd_usage(cmdtp);
	}

	return (sunxi_bmp_probe_info(addr));
}
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;
}
static int do_sunxi_bmp_display(cmd_tbl_t * cmdtp, int flag, int argc, char * const argv[])
{
	uint addr;
	uint de_addr;
	sunxi_bmp_store_t bmp_info;

	if(argc == 2)
	{
		/* use argument only*/
		addr = simple_strtoul(argv[1], NULL, 16);
#if defined(CONFIG_SUNXI_LOGBUFFER)
		de_addr = CONFIG_SYS_SDRAM_BASE + gd->ram_size - SUNXI_DISPLAY_FRAME_BUFFER_SIZE;
#else
		de_addr = SUNXI_DISPLAY_FRAME_BUFFER_ADDR;
#endif
	}
	else if(argc == 3)
	{
		addr = simple_strtoul(argv[1], NULL, 16);
		de_addr = simple_strtoul(argv[2], NULL, 16);
	}
	else if(argc == 4)
	{
		char  load_addr[8];
		char  filename[32];
		char *const bmp_argv[6] = { "fatload", "sunxi_flash", "0", load_addr, filename, NULL };

		addr = simple_strtoul(argv[1], NULL, 16);
		memcpy(load_addr, argv[1], 8);
		memset(filename, 0, 32);
		memcpy(filename, argv[3], strlen(argv[3]));
		de_addr = simple_strtoul(argv[2], NULL, 16);
#ifdef DEBUG
	    int i;

		for(i=0;i<6;i++)
		{
	        printf("argv[%d] = %s\n", i, argv[i]);
		}
#endif
	    if(do_fat_fsload(0, 0, 5, bmp_argv))
		{
		   printf("sunxi bmp info error : unable to open bmp file %s\n", argv[2]);

		   return cmd_usage(cmdtp);
	    }
	}
	else
	{
		return cmd_usage(cmdtp);
	}
	if(de_addr < CONFIG_SYS_SDRAM_BASE)
	{
#if defined(CONFIG_SUNXI_LOGBUFFER)
		de_addr = CONFIG_SYS_SDRAM_BASE + gd->ram_size - SUNXI_DISPLAY_FRAME_BUFFER_SIZE;
#else
		de_addr = SUNXI_DISPLAY_FRAME_BUFFER_ADDR;
#endif
	}
	debug("bmp addr %x, display addr %x\n", addr, de_addr);
	bmp_info.buffer = (void *)de_addr;
	if(!sunxi_bmp_decode(addr, &bmp_info))
	{
		debug("decode bmp ok\n");

		return sunxi_bmp_show(bmp_info);
	}
	debug("decode bmp error\n");

	return -1;
}
//extern int do_bootm (cmd_tbl_t *cmdtp, int flag, int argc, char *argv[]);
void recoveryHandle(void)
{
	char cmd[256];
	char img[10];
	char * argv[3];
	char *env;
	MV_32 imagAddr, imagSize = 0, netflag = 1;
	char ip[16]= {"dhcp"};
	char* usbload[5];
	unsigned int netwait = 3000;
	int upgrade = -1;
	
	/* get the loadaddr env var */
	if (!getenv("loadaddr")) {
		printf("Missing loadaddr environment variable assuming default (%s)!\n", RCVR_LOAD_ADDR);
		setenv("loadaddr",RCVR_LOAD_ADDR);
		saveenv();
	}

#ifdef CONFIG_USB_STORAGE
	/* First try to perform recovery from USB DOK*/
	/* try to recognize storage devices immediately */
	if (usb_init() >= 0)
	{
		if (usb_stor_scan(1) >= 0)
		{
			netflag = 0;
			usbload[0] = "usbload";
			usbload[1] = "usb";
			usbload[2] = "0:1";
			usbload[3] = getenv("loadaddr");
			usbload[4] = "/multiware.img";

			printf("Trying to load image from USB flash drive using FAT FS\n");
			if (do_fat_fsload(0, 0, 5, usbload) == 1)
			{
				printf("Trying to load image from USB flash drive using ext2 FS partition 0\n");
				usbload[2] = "0:0";
				if(do_ext2load(0, 0, 5, usbload) == 1)
				{
					printf("Trying to load image from USB flash drive using ext2 FS partition 1\n");
					usbload[2] = "0:1";
					if(do_ext2load(0, 0, 5, usbload) == 1)
					{
						printf("Couldn't load recovery image from USB flash drive, Trying network interface\n");
						netflag = 1;
					}
					else
					{
						env = getenv("filesize");
						usbload[3] = getenv("loadaddr");
						imagSize = simple_strtoul(env, NULL, 16); /* get the filesize env var */
			
						/* Trying to check if we forced to upgrade by placing upgrade.me */
						usbload[4] = "/upgrade.me";
						usbload[3] = "0x000000000";
						env=getenv("loadaddr");
						imagAddr=simple_strtoul(env, NULL, 16);
						sprintf(usbload[3], "0x%x", imagAddr + imagSize + 1);
						printf("dummyaddr:%s\n", usbload[3]);
						upgrade=do_ext2load(0, 0, 5, usbload);
					}
				}
				else
				{
					env = getenv("filesize");
					imagSize = simple_strtoul(env, NULL, 16); /* get the filesize env var */

					/* Trying to check if we forced to upgrade by placing upgrade.me */
					usbload[4] = "/upgrade.me";
					usbload[3] = "0x000000000";
					env=getenv("loadaddr");
					imagAddr=simple_strtoul(env, NULL, 16);
					sprintf(usbload[3], "0x%x", imagAddr + imagSize + 1);
					printf("dummyaddr:%s\n", usbload[3]);
					upgrade=do_ext2load(0, 0, 5, usbload);
				}
			}
			else
			{
				env = getenv("filesize");
				imagSize = simple_strtoul(env, NULL, 16); /* get the filesize env var */

				/* Trying to check if we forced to upgrade by placing upgrade.me */
				usbload[4] = "/upgrade.me";
				usbload[3] = "0x000000000";
				env=getenv("loadaddr");
				imagAddr=simple_strtoul(env, NULL, 16);
				sprintf(usbload[3], "0x%x", imagAddr + imagSize + 1);
				printf("dummyaddr:%s\n", usbload[3]);
				upgrade=do_fat_fsload(0, 0, 5, usbload);
			}

			// Decide on upgrade/init mode
			if (upgrade == 0)
				sprintf(ip, "usb_upgrade");
			else
				sprintf(ip, "usb");
			printf("USB mode:%s\n", ip);
		}
	}
#endif

	if(netflag == 1)
	{
		/* if recovery ip set same as our ip then skip dhcp */
		while ( strcmp(getenv("rcvrip"), getenv("ipaddr")) && (netwait > 0) )
		{
			/* Perform the DHCP */
			printf("Aquiring an IP address using DHCP after delay...\n");
			mvOsDelay(netwait);
			netwait-=1000;

			if (NetLoop(DHCP) != -1)
			{
				/* We'vev got DHCP progressing with recovery */
				printf("DHCP should be ready for Recovery.\n");
				break;
			}
		}

		/* No DHCP after timeout or forced */
		if ( !strcmp(getenv("rcvrip"), getenv("ipaddr")) || (netwait <= 0) )
		{
			ulong tmpip;
			printf("No DHCP after timeout or manual IP address configured, switching to static IP address (%s)!\n", getenv("rcvrip"));
			tmpip = getenv_IPaddr ("rcvrip");
			NetCopyIP(&NetOurIP, &tmpip);
			sprintf(ip, "static");
		}

		/* Perform the recovery */
		printf("Starting retrieval of recovery image over network...\n");
		if ((imagSize = NetLoop(RCVR)) == -1)
		{
			printf("Failed\n");
			return;
		}
	}

	switch (mvBoardIdGet())
	{
		case RD_88F6510_SFU_ID:
		case RD_88F6560_GW_ID:
		case DB_88F6535_BP_ID:
			setenv("bootcmd","setenv bootargs ${console} ubi.mtd=2 root=ubi0:rootfsU rootfstype=ubifs ${mvNetConfig} ${mvPhoneConfig}; nand read.e ${loadaddr} 0x200000 0x400000; bootm ${loadaddr};");
			setenv("console","console=ttyS0,115200");
			saveenv();
		break;
	}

	printf("\nPermanent bootcmd: %s\n", getenv("bootcmd"));
	printf("\nPermanent console: %s\n", getenv("console"));

	/* This assignment to cmd should execute prior to the RD setenv and saveenv below*/
	sprintf(cmd,"setenv bootargs ${console} root=/dev/ram0 ${mvNetConfig} recovery=%s rcvrip=%s:%s%s  ethact=${ethact} ethaddr=%s eth1addr=%s; bootm ${loadaddr};", ip, getenv("rcvrip"), getenv("serverip"), getenv("bootargs_end"), getenv("ethaddr"), getenv("eth1addr"));
	setenv("bootcmd", cmd);
	printf("\nRecovery bootcmd: %s\n", cmd);

	printf("Booting recovery image at: [%s]...\n", getenv("loadaddr"));
	sprintf(cmd, "boot");
	sprintf(img, "%s", getenv("loadaddr"));
	argv[0] = cmd;
	argv[1] = img;

	do_bootd(NULL, 0, 2, argv);
}