[PATCH v3 5/5] test/py: Create a test for launching UEFI binaries from FIT images
Heinrich Schuchardt
xypron.glpk at gmx.de
Wed Dec 18 11:06:48 CET 2019
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 at 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 at 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()
>>>
>>
>
More information about the U-Boot
mailing list