[PATCH] test/py: efi_capsule: Handle expected reset after capsule on disk

Masami Hiramatsu masami.hiramatsu at linaro.org
Tue Feb 15 10:09:50 CET 2022


Hi Heinrich,

I and Takahiro found that the capsule update test case and test framework
didn't expect that a command can reboot the sandbox and the sandbox can
reboot while booting, which happens when my "Reset system after
CapsuleUpdate on disk" patch applied.
This patch fixes those issues.

Thank you,


2022年2月15日(火) 18:05 Masami Hiramatsu <masami.hiramatsu at linaro.org>:

> Since now the capsule_on_disk will restart the u-boot sandbox right
> after the capsule update, if CONFIG_EFI_CAPSULE_ON_DISK_EARLY=y, the
> boot with a new capsule file will repeat reboot sequence. On the
> other hand, if CONFIG_EFI_CAPSULE_ON_DISK_EARLY=n, the 'env print -e'
> command will execute the capsule update on disk and reboot.
>
> Thus this update the uboot_console for those 2 cases;
>
>  - restart_uboot(): Add expect_earlyreset optional parameter so that
>    it can handle the reboot while booting.
>  - run_command(): Add wait_for_reboot optional parameter so that it
>    can handle the reboot after executing a command.
>
> And enable those options in the test_capsule_firmware.py test cases.
>
> Signed-off-by: Masami Hiramatsu <masami.hiramatsu at linaro.org>
> ---
>  .../test_efi_capsule/test_capsule_firmware.py      |   39 ++++++--
>  test/py/u_boot_console_base.py                     |   95
> +++++++++++++++-----
>  test/py/u_boot_console_sandbox.py                  |    6 +
>  3 files changed, 102 insertions(+), 38 deletions(-)
>
> diff --git a/test/py/tests/test_efi_capsule/test_capsule_firmware.py
> b/test/py/tests/test_efi_capsule/test_capsule_firmware.py
> index 6e803f699f..a539134ec2 100644
> --- a/test/py/tests/test_efi_capsule/test_capsule_firmware.py
> +++ b/test/py/tests/test_efi_capsule/test_capsule_firmware.py
> @@ -143,13 +143,14 @@ class TestEfiCapsuleFirmwareFit(object):
>                  'fatls host 0:1 %s' % CAPSULE_INSTALL_DIR])
>              assert 'Test01' in ''.join(output)
>
> -        # reboot
> -        u_boot_console.restart_uboot()
> -
>          capsule_early = u_boot_config.buildconfig.get(
>              'config_efi_capsule_on_disk_early')
>          capsule_auth = u_boot_config.buildconfig.get(
>              'config_efi_capsule_authenticate')
> +
> +        # reboot
> +        u_boot_console.restart_uboot(expect_earlyreset = capsule_early)
> +
>          with u_boot_console.log.section('Test Case 2-b, after reboot'):
>              if not capsule_early:
>                  # make sure that dfu_alt_info exists even persistent
> variables
> @@ -162,7 +163,7 @@ class TestEfiCapsuleFirmwareFit(object):
>
>                  # need to run uefi command to initiate capsule handling
>                  output = u_boot_console.run_command(
> -                    'env print -e Capsule0000')
> +                    'env print -e Capsule0000', wait_for_reboot = True)
>
>              output = u_boot_console.run_command_list([
>                  'host bind 0 %s' % disk_img,
> @@ -218,13 +219,14 @@ class TestEfiCapsuleFirmwareFit(object):
>                  'fatls host 0:1 %s' % CAPSULE_INSTALL_DIR])
>              assert 'Test02' in ''.join(output)
>
> -        # reboot
> -        u_boot_console.restart_uboot()
> -
>          capsule_early = u_boot_config.buildconfig.get(
>              'config_efi_capsule_on_disk_early')
>          capsule_auth = u_boot_config.buildconfig.get(
>              'config_efi_capsule_authenticate')
> +
> +        # reboot
> +        u_boot_console.restart_uboot(expect_earlyreset = capsule_early)
> +
>          with u_boot_console.log.section('Test Case 3-b, after reboot'):
>              if not capsule_early:
>                  # make sure that dfu_alt_info exists even persistent
> variables
> @@ -237,7 +239,13 @@ class TestEfiCapsuleFirmwareFit(object):
>
>                  # need to run uefi command to initiate capsule handling
>                  output = u_boot_console.run_command(
> -                    'env print -e Capsule0000')
> +                    'env print -e Capsule0000', wait_for_reboot = True)
> +
> +            output = u_boot_console.run_command_list([
> +                'env set dfu_alt_info "sf 0:0=u-boot-bin raw 0x100000
> 0x50000;u-boot-env raw 0x150000 0x200000"',
> +                'host bind 0 %s' % disk_img,
> +                'fatls host 0:1 %s' % CAPSULE_INSTALL_DIR])
> +            assert 'Test02' not in ''.join(output)
>
>              output = u_boot_console.run_command_list(['efidebug capsule
> esrt'])
>
> @@ -293,13 +301,14 @@ class TestEfiCapsuleFirmwareFit(object):
>                  'fatls host 0:1 %s' % CAPSULE_INSTALL_DIR])
>              assert 'Test03' in ''.join(output)
>
> -        # reboot
> -        u_boot_console.restart_uboot()
> -
>          capsule_early = u_boot_config.buildconfig.get(
>              'config_efi_capsule_on_disk_early')
>          capsule_auth = u_boot_config.buildconfig.get(
>              'config_efi_capsule_authenticate')
> +
> +        # reboot
> +        u_boot_console.restart_uboot(expect_earlyreset = capsule_early)
> +
>          with u_boot_console.log.section('Test Case 4-b, after reboot'):
>              if not capsule_early:
>                  # make sure that dfu_alt_info exists even persistent
> variables
> @@ -312,7 +321,13 @@ class TestEfiCapsuleFirmwareFit(object):
>
>                  # need to run uefi command to initiate capsule handling
>                  output = u_boot_console.run_command(
> -                    'env print -e Capsule0000')
> +                    'env print -e Capsule0000', wait_for_reboot = True)
> +
> +            output = u_boot_console.run_command_list([
> +                'env set dfu_alt_info "sf 0:0=u-boot-bin raw 0x100000
> 0x50000;u-boot-env raw 0x150000 0x200000"',
> +                'host bind 0 %s' % disk_img,
> +                'fatls host 0:1 %s' % CAPSULE_INSTALL_DIR])
> +            assert 'Test03' not in ''.join(output)
>
>              output = u_boot_console.run_command_list(['efidebug capsule
> esrt'])
>
> diff --git a/test/py/u_boot_console_base.py
> b/test/py/u_boot_console_base.py
> index 384fd53c65..e84f4d74ef 100644
> --- a/test/py/u_boot_console_base.py
> +++ b/test/py/u_boot_console_base.py
> @@ -140,7 +140,7 @@ class ConsoleBase(object):
>          self.logstream.close()
>
>      def run_command(self, cmd, wait_for_echo=True, send_nl=True,
> -            wait_for_prompt=True):
> +            wait_for_prompt=True, wait_for_reboot=False):
>          """Execute a command via the U-Boot console.
>
>          The command is always sent to U-Boot.
> @@ -168,6 +168,8 @@ class ConsoleBase(object):
>              wait_for_prompt: Boolean indicating whether to wait for the
>                  command prompt to be sent by U-Boot. This typically occurs
>                  immediately after the command has been executed.
> +            wait_for_reboot: Boolean indication whether to wait for the
> +                reboot U-Boot. If this is True, wait_for_prompt is
> ignored.
>
>          Returns:
>              If wait_for_prompt == False:
> @@ -202,11 +204,48 @@ class ConsoleBase(object):
>                                      self.bad_pattern_ids[m - 1])
>              if not wait_for_prompt:
>                  return
> -            m = self.p.expect([self.prompt_compiled] + self.bad_patterns)
> -            if m != 0:
> -                self.at_prompt = False
> -                raise Exception('Bad pattern found on console: ' +
> -                                self.bad_pattern_ids[m - 1])
> +            if wait_for_reboot:
> +                bcfg = self.config.buildconfig
> +                config_spl = bcfg.get('config_spl', 'n') == 'y'
> +                config_spl_serial = bcfg.get('config_spl_serial',
> +                                                 'n') == 'y'
> +                env_spl_skipped = self.config.env.get('env__spl_skipped',
> +                                                      False)
> +                env_spl2_skipped =
> self.config.env.get('env__spl2_skipped',
> +                                                       True)
> +                if config_spl and config_spl_serial and not
> env_spl_skipped:
> +                    m = self.p.expect([pattern_u_boot_spl_signon] +
> +                                      self.bad_patterns)
> +                    if m != 0:
> +                        raise Exception('Bad pattern found on SPL
> console: ' +
> +                                        self.bad_pattern_ids[m - 1])
> +                if not env_spl2_skipped:
> +                    m = self.p.expect([pattern_u_boot_spl2_signon] +
> +                                      self.bad_patterns)
> +                    if m != 0:
> +                        raise Exception('Bad pattern found on SPL2
> console: ' +
> +                                        self.bad_pattern_ids[m - 1])
> +                m = self.p.expect([pattern_u_boot_main_signon] +
> self.bad_patterns)
> +                if m != 0:
> +                    raise Exception('Bad pattern found on console: ' +
> +                                    self.bad_pattern_ids[m - 1])
> +                self.u_boot_version_string = self.p.after
> +                while True:
> +                    m = self.p.expect([self.prompt_compiled,
> +                        pattern_stop_autoboot_prompt] + self.bad_patterns)
> +                    if m == 0:
> +                        break
> +                    if m == 1:
> +                        self.p.send(' ')
> +                        continue
> +                    raise Exception('Bad pattern found on console: ' +
> +                                    self.bad_pattern_ids[m - 2])
> +            else:
> +                m = self.p.expect([self.prompt_compiled] +
> self.bad_patterns)
> +                if m != 0:
> +                    self.at_prompt = False
> +                    raise Exception('Bad pattern found on console: ' +
> +                                    self.bad_pattern_ids[m - 1])
>              self.at_prompt = True
>              self.at_prompt_logevt = self.logstream.logfile.cur_evt
>              # Only strip \r\n; space/TAB might be significant if testing
> @@ -321,7 +360,7 @@ class ConsoleBase(object):
>          finally:
>              self.p.timeout = orig_timeout
>
> -    def ensure_spawned(self):
> +    def ensure_spawned(self, expect_earlyreset=False):
>          """Ensure a connection to a correctly running U-Boot instance.
>
>          This may require spawning a new Sandbox process or resetting
> target
> @@ -330,7 +369,8 @@ class ConsoleBase(object):
>          This is an internal function and should not be called directly.
>
>          Args:
> -            None.
> +            expect_earlyreset: This boot is expected to be reset in early
> +                stage (before prompt). False by default.
>
>          Returns:
>              Nothing.
> @@ -357,22 +397,29 @@ class ConsoleBase(object):
>                                                    False)
>              env_spl2_skipped = self.config.env.get('env__spl2_skipped',
>                                                    True)
> -            if config_spl and config_spl_serial and not env_spl_skipped:
> -                m = self.p.expect([pattern_u_boot_spl_signon] +
> -                                  self.bad_patterns)
> +            if expect_earlyreset:
> +                loop_num = 2
> +            else:
> +                loop_num = 1
> +
> +            while loop_num > 0:
> +                loop_num -= 1
> +                if config_spl and config_spl_serial and not
> env_spl_skipped:
> +                    m = self.p.expect([pattern_u_boot_spl_signon] +
> +                                      self.bad_patterns)
> +                    if m != 0:
> +                        raise Exception('Bad pattern found on SPL
> console: ' +
> +                                        self.bad_pattern_ids[m - 1])
> +                if not env_spl2_skipped:
> +                    m = self.p.expect([pattern_u_boot_spl2_signon] +
> +                                      self.bad_patterns)
> +                    if m != 0:
> +                        raise Exception('Bad pattern found on SPL2
> console: ' +
> +                                        self.bad_pattern_ids[m - 1])
> +                m = self.p.expect([pattern_u_boot_main_signon] +
> self.bad_patterns)
>                  if m != 0:
> -                    raise Exception('Bad pattern found on SPL console: ' +
> -                                    self.bad_pattern_ids[m - 1])
> -            if not env_spl2_skipped:
> -                m = self.p.expect([pattern_u_boot_spl2_signon] +
> -                                  self.bad_patterns)
> -                if m != 0:
> -                    raise Exception('Bad pattern found on SPL2 console: '
> +
> +                    raise Exception('Bad pattern found on console: ' +
>                                      self.bad_pattern_ids[m - 1])
> -            m = self.p.expect([pattern_u_boot_main_signon] +
> self.bad_patterns)
> -            if m != 0:
> -                raise Exception('Bad pattern found on console: ' +
> -                                self.bad_pattern_ids[m - 1])
>              self.u_boot_version_string = self.p.after
>              while True:
>                  m = self.p.expect([self.prompt_compiled,
> @@ -416,10 +463,10 @@ class ConsoleBase(object):
>              pass
>          self.p = None
>
> -    def restart_uboot(self):
> +    def restart_uboot(self, expect_earlyreset=False):
>          """Shut down and restart U-Boot."""
>          self.cleanup_spawn()
> -        self.ensure_spawned()
> +        self.ensure_spawned(expect_earlyreset)
>
>      def get_spawn_output(self):
>          """Return the start-up output from U-Boot
> diff --git a/test/py/u_boot_console_sandbox.py
> b/test/py/u_boot_console_sandbox.py
> index 7e1eb0e0b4..9cd9ccad30 100644
> --- a/test/py/u_boot_console_sandbox.py
> +++ b/test/py/u_boot_console_sandbox.py
> @@ -57,11 +57,13 @@ class ConsoleSandbox(ConsoleBase):
>          cmd += self.sandbox_flags
>          return Spawn(cmd, cwd=self.config.source_dir)
>
> -    def restart_uboot_with_flags(self, flags):
> +    def restart_uboot_with_flags(self, flags, expect_earlyreset=False):
>          """Run U-Boot with the given command-line flags
>
>          Args:
>              flags: List of flags to pass, each a string
> +            expect_earlyreset: This boot is expected to be reset in early
> +                stage (before prompt). False by default.
>
>          Returns:
>              A u_boot_spawn.Spawn object that is attached to U-Boot.
> @@ -69,7 +71,7 @@ class ConsoleSandbox(ConsoleBase):
>
>          try:
>              self.sandbox_flags = flags
> -            return self.restart_uboot()
> +            return self.restart_uboot(expect_earlyreset)
>          finally:
>              self.sandbox_flags = []
>
>
>

-- 
Masami Hiramatsu


More information about the U-Boot mailing list