1# HOST_TEST for espefuse.py using the pytest framework 2# 3# Supports esp32, esp32s2, esp32s3beta2, esp32s3, 4# esp32c3, esp32h2beta1, esp32c2, esp32c6, esp32p4, 5# esp32c61, esp32c5, esp32c5beta3. 6# 7# How to use: 8# 9# Run as HOST_TEST (without a physical connection to a chip): 10# - `pytest test_espefuse.py --chip esp32` 11# - `pytest test_espefuse.py --chip esp32s2` 12# 13# OR 14# 15# Run as TEST on FPGA (connection to FPGA with a flashed image): 16# required two COM ports 17# - `pytest test_espefuse.py \ 18# --chip esp32 --port /dev/ttyUSB0 --reset-port /dev/ttyUSB1` 19# 20# where - --port - a port for espefuse.py operation 21# - --reset-port - a port to clear efuses (connect RTS or DTR ->- J14 pin 39) 22# 23# Note: For FPGA with ESP32 image, you need to set an env variable ESPTOOL_ENV_FPGA to 1 24# to slow down the connection sequence 25# because of a long delay (~6 seconds) after resetting the FPGA. 26# This is not necessary when using other images than ESP32 27 28import os 29import subprocess 30import sys 31import tempfile 32import time 33 34from bitstring import BitStream 35 36# Make command line options --port, --reset-port and --chip available 37from conftest import arg_chip, arg_port, arg_reset_port, need_to_install_package_err 38 39TEST_DIR = os.path.abspath(os.path.dirname(__file__)) 40IMAGES_DIR = os.path.join(TEST_DIR, "images", "efuse") 41S_IMAGES_DIR = os.path.join(TEST_DIR, "secure_images") 42EFUSE_S_DIR = os.path.join(TEST_DIR, "efuse_scripts") 43 44import pytest 45 46try: 47 from espefuse import SUPPORTED_CHIPS 48except ImportError: 49 need_to_install_package_err() 50 51SUPPORTED_CHIPS = list(SUPPORTED_CHIPS.keys()) 52 53import serial 54 55# Set reset_port if --reset-port cmdline option is specified 56# This activates testing with real hardware (FPGA) 57reset_port = ( 58 serial.Serial(arg_reset_port, 115200) if arg_reset_port is not None else None 59) 60 61if arg_chip not in SUPPORTED_CHIPS: 62 pytest.exit(f"{arg_chip} is not a supported target, choose from {SUPPORTED_CHIPS}") 63print(f"\nHost tests of espefuse.py for {arg_chip}:") 64print("Running espefuse.py tests...") 65 66 67@pytest.mark.host_test 68class EfuseTestCase: 69 def setup_method(self): 70 if reset_port is None: 71 self.efuse_file = tempfile.NamedTemporaryFile(delete=False) 72 self.base_cmd = ( 73 f"{sys.executable} -m espefuse --chip {arg_chip} " 74 f"--virt --path-efuse-file {self.efuse_file.name} -d" 75 ) 76 self._set_target_wafer_version() 77 else: 78 self.base_cmd = ( 79 f"{sys.executable} -m espefuse --chip {arg_chip} " 80 f"--port {arg_port} -d" 81 ) 82 self.reset_efuses() 83 84 def teardown_method(self): 85 if reset_port is None: 86 self.efuse_file.close() 87 os.unlink(self.efuse_file.name) 88 89 def reset_efuses(self): 90 # reset and zero efuses 91 reset_port.dtr = False 92 reset_port.rts = False 93 time.sleep(0.05) 94 reset_port.dtr = True 95 reset_port.rts = True 96 time.sleep(0.05) 97 reset_port.dtr = False 98 reset_port.rts = False 99 100 def get_esptool(self): 101 if reset_port is not None: 102 import esptool 103 104 esp = esptool.cmds.detect_chip(port=arg_port) 105 del esptool 106 else: 107 import espefuse 108 109 efuse = espefuse.SUPPORTED_CHIPS[arg_chip].efuse_lib 110 esp = efuse.EmulateEfuseController(self.efuse_file.name) 111 del espefuse 112 del efuse 113 return esp 114 115 def _set_34_coding_scheme(self): 116 self.espefuse_py("burn_efuse CODING_SCHEME 1") 117 118 def _set_none_recovery_coding_scheme(self): 119 self.espefuse_py("burn_efuse CODING_SCHEME 3") 120 121 def _set_target_wafer_version(self): 122 # ESP32 has to be ECO3 (v3.0) for tests 123 if arg_chip == "esp32": 124 self.espefuse_py("burn_efuse CHIP_VER_REV1 1 CHIP_VER_REV2 1") 125 126 def check_data_block_in_log( 127 self, log, file_path, repeat=1, reverse_order=False, offset=0 128 ): 129 with open(file_path, "rb") as f: 130 data = BitStream("0x00") * offset + BitStream(f) 131 blk = data.readlist(f"{data.len // 8}*uint:8") 132 blk = blk[::-1] if reverse_order else blk 133 hex_blk = " ".join(f"{num:02x}" for num in blk) 134 assert repeat == log.count(hex_blk) 135 136 def espefuse_not_virt_py(self, cmd, check_msg=None, ret_code=0): 137 full_cmd = " ".join((f"{sys.executable} -m espefuse", cmd)) 138 return self._run_command(full_cmd, check_msg, ret_code) 139 140 def espefuse_py(self, cmd, do_not_confirm=True, check_msg=None, ret_code=0): 141 full_cmd = " ".join( 142 [self.base_cmd, "--do-not-confirm" if do_not_confirm else "", cmd] 143 ) 144 output = self._run_command(full_cmd, check_msg, ret_code) 145 self._run_command( 146 " ".join([self.base_cmd, "check_error"]), "No errors detected", 0 147 ) 148 print(output) 149 return output 150 151 def _run_command(self, cmd, check_msg, ret_code): 152 try: 153 p = subprocess.Popen( 154 cmd.split(), 155 shell=False, 156 stdin=subprocess.PIPE, 157 stdout=subprocess.PIPE, 158 universal_newlines=True, 159 ) 160 output, _ = p.communicate() 161 returncode = p.returncode 162 if check_msg: 163 assert check_msg in output 164 if returncode: 165 print(output) 166 print(cmd) 167 assert ret_code == returncode 168 return output 169 except subprocess.CalledProcessError as error: 170 print(error) 171 raise 172 173 174class TestReadCommands(EfuseTestCase): 175 def test_help(self): 176 self.espefuse_not_virt_py("--help", check_msg="usage: __main__.py [-h]") 177 self.espefuse_not_virt_py(f"--chip {arg_chip} --help") 178 179 def test_help2(self): 180 self.espefuse_not_virt_py("", check_msg="usage: __main__.py [-h]", ret_code=1) 181 182 def test_dump(self): 183 self.espefuse_py("dump -h") 184 self.espefuse_py("dump") 185 186 def test_dump_format_joint(self): 187 tmp_file = tempfile.NamedTemporaryFile(delete=False) 188 self.espefuse_py(f"dump --format joint --file_name {tmp_file.name}") 189 190 def test_dump_split_default(self): 191 tmp_file = tempfile.NamedTemporaryFile(delete=False) 192 self.espefuse_py(f"dump --file_name {tmp_file.name}") 193 194 def test_dump_split(self): 195 tmp_file = tempfile.NamedTemporaryFile(delete=False) 196 self.espefuse_py(f"dump --format split --file_name {tmp_file.name}") 197 198 def test_summary(self): 199 self.espefuse_py("summary -h") 200 self.espefuse_py("summary") 201 202 def test_summary_json(self): 203 self.espefuse_py("summary --format json") 204 205 def test_summary_filter(self): 206 self.espefuse_py("summary MAC") 207 self.espefuse_py("summary --format value_only MAC") 208 self.espefuse_py( 209 "summary --format value_only MAC WR_DIS", 210 check_msg="The 'value_only' format can be used exactly for one efuse.", 211 ret_code=2, 212 ) 213 214 @pytest.mark.skipif( 215 arg_chip == "esp32p4", reason="No Custom MAC Address defined yet" 216 ) 217 def test_get_custom_mac(self): 218 self.espefuse_py("get_custom_mac -h") 219 if arg_chip == "esp32": 220 right_msg = "Custom MAC Address is not set in the device." 221 else: 222 right_msg = "Custom MAC Address: 00:00:00:00:00:00 (OK)" 223 self.espefuse_py("get_custom_mac", check_msg=right_msg) 224 225 def test_adc_info(self): 226 self.espefuse_py("adc_info -h") 227 self.espefuse_py("adc_info") 228 229 def test_adc_info_2(self): 230 if arg_chip == "esp32": 231 self.espefuse_py("burn_efuse BLK3_PART_RESERVE 1") 232 elif arg_chip in ["esp32c3", "esp32s3", "esp32s3beta2"]: 233 self.espefuse_py("burn_efuse BLK_VERSION_MAJOR 1") 234 elif arg_chip in ["esp32c2", "esp32s2", "esp32c6"]: 235 self.espefuse_py("burn_efuse BLK_VERSION_MINOR 1") 236 elif arg_chip in ["esp32h2", "esp32h2beta1"]: 237 self.espefuse_py("burn_efuse BLK_VERSION_MINOR 2") 238 self.espefuse_py("adc_info") 239 240 def test_check_error(self): 241 self.espefuse_py("check_error -h") 242 self.espefuse_py("check_error") 243 self.espefuse_py("check_error --recovery") 244 245 246class TestReadProtectionCommands(EfuseTestCase): 247 def test_read_protect_efuse(self): 248 self.espefuse_py("read_protect_efuse -h") 249 if arg_chip == "esp32": 250 cmd = "read_protect_efuse \ 251 CODING_SCHEME \ 252 MAC_VERSION \ 253 BLOCK1 \ 254 BLOCK2 \ 255 BLOCK3" 256 count_protects = 5 257 elif arg_chip == "esp32c2": 258 cmd = "read_protect_efuse \ 259 BLOCK_KEY0_LOW_128" 260 count_protects = 1 261 else: 262 self.espefuse_py( 263 "burn_efuse \ 264 KEY_PURPOSE_0 HMAC_UP \ 265 KEY_PURPOSE_1 XTS_AES_128_KEY \ 266 KEY_PURPOSE_2 XTS_AES_128_KEY \ 267 KEY_PURPOSE_3 HMAC_DOWN_ALL \ 268 KEY_PURPOSE_4 HMAC_DOWN_JTAG \ 269 KEY_PURPOSE_5 HMAC_DOWN_DIGITAL_SIGNATURE" 270 ) 271 cmd = "read_protect_efuse \ 272 BLOCK_KEY0 \ 273 BLOCK_KEY1 \ 274 BLOCK_KEY2 \ 275 BLOCK_KEY3 \ 276 BLOCK_KEY4 \ 277 BLOCK_KEY5" 278 count_protects = 6 279 self.espefuse_py(cmd) 280 output = self.espefuse_py(cmd) 281 assert count_protects == output.count("is already read protected") 282 283 def test_read_protect_efuse2(self): 284 self.espefuse_py("write_protect_efuse RD_DIS") 285 if arg_chip == "esp32": 286 efuse_name = "CODING_SCHEME" 287 elif arg_chip == "esp32c2": 288 efuse_name = "BLOCK_KEY0_HI_128" 289 else: 290 efuse_name = "BLOCK_SYS_DATA2" 291 self.espefuse_py( 292 f"read_protect_efuse {efuse_name}", 293 check_msg="A fatal error occurred: This efuse cannot be read-disabled " 294 "due the to RD_DIS field is already write-disabled", 295 ret_code=2, 296 ) 297 298 @pytest.mark.skipif(arg_chip != "esp32", reason="when the purpose of BLOCK2 is set") 299 def test_read_protect_efuse3(self): 300 self.espefuse_py("burn_efuse ABS_DONE_1 1") 301 self.espefuse_py(f"burn_key BLOCK2 {IMAGES_DIR}/256bit") 302 self.espefuse_py( 303 "read_protect_efuse BLOCK2", 304 check_msg="Secure Boot V2 is on (ABS_DONE_1 = True), " 305 "BLOCK2 must be readable, stop this operation!", 306 ret_code=2, 307 ) 308 309 def test_read_protect_efuse4(self): 310 if arg_chip == "esp32": 311 self.espefuse_py(f"burn_key BLOCK2 {IMAGES_DIR}/256bit") 312 msg = "must be readable, please stop this operation!" 313 self.espefuse_py("read_protect_efuse BLOCK2", check_msg=msg) 314 elif arg_chip == "esp32c2": 315 self.espefuse_py( 316 f"burn_key BLOCK_KEY0 {IMAGES_DIR}/128bit_key SECURE_BOOT_DIGEST" 317 ) 318 self.espefuse_py( 319 "read_protect_efuse BLOCK_KEY0", 320 check_msg="A fatal error occurred: " 321 "BLOCK_KEY0 must be readable, stop this operation!", 322 ret_code=2, 323 ) 324 else: 325 key1_purpose = ( 326 "USER" 327 if arg_chip in ["esp32p4", "esp32c61", "esp32c5", "esp32c5beta3"] 328 else "RESERVED" 329 ) 330 self.espefuse_py( 331 f"burn_key BLOCK_KEY0 {IMAGES_DIR}/256bit USER \ 332 BLOCK_KEY1 {IMAGES_DIR}/256bit {key1_purpose} \ 333 BLOCK_KEY2 {IMAGES_DIR}/256bit SECURE_BOOT_DIGEST0 \ 334 BLOCK_KEY3 {IMAGES_DIR}/256bit SECURE_BOOT_DIGEST1 \ 335 BLOCK_KEY4 {IMAGES_DIR}/256bit SECURE_BOOT_DIGEST2 \ 336 BLOCK_KEY5 {IMAGES_DIR}/256bit HMAC_UP" 337 ) 338 self.espefuse_py( 339 "read_protect_efuse BLOCK_KEY0", 340 check_msg="A fatal error occurred: " 341 "BLOCK_KEY0 must be readable, stop this operation!", 342 ret_code=2, 343 ) 344 self.espefuse_py( 345 "read_protect_efuse BLOCK_KEY1", 346 check_msg="A fatal error occurred: " 347 "BLOCK_KEY1 must be readable, stop this operation!", 348 ret_code=2, 349 ) 350 self.espefuse_py( 351 "read_protect_efuse BLOCK_KEY2", 352 check_msg="A fatal error occurred: " 353 "BLOCK_KEY2 must be readable, stop this operation!", 354 ret_code=2, 355 ) 356 self.espefuse_py( 357 "read_protect_efuse BLOCK_KEY3", 358 check_msg="A fatal error occurred: " 359 "BLOCK_KEY3 must be readable, stop this operation!", 360 ret_code=2, 361 ) 362 self.espefuse_py( 363 "read_protect_efuse BLOCK_KEY4", 364 check_msg="A fatal error occurred: " 365 "BLOCK_KEY4 must be readable, stop this operation!", 366 ret_code=2, 367 ) 368 self.espefuse_py("read_protect_efuse BLOCK_KEY5") 369 370 @pytest.mark.skipif( 371 arg_chip != "esp32", 372 reason="system parameters efuse read-protection is supported only by esp32, " 373 "other chips protect whole blocks", 374 ) 375 def test_burn_and_read_protect_efuse(self): 376 self.espefuse_py( 377 "burn_efuse FLASH_CRYPT_CONFIG 15 RD_DIS 8", 378 check_msg="Efuse FLASH_CRYPT_CONFIG is read-protected. " 379 "Read back the burn value is not possible.", 380 ) 381 382 383class TestWriteProtectionCommands(EfuseTestCase): 384 def test_write_protect_efuse(self): 385 self.espefuse_py("write_protect_efuse -h") 386 if arg_chip == "esp32": 387 efuse_lists = """WR_DIS RD_DIS CODING_SCHEME 388 XPD_SDIO_FORCE XPD_SDIO_REG XPD_SDIO_TIEH SPI_PAD_CONFIG_CLK 389 FLASH_CRYPT_CNT UART_DOWNLOAD_DIS FLASH_CRYPT_CONFIG 390 ADC_VREF BLOCK1 BLOCK2 BLOCK3""" 391 efuse_lists2 = "WR_DIS RD_DIS" 392 elif arg_chip == "esp32c2": 393 efuse_lists = """RD_DIS DIS_DOWNLOAD_ICACHE 394 XTS_KEY_LENGTH_256 UART_PRINT_CONTROL""" 395 efuse_lists2 = "RD_DIS DIS_DOWNLOAD_ICACHE" 396 elif arg_chip == "esp32p4": 397 efuse_lists = """RD_DIS KEY_PURPOSE_0 SECURE_BOOT_KEY_REVOKE0 398 SPI_BOOT_CRYPT_CNT""" 399 efuse_lists2 = "RD_DIS KEY_PURPOSE_0 KEY_PURPOSE_2" 400 else: 401 efuse_lists = """RD_DIS DIS_ICACHE DIS_FORCE_DOWNLOAD 402 DIS_DOWNLOAD_MANUAL_ENCRYPT 403 USB_EXCHG_PINS WDT_DELAY_SEL SPI_BOOT_CRYPT_CNT 404 SECURE_BOOT_KEY_REVOKE0 SECURE_BOOT_KEY_REVOKE1 405 SECURE_BOOT_KEY_REVOKE2 KEY_PURPOSE_0 KEY_PURPOSE_1 406 KEY_PURPOSE_2 KEY_PURPOSE_3 KEY_PURPOSE_4 KEY_PURPOSE_5 407 SECURE_BOOT_EN SECURE_BOOT_AGGRESSIVE_REVOKE FLASH_TPUW 408 DIS_DOWNLOAD_MODE 409 ENABLE_SECURITY_DOWNLOAD UART_PRINT_CONTROL 410 MAC 411 BLOCK_USR_DATA BLOCK_KEY0 BLOCK_KEY1 412 BLOCK_KEY2 BLOCK_KEY3 BLOCK_KEY4 BLOCK_KEY5""" 413 if arg_chip not in [ 414 "esp32h2", 415 "esp32h2beta1", 416 "esp32c6", 417 "esp32c61", 418 "esp32c5", 419 "esp32c5beta3", 420 ]: 421 efuse_lists += """ DIS_DOWNLOAD_ICACHE 422 SPI_PAD_CONFIG_CLK SPI_PAD_CONFIG_Q 423 SPI_PAD_CONFIG_D SPI_PAD_CONFIG_CS SPI_PAD_CONFIG_HD 424 SPI_PAD_CONFIG_WP SPI_PAD_CONFIG_DQS SPI_PAD_CONFIG_D4 425 SPI_PAD_CONFIG_D5 SPI_PAD_CONFIG_D6 SPI_PAD_CONFIG_D7""" 426 efuse_lists2 = "RD_DIS DIS_ICACHE" 427 self.espefuse_py(f"write_protect_efuse {efuse_lists}") 428 output = self.espefuse_py(f"write_protect_efuse {efuse_lists2}") 429 assert output.count("is already write protected") == 2 430 431 def test_write_protect_efuse2(self): 432 if arg_chip == "esp32": 433 self.espefuse_py("write_protect_efuse WR_DIS") 434 self.espefuse_py( 435 "write_protect_efuse CODING_SCHEME", 436 check_msg="A fatal error occurred: This efuse cannot be write-disabled " 437 "due to the WR_DIS field is already write-disabled", 438 ret_code=2, 439 ) 440 441 442@pytest.mark.skipif(arg_chip == "esp32p4", reason="No Custom MAC Address defined yet") 443class TestBurnCustomMacCommands(EfuseTestCase): 444 def test_burn_custom_mac(self): 445 self.espefuse_py("burn_custom_mac -h") 446 cmd = "burn_custom_mac AA:CD:EF:11:22:33" 447 mac = "aa:cd:ef:11:22:33" 448 if arg_chip == "esp32": 449 self.espefuse_py( 450 cmd, check_msg=f"Custom MAC Address version 1: {mac} (CRC 0x63 OK)" 451 ) 452 else: 453 self.espefuse_py(cmd, check_msg=f"Custom MAC Address: {mac} (OK)") 454 455 def test_burn_custom_mac2(self): 456 self.espefuse_py( 457 "burn_custom_mac AA:CD:EF:11:22:33:44", 458 check_msg="A fatal error occurred: MAC Address needs to be a 6-byte " 459 "hexadecimal format separated by colons (:)!", 460 ret_code=2, 461 ) 462 463 def test_burn_custom_mac3(self): 464 self.espefuse_py( 465 "burn_custom_mac AB:CD:EF:11:22:33", 466 check_msg="A fatal error occurred: Custom MAC must be a unicast MAC!", 467 ret_code=2, 468 ) 469 470 @pytest.mark.skipif( 471 arg_chip != "esp32", reason="3/4 coding scheme is only in esp32" 472 ) 473 def test_burn_custom_mac_with_34_coding_scheme(self): 474 self._set_34_coding_scheme() 475 self.espefuse_py("burn_custom_mac -h") 476 self.espefuse_py( 477 "burn_custom_mac AA:CD:EF:01:02:03", 478 check_msg="Custom MAC Address version 1: aa:cd:ef:01:02:03 (CRC 0x56 OK)", 479 ) 480 self.espefuse_py( 481 "get_custom_mac", 482 check_msg="Custom MAC Address version 1: aa:cd:ef:01:02:03 (CRC 0x56 OK)", 483 ) 484 485 self.espefuse_py( 486 "burn_custom_mac FE:22:33:44:55:66", 487 check_msg="New value contains some bits that cannot be cleared " 488 "(value will be 0x675745ffeffe)", 489 ret_code=2, 490 ) 491 492 493@pytest.mark.skipif( 494 arg_chip 495 not in [ 496 "esp32", 497 "esp32s2", 498 "esp32s3", 499 ], 500 reason=f"{arg_chip} does not support set_flash_voltage", 501) 502class TestSetFlashVoltageCommands(EfuseTestCase): 503 def test_set_flash_voltage_1_8v(self): 504 self.espefuse_py("set_flash_voltage -h") 505 vdd = "VDD_SDIO" if arg_chip == "esp32" else "VDD_SPI" 506 self.espefuse_py( 507 "set_flash_voltage 1.8V", 508 check_msg=f"Set internal flash voltage regulator ({vdd}) to 1.8V.", 509 ) 510 if arg_chip == "esp32": 511 error_msg = "A fatal error occurred: " 512 "Can't set flash regulator to OFF as XPD_SDIO_REG efuse is already burned" 513 else: 514 error_msg = "A fatal error occurred: " 515 "Can't set flash regulator to OFF as VDD_SPI_XPD efuse is already burned" 516 self.espefuse_py( 517 "set_flash_voltage 3.3V", 518 check_msg=f"Enable internal flash voltage regulator ({vdd}) to 3.3V.", 519 ) 520 self.espefuse_py("set_flash_voltage OFF", check_msg=error_msg, ret_code=2) 521 522 def test_set_flash_voltage_3_3v(self): 523 vdd = "VDD_SDIO" if arg_chip == "esp32" else "VDD_SPI" 524 self.espefuse_py( 525 "set_flash_voltage 3.3V", 526 check_msg=f"Enable internal flash voltage regulator ({vdd}) to 3.3V.", 527 ) 528 if arg_chip == "esp32": 529 error_msg = "A fatal error occurred: " 530 "Can't set regulator to 1.8V is XPD_SDIO_TIEH efuse is already burned" 531 else: 532 error_msg = "A fatal error occurred: " 533 "Can't set regulator to 1.8V is VDD_SPI_TIEH efuse is already burned" 534 self.espefuse_py("set_flash_voltage 1.8V", check_msg=error_msg, ret_code=2) 535 536 if arg_chip == "esp32": 537 error_msg = "A fatal error occurred: " 538 "Can't set flash regulator to OFF as XPD_SDIO_REG efuse is already burned" 539 else: 540 error_msg = "A fatal error occurred: " 541 "Can't set flash regulator to OFF as VDD_SPI_XPD efuse is already burned" 542 self.espefuse_py("set_flash_voltage OFF", check_msg=error_msg, ret_code=2) 543 544 def test_set_flash_voltage_off(self): 545 vdd = "VDD_SDIO" if arg_chip == "esp32" else "VDD_SPI" 546 self.espefuse_py( 547 "set_flash_voltage OFF", 548 check_msg=f"Disable internal flash voltage regulator ({vdd})", 549 ) 550 self.espefuse_py( 551 "set_flash_voltage 3.3V", 552 check_msg=f"Enable internal flash voltage regulator ({vdd}) to 3.3V.", 553 ) 554 555 def test_set_flash_voltage_off2(self): 556 vdd = "VDD_SDIO" if arg_chip == "esp32" else "VDD_SPI" 557 self.espefuse_py( 558 "set_flash_voltage OFF", 559 check_msg=f"Disable internal flash voltage regulator ({vdd})", 560 ) 561 self.espefuse_py( 562 "set_flash_voltage 1.8V", 563 check_msg=f"Set internal flash voltage regulator ({vdd}) to 1.8V.", 564 ) 565 566 567@pytest.mark.skipif(arg_chip != "esp32c3", reason="Not necessary for all chips") 568class TestValueArgForBurnEfuseCommands(EfuseTestCase): 569 def test_efuse_is_bool_given_none(self): 570 self.espefuse_py("burn_efuse SECURE_BOOT_KEY_REVOKE0") 571 572 def test_efuse_is_bool_given_0(self): 573 self.espefuse_py( 574 "burn_efuse SECURE_BOOT_KEY_REVOKE0 0", 575 check_msg="A fatal error occurred: " 576 "New value is not accepted for efuse 'SECURE_BOOT_KEY_REVOKE0' " 577 "(will always burn 0->1), given value=0", 578 ret_code=2, 579 ) 580 581 def test_efuse_is_bool_given_2(self): 582 self.espefuse_py( 583 "burn_efuse SECURE_BOOT_KEY_REVOKE0 2", 584 check_msg="A fatal error occurred: " 585 "New value is not accepted for efuse 'SECURE_BOOT_KEY_REVOKE0' " 586 "(will always burn 0->1), given value=2", 587 ret_code=2, 588 ) 589 590 def test_efuse_is_bytes_ok(self): 591 self.espefuse_py( 592 "burn_efuse OPTIONAL_UNIQUE_ID 0x12345678123456781234567812345678" 593 ) 594 595 def test_efuse_is_bytes_given_short_val(self): 596 self.espefuse_py( 597 "burn_efuse OPTIONAL_UNIQUE_ID 0x1234567812345678", 598 check_msg="A fatal error occurred: " 599 "The length of efuse 'OPTIONAL_UNIQUE_ID' (128 bits) " 600 "(given len of the new value= 64 bits)", 601 ret_code=2, 602 ) 603 604 def test_efuse_is_bytes_given_none(self): 605 self.espefuse_py( 606 "burn_efuse OPTIONAL_UNIQUE_ID", 607 check_msg="A fatal error occurred: " 608 "New value required for efuse 'OPTIONAL_UNIQUE_ID' (given None)", 609 ret_code=2, 610 ) 611 612 def test_efuse_is_int_ok(self): 613 self.espefuse_py("burn_efuse SPI_PAD_CONFIG_D 7") 614 615 def test_efuse_is_int_given_out_of_range_val(self): 616 self.espefuse_py( 617 "burn_efuse SPI_PAD_CONFIG_D 200", 618 check_msg="A fatal error occurred: " 619 "200 is too large an unsigned integer for a bitstring " 620 "of length 6. The allowed range is [0, 63].", 621 ret_code=2, 622 ) 623 624 def test_efuse_is_int_given_none(self): 625 self.espefuse_py( 626 "burn_efuse SPI_PAD_CONFIG_D", 627 check_msg="A fatal error occurred: " 628 "New value required for efuse 'SPI_PAD_CONFIG_D' (given None)", 629 ret_code=2, 630 ) 631 632 def test_efuse_is_int_given_0(self): 633 self.espefuse_py( 634 "burn_efuse SPI_PAD_CONFIG_D 0", 635 check_msg="A fatal error occurred: " 636 "New value should not be 0 for 'SPI_PAD_CONFIG_D' " 637 "(given value= 0)", 638 ret_code=2, 639 ) 640 641 def test_efuse_is_bitcount_given_out_of_range_val(self): 642 self.espefuse_py( 643 "burn_efuse SPI_BOOT_CRYPT_CNT 9", 644 check_msg="A fatal error occurred: " 645 "9 is too large an unsigned integer for a bitstring " 646 "of length 3. The allowed range is [0, 7].", 647 ret_code=2, 648 ) 649 650 def test_efuse_is_bitcount_given_increase_over_max(self): 651 self.espefuse_py("burn_efuse SPI_BOOT_CRYPT_CNT") 652 self.espefuse_py("burn_efuse SPI_BOOT_CRYPT_CNT") 653 self.espefuse_py("burn_efuse SPI_BOOT_CRYPT_CNT") 654 self.espefuse_py( 655 "burn_efuse SPI_BOOT_CRYPT_CNT", 656 check_msg="A fatal error occurred: " 657 "15 is too large an unsigned integer for a bitstring " 658 "of length 3. The allowed range is [0, 7].", 659 ret_code=2, 660 ) 661 662 663class TestBurnEfuseCommands(EfuseTestCase): 664 @pytest.mark.skipif( 665 arg_chip != "esp32", 666 reason="IO pins 30 & 31 cannot be set for SPI flash only on esp32", 667 ) 668 def test_set_spi_flash_pin_efuses(self): 669 self.espefuse_py( 670 "burn_efuse SPI_PAD_CONFIG_HD 30", 671 check_msg="A fatal error occurred: " 672 "IO pins 30 & 31 cannot be set for SPI flash. 0-29, 32 & 33 only.", 673 ret_code=2, 674 ) 675 self.espefuse_py( 676 "burn_efuse SPI_PAD_CONFIG_Q 0x23", 677 check_msg="A fatal error occurred: " 678 "IO pin 35 cannot be set for SPI flash. 0-29, 32 & 33 only.", 679 ret_code=2, 680 ) 681 output = self.espefuse_py("burn_efuse SPI_PAD_CONFIG_CS0 33") 682 assert "(Override SD_CMD pad (GPIO11/SPICS0)) 0b00000 -> 0b11111" in output 683 assert "BURN BLOCK0 - OK (all write block bits are set)" in output 684 685 @pytest.mark.skipif( 686 arg_chip == "esp32p4", reason="No Custom MAC Address defined yet" 687 ) 688 def test_burn_mac_custom_efuse(self): 689 crc_msg = "(OK)" 690 self.espefuse_py("burn_efuse -h") 691 if arg_chip == "esp32": 692 self.espefuse_py( 693 "burn_efuse MAC AA:CD:EF:01:02:03", 694 check_msg="Writing Factory MAC address is not supported", 695 ret_code=2, 696 ) 697 self.espefuse_py("burn_efuse MAC_VERSION 1") 698 crc_msg = "(CRC 0x56 OK)" 699 if arg_chip == "esp32c2": 700 self.espefuse_py("burn_efuse CUSTOM_MAC_USED 1") 701 self.espefuse_py("burn_efuse -h") 702 self.espefuse_py( 703 "burn_efuse CUSTOM_MAC AB:CD:EF:01:02:03", 704 check_msg="A fatal error occurred: Custom MAC must be a unicast MAC!", 705 ret_code=2, 706 ) 707 self.espefuse_py("burn_efuse CUSTOM_MAC AA:CD:EF:01:02:03") 708 self.espefuse_py("get_custom_mac", check_msg=f"aa:cd:ef:01:02:03 {crc_msg}") 709 710 def test_burn_efuse(self): 711 self.espefuse_py("burn_efuse -h") 712 if arg_chip == "esp32": 713 self.espefuse_py( 714 "burn_efuse \ 715 CHIP_VER_REV2 1 \ 716 DISABLE_DL_ENCRYPT 1 \ 717 CONSOLE_DEBUG_DISABLE 1" 718 ) 719 blk1 = "BLOCK1" 720 blk2 = "BLOCK2" 721 elif arg_chip == "esp32c2": 722 self.espefuse_py( 723 "burn_efuse \ 724 XTS_KEY_LENGTH_256 1 \ 725 UART_PRINT_CONTROL 1 \ 726 FORCE_SEND_RESUME 1" 727 ) 728 blk1 = "BLOCK_KEY0" 729 blk2 = None 730 else: 731 self.espefuse_py( 732 "burn_efuse \ 733 SECURE_BOOT_EN 1 \ 734 UART_PRINT_CONTROL 1" 735 ) 736 if arg_chip not in ["esp32c5", "esp32c5beta3", "esp32c61"]: 737 # chips having the OPTIONAL_UNIQUE_ID field 738 self.espefuse_py( 739 "burn_efuse \ 740 OPTIONAL_UNIQUE_ID 0x2328ad5ac9145f698f843a26d6eae168", 741 check_msg="-> 0x2328ad5ac9145f698f843a26d6eae168", 742 ) 743 output = self.espefuse_py("summary -d") 744 assert ( 745 "read_regs: d6eae168 8f843a26 c9145f69 2328ad5a " 746 "00000000 00000000 00000000 00000000" 747 ) in output 748 assert "= 68 e1 ea d6 26 3a 84 8f 69 5f 14 c9 5a ad 28 23 R/W" in output 749 self.espefuse_py( 750 "burn_bit BLOCK_SYS_DATA 1", 751 check_msg="Burn into BLOCK_SYS_DATA is forbidden " 752 "(RS coding scheme does not allow this).", 753 ret_code=2, 754 ) 755 blk1 = "BLOCK_KEY1" 756 blk2 = "BLOCK_KEY2" 757 output = self.espefuse_py( 758 f"burn_efuse {blk1}" 759 + " 0x00010203040506070809111111111111111111111111111111110000112233FF" 760 ) 761 assert ( 762 "-> 0x00010203040506070809111111111111111111111111111111110000112233ff" 763 in output 764 ) 765 output = self.espefuse_py("summary -d") 766 assert ( 767 "read_regs: 112233ff 11110000 11111111 11111111 " 768 "11111111 08091111 04050607 00010203" 769 ) in output 770 assert ( 771 "= ff 33 22 11 00 00 11 11 11 11 11 11 11 11 11 11 " 772 "11 11 11 11 11 11 09 08 07 06 05 04 03 02 01 00 R/W" 773 ) in output 774 775 if blk2 is not None: 776 output = self.espefuse_py( 777 f"burn_efuse {blk2}" 778 + " 00010203040506070809111111111111111111111111111111110000112233FF" 779 ) 780 assert ( 781 "-> 0xff33221100001111111111111111111111111111111109080706050403020100" 782 in output 783 ) 784 output = self.espefuse_py("summary -d") 785 assert ( 786 "read_regs: 03020100 07060504 11110908 11111111 " 787 "11111111 11111111 00001111 ff332211" 788 ) in output 789 assert ( 790 "= 00 01 02 03 04 05 06 07 08 09 11 11 11 11 11 11 " 791 "11 11 11 11 11 11 11 11 11 11 00 00 11 22 33 ff R/W" 792 ) in output 793 794 @pytest.mark.skipif( 795 arg_chip != "esp32", reason="3/4 coding scheme is only in esp32" 796 ) 797 def test_burn_efuse_with_34_coding_scheme(self): 798 self._set_34_coding_scheme() 799 self.espefuse_py("burn_efuse BLK3_PART_RESERVE 1") 800 self.espefuse_py("burn_efuse ADC1_TP_LOW 50") 801 self.espefuse_py( 802 "burn_efuse ADC1_TP_HIGH 55", 803 check_msg="Burn into BLOCK3 is forbidden " 804 "(3/4 coding scheme does not allow this)", 805 ret_code=2, 806 ) 807 808 @pytest.mark.skipif( 809 arg_chip != "esp32", reason="3/4 coding scheme is only in esp32" 810 ) 811 def test_burn_efuse_with_34_coding_scheme2(self): 812 self._set_34_coding_scheme() 813 self.espefuse_py("burn_efuse BLK3_PART_RESERVE 1") 814 self.espefuse_py( 815 "burn_efuse \ 816 ADC1_TP_LOW 50 \ 817 ADC1_TP_HIGH 55 \ 818 ADC2_TP_LOW 40 \ 819 ADC2_TP_HIGH 45" 820 ) 821 822 @pytest.mark.skipif( 823 arg_chip != "esp32s3", 824 reason="Currently S3 only has this efuse incompatibility check", 825 ) 826 def test_burn_efuse_incompatibility_check(self): 827 self.espefuse_py( 828 "burn_efuse DIS_USB_JTAG 1 DIS_USB_SERIAL_JTAG 1", 829 check_msg="Incompatible eFuse settings detected, abort", 830 ret_code=2, 831 ) 832 self.espefuse_py("burn_efuse DIS_USB_JTAG 1") 833 self.espefuse_py( 834 "burn_efuse DIS_USB_SERIAL_JTAG 1", 835 check_msg="Incompatible eFuse settings detected, abort", 836 ret_code=2, 837 ) 838 self.espefuse_py("burn_efuse DIS_USB_SERIAL_JTAG 1 --force") 839 840 841class TestBurnKeyCommands(EfuseTestCase): 842 @pytest.mark.skipif(arg_chip != "esp32", reason="ESP32-only") 843 def test_burn_key_3_key_blocks(self): 844 self.espefuse_py("burn_key -h") 845 self.espefuse_py( 846 f"burn_key BLOCK1 {IMAGES_DIR}/192bit", 847 check_msg="A fatal error occurred: Incorrect key file size 24. " 848 "Key file must be 32 bytes (256 bits) of raw binary key data.", 849 ret_code=2, 850 ) 851 self.espefuse_py( 852 f"burn_key \ 853 BLOCK1 {IMAGES_DIR}/256bit \ 854 BLOCK2 {IMAGES_DIR}/256bit_1 \ 855 BLOCK3 {IMAGES_DIR}/256bit_2 --no-protect-key" 856 ) 857 output = self.espefuse_py("summary -d") 858 self.check_data_block_in_log(output, f"{IMAGES_DIR}/256bit") 859 self.check_data_block_in_log(output, f"{IMAGES_DIR}/256bit_1") 860 self.check_data_block_in_log(output, f"{IMAGES_DIR}/256bit_2") 861 862 self.espefuse_py( 863 f"burn_key \ 864 BLOCK1 {IMAGES_DIR}/256bit \ 865 BLOCK2 {IMAGES_DIR}/256bit_1 \ 866 BLOCK3 {IMAGES_DIR}/256bit_2" 867 ) 868 output = self.espefuse_py("summary -d") 869 self.check_data_block_in_log(output, f"{IMAGES_DIR}/256bit") 870 self.check_data_block_in_log(output, f"{IMAGES_DIR}/256bit_1") 871 self.check_data_block_in_log(output, f"{IMAGES_DIR}/256bit_2") 872 873 @pytest.mark.skipif(arg_chip != "esp32c2", reason="ESP32-C2-only") 874 def test_burn_key_1_key_block(self): 875 self.espefuse_py("burn_key -h") 876 self.espefuse_py( 877 f"burn_key BLOCK_KEY0 {IMAGES_DIR}/128bit XTS_AES_128_KEY", 878 check_msg="A fatal error occurred: Incorrect key file size 16. " 879 "Key file must be 32 bytes (256 bits) of raw binary key data.", 880 ret_code=2, 881 ) 882 self.espefuse_py( 883 f"burn_key BLOCK_KEY0 {IMAGES_DIR}/256bit XTS_AES_128_KEY --no-read-protect" 884 ) 885 output = self.espefuse_py("summary -d") 886 self.check_data_block_in_log(output, f"{IMAGES_DIR}/256bit", reverse_order=True) 887 888 self.espefuse_py(f"burn_key BLOCK_KEY0 {IMAGES_DIR}/256bit XTS_AES_128_KEY") 889 output = self.espefuse_py("summary -d") 890 assert ( 891 "[3 ] read_regs: 00000000 00000000 00000000 00000000 " 892 "00000000 00000000 00000000 00000000" 893 ) in output 894 895 assert ( 896 "= ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? " 897 "?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? -/-" 898 ) in output 899 900 @pytest.mark.skipif(arg_chip != "esp32c2", reason="ESP32-C2-only") 901 def test_burn_key_one_key_block_with_fe_and_sb_keys(self): 902 self.espefuse_py("burn_key -h") 903 self.espefuse_py( 904 f"burn_key BLOCK_KEY0 {IMAGES_DIR}/256bit XTS_AES_128_KEY \ 905 BLOCK_KEY0 {IMAGES_DIR}/128bit_key SECURE_BOOT_DIGEST", 906 check_msg="A fatal error occurred: These keypurposes are incompatible " 907 "['XTS_AES_128_KEY', 'SECURE_BOOT_DIGEST']", 908 ret_code=2, 909 ) 910 self.espefuse_py( 911 f"burn_key BLOCK_KEY0 {IMAGES_DIR}/128bit_key " 912 f"XTS_AES_128_KEY_DERIVED_FROM_128_EFUSE_BITS " 913 f"BLOCK_KEY0 {IMAGES_DIR}/128bit_key SECURE_BOOT_DIGEST --no-read-protect" 914 ) 915 output = self.espefuse_py("summary -d") 916 assert ( 917 "[3 ] read_regs: 0c0d0e0f 08090a0b 04050607 00010203 " 918 "03020100 07060504 0b0a0908 0f0e0d0c" 919 ) in output 920 921 self.espefuse_py( 922 f"burn_key BLOCK_KEY0 {IMAGES_DIR}/128bit_key " 923 "XTS_AES_128_KEY_DERIVED_FROM_128_EFUSE_BITS " 924 f"BLOCK_KEY0 {IMAGES_DIR}/128bit_key SECURE_BOOT_DIGEST" 925 ) 926 output = self.espefuse_py("summary -d") 927 assert ( 928 "[3 ] read_regs: 00000000 00000000 00000000 00000000 " 929 "03020100 07060504 0b0a0908 0f0e0d0c" 930 ) in output 931 932 assert ( 933 "= ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? " 934 "00 01 02 03 04 05 06 07 08 09 0a 0b 0c 0d 0e 0f -/-" 935 ) in output 936 assert "= ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? -/-" in output 937 assert "= 00 01 02 03 04 05 06 07 08 09 0a 0b 0c 0d 0e 0f R/-" in output 938 939 @pytest.mark.skipif( 940 arg_chip 941 not in [ 942 "esp32s2", 943 "esp32s3", 944 "esp32s3beta1", 945 "esp32c3", 946 "esp32h2beta1", 947 "esp32c6", 948 "esp32h2", 949 "esp32p4", 950 "esp32c5", 951 "esp32c5beta3", 952 "esp32c61", 953 ], 954 reason="Only chips with 6 keys", 955 ) 956 def test_burn_key_with_6_keys(self): 957 cmd = f"burn_key \ 958 BLOCK_KEY0 {IMAGES_DIR}/256bit XTS_AES_256_KEY_1 \ 959 BLOCK_KEY1 {IMAGES_DIR}/256bit_1 XTS_AES_256_KEY_2 \ 960 BLOCK_KEY2 {IMAGES_DIR}/256bit_2 XTS_AES_128_KEY" 961 if arg_chip in [ 962 "esp32c3", 963 "esp32c6", 964 "esp32h2", 965 "esp32h2beta1", 966 "esp32c5", 967 "esp32c5beta3", 968 ]: 969 cmd = cmd.replace("XTS_AES_256_KEY_1", "XTS_AES_128_KEY") 970 cmd = cmd.replace("XTS_AES_256_KEY_2", "XTS_AES_128_KEY") 971 self.espefuse_py(cmd + " --no-read-protect --no-write-protect") 972 output = self.espefuse_py("summary -d") 973 self.check_data_block_in_log(output, f"{IMAGES_DIR}/256bit", reverse_order=True) 974 self.check_data_block_in_log( 975 output, f"{IMAGES_DIR}/256bit_1", reverse_order=True 976 ) 977 self.check_data_block_in_log( 978 output, f"{IMAGES_DIR}/256bit_2", reverse_order=True 979 ) 980 981 self.espefuse_py(cmd) 982 output = self.espefuse_py("summary -d") 983 assert ( 984 "[4 ] read_regs: 00000000 00000000 00000000 00000000 " 985 "00000000 00000000 00000000 00000000" 986 ) in output 987 assert ( 988 "[5 ] read_regs: 00000000 00000000 00000000 00000000 " 989 "00000000 00000000 00000000 00000000" 990 ) in output 991 assert ( 992 "[6 ] read_regs: 00000000 00000000 00000000 00000000 " 993 "00000000 00000000 00000000 00000000" 994 ) in output 995 996 self.espefuse_py( 997 f"burn_key \ 998 BLOCK_KEY3 {IMAGES_DIR}/256bit SECURE_BOOT_DIGEST0 \ 999 BLOCK_KEY4 {IMAGES_DIR}/256bit_1 SECURE_BOOT_DIGEST1 \ 1000 BLOCK_KEY5 {IMAGES_DIR}/256bit_2 SECURE_BOOT_DIGEST2" 1001 ) 1002 output = self.espefuse_py("summary -d") 1003 self.check_data_block_in_log(output, f"{IMAGES_DIR}/256bit") 1004 self.check_data_block_in_log(output, f"{IMAGES_DIR}/256bit_1") 1005 self.check_data_block_in_log(output, f"{IMAGES_DIR}/256bit_2") 1006 1007 @pytest.mark.skipif( 1008 arg_chip != "esp32", reason="3/4 coding scheme is only in esp32" 1009 ) 1010 def test_burn_key_with_34_coding_scheme(self): 1011 self._set_34_coding_scheme() 1012 self.espefuse_py( 1013 f"burn_key BLOCK1 {IMAGES_DIR}/256bit", 1014 check_msg="A fatal error occurred: Incorrect key file size 32. " 1015 "Key file must be 24 bytes (192 bits) of raw binary key data.", 1016 ret_code=2, 1017 ) 1018 self.espefuse_py( 1019 f"burn_key \ 1020 BLOCK1 {IMAGES_DIR}/192bit \ 1021 BLOCK2 {IMAGES_DIR}/192bit_1 \ 1022 BLOCK3 {IMAGES_DIR}/192bit_2 --no-protect-key" 1023 ) 1024 output = self.espefuse_py("summary -d") 1025 self.check_data_block_in_log(output, f"{IMAGES_DIR}/192bit") 1026 self.check_data_block_in_log(output, f"{IMAGES_DIR}/192bit_1") 1027 self.check_data_block_in_log(output, f"{IMAGES_DIR}/192bit_2") 1028 1029 self.espefuse_py( 1030 f"burn_key \ 1031 BLOCK1 {IMAGES_DIR}/192bit \ 1032 BLOCK2 {IMAGES_DIR}/192bit_1 \ 1033 BLOCK3 {IMAGES_DIR}/192bit_2" 1034 ) 1035 output = self.espefuse_py("summary -d") 1036 self.check_data_block_in_log(output, f"{IMAGES_DIR}/192bit") 1037 self.check_data_block_in_log(output, f"{IMAGES_DIR}/192bit_1") 1038 self.check_data_block_in_log(output, f"{IMAGES_DIR}/192bit_2") 1039 1040 @pytest.mark.skipif( 1041 arg_chip not in ["esp32s2", "esp32s3", "esp32p4", "esp32c61"], 1042 reason="512 bit keys are only supported on ESP32-S2, S3, P4, C61", 1043 ) 1044 def test_burn_key_512bit(self): 1045 self.espefuse_py( 1046 f"burn_key \ 1047 BLOCK_KEY0 {IMAGES_DIR}/256bit_1_256bit_2_combined \ 1048 XTS_AES_256_KEY --no-read-protect --no-write-protect" 1049 ) 1050 output = self.espefuse_py("summary -d") 1051 self.check_data_block_in_log( 1052 output, f"{IMAGES_DIR}/256bit_1", reverse_order=True 1053 ) 1054 self.check_data_block_in_log( 1055 output, f"{IMAGES_DIR}/256bit_2", reverse_order=True 1056 ) 1057 1058 @pytest.mark.skipif( 1059 arg_chip not in ["esp32s2", "esp32s3", "esp32p4", "esp32c61"], 1060 reason="512 bit keys are only supported on ESP32-S2, S3, P4, C61", 1061 ) 1062 def test_burn_key_512bit_non_consecutive_blocks(self): 1063 # Burn efuses separately to test different kinds 1064 # of "key used" detection criteria 1065 self.espefuse_py( 1066 f"burn_key \ 1067 BLOCK_KEY2 {IMAGES_DIR}/256bit XTS_AES_128_KEY" 1068 ) 1069 self.espefuse_py( 1070 f"burn_key \ 1071 BLOCK_KEY4 {IMAGES_DIR}/256bit SECURE_BOOT_DIGEST0" 1072 ) 1073 self.espefuse_py( 1074 f"burn_key \ 1075 BLOCK_KEY1 {IMAGES_DIR}/256bit_1_256bit_2_combined \ 1076 XTS_AES_256_KEY --no-read-protect --no-write-protect" 1077 ) 1078 self.espefuse_py( 1079 f"burn_key \ 1080 BLOCK_KEY5 {IMAGES_DIR}/256bit USER --no-read-protect --no-write-protect" 1081 ) 1082 1083 # Second half of key should burn to first available key block (BLOCK_KEY5) 1084 output = self.espefuse_py("summary -d") 1085 self.check_data_block_in_log( 1086 output, f"{IMAGES_DIR}/256bit_1", reverse_order=True 1087 ) 1088 self.check_data_block_in_log( 1089 output, f"{IMAGES_DIR}/256bit_2", reverse_order=True 1090 ) 1091 1092 assert ( 1093 "[5 ] read_regs: bcbd11bf b8b9babb b4b5b6b7 " 1094 "b0b1b2b3 acadaeaf a8a9aaab a4a5a6a7 11a1a2a3" 1095 ) in output 1096 assert ( 1097 "[7 ] read_regs: bcbd22bf b8b9babb b4b5b6b7 " 1098 "b0b1b2b3 acadaeaf a8a9aaab a4a5a6a7 22a1a2a3" 1099 ) in output 1100 1101 @pytest.mark.skipif( 1102 arg_chip not in ["esp32s2", "esp32s3", "esp32p4", "esp32c61"], 1103 reason="512 bit keys are only supported on ESP32-S2, S3, P4, C61", 1104 ) 1105 def test_burn_key_512bit_non_consecutive_blocks_loop_around(self): 1106 self.espefuse_py( 1107 f"burn_key \ 1108 BLOCK_KEY2 {IMAGES_DIR}/256bit XTS_AES_128_KEY \ 1109 BLOCK_KEY3 {IMAGES_DIR}/256bit USER \ 1110 BLOCK_KEY4 {IMAGES_DIR}/256bit SECURE_BOOT_DIGEST0 \ 1111 BLOCK_KEY5 {IMAGES_DIR}/256bit SECURE_BOOT_DIGEST1 \ 1112 BLOCK_KEY1 {IMAGES_DIR}/256bit_1_256bit_2_combined \ 1113 XTS_AES_256_KEY --no-read-protect --no-write-protect" 1114 ) 1115 1116 # Second half of key should burn to first available key block (BLOCK_KEY0) 1117 output = self.espefuse_py("summary -d") 1118 self.check_data_block_in_log( 1119 output, f"{IMAGES_DIR}/256bit_1", reverse_order=True 1120 ) 1121 self.check_data_block_in_log( 1122 output, f"{IMAGES_DIR}/256bit_2", reverse_order=True 1123 ) 1124 1125 assert ( 1126 "[5 ] read_regs: bcbd11bf b8b9babb b4b5b6b7 b0b1b2b3 " 1127 "acadaeaf a8a9aaab a4a5a6a7 11a1a2a3" 1128 ) in output 1129 assert ( 1130 "[4 ] read_regs: bcbd22bf b8b9babb b4b5b6b7 b0b1b2b3 " 1131 "acadaeaf a8a9aaab a4a5a6a7 22a1a2a3" 1132 ) in output 1133 1134 @pytest.mark.skipif( 1135 arg_chip not in ["esp32h2", "esp32c5", "esp32c5beta3", "esp32c61", "esp32p4"], 1136 reason="These chips support ECDSA_KEY", 1137 ) 1138 def test_burn_key_ecdsa_key(self): 1139 self.espefuse_py( 1140 f"burn_key \ 1141 BLOCK_KEY0 {S_IMAGES_DIR}/ecdsa192_secure_boot_signing_key_v2.pem \ 1142 ECDSA_KEY \ 1143 BLOCK_KEY1 {S_IMAGES_DIR}/ecdsa256_secure_boot_signing_key_v2.pem \ 1144 ECDSA_KEY" 1145 ) 1146 output = self.espefuse_py("summary -d") 1147 assert 2 == output.count( 1148 "= ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? " 1149 "?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? -/-" 1150 ) 1151 assert ( 1152 "[4 ] read_regs: 00000000 00000000 00000000 00000000 " 1153 "00000000 00000000 00000000 00000000" 1154 ) in output 1155 assert ( 1156 "[5 ] read_regs: 00000000 00000000 00000000 00000000 " 1157 "00000000 00000000 00000000 00000000" 1158 ) in output 1159 1160 @pytest.mark.skipif( 1161 arg_chip not in ["esp32h2", "esp32c5", "esp32c5beta3", "esp32c61", "esp32p4"], 1162 reason="These chips support ECDSA_KEY", 1163 ) 1164 def test_burn_key_ecdsa_key_check_byte_order(self): 1165 self.espefuse_py( 1166 f"burn_key \ 1167 BLOCK_KEY0 {S_IMAGES_DIR}/ecdsa192_secure_boot_signing_key_v2.pem \ 1168 ECDSA_KEY \ 1169 BLOCK_KEY1 {S_IMAGES_DIR}/ecdsa256_secure_boot_signing_key_v2.pem \ 1170 ECDSA_KEY \ 1171 --no-read-protect" 1172 ) 1173 output = self.espefuse_py("summary -d") 1174 assert ( 1175 "= c8 c4 5d 62 9e 05 05 bd cb 04 a4 7c 06 f5 86 14 " 1176 "cb 23 81 23 95 b7 71 4f 00 00 00 00 00 00 00 00 R/-" 1177 ) in output 1178 assert ( 1179 "= fc 6b ec 75 64 37 7d 3b 88 8d 34 05 ed 91 06 1b " 1180 "38 c2 50 84 7a 08 9d c3 66 6a 06 90 23 8b 54 b4 R/-" 1181 ) in output 1182 assert ( 1183 "[4 ] read_regs: 625dc4c8 bd05059e 7ca404cb 1486f506 " 1184 "238123cb 4f71b795 00000000 00000000" 1185 ) in output 1186 assert ( 1187 "[5 ] read_regs: 75ec6bfc 3b7d3764 05348d88 1b0691ed " 1188 "8450c238 c39d087a 90066a66 b4548b23" 1189 ) in output 1190 1191 1192class TestBurnBlockDataCommands(EfuseTestCase): 1193 def test_burn_block_data_check_args(self): 1194 self.espefuse_py("burn_block_data -h") 1195 blk0 = "BLOCK0" 1196 blk1 = "BLOCK1" 1197 self.espefuse_py( 1198 f"burn_block_data {blk0} {IMAGES_DIR}/224bit {blk1}", 1199 check_msg="A fatal error occurred: " 1200 "The number of block_name (2) and datafile (1) should be the same.", 1201 ret_code=2, 1202 ) 1203 1204 @pytest.mark.skipif(arg_chip != "esp32", reason="ESP32-only") 1205 def test_burn_block_data_with_3_key_blocks(self): 1206 self.espefuse_py( 1207 f"burn_block_data \ 1208 BLOCK0 {IMAGES_DIR}/224bit \ 1209 BLOCK3 {IMAGES_DIR}/256bit" 1210 ) 1211 output = self.espefuse_py("summary -d") 1212 assert ( 1213 "[3 ] read_regs: a3a2a1a0 a7a6a5a4 abaaa9a8 afaeadac " 1214 "b3b2b1b0 b7b6b5b4 bbbab9b8 bfbebdbc" 1215 ) in output 1216 self.check_data_block_in_log(output, f"{IMAGES_DIR}/256bit") 1217 1218 self.espefuse_py( 1219 f"burn_block_data \ 1220 BLOCK2 {IMAGES_DIR}/256bit_1" 1221 ) 1222 self.check_data_block_in_log( 1223 self.espefuse_py("summary -d"), f"{IMAGES_DIR}/256bit_1" 1224 ) 1225 1226 self.espefuse_py( 1227 f"burn_block_data \ 1228 BLOCK1 {IMAGES_DIR}/256bit_2" 1229 ) 1230 self.check_data_block_in_log( 1231 self.espefuse_py("summary -d"), f"{IMAGES_DIR}/256bit_2" 1232 ) 1233 1234 @pytest.mark.skipif(arg_chip != "esp32c2", reason="ESP32-C2-only") 1235 def test_burn_block_data_with_1_key_block(self): 1236 self.espefuse_py( 1237 f"burn_block_data \ 1238 BLOCK0 {IMAGES_DIR}/64bit \ 1239 BLOCK1 {IMAGES_DIR}/96bit \ 1240 BLOCK2 {IMAGES_DIR}/256bit \ 1241 BLOCK3 {IMAGES_DIR}/256bit" 1242 ) 1243 output = self.espefuse_py("summary -d") 1244 assert "[0 ] read_regs: 00000001 0000000c" in output 1245 assert "[1 ] read_regs: 03020100 07060504 000a0908" in output 1246 assert ( 1247 "[2 ] read_regs: a3a2a1a0 a7a6a5a4 abaaa9a8 afaeadac " 1248 "b3b2b1b0 b7b6b5b4 bbbab9b8 bfbebdbc" 1249 ) in output 1250 assert ( 1251 "[3 ] read_regs: a3a2a1a0 a7a6a5a4 abaaa9a8 afaeadac " 1252 "b3b2b1b0 b7b6b5b4 bbbab9b8 bfbebdbc" 1253 ) in output 1254 1255 @pytest.mark.skipif( 1256 arg_chip 1257 not in [ 1258 "esp32s2", 1259 "esp32s3", 1260 "esp32s3beta1", 1261 "esp32c3", 1262 "esp32h2beta1", 1263 "esp32c6", 1264 "esp32h2", 1265 "esp32p4", 1266 "esp32c5", 1267 "esp32c5beta3", 1268 "esp32c61", 1269 ], 1270 reason="Only chip with 6 keys", 1271 ) 1272 def test_burn_block_data_with_6_keys(self): 1273 self.espefuse_py( 1274 f"burn_block_data \ 1275 BLOCK0 {IMAGES_DIR}/192bit \ 1276 BLOCK3 {IMAGES_DIR}/256bit" 1277 ) 1278 output = self.espefuse_py("summary -d") 1279 assert ( 1280 "[0 ] read_regs: 00000000 07060500 00000908 00000000 13000000 00161514" 1281 in output 1282 ) 1283 assert ( 1284 "[3 ] read_regs: a3a2a1a0 a7a6a5a4 abaaa9a8 afaeadac " 1285 "b3b2b1b0 b7b6b5b4 bbbab9b8 bfbebdbc" 1286 ) in output 1287 self.check_data_block_in_log(output, f"{IMAGES_DIR}/256bit") 1288 1289 self.espefuse_py( 1290 f"burn_block_data \ 1291 BLOCK10 {IMAGES_DIR}/256bit_1" 1292 ) 1293 self.check_data_block_in_log( 1294 self.espefuse_py("summary -d"), f"{IMAGES_DIR}/256bit_1" 1295 ) 1296 1297 self.espefuse_py( 1298 f"burn_block_data \ 1299 BLOCK1 {IMAGES_DIR}/192bit \ 1300 BLOCK5 {IMAGES_DIR}/256bit_1 \ 1301 BLOCK6 {IMAGES_DIR}/256bit_2" 1302 ) 1303 output = self.espefuse_py("summary -d") 1304 assert ( 1305 "[1 ] read_regs: 00000000 07060500 00000908 00000000 13000000 00161514" 1306 in output 1307 ) 1308 self.check_data_block_in_log(output, f"{IMAGES_DIR}/256bit") 1309 self.check_data_block_in_log(output, f"{IMAGES_DIR}/256bit_1", 2) 1310 self.check_data_block_in_log(output, f"{IMAGES_DIR}/256bit_2") 1311 1312 def test_burn_block_data_check_errors(self): 1313 self.espefuse_py( 1314 f"burn_block_data \ 1315 BLOCK2 {IMAGES_DIR}/192bit \ 1316 BLOCK2 {IMAGES_DIR}/192bit_1", 1317 check_msg="A fatal error occurred: Found repeated", 1318 ret_code=2, 1319 ) 1320 self.espefuse_py( 1321 f"burn_block_data \ 1322 BLOCK2 {IMAGES_DIR}/192bit \ 1323 BLOCK3 {IMAGES_DIR}/192bit_1 \ 1324 --offset 4", 1325 check_msg="A fatal error occurred: " 1326 "The 'offset' option is not applicable when a few blocks are passed.", 1327 ret_code=2, 1328 ) 1329 self.espefuse_py( 1330 f"burn_block_data BLOCK0 {IMAGES_DIR}/192bit --offset 33", 1331 check_msg="A fatal error occurred: Invalid offset: the block0 only holds", 1332 ret_code=2, 1333 ) 1334 self.espefuse_py( 1335 f"burn_block_data BLOCK0 {IMAGES_DIR}/256bit --offset 4", 1336 check_msg="A fatal error occurred: Data does not fit:", 1337 ret_code=2, 1338 ) 1339 1340 @pytest.mark.skipif(arg_chip != "esp32", reason="ESP32-only") 1341 def test_burn_block_data_with_offset_for_3_key_blocks(self): 1342 offset = 1 1343 self.espefuse_py( 1344 f"burn_block_data --offset {offset} BLOCK0 {IMAGES_DIR}/192bit" 1345 ) 1346 1347 offset = 4 1348 self.espefuse_py( 1349 f"burn_block_data --offset {offset} BLOCK1 {IMAGES_DIR}/192bit_1" 1350 ) 1351 self.check_data_block_in_log( 1352 self.espefuse_py("summary -d"), f"{IMAGES_DIR}/192bit_1", offset=offset 1353 ) 1354 1355 offset = 6 1356 self.espefuse_py( 1357 f"burn_block_data --offset {offset} BLOCK2 {IMAGES_DIR}/192bit_2" 1358 ) 1359 self.check_data_block_in_log( 1360 self.espefuse_py("summary -d"), f"{IMAGES_DIR}/192bit_2", offset=offset 1361 ) 1362 1363 offset = 8 1364 self.espefuse_py( 1365 f"burn_block_data --offset {offset} BLOCK3 {IMAGES_DIR}/192bit_2" 1366 ) 1367 self.check_data_block_in_log( 1368 self.espefuse_py("summary -d"), f"{IMAGES_DIR}/192bit_2", offset=offset 1369 ) 1370 1371 @pytest.mark.skipif(arg_chip != "esp32c2", reason="ESP32-C2-only") 1372 def test_burn_block_data_with_offset_1_key_block(self): 1373 offset = 4 1374 self.espefuse_py(f"burn_block_data --offset {offset} BLOCK1 {IMAGES_DIR}/92bit") 1375 output = self.espefuse_py("summary -d") 1376 assert "[1 ] read_regs: 00000000 03020100 00060504" in output 1377 1378 offset = 6 1379 self.espefuse_py( 1380 f"burn_block_data --offset {offset} BLOCK2 {IMAGES_DIR}/192bit_1" 1381 ) 1382 output = self.espefuse_py("summary -d") 1383 assert ( 1384 "[2 ] read_regs: 00000000 00110000 05000000 09080706 " 1385 "0d0c0b0a 11100f0e 15141312 00002116" 1386 ) in output 1387 1388 offset = 8 1389 self.espefuse_py( 1390 f"burn_block_data --offset {offset} BLOCK3 {IMAGES_DIR}/192bit_2" 1391 ) 1392 self.check_data_block_in_log( 1393 self.espefuse_py("summary -d"), f"{IMAGES_DIR}/192bit_2", offset=offset 1394 ) 1395 1396 @pytest.mark.skipif( 1397 arg_chip 1398 not in [ 1399 "esp32s2", 1400 "esp32s3", 1401 "esp32s3beta1", 1402 "esp32c3", 1403 "esp32h2beta1", 1404 "esp32c6", 1405 "esp32h2", 1406 "esp32p4", 1407 "esp32c5", 1408 "esp32c5beta3", 1409 "esp32c61", 1410 ], 1411 reason="Only chips with 6 keys", 1412 ) 1413 def test_burn_block_data_with_offset_6_keys(self): 1414 offset = 4 1415 self.espefuse_py( 1416 f"burn_block_data --offset {offset} BLOCK_KEY0 {IMAGES_DIR}/192bit_1" 1417 ) 1418 self.check_data_block_in_log( 1419 self.espefuse_py("summary -d"), f"{IMAGES_DIR}/192bit_1", offset=offset 1420 ) 1421 1422 offset = 6 1423 self.espefuse_py( 1424 f"burn_block_data --offset {offset} BLOCK_KEY1 {IMAGES_DIR}/192bit_2" 1425 ) 1426 self.check_data_block_in_log( 1427 self.espefuse_py("summary -d"), f"{IMAGES_DIR}/192bit_2", offset=offset 1428 ) 1429 1430 offset = 8 1431 self.espefuse_py( 1432 f"burn_block_data --offset {offset} BLOCK_KEY2 {IMAGES_DIR}/192bit_2" 1433 ) 1434 self.check_data_block_in_log( 1435 self.espefuse_py("summary -d"), f"{IMAGES_DIR}/192bit_2", offset=offset 1436 ) 1437 1438 @pytest.mark.skipif( 1439 arg_chip != "esp32", reason="3/4 coding scheme is only in esp32" 1440 ) 1441 def test_burn_block_data_with_34_coding_scheme(self): 1442 self._set_34_coding_scheme() 1443 self.espefuse_py( 1444 f"burn_block_data BLOCK1 {IMAGES_DIR}/256bit", 1445 check_msg="A fatal error occurred: Data does not fit: " 1446 "the block1 size is 24 bytes, data file is 32 bytes, offset 0", 1447 ret_code=2, 1448 ) 1449 1450 self.espefuse_py( 1451 f"burn_block_data \ 1452 BLOCK1 {IMAGES_DIR}/192bit \ 1453 BLOCK2 {IMAGES_DIR}/192bit_1 \ 1454 BLOCK3 {IMAGES_DIR}/192bit_2" 1455 ) 1456 output = self.espefuse_py("summary -d") 1457 self.check_data_block_in_log(output, f"{IMAGES_DIR}/192bit") 1458 self.check_data_block_in_log(output, f"{IMAGES_DIR}/192bit_1") 1459 self.check_data_block_in_log(output, f"{IMAGES_DIR}/192bit_2") 1460 1461 @pytest.mark.skipif( 1462 arg_chip != "esp32", reason="3/4 coding scheme is only in esp32" 1463 ) 1464 def test_burn_block_data_with_34_coding_scheme_and_offset(self): 1465 self._set_34_coding_scheme() 1466 1467 offset = 4 1468 self.espefuse_py( 1469 f"burn_block_data --offset {offset} BLOCK1 {IMAGES_DIR}/128bit" 1470 ) 1471 self.check_data_block_in_log( 1472 self.espefuse_py("summary -d"), f"{IMAGES_DIR}/128bit", offset=offset 1473 ) 1474 1475 offset = 6 1476 self.espefuse_py( 1477 f"burn_block_data --offset {offset} BLOCK2 {IMAGES_DIR}/128bit" 1478 ) 1479 self.check_data_block_in_log( 1480 self.espefuse_py("summary -d"), f"{IMAGES_DIR}/128bit", offset=offset 1481 ) 1482 1483 offset = 8 1484 self.espefuse_py( 1485 f"burn_block_data --offset {offset} BLOCK3 {IMAGES_DIR}/128bit" 1486 ) 1487 self.check_data_block_in_log( 1488 self.espefuse_py("summary -d"), f"{IMAGES_DIR}/128bit", offset=offset 1489 ) 1490 1491 1492@pytest.mark.skipif(arg_chip != "esp32", reason="ESP32-only, supports 2 key blocks") 1493class TestBurnKeyDigestCommandsEsp32(EfuseTestCase): 1494 def test_burn_key_digest(self): 1495 self.espefuse_py("burn_key_digest -h") 1496 esp = self.get_esptool() 1497 if esp.get_chip_revision() >= 300: 1498 self.espefuse_py( 1499 f"burn_key_digest {S_IMAGES_DIR}/rsa_secure_boot_signing_key.pem" 1500 ) 1501 output = self.espefuse_py("summary -d") 1502 assert ( 1503 " = cb 27 91 a3 71 b0 c0 32 2b f7 37 04 78 ba 09 62 " 1504 "22 4c ab 1c f2 28 78 79 e4 29 67 3e 7d a8 44 63 R/-" 1505 ) in output 1506 else: 1507 self.espefuse_py( 1508 f"burn_key_digest {S_IMAGES_DIR}/rsa_secure_boot_signing_key.pem", 1509 check_msg="Incorrect chip revision for Secure boot v2.", 1510 ret_code=2, 1511 ) 1512 1513 def test_burn_key_from_digest(self): 1514 # python espsecure.py digest_rsa_public_key 1515 # --keyfile test/{S_IMAGES_DIR}/rsa_secure_boot_signing_key.pem 1516 # -o {S_IMAGES_DIR}/rsa_public_key_digest.bin 1517 self.espefuse_py( 1518 f"burn_key \ 1519 BLOCK2 {S_IMAGES_DIR}/rsa_public_key_digest.bin --no-protect-key" 1520 ) 1521 output = self.espefuse_py("summary -d") 1522 assert 1 == output.count( 1523 " = cb 27 91 a3 71 b0 c0 32 2b f7 37 04 78 ba 09 62 " 1524 "22 4c ab 1c f2 28 78 79 e4 29 67 3e 7d a8 44 63 R/W" 1525 ) 1526 1527 def test_burn_key_digest_with_34_coding_scheme(self): 1528 self._set_34_coding_scheme() 1529 self.espefuse_py( 1530 f"burn_key_digest {S_IMAGES_DIR}/rsa_secure_boot_signing_key.pem", 1531 check_msg="burn_key_digest only works with 'None' coding scheme", 1532 ret_code=2, 1533 ) 1534 1535 1536@pytest.mark.skipif(arg_chip != "esp32c2", reason="ESP32-C2-only, supports 1 key block") 1537class TestBurnKeyDigestCommandsEsp32C2(EfuseTestCase): 1538 def test_burn_key_digest1(self): 1539 # python espsecure.py generate_signing_key --version 2 1540 # secure_images/ecdsa192_secure_boot_signing_key_v2.pem --scheme ecdsa192 1541 self.espefuse_py("burn_key_digest -h") 1542 self.espefuse_py( 1543 f"burn_key_digest {S_IMAGES_DIR}/ecdsa192_secure_boot_signing_key_v2.pem" 1544 ) 1545 output = self.espefuse_py("summary -d") 1546 assert " = 1e 3d 15 16 96 ca 7f 22 a6 e8 8b d5 27 a0 3b 3b R/-" in output 1547 assert ( 1548 " = 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 " 1549 "1e 3d 15 16 96 ca 7f 22 a6 e8 8b d5 27 a0 3b 3b R/-" 1550 ) in output 1551 1552 def test_burn_key_digest2(self): 1553 # python espsecure.py generate_signing_key --version 2 1554 # secure_images/ecdsa256_secure_boot_signing_key_v2.pem --scheme ecdsa256 1555 self.espefuse_py("burn_key_digest -h") 1556 self.espefuse_py( 1557 f"burn_key_digest {S_IMAGES_DIR}/ecdsa256_secure_boot_signing_key_v2.pem" 1558 ) 1559 output = self.espefuse_py("summary -d") 1560 assert " = bf 0f 6a f6 8b d3 6d 8b 53 b3 da a9 33 f6 0a 04 R/-" in output 1561 assert ( 1562 " = 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 " 1563 "bf 0f 6a f6 8b d3 6d 8b 53 b3 da a9 33 f6 0a 04 R/-" 1564 ) in output 1565 1566 def test_burn_key_from_digest1(self): 1567 # python espsecure.py digest_sbv2_public_key --keyfile 1568 # secure_images/ecdsa192_secure_boot_signing_key_v2.pem 1569 # -o secure_images/ecdsa192_public_key_digest_v2.bin 1570 self.espefuse_py( 1571 "burn_key BLOCK_KEY0 " 1572 f"{S_IMAGES_DIR}/ecdsa192_public_key_digest_v2.bin SECURE_BOOT_DIGEST" 1573 ) 1574 output = self.espefuse_py("summary -d") 1575 assert ( 1576 " = 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 " 1577 "1e 3d 15 16 96 ca 7f 22 a6 e8 8b d5 27 a0 3b 3b R/-" 1578 ) in output 1579 1580 def test_burn_key_from_digest2(self): 1581 # python espsecure.py digest_sbv2_public_key --keyfile 1582 # secure_images/ecdsa256_secure_boot_signing_key_v2.pem 1583 # -o secure_images/ecdsa256_public_key_digest_v2.bin 1584 self.espefuse_py( 1585 "burn_key BLOCK_KEY0 " 1586 f"{S_IMAGES_DIR}/ecdsa256_public_key_digest_v2.bin SECURE_BOOT_DIGEST" 1587 ) 1588 output = self.espefuse_py("summary -d") 1589 assert ( 1590 " = 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 " 1591 "bf 0f 6a f6 8b d3 6d 8b 53 b3 da a9 33 f6 0a 04 R/-" 1592 ) in output 1593 1594 1595@pytest.mark.skipif( 1596 arg_chip 1597 not in [ 1598 "esp32s2", 1599 "esp32s3", 1600 "esp32s3beta1", 1601 "esp32c3", 1602 "esp32h2beta1", 1603 "esp32c6", 1604 "esp32h2", 1605 "esp32p4", 1606 "esp32c5", 1607 "esp32c5beta3", 1608 "esp32c61", 1609 ], 1610 reason="Supports 6 key blocks", 1611) 1612class TestBurnKeyDigestCommands(EfuseTestCase): 1613 def test_burn_key_digest(self): 1614 self.espefuse_py("burn_key_digest -h") 1615 self.espefuse_py( 1616 f"burn_key_digest \ 1617 BLOCK_KEY0 \ 1618 {S_IMAGES_DIR}/rsa_secure_boot_signing_key.pem SECURE_BOOT_DIGEST0 \ 1619 BLOCK_KEY1 \ 1620 {S_IMAGES_DIR}/rsa_secure_boot_signing_key2.pem SECURE_BOOT_DIGEST1 \ 1621 BLOCK_KEY2 ", 1622 check_msg="A fatal error occurred: The number of blocks (3), " 1623 "datafile (2) and keypurpose (2) should be the same.", 1624 ret_code=2, 1625 ) 1626 self.espefuse_py( 1627 f"burn_key_digest \ 1628 BLOCK_KEY0 \ 1629 {S_IMAGES_DIR}/rsa_secure_boot_signing_key.pem SECURE_BOOT_DIGEST0 \ 1630 BLOCK_KEY1 \ 1631 {S_IMAGES_DIR}/rsa_secure_boot_signing_key2.pem SECURE_BOOT_DIGEST1 \ 1632 BLOCK_KEY2 \ 1633 {S_IMAGES_DIR}/rsa_secure_boot_signing_key2.pem SECURE_BOOT_DIGEST2" 1634 ) 1635 output = self.espefuse_py("summary -d") 1636 assert 1 == output.count( 1637 " = cb 27 91 a3 71 b0 c0 32 2b f7 37 04 78 ba 09 62 " 1638 "22 4c ab 1c f2 28 78 79 e4 29 67 3e 7d a8 44 63 R/-" 1639 ) 1640 assert 2 == output.count( 1641 " = 90 1a 74 09 23 8d 52 d4 cb f9 6f 56 3f b3 f4 29 " 1642 "6d ab d6 6a 33 f5 3b 15 ee cd 8c b3 e7 ec 45 d3 R/-" 1643 ) 1644 1645 def test_burn_key_from_digest(self): 1646 # python espsecure.py digest_rsa_public_key 1647 # --keyfile test/secure_images/rsa_secure_boot_signing_key.pem 1648 # -o secure_images/rsa_public_key_digest.bin 1649 self.espefuse_py( 1650 f"burn_key \ 1651 BLOCK_KEY0 {S_IMAGES_DIR}/rsa_public_key_digest.bin SECURE_BOOT_DIGEST0" 1652 ) 1653 output = self.espefuse_py("summary -d") 1654 assert 1 == output.count( 1655 " = cb 27 91 a3 71 b0 c0 32 2b f7 37 04 78 ba 09 62 " 1656 "22 4c ab 1c f2 28 78 79 e4 29 67 3e 7d a8 44 63 R/-" 1657 ) 1658 1659 self.espefuse_py( 1660 f"burn_key_digest \ 1661 BLOCK_KEY1 \ 1662 {S_IMAGES_DIR}/rsa_secure_boot_signing_key.pem SECURE_BOOT_DIGEST1" 1663 ) 1664 output = self.espefuse_py("summary -d") 1665 assert 2 == output.count( 1666 " = cb 27 91 a3 71 b0 c0 32 2b f7 37 04 78 ba 09 62 " 1667 "22 4c ab 1c f2 28 78 79 e4 29 67 3e 7d a8 44 63 R/-" 1668 ) 1669 1670 1671class TestBurnBitCommands(EfuseTestCase): 1672 @pytest.mark.skipif(arg_chip != "esp32", reason="ESP32-only") 1673 def test_burn_bit_for_chips_with_3_key_blocks(self): 1674 self.espefuse_py("burn_bit -h") 1675 self.espefuse_py("burn_bit BLOCK3 0 1 2 4 8 16 32 64 96 128 160 192 224 255") 1676 self.espefuse_py( 1677 "summary", 1678 check_msg="17 01 01 00 01 00 00 00 01 00 00 00 01 00 00 " 1679 "00 01 00 00 00 01 00 00 00 01 00 00 00 01 00 00 80", 1680 ) 1681 1682 self.espefuse_py( 1683 "burn_bit BLOCK3 3 5 6 7 9 10 11 12 13 14 15 31 63 95 127 159 191 223 254" 1684 ) 1685 self.espefuse_py( 1686 "summary", 1687 check_msg="ff ff 01 80 01 00 00 80 01 00 00 80 01 " 1688 "00 00 80 01 00 00 80 01 00 00 80 01 00 00 80 01 00 00 c0", 1689 ) 1690 1691 @pytest.mark.skipif(arg_chip != "esp32c2", reason="ESP32-C2-only") 1692 def test_burn_bit_for_chips_with_1_key_block(self): 1693 self.espefuse_py("burn_bit -h") 1694 self.espefuse_py("burn_bit BLOCK3 0 1 2 4 8 16 32 64 96 128 160 192 224 255") 1695 self.espefuse_py( 1696 "summary", 1697 check_msg="17 01 01 00 01 00 00 00 01 00 00 00 01 00 " 1698 "00 00 01 00 00 00 01 00 00 00 01 00 00 00 01 00 00 80", 1699 ) 1700 self.espefuse_py( 1701 "burn_bit BLOCK3 100", 1702 check_msg="Burn into BLOCK_KEY0 is forbidden " 1703 "(RS coding scheme does not allow this)", 1704 ret_code=2, 1705 ) 1706 1707 self.espefuse_py("burn_bit BLOCK0 0 1 2") 1708 self.espefuse_py("summary", check_msg="[0 ] read_regs: 00000007 00000000") 1709 1710 @pytest.mark.skipif( 1711 arg_chip 1712 not in [ 1713 "esp32s2", 1714 "esp32s3", 1715 "esp32s3beta1", 1716 "esp32c3", 1717 "esp32h2beta1", 1718 "esp32c6", 1719 "esp32h2", 1720 "esp32p4", 1721 "esp32c5", 1722 "esp32c5beta3", 1723 "esp32c61", 1724 ], 1725 reason="Only chip with 6 keys", 1726 ) 1727 def test_burn_bit_for_chips_with_6_key_blocks(self): 1728 self.espefuse_py("burn_bit -h") 1729 self.espefuse_py("burn_bit BLOCK3 0 1 2 4 8 16 32 64 96 128 160 192 224 255") 1730 self.espefuse_py( 1731 "summary", 1732 check_msg="17 01 01 00 01 00 00 00 01 00 00 00 01 00 " 1733 "00 00 01 00 00 00 01 00 00 00 01 00 00 00 01 00 00 80", 1734 ) 1735 self.espefuse_py( 1736 "burn_bit BLOCK3 100", 1737 check_msg="Burn into BLOCK_USR_DATA is forbidden " 1738 "(RS coding scheme does not allow this)", 1739 ret_code=2, 1740 ) 1741 1742 self.espefuse_py("burn_bit BLOCK0 13") 1743 self.espefuse_py( 1744 "summary", 1745 check_msg="[0 ] read_regs: 00002000 00000000 00000000 " 1746 "00000000 00000000 00000000", 1747 ) 1748 1749 self.espefuse_py("burn_bit BLOCK0 24") 1750 self.espefuse_py( 1751 "summary", 1752 check_msg="[0 ] read_regs: 01002000 00000000 00000000 " 1753 "00000000 00000000 00000000", 1754 ) 1755 1756 @pytest.mark.skipif( 1757 arg_chip != "esp32", reason="3/4 coding scheme is only in esp32" 1758 ) 1759 def test_burn_bit_with_34_coding_scheme(self): 1760 self._set_34_coding_scheme() 1761 self.espefuse_py("burn_bit BLOCK3 0 1 2 4 8 16 32 64 96 128 160 191") 1762 self.espefuse_py( 1763 "summary", 1764 check_msg="17 01 01 00 01 00 00 00 01 00 00 00 01 00 " 1765 "00 00 01 00 00 00 01 00 00 80", 1766 ) 1767 self.espefuse_py( 1768 "burn_bit BLOCK3 17", 1769 check_msg="Burn into BLOCK3 is forbidden " 1770 "(3/4 coding scheme does not allow this).", 1771 ret_code=2, 1772 ) 1773 1774 @pytest.mark.skipif(arg_chip != "esp32", reason="ESP32-only") 1775 def test_burn_bit_with_none_recovery_coding_scheme(self): 1776 self._set_none_recovery_coding_scheme() 1777 self.espefuse_py("burn_bit BLOCK3 0 1 2 4 8 16 32 64 96 128 160 192 224 255") 1778 self.espefuse_py( 1779 "summary", 1780 check_msg="17 01 01 00 01 00 00 00 01 00 00 00 01 00 00 " 1781 "00 01 00 00 00 01 00 00 00 01 00 00 00 01 00 00 80", 1782 ) 1783 1784 1785@pytest.mark.skipif( 1786 arg_chip != "esp32", reason="Tests are only for esp32. (TODO: add for all chips)" 1787) 1788class TestByteOrderBurnKeyCommand(EfuseTestCase): 1789 def test_1_secure_boot_v1(self): 1790 if arg_chip == "esp32": 1791 self.espefuse_py( 1792 f"burn_key \ 1793 flash_encryption {IMAGES_DIR}/256bit \ 1794 secure_boot_v1 {IMAGES_DIR}/256bit_1 --no-protect-key" 1795 ) 1796 output = self.espefuse_py("summary -d") 1797 self.check_data_block_in_log( 1798 output, f"{IMAGES_DIR}/256bit", reverse_order=True 1799 ) 1800 self.check_data_block_in_log( 1801 output, f"{IMAGES_DIR}/256bit_1", reverse_order=True 1802 ) 1803 1804 self.espefuse_py( 1805 f"burn_key \ 1806 flash_encryption {IMAGES_DIR}/256bit \ 1807 secure_boot_v1 {IMAGES_DIR}/256bit_1" 1808 ) 1809 output = self.espefuse_py("summary -d") 1810 assert ( 1811 "[1 ] read_regs: 00000000 00000000 00000000 00000000 " 1812 "00000000 00000000 00000000 00000000" 1813 ) in output 1814 assert ( 1815 "[2 ] read_regs: 00000000 00000000 00000000 00000000 " 1816 "00000000 00000000 00000000 00000000" 1817 ) in output 1818 assert ( 1819 "[3 ] read_regs: 00000000 00000000 00000000 00000000 " 1820 "00000000 00000000 00000000 00000000" 1821 ) in output 1822 1823 def test_2_secure_boot_v1(self): 1824 if arg_chip == "esp32": 1825 self.espefuse_py( 1826 f"burn_key \ 1827 flash_encryption {IMAGES_DIR}/256bit \ 1828 secure_boot_v2 {IMAGES_DIR}/256bit_1 --no-protect-key" 1829 ) 1830 output = self.espefuse_py("summary -d") 1831 self.check_data_block_in_log( 1832 output, f"{IMAGES_DIR}/256bit", reverse_order=True 1833 ) 1834 self.check_data_block_in_log( 1835 output, f"{IMAGES_DIR}/256bit_1", reverse_order=False 1836 ) 1837 1838 self.espefuse_py( 1839 f"burn_key \ 1840 flash_encryption {IMAGES_DIR}/256bit \ 1841 secure_boot_v2 {IMAGES_DIR}/256bit_1" 1842 ) 1843 output = self.espefuse_py("summary -d") 1844 assert ( 1845 "[1 ] read_regs: 00000000 00000000 00000000 00000000 " 1846 "00000000 00000000 00000000 00000000" 1847 ) in output 1848 self.check_data_block_in_log( 1849 output, f"{IMAGES_DIR}/256bit_1", reverse_order=False 1850 ) 1851 1852 1853class TestExecuteScriptsCommands(EfuseTestCase): 1854 @classmethod 1855 def setup_class(self): 1856 # Save the current working directory to be restored later 1857 self.stored_dir = os.getcwd() 1858 1859 @classmethod 1860 def teardown_class(self): 1861 # Restore the stored working directory 1862 os.chdir(self.stored_dir) 1863 1864 @pytest.mark.skipif( 1865 arg_chip in ["esp32c2", "esp32p4"], 1866 reason="These chips do not have eFuses used in this test", 1867 ) 1868 def test_execute_scripts_with_check_that_only_one_burn(self): 1869 self.espefuse_py("execute_scripts -h") 1870 name = arg_chip if arg_chip in ["esp32", "esp32c2"] else "esp32xx" 1871 os.chdir(os.path.join(TEST_DIR, "efuse_scripts", name)) 1872 self.espefuse_py("execute_scripts execute_efuse_script2.py") 1873 1874 @pytest.mark.skipif( 1875 arg_chip in ["esp32c2", "esp32p4"], 1876 reason="These chips do not have eFuses used in this test", 1877 ) 1878 def test_execute_scripts_with_check(self): 1879 self.espefuse_py("execute_scripts -h") 1880 name = arg_chip if arg_chip in ["esp32", "esp32c2"] else "esp32xx" 1881 os.chdir(os.path.join(TEST_DIR, "efuse_scripts", name)) 1882 self.espefuse_py("execute_scripts execute_efuse_script.py") 1883 1884 def test_execute_scripts_with_index_and_config(self): 1885 os.chdir(TEST_DIR) 1886 if arg_chip in ["esp32", "esp32c2"]: 1887 cmd = f"execute_scripts {EFUSE_S_DIR}/efuse_burn1.py --index 10 \ 1888 --configfiles {EFUSE_S_DIR}/esp32/config1.json" 1889 else: 1890 cmd = f"execute_scripts {EFUSE_S_DIR}/efuse_burn1.py --index 10 \ 1891 --configfiles {EFUSE_S_DIR}/esp32xx/config1.json" 1892 self.espefuse_py(cmd) 1893 output = self.espefuse_py("summary -d") 1894 if arg_chip in ["esp32", "esp32c2"]: 1895 assert ( 1896 "[3 ] read_regs: e00007ff 00000000 00000000 00000000 " 1897 "00000000 00000000 00000000 00000000" 1898 ) in output 1899 else: 1900 assert ( 1901 "[8 ] read_regs: e00007ff 00000000 00000000 00000000 " 1902 "00000000 00000000 00000000 00000000" 1903 ) in output 1904 1905 def test_execute_scripts_nesting(self): 1906 os.chdir(TEST_DIR) 1907 if arg_chip in ["esp32", "esp32c2"]: 1908 cmd = f"execute_scripts {EFUSE_S_DIR}/efuse_burn2.py --index 28 \ 1909 --configfiles {EFUSE_S_DIR}/esp32/config2.json" 1910 else: 1911 cmd = f"execute_scripts {EFUSE_S_DIR}/efuse_burn2.py --index 28 \ 1912 --configfiles {EFUSE_S_DIR}/esp32xx/config2.json" 1913 self.espefuse_py(cmd) 1914 output = self.espefuse_py("summary -d") 1915 if arg_chip in ["esp32", "esp32c2"]: 1916 assert ( 1917 "[2 ] read_regs: 10000000 00000000 00000000 00000000 " 1918 "00000000 00000000 00000000 00000000" 1919 ) in output 1920 assert ( 1921 "[3 ] read_regs: ffffffff 00000000 00000000 00000000 " 1922 "00000000 00000000 00000000 00000000" 1923 ) in output 1924 else: 1925 assert ( 1926 "[7 ] read_regs: 10000000 00000000 00000000 00000000 " 1927 "00000000 00000000 00000000 00000000" 1928 ) in output 1929 assert ( 1930 "[8 ] read_regs: ffffffff 00000000 00000000 00000000 " 1931 "00000000 00000000 00000000 00000000" 1932 ) in output 1933 1934 1935class TestMultipleCommands(EfuseTestCase): 1936 def test_multiple_cmds_help(self): 1937 if arg_chip == "esp32c2": 1938 command1 = ( 1939 f"burn_key_digest {S_IMAGES_DIR}" 1940 "/ecdsa256_secure_boot_signing_key_v2.pem" 1941 ) 1942 command2 = ( 1943 f"burn_key BLOCK_KEY0 {IMAGES_DIR}/128bit_key " 1944 "XTS_AES_128_KEY_DERIVED_FROM_128_EFUSE_BITS" 1945 ) 1946 elif arg_chip == "esp32": 1947 command1 = f"burn_key_digest {S_IMAGES_DIR}/rsa_secure_boot_signing_key.pem" 1948 command2 = f"burn_key flash_encryption {IMAGES_DIR}/256bit" 1949 else: 1950 command1 = f"burn_key_digest BLOCK_KEY0 \ 1951 {S_IMAGES_DIR}/rsa_secure_boot_signing_key.pem SECURE_BOOT_DIGEST0" 1952 command2 = f"burn_key BLOCK_KEY0 \ 1953 {S_IMAGES_DIR}/rsa_public_key_digest.bin SECURE_BOOT_DIGEST0" 1954 1955 self.espefuse_py( 1956 f"-h {command1} {command2}", 1957 check_msg="usage: __main__.py [-h]", 1958 ) 1959 1960 self.espefuse_py( 1961 f"{command1} -h {command2}", 1962 check_msg="usage: __main__.py burn_key_digest [-h]", 1963 ) 1964 1965 self.espefuse_py( 1966 f"{command1} {command2} -h", 1967 check_msg="usage: __main__.py burn_key [-h]", 1968 ) 1969 1970 @pytest.mark.skipif( 1971 arg_chip != "esp32c2", reason="For this chip, FE and SB keys go into one BLOCK" 1972 ) 1973 def test_1_esp32c2(self): 1974 self.espefuse_py( 1975 f"burn_key_digest {S_IMAGES_DIR}/ecdsa256_secure_boot_signing_key_v2.pem \ 1976 burn_key BLOCK_KEY0 {IMAGES_DIR}/128bit_key \ 1977 XTS_AES_128_KEY_DERIVED_FROM_128_EFUSE_BITS --no-read-protect \ 1978 summary" 1979 ) 1980 output = self.espefuse_py("summary -d") 1981 assert ( 1982 "[3 ] read_regs: 0c0d0e0f 08090a0b 04050607 00010203 " 1983 "f66a0fbf 8b6dd38b a9dab353 040af633" 1984 ) in output 1985 assert " = 0f 0e 0d 0c 0b 0a 09 08 07 06 05 04 03 02 01 00 R/-" in output 1986 assert " = bf 0f 6a f6 8b d3 6d 8b 53 b3 da a9 33 f6 0a 04 R/-" in output 1987 1988 @pytest.mark.skipif( 1989 arg_chip != "esp32c2", reason="For this chip, FE and SB keys go into one BLOCK" 1990 ) 1991 def test_2_esp32c2(self): 1992 self.espefuse_py( 1993 f"burn_key_digest {S_IMAGES_DIR}/ecdsa256_secure_boot_signing_key_v2.pem \ 1994 burn_key BLOCK_KEY0 \ 1995 {IMAGES_DIR}/128bit_key XTS_AES_128_KEY_DERIVED_FROM_128_EFUSE_BITS \ 1996 summary" 1997 ) 1998 output = self.espefuse_py("summary -d") 1999 assert ( 2000 "[3 ] read_regs: 00000000 00000000 00000000 00000000 " 2001 "f66a0fbf 8b6dd38b a9dab353 040af633" 2002 ) in output 2003 assert " = ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? -/-" in output 2004 assert " = bf 0f 6a f6 8b d3 6d 8b 53 b3 da a9 33 f6 0a 04 R/-" in output 2005 2006 def test_burn_bit(self): 2007 if arg_chip == "esp32": 2008 self._set_34_coding_scheme() 2009 self.espefuse_py( 2010 "burn_bit BLOCK2 0 1 2 3 \ 2011 burn_bit BLOCK2 4 5 6 7 \ 2012 burn_bit BLOCK2 8 9 10 11 \ 2013 burn_bit BLOCK2 12 13 14 15 \ 2014 summary" 2015 ) 2016 output = self.espefuse_py("summary -d") 2017 assert "[2 ] read_regs: 0000ffff 00000000" in output 2018 2019 def test_not_burn_cmds(self): 2020 self.espefuse_py( 2021 "summary \ 2022 dump \ 2023 get_custom_mac \ 2024 adc_info \ 2025 check_error" 2026 ) 2027 2028 2029@pytest.mark.skipif( 2030 arg_chip not in ["esp32c3", "esp32c6", "esp32h2", "esp32s3"], 2031 reason="These chips have a hardware bug that limits the use of the KEY5", 2032) 2033class TestKeyPurposes(EfuseTestCase): 2034 def test_burn_xts_aes_key_purpose(self): 2035 self.espefuse_py( 2036 "burn_efuse KEY_PURPOSE_5 XTS_AES_128_KEY", 2037 check_msg="A fatal error occurred: " 2038 "KEY_PURPOSE_5 can not have XTS_AES_128_KEY " 2039 "key due to a hardware bug (please see TRM for more details)", 2040 ret_code=2, 2041 ) 2042 2043 @pytest.mark.skipif( 2044 arg_chip != "esp32h2", reason="esp32h2 can not have ECDSA key in KEY5" 2045 ) 2046 def test_burn_ecdsa_key_purpose(self): 2047 self.espefuse_py( 2048 "burn_efuse KEY_PURPOSE_5 ECDSA_KEY", 2049 check_msg="A fatal error occurred: " 2050 "KEY_PURPOSE_5 can not have ECDSA_KEY " 2051 "key due to a hardware bug (please see TRM for more details)", 2052 ret_code=2, 2053 ) 2054 2055 def test_burn_xts_aes_key(self): 2056 self.espefuse_py( 2057 f"burn_key \ 2058 BLOCK_KEY5 {IMAGES_DIR}/256bit XTS_AES_128_KEY", 2059 check_msg="A fatal error occurred: " 2060 "KEY_PURPOSE_5 can not have XTS_AES_128_KEY " 2061 "key due to a hardware bug (please see TRM for more details)", 2062 ret_code=2, 2063 ) 2064 2065 @pytest.mark.skipif( 2066 arg_chip != "esp32h2", reason="esp32h2 can not have ECDSA key in KEY5" 2067 ) 2068 def test_burn_ecdsa_key(self): 2069 self.espefuse_py( 2070 f"burn_key \ 2071 BLOCK_KEY5 {S_IMAGES_DIR}/ecdsa192_secure_boot_signing_key_v2.pem \ 2072 ECDSA_KEY", 2073 check_msg="A fatal error occurred: " 2074 "KEY_PURPOSE_5 can not have ECDSA_KEY " 2075 "key due to a hardware bug (please see TRM for more details)", 2076 ret_code=2, 2077 ) 2078 2079 2080class TestPostponedEfuses(EfuseTestCase): 2081 def test_postpone_efuses(self): 2082 if arg_chip == "esp32": 2083 cmd = f"--postpone \ 2084 burn_efuse UART_DOWNLOAD_DIS 1 \ 2085 burn_key BLOCK1 {IMAGES_DIR}/256bit \ 2086 burn_efuse ABS_DONE_1 1 FLASH_CRYPT_CNT 1" 2087 num = 1 2088 else: 2089 sb_digest_name = ( 2090 "SECURE_BOOT_DIGEST" if arg_chip == "esp32c2" else "SECURE_BOOT_DIGEST0" 2091 ) 2092 cmd = f"--postpone \ 2093 burn_efuse ENABLE_SECURITY_DOWNLOAD 1 DIS_DOWNLOAD_MODE 1 \ 2094 SECURE_VERSION 1 \ 2095 burn_key BLOCK_KEY0 {IMAGES_DIR}/256bit {sb_digest_name} \ 2096 burn_efuse SPI_BOOT_CRYPT_CNT 1 SECURE_BOOT_EN 1" 2097 num = 3 if arg_chip == "esp32c2" else 4 2098 output = self.espefuse_py(cmd) 2099 assert f"BURN BLOCK{num} - OK" in output 2100 assert "BURN BLOCK0 - OK" in output 2101 assert "Burn postponed efuses from BLOCK0" in output 2102 assert "BURN BLOCK0 - OK" in output 2103 assert "Successful" in output 2104 2105 2106class TestCSVEfuseTable(EfuseTestCase): 2107 def test_extend_efuse_table_with_csv_file(self): 2108 csv_file = f"{IMAGES_DIR}/esp_efuse_custom_table.csv" 2109 output = self.espefuse_py(f" --extend-efuse-table {csv_file} summary") 2110 assert "MODULE_VERSION (BLOCK3)" in output 2111 assert "DEVICE_ROLE (BLOCK3)" in output 2112 assert "SETTING_2 (BLOCK3)" in output 2113 assert "ID_NUM_0 (BLOCK3)" in output 2114 assert "ID_NUM_1 (BLOCK3)" in output 2115 assert "ID_NUM_2 (BLOCK3)" in output 2116 assert "CUSTOM_SECURE_VERSION (BLOCK3)" in output 2117 assert "ID_NUMK_0 (BLOCK3)" in output 2118 assert "ID_NUMK_1 (BLOCK3)" in output 2119 2120 self.espefuse_py( 2121 f"--extend-efuse-table {csv_file} burn_efuse \ 2122 MODULE_VERSION 1 \ 2123 CUSTOM_SECURE_VERSION 4 \ 2124 SETTING_1_ALT_NAME 7 \ 2125 SETTING_2 1 \ 2126 ID_NUM_0 1 \ 2127 ID_NUM_1 1 \ 2128 ID_NUM_2 1 \ 2129 MY_ID_NUMK_0 1 \ 2130 MY_ID_NUMK_1 1 \ 2131 MY_DATA_FIELD1 1" 2132 ) 2133