Community
cancel
Showing results for 
Search instead for 
Did you mean: 
Highlighted
Novice
1,727 Views

how to boot a signed kernel image from u-boot?

Jump to solution

I want to boot a signed kernel. Ideally, I could use u-boot's FIT image format. I found many guides outlining how to do this, but most don't discuss x86 specifically. Mostly I've just been trying to get the FIT image working.

Normally I boot with a bzImage and an initrd, but the initrd can be ignored for now, because I can't even boot the kernel.

If I try to boot with part of vmlinux image (`objcopy -O binary vmlinux vmlinux.bin`), it fails with `Image too large: increase CONFIG_SYS_BOOTM_LEN`, which I've increased to 32 MB and rebuilt u-boot, but it always happens.

If I try to boot a bzImage, it fails with a general protection fault, which I think is actually due the `setup.bin` because the same error happens if I just load the `setup.bin` and do `go` on it. I'm not even sure what `setup.bin` does, but apparently I need it according to the u-boot docs.

I got `setup.bin` from `arch/x86/boot/setup.bin` in the kernel build tree. I got vmlinux and bzImage from `build/tmp/deploy/images/edison/`.

I've changed edison_defconfig in the u-boot source tree with CONFIG_FIT=y and CONFIG_SYS_BOOTM_LEN=33554432. U-boot is correctly reading the FIT image, I just don't have the kernel/setup.bin images correct, or loading them at the wrong place, or something like that.

Here's my fit-image.its:

// see /doc/uImage.FIT/source_file_format.txt

// http://www.denx.de/wiki/pub/U-Boot/Documentation/multi_image_booting_scenarios.pdf http://www.denx.de/wiki/pub/U-Boot/Documentation/multi_image_booting_scenarios.pdf

/dts-v1/;

/ {

description = "Linux kernel";

# address-cells = <1>;

images {

kernel@1 {

description = "Linux kernel";

data = /incbin/("vmlinux.bin");

arch = "x86";

os = "linux";

type = "kernel";

// not compressed from u-boot's perspective

compression = "none";

load = <0x800000>;

entry = <0x800000>;

hash@1 {

algo = "sha256";

};

/*sigature@1 {

algo = "sha256,rsa2048";

key-name-hint = "xrd";

};*/

};

ramdisk@1 {

description = "initrd";

data = /incbin/("initrd");

type = "ramdisk";

arch = "x86";

os = "linux";

// not compressed from u-boot's perspective

compression = "none";

load = <0x100000>;

entry = <0x100000>;

hash@1 {

algo = "sha256";

};

/*sigature@1 {

algo = "sha256,rsa2048";

key-name-hint = "xrd";

};*/

};

setup@1 {

description = "setup.bin";

data = /incbin/("setup.bin");

type = "x86_setup";

arch = "x86";

os = "linux";

compression = "none";

load = <0x90000>;

entry = <0x90000>;

hash@1 {

algo = "sha256";

};

};

};

configurations {

default = "conf@1";

conf@1 {

description = "Boot Linux Kernel";

kernel = "kernel@1";

ramdisk = "ramdisk@1";

setup = "setup@1";

/*signature@1 {

algo = "sha256,rsa2048";

key-name-hint = "xrd";

sign-images = "kernel,fdt";

};*/

};

};

};


Accepted Solutions
Highlighted
Novice
258 Views

I got it working. I found that the best tutorial was the http://git.denx.de/?p=u-boot.git;a=blob_plain;f=doc/uImage.FIT/beaglebone_vboot.txt;hb=HEAD BeagleBone tutorial from u-boot.

To create the FIT image, I needed my initrd (optional), arch/x86/boot/vmlinux.bin, and arch/x86/boot/setup.bin from a successfully built kernel (I added a .bbappend to the kernel recipe to make a new package containing these). As explained before, the kernel is compressed and will decompress itself, thus there's no need to compress in the FIT.

Here's the boot.its:

// see /doc/uImage.FIT/source_file_format.txt

// http://www.denx.de/wiki/pub/U-Boot/Documentation/multi_image_booting_scenarios.pdf http://www.denx.de/wiki/pub/U-Boot/Documentation/multi_image_booting_scenarios.pdf

/dts-v1/;

