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 raw images
7"""
8
9import pytest
10from capsule_common import (
11    capsule_setup,
12    init_content,
13    place_capsule_file,
14    exec_manual_update,
15    check_file_removed,
16    check_file_exist,
17    verify_content,
18    do_reboot_dtb_specified
19)
20
21@pytest.mark.boardspec('sandbox')
22@pytest.mark.buildconfigspec('efi_capsule_firmware_raw')
23@pytest.mark.buildconfigspec('efi_capsule_on_disk')
24@pytest.mark.buildconfigspec('dfu')
25@pytest.mark.buildconfigspec('dfu_sf')
26@pytest.mark.buildconfigspec('cmd_efidebug')
27@pytest.mark.buildconfigspec('cmd_fat')
28@pytest.mark.buildconfigspec('cmd_memory')
29@pytest.mark.buildconfigspec('cmd_nvedit_efi')
30@pytest.mark.buildconfigspec('cmd_sf')
31@pytest.mark.slow
32class TestEfiCapsuleFirmwareRaw:
33    """ Tests verifying capsule-on-disk firmware update for raw images
34    """
35
36    def test_efi_capsule_fw1(
37            self, u_boot_config, ubman, efi_capsule_data):
38        """ Test Case 1
39        Update U-Boot and U-Boot environment on SPI Flash
40        but with an incorrect GUID value in the capsule
41        No update should happen
42        0x100000-0x150000: U-Boot binary (but dummy)
43        0x150000-0x200000: U-Boot environment (but dummy)
44        """
45
46        # other tests might have run and the
47        # system might not be in a clean state.
48        # Restart before starting the tests.
49        ubman.restart_uboot()
50
51        disk_img = efi_capsule_data
52        capsule_files = ['Test03']
53        with ubman.log.section('Test Case 1-a, before reboot'):
54            capsule_setup(ubman, disk_img, '0x0000000000000004')
55            init_content(ubman, '100000', 'u-boot.bin.old', 'Old')
56            init_content(ubman, '150000', 'u-boot.env.old', 'Old')
57            place_capsule_file(ubman, capsule_files)
58
59        # reboot
60        ubman.restart_uboot()
61
62        capsule_early = u_boot_config.buildconfig.get(
63            'config_efi_capsule_on_disk_early')
64
65        with ubman.log.section('Test Case 1-b, after reboot'):
66            if not capsule_early:
67                exec_manual_update(ubman, disk_img, capsule_files)
68
69            # deleted anyway
70            check_file_removed(ubman, disk_img, capsule_files)
71
72            verify_content(ubman, '100000', 'u-boot:Old')
73            verify_content(ubman, '150000', 'u-boot-env:Old')
74
75    def test_efi_capsule_fw2(
76            self, u_boot_config, ubman, efi_capsule_data):
77        """ Test Case 2
78        Update U-Boot and U-Boot environment on SPI Flash but with OsIndications unset
79        No update should happen unless CONFIG_EFI_IGNORE_OSINDICATIONS is set
80        0x100000-0x150000: U-Boot binary (but dummy)
81        0x150000-0x200000: U-Boot environment (but dummy)
82        """
83        disk_img = efi_capsule_data
84        capsule_files = ['Test01', 'Test02']
85        with ubman.log.section('Test Case 2-a, before reboot'):
86            capsule_setup(ubman, disk_img, None)
87            init_content(ubman, '100000', 'u-boot.bin.old', 'Old')
88            init_content(ubman, '150000', 'u-boot.env.old', 'Old')
89            place_capsule_file(ubman, capsule_files)
90
91        # reboot
92        ubman.restart_uboot()
93
94        ignore_os_indications = u_boot_config.buildconfig.get(
95            'config_efi_ignore_osindications')
96        need_reboot = True if ignore_os_indications else False
97
98        capsule_auth = u_boot_config.buildconfig.get(
99            'config_efi_capsule_authenticate')
100
101        capsule_early = u_boot_config.buildconfig.get(
102            'config_efi_capsule_on_disk_early')
103        with ubman.log.section('Test Case 2-b, after reboot'):
104            if not capsule_early:
105                exec_manual_update(ubman, disk_img, capsule_files, need_reboot)
106
107            if not ignore_os_indications:
108                check_file_exist(ubman, disk_img, capsule_files)
109
110            expected = 'u-boot:New' if (ignore_os_indications and not capsule_auth) else 'u-boot:Old'
111            verify_content(ubman, '100000', expected)
112
113            expected = 'u-boot-env:New' if (ignore_os_indications and not capsule_auth) else 'u-boot-env:Old'
114            verify_content(ubman, '150000', expected)
115
116    def test_efi_capsule_fw3(
117            self, u_boot_config, ubman, efi_capsule_data):
118        """ Test Case 3
119        Update U-Boot on SPI Flash, raw image format
120        0x100000-0x150000: U-Boot binary (but dummy)
121        """
122        disk_img = efi_capsule_data
123        capsule_files = ['Test01', 'Test02']
124        with ubman.log.section('Test Case 3-a, before reboot'):
125            capsule_setup(ubman, disk_img, '0x0000000000000004')
126            init_content(ubman, '100000', 'u-boot.bin.old', 'Old')
127            init_content(ubman, '150000', 'u-boot.env.old', 'Old')
128            place_capsule_file(ubman, capsule_files)
129
130        capsule_early = u_boot_config.buildconfig.get(
131            'config_efi_capsule_on_disk_early')
132        capsule_auth = u_boot_config.buildconfig.get(
133            'config_efi_capsule_authenticate')
134
135        # reboot
136        ubman.restart_uboot(expect_reset = capsule_early)
137
138        with ubman.log.section('Test Case 3-b, after reboot'):
139            if not capsule_early:
140                exec_manual_update(ubman, disk_img, capsule_files)
141
142            # make sure the dfu_alt_info exists because it is required for making ESRT.
143            output = ubman.run_command_list([
144                'env set dfu_alt_info "sf 0:0=u-boot-bin raw 0x100000 0x50000;u-boot-env raw 0x150000 0x200000"',
145                'efidebug capsule esrt'])
146
147            # ensure that SANDBOX_UBOOT_ENV_IMAGE_GUID is in the ESRT.
148            assert '9E339473-C2EB-530A-A69B-0CD6BBBED40E' in ''.join(output)
149
150            # ensure that SANDBOX_UBOOT_IMAGE_GUID is in the ESRT.
151            assert '985F2937-7C2E-5E9A-8A5E-8E063312964B' in ''.join(output)
152
153            check_file_removed(ubman, disk_img, capsule_files)
154
155            expected = 'u-boot:Old' if capsule_auth else 'u-boot:New'
156            verify_content(ubman, '100000', expected)
157
158            expected = 'u-boot-env:Old' if capsule_auth else 'u-boot-env:New'
159            verify_content(ubman, '150000', expected)
160
161    def test_efi_capsule_fw4(
162            self, u_boot_config, ubman, efi_capsule_data):
163        """ Test Case 4
164        Update U-Boot on SPI Flash, raw image format with fw_version and lowest_supported_version
165        0x100000-0x150000: U-Boot binary (but dummy)
166        0x150000-0x200000: U-Boot environment (but dummy)
167        """
168        disk_img = efi_capsule_data
169        capsule_files = ['Test101', 'Test102']
170        with ubman.log.section('Test Case 4-a, before reboot'):
171            capsule_setup(ubman, disk_img, '0x0000000000000004')
172            init_content(ubman, '100000', 'u-boot.bin.old', 'Old')
173            init_content(ubman, '150000', 'u-boot.env.old', 'Old')
174            place_capsule_file(ubman, capsule_files)
175
176        # reboot
177        do_reboot_dtb_specified(u_boot_config, ubman, 'test_ver.dtb')
178
179        capsule_early = u_boot_config.buildconfig.get(
180            'config_efi_capsule_on_disk_early')
181        capsule_auth = u_boot_config.buildconfig.get(
182            'config_efi_capsule_authenticate')
183        with ubman.log.section('Test Case 4-b, after reboot'):
184            if not capsule_early:
185                exec_manual_update(ubman, disk_img, capsule_files)
186
187            # deleted anyway
188            check_file_removed(ubman, disk_img, capsule_files)
189
190            # make sure the dfu_alt_info exists because it is required for making ESRT.
191            output = ubman.run_command_list([
192                'env set dfu_alt_info "sf 0:0=u-boot-bin raw 0x100000 0x50000'
193                'u-boot-env raw 0x150000 0x200000"',
194                'efidebug capsule esrt'])
195
196            if capsule_auth:
197                # capsule authentication failed
198                verify_content(ubman, '100000', 'u-boot:Old')
199                verify_content(ubman, '150000', 'u-boot-env:Old')
200            else:
201                # ensure that SANDBOX_UBOOT_IMAGE_GUID is in the ESRT.
202                assert '985F2937-7C2E-5E9A-8A5E-8E063312964B' in ''.join(output)
203                assert 'ESRT: fw_version=5' in ''.join(output)
204                assert 'ESRT: lowest_supported_fw_version=3' in ''.join(output)
205
206                # ensure that SANDBOX_UBOOT_ENV_IMAGE_GUID is in the ESRT.
207                assert '9E339473-C2EB-530A-A69B-0CD6BBBED40E' in ''.join(output)
208                assert 'ESRT: fw_version=10' in ''.join(output)
209                assert 'ESRT: lowest_supported_fw_version=7' in ''.join(output)
210
211                verify_content(ubman, '100000', 'u-boot:New')
212                verify_content(ubman, '150000', 'u-boot-env:New')
213
214    def test_efi_capsule_fw5(
215            self, u_boot_config, ubman, efi_capsule_data):
216        """ Test Case 5
217        Update U-Boot on SPI Flash, raw image format with fw_version and lowest_supported_version
218        but fw_version is lower than lowest_supported_version
219        No update should happen
220        0x100000-0x150000: U-Boot binary (but dummy)
221        """
222        disk_img = efi_capsule_data
223        capsule_files = ['Test103']
224        with ubman.log.section('Test Case 5-a, before reboot'):
225            capsule_setup(ubman, disk_img, '0x0000000000000004')
226            init_content(ubman, '100000', 'u-boot.bin.old', 'Old')
227            place_capsule_file(ubman, capsule_files)
228
229        # reboot
230        do_reboot_dtb_specified(u_boot_config, ubman, 'test_ver.dtb')
231
232        capsule_early = u_boot_config.buildconfig.get(
233            'config_efi_capsule_on_disk_early')
234        with ubman.log.section('Test Case 5-b, after reboot'):
235            if not capsule_early:
236                exec_manual_update(ubman, disk_img, capsule_files)
237
238            check_file_removed(ubman, disk_img, capsule_files)
239
240            verify_content(ubman, '100000', 'u-boot:Old')
241