diff options
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: */ @@ -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) { @@ -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); @@ -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__ */ @@ -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 |