[PATCH 0/3] patches to allow DTB to be appended to the ARM zImage
Shawn Guo
shawn.guo at freescale.com
Tue Jun 14 21:25:00 EST 2011
On Tue, Jun 14, 2011 at 03:09:02AM -0400, Nicolas Pitre wrote:
> On Mon, 13 Jun 2011, Nicolas Pitre wrote:
>
> > > Unless I'm missing something, I don't see a clean way of supporting this
> > > that doesn't involve the kernel being able to parse the ATAGS as well.
> >
> > FYI: I've dug up the patch from John Bonesio doing just that. While the
> > patch doesn't apply anymore, it looks trivial enough. I should have it
> > working by tomorrow.
>
> Well, here it is. It compiles, but otherwise completely untested.
>
Just tested the patch on mx51 babbage, and it's working. Great work!
I have one comment below though.
> This applies on top of the 3 other patches I posted when this thread was
> started.
>
> While this could be cleaned up further, the functionality should all be
> there and usable.
>
> From: Nicolas Pitre <nicolas.pitre at linaro.org>
> Date: Tue, 14 Jun 2011 02:40:33 -0400
> Subject: [PATCH] ARM: zImage: allow supplementing appended DTB with traditional ATAG data
>
> This is based on an older patch from John Bonesio <bones at secretlab.ca>.
>
> Signed-off-by: Nicolas Pitre <nicolas.pitre at linaro.org>
>
> diff --git a/arch/arm/Kconfig b/arch/arm/Kconfig
> index 66b7d1e..166bd2a 100644
> --- a/arch/arm/Kconfig
> +++ b/arch/arm/Kconfig
> @@ -1735,6 +1735,17 @@ config ARM_APPENDED_DTB
> (dtb) appended to zImage
> (e.g. cat zImage <filename>.dtb > zImage_w_dtb).
>
> +config ARM_ATAG_DTB_COMPAT
> + bool "Supplement the appended DTB with traditional ATAG information"
> + depends on ARM_APPENDED_DTB
> + help
> + Some old bootloaders can't be updated to a DTB capable one, yet
> + they provide ATAGs with memory configuration, the ramdisk address,
> + the kernel cmdline string, etc. To allow a device tree enabled
> + kernel to be used with such bootloaders, this option allows
> + zImage to extract the information from the ATAG list and store it
> + at run time into the appended DTB.
> +
> config CMDLINE
> string "Default kernel command string"
> default ""
> diff --git a/arch/arm/boot/compressed/.gitignore b/arch/arm/boot/compressed/.gitignore
> index c602896..e0936a1 100644
> --- a/arch/arm/boot/compressed/.gitignore
> +++ b/arch/arm/boot/compressed/.gitignore
> @@ -5,3 +5,12 @@ piggy.lzo
> piggy.lzma
> vmlinux
> vmlinux.lds
> +
> +# borrowed libfdt files
> +fdt.c
> +fdt.h
> +fdt_ro.c
> +fdt_rw.c
> +fdt_wip.c
> +libfdt.h
> +libfdt_internal.h
[Note: I copied these files from scripts/dtc/libfdt]
> diff --git a/arch/arm/boot/compressed/Makefile b/arch/arm/boot/compressed/Makefile
> index 48bead9..4b94995 100644
> --- a/arch/arm/boot/compressed/Makefile
> +++ b/arch/arm/boot/compressed/Makefile
> @@ -83,19 +83,36 @@ suffix_$(CONFIG_KERNEL_GZIP) = gzip
> suffix_$(CONFIG_KERNEL_LZO) = lzo
> suffix_$(CONFIG_KERNEL_LZMA) = lzma
>
> +# libfdt files for the ATAG compatibility mode
> +
> +libfdt := fdt_rw.c fdt_ro.c fdt_wip.c fdt.c
> +libfdt_hdrs := fdt.h libfdt.h libfdt_internal.h
> +
> +libfdt_objs := $(addsuffix .o, $(basename $(libfdt)))
> +
> +$(addprefix $(obj)/,$(libfdt) $(libfdt_hdrs)): $(obj)/%: $(srctree)/scripts/dtc/libfdt/%
> + $(call if_changed,shipped)
> +
> +$(addprefix $(obj)/,$(libfdt_objs) atags_to_fdt.o): \
> + $(addprefix $(obj)/,$(libfdt_hdrs))
> +
> +ifeq ($(CONFIG_ARM_ATAG_DTB_COMPAT),y)
> +OBJS += $(libfdt_objs) atags_to_fdt.o
> +endif
> +
> targets := vmlinux vmlinux.lds \
> piggy.$(suffix_y) piggy.$(suffix_y).o \
> font.o font.c head.o misc.o $(OBJS)
>
> # Make sure files are removed during clean
> -extra-y += piggy.gzip piggy.lzo piggy.lzma lib1funcs.S
> +extra-y += piggy.gzip piggy.lzo piggy.lzma lib1funcs.S $(libfdt) $(libfdt_hdrs)
>
> ifeq ($(CONFIG_FUNCTION_TRACER),y)
> ORIG_CFLAGS := $(KBUILD_CFLAGS)
> KBUILD_CFLAGS = $(subst -pg, , $(ORIG_CFLAGS))
> endif
>
> -ccflags-y := -fpic -fno-builtin
> +ccflags-y := -fpic -fno-builtin -I$(src)
> asflags-y := -Wa,-march=all
>
> # Supply kernel BSS size to the decompressor via a linker symbol.
> @@ -118,7 +135,7 @@ LDFLAGS_vmlinux += -X
> LDFLAGS_vmlinux += -T
>
> # For __aeabi_uidivmod
> -lib1funcs = $(obj)/lib1funcs.o
> +lib1funcs = $(obj)/lib1funcs.o $(obj)/../../lib/lib.a
>
> $(obj)/lib1funcs.S: $(srctree)/arch/$(SRCARCH)/lib/lib1funcs.S FORCE
> $(call cmd,shipped)
> diff --git a/arch/arm/boot/compressed/atags_to_fdt.c b/arch/arm/boot/compressed/atags_to_fdt.c
> new file mode 100644
> index 0000000..11c1a88
> --- /dev/null
> +++ b/arch/arm/boot/compressed/atags_to_fdt.c
> @@ -0,0 +1,71 @@
> +#include <asm/setup.h>
> +#include <libfdt.h>
> +
> +static int setprop(void *fdt, const char *node_path, const char *property,
> + uint32_t *val_array, int size)
> +{
> + int offset = fdt_path_offset(fdt, node_path);
> + if (offset < 0)
> + return offset;
> + return fdt_setprop(fdt, offset, property, val_array, size);
> +}
> +
> +static int setprop_string(void *fdt, const char *node_path,
> + const char *property, const char *string)
> +{
> + int offset = fdt_path_offset(fdt, node_path);
> + if (offset < 0)
> + return offset;
> + return fdt_setprop_string(fdt, offset, property, string);
> +}
> +
> +static int setprop_cell(void *fdt, const char *node_path,
> + const char *property, uint32_t val)
> +{
> + int offset = fdt_path_offset(fdt, node_path);
> + if (offset < 0)
> + return offset;
> + return fdt_setprop_cell(fdt, offset, property, val);
> +}
> +
> +int atags_to_fdt(void *dt, void *atag_list)
> +{
> + struct tag *atag = atag_list;
> +
> + /* make sure we've got an aligned pointer */
> + if ((u32)atag_list & 0x3)
> + return -1;
> +
> + /* if we get a DTB here we're done already */
> + if (*(u32 *)atag_list == fdt32_to_cpu(FDT_MAGIC))
> + return 0;
> +
> + /* validate the ATAG */
> + if (atag->hdr.tag != ATAG_CORE ||
> + (atag->hdr.size != tag_size(tag_core) &&
> + atag->hdr.size != 2))
> + return -1;
> +
> + for_each_tag(atag, atag_list) {
> + if (atag->hdr.tag == ATAG_CMDLINE) {
> + setprop_string(dt, "/chosen", "bootargs",
> + atag->u.cmdline.cmdline);
> + } else if (atag->hdr.tag == ATAG_MEM) {
> + uint32_t mem_reg_property[2];
> + mem_reg_property[0] = cpu_to_fdt32(atag->u.mem.start);
> + mem_reg_property[1] = cpu_to_fdt32(atag->u.mem.size);
> + setprop(dt, "/memory", "reg", mem_reg_property,
> + sizeof(mem_reg_property));
> + } else if (atag->hdr.tag == ATAG_INITRD2) {
> + uint32_t initrd_start, initrd_size;
> + initrd_start = atag->u.initrd.start;
> + initrd_size = atag->u.initrd.size;
> + setprop_cell(dt, "/chosen", "linux,initrd-start",
> + initrd_start);
> + setprop_cell(dt, "/chosen", "linux,initrd-end",
> + initrd_start + initrd_size);
> + }
> + }
> +
> + return 0;
> +}
This works only when there are corresponding nodes already in dtb.
Otherwise, the atag arguments are not going to be updated into dtb.
I suppose these nodes should be created to accommodate the arguments
from atags if the appended dtb does not have them, no?
--
Regards,
Shawn
More information about the devicetree-discuss
mailing list