public inbox for u-boot@lists.denx.de
 help / color / mirror / Atom feed
* [PATCH v3 0/5] Add support for booting EFI FIT images
@ 2019-12-17  7:46 Cristian Ciocaltea
  2019-12-17  7:46 ` [PATCH v3 1/5] image: Add IH_OS_EFI for EFI chain-load boot Cristian Ciocaltea
                   ` (4 more replies)
  0 siblings, 5 replies; 15+ messages in thread
From: Cristian Ciocaltea @ 2019-12-17  7:46 UTC (permalink / raw)
  To: u-boot

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

^ permalink raw reply	[flat|nested] 15+ messages in thread

* [PATCH v3 1/5] image: Add IH_OS_EFI for EFI chain-load boot
  2019-12-17  7:46 [PATCH v3 0/5] Add support for booting EFI FIT images Cristian Ciocaltea
@ 2019-12-17  7:46 ` Cristian Ciocaltea
  2019-12-17 20:30   ` Heinrich Schuchardt
  2019-12-17  7:46 ` [PATCH v3 2/5] bootm: Add a bootm command for type IH_OS_EFI Cristian Ciocaltea
                   ` (3 subsequent siblings)
  4 siblings, 1 reply; 15+ messages in thread
From: Cristian Ciocaltea @ 2019-12-17  7:46 UTC (permalink / raw)
  To: u-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 <cristian.ciocaltea@gmail.com>
---
 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

^ permalink raw reply related	[flat|nested] 15+ messages in thread

* [PATCH v3 2/5] bootm: Add a bootm command for type IH_OS_EFI
  2019-12-17  7:46 [PATCH v3 0/5] Add support for booting EFI FIT images Cristian Ciocaltea
  2019-12-17  7:46 ` [PATCH v3 1/5] image: Add IH_OS_EFI for EFI chain-load boot Cristian Ciocaltea
@ 2019-12-17  7:46 ` Cristian Ciocaltea
  2019-12-17 20:34   ` Heinrich Schuchardt
  2019-12-17  7:47 ` [PATCH v3 3/5] doc: Add sample uefi.its image description file Cristian Ciocaltea
                   ` (2 subsequent siblings)
  4 siblings, 1 reply; 15+ messages in thread
From: Cristian Ciocaltea @ 2019-12-17  7:46 UTC (permalink / raw)
  To: u-boot

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 <cristian.ciocaltea@gmail.com>
---
 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 <common.h>
 #include <bootm.h>
+#include <efi_loader.h>
 #include <env.h>
 #include <fdt_support.h>
 #include <linux/libfdt.h>
 #include <malloc.h>
+#include <mapmem.h>
 #include <vxworks.h>
 #include <tee/optee.h>
 
@@ -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

^ permalink raw reply related	[flat|nested] 15+ messages in thread

* [PATCH v3 3/5] doc: Add sample uefi.its image description file
  2019-12-17  7:46 [PATCH v3 0/5] Add support for booting EFI FIT images Cristian Ciocaltea
  2019-12-17  7:46 ` [PATCH v3 1/5] image: Add IH_OS_EFI for EFI chain-load boot Cristian Ciocaltea
  2019-12-17  7:46 ` [PATCH v3 2/5] bootm: Add a bootm command for type IH_OS_EFI Cristian Ciocaltea
@ 2019-12-17  7:47 ` Cristian Ciocaltea
  2019-12-17  7:47 ` [PATCH v3 4/5] doc: uefi.rst: Document launching UEFI binaries from FIT images Cristian Ciocaltea
  2019-12-17  7:47 ` [PATCH v3 5/5] test/py: Create a test for " Cristian Ciocaltea
  4 siblings, 0 replies; 15+ messages in thread
From: Cristian Ciocaltea @ 2019-12-17  7:47 UTC (permalink / raw)
  To: u-boot

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 <cristian.ciocaltea@gmail.com>
Reviewed-by: Heinrich Schuchardt <xypron.glpk@gmx.de>
---
 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 0000000000..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

^ permalink raw reply related	[flat|nested] 15+ messages in thread

* [PATCH v3 4/5] doc: uefi.rst: Document launching UEFI binaries from FIT images
  2019-12-17  7:46 [PATCH v3 0/5] Add support for booting EFI FIT images Cristian Ciocaltea
                   ` (2 preceding siblings ...)
  2019-12-17  7:47 ` [PATCH v3 3/5] doc: Add sample uefi.its image description file Cristian Ciocaltea
@ 2019-12-17  7:47 ` Cristian Ciocaltea
  2019-12-17  7:47 ` [PATCH v3 5/5] test/py: Create a test for " Cristian Ciocaltea
  4 siblings, 0 replies; 15+ messages in thread
