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.ciocal...@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.ciocal...@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@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";

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

Best regards

Heinrich


+    };
+};
+'''
+
+@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):
+        """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()




Reply via email to