summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--MAINTAINERS405
-rw-r--r--Makefile9
-rw-r--r--arch/arm/include/asm/emif.h3
-rw-r--r--common/board_r.c1
-rw-r--r--common/bootm.c25
-rw-r--r--common/cmd_dfu.c3
-rw-r--r--common/cmd_ext4.c16
-rw-r--r--common/cmd_fat.c13
-rw-r--r--common/cmd_fdt.c2
-rw-r--r--common/cmd_fs.c13
-rw-r--r--common/cmd_pxe.c17
-rw-r--r--common/cmd_thordown.c6
-rw-r--r--common/env_fat.c4
-rw-r--r--common/fdt_support.c2
-rw-r--r--common/image-fdt.c2
-rw-r--r--common/image.c43
-rw-r--r--common/lcd.c85
-rw-r--r--doc/README.android-fastboot4
-rw-r--r--doc/README.scrapyard30
-rw-r--r--doc/git-mailrc3
-rw-r--r--doc/uImage.FIT/signature.txt4
-rw-r--r--drivers/dfu/Makefile1
-rw-r--r--drivers/dfu/dfu.c105
-rw-r--r--drivers/dfu/dfu_mmc.c80
-rw-r--r--drivers/dfu/dfu_nand.c9
-rw-r--r--drivers/dfu/dfu_ram.c13
-rw-r--r--drivers/dfu/dfu_sf.c139
-rw-r--r--drivers/dma/Makefile1
-rw-r--r--drivers/dma/omap3_dma.c167
-rw-r--r--drivers/net/phy/vitesse.c1
-rw-r--r--drivers/serial/ns16550.c2
-rw-r--r--drivers/serial/serial_ns16550.c9
-rw-r--r--drivers/serial/serial_sh.c8
-rw-r--r--drivers/serial/serial_sh.h7
-rw-r--r--drivers/serial/usbtty.h2
-rw-r--r--drivers/usb/gadget/Makefile1
-rw-r--r--drivers/usb/gadget/f_dfu.c20
-rw-r--r--drivers/usb/gadget/f_thor.c5
-rw-r--r--drivers/usb/gadget/omap1510_udc.c49
-rw-r--r--drivers/usb/host/ehci-rmobile.c7
-rw-r--r--drivers/video/Makefile1
-rw-r--r--drivers/video/am335x-fb.c169
-rw-r--r--drivers/video/am335x-fb.h67
-rw-r--r--drivers/video/ipu.h8
-rw-r--r--drivers/video/ipu_disp.c29
-rw-r--r--drivers/video/ipu_regs.h3
-rw-r--r--fs/ext4/ext4fs.c5
-rw-r--r--fs/fat/fat.c5
-rw-r--r--fs/fs.c43
-rw-r--r--fs/sandbox/sandboxfs.c5
-rw-r--r--include/config_distro_bootcmd.h197
-rw-r--r--include/configs/koelsch.h2
-rw-r--r--include/configs/lager.h2
-rw-r--r--include/configs/omap1510.h16
-rw-r--r--include/configs/rpi_b.h129
-rw-r--r--include/configs/tegra-common-post.h140
-rw-r--r--include/configs/trats.h6
-rw-r--r--include/configs/trats2.h6
-rw-r--r--include/dfu.h52
-rw-r--r--include/ext4fs.h1
-rw-r--r--include/fat.h1
-rw-r--r--include/fdt_support.h2
-rw-r--r--include/fs.h9
-rw-r--r--include/image.h1
-rw-r--r--include/lcd.h19
-rw-r--r--include/libfdt.h73
-rw-r--r--include/ns16550.h7
-rw-r--r--include/sandboxfs.h1
-rw-r--r--include/u-boot/rsa.h1
-rw-r--r--include/usb/udc.h4
-rw-r--r--lib/libfdt/Makefile3
-rw-r--r--lib/libfdt/fdt_addresses.c55
-rw-r--r--lib/libfdt/fdt_rw.c6
-rw-r--r--lib/libfdt/fdt_sw.c32
-rw-r--r--lib/libfdt/libfdt_internal.h6
-rw-r--r--lib/lmb.c5
-rw-r--r--lib/rsa/rsa-sign.c61
-rw-r--r--lib/rsa/rsa-verify.c97
-rw-r--r--net/bootp.c38
-rw-r--r--net/bootp.h3
-rw-r--r--net/net.c4
-rwxr-xr-xscripts/get_maintainer.pl2270
-rw-r--r--test/dfu/README37
-rwxr-xr-xtest/dfu/dfu_gadget_test.sh94
-rwxr-xr-xtest/dfu/dfu_gadget_test_init.sh31
-rwxr-xr-xtest/vboot/vboot_test.sh10
86 files changed, 4349 insertions, 723 deletions
diff --git a/MAINTAINERS b/MAINTAINERS
new file mode 100644
index 0000000000..af194ca755
--- /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 666d291137..b5d5e0110a 100644
--- a/Makefile
+++ b/Makefile
@@ -802,14 +802,15 @@ u-boot.hex u-boot.srec: u-boot FORCE
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 b8d6bdca9b..2fe5776c6c 100644
--- a/arch/arm/include/asm/emif.h
+++ b/arch/arm/include/asm/emif.h
@@ -878,7 +878,6 @@ struct dmm_lisa_map_regs {
((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 @@ struct dmm_lisa_map_regs {
((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 8e7a3ac74c..ba9a68dc66 100644
--- a/common/board_r.c
+++ b/common/board_r.c
@@ -587,6 +587,7 @@ static int initr_doc(void)
{
puts("DOC: ");
doc_init();
+ return 0;
}
#endif
diff --git a/common/bootm.c b/common/bootm.c
index 7ec2ed8f45..76d811c983 100644
--- a/common/bootm.c
+++ b/common/bootm.c
@@ -731,26 +731,7 @@ static const void *boot_get_kernel(cmd_tbl_t *cmdtp, int flag, int argc,
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 @@ static const void *boot_get_kernel(cmd_tbl_t *cmdtp, int flag, int argc,
#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 433bddd5d2..2633b30e55 100644
--- a/common/cmd_dfu.c
+++ b/common/cmd_dfu.c
@@ -24,8 +24,7 @@ static int do_dfu(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
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 68b047ba6a..ecfc6d3c9b 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 @@ U_BOOT_CMD(ext4write, 6, 1, do_ext4_write,
#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(ext4ls, 4, 1, do_ext4_ls,
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 a478017448..633fbf1d31 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 e86d992838..5640ded296 100644
--- a/common/cmd_fdt.c
+++ b/common/cmd_fdt.c
@@ -621,7 +621,7 @@ static int do_fdt(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
}
/* 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 78590d2ef0..6754340786 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 ba48692e86..c816339232 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 @@ static int label_boot(cmd_tbl_t *cmdtp, struct pxe_label *label)
char *bootargs;
int bootm_argc = 3;
int len = 0;
+ ulong kernel_addr;
+ void *buf;
label_print(label);
@@ -771,11 +774,15 @@ static int label_boot(cmd_tbl_t *cmdtp, struct pxe_label *label)
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 @@ do_pxe_boot(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
destroy_pxe_menu(cfg);
+ copy_filename(BootFile, "", sizeof(BootFile));
+
return 0;
}
diff --git a/common/cmd_thordown.c b/common/cmd_thordown.c
index 2dd750928e..8ed1dc6f9e 100644
--- a/common/cmd_thordown.c
+++ b/common/cmd_thordown.c
@@ -26,10 +26,9 @@ int do_thor_down(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
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 @@ int do_thor_down(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
exit:
g_dnl_unregister();
+done:
dfu_free_entities();
return ret;
diff --git a/common/env_fat.c b/common/env_fat.c
index 328c09d45f..8db0160ceb 100644
--- a/common/env_fat.c
+++ b/common/env_fat.c
@@ -73,7 +73,7 @@ int saveenv(void)
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 @@ void env_relocate_spec(void)
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 7927a83b89..784a570a81 100644
--- a/common/fdt_support.c
+++ b/common/fdt_support.c
@@ -508,7 +508,7 @@ void fdt_fixup_ethernet(void *fdt)
}
/* 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 db6e395562..a2342fa3df 100644
--- a/common/image-fdt.c
+++ b/common/image-fdt.c
@@ -479,7 +479,7 @@ int image_setup_libfdt(bootm_headers_t *images, void *blob,
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 11b3cf58e6..a2999c0fba 100644
--- a/common/image.c
+++ b/common/image.c
@@ -643,6 +643,49 @@ int genimg_get_comp_id(const char *name)
#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 feb913a720..217ec9dbd2 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 @@ static void console_scrollup(void)
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 @@ static void lcd_drawchars(ushort x, ushort y, uchar *str, int count)
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 @@ static void lcd_drawchars(ushort x, ushort y, uchar *str, int count)
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 void lcd_drawchars(ushort x, ushort y, uchar *str, int count)
}
}
-/*----------------------------------------------------------------------*/
-
-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 @@ void lcd_clear(void)
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 @@ static void lcd_setbgcolor(int color)
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 @@ int lcd_display_bitmap(ulong bmp_image, int x, int y)
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 @@ int lcd_display_bitmap(ulong bmp_image, int x, int y)
}
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 f1d128caa9..404572729a 100644
--- a/doc/README.android-fastboot
+++ b/doc/README.android-fastboot
@@ -38,6 +38,10 @@ CONFIG_G_DNL_VENDOR_NUM
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 6a1d2a5c7e..b950a4174f 100644
--- a/doc/README.scrapyard
+++ b/doc/README.scrapyard
@@ -5,23 +5,25 @@ by unnoticed, but often build errors will result. If nobody cares any
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 @@ zpc1900 powerpc mpc8260 6f80bb48 2014-05-30 Yuli Barcohe
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 @@ MVS1 powerpc MPC823 306620b 2008-08-26 Andre Schwar
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 0985791293..70405f2c96 100644
--- a/doc/git-mailrc
+++ b/doc/git-mailrc
@@ -106,10 +106,11 @@ alias sh superh
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 a6ab543de4..b2f89fcc65 100644
--- a/doc/uImage.FIT/signature.txt
+++ b/doc/uImage.FIT/signature.txt
@@ -66,7 +66,8 @@ Creating an RSA key and certificate
-----------------------------------
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 @@ For RSA the following are mandatory:
- 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 def628dcdc..5cc535efdd 100644
--- a/drivers/dfu/Makefile
+++ b/drivers/dfu/Makefile
@@ -9,3 +9,4 @@ obj-$(CONFIG_DFU_FUNCTION) += dfu.o
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 dc09ff6466..3512b149c5 100644
--- a/drivers/dfu/dfu.c
+++ b/drivers/dfu/dfu.c
@@ -44,7 +44,7 @@ static int dfu_find_alt_num(const char *s)
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 @@ int dfu_init_env_entities(char *interface, int dev)
}
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 @@ unsigned long dfu_get_buf_size(void)
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 @@ unsigned char *dfu_get_buf(void)
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 @@ static int dfu_write_buffer_drain(struct dfu_entity *dfu)
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 @@ int dfu_flush(struct dfu_entity *dfu, void *buf, int size, int blk_seq_num)
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 @@ int dfu_write(struct dfu_entity *dfu, void *buf, int size, int blk_seq_num)
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 @@ int dfu_write(struct dfu_entity *dfu, void *buf, int size, int blk_seq_num)
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 @@ int dfu_write(struct dfu_entity *dfu, void *buf, int size, int blk_seq_num)
/* 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 @@ int dfu_write(struct dfu_entity *dfu, void *buf, int size, int blk_seq_num)
/* 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 @@ static int dfu_read_buffer_fill(struct dfu_entity *dfu, void *buf, int size)
dfu->i_buf += chunk;
dfu->b_left -= chunk;
- dfu->r_left -= chunk;
size -= chunk;
buf += chunk;
readn += chunk;
@@ -309,14 +320,23 @@ int dfu_read(struct dfu_entity *dfu, void *buf, int size, int blk_seq_num)
__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 @@ int dfu_read(struct dfu_entity *dfu, void *buf, int size, int blk_seq_num)
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 @@ int dfu_read(struct dfu_entity *dfu, void *buf, int size, int blk_seq_num)
}
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 @@ void dfu_free_entities(void)
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 @@ void dfu_free_entities(void)
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 @@ int dfu_config_entities(char *env, char *interface, int num)
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 63cc876612..72fa03eeda 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 @@ static int mmc_access_part(struct dfu_entity *dfu, struct mmc *mmc, int part)
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_access_part(struct dfu_entity *dfu, struct mmc *mmc, int part)
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 @@ static int mmc_block_op(enum dfu_op op, struct dfu_entity *dfu,
}
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_buffer(struct dfu_entity *dfu, void *buf, long *len)
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 @@ static int mmc_file_op(enum dfu_op op, struct dfu_entity *dfu,
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 @@ static int mmc_file_op(enum dfu_op op, struct dfu_entity *dfu,
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 @@ int dfu_flush_medium_mmc(struct dfu_entity *dfu)
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 @@ int dfu_read_medium_mmc(struct dfu_entity *dfu, u64 offset, void *buf,
* 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 @@ int dfu_fill_entity_mmc(struct dfu_entity *dfu, char *s)
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 @@ int dfu_fill_entity_mmc(struct dfu_entity *dfu, char *s)
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 @@ int dfu_fill_entity_mmc(struct dfu_entity *dfu, char *s)
}
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 ccdbef6b75..f9ee18999a 100644
--- a/drivers/dfu/dfu_nand.c
+++ b/drivers/dfu/dfu_nand.c
@@ -114,6 +114,11 @@ static int dfu_write_medium_nand(struct dfu_entity *dfu,
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 @@ static int dfu_read_medium_nand(struct dfu_entity *dfu, u64 offset, void *buf,
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 @@ unsigned int dfu_polltimeout_nand(struct dfu_entity *dfu)
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 @@ int dfu_fill_entity_nand(struct dfu_entity *dfu, char *s)
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 335a8e1f24..e094a946f6 100644
--- a/drivers/dfu/dfu_ram.c
+++ b/drivers/dfu/dfu_ram.c
@@ -41,18 +41,18 @@ static int dfu_write_medium_ram(struct dfu_entity *dfu, u64 offset,
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 @@ int dfu_fill_entity_ram(struct dfu_entity *dfu, char *s)
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 0000000000..91f6df220b
--- /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 8b2821b762..a79c3919dd 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 3320b3d08d..0000000000
--- 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 c58fe50b72..2b29cd89f8 100644
--- a/drivers/net/phy/vitesse.c
+++ b/drivers/net/phy/vitesse.c
@@ -126,7 +126,6 @@ static int cis8204_config(struct phy_device *phydev)
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 8e7052dda7..079f67d380 100644
--- a/drivers/serial/ns16550.c
+++ b/drivers/serial/ns16550.c
@@ -81,7 +81,7 @@ void NS16550_init(NS16550_t com_port, int baud_divisor)
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 4413e69118..dafeed742d 100644
--- a/drivers/serial/serial_ns16550.c
+++ b/drivers/serial/serial_ns16550.c
@@ -122,15 +122,6 @@ static int calc_divisor (NS16550_t port)
{
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 0826d59ab2..144a925394 100644
--- a/drivers/serial/serial_sh.c
+++ b/drivers/serial/serial_sh.c
@@ -49,9 +49,15 @@ static struct uart_port sh_sci = {
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 341997c8ec..fe8cde4ded 100644
--- a/drivers/serial/serial_sh.h
+++ b/drivers/serial/serial_sh.h
@@ -588,7 +588,8 @@ SCIF_FNS(SCSPTR, 0, 0, 0, 0)
#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 @@ static inline int scbrr_calc(struct uart_port port, int bps, int clk)
#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 21a3ef4d97..538b6d715d 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 66becdc782..4eea907d2e 100644
--- a/drivers/usb/gadget/Makefile
+++ b/drivers/usb/gadget/Makefile
@@ -31,7 +31,6 @@ ifdef CONFIG_USB_DEVICE
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 859fe828de..9863dec44d 100644
--- a/drivers/usb/gadget/f_dfu.c
+++ b/drivers/usb/gadget/f_dfu.c
@@ -162,17 +162,27 @@ static void dfu_set_poll_timeout(struct dfu_status *dstat, unsigned int ms)
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 @@ static int dfu_set_alt(struct usb_function *f, unsigned intf, unsigned alt)
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 4e06273f7f..c85b0fbd3c 100644
--- a/drivers/usb/gadget/f_thor.c
+++ b/drivers/usb/gadget/f_thor.c
@@ -142,7 +142,8 @@ static long long int download_head(unsigned long long total,
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 long long int download_head(unsigned long long total,
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 bdc1b886f5..959df8cdcd 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 @@ int udc_init (void)
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 @@ int udc_init (void)
/* 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 049e4c4e6b..0d1a726d35 100644
--- a/drivers/usb/host/ehci-rmobile.c
+++ b/drivers/usb/host/ehci-rmobile.c
@@ -21,13 +21,16 @@ static u32 usb_base_address[CONFIG_USB_MAX_CONTROLLER_COUNT] = {
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 945f35dc5d..93a91c3fa6 100644
--- a/drivers/video/Makefile
+++ b/drivers/video/Makefile
@@ -41,3 +41,4 @@ obj-$(CONFIG_VIDEO_SMI_LYNXEM) += smiLynxEM.o videomodes.o
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 0000000000..ab9894102d
--- /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 0000000000..8a0b131495
--- /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 3d2741f223..091b58fb47 100644
--- a/drivers/video/ipu.h
+++ b/drivers/video/ipu.h
@@ -176,6 +176,14 @@ typedef union {
} 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 cefd2dc14a..948e1fc401 100644
--- a/drivers/video/ipu_disp.c
+++ b/drivers/video/ipu_disp.c
@@ -33,7 +33,7 @@ enum csc_type_t {
struct dp_csc_param_t {
int mode;
- void *coeff;
+ const int (*coeff)[5][3];
};
#define SYNC_WAVE 0
@@ -666,13 +666,16 @@ void ipu_dp_dc_disable(ipu_channel_t channel, unsigned char swap)
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 @@ void ipu_dp_dc_disable(ipu_channel_t channel, unsigned char swap)
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 21e9c99e0e..c2c134a7de 100644
--- a/drivers/video/ipu_regs.h
+++ b/drivers/video/ipu_regs.h
@@ -313,9 +313,12 @@ struct ipu_dmfc {
#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 417ce7b63b..cbdc22026d 100644
--- a/fs/ext4/ext4fs.c
+++ b/fs/ext4/ext4fs.c
@@ -182,6 +182,11 @@ int ext4fs_exists(const char *filename)
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 54f42eae0d..561921fa2d 100644
--- a/fs/fat/fat.c
+++ b/fs/fat/fat.c
@@ -1243,6 +1243,11 @@ int fat_exists(const char *filename)
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 ea15c5f447..dd680f39c9 100644
--- a/fs/fs.c
+++ b/fs/fs.c
@@ -46,6 +46,11 @@ static inline int fs_exists_unsupported(const char *filename)
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 @@ struct fstype_info {
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 @@ static struct fstype_info fstypes[] = {
.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 @@ static struct fstype_info fstypes[] = {
.close = ext4fs_close,
.ls = ext4fs_ls,
.exists = ext4fs_exists,
+ .size = ext4fs_size,
.read = ext4_read_file,
.write = fs_write_unsupported,
},
@@ -115,6 +123,7 @@ static struct fstype_info fstypes[] = {
.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 @@ static struct fstype_info fstypes[] = {
.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 @@ int fs_exists(const char *filename)
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 @@ int fs_write(const char *filename, ulong addr, int offset, int len)
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 85079788c9..ba6402c81c 100644
--- a/fs/sandbox/sandboxfs.c
+++ b/fs/sandbox/sandboxfs.c
@@ -80,6 +80,11 @@ int sandbox_fs_exists(const char *filename)
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 0000000000..90d990157f
--- /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 6795f28a11..3c2b61353b 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 f39a788e91..74c998f3d4 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 41f7973f2b..5482722561 100644
--- a/include/configs/omap1510.h
+++ b/include/configs/omap1510.h
@@ -612,22 +612,6 @@ typedef struct {
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 60f24895e5..2d69809480 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 1c770c90fe..c337e3016e 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 ""
-
-#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"
+#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
-#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 90f19626a3..7db1db6074 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 206975bcae..f537e4fdc4 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 26ffbc8e81..7e0a99908c 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 @@ enum dfu_device_type {
DFU_DEV_ONENAND,
DFU_DEV_NAND,
DFU_DEV_RAM,
+ DFU_DEV_SF,
};
enum dfu_layout {
@@ -35,9 +37,12 @@ enum dfu_layout {
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 @@ struct ram_internal_data {
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 @@ struct dfu_entity {
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 @@ struct dfu_entity {
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 @@ struct dfu_entity {
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 @@ char *dfu_extract_token(char** e, int *n);
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_write(struct dfu_entity *de, void *buf, int size, int blk_seq_num);
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 @@ static inline int dfu_fill_entity_mmc(struct dfu_entity *dfu, char *s)
#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 @@ static inline int dfu_fill_entity_nand(struct dfu_entity *dfu, char *s)
#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 fbbb002b16..6c419f3a23 100644
--- a/include/ext4fs.h
+++ b/include/ext4fs.h
@@ -136,6 +136,7 @@ void ext4fs_close(void);
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 63cf78779b..20ca3f3dca 100644
--- a/include/fat.h
+++ b/include/fat.h
@@ -198,6 +198,7 @@ int file_cd(const char *path);
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 fd44d7e2f6..1bda686a0b 100644
--- a/include/fdt_support.h
+++ b/include/fdt_support.h
@@ -76,7 +76,7 @@ void ft_cpu_setup(void *blob, bd_t *bd);
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 26de0539f7..06a45f2788 100644
--- a/include/fs.h
+++ b/include/fs.h
@@ -51,6 +51,13 @@ int fs_ls(const char *dirname);
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 @@ int fs_write(const char *filename, ulong addr, int offset, int len);
* 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 3e8f78d583..ca2fe862ce 100644
--- a/include/image.h
+++ b/include/image.h
@@ -424,6 +424,7 @@ enum fit_load_op {
#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 cc2ee3f956..ea5860c861 100644
--- a/include/lcd.h
+++ b/include/lcd.h
@@ -26,8 +26,6 @@ void lcd_enable(void);
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 @@ void lcd_sync(void);
#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 @@ void lcd_sync(void);
# 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 9eefaaf5f8..a1ef1e15df 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 *fdt_get_alias_namelen(const void *fdt,
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 @@ int fdt_parent_offset(const void *fdt, int nodeoffset);
* 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 @@ int fdt_node_check_compatible(const void *fdt, int nodeoffset,
* 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_node_offset_by_compatible(const void *fdt, int startoffset,
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_nop_node(void *fdt, int nodeoffset);
/**********************************************************************/
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 17f829f6f9..d1f3a906c0 100644
--- a/include/ns16550.h
+++ b/include/ns16550.h
@@ -64,8 +64,6 @@ struct NS16550 {
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 @@ typedef struct NS16550 *NS16550_t;
#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 a51ad13044..e7c32623e1 100644
--- a/include/sandboxfs.h
+++ b/include/sandboxfs.h
@@ -26,6 +26,7 @@ long sandbox_fs_read_at(const char *filename, unsigned long pos,
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 325751ab7e..fd08a617fb 100644
--- a/include/u-boot/rsa.h
+++ b/include/u-boot/rsa.h
@@ -27,6 +27,7 @@ struct rsa_public_key {
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 1f545ec1b0..b2e0c6b6f5 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 a02c9b02ad..6fe79e0b06 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 0000000000..76054d98e5
--- /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 6fa4f13073..bec8b8ad89 100644
--- a/lib/libfdt/fdt_rw.c
+++ b/lib/libfdt/fdt_rw.c
@@ -43,9 +43,9 @@ static int _fdt_rw_check_header(void *fdt)
#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 580b57024f..320a914991 100644
--- a/lib/libfdt/fdt_sw.c
+++ b/lib/libfdt/fdt_sw.c
@@ -62,6 +62,38 @@ int fdt_create(void *buf, int bufsize)
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 13cbc9af2a..9a79fe85dd 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 49a3c9e01e..41a2be4635 100644
--- a/lib/lmb.c
+++ b/lib/lmb.c
@@ -295,7 +295,10 @@ phys_addr_t __lmb_alloc_base(struct lmb *lmb, phys_size_t size, ulong align, phy
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 83f5e87838..5d9716f013 100644
--- a/lib/rsa/rsa-sign.c
+++ b/lib/rsa/rsa-sign.c
@@ -76,6 +76,7 @@ static int rsa_get_pub_key(const char *keydir, const char *name, RSA **rsap)
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 @@ err_priv:
}
/*
+ * 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 @@ int rsa_get_params(RSA *key, uint32_t *n0_invp, BIGNUM **modulusp,
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 @@ static int fdt_add_bignum(void *blob, int noffset, const char *prop_name,
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 @@ int rsa_add_verify_data(struct image_sign_info *info, void *keydest)
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 @@ int rsa_add_verify_data(struct image_sign_info *info, void *keydest)
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 bcb906368d..4ef19b66f4 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 void subtract_modulus(const struct rsa_public_key *key, uint32_t num[])
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 @@ static void montgomery_mul(const struct rsa_public_key *key,
}
/**
+ * 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 @@ static int pow_mod(const struct rsa_public_key *key, uint32_t *inout)
{
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 @@ static int pow_mod(const struct rsa_public_key *key, uint32_t *inout)
}
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);
- 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 */
+ 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;
}
- montgomery_mul(key, result, acc, val); /* result = XX * a / R mod M */
+
+ 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]));
+
+ 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]));
+ }
+ }
+
+ /* 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 @@ static int rsa_verify_with_keynode(struct image_sign_info *info,
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 @@ static int rsa_verify_with_keynode(struct image_sign_info *info,
}
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 fdb97cb562..a4f6db570c 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 @@ BootpHandler(uchar *pkt, unsigned dest, IPaddr_t sip, unsigned src,
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 @@ static int BootpExtended(u8 *e)
}
#endif
+void BootpReset(void)
+{
+ BootpTry = 0;
+ bootp_start = get_timer(0);
+ bootp_timeout = 10;
+}
+
void
BootpRequest(void)
{
@@ -685,7 +709,7 @@ BootpRequest(void)
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 @@ DhcpHandler(uchar *pkt, unsigned dest, IPaddr_t sip, unsigned src,
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 ecbcc4d509..3b95a0a2de 100644
--- a/net/bootp.h
+++ b/net/bootp.h
@@ -65,6 +65,7 @@ extern int BootpTry;
/* Send a BOOTP request */
+extern void BootpReset(void);
extern void BootpRequest(void);
/****************** DHCP Support *********************/
@@ -88,8 +89,6 @@ typedef enum { INIT,
#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 0f7625fde1..722089f3b9 100644
--- a/net/net.c
+++ b/net/net.c
@@ -385,14 +385,14 @@ restart:
#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 0000000000..7717d689bf
--- /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 0000000000..5176aba632
--- /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 0000000000..4133155ae9
--- /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 0000000000..2163a685a5
--- /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 8074fc6adc..6d7abb82bd 100755
--- a/test/vboot/vboot_test.sh
+++ b/test/vboot/vboot_test.sh
@@ -54,8 +54,16 @@ echo ${mkimage} -D "${dtc}"
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