From: Cristian Ciocaltea @ 2019-12-17  7:47 UTC (permalink / raw)
  To: u-boot

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 <cristian.ciocaltea@gmail.com>
Reviewed-by: Heinrich Schuchardt <xypron.glpk@gmx.de>
---
 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 40400000 ...
+       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

^ permalink raw reply related	[flat|nested] 15+ messages in thread

* [PATCH v3 5/5] test/py: Create a test for launching UEFI binaries from FIT images
  2019-12-17  7:46 [PATCH v3 0/5] Add support for booting EFI FIT images Cristian Ciocaltea
                   ` (3 preceding siblings ...)
  2019-12-17  7:47 ` [PATCH v3 4/5] doc: uefi.rst: Document launching UEFI binaries from FIT images Cristian Ciocaltea
@ 2019-12-17  7:47 ` Cristian Ciocaltea
  2019-12-17 21:08   ` Heinrich Schuchardt
  4 siblings, 1 reply; 15+ messages in thread
From: Cristian Ciocaltea @ 2019-12-17  7:47 UTC (permalink / raw)
  To: u-boot

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 <cristian.ciocaltea@gmail.com>
---
 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 0000000000..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 <cristian.ciocaltea@gmail.com>
+
+# 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 at 0 {
+        compatible = "sandbox,reset";
+    };
+};
+'''
+
+ at pytest.mark.boardspec('sandbox')
+ at pytest.mark.buildconfigspec('bootm_efi')
+ at pytest.mark.buildconfigspec('cmd_bootefi_hello_compile')
+ at 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):
+        """Create a sample FIT image.
+
+        Runs 'mkimage' to create a FIT image within U-Boot build dir.
+        Args:
+            efi_comp: Enable gzip compression for the EFI binary.
+            fdt_comp: Enable gzip compression for the FDT blob.
+        Return:
+            The path of the created file.
+        """
+        # Generate resources referenced by ITS.
+        its_params = {
+            'efi-bin' : os.path.basename(
+                            make_efi('test-efi-fit-sandbox.efi', efi_comp)),
+            'kernel-type' : 'kernel' if efi_comp else 'kernel_noload',
+            'efi-comp' : 'gzip' if efi_comp else 'none',
+            'fdt-bin' : os.path.basename(make_dtb('user', fdt_comp)),
+            'fdt-comp' : 'gzip' if fdt_comp else 'none',
+        }
+
+        # Generate a test ITS file.
+        its_path = make_fpath('test-efi-fit.its')
+        with open(its_path, 'w') as fd:
+            fd.write(its_data % its_params)
+
+        # Build the test ITS.
+        fit_path = make_fpath('test-efi-fit.fit')
+        util.run_and_log(u_boot_console,
+            [make_fpath('tools/mkimage'), '-f', its_path, fit_path])
+        return fit_path
+
+    def file_size(fpath):
+        """Get the size of a file.
+
+        Args:
+            fname: Path of the file to check.
+        Return:
+            The size of file in bytes.
+        """
+        return os.stat(fpath).st_size
+
+    def launch_efi(enable_fdt, enable_comp):
+        """Launch a UEFI binary from a FIT image.
+
+        Creates a test FIT image containing a fake UEFI binary and tries
+        to run it via the 'bootm' command in the U-Boot console.
+
+        Args:
+            enable_fdt: Flag to enable using the FDT blob inside FIT image.
+            enable_comp: Flag to enable gzip compression on EFI and FDT content.
+        """
+        # Create test FIT image.
+        fit_img_path = make_fit(enable_comp, enable_comp)
+
+        # Select boot configuration.
+        fit_config = 'config-efi-fdt' if enable_fdt else 'config-efi-nofdt'
+
+        # Run U-Boot commands.
+        with u_boot_console.log.section('Boot EFI FIT %s' % fit_config):
+            output = u_boot_console.run_command(
+                'host load hostfs - $kernel_addr_r %s' % fit_img_path)
+
+            expected_text = '%d bytes read' % file_size(fit_img_path)
+            assert(expected_text in output)
+
+            output = u_boot_console.run_command(
+                'bootm ${kernel_addr_r}#%s' % fit_config)
+
+            if enable_fdt:
+                expected_text = 'Booting using the fdt blob'
+                assert(expected_text in output)
+
+            expected_text = 'Hello, world'
+            assert expected_text in output
+            expected_text = '## Application terminated, r = 0'
+            assert expected_text in output
+
+    try:
+        # Use our own device tree file, will be restored afterwards.
+        control_dtb = make_dtb('internal', False)
+        old_dtb = u_boot_console.config.dtb
+        u_boot_console.config.dtb = control_dtb
+
+        # Run tests
+        # - fdt ON, gzip OFF
+        launch_efi(True, False)
+        # - fdt ON, gzip ON
+        launch_efi(True, True)
+        # - fdt OFF, gzip OFF
+        launch_efi(False, False)
+        # - fdt OFF, gzip ON
+        launch_efi(False, True)
+
+    finally:
+        # Go back to the original U-Boot with the correct dtb.
+        u_boot_console.config.dtb = old_dtb
+        u_boot_console.restart_uboot()
-- 
2.17.1

^ permalink raw reply related	[flat|nested] 15+ messages in thread

* [PATCH v3 1/5] image: Add IH_OS_EFI for EFI chain-load boot
  2019-12-17  7:46 ` [PATCH v3 1/5] image: Add IH_OS_EFI for EFI chain-load boot Cristian Ciocaltea
@ 2019-12-17 20:30   ` Heinrich Schuchardt
  0 siblings, 0 replies; 15+ messages in thread
From: Heinrich Schuchardt @ 2019-12-17 20:30 UTC (permalink / raw)
  To: u-boot

On 12/17/19 8:46 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/("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 <cristian.ciocaltea@gmail.com>

Reviewed-by: Heinrich Schuchardt <xypron.glpk@gmx.de>

^ permalink raw reply	[flat|nested] 15+ messages in thread

* [PATCH v3 2/5] bootm: Add a bootm command for type IH_OS_EFI
  2019-12-17  7:46 ` [PATCH v3 2/5] bootm: Add a bootm command for type IH_OS_EFI Cristian Ciocaltea
@ 2019-12-17 20:34   ` Heinrich Schuchardt
  2019-12-18  8:27     ` Cristian Ciocaltea
  0 siblings, 1 reply; 15+ messages in thread
From: Heinrich Schuchardt @ 2019-12-17 20:34 UTC (permalink / raw)
  To: u-boot

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 <cristian.ciocaltea@gmail.com>

You missed the current changes in common/bootm_os.c. I will rebase the
patch.

Reviewed-by: Heinrich Schuchardt <xypron.glpk@gmx.de>

^ permalink raw reply	[flat|nested] 15+ messages in thread

* [PATCH v3 5/5] test/py: Create a test for launching UEFI binaries from FIT images
  2019-12-17  7:47 ` [PATCH v3 5/5] test/py: Create a test for " Cristian Ciocaltea
@ 2019-12-17 21:08   ` Heinrich Schuchardt
  2019-12-18  8:22     ` Cristian Ciocaltea
  0 siblings, 1 reply; 15+ messages in thread
From: Heinrich Schuchardt @ 2019-12-17 21:08 UTC (permalink / raw)
  To: u-boot

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 <cristian.ciocaltea@gmail.com>
> ---
>   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 0000000000..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 <cristian.ciocaltea@gmail.com>
> +
> +# 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 at 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 at 0: node has a unit name, but no reg property

> +    };
> +};
> +'''
> +
> + at pytest.mark.boardspec('sandbox')

