diff mbox

[U-Boot,v2] common: fit: Allow U-Boot images to be booted

Message ID 20160720063250.19532-1-mario.six@gdsys.cc
State Accepted
Delegated to: Tom Rini
Headers show

Commit Message

Mario Six July 20, 2016, 6:32 a.m. UTC
In certain circumstances it comes in handy to be able to boot into a second
U-Boot. But as of now it is not possible to boot a U-Boot binary that is inside
a FIT image, which is problematic for projects that e.g. need to guarantee a
unbroken chain of trust from SOC all the way into the OS, since the FIT signing
mechanism cannot be used.

This patch adds the capability to load such FIT images.

An example .its snippet (utilizing signature verification) might look
like the following:

images {
	firmware@1 {
		description = "2nd stage U-Boot image";
		data = /incbin/("u-boot-dtb.img.gz");
		type = "firmware";
		arch = "arm";
		os = "u-boot";
		compression = "gzip";
		load = <0x8FFFC0>;
		entry = <0x900000>;
		signature@1 {
			algo = "sha256,rsa4096";
			key-name-hint = "key";
		};
	};
};

Signed-off-by: Mario Six <mario.six@gdsys.cc>
---

Changes in v2:
 - Use images of type 'firmware' for U-Boot images (as per Wolfgang Denk's
   hint), and make them bootable

---
 common/image-fit.c | 7 ++++---
 1 file changed, 4 insertions(+), 3 deletions(-)

--
2.9.0

Comments

Tom Rini July 20, 2016, 12:27 p.m. UTC | #1
On Wed, Jul 20, 2016 at 08:32:50AM +0200, Mario Six wrote:

> In certain circumstances it comes in handy to be able to boot into a second
> U-Boot. But as of now it is not possible to boot a U-Boot binary that is inside
> a FIT image, which is problematic for projects that e.g. need to guarantee a
> unbroken chain of trust from SOC all the way into the OS, since the FIT signing
> mechanism cannot be used.
> 
> This patch adds the capability to load such FIT images.
> 
> An example .its snippet (utilizing signature verification) might look
> like the following:
> 
> images {
> 	firmware@1 {
> 		description = "2nd stage U-Boot image";
> 		data = /incbin/("u-boot-dtb.img.gz");
> 		type = "firmware";
> 		arch = "arm";
> 		os = "u-boot";
> 		compression = "gzip";
> 		load = <0x8FFFC0>;
> 		entry = <0x900000>;
> 		signature@1 {
> 			algo = "sha256,rsa4096";
> 			key-name-hint = "key";
> 		};
> 	};
> };
> 
> Signed-off-by: Mario Six <mario.six@gdsys.cc>

Reviewed-by: Tom Rini <trini@konsulko.com>
Robert P. J. Day July 20, 2016, 12:59 p.m. UTC | #2
On Wed, 20 Jul 2016, Mario Six wrote:

> In certain circumstances it comes in handy to be able to boot into a second
> U-Boot. But as of now it is not possible to boot a U-Boot binary that is inside
> a FIT image, which is problematic for projects that e.g. need to guarantee a
> unbroken chain of trust from SOC all the way into the OS, since the FIT signing
> mechanism cannot be used.
>
> This patch adds the capability to load such FIT images.
>
> An example .its snippet (utilizing signature verification) might look
> like the following:
>
> images {
> 	firmware@1 {
> 		description = "2nd stage U-Boot image";
> 		data = /incbin/("u-boot-dtb.img.gz");
> 		type = "firmware";
> 		arch = "arm";
> 		os = "u-boot";
> 		compression = "gzip";
> 		load = <0x8FFFC0>;
> 		entry = <0x900000>;
> 		signature@1 {
> 			algo = "sha256,rsa4096";
> 			key-name-hint = "key";
> 		};
> 	};
> };

  i'm sure i'm about to embarrass myself, but the above represents
loading a second version of u-boot into RAM, no? but i thought u-boot
didn't support being run out of RAM (except in special circumstances).
so what am i misunderstanding here?

