1# SPDX-License-Identifier:      GPL-2.0+
2# Copyright (c) 2021, Linaro Limited
3# Copyright (c) 2022, Arm Limited
4# Author: AKASHI Takahiro <takahiro.akashi@linaro.org>,
5#         adapted to FIT images by Vincent Stehl�� <vincent.stehle@arm.com>
6
7"""U-Boot UEFI: Firmware Update (Signed capsule with FIT images) Test
8This test verifies capsule-on-disk firmware update
9with signed capsule files containing FIT images
10"""
11
12import pytest
13from capsule_common import (
14    capsule_setup,
15    init_content,
16    place_capsule_file,
17    exec_manual_update,
18    check_file_removed,
19    verify_content,
20    do_reboot_dtb_specified
21)
22
23@pytest.mark.boardspec('sandbox_flattree')
24@pytest.mark.buildconfigspec('efi_capsule_firmware_fit')
25@pytest.mark.buildconfigspec('efi_capsule_authenticate')
26@pytest.mark.buildconfigspec('dfu')
27@pytest.mark.buildconfigspec('dfu_sf')
28@pytest.mark.buildconfigspec('cmd_efidebug')
29@pytest.mark.buildconfigspec('cmd_fat')
30@pytest.mark.buildconfigspec('cmd_memory')
31@pytest.mark.buildconfigspec('cmd_nvedit_efi')
32@pytest.mark.buildconfigspec('cmd_sf')
33@pytest.mark.slow
34class TestEfiCapsuleFirmwareSignedFit():
35    """Capsule-on-disk firmware update test
36    """
37
38    def test_efi_capsule_auth1(
39            self, u_boot_config, u_boot_console, efi_capsule_data):
40        """Test Case 1
41        Update U-Boot on SPI Flash, FIT image format
42        x150000: U-Boot binary (but dummy)
43
44        If the capsule is properly signed, the authentication
45        should pass and the firmware be updated.
46        """
47        disk_img = efi_capsule_data
48        capsule_files = ['Test13']
49        with u_boot_console.log.section('Test Case 1-a, before reboot'):
50            capsule_setup(u_boot_console, disk_img, '0x0000000000000004')
51            init_content(u_boot_console, '100000', 'u-boot.bin.old', 'Old')
52            place_capsule_file(u_boot_console, capsule_files)
53
54        do_reboot_dtb_specified(u_boot_config, u_boot_console, 'test_sig.dtb')
55
56        capsule_early = u_boot_config.buildconfig.get(
57            'config_efi_capsule_on_disk_early')
58        with u_boot_console.log.section('Test Case 1-b, after reboot'):
59            if not capsule_early:
60                exec_manual_update(u_boot_console, disk_img, capsule_files)
61
62            check_file_removed(u_boot_console, disk_img, capsule_files)
63
64            verify_content(u_boot_console, '100000', 'u-boot:New')
65
66    def test_efi_capsule_auth2(
67            self, u_boot_config, u_boot_console, efi_capsule_data):
68        """Test Case 2
69        Update U-Boot on SPI Flash, FIT image format
70        0x100000-0x150000: U-Boot binary (but dummy)
71
72        If the capsule is signed but with an invalid key,
73        the authentication should fail and the firmware
74        not be updated.
75        """
76        disk_img = efi_capsule_data
77        capsule_files = ['Test14']
78        with u_boot_console.log.section('Test Case 2-a, before reboot'):
79            capsule_setup(u_boot_console, disk_img, '0x0000000000000004')
80            init_content(u_boot_console, '100000', 'u-boot.bin.old', 'Old')
81            place_capsule_file(u_boot_console, capsule_files)
82
83        do_reboot_dtb_specified(u_boot_config, u_boot_console, 'test_sig.dtb')
84
85        capsule_early = u_boot_config.buildconfig.get(
86            'config_efi_capsule_on_disk_early')
87        with u_boot_console.log.section('Test Case 2-b, after reboot'):
88            if not capsule_early:
89                exec_manual_update(u_boot_console, disk_img, capsule_files)
90
91            # deleted any way
92            check_file_removed(u_boot_console, disk_img, capsule_files)
93
94            # TODO: check CapsuleStatus in CapsuleXXXX
95
96            verify_content(u_boot_console, '100000', 'u-boot:Old')
97
98    def test_efi_capsule_auth3(
99            self, u_boot_config, u_boot_console, efi_capsule_data):
100        """Test Case 3
101        Update U-Boot on SPI Flash, FIT image format
102        0x100000-0x150000: U-Boot binary (but dummy)
103
104        If the capsule is not signed, the authentication
105        should fail and the firmware not be updated.
106        """
107        disk_img = efi_capsule_data
108        capsule_files = ['Test02']
109        with u_boot_console.log.section('Test Case 3-a, before reboot'):
110            capsule_setup(u_boot_console, disk_img, '0x0000000000000004')
111            init_content(u_boot_console, '100000', 'u-boot.bin.old', 'Old')
112            place_capsule_file(u_boot_console, capsule_files)
113
114        do_reboot_dtb_specified(u_boot_config, u_boot_console, 'test_sig.dtb')
115
116        capsule_early = u_boot_config.buildconfig.get(
117            'config_efi_capsule_on_disk_early')
118        with u_boot_console.log.section('Test Case 3-b, after reboot'):
119            if not capsule_early:
120                exec_manual_update(u_boot_console, disk_img, capsule_files)
121
122            # deleted any way
123            check_file_removed(u_boot_console, disk_img, capsule_files)
124
125            # TODO: check CapsuleStatus in CapsuleXXXX
126
127            verify_content(u_boot_console, '100000', 'u-boot:Old')
128
129    def test_efi_capsule_auth4(
130            self, u_boot_config, u_boot_console, efi_capsule_data):
131        """Test Case 4 - Update U-Boot on SPI Flash, raw image format with version information
132        0x100000-0x150000: U-Boot binary (but dummy)
133
134        If the capsule is properly signed, the authentication
135        should pass and the firmware be updated.
136        """
137        disk_img = efi_capsule_data
138        capsule_files = ['Test114']
139        with u_boot_console.log.section('Test Case 4-a, before reboot'):
140            capsule_setup(u_boot_console, disk_img, '0x0000000000000004')
141            init_content(u_boot_console, '100000', 'u-boot.bin.old', 'Old')
142            place_capsule_file(u_boot_console, capsule_files)
143
144        do_reboot_dtb_specified(u_boot_config, u_boot_console, 'test_ver.dtb')
145
146        capsule_early = u_boot_config.buildconfig.get(
147            'config_efi_capsule_on_disk_early')
148        with u_boot_console.log.section('Test Case 4-b, after reboot'):
149            if not capsule_early:
150                exec_manual_update(u_boot_console, disk_img, capsule_files)
151
152            check_file_removed(u_boot_console, disk_img, capsule_files)
153
154            output = u_boot_console.run_command_list([
155                'env set dfu_alt_info "sf 0:0=u-boot-bin raw 0x100000 0x50000;'
156                'u-boot-env raw 0x150000 0x200000"',
157                'efidebug capsule esrt'])
158
159            # ensure that SANDBOX_UBOOT_IMAGE_GUID is in the ESRT.
160            assert '3673B45D-6A7C-46F3-9E60-ADABB03F7937' in ''.join(output)
161            assert 'ESRT: fw_version=5' in ''.join(output)
162            assert 'ESRT: lowest_supported_fw_version=3' in ''.join(output)
163
164            verify_content(u_boot_console, '100000', 'u-boot:New')
165            verify_content(u_boot_console, '150000', 'u-boot-env:New')
166
167    def test_efi_capsule_auth5(
168            self, u_boot_config, u_boot_console, efi_capsule_data):
169        """Test Case 5 - Update U-Boot on SPI Flash, raw image format with version information
170        0x100000-0x150000: U-Boot binary (but dummy)
171
172        If the capsule is signed but fw_version is lower than lowest
173        supported version, the authentication should fail and the firmware
174        not be updated.
175        """
176        disk_img = efi_capsule_data
177        capsule_files = ['Test115']
178        with u_boot_console.log.section('Test Case 5-a, before reboot'):
179            capsule_setup(u_boot_console, disk_img, '0x0000000000000004')
180            init_content(u_boot_console, '100000', 'u-boot.bin.old', 'Old')
181            place_capsule_file(u_boot_console, capsule_files)
182
183        do_reboot_dtb_specified(u_boot_config, u_boot_console, 'test_ver.dtb')
184
185        capsule_early = u_boot_config.buildconfig.get(
186            'config_efi_capsule_on_disk_early')
187        with u_boot_console.log.section('Test Case 5-b, after reboot'):
188            if not capsule_early:
189                exec_manual_update(u_boot_console, disk_img, capsule_files)
190
191            check_file_removed(u_boot_console, disk_img, capsule_files)
192
193            verify_content(u_boot_console, '100000', 'u-boot:Old')
194