This test looks ok in principal. But why should we restrict it to the
sandbox?

Best regards

Heinrich

> + at pytest.mark.buildconfigspec('bootm_efi')
> + at pytest.mark.buildconfigspec('cmd_bootefi_hello_compile')
> + at 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):
> +        """Create a sample FIT image.
> +
> +        Runs 'mkimage' to create a FIT image within U-Boot build dir.
> +        Args:
> +            efi_comp: Enable gzip compression for the EFI binary.
> +            fdt_comp: Enable gzip compression for the FDT blob.
> +        Return:
> +            The path of the created file.
> +        """
> +        # Generate resources referenced by ITS.
> +        its_params = {
> +            'efi-bin' : os.path.basename(
> +                            make_efi('test-efi-fit-sandbox.efi', efi_comp)),
> +            'kernel-type' : 'kernel' if efi_comp else 'kernel_noload',
> +            'efi-comp' : 'gzip' if efi_comp else 'none',
> +            'fdt-bin' : os.path.basename(make_dtb('user', fdt_comp)),
> +            'fdt-comp' : 'gzip' if fdt_comp else 'none',
> +        }
> +
> +        # Generate a test ITS file.
> +        its_path = make_fpath('test-efi-fit.its')
> +        with open(its_path, 'w') as fd:
> +            fd.write(its_data % its_params)
> +
> +        # Build the test ITS.
> +        fit_path = make_fpath('test-efi-fit.fit')
> +        util.run_and_log(u_boot_console,
> +            [make_fpath('tools/mkimage'), '-f', its_path, fit_path])
> +        return fit_path
> +
> +    def file_size(fpath):
> +        """Get the size of a file.
> +
> +        Args:
> +            fname: Path of the file to check.
> +        Return:
> +            The size of file in bytes.
> +        """
> +        return os.stat(fpath).st_size
> +
> +    def launch_efi(enable_fdt, enable_comp):
> +        """Launch a UEFI binary from a FIT image.
> +
> +        Creates a test FIT image containing a fake UEFI binary and tries
> +        to run it via the 'bootm' command in the U-Boot console.
> +
> +        Args:
> +            enable_fdt: Flag to enable using the FDT blob inside FIT image.
> +            enable_comp: Flag to enable gzip compression on EFI and FDT content.
> +        """
> +        # Create test FIT image.
> +        fit_img_path = make_fit(enable_comp, enable_comp)
> +
> +        # Select boot configuration.
> +        fit_config = 'config-efi-fdt' if enable_fdt else 'config-efi-nofdt'
> +
> +        # Run U-Boot commands.
> +        with u_boot_console.log.section('Boot EFI FIT %s' % fit_config):
> +            output = u_boot_console.run_command(
> +                'host load hostfs - $kernel_addr_r %s' % fit_img_path)
> +
> +            expected_text = '%d bytes read' % file_size(fit_img_path)
> +            assert(expected_text in output)
> +
> +            output = u_boot_console.run_command(
> +                'bootm ${kernel_addr_r}#%s' % fit_config)
> +
> +            if enable_fdt:
> +                expected_text = 'Booting using the fdt blob'
> +                assert(expected_text in output)
> +
> +            expected_text = 'Hello, world'
> +            assert expected_text in output
> +            expected_text = '## Application terminated, r = 0'
> +            assert expected_text in output
> +
> +    try:
> +        # Use our own device tree file, will be restored afterwards.
> +        control_dtb = make_dtb('internal', False)
> +        old_dtb = u_boot_console.config.dtb
> +        u_boot_console.config.dtb = control_dtb
> +
> +        # Run tests
> +        # - fdt ON, gzip OFF
> +        launch_efi(True, False)
> +        # - fdt ON, gzip ON
> +        launch_efi(True, True)
> +        # - fdt OFF, gzip OFF
> +        launch_efi(False, False)
> +        # - fdt OFF, gzip ON
> +        launch_efi(False, True)
> +
> +    finally:
> +        # Go back to the original U-Boot with the correct dtb.
> +        u_boot_console.config.dtb = old_dtb
> +        u_boot_console.restart_uboot()
>

