aboutsummaryrefslogtreecommitdiffstats
path: root/arch
diff options
context:
space:
mode:
authorGenoud Richard <richard.genoud@gmail.com>2012-06-26 11:37:59 -0400
committerRussell King <rmk+kernel@arm.linux.org.uk>2012-07-09 12:39:39 -0400
commitd0f34a11ddab9b456e4caf9fc48d8d7e832e0e50 (patch)
tree00c0dfd265bb37ced1c3f12626f17ec4b9df131a /arch
parent9ad86ddde0345e903eb74837e52cf19fe0c7f825 (diff)
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 <richard.genoud@gmail.com> Tested-by: Gregory CLEMENT <gregory.clement@free-electrons.com> Acked-by: Nicolas Pitre <nico@linaro.org> Signed-off-by: Russell King <rmk+kernel@arm.linux.org.uk>
Diffstat (limited to 'arch')
-rw-r--r--arch/arm/Kconfig19
-rw-r--r--arch/arm/boot/compressed/atags_to_fdt.c62
2 files changed, 79 insertions, 2 deletions
diff --git a/arch/arm/Kconfig b/arch/arm/Kconfig
index b649c5904a4f..8c9d264f2108 100644
--- a/arch/arm/Kconfig
+++ b/arch/arm/Kconfig
@@ -1960,6 +1960,25 @@ config ARM_ATAG_DTB_COMPAT
1960 bootloaders, this option allows zImage to extract the information 1960 bootloaders, this option allows zImage to extract the information
1961 from the ATAG list and store it at run time into the appended DTB. 1961 from the ATAG list and store it at run time into the appended DTB.
1962 1962
1963choice
1964 prompt "Kernel command line type" if ARM_ATAG_DTB_COMPAT
1965 default ARM_ATAG_DTB_COMPAT_CMDLINE_FROM_BOOTLOADER
1966
1967config ARM_ATAG_DTB_COMPAT_CMDLINE_FROM_BOOTLOADER
1968 bool "Use bootloader kernel arguments if available"
1969 help
1970 Uses the command-line options passed by the boot loader instead of
1971 the device tree bootargs property. If the boot loader doesn't provide
1972 any, the device tree bootargs property will be used.
1973
1974config ARM_ATAG_DTB_COMPAT_CMDLINE_EXTEND
1975 bool "Extend with bootloader kernel arguments"
1976 help
1977 The command-line arguments provided by the boot loader will be
1978 appended to the the device tree bootargs property.
1979
1980endchoice
1981
1963config CMDLINE 1982config CMDLINE
1964 string "Default kernel command string" 1983 string "Default kernel command string"
1965 default "" 1984 default ""
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 @@
1#include <asm/setup.h> 1#include <asm/setup.h>
2#include <libfdt.h> 2#include <libfdt.h>
3 3
4#if defined(CONFIG_ARM_ATAG_DTB_COMPAT_CMDLINE_EXTEND)
5#define do_extend_cmdline 1
6#else
7#define do_extend_cmdline 0
8#endif
9
4static int node_offset(void *fdt, const char *node_path) 10static int node_offset(void *fdt, const char *node_path)
5{ 11{
6 int offset = fdt_path_offset(fdt, node_path); 12 int offset = fdt_path_offset(fdt, node_path);
@@ -36,6 +42,48 @@ static int setprop_cell(void *fdt, const char *node_path,
36 return fdt_setprop_cell(fdt, offset, property, val); 42 return fdt_setprop_cell(fdt, offset, property, val);
37} 43}
38 44
45static const void *getprop(const void *fdt, const char *node_path,
46 const char *property, int *len)
47{
48 int offset = fdt_path_offset(fdt, node_path);
49
50 if (offset == -FDT_ERR_NOTFOUND)
51 return NULL;
52
53 return fdt_getprop(fdt, offset, property, len);
54}
55
56static void merge_fdt_bootargs(void *fdt, const char *fdt_cmdline)
57{
58 char cmdline[COMMAND_LINE_SIZE];
59 const char *fdt_bootargs;
60 char *ptr = cmdline;
61 int len = 0;
62
63 /* copy the fdt command line into the buffer */
64 fdt_bootargs = getprop(fdt, "/chosen", "bootargs", &len);
65 if (fdt_bootargs)
66 if (len < COMMAND_LINE_SIZE) {
67 memcpy(ptr, fdt_bootargs, len);
68 /* len is the length of the string
69 * including the NULL terminator */
70 ptr += len - 1;
71 }
72
73 /* and append the ATAG_CMDLINE */
74 if (fdt_cmdline) {
75 len = strlen(fdt_cmdline);
76 if (ptr - cmdline + len + 2 < COMMAND_LINE_SIZE) {
77 *ptr++ = ' ';
78 memcpy(ptr, fdt_cmdline, len);
79 ptr += len;
80 }
81 }
82 *ptr = '\0';
83
84 setprop_string(fdt, "/chosen", "bootargs", cmdline);
85}
86
39/* 87/*
40 * Convert and fold provided ATAGs into the provided FDT. 88 * Convert and fold provided ATAGs into the provided FDT.
41 * 89 *
@@ -72,8 +120,18 @@ int atags_to_fdt(void *atag_list, void *fdt, int total_space)
72 120
73 for_each_tag(atag, atag_list) { 121 for_each_tag(atag, atag_list) {
74 if (atag->hdr.tag == ATAG_CMDLINE) { 122 if (atag->hdr.tag == ATAG_CMDLINE) {
75 setprop_string(fdt, "/chosen", "bootargs", 123 /* Append the ATAGS command line to the device tree
76 atag->u.cmdline.cmdline); 124 * command line.
125 * NB: This means that if the same parameter is set in
126 * the device tree and in the tags, the one from the
127 * tags will be chosen.
128 */
129 if (do_extend_cmdline)
130 merge_fdt_bootargs(fdt,
131 atag->u.cmdline.cmdline);
132 else
133 setprop_string(fdt, "/chosen", "bootargs",
134 atag->u.cmdline.cmdline);
77 } else if (atag->hdr.tag == ATAG_MEM) { 135 } else if (atag->hdr.tag == ATAG_MEM) {
78 if (memcount >= sizeof(mem_reg_property)/4) 136 if (memcount >= sizeof(mem_reg_property)/4)
79 continue; 137 continue;