1# SPDX-License-Identifier:      GPL-2.0+
2# Copyright (c) 2020, Linaro Limited
3# Author: AKASHI Takahiro <takahiro.akashi@linaro.org>
4
5"""U-Boot UEFI: Firmware Update Test
6This test verifies capsule-on-disk firmware update for FIT images
7"""
8
9import pytest
10from capsule_defs import CAPSULE_DATA_DIR, CAPSULE_INSTALL_DIR
11
12
13@pytest.mark.boardspec('sandbox_flattree')
14@pytest.mark.buildconfigspec('efi_capsule_firmware_fit')
15@pytest.mark.buildconfigspec('efi_capsule_on_disk')
16@pytest.mark.buildconfigspec('dfu')
17@pytest.mark.buildconfigspec('dfu_sf')
18@pytest.mark.buildconfigspec('cmd_efidebug')
19@pytest.mark.buildconfigspec('cmd_fat')
20@pytest.mark.buildconfigspec('cmd_memory')
21@pytest.mark.buildconfigspec('cmd_nvedit_efi')
22@pytest.mark.buildconfigspec('cmd_sf')
23@pytest.mark.slow
24class TestEfiCapsuleFirmwareFit():
25    """Test capsule-on-disk firmware update for FIT images
26    """
27
28    def test_efi_capsule_fw1(
29            self, u_boot_config, u_boot_console, efi_capsule_data):
30        """Test Case 1
31        Update U-Boot and U-Boot environment on SPI Flash
32        but with an incorrect GUID value in the capsule
33        No update should happen
34        0x100000-0x150000: U-Boot binary (but dummy)
35        0x150000-0x200000: U-Boot environment (but dummy)
36        """
37        # other tests might have run and the
38        # system might not be in a clean state.
39        # Restart before starting the tests.
40        u_boot_console.restart_uboot()
41
42        disk_img = efi_capsule_data
43        with u_boot_console.log.section('Test Case 1-a, before reboot'):
44            output = u_boot_console.run_command_list([
45                'host bind 0 %s' % disk_img,
46                'efidebug boot add -b 1 TEST host 0:1 /helloworld.efi -s ""',
47                'efidebug boot order 1',
48                'env set -e -nv -bs -rt OsIndications =0x0000000000000004',
49                'env set dfu_alt_info "sf 0:0=u-boot-bin raw 0x100000 0x50000;u-boot-env raw 0x150000 0x200000"',
50                'env save'])
51
52            # initialize contents
53            output = u_boot_console.run_command_list([
54                'sf probe 0:0',
55                'fatload host 0:1 4000000 %s/u-boot.bin.old' % CAPSULE_DATA_DIR,
56                'sf write 4000000 100000 10',
57                'sf read 5000000 100000 10',
58                'md.b 5000000 10'])
59            assert 'Old' in ''.join(output)
60            output = u_boot_console.run_command_list([
61                'sf probe 0:0',
62                'fatload host 0:1 4000000 %s/u-boot.env.old' % CAPSULE_DATA_DIR,
63                'sf write 4000000 150000 10',
64                'sf read 5000000 150000 10',
65                'md.b 5000000 10'])
66            assert 'Old' in ''.join(output)
67
68            # place a capsule file
69            output = u_boot_console.run_command_list([
70                'fatload host 0:1 4000000 %s/Test05' % CAPSULE_DATA_DIR,
71                'fatwrite host 0:1 4000000 %s/Test05 $filesize' % CAPSULE_INSTALL_DIR,
72                'fatls host 0:1 %s' % CAPSULE_INSTALL_DIR])
73            assert 'Test05' in ''.join(output)
74
75        capsule_early = u_boot_config.buildconfig.get(
76            'config_efi_capsule_on_disk_early')
77
78        # reboot
79        u_boot_console.restart_uboot(expect_reset = capsule_early)
80
81        with u_boot_console.log.section('Test Case 1-b, after reboot'):
82            if not capsule_early:
83                # make sure that dfu_alt_info exists even persistent variables
84                # are not available.
85                output = u_boot_console.run_command_list([
86                    'env set dfu_alt_info "sf 0:0=u-boot-bin raw 0x100000 0x50000;u-boot-env raw 0x150000 0x200000"',
87                    'host bind 0 %s' % disk_img,
88                    'fatls host 0:1 %s' % CAPSULE_INSTALL_DIR])
89                assert 'Test05' in ''.join(output)
90
91                # need to run uefi command to initiate capsule handling
92                output = u_boot_console.run_command(
93                    'env print -e Capsule0000', wait_for_reboot = True)
94
95            output = u_boot_console.run_command_list([
96                'sf probe 0:0',
97                'sf read 4000000 100000 10',
98                'md.b 4000000 10'])
99            assert 'u-boot:Old' in ''.join(output)
100
101            output = u_boot_console.run_command_list([
102                'sf read 4000000 150000 10',
103                'md.b 4000000 10'])
104            assert 'u-boot-env:Old' in ''.join(output)
105
106    def test_efi_capsule_fw2(
107            self, u_boot_config, u_boot_console, efi_capsule_data):
108        """Test Case 2
109        Update U-Boot and U-Boot environment on SPI Flash
110        0x100000-0x150000: U-Boot binary (but dummy)
111        0x150000-0x200000: U-Boot environment (but dummy)
112        """
113
114        disk_img = efi_capsule_data
115        with u_boot_console.log.section('Test Case 2-a, before reboot'):
116            output = u_boot_console.run_command_list([
117                'host bind 0 %s' % disk_img,
118                'printenv -e PlatformLangCodes', # workaround for terminal size determination
119                'efidebug boot add -b 1 TEST host 0:1 /helloworld.efi -s ""',
120                'efidebug boot order 1',
121                'env set -e -nv -bs -rt OsIndications =0x0000000000000004',
122                'env set dfu_alt_info "sf 0:0=u-boot-bin raw 0x100000 0x50000;u-boot-env raw 0x150000 0x200000"',
123                'env save'])
124
125            # initialize contents
126            output = u_boot_console.run_command_list([
127                'sf probe 0:0',
128                'fatload host 0:1 4000000 %s/u-boot.bin.old' % CAPSULE_DATA_DIR,
129                'sf write 4000000 100000 10',
130                'sf read 5000000 100000 10',
131                'md.b 5000000 10'])
132            assert 'Old' in ''.join(output)
133            output = u_boot_console.run_command_list([
134                'sf probe 0:0',
135                'fatload host 0:1 4000000 %s/u-boot.env.old' % CAPSULE_DATA_DIR,
136                'sf write 4000000 150000 10',
137                'sf read 5000000 150000 10',
138                'md.b 5000000 10'])
139            assert 'Old' in ''.join(output)
140
141            # place a capsule file
142            output = u_boot_console.run_command_list([
143                'fatload host 0:1 4000000 %s/Test04' % CAPSULE_DATA_DIR,
144                'fatwrite host 0:1 4000000 %s/Test04 $filesize' % CAPSULE_INSTALL_DIR,
145                'fatls host 0:1 %s' % CAPSULE_INSTALL_DIR])
146            assert 'Test04' in ''.join(output)
147
148        capsule_early = u_boot_config.buildconfig.get(
149            'config_efi_capsule_on_disk_early')
150        capsule_auth = u_boot_config.buildconfig.get(
151            'config_efi_capsule_authenticate')
152
153        # reboot
154        u_boot_console.restart_uboot(expect_reset = capsule_early)
155
156        with u_boot_console.log.section('Test Case 2-b, after reboot'):
157            if not capsule_early:
158                # make sure that dfu_alt_info exists even persistent variables
159                # are not available.
160                output = u_boot_console.run_command_list([
161                    'env set dfu_alt_info "sf 0:0=u-boot-bin raw 0x100000 0x50000;u-boot-env raw 0x150000 0x200000"',
162                    'host bind 0 %s' % disk_img,
163                    'fatls host 0:1 %s' % CAPSULE_INSTALL_DIR])
164                assert 'Test04' in ''.join(output)
165
166                # need to run uefi command to initiate capsule handling
167                output = u_boot_console.run_command(
168                    'env print -e Capsule0000', wait_for_reboot = True)
169
170            output = u_boot_console.run_command_list([
171                'host bind 0 %s' % disk_img,
172                'fatls host 0:1 %s' % CAPSULE_INSTALL_DIR])
173            assert 'Test04' not in ''.join(output)
174
175            output = u_boot_console.run_command_list([
176                'sf probe 0:0',
177                'sf read 4000000 100000 10',
178                'md.b 4000000 10'])
179            if capsule_auth:
180                assert 'u-boot:Old' in ''.join(output)
181            else:
182                assert 'u-boot:New' in ''.join(output)
183
184            output = u_boot_console.run_command_list([
185                'sf read 4000000 150000 10',
186                'md.b 4000000 10'])
187            if capsule_auth:
188                assert 'u-boot-env:Old' in ''.join(output)
189            else:
190                assert 'u-boot-env:New' in ''.join(output)
191