^ permalink raw reply	[flat|nested] 15+ messages in thread

* [PATCH v3 5/5] test/py: Create a test for launching UEFI binaries from FIT images
  2019-12-17 21:08   ` Heinrich Schuchardt
@ 2019-12-18  8:22     ` Cristian Ciocaltea
  2019-12-18 10:06       ` Heinrich Schuchardt
  2019-12-18 10:56       ` Heinrich Schuchardt
  0 siblings, 2 replies; 15+ messages in thread
From: Cristian Ciocaltea @ 2019-12-18  8:22 UTC (permalink / raw)
  To: u-boot

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 <cristian.ciocaltea@gmail.com>
> > ---
> >   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 0000000000..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 <cristian.ciocaltea@gmail.com>
> > +
> > +# 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 at 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 at 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'.

> > +    };
> > +};
> > +'''
> > +
> > + at 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
> 
> > + at pytest.mark.buildconfigspec('bootm_efi')
> > + at pytest.mark.buildconfigspec('cmd_bootefi_hello_compile')
> > + at 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):
> > +        """Create a sample FIT image.
> > +
> > +        Runs 'mkimage' to create a FIT image within U-Boot build dir.
> > +        Args:
> > +            efi_comp: Enable gzip compression for the EFI binary.
> > +            fdt_comp: Enable gzip compression for the FDT blob.
> > +        Return:
> > +            The path of the created file.
> > +        """
> > +        # Generate resources referenced by ITS.
> > +        its_params = {
> > +            'efi-bin' : os.path.basename(
> > +                            make_efi('test-efi-fit-sandbox.efi', efi_comp)),
> > +            'kernel-type' : 'kernel' if efi_comp else 'kernel_noload',
> > +            'efi-comp' : 'gzip' if efi_comp else 'none',
> > +            'fdt-bin' : os.path.basename(make_dtb('user', fdt_comp)),
> > +            'fdt-comp' : 'gzip' if fdt_comp else 'none',
> > +        }
> > +
> > +        # Generate a test ITS file.
> > +        its_path = make_fpath('test-efi-fit.its')
> > +        with open(its_path, 'w') as fd:
> > +            fd.write(its_data % its_params)
> > +
> > +        # Build the test ITS.
> > +        fit_path = make_fpath('test-efi-fit.fit')
> > +        util.run_and_log(u_boot_console,
> > +            [make_fpath('tools/mkimage'), '-f', its_path, fit_path])
> > +        return fit_path
> > +
> > +    def file_size(fpath):
> > +        """Get the size of a file.
> > +
> > +        Args:
> > +            fname: Path of the file to check.
> > +        Return:
> > +            The size of file in bytes.
> > +        """
> > +        return os.stat(fpath).st_size
> > +
> > +    def launch_efi(enable_fdt, enable_comp):
> > +        """Launch a UEFI binary from a FIT image.
> > +
> > +        Creates a test FIT image containing a fake UEFI binary and tries
> > +        to run it via the 'bootm' command in the U-Boot console.
> > +
> > +        Args:
> > +            enable_fdt: Flag to enable using the FDT blob inside FIT image.
> > +            enable_comp: Flag to enable gzip compression on EFI and FDT content.
> > +        """
> > +        # Create test FIT image.
> > +        fit_img_path = make_fit(enable_comp, enable_comp)
> > +
> > +        # Select boot configuration.
> > +        fit_config = 'config-efi-fdt' if enable_fdt else 'config-efi-nofdt'
> > +
> > +        # Run U-Boot commands.
> > +        with u_boot_console.log.section('Boot EFI FIT %s' % fit_config):
> > +            output = u_boot_console.run_command(
> > +                'host load hostfs - $kernel_addr_r %s' % fit_img_path)
> > +
> > +            expected_text = '%d bytes read' % file_size(fit_img_path)
> > +            assert(expected_text in output)
> > +
> > +            output = u_boot_console.run_command(
> > +                'bootm ${kernel_addr_r}#%s' % fit_config)
> > +
> > +            if enable_fdt:
> > +                expected_text = 'Booting using the fdt blob'
> > +                assert(expected_text in output)
> > +
> > +            expected_text = 'Hello, world'
> > +            assert expected_text in output
> > +            expected_text = '## Application terminated, r = 0'
> > +            assert expected_text in output
> > +
> > +    try:
> > +        # Use our own device tree file, will be restored afterwards.
> > +        control_dtb = make_dtb('internal', False)
> > +        old_dtb = u_boot_console.config.dtb
> > +        u_boot_console.config.dtb = control_dtb
> > +
> > +        # Run tests
> > +        # - fdt ON, gzip OFF
> > +        launch_efi(True, False)
> > +        # - fdt ON, gzip ON
> > +        launch_efi(True, True)
> > +        # - fdt OFF, gzip OFF
> > +        launch_efi(False, False)
> > +        # - fdt OFF, gzip ON
> > +        launch_efi(False, True)
> > +
> > +    finally:
> > +        # Go back to the original U-Boot with the correct dtb.
> > +        u_boot_console.config.dtb = old_dtb
> > +        u_boot_console.restart_uboot()
> > 
> 

^ permalink raw reply	[flat|nested] 15+ messages in thread

* [PATCH v3 2/5] bootm: Add a bootm command for type IH_OS_EFI
  2019-12-17 20:34   ` Heinrich Schuchardt
@ 2019-12-18  8:27     ` Cristian Ciocaltea
  0 siblings, 0 replies; 15+ messages in thread
From: Cristian Ciocaltea @ 2019-12-18  8:27 UTC (permalink / raw)
  To: u-boot

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 <cristian.ciocaltea@gmail.com>
> 
> 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 <xypron.glpk@gmx.de>

^ permalink raw reply	[flat|nested] 15+ messages in thread

* [PATCH v3 5/5] test/py: Create a test for launching UEFI binaries from FIT images
  2019-12-18  8:22     ` Cristian Ciocaltea
@ 2019-12-18 10:06       ` Heinrich Schuchardt
  2019-12-18 15:07         ` Cristian Ciocaltea
  2019-12-18 10:56       ` Heinrich Schuchardt
  1 sibling, 1 reply; 15+ messages in thread
From: Heinrich Schuchardt @ 2019-12-18 10:06 UTC (permalink / raw)
  To: u-boot

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 <cristian.ciocaltea@gmail.com>
>>> ---
>>>    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 0000000000..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 <cristian.ciocaltea@gmail.com>
>>> +
>>> +# 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 at 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 at 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 at 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";

	reset at 0 {
		compatible = "sandbox,reset";
		reg = <0>;
	};
};

Best regards

Heinrich

>
>>> +    };
>>> +};
>>> +'''
>>> +
>>> + at 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
>>
>>> + at pytest.mark.buildconfigspec('bootm_efi')
>>> + at pytest.mark.buildconfigspec('cmd_bootefi_hello_compile')
>>> + at 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):
>>> +        """Create a sample FIT image.
>>> +
>>> +        Runs 'mkimage' to create a FIT image within U-Boot build dir.
>>> +        Args:
>>> +            efi_comp: Enable gzip compression for the EFI binary.
>>> +            fdt_comp: Enable gzip compression for the FDT blob.
>>> +        Return:
>>> +            The path of the created file.
>>> +        """
>>> +        # Generate resources referenced by ITS.
>>> +        its_params = {
>>> +            'efi-bin' : os.path.basename(
>>> +                            make_efi('test-efi-fit-sandbox.efi', efi_comp)),
>>> +            'kernel-type' : 'kernel' if efi_comp else 'kernel_noload',
>>> +            'efi-comp' : 'gzip' if efi_comp else 'none',
>>> +            'fdt-bin' : os.path.basename(make_dtb('user', fdt_comp)),
>>> +            'fdt-comp' : 'gzip' if fdt_comp else 'none',
>>> +        }
>>> +
>>> +        # Generate a test ITS file.
>>> +        its_path = make_fpath('test-efi-fit.its')
>>> +        with open(its_path, 'w') as fd:
>>> +            fd.write(its_data % its_params)
>>> +
>>> +        # Build the test ITS.
>>> +        fit_path = make_fpath('test-efi-fit.fit')
>>> +        util.run_and_log(u_boot_console,
>>> +            [make_fpath('tools/mkimage'), '-f', its_path, fit_path])
>>> +        return fit_path
>>> +
>>> +    def file_size(fpath):
>>> +        """Get the size of a file.
>>> +
>>> +        Args:
>>> +            fname: Path of the file to check.
>>> +        Return:
>>> +            The size of file in bytes.
>>> +        """
>>> +        return os.stat(fpath).st_size
>>> +
>>> +    def launch_efi(enable_fdt, enable_comp):
>>> +        """Launch a UEFI binary from a FIT image.
>>> +
>>> +        Creates a test FIT image containing a fake UEFI binary and tries
>>> +        to run it via the 'bootm' command in the U-Boot console.
>>> +
>>> +        Args:
>>> +            enable_fdt: Flag to enable using the FDT blob inside FIT image.
>>> +            enable_comp: Flag to enable gzip compression on EFI and FDT content.
>>> +        """
>>> +        # Create test FIT image.
>>> +        fit_img_path = make_fit(enable_comp, enable_comp)
>>> +
>>> +        # Select boot configuration.
>>> +        fit_config = 'config-efi-fdt' if enable_fdt else 'config-efi-nofdt'
>>> +
>>> +        # Run U-Boot commands.
>>> +        with u_boot_console.log.section('Boot EFI FIT %s' % fit_config):
>>> +            output = u_boot_console.run_command(
>>> +                'host load hostfs - $kernel_addr_r %s' % fit_img_path)
>>> +
>>> +            expected_text = '%d bytes read' % file_size(fit_img_path)
>>> +            assert(expected_text in output)
>>> +
>>> +            output = u_boot_console.run_command(
>>> +                'bootm ${kernel_addr_r}#%s' % fit_config)
>>> +
>>> +            if enable_fdt:
>>> +                expected_text = 'Booting using the fdt blob'
>>> +                assert(expected_text in output)
>>> +
>>> +            expected_text = 'Hello, world'
>>> +            assert expected_text in output
>>> +            expected_text = '## Application terminated, r = 0'
>>> +            assert expected_text in output
>>> +
>>> +    try:
>>> +        # Use our own device tree file, will be restored afterwards.
>>> +        control_dtb = make_dtb('internal', False)
>>> +        old_dtb = u_boot_console.config.dtb
>>> +        u_boot_console.config.dtb = control_dtb
>>> +
>>> +        # Run tests
>>> +        # - fdt ON, gzip OFF
>>> +        launch_efi(True, False)
>>> +        # - fdt ON, gzip ON
>>> +        launch_efi(True, True)
>>> +        # - fdt OFF, gzip OFF
>>> +        launch_efi(False, False)
>>> +        # - fdt OFF, gzip ON
>>> +        launch_efi(False, True)
>>> +
>>> +    finally:
>>> +        # Go back to the original U-Boot with the correct dtb.
>>> +        u_boot_console.config.dtb = old_dtb
>>> +        u_boot_console.restart_uboot()
>>>
>>
>

