[PATCH 0/3] patches to allow DTB to be appended to the ARM zImage
From: Shawn Guo <hidden>
Date: 2011-06-14 11:25:00
Also in:
linux-devicetree
On Tue, Jun 14, 2011 at 03:09:02AM -0400, Nicolas Pitre wrote:
On Mon, 13 Jun 2011, Nicolas Pitre wrote:quoted
quoted
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.
quoted hunk
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 <redacted> 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 [off-list ref]. Signed-off-by: Nicolas Pitre <redacted>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]
quoted hunk
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