summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--.mailmap1
-rw-r--r--.travis.yml4
-rw-r--r--Kconfig32
-rw-r--r--MAINTAINERS1
-rw-r--r--arch/arc/dts/axs10x_mb.dtsi34
-rw-r--r--arch/arc/dts/hsdk.dts7
-rw-r--r--arch/arc/include/asm/arcregs.h3
-rw-r--r--arch/arc/lib/start.S9
-rw-r--r--arch/arm/cpu/armv8/Kconfig11
-rw-r--r--arch/arm/cpu/armv8/Makefile4
-rw-r--r--arch/arm/cpu/armv8/exceptions.S132
-rw-r--r--arch/arm/cpu/armv8/start.S19
-rw-r--r--arch/arm/dts/stm32429i-eval.dts3
-rw-r--r--arch/arm/dts/sunxi-u-boot.dtsi2
-rw-r--r--arch/arm/dts/tegra-u-boot.dtsi6
-rw-r--r--arch/arm/mach-imx/mx7/Kconfig2
-rw-r--r--arch/arm/mach-tegra/board2.c2
-rw-r--r--arch/sandbox/include/asm/clk.h8
-rw-r--r--arch/x86/dts/u-boot.dtsi24
-rw-r--r--board/Marvell/openrd/MAINTAINERS10
-rw-r--r--board/freescale/ls1046ardb/MAINTAINERS1
-rw-r--r--board/synopsys/axs10x/config.mk23
-rw-r--r--board/synopsys/axs10x/headerize-axs.py176
-rw-r--r--board/synopsys/hsdk/README10
-rw-r--r--board/synopsys/hsdk/config.mk2
-rw-r--r--board/technexion/pico-imx7d/MAINTAINERS5
-rw-r--r--board/ti/am335x/board.c6
-rw-r--r--board/ti/am335x/board.h8
-rw-r--r--board/ti/am335x/mux.c7
-rw-r--r--common/spl/spl.c4
-rw-r--r--common/spl/spl_ram.c2
-rw-r--r--configs/axs101_defconfig12
-rw-r--r--configs/axs103_defconfig12
-rw-r--r--configs/stm32f429-evaluation_defconfig1
-rw-r--r--configs/stm32f469-discovery_defconfig1
-rw-r--r--configs/stm32f746-disco_defconfig1
-rw-r--r--configs/stm32mp15_basic_defconfig2
-rw-r--r--doc/device-tree-bindings/adc/st,stm32-adc.txt141
-rw-r--r--doc/device-tree-bindings/gpio/snps,creg-gpio.txt43
-rw-r--r--drivers/adc/Kconfig16
-rw-r--r--drivers/adc/Makefile1
-rw-r--r--drivers/adc/adc-uclass.c35
-rw-r--r--drivers/adc/stm32-adc-core.c209
-rw-r--r--drivers/adc/stm32-adc-core.h51
-rw-r--r--drivers/adc/stm32-adc.c257
-rw-r--r--drivers/bootcount/bootcount.c13
-rw-r--r--drivers/clk/clk-uclass.c8
-rw-r--r--drivers/clk/clk_sandbox_test.c13
-rw-r--r--drivers/gpio/hsdk-creg-gpio.c103
-rw-r--r--drivers/mmc/arm_pl180_mmci.c73
-rw-r--r--drivers/mmc/arm_pl180_mmci.h1
-rw-r--r--include/clk.h10
-rw-r--r--include/configs/T104xRDB.h1
-rw-r--r--include/configs/am335x_evm.h2
-rw-r--r--include/configs/axs10x.h7
-rw-r--r--include/configs/omap3_cairo.h2
-rw-r--r--include/configs/omap3_logic.h6
-rw-r--r--include/configs/p1_p2_rdb_pc.h1
-rw-r--r--include/configs/ti_omap3_common.h2
-rw-r--r--include/spl.h2
-rw-r--r--scripts/.gitignore1
-rw-r--r--scripts/Makefile9
-rw-r--r--scripts/docproc.c580
-rw-r--r--test/dm/clk.c1
-rw-r--r--tools/binman/README135
-rw-r--r--tools/binman/README.entries585
-rwxr-xr-xtools/binman/binman.py22
-rw-r--r--tools/binman/bsection.py153
-rw-r--r--tools/binman/cmdline.py6
-rw-r--r--tools/binman/control.py35
-rw-r--r--tools/binman/elf.py10
-rw-r--r--tools/binman/elf_test.py33
-rw-r--r--tools/binman/entry.py267
-rw-r--r--tools/binman/etype/_testing.py47
-rw-r--r--tools/binman/etype/blob.py16
-rw-r--r--tools/binman/etype/blob_named_by_arg.py34
-rw-r--r--tools/binman/etype/cros_ec_rw.py22
-rw-r--r--tools/binman/etype/fill.py32
-rw-r--r--tools/binman/etype/fmap.py61
-rw-r--r--tools/binman/etype/gbb.py96
-rw-r--r--tools/binman/etype/intel_cmc.py10
-rw-r--r--tools/binman/etype/intel_descriptor.py26
-rw-r--r--tools/binman/etype/intel_fsp.py14
-rw-r--r--tools/binman/etype/intel_me.py15
-rw-r--r--tools/binman/etype/intel_mrc.py11
-rw-r--r--tools/binman/etype/intel_vbt.py10
-rw-r--r--tools/binman/etype/intel_vga.py12
-rw-r--r--tools/binman/etype/section.py48
-rw-r--r--tools/binman/etype/text.py57
-rw-r--r--tools/binman/etype/u_boot.py16
-rw-r--r--tools/binman/etype/u_boot_dtb.py9
-rw-r--r--tools/binman/etype/u_boot_dtb_with_ucode.py22
-rw-r--r--tools/binman/etype/u_boot_img.py11
-rw-r--r--tools/binman/etype/u_boot_nodtb.py11
-rw-r--r--tools/binman/etype/u_boot_spl.py21
-rw-r--r--tools/binman/etype/u_boot_spl_bss_pad.py16
-rw-r--r--tools/binman/etype/u_boot_spl_dtb.py11
-rw-r--r--tools/binman/etype/u_boot_spl_nodtb.py12
-rw-r--r--tools/binman/etype/u_boot_tpl.py43
-rw-r--r--tools/binman/etype/u_boot_tpl_dtb.py25
-rw-r--r--tools/binman/etype/u_boot_ucode.py12
-rw-r--r--tools/binman/etype/u_boot_with_ucode_ptr.py44
-rw-r--r--tools/binman/etype/vblock.py74
-rw-r--r--tools/binman/etype/x86_start16.py14
-rw-r--r--tools/binman/etype/x86_start16_spl.py14
-rw-r--r--tools/binman/fmap_util.py109
-rw-r--r--tools/binman/ftest.py428
-rw-r--r--tools/binman/image.py16
-rw-r--r--tools/binman/test/08_pack.dts2
-rw-r--r--tools/binman/test/12_pack_inv_align.dts2
-rw-r--r--tools/binman/test/14_pack_overlap.dts2
-rw-r--r--tools/binman/test/21_image_pad.dts2
-rw-r--r--tools/binman/test/24_sorted.dts6
-rw-r--r--tools/binman/test/25_pack_zero_size.dts2
-rw-r--r--tools/binman/test/27_pack_4gb_no_size.dts6
-rw-r--r--tools/binman/test/28_pack_4gb_outside.dts6
-rw-r--r--tools/binman/test/29_x86-rom.dts6
-rw-r--r--tools/binman/test/30_x86-rom-me-no-desc.dts4
-rw-r--r--tools/binman/test/31_x86-rom-me.dts4
-rw-r--r--tools/binman/test/34_x86_ucode.dts2
-rw-r--r--tools/binman/test/35_x86_single_ucode.dts2
-rw-r--r--tools/binman/test/37_x86_no_ucode.dts2
-rw-r--r--tools/binman/test/38_x86_ucode_missing_node.dts2
-rw-r--r--tools/binman/test/39_x86_ucode_missing_node2.dts2
-rw-r--r--tools/binman/test/40_x86_ucode_not_in_image.dts2
-rw-r--r--tools/binman/test/44_x86_optional_ucode.dts2
-rw-r--r--tools/binman/test/45_prop_test.dts4
-rw-r--r--tools/binman/test/49_x86_ucode_spl.dts2
-rw-r--r--tools/binman/test/53_symbols.dts2
-rw-r--r--tools/binman/test/55_sections.dts4
-rw-r--r--tools/binman/test/58_x86_ucode_spl_needs_retry.dts2
-rw-r--r--tools/binman/test/62_entry_args.dts14
-rw-r--r--tools/binman/test/63_entry_args_missing.dts13
-rw-r--r--tools/binman/test/64_entry_args_required.dts14
-rw-r--r--tools/binman/test/65_entry_args_unknown_datatype.dts15
-rw-r--r--tools/binman/test/66_text.dts28
-rw-r--r--tools/binman/test/67_fmap.dts29
-rw-r--r--tools/binman/test/68_blob_named_by_arg.dts12
-rw-r--r--tools/binman/test/69_fill.dts15
-rw-r--r--tools/binman/test/70_fill_no_size.dts14
-rw-r--r--tools/binman/test/71_gbb.dts31
-rw-r--r--tools/binman/test/72_gbb_too_small.dts10
-rw-r--r--tools/binman/test/73_gbb_no_size.dts9
-rw-r--r--tools/binman/test/74_vblock.dts28
-rw-r--r--tools/binman/test/75_vblock_no_content.dts23
-rw-r--r--tools/binman/test/76_vblock_bad_phandle.dts24
-rw-r--r--tools/binman/test/77_vblock_bad_entry.dts27
-rw-r--r--tools/binman/test/78_u_boot_tpl.dts11
-rw-r--r--tools/binman/test/79_uses_pos.dts10
-rwxr-xr-xtools/binman/test/u_boot_binman_symsbin4921 -> 4924 bytes
-rw-r--r--tools/binman/test/u_boot_binman_syms.c6
-rw-r--r--tools/dtoc/fdt.py23
-rw-r--r--tools/dtoc/fdt_util.py96
-rwxr-xr-xtools/dtoc/test_fdt.py49
-rw-r--r--tools/patman/command.py8
-rw-r--r--tools/patman/tools.py80
156 files changed, 4381 insertions, 1118 deletions
diff --git a/.mailmap b/.mailmap
index d29703058db..1bee048d134 100644
--- a/.mailmap
+++ b/.mailmap
@@ -34,4 +34,5 @@ Wolfgang Denk <wdenk>
York Sun <yorksun@freescale.com>
York Sun <york.sun@nxp.com>
Łukasz Majewski <l.majewski@samsung.com>
+Lukasz Majewski <lukma@denx.de>
Mirza <Taimoor_Mirza@mentor.com>
diff --git a/.travis.yml b/.travis.yml
index 7b0eb6e4f6b..d5862066570 100644
--- a/.travis.yml
+++ b/.travis.yml
@@ -153,7 +153,7 @@ matrix:
- BUILDMAN="arm11 arm7 arm920t arm946es"
- env:
- JOB="arm926ejs"
- BUILDMAN="arm926ejs -x mx,siemens,atmel"
+ BUILDMAN="arm926ejs -x mx,siemens,atmel,kirkwood"
- env:
- BUILDMAN="atmel"
- env:
@@ -195,7 +195,7 @@ matrix:
- BUILDMAN="sandbox x86"
TOOLCHAIN="x86_64"
- env:
- - BUILDMAN="kirkwood"
+ - BUILDMAN="kirkwood -x openrd"
- env:
- BUILDMAN="mvebu"
- env:
diff --git a/Kconfig b/Kconfig
index 62235cae96c..7dc7798df4e 100644
--- a/Kconfig
+++ b/Kconfig
@@ -137,24 +137,24 @@ config SYS_MALLOC_F_LEN
initial serial device and any others that are needed.
config SPL_SYS_MALLOC_F_LEN
- hex "Size of malloc() pool in SPL before relocation"
- depends on SYS_MALLOC_F
- default SYS_MALLOC_F_LEN
- help
- Before relocation, memory is very limited on many platforms. Still,
- we can provide a small malloc() pool if needed. Driver model in
- particular needs this to operate, so that it can allocate the
- initial serial device and any others that are needed.
+ hex "Size of malloc() pool in SPL before relocation"
+ depends on SYS_MALLOC_F
+ default SYS_MALLOC_F_LEN
+ help
+ Before relocation, memory is very limited on many platforms. Still,
+ we can provide a small malloc() pool if needed. Driver model in
+ particular needs this to operate, so that it can allocate the
+ initial serial device and any others that are needed.
config TPL_SYS_MALLOC_F_LEN
- hex "Size of malloc() pool in TPL before relocation"
- depends on SYS_MALLOC_F
- default SYS_MALLOC_F_LEN
- help
- Before relocation, memory is very limited on many platforms. Still,
- we can provide a small malloc() pool if needed. Driver model in
- particular needs this to operate, so that it can allocate the
- initial serial device and any others that are needed.
+ hex "Size of malloc() pool in TPL before relocation"
+ depends on SYS_MALLOC_F
+ default SYS_MALLOC_F_LEN
+ help
+ Before relocation, memory is very limited on many platforms. Still,
+ we can provide a small malloc() pool if needed. Driver model in
+ particular needs this to operate, so that it can allocate the
+ initial serial device and any others that are needed.
menuconfig EXPERT
bool "Configure standard U-Boot features (expert users)"
diff --git a/MAINTAINERS b/MAINTAINERS
index fe8423530c1..1bd583c9753 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -74,6 +74,7 @@ ARC HSDK CREG GPIO
M: Eugeniy Paltsev <Eugeniy.Paltsev@synopsys.com>
S: Maintained
L: uboot-snps-arc@synopsys.com
+F: doc/device-tree-bindings/gpio/snps,creg-gpio.txt
F: drivers/gpio/hsdk-creg-gpio.c
ARM
diff --git a/arch/arc/dts/axs10x_mb.dtsi b/arch/arc/dts/axs10x_mb.dtsi
index 3855a34dc20..dfc03810ca0 100644
--- a/arch/arc/dts/axs10x_mb.dtsi
+++ b/arch/arc/dts/axs10x_mb.dtsi
@@ -4,6 +4,10 @@
*/
/ {
+ aliases {
+ spi0 = &spi0;
+ };
+
axs10x_mb@e0000000 {
compatible = "simple-bus";
#address-cells = <1>;
@@ -56,5 +60,35 @@
reg-shift = <2>;
reg-io-width = <4>;
};
+
+ spi0: spi@0 {
+ compatible = "snps,dw-apb-ssi";
+ reg = <0x0 0x100>;
+ #address-cells = <1>;
+ #size-cells = <0>;
+ spi-max-frequency = <4000000>;
+ clocks = <&apbclk>;
+ clock-names = "spi_clk";
+ cs-gpio = <&cs_gpio 0>;
+ spi_flash@0 {
+ compatible = "spi-flash";
+ reg = <0>;
+ spi-max-frequency = <4000000>;
+ };
+ };
+
+ cs_gpio: gpio@11218 {
+ compatible = "snps,creg-gpio";
+ reg = <0x11218 0x4>;
+ gpio-controller;
+ #gpio-cells = <1>;
+ gpio-bank-name = "axs-spi-cs";
+ gpio-count = <1>;
+ gpio-first-shift = <0>;
+ gpio-bit-per-line = <2>;
+ gpio-activate-val = <1>;
+ gpio-deactivate-val = <3>;
+ gpio-default-val = <1>;
+ };
};
};
diff --git a/arch/arc/dts/hsdk.dts b/arch/arc/dts/hsdk.dts
index 264512877e9..e41e4ce84bc 100644
--- a/arch/arc/dts/hsdk.dts
+++ b/arch/arc/dts/hsdk.dts
@@ -101,11 +101,16 @@
};
cs_gpio: gpio@f00014b0 {
- compatible = "snps,hsdk-creg-gpio";
+ compatible = "snps,creg-gpio";
reg = <0xf00014b0 0x4>;
gpio-controller;
#gpio-cells = <1>;
gpio-bank-name = "hsdk-spi-cs";
gpio-count = <1>;
+ gpio-first-shift = <0>;
+ gpio-bit-per-line = <2>;
+ gpio-activate-val = <2>;
+ gpio-deactivate-val = <3>;
+ gpio-default-val = <1>;
};
};
diff --git a/arch/arc/include/asm/arcregs.h b/arch/arc/include/asm/arcregs.h
index 56ec11f789b..9920d2e7195 100644
--- a/arch/arc/include/asm/arcregs.h
+++ b/arch/arc/include/asm/arcregs.h
@@ -19,6 +19,9 @@
#define ARC_AUX_IDENTITY 0x04
#define ARC_AUX_STATUS32 0x0a
+/* STATUS32 Bits Positions */
+#define STATUS_AD_BIT 19 /* Enable unaligned access */
+
/* Instruction cache related auxiliary registers */
#define ARC_AUX_IC_IVIC 0x10
#define ARC_AUX_IC_CTRL 0x11
diff --git a/arch/arc/lib/start.S b/arch/arc/lib/start.S
index e573ce7718b..84959b41bdf 100644
--- a/arch/arc/lib/start.S
+++ b/arch/arc/lib/start.S
@@ -61,6 +61,15 @@ ENTRY(_start)
1:
#endif
+#ifdef __ARC_UNALIGNED__
+ /*
+ * Enable handling of unaligned access in the CPU as by default
+ * this HW feature is disabled while GCC starting from 8.1.0
+ * unconditionally uses it for ARC HS cores.
+ */
+ flag 1 << STATUS_AD_BIT
+#endif
+
/* Establish C runtime stack and frame */
mov %sp, CONFIG_SYS_INIT_SP_ADDR
mov %fp, %sp
diff --git a/arch/arm/cpu/armv8/Kconfig b/arch/arm/cpu/armv8/Kconfig
index 741e15c7737..c8bebabdf6f 100644
--- a/arch/arm/cpu/armv8/Kconfig
+++ b/arch/arm/cpu/armv8/Kconfig
@@ -1,5 +1,16 @@
if ARM64
+config ARMV8_SPL_EXCEPTION_VECTORS
+ bool "Install crash dump exception vectors"
+ depends on SPL
+ default y
+ help
+ The default exception vector table is only used for the crash
+ dump, but still takes quite a lot of space in the image size.
+
+ Say N here if you are running out of code space in the image
+ and want to save some space at the cost of less debugging info.
+
config ARMV8_MULTIENTRY
bool "Enable multiple CPUs to enter into U-Boot"
diff --git a/arch/arm/cpu/armv8/Makefile b/arch/arm/cpu/armv8/Makefile
index d1d4ffecfd2..52c8daa0496 100644
--- a/arch/arm/cpu/armv8/Makefile
+++ b/arch/arm/cpu/armv8/Makefile
@@ -10,7 +10,11 @@ ifndef CONFIG_$(SPL_TPL_)TIMER
obj-$(CONFIG_SYS_ARCH_TIMER) += generic_timer.o
endif
obj-y += cache_v8.o
+ifdef CONFIG_SPL_BUILD
+obj-$(CONFIG_ARMV8_SPL_EXCEPTION_VECTORS) += exceptions.o
+else
obj-y += exceptions.o
+endif
obj-y += cache.o
obj-y += tlb.o
obj-y += transition.o
diff --git a/arch/arm/cpu/armv8/exceptions.S b/arch/arm/cpu/armv8/exceptions.S
index 1a78a5d1dcc..a15af72e023 100644
--- a/arch/arm/cpu/armv8/exceptions.S
+++ b/arch/arm/cpu/armv8/exceptions.S
@@ -11,7 +11,26 @@
#include <linux/linkage.h>
/*
- * Exception vectors.
+ * AArch64 exception vectors:
+ * We have four types of exceptions:
+ * - synchronous: traps, data aborts, undefined instructions, ...
+ * - IRQ: group 1 (normal) interrupts
+ * - FIQ: group 0 or secure interrupts
+ * - SError: fatal system errors
+ * There are entries for all four of those for different contexts:
+ * - from same exception level, when using the SP_EL0 stack pointer
+ * - from same exception level, when using the SP_ELx stack pointer
+ * - from lower exception level, when this is AArch64
+ * - from lower exception level, when this is AArch32
+ * Each of those 16 entries have space for 32 instructions, each entry must
+ * be 128 byte aligned, the whole table must be 2K aligned.
+ * The 32 instructions are not enough to save and restore all registers and
+ * to branch to the actual handler, so we split this up:
+ * Each entry saves the LR, branches to the save routine, then to the actual
+ * handler, then to the restore routine. The save and restore routines are
+ * each split in half and stuffed in the unused gap between the entries.
+ * Also as we do not run anything in a lower exception level, we just provide
+ * the first 8 entries for exceptions from the same EL.
*/
.align 11
.globl vectors
@@ -22,52 +41,9 @@ vectors:
bl do_bad_sync
b exception_exit
- .align 7 /* Current EL IRQ Thread */
- stp x29, x30, [sp, #-16]!
- bl _exception_entry
- bl do_bad_irq
- b exception_exit
-
- .align 7 /* Current EL FIQ Thread */
- stp x29, x30, [sp, #-16]!
- bl _exception_entry
- bl do_bad_fiq
- b exception_exit
-
- .align 7 /* Current EL Error Thread */
- stp x29, x30, [sp, #-16]!
- bl _exception_entry
- bl do_bad_error
- b exception_exit
-
- .align 7 /* Current EL Synchronous Handler */
- stp x29, x30, [sp, #-16]!
- bl _exception_entry
- bl do_sync
- b exception_exit
-
- .align 7 /* Current EL IRQ Handler */
- stp x29, x30, [sp, #-16]!
- bl _exception_entry
- bl do_irq
- b exception_exit
-
- .align 7 /* Current EL FIQ Handler */
- stp x29, x30, [sp, #-16]!
- bl _exception_entry
- bl do_fiq
- b exception_exit
-
- .align 7 /* Current EL Error Handler */
- stp x29, x30, [sp, #-16]!
- bl _exception_entry
- bl do_error
- b exception_exit
-
/*
- * Enter Exception.
- * This will save the processor state that is ELR/X0~X30
- * to the stack frame.
+ * Save (most of) the GP registers to the stack frame.
+ * This is the first part of the shared routine called into from all entries.
*/
_exception_entry:
stp x27, x28, [sp, #-16]!
@@ -84,7 +60,19 @@ _exception_entry:
stp x5, x6, [sp, #-16]!
stp x3, x4, [sp, #-16]!
stp x1, x2, [sp, #-16]!
+ b _save_el_regs /* jump to the second part */
+ .align 7 /* Current EL IRQ Thread */
+ stp x29, x30, [sp, #-16]!
+ bl _exception_entry
+ bl do_bad_irq
+ b exception_exit
+
+/*
+ * Save exception specific context: ESR and ELR, for all exception levels.
+ * This is the second part of the shared routine called into from all entries.
+ */
+_save_el_regs:
/* Could be running at EL3/EL2/EL1 */
switch_el x11, 3f, 2f, 1f
3: mrs x1, esr_el3
@@ -100,16 +88,36 @@ _exception_entry:
mov x0, sp
ret
-
+ .align 7 /* Current EL FIQ Thread */
+ stp x29, x30, [sp, #-16]!
+ bl _exception_entry
+ bl do_bad_fiq
+ /* falling through to _exception_exit */
+/*
+ * Restore the exception return address, for all exception levels.
+ * This is the first part of the shared routine called into from all entries.
+ */
exception_exit:
ldp x2, x0, [sp],#16
switch_el x11, 3f, 2f, 1f
3: msr elr_el3, x2
- b 0f
+ b _restore_regs
2: msr elr_el2, x2
- b 0f
+ b _restore_regs
1: msr elr_el1, x2
-0:
+ b _restore_regs /* jump to the second part */
+
+ .align 7 /* Current EL Error Thread */
+ stp x29, x30, [sp, #-16]!
+ bl _exception_entry
+ bl do_bad_error
+ b exception_exit
+
+/*
+ * Restore the general purpose registers from the exception stack, then return.
+ * This is the second part of the shared routine called into from all entries.
+ */
+_restore_regs:
ldp x1, x2, [sp],#16
ldp x3, x4, [sp],#16
ldp x5, x6, [sp],#16
@@ -126,3 +134,27 @@ exception_exit:
ldp x27, x28, [sp],#16
ldp x29, x30, [sp],#16
eret
+
+ .align 7 /* Current EL (SP_ELx) Synchronous Handler */
+ stp x29, x30, [sp, #-16]!
+ bl _exception_entry
+ bl do_sync
+ b exception_exit
+
+ .align 7 /* Current EL (SP_ELx) IRQ Handler */
+ stp x29, x30, [sp, #-16]!
+ bl _exception_entry
+ bl do_irq
+ b exception_exit
+
+ .align 7 /* Current EL (SP_ELx) FIQ Handler */
+ stp x29, x30, [sp, #-16]!
+ bl _exception_entry
+ bl do_fiq
+ b exception_exit
+
+ .align 7 /* Current EL (SP_ELx) Error Handler */
+ stp x29, x30, [sp, #-16]!
+ bl _exception_entry
+ bl do_error
+ b exception_exit
diff --git a/arch/arm/cpu/armv8/start.S b/arch/arm/cpu/armv8/start.S
index d4db4d044f6..12a78ee38b4 100644
--- a/arch/arm/cpu/armv8/start.S
+++ b/arch/arm/cpu/armv8/start.S
@@ -87,13 +87,22 @@ pie_fixup_done:
#ifdef CONFIG_SYS_RESET_SCTRL
bl reset_sctrl
#endif
+
+#if defined(CONFIG_ARMV8__SPL_EXCEPTION_VECTORS) || !defined(CONFIG_SPL_BUILD)
+.macro set_vbar, regname, reg
+ msr \regname, \reg
+.endm
+ adr x0, vectors
+#else
+.macro set_vbar, regname, reg
+.endm
+#endif
/*
* Could be EL3/EL2/EL1, Initial State:
* Little Endian, MMU Disabled, i/dCache Disabled
*/
- adr x0, vectors
switch_el x1, 3f, 2f, 1f
-3: msr vbar_el3, x0
+3: set_vbar vbar_el3, x0
mrs x0, scr_el3
orr x0, x0, #0xf /* SCR_EL3.NS|IRQ|FIQ|EA */
msr scr_el3, x0
@@ -103,11 +112,11 @@ pie_fixup_done:
msr cntfrq_el0, x0 /* Initialize CNTFRQ */
#endif
b 0f
-2: msr vbar_el2, x0
+2: set_vbar vbar_el2, x0
mov x0, #0x33ff
msr cptr_el2, x0 /* Enable FP/SIMD */
b 0f
-1: msr vbar_el1, x0
+1: set_vbar vbar_el1, x0
mov x0, #3 << 20
msr cpacr_el1, x0 /* Enable FP/SIMD */
0:
@@ -345,6 +354,7 @@ ENDPROC(smp_kick_all_cpus)
/*-----------------------------------------------------------------------*/
ENTRY(c_runtime_cpu_setup)
+#if defined(CONFIG_ARMV8__SPL_EXCEPTION_VECTORS) || !defined(CONFIG_SPL_BUILD)
/* Relocate vBAR */
adr x0, vectors
switch_el x1, 3f, 2f, 1f
@@ -354,6 +364,7 @@ ENTRY(c_runtime_cpu_setup)
b 0f
1: msr vbar_el1, x0
0:
+#endif
ret
ENDPROC(c_runtime_cpu_setup)
diff --git a/arch/arm/dts/stm32429i-eval.dts b/arch/arm/dts/stm32429i-eval.dts
index c16594b7e43..f6753a4d1a1 100644
--- a/arch/arm/dts/stm32429i-eval.dts
+++ b/arch/arm/dts/stm32429i-eval.dts
@@ -223,8 +223,7 @@
&sdio {
status = "okay";
vmmc-supply = <&mmc_vcard>;
- cd-gpios = <&stmpegpio 15 GPIO_ACTIVE_HIGH>;
- cd-inverted;
+ cd-gpios = <&stmpegpio 15 GPIO_ACTIVE_LOW>;
pinctrl-names = "default", "opendrain";
pinctrl-0 = <&sdio_pins>;
pinctrl-1 = <&sdio_pins_od>;
diff --git a/arch/arm/dts/sunxi-u-boot.dtsi b/arch/arm/dts/sunxi-u-boot.dtsi
index 5adfd9bca2e..8a9f2a6417d 100644
--- a/arch/arm/dts/sunxi-u-boot.dtsi
+++ b/arch/arm/dts/sunxi-u-boot.dtsi
@@ -8,7 +8,7 @@
filename = "spl/sunxi-spl.bin";
};
u-boot-img {
- pos = <CONFIG_SPL_PAD_TO>;
+ offset = <CONFIG_SPL_PAD_TO>;
};
};
};
diff --git a/arch/arm/dts/tegra-u-boot.dtsi b/arch/arm/dts/tegra-u-boot.dtsi
index 4f692ee9757..fe19619919e 100644
--- a/arch/arm/dts/tegra-u-boot.dtsi
+++ b/arch/arm/dts/tegra-u-boot.dtsi
@@ -15,7 +15,7 @@
u-boot-spl {
};
u-boot {
- pos = <(U_BOOT_OFFSET)>;
+ offset = <(U_BOOT_OFFSET)>;
};
};
@@ -26,7 +26,7 @@
u-boot-spl {
};
u-boot {
- pos = <(U_BOOT_OFFSET)>;
+ offset = <(U_BOOT_OFFSET)>;
};
};
@@ -36,7 +36,7 @@
u-boot-spl {
};
u-boot-nodtb {
- pos = <(U_BOOT_OFFSET)>;
+ offset = <(U_BOOT_OFFSET)>;
};
};
};
diff --git a/arch/arm/mach-imx/mx7/Kconfig b/arch/arm/mach-imx/mx7/Kconfig
index 1acd7f3c7cb..232f33285d4 100644
--- a/arch/arm/mach-imx/mx7/Kconfig
+++ b/arch/arm/mach-imx/mx7/Kconfig
@@ -43,6 +43,7 @@ config TARGET_PICO_IMX7D
select DM_THERMAL
select MX7D
select SUPPORT_SPL
+ imply CMD_DM
config TARGET_WARP7
bool "warp7"
@@ -51,7 +52,6 @@ config TARGET_WARP7
select DM_THERMAL
select MX7D
imply CMD_DM
- imply CMD_DM
config TARGET_COLIBRI_IMX7
bool "Support Colibri iMX7S/iMX7D modules"
diff --git a/arch/arm/mach-tegra/board2.c b/arch/arm/mach-tegra/board2.c
index 5ecadf705e7..421a71b3014 100644
--- a/arch/arm/mach-tegra/board2.c
+++ b/arch/arm/mach-tegra/board2.c
@@ -252,7 +252,7 @@ static ulong carveout_size(void)
#elif defined(CONFIG_ARMV7_SECURE_RESERVE_SIZE)
// BASE+SIZE might not == 4GB. If so, we want the carveout to cover
// from BASE to 4GB, not BASE to BASE+SIZE.
- return (0 - CONFIG_ARMV7_SECURE_BASE);
+ return (0 - CONFIG_ARMV7_SECURE_BASE) & ~(SZ_2M - 1);
#else
return 0;
#endif
diff --git a/arch/sandbox/include/asm/clk.h b/arch/sandbox/include/asm/clk.h
index d85cbadf6ec..2b1c49f7830 100644
--- a/arch/sandbox/include/asm/clk.h
+++ b/arch/sandbox/include/asm/clk.h
@@ -138,5 +138,13 @@ int sandbox_clk_test_free(struct udevice *dev);
* @return: 0 if OK, or a negative error code.
*/
int sandbox_clk_test_release_bulk(struct udevice *dev);
+/**
+ * sandbox_clk_test_valid - Ask the sandbox clock test device to check its
+ * clocks are valid.
+ *
+ * @dev: The sandbox clock test (client) devivce.
+ * @return: 0 if OK, or a negative error code.
+ */
+int sandbox_clk_test_valid(struct udevice *dev);
#endif
diff --git a/arch/x86/dts/u-boot.dtsi b/arch/x86/dts/u-boot.dtsi
index 1253fa51c22..1050236330a 100644
--- a/arch/x86/dts/u-boot.dtsi
+++ b/arch/x86/dts/u-boot.dtsi
@@ -11,7 +11,7 @@
binman {
filename = "u-boot.rom";
end-at-4gb;
- sort-by-pos;
+ sort-by-offset;
pad-byte = <0xff>;
size = <CONFIG_ROM_SIZE>;
#ifdef CONFIG_HAVE_INTEL_ME
@@ -24,18 +24,18 @@
#endif
#ifdef CONFIG_SPL
u-boot-spl-with-ucode-ptr {
- pos = <CONFIG_SPL_TEXT_BASE>;
+ offset = <CONFIG_SPL_TEXT_BASE>;
};
u-boot-dtb-with-ucode2 {
type = "u-boot-dtb-with-ucode";
};
u-boot {
- pos = <0xfff00000>;
+ offset = <0xfff00000>;
};
#else
u-boot-with-ucode-ptr {
- pos = <CONFIG_SYS_TEXT_BASE>;
+ offset = <CONFIG_SYS_TEXT_BASE>;
};
#endif
u-boot-dtb-with-ucode {
@@ -45,45 +45,45 @@
};
#ifdef CONFIG_HAVE_MRC
intel-mrc {
- pos = <CONFIG_X86_MRC_ADDR>;
+ offset = <CONFIG_X86_MRC_ADDR>;
};
#endif
#ifdef CONFIG_HAVE_FSP
intel-fsp {
filename = CONFIG_FSP_FILE;
- pos = <CONFIG_FSP_ADDR>;
+ offset = <CONFIG_FSP_ADDR>;
};
#endif
#ifdef CONFIG_HAVE_CMC
intel-cmc {
filename = CONFIG_CMC_FILE;
- pos = <CONFIG_CMC_ADDR>;
+ offset = <CONFIG_CMC_ADDR>;
};
#endif
#ifdef CONFIG_HAVE_VGA_BIOS
intel-vga {
filename = CONFIG_VGA_BIOS_FILE;
- pos = <CONFIG_VGA_BIOS_ADDR>;
+ offset = <CONFIG_VGA_BIOS_ADDR>;
};
#endif
#ifdef CONFIG_HAVE_VBT
intel-vbt {
filename = CONFIG_VBT_FILE;
- pos = <CONFIG_VBT_ADDR>;
+ offset = <CONFIG_VBT_ADDR>;
};
#endif
#ifdef CONFIG_HAVE_REFCODE
intel-refcode {
- pos = <CONFIG_X86_REFCODE_ADDR>;
+ offset = <CONFIG_X86_REFCODE_ADDR>;
};
#endif
#ifdef CONFIG_SPL
x86-start16-spl {
- pos = <CONFIG_SYS_X86_START16>;
+ offset = <CONFIG_SYS_X86_START16>;
};
#else
x86-start16 {
- pos = <CONFIG_SYS_X86_START16>;
+ offset = <CONFIG_SYS_X86_START16>;
};
#endif
};
diff --git a/board/Marvell/openrd/MAINTAINERS b/board/Marvell/openrd/MAINTAINERS
index 3789a04c891..b24fff0a783 100644
--- a/board/Marvell/openrd/MAINTAINERS
+++ b/board/Marvell/openrd/MAINTAINERS
@@ -1,12 +1,8 @@
-OPENRD BOARD
-M: Albert ARIBAUD <albert-u-boot@aribaud.net>
-S: Maintained
+OPENRD / OPENRD_CLIENT BOARD
+#M: Albert ARIBAUD <albert-u-boot@aribaud.net>
+S: Orphaned (Since 2018-09)
F: board/Marvell/openrd/
F: include/configs/openrd.h
F: configs/openrd_base_defconfig
-
-OPENRD_CLIENT BOARD
-M: Albert ARIBAUD <albert-u-boot@aribaud.net>
-S: Maintained
F: configs/openrd_client_defconfig
F: configs/openrd_ultimate_defconfig
diff --git a/board/freescale/ls1046ardb/MAINTAINERS b/board/freescale/ls1046ardb/MAINTAINERS
index 79a2290974f..aac649a9428 100644
--- a/board/freescale/ls1046ardb/MAINTAINERS
+++ b/board/freescale/ls1046ardb/MAINTAINERS
@@ -5,6 +5,7 @@ F: board/freescale/ls1046ardb/
F: board/freescale/ls1046ardb/ls1046ardb.c
F: include/configs/ls1046ardb.h
F: configs/ls1046ardb_qspi_defconfig
+F: configs/ls1046ardb_qspi_spl_defconfig
F: configs/ls1046ardb_sdcard_defconfig
F: configs/ls1046ardb_emmc_defconfig
diff --git a/board/synopsys/axs10x/config.mk b/board/synopsys/axs10x/config.mk
new file mode 100644
index 00000000000..81ff498f818
--- /dev/null
+++ b/board/synopsys/axs10x/config.mk
@@ -0,0 +1,23 @@
+# SPDX-License-Identifier: GPL-2.0+
+#
+# Copyright (C) 2018 Synopsys, Inc. All rights reserved.
+
+bsp-generate: u-boot u-boot.bin
+ifdef CONFIG_ISA_ARCV2
+ $(Q)python3 $(srctree)/board/$(BOARDDIR)/headerize-axs.py \
+ --header-type v2 \
+ --arc-id 0x53 \
+ --spi-flash-offset 0x200000 \
+ --image $(srctree)/u-boot.bin \
+ --elf $(srctree)/u-boot
+else
+ $(Q)python3 $(srctree)/board/$(BOARDDIR)/headerize-axs.py \
+ --header-type v1 \
+ --arc-id 0x434 \
+ --spi-flash-offset 0x0 \
+ --image $(srctree)/u-boot.bin \
+ --elf $(srctree)/u-boot
+endif
+ $(Q)tools/mkimage -T script -C none -n 'uboot update script' \
+ -d $(srctree)/u-boot-update.txt \
+ $(srctree)/u-boot-update.img &> /dev/null
diff --git a/board/synopsys/axs10x/headerize-axs.py b/board/synopsys/axs10x/headerize-axs.py
new file mode 100644
index 00000000000..fa6aaf350c2
--- /dev/null
+++ b/board/synopsys/axs10x/headerize-axs.py
@@ -0,0 +1,176 @@
+#!/usr/bin/env python3
+
+#we can use binascii instead of zlib
+import os, getopt, sys, zlib
+from elftools.elf.elffile import ELFFile
+
+
+def usage(exit_code):
+ print("typical usage:")
+ print("AXS101:")
+ print(sys.argv[0] + \
+ " --header-type v1 --arc-id 0x434 --spi-flash-offset 0x0 --image u-boot.bin --elf u-boot")
+ print("AXS103:")
+ print(sys.argv[0] + \
+ " --header-type v2 --arc-id 0x53 --spi-flash-offset 0x200000 --image u-boot.bin --elf u-boot")
+ sys.exit(exit_code)
+
+
+def elf_get_entry(filename):
+ with open(filename, 'rb') as f:
+ elffile = ELFFile(f)
+ return elffile.header['e_entry']
+
+
+def calc_check_sum(filename):
+ # Calculate u-boot image check_sum: it is sum of all u-boot binary bytes
+ with open(filename, "rb") as file:
+ ba = bytearray(file.read())
+ return sum(ba) & 0xFF
+
+
+def arg_verify(uboot_bin_filename, uboot_elf_filename, header_type):
+ if not os.path.isfile(uboot_bin_filename):
+ print("uboot bin file not exists: " + uboot_bin_filename)
+ sys.exit(2)
+
+ if not os.path.isfile(uboot_elf_filename):
+ print("uboot elf file not exists: " + uboot_elf_filename)
+ sys.exit(2)
+
+ if header_type not in ("v1", "v2"):
+ print("unknown header type: " + header_type)
+ print("choose between 'v1' (most likely AXS101) and 'v2' (most likely AXS103)")
+ sys.exit(2)
+
+
+def main():
+ try:
+ opts, args = getopt.getopt(sys.argv[1:],
+ "ht:a:s:i:l:e:",
+ ["help", "header-type=", "arc-id=", "spi-flash-offset=", "image=", "elf="])
+ except getopt.GetoptError as err:
+ print(err)
+ usage(2)
+
+ # default filenames
+ uboot_elf_filename = "u-boot"
+ uboot_bin_filename = "u-boot.bin"
+ headerised_filename = "u-boot.head"
+ uboot_scrypt_file = "u-boot-update.txt"
+
+ # default values
+ spi_flash_offset = 0x200000
+ header_type = "v2"
+ arc_id = 0x53
+
+ # initial header values: place where preloader will store u-boot binary,
+ # should be equal to CONFIG_SYS_TEXT_BASE
+ image_copy_adr = 0x81000000
+
+ # initial constant header values, do not change these values
+ magic1 = 0xdeadbeafaf # big endian byte order
+ magic2 = [ # big endian byte order
+ 0x20202a2020202020202020202a20202020207c5c2e20202020202e2f7c20202020207c2d,
+ 0x2e5c2020202f2e2d7c20202020205c2020602d2d2d6020202f20202020202f205f202020,
+ 0x205f20205c20202020207c205f60712070205f207c2020202020272e5f3d2f205c3d5f2e,
+ 0x272020202020202020605c202f60202020202020202020202020206f2020202020202020]
+
+ for opt, arg in opts:
+ if opt in ('-h', "--help"): usage(0)
+ if opt in ('-t', "--header-type"): header_type = arg
+ if opt in ('-a', "--arc-id"): arc_id = int(arg, 16)
+ if opt in ('-s', "--spi-flash-offset"): spi_flash_offset = int(arg, 16)
+ if opt in ('-i', "--image"): uboot_bin_filename = arg
+ if opt in ('-e', "--elf"): uboot_elf_filename = arg
+
+ arg_verify(uboot_bin_filename, uboot_elf_filename, header_type)
+
+ uboot_img_size = os.path.getsize(uboot_bin_filename)
+ jump_address = elf_get_entry(uboot_elf_filename)
+ check_sum = calc_check_sum(uboot_bin_filename)
+
+ # Calculate header adresses depend on header type
+ if header_type == "v2":
+ image_copy_adr -= 0x4
+ uboot_img_size += 0x4
+ # we append image so we need to append checksum
+ jmpchk_sum = sum(jump_address.to_bytes(4, byteorder='big'))
+ check_sum = (check_sum + jmpchk_sum) & 0xFF
+ imade_jump_append = True
+ else:
+ imade_jump_append = False
+
+ # write header to file
+ with open(headerised_filename, "wb") as file:
+ file.write(arc_id.to_bytes(2, byteorder='little'))
+ file.write(uboot_img_size.to_bytes(4, byteorder='little'))
+ file.write(check_sum.to_bytes(1, byteorder='little'))
+ file.write(image_copy_adr.to_bytes(4, byteorder='little'))
+ file.write(magic1.to_bytes(5, byteorder='big'))
+ for i in range(16): file.write(0x00.to_bytes(1, byteorder='little'))
+ for byte in magic2: file.write(byte.to_bytes(36, byteorder='big'))
+ for i in range(224 - len(magic2) * 36):
+ file.write(0x00.to_bytes(1, byteorder='little'))
+ if imade_jump_append:
+ file.write(jump_address.to_bytes(4, byteorder='little'))
+
+ # append u-boot image to header
+ with open(headerised_filename, "ab") as fo:
+ with open(uboot_bin_filename,'rb') as fi:
+ fo.write(fi.read())
+
+ # calc u-boot headerised image CRC32 (will be used by uboot update
+ # command for check)
+ headerised_image_crc = ""
+ with open(headerised_filename, "rb") as fi:
+ headerised_image_crc = hex(zlib.crc32(fi.read()) & 0xffffffff)
+
+ load_addr = 0x81000000
+ crc_store_adr = load_addr - 0x8
+ crc_calc_adr = crc_store_adr - 0x4
+ load_size = os.path.getsize(headerised_filename)
+ crc_calc_cmd = \
+ "crc32 " + hex(load_addr) + " " + hex(load_size) + " " + hex(crc_calc_adr)
+ crc_check_cmd = \
+ "mw.l " + hex(crc_store_adr) + " " + headerised_image_crc + " && " + \
+ crc_calc_cmd + " && " + \
+ "cmp.l " + hex(crc_store_adr) + " " + hex(crc_calc_adr) + " 1"
+
+ # make errase size to be allighned by 64K
+ if load_size & 0xFFFF == 0:
+ errase_size = load_size
+ else:
+ errase_size = load_size - (load_size & 0xFFFF) + 0x10000
+
+ # Hack to handle n25*** flash protect ops weirdness:
+ # protect unlock return fail status is region is already unlock (entire or
+ # partially). Same for lock ops.
+ # As there is no possibility to check current flash status pretend
+ # unlock & lock always success.
+ sf_unlock_cmd = \
+ "if sf protect unlock 0x0 0x4000000 ; then true ; else true ; fi"
+ sf_lock_cmd = \
+ "if sf protect lock 0x0 0x4000000 ; then true ; else true ; fi"
+
+ # u-bood CMD to load u-bood with header to SPI flash
+ sf_load_image_cmd = \
+ "fatload mmc 0:1 " + hex(load_addr) + " " + headerised_filename + " && " + \
+ "sf probe 0:0 && " + \
+ sf_unlock_cmd + " && " + \
+ "sf erase " + hex(spi_flash_offset) + " " + hex(errase_size) + " && " + \
+ "sf write " + hex(load_addr) + " " + hex(spi_flash_offset) + " " + hex(load_size) + " && " + \
+ sf_lock_cmd
+
+ update_uboot_cmd = sf_load_image_cmd + " && echo \"u-boot update: OK\""
+
+ with open(uboot_scrypt_file, "wb") as fo:
+ fo.write(update_uboot_cmd.encode('ascii'))
+
+
+if __name__ == "__main__":
+ try:
+ main()
+ except Exception as err:
+ print(err)
+ sys.exit(2)
diff --git a/board/synopsys/hsdk/README b/board/synopsys/hsdk/README
index e3793e48298..e29a6a17273 100644
--- a/board/synopsys/hsdk/README
+++ b/board/synopsys/hsdk/README
@@ -82,6 +82,12 @@ Useful notes on bulding and using of U-Boot on ARC HS Development Kit (AKA HSDK)
be put on the first FAT partition of micro SD-card to be inserted in the
HSDK board.
+ Note that Python3 script is used for generation of a header, thus
+ to get that done it's required to have Python3 with elftools installed.
+ On CentOS/RHEL/Fedora this could be installed with:
+ ------------------------->8----------------------
+ sudo dnf install python3-pyelftools
+ ------------------------->8----------------------
EXECUTING U-BOOT
@@ -104,8 +110,8 @@ Useful notes on bulding and using of U-Boot on ARC HS Development Kit (AKA HSDK)
1. Create `u-boot.head` and `u-boot-update.scr` as discribed above with
`make bsp-generate` command.
- 2. Copy `u-boot.head` and `u-boot-update.scr` to the first the first FAT
- partition of micro SD-card.
+ 2. Copy `u-boot.head` and `u-boot-update.scr` to the first FAT partition
+ of micro SD-card.
3. Connect USB cable from the HSDK board to the developemnt host and
fire-up serial terminal.
diff --git a/board/synopsys/hsdk/config.mk b/board/synopsys/hsdk/config.mk
index 16fb59c438c..9e280f921a1 100644
--- a/board/synopsys/hsdk/config.mk
+++ b/board/synopsys/hsdk/config.mk
@@ -6,6 +6,6 @@ bsp-generate: u-boot u-boot.bin
$(Q)python3 $(srctree)/board/$(BOARDDIR)/headerize-hsdk.py \
--arc-id 0x52 --image $(srctree)/u-boot.bin \
--elf $(srctree)/u-boot
- $(Q)mkimage -T script -C none -n 'uboot update script' \
+ $(Q)tools/mkimage -T script -C none -n 'uboot update script' \
-d $(srctree)/u-boot-update.txt \
$(srctree)/u-boot-update.scr &> /dev/null
diff --git a/board/technexion/pico-imx7d/MAINTAINERS b/board/technexion/pico-imx7d/MAINTAINERS
index 3ab1aa6381c..0755bd83666 100644
--- a/board/technexion/pico-imx7d/MAINTAINERS
+++ b/board/technexion/pico-imx7d/MAINTAINERS
@@ -4,3 +4,8 @@ S: Maintained
F: board/technexion/pico-imx7d/
F: include/configs/pico-imx7d.h
F: configs/pico-imx7d_defconfig
+
+Technexion PICO-PI-IMX7
+M: Otavio Salvador <otavio@ossystems.com.br>
+S: Maintained
+F: configs/pico-pi-imx7d_defconfig
diff --git a/board/ti/am335x/board.c b/board/ti/am335x/board.c
index 147ff0b2f00..a359d20021f 100644
--- a/board/ti/am335x/board.c
+++ b/board/ti/am335x/board.c
@@ -725,6 +725,8 @@ int board_late_init(void)
if (board_is_bbg1())
name = "BBG1";
+ if (board_is_bben())
+ name = "BBEN";
set_board_info_env(name);
/*
@@ -870,7 +872,7 @@ int board_eth_init(bd_t *bis)
(defined(CONFIG_SPL_ETH_SUPPORT) && defined(CONFIG_SPL_BUILD))
#ifdef CONFIG_DRIVER_TI_CPSW
- if (board_is_bone() || board_is_bone_lt() ||
+ if (board_is_bone() || board_is_bone_lt() || board_is_bben() ||
board_is_idk()) {
writel(MII_MODE_ENABLE, &cdev->miisel);
cpsw_slaves[0].phy_if = cpsw_slaves[1].phy_if =
@@ -906,7 +908,7 @@ int board_eth_init(bd_t *bis)
#define AR8051_DEBUG_RGMII_CLK_DLY_REG 0x5
#define AR8051_RGMII_TX_CLK_DLY 0x100
- if (board_is_evm_sk() || board_is_gp_evm()) {
+ if (board_is_evm_sk() || board_is_gp_evm() || board_is_bben()) {
const char *devname;
devname = miiphy_get_current_dev();
diff --git a/board/ti/am335x/board.h b/board/ti/am335x/board.h
index 652b10b5e4c..48df914af96 100644
--- a/board/ti/am335x/board.h
+++ b/board/ti/am335x/board.h
@@ -43,9 +43,15 @@ static inline int board_is_bbg1(void)
return board_is_bone_lt() && !strncmp(board_ti_get_rev(), "BBG1", 4);
}
+static inline int board_is_bben(void)
+{
+ return board_is_bone_lt() && !strncmp(board_ti_get_rev(), "SE", 2);
+}
+
static inline int board_is_beaglebonex(void)
{
- return board_is_pb() || board_is_bone() || board_is_bone_lt() || board_is_bbg1();
+ return board_is_pb() || board_is_bone() || board_is_bone_lt() ||
+ board_is_bbg1() || board_is_bben();
}
static inline int board_is_evm_sk(void)
diff --git a/board/ti/am335x/mux.c b/board/ti/am335x/mux.c
index aa187605d09..41333f93f40 100644
--- a/board/ti/am335x/mux.c
+++ b/board/ti/am335x/mux.c
@@ -380,6 +380,13 @@ void enable_board_pin_mux(void)
configure_module_pin_mux(rgmii1_pin_mux);
configure_module_pin_mux(mmc0_pin_mux_sk_evm);
} else if (board_is_bone_lt()) {
+ if (board_is_bben()) {
+ /* SanCloud Beaglebone LT Enhanced pinmux */
+ configure_module_pin_mux(rgmii1_pin_mux);
+ } else {
+ /* Beaglebone LT pinmux */
+ configure_module_pin_mux(mii1_pin_mux);
+ }
/* Beaglebone LT pinmux */
configure_module_pin_mux(mii1_pin_mux);
configure_module_pin_mux(mmc0_pin_mux);
diff --git a/common/spl/spl.c b/common/spl/spl.c
index a1e7b9fa914..eda84d0c74c 100644
--- a/common/spl/spl.c
+++ b/common/spl/spl.c
@@ -34,7 +34,7 @@ DECLARE_GLOBAL_DATA_PTR;
u32 *boot_params_ptr = NULL;
/* See spl.h for information about this */
-binman_sym_declare(ulong, u_boot_any, pos);
+binman_sym_declare(ulong, u_boot_any, image_pos);
/* Define board data structure */
static bd_t bdata __attribute__ ((section(".data")));
@@ -129,7 +129,7 @@ __weak void spl_board_prepare_for_boot(void)
void spl_set_header_raw_uboot(struct spl_image_info *spl_image)
{
- ulong u_boot_pos = binman_sym(ulong, u_boot_any, pos);
+ ulong u_boot_pos = binman_sym(ulong, u_boot_any, image_pos);
spl_image->size = CONFIG_SYS_MONITOR_LEN;
diff --git a/common/spl/spl_ram.c b/common/spl/spl_ram.c
index e8701934b87..e594beaeaa3 100644
--- a/common/spl/spl_ram.c
+++ b/common/spl/spl_ram.c
@@ -49,7 +49,7 @@ static int spl_ram_load_image(struct spl_image_info *spl_image,
load.read = spl_ram_load_read;
spl_load_simple_fit(spl_image, &load, 0, header);
} else {
- ulong u_boot_pos = binman_sym(ulong, u_boot_any, pos);
+ ulong u_boot_pos = binman_sym(ulong, u_boot_any, image_pos);
debug("Legacy image\n");
/*
diff --git a/configs/axs101_defconfig b/configs/axs101_defconfig
index d056719e14e..a981398cb51 100644
--- a/configs/axs101_defconfig
+++ b/configs/axs101_defconfig
@@ -15,6 +15,8 @@ CONFIG_SYS_PROMPT="AXS# "
# CONFIG_CMD_FLASH is not set
CONFIG_CMD_MMC=y
CONFIG_CMD_NAND=y
+CONFIG_CMD_SF=y
+CONFIG_CMD_SPI=y
CONFIG_CMD_USB=y
# CONFIG_CMD_SETEXPR is not set
CONFIG_CMD_DHCP=y
@@ -30,8 +32,15 @@ CONFIG_ENV_FAT_INTERFACE="mmc"
CONFIG_ENV_FAT_DEVICE_AND_PART="0:1"
CONFIG_NET_RANDOM_ETHADDR=y
CONFIG_DM=y
+CONFIG_DM_GPIO=y
+CONFIG_HSDK_CREG_GPIO=y
CONFIG_MMC=y
CONFIG_MMC_DW=y
+CONFIG_DM_SPI_FLASH=y
+CONFIG_SPI_FLASH=y
+CONFIG_SPI_FLASH_BAR=y
+CONFIG_SPI_FLASH_STMICRO=y
+CONFIG_SPI_FLASH_MTD=y
CONFIG_DM_ETH=y
CONFIG_PHY_GIGE=y
CONFIG_ETH_DESIGNWARE=y
@@ -39,6 +48,9 @@ CONFIG_DM_SERIAL=y
CONFIG_DEBUG_UART_SHIFT=2
CONFIG_DEBUG_UART_ANNOUNCE=y
CONFIG_SYS_NS16550=y
+CONFIG_SPI=y
+CONFIG_DM_SPI=y
+CONFIG_DESIGNWARE_SPI=y
CONFIG_USB=y
CONFIG_DM_USB=y
CONFIG_USB_EHCI_HCD=y
diff --git a/configs/axs103_defconfig b/configs/axs103_defconfig
index f0fccf4d9f8..e524e6a9c67 100644
--- a/configs/axs103_defconfig
+++ b/configs/axs103_defconfig
@@ -15,6 +15,8 @@ CONFIG_SYS_PROMPT="AXS# "
# CONFIG_CMD_FLASH is not set
CONFIG_CMD_MMC=y
CONFIG_CMD_NAND=y
+CONFIG_CMD_SF=y
+CONFIG_CMD_SPI=y
CONFIG_CMD_USB=y
# CONFIG_CMD_SETEXPR is not set
CONFIG_CMD_DHCP=y
@@ -30,8 +32,15 @@ CONFIG_ENV_FAT_INTERFACE="mmc"
CONFIG_ENV_FAT_DEVICE_AND_PART="0:1"
CONFIG_NET_RANDOM_ETHADDR=y
CONFIG_DM=y
+CONFIG_DM_GPIO=y
+CONFIG_HSDK_CREG_GPIO=y
CONFIG_MMC=y
CONFIG_MMC_DW=y
+CONFIG_DM_SPI_FLASH=y
+CONFIG_SPI_FLASH=y
+CONFIG_SPI_FLASH_BAR=y
+CONFIG_SPI_FLASH_STMICRO=y
+CONFIG_SPI_FLASH_MTD=y
CONFIG_DM_ETH=y
CONFIG_PHY_GIGE=y
CONFIG_ETH_DESIGNWARE=y
@@ -39,6 +48,9 @@ CONFIG_DM_SERIAL=y
CONFIG_DEBUG_UART_SHIFT=2
CONFIG_DEBUG_UART_ANNOUNCE=y
CONFIG_SYS_NS16550=y
+CONFIG_SPI=y
+CONFIG_DM_SPI=y
+CONFIG_DESIGNWARE_SPI=y
CONFIG_USB=y
CONFIG_DM_USB=y
CONFIG_USB_OHCI_HCD=y
diff --git a/configs/stm32f429-evaluation_defconfig b/configs/stm32f429-evaluation_defconfig
index 1b14a496406..3ddd5c50fb1 100644
--- a/configs/stm32f429-evaluation_defconfig
+++ b/configs/stm32f429-evaluation_defconfig
@@ -26,7 +26,6 @@ CONFIG_CMD_FAT=y
CONFIG_CMD_FS_GENERIC=y
CONFIG_OF_CONTROL=y
CONFIG_OF_EMBED=y
-# CONFIG_BLK is not set
CONFIG_DM_MMC=y
CONFIG_ARM_PL180_MMCI=y
CONFIG_MTD_NOR_FLASH=y
diff --git a/configs/stm32f469-discovery_defconfig b/configs/stm32f469-discovery_defconfig
index 4de03edcc2c..a55476f2f32 100644
--- a/configs/stm32f469-discovery_defconfig
+++ b/configs/stm32f469-discovery_defconfig
@@ -26,7 +26,6 @@ CONFIG_CMD_FAT=y
CONFIG_CMD_FS_GENERIC=y
CONFIG_OF_CONTROL=y
CONFIG_OF_EMBED=y
-# CONFIG_BLK is not set
CONFIG_DM_MMC=y
CONFIG_ARM_PL180_MMCI=y
CONFIG_MTD_NOR_FLASH=y
diff --git a/configs/stm32f746-disco_defconfig b/configs/stm32f746-disco_defconfig
index aa7403f3c51..6f07ff15586 100644
--- a/configs/stm32f746-disco_defconfig
+++ b/configs/stm32f746-disco_defconfig
@@ -40,7 +40,6 @@ CONFIG_CMD_FS_GENERIC=y
CONFIG_OF_CONTROL=y
CONFIG_NET_RANDOM_ETHADDR=y
CONFIG_NETCONSOLE=y
-# CONFIG_BLK is not set
CONFIG_DM_MMC=y
# CONFIG_SPL_DM_MMC is not set
CONFIG_ARM_PL180_MMCI=y
diff --git a/configs/stm32mp15_basic_defconfig b/configs/stm32mp15_basic_defconfig
index c72a440dff1..7a9a83e3aec 100644
--- a/configs/stm32mp15_basic_defconfig
+++ b/configs/stm32mp15_basic_defconfig
@@ -18,6 +18,7 @@ CONFIG_SYS_PROMPT="STM32MP> "
# CONFIG_CMD_EXPORTENV is not set
# CONFIG_CMD_IMPORTENV is not set
CONFIG_CMD_MEMINFO=y
+CONFIG_CMD_ADC=y
CONFIG_CMD_FUSE=y
CONFIG_CMD_GPIO=y
CONFIG_CMD_GPT=y
@@ -27,6 +28,7 @@ CONFIG_CMD_PMIC=y
CONFIG_CMD_REGULATOR=y
CONFIG_CMD_EXT4_WRITE=y
# CONFIG_SPL_DOS_PARTITION is not set
+CONFIG_STM32_ADC=y
CONFIG_DM_I2C=y
CONFIG_SYS_I2C_STM32F7=y
CONFIG_DM_MMC=y
diff --git a/doc/device-tree-bindings/adc/st,stm32-adc.txt b/doc/device-tree-bindings/adc/st,stm32-adc.txt
new file mode 100644
index 00000000000..07fb6cd76b9
--- /dev/null
+++ b/doc/device-tree-bindings/adc/st,stm32-adc.txt
@@ -0,0 +1,141 @@
+STMicroelectronics STM32 ADC device
+
+STM32 ADC is a successive approximation analog-to-digital converter.
+It has several multiplexed input channels. Conversions can be performed
+in single, continuous, scan or discontinuous mode. Result of the ADC is
+stored in a left-aligned or right-aligned 32-bit data register.
+Conversions can be launched in software or using hardware triggers.
+
+The analog watchdog feature allows the application to detect if the input
+voltage goes beyond the user-defined, higher or lower thresholds.
+
+Each STM32 ADC block can have up to 3 ADC instances.
+
+Each instance supports two contexts to manage conversions, each one has its
+own configurable sequence and trigger:
+- regular conversion can be done in sequence, running in background
+- injected conversions have higher priority, and so have the ability to
+ interrupt regular conversion sequence (either triggered in SW or HW).
+ Regular sequence is resumed, in case it has been interrupted.
+
+Contents of a stm32 adc root node:
+-----------------------------------
+Required properties:
+- compatible: Should be one of:
+ "st,stm32f4-adc-core"
+ "st,stm32h7-adc-core"
+ "st,stm32mp1-adc-core"
+- reg: Offset and length of the ADC block register set.
+- interrupts: One or more interrupts for ADC block. Some parts like stm32f4
+ and stm32h7 share a common ADC interrupt line. stm32mp1 has two separate
+ interrupt lines, one for each ADC within ADC block.
+- clocks: Core can use up to two clocks, depending on part used:
+ - "adc" clock: for the analog circuitry, common to all ADCs.
+ It's required on stm32f4.
+ It's optional on stm32h7.
+ - "bus" clock: for registers access, common to all ADCs.
+ It's not present on stm32f4.
+ It's required on stm32h7.
+- clock-names: Must be "adc" and/or "bus" depending on part used.
+- interrupt-controller: Identifies the controller node as interrupt-parent
+- vref-supply: Phandle to the vref input analog reference voltage.
+- #interrupt-cells = <1>;
+- #address-cells = <1>;
+- #size-cells = <0>;
+
+Optional properties:
+- A pinctrl state named "default" for each ADC channel may be defined to set
+ inX ADC pins in mode of operation for analog input on external pin.
+
+Contents of a stm32 adc child node:
+-----------------------------------
+An ADC block node should contain at least one subnode, representing an
+ADC instance available on the machine.
+
+Required properties:
+- compatible: Should be one of:
+ "st,stm32f4-adc"
+ "st,stm32h7-adc"
+ "st,stm32mp1-adc"
+- reg: Offset of ADC instance in ADC block (e.g. may be 0x0, 0x100, 0x200).
+- clocks: Input clock private to this ADC instance. It's required only on
+ stm32f4, that has per instance clock input for registers access.
+- interrupt-parent: Phandle to the parent interrupt controller.
+- interrupts: IRQ Line for the ADC (e.g. may be 0 for adc@0, 1 for adc@100 or
+ 2 for adc@200).
+- st,adc-channels: List of single-ended channels muxed for this ADC.
+ It can have up to 16 channels on stm32f4 or 20 channels on stm32h7, numbered
+ from 0 to 15 or 19 (resp. for in0..in15 or in0..in19).
+- st,adc-diff-channels: List of differential channels muxed for this ADC.
+ Depending on part used, some channels can be configured as differential
+ instead of single-ended (e.g. stm32h7). List here positive and negative
+ inputs pairs as <vinp vinn>, <vinp vinn>,... vinp and vinn are numbered
+ from 0 to 19 on stm32h7)
+ Note: At least one of "st,adc-channels" or "st,adc-diff-channels" is required.
+ Both properties can be used together. Some channels can be used as
+ single-ended and some other ones as differential (mixed). But channels
+ can't be configured both as single-ended and differential (invalid).
+- #io-channel-cells = <1>: See the IIO bindings section "IIO consumers" in
+ Documentation/devicetree/bindings/iio/iio-bindings.txt
+
+Optional properties:
+- dmas: Phandle to dma channel for this ADC instance.
+ See ../../dma/dma.txt for details.
+- dma-names: Must be "rx" when dmas property is being used.
+- assigned-resolution-bits: Resolution (bits) to use for conversions. Must
+ match device available resolutions:
+ * can be 6, 8, 10 or 12 on stm32f4
+ * can be 8, 10, 12, 14 or 16 on stm32h7
+ Default is maximum resolution if unset.
+- st,min-sample-time-nsecs: Minimum sampling time in nanoseconds.
+ Depending on hardware (board) e.g. high/low analog input source impedance,
+ fine tune of ADC sampling time may be recommended.
+ This can be either one value or an array that matches 'st,adc-channels' list,
+ to set sample time resp. for all channels, or independently for each channel.
+
+Example:
+ adc: adc@40012000 {
+ compatible = "st,stm32f4-adc-core";
+ reg = <0x40012000 0x400>;
+ interrupts = <18>;
+ clocks = <&rcc 0 168>;
+ clock-names = "adc";
+ vref-supply = <&reg_vref>;
+ interrupt-controller;
+ pinctrl-names = "default";
+ pinctrl-0 = <&adc3_in8_pin>;
+
+ #interrupt-cells = <1>;
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ adc@0 {
+ compatible = "st,stm32f4-adc";
+ #io-channel-cells = <1>;
+ reg = <0x0>;
+ clocks = <&rcc 0 168>;
+ interrupt-parent = <&adc>;
+ interrupts = <0>;
+ st,adc-channels = <8>;
+ dmas = <&dma2 0 0 0x400 0x0>;
+ dma-names = "rx";
+ assigned-resolution-bits = <8>;
+ };
+ ...
+ other adc child nodes follow...
+ };
+
+Example to setup:
+- channel 1 as single-ended
+- channels 2 & 3 as differential (with resp. 6 & 7 negative inputs)
+
+ adc: adc@40022000 {
+ compatible = "st,stm32h7-adc-core";
+ ...
+ adc1: adc@0 {
+ compatible = "st,stm32h7-adc";
+ ...
+ st,adc-channels = <1>;
+ st,adc-diff-channels = <2 6>, <3 7>;
+ };
+ };
diff --git a/doc/device-tree-bindings/gpio/snps,creg-gpio.txt b/doc/device-tree-bindings/gpio/snps,creg-gpio.txt
new file mode 100644
index 00000000000..46ceb65c531
--- /dev/null
+++ b/doc/device-tree-bindings/gpio/snps,creg-gpio.txt
@@ -0,0 +1,43 @@
+GPIO via CREG (control registers) driver
+
+31 9 7 5 0 < bit number
+| | | | |
+[ not used | gpio-1 | gpio-0 | <-shift-> ] < 32 bit register
+ ^ ^
+ | |
+ write 0x2 == set output to "1" (activate)
+ write 0x3 == set output to "0" (deactivate)
+
+Required properties:
+- compatible : "snps,creg-gpio"
+- reg : Exactly one register range with length 0x4.
+- #gpio-cells : Should be one - the pin number.
+- gpio-controller : Marks the device node as a GPIO controller.
+- gpio-count: Number of GPIO pins.
+- gpio-bit-per-line: Number of bits per gpio line (see picture).
+- gpio-first-shift: Shift (in bits) of the first GPIO field in register
+ (see picture).
+- gpio-activate-val: Value should be set in corresponding field to set
+ output to "1" (see picture). Applied to all GPIO ports.
+- gpio-deactivate-val: Value should be set in corresponding field to set
+ output to "0" (see picture). Applied to all GPIO ports.
+
+Optional properties:
+- gpio-bank-name: name of bank (as default driver name is used is used)
+- gpio-default-val: array of default output values (must me 0 or 1)
+
+Example (see picture):
+
+gpio: gpio@f00014b0 {
+ compatible = "snps,creg-gpio";
+ reg = <0xf00014b0 0x4>;
+ gpio-controller;
+ #gpio-cells = <1>;
+ gpio-bank-name = "hsdk-spi-cs";
+ gpio-count = <2>;
+ gpio-first-shift = <5>;
+ gpio-bit-per-line = <2>;
+ gpio-activate-val = <2>;
+ gpio-deactivate-val = <3>;
+ gpio-default-val = <1 1>;
+};
diff --git a/drivers/adc/Kconfig b/drivers/adc/Kconfig
index 93e27f131ca..e719c38bb31 100644
--- a/drivers/adc/Kconfig
+++ b/drivers/adc/Kconfig
@@ -47,3 +47,19 @@ config SARADC_ROCKCHIP
- 2~6 analog input channels
- 1O or 12 bits resolution
- Up to 1MSPS of sample rate
+
+config STM32_ADC
+ bool "Enable STMicroelectronics STM32 ADC driver"
+ depends on ADC && (STM32H7 || ARCH_STM32MP)
+ help
+ This enables driver for STMicroelectronics STM32 analog-to-digital
+ converter (ADC).
+ A STM32 ADC block can be composed of several individual ADCs.
+ Each has its own private registers, but shares some resources:
+ - clock selection and prescaler
+ - voltage reference
+ - common registers area.
+ STM32 ADC driver is composed of:
+ - core driver to deal with common resources
+ - child driver to deal with individual ADC resources (declare ADC
+ device and associated channels, start/stop conversions)
diff --git a/drivers/adc/Makefile b/drivers/adc/Makefile
index 95c93d4c57a..cca0fecd597 100644
--- a/drivers/adc/Makefile
+++ b/drivers/adc/Makefile
@@ -10,3 +10,4 @@ obj-$(CONFIG_ADC_EXYNOS) += exynos-adc.o
obj-$(CONFIG_ADC_SANDBOX) += sandbox.o
obj-$(CONFIG_SARADC_ROCKCHIP) += rockchip-saradc.o
obj-$(CONFIG_SARADC_MESON) += meson-saradc.o
+obj-$(CONFIG_STM32_ADC) += stm32-adc.o stm32-adc-core.o
diff --git a/drivers/adc/adc-uclass.c b/drivers/adc/adc-uclass.c
index 17c1a4e52aa..738c1eabdc3 100644
--- a/drivers/adc/adc-uclass.c
+++ b/drivers/adc/adc-uclass.c
@@ -264,10 +264,8 @@ static int adc_vdd_platdata_update(struct udevice *dev)
* will bind before its supply regulator device, then the below 'get'
* will return an error.
*/
- ret = device_get_supply_regulator(dev, "vdd-supply",
- &uc_pdata->vdd_supply);
- if (ret)
- return ret;
+ if (!uc_pdata->vdd_supply)
+ return 0;
ret = regulator_get_value(uc_pdata->vdd_supply);
if (ret < 0)
@@ -283,10 +281,8 @@ static int adc_vss_platdata_update(struct udevice *dev)
struct adc_uclass_platdata *uc_pdata = dev_get_uclass_platdata(dev);
int ret;
- ret = device_get_supply_regulator(dev, "vss-supply",
- &uc_pdata->vss_supply);
- if (ret)
- return ret;
+ if (!uc_pdata->vss_supply)
+ return 0;
ret = regulator_get_value(uc_pdata->vss_supply);
if (ret < 0)
@@ -302,14 +298,11 @@ int adc_vdd_value(struct udevice *dev, int *uV)
struct adc_uclass_platdata *uc_pdata = dev_get_uclass_platdata(dev);
int ret, value_sign = uc_pdata->vdd_polarity_negative ? -1 : 1;
- if (!uc_pdata->vdd_supply)
- goto nodev;
-
/* Update the regulator Value. */
ret = adc_vdd_platdata_update(dev);
if (ret)
return ret;
-nodev:
+
if (uc_pdata->vdd_microvolts == -ENODATA)
return -ENODATA;
@@ -323,14 +316,11 @@ int adc_vss_value(struct udevice *dev, int *uV)
struct adc_uclass_platdata *uc_pdata = dev_get_uclass_platdata(dev);
int ret, value_sign = uc_pdata->vss_polarity_negative ? -1 : 1;
- if (!uc_pdata->vss_supply)
- goto nodev;
-
/* Update the regulator Value. */
ret = adc_vss_platdata_update(dev);
if (ret)
return ret;
-nodev:
+
if (uc_pdata->vss_microvolts == -ENODATA)
return -ENODATA;
@@ -348,7 +338,12 @@ static int adc_vdd_platdata_set(struct udevice *dev)
prop = "vdd-polarity-negative";
uc_pdata->vdd_polarity_negative = dev_read_bool(dev, prop);
- ret = adc_vdd_platdata_update(dev);
+ /* Optionally get regulators */
+ ret = device_get_supply_regulator(dev, "vdd-supply",
+ &uc_pdata->vdd_supply);
+ if (!ret)
+ return adc_vdd_platdata_update(dev);
+
if (ret != -ENOENT)
return ret;
@@ -368,7 +363,11 @@ static int adc_vss_platdata_set(struct udevice *dev)
prop = "vss-polarity-negative";
uc_pdata->vss_polarity_negative = dev_read_bool(dev, prop);
- ret = adc_vss_platdata_update(dev);
+ ret = device_get_supply_regulator(dev, "vss-supply",
+ &uc_pdata->vss_supply);
+ if (!ret)
+ return adc_vss_platdata_update(dev);
+
if (ret != -ENOENT)
return ret;
diff --git a/drivers/adc/stm32-adc-core.c b/drivers/adc/stm32-adc-core.c
new file mode 100644
index 00000000000..a9aa143bfe7
--- /dev/null
+++ b/drivers/adc/stm32-adc-core.c
@@ -0,0 +1,209 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Copyright (C) 2018, STMicroelectronics - All Rights Reserved
+ * Author: Fabrice Gasnier <fabrice.gasnier@st.com>
+ *
+ * Originally based on the Linux kernel v4.18 drivers/iio/adc/stm32-adc-core.c.
+ */
+
+#include <common.h>
+#include <asm/io.h>
+#include <power/regulator.h>
+#include "stm32-adc-core.h"
+
+/* STM32H7 - common registers for all ADC instances */
+#define STM32H7_ADC_CCR (STM32_ADCX_COMN_OFFSET + 0x08)
+
+/* STM32H7_ADC_CCR - bit fields */
+#define STM32H7_PRESC_SHIFT 18
+#define STM32H7_PRESC_MASK GENMASK(21, 18)
+#define STM32H7_CKMODE_SHIFT 16
+#define STM32H7_CKMODE_MASK GENMASK(17, 16)
+
+/* STM32 H7 maximum analog clock rate (from datasheet) */
+#define STM32H7_ADC_MAX_CLK_RATE 36000000
+
+/**
+ * struct stm32h7_adc_ck_spec - specification for stm32h7 adc clock
+ * @ckmode: ADC clock mode, Async or sync with prescaler.
+ * @presc: prescaler bitfield for async clock mode
+ * @div: prescaler division ratio
+ */
+struct stm32h7_adc_ck_spec {
+ u32 ckmode;
+ u32 presc;
+ int div;
+};
+
+static const struct stm32h7_adc_ck_spec stm32h7_adc_ckmodes_spec[] = {
+ /* 00: CK_ADC[1..3]: Asynchronous clock modes */
+ { 0, 0, 1 },
+ { 0, 1, 2 },
+ { 0, 2, 4 },
+ { 0, 3, 6 },
+ { 0, 4, 8 },
+ { 0, 5, 10 },
+ { 0, 6, 12 },
+ { 0, 7, 16 },
+ { 0, 8, 32 },
+ { 0, 9, 64 },
+ { 0, 10, 128 },
+ { 0, 11, 256 },
+ /* HCLK used: Synchronous clock modes (1, 2 or 4 prescaler) */
+ { 1, 0, 1 },
+ { 2, 0, 2 },
+ { 3, 0, 4 },
+};
+
+static int stm32h7_adc_clk_sel(struct udevice *dev,
+ struct stm32_adc_common *common)
+{
+ u32 ckmode, presc;
+ unsigned long rate;
+ int i, div;
+
+ /* stm32h7 bus clock is common for all ADC instances (mandatory) */
+ if (!clk_valid(&common->bclk)) {
+ dev_err(dev, "No bclk clock found\n");
+ return -ENOENT;
+ }
+
+ /*
+ * stm32h7 can use either 'bus' or 'adc' clock for analog circuitry.
+ * So, choice is to have bus clock mandatory and adc clock optional.
+ * If optional 'adc' clock has been found, then try to use it first.
+ */
+ if (clk_valid(&common->aclk)) {
+ /*
+ * Asynchronous clock modes (e.g. ckmode == 0)
+ * From spec: PLL output musn't exceed max rate
+ */
+ rate = clk_get_rate(&common->aclk);
+ if (!rate) {
+ dev_err(dev, "Invalid aclk rate: 0\n");
+ return -EINVAL;
+ }
+
+ for (i = 0; i < ARRAY_SIZE(stm32h7_adc_ckmodes_spec); i++) {
+ ckmode = stm32h7_adc_ckmodes_spec[i].ckmode;
+ presc = stm32h7_adc_ckmodes_spec[i].presc;
+ div = stm32h7_adc_ckmodes_spec[i].div;
+
+ if (ckmode)
+ continue;
+
+ if ((rate / div) <= STM32H7_ADC_MAX_CLK_RATE)
+ goto out;
+ }
+ }
+
+ /* Synchronous clock modes (e.g. ckmode is 1, 2 or 3) */
+ rate = clk_get_rate(&common->bclk);
+ if (!rate) {
+ dev_err(dev, "Invalid bus clock rate: 0\n");
+ return -EINVAL;
+ }
+
+ for (i = 0; i < ARRAY_SIZE(stm32h7_adc_ckmodes_spec); i++) {
+ ckmode = stm32h7_adc_ckmodes_spec[i].ckmode;
+ presc = stm32h7_adc_ckmodes_spec[i].presc;
+ div = stm32h7_adc_ckmodes_spec[i].div;
+
+ if (!ckmode)
+ continue;
+
+ if ((rate / div) <= STM32H7_ADC_MAX_CLK_RATE)
+ goto out;
+ }
+
+ dev_err(dev, "clk selection failed\n");
+ return -EINVAL;
+
+out:
+ /* rate used later by each ADC instance to control BOOST mode */
+ common->rate = rate / div;
+
+ /* Set common clock mode and prescaler */
+ clrsetbits_le32(common->base + STM32H7_ADC_CCR,
+ STM32H7_CKMODE_MASK | STM32H7_PRESC_MASK,
+ ckmode << STM32H7_CKMODE_SHIFT |
+ presc << STM32H7_PRESC_SHIFT);
+
+ dev_dbg(dev, "Using %s clock/%d source at %ld kHz\n",
+ ckmode ? "bus" : "adc", div, common->rate / 1000);
+
+ return 0;
+}
+
+static int stm32_adc_core_probe(struct udevice *dev)
+{
+ struct stm32_adc_common *common = dev_get_priv(dev);
+ int ret;
+
+ common->base = dev_read_addr_ptr(dev);
+ if (!common->base) {
+ dev_err(dev, "can't get address\n");
+ return -ENOENT;
+ }
+
+ ret = device_get_supply_regulator(dev, "vref-supply", &common->vref);
+ if (ret) {
+ dev_err(dev, "can't get vref-supply: %d\n", ret);
+ return ret;
+ }
+
+ ret = regulator_get_value(common->vref);
+ if (ret < 0) {
+ dev_err(dev, "can't get vref-supply value: %d\n", ret);
+ return ret;
+ }
+ common->vref_uv = ret;
+
+ ret = clk_get_by_name(dev, "adc", &common->aclk);
+ if (!ret) {
+ ret = clk_enable(&common->aclk);
+ if (ret) {
+ dev_err(dev, "Can't enable aclk: %d\n", ret);
+ return ret;
+ }
+ }
+
+ ret = clk_get_by_name(dev, "bus", &common->bclk);
+ if (!ret) {
+ ret = clk_enable(&common->bclk);
+ if (ret) {
+ dev_err(dev, "Can't enable bclk: %d\n", ret);
+ goto err_aclk_disable;
+ }
+ }
+
+ ret = stm32h7_adc_clk_sel(dev, common);
+ if (ret)
+ goto err_bclk_disable;
+
+ return ret;
+
+err_bclk_disable:
+ if (clk_valid(&common->bclk))
+ clk_disable(&common->bclk);
+
+err_aclk_disable:
+ if (clk_valid(&common->aclk))
+ clk_disable(&common->aclk);
+
+ return ret;
+}
+
+static const struct udevice_id stm32_adc_core_ids[] = {
+ { .compatible = "st,stm32h7-adc-core" },
+ { .compatible = "st,stm32mp1-adc-core" },
+ {}
+};
+
+U_BOOT_DRIVER(stm32_adc_core) = {
+ .name = "stm32-adc-core",
+ .id = UCLASS_SIMPLE_BUS,
+ .of_match = stm32_adc_core_ids,
+ .probe = stm32_adc_core_probe,
+ .priv_auto_alloc_size = sizeof(struct stm32_adc_common),
+};
diff --git a/drivers/adc/stm32-adc-core.h b/drivers/adc/stm32-adc-core.h
new file mode 100644
index 00000000000..ba0e10e6cc2
--- /dev/null
+++ b/drivers/adc/stm32-adc-core.h
@@ -0,0 +1,51 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/*
+ * Copyright (C) 2018, STMicroelectronics - All Rights Reserved
+ * Author: Fabrice Gasnier <fabrice.gasnier@st.com>.
+ *
+ * Originally based on the Linux kernel v4.18 drivers/iio/adc/stm32-adc-core.h.
+ */
+
+#ifndef __STM32_ADC_H
+#define __STM32_ADC_H
+
+/*
+ * STM32 - ADC global register map
+ * ________________________________________________________
+ * | Offset | Register |
+ * --------------------------------------------------------
+ * | 0x000 | Master ADC1 |
+ * --------------------------------------------------------
+ * | 0x100 | Slave ADC2 |
+ * --------------------------------------------------------
+ * | 0x200 | Slave ADC3 |
+ * --------------------------------------------------------
+ * | 0x300 | Master & Slave common regs |
+ * --------------------------------------------------------
+ */
+#define STM32_ADC_MAX_ADCS 3
+#define STM32_ADCX_COMN_OFFSET 0x300
+
+#include <common.h>
+#include <clk.h>
+#include <dm.h>
+
+/**
+ * struct stm32_adc_common - stm32 ADC driver common data (for all instances)
+ * @base: control registers base cpu addr
+ * @rate: clock rate used for analog circuitry
+ * @aclk: clock for the analog circuitry
+ * @bclk: bus clock common for all ADCs
+ * @vref: regulator reference
+ * @vref_uv: reference supply voltage (uV)
+ */
+struct stm32_adc_common {
+ void __iomem *base;
+ unsigned long rate;
+ struct clk aclk;
+ struct clk bclk;
+ struct udevice *vref;
+ int vref_uv;
+};
+
+#endif
diff --git a/drivers/adc/stm32-adc.c b/drivers/adc/stm32-adc.c
new file mode 100644
index 00000000000..e108062f2fe
--- /dev/null
+++ b/drivers/adc/stm32-adc.c
@@ -0,0 +1,257 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Copyright (C) 2018, STMicroelectronics - All Rights Reserved
+ * Author: Fabrice Gasnier <fabrice.gasnier@st.com>
+ *
+ * Originally based on the Linux kernel v4.18 drivers/iio/adc/stm32-adc.c.
+ */
+
+#include <common.h>
+#include <adc.h>
+#include <asm/io.h>
+#include <linux/iopoll.h>
+#include "stm32-adc-core.h"
+
+/* STM32H7 - Registers for each ADC instance */
+#define STM32H7_ADC_ISR 0x00
+#define STM32H7_ADC_CR 0x08
+#define STM32H7_ADC_CFGR 0x0C
+#define STM32H7_ADC_SMPR1 0x14
+#define STM32H7_ADC_SMPR2 0x18
+#define STM32H7_ADC_PCSEL 0x1C
+#define STM32H7_ADC_SQR1 0x30
+#define STM32H7_ADC_DR 0x40
+#define STM32H7_ADC_DIFSEL 0xC0
+
+/* STM32H7_ADC_ISR - bit fields */
+#define STM32MP1_VREGREADY BIT(12)
+#define STM32H7_EOC BIT(2)
+#define STM32H7_ADRDY BIT(0)
+
+/* STM32H7_ADC_CR - bit fields */
+#define STM32H7_DEEPPWD BIT(29)
+#define STM32H7_ADVREGEN BIT(28)
+#define STM32H7_BOOST BIT(8)
+#define STM32H7_ADSTART BIT(2)
+#define STM32H7_ADDIS BIT(1)
+#define STM32H7_ADEN BIT(0)
+
+/* STM32H7_ADC_CFGR bit fields */
+#define STM32H7_EXTEN GENMASK(11, 10)
+#define STM32H7_DMNGT GENMASK(1, 0)
+
+/* STM32H7_ADC_SQR1 - bit fields */
+#define STM32H7_SQ1_SHIFT 6
+
+/* BOOST bit must be set on STM32H7 when ADC clock is above 20MHz */
+#define STM32H7_BOOST_CLKRATE 20000000UL
+
+#define STM32_ADC_CH_MAX 20 /* max number of channels */
+#define STM32_ADC_TIMEOUT_US 100000
+
+struct stm32_adc_cfg {
+ unsigned int max_channels;
+ unsigned int num_bits;
+ bool has_vregready;
+};
+
+struct stm32_adc {
+ void __iomem *regs;
+ int active_channel;
+ const struct stm32_adc_cfg *cfg;
+};
+
+static int stm32_adc_stop(struct udevice *dev)
+{
+ struct stm32_adc *adc = dev_get_priv(dev);
+
+ setbits_le32(adc->regs + STM32H7_ADC_CR, STM32H7_ADDIS);
+ clrbits_le32(adc->regs + STM32H7_ADC_CR, STM32H7_BOOST);
+ /* Setting DEEPPWD disables ADC vreg and clears ADVREGEN */
+ setbits_le32(adc->regs + STM32H7_ADC_CR, STM32H7_DEEPPWD);
+ adc->active_channel = -1;
+
+ return 0;
+}
+
+static int stm32_adc_start_channel(struct udevice *dev, int channel)
+{
+ struct adc_uclass_platdata *uc_pdata = dev_get_uclass_platdata(dev);
+ struct stm32_adc_common *common = dev_get_priv(dev_get_parent(dev));
+ struct stm32_adc *adc = dev_get_priv(dev);
+ int ret;
+ u32 val;
+
+ /* Exit deep power down, then enable ADC voltage regulator */
+ clrbits_le32(adc->regs + STM32H7_ADC_CR, STM32H7_DEEPPWD);
+ setbits_le32(adc->regs + STM32H7_ADC_CR, STM32H7_ADVREGEN);
+ if (common->rate > STM32H7_BOOST_CLKRATE)
+ setbits_le32(adc->regs + STM32H7_ADC_CR, STM32H7_BOOST);
+
+ /* Wait for startup time */
+ if (!adc->cfg->has_vregready) {
+ udelay(20);
+ } else {
+ ret = readl_poll_timeout(adc->regs + STM32H7_ADC_ISR, val,
+ val & STM32MP1_VREGREADY,
+ STM32_ADC_TIMEOUT_US);
+ if (ret < 0) {
+ stm32_adc_stop(dev);
+ dev_err(dev, "Failed to enable vreg: %d\n", ret);
+ return ret;
+ }
+ }
+
+ /* Only use single ended channels */
+ writel(0, adc->regs + STM32H7_ADC_DIFSEL);
+
+ /* Enable ADC, Poll for ADRDY to be set (after adc startup time) */
+ setbits_le32(adc->regs + STM32H7_ADC_CR, STM32H7_ADEN);
+ ret = readl_poll_timeout(adc->regs + STM32H7_ADC_ISR, val,
+ val & STM32H7_ADRDY, STM32_ADC_TIMEOUT_US);
+ if (ret < 0) {
+ stm32_adc_stop(dev);
+ dev_err(dev, "Failed to enable ADC: %d\n", ret);
+ return ret;
+ }
+
+ /* Preselect channels */
+ writel(uc_pdata->channel_mask, adc->regs + STM32H7_ADC_PCSEL);
+
+ /* Set sampling time to max value by default */
+ writel(0xffffffff, adc->regs + STM32H7_ADC_SMPR1);
+ writel(0xffffffff, adc->regs + STM32H7_ADC_SMPR2);
+
+ /* Program regular sequence: chan in SQ1 & len = 0 for one channel */
+ writel(channel << STM32H7_SQ1_SHIFT, adc->regs + STM32H7_ADC_SQR1);
+
+ /* Trigger detection disabled (conversion can be launched in SW) */
+ clrbits_le32(adc->regs + STM32H7_ADC_CFGR, STM32H7_EXTEN |
+ STM32H7_DMNGT);
+ adc->active_channel = channel;
+
+ return 0;
+}
+
+static int stm32_adc_channel_data(struct udevice *dev, int channel,
+ unsigned int *data)
+{
+ struct stm32_adc *adc = dev_get_priv(dev);
+ int ret;
+ u32 val;
+
+ if (channel != adc->active_channel) {
+ dev_err(dev, "Requested channel is not active!\n");
+ return -EINVAL;
+ }
+
+ setbits_le32(adc->regs + STM32H7_ADC_CR, STM32H7_ADSTART);
+ ret = readl_poll_timeout(adc->regs + STM32H7_ADC_ISR, val,
+ val & STM32H7_EOC, STM32_ADC_TIMEOUT_US);
+ if (ret < 0) {
+ dev_err(dev, "conversion timed out: %d\n", ret);
+ return ret;
+ }
+
+ *data = readl(adc->regs + STM32H7_ADC_DR);
+
+ return 0;
+}
+
+static int stm32_adc_chan_of_init(struct udevice *dev)
+{
+ struct adc_uclass_platdata *uc_pdata = dev_get_uclass_platdata(dev);
+ struct stm32_adc *adc = dev_get_priv(dev);
+ u32 chans[STM32_ADC_CH_MAX];
+ int i, num_channels, ret;
+
+ /* Retrieve single ended channels listed in device tree */
+ num_channels = dev_read_size(dev, "st,adc-channels");
+ if (num_channels < 0) {
+ dev_err(dev, "can't get st,adc-channels: %d\n", num_channels);
+ return num_channels;
+ }
+ num_channels /= sizeof(u32);
+
+ if (num_channels > adc->cfg->max_channels) {
+ dev_err(dev, "too many st,adc-channels: %d\n", num_channels);
+ return -EINVAL;
+ }
+
+ ret = dev_read_u32_array(dev, "st,adc-channels", chans, num_channels);
+ if (ret < 0) {
+ dev_err(dev, "can't read st,adc-channels: %d\n", ret);
+ return ret;
+ }
+
+ for (i = 0; i < num_channels; i++) {
+ if (chans[i] >= adc->cfg->max_channels) {
+ dev_err(dev, "bad channel %u\n", chans[i]);
+ return -EINVAL;
+ }
+ uc_pdata->channel_mask |= 1 << chans[i];
+ }
+
+ uc_pdata->data_mask = (1 << adc->cfg->num_bits) - 1;
+ uc_pdata->data_format = ADC_DATA_FORMAT_BIN;
+ uc_pdata->data_timeout_us = 100000;
+
+ return 0;
+}
+
+static int stm32_adc_probe(struct udevice *dev)
+{
+ struct adc_uclass_platdata *uc_pdata = dev_get_uclass_platdata(dev);
+ struct stm32_adc_common *common = dev_get_priv(dev_get_parent(dev));
+ struct stm32_adc *adc = dev_get_priv(dev);
+ int offset;
+
+ offset = dev_read_u32_default(dev, "reg", -ENODATA);
+ if (offset < 0) {
+ dev_err(dev, "Can't read reg property\n");
+ return offset;
+ }
+ adc->regs = common->base + offset;
+ adc->cfg = (const struct stm32_adc_cfg *)dev_get_driver_data(dev);
+
+ /* VDD supplied by common vref pin */
+ uc_pdata->vdd_supply = common->vref;
+ uc_pdata->vdd_microvolts = common->vref_uv;
+ uc_pdata->vss_microvolts = 0;
+
+ return stm32_adc_chan_of_init(dev);
+}
+
+static const struct adc_ops stm32_adc_ops = {
+ .start_channel = stm32_adc_start_channel,
+ .channel_data = stm32_adc_channel_data,
+ .stop = stm32_adc_stop,
+};
+
+static const struct stm32_adc_cfg stm32h7_adc_cfg = {
+ .num_bits = 16,
+ .max_channels = STM32_ADC_CH_MAX,
+};
+
+static const struct stm32_adc_cfg stm32mp1_adc_cfg = {
+ .num_bits = 16,
+ .max_channels = STM32_ADC_CH_MAX,
+ .has_vregready = true,
+};
+
+static const struct udevice_id stm32_adc_ids[] = {
+ { .compatible = "st,stm32h7-adc",
+ .data = (ulong)&stm32h7_adc_cfg },
+ { .compatible = "st,stm32mp1-adc",
+ .data = (ulong)&stm32mp1_adc_cfg },
+ {}
+};
+
+U_BOOT_DRIVER(stm32_adc) = {
+ .name = "stm32-adc",
+ .id = UCLASS_ADC,
+ .of_match = stm32_adc_ids,
+ .probe = stm32_adc_probe,
+ .ops = &stm32_adc_ops,
+ .priv_auto_alloc_size = sizeof(struct stm32_adc),
+};
diff --git a/drivers/bootcount/bootcount.c b/drivers/bootcount/bootcount.c
index a3162c97edd..646c563f8a4 100644
--- a/drivers/bootcount/bootcount.c
+++ b/drivers/bootcount/bootcount.c
@@ -11,16 +11,23 @@
__weak void bootcount_store(ulong a)
{
void *reg = (void *)CONFIG_SYS_BOOTCOUNT_ADDR;
+ uintptr_t flush_start = rounddown(CONFIG_SYS_BOOTCOUNT_ADDR,
+ CONFIG_SYS_CACHELINE_SIZE);
+ uintptr_t flush_end;
#if defined(CONFIG_SYS_BOOTCOUNT_SINGLEWORD)
raw_bootcount_store(reg, (BOOTCOUNT_MAGIC & 0xffff0000) | a);
+
+ flush_end = roundup(CONFIG_SYS_BOOTCOUNT_ADDR + 4,
+ CONFIG_SYS_CACHELINE_SIZE);
#else
raw_bootcount_store(reg, a);
raw_bootcount_store(reg + 4, BOOTCOUNT_MAGIC);
+
+ flush_end = roundup(CONFIG_SYS_BOOTCOUNT_ADDR + 8,
+ CONFIG_SYS_CACHELINE_SIZE);
#endif /* defined(CONFIG_SYS_BOOTCOUNT_SINGLEWORD */
- flush_dcache_range(CONFIG_SYS_BOOTCOUNT_ADDR,
- CONFIG_SYS_BOOTCOUNT_ADDR +
- CONFIG_SYS_CACHELINE_SIZE);
+ flush_dcache_range(flush_start, flush_end);
}
__weak ulong bootcount_load(void)
diff --git a/drivers/clk/clk-uclass.c b/drivers/clk/clk-uclass.c
index 419d4515acc..2b15978e141 100644
--- a/drivers/clk/clk-uclass.c
+++ b/drivers/clk/clk-uclass.c
@@ -154,6 +154,10 @@ static int clk_set_default_parents(struct udevice *dev)
for (index = 0; index < num_parents; index++) {
ret = clk_get_by_indexed_prop(dev, "assigned-clock-parents",
index, &parent_clk);
+ /* If -ENOENT, this is a no-op entry */
+ if (ret == -ENOENT)
+ continue;
+
if (ret) {
debug("%s: could not get parent clock %d for %s\n",
__func__, index, dev_read_name(dev));
@@ -210,6 +214,10 @@ static int clk_set_default_rates(struct udevice *dev)
goto fail;
for (index = 0; index < num_rates; index++) {
+ /* If 0 is passed, this is a no-op */
+ if (!rates[index])
+ continue;
+
ret = clk_get_by_indexed_prop(dev, "assigned-clocks",
index, &clk);
if (ret) {
diff --git a/drivers/clk/clk_sandbox_test.c b/drivers/clk/clk_sandbox_test.c
index 8cd4abb84f5..e8465dbfad1 100644
--- a/drivers/clk/clk_sandbox_test.c
+++ b/drivers/clk/clk_sandbox_test.c
@@ -116,6 +116,19 @@ int sandbox_clk_test_release_bulk(struct udevice *dev)
return clk_release_bulk(&sbct->bulk);
}
+int sandbox_clk_test_valid(struct udevice *dev)
+{
+ struct sandbox_clk_test *sbct = dev_get_priv(dev);
+ int i;
+
+ for (i = 0; i < SANDBOX_CLK_TEST_ID_COUNT; i++) {
+ if (!clk_valid(&sbct->clks[i]))
+ return -EINVAL;
+ }
+
+ return 0;
+}
+
static const struct udevice_id sandbox_clk_test_ids[] = {
{ .compatible = "sandbox,clk-test" },
{ }
diff --git a/drivers/gpio/hsdk-creg-gpio.c b/drivers/gpio/hsdk-creg-gpio.c
index 084a2da6522..800027f18ef 100644
--- a/drivers/gpio/hsdk-creg-gpio.c
+++ b/drivers/gpio/hsdk-creg-gpio.c
@@ -16,25 +16,24 @@
#include <errno.h>
#include <linux/printk.h>
-#define HSDK_CREG_MAX_GPIO 8
-
-#define GPIO_ACTIVATE 0x2
-#define GPIO_DEACTIVATE 0x3
-#define GPIO_PIN_MASK 0x3
-#define BIT_PER_GPIO 2
+#define DRV_NAME "gpio_creg"
struct hsdk_creg_gpio {
- uint32_t *regs;
+ u32 *regs;
+ u8 shift;
+ u8 activate;
+ u8 deactivate;
+ u8 bit_per_gpio;
};
static int hsdk_creg_gpio_set_value(struct udevice *dev, unsigned oft, int val)
{
struct hsdk_creg_gpio *hcg = dev_get_priv(dev);
- uint32_t reg = readl(hcg->regs);
- uint32_t cmd = val ? GPIO_DEACTIVATE : GPIO_ACTIVATE;
+ u8 reg_shift = oft * hcg->bit_per_gpio + hcg->shift;
+ u32 reg = readl(hcg->regs);
- reg &= ~(GPIO_PIN_MASK << (oft * BIT_PER_GPIO));
- reg |= (cmd << (oft * BIT_PER_GPIO));
+ reg &= ~(GENMASK(hcg->bit_per_gpio - 1, 0) << reg_shift);
+ reg |= ((val ? hcg->deactivate : hcg->activate) << reg_shift);
writel(reg, hcg->regs);
@@ -51,7 +50,9 @@ static int hsdk_creg_gpio_direction_output(struct udevice *dev, unsigned oft,
static int hsdk_creg_gpio_direction_input(struct udevice *dev, unsigned oft)
{
- pr_err("hsdk-creg-gpio can't be used as input!\n");
+ struct gpio_dev_priv *uc_priv = dev_get_uclass_priv(dev);
+
+ pr_err("%s can't be used as input!\n", uc_priv->bank_name);
return -ENOTSUPP;
}
@@ -59,10 +60,11 @@ static int hsdk_creg_gpio_direction_input(struct udevice *dev, unsigned oft)
static int hsdk_creg_gpio_get_value(struct udevice *dev, unsigned int oft)
{
struct hsdk_creg_gpio *hcg = dev_get_priv(dev);
- uint32_t val = readl(hcg->regs);
+ u32 val = readl(hcg->regs);
- val = (val >> (oft * BIT_PER_GPIO)) & GPIO_PIN_MASK;
- return (val == GPIO_DEACTIVATE) ? 1 : 0;
+ val >>= oft * hcg->bit_per_gpio + hcg->shift;
+ val &= GENMASK(hcg->bit_per_gpio - 1, 0);
+ return (val == hcg->deactivate) ? 1 : 0;
}
static const struct dm_gpio_ops hsdk_creg_gpio_ops = {
@@ -76,17 +78,74 @@ static int hsdk_creg_gpio_probe(struct udevice *dev)
{
struct gpio_dev_priv *uc_priv = dev_get_uclass_priv(dev);
struct hsdk_creg_gpio *hcg = dev_get_priv(dev);
+ u32 shift, bit_per_gpio, activate, deactivate, gpio_count;
+ const u8 *defaults;
- hcg->regs = (uint32_t *)devfdt_get_addr_ptr(dev);
-
- uc_priv->gpio_count = dev_read_u32_default(dev, "gpio-count", 1);
- if (uc_priv->gpio_count > HSDK_CREG_MAX_GPIO)
- uc_priv->gpio_count = HSDK_CREG_MAX_GPIO;
+ hcg->regs = (u32 *)devfdt_get_addr_ptr(dev);
+ gpio_count = dev_read_u32_default(dev, "gpio-count", 1);
+ shift = dev_read_u32_default(dev, "gpio-first-shift", 0);
+ bit_per_gpio = dev_read_u32_default(dev, "gpio-bit-per-line", 1);
+ activate = dev_read_u32_default(dev, "gpio-activate-val", 1);
+ deactivate = dev_read_u32_default(dev, "gpio-deactivate-val", 0);
+ defaults = dev_read_u8_array_ptr(dev, "gpio-default-val", gpio_count);
uc_priv->bank_name = dev_read_string(dev, "gpio-bank-name");
if (!uc_priv->bank_name)
uc_priv->bank_name = dev_read_name(dev);
+ if (!bit_per_gpio) {
+ pr_err("%s: 'gpio-bit-per-line' can't be 0\n",
+ uc_priv->bank_name);
+
+ return -EINVAL;
+ }
+
+ if (!gpio_count) {
+ pr_err("%s: 'gpio-count' can't be 0\n",
+ uc_priv->bank_name);
+
+ return -EINVAL;
+ }
+
+ if ((gpio_count * bit_per_gpio + shift) > 32) {
+ pr_err("%s: u32 io register overflow: try to use %u bits\n",
+ uc_priv->bank_name, gpio_count * bit_per_gpio + shift);
+
+ return -EINVAL;
+ }
+
+ if (GENMASK(31, bit_per_gpio) & activate) {
+ pr_err("%s: 'gpio-activate-val' can't be more than %lu\n",
+ uc_priv->bank_name, GENMASK(bit_per_gpio - 1, 0));
+
+ return -EINVAL;
+ }
+
+ if (GENMASK(31, bit_per_gpio) & deactivate) {
+ pr_err("%s: 'gpio-deactivate-val' can't be more than %lu\n",
+ uc_priv->bank_name, GENMASK(bit_per_gpio - 1, 0));
+
+ return -EINVAL;
+ }
+
+ if (activate == deactivate) {
+ pr_err("%s: 'gpio-deactivate-val' and 'gpio-activate-val' can't be equal\n",
+ uc_priv->bank_name);
+
+ return -EINVAL;
+ }
+
+ hcg->shift = (u8)shift;
+ hcg->bit_per_gpio = (u8)bit_per_gpio;
+ hcg->activate = (u8)activate;
+ hcg->deactivate = (u8)deactivate;
+ uc_priv->gpio_count = gpio_count;
+
+ /* Setup default GPIO value if we have "gpio-default-val" array */
+ if (defaults)
+ for (u8 i = 0; i < gpio_count; i++)
+ hsdk_creg_gpio_set_value(dev, i, defaults[i]);
+
pr_debug("%s GPIO [0x%p] controller with %d gpios probed\n",
uc_priv->bank_name, hcg->regs, uc_priv->gpio_count);
@@ -94,12 +153,12 @@ static int hsdk_creg_gpio_probe(struct udevice *dev)
}
static const struct udevice_id hsdk_creg_gpio_ids[] = {
- { .compatible = "snps,hsdk-creg-gpio" },
+ { .compatible = "snps,creg-gpio" },
{ }
};
U_BOOT_DRIVER(gpio_hsdk_creg) = {
- .name = "gpio_hsdk_creg",
+ .name = DRV_NAME,
.id = UCLASS_GPIO,
.ops = &hsdk_creg_gpio_ops,
.probe = hsdk_creg_gpio_probe,
diff --git a/drivers/mmc/arm_pl180_mmci.c b/drivers/mmc/arm_pl180_mmci.c
index e267cd782e8..f71d79ecd6b 100644
--- a/drivers/mmc/arm_pl180_mmci.c
+++ b/drivers/mmc/arm_pl180_mmci.c
@@ -357,13 +357,13 @@ static const struct mmc_ops arm_pl180_mmci_ops = {
.set_ios = host_set_ios,
.init = mmc_host_reset,
};
-#endif
/*
* mmc_host_init - initialize the mmc controller.
* Set initial clock and power for mmc slot.
* Initialize mmc struct and register with mmc framework.
*/
+
int arm_pl180_mmci_init(struct pl180_mmc_host *host, struct mmc **mmc)
{
u32 sdi_u32;
@@ -377,9 +377,8 @@ int arm_pl180_mmci_init(struct pl180_mmc_host *host, struct mmc **mmc)
writel(sdi_u32, &host->base->mask0);
host->cfg.name = host->name;
-#ifndef CONFIG_DM_MMC
host->cfg.ops = &arm_pl180_mmci_ops;
-#endif
+
/* TODO remove the duplicates */
host->cfg.host_caps = host->caps;
host->cfg.voltages = host->voltages;
@@ -393,20 +392,34 @@ int arm_pl180_mmci_init(struct pl180_mmc_host *host, struct mmc **mmc)
*mmc = mmc_create(&host->cfg, host);
if (!*mmc)
return -1;
-
debug("registered mmc interface number is:%d\n",
(*mmc)->block_dev.devnum);
return 0;
}
+#endif
#ifdef CONFIG_DM_MMC
+static void arm_pl180_mmc_init(struct pl180_mmc_host *host)
+{
+ u32 sdi_u32;
+
+ writel(host->pwr_init, &host->base->power);
+ writel(host->clkdiv_init, &host->base->clock);
+ udelay(CLK_CHANGE_DELAY);
+
+ /* Disable mmc interrupts */
+ sdi_u32 = readl(&host->base->mask0) & ~SDI_MASK0_MASK;
+ writel(sdi_u32, &host->base->mask0);
+}
+
static int arm_pl180_mmc_probe(struct udevice *dev)
{
struct arm_pl180_mmc_plat *pdata = dev_get_platdata(dev);
struct mmc_uclass_priv *upriv = dev_get_uclass_priv(dev);
struct mmc *mmc = &pdata->mmc;
- struct pl180_mmc_host *host = mmc->priv;
+ struct pl180_mmc_host *host = dev->priv;
+ struct mmc_config *cfg = &pdata->cfg;
struct clk clk;
u32 bus_width;
int ret;
@@ -417,31 +430,33 @@ static int arm_pl180_mmc_probe(struct udevice *dev)
ret = clk_enable(&clk);
if (ret) {
+ clk_free(&clk);
dev_err(dev, "failed to enable clock\n");
return ret;
}
- strcpy(host->name, "MMC");
host->pwr_init = INIT_PWR;
host->clkdiv_init = SDI_CLKCR_CLKDIV_INIT_V1 | SDI_CLKCR_CLKEN |
SDI_CLKCR_HWFC_EN;
- host->voltages = VOLTAGE_WINDOW_SD;
- host->caps = 0;
host->clock_in = clk_get_rate(&clk);
- host->clock_min = host->clock_in / (2 * (SDI_CLKCR_CLKDIV_INIT_V1 + 1));
- host->clock_max = dev_read_u32_default(dev, "max-frequency",
- MMC_CLOCK_MAX);
host->version2 = dev_get_driver_data(dev);
+ cfg->name = dev->name;
+ cfg->voltages = VOLTAGE_WINDOW_SD;
+ cfg->host_caps = 0;
+ cfg->f_min = host->clock_in / (2 * (SDI_CLKCR_CLKDIV_INIT_V1 + 1));
+ cfg->f_max = dev_read_u32_default(dev, "max-frequency", MMC_CLOCK_MAX);
+ cfg->b_max = CONFIG_SYS_MMC_MAX_BLK_COUNT;
+
gpio_request_by_name(dev, "cd-gpios", 0, &host->cd_gpio, GPIOD_IS_IN);
bus_width = dev_read_u32_default(dev, "bus-width", 1);
switch (bus_width) {
case 8:
- host->caps |= MMC_MODE_8BIT;
+ cfg->host_caps |= MMC_MODE_8BIT;
/* Hosts capable of 8-bit transfers can also do 4 bits */
case 4:
- host->caps |= MMC_MODE_4BIT;
+ cfg->host_caps |= MMC_MODE_4BIT;
break;
case 1:
break;
@@ -449,19 +464,21 @@ static int arm_pl180_mmc_probe(struct udevice *dev)
dev_err(dev, "Invalid bus-width value %u\n", bus_width);
}
- ret = arm_pl180_mmci_init(host, &mmc);
- if (ret) {
- dev_err(dev, "arm_pl180_mmci init failed\n");
- return ret;
- }
-
+ arm_pl180_mmc_init(host);
+ mmc->priv = host;
mmc->dev = dev;
- dev->priv = host;
upriv->mmc = mmc;
return 0;
}
+int arm_pl180_mmc_bind(struct udevice *dev)
+{
+ struct arm_pl180_mmc_plat *plat = dev_get_platdata(dev);
+
+ return mmc_bind(dev, &plat->mmc, &plat->cfg);
+}
+
static int dm_host_request(struct udevice *dev, struct mmc_cmd *cmd,
struct mmc_data *data)
{
@@ -479,16 +496,11 @@ static int dm_host_set_ios(struct udevice *dev)
static int dm_mmc_getcd(struct udevice *dev)
{
- struct arm_pl180_mmc_plat *pdata = dev_get_platdata(dev);
- struct mmc *mmc = &pdata->mmc;
- struct pl180_mmc_host *host = mmc->priv;
+ struct pl180_mmc_host *host = dev->priv;
int value = 1;
- if (dm_gpio_is_valid(&host->cd_gpio)) {
+ if (dm_gpio_is_valid(&host->cd_gpio))
value = dm_gpio_get_value(&host->cd_gpio);
- if (host->cd_inverted)
- return !value;
- }
return value;
}
@@ -501,12 +513,10 @@ static const struct dm_mmc_ops arm_pl180_dm_mmc_ops = {
static int arm_pl180_mmc_ofdata_to_platdata(struct udevice *dev)
{
- struct arm_pl180_mmc_plat *pdata = dev_get_platdata(dev);
- struct mmc *mmc = &pdata->mmc;
- struct pl180_mmc_host *host = mmc->priv;
+ struct pl180_mmc_host *host = dev->priv;
fdt_addr_t addr;
- addr = devfdt_get_addr(dev);
+ addr = dev_read_addr(dev);
if (addr == FDT_ADDR_T_NONE)
return -EINVAL;
@@ -527,6 +537,7 @@ U_BOOT_DRIVER(arm_pl180_mmc) = {
.ops = &arm_pl180_dm_mmc_ops,
.probe = arm_pl180_mmc_probe,
.ofdata_to_platdata = arm_pl180_mmc_ofdata_to_platdata,
+ .bind = arm_pl180_mmc_bind,
.priv_auto_alloc_size = sizeof(struct pl180_mmc_host),
.platdata_auto_alloc_size = sizeof(struct arm_pl180_mmc_plat),
};
diff --git a/drivers/mmc/arm_pl180_mmci.h b/drivers/mmc/arm_pl180_mmci.h
index 6b98db6cd97..36487be288b 100644
--- a/drivers/mmc/arm_pl180_mmci.h
+++ b/drivers/mmc/arm_pl180_mmci.h
@@ -192,7 +192,6 @@ struct pl180_mmc_host {
struct mmc_config cfg;
#ifdef CONFIG_DM_MMC
struct gpio_desc cd_gpio;
- bool cd_inverted;
#endif
};
diff --git a/include/clk.h b/include/clk.h
index 9a357646ff0..f6d1cc53a1f 100644
--- a/include/clk.h
+++ b/include/clk.h
@@ -294,4 +294,14 @@ int clk_disable_bulk(struct clk_bulk *bulk);
int soc_clk_dump(void);
+/**
+ * clk_valid() - check if clk is valid
+ *
+ * @clk: the clock to check
+ * @return true if valid, or false
+ */
+static inline bool clk_valid(struct clk *clk)
+{
+ return !!clk->dev;
+}
#endif
diff --git a/include/configs/T104xRDB.h b/include/configs/T104xRDB.h
index 4d097747a3a..71eb8e0535d 100644
--- a/include/configs/T104xRDB.h
+++ b/include/configs/T104xRDB.h
@@ -617,7 +617,6 @@ $(SRCTREE)/board/freescale/t104xrdb/t1042d4_sd_rcw.cfg
#ifdef CONFIG_USB_EHCI_HCD
#define CONFIG_USB_EHCI_FSL
#define CONFIG_EHCI_HCD_INIT_AFTER_RESET
-#define CONFIG_EHCI_DESC_BIG_ENDIAN
#endif
#endif
diff --git a/include/configs/am335x_evm.h b/include/configs/am335x_evm.h
index ff87adcd490..f1aa653a9ae 100644
--- a/include/configs/am335x_evm.h
+++ b/include/configs/am335x_evm.h
@@ -153,6 +153,8 @@
"setenv fdtfile am335x-bonegreen-wireless.dtb; fi; " \
"if test $board_name = BBBL; then " \
"setenv fdtfile am335x-boneblue.dtb; fi; " \
+ "if test $board_name = BBEN; then " \
+ "setenv fdtfile am335x-sancloud-bbe.dtb; fi; " \
"if test $board_name = A33515BB; then " \
"setenv fdtfile am335x-evm.dtb; fi; " \
"if test $board_name = A335X_SK; then " \
diff --git a/include/configs/axs10x.h b/include/configs/axs10x.h
index f044158265d..f78e1573b6c 100644
--- a/include/configs/axs10x.h
+++ b/include/configs/axs10x.h
@@ -65,6 +65,13 @@
* Environment settings
*/
#define CONFIG_ENV_SIZE SZ_16K
+#define CONFIG_EXTRA_ENV_SETTINGS \
+ "upgrade=if mmc rescan && " \
+ "fatload mmc 0:1 ${loadaddr} u-boot-update.img && " \
+ "iminfo ${loadaddr} && source ${loadaddr}; then; else echo " \
+ "\"Fail to upgrade.\n" \
+ "Do you have u-boot-update.img and u-boot.head on first (FAT) SD card partition?\"" \
+ "; fi\0"
/*
* Environment configuration
diff --git a/include/configs/omap3_cairo.h b/include/configs/omap3_cairo.h
index 5081f3200e2..72f04c3c18c 100644
--- a/include/configs/omap3_cairo.h
+++ b/include/configs/omap3_cairo.h
@@ -203,8 +203,6 @@
* function per_clocks_enable().
*/
#ifdef CONFIG_SPL_BUILD
-#undef CONFIG_SYS_NS16550_COM3
-#define CONFIG_SYS_NS16550_COM2 OMAP34XX_UART2
#undef CONFIG_SERIAL3
#define CONFIG_SERIAL2
#endif
diff --git a/include/configs/omap3_logic.h b/include/configs/omap3_logic.h
index 4d811e096cc..3b65a8505f0 100644
--- a/include/configs/omap3_logic.h
+++ b/include/configs/omap3_logic.h
@@ -16,12 +16,6 @@
#include <configs/ti_omap3_common.h>
-#ifdef CONFIG_SPL_BUILD
-/* select serial console configuration for SPL */
-#define CONFIG_SYS_NS16550_COM1 OMAP34XX_UART1
-#endif
-
-
/*
* We are only ever GP parts and will utilize all of the "downloaded image"
* area in SRAM which starts at 0x40200000 and ends at 0x4020FFFF (64KB) in
diff --git a/include/configs/p1_p2_rdb_pc.h b/include/configs/p1_p2_rdb_pc.h
index 32104c2ad49..3aebc845cdb 100644
--- a/include/configs/p1_p2_rdb_pc.h
+++ b/include/configs/p1_p2_rdb_pc.h
@@ -757,7 +757,6 @@
#ifdef CONFIG_USB_EHCI_HCD
#define CONFIG_EHCI_HCD_INIT_AFTER_RESET
#define CONFIG_USB_EHCI_FSL
-#define CONFIG_EHCI_DESC_BIG_ENDIAN
#endif
#endif
diff --git a/include/configs/ti_omap3_common.h b/include/configs/ti_omap3_common.h
index 7cd4272ce5b..6d16fc782bd 100644
--- a/include/configs/ti_omap3_common.h
+++ b/include/configs/ti_omap3_common.h
@@ -38,6 +38,8 @@
/* Select serial console configuration */
#ifdef CONFIG_SPL_BUILD
+#define CONFIG_SYS_NS16550_COM1 OMAP34XX_UART1
+#define CONFIG_SYS_NS16550_COM2 OMAP34XX_UART2
#define CONFIG_SYS_NS16550_COM3 OMAP34XX_UART3
#define CONFIG_SERIAL3 3
#endif
diff --git a/include/spl.h b/include/spl.h
index 86287874e1b..7fad62c043e 100644
--- a/include/spl.h
+++ b/include/spl.h
@@ -60,7 +60,7 @@ struct spl_load_info {
* image is found. For * example if u-boot.img is used we don't check that
* spl_parse_image_header() can parse a valid header.
*/
-binman_sym_extern(ulong, u_boot_any, pos);
+binman_sym_extern(ulong, u_boot_any, image_pos);
/**
* spl_load_simple_fit() - Loads a fit image from a device.
diff --git a/scripts/.gitignore b/scripts/.gitignore
index 17b903b0f5b..08cc824bac3 100644
--- a/scripts/.gitignore
+++ b/scripts/.gitignore
@@ -2,4 +2,3 @@
# Generated files
#
bin2c
-docproc
diff --git a/scripts/Makefile b/scripts/Makefile
index e27308a97a5..e7b353f77f4 100644
--- a/scripts/Makefile
+++ b/scripts/Makefile
@@ -3,20 +3,11 @@
# scripts contains sources for various helper programs used throughout
# the kernel for the build process.
# ---------------------------------------------------------------------------
-# docproc: Used in Documentation/DocBook
hostprogs-$(CONFIG_BUILD_BIN2C) += bin2c
always := $(hostprogs-y)
-# The following hostprogs-y programs are only build on demand
-hostprogs-y += docproc
-
-# These targets are used internally to avoid "is up to date" messages
-PHONY += build_docproc
-build_docproc: $(obj)/docproc
- @:
-
# Let clean descend into subdirs
subdir- += basic kconfig
subdir-$(CONFIG_DTC) += dtc
diff --git a/scripts/docproc.c b/scripts/docproc.c
deleted file mode 100644
index e267e621431..00000000000
--- a/scripts/docproc.c
+++ /dev/null
@@ -1,580 +0,0 @@
-/*
- * docproc is a simple preprocessor for the template files
- * used as placeholders for the kernel internal documentation.
- * docproc is used for documentation-frontend and
- * dependency-generator.
- * The two usages have in common that they require
- * some knowledge of the .tmpl syntax, therefore they
- * are kept together.
- *
- * documentation-frontend
- * Scans the template file and call kernel-doc for
- * all occurrences of ![EIF]file
- * Beforehand each referenced file is scanned for
- * any symbols that are exported via these macros:
- * EXPORT_SYMBOL(), EXPORT_SYMBOL_GPL(), &
- * EXPORT_SYMBOL_GPL_FUTURE()
- * This is used to create proper -function and
- * -nofunction arguments in calls to kernel-doc.
- * Usage: docproc doc file.tmpl
- *
- * dependency-generator:
- * Scans the template file and list all files
- * referenced in a format recognized by make.
- * Usage: docproc depend file.tmpl
- * Writes dependency information to stdout
- * in the following format:
- * file.tmpl src.c src2.c
- * The filenames are obtained from the following constructs:
- * !Efilename
- * !Ifilename
- * !Dfilename
- * !Ffilename
- * !Pfilename
- *
- */
-
-#define _GNU_SOURCE
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include <ctype.h>
-#include <unistd.h>
-#include <limits.h>
-#include <errno.h>
-#include <sys/types.h>
-#include <sys/wait.h>
-
-/* exitstatus is used to keep track of any failing calls to kernel-doc,
- * but execution continues. */
-int exitstatus = 0;
-
-typedef void DFL(char *);
-DFL *defaultline;
-
-typedef void FILEONLY(char * file);
-FILEONLY *internalfunctions;
-FILEONLY *externalfunctions;
-FILEONLY *symbolsonly;
-FILEONLY *findall;
-
-typedef void FILELINE(char * file, char * line);
-FILELINE * singlefunctions;
-FILELINE * entity_system;
-FILELINE * docsection;
-
-#define MAXLINESZ 2048
-#define MAXFILES 250
-#define KERNELDOCPATH "scripts/"
-#define KERNELDOC "kernel-doc"
-#define DOCBOOK "-docbook"
-#define LIST "-list"
-#define FUNCTION "-function"
-#define NOFUNCTION "-nofunction"
-#define NODOCSECTIONS "-no-doc-sections"
-#define SHOWNOTFOUND "-show-not-found"
-
-static char *srctree, *kernsrctree;
-
-static char **all_list = NULL;
-static int all_list_len = 0;
-
-static void consume_symbol(const char *sym)
-{
- int i;
-
- for (i = 0; i < all_list_len; i++) {
- if (!all_list[i])
- continue;
- if (strcmp(sym, all_list[i]))
- continue;
- all_list[i] = NULL;
- break;
- }
-}
-
-static void usage (void)
-{
- fprintf(stderr, "Usage: docproc {doc|depend} file\n");
- fprintf(stderr, "Input is read from file.tmpl. Output is sent to stdout\n");
- fprintf(stderr, "doc: frontend when generating kernel documentation\n");
- fprintf(stderr, "depend: generate list of files referenced within file\n");
- fprintf(stderr, "Environment variable SRCTREE: absolute path to sources.\n");
- fprintf(stderr, " KBUILD_SRC: absolute path to kernel source tree.\n");
-}
-
-/*
- * Execute kernel-doc with parameters given in svec
- */
-static void exec_kernel_doc(char **svec)
-{
- pid_t pid;
- int ret;
- char real_filename[PATH_MAX + 1];
- /* Make sure output generated so far are flushed */
- fflush(stdout);
- switch (pid=fork()) {
- case -1:
- perror("fork");
- exit(1);
- case 0:
- memset(real_filename, 0, sizeof(real_filename));
- strncat(real_filename, kernsrctree, PATH_MAX);
- strncat(real_filename, "/" KERNELDOCPATH KERNELDOC,
- PATH_MAX - strlen(real_filename));
- execvp(real_filename, svec);
- fprintf(stderr, "exec ");
- perror(real_filename);
- exit(1);
- default:
- waitpid(pid, &ret ,0);
- }
- if (WIFEXITED(ret))
- exitstatus |= WEXITSTATUS(ret);
- else
- exitstatus = 0xff;
-}
-
-/* Types used to create list of all exported symbols in a number of files */
-struct symbols
-{
- char *name;
-};
-
-struct symfile
-{
- char *filename;
- struct symbols *symbollist;
- int symbolcnt;
-};
-
-struct symfile symfilelist[MAXFILES];
-int symfilecnt = 0;
-
-static void add_new_symbol(struct symfile *sym, char * symname)
-{
- sym->symbollist =
- realloc(sym->symbollist, (sym->symbolcnt + 1) * sizeof(char *));
- sym->symbollist[sym->symbolcnt++].name = strdup(symname);
-}
-
-/* Add a filename to the list */
-static struct symfile * add_new_file(char * filename)
-{
- symfilelist[symfilecnt++].filename = strdup(filename);
- return &symfilelist[symfilecnt - 1];
-}
-
-/* Check if file already are present in the list */
-static struct symfile * filename_exist(char * filename)
-{
- int i;
- for (i=0; i < symfilecnt; i++)
- if (strcmp(symfilelist[i].filename, filename) == 0)
- return &symfilelist[i];
- return NULL;
-}
-
-/*
- * List all files referenced within the template file.
- * Files are separated by tabs.
- */
-static void adddep(char * file) { printf("\t%s", file); }
-static void adddep2(char * file, char * line) { line = line; adddep(file); }
-static void noaction(char * line) { line = line; }
-static void noaction2(char * file, char * line) { file = file; line = line; }
-
-/* Echo the line without further action */
-static void printline(char * line) { printf("%s", line); }
-
-/*
- * Find all symbols in filename that are exported with EXPORT_SYMBOL &
- * EXPORT_SYMBOL_GPL (& EXPORT_SYMBOL_GPL_FUTURE implicitly).
- * All symbols located are stored in symfilelist.
- */
-static void find_export_symbols(char * filename)
-{
- FILE * fp;
- struct symfile *sym;
- char line[MAXLINESZ];
- if (filename_exist(filename) == NULL) {
- char real_filename[PATH_MAX + 1];
- memset(real_filename, 0, sizeof(real_filename));
- strncat(real_filename, srctree, PATH_MAX);
- strncat(real_filename, "/", PATH_MAX - strlen(real_filename));
- strncat(real_filename, filename,
- PATH_MAX - strlen(real_filename));
- sym = add_new_file(filename);
- fp = fopen(real_filename, "r");
- if (fp == NULL) {
- fprintf(stderr, "docproc: ");
- perror(real_filename);
- exit(1);
- }
- while (fgets(line, MAXLINESZ, fp)) {
- char *p;
- char *e;
- if (((p = strstr(line, "EXPORT_SYMBOL_GPL")) != NULL) ||
- ((p = strstr(line, "EXPORT_SYMBOL")) != NULL)) {
- /* Skip EXPORT_SYMBOL{_GPL} */
- while (isalnum(*p) || *p == '_')
- p++;
- /* Remove parentheses & additional whitespace */
- while (isspace(*p))
- p++;
- if (*p != '(')
- continue; /* Syntax error? */
- else
- p++;
- while (isspace(*p))
- p++;
- e = p;
- while (isalnum(*e) || *e == '_')
- e++;
- *e = '\0';
- add_new_symbol(sym, p);
- }
- }
- fclose(fp);
- }
-}
-
-/*
- * Document all external or internal functions in a file.
- * Call kernel-doc with following parameters:
- * kernel-doc -docbook -nofunction function_name1 filename
- * Function names are obtained from all the src files
- * by find_export_symbols.
- * intfunc uses -nofunction
- * extfunc uses -function
- */
-static void docfunctions(char * filename, char * type)
-{
- int i,j;
- int symcnt = 0;
- int idx = 0;
- char **vec;
-
- for (i=0; i <= symfilecnt; i++)
- symcnt += symfilelist[i].symbolcnt;
- vec = malloc((2 + 2 * symcnt + 3) * sizeof(char *));
- if (vec == NULL) {
- perror("docproc: ");
- exit(1);
- }
- vec[idx++] = KERNELDOC;
- vec[idx++] = DOCBOOK;
- vec[idx++] = NODOCSECTIONS;
- for (i=0; i < symfilecnt; i++) {
- struct symfile * sym = &symfilelist[i];
- for (j=0; j < sym->symbolcnt; j++) {
- vec[idx++] = type;
- consume_symbol(sym->symbollist[j].name);
- vec[idx++] = sym->symbollist[j].name;
- }
- }
- vec[idx++] = filename;
- vec[idx] = NULL;
- printf("<!-- %s -->\n", filename);
- exec_kernel_doc(vec);
- fflush(stdout);
- free(vec);
-}
-static void intfunc(char * filename) { docfunctions(filename, NOFUNCTION); }
-static void extfunc(char * filename) { docfunctions(filename, FUNCTION); }
-
-/*
- * Document specific function(s) in a file.
- * Call kernel-doc with the following parameters:
- * kernel-doc -docbook -function function1 [-function function2]
- */
-static void singfunc(char * filename, char * line)
-{
- char *vec[200]; /* Enough for specific functions */
- int i, idx = 0;
- int startofsym = 1;
- vec[idx++] = KERNELDOC;
- vec[idx++] = DOCBOOK;
- vec[idx++] = SHOWNOTFOUND;
-
- /* Split line up in individual parameters preceded by FUNCTION */
- for (i=0; line[i]; i++) {
- if (isspace(line[i])) {
- line[i] = '\0';
- startofsym = 1;
- continue;
- }
- if (startofsym) {
- startofsym = 0;
- vec[idx++] = FUNCTION;
- vec[idx++] = &line[i];
- }
- }
- for (i = 0; i < idx; i++) {
- if (strcmp(vec[i], FUNCTION))
- continue;
- consume_symbol(vec[i + 1]);
- }
- vec[idx++] = filename;
- vec[idx] = NULL;
- exec_kernel_doc(vec);
-}
-
-/*
- * Insert specific documentation section from a file.
- * Call kernel-doc with the following parameters:
- * kernel-doc -docbook -function "doc section" filename
- */
-static void docsect(char *filename, char *line)
-{
- /* kerneldoc -docbook -show-not-found -function "section" file NULL */
- char *vec[7];
- char *s;
-
- for (s = line; *s; s++)
- if (*s == '\n')
- *s = '\0';
-
- if (asprintf(&s, "DOC: %s", line) < 0) {
- perror("asprintf");
- exit(1);
- }
- consume_symbol(s);
- free(s);
-
- vec[0] = KERNELDOC;
- vec[1] = DOCBOOK;
- vec[2] = SHOWNOTFOUND;
- vec[3] = FUNCTION;
- vec[4] = line;
- vec[5] = filename;
- vec[6] = NULL;
- exec_kernel_doc(vec);
-}
-
-static void find_all_symbols(char *filename)
-{
- char *vec[4]; /* kerneldoc -list file NULL */
- pid_t pid;
- int ret, i, count, start;
- char real_filename[PATH_MAX + 1];
- int pipefd[2];
- char *data, *str;
- size_t data_len = 0;
-
- vec[0] = KERNELDOC;
- vec[1] = LIST;
- vec[2] = filename;
- vec[3] = NULL;
-
- if (pipe(pipefd)) {
- perror("pipe");
- exit(1);
- }
-
- switch (pid=fork()) {
- case -1:
- perror("fork");
- exit(1);
- case 0:
- close(pipefd[0]);
- dup2(pipefd[1], 1);
- memset(real_filename, 0, sizeof(real_filename));
- strncat(real_filename, kernsrctree, PATH_MAX);
- strncat(real_filename, "/" KERNELDOCPATH KERNELDOC,
- PATH_MAX - strlen(real_filename));
- execvp(real_filename, vec);
- fprintf(stderr, "exec ");
- perror(real_filename);
- exit(1);
- default:
- close(pipefd[1]);
- data = malloc(4096);
- do {
- while ((ret = read(pipefd[0],
- data + data_len,
- 4096)) > 0) {
- data_len += ret;
- data = realloc(data, data_len + 4096);
- }
- } while (ret == -EAGAIN);
- if (ret != 0) {
- perror("read");
- exit(1);
- }
- waitpid(pid, &ret ,0);
- }
- if (WIFEXITED(ret))
- exitstatus |= WEXITSTATUS(ret);
- else
- exitstatus = 0xff;
-
- count = 0;
- /* poor man's strtok, but with counting */
- for (i = 0; i < data_len; i++) {
- if (data[i] == '\n') {
- count++;
- data[i] = '\0';
- }
- }
- start = all_list_len;
- all_list_len += count;
- all_list = realloc(all_list, sizeof(char *) * all_list_len);
- str = data;
- for (i = 0; i < data_len && start != all_list_len; i++) {
- if (data[i] == '\0') {
- all_list[start] = str;
- str = data + i + 1;
- start++;
- }
- }
-}
-
-/*
- * Parse file, calling action specific functions for:
- * 1) Lines containing !E
- * 2) Lines containing !I
- * 3) Lines containing !D
- * 4) Lines containing !F
- * 5) Lines containing !P
- * 6) Lines containing !C
- * 7) Default lines - lines not matching the above
- */
-static void parse_file(FILE *infile)
-{
- char line[MAXLINESZ];
- char * s;
- while (fgets(line, MAXLINESZ, infile)) {
- if (line[0] == '!') {
- s = line + 2;
- switch (line[1]) {
- case 'E':
- while (*s && !isspace(*s)) s++;
- *s = '\0';
- externalfunctions(line+2);
- break;
- case 'I':
- while (*s && !isspace(*s)) s++;
- *s = '\0';
- internalfunctions(line+2);
- break;
- case 'D':
- while (*s && !isspace(*s)) s++;
- *s = '\0';
- symbolsonly(line+2);
- break;
- case 'F':
- /* filename */
- while (*s && !isspace(*s)) s++;
- *s++ = '\0';
- /* function names */
- while (isspace(*s))
- s++;
- singlefunctions(line +2, s);
- break;
- case 'P':
- /* filename */
- while (*s && !isspace(*s)) s++;
- *s++ = '\0';
- /* DOC: section name */
- while (isspace(*s))
- s++;
- docsection(line + 2, s);
- break;
- case 'C':
- while (*s && !isspace(*s)) s++;
- *s = '\0';
- if (findall)
- findall(line+2);
- break;
- default:
- defaultline(line);
- }
- } else {
- defaultline(line);
- }
- }
- fflush(stdout);
-}
-
-
-int main(int argc, char *argv[])
-{
- FILE * infile;
- int i;
-
- srctree = getenv("SRCTREE");
- if (!srctree)
- srctree = getcwd(NULL, 0);
- kernsrctree = getenv("KBUILD_SRC");
- if (!kernsrctree || !*kernsrctree)
- kernsrctree = srctree;
- if (argc != 3) {
- usage();
- exit(1);
- }
- /* Open file, exit on error */
- infile = fopen(argv[2], "r");
- if (infile == NULL) {
- fprintf(stderr, "docproc: ");
- perror(argv[2]);
- exit(2);
- }
-
- if (strcmp("doc", argv[1]) == 0) {
- /* Need to do this in two passes.
- * First pass is used to collect all symbols exported
- * in the various files;
- * Second pass generate the documentation.
- * This is required because some functions are declared
- * and exported in different files :-((
- */
- /* Collect symbols */
- defaultline = noaction;
- internalfunctions = find_export_symbols;
- externalfunctions = find_export_symbols;
- symbolsonly = find_export_symbols;
- singlefunctions = noaction2;
- docsection = noaction2;
- findall = find_all_symbols;
- parse_file(infile);
-
- /* Rewind to start from beginning of file again */
- fseek(infile, 0, SEEK_SET);
- defaultline = printline;
- internalfunctions = intfunc;
- externalfunctions = extfunc;
- symbolsonly = printline;
- singlefunctions = singfunc;
- docsection = docsect;
- findall = NULL;
-
- parse_file(infile);
-
- for (i = 0; i < all_list_len; i++) {
- if (!all_list[i])
- continue;
- fprintf(stderr, "Warning: didn't use docs for %s\n",
- all_list[i]);
- }
- } else if (strcmp("depend", argv[1]) == 0) {
- /* Create first part of dependency chain
- * file.tmpl */
- printf("%s\t", argv[2]);
- defaultline = noaction;
- internalfunctions = adddep;
- externalfunctions = adddep;
- symbolsonly = adddep;
- singlefunctions = adddep2;
- docsection = adddep2;
- findall = adddep;
- parse_file(infile);
- printf("\n");
- } else {
- fprintf(stderr, "Unknown option: %s\n", argv[1]);
- exit(1);
- }
- fclose(infile);
- fflush(stdout);
- return exitstatus;
-}
diff --git a/test/dm/clk.c b/test/dm/clk.c
index b06906a3ecf..898c034e27b 100644
--- a/test/dm/clk.c
+++ b/test/dm/clk.c
@@ -28,6 +28,7 @@ static int dm_test_clk(struct unit_test_state *uts)
ut_assertok(uclass_get_device_by_name(UCLASS_MISC, "clk-test",
&dev_test));
ut_assertok(sandbox_clk_test_get(dev_test));
+ ut_assertok(sandbox_clk_test_valid(dev_test));
ut_asserteq(1234,
sandbox_clk_test_get_rate(dev_test,
diff --git a/tools/binman/README b/tools/binman/README
index 207928aa955..cb34171e5fc 100644
--- a/tools/binman/README
+++ b/tools/binman/README
@@ -238,7 +238,7 @@ below:
filename = "spl/sunxi-spl.bin";
};
u-boot {
- pos = <CONFIG_SPL_PAD_TO>;
+ offset = <CONFIG_SPL_PAD_TO>;
};
};
@@ -257,7 +257,7 @@ provide a filename. For 'u-boot', binman knows that this means 'u-boot.bin'.
Entries are normally placed into the image sequentially, one after the other.
The image size is the total size of all entries. As you can see, you can
-specify the start position of an entry using the 'pos' property.
+specify the start offset of an entry using the 'offset' property.
Note that due to a device tree requirement, all entries must have a unique
name. If you want to put the same binary in the image multiple times, you can
@@ -265,14 +265,15 @@ use any unique name, with the 'type' property providing the type.
The attributes supported for entries are described below.
-pos:
- This sets the position of an entry within the image. The first byte
- of the image is normally at position 0. If 'pos' is not provided,
- binman sets it to the end of the previous region, or the start of
- the image's entry area (normally 0) if there is no previous region.
+offset:
+ This sets the offset of an entry within the image or section containing
+ it. The first byte of the image is normally at offset 0. If 'offset' is
+ not provided, binman sets it to the end of the previous region, or the
+ start of the image's entry area (normally 0) if there is no previous
+ region.
align:
- This sets the alignment of the entry. The entry position is adjusted
+ This sets the alignment of the entry. The entry offset is adjusted
so that the entry starts on an aligned boundary within the image. For
example 'align = <16>' means that the entry will start on a 16-byte
boundary. Alignment shold be a power of 2. If 'align' is not
@@ -316,12 +317,18 @@ type:
possible to use any name, and then add (for example) 'type = "u-boot"'
to specify the type.
-pos-unset:
- Indicates that the position of this entry should not be set by placing
+offset-unset:
+ Indicates that the offset of this entry should not be set by placing
it immediately after the entry before. Instead, is set by another
entry which knows where this entry should go. When this boolean
property is present, binman will give an error if another entry does
- not set the position (with the GetPositions() method).
+ not set the offset (with the GetOffsets() method).
+
+image-pos:
+ This cannot be set on entry (or at least it is ignored if it is), but
+ with the -u option, binman will set it to the absolute image position
+ for each entry. This makes it easy to find out exactly where the entry
+ ended up in the image, regardless of parent sections, etc.
The attributes supported for images are described below. Several are similar
@@ -338,7 +345,7 @@ align-size:
pad-before:
This sets the padding before the image entries. The first entry will
- be positionad after the padding. This defaults to 0.
+ be positioned after the padding. This defaults to 0.
pad-after:
This sets the padding after the image entries. The padding will be
@@ -351,15 +358,15 @@ pad-byte:
filename:
This specifies the image filename. It defaults to 'image.bin'.
-sort-by-pos:
+sort-by-offset:
This causes binman to reorder the entries as needed to make sure they
are in increasing positional order. This can be used when your entry
order may not match the positional order. A common situation is where
- the 'pos' properties are set by CONFIG options, so their ordering is
+ the 'offset' properties are set by CONFIG options, so their ordering is
not known a priori.
This is a boolean property so needs no value. To enable it, add a
- line 'sort-by-pos;' to your description.
+ line 'sort-by-offset;' to your description.
multiple-images:
Normally only a single image is generated. To create more than one
@@ -383,11 +390,11 @@ multiple-images:
};
end-at-4gb:
- For x86 machines the ROM positions start just before 4GB and extend
+ For x86 machines the ROM offsets start just before 4GB and extend
up so that the image finished at the 4GB boundary. This boolean
option can be enabled to support this. The image size must be
provided so that binman knows when the image should start. For an
- 8MB ROM, the position of the first entry would be 0xfff80000 with
+ 8MB ROM, the offset of the first entry would be 0xfff80000 with
this option, instead of 0 without this option.
@@ -446,6 +453,15 @@ name-prefix:
distinguish binaries with otherwise identical names.
+Entry Documentation
+-------------------
+
+For details on the various entry types supported by binman and how to use them,
+see README.entries. This is generated from the source code using:
+
+ binman -E >tools/binman/README.entries
+
+
Special properties
------------------
@@ -463,7 +479,7 @@ Order of image creation
Image creation proceeds in the following order, for each entry in the image.
1. AddMissingProperties() - binman can add calculated values to the device
-tree as part of its processing, for example the position and size of each
+tree as part of its processing, for example the offset and size of each
entry. This method adds any properties associated with this, expanding the
device tree as needed. These properties can have placeholder values which are
set later by SetCalculatedProperties(). By that stage the size of sections
@@ -486,15 +502,15 @@ functions must return True when they have read the contents. Binman will
retry calling the functions a few times if False is returned, allowing
dependencies between the contents of different entries.
-4. GetEntryPositions() - calls Entry.GetPositions() for each entry. This can
+4. GetEntryOffsets() - calls Entry.GetOffsets() for each entry. This can
return a dict containing entries that need updating. The key should be the
-entry name and the value is a tuple (pos, size). This allows an entry to
-provide the position and size for other entries. The default implementation
-of GetEntryPositions() returns {}.
+entry name and the value is a tuple (offset, size). This allows an entry to
+provide the offset and size for other entries. The default implementation
+of GetEntryOffsets() returns {}.
-5. PackEntries() - calls Entry.Pack() which figures out the position and
-size of an entry. The 'current' image position is passed in, and the function
-returns the position immediately after the entry being packed. The default
+5. PackEntries() - calls Entry.Pack() which figures out the offset and
+size of an entry. The 'current' image offset is passed in, and the function
+returns the offset immediately after the entry being packed. The default
implementation of Pack() is usually sufficient.
6. CheckSize() - checks that the contents of all the entries fits within
@@ -505,16 +521,16 @@ large enough to hold all the entries.
outside the image.
8. SetCalculatedProperties() - update any calculated properties in the device
-tree. This sets the correct 'pos' and 'size' vaues, for example.
+tree. This sets the correct 'offset' and 'size' vaues, for example.
9. ProcessEntryContents() - this calls Entry.ProcessContents() on each entry.
The default implementatoin does nothing. This can be overriden to adjust the
contents of an entry in some way. For example, it would be possible to create
an entry containing a hash of the contents of some other entries. At this
-stage the position and size of entries should not be adjusted.
+stage the offset and size of entries should not be adjusted.
10. WriteSymbols() - write the value of symbols into the U-Boot SPL binary.
-See 'Access to binman entry positions at run time' below for a description of
+See 'Access to binman entry offsets at run time' below for a description of
what happens in this stage.
11. BuildImage() - builds the image and writes it to a file. This is the final
@@ -549,8 +565,8 @@ the 'warning' line in scripts/Makefile.lib to see what it has found:
# u_boot_dtsi_options_debug = $(u_boot_dtsi_options_raw)
-Access to binman entry positions at run time
---------------------------------------------
+Access to binman entry offsets at run time (symbols)
+----------------------------------------------------
Binman assembles images and determines where each entry is placed in the image.
This information may be useful to U-Boot at run time. For example, in SPL it
@@ -560,15 +576,15 @@ when SPL is finished.
Binman allows you to declare symbols in the SPL image which are filled in
with their correct values during the build. For example:
- binman_sym_declare(ulong, u_boot_any, pos);
+ binman_sym_declare(ulong, u_boot_any, offset);
-declares a ulong value which will be assigned to the position of any U-Boot
+declares a ulong value which will be assigned to the offset of any U-Boot
image (u-boot.bin, u-boot.img, u-boot-nodtb.bin) that is present in the image.
You can access this value with something like:
- ulong u_boot_pos = binman_sym(ulong, u_boot_any, pos);
+ ulong u_boot_offset = binman_sym(ulong, u_boot_any, offset);
-Thus u_boot_pos will be set to the position of U-Boot in memory, assuming that
+Thus u_boot_offset will be set to the offset of U-Boot in memory, assuming that
the whole image has been loaded, or is available in flash. You can then jump to
that address to start U-Boot.
@@ -576,25 +592,58 @@ At present this feature is only supported in SPL. In principle it is possible
to fill in such symbols in U-Boot proper, as well.
+Access to binman entry offsets at run time (fdt)
+------------------------------------------------
+
+Binman can update the U-Boot FDT to include the final position and size of
+each entry in the images it processes. The option to enable this is -u and it
+causes binman to make sure that the 'offset', 'image-pos' and 'size' properties
+are set correctly for every entry. Since it is not necessary to specify these in
+the image definition, binman calculates the final values and writes these to
+the device tree. These can be used by U-Boot at run-time to find the location
+of each entry.
+
+
Map files
---------
The -m option causes binman to output a .map file for each image that it
-generates. This shows the position and size of each entry. For example:
+generates. This shows the offset and size of each entry. For example:
- Position Size Name
- 00000000 00000010 section@0
- 00000000 00000004 u-boot
- 00000010 00000010 section@1
- 00000000 00000004 u-boot
+ Offset Size Name
+ 00000000 00000028 main-section
+ 00000000 00000010 section@0
+ 00000000 00000004 u-boot
+ 00000010 00000010 section@1
+ 00000000 00000004 u-boot
This shows a hierarchical image with two sections, each with a single entry. The
-positions of the sections are absolute hex byte offsets within the image. The
-positions of the entries are relative to their respective sections. The size of
+offsets of the sections are absolute hex byte offsets within the image. The
+offsets of the entries are relative to their respective sections. The size of
each entry is also shown, in bytes (hex). The indentation shows the entries
nested inside their sections.
+Passing command-line arguments to entries
+-----------------------------------------
+
+Sometimes it is useful to pass binman the value of an entry property from the
+command line. For example some entries need access to files and it is not
+always convenient to put these filenames in the image definition (device tree).
+
+The-a option supports this:
+
+ -a<prop>=<value>
+
+where
+
+ <prop> is the property to set
+ <value> is the value to set it to
+
+Not all properties can be provided this way. Only some entries support it,
+typically for filenames.
+
+
Code coverage
-------------
@@ -623,7 +672,7 @@ Entry properties are documented in entry.py. The entry subclasses are free
to change the values of properties to support special behaviour. For example,
when Entry_blob loads a file, it sets content_size to the size of the file.
Entry classes can adjust other entries. For example, an entry that knows
-where other entries should be positioned can set up those entries' positions
+where other entries should be positioned can set up those entries' offsets
so they don't need to be set in the binman decription. It can also adjust
entry contents.
diff --git a/tools/binman/README.entries b/tools/binman/README.entries
new file mode 100644
index 00000000000..c6e7b226090
--- /dev/null
+++ b/tools/binman/README.entries
@@ -0,0 +1,585 @@
+Binman Entry Documentation
+===========================
+
+This file describes the entry types supported by binman. These entry types can
+be placed in an image one by one to build up a final firmware image. It is
+fairly easy to create new entry types. Just add a new file to the 'etype'
+directory. You can use the existing entries as examples.
+
+Note that some entries are subclasses of others, using and extending their
+features to produce new behaviours.
+
+
+
+Entry: blob: Entry containing an arbitrary binary blob
+------------------------------------------------------
+
+Note: This should not be used by itself. It is normally used as a parent
+class by other entry types.
+
+Properties / Entry arguments:
+ - filename: Filename of file to read into entry
+
+This entry reads data from a file and places it in the entry. The
+default filename is often specified specified by the subclass. See for
+example the 'u_boot' entry which provides the filename 'u-boot.bin'.
+
+
+
+Entry: blob-named-by-arg: A blob entry which gets its filename property from its subclass
+-----------------------------------------------------------------------------------------
+
+Properties / Entry arguments:
+ - <xxx>-path: Filename containing the contents of this entry (optional,
+ defaults to 0)
+
+where <xxx> is the blob_fname argument to the constructor.
+
+This entry cannot be used directly. Instead, it is used as a parent class
+for another entry, which defined blob_fname. This parameter is used to
+set the entry-arg or property containing the filename. The entry-arg or
+property is in turn used to set the actual filename.
+
+See cros_ec_rw for an example of this.
+
+
+
+Entry: cros-ec-rw: A blob entry which contains a Chromium OS read-write EC image
+--------------------------------------------------------------------------------
+
+Properties / Entry arguments:
+ - cros-ec-rw-path: Filename containing the EC image
+
+This entry holds a Chromium OS EC (embedded controller) image, for use in
+updating the EC on startup via software sync.
+
+
+
+Entry: fill: An entry which is filled to a particular byte value
+----------------------------------------------------------------
+
+Properties / Entry arguments:
+ - fill-byte: Byte to use to fill the entry
+
+Note that the size property must be set since otherwise this entry does not
+know how large it should be.
+
+You can often achieve the same effect using the pad-byte property of the
+overall image, in that the space between entries will then be padded with
+that byte. But this entry is sometimes useful for explicitly setting the
+byte value of a region.
+
+
+
+Entry: fmap: An entry which contains an Fmap section
+----------------------------------------------------
+
+Properties / Entry arguments:
+ None
+
+FMAP is a simple format used by flashrom, an open-source utility for
+reading and writing the SPI flash, typically on x86 CPUs. The format
+provides flashrom with a list of areas, so it knows what it in the flash.
+It can then read or write just a single area, instead of the whole flash.
+
+The format is defined by the flashrom project, in the file lib/fmap.h -
+see www.flashrom.org/Flashrom for more information.
+
+When used, this entry will be populated with an FMAP which reflects the
+entries in the current image. Note that any hierarchy is squashed, since
+FMAP does not support this.
+
+
+
+Entry: gbb: An entry which contains a Chromium OS Google Binary Block
+---------------------------------------------------------------------
+
+Properties / Entry arguments:
+ - hardware-id: Hardware ID to use for this build (a string)
+ - keydir: Directory containing the public keys to use
+ - bmpblk: Filename containing images used by recovery
+
+Chromium OS uses a GBB to store various pieces of information, in particular
+the root and recovery keys that are used to verify the boot process. Some
+more details are here:
+
+ https://www.chromium.org/chromium-os/firmware-porting-guide/2-concepts
+
+but note that the page dates from 2013 so is quite out of date. See
+README.chromium for how to obtain the required keys and tools.
+
+
+
+Entry: intel-cmc: Entry containing an Intel Chipset Micro Code (CMC) file
+-------------------------------------------------------------------------
+
+Properties / Entry arguments:
+ - filename: Filename of file to read into entry
+
+This file contains microcode for some devices in a special format. An
+example filename is 'Microcode/C0_22211.BIN'.
+
+See README.x86 for information about x86 binary blobs.
+
+
+
+Entry: intel-descriptor: Intel flash descriptor block (4KB)
+-----------------------------------------------------------
+
+Properties / Entry arguments:
+ filename: Filename of file containing the descriptor. This is typically
+ a 4KB binary file, sometimes called 'descriptor.bin'
+
+This entry is placed at the start of flash and provides information about
+the SPI flash regions. In particular it provides the base address and
+size of the ME (Management Engine) region, allowing us to place the ME
+binary in the right place.
+
+With this entry in your image, the position of the 'intel-me' entry will be
+fixed in the image, which avoids you needed to specify an offset for that
+region. This is useful, because it is not possible to change the position
+of the ME region without updating the descriptor.
+
+See README.x86 for information about x86 binary blobs.
+
+
+
+Entry: intel-fsp: Entry containing an Intel Firmware Support Package (FSP) file
+-------------------------------------------------------------------------------
+
+Properties / Entry arguments:
+ - filename: Filename of file to read into entry
+
+This file contains binary blobs which are used on some devices to make the
+platform work. U-Boot executes this code since it is not possible to set up
+the hardware using U-Boot open-source code. Documentation is typically not
+available in sufficient detail to allow this.
+
+An example filename is 'FSP/QUEENSBAY_FSP_GOLD_001_20-DECEMBER-2013.fd'
+
+See README.x86 for information about x86 binary blobs.
+
+
+
+Entry: intel-me: Entry containing an Intel Management Engine (ME) file
+----------------------------------------------------------------------
+
+Properties / Entry arguments:
+ - filename: Filename of file to read into entry
+
+This file contains code used by the SoC that is required to make it work.
+The Management Engine is like a background task that runs things that are
+not clearly documented, but may include keyboard, deplay and network
+access. For platform that use ME it is not possible to disable it. U-Boot
+does not directly execute code in the ME binary.
+
+A typical filename is 'me.bin'.
+
+See README.x86 for information about x86 binary blobs.
+
+
+
+Entry: intel-mrc: Entry containing an Intel Memory Reference Code (MRC) file
+----------------------------------------------------------------------------
+
+Properties / Entry arguments:
+ - filename: Filename of file to read into entry
+
+This file contains code for setting up the SDRAM on some Intel systems. This
+is executed by U-Boot when needed early during startup. A typical filename
+is 'mrc.bin'.
+
+See README.x86 for information about x86 binary blobs.
+
+
+
+Entry: intel-vbt: Entry containing an Intel Video BIOS Table (VBT) file
+-----------------------------------------------------------------------
+
+Properties / Entry arguments:
+ - filename: Filename of file to read into entry
+
+This file contains code that sets up the integrated graphics subsystem on
+some Intel SoCs. U-Boot executes this when the display is started up.
+
+See README.x86 for information about Intel binary blobs.
+
+
+
+Entry: intel-vga: Entry containing an Intel Video Graphics Adaptor (VGA) file
+-----------------------------------------------------------------------------
+
+Properties / Entry arguments:
+ - filename: Filename of file to read into entry
+
+This file contains code that sets up the integrated graphics subsystem on
+some Intel SoCs. U-Boot executes this when the display is started up.
+
+This is similar to the VBT file but in a different format.
+
+See README.x86 for information about Intel binary blobs.
+
+
+
+Entry: section: Entry that contains other entries
+-------------------------------------------------
+
+Properties / Entry arguments: (see binman README for more information)
+ - size: Size of section in bytes
+ - align-size: Align size to a particular power of two
+ - pad-before: Add padding before the entry
+ - pad-after: Add padding after the entry
+ - pad-byte: Pad byte to use when padding
+ - sort-by-offset: Reorder the entries by offset
+ - end-at-4gb: Used to build an x86 ROM which ends at 4GB (2^32)
+ - name-prefix: Adds a prefix to the name of every entry in the section
+ when writing out the map
+
+A section is an entry which can contain other entries, thus allowing
+hierarchical images to be created. See 'Sections and hierarchical images'
+in the binman README for more information.
+
+
+
+Entry: text: An entry which contains text
+-----------------------------------------
+
+The text can be provided either in the node itself or by a command-line
+argument. There is a level of indirection to allow multiple text strings
+and sharing of text.
+
+Properties / Entry arguments:
+ text-label: The value of this string indicates the property / entry-arg
+ that contains the string to place in the entry
+ <xxx> (actual name is the value of text-label): contains the string to
+ place in the entry.
+
+Example node:
+
+ text {
+ size = <50>;
+ text-label = "message";
+ };
+
+You can then use:
+
+ binman -amessage="this is my message"
+
+and binman will insert that string into the entry.
+
+It is also possible to put the string directly in the node:
+
+ text {
+ size = <8>;
+ text-label = "message";
+ message = "a message directly in the node"
+ };
+
+The text is not itself nul-terminated. This can be achieved, if required,
+by setting the size of the entry to something larger than the text.
+
+
+
+Entry: u-boot: U-Boot flat binary
+---------------------------------
+
+Properties / Entry arguments:
+ - filename: Filename of u-boot.bin (default 'u-boot.bin')
+
+This is the U-Boot binary, containing relocation information to allow it
+to relocate itself at runtime. The binary typically includes a device tree
+blob at the end of it. Use u_boot_nodtb if you want to package the device
+tree separately.
+
+U-Boot can access binman symbols at runtime. See:
+
+ 'Access to binman entry offsets at run time (fdt)'
+
+in the binman README for more information.
+
+
+
+Entry: u-boot-dtb: U-Boot device tree
+-------------------------------------
+
+Properties / Entry arguments:
+ - filename: Filename of u-boot.dtb (default 'u-boot.dtb')
+
+This is the U-Boot device tree, containing configuration information for
+U-Boot. U-Boot needs this to know what devices are present and which drivers
+to activate.
+
+
+
+Entry: u-boot-dtb-with-ucode: A U-Boot device tree file, with the microcode removed
+-----------------------------------------------------------------------------------
+
+Properties / Entry arguments:
+ - filename: Filename of u-boot.dtb (default 'u-boot.dtb')
+
+See Entry_u_boot_ucode for full details of the three entries involved in
+this process. This entry provides the U-Boot device-tree file, which
+contains the microcode. If the microcode is not being collated into one
+place then the offset and size of the microcode is recorded by this entry,
+for use by u_boot_with_ucode_ptr. If it is being collated, then this
+entry deletes the microcode from the device tree (to save space) and makes
+it available to u_boot_ucode.
+
+
+
+Entry: u-boot-img: U-Boot legacy image
+--------------------------------------
+
+Properties / Entry arguments:
+ - filename: Filename of u-boot.img (default 'u-boot.img')
+
+This is the U-Boot binary as a packaged image, in legacy format. It has a
+header which allows it to be loaded at the correct address for execution.
+
+You should use FIT (Flat Image Tree) instead of the legacy image for new
+applications.
+
+
+
+Entry: u-boot-nodtb: U-Boot flat binary without device tree appended
+--------------------------------------------------------------------
+
+Properties / Entry arguments:
+ - filename: Filename of u-boot.bin (default 'u-boot-nodtb.bin')
+
+This is the U-Boot binary, containing relocation information to allow it
+to relocate itself at runtime. It does not include a device tree blob at
+the end of it so normally cannot work without it. You can add a u_boot_dtb
+entry after this one, or use a u_boot entry instead (which contains both
+U-Boot and the device tree).
+
+
+
+Entry: u-boot-spl: U-Boot SPL binary
+------------------------------------
+
+Properties / Entry arguments:
+ - filename: Filename of u-boot-spl.bin (default 'spl/u-boot-spl.bin')
+
+This is the U-Boot SPL (Secondary Program Loader) binary. This is a small
+binary which loads before U-Boot proper, typically into on-chip SRAM. It is
+responsible for locating, loading and jumping to U-Boot. Note that SPL is
+not relocatable so must be loaded to the correct address in SRAM, or written
+to run from the correct address if direct flash execution is possible (e.g.
+on x86 devices).
+
+SPL can access binman symbols at runtime. See:
+
+ 'Access to binman entry offsets at run time (symbols)'
+
+in the binman README for more information.
+
+The ELF file 'spl/u-boot-spl' must also be available for this to work, since
+binman uses that to look up symbols to write into the SPL binary.
+
+
+
+Entry: u-boot-spl-bss-pad: U-Boot SPL binary padded with a BSS region
+---------------------------------------------------------------------
+
+Properties / Entry arguments:
+ None
+
+This is similar to u_boot_spl except that padding is added after the SPL
+binary to cover the BSS (Block Started by Symbol) region. This region holds
+the various used by SPL. It is set to 0 by SPL when it starts up. If you
+want to append data to the SPL image (such as a device tree file), you must
+pad out the BSS region to avoid the data overlapping with U-Boot variables.
+This entry is useful in that case. It automatically pads out the entry size
+to cover both the code, data and BSS.
+
+The ELF file 'spl/u-boot-spl' must also be available for this to work, since
+binman uses that to look up the BSS address.
+
+
+
+Entry: u-boot-spl-dtb: U-Boot SPL device tree
+---------------------------------------------
+
+Properties / Entry arguments:
+ - filename: Filename of u-boot.dtb (default 'spl/u-boot-spl.dtb')
+
+This is the SPL device tree, containing configuration information for
+SPL. SPL needs this to know what devices are present and which drivers
+to activate.
+
+
+
+Entry: u-boot-spl-nodtb: SPL binary without device tree appended
+----------------------------------------------------------------
+
+Properties / Entry arguments:
+ - filename: Filename of spl/u-boot-spl-nodtb.bin (default
+ 'spl/u-boot-spl-nodtb.bin')
+
+This is the U-Boot SPL binary, It does not include a device tree blob at
+the end of it so may not be able to work without it, assuming SPL needs
+a device tree to operation on your platform. You can add a u_boot_spl_dtb
+entry after this one, or use a u_boot_spl entry instead (which contains
+both SPL and the device tree).
+
+
+
+Entry: u-boot-spl-with-ucode-ptr: U-Boot SPL with embedded microcode pointer
+----------------------------------------------------------------------------
+
+See Entry_u_boot_ucode for full details of the entries involved in this
+process.
+
+
+
+Entry: u-boot-tpl: U-Boot TPL binary
+------------------------------------
+
+Properties / Entry arguments:
+ - filename: Filename of u-boot-tpl.bin (default 'tpl/u-boot-tpl.bin')
+
+This is the U-Boot TPL (Tertiary Program Loader) binary. This is a small
+binary which loads before SPL, typically into on-chip SRAM. It is
+responsible for locating, loading and jumping to SPL, the next-stage
+loader. Note that SPL is not relocatable so must be loaded to the correct
+address in SRAM, or written to run from the correct address if direct
+flash execution is possible (e.g. on x86 devices).
+
+SPL can access binman symbols at runtime. See:
+
+ 'Access to binman entry offsets at run time (symbols)'
+
+in the binman README for more information.
+
+The ELF file 'tpl/u-boot-tpl' must also be available for this to work, since
+binman uses that to look up symbols to write into the TPL binary.
+
+
+
+Entry: u-boot-tpl-dtb: U-Boot TPL device tree
+---------------------------------------------
+
+Properties / Entry arguments:
+ - filename: Filename of u-boot.dtb (default 'tpl/u-boot-tpl.dtb')
+
+This is the TPL device tree, containing configuration information for
+TPL. TPL needs this to know what devices are present and which drivers
+to activate.
+
+
+
+Entry: u-boot-ucode: U-Boot microcode block
+-------------------------------------------
+
+Properties / Entry arguments:
+ None
+
+The contents of this entry are filled in automatically by other entries
+which must also be in the image.
+
+U-Boot on x86 needs a single block of microcode. This is collected from
+the various microcode update nodes in the device tree. It is also unable
+to read the microcode from the device tree on platforms that use FSP
+(Firmware Support Package) binaries, because the API requires that the
+microcode is supplied before there is any SRAM available to use (i.e.
+the FSP sets up the SRAM / cache-as-RAM but does so in the call that
+requires the microcode!). To keep things simple, all x86 platforms handle
+microcode the same way in U-Boot (even non-FSP platforms). This is that
+a table is placed at _dt_ucode_base_size containing the base address and
+size of the microcode. This is either passed to the FSP (for FSP
+platforms), or used to set up the microcode (for non-FSP platforms).
+This all happens in the build system since it is the only way to get
+the microcode into a single blob and accessible without SRAM.
+
+There are two cases to handle. If there is only one microcode blob in
+the device tree, then the ucode pointer it set to point to that. This
+entry (u-boot-ucode) is empty. If there is more than one update, then
+this entry holds the concatenation of all updates, and the device tree
+entry (u-boot-dtb-with-ucode) is updated to remove the microcode. This
+last step ensures that that the microcode appears in one contiguous
+block in the image and is not unnecessarily duplicated in the device
+tree. It is referred to as 'collation' here.
+
+Entry types that have a part to play in handling microcode:
+
+ Entry_u_boot_with_ucode_ptr:
+ Contains u-boot-nodtb.bin (i.e. U-Boot without the device tree).
+ It updates it with the address and size of the microcode so that
+ U-Boot can find it early on start-up.
+ Entry_u_boot_dtb_with_ucode:
+ Contains u-boot.dtb. It stores the microcode in a
+ 'self.ucode_data' property, which is then read by this class to
+ obtain the microcode if needed. If collation is performed, it
+ removes the microcode from the device tree.
+ Entry_u_boot_ucode:
+ This class. If collation is enabled it reads the microcode from
+ the Entry_u_boot_dtb_with_ucode entry, and uses it as the
+ contents of this entry.
+
+
+
+Entry: u-boot-with-ucode-ptr: U-Boot with embedded microcode pointer
+--------------------------------------------------------------------
+
+Properties / Entry arguments:
+ - filename: Filename of u-boot-nodtb.dtb (default 'u-boot-nodtb.dtb')
+
+See Entry_u_boot_ucode for full details of the three entries involved in
+this process. This entry updates U-Boot with the offset and size of the
+microcode, to allow early x86 boot code to find it without doing anything
+complicated. Otherwise it is the same as the u_boot entry.
+
+
+
+Entry: vblock: An entry which contains a Chromium OS verified boot block
+------------------------------------------------------------------------
+
+Properties / Entry arguments:
+ - keydir: Directory containing the public keys to use
+ - keyblock: Name of the key file to use (inside keydir)
+ - signprivate: Name of provide key file to use (inside keydir)
+ - version: Version number of the vblock (typically 1)
+ - kernelkey: Name of the kernel key to use (inside keydir)
+ - preamble-flags: Value of the vboot preamble flags (typically 0)
+
+Chromium OS signs the read-write firmware and kernel, writing the signature
+in this block. This allows U-Boot to verify that the next firmware stage
+and kernel are genuine.
+
+
+
+Entry: x86-start16: x86 16-bit start-up code for U-Boot
+-------------------------------------------------------
+
+Properties / Entry arguments:
+ - filename: Filename of u-boot-x86-16bit.bin (default
+ 'u-boot-x86-16bit.bin')
+
+x86 CPUs start up in 16-bit mode, even if they are 32-bit CPUs. This code
+must be placed at a particular address. This entry holds that code. It is
+typically placed at offset CONFIG_SYS_X86_START16. The code is responsible
+for changing to 32-bit mode and jumping to U-Boot's entry point, which
+requires 32-bit mode (for 32-bit U-Boot).
+
+For 64-bit U-Boot, the 'x86_start16_spl' entry type is used instead.
+
+
+
+Entry: x86-start16-spl: x86 16-bit start-up code for SPL
+--------------------------------------------------------
+
+Properties / Entry arguments:
+ - filename: Filename of spl/u-boot-x86-16bit-spl.bin (default
+ 'spl/u-boot-x86-16bit-spl.bin')
+
+x86 CPUs start up in 16-bit mode, even if they are 64-bit CPUs. This code
+must be placed at a particular address. This entry holds that code. It is
+typically placed at offset CONFIG_SYS_X86_START16. The code is responsible
+for changing to 32-bit mode and starting SPL, which in turn changes to
+64-bit mode and jumps to U-Boot (for 64-bit U-Boot).
+
+For 32-bit U-Boot, the 'x86_start16' entry type is used instead.
+
+
+
diff --git a/tools/binman/binman.py b/tools/binman/binman.py
index 52e02ed91b4..1536e956517 100755
--- a/tools/binman/binman.py
+++ b/tools/binman/binman.py
@@ -77,9 +77,20 @@ def RunTests(debug, args):
return 1
return 0
+def GetEntryModules(include_testing=True):
+ """Get a set of entry class implementations
+
+ Returns:
+ Set of paths to entry class filenames
+ """
+ glob_list = glob.glob(os.path.join(our_path, 'etype/*.py'))
+ return set([os.path.splitext(os.path.basename(item))[0]
+ for item in glob_list
+ if include_testing or '_testing' not in item])
+
def RunTestCoverage():
"""Run the tests and check that we get 100% coverage"""
- glob_list = glob.glob(os.path.join(our_path, 'etype/*.py'))
+ glob_list = GetEntryModules(False)
all_set = set([os.path.splitext(os.path.basename(item))[0]
for item in glob_list if '_testing' not in item])
test_util.RunTestCoverage('tools/binman/binman.py', None,
@@ -107,13 +118,8 @@ def RunBinman(options, args):
elif options.test_coverage:
RunTestCoverage()
- elif options.full_help:
- pager = os.getenv('PAGER')
- if not pager:
- pager = 'more'
- fname = os.path.join(os.path.dirname(os.path.realpath(sys.argv[0])),
- 'README')
- command.Run(pager, fname)
+ elif options.entry_docs:
+ control.WriteEntryDocs(GetEntryModules())
else:
try:
diff --git a/tools/binman/bsection.py b/tools/binman/bsection.py
index de439ef625f..a0bd1b6d34e 100644
--- a/tools/binman/bsection.py
+++ b/tools/binman/bsection.py
@@ -25,22 +25,21 @@ class Section(object):
_size: Section size in bytes, or None if not known yet
_align_size: Section size alignment, or None
_pad_before: Number of bytes before the first entry starts. This
- effectively changes the place where entry position 0 starts
+ effectively changes the place where entry offset 0 starts
_pad_after: Number of bytes after the last entry ends. The last
entry will finish on or before this boundary
_pad_byte: Byte to use to pad the section where there is no entry
- _sort: True if entries should be sorted by position, False if they
+ _sort: True if entries should be sorted by offset, False if they
must be in-order in the device tree description
_skip_at_start: Number of bytes before the first entry starts. These
- effectively adjust the starting position of entries. For example,
+ effectively adjust the starting offset of entries. For example,
if _pad_before is 16, then the first entry would start at 16.
- An entry with pos = 20 would in fact be written at position 4
+ An entry with offset = 20 would in fact be written at offset 4
in the image file.
_end_4gb: Indicates that the section ends at the 4GB boundary. This is
- used for x86 images, which want to use positions such that a
- memory address (like 0xff800000) is the first entry position.
- This causes _skip_at_start to be set to the starting memory
- address.
+ used for x86 images, which want to use offsets such that a memory
+ address (like 0xff800000) is the first entry offset. This causes
+ _skip_at_start to be set to the starting memory address.
_name_prefix: Prefix to add to the name of all entries within this
section
_entries: OrderedDict() of entries
@@ -51,7 +50,9 @@ class Section(object):
import entry
from entry import Entry
+ self._name = name
self._node = node
+ self._offset = 0
self._size = None
self._align_size = None
self._pad_before = 0
@@ -76,7 +77,7 @@ class Section(object):
self._pad_before = fdt_util.GetInt(self._node, 'pad-before', 0)
self._pad_after = fdt_util.GetInt(self._node, 'pad-after', 0)
self._pad_byte = fdt_util.GetInt(self._node, 'pad-byte', 0)
- self._sort = fdt_util.GetBool(self._node, 'sort-by-pos')
+ self._sort = fdt_util.GetBool(self._node, 'sort-by-offset')
self._end_4gb = fdt_util.GetBool(self._node, 'end-at-4gb')
if self._end_4gb and not self._size:
self._Raise("Section size must be provided when using end-at-4gb")
@@ -90,11 +91,21 @@ class Section(object):
entry.SetPrefix(self._name_prefix)
self._entries[node.name] = entry
+ def SetOffset(self, offset):
+ self._offset = offset
+
def AddMissingProperties(self):
+ """Add new properties to the device tree as needed for this entry"""
+ for prop in ['offset', 'size', 'image-pos']:
+ if not prop in self._node.props:
+ self._node.AddZeroProp(prop)
for entry in self._entries.values():
entry.AddMissingProperties()
def SetCalculatedProperties(self):
+ self._node.SetInt('offset', self._offset)
+ self._node.SetInt('size', self._size)
+ self._node.SetInt('image-pos', self._image_pos)
for entry in self._entries.values():
entry.SetCalculatedProperties()
@@ -117,7 +128,7 @@ class Section(object):
"""Check that the section contents does not exceed its size, etc."""
contents_size = 0
for entry in self._entries.values():
- contents_size = max(contents_size, entry.pos + entry.size)
+ contents_size = max(contents_size, entry.offset + entry.size)
contents_size -= self._skip_at_start
@@ -190,39 +201,41 @@ class Section(object):
'contents: remaining %s' % todo)
return True
- def _SetEntryPosSize(self, name, pos, size):
- """Set the position and size of an entry
+ def _SetEntryOffsetSize(self, name, offset, size):
+ """Set the offset and size of an entry
Args:
name: Entry name to update
- pos: New position
+ offset: New offset
size: New size
"""
entry = self._entries.get(name)
if not entry:
- self._Raise("Unable to set pos/size for unknown entry '%s'" % name)
- entry.SetPositionSize(self._skip_at_start + pos, size)
+ self._Raise("Unable to set offset/size for unknown entry '%s'" %
+ name)
+ entry.SetOffsetSize(self._skip_at_start + offset, size)
- def GetEntryPositions(self):
- """Handle entries that want to set the position/size of other entries
+ def GetEntryOffsets(self):
+ """Handle entries that want to set the offset/size of other entries
- This calls each entry's GetPositions() method. If it returns a list
+ This calls each entry's GetOffsets() method. If it returns a list
of entries to update, it updates them.
"""
for entry in self._entries.values():
- pos_dict = entry.GetPositions()
- for name, info in pos_dict.iteritems():
- self._SetEntryPosSize(name, *info)
+ offset_dict = entry.GetOffsets()
+ for name, info in offset_dict.iteritems():
+ self._SetEntryOffsetSize(name, *info)
def PackEntries(self):
"""Pack all entries into the section"""
- pos = self._skip_at_start
+ offset = self._skip_at_start
for entry in self._entries.values():
- pos = entry.Pack(pos)
+ offset = entry.Pack(offset)
+ self._size = self.CheckSize()
def _SortEntries(self):
- """Sort entries by position"""
- entries = sorted(self._entries.values(), key=lambda entry: entry.pos)
+ """Sort entries by offset"""
+ entries = sorted(self._entries.values(), key=lambda entry: entry.offset)
self._entries.clear()
for entry in entries:
self._entries[entry._node.name] = entry
@@ -231,23 +244,28 @@ class Section(object):
"""Check that entries do not overlap or extend outside the section"""
if self._sort:
self._SortEntries()
- pos = 0
+ offset = 0
prev_name = 'None'
for entry in self._entries.values():
- entry.CheckPosition()
- if (entry.pos < self._skip_at_start or
- entry.pos >= self._skip_at_start + self._size):
- entry.Raise("Position %#x (%d) is outside the section starting "
+ entry.CheckOffset()
+ if (entry.offset < self._skip_at_start or
+ entry.offset >= self._skip_at_start + self._size):
+ entry.Raise("Offset %#x (%d) is outside the section starting "
"at %#x (%d)" %
- (entry.pos, entry.pos, self._skip_at_start,
+ (entry.offset, entry.offset, self._skip_at_start,
self._skip_at_start))
- if entry.pos < pos:
- entry.Raise("Position %#x (%d) overlaps with previous entry '%s' "
+ if entry.offset < offset:
+ entry.Raise("Offset %#x (%d) overlaps with previous entry '%s' "
"ending at %#x (%d)" %
- (entry.pos, entry.pos, prev_name, pos, pos))
- pos = entry.pos + entry.size
+ (entry.offset, entry.offset, prev_name, offset, offset))
+ offset = entry.offset + entry.size
prev_name = entry.GetPath()
+ def SetImagePos(self, image_pos):
+ self._image_pos = image_pos
+ for entry in self._entries.values():
+ entry.SetImagePos(image_pos)
+
def ProcessEntryContents(self):
"""Call the ProcessContents() method for each entry
@@ -261,18 +279,18 @@ class Section(object):
for entry in self._entries.values():
entry.WriteSymbols(self)
- def BuildSection(self, fd, base_pos):
+ def BuildSection(self, fd, base_offset):
"""Write the section to a file"""
- fd.seek(base_pos)
+ fd.seek(base_offset)
fd.write(self.GetData())
def GetData(self):
- """Write the section to a file"""
+ """Get the contents of the section"""
section_data = chr(self._pad_byte) * self._size
for entry in self._entries.values():
data = entry.GetData()
- base = self._pad_before + entry.pos - self._skip_at_start
+ base = self._pad_before + entry.offset - self._skip_at_start
section_data = (section_data[:base] + data +
section_data[base + len(data):])
return section_data
@@ -283,15 +301,15 @@ class Section(object):
Looks up a symbol in an ELF file. Only entry types which come from an
ELF image can be used by this function.
- At present the only entry property supported is pos.
+ At present the only entry property supported is offset.
Args:
sym_name: Symbol name in the ELF file to look up in the format
_binman_<entry>_prop_<property> where <entry> is the name of
the entry and <property> is the property to find (e.g.
- _binman_u_boot_prop_pos). As a special case, you can append
+ _binman_u_boot_prop_offset). As a special case, you can append
_any to <entry> to have it search for any matching entry. E.g.
- _binman_u_boot_any_prop_pos will match entries called u-boot,
+ _binman_u_boot_any_prop_offset will match entries called u-boot,
u-boot-img and u-boot-nodtb)
optional: True if the symbol is optional. If False this function
will raise if the symbol is not found
@@ -327,19 +345,64 @@ class Section(object):
print('Warning: %s' % err, file=sys.stderr)
return None
raise ValueError(err)
- if prop_name == 'pos':
- return entry.pos
+ if prop_name == 'offset':
+ return entry.offset
+ elif prop_name == 'image_pos':
+ return entry.image_pos
else:
raise ValueError("%s: No such property '%s'" % (msg, prop_name))
def GetEntries(self):
+ """Get the number of entries in a section
+
+ Returns:
+ Number of entries in a section
+ """
return self._entries
+ def GetSize(self):
+ """Get the size of a section in bytes
+
+ This is only meaningful if the section has a pre-defined size, or the
+ entries within it have been packed, so that the size has been
+ calculated.
+
+ Returns:
+ Entry size in bytes
+ """
+ return self._size
+
def WriteMap(self, fd, indent):
"""Write a map of the section to a .map file
Args:
fd: File to write the map to
"""
+ Entry.WriteMapLine(fd, indent, self._name, self._offset, self._size,
+ self._image_pos)
+ for entry in self._entries.values():
+ entry.WriteMap(fd, indent + 1)
+
+ def GetContentsByPhandle(self, phandle, source_entry):
+ """Get the data contents of an entry specified by a phandle
+
+ This uses a phandle to look up a node and and find the entry
+ associated with it. Then it returnst he contents of that entry.
+
+ Args:
+ phandle: Phandle to look up (integer)
+ source_entry: Entry containing that phandle (used for error
+ reporting)
+
+ Returns:
+ data from associated entry (as a string), or None if not found
+ """
+ node = self._node.GetFdt().LookupPhandle(phandle)
+ if not node:
+ source_entry.Raise("Cannot find node for phandle %d" % phandle)
for entry in self._entries.values():
- entry.WriteMap(fd, indent)
+ if entry._node == node:
+ if entry.data is None:
+ return None
+ return entry.data
+ source_entry.Raise("Cannot find entry for node '%s'" % node.name)
diff --git a/tools/binman/cmdline.py b/tools/binman/cmdline.py
index ae2d1670f9a..f0de4ded443 100644
--- a/tools/binman/cmdline.py
+++ b/tools/binman/cmdline.py
@@ -18,6 +18,8 @@ def ParseArgs(argv):
args is a list of string arguments
"""
parser = OptionParser()
+ parser.add_option('-a', '--entry-arg', type='string', action='append',
+ help='Set argument value arg=value')
parser.add_option('-b', '--board', type='string',
help='Board name to build')
parser.add_option('-B', '--build-dir', type='string', default='b',
@@ -26,6 +28,8 @@ def ParseArgs(argv):
help='Configuration file (.dtb) to use')
parser.add_option('-D', '--debug', action='store_true',
help='Enabling debugging (provides a full traceback on error)')
+ parser.add_option('-E', '--entry-docs', action='store_true',
+ help='Write out entry documentation (see README.entries)')
parser.add_option('-I', '--indir', action='append',
help='Add a path to a directory to use for input files')
parser.add_option('-H', '--full-help', action='store_true',
@@ -43,7 +47,7 @@ def ParseArgs(argv):
parser.add_option('-T', '--test-coverage', action='store_true',
default=False, help='run tests and check for 100% coverage')
parser.add_option('-u', '--update-fdt', action='store_true',
- default=False, help='Update the binman node with position/size info')
+ default=False, help='Update the binman node with offset/size info')
parser.add_option('-v', '--verbosity', default=1,
type='int', help='Control verbosity: 0=silent, 1=progress, 3=full, '
'4=debug')
diff --git a/tools/binman/control.py b/tools/binman/control.py
index a40b300fdac..2de1c86ecfe 100644
--- a/tools/binman/control.py
+++ b/tools/binman/control.py
@@ -7,13 +7,12 @@
from collections import OrderedDict
import os
+import re
import sys
import tools
import command
import elf
-import fdt
-import fdt_util
from image import Image
import tout
@@ -25,6 +24,9 @@ images = OrderedDict()
# 'u-boot-spl.dtb')
fdt_files = {}
+# Arguments passed to binman to provide arguments to entries
+entry_args = {}
+
def _ReadImageDesc(binman_node):
"""Read the image descriptions from the /binman node
@@ -76,6 +78,24 @@ def GetFdt(fname):
def GetFdtPath(fname):
return fdt_files[fname]._fname
+def SetEntryArgs(args):
+ global entry_args
+
+ entry_args = {}
+ if args:
+ for arg in args:
+ m = re.match('([^=]*)=(.*)', arg)
+ if not m:
+ raise ValueError("Invalid entry arguemnt '%s'" % arg)
+ entry_args[m.group(1)] = m.group(2)
+
+def GetEntryArg(name):
+ return entry_args.get(name)
+
+def WriteEntryDocs(modules, test_missing=None):
+ from entry import Entry
+ Entry.WriteDocs(modules, test_missing)
+
def Binman(options, args):
"""The main control code for binman
@@ -111,11 +131,17 @@ def Binman(options, args):
options.indir.append(board_pathname)
try:
+ # Import these here in case libfdt.py is not available, in which case
+ # the above help option still works.
+ import fdt
+ import fdt_util
+
tout.Init(options.verbosity)
elf.debug = options.debug
try:
tools.SetInputDirs(options.indir)
tools.PrepareOutputDir(options.outdir, options.preserve)
+ SetEntryArgs(options.entry_arg)
# Get the device tree ready by compiling it and copying the compiled
# output into a file in our output directly. Then scan it for use
@@ -142,7 +168,7 @@ def Binman(options, args):
# size of the device tree is correct. Later, in
# SetCalculatedProperties() we will insert the correct values
# without changing the device-tree size, thus ensuring that our
- # entry positions remain the same.
+ # entry offsets remain the same.
for image in images.values():
if options.update_fdt:
image.AddMissingProperties()
@@ -157,10 +183,11 @@ def Binman(options, args):
# image will be reported after earlier images are already
# completed and written, but that does not seem important.
image.GetEntryContents()
- image.GetEntryPositions()
+ image.GetEntryOffsets()
image.PackEntries()
image.CheckSize()
image.CheckEntries()
+ image.SetImagePos()
if options.update_fdt:
image.SetCalculatedProperties()
image.ProcessEntryContents()
diff --git a/tools/binman/elf.py b/tools/binman/elf.py
index 0ae3b611bae..97df8e32c5d 100644
--- a/tools/binman/elf.py
+++ b/tools/binman/elf.py
@@ -57,7 +57,9 @@ def GetSymbols(fname, patterns):
name = parts[2]
syms[name] = Symbol(section, int(value, 16), int(size,16),
flags[1] == 'w')
- return syms
+
+ # Sort dict by address
+ return OrderedDict(sorted(syms.iteritems(), key=lambda x: x[1].address))
def GetSymbolAddress(fname, sym_name):
"""Get a value of a symbol from an ELF file
@@ -79,9 +81,9 @@ def LookupAndWriteSymbols(elf_fname, entry, section):
"""Replace all symbols in an entry with their correct values
The entry contents is updated so that values for referenced symbols will be
- visible at run time. This is done by finding out the symbols positions in
- the entry (using the ELF file) and replacing them with values from binman's
- data structures.
+ visible at run time. This is done by finding out the symbols offsets in the
+ entry (using the ELF file) and replacing them with values from binman's data
+ structures.
Args:
elf_fname: Filename of ELF image containing the symbol information for
diff --git a/tools/binman/elf_test.py b/tools/binman/elf_test.py
index 9c8f1feca85..c16f71401d1 100644
--- a/tools/binman/elf_test.py
+++ b/tools/binman/elf_test.py
@@ -15,6 +15,10 @@ binman_dir = os.path.dirname(os.path.realpath(sys.argv[0]))
class FakeEntry:
+ """A fake Entry object, usedfor testing
+
+ This supports an entry with a given size.
+ """
def __init__(self, contents_size):
self.contents_size = contents_size
self.data = 'a' * contents_size
@@ -22,7 +26,14 @@ class FakeEntry:
def GetPath(self):
return 'entry_path'
+
class FakeSection:
+ """A fake Section object, used for testing
+
+ This has the minimum feature set needed to support testing elf functions.
+ A LookupSymbol() function is provided which returns a fake value for amu
+ symbol requested.
+ """
def __init__(self, sym_value=1):
self.sym_value = sym_value
@@ -30,15 +41,19 @@ class FakeSection:
return 'section_path'
def LookupSymbol(self, name, weak, msg):
+ """Fake implementation which returns the same value for all symbols"""
return self.sym_value
+
class TestElf(unittest.TestCase):
def testAllSymbols(self):
+ """Test that we can obtain a symbol from the ELF file"""
fname = os.path.join(binman_dir, 'test', 'u_boot_ucode_ptr')
syms = elf.GetSymbols(fname, [])
self.assertIn('.ucode', syms)
def testRegexSymbols(self):
+ """Test that we can obtain from the ELF file by regular expression"""
fname = os.path.join(binman_dir, 'test', 'u_boot_ucode_ptr')
syms = elf.GetSymbols(fname, ['ucode'])
self.assertIn('.ucode', syms)
@@ -48,6 +63,7 @@ class TestElf(unittest.TestCase):
self.assertIn('.ucode', syms)
def testMissingFile(self):
+ """Test that a missing file is detected"""
entry = FakeEntry(10)
section = FakeSection()
with self.assertRaises(ValueError) as e:
@@ -56,6 +72,7 @@ class TestElf(unittest.TestCase):
str(e.exception))
def testOutsideFile(self):
+ """Test a symbol which extends outside the entry area is detected"""
entry = FakeEntry(10)
section = FakeSection()
elf_fname = os.path.join(binman_dir, 'test', 'u_boot_binman_syms')
@@ -65,6 +82,11 @@ class TestElf(unittest.TestCase):
'is a', str(e.exception))
def testMissingImageStart(self):
+ """Test that we detect a missing __image_copy_start symbol
+
+ This is needed to mark the start of the image. Without it we cannot
+ locate the offset of a binman symbol within the image.
+ """
entry = FakeEntry(10)
section = FakeSection()
elf_fname = os.path.join(binman_dir, 'test', 'u_boot_binman_syms_bad')
@@ -72,6 +94,11 @@ class TestElf(unittest.TestCase):
None)
def testBadSymbolSize(self):
+ """Test that an attempt to use an 8-bit symbol are detected
+
+ Only 32 and 64 bits are supported, since we need to store an offset
+ into the image.
+ """
entry = FakeEntry(10)
section = FakeSection()
elf_fname = os.path.join(binman_dir, 'test', 'u_boot_binman_syms_size')
@@ -81,6 +108,11 @@ class TestElf(unittest.TestCase):
str(e.exception))
def testNoValue(self):
+ """Test the case where we have no value for the symbol
+
+ This should produce -1 values for all thress symbols, taking up the
+ first 16 bytes of the image.
+ """
entry = FakeEntry(20)
section = FakeSection(sym_value=None)
elf_fname = os.path.join(binman_dir, 'test', 'u_boot_binman_syms')
@@ -88,6 +120,7 @@ class TestElf(unittest.TestCase):
self.assertEqual(chr(255) * 16 + 'a' * 4, entry.data)
def testDebug(self):
+ """Check that enabling debug in the elf module produced debug output"""
elf.debug = True
entry = FakeEntry(20)
section = FakeSection()
diff --git a/tools/binman/entry.py b/tools/binman/entry.py
index 6a173e663d0..77cfab9c5de 100644
--- a/tools/binman/entry.py
+++ b/tools/binman/entry.py
@@ -6,6 +6,8 @@
from __future__ import print_function
+from collections import namedtuple
+
# importlib was introduced in Python 2.7 but there was a report of it not
# working in 2.7.12, so we work around this:
# http://lists.denx.de/pipermail/u-boot/2016-October/269729.html
@@ -16,6 +18,7 @@ except:
have_importlib = False
import fdt_util
+import control
import os
import sys
import tools
@@ -24,6 +27,12 @@ modules = {}
our_path = os.path.dirname(os.path.realpath(__file__))
+
+# An argument which can be passed to entries on the command line, in lieu of
+# device-tree properties.
+EntryArg = namedtuple('EntryArg', ['name', 'datatype'])
+
+
class Entry(object):
"""An Entry in the section
@@ -36,14 +45,15 @@ class Entry(object):
Entry.
Attributes:
- section: The section containing this entry
+ section: Section object containing this entry
node: The node that created this entry
- pos: Absolute position of entry within the section, None if not known
+ offset: Offset of entry within the section, None if not known yet (in
+ which case it will be calculated by Pack())
size: Entry size in bytes, None if not known
contents_size: Size of contents in bytes, 0 by default
- align: Entry start position alignment, or None
+ align: Entry start offset alignment, or None
align_size: Entry size alignment, or None
- align_end: Entry end position alignment, or None
+ align_end: Entry end offset alignment, or None
pad_before: Number of pad bytes before the contents, 0 if none
pad_after: Number of pad bytes after the contents, 0 if none
data: Contents of entry (string of bytes)
@@ -53,34 +63,33 @@ class Entry(object):
self.etype = etype
self._node = node
self.name = node and (name_prefix + node.name) or 'none'
- self.pos = None
+ self.offset = None
self.size = None
- self.data = ''
+ self.data = None
self.contents_size = 0
self.align = None
self.align_size = None
self.align_end = None
self.pad_before = 0
self.pad_after = 0
- self.pos_unset = False
+ self.offset_unset = False
+ self.image_pos = None
if read_node:
self.ReadNode()
@staticmethod
- def Create(section, node, etype=None):
- """Create a new entry for a node.
+ def Lookup(section, node_path, etype):
+ """Look up the entry class for a node.
Args:
- section: Image object containing this node
- node: Node object containing information about the entry to create
- etype: Entry type to use, or None to work it out (used for tests)
+ section: Section object containing this node
+ node_node: Path name of Node object containing information about
+ the entry to create (used for errors)
+ etype: Entry type to use
Returns:
- A new Entry object of the correct type (a subclass of Entry)
+ The entry class object if found, else None
"""
- if not etype:
- etype = fdt_util.GetString(node, 'type', node.name)
-
# Convert something like 'u-boot@0' to 'u_boot' since we are only
# interested in the type.
module_name = etype.replace('-', '_')
@@ -99,15 +108,34 @@ class Entry(object):
module = importlib.import_module(module_name)
else:
module = __import__(module_name)
- except ImportError:
- raise ValueError("Unknown entry type '%s' in node '%s'" %
- (etype, node.path))
+ except ImportError as e:
+ raise ValueError("Unknown entry type '%s' in node '%s' (expected etype/%s.py, error '%s'" %
+ (etype, node_path, module_name, e))
finally:
sys.path = old_path
modules[module_name] = module
+ # Look up the expected class name
+ return getattr(module, 'Entry_%s' % module_name)
+
+ @staticmethod
+ def Create(section, node, etype=None):
+ """Create a new entry for a node.
+
+ Args:
+ section: Section object containing this node
+ node: Node object containing information about the entry to
+ create
+ etype: Entry type to use, or None to work it out (used for tests)
+
+ Returns:
+ A new Entry object of the correct type (a subclass of Entry)
+ """
+ if not etype:
+ etype = fdt_util.GetString(node, 'type', node.name)
+ obj = Entry.Lookup(section, node.path, etype)
+
# Call its constructor to get the object we want.
- obj = getattr(module, 'Entry_%s' % module_name)
return obj(section, etype, node)
def ReadNode(self):
@@ -115,7 +143,9 @@ class Entry(object):
This reads all the fields we recognise from the node, ready for use.
"""
- self.pos = fdt_util.GetInt(self._node, 'pos')
+ if 'pos' in self._node.props:
+ self.Raise("Please use 'offset' instead of 'pos'")
+ self.offset = fdt_util.GetInt(self._node, 'offset')
self.size = fdt_util.GetInt(self._node, 'size')
self.align = fdt_util.GetInt(self._node, 'align')
if tools.NotPowerOfTwo(self.align):
@@ -128,18 +158,19 @@ class Entry(object):
raise ValueError("Node '%s': Alignment size %s must be a power "
"of two" % (self._node.path, self.align_size))
self.align_end = fdt_util.GetInt(self._node, 'align-end')
- self.pos_unset = fdt_util.GetBool(self._node, 'pos-unset')
+ self.offset_unset = fdt_util.GetBool(self._node, 'offset-unset')
def AddMissingProperties(self):
"""Add new properties to the device tree as needed for this entry"""
- for prop in ['pos', 'size']:
+ for prop in ['offset', 'size', 'image-pos']:
if not prop in self._node.props:
self._node.AddZeroProp(prop)
def SetCalculatedProperties(self):
"""Set the value of device-tree properties calculated by binman"""
- self._node.SetInt('pos', self.pos)
+ self._node.SetInt('offset', self.offset)
self._node.SetInt('size', self.size)
+ self._node.SetInt('image-pos', self.image_pos)
def ProcessFdt(self, fdt):
return True
@@ -190,39 +221,39 @@ class Entry(object):
# No contents by default: subclasses can implement this
return True
- def Pack(self, pos):
+ def Pack(self, offset):
"""Figure out how to pack the entry into the section
Most of the time the entries are not fully specified. There may be
an alignment but no size. In that case we take the size from the
contents of the entry.
- If an entry has no hard-coded position, it will be placed at @pos.
+ If an entry has no hard-coded offset, it will be placed at @offset.
- Once this function is complete, both the position and size of the
+ Once this function is complete, both the offset and size of the
entry will be know.
Args:
- Current section position pointer
+ Current section offset pointer
Returns:
- New section position pointer (after this entry)
+ New section offset pointer (after this entry)
"""
- if self.pos is None:
- if self.pos_unset:
- self.Raise('No position set with pos-unset: should another '
- 'entry provide this correct position?')
- self.pos = tools.Align(pos, self.align)
+ if self.offset is None:
+ if self.offset_unset:
+ self.Raise('No offset set with offset-unset: should another '
+ 'entry provide this correct offset?')
+ self.offset = tools.Align(offset, self.align)
needed = self.pad_before + self.contents_size + self.pad_after
needed = tools.Align(needed, self.align_size)
size = self.size
if not size:
size = needed
- new_pos = self.pos + size
- aligned_pos = tools.Align(new_pos, self.align_end)
- if aligned_pos != new_pos:
- size = aligned_pos - self.pos
- new_pos = aligned_pos
+ new_offset = self.offset + size
+ aligned_offset = tools.Align(new_offset, self.align_end)
+ if aligned_offset != new_offset:
+ size = aligned_offset - self.offset
+ new_offset = aligned_offset
if not self.size:
self.size = size
@@ -231,21 +262,48 @@ class Entry(object):
self.Raise("Entry contents size is %#x (%d) but entry size is "
"%#x (%d)" % (needed, needed, self.size, self.size))
# Check that the alignment is correct. It could be wrong if the
- # and pos or size values were provided (i.e. not calculated), but
+ # and offset or size values were provided (i.e. not calculated), but
# conflict with the provided alignment values
if self.size != tools.Align(self.size, self.align_size):
self.Raise("Size %#x (%d) does not match align-size %#x (%d)" %
(self.size, self.size, self.align_size, self.align_size))
- if self.pos != tools.Align(self.pos, self.align):
- self.Raise("Position %#x (%d) does not match align %#x (%d)" %
- (self.pos, self.pos, self.align, self.align))
+ if self.offset != tools.Align(self.offset, self.align):
+ self.Raise("Offset %#x (%d) does not match align %#x (%d)" %
+ (self.offset, self.offset, self.align, self.align))
- return new_pos
+ return new_offset
def Raise(self, msg):
"""Convenience function to raise an error referencing a node"""
raise ValueError("Node '%s': %s" % (self._node.path, msg))
+ def GetEntryArgsOrProps(self, props, required=False):
+ """Return the values of a set of properties
+
+ Args:
+ props: List of EntryArg objects
+
+ Raises:
+ ValueError if a property is not found
+ """
+ values = []
+ missing = []
+ for prop in props:
+ python_prop = prop.name.replace('-', '_')
+ if hasattr(self, python_prop):
+ value = getattr(self, python_prop)
+ else:
+ value = None
+ if value is None:
+ value = self.GetArg(prop.name, prop.datatype)
+ if value is None and required:
+ missing.append(prop.name)
+ values.append(value)
+ if missing:
+ self.Raise('Missing required properties/entry args: %s' %
+ (', '.join(missing)))
+ return values
+
def GetPath(self):
"""Get the path of a node
@@ -257,13 +315,21 @@ class Entry(object):
def GetData(self):
return self.data
- def GetPositions(self):
+ def GetOffsets(self):
return {}
- def SetPositionSize(self, pos, size):
- self.pos = pos
+ def SetOffsetSize(self, pos, size):
+ self.offset = pos
self.size = size
+ def SetImagePos(self, image_pos):
+ """Set the position in the image
+
+ Args:
+ image_pos: Position of this entry in the image
+ """
+ self.image_pos = image_pos + self.offset
+
def ProcessContents(self):
pass
@@ -275,15 +341,20 @@ class Entry(object):
"""
pass
- def CheckPosition(self):
- """Check that the entry positions are correct
+ def CheckOffset(self):
+ """Check that the entry offsets are correct
- This is used for entries which have extra position requirements (other
+ This is used for entries which have extra offset requirements (other
than having to be fully inside their section). Sub-classes can implement
this function and raise if there is a problem.
"""
pass
+ @staticmethod
+ def WriteMapLine(fd, indent, name, offset, size, image_pos):
+ print('%08x %s%08x %08x %s' % (image_pos, ' ' * indent, offset,
+ size, name), file=fd)
+
def WriteMap(self, fd, indent):
"""Write a map of the entry to a .map file
@@ -291,5 +362,97 @@ class Entry(object):
fd: File to write the map to
indent: Curent indent level of map (0=none, 1=one level, etc.)
"""
- print('%s%08x %08x %s' % (' ' * indent, self.pos, self.size,
- self.name), file=fd)
+ self.WriteMapLine(fd, indent, self.name, self.offset, self.size,
+ self.image_pos)
+
+ def GetEntries(self):
+ """Return a list of entries contained by this entry
+
+ Returns:
+ List of entries, or None if none. A normal entry has no entries
+ within it so will return None
+ """
+ return None
+
+ def GetArg(self, name, datatype=str):
+ """Get the value of an entry argument or device-tree-node property
+
+ Some node properties can be provided as arguments to binman. First check
+ the entry arguments, and fall back to the device tree if not found
+
+ Args:
+ name: Argument name
+ datatype: Data type (str or int)
+
+ Returns:
+ Value of argument as a string or int, or None if no value
+
+ Raises:
+ ValueError if the argument cannot be converted to in
+ """
+ value = control.GetEntryArg(name)
+ if value is not None:
+ if datatype == int:
+ try:
+ value = int(value)
+ except ValueError:
+ self.Raise("Cannot convert entry arg '%s' (value '%s') to integer" %
+ (name, value))
+ elif datatype == str:
+ pass
+ else:
+ raise ValueError("GetArg() internal error: Unknown data type '%s'" %
+ datatype)
+ else:
+ value = fdt_util.GetDatatype(self._node, name, datatype)
+ return value
+
+ @staticmethod
+ def WriteDocs(modules, test_missing=None):
+ """Write out documentation about the various entry types to stdout
+
+ Args:
+ modules: List of modules to include
+ test_missing: Used for testing. This is a module to report
+ as missing
+ """
+ print('''Binman Entry Documentation
+===========================
+
+This file describes the entry types supported by binman. These entry types can
+be placed in an image one by one to build up a final firmware image. It is
+fairly easy to create new entry types. Just add a new file to the 'etype'
+directory. You can use the existing entries as examples.
+
+Note that some entries are subclasses of others, using and extending their
+features to produce new behaviours.
+
+
+''')
+ modules = sorted(modules)
+
+ # Don't show the test entry
+ if '_testing' in modules:
+ modules.remove('_testing')
+ missing = []
+ for name in modules:
+ module = Entry.Lookup(name, name, name)
+ docs = getattr(module, '__doc__')
+ if test_missing == name:
+ docs = None
+ if docs:
+ lines = docs.splitlines()
+ first_line = lines[0]
+ rest = [line[4:] for line in lines[1:]]
+ hdr = 'Entry: %s: %s' % (name.replace('_', '-'), first_line)
+ print(hdr)
+ print('-' * len(hdr))
+ print('\n'.join(rest))
+ print()
+ print()
+ else:
+ missing.append(name)
+
+ if missing:
+ raise ValueError('Documentation is missing for modules: %s' %
+ ', '.join(missing))
diff --git a/tools/binman/etype/_testing.py b/tools/binman/etype/_testing.py
index 6a1af577988..02c165c0c3e 100644
--- a/tools/binman/etype/_testing.py
+++ b/tools/binman/etype/_testing.py
@@ -5,7 +5,9 @@
# Entry-type module for testing purposes. Not used in real images.
#
-from entry import Entry
+from collections import OrderedDict
+
+from entry import Entry, EntryArg
import fdt_util
import tools
@@ -13,8 +15,30 @@ import tools
class Entry__testing(Entry):
"""A fake entry used for testing
+ This entry should not be used in normal images. It is a special entry with
+ strange features used for testing.
+
+ Properties / Entry arguments
+ test-str-fdt: Test string, normally in the node
+ test-int-fdt: Test integer, normally in the node
+ test-str-arg: Test string, normally in the entry arguments
+ test-int-arg: Test integer, normally in the entry arguments
+
+ The entry has a single 'a' byte as its contents. Operation is controlled by
+ a number of properties in the node, as follows:
+
Properties:
- return_invalid_entry: Return an invalid entry from GetPositions()
+ return-invalid-entry: Return an invalid entry from GetOffsets()
+ return-unknown-contents: Refuse to provide any contents (to cause a
+ failure)
+ bad-update-contents: Implement ProcessContents() incorrectly so as to
+ cause a failure
+ never-complete-process-fdt: Refund to process the FDT (to cause a
+ failure)
+ require-args: Require that all used args are present (generating an
+ error if not)
+ force-bad-datatype: Force a call to GetEntryArgsOrProps() with a bad
+ data type (generating an error)
"""
def __init__(self, section, etype, node):
Entry.__init__(self, section, etype, node)
@@ -24,9 +48,26 @@ class Entry__testing(Entry):
'return-unknown-contents')
self.bad_update_contents = fdt_util.GetBool(self._node,
'bad-update-contents')
+
+ # Set to True when the entry is ready to process the FDT.
self.process_fdt_ready = False
self.never_complete_process_fdt = fdt_util.GetBool(self._node,
'never-complete-process-fdt')
+ self.require_args = fdt_util.GetBool(self._node, 'require-args')
+
+ # This should be picked up by GetEntryArgsOrProps()
+ self.test_existing_prop = 'existing'
+ self.force_bad_datatype = fdt_util.GetBool(self._node,
+ 'force-bad-datatype')
+ (self.test_str_fdt, self.test_str_arg, self.test_int_fdt,
+ self.test_int_arg, existing) = self.GetEntryArgsOrProps([
+ EntryArg('test-str-fdt', str),
+ EntryArg('test-str-arg', str),
+ EntryArg('test-int-fdt', int),
+ EntryArg('test-int-arg', int),
+ EntryArg('test-existing-prop', str)], self.require_args)
+ if self.force_bad_datatype:
+ self.GetEntryArgsOrProps([EntryArg('test-bad-datatype-arg', bool)])
def ObtainContents(self):
if self.return_unknown_contents:
@@ -35,7 +76,7 @@ class Entry__testing(Entry):
self.contents_size = len(self.data)
return True
- def GetPositions(self):
+ def GetOffsets(self):
if self.return_invalid_entry :
return {'invalid-entry': [1, 2]}
return {}
diff --git a/tools/binman/etype/blob.py b/tools/binman/etype/blob.py
index 28e6651a935..3f46eecf308 100644
--- a/tools/binman/etype/blob.py
+++ b/tools/binman/etype/blob.py
@@ -10,6 +10,18 @@ import fdt_util
import tools
class Entry_blob(Entry):
+ """Entry containing an arbitrary binary blob
+
+ Note: This should not be used by itself. It is normally used as a parent
+ class by other entry types.
+
+ Properties / Entry arguments:
+ - filename: Filename of file to read into entry
+
+ This entry reads data from a file and places it in the entry. The
+ default filename is often specified specified by the subclass. See for
+ example the 'u_boot' entry which provides the filename 'u-boot.bin'.
+ """
def __init__(self, section, etype, node):
Entry.__init__(self, section, etype, node)
self._filename = fdt_util.GetString(self._node, "filename", self.etype)
@@ -17,10 +29,10 @@ class Entry_blob(Entry):
def ObtainContents(self):
self._filename = self.GetDefaultFilename()
self._pathname = tools.GetInputFilename(self._filename)
- self.ReadContents()
+ self.ReadBlobContents()
return True
- def ReadContents(self):
+ def ReadBlobContents(self):
with open(self._pathname) as fd:
# We assume the data is small enough to fit into memory. If this
# is used for large filesystem image that might not be true.
diff --git a/tools/binman/etype/blob_named_by_arg.py b/tools/binman/etype/blob_named_by_arg.py
new file mode 100644
index 00000000000..344112bc420
--- /dev/null
+++ b/tools/binman/etype/blob_named_by_arg.py
@@ -0,0 +1,34 @@
+# SPDX-License-Identifier: GPL-2.0+
+# Copyright (c) 2018 Google, Inc
+# Written by Simon Glass <sjg@chromium.org>
+#
+# Entry-type module for a blob where the filename comes from a property in the
+# node or an entry argument. The property is called '<blob_fname>-path' where
+# <blob_fname> is provided by the subclass using this entry type.
+
+from collections import OrderedDict
+
+from blob import Entry_blob
+from entry import EntryArg
+
+
+class Entry_blob_named_by_arg(Entry_blob):
+ """A blob entry which gets its filename property from its subclass
+
+ Properties / Entry arguments:
+ - <xxx>-path: Filename containing the contents of this entry (optional,
+ defaults to 0)
+
+ where <xxx> is the blob_fname argument to the constructor.
+
+ This entry cannot be used directly. Instead, it is used as a parent class
+ for another entry, which defined blob_fname. This parameter is used to
+ set the entry-arg or property containing the filename. The entry-arg or
+ property is in turn used to set the actual filename.
+
+ See cros_ec_rw for an example of this.
+ """
+ def __init__(self, section, etype, node, blob_fname):
+ Entry_blob.__init__(self, section, etype, node)
+ self._filename, = self.GetEntryArgsOrProps(
+ [EntryArg('%s-path' % blob_fname, str)])
diff --git a/tools/binman/etype/cros_ec_rw.py b/tools/binman/etype/cros_ec_rw.py
new file mode 100644
index 00000000000..261f8657a62
--- /dev/null
+++ b/tools/binman/etype/cros_ec_rw.py
@@ -0,0 +1,22 @@
+# SPDX-License-Identifier: GPL-2.0+
+# Copyright (c) 2018 Google, Inc
+# Written by Simon Glass <sjg@chromium.org>
+#
+# Entry-type module for a Chromium OS EC image (read-write section)
+#
+
+from blob_named_by_arg import Entry_blob_named_by_arg
+
+
+class Entry_cros_ec_rw(Entry_blob_named_by_arg):
+ """A blob entry which contains a Chromium OS read-write EC image
+
+ Properties / Entry arguments:
+ - cros-ec-rw-path: Filename containing the EC image
+
+ This entry holds a Chromium OS EC (embedded controller) image, for use in
+ updating the EC on startup via software sync.
+ """
+ def __init__(self, section, etype, node):
+ Entry_blob_named_by_arg.__init__(self, section, etype, node,
+ 'cros-ec-rw')
diff --git a/tools/binman/etype/fill.py b/tools/binman/etype/fill.py
new file mode 100644
index 00000000000..7210a8324a0
--- /dev/null
+++ b/tools/binman/etype/fill.py
@@ -0,0 +1,32 @@
+# SPDX-License-Identifier: GPL-2.0+
+# Copyright (c) 2018 Google, Inc
+# Written by Simon Glass <sjg@chromium.org>
+#
+
+from entry import Entry
+import fdt_util
+
+
+class Entry_fill(Entry):
+ """An entry which is filled to a particular byte value
+
+ Properties / Entry arguments:
+ - fill-byte: Byte to use to fill the entry
+
+ Note that the size property must be set since otherwise this entry does not
+ know how large it should be.
+
+ You can often achieve the same effect using the pad-byte property of the
+ overall image, in that the space between entries will then be padded with
+ that byte. But this entry is sometimes useful for explicitly setting the
+ byte value of a region.
+ """
+ def __init__(self, section, etype, node):
+ Entry.__init__(self, section, etype, node)
+ if not self.size:
+ self.Raise("'fill' entry must have a size property")
+ self.fill_value = fdt_util.GetByte(self._node, 'fill-byte', 0)
+
+ def ObtainContents(self):
+ self.SetContents(chr(self.fill_value) * self.size)
+ return True
diff --git a/tools/binman/etype/fmap.py b/tools/binman/etype/fmap.py
new file mode 100644
index 00000000000..f1dd81ec493
--- /dev/null
+++ b/tools/binman/etype/fmap.py
@@ -0,0 +1,61 @@
+# SPDX-License-Identifier: GPL-2.0+
+# Copyright (c) 2018 Google, Inc
+# Written by Simon Glass <sjg@chromium.org>
+#
+# Entry-type module for a Flash map, as used by the flashrom SPI flash tool
+#
+
+from entry import Entry
+import fmap_util
+
+
+class Entry_fmap(Entry):
+ """An entry which contains an Fmap section
+
+ Properties / Entry arguments:
+ None
+
+ FMAP is a simple format used by flashrom, an open-source utility for
+ reading and writing the SPI flash, typically on x86 CPUs. The format
+ provides flashrom with a list of areas, so it knows what it in the flash.
+ It can then read or write just a single area, instead of the whole flash.
+
+ The format is defined by the flashrom project, in the file lib/fmap.h -
+ see www.flashrom.org/Flashrom for more information.
+
+ When used, this entry will be populated with an FMAP which reflects the
+ entries in the current image. Note that any hierarchy is squashed, since
+ FMAP does not support this.
+ """
+ def __init__(self, section, etype, node):
+ Entry.__init__(self, section, etype, node)
+
+ def _GetFmap(self):
+ """Build an FMAP from the entries in the current image
+
+ Returns:
+ FMAP binary data
+ """
+ def _AddEntries(areas, entry):
+ entries = entry.GetEntries()
+ if entries:
+ for subentry in entries.values():
+ _AddEntries(areas, subentry)
+ else:
+ areas.append(fmap_util.FmapArea(entry.image_pos or 0,
+ entry.size or 0, entry.name, 0))
+
+ entries = self.section.GetEntries()
+ areas = []
+ for entry in entries.values():
+ _AddEntries(areas, entry)
+ return fmap_util.EncodeFmap(self.section.GetSize() or 0, self.name,
+ areas)
+
+ def ObtainContents(self):
+ """Obtain a placeholder for the fmap contents"""
+ self.SetContents(self._GetFmap())
+ return True
+
+ def ProcessContents(self):
+ self.SetContents(self._GetFmap())
diff --git a/tools/binman/etype/gbb.py b/tools/binman/etype/gbb.py
new file mode 100644
index 00000000000..8fe10f47135
--- /dev/null
+++ b/tools/binman/etype/gbb.py
@@ -0,0 +1,96 @@
+# SPDX-License-Identifier: GPL-2.0+
+# Copyright (c) 2018 Google, Inc
+# Written by Simon Glass <sjg@chromium.org>
+#
+
+# Support for a Chromium OS Google Binary Block, used to record read-only
+# information mostly used by firmware.
+
+from collections import OrderedDict
+
+import command
+from entry import Entry, EntryArg
+
+import fdt_util
+import tools
+
+# Build GBB flags.
+# (src/platform/vboot_reference/firmware/include/gbb_header.h)
+gbb_flag_properties = {
+ 'dev-screen-short-delay': 0x1,
+ 'load-option-roms': 0x2,
+ 'enable-alternate-os': 0x4,
+ 'force-dev-switch-on': 0x8,
+ 'force-dev-boot-usb': 0x10,
+ 'disable-fw-rollback-check': 0x20,
+ 'enter-triggers-tonorm': 0x40,
+ 'force-dev-boot-legacy': 0x80,
+ 'faft-key-override': 0x100,
+ 'disable-ec-software-sync': 0x200,
+ 'default-dev-boot-legacy': 0x400,
+ 'disable-pd-software-sync': 0x800,
+ 'disable-lid-shutdown': 0x1000,
+ 'force-dev-boot-fastboot-full-cap': 0x2000,
+ 'enable-serial': 0x4000,
+ 'disable-dwmp': 0x8000,
+}
+
+
+class Entry_gbb(Entry):
+ """An entry which contains a Chromium OS Google Binary Block
+
+ Properties / Entry arguments:
+ - hardware-id: Hardware ID to use for this build (a string)
+ - keydir: Directory containing the public keys to use
+ - bmpblk: Filename containing images used by recovery
+
+ Chromium OS uses a GBB to store various pieces of information, in particular
+ the root and recovery keys that are used to verify the boot process. Some
+ more details are here:
+
+ https://www.chromium.org/chromium-os/firmware-porting-guide/2-concepts
+
+ but note that the page dates from 2013 so is quite out of date. See
+ README.chromium for how to obtain the required keys and tools.
+ """
+ def __init__(self, section, etype, node):
+ Entry.__init__(self, section, etype, node)
+ self.hardware_id, self.keydir, self.bmpblk = self.GetEntryArgsOrProps(
+ [EntryArg('hardware-id', str),
+ EntryArg('keydir', str),
+ EntryArg('bmpblk', str)])
+
+ # Read in the GBB flags from the config
+ self.gbb_flags = 0
+ flags_node = node.FindNode('flags')
+ if flags_node:
+ for flag, value in gbb_flag_properties.iteritems():
+ if fdt_util.GetBool(flags_node, flag):
+ self.gbb_flags |= value
+
+ def ObtainContents(self):
+ gbb = 'gbb.bin'
+ fname = tools.GetOutputFilename(gbb)
+ if not self.size:
+ self.Raise('GBB must have a fixed size')
+ gbb_size = self.size
+ bmpfv_size = gbb_size - 0x2180
+ if bmpfv_size < 0:
+ self.Raise('GBB is too small (minimum 0x2180 bytes)')
+ sizes = [0x100, 0x1000, bmpfv_size, 0x1000]
+ sizes = ['%#x' % size for size in sizes]
+ keydir = tools.GetInputFilename(self.keydir)
+ gbb_set_command = [
+ 'gbb_utility', '-s',
+ '--hwid=%s' % self.hardware_id,
+ '--rootkey=%s/root_key.vbpubk' % keydir,
+ '--recoverykey=%s/recovery_key.vbpubk' % keydir,
+ '--flags=%d' % self.gbb_flags,
+ '--bmpfv=%s' % tools.GetInputFilename(self.bmpblk),
+ fname]
+
+ tools.Run('futility', 'gbb_utility', '-c', ','.join(sizes), fname)
+ tools.Run('futility', *gbb_set_command)
+
+ self.SetContents(tools.ReadFile(fname))
+ return True
diff --git a/tools/binman/etype/intel_cmc.py b/tools/binman/etype/intel_cmc.py
index b8621e0cc5e..fa6f7793c64 100644
--- a/tools/binman/etype/intel_cmc.py
+++ b/tools/binman/etype/intel_cmc.py
@@ -9,5 +9,15 @@ from entry import Entry
from blob import Entry_blob
class Entry_intel_cmc(Entry_blob):
+ """Entry containing an Intel Chipset Micro Code (CMC) file
+
+ Properties / Entry arguments:
+ - filename: Filename of file to read into entry
+
+ This file contains microcode for some devices in a special format. An
+ example filename is 'Microcode/C0_22211.BIN'.
+
+ See README.x86 for information about x86 binary blobs.
+ """
def __init__(self, section, etype, node):
Entry_blob.__init__(self, section, etype, node)
diff --git a/tools/binman/etype/intel_descriptor.py b/tools/binman/etype/intel_descriptor.py
index 0e7865521e1..6acbbd8b7a5 100644
--- a/tools/binman/etype/intel_descriptor.py
+++ b/tools/binman/etype/intel_descriptor.py
@@ -13,6 +13,7 @@ from blob import Entry_blob
FD_SIGNATURE = struct.pack('<L', 0x0ff0a55a)
MAX_REGIONS = 5
+# Region numbers supported by the Intel firmware format
(REGION_DESCRIPTOR, REGION_BIOS, REGION_ME, REGION_GBE,
REGION_PDATA) = range(5)
@@ -27,21 +28,32 @@ class Region:
class Entry_intel_descriptor(Entry_blob):
"""Intel flash descriptor block (4KB)
- This is placed at the start of flash and provides information about
+ Properties / Entry arguments:
+ filename: Filename of file containing the descriptor. This is typically
+ a 4KB binary file, sometimes called 'descriptor.bin'
+
+ This entry is placed at the start of flash and provides information about
the SPI flash regions. In particular it provides the base address and
- size of the ME region, allowing us to place the ME binary in the right
- place.
+ size of the ME (Management Engine) region, allowing us to place the ME
+ binary in the right place.
+
+ With this entry in your image, the position of the 'intel-me' entry will be
+ fixed in the image, which avoids you needed to specify an offset for that
+ region. This is useful, because it is not possible to change the position
+ of the ME region without updating the descriptor.
+
+ See README.x86 for information about x86 binary blobs.
"""
def __init__(self, section, etype, node):
Entry_blob.__init__(self, section, etype, node)
self._regions = []
- def GetPositions(self):
- pos = self.data.find(FD_SIGNATURE)
- if pos == -1:
+ def GetOffsets(self):
+ offset = self.data.find(FD_SIGNATURE)
+ if offset == -1:
self.Raise('Cannot find FD signature')
flvalsig, flmap0, flmap1, flmap2 = struct.unpack('<LLLL',
- self.data[pos:pos + 16])
+ self.data[offset:offset + 16])
frba = ((flmap0 >> 16) & 0xff) << 4
for i in range(MAX_REGIONS):
self._regions.append(Region(self.data, frba, i))
diff --git a/tools/binman/etype/intel_fsp.py b/tools/binman/etype/intel_fsp.py
index cb80a617c32..00a78e70832 100644
--- a/tools/binman/etype/intel_fsp.py
+++ b/tools/binman/etype/intel_fsp.py
@@ -9,5 +9,19 @@ from entry import Entry
from blob import Entry_blob
class Entry_intel_fsp(Entry_blob):
+ """Entry containing an Intel Firmware Support Package (FSP) file
+
+ Properties / Entry arguments:
+ - filename: Filename of file to read into entry
+
+ This file contains binary blobs which are used on some devices to make the
+ platform work. U-Boot executes this code since it is not possible to set up
+ the hardware using U-Boot open-source code. Documentation is typically not
+ available in sufficient detail to allow this.
+
+ An example filename is 'FSP/QUEENSBAY_FSP_GOLD_001_20-DECEMBER-2013.fd'
+
+ See README.x86 for information about x86 binary blobs.
+ """
def __init__(self, section, etype, node):
Entry_blob.__init__(self, section, etype, node)
diff --git a/tools/binman/etype/intel_me.py b/tools/binman/etype/intel_me.py
index 0682ead9439..247c5b33866 100644
--- a/tools/binman/etype/intel_me.py
+++ b/tools/binman/etype/intel_me.py
@@ -9,5 +9,20 @@ from entry import Entry
from blob import Entry_blob
class Entry_intel_me(Entry_blob):
+ """Entry containing an Intel Management Engine (ME) file
+
+ Properties / Entry arguments:
+ - filename: Filename of file to read into entry
+
+ This file contains code used by the SoC that is required to make it work.
+ The Management Engine is like a background task that runs things that are
+ not clearly documented, but may include keyboard, deplay and network
+ access. For platform that use ME it is not possible to disable it. U-Boot
+ does not directly execute code in the ME binary.
+
+ A typical filename is 'me.bin'.
+
+ See README.x86 for information about x86 binary blobs.
+ """
def __init__(self, section, etype, node):
Entry_blob.__init__(self, section, etype, node)
diff --git a/tools/binman/etype/intel_mrc.py b/tools/binman/etype/intel_mrc.py
index 305ac98888b..4dbc99a04f2 100644
--- a/tools/binman/etype/intel_mrc.py
+++ b/tools/binman/etype/intel_mrc.py
@@ -9,6 +9,17 @@ from entry import Entry
from blob import Entry_blob
class Entry_intel_mrc(Entry_blob):
+ """Entry containing an Intel Memory Reference Code (MRC) file
+
+ Properties / Entry arguments:
+ - filename: Filename of file to read into entry
+
+ This file contains code for setting up the SDRAM on some Intel systems. This
+ is executed by U-Boot when needed early during startup. A typical filename
+ is 'mrc.bin'.
+
+ See README.x86 for information about x86 binary blobs.
+ """
def __init__(self, section, etype, node):
Entry_blob.__init__(self, section, etype, node)
diff --git a/tools/binman/etype/intel_vbt.py b/tools/binman/etype/intel_vbt.py
index d4e8c3f797d..d93dd196341 100644
--- a/tools/binman/etype/intel_vbt.py
+++ b/tools/binman/etype/intel_vbt.py
@@ -8,5 +8,15 @@ from entry import Entry
from blob import Entry_blob
class Entry_intel_vbt(Entry_blob):
+ """Entry containing an Intel Video BIOS Table (VBT) file
+
+ Properties / Entry arguments:
+ - filename: Filename of file to read into entry
+
+ This file contains code that sets up the integrated graphics subsystem on
+ some Intel SoCs. U-Boot executes this when the display is started up.
+
+ See README.x86 for information about Intel binary blobs.
+ """
def __init__(self, section, etype, node):
Entry_blob.__init__(self, section, etype, node)
diff --git a/tools/binman/etype/intel_vga.py b/tools/binman/etype/intel_vga.py
index 140dd40dda6..40982c86656 100644
--- a/tools/binman/etype/intel_vga.py
+++ b/tools/binman/etype/intel_vga.py
@@ -9,5 +9,17 @@ from entry import Entry
from blob import Entry_blob
class Entry_intel_vga(Entry_blob):
+ """Entry containing an Intel Video Graphics Adaptor (VGA) file
+
+ Properties / Entry arguments:
+ - filename: Filename of file to read into entry
+
+ This file contains code that sets up the integrated graphics subsystem on
+ some Intel SoCs. U-Boot executes this when the display is started up.
+
+ This is similar to the VBT file but in a different format.
+
+ See README.x86 for information about Intel binary blobs.
+ """
def __init__(self, section, etype, node):
Entry_blob.__init__(self, section, etype, node)
diff --git a/tools/binman/etype/section.py b/tools/binman/etype/section.py
index 787257d3ec1..f5b2ed67cf8 100644
--- a/tools/binman/etype/section.py
+++ b/tools/binman/etype/section.py
@@ -13,8 +13,25 @@ import tools
import bsection
class Entry_section(Entry):
- def __init__(self, image, etype, node):
- Entry.__init__(self, image, etype, node)
+ """Entry that contains other entries
+
+ Properties / Entry arguments: (see binman README for more information)
+ - size: Size of section in bytes
+ - align-size: Align size to a particular power of two
+ - pad-before: Add padding before the entry
+ - pad-after: Add padding after the entry
+ - pad-byte: Pad byte to use when padding
+ - sort-by-offset: Reorder the entries by offset
+ - end-at-4gb: Used to build an x86 ROM which ends at 4GB (2^32)
+ - name-prefix: Adds a prefix to the name of every entry in the section
+ when writing out the map
+
+ A section is an entry which can contain other entries, thus allowing
+ hierarchical images to be created. See 'Sections and hierarchical images'
+ in the binman README for more information.
+ """
+ def __init__(self, section, etype, node):
+ Entry.__init__(self, section, etype, node)
self._section = bsection.Section(node.name, node)
def ProcessFdt(self, fdt):
@@ -30,20 +47,25 @@ class Entry_section(Entry):
def GetData(self):
return self._section.GetData()
- def GetPositions(self):
- """Handle entries that want to set the position/size of other entries
+ def GetOffsets(self):
+ """Handle entries that want to set the offset/size of other entries
- This calls each entry's GetPositions() method. If it returns a list
+ This calls each entry's GetOffsets() method. If it returns a list
of entries to update, it updates them.
"""
- self._section.GetEntryPositions()
+ self._section.GetEntryOffsets()
return {}
- def Pack(self, pos):
+ def Pack(self, offset):
"""Pack all entries into the section"""
self._section.PackEntries()
- self.size = self._section.CheckSize()
- return super(Entry_section, self).Pack(pos)
+ self._section.SetOffset(offset)
+ self.size = self._section.GetSize()
+ return super(Entry_section, self).Pack(offset)
+
+ def SetImagePos(self, image_pos):
+ Entry.SetImagePos(self, image_pos)
+ self._section.SetImagePos(image_pos + self.offset)
def WriteSymbols(self, section):
"""Write symbol values into binary files for access at run time"""
@@ -57,7 +79,7 @@ class Entry_section(Entry):
self._section.ProcessEntryContents()
super(Entry_section, self).ProcessContents()
- def CheckPosition(self):
+ def CheckOffset(self):
self._section.CheckEntries()
def WriteMap(self, fd, indent):
@@ -66,5 +88,7 @@ class Entry_section(Entry):
Args:
fd: File to write the map to
"""
- super(Entry_section, self).WriteMap(fd, indent)
- self._section.WriteMap(fd, indent + 1)
+ self._section.WriteMap(fd, indent)
+
+ def GetEntries(self):
+ return self._section.GetEntries()
diff --git a/tools/binman/etype/text.py b/tools/binman/etype/text.py
new file mode 100644
index 00000000000..7a1cddf4af8
--- /dev/null
+++ b/tools/binman/etype/text.py
@@ -0,0 +1,57 @@
+# SPDX-License-Identifier: GPL-2.0+
+# Copyright (c) 2018 Google, Inc
+# Written by Simon Glass <sjg@chromium.org>
+#
+
+from collections import OrderedDict
+
+from entry import Entry, EntryArg
+import fdt_util
+
+
+class Entry_text(Entry):
+ """An entry which contains text
+
+ The text can be provided either in the node itself or by a command-line
+ argument. There is a level of indirection to allow multiple text strings
+ and sharing of text.
+
+ Properties / Entry arguments:
+ text-label: The value of this string indicates the property / entry-arg
+ that contains the string to place in the entry
+ <xxx> (actual name is the value of text-label): contains the string to
+ place in the entry.
+
+ Example node:
+
+ text {
+ size = <50>;
+ text-label = "message";
+ };
+
+ You can then use:
+
+ binman -amessage="this is my message"
+
+ and binman will insert that string into the entry.
+
+ It is also possible to put the string directly in the node:
+
+ text {
+ size = <8>;
+ text-label = "message";
+ message = "a message directly in the node"
+ };
+
+ The text is not itself nul-terminated. This can be achieved, if required,
+ by setting the size of the entry to something larger than the text.
+ """
+ def __init__(self, section, etype, node):
+ Entry.__init__(self, section, etype, node)
+ self.text_label, = self.GetEntryArgsOrProps(
+ [EntryArg('text-label', str)])
+ self.value, = self.GetEntryArgsOrProps([EntryArg(self.text_label, str)])
+
+ def ObtainContents(self):
+ self.SetContents(self.value)
+ return True
diff --git a/tools/binman/etype/u_boot.py b/tools/binman/etype/u_boot.py
index b6058bf6b52..23dd12ce435 100644
--- a/tools/binman/etype/u_boot.py
+++ b/tools/binman/etype/u_boot.py
@@ -9,6 +9,22 @@ from entry import Entry
from blob import Entry_blob
class Entry_u_boot(Entry_blob):
+ """U-Boot flat binary
+
+ Properties / Entry arguments:
+ - filename: Filename of u-boot.bin (default 'u-boot.bin')
+
+ This is the U-Boot binary, containing relocation information to allow it
+ to relocate itself at runtime. The binary typically includes a device tree
+ blob at the end of it. Use u_boot_nodtb if you want to package the device
+ tree separately.
+
+ U-Boot can access binman symbols at runtime. See:
+
+ 'Access to binman entry offsets at run time (fdt)'
+
+ in the binman README for more information.
+ """
def __init__(self, section, etype, node):
Entry_blob.__init__(self, section, etype, node)
diff --git a/tools/binman/etype/u_boot_dtb.py b/tools/binman/etype/u_boot_dtb.py
index dd3c5b27901..fb3dd1cf642 100644
--- a/tools/binman/etype/u_boot_dtb.py
+++ b/tools/binman/etype/u_boot_dtb.py
@@ -9,6 +9,15 @@ from entry import Entry
from blob import Entry_blob
class Entry_u_boot_dtb(Entry_blob):
+ """U-Boot device tree
+
+ Properties / Entry arguments:
+ - filename: Filename of u-boot.dtb (default 'u-boot.dtb')
+
+ This is the U-Boot device tree, containing configuration information for
+ U-Boot. U-Boot needs this to know what devices are present and which drivers
+ to activate.
+ """
def __init__(self, section, etype, node):
Entry_blob.__init__(self, section, etype, node)
diff --git a/tools/binman/etype/u_boot_dtb_with_ucode.py b/tools/binman/etype/u_boot_dtb_with_ucode.py
index 3808d6d2780..285a28dd1e7 100644
--- a/tools/binman/etype/u_boot_dtb_with_ucode.py
+++ b/tools/binman/etype/u_boot_dtb_with_ucode.py
@@ -6,7 +6,6 @@
#
import control
-import fdt
from entry import Entry
from blob import Entry_blob
import tools
@@ -14,8 +13,16 @@ import tools
class Entry_u_boot_dtb_with_ucode(Entry_blob):
"""A U-Boot device tree file, with the microcode removed
- See Entry_u_boot_ucode for full details of the 3 entries involved in this
- process.
+ Properties / Entry arguments:
+ - filename: Filename of u-boot.dtb (default 'u-boot.dtb')
+
+ See Entry_u_boot_ucode for full details of the three entries involved in
+ this process. This entry provides the U-Boot device-tree file, which
+ contains the microcode. If the microcode is not being collated into one
+ place then the offset and size of the microcode is recorded by this entry,
+ for use by u_boot_with_ucode_ptr. If it is being collated, then this
+ entry deletes the microcode from the device tree (to save space) and makes
+ it available to u_boot_ucode.
"""
def __init__(self, section, etype, node):
Entry_blob.__init__(self, section, etype, node)
@@ -30,13 +37,16 @@ class Entry_u_boot_dtb_with_ucode(Entry_blob):
return 'u-boot.dtb'
def ProcessFdt(self, fdt):
+ # So the module can be loaded without it
+ import fdt
+
# If the section does not need microcode, there is nothing to do
ucode_dest_entry = self.section.FindEntryType(
'u-boot-spl-with-ucode-ptr')
- if not ucode_dest_entry or not ucode_dest_entry.target_pos:
+ if not ucode_dest_entry or not ucode_dest_entry.target_offset:
ucode_dest_entry = self.section.FindEntryType(
'u-boot-with-ucode-ptr')
- if not ucode_dest_entry or not ucode_dest_entry.target_pos:
+ if not ucode_dest_entry or not ucode_dest_entry.target_offset:
return True
# Remove the microcode
@@ -61,7 +71,7 @@ class Entry_u_boot_dtb_with_ucode(Entry_blob):
# Call the base class just in case it does something important.
Entry_blob.ObtainContents(self)
self._pathname = control.GetFdtPath(self._filename)
- self.ReadContents()
+ self.ReadBlobContents()
if self.ucode:
for node in self.ucode.subnodes:
data_prop = node.props.get('data')
diff --git a/tools/binman/etype/u_boot_img.py b/tools/binman/etype/u_boot_img.py
index 6e0b736af14..1ec0757c7f8 100644
--- a/tools/binman/etype/u_boot_img.py
+++ b/tools/binman/etype/u_boot_img.py
@@ -9,6 +9,17 @@ from entry import Entry
from blob import Entry_blob
class Entry_u_boot_img(Entry_blob):
+ """U-Boot legacy image
+
+ Properties / Entry arguments:
+ - filename: Filename of u-boot.img (default 'u-boot.img')
+
+ This is the U-Boot binary as a packaged image, in legacy format. It has a
+ header which allows it to be loaded at the correct address for execution.
+
+ You should use FIT (Flat Image Tree) instead of the legacy image for new
+ applications.
+ """
def __init__(self, section, etype, node):
Entry_blob.__init__(self, section, etype, node)
diff --git a/tools/binman/etype/u_boot_nodtb.py b/tools/binman/etype/u_boot_nodtb.py
index ca9e53a0947..a4b95a4390a 100644
--- a/tools/binman/etype/u_boot_nodtb.py
+++ b/tools/binman/etype/u_boot_nodtb.py
@@ -9,6 +9,17 @@ from entry import Entry
from blob import Entry_blob
class Entry_u_boot_nodtb(Entry_blob):
+ """U-Boot flat binary without device tree appended
+
+ Properties / Entry arguments:
+ - filename: Filename of u-boot.bin (default 'u-boot-nodtb.bin')
+
+ This is the U-Boot binary, containing relocation information to allow it
+ to relocate itself at runtime. It does not include a device tree blob at
+ the end of it so normally cannot work without it. You can add a u_boot_dtb
+ entry after this one, or use a u_boot entry instead (which contains both
+ U-Boot and the device tree).
+ """
def __init__(self, section, etype, node):
Entry_blob.__init__(self, section, etype, node)
diff --git a/tools/binman/etype/u_boot_spl.py b/tools/binman/etype/u_boot_spl.py
index 9edd2dad030..ab78714c8d6 100644
--- a/tools/binman/etype/u_boot_spl.py
+++ b/tools/binman/etype/u_boot_spl.py
@@ -11,6 +11,27 @@ from entry import Entry
from blob import Entry_blob
class Entry_u_boot_spl(Entry_blob):
+ """U-Boot SPL binary
+
+ Properties / Entry arguments:
+ - filename: Filename of u-boot-spl.bin (default 'spl/u-boot-spl.bin')
+
+ This is the U-Boot SPL (Secondary Program Loader) binary. This is a small
+ binary which loads before U-Boot proper, typically into on-chip SRAM. It is
+ responsible for locating, loading and jumping to U-Boot. Note that SPL is
+ not relocatable so must be loaded to the correct address in SRAM, or written
+ to run from the correct address if direct flash execution is possible (e.g.
+ on x86 devices).
+
+ SPL can access binman symbols at runtime. See:
+
+ 'Access to binman entry offsets at run time (symbols)'
+
+ in the binman README for more information.
+
+ The ELF file 'spl/u-boot-spl' must also be available for this to work, since
+ binman uses that to look up symbols to write into the SPL binary.
+ """
def __init__(self, section, etype, node):
Entry_blob.__init__(self, section, etype, node)
self.elf_fname = 'spl/u-boot-spl'
diff --git a/tools/binman/etype/u_boot_spl_bss_pad.py b/tools/binman/etype/u_boot_spl_bss_pad.py
index 65f631d3c5e..00b7ac50040 100644
--- a/tools/binman/etype/u_boot_spl_bss_pad.py
+++ b/tools/binman/etype/u_boot_spl_bss_pad.py
@@ -14,6 +14,22 @@ from blob import Entry_blob
import tools
class Entry_u_boot_spl_bss_pad(Entry_blob):
+ """U-Boot SPL binary padded with a BSS region
+
+ Properties / Entry arguments:
+ None
+
+ This is similar to u_boot_spl except that padding is added after the SPL
+ binary to cover the BSS (Block Started by Symbol) region. This region holds
+ the various used by SPL. It is set to 0 by SPL when it starts up. If you
+ want to append data to the SPL image (such as a device tree file), you must
+ pad out the BSS region to avoid the data overlapping with U-Boot variables.
+ This entry is useful in that case. It automatically pads out the entry size
+ to cover both the code, data and BSS.
+
+ The ELF file 'spl/u-boot-spl' must also be available for this to work, since
+ binman uses that to look up the BSS address.
+ """
def __init__(self, section, etype, node):
Entry_blob.__init__(self, section, etype, node)
diff --git a/tools/binman/etype/u_boot_spl_dtb.py b/tools/binman/etype/u_boot_spl_dtb.py
index eefa1ff53a4..cb29ba3fd87 100644
--- a/tools/binman/etype/u_boot_spl_dtb.py
+++ b/tools/binman/etype/u_boot_spl_dtb.py
@@ -2,13 +2,22 @@
# Copyright (c) 2016 Google, Inc
# Written by Simon Glass <sjg@chromium.org>
#
-# Entry-type module for U-Boot device tree
+# Entry-type module for U-Boot device tree in SPL (Secondary Program Loader)
#
from entry import Entry
from blob import Entry_blob
class Entry_u_boot_spl_dtb(Entry_blob):
+ """U-Boot SPL device tree
+
+ Properties / Entry arguments:
+ - filename: Filename of u-boot.dtb (default 'spl/u-boot-spl.dtb')
+
+ This is the SPL device tree, containing configuration information for
+ SPL. SPL needs this to know what devices are present and which drivers
+ to activate.
+ """
def __init__(self, section, etype, node):
Entry_blob.__init__(self, section, etype, node)
diff --git a/tools/binman/etype/u_boot_spl_nodtb.py b/tools/binman/etype/u_boot_spl_nodtb.py
index 99e56ebe3bf..41c17366b1d 100644
--- a/tools/binman/etype/u_boot_spl_nodtb.py
+++ b/tools/binman/etype/u_boot_spl_nodtb.py
@@ -9,6 +9,18 @@ from entry import Entry
from blob import Entry_blob
class Entry_u_boot_spl_nodtb(Entry_blob):
+ """SPL binary without device tree appended
+
+ Properties / Entry arguments:
+ - filename: Filename of spl/u-boot-spl-nodtb.bin (default
+ 'spl/u-boot-spl-nodtb.bin')
+
+ This is the U-Boot SPL binary, It does not include a device tree blob at
+ the end of it so may not be able to work without it, assuming SPL needs
+ a device tree to operation on your platform. You can add a u_boot_spl_dtb
+ entry after this one, or use a u_boot_spl entry instead (which contains
+ both SPL and the device tree).
+ """
def __init__(self, section, etype, node):
Entry_blob.__init__(self, section, etype, node)
diff --git a/tools/binman/etype/u_boot_tpl.py b/tools/binman/etype/u_boot_tpl.py
new file mode 100644
index 00000000000..4d4bb925961
--- /dev/null
+++ b/tools/binman/etype/u_boot_tpl.py
@@ -0,0 +1,43 @@
+# SPDX-License-Identifier: GPL-2.0+
+# Copyright (c) 2016 Google, Inc
+# Written by Simon Glass <sjg@chromium.org>
+#
+# Entry-type module for tpl/u-boot-tpl.bin
+#
+
+import elf
+
+from entry import Entry
+from blob import Entry_blob
+
+class Entry_u_boot_tpl(Entry_blob):
+ """U-Boot TPL binary
+
+ Properties / Entry arguments:
+ - filename: Filename of u-boot-tpl.bin (default 'tpl/u-boot-tpl.bin')
+
+ This is the U-Boot TPL (Tertiary Program Loader) binary. This is a small
+ binary which loads before SPL, typically into on-chip SRAM. It is
+ responsible for locating, loading and jumping to SPL, the next-stage
+ loader. Note that SPL is not relocatable so must be loaded to the correct
+ address in SRAM, or written to run from the correct address if direct
+ flash execution is possible (e.g. on x86 devices).
+
+ SPL can access binman symbols at runtime. See:
+
+ 'Access to binman entry offsets at run time (symbols)'
+
+ in the binman README for more information.
+
+ The ELF file 'tpl/u-boot-tpl' must also be available for this to work, since
+ binman uses that to look up symbols to write into the TPL binary.
+ """
+ def __init__(self, section, etype, node):
+ Entry_blob.__init__(self, section, etype, node)
+ self.elf_fname = 'tpl/u-boot-tpl'
+
+ def GetDefaultFilename(self):
+ return 'tpl/u-boot-tpl.bin'
+
+ def WriteSymbols(self, section):
+ elf.LookupAndWriteSymbols(self.elf_fname, self, section)
diff --git a/tools/binman/etype/u_boot_tpl_dtb.py b/tools/binman/etype/u_boot_tpl_dtb.py
new file mode 100644
index 00000000000..9c4e668347e
--- /dev/null
+++ b/tools/binman/etype/u_boot_tpl_dtb.py
@@ -0,0 +1,25 @@
+# SPDX-License-Identifier: GPL-2.0+
+# Copyright (c) 2018 Google, Inc
+# Written by Simon Glass <sjg@chromium.org>
+#
+# Entry-type module for U-Boot device tree in TPL (Tertiary Program Loader)
+#
+
+from entry import Entry
+from blob import Entry_blob
+
+class Entry_u_boot_tpl_dtb(Entry_blob):
+ """U-Boot TPL device tree
+
+ Properties / Entry arguments:
+ - filename: Filename of u-boot.dtb (default 'tpl/u-boot-tpl.dtb')
+
+ This is the TPL device tree, containing configuration information for
+ TPL. TPL needs this to know what devices are present and which drivers
+ to activate.
+ """
+ def __init__(self, section, etype, node):
+ Entry_blob.__init__(self, section, etype, node)
+
+ def GetDefaultFilename(self):
+ return 'tpl/u-boot-tpl.dtb'
diff --git a/tools/binman/etype/u_boot_ucode.py b/tools/binman/etype/u_boot_ucode.py
index ea0c85cc5c7..6acf94d8cbc 100644
--- a/tools/binman/etype/u_boot_ucode.py
+++ b/tools/binman/etype/u_boot_ucode.py
@@ -12,6 +12,12 @@ import tools
class Entry_u_boot_ucode(Entry_blob):
"""U-Boot microcode block
+ Properties / Entry arguments:
+ None
+
+ The contents of this entry are filled in automatically by other entries
+ which must also be in the image.
+
U-Boot on x86 needs a single block of microcode. This is collected from
the various microcode update nodes in the device tree. It is also unable
to read the microcode from the device tree on platforms that use FSP
@@ -59,8 +65,8 @@ class Entry_u_boot_ucode(Entry_blob):
ucode_dest_entry = self.section.FindEntryType('u-boot-with-ucode-ptr')
ucode_dest_entry_spl = self.section.FindEntryType(
'u-boot-spl-with-ucode-ptr')
- if ((not ucode_dest_entry or not ucode_dest_entry.target_pos) and
- (not ucode_dest_entry_spl or not ucode_dest_entry_spl.target_pos)):
+ if ((not ucode_dest_entry or not ucode_dest_entry.target_offset) and
+ (not ucode_dest_entry_spl or not ucode_dest_entry_spl.target_offset)):
self.data = ''
return True
@@ -86,6 +92,6 @@ class Entry_u_boot_ucode(Entry_blob):
fd.write(fdt_entry.ucode_data)
self._pathname = fname
- self.ReadContents()
+ self.ReadBlobContents()
return True
diff --git a/tools/binman/etype/u_boot_with_ucode_ptr.py b/tools/binman/etype/u_boot_with_ucode_ptr.py
index 8b1e41152e3..51e7ba48f59 100644
--- a/tools/binman/etype/u_boot_with_ucode_ptr.py
+++ b/tools/binman/etype/u_boot_with_ucode_ptr.py
@@ -17,13 +17,18 @@ import tools
class Entry_u_boot_with_ucode_ptr(Entry_blob):
"""U-Boot with embedded microcode pointer
- See Entry_u_boot_ucode for full details of the 3 entries involved in this
- process.
+ Properties / Entry arguments:
+ - filename: Filename of u-boot-nodtb.dtb (default 'u-boot-nodtb.dtb')
+
+ See Entry_u_boot_ucode for full details of the three entries involved in
+ this process. This entry updates U-Boot with the offset and size of the
+ microcode, to allow early x86 boot code to find it without doing anything
+ complicated. Otherwise it is the same as the u_boot entry.
"""
def __init__(self, section, etype, node):
Entry_blob.__init__(self, section, etype, node)
self.elf_fname = 'u-boot'
- self.target_pos = None
+ self.target_offset = None
def GetDefaultFilename(self):
return 'u-boot-nodtb.bin'
@@ -33,52 +38,53 @@ class Entry_u_boot_with_ucode_ptr(Entry_blob):
fname = tools.GetInputFilename(self.elf_fname)
sym = elf.GetSymbolAddress(fname, '_dt_ucode_base_size')
if sym:
- self.target_pos = sym
+ self.target_offset = sym
elif not fdt_util.GetBool(self._node, 'optional-ucode'):
self.Raise('Cannot locate _dt_ucode_base_size symbol in u-boot')
return True
def ProcessContents(self):
# If the image does not need microcode, there is nothing to do
- if not self.target_pos:
+ if not self.target_offset:
return
- # Get the position of the microcode
+ # Get the offset of the microcode
ucode_entry = self.section.FindEntryType('u-boot-ucode')
if not ucode_entry:
self.Raise('Cannot find microcode region u-boot-ucode')
# Check the target pos is in the section. If it is not, then U-Boot is
- # being linked incorrectly, or is being placed at the wrong position
+ # being linked incorrectly, or is being placed at the wrong offset
# in the section.
#
# The section must be set up so that U-Boot is placed at the
# flash address to which it is linked. For example, if
# CONFIG_SYS_TEXT_BASE is 0xfff00000, and the ROM is 8MB, then
- # the U-Boot region must start at position 7MB in the section. In this
- # case the ROM starts at 0xff800000, so the position of the first
+ # the U-Boot region must start at offset 7MB in the section. In this
+ # case the ROM starts at 0xff800000, so the offset of the first
# entry in the section corresponds to that.
- if (self.target_pos < self.pos or
- self.target_pos >= self.pos + self.size):
+ if (self.target_offset < self.offset or
+ self.target_offset >= self.offset + self.size):
self.Raise('Microcode pointer _dt_ucode_base_size at %08x is '
'outside the section ranging from %08x to %08x' %
- (self.target_pos, self.pos, self.pos + self.size))
+ (self.target_offset, self.offset, self.offset + self.size))
# Get the microcode, either from u-boot-ucode or u-boot-dtb-with-ucode.
# If we have left the microcode in the device tree, then it will be
# in the former. If we extracted the microcode from the device tree
# and collated it in one place, it will be in the latter.
if ucode_entry.size:
- pos, size = ucode_entry.pos, ucode_entry.size
+ offset, size = ucode_entry.offset, ucode_entry.size
else:
dtb_entry = self.section.FindEntryType('u-boot-dtb-with-ucode')
if not dtb_entry or not dtb_entry.ready:
self.Raise('Cannot find microcode region u-boot-dtb-with-ucode')
- pos = dtb_entry.pos + dtb_entry.ucode_offset
+ offset = dtb_entry.offset + dtb_entry.ucode_offset
size = dtb_entry.ucode_size
- # Write the microcode position and size into the entry
- pos_and_size = struct.pack('<2L', pos, size)
- self.target_pos -= self.pos
- self.ProcessContentsUpdate(self.data[:self.target_pos] + pos_and_size +
- self.data[self.target_pos + 8:])
+ # Write the microcode offset and size into the entry
+ offset_and_size = struct.pack('<2L', offset, size)
+ self.target_offset -= self.offset
+ self.ProcessContentsUpdate(self.data[:self.target_offset] +
+ offset_and_size +
+ self.data[self.target_offset + 8:])
diff --git a/tools/binman/etype/vblock.py b/tools/binman/etype/vblock.py
new file mode 100644
index 00000000000..595af5456d1
--- /dev/null
+++ b/tools/binman/etype/vblock.py
@@ -0,0 +1,74 @@
+# SPDX-License-Identifier: GPL-2.0+
+# Copyright (c) 2018 Google, Inc
+# Written by Simon Glass <sjg@chromium.org>
+#
+
+# Support for a Chromium OS verified boot block, used to sign a read-write
+# section of the image.
+
+from collections import OrderedDict
+import os
+
+from entry import Entry, EntryArg
+
+import fdt_util
+import tools
+
+class Entry_vblock(Entry):
+ """An entry which contains a Chromium OS verified boot block
+
+ Properties / Entry arguments:
+ - keydir: Directory containing the public keys to use
+ - keyblock: Name of the key file to use (inside keydir)
+ - signprivate: Name of provide key file to use (inside keydir)
+ - version: Version number of the vblock (typically 1)
+ - kernelkey: Name of the kernel key to use (inside keydir)
+ - preamble-flags: Value of the vboot preamble flags (typically 0)
+
+ Chromium OS signs the read-write firmware and kernel, writing the signature
+ in this block. This allows U-Boot to verify that the next firmware stage
+ and kernel are genuine.
+ """
+ def __init__(self, section, etype, node):
+ Entry.__init__(self, section, etype, node)
+ self.content = fdt_util.GetPhandleList(self._node, 'content')
+ if not self.content:
+ self.Raise("Vblock must have a 'content' property")
+ (self.keydir, self.keyblock, self.signprivate, self.version,
+ self.kernelkey, self.preamble_flags) = self.GetEntryArgsOrProps([
+ EntryArg('keydir', str),
+ EntryArg('keyblock', str),
+ EntryArg('signprivate', str),
+ EntryArg('version', int),
+ EntryArg('kernelkey', str),
+ EntryArg('preamble-flags', int)])
+
+ def ObtainContents(self):
+ # Join up the data files to be signed
+ input_data = ''
+ for entry_phandle in self.content:
+ data = self.section.GetContentsByPhandle(entry_phandle, self)
+ if data is None:
+ # Data not available yet
+ return False
+ input_data += data
+
+ output_fname = tools.GetOutputFilename('vblock.%s' % self.name)
+ input_fname = tools.GetOutputFilename('input.%s' % self.name)
+ tools.WriteFile(input_fname, input_data)
+ prefix = self.keydir + '/'
+ args = [
+ 'vbutil_firmware',
+ '--vblock', output_fname,
+ '--keyblock', prefix + self.keyblock,
+ '--signprivate', prefix + self.signprivate,
+ '--version', '%d' % self.version,
+ '--fv', input_fname,
+ '--kernelkey', prefix + self.kernelkey,
+ '--flags', '%d' % self.preamble_flags,
+ ]
+ #out.Notice("Sign '%s' into %s" % (', '.join(self.value), self.label))
+ stdout = tools.Run('futility', *args)
+ #out.Debug(stdout)
+ self.SetContents(tools.ReadFile(output_fname))
+ return True
diff --git a/tools/binman/etype/x86_start16.py b/tools/binman/etype/x86_start16.py
index 23d27f07040..7d32ecd321b 100644
--- a/tools/binman/etype/x86_start16.py
+++ b/tools/binman/etype/x86_start16.py
@@ -9,6 +9,20 @@ from entry import Entry
from blob import Entry_blob
class Entry_x86_start16(Entry_blob):
+ """x86 16-bit start-up code for U-Boot
+
+ Properties / Entry arguments:
+ - filename: Filename of u-boot-x86-16bit.bin (default
+ 'u-boot-x86-16bit.bin')
+
+ x86 CPUs start up in 16-bit mode, even if they are 32-bit CPUs. This code
+ must be placed at a particular address. This entry holds that code. It is
+ typically placed at offset CONFIG_SYS_X86_START16. The code is responsible
+ for changing to 32-bit mode and jumping to U-Boot's entry point, which
+ requires 32-bit mode (for 32-bit U-Boot).
+
+ For 64-bit U-Boot, the 'x86_start16_spl' entry type is used instead.
+ """
def __init__(self, section, etype, node):
Entry_blob.__init__(self, section, etype, node)
diff --git a/tools/binman/etype/x86_start16_spl.py b/tools/binman/etype/x86_start16_spl.py
index 176420ba88c..d85909e7ae8 100644
--- a/tools/binman/etype/x86_start16_spl.py
+++ b/tools/binman/etype/x86_start16_spl.py
@@ -9,6 +9,20 @@ from entry import Entry
from blob import Entry_blob
class Entry_x86_start16_spl(Entry_blob):
+ """x86 16-bit start-up code for SPL
+
+ Properties / Entry arguments:
+ - filename: Filename of spl/u-boot-x86-16bit-spl.bin (default
+ 'spl/u-boot-x86-16bit-spl.bin')
+
+ x86 CPUs start up in 16-bit mode, even if they are 64-bit CPUs. This code
+ must be placed at a particular address. This entry holds that code. It is
+ typically placed at offset CONFIG_SYS_X86_START16. The code is responsible
+ for changing to 32-bit mode and starting SPL, which in turn changes to
+ 64-bit mode and jumps to U-Boot (for 64-bit U-Boot).
+
+ For 32-bit U-Boot, the 'x86_start16' entry type is used instead.
+ """
def __init__(self, section, etype, node):
Entry_blob.__init__(self, section, etype, node)
diff --git a/tools/binman/fmap_util.py b/tools/binman/fmap_util.py
new file mode 100644
index 00000000000..7d520e33919
--- /dev/null
+++ b/tools/binman/fmap_util.py
@@ -0,0 +1,109 @@
+# SPDX-License-Identifier: GPL-2.0+
+# Copyright (c) 2018 Google, Inc
+# Written by Simon Glass <sjg@chromium.org>
+#
+# Support for flashrom's FMAP format. This supports a header followed by a
+# number of 'areas', describing regions of a firmware storage device,
+# generally SPI flash.
+
+import collections
+import struct
+
+# constants imported from lib/fmap.h
+FMAP_SIGNATURE = '__FMAP__'
+FMAP_VER_MAJOR = 1
+FMAP_VER_MINOR = 0
+FMAP_STRLEN = 32
+
+FMAP_AREA_STATIC = 1 << 0
+FMAP_AREA_COMPRESSED = 1 << 1
+FMAP_AREA_RO = 1 << 2
+
+FMAP_HEADER_LEN = 56
+FMAP_AREA_LEN = 42
+
+FMAP_HEADER_FORMAT = '<8sBBQI%dsH'% (FMAP_STRLEN)
+FMAP_AREA_FORMAT = '<II%dsH' % (FMAP_STRLEN)
+
+FMAP_HEADER_NAMES = (
+ 'signature',
+ 'ver_major',
+ 'ver_minor',
+ 'base',
+ 'image_size',
+ 'name',
+ 'nareas',
+)
+
+FMAP_AREA_NAMES = (
+ 'offset',
+ 'size',
+ 'name',
+ 'flags',
+)
+
+# These are the two data structures supported by flashrom, a header (which
+# appears once at the start) and an area (which is repeated until the end of
+# the list of areas)
+FmapHeader = collections.namedtuple('FmapHeader', FMAP_HEADER_NAMES)
+FmapArea = collections.namedtuple('FmapArea', FMAP_AREA_NAMES)
+
+
+def ConvertName(field_names, fields):
+ """Convert a name to something flashrom likes
+
+ Flashrom requires upper case, underscores instead of hyphens. We remove any
+ null characters as well. This updates the 'name' value in fields.
+
+ Args:
+ field_names: List of field names for this struct
+ fields: Dict:
+ key: Field name
+ value: value of that field (string for the ones we support)
+ """
+ name_index = field_names.index('name')
+ fields[name_index] = fields[name_index].replace('\0', '').replace('-', '_').upper()
+
+def DecodeFmap(data):
+ """Decode a flashmap into a header and list of areas
+
+ Args:
+ data: Data block containing the FMAP
+
+ Returns:
+ Tuple:
+ header: FmapHeader object
+ List of FmapArea objects
+ """
+ fields = list(struct.unpack(FMAP_HEADER_FORMAT, data[:FMAP_HEADER_LEN]))
+ ConvertName(FMAP_HEADER_NAMES, fields)
+ header = FmapHeader(*fields)
+ areas = []
+ data = data[FMAP_HEADER_LEN:]
+ for area in range(header.nareas):
+ fields = list(struct.unpack(FMAP_AREA_FORMAT, data[:FMAP_AREA_LEN]))
+ ConvertName(FMAP_AREA_NAMES, fields)
+ areas.append(FmapArea(*fields))
+ data = data[FMAP_AREA_LEN:]
+ return header, areas
+
+def EncodeFmap(image_size, name, areas):
+ """Create a new FMAP from a list of areas
+
+ Args:
+ image_size: Size of image, to put in the header
+ name: Name of image, to put in the header
+ areas: List of FmapArea objects
+
+ Returns:
+ String containing the FMAP created
+ """
+ def _FormatBlob(fmt, names, obj):
+ params = [getattr(obj, name) for name in names]
+ return struct.pack(fmt, *params)
+
+ values = FmapHeader(FMAP_SIGNATURE, 1, 0, 0, image_size, name, len(areas))
+ blob = _FormatBlob(FMAP_HEADER_FORMAT, FMAP_HEADER_NAMES, values)
+ for area in areas:
+ blob += _FormatBlob(FMAP_AREA_FORMAT, FMAP_AREA_NAMES, area)
+ return blob
diff --git a/tools/binman/ftest.py b/tools/binman/ftest.py
index 12164a85b4d..a8456c26157 100644
--- a/tools/binman/ftest.py
+++ b/tools/binman/ftest.py
@@ -21,6 +21,8 @@ import control
import elf
import fdt
import fdt_util
+import fmap_util
+import test_util
import tools
import tout
@@ -28,11 +30,13 @@ import tout
U_BOOT_DATA = '1234'
U_BOOT_IMG_DATA = 'img'
U_BOOT_SPL_DATA = '56780123456789abcde'
+U_BOOT_TPL_DATA = 'tpl'
BLOB_DATA = '89'
ME_DATA = '0abcd'
VGA_DATA = 'vga'
U_BOOT_DTB_DATA = 'udtb'
U_BOOT_SPL_DTB_DATA = 'spldtb'
+U_BOOT_TPL_DTB_DATA = 'tpldtb'
X86_START16_DATA = 'start16'
X86_START16_SPL_DATA = 'start16spl'
U_BOOT_NODTB_DATA = 'nodtb with microcode pointer somewhere in here'
@@ -41,6 +45,14 @@ FSP_DATA = 'fsp'
CMC_DATA = 'cmc'
VBT_DATA = 'vbt'
MRC_DATA = 'mrc'
+TEXT_DATA = 'text'
+TEXT_DATA2 = 'text2'
+TEXT_DATA3 = 'text3'
+CROS_EC_RW_DATA = 'ecrw'
+GBB_DATA = 'gbbd'
+BMPBLK_DATA = 'bmp'
+VBLOCK_DATA = 'vblk'
+
class TestFunctional(unittest.TestCase):
"""Functional tests for binman
@@ -72,11 +84,11 @@ class TestFunctional(unittest.TestCase):
TestFunctional._MakeInputFile('u-boot.bin', U_BOOT_DATA)
TestFunctional._MakeInputFile('u-boot.img', U_BOOT_IMG_DATA)
TestFunctional._MakeInputFile('spl/u-boot-spl.bin', U_BOOT_SPL_DATA)
+ TestFunctional._MakeInputFile('tpl/u-boot-tpl.bin', U_BOOT_TPL_DATA)
TestFunctional._MakeInputFile('blobfile', BLOB_DATA)
TestFunctional._MakeInputFile('me.bin', ME_DATA)
TestFunctional._MakeInputFile('vga.bin', VGA_DATA)
- TestFunctional._MakeInputFile('u-boot.dtb', U_BOOT_DTB_DATA)
- TestFunctional._MakeInputFile('spl/u-boot-spl.dtb', U_BOOT_SPL_DTB_DATA)
+ self._ResetDtbs()
TestFunctional._MakeInputFile('u-boot-x86-16bit.bin', X86_START16_DATA)
TestFunctional._MakeInputFile('spl/u-boot-x86-16bit-spl.bin',
X86_START16_SPL_DATA)
@@ -87,6 +99,9 @@ class TestFunctional(unittest.TestCase):
TestFunctional._MakeInputFile('cmc.bin', CMC_DATA)
TestFunctional._MakeInputFile('vbt.bin', VBT_DATA)
TestFunctional._MakeInputFile('mrc.bin', MRC_DATA)
+ TestFunctional._MakeInputFile('ecrw.bin', CROS_EC_RW_DATA)
+ TestFunctional._MakeInputDir('devkeys')
+ TestFunctional._MakeInputFile('bmpblk.bin', BMPBLK_DATA)
self._output_setup = False
# ELF file with a '_dt_ucode_base_size' symbol
@@ -113,6 +128,12 @@ class TestFunctional(unittest.TestCase):
"""Remove the temporary output directory"""
tools._FinaliseForTest()
+ @classmethod
+ def _ResetDtbs(self):
+ TestFunctional._MakeInputFile('u-boot.dtb', U_BOOT_DTB_DATA)
+ TestFunctional._MakeInputFile('spl/u-boot-spl.dtb', U_BOOT_SPL_DTB_DATA)
+ TestFunctional._MakeInputFile('tpl/u-boot-tpl.dtb', U_BOOT_TPL_DTB_DATA)
+
def _RunBinman(self, *args, **kwargs):
"""Run binman using the command line
@@ -146,14 +167,15 @@ class TestFunctional(unittest.TestCase):
# options.verbosity = tout.DEBUG
return control.Binman(options, args)
- def _DoTestFile(self, fname, debug=False, map=False, update_dtb=False):
+ def _DoTestFile(self, fname, debug=False, map=False, update_dtb=False,
+ entry_args=None):
"""Run binman with a given test file
Args:
fname: Device-tree source filename to use (e.g. 05_simple.dts)
debug: True to enable debugging output
map: True to output map files for the images
- update_dtb: Update the position and size of each entry in the device
+ update_dtb: Update the offset and size of each entry in the device
tree before packing it into the image
"""
args = ['-p', '-I', self._indir, '-d', self.TestFile(fname)]
@@ -163,6 +185,9 @@ class TestFunctional(unittest.TestCase):
args.append('-m')
if update_dtb:
args.append('-up')
+ if entry_args:
+ for arg, value in entry_args.iteritems():
+ args.append('-a%s=%s' % (arg, value))
return self._DoBinman(*args)
def _SetupDtb(self, fname, outfile='u-boot.dtb'):
@@ -188,7 +213,7 @@ class TestFunctional(unittest.TestCase):
return data
def _DoReadFileDtb(self, fname, use_real_dtb=False, map=False,
- update_dtb=False):
+ update_dtb=False, entry_args=None):
"""Run binman and return the resulting image
This runs binman with a given test file and then reads the resulting
@@ -204,7 +229,7 @@ class TestFunctional(unittest.TestCase):
test contents (the U_BOOT_DTB_DATA string) can be used.
But in some test we need the real contents.
map: True to output map files for the images
- update_dtb: Update the position and size of each entry in the device
+ update_dtb: Update the offset and size of each entry in the device
tree before packing it into the image
Returns:
@@ -212,6 +237,7 @@ class TestFunctional(unittest.TestCase):
Resulting image contents
Device tree contents
Map data showing contents of image (or None if none)
+ Output device tree binary filename ('u-boot.dtb' path)
"""
dtb_data = None
# Use the compiled test file as the u-boot-dtb input
@@ -219,7 +245,8 @@ class TestFunctional(unittest.TestCase):
dtb_data = self._SetupDtb(fname)
try:
- retcode = self._DoTestFile(fname, map=map, update_dtb=update_dtb)
+ retcode = self._DoTestFile(fname, map=map, update_dtb=update_dtb,
+ entry_args=entry_args)
self.assertEqual(0, retcode)
out_dtb_fname = control.GetFdtPath('u-boot.dtb')
@@ -238,7 +265,7 @@ class TestFunctional(unittest.TestCase):
finally:
# Put the test file back
if use_real_dtb:
- TestFunctional._MakeInputFile('u-boot.dtb', U_BOOT_DTB_DATA)
+ self._ResetDtbs()
def _DoReadFile(self, fname, use_real_dtb=False):
"""Helper function which discards the device-tree binary
@@ -249,6 +276,9 @@ class TestFunctional(unittest.TestCase):
the u-boot-dtb entry. Normally this is not needed and the
test contents (the U_BOOT_DTB_DATA string) can be used.
But in some test we need the real contents.
+
+ Returns:
+ Resulting image contents
"""
return self._DoReadFileDtb(fname, use_real_dtb)[0]
@@ -257,7 +287,7 @@ class TestFunctional(unittest.TestCase):
"""Create a new test input file, creating directories as needed
Args:
- fname: Filenaem to create
+ fname: Filename to create
contents: File contents to write in to the file
Returns:
Full pathname of file created
@@ -271,6 +301,21 @@ class TestFunctional(unittest.TestCase):
return pathname
@classmethod
+ def _MakeInputDir(self, dirname):
+ """Create a new test input directory, creating directories as needed
+
+ Args:
+ dirname: Directory name to create
+
+ Returns:
+ Full pathname of directory created
+ """
+ pathname = os.path.join(self._indir, dirname)
+ if not os.path.exists(pathname):
+ os.makedirs(pathname)
+ return pathname
+
+ @classmethod
def TestFile(self, fname):
return os.path.join(self._binman_dir, 'test', fname)
@@ -292,10 +337,10 @@ class TestFunctional(unittest.TestCase):
Args:
entries: List of entries to check
"""
- pos = 0
+ offset = 0
for entry in entries.values():
- self.assertEqual(pos, entry.pos)
- pos += entry.size
+ self.assertEqual(offset, entry.offset)
+ offset += entry.size
def GetFdtLen(self, dtb):
"""Get the totalsize field from a device-tree binary
@@ -308,23 +353,19 @@ class TestFunctional(unittest.TestCase):
"""
return struct.unpack('>L', dtb[4:8])[0]
- def _GetPropTree(self, dtb_data, node_names):
+ def _GetPropTree(self, dtb, prop_names):
def AddNode(node, path):
if node.name != '/':
path += '/' + node.name
- #print 'path', path
for subnode in node.subnodes:
for prop in subnode.props.values():
- if prop.name in node_names:
+ if prop.name in prop_names:
prop_path = path + '/' + subnode.name + ':' + prop.name
tree[prop_path[len('/binman/'):]] = fdt_util.fdt32_to_cpu(
prop.value)
- #print ' ', prop.name
AddNode(subnode, path)
tree = {}
- dtb = fdt.Fdt(dtb_data)
- dtb.Scan()
AddNode(dtb.GetRoot(), '')
return tree
@@ -409,7 +450,6 @@ class TestFunctional(unittest.TestCase):
with self.assertRaises(Exception) as e:
result = self._RunBinman('-d',
self.TestFile('04_invalid_entry.dts'))
- #print e.exception
self.assertIn("Unknown entry type 'not-a-valid-type' in node "
"'/binman/not-a-valid-type'", str(e.exception))
@@ -467,32 +507,32 @@ class TestFunctional(unittest.TestCase):
# First u-boot
self.assertIn('u-boot', entries)
entry = entries['u-boot']
- self.assertEqual(0, entry.pos)
+ self.assertEqual(0, entry.offset)
self.assertEqual(len(U_BOOT_DATA), entry.size)
# Second u-boot, aligned to 16-byte boundary
self.assertIn('u-boot-align', entries)
entry = entries['u-boot-align']
- self.assertEqual(16, entry.pos)
+ self.assertEqual(16, entry.offset)
self.assertEqual(len(U_BOOT_DATA), entry.size)
# Third u-boot, size 23 bytes
self.assertIn('u-boot-size', entries)
entry = entries['u-boot-size']
- self.assertEqual(20, entry.pos)
+ self.assertEqual(20, entry.offset)
self.assertEqual(len(U_BOOT_DATA), entry.contents_size)
self.assertEqual(23, entry.size)
# Fourth u-boot, placed immediate after the above
self.assertIn('u-boot-next', entries)
entry = entries['u-boot-next']
- self.assertEqual(43, entry.pos)
+ self.assertEqual(43, entry.offset)
self.assertEqual(len(U_BOOT_DATA), entry.size)
- # Fifth u-boot, placed at a fixed position
+ # Fifth u-boot, placed at a fixed offset
self.assertIn('u-boot-fixed', entries)
entry = entries['u-boot-fixed']
- self.assertEqual(61, entry.pos)
+ self.assertEqual(61, entry.offset)
self.assertEqual(len(U_BOOT_DATA), entry.size)
self.assertEqual(65, image._size)
@@ -510,32 +550,32 @@ class TestFunctional(unittest.TestCase):
# First u-boot with padding before and after
self.assertIn('u-boot', entries)
entry = entries['u-boot']
- self.assertEqual(0, entry.pos)
+ self.assertEqual(0, entry.offset)
self.assertEqual(3, entry.pad_before)
self.assertEqual(3 + 5 + len(U_BOOT_DATA), entry.size)
# Second u-boot has an aligned size, but it has no effect
self.assertIn('u-boot-align-size-nop', entries)
entry = entries['u-boot-align-size-nop']
- self.assertEqual(12, entry.pos)
+ self.assertEqual(12, entry.offset)
self.assertEqual(4, entry.size)
# Third u-boot has an aligned size too
self.assertIn('u-boot-align-size', entries)
entry = entries['u-boot-align-size']
- self.assertEqual(16, entry.pos)
+ self.assertEqual(16, entry.offset)
self.assertEqual(32, entry.size)
# Fourth u-boot has an aligned end
self.assertIn('u-boot-align-end', entries)
entry = entries['u-boot-align-end']
- self.assertEqual(48, entry.pos)
+ self.assertEqual(48, entry.offset)
self.assertEqual(16, entry.size)
# Fifth u-boot immediately afterwards
self.assertIn('u-boot-align-both', entries)
entry = entries['u-boot-align-both']
- self.assertEqual(64, entry.pos)
+ self.assertEqual(64, entry.offset)
self.assertEqual(64, entry.size)
self.CheckNoGaps(entries)
@@ -556,10 +596,10 @@ class TestFunctional(unittest.TestCase):
"power of two", str(e.exception))
def testPackInvalidAlign(self):
- """Test detection of an position that does not match its alignment"""
+ """Test detection of an offset that does not match its alignment"""
with self.assertRaises(ValueError) as e:
self._DoTestFile('12_pack_inv_align.dts')
- self.assertIn("Node '/binman/u-boot': Position 0x5 (5) does not match "
+ self.assertIn("Node '/binman/u-boot': Offset 0x5 (5) does not match "
"align 0x4 (4)", str(e.exception))
def testPackInvalidSizeAlign(self):
@@ -573,7 +613,7 @@ class TestFunctional(unittest.TestCase):
"""Test that overlapping regions are detected"""
with self.assertRaises(ValueError) as e:
self._DoTestFile('14_pack_overlap.dts')
- self.assertIn("Node '/binman/u-boot-align': Position 0x3 (3) overlaps "
+ self.assertIn("Node '/binman/u-boot-align': Offset 0x3 (3) overlaps "
"with previous entry '/binman/u-boot' ending at 0x4 (4)",
str(e.exception))
@@ -651,11 +691,11 @@ class TestFunctional(unittest.TestCase):
self.assertEqual(chr(0) * 1 + U_BOOT_SPL_DATA + chr(0) * 2 +
U_BOOT_DATA, data)
- def testPackZeroPosition(self):
- """Test that an entry at position 0 is not given a new position"""
+ def testPackZeroOffset(self):
+ """Test that an entry at offset 0 is not given a new offset"""
with self.assertRaises(ValueError) as e:
self._DoTestFile('25_pack_zero_size.dts')
- self.assertIn("Node '/binman/u-boot-spl': Position 0x0 (0) overlaps "
+ self.assertIn("Node '/binman/u-boot-spl': Offset 0x0 (0) overlaps "
"with previous entry '/binman/u-boot' ending at 0x4 (4)",
str(e.exception))
@@ -672,10 +712,10 @@ class TestFunctional(unittest.TestCase):
"using end-at-4gb", str(e.exception))
def testPackX86RomOutside(self):
- """Test that the end-at-4gb property checks for position boundaries"""
+ """Test that the end-at-4gb property checks for offset boundaries"""
with self.assertRaises(ValueError) as e:
self._DoTestFile('28_pack_4gb_outside.dts')
- self.assertIn("Node '/binman/u-boot': Position 0x0 (0) is outside "
+ self.assertIn("Node '/binman/u-boot': Offset 0x0 (0) is outside "
"the section starting at 0xffffffe0 (4294967264)",
str(e.exception))
@@ -697,9 +737,9 @@ class TestFunctional(unittest.TestCase):
"""Test that the Intel requires a descriptor entry"""
with self.assertRaises(ValueError) as e:
self._DoTestFile('30_x86-rom-me-no-desc.dts')
- self.assertIn("Node '/binman/intel-me': No position set with "
- "pos-unset: should another entry provide this correct "
- "position?", str(e.exception))
+ self.assertIn("Node '/binman/intel-me': No offset set with "
+ "offset-unset: should another entry provide this correct "
+ "offset?", str(e.exception))
def testPackX86RomMe(self):
"""Test that an x86 ROM with an ME region can be created"""
@@ -728,7 +768,7 @@ class TestFunctional(unittest.TestCase):
Returns:
Tuple:
Contents of first region (U-Boot or SPL)
- Position and size components of microcode pointer, as inserted
+ Offset and size components of microcode pointer, as inserted
in the above (two 4-byte words)
"""
data = self._DoReadFile(dts_fname, True)
@@ -761,7 +801,7 @@ class TestFunctional(unittest.TestCase):
self.assertEqual(ucode_data, ucode_content[:len(ucode_data)])
# Check that the microcode pointer was inserted. It should match the
- # expected position and size
+ # expected offset and size
pos_and_size = struct.pack('<2L', 0xfffffe00 + ucode_pos,
len(ucode_data))
u_boot = data[:len(nodtb_data)]
@@ -806,7 +846,7 @@ class TestFunctional(unittest.TestCase):
ucode_pos = second.find(ucode_data) + len(U_BOOT_NODTB_DATA)
# Check that the microcode pointer was inserted. It should match the
- # expected position and size
+ # expected offset and size
pos_and_size = struct.pack('<2L', 0xfffffe00 + ucode_pos,
len(ucode_data))
first = data[:len(U_BOOT_NODTB_DATA)]
@@ -890,7 +930,7 @@ class TestFunctional(unittest.TestCase):
"""Test that microcode must be placed within the image"""
with self.assertRaises(ValueError) as e:
self._DoReadFile('41_unknown_pos_size.dts', True)
- self.assertIn("Section '/binman': Unable to set pos/size for unknown "
+ self.assertIn("Section '/binman': Unable to set offset/size for unknown "
"entry 'invalid-entry'", str(e.exception))
def testPackFsp(self):
@@ -984,7 +1024,7 @@ class TestFunctional(unittest.TestCase):
elf_fname = self.TestFile('u_boot_binman_syms')
syms = elf.GetSymbols(elf_fname, ['binman', 'image'])
addr = elf.GetSymbolAddress(elf_fname, '__image_copy_start')
- self.assertEqual(syms['_binman_u_boot_spl_prop_pos'].address, addr)
+ self.assertEqual(syms['_binman_u_boot_spl_prop_offset'].address, addr)
with open(self.TestFile('u_boot_binman_syms')) as fd:
TestFunctional._MakeInputFile('spl/u-boot-spl', fd.read())
@@ -1003,27 +1043,32 @@ class TestFunctional(unittest.TestCase):
def testSections(self):
"""Basic test of sections"""
data = self._DoReadFile('55_sections.dts')
- expected = U_BOOT_DATA + '!' * 12 + U_BOOT_DATA + 'a' * 12 + '&' * 8
+ expected = (U_BOOT_DATA + '!' * 12 + U_BOOT_DATA + 'a' * 12 +
+ U_BOOT_DATA + '&' * 4)
self.assertEqual(expected, data)
def testMap(self):
"""Tests outputting a map of the images"""
_, _, map_data, _ = self._DoReadFileDtb('55_sections.dts', map=True)
- self.assertEqual('''Position Size Name
-00000000 00000010 section@0
- 00000000 00000004 u-boot
-00000010 00000010 section@1
- 00000000 00000004 u-boot
+ self.assertEqual('''ImagePos Offset Size Name
+00000000 00000000 00000028 main-section
+00000000 00000000 00000010 section@0
+00000000 00000000 00000004 u-boot
+00000010 00000010 00000010 section@1
+00000010 00000000 00000004 u-boot
+00000020 00000020 00000004 section@2
+00000020 00000000 00000004 u-boot
''', map_data)
def testNamePrefix(self):
"""Tests that name prefixes are used"""
_, _, map_data, _ = self._DoReadFileDtb('56_name_prefix.dts', map=True)
- self.assertEqual('''Position Size Name
-00000000 00000010 section@0
- 00000000 00000004 ro-u-boot
-00000010 00000010 section@1
- 00000000 00000004 rw-u-boot
+ self.assertEqual('''ImagePos Offset Size Name
+00000000 00000000 00000028 main-section
+00000000 00000000 00000010 section@0
+00000000 00000000 00000004 ro-u-boot
+00000010 00000010 00000010 section@1
+00000010 00000000 00000004 rw-u-boot
''', map_data)
def testUnknownContents(self):
@@ -1042,25 +1087,31 @@ class TestFunctional(unittest.TestCase):
'2 to 1', str(e.exception))
def testUpdateFdt(self):
- """Test that we can update the device tree with pos/size info"""
+ """Test that we can update the device tree with offset/size info"""
_, _, _, out_dtb_fname = self._DoReadFileDtb('60_fdt_update.dts',
update_dtb=True)
- props = self._GetPropTree(out_dtb_fname, ['pos', 'size'])
- with open('/tmp/x.dtb', 'wb') as outf:
- with open(out_dtb_fname) as inf:
- outf.write(inf.read())
+ dtb = fdt.Fdt(out_dtb_fname)
+ dtb.Scan()
+ props = self._GetPropTree(dtb, ['offset', 'size', 'image-pos'])
self.assertEqual({
- '_testing:pos': 32,
+ 'image-pos': 0,
+ 'offset': 0,
+ '_testing:offset': 32,
'_testing:size': 1,
- 'section@0/u-boot:pos': 0,
+ '_testing:image-pos': 32,
+ 'section@0/u-boot:offset': 0,
'section@0/u-boot:size': len(U_BOOT_DATA),
- 'section@0:pos': 0,
+ 'section@0/u-boot:image-pos': 0,
+ 'section@0:offset': 0,
'section@0:size': 16,
+ 'section@0:image-pos': 0,
- 'section@1/u-boot:pos': 0,
+ 'section@1/u-boot:offset': 0,
'section@1/u-boot:size': len(U_BOOT_DATA),
- 'section@1:pos': 16,
+ 'section@1/u-boot:image-pos': 16,
+ 'section@1:offset': 16,
'section@1:size': 16,
+ 'section@1:image-pos': 16,
'size': 40
}, props)
@@ -1071,5 +1122,248 @@ class TestFunctional(unittest.TestCase):
self.assertIn('Could not complete processing of Fdt: remaining '
'[<_testing.Entry__testing', str(e.exception))
+ def testEntryArgs(self):
+ """Test passing arguments to entries from the command line"""
+ entry_args = {
+ 'test-str-arg': 'test1',
+ 'test-int-arg': '456',
+ }
+ self._DoReadFileDtb('62_entry_args.dts', entry_args=entry_args)
+ self.assertIn('image', control.images)
+ entry = control.images['image'].GetEntries()['_testing']
+ self.assertEqual('test0', entry.test_str_fdt)
+ self.assertEqual('test1', entry.test_str_arg)
+ self.assertEqual(123, entry.test_int_fdt)
+ self.assertEqual(456, entry.test_int_arg)
+
+ def testEntryArgsMissing(self):
+ """Test missing arguments and properties"""
+ entry_args = {
+ 'test-int-arg': '456',
+ }
+ self._DoReadFileDtb('63_entry_args_missing.dts', entry_args=entry_args)
+ entry = control.images['image'].GetEntries()['_testing']
+ self.assertEqual('test0', entry.test_str_fdt)
+ self.assertEqual(None, entry.test_str_arg)
+ self.assertEqual(None, entry.test_int_fdt)
+ self.assertEqual(456, entry.test_int_arg)
+
+ def testEntryArgsRequired(self):
+ """Test missing arguments and properties"""
+ entry_args = {
+ 'test-int-arg': '456',
+ }
+ with self.assertRaises(ValueError) as e:
+ self._DoReadFileDtb('64_entry_args_required.dts')
+ self.assertIn("Node '/binman/_testing': Missing required "
+ 'properties/entry args: test-str-arg, test-int-fdt, test-int-arg',
+ str(e.exception))
+
+ def testEntryArgsInvalidFormat(self):
+ """Test that an invalid entry-argument format is detected"""
+ args = ['-d', self.TestFile('64_entry_args_required.dts'), '-ano-value']
+ with self.assertRaises(ValueError) as e:
+ self._DoBinman(*args)
+ self.assertIn("Invalid entry arguemnt 'no-value'", str(e.exception))
+
+ def testEntryArgsInvalidInteger(self):
+ """Test that an invalid entry-argument integer is detected"""
+ entry_args = {
+ 'test-int-arg': 'abc',
+ }
+ with self.assertRaises(ValueError) as e:
+ self._DoReadFileDtb('62_entry_args.dts', entry_args=entry_args)
+ self.assertIn("Node '/binman/_testing': Cannot convert entry arg "
+ "'test-int-arg' (value 'abc') to integer",
+ str(e.exception))
+
+ def testEntryArgsInvalidDatatype(self):
+ """Test that an invalid entry-argument datatype is detected
+
+ This test could be written in entry_test.py except that it needs
+ access to control.entry_args, which seems more than that module should
+ be able to see.
+ """
+ entry_args = {
+ 'test-bad-datatype-arg': '12',
+ }
+ with self.assertRaises(ValueError) as e:
+ self._DoReadFileDtb('65_entry_args_unknown_datatype.dts',
+ entry_args=entry_args)
+ self.assertIn('GetArg() internal error: Unknown data type ',
+ str(e.exception))
+
+ def testText(self):
+ """Test for a text entry type"""
+ entry_args = {
+ 'test-id': TEXT_DATA,
+ 'test-id2': TEXT_DATA2,
+ 'test-id3': TEXT_DATA3,
+ }
+ data, _, _, _ = self._DoReadFileDtb('66_text.dts',
+ entry_args=entry_args)
+ expected = (TEXT_DATA + chr(0) * (8 - len(TEXT_DATA)) + TEXT_DATA2 +
+ TEXT_DATA3 + 'some text')
+ self.assertEqual(expected, data)
+
+ def testEntryDocs(self):
+ """Test for creation of entry documentation"""
+ with test_util.capture_sys_output() as (stdout, stderr):
+ control.WriteEntryDocs(binman.GetEntryModules())
+ self.assertTrue(len(stdout.getvalue()) > 0)
+
+ def testEntryDocsMissing(self):
+ """Test handling of missing entry documentation"""
+ with self.assertRaises(ValueError) as e:
+ with test_util.capture_sys_output() as (stdout, stderr):
+ control.WriteEntryDocs(binman.GetEntryModules(), 'u_boot')
+ self.assertIn('Documentation is missing for modules: u_boot',
+ str(e.exception))
+
+ def testFmap(self):
+ """Basic test of generation of a flashrom fmap"""
+ data = self._DoReadFile('67_fmap.dts')
+ fhdr, fentries = fmap_util.DecodeFmap(data[32:])
+ expected = U_BOOT_DATA + '!' * 12 + U_BOOT_DATA + 'a' * 12
+ self.assertEqual(expected, data[:32])
+ self.assertEqual('__FMAP__', fhdr.signature)
+ self.assertEqual(1, fhdr.ver_major)
+ self.assertEqual(0, fhdr.ver_minor)
+ self.assertEqual(0, fhdr.base)
+ self.assertEqual(16 + 16 +
+ fmap_util.FMAP_HEADER_LEN +
+ fmap_util.FMAP_AREA_LEN * 3, fhdr.image_size)
+ self.assertEqual('FMAP', fhdr.name)
+ self.assertEqual(3, fhdr.nareas)
+ for fentry in fentries:
+ self.assertEqual(0, fentry.flags)
+
+ self.assertEqual(0, fentries[0].offset)
+ self.assertEqual(4, fentries[0].size)
+ self.assertEqual('RO_U_BOOT', fentries[0].name)
+
+ self.assertEqual(16, fentries[1].offset)
+ self.assertEqual(4, fentries[1].size)
+ self.assertEqual('RW_U_BOOT', fentries[1].name)
+
+ self.assertEqual(32, fentries[2].offset)
+ self.assertEqual(fmap_util.FMAP_HEADER_LEN +
+ fmap_util.FMAP_AREA_LEN * 3, fentries[2].size)
+ self.assertEqual('FMAP', fentries[2].name)
+
+ def testBlobNamedByArg(self):
+ """Test we can add a blob with the filename coming from an entry arg"""
+ entry_args = {
+ 'cros-ec-rw-path': 'ecrw.bin',
+ }
+ data, _, _, _ = self._DoReadFileDtb('68_blob_named_by_arg.dts',
+ entry_args=entry_args)
+
+ def testFill(self):
+ """Test for an fill entry type"""
+ data = self._DoReadFile('69_fill.dts')
+ expected = 8 * chr(0xff) + 8 * chr(0)
+ self.assertEqual(expected, data)
+
+ def testFillNoSize(self):
+ """Test for an fill entry type with no size"""
+ with self.assertRaises(ValueError) as e:
+ self._DoReadFile('70_fill_no_size.dts')
+ self.assertIn("'fill' entry must have a size property",
+ str(e.exception))
+
+ def _HandleGbbCommand(self, pipe_list):
+ """Fake calls to the futility utility"""
+ if pipe_list[0][0] == 'futility':
+ fname = pipe_list[0][-1]
+ # Append our GBB data to the file, which will happen every time the
+ # futility command is called.
+ with open(fname, 'a') as fd:
+ fd.write(GBB_DATA)
+ return command.CommandResult()
+
+ def testGbb(self):
+ """Test for the Chromium OS Google Binary Block"""
+ command.test_result = self._HandleGbbCommand
+ entry_args = {
+ 'keydir': 'devkeys',
+ 'bmpblk': 'bmpblk.bin',
+ }
+ data, _, _, _ = self._DoReadFileDtb('71_gbb.dts', entry_args=entry_args)
+
+ # Since futility
+ expected = GBB_DATA + GBB_DATA + 8 * chr(0) + (0x2180 - 16) * chr(0)
+ self.assertEqual(expected, data)
+
+ def testGbbTooSmall(self):
+ """Test for the Chromium OS Google Binary Block being large enough"""
+ with self.assertRaises(ValueError) as e:
+ self._DoReadFileDtb('72_gbb_too_small.dts')
+ self.assertIn("Node '/binman/gbb': GBB is too small",
+ str(e.exception))
+
+ def testGbbNoSize(self):
+ """Test for the Chromium OS Google Binary Block having a size"""
+ with self.assertRaises(ValueError) as e:
+ self._DoReadFileDtb('73_gbb_no_size.dts')
+ self.assertIn("Node '/binman/gbb': GBB must have a fixed size",
+ str(e.exception))
+
+ def _HandleVblockCommand(self, pipe_list):
+ """Fake calls to the futility utility"""
+ if pipe_list[0][0] == 'futility':
+ fname = pipe_list[0][3]
+ with open(fname, 'w') as fd:
+ fd.write(VBLOCK_DATA)
+ return command.CommandResult()
+
+ def testVblock(self):
+ """Test for the Chromium OS Verified Boot Block"""
+ command.test_result = self._HandleVblockCommand
+ entry_args = {
+ 'keydir': 'devkeys',
+ }
+ data, _, _, _ = self._DoReadFileDtb('74_vblock.dts',
+ entry_args=entry_args)
+ expected = U_BOOT_DATA + VBLOCK_DATA + U_BOOT_DTB_DATA
+ self.assertEqual(expected, data)
+
+ def testVblockNoContent(self):
+ """Test we detect a vblock which has no content to sign"""
+ with self.assertRaises(ValueError) as e:
+ self._DoReadFile('75_vblock_no_content.dts')
+ self.assertIn("Node '/binman/vblock': Vblock must have a 'content' "
+ 'property', str(e.exception))
+
+ def testVblockBadPhandle(self):
+ """Test that we detect a vblock with an invalid phandle in contents"""
+ with self.assertRaises(ValueError) as e:
+ self._DoReadFile('76_vblock_bad_phandle.dts')
+ self.assertIn("Node '/binman/vblock': Cannot find node for phandle "
+ '1000', str(e.exception))
+
+ def testVblockBadEntry(self):
+ """Test that we detect an entry that points to a non-entry"""
+ with self.assertRaises(ValueError) as e:
+ self._DoReadFile('77_vblock_bad_entry.dts')
+ self.assertIn("Node '/binman/vblock': Cannot find entry for node "
+ "'other'", str(e.exception))
+
+ def testTpl(self):
+ """Test that an image with TPL and ots device tree can be created"""
+ # ELF file with a '__bss_size' symbol
+ with open(self.TestFile('bss_data')) as fd:
+ TestFunctional._MakeInputFile('tpl/u-boot-tpl', fd.read())
+ data = self._DoReadFile('78_u_boot_tpl.dts')
+ self.assertEqual(U_BOOT_TPL_DATA + U_BOOT_TPL_DTB_DATA, data)
+
+ def testUsesPos(self):
+ """Test that the 'pos' property cannot be used anymore"""
+ with self.assertRaises(ValueError) as e:
+ data = self._DoReadFile('79_uses_pos.dts')
+ self.assertIn("Node '/binman/u-boot': Please use 'offset' instead of "
+ "'pos'", str(e.exception))
+
+
if __name__ == "__main__":
unittest.main()
diff --git a/tools/binman/image.py b/tools/binman/image.py
index 94028f19a51..68126bc3e69 100644
--- a/tools/binman/image.py
+++ b/tools/binman/image.py
@@ -57,7 +57,7 @@ class Image:
def AddMissingProperties(self):
"""Add properties that are not present in the device tree
- When binman has completed packing the entries the position and size of
+ When binman has completed packing the entries the offset and size of
each entry are known. But before this the device tree may not specify
these. Add any missing properties, with a dummy value, so that the
size of the entry is correct. That way we can insert the correct values
@@ -73,13 +73,13 @@ class Image:
"""
self._section.GetEntryContents()
- def GetEntryPositions(self):
- """Handle entries that want to set the position/size of other entries
+ def GetEntryOffsets(self):
+ """Handle entries that want to set the offset/size of other entries
- This calls each entry's GetPositions() method. If it returns a list
+ This calls each entry's GetOffsets() method. If it returns a list
of entries to update, it updates them.
"""
- self._section.GetEntryPositions()
+ self._section.GetEntryOffsets()
def PackEntries(self):
"""Pack all entries into the image"""
@@ -96,6 +96,9 @@ class Image:
def SetCalculatedProperties(self):
self._section.SetCalculatedProperties()
+ def SetImagePos(self):
+ self._section.SetImagePos(0)
+
def ProcessEntryContents(self):
"""Call the ProcessContents() method for each entry
@@ -121,5 +124,6 @@ class Image:
filename = '%s.map' % self._name
fname = tools.GetOutputFilename(filename)
with open(fname, 'w') as fd:
- print('%8s %8s %s' % ('Position', 'Size', 'Name'), file=fd)
+ print('%8s %8s %8s %s' % ('ImagePos', 'Offset', 'Size', 'Name'),
+ file=fd)
self._section.WriteMap(fd, 0)
diff --git a/tools/binman/test/08_pack.dts b/tools/binman/test/08_pack.dts
index dc63d99dcb0..a88785d8352 100644
--- a/tools/binman/test/08_pack.dts
+++ b/tools/binman/test/08_pack.dts
@@ -24,7 +24,7 @@
u-boot-fixed {
type = "u-boot";
- pos = <61>;
+ offset = <61>;
};
};
};
diff --git a/tools/binman/test/12_pack_inv_align.dts b/tools/binman/test/12_pack_inv_align.dts
index 1d9d80a65cc..d8dd600edb8 100644
--- a/tools/binman/test/12_pack_inv_align.dts
+++ b/tools/binman/test/12_pack_inv_align.dts
@@ -6,7 +6,7 @@
binman {
u-boot {
- pos = <5>;
+ offset = <5>;
align = <4>;
};
};
diff --git a/tools/binman/test/14_pack_overlap.dts b/tools/binman/test/14_pack_overlap.dts
index 611cfd97300..3895cba3bdb 100644
--- a/tools/binman/test/14_pack_overlap.dts
+++ b/tools/binman/test/14_pack_overlap.dts
@@ -10,7 +10,7 @@
u-boot-align {
type = "u-boot";
- pos = <3>;
+ offset = <3>;
};
};
};
diff --git a/tools/binman/test/21_image_pad.dts b/tools/binman/test/21_image_pad.dts
index bf39dc1b6f7..c6516689d94 100644
--- a/tools/binman/test/21_image_pad.dts
+++ b/tools/binman/test/21_image_pad.dts
@@ -10,7 +10,7 @@
};
u-boot {
- pos = <20>;
+ offset = <20>;
};
};
};
diff --git a/tools/binman/test/24_sorted.dts b/tools/binman/test/24_sorted.dts
index 43a7831341c..d35d39f077d 100644
--- a/tools/binman/test/24_sorted.dts
+++ b/tools/binman/test/24_sorted.dts
@@ -5,13 +5,13 @@
#size-cells = <1>;
binman {
- sort-by-pos;
+ sort-by-offset;
u-boot {
- pos = <22>;
+ offset = <22>;
};
u-boot-spl {
- pos = <1>;
+ offset = <1>;
};
};
};
diff --git a/tools/binman/test/25_pack_zero_size.dts b/tools/binman/test/25_pack_zero_size.dts
index 7d2baad3c6d..e863c44e3fd 100644
--- a/tools/binman/test/25_pack_zero_size.dts
+++ b/tools/binman/test/25_pack_zero_size.dts
@@ -9,7 +9,7 @@
};
u-boot-spl {
- pos = <0>;
+ offset = <0>;
};
};
};
diff --git a/tools/binman/test/27_pack_4gb_no_size.dts b/tools/binman/test/27_pack_4gb_no_size.dts
index e0b6519e75b..371cca10d58 100644
--- a/tools/binman/test/27_pack_4gb_no_size.dts
+++ b/tools/binman/test/27_pack_4gb_no_size.dts
@@ -5,14 +5,14 @@
#size-cells = <1>;
binman {
- sort-by-pos;
+ sort-by-offset;
end-at-4gb;
u-boot {
- pos = <0xfffffff0>;
+ offset = <0xfffffff0>;
};
u-boot-spl {
- pos = <0xfffffff7>;
+ offset = <0xfffffff7>;
};
};
};
diff --git a/tools/binman/test/28_pack_4gb_outside.dts b/tools/binman/test/28_pack_4gb_outside.dts
index 18d6bb5b8af..2216abfb70c 100644
--- a/tools/binman/test/28_pack_4gb_outside.dts
+++ b/tools/binman/test/28_pack_4gb_outside.dts
@@ -5,15 +5,15 @@
#size-cells = <1>;
binman {
- sort-by-pos;
+ sort-by-offset;
end-at-4gb;
size = <32>;
u-boot {
- pos = <0>;
+ offset = <0>;
};
u-boot-spl {
- pos = <0xffffffeb>;
+ offset = <0xffffffeb>;
};
};
};
diff --git a/tools/binman/test/29_x86-rom.dts b/tools/binman/test/29_x86-rom.dts
index d49078e19e2..d5c69f9d4a9 100644
--- a/tools/binman/test/29_x86-rom.dts
+++ b/tools/binman/test/29_x86-rom.dts
@@ -5,15 +5,15 @@
#size-cells = <1>;
binman {
- sort-by-pos;
+ sort-by-offset;
end-at-4gb;
size = <32>;
u-boot {
- pos = <0xffffffe0>;
+ offset = <0xffffffe0>;
};
u-boot-spl {
- pos = <0xffffffeb>;
+ offset = <0xffffffeb>;
};
};
};
diff --git a/tools/binman/test/30_x86-rom-me-no-desc.dts b/tools/binman/test/30_x86-rom-me-no-desc.dts
index 68d3ce09ecd..796cb87afc7 100644
--- a/tools/binman/test/30_x86-rom-me-no-desc.dts
+++ b/tools/binman/test/30_x86-rom-me-no-desc.dts
@@ -5,12 +5,12 @@
#size-cells = <1>;
binman {
- sort-by-pos;
+ sort-by-offset;
end-at-4gb;
size = <16>;
intel-me {
filename = "me.bin";
- pos-unset;
+ offset-unset;
};
};
};
diff --git a/tools/binman/test/31_x86-rom-me.dts b/tools/binman/test/31_x86-rom-me.dts
index ee3dac875a6..b8b0a5a74bb 100644
--- a/tools/binman/test/31_x86-rom-me.dts
+++ b/tools/binman/test/31_x86-rom-me.dts
@@ -5,7 +5,7 @@
#size-cells = <1>;
binman {
- sort-by-pos;
+ sort-by-offset;
end-at-4gb;
size = <0x800000>;
intel-descriptor {
@@ -14,7 +14,7 @@
intel-me {
filename = "me.bin";
- pos-unset;
+ offset-unset;
};
};
};
diff --git a/tools/binman/test/34_x86_ucode.dts b/tools/binman/test/34_x86_ucode.dts
index 64a6c2c3d5d..40725731cd3 100644
--- a/tools/binman/test/34_x86_ucode.dts
+++ b/tools/binman/test/34_x86_ucode.dts
@@ -5,7 +5,7 @@
#size-cells = <1>;
binman {
- sort-by-pos;
+ sort-by-offset;
end-at-4gb;
size = <0x200>;
u-boot-with-ucode-ptr {
diff --git a/tools/binman/test/35_x86_single_ucode.dts b/tools/binman/test/35_x86_single_ucode.dts
index 973e97f8641..2b1f086a41c 100644
--- a/tools/binman/test/35_x86_single_ucode.dts
+++ b/tools/binman/test/35_x86_single_ucode.dts
@@ -5,7 +5,7 @@
#size-cells = <1>;
binman {
- sort-by-pos;
+ sort-by-offset;
end-at-4gb;
size = <0x200>;
u-boot-with-ucode-ptr {
diff --git a/tools/binman/test/37_x86_no_ucode.dts b/tools/binman/test/37_x86_no_ucode.dts
index 9e12156ee2f..6da49c3da6d 100644
--- a/tools/binman/test/37_x86_no_ucode.dts
+++ b/tools/binman/test/37_x86_no_ucode.dts
@@ -5,7 +5,7 @@
#size-cells = <1>;
binman {
- sort-by-pos;
+ sort-by-offset;
end-at-4gb;
size = <0x200>;
u-boot-with-ucode-ptr {
diff --git a/tools/binman/test/38_x86_ucode_missing_node.dts b/tools/binman/test/38_x86_ucode_missing_node.dts
index d6cf0d844ed..720677c9c1e 100644
--- a/tools/binman/test/38_x86_ucode_missing_node.dts
+++ b/tools/binman/test/38_x86_ucode_missing_node.dts
@@ -5,7 +5,7 @@
#size-cells = <1>;
binman {
- sort-by-pos;
+ sort-by-offset;
end-at-4gb;
size = <0x200>;
u-boot-with-ucode-ptr {
diff --git a/tools/binman/test/39_x86_ucode_missing_node2.dts b/tools/binman/test/39_x86_ucode_missing_node2.dts
index b7e26c5ae41..10ac086d549 100644
--- a/tools/binman/test/39_x86_ucode_missing_node2.dts
+++ b/tools/binman/test/39_x86_ucode_missing_node2.dts
@@ -5,7 +5,7 @@
#size-cells = <1>;
binman {
- sort-by-pos;
+ sort-by-offset;
end-at-4gb;
size = <0x200>;
u-boot-with-ucode-ptr {
diff --git a/tools/binman/test/40_x86_ucode_not_in_image.dts b/tools/binman/test/40_x86_ucode_not_in_image.dts
index 67d17d392fd..609725824a5 100644
--- a/tools/binman/test/40_x86_ucode_not_in_image.dts
+++ b/tools/binman/test/40_x86_ucode_not_in_image.dts
@@ -5,7 +5,7 @@
#size-cells = <1>;
binman {
- sort-by-pos;
+ sort-by-offset;
size = <0x200>;
u-boot-with-ucode-ptr {
};
diff --git a/tools/binman/test/44_x86_optional_ucode.dts b/tools/binman/test/44_x86_optional_ucode.dts
index abe1322798e..24a7040d318 100644
--- a/tools/binman/test/44_x86_optional_ucode.dts
+++ b/tools/binman/test/44_x86_optional_ucode.dts
@@ -5,7 +5,7 @@
#size-cells = <1>;
binman {
- sort-by-pos;
+ sort-by-offset;
end-at-4gb;
size = <0x200>;
u-boot-with-ucode-ptr {
diff --git a/tools/binman/test/45_prop_test.dts b/tools/binman/test/45_prop_test.dts
index d22e460d299..064de2b3167 100644
--- a/tools/binman/test/45_prop_test.dts
+++ b/tools/binman/test/45_prop_test.dts
@@ -5,12 +5,12 @@
#size-cells = <1>;
binman {
- sort-by-pos;
+ sort-by-offset;
end-at-4gb;
size = <16>;
intel-me {
filename = "me.bin";
- pos-unset;
+ offset-unset;
intval = <3>;
intarray = <5 6>;
byteval = [08];
diff --git a/tools/binman/test/49_x86_ucode_spl.dts b/tools/binman/test/49_x86_ucode_spl.dts
index 67db93ad502..350d2c4730b 100644
--- a/tools/binman/test/49_x86_ucode_spl.dts
+++ b/tools/binman/test/49_x86_ucode_spl.dts
@@ -5,7 +5,7 @@
#size-cells = <1>;
binman {
- sort-by-pos;
+ sort-by-offset;
end-at-4gb;
size = <0x200>;
u-boot-spl-with-ucode-ptr {
diff --git a/tools/binman/test/53_symbols.dts b/tools/binman/test/53_symbols.dts
index 980b066eb21..9f135676cb0 100644
--- a/tools/binman/test/53_symbols.dts
+++ b/tools/binman/test/53_symbols.dts
@@ -10,7 +10,7 @@
};
u-boot {
- pos = <20>;
+ offset = <20>;
};
u-boot-spl2 {
diff --git a/tools/binman/test/55_sections.dts b/tools/binman/test/55_sections.dts
index 2ada395b036..6b306aeda46 100644
--- a/tools/binman/test/55_sections.dts
+++ b/tools/binman/test/55_sections.dts
@@ -24,5 +24,9 @@
u-boot {
};
};
+ section@2 {
+ u-boot {
+ };
+ };
};
};
diff --git a/tools/binman/test/58_x86_ucode_spl_needs_retry.dts b/tools/binman/test/58_x86_ucode_spl_needs_retry.dts
index e2cb80cf6e2..a04adaaf7ba 100644
--- a/tools/binman/test/58_x86_ucode_spl_needs_retry.dts
+++ b/tools/binman/test/58_x86_ucode_spl_needs_retry.dts
@@ -7,7 +7,7 @@
#size-cells = <1>;
binman {
- sort-by-pos;
+ sort-by-offset;
end-at-4gb;
size = <0x200>;
u-boot-spl-with-ucode-ptr {
diff --git a/tools/binman/test/62_entry_args.dts b/tools/binman/test/62_entry_args.dts
new file mode 100644
index 00000000000..4d4f102d60c
--- /dev/null
+++ b/tools/binman/test/62_entry_args.dts
@@ -0,0 +1,14 @@
+// SPDX-License-Identifier: GPL-2.0+
+/dts-v1/;
+
+/ {
+ #address-cells = <1>;
+ #size-cells = <1>;
+
+ binman {
+ _testing {
+ test-str-fdt = "test0";
+ test-int-fdt = <123>;
+ };
+ };
+};
diff --git a/tools/binman/test/63_entry_args_missing.dts b/tools/binman/test/63_entry_args_missing.dts
new file mode 100644
index 00000000000..1644e2fef3a
--- /dev/null
+++ b/tools/binman/test/63_entry_args_missing.dts
@@ -0,0 +1,13 @@
+// SPDX-License-Identifier: GPL-2.0+
+/dts-v1/;
+
+/ {
+ #address-cells = <1>;
+ #size-cells = <1>;
+
+ binman {
+ _testing {
+ test-str-fdt = "test0";
+ };
+ };
+};
diff --git a/tools/binman/test/64_entry_args_required.dts b/tools/binman/test/64_entry_args_required.dts
new file mode 100644
index 00000000000..705be100691
--- /dev/null
+++ b/tools/binman/test/64_entry_args_required.dts
@@ -0,0 +1,14 @@
+// SPDX-License-Identifier: GPL-2.0+
+/dts-v1/;
+
+/ {
+ #address-cells = <1>;
+ #size-cells = <1>;
+
+ binman {
+ _testing {
+ require-args;
+ test-str-fdt = "test0";
+ };
+ };
+};
diff --git a/tools/binman/test/65_entry_args_unknown_datatype.dts b/tools/binman/test/65_entry_args_unknown_datatype.dts
new file mode 100644
index 00000000000..3e4838f4fff
--- /dev/null
+++ b/tools/binman/test/65_entry_args_unknown_datatype.dts
@@ -0,0 +1,15 @@
+// SPDX-License-Identifier: GPL-2.0+
+/dts-v1/;
+
+/ {
+ #address-cells = <1>;
+ #size-cells = <1>;
+
+ binman {
+ _testing {
+ test-str-fdt = "test0";
+ test-int-fdt = <123>;
+ force-bad-datatype;
+ };
+ };
+};
diff --git a/tools/binman/test/66_text.dts b/tools/binman/test/66_text.dts
new file mode 100644
index 00000000000..59b1fed0ef8
--- /dev/null
+++ b/tools/binman/test/66_text.dts
@@ -0,0 +1,28 @@
+// SPDX-License-Identifier: GPL-2.0+
+/dts-v1/;
+
+/ {
+ #address-cells = <1>;
+ #size-cells = <1>;
+
+ binman {
+ text {
+ size = <8>;
+ text-label = "test-id";
+ };
+ text2 {
+ type = "text";
+ text-label = "test-id2";
+ };
+ text3 {
+ type = "text";
+ text-label = "test-id3";
+ };
+ /* This one does not use command-line args */
+ text4 {
+ type = "text";
+ text-label = "test-id4";
+ test-id4 = "some text";
+ };
+ };
+};
diff --git a/tools/binman/test/67_fmap.dts b/tools/binman/test/67_fmap.dts
new file mode 100644
index 00000000000..9c0e293ac83
--- /dev/null
+++ b/tools/binman/test/67_fmap.dts
@@ -0,0 +1,29 @@
+// SPDX-License-Identifier: GPL-2.0+
+/dts-v1/;
+
+/ {
+ #address-cells = <1>;
+ #size-cells = <1>;
+
+ binman {
+ section@0 {
+ read-only;
+ name-prefix = "ro-";
+ size = <0x10>;
+ pad-byte = <0x21>;
+
+ u-boot {
+ };
+ };
+ section@1 {
+ name-prefix = "rw-";
+ size = <0x10>;
+ pad-byte = <0x61>;
+
+ u-boot {
+ };
+ };
+ fmap {
+ };
+ };
+};
diff --git a/tools/binman/test/68_blob_named_by_arg.dts b/tools/binman/test/68_blob_named_by_arg.dts
new file mode 100644
index 00000000000..e129f843cd5
--- /dev/null
+++ b/tools/binman/test/68_blob_named_by_arg.dts
@@ -0,0 +1,12 @@
+// SPDX-License-Identifier: GPL-2.0+
+/dts-v1/;
+
+/ {
+ #address-cells = <1>;
+ #size-cells = <1>;
+
+ binman {
+ cros-ec-rw {
+ };
+ };
+};
diff --git a/tools/binman/test/69_fill.dts b/tools/binman/test/69_fill.dts
new file mode 100644
index 00000000000..e372ea37aaa
--- /dev/null
+++ b/tools/binman/test/69_fill.dts
@@ -0,0 +1,15 @@
+// SPDX-License-Identifier: GPL-2.0+
+/dts-v1/;
+
+/ {
+ #address-cells = <1>;
+ #size-cells = <1>;
+
+ binman {
+ size = <16>;
+ fill {
+ size = <8>;
+ fill-byte = [ff];
+ };
+ };
+};
diff --git a/tools/binman/test/70_fill_no_size.dts b/tools/binman/test/70_fill_no_size.dts
new file mode 100644
index 00000000000..7b1fcf1b68b
--- /dev/null
+++ b/tools/binman/test/70_fill_no_size.dts
@@ -0,0 +1,14 @@
+// SPDX-License-Identifier: GPL-2.0+
+/dts-v1/;
+
+/ {
+ #address-cells = <1>;
+ #size-cells = <1>;
+
+ binman {
+ size = <16>;
+ fill {
+ fill-byte = [ff];
+ };
+ };
+};
diff --git a/tools/binman/test/71_gbb.dts b/tools/binman/test/71_gbb.dts
new file mode 100644
index 00000000000..551756372af
--- /dev/null
+++ b/tools/binman/test/71_gbb.dts
@@ -0,0 +1,31 @@
+// SPDX-License-Identifier: GPL-2.0+
+/dts-v1/;
+
+/ {
+ #address-cells = <1>;
+ #size-cells = <1>;
+
+ binman {
+ gbb {
+ size = <0x2180>;
+ flags {
+ dev-screen-short-delay;
+ load-option-roms;
+ enable-alternate-os;
+ force-dev-switch-on;
+ force-dev-boot-usb;
+ disable-fw-rollback-check;
+ enter-triggers-tonorm;
+ force-dev-boot-legacy;
+ faft-key-override;
+ disable-ec-software-sync;
+ default-dev-boot-legacy;
+ disable-pd-software-sync;
+ disable-lid-shutdown;
+ force-dev-boot-fastboot-full-cap;
+ enable-serial;
+ disable-dwmp;
+ };
+ };
+ };
+};
diff --git a/tools/binman/test/72_gbb_too_small.dts b/tools/binman/test/72_gbb_too_small.dts
new file mode 100644
index 00000000000..c088f36a1d0
--- /dev/null
+++ b/tools/binman/test/72_gbb_too_small.dts
@@ -0,0 +1,10 @@
+// SPDX-License-Identifier: GPL-2.0+
+/dts-v1/;
+
+/ {
+ binman {
+ gbb {
+ size = <0x200>;
+ };
+ };
+};
diff --git a/tools/binman/test/73_gbb_no_size.dts b/tools/binman/test/73_gbb_no_size.dts
new file mode 100644
index 00000000000..83be4037852
--- /dev/null
+++ b/tools/binman/test/73_gbb_no_size.dts
@@ -0,0 +1,9 @@
+// SPDX-License-Identifier: GPL-2.0+
+/dts-v1/;
+
+/ {
+ binman {
+ gbb {
+ };
+ };
+};
diff --git a/tools/binman/test/74_vblock.dts b/tools/binman/test/74_vblock.dts
new file mode 100644
index 00000000000..f0c21bfe9fc
--- /dev/null
+++ b/tools/binman/test/74_vblock.dts
@@ -0,0 +1,28 @@
+// SPDX-License-Identifier: GPL-2.0+
+/dts-v1/;
+
+/ {
+ #address-cells = <1>;
+ #size-cells = <1>;
+
+ binman {
+ u_boot: u-boot {
+ };
+
+ vblock {
+ content = <&u_boot &dtb>;
+ keyblock = "firmware.keyblock";
+ signprivate = "firmware_data_key.vbprivk";
+ version = <1>;
+ kernelkey = "kernel_subkey.vbpubk";
+ preamble-flags = <1>;
+ };
+
+ /*
+ * Put this after the vblock so that its contents are not
+ * available when the vblock first tries to obtain its contents
+ */
+ dtb: u-boot-dtb {
+ };
+ };
+};
diff --git a/tools/binman/test/75_vblock_no_content.dts b/tools/binman/test/75_vblock_no_content.dts
new file mode 100644
index 00000000000..676d9474b31
--- /dev/null
+++ b/tools/binman/test/75_vblock_no_content.dts
@@ -0,0 +1,23 @@
+// SPDX-License-Identifier: GPL-2.0+
+/dts-v1/;
+
+/ {
+ #address-cells = <1>;
+ #size-cells = <1>;
+
+ binman {
+ u_boot: u-boot {
+ };
+
+ vblock {
+ keyblock = "firmware.keyblock";
+ signprivate = "firmware_data_key.vbprivk";
+ version = <1>;
+ kernelkey = "kernel_subkey.vbpubk";
+ preamble-flags = <1>;
+ };
+
+ dtb: u-boot-dtb {
+ };
+ };
+};
diff --git a/tools/binman/test/76_vblock_bad_phandle.dts b/tools/binman/test/76_vblock_bad_phandle.dts
new file mode 100644
index 00000000000..ffbd0c335c3
--- /dev/null
+++ b/tools/binman/test/76_vblock_bad_phandle.dts
@@ -0,0 +1,24 @@
+// SPDX-License-Identifier: GPL-2.0+
+/dts-v1/;
+
+/ {
+ #address-cells = <1>;
+ #size-cells = <1>;
+
+ binman {
+ u_boot: u-boot {
+ };
+
+ vblock {
+ content = <1000>;
+ keyblock = "firmware.keyblock";
+ signprivate = "firmware_data_key.vbprivk";
+ version = <1>;
+ kernelkey = "kernel_subkey.vbpubk";
+ preamble-flags = <1>;
+ };
+
+ dtb: u-boot-dtb {
+ };
+ };
+};
diff --git a/tools/binman/test/77_vblock_bad_entry.dts b/tools/binman/test/77_vblock_bad_entry.dts
new file mode 100644
index 00000000000..764c42a56e1
--- /dev/null
+++ b/tools/binman/test/77_vblock_bad_entry.dts
@@ -0,0 +1,27 @@
+// SPDX-License-Identifier: GPL-2.0+
+/dts-v1/;
+
+/ {
+ #address-cells = <1>;
+ #size-cells = <1>;
+
+ binman {
+ u_boot: u-boot {
+ };
+
+ vblock {
+ content = <&u_boot &other>;
+ keyblock = "firmware.keyblock";
+ signprivate = "firmware_data_key.vbprivk";
+ version = <1>;
+ kernelkey = "kernel_subkey.vbpubk";
+ preamble-flags = <1>;
+ };
+
+ dtb: u-boot-dtb {
+ };
+ };
+
+ other: other {
+ };
+};
diff --git a/tools/binman/test/78_u_boot_tpl.dts b/tools/binman/test/78_u_boot_tpl.dts
new file mode 100644
index 00000000000..6c60b4c46f4
--- /dev/null
+++ b/tools/binman/test/78_u_boot_tpl.dts
@@ -0,0 +1,11 @@
+// SPDX-License-Identifier: GPL-2.0+
+/dts-v1/;
+
+/ {
+ binman {
+ u-boot-tpl {
+ };
+ u-boot-tpl-dtb {
+ };
+ };
+};
diff --git a/tools/binman/test/79_uses_pos.dts b/tools/binman/test/79_uses_pos.dts
new file mode 100644
index 00000000000..7638b9b5e0c
--- /dev/null
+++ b/tools/binman/test/79_uses_pos.dts
@@ -0,0 +1,10 @@
+// SPDX-License-Identifier: GPL-2.0+
+/dts-v1/;
+
+/ {
+ binman {
+ u-boot {
+ pos = <10>;
+ };
+ };
+};
diff --git a/tools/binman/test/u_boot_binman_syms b/tools/binman/test/u_boot_binman_syms
index 2e02dc0ca9e..126a1a62309 100755
--- a/tools/binman/test/u_boot_binman_syms
+++ b/tools/binman/test/u_boot_binman_syms
Binary files differ
diff --git a/tools/binman/test/u_boot_binman_syms.c b/tools/binman/test/u_boot_binman_syms.c
index d8371610a5b..4898f983e32 100644
--- a/tools/binman/test/u_boot_binman_syms.c
+++ b/tools/binman/test/u_boot_binman_syms.c
@@ -8,6 +8,6 @@
#define CONFIG_BINMAN
#include <binman_sym.h>
-binman_sym_declare(unsigned long, u_boot_spl, pos);
-binman_sym_declare(unsigned long long, u_boot_spl2, pos);
-binman_sym_declare(unsigned long, u_boot_any, pos);
+binman_sym_declare(unsigned long, u_boot_spl, offset);
+binman_sym_declare(unsigned long long, u_boot_spl2, offset);
+binman_sym_declare(unsigned long, u_boot_any, image_pos);
diff --git a/tools/dtoc/fdt.py b/tools/dtoc/fdt.py
index 9d69b426c14..d36179bad36 100644
--- a/tools/dtoc/fdt.py
+++ b/tools/dtoc/fdt.py
@@ -181,7 +181,15 @@ class Node:
self.subnodes = []
self.props = {}
- def _FindNode(self, name):
+ def GetFdt(self):
+ """Get the Fdt object for this node
+
+ Returns:
+ Fdt object
+ """
+ return self._fdt
+
+ def FindNode(self, name):
"""Find a node given its name
Args:
@@ -314,6 +322,17 @@ class Fdt:
with open(self._fname) as fd:
self._fdt_obj = libfdt.Fdt(fd.read())
+ def LookupPhandle(self, phandle):
+ """Look up a phandle
+
+ Args:
+ phandle: Phandle to look up (int)
+
+ Returns:
+ Node object the phandle points to
+ """
+ return self.phandle_to_node.get(phandle)
+
def Scan(self, root='/'):
"""Scan a device tree, building up a tree of Node objects
@@ -349,7 +368,7 @@ class Fdt:
if len(parts) < 2:
return None
for part in parts[1:]:
- node = node._FindNode(part)
+ node = node.FindNode(part)
if not node:
return None
return node
diff --git a/tools/dtoc/fdt_util.py b/tools/dtoc/fdt_util.py
index 5b631419a92..5fbfc8877bd 100644
--- a/tools/dtoc/fdt_util.py
+++ b/tools/dtoc/fdt_util.py
@@ -5,6 +5,9 @@
# Written by Simon Glass <sjg@chromium.org>
#
+# Utility functions for reading from a device tree. Once the upstream pylibfdt
+# implementation advances far enough, we should be able to drop these.
+
import os
import struct
import sys
@@ -90,6 +93,16 @@ def EnsureCompiled(fname, capture_stderr=False):
return dtb_output
def GetInt(node, propname, default=None):
+ """Get an integer from a property
+
+ Args:
+ node: Node object to read from
+ propname: property name to read
+ default: Default value to use if the node/property do not exist
+
+ Returns:
+ Integer value read, or default if none
+ """
prop = node.props.get(propname)
if not prop:
return default
@@ -100,6 +113,16 @@ def GetInt(node, propname, default=None):
return value
def GetString(node, propname, default=None):
+ """Get a string from a property
+
+ Args:
+ node: Node object to read from
+ propname: property name to read
+ default: Default value to use if the node/property do not exist
+
+ Returns:
+ String value read, or default if none
+ """
prop = node.props.get(propname)
if not prop:
return default
@@ -110,6 +133,79 @@ def GetString(node, propname, default=None):
return value
def GetBool(node, propname, default=False):
+ """Get an boolean from a property
+
+ Args:
+ node: Node object to read from
+ propname: property name to read
+ default: Default value to use if the node/property do not exist
+
+ Returns:
+ Boolean value read, or default if none (if you set this to True the
+ function will always return True)
+ """
if propname in node.props:
return True
return default
+
+def GetByte(node, propname, default=None):
+ """Get an byte from a property
+
+ Args:
+ node: Node object to read from
+ propname: property name to read
+ default: Default value to use if the node/property do not exist
+
+ Returns:
+ Byte value read, or default if none
+ """
+ prop = node.props.get(propname)
+ if not prop:
+ return default
+ value = prop.value
+ if isinstance(value, list):
+ raise ValueError("Node '%s' property '%s' has list value: expecting "
+ "a single byte" % (node.name, propname))
+ if len(value) != 1:
+ raise ValueError("Node '%s' property '%s' has length %d, expecting %d" %
+ (node.name, propname, len(value), 1))
+ return ord(value[0])
+
+def GetPhandleList(node, propname):
+ """Get a list of phandles from a property
+
+ Args:
+ node: Node object to read from
+ propname: property name to read
+
+ Returns:
+ List of phandles read, each an integer
+ """
+ prop = node.props.get(propname)
+ if not prop:
+ return None
+ value = prop.value
+ if not isinstance(value, list):
+ value = [value]
+ return [fdt32_to_cpu(v) for v in value]
+
+def GetDatatype(node, propname, datatype):
+ """Get a value of a given type from a property
+
+ Args:
+ node: Node object to read from
+ propname: property name to read
+ datatype: Type to read (str or int)
+
+ Returns:
+ value read, or None if none
+
+ Raises:
+ ValueError if datatype is not str or int
+ """
+ if datatype == str:
+ return GetString(node, propname)
+ elif datatype == int:
+ return GetInt(node, propname)
+ raise ValueError("fdt_util internal error: Unknown data type '%s'" %
+ datatype)
diff --git a/tools/dtoc/test_fdt.py b/tools/dtoc/test_fdt.py
index f085b1dd1a9..6fe03ac53d0 100755
--- a/tools/dtoc/test_fdt.py
+++ b/tools/dtoc/test_fdt.py
@@ -115,6 +115,9 @@ class TestFdt(unittest.TestCase):
fdt.CheckErr(-libfdt.NOTFOUND, 'hello')
self.assertIn('FDT_ERR_NOTFOUND: hello', str(e.exception))
+ def testGetFdt(self):
+ node = self.dtb.GetNode('/spl-test')
+ self.assertEqual(self.dtb, node.GetFdt())
class TestNode(unittest.TestCase):
"""Test operation of the Node class"""
@@ -155,12 +158,12 @@ class TestNode(unittest.TestCase):
self.assertEqual(prop.value, value)
def testFindNode(self):
- """Tests that we can find a node using the _FindNode() functoin"""
- node = self.dtb.GetRoot()._FindNode('i2c@0')
+ """Tests that we can find a node using the FindNode() functoin"""
+ node = self.dtb.GetRoot().FindNode('i2c@0')
self.assertEqual('i2c@0', node.name)
- subnode = node._FindNode('pmic@9')
+ subnode = node.FindNode('pmic@9')
self.assertEqual('pmic@9', subnode.name)
- self.assertEqual(None, node._FindNode('missing'))
+ self.assertEqual(None, node.FindNode('missing'))
def testRefreshMissingNode(self):
"""Test refreshing offsets when an extra node is present in dtb"""
@@ -188,6 +191,14 @@ class TestNode(unittest.TestCase):
self.assertIn("Internal error, property 'notstring' missing, offset ",
str(e.exception))
+ def testLookupPhandle(self):
+ """Test looking up a single phandle"""
+ dtb = fdt.FdtScan('tools/dtoc/dtoc_test_phandle.dts')
+ node = dtb.GetNode('/phandle-source2')
+ prop = node.props['clocks']
+ target = dtb.GetNode('/phandle-target')
+ self.assertEqual(target, dtb.LookupPhandle(fdt32_to_cpu(prop.value)))
+
class TestProp(unittest.TestCase):
"""Test operation of the Prop class"""
@@ -380,6 +391,36 @@ class TestFdtUtil(unittest.TestCase):
self.assertEqual(True, fdt_util.GetBool(self.node, 'missing', True))
self.assertEqual(False, fdt_util.GetBool(self.node, 'missing', False))
+ def testGetByte(self):
+ self.assertEqual(5, fdt_util.GetByte(self.node, 'byteval'))
+ self.assertEqual(3, fdt_util.GetByte(self.node, 'missing', 3))
+
+ with self.assertRaises(ValueError) as e:
+ fdt_util.GetByte(self.node, 'longbytearray')
+ self.assertIn("property 'longbytearray' has list value: expecting a "
+ 'single byte', str(e.exception))
+
+ with self.assertRaises(ValueError) as e:
+ fdt_util.GetByte(self.node, 'intval')
+ self.assertIn("property 'intval' has length 4, expecting 1",
+ str(e.exception))
+
+ def testGetPhandleList(self):
+ dtb = fdt.FdtScan('tools/dtoc/dtoc_test_phandle.dts')
+ node = dtb.GetNode('/phandle-source2')
+ self.assertEqual([1], fdt_util.GetPhandleList(node, 'clocks'))
+ node = dtb.GetNode('/phandle-source')
+ self.assertEqual([1, 2, 11, 3, 12, 13, 1],
+ fdt_util.GetPhandleList(node, 'clocks'))
+ self.assertEqual(None, fdt_util.GetPhandleList(node, 'missing'))
+
+ def testGetDataType(self):
+ self.assertEqual(1, fdt_util.GetDatatype(self.node, 'intval', int))
+ self.assertEqual('message', fdt_util.GetDatatype(self.node, 'stringval',
+ str))
+ with self.assertRaises(ValueError) as e:
+ self.assertEqual(3, fdt_util.GetDatatype(self.node, 'boolval',
+ bool))
def testFdtCellsToCpu(self):
val = self.node.props['intarray'].value
self.assertEqual(0, fdt_util.fdt_cells_to_cpu(val, 0))
diff --git a/tools/patman/command.py b/tools/patman/command.py
index 598bfdcd90b..14edcdaffd2 100644
--- a/tools/patman/command.py
+++ b/tools/patman/command.py
@@ -61,8 +61,12 @@ def RunPipe(pipe_list, infile=None, outfile=None,
"""
if test_result:
if hasattr(test_result, '__call__'):
- return test_result(pipe_list=pipe_list)
- return test_result
+ result = test_result(pipe_list=pipe_list)
+ if result:
+ return result
+ else:
+ return test_result
+ # No result: fall through to normal processing
result = CommandResult()
last_pipe = None
pipeline = list(pipe_list)
diff --git a/tools/patman/tools.py b/tools/patman/tools.py
index 700cb4505d4..e80481438b5 100644
--- a/tools/patman/tools.py
+++ b/tools/patman/tools.py
@@ -3,16 +3,26 @@
# Copyright (c) 2016 Google, Inc
#
+import command
import os
import shutil
import tempfile
import tout
+# Output directly (generally this is temporary)
outdir = None
-indirs = None
+
+# True to keep the output directory around after exiting
preserve_outdir = False
+# Path to the Chrome OS chroot, if we know it
+chroot_path = None
+
+# Search paths to use for Filename(), used to find files
+search_paths = []
+
+
def PrepareOutputDir(dirname, preserve=False):
"""Select an output directory, ensuring it exists.
@@ -106,8 +116,8 @@ def GetInputFilename(fname):
if os.path.exists(pathname):
return pathname
- raise ValueError("Filename '%s' not found in input path (%s)" %
- (fname, ','.join(indir)))
+ raise ValueError("Filename '%s' not found in input path (%s) (cwd='%s')" %
+ (fname, ','.join(indir), os.getcwd()))
def Align(pos, align):
if align:
@@ -117,3 +127,67 @@ def Align(pos, align):
def NotPowerOfTwo(num):
return num and (num & (num - 1))
+
+def Run(name, *args):
+ command.Run(name, *args, cwd=outdir)
+
+def Filename(fname):
+ """Resolve a file path to an absolute path.
+
+ If fname starts with ##/ and chroot is available, ##/ gets replaced with
+ the chroot path. If chroot is not available, this file name can not be
+ resolved, `None' is returned.
+
+ If fname is not prepended with the above prefix, and is not an existing
+ file, the actual file name is retrieved from the passed in string and the
+ search_paths directories (if any) are searched to for the file. If found -
+ the path to the found file is returned, `None' is returned otherwise.
+
+ Args:
+ fname: a string, the path to resolve.
+
+ Returns:
+ Absolute path to the file or None if not found.
+ """
+ if fname.startswith('##/'):
+ if chroot_path:
+ fname = os.path.join(chroot_path, fname[3:])
+ else:
+ return None
+
+ # Search for a pathname that exists, and return it if found
+ if fname and not os.path.exists(fname):
+ for path in search_paths:
+ pathname = os.path.join(path, os.path.basename(fname))
+ if os.path.exists(pathname):
+ return pathname
+
+ # If not found, just return the standard, unchanged path
+ return fname
+
+def ReadFile(fname):
+ """Read and return the contents of a file.
+
+ Args:
+ fname: path to filename to read, where ## signifiies the chroot.
+
+ Returns:
+ data read from file, as a string.
+ """
+ with open(Filename(fname), 'rb') as fd:
+ data = fd.read()
+ #self._out.Info("Read file '%s' size %d (%#0x)" %
+ #(fname, len(data), len(data)))
+ return data
+
+def WriteFile(fname, data):
+ """Write data into a file.
+
+ Args:
+ fname: path to filename to write
+ data: data to write to file, as a string
+ """
+ #self._out.Info("Write file '%s' size %d (%#0x)" %
+ #(fname, len(data), len(data)))
+ with open(Filename(fname), 'wb') as fd:
+ fd.write(data)