^ permalink raw reply	[flat|nested] 15+ messages in thread

* [PATCH v3 5/5] test/py: Create a test for launching UEFI binaries from FIT images
  2019-12-18  8:22     ` Cristian Ciocaltea
  2019-12-18 10:06       ` Heinrich Schuchardt
@ 2019-12-18 10:56       ` Heinrich Schuchardt
  2019-12-18 15:50         ` Cristian Ciocaltea
  1 sibling, 1 reply; 15+ messages in thread
From: Heinrich Schuchardt @ 2019-12-18 10:56 UTC (permalink / raw)
  To: u-boot

On 12/18/19 9:22 AM, Cristian Ciocaltea wrote:
>>> +    };
>>> +};
>>> +'''
>>> +
>>> + at 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')

Best regards

Heinrich

^ permalink raw reply	[flat|nested] 15+ messages in thread

* [PATCH v3 5/5] test/py: Create a test for launching UEFI binaries from FIT images
  2019-12-18 10:06       ` Heinrich Schuchardt
@ 2019-12-18 15:07         ` Cristian Ciocaltea
  0 siblings, 0 replies; 15+ messages in thread
From: Cristian Ciocaltea @ 2019-12-18 15:07 UTC (permalink / raw)
  To: u-boot

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 <cristian.ciocaltea@gmail.com>
> > > > ---
> > > >    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 0000000000..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 <cristian.ciocaltea@gmail.com>
> > > > +
> > > > +# 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 at 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 at 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 at 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";
> 
> 	reset at 0 {
> 		compatible = "sandbox,reset";
> 		reg = <0>;
> 	};
> };

Yes, that's a much better approach. It works fine, thanks!

> Best regards
> 
> Heinrich
> 
> > 
> > > > +    };
> > > > +};
> > > > +'''
> > > > +
> > > > + at 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
> > > 
> > > > + at pytest.mark.buildconfigspec('bootm_efi')
> > > > + at pytest.mark.buildconfigspec('cmd_bootefi_hello_compile')
> > > > + at 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):
> > > > +        """Create a sample FIT image.
> > > > +
> > > > +        Runs 'mkimage' to create a FIT image within U-Boot build dir.
> > > > +        Args:
> > > > +            efi_comp: Enable gzip compression for the EFI binary.
> > > > +            fdt_comp: Enable gzip compression for the FDT blob.
> > > > +        Return:
> > > > +            The path of the created file.
> > > > +        """
> > > > +        # Generate resources referenced by ITS.
> > > > +        its_params = {
> > > > +            'efi-bin' : os.path.basename(
> > > > +                            make_efi('test-efi-fit-sandbox.efi', efi_comp)),
> > > > +            'kernel-type' : 'kernel' if efi_comp else 'kernel_noload',
> > > > +            'efi-comp' : 'gzip' if efi_comp else 'none',
> > > > +            'fdt-bin' : os.path.basename(make_dtb('user', fdt_comp)),
> > > > +            'fdt-comp' : 'gzip' if fdt_comp else 'none',
> > > > +        }
> > > > +
> > > > +        # Generate a test ITS file.
> > > > +        its_path = make_fpath('test-efi-fit.its')
> > > > +        with open(its_path, 'w') as fd:
> > > > +            fd.write(its_data % its_params)
> > > > +
> > > > +        # Build the test ITS.
> > > > +        fit_path = make_fpath('test-efi-fit.fit')
> > > > +        util.run_and_log(u_boot_console,
> > > > +            [make_fpath('tools/mkimage'), '-f', its_path, fit_path])
> > > > +        return fit_path
> > > > +
> > > > +    def file_size(fpath):
> > > > +        """Get the size of a file.
> > > > +
> > > > +        Args:
> > > > +            fname: Path of the file to check.
> > > > +        Return:
> > > > +            The size of file in bytes.
> > > > +        """
> > > > +        return os.stat(fpath).st_size
> > > > +
> > > > +    def launch_efi(enable_fdt, enable_comp):
> > > > +        """Launch a UEFI binary from a FIT image.
> > > > +
> > > > +        Creates a test FIT image containing a fake UEFI binary and tries
> > > > +        to run it via the 'bootm' command in the U-Boot console.
> > > > +
> > > > +        Args:
> > > > +            enable_fdt: Flag to enable using the FDT blob inside FIT image.
> > > > +            enable_comp: Flag to enable gzip compression on EFI and FDT content.
> > > > +        """
> > > > +        # Create test FIT image.
> > > > +        fit_img_path = make_fit(enable_comp, enable_comp)
> > > > +
> > > > +        # Select boot configuration.
> > > > +        fit_config = 'config-efi-fdt' if enable_fdt else 'config-efi-nofdt'
> > > > +
> > > > +        # Run U-Boot commands.
> > > > +        with u_boot_console.log.section('Boot EFI FIT %s' % fit_config):
> > > > +            output = u_boot_console.run_command(
> > > > +                'host load hostfs - $kernel_addr_r %s' % fit_img_path)
> > > > +
> > > > +            expected_text = '%d bytes read' % file_size(fit_img_path)
> > > > +            assert(expected_text in output)
> > > > +
> > > > +            output = u_boot_console.run_command(
> > > > +                'bootm ${kernel_addr_r}#%s' % fit_config)
> > > > +
> > > > +            if enable_fdt:
> > > > +                expected_text = 'Booting using the fdt blob'
> > > > +                assert(expected_text in output)
> > > > +
> > > > +            expected_text = 'Hello, world'
> > > > +            assert expected_text in output
> > > > +            expected_text = '## Application terminated, r = 0'
> > > > +            assert expected_text in output
> > > > +
> > > > +    try:
> > > > +        # Use our own device tree file, will be restored afterwards.
> > > > +        control_dtb = make_dtb('internal', False)
> > > > +        old_dtb = u_boot_console.config.dtb
> > > > +        u_boot_console.config.dtb = control_dtb
> > > > +
> > > > +        # Run tests
> > > > +        # - fdt ON, gzip OFF
> > > > +        launch_efi(True, False)
> > > > +        # - fdt ON, gzip ON
> > > > +        launch_efi(True, True)
> > > > +        # - fdt OFF, gzip OFF
> > > > +        launch_efi(False, False)
> > > > +        # - fdt OFF, gzip ON
> > > > +        launch_efi(False, True)
> > > > +
> > > > +    finally:
> > > > +        # Go back to the original U-Boot with the correct dtb.
> > > > +        u_boot_console.config.dtb = old_dtb
> > > > +        u_boot_console.restart_uboot()
> > > > 
> > > 
> > 
> 

