Re: Fit images and EFI_LOAD_FILE2_PROTOCOL
Hello Heinrich, On Sat, Oct 03, 2020 at 10:51:24AM +0200, Heinrich Schuchardt wrote: > Hello Ilias, hello Christian, > > with commit ec80b4735a59 ("efi_loader: Implement FileLoad2 for initramfs > loading") Ilias provided the possibility to specify a device path > (CONFIG_EFI_INITRD_FILESPEC) from which an initial RAM disk can be > served via the EFI_FILE_LOAD2_PROTOCOL. > > Ard extended the Linux EFI stub to allow loading the initial RAM disk > via the EFI_FILE_LOAD2_PROTOCOL with the utmost priority. Thanks for sharing this information, I was not aware of the work related to the EFI_FILE_LOAD2_PROTOCOL, neither in the Linux kernel nor in U-Boot. > With commit ecc7fdaa9ef1 ("bootm: Add a bootm command for type > IH_OS_EFI") Cristian enabled signed FIT images that contain a device > tree and a UEFI binary (enabled by CONFIG_BOOTM_EFI=y). > > In the DTE calls we have discussed that it is unfortunate that we do not > have a method to validate initial RAM images in the UEFI context. > > To me it would look like a good path forward to combine the two ideas: > > * Let the signed FIT image (of type IH_OS_EFI) contain a RAM disk > * Pass location and size to the UEFI subsystem and serve them via > the EFI_FILE_LOAD2_PROTOCOL. > > We could also extend the bootefi command to be callable as > >bootefi $kernel_addr_r $ramdisk_addr_r:$filesize $fdt_addr_r > > like the booti command to serve an initial RAM disk. > > What are your thoughts? I think having initial RAM disk support in UEFI FIT images would be a great improvement. For the moment I had to put on hold my experiments around bootefi and verified boot scenarios, but I will do my best to resume this work in the foreseeable future. > Best regards > > Heinrich Kind regards, Cristi
Re: [PATCH v2 1/1] travis-ci: Fix "ResourceWarning: unclosed file"
On Wed, Jun 24, 2020 at 02:30:24PM -0600, Stephen Warren wrote: > On 12/30/19 9:41 AM, Stephen Warren wrote: > > On 12/30/19 4:49 AM, Cristian Ciocaltea wrote: > >> This patch gets rid of the warning messages like: > >> > >> uboot-test-hooks/py/travis-ci/travis_tftp.py:43: ResourceWarning: > >> unclosed file <_io.BufferedReader name='.bm-work/qemu_arm/u-boot.bin'> > >> > >> Signed-off-by: Cristian Ciocaltea > >> --- > >> Changes in v2: > >> * The warning line number in the comment relies on Heinrich Schuchardt's > >> work 'travis-ci: provide env__efi_fit_tftp_file', but my initial patch > >> was based on the master version. Even though it is still applicable, > >> to avoid any confusion, I rebased it on Heinrich's latest patch (v2): > >> https://lists.denx.de/pipermail/u-boot/2019-December/395029.html > > > > There's no need to rebase the patch for that kind of thing; the warning > > is only a reference/example anyway, and the next time someone edits this > > file after you, the line number will change again, and we can't go back > > and edit this commit description to patch that up. > > > >> diff --git a/py/travis-ci/travis_tftp.py b/py/travis-ci/travis_tftp.py > > > >> + > >> + with open(file_full, 'rb') as fd: > >> + ret["crc32"] = hex(binascii.crc32(fd.read()) & 0x)[2:] > > > > Nit: "f" for "file" rather than "fd" for "file descriptor" (usually an > > integer) would have been a better variable name. No need to resend to > > change this though. > > > > Reviewed-by: Stephen Warren > > Oh, somehow I failed to realize that I needed to apply this. It's now > applied. Great, thanks!
Re: [PATCH v2 1/1] travis-ci: provide env__efi_fit_tftp_file
On Tue, Dec 31, 2019 at 12:42:36PM +0200, Cristian Ciocaltea wrote: > On Mon, Dec 30, 2019 at 09:03:38PM +0100, Heinrich Schuchardt wrote: > > On 12/30/19 8:32 PM, Stephen Warren wrote: > > > On 12/30/19 12:05 PM, Heinrich Schuchardt wrote: > > > > On 12/30/19 5:38 PM, Stephen Warren wrote: > > > > > On 12/30/19 3:52 AM, Heinrich Schuchardt wrote: > > > > > > Provide dictionary env__efi_fit_tftp_file describing the file used > > > > > > for > > > > > > the > > > > > > UEFI FIT image test. > > > > > > > > > > > diff --git a/py/travis-ci/travis_tftp.py > > > > > > b/py/travis-ci/travis_tftp.py > > > > > > > > > > > +def efifit2env(addr=None): > > > > > > + """Create dictionary describing file for EFI fit image test > > > > > > + > > > > > > + @addr: address used for loading the file as int (e.g. > > > > > > 0x4040) > > > > > > + Return: dictionary describing the file with entries > > > > > > + * fn - filename > > > > > > + * addr - loading address, optional > > > > > > + * dn - tftp directory > > > > > > + """ > > > > > > + tftp_dir = os.environ['UBOOT_TRAVIS_BUILD_DIR'] > > > > > > + > > > > > > + ret = { > > > > > > + "fn": "test-efi-fit.img", > > > > > > > > > > If this function were to exist, then the filename shouldn't be > > > > > hard-coded; it should be a parameter. > > > > > > > > > > > > > Hello Stephen, > > > > > > > > thanks for reviewing. > > > > > > > > This is the name of a generated file. It does not depend on the board. > > > > > > What generates the file and when/why? > > > > > > Generated files should generally be put into > > > u_boot_console.config.persistent_data_dir, and presumably the name > > > hard-coded into the test that uses it. > > > > > > > Hello Stephen, > > > > this is the test case: > > > > https://lists.denx.de/pipermail/u-boot/2019-December/394957.html > > test/py: Create a test for launching UEFI binaries from FIT images > > > > The test can be run in different styles: > > > > * A complete FIT image can be supplied. In this case the dictionary > > must contain a "size" entry. > > * The test can generate a FIT image from lib/efi_loader/helloworld.efi. > > In this case no "size" entry shall be supplied. The "fn" field > > provides the name of the generated file. The file is generated in > > cons.config.build_dir. The "dn" field" describes the tFTP root > > directory to which the generated file is copied. > > A small correction here: if the "size" entry is not provided in the > dictionary, the test generates a FIT image using a hardcoded file > name (test-efi-fit-helloworld.fit), so any "fn" entry provided in the > dictionary is ignored in this case. > > > The tFTP directory "dn" is only known in uboot-test-hooks.git. > > Yes, and this is actually the only mandatory information to be > provided in the dictionary when the test is supposed to generate the > FIT image. We could get rid of this, too, if we make the assumption > that the tFTP root directory is u_boot_console.config.build_dir by > default. > > > test/py/README.md says --persistent-data-dir is used for data that may > > be re-used across test runs. Currently the FIT file is generated in > > every run. In principal it could be reused. So Christian could consider > > adjusting his patch. > > Actually the FIT image file can be generated multiple times per test > run, with different content, which is determined by various combinations > of flags. E.g. for sandbox we have: enable/disable GZIP compression, > enable/disable FDT usage. Each combination is used in a subtest, that > (re)generates the corresponding FIT image. > > To re-use the generated data we need to introduce additional complexity > to handle FIT image identification for each subtest and to invalidate > those images when they become out of sync with the parametrized input > data samples (ITS, FDT) used to generate their content. > > > Best regards > > > > Heinric
Re: [PATCH v2 1/1] travis-ci: provide env__efi_fit_tftp_file
On Mon, Dec 30, 2019 at 09:03:38PM +0100, Heinrich Schuchardt wrote: > On 12/30/19 8:32 PM, Stephen Warren wrote: > > On 12/30/19 12:05 PM, Heinrich Schuchardt wrote: > > > On 12/30/19 5:38 PM, Stephen Warren wrote: > > > > On 12/30/19 3:52 AM, Heinrich Schuchardt wrote: > > > > > Provide dictionary env__efi_fit_tftp_file describing the file used for > > > > > the > > > > > UEFI FIT image test. > > > > > > > > > diff --git a/py/travis-ci/travis_tftp.py b/py/travis-ci/travis_tftp.py > > > > > > > > > +def efifit2env(addr=None): > > > > > + """Create dictionary describing file for EFI fit image test > > > > > + > > > > > + @addr: address used for loading the file as int (e.g. > > > > > 0x4040) > > > > > + Return: dictionary describing the file with entries > > > > > + * fn - filename > > > > > + * addr - loading address, optional > > > > > + * dn - tftp directory > > > > > + """ > > > > > + tftp_dir = os.environ['UBOOT_TRAVIS_BUILD_DIR'] > > > > > + > > > > > + ret = { > > > > > + "fn": "test-efi-fit.img", > > > > > > > > If this function were to exist, then the filename shouldn't be > > > > hard-coded; it should be a parameter. > > > > > > > > > > Hello Stephen, > > > > > > thanks for reviewing. > > > > > > This is the name of a generated file. It does not depend on the board. > > > > What generates the file and when/why? > > > > Generated files should generally be put into > > u_boot_console.config.persistent_data_dir, and presumably the name > > hard-coded into the test that uses it. > > > > Hello Stephen, > > this is the test case: > > https://lists.denx.de/pipermail/u-boot/2019-December/394957.html > test/py: Create a test for launching UEFI binaries from FIT images > > The test can be run in different styles: > > * A complete FIT image can be supplied. In this case the dictionary > must contain a "size" entry. > * The test can generate a FIT image from lib/efi_loader/helloworld.efi. > In this case no "size" entry shall be supplied. The "fn" field > provides the name of the generated file. The file is generated in > cons.config.build_dir. The "dn" field" describes the tFTP root > directory to which the generated file is copied. A small correction here: if the "size" entry is not provided in the dictionary, the test generates a FIT image using a hardcoded file name (test-efi-fit-helloworld.fit), so any "fn" entry provided in the dictionary is ignored in this case. > The tFTP directory "dn" is only known in uboot-test-hooks.git. Yes, and this is actually the only mandatory information to be provided in the dictionary when the test is supposed to generate the FIT image. We could get rid of this, too, if we make the assumption that the tFTP root directory is u_boot_console.config.build_dir by default. > test/py/README.md says --persistent-data-dir is used for data that may > be re-used across test runs. Currently the FIT file is generated in > every run. In principal it could be reused. So Christian could consider > adjusting his patch. Actually the FIT image file can be generated multiple times per test run, with different content, which is determined by various combinations of flags. E.g. for sandbox we have: enable/disable GZIP compression, enable/disable FDT usage. Each combination is used in a subtest, that (re)generates the corresponding FIT image. To re-use the generated data we need to introduce additional complexity to handle FIT image identification for each subtest and to invalidate those images when they become out of sync with the parametrized input data samples (ITS, FDT) used to generate their content. > Best regards > > Heinrich
[PATCH v2 1/1] travis-ci: Fix "ResourceWarning: unclosed file"
This patch gets rid of the warning messages like: uboot-test-hooks/py/travis-ci/travis_tftp.py:43: ResourceWarning: unclosed file <_io.BufferedReader name='.bm-work/qemu_arm/u-boot.bin'> Signed-off-by: Cristian Ciocaltea --- Changes in v2: * The warning line number in the comment relies on Heinrich Schuchardt's work 'travis-ci: provide env__efi_fit_tftp_file', but my initial patch was based on the master version. Even though it is still applicable, to avoid any confusion, I rebased it on Heinrich's latest patch (v2): https://lists.denx.de/pipermail/u-boot/2019-December/395029.html py/travis-ci/travis_tftp.py | 5 - 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/py/travis-ci/travis_tftp.py b/py/travis-ci/travis_tftp.py index 884823c..f9a44aa 100644 --- a/py/travis-ci/travis_tftp.py +++ b/py/travis-ci/travis_tftp.py @@ -40,8 +40,11 @@ def file2env(file_name, addr=None): ret = { "fn": file_name, "size": os.path.getsize(file_full), -"crc32": hex(binascii.crc32(open(file_full, 'rb').read()) & 0x)[2:], } + +with open(file_full, 'rb') as fd: +ret["crc32"] = hex(binascii.crc32(fd.read()) & 0x)[2:] + if addr is not None: ret['addr'] = addr -- 2.17.1
Re: [PATCH 1/1] travis-ci: provide env__efi_fit_tftp_file
On Sun, Dec 29, 2019 at 06:46:40PM +0100, Heinrich Schuchardt wrote: > Provide dictionary env__efi_fit_tftp_file describing the file used for the > UEFI FIT image test. > > Cf. "test/py: Create a test for launching UEFI binaries from FIT images" > https://lists.denx.de/pipermail/u-boot/2019-December/394516.html > > Signed-off-by: Heinrich Schuchardt > --- > py/travis-ci/travis_tftp.py | 20 +++ > py/travis-ci/u_boot_boardenv_qemu_arm64_na.py | 1 + > py/travis-ci/u_boot_boardenv_qemu_arm_na.py | 1 + > .../u_boot_boardenv_qemu_x86_64_na.py | 2 ++ > py/travis-ci/u_boot_boardenv_qemu_x86_na.py | 2 ++ > .../u_boot_boardenv_vexpress_ca15_tc2_qemu.py | 1 + > .../u_boot_boardenv_vexpress_ca9x4_qemu.py| 1 + > 7 files changed, 28 insertions(+) > > diff --git a/py/travis-ci/travis_tftp.py b/py/travis-ci/travis_tftp.py > index 4ea5c06..2ab7740 100644 > --- a/py/travis-ci/travis_tftp.py > +++ b/py/travis-ci/travis_tftp.py > @@ -1,6 +1,26 @@ > import os > import binascii > > +def efifit2env(addr=None): > +"""Create dictionary describing file for UEFI FIT image test > + > +@addr: address used for loading the file as int (e.g. 0x4040) > +Return: dictionary describing the file with entries > +* fn- filename > +* addr - loading address, optional > +* dn- tftp directory > +""" > +tftp_dir = os.environ['UBOOT_TRAVIS_BUILD_DIR'] + "/" > + > +ret = { > +"fn": "test-efi-fit.img", > +"dn": "tftp_dir", The quotes around tftp_dir should be removed to allow variable evaluation: "dn": tftp_dir, > +} > +if addr is not None: > +ret['addr'] = addr > + > +return ret > + > def file2env(file_name, addr=None): > """Create dictionary describing file > > diff --git a/py/travis-ci/u_boot_boardenv_qemu_arm64_na.py > b/py/travis-ci/u_boot_boardenv_qemu_arm64_na.py > index 2986115..98ce873 100644 > --- a/py/travis-ci/u_boot_boardenv_qemu_arm64_na.py > +++ b/py/travis-ci/u_boot_boardenv_qemu_arm64_na.py > @@ -6,3 +6,4 @@ env__net_dhcp_server = True > env__net_tftp_readable_file = travis_tftp.file2env('u-boot.bin', 0x4040) > env__efi_loader_helloworld_file = > travis_tftp.file2env('lib/efi_loader/helloworld.efi', 0x4040) > env__efi_loader_grub_file = travis_tftp.file2env('grub_arm64.efi', > 0x4040) > +env__efi_fit_tftp_file = travis_tftp.efifit2env(0x4040) > diff --git a/py/travis-ci/u_boot_boardenv_qemu_arm_na.py > b/py/travis-ci/u_boot_boardenv_qemu_arm_na.py > index 391e3c4..3dbedde 100644 > --- a/py/travis-ci/u_boot_boardenv_qemu_arm_na.py > +++ b/py/travis-ci/u_boot_boardenv_qemu_arm_na.py > @@ -6,3 +6,4 @@ env__net_dhcp_server = True > env__net_tftp_readable_file = travis_tftp.file2env('u-boot.bin', 0x4040) > env__efi_loader_helloworld_file = > travis_tftp.file2env('lib/efi_loader/helloworld.efi', 0x4040) > env__efi_loader_grub_file = travis_tftp.file2env('grub_arm.efi', 0x4040) > +env__efi_fit_tftp_file = travis_tftp.efifit2env(0x4040) > diff --git a/py/travis-ci/u_boot_boardenv_qemu_x86_64_na.py > b/py/travis-ci/u_boot_boardenv_qemu_x86_64_na.py > index 6f7c593..2fe72c8 100644 > --- a/py/travis-ci/u_boot_boardenv_qemu_x86_64_na.py > +++ b/py/travis-ci/u_boot_boardenv_qemu_x86_64_na.py > @@ -8,3 +8,5 @@ env__efi_loader_helloworld_file = > travis_tftp.file2env('lib/efi_loader/helloworl > > env__efi_loader_check_smbios = True > env__efi_loader_grub_file = travis_tftp.file2env('grub_x64.efi') > + > +env__efi_fit_tftp_file = travis_tftp.efifit2env() > diff --git a/py/travis-ci/u_boot_boardenv_qemu_x86_na.py > b/py/travis-ci/u_boot_boardenv_qemu_x86_na.py > index 70dc0ae..62cc279 100644 > --- a/py/travis-ci/u_boot_boardenv_qemu_x86_na.py > +++ b/py/travis-ci/u_boot_boardenv_qemu_x86_na.py > @@ -8,3 +8,5 @@ env__efi_loader_helloworld_file = > travis_tftp.file2env('lib/efi_loader/helloworl > > env__efi_loader_check_smbios = True > env__efi_loader_grub_file = travis_tftp.file2env('grub_x86.efi') > + > +env__efi_fit_tftp_file = travis_tftp.efifit2env() > diff --git a/py/travis-ci/u_boot_boardenv_vexpress_ca15_tc2_qemu.py > b/py/travis-ci/u_boot_boardenv_vexpress_ca15_tc2_qemu.py > index 7437ae6..75f287c 100644 > --- a/py/travis-ci/u_boot_boardenv_vexpress_ca15_tc2_qemu.py > +++ b/py/travis-ci/u_boot_boardenv_vexpress_ca15_tc2_qemu.py > @@ -5,3 +5,4 @@ env__net_dhcp_server = True > env__net_tftp_readable_file = travis_tftp.file2env('u-boot') > env__efi_loader_helloworld_file = > travis_tftp.file2env('lib/efi_loader/helloworld.efi') > env__efi_loader_grub_file = travis_tftp.file2env('grub_arm.efi') > +env__efi_fit_tftp_file = travis_tftp.efifit2env() > diff --git a/py/travis-ci/u_boot_boardenv_vexpress_ca9x4_qemu.py > b/py/travis-ci/u_boot_boardenv_vexpress_ca9x4_qemu.py > index 7437ae6..75f287c 100644 > --- a/py/travis-ci/u_boot_boardenv_vexpress_ca9x4_qemu.py > +++
[PATCH v5 1/5] image: Add IH_OS_EFI for EFI chain-load boot
Add a new OS type to be used for chain-loading an EFI compatible firmware or boot loader like GRUB2, possibly in a verified boot scenario. Bellow is sample ITS file that generates a FIT image supporting secure boot. Please note the presence of 'os = "efi";' line, which identifies the currently introduced OS type: / { #address-cells = <1>; images { efi-grub { description = "GRUB EFI"; data = /incbin/("bootarm.efi"); type = "kernel_noload"; arch = "arm"; os = "efi"; compression = "none"; load = <0x0>; entry = <0x0>; hash-1 { algo = "sha256"; }; }; }; configurations { default = "config-grub"; config-grub { kernel = "efi-grub"; signature-1 { algo = "sha256,rsa2048"; sign-images = "kernel"; }; }; }; }; Signed-off-by: Cristian Ciocaltea Reviewed-by: Heinrich Schuchardt --- common/image-fit.c | 3 ++- common/image.c | 1 + include/image.h| 1 + 3 files changed, 4 insertions(+), 1 deletion(-) diff --git a/common/image-fit.c b/common/image-fit.c index c52f945120..231612ff5f 100644 --- a/common/image-fit.c +++ b/common/image-fit.c @@ -1926,7 +1926,8 @@ int fit_image_load(bootm_headers_t *images, ulong addr, image_type == 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); + fit_image_check_os(fit, noffset, IH_OS_OPENRTOS) || + fit_image_check_os(fit, noffset, IH_OS_EFI); /* * If either of the checks fail, we should report an error, but diff --git a/common/image.c b/common/image.c index eb626dcac9..75d5dd944f 100644 --- a/common/image.c +++ b/common/image.c @@ -137,6 +137,7 @@ static const table_entry_t uimage_os[] = { { IH_OS_OPENRTOS, "openrtos", "OpenRTOS", }, #endif { IH_OS_OPENSBI, "opensbi", "RISC-V OpenSBI", }, + { IH_OS_EFI, "efi", "EFI Firmware" }, { -1, "", "", }, }; diff --git a/include/image.h b/include/image.h index f4d2aaf53e..4a280b78e7 100644 --- a/include/image.h +++ b/include/image.h @@ -157,6 +157,7 @@ enum { IH_OS_ARM_TRUSTED_FIRMWARE, /* ARM Trusted Firmware */ IH_OS_TEE, /* Trusted Execution Environment */ IH_OS_OPENSBI, /* RISC-V OpenSBI */ + IH_OS_EFI, /* EFI Firmware (e.g. GRUB2) */ IH_OS_COUNT, }; -- 2.17.1
[PATCH v5 5/5] test/py: Create a test for launching UEFI binaries from FIT images
This test verifies the implementation of the 'bootm' extension that handles UEFI binaries inside FIT images (enabled via CONFIG_BOOTM_EFI). Signed-off-by: Cristian Ciocaltea --- test/py/tests/test_efi_fit.py | 458 ++ 1 file changed, 458 insertions(+) create mode 100644 test/py/tests/test_efi_fit.py diff --git a/test/py/tests/test_efi_fit.py b/test/py/tests/test_efi_fit.py new file mode 100644 index 00..6986b2d35c --- /dev/null +++ b/test/py/tests/test_efi_fit.py @@ -0,0 +1,458 @@ +# SPDX-License-Identifier: GPL-2.0 +# Copyright (c) 2019, Cristian Ciocaltea +# +# Work based on: +# - test_net.py +# Copyright (c) 2016, NVIDIA CORPORATION. All rights reserved. +# - test_fit.py +# Copyright (c) 2013, Google Inc. +# +# Test launching UEFI binaries from FIT images. + +import os.path +import pytest +import u_boot_utils as util + +""" +Note: This test relies on boardenv_* containing configuration values to define +which network environment is available for testing. Without this, the parts +that rely on network will be automatically skipped. + +For example: + +# Boolean indicating whether the Ethernet device is attached to USB, and hence +# USB enumeration needs to be performed prior to network tests. +# This variable may be omitted if its value is False. +env__net_uses_usb = False + +# Boolean indicating whether the Ethernet device is attached to PCI, and hence +# PCI enumeration needs to be performed prior to network tests. +# This variable may be omitted if its value is False. +env__net_uses_pci = True + +# True if a DHCP server is attached to the network, and should be tested. +# If DHCP testing is not possible or desired, this variable may be omitted or +# set to False. +env__net_dhcp_server = True + +# A list of environment variables that should be set in order to configure a +# static IP. If solely relying on DHCP, this variable may be omitted or set to +# an empty list. +env__net_static_env_vars = [ +('ipaddr', '10.0.0.100'), +('netmask', '255.255.255.0'), +('serverip', '10.0.0.1'), +] + +# Details regarding a file that may be read from a TFTP server. This variable +# may be omitted or set to None if TFTP testing is not possible or desired. +# Additionally, when the 'size' is not available, the file will be generated +# automatically in the TFTP root directory, as specified by the 'dn' field. +env__efi_fit_tftp_file = { +'fn': 'test-efi-fit.img', # File path relative to TFTP root +'size': 3831, # File size +'crc32': '9fa3f79c',# Checksum using CRC-32 algorithm, optional +'addr': 0x4040, # Loading address, integer, optional +'dn': 'tftp/root/dir', # TFTP root directory path, optional +} +""" + +# Define the parametrized ITS data to be used for FIT images generation. +its_data = ''' +/dts-v1/; + +/ { +description = "EFI image with FDT blob"; +#address-cells = <1>; + +images { +efi { +description = "Test EFI"; +data = /incbin/("%(efi-bin)s"); +type = "%(kernel-type)s"; +arch = "%(sys-arch)s"; +os = "efi"; +compression = "%(efi-comp)s"; +load = <0x0>; +entry = <0x0>; +}; +fdt { +description = "Test FDT"; +data = /incbin/("%(fdt-bin)s"); +type = "flat_dt"; +arch = "%(sys-arch)s"; +compression = "%(fdt-comp)s"; +}; +}; + +configurations { +default = "config-efi-fdt"; +config-efi-fdt { +description = "EFI FIT w/ FDT"; +kernel = "efi"; +fdt = "fdt"; +}; +config-efi-nofdt { +description = "EFI FIT w/o FDT"; +kernel = "efi"; +}; +}; +}; +''' + +# Define the parametrized FDT data to be used for DTB images generation. +fdt_data = ''' +/dts-v1/; + +/ { +#address-cells = <1>; +#size-cells = <0>; + +model = "%(sys-arch)s %(fdt_type)s EFI FIT Boot Test"; +compatible = "%(sys-arch)s"; + +reset@0 { +compatible = "%(sys-arch)s,reset"; +reg = <0>; +}; +}; +''' + +@pytest.mark.buildconfigspec('bootm_efi') +@pytest.mark.buildconfigspec('cmd_bootefi_hello_compile') +@pytest.mark.buildconfigspec('fit') +@pytest.mark.notbuildconfigspec('generate_acpi_table') +@pytest.mark.requiredtool('dtc') +def test_efi_fit_launch(u_boot_console): +"""Test handling of UEFI binaries inside FIT images. + +The tests are trying to launch U-Boot's helloworld.efi embedded into +FIT images, in uncompressed or gzip compressed format. + +Additionally, a sample FDT blob is created and embed
[PATCH v5 4/5] doc: uefi.rst: Document launching UEFI binaries from FIT images
This patch adds a new section "Launching a UEFI binary from a FIT image" documenting the usage of the CONFIG_BOOTM_EFI extension to bootm command that offers a verified boot alternative for UEFI binaries such as GRUB2. Signed-off-by: Cristian Ciocaltea Reviewed-by: Heinrich Schuchardt --- doc/uefi/uefi.rst | 34 ++ 1 file changed, 34 insertions(+) diff --git a/doc/uefi/uefi.rst b/doc/uefi/uefi.rst index db942df694..a8fd886d6b 100644 --- a/doc/uefi/uefi.rst +++ b/doc/uefi/uefi.rst @@ -63,6 +63,40 @@ The environment variable 'bootargs' is passed as load options in the UEFI system table. The Linux kernel EFI stub uses the load options as command line arguments. +Launching a UEFI binary from a FIT image + + +A signed FIT image can be used to securely boot a UEFI image via the +bootm command. This feature is available if U-Boot is configured with:: + +CONFIG_BOOTM_EFI=y + +A sample configuration is provided as file doc/uImage.FIT/uefi.its. + +Below you find the output of an example session starting GRUB:: + +=> load mmc 0:1 ${kernel_addr_r} image.fit +4620426 bytes read in 83 ms (53.1 MiB/s) +=> bootm ${kernel_addr_r}#config-grub-nofdt +## Loading kernel from FIT Image at 4040 ... + Using 'config-grub-nofdt' configuration + Verifying Hash Integrity ... sha256,rsa2048:dev+ OK + Trying 'efi-grub' kernel subimage + Description: GRUB EFI Firmware + Created: 2019-11-20 8:18:16 UTC + Type: Kernel Image (no loading done) + Compression: uncompressed + Data Start: 0x404000d0 + Data Size:450560 Bytes = 440 KiB + Hash algo:sha256 + Hash value: 4dbee00021112df618f58b3f7cf5e1595533d543094064b9ce991e8b054a9eec + Verifying Hash Integrity ... sha256+ OK + XIP Kernel Image (no loading done) +## Transferring control to EFI (at address 404000d0) ... +Welcome to GRUB! + +See doc/uImage.FIT/howto.txt for an introduction to FIT images. + Executing the boot manager ~~ -- 2.17.1
[PATCH v5 2/5] bootm: Add a bootm command for type IH_OS_EFI
Add support for booting EFI binaries contained in FIT images. A typical usage scenario is chain-loading GRUB2 in a verified boot environment. Signed-off-by: Cristian Ciocaltea Reviewed-by: Heinrich Schuchardt --- cmd/Kconfig | 7 ++ common/bootm_os.c | 56 +++ 2 files changed, 63 insertions(+) diff --git a/cmd/Kconfig b/cmd/Kconfig index 1e4cf146c5..4394bb8e51 100644 --- a/cmd/Kconfig +++ b/cmd/Kconfig @@ -251,6 +251,13 @@ config CMD_BOOTM help Boot an application image from the memory. +config BOOTM_EFI + bool "Support booting UEFI FIT images" + depends on CMD_BOOTEFI && CMD_BOOTM && FIT + default y + help + Support booting UEFI FIT images via the bootm command. + config CMD_BOOTZ bool "bootz" help diff --git a/common/bootm_os.c b/common/bootm_os.c index d89ddc32b0..1d58462509 100644 --- a/common/bootm_os.c +++ b/common/bootm_os.c @@ -7,10 +7,12 @@ #include #include #include +#include #include #include #include #include +#include #include #include @@ -498,6 +500,57 @@ static int do_bootm_tee(int flag, int argc, char * const argv[], } #endif +#ifdef CONFIG_BOOTM_EFI +static int do_bootm_efi(int flag, int argc, char * const argv[], + bootm_headers_t *images) +{ + int ret; + efi_status_t efi_ret; + void *image_buf; + + if (flag != BOOTM_STATE_OS_GO) + return 0; + + /* Locate FDT, if provided */ + ret = bootm_find_images(flag, argc, argv); + if (ret) + return ret; + + /* Initialize EFI drivers */ + efi_ret = efi_init_obj_list(); + if (efi_ret != EFI_SUCCESS) { + printf("## Failed to initialize UEFI sub-system: r = %lu\n", + efi_ret & ~EFI_ERROR_MASK); + return 1; + } + + /* Install device tree */ + efi_ret = efi_install_fdt(images->ft_len + ? images->ft_addr : EFI_FDT_USE_INTERNAL); + if (efi_ret != EFI_SUCCESS) { + printf("## Failed to install device tree: r = %lu\n", + efi_ret & ~EFI_ERROR_MASK); + return 1; + } + + /* Run EFI image */ + printf("## Transferring control to EFI (at address %08lx) ...\n", + images->ep); + bootstage_mark(BOOTSTAGE_ID_RUN_OS); + + image_buf = map_sysmem(images->ep, images->os.image_len); + + efi_ret = efi_run_image(image_buf, images->os.image_len); + if (efi_ret != EFI_SUCCESS) { + printf("## Failed to run EFI image: r = %lu\n", + efi_ret & ~EFI_ERROR_MASK); + return 1; + } + + return 0; +} +#endif + static boot_os_fn *boot_os[] = { [IH_OS_U_BOOT] = do_bootm_standalone, #ifdef CONFIG_BOOTM_LINUX @@ -534,6 +587,9 @@ static boot_os_fn *boot_os[] = { #ifdef CONFIG_BOOTM_OPTEE [IH_OS_TEE] = do_bootm_tee, #endif +#ifdef CONFIG_BOOTM_EFI + [IH_OS_EFI] = do_bootm_efi, +#endif }; /* Allow for arch specific config before we boot */ -- 2.17.1
[PATCH v5 0/5] Add support for booting EFI FIT images
Currently the only way to run an EFI binary like GRUB2 is via the 'bootefi' command, which cannot be used in a verified boot scenario. The obvious solution to this limitation is to add support for booting FIT images containing those EFI binaries. The implementation relies on a new image type - IH_OS_EFI - which can be created by using 'os = "efi"' inside an ITS file: / { #address-cells = <1>; images { efi-grub { description = "GRUB EFI"; data = /incbin/("bootarm.efi"); type = "kernel_noload"; arch = "arm"; os = "efi"; compression = "none"; load = <0x0>; entry = <0x0>; hash-1 { algo = "sha256"; }; }; }; configurations { default = "config-grub"; config-grub { kernel = "efi-grub"; signature-1 { algo = "sha256,rsa2048"; sign-images = "kernel"; }; }; }; }; The bootm command has been extended to handle the IH_OS_EFI images. To enable this feature, a new configuration option has been added: BOOTM_EFI I tested the solution using the 'qemu_arm' board: => load scsi 0:1 ${kernel_addr_r} efi-image.fit => bootm ${kernel_addr_r}#config-grub Changes in v5: * Update the definition of BOOTM_EFI: move content right after CMD_BOOTM, improve description and help text, fix dependency * Change the type of the 'addr' field inside 'env__efi_fit_tftp_file' dictionary from string to integer, currently tested on: sandbox, qemu_arm, qemu_arm64 Changes in v4: * Extend the python test to also run on real hardware, currently tested on qemu_arm Changes in v3: * Rebase patches on Heinrich Schuchardt's patch series v3: efi_loader: prepare for FIT images https://lists.denx.de/pipermail/u-boot/2019-December/393677.html This fixes implicitly the sandbox issue 'phys_to_virt: Cannot map sandbox address' since efi_install_fdt() is now expecting a pointer to addressable memory instead of a physical address. * Get rid of 'EFI/BOOT/' prefix used in ITS samples * Add a python test to verify the implementation in sandbox environment Changes in v2: * Rebase patches on Heinrich Schuchardt's patch series: efi_loader: prepare for FIT images https://lists.denx.de/pipermail/u-boot/2019-December/393192.html * Add sample configuration: doc/uImage.FIT/uefi.its * Update uefi documentation: doc/uefi/uefi.rst Cristian Ciocaltea (5): image: Add IH_OS_EFI for EFI chain-load boot bootm: Add a bootm command for type IH_OS_EFI doc: Add sample uefi.its image description file doc: uefi.rst: Document launching UEFI binaries from FIT images test/py: Create a test for launching UEFI binaries from FIT images cmd/Kconfig | 7 + common/bootm_os.c | 56 + common/image-fit.c| 3 +- common/image.c| 1 + doc/uImage.FIT/uefi.its | 67 + doc/uefi/uefi.rst | 34 +++ include/image.h | 1 + test/py/tests/test_efi_fit.py | 458 ++ 8 files changed, 626 insertions(+), 1 deletion(-) create mode 100644 doc/uImage.FIT/uefi.its create mode 100644 test/py/tests/test_efi_fit.py -- 2.17.1
[PATCH v5 3/5] doc: Add sample uefi.its image description file
This patch adds an example FIT image description file demonstrating the usage of bootm command to securely launch UEFI binaries. Signed-off-by: Cristian Ciocaltea Reviewed-by: Heinrich Schuchardt --- doc/uImage.FIT/uefi.its | 67 + 1 file changed, 67 insertions(+) create mode 100644 doc/uImage.FIT/uefi.its diff --git a/doc/uImage.FIT/uefi.its b/doc/uImage.FIT/uefi.its new file mode 100644 index 00..378ca4ed8d --- /dev/null +++ b/doc/uImage.FIT/uefi.its @@ -0,0 +1,67 @@ +/* + * Example FIT image description file demonstrating the usage of the + * bootm command to launch UEFI binaries. + * + * Two boot configurations are available to enable booting GRUB2 on QEMU, + * the former uses a FDT blob contained in the FIT image, while the later + * relies on the FDT provided by the board emulator. + */ + +/dts-v1/; + +/ { + description = "GRUB2 EFI and QEMU FDT blob"; + #address-cells = <1>; + + images { + efi-grub { + description = "GRUB EFI Firmware"; + data = /incbin/("bootarm.efi"); + type = "kernel_noload"; + arch = "arm"; + os = "efi"; + compression = "none"; + load = <0x0>; + entry = <0x0>; + hash-1 { + algo = "sha256"; + }; + }; + + fdt-qemu { + description = "QEMU DTB"; + data = /incbin/("qemu-arm.dtb"); + type = "flat_dt"; + arch = "arm"; + compression = "none"; + hash-1 { + algo = "sha256"; + }; + }; + }; + + configurations { + default = "config-grub-fdt"; + + config-grub-fdt { + description = "GRUB EFI Boot w/ FDT"; + kernel = "efi-grub"; + fdt = "fdt-qemu"; + signature-1 { + algo = "sha256,rsa2048"; + key-name-hint = "dev"; + sign-images = "kernel", "fdt"; + }; + }; + + config-grub-nofdt { + description = "GRUB EFI Boot w/o FDT"; + kernel = "efi-grub"; + signature-1 { + algo = "sha256,rsa2048"; + key-name-hint = "dev"; + sign-images = "kernel"; + }; + }; + }; +}; -- 2.17.1
[PATCH v1 1/1] travis-ci: Fix "ResourceWarning: unclosed file"
This patch gets rid of the warning messages like: uboot-test-hooks/py/travis-ci/travis_tftp.py:43: ResourceWarning: unclosed file <_io.BufferedReader name='.bm-work/qemu_arm/u-boot.bin'> Signed-off-by: Cristian Ciocaltea --- py/travis-ci/travis_tftp.py | 5 - 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/py/travis-ci/travis_tftp.py b/py/travis-ci/travis_tftp.py index 4ea5c06..3e1f11d 100644 --- a/py/travis-ci/travis_tftp.py +++ b/py/travis-ci/travis_tftp.py @@ -20,8 +20,11 @@ def file2env(file_name, addr=None): ret = { "fn": file_name, "size": os.path.getsize(file_full), -"crc32": hex(binascii.crc32(open(file_full, 'rb').read()) & 0x)[2:], } + +with open(file_full, 'rb') as fd: +ret["crc32"] = hex(binascii.crc32(fd.read()) & 0x)[2:] + if addr is not None: ret['addr'] = addr -- 2.17.1
Re: [PATCH v4 5/5] test/py: Create a test for launching UEFI binaries from FIT images
On Sun, Dec 29, 2019 at 08:11:10PM +0100, Heinrich Schuchardt wrote: > On 12/29/19 7:39 PM, Cristian Ciocaltea wrote: > > On Sun, Dec 29, 2019 at 11:22:08AM +0100, Heinrich Schuchardt wrote: > > > On 12/24/19 5:05 PM, Cristian Ciocaltea wrote: > > > > This test verifies the implementation of the 'bootm' extension that > > > > handles UEFI binaries inside FIT images (enabled via CONFIG_BOOTM_EFI). > > > > > > > > Signed-off-by: Cristian Ciocaltea > > > > > > Thanks a lot for devising this test. > > > > > > --- > > > > > > You are using variable env__efi_fit_tftp_file. To run the test on Gitlab > > > and Travis CI a patch will be needed for: > > > > > > https://github.com/swarren/uboot-test-hooks.git > > > > > > I hope > > > > > > https://github.com/xypron/uboot-test-hooks/commit/20dcd721437dd5f7d7d3d235f7112246f43305d2 > > > > > > will do the job. > > > > > > Once we have this applied we will have to adjust the config files for > > > QEMU. > > > > > > --- > > > > > > I have been trying to run the test on qemu_arm64_defconfig using the > > > following lines in u_boot_boardenv_qemu_arm64.py: > > > > > > env__efi_fit_tftp_file = { > > > "fn": "helloworld.efi", > > > "size": 4480, > > > "crc32": "19f9c0ab", > > > } > > > > > > I got an error: > > > > > > test/py/tests/test_efi_fit.py:417: in launch_efi > > > addr = load_fit_from_host(fit) if is_sandbox else > > > load_fit_from_tftp(fit) > > > _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ > > > addr = f.get('addr', None) > > > if not addr: > > > >addr = u_boot_utils.find_ram_base(cons) > > > E NameError: name 'u_boot_utils' is not defined > > > > > > > > > When I provided addr: > > > > > > env__efi_fit_tftp_file = { > > > "fn": "helloworld.efi", > > > "size": 4480, > > > "crc32": "19f9c0ab", > > > "addr": 0x4040, > > > } > > > > > > I got the following error: > > > > > > => tftpboot 1073741824 helloworld.efi > > > TFTP error: trying to overwrite reserved memory... > > > > > > I would have expected a command > > > > > > tftpboot 4040 helloworld.efi > > > > > > to be issued. > > > > > > Same error with bootm: > > > > > > => bootm 1077936128#config-efi-nofdt > > > "Synchronous Abort" handler, esr 0x9610 > > > elr: 0001c36c lr : 000140f4 (reloc) > > > > > > Please, fix the lines indicated below and verify that you can actually > > > execute this test on the QEMU platform. > > > > Thank you for the detailed report! > > > > Unfortunately I have only tested on qemu_arm and somehow I missed the > > check of having the address computed by the test suite. It used to work > > before I changed the address data type to string - the reason was to > > allow for more flexibility, e.g. providing values like '$kernel_addr_r' > > instead of just precomputed numbers. > > > > I'm going to extend the tests on qemu_arm64 as well. > > > > > > > > https://github.com/xypron/u-boot-build/tree/qemu-arm64/u-boot-test > > > > > > contains the files I use to run Python tests on qemu_arm64_defconfig. > > > > > > > --- > > > >test/py/tests/test_efi_fit.py | 459 > > > > ++ > > > >1 file changed, 459 insertions(+) > > > >create mode 100644 test/py/tests/test_efi_fit.py > > > > > > > > diff --git a/test/py/tests/test_efi_fit.py > > > > b/test/py/tests/test_efi_fit.py > > > > new file mode 100644 > > > > index 00..e1f0e42694 > > > > --- /dev/null > > > > +++ b/test/py/tests/test_efi_fit.py > > > > @@ -0,0 +1,459 @@ > > > > +# SPDX-License-Identifier: GPL-2.0 > > > > +# Copyright (c) 2019, Cristian Ciocaltea > > > > +# > > > > +# Work based on: > > > > +# - test_net.py > > > > +# Copyright (c) 2016, NVIDIA CORPORATI
Re: [PATCH v4 5/5] test/py: Create a test for launching UEFI binaries from FIT images
On Sun, Dec 29, 2019 at 11:22:08AM +0100, Heinrich Schuchardt wrote: > On 12/24/19 5:05 PM, Cristian Ciocaltea wrote: > > This test verifies the implementation of the 'bootm' extension that > > handles UEFI binaries inside FIT images (enabled via CONFIG_BOOTM_EFI). > > > > Signed-off-by: Cristian Ciocaltea > > Thanks a lot for devising this test. > > --- > > You are using variable env__efi_fit_tftp_file. To run the test on Gitlab > and Travis CI a patch will be needed for: > > https://github.com/swarren/uboot-test-hooks.git > > I hope > > https://github.com/xypron/uboot-test-hooks/commit/20dcd721437dd5f7d7d3d235f7112246f43305d2 > > will do the job. > > Once we have this applied we will have to adjust the config files for QEMU. > > --- > > I have been trying to run the test on qemu_arm64_defconfig using the > following lines in u_boot_boardenv_qemu_arm64.py: > > env__efi_fit_tftp_file = { > "fn": "helloworld.efi", > "size": 4480, > "crc32": "19f9c0ab", > } > > I got an error: > > test/py/tests/test_efi_fit.py:417: in launch_efi > addr = load_fit_from_host(fit) if is_sandbox else > load_fit_from_tftp(fit) > _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ > addr = f.get('addr', None) > if not addr: > > addr = u_boot_utils.find_ram_base(cons) > E NameError: name 'u_boot_utils' is not defined > > > When I provided addr: > > env__efi_fit_tftp_file = { > "fn": "helloworld.efi", > "size": 4480, > "crc32": "19f9c0ab", > "addr": 0x4040, > } > > I got the following error: > > => tftpboot 1073741824 helloworld.efi > TFTP error: trying to overwrite reserved memory... > > I would have expected a command > > tftpboot 4040 helloworld.efi > > to be issued. > > Same error with bootm: > > => bootm 1077936128#config-efi-nofdt > "Synchronous Abort" handler, esr 0x9610 > elr: 0001c36c lr : 000140f4 (reloc) > > Please, fix the lines indicated below and verify that you can actually > execute this test on the QEMU platform. Thank you for the detailed report! Unfortunately I have only tested on qemu_arm and somehow I missed the check of having the address computed by the test suite. It used to work before I changed the address data type to string - the reason was to allow for more flexibility, e.g. providing values like '$kernel_addr_r' instead of just precomputed numbers. I'm going to extend the tests on qemu_arm64 as well. > > https://github.com/xypron/u-boot-build/tree/qemu-arm64/u-boot-test > > contains the files I use to run Python tests on qemu_arm64_defconfig. > > > --- > > test/py/tests/test_efi_fit.py | 459 ++ > > 1 file changed, 459 insertions(+) > > create mode 100644 test/py/tests/test_efi_fit.py > > > > diff --git a/test/py/tests/test_efi_fit.py b/test/py/tests/test_efi_fit.py > > new file mode 100644 > > index 00..e1f0e42694 > > --- /dev/null > > +++ b/test/py/tests/test_efi_fit.py > > @@ -0,0 +1,459 @@ > > +# SPDX-License-Identifier: GPL-2.0 > > +# Copyright (c) 2019, Cristian Ciocaltea > > +# > > +# Work based on: > > +# - test_net.py > > +# Copyright (c) 2016, NVIDIA CORPORATION. All rights reserved. > > +# - test_fit.py > > +# Copyright (c) 2013, Google Inc. > > +# > > +# Test launching UEFI binaries from FIT images. > > + > > +import os.path > > +import pytest > > +import u_boot_utils as util > > "as util" causes an error if you use u_boot_utils.* below. Below I > indicate the places to change. Fixed, thanks. > > + > > +""" > > +Note: This test relies on boardenv_* containing configuration values to > > define > > +which network environment is available for testing. Without this, the parts > > +that rely on network will be automatically skipped. > > + > > +For example: > > + > > +# Boolean indicating whether the Ethernet device is attached to USB, and > > hence > > +# USB enumeration needs to be performed prior to network tests. > > +# This variable may be omitted if its value is False. > > +env__net_uses_usb = False > > + > > +# Boolean indicating whether the Ethernet device is attached to PCI, and > > hence > > +# PCI enumeration needs to be performed prior to network tests. > > +# This variable may be omitted if its value is False. &
Re: [PATCH v4 2/5] bootm: Add a bootm command for type IH_OS_EFI
On Sun, Dec 29, 2019 at 11:56:01AM +0100, Heinrich Schuchardt wrote: > On 12/29/19 11:34 AM, Heinrich Schuchardt wrote: > > On 12/24/19 5:05 PM, Cristian Ciocaltea wrote: > > > Add support for booting EFI binaries contained in FIT images. > > > A typical usage scenario is chain-loading GRUB2 in a verified > > > boot environment. > > > > > > Signed-off-by: Cristian Ciocaltea > > > Reviewed-by: Heinrich Schuchardt > > > --- > > > cmd/Kconfig | 7 ++ > > > common/bootm_os.c | 56 +++ > > > 2 files changed, 63 insertions(+) > > > > > > diff --git a/cmd/Kconfig b/cmd/Kconfig > > > index 1e4cf146c5..87f2335a3c 100644 > > > --- a/cmd/Kconfig > > > +++ b/cmd/Kconfig > > > @@ -263,6 +263,13 @@ config CMD_BOOTI > > > help > > > Boot an AArch64 Linux Kernel image from memory. > > > > > > +config BOOTM_EFI > > > + bool "Support booting EFI OS images" > > > > Shouldn't this be "Support booting UEFI FIT images"? > > > > > + depends on CMD_BOOTEFI > > > > depends on BOOTM > > depends on CMD_BOOTM > > The patch series compiles without CONFIG_FIT. But shouldn't this also be > a dependency? Indeed, thanks. > If we place the definition directly after CMD_BOOTM, it will be indented > so that it is evident that this is a sub-feature of CMD_BOOTM. > > So how about the following? > > config CMD_BOOTM > bool "bootm" > default y > help > Boot an application image from the memory. > > config BOOTM_EFI > bool "Support booting UEFI FIT images" > depends on CMD_BOOTEFI && CMD_BOOTM && FIT > default y > help > Support booting UEFI FIT images via the bootm command. In this case, we should probably also move CMD_BOOTZ, CMD_BOOTI and BOOTM_LINUX right after CMD_BOOTEFI_HELLO, since those commands do not depend on CMD_BOOTM, while all BOOTM_* features, except BOOTM_LINUX, depend exclusively on CMD_BOOTM. > Best regards > > Heinrich > > > > > is missing here. > > > > > + default y > > > + help > > > + Support booting EFI images via the bootm command. > > > > Should we say: > > > > Support booting UEFI FIT images via the bootm command. > > > > Best regards > > > > Heinrich > > > > > + > > > config BOOTM_LINUX > > > bool "Support booting Linux OS images" > > > depends on CMD_BOOTM || CMD_BOOTZ || CMD_BOOTI > > > diff --git a/common/bootm_os.c b/common/bootm_os.c > > > index d89ddc32b0..1d58462509 100644 > > > --- a/common/bootm_os.c > > > +++ b/common/bootm_os.c > > > @@ -7,10 +7,12 @@ > > > #include > > > #include > > > #include > > > +#include > > > #include > > > #include > > > #include > > > #include > > > +#include > > > #include > > > #include > > > > > > @@ -498,6 +500,57 @@ static int do_bootm_tee(int flag, int argc, char > > > * const argv[], > > > } > > > #endif > > > > > > +#ifdef CONFIG_BOOTM_EFI > > > +static int do_bootm_efi(int flag, int argc, char * const argv[], > > > + bootm_headers_t *images) > > > +{ > > > + int ret; > > > + efi_status_t efi_ret; > > > + void *image_buf; > > > + > > > + if (flag != BOOTM_STATE_OS_GO) > > > + return 0; > > > + > > > + /* Locate FDT, if provided */ > > > + ret = bootm_find_images(flag, argc, argv); > > > + if (ret) > > > + return ret; > > > + > > > + /* Initialize EFI drivers */ > > > + efi_ret = efi_init_obj_list(); > > > + if (efi_ret != EFI_SUCCESS) { > > > + printf("## Failed to initialize UEFI sub-system: r = %lu\n", > > > + efi_ret & ~EFI_ERROR_MASK); > > > + return 1; > > > + } > > > + > > > + /* Install device tree */ > > > + efi_ret = efi_install_fdt(images->ft_len > > > + ? images->ft_addr : EFI_FDT_USE_INTERNAL); > > > + if (efi_ret != EFI_SUCCESS) { > > > + printf("## Failed to install device tree: r = %lu\n", > > > +
Re: [PATCH v4 2/5] bootm: Add a bootm command for type IH_OS_EFI
On Sun, Dec 29, 2019 at 11:34:09AM +0100, Heinrich Schuchardt wrote: > On 12/24/19 5:05 PM, Cristian Ciocaltea wrote: > > Add support for booting EFI binaries contained in FIT images. > > A typical usage scenario is chain-loading GRUB2 in a verified > > boot environment. > > > > Signed-off-by: Cristian Ciocaltea > > Reviewed-by: Heinrich Schuchardt > > --- > > cmd/Kconfig | 7 ++ > > common/bootm_os.c | 56 +++ > > 2 files changed, 63 insertions(+) > > > > diff --git a/cmd/Kconfig b/cmd/Kconfig > > index 1e4cf146c5..87f2335a3c 100644 > > --- a/cmd/Kconfig > > +++ b/cmd/Kconfig > > @@ -263,6 +263,13 @@ config CMD_BOOTI > > help > > Boot an AArch64 Linux Kernel image from memory. > > > > +config BOOTM_EFI > > + bool "Support booting EFI OS images" > > Shouldn't this be "Support booting UEFI FIT images"? Done. > > + depends on CMD_BOOTEFI > > depends on BOOTM > > is missing here. Right, thanks. Added 'CMD_BOOTEFI && CMD_BOOTM'. > > + default y > > + help > > + Support booting EFI images via the bootm command. > > Should we say: > > Support booting UEFI FIT images via the bootm command. Done. > Best regards > > Heinrich > > > + > > config BOOTM_LINUX > > bool "Support booting Linux OS images" > > depends on CMD_BOOTM || CMD_BOOTZ || CMD_BOOTI > > diff --git a/common/bootm_os.c b/common/bootm_os.c > > index d89ddc32b0..1d58462509 100644 > > --- a/common/bootm_os.c > > +++ b/common/bootm_os.c > > @@ -7,10 +7,12 @@ > > #include > > #include > > #include > > +#include > > #include > > #include > > #include > > #include > > +#include > > #include > > #include > > > > @@ -498,6 +500,57 @@ static int do_bootm_tee(int flag, int argc, char * > > const argv[], > > } > > #endif > > > > +#ifdef CONFIG_BOOTM_EFI > > +static int do_bootm_efi(int flag, int argc, char * const argv[], > > + bootm_headers_t *images) > > +{ > > + int ret; > > + efi_status_t efi_ret; > > + void *image_buf; > > + > > + if (flag != BOOTM_STATE_OS_GO) > > + return 0; > > + > > + /* Locate FDT, if provided */ > > + ret = bootm_find_images(flag, argc, argv); > > + if (ret) > > + return ret; > > + > > + /* Initialize EFI drivers */ > > + efi_ret = efi_init_obj_list(); > > + if (efi_ret != EFI_SUCCESS) { > > + printf("## Failed to initialize UEFI sub-system: r = %lu\n", > > + efi_ret & ~EFI_ERROR_MASK); > > + return 1; > > + } > > + > > + /* Install device tree */ > > + efi_ret = efi_install_fdt(images->ft_len > > + ? images->ft_addr : EFI_FDT_USE_INTERNAL); > > + if (efi_ret != EFI_SUCCESS) { > > + printf("## Failed to install device tree: r = %lu\n", > > + efi_ret & ~EFI_ERROR_MASK); > > + return 1; > > + } > > + > > + /* Run EFI image */ > > + printf("## Transferring control to EFI (at address %08lx) ...\n", > > + images->ep); > > + bootstage_mark(BOOTSTAGE_ID_RUN_OS); > > + > > + image_buf = map_sysmem(images->ep, images->os.image_len); > > + > > + efi_ret = efi_run_image(image_buf, images->os.image_len); > > + if (efi_ret != EFI_SUCCESS) { > > + printf("## Failed to run EFI image: r = %lu\n", > > + efi_ret & ~EFI_ERROR_MASK); > > + return 1; > > + } > > + > > + return 0; > > +} > > +#endif > > + > > static boot_os_fn *boot_os[] = { > > [IH_OS_U_BOOT] = do_bootm_standalone, > > #ifdef CONFIG_BOOTM_LINUX > > @@ -534,6 +587,9 @@ static boot_os_fn *boot_os[] = { > > #ifdef CONFIG_BOOTM_OPTEE > > [IH_OS_TEE] = do_bootm_tee, > > #endif > > +#ifdef CONFIG_BOOTM_EFI > > + [IH_OS_EFI] = do_bootm_efi, > > +#endif > > }; > > > > /* Allow for arch specific config before we boot */ > > >
[PATCH v4 5/5] test/py: Create a test for launching UEFI binaries from FIT images
This test verifies the implementation of the 'bootm' extension that handles UEFI binaries inside FIT images (enabled via CONFIG_BOOTM_EFI). Signed-off-by: Cristian Ciocaltea --- test/py/tests/test_efi_fit.py | 459 ++ 1 file changed, 459 insertions(+) create mode 100644 test/py/tests/test_efi_fit.py diff --git a/test/py/tests/test_efi_fit.py b/test/py/tests/test_efi_fit.py new file mode 100644 index 00..e1f0e42694 --- /dev/null +++ b/test/py/tests/test_efi_fit.py @@ -0,0 +1,459 @@ +# SPDX-License-Identifier: GPL-2.0 +# Copyright (c) 2019, Cristian Ciocaltea +# +# Work based on: +# - test_net.py +# Copyright (c) 2016, NVIDIA CORPORATION. All rights reserved. +# - test_fit.py +# Copyright (c) 2013, Google Inc. +# +# Test launching UEFI binaries from FIT images. + +import os.path +import pytest +import u_boot_utils as util + +""" +Note: This test relies on boardenv_* containing configuration values to define +which network environment is available for testing. Without this, the parts +that rely on network will be automatically skipped. + +For example: + +# Boolean indicating whether the Ethernet device is attached to USB, and hence +# USB enumeration needs to be performed prior to network tests. +# This variable may be omitted if its value is False. +env__net_uses_usb = False + +# Boolean indicating whether the Ethernet device is attached to PCI, and hence +# PCI enumeration needs to be performed prior to network tests. +# This variable may be omitted if its value is False. +env__net_uses_pci = True + +# True if a DHCP server is attached to the network, and should be tested. +# If DHCP testing is not possible or desired, this variable may be omitted or +# set to False. +env__net_dhcp_server = True + +# A list of environment variables that should be set in order to configure a +# static IP. If solely relying on DHCP, this variable may be omitted or set to +# an empty list. +env__net_static_env_vars = [ +('ipaddr', '10.0.0.100'), +('netmask', '255.255.255.0'), +('serverip', '10.0.0.1'), +] + +# Details regarding a file that may be read from a TFTP server. This variable +# may be omitted or set to None if TFTP testing is not possible or desired. +# Additionally, when the 'size' is not available, the file will be generated +# automatically in the TFTP root directory, as specified by the 'dn' field. +env__efi_fit_tftp_file = { +'fn': 'test-efi-fit.img', # File path relative to TFTP root +'size': 3831, # File size +'crc32': '9fa3f79c',# Checksum using CRC-32 algorithm, optional +'addr': '$kernel_addr_r', # Loading address, optional +'dn': 'tftp/root/dir', # TFTP root directory path, optional +} +""" + +# Define the parametrized ITS data to be used for FIT images generation. +its_data = ''' +/dts-v1/; + +/ { +description = "EFI image with FDT blob"; +#address-cells = <1>; + +images { +efi { +description = "Test EFI"; +data = /incbin/("%(efi-bin)s"); +type = "%(kernel-type)s"; +arch = "%(sys-arch)s"; +os = "efi"; +compression = "%(efi-comp)s"; +load = <0x0>; +entry = <0x0>; +}; +fdt { +description = "Test FDT"; +data = /incbin/("%(fdt-bin)s"); +type = "flat_dt"; +arch = "%(sys-arch)s"; +compression = "%(fdt-comp)s"; +}; +}; + +configurations { +default = "config-efi-fdt"; +config-efi-fdt { +description = "EFI FIT w/ FDT"; +kernel = "efi"; +fdt = "fdt"; +}; +config-efi-nofdt { +description = "EFI FIT w/o FDT"; +kernel = "efi"; +}; +}; +}; +''' + +# Define the parametrized FDT data to be used for DTB images generation. +fdt_data = ''' +/dts-v1/; + +/ { +#address-cells = <1>; +#size-cells = <0>; + +model = "%(sys-arch)s %(fdt_type)s EFI FIT Boot Test"; +compatible = "%(sys-arch)s"; + +reset@0 { +compatible = "%(sys-arch)s,reset"; +reg = <0>; +}; +}; +''' + +@pytest.mark.buildconfigspec('bootm_efi') +@pytest.mark.buildconfigspec('cmd_bootefi_hello_compile') +@pytest.mark.buildconfigspec('fit') +@pytest.mark.notbuildconfigspec('generate_acpi_table') +@pytest.mark.requiredtool('dtc') +def test_efi_fit_launch(u_boot_console): +"""Test handling of UEFI binaries inside FIT images. + +The tests are trying to launch U-Boot's helloworld.efi embedded into +FIT images, in uncompressed or gzip compressed format. + +Additionally, a sample FDT blob is created and embedded
[PATCH v4 4/5] doc: uefi.rst: Document launching UEFI binaries from FIT images
This patch adds a new section "Launching a UEFI binary from a FIT image" documenting the usage of the CONFIG_BOOTM_EFI extension to bootm command that offers a verified boot alternative for UEFI binaries such as GRUB2. Signed-off-by: Cristian Ciocaltea Reviewed-by: Heinrich Schuchardt --- doc/uefi/uefi.rst | 34 ++ 1 file changed, 34 insertions(+) diff --git a/doc/uefi/uefi.rst b/doc/uefi/uefi.rst index db942df694..a8fd886d6b 100644 --- a/doc/uefi/uefi.rst +++ b/doc/uefi/uefi.rst @@ -63,6 +63,40 @@ The environment variable 'bootargs' is passed as load options in the UEFI system table. The Linux kernel EFI stub uses the load options as command line arguments. +Launching a UEFI binary from a FIT image + + +A signed FIT image can be used to securely boot a UEFI image via the +bootm command. This feature is available if U-Boot is configured with:: + +CONFIG_BOOTM_EFI=y + +A sample configuration is provided as file doc/uImage.FIT/uefi.its. + +Below you find the output of an example session starting GRUB:: + +=> load mmc 0:1 ${kernel_addr_r} image.fit +4620426 bytes read in 83 ms (53.1 MiB/s) +=> bootm ${kernel_addr_r}#config-grub-nofdt +## Loading kernel from FIT Image at 4040 ... + Using 'config-grub-nofdt' configuration + Verifying Hash Integrity ... sha256,rsa2048:dev+ OK + Trying 'efi-grub' kernel subimage + Description: GRUB EFI Firmware + Created: 2019-11-20 8:18:16 UTC + Type: Kernel Image (no loading done) + Compression: uncompressed + Data Start: 0x404000d0 + Data Size:450560 Bytes = 440 KiB + Hash algo:sha256 + Hash value: 4dbee00021112df618f58b3f7cf5e1595533d543094064b9ce991e8b054a9eec + Verifying Hash Integrity ... sha256+ OK + XIP Kernel Image (no loading done) +## Transferring control to EFI (at address 404000d0) ... +Welcome to GRUB! + +See doc/uImage.FIT/howto.txt for an introduction to FIT images. + Executing the boot manager ~~ -- 2.17.1
[PATCH v4 3/5] doc: Add sample uefi.its image description file
This patch adds an example FIT image description file demonstrating the usage of bootm command to securely launch UEFI binaries. Signed-off-by: Cristian Ciocaltea Reviewed-by: Heinrich Schuchardt --- doc/uImage.FIT/uefi.its | 67 + 1 file changed, 67 insertions(+) create mode 100644 doc/uImage.FIT/uefi.its diff --git a/doc/uImage.FIT/uefi.its b/doc/uImage.FIT/uefi.its new file mode 100644 index 00..378ca4ed8d --- /dev/null +++ b/doc/uImage.FIT/uefi.its @@ -0,0 +1,67 @@ +/* + * Example FIT image description file demonstrating the usage of the + * bootm command to launch UEFI binaries. + * + * Two boot configurations are available to enable booting GRUB2 on QEMU, + * the former uses a FDT blob contained in the FIT image, while the later + * relies on the FDT provided by the board emulator. + */ + +/dts-v1/; + +/ { + description = "GRUB2 EFI and QEMU FDT blob"; + #address-cells = <1>; + + images { + efi-grub { + description = "GRUB EFI Firmware"; + data = /incbin/("bootarm.efi"); + type = "kernel_noload"; + arch = "arm"; + os = "efi"; + compression = "none"; + load = <0x0>; + entry = <0x0>; + hash-1 { + algo = "sha256"; + }; + }; + + fdt-qemu { + description = "QEMU DTB"; + data = /incbin/("qemu-arm.dtb"); + type = "flat_dt"; + arch = "arm"; + compression = "none"; + hash-1 { + algo = "sha256"; + }; + }; + }; + + configurations { + default = "config-grub-fdt"; + + config-grub-fdt { + description = "GRUB EFI Boot w/ FDT"; + kernel = "efi-grub"; + fdt = "fdt-qemu"; + signature-1 { + algo = "sha256,rsa2048"; + key-name-hint = "dev"; + sign-images = "kernel", "fdt"; + }; + }; + + config-grub-nofdt { + description = "GRUB EFI Boot w/o FDT"; + kernel = "efi-grub"; + signature-1 { + algo = "sha256,rsa2048"; + key-name-hint = "dev"; + sign-images = "kernel"; + }; + }; + }; +}; -- 2.17.1
[PATCH v4 2/5] bootm: Add a bootm command for type IH_OS_EFI
Add support for booting EFI binaries contained in FIT images. A typical usage scenario is chain-loading GRUB2 in a verified boot environment. Signed-off-by: Cristian Ciocaltea Reviewed-by: Heinrich Schuchardt --- cmd/Kconfig | 7 ++ common/bootm_os.c | 56 +++ 2 files changed, 63 insertions(+) diff --git a/cmd/Kconfig b/cmd/Kconfig index 1e4cf146c5..87f2335a3c 100644 --- a/cmd/Kconfig +++ b/cmd/Kconfig @@ -263,6 +263,13 @@ config CMD_BOOTI help Boot an AArch64 Linux Kernel image from memory. +config BOOTM_EFI + bool "Support booting EFI OS images" + depends on CMD_BOOTEFI + default y + help + Support booting EFI images via the bootm command. + config BOOTM_LINUX bool "Support booting Linux OS images" depends on CMD_BOOTM || CMD_BOOTZ || CMD_BOOTI diff --git a/common/bootm_os.c b/common/bootm_os.c index d89ddc32b0..1d58462509 100644 --- a/common/bootm_os.c +++ b/common/bootm_os.c @@ -7,10 +7,12 @@ #include #include #include +#include #include #include #include #include +#include #include #include @@ -498,6 +500,57 @@ static int do_bootm_tee(int flag, int argc, char * const argv[], } #endif +#ifdef CONFIG_BOOTM_EFI +static int do_bootm_efi(int flag, int argc, char * const argv[], + bootm_headers_t *images) +{ + int ret; + efi_status_t efi_ret; + void *image_buf; + + if (flag != BOOTM_STATE_OS_GO) + return 0; + + /* Locate FDT, if provided */ + ret = bootm_find_images(flag, argc, argv); + if (ret) + return ret; + + /* Initialize EFI drivers */ + efi_ret = efi_init_obj_list(); + if (efi_ret != EFI_SUCCESS) { + printf("## Failed to initialize UEFI sub-system: r = %lu\n", + efi_ret & ~EFI_ERROR_MASK); + return 1; + } + + /* Install device tree */ + efi_ret = efi_install_fdt(images->ft_len + ? images->ft_addr : EFI_FDT_USE_INTERNAL); + if (efi_ret != EFI_SUCCESS) { + printf("## Failed to install device tree: r = %lu\n", + efi_ret & ~EFI_ERROR_MASK); + return 1; + } + + /* Run EFI image */ + printf("## Transferring control to EFI (at address %08lx) ...\n", + images->ep); + bootstage_mark(BOOTSTAGE_ID_RUN_OS); + + image_buf = map_sysmem(images->ep, images->os.image_len); + + efi_ret = efi_run_image(image_buf, images->os.image_len); + if (efi_ret != EFI_SUCCESS) { + printf("## Failed to run EFI image: r = %lu\n", + efi_ret & ~EFI_ERROR_MASK); + return 1; + } + + return 0; +} +#endif + static boot_os_fn *boot_os[] = { [IH_OS_U_BOOT] = do_bootm_standalone, #ifdef CONFIG_BOOTM_LINUX @@ -534,6 +587,9 @@ static boot_os_fn *boot_os[] = { #ifdef CONFIG_BOOTM_OPTEE [IH_OS_TEE] = do_bootm_tee, #endif +#ifdef CONFIG_BOOTM_EFI + [IH_OS_EFI] = do_bootm_efi, +#endif }; /* Allow for arch specific config before we boot */ -- 2.17.1
[PATCH v4 1/5] image: Add IH_OS_EFI for EFI chain-load boot
Add a new OS type to be used for chain-loading an EFI compatible firmware or boot loader like GRUB2, possibly in a verified boot scenario. Bellow is sample ITS file that generates a FIT image supporting secure boot. Please note the presence of 'os = "efi";' line, which identifies the currently introduced OS type: / { #address-cells = <1>; images { efi-grub { description = "GRUB EFI"; data = /incbin/("bootarm.efi"); type = "kernel_noload"; arch = "arm"; os = "efi"; compression = "none"; load = <0x0>; entry = <0x0>; hash-1 { algo = "sha256"; }; }; }; configurations { default = "config-grub"; config-grub { kernel = "efi-grub"; signature-1 { algo = "sha256,rsa2048"; sign-images = "kernel"; }; }; }; }; Signed-off-by: Cristian Ciocaltea Reviewed-by: Heinrich Schuchardt --- common/image-fit.c | 3 ++- common/image.c | 1 + include/image.h| 1 + 3 files changed, 4 insertions(+), 1 deletion(-) diff --git a/common/image-fit.c b/common/image-fit.c index c52f945120..231612ff5f 100644 --- a/common/image-fit.c +++ b/common/image-fit.c @@ -1926,7 +1926,8 @@ int fit_image_load(bootm_headers_t *images, ulong addr, image_type == 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); + fit_image_check_os(fit, noffset, IH_OS_OPENRTOS) || + fit_image_check_os(fit, noffset, IH_OS_EFI); /* * If either of the checks fail, we should report an error, but diff --git a/common/image.c b/common/image.c index eb626dcac9..75d5dd944f 100644 --- a/common/image.c +++ b/common/image.c @@ -137,6 +137,7 @@ static const table_entry_t uimage_os[] = { { IH_OS_OPENRTOS, "openrtos", "OpenRTOS", }, #endif { IH_OS_OPENSBI, "opensbi", "RISC-V OpenSBI", }, + { IH_OS_EFI, "efi", "EFI Firmware" }, { -1, "", "", }, }; diff --git a/include/image.h b/include/image.h index f4d2aaf53e..4a280b78e7 100644 --- a/include/image.h +++ b/include/image.h @@ -157,6 +157,7 @@ enum { IH_OS_ARM_TRUSTED_FIRMWARE, /* ARM Trusted Firmware */ IH_OS_TEE, /* Trusted Execution Environment */ IH_OS_OPENSBI, /* RISC-V OpenSBI */ + IH_OS_EFI, /* EFI Firmware (e.g. GRUB2) */ IH_OS_COUNT, }; -- 2.17.1
[PATCH v4 0/5] Add support for booting EFI FIT images
Currently the only way to run an EFI binary like GRUB2 is via the 'bootefi' command, which cannot be used in a verified boot scenario. The obvious solution to this limitation is to add support for booting FIT images containing those EFI binaries. The implementation relies on a new image type - IH_OS_EFI - which can be created by using 'os = "efi"' inside an ITS file: / { #address-cells = <1>; images { efi-grub { description = "GRUB EFI"; data = /incbin/("bootarm.efi"); type = "kernel_noload"; arch = "arm"; os = "efi"; compression = "none"; load = <0x0>; entry = <0x0>; hash-1 { algo = "sha256"; }; }; }; configurations { default = "config-grub"; config-grub { kernel = "efi-grub"; signature-1 { algo = "sha256,rsa2048"; sign-images = "kernel"; }; }; }; }; The bootm command has been extended to handle the IH_OS_EFI images. To enable this feature, a new configuration option has been added: BOOTM_EFI I tested the solution using the 'qemu_arm' board: => load scsi 0:1 ${kernel_addr_r} efi-image.fit => bootm ${kernel_addr_r}#config-grub Changes in v4: * Extend the python test to also run on real hardware, currently tested on qemu_arm Changes in v3: * Rebase patches on Heinrich Schuchardt's patch series v3: efi_loader: prepare for FIT images https://lists.denx.de/pipermail/u-boot/2019-December/393677.html This fixes implicitly the sandbox issue 'phys_to_virt: Cannot map sandbox address' since efi_install_fdt() is now expecting a pointer to addressable memory instead of a physical address. * Get rid of 'EFI/BOOT/' prefix used in ITS samples * Add a python test to verify the implementation in sandbox environment Changes in v2: * Rebase patches on Heinrich Schuchardt's patch series: efi_loader: prepare for FIT images https://lists.denx.de/pipermail/u-boot/2019-December/393192.html * Add sample configuration: doc/uImage.FIT/uefi.its * Update uefi documentation: doc/uefi/uefi.rst Cristian Ciocaltea (5): image: Add IH_OS_EFI for EFI chain-load boot bootm: Add a bootm command for type IH_OS_EFI doc: Add sample uefi.its image description file doc: uefi.rst: Document launching UEFI binaries from FIT images test/py: Create a test for launching UEFI binaries from FIT images cmd/Kconfig | 7 + common/bootm_os.c | 56 + common/image-fit.c| 3 +- common/image.c| 1 + doc/uImage.FIT/uefi.its | 67 + doc/uefi/uefi.rst | 34 +++ include/image.h | 1 + test/py/tests/test_efi_fit.py | 459 ++ 8 files changed, 627 insertions(+), 1 deletion(-) create mode 100644 doc/uImage.FIT/uefi.its create mode 100644 test/py/tests/test_efi_fit.py -- 2.17.1
[PATCH 1/1] test/py: Fix broken 'notbuildconfigspec' marker
Consider the following test sample: @pytest.mark.buildconfigspec('fit') @pytest.mark.notbuildconfigspec('generate_acpi_table') def test_sample(u_boot_console): Whatever the argument of the 'notbuildconfigspec' is, the test ends up being skipped with the message: ('/uboot/test/py/conftest.py', 463, 'Skipped: .config feature "fit" enabled') Signed-off-by: Cristian Ciocaltea --- test/py/conftest.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/py/conftest.py b/test/py/conftest.py index bffee6b8a3..c7f361f7bf 100644 --- a/test/py/conftest.py +++ b/test/py/conftest.py @@ -457,7 +457,7 @@ def setup_buildconfigspec(item): option = options.args[0] if not ubconfig.buildconfig.get('config_' + option.lower(), None): pytest.skip('.config feature "%s" not enabled' % option.lower()) -for option in item.iter_markers('notbuildconfigspec'): +for options in item.iter_markers('notbuildconfigspec'): option = options.args[0] if ubconfig.buildconfig.get('config_' + option.lower(), None): pytest.skip('.config feature "%s" enabled' % option.lower()) -- 2.17.1
Re: [PATCH v3 5/5] test/py: Create a test for launching UEFI binaries from FIT images
On Wed, Dec 18, 2019 at 11:56:00AM +0100, Heinrich Schuchardt wrote: > On 12/18/19 9:22 AM, Cristian Ciocaltea wrote: > > > > +}; > > > > +}; > > > > +''' > > > > + > > > > +@pytest.mark.boardspec('sandbox') > > > This test looks ok in principal. But why should we restrict it to the > > > sandbox? > > Let me see how this should work on real hardware, I'm going to test > > on qemu for the moment. > > Device trees cannot be used in conjunction with ACPI tables when booting > via UEFI. Currently this concerns only x86 and x86_64 but Phytec is > working on an arm64 board which shall provide an ACPI table. So you > probably want to check CONFIG_GENERATE_ACPI_TABLE instead of the board > type, e.g. > > @pytest.mark.notbuildconfigspec('generate_acpi_table') Thanks for the hint! For some strange reason, whatever I put in the 'notbuildconfigspec' marker causes the test to be skipped: [-] Section: test_efi_fit TIME: NOW: 2019/12/18 17:33:14.976576 TIME: SINCE-PREV: 0:00:00.192132 TIME: SINCE-START: 0:00:00.192132 SKIPPED: ('[...]/uboot/test/py/conftest.py', 463, 'Skipped: .config feature "bootm_efi" enabled') I don't really understand the connection to 'bootm_efi'. If I comment out the 'bootm_efi' marker, the reported status becomes: SKIPPED: ('[].../uboot/test/py/conftest.py', 463, 'Skipped: .config feature "cmd_bootefi_hello_compile" enabled') So it seems 'notbuildconfigspec' gets its parameter from the first active 'buildconfigspec' statement. This is my current test: #@pytest.mark.buildconfigspec('bootm_efi') @pytest.mark.buildconfigspec('cmd_bootefi_hello_compile') #@pytest.mark.notbuildconfigspec('generate_acpi_table') @pytest.mark.notbuildconfigspec('fake_item') @pytest.mark.requiredtool('dtc') > Best regards > > Heinrich
Re: [PATCH v3 5/5] test/py: Create a test for launching UEFI binaries from FIT images
On Wed, Dec 18, 2019 at 11:06:48AM +0100, Heinrich Schuchardt wrote: > On 12/18/19 9:22 AM, Cristian Ciocaltea wrote: > > On Tue, Dec 17, 2019 at 10:08:31PM +0100, Heinrich Schuchardt wrote: > > > On 12/17/19 8:47 AM, Cristian Ciocaltea wrote: > > > > This test verifies the implementation of the 'bootm' extension that > > > > handles UEFI binaries inside FIT images (enabled via CONFIG_BOOTM_EFI). > > > > > > > > Signed-off-by: Cristian Ciocaltea > > > > --- > > > >test/py/tests/test_efi_fit.py | 233 > > > > ++ > > > >1 file changed, 233 insertions(+) > > > >create mode 100644 test/py/tests/test_efi_fit.py > > > > > > > > diff --git a/test/py/tests/test_efi_fit.py > > > > b/test/py/tests/test_efi_fit.py > > > > new file mode 100644 > > > > index 00..52b415b198 > > > > --- /dev/null > > > > +++ b/test/py/tests/test_efi_fit.py > > > > @@ -0,0 +1,233 @@ > > > > +# SPDX-License-Identifier: GPL-2.0 > > > > +# Copyright (c) 2019, Cristian Ciocaltea > > > > + > > > > +# Test launching UEFI binaries from FIT images. > > > > + > > > > +import os > > > > +import pytest > > > > +import u_boot_utils as util > > > > + > > > > +# Define the parametrized ITS data to be used for FIT image generation. > > > > +its_data = ''' > > > > +/dts-v1/; > > > > + > > > > +/ { > > > > +description = "EFI image with FDT blob"; > > > > +#address-cells = <1>; > > > > + > > > > +images { > > > > +efi { > > > > +description = "Sandbox EFI"; > > > > +data = /incbin/("%(efi-bin)s"); > > > > +type = "%(kernel-type)s"; > > > > +arch = "sandbox"; > > > > +os = "efi"; > > > > +compression = "%(efi-comp)s"; > > > > +load = <0x0>; > > > > +entry = <0x0>; > > > > +}; > > > > +fdt { > > > > +description = "Sandbox FDT"; > > > > +data = /incbin/("%(fdt-bin)s"); > > > > +type = "flat_dt"; > > > > +arch = "sandbox"; > > > > +compression = "%(fdt-comp)s"; > > > > +}; > > > > +}; > > > > + > > > > +configurations { > > > > +default = "config-efi-fdt"; > > > > +config-efi-fdt { > > > > +description = "EFI FIT w/ FDT"; > > > > +kernel = "efi"; > > > > +fdt = "fdt"; > > > > +}; > > > > +config-efi-nofdt { > > > > +description = "EFI FIT w/o FDT"; > > > > +kernel = "efi"; > > > > +}; > > > > +}; > > > > +}; > > > > +''' > > > > + > > > > +# Define the parametrized FDT data. > > > > +fdt_data = ''' > > > > +/dts-v1/; > > > > + > > > > +/ { > > > > +model = "Sandbox %(fdt_type) EFI FIT Boot Test "; > > > > +compatible = "sandbox"; > > > > + > > > > +reset@0 { > > > > +compatible = "sandbox,reset"; > > > > > > This produces a warning: > > > > > > +dtc ./test-efi-fit-sandbox-internal.dts -O dtb -o > > > ./test-efi-fit-sandbox-internal.dtb > > > ./test-efi-fit-sandbox-internal.dts:8.13-10.7: Warning > > > (unit_address_vs_reg): /reset@0: node has a unit name, but no reg property > > > > A similar sample is also used by test_fit.py and test_vboot.py, which > > expose the same warning, that's why I initially ignored it. > > If acceptable, I can suppress it via '-W no-unit_address_vs_reg'. > > reset@0 includes a unit-address. So a reg property is expected. How about: > > /dts-v1/; > > / { > #address-cells = <1>; > #size-cells = <0>; > > model = "Sandbox %(fdt_type) EFI FIT Boot Test "; > compatible = "sandbox"; > >
Re: [PATCH v3 2/5] bootm: Add a bootm command for type IH_OS_EFI
On Tue, Dec 17, 2019 at 09:34:44PM +0100, Heinrich Schuchardt wrote: > On 12/17/19 8:46 AM, Cristian Ciocaltea wrote: > > Add support for booting EFI binaries contained in FIT images. > > A typical usage scenario is chain-loading GRUB2 in a verified > > boot environment. > > > > Signed-off-by: Cristian Ciocaltea > > You missed the current changes in common/bootm_os.c. I will rebase the > patch. Right, sorry. I have already rebased the patch and I will resubmit it as soon as I finalize the changes on pytest. Thanks! > Reviewed-by: Heinrich Schuchardt
Re: [PATCH v3 5/5] test/py: Create a test for launching UEFI binaries from FIT images
On Tue, Dec 17, 2019 at 10:08:31PM +0100, Heinrich Schuchardt wrote: > On 12/17/19 8:47 AM, Cristian Ciocaltea wrote: > > This test verifies the implementation of the 'bootm' extension that > > handles UEFI binaries inside FIT images (enabled via CONFIG_BOOTM_EFI). > > > > Signed-off-by: Cristian Ciocaltea > > --- > > test/py/tests/test_efi_fit.py | 233 ++ > > 1 file changed, 233 insertions(+) > > create mode 100644 test/py/tests/test_efi_fit.py > > > > diff --git a/test/py/tests/test_efi_fit.py b/test/py/tests/test_efi_fit.py > > new file mode 100644 > > index 00..52b415b198 > > --- /dev/null > > +++ b/test/py/tests/test_efi_fit.py > > @@ -0,0 +1,233 @@ > > +# SPDX-License-Identifier: GPL-2.0 > > +# Copyright (c) 2019, Cristian Ciocaltea > > + > > +# Test launching UEFI binaries from FIT images. > > + > > +import os > > +import pytest > > +import u_boot_utils as util > > + > > +# Define the parametrized ITS data to be used for FIT image generation. > > +its_data = ''' > > +/dts-v1/; > > + > > +/ { > > +description = "EFI image with FDT blob"; > > +#address-cells = <1>; > > + > > +images { > > +efi { > > +description = "Sandbox EFI"; > > +data = /incbin/("%(efi-bin)s"); > > +type = "%(kernel-type)s"; > > +arch = "sandbox"; > > +os = "efi"; > > +compression = "%(efi-comp)s"; > > +load = <0x0>; > > +entry = <0x0>; > > +}; > > +fdt { > > +description = "Sandbox FDT"; > > +data = /incbin/("%(fdt-bin)s"); > > +type = "flat_dt"; > > +arch = "sandbox"; > > +compression = "%(fdt-comp)s"; > > +}; > > +}; > > + > > +configurations { > > +default = "config-efi-fdt"; > > +config-efi-fdt { > > +description = "EFI FIT w/ FDT"; > > +kernel = "efi"; > > +fdt = "fdt"; > > +}; > > +config-efi-nofdt { > > +description = "EFI FIT w/o FDT"; > > +kernel = "efi"; > > +}; > > +}; > > +}; > > +''' > > + > > +# Define the parametrized FDT data. > > +fdt_data = ''' > > +/dts-v1/; > > + > > +/ { > > +model = "Sandbox %(fdt_type) EFI FIT Boot Test "; > > +compatible = "sandbox"; > > + > > +reset@0 { > > +compatible = "sandbox,reset"; > > This produces a warning: > > +dtc ./test-efi-fit-sandbox-internal.dts -O dtb -o > ./test-efi-fit-sandbox-internal.dtb > ./test-efi-fit-sandbox-internal.dts:8.13-10.7: Warning > (unit_address_vs_reg): /reset@0: node has a unit name, but no reg property A similar sample is also used by test_fit.py and test_vboot.py, which expose the same warning, that's why I initially ignored it. If acceptable, I can suppress it via '-W no-unit_address_vs_reg'. > > +}; > > +}; > > +''' > > + > > +@pytest.mark.boardspec('sandbox') > > This test looks ok in principal. But why should we restrict it to the > sandbox? Let me see how this should work on real hardware, I'm going to test on qemu for the moment. > Best regards > > Heinrich > > > +@pytest.mark.buildconfigspec('bootm_efi') > > +@pytest.mark.buildconfigspec('cmd_bootefi_hello_compile') > > +@pytest.mark.requiredtool('dtc') > > +def test_efi_fit(u_boot_console): > > +"""Test handling of UEFI binaries inside FIT images. > > + > > +The tests are trying to launch U-Boot's helloworld.efi embedded into > > +FIT images, in uncompressed or gzip compressed format. > > + > > +Additionally, a sample FDT blob is created and embedded into the above > > +mentioned FIT images, in uncompressed or gzip compressed format. > > + > > +The following test cases are currently defined and enabled: > > +- Launch uncompressed FIT EFI & FIT FDT > > +- Launch compressed FIT EFI & FIT FDT > > +- Launch uncompressed FIT EFI & internal FDT > > +- Launch compressed FIT EFI & internal FDT > > +""" > > + > > +def make_fpath(fname): >
[PATCH v3 5/5] test/py: Create a test for launching UEFI binaries from FIT images
This test verifies the implementation of the 'bootm' extension that handles UEFI binaries inside FIT images (enabled via CONFIG_BOOTM_EFI). Signed-off-by: Cristian Ciocaltea --- test/py/tests/test_efi_fit.py | 233 ++ 1 file changed, 233 insertions(+) create mode 100644 test/py/tests/test_efi_fit.py diff --git a/test/py/tests/test_efi_fit.py b/test/py/tests/test_efi_fit.py new file mode 100644 index 00..52b415b198 --- /dev/null +++ b/test/py/tests/test_efi_fit.py @@ -0,0 +1,233 @@ +# SPDX-License-Identifier: GPL-2.0 +# Copyright (c) 2019, Cristian Ciocaltea + +# Test launching UEFI binaries from FIT images. + +import os +import pytest +import u_boot_utils as util + +# Define the parametrized ITS data to be used for FIT image generation. +its_data = ''' +/dts-v1/; + +/ { +description = "EFI image with FDT blob"; +#address-cells = <1>; + +images { +efi { +description = "Sandbox EFI"; +data = /incbin/("%(efi-bin)s"); +type = "%(kernel-type)s"; +arch = "sandbox"; +os = "efi"; +compression = "%(efi-comp)s"; +load = <0x0>; +entry = <0x0>; +}; +fdt { +description = "Sandbox FDT"; +data = /incbin/("%(fdt-bin)s"); +type = "flat_dt"; +arch = "sandbox"; +compression = "%(fdt-comp)s"; +}; +}; + +configurations { +default = "config-efi-fdt"; +config-efi-fdt { +description = "EFI FIT w/ FDT"; +kernel = "efi"; +fdt = "fdt"; +}; +config-efi-nofdt { +description = "EFI FIT w/o FDT"; +kernel = "efi"; +}; +}; +}; +''' + +# Define the parametrized FDT data. +fdt_data = ''' +/dts-v1/; + +/ { +model = "Sandbox %(fdt_type) EFI FIT Boot Test "; +compatible = "sandbox"; + +reset@0 { +compatible = "sandbox,reset"; +}; +}; +''' + +@pytest.mark.boardspec('sandbox') +@pytest.mark.buildconfigspec('bootm_efi') +@pytest.mark.buildconfigspec('cmd_bootefi_hello_compile') +@pytest.mark.requiredtool('dtc') +def test_efi_fit(u_boot_console): +"""Test handling of UEFI binaries inside FIT images. + +The tests are trying to launch U-Boot's helloworld.efi embedded into +FIT images, in uncompressed or gzip compressed format. + +Additionally, a sample FDT blob is created and embedded into the above +mentioned FIT images, in uncompressed or gzip compressed format. + +The following test cases are currently defined and enabled: +- Launch uncompressed FIT EFI & FIT FDT +- Launch compressed FIT EFI & FIT FDT +- Launch uncompressed FIT EFI & internal FDT +- Launch compressed FIT EFI & internal FDT +""" + +def make_fpath(fname): +"""Compute the path of a given (temporary) file. + +Args: +fname: The name of a file within U-Boot build dir. +Return: +The computed file path. +""" +return os.path.join(u_boot_console.config.build_dir, fname) + +def make_efi(fname, comp): +"""Create an UEFI binary. + +This simply copies lib/efi_loader/helloworld.efi into U-Boot +build dir and, optionally, compresses the file using gzip. + +Args: +fname: The target file name within U-Boot build dir. +comp: Flag to enable gzip compression. +Return: +The path of the created file. +""" +bin_path = make_fpath(fname) +os.system('cp %s %s' % (make_fpath('lib/efi_loader/helloworld.efi'), bin_path)) +if comp: +util.run_and_log(u_boot_console, ['gzip', '-f', bin_path]) +bin_path += '.gz' +return bin_path + +def make_dtb(fdt_type, comp): +"""Create a sample DTB file. + +Creates a DTS file and compiles it to a DTB. + +Args: +fdt_type: The type of the FDT, i.e. internal, user. +comp: Flag to enable gzip compression. +Returns: +The path of the created file. +""" +dts = make_fpath('test-efi-fit-sandbox-%s.dts' % fdt_type) +dtb = make_fpath('test-efi-fit-sandbox-%s.dtb' % fdt_type) +with open(dts, 'w') as fd: +fd.write(fdt_data) +util.run_and_log(u_boot_console, ['dtc', dts, '-O', 'dtb', '-o', dtb]) +if comp: +util.run_and_log(u_boot_console, ['gzip', '-f', dtb]) +dtb += '.gz' +return dtb + +def make_fit(efi_comp, fdt_comp): +"
[PATCH v3 4/5] doc: uefi.rst: Document launching UEFI binaries from FIT images
This patch adds a new section "Launching a UEFI binary from a FIT image" documenting the usage of the CONFIG_BOOTM_EFI extension to bootm command that offers a verified boot alternative for UEFI binaries such as GRUB2. Signed-off-by: Cristian Ciocaltea Reviewed-by: Heinrich Schuchardt --- doc/uefi/uefi.rst | 34 ++ 1 file changed, 34 insertions(+) diff --git a/doc/uefi/uefi.rst b/doc/uefi/uefi.rst index db942df694..a8fd886d6b 100644 --- a/doc/uefi/uefi.rst +++ b/doc/uefi/uefi.rst @@ -63,6 +63,40 @@ The environment variable 'bootargs' is passed as load options in the UEFI system table. The Linux kernel EFI stub uses the load options as command line arguments. +Launching a UEFI binary from a FIT image + + +A signed FIT image can be used to securely boot a UEFI image via the +bootm command. This feature is available if U-Boot is configured with:: + +CONFIG_BOOTM_EFI=y + +A sample configuration is provided as file doc/uImage.FIT/uefi.its. + +Below you find the output of an example session starting GRUB:: + +=> load mmc 0:1 ${kernel_addr_r} image.fit +4620426 bytes read in 83 ms (53.1 MiB/s) +=> bootm ${kernel_addr_r}#config-grub-nofdt +## Loading kernel from FIT Image at 4040 ... + Using 'config-grub-nofdt' configuration + Verifying Hash Integrity ... sha256,rsa2048:dev+ OK + Trying 'efi-grub' kernel subimage + Description: GRUB EFI Firmware + Created: 2019-11-20 8:18:16 UTC + Type: Kernel Image (no loading done) + Compression: uncompressed + Data Start: 0x404000d0 + Data Size:450560 Bytes = 440 KiB + Hash algo:sha256 + Hash value: 4dbee00021112df618f58b3f7cf5e1595533d543094064b9ce991e8b054a9eec + Verifying Hash Integrity ... sha256+ OK + XIP Kernel Image (no loading done) +## Transferring control to EFI (at address 404000d0) ... +Welcome to GRUB! + +See doc/uImage.FIT/howto.txt for an introduction to FIT images. + Executing the boot manager ~~ -- 2.17.1
[PATCH v3 0/5] Add support for booting EFI FIT images
Currently the only way to run an EFI binary like GRUB2 is via the 'bootefi' command, which cannot be used in a verified boot scenario. The obvious solution to this limitation is to add support for booting FIT images containing those EFI binaries. The implementation relies on a new image type - IH_OS_EFI - which can be created by using 'os = "efi"' inside an ITS file: / { #address-cells = <1>; images { efi-grub { description = "GRUB EFI"; data = /incbin/("bootarm.efi"); type = "kernel_noload"; arch = "arm"; os = "efi"; compression = "none"; load = <0x0>; entry = <0x0>; hash-1 { algo = "sha256"; }; }; }; configurations { default = "config-grub"; config-grub { kernel = "efi-grub"; signature-1 { algo = "sha256,rsa2048"; sign-images = "kernel"; }; }; }; }; The bootm command has been extended to handle the IH_OS_EFI images. To enable this feature, a new configuration option has been added: BOOTM_EFI I tested the solution using the 'qemu_arm' board: => load scsi 0:1 ${kernel_addr_r} efi-image.fit => bootm ${kernel_addr_r}#config-grub Changes in v3: * Rebase patches on Heinrich Schuchardt's patch series v3: efi_loader: prepare for FIT images https://lists.denx.de/pipermail/u-boot/2019-December/393677.html This fixes implicitly the sandbox issue 'phys_to_virt: Cannot map sandbox address' since efi_install_fdt() is now expecting a pointer to addressable memory instead of a physical address. * Get rid of 'EFI/BOOT/' prefix used in ITS samples * Add a python test to verify the implementation in sandbox environment Changes in v2: * Rebase patches on Heinrich Schuchardt's patch series: efi_loader: prepare for FIT images https://lists.denx.de/pipermail/u-boot/2019-December/393192.html * Add sample configuration: doc/uImage.FIT/uefi.its * Update uefi documentation: doc/uefi/uefi.rst Cristian Ciocaltea (5): image: Add IH_OS_EFI for EFI chain-load boot bootm: Add a bootm command for type IH_OS_EFI doc: Add sample uefi.its image description file doc: uefi.rst: Document launching UEFI binaries from FIT images test/py: Create a test for launching UEFI binaries from FIT images cmd/Kconfig | 7 + common/bootm_os.c | 56 common/image-fit.c| 3 +- common/image.c| 1 + doc/uImage.FIT/uefi.its | 67 ++ doc/uefi/uefi.rst | 34 + include/image.h | 1 + test/py/tests/test_efi_fit.py | 233 ++ 8 files changed, 401 insertions(+), 1 deletion(-) create mode 100644 doc/uImage.FIT/uefi.its create mode 100644 test/py/tests/test_efi_fit.py -- 2.17.1
[PATCH v3 1/5] image: Add IH_OS_EFI for EFI chain-load boot
Add a new OS type to be used for chain-loading an EFI compatible firmware or boot loader like GRUB2, possibly in a verified boot scenario. Bellow is sample ITS file that generates a FIT image supporting secure boot. Please note the presence of 'os = "efi";' line, which identifies the currently introduced OS type: / { #address-cells = <1>; images { efi-grub { description = "GRUB EFI"; data = /incbin/("bootarm.efi"); type = "kernel_noload"; arch = "arm"; os = "efi"; compression = "none"; load = <0x0>; entry = <0x0>; hash-1 { algo = "sha256"; }; }; }; configurations { default = "config-grub"; config-grub { kernel = "efi-grub"; signature-1 { algo = "sha256,rsa2048"; sign-images = "kernel"; }; }; }; }; Signed-off-by: Cristian Ciocaltea --- common/image-fit.c | 3 ++- common/image.c | 1 + include/image.h| 1 + 3 files changed, 4 insertions(+), 1 deletion(-) diff --git a/common/image-fit.c b/common/image-fit.c index 5c63c769de..19e313bf41 100644 --- a/common/image-fit.c +++ b/common/image-fit.c @@ -1925,7 +1925,8 @@ int fit_image_load(bootm_headers_t *images, ulong addr, image_type == 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); + fit_image_check_os(fit, noffset, IH_OS_OPENRTOS) || + fit_image_check_os(fit, noffset, IH_OS_EFI); /* * If either of the checks fail, we should report an error, but diff --git a/common/image.c b/common/image.c index f17fa40c49..2e0e2b0e7f 100644 --- a/common/image.c +++ b/common/image.c @@ -134,6 +134,7 @@ static const table_entry_t uimage_os[] = { { IH_OS_OPENRTOS, "openrtos", "OpenRTOS", }, #endif { IH_OS_OPENSBI, "opensbi", "RISC-V OpenSBI", }, + { IH_OS_EFI, "efi", "EFI Firmware" }, { -1, "", "", }, }; diff --git a/include/image.h b/include/image.h index f4d2aaf53e..4a280b78e7 100644 --- a/include/image.h +++ b/include/image.h @@ -157,6 +157,7 @@ enum { IH_OS_ARM_TRUSTED_FIRMWARE, /* ARM Trusted Firmware */ IH_OS_TEE, /* Trusted Execution Environment */ IH_OS_OPENSBI, /* RISC-V OpenSBI */ + IH_OS_EFI, /* EFI Firmware (e.g. GRUB2) */ IH_OS_COUNT, }; -- 2.17.1
[PATCH v3 3/5] doc: Add sample uefi.its image description file
This patch adds an example FIT image description file demonstrating the usage of bootm command to securely launch UEFI binaries. Signed-off-by: Cristian Ciocaltea Reviewed-by: Heinrich Schuchardt --- doc/uImage.FIT/uefi.its | 67 + 1 file changed, 67 insertions(+) create mode 100644 doc/uImage.FIT/uefi.its diff --git a/doc/uImage.FIT/uefi.its b/doc/uImage.FIT/uefi.its new file mode 100644 index 00..378ca4ed8d --- /dev/null +++ b/doc/uImage.FIT/uefi.its @@ -0,0 +1,67 @@ +/* + * Example FIT image description file demonstrating the usage of the + * bootm command to launch UEFI binaries. + * + * Two boot configurations are available to enable booting GRUB2 on QEMU, + * the former uses a FDT blob contained in the FIT image, while the later + * relies on the FDT provided by the board emulator. + */ + +/dts-v1/; + +/ { + description = "GRUB2 EFI and QEMU FDT blob"; + #address-cells = <1>; + + images { + efi-grub { + description = "GRUB EFI Firmware"; + data = /incbin/("bootarm.efi"); + type = "kernel_noload"; + arch = "arm"; + os = "efi"; + compression = "none"; + load = <0x0>; + entry = <0x0>; + hash-1 { + algo = "sha256"; + }; + }; + + fdt-qemu { + description = "QEMU DTB"; + data = /incbin/("qemu-arm.dtb"); + type = "flat_dt"; + arch = "arm"; + compression = "none"; + hash-1 { + algo = "sha256"; + }; + }; + }; + + configurations { + default = "config-grub-fdt"; + + config-grub-fdt { + description = "GRUB EFI Boot w/ FDT"; + kernel = "efi-grub"; + fdt = "fdt-qemu"; + signature-1 { + algo = "sha256,rsa2048"; + key-name-hint = "dev"; + sign-images = "kernel", "fdt"; + }; + }; + + config-grub-nofdt { + description = "GRUB EFI Boot w/o FDT"; + kernel = "efi-grub"; + signature-1 { + algo = "sha256,rsa2048"; + key-name-hint = "dev"; + sign-images = "kernel"; + }; + }; + }; +}; -- 2.17.1
[PATCH v3 2/5] bootm: Add a bootm command for type IH_OS_EFI
Add support for booting EFI binaries contained in FIT images. A typical usage scenario is chain-loading GRUB2 in a verified boot environment. Signed-off-by: Cristian Ciocaltea --- cmd/Kconfig | 7 ++ common/bootm_os.c | 56 +++ 2 files changed, 63 insertions(+) diff --git a/cmd/Kconfig b/cmd/Kconfig index cf982ff65e..39fa87082d 100644 --- a/cmd/Kconfig +++ b/cmd/Kconfig @@ -263,6 +263,13 @@ config CMD_BOOTI help Boot an AArch64 Linux Kernel image from memory. +config BOOTM_EFI + bool "Support booting EFI OS images" + depends on CMD_BOOTEFI + default y + help + Support booting EFI images via the bootm command. + config BOOTM_LINUX bool "Support booting Linux OS images" depends on CMD_BOOTM || CMD_BOOTZ || CMD_BOOTI diff --git a/common/bootm_os.c b/common/bootm_os.c index 6fb7d658da..96792430da 100644 --- a/common/bootm_os.c +++ b/common/bootm_os.c @@ -6,10 +6,12 @@ #include #include +#include #include #include #include #include +#include #include #include @@ -462,6 +464,57 @@ static int do_bootm_tee(int flag, int argc, char * const argv[], } #endif +#ifdef CONFIG_BOOTM_EFI +static int do_bootm_efi(int flag, int argc, char * const argv[], + bootm_headers_t *images) +{ + int ret; + efi_status_t efi_ret; + void *image_buf; + + if (flag != BOOTM_STATE_OS_GO) + return 0; + + /* Locate FDT, if provided */ + ret = bootm_find_images(flag, argc, argv); + if (ret) + return ret; + + /* Initialize EFI drivers */ + efi_ret = efi_init_obj_list(); + if (efi_ret != EFI_SUCCESS) { + printf("## Failed to initialize UEFI sub-system: r = %lu\n", + efi_ret & ~EFI_ERROR_MASK); + return 1; + } + + /* Install device tree */ + efi_ret = efi_install_fdt(images->ft_len + ? images->ft_addr : EFI_FDT_USE_INTERNAL); + if (efi_ret != EFI_SUCCESS) { + printf("## Failed to install device tree: r = %lu\n", + efi_ret & ~EFI_ERROR_MASK); + return 1; + } + + /* Run EFI image */ + printf("## Transferring control to EFI (at address %08lx) ...\n", + images->ep); + bootstage_mark(BOOTSTAGE_ID_RUN_OS); + + image_buf = map_sysmem(images->ep, images->os.image_len); + + efi_ret = efi_run_image(image_buf, images->os.image_len); + if (efi_ret != EFI_SUCCESS) { + printf("## Failed to run EFI image: r = %lu\n", + efi_ret & ~EFI_ERROR_MASK); + return 1; + } + + return 0; +} +#endif + static boot_os_fn *boot_os[] = { [IH_OS_U_BOOT] = do_bootm_standalone, #ifdef CONFIG_BOOTM_LINUX @@ -498,6 +551,9 @@ static boot_os_fn *boot_os[] = { #ifdef CONFIG_BOOTM_OPTEE [IH_OS_TEE] = do_bootm_tee, #endif +#ifdef CONFIG_BOOTM_EFI + [IH_OS_EFI] = do_bootm_efi, +#endif }; /* Allow for arch specific config before we boot */ -- 2.17.1
Re: [PATCH v2 2/4] bootm: Add a bootm command for type IH_OS_EFI
On Wed, Dec 11, 2019 at 10:57:48AM +0100, Heinrich Schuchardt wrote: > On 12/11/19 9:54 AM, Cristian Ciocaltea wrote: > > On Tue, Dec 10, 2019 at 08:32:17PM +0100, Heinrich Schuchardt wrote: > > > On 12/10/19 9:56 AM, Cristian Ciocaltea wrote: > > > > Add support for booting EFI binaries contained in FIT images. > > > > A typical usage scenario is chain-loading GRUB2 in a verified > > > > boot environment. > > > > > > > > Signed-off-by: Cristian Ciocaltea > > > > > > Reading through the code it looks good. What I really need to do is > > > analyze the address usage on the sandbox. To me it is unclear if > > > images->fdt_addr is a physical address or an address in the address > > > space of the sandbox. > > > > > > Did you test this on the sandbox? You can use > > > lib/efi_loader/helloworld.efi as a binary and the 'host load hostfs' > > > command for loading the FIT image. > > > > I only tested on qemu, I've never used the sandbox, so it's a good > > opportunity to give it a try. > > > > > Shouldn't we add booting a UEFI FIT image to the Python test in > > > test/py/tests/test_fit.py? > > > > Unfortunately I'm not familiar with the testing framework (including > > Python scripting), but I'll do my best to add such a test. > > > > > doc/uImage.FIT/signature.txt describes that several properties of the > > > RSA public key should be stored in the control device tree. > > > Unfortunately no example is supplied in which format they should be > > > stored. Could you send me an example, please. > > > > > > I found the following > > > > > > https://github.com/bn121rajesh/ipython-notebooks/blob/master/BehindTheScene/RSAPublicKeyParamsUBoot/rsa_public_key_params_uboot.ipynb > > > > > > Is this an accurate description? Or how do you get the parameters from > > > your RSA public key? > > > > My test scenario involves the following steps: > > > > 1. Create a public/private key pair > > $ openssl genpkey -algorithm RSA -out ${DEV_KEY} \ > > -pkeyopt rsa_keygen_bits:2048 -pkeyopt rsa_keygen_pubexp:65537 > > > > 2. Create a certificate containing the public key > > $ openssl req -batch -new -x509 -key ${DEV_KEY} -out ${DEV_CRT} > > > > 3. Dump QEMU virt board DTB > > $ qemu-system-arm -nographic -M virt,dumpdtb=${BOARD_DTB} \ > > -cpu cortex-a15 -smp 1 -m 512 -bios u-boot.bin [...] > > > > 4. Create (unsigned) FIT image and put the public key into DTB, with > > the 'required' property set, telling U-Boot that this key MUST be > > verified for the image to be valid > > $ mkimage -f ${FIT_ITS} -K ${BOARD_DTB} -k ${KEYS_DIR} -r ${FIT_IMG} > > > > 5. Sign the FIT image > > $ fit_check_sign -f ${FIT_IMG} -k ${BOARD_DTB} > > > > 6. Run QEMU supplying the DTB containing the public key and the > > u-boot binary built with CONFIG_OF_BOARD > > $ qemu-system-arm -nographic \ > > -M virt -cpu cortex-a15 -smp 1 -m 512 -bios u-boot.bin \ > > -dtb ${BOARD_DTB} [...] > > > > This is what I get after booting QEMU with the command above: > > > > => fdt addr $fdtcontroladdr > > => fdt print > > / { > > [...] > > signature { > > key-dev { > > required = "conf"; > > algo = "sha256,rsa2048"; > > rsa,r-squared = * 0x5ef05188 [0x0100]; > > rsa,modulus = * 0x5ef05294 [0x0100]; > > rsa,exponent = <0x 0x00010001>; > > rsa,n0-inverse = <0x649cd557>; > > rsa,num-bits = <0x0800>; > > key-name-hint = "dev"; > > }; > > }; > > [...] > > See my patch > > doc: fitImage: example of a signature node > https://lists.denx.de/pipermail/u-boot/2019-December/393613.html > > --- > > Booting of the sandbox fails due to an incorrect address passed for the > device tree: > > => host load hostfs - $kernel_addr_r image.fit > 26558 bytes read in 0 ms > => bootm ${kernel_addr_r}#config-grub-fdt > ## Loading kernel from FIT Image at 0100 ... >Using 'config-grub-fdt' configuration >Verifying Hash Integrity ... OK >Trying 'helloworld' kernel subimage > Description: Hello World > Created: 2019-12-11 9:19:22 UTC > Type:
Re: [PATCH v2 2/4] bootm: Add a bootm command for type IH_OS_EFI
On Wed, Dec 11, 2019 at 11:13:28AM +0100, Heinrich Schuchardt wrote: > On 12/11/19 9:54 AM, Cristian Ciocaltea wrote: > > 1. Create a public/private key pair > > $ openssl genpkey -algorithm RSA -out ${DEV_KEY} \ > > -pkeyopt rsa_keygen_bits:2048 -pkeyopt rsa_keygen_pubexp:65537 > > > > 2. Create a certificate containing the public key > > $ openssl req -batch -new -x509 -key ${DEV_KEY} -out ${DEV_CRT} > > > > 3. Dump QEMU virt board DTB > > $ qemu-system-arm -nographic -M virt,dumpdtb=${BOARD_DTB} \ > > -cpu cortex-a15 -smp 1 -m 512 -bios u-boot.bin [...] > > > > 4. Create (unsigned) FIT image and put the public key into DTB, with > > the 'required' property set, telling U-Boot that this key MUST be > > verified for the image to be valid > > $ mkimage -f ${FIT_ITS} -K ${BOARD_DTB} -k ${KEYS_DIR} -r ${FIT_IMG} > > > > 5. Sign the FIT image > > $ fit_check_sign -f ${FIT_IMG} -k ${BOARD_DTB} > > Thanks for the description > > tools/fit_check_sign does not change any file. The signature is added in > step 4. You are right, I've taken the commands from a script I use to automate the whole procedure and I've just missed the verification step. > What seems to be missing in the U-Boot build system is the capability to > specify a public key in the configuation file to automatically include > the public key in the generated dtbs similar to Linux's > CONFIG_SYSTEM_TRUSTED_KEYS. That would be a nice addition. Currently it is only possible to pass the 'EXT_DTB' parameter to 'make' in order to provide the path to an external DTB file to be put in the U-Boot image. > Best regards > > Heinrich > > > > > 6. Run QEMU supplying the DTB containing the public key and the > > u-boot binary built with CONFIG_OF_BOARD > > $ qemu-system-arm -nographic \ > > -M virt -cpu cortex-a15 -smp 1 -m 512 -bios u-boot.bin \ > > -dtb ${BOARD_DTB} [...] >
Re: [PATCH v2 1/4] image: Add IH_OS_EFI for EFI chain-load boot
On Tue, Dec 10, 2019 at 10:49:09PM +, Peter Robinson wrote: > On Tue, Dec 10, 2019 at 6:30 PM Heinrich Schuchardt > wrote: > > > > On 12/10/19 9:56 AM, Cristian Ciocaltea wrote: > > > Add a new OS type to be used for chain-loading an EFI compatible > > > firmware or boot loader like GRUB2, possibly in a verified boot > > > scenario. > > > > > > Bellow is sample ITS file that generates a FIT image supporting > > > secure boot. Please note the presence of 'os = "efi";' line, which > > > identifies the currently introduced OS type: > > > > > > / { > > > #address-cells = <1>; > > > > > > images { > > > efi-grub { > > > description = "GRUB EFI"; > > > data = /incbin/("EFI/BOOT/bootarm.efi"); > > > > According to UEFI Spec 2.8 the default file name for 32 bit ARM is > > BOOTARM.EFI. But GRUB calls the file grubarm.efi. > > In Linux the boot.efi file is provided by shim [1] and used for > secure boot etc, I believe the default is also the fall back boot > method. I'm unaware of shim currently being built for armv7. > > [1] https://github.com/rhboot/shim/ > > > So shouldn't we use grubarm.efi here as filename? My build platform relies on buildroot and that is the default path where the GRUB EFI binary is deployed. I don't know the reasons behind, but most probably they are related to portability/compatibility, as Peter already pointed out. > > You use EFI/BOOT as directory name. I think this path does not add > > benefit to the example. The other *.its files also come without any > > specific path. Totally agree, I will remove the directory path. > > Best regards > > > > Heinrich > > > > > type = "kernel_noload"; > > > arch = "arm"; > > > os = "efi"; > > > compression = "none"; > > > load = <0x0>; > > > entry = <0x0>; > > > hash-1 { > > > algo = "sha256"; > > > }; > > > }; > > > }; > > > > > > configurations { > > > default = "config-grub"; > > > config-grub { > > > kernel = "efi-grub"; > > > signature-1 { > > > algo = "sha256,rsa2048"; > > > sign-images = "kernel"; > > > }; > > > }; > > > }; > > > }; > > > > > > Signed-off-by: Cristian Ciocaltea > > > --- > > > common/image-fit.c | 3 ++- > > > common/image.c | 1 + > > > include/image.h| 1 + > > > 3 files changed, 4 insertions(+), 1 deletion(-) > > > > > > diff --git a/common/image-fit.c b/common/image-fit.c > > > index 5c63c769de..19e313bf41 100644 > > > --- a/common/image-fit.c > > > +++ b/common/image-fit.c > > > @@ -1925,7 +1925,8 @@ int fit_image_load(bootm_headers_t *images, ulong > > > addr, > > > image_type == 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); > > > + fit_image_check_os(fit, noffset, IH_OS_OPENRTOS) || > > > + fit_image_check_os(fit, noffset, IH_OS_EFI); > > > > > > /* > > >* If either of the checks fail, we should report an error, but > > > diff --git a/common/image.c b/common/image.c > > > index f17fa40c49..2e0e2b0e7f 100644 > > > --- a/common/image.c > > > +++ b/common/image.c > > > @@ -134,6 +134,7 @@ static const table_entry_t uimage_os[] = { > > > { IH_OS_OPENRTOS, "openrtos", "OpenRTOS", }, > > > #endif > > > { IH_OS_OPENSBI, "opensbi", "RISC-V OpenSBI", }, > > > + { IH_OS_EFI, "efi", "EFI Firmware" }, > > > > > > { -1, "", "", }, > > > }; > > > diff --git a/include/image.h b/include/image.h > > > index f4d2aaf53e..4a280b78e7 100644 > > > --- a/include/image.h > > > +++ b/include/image.h > > > @@ -157,6 +157,7 @@ enum { > > > IH_OS_ARM_TRUSTED_FIRMWARE, /* ARM Trusted Firmware */ > > > IH_OS_TEE, /* Trusted Execution Environment */ > > > IH_OS_OPENSBI, /* RISC-V OpenSBI */ > > > + IH_OS_EFI, /* EFI Firmware (e.g. GRUB2) */ > > > > > > IH_OS_COUNT, > > > }; > > > > >
Re: [PATCH v2 2/4] bootm: Add a bootm command for type IH_OS_EFI
On Tue, Dec 10, 2019 at 08:32:17PM +0100, Heinrich Schuchardt wrote: > On 12/10/19 9:56 AM, Cristian Ciocaltea wrote: > > Add support for booting EFI binaries contained in FIT images. > > A typical usage scenario is chain-loading GRUB2 in a verified > > boot environment. > > > > Signed-off-by: Cristian Ciocaltea > > Reading through the code it looks good. What I really need to do is > analyze the address usage on the sandbox. To me it is unclear if > images->fdt_addr is a physical address or an address in the address > space of the sandbox. > > Did you test this on the sandbox? You can use > lib/efi_loader/helloworld.efi as a binary and the 'host load hostfs' > command for loading the FIT image. I only tested on qemu, I've never used the sandbox, so it's a good opportunity to give it a try. > Shouldn't we add booting a UEFI FIT image to the Python test in > test/py/tests/test_fit.py? Unfortunately I'm not familiar with the testing framework (including Python scripting), but I'll do my best to add such a test. > doc/uImage.FIT/signature.txt describes that several properties of the > RSA public key should be stored in the control device tree. > Unfortunately no example is supplied in which format they should be > stored. Could you send me an example, please. > > I found the following > > https://github.com/bn121rajesh/ipython-notebooks/blob/master/BehindTheScene/RSAPublicKeyParamsUBoot/rsa_public_key_params_uboot.ipynb > > Is this an accurate description? Or how do you get the parameters from > your RSA public key? My test scenario involves the following steps: 1. Create a public/private key pair $ openssl genpkey -algorithm RSA -out ${DEV_KEY} \ -pkeyopt rsa_keygen_bits:2048 -pkeyopt rsa_keygen_pubexp:65537 2. Create a certificate containing the public key $ openssl req -batch -new -x509 -key ${DEV_KEY} -out ${DEV_CRT} 3. Dump QEMU virt board DTB $ qemu-system-arm -nographic -M virt,dumpdtb=${BOARD_DTB} \ -cpu cortex-a15 -smp 1 -m 512 -bios u-boot.bin [...] 4. Create (unsigned) FIT image and put the public key into DTB, with the 'required' property set, telling U-Boot that this key MUST be verified for the image to be valid $ mkimage -f ${FIT_ITS} -K ${BOARD_DTB} -k ${KEYS_DIR} -r ${FIT_IMG} 5. Sign the FIT image $ fit_check_sign -f ${FIT_IMG} -k ${BOARD_DTB} 6. Run QEMU supplying the DTB containing the public key and the u-boot binary built with CONFIG_OF_BOARD $ qemu-system-arm -nographic \ -M virt -cpu cortex-a15 -smp 1 -m 512 -bios u-boot.bin \ -dtb ${BOARD_DTB} [...] This is what I get after booting QEMU with the command above: => fdt addr $fdtcontroladdr => fdt print / { [...] signature { key-dev { required = "conf"; algo = "sha256,rsa2048"; rsa,r-squared = * 0x5ef05188 [0x0100]; rsa,modulus = * 0x5ef05294 [0x0100]; rsa,exponent = <0x 0x00010001>; rsa,n0-inverse = <0x649cd557>; rsa,num-bits = <0x0800>; key-name-hint = "dev"; }; }; [...] > Best regards > > Heinrich
[PATCH v2 4/4] doc: uefi.rst: Document launching UEFI binaries from FIT images
This patch adds a new section "Launching a UEFI binary from a FIT image" documenting the usage of the CONFIG_BOOTM_EFI extension to bootm command that offers a secure boot alternative for UEFI binaries such as GRUB2. Signed-off-by: Cristian Ciocaltea --- doc/uefi/uefi.rst | 34 ++ 1 file changed, 34 insertions(+) diff --git a/doc/uefi/uefi.rst b/doc/uefi/uefi.rst index db942df694..a8fd886d6b 100644 --- a/doc/uefi/uefi.rst +++ b/doc/uefi/uefi.rst @@ -63,6 +63,40 @@ The environment variable 'bootargs' is passed as load options in the UEFI system table. The Linux kernel EFI stub uses the load options as command line arguments. +Launching a UEFI binary from a FIT image + + +A signed FIT image can be used to securely boot a UEFI image via the +bootm command. This feature is available if U-Boot is configured with:: + +CONFIG_BOOTM_EFI=y + +A sample configuration is provided as file doc/uImage.FIT/uefi.its. + +Below you find the output of an example session starting GRUB:: + +=> load mmc 0:1 ${kernel_addr_r} image.fit +4620426 bytes read in 83 ms (53.1 MiB/s) +=> bootm ${kernel_addr_r}#config-grub-nofdt +## Loading kernel from FIT Image at 4040 ... + Using 'config-grub-nofdt' configuration + Verifying Hash Integrity ... sha256,rsa2048:dev+ OK + Trying 'efi-grub' kernel subimage + Description: GRUB EFI Firmware + Created: 2019-11-20 8:18:16 UTC + Type: Kernel Image (no loading done) + Compression: uncompressed + Data Start: 0x404000d0 + Data Size:450560 Bytes = 440 KiB + Hash algo:sha256 + Hash value: 4dbee00021112df618f58b3f7cf5e1595533d543094064b9ce991e8b054a9eec + Verifying Hash Integrity ... sha256+ OK + XIP Kernel Image (no loading done) +## Transferring control to EFI (at address 404000d0) ... +Welcome to GRUB! + +See doc/uImage.FIT/howto.txt for an introduction to FIT images. + Executing the boot manager ~~ -- 2.17.1
[PATCH v2 3/4] doc: Add sample uefi.its image description file
This patch adds an example FIT image description file demonstrating the usage of bootm command to securely launch UEFI binaries. Signed-off-by: Cristian Ciocaltea --- doc/uImage.FIT/uefi.its | 67 + 1 file changed, 67 insertions(+) create mode 100644 doc/uImage.FIT/uefi.its diff --git a/doc/uImage.FIT/uefi.its b/doc/uImage.FIT/uefi.its new file mode 100644 index 00..e336ad938d --- /dev/null +++ b/doc/uImage.FIT/uefi.its @@ -0,0 +1,67 @@ +/* + * Example FIT image description file demonstrating the usage of + * bootm command to launch UEFI binaries. + * + * Two boot configurations are available to enable booting GRUB2 on QEMU, + * the former uses a FDT blob contained in the FIT image, while the later + * relies on the FDT provided by the board emulator. + */ + +/dts-v1/; + +/ { + description = "GRUB2 EFI and QEMU FDT blob"; + #address-cells = <1>; + + images { + efi-grub { + description = "GRUB EFI Firmware"; + data = /incbin/("efi-part/EFI/BOOT/bootarm.efi"); + type = "kernel_noload"; + arch = "arm"; + os = "efi"; + compression = "none"; + load = <0x0>; + entry = <0x0>; + hash-1 { + algo = "sha256"; + }; + }; + + fdt-qemu { + description = "QEMU DTB"; + data = /incbin/("qemu-arm.dtb"); + type = "flat_dt"; + arch = "arm"; + compression = "none"; + hash-1 { + algo = "sha256"; + }; + }; + }; + + configurations { + default = "config-grub-fdt"; + + config-grub-fdt { + description = "GRUB EFI Boot with FDT"; + kernel = "efi-grub"; + fdt = "fdt-qemu"; + signature-1 { + algo = "sha256,rsa2048"; + key-name-hint = "dev"; + sign-images = "kernel", "fdt"; + }; + }; + + config-grub-nofdt { + description = "GRUB EFI Boot w/o FDT"; + kernel = "efi-grub"; + signature-1 { + algo = "sha256,rsa2048"; + key-name-hint = "dev"; + sign-images = "kernel"; + }; + }; + }; +}; -- 2.17.1
[PATCH v2 2/4] bootm: Add a bootm command for type IH_OS_EFI
Add support for booting EFI binaries contained in FIT images. A typical usage scenario is chain-loading GRUB2 in a verified boot environment. Signed-off-by: Cristian Ciocaltea --- cmd/Kconfig | 7 ++ common/bootm_os.c | 61 +++ 2 files changed, 68 insertions(+) diff --git a/cmd/Kconfig b/cmd/Kconfig index cf982ff65e..39fa87082d 100644 --- a/cmd/Kconfig +++ b/cmd/Kconfig @@ -263,6 +263,13 @@ config CMD_BOOTI help Boot an AArch64 Linux Kernel image from memory. +config BOOTM_EFI + bool "Support booting EFI OS images" + depends on CMD_BOOTEFI + default y + help + Support booting EFI images via the bootm command. + config BOOTM_LINUX bool "Support booting Linux OS images" depends on CMD_BOOTM || CMD_BOOTZ || CMD_BOOTI diff --git a/common/bootm_os.c b/common/bootm_os.c index 6fb7d658da..7aa76052b9 100644 --- a/common/bootm_os.c +++ b/common/bootm_os.c @@ -6,10 +6,12 @@ #include #include +#include #include #include #include #include +#include #include #include @@ -462,6 +464,62 @@ static int do_bootm_tee(int flag, int argc, char * const argv[], } #endif +#ifdef CONFIG_BOOTM_EFI +static int do_bootm_efi(int flag, int argc, char * const argv[], + bootm_headers_t *images) +{ + int ret; + efi_status_t efi_ret; + uintptr_t fdt_addr; + void *image_buf; + + if (flag != BOOTM_STATE_OS_GO) + return 0; + + /* Locate EFI binary and FDT, if provided */ + ret = bootm_find_images(flag, argc, argv); + if (ret) + return ret; + + /* Initialize EFI drivers */ + efi_ret = efi_init_obj_list(); + if (efi_ret != EFI_SUCCESS) { + printf("## Error: Cannot initialize UEFI sub-system, r = %lu\n", + efi_ret & ~EFI_ERROR_MASK); + return 1; + } + + /* Install device tree */ + if (images->ft_len) + fdt_addr = (uintptr_t)images->ft_addr; + else + fdt_addr = EFI_FDT_USE_INTERNAL; + + efi_ret = efi_install_fdt(fdt_addr); + if (efi_ret != EFI_SUCCESS) { + printf("## Error: Cannot install device tree, r = %lu\n", + efi_ret & ~EFI_ERROR_MASK); + return 1; + } + + /* Run EFI image */ + printf("## Transferring control to EFI (at address %08lx) ...\n", + images->ep); + bootstage_mark(BOOTSTAGE_ID_RUN_OS); + + image_buf = map_sysmem(images->ep, images->os.image_len); + + efi_ret = efi_run_image(image_buf, images->os.image_len); + if (efi_ret != EFI_SUCCESS) { + printf("## Error: Cannot run EFI image, r = %lu\n", + efi_ret & ~EFI_ERROR_MASK); + return 1; + } + + return 0; +} +#endif + static boot_os_fn *boot_os[] = { [IH_OS_U_BOOT] = do_bootm_standalone, #ifdef CONFIG_BOOTM_LINUX @@ -498,6 +556,9 @@ static boot_os_fn *boot_os[] = { #ifdef CONFIG_BOOTM_OPTEE [IH_OS_TEE] = do_bootm_tee, #endif +#ifdef CONFIG_BOOTM_EFI + [IH_OS_EFI] = do_bootm_efi, +#endif }; /* Allow for arch specific config before we boot */ -- 2.17.1
[PATCH v2 0/4] Add support for booting EFI FIT images
Currently the only way to run an EFI binary like GRUB2 is via the 'bootefi' command, which cannot be used in a verified boot scenario. The obvious solution to this limitation is to add support for booting FIT images containing those EFI binaries. The implementation relies on a new image type - IH_OS_EFI - which can be created by using 'os = "efi"' inside an ITS file: / { #address-cells = <1>; images { efi-grub { description = "GRUB EFI"; data = /incbin/("EFI/BOOT/bootarm.efi"); type = "kernel_noload"; arch = "arm"; os = "efi"; compression = "none"; load = <0x0>; entry = <0x0>; hash-1 { algo = "sha256"; }; }; }; configurations { default = "config-grub"; config-grub { kernel = "efi-grub"; signature-1 { algo = "sha256,rsa2048"; sign-images = "kernel"; }; }; }; }; The bootm command has been extended to handle the IH_OS_EFI images. To enable this feature, a new configuration option has been added: BOOTM_EFI I tested the solution using the 'qemu_arm' board: => load scsi 0:1 ${kernel_addr_r} efi-image.fit => bootm ${kernel_addr_r}#config-grub Changes since v1: * Rebase patches on Heinrich Schuchardt's patch series: efi_loader: prepare for FIT images https://lists.denx.de/pipermail/u-boot/2019-December/393192.html * Add sample configuration: doc/uImage.FIT/uefi.its * Update uefi documentation: doc/uefi/uefi.rst Cristian Ciocaltea (4): image: Add IH_OS_EFI for EFI chain-load boot bootm: Add a bootm command for type IH_OS_EFI doc: Add sample uefi.its image description file doc: uefi.rst: Document launching UEFI binaries from FIT images cmd/Kconfig | 7 + common/bootm_os.c | 61 + common/image-fit.c | 3 +- common/image.c | 1 + doc/uImage.FIT/uefi.its | 67 + doc/uefi/uefi.rst | 34 + include/image.h | 1 + 7 files changed, 173 insertions(+), 1 deletion(-) create mode 100644 doc/uImage.FIT/uefi.its -- 2.17.1
[PATCH v2 1/4] image: Add IH_OS_EFI for EFI chain-load boot
Add a new OS type to be used for chain-loading an EFI compatible firmware or boot loader like GRUB2, possibly in a verified boot scenario. Bellow is sample ITS file that generates a FIT image supporting secure boot. Please note the presence of 'os = "efi";' line, which identifies the currently introduced OS type: / { #address-cells = <1>; images { efi-grub { description = "GRUB EFI"; data = /incbin/("EFI/BOOT/bootarm.efi"); type = "kernel_noload"; arch = "arm"; os = "efi"; compression = "none"; load = <0x0>; entry = <0x0>; hash-1 { algo = "sha256"; }; }; }; configurations { default = "config-grub"; config-grub { kernel = "efi-grub"; signature-1 { algo = "sha256,rsa2048"; sign-images = "kernel"; }; }; }; }; Signed-off-by: Cristian Ciocaltea --- common/image-fit.c | 3 ++- common/image.c | 1 + include/image.h| 1 + 3 files changed, 4 insertions(+), 1 deletion(-) diff --git a/common/image-fit.c b/common/image-fit.c index 5c63c769de..19e313bf41 100644 --- a/common/image-fit.c +++ b/common/image-fit.c @@ -1925,7 +1925,8 @@ int fit_image_load(bootm_headers_t *images, ulong addr, image_type == 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); + fit_image_check_os(fit, noffset, IH_OS_OPENRTOS) || + fit_image_check_os(fit, noffset, IH_OS_EFI); /* * If either of the checks fail, we should report an error, but diff --git a/common/image.c b/common/image.c index f17fa40c49..2e0e2b0e7f 100644 --- a/common/image.c +++ b/common/image.c @@ -134,6 +134,7 @@ static const table_entry_t uimage_os[] = { { IH_OS_OPENRTOS, "openrtos", "OpenRTOS", }, #endif { IH_OS_OPENSBI, "opensbi", "RISC-V OpenSBI", }, + { IH_OS_EFI, "efi", "EFI Firmware" }, { -1, "", "", }, }; diff --git a/include/image.h b/include/image.h index f4d2aaf53e..4a280b78e7 100644 --- a/include/image.h +++ b/include/image.h @@ -157,6 +157,7 @@ enum { IH_OS_ARM_TRUSTED_FIRMWARE, /* ARM Trusted Firmware */ IH_OS_TEE, /* Trusted Execution Environment */ IH_OS_OPENSBI, /* RISC-V OpenSBI */ + IH_OS_EFI, /* EFI Firmware (e.g. GRUB2) */ IH_OS_COUNT, }; -- 2.17.1
Re: [U-Boot] [PATCH 0/2] Add support for booting EFI FIT images
On Sun, Dec 08, 2019 at 01:25:27AM +0100, Heinrich Schuchardt wrote: > On 11/28/19 8:20 AM, Heinrich Schuchardt wrote: > > On 11/27/19 8:45 PM, Cristian Ciocaltea wrote: > > > On Tue, Nov 26, 2019 at 07:31:39PM +0100, Heinrich Schuchardt wrote: > > > > On 11/24/19 9:11 PM, Cristian Ciocaltea wrote: > > > > > Currently the only way to run an EFI binary like GRUB2 is via the > > > > > 'bootefi' command, which cannot be used in a verified boot scenario. > > > > > > > > > > The obvious solution to this limitation is to add support for > > > > > booting FIT images containing those EFI binaries. > > > > > > > > > > The implementation relies on a new image type - IH_OS_EFI - which > > > > > can be created by using 'os = "efi"' inside an ITS file: > > > > > > > > > > / { > > > > > #address-cells = <1>; > > > > > > > > > > images { > > > > > efi-grub { > > > > > description = "GRUB EFI"; > > > > > data = /incbin/("EFI/BOOT/bootarm.efi"); > > > > > type = "kernel_noload"; > > > > > arch = "arm"; > > > > > os = "efi"; > > > > > compression = "none"; > > > > > load = <0x0>; > > > > > entry = <0x0>; > > > > > hash-1 { > > > > > algo = "sha256"; > > > > > }; > > > > > }; > > > > > }; > > > > > > > > > > configurations { > > > > > default = "config-grub"; > > > > > config-grub { > > > > > kernel = "efi-grub"; > > > > > signature-1 { > > > > > algo = "sha256,rsa2048"; > > > > > sign-images = "kernel"; > > > > > }; > > > > > }; > > > > > }; > > > > > }; > > > > > > > > > > The bootm command has been extended to handle the IH_OS_EFI images. > > > > > To enable this feature, a new configuration option has been added: > > > > > BOOTM_EFI > > > > > > > > > > I tested the solution using the 'qemu_arm' board: > > > > > > > > > > => load scsi 0:1 ${kernel_addr_r} efi-image.fit > > > > > => bootm ${kernel_addr_r}#config-grub > > > > > > > > Thanks a lot for the patch series which makes good sense to me. > > > > > > > > I think we should pass addresses and not strings to cmd/bootefi.c. This > > > > will need a bit of refactoring as already addressed in a comment to > > > > patch 2/2. > > > > > > > > Additionally the documentation in doc/uefi/u-boot_on_efi.rst and > > > > doc/uImage.FIT/howto.txt should be updated. > > > > > > > > I cc the contributors given by > > > > scripts/get_maintainer.pl -f common/bootm_os.c > > > > > > > > Best regards > > > > > > > > Heinrich > > > > > > > > > > Thanks for the feedback, Heinrich! > > > > > > Instead of creating new function(s), I think we could simply extend > > > int do_bootefi_image(const char *image_opt) > > > with a new parameter to hold the fdt address and move here the call > > > to 'efi_install_fdt()', which is now performed by 'do_bootefi()'. > > > > efi_install_fdt() has to be called for the 'bootefi bootmgr' command too > > so the refactoring is a bit more complicated. I have started on that. > > > > The first step is to change efi_install_fdt() to expect the argument as > > address instead of a string. > > > > https://github.com/xypron/u-boot-patches/blob/efi-next/0001-efi_loader-pass-address-to-efi_install_fdt.patch > > > > > > fdt_addr==NULL indicates no device tree supplied by user. > > > > Best regards > > > > Heinrich > > > > > > > > However, I'm not sure about changing the data types, i.e. from > > > 'char *' to ulong, for the following reasons: > > > 1. image
Re: [U-Boot] [PATCH 0/2] Add support for booting EFI FIT images
On Tue, Nov 26, 2019 at 07:31:39PM +0100, Heinrich Schuchardt wrote: > On 11/24/19 9:11 PM, Cristian Ciocaltea wrote: > > Currently the only way to run an EFI binary like GRUB2 is via the > > 'bootefi' command, which cannot be used in a verified boot scenario. > > > > The obvious solution to this limitation is to add support for > > booting FIT images containing those EFI binaries. > > > > The implementation relies on a new image type - IH_OS_EFI - which > > can be created by using 'os = "efi"' inside an ITS file: > > > > / { > > #address-cells = <1>; > > > > images { > > efi-grub { > > description = "GRUB EFI"; > > data = /incbin/("EFI/BOOT/bootarm.efi"); > > type = "kernel_noload"; > > arch = "arm"; > > os = "efi"; > > compression = "none"; > > load = <0x0>; > > entry = <0x0>; > > hash-1 { > > algo = "sha256"; > > }; > > }; > > }; > > > > configurations { > > default = "config-grub"; > > config-grub { > > kernel = "efi-grub"; > > signature-1 { > > algo = "sha256,rsa2048"; > > sign-images = "kernel"; > > }; > > }; > > }; > > }; > > > > The bootm command has been extended to handle the IH_OS_EFI images. > > To enable this feature, a new configuration option has been added: > > BOOTM_EFI > > > > I tested the solution using the 'qemu_arm' board: > > > > => load scsi 0:1 ${kernel_addr_r} efi-image.fit > > => bootm ${kernel_addr_r}#config-grub > > Thanks a lot for the patch series which makes good sense to me. > > I think we should pass addresses and not strings to cmd/bootefi.c. This > will need a bit of refactoring as already addressed in a comment to > patch 2/2. > > Additionally the documentation in doc/uefi/u-boot_on_efi.rst and > doc/uImage.FIT/howto.txt should be updated. > > I cc the contributors given by > scripts/get_maintainer.pl -f common/bootm_os.c > > Best regards > > Heinrich > Thanks for the feedback, Heinrich! Instead of creating new function(s), I think we could simply extend int do_bootefi_image(const char *image_opt) with a new parameter to hold the fdt address and move here the call to 'efi_install_fdt()', which is now performed by 'do_bootefi()'. However, I'm not sure about changing the data types, i.e. from 'char *' to ulong, for the following reasons: 1. image_opt may have a different meaning in addition to efi address 2. fdt address may not be provided, so we need somehow to detect an invalid value Kind regards, Cristian > > > > > > Cristian Ciocaltea (2): > >image: Add IH_OS_EFI for EFI chain-load boot > >bootm: Add a bootm command for type IH_OS_EFI > > > > cmd/Kconfig| 9 - > > cmd/bootefi.c | 2 +- > > common/bootm_os.c | 44 > > common/image-fit.c | 3 ++- > > common/image.c | 1 + > > include/bootm.h| 2 ++ > > include/image.h| 1 + > > 7 files changed, 59 insertions(+), 3 deletions(-) > > > ___ U-Boot mailing list U-Boot@lists.denx.de https://lists.denx.de/listinfo/u-boot
[U-Boot] [PATCH 1/1] buildman: Improve [make-flags] section parser to allow quoted strings
The parser responsible for the '[make-flags]' section in the '.buildman' settings file is currently not able to handle quoted strings, as given in the sample bellow: [make-flags] qemu_arm=HOSTCC="cc -isystem /add/include" HOSTLDFLAGS="-L/add/lib" This patch replaces the simple string splitter based on the delimiter with a regex tokenizer that preserves spaces inside double quoted strings. Signed-off-by: Cristian Ciocaltea --- tools/buildman/toolchain.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/tools/buildman/toolchain.py b/tools/buildman/toolchain.py index cc26e2ede5..086a4d47cd 100644 --- a/tools/buildman/toolchain.py +++ b/tools/buildman/toolchain.py @@ -435,9 +435,10 @@ class Toolchains: self._make_flags['target'] = board.target arg_str = self.ResolveReferences(self._make_flags, self._make_flags.get(board.target, '')) -args = arg_str.split(' ') +args = re.findall("(?:\".*?\"|\S)+", arg_str) i = 0 while i < len(args): +args[i] = args[i].replace('"', '') if not args[i]: del args[i] else: -- 2.17.1 ___ U-Boot mailing list U-Boot@lists.denx.de https://lists.denx.de/listinfo/u-boot
[U-Boot] [PATCH 1/2] image: Add IH_OS_EFI for EFI chain-load boot
Add a new OS type to be used for chain-loading an EFI compatible firmware or boot loader like GRUB2, possibly in a verified boot scenario. Bellow is sample ITS file that generates a FIT image supporting secure boot. Please note the presence of 'os = "efi";' line, which identifies the currently introduced OS type: / { #address-cells = <1>; images { efi-grub { description = "GRUB EFI"; data = /incbin/("EFI/BOOT/bootarm.efi"); type = "kernel_noload"; arch = "arm"; os = "efi"; compression = "none"; load = <0x0>; entry = <0x0>; hash-1 { algo = "sha256"; }; }; }; configurations { default = "config-grub"; config-grub { kernel = "efi-grub"; signature-1 { algo = "sha256,rsa2048"; sign-images = "kernel"; }; }; }; }; Signed-off-by: Cristian Ciocaltea --- common/image-fit.c | 3 ++- common/image.c | 1 + include/image.h| 1 + 3 files changed, 4 insertions(+), 1 deletion(-) diff --git a/common/image-fit.c b/common/image-fit.c index 5c63c769de..19e313bf41 100644 --- a/common/image-fit.c +++ b/common/image-fit.c @@ -1925,7 +1925,8 @@ int fit_image_load(bootm_headers_t *images, ulong addr, image_type == 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); + fit_image_check_os(fit, noffset, IH_OS_OPENRTOS) || + fit_image_check_os(fit, noffset, IH_OS_EFI); /* * If either of the checks fail, we should report an error, but diff --git a/common/image.c b/common/image.c index f17fa40c49..2e0e2b0e7f 100644 --- a/common/image.c +++ b/common/image.c @@ -134,6 +134,7 @@ static const table_entry_t uimage_os[] = { { IH_OS_OPENRTOS, "openrtos", "OpenRTOS", }, #endif { IH_OS_OPENSBI, "opensbi", "RISC-V OpenSBI", }, + { IH_OS_EFI, "efi", "EFI Firmware" }, { -1, "", "", }, }; diff --git a/include/image.h b/include/image.h index f4d2aaf53e..4a280b78e7 100644 --- a/include/image.h +++ b/include/image.h @@ -157,6 +157,7 @@ enum { IH_OS_ARM_TRUSTED_FIRMWARE, /* ARM Trusted Firmware */ IH_OS_TEE, /* Trusted Execution Environment */ IH_OS_OPENSBI, /* RISC-V OpenSBI */ + IH_OS_EFI, /* EFI Firmware (e.g. GRUB2) */ IH_OS_COUNT, }; -- 2.17.1 ___ U-Boot mailing list U-Boot@lists.denx.de https://lists.denx.de/listinfo/u-boot
[U-Boot] [PATCH 0/2] Add support for booting EFI FIT images
Currently the only way to run an EFI binary like GRUB2 is via the 'bootefi' command, which cannot be used in a verified boot scenario. The obvious solution to this limitation is to add support for booting FIT images containing those EFI binaries. The implementation relies on a new image type - IH_OS_EFI - which can be created by using 'os = "efi"' inside an ITS file: / { #address-cells = <1>; images { efi-grub { description = "GRUB EFI"; data = /incbin/("EFI/BOOT/bootarm.efi"); type = "kernel_noload"; arch = "arm"; os = "efi"; compression = "none"; load = <0x0>; entry = <0x0>; hash-1 { algo = "sha256"; }; }; }; configurations { default = "config-grub"; config-grub { kernel = "efi-grub"; signature-1 { algo = "sha256,rsa2048"; sign-images = "kernel"; }; }; }; }; The bootm command has been extended to handle the IH_OS_EFI images. To enable this feature, a new configuration option has been added: BOOTM_EFI I tested the solution using the 'qemu_arm' board: => load scsi 0:1 ${kernel_addr_r} efi-image.fit => bootm ${kernel_addr_r}#config-grub Cristian Ciocaltea (2): image: Add IH_OS_EFI for EFI chain-load boot bootm: Add a bootm command for type IH_OS_EFI cmd/Kconfig| 9 - cmd/bootefi.c | 2 +- common/bootm_os.c | 44 common/image-fit.c | 3 ++- common/image.c | 1 + include/bootm.h| 2 ++ include/image.h| 1 + 7 files changed, 59 insertions(+), 3 deletions(-) -- 2.17.1 ___ U-Boot mailing list U-Boot@lists.denx.de https://lists.denx.de/listinfo/u-boot
[U-Boot] [PATCH 2/2] bootm: Add a bootm command for type IH_OS_EFI
Add support for booting EFI binaries contained in FIT images. A typical usage scenario is chain-loading GRUB2 in a verified boot environment. Signed-off-by: Cristian Ciocaltea --- cmd/Kconfig | 9 - cmd/bootefi.c | 2 +- common/bootm_os.c | 44 include/bootm.h | 2 ++ 4 files changed, 55 insertions(+), 2 deletions(-) diff --git a/cmd/Kconfig b/cmd/Kconfig index cf982ff65e..1bec840f5a 100644 --- a/cmd/Kconfig +++ b/cmd/Kconfig @@ -263,6 +263,13 @@ config CMD_BOOTI help Boot an AArch64 Linux Kernel image from memory. +config BOOTM_EFI + bool "Support booting EFI OS images" + depends on CMD_BOOTEFI + default y + help + Support booting EFI images via the bootm command. + config BOOTM_LINUX bool "Support booting Linux OS images" depends on CMD_BOOTM || CMD_BOOTZ || CMD_BOOTI @@ -316,7 +323,7 @@ config CMD_BOOTEFI depends on EFI_LOADER default y help - Boot an EFI image from memory. + Boot an EFI binary from memory. config CMD_BOOTEFI_HELLO_COMPILE bool "Compile a standard EFI hello world binary for testing" diff --git a/cmd/bootefi.c b/cmd/bootefi.c index f613cce7e2..f25d639dfe 100644 --- a/cmd/bootefi.c +++ b/cmd/bootefi.c @@ -553,7 +553,7 @@ static int do_efi_selftest(void) * @argv: command line arguments * Return: status code */ -static int do_bootefi(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]) +int do_bootefi(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]) { efi_status_t ret; diff --git a/common/bootm_os.c b/common/bootm_os.c index 6fb7d658da..706151913a 100644 --- a/common/bootm_os.c +++ b/common/bootm_os.c @@ -462,6 +462,47 @@ static int do_bootm_tee(int flag, int argc, char * const argv[], } #endif +#ifdef CONFIG_BOOTM_EFI +static int do_bootm_efi(int flag, int argc, char * const argv[], + bootm_headers_t *images) +{ + int ret; + int local_argc = 2; + char *local_args[3]; + char str_efi_addr[16]; + char str_fdt_addr[16]; + + if (flag != BOOTM_STATE_OS_GO) + return 0; + + /* Locate FDT etc */ + ret = bootm_find_images(flag, argc, argv); + if (ret) + return ret; + + printf("## Transferring control to EFI (at address %08lx) ...\n", + images->ep); + bootstage_mark(BOOTSTAGE_ID_RUN_OS); + + local_args[0] = argv[0]; + + /* Write efi addr into string */ + sprintf(str_efi_addr, "%lx", images->ep); + /* and provide it via the arguments */ + local_args[1] = str_efi_addr; + + if (images->ft_len) { + /* Write fdt addr into string */ + sprintf(str_fdt_addr, "%lx", (unsigned long)images->ft_addr); + /* and provide it via the arguments */ + local_args[2] = str_fdt_addr; + local_argc = 3; + } + + return do_bootefi(NULL, 0, local_argc, local_args); +} +#endif + static boot_os_fn *boot_os[] = { [IH_OS_U_BOOT] = do_bootm_standalone, #ifdef CONFIG_BOOTM_LINUX @@ -498,6 +539,9 @@ static boot_os_fn *boot_os[] = { #ifdef CONFIG_BOOTM_OPTEE [IH_OS_TEE] = do_bootm_tee, #endif +#ifdef CONFIG_BOOTM_EFI + [IH_OS_EFI] = do_bootm_efi, +#endif }; /* Allow for arch specific config before we boot */ diff --git a/include/bootm.h b/include/bootm.h index edeeacb0df..a0da86dc32 100644 --- a/include/bootm.h +++ b/include/bootm.h @@ -37,7 +37,9 @@ typedef int boot_os_fn(int flag, int argc, char * const argv[], extern boot_os_fn do_bootm_linux; extern boot_os_fn do_bootm_vxworks; +int do_bootefi(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]); int do_bootelf(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]); + void lynxkdi_boot(image_header_t *hdr); boot_os_fn *bootm_os_get_boot_func(int os); -- 2.17.1 ___ U-Boot mailing list U-Boot@lists.denx.de https://lists.denx.de/listinfo/u-boot
[U-Boot] [PATCH] api: storage: Add the missing write operation support
API_dev_write(va_list ap) is currently lacking the write support to storage devices because, historically, those devices did not implement block_write() The solution has been tested by loading and booting a (patched) GRUB instance in a QEMU vexpress-a9 environment. The disk write operations were triggered with GRUB's save_env command. Signed-off-by: Cristian Ciocaltea --- api/api.c | 59 ++- api/api_private.h | 1 + api/api_storage.c | 24 +++ 3 files changed, 63 insertions(+), 21 deletions(-) diff --git a/api/api.c b/api/api.c index 9f03f1a35b..f7cfcc9ebc 100644 --- a/api/api.c +++ b/api/api.c @@ -294,27 +294,31 @@ static int API_dev_close(va_list ap) /* - * Notice: this is for sending network packets only, as U-Boot does not - * support writing to storage at the moment (12.2007) - * * pseudo signature: * * int API_dev_write( * struct device_info *di, * void *buf, - * int *len + * int *len, + * unsigned long *start * ) * * buf:ptr to buffer from where to get the data to send * - * len: length of packet to be sent (in bytes) + * len: ptr to length to be read + * - network: len of packet to be sent (in bytes) + * - storage: # of blocks to write (can vary in size depending on define) * + * start: ptr to start block (only used for storage devices, ignored for + *network) */ static int API_dev_write(va_list ap) { struct device_info *di; void *buf; - int *len; + lbasize_t *len_stor, act_len_stor; + lbastart_t *start; + int *len_net; int err = 0; /* 1. arg is ptr to the device_info struct */ @@ -332,23 +336,36 @@ static int API_dev_write(va_list ap) if (buf == NULL) return API_EINVAL; - /* 3. arg is length of buffer */ - len = (int *)va_arg(ap, uintptr_t); - if (len == NULL) - return API_EINVAL; - if (*len <= 0) - return API_EINVAL; + if (di->type & DEV_TYP_STOR) { + /* 3. arg - ptr to var with # of blocks to write */ + len_stor = (lbasize_t *)va_arg(ap, uintptr_t); + if (!len_stor) + return API_EINVAL; + if (*len_stor <= 0) + return API_EINVAL; - if (di->type & DEV_TYP_STOR) - /* -* write to storage is currently not supported by U-Boot: -* no storage device implements block_write() method -*/ - return API_ENODEV; + /* 4. arg - ptr to var with start block */ + start = (lbastart_t *)va_arg(ap, uintptr_t); - else if (di->type & DEV_TYP_NET) - err = dev_write_net(di->cookie, buf, *len); - else + act_len_stor = dev_write_stor(di->cookie, buf, *len_stor, *start); + if (act_len_stor != *len_stor) { + debugf("write @ %llu: done %llu out of %llu blocks", + (uint64_t)blk, (uint64_t)act_len_stor, + (uint64_t)len_stor); + return API_EIO; + } + + } else if (di->type & DEV_TYP_NET) { + /* 3. arg points to the var with length of packet to write */ + len_net = (int *)va_arg(ap, uintptr_t); + if (!len_net) + return API_EINVAL; + if (*len_net <= 0) + return API_EINVAL; + + err = dev_write_net(di->cookie, buf, *len_net); + + } else err = API_ENODEV; return err; diff --git a/api/api_private.h b/api/api_private.h index 8d97ca95a2..07fd50ad3a 100644 --- a/api/api_private.h +++ b/api/api_private.h @@ -22,6 +22,7 @@ int dev_close_stor(void *); intdev_close_net(void *); lbasize_t dev_read_stor(void *, void *, lbasize_t, lbastart_t); +lbasize_t dev_write_stor(void *, void *, lbasize_t, lbastart_t); intdev_read_net(void *, void *, int); intdev_write_net(void *, void *, int); diff --git a/api/api_storage.c b/api/api_storage.c index 2b90c18aae..7ae03ac230 100644 --- a/api/api_storage.c +++ b/api/api_storage.c @@ -349,3 +349,27 @@ lbasize_t dev_read_stor(void *cookie, void *buf, lbasize_t len, lbastart_t start return dd->block_read(dd, start, len, buf); #endif /* defined(CONFIG_BLK) */ } + + +lbasize_t dev_write_stor(void *cookie, void *buf, lbasize_t len, lbastart_t start) +{ + struct blk_desc *dd = (struct blk_desc *)cookie; + int type = dev_stor_type(dd); + + if (type == ENUM_MAX) + return 0; + + if (!dev_stor_is_valid(type, dd)) + return 0; + +#ifdef CONFIG_BLK + return blk_dwrite(dd, start, len, buf); +#else + if (dd->block_write
[U-Boot] [PATCH] api: storage: Fix enumeration of storage devices
dev_stor_get() is not able to find the next available device in the current storage group when the previous enumerated device belongs to a different group or class (e.g. network). The root cause is the device group iterator not being reset after an unsuccessful search for the last returned device so that the following search for the next available device will start from beginning. The issue has been identified by loading and booting GRUB in a QEMU vexpress-a9 environment. Signed-off-by: Cristian Ciocaltea --- api/api_storage.c | 5 + 1 file changed, 5 insertions(+) diff --git a/api/api_storage.c b/api/api_storage.c index 8aeeda2715..2b90c18aae 100644 --- a/api/api_storage.c +++ b/api/api_storage.c @@ -99,6 +99,7 @@ static int dev_stor_get(int type, int *more, struct device_info *di) { struct blk_desc *dd; int found = 0; + int found_last = 0; int i = 0; /* Wasn't configured for this type, return 0 directly */ @@ -111,9 +112,13 @@ static int dev_stor_get(int type, int *more, struct device_info *di) if (di->cookie == (void *)blk_get_dev(specs[type].name, i)) { i += 1; + found_last = 1; break; } } + + if (!found_last) + i = 0; } for (; i < specs[type].max_dev; i++) { -- 2.17.1 ___ U-Boot mailing list U-Boot@lists.denx.de https://lists.denx.de/listinfo/u-boot