diff --git a/Documentation/user/imd.rst b/Documentation/user/imd.rst new file mode 100644 index 000000000..e0251d644 --- /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 `` 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 `` 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 2a963b620..6a1a73348 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 0eac0aadc..3d68bbb9a 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 8e729013c..96fb02d80 100644 --- a/arch/arm/boards/at91sam9m10ihd/hw_version.c +++ b/arch/arm/boards/at91sam9m10ihd/hw_version.c @@ -18,6 +18,7 @@ #include #include #include +#include #include #include diff --git a/arch/arm/boards/at91sam9x5ek/hw_version.c b/arch/arm/boards/at91sam9x5ek/hw_version.c index 2da4e5ed8..37eb1f80c 100644 --- a/arch/arm/boards/at91sam9x5ek/hw_version.c +++ b/arch/arm/boards/at91sam9x5ek/hw_version.c @@ -18,6 +18,7 @@ #include #include #include +#include #include #include diff --git a/arch/arm/boards/crystalfontz-cfa10036/hwdetect.c b/arch/arm/boards/crystalfontz-cfa10036/hwdetect.c index e28dd49fa..c94cb355e 100644 --- a/arch/arm/boards/crystalfontz-cfa10036/hwdetect.c +++ b/arch/arm/boards/crystalfontz-cfa10036/hwdetect.c @@ -21,6 +21,7 @@ #include #include #include +#include #include #include diff --git a/arch/arm/boards/freescale-mx53-qsb/lowlevel.c b/arch/arm/boards/freescale-mx53-qsb/lowlevel.c index 51b9ef8db..7d1c1d5b2 100644 --- a/arch/arm/boards/freescale-mx53-qsb/lowlevel.c +++ b/arch/arm/boards/freescale-mx53-qsb/lowlevel.c @@ -2,6 +2,7 @@ #include #include #include +#include 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 55aae0095..1d08f0561 100644 --- a/arch/arm/boards/phytec-phyflex-imx6/lowlevel.c +++ b/arch/arm/boards/phytec-phyflex-imx6/lowlevel.c @@ -16,6 +16,7 @@ #include #include #include +#include #include #include #include @@ -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 450eb9f8a..c809c3774 100644 --- a/arch/arm/boards/sama5d3xek/hw_version.c +++ b/arch/arm/boards/sama5d3xek/hw_version.c @@ -18,6 +18,7 @@ #include #include #include +#include #include #include diff --git a/arch/arm/boards/tqma53/lowlevel.c b/arch/arm/boards/tqma53/lowlevel.c index 0a6722800..cd8721255 100644 --- a/arch/arm/boards/tqma53/lowlevel.c +++ b/arch/arm/boards/tqma53/lowlevel.c @@ -5,6 +5,7 @@ #include #include #include +#include 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 18e451988..fac2b273c 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 +obj-dtb-$(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 +# just to build a built-in.o. Otherwise compilation fails when no devicetree is +# created. +obj-y += empty.o -.SECONDARY: $(obj)/$(BUILTIN_DTB).dtb.S -.SECONDARY: $(patsubst %,$(obj)/%.S,$(dtb-y)) - -targets += dtbs -targets += $(dtb-y) - -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 000000000..d141224cf --- /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 d9588736f..bb0354ae2 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 ffd56edfd..baf0946a4 100644 --- a/arch/arm/lib/bootm.c +++ b/arch/arm/lib/bootm.c @@ -6,6 +6,7 @@ #include #include #include +#include #include #include #include diff --git a/arch/arm/lib/pbl.lds.S b/arch/arm/lib/pbl.lds.S index 76184a0ee..9afee2964 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 66c598b7c..4fd1998ad 100644 --- a/arch/arm/mach-at91/boot_test_cmd.c +++ b/arch/arm/mach-at91/boot_test_cmd.c @@ -7,6 +7,7 @@ #include #include #include +#include #include #include #include diff --git a/arch/arm/mach-omap/omap_generic.c b/arch/arm/mach-omap/omap_generic.c index 060c59277..334cf8db5 100644 --- a/arch/arm/mach-omap/omap_generic.c +++ b/arch/arm/mach-omap/omap_generic.c @@ -20,6 +20,7 @@ #include #include #include +#include #include #include #include diff --git a/arch/arm/mach-omap/xload.c b/arch/arm/mach-omap/xload.c index a30945010..e9d7bbb2e 100644 --- a/arch/arm/mach-omap/xload.c +++ b/arch/arm/mach-omap/xload.c @@ -5,6 +5,7 @@ #include #include #include +#include #include #include #include diff --git a/arch/blackfin/boards/ipe337/cmd_alternate.c b/arch/blackfin/boards/ipe337/cmd_alternate.c index 992d27484..b332cfb05 100644 --- a/arch/blackfin/boards/ipe337/cmd_alternate.c +++ b/arch/blackfin/boards/ipe337/cmd_alternate.c @@ -1,5 +1,6 @@ #include #include +#include #include #include #include diff --git a/arch/mips/configs/qemu-malta_defconfig b/arch/mips/configs/qemu-malta_defconfig index 6ee302df0..5a1ca3682 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 7ccb2f811..6d6c9a3ce 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 4ee4252b6..c690e7197 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 3d6a4ce64..0e03aa9bc 100644 --- a/arch/mips/lib/bootm.c +++ b/arch/mips/lib/bootm.c @@ -1,5 +1,6 @@ #include #include +#include #include #include #include diff --git a/arch/mips/pbl/zbarebox.lds.S b/arch/mips/pbl/zbarebox.lds.S index 3a26942b4..a883fdb2d 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 b03f74a82..71cd1ee99 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 d42aca5c0..44741360e 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 a24dc3ef4..92e0efab6 100644 --- a/commands/barebox-update.c +++ b/commands/barebox-update.c @@ -17,6 +17,7 @@ */ #include #include +#include #include #include #include diff --git a/commands/cp.c b/commands/cp.c index 1a5675405..af7a3d4dc 100644 --- a/commands/cp.c +++ b/commands/cp.c @@ -26,6 +26,7 @@ #include #include #include +#include /** * @param[in] argc Argument count from command line diff --git a/commands/crc.c b/commands/crc.c index 7c2936c23..9b6a3e2a4 100644 --- a/commands/crc.c +++ b/commands/crc.c @@ -22,6 +22,7 @@ #include #include #include +#include #include static int crc_from_file(const char* file, ulong *crc) diff --git a/commands/edit.c b/commands/edit.c index 98af58357..b28e2b92a 100644 --- a/commands/edit.c +++ b/commands/edit.c @@ -21,6 +21,7 @@ #include #include #include +#include #include #include #include diff --git a/commands/exec.c b/commands/exec.c index 635f65eeb..7c8934f13 100644 --- a/commands/exec.c +++ b/commands/exec.c @@ -23,6 +23,7 @@ #include #include #include +#include #include #include diff --git a/commands/imd.c b/commands/imd.c new file mode 100644 index 000000000..f1a22cef9 --- /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 +#include +#include +#include +#include + +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 ", "only show information of ") +BAREBOX_CMD_HELP_OPT ("-n ", "for tags with multiple strings only show string ") +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 176437ee7..735dde022 100644 --- a/commands/insmod.c +++ b/commands/insmod.c @@ -3,6 +3,7 @@ #include #include #include +#include #include static int do_insmod(int argc, char *argv[]) diff --git a/commands/linux16.c b/commands/linux16.c index 594efc7dc..bb678bdb8 100644 --- a/commands/linux16.c +++ b/commands/linux16.c @@ -24,6 +24,7 @@ #include #include #include +#include #include #include #include diff --git a/commands/of_dump.c b/commands/of_dump.c index cafde07b7..315dbbae8 100644 --- a/commands/of_dump.c +++ b/commands/of_dump.c @@ -18,6 +18,7 @@ */ #include +#include #include #include #include diff --git a/commands/oftree.c b/commands/oftree.c index 49976bc02..8a47c0be5 100644 --- a/commands/oftree.c +++ b/commands/oftree.c @@ -26,6 +26,7 @@ #include #include #include +#include #include #include #include diff --git a/commands/readf.c b/commands/readf.c index c8cc574f3..8dd5a2b55 100644 --- a/commands/readf.c +++ b/commands/readf.c @@ -1,6 +1,7 @@ #include #include #include +#include #include #include #include diff --git a/commands/tftp.c b/commands/tftp.c index 62b9424cf..8a3b54138 100644 --- a/commands/tftp.c +++ b/commands/tftp.c @@ -24,6 +24,7 @@ #include #include #include +#include #define TFTP_MOUNT_PATH "/.tftp_tmp_path" diff --git a/commands/ubiformat.c b/commands/ubiformat.c index 443d645a5..df0b801da 100644 --- a/commands/ubiformat.c +++ b/commands/ubiformat.c @@ -40,6 +40,7 @@ #include #include #include +#include #include #include #include diff --git a/commands/uimage.c b/commands/uimage.c index 33523d7e5..7c2dca41e 100644 --- a/commands/uimage.c +++ b/commands/uimage.c @@ -7,6 +7,7 @@ #include #include #include +#include static int uimage_fd; diff --git a/common/Kconfig b/common/Kconfig index 8b361260c..d3f980164 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 4220e1512..ddd7db257 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 9314eeab0..a4adc48da 100644 --- a/common/blspec.c +++ b/common/blspec.c @@ -21,6 +21,7 @@ #include #include #include +#include #include #include #include diff --git a/common/bootm.c b/common/bootm.c index 71390cb84..447c9b624 100644 --- a/common/bootm.c +++ b/common/bootm.c @@ -16,6 +16,7 @@ #include #include #include +#include #include #include diff --git a/common/hush.c b/common/hush.c index 6be43cf8e..09d9326c8 100644 --- a/common/hush.c +++ b/common/hush.c @@ -118,6 +118,7 @@ #include #include #include +#include #include #include #include diff --git a/common/imd-barebox.c b/common/imd-barebox.c new file mode 100644 index 000000000..e9cd37d83 --- /dev/null +++ b/common/imd-barebox.c @@ -0,0 +1,25 @@ +#include +#include +#include +#include + +/* + * 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 000000000..2c837d6f2 --- /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 +#include +#include +#include +#include +#include +#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 814512d7b..97e628de8 100644 --- a/common/menutree.c +++ b/common/menutree.c @@ -15,6 +15,7 @@ #include #include #include +#include #include diff --git a/common/uimage.c b/common/uimage.c index 4ef09682c..a7011a762 100644 --- a/common/uimage.c +++ b/common/uimage.c @@ -22,6 +22,7 @@ #include #include #include +#include #include #include #include diff --git a/drivers/usb/gadget/dfu.c b/drivers/usb/gadget/dfu.c index d0f2155e4..bc5ee9c7d 100644 --- a/drivers/usb/gadget/dfu.c +++ b/drivers/usb/gadget/dfu.c @@ -43,6 +43,7 @@ #include #include #include +#include #include #include #include diff --git a/fs/fs.c b/fs/fs.c index dd410b731..fd3d35358 100644 --- a/fs/fs.c +++ b/fs/fs.c @@ -34,78 +34,6 @@ #include #include -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 6547b7cb7..63931c2d7 100644 --- a/fs/uimagefs.c +++ b/fs/uimagefs.c @@ -17,6 +17,7 @@ #include #include #include +#include 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 5dabda3fb..66abff30f 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 073641c74..b2541a4ee 100644 --- a/include/fs.h +++ b/include/fs.h @@ -163,20 +163,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 000000000..34dae5ce3 --- /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 + +#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 2fe710c36..a362bd32d 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 000000000..4a25a9153 --- /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 48c953d67..a75653fb4 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 527e43089..1e9fbd834 100644 --- a/lib/bootstrap/disk.c +++ b/lib/bootstrap/disk.c @@ -11,6 +11,7 @@ #include #include #include +#include #include 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 fdd0cacb4..000000000 --- a/lib/copy_file.c +++ /dev/null @@ -1,86 +0,0 @@ -#include -#include -#include -#include -#include -#include -#include - -/** - * @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 8047961e9..dd29389ba 100644 --- a/lib/gui/image_renderer.c +++ b/lib/gui/image_renderer.c @@ -10,6 +10,7 @@ #include #include #include +#include static LIST_HEAD(image_renderers); diff --git a/lib/libbb.c b/lib/libbb.c index dd42e662b..239611c27 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 000000000..c6fb6d715 --- /dev/null +++ b/lib/libfile.c @@ -0,0 +1,331 @@ +/* + * Copyright (c) 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 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 +#include +#include +#include +#include +#include +#include + +/* + * 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 9c77680a1..2050ec497 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 08518704f..7d97d573a 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 '; \ - 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 000000000..a3622af82 --- /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 +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#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 only show information of \n" +"-n for tags with multiple strings only show string \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 cdabdc95a..80f6b50fd 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 2a48022c4..05973b12a 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 similarity index 100% rename from scripts/dtc/libfdt/fdt.c rename to scripts/dtc/fdt.c diff --git a/scripts/dtc/libfdt/fdt.h b/scripts/dtc/fdt.h similarity index 100% rename from scripts/dtc/libfdt/fdt.h rename to scripts/dtc/fdt.h diff --git a/scripts/dtc/libfdt/fdt_empty_tree.c b/scripts/dtc/fdt_empty_tree.c similarity index 100% rename from scripts/dtc/libfdt/fdt_empty_tree.c rename to scripts/dtc/fdt_empty_tree.c diff --git a/scripts/dtc/libfdt/fdt_ro.c b/scripts/dtc/fdt_ro.c similarity index 100% rename from scripts/dtc/libfdt/fdt_ro.c rename to scripts/dtc/fdt_ro.c diff --git a/scripts/dtc/libfdt/fdt_rw.c b/scripts/dtc/fdt_rw.c similarity index 100% rename from scripts/dtc/libfdt/fdt_rw.c rename to scripts/dtc/fdt_rw.c diff --git a/scripts/dtc/libfdt/fdt_strerror.c b/scripts/dtc/fdt_strerror.c similarity index 100% rename from scripts/dtc/libfdt/fdt_strerror.c rename to scripts/dtc/fdt_strerror.c diff --git a/scripts/dtc/libfdt/fdt_sw.c b/scripts/dtc/fdt_sw.c similarity index 100% rename from scripts/dtc/libfdt/fdt_sw.c rename to scripts/dtc/fdt_sw.c diff --git a/scripts/dtc/libfdt/fdt_wip.c b/scripts/dtc/fdt_wip.c similarity index 100% rename from scripts/dtc/libfdt/fdt_wip.c rename to scripts/dtc/fdt_wip.c diff --git a/scripts/dtc/libfdt/libfdt.h b/scripts/dtc/libfdt.h similarity index 100% rename from scripts/dtc/libfdt/libfdt.h rename to scripts/dtc/libfdt.h diff --git a/scripts/dtc/libfdt/libfdt_env.h b/scripts/dtc/libfdt_env.h similarity index 100% rename from scripts/dtc/libfdt/libfdt_env.h rename to scripts/dtc/libfdt_env.h diff --git a/scripts/dtc/libfdt/libfdt_internal.h b/scripts/dtc/libfdt_internal.h similarity index 100% rename from scripts/dtc/libfdt/libfdt_internal.h rename to scripts/dtc/libfdt_internal.h diff --git a/scripts/gen-dtb-s b/scripts/gen-dtb-s new file mode 100755 index 000000000..434612f36 --- /dev/null +++ b/scripts/gen-dtb-s @@ -0,0 +1,56 @@ +#!/bin/bash + +name=$1 +dtb=$2 +imd=$3 + +echo "#include " + +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