^ permalink raw reply	[flat|nested] 15+ messages in thread

* [PATCH v3 5/5] test/py: Create a test for launching UEFI binaries from FIT images
  2019-12-18 10:56       ` Heinrich Schuchardt
@ 2019-12-18 15:50         ` Cristian Ciocaltea
  0 siblings, 0 replies; 15+ messages in thread
From: Cristian Ciocaltea @ 2019-12-18 15:50 UTC (permalink / raw)
  To: u-boot

On Wed, Dec 18, 2019 at 11:56:00AM +0100, Heinrich Schuchardt wrote:
> On 12/18/19 9:22 AM, Cristian Ciocaltea wrote:
> > > > +    };
> > > > +};
> > > > +'''
> > > > +
> > > > + at 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

^ permalink raw reply	[flat|nested] 15+ messages in thread

end of thread, other threads:[~2019-12-18 15:50 UTC | newest]

Thread overview: 15+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2019-12-17  7:46 [PATCH v3 0/5] Add support for booting EFI FIT images Cristian Ciocaltea
2019-12-17  7:46 ` [PATCH v3 1/5] image: Add IH_OS_EFI for EFI chain-load boot Cristian Ciocaltea
2019-12-17 20:30   ` Heinrich Schuchardt
2019-12-17  7:46 ` [PATCH v3 2/5] bootm: Add a bootm command for type IH_OS_EFI Cristian Ciocaltea
2019-12-17 20:34   ` Heinrich Schuchardt
2019-12-18  8:27     ` Cristian Ciocaltea
2019-12-17  7:47 ` [PATCH v3 3/5] doc: Add sample uefi.its image description file Cristian Ciocaltea
2019-12-17  7:47 ` [PATCH v3 4/5] doc: uefi.rst: Document launching UEFI binaries from FIT images Cristian Ciocaltea
2019-12-17  7:47 ` [PATCH v3 5/5] test/py: Create a test for " Cristian Ciocaltea
2019-12-17 21:08   ` Heinrich Schuchardt
2019-12-18  8:22     ` Cristian Ciocaltea
2019-12-18 10:06       ` Heinrich Schuchardt
2019-12-18 15:07         ` Cristian Ciocaltea
2019-12-18 10:56       ` Heinrich Schuchardt
2019-12-18 15:50         ` Cristian Ciocaltea

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox