[U-Boot] [PATCH 0/4] efi_laoder: Add travis test coverage

Now that we have Travis-CI support in U-Boot as well as a simple hello world efi binary test case, we can make use of the two and verify that efi_loader support still works on every commit.
This patch set enables network as well as basic efi_loader test coverage once the uboot-test-hooks pull request at
https://github.com/swarren/uboot-test-hooks/pull/9
is accepted.
Alexander Graf (4): tests: net: Offset downloads to 4MB travis: Add python path for environments tests: Add efi_loader hello world test efi_loader: Allow to compile helloworld.efi w/o bundling it
.travis.yml | 1 + arch/arm/lib/Makefile | 2 +- arch/x86/config.mk | 2 +- arch/x86/lib/Makefile | 2 +- cmd/Kconfig | 15 +++- lib/efi_loader/Makefile | 3 + test/py/tests/test_efi_loader.py | 158 +++++++++++++++++++++++++++++++++++++++ test/py/tests/test_net.py | 4 +- 8 files changed, 181 insertions(+), 6 deletions(-) create mode 100644 test/py/tests/test_efi_loader.py

The network test currently downloads files at 0MB offset of RAM start. This works for most ARM systems, but x86 has weird memory layout constraints on the first MB of RAM.
To not get caught into any of these, let's add a 4MB pad from start of RAM to the default memory offset.
Signed-off-by: Alexander Graf agraf@suse.de --- test/py/tests/test_net.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/test/py/tests/test_net.py b/test/py/tests/test_net.py index 0884051..293b73a 100644 --- a/test/py/tests/test_net.py +++ b/test/py/tests/test_net.py @@ -147,7 +147,7 @@ def test_net_tftpboot(u_boot_console):
addr = f.get('addr', None) if not addr: - addr = u_boot_utils.find_ram_base(u_boot_console) + addr = u_boot_utils.find_ram_base(u_boot_console) + (1024 * 1024 * 4)
fn = f['fn'] output = u_boot_console.run_command('tftpboot %x %s' % (addr, fn)) @@ -187,7 +187,7 @@ def test_net_nfs(u_boot_console):
addr = f.get('addr', None) if not addr: - addr = u_boot_utils.find_ram_base(u_boot_console) + addr = u_boot_utils.find_ram_base(u_boot_console) + (1024 * 1024 * 4)
fn = f['fn'] output = u_boot_console.run_command('nfs %x %s' % (addr, fn))

When running in travis-ci, we want to pass environment configuration to the tests. These reside in a path available through PYTHONPATH, so let's define that one to point to the unit test repo.
Signed-off-by: Alexander Graf agraf@suse.de --- .travis.yml | 1 + 1 file changed, 1 insertion(+)
diff --git a/.travis.yml b/.travis.yml index 3d7fffe..94cddee 100644 --- a/.travis.yml +++ b/.travis.yml @@ -49,6 +49,7 @@ install: env: global: - PATH=/tmp/dtc:/tmp/uboot-test-hooks/bin:$PATH + - PYTHONPATH=/tmp/uboot-test-hooks/py/travis-ci - BUILD_DIR=build - HOSTCC="cc" - HOSTCXX="c++"