/ {

description = "FIT Image";

//# address-cells = <1>;

images {

kernel@1 {

description = "Linux kernel";

data = /incbin/("vmlinux.bin");

arch = "x86";

os = "linux";

type = "kernel";

// not compressed from u-boot's perspective

compression = "none";

load = <0x1200000>;

entry = <0x1200000>;

hash@1 {

algo = "sha256";

};

};

ramdisk@1 {

description = "initrd";

data = /incbin/("initrd");

type = "ramdisk";

arch = "x86";

os = "linux";

// not compressed from u-boot's perspective

compression = "none";

load = <0x100000>;

entry = <0x100000>;

hash@1 {

algo = "sha256";

};

};

setup@1 {

description = "setup.bin";

data = /incbin/("setup.bin");

type = "x86_setup";

arch = "x86";

os = "linux";

compression = "none";

load = <0x90000>;

entry = <0x90000>;

hash@1 {

algo = "sha256";

};

};

};

configurations {

default = "conf@1";

conf@1 {

description = "Boot Linux Kernel";

kernel = "kernel@1";

ramdisk = "ramdisk@1";

setup = "setup@1";

signature@1 {

algo = "sha256,rsa2048";

key-name-hint = "xrd";

sign-images = "kernel","ramdisk","setup";

};

};

};

};

I made the keys as directed in the tutorial, and named them `keys/xrd.crt` and `keys/xrd.key` ("xrd" is a codename for our device, the important thing is that this matches the "key-name-hint" field).

I needed to add these options to u-boot's defconfig:

CONFIG_FIT=y

CONFIG_FIT_SIGNATURE=y

CONFIG_RSA=y

And build u-boot with a dtb using `make EXT_DTB=/path/to/edison-pubkey.dtb`. I made the dtb by taking the original dtb from `dts/dt.dtb` in a successfully built u-boot source tree. Most tutorials will tell you to use `CONFIG_OF_SEPARATE=y`, and I got a working u-boot with that option (after figuring out all the weird post processing that edison expects), but it wouldn't recognize the key (I probably just had some small detail wrong). Using the original dtb, I made the public key dtb with:

cp $uboot_src/dt.dtb edison-pubkey.dtb

mkimage -f boot.its -k keys -K edison-pubkey.dtb -r boot.itb

The pwd should have the files referenced in boot.its (kernel, setup.bin, initrd), the `keys/` directory, and `edison-pubkey.dtb`. After running that command, you get both a signed FIT (boot.itb) and an edited u-boot dtb with the public key (edison-pubkey.dtb). To sign more images, you don't need the `-K foo.dtb` option.

Finally, in u-boot, to boot the FIT you can simply load the FIT somewhere that doesn't interfere with the load addresses in the FIT.

setenv loadaddr 0x20000000 # loadaddr is a special variable

fatload mmc 1 $loadaddr boot.itb

bootm

It should fail if the sig/hashes don't match. It's checking the key if you see the lines:

Using 'conf@1' configuration

Verifying Hash Integrity ... sha256,rsa2048:xrd+ OK

The "+" and "OK" means it passed the check, and the "rsa2048" means it's checking the sig.

View solution in original post

0 Kudos
5 Replies
Highlighted
Community Manager
258 Views

Hello jpkotta,

 

 

Thanks for reaching out!

 

 

Please let me investigate to see if I can find some information that can help you. However, I must point out that U-boot modifications are not supported by us.

 

 

-Peter.
0 Kudos
Highlighted
Novice
258 Views

After posting this I got the FIT image booting, including my initrd. I needed to use `arch/x86/boot/vmlinux.bin`, which is different from both the `vmlinux.bin` that ends up in the root of the kernel build tree, and the `vmlinux.bin` that I created with `objcopy`. I'll note that I'm using an XZ compressed kernel, but I'm sure a gzip or bzip2 kernel would work too, and no compression support needs to be in u-boot because the kernel decompresses itself. I haven't gotten signing working yet, as I'm working on other things for a few days, but I'm guessing it will be a matter of following the docs.

0 Kudos
Highlighted
Community Manager
258 Views

I'm glad to hear that you have managed to progress in your project. I encourage you to continue working on it and to share your progress in the community. Other users might find it helpful.

 

 

I look forward to hear from you again.

 

-Peter.
0 Kudos
Highlighted
Novice
259 Views

