summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--Makefile57
-rw-r--r--arch/arm/cpu/armv8/zynqmp/Kconfig1
-rw-r--r--arch/arm/dts/s5pc1xx-goni.dts165
-rw-r--r--arch/arm/dts/sunxi-u-boot.dtsi14
-rw-r--r--arch/arm/dts/tegra124-nyan-big-u-boot.dtsi15
-rw-r--r--arch/arm/dts/tegra124-nyan-big.dts2
-rw-r--r--arch/arm/dts/tegra20-u-boot.dtsi8
-rw-r--r--arch/arm/dts/tegra20.dtsi2
-rw-r--r--arch/arm/dts/zynq-7000.dtsi4
-rw-r--r--arch/arm/dts/zynqmp.dtsi1
-rw-r--r--arch/arm/include/asm/arch-zynqmp/hardware.h2
-rw-r--r--arch/arm/mach-mvebu/armada8k/cpu.c58
-rw-r--r--arch/powerpc/cpu/mpc85xx/fdt.c61
-rw-r--r--arch/x86/dts/emulation-u-boot.dtsi18
-rw-r--r--arch/x86/dts/u-boot.dtsi62
-rw-r--r--board/intercontrol/digsy_mtc/Makefile2
-rw-r--r--board/intercontrol/digsy_mtc/cmd_mtc.c369
-rw-r--r--board/intercontrol/digsy_mtc/cmd_mtc.h45
-rw-r--r--board/intercontrol/digsy_mtc/digsy_mtc.c9
-rw-r--r--board/xilinx/zynq/board.c112
-rw-r--r--board/xilinx/zynqmp/zynqmp.c123
-rw-r--r--common/board_r.c4
-rw-r--r--common/image.c7
-rw-r--r--common/miiphyutil.c12
-rw-r--r--common/scsi.c76
-rw-r--r--configs/digsy_mtc_RAMBOOT_defconfig1
-rw-r--r--configs/digsy_mtc_defconfig1
-rw-r--r--configs/digsy_mtc_rev5_RAMBOOT_defconfig1
-rw-r--r--configs/digsy_mtc_rev5_defconfig1
-rw-r--r--configs/gplugd_defconfig5
-rw-r--r--configs/s5p_goni_defconfig3
-rw-r--r--configs/xilinx_zynqmp_ep_defconfig2
-rw-r--r--configs/xilinx_zynqmp_zcu102_defconfig2
-rw-r--r--configs/xilinx_zynqmp_zcu102_revB_defconfig2
-rw-r--r--doc/mvebu/armada-8k-memory.txt56
-rw-r--r--drivers/block/Kconfig22
-rw-r--r--drivers/block/Makefile1
-rw-r--r--drivers/block/ahci.c30
-rw-r--r--drivers/block/blk-uclass.c2
-rw-r--r--drivers/block/sata_ceva.c41
-rw-r--r--drivers/block/scsi-uclass.c27
-rw-r--r--drivers/gpio/zynq_gpio.c1
-rw-r--r--drivers/i2c/mv_i2c.c4
-rw-r--r--drivers/mmc/Kconfig2
-rw-r--r--drivers/mmc/Makefile1
-rw-r--r--drivers/mmc/spear_sdhci.c27
-rw-r--r--drivers/net/xilinx_axi_emac.c3
-rw-r--r--drivers/net/xilinx_emaclite.c3
-rw-r--r--drivers/net/zynq_gem.c3
-rw-r--r--drivers/power/pmic/Kconfig7
-rw-r--r--drivers/power/pmic/Makefile1
-rw-r--r--drivers/power/pmic/max8998.c61
-rw-r--r--drivers/spi/Makefile2
-rw-r--r--drivers/spi/armada100_spi.c203
-rw-r--r--drivers/spi/mpc52xx_spi.c90
-rw-r--r--include/ahci.h2
-rw-r--r--include/configs/digsy_mtc.h6
-rw-r--r--include/configs/gplugd.h9
-rw-r--r--include/configs/xilinx_zynqmp.h1
-rw-r--r--include/configs/xilinx_zynqmp_ep.h1
-rw-r--r--include/configs/xilinx_zynqmp_zcu102.h2
-rw-r--r--include/dm/uclass-id.h1
-rw-r--r--include/fdtdec.h34
-rw-r--r--include/miiphy.h9
-rw-r--r--include/sata.h2
-rw-r--r--include/scsi.h20
-rw-r--r--lib/fdtdec.c56
-rw-r--r--scripts/Makefile.lib25
-rw-r--r--scripts/config_whitelist.txt2
-rw-r--r--tools/binman/.gitignore1
-rw-r--r--tools/binman/README541
l---------tools/binman/binman1
-rwxr-xr-xtools/binman/binman.py114
-rw-r--r--tools/binman/cmdline.py53
-rw-r--r--tools/binman/control.py118
-rw-r--r--tools/binman/entry_test.py27
-rw-r--r--tools/binman/etype/_testing.py26
-rw-r--r--tools/binman/etype/blob.py37
-rw-r--r--tools/binman/etype/entry.py200
-rw-r--r--tools/binman/etype/intel_cmc.py17
-rw-r--r--tools/binman/etype/intel_descriptor.py55
-rw-r--r--tools/binman/etype/intel_fsp.py17
-rw-r--r--tools/binman/etype/intel_me.py17
-rw-r--r--tools/binman/etype/intel_mrc.py17
-rw-r--r--tools/binman/etype/intel_vga.py17
-rw-r--r--tools/binman/etype/u_boot.py17
-rw-r--r--tools/binman/etype/u_boot_dtb.py17
-rw-r--r--tools/binman/etype/u_boot_dtb_with_ucode.py78
-rw-r--r--tools/binman/etype/u_boot_img.py17
-rw-r--r--tools/binman/etype/u_boot_nodtb.py17
-rw-r--r--tools/binman/etype/u_boot_spl.py17
-rw-r--r--tools/binman/etype/u_boot_spl_bss_pad.py26
-rw-r--r--tools/binman/etype/u_boot_spl_with_ucode_ptr.py28
-rw-r--r--tools/binman/etype/u_boot_ucode.py84
-rw-r--r--tools/binman/etype/u_boot_with_ucode_ptr.py87
-rw-r--r--tools/binman/etype/x86_start16.py17
-rw-r--r--tools/binman/etype/x86_start16_spl.py17
-rw-r--r--tools/binman/fdt_test.py48
-rw-r--r--tools/binman/func_test.py822
-rw-r--r--tools/binman/image.py229
-rw-r--r--tools/binman/test/01_invalid.dts5
-rw-r--r--tools/binman/test/02_missing_node.dts6
-rw-r--r--tools/binman/test/03_empty.dts9
-rw-r--r--tools/binman/test/04_invalid_entry.dts11
-rw-r--r--tools/binman/test/05_simple.dts11
-rw-r--r--tools/binman/test/06_dual_image.dts22
-rw-r--r--tools/binman/test/07_bad_align.dts12
-rw-r--r--tools/binman/test/08_pack.dts30
-rw-r--r--tools/binman/test/09_pack_extra.dts35
-rw-r--r--tools/binman/test/10_pack_align_power2.dts12
-rw-r--r--tools/binman/test/11_pack_align_size_power2.dts12
-rw-r--r--tools/binman/test/12_pack_inv_align.dts13
-rw-r--r--tools/binman/test/13_pack_inv_size_align.dts13
-rw-r--r--tools/binman/test/14_pack_overlap.dts16
-rw-r--r--tools/binman/test/15_pack_overflow.dts12
-rw-r--r--tools/binman/test/16_pack_image_overflow.dts13
-rw-r--r--tools/binman/test/17_pack_image_size.dts13
-rw-r--r--tools/binman/test/18_pack_image_align.dts13
-rw-r--r--tools/binman/test/19_pack_inv_image_align.dts14
-rw-r--r--tools/binman/test/20_pack_inv_image_align_power2.dts13
-rw-r--r--tools/binman/test/21_image_pad.dts16
-rw-r--r--tools/binman/test/22_image_name.dts21
-rw-r--r--tools/binman/test/23_blob.dts12
-rw-r--r--tools/binman/test/24_sorted.dts17
-rw-r--r--tools/binman/test/25_pack_zero_size.dts15
-rw-r--r--tools/binman/test/26_pack_u_boot_dtb.dts14
-rw-r--r--tools/binman/test/27_pack_4gb_no_size.dts18
-rw-r--r--tools/binman/test/28_pack_4gb_outside.dts19
-rw-r--r--tools/binman/test/29_x86-rom.dts19
-rw-r--r--tools/binman/test/30_x86-rom-me-no-desc.dts15
-rw-r--r--tools/binman/test/31_x86-rom-me.dts18
-rw-r--r--tools/binman/test/32_intel-vga.dts13
-rw-r--r--tools/binman/test/33_x86-start16.dts13
-rw-r--r--tools/binman/test/34_x86_ucode.dts29
-rw-r--r--tools/binman/test/35_x86_single_ucode.dts26
-rw-r--r--tools/binman/test/36_u_boot_img.dts11
-rw-r--r--tools/binman/test/37_x86_no_ucode.dts20
-rw-r--r--tools/binman/test/38_x86_ucode_missing_node.dts26
-rw-r--r--tools/binman/test/39_x86_ucode_missing_node2.dts23
-rw-r--r--tools/binman/test/40_x86_ucode_not_in_image.dts28
-rw-r--r--tools/binman/test/41_unknown_pos_size.dts11
-rw-r--r--tools/binman/test/42_intel-fsp.dts13
-rw-r--r--tools/binman/test/43_intel-cmc.dts13
-rw-r--r--tools/binman/test/44_x86_optional_ucode.dts30
-rw-r--r--tools/binman/test/descriptor.binbin0 -> 4096 bytes
-rwxr-xr-xtools/binman/test/u_boot_no_ucode_ptrbin0 -> 4182 bytes
-rw-r--r--tools/binman/test/u_boot_no_ucode_ptr.c15
-rwxr-xr-xtools/binman/test/u_boot_ucode_ptrbin0 -> 4175 bytes
-rw-r--r--tools/binman/test/u_boot_ucode_ptr.c15
-rw-r--r--tools/binman/test/u_boot_ucode_ptr.lds18
-rw-r--r--tools/ifdtool.c254
151 files changed, 4434 insertions, 1376 deletions
diff --git a/Makefile b/Makefile
index 6a94504..0874964 100644
--- a/Makefile
+++ b/Makefile
@@ -903,6 +903,12 @@ u-boot.ldr: u-boot
$(LDR) -T $(CONFIG_CPU) -c $@ $< $(LDR_FLAGS)
$(BOARD_SIZE_CHECK)
+# binman
+# ---------------------------------------------------------------------------
+quiet_cmd_binman = BINMAN $@
+cmd_binman = $(srctree)/tools/binman/binman -d u-boot.dtb -O . \
+ -I . -I $(srctree)/board/$(BOARDDIR) $<
+
OBJCOPYFLAGS_u-boot.ldr.hex := -I binary -O ihex
OBJCOPYFLAGS_u-boot.ldr.srec := -I binary -O srec
@@ -1047,50 +1053,11 @@ endif
# x86 uses a large ROM. We fill it with 0xff, put the 16-bit stuff (including
# reset vector) at the top, Intel ME descriptor at the bottom, and U-Boot in
-# the middle.
+# the middle. This is handled by binman based on an image description in the
+# board's device tree.
ifneq ($(CONFIG_X86_RESET_VECTOR),)
rom: u-boot.rom FORCE
-IFDTOOL=$(objtree)/tools/ifdtool
-IFDTOOL_FLAGS = -f 0:$(objtree)/u-boot.dtb
-IFDTOOL_FLAGS += -m 0x$(shell $(NM) u-boot |grep _dt_ucode_base_size |cut -d' ' -f1)
-IFDTOOL_FLAGS += -U $(CONFIG_SYS_TEXT_BASE):$(objtree)/u-boot-nodtb.bin
-IFDTOOL_FLAGS += -w $(CONFIG_SYS_X86_START16):$(objtree)/u-boot-x86-16bit.bin
-IFDTOOL_FLAGS += -C
-
-ifneq ($(CONFIG_HAVE_INTEL_ME),)
-IFDTOOL_ME_FLAGS = -D $(srctree)/board/$(BOARDDIR)/descriptor.bin
-IFDTOOL_ME_FLAGS += -i ME:$(srctree)/board/$(BOARDDIR)/me.bin
-endif
-
-ifneq ($(CONFIG_HAVE_MRC),)
-IFDTOOL_FLAGS += -w $(CONFIG_X86_MRC_ADDR):$(srctree)/board/$(BOARDDIR)/mrc.bin
-endif
-
-ifneq ($(CONFIG_HAVE_FSP),)
-IFDTOOL_FLAGS += -w $(CONFIG_FSP_ADDR):$(srctree)/board/$(BOARDDIR)/$(CONFIG_FSP_FILE)
-endif
-
-ifneq ($(CONFIG_HAVE_CMC),)
-IFDTOOL_FLAGS += -w $(CONFIG_CMC_ADDR):$(srctree)/board/$(BOARDDIR)/$(CONFIG_CMC_FILE)
-endif
-
-ifneq ($(CONFIG_HAVE_VGA_BIOS),)
-IFDTOOL_FLAGS += -w $(CONFIG_VGA_BIOS_ADDR):$(srctree)/board/$(BOARDDIR)/$(CONFIG_VGA_BIOS_FILE)
-endif
-
-ifneq ($(CONFIG_HAVE_REFCODE),)
-IFDTOOL_FLAGS += -w $(CONFIG_X86_REFCODE_ADDR):refcode.bin
-endif
-
-quiet_cmd_ifdtool = IFDTOOL $@
-cmd_ifdtool = $(IFDTOOL) -c -r $(CONFIG_ROM_SIZE) u-boot.tmp;
-ifneq ($(CONFIG_HAVE_INTEL_ME),)
-cmd_ifdtool += $(IFDTOOL) $(IFDTOOL_ME_FLAGS) u-boot.tmp;
-endif
-cmd_ifdtool += $(IFDTOOL) $(IFDTOOL_FLAGS) u-boot.tmp;
-cmd_ifdtool += mv u-boot.tmp $@
-
refcode.bin: $(srctree)/board/$(BOARDDIR)/refcode.bin FORCE
$(call if_changed,copy)
@@ -1100,7 +1067,7 @@ cmd_ldr = $(LD) $(LDFLAGS_$(@F)) \
u-boot.rom: u-boot-x86-16bit.bin u-boot.bin FORCE \
$(if $(CONFIG_HAVE_REFCODE),refcode.bin)
- $(call if_changed,ifdtool)
+ $(call if_changed,binman)
OBJCOPYFLAGS_u-boot-x86-16bit.bin := -O binary -j .start16 -j .resetvec
u-boot-x86-16bit.bin: u-boot FORCE
@@ -1108,10 +1075,8 @@ u-boot-x86-16bit.bin: u-boot FORCE
endif
ifneq ($(CONFIG_ARCH_SUNXI),)
-OBJCOPYFLAGS_u-boot-sunxi-with-spl.bin = -I binary -O binary \
- --pad-to=$(CONFIG_SPL_PAD_TO) --gap-fill=0xff
-u-boot-sunxi-with-spl.bin: spl/sunxi-spl.bin u-boot.img FORCE
- $(call if_changed,pad_cat)
+u-boot-sunxi-with-spl.bin: spl/sunxi-spl.bin u-boot.img u-boot.dtb FORCE
+ $(call if_changed,binman)
endif
ifneq ($(CONFIG_TEGRA),)
diff --git a/arch/arm/cpu/armv8/zynqmp/Kconfig b/arch/arm/cpu/armv8/zynqmp/Kconfig
index f354aae..e175e6e 100644
--- a/arch/arm/cpu/armv8/zynqmp/Kconfig
+++ b/arch/arm/cpu/armv8/zynqmp/Kconfig
@@ -43,6 +43,7 @@ config SYS_CONFIG_NAME
config BOOT_INIT_FILE
string "boot.bin init register filename"
+ depends on SPL
default ""
help
Add register writes to boot.bin format (max 256 pairs).
diff --git a/arch/arm/dts/s5pc1xx-goni.dts b/arch/arm/dts/s5pc1xx-goni.dts
index 7bbfe59..e80132d 100644
--- a/arch/arm/dts/s5pc1xx-goni.dts
+++ b/arch/arm/dts/s5pc1xx-goni.dts
@@ -19,6 +19,7 @@
serial2 = "/serial@e2900800";
console = "/serial@e2900800";
pinctrl0 = &pinctrl0;
+ i2c3 = &i2c_pmic;
};
pinctrl0: pinctrl@e0200000 {
@@ -32,4 +33,168 @@
id = <2>;
};
+ i2c_pmic: i2c-pmic {
+ compatible = "i2c-gpio";
+ gpios = <&gpj4 0 0>, /* sda */
+ <&gpj4 3 0>; /* scl */
+ i2c-gpio,delay-us = <2>; /* ~100 kHz */
+ #address-cells = <1>;
+ #size-cells = <0>;
+ status = "okay";
+
+ pmic@66 {
+ compatible = "maxim,max8998";
+ reg = <0x66 0 0>;
+
+ voltage-regulators {
+ ldo2_reg: LDO2 {
+ regulator-compatible = "LDO2";
+ regulator-name = "VALIVE_1.1V";
+ regulator-min-microvolt = <1100000>;
+ regulator-max-microvolt = <1100000>;
+ regulator-always-on;
+ };
+
+ ldo3_reg: LDO3 {
+ regulator-compatible = "LDO3";
+ regulator-name = "VUSB+MIPI_1.1V";
+ regulator-min-microvolt = <1100000>;
+ regulator-max-microvolt = <1100000>;
+ regulator-always-on;
+ };
+
+ ldo4_reg: LDO4 {
+ regulator-compatible = "LDO4";
+ regulator-name = "VADC_3.3V";
+ regulator-min-microvolt = <3300000>;
+ regulator-max-microvolt = <3300000>;
+ };
+
+ ldo5_reg: LDO5 {
+ regulator-compatible = "LDO5";
+ regulator-name = "VTF_2.8V";
+ regulator-min-microvolt = <2800000>;
+ regulator-max-microvolt = <2800000>;
+ };
+
+ ldo6_reg: LDO6 {
+ regulator-compatible = "LDO6";
+ regulator-name = "VCC_3.3V";
+ regulator-min-microvolt = <3300000>;
+ regulator-max-microvolt = <3300000>;
+ };
+
+ ldo7_reg: LDO7 {
+ regulator-compatible = "LDO7";
+ regulator-name = "VLCD_1.8V";
+ regulator-min-microvolt = <1800000>;
+ regulator-max-microvolt = <1800000>;
+ regulator-always-on;
+ };
+
+ ldo8_reg: LDO8 {
+ regulator-compatible = "LDO8";
+ regulator-name = "VUSB+VDAC_3.3V";
+ regulator-min-microvolt = <3300000>;
+ regulator-max-microvolt = <3300000>;
+ };
+
+ ldo9_reg: LDO9 {
+ regulator-compatible = "LDO9";
+ regulator-name = "VCC+VCAM_2.8V";
+ regulator-min-microvolt = <2800000>;
+ regulator-max-microvolt = <2800000>;
+ };
+
+ ldo10_reg: LDO10 {
+ regulator-compatible = "LDO10";
+ regulator-name = "VPLL_1.1V";
+ regulator-min-microvolt = <1100000>;
+ regulator-max-microvolt = <1100000>;
+ regulator-boot-on;
+ };
+
+ ldo11_reg: LDO11 {
+ regulator-compatible = "LDO11";
+ regulator-name = "CAM_IO_2.8V";
+ regulator-min-microvolt = <2800000>;
+ regulator-max-microvolt = <2800000>;
+ };
+
+ ldo12_reg: LDO12 {
+ regulator-compatible = "LDO12";
+ regulator-name = "CAM_ISP_1.2V";
+ regulator-min-microvolt = <1200000>;
+ regulator-max-microvolt = <1200000>;
+ };
+
+ ldo13_reg: LDO13 {
+ regulator-compatible = "LDO13";
+ regulator-name = "CAM_A_2.8V";
+ regulator-min-microvolt = <2800000>;
+ regulator-max-microvolt = <2800000>;
+ };
+
+ ldo14_reg: LDO14 {
+ regulator-compatible = "LDO14";
+ regulator-name = "CAM_CIF_1.8V";
+ regulator-min-microvolt = <1800000>;
+ regulator-max-microvolt = <1800000>;
+ };
+
+ ldo15_reg: LDO15 {
+ regulator-compatible = "LDO15";
+ regulator-name = "CAM_AF_3.3V";
+ regulator-min-microvolt = <3300000>;
+ regulator-max-microvolt = <3300000>;
+ };
+
+ ldo16_reg: LDO16 {
+ regulator-compatible = "LDO16";
+ regulator-name = "VMIPI_1.8V";
+ regulator-min-microvolt = <1800000>;
+ regulator-max-microvolt = <1800000>;
+ };
+
+ ldo17_reg: LDO17 {
+ regulator-compatible = "LDO17";
+ regulator-name = "CAM_8M_1.8V";
+ regulator-min-microvolt = <1800000>;
+ regulator-max-microvolt = <1800000>;
+ regulator-always-on;
+ };
+
+ buck1_reg: BUCK1 {
+ regulator-compatible = "BUCK1";
+ regulator-name = "VARM_1.2V";
+ regulator-min-microvolt = <1200000>;
+ regulator-max-microvolt = <1200000>;
+ };
+
+ buck2_reg: BUCK2 {
+ regulator-compatible = "BUCK2";
+ regulator-name = "VINT_1.2V";
+ regulator-min-microvolt = <1200000>;
+ regulator-max-microvolt = <1200000>;
+ };
+
+ buck3_reg: BUCK3 {
+ regulator-compatible = "BUCK3";
+ regulator-name = "VCC_1.8V";
+ regulator-min-microvolt = <1800000>;
+ regulator-max-microvolt = <1800000>;
+ regulator-always-on;
+ };
+
+ buck4_reg: BUCK4 {
+ regulator-compatible = "BUCK4";
+ regulator-name = "CAM_CORE_1.2V";
+ regulator-min-microvolt = <1200000>;
+ regulator-max-microvolt = <1200000>;
+ regulator-always-on;
+ };
+ };
+ };
+ };
+
};
diff --git a/arch/arm/dts/sunxi-u-boot.dtsi b/arch/arm/dts/sunxi-u-boot.dtsi
new file mode 100644
index 0000000..5adfd9b
--- /dev/null
+++ b/arch/arm/dts/sunxi-u-boot.dtsi
@@ -0,0 +1,14 @@
+#include <config.h>
+
+/ {
+ binman {
+ filename = "u-boot-sunxi-with-spl.bin";
+ pad-byte = <0xff>;
+ blob {
+ filename = "spl/sunxi-spl.bin";
+ };
+ u-boot-img {
+ pos = <CONFIG_SPL_PAD_TO>;
+ };
+ };
+};
diff --git a/arch/arm/dts/tegra124-nyan-big-u-boot.dtsi b/arch/arm/dts/tegra124-nyan-big-u-boot.dtsi
new file mode 100644
index 0000000..fff1d78
--- /dev/null
+++ b/arch/arm/dts/tegra124-nyan-big-u-boot.dtsi
@@ -0,0 +1,15 @@
+/*
+ * Copyright (C) 2016 Google, Inc
+ * Written by Simon Glass <sjg@chromium.org>
+ *
+ * SPDX-License-Identifier: GPL-2.0+
+ */
+
+/ {
+ host1x@50000000 {
+ u-boot,dm-pre-reloc;
+ dc@54200000 {
+ u-boot,dm-pre-reloc;
+ };
+ };
+};
diff --git a/arch/arm/dts/tegra124-nyan-big.dts b/arch/arm/dts/tegra124-nyan-big.dts
index 3758395..62f89d0 100644
--- a/arch/arm/dts/tegra124-nyan-big.dts
+++ b/arch/arm/dts/tegra124-nyan-big.dts
@@ -27,9 +27,7 @@
};
host1x@50000000 {
- u-boot,dm-pre-reloc;
dc@54200000 {
- u-boot,dm-pre-reloc;
display-timings {
timing@0 {
clock-frequency = <69500000>;
diff --git a/arch/arm/dts/tegra20-u-boot.dtsi b/arch/arm/dts/tegra20-u-boot.dtsi
new file mode 100644
index 0000000..9b9835d
--- /dev/null
+++ b/arch/arm/dts/tegra20-u-boot.dtsi
@@ -0,0 +1,8 @@
+/ {
+ host1x@50000000 {
+ u-boot,dm-pre-reloc;
+ dc@54200000 {
+ u-boot,dm-pre-reloc;
+ };
+ };
+};
diff --git a/arch/arm/dts/tegra20.dtsi b/arch/arm/dts/tegra20.dtsi
index 84bb1b0..e21ee25 100644
--- a/arch/arm/dts/tegra20.dtsi
+++ b/arch/arm/dts/tegra20.dtsi
@@ -10,7 +10,6 @@
interrupt-parent = <&lic>;
host1x@50000000 {
- u-boot,dm-pre-reloc;
compatible = "nvidia,tegra20-host1x", "simple-bus";
reg = <0x50000000 0x00024000>;
interrupts = <GIC_SPI 65 IRQ_TYPE_LEVEL_HIGH>, /* syncpt */
@@ -78,7 +77,6 @@
};
dc@54200000 {
- u-boot,dm-pre-reloc;
compatible = "nvidia,tegra20-dc";
reg = <0x54200000 0x00040000>;
interrupts = <GIC_SPI 73 IRQ_TYPE_LEVEL_HIGH>;
diff --git a/arch/arm/dts/zynq-7000.dtsi b/arch/arm/dts/zynq-7000.dtsi
index 6df0329..668f54e 100644
--- a/arch/arm/dts/zynq-7000.dtsi
+++ b/arch/arm/dts/zynq-7000.dtsi
@@ -16,7 +16,7 @@
#address-cells = <1>;
#size-cells = <0>;
- cpu@0 {
+ cpu0: cpu@0 {
compatible = "arm,cortex-a9";
device_type = "cpu";
reg = <0>;
@@ -30,7 +30,7 @@
>;
};
- cpu@1 {
+ cpu1: cpu@1 {
compatible = "arm,cortex-a9";
device_type = "cpu";
reg = <1>;
diff --git a/arch/arm/dts/zynqmp.dtsi b/arch/arm/dts/zynqmp.dtsi
index ab5c243..de1f160 100644
--- a/arch/arm/dts/zynqmp.dtsi
+++ b/arch/arm/dts/zynqmp.dtsi
@@ -7,6 +7,7 @@
*
* SPDX-License-Identifier: GPL-2.0+
*/
+
/ {
compatible = "xlnx,zynqmp";
#address-cells = <2>;
diff --git a/arch/arm/include/asm/arch-zynqmp/hardware.h b/arch/arm/include/asm/arch-zynqmp/hardware.h
index 5908c50..041b43c 100644
--- a/arch/arm/include/asm/arch-zynqmp/hardware.h
+++ b/arch/arm/include/asm/arch-zynqmp/hardware.h
@@ -18,8 +18,6 @@
#define ARASAN_NAND_BASEADDR 0xFF100000
-#define ZYNQMP_SATA_BASEADDR 0xFD0C0000
-
#define ZYNQMP_USB0_XHCI_BASEADDR 0xFE200000
#define ZYNQMP_USB1_XHCI_BASEADDR 0xFE300000
diff --git a/arch/arm/mach-mvebu/armada8k/cpu.c b/arch/arm/mach-mvebu/armada8k/cpu.c
index 2719d68..2325e9a 100644
--- a/arch/arm/mach-mvebu/armada8k/cpu.c
+++ b/arch/arm/mach-mvebu/armada8k/cpu.c
@@ -21,7 +21,33 @@ DECLARE_GLOBAL_DATA_PTR;
#define RFU_GLOBAL_SW_RST (MVEBU_RFU_BASE + 0x84)
#define RFU_SW_RESET_OFFSET 0
+/*
+ * The following table includes all memory regions for Armada 7k and
+ * 8k SoCs. The Armada 7k is missing the CP110 slave regions here. Lets
+ * define these regions at the beginning of the struct so that they
+ * can be easier removed later dynamically if an Armada 7k device is detected.
+ * For a detailed memory map, please see doc/mvebu/armada-8k-memory.txt
+ */
+#define ARMADA_7K8K_COMMON_REGIONS_START 2
static struct mm_region mvebu_mem_map[] = {
+ /* Armada 80x0 memory regions include the CP1 (slave) units */
+ {
+ /* SRAM, MMIO regions - CP110 slave region */
+ .phys = 0xf4000000UL,
+ .virt = 0xf4000000UL,
+ .size = 0x02000000UL, /* 32MiB internal registers */
+ .attrs = PTE_BLOCK_MEMTYPE(MT_DEVICE_NGNRNE) |
+ PTE_BLOCK_NON_SHARE
+ },
+ {
+ /* PCI CP1 regions */
+ .phys = 0xfa000000UL,
+ .virt = 0xfa000000UL,
+ .size = 0x04000000UL, /* 64MiB CP110 slave PCI space */
+ .attrs = PTE_BLOCK_MEMTYPE(MT_DEVICE_NGNRNE) |
+ PTE_BLOCK_NON_SHARE
+ },
+ /* Armada 80x0 and 70x0 common memory regions start here */
{
/* RAM */
.phys = 0x0UL,
@@ -47,29 +73,35 @@ static struct mm_region mvebu_mem_map[] = {
PTE_BLOCK_NON_SHARE
},
{
- /* SRAM, MMIO regions - CP110 slave region */
- .phys = 0xf4000000UL,
- .virt = 0xf4000000UL,
- .size = 0x02000000UL, /* 32MiB internal registers */
+ /* PCI CP0 regions */
+ .phys = 0xf6000000UL,
+ .virt = 0xf6000000UL,
+ .size = 0x04000000UL, /* 64MiB CP110 master PCI space */
.attrs = PTE_BLOCK_MEMTYPE(MT_DEVICE_NGNRNE) |
PTE_BLOCK_NON_SHARE
},
{
- /* PCI regions */
- .phys = 0xf8000000UL,
- .virt = 0xf8000000UL,
- .size = 0x08000000UL, /* 128MiB PCI space (master & slave) */
- .attrs = PTE_BLOCK_MEMTYPE(MT_DEVICE_NGNRNE) |
- PTE_BLOCK_NON_SHARE
- },
- {
- /* List terminator */
0,
}
};
struct mm_region *mem_map = mvebu_mem_map;
+void enable_caches(void)
+{
+ /*
+ * Armada 7k is not equipped with the CP110 slave CP. In case this
+ * code runs on an Armada 7k device, lets remove the CP110 slave
+ * entries from the memory mapping by moving the start to the
+ * common regions.
+ */
+ if (of_machine_is_compatible("marvell,armada7040"))
+ mem_map = &mvebu_mem_map[ARMADA_7K8K_COMMON_REGIONS_START];
+
+ icache_enable();
+ dcache_enable();
+}
+
void reset_cpu(ulong ignored)
{
u32 reg;
diff --git a/arch/powerpc/cpu/mpc85xx/fdt.c b/arch/powerpc/cpu/mpc85xx/fdt.c
index 12001f8..67140ba 100644
--- a/arch/powerpc/cpu/mpc85xx/fdt.c
+++ b/arch/powerpc/cpu/mpc85xx/fdt.c
@@ -180,6 +180,39 @@ static inline void ft_fixup_l3cache(void *blob, int off)
#define ft_fixup_l3cache(x, y)
#endif
+#if defined(CONFIG_L2_CACHE) || \
+ defined(CONFIG_BACKSIDE_L2_CACHE) || \
+ defined(CONFIG_SYS_FSL_QORIQ_CHASSIS2)
+static inline void ft_fixup_l2cache_compatible(void *blob, int off)
+{
+ int len;
+ struct cpu_type *cpu = identify_cpu(SVR_SOC_VER(get_svr()));
+
+ if (cpu) {
+ char buf[40];
+
+ if (isdigit(cpu->name[0])) {
+ /* MPCxxxx, where xxxx == 4-digit number */
+ len = sprintf(buf, "fsl,mpc%s-l2-cache-controller",
+ cpu->name) + 1;
+ } else {
+ /* Pxxxx or Txxxx, where xxxx == 4-digit number */
+ len = sprintf(buf, "fsl,%c%s-l2-cache-controller",
+ tolower(cpu->name[0]), cpu->name + 1) + 1;
+ }
+
+ /*
+ * append "cache" after the NULL character that the previous
+ * sprintf wrote. This is how a device tree stores multiple
+ * strings in a property.
+ */
+ len += sprintf(buf + len, "cache") + 1;
+
+ fdt_setprop(blob, off, "compatible", buf, len);
+ }
+}
+#endif
+
#if defined(CONFIG_L2_CACHE)
/* return size in kilobytes */
static inline u32 l2cache_size(void)
@@ -215,9 +248,8 @@ static inline u32 l2cache_size(void)
static inline void ft_fixup_l2cache(void *blob)
{
- int len, off;
+ int off;
u32 *ph;
- struct cpu_type *cpu = identify_cpu(SVR_SOC_VER(get_svr()));
const u32 line_size = 32;
const u32 num_ways = 8;
@@ -243,28 +275,7 @@ static inline void ft_fixup_l2cache(void *blob)
return ;
}
- if (cpu) {
- char buf[40];
-
- if (isdigit(cpu->name[0])) {
- /* MPCxxxx, where xxxx == 4-digit number */
- len = sprintf(buf, "fsl,mpc%s-l2-cache-controller",
- cpu->name) + 1;
- } else {
- /* Pxxxx or Txxxx, where xxxx == 4-digit number */
- len = sprintf(buf, "fsl,%c%s-l2-cache-controller",
- tolower(cpu->name[0]), cpu->name + 1) + 1;
- }
-
- /*
- * append "cache" after the NULL character that the previous
- * sprintf wrote. This is how a device tree stores multiple
- * strings in a property.
- */
- len += sprintf(buf + len, "cache") + 1;
-
- fdt_setprop(blob, off, "compatible", buf, len);
- }
+ ft_fixup_l2cache_compatible(blob, off);
fdt_setprop(blob, off, "cache-unified", NULL, 0);
fdt_setprop_cell(blob, off, "cache-block-size", line_size);
fdt_setprop_cell(blob, off, "cache-size", size);
@@ -337,7 +348,7 @@ static inline void ft_fixup_l2cache(void *blob)
fdt_setprop_cell(blob, l2_off, "cache-size", size);
fdt_setprop_cell(blob, l2_off, "cache-sets", num_sets);
fdt_setprop_cell(blob, l2_off, "cache-level", 2);
- fdt_setprop(blob, l2_off, "compatible", "cache", 6);
+ ft_fixup_l2cache_compatible(blob, l2_off);
}
if (l3_off < 0) {
diff --git a/arch/x86/dts/emulation-u-boot.dtsi b/arch/x86/dts/emulation-u-boot.dtsi
new file mode 100644
index 0000000..56d34af
--- /dev/null
+++ b/arch/x86/dts/emulation-u-boot.dtsi
@@ -0,0 +1,18 @@
+/*
+ * Copyright (C) 2016 Google, Inc
+ * Written by Simon Glass <sjg@chromium.org>
+ *
+ * SPDX-License-Identifier: GPL-2.0+
+ */
+
+#include <u-boot.dtsi>
+
+#ifdef CONFIG_ROM_SIZE
+/ {
+ binman {
+ u-boot-with-ucode-ptr {
+ optional-ucode;
+ };
+ };
+};
+#endif
diff --git a/arch/x86/dts/u-boot.dtsi b/arch/x86/dts/u-boot.dtsi
new file mode 100644
index 0000000..724913f
--- /dev/null
+++ b/arch/x86/dts/u-boot.dtsi
@@ -0,0 +1,62 @@
+/*
+ * Copyright (C) 2016 Google, Inc
+ * Written by Simon Glass <sjg@chromium.org>
+ *
+ * SPDX-License-Identifier: GPL-2.0+
+ */
+
+#include <config.h>
+
+#ifdef CONFIG_ROM_SIZE
+/ {
+ binman {
+ filename = "u-boot.rom";
+ end-at-4gb;
+ sort-by-pos;
+ pad-byte = <0xff>;
+ size = <CONFIG_ROM_SIZE>;
+#ifdef CONFIG_HAVE_INTEL_ME
+ intel-descriptor {
+ };
+ intel-me {
+ };
+#endif
+ u-boot-with-ucode-ptr {
+ pos = <CONFIG_SYS_TEXT_BASE>;
+ };
+ u-boot-dtb-with-ucode {
+ };
+ u-boot-ucode {
+ align = <16>;
+ };
+#ifdef CONFIG_HAVE_MRC
+ intel-mrc {
+ pos = <CONFIG_X86_MRC_ADDR>;
+ };
+#endif
+#ifdef CONFIG_HAVE_FSP
+ intel-fsp {
+ pos = <CONFIG_FSP_ADDR>;
+ };
+#endif
+#ifdef CONFIG_HAVE_CMC
+ intel-cmc {
+ pos = <CONFIG_CMC_ADDR>;
+ };
+#endif
+#ifdef CONFIG_HAVE_VGA_BIOS
+ intel-vga {
+ pos = <CONFIG_VGA_BIOS_ADDR>;
+ };
+#endif
+#ifdef CONFIG_HAVE_REFCODE
+ intel-refcode {
+ pos = <CONFIG_X86_REFCODE_ADDR>;
+ };
+#endif
+ x86-start16 {
+ pos = <CONFIG_SYS_X86_START16>;
+ };
+ };
+};
+#endif
diff --git a/board/intercontrol/digsy_mtc/Makefile b/board/intercontrol/digsy_mtc/Makefile
index fd0c2f9..4d13ead 100644
--- a/board/intercontrol/digsy_mtc/Makefile
+++ b/board/intercontrol/digsy_mtc/Makefile
@@ -4,5 +4,5 @@
# SPDX-License-Identifier: GPL-2.0+
#
-obj-y := digsy_mtc.o cmd_mtc.o
+obj-y := digsy_mtc.o
obj-$(CONFIG_VIDEO) += cmd_disp.o
diff --git a/board/intercontrol/digsy_mtc/cmd_mtc.c b/board/intercontrol/digsy_mtc/cmd_mtc.c
deleted file mode 100644
index f17ec55..0000000
--- a/board/intercontrol/digsy_mtc/cmd_mtc.c
+++ /dev/null
@@ -1,369 +0,0 @@
-/*
- * (C) Copyright 2009
- * Werner Pfister <Pfister_Werner@intercontrol.de>
- *
- * (C) Copyright 2009 Semihalf, Grzegorz Bernacki
- *
- * SPDX-License-Identifier: GPL-2.0+
- */
-
-#include <common.h>
-#include <command.h>
-#include <mpc5xxx.h>
-#include "spi.h"
-#include "cmd_mtc.h"
-
-DECLARE_GLOBAL_DATA_PTR;
-
-static uchar user_out;
-
-static const char *led_names[] = {
- "diag",
- "can1",
- "can2",
- "can3",
- "can4",
- "usbpwr",
- "usbbusy",
- "user1",
- "user2",
- ""
-};
-
-static int msp430_xfer(const void *dout, void *din)
-{
- int err;
-
- err = spi_xfer(NULL, MTC_TRANSFER_SIZE, dout, din,
- SPI_XFER_BEGIN | SPI_XFER_END);
-
- /* The MSP chip needs time to ready itself for the next command */
- udelay(1000);
-
- return err;
-}
-
-static void mtc_calculate_checksum(tx_msp_cmd *packet)
-{
- int i;
- uchar *buff;
-
- buff = (uchar *) packet;
-
- for (i = 0; i < 6; i++)
- packet->cks += buff[i];
-}
-
-static int do_mtc_led(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
-{
- tx_msp_cmd pcmd;
- rx_msp_cmd prx;
- int err;
- int i;
-
- if (argc < 2)
- return cmd_usage(cmdtp);
-
- memset(&pcmd, 0, sizeof(pcmd));
- memset(&prx, 0, sizeof(prx));
-
- pcmd.cmd = CMD_SET_LED;
-
- pcmd.cmd_val0 = 0xff;
- for (i = 0; strlen(led_names[i]) != 0; i++) {
- if (strncmp(argv[1], led_names[i], strlen(led_names[i])) == 0) {
- pcmd.cmd_val0 = i;
- break;
- }
- }
-
- if (pcmd.cmd_val0 == 0xff) {
- printf("Usage:\n%s\n", cmdtp->help);
- return -1;
- }
-
- if (argc >= 3) {
- if (strncmp(argv[2], "red", 3) == 0)
- pcmd.cmd_val1 = 1;
- else if (strncmp(argv[2], "green", 5) == 0)
- pcmd.cmd_val1 = 2;
- else if (strncmp(argv[2], "orange", 6) == 0)
- pcmd.cmd_val1 = 3;
- else
- pcmd.cmd_val1 = 0;
- }
-
- if (argc >= 4)
- pcmd.cmd_val2 = simple_strtol(argv[3], NULL, 10);
- else
- pcmd.cmd_val2 = 0;
-
- pcmd.user_out = user_out;
-
- mtc_calculate_checksum(&pcmd);
- err = msp430_xfer(&pcmd, &prx);
-
- return err;
-}
-
-static int do_mtc_key(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
-{
- tx_msp_cmd pcmd;
- rx_msp_cmd prx;
- int err;
-
- memset(&pcmd, 0, sizeof(pcmd));
- memset(&prx, 0, sizeof(prx));
-
- pcmd.cmd = CMD_GET_VIM;
- pcmd.user_out = user_out;
-
- mtc_calculate_checksum(&pcmd);
- err = msp430_xfer(&pcmd, &prx);
-
- if (!err) {
- /* function returns '0' if key is pressed */
- err = (prx.input & 0x80) ? 0 : 1;
- }
-
- return err;
-}
-
-static int do_mtc_digout(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
-{
- tx_msp_cmd pcmd;
- rx_msp_cmd prx;
- int err;
- uchar channel_mask = 0;
-
- if (argc < 3)
- return cmd_usage(cmdtp);
-
- if (strncmp(argv[1], "on", 2) == 0)
- channel_mask |= 1;
- if (strncmp(argv[2], "on", 2) == 0)
- channel_mask |= 2;
-
- memset(&pcmd, 0, sizeof(pcmd));
- memset(&prx, 0, sizeof(prx));
-
- pcmd.cmd = CMD_GET_VIM;
- pcmd.user_out = channel_mask;
- user_out = channel_mask;
-
- mtc_calculate_checksum(&pcmd);
- err = msp430_xfer(&pcmd, &prx);
-
- return err;
-}
-
-static int do_mtc_digin(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
-{
- tx_msp_cmd pcmd;
- rx_msp_cmd prx;
- int err;
- uchar channel_num = 0;
-
- if (argc < 2)
- return cmd_usage(cmdtp);
-
- channel_num = simple_strtol(argv[1], NULL, 10);
- if ((channel_num != 1) && (channel_num != 2)) {
- printf("mtc digin: invalid parameter - must be '1' or '2'\n");
- return -1;
- }
-
- memset(&pcmd, 0, sizeof(pcmd));
- memset(&prx, 0, sizeof(prx));
-
- pcmd.cmd = CMD_GET_VIM;
- pcmd.user_out = user_out;
-
- mtc_calculate_checksum(&pcmd);
- err = msp430_xfer(&pcmd, &prx);
-
- if (!err) {
- /* function returns '0' when digin is on */
- err = (prx.input & channel_num) ? 0 : 1;
- }
-
- return err;
-}
-
-static int do_mtc_appreg(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
-{
- tx_msp_cmd pcmd;
- rx_msp_cmd prx;
- int err;
- char buf[5];
- uchar appreg;
-
- /* read appreg */
- memset(&pcmd, 0, sizeof(pcmd));
- memset(&prx, 0, sizeof(prx));
-
- pcmd.cmd = CMD_WD_PARA;
- pcmd.cmd_val0 = 5; /* max. Count */
- pcmd.cmd_val1 = 5; /* max. Time */
- pcmd.cmd_val2 = 0; /* =0 means read appreg */
- pcmd.user_out = user_out;
-
- mtc_calculate_checksum(&pcmd);
- err = msp430_xfer(&pcmd, &prx);
-
- /* on success decide between read or write */
- if (!err) {
- if (argc == 2) {
- appreg = simple_strtol(argv[1], NULL, 10);
- if (appreg == 0) {
- printf("mtc appreg: invalid parameter - "
- "must be between 1 and 255\n");
- return -1;
- }
- memset(&pcmd, 0, sizeof(pcmd));
- pcmd.cmd = CMD_WD_PARA;
- pcmd.cmd_val0 = prx.ack3; /* max. Count */
- pcmd.cmd_val1 = prx.ack0; /* max. Time */
- pcmd.cmd_val2 = appreg; /* !=0 means write appreg */
- pcmd.user_out = user_out;
- memset(&prx, 0, sizeof(prx));
-
- mtc_calculate_checksum(&pcmd);
- err = msp430_xfer(&pcmd, &prx);
- } else {
- sprintf(buf, "%d", prx.ack2);
- setenv("appreg", buf);
- }
- }
-
- return err;
-}
-
-static int do_mtc_version(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
-{
- tx_msp_cmd pcmd;
- rx_msp_cmd prx;
- int err;
-
- memset(&pcmd, 0, sizeof(pcmd));
- memset(&prx, 0, sizeof(prx));
-
- pcmd.cmd = CMD_FW_VERSION;
- pcmd.user_out = user_out;
-
- mtc_calculate_checksum(&pcmd);
- err = msp430_xfer(&pcmd, &prx);
-
- if (!err) {
- printf("FW V%d.%d.%d / HW %d\n",
- prx.ack0, prx.ack1, prx.ack3, prx.ack2);
- }
-
- return err;
-}
-
-static int do_mtc_state(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
-{
- tx_msp_cmd pcmd;
- rx_msp_cmd prx;
- int err;
-
- memset(&pcmd, 0, sizeof(pcmd));
- memset(&prx, 0, sizeof(prx));
-
- pcmd.cmd = CMD_WD_WDSTATE;
- pcmd.cmd_val2 = 1;
- pcmd.user_out = user_out;
-
- mtc_calculate_checksum(&pcmd);
- err = msp430_xfer(&pcmd, &prx);
-
- if (!err) {
- printf("State %02Xh\n", prx.state);
- printf("Input %02Xh\n", prx.input);
- printf("UserWD %02Xh\n", prx.ack2);
- printf("Sys WD %02Xh\n", prx.ack3);
- printf("WD Timout %02Xh\n", prx.ack0);
- printf("eSysState %02Xh\n", prx.ack1);
- }
-
- return err;
-}
-
-static int do_mtc_help(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]);
-
-cmd_tbl_t cmd_mtc_sub[] = {
- U_BOOT_CMD_MKENT(led, 3, 1, do_mtc_led,
- "set state of leds",
- "[ledname] [state] [blink]\n"
- " - lednames: diag can1 can2 can3 can4 usbpwr usbbusy user1 user2\n"
- " - state: off red green orange\n"
- " - blink: blink interval in 100ms steps (1 - 10; 0 = static)\n"),
- U_BOOT_CMD_MKENT(key, 0, 1, do_mtc_key,
- "returns state of user key", ""),
- U_BOOT_CMD_MKENT(version, 0, 1, do_mtc_version,
- "returns firmware version of supervisor uC", ""),
- U_BOOT_CMD_MKENT(appreg, 1, 1, do_mtc_appreg,
- "reads or writes appreg value and stores in environment "
- "variable 'appreg'",
- "[value] - value (1 - 255) to write to appreg"),
- U_BOOT_CMD_MKENT(digin, 1, 1, do_mtc_digin,
- "returns state of digital input",
- "<channel_num> - get state of digital input (1 or 2)\n"),
- U_BOOT_CMD_MKENT(digout, 2, 1, do_mtc_digout,
- "sets digital outputs",
- "<on|off> <on|off>- set state of digital output 1 and 2\n"),
- U_BOOT_CMD_MKENT(state, 0, 1, do_mtc_state,
- "displays state", ""),
- U_BOOT_CMD_MKENT(help, 4, 1, do_mtc_help, "get help",
- "[command] - get help for command\n"),
-};
-
-static int do_mtc_help(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
-{
- extern int _do_help(cmd_tbl_t *cmd_start, int cmd_items,
- cmd_tbl_t *cmdtp, int flag,
- int argc, char * const argv[]);
-#ifdef CONFIG_SYS_LONGHELP
- puts("mtc ");
-#endif
- return _do_help(&cmd_mtc_sub[0],
- ARRAY_SIZE(cmd_mtc_sub), cmdtp, flag, argc, argv);
-}
-
-int cmd_mtc(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
-{
- cmd_tbl_t *c;
- int err = 0;
-
- c = find_cmd_tbl(argv[1], &cmd_mtc_sub[0], ARRAY_SIZE(cmd_mtc_sub));
- if (c) {
- argc--;
- argv++;
- return c->cmd(c, flag, argc, argv);
- } else {
- /* Unrecognized command */
- return cmd_usage(cmdtp);
- }
-
- return err;
-}
-
-U_BOOT_CMD(mtc, 5, 1, cmd_mtc,
- "special commands for digsyMTC",
- "[subcommand] [args...]\n"
- "Subcommands list:\n"
- "led [ledname] [state] [blink] - set state of leds\n"
- " [ledname]: diag can1 can2 can3 can4 usbpwr usbbusy user1 user2\n"
- " [state]: off red green orange\n"
- " [blink]: blink interval in 100ms steps (1 - 10; 0 = static)\n"
- "key - returns state of user key\n"
- "version - returns firmware version of supervisor uC\n"
- "appreg [value] - reads (in environment variable 'appreg') or writes"
- " appreg value\n"
- " [value]: value (1 - 255) to write to appreg\n"
- "digin [channel] - returns state of digital input (1 or 2)\n"
- "digout <on|off> <on|off> - sets state of two digital outputs\n"
- "state - displays state\n"
- "help [subcommand] - get help for subcommand\n"
-);
diff --git a/board/intercontrol/digsy_mtc/cmd_mtc.h b/board/intercontrol/digsy_mtc/cmd_mtc.h
deleted file mode 100644
index 4493433..0000000
--- a/board/intercontrol/digsy_mtc/cmd_mtc.h
+++ /dev/null
@@ -1,45 +0,0 @@
-/*
- * (C) Copyright 2009
- * Werner Pfister <Pfister_Werner@intercontrol.de>
- *
- * (C) Copyright 2009 Semihalf, Grzegorz Bernacki
- *
- * SPDX-License-Identifier: GPL-2.0+
- */
-
-#ifndef CMD_MTC_H
-#define CMD_MTC_H
-
-#define CMD_WD_PARA 0x02
-#define CMD_WD_WDSTATE 0x04
-#define CMD_FW_VERSION 0x10
-#define CMD_GET_VIM 0x30
-#define CMD_SET_LED 0x40
-
-typedef struct {
- u8 cmd;
- u8 sys_in;
- u8 cmd_val0;
- u8 cmd_val1;
- u8 cmd_val2;
- u8 user_out;
- u8 cks;
- u8 dummy1;
- u8 dummy2;
-} tx_msp_cmd;
-
-typedef struct {
- u8 input;
- u8 state;
- u8 ack2;
- u8 ack3;
- u8 ack0;
- u8 ack1;
- u8 ack;
- u8 dummy;
- u8 cks;
-} rx_msp_cmd;
-
-#define MTC_TRANSFER_SIZE (sizeof(tx_msp_cmd) * 8)
-
-#endif
diff --git a/board/intercontrol/digsy_mtc/digsy_mtc.c b/board/intercontrol/digsy_mtc/digsy_mtc.c
index 2e52d51..37eb6c7 100644
--- a/board/intercontrol/digsy_mtc/digsy_mtc.c
+++ b/board/intercontrol/digsy_mtc/digsy_mtc.c
@@ -250,9 +250,6 @@ static inline void exbo_hw_init(void) {}
int board_early_init_r(void)
{
-#ifdef CONFIG_MPC52XX_SPI
- struct mpc5xxx_gpt *gpt = (struct mpc5xxx_gpt*)MPC5XXX_GPT;
-#endif
/*
* Now, when we are in RAM, enable flash write access for detection
* process. Note that CS_BOOT cannot be cleared when executing in
@@ -269,12 +266,6 @@ int board_early_init_r(void)
/* Low level USB init, required for proper kernel operation */
usb_cpu_init();
#endif
-#ifdef CONFIG_MPC52XX_SPI
- /* GPT 6 Output Enable */
- out_be32(&gpt[6].emsr, 0x00000034);
- /* GPT 7 Output Enable */
- out_be32(&gpt[7].emsr, 0x00000034);
-#endif
return (0);
}
diff --git a/board/xilinx/zynq/board.c b/board/xilinx/zynq/board.c
index 2c86940..5cd9bbf 100644
--- a/board/xilinx/zynq/board.c
+++ b/board/xilinx/zynq/board.c
@@ -124,121 +124,15 @@ int zynq_board_read_rom_ethaddr(unsigned char *ethaddr)
}
#if !defined(CONFIG_SYS_SDRAM_BASE) && !defined(CONFIG_SYS_SDRAM_SIZE)
-/*
- * fdt_get_reg - Fill buffer by information from DT
- */
-static phys_size_t fdt_get_reg(const void *fdt, int nodeoffset, void *buf,
- const u32 *cell, int n)
-{
- int i = 0, b, banks;
- int parent_offset = fdt_parent_offset(fdt, nodeoffset);
- int address_cells = fdt_address_cells(fdt, parent_offset);
- int size_cells = fdt_size_cells(fdt, parent_offset);
- char *p = buf;
- u64 val;
- u64 vals;
-
- debug("%s: addr_cells=%x, size_cell=%x, buf=%p, cell=%p\n",
- __func__, address_cells, size_cells, buf, cell);
-
- /* Check memory bank setup */
- banks = n % (address_cells + size_cells);
- if (banks)
- panic("Incorrect memory setup cells=%d, ac=%d, sc=%d\n",
- n, address_cells, size_cells);
-
- banks = n / (address_cells + size_cells);
-
- for (b = 0; b < banks; b++) {
- debug("%s: Bank #%d:\n", __func__, b);
- if (address_cells == 2) {
- val = cell[i + 1];
- val <<= 32;
- val |= cell[i];
- val = fdt64_to_cpu(val);
- debug("%s: addr64=%llx, ptr=%p, cell=%p\n",
- __func__, val, p, &cell[i]);
- *(phys_addr_t *)p = val;
- } else {
- debug("%s: addr32=%x, ptr=%p\n",
- __func__, fdt32_to_cpu(cell[i]), p);
- *(phys_addr_t *)p = fdt32_to_cpu(cell[i]);
- }
- p += sizeof(phys_addr_t);
- i += address_cells;
-
- debug("%s: pa=%p, i=%x, size=%zu\n", __func__, p, i,
- sizeof(phys_addr_t));
-
- if (size_cells == 2) {
- vals = cell[i + 1];
- vals <<= 32;
- vals |= cell[i];
- vals = fdt64_to_cpu(vals);
-
- debug("%s: size64=%llx, ptr=%p, cell=%p\n",
- __func__, vals, p, &cell[i]);
- *(phys_size_t *)p = vals;
- } else {
- debug("%s: size32=%x, ptr=%p\n",
- __func__, fdt32_to_cpu(cell[i]), p);
- *(phys_size_t *)p = fdt32_to_cpu(cell[i]);
- }
- p += sizeof(phys_size_t);
- i += size_cells;
-
- debug("%s: ps=%p, i=%x, size=%zu\n",
- __func__, p, i, sizeof(phys_size_t));
- }
-
- /* Return the first address size */
- return *(phys_size_t *)((char *)buf + sizeof(phys_addr_t));
-}
-
-#define FDT_REG_SIZE sizeof(u32)
-/* Temp location for sharing data for storing */
-/* Up to 64-bit address + 64-bit size */
-static u8 tmp[CONFIG_NR_DRAM_BANKS * 16];
-
void dram_init_banksize(void)
{
- int bank;
-
- memcpy(&gd->bd->bi_dram[0], &tmp, sizeof(tmp));
-
- for (bank = 0; bank < CONFIG_NR_DRAM_BANKS; bank++) {
- debug("Bank #%d: start %llx\n", bank,
- (unsigned long long)gd->bd->bi_dram[bank].start);
- debug("Bank #%d: size %llx\n", bank,
- (unsigned long long)gd->bd->bi_dram[bank].size);
- }
+ fdtdec_setup_memory_banksize();
}
int dram_init(void)
{
- int node, len;
- const void *blob = gd->fdt_blob;
- const u32 *cell;
-
- memset(&tmp, 0, sizeof(tmp));
-
- /* find or create "/memory" node. */
- node = fdt_subnode_offset(blob, 0, "memory");
- if (node < 0) {
- printf("%s: Can't get memory node\n", __func__);
- return node;
- }
-
- /* Get pointer to cells and lenght of it */
- cell = fdt_getprop(blob, node, "reg", &len);
- if (!cell) {
- printf("%s: Can't get reg property\n", __func__);
- return -1;
- }
-
- gd->ram_size = fdt_get_reg(blob, node, &tmp, cell, len / FDT_REG_SIZE);
-
- debug("%s: Initial DRAM size %llx\n", __func__, (u64)gd->ram_size);
+ if (fdtdec_setup_memory_size() != 0)
+ return -EINVAL;
zynq_ddrc_init();
diff --git a/board/xilinx/zynqmp/zynqmp.c b/board/xilinx/zynqmp/zynqmp.c
index cef1f6a..4e5871b 100644
--- a/board/xilinx/zynqmp/zynqmp.c
+++ b/board/xilinx/zynqmp/zynqmp.c
@@ -180,121 +180,15 @@ int zynq_board_read_rom_ethaddr(unsigned char *ethaddr)
}
#if !defined(CONFIG_SYS_SDRAM_BASE) && !defined(CONFIG_SYS_SDRAM_SIZE)
-/*
- * fdt_get_reg - Fill buffer by information from DT
- */
-static phys_size_t fdt_get_reg(const void *fdt, int nodeoffset, void *buf,
- const u32 *cell, int n)
-{
- int i = 0, b, banks;
- int parent_offset = fdt_parent_offset(fdt, nodeoffset);
- int address_cells = fdt_address_cells(fdt, parent_offset);
- int size_cells = fdt_size_cells(fdt, parent_offset);
- char *p = buf;
- u64 val;
- u64 vals;
-
- debug("%s: addr_cells=%x, size_cell=%x, buf=%p, cell=%p\n",
- __func__, address_cells, size_cells, buf, cell);
-
- /* Check memory bank setup */
- banks = n % (address_cells + size_cells);
- if (banks)
- panic("Incorrect memory setup cells=%d, ac=%d, sc=%d\n",
- n, address_cells, size_cells);
-
- banks = n / (address_cells + size_cells);
-
- for (b = 0; b < banks; b++) {
- debug("%s: Bank #%d:\n", __func__, b);
- if (address_cells == 2) {
- val = cell[i + 1];
- val <<= 32;
- val |= cell[i];
- val = fdt64_to_cpu(val);
- debug("%s: addr64=%llx, ptr=%p, cell=%p\n",
- __func__, val, p, &cell[i]);
- *(phys_addr_t *)p = val;
- } else {
- debug("%s: addr32=%x, ptr=%p\n",
- __func__, fdt32_to_cpu(cell[i]), p);
- *(phys_addr_t *)p = fdt32_to_cpu(cell[i]);
- }
- p += sizeof(phys_addr_t);
- i += address_cells;
-
- debug("%s: pa=%p, i=%x, size=%zu\n", __func__, p, i,
- sizeof(phys_addr_t));
-
- if (size_cells == 2) {
- vals = cell[i + 1];
- vals <<= 32;
- vals |= cell[i];
- vals = fdt64_to_cpu(vals);
-
- debug("%s: size64=%llx, ptr=%p, cell=%p\n",
- __func__, vals, p, &cell[i]);
- *(phys_size_t *)p = vals;
- } else {
- debug("%s: size32=%x, ptr=%p\n",
- __func__, fdt32_to_cpu(cell[i]), p);
- *(phys_size_t *)p = fdt32_to_cpu(cell[i]);
- }
- p += sizeof(phys_size_t);
- i += size_cells;
-
- debug("%s: ps=%p, i=%x, size=%zu\n",
- __func__, p, i, sizeof(phys_size_t));
- }
-
- /* Return the first address size */
- return *(phys_size_t *)((char *)buf + sizeof(phys_addr_t));
-}
-
-#define FDT_REG_SIZE sizeof(u32)
-/* Temp location for sharing data for storing */
-/* Up to 64-bit address + 64-bit size */
-static u8 tmp[CONFIG_NR_DRAM_BANKS * 16];
-
void dram_init_banksize(void)
{
- int bank;
-
- memcpy(&gd->bd->bi_dram[0], &tmp, sizeof(tmp));
-
- for (bank = 0; bank < CONFIG_NR_DRAM_BANKS; bank++) {
- debug("Bank #%d: start %llx\n", bank,
- (unsigned long long)gd->bd->bi_dram[bank].start);
- debug("Bank #%d: size %llx\n", bank,
- (unsigned long long)gd->bd->bi_dram[bank].size);
- }
+ fdtdec_setup_memory_banksize();
}
int dram_init(void)
{
- int node, len;
- const void *blob = gd->fdt_blob;
- const u32 *cell;
-
- memset(&tmp, 0, sizeof(tmp));
-
- /* find or create "/memory" node. */
- node = fdt_subnode_offset(blob, 0, "memory");
- if (node < 0) {
- printf("%s: Can't get memory node\n", __func__);
- return node;
- }
-
- /* Get pointer to cells and lenght of it */
- cell = fdt_getprop(blob, node, "reg", &len);
- if (!cell) {
- printf("%s: Can't get reg property\n", __func__);
- return -1;
- }
-
- gd->ram_size = fdt_get_reg(blob, node, &tmp, cell, len / FDT_REG_SIZE);
-
- debug("%s: Initial DRAM size %llx\n", __func__, (u64)gd->ram_size);
+ if (fdtdec_setup_memory_size() != 0)
+ return -EINVAL;
return 0;
}
@@ -311,17 +205,6 @@ void reset_cpu(ulong addr)
{
}
-#ifdef CONFIG_SCSI_AHCI_PLAT
-void scsi_init(void)
-{
-#if defined(CONFIG_SATA_CEVA)
- init_sata(0);
-#endif
- ahci_init((void __iomem *)ZYNQMP_SATA_BASEADDR);
- scsi_scan(1);
-}
-#endif
-
int board_late_init(void)
{
u32 reg = 0;
diff --git a/common/board_r.c b/common/board_r.c
index 5496f45..a373352 100644
--- a/common/board_r.c
+++ b/common/board_r.c
@@ -620,7 +620,7 @@ static int initr_ambapp_print(void)
}
#endif
-#if defined(CONFIG_SCSI)
+#if defined(CONFIG_SCSI) && !defined(CONFIG_DM_SCSI)
static int initr_scsi(void)
{
puts("SCSI: ");
@@ -923,7 +923,7 @@ init_fnc_t init_sequence_r[] = {
initr_ambapp_print,
#endif
#endif
-#ifdef CONFIG_SCSI
+#if defined(CONFIG_SCSI) && !defined(CONFIG_DM_SCSI)
INIT_FUNC_WATCHDOG_RESET
initr_scsi,
#endif
diff --git a/common/image.c b/common/image.c
index bd07e86..909dbed 100644
--- a/common/image.c
+++ b/common/image.c
@@ -1375,11 +1375,10 @@ int boot_get_fpga(int argc, char * const argv[], bootm_headers_t *images,
img_len, BIT_PARTIAL);
}
- printf(" Programming %s bitstream... ", name);
if (err)
- printf("failed\n");
- else
- printf("OK\n");
+ return err;
+
+ printf(" Programming %s bitstream... OK\n", name);
break;
default:
printf("The given image format is not supported (corrupt?)\n");
diff --git a/common/miiphyutil.c b/common/miiphyutil.c
index aca18db..8eb0f76 100644
--- a/common/miiphyutil.c
+++ b/common/miiphyutil.c
@@ -107,6 +107,18 @@ int mdio_register(struct mii_dev *bus)
return 0;
}
+int mdio_register_seq(struct mii_dev *bus, int seq)
+{
+ int ret;
+
+ /* Setup a unique name for each mdio bus */
+ ret = snprintf(bus->name, MDIO_NAME_LEN, "eth%d", seq);
+ if (ret < 0)
+ return ret;
+
+ return mdio_register(bus);
+}
+
int mdio_unregister(struct mii_dev *bus)
{
if (!bus)
diff --git a/common/scsi.c b/common/scsi.c
index 04add62..e7efa5a 100644
--- a/common/scsi.c
+++ b/common/scsi.c
@@ -10,7 +10,10 @@
#include <inttypes.h>
#include <pci.h>
#include <scsi.h>
+#include <dm/device-internal.h>
+#include <dm/uclass-internal.h>
+#if !defined(CONFIG_DM_SCSI)
#ifdef CONFIG_SCSI_DEV_LIST
#define SCSI_DEV_LIST CONFIG_SCSI_DEV_LIST
#else
@@ -31,6 +34,7 @@
#endif
#define SCSI_DEV_LIST {SCSI_VEND_ID, SCSI_DEV_ID}
#endif
+#endif
#if defined(CONFIG_PCI) && !defined(CONFIG_SCSI_AHCI_PLAT)
const struct pci_device_id scsi_device_list[] = { SCSI_DEV_LIST };
@@ -39,11 +43,13 @@ static ccb tempccb; /* temporary scsi command buffer */
static unsigned char tempbuff[512]; /* temporary data buffer */
+#if !defined(CONFIG_DM_SCSI)
static int scsi_max_devs; /* number of highest available scsi device */
static int scsi_curr_dev; /* current device */
static struct blk_desc scsi_dev_desc[CONFIG_SYS_SCSI_MAX_DEVICE];
+#endif
/* almost the maximum amount of the scsi_ext command.. */
#define SCSI_MAX_READ_BLK 0xFFFF
@@ -444,6 +450,7 @@ static void scsi_init_dev_desc_priv(struct blk_desc *dev_desc)
#endif
}
+#if !defined(CONFIG_DM_SCSI)
/**
* scsi_init_dev_desc - initialize all SCSI specific blk_desc properties
*
@@ -460,6 +467,7 @@ static void scsi_init_dev_desc(struct blk_desc *dev_desc, int devnum)
scsi_init_dev_desc_priv(dev_desc);
}
+#endif
/**
* scsi_detect_dev - Detect scsi device
@@ -540,6 +548,73 @@ removable:
* (re)-scan the scsi bus and reports scsi device info
* to the user if mode = 1
*/
+#if defined(CONFIG_DM_SCSI)
+int scsi_scan(int mode)
+{
+ unsigned char i, lun;
+ struct uclass *uc;
+ struct udevice *dev; /* SCSI controller */
+ int ret;
+
+ if (mode == 1)
+ printf("scanning bus for devices...\n");
+
+ ret = uclass_get(UCLASS_SCSI, &uc);
+ if (ret)
+ return ret;
+
+ uclass_foreach_dev(dev, uc) {
+ struct scsi_platdata *plat; /* scsi controller platdata */
+
+ /* probe SCSI controller driver */
+ ret = device_probe(dev);
+ if (ret)
+ return ret;
+
+ /* Get controller platdata */
+ plat = dev_get_platdata(dev);
+
+ for (i = 0; i < plat->max_id; i++) {
+ for (lun = 0; lun < plat->max_lun; lun++) {
+ struct udevice *bdev; /* block device */
+ /* block device description */
+ struct blk_desc *bdesc;
+ char str[10];
+
+ /*
+ * Create only one block device and do detection
+ * to make sure that there won't be a lot of
+ * block devices created
+ */
+ snprintf(str, sizeof(str), "id%dlun%d", i, lun);
+ ret = blk_create_devicef(dev, "scsi_blk",
+ str, IF_TYPE_SCSI,
+ -1, 0, 0, &bdev);
+ if (ret) {
+ debug("Can't create device\n");
+ return ret;
+ }
+ bdesc = dev_get_uclass_platdata(bdev);
+
+ scsi_init_dev_desc_priv(bdesc);
+ bdesc->lun = lun;
+ ret = scsi_detect_dev(i, bdesc);
+ if (ret) {
+ device_unbind(bdev);
+ continue;
+ }
+
+ if (mode == 1) {
+ printf(" Device %d: ", 0);
+ dev_print(bdesc);
+ } /* if mode */
+ } /* next LUN */
+ }
+ }
+
+ return 0;
+}
+#else
int scsi_scan(int mode)
{
unsigned char i, lun;
@@ -576,6 +651,7 @@ int scsi_scan(int mode)
#endif
return 0;
}
+#endif
#ifdef CONFIG_BLK
static const struct blk_ops scsi_blk_ops = {
diff --git a/configs/digsy_mtc_RAMBOOT_defconfig b/configs/digsy_mtc_RAMBOOT_defconfig
index 71fa0b7..66c3393 100644
--- a/configs/digsy_mtc_RAMBOOT_defconfig
+++ b/configs/digsy_mtc_RAMBOOT_defconfig
@@ -13,7 +13,6 @@ CONFIG_AUTOBOOT_PROMPT="Press SPACE to abort autoboot in %d seconds\n"
CONFIG_AUTOBOOT_DELAY_STR="d"
CONFIG_AUTOBOOT_STOP_STR=" "
CONFIG_LOOPW=y
-CONFIG_CMD_SPI=y
CONFIG_CMD_I2C=y
CONFIG_CMD_USB=y
# CONFIG_CMD_SETEXPR is not set
diff --git a/configs/digsy_mtc_defconfig b/configs/digsy_mtc_defconfig
index 20491a4..daf08ce 100644
--- a/configs/digsy_mtc_defconfig
+++ b/configs/digsy_mtc_defconfig
@@ -11,7 +11,6 @@ CONFIG_AUTOBOOT_KEYED=y
CONFIG_AUTOBOOT_PROMPT="autoboot in %d seconds\n"
CONFIG_AUTOBOOT_DELAY_STR=" "
CONFIG_LOOPW=y
-CONFIG_CMD_SPI=y
CONFIG_CMD_I2C=y
CONFIG_CMD_USB=y
# CONFIG_CMD_SETEXPR is not set
diff --git a/configs/digsy_mtc_rev5_RAMBOOT_defconfig b/configs/digsy_mtc_rev5_RAMBOOT_defconfig
index 0db5f92..e55653b 100644
--- a/configs/digsy_mtc_rev5_RAMBOOT_defconfig
+++ b/configs/digsy_mtc_rev5_RAMBOOT_defconfig
@@ -13,7 +13,6 @@ CONFIG_AUTOBOOT_PROMPT="Press SPACE to abort autoboot in %d seconds\n"
CONFIG_AUTOBOOT_DELAY_STR="d"
CONFIG_AUTOBOOT_STOP_STR=" "
CONFIG_LOOPW=y
-CONFIG_CMD_SPI=y
CONFIG_CMD_I2C=y
CONFIG_CMD_USB=y
# CONFIG_CMD_SETEXPR is not set
diff --git a/configs/digsy_mtc_rev5_defconfig b/configs/digsy_mtc_rev5_defconfig
index 713fa3d..f1f5f2e 100644
--- a/configs/digsy_mtc_rev5_defconfig
+++ b/configs/digsy_mtc_rev5_defconfig
@@ -13,7 +13,6 @@ CONFIG_AUTOBOOT_PROMPT="Press SPACE to abort autoboot in %d seconds\n"
CONFIG_AUTOBOOT_DELAY_STR="d"
CONFIG_AUTOBOOT_STOP_STR=" "
CONFIG_LOOPW=y
-CONFIG_CMD_SPI=y
CONFIG_CMD_I2C=y
CONFIG_CMD_USB=y
# CONFIG_CMD_SETEXPR is not set
diff --git a/configs/gplugd_defconfig b/configs/gplugd_defconfig
index 59c9fdf..3d98f8d 100644
--- a/configs/gplugd_defconfig
+++ b/configs/gplugd_defconfig
@@ -4,9 +4,7 @@ CONFIG_IDENT_STRING="\nMarvell-gplugD"
CONFIG_BOOTDELAY=3
# CONFIG_DISPLAY_BOARDINFO is not set
# CONFIG_CMD_IMLS is not set
-CONFIG_CMD_ASKENV=y
# CONFIG_CMD_FLASH is not set
-CONFIG_CMD_SF=y
CONFIG_CMD_I2C=y
CONFIG_CMD_USB=y
# CONFIG_CMD_FPGA is not set
@@ -16,9 +14,6 @@ CONFIG_CMD_MII=y
CONFIG_CMD_PING=y
CONFIG_CMD_EXT2=y
CONFIG_CMD_FAT=y
-CONFIG_SPI_FLASH=y
-CONFIG_SPI_FLASH_ATMEL=y
-CONFIG_SPI_FLASH_MACRONIX=y
CONFIG_SYS_NS16550=y
CONFIG_USB=y
CONFIG_USB_STORAGE=y
diff --git a/configs/s5p_goni_defconfig b/configs/s5p_goni_defconfig
index 4cbf022..aa61ef4 100644
--- a/configs/s5p_goni_defconfig
+++ b/configs/s5p_goni_defconfig
@@ -29,3 +29,6 @@ CONFIG_USB_GADGET_DOWNLOAD=y
CONFIG_G_DNL_MANUFACTURER="Samsung"
CONFIG_G_DNL_VENDOR_NUM=0x04e8
CONFIG_G_DNL_PRODUCT_NUM=0x6601
+CONFIG_DM_PMIC=y
+CONFIG_DM_PMIC_MAX8998=y
+CONFIG_DM_I2C_GPIO=y
diff --git a/configs/xilinx_zynqmp_ep_defconfig b/configs/xilinx_zynqmp_ep_defconfig
index f261e22..b223e11 100644
--- a/configs/xilinx_zynqmp_ep_defconfig
+++ b/configs/xilinx_zynqmp_ep_defconfig
@@ -42,6 +42,8 @@ CONFIG_OF_EMBED=y
CONFIG_NET_RANDOM_ETHADDR=y
CONFIG_SPL_DM=y
CONFIG_SPL_DM_SEQ_ALIAS=y
+CONFIG_DM_SCSI=y
+CONFIG_SATA_CEVA=y
CONFIG_DFU_RAM=y
CONFIG_FPGA_XILINX=y
CONFIG_FPGA_ZYNQMPPL=y
diff --git a/configs/xilinx_zynqmp_zcu102_defconfig b/configs/xilinx_zynqmp_zcu102_defconfig
index 021e0ff..9f2df49 100644
--- a/configs/xilinx_zynqmp_zcu102_defconfig
+++ b/configs/xilinx_zynqmp_zcu102_defconfig
@@ -34,6 +34,8 @@ CONFIG_OF_EMBED=y
CONFIG_NET_RANDOM_ETHADDR=y
CONFIG_SPL_DM=y
CONFIG_SPL_DM_SEQ_ALIAS=y
+CONFIG_DM_SCSI=y
+CONFIG_SATA_CEVA=y
CONFIG_DFU_RAM=y
CONFIG_FPGA_XILINX=y
CONFIG_FPGA_ZYNQMPPL=y
diff --git a/configs/xilinx_zynqmp_zcu102_revB_defconfig b/configs/xilinx_zynqmp_zcu102_revB_defconfig
index 34062bd..b2b1720 100644
--- a/configs/xilinx_zynqmp_zcu102_revB_defconfig
+++ b/configs/xilinx_zynqmp_zcu102_revB_defconfig
@@ -34,6 +34,8 @@ CONFIG_OF_EMBED=y
CONFIG_NET_RANDOM_ETHADDR=y
CONFIG_SPL_DM=y
CONFIG_SPL_DM_SEQ_ALIAS=y
+CONFIG_DM_SCSI=y
+CONFIG_SATA_CEVA=y
CONFIG_DFU_RAM=y
CONFIG_FPGA_XILINX=y
CONFIG_FPGA_ZYNQMPPL=y
diff --git a/doc/mvebu/armada-8k-memory.txt b/doc/mvebu/armada-8k-memory.txt
new file mode 100644
index 0000000..064518e
--- /dev/null
+++ b/doc/mvebu/armada-8k-memory.txt
@@ -0,0 +1,56 @@
+ Memory Layout on Armada-8k SoC's
+ ================================
+
+The below desribes the physical memory layout for Marvell's Armada-8k SoC's.
+
+This assumes that the SoC includes Dual CP configuration, in case the flavor is using
+a single CP configuration, then all secondary-CP mappings are invalid.
+
+All "Reserved" areas below, are kept for future usage.
+
+Start End Use
+--------------------------------------------------------------------------
+0x00000000 0xEFFFFFFF DRAM
+
+0xF0000000 0xF0FFFFFF AP Internal registers space
+
+0xF1000000 0xF1FFFFFF Reserved.
+
+0xF2000000 0xF3FFFFFF CP-0 Internal (configuration) registers
+ space.
+
+0xF4000000 0xF5FFFFFF CP-1 Internal (configuration) registers
+ space.
+
+0xF6000000 0xF6FFFFFF CP-0 / PCIe#0 Memory space.
+
+0xF7000000 0xF7FFFFFF CP-0 / PCIe#1 Memory space.
+
+0xF8000000 0xF8FFFFFF CP-0 / PCIe#2 Memory space.
+
+0xF9000000 0xF900FFFF CP-0 / PCIe#0 IO space.
+
+0xF9010000 0xF901FFFF CP-0 / PCIe#1 IO space.
+
+0xF9020000 0xF902FFFF CP-0 / PCIe#2 IO space.
+
+0xF9030000 0xF9FFFFFF Reserved.
+
+0xFA000000 0xFAFFFFFF CP-1 / PCIe#0 Memory space.
+
+0xFB000000 0xFBFFFFFF CP-1 / PCIe#1 Memory space.
+
+0xFC000000 0xFCFFFFFF CP-1 / PCIe#2 Memory space.
+
+0xFD000000 0xFD00FFFF CP-1 / PCIe#0 IO space.
+
+0xFD010000 0xFD01FFFF CP-1 / PCIe#1 IO space.
+
+0xFD020000 0xFD02FFFF CP-1 / PCIe#2 IO space.
+
+0xFD030000 0xFFEFFFFF Reserved.
+
+0xFFF00000 0xFFFFFFFF Bootrom
+
+0x100000000 <DRAM Size>-1 DRAM
+
diff --git a/drivers/block/Kconfig b/drivers/block/Kconfig
index fe5aa07..88e66e2 100644
--- a/drivers/block/Kconfig
+++ b/drivers/block/Kconfig
@@ -19,6 +19,15 @@ config AHCI
operations at present. The block device interface has not been converted
to driver model.
+config DM_SCSI
+ bool "Support SCSI controllers with driver model"
+ depends on BLK
+ help
+ This option enables the SCSI (Small Computer System Interface) uclass
+ which supports SCSI and SATA HDDs. For every device configuration
+ (IDs/LUNs) a block device is created with RAW read/write and
+ filesystem support.
+
config BLOCK_CACHE
bool "Use block device cache"
default n
@@ -27,3 +36,16 @@ config BLOCK_CACHE
This is most useful when accessing filesystems under U-Boot since
it will prevent repeated reads from directory structures and other
filesystem data structures.
+
+menu "SATA/SCSI device support"
+
+config SATA_CEVA
+ bool "Ceva Sata controller"
+ depends on AHCI
+ depends on DM_SCSI
+ help
+ This option enables Ceva Sata controller hard IP available on Xilinx
+ ZynqMP. Support up to 2 external devices. Complient with SATA 3.1 and
+ AHCI 1.3 specifications with hot-plug detect feature.
+
+endmenu
diff --git a/drivers/block/Makefile b/drivers/block/Makefile
index 436b79f..a72feec 100644
--- a/drivers/block/Makefile
+++ b/drivers/block/Makefile
@@ -12,6 +12,7 @@ obj-y += blk_legacy.o
endif
obj-$(CONFIG_AHCI) += ahci-uclass.o
+obj-$(CONFIG_DM_SCSI) += scsi-uclass.o
obj-$(CONFIG_SCSI_AHCI) += ahci.o
obj-$(CONFIG_DWC_AHSATA) += dwc_ahsata.o
obj-$(CONFIG_FSL_SATA) += fsl_sata.o
diff --git a/drivers/block/ahci.c b/drivers/block/ahci.c
index 5139989..3fa14a7 100644
--- a/drivers/block/ahci.c
+++ b/drivers/block/ahci.c
@@ -168,7 +168,7 @@ int ahci_reset(void __iomem *base)
static int ahci_host_init(struct ahci_probe_ent *probe_ent)
{
-#ifndef CONFIG_SCSI_AHCI_PLAT
+#if !defined(CONFIG_SCSI_AHCI_PLAT) && !defined(CONFIG_DM_SCSI)
# ifdef CONFIG_DM_PCI
struct udevice *dev = probe_ent->dev;
struct pci_child_platdata *pplat = dev_get_parent_platdata(dev);
@@ -198,7 +198,7 @@ static int ahci_host_init(struct ahci_probe_ent *probe_ent)
writel(cap_save, mmio + HOST_CAP);
writel_with_flush(0xf, mmio + HOST_PORTS_IMPL);
-#ifndef CONFIG_SCSI_AHCI_PLAT
+#if !defined(CONFIG_SCSI_AHCI_PLAT) && !defined(CONFIG_DM_SCSI)
# ifdef CONFIG_DM_PCI
if (pplat->vendor == PCI_VENDOR_ID_INTEL) {
u16 tmp16;
@@ -327,6 +327,7 @@ static int ahci_host_init(struct ahci_probe_ent *probe_ent)
writel(tmp | HOST_IRQ_EN, mmio + HOST_CTL);
tmp = readl(mmio + HOST_CTL);
debug("HOST_CTL 0x%x\n", tmp);
+#if !defined(CONFIG_DM_SCSI)
#ifndef CONFIG_SCSI_AHCI_PLAT
# ifdef CONFIG_DM_PCI
dm_pci_read_config16(dev, PCI_COMMAND, &tmp16);
@@ -338,14 +339,15 @@ static int ahci_host_init(struct ahci_probe_ent *probe_ent)
pci_write_config_word(pdev, PCI_COMMAND, tmp16);
# endif
#endif
+#endif
return 0;
}
static void ahci_print_info(struct ahci_probe_ent *probe_ent)
{
-#ifndef CONFIG_SCSI_AHCI_PLAT
-# ifdef CONFIG_DM_PCI
+#if !defined(CONFIG_SCSI_AHCI_PLAT) && !defined(CONFIG_DM_SCSI)
+# if defined(CONFIG_DM_PCI)
struct udevice *dev = probe_ent->dev;
# else
pci_dev_t pdev = probe_ent->dev;
@@ -372,7 +374,7 @@ static void ahci_print_info(struct ahci_probe_ent *probe_ent)
else
speed_s = "?";
-#ifdef CONFIG_SCSI_AHCI_PLAT
+#if defined(CONFIG_SCSI_AHCI_PLAT) || defined(CONFIG_DM_SCSI)
scc_s = "SATA";
#else
# ifdef CONFIG_DM_PCI
@@ -424,13 +426,15 @@ static void ahci_print_info(struct ahci_probe_ent *probe_ent)
}
#ifndef CONFIG_SCSI_AHCI_PLAT
-# ifdef CONFIG_DM_PCI
+# if defined(CONFIG_DM_PCI) || defined(CONFIG_DM_SCSI)
static int ahci_init_one(struct udevice *dev)
# else
static int ahci_init_one(pci_dev_t dev)
# endif
{
+#if !defined(CONFIG_DM_SCSI)
u16 vendor;
+#endif
int rc;
probe_ent = malloc(sizeof(struct ahci_probe_ent));
@@ -450,6 +454,7 @@ static int ahci_init_one(pci_dev_t dev)
probe_ent->pio_mask = 0x1f;
probe_ent->udma_mask = 0x7f; /*Fixme,assume to support UDMA6 */
+#if !defined(CONFIG_DM_SCSI)
#ifdef CONFIG_DM_PCI
probe_ent->mmio_base = dm_pci_map_bar(dev, PCI_BASE_ADDRESS_5,
PCI_REGION_MEM);
@@ -473,6 +478,10 @@ static int ahci_init_one(pci_dev_t dev)
if (vendor == 0x197b)
pci_write_config_byte(dev, 0x41, 0xa1);
#endif
+#else
+ struct scsi_platdata *plat = dev_get_platdata(dev);
+ probe_ent->mmio_base = (void *)plat->base;
+#endif
debug("ahci mmio_base=0x%p\n", probe_ent->mmio_base);
/* initialize adapter */
@@ -954,14 +963,17 @@ int scsi_exec(ccb *pccb)
}
-
+#if defined(CONFIG_DM_SCSI)
+void scsi_low_level_init(int busdevfunc, struct udevice *dev)
+#else
void scsi_low_level_init(int busdevfunc)
+#endif
{
int i;
u32 linkmap;
#ifndef CONFIG_SCSI_AHCI_PLAT
-# ifdef CONFIG_DM_PCI
+# if defined(CONFIG_DM_PCI)
struct udevice *dev;
int ret;
@@ -969,6 +981,8 @@ void scsi_low_level_init(int busdevfunc)
if (ret)
return;
ahci_init_one(dev);
+# elif defined(CONFIG_DM_SCSI)
+ ahci_init_one(dev);
# else
ahci_init_one(busdevfunc);
# endif
diff --git a/drivers/block/blk-uclass.c b/drivers/block/blk-uclass.c
index 2e041c2..38cb938 100644
--- a/drivers/block/blk-uclass.c
+++ b/drivers/block/blk-uclass.c
@@ -26,7 +26,7 @@ static const char *if_typename_str[IF_TYPE_COUNT] = {
static enum uclass_id if_type_uclass_id[IF_TYPE_COUNT] = {
[IF_TYPE_IDE] = UCLASS_INVALID,
- [IF_TYPE_SCSI] = UCLASS_INVALID,
+ [IF_TYPE_SCSI] = UCLASS_SCSI,
[IF_TYPE_ATAPI] = UCLASS_INVALID,
[IF_TYPE_USB] = UCLASS_MASS_STORAGE,
[IF_TYPE_DOC] = UCLASS_INVALID,
diff --git a/drivers/block/sata_ceva.c b/drivers/block/sata_ceva.c
index dcc3b90..9b54664 100644
--- a/drivers/block/sata_ceva.c
+++ b/drivers/block/sata_ceva.c
@@ -5,6 +5,7 @@
* SPDX-License-Identifier: GPL-2.0+
*/
#include <common.h>
+#include <dm.h>
#include <netdev.h>
#include <ahci.h>
#include <scsi.h>
@@ -73,10 +74,9 @@
#define DRV_NAME "ahci-ceva"
#define CEVA_FLAG_BROKEN_GEN2 1
-int init_sata(int dev)
+static int ceva_init_sata(ulong mmio)
{
ulong tmp;
- ulong mmio = ZYNQMP_SATA_BASEADDR;
int i;
/*
@@ -111,3 +111,40 @@ int init_sata(int dev)
}
return 0;
}
+
+static int sata_ceva_probe(struct udevice *dev)
+{
+ struct scsi_platdata *plat = dev_get_platdata(dev);
+
+ ceva_init_sata(plat->base);
+ return 0;
+}
+
+static const struct udevice_id sata_ceva_ids[] = {
+ { .compatible = "ceva,ahci-1v84" },
+ { }
+};
+
+static int sata_ceva_ofdata_to_platdata(struct udevice *dev)
+{
+ struct scsi_platdata *plat = dev_get_platdata(dev);
+
+ plat->base = dev_get_addr(dev);
+ if (plat->base == FDT_ADDR_T_NONE)
+ return -EINVAL;
+
+ /* Hardcode number for ceva sata controller */
+ plat->max_lun = 1; /* Actually two but untested */
+ plat->max_id = 2;
+
+ return 0;
+}
+
+U_BOOT_DRIVER(ceva_host_blk) = {
+ .name = "ceva_sata",
+ .id = UCLASS_SCSI,
+ .of_match = sata_ceva_ids,
+ .probe = sata_ceva_probe,
+ .ofdata_to_platdata = sata_ceva_ofdata_to_platdata,
+ .platdata_auto_alloc_size = sizeof(struct scsi_platdata),
+};
diff --git a/drivers/block/scsi-uclass.c b/drivers/block/scsi-uclass.c
new file mode 100644
index 0000000..05da6cd
--- /dev/null
+++ b/drivers/block/scsi-uclass.c
@@ -0,0 +1,27 @@
+/*
+ * Copyright (c) 2015 Google, Inc
+ * Written by Simon Glass <sjg@chromium.org>
+ * Copyright (c) 2016 Xilinx, Inc
+ * Written by Michal Simek
+ *
+ * Based on ahci-uclass.c
+ *
+ * SPDX-License-Identifier: GPL-2.0+
+ */
+
+#include <common.h>
+#include <dm.h>
+#include <scsi.h>
+
+static int scsi_post_probe(struct udevice *dev)
+{
+ debug("%s: device %p\n", __func__, dev);
+ scsi_low_level_init(0, dev);
+ return 0;
+}
+
+UCLASS_DRIVER(scsi) = {
+ .id = UCLASS_SCSI,
+ .name = "scsi",
+ .post_probe = scsi_post_probe,
+};
diff --git a/drivers/gpio/zynq_gpio.c b/drivers/gpio/zynq_gpio.c
index 8a448c9..64579a1 100644
--- a/drivers/gpio/zynq_gpio.c
+++ b/drivers/gpio/zynq_gpio.c
@@ -325,7 +325,6 @@ static const struct dm_gpio_ops gpio_zynq_ops = {
.get_value = zynq_gpio_get_value,
.set_value = zynq_gpio_set_value,
.get_function = zynq_gpio_get_function,
-
};
static const struct udevice_id zynq_gpio_ids[] = {
diff --git a/drivers/i2c/mv_i2c.c b/drivers/i2c/mv_i2c.c
index 7f52fa2..c780272 100644
--- a/drivers/i2c/mv_i2c.c
+++ b/drivers/i2c/mv_i2c.c
@@ -270,7 +270,7 @@ static int __i2c_read(struct mv_i2c *base, uchar chip, u8 *addr, int alen,
msg.condition = I2C_COND_NORMAL;
msg.acknack = I2C_ACKNAK_WAITACK;
msg.direction = I2C_WRITE;
- msg.data = *(addr++);
+ msg.data = addr[alen];
if (i2c_transfer(base, &msg))
return -1;
}
@@ -341,7 +341,7 @@ static int __i2c_write(struct mv_i2c *base, uchar chip, u8 *addr, int alen,
msg.condition = I2C_COND_NORMAL;
msg.acknack = I2C_ACKNAK_WAITACK;
msg.direction = I2C_WRITE;
- msg.data = *(addr++);
+ msg.data = addr[alen];
if (i2c_transfer(base, &msg))
return -1;
}
diff --git a/drivers/mmc/Kconfig b/drivers/mmc/Kconfig
index 5e84a41..9983913 100644
--- a/drivers/mmc/Kconfig
+++ b/drivers/mmc/Kconfig
@@ -83,7 +83,7 @@ config PIC32_SDHCI
config ZYNQ_SDHCI
bool "Arasan SDHCI controller support"
- depends on DM_MMC && OF_CONTROL
+ depends on DM_MMC && OF_CONTROL && BLK && DM_MMC_OPS
help
Support for Arasan SDHCI host controller on Zynq/ZynqMP ARM SoCs platform
diff --git a/drivers/mmc/Makefile b/drivers/mmc/Makefile
index d850758..94da954 100644
--- a/drivers/mmc/Makefile
+++ b/drivers/mmc/Makefile
@@ -52,7 +52,6 @@ obj-$(CONFIG_SDHCI) += sdhci.o
obj-$(CONFIG_SH_MMCIF) += sh_mmcif.o
obj-$(CONFIG_SH_SDHI) += sh_sdhi.o
obj-$(CONFIG_SOCFPGA_DWMMC) += socfpga_dw_mmc.o
-obj-$(CONFIG_SPEAR_SDHCI) += spear_sdhci.o
obj-$(CONFIG_TEGRA_MMC) += tegra_mmc.o
obj-$(CONFIG_MMC_UNIPHIER) += uniphier-sd.o
obj-$(CONFIG_ZYNQ_SDHCI) += zynq_sdhci.o
diff --git a/drivers/mmc/spear_sdhci.c b/drivers/mmc/spear_sdhci.c
deleted file mode 100644
index 06179cd..0000000
--- a/drivers/mmc/spear_sdhci.c
+++ /dev/null
@@ -1,27 +0,0 @@
-/*
- * (C) Copyright 2012
- * Vipin Kumar, ST Micoelectronics, vipin.kumar@st.com.
- *
- * SPDX-License-Identifier: GPL-2.0+
- */
-
-#include <common.h>
-#include <malloc.h>
-#include <sdhci.h>
-
-int spear_sdhci_init(u32 regbase, u32 max_clk, u32 min_clk, u32 quirks)
-{
- struct sdhci_host *host = NULL;
- host = (struct sdhci_host *)malloc(sizeof(struct sdhci_host));
- if (!host) {
- printf("sdhci host malloc fail!\n");
- return 1;
- }
-
- host->name = "sdhci";
- host->ioaddr = (void *)regbase;
- host->quirks = quirks;
-
- add_sdhci(host, max_clk, min_clk);
- return 0;
-}
diff --git a/drivers/net/xilinx_axi_emac.c b/drivers/net/xilinx_axi_emac.c
index 5de06ef..51c7426 100644
--- a/drivers/net/xilinx_axi_emac.c
+++ b/drivers/net/xilinx_axi_emac.c
@@ -648,9 +648,8 @@ static int axi_emac_probe(struct udevice *dev)
priv->bus->read = axiemac_miiphy_read;
priv->bus->write = axiemac_miiphy_write;
priv->bus->priv = priv;
- strcpy(priv->bus->name, "axi_emac");
- ret = mdio_register(priv->bus);
+ ret = mdio_register_seq(priv->bus, dev->seq);
if (ret)
return ret;
diff --git a/drivers/net/xilinx_emaclite.c b/drivers/net/xilinx_emaclite.c
index 78ff44c..ea93cf9 100644
--- a/drivers/net/xilinx_emaclite.c
+++ b/drivers/net/xilinx_emaclite.c
@@ -566,9 +566,8 @@ static int emaclite_probe(struct udevice *dev)
emaclite->bus->read = emaclite_miiphy_read;
emaclite->bus->write = emaclite_miiphy_write;
emaclite->bus->priv = emaclite;
- strcpy(emaclite->bus->name, "emaclite");
- ret = mdio_register(emaclite->bus);
+ ret = mdio_register_seq(emaclite->bus, dev->seq);
if (ret)
return ret;
diff --git a/drivers/net/zynq_gem.c b/drivers/net/zynq_gem.c
index 526eac6..d2e5e7c 100644
--- a/drivers/net/zynq_gem.c
+++ b/drivers/net/zynq_gem.c
@@ -647,9 +647,8 @@ static int zynq_gem_probe(struct udevice *dev)
priv->bus->read = zynq_gem_miiphy_read;
priv->bus->write = zynq_gem_miiphy_write;
priv->bus->priv = priv;
- strcpy(priv->bus->name, "gem");
- ret = mdio_register(priv->bus);
+ ret = mdio_register_seq(priv->bus, dev->seq);
if (ret)
return ret;
diff --git a/drivers/power/pmic/Kconfig b/drivers/power/pmic/Kconfig
index ce204b3..5e244c8 100644
--- a/drivers/power/pmic/Kconfig
+++ b/drivers/power/pmic/Kconfig
@@ -54,6 +54,13 @@ config DM_PMIC_MAX77686
This config enables implementation of driver-model pmic uclass features
for PMIC MAX77686. The driver implements read/write operations.
+config DM_PMIC_MAX8998
+ bool "Enable Driver Model for PMIC MAX8998"
+ depends on DM_PMIC
+ ---help---
+ This config enables implementation of driver-model pmic uclass features
+ for PMIC MAX8998. The driver implements read/write operations.
+
config PMIC_PM8916
bool "Enable Driver Model for Qualcomm PM8916 PMIC"
depends on DM_PMIC
diff --git a/drivers/power/pmic/Makefile b/drivers/power/pmic/Makefile
index cd1c694..b4ac7d2 100644
--- a/drivers/power/pmic/Makefile
+++ b/drivers/power/pmic/Makefile
@@ -7,6 +7,7 @@
obj-$(CONFIG_DM_PMIC) += pmic-uclass.o
obj-$(CONFIG_DM_PMIC_MAX77686) += max77686.o
+obj-$(CONFIG_DM_PMIC_MAX8998) += max8998.o
obj-$(CONFIG_DM_PMIC_PFUZE100) += pfuze100.o
obj-$(CONFIG_PMIC_S2MPS11) += s2mps11.o
obj-$(CONFIG_DM_PMIC_SANDBOX) += sandbox.o i2c_pmic_emul.o
diff --git a/drivers/power/pmic/max8998.c b/drivers/power/pmic/max8998.c
new file mode 100644
index 0000000..3baa8da
--- /dev/null
+++ b/drivers/power/pmic/max8998.c
@@ -0,0 +1,61 @@
+/*
+ * Copyright (C) 2016 Samsung Electronics
+ * Jaehoon Chung <jh80.chung@samsung.com>
+ *
+ * SPDX-License-Identifier: GPL-2.0+
+ */
+
+#include <common.h>
+#include <dm.h>
+#include <i2c.h>
+#include <power/pmic.h>
+#include <power/max8998_pmic.h>
+#include <errno.h>
+
+DECLARE_GLOBAL_DATA_PTR;
+
+static int max8998_reg_count(struct udevice *dev)
+{
+ return PMIC_NUM_OF_REGS;
+}
+
+static int max8998_write(struct udevice *dev, uint reg, const uint8_t *buff,
+ int len)
+{
+ int ret;
+
+ ret = dm_i2c_write(dev, reg, buff, len);
+ if (ret)
+ error("write error to device: %p register: %#x!", dev, reg);
+
+ return ret;
+}
+
+static int max8998_read(struct udevice *dev, uint reg, uint8_t *buff, int len)
+{
+ int ret;
+
+ ret = dm_i2c_read(dev, reg, buff, len);
+ if (ret)
+ error("read error from device: %p register: %#x!", dev, reg);
+
+ return ret;
+}
+
+static struct dm_pmic_ops max8998_ops = {
+ .reg_count = max8998_reg_count,
+ .read = max8998_read,
+ .write = max8998_write,
+};
+
+static const struct udevice_id max8998_ids[] = {
+ { .compatible = "maxim,max8998" },
+ { }
+};
+
+U_BOOT_DRIVER(pmic_max8998) = {
+ .name = "max8998_pmic",
+ .id = UCLASS_PMIC,
+ .of_match = max8998_ids,
+ .ops = &max8998_ops,
+};
diff --git a/drivers/spi/Makefile b/drivers/spi/Makefile
index 247c5f6..c1ce158 100644
--- a/drivers/spi/Makefile
+++ b/drivers/spi/Makefile
@@ -16,7 +16,6 @@ obj-$(CONFIG_SOFT_SPI) += soft_spi_legacy.o
endif
obj-$(CONFIG_ALTERA_SPI) += altera_spi.o
-obj-$(CONFIG_ARMADA100_SPI) += armada100_spi.o
obj-$(CONFIG_ATH79_SPI) += ath79_spi.o
obj-$(CONFIG_ATMEL_DATAFLASH_SPI) += atmel_dataflash_spi.o
obj-$(CONFIG_ATMEL_SPI) += atmel_spi.o
@@ -35,7 +34,6 @@ obj-$(CONFIG_FSL_QSPI) += fsl_qspi.o
obj-$(CONFIG_ICH_SPI) += ich.o
obj-$(CONFIG_KIRKWOOD_SPI) += kirkwood_spi.o
obj-$(CONFIG_LPC32XX_SSP) += lpc32xx_ssp.o
-obj-$(CONFIG_MPC52XX_SPI) += mpc52xx_spi.o
obj-$(CONFIG_MPC8XXX_SPI) += mpc8xxx_spi.o
obj-$(CONFIG_MVEBU_A3700_SPI) += mvebu_a3700_spi.o
obj-$(CONFIG_MXC_SPI) += mxc_spi.o
diff --git a/drivers/spi/armada100_spi.c b/drivers/spi/armada100_spi.c
deleted file mode 100644
index 53aaf95..0000000
--- a/drivers/spi/armada100_spi.c
+++ /dev/null
@@ -1,203 +0,0 @@
-/*
- * (C) Copyright 2011
- * eInfochips Ltd. <www.einfochips.com>
- * Written-by: Ajay Bhargav <ajay.bhargav@einfochips.com>
- *
- * (C) Copyright 2009
- * Marvell Semiconductor <www.marvell.com>
- * Based on SSP driver
- * Written-by: Lei Wen <leiwen@marvell.com>
- *
- * SPDX-License-Identifier: GPL-2.0+
- */
-
-
-#include <common.h>
-#include <malloc.h>
-#include <spi.h>
-
-#include <asm/io.h>
-#include <asm/arch/spi.h>
-#include <asm/gpio.h>
-
-#define to_armd_spi_slave(s) container_of(s, struct armd_spi_slave, slave)
-
-struct armd_spi_slave {
- struct spi_slave slave;
- struct ssp_reg *spi_reg;
- u32 cr0, cr1;
- u32 int_cr1;
- u32 clear_sr;
- const void *tx;
- void *rx;
- int gpio_cs_inverted;
-};
-
-static int spi_armd_write(struct armd_spi_slave *pss)
-{
- int wait_timeout = SSP_FLUSH_NUM;
- while (--wait_timeout && !(readl(&pss->spi_reg->sssr) & SSSR_TNF))
- ;
- if (!wait_timeout) {
- debug("%s: timeout error\n", __func__);
- return -1;
- }
-
- if (pss->tx != NULL) {
- writel(*(u8 *)pss->tx, &pss->spi_reg->ssdr);
- ++pss->tx;
- } else {
- writel(0, &pss->spi_reg->ssdr);
- }
- return 0;
-}
-
-static int spi_armd_read(struct armd_spi_slave *pss)
-{
- int wait_timeout = SSP_FLUSH_NUM;
- while (--wait_timeout && !(readl(&pss->spi_reg->sssr) & SSSR_RNE))
- ;
- if (!wait_timeout) {
- debug("%s: timeout error\n", __func__);
- return -1;
- }
-
- if (pss->rx != NULL) {
- *(u8 *)pss->rx = readl(&pss->spi_reg->ssdr);
- ++pss->rx;
- } else {
- readl(&pss->spi_reg->ssdr);
- }
- return 0;
-}
-
-static int spi_armd_flush(struct armd_spi_slave *pss)
-{
- unsigned long limit = SSP_FLUSH_NUM;
-
- do {
- while (readl(&pss->spi_reg->sssr) & SSSR_RNE)
- readl(&pss->spi_reg->ssdr);
- } while ((readl(&pss->spi_reg->sssr) & SSSR_BSY) && limit--);
-
- writel(SSSR_ROR, &pss->spi_reg->sssr);
-
- return limit;
-}
-
-void spi_cs_activate(struct spi_slave *slave)
-{
- struct armd_spi_slave *pss = to_armd_spi_slave(slave);
-
- gpio_set_value(slave->cs, pss->gpio_cs_inverted);
-}
-
-void spi_cs_deactivate(struct spi_slave *slave)
-{
- struct armd_spi_slave *pss = to_armd_spi_slave(slave);
-
- gpio_set_value(slave->cs, !pss->gpio_cs_inverted);
-}
-
-struct spi_slave *spi_setup_slave(unsigned int bus, unsigned int cs,
- unsigned int max_hz, unsigned int mode)
-{
- struct armd_spi_slave *pss;
-
- pss = spi_alloc_slave(struct armd_spi_slave, bus, cs);
- if (!pss)
- return NULL;
-
- pss->spi_reg = (struct ssp_reg *)SSP_REG_BASE(CONFIG_SYS_SSP_PORT);
-
- pss->cr0 = SSCR0_MOTO | SSCR0_DATASIZE(DEFAULT_WORD_LEN) | SSCR0_SSE;
-
- pss->cr1 = (SSCR1_RXTRESH(RX_THRESH_DEF) & SSCR1_RFT) |
- (SSCR1_TXTRESH(TX_THRESH_DEF) & SSCR1_TFT);
- pss->cr1 &= ~(SSCR1_SPO | SSCR1_SPH);
- pss->cr1 |= (((mode & SPI_CPHA) != 0) ? SSCR1_SPH : 0)
- | (((mode & SPI_CPOL) != 0) ? SSCR1_SPO : 0);
-
- pss->int_cr1 = SSCR1_TIE | SSCR1_RIE | SSCR1_TINTE;
- pss->clear_sr = SSSR_ROR | SSSR_TINT;
-
- pss->gpio_cs_inverted = mode & SPI_CS_HIGH;
- gpio_set_value(cs, !pss->gpio_cs_inverted);
-
- return &pss->slave;
-}
-
-void spi_free_slave(struct spi_slave *slave)
-{
- struct armd_spi_slave *pss = to_armd_spi_slave(slave);
-
- free(pss);
-}
-
-int spi_claim_bus(struct spi_slave *slave)
-{
- struct armd_spi_slave *pss = to_armd_spi_slave(slave);
-
- debug("%s: bus:%i cs:%i\n", __func__, slave->bus, slave->cs);
- if (spi_armd_flush(pss) == 0)
- return -1;
-
- return 0;
-}
-
-void spi_release_bus(struct spi_slave *slave)
-{
-}
-
-int spi_xfer(struct spi_slave *slave, unsigned int bitlen, const void *dout,
- void *din, unsigned long flags)
-{
- struct armd_spi_slave *pss = to_armd_spi_slave(slave);
- uint bytes = bitlen / 8;
- unsigned long limit;
- int ret = 0;
-
- if (bitlen == 0)
- goto done;
-
- /* we can only do 8 bit transfers */
- if (bitlen % 8) {
- flags |= SPI_XFER_END;
- goto done;
- }
-
- pss->tx = dout;
- pss->rx = din;
-
- if (flags & SPI_XFER_BEGIN) {
- spi_cs_activate(slave);
- writel(pss->cr1 | pss->int_cr1, &pss->spi_reg->sscr1);
- writel(TIMEOUT_DEF, &pss->spi_reg->ssto);
- writel(pss->cr0, &pss->spi_reg->sscr0);
- }
-
- while (bytes--) {
- limit = SSP_FLUSH_NUM;
- ret = spi_armd_write(pss);
- if (ret)
- break;
-
- while ((readl(&pss->spi_reg->sssr) & SSSR_BSY) && limit--)
- udelay(1);
-
- ret = spi_armd_read(pss);
- if (ret)
- break;
- }
-
- done:
- if (flags & SPI_XFER_END) {
- /* Stop SSP */
- writel(pss->clear_sr, &pss->spi_reg->sssr);
- clrbits_le32(&pss->spi_reg->sscr1, pss->int_cr1);
- writel(0, &pss->spi_reg->ssto);
- spi_cs_deactivate(slave);
- }
-
- return ret;
-}
diff --git a/drivers/spi/mpc52xx_spi.c b/drivers/spi/mpc52xx_spi.c
deleted file mode 100644
index 4613bec..0000000
--- a/drivers/spi/mpc52xx_spi.c
+++ /dev/null
@@ -1,90 +0,0 @@
-/*
- * (C) Copyright 2009
- * Frank Bodammer <frank.bodammer@gcd-solutions.de>
- * (C) Copyright 2009 Semihalf, Grzegorz Bernacki
- *
- * SPDX-License-Identifier: GPL-2.0+
- */
-
-#include <common.h>
-#include <asm/io.h>
-#include <malloc.h>
-#include <spi.h>
-#include <mpc5xxx.h>
-
-void spi_init(void)
-{
- struct mpc5xxx_spi *spi = (struct mpc5xxx_spi *)MPC5XXX_SPI;
- /*
- * Its important to use the correct order when initializing the
- * registers
- */
- out_8(&spi->ddr, 0x0F); /* set all SPI pins as output */
- out_8(&spi->pdr, 0x00); /* set SS low */
- /* SPI is master, SS is general purpose output */
- out_8(&spi->cr1, SPI_CR_MSTR | SPI_CR_SPE);
- out_8(&spi->cr2, 0x00); /* normal operation */
- out_8(&spi->brr, 0x77); /* baud rate: IPB clock / 2048 */
-}
-
-struct spi_slave *spi_setup_slave(unsigned int bus, unsigned int cs,
- unsigned int max_hz, unsigned int mode)
-{
- struct spi_slave *slave;
-
- slave = spi_alloc_slave_base(bus, cs);
- if (!slave)
- return NULL;
-
- return slave;
-}
-
-void spi_free_slave(struct spi_slave *slave)
-{
- free(slave);
-}
-
-int spi_claim_bus(struct spi_slave *slave)
-{
- return 0;
-}
-
-void spi_release_bus(struct spi_slave *slave)
-{
- return;
-}
-
-int spi_xfer(struct spi_slave *slave, unsigned int bitlen, const void *dout,
- void *din, unsigned long flags)
-{
- struct mpc5xxx_spi *spi = (struct mpc5xxx_spi *)MPC5XXX_SPI;
- int i, iter = bitlen >> 3;
- const uchar *txp = dout;
- uchar *rxp = din;
-
- debug("spi_xfer: slave %u:%u dout %08X din %08X bitlen %u\n",
- slave->bus, slave->cs, *(uint *) dout, *(uint *) din, bitlen);
-
- if (flags & SPI_XFER_BEGIN)
- setbits_8(&spi->pdr, SPI_PDR_SS);
-
- for (i = 0; i < iter; i++) {
- udelay(1000);
- debug("spi_xfer: sending %x\n", txp[i]);
- out_8(&spi->dr, txp[i]);
- while (!(in_8(&spi->sr) & SPI_SR_SPIF)) {
- udelay(1000);
- if (in_8(&spi->sr) & SPI_SR_WCOL) {
- rxp[i] = in_8(&spi->dr);
- puts("spi_xfer: write collision\n");
- return -1;
- }
- }
- rxp[i] = in_8(&spi->dr);
- debug("spi_xfer: received %x\n", rxp[i]);
- }
- if (flags & SPI_XFER_END)
- clrbits_8(&spi->pdr, SPI_PDR_SS);
-
- return 0;
-}
diff --git a/include/ahci.h b/include/ahci.h
index a956c6f..4876b41 100644
--- a/include/ahci.h
+++ b/include/ahci.h
@@ -145,7 +145,7 @@ struct ahci_ioports {
};
struct ahci_probe_ent {
-#ifdef CONFIG_DM_PCI
+#if defined(CONFIG_DM_PCI) || defined(CONFIG_DM_SCSI)
struct udevice *dev;
#else
pci_dev_t dev;
diff --git a/include/configs/digsy_mtc.h b/include/configs/digsy_mtc.h
index b2120b9..ae0d3d4 100644
--- a/include/configs/digsy_mtc.h
+++ b/include/configs/digsy_mtc.h
@@ -216,12 +216,6 @@
#define CONFIG_BOOTCOMMAND "run mtcb_start"
/*
- * SPI configuration
- */
-#define CONFIG_HARD_SPI 1
-#define CONFIG_MPC52XX_SPI 1
-
-/*
* I2C configuration
*/
#define CONFIG_HARD_I2C 1
diff --git a/include/configs/gplugd.h b/include/configs/gplugd.h
index c1b43fd..92e2117 100644
--- a/include/configs/gplugd.h
+++ b/include/configs/gplugd.h
@@ -72,11 +72,6 @@
/* GPIO Configuration for PHY */
#define CONFIG_SYS_GPIO_PHY_RST 104 /* GPIO104 */
-/* SPI Support */
-#define CONFIG_ARMADA100_SPI
-#define CONFIG_ENV_SPI_CS 110
-#define CONFIG_SYS_SSP_PORT 2
-
/* Flash Support */
/*
@@ -95,10 +90,8 @@
/*
* Environment variables configurations
*/
-#define CONFIG_ENV_IS_IN_SPI_FLASH
-#define CONFIG_ENV_SECT_SIZE 0x4000
+#define CONFIG_ENV_IS_NOWHERE
#define CONFIG_ENV_SIZE 0x4000
-#define CONFIG_ENV_OFFSET 0x07C000
#ifdef CONFIG_CMD_USB
#define CONFIG_USB_EHCI
diff --git a/include/configs/xilinx_zynqmp.h b/include/configs/xilinx_zynqmp.h
index d480990..fb4f6d6 100644
--- a/include/configs/xilinx_zynqmp.h
+++ b/include/configs/xilinx_zynqmp.h
@@ -181,7 +181,6 @@
#ifdef CONFIG_SATA_CEVA
#define CONFIG_LIBATA
#define CONFIG_SCSI_AHCI
-#define CONFIG_SCSI_AHCI_PLAT
#define CONFIG_SYS_SCSI_MAX_SCSI_ID 2
#define CONFIG_SYS_SCSI_MAX_LUN 1
#define CONFIG_SYS_SCSI_MAX_DEVICE (CONFIG_SYS_SCSI_MAX_SCSI_ID * \
diff --git a/include/configs/xilinx_zynqmp_ep.h b/include/configs/xilinx_zynqmp_ep.h
index d0ce768..3a572b7 100644
--- a/include/configs/xilinx_zynqmp_ep.h
+++ b/include/configs/xilinx_zynqmp_ep.h
@@ -16,7 +16,6 @@
#define CONFIG_ZYNQ_SDHCI_MAX_FREQ 52000000
#define CONFIG_ZYNQ_SDHCI_MIN_FREQ (CONFIG_ZYNQ_SDHCI_MAX_FREQ >> 9)
#define CONFIG_ZYNQ_EEPROM
-#define CONFIG_SATA_CEVA
#define CONFIG_ZYNQMP_XHCI_LIST {ZYNQMP_USB0_XHCI_BASEADDR, \
ZYNQMP_USB1_XHCI_BASEADDR}
diff --git a/include/configs/xilinx_zynqmp_zcu102.h b/include/configs/xilinx_zynqmp_zcu102.h
index adf2321..8d018da 100644
--- a/include/configs/xilinx_zynqmp_zcu102.h
+++ b/include/configs/xilinx_zynqmp_zcu102.h
@@ -41,8 +41,6 @@
#define CONFIG_CMD_PCA953X
#define CONFIG_CMD_PCA953X_INFO
-#define CONFIG_SATA_CEVA
-
#define CONFIG_ZYNQMP_XHCI_LIST {ZYNQMP_USB0_XHCI_BASEADDR}
#define CONFIG_SYS_I2C_EEPROM_ADDR_LEN 1
diff --git a/include/dm/uclass-id.h b/include/dm/uclass-id.h
index eb78c4d..8c92d0b 100644
--- a/include/dm/uclass-id.h
+++ b/include/dm/uclass-id.h
@@ -66,6 +66,7 @@ enum uclass_id {
UCLASS_REMOTEPROC, /* Remote Processor device */
UCLASS_RESET, /* Reset controller device */
UCLASS_RTC, /* Real time clock device */
+ UCLASS_SCSI, /* SCSI device */
UCLASS_SERIAL, /* Serial UART */
UCLASS_SPI, /* SPI bus */
UCLASS_SPMI, /* System Power Management Interface bus */
diff --git a/include/fdtdec.h b/include/fdtdec.h
index 27887c8..d074478 100644
--- a/include/fdtdec.h
+++ b/include/fdtdec.h
@@ -976,6 +976,40 @@ struct display_timing {
*/
int fdtdec_decode_display_timing(const void *blob, int node, int index,
struct display_timing *config);
+
+/**
+ * fdtdec_setup_memory_size() - decode and setup gd->ram_size
+ *
+ * Decode the /memory 'reg' property to determine the size of the first memory
+ * bank, populate the global data with the size of the first bank of memory.
+ *
+ * This function should be called from a boards dram_init(). This helper
+ * function allows for boards to query the device tree for DRAM size instead of
+ * hard coding the value in the case where the memory size cannot be detected
+ * automatically.
+ *
+ * @return 0 if OK, -EINVAL if the /memory node or reg property is missing or
+ * invalid
+ */
+int fdtdec_setup_memory_size(void);
+
+/**
+ * fdtdec_setup_memory_banksize() - decode and populate gd->bd->bi_dram
+ *
+ * Decode the /memory 'reg' property to determine the address and size of the
+ * memory banks. Use this data to populate the global data board info with the
+ * phys address and size of memory banks.
+ *
+ * This function should be called from a boards dram_init_banksize(). This
+ * helper function allows for boards to query the device tree for memory bank
+ * information instead of hard coding the information in cases where it cannot
+ * be detected automatically.
+ *
+ * @return 0 if OK, -EINVAL if the /memory node or reg property is missing or
+ * invalid
+ */
+int fdtdec_setup_memory_banksize(void);
+
/**
* Set up the device tree ready for use
*/
diff --git a/include/miiphy.h b/include/miiphy.h
index 83141b4..fe8928a 100644
--- a/include/miiphy.h
+++ b/include/miiphy.h
@@ -48,6 +48,15 @@ void miiphy_listdev(void);
struct mii_dev *mdio_alloc(void);
void mdio_free(struct mii_dev *bus);
int mdio_register(struct mii_dev *bus);
+
+/**
+ * mdio_register_seq - Register mdio bus with sequence number
+ * @bus: mii device structure
+ * @seq: sequence number
+ *
+ * Return: 0 if success, negative value if error
+ */
+int mdio_register_seq(struct mii_dev *bus, int seq);
int mdio_unregister(struct mii_dev *bus);
void mdio_list_devices(void);
diff --git a/include/sata.h b/include/sata.h
index b35359a..d18cc9a 100644
--- a/include/sata.h
+++ b/include/sata.h
@@ -2,6 +2,7 @@
#define __SATA_H__
#include <part.h>
+#if !defined(CONFIG_DM_SCSI)
int init_sata(int dev);
int reset_sata(int dev);
int scan_sata(int dev);
@@ -15,5 +16,6 @@ int __sata_stop(void);
int sata_port_status(int dev, int port);
extern struct blk_desc sata_dev_desc[];
+#endif
#endif
diff --git a/include/scsi.h b/include/scsi.h
index c879678..190dacd 100644
--- a/include/scsi.h
+++ b/include/scsi.h
@@ -166,8 +166,11 @@ typedef struct SCSI_cmd_block{
void scsi_print_error(ccb *pccb);
int scsi_exec(ccb *pccb);
void scsi_bus_reset(void);
+#if !defined(CONFIG_DM_SCSI)
void scsi_low_level_init(int busdevfunc);
-
+#else
+void scsi_low_level_init(int busdevfunc, struct udevice *dev);
+#endif
/***************************************************************************
* functions residing inside cmd_scsi.c
@@ -175,6 +178,21 @@ void scsi_low_level_init(int busdevfunc);
void scsi_init(void);
int scsi_scan(int mode);
+#if defined(CONFIG_DM_SCSI)
+/**
+ * struct scsi_platdata - stores information about SCSI controller
+ *
+ * @base: Controller base address
+ * @max_lun: Maximum number of logical units
+ * @max_id: Maximum number of target ids
+ */
+struct scsi_platdata {
+ unsigned long base;
+ unsigned long max_lun;
+ unsigned long max_id;
+};
+#endif
+
#define SCSI_IDENTIFY 0xC0 /* not used */
/* Hardware errors */
diff --git a/lib/fdtdec.c b/lib/fdtdec.c
index 4e619c4..81f47ef 100644
--- a/lib/fdtdec.c
+++ b/lib/fdtdec.c
@@ -1174,6 +1174,62 @@ int fdtdec_decode_display_timing(const void *blob, int parent, int index,
return ret;
}
+int fdtdec_setup_memory_size(void)
+{
+ int ret, mem;
+ struct fdt_resource res;
+
+ mem = fdt_path_offset(gd->fdt_blob, "/memory");
+ if (mem < 0) {
+ debug("%s: Missing /memory node\n", __func__);
+ return -EINVAL;
+ }
+
+ ret = fdt_get_resource(gd->fdt_blob, mem, "reg", 0, &res);
+ if (ret != 0) {
+ debug("%s: Unable to decode first memory bank\n", __func__);
+ return -EINVAL;
+ }
+
+ gd->ram_size = (phys_size_t)(res.end - res.start + 1);
+ debug("%s: Initial DRAM size %llx\n", __func__, (u64)gd->ram_size);
+
+ return 0;
+}
+
+#if defined(CONFIG_NR_DRAM_BANKS)
+int fdtdec_setup_memory_banksize(void)
+{
+ int bank, ret, mem;
+ struct fdt_resource res;
+
+ mem = fdt_path_offset(gd->fdt_blob, "/memory");
+ if (mem < 0) {
+ debug("%s: Missing /memory node\n", __func__);
+ return -EINVAL;
+ }
+
+ for (bank = 0; bank < CONFIG_NR_DRAM_BANKS; bank++) {
+ ret = fdt_get_resource(gd->fdt_blob, mem, "reg", bank, &res);
+ if (ret == -FDT_ERR_NOTFOUND)
+ break;
+ if (ret != 0)
+ return -EINVAL;
+
+ gd->bd->bi_dram[bank].start = (phys_addr_t)res.start;
+ gd->bd->bi_dram[bank].size =
+ (phys_size_t)(res.end - res.start + 1);
+
+ debug("%s: DRAM Bank #%d: start = 0x%llx, size = 0x%llx\n",
+ __func__, bank,
+ (unsigned long long)gd->bd->bi_dram[bank].start,
+ (unsigned long long)gd->bd->bi_dram[bank].size);
+ }
+
+ return 0;
+}
+#endif
+
int fdtdec_setup(void)
{
#if CONFIG_IS_ENABLED(OF_CONTROL)
diff --git a/scripts/Makefile.lib b/scripts/Makefile.lib
index 956a8a9..348de2d 100644
--- a/scripts/Makefile.lib
+++ b/scripts/Makefile.lib
@@ -164,10 +164,30 @@ cpp_flags = -Wp,-MD,$(depfile) $(NOSTDINC_FLAGS) $(UBOOTINCLUDE) \
ld_flags = $(LDFLAGS) $(ldflags-y)
+dts_dir = $(srctree)/arch/$(ARCH)/dts
+
+# Try these files in order to find the U-Boot-specific .dtsi include file
+u_boot_dtsi_options = $(wildcard $(dts_dir)/$(basename $(notdir $<))-u-boot.dtsi) \
+ $(wildcard $(dts_dir)/$(subst $\",,$(CONFIG_SYS_SOC))-u-boot.dtsi) \
+ $(wildcard $(dts_dir)/$(subst $\",,$(CONFIG_SYS_CPU))-u-boot.dtsi) \
+ $(wildcard $(dts_dir)/$(subst $\",,$(CONFIG_SYS_VENDOR))-u-boot.dtsi) \
+ $(wildcard $(dts_dir)/u-boot.dtsi)
+
+# Uncomment for debugging
+# $(warning u_boot_dtsi_options: $(u_boot_dtsi_options))
+
+# We use the first match
+u_boot_dtsi = $(firstword $(u_boot_dtsi_options))
+
# Modified for U-Boot
dtc_cpp_flags = -Wp,-MD,$(depfile).pre.tmp -nostdinc \
-I$(srctree)/arch/$(ARCH)/dts \
-I$(srctree)/arch/$(ARCH)/dts/include \
+ -Iinclude \
+ -I$(srctree)/include \
+ -I$(srctree)/arch/$(ARCH)/include \
+ -include $(srctree)/include/linux/kconfig.h \
+ -D__ASSEMBLY__ \
-undef -D__DTS__
# Finds the multi-part object the current object will be linked into
@@ -288,8 +308,11 @@ $(obj)/%.dtb.S: $(obj)/%.dtb
quiet_cmd_dtc = DTC $@
# Modified for U-Boot
+# Bring in any U-Boot-specific include after the '/dts-v1/;' header
cmd_dtc = mkdir -p $(dir ${dtc-tmp}) ; \
- $(CPP) $(dtc_cpp_flags) -x assembler-with-cpp -o $(dtc-tmp) $< ; \
+ cat $< $(if $(u_boot_dtsi),\
+ | sed 's%^/ {$$%\#include \"$(u_boot_dtsi)\"\n&%') | \
+ $(CPP) $(dtc_cpp_flags) -x assembler-with-cpp -o $(dtc-tmp) - ; \
$(DTC) -O dtb -o $@ -b 0 \
-i $(dir $<) $(DTC_FLAGS) \
-d $(depfile).dtc.tmp $(dtc-tmp) ; \
diff --git a/scripts/config_whitelist.txt b/scripts/config_whitelist.txt
index 8814841..6d614c6 100644
--- a/scripts/config_whitelist.txt
+++ b/scripts/config_whitelist.txt
@@ -176,7 +176,6 @@ CONFIG_ARIA_FPGA
CONFIG_ARM926EJS
CONFIG_ARMADA100
CONFIG_ARMADA100_FEC
-CONFIG_ARMADA100_SPI
CONFIG_ARMADA168
CONFIG_ARMADA_39X
CONFIG_ARMCORTEXA9
@@ -3095,7 +3094,6 @@ CONFIG_MPC5121ADS_REV2
CONFIG_MPC512x_FEC
CONFIG_MPC5200
CONFIG_MPC5200_DDR
-CONFIG_MPC52XX_SPI
CONFIG_MPC555
CONFIG_MPC5xxx_FEC
CONFIG_MPC5xxx_FEC_MII10
diff --git a/tools/binman/.gitignore b/tools/binman/.gitignore
new file mode 100644
index 0000000..0d20b64
--- /dev/null
+++ b/tools/binman/.gitignore
@@ -0,0 +1 @@
+*.pyc
diff --git a/tools/binman/README b/tools/binman/README
new file mode 100644
index 0000000..cb47e73
--- /dev/null
+++ b/tools/binman/README
@@ -0,0 +1,541 @@
+# Copyright (c) 2016 Google, Inc
+#
+# SPDX-License-Identifier: GPL-2.0+
+#
+
+Introduction
+------------
+
+Firmware often consists of several components which must be packaged together.
+For example, we may have SPL, U-Boot, a device tree and an environment area
+grouped together and placed in MMC flash. When the system starts, it must be
+able to find these pieces.
+
+So far U-Boot has not provided a way to handle creating such images in a
+general way. Each SoC does what it needs to build an image, often packing or
+concatenating images in the U-Boot build system.
+
+Binman aims to provide a mechanism for building images, from simple
+SPL + U-Boot combinations, to more complex arrangements with many parts.
+
+
+What it does
+------------
+
+Binman reads your board's device tree and finds a node which describes the
+required image layout. It uses this to work out what to place where. The
+output file normally contains the device tree, so it is in principle possible
+to read an image and extract its constituent parts.
+
+
+Features
+--------
+
+So far binman is pretty simple. It supports binary blobs, such as 'u-boot',
+'spl' and 'fdt'. It supports empty entries (such as setting to 0xff). It can
+place entries at a fixed location in the image, or fit them together with
+suitable padding and alignment. It provides a way to process binaries before
+they are included, by adding a Python plug-in. The device tree is available
+to U-Boot at run-time so that the images can be interpreted.
+
+Binman does not yet update the device tree with the final location of
+everything when it is done. A simple C structure could be generated for
+constrained environments like SPL (using dtoc) but this is also not
+implemented.
+
+Binman can also support incorporating filesystems in the image if required.
+For example x86 platforms may use CBFS in some cases.
+
+Binman is intended for use with U-Boot but is designed to be general enough
+to be useful in other image-packaging situations.
+
+
+Motivation
+----------
+
+Packaging of firmware is quite a different task from building the various
+parts. In many cases the various binaries which go into the image come from
+separate build systems. For example, ARM Trusted Firmware is used on ARMv8
+devices but is not built in the U-Boot tree. If a Linux kernel is included
+in the firmware image, it is built elsewhere.
+
+It is of course possible to add more and more build rules to the U-Boot
+build system to cover these cases. It can shell out to other Makefiles and
+build scripts. But it seems better to create a clear divide between building
+software and packaging it.
+
+At present this is handled by manual instructions, different for each board,
+on how to create images that will boot. By turning these instructions into a
+standard format, we can support making valid images for any board without
+manual effort, lots of READMEs, etc.
+
+Benefits:
+- Each binary can have its own build system and tool chain without creating
+any dependencies between them
+- Avoids the need for a single-shot build: individual parts can be updated
+and brought in as needed
+- Provides for a standard image description available in the build and at
+run-time
+- SoC-specific image-signing tools can be accomodated
+- Avoids cluttering the U-Boot build system with image-building code
+- The image description is automatically available at run-time in U-Boot,
+SPL. It can be made available to other software also
+- The image description is easily readable (it's a text file in device-tree
+format) and permits flexible packing of binaries
+
+
+Terminology
+-----------
+
+Binman uses the following terms:
+
+- image - an output file containing a firmware image
+- binary - an input binary that goes into the image
+
+
+Relationship to FIT
+-------------------
+
+FIT is U-Boot's official image format. It supports multiple binaries with
+load / execution addresses, compression. It also supports verification
+through hashing and RSA signatures.
+
+FIT was originally designed to support booting a Linux kernel (with an
+optional ramdisk) and device tree chosen from various options in the FIT.
+Now that U-Boot supports configuration via device tree, it is possible to
+load U-Boot from a FIT, with the device tree chosen by SPL.
+
+Binman considers FIT to be one of the binaries it can place in the image.
+
+Where possible it is best to put as much as possible in the FIT, with binman
+used to deal with cases not covered by FIT. Examples include initial
+execution (since FIT itself does not have an executable header) and dealing
+with device boundaries, such as the read-only/read-write separation in SPI
+flash.
+
+For U-Boot, binman should not be used to create ad-hoc images in place of
+FIT.
+
+
+Relationship to mkimage
+-----------------------
+
+The mkimage tool provides a means to create a FIT. Traditionally it has
+needed an image description file: a device tree, like binman, but in a
+different format. More recently it has started to support a '-f auto' mode
+which can generate that automatically.
+
+More relevant to binman, mkimage also permits creation of many SoC-specific
+image types. These can be listed by running 'mkimage -T list'. Examples
+include 'rksd', the Rockchip SD/MMC boot format. The mkimage tool is often
+called from the U-Boot build system for this reason.
+
+Binman considers the output files created by mkimage to be binary blobs
+which it can place in an image. Binman does not replace the mkimage tool or
+this purpose. It would be possible in some situtions to create a new entry
+type for the images in mkimage, but this would not add functionality. It
+seems better to use the mkiamge tool to generate binaries and avoid blurring
+the boundaries between building input files (mkimage) and packaging then
+into a final image (binman).
+
+
+Example use of binman in U-Boot
+-------------------------------
+
+Binman aims to replace some of the ad-hoc image creation in the U-Boot
+build system.
+
+Consider sunxi. It has the following steps:
+
+1. It uses a custom mksunxiboot tool to build an SPL image called
+sunxi-spl.bin. This should probably move into mkimage.
+
+2. It uses mkimage to package U-Boot into a legacy image file (so that it can
+hold the load and execution address) called u-boot.img.
+
+3. It builds a final output image called u-boot-sunxi-with-spl.bin which
+consists of sunxi-spl.bin, some padding and u-boot.img.
+
+Binman is intended to replace the last step. The U-Boot build system builds
+u-boot.bin and sunxi-spl.bin. Binman can then take over creation of
+sunxi-spl.bin (by calling mksunxiboot, or hopefully one day mkimage). In any
+case, it would then create the image from the component parts.
+
+This simplifies the U-Boot Makefile somewhat, since various pieces of logic
+can be replaced by a call to binman.
+
+
+Example use of binman for x86
+-----------------------------
+
+In most cases x86 images have a lot of binary blobs, 'black-box' code
+provided by Intel which must be run for the platform to work. Typically
+these blobs are not relocatable and must be placed at fixed areas in the
+firmare image.
+
+Currently this is handled by ifdtool, which places microcode, FSP, MRC, VGA
+BIOS, reference code and Intel ME binaries into a u-boot.rom file.
+
+Binman is intended to replace all of this, with ifdtool left to handle only
+the configuration of the Intel-format descriptor.
+
+
+Running binman
+--------------
+
+Type:
+
+ binman -b <board_name>
+
+to build an image for a board. The board name is the same name used when
+configuring U-Boot (e.g. for sandbox_defconfig the board name is 'sandbox').
+Binman assumes that the input files for the build are in ../b/<board_name>.
+
+Or you can specify this explicitly:
+
+ binman -I <build_path>
+
+where <build_path> is the build directory containing the output of the U-Boot
+build.
+
+(Future work will make this more configurable)
+
+In either case, binman picks up the device tree file (u-boot.dtb) and looks
+for its instructions in the 'binman' node.
+
+Binman has a few other options which you can see by running 'binman -h'.
+
+
+Image description format
+------------------------
+
+The binman node is called 'binman'. An example image description is shown
+below:
+
+ binman {
+ filename = "u-boot-sunxi-with-spl.bin";
+ pad-byte = <0xff>;
+ blob {
+ filename = "spl/sunxi-spl.bin";
+ };
+ u-boot {
+ pos = <CONFIG_SPL_PAD_TO>;
+ };
+ };
+
+
+This requests binman to create an image file called u-boot-sunxi-with-spl.bin
+consisting of a specially formatted SPL (spl/sunxi-spl.bin, built by the
+normal U-Boot Makefile), some 0xff padding, and a U-Boot legacy image. The
+padding comes from the fact that the second binary is placed at
+CONFIG_SPL_PAD_TO. If that line were omitted then the U-Boot binary would
+immediately follow the SPL binary.
+
+The binman node describes an image. The sub-nodes describe entries in the
+image. Each entry represents a region within the overall image. The name of
+the entry (blob, u-boot) tells binman what to put there. For 'blob' we must
+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.
+
+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
+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.
+
+align:
+ This sets the alignment of the entry. The entry position 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
+ provided, no alignment is performed.
+
+size:
+ This sets the size of the entry. The contents will be padded out to
+ this size. If this is not provided, it will be set to the size of the
+ contents.
+
+pad-before:
+ Padding before the contents of the entry. Normally this is 0, meaning
+ that the contents start at the beginning of the entry. This can be
+ offset the entry contents a little. Defaults to 0.
+
+pad-after:
+ Padding after the contents of the entry. Normally this is 0, meaning
+ that the entry ends at the last byte of content (unless adjusted by
+ other properties). This allows room to be created in the image for
+ this entry to expand later. Defaults to 0.
+
+align-size:
+ This sets the alignment of the entry size. For example, to ensure
+ that the size of an entry is a multiple of 64 bytes, set this to 64.
+ If 'align-size' is not provided, no alignment is performed.
+
+align-end:
+ This sets the alignment of the end of an entry. Some entries require
+ that they end on an alignment boundary, regardless of where they
+ start. If 'align-end' is not provided, no alignment is performed.
+
+ Note: This is not yet implemented in binman.
+
+filename:
+ For 'blob' types this provides the filename containing the binary to
+ put into the entry. If binman knows about the entry type (like
+ u-boot-bin), then there is no need to specify this.
+
+type:
+ Sets the type of an entry. This defaults to the entry name, but it is
+ possible to use any name, and then add (for example) 'type = "u-boot"'
+ to specify the type.
+
+
+The attributes supported for images are described below. Several are similar
+to those for entries.
+
+size:
+ Sets the image size in bytes, for example 'size = <0x100000>' for a
+ 1MB image.
+
+align-size:
+ This sets the alignment of the image size. For example, to ensure
+ that the image ends on a 512-byte boundary, use 'align-size = <512>'.
+ If 'align-size' is not provided, no alignment is performed.
+
+pad-before:
+ This sets the padding before the image entries. The first entry will
+ be positionad after the padding. This defaults to 0.
+
+pad-after:
+ This sets the padding after the image entries. The padding will be
+ placed after the last entry. This defaults to 0.
+
+pad-byte:
+ This specifies the pad byte to use when padding in the image. It
+ defaults to 0. To use 0xff, you would add 'pad-byte = <0xff>'.
+
+filename:
+ This specifies the image filename. It defaults to 'image.bin'.
+
+sort-by-pos:
+ 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
+ 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.
+
+multiple-images:
+ Normally only a single image is generated. To create more than one
+ image, put this property in the binman node. For example, this will
+ create image1.bin containing u-boot.bin, and image2.bin containing
+ both spl/u-boot-spl.bin and u-boot.bin:
+
+ binman {
+ multiple-images;
+ image1 {
+ u-boot {
+ };
+ };
+
+ image2 {
+ spl {
+ };
+ u-boot {
+ };
+ };
+ };
+
+end-at-4gb:
+ For x86 machines the ROM positions 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
+ this option, instead of 0 without this option.
+
+
+Examples of the above options can be found in the tests. See the
+tools/binman/test directory.
+
+
+Special properties
+------------------
+
+Some entries support special properties, documented here:
+
+u-boot-with-ucode-ptr:
+ optional-ucode: boolean property to make microcode optional. If the
+ u-boot.bin image does not include microcode, no error will
+ be generated.
+
+
+Order of image creation
+-----------------------
+
+Image creation proceeds in the following order, for each entry in the image.
+
+1. GetEntryContents() - the contents of each entry are obtained, normally by
+reading from a file. This calls the Entry.ObtainContents() to read the
+contents. The default version of Entry.ObtainContents() calls
+Entry.GetDefaultFilename() and then reads that file. So a common mechanism
+to select a file to read is to override that function in the subclass. The
+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.
+
+2. GetEntryPositions() - calls Entry.GetPositions() 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 {}.
+
+3. 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
+implementation of Pack() is usually sufficient.
+
+4. CheckSize() - checks that the contents of all the entries fits within
+the image size. If the image does not have a defined size, the size is set
+large enough to hold all the entries.
+
+5. CheckEntries() - checks that the entries do not overlap, nor extend
+outside the image.
+
+6. 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.
+
+7. BuildImage() - builds the image and writes it to a file. This is the final
+step.
+
+
+Automatic .dtsi inclusion
+-------------------------
+
+It is sometimes inconvenient to add a 'binman' node to the .dts file for each
+board. This can be done by using #include to bring in a common file. Another
+approach supported by the U-Boot build system is to automatically include
+a common header. You can then put the binman node (and anything else that is
+specific to U-Boot, such as u-boot,dm-pre-reloc properies) in that header
+file.
+
+Binman will search for the following files in arch/<arch>/dts:
+
+ <dts>-u-boot.dtsi where <dts> is the base name of the .dts file
+ <CONFIG_SYS_SOC>-u-boot.dtsi
+ <CONFIG_SYS_CPU>-u-boot.dtsi
+ <CONFIG_SYS_VENDOR>-u-boot.dtsi
+ u-boot.dtsi
+
+U-Boot will only use the first one that it finds. If you need to include a
+more general file you can do that from the more specific file using #include.
+If you are having trouble figuring out what is going on, you can uncomment
+the 'warning' line in scripts/Makefile.lib to see what it has found:
+
+ # Uncomment for debugging
+ # $(warning binman_dtsi_options: $(binman_dtsi_options))
+
+
+Code coverage
+-------------
+
+Binman is a critical tool and is designed to be very testable. Entry
+implementations target 100% test coverage. Run 'binman -T' to check this.
+
+To enable Python test coverage on Debian-type distributions (e.g. Ubuntu):
+
+ $ sudo apt-get install python-pip python-pytest
+ $ sudo pip install coverage
+
+
+Advanced Features / Technical docs
+----------------------------------
+
+The behaviour of entries is defined by the Entry class. All other entries are
+a subclass of this. An important subclass is Entry_blob which takes binary
+data from a file and places it in the entry. In fact most entry types are
+subclasses of Entry_blob.
+
+Each entry type is a separate file in the tools/binman/etype directory. Each
+file contains a class called Entry_<type> where <type> is the entry type.
+New entry types can be supported by adding new files in that directory.
+These will automatically be detected by binman when needed.
+
+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
+so they don't need to be set in the binman decription. It can also adjust
+entry contents.
+
+Most of the time such essoteric behaviour is not needed, but it can be
+essential for complex images.
+
+
+History / Credits
+-----------------
+
+Binman takes a lot of inspiration from a Chrome OS tool called
+'cros_bundle_firmware', which I wrote some years ago. That tool was based on
+a reasonably simple and sound design but has expanded greatly over the
+years. In particular its handling of x86 images is convoluted.
+
+Quite a few lessons have been learned which are hopefully be applied here.
+
+
+Design notes
+------------
+
+On the face of it, a tool to create firmware images should be fairly simple:
+just find all the input binaries and place them at the right place in the
+image. The difficulty comes from the wide variety of input types (simple
+flat binaries containing code, packaged data with various headers), packing
+requirments (alignment, spacing, device boundaries) and other required
+features such as hierarchical images.
+
+The design challenge is to make it easy to create simple images, while
+allowing the more complex cases to be supported. For example, for most
+images we don't much care exactly where each binary ends up, so we should
+not have to specify that unnecessarily.
+
+New entry types should aim to provide simple usage where possible. If new
+core features are needed, they can be added in the Entry base class.
+
+
+To do
+-----
+
+Some ideas:
+- Fill out the device tree to include the final position and size of each
+ entry (since the input file may not always specify these)
+- Use of-platdata to make the information available to code that is unable
+ to use device tree (such as a very small SPL image)
+- Write an image map to a text file
+- Allow easy building of images by specifying just the board name
+- Produce a full Python binding for libfdt (for upstream)
+- Add an option to decode an image into the constituent binaries
+- Suppoort hierarchical images (packing of binaries into another binary
+ which is then placed in the image)
+- Support building an image for a board (-b) more completely, with a
+ configurable build directory
+- Consider making binman work with buildman, although if it is used in the
+ Makefile, this will be automatic
+- Implement align-end
+
+--
+Simon Glass <sjg@chromium.org>
+7/7/2016
diff --git a/tools/binman/binman b/tools/binman/binman
new file mode 120000
index 0000000..979b7e4
--- /dev/null
+++ b/tools/binman/binman
@@ -0,0 +1 @@
+binman.py \ No newline at end of file
diff --git a/tools/binman/binman.py b/tools/binman/binman.py
new file mode 100755
index 0000000..7fb67cb
--- /dev/null
+++ b/tools/binman/binman.py
@@ -0,0 +1,114 @@
+#!/usr/bin/python
+
+# Copyright (c) 2016 Google, Inc
+# Written by Simon Glass <sjg@chromium.org>
+#
+# SPDX-License-Identifier: GPL-2.0+
+#
+# Creates binary images from input files controlled by a description
+#
+
+"""See README for more information"""
+
+import os
+import sys
+import traceback
+import unittest
+
+# Bring in the patman and dtoc libraries
+our_path = os.path.dirname(os.path.realpath(__file__))
+sys.path.append(os.path.join(our_path, '../patman'))
+sys.path.append(os.path.join(our_path, '../dtoc'))
+
+# Also allow entry-type modules to be brought in from the etype directory.
+sys.path.append(os.path.join(our_path, 'etype'))
+
+import cmdline
+import command
+import control
+
+def RunTests():
+ """Run the functional tests and any embedded doctests"""
+ import entry_test
+ import fdt_test
+ import func_test
+ import test
+ import doctest
+
+ result = unittest.TestResult()
+ for module in []:
+ suite = doctest.DocTestSuite(module)
+ suite.run(result)
+
+ sys.argv = [sys.argv[0]]
+ for module in (func_test.TestFunctional, fdt_test.TestFdt,
+ entry_test.TestEntry):
+ suite = unittest.TestLoader().loadTestsFromTestCase(module)
+ suite.run(result)
+
+ print result
+ for test, err in result.errors:
+ print test.id(), err
+ for test, err in result.failures:
+ print err
+
+def RunTestCoverage():
+ """Run the tests and check that we get 100% coverage"""
+ # This uses the build output from sandbox_spl to get _libfdt.so
+ cmd = ('PYTHONPATH=%s/sandbox_spl/tools coverage run '
+ '--include "tools/binman/*.py" --omit "*test*,*binman.py" '
+ 'tools/binman/binman.py -t' % options.build_dir)
+ os.system(cmd)
+ stdout = command.Output('coverage', 'report')
+ coverage = stdout.splitlines()[-1].split(' ')[-1]
+ if coverage != '100%':
+ print stdout
+ print "Type 'coverage html' to get a report in htmlcov/index.html"
+ raise ValueError('Coverage error: %s, but should be 100%%' % coverage)
+
+
+def RunBinman(options, args):
+ """Main entry point to binman once arguments are parsed
+
+ Args:
+ options: Command-line options
+ args: Non-option arguments
+ """
+ ret_code = 0
+
+ # For testing: This enables full exception traces.
+ #options.debug = True
+
+ if not options.debug:
+ sys.tracebacklimit = 0
+
+ if options.test:
+ RunTests()
+
+ 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)
+
+ else:
+ try:
+ ret_code = control.Binman(options, args)
+ except Exception as e:
+ print 'binman: %s' % e
+ if options.debug:
+ print
+ traceback.print_exc()
+ ret_code = 1
+ return ret_code
+
+
+if __name__ == "__main__":
+ (options, args) = cmdline.ParseArgs(sys.argv)
+ ret_code = RunBinman(options, args)
+ sys.exit(ret_code)
diff --git a/tools/binman/cmdline.py b/tools/binman/cmdline.py
new file mode 100644
index 0000000..233d5e1
--- /dev/null
+++ b/tools/binman/cmdline.py
@@ -0,0 +1,53 @@
+# Copyright (c) 2016 Google, Inc
+# Written by Simon Glass <sjg@chromium.org>
+#
+# SPDX-License-Identifier: GPL-2.0+
+#
+# Command-line parser for binman
+#
+
+from optparse import OptionParser
+
+def ParseArgs(argv):
+ """Parse the binman command-line arguments
+
+ Args:
+ argv: List of string arguments
+ Returns:
+ Tuple (options, args) with the command-line options and arugments.
+ options provides access to the options (e.g. option.debug)
+ args is a list of string arguments
+ """
+ parser = OptionParser()
+ parser.add_option('-b', '--board', type='string',
+ help='Board name to build')
+ parser.add_option('-B', '--build-dir', type='string', default='b',
+ help='Directory containing the build output')
+ parser.add_option('-d', '--dt', type='string',
+ 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('-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',
+ default=False, help='Display the README file')
+ parser.add_option('-O', '--outdir', type='string',
+ action='store', help='Path to directory to use for intermediate and '
+ 'output files')
+ parser.add_option('-p', '--preserve', action='store_true',\
+ help='Preserve temporary output directory even if option -O is not '
+ 'given')
+ parser.add_option('-t', '--test', action='store_true',
+ default=False, help='run tests')
+ parser.add_option('-T', '--test-coverage', action='store_true',
+ default=False, help='run tests and check for 100% coverage')
+ parser.add_option('-v', '--verbosity', default=1,
+ type='int', help='Control verbosity: 0=silent, 1=progress, 3=full, '
+ '4=debug')
+
+ parser.usage += """
+
+Create images for a board from a set of binaries. It is controlled by a
+description in the board device tree."""
+
+ return parser.parse_args(argv)
diff --git a/tools/binman/control.py b/tools/binman/control.py
new file mode 100644
index 0000000..e909678
--- /dev/null
+++ b/tools/binman/control.py
@@ -0,0 +1,118 @@
+# Copyright (c) 2016 Google, Inc
+# Written by Simon Glass <sjg@chromium.org>
+#
+# SPDX-License-Identifier: GPL-2.0+
+#
+# Creates binary images from input files controlled by a description
+#
+
+from collections import OrderedDict
+import os
+import sys
+import tools
+
+import command
+import fdt_select
+import fdt_util
+from image import Image
+import tout
+
+# List of images we plan to create
+# Make this global so that it can be referenced from tests
+images = OrderedDict()
+
+def _ReadImageDesc(binman_node):
+ """Read the image descriptions from the /binman node
+
+ This normally produces a single Image object called 'image'. But if
+ multiple images are present, they will all be returned.
+
+ Args:
+ binman_node: Node object of the /binman node
+ Returns:
+ OrderedDict of Image objects, each of which describes an image
+ """
+ images = OrderedDict()
+ if 'multiple-images' in binman_node.props:
+ for node in binman_node.subnodes:
+ images[node.name] = Image(node.name, node)
+ else:
+ images['image'] = Image('image', binman_node)
+ return images
+
+def _FindBinmanNode(fdt):
+ """Find the 'binman' node in the device tree
+
+ Args:
+ fdt: Fdt object to scan
+ Returns:
+ Node object of /binman node, or None if not found
+ """
+ for node in fdt.GetRoot().subnodes:
+ if node.name == 'binman':
+ return node
+ return None
+
+def Binman(options, args):
+ """The main control code for binman
+
+ This assumes that help and test options have already been dealt with. It
+ deals with the core task of building images.
+
+ Args:
+ options: Command line options object
+ args: Command line arguments (list of strings)
+ """
+ global images
+
+ if 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)
+ return 0
+
+ # Try to figure out which device tree contains our image description
+ if options.dt:
+ dtb_fname = options.dt
+ else:
+ board = options.board
+ if not board:
+ raise ValueError('Must provide a board to process (use -b <board>)')
+ board_pathname = os.path.join(options.build_dir, board)
+ dtb_fname = os.path.join(board_pathname, 'u-boot.dtb')
+ if not options.indir:
+ options.indir = ['.']
+ options.indir.append(board_pathname)
+
+ try:
+ tout.Init(options.verbosity)
+ try:
+ tools.SetInputDirs(options.indir)
+ tools.PrepareOutputDir(options.outdir, options.preserve)
+ fdt = fdt_select.FdtScan(dtb_fname)
+ node = _FindBinmanNode(fdt)
+ if not node:
+ raise ValueError("Device tree '%s' does not have a 'binman' "
+ "node" % dtb_fname)
+ images = _ReadImageDesc(node)
+ for image in images.values():
+ # Perform all steps for this image, including checking and
+ # writing it. This means that errors found with a later
+ # image will be reported after earlier images are already
+ # completed and written, but that does not seem important.
+ image.GetEntryContents()
+ image.GetEntryPositions()
+ image.PackEntries()
+ image.CheckSize()
+ image.CheckEntries()
+ image.ProcessEntryContents()
+ image.BuildImage()
+ finally:
+ tools.FinaliseOutputDir()
+ finally:
+ tout.Uninit()
+
+ return 0
diff --git a/tools/binman/entry_test.py b/tools/binman/entry_test.py
new file mode 100644
index 0000000..8a9ae01
--- /dev/null
+++ b/tools/binman/entry_test.py
@@ -0,0 +1,27 @@
+#
+# Copyright (c) 2016 Google, Inc
+# Written by Simon Glass <sjg@chromium.org>
+#
+# SPDX-License-Identifier: GPL-2.0+
+#
+# Test for the Entry class
+
+import collections
+import unittest
+
+import entry
+
+class TestEntry(unittest.TestCase):
+ def testEntryContents(self):
+ """Test the Entry bass class"""
+ base_entry = entry.Entry(None, None, None, read_node=False)
+ self.assertEqual(True, base_entry.ObtainContents())
+
+ def testUnknownEntry(self):
+ """Test that unknown entry types are detected"""
+ Node = collections.namedtuple('Node', ['name', 'path'])
+ node = Node('invalid-name', 'invalid-path')
+ with self.assertRaises(ValueError) as e:
+ entry.Entry.Create(None, node, node.name)
+ self.assertIn("Unknown entry type 'invalid-name' in node "
+ "'invalid-path'", str(e.exception))
diff --git a/tools/binman/etype/_testing.py b/tools/binman/etype/_testing.py
new file mode 100644
index 0000000..1783098
--- /dev/null
+++ b/tools/binman/etype/_testing.py
@@ -0,0 +1,26 @@
+# Copyright (c) 2016 Google, Inc
+# Written by Simon Glass <sjg@chromium.org>
+#
+# SPDX-License-Identifier: GPL-2.0+
+#
+# Entry-type module for testing purposes. Not used in real images.
+#
+
+from entry import Entry
+import fdt_util
+import tools
+
+class Entry__testing(Entry):
+ def __init__(self, image, etype, node):
+ Entry.__init__(self, image, etype, node)
+
+ def ObtainContents(self):
+ self.data = 'a'
+ self.contents_size = len(self.data)
+ return True
+
+ def ReadContents(self):
+ return True
+
+ def GetPositions(self):
+ return {'invalid-entry': [1, 2]}
diff --git a/tools/binman/etype/blob.py b/tools/binman/etype/blob.py
new file mode 100644
index 0000000..def2164
--- /dev/null
+++ b/tools/binman/etype/blob.py
@@ -0,0 +1,37 @@
+# Copyright (c) 2016 Google, Inc
+# Written by Simon Glass <sjg@chromium.org>
+#
+# SPDX-License-Identifier: GPL-2.0+
+#
+# Entry-type module for blobs, which are binary objects read from files
+#
+
+from entry import Entry
+import fdt_util
+import tools
+
+class Entry_blob(Entry):
+ def __init__(self, image, etype, node):
+ Entry.__init__(self, image, etype, node)
+ self._filename = fdt_util.GetString(self._node, "filename", self.etype)
+
+ def ObtainContents(self):
+ self._filename = self.GetDefaultFilename()
+ self._pathname = tools.GetInputFilename(self._filename)
+ self.ReadContents()
+ return True
+
+ def ReadContents(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.
+ # In that case, Image.BuildImage() could be adjusted to use a
+ # new Entry method which can read in chunks. Then we could copy
+ # the data in chunks and avoid reading it all at once. For now
+ # this seems like an unnecessary complication.
+ self.data = fd.read()
+ self.contents_size = len(self.data)
+ return True
+
+ def GetDefaultFilename(self):
+ return self._filename
diff --git a/tools/binman/etype/entry.py b/tools/binman/etype/entry.py
new file mode 100644
index 0000000..67c5734
--- /dev/null
+++ b/tools/binman/etype/entry.py
@@ -0,0 +1,200 @@
+# Copyright (c) 2016 Google, Inc
+#
+# SPDX-License-Identifier: GPL-2.0+
+#
+# Base class for all entries
+#
+
+# 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
+try:
+ import importlib
+ have_importlib = True
+except:
+ have_importlib = False
+
+import fdt_util
+import tools
+
+modules = {}
+
+class Entry(object):
+ """An Entry in the image
+
+ An entry corresponds to a single node in the device-tree description
+ of the image. Each entry ends up being a part of the final image.
+ Entries can be placed either right next to each other, or with padding
+ between them. The type of the entry determines the data that is in it.
+
+ This class is not used by itself. All entry objects are subclasses of
+ Entry.
+
+ Attributes:
+ image: The image containing this entry
+ node: The node that created this entry
+ pos: Absolute position of entry within the image, None if not known
+ 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_size: Entry size alignment, or None
+ align_end: Entry end position 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)
+ """
+ def __init__(self, image, etype, node, read_node=True):
+ self.image = image
+ self.etype = etype
+ self._node = node
+ self.pos = None
+ self.size = 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
+ if read_node:
+ self.ReadNode()
+
+ @staticmethod
+ def Create(image, node, etype=None):
+ """Create a new entry for a node.
+
+ Args:
+ image: 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)
+
+ Returns:
+ A new Entry object of the correct type (a subclass of Entry)
+ """
+ if not etype:
+ etype = fdt_util.GetString(node, 'type', node.name)
+ module_name = etype.replace('-', '_')
+ module = modules.get(module_name)
+
+ # Import the module if we have not already done so.
+ if not module:
+ try:
+ if have_importlib:
+ 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))
+ modules[module_name] = module
+
+ # Call its constructor to get the object we want.
+ obj = getattr(module, 'Entry_%s' % module_name)
+ return obj(image, etype, node)
+
+ def ReadNode(self):
+ """Read entry information from the node
+
+ This reads all the fields we recognise from the node, ready for use.
+ """
+ self.pos = fdt_util.GetInt(self._node, 'pos')
+ self.size = fdt_util.GetInt(self._node, 'size')
+ self.align = fdt_util.GetInt(self._node, 'align')
+ if tools.NotPowerOfTwo(self.align):
+ raise ValueError("Node '%s': Alignment %s must be a power of two" %
+ (self._node.path, self.align))
+ self.pad_before = fdt_util.GetInt(self._node, 'pad-before', 0)
+ self.pad_after = fdt_util.GetInt(self._node, 'pad-after', 0)
+ self.align_size = fdt_util.GetInt(self._node, 'align-size')
+ if tools.NotPowerOfTwo(self.align_size):
+ 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')
+
+ def ObtainContents(self):
+ """Figure out the contents of an entry.
+
+ Returns:
+ True if the contents were found, False if another call is needed
+ after the other entries are processed.
+ """
+ # No contents by default: subclasses can implement this
+ return True
+
+ def Pack(self, pos):
+ """Figure out how to pack the entry into the image
+
+ 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.
+
+ Once this function is complete, both the position and size of the
+ entry will be know.
+
+ Args:
+ Current image position pointer
+
+ Returns:
+ New image position 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)
+ 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
+
+ if not self.size:
+ self.size = size
+
+ if self.size < needed:
+ 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
+ # 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))
+
+ return new_pos
+
+ def Raise(self, msg):
+ """Convenience function to raise an error referencing a node"""
+ raise ValueError("Node '%s': %s" % (self._node.path, msg))
+
+ def GetPath(self):
+ """Get the path of a node
+
+ Returns:
+ Full path of the node for this entry
+ """
+ return self._node.path
+
+ def GetData(self):
+ return self.data
+
+ def GetPositions(self):
+ return {}
+
+ def SetPositionSize(self, pos, size):
+ self.pos = pos
+ self.size = size
+
+ def ProcessContents(self):
+ pass
diff --git a/tools/binman/etype/intel_cmc.py b/tools/binman/etype/intel_cmc.py
new file mode 100644
index 0000000..9bce8ae
--- /dev/null
+++ b/tools/binman/etype/intel_cmc.py
@@ -0,0 +1,17 @@
+# Copyright (c) 2016 Google, Inc
+# Written by Simon Glass <sjg@chromium.org>
+#
+# SPDX-License-Identifier: GPL-2.0+
+#
+# Entry-type module for Intel Chip Microcode binary blob
+#
+
+from entry import Entry
+from blob import Entry_blob
+
+class Entry_intel_cmc(Entry_blob):
+ def __init__(self, image, etype, node):
+ Entry_blob.__init__(self, image, etype, node)
+
+ def GetDefaultFilename(self):
+ return 'cmc.bin'
diff --git a/tools/binman/etype/intel_descriptor.py b/tools/binman/etype/intel_descriptor.py
new file mode 100644
index 0000000..7f4ea0b
--- /dev/null
+++ b/tools/binman/etype/intel_descriptor.py
@@ -0,0 +1,55 @@
+# Copyright (c) 2016 Google, Inc
+# Written by Simon Glass <sjg@chromium.org>
+#
+# SPDX-License-Identifier: GPL-2.0+
+#
+# Entry-type module for 'u-boot'
+#
+
+import struct
+
+from entry import Entry
+from blob import Entry_blob
+
+FD_SIGNATURE = struct.pack('<L', 0x0ff0a55a)
+MAX_REGIONS = 5
+
+(REGION_DESCRIPTOR, REGION_BIOS, REGION_ME, REGION_GBE,
+ REGION_PDATA) = range(5)
+
+class Region:
+ def __init__(self, data, frba, region_num):
+ pos = frba + region_num * 4
+ val = struct.unpack('<L', data[pos:pos + 4])[0]
+ self.base = (val & 0xfff) << 12
+ self.limit = ((val & 0x0fff0000) >> 4) | 0xfff
+ self.size = self.limit - self.base + 1
+
+class Entry_intel_descriptor(Entry_blob):
+ """Intel flash descriptor block (4KB)
+
+ This 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.
+ """
+ def __init__(self, image, etype, node):
+ Entry_blob.__init__(self, image, etype, node)
+ self._regions = []
+
+ def GetDefaultFilename(self):
+ return 'descriptor.bin'
+
+ def GetPositions(self):
+ pos = self.data.find(FD_SIGNATURE)
+ if pos == -1:
+ self.Raise('Cannot find FD signature')
+ flvalsig, flmap0, flmap1, flmap2 = struct.unpack('<LLLL',
+ self.data[pos:pos + 16])
+ frba = ((flmap0 >> 16) & 0xff) << 4
+ for i in range(MAX_REGIONS):
+ self._regions.append(Region(self.data, frba, i))
+
+ # Set the offset for ME only, for now, since the others are not used
+ return {'intel-me': [self._regions[REGION_ME].base,
+ self._regions[REGION_ME].size]}
diff --git a/tools/binman/etype/intel_fsp.py b/tools/binman/etype/intel_fsp.py
new file mode 100644
index 0000000..d75be5b
--- /dev/null
+++ b/tools/binman/etype/intel_fsp.py
@@ -0,0 +1,17 @@
+# Copyright (c) 2016 Google, Inc
+# Written by Simon Glass <sjg@chromium.org>
+#
+# SPDX-License-Identifier: GPL-2.0+
+#
+# Entry-type module for Intel Firmware Support Package binary blob
+#
+
+from entry import Entry
+from blob import Entry_blob
+
+class Entry_intel_fsp(Entry_blob):
+ def __init__(self, image, etype, node):
+ Entry_blob.__init__(self, image, etype, node)
+
+ def GetDefaultFilename(self):
+ return 'fsp.bin'
diff --git a/tools/binman/etype/intel_me.py b/tools/binman/etype/intel_me.py
new file mode 100644
index 0000000..45ab50c
--- /dev/null
+++ b/tools/binman/etype/intel_me.py
@@ -0,0 +1,17 @@
+# Copyright (c) 2016 Google, Inc
+# Written by Simon Glass <sjg@chromium.org>
+#
+# SPDX-License-Identifier: GPL-2.0+
+#
+# Entry-type module for Intel Management Engine binary blob
+#
+
+from entry import Entry
+from blob import Entry_blob
+
+class Entry_intel_me(Entry_blob):
+ def __init__(self, image, etype, node):
+ Entry_blob.__init__(self, image, etype, node)
+
+ def GetDefaultFilename(self):
+ return 'me.bin'
diff --git a/tools/binman/etype/intel_mrc.py b/tools/binman/etype/intel_mrc.py
new file mode 100644
index 0000000..f6cedb7
--- /dev/null
+++ b/tools/binman/etype/intel_mrc.py
@@ -0,0 +1,17 @@
+# Copyright (c) 2016 Google, Inc
+# Written by Simon Glass <sjg@chromium.org>
+#
+# SPDX-License-Identifier: GPL-2.0+
+#
+# Entry-type module for Intel Memory Reference Code binary blob
+#
+
+from entry import Entry
+from blob import Entry_blob
+
+class Entry_intel_mrc(Entry_blob):
+ def __init__(self, image, etype, node):
+ Entry_blob.__init__(self, image, etype, node)
+
+ def GetDefaultFilename(self):
+ return 'mrc.bin'
diff --git a/tools/binman/etype/intel_vga.py b/tools/binman/etype/intel_vga.py
new file mode 100644
index 0000000..d8f270b
--- /dev/null
+++ b/tools/binman/etype/intel_vga.py
@@ -0,0 +1,17 @@
+# Copyright (c) 2016 Google, Inc
+# Written by Simon Glass <sjg@chromium.org>
+#
+# SPDX-License-Identifier: GPL-2.0+
+#
+# Entry-type module for x86 VGA ROM binary blob
+#
+
+from entry import Entry
+from blob import Entry_blob
+
+class Entry_intel_vga(Entry_blob):
+ def __init__(self, image, etype, node):
+ Entry_blob.__init__(self, image, etype, node)
+
+ def GetDefaultFilename(self):
+ return 'vga.bin'
diff --git a/tools/binman/etype/u_boot.py b/tools/binman/etype/u_boot.py
new file mode 100644
index 0000000..1fcff73
--- /dev/null
+++ b/tools/binman/etype/u_boot.py
@@ -0,0 +1,17 @@
+# Copyright (c) 2016 Google, Inc
+# Written by Simon Glass <sjg@chromium.org>
+#
+# SPDX-License-Identifier: GPL-2.0+
+#
+# Entry-type module for U-Boot binary
+#
+
+from entry import Entry
+from blob import Entry_blob
+
+class Entry_u_boot(Entry_blob):
+ def __init__(self, image, etype, node):
+ Entry_blob.__init__(self, image, etype, node)
+
+ def GetDefaultFilename(self):
+ return 'u-boot.bin'
diff --git a/tools/binman/etype/u_boot_dtb.py b/tools/binman/etype/u_boot_dtb.py
new file mode 100644
index 0000000..1122c95
--- /dev/null
+++ b/tools/binman/etype/u_boot_dtb.py
@@ -0,0 +1,17 @@
+# Copyright (c) 2016 Google, Inc
+# Written by Simon Glass <sjg@chromium.org>
+#
+# SPDX-License-Identifier: GPL-2.0+
+#
+# Entry-type module for U-Boot device tree
+#
+
+from entry import Entry
+from blob import Entry_blob
+
+class Entry_u_boot_dtb(Entry_blob):
+ def __init__(self, image, etype, node):
+ Entry_blob.__init__(self, image, etype, node)
+
+ def GetDefaultFilename(self):
+ return 'u-boot.dtb'
diff --git a/tools/binman/etype/u_boot_dtb_with_ucode.py b/tools/binman/etype/u_boot_dtb_with_ucode.py
new file mode 100644
index 0000000..fc02c67
--- /dev/null
+++ b/tools/binman/etype/u_boot_dtb_with_ucode.py
@@ -0,0 +1,78 @@
+# Copyright (c) 2016 Google, Inc
+## Written by Simon Glass <sjg@chromium.org>
+
+# SPDX-License-Identifier: GPL-2.0+
+#
+# Entry-type module for U-Boot device tree with the microcode removed
+#
+
+import fdt_select
+from entry import Entry
+from blob import Entry_blob
+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.
+ """
+ def __init__(self, image, etype, node):
+ Entry_blob.__init__(self, image, etype, node)
+ self.ucode_data = ''
+ self.collate = False
+ self.ucode_offset = None
+ self.ucode_size = None
+
+ def GetDefaultFilename(self):
+ return 'u-boot.dtb'
+
+ def ObtainContents(self):
+ Entry_blob.ObtainContents(self)
+
+ # If the image does not need microcode, there is nothing to do
+ ucode_dest_entry = self.image.FindEntryType('u-boot-spl-with-ucode-ptr')
+ if not ucode_dest_entry or not ucode_dest_entry.target_pos:
+ ucode_dest_entry = self.image.FindEntryType('u-boot-with-ucode-ptr')
+ if not ucode_dest_entry or not ucode_dest_entry.target_pos:
+ return True
+
+ # Create a new file to hold the copied device tree
+ dtb_name = 'u-boot-dtb-with-ucode.dtb'
+ fname = tools.GetOutputFilename(dtb_name)
+ with open(fname, 'wb') as fd:
+ fd.write(self.data)
+
+ # Remove the microcode
+ fdt = fdt_select.FdtScan(fname)
+ fdt.Scan()
+ ucode = fdt.GetNode('/microcode')
+ if not ucode:
+ raise self.Raise("No /microcode node found in '%s'" % fname)
+
+ # There's no need to collate it (move all microcode into one place)
+ # if we only have one chunk of microcode.
+ self.collate = len(ucode.subnodes) > 1
+ for node in ucode.subnodes:
+ data_prop = node.props.get('data')
+ if data_prop:
+ self.ucode_data += ''.join(data_prop.bytes)
+ if not self.collate:
+ poffset = data_prop.GetOffset()
+ if poffset is None:
+ # We cannot obtain a property offset. Collate instead.
+ self.collate = True
+ else:
+ # Find the offset in the device tree of the ucode data
+ self.ucode_offset = poffset + 12
+ self.ucode_size = len(data_prop.bytes)
+ if self.collate:
+ prop = node.DeleteProp('data')
+ if self.collate:
+ fdt.Pack()
+ fdt.Flush()
+
+ # Make this file the contents of this entry
+ self._pathname = fname
+ self.ReadContents()
+ return True
diff --git a/tools/binman/etype/u_boot_img.py b/tools/binman/etype/u_boot_img.py
new file mode 100644
index 0000000..744f1b4
--- /dev/null
+++ b/tools/binman/etype/u_boot_img.py
@@ -0,0 +1,17 @@
+# Copyright (c) 2016 Google, Inc
+# Written by Simon Glass <sjg@chromium.org>
+#
+# SPDX-License-Identifier: GPL-2.0+
+#
+# Entry-type module for U-Boot binary
+#
+
+from entry import Entry
+from blob import Entry_blob
+
+class Entry_u_boot_img(Entry_blob):
+ def __init__(self, image, etype, node):
+ Entry_blob.__init__(self, image, etype, node)
+
+ def GetDefaultFilename(self):
+ return 'u-boot.img'
diff --git a/tools/binman/etype/u_boot_nodtb.py b/tools/binman/etype/u_boot_nodtb.py
new file mode 100644
index 0000000..3721c3b
--- /dev/null
+++ b/tools/binman/etype/u_boot_nodtb.py
@@ -0,0 +1,17 @@
+# Copyright (c) 2016 Google, Inc
+# Written by Simon Glass <sjg@chromium.org>
+#
+# SPDX-License-Identifier: GPL-2.0+
+#
+# Entry-type module for 'u-boot-nodtb.bin'
+#
+
+from entry import Entry
+from blob import Entry_blob
+
+class Entry_u_boot_nodtb(Entry_blob):
+ def __init__(self, image, etype, node):
+ Entry_blob.__init__(self, image, etype, node)
+
+ def GetDefaultFilename(self):
+ return 'u-boot-nodtb.bin'
diff --git a/tools/binman/etype/u_boot_spl.py b/tools/binman/etype/u_boot_spl.py
new file mode 100644
index 0000000..68b0148
--- /dev/null
+++ b/tools/binman/etype/u_boot_spl.py
@@ -0,0 +1,17 @@
+# Copyright (c) 2016 Google, Inc
+# Written by Simon Glass <sjg@chromium.org>
+#
+# SPDX-License-Identifier: GPL-2.0+
+#
+# Entry-type module for spl/u-boot-spl.bin
+#
+
+from entry import Entry
+from blob import Entry_blob
+
+class Entry_u_boot_spl(Entry_blob):
+ def __init__(self, image, etype, node):
+ Entry_blob.__init__(self, image, etype, node)
+
+ def GetDefaultFilename(self):
+ return 'spl/u-boot-spl.bin'
diff --git a/tools/binman/etype/u_boot_spl_bss_pad.py b/tools/binman/etype/u_boot_spl_bss_pad.py
new file mode 100644
index 0000000..c005f28
--- /dev/null
+++ b/tools/binman/etype/u_boot_spl_bss_pad.py
@@ -0,0 +1,26 @@
+# Copyright (c) 2016 Google, Inc
+# Written by Simon Glass <sjg@chromium.org>
+#
+# SPDX-License-Identifier: GPL-2.0+
+#
+# Entry-type module for BSS padding for spl/u-boot-spl.bin. This padding
+# can be added after the SPL binary to ensure that anything concatenated
+# to it will appear to SPL to be at the end of BSS rather than the start.
+#
+
+import command
+from entry import Entry
+from blob import Entry_blob
+import tools
+
+class Entry_u_boot_spl_bss_pad(Entry_blob):
+ def __init__(self, image, etype, node):
+ Entry_blob.__init__(self, image, etype, node)
+
+ def ObtainContents(self):
+ fname = tools.GetInputFilename('spl/u-boot-spl')
+ args = [['nm', fname], ['grep', '__bss_size']]
+ out = command.RunPipe(args, capture=True).stdout.splitlines()
+ bss_size = int(out[0].split()[0], 16)
+ self.data = chr(0) * bss_size
+ self.contents_size = bss_size
diff --git a/tools/binman/etype/u_boot_spl_with_ucode_ptr.py b/tools/binman/etype/u_boot_spl_with_ucode_ptr.py
new file mode 100644
index 0000000..764c282
--- /dev/null
+++ b/tools/binman/etype/u_boot_spl_with_ucode_ptr.py
@@ -0,0 +1,28 @@
+# Copyright (c) 2016 Google, Inc
+# Written by Simon Glass <sjg@chromium.org>
+#
+# SPDX-License-Identifier: GPL-2.0+
+#
+# Entry-type module for an SPL binary with an embedded microcode pointer
+#
+
+import struct
+
+import command
+from entry import Entry
+from blob import Entry_blob
+from u_boot_with_ucode_ptr import Entry_u_boot_with_ucode_ptr
+import tools
+
+class Entry_u_boot_spl_with_ucode_ptr(Entry_u_boot_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.
+ """
+ def __init__(self, image, etype, node):
+ Entry_blob.__init__(self, image, etype, node)
+ self.elf_fname = 'spl/u-boot-spl'
+
+ def GetDefaultFilename(self):
+ return 'spl/u-boot-spl.bin'
diff --git a/tools/binman/etype/u_boot_ucode.py b/tools/binman/etype/u_boot_ucode.py
new file mode 100644
index 0000000..8fe27ac
--- /dev/null
+++ b/tools/binman/etype/u_boot_ucode.py
@@ -0,0 +1,84 @@
+# Copyright (c) 2016 Google, Inc
+# Written by Simon Glass <sjg@chromium.org>
+#
+# SPDX-License-Identifier: GPL-2.0+
+#
+# Entry-type module for a U-Boot binary with an embedded microcode pointer
+#
+
+from entry import Entry
+from blob import Entry_blob
+import tools
+
+class Entry_u_boot_ucode(Entry_blob):
+ """U-Boot microcode block
+
+ 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.
+ """
+ def __init__(self, image, etype, node):
+ Entry_blob.__init__(self, image, etype, node)
+
+ def ObtainContents(self):
+ # If the image does not need microcode, there is nothing to do
+ ucode_dest_entry = self.image.FindEntryType('u-boot-with-ucode-ptr')
+ if ucode_dest_entry and not ucode_dest_entry.target_pos:
+ self.data = ''
+ return True
+
+ # Get the microcode from the device tree entry
+ fdt_entry = self.image.FindEntryType('u-boot-dtb-with-ucode')
+ if not fdt_entry or not fdt_entry.ucode_data:
+ return False
+
+ if not fdt_entry.collate:
+ # This section can be empty
+ self.data = ''
+ return True
+
+ # Write it out to a file
+ dtb_name = 'u-boot-ucode.bin'
+ fname = tools.GetOutputFilename(dtb_name)
+ with open(fname, 'wb') as fd:
+ fd.write(fdt_entry.ucode_data)
+
+ self._pathname = fname
+ self.ReadContents()
+
+ return True
diff --git a/tools/binman/etype/u_boot_with_ucode_ptr.py b/tools/binman/etype/u_boot_with_ucode_ptr.py
new file mode 100644
index 0000000..6f01adb
--- /dev/null
+++ b/tools/binman/etype/u_boot_with_ucode_ptr.py
@@ -0,0 +1,87 @@
+# Copyright (c) 2016 Google, Inc
+# Written by Simon Glass <sjg@chromium.org>
+#
+# SPDX-License-Identifier: GPL-2.0+
+#
+# Entry-type module for a U-Boot binary with an embedded microcode pointer
+#
+
+import struct
+
+import command
+from entry import Entry
+from blob import Entry_blob
+import fdt_util
+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.
+ """
+ def __init__(self, image, etype, node):
+ Entry_blob.__init__(self, image, etype, node)
+ self.elf_fname = 'u-boot'
+ self.target_pos = None
+
+ def GetDefaultFilename(self):
+ return 'u-boot-nodtb.bin'
+
+ def ObtainContents(self):
+ # Figure out where to put the microcode pointer
+ fname = tools.GetInputFilename(self.elf_fname)
+ args = [['nm', fname], ['grep', '-w', '_dt_ucode_base_size']]
+ out = (command.RunPipe(args, capture=True, raise_on_error=False).
+ stdout.splitlines())
+ if len(out) == 1:
+ self.target_pos = int(out[0].split()[0], 16)
+ elif not fdt_util.GetBool(self._node, 'optional-ucode'):
+ self.Raise('Cannot locate _dt_ucode_base_size symbol in u-boot')
+
+ return Entry_blob.ObtainContents(self)
+
+ def ProcessContents(self):
+ # If the image does not need microcode, there is nothing to do
+ if not self.target_pos:
+ return
+
+ # Get the position of the microcode
+ ucode_entry = self.image.FindEntryType('u-boot-ucode')
+ if not ucode_entry:
+ self.Raise('Cannot find microcode region u-boot-ucode')
+
+ # Check the target pos is in the image. If it is not, then U-Boot is
+ # being linked incorrectly, or is being placed at the wrong position
+ # in the image.
+ #
+ # The image 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 image. In this
+ # case the ROM starts at 0xff800000, so the position of the first
+ # entry in the image corresponds to that.
+ if (self.target_pos < self.pos or
+ self.target_pos >= self.pos + self.size):
+ self.Raise('Microcode pointer _dt_ucode_base_size at %08x is '
+ 'outside the image ranging from %08x to %08x' %
+ (self.target_pos, self.pos, self.pos + 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
+ else:
+ dtb_entry = self.image.FindEntryType('u-boot-dtb-with-ucode')
+ if not dtb_entry:
+ self.Raise('Cannot find microcode region u-boot-dtb-with-ucode')
+ pos = dtb_entry.pos + 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.data = (self.data[:self.target_pos] + pos_and_size +
+ self.data[self.target_pos + 8:])
diff --git a/tools/binman/etype/x86_start16.py b/tools/binman/etype/x86_start16.py
new file mode 100644
index 0000000..a44ea68
--- /dev/null
+++ b/tools/binman/etype/x86_start16.py
@@ -0,0 +1,17 @@
+# Copyright (c) 2016 Google, Inc
+# Written by Simon Glass <sjg@chromium.org>
+#
+# SPDX-License-Identifier: GPL-2.0+
+#
+# Entry-type module for the 16-bit x86 start-up code for U-Boot
+#
+
+from entry import Entry
+from blob import Entry_blob
+
+class Entry_x86_start16(Entry_blob):
+ def __init__(self, image, etype, node):
+ Entry_blob.__init__(self, image, etype, node)
+
+ def GetDefaultFilename(self):
+ return 'u-boot-x86-16bit.bin'
diff --git a/tools/binman/etype/x86_start16_spl.py b/tools/binman/etype/x86_start16_spl.py
new file mode 100644
index 0000000..3679a43
--- /dev/null
+++ b/tools/binman/etype/x86_start16_spl.py
@@ -0,0 +1,17 @@
+# Copyright (c) 2016 Google, Inc
+# Written by Simon Glass <sjg@chromium.org>
+#
+# SPDX-License-Identifier: GPL-2.0+
+#
+# Entry-type module for the 16-bit x86 start-up code for U-Boot SPL
+#
+
+from entry import Entry
+from blob import Entry_blob
+
+class Entry_x86_start16_spl(Entry_blob):
+ def __init__(self, image, etype, node):
+ Entry_blob.__init__(self, image, etype, node)
+
+ def GetDefaultFilename(self):
+ return 'spl/u-boot-x86-16bit-spl.bin'
diff --git a/tools/binman/fdt_test.py b/tools/binman/fdt_test.py
new file mode 100644
index 0000000..1d9494e
--- /dev/null
+++ b/tools/binman/fdt_test.py
@@ -0,0 +1,48 @@
+#
+# Copyright (c) 2016 Google, Inc
+# Written by Simon Glass <sjg@chromium.org>
+#
+# SPDX-License-Identifier: GPL-2.0+
+#
+# Test for the fdt modules
+
+import os
+import sys
+import tempfile
+import unittest
+
+from fdt_select import FdtScan
+import fdt_util
+import tools
+
+class TestFdt(unittest.TestCase):
+ @classmethod
+ def setUpClass(self):
+ self._binman_dir = os.path.dirname(os.path.realpath(sys.argv[0]))
+ self._indir = tempfile.mkdtemp(prefix='binmant.')
+ tools.PrepareOutputDir(self._indir, True)
+
+ def TestFile(self, fname):
+ return os.path.join(self._binman_dir, 'test', fname)
+
+ def GetCompiled(self, fname):
+ return fdt_util.EnsureCompiled(self.TestFile(fname))
+
+ def _DeleteProp(self, fdt):
+ node = fdt.GetNode('/microcode/update@0')
+ node.DeleteProp('data')
+
+ def testFdtNormal(self):
+ fname = self.GetCompiled('34_x86_ucode.dts')
+ fdt = FdtScan(fname)
+ self._DeleteProp(fdt)
+
+ def testFdtFallback(self):
+ fname = self.GetCompiled('34_x86_ucode.dts')
+ fdt = FdtScan(fname, True)
+ fdt.GetProp('/microcode/update@0', 'data')
+ self.assertEqual('fred',
+ fdt.GetProp('/microcode/update@0', 'none', default='fred'))
+ self.assertEqual('12345678 12345679',
+ fdt.GetProp('/microcode/update@0', 'data', typespec='x'))
+ self._DeleteProp(fdt)
diff --git a/tools/binman/func_test.py b/tools/binman/func_test.py
new file mode 100644
index 0000000..740fa9e
--- /dev/null
+++ b/tools/binman/func_test.py
@@ -0,0 +1,822 @@
+#
+# Copyright (c) 2016 Google, Inc
+# Written by Simon Glass <sjg@chromium.org>
+#
+# SPDX-License-Identifier: GPL-2.0+
+#
+# To run a single test, change to this directory, and:
+#
+# python -m unittest func_test.TestFunctional.testHelp
+
+from optparse import OptionParser
+import os
+import shutil
+import struct
+import sys
+import tempfile
+import unittest
+
+import binman
+import cmdline
+import command
+import control
+import entry
+import fdt_select
+import fdt_util
+import tools
+import tout
+
+# Contents of test files, corresponding to different entry types
+U_BOOT_DATA = '1234'
+U_BOOT_IMG_DATA = 'img'
+U_BOOT_SPL_DATA = '567'
+BLOB_DATA = '89'
+ME_DATA = '0abcd'
+VGA_DATA = 'vga'
+U_BOOT_DTB_DATA = 'udtb'
+X86_START16_DATA = 'start16'
+U_BOOT_NODTB_DATA = 'nodtb with microcode pointer somewhere in here'
+FSP_DATA = 'fsp'
+CMC_DATA = 'cmc'
+
+class TestFunctional(unittest.TestCase):
+ """Functional tests for binman
+
+ Most of these use a sample .dts file to build an image and then check
+ that it looks correct. The sample files are in the test/ subdirectory
+ and are numbered.
+
+ For each entry type a very small test file is created using fixed
+ string contents. This makes it easy to test that things look right, and
+ debug problems.
+
+ In some cases a 'real' file must be used - these are also supplied in
+ the test/ diurectory.
+ """
+ @classmethod
+ def setUpClass(self):
+ # Handle the case where argv[0] is 'python'
+ self._binman_dir = os.path.dirname(os.path.realpath(sys.argv[0]))
+ self._binman_pathname = os.path.join(self._binman_dir, 'binman')
+
+ # Create a temporary directory for input files
+ self._indir = tempfile.mkdtemp(prefix='binmant.')
+
+ # Create some test files
+ 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('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('u-boot-x86-16bit.bin', X86_START16_DATA)
+ TestFunctional._MakeInputFile('u-boot-nodtb.bin', U_BOOT_NODTB_DATA)
+ TestFunctional._MakeInputFile('fsp.bin', FSP_DATA)
+ TestFunctional._MakeInputFile('cmc.bin', CMC_DATA)
+ self._output_setup = False
+
+ # ELF file with a '_dt_ucode_base_size' symbol
+ with open(self.TestFile('u_boot_ucode_ptr')) as fd:
+ TestFunctional._MakeInputFile('u-boot', fd.read())
+
+ # Intel flash descriptor file
+ with open(self.TestFile('descriptor.bin')) as fd:
+ TestFunctional._MakeInputFile('descriptor.bin', fd.read())
+
+ @classmethod
+ def tearDownClass(self):
+ """Remove the temporary input directory and its contents"""
+ if self._indir:
+ shutil.rmtree(self._indir)
+ self._indir = None
+
+ def setUp(self):
+ # Enable this to turn on debugging output
+ # tout.Init(tout.DEBUG)
+ command.test_result = None
+
+ def tearDown(self):
+ """Remove the temporary output directory"""
+ tools._FinaliseForTest()
+
+ def _RunBinman(self, *args, **kwargs):
+ """Run binman using the command line
+
+ Args:
+ Arguments to pass, as a list of strings
+ kwargs: Arguments to pass to Command.RunPipe()
+ """
+ result = command.RunPipe([[self._binman_pathname] + list(args)],
+ capture=True, capture_stderr=True, raise_on_error=False)
+ if result.return_code and kwargs.get('raise_on_error', True):
+ raise Exception("Error running '%s': %s" % (' '.join(args),
+ result.stdout + result.stderr))
+ return result
+
+ def _DoBinman(self, *args):
+ """Run binman using directly (in the same process)
+
+ Args:
+ Arguments to pass, as a list of strings
+ Returns:
+ Return value (0 for success)
+ """
+ (options, args) = cmdline.ParseArgs(list(args))
+ options.pager = 'binman-invalid-pager'
+ options.build_dir = self._indir
+
+ # For testing, you can force an increase in verbosity here
+ # options.verbosity = tout.DEBUG
+ return control.Binman(options, args)
+
+ def _DoTestFile(self, fname):
+ """Run binman with a given test file
+
+ Args:
+ fname: Device tree source filename to use (e.g. 05_simple.dts)
+ """
+ return self._DoBinman('-p', '-I', self._indir,
+ '-d', self.TestFile(fname))
+
+ def _SetupDtb(self, fname, outfile='u-boot.dtb'):
+ """Set up a new test device-tree file
+
+ The given file is compiled and set up as the device tree to be used
+ for ths test.
+
+ Args:
+ fname: Filename of .dts file to read
+ outfile: Output filename for compiled device tree binary
+
+ Returns:
+ Contents of device tree binary
+ """
+ if not self._output_setup:
+ tools.PrepareOutputDir(self._indir, True)
+ self._output_setup = True
+ dtb = fdt_util.EnsureCompiled(self.TestFile(fname))
+ with open(dtb) as fd:
+ data = fd.read()
+ TestFunctional._MakeInputFile(outfile, data)
+ return data
+
+ def _DoReadFileDtb(self, fname, use_real_dtb=False):
+ """Run binman and return the resulting image
+
+ This runs binman with a given test file and then reads the resulting
+ output file. It is a shortcut function since most tests need to do
+ these steps.
+
+ Raises an assertion failure if binman returns a non-zero exit code.
+
+ Args:
+ fname: Device tree source filename to use (e.g. 05_simple.dts)
+ use_real_dtb: True to use the test file as the contents of
+ 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:
+ Tuple:
+ Resulting image contents
+ Device tree contents
+ """
+ dtb_data = None
+ # Use the compiled test file as the u-boot-dtb input
+ if use_real_dtb:
+ dtb_data = self._SetupDtb(fname)
+
+ try:
+ retcode = self._DoTestFile(fname)
+ self.assertEqual(0, retcode)
+
+ # Find the (only) image, read it and return its contents
+ image = control.images['image']
+ fname = tools.GetOutputFilename('image.bin')
+ self.assertTrue(os.path.exists(fname))
+ with open(fname) as fd:
+ return fd.read(), dtb_data
+ finally:
+ # Put the test file back
+ if use_real_dtb:
+ TestFunctional._MakeInputFile('u-boot.dtb', U_BOOT_DTB_DATA)
+
+ def _DoReadFile(self, fname, use_real_dtb=False):
+ """Helper function which discards the device-tree binary"""
+ return self._DoReadFileDtb(fname, use_real_dtb)[0]
+
+ @classmethod
+ def _MakeInputFile(self, fname, contents):
+ """Create a new test input file, creating directories as needed
+
+ Args:
+ fname: Filenaem to create
+ contents: File contents to write in to the file
+ Returns:
+ Full pathname of file created
+ """
+ pathname = os.path.join(self._indir, fname)
+ dirname = os.path.dirname(pathname)
+ if dirname and not os.path.exists(dirname):
+ os.makedirs(dirname)
+ with open(pathname, 'wb') as fd:
+ fd.write(contents)
+ return pathname
+
+ @classmethod
+ def TestFile(self, fname):
+ return os.path.join(self._binman_dir, 'test', fname)
+
+ def AssertInList(self, grep_list, target):
+ """Assert that at least one of a list of things is in a target
+
+ Args:
+ grep_list: List of strings to check
+ target: Target string
+ """
+ for grep in grep_list:
+ if grep in target:
+ return
+ self.fail("Error: '%' not found in '%s'" % (grep_list, target))
+
+ def CheckNoGaps(self, entries):
+ """Check that all entries fit together without gaps
+
+ Args:
+ entries: List of entries to check
+ """
+ pos = 0
+ for entry in entries.values():
+ self.assertEqual(pos, entry.pos)
+ pos += entry.size
+
+ def GetFdtLen(self, dtb):
+ """Get the totalsize field from a device tree binary
+
+ Args:
+ dtb: Device tree binary contents
+
+ Returns:
+ Total size of device tree binary, from the header
+ """
+ return struct.unpack('>L', dtb[4:8])[0]
+
+ def testRun(self):
+ """Test a basic run with valid args"""
+ result = self._RunBinman('-h')
+
+ def testFullHelp(self):
+ """Test that the full help is displayed with -H"""
+ result = self._RunBinman('-H')
+ help_file = os.path.join(self._binman_dir, 'README')
+ self.assertEqual(len(result.stdout), os.path.getsize(help_file))
+ self.assertEqual(0, len(result.stderr))
+ self.assertEqual(0, result.return_code)
+
+ def testFullHelpInternal(self):
+ """Test that the full help is displayed with -H"""
+ try:
+ command.test_result = command.CommandResult()
+ result = self._DoBinman('-H')
+ help_file = os.path.join(self._binman_dir, 'README')
+ finally:
+ command.test_result = None
+
+ def testHelp(self):
+ """Test that the basic help is displayed with -h"""
+ result = self._RunBinman('-h')
+ self.assertTrue(len(result.stdout) > 200)
+ self.assertEqual(0, len(result.stderr))
+ self.assertEqual(0, result.return_code)
+
+ # Not yet available.
+ def testBoard(self):
+ """Test that we can run it with a specific board"""
+ self._SetupDtb('05_simple.dts', 'sandbox/u-boot.dtb')
+ TestFunctional._MakeInputFile('sandbox/u-boot.bin', U_BOOT_DATA)
+ result = self._DoBinman('-b', 'sandbox')
+ self.assertEqual(0, result)
+
+ def testNeedBoard(self):
+ """Test that we get an error when no board ius supplied"""
+ with self.assertRaises(ValueError) as e:
+ result = self._DoBinman()
+ self.assertIn("Must provide a board to process (use -b <board>)",
+ str(e.exception))
+
+ def testMissingDt(self):
+ """Test that an invalid device tree file generates an error"""
+ with self.assertRaises(Exception) as e:
+ self._RunBinman('-d', 'missing_file')
+ # We get one error from libfdt, and a different one from fdtget.
+ self.AssertInList(["Couldn't open blob from 'missing_file'",
+ 'No such file or directory'], str(e.exception))
+
+ def testBrokenDt(self):
+ """Test that an invalid device tree source file generates an error
+
+ Since this is a source file it should be compiled and the error
+ will come from the device-tree compiler (dtc).
+ """
+ with self.assertRaises(Exception) as e:
+ self._RunBinman('-d', self.TestFile('01_invalid.dts'))
+ self.assertIn("FATAL ERROR: Unable to parse input tree",
+ str(e.exception))
+
+ def testMissingNode(self):
+ """Test that a device tree without a 'binman' node generates an error"""
+ with self.assertRaises(Exception) as e:
+ self._DoBinman('-d', self.TestFile('02_missing_node.dts'))
+ self.assertIn("does not have a 'binman' node", str(e.exception))
+
+ def testEmpty(self):
+ """Test that an empty binman node works OK (i.e. does nothing)"""
+ result = self._RunBinman('-d', self.TestFile('03_empty.dts'))
+ self.assertEqual(0, len(result.stderr))
+ self.assertEqual(0, result.return_code)
+
+ def testInvalidEntry(self):
+ """Test that an invalid entry is flagged"""
+ 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))
+
+ def testSimple(self):
+ """Test a simple binman with a single file"""
+ data = self._DoReadFile('05_simple.dts')
+ self.assertEqual(U_BOOT_DATA, data)
+
+ def testDual(self):
+ """Test that we can handle creating two images
+
+ This also tests image padding.
+ """
+ retcode = self._DoTestFile('06_dual_image.dts')
+ self.assertEqual(0, retcode)
+
+ image = control.images['image1']
+ self.assertEqual(len(U_BOOT_DATA), image._size)
+ fname = tools.GetOutputFilename('image1.bin')
+ self.assertTrue(os.path.exists(fname))
+ with open(fname) as fd:
+ data = fd.read()
+ self.assertEqual(U_BOOT_DATA, data)
+
+ image = control.images['image2']
+ self.assertEqual(3 + len(U_BOOT_DATA) + 5, image._size)
+ fname = tools.GetOutputFilename('image2.bin')
+ self.assertTrue(os.path.exists(fname))
+ with open(fname) as fd:
+ data = fd.read()
+ self.assertEqual(U_BOOT_DATA, data[3:7])
+ self.assertEqual(chr(0) * 3, data[:3])
+ self.assertEqual(chr(0) * 5, data[7:])
+
+ def testBadAlign(self):
+ """Test that an invalid alignment value is detected"""
+ with self.assertRaises(ValueError) as e:
+ self._DoTestFile('07_bad_align.dts')
+ self.assertIn("Node '/binman/u-boot': Alignment 23 must be a power "
+ "of two", str(e.exception))
+
+ def testPackSimple(self):
+ """Test that packing works as expected"""
+ retcode = self._DoTestFile('08_pack.dts')
+ self.assertEqual(0, retcode)
+ self.assertIn('image', control.images)
+ image = control.images['image']
+ entries = image._entries
+ self.assertEqual(5, len(entries))
+
+ # First u-boot
+ self.assertIn('u-boot', entries)
+ entry = entries['u-boot']
+ self.assertEqual(0, entry.pos)
+ 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(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(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(len(U_BOOT_DATA), entry.size)
+
+ # Fifth u-boot, placed at a fixed position
+ self.assertIn('u-boot-fixed', entries)
+ entry = entries['u-boot-fixed']
+ self.assertEqual(61, entry.pos)
+ self.assertEqual(len(U_BOOT_DATA), entry.size)
+
+ self.assertEqual(65, image._size)
+
+ def testPackExtra(self):
+ """Test that extra packing feature works as expected"""
+ retcode = self._DoTestFile('09_pack_extra.dts')
+
+ self.assertEqual(0, retcode)
+ self.assertIn('image', control.images)
+ image = control.images['image']
+ entries = image._entries
+ self.assertEqual(5, len(entries))
+
+ # First u-boot with padding before and after
+ self.assertIn('u-boot', entries)
+ entry = entries['u-boot']
+ self.assertEqual(0, entry.pos)
+ 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(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(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(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.size)
+
+ self.CheckNoGaps(entries)
+ self.assertEqual(128, image._size)
+
+ def testPackAlignPowerOf2(self):
+ """Test that invalid entry alignment is detected"""
+ with self.assertRaises(ValueError) as e:
+ self._DoTestFile('10_pack_align_power2.dts')
+ self.assertIn("Node '/binman/u-boot': Alignment 5 must be a power "
+ "of two", str(e.exception))
+
+ def testPackAlignSizePowerOf2(self):
+ """Test that invalid entry size alignment is detected"""
+ with self.assertRaises(ValueError) as e:
+ self._DoTestFile('11_pack_align_size_power2.dts')
+ self.assertIn("Node '/binman/u-boot': Alignment size 55 must be a "
+ "power of two", str(e.exception))
+
+ def testPackInvalidAlign(self):
+ """Test detection of an position 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 "
+ "align 0x4 (4)", str(e.exception))
+
+ def testPackInvalidSizeAlign(self):
+ """Test that invalid entry size alignment is detected"""
+ with self.assertRaises(ValueError) as e:
+ self._DoTestFile('13_pack_inv_size_align.dts')
+ self.assertIn("Node '/binman/u-boot': Size 0x5 (5) does not match "
+ "align-size 0x4 (4)", str(e.exception))
+
+ def testPackOverlap(self):
+ """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 "
+ "with previous entry '/binman/u-boot' ending at 0x4 (4)",
+ str(e.exception))
+
+ def testPackEntryOverflow(self):
+ """Test that entries that overflow their size are detected"""
+ with self.assertRaises(ValueError) as e:
+ self._DoTestFile('15_pack_overflow.dts')
+ self.assertIn("Node '/binman/u-boot': Entry contents size is 0x4 (4) "
+ "but entry size is 0x3 (3)", str(e.exception))
+
+ def testPackImageOverflow(self):
+ """Test that entries which overflow the image size are detected"""
+ with self.assertRaises(ValueError) as e:
+ self._DoTestFile('16_pack_image_overflow.dts')
+ self.assertIn("Image '/binman': contents size 0x4 (4) exceeds image "
+ "size 0x3 (3)", str(e.exception))
+
+ def testPackImageSize(self):
+ """Test that the image size can be set"""
+ retcode = self._DoTestFile('17_pack_image_size.dts')
+ self.assertEqual(0, retcode)
+ self.assertIn('image', control.images)
+ image = control.images['image']
+ self.assertEqual(7, image._size)
+
+ def testPackImageSizeAlign(self):
+ """Test that image size alignemnt works as expected"""
+ retcode = self._DoTestFile('18_pack_image_align.dts')
+ self.assertEqual(0, retcode)
+ self.assertIn('image', control.images)
+ image = control.images['image']
+ self.assertEqual(16, image._size)
+
+ def testPackInvalidImageAlign(self):
+ """Test that invalid image alignment is detected"""
+ with self.assertRaises(ValueError) as e:
+ self._DoTestFile('19_pack_inv_image_align.dts')
+ self.assertIn("Image '/binman': Size 0x7 (7) does not match "
+ "align-size 0x8 (8)", str(e.exception))
+
+ def testPackAlignPowerOf2(self):
+ """Test that invalid image alignment is detected"""
+ with self.assertRaises(ValueError) as e:
+ self._DoTestFile('20_pack_inv_image_align_power2.dts')
+ self.assertIn("Image '/binman': Alignment size 131 must be a power of "
+ "two", str(e.exception))
+
+ def testImagePadByte(self):
+ """Test that the image pad byte can be specified"""
+ data = self._DoReadFile('21_image_pad.dts')
+ self.assertEqual(U_BOOT_SPL_DATA + (chr(0xff) * 9) + U_BOOT_DATA, data)
+
+ def testImageName(self):
+ """Test that image files can be named"""
+ retcode = self._DoTestFile('22_image_name.dts')
+ self.assertEqual(0, retcode)
+ image = control.images['image1']
+ fname = tools.GetOutputFilename('test-name')
+ self.assertTrue(os.path.exists(fname))
+
+ image = control.images['image2']
+ fname = tools.GetOutputFilename('test-name.xx')
+ self.assertTrue(os.path.exists(fname))
+
+ def testBlobFilename(self):
+ """Test that generic blobs can be provided by filename"""
+ data = self._DoReadFile('23_blob.dts')
+ self.assertEqual(BLOB_DATA, data)
+
+ def testPackSorted(self):
+ """Test that entries can be sorted"""
+ data = self._DoReadFile('24_sorted.dts')
+ self.assertEqual(chr(0) * 5 + 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"""
+ with self.assertRaises(ValueError) as e:
+ self._DoTestFile('25_pack_zero_size.dts')
+ self.assertIn("Node '/binman/u-boot-spl': Position 0x0 (0) overlaps "
+ "with previous entry '/binman/u-boot' ending at 0x4 (4)",
+ str(e.exception))
+
+ def testPackUbootDtb(self):
+ """Test that a device tree can be added to U-Boot"""
+ data = self._DoReadFile('26_pack_u_boot_dtb.dts')
+ self.assertEqual(U_BOOT_NODTB_DATA + U_BOOT_DTB_DATA, data)
+
+ def testPackX86RomNoSize(self):
+ """Test that the end-at-4gb property requires a size property"""
+ with self.assertRaises(ValueError) as e:
+ self._DoTestFile('27_pack_4gb_no_size.dts')
+ self.assertIn("Image '/binman': Image size must be provided when "
+ "using end-at-4gb", str(e.exception))
+
+ def testPackX86RomOutside(self):
+ """Test that the end-at-4gb property checks for position 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 "
+ "the image starting at 0xfffffff0 (4294967280)",
+ str(e.exception))
+
+ def testPackX86Rom(self):
+ """Test that a basic x86 ROM can be created"""
+ data = self._DoReadFile('29_x86-rom.dts')
+ self.assertEqual(U_BOOT_DATA + chr(0) * 3 + U_BOOT_SPL_DATA +
+ chr(0) * 6, data)
+
+ def testPackX86RomMeNoDesc(self):
+ """Test that an invalid Intel descriptor entry is detected"""
+ TestFunctional._MakeInputFile('descriptor.bin', '')
+ with self.assertRaises(ValueError) as e:
+ self._DoTestFile('31_x86-rom-me.dts')
+ self.assertIn("Node '/binman/intel-descriptor': Cannot find FD "
+ "signature", str(e.exception))
+
+ def testPackX86RomBadDesc(self):
+ """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))
+
+ def testPackX86RomMe(self):
+ """Test that an x86 ROM with an ME region can be created"""
+ data = self._DoReadFile('31_x86-rom-me.dts')
+ self.assertEqual(ME_DATA, data[0x1000:0x1000 + len(ME_DATA)])
+
+ def testPackVga(self):
+ """Test that an image with a VGA binary can be created"""
+ data = self._DoReadFile('32_intel-vga.dts')
+ self.assertEqual(VGA_DATA, data[:len(VGA_DATA)])
+
+ def testPackStart16(self):
+ """Test that an image with an x86 start16 region can be created"""
+ data = self._DoReadFile('33_x86-start16.dts')
+ self.assertEqual(X86_START16_DATA, data[:len(X86_START16_DATA)])
+
+ def testPackUbootMicrocode(self):
+ """Test that x86 microcode can be handled correctly
+
+ We expect to see the following in the image, in order:
+ u-boot-nodtb.bin with a microcode pointer inserted at the correct
+ place
+ u-boot.dtb with the microcode removed
+ the microcode
+ """
+ data = self._DoReadFile('34_x86_ucode.dts', True)
+
+ # Now check the device tree has no microcode
+ second = data[len(U_BOOT_NODTB_DATA):]
+ fname = tools.GetOutputFilename('test.dtb')
+ with open(fname, 'wb') as fd:
+ fd.write(second)
+ fdt = fdt_select.FdtScan(fname)
+ ucode = fdt.GetNode('/microcode')
+ self.assertTrue(ucode)
+ for node in ucode.subnodes:
+ self.assertFalse(node.props.get('data'))
+
+ fdt_len = self.GetFdtLen(second)
+ third = second[fdt_len:]
+
+ # Check that the microcode appears immediately after the Fdt
+ # This matches the concatenation of the data properties in
+ # the /microcode/update@xxx nodes in x86_ucode.dts.
+ ucode_data = struct.pack('>4L', 0x12345678, 0x12345679, 0xabcd0000,
+ 0x78235609)
+ self.assertEqual(ucode_data, third[:len(ucode_data)])
+ ucode_pos = len(U_BOOT_NODTB_DATA) + fdt_len
+
+ # Check that the microcode pointer was inserted. It should match the
+ # expected position and size
+ pos_and_size = struct.pack('<2L', 0xfffffe00 + ucode_pos,
+ len(ucode_data))
+ first = data[:len(U_BOOT_NODTB_DATA)]
+ self.assertEqual('nodtb with microcode' + pos_and_size +
+ ' somewhere in here', first)
+
+ def _RunPackUbootSingleMicrocode(self, collate):
+ """Test that x86 microcode can be handled correctly
+
+ We expect to see the following in the image, in order:
+ u-boot-nodtb.bin with a microcode pointer inserted at the correct
+ place
+ u-boot.dtb with the microcode
+ an empty microcode region
+ """
+ # We need the libfdt library to run this test since only that allows
+ # finding the offset of a property. This is required by
+ # Entry_u_boot_dtb_with_ucode.ObtainContents().
+ if not fdt_select.have_libfdt:
+ return
+ data = self._DoReadFile('35_x86_single_ucode.dts', True)
+
+ second = data[len(U_BOOT_NODTB_DATA):]
+
+ fdt_len = self.GetFdtLen(second)
+ third = second[fdt_len:]
+ second = second[:fdt_len]
+
+ if not collate:
+ ucode_data = struct.pack('>2L', 0x12345678, 0x12345679)
+ self.assertIn(ucode_data, second)
+ 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
+ pos_and_size = struct.pack('<2L', 0xfffffe00 + ucode_pos,
+ len(ucode_data))
+ first = data[:len(U_BOOT_NODTB_DATA)]
+ self.assertEqual('nodtb with microcode' + pos_and_size +
+ ' somewhere in here', first)
+
+ def testPackUbootSingleMicrocode(self):
+ """Test that x86 microcode can be handled correctly with fdt_normal.
+ """
+ self._RunPackUbootSingleMicrocode(False)
+
+ def testPackUbootSingleMicrocodeFallback(self):
+ """Test that x86 microcode can be handled correctly with fdt_fallback.
+
+ This only supports collating the microcode.
+ """
+ try:
+ old_val = fdt_select.UseFallback(True)
+ self._RunPackUbootSingleMicrocode(True)
+ finally:
+ fdt_select.UseFallback(old_val)
+
+ def testUBootImg(self):
+ """Test that u-boot.img can be put in a file"""
+ data = self._DoReadFile('36_u_boot_img.dts')
+ self.assertEqual(U_BOOT_IMG_DATA, data)
+
+ def testNoMicrocode(self):
+ """Test that a missing microcode region is detected"""
+ with self.assertRaises(ValueError) as e:
+ self._DoReadFile('37_x86_no_ucode.dts', True)
+ self.assertIn("Node '/binman/u-boot-dtb-with-ucode': No /microcode "
+ "node found in ", str(e.exception))
+
+ def testMicrocodeWithoutNode(self):
+ """Test that a missing u-boot-dtb-with-ucode node is detected"""
+ with self.assertRaises(ValueError) as e:
+ self._DoReadFile('38_x86_ucode_missing_node.dts', True)
+ self.assertIn("Node '/binman/u-boot-with-ucode-ptr': Cannot find "
+ "microcode region u-boot-dtb-with-ucode", str(e.exception))
+
+ def testMicrocodeWithoutNode2(self):
+ """Test that a missing u-boot-ucode node is detected"""
+ with self.assertRaises(ValueError) as e:
+ self._DoReadFile('39_x86_ucode_missing_node2.dts', True)
+ self.assertIn("Node '/binman/u-boot-with-ucode-ptr': Cannot find "
+ "microcode region u-boot-ucode", str(e.exception))
+
+ def testMicrocodeWithoutPtrInElf(self):
+ """Test that a U-Boot binary without the microcode symbol is detected"""
+ # ELF file without a '_dt_ucode_base_size' symbol
+ if not fdt_select.have_libfdt:
+ return
+ try:
+ with open(self.TestFile('u_boot_no_ucode_ptr')) as fd:
+ TestFunctional._MakeInputFile('u-boot', fd.read())
+
+ with self.assertRaises(ValueError) as e:
+ self._RunPackUbootSingleMicrocode(False)
+ self.assertIn("Node '/binman/u-boot-with-ucode-ptr': Cannot locate "
+ "_dt_ucode_base_size symbol in u-boot", str(e.exception))
+
+ finally:
+ # Put the original file back
+ with open(self.TestFile('u_boot_ucode_ptr')) as fd:
+ TestFunctional._MakeInputFile('u-boot', fd.read())
+
+ def testMicrocodeNotInImage(self):
+ """Test that microcode must be placed within the image"""
+ with self.assertRaises(ValueError) as e:
+ self._DoReadFile('40_x86_ucode_not_in_image.dts', True)
+ self.assertIn("Node '/binman/u-boot-with-ucode-ptr': Microcode "
+ "pointer _dt_ucode_base_size at fffffe14 is outside the "
+ "image ranging from 00000000 to 0000002e", str(e.exception))
+
+ def testWithoutMicrocode(self):
+ """Test that we can cope with an image without microcode (e.g. qemu)"""
+ with open(self.TestFile('u_boot_no_ucode_ptr')) as fd:
+ TestFunctional._MakeInputFile('u-boot', fd.read())
+ data, dtb = self._DoReadFileDtb('44_x86_optional_ucode.dts', True)
+
+ # Now check the device tree has no microcode
+ self.assertEqual(U_BOOT_NODTB_DATA, data[:len(U_BOOT_NODTB_DATA)])
+ second = data[len(U_BOOT_NODTB_DATA):]
+
+ fdt_len = self.GetFdtLen(second)
+ self.assertEqual(dtb, second[:fdt_len])
+
+ used_len = len(U_BOOT_NODTB_DATA) + fdt_len
+ third = data[used_len:]
+ self.assertEqual(chr(0) * (0x200 - used_len), third)
+
+ def testUnknownPosSize(self):
+ """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("Image '/binman': Unable to set pos/size for unknown "
+ "entry 'invalid-entry'", str(e.exception))
+
+ def testPackFsp(self):
+ """Test that an image with a FSP binary can be created"""
+ data = self._DoReadFile('42_intel-fsp.dts')
+ self.assertEqual(FSP_DATA, data[:len(FSP_DATA)])
+
+ def testPackCmc(self):
+ """Test that an image with a FSP binary can be created"""
+ data = self._DoReadFile('43_intel-cmc.dts')
+ self.assertEqual(CMC_DATA, data[:len(CMC_DATA)])
diff --git a/tools/binman/image.py b/tools/binman/image.py
new file mode 100644
index 0000000..07fc930
--- /dev/null
+++ b/tools/binman/image.py
@@ -0,0 +1,229 @@
+# Copyright (c) 2016 Google, Inc
+# Written by Simon Glass <sjg@chromium.org>
+#
+# SPDX-License-Identifier: GPL-2.0+
+#
+# Class for an image, the output of binman
+#
+
+from collections import OrderedDict
+from operator import attrgetter
+
+import entry
+from entry import Entry
+import fdt_util
+import tools
+
+class Image:
+ """A Image, representing an output from binman
+
+ An image is comprised of a collection of entries each containing binary
+ data. The image size must be large enough to hold all of this data.
+
+ This class implements the various operations needed for images.
+
+ Atrtributes:
+ _node: Node object that contains the image definition in device tree
+ _name: Image name
+ _size: Image size in bytes, or None if not known yet
+ _align_size: Image size alignment, or None
+ _pad_before: Number of bytes before the first entry starts. This
+ effectively changes the place where entry position 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 image where there is no entry
+ _filename: Output filename for image
+ _sort: True if entries should be sorted by position, False if they
+ must be in-order in the device tree description
+ _skip_at_start: Number of bytes before the first entry starts. These
+ effecively adjust the starting position 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
+ in the image file.
+ _end_4gb: Indicates that the image 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.
+ _entries: OrderedDict() of entries
+ """
+ def __init__(self, name, node):
+ self._node = node
+ self._name = name
+ self._size = None
+ self._align_size = None
+ self._pad_before = 0
+ self._pad_after = 0
+ self._pad_byte = 0
+ self._filename = '%s.bin' % self._name
+ self._sort = False
+ self._skip_at_start = 0
+ self._end_4gb = False
+ self._entries = OrderedDict()
+
+ self._ReadNode()
+ self._ReadEntries()
+
+ def _ReadNode(self):
+ """Read properties from the image node"""
+ self._size = fdt_util.GetInt(self._node, 'size')
+ self._align_size = fdt_util.GetInt(self._node, 'align-size')
+ if tools.NotPowerOfTwo(self._align_size):
+ self._Raise("Alignment size %s must be a power of two" %
+ self._align_size)
+ 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)
+ filename = fdt_util.GetString(self._node, 'filename')
+ if filename:
+ self._filename = filename
+ self._sort = fdt_util.GetBool(self._node, 'sort-by-pos')
+ self._end_4gb = fdt_util.GetBool(self._node, 'end-at-4gb')
+ if self._end_4gb and not self._size:
+ self._Raise("Image size must be provided when using end-at-4gb")
+ if self._end_4gb:
+ self._skip_at_start = 0x100000000 - self._size
+
+ def CheckSize(self):
+ """Check that the image 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 -= self._skip_at_start
+
+ size = self._size
+ if not size:
+ size = self._pad_before + contents_size + self._pad_after
+ size = tools.Align(size, self._align_size)
+
+ if self._size and contents_size > self._size:
+ self._Raise("contents size %#x (%d) exceeds image size %#x (%d)" %
+ (contents_size, contents_size, self._size, self._size))
+ if not self._size:
+ self._size = size
+ 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))
+
+ def _Raise(self, msg):
+ """Raises an error for this image
+
+ Args:
+ msg: Error message to use in the raise string
+ Raises:
+ ValueError()
+ """
+ raise ValueError("Image '%s': %s" % (self._node.path, msg))
+
+ def _ReadEntries(self):
+ for node in self._node.subnodes:
+ self._entries[node.name] = Entry.Create(self, node)
+
+ def FindEntryType(self, etype):
+ """Find an entry type in the image
+
+ Args:
+ etype: Entry type to find
+ Returns:
+ entry matching that type, or None if not found
+ """
+ for entry in self._entries.values():
+ if entry.etype == etype:
+ return entry
+ return None
+
+ def GetEntryContents(self):
+ """Call ObtainContents() for each entry
+
+ This calls each entry's ObtainContents() a few times until they all
+ return True. We stop calling an entry's function once it returns
+ True. This allows the contents of one entry to depend on another.
+
+ After 3 rounds we give up since it's likely an error.
+ """
+ todo = self._entries.values()
+ for passnum in range(3):
+ next_todo = []
+ for entry in todo:
+ if not entry.ObtainContents():
+ next_todo.append(entry)
+ todo = next_todo
+ if not todo:
+ break
+
+ def _SetEntryPosSize(self, name, pos, size):
+ """Set the position and size of an entry
+
+ Args:
+ name: Entry name to update
+ pos: New position
+ 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)
+
+ def GetEntryPositions(self):
+ """Handle entries that want to set the position/size of other entries
+
+ This calls each entry's GetPositions() 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)
+
+ def PackEntries(self):
+ """Pack all entries into the image"""
+ pos = self._skip_at_start
+ for entry in self._entries.values():
+ pos = entry.Pack(pos)
+
+ def _SortEntries(self):
+ """Sort entries by position"""
+ entries = sorted(self._entries.values(), key=lambda entry: entry.pos)
+ self._entries.clear()
+ for entry in entries:
+ self._entries[entry._node.name] = entry
+
+ def CheckEntries(self):
+ """Check that entries do not overlap or extend outside the image"""
+ if self._sort:
+ self._SortEntries()
+ pos = 0
+ prev_name = 'None'
+ for entry in self._entries.values():
+ if (entry.pos < self._skip_at_start or
+ entry.pos >= self._skip_at_start + self._size):
+ entry.Raise("Position %#x (%d) is outside the image starting "
+ "at %#x (%d)" %
+ (entry.pos, entry.pos, self._skip_at_start,
+ self._skip_at_start))
+ if entry.pos < pos:
+ entry.Raise("Position %#x (%d) overlaps with previous entry '%s' "
+ "ending at %#x (%d)" %
+ (entry.pos, entry.pos, prev_name, pos, pos))
+ pos = entry.pos + entry.size
+ prev_name = entry.GetPath()
+
+ def ProcessEntryContents(self):
+ """Call the ProcessContents() method for each entry
+
+ This is intended to adjust the contents as needed by the entry type.
+ """
+ for entry in self._entries.values():
+ entry.ProcessContents()
+
+ def BuildImage(self):
+ """Write the image to a file"""
+ fname = tools.GetOutputFilename(self._filename)
+ with open(fname, 'wb') as fd:
+ fd.write(chr(self._pad_byte) * self._size)
+
+ for entry in self._entries.values():
+ data = entry.GetData()
+ fd.seek(self._pad_before + entry.pos - self._skip_at_start)
+ fd.write(data)
diff --git a/tools/binman/test/01_invalid.dts b/tools/binman/test/01_invalid.dts
new file mode 100644
index 0000000..7d00455
--- /dev/null
+++ b/tools/binman/test/01_invalid.dts
@@ -0,0 +1,5 @@
+/dts-v1/;
+
+/ {
+ #address-cells = <1>;
+ #size-cells = <1>;
diff --git a/tools/binman/test/02_missing_node.dts b/tools/binman/test/02_missing_node.dts
new file mode 100644
index 0000000..3a51ec2
--- /dev/null
+++ b/tools/binman/test/02_missing_node.dts
@@ -0,0 +1,6 @@
+/dts-v1/;
+
+/ {
+ #address-cells = <1>;
+ #size-cells = <1>;
+};
diff --git a/tools/binman/test/03_empty.dts b/tools/binman/test/03_empty.dts
new file mode 100644
index 0000000..493c9a0
--- /dev/null
+++ b/tools/binman/test/03_empty.dts
@@ -0,0 +1,9 @@
+/dts-v1/;
+
+/ {
+ #address-cells = <1>;
+ #size-cells = <1>;
+
+ binman {
+ };
+};
diff --git a/tools/binman/test/04_invalid_entry.dts b/tools/binman/test/04_invalid_entry.dts
new file mode 100644
index 0000000..b043455
--- /dev/null
+++ b/tools/binman/test/04_invalid_entry.dts
@@ -0,0 +1,11 @@
+/dts-v1/;
+
+/ {
+ #address-cells = <1>;
+ #size-cells = <1>;
+
+ binman {
+ not-a-valid-type {
+ };
+ };
+};
diff --git a/tools/binman/test/05_simple.dts b/tools/binman/test/05_simple.dts
new file mode 100644
index 0000000..3771aa2
--- /dev/null
+++ b/tools/binman/test/05_simple.dts
@@ -0,0 +1,11 @@
+/dts-v1/;
+
+/ {
+ #address-cells = <1>;
+ #size-cells = <1>;
+
+ binman {
+ u-boot {
+ };
+ };
+};
diff --git a/tools/binman/test/06_dual_image.dts b/tools/binman/test/06_dual_image.dts
new file mode 100644
index 0000000..78be16f
--- /dev/null
+++ b/tools/binman/test/06_dual_image.dts
@@ -0,0 +1,22 @@
+/dts-v1/;
+
+/ {
+ #address-cells = <1>;
+ #size-cells = <1>;
+
+ binman {
+ multiple-images;
+ image1 {
+ u-boot {
+ };
+ };
+
+ image2 {
+ pad-before = <3>;
+ pad-after = <5>;
+
+ u-boot {
+ };
+ };
+ };
+};
diff --git a/tools/binman/test/07_bad_align.dts b/tools/binman/test/07_bad_align.dts
new file mode 100644
index 0000000..123bb13
--- /dev/null
+++ b/tools/binman/test/07_bad_align.dts
@@ -0,0 +1,12 @@
+/dts-v1/;
+
+/ {
+ #address-cells = <1>;
+ #size-cells = <1>;
+
+ binman {
+ u-boot {
+ align = <23>;
+ };
+ };
+};
diff --git a/tools/binman/test/08_pack.dts b/tools/binman/test/08_pack.dts
new file mode 100644
index 0000000..dc63d99
--- /dev/null
+++ b/tools/binman/test/08_pack.dts
@@ -0,0 +1,30 @@
+/dts-v1/;
+
+/ {
+ #address-cells = <1>;
+ #size-cells = <1>;
+
+ binman {
+ u-boot {
+ };
+
+ u-boot-align {
+ type = "u-boot";
+ align = <16>;
+ };
+
+ u-boot-size {
+ type = "u-boot";
+ size = <23>;
+ };
+
+ u-boot-next {
+ type = "u-boot";
+ };
+
+ u-boot-fixed {
+ type = "u-boot";
+ pos = <61>;
+ };
+ };
+};
diff --git a/tools/binman/test/09_pack_extra.dts b/tools/binman/test/09_pack_extra.dts
new file mode 100644
index 0000000..0765707
--- /dev/null
+++ b/tools/binman/test/09_pack_extra.dts
@@ -0,0 +1,35 @@
+/dts-v1/;
+
+/ {
+ #address-cells = <1>;
+ #size-cells = <1>;
+
+ binman {
+ u-boot {
+ pad-before = <3>;
+ pad-after = <5>;
+ };
+
+ u-boot-align-size-nop {
+ type = "u-boot";
+ align-size = <4>;
+ };
+
+ u-boot-align-size {
+ type = "u-boot";
+ align = <16>;
+ align-size = <32>;
+ };
+
+ u-boot-align-end {
+ type = "u-boot";
+ align-end = <64>;
+ };
+
+ u-boot-align-both {
+ type = "u-boot";
+ align= <64>;
+ align-end = <128>;
+ };
+ };
+};
diff --git a/tools/binman/test/10_pack_align_power2.dts b/tools/binman/test/10_pack_align_power2.dts
new file mode 100644
index 0000000..8f6253a
--- /dev/null
+++ b/tools/binman/test/10_pack_align_power2.dts
@@ -0,0 +1,12 @@
+/dts-v1/;
+
+/ {
+ #address-cells = <1>;
+ #size-cells = <1>;
+
+ binman {
+ u-boot {
+ align = <5>;
+ };
+ };
+};
diff --git a/tools/binman/test/11_pack_align_size_power2.dts b/tools/binman/test/11_pack_align_size_power2.dts
new file mode 100644
index 0000000..04f7672
--- /dev/null
+++ b/tools/binman/test/11_pack_align_size_power2.dts
@@ -0,0 +1,12 @@
+/dts-v1/;
+
+/ {
+ #address-cells = <1>;
+ #size-cells = <1>;
+
+ binman {
+ u-boot {
+ align-size = <55>;
+ };
+ };
+};
diff --git a/tools/binman/test/12_pack_inv_align.dts b/tools/binman/test/12_pack_inv_align.dts
new file mode 100644
index 0000000..1d9d80a
--- /dev/null
+++ b/tools/binman/test/12_pack_inv_align.dts
@@ -0,0 +1,13 @@
+/dts-v1/;
+
+/ {
+ #address-cells = <1>;
+ #size-cells = <1>;
+
+ binman {
+ u-boot {
+ pos = <5>;
+ align = <4>;
+ };
+ };
+};
diff --git a/tools/binman/test/13_pack_inv_size_align.dts b/tools/binman/test/13_pack_inv_size_align.dts
new file mode 100644
index 0000000..dfafa13
--- /dev/null
+++ b/tools/binman/test/13_pack_inv_size_align.dts
@@ -0,0 +1,13 @@
+/dts-v1/;
+
+/ {
+ #address-cells = <1>;
+ #size-cells = <1>;
+
+ binman {
+ u-boot {
+ size = <5>;
+ align-size = <4>;
+ };
+ };
+};
diff --git a/tools/binman/test/14_pack_overlap.dts b/tools/binman/test/14_pack_overlap.dts
new file mode 100644
index 0000000..611cfd9
--- /dev/null
+++ b/tools/binman/test/14_pack_overlap.dts
@@ -0,0 +1,16 @@
+/dts-v1/;
+
+/ {
+ #address-cells = <1>;
+ #size-cells = <1>;
+
+ binman {
+ u-boot {
+ };
+
+ u-boot-align {
+ type = "u-boot";
+ pos = <3>;
+ };
+ };
+};
diff --git a/tools/binman/test/15_pack_overflow.dts b/tools/binman/test/15_pack_overflow.dts
new file mode 100644
index 0000000..6f65433
--- /dev/null
+++ b/tools/binman/test/15_pack_overflow.dts
@@ -0,0 +1,12 @@
+/dts-v1/;
+
+/ {
+ #address-cells = <1>;
+ #size-cells = <1>;
+
+ binman {
+ u-boot {
+ size = <3>;
+ };
+ };
+};
diff --git a/tools/binman/test/16_pack_image_overflow.dts b/tools/binman/test/16_pack_image_overflow.dts
new file mode 100644
index 0000000..6ae66f3
--- /dev/null
+++ b/tools/binman/test/16_pack_image_overflow.dts
@@ -0,0 +1,13 @@
+/dts-v1/;
+
+/ {
+ #address-cells = <1>;
+ #size-cells = <1>;
+
+ binman {
+ size = <3>;
+
+ u-boot {
+ };
+ };
+};
diff --git a/tools/binman/test/17_pack_image_size.dts b/tools/binman/test/17_pack_image_size.dts
new file mode 100644
index 0000000..2360eb5
--- /dev/null
+++ b/tools/binman/test/17_pack_image_size.dts
@@ -0,0 +1,13 @@
+/dts-v1/;
+
+/ {
+ #address-cells = <1>;
+ #size-cells = <1>;
+
+ binman {
+ size = <7>;
+
+ u-boot {
+ };
+ };
+};
diff --git a/tools/binman/test/18_pack_image_align.dts b/tools/binman/test/18_pack_image_align.dts
new file mode 100644
index 0000000..16cd2a4
--- /dev/null
+++ b/tools/binman/test/18_pack_image_align.dts
@@ -0,0 +1,13 @@
+/dts-v1/;
+
+/ {
+ #address-cells = <1>;
+ #size-cells = <1>;
+
+ binman {
+ align-size = <16>;
+
+ u-boot {
+ };
+ };
+};
diff --git a/tools/binman/test/19_pack_inv_image_align.dts b/tools/binman/test/19_pack_inv_image_align.dts
new file mode 100644
index 0000000..e5ee87b
--- /dev/null
+++ b/tools/binman/test/19_pack_inv_image_align.dts
@@ -0,0 +1,14 @@
+/dts-v1/;
+
+/ {
+ #address-cells = <1>;
+ #size-cells = <1>;
+
+ binman {
+ size = <7>;
+ align-size = <8>;
+
+ u-boot {
+ };
+ };
+};
diff --git a/tools/binman/test/20_pack_inv_image_align_power2.dts b/tools/binman/test/20_pack_inv_image_align_power2.dts
new file mode 100644
index 0000000..a428c4b
--- /dev/null
+++ b/tools/binman/test/20_pack_inv_image_align_power2.dts
@@ -0,0 +1,13 @@
+/dts-v1/;
+
+/ {
+ #address-cells = <1>;
+ #size-cells = <1>;
+
+ binman {
+ align-size = <131>;
+
+ u-boot {
+ };
+ };
+};
diff --git a/tools/binman/test/21_image_pad.dts b/tools/binman/test/21_image_pad.dts
new file mode 100644
index 0000000..daf8385
--- /dev/null
+++ b/tools/binman/test/21_image_pad.dts
@@ -0,0 +1,16 @@
+/dts-v1/;
+
+/ {
+ #address-cells = <1>;
+ #size-cells = <1>;
+
+ binman {
+ pad-byte = <0xff>;
+ u-boot-spl {
+ };
+
+ u-boot {
+ pos = <12>;
+ };
+ };
+};
diff --git a/tools/binman/test/22_image_name.dts b/tools/binman/test/22_image_name.dts
new file mode 100644
index 0000000..94fc069
--- /dev/null
+++ b/tools/binman/test/22_image_name.dts
@@ -0,0 +1,21 @@
+/dts-v1/;
+
+/ {
+ #address-cells = <1>;
+ #size-cells = <1>;
+
+ binman {
+ multiple-images;
+ image1 {
+ filename = "test-name";
+ u-boot {
+ };
+ };
+
+ image2 {
+ filename = "test-name.xx";
+ u-boot {
+ };
+ };
+ };
+};
diff --git a/tools/binman/test/23_blob.dts b/tools/binman/test/23_blob.dts
new file mode 100644
index 0000000..7dcff69
--- /dev/null
+++ b/tools/binman/test/23_blob.dts
@@ -0,0 +1,12 @@
+/dts-v1/;
+
+/ {
+ #address-cells = <1>;
+ #size-cells = <1>;
+
+ binman {
+ blob {
+ filename = "blobfile";
+ };
+ };
+};
diff --git a/tools/binman/test/24_sorted.dts b/tools/binman/test/24_sorted.dts
new file mode 100644
index 0000000..9f4151c
--- /dev/null
+++ b/tools/binman/test/24_sorted.dts
@@ -0,0 +1,17 @@
+/dts-v1/;
+
+/ {
+ #address-cells = <1>;
+ #size-cells = <1>;
+
+ binman {
+ sort-by-pos;
+ u-boot {
+ pos = <10>;
+ };
+
+ u-boot-spl {
+ pos = <5>;
+ };
+ };
+};
diff --git a/tools/binman/test/25_pack_zero_size.dts b/tools/binman/test/25_pack_zero_size.dts
new file mode 100644
index 0000000..7d2baad
--- /dev/null
+++ b/tools/binman/test/25_pack_zero_size.dts
@@ -0,0 +1,15 @@
+/dts-v1/;
+
+/ {
+ #address-cells = <1>;
+ #size-cells = <1>;
+
+ binman {
+ u-boot {
+ };
+
+ u-boot-spl {
+ pos = <0>;
+ };
+ };
+};
diff --git a/tools/binman/test/26_pack_u_boot_dtb.dts b/tools/binman/test/26_pack_u_boot_dtb.dts
new file mode 100644
index 0000000..2707a73
--- /dev/null
+++ b/tools/binman/test/26_pack_u_boot_dtb.dts
@@ -0,0 +1,14 @@
+/dts-v1/;
+
+/ {
+ #address-cells = <1>;
+ #size-cells = <1>;
+
+ binman {
+ u-boot-nodtb {
+ };
+
+ u-boot-dtb {
+ };
+ };
+};
diff --git a/tools/binman/test/27_pack_4gb_no_size.dts b/tools/binman/test/27_pack_4gb_no_size.dts
new file mode 100644
index 0000000..e0b6519
--- /dev/null
+++ b/tools/binman/test/27_pack_4gb_no_size.dts
@@ -0,0 +1,18 @@
+/dts-v1/;
+
+/ {
+ #address-cells = <1>;
+ #size-cells = <1>;
+
+ binman {
+ sort-by-pos;
+ end-at-4gb;
+ u-boot {
+ pos = <0xfffffff0>;
+ };
+
+ u-boot-spl {
+ pos = <0xfffffff7>;
+ };
+ };
+};
diff --git a/tools/binman/test/28_pack_4gb_outside.dts b/tools/binman/test/28_pack_4gb_outside.dts
new file mode 100644
index 0000000..ff468c7
--- /dev/null
+++ b/tools/binman/test/28_pack_4gb_outside.dts
@@ -0,0 +1,19 @@
+/dts-v1/;
+
+/ {
+ #address-cells = <1>;
+ #size-cells = <1>;
+
+ binman {
+ sort-by-pos;
+ end-at-4gb;
+ size = <16>;
+ u-boot {
+ pos = <0>;
+ };
+
+ u-boot-spl {
+ pos = <0xfffffff7>;
+ };
+ };
+};
diff --git a/tools/binman/test/29_x86-rom.dts b/tools/binman/test/29_x86-rom.dts
new file mode 100644
index 0000000..075ede3
--- /dev/null
+++ b/tools/binman/test/29_x86-rom.dts
@@ -0,0 +1,19 @@
+/dts-v1/;
+
+/ {
+ #address-cells = <1>;
+ #size-cells = <1>;
+
+ binman {
+ sort-by-pos;
+ end-at-4gb;
+ size = <16>;
+ u-boot {
+ pos = <0xfffffff0>;
+ };
+
+ u-boot-spl {
+ pos = <0xfffffff7>;
+ };
+ };
+};
diff --git a/tools/binman/test/30_x86-rom-me-no-desc.dts b/tools/binman/test/30_x86-rom-me-no-desc.dts
new file mode 100644
index 0000000..4578f66
--- /dev/null
+++ b/tools/binman/test/30_x86-rom-me-no-desc.dts
@@ -0,0 +1,15 @@
+/dts-v1/;
+
+/ {
+ #address-cells = <1>;
+ #size-cells = <1>;
+
+ binman {
+ sort-by-pos;
+ end-at-4gb;
+ size = <16>;
+ intel-me {
+ pos-unset;
+ };
+ };
+};
diff --git a/tools/binman/test/31_x86-rom-me.dts b/tools/binman/test/31_x86-rom-me.dts
new file mode 100644
index 0000000..b484ab3
--- /dev/null
+++ b/tools/binman/test/31_x86-rom-me.dts
@@ -0,0 +1,18 @@
+/dts-v1/;
+
+/ {
+ #address-cells = <1>;
+ #size-cells = <1>;
+
+ binman {
+ sort-by-pos;
+ end-at-4gb;
+ size = <0x800000>;
+ intel-descriptor {
+ };
+
+ intel-me {
+ pos-unset;
+ };
+ };
+};
diff --git a/tools/binman/test/32_intel-vga.dts b/tools/binman/test/32_intel-vga.dts
new file mode 100644
index 0000000..1790833
--- /dev/null
+++ b/tools/binman/test/32_intel-vga.dts
@@ -0,0 +1,13 @@
+/dts-v1/;
+
+/ {
+ #address-cells = <1>;
+ #size-cells = <1>;
+
+ binman {
+ size = <16>;
+
+ intel-vga {
+ };
+ };
+};
diff --git a/tools/binman/test/33_x86-start16.dts b/tools/binman/test/33_x86-start16.dts
new file mode 100644
index 0000000..2e279de
--- /dev/null
+++ b/tools/binman/test/33_x86-start16.dts
@@ -0,0 +1,13 @@
+/dts-v1/;
+
+/ {
+ #address-cells = <1>;
+ #size-cells = <1>;
+
+ binman {
+ size = <16>;
+
+ x86-start16 {
+ };
+ };
+};
diff --git a/tools/binman/test/34_x86_ucode.dts b/tools/binman/test/34_x86_ucode.dts
new file mode 100644
index 0000000..64a6c2c
--- /dev/null
+++ b/tools/binman/test/34_x86_ucode.dts
@@ -0,0 +1,29 @@
+/dts-v1/;
+
+/ {
+ #address-cells = <1>;
+ #size-cells = <1>;
+
+ binman {
+ sort-by-pos;
+ end-at-4gb;
+ size = <0x200>;
+ u-boot-with-ucode-ptr {
+ };
+
+ u-boot-dtb-with-ucode {
+ };
+
+ u-boot-ucode {
+ };
+ };
+
+ microcode {
+ update@0 {
+ data = <0x12345678 0x12345679>;
+ };
+ update@1 {
+ data = <0xabcd0000 0x78235609>;
+ };
+ };
+};
diff --git a/tools/binman/test/35_x86_single_ucode.dts b/tools/binman/test/35_x86_single_ucode.dts
new file mode 100644
index 0000000..973e97f
--- /dev/null
+++ b/tools/binman/test/35_x86_single_ucode.dts
@@ -0,0 +1,26 @@
+/dts-v1/;
+
+/ {
+ #address-cells = <1>;
+ #size-cells = <1>;
+
+ binman {
+ sort-by-pos;
+ end-at-4gb;
+ size = <0x200>;
+ u-boot-with-ucode-ptr {
+ };
+
+ u-boot-dtb-with-ucode {
+ };
+
+ u-boot-ucode {
+ };
+ };
+
+ microcode {
+ update@0 {
+ data = <0x12345678 0x12345679>;
+ };
+ };
+};
diff --git a/tools/binman/test/36_u_boot_img.dts b/tools/binman/test/36_u_boot_img.dts
new file mode 100644
index 0000000..aa5a3fe
--- /dev/null
+++ b/tools/binman/test/36_u_boot_img.dts
@@ -0,0 +1,11 @@
+/dts-v1/;
+
+/ {
+ #address-cells = <1>;
+ #size-cells = <1>;
+
+ binman {
+ u-boot-img {
+ };
+ };
+};
diff --git a/tools/binman/test/37_x86_no_ucode.dts b/tools/binman/test/37_x86_no_ucode.dts
new file mode 100644
index 0000000..9e12156
--- /dev/null
+++ b/tools/binman/test/37_x86_no_ucode.dts
@@ -0,0 +1,20 @@
+/dts-v1/;
+
+/ {
+ #address-cells = <1>;
+ #size-cells = <1>;
+
+ binman {
+ sort-by-pos;
+ end-at-4gb;
+ size = <0x200>;
+ u-boot-with-ucode-ptr {
+ };
+
+ u-boot-dtb-with-ucode {
+ };
+
+ u-boot-ucode {
+ };
+ };
+};
diff --git a/tools/binman/test/38_x86_ucode_missing_node.dts b/tools/binman/test/38_x86_ucode_missing_node.dts
new file mode 100644
index 0000000..d6cf0d8
--- /dev/null
+++ b/tools/binman/test/38_x86_ucode_missing_node.dts
@@ -0,0 +1,26 @@
+/dts-v1/;
+
+/ {
+ #address-cells = <1>;
+ #size-cells = <1>;
+
+ binman {
+ sort-by-pos;
+ end-at-4gb;
+ size = <0x200>;
+ u-boot-with-ucode-ptr {
+ };
+
+ u-boot-ucode {
+ };
+ };
+
+ microcode {
+ update@0 {
+ data = <0x12345678 0x12345679>;
+ };
+ update@1 {
+ data = <0xabcd0000 0x78235609>;
+ };
+ };
+};
diff --git a/tools/binman/test/39_x86_ucode_missing_node2.dts b/tools/binman/test/39_x86_ucode_missing_node2.dts
new file mode 100644
index 0000000..b7e26c5
--- /dev/null
+++ b/tools/binman/test/39_x86_ucode_missing_node2.dts
@@ -0,0 +1,23 @@
+/dts-v1/;
+
+/ {
+ #address-cells = <1>;
+ #size-cells = <1>;
+
+ binman {
+ sort-by-pos;
+ end-at-4gb;
+ size = <0x200>;
+ u-boot-with-ucode-ptr {
+ };
+ };
+
+ microcode {
+ update@0 {
+ data = <0x12345678 0x12345679>;
+ };
+ update@1 {
+ data = <0xabcd0000 0x78235609>;
+ };
+ };
+};
diff --git a/tools/binman/test/40_x86_ucode_not_in_image.dts b/tools/binman/test/40_x86_ucode_not_in_image.dts
new file mode 100644
index 0000000..67d17d3
--- /dev/null
+++ b/tools/binman/test/40_x86_ucode_not_in_image.dts
@@ -0,0 +1,28 @@
+/dts-v1/;
+
+/ {
+ #address-cells = <1>;
+ #size-cells = <1>;
+
+ binman {
+ sort-by-pos;
+ size = <0x200>;
+ u-boot-with-ucode-ptr {
+ };
+
+ u-boot-dtb-with-ucode {
+ };
+
+ u-boot-ucode {
+ };
+ };
+
+ microcode {
+ update@0 {
+ data = <0x12345678 0x12345679>;
+ };
+ update@1 {
+ data = <0xabcd0000 0x78235609>;
+ };
+ };
+};
diff --git a/tools/binman/test/41_unknown_pos_size.dts b/tools/binman/test/41_unknown_pos_size.dts
new file mode 100644
index 0000000..a8e7d8a
--- /dev/null
+++ b/tools/binman/test/41_unknown_pos_size.dts
@@ -0,0 +1,11 @@
+/dts-v1/;
+
+/ {
+ #address-cells = <1>;
+ #size-cells = <1>;
+
+ binman {
+ _testing {
+ };
+ };
+};
diff --git a/tools/binman/test/42_intel-fsp.dts b/tools/binman/test/42_intel-fsp.dts
new file mode 100644
index 0000000..e0a1e76
--- /dev/null
+++ b/tools/binman/test/42_intel-fsp.dts
@@ -0,0 +1,13 @@
+/dts-v1/;
+
+/ {
+ #address-cells = <1>;
+ #size-cells = <1>;
+
+ binman {
+ size = <16>;
+
+ intel-fsp {
+ };
+ };
+};
diff --git a/tools/binman/test/43_intel-cmc.dts b/tools/binman/test/43_intel-cmc.dts
new file mode 100644
index 0000000..26c456d
--- /dev/null
+++ b/tools/binman/test/43_intel-cmc.dts
@@ -0,0 +1,13 @@
+/dts-v1/;
+
+/ {
+ #address-cells = <1>;
+ #size-cells = <1>;
+
+ binman {
+ size = <16>;
+
+ intel-cmc {
+ };
+ };
+};
diff --git a/tools/binman/test/44_x86_optional_ucode.dts b/tools/binman/test/44_x86_optional_ucode.dts
new file mode 100644
index 0000000..abe1322
--- /dev/null
+++ b/tools/binman/test/44_x86_optional_ucode.dts
@@ -0,0 +1,30 @@
+/dts-v1/;
+
+/ {
+ #address-cells = <1>;
+ #size-cells = <1>;
+
+ binman {
+ sort-by-pos;
+ end-at-4gb;
+ size = <0x200>;
+ u-boot-with-ucode-ptr {
+ optional-ucode;
+ };
+
+ u-boot-dtb-with-ucode {
+ };
+
+ u-boot-ucode {
+ };
+ };
+
+ microcode {
+ update@0 {
+ data = <0x12345678 0x12345679>;
+ };
+ update@1 {
+ data = <0xabcd0000 0x78235609>;
+ };
+ };
+};
diff --git a/tools/binman/test/descriptor.bin b/tools/binman/test/descriptor.bin
new file mode 100644
index 0000000..3d54943
--- /dev/null
+++ b/tools/binman/test/descriptor.bin
Binary files differ
diff --git a/tools/binman/test/u_boot_no_ucode_ptr b/tools/binman/test/u_boot_no_ucode_ptr
new file mode 100755
index 0000000..f72462f
--- /dev/null
+++ b/tools/binman/test/u_boot_no_ucode_ptr
Binary files differ
diff --git a/tools/binman/test/u_boot_no_ucode_ptr.c b/tools/binman/test/u_boot_no_ucode_ptr.c
new file mode 100644
index 0000000..a17bb4c
--- /dev/null
+++ b/tools/binman/test/u_boot_no_ucode_ptr.c
@@ -0,0 +1,15 @@
+/*
+ * Copyright (c) 2016 Google, Inc
+ *
+ * SPDX-License-Identifier: GPL-2.0+
+ *
+ * Simple program to create a bad _dt_ucode_base_size symbol to create an
+ * error when it is used. This is used by binman tests.
+ *
+ * Build with:
+ * cc -march=i386 -m32 -o u_boot_no_ucode_ptr -T u_boot_ucode_ptr.lds \
+ -nostdlib u_boot_no_ucode_ptr.c
+ */
+
+static unsigned long not__dt_ucode_base_size[2]
+ __attribute__((section(".ucode"))) = {1, 2};
diff --git a/tools/binman/test/u_boot_ucode_ptr b/tools/binman/test/u_boot_ucode_ptr
new file mode 100755
index 0000000..dbfb184
--- /dev/null
+++ b/tools/binman/test/u_boot_ucode_ptr
Binary files differ
diff --git a/tools/binman/test/u_boot_ucode_ptr.c b/tools/binman/test/u_boot_ucode_ptr.c
new file mode 100644
index 0000000..434c9f4
--- /dev/null
+++ b/tools/binman/test/u_boot_ucode_ptr.c
@@ -0,0 +1,15 @@
+/*
+ * Copyright (c) 2016 Google, Inc
+ *
+ * SPDX-License-Identifier: GPL-2.0+
+ *
+ * Simple program to create a _dt_ucode_base_size symbol which can be read
+ * by 'nm'. This is used by binman tests.
+ *
+ * Build with:
+ * cc -march=i386 -m32 -o u_boot_ucode_ptr -T u_boot_ucode_ptr.lds -nostdlib \
+ u_boot_ucode_ptr.c
+ */
+
+static unsigned long _dt_ucode_base_size[2]
+ __attribute__((section(".ucode"))) = {1, 2};
diff --git a/tools/binman/test/u_boot_ucode_ptr.lds b/tools/binman/test/u_boot_ucode_ptr.lds
new file mode 100644
index 0000000..167debf
--- /dev/null
+++ b/tools/binman/test/u_boot_ucode_ptr.lds
@@ -0,0 +1,18 @@
+/*
+ * Copyright (c) 2016 Google, Inc
+ *
+ * SPDX-License-Identifier: GPL-2.0+
+ */
+
+OUTPUT_FORMAT("elf32-i386", "elf32-i386", "elf32-i386")
+OUTPUT_ARCH(i386)
+ENTRY(_start)
+
+SECTIONS
+{
+ . = 0xfffffdf0;
+ _start = .;
+ .ucode : {
+ *(.ucode)
+ }
+}
diff --git a/tools/ifdtool.c b/tools/ifdtool.c
index 48059c0..195b153 100644
--- a/tools/ifdtool.c
+++ b/tools/ifdtool.c
@@ -33,16 +33,9 @@
#define FLREG_BASE(reg) ((reg & 0x00000fff) << 12);
#define FLREG_LIMIT(reg) (((reg & 0x0fff0000) >> 4) | 0xfff);
-enum input_file_type_t {
- IF_normal,
- IF_fdt,
- IF_uboot,
-};
-
struct input_file {
char *fname;
unsigned int addr;
- enum input_file_type_t type;
};
/**
@@ -760,219 +753,6 @@ static int write_data(char *image, int size, unsigned int addr,
return write_size;
}
-static int scan_ucode(const void *blob, char *ucode_base, int *countp,
- const char **datap, int *data_sizep)
-{
- const char *data = NULL;
- int node, count;
- int data_size;
- char *ucode;
-
- for (node = 0, count = 0, ucode = ucode_base; node >= 0; count++) {
- node = fdt_node_offset_by_compatible(blob, node,
- "intel,microcode");
- if (node < 0)
- break;
-
- data = fdt_getprop(blob, node, "data", &data_size);
- if (!data) {
- debug("Missing microcode data in FDT '%s': %s\n",
- fdt_get_name(blob, node, NULL),
- fdt_strerror(data_size));
- return -ENOENT;
- }
-
- if (ucode_base)
- memcpy(ucode, data, data_size);
- ucode += data_size;
- }
-
- if (countp)
- *countp = count;
- if (datap)
- *datap = data;
- if (data_sizep)
- *data_sizep = data_size;
-
- return ucode - ucode_base;
-}
-
-static int remove_ucode(char *blob)
-{
- int node, count;
- int ret;
-
- /* Keep going until we find no more microcode to remove */
- do {
- for (node = 0, count = 0; node >= 0;) {
- int ret;
-
- node = fdt_node_offset_by_compatible(blob, node,
- "intel,microcode");
- if (node < 0)
- break;
-
- ret = fdt_delprop(blob, node, "data");
-
- /*
- * -FDT_ERR_NOTFOUND means we already removed the
- * data for this one, so we just continue.
- * 0 means we did remove it, so offsets may have
- * changed and we need to restart our scan.
- * Anything else indicates an error we should report.
- */
- if (ret == -FDT_ERR_NOTFOUND)
- continue;
- else if (!ret)
- node = 0;
- else
- return ret;
- }
- } while (count);
-
- /* Pack down to remove excees space */
- ret = fdt_pack(blob);
- if (ret)
- return ret;
-
- return fdt_totalsize(blob);
-}
-
-static int write_ucode(char *image, int size, struct input_file *fdt,
- int fdt_size, unsigned int ucode_ptr,
- int collate_ucode)
-{
- const char *data = NULL;
- char *ucode_buf;
- const void *blob;
- char *ucode_base;
- uint32_t *ptr;
- int ucode_size;
- int data_size;
- int offset;
- int count;
- int ret;
-
- blob = (void *)image + (uint32_t)(fdt->addr + size);
-
- debug("DTB at %lx\n", (char *)blob - image);
-
- /* Find out about the micrcode we have */
- ucode_size = scan_ucode(blob, NULL, &count, &data, &data_size);
- if (ucode_size < 0)
- return ucode_size;
- if (!count) {
- debug("No microcode found in FDT\n");
- return -ENOENT;
- }
-
- if (count > 1 && !collate_ucode) {
- fprintf(stderr,
- "Cannot handle multiple microcode blocks - please use -C flag to collate them\n");
- return -EMLINK;
- }
-
- /*
- * Collect the microcode into a buffer, remove it from the device
- * tree and place it immediately above the (now smaller) device tree.
- */
- if (collate_ucode && count > 1) {
- ucode_buf = malloc(ucode_size);
- if (!ucode_buf) {
- fprintf(stderr,
- "Out of memory for microcode (%d bytes)\n",
- ucode_size);
- return -ENOMEM;
- }
- ret = scan_ucode(blob, ucode_buf, NULL, NULL, NULL);
- if (ret < 0)
- return ret;
-
- /* Remove the microcode from the device tree */
- ret = remove_ucode((char *)blob);
- if (ret < 0) {
- debug("Could not remove FDT microcode: %s\n",
- fdt_strerror(ret));
- return -EINVAL;
- }
- debug("Collated %d microcode block(s)\n", count);
- debug("Device tree reduced from %x to %x bytes\n",
- fdt_size, ret);
- fdt_size = ret;
-
- /*
- * Place microcode area immediately above the FDT, aligned
- * to a 16-byte boundary.
- */
- ucode_base = (char *)(((unsigned long)blob + fdt_size + 15) &
- ~15);
-
- data = ucode_base;
- data_size = ucode_size;
- memcpy(ucode_base, ucode_buf, ucode_size);
- free(ucode_buf);
- }
-
- offset = (uint32_t)(ucode_ptr + size);
- ptr = (void *)image + offset;
-
- ptr[0] = (data - image) - size;
- ptr[1] = data_size;
- debug("Wrote microcode pointer at %x: addr=%x, size=%x\n", ucode_ptr,
- ptr[0], ptr[1]);
-
- return (collate_ucode ? data + data_size : (char *)blob + fdt_size) -
- image;
-}
-
-/**
- * write_uboot() - Write U-Boot, device tree and microcode pointer
- *
- * This writes U-Boot into a place in the flash, followed by its device tree.
- * The microcode pointer is written so that U-Boot can find the microcode in
- * the device tree very early in boot.
- *
- * @image: Pointer to image
- * @size: Size of image in bytes
- * @uboot: Input file information for u-boot.bin
- * @fdt: Input file information for u-boot.dtb
- * @ucode_ptr: Address in U-Boot where the microcode pointer should be placed
- * @return 0 if OK, -ve on error
- */
-static int write_uboot(char *image, int size, struct input_file *uboot,
- struct input_file *fdt, unsigned int ucode_ptr,
- int collate_ucode, int *offset_uboot_top,
- int *offset_uboot_start)
-{
- int uboot_size, fdt_size;
- int uboot_top;
-
- uboot_size = write_data(image, size, uboot->addr, uboot->fname, 0, 0);
- if (uboot_size < 0)
- return uboot_size;
- fdt->addr = uboot->addr + uboot_size;
- debug("U-Boot size %#x, FDT at %#x\n", uboot_size, fdt->addr);
- fdt_size = write_data(image, size, fdt->addr, fdt->fname, 0, 0);
- if (fdt_size < 0)
- return fdt_size;
-
- uboot_top = (uint32_t)(fdt->addr + size) + fdt_size;
-
- if (ucode_ptr) {
- uboot_top = write_ucode(image, size, fdt, fdt_size, ucode_ptr,
- collate_ucode);
- if (uboot_top < 0)
- return uboot_top;
- }
-
- if (offset_uboot_top && offset_uboot_start) {
- *offset_uboot_top = uboot_top;
- *offset_uboot_start = (uint32_t)(uboot->addr + size);
- }
-
- return 0;
-}
-
static void print_version(void)
{
printf("ifdtool v%s -- ", IFDTOOL_VERSION);
@@ -1034,7 +814,7 @@ int main(int argc, char *argv[])
int mode_dump = 0, mode_extract = 0, mode_inject = 0;
int mode_spifreq = 0, mode_em100 = 0, mode_locked = 0;
int mode_unlocked = 0, mode_write = 0, mode_write_descriptor = 0;
- int create = 0, collate_ucode = 0;
+ int create = 0;
char *region_type_string = NULL, *inject_fname = NULL;
char *desc_fname = NULL, *addr_str = NULL;
int region_type = -1, inputfreq = 0;
@@ -1047,14 +827,12 @@ int main(int argc, char *argv[])
char *outfile = NULL;
struct stat buf;
int size = 0;
- unsigned int ucode_ptr = 0;
bool have_uboot = false;
int bios_fd;
char *image;
int ret;
static struct option long_options[] = {
{"create", 0, NULL, 'c'},
- {"collate-microcode", 0, NULL, 'C'},
{"dump", 0, NULL, 'd'},
{"descriptor", 1, NULL, 'D'},
{"em100", 0, NULL, 'e'},
@@ -1062,7 +840,6 @@ int main(int argc, char *argv[])
{"fdt", 1, NULL, 'f'},
{"inject", 1, NULL, 'i'},
{"lock", 0, NULL, 'l'},
- {"microcode", 1, NULL, 'm'},
{"romsize", 1, NULL, 'r'},
{"spifreq", 1, NULL, 's'},
{"unlock", 0, NULL, 'u'},
@@ -1073,15 +850,12 @@ int main(int argc, char *argv[])
{0, 0, 0, 0}
};
- while ((opt = getopt_long(argc, argv, "cCdD:ef:hi:lm:r:s:uU:vw:x?",
+ while ((opt = getopt_long(argc, argv, "cdD:ef:hi:lr:s:uU:vw:x?",
long_options, &option_index)) != EOF) {
switch (opt) {
case 'c':
create = 1;
break;
- case 'C':
- collate_ucode = 1;
- break;
case 'd':
mode_dump = 1;
break;
@@ -1119,9 +893,6 @@ int main(int argc, char *argv[])
case 'l':
mode_locked = 1;
break;
- case 'm':
- ucode_ptr = strtoul(optarg, NULL, 0);
- break;
case 'r':
rom_size = strtol(optarg, NULL, 0);
debug("ROM size %d\n", rom_size);
@@ -1166,12 +937,6 @@ int main(int argc, char *argv[])
exit(EXIT_FAILURE);
}
ifile->addr = strtoll(optarg, NULL, 0);
- ifile->type = opt == 'f' ? IF_fdt :
- opt == 'U' ? IF_uboot : IF_normal;
- if (ifile->type == IF_fdt)
- fdt = ifile;
- else if (ifile->type == IF_uboot)
- have_uboot = true;
wr_num++;
} else {
fprintf(stderr,
@@ -1302,18 +1067,9 @@ int main(int argc, char *argv[])
for (wr_idx = 0; wr_idx < wr_num; wr_idx++) {
ifile = &input_file[wr_idx];
- if (ifile->type == IF_fdt) {
- continue;
- } else if (ifile->type == IF_uboot) {
- ret = write_uboot(image, size, ifile, fdt,
- ucode_ptr, collate_ucode,
- &offset_uboot_top,
- &offset_uboot_start);
- } else {
- ret = write_data(image, size, ifile->addr,
- ifile->fname, offset_uboot_top,
- offset_uboot_start);
- }
+ ret = write_data(image, size, ifile->addr,
+ ifile->fname, offset_uboot_top,
+ offset_uboot_start);
if (ret < 0)
break;
}