Now that we have working network tests and a hello world efi application built inside our tree, we can automatically test that efi binary running inside of U-Boot.
Signed-off-by: Alexander Graf agraf@suse.de --- test/py/tests/test_efi_loader.py | 158 +++++++++++++++++++++++++++++++++++++++ 1 file changed, 158 insertions(+) create mode 100644 test/py/tests/test_efi_loader.py
diff --git a/test/py/tests/test_efi_loader.py b/test/py/tests/test_efi_loader.py new file mode 100644 index 0000000..1c42653 --- /dev/null +++ b/test/py/tests/test_efi_loader.py @@ -0,0 +1,158 @@ +# Copyright (c) 2016, NVIDIA CORPORATION. All rights reserved. +# Copyright (c) 2016, Alexander Graf agraf@suse.de +# +# based on test_net.py. +# +# SPDX-License-Identifier: GPL-2.0 + +# Test efi loader implementation + +import pytest +import u_boot_utils + +""" +Note: This test relies on boardenv_* containing configuration values to define +which the network environment available for testing. Without this, the parts +that rely on network will be automatically skipped. + +For example: + +# Boolean indicating whether the Ethernet device is attached to USB, and hence +# USB enumeration needs to be performed prior to network tests. +# This variable may be omitted if its value is False. +env__net_uses_usb = False + +# Boolean indicating whether the Ethernet device is attached to PCI, and hence +# PCI enumeration needs to be performed prior to network tests. +# This variable may be omitted if its value is False. +env__net_uses_pci = True + +# True if a DHCP server is attached to the network, and should be tested. +# If DHCP testing is not possible or desired, this variable may be omitted or +# set to False. +env__net_dhcp_server = True + +# A list of environment variables that should be set in order to configure a +# static IP. If solely relying on DHCP, this variable may be omitted or set to +# an empty list. +env__net_static_env_vars = [ + ("ipaddr", "10.0.0.100"), + ("netmask", "255.255.255.0"), + ("serverip", "10.0.0.1"), +] + +# Details regarding a file that may be read from a TFTP server. This variable +# may be omitted or set to None if TFTP testing is not possible or desired. +env__efi_loader_helloworld_file = { + "fn": "lib/efi_loader/helloworld.efi", + "size": 5058624, + "crc32": "c2244b26", +} +""" + +net_set_up = False + +def test_efi_pre_commands(u_boot_console): + """Execute any commands required to enable network hardware. + + These commands are provided by the boardenv_* file; see the comment at the + beginning of this file. + """ + + init_usb = u_boot_console.config.env.get('env__net_uses_usb', False) + if init_usb: + u_boot_console.run_command('usb start') + + init_pci = u_boot_console.config.env.get('env__net_uses_pci', False) + if init_pci: + u_boot_console.run_command('pci enum') + +@pytest.mark.buildconfigspec('cmd_dhcp') +def test_efi_dhcp(u_boot_console): + """Test the dhcp command. + + The boardenv_* file may be used to enable/disable this test; see the + comment at the beginning of this file. + """ + + test_dhcp = u_boot_console.config.env.get('env__net_dhcp_server', False) + if not test_dhcp: + pytest.skip('No DHCP server available') + + u_boot_console.run_command('setenv autoload no') + output = u_boot_console.run_command('dhcp') + assert 'DHCP client bound to address ' in output + + global net_set_up + net_set_up = True + +@pytest.mark.buildconfigspec('net') +def test_efi_setup_static(u_boot_console): + """Set up a static IP configuration. + + The configuration is provided by the boardenv_* file; see the comment at + the beginning of this file. + """ + + env_vars = u_boot_console.config.env.get('env__net_static_env_vars', None) + if not env_vars: + pytest.skip('No static network configuration is defined') + + for (var, val) in env_vars: + u_boot_console.run_command('setenv %s %s' % (var, val)) + + global net_set_up + net_set_up = True + +@pytest.mark.buildconfigspec('cmd_bootefi_hello') +def test_efi_helloworld_net(u_boot_console): + """Run the helloworld.efi binary via TFTP. + + The helloworld.efi file is downloaded from the TFTP server and gets + executed. + """ + + if not net_set_up: + pytest.skip('Network not initialized') + + f = u_boot_console.config.env.get('env__efi_loader_helloworld_file', None) + if not f: + pytest.skip('No hello world binary specified in environment') + + addr = f.get('addr', None) + if not addr: + addr = u_boot_utils.find_ram_base(u_boot_console) + (1024 * 1024 * 4) + + fn = f['fn'] + output = u_boot_console.run_command('tftpboot %x %s' % (addr, fn)) + expected_text = 'Bytes transferred = ' + sz = f.get('size', None) + if sz: + expected_text += '%d' % sz + assert expected_text in output + + expected_crc = f.get('crc32', None) + if not expected_crc: + return + + if u_boot_console.config.buildconfig.get('config_cmd_crc32', 'n') != 'y': + return + + output = u_boot_console.run_command('crc32 %x $filesize' % addr) + assert expected_crc in output + + output = u_boot_console.run_command('bootefi %x' % addr) + expected_text = 'Hello, world' + assert expected_text in output + +@pytest.mark.buildconfigspec('cmd_bootefi_hello') +def test_efi_helloworld_builtin(u_boot_console): + """Run the builtin helloworld.efi binary. + + The helloworld.efi file is included in U-Boot, execute it using the + special "bootefi hello" command. + """ + + output = u_boot_console.run_command('bootefi hello') + expected_text = 'Hello, world' + assert expected_text in output