rday
Mario Six July 20, 2016, 1:39 p.m. UTC | #3
On Wed, Jul 20, 2016 at 2:59 PM, Robert P. J. Day <rpjday@crashcourse.ca> wrote:
> On Wed, 20 Jul 2016, Mario Six wrote:
>
>> In certain circumstances it comes in handy to be able to boot into a second
>> U-Boot. But as of now it is not possible to boot a U-Boot binary that is inside
>> a FIT image, which is problematic for projects that e.g. need to guarantee a
>> unbroken chain of trust from SOC all the way into the OS, since the FIT signing
>> mechanism cannot be used.
>>
>> This patch adds the capability to load such FIT images.
>>
>> An example .its snippet (utilizing signature verification) might look
>> like the following:
>>
>> images {
>>       firmware@1 {
>>               description = "2nd stage U-Boot image";
>>               data = /incbin/("u-boot-dtb.img.gz");
>>               type = "firmware";
>>               arch = "arm";
>>               os = "u-boot";
>>               compression = "gzip";
>>               load = <0x8FFFC0>;
>>               entry = <0x900000>;
>>               signature@1 {
>>                       algo = "sha256,rsa4096";
>>                       key-name-hint = "key";
>>               };
>>       };
>> };
>
>   i'm sure i'm about to embarrass myself, but the above represents
> loading a second version of u-boot into RAM, no? but i thought u-boot
> didn't support being run out of RAM (except in special circumstances).
> so what am i misunderstanding here?
>
> rday
>

Well, if by "special circumstances" you mean "load the U-Boot image exactly
where CONFIG_SYS_TEXT_BASE expects it to be loaded," then these are special
circumstances; the U-Boot in the example snippet has CONFIG_SYS_TEXT_BASE of
0x900000, we load it to 0x8FFFC0 (offset for the 0x40 byte header), and the
bootm routine simply jumps to the entry point.

Accordingly, the second stage U-Boot you want to run must not have the save
CONFIG_SYS_TEXT_BASE as the U-Boot you want to run it out of (otherwise you
would overwrite the existing image in memory); something like

#ifdef CONFIG_SECONDUBOOT
#define    CONFIG_SYS_TEXT_BASE    0x00800000
#else
#define    CONFIG_SYS_TEXT_BASE    0x00900000
#endif

is needed if you want to build both with the same header file.

Hope that makes things a bit clearer.

Best regards,

Mario
Robert P. J. Day July 20, 2016, 1:56 p.m. UTC | #4
On Wed, 20 Jul 2016, Mario Six wrote:

> On Wed, Jul 20, 2016 at 2:59 PM, Robert P. J. Day <rpjday@crashcourse.ca> wrote:
> > On Wed, 20 Jul 2016, Mario Six wrote:
> >
> >> In certain circumstances it comes in handy to be able to boot
> >> into a second U-Boot. But as of now it is not possible to boot a
> >> U-Boot binary that is inside a FIT image, which is problematic
> >> for projects that e.g. need to guarantee a unbroken chain of
> >> trust from SOC all the way into the OS, since the FIT signing
> >> mechanism cannot be used.
> >>
> >> This patch adds the capability to load such FIT images.
> >>
> >> An example .its snippet (utilizing signature verification) might
> >> look like the following:
> >>
> >> images {
> >>       firmware@1 {
> >>               description = "2nd stage U-Boot image";
> >>               data = /incbin/("u-boot-dtb.img.gz");
> >>               type = "firmware";
> >>               arch = "arm";
> >>               os = "u-boot";
> >>               compression = "gzip";
> >>               load = <0x8FFFC0>;
> >>               entry = <0x900000>;
> >>               signature@1 {
> >>                       algo = "sha256,rsa4096";
> >>                       key-name-hint = "key";
> >>               };
> >>       };
> >> };
> >
> >   i'm sure i'm about to embarrass myself, but the above represents
> > loading a second version of u-boot into RAM, no? but i thought
> > u-boot didn't support being run out of RAM (except in special
> > circumstances). so what am i misunderstanding here?
>
> Well, if by "special circumstances" you mean "load the U-Boot image
> exactly where CONFIG_SYS_TEXT_BASE expects it to be loaded," then
> these are special circumstances; the U-Boot in the example snippet
> has CONFIG_SYS_TEXT_BASE of 0x900000, we load it to 0x8FFFC0 (offset
> for the 0x40 byte header), and the bootm routine simply jumps to the
> entry point.
>
> Accordingly, the second stage U-Boot you want to run must not have
> the save CONFIG_SYS_TEXT_BASE as the U-Boot you want to run it out
> of (otherwise you would overwrite the existing image in memory);
> something like
>
> #ifdef CONFIG_SECONDUBOOT
> #define    CONFIG_SYS_TEXT_BASE    0x00800000
> #else
> #define    CONFIG_SYS_TEXT_BASE    0x00900000
> #endif
>
> is needed if you want to build both with the same header file.
>
> Hope that makes things a bit clearer.

  not really, since i always thought that the difficulty in loading
and booting a second-stage u-boot was explained here:

http://www.denx.de/wiki/view/DULG/CanUBootBeConfiguredSuchThatItCanBeStartedInRAM

