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, u_boot_console, 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        u_boot_console.restart_uboot()
50
51        disk_img = efi_capsule_data
52        capsule_files = ['Test03']
53        with u_boot_console.log.section('Test Case 1-a, before reboot'):
54            capsule_setup(u_boot_console, disk_img, '0x0000000000000004')
55            init_content(u_boot_console, '100000', 'u-boot.bin.old', 'Old')
56            init_content(u_boot_console, '150000', 'u-boot.env.old', 'Old')
57            place_capsule_file(u_boot_console, capsule_files)
58
59        # reboot
60        u_boot_console.restart_uboot()
61
62        capsule_early = u_boot_config.buildconfig.get(
63            'config_efi_capsule_on_disk_early')
64
65        with u_boot_console.log.section('Test Case 1-b, after reboot'):
66            if not capsule_early:
67                exec_manual_update(u_boot_console, disk_img, capsule_files)
68
69            # deleted anyway
70            check_file_removed(u_boot_console, disk_img, capsule_files)
71
72            verify_content(u_boot_console, '100000', 'u-boot:Old')
73            verify_content(u_boot_console, '150000', 'u-boot-env:Old')
74
75    def test_efi_capsule_fw2(
76            self, u_boot_config, u_boot_console, 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
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 u_boot_console.log.section('Test Case 2-a, before reboot'):
86            capsule_setup(u_boot_console, disk_img, None)
87            init_content(u_boot_console, '100000', 'u-boot.bin.old', 'Old')
88            init_content(u_boot_console, '150000', 'u-boot.env.old', 'Old')
89            place_capsule_file(u_boot_console, capsule_files)
90
91        # reboot
92        u_boot_console.restart_uboot()
93
94        capsule_early = u_boot_config.buildconfig.get(
95            'config_efi_capsule_on_disk_early')
96        with u_boot_console.log.section('Test Case 2-b, after reboot'):
97            if not capsule_early:
98                exec_manual_update(u_boot_console, disk_img, capsule_files, False)
99
100            check_file_exist(u_boot_console, disk_img, capsule_files)
101
102            verify_content(u_boot_console, '100000', 'u-boot:Old')
103            verify_content(u_boot_console, '150000', 'u-boot-env:Old')
104
105    def test_efi_capsule_fw3(
106            self, u_boot_config, u_boot_console, efi_capsule_data):
107        """ Test Case 3
108        Update U-Boot on SPI Flash, raw image format
109        0x100000-0x150000: U-Boot binary (but dummy)
110        """
111        disk_img = efi_capsule_data
112        capsule_files = ['Test01', 'Test02']
113        with u_boot_console.log.section('Test Case 3-a, before reboot'):
114            capsule_setup(u_boot_console, disk_img, '0x0000000000000004')
115            init_content(u_boot_console, '100000', 'u-boot.bin.old', 'Old')
116            init_content(u_boot_console, '150000', 'u-boot.env.old', 'Old')
117            place_capsule_file(u_boot_console, capsule_files)
118
119        capsule_early = u_boot_config.buildconfig.get(
120            'config_efi_capsule_on_disk_early')
121        capsule_auth = u_boot_config.buildconfig.get(
122            'config_efi_capsule_authenticate')
123
124        # reboot
125        u_boot_console.restart_uboot(expect_reset = capsule_early)
126
127        with u_boot_console.log.section('Test Case 3-b, after reboot'):
128            if not capsule_early:
129                exec_manual_update(u_boot_console, disk_img, capsule_files)
130
131            # make sure the dfu_alt_info exists because it is required for making ESRT.
132            output = u_boot_console.run_command_list([
133                'env set dfu_alt_info "sf 0:0=u-boot-bin raw 0x100000 0x50000;u-boot-env raw 0x150000 0x200000"',
134                'efidebug capsule esrt'])
135
136            # ensure that SANDBOX_UBOOT_ENV_IMAGE_GUID is in the ESRT.
137            assert '5A7021F5-FEF2-48B4-AABA-832E777418C0' in ''.join(output)
138
139            # ensure that SANDBOX_UBOOT_IMAGE_GUID is in the ESRT.
140            assert '09D7CF52-0720-4710-91D1-08469B7FE9C8' in ''.join(output)
141
142            check_file_removed(u_boot_console, disk_img, capsule_files)
143
144            expected = 'u-boot:Old' if capsule_auth else 'u-boot:New'
145            verify_content(u_boot_console, '100000', expected)
146
147            expected = 'u-boot-env:Old' if capsule_auth else 'u-boot-env:New'
148            verify_content(u_boot_console, '150000', expected)
149
150    def test_efi_capsule_fw4(
151            self, u_boot_config, u_boot_console, efi_capsule_data):
152        """ Test Case 4
153        Update U-Boot on SPI Flash, raw image format with fw_version and lowest_supported_version
154        0x100000-0x150000: U-Boot binary (but dummy)
155        0x150000-0x200000: U-Boot environment (but dummy)
156        """
157        disk_img = efi_capsule_data
158        capsule_files = ['Test101', 'Test102']
159        with u_boot_console.log.section('Test Case 4-a, before reboot'):
160            capsule_setup(u_boot_console, disk_img, '0x0000000000000004')
161            init_content(u_boot_console, '100000', 'u-boot.bin.old', 'Old')
162            init_content(u_boot_console, '150000', 'u-boot.env.old', 'Old')
163            place_capsule_file(u_boot_console, capsule_files)
164
165        # reboot
166        do_reboot_dtb_specified(u_boot_config, u_boot_console, 'test_ver.dtb')
167
168        capsule_early = u_boot_config.buildconfig.get(
169            'config_efi_capsule_on_disk_early')
170        capsule_auth = u_boot_config.buildconfig.get(
171            'config_efi_capsule_authenticate')
172        with u_boot_console.log.section('Test Case 4-b, after reboot'):
173            if not capsule_early:
174                exec_manual_update(u_boot_console, disk_img, capsule_files)
175
176            # deleted anyway
177            check_file_removed(u_boot_console, disk_img, capsule_files)
178
179            # make sure the dfu_alt_info exists because it is required for making ESRT.
180            output = u_boot_console.run_command_list([
181                'env set dfu_alt_info "sf 0:0=u-boot-bin raw 0x100000 0x50000'
182                'u-boot-env raw 0x150000 0x200000"',
183                'efidebug capsule esrt'])
184
185            if capsule_auth:
186                # capsule authentication failed
187                verify_content(u_boot_console, '100000', 'u-boot:Old')
188                verify_content(u_boot_console, '150000', 'u-boot-env:Old')
189            else:
190                # ensure that SANDBOX_UBOOT_IMAGE_GUID is in the ESRT.
191                assert '09D7CF52-0720-4710-91D1-08469B7FE9C8' in ''.join(output)
192                assert 'ESRT: fw_version=5' in ''.join(output)
193                assert 'ESRT: lowest_supported_fw_version=3' in ''.join(output)
194
195                # ensure that SANDBOX_UBOOT_ENV_IMAGE_GUID is in the ESRT.
196                assert '5A7021F5-FEF2-48B4-AABA-832E777418C0' in ''.join(output)
197                assert 'ESRT: fw_version=10' in ''.join(output)
198                assert 'ESRT: lowest_supported_fw_version=7' in ''.join(output)
199
200                verify_content(u_boot_console, '100000', 'u-boot:New')
201                verify_content(u_boot_console, '150000', 'u-boot-env:New')
202
203    def test_efi_capsule_fw5(
204            self, u_boot_config, u_boot_console, efi_capsule_data):
205        """ Test Case 5
206        Update U-Boot on SPI Flash, raw image format with fw_version and lowest_supported_version
207        but fw_version is lower than lowest_supported_version
208        No update should happen
209        0x100000-0x150000: U-Boot binary (but dummy)
210        """
211        disk_img = efi_capsule_data
212        capsule_files = ['Test103']
213        with u_boot_console.log.section('Test Case 5-a, before reboot'):
214            capsule_setup(u_boot_console, disk_img, '0x0000000000000004')
215            init_content(u_boot_console, '100000', 'u-boot.bin.old', 'Old')
216            place_capsule_file(u_boot_console, capsule_files)
217
218        # reboot
219        do_reboot_dtb_specified(u_boot_config, u_boot_console, 'test_ver.dtb')
220
221        capsule_early = u_boot_config.buildconfig.get(
222            'config_efi_capsule_on_disk_early')
223        with u_boot_console.log.section('Test Case 5-b, after reboot'):
224            if not capsule_early:
225                exec_manual_update(u_boot_console, disk_img, capsule_files)
226
227            check_file_removed(u_boot_console, disk_img, capsule_files)
228
229            verify_content(u_boot_console, '100000', 'u-boot:Old')
230