[PATCH] fdt_support.c: Allow late kernel cmdline modification

By declaring board-specific board_fdt_chosen_bootargs() the kernel command line arguments can be adjusted before injecting to flat dt chosen node.
Signed-off-by: Niko Mauno niko.mauno@vaisala.com --- common/fdt_support.c | 12 +++++++++++- include/fdt_support.h | 10 ++++++++++ 2 files changed, 21 insertions(+), 1 deletion(-)
diff --git a/common/fdt_support.c b/common/fdt_support.c index 08d540bfc8..4379507e30 100644 --- a/common/fdt_support.c +++ b/common/fdt_support.c @@ -269,6 +269,15 @@ int fdt_initrd(void *fdt, ulong initrd_start, ulong initrd_end) return 0; }
+/** + * board_fdt_chosen_bootargs - boards may override this function to use + * alternative kernel command line arguments + */ +__weak char *board_fdt_chosen_bootargs(void) +{ + return env_get("bootargs"); +} + int fdt_chosen(void *fdt) { int nodeoffset; @@ -286,7 +295,8 @@ int fdt_chosen(void *fdt) if (nodeoffset < 0) return nodeoffset;
- str = env_get("bootargs"); + str = board_fdt_chosen_bootargs(); + if (str) { err = fdt_setprop(fdt, nodeoffset, "bootargs", str, strlen(str) + 1); diff --git a/include/fdt_support.h b/include/fdt_support.h index 46eb1dbbb2..e2a4689cd8 100644 --- a/include/fdt_support.h +++ b/include/fdt_support.h @@ -185,6 +185,16 @@ int fdt_find_or_add_subnode(void *fdt, int parentoffset, const char *name); */ int ft_board_setup(void *blob, struct bd_info *bd);
+/** + * board_fdt_chosen_bootargs() - Arbitrarily amend fdt kernel command line + * + * This is used for late modification of kernel command line arguments just + * before they are added into the /chosen node in flat device tree. + * + * @return: pointer to kernel command line arguments in memory + */ +char *board_fdt_chosen_bootargs(void); + /* * The keystone2 SOC requires all 32 bit aliased addresses to be converted * to their 36 physical format. This has to happen after all fdt nodes

On Mon, Feb 22, 2021 at 07:18:51PM +0000, Niko Mauno wrote:
By declaring board-specific board_fdt_chosen_bootargs() the kernel command line arguments can be adjusted before injecting to flat dt chosen node.
Signed-off-by: Niko Mauno niko.mauno@vaisala.com
common/fdt_support.c | 12 +++++++++++- include/fdt_support.h | 10 ++++++++++ 2 files changed, 21 insertions(+), 1 deletion(-)
diff --git a/common/fdt_support.c b/common/fdt_support.c index 08d540bfc8..4379507e30 100644 --- a/common/fdt_support.c +++ b/common/fdt_support.c @@ -269,6 +269,15 @@ int fdt_initrd(void *fdt, ulong initrd_start, ulong initrd_end) return 0; }
+/**
- board_fdt_chosen_bootargs - boards may override this function to use
alternative kernel command line arguments
- */
+__weak char *board_fdt_chosen_bootargs(void) +{
- return env_get("bootargs");
+}
int fdt_chosen(void *fdt) { int nodeoffset; @@ -286,7 +295,8 @@ int fdt_chosen(void *fdt) if (nodeoffset < 0) return nodeoffset;
- str = env_get("bootargs");
- str = board_fdt_chosen_bootargs();
- if (str) { err = fdt_setprop(fdt, nodeoffset, "bootargs", str, strlen(str) + 1);
What's this look like in practice? I'm very wary about changing "set bootargs to what you pass to the kernel" logic that's been there for forever and a constant of every platform. Thanks!

On 2/22/21 10:21 PM, Tom Rini wrote:
On Mon, Feb 22, 2021 at 07:18:51PM +0000, Niko Mauno wrote:
By declaring board-specific board_fdt_chosen_bootargs() the kernel command line arguments can be adjusted before injecting to flat dt chosen node.
Signed-off-by: Niko Mauno niko.mauno@vaisala.com
common/fdt_support.c | 12 +++++++++++- include/fdt_support.h | 10 ++++++++++ 2 files changed, 21 insertions(+), 1 deletion(-)
diff --git a/common/fdt_support.c b/common/fdt_support.c index 08d540bfc8..4379507e30 100644 --- a/common/fdt_support.c +++ b/common/fdt_support.c @@ -269,6 +269,15 @@ int fdt_initrd(void *fdt, ulong initrd_start, ulong initrd_end) return 0; }
+/**
- board_fdt_chosen_bootargs - boards may override this function to use
alternative kernel command line arguments
- */
+__weak char *board_fdt_chosen_bootargs(void) +{
- return env_get("bootargs");
+}
- int fdt_chosen(void *fdt) { int nodeoffset;
@@ -286,7 +295,8 @@ int fdt_chosen(void *fdt) if (nodeoffset < 0) return nodeoffset;
- str = env_get("bootargs");
- str = board_fdt_chosen_bootargs();
- if (str) { err = fdt_setprop(fdt, nodeoffset, "bootargs", str, strlen(str) + 1);
What's this look like in practice? I'm very wary about changing "set bootargs to what you pass to the kernel" logic that's been there for forever and a constant of every platform. Thanks!
Hi Tom,
Effectively this change as such should introduce no changes to prevalent "bootargs" logic when an overriding board_fdt_chosen_bootargs() is not defined. Our motivation for proposing this change is that it provides us with a means to introduce an entry point where we can append rootfs specific dm-verity kernel command line metrics (such as described in https://www.kernel.org/doc/html/latest/admin-guide/device-mapper/verity.html) by reading a property from within a kernel tier FIT image header, in order to facilitate secure boot process all the way to root filesystem.
-Niko

On Tue, Feb 23, 2021 at 08:33:36AM +0200, Niko Mauno wrote:
On 2/22/21 10:21 PM, Tom Rini wrote:
On Mon, Feb 22, 2021 at 07:18:51PM +0000, Niko Mauno wrote:
By declaring board-specific board_fdt_chosen_bootargs() the kernel command line arguments can be adjusted before injecting to flat dt chosen node.
Signed-off-by: Niko Mauno niko.mauno@vaisala.com
common/fdt_support.c | 12 +++++++++++- include/fdt_support.h | 10 ++++++++++ 2 files changed, 21 insertions(+), 1 deletion(-)
diff --git a/common/fdt_support.c b/common/fdt_support.c index 08d540bfc8..4379507e30 100644 --- a/common/fdt_support.c +++ b/common/fdt_support.c @@ -269,6 +269,15 @@ int fdt_initrd(void *fdt, ulong initrd_start, ulong initrd_end) return 0; } +/**
- board_fdt_chosen_bootargs - boards may override this function to use
alternative kernel command line arguments
- */
+__weak char *board_fdt_chosen_bootargs(void) +{
- return env_get("bootargs");
+}
- int fdt_chosen(void *fdt) { int nodeoffset;
@@ -286,7 +295,8 @@ int fdt_chosen(void *fdt) if (nodeoffset < 0) return nodeoffset;
- str = env_get("bootargs");
- str = board_fdt_chosen_bootargs();
- if (str) { err = fdt_setprop(fdt, nodeoffset, "bootargs", str, strlen(str) + 1);
What's this look like in practice? I'm very wary about changing "set bootargs to what you pass to the kernel" logic that's been there for forever and a constant of every platform. Thanks!
Hi Tom,
Effectively this change as such should introduce no changes to prevalent "bootargs" logic when an overriding board_fdt_chosen_bootargs() is not defined. Our motivation for proposing this change is that it provides us with a means to introduce an entry point where we can append rootfs specific dm-verity kernel command line metrics (such as described in https://www.kernel.org/doc/html/latest/admin-guide/device-mapper/verity.html) by reading a property from within a kernel tier FIT image header, in order to facilitate secure boot process all the way to root filesystem.
Right. But what does that logic look like, and why must it be done in C? People have used dm-verity with U-Boot for ages, for example.

On 2/24/21 3:51 PM, Tom Rini wrote:
On Tue, Feb 23, 2021 at 08:33:36AM +0200, Niko Mauno wrote:
On 2/22/21 10:21 PM, Tom Rini wrote:
On Mon, Feb 22, 2021 at 07:18:51PM +0000, Niko Mauno wrote:
By declaring board-specific board_fdt_chosen_bootargs() the kernel command line arguments can be adjusted before injecting to flat dt chosen node.
Signed-off-by: Niko Mauno niko.mauno@vaisala.com
common/fdt_support.c | 12 +++++++++++- include/fdt_support.h | 10 ++++++++++ 2 files changed, 21 insertions(+), 1 deletion(-)
diff --git a/common/fdt_support.c b/common/fdt_support.c index 08d540bfc8..4379507e30 100644 --- a/common/fdt_support.c +++ b/common/fdt_support.c @@ -269,6 +269,15 @@ int fdt_initrd(void *fdt, ulong initrd_start, ulong initrd_end) return 0; } +/**
- board_fdt_chosen_bootargs - boards may override this function to use
alternative kernel command line arguments
- */
+__weak char *board_fdt_chosen_bootargs(void) +{
- return env_get("bootargs");
+}
- int fdt_chosen(void *fdt) { int nodeoffset;
@@ -286,7 +295,8 @@ int fdt_chosen(void *fdt) if (nodeoffset < 0) return nodeoffset;
- str = env_get("bootargs");
- str = board_fdt_chosen_bootargs();
- if (str) { err = fdt_setprop(fdt, nodeoffset, "bootargs", str, strlen(str) + 1);
What's this look like in practice? I'm very wary about changing "set bootargs to what you pass to the kernel" logic that's been there for forever and a constant of every platform. Thanks!
Hi Tom,
Effectively this change as such should introduce no changes to prevalent
"bootargs" logic when an overriding board_fdt_chosen_bootargs() is not defined. Our motivation for proposing this change is that it provides us with a means to introduce an entry point where we can append rootfs specific dm-verity kernel command line metrics (such as described in https://www.kernel.org/doc/html/latest/admin-guide/device-mapper/verity.html) by reading a property from within a kernel tier FIT image header, in order to facilitate secure boot process all the way to root filesystem.
Right. But what does that logic look like, and why must it be done in C? People have used dm-verity with U-Boot for ages, for example.
Our build time implementation injects rootfs specific dm-verity metrics in FIT conf node property, effectively coupling the particular (kernel tier) FIT image and particular rootfs image containing trailing verity hash tree.
Below is a sample of such conf node - please note also that the two '${rootdev}' placeholder strings in the injected property are replaced with device node path to 'active' rootfs (in a dual bank scheme where the 'active' rootfs bank is resolved runtime).
configurations { default = "conf-c"; conf-c { description = "Linux kernel and FDT blob"; kernel = "kernel"; fdt = "fdt-c"; vaisala,dm-verity-args = "dm-mod.create="dm-verity, ec077aa7-78e5-43b7-9605-0d7f72fc65b9, , ro, 0 136220 verity 1 ${rootdev} ${rootdev} 1024 4096 68110 17028 sha256 2dcd25db0f5b94603843316e5a16ca7717585802bf9a3fbced1443d7f83ec5f6 fec6bf67513d044bc704c63e37508b223d75867842ac828ba0147c6080578698 1 restart_on_corruption" root=/dev/dm-0 ro"; signature { ... }; };
In the boot flow the FIT needs to be signature verified and is processed only after boot command has been issued. Resorting to u-boot scripting means it would require parsing FIT twice and do all verifications twice. Using C avoids this redundancy.
The command line approach is supported since Linux kernel version 5.1 onwards (CONFIG_DM_INIT), and it avoids us the need to bundle a "trampoline" initramfs with Linux kernel for issuing veritysetup and mount commands. The bundling approach struck as more time consuming and also more cumbersome on Yocto to build for various different image types in same build, and introduces additional booting overhead on target.
Related to existing dm-verity support in U-Boot, I observed there is Android Verified Boot 2.0 code which seemed to resort to appending the kernel command line, which lead us to propose this change which would allow us to perform the picking of the property from the FIT image, processing it and appending it to our default "bootargs" in a board specific function.
-Niko

On 2/25/21 6:09 PM, Niko Mauno wrote:
On 2/24/21 3:51 PM, Tom Rini wrote:
On Tue, Feb 23, 2021 at 08:33:36AM +0200, Niko Mauno wrote:
On 2/22/21 10:21 PM, Tom Rini wrote:
On Mon, Feb 22, 2021 at 07:18:51PM +0000, Niko Mauno wrote:
By declaring board-specific board_fdt_chosen_bootargs() the kernel command line arguments can be adjusted before injecting to flat dt chosen node.
Signed-off-by: Niko Mauno niko.mauno@vaisala.com
common/fdt_support.c | 12 +++++++++++- include/fdt_support.h | 10 ++++++++++ 2 files changed, 21 insertions(+), 1 deletion(-)
diff --git a/common/fdt_support.c b/common/fdt_support.c index 08d540bfc8..4379507e30 100644 --- a/common/fdt_support.c +++ b/common/fdt_support.c @@ -269,6 +269,15 @@ int fdt_initrd(void *fdt, ulong initrd_start, ulong initrd_end) return 0; } +/**
- board_fdt_chosen_bootargs - boards may override this function
to use
- * alternative kernel command line
arguments
- */
+__weak char *board_fdt_chosen_bootargs(void) +{ + return env_get("bootargs"); +}
int fdt_chosen(void *fdt) { int nodeoffset; @@ -286,7 +295,8 @@ int fdt_chosen(void *fdt) if (nodeoffset < 0) return nodeoffset; - str = env_get("bootargs"); + str = board_fdt_chosen_bootargs();
if (str) { err = fdt_setprop(fdt, nodeoffset, "bootargs", str, strlen(str) + 1);
What's this look like in practice? I'm very wary about changing "set bootargs to what you pass to the kernel" logic that's been there for forever and a constant of every platform. Thanks!
Hi Tom,
Effectively this change as such should introduce no changes to prevalent "bootargs" logic when an overriding board_fdt_chosen_bootargs() is not defined. Our motivation for proposing this change is that it provides us with a means to introduce an entry point where we can append rootfs specific dm-verity kernel command line metrics (such as described in https://www.kernel.org/doc/html/latest/admin-guide/device-mapper/verity.html)
by reading a property from within a kernel tier FIT image header, in order to facilitate secure boot process all the way to root filesystem.
Right. But what does that logic look like, and why must it be done in C? People have used dm-verity with U-Boot for ages, for example.
Our build time implementation injects rootfs specific dm-verity metrics in FIT conf node property, effectively coupling the particular (kernel tier) FIT image and particular rootfs image containing trailing verity hash tree.
Below is a sample of such conf node - please note also that the two '${rootdev}' placeholder strings in the injected property are replaced with device node path to 'active' rootfs (in a dual bank scheme where the 'active' rootfs bank is resolved runtime).
configurations { default = "conf-c"; conf-c { description = "Linux kernel and FDT blob"; kernel = "kernel"; fdt = "fdt-c"; vaisala,dm-verity-args = "dm-mod.create="dm-verity, ec077aa7-78e5-43b7-9605-0d7f72fc65b9, , ro, 0 136220 verity 1 ${rootdev} ${rootdev} 1024 4096 68110 17028 sha256 2dcd25db0f5b94603843316e5a16ca7717585802bf9a3fbced1443d7f83ec5f6 fec6bf67513d044bc704c63e37508b223d75867842ac828ba0147c6080578698 1 restart_on_corruption" root=/dev/dm-0 ro"; signature { ... }; };
In the boot flow the FIT needs to be signature verified and is processed only after boot command has been issued. Resorting to u-boot scripting means it would require parsing FIT twice and do all verifications twice. Using C avoids this redundancy.
The command line approach is supported since Linux kernel version 5.1 onwards (CONFIG_DM_INIT), and it avoids us the need to bundle a "trampoline" initramfs with Linux kernel for issuing veritysetup and mount commands. The bundling approach struck as more time consuming and also more cumbersome on Yocto to build for various different image types in same build, and introduces additional booting overhead on target.
Related to existing dm-verity support in U-Boot, I observed there is Android Verified Boot 2.0 code which seemed to resort to appending the kernel command line, which lead us to propose this change which would allow us to perform the picking of the property from the FIT image, processing it and appending it to our default "bootargs" in a board specific function.
-Niko
Since discussion seems discontinued, adding Mr. Simon Glass to recipients as custodian of common/fdt_support.c as reported by scripts/get_maintainer.pl

Hi Niko,
On Thu, 11 Mar 2021 at 20:34, Niko Mauno niko.mauno@vaisala.com wrote:
On 2/25/21 6:09 PM, Niko Mauno wrote:
On 2/24/21 3:51 PM, Tom Rini wrote:
On Tue, Feb 23, 2021 at 08:33:36AM +0200, Niko Mauno wrote:
On 2/22/21 10:21 PM, Tom Rini wrote:
On Mon, Feb 22, 2021 at 07:18:51PM +0000, Niko Mauno wrote:
By declaring board-specific board_fdt_chosen_bootargs() the kernel command line arguments can be adjusted before injecting to flat dt chosen node.
Signed-off-by: Niko Mauno niko.mauno@vaisala.com
common/fdt_support.c | 12 +++++++++++- include/fdt_support.h | 10 ++++++++++ 2 files changed, 21 insertions(+), 1 deletion(-)
diff --git a/common/fdt_support.c b/common/fdt_support.c index 08d540bfc8..4379507e30 100644 --- a/common/fdt_support.c +++ b/common/fdt_support.c @@ -269,6 +269,15 @@ int fdt_initrd(void *fdt, ulong initrd_start, ulong initrd_end) return 0; } +/**
- board_fdt_chosen_bootargs - boards may override this function
to use
alternative kernel command line
arguments
- */
+__weak char *board_fdt_chosen_bootargs(void) +{
- return env_get("bootargs");
+}
- int fdt_chosen(void *fdt) { int nodeoffset;
@@ -286,7 +295,8 @@ int fdt_chosen(void *fdt) if (nodeoffset < 0) return nodeoffset;
- str = env_get("bootargs");
- str = board_fdt_chosen_bootargs();
if (str) { err = fdt_setprop(fdt, nodeoffset, "bootargs", str, strlen(str) + 1);
What's this look like in practice? I'm very wary about changing "set bootargs to what you pass to the kernel" logic that's been there for forever and a constant of every platform. Thanks!
Hi Tom,
Effectively this change as such should introduce no changes to
prevalent "bootargs" logic when an overriding board_fdt_chosen_bootargs() is not defined. Our motivation for proposing this change is that it provides us with a means to introduce an entry point where we can append rootfs specific dm-verity kernel command line metrics (such as described in https://www.kernel.org/doc/html/latest/admin-guide/device-mapper/verity.html)
by reading a property from within a kernel tier FIT image header, in order to facilitate secure boot process all the way to root filesystem.
Right. But what does that logic look like, and why must it be done in C? People have used dm-verity with U-Boot for ages, for example.
Our build time implementation injects rootfs specific dm-verity metrics in FIT conf node property, effectively coupling the particular (kernel tier) FIT image and particular rootfs image containing trailing verity hash tree.
Below is a sample of such conf node - please note also that the two '${rootdev}' placeholder strings in the injected property are replaced with device node path to 'active' rootfs (in a dual bank scheme where the 'active' rootfs bank is resolved runtime).
configurations { default = "conf-c"; conf-c { description = "Linux kernel and FDT blob"; kernel = "kernel"; fdt = "fdt-c"; vaisala,dm-verity-args = "dm-mod.create="dm-verity,
ec077aa7-78e5-43b7-9605-0d7f72fc65b9, , ro, 0 136220 verity 1 ${rootdev} ${rootdev} 1024 4096 68110 17028 sha256 2dcd25db0f5b94603843316e5a16ca7717585802bf9a3fbced1443d7f83ec5f6 fec6bf67513d044bc704c63e37508b223d75867842ac828ba0147c6080578698 1 restart_on_corruption" root=/dev/dm-0 ro"; signature { ... }; };
In the boot flow the FIT needs to be signature verified and is processed only after boot command has been issued. Resorting to u-boot scripting means it would require parsing FIT twice and do all verifications twice. Using C avoids this redundancy.
The command line approach is supported since Linux kernel version 5.1 onwards (CONFIG_DM_INIT), and it avoids us the need to bundle a "trampoline" initramfs with Linux kernel for issuing veritysetup and mount commands. The bundling approach struck as more time consuming and also more cumbersome on Yocto to build for various different image types in same build, and introduces additional booting overhead on target.
Related to existing dm-verity support in U-Boot, I observed there is Android Verified Boot 2.0 code which seemed to resort to appending the kernel command line, which lead us to propose this change which would allow us to perform the picking of the property from the FIT image, processing it and appending it to our default "bootargs" in a board specific function.
-Niko
Since discussion seems discontinued, adding Mr. Simon Glass to recipients as custodian of common/fdt_support.c as reported by scripts/get_maintainer.pl
This is used on coral which enables CONFIG_BOOTARGS_SUBST so you might find that does what you want. Once you have the args in an env var then bootm should do it for you.
Regards, Simon

On Mon, Feb 22, 2021 at 07:18:51PM +0000, Niko Mauno wrote:
By declaring board-specific board_fdt_chosen_bootargs() the kernel command line arguments can be adjusted before injecting to flat dt chosen node.
Signed-off-by: Niko Mauno niko.mauno@vaisala.com
Applied to u-boot/master, thanks!
participants (3)
-
Niko Mauno
-
Simon Glass
-
Tom Rini