that is, loading the second image to a different address is simple;
the apparent difficulty is that the second-stage u-boot might not be
able to handle the early setup already done by the first stage.

  so i'm still confused as to what is being proposed here, and how it
works.

rday
Mario Six July 20, 2016, 2:26 p.m. UTC | #5
On Wed, Jul 20, 2016 at 3:56 PM, Robert P. J. Day <rpjday@crashcourse.ca> wrote:
> On Wed, 20 Jul 2016, Mario Six wrote:
>
>> On Wed, Jul 20, 2016 at 2:59 PM, Robert P. J. Day <rpjday@crashcourse.ca> wrote:
>> > On Wed, 20 Jul 2016, Mario Six wrote:
>> >
>> >> In certain circumstances it comes in handy to be able to boot
>> >> into a second U-Boot. But as of now it is not possible to boot a
>> >> U-Boot binary that is inside a FIT image, which is problematic
>> >> for projects that e.g. need to guarantee a unbroken chain of
>> >> trust from SOC all the way into the OS, since the FIT signing
>> >> mechanism cannot be used.
>> >>
>> >> This patch adds the capability to load such FIT images.
>> >>
>> >> An example .its snippet (utilizing signature verification) might
>> >> look like the following:
>> >>
>> >> images {
>> >>       firmware@1 {
>> >>               description = "2nd stage U-Boot image";
>> >>               data = /incbin/("u-boot-dtb.img.gz");
>> >>               type = "firmware";
>> >>               arch = "arm";
>> >>               os = "u-boot";
>> >>               compression = "gzip";
>> >>               load = <0x8FFFC0>;
>> >>               entry = <0x900000>;
>> >>               signature@1 {
>> >>                       algo = "sha256,rsa4096";
>> >>                       key-name-hint = "key";
>> >>               };
>> >>       };
>> >> };
>> >
>> >   i'm sure i'm about to embarrass myself, but the above represents
>> > loading a second version of u-boot into RAM, no? but i thought
>> > u-boot didn't support being run out of RAM (except in special
>> > circumstances). so what am i misunderstanding here?
>>
>> Well, if by "special circumstances" you mean "load the U-Boot image
>> exactly where CONFIG_SYS_TEXT_BASE expects it to be loaded," then
>> these are special circumstances; the U-Boot in the example snippet
>> has CONFIG_SYS_TEXT_BASE of 0x900000, we load it to 0x8FFFC0 (offset
>> for the 0x40 byte header), and the bootm routine simply jumps to the
>> entry point.
>>
>> Accordingly, the second stage U-Boot you want to run must not have
>> the save CONFIG_SYS_TEXT_BASE as the U-Boot you want to run it out
>> of (otherwise you would overwrite the existing image in memory);
>> something like
>>
>> #ifdef CONFIG_SECONDUBOOT
>> #define    CONFIG_SYS_TEXT_BASE    0x00800000
>> #else
>> #define    CONFIG_SYS_TEXT_BASE    0x00900000
>> #endif
>>
>> is needed if you want to build both with the same header file.
>>
>> Hope that makes things a bit clearer.
>
>   not really, since i always thought that the difficulty in loading
> and booting a second-stage u-boot was explained here:
>
> http://www.denx.de/wiki/view/DULG/CanUBootBeConfiguredSuchThatItCanBeStartedInRAM
>
> that is, loading the second image to a different address is simple;
> the apparent difficulty is that the second-stage u-boot might not be
> able to handle the early setup already done by the first stage.
>
>   so i'm still confused as to what is being proposed here, and how it
> works.
>
> rday
>

Ah, alright. Look at the following quote from the page:

"On machines with boot-ROM and U-Boot-SPL, you might have better luck."

I'd venture that most SoCs these days have a boot-ROM; on these U-Boot, is not
as sensitive to not finding a "virgin" system (because the boot-ROM does some
initialization beforehand). The system I tested with is a Armada 38x, and we've
also use a similar approach on a MPC85xx system (if you would like to dig that
deep, the code is upstream: board/gdsys/p1022/controlcenterd*). The whole SPL
concept would be a problem if the boot loader needed a virgin CPU (since, well,
the SPL *is* a second U-Boot), so the restrictions mentioned in the page are
not as relevant for modern SoCs.

That's as far as my knowledge goes, if anyone wants to correct me, you're
welcome to do so :-)

Best regards,

Mario
Robert P. J. Day July 21, 2016, 10:56 a.m. UTC | #6
On Wed, 20 Jul 2016, Mario Six wrote:

> On Wed, Jul 20, 2016 at 3:56 PM, Robert P. J. Day <rpjday@crashcourse.ca> wrote:

... snip ...

> >   not really, since i always thought that the difficulty in loading
> > and booting a second-stage u-boot was explained here:
> >
> > http://www.denx.de/wiki/view/DULG/CanUBootBeConfiguredSuchThatItCanBeStartedInRAM
> >
> > that is, loading the second image to a different address is simple;
> > the apparent difficulty is that the second-stage u-boot might not be
> > able to handle the early setup already done by the first stage.
> >
> >   so i'm still confused as to what is being proposed here, and how it
> > works.
> >
> > rday
> >
>
> Ah, alright. Look at the following quote from the page:
>
> "On machines with boot-ROM and U-Boot-SPL, you might have better luck."
>
> I'd venture that most SoCs these days have a boot-ROM; on these
> U-Boot, is not as sensitive to not finding a "virgin" system
> (because the boot-ROM does some initialization beforehand). The
> system I tested with is a Armada 38x, and we've also use a similar
> approach on a MPC85xx system (if you would like to dig that deep,
> the code is upstream: board/gdsys/p1022/controlcenterd*). The whole
> SPL concept would be a problem if the boot loader needed a virgin
> CPU (since, well, the SPL *is* a second U-Boot), so the restrictions
> mentioned in the page are not as relevant for modern SoCs.
>
> That's as far as my knowledge goes, if anyone wants to correct me,
> you're welcome to do so :-)

  ok, so it appears that wiki page is a little on the pessimistic
side, then. i was aware of the SPL, having worked with beaglebone
black for a while. i've never looked *closely* at how limited or
restrictive the SPL is, but i did know it had to do far less than the
full-featured u-boot. maybe it's time to look into that far more
closely to understand it better, and to appreciate what's possible.

  i can see this 2013 presentation, "TPL: SPL loading SPL (and, SPL as
just another U-Boot config", from scott wood of freescale. that looks
like it might be educational.

rday
Tom Rini July 26, 2016, 2:32 a.m. UTC | #7
On Wed, Jul 20, 2016 at 08:32:50AM +0200, mario.six@gdsys.cc wrote:

> In certain circumstances it comes in handy to be able to boot into a second
> U-Boot. But as of now it is not possible to boot a U-Boot binary that is inside
> a FIT image, which is problematic for projects that e.g. need to guarantee a
> unbroken chain of trust from SOC all the way into the OS, since the FIT signing
> mechanism cannot be used.
> 
> This patch adds the capability to load such FIT images.
> 
> An example .its snippet (utilizing signature verification) might look
> like the following:
> 
> images {
> 	firmware@1 {
> 		description = "2nd stage U-Boot image";
> 		data = /incbin/("u-boot-dtb.img.gz");
> 		type = "firmware";
> 		arch = "arm";
> 		os = "u-boot";
> 		compression = "gzip";
> 		load = <0x8FFFC0>;
> 		entry = <0x900000>;
> 		signature@1 {
> 			algo = "sha256,rsa4096";
> 			key-name-hint = "key";
> 		};
> 	};
> };
> 
> Signed-off-by: Mario Six <mario.six@gdsys.cc>
> Reviewed-by: Tom Rini <trini@konsulko.com>

Applied to u-boot/master, thanks!
diff mbox

Patch

diff --git a/common/image-fit.c b/common/image-fit.c
index 6f920da..73ad34e 100644
--- a/common/image-fit.c
+++ b/common/image-fit.c
@@ -1684,12 +1684,13 @@  int fit_image_load(bootm_headers_t *images, ulong addr,

 	bootstage_mark(bootstage_id + BOOTSTAGE_SUB_CHECK_ALL);
 	type_ok = fit_image_check_type(fit, noffset, image_type) ||
-		(image_type == IH_TYPE_KERNEL &&
-			fit_image_check_type(fit, noffset,
-					     IH_TYPE_KERNEL_NOLOAD));
+		  fit_image_check_type(fit, noffset, IH_TYPE_FIRMWARE) ||
+		  (image_type == IH_TYPE_KERNEL &&
+		   fit_image_check_type(fit, noffset, IH_TYPE_KERNEL_NOLOAD));

 	os_ok = image_type == IH_TYPE_FLATDT || IH_TYPE_FPGA ||
 		fit_image_check_os(fit, noffset, IH_OS_LINUX) ||
+		fit_image_check_os(fit, noffset, IH_OS_U_BOOT) ||
 		fit_image_check_os(fit, noffset, IH_OS_OPENRTOS);

 	/*