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
6
7"""
8This test verifies capsule-on-disk firmware update
9"""
10
11from subprocess import check_call, check_output, CalledProcessError
12import pytest
13from capsule_defs import *
14
15
16@pytest.mark.boardspec('sandbox')
17@pytest.mark.buildconfigspec('efi_capsule_firmware_fit')
18@pytest.mark.buildconfigspec('efi_capsule_firmware_raw')
19@pytest.mark.buildconfigspec('efi_capsule_on_disk')
20@pytest.mark.buildconfigspec('dfu')
21@pytest.mark.buildconfigspec('dfu_sf')
22@pytest.mark.buildconfigspec('cmd_efidebug')
23@pytest.mark.buildconfigspec('cmd_fat')
24@pytest.mark.buildconfigspec('cmd_memory')
25@pytest.mark.buildconfigspec('cmd_nvedit_efi')
26@pytest.mark.buildconfigspec('cmd_sf')
27@pytest.mark.slow
28class TestEfiCapsuleFirmwareFit(object):
29    def test_efi_capsule_fw1(
30            self, u_boot_config, u_boot_console, efi_capsule_data):
31        """
32        Test Case 1 - Update U-Boot and U-Boot environment on SPI Flash
33                      but with OsIndications unset
34                      No update should happen
35                      0x100000-0x150000: U-Boot binary (but dummy)
36                      0x150000-0x200000: U-Boot environment (but dummy)
37        """
38        disk_img = efi_capsule_data
39        with u_boot_console.log.section('Test Case 1-a, before reboot'):
40            output = u_boot_console.run_command_list([
41                'host bind 0 %s' % disk_img,
42                'efidebug boot add 1 TEST host 0:1 /helloworld.efi ""',
43                'efidebug boot order 1',
44                'env set -e OsIndications',
45                'env set dfu_alt_info "sf 0:0=u-boot-bin raw 0x100000 0x50000;u-boot-env raw 0x150000 0x200000"',
46                'env save'])
47
48            # initialize contents
49            output = u_boot_console.run_command_list([
50                'sf probe 0:0',
51                'fatload host 0:1 4000000 %s/u-boot.bin.old' % CAPSULE_DATA_DIR,
52                'sf write 4000000 100000 10',
53                'sf read 5000000 100000 10',
54                'md.b 5000000 10'])
55            assert 'Old' in ''.join(output)
56            output = u_boot_console.run_command_list([
57                'sf probe 0:0',
58                'fatload host 0:1 4000000 %s/u-boot.env.old' % CAPSULE_DATA_DIR,
59                'sf write 4000000 150000 10',
60                'sf read 5000000 150000 10',
61                'md.b 5000000 10'])
62            assert 'Old' in ''.join(output)
63
64            # place a capsule file
65            output = u_boot_console.run_command_list([
66                'fatload host 0:1 4000000 %s/Test01' % CAPSULE_DATA_DIR,
67                'fatwrite host 0:1 4000000 %s/Test01 $filesize' % CAPSULE_INSTALL_DIR,
68                'fatls host 0:1 %s' % CAPSULE_INSTALL_DIR])
69            assert 'Test01' in ''.join(output)
70
71        # reboot
72        u_boot_console.restart_uboot()
73
74        capsule_early = u_boot_config.buildconfig.get(
75            'config_efi_capsule_on_disk_early')
76        with u_boot_console.log.section('Test Case 1-b, after reboot'):
77            if not capsule_early:
78                # make sure that dfu_alt_info exists even persistent variables
79                # are not available.
80                output = u_boot_console.run_command_list([
81                    'env set dfu_alt_info "sf 0:0=u-boot-bin raw 0x100000 0x50000;u-boot-env raw 0x150000 0x200000"',
82                    'host bind 0 %s' % disk_img,
83                    'fatls host 0:1 %s' % CAPSULE_INSTALL_DIR])
84                assert 'Test01' in ''.join(output)
85
86                # need to run uefi command to initiate capsule handling
87                output = u_boot_console.run_command(
88                    'env print -e -all Capsule0000')
89
90            output = u_boot_console.run_command_list([
91                'host bind 0 %s' % disk_img,
92                'fatls host 0:1 %s' % CAPSULE_INSTALL_DIR])
93            assert 'Test01' in ''.join(output)
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        """
109        Test Case 2 - 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        disk_img = efi_capsule_data
114        with u_boot_console.log.section('Test Case 2-a, before reboot'):
115            output = u_boot_console.run_command_list([
116                'host bind 0 %s' % disk_img,
117                'efidebug boot add 1 TEST host 0:1 /helloworld.efi ""',
118                'efidebug boot order 1',
119                'env set -e -nv -bs -rt OsIndications =0x0000000000000004',
120                'env set dfu_alt_info "sf 0:0=u-boot-bin raw 0x100000 0x50000;u-boot-env raw 0x150000 0x200000"',
121                'env save'])
122
123            # initialize contents
124            output = u_boot_console.run_command_list([
125                'sf probe 0:0',
126                'fatload host 0:1 4000000 %s/u-boot.bin.old' % CAPSULE_DATA_DIR,
127                'sf write 4000000 100000 10',
128                'sf read 5000000 100000 10',
129                'md.b 5000000 10'])
130            assert 'Old' in ''.join(output)
131            output = u_boot_console.run_command_list([
132                'sf probe 0:0',
133                'fatload host 0:1 4000000 %s/u-boot.env.old' % CAPSULE_DATA_DIR,
134                'sf write 4000000 150000 10',
135                'sf read 5000000 150000 10',
136                'md.b 5000000 10'])
137            assert 'Old' in ''.join(output)
138
139            # place a capsule file
140            output = u_boot_console.run_command_list([
141                'fatload host 0:1 4000000 %s/Test01' % CAPSULE_DATA_DIR,
142                'fatwrite host 0:1 4000000 %s/Test01 $filesize' % CAPSULE_INSTALL_DIR,
143                'fatls host 0:1 %s' % CAPSULE_INSTALL_DIR])
144            assert 'Test01' in ''.join(output)
145
146        # reboot
147        u_boot_console.restart_uboot()
148
149        capsule_early = u_boot_config.buildconfig.get(
150            'config_efi_capsule_on_disk_early')
151        with u_boot_console.log.section('Test Case 2-b, after reboot'):
152            if not capsule_early:
153                # make sure that dfu_alt_info exists even persistent variables
154                # are not available.
155                output = u_boot_console.run_command_list([
156                    'env set dfu_alt_info "sf 0:0=u-boot-bin raw 0x100000 0x50000;u-boot-env raw 0x150000 0x200000"',
157                    'host bind 0 %s' % disk_img,
158                    'fatls host 0:1 %s' % CAPSULE_INSTALL_DIR])
159                assert 'Test01' in ''.join(output)
160
161                # need to run uefi command to initiate capsule handling
162                output = u_boot_console.run_command(
163                    'env print -e -all Capsule0000')
164
165            output = u_boot_console.run_command_list([
166                'host bind 0 %s' % disk_img,
167                'fatls host 0:1 %s' % CAPSULE_INSTALL_DIR])
168            assert 'Test01' not in ''.join(output)
169
170            output = u_boot_console.run_command_list([
171                'sf probe 0:0',
172                'sf read 4000000 100000 10',
173                'md.b 4000000 10'])
174            assert 'u-boot:New' in ''.join(output)
175
176            output = u_boot_console.run_command_list([
177                'sf read 4000000 150000 10',
178                'md.b 4000000 10'])
179            assert 'u-boot-env:New' in ''.join(output)
180
181    def test_efi_capsule_fw3(
182            self, u_boot_config, u_boot_console, efi_capsule_data):
183        """
184        Test Case 3 - Update U-Boot on SPI Flash, raw image format
185                      0x100000-0x150000: U-Boot binary (but dummy)
186        """
187        disk_img = efi_capsule_data
188        with u_boot_console.log.section('Test Case 3-a, before reboot'):
189            output = u_boot_console.run_command_list([
190                'host bind 0 %s' % disk_img,
191                'efidebug boot add 1 TEST host 0:1 /helloworld.efi ""',
192                'efidebug boot order 1',
193                'env set -e -nv -bs -rt OsIndications =0x0000000000000004',
194                'env set dfu_alt_info "sf 0:0=u-boot-bin raw 0x100000 0x50000;u-boot-env raw 0x150000 0x200000"',
195                'env save'])
196
197            # initialize content
198            output = u_boot_console.run_command_list([
199                'sf probe 0:0',
200                'fatload host 0:1 4000000 %s/u-boot.bin.old' % CAPSULE_DATA_DIR,
201                'sf write 4000000 100000 10',
202                'sf read 5000000 100000 10',
203                'md.b 5000000 10'])
204            assert 'Old' in ''.join(output)
205
206            # place a capsule file
207            output = u_boot_console.run_command_list([
208                'fatload host 0:1 4000000 %s/Test02' % CAPSULE_DATA_DIR,
209                'fatwrite host 0:1 4000000 %s/Test02 $filesize' % CAPSULE_INSTALL_DIR,
210                'fatls host 0:1 %s' % CAPSULE_INSTALL_DIR])
211            assert 'Test02' in ''.join(output)
212
213        # reboot
214        u_boot_console.restart_uboot()
215
216        capsule_early = u_boot_config.buildconfig.get(
217            'config_efi_capsule_on_disk_early')
218        with u_boot_console.log.section('Test Case 3-b, after reboot'):
219            if not capsule_early:
220                # make sure that dfu_alt_info exists even persistent variables
221                # are not available.
222                output = u_boot_console.run_command_list([
223                    'env set dfu_alt_info "sf 0:0=u-boot-bin raw 0x100000 0x50000;u-boot-env raw 0x150000 0x200000"',
224                    'host bind 0 %s' % disk_img,
225                    'fatls host 0:1 %s' % CAPSULE_INSTALL_DIR])
226                assert 'Test02' in ''.join(output)
227
228                # need to run uefi command to initiate capsule handling
229                output = u_boot_console.run_command(
230                    'env print -e -all Capsule0000')
231
232            output = u_boot_console.run_command_list([
233                'host bind 0 %s' % disk_img,
234                'fatls host 0:1 %s' % CAPSULE_INSTALL_DIR])
235            assert 'Test02' not in ''.join(output)
236
237            output = u_boot_console.run_command_list([
238                'sf probe 0:0',
239                'sf read 4000000 100000 10',
240                'md.b 4000000 10'])
241            assert 'u-boot:New' in ''.join(output)
242