Merge branch 'master' of git://git.denx.de/u-boot-blackfin
diff --git a/MAINTAINERS b/MAINTAINERS
new file mode 100644
index 0000000..af194ca
--- /dev/null
+++ b/MAINTAINERS
@@ -0,0 +1,405 @@
+Descriptions of section entries:
+
+	P: Person (obsolete)
+	M: Mail patches to: FullName <address@domain>
+	L: Mailing list that is relevant to this area
+	W: Web-page with status/info
+	Q: Patchwork web based patch tracking system site
+	T: SCM tree type and location.
+	   Type is one of: git, hg, quilt, stgit, topgit
+	S: Status, one of the following:
+	   Supported:	Someone is actually paid to look after this.
+	   Maintained:	Someone actually looks after it.
+	   Odd Fixes:	It has a maintainer but they don't have time to do
+			much other than throw the odd patch in. See below..
+	   Orphan:	No current maintainer [but maybe you could take the
+			role as you write your new code].
+	   Obsolete:	Old code. Something tagged obsolete generally means
+			it has been replaced by a better system and you
+			should be using that.
+	F: Files and directories with wildcard patterns.
+	   A trailing slash includes all files and subdirectory files.
+	   F:	drivers/net/	all files in and below drivers/net
+	   F:	drivers/net/*	all files in drivers/net, but not below
+	   F:	*/net/*		all files in "any top level directory"/net
+	   One pattern per line.  Multiple F: lines acceptable.
+	N: Files and directories with regex patterns.
+	   N:	[^a-z]tegra	all files whose path contains the word tegra
+	   One pattern per line.  Multiple N: lines acceptable.
+	   scripts/get_maintainer.pl has different behavior for files that
+	   match F: pattern and matches of N: patterns.  By default,
+	   get_maintainer will not look at git log history when an F: pattern
+	   match occurs.  When an N: match occurs, git log history is used
+	   to also notify the people that have git commit signatures.
+	X: Files and directories that are NOT maintained, same rules as F:
+	   Files exclusions are tested before file matches.
+	   Can be useful for excluding a specific subdirectory, for instance:
+	   F:	net/
+	   X:	net/ipv6/
+	   matches all files in and below net excluding net/ipv6/
+	K: Keyword perl extended regex pattern to match content in a
+	   patch or file.  For instance:
+	   K: of_get_profile
+	      matches patches or files that contain "of_get_profile"
+	   K: \b(printk|pr_(info|err))\b
+	      matches patches or files that contain one or more of the words
+	      printk, pr_info or pr_err
+	   One regex pattern per line.  Multiple K: lines acceptable.
+
+Note: For the hard of thinking, this list is meant to remain in alphabetical
+order. If you could add yourselves to it in alphabetical order that would be
+so much easier [Ed]
+
+Maintainers List (try to look for most precise areas first)
+
+		-----------------------------------
+ARC
+M:	Alexey Brodkin <alexey.brodkin@synopsys.com>
+S:	Maintained
+T:	git git://git.denx.de/u-boot-arc.git
+F:	arch/arc/
+
+ARM
+M:	Albert Aribaud <albert.u.boot@aribaud.net>
+S:	Maintained
+T:	git git://git.denx.de/u-boot-arm.git
+F:	arch/arm/
+
+ARM ATMEL AT91
+M:	Andreas Bießmann <andreas.devel@googlemail.com>
+S:	Maintained
+T:	git git://git.denx.de/u-boot-atmel.git
+F:	arch/arm/cpu/armv7/at91/
+F:	arch/arm/cpu/at91-common/
+F:	arch/arm/include/asm/arch-at91/
+
+ARM FREESCALE IMX
+M:	Stefano Babic <sbabic@denx.de>
+S:	Maintained
+T:	git git://git.denx.de/u-boot-imx.git
+F:	arch/arm/cpu/arm1136/mx*/
+F:	arch/arm/cpu/arm926ejs/mx*/
+F:	arch/arm/cpu/arm926ejs/imx/
+F:	arch/arm/cpu/armv7/mx*/
+F:	arch/arm/cpu/armv7/vf610/
+F:	arch/arm/cpu/imx-common/
+F:	arch/arm/include/asm/arch-imx/
+F:	arch/arm/include/asm/arch-mx*/
+F:	arch/arm/include/asm/arch-vf610/
+F:	arch/arm/include/asm/imx-common/
+
+ARM MARVELL KIRKWOOD
+M:	Prafulla Wadaskar <prafulla@marvell.com>
+S:	Maintained
+T:	git git://git.denx.de/u-boot-marvell.git
+F:	arch/arm/cpu/arm926ejs/kirkwood/
+F:	arch/arm/include/asm/arch-kirkwood/
+
+ARM MARVELL PXA
+M:	Marek Vasut <marex@denx.de>
+S:	Maintained
+T:	git git://git.denx.de/u-boot-pxa.git
+F:	arch/arm/cpu/pxa/
+F:	arch/arm/include/asm/arch-pxa/
+
+ARM SAMSUNG
+M:	Minkyu Kang <mk7.kang@samsung.com>
+S:	Maintained
+T:	git git://git.denx.de/u-boot-samsung.git
+F:	arch/arm/cpu/arm920t/s3c24x0/
+F:	arch/arm/cpu/armv7/exynos/
+F:	arch/arm/cpu/armv7/s5pc1xx/
+F:	arch/arm/cpu/armv7/s5p-common/
+F:	arch/arm/include/asm/arch-exynos/
+F:	arch/arm/include/asm/arch-s3c24x0/
+F:	arch/arm/include/asm/arch-s5pc1xx/
+
+ARM STM SPEAR
+M:	Vipin Kumar <vipin.kumar@st.com>
+S:	Maintained
+T:	git git://git.denx.de/u-boot-stm.git
+F:	arch/arm/cpu/arm926ejs/spear/
+F:	arch/arm/include/asm/arch-spear/
+
+ARM SUNXI
+M:	Ian Campbell <ijc@hellion.org.uk>
+M:	Hans De Goede <hdegoede@redhat.com>
+S:	Maintained
+T:	git git://git.denx.de/u-boot-sunxi.git
+F:	arch/arm/cpu/armv7/sunxi/
+F:	arch/arm/include/asm/arch-sunxi/
+
+ARM TEGRA
+M:	Tom Warren <twarren@nvidia.com>
+S:	Maintained
+T:	git git://git.denx.de/u-boot-tegra.git
+F:	arch/arm/cpu/arm720t/tegra*/
+F:	arch/arm/cpu/armv7/tegra*/
+F:	arch/arm/cpu/tegra*/
+F:	arch/arm/include/asm/arch-tegra*/
+
+ARM TI
+M:	Tom Rini <trini@ti.com>
+S:	Maintained
+T:	git git://git.denx.de/u-boot-ti.git
+F:	arch/arm/cpu/arm926ejs/davinci/
+F:	arch/arm/cpu/arm926ejs/omap/
+F:	arch/arm/cpu/armv7/omap*/
+F:	arch/arm/include/asm/arch-davinci/
+F:	arch/arm/include/asm/arch-omap*/
+F:	arch/arm/include/asm/ti-common/
+
+ARM ZYNQ
+M:	Michal Simek <monstr@monstr.eu>
+S:	Maintained
+F:	arch/arm/cpu/armv7/zynq/
+F:	arch/arm/include/asm/arch-zynq/
+
+AVR32
+M:	Andreas Bießmann <andreas.devel@googlemail.com>
+S:	Maintained
+T:	git git://git.denx.de/u-boot-avr32.git
+F:	arch/avr32/
+
+BLACKFIN
+M:	Sonic Zhang <sonic.adi@gmail.com>
+S:	Maintained
+T:	git git://git.denx.de/u-boot-blackfin.git
+F:	arch/blackfin/
+
+BUILDMAN
+M:	Simon Glass <sjg@chromium.org>
+S:	Maintained
+F:	tools/buildman/
+
+CFI FLASH
+M:	Stefan Roese <sr@denx.de>
+S:	Maintained
+T:	git git://git.denx.de/u-boot-cfi-flash.git
+F:	drivers/mtd/*
+
+COLDFIRE
+M:	Jason Jin <jason.jin@freescale.com>
+S:	Maintained
+T:	git git://git.denx.de/u-boot-coldfire.git
+F:	arch/m68k/
+
+DFU
+M:	Lukasz Majewski <l.majewski@samsung.com>
+S:	Maintained
+T:	git git://git.denx.de/u-boot-dfu.git
+F:	drivers/dfu/
+
+DRIVER MODEL
+M:	Simon Glass <sjg@chromium.org>
+S:	Maintained
+F:	drivers/core/
+F:	include/dm/
+F:	test/dm/
+
+FLATTENED DEVICE TREE
+M:	Simon Glass <sjg@chromium.org>
+S:	Maintained
+T:	git git://git.denx.de/u-boot-fdt.git
+F:	lib/fdtdec*
+F:	lib/libfdt/
+F:	include/fdt*
+F:	include/libfdt*
+F.	common/cmd_fdt.c
+F:	common/fdt_support.c
+
+FREEBSD
+M:	Rafal Jaworowski <raj@semihalf.com>
+S:	Maintained
+T:	git git://git.denx.de/u-boot-freebsd.git
+
+FREESCALE QORIQ
+M:	York Sun <yorksun@freescale.com>
+S:	Maintained
+T:	git git://git.denx.de/u-boot-fsl-qoriq.git
+
+I2C
+M:	Heiko Schocher <hs@denx.de>
+S:	Maintained
+T:	git git://git.denx.de/u-boot-i2c.git
+F:	drivers/i2c/
+
+MICROBLAZE
+M:	Michal Simek <monstr@monstr.eu>
+S:	Maintained
+T:	git git://git.denx.de/u-boot-microblaze.git
+F:	arch/microblaze/
+
+MIPS
+M:	Daniel Schwierzeck <daniel.schwierzeck@gmail.com>
+S:	Maintained
+T:	git git://git.denx.de/u-boot-mips.git
+F:	arch/mips/
+
+MMC
+M:	Pantelis Antoniou <panto.antoniou-consulting.com>
+S:	Maintained
+T:	git git://git.denx.de/u-boot-mmc.git
+F:	drivers/mmc/
+
+OPENRISC
+M:	Stefan Kristiansson <stefan.kristiansson@saunalahti.fi>
+S:	Maintained
+F:	arch/openrisc/
+
+PATMAN
+M:	Simon Glass <sjg@chromium.org>
+S:	Maintained
+F:	tools/patman/
+
+POWERPC
+M:	Wolfgang Denk <wd@denx.de>
+S:	Maintained
+F:	arch/powerpc/
+
+POWERPC MPC5XXX
+M:	Wolfgang Denk <wd@denx.de>
+S:	Maintained
+T:	git git://git.denx.de/u-boot-mpc5xxx.git
+F:	arch/powerpc/cpu/mpc5*/
+
+POWERPC MPC8XX
+M:	Wolfgang Denk <wd@denx.de>
+S:	Maintained
+T:	git git://git.denx.de/u-boot-mpc8xx.git
+F:	arch/powerpc/cpu/mpc8xx/
+
+POWERPC MPC82XX
+M:	Wolfgang Denk <wd@denx.de>
+S:	Maintained
+T:	git git://git.denx.de/u-boot-mpc82xx.git
+F:	arch/powerpc/cpu/mpc82*/
+
+POWERPC MPC83XX
+M:	Kim Phillips <kim.phillips@freescale.com>
+S:	Maintained
+T:	git git://git.denx.de/u-boot-mpc83xx.git
+F:	arch/powerpc/cpu/mpc83xx/
+F:	arch/powerpc/include/asm/arch-mpc83xx/
+
+POWERPC MPC85XX
+M:	York Sun <yorksun@freescale.com>
+S:	Maintained
+T:	git git://git.denx.de/u-boot-mpc85xx.git
+F:	arch/powerpc/cpu/mpc85xx/
+
+POWERPC MPC86XX
+M:	York Sun <yorksun@freescale.com>
+S:	Maintained
+T:	git git://git.denx.de/u-boot-mpc86xx.git
+F:	arch/powerpc/cpu/mpc86xx/
+
+POWERPC PPC74XX PPC7XX
+M:	Wolfgang Denk <wd@denx.de>
+S:	Maintained
+T:	git git://git.denx.de/u-boot-74xx-7xx.git
+F:	arch/powerpc/cpu/74xx_7xx/
+
+POWERPC PPC4XX
+M:	Stefan Roese <sr@denx.de>
+S:	Maintained
+T:	git git://git.denx.de/u-boot-ppc4xx.git
+F:	arch/powerpc/cpu/ppc4xx/
+
+NETWORK
+M:	Joe Hershberger <joe.hershberger@gmail.com>
+S:	Maintained
+T:	git git://git.denx.de/u-boot-net.git
+F:	drivers/net/
+
+NAND FLASH
+M:	Scott Wood <scottwood@freescale.com>
+S:	Maintained
+T:	git git://git.denx.de/u-boot-nand-flash.git
+F:	drivers/mtd/nand/
+
+NDS32
+M:	Macpaul Lin <macpaul@andestech.com>
+S:	Maintained
+T:	git git://git.denx.de/u-boot-nds32.git
+F:	arch/nds32/
+
+NIOS
+M:	Thomas Chou <thomas@wytron.com.tw>
+S:	Maintained
+T:	git git://git.denx.de/u-boot-nios.git
+F:	arch/nios2/
+
+ONENAND
+M:	Lukasz Majewski <l.majewski@samsung.com>
+S:	Maintained
+T:	git git://git.denx.de/u-boot-onenand.git
+F:	drivers/mtd/onenand/
+
+SANDBOX
+M:	Simon Glass <sjg@chromium.org>
+S:	Maintained
+F:	arch/sandbox/
+
+SH
+M:	Nobuhiro Iwamatsu <iwamatsu@nigauri.org>
+S:	Maintained
+T:	git git://git.denx.de/u-boot-sh.git
+F:	arch/sh/
+
+SPARC
+M:	Daniel Hellstrom <daniel@gaisler.com>
+S:	Maintained
+T:	git git://git.denx.de/u-boot-sparc.git
+F:	arch/sparc/
+
+SPI
+M:	Jagannadha Sutradharudu Teki <jagannadh.teki@gmail.com>
+S:	Maintained
+T:	git git://git.denx.de/u-boot-spi.git
+F:	drivers/mtd/spi/
+F:	drivers/spi/
+F:	include/spi*
+
+TESTING
+M:	Detlev Zundel <dzu@denx.de>
+S:	Maintained
+T:	git git://git.denx.de/u-boot-testing.git
+
+TQ GROUP
+M:	Martin Krause <martin.krause@tq-systems.de>
+S:	Maintained
+T:	git git://git.denx.de/u-boot-tq-group.git
+
+UBI
+M:	Kyungmin Park <kmpark@infradead.org>
+S:	Maintained
+T:	git git://git.denx.de/u-boot-ubi.git
+F:	drivers/mtd/ubi/
+
+USB
+M:	Marek Vasut <marex@denx.de>
+S:	Maintained
+T:	git git://git.denx.de/u-boot-usb.git
+F:	drivers/usb/
+
+VIDEO
+M:	Anatolij Gustschin <agust@denx.de>
+S:	Maintained
+T:	git git://git.denx.de/u-boot-video.git
+F:	drivers/video/
+
+X86
+M:	Simon Glass <sjg@chromium.org>
+S:	Maintained
+T:	git git://git.denx.de/u-boot-x86.git
+F:	arch/x86/
+
+THE REST
+M:	Tom Rini <trini@ti.com>
+L:	u-boot@lists.denx.de
+Q:	http://patchwork.ozlabs.org/project/uboot/list/
+S:	Maintained
+T:	git git://git.denx.de/u-boot.git
+F:	*
+F:	*/
diff --git a/Makefile b/Makefile
index 666d291..b5d5e01 100644
--- a/Makefile
+++ b/Makefile
@@ -802,14 +802,15 @@
 
 OBJCOPYFLAGS_u-boot.bin := -O binary
 