I got it working. I found that the best tutorial was the http://git.denx.de/?p=u-boot.git;a=blob_plain;f=doc/uImage.FIT/beaglebone_vboot.txt;hb=HEAD BeagleBone tutorial from u-boot.

To create the FIT image, I needed my initrd (optional), arch/x86/boot/vmlinux.bin, and arch/x86/boot/setup.bin from a successfully built kernel (I added a .bbappend to the kernel recipe to make a new package containing these). As explained before, the kernel is compressed and will decompress itself, thus there's no need to compress in the FIT.

Here's the boot.its:

// see /doc/uImage.FIT/source_file_format.txt

// http://www.denx.de/wiki/pub/U-Boot/Documentation/multi_image_booting_scenarios.pdf http://www.denx.de/wiki/pub/U-Boot/Documentation/multi_image_booting_scenarios.pdf

/dts-v1/;

/ {

description = "FIT Image";

//# address-cells = <1>;

images {

kernel@1 {

description = "Linux kernel";

data = /incbin/("vmlinux.bin");

arch = "x86";

os = "linux";

type = "kernel";

// not compressed from u-boot's perspective

compression = "none";

load = <0x1200000>;

entry = <0x1200000>;

hash@1 {

algo = "sha256";

};

};

ramdisk@1 {

description = "initrd";

data = /incbin/("initrd");

type = "ramdisk";

arch = "x86";

os = "linux";

// not compressed from u-boot's perspective

compression = "none";

load = <0x100000>;

entry = <0x100000>;

hash@1 {

algo = "sha256";

};

};

setup@1 {

description = "setup.bin";

data = /incbin/("setup.bin");

type = "x86_setup";

arch = "x86";

os = "linux";

compression = "none";

load = <0x90000>;

entry = <0x90000>;

hash@1 {

algo = "sha256";

};

};

};

configurations {

default = "conf@1";

conf@1 {

description = "Boot Linux Kernel";

kernel = "kernel@1";

ramdisk = "ramdisk@1";

setup = "setup@1";

signature@1 {

algo = "sha256,rsa2048";

key-name-hint = "xrd";

sign-images = "kernel","ramdisk","setup";

};

};

};

};

I made the keys as directed in the tutorial, and named them `keys/xrd.crt` and `keys/xrd.key` ("xrd" is a codename for our device, the important thing is that this matches the "key-name-hint" field).

I needed to add these options to u-boot's defconfig:

CONFIG_FIT=y

CONFIG_FIT_SIGNATURE=y

CONFIG_RSA=y

And build u-boot with a dtb using `make EXT_DTB=/path/to/edison-pubkey.dtb`. I made the dtb by taking the original dtb from `dts/dt.dtb` in a successfully built u-boot source tree. Most tutorials will tell you to use `CONFIG_OF_SEPARATE=y`, and I got a working u-boot with that option (after figuring out all the weird post processing that edison expects), but it wouldn't recognize the key (I probably just had some small detail wrong). Using the original dtb, I made the public key dtb with:

cp $uboot_src/dt.dtb edison-pubkey.dtb

mkimage -f boot.its -k keys -K edison-pubkey.dtb -r boot.itb

The pwd should have the files referenced in boot.its (kernel, setup.bin, initrd), the `keys/` directory, and `edison-pubkey.dtb`. After running that command, you get both a signed FIT (boot.itb) and an edited u-boot dtb with the public key (edison-pubkey.dtb). To sign more images, you don't need the `-K foo.dtb` option.

Finally, in u-boot, to boot the FIT you can simply load the FIT somewhere that doesn't interfere with the load addresses in the FIT.

setenv loadaddr 0x20000000 # loadaddr is a special variable

fatload mmc 1 $loadaddr boot.itb

bootm

It should fail if the sig/hashes don't match. It's checking the key if you see the lines:

Using 'conf@1' configuration

Verifying Hash Integrity ... sha256,rsa2048:xrd+ OK

The "+" and "OK" means it passed the check, and the "rsa2048" means it's checking the sig.

View solution in original post

0 Kudos
Highlighted
Community Manager
258 Views

Those are great new! Thank you for sharing this information with the community, we look forward to hearing more from you. In case you ever have any doubts, please don't hesitate to come back to the community, we'll try to help you in any way we can.

 

 

-Peter.
0 Kudos