summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--Documentation/user/imd.rst54
-rw-r--r--Documentation/user/updating.rst3
-rw-r--r--Documentation/user/user-manual.rst1
-rw-r--r--arch/arm/boards/at91sam9m10ihd/hw_version.c1
-rw-r--r--arch/arm/boards/at91sam9x5ek/hw_version.c1
-rw-r--r--arch/arm/boards/crystalfontz-cfa10036/hwdetect.c1
-rw-r--r--arch/arm/boards/freescale-mx53-qsb/lowlevel.c1
-rw-r--r--arch/arm/boards/phytec-phyflex-imx6/lowlevel.c16
-rw-r--r--arch/arm/boards/sama5d3xek/hw_version.c1
-rw-r--r--arch/arm/boards/tqma53/lowlevel.c9
-rw-r--r--arch/arm/dts/Makefile132
-rw-r--r--arch/arm/dts/empty.c3
-rw-r--r--arch/arm/lib/barebox.lds.S2
-rw-r--r--arch/arm/lib/bootm.c1
-rw-r--r--arch/arm/lib/pbl.lds.S2
-rw-r--r--arch/arm/mach-at91/boot_test_cmd.c1
-rw-r--r--arch/arm/mach-omap/omap_generic.c1
-rw-r--r--arch/arm/mach-omap/xload.c1
-rw-r--r--arch/blackfin/boards/ipe337/cmd_alternate.c1
-rw-r--r--arch/mips/configs/qemu-malta_defconfig1
-rw-r--r--arch/mips/dts/Makefile10
-rw-r--r--arch/mips/lib/barebox.lds.S2
-rw-r--r--arch/mips/lib/bootm.c1
-rw-r--r--arch/mips/pbl/zbarebox.lds.S2
-rw-r--r--commands/Kconfig9
-rw-r--r--commands/Makefile1
-rw-r--r--commands/barebox-update.c1
-rw-r--r--commands/cp.c1
-rw-r--r--commands/crc.c1
-rw-r--r--commands/edit.c1
-rw-r--r--commands/exec.c1
-rw-r--r--commands/imd.c60
-rw-r--r--commands/insmod.c1
-rw-r--r--commands/linux16.c1
-rw-r--r--commands/of_dump.c1
-rw-r--r--commands/oftree.c1
-rw-r--r--commands/readf.c1
-rw-r--r--commands/tftp.c1
-rw-r--r--commands/ubiformat.c1
-rw-r--r--commands/uimage.c1
-rw-r--r--common/Kconfig7
-rw-r--r--common/Makefile2
-rw-r--r--common/blspec.c1
-rw-r--r--common/bootm.c1
-rw-r--r--common/hush.c1
-rw-r--r--common/imd-barebox.c25
-rw-r--r--common/imd.c322
-rw-r--r--common/menutree.c1
-rw-r--r--common/uimage.c1
-rw-r--r--drivers/usb/gadget/dfu.c1
-rw-r--r--fs/fs.c72
-rw-r--r--fs/uimagefs.c1
-rw-r--r--include/asm-generic/barebox.lds.h6
-rw-r--r--include/fs.h14
-rw-r--r--include/image-metadata.h117
-rw-r--r--include/libbb.h7
-rw-r--r--include/libfile.h18
-rw-r--r--lib/Makefile2
-rw-r--r--lib/bootstrap/disk.c1
-rw-r--r--lib/copy_file.c86
-rw-r--r--lib/gui/image_renderer.c1
-rw-r--r--lib/libbb.c93
-rw-r--r--lib/libfile.c331
-rw-r--r--scripts/Makefile2
-rw-r--r--scripts/Makefile.lib25
-rw-r--r--scripts/bareboximd.c161
-rw-r--r--scripts/dtc/.gitignore1
-rw-r--r--scripts/dtc/Makefile18
-rw-r--r--scripts/dtc/fdt.c (renamed from scripts/dtc/libfdt/fdt.c)0
-rw-r--r--scripts/dtc/fdt.h (renamed from scripts/dtc/libfdt/fdt.h)0
-rw-r--r--scripts/dtc/fdt_empty_tree.c (renamed from scripts/dtc/libfdt/fdt_empty_tree.c)0
-rw-r--r--scripts/dtc/fdt_ro.c (renamed from scripts/dtc/libfdt/fdt_ro.c)0
-rw-r--r--scripts/dtc/fdt_rw.c (renamed from scripts/dtc/libfdt/fdt_rw.c)0
-rw-r--r--scripts/dtc/fdt_strerror.c (renamed from scripts/dtc/libfdt/fdt_strerror.c)0
-rw-r--r--scripts/dtc/fdt_sw.c (renamed from scripts/dtc/libfdt/fdt_sw.c)0
-rw-r--r--scripts/dtc/fdt_wip.c (renamed from scripts/dtc/libfdt/fdt_wip.c)0
-rw-r--r--scripts/dtc/libfdt.h (renamed from scripts/dtc/libfdt/libfdt.h)0
-rw-r--r--scripts/dtc/libfdt_env.h (renamed from scripts/dtc/libfdt/libfdt_env.h)0
-rw-r--r--scripts/dtc/libfdt_internal.h (renamed from scripts/dtc/libfdt/libfdt_internal.h)0
-rwxr-xr-xscripts/gen-dtb-s56
80 files changed, 1315 insertions, 390 deletions
diff --git a/Documentation/user/imd.rst b/Documentation/user/imd.rst
new file mode 100644
index 0000000000..e0251d644e
--- /dev/null
+++ b/Documentation/user/imd.rst
@@ -0,0 +1,54 @@
+
+.. _imd:
+
+Image MetaData (IMD)
+====================
+
+barebox images can be enriched with metadata. This is useful to get information
+the board an image is compiled for and which barebox version an image contains.
+
+There are predefined tags for:
+
+- The build timestamp
+- The barebox release version
+- The model (board) the image is compiled for
+- The toplevel device tree compatible properties the image can handle
+
+Additionally there is a generic key/value tag to add information which does not
+fit into the above categories, for example the memory size for boards which come
+with different memory sizes which can't be automatically detected.
+
+The informations can be extracted with the ``bareboximd`` tool which lives under
+``scripts/`` in the barebox sourcecode. If enabled it is compiled for the compile
+host and also for the target architecture. barebox itself has the :ref:`command_imd`
+command to extract the informations. Here is an example output of the tool called
+without additional options::
+
+ # imd barebox-phytec-pbab01dl-1gib.img
+ build: #890 Wed Jul 30 16:15:24 CEST 2014
+ release: 2014.07.0-00167-ge6632a9-dirty
+ parameter: memsize=1024
+ of_compatible: phytec,imx6x-pbab01 phytec,imx6dl-pfla02 fsl,imx6dl
+ model: Phytec phyFLEX-i.MX6 Duallite Carrier-Board
+
+Single informations can be extracted with the ``-t <type>`` option::
+
+ # imd barebox-phytec-pbab01dl-1gib.img -t release
+ 2014.07.0-00167-ge6632a9-dirty
+
+Since the barebox hush does not have output redirection the barebox too has the
+``-s <var>`` option to assign the output to a variable for later evaluation.
+
+Limitations
+-----------
+
+The IMD tags are generated in the barebox binary before a SoC specific image is
+generated. Some SoCs encrypt or otherwise manipulate the images in a way that the
+IMD information is lost. The IMD mechanism does not work on these SoCs. A known
+example is the Freescale i.MX28.
+
+IMD and barebox_update
+----------------------
+
+The IMD informations could well be used to check if an image is suitable for updating
+barebox for a particular board. Support for such a check is planned but not yet implemented.
diff --git a/Documentation/user/updating.rst b/Documentation/user/updating.rst
index 2a963b6200..6a1a73348c 100644
--- a/Documentation/user/updating.rst
+++ b/Documentation/user/updating.rst
@@ -27,3 +27,6 @@ barebox has been started from is registered as default (marked with a ``*``)::
available for your board. It is recommended to implement it, but you can also
update barebox manually using :ref:`command_erase` and :ref:`command_cp`
commands. The exact commands are board specific.
+
+**NOTE** barebox images can be enriched with metadata which can be used to check
+if a given image is suitable for updating barebox, see :ref:`imd`.
diff --git a/Documentation/user/user-manual.rst b/Documentation/user/user-manual.rst
index 0eac0aadc7..3d68bbb9ae 100644
--- a/Documentation/user/user-manual.rst
+++ b/Documentation/user/user-manual.rst
@@ -19,6 +19,7 @@ Contents:
hush
defaultenv-2
updating
+ imd
devicetree
pbl
multi-image
diff --git a/arch/arm/boards/at91sam9m10ihd/hw_version.c b/arch/arm/boards/at91sam9m10ihd/hw_version.c
index 8e729013c7..96fb02d801 100644
--- a/arch/arm/boards/at91sam9m10ihd/hw_version.c
+++ b/arch/arm/boards/at91sam9m10ihd/hw_version.c
@@ -18,6 +18,7 @@
#include <fs.h>
#include <fcntl.h>
#include <libbb.h>
+#include <libfile.h>
#include <asm/armlinux.h>
#include <of.h>
diff --git a/arch/arm/boards/at91sam9x5ek/hw_version.c b/arch/arm/boards/at91sam9x5ek/hw_version.c
index 2da4e5ed8c..37eb1f80c5 100644
--- a/arch/arm/boards/at91sam9x5ek/hw_version.c
+++ b/arch/arm/boards/at91sam9x5ek/hw_version.c
@@ -18,6 +18,7 @@
#include <fs.h>
#include <fcntl.h>
#include <libbb.h>
+#include <libfile.h>
#include <asm/armlinux.h>
#include <of.h>
diff --git a/arch/arm/boards/crystalfontz-cfa10036/hwdetect.c b/arch/arm/boards/crystalfontz-cfa10036/hwdetect.c
index e28dd49fad..c94cb355e2 100644
--- a/arch/arm/boards/crystalfontz-cfa10036/hwdetect.c
+++ b/arch/arm/boards/crystalfontz-cfa10036/hwdetect.c
@@ -21,6 +21,7 @@
#include <fs.h>
#include <globalvar.h>
#include <libbb.h>
+#include <libfile.h>
#include <magicvar.h>
#include <asm/armlinux.h>
diff --git a/arch/arm/boards/freescale-mx53-qsb/lowlevel.c b/arch/arm/boards/freescale-mx53-qsb/lowlevel.c
index 51b9ef8db7..7d1c1d5b2a 100644
--- a/arch/arm/boards/freescale-mx53-qsb/lowlevel.c
+++ b/arch/arm/boards/freescale-mx53-qsb/lowlevel.c
@@ -2,6 +2,7 @@
#include <mach/esdctl.h>
#include <asm/barebox-arm-head.h>
#include <asm/barebox-arm.h>
+#include <image-metadata.h>
extern char __dtb_imx53_qsb_start[];
diff --git a/arch/arm/boards/phytec-phyflex-imx6/lowlevel.c b/arch/arm/boards/phytec-phyflex-imx6/lowlevel.c
index 55aae00954..1d08f0561a 100644
--- a/arch/arm/boards/phytec-phyflex-imx6/lowlevel.c
+++ b/arch/arm/boards/phytec-phyflex-imx6/lowlevel.c
@@ -16,6 +16,7 @@
#include <common.h>
#include <sizes.h>
#include <io.h>
+#include <image-metadata.h>
#include <asm/barebox-arm-head.h>
#include <asm/barebox-arm.h>
#include <asm/sections.h>
@@ -57,6 +58,11 @@ extern char __dtb_imx6q_phytec_pbab01_start[];
extern char __dtb_imx6dl_phytec_pbab01_start[];
extern char __dtb_imx6s_phytec_pbab01_start[];
+BAREBOX_IMD_TAG_STRING(phyflex_mx6_memsize_512M, IMD_TYPE_PARAMETER, "memsize=512", 0);
+BAREBOX_IMD_TAG_STRING(phyflex_mx6_memsize_1G, IMD_TYPE_PARAMETER, "memsize=1024", 0);
+BAREBOX_IMD_TAG_STRING(phyflex_mx6_memsize_2G, IMD_TYPE_PARAMETER, "memsize=2048", 0);
+BAREBOX_IMD_TAG_STRING(phyflex_mx6_memsize_4G, IMD_TYPE_PARAMETER, "memsize=4096", 0);
+
ENTRY_FUNCTION(start_phytec_pbab01_1gib, r0, r1, r2)
{
void *fdt;
@@ -65,6 +71,8 @@ ENTRY_FUNCTION(start_phytec_pbab01_1gib, r0, r1, r2)
arm_setup_stack(0x00920000 - 8);
+ IMD_USED(phyflex_mx6_memsize_1G);
+
if (IS_ENABLED(CONFIG_DEBUG_LL))
setup_uart();
@@ -81,6 +89,8 @@ ENTRY_FUNCTION(start_phytec_pbab01_2gib, r0, r1, r2)
arm_setup_stack(0x00920000 - 8);
+ IMD_USED(phyflex_mx6_memsize_2G);
+
if (IS_ENABLED(CONFIG_DEBUG_LL))
setup_uart();
@@ -97,6 +107,8 @@ ENTRY_FUNCTION(start_phytec_pbab01_4gib, r0, r1, r2)
arm_setup_stack(0x00920000 - 8);
+ IMD_USED(phyflex_mx6_memsize_4G);
+
fdt = __dtb_imx6q_phytec_pbab01_start - get_runtime_offset();
barebox_arm_entry(0x10000000, 0xEFFFFFF8, fdt);
@@ -110,6 +122,8 @@ ENTRY_FUNCTION(start_phytec_pbab01dl_1gib, r0, r1, r2)
arm_setup_stack(0x00920000 - 8);
+ IMD_USED(phyflex_mx6_memsize_1G);
+
fdt = __dtb_imx6dl_phytec_pbab01_start - get_runtime_offset();
barebox_arm_entry(0x10000000, SZ_1G, fdt);
@@ -123,6 +137,8 @@ ENTRY_FUNCTION(start_phytec_pbab01s_512mb, r0, r1, r2)
arm_setup_stack(0x00920000 - 8);
+ IMD_USED(phyflex_mx6_memsize_512M);
+
fdt = __dtb_imx6s_phytec_pbab01_start - get_runtime_offset();
barebox_arm_entry(0x10000000, SZ_512M, fdt);
diff --git a/arch/arm/boards/sama5d3xek/hw_version.c b/arch/arm/boards/sama5d3xek/hw_version.c
index 450eb9f8a1..c809c37742 100644
--- a/arch/arm/boards/sama5d3xek/hw_version.c
+++ b/arch/arm/boards/sama5d3xek/hw_version.c
@@ -18,6 +18,7 @@
#include <fs.h>
#include <fcntl.h>
#include <libbb.h>
+#include <libfile.h>
#include <asm/armlinux.h>
#include <of.h>
diff --git a/arch/arm/boards/tqma53/lowlevel.c b/arch/arm/boards/tqma53/lowlevel.c
index 0a67228008..cd87212555 100644
--- a/arch/arm/boards/tqma53/lowlevel.c
+++ b/arch/arm/boards/tqma53/lowlevel.c
@@ -5,6 +5,7 @@
#include <asm/barebox-arm-head.h>
#include <asm/barebox-arm.h>
#include <mach/imx5.h>
+#include <image-metadata.h>
extern char __dtb_imx53_mba53_start[];
@@ -34,6 +35,8 @@ static void __noreturn start_imx53_tqma53_common(void *fdt)
imx53_barebox_entry(fdt);
}
+BAREBOX_IMD_TAG_STRING(tqma53_memsize_512M, IMD_TYPE_PARAMETER, "memsize=512", 0);
+
ENTRY_FUNCTION(start_imx53_mba53_512mib, r0, r1, r2)
{
void *fdt;
@@ -42,6 +45,8 @@ ENTRY_FUNCTION(start_imx53_mba53_512mib, r0, r1, r2)
arm_setup_stack(0xf8020000 - 8);
+ IMD_USED(tqma53_memsize_512M);
+
imx53_init_lowlevel_early(800);
fdt = __dtb_imx53_mba53_start - get_runtime_offset();
@@ -49,6 +54,8 @@ ENTRY_FUNCTION(start_imx53_mba53_512mib, r0, r1, r2)
start_imx53_tqma53_common(fdt);
}
+BAREBOX_IMD_TAG_STRING(tqma53_memsize_1G, IMD_TYPE_PARAMETER, "memsize=1024", 0);
+
ENTRY_FUNCTION(start_imx53_mba53_1gib, r0, r1, r2)
{
void *fdt;
@@ -57,6 +64,8 @@ ENTRY_FUNCTION(start_imx53_mba53_1gib, r0, r1, r2)
arm_setup_stack(0xf8020000 - 8);
+ IMD_USED(tqma53_memsize_1G);
+
imx53_init_lowlevel_early(800);
fdt = __dtb_imx53_mba53_start - get_runtime_offset();
diff --git a/arch/arm/dts/Makefile b/arch/arm/dts/Makefile
index 18e451988d..fac2b273cb 100644
--- a/arch/arm/dts/Makefile
+++ b/arch/arm/dts/Makefile
@@ -1,95 +1,47 @@
-dtb-$(CONFIG_ARCH_AM33XX) += \
- am335x-bone.dtb \
- am335x-boneblack.dtb \
- am335x-bone-common.dtb \
- am335x-phytec-phycore.dtb
-dtb-$(CONFIG_ARCH_IMX25) += imx25-karo-tx25.dtb
-dtb-$(CONFIG_ARCH_IMX27) += imx27-phytec-phycard-s-rdk-bb.dtb \
- imx27-phytec-phycore-rdk.dtb
-dtb-$(CONFIG_ARCH_IMX51) += imx51-babbage.dtb \
- imx51-genesi-efika-sb.dtb
-dtb-$(CONFIG_ARCH_IMX53) += imx53-mba53.dtb \
- imx53-qsb.dtb \
- imx53-qsrb.dtb \
- imx53-voipac-bsb.dtb
-dtb-$(CONFIG_ARCH_IMX6) += imx6q-gk802.dtb \
- imx6dl-dfi-fs700-m60-6s.dtb \
- imx6q-dfi-fs700-m60-6q.dtb \
- imx6q-dmo-edmqmx6.dtb \
- imx6q-sabrelite.dtb \
- imx6dl-sabrelite.dtb \
- imx6q-sabresd.dtb \
- imx6dl-mba6x.dtb \
- imx6q-mba6x.dtb \
- imx6dl-phytec-pbab01.dtb \
- imx6q-phytec-pbab01.dtb \
- imx6s-phytec-pbab01.dtb \
- imx6dl-hummingboard.dtb \
- imx6q-guf-santaro.dtb \
- imx6q-nitrogen6x.dtb \
- imx6dl-nitrogen6x.dtb \
- imx6q-udoo.dtb \
- imx6q-var-custom.dtb \
- imx6s-riotboard.dtb \
- imx6q-phytec-pbaa03.dtb \
- imx6q-embedsky-e9.dtb
-dtb-$(CONFIG_ARCH_ROCKCHIP) += rk3188-radxarock.dtb
-dtb-$(CONFIG_ARCH_SOCFPGA) += socfpga_cyclone5_sockit.dtb \
- socfpga_cyclone5_socrates.dtb
-dtb-$(CONFIG_ARCH_TEGRA) += \
- tegra20-colibri-iris.dtb \
- tegra20-paz00.dtb \
- tegra30-beaver.dtb \
- tegra124-jetson-tk1.dtb
-
BUILTIN_DTB := $(patsubst "%",%,$(CONFIG_BUILTIN_DTB_NAME))
-obj-$(CONFIG_BUILTIN_DTB) += $(BUILTIN_DTB).dtb.o
-
-pbl-$(CONFIG_MACH_BEAGLEBONE) += am335x-bone.dtb.o am335x-boneblack.dtb.o am335x-bone-common.dtb.o
-pbl-$(CONFIG_MACH_DFI_FS700_M60) += imx6q-dfi-fs700-m60-6q.dtb.o imx6dl-dfi-fs700-m60-6s.dtb.o
-pbl-$(CONFIG_MACH_EFIKA_MX_SMARTBOOK) += imx51-genesi-efika-sb.dtb.o
-pbl-$(CONFIG_MACH_EMBEDSKY_E9) += imx6q-embedsky-e9.dtb.o
-pbl-$(CONFIG_MACH_EMBEST_RIOTBOARD) += imx6s-riotboard.dtb.o
-pbl-$(CONFIG_MACH_FREESCALE_MX51_PDK) += imx51-babbage.dtb.o
-pbl-$(CONFIG_MACH_FREESCALE_MX53_LOCO) += imx53-qsb.dtb.o imx53-qsrb.dtb.o
-pbl-$(CONFIG_MACH_FREESCALE_MX53_VMX53) += imx53-voipac-bsb.dtb.o
-pbl-$(CONFIG_MACH_GK802) += imx6q-gk802.dtb.o
-pbl-$(CONFIG_MACH_GLOBALSCALE_GURUPLUG) += kirkwood-guruplug-server-plus-bb.dtb.o
-pbl-$(CONFIG_MACH_GLOBALSCALE_MIRABOX) += armada-370-mirabox-bb.dtb.o
-pbl-$(CONFIG_MACH_GUF_SANTARO) += imx6q-guf-santaro.dtb.o
-pbl-$(CONFIG_MACH_MARVELL_ARMADA_XP_GP) += armada-xp-gp-bb.dtb.o
-pbl-$(CONFIG_MACH_NITROGEN6X) += imx6q-nitrogen6x.dtb.o imx6dl-nitrogen6x.dtb.o
-pbl-$(CONFIG_MACH_NVIDIA_BEAVER) += tegra30-beaver.dtb.o
-pbl-$(CONFIG_MACH_NVIDIA_JETSON) += tegra124-jetson-tk1.dtb.o
-pbl-$(CONFIG_MACH_PCA100) += imx27-phytec-phycard-s-rdk-bb.dtb.o
-pbl-$(CONFIG_MACH_PCAAXL3) += imx6q-phytec-pbaa03.dtb.o
-pbl-$(CONFIG_MACH_PCM038) += imx27-phytec-phycore-rdk.dtb.o
-pbl-$(CONFIG_MACH_PCM051) += am335x-phytec-phycore.dtb.o
-pbl-$(CONFIG_MACH_PHYTEC_PFLA02) += imx6s-phytec-pbab01.dtb.o imx6dl-phytec-pbab01.dtb.o imx6q-phytec-pbab01.dtb.o
-pbl-$(CONFIG_MACH_PLATHOME_OPENBLOCKS_AX3) += armada-xp-openblocks-ax3-4-bb.dtb.o
-pbl-$(CONFIG_MACH_RADXA_ROCK) += rk3188-radxarock.dtb.o
-pbl-$(CONFIG_MACH_REALQ7) += imx6q-dmo-edmqmx6.dtb.o
-pbl-$(CONFIG_MACH_SABRELITE) += imx6q-sabrelite.dtb.o imx6dl-sabrelite.dtb.o
-pbl-$(CONFIG_MACH_SABRESD) += imx6q-sabresd.dtb.o
-pbl-$(CONFIG_MACH_SOCFPGA_EBV_SOCRATES) += socfpga_cyclone5_socrates.dtb.o
-pbl-$(CONFIG_MACH_SOCFPGA_TERASIC_SOCKIT) += socfpga_cyclone5_sockit.dtb.o
-pbl-$(CONFIG_MACH_SOLIDRUN_CUBOX) += dove-cubox-bb.dtb.o
-pbl-$(CONFIG_MACH_SOLIDRUN_MICROSOM) += imx6dl-hummingboard.dtb.o
-pbl-$(CONFIG_MACH_TORADEX_COLIBRI_T20) += tegra20-colibri-iris.dtb.o
-pbl-$(CONFIG_MACH_TOSHIBA_AC100) += tegra20-paz00.dtb.o
-pbl-$(CONFIG_MACH_TQMA53) += imx53-mba53.dtb.o
-pbl-$(CONFIG_MACH_TQMA6X) += imx6dl-mba6x.dtb.o imx6q-mba6x.dtb.o
-pbl-$(CONFIG_MACH_TX25) += imx25-karo-tx25.dtb.o
-pbl-$(CONFIG_MACH_UDOO) += imx6q-udoo.dtb.o
-pbl-$(CONFIG_MACH_USI_TOPKICK) += kirkwood-topkick-bb.dtb.o
-pbl-$(CONFIG_MACH_VARISCITE_MX6) += imx6q-var-custom.dtb.o
-
-.SECONDARY: $(obj)/$(BUILTIN_DTB).dtb.S
-.SECONDARY: $(patsubst %,$(obj)/%.S,$(dtb-y))
+obj-dtb-$(CONFIG_BUILTIN_DTB) += $(BUILTIN_DTB).dtb.o
-targets += dtbs
-targets += $(dtb-y)
+# just to build a built-in.o. Otherwise compilation fails when no devicetree is
+# created.
+obj-y += empty.o
-extra-y += $(dtb-y)
+pbl-dtb-$(CONFIG_MACH_BEAGLEBONE) += am335x-bone.dtb.o am335x-boneblack.dtb.o am335x-bone-common.dtb.o
+pbl-dtb-$(CONFIG_MACH_DFI_FS700_M60) += imx6q-dfi-fs700-m60-6q.dtb.o imx6dl-dfi-fs700-m60-6s.dtb.o
+pbl-dtb-$(CONFIG_MACH_EFIKA_MX_SMARTBOOK) += imx51-genesi-efika-sb.dtb.o
+pbl-dtb-$(CONFIG_MACH_EMBEST_RIOTBOARD) += imx6s-riotboard.dtb.o
+pbl-dtb-$(CONFIG_MACH_EMBEDSKY_E9) += imx6q-embedsky-e9.dtb.o
+pbl-dtb-$(CONFIG_MACH_FREESCALE_MX51_PDK) += imx51-babbage.dtb.o
+pbl-dtb-$(CONFIG_MACH_FREESCALE_MX53_LOCO) += imx53-qsb.dtb.o imx53-qsrb.dtb.o
+pbl-dtb-$(CONFIG_MACH_FREESCALE_MX53_VMX53) += imx53-voipac-bsb.dtb.o
+pbl-dtb-$(CONFIG_MACH_GK802) += imx6q-gk802.dtb.o
+pbl-dtb-$(CONFIG_MACH_GLOBALSCALE_GURUPLUG) += kirkwood-guruplug-server-plus-bb.dtb.o
+pbl-dtb-$(CONFIG_MACH_GLOBALSCALE_MIRABOX) += armada-370-mirabox-bb.dtb.o
+pbl-dtb-$(CONFIG_MACH_GUF_SANTARO) += imx6q-guf-santaro.dtb.o
+pbl-dtb-$(CONFIG_MACH_MARVELL_ARMADA_XP_GP) += armada-xp-gp-bb.dtb.o
+pbl-dtb-$(CONFIG_MACH_NITROGEN6X) += imx6q-nitrogen6x.dtb.o imx6dl-nitrogen6x.dtb.o
+pbl-dtb-$(CONFIG_MACH_NVIDIA_BEAVER) += tegra30-beaver.dtb.o
+pbl-dtb-$(CONFIG_MACH_NVIDIA_JETSON) += tegra124-jetson-tk1.dtb.o
+pbl-dtb-$(CONFIG_MACH_PCA100) += imx27-phytec-phycard-s-rdk-bb.dtb.o
+pbl-dtb-$(CONFIG_MACH_PCAAXL3) += imx6q-phytec-pbaa03.dtb.o
+pbl-dtb-$(CONFIG_MACH_PCM038) += imx27-phytec-phycore-rdk.dtb.o
+pbl-dtb-$(CONFIG_MACH_PCM051) += am335x-phytec-phycore.dtb.o
+pbl-dtb-$(CONFIG_MACH_PHYTEC_PFLA02) += imx6s-phytec-pbab01.dtb.o imx6dl-phytec-pbab01.dtb.o imx6q-phytec-pbab01.dtb.o
+pbl-dtb-$(CONFIG_MACH_PLATHOME_OPENBLOCKS_AX3) += armada-xp-openblocks-ax3-4-bb.dtb.o
+pbl-dtb-$(CONFIG_MACH_RADXA_ROCK) += rk3188-radxarock.dtb.o
+pbl-dtb-$(CONFIG_MACH_REALQ7) += imx6q-dmo-edmqmx6.dtb.o
+pbl-dtb-$(CONFIG_MACH_SABRELITE) += imx6q-sabrelite.dtb.o imx6dl-sabrelite.dtb.o
+pbl-dtb-$(CONFIG_MACH_SABRESD) += imx6q-sabresd.dtb.o
+pbl-dtb-$(CONFIG_MACH_SOCFPGA_EBV_SOCRATES) += socfpga_cyclone5_socrates.dtb.o
+pbl-dtb-$(CONFIG_MACH_SOCFPGA_TERASIC_SOCKIT) += socfpga_cyclone5_sockit.dtb.o
+pbl-dtb-$(CONFIG_MACH_SOLIDRUN_CUBOX) += dove-cubox-bb.dtb.o
+pbl-dtb-$(CONFIG_MACH_SOLIDRUN_MICROSOM) += imx6dl-hummingboard.dtb.o
+pbl-dtb-$(CONFIG_MACH_TORADEX_COLIBRI_T20) += tegra20-colibri-iris.dtb.o
+pbl-dtb-$(CONFIG_MACH_TOSHIBA_AC100) += tegra20-paz00.dtb.o
+pbl-dtb-$(CONFIG_MACH_TQMA53) += imx53-mba53.dtb.o
+pbl-dtb-$(CONFIG_MACH_TQMA6X) += imx6dl-mba6x.dtb.o imx6q-mba6x.dtb.o
+pbl-dtb-$(CONFIG_MACH_TX25) += imx25-karo-tx25.dtb.o
+pbl-dtb-$(CONFIG_MACH_UDOO) += imx6q-udoo.dtb.o
+pbl-dtb-$(CONFIG_MACH_USI_TOPKICK) += kirkwood-topkick-bb.dtb.o
+pbl-dtb-$(CONFIG_MACH_VARISCITE_MX6) += imx6q-var-custom.dtb.o
clean-files := *.dtb *.dtb.S .*.dtc .*.pre .*.dts
diff --git a/arch/arm/dts/empty.c b/arch/arm/dts/empty.c
new file mode 100644
index 0000000000..d141224cf8
--- /dev/null
+++ b/arch/arm/dts/empty.c
@@ -0,0 +1,3 @@
+static inline void empty(void)
+{
+}
diff --git a/arch/arm/lib/barebox.lds.S b/arch/arm/lib/barebox.lds.S
index d9588736f8..bb0354ae29 100644
--- a/arch/arm/lib/barebox.lds.S
+++ b/arch/arm/lib/barebox.lds.S
@@ -75,6 +75,8 @@ SECTIONS
. = ALIGN(4);
.data : { *(.data*) }
+ .barebox_imd : { BAREBOX_IMD }
+
. = .;
__barebox_cmd_start = .;
.barebox_cmd : { BAREBOX_CMDS }
diff --git a/arch/arm/lib/bootm.c b/arch/arm/lib/bootm.c
index ffd56edfd3..baf0946a47 100644
--- a/arch/arm/lib/bootm.c
+++ b/arch/arm/lib/bootm.c
@@ -6,6 +6,7 @@
#include <image.h>
#include <init.h>
#include <fs.h>
+#include <libfile.h>
#include <linux/list.h>
#include <xfuncs.h>
#include <malloc.h>
diff --git a/arch/arm/lib/pbl.lds.S b/arch/arm/lib/pbl.lds.S
index 76184a0eec..9afee2964a 100644
--- a/arch/arm/lib/pbl.lds.S
+++ b/arch/arm/lib/pbl.lds.S
@@ -54,6 +54,8 @@ SECTIONS
. = ALIGN(4);
.rodata : { *(.rodata*) }
+ .barebox_imd : { BAREBOX_IMD }
+
_etext = .; /* End of text and rodata section */
. = ALIGN(4);
diff --git a/arch/arm/mach-at91/boot_test_cmd.c b/arch/arm/mach-at91/boot_test_cmd.c
index 66c598b7ce..4fd1998ad0 100644
--- a/arch/arm/mach-at91/boot_test_cmd.c
+++ b/arch/arm/mach-at91/boot_test_cmd.c
@@ -7,6 +7,7 @@
#include <common.h>
#include <command.h>
#include <libbb.h>
+#include <libfile.h>
#include <getopt.h>
#include <fs.h>
#include <fcntl.h>
diff --git a/arch/arm/mach-omap/omap_generic.c b/arch/arm/mach-omap/omap_generic.c
index 060c59277f..334cf8db56 100644
--- a/arch/arm/mach-omap/omap_generic.c
+++ b/arch/arm/mach-omap/omap_generic.c
@@ -20,6 +20,7 @@
#include <io.h>
#include <fs.h>
#include <malloc.h>
+#include <libfile.h>
#include <linux/stat.h>
#include <mach/gpmc.h>
#include <mach/generic.h>
diff --git a/arch/arm/mach-omap/xload.c b/arch/arm/mach-omap/xload.c
index a309450109..e9d7bbb2e9 100644
--- a/arch/arm/mach-omap/xload.c
+++ b/arch/arm/mach-omap/xload.c
@@ -5,6 +5,7 @@
#include <init.h>
#include <driver.h>
#include <linux/mtd/mtd.h>
+#include <libfile.h>
#include <fs.h>
#include <fcntl.h>
#include <sizes.h>
diff --git a/arch/blackfin/boards/ipe337/cmd_alternate.c b/arch/blackfin/boards/ipe337/cmd_alternate.c
index 992d274847..b332cfb059 100644
--- a/arch/blackfin/boards/ipe337/cmd_alternate.c
+++ b/arch/blackfin/boards/ipe337/cmd_alternate.c
@@ -1,5 +1,6 @@
#include <common.h>
#include <command.h>
+#include <libfile.h>
#include <linux/stat.h>
#include <malloc.h>
#include <fs.h>
diff --git a/arch/mips/configs/qemu-malta_defconfig b/arch/mips/configs/qemu-malta_defconfig
index 6ee302df02..5a1ca36822 100644
--- a/arch/mips/configs/qemu-malta_defconfig
+++ b/arch/mips/configs/qemu-malta_defconfig
@@ -14,6 +14,7 @@ CONFIG_POLLER=y
CONFIG_DEBUG_INFO=y
CONFIG_LONGHELP=y
CONFIG_CMD_IOMEM=y
+CONFIG_CMD_IMD=y
CONFIG_CMD_MEMINFO=y
CONFIG_CMD_BOOTM_SHOW_TYPE=y
CONFIG_CMD_GO=y
diff --git a/arch/mips/dts/Makefile b/arch/mips/dts/Makefile
index 7ccb2f811c..6d6c9a3ce0 100644
--- a/arch/mips/dts/Makefile
+++ b/arch/mips/dts/Makefile
@@ -2,14 +2,4 @@
BUILTIN_DTB := $(patsubst "%",%,$(CONFIG_BUILTIN_DTB_NAME))
obj-$(CONFIG_BUILTIN_DTB) += $(BUILTIN_DTB).dtb.o
-dtb-y += ${BUILTIN_DTB}.dtb
-
-.SECONDARY: $(obj)/$(BUILTIN_DTB).dtb.S
-.SECONDARY: $(patsubst %,$(obj)/%.S,$(dtb-y))
-
-targets += dtbs
-targets += $(dtb-y)
-
-extra-y += $(dtb-y)
-
clean-files := *.dtb *.dtb.S
diff --git a/arch/mips/lib/barebox.lds.S b/arch/mips/lib/barebox.lds.S
index 4ee4252b6d..c690e71976 100644
--- a/arch/mips/lib/barebox.lds.S
+++ b/arch/mips/lib/barebox.lds.S
@@ -49,6 +49,8 @@ SECTIONS
. = ALIGN(4);
.data : { *(.data*) }
+ .barebox_imd : { BAREBOX_IMD }
+
. = ALIGN(4);
.got : { *(.got*) }
diff --git a/arch/mips/lib/bootm.c b/arch/mips/lib/bootm.c
index 3d6a4ce648..0e03aa9bcb 100644
--- a/arch/mips/lib/bootm.c
+++ b/arch/mips/lib/bootm.c
@@ -1,5 +1,6 @@
#include <boot.h>
#include <common.h>
+#include <libfile.h>
#include <init.h>
#include <fs.h>
#include <errno.h>
diff --git a/arch/mips/pbl/zbarebox.lds.S b/arch/mips/pbl/zbarebox.lds.S
index 3a26942b4c..a883fdb2db 100644
--- a/arch/mips/pbl/zbarebox.lds.S
+++ b/arch/mips/pbl/zbarebox.lds.S
@@ -44,6 +44,8 @@ SECTIONS
. = ALIGN(4);
.rodata : { *(.rodata*) }
+ .barebox_imd : { BAREBOX_IMD }
+
_etext = .; /* End of text and rodata section */
. = ALIGN(4);
diff --git a/commands/Kconfig b/commands/Kconfig
index b03f74a82b..71cd1ee99e 100644
--- a/commands/Kconfig
+++ b/commands/Kconfig
@@ -148,6 +148,15 @@ config CMD_IOMEM
Show information about iomem/ioport usage. Pendant to
'cat /proc/iomem' and 'cat /proc/ioports' under Linux.
+config CMD_IMD
+ tristate
+ prompt "imd"
+ select IMD
+ help
+ barebox images can have metadata in them which contains information
+ like the barebox version and the build time. Say yes here to get the
+ imd command which can extract that information from images.
+
config CMD_MEMINFO
tristate
prompt "meminfo"
diff --git a/commands/Makefile b/commands/Makefile
index d42aca5c0c..44741360e2 100644
--- a/commands/Makefile
+++ b/commands/Makefile
@@ -100,3 +100,4 @@ obj-$(CONFIG_CMD_MENUTREE) += menutree.o
obj-$(CONFIG_CMD_2048) += 2048.o
obj-$(CONFIG_CMD_REGULATOR) += regulator.o
obj-$(CONFIG_CMD_LSPCI) += lspci.o
+obj-$(CONFIG_CMD_IMD) += imd.o
diff --git a/commands/barebox-update.c b/commands/barebox-update.c
index a24dc3ef4d..92e0efab6a 100644
--- a/commands/barebox-update.c
+++ b/commands/barebox-update.c
@@ -17,6 +17,7 @@
*/
#include <common.h>
#include <command.h>
+#include <libfile.h>
#include <getopt.h>
#include <malloc.h>
#include <errno.h>
diff --git a/commands/cp.c b/commands/cp.c
index 1a5675405e..af7a3d4dc0 100644
--- a/commands/cp.c
+++ b/commands/cp.c
@@ -26,6 +26,7 @@
#include <malloc.h>
#include <libgen.h>
#include <getopt.h>
+#include <libfile.h>
/**
* @param[in] argc Argument count from command line
diff --git a/commands/crc.c b/commands/crc.c
index 7c2936c23c..9b6a3e2a4b 100644
--- a/commands/crc.c
+++ b/commands/crc.c
@@ -22,6 +22,7 @@
#include <fs.h>
#include <getopt.h>
#include <malloc.h>
+#include <libfile.h>
#include <environment.h>
static int crc_from_file(const char* file, ulong *crc)
diff --git a/commands/edit.c b/commands/edit.c
index 98af583574..b28e2b92a1 100644
--- a/commands/edit.c
+++ b/commands/edit.c
@@ -21,6 +21,7 @@
#include <fs.h>
#include <linux/ctype.h>
#include <fcntl.h>
+#include <libfile.h>
#include <readkey.h>
#include <errno.h>
#include <xfuncs.h>
diff --git a/commands/exec.c b/commands/exec.c
index 635f65eeb2..7c8934f137 100644
--- a/commands/exec.c
+++ b/commands/exec.c
@@ -23,6 +23,7 @@
#include <fcntl.h>
#include <linux/stat.h>
#include <errno.h>
+#include <libfile.h>
#include <malloc.h>
#include <xfuncs.h>
diff --git a/commands/imd.c b/commands/imd.c
new file mode 100644
index 0000000000..f1a22cef96
--- /dev/null
+++ b/commands/imd.c
@@ -0,0 +1,60 @@
+/*
+ * (C) Copyright 2014 Sascha Hauer, Pengutronix
+ *
+ * See file CREDITS for list of people who contributed to this
+ * project.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of
+ * the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ */
+
+#include <common.h>
+#include <command.h>
+#include <complete.h>
+#include <environment.h>
+#include <image-metadata.h>
+
+int imd_command_setenv(const char *variable_name, const char *value)
+{
+ return setenv(variable_name, value);
+}
+
+static int do_imd(int argc, char *argv[])
+{
+ int ret;
+
+ ret = imd_command(argc, argv);
+
+ if (ret == -ENOSYS)
+ return COMMAND_ERROR_USAGE;
+
+ return ret;
+}
+
+BAREBOX_CMD_HELP_START(imd)
+BAREBOX_CMD_HELP_TEXT("extract metadata from barebox binary")
+BAREBOX_CMD_HELP_TEXT("")
+BAREBOX_CMD_HELP_TEXT("Options:")
+BAREBOX_CMD_HELP_OPT ("-t <type>", "only show information of <type>")
+BAREBOX_CMD_HELP_OPT ("-n <no>", "for tags with multiple strings only show string <no>")
+BAREBOX_CMD_HELP_OPT ("-s VARNAME", "set variable VARNAME instead of showing information")
+BAREBOX_CMD_HELP_TEXT("")
+BAREBOX_CMD_HELP_TEXT("Without options all information available is printed. Valid types are:")
+BAREBOX_CMD_HELP_TEXT("release, build, model, of_compatible")
+BAREBOX_CMD_HELP_END
+
+BAREBOX_CMD_START(imd)
+ .cmd = do_imd,
+ BAREBOX_CMD_DESC("extract metadata from barebox binary")
+ BAREBOX_CMD_OPTS("[nst] FILE")
+ BAREBOX_CMD_GROUP(CMD_GRP_INFO)
+ BAREBOX_CMD_HELP(cmd_imd_help)
+BAREBOX_CMD_END
diff --git a/commands/insmod.c b/commands/insmod.c
index 176437ee70..735dde0222 100644
--- a/commands/insmod.c
+++ b/commands/insmod.c
@@ -3,6 +3,7 @@
#include <module.h>
#include <errno.h>
#include <fs.h>
+#include <libfile.h>
#include <malloc.h>
static int do_insmod(int argc, char *argv[])
diff --git a/commands/linux16.c b/commands/linux16.c
index 594efc7dc2..bb678bdb83 100644
--- a/commands/linux16.c
+++ b/commands/linux16.c
@@ -24,6 +24,7 @@
#include <environment.h>
#include <fs.h>
#include <errno.h>
+#include <libfile.h>
#include <getopt.h>
#include <malloc.h>
#include <boot.h>
diff --git a/commands/of_dump.c b/commands/of_dump.c
index cafde07b7c..315dbbae8c 100644
--- a/commands/of_dump.c
+++ b/commands/of_dump.c
@@ -18,6 +18,7 @@
*/
#include <common.h>
+#include <libfile.h>
#include <fdt.h>
#include <of.h>
#include <command.h>
diff --git a/commands/oftree.c b/commands/oftree.c
index 49976bc02a..8a47c0be58 100644
--- a/commands/oftree.c
+++ b/commands/oftree.c
@@ -26,6 +26,7 @@
#include <common.h>
#include <environment.h>
#include <fdt.h>
+#include <libfile.h>
#include <of.h>
#include <command.h>
#include <fs.h>
diff --git a/commands/readf.c b/commands/readf.c
index c8cc574f35..8dd5a2b55a 100644
--- a/commands/readf.c
+++ b/commands/readf.c
@@ -1,6 +1,7 @@
#include <common.h>
#include <command.h>
#include <fs.h>
+#include <libfile.h>
#include <malloc.h>
#include <linux/stat.h>
#include <linux/ctype.h>
diff --git a/commands/tftp.c b/commands/tftp.c
index 62b9424cf3..8a3b541382 100644
--- a/commands/tftp.c
+++ b/commands/tftp.c
@@ -24,6 +24,7 @@
#include <fs.h>
#include <net.h>
#include <libbb.h>
+#include <libfile.h>
#define TFTP_MOUNT_PATH "/.tftp_tmp_path"
diff --git a/commands/ubiformat.c b/commands/ubiformat.c
index 443d645a5a..df0b801da9 100644
--- a/commands/ubiformat.c
+++ b/commands/ubiformat.c
@@ -40,6 +40,7 @@
#include <malloc.h>
#include <ioctl.h>
#include <libbb.h>
+#include <libfile.h>
#include <linux/mtd/mtd.h>
#include <linux/kernel.h>
#include <linux/stat.h>
diff --git a/commands/uimage.c b/commands/uimage.c
index 33523d7e5c..7c2dca41ec 100644
--- a/commands/uimage.c
+++ b/commands/uimage.c
@@ -7,6 +7,7 @@
#include <malloc.h>
#include <errno.h>
#include <getopt.h>
+#include <libfile.h>
static int uimage_fd;
diff --git a/common/Kconfig b/common/Kconfig
index 8b361260c0..d3f9801647 100644
--- a/common/Kconfig
+++ b/common/Kconfig
@@ -465,6 +465,13 @@ config BLSPEC
on a device and it allows the Operating System to install / update
kernels.
+config IMD
+ bool "barebox metadata support"
+
+config IMD_TARGET
+ bool "build bareboximd target tool"
+ depends on IMD
+
config KERNEL_INSTALL_TARGET
bool
depends on !SANDBOX
diff --git a/common/Makefile b/common/Makefile
index 4220e15127..ddd7db2578 100644
--- a/common/Makefile
+++ b/common/Makefile
@@ -46,6 +46,8 @@ obj-$(CONFIG_UIMAGE) += image.o uimage.o
obj-$(CONFIG_MENUTREE) += menutree.o
obj-$(CONFIG_EFI_GUID) += efi-guid.o
obj-$(CONFIG_EFI_DEVICEPATH) += efi-devicepath.o
+lwl-$(CONFIG_IMD) += imd-barebox.o
+obj-$(CONFIG_IMD) += imd.o
quiet_cmd_pwd_h = PWDH $@
ifdef CONFIG_PASSWORD
diff --git a/common/blspec.c b/common/blspec.c
index 9314eeab04..a4adc48da9 100644
--- a/common/blspec.c
+++ b/common/blspec.c
@@ -21,6 +21,7 @@
#include <malloc.h>
#include <block.h>
#include <fcntl.h>
+#include <libfile.h>
#include <libbb.h>
#include <init.h>
#include <boot.h>
diff --git a/common/bootm.c b/common/bootm.c
index 71390cb845..447c9b624c 100644
--- a/common/bootm.c
+++ b/common/bootm.c
@@ -16,6 +16,7 @@
#include <fs.h>
#include <malloc.h>
#include <memory.h>
+#include <libfile.h>
#include <globalvar.h>
#include <init.h>
diff --git a/common/hush.c b/common/hush.c
index 6be43cf8ea..09d9326c85 100644
--- a/common/hush.c
+++ b/common/hush.c
@@ -118,6 +118,7 @@
#include <libbb.h>
#include <glob.h>
#include <getopt.h>
+#include <libfile.h>
#include <libbb.h>
#include <magicvar.h>
#include <linux/list.h>
diff --git a/common/imd-barebox.c b/common/imd-barebox.c
new file mode 100644
index 0000000000..e9cd37d83e
--- /dev/null
+++ b/common/imd-barebox.c
@@ -0,0 +1,25 @@
+#include <common.h>
+#include <image-metadata.h>
+#include <generated/compile.h>
+#include <generated/utsrelease.h>
+
+/*
+ * Mark a imd entry as used so that the linker cannot
+ * throw it away.
+ */
+void imd_used(const void *used)
+{
+}
+
+struct imd_header imd_start_header
+__BAREBOX_IMD_SECTION(.barebox_imd_start) = {
+ .type = cpu_to_le32(IMD_TYPE_START),
+};
+
+struct imd_header imd_end_header
+__BAREBOX_IMD_SECTION(.barebox_imd_end) = {
+ .type = cpu_to_le32(IMD_TYPE_END),
+};
+
+BAREBOX_IMD_TAG_STRING(imd_build_tag, IMD_TYPE_BUILD, UTS_VERSION, 1);
+BAREBOX_IMD_TAG_STRING(imd_release_tag, IMD_TYPE_RELEASE, UTS_RELEASE, 1);
diff --git a/common/imd.c b/common/imd.c
new file mode 100644
index 0000000000..2c837d6f25
--- /dev/null
+++ b/common/imd.c
@@ -0,0 +1,322 @@
+/*
+ * (C) Copyright 2014 Sascha Hauer, Pengutronix
+ *
+ * See file CREDITS for list of people who contributed to this
+ * project.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of
+ * the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ */
+#ifdef __BAREBOX__
+#include <common.h>
+#include <image-metadata.h>
+#include <libfile.h>
+#include <getopt.h>
+#include <malloc.h>
+#include <fs.h>
+#endif
+
+/*
+ * imd_next - return a pointer to the next metadata field.
+ * @imd The current metadata field
+ */
+struct imd_header *imd_next(struct imd_header *imd)
+{
+ int length;
+
+ length = imd_read_length(imd);
+ length = ALIGN(length, 4);
+ length += 8;
+
+ return (void *)imd + length;
+}
+
+struct imd_header *imd_find_type(struct imd_header *imd, uint32_t type)
+{
+ imd_for_each(imd, imd)
+ if (imd_read_type(imd) == type)
+ return imd;
+
+ return NULL;
+}
+
+static int imd_next_validate(void *buf, int bufsize, int start_ofs)
+{
+ int length, size;
+ struct imd_header *imd = buf + start_ofs;
+
+ size = bufsize - start_ofs;
+
+ if (size < 8) {
+ debug("trunkated tag at offset %dd\n", start_ofs);
+ return -EINVAL;
+ }
+
+ length = imd_read_length(imd);
+ length = ALIGN(length, 4);
+ length += 8;
+
+ if (size < length) {
+ debug("tag at offset %d with size %d exceeds bufsize %d\n",
+ start_ofs, size, bufsize);
+ return -EINVAL;
+ }
+
+ debug("tag at offset %d has length %d\n", start_ofs, length);
+
+ return length;
+}
+
+static int imd_validate_tags(void *buf, int bufsize, int start_ofs)
+{
+ int ret;
+ struct imd_header *imd = buf + start_ofs;
+
+ while (1) {
+ uint32_t type;
+
+ ret = imd_next_validate(buf, bufsize, start_ofs);
+ if (ret < 0) {
+ debug("Invalid tag at offset %d\n", start_ofs);
+ return -EINVAL;
+ }
+
+ imd = (void *)imd + ret;
+ start_ofs += ret;
+
+ type = imd_read_type(imd);
+
+ if (!imd_type_valid(type)) {
+ debug("Invalid: tag: 0x%08x\n", type);
+ return -EINVAL;
+ }
+
+ if (type == IMD_TYPE_END)
+ return 0;
+ }
+}
+
+/*
+ * imd_search_validate - find valid metadata in a buffer
+ * @buf the buffer
+ * @size buffer size
+ * @start The returned pointer to the metadata
+ *
+ * This iterates over a buffer and searches for metadata. The metadata
+ * is checked for consistency (length fields not exceeding buffer and
+ * presence of end header) and returned in @start. The returned pointer
+ * is only valid when 0 is returned. The returned data may be unaligned.
+ */
+static int imd_search_validate(void *buf, int size, struct imd_header **start)
+{
+ int start_ofs = 0;
+ int i, ret;
+
+ for (i = start_ofs; i < size - 32; i++) {
+ uint32_t type;
+
+ type = imd_read_le32(buf + i);
+
+ if (type != IMD_TYPE_START)
+ continue;
+
+ debug("Start tag found at offset %d\n", i);
+
+ ret = imd_validate_tags(buf, size, i);
+ if (!ret) {
+ *start = buf + i;
+ return 0;
+ }
+ }
+
+ return -EINVAL;
+}
+
+struct imd_type_names {
+ uint32_t type;
+ const char *name;
+};
+
+static struct imd_type_names imd_types[] = {
+ {
+ .type = IMD_TYPE_RELEASE,
+ .name = "release",
+ }, {
+ .type = IMD_TYPE_BUILD,
+ .name = "build",
+ }, {
+ .type = IMD_TYPE_MODEL,
+ .name = "model",
+ }, {
+ .type = IMD_TYPE_PARAMETER,
+ .name = "parameter",
+ }, {
+ .type = IMD_TYPE_OF_COMPATIBLE,
+ .name = "of_compatible",
+ },
+};
+
+static const char *imd_type_to_name(uint32_t type)
+{
+ int i;
+
+ for (i = 0; i < ARRAY_SIZE(imd_types); i++)
+ if (imd_types[i].type == type)
+ return imd_types[i].name;
+
+ return "unknown";
+}
+
+static uint32_t imd_name_to_type(const char *name)
+{
+ int i;
+
+ for (i = 0; i < ARRAY_SIZE(imd_types); i++)
+ if (!strcmp(imd_types[i].name, name))
+ return imd_types[i].type;
+
+ return IMD_TYPE_INVALID;
+}
+
+static char *imd_string_data(struct imd_entry_string *imd_string, int index)
+{
+ int i, total = 0, l = 0;
+ int len = imd_read_length(&imd_string->header);
+ char *p = imd_string->data;
+
+ for (i = 0; total < len; total += l, p += l) {
+ l = strlen(p) + 1;
+ if (i++ == index)
+ return p;
+ }
+
+ return NULL;
+}
+
+static char *imd_concat_strings(struct imd_entry_string *imd_string)
+{
+ int i, len = imd_read_length(&imd_string->header);
+ char *str;
+
+ str = malloc(len);
+ if (!str)
+ return NULL;
+
+ memcpy(str, imd_string->data, len);
+
+ for (i = 0; i < len - 1; i++)
+ if (str[i] == 0)
+ str[i] = ' ';
+
+ return str;
+}
+
+int imd_command_verbose;
+
+int imd_command(int argc, char *argv[])
+{
+ int ret, opt, strno = -1;
+ void *buf;
+ size_t size;
+ uint32_t type = IMD_TYPE_INVALID;
+ struct imd_header *imd_start, *imd;
+ const char *filename;
+ const char *variable_name = NULL;
+ char *str;
+
+ imd_command_verbose = 0;
+
+ while ((opt = getopt(argc, argv, "vt:s:n:")) > 0) {
+ switch(opt) {
+ case 't':
+ type = imd_name_to_type(optarg);
+ if (type == IMD_TYPE_INVALID) {
+ fprintf(stderr, "no such type: %s\n", optarg);
+ return -ENOSYS;
+ }
+ break;
+ case 's':
+ variable_name = optarg;
+ break;
+ case 'v':
+ imd_command_verbose = 1;
+ break;
+ case 'n':
+ strno = simple_strtoul(optarg, NULL, 0);
+ break;
+ default:
+ return -ENOSYS;
+ }
+ }
+
+ if (optind == argc) {
+ fprintf(stderr, "No image given\n");
+ return -ENOSYS;
+ }
+
+ filename = argv[optind];
+
+ ret = read_file_2(filename, &size, &buf, 0x100000);
+ if (ret && ret != -EFBIG)
+ return -errno;
+
+ ret = imd_search_validate(buf, size, &imd_start);
+ if (ret)
+ return ret;
+
+ if (type == IMD_TYPE_INVALID) {
+ imd_for_each(imd_start, imd) {
+ uint32_t type = imd_read_type(imd);
+
+ if (imd_is_string(type)) {
+ struct imd_entry_string *imd_string =
+ (struct imd_entry_string *)imd;
+
+ str = imd_concat_strings(imd_string);
+
+ printf("%s: %s\n", imd_type_to_name(type), str);
+ } else {
+ debug("Unknown tag 0x%08x\n", type);
+ }
+ }
+ } else {
+ imd = imd_find_type(imd_start, type);
+ if (!imd) {
+ debug("No tag of type 0x%08x found\n", type);
+ return -ENODATA;
+ }
+
+ if (imd_is_string(type)) {
+ struct imd_entry_string *imd_string =
+ (struct imd_entry_string *)imd;
+
+ if (strno >= 0)
+ str = imd_string_data(imd_string, strno);
+ else
+ str = imd_concat_strings(imd_string);
+
+ if (!str)
+ return -ENODATA;
+
+ if (variable_name)
+ imd_command_setenv(variable_name, str);
+ else
+ printf("%s\n", str);
+
+ if (strno < 0)
+ free(str);
+ } else {
+ printf("tag 0x%08x present\n", type);
+ }
+ }
+
+ return 0;
+}
diff --git a/common/menutree.c b/common/menutree.c
index 814512d7b7..97e628de88 100644
--- a/common/menutree.c
+++ b/common/menutree.c
@@ -15,6 +15,7 @@
#include <glob.h>
#include <menu.h>
#include <fs.h>
+#include <libfile.h>
#include <linux/stat.h>
diff --git a/common/uimage.c b/common/uimage.c
index 4ef09682c1..a7011a7623 100644
--- a/common/uimage.c
+++ b/common/uimage.c
@@ -22,6 +22,7 @@
#include <malloc.h>
#include <errno.h>
#include <libbb.h>
+#include <libfile.h>
#include <uncompress.h>
#include <fcntl.h>
#include <fs.h>
diff --git a/drivers/usb/gadget/dfu.c b/drivers/usb/gadget/dfu.c
index d0f2155e49..bc5ee9c7dd 100644
--- a/drivers/usb/gadget/dfu.c
+++ b/drivers/usb/gadget/dfu.c
@@ -43,6 +43,7 @@
#include <linux/list.h>
#include <usb/gadget.h>
#include <linux/stat.h>
+#include <libfile.h>
#include <usb/ch9.h>
#include <usb/dfu.h>
#include <config.h>
diff --git a/fs/fs.c b/fs/fs.c
index dd410b731a..fd3d353588 100644
--- a/fs/fs.c
+++ b/fs/fs.c
@@ -34,78 +34,6 @@
#include <libgen.h>
#include <block.h>
-void *read_file(const char *filename, size_t *size)
-{
- int fd;
- struct stat s;
- void *buf = NULL;
- const char *tmpfile = "/.read_file_tmp";
- int ret;
-
-again:
- if (stat(filename, &s))
- return NULL;
-
- if (s.st_size == FILESIZE_MAX) {
- ret = copy_file(filename, tmpfile, 0);
- if (ret)
- return NULL;
- filename = tmpfile;
- goto again;
- }
-
- buf = xzalloc(s.st_size + 1);
-
- fd = open(filename, O_RDONLY);
- if (fd < 0)
- goto err_out;
-
- ret = read_full(fd, buf, s.st_size);
- if (ret < 0)
- goto err_out1;
-
- close(fd);
-
- if (size)
- *size = s.st_size;
-
- if (filename == tmpfile)
- unlink(tmpfile);
-
- return buf;
-
-err_out1:
- close(fd);
-err_out:
- free(buf);
-
- if (filename == tmpfile)
- unlink(tmpfile);
-
- return NULL;
-}
-
-EXPORT_SYMBOL(read_file);
-
-int write_file(const char *filename, void *buf, size_t size)
-{
- int fd, ret;
-
- fd = open(filename, O_WRONLY | O_TRUNC | O_CREAT);
- if (fd < 0)
- return fd;
-
- ret = write_full(fd, buf, size);
-
- close(fd);
-
- if (ret < 0)
- return ret;
-
- return 0;
-}
-EXPORT_SYMBOL(write_file);
-
char *mkmodestr(unsigned long mode, char *str)
{
static const char *l = "xwr";
diff --git a/fs/uimagefs.c b/fs/uimagefs.c
index 6547b7cb77..63931c2d7d 100644
--- a/fs/uimagefs.c
+++ b/fs/uimagefs.c
@@ -17,6 +17,7 @@
#include <uimagefs.h>
#include <libbb.h>
#include <rtc.h>
+#include <libfile.h>
static bool uimagefs_is_data_file(struct uimagefs_handle_data *d)
{
diff --git a/include/asm-generic/barebox.lds.h b/include/asm-generic/barebox.lds.h
index 5dabda3fbb..66abff30fa 100644
--- a/include/asm-generic/barebox.lds.h
+++ b/include/asm-generic/barebox.lds.h
@@ -53,6 +53,12 @@
KEEP(*(.dtb.rodata.*)); \
__dtb_end = .;
+#define BAREBOX_IMD \
+ KEEP(*(.barebox_imd_start)) \
+ KEEP(*(.barebox_imd_1*)) \
+ *(.barebox_imd_0*) \
+ KEEP(*(.barebox_imd_end))
+
#if defined(CONFIG_ARCH_BAREBOX_MAX_BARE_INIT_SIZE) && \
CONFIG_ARCH_BAREBOX_MAX_BARE_INIT_SIZE < CONFIG_BAREBOX_MAX_BARE_INIT_SIZE
#define MAX_BARE_INIT_SIZE CONFIG_ARCH_BAREBOX_MAX_BARE_INIT_SIZE
diff --git a/include/fs.h b/include/fs.h
index 073641c747..b2541a4ee5 100644
--- a/include/fs.h
+++ b/include/fs.h
@@ -164,20 +164,6 @@ int ls(const char *path, ulong flags);
char *mkmodestr(unsigned long mode, char *str);
/*
- * Read a file into memory. Memory is allocated with malloc and must
- * be freed with free() afterwards. This function allocates one
- * byte more than actually needed and sets this to zero, so that
- * it can be used for text files.
- * If size is nonzero it s set to the file size.
- */
-void *read_file(const char *filename, size_t *size);
-
-/*
- * Write a buffer to a file. This file is newly created.
- */
-int write_file(const char *filename, void *buf, size_t size);
-
-/*
* This function turns 'path' into an absolute path and removes all occurrences
* of "..", "." and double slashes. The returned string must be freed wit free().
*/
diff --git a/include/image-metadata.h b/include/image-metadata.h
new file mode 100644
index 0000000000..34dae5ce34
--- /dev/null
+++ b/include/image-metadata.h
@@ -0,0 +1,117 @@
+#ifndef __INCLUDE_IMAGE_METADTA_H
+#define __INCLUDE_IMAGE_METADTA_H
+
+/*
+ * barebox Image MetaData (IMD)
+ *
+ * IMD is a mechanism to store metadata in barebox images. With IMD
+ * it's possible to extract the release, the build timestamp and the
+ * board type from a barebox image.
+ *
+ * Since there is no fixed place in the image suitable for all SoC image
+ * types the metadata can be stored anywhere in the image and is found
+ * by iterating over the image. The metadata starts with a start header
+ * and ends with an end header. All tags in between carry the payload.
+ *
+ * Make sure source files containing IMD data are compiled with lwl-y so
+ * that the tags end up in the PBL if one exists and in the regular image
+ * without PBL.
+ *
+ * The following types exist:
+ */
+#define IMD_TYPE_START 0x640c0001
+#define IMD_TYPE_RELEASE 0x640c8002 /* The barebox release aka UTS_RELEASE */
+#define IMD_TYPE_BUILD 0x640c8003 /* build number and timestamp (UTS_VERSION) */
+#define IMD_TYPE_MODEL 0x640c8004 /* The board name this image is for */
+#define IMD_TYPE_OF_COMPATIBLE 0x640c8005 /* the device tree compatible string */
+#define IMD_TYPE_PARAMETER 0x640c8006 /* A generic parameter. Use key=value as data */
+#define IMD_TYPE_END 0x640c7fff
+#define IMD_TYPE_INVALID 0xffffffff
+
+/*
+ * The IMD header. All data is stored in little endian format in the image.
+ * The next header starts at the next 4 byte boundary after the data.
+ */
+struct imd_header {
+ uint32_t type; /* One of IMD_TYPE_* above */
+ uint32_t datalength; /* Length of the data (exluding the header) */
+};
+
+/*
+ * A IMD string. Set bit 15 of the IMD_TYPE to indicate the data is printable
+ * as string.
+ */
+struct imd_entry_string {
+ struct imd_header header;
+ char data[];
+};
+
+static inline int imd_is_string(uint32_t type)
+{
+ return (type & 0x8000) ? 1 : 0;
+}
+
+static inline int imd_type_valid(uint32_t type)
+{
+ return (type & 0xffff0000) == 0x640c0000;
+}
+
+struct imd_header *imd_next(struct imd_header *imd);
+
+#define imd_for_each(start, imd) \
+ for (imd = imd_next(start); imd_read_type(imd) != IMD_TYPE_END; imd = imd_next(imd))
+
+static inline uint32_t imd_read_le32(void *_ptr)
+{
+ uint8_t *ptr = _ptr;
+
+ return ptr[0] | (ptr[1] << 8) | (ptr[2] << 16) | (ptr[3] << 24);
+}
+
+static inline uint32_t imd_read_type(struct imd_header *imd)
+{
+ return imd_read_le32(&imd->type);
+}
+
+static inline uint32_t imd_read_length(struct imd_header *imd)
+{
+ return imd_read_le32(&imd->datalength);
+}
+
+struct imd_header *imd_find_type(struct imd_header *imd, uint32_t type);
+
+extern int imd_command_verbose;
+int imd_command_setenv(const char *variable_name, const char *value);
+int imd_command(int argc, char *argv[]);
+
+#ifdef __BAREBOX__
+
+#include <linux/stringify.h>
+
+#define __BAREBOX_IMD_SECTION(_section) \
+ __attribute__ ((unused,section (__stringify(_section)))) \
+ __attribute__((aligned(4)))
+
+#define BAREBOX_IMD_TAG_STRING(_name, _type, _string, _keep_if_unused) \
+ const struct imd_entry_string __barebox_imd_##_name \
+ __BAREBOX_IMD_SECTION(.barebox_imd_ ## _keep_if_unused ## _ ## _name) = { \
+ .header.type = cpu_to_le32(_type), \
+ .header.datalength = cpu_to_le32(sizeof(_string)), \
+ .data = _string, \
+ }
+
+
+#ifdef CONFIG_IMD
+void imd_used(const void *);
+#else
+static inline void imd_used(const void *unused)
+{
+}
+#endif
+
+#define IMD_USED(_name) \
+ imd_used(&__barebox_imd_##_name)
+
+#endif /* __BAREBOX__ */
+
+#endif /* __INCLUDE_IMAGE_METADTA_H */
diff --git a/include/libbb.h b/include/libbb.h
index 2fe710c368..a362bd32d8 100644
--- a/include/libbb.h
+++ b/include/libbb.h
@@ -26,15 +26,8 @@ int recursive_action(const char *fileName, unsigned flags,
char * safe_strncpy(char *dst, const char *src, size_t size);
-int copy_file(const char *src, const char *dst, int verbose);
-
int process_escape_sequence(const char *source, char *dest, int destlen);
char *simple_itoa(unsigned int i);
-int write_full(int fd, void *buf, size_t size);
-int read_full(int fd, void *buf, size_t size);
-
-char *read_file_line(const char *fmt, ...);
-
#endif /* __LIBBB_H */
diff --git a/include/libfile.h b/include/libfile.h
new file mode 100644
index 0000000000..4a25a9153c
--- /dev/null
+++ b/include/libfile.h
@@ -0,0 +1,18 @@
+#ifndef __LIBFILE_H
+#define __LIBFILE_H
+
+int write_full(int fd, void *buf, size_t size);
+int read_full(int fd, void *buf, size_t size);
+
+char *read_file_line(const char *fmt, ...);
+
+void *read_file(const char *filename, size_t *size);
+
+int read_file_2(const char *filename, size_t *size, void **outbuf,
+ loff_t max_size);
+
+int write_file(const char *filename, void *buf, size_t size);
+
+int copy_file(const char *src, const char *dst, int verbose);
+
+#endif /* __LIBFILE_H */
diff --git a/lib/Makefile b/lib/Makefile
index 48c953d679..a75653fb48 100644
--- a/lib/Makefile
+++ b/lib/Makefile
@@ -25,7 +25,6 @@ obj-$(CONFIG_GLOB) += fnmatch.o
obj-$(CONFIG_GENERIC_FIND_NEXT_BIT) += find_next_bit.o
obj-y += glob.o
obj-y += notifier.o
-obj-y += copy_file.o
obj-y += random.o
obj-y += lzo/
obj-$(CONFIG_LZ4_DECOMPRESS) += lz4/
@@ -45,3 +44,4 @@ obj-$(CONFIG_XYMODEM) += xymodem.o
obj-y += unlink-recursive.o
obj-$(CONFIG_STMP_DEVICE) += stmp-device.o
obj-y += wchar.o
+obj-y += libfile.o
diff --git a/lib/bootstrap/disk.c b/lib/bootstrap/disk.c
index 527e430897..1e9fbd834b 100644
--- a/lib/bootstrap/disk.c
+++ b/lib/bootstrap/disk.c
@@ -11,6 +11,7 @@
#include <sizes.h>
#include <errno.h>
#include <malloc.h>
+#include <libfile.h>
#include <bootstrap.h>
void* bootstrap_read_disk(char *dev, char *fstype)
diff --git a/lib/copy_file.c b/lib/copy_file.c
deleted file mode 100644
index fdd0cacb40..0000000000
--- a/lib/copy_file.c
+++ /dev/null
@@ -1,86 +0,0 @@
-#include <common.h>
-#include <fs.h>
-#include <fcntl.h>
-#include <errno.h>
-#include <malloc.h>
-#include <libbb.h>
-#include <progress.h>
-
-/**
- * @param[in] src FIXME
- * @param[out] dst FIXME
- * @param[in] verbose FIXME
- */
-int copy_file(const char *src, const char *dst, int verbose)
-{
- char *rw_buf = NULL;
- int srcfd = 0, dstfd = 0;
- int r, w;
- int ret = 1;
- void *buf;
- int total = 0;
- struct stat statbuf;
-
- rw_buf = xmalloc(RW_BUF_SIZE);
-
- srcfd = open(src, O_RDONLY);
- if (srcfd < 0) {
- printf("could not open %s: %s\n", src, errno_str());
- goto out;
- }
-
- dstfd = open(dst, O_WRONLY | O_CREAT | O_TRUNC);
- if (dstfd < 0) {
- printf("could not open %s: %s\n", dst, errno_str());
- goto out;
- }
-
- if (verbose) {
- if (stat(src, &statbuf) < 0)
- statbuf.st_size = 0;
-
- init_progression_bar(statbuf.st_size);
- }
-
- while(1) {
- r = read(srcfd, rw_buf, RW_BUF_SIZE);
- if (r < 0) {
- perror("read");
- goto out;
- }
- if (!r)
- break;
-
- buf = rw_buf;
- while (r) {
- w = write(dstfd, buf, r);
- if (w < 0) {
- perror("write");
- goto out;
- }
- buf += w;
- r -= w;
- total += w;
- }
-
- if (verbose) {
- if (statbuf.st_size && statbuf.st_size != FILESIZE_MAX)
- show_progress(total);
- else
- show_progress(total / 16384);
- }
- }
-
- ret = 0;
-out:
- if (verbose)
- putchar('\n');
-
- free(rw_buf);
- if (srcfd > 0)
- close(srcfd);
- if (dstfd > 0)
- close(dstfd);
-
- return ret;
-}
diff --git a/lib/gui/image_renderer.c b/lib/gui/image_renderer.c
index 8047961e9e..dd29389baa 100644
--- a/lib/gui/image_renderer.c
+++ b/lib/gui/image_renderer.c
@@ -10,6 +10,7 @@
#include <errno.h>
#include <fs.h>
#include <malloc.h>
+#include <libfile.h>
static LIST_HEAD(image_renderers);
diff --git a/lib/libbb.c b/lib/libbb.c
index dd42e662b4..239611c27b 100644
--- a/lib/libbb.c
+++ b/lib/libbb.c
@@ -126,96 +126,3 @@ char *simple_itoa(unsigned int i)
return p + 1;
}
EXPORT_SYMBOL(simple_itoa);
-
-/*
- * write_full - write to filedescriptor
- *
- * Like write, but guarantees to write the full buffer out, else
- * it returns with an error.
- */
-int write_full(int fd, void *buf, size_t size)
-{
- size_t insize = size;
- int now;
-
- while (size) {
- now = write(fd, buf, size);
- if (now <= 0)
- return now;
- size -= now;
- buf += now;
- }
-
- return insize;
-}
-EXPORT_SYMBOL(write_full);
-
-/*
- * read_full - read from filedescriptor
- *
- * Like read, but this function only returns less bytes than
- * requested when the end of file is reached.
- */
-int read_full(int fd, void *buf, size_t size)
-{
- size_t insize = size;
- int now;
- int total = 0;
-
- while (size) {
- now = read(fd, buf, size);
- if (now == 0)
- return total;
- if (now < 0)
- return now;
- total += now;
- size -= now;
- buf += now;
- }
-
- return insize;
-}
-EXPORT_SYMBOL(read_full);
-
-/*
- * read_file_line - read a line from a file
- *
- * Used to compose a filename from a printf format and to read a line from this
- * file. All leading and trailing whitespaces (including line endings) are
- * removed. The returned buffer must be freed with free(). This function is
- * supposed for reading variable like content into a buffer, so files > 1024
- * bytes are ignored.
- */
-char *read_file_line(const char *fmt, ...)
-{
- va_list args;
- char *filename;
- char *buf, *line = NULL;
- size_t size;
- int ret;
- struct stat s;
-
- va_start(args, fmt);
- filename = vasprintf(fmt, args);
- va_end(args);
-
- ret = stat(filename, &s);
- if (ret)
- goto out;
-
- if (s.st_size > 1024)
- goto out;
-
- buf = read_file(filename, &size);
- if (!buf)
- goto out;
-
- line = strim(buf);
-
- line = xstrdup(line);
- free(buf);
-out:
- free(filename);
- return line;
-}
-EXPORT_SYMBOL_GPL(read_file_line);
diff --git a/lib/libfile.c b/lib/libfile.c
new file mode 100644
index 0000000000..c6fb6d7157
--- /dev/null
+++ b/lib/libfile.c
@@ -0,0 +1,331 @@
+/*
+ * Copyright (c) 2014 Sascha Hauer <s.hauer@pengutronix.de>, Pengutronix
+ *
+ * See file CREDITS for list of people who contributed to this
+ * project.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2
+ * as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ */
+#include <common.h>
+#include <fs.h>
+#include <fcntl.h>
+#include <malloc.h>
+#include <libfile.h>
+#include <progress.h>
+#include <linux/stat.h>
+
+/*
+ * write_full - write to filedescriptor
+ *
+ * Like write, but guarantees to write the full buffer out, else
+ * it returns with an error.
+ */
+int write_full(int fd, void *buf, size_t size)
+{
+ size_t insize = size;
+ int now;
+
+ while (size) {
+ now = write(fd, buf, size);
+ if (now <= 0)
+ return now;
+ size -= now;
+ buf += now;
+ }
+
+ return insize;
+}
+EXPORT_SYMBOL(write_full);
+
+/*
+ * read_full - read from filedescriptor
+ *
+ * Like read, but this function only returns less bytes than
+ * requested when the end of file is reached.
+ */
+int read_full(int fd, void *buf, size_t size)
+{
+ size_t insize = size;
+ int now;
+ int total = 0;
+
+ while (size) {
+ now = read(fd, buf, size);
+ if (now == 0)
+ return total;
+ if (now < 0)
+ return now;
+ total += now;
+ size -= now;
+ buf += now;
+ }
+
+ return insize;
+}
+EXPORT_SYMBOL(read_full);
+
+/*
+ * read_file_line - read a line from a file
+ *
+ * Used to compose a filename from a printf format and to read a line from this
+ * file. All leading and trailing whitespaces (including line endings) are
+ * removed. The returned buffer must be freed with free(). This function is
+ * supposed for reading variable like content into a buffer, so files > 1024
+ * bytes are ignored.
+ */
+char *read_file_line(const char *fmt, ...)
+{
+ va_list args;
+ char *filename;
+ char *buf, *line = NULL;
+ size_t size;
+ int ret;
+ struct stat s;
+
+ va_start(args, fmt);
+ filename = vasprintf(fmt, args);
+ va_end(args);
+
+ ret = stat(filename, &s);
+ if (ret)
+ goto out;
+
+ if (s.st_size > 1024)
+ goto out;
+
+ buf = read_file(filename, &size);
+ if (!buf)
+ goto out;
+
+ line = strim(buf);
+
+ line = xstrdup(line);
+ free(buf);
+out:
+ free(filename);
+ return line;
+}
+EXPORT_SYMBOL_GPL(read_file_line);
+
+/**
+ * read_file_2 - read a file to an allocated buffer
+ * @filename: The filename to read
+ * @size: After successful return contains the size of the file
+ * @outbuf: contains a pointer to the file data after successful return
+ * @max_size: The maximum size to read. Use FILESIZE_MAX for reading files
+ * of any size.
+ *
+ * This function reads a file to an allocated buffer. At maximum @max_size
+ * bytes are read. The actual read size is returned in @size. -EFBIG is
+ * returned if the file is bigger than @max_size, but the buffer is read
+ * anyway up to @max_size in this case. Free the buffer with free() after
+ * usage.
+ *
+ * Return: 0 for success, or negative error code. -EFBIG is returned
+ * when the file has been bigger than max_size.
+ */
+int read_file_2(const char *filename, size_t *size, void **outbuf,
+ loff_t max_size)
+{
+ int fd;
+ struct stat s;
+ void *buf = NULL;
+ const char *tmpfile = "/.read_file_tmp";
+ int ret;
+ loff_t read_size;
+
+again:
+ ret = stat(filename, &s);
+ if (ret)
+ return ret;
+
+ if (max_size == FILESIZE_MAX)
+ read_size = s.st_size;
+ else
+ read_size = max_size;
+
+ if (read_size == FILESIZE_MAX) {
+ ret = copy_file(filename, tmpfile, 0);
+ if (ret)
+ return ret;
+ filename = tmpfile;
+ goto again;
+ }
+
+ buf = xzalloc(read_size + 1);
+
+ fd = open(filename, O_RDONLY);
+ if (fd < 0)
+ goto err_out;
+
+ ret = read_full(fd, buf, read_size);
+ if (ret < 0)
+ goto err_out1;
+
+ close(fd);
+
+ if (size)
+ *size = ret;
+
+ if (filename == tmpfile)
+ unlink(tmpfile);
+
+ *outbuf = buf;
+
+ if (read_size < s.st_size)
+ return -EFBIG;
+ else
+ return 0;
+
+err_out1:
+ close(fd);
+err_out:
+ free(buf);
+
+ if (filename == tmpfile)
+ unlink(tmpfile);
+
+ return ret;
+}
+EXPORT_SYMBOL(read_file_2);
+
+/**
+ * read_file - read a file to an allocated buffer
+ * @filename: The filename to read
+ * @size: After successful return contains the size of the file
+ *
+ * This function reads a file to an allocated buffer.
+ * Some TFTP servers do not transfer the size of a file. In this case
+ * a the file is first read to a temporary file.
+ *
+ * Return: The buffer conataining the file or NULL on failure
+ */
+void *read_file(const char *filename, size_t *size)
+{
+ int ret;
+ void *buf;
+
+ ret = read_file_2(filename, size, &buf, FILESIZE_MAX);
+ if (!ret)
+ return buf;
+
+ return NULL;
+}
+EXPORT_SYMBOL(read_file);
+
+/**
+ * write_file - write a buffer to a file
+ * @filename: The filename to write
+ * @size: The size of the buffer
+ *
+ * Return: 0 for success or negative error value
+ */
+int write_file(const char *filename, void *buf, size_t size)
+{
+ int fd, ret;
+
+ fd = open(filename, O_WRONLY | O_TRUNC | O_CREAT);
+ if (fd < 0)
+ return fd;
+
+ ret = write_full(fd, buf, size);
+
+ close(fd);
+
+ if (ret < 0)
+ return ret;
+
+ return 0;
+}
+EXPORT_SYMBOL(write_file);
+
+/**
+ * copy_file - Copy a file
+ * @src: The source filename
+ * @dst: The destination filename
+ * @verbose: if true, show a progression bar
+ *
+ * Return: 0 for success or negative error code
+ */
+int copy_file(const char *src, const char *dst, int verbose)
+{
+ char *rw_buf = NULL;
+ int srcfd = 0, dstfd = 0;
+ int r, w;
+ int ret = 1;
+ void *buf;
+ int total = 0;
+ struct stat statbuf;
+
+ rw_buf = xmalloc(RW_BUF_SIZE);
+
+ srcfd = open(src, O_RDONLY);
+ if (srcfd < 0) {
+ printf("could not open %s: %s\n", src, errno_str());
+ goto out;
+ }
+
+ dstfd = open(dst, O_WRONLY | O_CREAT | O_TRUNC);
+ if (dstfd < 0) {
+ printf("could not open %s: %s\n", dst, errno_str());
+ goto out;
+ }
+
+ if (verbose) {
+ if (stat(src, &statbuf) < 0)
+ statbuf.st_size = 0;
+
+ init_progression_bar(statbuf.st_size);
+ }
+
+ while (1) {
+ r = read(srcfd, rw_buf, RW_BUF_SIZE);
+ if (r < 0) {
+ perror("read");
+ goto out;
+ }
+ if (!r)
+ break;
+
+ buf = rw_buf;
+ while (r) {
+ w = write(dstfd, buf, r);
+ if (w < 0) {
+ perror("write");
+ goto out;
+ }
+ buf += w;
+ r -= w;
+ total += w;
+ }
+
+ if (verbose) {
+ if (statbuf.st_size && statbuf.st_size != FILESIZE_MAX)
+ show_progress(total);
+ else
+ show_progress(total / 16384);
+ }
+ }
+
+ ret = 0;
+out:
+ if (verbose)
+ putchar('\n');
+
+ free(rw_buf);
+ if (srcfd > 0)
+ close(srcfd);
+ if (dstfd > 0)
+ close(dstfd);
+
+ return ret;
+}
+EXPORT_SYMBOL(copy_file);
diff --git a/scripts/Makefile b/scripts/Makefile
index 9c77680a17..2050ec497d 100644
--- a/scripts/Makefile
+++ b/scripts/Makefile
@@ -10,6 +10,7 @@ hostprogs-y += fix_size
hostprogs-y += bareboxenv
hostprogs-y += bareboxcrc32
hostprogs-y += kernel-install
+hostprogs-$(CONFIG_IMD) += bareboximd
hostprogs-$(CONFIG_KALLSYMS) += kallsyms
hostprogs-$(CONFIG_ARCH_MVEBU) += kwbimage kwboot
hostprogs-$(CONFIG_ARCH_NETX) += gen_netx_image
@@ -29,6 +30,7 @@ subdir-$(CONFIG_ARCH_TEGRA) += tegra
targetprogs-$(CONFIG_BAREBOXENV_TARGET) += bareboxenv-target
targetprogs-$(CONFIG_KERNEL_INSTALL_TARGET) += kernel-install-target
targetprogs-$(CONFIG_BAREBOXCRC32_TARGET) += bareboxcrc32-target
+targetprogs-$(CONFIG_IMD_TARGET) += bareboximd-target
# Let clean descend into subdirs
subdir- += basic kconfig setupmbr
diff --git a/scripts/Makefile.lib b/scripts/Makefile.lib
index 08518704fe..7d97d573ab 100644
--- a/scripts/Makefile.lib
+++ b/scripts/Makefile.lib
@@ -14,6 +14,13 @@ obj-m := $(filter-out $(obj-y),$(obj-m))
lib-y := $(filter-out $(obj-y), $(sort $(lib-y) $(lib-m)))
+pbl-y += $(pbl-dtb-y)
+obj-y += $(obj-dtb-y)
+extra-y += $(patsubst %.dtb.o,%.dtb.S,$(obj-dtb-y))
+extra-y += $(patsubst %.dtb.o,%.dtb,$(obj-dtb-y))
+extra-y += $(patsubst %.dtb.o,%.dtb.S,$(pbl-dtb-y))
+extra-y += $(patsubst %.dtb.o,%.dtb,$(pbl-dtb-y))
+
# Handle objects in subdirs
# ---------------------------------------------------------------------------
# o if we encounter foo/ in $(obj-y), replace it by foo/built-in.o
@@ -203,21 +210,9 @@ cmd_gzip = (cat $(filter-out FORCE,$^) | gzip -n -f -9 > $@) || \
# Generate an assembly file to wrap the output of the device tree compiler
quiet_cmd_dt_S_dtb = DTB $@
-cmd_dt_S_dtb= \
-( \
- echo '\#include <asm-generic/barebox.lds.h>'; \
- echo '.section .dtb.rodata.$(subst -,_,$(*F)),"a"'; \
- echo '.balign STRUCT_ALIGNMENT'; \
- echo '.global __dtb_$(subst -,_,$(*F))_start'; \
- echo '__dtb_$(subst -,_,$(*F))_start:'; \
- echo '.incbin "$<" '; \
- echo '__dtb_$(subst -,_,$(*F))_end:'; \
- echo '.global __dtb_$(subst -,_,$(*F))_end'; \
- echo '.balign STRUCT_ALIGNMENT'; \
-) > $@
-
-$(obj)/%.dtb.S: $(obj)/%.dtb
- $(call cmd,dt_S_dtb)
+cmd_dt_S_dtb = $(srctree)/scripts/gen-dtb-s $(subst -,_,$(*F)) $< $(CONFIG_IMD) > $@
+$(obj)/%.dtb.S: $(obj)/%.dtb $(srctree)/scripts/gen-dtb-s FORCE
+ $(call if_changed,dt_S_dtb)
quiet_cmd_dtc = DTC $@
cmd_dtc = $(CPP) $(dtc_cpp_flags) -x assembler-with-cpp -o $(dtc-tmp) $< ; \
diff --git a/scripts/bareboximd.c b/scripts/bareboximd.c
new file mode 100644
index 0000000000..a3622af821
--- /dev/null
+++ b/scripts/bareboximd.c
@@ -0,0 +1,161 @@
+/*
+ * (C) Copyright 2014 Sascha Hauer, Pengutronix
+ *
+ * See file CREDITS for list of people who contributed to this
+ * project.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of
+ * the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ */
+
+#define __ALIGN_MASK(x, mask) (((x) + (mask)) & ~(mask))
+#define ALIGN(x, a) __ALIGN_MASK(x, (typeof(x))(a) - 1)
+#define ARRAY_SIZE(x) (sizeof(x) / sizeof((x)[0]))
+
+#include <stdio.h>
+#include <sys/types.h>
+#include <stdint.h>
+#include <asm-generic/errno.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <sys/mman.h>
+#include <string.h>
+#include <errno.h>
+#include <stdarg.h>
+
+#include "../include/image-metadata.h"
+
+static void debug(const char *fmt, ...)
+{
+ va_list ap;
+
+ if (!imd_command_verbose)
+ return;
+
+ va_start(ap, fmt);
+ vfprintf(stderr, fmt, ap);
+ va_end(ap);
+}
+
+int imd_command_setenv(const char *variable_name, const char *value)
+{
+ fprintf(stderr, "-s option ignored\n");
+
+ return -EINVAL;
+}
+
+static int read_file_2(const char *filename, size_t *size, void **outbuf, loff_t max_size)
+{
+ off_t fsize;
+ ssize_t rsize;
+ int ret, fd;
+ void *buf;
+
+ *size = 0;
+ *outbuf = NULL;
+
+ fd = open(filename, O_RDONLY);
+ if (fd < 0) {
+ fprintf(stderr, "Cannot open %s: %s\n", filename, strerror(errno));
+ return -errno;
+ }
+
+ fsize = lseek(fd, 0, SEEK_END);
+ if (fsize == -1) {
+ fprintf(stderr, "Cannot get size %s: %s\n", filename, strerror(errno));
+ ret = -errno;
+ goto close;
+ }
+
+ if (fsize < max_size)
+ max_size = fsize;
+
+ if (lseek(fd, 0, SEEK_SET) == -1) {
+ fprintf(stderr, "Cannot seek to start %s: %s\n", filename, strerror(errno));
+ ret = -errno;
+ goto close;
+ }
+
+ buf = malloc(max_size);
+ if (!buf) {
+ fprintf(stderr, "Cannot allocate memory\n");
+ ret = -ENOMEM;
+ goto close;
+ }
+
+ *outbuf = buf;
+ while (*size < max_size) {
+ rsize = read(fd, buf, max_size-*size);
+ if (rsize == 0) {
+ ret = -EIO;
+ goto free;
+ } else if (rsize < 0) {
+ if (errno == EAGAIN)
+ continue;
+ else {
+ ret = -errno;
+ goto free;
+ }
+ } /* ret > 0 */
+ buf += rsize;
+ *size += rsize;
+ }
+
+ ret = 0;
+ goto close;
+free:
+ *outbuf = NULL;
+ free(buf);
+close:
+ close(fd);
+ return ret;
+}
+
+static unsigned long simple_strtoul(const char *cp, char **endp, unsigned int base)
+{
+ return strtoul(cp, endp, base);
+}
+
+#include "../common/imd.c"
+
+static void usage(const char *prgname)
+{
+ printf(
+"Extract metadata from a barebox image\n"
+"\n"
+"Usage: %s [OPTIONS] FILE\n"
+"Options:\n"
+"-t <type> only show information of <type>\n"
+"-n <no> for tags with multiple strings only show string <no>\n"
+"\n"
+"Without options all information available is printed. Valid types are:\n"
+"release, build, model, of_compatible\n",
+ prgname);
+}
+
+int main(int argc, char *argv[])
+{
+ int ret;
+
+ ret = imd_command(argc, argv);
+ if (ret == -ENOSYS) {
+ usage(argv[0]);
+ exit(1);
+ }
+
+ if (ret)
+ fprintf(stderr, "%s\n", strerror(-ret));
+
+ return ret ? 1 : 0;
+}
diff --git a/scripts/dtc/.gitignore b/scripts/dtc/.gitignore
index cdabdc95a6..80f6b50fdf 100644
--- a/scripts/dtc/.gitignore
+++ b/scripts/dtc/.gitignore
@@ -2,3 +2,4 @@ dtc
dtc-lexer.lex.c
dtc-parser.tab.c
dtc-parser.tab.h
+fdtget
diff --git a/scripts/dtc/Makefile b/scripts/dtc/Makefile
index 2a48022c41..05973b12aa 100644
--- a/scripts/dtc/Makefile
+++ b/scripts/dtc/Makefile
@@ -1,15 +1,20 @@
# scripts/dtc makefile
-hostprogs-y := dtc
+hostprogs-y := dtc fdtget
always := $(hostprogs-y)
dtc-objs := dtc.o flattree.o fstree.o data.o livetree.o treesource.o \
srcpos.o checks.o util.o
dtc-objs += dtc-lexer.lex.o dtc-parser.tab.o
+libfdt-objs = fdt.o fdt_ro.o fdt_strerror.o fdt_wip.o
+libfdt-objs += fdt_empty_tree.o fdt_rw.o fdt_sw.o
+
+fdtget-objs += fdtget.o $(libfdt-objs) util.o
+
# Source files need to get at the userspace version of libfdt_env.h to compile
-HOSTCFLAGS_DTC := -I$(src) -I$(src)/libfdt
+HOSTCFLAGS_DTC := -I$(src)
HOSTCFLAGS_checks.o := $(HOSTCFLAGS_DTC)
HOSTCFLAGS_data.o := $(HOSTCFLAGS_DTC)
@@ -21,6 +26,15 @@ HOSTCFLAGS_srcpos.o := $(HOSTCFLAGS_DTC)
HOSTCFLAGS_treesource.o := $(HOSTCFLAGS_DTC)
HOSTCFLAGS_util.o := $(HOSTCFLAGS_DTC)
+HOSTCFLAGS_fdt.o := $(HOSTCFLAGS_DTC)
+HOSTCFLAGS_fdt_ro.o := $(HOSTCFLAGS_DTC)
+HOSTCFLAGS_fdt_strerror.o := $(HOSTCFLAGS_DTC)
+HOSTCFLAGS_fdt_wip.o := $(HOSTCFLAGS_DTC)
+HOSTCFLAGS_fdt_empty_tree.o := $(HOSTCFLAGS_DTC)
+HOSTCFLAGS_fdt_rw.o := $(HOSTCFLAGS_DTC)
+HOSTCFLAGS_fdt_sw.o := $(HOSTCFLAGS_DTC)
+HOSTCFLAGS_fdtget.o := $(HOSTCFLAGS_DTC)
+
HOSTCFLAGS_dtc-lexer.lex.o := $(HOSTCFLAGS_DTC)
HOSTCFLAGS_dtc-parser.tab.o := $(HOSTCFLAGS_DTC)
diff --git a/scripts/dtc/libfdt/fdt.c b/scripts/dtc/fdt.c
index e56833ae9b..e56833ae9b 100644
--- a/scripts/dtc/libfdt/fdt.c
+++ b/scripts/dtc/fdt.c
diff --git a/scripts/dtc/libfdt/fdt.h b/scripts/dtc/fdt.h
index 48ccfd9100..48ccfd9100 100644
--- a/scripts/dtc/libfdt/fdt.h
+++ b/scripts/dtc/fdt.h
diff --git a/scripts/dtc/libfdt/fdt_empty_tree.c b/scripts/dtc/fdt_empty_tree.c
index f72d13b1d1..f72d13b1d1 100644
--- a/scripts/dtc/libfdt/fdt_empty_tree.c
+++ b/scripts/dtc/fdt_empty_tree.c
diff --git a/scripts/dtc/libfdt/fdt_ro.c b/scripts/dtc/fdt_ro.c
index 02b6d68753..02b6d68753 100644
--- a/scripts/dtc/libfdt/fdt_ro.c
+++ b/scripts/dtc/fdt_ro.c
diff --git a/scripts/dtc/libfdt/fdt_rw.c b/scripts/dtc/fdt_rw.c
index 24437dfc32..24437dfc32 100644
--- a/scripts/dtc/libfdt/fdt_rw.c
+++ b/scripts/dtc/fdt_rw.c
diff --git a/scripts/dtc/libfdt/fdt_strerror.c b/scripts/dtc/fdt_strerror.c
index e6c3ceee8c..e6c3ceee8c 100644
--- a/scripts/dtc/libfdt/fdt_strerror.c
+++ b/scripts/dtc/fdt_strerror.c
diff --git a/scripts/dtc/libfdt/fdt_sw.c b/scripts/dtc/fdt_sw.c
index 55ebebf1eb..55ebebf1eb 100644
--- a/scripts/dtc/libfdt/fdt_sw.c
+++ b/scripts/dtc/fdt_sw.c
diff --git a/scripts/dtc/libfdt/fdt_wip.c b/scripts/dtc/fdt_wip.c
index 6025fa1fe8..6025fa1fe8 100644
--- a/scripts/dtc/libfdt/fdt_wip.c
+++ b/scripts/dtc/fdt_wip.c
diff --git a/scripts/dtc/libfdt/libfdt.h b/scripts/dtc/libfdt.h
index 73f49759a5..73f49759a5 100644
--- a/scripts/dtc/libfdt/libfdt.h
+++ b/scripts/dtc/libfdt.h
diff --git a/scripts/dtc/libfdt/libfdt_env.h b/scripts/dtc/libfdt_env.h
index 213d7fb81c..213d7fb81c 100644
--- a/scripts/dtc/libfdt/libfdt_env.h
+++ b/scripts/dtc/libfdt_env.h
diff --git a/scripts/dtc/libfdt/libfdt_internal.h b/scripts/dtc/libfdt_internal.h
index 381133ba81..381133ba81 100644
--- a/scripts/dtc/libfdt/libfdt_internal.h
+++ b/scripts/dtc/libfdt_internal.h
diff --git a/scripts/gen-dtb-s b/scripts/gen-dtb-s
new file mode 100755
index 0000000000..434612f362
--- /dev/null
+++ b/scripts/gen-dtb-s
@@ -0,0 +1,56 @@
+#!/bin/bash
+
+name=$1
+dtb=$2
+imd=$3
+
+echo "#include <asm-generic/barebox.lds.h>"
+
+le32() {
+ printf ".byte 0x%02x, 0x%02x, 0x%02x, 0x%02x\n" \
+ $(($1 & 0xff)) \
+ $((($1 >> 8) & 0xff)) \
+ $((($1 >> 16) & 0xff)) \
+ $((($1 >> 24) & 0xff))
+}
+
+FDTGET=scripts/dtc/fdtget
+
+if [ "$imd" = "y" ]; then
+ echo ".section .barebox_imd_0.${name},\"a\""
+ echo ".global __imd_${name}_start"
+ echo "__imd_${name}_start:"
+
+ compat=$($FDTGET -d notfound -t bi "$dtb" / compatible | sed "s^ ^,^g")
+ if [ "$compat" != "notfound" ]; then
+
+ compatlen=$($FDTGET -t s "$dtb" / compatible | wc -c)
+ le32 0x640c8005
+ le32 $compatlen
+ echo ".byte " $compat
+ echo ".balign 4"
+ fi
+
+ model=$($FDTGET -d notfound -t bi "$dtb" / model | sed "s^ ^,^g")
+
+ if [ "$model" != "notfound" ]; then
+ modellen=$($FDTGET -t s "$dtb" / model | wc -c)
+ le32 0x640c8004
+ le32 $compatlen
+ echo ".byte " $model
+ echo ".balign 4"
+ fi
+fi
+
+echo ".section .dtb.rodata.${name},\"a\""
+echo ".balign STRUCT_ALIGNMENT"
+echo ".global __dtb_${name}_start"
+echo "__dtb_${name}_start:"
+echo ".incbin \"$dtb\""
+echo "__dtb_${name}_end:"
+echo ".global __dtb_${name}_end"
+echo ".balign STRUCT_ALIGNMENT"
+
+if [ "$imd" = "y" ]; then
+ echo ".word __imd_${name}_start"
+fi