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_common import (
11    capsule_setup,
12    init_content,
13    place_capsule_file,
14    exec_manual_update,
15    check_file_removed,
16    verify_content,
17    do_reboot_dtb_specified
18)
19
20@pytest.mark.boardspec('sandbox_flattree')
21@pytest.mark.buildconfigspec('efi_capsule_firmware_fit')
22@pytest.mark.buildconfigspec('efi_capsule_on_disk')
23@pytest.mark.buildconfigspec('dfu')
24@pytest.mark.buildconfigspec('dfu_sf')
25@pytest.mark.buildconfigspec('cmd_efidebug')
26@pytest.mark.buildconfigspec('cmd_fat')
27@pytest.mark.buildconfigspec('cmd_memory')
28@pytest.mark.buildconfigspec('cmd_nvedit_efi')
29@pytest.mark.buildconfigspec('cmd_sf')
30@pytest.mark.slow
31class TestEfiCapsuleFirmwareFit():
32    """Test capsule-on-disk firmware update for FIT images
33    """
34
35    def test_efi_capsule_fw1(
36            self, u_boot_config, u_boot_console, efi_capsule_data):
37        """Test Case 1
38        Update U-Boot and U-Boot environment on SPI Flash
39        but with an incorrect GUID value in the capsule
40        No update should happen
41        0x100000-0x150000: U-Boot binary (but dummy)
42        0x150000-0x200000: U-Boot environment (but dummy)
43        """
44        # other tests might have run and the
45        # system might not be in a clean state.
46        # Restart before starting the tests.
47        u_boot_console.restart_uboot()
48
49        disk_img = efi_capsule_data
50        capsule_files = ['Test05']
51        with u_boot_console.log.section('Test Case 1-a, before reboot'):
52            capsule_setup(u_boot_console, disk_img, '0x0000000000000004')
53            init_content(u_boot_console, '100000', 'u-boot.bin.old', 'Old')
54            init_content(u_boot_console, '150000', 'u-boot.env.old', 'Old')
55            place_capsule_file(u_boot_console, capsule_files)
56
57        capsule_early = u_boot_config.buildconfig.get(
58            'config_efi_capsule_on_disk_early')
59
60        # reboot
61        u_boot_console.restart_uboot(expect_reset = capsule_early)
62
63        with u_boot_console.log.section('Test Case 1-b, after reboot'):
64            if not capsule_early:
65                exec_manual_update(u_boot_console, disk_img, capsule_files)
66
67            # deleted anyway
68            check_file_removed(u_boot_console, disk_img, capsule_files)
69
70            verify_content(u_boot_console, '100000', 'u-boot:Old')
71            verify_content(u_boot_console, '150000', 'u-boot-env:Old')
72
73    def test_efi_capsule_fw2(
74            self, u_boot_config, u_boot_console, efi_capsule_data):
75        """Test Case 2
76        Update U-Boot and U-Boot environment on SPI Flash
77        0x100000-0x150000: U-Boot binary (but dummy)
78        0x150000-0x200000: U-Boot environment (but dummy)
79        """
80
81        disk_img = efi_capsule_data
82        capsule_files = ['Test04']
83        with u_boot_console.log.section('Test Case 2-a, before reboot'):
84            capsule_setup(u_boot_console, disk_img, '0x0000000000000004')
85            init_content(u_boot_console, '100000', 'u-boot.bin.old', 'Old')
86            init_content(u_boot_console, '150000', 'u-boot.env.old', 'Old')
87            place_capsule_file(u_boot_console, capsule_files)
88
89        capsule_early = u_boot_config.buildconfig.get(
90            'config_efi_capsule_on_disk_early')
91        capsule_auth = u_boot_config.buildconfig.get(
92            'config_efi_capsule_authenticate')
93
94        # reboot
95        u_boot_console.restart_uboot(expect_reset = capsule_early)
96
97        with u_boot_console.log.section('Test Case 2-b, after reboot'):
98            if not capsule_early:
99                exec_manual_update(u_boot_console, disk_img, capsule_files)
100
101            check_file_removed(u_boot_console, disk_img, capsule_files)
102
103            expected = 'u-boot:Old' if capsule_auth else 'u-boot:New'
104            verify_content(u_boot_console, '100000', expected)
105
106            expected = 'u-boot-env:Old' if capsule_auth else 'u-boot-env:New'
107            verify_content(u_boot_console, '150000', expected)
108
109    def test_efi_capsule_fw3(
110            self, u_boot_config, u_boot_console, efi_capsule_data):
111        """ Test Case 3
112        Update U-Boot on SPI Flash, raw image format with fw_version and lowest_supported_version
113        0x100000-0x150000: U-Boot binary (but dummy)
114        0x150000-0x200000: U-Boot environment (but dummy)
115        """
116        disk_img = efi_capsule_data
117        capsule_files = ['Test104']
118        with u_boot_console.log.section('Test Case 3-a, before reboot'):
119            capsule_setup(u_boot_console, disk_img, '0x0000000000000004')
120            init_content(u_boot_console, '100000', 'u-boot.bin.old', 'Old')
121            init_content(u_boot_console, '150000', 'u-boot.env.old', 'Old')
122            place_capsule_file(u_boot_console, capsule_files)
123
124        # reboot
125        do_reboot_dtb_specified(u_boot_config, u_boot_console, 'test_ver.dtb')
126
127        capsule_early = u_boot_config.buildconfig.get(
128            'config_efi_capsule_on_disk_early')
129        capsule_auth = u_boot_config.buildconfig.get(
130            'config_efi_capsule_authenticate')
131        with u_boot_console.log.section('Test Case 3-b, after reboot'):
132            if not capsule_early:
133                exec_manual_update(u_boot_console, disk_img, capsule_files)
134
135            # deleted anyway
136            check_file_removed(u_boot_console, disk_img, capsule_files)
137
138            # make sure the dfu_alt_info exists because it is required for making ESRT.
139            output = u_boot_console.run_command_list([
140                'env set dfu_alt_info "sf 0:0=u-boot-bin raw 0x100000 0x50000;'
141                'u-boot-env raw 0x150000 0x200000"',
142                'efidebug capsule esrt'])
143
144            if capsule_auth:
145                # capsule authentication failed
146                verify_content(u_boot_console, '100000', 'u-boot:Old')
147                verify_content(u_boot_console, '150000', 'u-boot-env:Old')
148            else:
149                # ensure that SANDBOX_UBOOT_IMAGE_GUID is in the ESRT.
150                assert '3673B45D-6A7C-46F3-9E60-ADABB03F7937' in ''.join(output)
151                assert 'ESRT: fw_version=5' in ''.join(output)
152                assert 'ESRT: lowest_supported_fw_version=3' in ''.join(output)
153
154                verify_content(u_boot_console, '100000', 'u-boot:New')
155                verify_content(u_boot_console, '150000', 'u-boot-env:New')
156
157    def test_efi_capsule_fw4(
158            self, u_boot_config, u_boot_console, efi_capsule_data):
159        """ Test Case 4
160        Update U-Boot on SPI Flash, raw image format with fw_version and lowest_supported_version
161        but fw_version is lower than lowest_supported_version
162        No update should happen
163        0x100000-0x150000: U-Boot binary (but dummy)
164        """
165        disk_img = efi_capsule_data
166        capsule_files = ['Test105']
167        with u_boot_console.log.section('Test Case 4-a, before reboot'):
168            capsule_setup(u_boot_console, disk_img, '0x0000000000000004')
169            init_content(u_boot_console, '100000', 'u-boot.bin.old', 'Old')
170            place_capsule_file(u_boot_console, capsule_files)
171
172        # reboot
173        do_reboot_dtb_specified(u_boot_config, u_boot_console, 'test_ver.dtb')
174
175        capsule_early = u_boot_config.buildconfig.get(
176            'config_efi_capsule_on_disk_early')
177        with u_boot_console.log.section('Test Case 4-b, after reboot'):
178            if not capsule_early:
179                exec_manual_update(u_boot_console, disk_img, capsule_files)
180
181            check_file_removed(u_boot_console, disk_img, capsule_files)
182
183            verify_content(u_boot_console, '100000', 'u-boot:Old')
184