-binary_size_check: u-boot.bin System.map FORCE
-	@file_size=`stat -c %s u-boot.bin` ; \
-	map_size=$(shell cat System.map | \
+binary_size_check: u-boot.bin FORCE
+	@file_size=$(shell wc -c u-boot.bin | awk '{print $$1}') ; \
+	map_size=$(shell cat u-boot.map | \
 		awk '/_image_copy_start/ {start = $$1} /_image_binary_end/ {end = $$1} END {if (start != "" && end != "") print "ibase=16; " toupper(end) " - " toupper(start)}' \
+		| sed 's/0X//g' \
 		| bc); \
 	if [ "" != "$$map_size" ]; then \
 		if test $$map_size -ne $$file_size; then \
-			echo "System.map shows a binary size of $$map_size" >&2 ; \
+			echo "u-boot.map shows a binary size of $$map_size" >&2 ; \
 			echo "  but u-boot.bin shows $$file_size" >&2 ; \
 			exit 1; \
 		fi \
diff --git a/arch/arm/include/asm/emif.h b/arch/arm/include/asm/emif.h
index b8d6bdc..2fe5776 100644
--- a/arch/arm/include/asm/emif.h
+++ b/arch/arm/include/asm/emif.h
@@ -878,7 +878,6 @@
 	((REG_CS_TIM << EMIF_REG_CS_TIM_SHIFT) & EMIF_REG_CS_TIM_MASK)|\
 	((REG_SR_TIM << EMIF_REG_SR_TIM_SHIFT) & EMIF_REG_SR_TIM_MASK)|\
 	((REG_PD_TIM << EMIF_REG_PD_TIM_SHIFT) & EMIF_REG_PD_TIM_MASK)|\
-	((REG_PD_TIM << EMIF_REG_PD_TIM_SHIFT) & EMIF_REG_PD_TIM_MASK)|\
 	((LP_MODE_DISABLE << EMIF_REG_LP_MODE_SHIFT)\
 			& EMIF_REG_LP_MODE_MASK) |\
 	((DPD_DISABLE << EMIF_REG_DPD_EN_SHIFT)\
@@ -890,8 +889,6 @@
 	((REG_SR_TIM << EMIF_REG_SR_TIM_SHDW_SHIFT)\
 			& EMIF_REG_SR_TIM_SHDW_MASK) |\
 	((REG_PD_TIM << EMIF_REG_PD_TIM_SHDW_SHIFT)\
-			& EMIF_REG_PD_TIM_SHDW_MASK) |\
-	((REG_PD_TIM << EMIF_REG_PD_TIM_SHDW_SHIFT)\
 			& EMIF_REG_PD_TIM_SHDW_MASK))
 
 /* EMIF_L3_CONFIG register value */
diff --git a/common/board_r.c b/common/board_r.c
index 8e7a3ac..ba9a68d 100644
--- a/common/board_r.c
+++ b/common/board_r.c
@@ -587,6 +587,7 @@
 {
 	puts("DOC:   ");
 	doc_init();
+	return 0;
 }
 #endif
 
diff --git a/common/bootm.c b/common/bootm.c
index 7ec2ed8..76d811c 100644
--- a/common/bootm.c
+++ b/common/bootm.c
@@ -731,26 +731,7 @@
 	int		os_noffset;
 #endif
 
-	/* find out kernel image address */
-	if (argc < 1) {
-		img_addr = load_addr;
-		debug("*  kernel: default image load address = 0x%08lx\n",
-		      load_addr);
-#if defined(CONFIG_FIT)
-	} else if (fit_parse_conf(argv[0], load_addr, &img_addr,
-				  &fit_uname_config)) {
-		debug("*  kernel: config '%s' from image at 0x%08lx\n",
-		      fit_uname_config, img_addr);
-	} else if (fit_parse_subimage(argv[0], load_addr, &img_addr,
-				     &fit_uname_kernel)) {
-		debug("*  kernel: subimage '%s' from image at 0x%08lx\n",
-		      fit_uname_kernel, img_addr);
-#endif
-	} else {
-		img_addr = simple_strtoul(argv[0], NULL, 16);
-		debug("*  kernel: cmdline image address = 0x%08lx\n",
-		      img_addr);
-	}
+	img_addr = genimg_get_kernel_addr(argv[0]);
 
 	bootstage_mark(BOOTSTAGE_ID_CHECK_MAGIC);
 
@@ -807,6 +788,10 @@
 #endif
 #if defined(CONFIG_FIT)
 	case IMAGE_FORMAT_FIT:
+		if (!fit_parse_conf(argv[0], load_addr, &img_addr,
+					&fit_uname_config))
+			fit_parse_subimage(argv[0], load_addr, &img_addr,
+					&fit_uname_kernel);
 		os_noffset = fit_image_load(images, img_addr,
 				&fit_uname_kernel, &fit_uname_config,
 				IH_ARCH_DEFAULT, IH_TYPE_KERNEL,
diff --git a/common/cmd_dfu.c b/common/cmd_dfu.c
index 433bddd..2633b30 100644
--- a/common/cmd_dfu.c
+++ b/common/cmd_dfu.c
@@ -24,8 +24,7 @@
 
 	int ret, i = 0;
 
-	ret = dfu_init_env_entities(interface, simple_strtoul(devstring,
-							      NULL, 10));
+	ret = dfu_init_env_entities(interface, devstring);
 	if (ret)
 		goto done;
 
diff --git a/common/cmd_ext4.c b/common/cmd_ext4.c
index 68b047b..ecfc6d3 100644
--- a/common/cmd_ext4.c
+++ b/common/cmd_ext4.c
@@ -42,6 +42,12 @@
 #include <usb.h>
 #endif
 
+int do_ext4_size(cmd_tbl_t *cmdtp, int flag, int argc,
+						char *const argv[])
+{
+	return do_size(cmdtp, flag, argc, argv, FS_TYPE_EXT);
+}
+
 int do_ext4_load(cmd_tbl_t *cmdtp, int flag, int argc,
 						char *const argv[])
 {
@@ -113,6 +119,14 @@
 
 #endif
 
+U_BOOT_CMD(
+	ext4size,	4,	0,	do_ext4_size,
+	"determine a file's size",
+	"<interface> <dev[:part]> <filename>\n"
+	"    - Find file 'filename' from 'dev' on 'interface'\n"
+	"      and determine its size."
+);
+
 U_BOOT_CMD(ext4ls, 4, 1, do_ext4_ls,
 	   "list files in a directory (default /)",
 	   "<interface> <dev[:part]> [directory]\n"
@@ -120,6 +134,6 @@
 
 U_BOOT_CMD(ext4load, 6, 0, do_ext4_load,
 	   "load binary file from a Ext4 filesystem",
-	   "<interface> <dev[:part]> [addr] [filename] [bytes]\n"
+	   "<interface> [<dev[:part]> [addr [filename [bytes [pos]]]]]\n"
 	   "    - load binary file 'filename' from 'dev' on 'interface'\n"
 	   "      to address 'addr' from ext4 filesystem");
diff --git a/common/cmd_fat.c b/common/cmd_fat.c
index a478017..633fbf1 100644
--- a/common/cmd_fat.c
+++ b/common/cmd_fat.c
@@ -18,6 +18,19 @@
 #include <fat.h>
 #include <fs.h>
 
+int do_fat_size(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
+{
+	return do_size(cmdtp, flag, argc, argv, FS_TYPE_FAT);
+}
+
+U_BOOT_CMD(
+	fatsize,	4,	0,	do_fat_size,
+	"determine a file's size",
+	"<interface> <dev[:part]> <filename>\n"
+	"    - Find file 'filename' from 'dev' on 'interface'\n"
+	"      and determine its size."
+);
+
 int do_fat_fsload (cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
 {
 	return do_load(cmdtp, flag, argc, argv, FS_TYPE_FAT);
diff --git a/common/cmd_fdt.c b/common/cmd_fdt.c
index e86d992..5640ded 100644
--- a/common/cmd_fdt.c
+++ b/common/cmd_fdt.c
@@ -621,7 +621,7 @@
 	}
 	/* resize the fdt */
 	else if (strncmp(argv[1], "re", 2) == 0) {
-		fdt_resize(working_fdt);
+		fdt_shrink_to_minimum(working_fdt);
 	}
 	else {
 		/* Unrecognized command */
diff --git a/common/cmd_fs.c b/common/cmd_fs.c
index 78590d2..6754340 100644
--- a/common/cmd_fs.c
+++ b/common/cmd_fs.c
@@ -20,6 +20,19 @@
 #include <command.h>
 #include <fs.h>
 
+static int do_size_wrapper(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
+{
+	return do_size(cmdtp, flag, argc, argv, FS_TYPE_ANY);
+}
+
+U_BOOT_CMD(
+	size,	4,	0,	do_size_wrapper,
+	"determine a file's size",
+	"<interface> <dev[:part]> <filename>\n"
+	"    - Find file 'filename' from 'dev' on 'interface'\n"
+	"      and determine its size."
+);
+
 static int do_load_wrapper(cmd_tbl_t *cmdtp, int flag, int argc,
 				char * const argv[])
 {
diff --git a/common/cmd_pxe.c b/common/cmd_pxe.c
index ba48692..c816339 100644
--- a/common/cmd_pxe.c
+++ b/common/cmd_pxe.c
@@ -1,5 +1,6 @@
 /*
  * Copyright 2010-2011 Calxeda, Inc.
+ * Copyright (c) 2014, NVIDIA CORPORATION.  All rights reserved.
  *
  * SPDX-License-Identifier:	GPL-2.0+
  */
@@ -609,6 +610,8 @@
 	char *bootargs;
 	int bootm_argc = 3;
 	int len = 0;
+	ulong kernel_addr;
+	void *buf;
 
 	label_print(label);
 
@@ -771,11 +774,15 @@
 	if (bootm_argv[3])
 		bootm_argc = 4;
 
-	do_bootm(cmdtp, 0, bootm_argc, bootm_argv);
-
+	kernel_addr = genimg_get_kernel_addr(bootm_argv[1]);
+	buf = map_sysmem(kernel_addr, 0);
+	/* Try bootm for legacy and FIT format image */
+	if (genimg_get_format(buf) != IMAGE_FORMAT_INVALID)
+		do_bootm(cmdtp, 0, bootm_argc, bootm_argv);
 #ifdef CONFIG_CMD_BOOTZ
-	/* Try booting a zImage if do_bootm returns */
-	do_bootz(cmdtp, 0, bootm_argc, bootm_argv);
+	/* Try booting a zImage */
+	else
+		do_bootz(cmdtp, 0, bootm_argc, bootm_argv);
 #endif
 	return 1;
 }
@@ -1554,6 +1561,8 @@
 
 	destroy_pxe_menu(cfg);
 
+	copy_filename(BootFile, "", sizeof(BootFile));
+
 	return 0;
 }
 
diff --git a/common/cmd_thordown.c b/common/cmd_thordown.c
index 2dd7509..8ed1dc6 100644
--- a/common/cmd_thordown.c
+++ b/common/cmd_thordown.c
@@ -26,10 +26,9 @@
 
 	puts("TIZEN \"THOR\" Downloader\n");
 
-	ret = dfu_init_env_entities(interface, simple_strtoul(devstring,
-							      NULL, 10));
+	ret = dfu_init_env_entities(interface, devstring);
 	if (ret)
-		return ret;
+		goto done;
 
 	int controller_index = simple_strtoul(usb_controller, NULL, 0);
 	ret = board_usb_init(controller_index, USB_INIT_DEVICE);
@@ -57,6 +56,7 @@
 
 exit:
 	g_dnl_unregister();
+done:
 	dfu_free_entities();
 
 	return ret;
diff --git a/common/env_fat.c b/common/env_fat.c
index 328c09d..8db0160 100644
--- a/common/env_fat.c
+++ b/common/env_fat.c
@@ -73,7 +73,7 @@
 
 void env_relocate_spec(void)
 {
-	char buf[CONFIG_ENV_SIZE];
+	ALLOC_CACHE_ALIGN_BUFFER(char, buf, CONFIG_ENV_SIZE);
 	block_dev_desc_t *dev_desc = NULL;
 	disk_partition_t info;
 	int dev, part;
@@ -92,7 +92,7 @@
 		goto err_env_relocate;
 	}
 
-	err = file_fat_read(FAT_ENV_FILE, (uchar *)&buf, CONFIG_ENV_SIZE);
+	err = file_fat_read(FAT_ENV_FILE, buf, CONFIG_ENV_SIZE);
 	if (err == -1) {
 		printf("\n** Unable to read \"%s\" from %s%d:%d **\n",
 			FAT_ENV_FILE, FAT_ENV_INTERFACE, dev, part);
diff --git a/common/fdt_support.c b/common/fdt_support.c
index 7927a83..784a570 100644
--- a/common/fdt_support.c
+++ b/common/fdt_support.c
@@ -508,7 +508,7 @@
 }
 
 /* Resize the fdt to its actual size + a bit of padding */
-int fdt_resize(void *blob)
+int fdt_shrink_to_minimum(void *blob)
 {
 	int i;
 	uint64_t addr, size;
diff --git a/common/image-fdt.c b/common/image-fdt.c
index db6e395..a2342fa 100644
--- a/common/image-fdt.c
+++ b/common/image-fdt.c
@@ -479,7 +479,7 @@
 	lmb_free(lmb, (phys_addr_t)(u32)(uintptr_t)blob,
 		 (phys_size_t)fdt_totalsize(blob));
 
-	ret = fdt_resize(blob);
+	ret = fdt_shrink_to_minimum(blob);
 	if (ret < 0)
 		return ret;
 	of_size = ret;
diff --git a/common/image.c b/common/image.c
index 11b3cf5..a2999c0 100644
--- a/common/image.c
+++ b/common/image.c
@@ -643,6 +643,49 @@
 
 #ifndef USE_HOSTCC
 /**
+ * genimg_get_kernel_addr - get the real kernel address
+ * @img_addr: a string might contain real image address
+ *
+ * genimg_get_kernel_addr() get the real kernel start address from a string
+ * which is normally the first argv of bootm/bootz
+ *
+ * returns:
+ *     kernel start address
+ */
+ulong genimg_get_kernel_addr(char * const img_addr)
+{
+#if defined(CONFIG_FIT)
+	const char	*fit_uname_config = NULL;
+	const char	*fit_uname_kernel = NULL;
+#endif
+
+	ulong kernel_addr;
+
+	/* find out kernel image address */
+	if (!img_addr) {
+		kernel_addr = load_addr;
+		debug("*  kernel: default image load address = 0x%08lx\n",
+		      load_addr);
+#if defined(CONFIG_FIT)
+	} else if (fit_parse_conf(img_addr, load_addr, &kernel_addr,
+				  &fit_uname_config)) {
+		debug("*  kernel: config '%s' from image at 0x%08lx\n",
+		      fit_uname_config, kernel_addr);
+	} else if (fit_parse_subimage(img_addr, load_addr, &kernel_addr,
+				     &fit_uname_kernel)) {
+		debug("*  kernel: subimage '%s' from image at 0x%08lx\n",
+		      fit_uname_kernel, kernel_addr);
+#endif
+	} else {
+		kernel_addr = simple_strtoul(img_addr, NULL, 16);
+		debug("*  kernel: cmdline image address = 0x%08lx\n",
+		      kernel_addr);
+	}
+
+	return kernel_addr;
+}
+
+/**
  * genimg_get_format - get image format type
  * @img_addr: image start address
  *
diff --git a/common/lcd.c b/common/lcd.c
index feb913a..217ec9d 100644
--- a/common/lcd.c
+++ b/common/lcd.c
@@ -100,7 +100,8 @@
 #if LCD_BPP == LCD_MONOCHROME
 # define COLOR_MASK(c)		((c)	  | (c) << 1 | (c) << 2 | (c) << 3 | \
 				 (c) << 4 | (c) << 5 | (c) << 6 | (c) << 7)
-#elif (LCD_BPP == LCD_COLOR8) || (LCD_BPP == LCD_COLOR16)
+#elif (LCD_BPP == LCD_COLOR8) || (LCD_BPP == LCD_COLOR16) || \
+	(LCD_BPP == LCD_COLOR32)
 # define COLOR_MASK(c)		(c)
 #else
 # error Unsupported LCD BPP.
@@ -109,14 +110,12 @@
 DECLARE_GLOBAL_DATA_PTR;
 
 static void lcd_drawchars(ushort x, ushort y, uchar *str, int count);
-static inline void lcd_puts_xy(ushort x, ushort y, uchar *s);
 static inline void lcd_putc_xy(ushort x, ushort y, uchar  c);
 
 static int lcd_init(void *lcdbase);
 
 static void *lcd_logo(void);
 
-static int lcd_getbgcolor(void);
 static void lcd_setfgcolor(int color);
 static void lcd_setbgcolor(int color);
 
@@ -177,10 +176,20 @@
 	       CONSOLE_SIZE - CONSOLE_ROW_SIZE * rows);
 
 	/* Clear the last rows */
+#if (LCD_BPP != LCD_COLOR32)
 	memset(lcd_console_address + CONSOLE_SIZE - CONSOLE_ROW_SIZE * rows,
 		COLOR_MASK(lcd_color_bg),
 		CONSOLE_ROW_SIZE * rows);
-
+#else
+	u32 *ppix = lcd_console_address +
+		    CONSOLE_SIZE - CONSOLE_ROW_SIZE * rows;
+	u32 i;
+	for (i = 0;
+	    i < (CONSOLE_ROW_SIZE * rows) / NBYTES(panel_info.vl_bpix);
+	    i++) {
+		*ppix++ = COLOR_MASK(lcd_color_bg);
+	}
+#endif
 	lcd_sync();
 	console_row -= rows;
 }
@@ -308,13 +317,15 @@
 	ushort off  = x * (1 << LCD_BPP) % 8;
 #endif
 
-	dest = (uchar *)(lcd_base + y * lcd_line_length + x * (1 << LCD_BPP) / 8);
+	dest = (uchar *)(lcd_base + y * lcd_line_length + x * NBITS(LCD_BPP)/8);
 
 	for (row = 0; row < VIDEO_FONT_HEIGHT; ++row, dest += lcd_line_length) {
 		uchar *s = str;
 		int i;
 #if LCD_BPP == LCD_COLOR16
 		ushort *d = (ushort *)dest;
+#elif LCD_BPP == LCD_COLOR32
+		u32 *d = (u32 *)dest;
 #else
 		uchar *d = dest;
 #endif
@@ -347,6 +358,12 @@
 						lcd_color_fg : lcd_color_bg;
 				bits <<= 1;
 			}
+#elif LCD_BPP == LCD_COLOR32
+			for (c = 0; c < 8; ++c) {
+				*d++ = (bits & 0x80) ?
+						lcd_color_fg : lcd_color_bg;
+				bits <<= 1;
+			}
 #endif
 		}
 #if LCD_BPP == LCD_MONOCHROME
@@ -355,15 +372,6 @@
 	}
 }
 
-/*----------------------------------------------------------------------*/
-
-static inline void lcd_puts_xy(ushort x, ushort y, uchar *s)
-{
-	lcd_drawchars(x, y, s, strlen((char *)s));
-}
-
-/*----------------------------------------------------------------------*/
-
 static inline void lcd_putc_xy(ushort x, ushort y, uchar c)
 {
 	lcd_drawchars(x, y, &c, 1);
@@ -476,9 +484,19 @@
 	test_pattern();
 #else
 	/* set framebuffer to background color */
+#if (LCD_BPP != LCD_COLOR32)
 	memset((char *)lcd_base,
-		COLOR_MASK(lcd_getbgcolor()),
+		COLOR_MASK(lcd_color_bg),
 		lcd_line_length * panel_info.vl_row);
+#else
+	u32 *ppix = lcd_base;
+	u32 i;
+	for (i = 0;
+	   i < (lcd_line_length * panel_info.vl_row)/NBYTES(panel_info.vl_bpix);
+	   i++) {
+		*ppix++ = COLOR_MASK(lcd_color_bg);
+	}
+#endif
 #endif
 	/* Paint the logo and retrieve LCD base address */
 	debug("[LCD] Drawing the logo...\n");
@@ -586,20 +604,6 @@
 	lcd_color_bg = color;
 }
 
-/*----------------------------------------------------------------------*/
-
-int lcd_getfgcolor(void)
-{
-	return lcd_color_fg;
-}
-
-/*----------------------------------------------------------------------*/
-
-static int lcd_getbgcolor(void)
-{
-	return lcd_color_bg;
-}
-
 /************************************************************************/
 /* ** Chipset depending Bitmap / Logo stuff...                          */
 /************************************************************************/
@@ -938,8 +942,13 @@
 		return 1;
 	}
 
-	/* We support displaying 8bpp BMPs on 16bpp LCDs */
-	if (bpix != bmp_bpix && !(bmp_bpix == 8 && bpix == 16)) {
+	/*
+	 * We support displaying 8bpp BMPs on 16bpp LCDs
+	 * and displaying 24bpp BMPs on 32bpp LCDs
+	 * */
+	if (bpix != bmp_bpix &&
+	    !(bmp_bpix == 8 && bpix == 16) &&
+	    !(bmp_bpix == 24 && bpix == 32)) {
 		printf ("Error: %d bit/pixel mode, but BMP has %d bit/pixel\n",
 			bpix, get_unaligned_le16(&bmp->header.bit_count));
 		return 1;
@@ -1060,7 +1069,19 @@
 		}
 		break;
 #endif /* CONFIG_BMP_16BPP */
-
+#if defined(CONFIG_BMP_24BMP)
+	case 24:
+		for (i = 0; i < height; ++i) {
+			for (j = 0; j < width; j++) {
+				*(fb++) = *(bmap++);
+				*(fb++) = *(bmap++);
+				*(fb++) = *(bmap++);
+				*(fb++) = 0;
+			}
+			fb -= lcd_line_length + width * (bpix / 8);
+		}
+		break;
+#endif /* CONFIG_BMP_24BMP */
 #if defined(CONFIG_BMP_32BPP)
 	case 32:
 		for (i = 0; i < height; ++i) {
diff --git a/doc/README.android-fastboot b/doc/README.android-fastboot
index f1d128c..4045727 100644
--- a/doc/README.android-fastboot
+++ b/doc/README.android-fastboot
@@ -38,6 +38,10 @@
 CONFIG_G_DNL_PRODUCT_NUM
 CONFIG_G_DNL_MANUFACTURER
 
+NOTE: The CONFIG_G_DNL_VENDOR_NUM must be one of the numbers supported by
+the fastboot client. The list of vendor IDs supported can be found in the
+fastboot client source code (fastboot.c) mentioned above.
+
 The fastboot function is enabled by defining CONFIG_CMD_FASTBOOT and
 CONFIG_ANDROID_BOOT_IMAGE.
 
diff --git a/doc/README.scrapyard b/doc/README.scrapyard
index 6a1d2a5..b950a41 100644
--- a/doc/README.scrapyard
+++ b/doc/README.scrapyard
@@ -5,23 +5,25 @@
 more to resolve such problems, then the code is really dead and will
 be removed from the U-Boot source tree.  The remainders rest in piece
 in the imperishable depths of the git history.  This document tries to
-maintain a list of such former fellows, so archeologists can check
-easily if here is something they might want to dig for...
+maintain a list of such former fellows, so archaeologists can check
+easily if there is something they might want to dig for...
+The list should be sorted in reverse chronological order.
 
 
 Board            Arch        CPU            Commit      Removed     Last known maintainer/contact
 =================================================================================================
-spc1920          powerpc     mpc8xx         -           -
-v37              powerpc     mpc8xx         -           -
-fads             powerpc     mpc8xx         -           -
-netphone         powerpc     mpc8xx         -           -
-netta2           powerpc     mpc8xx         -           -
-netta            powerpc     mpc8xx         -           -
-rbc823           powerpc     mpc8xx         -           -
-quantum          powerpc     mpc8xx         -           -
-RPXlite_dw       powerpc     mpc8xx         -           -
-qs850            powerpc     mpc8xx         -           -
-qs860t           powerpc     mpc8xx         -           -
+p1023rds         powerpc     mpc85xx        d0bc5140    2014-07-22  Roy Zang <tie-fei.zang@freescale.com>
+spc1920          powerpc     mpc8xx         98ad54be    2014-07-07
+v37              powerpc     mpc8xx         b8c1438a    2014-07-07
+fads             powerpc     mpc8xx         03f9d7d1    2014-07-07
+netphone         powerpc     mpc8xx         c51c1c9a    2014-07-07
+netta2           powerpc     mpc8xx         c51c1c9a    2014-07-07
+netta            powerpc     mpc8xx         c51c1c9a    2014-07-07
+rbc823           powerpc     mpc8xx         c750b9c0    2014-07-07
+quantum          powerpc     mpc8xx         0657e46e    2014-07-07
+RPXlite_dw       powerpc     mpc8xx         0657e46e    2014-07-07
+qs850            powerpc     mpc8xx         dab0f762    2014-07-07
+qs860t           powerpc     mpc8xx         dab0f762    2014-07-07
 simpc8313        powerpc     mpc83xx        7445207f    2014-06-05  Ron Madrid <info@sheldoninst.com>
 hidden_dragon    powerpc     mpc824x        3fe1a854    2014-05-30  Yusdi Santoso <yusdi_santoso@adaptec.com>
 debris           powerpc     mpc824x        7edb1f7b    2014-05-30  Sangmoon Kim <dogoil@etinsys.com>
@@ -33,6 +35,7 @@
 mpc8260ads       powerpc     mpc8260        facb6725    2014-05-30  Yuli Barcohen <yuli@arabellasw.com>
 adder            powerpc     mpc8xx         373a9788    2014-05-30  Yuli Barcohen <yuli@arabellasw.com>
 quad100hd        powerpc     ppc405ep       3569571d    2014-05-30  Gary Jennejohn <gljennjohn@googlemail.com>
+incaip           mips        mips32         538cf92c    2014-04-20  Wolfgang Denk <wd@denx.de>
 lubbock          arm         pxa            36bf57b     2014-04-18  Kyle Harris <kharris@nexus-tech.net>
 EVB64260	 powerpc     mpc824x        bb3aef9	2014-04-18
 MOUSSE           powerpc     mpc824x        03f2ecc     2014-04-18
@@ -149,4 +152,3 @@
 adsvix           ARM         PXA27x         7610db1     2008-07-30  Adrian Filipi <adrian.filipi@eurotech.com>
 R5200            ColdFire    -              48ead7a     2008-03-31  Zachary P. Landau <zachary.landau@labxtechnologies.com>
 CPCI440          powerpc     440GP          b568fd2     2007-12-27  Matthias Fuchs <matthias.fuchs@esd-electronics.com>
-incaip           mips        mips32         -           2014-04-17  Wolfgang Denk <wd@denx.de>
diff --git a/doc/git-mailrc b/doc/git-mailrc
index 0985791..70405f2 100644
--- a/doc/git-mailrc
+++ b/doc/git-mailrc
@@ -106,10 +106,11 @@
 alias x86            uboot, sjg, gruss
 
 # Subsystem aliases
+alias dm             uboot, sjg
 alias cfi            uboot, stroese
 alias dfu            uboot, lukma
 alias kerneldoc      uboot, marex
-alias fdt            uboot, Jerry Van Baren <vanbaren@cideas.com>
+alias fdt            uboot, sjg
 alias i2c            uboot, hs
 alias kconfig        uboot, masahiro
 alias mmc            uboot, panto
diff --git a/doc/uImage.FIT/signature.txt b/doc/uImage.FIT/signature.txt
index a6ab543..b2f89fc 100644
--- a/doc/uImage.FIT/signature.txt
+++ b/doc/uImage.FIT/signature.txt
@@ -66,7 +66,8 @@
 -----------------------------------
 To create a new public key, size 2048 bits:
 
-$ openssl genrsa -F4 -out keys/dev.key 2048
+$ openssl genpkey -algorithm RSA -out keys/dev.key \
+    -pkeyopt rsa_keygen_bits:2048 -pkeyopt rsa_keygen_pubexp:65537
 
 To create a certificate for this:
 
@@ -159,6 +160,7 @@
 
 - rsa,num-bits: Number of key bits (e.g. 2048)
 - rsa,modulus: Modulus (N) as a big-endian multi-word integer
+- rsa,exponent: Public exponent (E) as a 64 bit unsigned integer
 - rsa,r-squared: (2^num-bits)^2 as a big-endian multi-word integer
 - rsa,n0-inverse: -1 / modulus[0] mod 2^32
 
diff --git a/drivers/dfu/Makefile b/drivers/dfu/Makefile
index def628d..5cc535e 100644
--- a/drivers/dfu/Makefile
+++ b/drivers/dfu/Makefile
@@ -9,3 +9,4 @@
 obj-$(CONFIG_DFU_MMC) += dfu_mmc.o
 obj-$(CONFIG_DFU_NAND) += dfu_nand.o
 obj-$(CONFIG_DFU_RAM) += dfu_ram.o
+obj-$(CONFIG_DFU_SF) += dfu_sf.o
diff --git a/drivers/dfu/dfu.c b/drivers/dfu/dfu.c
index dc09ff6..3512b14 100644
--- a/drivers/dfu/dfu.c
+++ b/drivers/dfu/dfu.c
@@ -44,7 +44,7 @@
 	return ++i;
 }
 
-int dfu_init_env_entities(char *interface, int dev)
+int dfu_init_env_entities(char *interface, char *devstr)
 {
 	const char *str_env;
 	char *env_bkp;
@@ -57,7 +57,7 @@
 	}
 
 	env_bkp = strdup(str_env);
-	ret = dfu_config_entities(env_bkp, interface, dev);
+	ret = dfu_config_entities(env_bkp, interface, devstr);
 	if (ret) {
 		error("DFU entities configuration failed!\n");
 		return ret;
@@ -82,7 +82,7 @@
 	return dfu_buf_size;
 }
 
-unsigned char *dfu_get_buf(void)
+unsigned char *dfu_get_buf(struct dfu_entity *dfu)
 {
 	char *s;
 
@@ -92,6 +92,8 @@
 	s = getenv("dfu_bufsiz");
 	dfu_buf_size = s ? (unsigned long)simple_strtol(s, NULL, 16) :
 			CONFIG_SYS_DFU_DATA_BUF_SIZE;
+	if (dfu->max_buf_size && dfu_buf_size > dfu->max_buf_size)
+		dfu_buf_size = dfu->max_buf_size;
 
 	dfu_buf = memalign(CONFIG_SYS_CACHELINE_SIZE, dfu_buf_size);
 	if (dfu_buf == NULL)
@@ -147,6 +149,19 @@
 	return ret;
 }
 
+void dfu_write_transaction_cleanup(struct dfu_entity *dfu)
+{
+	/* clear everything */
+	dfu_free_buf();
+	dfu->crc = 0;
+	dfu->offset = 0;
+	dfu->i_blk_seq_num = 0;
+	dfu->i_buf_start = dfu_buf;
+	dfu->i_buf_end = dfu_buf;
+	dfu->i_buf = dfu->i_buf_start;
+	dfu->inited = 0;
+}
+
 int dfu_flush(struct dfu_entity *dfu, void *buf, int size, int blk_seq_num)
 {
 	int ret = 0;
@@ -162,23 +177,14 @@
 		printf("\nDFU complete %s: 0x%08x\n", dfu_hash_algo->name,
 		       dfu->crc);
 
-	/* clear everything */
-	dfu_free_buf();
-	dfu->crc = 0;
-	dfu->offset = 0;
-	dfu->i_blk_seq_num = 0;
-	dfu->i_buf_start = dfu_buf;
-	dfu->i_buf_end = dfu_buf;
-	dfu->i_buf = dfu->i_buf_start;
-	dfu->inited = 0;
+	dfu_write_transaction_cleanup(dfu);
 
 	return ret;
 }
 
 int dfu_write(struct dfu_entity *dfu, void *buf, int size, int blk_seq_num)
 {
-	int ret = 0;
-	int tret;
+	int ret;
 
 	debug("%s: name: %s buf: 0x%p size: 0x%x p_num: 0x%x offset: 0x%llx bufoffset: 0x%x\n",
 	      __func__, dfu->name, buf, size, blk_seq_num, dfu->offset,
@@ -190,10 +196,10 @@
 		dfu->offset = 0;
 		dfu->bad_skip = 0;
 		dfu->i_blk_seq_num = 0;
-		dfu->i_buf_start = dfu_get_buf();
+		dfu->i_buf_start = dfu_get_buf(dfu);
 		if (dfu->i_buf_start == NULL)
 			return -ENOMEM;
-		dfu->i_buf_end = dfu_get_buf() + dfu_buf_size;
+		dfu->i_buf_end = dfu_get_buf(dfu) + dfu_buf_size;
 		dfu->i_buf = dfu->i_buf_start;
 
 		dfu->inited = 1;
@@ -202,6 +208,7 @@
 	if (dfu->i_blk_seq_num != blk_seq_num) {
 		printf("%s: Wrong sequence number! [%d] [%d]\n",
 		       __func__, dfu->i_blk_seq_num, blk_seq_num);
+		dfu_write_transaction_cleanup(dfu);
 		return -1;
 	}
 
@@ -223,15 +230,18 @@
 
 	/* flush buffer if overflow */
 	if ((dfu->i_buf + size) > dfu->i_buf_end) {
-		tret = dfu_write_buffer_drain(dfu);
-		if (ret == 0)
-			ret = tret;
+		ret = dfu_write_buffer_drain(dfu);
+		if (ret) {
+			dfu_write_transaction_cleanup(dfu);
+			return ret;
+		}
 	}
 
 	/* we should be in buffer now (if not then size too large) */
 	if ((dfu->i_buf + size) > dfu->i_buf_end) {
 		error("Buffer overflow! (0x%p + 0x%x > 0x%p)\n", dfu->i_buf,
 		      size, dfu->i_buf_end);
+		dfu_write_transaction_cleanup(dfu);
 		return -1;
 	}
 
@@ -240,12 +250,14 @@
 
 	/* if end or if buffer full flush */
 	if (size == 0 || (dfu->i_buf + size) > dfu->i_buf_end) {
-		tret = dfu_write_buffer_drain(dfu);
-		if (ret == 0)
-			ret = tret;
+		ret = dfu_write_buffer_drain(dfu);
+		if (ret) {
+			dfu_write_transaction_cleanup(dfu);
+			return ret;
+		}
 	}
 
-	return ret;
+	return 0;
 }
 
 static int dfu_read_buffer_fill(struct dfu_entity *dfu, void *buf, int size)
@@ -267,7 +279,6 @@
 
 			dfu->i_buf += chunk;
 			dfu->b_left -= chunk;
-			dfu->r_left -= chunk;
 			size -= chunk;
 			buf += chunk;
 			readn += chunk;
@@ -309,14 +320,23 @@
 	       __func__, dfu->name, buf, size, blk_seq_num, dfu->i_buf);
 
 	if (!dfu->inited) {
-		dfu->i_buf_start = dfu_get_buf();
+		dfu->i_buf_start = dfu_get_buf(dfu);
 		if (dfu->i_buf_start == NULL)
 			return -ENOMEM;
 
-		ret = dfu->read_medium(dfu, 0, dfu->i_buf_start, &dfu->r_left);
-		if (ret != 0) {
-			debug("%s: failed to get r_left\n", __func__);
-			return ret;
+		dfu->r_left = dfu->get_medium_size(dfu);
+		if (dfu->r_left < 0)
+			return dfu->r_left;
+		switch (dfu->layout) {
+		case DFU_RAW_ADDR:
+		case DFU_RAM_ADDR:
+			break;
+		default:
+			if (dfu->r_left > dfu_buf_size) {
+				printf("%s: File too big for buffer\n",
+				       __func__);
+				return -EOVERFLOW;
+			}
 		}
 
 		debug("%s: %s %ld [B]\n", __func__, dfu->name, dfu->r_left);
@@ -324,9 +344,9 @@
 		dfu->i_blk_seq_num = 0;
 		dfu->crc = 0;
 		dfu->offset = 0;
-		dfu->i_buf_end = dfu_get_buf() + dfu_buf_size;
+		dfu->i_buf_end = dfu_get_buf(dfu) + dfu_buf_size;
 		dfu->i_buf = dfu->i_buf_start;
-		dfu->b_left = min(dfu_buf_size, dfu->r_left);
+		dfu->b_left = 0;
 
 		dfu->bad_skip = 0;
 
@@ -371,26 +391,30 @@
 }
 
 static int dfu_fill_entity(struct dfu_entity *dfu, char *s, int alt,
-			   char *interface, int num)
+			   char *interface, char *devstr)
 {
 	char *st;
 
-	debug("%s: %s interface: %s num: %d\n", __func__, s, interface, num);
+	debug("%s: %s interface: %s dev: %s\n", __func__, s, interface, devstr);
 	st = strsep(&s, " ");
 	strcpy(dfu->name, st);
 
-	dfu->dev_num = num;
 	dfu->alt = alt;
+	dfu->max_buf_size = 0;
+	dfu->free_entity = NULL;
 
 	/* Specific for mmc device */
 	if (strcmp(interface, "mmc") == 0) {
-		if (dfu_fill_entity_mmc(dfu, s))
+		if (dfu_fill_entity_mmc(dfu, devstr, s))
 			return -1;
 	} else if (strcmp(interface, "nand") == 0) {
-		if (dfu_fill_entity_nand(dfu, s))
+		if (dfu_fill_entity_nand(dfu, devstr, s))
 			return -1;
 	} else if (strcmp(interface, "ram") == 0) {
-		if (dfu_fill_entity_ram(dfu, s))
+		if (dfu_fill_entity_ram(dfu, devstr, s))
+			return -1;
+	} else if (strcmp(interface, "sf") == 0) {
+		if (dfu_fill_entity_sf(dfu, devstr, s))
 			return -1;
 	} else {
 		printf("%s: Device %s not (yet) supported!\n",
@@ -407,6 +431,8 @@
 
 	list_for_each_entry_safe_reverse(dfu, p, &dfu_list, list) {
 		list_del(&dfu->list);
+		if (dfu->free_entity)
+			dfu->free_entity(dfu);
 		t = dfu;
 	}
 	if (t)
@@ -416,7 +442,7 @@
 	alt_num_cnt = 0;
 }
 
-int dfu_config_entities(char *env, char *interface, int num)
+int dfu_config_entities(char *env, char *interface, char *devstr)
 {
 	struct dfu_entity *dfu;
 	int i, ret;
@@ -439,7 +465,8 @@
 	for (i = 0; i < dfu_alt_num; i++) {
 
 		s = strsep(&env, ";");
-		ret = dfu_fill_entity(&dfu[i], s, alt_num_cnt, interface, num);
+		ret = dfu_fill_entity(&dfu[i], s, alt_num_cnt, interface,
+				      devstr);
 		if (ret)
 			return -1;
 
diff --git a/drivers/dfu/dfu_mmc.c b/drivers/dfu/dfu_mmc.c
index 63cc876..72fa03e 100644
--- a/drivers/dfu/dfu_mmc.c
+++ b/drivers/dfu/dfu_mmc.c
@@ -12,6 +12,8 @@
 #include <errno.h>
 #include <div64.h>
 #include <dfu.h>
+#include <ext4fs.h>
+#include <fat.h>
 #include <mmc.h>
 
 static unsigned char __aligned(CONFIG_SYS_CACHELINE_SIZE)
@@ -25,7 +27,7 @@
 	if (part == mmc->part_num)
 		return 0;
 
-	ret = mmc_switch_part(dfu->dev_num, part);
+	ret = mmc_switch_part(dfu->data.mmc.dev_num, part);
 	if (ret) {
 		error("Cannot switch to partition %d\n", part);
 		return ret;
@@ -38,7 +40,7 @@
 static int mmc_block_op(enum dfu_op op, struct dfu_entity *dfu,
 			u64 offset, void *buf, long *len)
 {
-	struct mmc *mmc = find_mmc_device(dfu->dev_num);
+	struct mmc *mmc = find_mmc_device(dfu->data.mmc.dev_num);
 	u32 blk_start, blk_count, n = 0;
 	int ret, part_num_bkp = 0;
 
@@ -65,15 +67,15 @@
 	}
 
 	debug("%s: %s dev: %d start: %d cnt: %d buf: 0x%p\n", __func__,
-	      op == DFU_OP_READ ? "MMC READ" : "MMC WRITE", dfu->dev_num,
-	      blk_start, blk_count, buf);
+	      op == DFU_OP_READ ? "MMC READ" : "MMC WRITE",
+	      dfu->data.mmc.dev_num, blk_start, blk_count, buf);
 	switch (op) {
 	case DFU_OP_READ:
-		n = mmc->block_dev.block_read(dfu->dev_num, blk_start,
+		n = mmc->block_dev.block_read(dfu->data.mmc.dev_num, blk_start,
 					      blk_count, buf);
 		break;
 	case DFU_OP_WRITE:
-		n = mmc->block_dev.block_write(dfu->dev_num, blk_start,
+		n = mmc->block_dev.block_write(dfu->data.mmc.dev_num, blk_start,
 					       blk_count, buf);
 		break;
 	default:
@@ -113,22 +115,17 @@
 static int mmc_file_op(enum dfu_op op, struct dfu_entity *dfu,
 			void *buf, long *len)
 {
+	const char *fsname, *opname;
 	char cmd_buf[DFU_CMD_BUF_SIZE];
 	char *str_env;
 	int ret;
 
 	switch (dfu->layout) {
 	case DFU_FS_FAT:
-		sprintf(cmd_buf, "fat%s mmc %d:%d 0x%x %s",
-			op == DFU_OP_READ ? "load" : "write",
-			dfu->data.mmc.dev, dfu->data.mmc.part,
-			(unsigned int) buf, dfu->name);
+		fsname = "fat";
 		break;
 	case DFU_FS_EXT4:
-		sprintf(cmd_buf, "ext4%s mmc %d:%d 0x%x /%s",
-			op == DFU_OP_READ ? "load" : "write",
-			dfu->data.mmc.dev, dfu->data.mmc.part,
-			(unsigned int) buf, dfu->name);
+		fsname = "ext4";
 		break;
 	default:
 		printf("%s: Layout (%s) not (yet) supported!\n", __func__,
@@ -136,6 +133,28 @@
 		return -1;
 	}
 
+	switch (op) {
+	case DFU_OP_READ:
+		opname = "load";
+		break;
+	case DFU_OP_WRITE:
+		opname = "write";
+		break;
+	case DFU_OP_SIZE:
+		opname = "size";
+		break;
+	default:
+		return -1;
+	}
+
+	sprintf(cmd_buf, "%s%s mmc %d:%d", fsname, opname,
+		dfu->data.mmc.dev, dfu->data.mmc.part);
+
+	if (op != DFU_OP_SIZE)
+		sprintf(cmd_buf + strlen(cmd_buf), " 0x%x", (unsigned int)buf);
+
+	sprintf(cmd_buf + strlen(cmd_buf), " %s", dfu->name);
+
 	if (op == DFU_OP_WRITE)
 		sprintf(cmd_buf + strlen(cmd_buf), " %lx", *len);
 
@@ -147,7 +166,7 @@
 		return ret;
 	}
 
-	if (dfu->layout != DFU_RAW_ADDR && op == DFU_OP_READ) {
+	if (op != DFU_OP_WRITE) {
 		str_env = getenv("filesize");
 		if (str_env == NULL) {
 			puts("dfu: Wrong file size!\n");
@@ -196,6 +215,27 @@
 	return ret;
 }
 
+long dfu_get_medium_size_mmc(struct dfu_entity *dfu)
+{
+	int ret;
+	long len;
+
+	switch (dfu->layout) {
+	case DFU_RAW_ADDR:
+		return dfu->data.mmc.lba_size * dfu->data.mmc.lba_blk_size;
+	case DFU_FS_FAT:
+	case DFU_FS_EXT4:
+		ret = mmc_file_op(DFU_OP_SIZE, dfu, NULL, &len);
+		if (ret < 0)
+			return ret;
+		return len;
+	default:
+		printf("%s: Layout (%s) not (yet) supported!\n", __func__,
+		       dfu_get_layout(dfu->layout));
+		return -1;
+	}
+}
+
 int dfu_read_medium_mmc(struct dfu_entity *dfu, u64 offset, void *buf,
 		long *len)
 {
@@ -230,7 +270,7 @@
  *	4th (optional):
  *		mmcpart <num> (access to HW eMMC partitions)
  */
-int dfu_fill_entity_mmc(struct dfu_entity *dfu, char *s)
+int dfu_fill_entity_mmc(struct dfu_entity *dfu, char *devstr, char *s)
 {
 	const char *entity_type;
 	size_t second_arg;
@@ -241,6 +281,8 @@
 	const char *argv[3];
 	const char **parg = argv;
 
+	dfu->data.mmc.dev_num = simple_strtoul(devstr, NULL, 10);
+
 	for (; parg < argv + sizeof(argv) / sizeof(*argv); ++parg) {
 		*parg = strsep(&s, " ");
 		if (*parg == NULL) {
@@ -257,9 +299,10 @@
 	second_arg = simple_strtoul(argv[1], NULL, 0);
 	third_arg = simple_strtoul(argv[2], NULL, 0);
 
-	mmc = find_mmc_device(dfu->dev_num);
+	mmc = find_mmc_device(dfu->data.mmc.dev_num);
 	if (mmc == NULL) {
-		error("Couldn't find MMC device no. %d.\n", dfu->dev_num);
+		error("Couldn't find MMC device no. %d.\n",
+		      dfu->data.mmc.dev_num);
 		return -ENODEV;
 	}
 
@@ -316,6 +359,7 @@
 	}
 
 	dfu->dev_type = DFU_DEV_MMC;
+	dfu->get_medium_size = dfu_get_medium_size_mmc;
 	dfu->read_medium = dfu_read_medium_mmc;
 	dfu->write_medium = dfu_write_medium_mmc;
 	dfu->flush_medium = dfu_flush_medium_mmc;
diff --git a/drivers/dfu/dfu_nand.c b/drivers/dfu/dfu_nand.c
index ccdbef6..f9ee189 100644
--- a/drivers/dfu/dfu_nand.c
+++ b/drivers/dfu/dfu_nand.c
@@ -114,6 +114,11 @@
 	return ret;
 }
 
+long dfu_get_medium_size_nand(struct dfu_entity *dfu)
+{
+	return dfu->data.nand.size;
+}
+
 static int dfu_read_medium_nand(struct dfu_entity *dfu, u64 offset, void *buf,
 		long *len)
 {
@@ -121,7 +126,6 @@
 
 	switch (dfu->layout) {
 	case DFU_RAW_ADDR:
-		*len = dfu->data.nand.size;
 		ret = nand_block_read(dfu, offset, buf, len);
 		break;
 	default:
@@ -175,7 +179,7 @@
 	return DFU_DEFAULT_POLL_TIMEOUT;
 }
 
-int dfu_fill_entity_nand(struct dfu_entity *dfu, char *s)
+int dfu_fill_entity_nand(struct dfu_entity *dfu, char *devstr, char *s)
 {
 	char *st;
 	int ret, dev, part;
@@ -220,6 +224,7 @@
 		return -1;
 	}
 
+	dfu->get_medium_size = dfu_get_medium_size_nand;
 	dfu->read_medium = dfu_read_medium_nand;
 	dfu->write_medium = dfu_write_medium_nand;
 	dfu->flush_medium = dfu_flush_medium_nand;
diff --git a/drivers/dfu/dfu_ram.c b/drivers/dfu/dfu_ram.c
index 335a8e1..e094a94 100644
--- a/drivers/dfu/dfu_ram.c
+++ b/drivers/dfu/dfu_ram.c
@@ -41,18 +41,18 @@
 	return dfu_transfer_medium_ram(DFU_OP_WRITE, dfu, offset, buf, len);
 }
 
+long dfu_get_medium_size_ram(struct dfu_entity *dfu)
+{
+	return dfu->data.ram.size;
+}
+
 static int dfu_read_medium_ram(struct dfu_entity *dfu, u64 offset,
 			       void *buf, long *len)
 {
-	if (!*len) {
-		*len = dfu->data.ram.size;
-		return 0;
-	}
-
 	return dfu_transfer_medium_ram(DFU_OP_READ, dfu, offset, buf, len);
 }
 
-int dfu_fill_entity_ram(struct dfu_entity *dfu, char *s)
+int dfu_fill_entity_ram(struct dfu_entity *dfu, char *devstr, char *s)
 {
 	char *st;
 
@@ -69,6 +69,7 @@
 	dfu->data.ram.size = simple_strtoul(s, &s, 16);
 
 	dfu->write_medium = dfu_write_medium_ram;
+	dfu->get_medium_size = dfu_get_medium_size_ram;
 	dfu->read_medium = dfu_read_medium_ram;
 
 	dfu->inited = 0;
diff --git a/drivers/dfu/dfu_sf.c b/drivers/dfu/dfu_sf.c
new file mode 100644
index 0000000..91f6df2
--- /dev/null
+++ b/drivers/dfu/dfu_sf.c
@@ -0,0 +1,139 @@
+/*
+ * Copyright (c) 2014, NVIDIA CORPORATION. All rights reserved.
+ *
+ * SPDX-License-Identifier: GPL-2.0+
+ */
+
+#include <common.h>
+#include <malloc.h>
+#include <errno.h>
+#include <div64.h>
+#include <dfu.h>
+#include <spi_flash.h>
+
+static long dfu_get_medium_size_sf(struct dfu_entity *dfu)
+{
+	return dfu->data.sf.size;
+}
+
+static int dfu_read_medium_sf(struct dfu_entity *dfu, u64 offset, void *buf,
+		long *len)
+{
+	return spi_flash_read(dfu->data.sf.dev, offset, *len, buf);
+}
+
+static int dfu_write_medium_sf(struct dfu_entity *dfu,
+		u64 offset, void *buf, long *len)
+{
+	int ret;
+
+	ret = spi_flash_erase(dfu->data.sf.dev, offset, *len);
+	if (ret)
+		return ret;
+
+	ret = spi_flash_write(dfu->data.sf.dev, offset, *len, buf);
+	if (ret)
+		return ret;
+
+	return 0;
+}
+
+static int dfu_flush_medium_sf(struct dfu_entity *dfu)
+{
+	return 0;
+}
+
+static unsigned int dfu_polltimeout_sf(struct dfu_entity *dfu)
+{
+	return DFU_DEFAULT_POLL_TIMEOUT;
+}
+
+static void dfu_free_entity_sf(struct dfu_entity *dfu)
+{
+	spi_flash_free(dfu->data.sf.dev);
+}
+
+static struct spi_flash *parse_dev(char *devstr)
+{
+	unsigned int bus;
+	unsigned int cs;
+	unsigned int speed = CONFIG_SF_DEFAULT_SPEED;
+	unsigned int mode = CONFIG_SF_DEFAULT_MODE;
+	char *s, *endp;
+	struct spi_flash *dev;
+
+	s = strsep(&devstr, ":");
+	if (!s || !*s || (bus = simple_strtoul(s, &endp, 0), *endp)) {
+		printf("Invalid SPI bus %s\n", s);
+		return NULL;
+	}
+
+	s = strsep(&devstr, ":");
+	if (!s || !*s || (cs = simple_strtoul(s, &endp, 0), *endp)) {
+		printf("Invalid SPI chip-select %s\n", s);
+		return NULL;
+	}
+
+	s = strsep(&devstr, ":");
+	if (s && *s) {
+		speed = simple_strtoul(s, &endp, 0);
+		if (*endp || !speed) {
+			printf("Invalid SPI speed %s\n", s);
+			return NULL;
+		}
+	}
+
+	s = strsep(&devstr, ":");
+	if (s && *s) {
+		mode = simple_strtoul(s, &endp, 0);
+		if (*endp || mode > 3) {
+			printf("Invalid SPI mode %s\n", s);
+			return NULL;
+		}
+	}
+
+	dev = spi_flash_probe(bus, cs, speed, mode);
+	if (!dev) {
+		printf("Failed to create SPI flash at %d:%d:%d:%d\n",
+		       bus, cs, speed, mode);
+		return NULL;
+	}
+
+	return dev;
+}
+
+int dfu_fill_entity_sf(struct dfu_entity *dfu, char *devstr, char *s)
+{
+	char *st;
+
+	dfu->data.sf.dev = parse_dev(devstr);
+	if (!dfu->data.sf.dev)
+		return -ENODEV;
+
+	dfu->dev_type = DFU_DEV_SF;
+	dfu->max_buf_size = dfu->data.sf.dev->sector_size;
+
+	st = strsep(&s, " ");
+	if (!strcmp(st, "raw")) {
+		dfu->layout = DFU_RAW_ADDR;
+		dfu->data.sf.start = simple_strtoul(s, &s, 16);
+		s++;
+		dfu->data.sf.size = simple_strtoul(s, &s, 16);
+	} else {
+		printf("%s: Memory layout (%s) not supported!\n", __func__, st);
+		spi_flash_free(dfu->data.sf.dev);
+		return -1;
+	}
+
+	dfu->get_medium_size = dfu_get_medium_size_sf;
+	dfu->read_medium = dfu_read_medium_sf;
+	dfu->write_medium = dfu_write_medium_sf;
+	dfu->flush_medium = dfu_flush_medium_sf;
+	dfu->poll_timeout = dfu_polltimeout_sf;
+	dfu->free_entity = dfu_free_entity_sf;
+
+	/* initial state */
+	dfu->inited = 0;
+
+	return 0;
+}
diff --git a/drivers/dma/Makefile b/drivers/dma/Makefile
index 8b2821b..a79c391 100644
--- a/drivers/dma/Makefile
+++ b/drivers/dma/Makefile
@@ -8,4 +8,3 @@
 obj-$(CONFIG_FSLDMAFEC) += MCD_tasksInit.o MCD_dmaApi.o MCD_tasks.o
 obj-$(CONFIG_APBH_DMA) += apbh_dma.o
 obj-$(CONFIG_FSL_DMA) += fsl_dma.o
-obj-$(CONFIG_OMAP3_DMA) += omap3_dma.o
diff --git a/drivers/dma/omap3_dma.c b/drivers/dma/omap3_dma.c
deleted file mode 100644
index 3320b3d..0000000
--- a/drivers/dma/omap3_dma.c
+++ /dev/null
@@ -1,167 +0,0 @@
-/* Copyright (C) 2011
- * Corscience GmbH & Co. KG - Simon Schwarz <schwarz@corscience.de>
- *
- * SPDX-License-Identifier:	GPL-2.0+
- */
-
-/* This is a basic implementation of the SDMA/DMA4 controller of OMAP3
- * Tested on Silicon Revision major:0x4 minor:0x0
- */
-
-#include <common.h>
-#include <asm/arch/cpu.h>
-#include <asm/arch/omap3.h>
-#include <asm/arch/dma.h>
-#include <asm/io.h>
-#include <asm/errno.h>
-
-static struct dma4 *dma4_cfg = (struct dma4 *)OMAP34XX_DMA4_BASE;
-uint32_t dma_active; /* if a transfer is started the respective
-	bit is set for the logical channel */
-
-/* Check if we have the given channel
- * PARAMETERS:
- * chan: Channel number
- *
- * RETURN of non-zero means error */
-static inline int check_channel(uint32_t chan)
-{
-	if (chan < CHAN_NR_MIN || chan > CHAN_NR_MAX)
-		return -EINVAL;
-	return 0;
-}
-
-static inline void reset_irq(uint32_t chan)
-{
-	/* reset IRQ reason */
-	writel(0x1DFE, &dma4_cfg->chan[chan].csr);
-	/* reset IRQ */
-	writel((1 << chan), &dma4_cfg->irqstatus_l[0]);
-	dma_active &= ~(1 << chan);
-}
-
-/* Set Source, Destination and Size of DMA transfer for the
- * specified channel.
- * PARAMETERS:
- * chan: channel to use
- * src: source of the transfer
- * dst: destination of the transfer
- * sze: Size of the transfer
- *
- * RETURN of non-zero means error */
-int omap3_dma_conf_transfer(uint32_t chan, uint32_t *src, uint32_t *dst,
-		uint32_t sze)
-{
-	if (check_channel(chan))
-		return -EINVAL;
-	/* CDSA0 */
-	writel((uint32_t)src, &dma4_cfg->chan[chan].cssa);
-	writel((uint32_t)dst, &dma4_cfg->chan[chan].cdsa);
-	writel(sze, &dma4_cfg->chan[chan].cen);
-return 0;
-}
-
-/* Start the DMA transfer */
-int omap3_dma_start_transfer(uint32_t chan)
-{
-	uint32_t val;
-
-	if (check_channel(chan))
-		return -EINVAL;
-
-	val = readl(&dma4_cfg->chan[chan].ccr);
-	/* Test for channel already in use */
-	if (val & CCR_ENABLE_ENABLE)
-		return -EBUSY;
-
-	writel((val | CCR_ENABLE_ENABLE), &dma4_cfg->chan[chan].ccr);
-	dma_active |= (1 << chan);
-	debug("started transfer...\n");
-	return 0;
-}
-
-/* Busy-waiting for a DMA transfer
- * This has to be called before another transfer is started
- * PARAMETER
- * chan: Channel to wait for
- *
- * RETURN of non-zero means error*/
-int omap3_dma_wait_for_transfer(uint32_t chan)
-{
-	uint32_t val;
-
-	if (!(dma_active & (1 << chan))) {
-		val = readl(&dma4_cfg->irqstatus_l[0]);
-		if (!(val & chan)) {
-			debug("dma: The channel you are trying to wait for "
-				"was never activated - ERROR\n");
-			return -1; /* channel was never active */
-		}
-	}
-
-	/* all irqs on line 0 */
-	while (!(readl(&dma4_cfg->irqstatus_l[0]) & (1 << chan)))
-		asm("nop");
-
-	val = readl(&dma4_cfg->chan[chan].csr);
-	if ((val & CSR_TRANS_ERR) | (val & CSR_SUPERVISOR_ERR) |
-			(val & CSR_MISALIGNED_ADRS_ERR)) {
-		debug("err code: %X\n", val);
-		debug("dma: transfer error detected\n");
-		reset_irq(chan);
-		return -1;
-	}
-	reset_irq(chan);
-	return 0;
-}
-
-/* Get the revision of the DMA module
- * PARAMETER
- * minor: Address of minor revision to write
- * major: Address of major revision to write
- *
- * RETURN of non-zero means error
- */
-int omap3_dma_get_revision(uint32_t *minor, uint32_t *major)
-{
-	uint32_t val;
-
-	/* debug information */
-	val = readl(&dma4_cfg->revision);
-	*major = (val & 0x000000F0) >> 4;
-	*minor = (val & 0x0000000F);
-	debug("DMA Silicon revision (maj/min): 0x%X/0x%X\n", *major, *minor);
-	return 0;
-}
-
-/* Initial config of omap dma
- */
-void omap3_dma_init(void)
-{
-	dma_active = 0;
-	/* All interrupts on channel 0 */
-	writel(0xFFFFFFFF, &dma4_cfg->irqenable_l[0]);
-}
-
-/* set channel config to config
- *
- * RETURN of non-zero means error */
-int omap3_dma_conf_chan(uint32_t chan, struct dma4_chan *config)
-{
-	if (check_channel(chan))
-		return -EINVAL;
-
-	dma4_cfg->chan[chan] = *config;
-	return 0;
-}
-
-/* get channel config to config
- *
- * RETURN of non-zero means error */
-int omap3_dma_get_conf_chan(uint32_t chan, struct dma4_chan *config)
-{
-	if (check_channel(chan))
-		return -EINVAL;
-	*config = dma4_cfg->chan[chan];
-	return 0;
-}
diff --git a/drivers/net/phy/vitesse.c b/drivers/net/phy/vitesse.c
index c58fe50..2b29cd8 100644
--- a/drivers/net/phy/vitesse.c
+++ b/drivers/net/phy/vitesse.c
@@ -126,7 +126,6 @@
 	genphy_config_aneg(phydev);
 
 	if ((phydev->interface == PHY_INTERFACE_MODE_RGMII) ||
-			(phydev->interface == PHY_INTERFACE_MODE_RGMII) ||
 			(phydev->interface == PHY_INTERFACE_MODE_RGMII_TXID) ||
 			(phydev->interface == PHY_INTERFACE_MODE_RGMII_RXID))
 		phy_write(phydev, MDIO_DEVAD_NONE, MIIM_CIS8204_EPHY_CON,
diff --git a/drivers/serial/ns16550.c b/drivers/serial/ns16550.c
index 8e7052d..079f67d 100644
--- a/drivers/serial/ns16550.c
+++ b/drivers/serial/ns16550.c
@@ -81,7 +81,7 @@
 	serial_out(baud_divisor & 0xff, &com_port->dll);
 	serial_out((baud_divisor >> 8) & 0xff, &com_port->dlm);
 	serial_out(UART_LCRVAL, &com_port->lcr);
-#if (defined(CONFIG_OMAP) && !defined(CONFIG_OMAP3_ZOOM2)) || \
+#if defined(CONFIG_OMAP) || \
 	defined(CONFIG_AM33XX) || defined(CONFIG_SOC_DA8XX) || \
 	defined(CONFIG_TI81XX) || defined(CONFIG_AM43XX)
 
diff --git a/drivers/serial/serial_ns16550.c b/drivers/serial/serial_ns16550.c
index 4413e69..dafeed7 100644
--- a/drivers/serial/serial_ns16550.c
+++ b/drivers/serial/serial_ns16550.c
@@ -122,15 +122,6 @@
 {
 	const unsigned int mode_x_div = 16;
 
-#ifdef CONFIG_OMAP1510
-	/* If can't cleanly clock 115200 set div to 1 */
-	if ((CONFIG_SYS_NS16550_CLK == 12000000) && (gd->baudrate == 115200)) {
-		port->osc_12m_sel = OSC_12M_SEL;	/* enable 6.5 * divisor */
-		return (1);				/* return 1 for base divisor */
-	}
-	port->osc_12m_sel = 0;			/* clear if previsouly set */
-#endif
-
 	return DIV_ROUND_CLOSEST(CONFIG_SYS_NS16550_CLK,
 						mode_x_div * gd->baudrate);
 }
diff --git a/drivers/serial/serial_sh.c b/drivers/serial/serial_sh.c
index 0826d59..144a925 100644
--- a/drivers/serial/serial_sh.c
+++ b/drivers/serial/serial_sh.c
@@ -49,9 +49,15 @@
 static void sh_serial_setbrg(void)
 {
 	DECLARE_GLOBAL_DATA_PTR;
-
+#ifdef CONFIG_SCIF_USE_EXT_CLK
+	unsigned short dl = DL_VALUE(gd->baudrate, CONFIG_SH_SCIF_CLK_FREQ);
+	sci_out(&sh_sci, DL, dl);
+	/* Need wait: Clock * 1/dl $B!_(B 1/16 */
+	udelay((1000000 * dl * 16 / CONFIG_SYS_CLK_FREQ) * 1000 + 1);
+#else
 	sci_out(&sh_sci, SCBRR,
 		SCBRR_VALUE(gd->baudrate, CONFIG_SH_SCIF_CLK_FREQ));
+#endif
 }
 
 static int sh_serial_init(void)
diff --git a/drivers/serial/serial_sh.h b/drivers/serial/serial_sh.h
index 341997c..fe8cde4 100644
--- a/drivers/serial/serial_sh.h
+++ b/drivers/serial/serial_sh.h
@@ -588,7 +588,8 @@
 #else
 SCIF_FNS(SCSPTR,                        0,  0, 0x20, 16)
 #endif
-#if defined(CONFIG_R8A7790) || defined(CONFIG_R8A7791)
+#if defined(CONFIG_R8A7790) || defined(CONFIG_R8A7791) || \
+	defined(CONFIG_R8A7794)
 SCIF_FNS(DL,				0,  0, 0x30, 16)
 SCIF_FNS(CKS,				0,  0, 0x34, 16)
 #endif
@@ -734,8 +735,8 @@
 #elif defined(__H8300H__) || defined(__H8300S__)
 #define SCBRR_VALUE(bps, clk) (((clk*1000/32)/bps)-1)
 #elif defined(CONFIG_R8A7790) || defined(CONFIG_R8A7791)
-#define SCBRR DL
-#define SCBRR_VALUE(bps, clk) (clk / bps / 16)
+#define DL_VALUE(bps, clk) (clk / bps / 16) /* External Clock */
+#define SCBRR_VALUE(bps, clk) ((clk+16*bps)/(32*bps)-1) /* Internal Clock */
 #else /* Generic SH */
 #define SCBRR_VALUE(bps, clk) ((clk+16*bps)/(32*bps)-1)
 #endif
diff --git a/drivers/serial/usbtty.h b/drivers/serial/usbtty.h
index 21a3ef4..538b6d7 100644
--- a/drivers/serial/usbtty.h
+++ b/drivers/serial/usbtty.h
@@ -14,8 +14,6 @@
 #include <usbdevice.h>
 #if defined(CONFIG_PPC)
 #include <usb/mpc8xx_udc.h>
-#elif defined(CONFIG_OMAP1510)
-#include <usb/omap1510_udc.h>
 #elif defined(CONFIG_CPU_PXA27X)
 #include <usb/pxa27x_udc.h>
 #elif defined(CONFIG_DW_UDC)
diff --git a/drivers/usb/gadget/Makefile b/drivers/usb/gadget/Makefile
index 66becdc..4eea907 100644
--- a/drivers/usb/gadget/Makefile
+++ b/drivers/usb/gadget/Makefile
@@ -31,7 +31,6 @@
 obj-y += core.o
 obj-y += ep0.o
 obj-$(CONFIG_DW_UDC) += designware_udc.o
-obj-$(CONFIG_OMAP1510) += omap1510_udc.o
 obj-$(CONFIG_OMAP1610) += omap1510_udc.o
 obj-$(CONFIG_MPC885_FAMILY) += mpc8xx_udc.o
 obj-$(CONFIG_CPU_PXA27X) += pxa27x_udc.o
diff --git a/drivers/usb/gadget/f_dfu.c b/drivers/usb/gadget/f_dfu.c
index 859fe82..9863dec 100644
--- a/drivers/usb/gadget/f_dfu.c
+++ b/drivers/usb/gadget/f_dfu.c
@@ -162,17 +162,27 @@
 static void dnload_request_complete(struct usb_ep *ep, struct usb_request *req)
 {
 	struct f_dfu *f_dfu = req->context;
+	int ret;
 
-	dfu_write(dfu_get_entity(f_dfu->altsetting), req->buf,
-		  req->length, f_dfu->blk_seq_num);
+	ret = dfu_write(dfu_get_entity(f_dfu->altsetting), req->buf,
+			req->length, f_dfu->blk_seq_num);
+	if (ret) {
+		f_dfu->dfu_status = DFU_STATUS_errUNKNOWN;
+		f_dfu->dfu_state = DFU_STATE_dfuERROR;
+	}
 }
 
 static void dnload_request_flush(struct usb_ep *ep, struct usb_request *req)
 {
 	struct f_dfu *f_dfu = req->context;
+	int ret;
 
-	dfu_flush(dfu_get_entity(f_dfu->altsetting), req->buf,
-		  req->length, f_dfu->blk_seq_num);
+	ret = dfu_flush(dfu_get_entity(f_dfu->altsetting), req->buf,
+			req->length, f_dfu->blk_seq_num);
+	if (ret) {
+		f_dfu->dfu_status = DFU_STATUS_errUNKNOWN;
+		f_dfu->dfu_state = DFU_STATE_dfuERROR;
+	}
 }
 
 static inline int dfu_get_manifest_timeout(struct dfu_entity *dfu)
@@ -770,6 +780,8 @@
 	debug("%s: intf:%d alt:%d\n", __func__, intf, alt);
 
 	f_dfu->altsetting = alt;
+	f_dfu->dfu_state = DFU_STATE_dfuIDLE;
+	f_dfu->dfu_status = DFU_STATUS_OK;
 
 	return 0;
 }
diff --git a/drivers/usb/gadget/f_thor.c b/drivers/usb/gadget/f_thor.c
index 4e06273..c85b0fb 100644
--- a/drivers/usb/gadget/f_thor.c
+++ b/drivers/usb/gadget/f_thor.c
@@ -142,7 +142,8 @@
 				   int *cnt)
 {
 	long long int rcv_cnt = 0, left_to_rcv, ret_rcv;
-	void *transfer_buffer = dfu_get_buf();
+	struct dfu_entity *dfu_entity = dfu_get_entity(alt_setting_num);
+	void *transfer_buffer = dfu_get_buf(dfu_entity);
 	void *buf = transfer_buffer;
 	int usb_pkt_cnt = 0, ret;
 
@@ -205,7 +206,7 @@
 static int download_tail(long long int left, int cnt)
 {
 	struct dfu_entity *dfu_entity = dfu_get_entity(alt_setting_num);
-	void *transfer_buffer = dfu_get_buf();
+	void *transfer_buffer = dfu_get_buf(dfu_entity);
 	int ret;
 
 	debug("%s: left: %llu cnt: %d\n", __func__, left, cnt);
diff --git a/drivers/usb/gadget/omap1510_udc.c b/drivers/usb/gadget/omap1510_udc.c
index bdc1b88..959df8c 100644
--- a/drivers/usb/gadget/omap1510_udc.c
+++ b/drivers/usb/gadget/omap1510_udc.c
@@ -15,9 +15,6 @@
 
 #include <common.h>
 #include <asm/io.h>
-#ifdef CONFIG_OMAP_SX1
-#include <i2c.h>
-#endif
 #include <usbdevice.h>
 #include <usb/omap1510_udc.h>
 #include <usb/udc.h>
@@ -1097,20 +1094,6 @@
 	outw ((1 << 4) | (1 << 5), CLOCK_CTRL);
 	UDCREG (CLOCK_CTRL);
 
-#ifdef CONFIG_OMAP1510
-	/* This code was originally implemented for OMAP1510 and
-	 * therefore is only applicable for OMAP1510 boards. For
-	 * OMAP5912 or OMAP16xx the register APLL_CTRL does not
-	 * exist and DPLL_CTRL is already configured.
-	 */
-
-	/* Set and check APLL */
-	outw (0x0008, APLL_CTRL);
-	UDCREG (APLL_CTRL);
-	/* Set and check DPLL */
-	outw (0x2210, DPLL_CTRL);
-	UDCREG (DPLL_CTRL);
-#endif
 	/* Set and check SOFT
 	 * The below line of code has been changed to perform a
 	 * read-modify-write instead of a simple write for
@@ -1124,44 +1107,12 @@
 
 	/* Print banner with device revision */
 	udc_rev = inw (UDC_REV) & 0xff;
-#ifdef CONFIG_OMAP1510
-	printf ("USB:   TI OMAP1510 USB function module rev %d.%d\n",
-		udc_rev >> 4, udc_rev & 0xf);
-#endif
 
 #ifdef CONFIG_OMAP1610
 	printf ("USB:   TI OMAP5912 USB function module rev %d.%d\n",
 		udc_rev >> 4, udc_rev & 0xf);
 #endif
 
-#ifdef CONFIG_OMAP_SX1
-	i2c_read (0x32, 0x04, 1, &value, 1);
-	value |= 0x04;
-	i2c_write (0x32, 0x04, 1, &value, 1);
-
-	i2c_read (0x32, 0x03, 1, &value, 1);
-	value |= 0x01;
-	i2c_write (0x32, 0x03, 1, &value, 1);
-
-	gpio = inl(GPIO_PIN_CONTROL_REG);
-	gpio |=  0x0002; /* A_IRDA_OFF */
-	gpio |=  0x0800; /* A_SWITCH   */
-	gpio |=  0x8000; /* A_USB_ON   */
-	outl (gpio, GPIO_PIN_CONTROL_REG);
-
-	gpio = inl(GPIO_DIR_CONTROL_REG);
-	gpio &= ~0x0002; /* A_IRDA_OFF */
-	gpio &= ~0x0800; /* A_SWITCH   */
-	gpio &= ~0x8000; /* A_USB_ON   */
-	outl (gpio, GPIO_DIR_CONTROL_REG);
-
-	gpio = inl(GPIO_DATA_OUTPUT_REG);
-	gpio |=  0x0002; /* A_IRDA_OFF */
-	gpio &= ~0x0800; /* A_SWITCH   */
-	gpio &= ~0x8000; /* A_USB_ON   */
-	outl (gpio, GPIO_DATA_OUTPUT_REG);
-#endif
-
 	/* The VBUS_MODE bit selects whether VBUS detection is done via
 	 * software (1) or hardware (0).  When software detection is
 	 * selected, VBUS_CTRL selects whether USB is not connected (0)
diff --git a/drivers/usb/host/ehci-rmobile.c b/drivers/usb/host/ehci-rmobile.c
index 049e4c4..0d1a726 100644
--- a/drivers/usb/host/ehci-rmobile.c
+++ b/drivers/usb/host/ehci-rmobile.c
@@ -21,13 +21,16 @@
 	0xEE080000,	/* USB0 (EHCI) */
 	0xEE0A0000,	/* USB1 */
 	0xEE0C0000,	/* USB2 */
-	0xEE000000	/* USB3 (USB3.0 Host)*/
 };
 #elif defined(CONFIG_R8A7791)
 static u32 usb_base_address[CONFIG_USB_MAX_CONTROLLER_COUNT] = {
 	0xEE080000,	/* USB0 (EHCI) */
 	0xEE0C0000,	/* USB1 */
-	0xEE000000	/* USB3 (USB3.0 Host)*/
+};
+#elif defined(CONFIG_R8A7794)
+static u32 usb_base_address[CONFIG_USB_MAX_CONTROLLER_COUNT] = {
+	0xEE080000,	/* USB0 (EHCI) */
+	0xEE0C0000,	/* USB1 */
 };
 #else
 #error rmobile EHCI USB driver not supported on this platform
diff --git a/drivers/video/Makefile b/drivers/video/Makefile
index 945f35d..93a91c3 100644
--- a/drivers/video/Makefile
+++ b/drivers/video/Makefile
@@ -41,3 +41,4 @@
 obj-$(CONFIG_VIDEO_TEGRA) += tegra.o
 obj-$(CONFIG_VIDEO_VCXK) += bus_vcxk.o
 obj-$(CONFIG_FORMIKE) += formike.o
+obj-$(CONFIG_AM335X_LCD) += am335x-fb.o
diff --git a/drivers/video/am335x-fb.c b/drivers/video/am335x-fb.c
new file mode 100644
index 0000000..ab98941
--- /dev/null
+++ b/drivers/video/am335x-fb.c
@@ -0,0 +1,169 @@
+/*
+ * Copyright (C) 2013 Hannes Petermaier <oe5hpm@oevsv.at>
+ * Bernecker & Rainer Industrieelektronik GmbH - http://www.br-automation.com
+ *
+ * minimal framebuffer driver for TI's AM335x SoC to be compatible with
+ * Wolfgang Denk's LCD-Framework (CONFIG_LCD, common/lcd.c)
+ *
+ * - supporting only 24bit RGB/TFT raster Mode (not using palette)
+ * - sets up LCD controller as in 'am335x_lcdpanel' struct given
+ * - starts output DMA from gd->fb_base buffer
+ *
+ * SPDX-License-Identifier:	GPL-2.0+
+ */
+#include <common.h>
+#include <asm/arch/hardware.h>
+#include <lcd.h>
+#include "am335x-fb.h"
+
+#if !defined(LCD_CNTL_BASE)
+#error "hw-base address of LCD-Controller (LCD_CNTL_BASE) not defined!"
+#endif
+
+
+/* LCD Control Register */
+#define LCD_CLK_DIVISOR(x)			((x) << 8)
+#define LCD_RASTER_MODE				0x01
+/* LCD Clock Enable Register */
+#define LCD_CORECLKEN				(0x01 << 0)
+#define LCD_LIDDCLKEN				(0x01 << 1)
+#define LCD_DMACLKEN				(0x01 << 2)
+/* LCD DMA Control Register */
+#define LCD_DMA_BURST_SIZE(x)			((x) << 4)
+#define LCD_DMA_BURST_1				0x0
+#define LCD_DMA_BURST_2				0x1
+#define LCD_DMA_BURST_4				0x2
+#define LCD_DMA_BURST_8				0x3
+#define LCD_DMA_BURST_16			0x4
+/* LCD Timing_0 Register */
+#define LCD_HBPLSB(x)				((((x)-1) & 0xFF) << 24)
+#define LCD_HFPLSB(x)				((((x)-1) & 0xFF) << 16)
+#define LCD_HSWLSB(x)				((((x)-1) & 0x3F) << 10)
+#define LCD_HORLSB(x)				(((((x) >> 4)-1) & 0x3F) << 4)
+#define LCD_HORMSB(x)				(((((x) >> 4)-1) & 0x40) >> 4)
+/* LCD Timing_1 Register */
+#define LCD_VBP(x)				((x) << 24)
+#define LCD_VFP(x)				((x) << 16)
+#define LCD_VSW(x)				(((x)-1) << 10)
+#define LCD_VERLSB(x)				(((x)-1) & 0x3FF)
+/* LCD Timing_2 Register */
+#define LCD_HSWMSB(x)				((((x)-1) & 0x3C0) << 21)
+#define LCD_VERMSB(x)				((((x)-1) & 0x400) << 16)
+#define LCD_HBPMSB(x)				((((x)-1) & 0x300) >> 4)
+#define LCD_HFPMSB(x)				((((x)-1) & 0x300) >> 8)
+#define LCD_INVMASK(x)				((x) & 0x3F00000)
+/* LCD Raster Ctrl Register */
+#define LCD_TFT_24BPP_MODE			(1 << 25)
+#define LCD_TFT_24BPP_UNPACK			(1 << 26)
+#define LCD_PALMODE_RAWDATA			(0x10 << 20)
+#define LCD_TFT_MODE				(0x01 << 7)
+#define LCD_RASTER_ENABLE			(0x01 << 0)
+
+
+/* Macro definitions */
+#define FBSIZE(x)	((x->hactive * x->vactive * x->bpp) >> 3)
+
+struct am335x_lcdhw {
+	unsigned int		pid;			/* 0x00 */
+	unsigned int		ctrl;			/* 0x04 */
+	unsigned int		gap0;			/* 0x08 */
+	unsigned int		lidd_ctrl;		/* 0x0C */
+	unsigned int		lidd_cs0_conf;		/* 0x10 */
+	unsigned int		lidd_cs0_addr;		/* 0x14 */
+	unsigned int		lidd_cs0_data;		/* 0x18 */
+	unsigned int		lidd_cs1_conf;		/* 0x1C */
+	unsigned int		lidd_cs1_addr;		/* 0x20 */
+	unsigned int		lidd_cs1_data;		/* 0x24 */
+	unsigned int		raster_ctrl;		/* 0x28 */
+	unsigned int		raster_timing0;		/* 0x2C */
+	unsigned int		raster_timing1;		/* 0x30 */
+	unsigned int		raster_timing2;		/* 0x34 */
+	unsigned int		raster_subpanel;	/* 0x38 */
+	unsigned int		raster_subpanel2;	/* 0x3C */
+	unsigned int		lcddma_ctrl;		/* 0x40 */
+	unsigned int		lcddma_fb0_base;	/* 0x44 */
+	unsigned int		lcddma_fb0_ceiling;	/* 0x48 */
+	unsigned int		lcddma_fb1_base;	/* 0x4C */
+	unsigned int		lcddma_fb1_ceiling;	/* 0x50 */
+	unsigned int		sysconfig;		/* 0x54 */
+	unsigned int		irqstatus_raw;		/* 0x58 */
+	unsigned int		irqstatus;		/* 0x5C */
+	unsigned int		irqenable_set;		/* 0x60 */
+	unsigned int		irqenable_clear;	/* 0x64 */
+	unsigned int		gap1;			/* 0x68 */
+	unsigned int		clkc_enable;		/* 0x6C */
+	unsigned int		clkc_reset;		/* 0x70 */
+};
+
+static struct am335x_lcdhw *lcdhw = (void *)LCD_CNTL_BASE;
+DECLARE_GLOBAL_DATA_PTR;
+
+int lcd_get_size(int *line_length)
+{
+	*line_length = (panel_info.vl_col * NBITS(panel_info.vl_bpix)) / 8;
+	return *line_length * panel_info.vl_row + 0x20;
+}
+
+int am335xfb_init(struct am335x_lcdpanel *panel)
+{
+	if (0 == gd->fb_base) {
+		printf("ERROR: no valid fb_base stored in GLOBAL_DATA_PTR!\n");
+		return -1;
+	}
+	if (0 == panel) {
+		printf("ERROR: missing ptr to am335x_lcdpanel!\n");
+		return -1;
+	}
+
+	debug("setting up LCD-Controller for %dx%dx%d (hfp=%d,hbp=%d,hsw=%d / ",
+	      panel->hactive, panel->vactive, panel->bpp,
+	      panel->hfp, panel->hbp, panel->hsw);
+	debug("vfp=%d,vbp=%d,vsw=%d / clk-div=%d)\n",
+	      panel->vfp, panel->vfp, panel->vsw, panel->pxl_clk_div);
+	debug("using frambuffer at 0x%08x with size %d.\n",
+	      (unsigned int)gd->fb_base, FBSIZE(panel));
+
+	/* palette default entry */
+	memset((void *)gd->fb_base, 0, 0x20);
+	*(unsigned int *)gd->fb_base = 0x4000;
+
+	lcdhw->clkc_enable = LCD_CORECLKEN | LCD_LIDDCLKEN | LCD_DMACLKEN;
+	lcdhw->raster_ctrl = 0;
+	lcdhw->ctrl = LCD_CLK_DIVISOR(panel->pxl_clk_div) | LCD_RASTER_MODE;
+	lcdhw->lcddma_fb0_base = gd->fb_base;
+	lcdhw->lcddma_fb0_ceiling = gd->fb_base + FBSIZE(panel) + 0x20;
+	lcdhw->lcddma_fb1_base = gd->fb_base;
+	lcdhw->lcddma_fb1_ceiling = gd->fb_base + FBSIZE(panel) + 0x20;
+	lcdhw->lcddma_ctrl = LCD_DMA_BURST_SIZE(LCD_DMA_BURST_16);
+
+	lcdhw->raster_timing0 = LCD_HORLSB(panel->hactive) |
+				LCD_HORMSB(panel->hactive) |
+				LCD_HFPLSB(panel->hfp) |
+				LCD_HBPLSB(panel->hbp) |
+				LCD_HSWLSB(panel->hsw);
+	lcdhw->raster_timing1 = LCD_VBP(panel->vbp) |
+				LCD_VFP(panel->vfp) |
+				LCD_VSW(panel->vsw) |
+				LCD_VERLSB(panel->vactive);
+	lcdhw->raster_timing2 = LCD_HSWMSB(panel->hsw) |
+				LCD_VERMSB(panel->vactive) |
+				LCD_INVMASK(panel->pol) |
+				LCD_HBPMSB(panel->hbp) |
+				LCD_HFPMSB(panel->hfp) |
+				0x0000FF00;	/* clk cycles for ac-bias */
+	lcdhw->raster_ctrl =	LCD_TFT_24BPP_MODE |
+				LCD_TFT_24BPP_UNPACK |
+				LCD_PALMODE_RAWDATA |
+				LCD_TFT_MODE |
+				LCD_RASTER_ENABLE;
+
+	gd->fb_base += 0x20;	/* point fb behind palette */
+
+	/* turn ON display through powercontrol function if accessible */
+	if (0 != panel->panel_power_ctrl) {
+		mdelay(panel->pon_delay);
+		panel->panel_power_ctrl(1);
+	}
+
+	return 0;
+}
diff --git a/drivers/video/am335x-fb.h b/drivers/video/am335x-fb.h
new file mode 100644
index 0000000..8a0b131
--- /dev/null
+++ b/drivers/video/am335x-fb.h
@@ -0,0 +1,67 @@
+/*
+ * Copyright (C) 2013 Hannes Petermaier <oe5hpm@oevsv.at> -
+ * Bernecker & Rainer Industrieelektronik GmbH - http://www.br-automation.com
+ *
+ * SPDX-License-Identifier:	GPL-2.0+
+ */
+
+#ifndef AM335X_FB_H
+#define AM335X_FB_H
+
+#define HSVS_CONTROL	(0x01 << 25)	/*
+					 * 0 = lcd_lp and lcd_fp are driven on
+					 * opposite edges of pixel clock than
+					 * the lcd_pixel_o
+					 * 1 = lcd_lp and lcd_fp are driven
+					 * according to bit 24 Note that this
+					 * bit MUST be set to '0' for Passive
+					 * Matrix displays the edge timing is
+					 * fixed
+					 */
+#define HSVS_RISEFALL	(0x01 << 24)	/*
+					 * 0 = lcd_lp and lcd_fp are driven on
+					 * the rising edge of pixel clock (bit
+					 * 25 must be set to 1)
+					 * 1 = lcd_lp and lcd_fp are driven on
+					 * the falling edge of pixel clock (bit
+					 * 25 must be set to 1)
+					 */
+#define DE_INVERT	(0x01 << 23)	/*
+					 * 0 = DE is low-active
+					 * 1 = DE is high-active
+					 */
+#define PXCLK_INVERT	(0x01 << 22)	/*
+					 * 0 = pix-clk is high-active
+					 * 1 = pic-clk is low-active
+					 */
+#define HSYNC_INVERT	(0x01 << 21)	/*
+					 * 0 = HSYNC is active high
+					 * 1 = HSYNC is avtive low
+					 */
+#define VSYNC_INVERT	(0x01 << 20)	/*
+					 * 0 = VSYNC is active high
+					 * 1 = VSYNC is active low
+					 */
+
+struct am335x_lcdpanel {
+	unsigned int	hactive;	/* Horizontal active area */
+	unsigned int	vactive;	/* Vertical active area */
+	unsigned int	bpp;		/* bits per pixel */
+	unsigned int	hfp;		/* Horizontal front porch */
+	unsigned int	hbp;		/* Horizontal back porch */
+	unsigned int	hsw;		/* Horizontal Sync Pulse Width */
+	unsigned int	vfp;		/* Vertical front porch */
+	unsigned int	vbp;		/* Vertical back porch */
+	unsigned int	vsw;		/* Vertical Sync Pulse Width */
+	unsigned int	pxl_clk_div;	/* Pixel clock divider*/
+	unsigned int	pol;		/* polarity of sync, clock signals */
+	unsigned int	pon_delay;	/*
+					 * time in ms for turning on lcd after
+					 * initializing lcd-controller
+					 */
+	void (*panel_power_ctrl)(int);	/* fp for power on/off display */
+};
+
+int am335xfb_init(struct am335x_lcdpanel *panel);
+
+#endif  /* AM335X_FB_H */
diff --git a/drivers/video/ipu.h b/drivers/video/ipu.h
index 3d2741f..091b58f 100644
--- a/drivers/video/ipu.h
+++ b/drivers/video/ipu.h
@@ -176,6 +176,14 @@
 } ipu_channel_params_t;
 
 /*
+ * Enumeration of IPU interrupts.
+ */
+enum ipu_irq_line {
+	IPU_IRQ_DP_SF_END = 448 + 3,
+	IPU_IRQ_DC_FC_1 = 448 + 9,
+};
+
+/*
  * Bitfield of Display Interface signal polarities.
  */
 typedef struct {
diff --git a/drivers/video/ipu_disp.c b/drivers/video/ipu_disp.c
index cefd2dc..948e1fc 100644
--- a/drivers/video/ipu_disp.c
+++ b/drivers/video/ipu_disp.c
@@ -33,7 +33,7 @@
 
 struct dp_csc_param_t {
 	int mode;
-	void *coeff;
+	const int (*coeff)[5][3];
 };
 
 #define SYNC_WAVE 0
@@ -666,13 +666,16 @@
 	uint32_t csc;
 	uint32_t dc_chan = 0;
 	int timeout = 50;
+	int irq = 0;
 
 	dc_swap = swap;
 
 	if (channel == MEM_DC_SYNC) {
 		dc_chan = 1;
+		irq = IPU_IRQ_DC_FC_1;
 	} else if (channel == MEM_BG_SYNC) {
 		dc_chan = 5;
+		irq = IPU_IRQ_DP_SF_END;
 	} else if (channel == MEM_FG_SYNC) {
 		/* Disable FG channel */
 		dc_chan = 5;
@@ -723,25 +726,11 @@
 		reg ^= DC_WR_CH_CONF_PROG_DI_ID;
 		__raw_writel(reg, DC_WR_CH_CONF(dc_chan));
 	} else {
-		timeout = 50;
-
-		/* Wait for DC triple buffer to empty */
-		if (g_dc_di_assignment[dc_chan] == 0)
-			while ((__raw_readl(DC_STAT) & 0x00000002)
-				!= 0x00000002) {
-				udelay(2000);
-				timeout -= 2;
-				if (timeout <= 0)
-					break;
-			}
-		else if (g_dc_di_assignment[dc_chan] == 1)
-			while ((__raw_readl(DC_STAT) & 0x00000020)
-				!= 0x00000020) {
-				udelay(2000);
-				timeout -= 2;
-				if (timeout <= 0)
-					break;
-			}
+		/* Make sure that we leave at the irq starting edge */
+		__raw_writel(IPUIRQ_2_MASK(irq), IPUIRQ_2_STATREG(irq));
+		do {
+			reg = __raw_readl(IPUIRQ_2_STATREG(irq));
+		} while (!(reg & IPUIRQ_2_MASK(irq)));
 
 		reg = __raw_readl(DC_WR_CH_CONF(dc_chan));
 		reg &= ~DC_WR_CH_CONF_PROG_TYPE_MASK;
diff --git a/drivers/video/ipu_regs.h b/drivers/video/ipu_regs.h
index 21e9c99..c2c134a 100644
--- a/drivers/video/ipu_regs.h
+++ b/drivers/video/ipu_regs.h
@@ -313,9 +313,12 @@
 
 #define IPU_STAT		((struct ipu_stat *)(IPU_CTRL_BASE_ADDR + \
 				IPU_STAT_REG_BASE))
+#define IPU_INT_STAT(n)		(&IPU_STAT->int_stat[(n) - 1])
 #define IPU_CHA_CUR_BUF(ch)	(&IPU_STAT->cur_buf[ch / 32])
 #define IPU_CHA_BUF0_RDY(ch)	(&IPU_STAT->ch_buf0_rdy[ch / 32])
 #define IPU_CHA_BUF1_RDY(ch)	(&IPU_STAT->ch_buf1_rdy[ch / 32])
+#define IPUIRQ_2_STATREG(irq)	(IPU_INT_STAT(1) + ((irq) / 32))
+#define IPUIRQ_2_MASK(irq)	(1UL << ((irq) & 0x1F))
 
 #define IPU_INT_CTRL(n)		(&IPU_CM_REG->int_ctrl[(n) - 1])
 
diff --git a/fs/ext4/ext4fs.c b/fs/ext4/ext4fs.c
index 417ce7b..cbdc220 100644
--- a/fs/ext4/ext4fs.c
+++ b/fs/ext4/ext4fs.c
@@ -182,6 +182,11 @@
 	return file_len >= 0;
 }
 
+int ext4fs_size(const char *filename)
+{
+	return ext4fs_open(filename);
+}
+
 int ext4fs_read(char *buf, unsigned len)
 {
 	if (ext4fs_root == NULL || ext4fs_file == NULL)
diff --git a/fs/fat/fat.c b/fs/fat/fat.c
index 54f42ea..561921f 100644
--- a/fs/fat/fat.c
+++ b/fs/fat/fat.c
@@ -1243,6 +1243,11 @@
 	return sz >= 0;
 }
 
+int fat_size(const char *filename)
+{
+	return do_fat_read_at(filename, 0, NULL, 0, LS_NO, 1);
+}
+
 long file_fat_read_at(const char *filename, unsigned long pos, void *buffer,
 		      unsigned long maxsize)
 {
diff --git a/fs/fs.c b/fs/fs.c
index ea15c5f..dd680f3 100644
--- a/fs/fs.c
+++ b/fs/fs.c
@@ -46,6 +46,11 @@
 	return 0;
 }
 
+static inline int fs_size_unsupported(const char *filename)
+{
+	return -1;
+}
+
 static inline int fs_read_unsupported(const char *filename, void *buf,
 				      int offset, int len)
 {
@@ -77,6 +82,7 @@
 		     disk_partition_t *fs_partition);
 	int (*ls)(const char *dirname);
 	int (*exists)(const char *filename);
+	int (*size)(const char *filename);
 	int (*read)(const char *filename, void *buf, int offset, int len);
 	int (*write)(const char *filename, void *buf, int offset, int len);
 	void (*close)(void);
@@ -91,6 +97,7 @@
 		.close = fat_close,
 		.ls = file_fat_ls,
 		.exists = fat_exists,
+		.size = fat_size,
 		.read = fat_read_file,
 		.write = fs_write_unsupported,
 	},
@@ -103,6 +110,7 @@
 		.close = ext4fs_close,
 		.ls = ext4fs_ls,
 		.exists = ext4fs_exists,
+		.size = ext4fs_size,
 		.read = ext4_read_file,
 		.write = fs_write_unsupported,
 	},
@@ -115,6 +123,7 @@
 		.close = sandbox_fs_close,
 		.ls = sandbox_fs_ls,
 		.exists = sandbox_fs_exists,
+		.size = sandbox_fs_size,
 		.read = fs_read_sandbox,
 		.write = fs_write_sandbox,
 	},
@@ -126,6 +135,7 @@
 		.close = fs_close_unsupported,
 		.ls = fs_ls_unsupported,
 		.exists = fs_exists_unsupported,
+		.size = fs_size_unsupported,
 		.read = fs_read_unsupported,
 		.write = fs_write_unsupported,
 	},
@@ -223,6 +233,19 @@
 	return ret;
 }
 
+int fs_size(const char *filename)
+{
+	int ret;
+
+	struct fstype_info *info = fs_get_info(fs_type);
+
+	ret = info->size(filename);
+
+	fs_close();
+
+	return ret;
+}
+
 int fs_read(const char *filename, ulong addr, int offset, int len)
 {
 	struct fstype_info *info = fs_get_info(fs_type);
@@ -266,6 +289,26 @@
 	return ret;
 }
 
+int do_size(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[],
+		int fstype)
+{
+	int size;
+
+	if (argc != 4)
+		return CMD_RET_USAGE;
+
+	if (fs_set_blk_dev(argv[1], argv[2], fstype))
+		return 1;
+
+	size = fs_size(argv[3]);
+	if (size < 0)
+		return CMD_RET_FAILURE;
+
+	setenv_hex("filesize", size);
+
+	return 0;
+}
+
 int do_load(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[],
 		int fstype)
 {
diff --git a/fs/sandbox/sandboxfs.c b/fs/sandbox/sandboxfs.c
index 8507978..ba6402c 100644
--- a/fs/sandbox/sandboxfs.c
+++ b/fs/sandbox/sandboxfs.c
@@ -80,6 +80,11 @@
 	return sz >= 0;
 }
 
+int sandbox_fs_size(const char *filename)
+{
+	return os_get_filesize(filename);
+}
+
 void sandbox_fs_close(void)
 {
 }
diff --git a/include/config_distro_bootcmd.h b/include/config_distro_bootcmd.h
new file mode 100644
index 0000000..90d9901
--- /dev/null
+++ b/include/config_distro_bootcmd.h
@@ -0,0 +1,197 @@
+/*
+ * (C) Copyright 2014
+ * NVIDIA Corporation <www.nvidia.com>
+ *
+ * Copyright 2014 Red Hat, Inc.
+ *
+ * SPDX-License-Identifier:     GPL-2.0+
+ */
+
+#ifndef _CONFIG_CMD_DISTRO_BOOTCMD_H
+#define _CONFIG_CMD_DISTRO_BOOTCMD_H
+
+#define BOOTENV_SHARED_BLKDEV_BODY(devtypel) \
+		"if " #devtypel " dev ${devnum}; then " \
+			"setenv devtype " #devtypel "; " \
+			"run scan_dev_for_boot; " \
+		"fi\0"
+
+#define BOOTENV_SHARED_BLKDEV(devtypel) \
+	#devtypel "_boot=" \
+	BOOTENV_SHARED_BLKDEV_BODY(devtypel)
+
+#define BOOTENV_DEV_BLKDEV(devtypeu, devtypel, instance) \
+	"bootcmd_" #devtypel #instance "=" \
+		"setenv devnum " #instance "; " \
+		"run " #devtypel "_boot\0"
+
+#define BOOTENV_DEV_NAME_BLKDEV(devtypeu, devtypel, instance) \
+	#devtypel #instance " "
+
+#ifdef CONFIG_CMD_MMC
+#define BOOTENV_SHARED_MMC	BOOTENV_SHARED_BLKDEV(mmc)
+#define BOOTENV_DEV_MMC		BOOTENV_DEV_BLKDEV
+#define BOOTENV_DEV_NAME_MMC	BOOTENV_DEV_NAME_BLKDEV
+#else
+#define BOOTENV_SHARED_MMC
+#define BOOTENV_DEV_MMC \
+	BOOT_TARGET_DEVICES_references_MMC_without_CONFIG_CMD_MMC
+#define BOOTENV_DEV_NAME_MMC \
+	BOOT_TARGET_DEVICES_references_MMC_without_CONFIG_CMD_MMC
+#endif
+
+#ifdef CONFIG_CMD_SATA
+#define BOOTENV_SHARED_SATA	BOOTENV_SHARED_BLKDEV(sata)
+#define BOOTENV_DEV_SATA	BOOTENV_DEV_BLKDEV
+#define BOOTENV_DEV_NAME_SATA	BOOTENV_DEV_NAME_BLKDEV
+#else
+#define BOOTENV_SHARED_SATA
+#define BOOTENV_DEV_SATA \
+	BOOT_TARGET_DEVICES_references_SATA_without_CONFIG_CMD_SATA
+#define BOOTENV_DEV_NAME_SATA \
+	BOOT_TARGET_DEVICES_references_SATA_without_CONFIG_CMD_SATA
+#endif
+
+#ifdef CONFIG_CMD_SCSI
+#define BOOTENV_SHARED_SCSI	BOOTENV_SHARED_BLKDEV(scsi)
+#define BOOTENV_DEV_SCSI	BOOTENV_DEV_BLKDEV
+#define BOOTENV_DEV_NAME_SCSI	BOOTENV_DEV_NAME_BLKDEV
+#else
+#define BOOTENV_SHARED_SCSI
+#define BOOTENV_DEV_SCSI \
+	BOOT_TARGET_DEVICES_references_SCSI_without_CONFIG_CMD_SCSI
+#define BOOTENV_DEV_NAME_SCSI \
+	BOOT_TARGET_DEVICES_references_SCSI_without_CONFIG_CMD_SCSI
+#endif
+
+#ifdef CONFIG_CMD_IDE
+#define BOOTENV_SHARED_IDE	BOOTENV_SHARED_BLKDEV(ide)
+#define BOOTENV_DEV_IDE		BOOTENV_DEV_BLKDEV
+#define BOOTENV_DEV_NAME_IDE	BOOTENV_DEV_NAME_BLKDEV
+#else
+#define BOOTENV_SHARED_IDE
+#define BOOTENV_DEV_IDE \
+	BOOT_TARGET_DEVICES_references_IDE_without_CONFIG_CMD_IDE
+#define BOOTENV_DEV_NAME_IDE \
+	BOOT_TARGET_DEVICES_references_IDE_without_CONFIG_CMD_IDE
+#endif
+
+#ifdef CONFIG_CMD_USB
+#define BOOTENV_RUN_USB_INIT "run usb_init; "
+#define BOOTENV_SET_USB_NEED_INIT "setenv usb_need_init; "
+#define BOOTENV_SHARED_USB \
+	"usb_init=" \
+		"if ${usb_need_init}; then " \
+			"setenv usb_need_init false; " \
+			"usb start 0; " \
+		"fi\0" \
+	\
+	"usb_boot=" \
+		BOOTENV_RUN_USB_INIT \
+		BOOTENV_SHARED_BLKDEV_BODY(usb)
+#define BOOTENV_DEV_USB		BOOTENV_DEV_BLKDEV
+#define BOOTENV_DEV_NAME_USB	BOOTENV_DEV_NAME_BLKDEV
+#else
+#define BOOTENV_RUN_USB_INIT
+#define BOOTENV_SET_USB_NEED_INIT
+#define BOOTENV_SHARED_USB
+#define BOOTENV_DEV_USB \
+	BOOT_TARGET_DEVICES_references_USB_without_CONFIG_CMD_USB
+#define BOOTENV_DEV_NAME_USB \
+	BOOT_TARGET_DEVICES_references_USB_without_CONFIG_CMD_USB
+#endif
+
+#if defined(CONFIG_CMD_DHCP)
+#define BOOTENV_DEV_DHCP(devtypeu, devtypel, instance) \
+	"bootcmd_dhcp=" \
+		BOOTENV_RUN_USB_INIT \
+		"if dhcp ${scriptaddr} boot.scr.uimg; then " \
+			"source ${scriptaddr}; " \
+		"fi\0"
+#define BOOTENV_DEV_NAME_DHCP(devtypeu, devtypel, instance) \
+	"dhcp "
+#else
+#define BOOTENV_DEV_DHCP \
+	BOOT_TARGET_DEVICES_references_DHCP_without_CONFIG_CMD_DHCP
+#define BOOTENV_DEV_NAME_DHCP \
+	BOOT_TARGET_DEVICES_references_DHCP_without_CONFIG_CMD_DHCP
+#endif
+
+#if defined(CONFIG_CMD_DHCP) && defined(CONFIG_CMD_PXE)
+#define BOOTENV_DEV_PXE(devtypeu, devtypel, instance) \
+	"bootcmd_pxe=" \
+		BOOTENV_RUN_USB_INIT \
+		"dhcp; " \
+		"if pxe get; then " \
+			"pxe boot; " \
+		"fi\0"
+#define BOOTENV_DEV_NAME_PXE(devtypeu, devtypel, instance) \
+	"pxe "
+#else
+#define BOOTENV_DEV_PXE \
+	BOOT_TARGET_DEVICES_references_PXE_without_CONFIG_CMD_DHCP_or_PXE
+#define BOOTENV_DEV_NAME_PXE \
+	BOOT_TARGET_DEVICES_references_PXE_without_CONFIG_CMD_DHCP_or_PXE
+#endif
+
+#define BOOTENV_DEV_NAME(devtypeu, devtypel, instance) \
+	BOOTENV_DEV_NAME_##devtypeu(devtypeu, devtypel, instance)
+#define BOOTENV_BOOT_TARGETS \
+	"boot_targets=" BOOT_TARGET_DEVICES(BOOTENV_DEV_NAME) "\0"
+
+#define BOOTENV_DEV(devtypeu, devtypel, instance) \
+	BOOTENV_DEV_##devtypeu(devtypeu, devtypel, instance)
+#define BOOTENV \
+	BOOTENV_SHARED_MMC \
+	BOOTENV_SHARED_USB \
+	BOOTENV_SHARED_SATA \
+	BOOTENV_SHARED_SCSI \
+	BOOTENV_SHARED_IDE \
+	"boot_prefixes=/ /boot/\0" \
+	"boot_scripts=boot.scr.uimg boot.scr\0" \
+	BOOTENV_BOOT_TARGETS \
+	"bootpart=1\0" \
+	\
+	"boot_extlinux="                                                  \
+		"sysboot ${devtype} ${devnum}:${bootpart} any "           \
+			"${scriptaddr} ${prefix}extlinux/extlinux.conf\0" \
+	\
+	"scan_dev_for_extlinux="                                          \
+		"if test -e ${devtype} ${devnum}:${bootpart} "            \
+				"${prefix}extlinux/extlinux.conf; then "  \
+			"echo Found ${prefix}extlinux/extlinux.conf; "    \
+			"run boot_extlinux; "                             \
+			"echo SCRIPT FAILED: continuing...; "             \
+		"fi\0"                                                    \
+	\
+	"boot_a_script="                                                  \
+		"load ${devtype} ${devnum}:${bootpart} "                  \
+			"${scriptaddr} ${prefix}${script}; "              \
+		"source ${scriptaddr}\0"                                  \
+	\
+	"scan_dev_for_scripts="                                           \
+		"for script in ${boot_scripts}; do "                      \
+			"if test -e ${devtype} ${devnum}:${bootpart} "    \
+					"${prefix}${script}; then "       \
+				"echo Found U-Boot script "               \
+					"${prefix}${script}; "            \
+				"run boot_a_script; "                     \
+				"echo SCRIPT FAILED: continuing...; "     \
+			"fi; "                                            \
+		"done\0"                                                  \
+	\
+	"scan_dev_for_boot="                                              \
+		"echo Scanning ${devtype} ${devnum}...; "                 \
+		"for prefix in ${boot_prefixes}; do "                     \
+			"run scan_dev_for_extlinux; "                     \
+			"run scan_dev_for_scripts; "                      \
+		"done\0"                                                  \
+	\
+	BOOT_TARGET_DEVICES(BOOTENV_DEV)                                  \
+	\
+	"bootcmd=" BOOTENV_SET_USB_NEED_INIT                              \
+		"for target in ${boot_targets}; do "                      \
+			"run bootcmd_${target}; "                         \
+		"done\0"
+
+#endif  /* _CONFIG_CMD_DISTRO_BOOTCMD_H */
diff --git a/include/configs/koelsch.h b/include/configs/koelsch.h
index 6795f28..3c2b613 100644
--- a/include/configs/koelsch.h
+++ b/include/configs/koelsch.h
@@ -171,7 +171,7 @@
 /* USB */
 #define CONFIG_USB_EHCI
 #define CONFIG_USB_EHCI_RMOBILE
-#define CONFIG_USB_MAX_CONTROLLER_COUNT	3
+#define CONFIG_USB_MAX_CONTROLLER_COUNT	2
 #define CONFIG_USB_STORAGE
 
 #endif	/* __KOELSCH_H */
diff --git a/include/configs/lager.h b/include/configs/lager.h
index f39a788..74c998f 100644
--- a/include/configs/lager.h
+++ b/include/configs/lager.h
@@ -175,7 +175,7 @@
 /* USB */
 #define CONFIG_USB_EHCI
 #define CONFIG_USB_EHCI_RMOBILE
-#define CONFIG_USB_MAX_CONTROLLER_COUNT	4
+#define CONFIG_USB_MAX_CONTROLLER_COUNT	3
 #define CONFIG_USB_STORAGE
 
 #endif	/* __LAGER_H */
diff --git a/include/configs/omap1510.h b/include/configs/omap1510.h
index 41f7973..5482722 100644
--- a/include/configs/omap1510.h
+++ b/include/configs/omap1510.h
@@ -612,22 +612,6 @@
 int cpu_type(void);
 #endif
 
-/*
- * EVM Implementation Specifics.
- *
- * *** NOTE ***
- * Any definitions in these files should be prefixed by an identifier -
- * eg. OMAP1510P1_FLASH0_BASE .
- *
- */
-#ifdef CONFIG_OMAP_INNOVATOR
-#include "innovator.h"
-#endif
-
-#ifdef CONFIG_OMAP_1510P1
-#include "omap1510p1.h"
-#endif
-
 /*****************************************************************************/
 
 #define CLKGEN_RESET_BASE (0xfffece00)
diff --git a/include/configs/rpi_b.h b/include/configs/rpi_b.h
index 60f2489..2d69809 100644
--- a/include/configs/rpi_b.h
+++ b/include/configs/rpi_b.h
@@ -101,6 +101,38 @@
 		"env import -t -r ${loadaddr} ${filesize}; " \
 	"fi"
 
+/* Shell */
+#define CONFIG_SYS_MAXARGS		8
+#define CONFIG_SYS_PROMPT		"U-Boot> "
+#define CONFIG_COMMAND_HISTORY
+
+/* Commands */
+#include <config_cmd_default.h>
+#define CONFIG_CMD_GPIO
+#define CONFIG_CMD_MMC
+#define CONFIG_PARTITION_UUIDS
+#define CONFIG_CMD_PART
+
+/* Device tree support */
+#define CONFIG_OF_BOARD_SETUP
+/* ATAGs support for bootm/bootz */
+#define CONFIG_SETUP_MEMORY_TAGS
+#define CONFIG_CMDLINE_TAG
+#define CONFIG_INITRD_TAG
+
+#include <config_distro_defaults.h>
+
+/* Some things don't make sense on this HW or yet */
+#undef CONFIG_CMD_FPGA
+#undef CONFIG_CMD_NET
+#undef CONFIG_CMD_NFS
+#undef CONFIG_CMD_SAVEENV
+#undef CONFIG_CMD_DHCP
+#undef CONFIG_CMD_MII
+#undef CONFIG_CMD_NET
+#undef CONFIG_CMD_PING
+
+/* Environment */
 #define ENV_DEVICE_SETTINGS \
 	"stdin=serial,lcd\0" \
 	"stdout=serial,lcd\0" \
@@ -138,104 +170,15 @@
 	"fdtfile=bcm2835-rpi-b.dtb\0" \
 	"ramdisk_addr_r=0x02100000\0" \
 
-#define BOOTCMDS_MMC \
-	"mmc_boot=" \
-		"setenv devtype mmc; " \
-		"if mmc dev ${devnum}; then " \
-			"run scan_boot; " \
-		"fi\0" \
-	"bootcmd_mmc0=setenv devnum 0; run mmc_boot;\0"
-#define BOOT_TARGETS_MMC "mmc0"
-
-#define BOOTCMDS_COMMON \
-	"rootpart=1\0" \
-	\
-	"do_script_boot="                                                 \
-		"load ${devtype} ${devnum}:${rootpart} "                  \
-			"${scriptaddr} ${prefix}${script}; "              \
-		"source ${scriptaddr}\0"                                  \
-	\
-	"script_boot="                                                    \
-		"for script in ${boot_scripts}; do "                      \
-			"if test -e ${devtype} ${devnum}:${rootpart} "    \
-					"${prefix}${script}; then "       \
-				"echo Found ${prefix}${script}; "         \
-				"run do_script_boot; "                    \
-				"echo SCRIPT FAILED: continuing...; "     \
-			"fi; "                                            \
-		"done\0"                                                  \
-	\
-	"do_sysboot_boot="                                                \
-		"sysboot ${devtype} ${devnum}:${rootpart} any "           \
-			"${scriptaddr} ${prefix}extlinux/extlinux.conf\0" \
-	\
-	"sysboot_boot="                                                   \
-		"if test -e ${devtype} ${devnum}:${rootpart} "            \
-				"${prefix}extlinux/extlinux.conf; then "  \
-			"echo Found ${prefix}extlinux/extlinux.conf; "    \
-			"run do_sysboot_boot; "                           \
-			"echo SCRIPT FAILED: continuing...; "             \
-		"fi\0"                                                    \
-	\
-	"scan_boot="                                                      \
-		"echo Scanning ${devtype} ${devnum}...; "                 \
-		"for prefix in ${boot_prefixes}; do "                     \
-			"run sysboot_boot; "                              \
-			"run script_boot; "                               \
-		"done\0"                                                  \
-	\
-	"boot_targets=" \
-		BOOT_TARGETS_MMC " " \
-		"\0" \
-	\
-	"boot_prefixes=/\0" \
-	\
-	"boot_scripts=boot.scr.uimg\0" \
-	\
-	BOOTCMDS_MMC
-
-#define CONFIG_BOOTCOMMAND \
-	"for target in ${boot_targets}; do run bootcmd_${target}; done"
-
-#define CONFIG_BOOTCOMMAND \
-	"for target in ${boot_targets}; do run bootcmd_${target}; done"
+#define BOOT_TARGET_DEVICES(func) \
+	func(MMC, mmc, 0)
+#include <config_distro_bootcmd.h>
 
 #define CONFIG_EXTRA_ENV_SETTINGS \
 	ENV_DEVICE_SETTINGS \
 	ENV_MEM_LAYOUT_SETTINGS \
-	BOOTCMDS_COMMON
+	BOOTENV
 
 #define CONFIG_BOOTDELAY 2
 
-/* Shell */
-#define CONFIG_SYS_MAXARGS		8
-#define CONFIG_SYS_PROMPT		"U-Boot> "
-#define CONFIG_COMMAND_HISTORY
-
-/* Commands */
-#include <config_cmd_default.h>
-#define CONFIG_CMD_GPIO
-#define CONFIG_CMD_MMC
-#define CONFIG_PARTITION_UUIDS
-#define CONFIG_CMD_PART
-
-/* Device tree support */
-#define CONFIG_OF_BOARD_SETUP
-/* ATAGs support for bootm/bootz */
-#define CONFIG_SETUP_MEMORY_TAGS
-#define CONFIG_CMDLINE_TAG
-#define CONFIG_INITRD_TAG
-
-#include <config_distro_defaults.h>
-
-/* Some things don't make sense on this HW or yet */
-#undef CONFIG_CMD_FPGA
-#undef CONFIG_CMD_NET
-#undef CONFIG_CMD_NFS
-#undef CONFIG_CMD_SAVEENV
-#undef CONFIG_CMD_DHCP
-#undef CONFIG_CMD_MII
-#undef CONFIG_CMD_NET
-#undef CONFIG_CMD_PING
-
 #endif
diff --git a/include/configs/tegra-common-post.h b/include/configs/tegra-common-post.h
index 1c770c9..c337e30 100644
--- a/include/configs/tegra-common-post.h
+++ b/include/configs/tegra-common-post.h
@@ -8,136 +8,16 @@
 #ifndef __TEGRA_COMMON_POST_H
 #define __TEGRA_COMMON_POST_H
 
-#ifdef CONFIG_BOOTCOMMAND
-
-#define BOOTCMDS_COMMON ""
-
+#ifndef CONFIG_SPL_BUILD
+#define BOOT_TARGET_DEVICES(func) \
+	func(MMC, mmc, 1) \
+	func(MMC, mmc, 0) \
+	func(USB, usb, 0) \
+	func(PXE, pxe, na) \
+	func(DHCP, dhcp, na)
+#include <config_distro_bootcmd.h>
 #else
-
-#ifdef CONFIG_CMD_MMC
-#define BOOTCMDS_MMC \
-	"mmc_boot=" \
-		"setenv devtype mmc; " \
-		"if mmc dev ${devnum}; then " \
-			"run scan_boot; " \
-		"fi\0" \
-	"bootcmd_mmc0=setenv devnum 0; run mmc_boot;\0" \
-	"bootcmd_mmc1=setenv devnum 1; run mmc_boot;\0"
-#define BOOT_TARGETS_MMC "mmc1 mmc0"
-#else
-#define BOOTCMDS_MMC ""
-#define BOOT_TARGETS_MMC ""
-#endif
-
-#ifdef CONFIG_CMD_USB
-#define BOOTCMD_INIT_USB "run usb_init; "
-#define BOOTCMDS_USB \
-	"usb_init=" \
-		"if ${usb_need_init}; then " \
-			"set usb_need_init false; " \
-			"usb start 0; " \
-		"fi\0" \
-	\
-	"usb_boot=" \
-		"setenv devtype usb; " \
-		BOOTCMD_INIT_USB \
-		"if usb dev ${devnum}; then " \
-			"run scan_boot; " \
-		"fi\0" \
-	\
-	"bootcmd_usb0=setenv devnum 0; run usb_boot;\0"
-#define BOOT_TARGETS_USB "usb0"
-#else
-#define BOOTCMD_INIT_USB ""
-#define BOOTCMDS_USB ""
-#define BOOT_TARGETS_USB ""
-#endif
-
-#ifdef CONFIG_CMD_DHCP
-#define BOOTCMDS_DHCP \
-	"bootcmd_dhcp=" \
-		BOOTCMD_INIT_USB \
-		"if dhcp ${scriptaddr} boot.scr.uimg; then "\
-			"source ${scriptaddr}; " \
-		"fi\0"
-#define BOOT_TARGETS_DHCP "dhcp"
-#else
-#define BOOTCMDS_DHCP ""
-#define BOOT_TARGETS_DHCP ""
-#endif
-
-#if defined(CONFIG_CMD_DHCP) && defined(CONFIG_CMD_PXE)
-#define BOOTCMDS_PXE \
-	"bootcmd_pxe=" \
-		BOOTCMD_INIT_USB \
-		"dhcp; " \
-		"if pxe get; then " \
-			"pxe boot; " \
-		"fi\0"
-#define BOOT_TARGETS_PXE "pxe"
-#else
-#define BOOTCMDS_PXE ""
-#define BOOT_TARGETS_PXE ""
-#endif
-
-#define BOOTCMDS_COMMON \
-	"rootpart=1\0" \
-	\
-	"do_script_boot="                                                 \
-		"load ${devtype} ${devnum}:${rootpart} "                  \
-			"${scriptaddr} ${prefix}${script}; "              \
-		"source ${scriptaddr}\0"                                  \
-	\
-	"script_boot="                                                    \
-		"for script in ${boot_scripts}; do "                      \
-			"if test -e ${devtype} ${devnum}:${rootpart} "    \
-					"${prefix}${script}; then "       \
-				"echo Found U-Boot script "               \
-					"${prefix}${script}; "            \
-				"run do_script_boot; "                    \
-				"echo SCRIPT FAILED: continuing...; "     \
-			"fi; "                                            \
-		"done\0"                                                  \
-	\
-	"do_sysboot_boot="                                                \
-		"sysboot ${devtype} ${devnum}:${rootpart} any "           \
-			"${scriptaddr} ${prefix}extlinux/extlinux.conf\0" \
-	\
-	"sysboot_boot="                                                   \
-		"if test -e ${devtype} ${devnum}:${rootpart} "            \
-				"${prefix}extlinux/extlinux.conf; then "  \
-			"echo Found ${prefix}extlinux/extlinux.conf; "    \
-			"run do_sysboot_boot; "                           \
-			"echo SCRIPT FAILED: continuing...; "             \
-		"fi\0"                                                    \
-	\
-	"scan_boot="                                                      \
-		"echo Scanning ${devtype} ${devnum}...; "                 \
-		"for prefix in ${boot_prefixes}; do "                     \
-			"run sysboot_boot; "                              \
-			"run script_boot; "                               \
-		"done\0"                                                  \
-	\
-	"boot_targets=" \
-		BOOT_TARGETS_MMC " " \
-		BOOT_TARGETS_USB " " \
-		BOOT_TARGETS_PXE " " \
-		BOOT_TARGETS_DHCP " " \
-		"\0" \
-	\
-	"boot_prefixes=/ /boot/\0" \
-	\
-	"boot_scripts=boot.scr.uimg boot.scr\0" \
-	\
-	BOOTCMDS_MMC \
-	BOOTCMDS_USB \
-	BOOTCMDS_DHCP \
-	BOOTCMDS_PXE
-
-#define CONFIG_BOOTCOMMAND \
-	"set usb_need_init; " \
-	"for target in ${boot_targets}; do run bootcmd_${target}; done"
-
+#define BOOTENV
 #endif
 
 #ifdef CONFIG_TEGRA_KEYBOARD
@@ -175,7 +55,7 @@
 	MEM_LAYOUT_ENV_SETTINGS \
 	"fdt_high=ffffffff\0" \
 	"initrd_high=ffffffff\0" \
-	BOOTCMDS_COMMON \
+	BOOTENV \
 	BOARD_EXTRA_ENV_SETTINGS
 
 #if defined(CONFIG_TEGRA20_SFLASH) || defined(CONFIG_TEGRA20_SLINK) || defined(CONFIG_TEGRA114_SPI)
diff --git a/include/configs/trats.h b/include/configs/trats.h
index 90f1962..7db1db6 100644
--- a/include/configs/trats.h
+++ b/include/configs/trats.h
@@ -102,9 +102,9 @@
 
 #define CONFIG_DFU_ALT \
 	"u-boot raw 0x80 0x400;" \
-	"uImage ext4 0 2;" \
-	"modem.bin ext4 0 2;" \
-	"exynos4210-trats.dtb ext4 0 2;" \
+	"/uImage ext4 0 2;" \
+	"/modem.bin ext4 0 2;" \
+	"/exynos4210-trats.dtb ext4 0 2;" \
 	""PARTS_CSA" part 0 1;" \
 	""PARTS_BOOT" part 0 2;" \
 	""PARTS_QBOOT" part 0 3;" \
diff --git a/include/configs/trats2.h b/include/configs/trats2.h
index 206975b..f537e4f 100644
--- a/include/configs/trats2.h
+++ b/include/configs/trats2.h
@@ -92,9 +92,9 @@
 
 #define CONFIG_DFU_ALT \
 	"u-boot raw 0x80 0x800;" \
-	"uImage ext4 0 2;" \
-	"modem.bin ext4 0 2;" \
-	"exynos4412-trats2.dtb ext4 0 2;" \
+	"/uImage ext4 0 2;" \
+	"/modem.bin ext4 0 2;" \
+	"/exynos4412-trats2.dtb ext4 0 2;" \
 	""PARTS_CSA" part 0 1;" \
 	""PARTS_BOOT" part 0 2;" \
 	""PARTS_QBOOT" part 0 3;" \
diff --git a/include/dfu.h b/include/dfu.h
index 26ffbc8..7e0a999 100644
--- a/include/dfu.h
+++ b/include/dfu.h
@@ -14,6 +14,7 @@
 #include <common.h>
 #include <linux/list.h>
 #include <mmc.h>
+#include <spi_flash.h>
 #include <linux/usb/composite.h>
 
 enum dfu_device_type {
@@ -21,6 +22,7 @@
 	DFU_DEV_ONENAND,
 	DFU_DEV_NAND,
 	DFU_DEV_RAM,
+	DFU_DEV_SF,
 };
 
 enum dfu_layout {
@@ -35,9 +37,12 @@
 enum dfu_op {
 	DFU_OP_READ = 1,
 	DFU_OP_WRITE,
+	DFU_OP_SIZE,
 };
 
 struct mmc_internal_data {
+	int dev_num;
+
 	/* RAW programming */
 	unsigned int lba_start;
 	unsigned int lba_size;
@@ -67,6 +72,14 @@
 	unsigned int	size;
 };
 
+struct sf_internal_data {
+	struct spi_flash *dev;
+
+	/* RAW programming */
+	u64 start;
+	u64 size;
+};
+
 #define DFU_NAME_SIZE			32
 #define DFU_CMD_BUF_SIZE		128
 #ifndef CONFIG_SYS_DFU_DATA_BUF_SIZE
@@ -86,16 +99,19 @@
 	char			name[DFU_NAME_SIZE];
 	int                     alt;
 	void                    *dev_private;
-	int                     dev_num;
 	enum dfu_device_type    dev_type;
 	enum dfu_layout         layout;
+	unsigned long           max_buf_size;
 
 	union {
 		struct mmc_internal_data mmc;
 		struct nand_internal_data nand;
 		struct ram_internal_data ram;
+		struct sf_internal_data sf;
 	} data;
 
+	long (*get_medium_size)(struct dfu_entity *dfu);
+
 	int (*read_medium)(struct dfu_entity *dfu,
 			u64 offset, void *buf, long *len);
 
@@ -105,6 +121,8 @@
 	int (*flush_medium)(struct dfu_entity *dfu);
 	unsigned int (*poll_timeout)(struct dfu_entity *dfu);
 
+	void (*free_entity)(struct dfu_entity *dfu);
+
 	struct list_head list;
 
 	/* on the fly state */
@@ -122,7 +140,7 @@
 	unsigned int inited:1;
 };
 
-int dfu_config_entities(char *s, char *interface, int num);
+int dfu_config_entities(char *s, char *interface, char *devstr);
 void dfu_free_entities(void);
 void dfu_show_entities(void);
 int dfu_get_alt_number(void);
@@ -133,8 +151,8 @@
 void dfu_trigger_reset(void);
 int dfu_get_alt(char *name);
 bool dfu_reset(void);
-int dfu_init_env_entities(char *interface, int dev);
-unsigned char *dfu_get_buf(void);
+int dfu_init_env_entities(char *interface, char *devstr);
+unsigned char *dfu_get_buf(struct dfu_entity *dfu);
 unsigned char *dfu_free_buf(void);
 unsigned long dfu_get_buf_size(void);
 
@@ -143,9 +161,10 @@
 int dfu_flush(struct dfu_entity *de, void *buf, int size, int blk_seq_num);
 /* Device specific */
 #ifdef CONFIG_DFU_MMC
-extern int dfu_fill_entity_mmc(struct dfu_entity *dfu, char *s);
+extern int dfu_fill_entity_mmc(struct dfu_entity *dfu, char *devstr, char *s);
 #else
-static inline int dfu_fill_entity_mmc(struct dfu_entity *dfu, char *s)
+static inline int dfu_fill_entity_mmc(struct dfu_entity *dfu, char *devstr,
+				      char *s)
 {
 	puts("MMC support not available!\n");
 	return -1;
@@ -153,9 +172,10 @@
 #endif
 
 #ifdef CONFIG_DFU_NAND
-extern int dfu_fill_entity_nand(struct dfu_entity *dfu, char *s);
+extern int dfu_fill_entity_nand(struct dfu_entity *dfu, char *devstr, char *s);
 #else
-static inline int dfu_fill_entity_nand(struct dfu_entity *dfu, char *s)
+static inline int dfu_fill_entity_nand(struct dfu_entity *dfu, char *devstr,
+				       char *s)
 {
 	puts("NAND support not available!\n");
 	return -1;
@@ -163,14 +183,26 @@
 #endif
 
 #ifdef CONFIG_DFU_RAM
-extern int dfu_fill_entity_ram(struct dfu_entity *dfu, char *s);
+extern int dfu_fill_entity_ram(struct dfu_entity *dfu, char *devstr, char *s);
 #else
-static inline int dfu_fill_entity_ram(struct dfu_entity *dfu, char *s)
+static inline int dfu_fill_entity_ram(struct dfu_entity *dfu, char *devstr,
+				      char *s)
 {
 	puts("RAM support not available!\n");
 	return -1;
 }
 #endif
 
+#ifdef CONFIG_DFU_SF
+extern int dfu_fill_entity_sf(struct dfu_entity *dfu, char *devstr, char *s);
+#else
+static inline int dfu_fill_entity_sf(struct dfu_entity *dfu, char *devstr,
+				     char *s)
+{
+	puts("SF support not available!\n");
+	return -1;
+}
+#endif
+
 int dfu_add(struct usb_configuration *c);
 #endif /* __DFU_ENTITY_H_ */
diff --git a/include/ext4fs.h b/include/ext4fs.h
index fbbb002..6c419f3 100644
--- a/include/ext4fs.h
+++ b/include/ext4fs.h
@@ -136,6 +136,7 @@
 void ext4fs_reinit_global(void);
 int ext4fs_ls(const char *dirname);
 int ext4fs_exists(const char *filename);
+int ext4fs_size(const char *filename);
 void ext4fs_free_node(struct ext2fs_node *node, struct ext2fs_node *currroot);
 int ext4fs_devread(lbaint_t sector, int byte_offset, int byte_len, char *buf);
 void ext4fs_set_blk_dev(block_dev_desc_t *rbdd, disk_partition_t *info);
diff --git a/include/fat.h b/include/fat.h
index 63cf787..20ca3f3 100644
--- a/include/fat.h
+++ b/include/fat.h
@@ -198,6 +198,7 @@
 int file_fat_detectfs(void);
 int file_fat_ls(const char *dir);
 int fat_exists(const char *filename);
+int fat_size(const char *filename);
 long file_fat_read_at(const char *filename, unsigned long pos, void *buffer,
 		      unsigned long maxsize);
 long file_fat_read(const char *filename, void *buffer, unsigned long maxsize);
diff --git a/include/fdt_support.h b/include/fdt_support.h
index fd44d7e..1bda686 100644
--- a/include/fdt_support.h
+++ b/include/fdt_support.h
@@ -76,7 +76,7 @@
 void ft_pci_setup(void *blob, bd_t *bd);
 
 void set_working_fdt_addr(void *addr);
-int fdt_resize(void *blob);
+int fdt_shrink_to_minimum(void *blob);
 int fdt_increase_size(void *fdt, int add_len);
 
 int fdt_fixup_nor_flash_size(void *blob);
diff --git a/include/fs.h b/include/fs.h
index 26de053..06a45f2 100644
--- a/include/fs.h
+++ b/include/fs.h
@@ -51,6 +51,13 @@
 int fs_exists(const char *filename);
 
 /*
+ * Determine a file's size
+ *
+ * Returns the file's size in bytes, or a negative value if it doesn't exist.
+ */
+int fs_size(const char *filename);
+
+/*
  * Read file "filename" from the partition previously set by fs_set_blk_dev(),
  * to address "addr", starting at byte offset "offset", and reading "len"
  * bytes. "offset" may be 0 to read from the start of the file. "len" may be
@@ -75,6 +82,8 @@
  * Common implementation for various filesystem commands, optionally limited
  * to a specific filesystem type via the fstype parameter.
  */
+int do_size(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[],
+		int fstype);
 int do_load(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[],
 		int fstype);
 int do_ls(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[],
diff --git a/include/image.h b/include/image.h
index 3e8f78d..ca2fe86 100644
--- a/include/image.h
+++ b/include/image.h
@@ -424,6 +424,7 @@
 #define IMAGE_FORMAT_FIT	0x02	/* new, libfdt based format */
 #define IMAGE_FORMAT_ANDROID	0x03	/* Android boot image */
 
+ulong genimg_get_kernel_addr(char * const img_addr);
 int genimg_get_format(const void *img_addr);
 int genimg_has_config(bootm_headers_t *images);
 ulong genimg_get_image(ulong img_addr);
diff --git a/include/lcd.h b/include/lcd.h
index cc2ee3f..ea5860c 100644
--- a/include/lcd.h
+++ b/include/lcd.h
@@ -26,8 +26,6 @@
 void lcd_setcolreg(ushort regno, ushort red, ushort green, ushort blue);
 void lcd_initcolregs(void);
 
-int lcd_getfgcolor(void);
-
 /* gunzip_bmp used if CONFIG_VIDEO_BMP_GZIP */
 struct bmp_image *gunzip_bmp(unsigned long addr, unsigned long *lenp,
 			     void **alloc_addr);
@@ -333,7 +331,7 @@
 #define LCD_COLOR4	2
 #define LCD_COLOR8	3
 #define LCD_COLOR16	4
-
+#define LCD_COLOR32	5
 /*----------------------------------------------------------------------*/
 #if defined(CONFIG_LCD_INFO_BELOW_LOGO)
 # define LCD_INFO_X		0
@@ -384,6 +382,21 @@
 # define CONSOLE_COLOR_GREY	14
 # define CONSOLE_COLOR_WHITE	15	/* Must remain last / highest	*/
 
+#elif LCD_BPP == LCD_COLOR32
+/*
+ * 32bpp color definitions
+ */
+# define CONSOLE_COLOR_RED	0x00ff0000
+# define CONSOLE_COLOR_GREEN	0x0000ff00
+# define CONSOLE_COLOR_YELLOW	0x00ffff00
+# define CONSOLE_COLOR_BLUE	0x000000ff
+# define CONSOLE_COLOR_MAGENTA	0x00ff00ff
+# define CONSOLE_COLOR_CYAN	0x0000ffff
+# define CONSOLE_COLOR_GREY	0x00aaaaaa
+# define CONSOLE_COLOR_BLACK	0x00000000
+# define CONSOLE_COLOR_WHITE	0x00ffffff	/* Must remain last / highest*/
+# define NBYTES(bit_code)	(NBITS(bit_code) >> 3)
+
 #else
 
 /*
diff --git a/include/libfdt.h b/include/libfdt.h
index 9eefaaf..a1ef1e1 100644
--- a/include/libfdt.h
+++ b/include/libfdt.h
@@ -116,7 +116,12 @@
 	 * Should never be returned, if it is, it indicates a bug in
 	 * libfdt itself. */
 
-#define FDT_ERR_MAX		13
+/* Errors in device tree content */
+#define FDT_ERR_BADNCELLS	14
+	/* FDT_ERR_BADNCELLS: Device tree has a #address-cells, #size-cells
+	 * or similar property with a bad format or value */
+
+#define FDT_ERR_MAX		14
 
 /**********************************************************************/
 /* Low-level functions (you probably don't need these)                */
@@ -596,9 +601,9 @@
 				  const char *name, int namelen);
 
 /**
- * fdt_get_alias - retrieve the path referenced by a given alias
+ * fdt_get_alias - retreive the path referenced by a given alias
  * @fdt: pointer to the device tree blob
- * @name: name of the alias to look up
+ * @name: name of the alias th look up
  *
  * fdt_get_alias() retrieves the value of a given alias.  That is, the
  * value of the property named 'name' in the node /aliases.
@@ -731,7 +736,7 @@
  *	offset = fdt_node_offset_by_prop_value(fdt, -1, propname,
  *					       propval, proplen);
  *	while (offset != -FDT_ERR_NOTFOUND) {
- *		... other code here ...
+ *		// other code here
  *		offset = fdt_node_offset_by_prop_value(fdt, offset, propname,
  *						       propval, proplen);
  *	}
@@ -816,7 +821,7 @@
  * idiom can be used:
  *	offset = fdt_node_offset_by_compatible(fdt, -1, compatible);
  *	while (offset != -FDT_ERR_NOTFOUND) {
- *		... other code here ...
+ *		// other code here
  *		offset = fdt_node_offset_by_compatible(fdt, offset, compatible);
  *	}
  *
@@ -853,6 +858,63 @@
 int fdt_stringlist_contains(const char *strlist, int listlen, const char *str);
 
 /**********************************************************************/
+/* Read-only functions (addressing related)                           */
+/**********************************************************************/
+
+/**
+ * FDT_MAX_NCELLS - maximum value for #address-cells and #size-cells
+ *
+ * This is the maximum value for #address-cells, #size-cells and
+ * similar properties that will be processed by libfdt.  IEE1275
+ * requires that OF implementations handle values up to 4.
+ * Implementations may support larger values, but in practice higher
+ * values aren't used.
+ */
+#define FDT_MAX_NCELLS		4
+
+/**
+ * fdt_address_cells - retrieve address size for a bus represented in the tree
+ * @fdt: pointer to the device tree blob
+ * @nodeoffset: offset of the node to find the address size for
+ *
+ * When the node has a valid #address-cells property, returns its value.
+ *
+ * returns:
+ *	0 <= n < FDT_MAX_NCELLS, on success
+ *      2, if the node has no #address-cells property
+ *      -FDT_ERR_BADNCELLS, if the node has a badly formatted or invalid
+ *		#address-cells property
+ *	-FDT_ERR_BADMAGIC,
+ *	-FDT_ERR_BADVERSION,
+ *	-FDT_ERR_BADSTATE,
+ *	-FDT_ERR_BADSTRUCTURE,
+ *	-FDT_ERR_TRUNCATED, standard meanings
+ */
+int fdt_address_cells(const void *fdt, int nodeoffset);
+
+/**
+ * fdt_size_cells - retrieve address range size for a bus represented in the
+ *                  tree
+ * @fdt: pointer to the device tree blob
+ * @nodeoffset: offset of the node to find the address range size for
+ *
+ * When the node has a valid #size-cells property, returns its value.
+ *
+ * returns:
+ *	0 <= n < FDT_MAX_NCELLS, on success
+ *      2, if the node has no #address-cells property
+ *      -FDT_ERR_BADNCELLS, if the node has a badly formatted or invalid
+ *		#size-cells property
+ *	-FDT_ERR_BADMAGIC,
+ *	-FDT_ERR_BADVERSION,
+ *	-FDT_ERR_BADSTATE,
+ *	-FDT_ERR_BADSTRUCTURE,
+ *	-FDT_ERR_TRUNCATED, standard meanings
+ */
+int fdt_size_cells(const void *fdt, int nodeoffset);
+
+
+/**********************************************************************/
 /* Write-in-place functions                                           */
 /**********************************************************************/
 
@@ -1023,6 +1085,7 @@
 /**********************************************************************/
 
 int fdt_create(void *buf, int bufsize);
+int fdt_resize(void *fdt, void *buf, int bufsize);
 int fdt_add_reservemap_entry(void *fdt, uint64_t addr, uint64_t size);
 int fdt_finish_reservemap(void *fdt);
 int fdt_begin_node(void *fdt, const char *name);
diff --git a/include/ns16550.h b/include/ns16550.h
index 17f829f..d1f3a90 100644
--- a/include/ns16550.h
+++ b/include/ns16550.h
@@ -64,8 +64,6 @@
 	UART_REG(uasr);		/* F */
 	UART_REG(scr);		/* 10*/
 	UART_REG(ssr);		/* 11*/
-	UART_REG(reg12);	/* 12*/
-	UART_REG(osc_12m_sel);	/* 13*/
 #endif
 };
 
@@ -164,11 +162,6 @@
 #define UART_IER_THRI	0x02	/* Enable Transmitter holding register int. */
 #define UART_IER_RDI	0x01	/* Enable receiver data interrupt */
 
-
-#ifdef CONFIG_OMAP1510
-#define OSC_12M_SEL	0x01	/* selects 6.5 * current clk div */
-#endif
-
 /* useful defaults for LCR */
 #define UART_LCR_8N1	0x03
 
diff --git a/include/sandboxfs.h b/include/sandboxfs.h
index a51ad13..e7c3262 100644
--- a/include/sandboxfs.h
+++ b/include/sandboxfs.h
@@ -26,6 +26,7 @@
 void sandbox_fs_close(void);
 int sandbox_fs_ls(const char *dirname);
 int sandbox_fs_exists(const char *filename);
+int sandbox_fs_size(const char *filename);
 int fs_read_sandbox(const char *filename, void *buf, int offset, int len);
 int fs_write_sandbox(const char *filename, void *buf, int offset, int len);
 
diff --git a/include/u-boot/rsa.h b/include/u-boot/rsa.h
index 325751a..fd08a61 100644
--- a/include/u-boot/rsa.h
+++ b/include/u-boot/rsa.h
@@ -27,6 +27,7 @@
 	uint32_t n0inv;		/* -1 / modulus[0] mod 2^32 */
 	uint32_t *modulus;	/* modulus as little endian array */
 	uint32_t *rr;		/* R^2 as little endian array */
+	uint64_t exponent;	/* public exponent */
 };
 
 #if IMAGE_ENABLE_SIGN
diff --git a/include/usb/udc.h b/include/usb/udc.h
index 1f545ec..b2e0c6b 100644
--- a/include/usb/udc.h
+++ b/include/usb/udc.h
@@ -12,8 +12,8 @@
 #define EP_MAX_PACKET_SIZE	64
 #endif
 
-#if !defined(CONFIG_PPC) && !defined(CONFIG_OMAP1510)
-/* omap1510_udc.h and mpc8xx_udc.h will set these values */
+#if !defined(CONFIG_PPC)
+/* mpc8xx_udc.h will set these values */
 #define UDC_OUT_PACKET_SIZE     EP_MAX_PACKET_SIZE
 #define UDC_IN_PACKET_SIZE      EP_MAX_PACKET_SIZE
 #define UDC_INT_PACKET_SIZE     EP_MAX_PACKET_SIZE
diff --git a/lib/libfdt/Makefile b/lib/libfdt/Makefile
index a02c9b0..6fe79e0 100644
--- a/lib/libfdt/Makefile
+++ b/lib/libfdt/Makefile
@@ -5,7 +5,8 @@
 # SPDX-License-Identifier:	GPL-2.0+
 #
 
-COBJS-libfdt += fdt.o fdt_ro.o fdt_rw.o fdt_strerror.o fdt_sw.o fdt_wip.o fdt_empty_tree.o
+COBJS-libfdt += fdt.o fdt_ro.o fdt_rw.o fdt_strerror.o fdt_sw.o fdt_wip.o \
+	fdt_empty_tree.o fdt_addresses.o
 
 obj-$(CONFIG_OF_LIBFDT) += $(COBJS-libfdt)
 obj-$(CONFIG_FIT) += $(COBJS-libfdt)
diff --git a/lib/libfdt/fdt_addresses.c b/lib/libfdt/fdt_addresses.c
new file mode 100644
index 0000000..76054d9
--- /dev/null
+++ b/lib/libfdt/fdt_addresses.c
@@ -0,0 +1,55 @@
+/*
+ * libfdt - Flat Device Tree manipulation
+ * Copyright (C) 2014 David Gibson <david@gibson.dropbear.id.au>
+ * SPDX-License-Identifier:	GPL-2.0+ BSD-2-Clause
+ */
+#include "libfdt_env.h"
+
+#ifndef USE_HOSTCC
+#include <fdt.h>
+#include <libfdt.h>
+#else
+#include "fdt_host.h"
+#endif
+
+#include "libfdt_internal.h"
+
+int fdt_address_cells(const void *fdt, int nodeoffset)
+{
+	const fdt32_t *ac;
+	int val;
+	int len;
+
+	ac = fdt_getprop(fdt, nodeoffset, "#address-cells", &len);
+	if (!ac)
+		return 2;
+
+	if (len != sizeof(*ac))
+		return -FDT_ERR_BADNCELLS;
+
+	val = fdt32_to_cpu(*ac);
+	if ((val <= 0) || (val > FDT_MAX_NCELLS))
+		return -FDT_ERR_BADNCELLS;
+
+	return val;
+}
+
+int fdt_size_cells(const void *fdt, int nodeoffset)
+{
+	const fdt32_t *sc;
+	int val;
+	int len;
+
+	sc = fdt_getprop(fdt, nodeoffset, "#size-cells", &len);
+	if (!sc)
+		return 2;
+
+	if (len != sizeof(*sc))
+		return -FDT_ERR_BADNCELLS;
+
+	val = fdt32_to_cpu(*sc);
+	if ((val < 0) || (val > FDT_MAX_NCELLS))
+		return -FDT_ERR_BADNCELLS;
+
+	return val;
+}
diff --git a/lib/libfdt/fdt_rw.c b/lib/libfdt/fdt_rw.c
index 6fa4f13..bec8b8a 100644
--- a/lib/libfdt/fdt_rw.c
+++ b/lib/libfdt/fdt_rw.c
@@ -43,9 +43,9 @@
 
 #define FDT_RW_CHECK_HEADER(fdt) \
 	{ \
-		int err; \
-		if ((err = _fdt_rw_check_header(fdt)) != 0) \
-			return err; \
+		int __err; \
+		if ((__err = _fdt_rw_check_header(fdt)) != 0) \
+			return __err; \
 	}
 
 static inline int _fdt_data_size(void *fdt)
diff --git a/lib/libfdt/fdt_sw.c b/lib/libfdt/fdt_sw.c
index 580b570..320a914 100644
--- a/lib/libfdt/fdt_sw.c
+++ b/lib/libfdt/fdt_sw.c
@@ -62,6 +62,38 @@
 	return 0;
 }
 
+int fdt_resize(void *fdt, void *buf, int bufsize)
+{
+	size_t headsize, tailsize;
+	char *oldtail, *newtail;
+
+	FDT_SW_CHECK_HEADER(fdt);
+
+	headsize = fdt_off_dt_struct(fdt);
+	tailsize = fdt_size_dt_strings(fdt);
+
+	if ((headsize + tailsize) > bufsize)
+		return -FDT_ERR_NOSPACE;
+
+	oldtail = (char *)fdt + fdt_totalsize(fdt) - tailsize;
+	newtail = (char *)buf + bufsize - tailsize;
+
+	/* Two cases to avoid clobbering data if the old and new
+	 * buffers partially overlap */
+	if (buf <= fdt) {
+		memmove(buf, fdt, headsize);
+		memmove(newtail, oldtail, tailsize);
+	} else {
+		memmove(newtail, oldtail, tailsize);
+		memmove(buf, fdt, headsize);
+	}
+
+	fdt_set_off_dt_strings(buf, bufsize);
+	fdt_set_totalsize(buf, bufsize);
+
+	return 0;
+}
+
 int fdt_add_reservemap_entry(void *fdt, uint64_t addr, uint64_t size)
 {
 	struct fdt_reserve_entry *re;
diff --git a/lib/libfdt/libfdt_internal.h b/lib/libfdt/libfdt_internal.h
index 13cbc9a..9a79fe8 100644
--- a/lib/libfdt/libfdt_internal.h
+++ b/lib/libfdt/libfdt_internal.h
@@ -12,9 +12,9 @@
 
 #define FDT_CHECK_HEADER(fdt) \
 	{ \
-		int err; \
-		if ((err = fdt_check_header(fdt)) != 0) \
-			return err; \
+		int __err; \
+		if ((__err = fdt_check_header(fdt)) != 0) \
+			return __err; \
 	}
 
 int _fdt_check_node_offset(const void *fdt, int offset);
diff --git a/lib/lmb.c b/lib/lmb.c
index 49a3c9e..41a2be4 100644
--- a/lib/lmb.c
+++ b/lib/lmb.c
@@ -295,7 +295,10 @@
 		if (max_addr == LMB_ALLOC_ANYWHERE)
 			base = lmb_align_down(lmbbase + lmbsize - size, align);
 		else if (lmbbase < max_addr) {
-			base = min(lmbbase + lmbsize, max_addr);
+			base = lmbbase + lmbsize;
+			if (base < lmbbase)
+				base = -1;
+			base = min(base, max_addr);
 			base = lmb_align_down(base - size, align);
 		} else
 			continue;
diff --git a/lib/rsa/rsa-sign.c b/lib/rsa/rsa-sign.c
index 83f5e87..5d9716f 100644
--- a/lib/rsa/rsa-sign.c
+++ b/lib/rsa/rsa-sign.c
@@ -76,6 +76,7 @@
 	rsa = EVP_PKEY_get1_RSA(key);
 	if (!rsa) {
 		rsa_err("Couldn't convert to a RSA style key");
+		ret = -EINVAL;
 		goto err_rsa;
 	}
 	fclose(f);
@@ -261,10 +262,57 @@
 }
 
 /*
+ * rsa_get_exponent(): - Get the public exponent from an RSA key
+ */
+static int rsa_get_exponent(RSA *key, uint64_t *e)
+{
+	int ret;
+	BIGNUM *bn_te;
+	uint64_t te;
+
+	ret = -EINVAL;
+	bn_te = NULL;
+
+	if (!e)
+		goto cleanup;
+
+	if (BN_num_bits(key->e) > 64)
+		goto cleanup;
+
+	*e = BN_get_word(key->e);
+
+	if (BN_num_bits(key->e) < 33) {
+		ret = 0;
+		goto cleanup;
+	}
+
+	bn_te = BN_dup(key->e);
+	if (!bn_te)
+		goto cleanup;
+
+	if (!BN_rshift(bn_te, bn_te, 32))
+		goto cleanup;
+
+	if (!BN_mask_bits(bn_te, 32))
+		goto cleanup;
+
+	te = BN_get_word(bn_te);
+	te <<= 32;
+	*e |= te;
+	ret = 0;
+
+cleanup:
+	if (bn_te)
+		BN_free(bn_te);
+
+	return ret;
+}
+
+/*
  * rsa_get_params(): - Get the important parameters of an RSA public key
  */
-int rsa_get_params(RSA *key, uint32_t *n0_invp, BIGNUM **modulusp,
-		   BIGNUM **r_squaredp)
+int rsa_get_params(RSA *key, uint64_t *exponent, uint32_t *n0_invp,
+		   BIGNUM **modulusp, BIGNUM **r_squaredp)
 {
 	BIGNUM *big1, *big2, *big32, *big2_32;
 	BIGNUM *n, *r, *r_squared, *tmp;
@@ -286,6 +334,9 @@
 		return -ENOMEM;
 	}
 
+	if (0 != rsa_get_exponent(key, exponent))
+		ret = -1;
+
 	if (!BN_copy(n, key->n) || !BN_set_word(big1, 1L) ||
 	    !BN_set_word(big2, 2L) || !BN_set_word(big32, 32L))
 		ret = -1;
@@ -386,6 +437,7 @@
 int rsa_add_verify_data(struct image_sign_info *info, void *keydest)
 {
 	BIGNUM *modulus, *r_squared;
+	uint64_t exponent;
 	uint32_t n0_inv;
 	int parent, node;
 	char name[100];
@@ -397,7 +449,7 @@
 	ret = rsa_get_pub_key(info->keydir, info->keyname, &rsa);
 	if (ret)
 		return ret;
-	ret = rsa_get_params(rsa, &n0_inv, &modulus, &r_squared);
+	ret = rsa_get_params(rsa, &exponent, &n0_inv, &modulus, &r_squared);
 	if (ret)
 		return ret;
 	bits = BN_num_bits(modulus);
@@ -442,6 +494,9 @@
 	if (!ret)
 		ret = fdt_setprop_u32(keydest, node, "rsa,n0-inverse", n0_inv);
 	if (!ret) {
+		ret = fdt_setprop_u64(keydest, node, "rsa,exponent", exponent);
+	}
+	if (!ret) {
 		ret = fdt_add_bignum(keydest, node, "rsa,modulus", modulus,
 				     bits);
 	}
diff --git a/lib/rsa/rsa-verify.c b/lib/rsa/rsa-verify.c
index bcb9063..4ef19b6 100644
--- a/lib/rsa/rsa-verify.c
+++ b/lib/rsa/rsa-verify.c
@@ -26,6 +26,9 @@
 #define get_unaligned_be32(a) fdt32_to_cpu(*(uint32_t *)a)
 #define put_unaligned_be32(a, b) (*(uint32_t *)(b) = cpu_to_fdt32(a))
 
+/* Default public exponent for backward compatibility */
+#define RSA_DEFAULT_PUBEXP	65537
+
 /**
  * subtract_modulus() - subtract modulus from the given value
  *
@@ -54,9 +57,9 @@
 static int greater_equal_modulus(const struct rsa_public_key *key,
 				 uint32_t num[])
 {
-	uint32_t i;
+	int i;
 
-	for (i = key->len - 1; i >= 0; i--) {
+	for (i = (int)key->len - 1; i >= 0; i--) {
 		if (num[i] < key->modulus[i])
 			return 0;
 		if (num[i] > key->modulus[i])
@@ -123,6 +126,48 @@
 }
 
 /**
+ * num_pub_exponent_bits() - Number of bits in the public exponent
+ *
+ * @key:	RSA key
+ * @num_bits:	Storage for the number of public exponent bits
+ */
+static int num_public_exponent_bits(const struct rsa_public_key *key,
+		int *num_bits)
+{
+	uint64_t exponent;
+	int exponent_bits;
+	const uint max_bits = (sizeof(exponent) * 8);
+
+	exponent = key->exponent;
+	exponent_bits = 0;
+
+	if (!exponent) {
+		*num_bits = exponent_bits;
+		return 0;
+	}
+
+	for (exponent_bits = 1; exponent_bits < max_bits + 1; ++exponent_bits)
+		if (!(exponent >>= 1)) {
+			*num_bits = exponent_bits;
+			return 0;
+		}
+
+	return -EINVAL;
+}
+
+/**
+ * is_public_exponent_bit_set() - Check if a bit in the public exponent is set
+ *
+ * @key:	RSA key
+ * @pos:	The bit position to check
+ */
+static int is_public_exponent_bit_set(const struct rsa_public_key *key,
+		int pos)
+{
+	return key->exponent & (1ULL << pos);
+}
+
+/**
  * pow_mod() - in-place public exponentiation
  *
  * @key:	RSA key
@@ -132,6 +177,7 @@
 {
 	uint32_t *result, *ptr;
 	uint i;
+	int j, k;
 
 	/* Sanity check for stack size - key->len is in 32-bit words */
 	if (key->len > RSA_MAX_KEY_BITS / 32) {
@@ -141,18 +187,48 @@
 	}
 
 	uint32_t val[key->len], acc[key->len], tmp[key->len];
+	uint32_t a_scaled[key->len];
 	result = tmp;  /* Re-use location. */
 
 	/* Convert from big endian byte array to little endian word array. */
 	for (i = 0, ptr = inout + key->len - 1; i < key->len; i++, ptr--)
 		val[i] = get_unaligned_be32(ptr);
 
+	if (0 != num_public_exponent_bits(key, &k))
+		return -EINVAL;
+
+	if (k < 2) {
+		debug("Public exponent is too short (%d bits, minimum 2)\n",
+		      k);
+		return -EINVAL;
+	}
+
+	if (!is_public_exponent_bit_set(key, 0)) {
+		debug("LSB of RSA public exponent must be set.\n");
+		return -EINVAL;
+	}
+
+	/* the bit at e[k-1] is 1 by definition, so start with: C := M */
+	montgomery_mul(key, acc, val, key->rr); /* acc = a * RR / R mod n */
+	/* retain scaled version for intermediate use */
+	memcpy(a_scaled, acc, key->len * sizeof(a_scaled[0]));
+
-	montgomery_mul(key, acc, val, key->rr);  /* axx = a * RR / R mod M */
-	for (i = 0; i < 16; i += 2) {
-		montgomery_mul(key, tmp, acc, acc); /* tmp = acc^2 / R mod M */
-		montgomery_mul(key, acc, tmp, tmp); /* acc = tmp^2 / R mod M */
+	for (j = k - 2; j > 0; --j) {
+		montgomery_mul(key, tmp, acc, acc); /* tmp = acc^2 / R mod n */
+
+		if (is_public_exponent_bit_set(key, j)) {
+			/* acc = tmp * val / R mod n */
+			montgomery_mul(key, acc, tmp, a_scaled);
+		} else {
+			/* e[j] == 0, copy tmp back to acc for next operation */
+			memcpy(acc, tmp, key->len * sizeof(acc[0]));
+		}
 	}
-	montgomery_mul(key, result, acc, val);  /* result = XX * a / R mod M */
+
+	/* the bit at e[0] is always 1 */
+	montgomery_mul(key, tmp, acc, acc); /* tmp = acc^2 / R mod n */
+	montgomery_mul(key, acc, tmp, val); /* acc = tmp * a / R mod M */
+	memcpy(result, acc, key->len * sizeof(result[0]));
 
 	/* Make sure result < mod; result is at most 1x mod too large. */
 	if (greater_equal_modulus(key, result))
@@ -229,6 +305,8 @@
 	const void *blob = info->fdt_blob;
 	struct rsa_public_key key;
 	const void *modulus, *rr;
+	const uint64_t *public_exponent;
+	int length;
 	int ret;
 
 	if (node < 0) {
@@ -241,6 +319,11 @@
 	}
 	key.len = fdtdec_get_int(blob, node, "rsa,num-bits", 0);
 	key.n0inv = fdtdec_get_int(blob, node, "rsa,n0-inverse", 0);
+	public_exponent = fdt_getprop(blob, node, "rsa,exponent", &length);
+	if (!public_exponent || length < sizeof(*public_exponent))
+		key.exponent = RSA_DEFAULT_PUBEXP;
+	else
+		key.exponent = fdt64_to_cpu(*public_exponent);
 	modulus = fdt_getprop(blob, node, "rsa,modulus", NULL);
 	rr = fdt_getprop(blob, node, "rsa,r-squared", NULL);
 	if (!key.len || !modulus || !rr) {
diff --git a/net/bootp.c b/net/bootp.c
index fdb97cb..a4f6db5 100644
--- a/net/bootp.c
+++ b/net/bootp.c
@@ -23,12 +23,22 @@
 
 #define BOOTP_VENDOR_MAGIC	0x63825363	/* RFC1048 Magic Cookie */
 
-#define TIMEOUT		5000UL	/* Milliseconds before trying BOOTP again */
+/*
+ * The timeout for the initial BOOTP/DHCP request used to be described by a
+ * counter of fixed-length timeout periods. TIMEOUT_COUNT represents
+ * that counter
+ *
+ * Now that the timeout periods are variable (exponential backoff and retry)
+ * we convert the timeout count to the absolute time it would have take to
+ * execute that many retries, and keep sending retry packets until that time
+ * is reached.
+ */
 #ifndef CONFIG_NET_RETRY_COUNT
 # define TIMEOUT_COUNT	5		/* # of timeouts before giving up */
 #else
 # define TIMEOUT_COUNT	(CONFIG_NET_RETRY_COUNT)
 #endif
+#define TIMEOUT_MS	((3 + (TIMEOUT_COUNT * 5)) * 1000)
 
 #define PORT_BOOTPS	67		/* BOOTP server UDP port */
 #define PORT_BOOTPC	68		/* BOOTP client UDP port */
@@ -39,6 +49,8 @@
 
 ulong		BootpID;
 int		BootpTry;
+ulong		bootp_start;
+ulong		bootp_timeout;
 
 #if defined(CONFIG_CMD_DHCP)
 static dhcp_state_t dhcp_state = INIT;
@@ -327,16 +339,21 @@
 static void
 BootpTimeout(void)
 {
-	if (BootpTry >= TIMEOUT_COUNT) {
+	ulong time_taken = get_timer(bootp_start);
+
+	if (time_taken >= TIMEOUT_MS) {
 #ifdef CONFIG_BOOTP_MAY_FAIL
-		puts("\nRetry count exceeded\n");
+		puts("\nRetry time exceeded\n");
 		net_set_state(NETLOOP_FAIL);
 #else
-		puts("\nRetry count exceeded; starting again\n");
+		puts("\nRetry time exceeded; starting again\n");
 		NetStartAgain();
 #endif
 	} else {
-		NetSetTimeout(TIMEOUT, BootpTimeout);
+		bootp_timeout *= 2;
+		if (bootp_timeout > 1000)
+			bootp_timeout = 1000;
+		NetSetTimeout(bootp_timeout, BootpTimeout);
 		BootpRequest();
 	}
 }
@@ -597,6 +614,13 @@
 }
 #endif
 
+void BootpReset(void)
+{
+	BootpTry = 0;
+	bootp_start = get_timer(0);
+	bootp_timeout = 10;
+}
+
 void
 BootpRequest(void)
 {
@@ -685,7 +709,7 @@
 	iplen = BOOTP_HDR_SIZE - OPT_FIELD_SIZE + extlen;
 	pktlen = eth_hdr_size + IP_UDP_HDR_SIZE + iplen;
 	net_set_udp_header(iphdr, 0xFFFFFFFFL, PORT_BOOTPS, PORT_BOOTPC, iplen);
-	NetSetTimeout(SELECT_TIMEOUT, BootpTimeout);
+	NetSetTimeout(bootp_timeout, BootpTimeout);
 
 #if defined(CONFIG_CMD_DHCP)
 	dhcp_state = SELECTING;
@@ -918,7 +942,7 @@
 						htonl(BOOTP_VENDOR_MAGIC))
 				DhcpOptionsProcess((u8 *)&bp->bp_vend[4], bp);
 
-			NetSetTimeout(TIMEOUT, BootpTimeout);
+			NetSetTimeout(5000, BootpTimeout);
 			DhcpSendRequestPkt(bp);
 #ifdef CONFIG_SYS_BOOTFILE_PREFIX
 		}
diff --git a/net/bootp.h b/net/bootp.h
index ecbcc4d..3b95a0a 100644
--- a/net/bootp.h
+++ b/net/bootp.h
@@ -65,6 +65,7 @@
 
 
 /* Send a BOOTP request */
+extern void BootpReset(void);
 extern void BootpRequest(void);
 
 /****************** DHCP Support *********************/
@@ -88,8 +89,6 @@
 #define DHCP_NAK      6
 #define DHCP_RELEASE  7
 
-#define SELECT_TIMEOUT 3000UL	/* Milliseconds to wait for offers */
-
 /**********************************************************************/
 
 #endif /* __BOOTP_H__ */
diff --git a/net/net.c b/net/net.c
index 0f7625f..722089f 100644
--- a/net/net.c
+++ b/net/net.c
@@ -385,14 +385,14 @@
 #endif
 #if defined(CONFIG_CMD_DHCP)
 		case DHCP:
-			BootpTry = 0;
+			BootpReset();
 			NetOurIP = 0;
 			DhcpRequest();		/* Basically same as BOOTP */
 			break;
 #endif
 
 		case BOOTP:
-			BootpTry = 0;
+			BootpReset();
 			NetOurIP = 0;
 			BootpRequest();
 			break;
diff --git a/scripts/get_maintainer.pl b/scripts/get_maintainer.pl
new file mode 100755
index 0000000..7717d68
--- /dev/null
+++ b/scripts/get_maintainer.pl
@@ -0,0 +1,2270 @@
+#!/usr/bin/perl -w
+# (c) 2007, Joe Perches <joe@perches.com>
+#           created from checkpatch.pl
+#
+# Print selected MAINTAINERS information for
+# the files modified in a patch or for a file
+#
+# usage: perl scripts/get_maintainer.pl [OPTIONS] <patch>
+#        perl scripts/get_maintainer.pl [OPTIONS] -f <file>
+#
+# Licensed under the terms of the GNU GPL License version 2
+
+use strict;
+
+my $P = $0;
+my $V = '0.26';
+
+use Getopt::Long qw(:config no_auto_abbrev);
+use File::Find;
+
+my $lk_path = "./";
+my $email = 1;
+my $email_usename = 1;
+my $email_maintainer = 1;
+my $email_list = 1;
+my $email_subscriber_list = 0;
+my $email_git_penguin_chiefs = 0;
+my $email_git = 0;
+my $email_git_all_signature_types = 0;
+my $email_git_blame = 0;
+my $email_git_blame_signatures = 1;
+my $email_git_fallback = 1;
+my $email_git_min_signatures = 1;
+my $email_git_max_maintainers = 5;
+my $email_git_min_percent = 5;
+my $email_git_since = "1-year-ago";
+my $email_hg_since = "-365";
+my $interactive = 0;
+my $email_remove_duplicates = 1;
+my $email_use_mailmap = 1;
+my $output_multiline = 1;
+my $output_separator = ", ";
+my $output_roles = 0;
+my $output_rolestats = 1;
+my $scm = 0;
+my $web = 0;
+my $subsystem = 0;
+my $status = 0;
+my $keywords = 1;
+my $sections = 0;
+my $file_emails = 0;
+my $from_filename = 0;
+my $pattern_depth = 0;
+my $version = 0;
+my $help = 0;
+
+my $vcs_used = 0;
+
+my $exit = 0;
+
+my %commit_author_hash;
+my %commit_signer_hash;
+
+my @penguin_chief = ();
+push(@penguin_chief, "Tom Rini:trini\@ti.com");
+
+my @penguin_chief_names = ();
+foreach my $chief (@penguin_chief) {
+    if ($chief =~ m/^(.*):(.*)/) {
+	my $chief_name = $1;
+	my $chief_addr = $2;
+	push(@penguin_chief_names, $chief_name);
+    }
+}
+my $penguin_chiefs = "\(" . join("|", @penguin_chief_names) . "\)";
+
+# Signature types of people who are either
+# 	a) responsible for the code in question, or
+# 	b) familiar enough with it to give relevant feedback
+my @signature_tags = ();
+push(@signature_tags, "Signed-off-by:");
+push(@signature_tags, "Reviewed-by:");
+push(@signature_tags, "Acked-by:");
+
+my $signature_pattern = "\(" . join("|", @signature_tags) . "\)";
+
+# rfc822 email address - preloaded methods go here.
+my $rfc822_lwsp = "(?:(?:\\r\\n)?[ \\t])";
+my $rfc822_char = '[\\000-\\377]';
+
+# VCS command support: class-like functions and strings
+
+my %VCS_cmds;
+
+my %VCS_cmds_git = (
+    "execute_cmd" => \&git_execute_cmd,
+    "available" => '(which("git") ne "") && (-e ".git")',
+    "find_signers_cmd" =>
+	"git log --no-color --follow --since=\$email_git_since " .
+	    '--numstat --no-merges ' .
+	    '--format="GitCommit: %H%n' .
+		      'GitAuthor: %an <%ae>%n' .
+		      'GitDate: %aD%n' .
+		      'GitSubject: %s%n' .
+		      '%b%n"' .
+	    " -- \$file",
+    "find_commit_signers_cmd" =>
+	"git log --no-color " .
+	    '--numstat ' .
+	    '--format="GitCommit: %H%n' .
+		      'GitAuthor: %an <%ae>%n' .
+		      'GitDate: %aD%n' .
+		      'GitSubject: %s%n' .
+		      '%b%n"' .
+	    " -1 \$commit",
+    "find_commit_author_cmd" =>
+	"git log --no-color " .
+	    '--numstat ' .
+	    '--format="GitCommit: %H%n' .
+		      'GitAuthor: %an <%ae>%n' .
+		      'GitDate: %aD%n' .
+		      'GitSubject: %s%n"' .
+	    " -1 \$commit",
+    "blame_range_cmd" => "git blame -l -L \$diff_start,+\$diff_length \$file",
+    "blame_file_cmd" => "git blame -l \$file",
+    "commit_pattern" => "^GitCommit: ([0-9a-f]{40,40})",
+    "blame_commit_pattern" => "^([0-9a-f]+) ",
+    "author_pattern" => "^GitAuthor: (.*)",
+    "subject_pattern" => "^GitSubject: (.*)",
+    "stat_pattern" => "^(\\d+)\\t(\\d+)\\t\$file\$",
+);
+
+my %VCS_cmds_hg = (
+    "execute_cmd" => \&hg_execute_cmd,
+    "available" => '(which("hg") ne "") && (-d ".hg")',
+    "find_signers_cmd" =>
+	"hg log --date=\$email_hg_since " .
+	    "--template='HgCommit: {node}\\n" .
+	                "HgAuthor: {author}\\n" .
+			"HgSubject: {desc}\\n'" .
+	    " -- \$file",
+    "find_commit_signers_cmd" =>
+	"hg log " .
+	    "--template='HgSubject: {desc}\\n'" .
+	    " -r \$commit",
+    "find_commit_author_cmd" =>
+	"hg log " .
+	    "--template='HgCommit: {node}\\n" .
+		        "HgAuthor: {author}\\n" .
+			"HgSubject: {desc|firstline}\\n'" .
+	    " -r \$commit",
+    "blame_range_cmd" => "",		# not supported
+    "blame_file_cmd" => "hg blame -n \$file",
+    "commit_pattern" => "^HgCommit: ([0-9a-f]{40,40})",
+    "blame_commit_pattern" => "^([ 0-9a-f]+):",
+    "author_pattern" => "^HgAuthor: (.*)",
+    "subject_pattern" => "^HgSubject: (.*)",
+    "stat_pattern" => "^(\\d+)\t(\\d+)\t\$file\$",
+);
+
+my $conf = which_conf(".get_maintainer.conf");
+if (-f $conf) {
+    my @conf_args;
+    open(my $conffile, '<', "$conf")
+	or warn "$P: Can't find a readable .get_maintainer.conf file $!\n";
+
+    while (<$conffile>) {
+	my $line = $_;
+
+	$line =~ s/\s*\n?$//g;
+	$line =~ s/^\s*//g;
+	$line =~ s/\s+/ /g;
+
+	next if ($line =~ m/^\s*#/);
+	next if ($line =~ m/^\s*$/);
+
+	my @words = split(" ", $line);
+	foreach my $word (@words) {
+	    last if ($word =~ m/^#/);
+	    push (@conf_args, $word);
+	}
+    }
+    close($conffile);
+    unshift(@ARGV, @conf_args) if @conf_args;
+}
+
+if (!GetOptions(
+		'email!' => \$email,
+		'git!' => \$email_git,
+		'git-all-signature-types!' => \$email_git_all_signature_types,
+		'git-blame!' => \$email_git_blame,
+		'git-blame-signatures!' => \$email_git_blame_signatures,
+		'git-fallback!' => \$email_git_fallback,
+		'git-chief-penguins!' => \$email_git_penguin_chiefs,
+		'git-min-signatures=i' => \$email_git_min_signatures,
+		'git-max-maintainers=i' => \$email_git_max_maintainers,
+		'git-min-percent=i' => \$email_git_min_percent,
+		'git-since=s' => \$email_git_since,
+		'hg-since=s' => \$email_hg_since,
+		'i|interactive!' => \$interactive,
+		'remove-duplicates!' => \$email_remove_duplicates,
+		'mailmap!' => \$email_use_mailmap,
+		'm!' => \$email_maintainer,
+		'n!' => \$email_usename,
+		'l!' => \$email_list,
+		's!' => \$email_subscriber_list,
+		'multiline!' => \$output_multiline,
+		'roles!' => \$output_roles,
+		'rolestats!' => \$output_rolestats,
+		'separator=s' => \$output_separator,
+		'subsystem!' => \$subsystem,
+		'status!' => \$status,
+		'scm!' => \$scm,
+		'web!' => \$web,
+		'pattern-depth=i' => \$pattern_depth,
+		'k|keywords!' => \$keywords,
+		'sections!' => \$sections,
+		'fe|file-emails!' => \$file_emails,
+		'f|file' => \$from_filename,
+		'v|version' => \$version,
+		'h|help|usage' => \$help,
+		)) {
+    die "$P: invalid argument - use --help if necessary\n";
+}
+
+if ($help != 0) {
+    usage();
+    exit 0;
+}
+
+if ($version != 0) {
+    print("${P} ${V}\n");
+    exit 0;
+}
+
+if (-t STDIN && !@ARGV) {
+    # We're talking to a terminal, but have no command line arguments.
+    die "$P: missing patchfile or -f file - use --help if necessary\n";
+}
+
+$output_multiline = 0 if ($output_separator ne ", ");
+$output_rolestats = 1 if ($interactive);
+$output_roles = 1 if ($output_rolestats);
+
+if ($sections) {
+    $email = 0;
+    $email_list = 0;
+    $scm = 0;
+    $status = 0;
+    $subsystem = 0;
+    $web = 0;
+    $keywords = 0;
+    $interactive = 0;
+} else {
+    my $selections = $email + $scm + $status + $subsystem + $web;
+    if ($selections == 0) {
+	die "$P:  Missing required option: email, scm, status, subsystem or web\n";
+    }
+}
+
+if ($email &&
+    ($email_maintainer + $email_list + $email_subscriber_list +
+     $email_git + $email_git_penguin_chiefs + $email_git_blame) == 0) {
+    die "$P: Please select at least 1 email option\n";
+}
+
+if (!top_of_kernel_tree($lk_path)) {
+    die "$P: The current directory does not appear to be "
+	. "a linux kernel source tree.\n";
+}
+
+## Read MAINTAINERS for type/value pairs
+
+my @typevalue = ();
+my %keyword_hash;
+
+my @maint_files = ();
+push(@maint_files, "${lk_path}MAINTAINERS");
+
+sub maint_wanted {
+    return unless $_ =~ /^MAINTAINERS/;
+    push(@maint_files, "$File::Find::name");
+}
+
+File::Find::find(\&maint_wanted, "${lk_path}board");
+
+foreach my $maint_file (@maint_files) {
+    my $maint;
+    open ($maint, '<', "$maint_file")
+	or die "$P: Can't open $maint_file: $!\n";
+    read_maintainers($maint);
+    close($maint);
+}
+
+sub read_maintainers {
+    my ($maint) = @_;
+
+    while (<$maint>) {
+	my $line = $_;
+
+	if ($line =~ m/^(\C):\s*(.*)/) {
+	    my $type = $1;
+	    my $value = $2;
+
+	    ##Filename pattern matching
+	    if ($type eq "F" || $type eq "X") {
+		$value =~ s@\.@\\\.@g;       ##Convert . to \.
+		$value =~ s/\*/\.\*/g;       ##Convert * to .*
+		$value =~ s/\?/\./g;         ##Convert ? to .
+		##if pattern is a directory and it lacks a trailing slash, add one
+		if ((-d $value)) {
+		    $value =~ s@([^/])$@$1/@;
+		}
+	    } elsif ($type eq "K") {
+		$keyword_hash{@typevalue} = $value;
+	    }
+	    push(@typevalue, "$type:$value");
+	} elsif (!/^(\s)*$/) {
+	    $line =~ s/\n$//g;
+	    push(@typevalue, $line);
+	}
+    }
+}
+
+
+#
+# Read mail address map
+#
+
+my $mailmap;
+
+read_mailmap();
+
+sub read_mailmap {
+    $mailmap = {
+	names => {},
+	addresses => {}
+    };
+
+    return if (!$email_use_mailmap || !(-f "${lk_path}.mailmap"));
+
+    open(my $mailmap_file, '<', "${lk_path}.mailmap")
+	or warn "$P: Can't open .mailmap: $!\n";
+
+    while (<$mailmap_file>) {
+	s/#.*$//; #strip comments
+	s/^\s+|\s+$//g; #trim
+
+	next if (/^\s*$/); #skip empty lines
+	#entries have one of the following formats:
+	# name1 <mail1>
+	# <mail1> <mail2>
+	# name1 <mail1> <mail2>
+	# name1 <mail1> name2 <mail2>
+	# (see man git-shortlog)
+
+	if (/^([^<]+)<([^>]+)>$/) {
+	    my $real_name = $1;
+	    my $address = $2;
+
+	    $real_name =~ s/\s+$//;
+	    ($real_name, $address) = parse_email("$real_name <$address>");
+	    $mailmap->{names}->{$address} = $real_name;
+
+	} elsif (/^<([^>]+)>\s*<([^>]+)>$/) {
+	    my $real_address = $1;
+	    my $wrong_address = $2;
+
+	    $mailmap->{addresses}->{$wrong_address} = $real_address;
+
+	} elsif (/^(.+)<([^>]+)>\s*<([^>]+)>$/) {
+	    my $real_name = $1;
+	    my $real_address = $2;
+	    my $wrong_address = $3;
+
+	    $real_name =~ s/\s+$//;
+	    ($real_name, $real_address) =
+		parse_email("$real_name <$real_address>");
+	    $mailmap->{names}->{$wrong_address} = $real_name;
+	    $mailmap->{addresses}->{$wrong_address} = $real_address;
+
+	} elsif (/^(.+)<([^>]+)>\s*(.+)\s*<([^>]+)>$/) {
+	    my $real_name = $1;
+	    my $real_address = $2;
+	    my $wrong_name = $3;
+	    my $wrong_address = $4;
+
+	    $real_name =~ s/\s+$//;
+	    ($real_name, $real_address) =
+		parse_email("$real_name <$real_address>");
+
+	    $wrong_name =~ s/\s+$//;
+	    ($wrong_name, $wrong_address) =
+		parse_email("$wrong_name <$wrong_address>");
+
+	    my $wrong_email = format_email($wrong_name, $wrong_address, 1);
+	    $mailmap->{names}->{$wrong_email} = $real_name;
+	    $mailmap->{addresses}->{$wrong_email} = $real_address;
+	}
+    }
+    close($mailmap_file);
+}
+
+## use the filenames on the command line or find the filenames in the patchfiles
+
+my @files = ();
+my @range = ();
+my @keyword_tvi = ();
+my @file_emails = ();
+
+if (!@ARGV) {
+    push(@ARGV, "&STDIN");
+}
+
+foreach my $file (@ARGV) {
+    if ($file ne "&STDIN") {
+	##if $file is a directory and it lacks a trailing slash, add one
+	if ((-d $file)) {
+	    $file =~ s@([^/])$@$1/@;
+	} elsif (!(-f $file)) {
+	    die "$P: file '${file}' not found\n";
+	}
+    }
+    if ($from_filename) {
+	push(@files, $file);
+	if ($file ne "MAINTAINERS" && -f $file && ($keywords || $file_emails)) {
+	    open(my $f, '<', $file)
+		or die "$P: Can't open $file: $!\n";
+	    my $text = do { local($/) ; <$f> };
+	    close($f);
+	    if ($keywords) {
+		foreach my $line (keys %keyword_hash) {
+		    if ($text =~ m/$keyword_hash{$line}/x) {
+			push(@keyword_tvi, $line);
+		    }
+		}
+	    }
+	    if ($file_emails) {
+		my @poss_addr = $text =~ m$[A-Za-zÀ-ÿ\"\' \,\.\+-]*\s*[\,]*\s*[\(\<\{]{0,1}[A-Za-z0-9_\.\+-]+\@[A-Za-z0-9\.-]+\.[A-Za-z0-9]+[\)\>\}]{0,1}$g;
+		push(@file_emails, clean_file_emails(@poss_addr));
+	    }
+	}
+    } else {
+	my $file_cnt = @files;
+	my $lastfile;
+
+	open(my $patch, "< $file")
+	    or die "$P: Can't open $file: $!\n";
+
+	# We can check arbitrary information before the patch
+	# like the commit message, mail headers, etc...
+	# This allows us to match arbitrary keywords against any part
+	# of a git format-patch generated file (subject tags, etc...)
+
+	my $patch_prefix = "";			#Parsing the intro
+
+	while (<$patch>) {
+	    my $patch_line = $_;
+	    if (m/^\+\+\+\s+(\S+)/ or m/^---\s+(\S+)/) {
+		my $filename = $1;
+		$filename =~ s@^[^/]*/@@;
+		$filename =~ s@\n@@;
+		$lastfile = $filename;
+		push(@files, $filename);
+		$patch_prefix = "^[+-].*";	#Now parsing the actual patch
+	    } elsif (m/^\@\@ -(\d+),(\d+)/) {
+		if ($email_git_blame) {
+		    push(@range, "$lastfile:$1:$2");
+		}
+	    } elsif ($keywords) {
+		foreach my $line (keys %keyword_hash) {
+		    if ($patch_line =~ m/${patch_prefix}$keyword_hash{$line}/x) {
+			push(@keyword_tvi, $line);
+		    }
+		}
+	    }
+	}
+	close($patch);
+
+	if ($file_cnt == @files) {
+	    warn "$P: file '${file}' doesn't appear to be a patch.  "
+		. "Add -f to options?\n";
+	}
+	@files = sort_and_uniq(@files);
+    }
+}
+
+@file_emails = uniq(@file_emails);
+
+my %email_hash_name;
+my %email_hash_address;
+my @email_to = ();
+my %hash_list_to;
+my @list_to = ();
+my @scm = ();
+my @web = ();
+my @subsystem = ();
+my @status = ();
+my %deduplicate_name_hash = ();
+my %deduplicate_address_hash = ();
+
+my @maintainers = get_maintainers();
+
+if (@maintainers) {
+    @maintainers = merge_email(@maintainers);
+    output(@maintainers);
+}
+
+if ($scm) {
+    @scm = uniq(@scm);
+    output(@scm);
+}
+
+if ($status) {
+    @status = uniq(@status);
+    output(@status);
+}
+
+if ($subsystem) {
+    @subsystem = uniq(@subsystem);
+    output(@subsystem);
+}
+
+if ($web) {
+    @web = uniq(@web);
+    output(@web);
+}
+
+exit($exit);
+
+sub range_is_maintained {
+    my ($start, $end) = @_;
+
+    for (my $i = $start; $i < $end; $i++) {
+	my $line = $typevalue[$i];
+	if ($line =~ m/^(\C):\s*(.*)/) {
+	    my $type = $1;
+	    my $value = $2;
+	    if ($type eq 'S') {
+		if ($value =~ /(maintain|support)/i) {
+		    return 1;
+		}
+	    }
+	}
+    }
+    return 0;
+}
+
+sub range_has_maintainer {
+    my ($start, $end) = @_;
+
+    for (my $i = $start; $i < $end; $i++) {
+	my $line = $typevalue[$i];
+	if ($line =~ m/^(\C):\s*(.*)/) {
+	    my $type = $1;
+	    my $value = $2;
+	    if ($type eq 'M') {
+		return 1;
+	    }
+	}
+    }
+    return 0;
+}
+
+sub get_maintainers {
+    %email_hash_name = ();
+    %email_hash_address = ();
+    %commit_author_hash = ();
+    %commit_signer_hash = ();
+    @email_to = ();
+    %hash_list_to = ();
+    @list_to = ();
+    @scm = ();
+    @web = ();
+    @subsystem = ();
+    @status = ();
+    %deduplicate_name_hash = ();
+    %deduplicate_address_hash = ();
+    if ($email_git_all_signature_types) {
+	$signature_pattern = "(.+?)[Bb][Yy]:";
+    } else {
+	$signature_pattern = "\(" . join("|", @signature_tags) . "\)";
+    }
+
+    # Find responsible parties
+
+    my %exact_pattern_match_hash = ();
+
+    foreach my $file (@files) {
+
+	my %hash;
+	my $tvi = find_first_section();
+	while ($tvi < @typevalue) {
+	    my $start = find_starting_index($tvi);
+	    my $end = find_ending_index($tvi);
+	    my $exclude = 0;
+	    my $i;
+
+	    #Do not match excluded file patterns
+
+	    for ($i = $start; $i < $end; $i++) {
+		my $line = $typevalue[$i];
+		if ($line =~ m/^(\C):\s*(.*)/) {
+		    my $type = $1;
+		    my $value = $2;
+		    if ($type eq 'X') {
+			if (file_match_pattern($file, $value)) {
+			    $exclude = 1;
+			    last;
+			}
+		    }
+		}
+	    }
+
+	    if (!$exclude) {
+		for ($i = $start; $i < $end; $i++) {
+		    my $line = $typevalue[$i];
+		    if ($line =~ m/^(\C):\s*(.*)/) {
+			my $type = $1;
+			my $value = $2;
+			if ($type eq 'F') {
+			    if (file_match_pattern($file, $value)) {
+				my $value_pd = ($value =~ tr@/@@);
+				my $file_pd = ($file  =~ tr@/@@);
+				$value_pd++ if (substr($value,-1,1) ne "/");
+				$value_pd = -1 if ($value =~ /^\.\*/);
+				if ($value_pd >= $file_pd &&
+				    range_is_maintained($start, $end) &&
+				    range_has_maintainer($start, $end)) {
+				    $exact_pattern_match_hash{$file} = 1;
+				}
+				if ($pattern_depth == 0 ||
+				    (($file_pd - $value_pd) < $pattern_depth)) {
+				    $hash{$tvi} = $value_pd;
+				}
+			    }
+			} elsif ($type eq 'N') {
+			    if ($file =~ m/$value/x) {
+				$hash{$tvi} = 0;
+			    }
+			}
+		    }
+		}
+	    }
+	    $tvi = $end + 1;
+	}
+
+	foreach my $line (sort {$hash{$b} <=> $hash{$a}} keys %hash) {
+	    add_categories($line);
+	    if ($sections) {
+		my $i;
+		my $start = find_starting_index($line);
+		my $end = find_ending_index($line);
+		for ($i = $start; $i < $end; $i++) {
+		    my $line = $typevalue[$i];
+		    if ($line =~ /^[FX]:/) {		##Restore file patterns
+			$line =~ s/([^\\])\.([^\*])/$1\?$2/g;
+			$line =~ s/([^\\])\.$/$1\?/g;	##Convert . back to ?
+			$line =~ s/\\\./\./g;       	##Convert \. to .
+			$line =~ s/\.\*/\*/g;       	##Convert .* to *
+		    }
+		    $line =~ s/^([A-Z]):/$1:\t/g;
+		    print("$line\n");
+		}
+		print("\n");
+	    }
+	}
+    }
+
+    if ($keywords) {
+	@keyword_tvi = sort_and_uniq(@keyword_tvi);
+	foreach my $line (@keyword_tvi) {
+	    add_categories($line);
+	}
+    }
+
+    foreach my $email (@email_to, @list_to) {
+	$email->[0] = deduplicate_email($email->[0]);
+    }
+
+    foreach my $file (@files) {
+	if ($email &&
+	    ($email_git || ($email_git_fallback &&
+			    !$exact_pattern_match_hash{$file}))) {
+	    vcs_file_signoffs($file);
+	}
+	if ($email && $email_git_blame) {
+	    vcs_file_blame($file);
+	}
+    }
+
+    if ($email) {
+	foreach my $chief (@penguin_chief) {
+	    if ($chief =~ m/^(.*):(.*)/) {
+		my $email_address;
+
+		$email_address = format_email($1, $2, $email_usename);
+		if ($email_git_penguin_chiefs) {
+		    push(@email_to, [$email_address, 'chief penguin']);
+		} else {
+		    @email_to = grep($_->[0] !~ /${email_address}/, @email_to);
+		}
+	    }
+	}
+
+	foreach my $email (@file_emails) {
+	    my ($name, $address) = parse_email($email);
+
+	    my $tmp_email = format_email($name, $address, $email_usename);
+	    push_email_address($tmp_email, '');
+	    add_role($tmp_email, 'in file');
+	}
+    }
+
+    my @to = ();
+    if ($email || $email_list) {
+	if ($email) {
+	    @to = (@to, @email_to);
+	}
+	if ($email_list) {
+	    @to = (@to, @list_to);
+	}
+    }
+
+    if ($interactive) {
+	@to = interactive_get_maintainers(\@to);
+    }
+
+    return @to;
+}
+
+sub file_match_pattern {
+    my ($file, $pattern) = @_;
+    if (substr($pattern, -1) eq "/") {
+	if ($file =~ m@^$pattern@) {
+	    return 1;
+	}
+    } else {
+	if ($file =~ m@^$pattern@) {
+	    my $s1 = ($file =~ tr@/@@);
+	    my $s2 = ($pattern =~ tr@/@@);
+	    if ($s1 == $s2) {
+		return 1;
+	    }
+	}
+    }
+    return 0;
+}
+
+sub usage {
+    print <<EOT;
+usage: $P [options] patchfile
+       $P [options] -f file|directory
+version: $V
+
+MAINTAINER field selection options:
+  --email => print email address(es) if any
+    --git => include recent git \*-by: signers
+    --git-all-signature-types => include signers regardless of signature type
+        or use only ${signature_pattern} signers (default: $email_git_all_signature_types)
+    --git-fallback => use git when no exact MAINTAINERS pattern (default: $email_git_fallback)
+    --git-chief-penguins => include ${penguin_chiefs}
+    --git-min-signatures => number of signatures required (default: $email_git_min_signatures)
+    --git-max-maintainers => maximum maintainers to add (default: $email_git_max_maintainers)
+    --git-min-percent => minimum percentage of commits required (default: $email_git_min_percent)
+    --git-blame => use git blame to find modified commits for patch or file
+    --git-since => git history to use (default: $email_git_since)
+    --hg-since => hg history to use (default: $email_hg_since)
+    --interactive => display a menu (mostly useful if used with the --git option)
+    --m => include maintainer(s) if any
+    --n => include name 'Full Name <addr\@domain.tld>'
+    --l => include list(s) if any
+    --s => include subscriber only list(s) if any
+    --remove-duplicates => minimize duplicate email names/addresses
+    --roles => show roles (status:subsystem, git-signer, list, etc...)
+    --rolestats => show roles and statistics (commits/total_commits, %)
+    --file-emails => add email addresses found in -f file (default: 0 (off))
+  --scm => print SCM tree(s) if any
+  --status => print status if any
+  --subsystem => print subsystem name if any
+  --web => print website(s) if any
+
+Output type options:
+  --separator [, ] => separator for multiple entries on 1 line
+    using --separator also sets --nomultiline if --separator is not [, ]
+  --multiline => print 1 entry per line
+
+Other options:
+  --pattern-depth => Number of pattern directory traversals (default: 0 (all))
+  --keywords => scan patch for keywords (default: $keywords)
+  --sections => print all of the subsystem sections with pattern matches
+  --mailmap => use .mailmap file (default: $email_use_mailmap)
+  --version => show version
+  --help => show this help information
+
+Default options:
+  [--email --nogit --git-fallback --m --n --l --multiline -pattern-depth=0
+   --remove-duplicates --rolestats]
+
+Notes:
+  Using "-f directory" may give unexpected results:
+      Used with "--git", git signators for _all_ files in and below
+          directory are examined as git recurses directories.
+          Any specified X: (exclude) pattern matches are _not_ ignored.
+      Used with "--nogit", directory is used as a pattern match,
+          no individual file within the directory or subdirectory
+          is matched.
+      Used with "--git-blame", does not iterate all files in directory
+  Using "--git-blame" is slow and may add old committers and authors
+      that are no longer active maintainers to the output.
+  Using "--roles" or "--rolestats" with git send-email --cc-cmd or any
+      other automated tools that expect only ["name"] <email address>
+      may not work because of additional output after <email address>.
+  Using "--rolestats" and "--git-blame" shows the #/total=% commits,
+      not the percentage of the entire file authored.  # of commits is
+      not a good measure of amount of code authored.  1 major commit may
+      contain a thousand lines, 5 trivial commits may modify a single line.
+  If git is not installed, but mercurial (hg) is installed and an .hg
+      repository exists, the following options apply to mercurial:
+          --git,
+          --git-min-signatures, --git-max-maintainers, --git-min-percent, and
+          --git-blame
+      Use --hg-since not --git-since to control date selection
+  File ".get_maintainer.conf", if it exists in the linux kernel source root
+      directory, can change whatever get_maintainer defaults are desired.
+      Entries in this file can be any command line argument.
+      This file is prepended to any additional command line arguments.
+      Multiple lines and # comments are allowed.
+EOT
+}
+
+sub top_of_kernel_tree {
+    my ($lk_path) = @_;
+
+    if ($lk_path ne "" && substr($lk_path,length($lk_path)-1,1) ne "/") {
+	$lk_path .= "/";
+    }
+    if (   (-f "${lk_path}CREDITS")
+	&& (-f "${lk_path}Kbuild")
+	&& (-f "${lk_path}MAINTAINERS")
+	&& (-f "${lk_path}Makefile")
+	&& (-f "${lk_path}README")
+	&& (-d "${lk_path}arch")
+	&& (-d "${lk_path}board")
+	&& (-d "${lk_path}common")
+	&& (-d "${lk_path}doc")
+	&& (-d "${lk_path}drivers")
+	&& (-d "${lk_path}dts")
+	&& (-d "${lk_path}fs")
+	&& (-d "${lk_path}lib")
+	&& (-d "${lk_path}include")
+	&& (-d "${lk_path}net")
+	&& (-d "${lk_path}post")
+	&& (-d "${lk_path}scripts")
+	&& (-d "${lk_path}test")
+	&& (-d "${lk_path}tools")) {
+	return 1;
+    }
+    return 0;
+}
+
+sub parse_email {
+    my ($formatted_email) = @_;
+
+    my $name = "";
+    my $address = "";
+
+    if ($formatted_email =~ /^([^<]+)<(.+\@.*)>.*$/) {
+	$name = $1;
+	$address = $2;
+    } elsif ($formatted_email =~ /^\s*<(.+\@\S*)>.*$/) {
+	$address = $1;
+    } elsif ($formatted_email =~ /^(.+\@\S*).*$/) {
+	$address = $1;
+    }
+
+    $name =~ s/^\s+|\s+$//g;
+    $name =~ s/^\"|\"$//g;
+    $address =~ s/^\s+|\s+$//g;
+
+    if ($name =~ /[^\w \-]/i) {  	 ##has "must quote" chars
+	$name =~ s/(?<!\\)"/\\"/g;       ##escape quotes
+	$name = "\"$name\"";
+    }
+
+    return ($name, $address);
+}
+
+sub format_email {
+    my ($name, $address, $usename) = @_;
+
+    my $formatted_email;
+
+    $name =~ s/^\s+|\s+$//g;
+    $name =~ s/^\"|\"$//g;
+    $address =~ s/^\s+|\s+$//g;
+
+    if ($name =~ /[^\w \-]/i) {          ##has "must quote" chars
+	$name =~ s/(?<!\\)"/\\"/g;       ##escape quotes
+	$name = "\"$name\"";
+    }
+
+    if ($usename) {
+	if ("$name" eq "") {
+	    $formatted_email = "$address";
+	} else {
+	    $formatted_email = "$name <$address>";
+	}
+    } else {
+	$formatted_email = $address;
+    }
+
+    return $formatted_email;
+}
+
+sub find_first_section {
+    my $index = 0;
+
+    while ($index < @typevalue) {
+	my $tv = $typevalue[$index];
+	if (($tv =~ m/^(\C):\s*(.*)/)) {
+	    last;
+	}
+	$index++;
+    }
+
+    return $index;
+}
+
+sub find_starting_index {
+    my ($index) = @_;
+
+    while ($index > 0) {
+	my $tv = $typevalue[$index];
+	if (!($tv =~ m/^(\C):\s*(.*)/)) {
+	    last;
+	}
+	$index--;
+    }
+
+    return $index;
+}
+
+sub find_ending_index {
+    my ($index) = @_;
+
+    while ($index < @typevalue) {
+	my $tv = $typevalue[$index];
+	if (!($tv =~ m/^(\C):\s*(.*)/)) {
+	    last;
+	}
+	$index++;
+    }
+
+    return $index;
+}
+
+sub get_maintainer_role {
+    my ($index) = @_;
+
+    my $i;
+    my $start = find_starting_index($index);
+    my $end = find_ending_index($index);
+
+    my $role = "unknown";
+    my $subsystem = $typevalue[$start];
+    if (length($subsystem) > 20) {
+	$subsystem = substr($subsystem, 0, 17);
+	$subsystem =~ s/\s*$//;
+	$subsystem = $subsystem . "...";
+    }
+
+    for ($i = $start + 1; $i < $end; $i++) {
+	my $tv = $typevalue[$i];
+	if ($tv =~ m/^(\C):\s*(.*)/) {
+	    my $ptype = $1;
+	    my $pvalue = $2;
+	    if ($ptype eq "S") {
+		$role = $pvalue;
+	    }
+	}
+    }
+
+    $role = lc($role);
+    if      ($role eq "supported") {
+	$role = "supporter";
+    } elsif ($role eq "maintained") {
+	$role = "maintainer";
+    } elsif ($role eq "odd fixes") {
+	$role = "odd fixer";
+    } elsif ($role eq "orphan") {
+	$role = "orphan minder";
+    } elsif ($role eq "obsolete") {
+	$role = "obsolete minder";
+    } elsif ($role eq "buried alive in reporters") {
+	$role = "chief penguin";
+    }
+
+    return $role . ":" . $subsystem;
+}
+
+sub get_list_role {
+    my ($index) = @_;
+
+    my $i;
+    my $start = find_starting_index($index);
+    my $end = find_ending_index($index);
+
+    my $subsystem = $typevalue[$start];
+    if (length($subsystem) > 20) {
+	$subsystem = substr($subsystem, 0, 17);
+	$subsystem =~ s/\s*$//;
+	$subsystem = $subsystem . "...";
+    }
+
+    if ($subsystem eq "THE REST") {
+	$subsystem = "";
+    }
+
+    return $subsystem;
+}
+
+sub add_categories {
+    my ($index) = @_;
+
+    my $i;
+    my $start = find_starting_index($index);
+    my $end = find_ending_index($index);
+
+    push(@subsystem, $typevalue[$start]);
+
+    for ($i = $start + 1; $i < $end; $i++) {
+	my $tv = $typevalue[$i];
+	if ($tv =~ m/^(\C):\s*(.*)/) {
+	    my $ptype = $1;
+	    my $pvalue = $2;
+	    if ($ptype eq "L") {
+		my $list_address = $pvalue;
+		my $list_additional = "";
+		my $list_role = get_list_role($i);
+
+		if ($list_role ne "") {
+		    $list_role = ":" . $list_role;
+		}
+		if ($list_address =~ m/([^\s]+)\s+(.*)$/) {
+		    $list_address = $1;
+		    $list_additional = $2;
+		}
+		if ($list_additional =~ m/subscribers-only/) {
+		    if ($email_subscriber_list) {
+			if (!$hash_list_to{lc($list_address)}) {
+			    $hash_list_to{lc($list_address)} = 1;
+			    push(@list_to, [$list_address,
+					    "subscriber list${list_role}"]);
+			}
+		    }
+		} else {
+		    if ($email_list) {
+			if (!$hash_list_to{lc($list_address)}) {
+			    $hash_list_to{lc($list_address)} = 1;
+			    if ($list_additional =~ m/moderated/) {
+				push(@list_to, [$list_address,
+						"moderated list${list_role}"]);
+			    } else {
+				push(@list_to, [$list_address,
+						"open list${list_role}"]);
+			    }
+			}
+		    }
+		}
+	    } elsif ($ptype eq "M") {
+		my ($name, $address) = parse_email($pvalue);
+		if ($name eq "") {
+		    if ($i > 0) {
+			my $tv = $typevalue[$i - 1];
+			if ($tv =~ m/^(\C):\s*(.*)/) {
+			    if ($1 eq "P") {
+				$name = $2;
+				$pvalue = format_email($name, $address, $email_usename);
+			    }
+			}
+		    }
+		}
+		if ($email_maintainer) {
+		    my $role = get_maintainer_role($i);
+		    push_email_addresses($pvalue, $role);
+		}
+	    } elsif ($ptype eq "T") {
+		push(@scm, $pvalue);
+	    } elsif ($ptype eq "W") {
+		push(@web, $pvalue);
+	    } elsif ($ptype eq "S") {
+		push(@status, $pvalue);
+	    }
+	}
+    }
+}
+
+sub email_inuse {
+    my ($name, $address) = @_;
+
+    return 1 if (($name eq "") && ($address eq ""));
+    return 1 if (($name ne "") && exists($email_hash_name{lc($name)}));
+    return 1 if (($address ne "") && exists($email_hash_address{lc($address)}));
+
+    return 0;
+}
+
+sub push_email_address {
+    my ($line, $role) = @_;
+
+    my ($name, $address) = parse_email($line);
+
+    if ($address eq "") {
+	return 0;
+    }
+
+    if (!$email_remove_duplicates) {
+	push(@email_to, [format_email($name, $address, $email_usename), $role]);
+    } elsif (!email_inuse($name, $address)) {
+	push(@email_to, [format_email($name, $address, $email_usename), $role]);
+	$email_hash_name{lc($name)}++ if ($name ne "");
+	$email_hash_address{lc($address)}++;
+    }
+
+    return 1;
+}
+
+sub push_email_addresses {
+    my ($address, $role) = @_;
+
+    my @address_list = ();
+
+    if (rfc822_valid($address)) {
+	push_email_address($address, $role);
+    } elsif (@address_list = rfc822_validlist($address)) {
+	my $array_count = shift(@address_list);
+	while (my $entry = shift(@address_list)) {
+	    push_email_address($entry, $role);
+	}
+    } else {
+	if (!push_email_address($address, $role)) {
+	    warn("Invalid MAINTAINERS address: '" . $address . "'\n");
+	}
+    }
+}
+
+sub add_role {
+    my ($line, $role) = @_;
+
+    my ($name, $address) = parse_email($line);
+    my $email = format_email($name, $address, $email_usename);
+
+    foreach my $entry (@email_to) {
+	if ($email_remove_duplicates) {
+	    my ($entry_name, $entry_address) = parse_email($entry->[0]);
+	    if (($name eq $entry_name || $address eq $entry_address)
+		&& ($role eq "" || !($entry->[1] =~ m/$role/))
+	    ) {
+		if ($entry->[1] eq "") {
+		    $entry->[1] = "$role";
+		} else {
+		    $entry->[1] = "$entry->[1],$role";
+		}
+	    }
+	} else {
+	    if ($email eq $entry->[0]
+		&& ($role eq "" || !($entry->[1] =~ m/$role/))
+	    ) {
+		if ($entry->[1] eq "") {
+		    $entry->[1] = "$role";
+		} else {
+		    $entry->[1] = "$entry->[1],$role";
+		}
+	    }
+	}
+    }
+}
+
+sub which {
+    my ($bin) = @_;
+
+    foreach my $path (split(/:/, $ENV{PATH})) {
+	if (-e "$path/$bin") {
+	    return "$path/$bin";
+	}
+    }
+
+    return "";
+}
+
+sub which_conf {
+    my ($conf) = @_;
+
+    foreach my $path (split(/:/, ".:$ENV{HOME}:.scripts")) {
+	if (-e "$path/$conf") {
+	    return "$path/$conf";
+	}
+    }
+
+    return "";
+}
+
+sub mailmap_email {
+    my ($line) = @_;
+
+    my ($name, $address) = parse_email($line);
+    my $email = format_email($name, $address, 1);
+    my $real_name = $name;
+    my $real_address = $address;
+
+    if (exists $mailmap->{names}->{$email} ||
+	exists $mailmap->{addresses}->{$email}) {
+	if (exists $mailmap->{names}->{$email}) {
+	    $real_name = $mailmap->{names}->{$email};
+	}
+	if (exists $mailmap->{addresses}->{$email}) {
+	    $real_address = $mailmap->{addresses}->{$email};
+	}
+    } else {
+	if (exists $mailmap->{names}->{$address}) {
+	    $real_name = $mailmap->{names}->{$address};
+	}
+	if (exists $mailmap->{addresses}->{$address}) {
+	    $real_address = $mailmap->{addresses}->{$address};
+	}
+    }
+    return format_email($real_name, $real_address, 1);
+}
+
+sub mailmap {
+    my (@addresses) = @_;
+
+    my @mapped_emails = ();
+    foreach my $line (@addresses) {
+	push(@mapped_emails, mailmap_email($line));
+    }
+    merge_by_realname(@mapped_emails) if ($email_use_mailmap);
+    return @mapped_emails;
+}
+
+sub merge_by_realname {
+    my %address_map;
+    my (@emails) = @_;
+
+    foreach my $email (@emails) {
+	my ($name, $address) = parse_email($email);
+	if (exists $address_map{$name}) {
+	    $address = $address_map{$name};
+	    $email = format_email($name, $address, 1);
+	} else {
+	    $address_map{$name} = $address;
+	}
+    }
+}
+
+sub git_execute_cmd {
+    my ($cmd) = @_;
+    my @lines = ();
+
+    my $output = `$cmd`;
+    $output =~ s/^\s*//gm;
+    @lines = split("\n", $output);
+
+    return @lines;
+}
+
+sub hg_execute_cmd {
+    my ($cmd) = @_;
+    my @lines = ();
+
+    my $output = `$cmd`;
+    @lines = split("\n", $output);
+
+    return @lines;
+}
+
+sub extract_formatted_signatures {
+    my (@signature_lines) = @_;
+
+    my @type = @signature_lines;
+
+    s/\s*(.*):.*/$1/ for (@type);
+
+    # cut -f2- -d":"
+    s/\s*.*:\s*(.+)\s*/$1/ for (@signature_lines);
+
+## Reformat email addresses (with names) to avoid badly written signatures
+
+    foreach my $signer (@signature_lines) {
+	$signer = deduplicate_email($signer);
+    }
+
+    return (\@type, \@signature_lines);
+}
+
+sub vcs_find_signers {
+    my ($cmd, $file) = @_;
+    my $commits;
+    my @lines = ();
+    my @signatures = ();
+    my @authors = ();
+    my @stats = ();
+
+    @lines = &{$VCS_cmds{"execute_cmd"}}($cmd);
+
+    my $pattern = $VCS_cmds{"commit_pattern"};
+    my $author_pattern = $VCS_cmds{"author_pattern"};
+    my $stat_pattern = $VCS_cmds{"stat_pattern"};
+
+    $stat_pattern =~ s/(\$\w+)/$1/eeg;		#interpolate $stat_pattern
+
+    $commits = grep(/$pattern/, @lines);	# of commits
+
+    @authors = grep(/$author_pattern/, @lines);
+    @signatures = grep(/^[ \t]*${signature_pattern}.*\@.*$/, @lines);
+    @stats = grep(/$stat_pattern/, @lines);
+
+#    print("stats: <@stats>\n");
+
+    return (0, \@signatures, \@authors, \@stats) if !@signatures;
+
+    save_commits_by_author(@lines) if ($interactive);
+    save_commits_by_signer(@lines) if ($interactive);
+
+    if (!$email_git_penguin_chiefs) {
+	@signatures = grep(!/${penguin_chiefs}/i, @signatures);
+    }
+
+    my ($author_ref, $authors_ref) = extract_formatted_signatures(@authors);
+    my ($types_ref, $signers_ref) = extract_formatted_signatures(@signatures);
+
+    return ($commits, $signers_ref, $authors_ref, \@stats);
+}
+
+sub vcs_find_author {
+    my ($cmd) = @_;
+    my @lines = ();
+
+    @lines = &{$VCS_cmds{"execute_cmd"}}($cmd);
+
+    if (!$email_git_penguin_chiefs) {
+	@lines = grep(!/${penguin_chiefs}/i, @lines);
+    }
+
+    return @lines if !@lines;
+
+    my @authors = ();
+    foreach my $line (@lines) {
+	if ($line =~ m/$VCS_cmds{"author_pattern"}/) {
+	    my $author = $1;
+	    my ($name, $address) = parse_email($author);
+	    $author = format_email($name, $address, 1);
+	    push(@authors, $author);
+	}
+    }
+
+    save_commits_by_author(@lines) if ($interactive);
+    save_commits_by_signer(@lines) if ($interactive);
+
+    return @authors;
+}
+
+sub vcs_save_commits {
+    my ($cmd) = @_;
+    my @lines = ();
+    my @commits = ();
+
+    @lines = &{$VCS_cmds{"execute_cmd"}}($cmd);
+
+    foreach my $line (@lines) {
+	if ($line =~ m/$VCS_cmds{"blame_commit_pattern"}/) {
+	    push(@commits, $1);
+	}
+    }
+
+    return @commits;
+}
+
+sub vcs_blame {
+    my ($file) = @_;
+    my $cmd;
+    my @commits = ();
+
+    return @commits if (!(-f $file));
+
+    if (@range && $VCS_cmds{"blame_range_cmd"} eq "") {
+	my @all_commits = ();
+
+	$cmd = $VCS_cmds{"blame_file_cmd"};
+	$cmd =~ s/(\$\w+)/$1/eeg;		#interpolate $cmd
+	@all_commits = vcs_save_commits($cmd);
+
+	foreach my $file_range_diff (@range) {
+	    next if (!($file_range_diff =~ m/(.+):(.+):(.+)/));
+	    my $diff_file = $1;
+	    my $diff_start = $2;
+	    my $diff_length = $3;
+	    next if ("$file" ne "$diff_file");
+	    for (my $i = $diff_start; $i < $diff_start + $diff_length; $i++) {
+		push(@commits, $all_commits[$i]);
+	    }
+	}
+    } elsif (@range) {
+	foreach my $file_range_diff (@range) {
+	    next if (!($file_range_diff =~ m/(.+):(.+):(.+)/));
+	    my $diff_file = $1;
+	    my $diff_start = $2;
+	    my $diff_length = $3;
+	    next if ("$file" ne "$diff_file");
+	    $cmd = $VCS_cmds{"blame_range_cmd"};
+	    $cmd =~ s/(\$\w+)/$1/eeg;		#interpolate $cmd
+	    push(@commits, vcs_save_commits($cmd));
+	}
+    } else {
+	$cmd = $VCS_cmds{"blame_file_cmd"};
+	$cmd =~ s/(\$\w+)/$1/eeg;		#interpolate $cmd
+	@commits = vcs_save_commits($cmd);
+    }
+
+    foreach my $commit (@commits) {
+	$commit =~ s/^\^//g;
+    }
+
+    return @commits;
+}
+
+my $printed_novcs = 0;
+sub vcs_exists {
+    %VCS_cmds = %VCS_cmds_git;
+    return 1 if eval $VCS_cmds{"available"};
+    %VCS_cmds = %VCS_cmds_hg;
+    return 2 if eval $VCS_cmds{"available"};
+    %VCS_cmds = ();
+    if (!$printed_novcs) {
+	warn("$P: No supported VCS found.  Add --nogit to options?\n");
+	warn("Using a git repository produces better results.\n");
+	warn("Try Linus Torvalds' latest git repository using:\n");
+	warn("git clone git://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git\n");
+	$printed_novcs = 1;
+    }
+    return 0;
+}
+
+sub vcs_is_git {
+    vcs_exists();
+    return $vcs_used == 1;
+}
+
+sub vcs_is_hg {
+    return $vcs_used == 2;
+}
+
+sub interactive_get_maintainers {
+    my ($list_ref) = @_;
+    my @list = @$list_ref;
+
+    vcs_exists();
+
+    my %selected;
+    my %authored;
+    my %signed;
+    my $count = 0;
+    my $maintained = 0;
+    foreach my $entry (@list) {
+	$maintained = 1 if ($entry->[1] =~ /^(maintainer|supporter)/i);
+	$selected{$count} = 1;
+	$authored{$count} = 0;
+	$signed{$count} = 0;
+	$count++;
+    }
+
+    #menu loop
+    my $done = 0;
+    my $print_options = 0;
+    my $redraw = 1;
+    while (!$done) {
+	$count = 0;
+	if ($redraw) {
+	    printf STDERR "\n%1s %2s %-65s",
+			  "*", "#", "email/list and role:stats";
+	    if ($email_git ||
+		($email_git_fallback && !$maintained) ||
+		$email_git_blame) {
+		print STDERR "auth sign";
+	    }
+	    print STDERR "\n";
+	    foreach my $entry (@list) {
+		my $email = $entry->[0];
+		my $role = $entry->[1];
+		my $sel = "";
+		$sel = "*" if ($selected{$count});
+		my $commit_author = $commit_author_hash{$email};
+		my $commit_signer = $commit_signer_hash{$email};
+		my $authored = 0;
+		my $signed = 0;
+		$authored++ for (@{$commit_author});
+		$signed++ for (@{$commit_signer});
+		printf STDERR "%1s %2d %-65s", $sel, $count + 1, $email;
+		printf STDERR "%4d %4d", $authored, $signed
+		    if ($authored > 0 || $signed > 0);
+		printf STDERR "\n     %s\n", $role;
+		if ($authored{$count}) {
+		    my $commit_author = $commit_author_hash{$email};
+		    foreach my $ref (@{$commit_author}) {
+			print STDERR "     Author: @{$ref}[1]\n";
+		    }
+		}
+		if ($signed{$count}) {
+		    my $commit_signer = $commit_signer_hash{$email};
+		    foreach my $ref (@{$commit_signer}) {
+			print STDERR "     @{$ref}[2]: @{$ref}[1]\n";
+		    }
+		}
+
+		$count++;
+	    }
+	}
+	my $date_ref = \$email_git_since;
+	$date_ref = \$email_hg_since if (vcs_is_hg());
+	if ($print_options) {
+	    $print_options = 0;
+	    if (vcs_exists()) {
+		print STDERR <<EOT
+
+Version Control options:
+g  use git history      [$email_git]
+gf use git-fallback     [$email_git_fallback]
+b  use git blame        [$email_git_blame]
+bs use blame signatures [$email_git_blame_signatures]
+c# minimum commits      [$email_git_min_signatures]
+%# min percent          [$email_git_min_percent]
+d# history to use       [$$date_ref]
+x# max maintainers      [$email_git_max_maintainers]
+t  all signature types  [$email_git_all_signature_types]
+m  use .mailmap         [$email_use_mailmap]
+EOT
+	    }
+	    print STDERR <<EOT
+
+Additional options:
+0  toggle all
+tm toggle maintainers
+tg toggle git entries
+tl toggle open list entries
+ts toggle subscriber list entries
+f  emails in file       [$file_emails]
+k  keywords in file     [$keywords]
+r  remove duplicates    [$email_remove_duplicates]
+p# pattern match depth  [$pattern_depth]
+EOT
+	}
+	print STDERR
+"\n#(toggle), A#(author), S#(signed) *(all), ^(none), O(options), Y(approve): ";
+
+	my $input = <STDIN>;
+	chomp($input);
+
+	$redraw = 1;
+	my $rerun = 0;
+	my @wish = split(/[, ]+/, $input);
+	foreach my $nr (@wish) {
+	    $nr = lc($nr);
+	    my $sel = substr($nr, 0, 1);
+	    my $str = substr($nr, 1);
+	    my $val = 0;
+	    $val = $1 if $str =~ /^(\d+)$/;
+
+	    if ($sel eq "y") {
+		$interactive = 0;
+		$done = 1;
+		$output_rolestats = 0;
+		$output_roles = 0;
+		last;
+	    } elsif ($nr =~ /^\d+$/ && $nr > 0 && $nr <= $count) {
+		$selected{$nr - 1} = !$selected{$nr - 1};
+	    } elsif ($sel eq "*" || $sel eq '^') {
+		my $toggle = 0;
+		$toggle = 1 if ($sel eq '*');
+		for (my $i = 0; $i < $count; $i++) {
+		    $selected{$i} = $toggle;
+		}
+	    } elsif ($sel eq "0") {
+		for (my $i = 0; $i < $count; $i++) {
+		    $selected{$i} = !$selected{$i};
+		}
+	    } elsif ($sel eq "t") {
+		if (lc($str) eq "m") {
+		    for (my $i = 0; $i < $count; $i++) {
+			$selected{$i} = !$selected{$i}
+			    if ($list[$i]->[1] =~ /^(maintainer|supporter)/i);
+		    }
+		} elsif (lc($str) eq "g") {
+		    for (my $i = 0; $i < $count; $i++) {
+			$selected{$i} = !$selected{$i}
+			    if ($list[$i]->[1] =~ /^(author|commit|signer)/i);
+		    }
+		} elsif (lc($str) eq "l") {
+		    for (my $i = 0; $i < $count; $i++) {
+			$selected{$i} = !$selected{$i}
+			    if ($list[$i]->[1] =~ /^(open list)/i);
+		    }
+		} elsif (lc($str) eq "s") {
+		    for (my $i = 0; $i < $count; $i++) {
+			$selected{$i} = !$selected{$i}
+			    if ($list[$i]->[1] =~ /^(subscriber list)/i);
+		    }
+		}
+	    } elsif ($sel eq "a") {
+		if ($val > 0 && $val <= $count) {
+		    $authored{$val - 1} = !$authored{$val - 1};
+		} elsif ($str eq '*' || $str eq '^') {
+		    my $toggle = 0;
+		    $toggle = 1 if ($str eq '*');
+		    for (my $i = 0; $i < $count; $i++) {
+			$authored{$i} = $toggle;
+		    }
+		}
+	    } elsif ($sel eq "s") {
+		if ($val > 0 && $val <= $count) {
+		    $signed{$val - 1} = !$signed{$val - 1};
+		} elsif ($str eq '*' || $str eq '^') {
+		    my $toggle = 0;
+		    $toggle = 1 if ($str eq '*');
+		    for (my $i = 0; $i < $count; $i++) {
+			$signed{$i} = $toggle;
+		    }
+		}
+	    } elsif ($sel eq "o") {
+		$print_options = 1;
+		$redraw = 1;
+	    } elsif ($sel eq "g") {
+		if ($str eq "f") {
+		    bool_invert(\$email_git_fallback);
+		} else {
+		    bool_invert(\$email_git);
+		}
+		$rerun = 1;
+	    } elsif ($sel eq "b") {
+		if ($str eq "s") {
+		    bool_invert(\$email_git_blame_signatures);
+		} else {
+		    bool_invert(\$email_git_blame);
+		}
+		$rerun = 1;
+	    } elsif ($sel eq "c") {
+		if ($val > 0) {
+		    $email_git_min_signatures = $val;
+		    $rerun = 1;
+		}
+	    } elsif ($sel eq "x") {
+		if ($val > 0) {
+		    $email_git_max_maintainers = $val;
+		    $rerun = 1;
+		}
+	    } elsif ($sel eq "%") {
+		if ($str ne "" && $val >= 0) {
+		    $email_git_min_percent = $val;
+		    $rerun = 1;
+		}
+	    } elsif ($sel eq "d") {
+		if (vcs_is_git()) {
+		    $email_git_since = $str;
+		} elsif (vcs_is_hg()) {
+		    $email_hg_since = $str;
+		}
+		$rerun = 1;
+	    } elsif ($sel eq "t") {
+		bool_invert(\$email_git_all_signature_types);
+		$rerun = 1;
+	    } elsif ($sel eq "f") {
+		bool_invert(\$file_emails);
+		$rerun = 1;
+	    } elsif ($sel eq "r") {
+		bool_invert(\$email_remove_duplicates);
+		$rerun = 1;
+	    } elsif ($sel eq "m") {
+		bool_invert(\$email_use_mailmap);
+		read_mailmap();
+		$rerun = 1;
+	    } elsif ($sel eq "k") {
+		bool_invert(\$keywords);
+		$rerun = 1;
+	    } elsif ($sel eq "p") {
+		if ($str ne "" && $val >= 0) {
+		    $pattern_depth = $val;
+		    $rerun = 1;
+		}
+	    } elsif ($sel eq "h" || $sel eq "?") {
+		print STDERR <<EOT
+
+Interactive mode allows you to select the various maintainers, submitters,
+commit signers and mailing lists that could be CC'd on a patch.
+
+Any *'d entry is selected.
+
+If you have git or hg installed, you can choose to summarize the commit
+history of files in the patch.  Also, each line of the current file can
+be matched to its commit author and that commits signers with blame.
+
+Various knobs exist to control the length of time for active commit
+tracking, the maximum number of commit authors and signers to add,
+and such.
+
+Enter selections at the prompt until you are satisfied that the selected
+maintainers are appropriate.  You may enter multiple selections separated
+by either commas or spaces.
+
+EOT
+	    } else {
+		print STDERR "invalid option: '$nr'\n";
+		$redraw = 0;
+	    }
+	}
+	if ($rerun) {
+	    print STDERR "git-blame can be very slow, please have patience..."
+		if ($email_git_blame);
+	    goto &get_maintainers;
+	}
+    }
+
+    #drop not selected entries
+    $count = 0;
+    my @new_emailto = ();
+    foreach my $entry (@list) {
+	if ($selected{$count}) {
+	    push(@new_emailto, $list[$count]);
+	}
+	$count++;
+    }
+    return @new_emailto;
+}
+
+sub bool_invert {
+    my ($bool_ref) = @_;
+
+    if ($$bool_ref) {
+	$$bool_ref = 0;
+    } else {
+	$$bool_ref = 1;
+    }
+}
+
+sub deduplicate_email {
+    my ($email) = @_;
+
+    my $matched = 0;
+    my ($name, $address) = parse_email($email);
+    $email = format_email($name, $address, 1);
+    $email = mailmap_email($email);
+
+    return $email if (!$email_remove_duplicates);
+
+    ($name, $address) = parse_email($email);
+
+    if ($name ne "" && $deduplicate_name_hash{lc($name)}) {
+	$name = $deduplicate_name_hash{lc($name)}->[0];
+	$address = $deduplicate_name_hash{lc($name)}->[1];
+	$matched = 1;
+    } elsif ($deduplicate_address_hash{lc($address)}) {
+	$name = $deduplicate_address_hash{lc($address)}->[0];
+	$address = $deduplicate_address_hash{lc($address)}->[1];
+	$matched = 1;
+    }
+    if (!$matched) {
+	$deduplicate_name_hash{lc($name)} = [ $name, $address ];
+	$deduplicate_address_hash{lc($address)} = [ $name, $address ];
+    }
+    $email = format_email($name, $address, 1);
+    $email = mailmap_email($email);
+    return $email;
+}
+
+sub save_commits_by_author {
+    my (@lines) = @_;
+
+    my @authors = ();
+    my @commits = ();
+    my @subjects = ();
+
+    foreach my $line (@lines) {
+	if ($line =~ m/$VCS_cmds{"author_pattern"}/) {
+	    my $author = $1;
+	    $author = deduplicate_email($author);
+	    push(@authors, $author);
+	}
+	push(@commits, $1) if ($line =~ m/$VCS_cmds{"commit_pattern"}/);
+	push(@subjects, $1) if ($line =~ m/$VCS_cmds{"subject_pattern"}/);
+    }
+
+    for (my $i = 0; $i < @authors; $i++) {
+	my $exists = 0;
+	foreach my $ref(@{$commit_author_hash{$authors[$i]}}) {
+	    if (@{$ref}[0] eq $commits[$i] &&
+		@{$ref}[1] eq $subjects[$i]) {
+		$exists = 1;
+		last;
+	    }
+	}
+	if (!$exists) {
+	    push(@{$commit_author_hash{$authors[$i]}},
+		 [ ($commits[$i], $subjects[$i]) ]);
+	}
+    }
+}
+
+sub save_commits_by_signer {
+    my (@lines) = @_;
+
+    my $commit = "";
+    my $subject = "";
+
+    foreach my $line (@lines) {
+	$commit = $1 if ($line =~ m/$VCS_cmds{"commit_pattern"}/);
+	$subject = $1 if ($line =~ m/$VCS_cmds{"subject_pattern"}/);
+	if ($line =~ /^[ \t]*${signature_pattern}.*\@.*$/) {
+	    my @signatures = ($line);
+	    my ($types_ref, $signers_ref) = extract_formatted_signatures(@signatures);
+	    my @types = @$types_ref;
+	    my @signers = @$signers_ref;
+
+	    my $type = $types[0];
+	    my $signer = $signers[0];
+
+	    $signer = deduplicate_email($signer);
+
+	    my $exists = 0;
+	    foreach my $ref(@{$commit_signer_hash{$signer}}) {
+		if (@{$ref}[0] eq $commit &&
+		    @{$ref}[1] eq $subject &&
+		    @{$ref}[2] eq $type) {
+		    $exists = 1;
+		    last;
+		}
+	    }
+	    if (!$exists) {
+		push(@{$commit_signer_hash{$signer}},
+		     [ ($commit, $subject, $type) ]);
+	    }
+	}
+    }
+}
+
+sub vcs_assign {
+    my ($role, $divisor, @lines) = @_;
+
+    my %hash;
+    my $count = 0;
+
+    return if (@lines <= 0);
+
+    if ($divisor <= 0) {
+	warn("Bad divisor in " . (caller(0))[3] . ": $divisor\n");
+	$divisor = 1;
+    }
+
+    @lines = mailmap(@lines);
+
+    return if (@lines <= 0);
+
+    @lines = sort(@lines);
+
+    # uniq -c
+    $hash{$_}++ for @lines;
+
+    # sort -rn
+    foreach my $line (sort {$hash{$b} <=> $hash{$a}} keys %hash) {
+	my $sign_offs = $hash{$line};
+	my $percent = $sign_offs * 100 / $divisor;
+
+	$percent = 100 if ($percent > 100);
+	$count++;
+	last if ($sign_offs < $email_git_min_signatures ||
+		 $count > $email_git_max_maintainers ||
+		 $percent < $email_git_min_percent);
+	push_email_address($line, '');
+	if ($output_rolestats) {
+	    my $fmt_percent = sprintf("%.0f", $percent);
+	    add_role($line, "$role:$sign_offs/$divisor=$fmt_percent%");
+	} else {
+	    add_role($line, $role);
+	}
+    }
+}
+
+sub vcs_file_signoffs {
+    my ($file) = @_;
+
+    my $authors_ref;
+    my $signers_ref;
+    my $stats_ref;
+    my @authors = ();
+    my @signers = ();
+    my @stats = ();
+    my $commits;
+
+    $vcs_used = vcs_exists();
+    return if (!$vcs_used);
+
+    my $cmd = $VCS_cmds{"find_signers_cmd"};
+    $cmd =~ s/(\$\w+)/$1/eeg;		# interpolate $cmd
+
+    ($commits, $signers_ref, $authors_ref, $stats_ref) = vcs_find_signers($cmd, $file);
+
+    @signers = @{$signers_ref} if defined $signers_ref;
+    @authors = @{$authors_ref} if defined $authors_ref;
+    @stats = @{$stats_ref} if defined $stats_ref;
+
+#    print("commits: <$commits>\nsigners:<@signers>\nauthors: <@authors>\nstats: <@stats>\n");
+
+    foreach my $signer (@signers) {
+	$signer = deduplicate_email($signer);
+    }
+
+    vcs_assign("commit_signer", $commits, @signers);
+    vcs_assign("authored", $commits, @authors);
+    if ($#authors == $#stats) {
+	my $stat_pattern = $VCS_cmds{"stat_pattern"};
+	$stat_pattern =~ s/(\$\w+)/$1/eeg;	#interpolate $stat_pattern
+
+	my $added = 0;
+	my $deleted = 0;
+	for (my $i = 0; $i <= $#stats; $i++) {
+	    if ($stats[$i] =~ /$stat_pattern/) {
+		$added += $1;
+		$deleted += $2;
+	    }
+	}
+	my @tmp_authors = uniq(@authors);
+	foreach my $author (@tmp_authors) {
+	    $author = deduplicate_email($author);
+	}
+	@tmp_authors = uniq(@tmp_authors);
+	my @list_added = ();
+	my @list_deleted = ();
+	foreach my $author (@tmp_authors) {
+	    my $auth_added = 0;
+	    my $auth_deleted = 0;
+	    for (my $i = 0; $i <= $#stats; $i++) {
+		if ($author eq deduplicate_email($authors[$i]) &&
+		    $stats[$i] =~ /$stat_pattern/) {
+		    $auth_added += $1;
+		    $auth_deleted += $2;
+		}
+	    }
+	    for (my $i = 0; $i < $auth_added; $i++) {
+		push(@list_added, $author);
+	    }
+	    for (my $i = 0; $i < $auth_deleted; $i++) {
+		push(@list_deleted, $author);
+	    }
+	}
+	vcs_assign("added_lines", $added, @list_added);
+	vcs_assign("removed_lines", $deleted, @list_deleted);
+    }
+}
+
+sub vcs_file_blame {
+    my ($file) = @_;
+
+    my @signers = ();
+    my @all_commits = ();
+    my @commits = ();
+    my $total_commits;
+    my $total_lines;
+
+    $vcs_used = vcs_exists();
+    return if (!$vcs_used);
+
+    @all_commits = vcs_blame($file);
+    @commits = uniq(@all_commits);
+    $total_commits = @commits;
+    $total_lines = @all_commits;
+
+    if ($email_git_blame_signatures) {
+	if (vcs_is_hg()) {
+	    my $commit_count;
+	    my $commit_authors_ref;
+	    my $commit_signers_ref;
+	    my $stats_ref;
+	    my @commit_authors = ();
+	    my @commit_signers = ();
+	    my $commit = join(" -r ", @commits);
+	    my $cmd;
+
+	    $cmd = $VCS_cmds{"find_commit_signers_cmd"};
+	    $cmd =~ s/(\$\w+)/$1/eeg;	#substitute variables in $cmd
+
+	    ($commit_count, $commit_signers_ref, $commit_authors_ref, $stats_ref) = vcs_find_signers($cmd, $file);
+	    @commit_authors = @{$commit_authors_ref} if defined $commit_authors_ref;
+	    @commit_signers = @{$commit_signers_ref} if defined $commit_signers_ref;
+
+	    push(@signers, @commit_signers);
+	} else {
+	    foreach my $commit (@commits) {
+		my $commit_count;
+		my $commit_authors_ref;
+		my $commit_signers_ref;
+		my $stats_ref;
+		my @commit_authors = ();
+		my @commit_signers = ();
+		my $cmd;
+
+		$cmd = $VCS_cmds{"find_commit_signers_cmd"};
+		$cmd =~ s/(\$\w+)/$1/eeg;	#substitute variables in $cmd
+
+		($commit_count, $commit_signers_ref, $commit_authors_ref, $stats_ref) = vcs_find_signers($cmd, $file);
+		@commit_authors = @{$commit_authors_ref} if defined $commit_authors_ref;
+		@commit_signers = @{$commit_signers_ref} if defined $commit_signers_ref;
+
+		push(@signers, @commit_signers);
+	    }
+	}
+    }
+
+    if ($from_filename) {
+	if ($output_rolestats) {
+	    my @blame_signers;
+	    if (vcs_is_hg()) {{		# Double brace for last exit
+		my $commit_count;
+		my @commit_signers = ();
+		@commits = uniq(@commits);
+		@commits = sort(@commits);
+		my $commit = join(" -r ", @commits);
+		my $cmd;
+
+		$cmd = $VCS_cmds{"find_commit_author_cmd"};
+		$cmd =~ s/(\$\w+)/$1/eeg;	#substitute variables in $cmd
+
+		my @lines = ();
+
+		@lines = &{$VCS_cmds{"execute_cmd"}}($cmd);
+
+		if (!$email_git_penguin_chiefs) {
+		    @lines = grep(!/${penguin_chiefs}/i, @lines);
+		}
+
+		last if !@lines;
+
+		my @authors = ();
+		foreach my $line (@lines) {
+		    if ($line =~ m/$VCS_cmds{"author_pattern"}/) {
+			my $author = $1;
+			$author = deduplicate_email($author);
+			push(@authors, $author);
+		    }
+		}
+
+		save_commits_by_author(@lines) if ($interactive);
+		save_commits_by_signer(@lines) if ($interactive);
+
+		push(@signers, @authors);
+	    }}
+	    else {
+		foreach my $commit (@commits) {
+		    my $i;
+		    my $cmd = $VCS_cmds{"find_commit_author_cmd"};
+		    $cmd =~ s/(\$\w+)/$1/eeg;	#interpolate $cmd
+		    my @author = vcs_find_author($cmd);
+		    next if !@author;
+
+		    my $formatted_author = deduplicate_email($author[0]);
+
+		    my $count = grep(/$commit/, @all_commits);
+		    for ($i = 0; $i < $count ; $i++) {
+			push(@blame_signers, $formatted_author);
+		    }
+		}
+	    }
+	    if (@blame_signers) {
+		vcs_assign("authored lines", $total_lines, @blame_signers);
+	    }
+	}
+	foreach my $signer (@signers) {
+	    $signer = deduplicate_email($signer);
+	}
+	vcs_assign("commits", $total_commits, @signers);
+    } else {
+	foreach my $signer (@signers) {
+	    $signer = deduplicate_email($signer);
+	}
+	vcs_assign("modified commits", $total_commits, @signers);
+    }
+}
+
+sub uniq {
+    my (@parms) = @_;
+
+    my %saw;
+    @parms = grep(!$saw{$_}++, @parms);
+    return @parms;
+}
+
+sub sort_and_uniq {
+    my (@parms) = @_;
+
+    my %saw;
+    @parms = sort @parms;
+    @parms = grep(!$saw{$_}++, @parms);
+    return @parms;
+}
+
+sub clean_file_emails {
+    my (@file_emails) = @_;
+    my @fmt_emails = ();
+
+    foreach my $email (@file_emails) {
+	$email =~ s/[\(\<\{]{0,1}([A-Za-z0-9_\.\+-]+\@[A-Za-z0-9\.-]+)[\)\>\}]{0,1}/\<$1\>/g;
+	my ($name, $address) = parse_email($email);
+	if ($name eq '"[,\.]"') {
+	    $name = "";
+	}
+
+	my @nw = split(/[^A-Za-zÀ-ÿ\'\,\.\+-]/, $name);
+	if (@nw > 2) {
+	    my $first = $nw[@nw - 3];
+	    my $middle = $nw[@nw - 2];
+	    my $last = $nw[@nw - 1];
+
+	    if (((length($first) == 1 && $first =~ m/[A-Za-z]/) ||
+		 (length($first) == 2 && substr($first, -1) eq ".")) ||
+		(length($middle) == 1 ||
+		 (length($middle) == 2 && substr($middle, -1) eq "."))) {
+		$name = "$first $middle $last";
+	    } else {
+		$name = "$middle $last";
+	    }
+	}
+
+	if (substr($name, -1) =~ /[,\.]/) {
+	    $name = substr($name, 0, length($name) - 1);
+	} elsif (substr($name, -2) =~ /[,\.]"/) {
+	    $name = substr($name, 0, length($name) - 2) . '"';
+	}
+
+	if (substr($name, 0, 1) =~ /[,\.]/) {
+	    $name = substr($name, 1, length($name) - 1);
+	} elsif (substr($name, 0, 2) =~ /"[,\.]/) {
+	    $name = '"' . substr($name, 2, length($name) - 2);
+	}
+
+	my $fmt_email = format_email($name, $address, $email_usename);
+	push(@fmt_emails, $fmt_email);
+    }
+    return @fmt_emails;
+}
+
+sub merge_email {
+    my @lines;
+    my %saw;
+
+    for (@_) {
+	my ($address, $role) = @$_;
+	if (!$saw{$address}) {
+	    if ($output_roles) {
+		push(@lines, "$address ($role)");
+	    } else {
+		push(@lines, $address);
+	    }
+	    $saw{$address} = 1;
+	}
+    }
+
+    return @lines;
+}
+
+sub output {
+    my (@parms) = @_;
+
+    if ($output_multiline) {
+	foreach my $line (@parms) {
+	    print("${line}\n");
+	}
+    } else {
+	print(join($output_separator, @parms));
+	print("\n");
+    }
+}
+
+my $rfc822re;
+
+sub make_rfc822re {
+#   Basic lexical tokens are specials, domain_literal, quoted_string, atom, and
+#   comment.  We must allow for rfc822_lwsp (or comments) after each of these.
+#   This regexp will only work on addresses which have had comments stripped
+#   and replaced with rfc822_lwsp.
+
+    my $specials = '()<>@,;:\\\\".\\[\\]';
+    my $controls = '\\000-\\037\\177';
+
+    my $dtext = "[^\\[\\]\\r\\\\]";
+    my $domain_literal = "\\[(?:$dtext|\\\\.)*\\]$rfc822_lwsp*";
+
+    my $quoted_string = "\"(?:[^\\\"\\r\\\\]|\\\\.|$rfc822_lwsp)*\"$rfc822_lwsp*";
+
+#   Use zero-width assertion to spot the limit of an atom.  A simple
+#   $rfc822_lwsp* causes the regexp engine to hang occasionally.
+    my $atom = "[^$specials $controls]+(?:$rfc822_lwsp+|\\Z|(?=[\\[\"$specials]))";
+    my $word = "(?:$atom|$quoted_string)";
+    my $localpart = "$word(?:\\.$rfc822_lwsp*$word)*";
+
+    my $sub_domain = "(?:$atom|$domain_literal)";
+    my $domain = "$sub_domain(?:\\.$rfc822_lwsp*$sub_domain)*";
+
+    my $addr_spec = "$localpart\@$rfc822_lwsp*$domain";
+
+    my $phrase = "$word*";
+    my $route = "(?:\@$domain(?:,\@$rfc822_lwsp*$domain)*:$rfc822_lwsp*)";
+    my $route_addr = "\\<$rfc822_lwsp*$route?$addr_spec\\>$rfc822_lwsp*";
+    my $mailbox = "(?:$addr_spec|$phrase$route_addr)";
+
+    my $group = "$phrase:$rfc822_lwsp*(?:$mailbox(?:,\\s*$mailbox)*)?;\\s*";
+    my $address = "(?:$mailbox|$group)";
+
+    return "$rfc822_lwsp*$address";
+}
+
+sub rfc822_strip_comments {
+    my $s = shift;
+#   Recursively remove comments, and replace with a single space.  The simpler
+#   regexps in the Email Addressing FAQ are imperfect - they will miss escaped
+#   chars in atoms, for example.
+
+    while ($s =~ s/^((?:[^"\\]|\\.)*
+                    (?:"(?:[^"\\]|\\.)*"(?:[^"\\]|\\.)*)*)
+                    \((?:[^()\\]|\\.)*\)/$1 /osx) {}
+    return $s;
+}
+
+#   valid: returns true if the parameter is an RFC822 valid address
+#
+sub rfc822_valid {
+    my $s = rfc822_strip_comments(shift);
+
+    if (!$rfc822re) {
+        $rfc822re = make_rfc822re();
+    }
+
+    return $s =~ m/^$rfc822re$/so && $s =~ m/^$rfc822_char*$/;
+}
+
+#   validlist: In scalar context, returns true if the parameter is an RFC822
+#              valid list of addresses.
+#
+#              In list context, returns an empty list on failure (an invalid
+#              address was found); otherwise a list whose first element is the
+#              number of addresses found and whose remaining elements are the
+#              addresses.  This is needed to disambiguate failure (invalid)
+#              from success with no addresses found, because an empty string is
+#              a valid list.
+
+sub rfc822_validlist {
+    my $s = rfc822_strip_comments(shift);
+
+    if (!$rfc822re) {
+        $rfc822re = make_rfc822re();
+    }
+    # * null list items are valid according to the RFC
+    # * the '1' business is to aid in distinguishing failure from no results
+
+    my @r;
+    if ($s =~ m/^(?:$rfc822re)?(?:,(?:$rfc822re)?)*$/so &&
+	$s =~ m/^$rfc822_char*$/) {
+        while ($s =~ m/(?:^|,$rfc822_lwsp*)($rfc822re)/gos) {
+            push(@r, $1);
+        }
+        return wantarray ? (scalar(@r), @r) : 1;
+    }
+    return wantarray ? () : 0;
+}
diff --git a/test/dfu/README b/test/dfu/README
new file mode 100644
index 0000000..5176aba
--- /dev/null
+++ b/test/dfu/README
@@ -0,0 +1,37 @@
+DFU TEST CASE DESCRIPTION:
+
+The prerequisites for running this script are assured by
+dfu_gadget_test_init.sh, which is automatically invoked by dfu_gadget_test.sh.
+In this file user is able to generate their own set of test files by altering
+the default set of TEST_FILES_SIZES variable.
+The dfu_gadget_test_init.sh would generate test images only if they are not
+already generated.
+
+On the target device, environment variable "dfu_alt_info" must contain at
+least:
+
+    dfu_test.bin fat 0 6;dfudummy.bin fat 0 6
+
+Depending on your device, you may need to replace "fat" with
+"ext4", and "6" with the relevant partition number. For reference please
+consult the config file for TRATS/TRATS2 devices
+(../../include/configs/trats{2}.h)
+
+One can use fat, ext4 or any other supported file system supported by U-Boot.
+These can be created by exporting storage devices via UMS (ums 0 mmc 0) and
+using standard tools on host (like mkfs.ext4).
+
+Example usage:
+1. On the target:
+   setenv dfu_alt_info dfu_test.bin fat 0 6\;dfudummy.bin fat 0 6
+   dfu 0 mmc 0
+2. On the host:
+   test/dfu/dfu_gadget_test.sh X Y  [test file name]
+   e.g. test/dfu/dfu_gadget_test.sh 0 1
+   or
+   e.g. test/dfu/dfu_gadget_test.sh 0 1 ./dat_960.img
+
+... where X and Y are dfu_test.bin's and dfudummy.bin's alt setting numbers.
+They can be obtained from dfu-util -l or $dfu_alt_info.
+It is also possible to pass optional [test file name] to force the script to
+test one particular file.
diff --git a/test/dfu/dfu_gadget_test.sh b/test/dfu/dfu_gadget_test.sh
new file mode 100755
index 0000000..4133155
--- /dev/null
+++ b/test/dfu/dfu_gadget_test.sh
@@ -0,0 +1,94 @@
+#! /bin/bash
+
+set -e # any command return if not equal to zero
+clear
+
+COLOUR_RED="\33[31m"
+COLOUR_GREEN="\33[32m"
+COLOUR_DEFAULT="\33[0m"
+
+DIR=./
+SUFFIX=img
+RCV_DIR=rcv/
+LOG_FILE=./log/log-`date +%d-%m-%Y_%H-%M-%S`
+
+cd `dirname $0`
+./dfu_gadget_test_init.sh
+
+cleanup () {
+    rm -rf $DIR$RCV_DIR
+}
+
+die () {
+	printf "   $COLOUR_RED FAILED $COLOUR_DEFAULT \n"
+	cleanup
+	exit 1
+}
+
+calculate_md5sum () {
+    MD5SUM=`md5sum $1`
+    MD5SUM=`echo $MD5SUM | cut -d ' ' -f1`
+    echo "md5sum:"$MD5SUM
+}
+
+dfu_test_file () {
+    printf "$COLOUR_GREEN ========================================================================================= $COLOUR_DEFAULT\n"
+    printf "File:$COLOUR_GREEN %s $COLOUR_DEFAULT\n" $1
+
+    dfu-util -D $1 -a $TARGET_ALT_SETTING >> $LOG_FILE 2>&1 || die $?
+
+    echo -n "TX: "
+    calculate_md5sum $1
+
+    MD5_TX=$MD5SUM
+
+    dfu-util -D ${DIR}/dfudummy.bin -a $TARGET_ALT_SETTING_B >> $LOG_FILE 2>&1 || die $?
+
+    N_FILE=$DIR$RCV_DIR${1:2}"_rcv"
+
+    dfu-util -U $N_FILE -a $TARGET_ALT_SETTING >> $LOG_FILE 2>&1 || die $?
+
+    echo -n "RX: "
+    calculate_md5sum $N_FILE
+    MD5_RX=$MD5SUM
+
+    if [ "$MD5_TX" == "$MD5_RX" ]; then
+	printf "   $COLOUR_GREEN -------> OK $COLOUR_DEFAULT \n"
+    else
+	printf "   $COLOUR_RED -------> FAILED $COLOUR_DEFAULT \n"
+	cleanup
+	exit 1
+    fi
+
+}
+
+printf "$COLOUR_GREEN========================================================================================= $COLOUR_DEFAULT\n"
+echo "DFU EP0 transmission test program"
+echo "Trouble shoot -> disable DBG (even the KERN_DEBUG) in the UDC driver"
+echo "@ -> TRATS2 # dfu 0 mmc 0"
+cleanup
+mkdir -p $DIR$RCV_DIR
+touch $LOG_FILE
+
+if [ $# -eq 0 ]
+then
+	printf "   $COLOUR_RED Please pass alt setting number!!  $COLOUR_DEFAULT \n"
+	exit 0
+fi
+
+TARGET_ALT_SETTING=$1
+TARGET_ALT_SETTING_B=$2
+
+if [ -n "$3" ]
+then
+	dfu_test_file $3
+else
+	for file in $DIR*.$SUFFIX
+	do
+	    dfu_test_file $file
+	done
+fi
+
+cleanup
+
+exit 0
diff --git a/test/dfu/dfu_gadget_test_init.sh b/test/dfu/dfu_gadget_test_init.sh
new file mode 100755
index 0000000..2163a68
--- /dev/null
+++ b/test/dfu/dfu_gadget_test_init.sh
@@ -0,0 +1,31 @@
+#! /bin/bash
+
+set -e # any command return if not equal to zero
+clear
+
+COLOUR_RED="\33[31m"
+COLOUR_GREEN="\33[32m"
+COLOUR_DEFAULT="\33[0m"
+
+LOG_DIR="./log"
+
+TEST_FILES_SIZES="63 64 65 127 128 129 4095 4096 4097 959 960 961 1048575 1048576 8M"
+
+printf "Init script for generating data necessary for DFU test script"
+
+if [ ! -d $LOG_DIR ]; then
+    `mkdir $LOG_DIR`
+fi
+
+for size in $TEST_FILES_SIZES
+do
+    FILE="./dat_$size.img"
+    if [ ! -f $FILE ]; then
+	dd if=/dev/urandom of="./dat_$size.img" bs=$size count=1 > /dev/null 2>&1 || exit $?
+    fi
+done
+dd if=/dev/urandom of="./dfudummy.bin" bs=1024 count=1 > /dev/null 2>&1 || exit $?
+
+printf "$COLOUR_GREEN OK $COLOUR_DEFAULT \n"
+
+exit 0
diff --git a/test/vboot/vboot_test.sh b/test/vboot/vboot_test.sh
index 8074fc6..6d7abb8 100755
--- a/test/vboot/vboot_test.sh
+++ b/test/vboot/vboot_test.sh
@@ -54,8 +54,16 @@
 echo "Build keys"
 mkdir -p ${keys}
 
+PUBLIC_EXPONENT=${1}
+
+if [ -z "${PUBLIC_EXPONENT}" ]; then
+	PUBLIC_EXPONENT=65537
+fi
+
 # Create an RSA key pair
-openssl genrsa -F4 -out ${keys}/dev.key 2048 2>/dev/null
+openssl genpkey -algorithm RSA -out ${keys}/dev.key \
+    -pkeyopt rsa_keygen_bits:2048 \
+    -pkeyopt rsa_keygen_pubexp:${PUBLIC_EXPONENT} 2>/dev/null
 
 # Create a certificate containing the public key
 openssl req -batch -new -x509 -key ${keys}/dev.key -out ${keys}/dev.crt