From d0f34a11ddab9b456e4caf9fc48d8d7e832e0e50 Mon Sep 17 00:00:00 2001 From: Genoud Richard Date: Tue, 26 Jun 2012 16:37:59 +0100 Subject: ARM: 7437/1: zImage: Allow DTB command line concatenation with ATAG_CMDLINE This patch allows the ATAG_CMDLINE provided by the bootloader to be concatenated to the bootargs property of the device tree. This is useful to merge static values defined in the device tree with the boot loader's (possibly) more dynamic values, such as startup reasons and more. The bootloader should use the device tree to pass those values to the kernel, but that's not always simple (old bootloader or very small one). The behaviour is the same as the one introduced by Victor Boivie in 4394c1244249198c6b85093d46935b761b36ae05 by extending the CONFIG_CMDLINE. Signed-off-by: Richard Genoud Tested-by: Gregory CLEMENT Acked-by: Nicolas Pitre Signed-off-by: Russell King --- arch/arm/boot/compressed/atags_to_fdt.c | 62 +++++++++++++++++++++++++++++++-- 1 file changed, 60 insertions(+), 2 deletions(-) (limited to 'arch/arm/boot/compressed') diff --git a/arch/arm/boot/compressed/atags_to_fdt.c b/arch/arm/boot/compressed/atags_to_fdt.c index 797f04bedb47..aabc02a68482 100644 --- a/arch/arm/boot/compressed/atags_to_fdt.c +++ b/arch/arm/boot/compressed/atags_to_fdt.c @@ -1,6 +1,12 @@ #include #include +#if defined(CONFIG_ARM_ATAG_DTB_COMPAT_CMDLINE_EXTEND) +#define do_extend_cmdline 1 +#else +#define do_extend_cmdline 0 +#endif + static int node_offset(void *fdt, const char *node_path) { int offset = fdt_path_offset(fdt, node_path); @@ -36,6 +42,48 @@ static int setprop_cell(void *fdt, const char *node_path, return fdt_setprop_cell(fdt, offset, property, val); } +static const void *getprop(const void *fdt, const char *node_path, + const char *property, int *len) +{ + int offset = fdt_path_offset(fdt, node_path); + + if (offset == -FDT_ERR_NOTFOUND) + return NULL; + + return fdt_getprop(fdt, offset, property, len); +} + +static void merge_fdt_bootargs(void *fdt, const char *fdt_cmdline) +{ + char cmdline[COMMAND_LINE_SIZE]; + const char *fdt_bootargs; + char *ptr = cmdline; + int len = 0; + + /* copy the fdt command line into the buffer */ + fdt_bootargs = getprop(fdt, "/chosen", "bootargs", &len); + if (fdt_bootargs) + if (len < COMMAND_LINE_SIZE) { + memcpy(ptr, fdt_bootargs, len); + /* len is the length of the string + * including the NULL terminator */ + ptr += len - 1; + } + + /* and append the ATAG_CMDLINE */ + if (fdt_cmdline) { + len = strlen(fdt_cmdline); + if (ptr - cmdline + len + 2 < COMMAND_LINE_SIZE) { + *ptr++ = ' '; + memcpy(ptr, fdt_cmdline, len); + ptr += len; + } + } + *ptr = '\0'; + + setprop_string(fdt, "/chosen", "bootargs", cmdline); +} + /* * Convert and fold provided ATAGs into the provided FDT. * @@ -72,8 +120,18 @@ int atags_to_fdt(void *atag_list, void *fdt, int total_space) for_each_tag(atag, atag_list) { if (atag->hdr.tag == ATAG_CMDLINE) { - setprop_string(fdt, "/chosen", "bootargs", - atag->u.cmdline.cmdline); + /* Append the ATAGS command line to the device tree + * command line. + * NB: This means that if the same parameter is set in + * the device tree and in the tags, the one from the + * tags will be chosen. + */ + if (do_extend_cmdline) + merge_fdt_bootargs(fdt, + atag->u.cmdline.cmdline); + else + setprop_string(fdt, "/chosen", "bootargs", + atag->u.cmdline.cmdline); } else if (atag->hdr.tag == ATAG_MEM) { if (memcount >= sizeof(mem_reg_property)/4) continue; -- cgit v1.2.1