Today we can compile a self-contained hello world efi test binary that allows us to quickly verify whether the EFI loader framwork works.
We can use that binary outside of the self-contained test case though, by providing it to a to-be-tested system via tftp.
This patch separates compilation of the helloworld.efi file from including it in the u-boot binary for "bootefi hello". It also modifies the efi_loader test case to enable travis to pick up the compiled file. Because we're now no longer bloating the resulting u-boot binary, we can enable compilation always, giving us good travis test coverage.
Signed-off-by: Alexander Graf agraf@suse.de --- arch/arm/lib/Makefile | 2 +- arch/x86/config.mk | 2 +- arch/x86/lib/Makefile | 2 +- cmd/Kconfig | 15 ++++++++++++++- lib/efi_loader/Makefile | 3 +++ test/py/tests/test_efi_loader.py | 2 +- 6 files changed, 21 insertions(+), 5 deletions(-)
diff --git a/arch/arm/lib/Makefile b/arch/arm/lib/Makefile index a812306..0051f76 100644 --- a/arch/arm/lib/Makefile +++ b/arch/arm/lib/Makefile @@ -100,5 +100,5 @@ CFLAGS_REMOVE_$(EFI_CRT0) := $(CFLAGS_NON_EFI) CFLAGS_$(EFI_RELOC) := $(CFLAGS_EFI) CFLAGS_REMOVE_$(EFI_RELOC) := $(CFLAGS_NON_EFI)
-extra-$(CONFIG_CMD_BOOTEFI_HELLO) += $(EFI_CRT0) $(EFI_RELOC) +extra-$(CONFIG_CMD_BOOTEFI_HELLO_COMPILE) += $(EFI_CRT0) $(EFI_RELOC) extra-$(CONFIG_EFI) += $(EFI_CRT0) $(EFI_RELOC) diff --git a/arch/x86/config.mk b/arch/x86/config.mk index 03c71f7..1697dca 100644 --- a/arch/x86/config.mk +++ b/arch/x86/config.mk @@ -66,7 +66,7 @@ LDFLAGS_FINAL += --gc-sections -pie
endif
-ifneq ($(CONFIG_EFI_STUB)$(CONFIG_CMD_BOOTEFI_HELLO),) +ifneq ($(CONFIG_EFI_STUB)$(CONFIG_CMD_BOOTEFI_HELLO_COMPILE),)
ifneq ($(CONFIG_EFI_STUB_64BIT),) EFI_LDS := elf_x86_64_efi.lds diff --git a/arch/x86/lib/Makefile b/arch/x86/lib/Makefile index ff402dc..723288f 100644 --- a/arch/x86/lib/Makefile +++ b/arch/x86/lib/Makefile @@ -64,6 +64,6 @@ extra-$(CONFIG_EFI_STUB_64BIT) += crt0_x86_64_efi.o reloc_x86_64_efi.o
endif
-ifneq ($(CONFIG_EFI_STUB)$(CONFIG_CMD_BOOTEFI_HELLO),) +ifneq ($(CONFIG_EFI_STUB)$(CONFIG_CMD_BOOTEFI_HELLO_COMPILE),) extra-y += $(EFI_CRT0) $(EFI_RELOC) endif diff --git a/cmd/Kconfig b/cmd/Kconfig index 2a2f23e..b16c603 100644 --- a/cmd/Kconfig +++ b/cmd/Kconfig @@ -181,9 +181,22 @@ config CMD_BOOTEFI help Boot an EFI image from memory.
+config CMD_BOOTEFI_HELLO_COMPILE + bool "Compile a standard EFI hello world binary for testing" + depends on CMD_BOOTEFI && (ARM || X86) + default y + help + This compiles a standard EFI hello world application with U-Boot so + that it can be used with the test/py testing framework. This is useful + for testing that EFI is working at a basic level, and for bringing + up EFI support on a new architecture. + + No additional space will be required in the resulting U-Boot binary + when this option is enabled. + config CMD_BOOTEFI_HELLO bool "Allow booting a standard EFI hello world for testing" - depends on CMD_BOOTEFI && (ARM || X86) + depends on CMD_BOOTEFI_HELLO_COMPILE help This adds a standard EFI hello world application to U-Boot so that it can be used with the 'bootefi hello' command. This is useful diff --git a/lib/efi_loader/Makefile b/lib/efi_loader/Makefile index f466408..fa8b91a 100644 --- a/lib/efi_loader/Makefile +++ b/lib/efi_loader/Makefile @@ -10,6 +10,9 @@ CFLAGS_helloworld.o := $(CFLAGS_EFI) CFLAGS_REMOVE_helloworld.o := $(CFLAGS_NON_EFI)
+efiprogs-$(CONFIG_CMD_BOOTEFI_HELLO_COMPILE) += helloworld.efi +always := $(efiprogs-y) + obj-$(CONFIG_CMD_BOOTEFI_HELLO) += helloworld_efi.o obj-y += efi_image_loader.o efi_boottime.o efi_runtime.o efi_console.o obj-y += efi_memory.o diff --git a/test/py/tests/test_efi_loader.py b/test/py/tests/test_efi_loader.py index 1c42653..7bf0170 100644 --- a/test/py/tests/test_efi_loader.py +++ b/test/py/tests/test_efi_loader.py @@ -104,7 +104,7 @@ def test_efi_setup_static(u_boot_console): global net_set_up net_set_up = True
-@pytest.mark.buildconfigspec('cmd_bootefi_hello') +@pytest.mark.buildconfigspec('cmd_bootefi_hello_compile') def test_efi_helloworld_net(u_boot_console): """Run the helloworld.efi binary via TFTP.

On 16/11/2016 12:15, Alexander Graf wrote:
Now that we have Travis-CI support in U-Boot as well as a simple hello world efi binary test case, we can make use of the two and verify that efi_loader support still works on every commit.
This patch set enables network as well as basic efi_loader test coverage once the uboot-test-hooks pull request at
https://github.com/swarren/uboot-test-hooks/pull/9
is accepted.
I love travis :).
https://travis-ci.org/agraf/u-boot/jobs/176341108
That patch set breaks the build for some ARM boards. Simon, could you please check why?
Thanks,
Alex
participants (1)
-
Alexander Graf