1# SPDX-License-Identifier: GPL-2.0+ 2""" Unit test for UEFI menu-driven configuration 3""" 4 5import pytest 6import time 7 8@pytest.mark.boardspec('sandbox') 9@pytest.mark.buildconfigspec('cmd_eficonfig') 10@pytest.mark.buildconfigspec('cmd_bootefi_bootmgr') 11def test_efi_eficonfig(u_boot_console, efi_eficonfig_data): 12 13 def send_user_input_and_wait(user_str, expect_str): 14 time.sleep(0.1) # TODO: does not work correctly without sleep 15 u_boot_console.run_command(cmd=user_str, wait_for_prompt=False, 16 wait_for_echo=True, send_nl=False) 17 u_boot_console.run_command(cmd='\x0d', wait_for_prompt=False, 18 wait_for_echo=False, send_nl=False) 19 if expect_str is not None: 20 for i in expect_str: 21 u_boot_console.p.expect([i]) 22 23 def press_up_down_enter_and_wait(up_count, down_count, enter, expect_str): 24 # press UP key 25 for i in range(up_count): 26 u_boot_console.run_command(cmd='\x1b\x5b\x41', wait_for_prompt=False, 27 wait_for_echo=False, send_nl=False) 28 # press DOWN key 29 for i in range(down_count): 30 u_boot_console.run_command(cmd='\x1b\x5b\x42', wait_for_prompt=False, 31 wait_for_echo=False, send_nl=False) 32 # press ENTER if requested 33 if enter: 34 u_boot_console.run_command(cmd='\x0d', wait_for_prompt=False, 35 wait_for_echo=False, send_nl=False) 36 # wait expected output 37 if expect_str is not None: 38 for i in expect_str: 39 u_boot_console.p.expect([i]) 40 41 def press_escape_key(wait_prompt): 42 u_boot_console.run_command(cmd='\x1b', wait_for_prompt=wait_prompt, wait_for_echo=False, send_nl=False) 43 44 def press_enter_key(wait_prompt): 45 u_boot_console.run_command(cmd='\x0d', wait_for_prompt=wait_prompt, 46 wait_for_echo=False, send_nl=False) 47 48 def check_current_is_maintenance_menu(): 49 for i in ('UEFI Maintenance Menu', 'Add Boot Option', 'Edit Boot Option', 50 'Change Boot Order', 'Delete Boot Option', 'Quit'): 51 u_boot_console.p.expect([i]) 52 53 """ Unit test for "eficonfig" command 54 The menu-driven interface is used to set up UEFI load options. 55 The bootefi bootmgr loads initrddump.efi as a payload. 56 The crc32 of the loaded initrd.img is checked 57 58 Args: 59 u_boot_console -- U-Boot console 60 efi__data -- Path to the disk image used for testing. 61 Test disk image has following files. 62 initrd-1.img 63 initrd-2.img 64 initrddump.efi 65 66 """ 67 # This test passes for unknown reasons in the bowels of U-Boot. It needs to 68 # be replaced with a unit test. 69 return 70 71 # Restart the system to clean the previous state 72 u_boot_console.restart_uboot() 73 74 with u_boot_console.temporary_timeout(500): 75 # 76 # Test Case 1: Check the menu is displayed 77 # 78 u_boot_console.run_command('eficonfig', wait_for_prompt=False) 79 for i in ('UEFI Maintenance Menu', 'Add Boot Option', 'Edit Boot Option', 80 'Change Boot Order', 'Delete Boot Option', 'Quit'): 81 u_boot_console.p.expect([i]) 82 # Select "Add Boot Option" 83 press_enter_key(False) 84 for i in ('Add Boot Option', 'Description:', 'File', 'Initrd File', 'Optional Data', 85 'Save', 'Quit'): 86 u_boot_console.p.expect([i]) 87 press_escape_key(False) 88 check_current_is_maintenance_menu() 89 # return to U-Boot console 90 press_escape_key(True) 91 92 # 93 # Test Case 2: check auto generated media device entry 94 # 95 96 # bind the test disk image for succeeding tests 97 u_boot_console.run_command(cmd = f'host bind 0 {efi_eficonfig_data}') 98 99 u_boot_console.run_command('eficonfig', wait_for_prompt=False) 100 101 # Change the Boot Order 102 press_up_down_enter_and_wait(0, 2, True, 'Quit') 103 for i in ('host 0:1', 'Save', 'Quit'): 104 u_boot_console.p.expect([i]) 105 # disable auto generated boot option for succeeding test 106 u_boot_console.run_command(cmd=' ', wait_for_prompt=False, 107 wait_for_echo=False, send_nl=False) 108 # Save the BootOrder 109 press_up_down_enter_and_wait(0, 1, True, None) 110 check_current_is_maintenance_menu() 111 112 # 113 # Test Case 3: Add first Boot Option and load it 114 # 115 116 # Select 'Add Boot Option' 117 press_up_down_enter_and_wait(0, 0, True, 'Quit') 118 119 # Press the enter key to select 'Description:' entry, then enter Description 120 press_up_down_enter_and_wait(0, 0, True, 'enter description:') 121 # Send Description user input, press ENTER key to complete 122 send_user_input_and_wait('test 1', 'Quit') 123 124 # Set EFI image(initrddump.efi) 125 press_up_down_enter_and_wait(0, 1, True, 'Quit') 126 press_up_down_enter_and_wait(0, 0, True, 'host 0:1') 127 # Select 'host 0:1' 128 press_up_down_enter_and_wait(0, 0, True, 'Quit') 129 # Press down key to select "initrddump.efi" entry followed by the enter key 130 press_up_down_enter_and_wait(0, 2, True, 'Quit') 131 132 # Set Initrd file(initrd-1.img) 133 press_up_down_enter_and_wait(0, 2, True, 'Quit') 134 press_up_down_enter_and_wait(0, 0, True, 'host 0:1') 135 # Select 'host 0:1' 136 press_up_down_enter_and_wait(0, 0, True, 'Quit') 137 # Press down key to select "initrd-1.img" entry followed by the enter key 138 press_up_down_enter_and_wait(0, 0, True, 'Quit') 139 140 # Set optional_data 141 press_up_down_enter_and_wait(0, 3, True, 'Optional Data:') 142 # Send Description user input, press ENTER key to complete 143 send_user_input_and_wait('nocolor', None) 144 for i in ('Description: test 1', 'File: host 0:1/initrddump.efi', 145 'Initrd File: host 0:1/initrd-1.img', 'Optional Data: nocolor', 'Save', 'Quit'): 146 u_boot_console.p.expect([i]) 147 148 # Save the Boot Option 149 press_up_down_enter_and_wait(0, 4, True, None) 150 check_current_is_maintenance_menu() 151 152 # Check the newly added Boot Option is handled correctly 153 # Return to U-Boot console 154 press_escape_key(True) 155 u_boot_console.run_command(cmd = 'bootefi bootmgr') 156 response = u_boot_console.run_command(cmd = 'load', wait_for_echo=False) 157 assert 'crc32: 0x181464af' in response 158 u_boot_console.run_command(cmd = 'exit', wait_for_echo=False) 159 160 # 161 # Test Case 4: Add second Boot Option and load it 162 # 163 u_boot_console.run_command('eficonfig', wait_for_prompt=False) 164 165 # Select 'Add Boot Option' 166 press_up_down_enter_and_wait(0, 0, True, 'Quit') 167 168 # Press the enter key to select 'Description:' entry, then enter Description 169 press_up_down_enter_and_wait(0, 0, True, 'enter description:') 170 # Send Description user input, press ENTER key to complete 171 send_user_input_and_wait('test 2', 'Quit') 172 173 # Set EFI image(initrddump.efi) 174 press_up_down_enter_and_wait(0, 1, True, 'Quit') 175 press_up_down_enter_and_wait(0, 0, True, 'host 0:1') 176 # Select 'host 0:1' 177 press_up_down_enter_and_wait(0, 0, True, 'Quit') 178 # Press down key to select "initrddump.efi" entry followed by the enter key 179 press_up_down_enter_and_wait(0, 2, True, 'Quit') 180 181 # Set Initrd file(initrd-2.img) 182 press_up_down_enter_and_wait(0, 2, True, 'Quit') 183 press_up_down_enter_and_wait(0, 0, True, 'host 0:1') 184 # Select 'host 0:1' 185 press_up_down_enter_and_wait(0, 0, True, 'Quit') 186 # Press down key to select "initrd-2.img" entry followed by the enter key 187 press_up_down_enter_and_wait(0, 1, True, 'Quit') 188 189 # Set optional_data 190 press_up_down_enter_and_wait(0, 3, True, 'Optional Data:') 191 # Send Description user input, press ENTER key to complete 192 send_user_input_and_wait('nocolor', None) 193 for i in ('Description: test 2', 'File: host 0:1/initrddump.efi', 194 'Initrd File: host 0:1/initrd-2.img', 'Optional Data: nocolor', 'Save', 'Quit'): 195 u_boot_console.p.expect([i]) 196 197 # Save the Boot Option 198 press_up_down_enter_and_wait(0, 4, True, 'Quit') 199 200 # Change the Boot Order 201 press_up_down_enter_and_wait(0, 2, True, 'Quit') 202 press_up_down_enter_and_wait(0, 1, False, 'Quit') 203 # move 'test 1' to the second entry 204 u_boot_console.run_command(cmd='+', wait_for_prompt=False, 205 wait_for_echo=False, send_nl=False) 206 for i in ('test 2', 'test 1', 'host 0:1', 'Save', 'Quit'): 207 u_boot_console.p.expect([i]) 208 # Save the BootOrder 209 press_up_down_enter_and_wait(0, 3, True, None) 210 check_current_is_maintenance_menu() 211 212 # Check the newly added Boot Option is handled correctly 213 # Return to U-Boot console 214 press_escape_key(True) 215 u_boot_console.run_command(cmd = 'bootefi bootmgr') 216 response = u_boot_console.run_command(cmd = 'load', wait_for_echo=False) 217 assert 'crc32: 0x811d3515' in response 218 u_boot_console.run_command(cmd = 'exit', wait_for_echo=False) 219 220 # 221 # Test Case 5: Change BootOrder and load it 222 # 223 u_boot_console.run_command('eficonfig', wait_for_prompt=False) 224 225 # Change the Boot Order 226 press_up_down_enter_and_wait(0, 2, True, None) 227 # Check the current BootOrder 228 for i in ('test 2', 'test 1', 'host 0:1', 'Save', 'Quit'): 229 u_boot_console.p.expect([i]) 230 # move 'test 2' to the second entry 231 u_boot_console.run_command(cmd='-', wait_for_prompt=False, 232 wait_for_echo=False, send_nl=False) 233 for i in ('test 1', 'test 2', 'host 0:1', 'Save', 'Quit'): 234 u_boot_console.p.expect([i]) 235 # Save the BootOrder 236 press_up_down_enter_and_wait(0, 2, True, None) 237 check_current_is_maintenance_menu() 238 239 # Return to U-Boot console 240 press_escape_key(True) 241 u_boot_console.run_command(cmd = 'bootefi bootmgr') 242 response = u_boot_console.run_command(cmd = 'load', wait_for_echo=False) 243 assert 'crc32: 0x181464af' in response 244 u_boot_console.run_command(cmd = 'exit', wait_for_echo=False) 245 246 # 247 # Test Case 6: Delete Boot Option(label:test 2) 248 # 249 u_boot_console.run_command('eficonfig', wait_for_prompt=False) 250 251 # Select 'Delete Boot Option' 252 press_up_down_enter_and_wait(0, 3, True, None) 253 # Check the current BootOrder 254 for i in ('test 1', 'test 2', 'Quit'): 255 u_boot_console.p.expect([i]) 256 257 # Delete 'test 2' 258 press_up_down_enter_and_wait(0, 1, True, None) 259 for i in ('test 1', 'Quit'): 260 u_boot_console.p.expect([i]) 261 press_escape_key(False) 262 check_current_is_maintenance_menu() 263 # Return to U-Boot console 264 press_escape_key(True) 265 266 # 267 # Test Case 7: Edit Boot Option 268 # 269 u_boot_console.run_command('eficonfig', wait_for_prompt=False) 270 # Select 'Edit Boot Option' 271 press_up_down_enter_and_wait(0, 1, True, None) 272 # Check the current BootOrder 273 for i in ('test 1', 'Quit'): 274 u_boot_console.p.expect([i]) 275 press_up_down_enter_and_wait(0, 0, True, None) 276 for i in ('Description: test 1', 'File: host 0:1/initrddump.efi', 277 'Initrd File: host 0:1/initrd-1.img', 'Optional Data: nocolor', 'Save', 'Quit'): 278 u_boot_console.p.expect([i]) 279 280 # Press the enter key to select 'Description:' entry, then enter Description 281 press_up_down_enter_and_wait(0, 0, True, 'enter description:') 282 # Send Description user input, press ENTER key to complete 283 send_user_input_and_wait('test 3', 'Quit') 284 285 # Set EFI image(initrddump.efi) 286 press_up_down_enter_and_wait(0, 1, True, 'Quit') 287 press_up_down_enter_and_wait(0, 0, True, 'host 0:1') 288 # Select 'host 0:1' 289 press_up_down_enter_and_wait(0, 0, True, 'Quit') 290 # Press down key to select "initrddump.efi" entry followed by the enter key 291 press_up_down_enter_and_wait(0, 2, True, 'Quit') 292 293 # Set Initrd file(initrd-2.img) 294 press_up_down_enter_and_wait(0, 2, True, 'Quit') 295 press_up_down_enter_and_wait(0, 0, True, 'host 0:1') 296 # Select 'host 0:1' 297 press_up_down_enter_and_wait(0, 0, True, 'Quit') 298 # Press down key to select "initrd-1.img" entry followed by the enter key 299 press_up_down_enter_and_wait(0, 1, True, 'Quit') 300 301 # Set optional_data 302 press_up_down_enter_and_wait(0, 3, True, 'Optional Data:') 303 # Send Description user input, press ENTER key to complete 304 send_user_input_and_wait('', None) 305 for i in ('Description: test 3', 'File: host 0:1/initrddump.efi', 306 'Initrd File: host 0:1/initrd-2.img', 'Optional Data:', 'Save', 'Quit'): 307 u_boot_console.p.expect([i]) 308 309 # Save the Boot Option 310 press_up_down_enter_and_wait(0, 4, True, 'Quit') 311 press_escape_key(False) 312 check_current_is_maintenance_menu() 313 314 # Check the updated Boot Option is handled correctly 315 # Return to U-Boot console 316 press_escape_key(True) 317 u_boot_console.run_command(cmd = 'bootefi bootmgr') 318 response = u_boot_console.run_command(cmd = 'load', wait_for_echo=False) 319 assert 'crc32: 0x811d3515' in response 320 u_boot_console.run_command(cmd = 'exit', wait_for_echo=False) 321 322 # 323 # Test Case 8: Delete Boot Option(label:test 3) 324 # 325 u_boot_console.run_command('eficonfig', wait_for_prompt=False) 326 327 # Select 'Delete Boot Option' 328 press_up_down_enter_and_wait(0, 3, True, None) 329 # Check the current BootOrder 330 for i in ('test 3', 'Quit'): 331 u_boot_console.p.expect([i]) 332 333 # Delete 'test 3' 334 press_up_down_enter_and_wait(0, 0, True, 'Quit') 335 press_escape_key(False) 336 check_current_is_maintenance_menu() 337 # Return to U-Boot console 338 press_escape_key(True) 339 340 # remove the host device 341 u_boot_console.run_command(cmd = f'host bind -r 0') 342 343 # 344 # Test Case 9: No block device found 345 # 346 u_boot_console.run_command('eficonfig', wait_for_prompt=False) 347 348 # Select 'Add Boot Option' 349 press_up_down_enter_and_wait(0, 0, True, 'Quit') 350 351 # Set EFI image 352 press_up_down_enter_and_wait(0, 1, True, 'Quit') 353 press_up_down_enter_and_wait(0, 0, True, 'No block device found!') 354 press_escape_key(False) 355 press_escape_key(False) 356 check_current_is_maintenance_menu() 357 # Return to U-Boot console 358 press_escape_key(True) 359