1# SPDX-License-Identifier: GPL-2.0+ 2# Copyright (c) 2021, Linaro Limited 3# Author: AKASHI Takahiro <takahiro.akashi@linaro.org> 4 5"""U-Boot UEFI: Firmware Update (Signed capsule with raw images) Test 6This test verifies capsule-on-disk firmware update 7with signed capsule files containing raw images 8""" 9 10import pytest 11from capsule_defs import CAPSULE_DATA_DIR, CAPSULE_INSTALL_DIR 12 13@pytest.mark.boardspec('sandbox') 14@pytest.mark.buildconfigspec('efi_capsule_firmware_raw') 15@pytest.mark.buildconfigspec('efi_capsule_authenticate') 16@pytest.mark.buildconfigspec('dfu') 17@pytest.mark.buildconfigspec('dfu_sf') 18@pytest.mark.buildconfigspec('cmd_efidebug') 19@pytest.mark.buildconfigspec('cmd_fat') 20@pytest.mark.buildconfigspec('cmd_memory') 21@pytest.mark.buildconfigspec('cmd_nvedit_efi') 22@pytest.mark.buildconfigspec('cmd_sf') 23@pytest.mark.slow 24class TestEfiCapsuleFirmwareSignedRaw(): 25 """Firmware Update (Signed capsule with raw images) Test 26 """ 27 28 def test_efi_capsule_auth1( 29 self, u_boot_config, u_boot_console, efi_capsule_data): 30 """Test Case 1 - Update U-Boot on SPI Flash, raw image format 31 0x100000-0x150000: U-Boot binary (but dummy) 32 33 If the capsule is properly signed, the authentication 34 should pass and the firmware be updated. 35 """ 36 disk_img = efi_capsule_data 37 with u_boot_console.log.section('Test Case 1-a, before reboot'): 38 output = u_boot_console.run_command_list([ 39 'host bind 0 %s' % disk_img, 40 'efidebug boot add -b 1 TEST host 0:1 /helloworld.efi', 41 'efidebug boot order 1', 42 'env set -e -nv -bs -rt OsIndications =0x0000000000000004', 43 'env set dfu_alt_info ' 44 '"sf 0:0=u-boot-bin raw 0x100000 ' 45 '0x50000;u-boot-env raw 0x150000 0x200000"', 46 'env save']) 47 48 # initialize content 49 output = u_boot_console.run_command_list([ 50 'sf probe 0:0', 51 'fatload host 0:1 4000000 %s/u-boot.bin.old' 52 % CAPSULE_DATA_DIR, 53 'sf write 4000000 100000 10', 54 'sf read 5000000 100000 10', 55 'md.b 5000000 10']) 56 assert 'Old' in ''.join(output) 57 58 # place a capsule file 59 output = u_boot_console.run_command_list([ 60 'fatload host 0:1 4000000 %s/Test11' % CAPSULE_DATA_DIR, 61 'fatwrite host 0:1 4000000 %s/Test11 $filesize' 62 % CAPSULE_INSTALL_DIR, 63 'fatls host 0:1 %s' % CAPSULE_INSTALL_DIR]) 64 assert 'Test11' in ''.join(output) 65 66 # reboot 67 mnt_point = u_boot_config.persistent_data_dir + '/test_efi_capsule' 68 u_boot_console.config.dtb = mnt_point + CAPSULE_DATA_DIR \ 69 + '/test_sig.dtb' 70 u_boot_console.restart_uboot() 71 72 capsule_early = u_boot_config.buildconfig.get( 73 'config_efi_capsule_on_disk_early') 74 with u_boot_console.log.section('Test Case 1-b, after reboot'): 75 if not capsule_early: 76 # make sure that dfu_alt_info exists even persistent variables 77 # are not available. 78 output = u_boot_console.run_command_list([ 79 'env set dfu_alt_info ' 80 '"sf 0:0=u-boot-bin raw 0x100000 ' 81 '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 'Test11' 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 Capsule0000', wait_for_reboot = True) 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 'Test11' not 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:New' in ''.join(output) 100 101 def test_efi_capsule_auth2( 102 self, u_boot_config, u_boot_console, efi_capsule_data): 103 """Test Case 2 - Update U-Boot on SPI Flash, raw image format 104 0x100000-0x150000: U-Boot binary (but dummy) 105 106 If the capsule is signed but with an invalid key, 107 the authentication should fail and the firmware 108 not be updated. 109 """ 110 disk_img = efi_capsule_data 111 with u_boot_console.log.section('Test Case 2-a, before reboot'): 112 output = u_boot_console.run_command_list([ 113 'host bind 0 %s' % disk_img, 114 'printenv -e PlatformLangCodes', # workaround for terminal size determination 115 'efidebug boot add -b 1 TEST host 0:1 /helloworld.efi', 116 'efidebug boot order 1', 117 'env set -e -nv -bs -rt OsIndications =0x0000000000000004', 118 'env set dfu_alt_info ' 119 '"sf 0:0=u-boot-bin raw 0x100000 ' 120 '0x50000;u-boot-env raw 0x150000 0x200000"', 121 'env save']) 122 123 # initialize content 124 output = u_boot_console.run_command_list([ 125 'sf probe 0:0', 126 'fatload host 0:1 4000000 %s/u-boot.bin.old' 127 % CAPSULE_DATA_DIR, 128 'sf write 4000000 100000 10', 129 'sf read 5000000 100000 10', 130 'md.b 5000000 10']) 131 assert 'Old' in ''.join(output) 132 133 # place a capsule file 134 output = u_boot_console.run_command_list([ 135 'fatload host 0:1 4000000 %s/Test12' % CAPSULE_DATA_DIR, 136 'fatwrite host 0:1 4000000 %s/Test12 $filesize' 137 % CAPSULE_INSTALL_DIR, 138 'fatls host 0:1 %s' % CAPSULE_INSTALL_DIR]) 139 assert 'Test12' in ''.join(output) 140 141 # reboot 142 mnt_point = u_boot_config.persistent_data_dir + '/test_efi_capsule' 143 u_boot_console.config.dtb = mnt_point + CAPSULE_DATA_DIR \ 144 + '/test_sig.dtb' 145 u_boot_console.restart_uboot() 146 147 capsule_early = u_boot_config.buildconfig.get( 148 'config_efi_capsule_on_disk_early') 149 with u_boot_console.log.section('Test Case 2-b, after reboot'): 150 if not capsule_early: 151 # make sure that dfu_alt_info exists even persistent variables 152 # are not available. 153 output = u_boot_console.run_command_list([ 154 'env set dfu_alt_info ' 155 '"sf 0:0=u-boot-bin raw 0x100000 ' 156 '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 'Test12' 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 Capsule0000', wait_for_reboot = True) 164 165 # deleted any way 166 output = u_boot_console.run_command_list([ 167 'host bind 0 %s' % disk_img, 168 'fatls host 0:1 %s' % CAPSULE_INSTALL_DIR]) 169 assert 'Test12' not in ''.join(output) 170 171 # TODO: check CapsuleStatus in CapsuleXXXX 172 173 output = u_boot_console.run_command_list([ 174 'sf probe 0:0', 175 'sf read 4000000 100000 10', 176 'md.b 4000000 10']) 177 assert 'u-boot:Old' in ''.join(output) 178 179 def test_efi_capsule_auth3( 180 self, u_boot_config, u_boot_console, efi_capsule_data): 181 """Test Case 3 - Update U-Boot on SPI Flash, raw image format 182 0x100000-0x150000: U-Boot binary (but dummy) 183 184 If the capsule is not signed, the authentication 185 should fail and the firmware not be updated. 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 'printenv -e PlatformLangCodes', # workaround for terminal size determination 192 'efidebug boot add -b 1 TEST host 0:1 /helloworld.efi', 193 'efidebug boot order 1', 194 'env set -e -nv -bs -rt OsIndications =0x0000000000000004', 195 'env set dfu_alt_info ' 196 '"sf 0:0=u-boot-bin raw 0x100000 ' 197 '0x50000;u-boot-env raw 0x150000 0x200000"', 198 'env save']) 199 200 # initialize content 201 output = u_boot_console.run_command_list([ 202 'sf probe 0:0', 203 'fatload host 0:1 4000000 %s/u-boot.bin.old' 204 % CAPSULE_DATA_DIR, 205 'sf write 4000000 100000 10', 206 'sf read 5000000 100000 10', 207 'md.b 5000000 10']) 208 assert 'Old' in ''.join(output) 209 210 # place a capsule file 211 output = u_boot_console.run_command_list([ 212 'fatload host 0:1 4000000 %s/Test02' % CAPSULE_DATA_DIR, 213 'fatwrite host 0:1 4000000 %s/Test02 $filesize' 214 % CAPSULE_INSTALL_DIR, 215 'fatls host 0:1 %s' % CAPSULE_INSTALL_DIR]) 216 assert 'Test02' in ''.join(output) 217 218 # reboot 219 mnt_point = u_boot_config.persistent_data_dir + '/test_efi_capsule' 220 u_boot_console.config.dtb = mnt_point + CAPSULE_DATA_DIR \ 221 + '/test_sig.dtb' 222 u_boot_console.restart_uboot() 223 224 capsule_early = u_boot_config.buildconfig.get( 225 'config_efi_capsule_on_disk_early') 226 with u_boot_console.log.section('Test Case 3-b, after reboot'): 227 if not capsule_early: 228 # make sure that dfu_alt_info exists even persistent variables 229 # are not available. 230 output = u_boot_console.run_command_list([ 231 'env set dfu_alt_info ' 232 '"sf 0:0=u-boot-bin raw 0x100000 ' 233 '0x50000;u-boot-env raw 0x150000 0x200000"', 234 'host bind 0 %s' % disk_img, 235 'fatls host 0:1 %s' % CAPSULE_INSTALL_DIR]) 236 assert 'Test02' in ''.join(output) 237 238 # need to run uefi command to initiate capsule handling 239 output = u_boot_console.run_command( 240 'env print -e Capsule0000', wait_for_reboot = True) 241 242 # deleted anyway 243 output = u_boot_console.run_command_list([ 244 'host bind 0 %s' % disk_img, 245 'fatls host 0:1 %s' % CAPSULE_INSTALL_DIR]) 246 assert 'Test02' not in ''.join(output) 247 248 # TODO: check CapsuleStatus in CapsuleXXXX 249 250 output = u_boot_console.run_command_list([ 251 'sf probe 0:0', 252 'sf read 4000000 100000 10', 253 'md.b 4000000 10']) 254 assert 'u-boot:Old' in ''.join(output) 255