esptool 4.9.dev8__tar.gz → 4.10.dev1__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- {esptool-4.9.dev8/esptool.egg-info → esptool-4.10.dev1}/PKG-INFO +1 -1
- {esptool-4.9.dev8 → esptool-4.10.dev1}/espefuse/efuse/base_operations.py +161 -0
- {esptool-4.9.dev8 → esptool-4.10.dev1}/espefuse/efuse/esp32c3/fields.py +1 -0
- {esptool-4.9.dev8 → esptool-4.10.dev1}/espefuse/efuse/esp32c3/operations.py +7 -9
- {esptool-4.9.dev8 → esptool-4.10.dev1}/espefuse/efuse/esp32c5/fields.py +15 -7
- esptool-4.10.dev1/espefuse/efuse/esp32c5/operations.py +390 -0
- {esptool-4.9.dev8/espefuse/efuse/esp32c61 → esptool-4.10.dev1/espefuse/efuse/esp32c6}/fields.py +18 -10
- {esptool-4.9.dev8 → esptool-4.10.dev1}/espefuse/efuse/esp32c6/operations.py +7 -9
- {esptool-4.9.dev8/espefuse/efuse/esp32c6 → esptool-4.10.dev1/espefuse/efuse/esp32c61}/fields.py +5 -8
- esptool-4.10.dev1/espefuse/efuse/esp32c61/operations.py +391 -0
- {esptool-4.9.dev8 → esptool-4.10.dev1}/espefuse/efuse/esp32h2/fields.py +1 -0
- {esptool-4.9.dev8 → esptool-4.10.dev1}/espefuse/efuse/esp32h2/operations.py +8 -17
- {esptool-4.9.dev8 → esptool-4.10.dev1}/espefuse/efuse/esp32h21/operations.py +8 -17
- {esptool-4.9.dev8 → esptool-4.10.dev1}/espefuse/efuse/esp32h4/fields.py +5 -0
- {esptool-4.9.dev8 → esptool-4.10.dev1}/espefuse/efuse/esp32h4/operations.py +8 -17
- {esptool-4.9.dev8 → esptool-4.10.dev1}/espefuse/efuse/esp32p4/fields.py +12 -2
- esptool-4.10.dev1/espefuse/efuse/esp32p4/operations.py +391 -0
- {esptool-4.9.dev8 → esptool-4.10.dev1}/espefuse/efuse/esp32s2/operations.py +7 -75
- {esptool-4.9.dev8 → esptool-4.10.dev1}/espefuse/efuse/esp32s3/fields.py +1 -0
- {esptool-4.9.dev8 → esptool-4.10.dev1}/espefuse/efuse/esp32s3/operations.py +7 -75
- esptool-4.10.dev1/espefuse/efuse_defs/esp32c61.yaml +105 -0
- {esptool-4.9.dev8 → esptool-4.10.dev1}/espsecure/__init__.py +2 -2
- {esptool-4.9.dev8 → esptool-4.10.dev1}/esptool/__init__.py +17 -7
- {esptool-4.9.dev8 → esptool-4.10.dev1}/esptool/bin_image.py +104 -39
- {esptool-4.9.dev8 → esptool-4.10.dev1}/esptool/cmds.py +78 -82
- {esptool-4.9.dev8 → esptool-4.10.dev1}/esptool/loader.py +204 -75
- {esptool-4.9.dev8 → esptool-4.10.dev1}/esptool/targets/esp32.py +1 -4
- {esptool-4.9.dev8 → esptool-4.10.dev1}/esptool/targets/esp32c2.py +0 -1
- {esptool-4.9.dev8 → esptool-4.10.dev1}/esptool/targets/esp32c3.py +0 -1
- {esptool-4.9.dev8 → esptool-4.10.dev1}/esptool/targets/esp32c5.py +0 -1
- {esptool-4.9.dev8 → esptool-4.10.dev1}/esptool/targets/esp32c5beta3.py +0 -1
- {esptool-4.9.dev8 → esptool-4.10.dev1}/esptool/targets/esp32c6.py +0 -1
- {esptool-4.9.dev8 → esptool-4.10.dev1}/esptool/targets/esp32c61.py +0 -1
- {esptool-4.9.dev8 → esptool-4.10.dev1}/esptool/targets/esp32h2.py +0 -1
- {esptool-4.9.dev8 → esptool-4.10.dev1}/esptool/targets/esp32h21.py +0 -1
- {esptool-4.9.dev8 → esptool-4.10.dev1}/esptool/targets/esp32h2beta1.py +0 -1
- {esptool-4.9.dev8 → esptool-4.10.dev1}/esptool/targets/esp32h2beta2.py +0 -1
- {esptool-4.9.dev8 → esptool-4.10.dev1}/esptool/targets/esp32h4.py +0 -1
- {esptool-4.9.dev8 → esptool-4.10.dev1}/esptool/targets/esp32p4.py +0 -1
- {esptool-4.9.dev8 → esptool-4.10.dev1}/esptool/targets/esp32s2.py +0 -1
- {esptool-4.9.dev8 → esptool-4.10.dev1}/esptool/targets/esp32s3.py +0 -1
- {esptool-4.9.dev8 → esptool-4.10.dev1}/esptool/targets/esp32s3beta2.py +0 -1
- {esptool-4.9.dev8 → esptool-4.10.dev1}/esptool/targets/stub_flasher/1/README.md +1 -1
- esptool-4.10.dev1/esptool/targets/stub_flasher/1/esp32.json +8 -0
- esptool-4.10.dev1/esptool/targets/stub_flasher/1/esp32c2.json +8 -0
- esptool-4.10.dev1/esptool/targets/stub_flasher/1/esp32c3.json +8 -0
- esptool-4.10.dev1/esptool/targets/stub_flasher/1/esp32c5.json +8 -0
- esptool-4.10.dev1/esptool/targets/stub_flasher/1/esp32c5beta3.json +8 -0
- esptool-4.10.dev1/esptool/targets/stub_flasher/1/esp32c6.json +8 -0
- esptool-4.10.dev1/esptool/targets/stub_flasher/1/esp32c61.json +8 -0
- esptool-4.10.dev1/esptool/targets/stub_flasher/1/esp32c6beta.json +8 -0
- esptool-4.10.dev1/esptool/targets/stub_flasher/1/esp32h2.json +8 -0
- esptool-4.10.dev1/esptool/targets/stub_flasher/1/esp32h2beta1.json +8 -0
- esptool-4.10.dev1/esptool/targets/stub_flasher/1/esp32h2beta2.json +8 -0
- esptool-4.10.dev1/esptool/targets/stub_flasher/1/esp32p4.json +8 -0
- esptool-4.10.dev1/esptool/targets/stub_flasher/1/esp32s2.json +8 -0
- esptool-4.10.dev1/esptool/targets/stub_flasher/1/esp32s3.json +8 -0
- esptool-4.10.dev1/esptool/targets/stub_flasher/1/esp32s3beta2.json +8 -0
- {esptool-4.9.dev8 → esptool-4.10.dev1/esptool.egg-info}/PKG-INFO +1 -1
- {esptool-4.9.dev8 → esptool-4.10.dev1}/pyproject.toml +1 -1
- esptool-4.9.dev8/espefuse/efuse/esp32c5/operations.py +0 -466
- esptool-4.9.dev8/espefuse/efuse/esp32c61/operations.py +0 -466
- esptool-4.9.dev8/espefuse/efuse/esp32p4/operations.py +0 -466
- esptool-4.9.dev8/espefuse/efuse_defs/esp32c61.yaml +0 -95
- esptool-4.9.dev8/esptool/targets/stub_flasher/1/esp32.json +0 -8
- esptool-4.9.dev8/esptool/targets/stub_flasher/1/esp32c2.json +0 -8
- esptool-4.9.dev8/esptool/targets/stub_flasher/1/esp32c3.json +0 -8
- esptool-4.9.dev8/esptool/targets/stub_flasher/1/esp32c5.json +0 -8
- esptool-4.9.dev8/esptool/targets/stub_flasher/1/esp32c5beta3.json +0 -8
- esptool-4.9.dev8/esptool/targets/stub_flasher/1/esp32c6.json +0 -8
- esptool-4.9.dev8/esptool/targets/stub_flasher/1/esp32c61.json +0 -8
- esptool-4.9.dev8/esptool/targets/stub_flasher/1/esp32c6beta.json +0 -8
- esptool-4.9.dev8/esptool/targets/stub_flasher/1/esp32h2.json +0 -8
- esptool-4.9.dev8/esptool/targets/stub_flasher/1/esp32h2beta1.json +0 -8
- esptool-4.9.dev8/esptool/targets/stub_flasher/1/esp32h2beta2.json +0 -8
- esptool-4.9.dev8/esptool/targets/stub_flasher/1/esp32p4.json +0 -8
- esptool-4.9.dev8/esptool/targets/stub_flasher/1/esp32s2.json +0 -8
- esptool-4.9.dev8/esptool/targets/stub_flasher/1/esp32s3.json +0 -8
- esptool-4.9.dev8/esptool/targets/stub_flasher/1/esp32s3beta2.json +0 -8
- {esptool-4.9.dev8 → esptool-4.10.dev1}/LICENSE +0 -0
- {esptool-4.9.dev8 → esptool-4.10.dev1}/MANIFEST.in +0 -0
- {esptool-4.9.dev8 → esptool-4.10.dev1}/README.md +0 -0
- {esptool-4.9.dev8 → esptool-4.10.dev1}/esp_rfc2217_server/__init__.py +0 -0
- {esptool-4.9.dev8 → esptool-4.10.dev1}/esp_rfc2217_server/__main__.py +0 -0
- {esptool-4.9.dev8 → esptool-4.10.dev1}/esp_rfc2217_server/esp_port_manager.py +0 -0
- {esptool-4.9.dev8 → esptool-4.10.dev1}/esp_rfc2217_server/redirector.py +0 -0
- {esptool-4.9.dev8 → esptool-4.10.dev1}/esp_rfc2217_server.py +0 -0
- {esptool-4.9.dev8 → esptool-4.10.dev1}/espefuse/__init__.py +0 -0
- {esptool-4.9.dev8 → esptool-4.10.dev1}/espefuse/__main__.py +0 -0
- {esptool-4.9.dev8 → esptool-4.10.dev1}/espefuse/efuse/__init__.py +0 -0
- {esptool-4.9.dev8 → esptool-4.10.dev1}/espefuse/efuse/base_fields.py +0 -0
- {esptool-4.9.dev8 → esptool-4.10.dev1}/espefuse/efuse/csv_table_parser.py +0 -0
- {esptool-4.9.dev8 → esptool-4.10.dev1}/espefuse/efuse/emulate_efuse_controller_base.py +0 -0
- {esptool-4.9.dev8 → esptool-4.10.dev1}/espefuse/efuse/esp32/__init__.py +0 -0
- {esptool-4.9.dev8 → esptool-4.10.dev1}/espefuse/efuse/esp32/emulate_efuse_controller.py +0 -0
- {esptool-4.9.dev8 → esptool-4.10.dev1}/espefuse/efuse/esp32/fields.py +0 -0
- {esptool-4.9.dev8 → esptool-4.10.dev1}/espefuse/efuse/esp32/mem_definition.py +0 -0
- {esptool-4.9.dev8 → esptool-4.10.dev1}/espefuse/efuse/esp32/operations.py +0 -0
- {esptool-4.9.dev8 → esptool-4.10.dev1}/espefuse/efuse/esp32c2/__init__.py +0 -0
- {esptool-4.9.dev8 → esptool-4.10.dev1}/espefuse/efuse/esp32c2/emulate_efuse_controller.py +0 -0
- {esptool-4.9.dev8 → esptool-4.10.dev1}/espefuse/efuse/esp32c2/fields.py +0 -0
- {esptool-4.9.dev8 → esptool-4.10.dev1}/espefuse/efuse/esp32c2/mem_definition.py +0 -0
- {esptool-4.9.dev8 → esptool-4.10.dev1}/espefuse/efuse/esp32c2/operations.py +0 -0
- {esptool-4.9.dev8 → esptool-4.10.dev1}/espefuse/efuse/esp32c3/__init__.py +0 -0
- {esptool-4.9.dev8 → esptool-4.10.dev1}/espefuse/efuse/esp32c3/emulate_efuse_controller.py +0 -0
- {esptool-4.9.dev8 → esptool-4.10.dev1}/espefuse/efuse/esp32c3/mem_definition.py +0 -0
- {esptool-4.9.dev8 → esptool-4.10.dev1}/espefuse/efuse/esp32c5/__init__.py +0 -0
- {esptool-4.9.dev8 → esptool-4.10.dev1}/espefuse/efuse/esp32c5/emulate_efuse_controller.py +0 -0
- {esptool-4.9.dev8 → esptool-4.10.dev1}/espefuse/efuse/esp32c5/mem_definition.py +0 -0
- {esptool-4.9.dev8 → esptool-4.10.dev1}/espefuse/efuse/esp32c5beta3/__init__.py +0 -0
- {esptool-4.9.dev8 → esptool-4.10.dev1}/espefuse/efuse/esp32c5beta3/emulate_efuse_controller.py +0 -0
- {esptool-4.9.dev8 → esptool-4.10.dev1}/espefuse/efuse/esp32c5beta3/fields.py +0 -0
- {esptool-4.9.dev8 → esptool-4.10.dev1}/espefuse/efuse/esp32c5beta3/mem_definition.py +0 -0
- {esptool-4.9.dev8 → esptool-4.10.dev1}/espefuse/efuse/esp32c5beta3/operations.py +0 -0
- {esptool-4.9.dev8 → esptool-4.10.dev1}/espefuse/efuse/esp32c6/__init__.py +0 -0
- {esptool-4.9.dev8 → esptool-4.10.dev1}/espefuse/efuse/esp32c6/emulate_efuse_controller.py +0 -0
- {esptool-4.9.dev8 → esptool-4.10.dev1}/espefuse/efuse/esp32c6/mem_definition.py +0 -0
- {esptool-4.9.dev8 → esptool-4.10.dev1}/espefuse/efuse/esp32c61/__init__.py +0 -0
- {esptool-4.9.dev8 → esptool-4.10.dev1}/espefuse/efuse/esp32c61/emulate_efuse_controller.py +0 -0
- {esptool-4.9.dev8 → esptool-4.10.dev1}/espefuse/efuse/esp32c61/mem_definition.py +0 -0
- {esptool-4.9.dev8 → esptool-4.10.dev1}/espefuse/efuse/esp32h2/__init__.py +0 -0
- {esptool-4.9.dev8 → esptool-4.10.dev1}/espefuse/efuse/esp32h2/emulate_efuse_controller.py +0 -0
- {esptool-4.9.dev8 → esptool-4.10.dev1}/espefuse/efuse/esp32h2/mem_definition.py +0 -0
- {esptool-4.9.dev8 → esptool-4.10.dev1}/espefuse/efuse/esp32h21/__init__.py +0 -0
- {esptool-4.9.dev8 → esptool-4.10.dev1}/espefuse/efuse/esp32h21/emulate_efuse_controller.py +0 -0
- {esptool-4.9.dev8 → esptool-4.10.dev1}/espefuse/efuse/esp32h21/fields.py +0 -0
- {esptool-4.9.dev8 → esptool-4.10.dev1}/espefuse/efuse/esp32h21/mem_definition.py +0 -0
- {esptool-4.9.dev8 → esptool-4.10.dev1}/espefuse/efuse/esp32h2beta1/__init__.py +0 -0
- {esptool-4.9.dev8 → esptool-4.10.dev1}/espefuse/efuse/esp32h2beta1/emulate_efuse_controller.py +0 -0
- {esptool-4.9.dev8 → esptool-4.10.dev1}/espefuse/efuse/esp32h2beta1/fields.py +0 -0
- {esptool-4.9.dev8 → esptool-4.10.dev1}/espefuse/efuse/esp32h2beta1/mem_definition.py +0 -0
- {esptool-4.9.dev8 → esptool-4.10.dev1}/espefuse/efuse/esp32h2beta1/operations.py +0 -0
- {esptool-4.9.dev8 → esptool-4.10.dev1}/espefuse/efuse/esp32h4/__init__.py +0 -0
- {esptool-4.9.dev8 → esptool-4.10.dev1}/espefuse/efuse/esp32h4/emulate_efuse_controller.py +0 -0
- {esptool-4.9.dev8 → esptool-4.10.dev1}/espefuse/efuse/esp32h4/mem_definition.py +0 -0
- {esptool-4.9.dev8 → esptool-4.10.dev1}/espefuse/efuse/esp32p4/__init__.py +0 -0
- {esptool-4.9.dev8 → esptool-4.10.dev1}/espefuse/efuse/esp32p4/emulate_efuse_controller.py +0 -0
- {esptool-4.9.dev8 → esptool-4.10.dev1}/espefuse/efuse/esp32p4/mem_definition.py +0 -0
- {esptool-4.9.dev8 → esptool-4.10.dev1}/espefuse/efuse/esp32s2/__init__.py +0 -0
- {esptool-4.9.dev8 → esptool-4.10.dev1}/espefuse/efuse/esp32s2/emulate_efuse_controller.py +0 -0
- {esptool-4.9.dev8 → esptool-4.10.dev1}/espefuse/efuse/esp32s2/fields.py +0 -0
- {esptool-4.9.dev8 → esptool-4.10.dev1}/espefuse/efuse/esp32s2/mem_definition.py +0 -0
- {esptool-4.9.dev8 → esptool-4.10.dev1}/espefuse/efuse/esp32s3/__init__.py +0 -0
- {esptool-4.9.dev8 → esptool-4.10.dev1}/espefuse/efuse/esp32s3/emulate_efuse_controller.py +0 -0
- {esptool-4.9.dev8 → esptool-4.10.dev1}/espefuse/efuse/esp32s3/mem_definition.py +0 -0
- {esptool-4.9.dev8 → esptool-4.10.dev1}/espefuse/efuse/esp32s3beta2/__init__.py +0 -0
- {esptool-4.9.dev8 → esptool-4.10.dev1}/espefuse/efuse/esp32s3beta2/emulate_efuse_controller.py +0 -0
- {esptool-4.9.dev8 → esptool-4.10.dev1}/espefuse/efuse/esp32s3beta2/fields.py +0 -0
- {esptool-4.9.dev8 → esptool-4.10.dev1}/espefuse/efuse/esp32s3beta2/mem_definition.py +0 -0
- {esptool-4.9.dev8 → esptool-4.10.dev1}/espefuse/efuse/esp32s3beta2/operations.py +0 -0
- {esptool-4.9.dev8 → esptool-4.10.dev1}/espefuse/efuse/mem_definition_base.py +0 -0
- {esptool-4.9.dev8 → esptool-4.10.dev1}/espefuse/efuse/util.py +0 -0
- {esptool-4.9.dev8 → esptool-4.10.dev1}/espefuse/efuse_defs/esp32.yaml +0 -0
- {esptool-4.9.dev8 → esptool-4.10.dev1}/espefuse/efuse_defs/esp32c2.yaml +0 -0
- {esptool-4.9.dev8 → esptool-4.10.dev1}/espefuse/efuse_defs/esp32c3.yaml +0 -0
- {esptool-4.9.dev8 → esptool-4.10.dev1}/espefuse/efuse_defs/esp32c5.yaml +0 -0
- {esptool-4.9.dev8 → esptool-4.10.dev1}/espefuse/efuse_defs/esp32c5beta3.yaml +0 -0
- {esptool-4.9.dev8 → esptool-4.10.dev1}/espefuse/efuse_defs/esp32c6.yaml +0 -0
- {esptool-4.9.dev8 → esptool-4.10.dev1}/espefuse/efuse_defs/esp32h2.yaml +0 -0
- {esptool-4.9.dev8 → esptool-4.10.dev1}/espefuse/efuse_defs/esp32h21.yaml +0 -0
- {esptool-4.9.dev8 → esptool-4.10.dev1}/espefuse/efuse_defs/esp32h2_v0.0_v1.1.yaml +0 -0
- {esptool-4.9.dev8 → esptool-4.10.dev1}/espefuse/efuse_defs/esp32h4.yaml +0 -0
- {esptool-4.9.dev8 → esptool-4.10.dev1}/espefuse/efuse_defs/esp32p4.yaml +0 -0
- {esptool-4.9.dev8 → esptool-4.10.dev1}/espefuse/efuse_defs/esp32s2.yaml +0 -0
- {esptool-4.9.dev8 → esptool-4.10.dev1}/espefuse/efuse_defs/esp32s3.yaml +0 -0
- {esptool-4.9.dev8 → esptool-4.10.dev1}/espefuse.py +0 -0
- {esptool-4.9.dev8 → esptool-4.10.dev1}/espsecure/__main__.py +0 -0
- {esptool-4.9.dev8 → esptool-4.10.dev1}/espsecure/esp_hsm_sign/__init__.py +0 -0
- {esptool-4.9.dev8 → esptool-4.10.dev1}/espsecure/esp_hsm_sign/exceptions.py +0 -0
- {esptool-4.9.dev8 → esptool-4.10.dev1}/espsecure.py +0 -0
- {esptool-4.9.dev8 → esptool-4.10.dev1}/esptool/__main__.py +0 -0
- {esptool-4.9.dev8 → esptool-4.10.dev1}/esptool/config.py +0 -0
- {esptool-4.9.dev8 → esptool-4.10.dev1}/esptool/reset.py +0 -0
- {esptool-4.9.dev8 → esptool-4.10.dev1}/esptool/targets/__init__.py +0 -0
- {esptool-4.9.dev8 → esptool-4.10.dev1}/esptool/targets/esp32c6beta.py +0 -0
- {esptool-4.9.dev8 → esptool-4.10.dev1}/esptool/targets/esp8266.py +0 -0
- {esptool-4.9.dev8 → esptool-4.10.dev1}/esptool/targets/stub_flasher/1/esp8266.json +0 -0
- {esptool-4.9.dev8 → esptool-4.10.dev1}/esptool/targets/stub_flasher/2/LICENSE-APACHE +0 -0
- {esptool-4.9.dev8 → esptool-4.10.dev1}/esptool/targets/stub_flasher/2/LICENSE-MIT +0 -0
- {esptool-4.9.dev8 → esptool-4.10.dev1}/esptool/targets/stub_flasher/2/README.md +0 -0
- {esptool-4.9.dev8 → esptool-4.10.dev1}/esptool/targets/stub_flasher/2/esp32.json +0 -0
- {esptool-4.9.dev8 → esptool-4.10.dev1}/esptool/targets/stub_flasher/2/esp32c2.json +0 -0
- {esptool-4.9.dev8 → esptool-4.10.dev1}/esptool/targets/stub_flasher/2/esp32c3.json +0 -0
- {esptool-4.9.dev8 → esptool-4.10.dev1}/esptool/targets/stub_flasher/2/esp32c6.json +0 -0
- {esptool-4.9.dev8 → esptool-4.10.dev1}/esptool/targets/stub_flasher/2/esp32h2.json +0 -0
- {esptool-4.9.dev8 → esptool-4.10.dev1}/esptool/targets/stub_flasher/2/esp32s2.json +0 -0
- {esptool-4.9.dev8 → esptool-4.10.dev1}/esptool/targets/stub_flasher/2/esp32s3.json +0 -0
- {esptool-4.9.dev8 → esptool-4.10.dev1}/esptool/uf2_writer.py +0 -0
- {esptool-4.9.dev8 → esptool-4.10.dev1}/esptool/util.py +0 -0
- {esptool-4.9.dev8 → esptool-4.10.dev1}/esptool.egg-info/SOURCES.txt +0 -0
- {esptool-4.9.dev8 → esptool-4.10.dev1}/esptool.egg-info/dependency_links.txt +0 -0
- {esptool-4.9.dev8 → esptool-4.10.dev1}/esptool.egg-info/requires.txt +0 -0
- {esptool-4.9.dev8 → esptool-4.10.dev1}/esptool.egg-info/top_level.txt +0 -0
- {esptool-4.9.dev8 → esptool-4.10.dev1}/esptool.py +0 -0
- {esptool-4.9.dev8 → esptool-4.10.dev1}/setup.cfg +0 -0
- {esptool-4.9.dev8 → esptool-4.10.dev1}/setup.py +0 -0
|
@@ -5,12 +5,14 @@
|
|
|
5
5
|
# SPDX-License-Identifier: GPL-2.0-or-later
|
|
6
6
|
|
|
7
7
|
import argparse
|
|
8
|
+
import io
|
|
8
9
|
import os
|
|
9
10
|
import json
|
|
10
11
|
import sys
|
|
11
12
|
|
|
12
13
|
from bitstring import BitStream
|
|
13
14
|
|
|
15
|
+
import espsecure
|
|
14
16
|
import esptool
|
|
15
17
|
|
|
16
18
|
from . import base_fields
|
|
@@ -802,3 +804,162 @@ def check_error(esp, efuses, args):
|
|
|
802
804
|
if error_in_blocks:
|
|
803
805
|
raise esptool.FatalError("Error(s) were detected in eFuses")
|
|
804
806
|
print("No errors detected")
|
|
807
|
+
|
|
808
|
+
|
|
809
|
+
def _key_block_is_unused(block, key_purpose_block):
|
|
810
|
+
"""Helper method to check if a key block is available for use"""
|
|
811
|
+
if not block.is_readable() or not block.is_writeable():
|
|
812
|
+
return False
|
|
813
|
+
|
|
814
|
+
if key_purpose_block.get() != "USER" or not key_purpose_block.is_writeable():
|
|
815
|
+
return False
|
|
816
|
+
|
|
817
|
+
if not block.get_bitstring().all(False):
|
|
818
|
+
return False
|
|
819
|
+
|
|
820
|
+
return True
|
|
821
|
+
|
|
822
|
+
|
|
823
|
+
def _get_next_key_block(efuses, current_key_block, block_name_list):
|
|
824
|
+
"""Helper method to get the next available key block"""
|
|
825
|
+
key_blocks = [b for b in efuses.blocks if b.key_purpose_name]
|
|
826
|
+
start = key_blocks.index(current_key_block)
|
|
827
|
+
|
|
828
|
+
# Sort key blocks so that we pick the next free block
|
|
829
|
+
# (and loop around if necessary)
|
|
830
|
+
key_blocks = key_blocks[start:] + key_blocks[0:start]
|
|
831
|
+
|
|
832
|
+
# Exclude any other blocks that will be be burned
|
|
833
|
+
key_blocks = [b for b in key_blocks if b.name not in block_name_list]
|
|
834
|
+
|
|
835
|
+
for block in key_blocks:
|
|
836
|
+
key_purpose_block = efuses[block.key_purpose_name]
|
|
837
|
+
if _key_block_is_unused(block, key_purpose_block):
|
|
838
|
+
return block
|
|
839
|
+
|
|
840
|
+
return None
|
|
841
|
+
|
|
842
|
+
|
|
843
|
+
def adjust_key_data_for_blocks(efuses, block_names, datafiles, keypurposes):
|
|
844
|
+
"""Split a key that takes more than one efuse block into two blocks.
|
|
845
|
+
It handles all key purposes that require splitting into two blocks.
|
|
846
|
+
|
|
847
|
+
This method checks if key purposes require splitting into two blocks,
|
|
848
|
+
such as "XTS_AES_256_KEY", "XTS_AES_256_PSRAM_KEY", and "ECDSA_KEY_P384".
|
|
849
|
+
|
|
850
|
+
Args:
|
|
851
|
+
block_names: List of block names.
|
|
852
|
+
datafiles: List of BinaryIO objects containing key data.
|
|
853
|
+
keypurposes: List of key purposes.
|
|
854
|
+
|
|
855
|
+
Returns:
|
|
856
|
+
A tuple containing updated block names, datafiles, and keypurposes.
|
|
857
|
+
"""
|
|
858
|
+
keypurposes = list(keypurposes)
|
|
859
|
+
datafiles = list(datafiles)
|
|
860
|
+
block_names = list(block_names)
|
|
861
|
+
|
|
862
|
+
if "XTS_AES_256_KEY" in keypurposes:
|
|
863
|
+
# XTS_AES_256_KEY is not an actual HW key purpose, needs to be split into
|
|
864
|
+
# XTS_AES_256_KEY_1 and XTS_AES_256_KEY_2
|
|
865
|
+
block_names, datafiles, keypurposes = _split_multiblock_key(
|
|
866
|
+
efuses,
|
|
867
|
+
block_names,
|
|
868
|
+
datafiles, # type: ignore
|
|
869
|
+
keypurposes,
|
|
870
|
+
"XTS_AES_256_KEY",
|
|
871
|
+
)
|
|
872
|
+
|
|
873
|
+
if "XTS_AES_256_PSRAM_KEY" in keypurposes:
|
|
874
|
+
# XTS_AES_256_PSRAM_KEY -> XTS_AES_256_PSRAM_KEY_1 and ..._KEY_2
|
|
875
|
+
block_names, datafiles, keypurposes = _split_multiblock_key(
|
|
876
|
+
efuses,
|
|
877
|
+
block_names,
|
|
878
|
+
datafiles, # type: ignore
|
|
879
|
+
keypurposes,
|
|
880
|
+
"XTS_AES_256_PSRAM_KEY",
|
|
881
|
+
)
|
|
882
|
+
|
|
883
|
+
# ECDSA keys can be present in a command multiple times
|
|
884
|
+
i = 0
|
|
885
|
+
while i < len(keypurposes):
|
|
886
|
+
if "ECDSA_KEY" in keypurposes[i]:
|
|
887
|
+
if keypurposes[i] not in ["ECDSA_KEY_P384_L", "ECDSA_KEY_P384_H"]:
|
|
888
|
+
sk = espsecure.load_ecdsa_signing_key(datafiles[i]) # type: ignore
|
|
889
|
+
data = sk.to_string()
|
|
890
|
+
if "ECDSA_KEY_P384" == keypurposes[i]:
|
|
891
|
+
assert (
|
|
892
|
+
len(data) == 48
|
|
893
|
+
), "NIST384p private key should be 48 bytes long"
|
|
894
|
+
datafiles[i] = io.BytesIO(b"\x00" * 16 + data)
|
|
895
|
+
# ECDSA_KEY_P384 -> ECDSA_KEY_P384_L and ECDSA_KEY_P384_H
|
|
896
|
+
block_names, datafiles, keypurposes = _split_multiblock_key(
|
|
897
|
+
efuses,
|
|
898
|
+
block_names,
|
|
899
|
+
datafiles, # type: ignore
|
|
900
|
+
keypurposes,
|
|
901
|
+
"ECDSA_KEY_P384",
|
|
902
|
+
)
|
|
903
|
+
else:
|
|
904
|
+
# the private key is 24 bytes long for NIST192p,
|
|
905
|
+
# and 8 bytes of padding
|
|
906
|
+
datafiles[i] = (
|
|
907
|
+
io.BytesIO(b"\x00" * 8 + data)
|
|
908
|
+
if len(data) == 24
|
|
909
|
+
else io.BytesIO(data)
|
|
910
|
+
)
|
|
911
|
+
|
|
912
|
+
i += 1
|
|
913
|
+
|
|
914
|
+
# Check that all block names are unique
|
|
915
|
+
util.check_duplicate_name_in_list(block_names)
|
|
916
|
+
|
|
917
|
+
# Check that the number of blocks, datafiles, and keypurposes is equal
|
|
918
|
+
if len(block_names) != len(datafiles) or len(block_names) != len(keypurposes):
|
|
919
|
+
raise esptool.FatalError(
|
|
920
|
+
f"The number of blocks ({len(block_names)}), "
|
|
921
|
+
f"datafile ({len(datafiles)}) and keypurpose ({len(keypurposes)}) "
|
|
922
|
+
"should be the same."
|
|
923
|
+
)
|
|
924
|
+
|
|
925
|
+
return block_names, datafiles, keypurposes
|
|
926
|
+
|
|
927
|
+
|
|
928
|
+
def _split_multiblock_key(
|
|
929
|
+
efuses, block_names, datafiles, keypurposes, base_keypurpose="XTS_AES_256_KEY"
|
|
930
|
+
):
|
|
931
|
+
"""Helper method to split 512-bit key into two 256-bit keys"""
|
|
932
|
+
|
|
933
|
+
keypurpose_list = list(keypurposes)
|
|
934
|
+
datafile_list = list(datafiles)
|
|
935
|
+
block_name_list = list(block_names)
|
|
936
|
+
|
|
937
|
+
i = keypurpose_list.index(base_keypurpose)
|
|
938
|
+
block_name = block_name_list[i]
|
|
939
|
+
|
|
940
|
+
block_num = efuses.get_index_block_by_name(block_name)
|
|
941
|
+
block = efuses.blocks[block_num]
|
|
942
|
+
|
|
943
|
+
data = datafile_list[i].read()
|
|
944
|
+
if len(data) != 64:
|
|
945
|
+
raise esptool.FatalError(
|
|
946
|
+
f"Incorrect key file size {len(data)}, {base_keypurpose} "
|
|
947
|
+
"should be 64 bytes"
|
|
948
|
+
)
|
|
949
|
+
|
|
950
|
+
key_block_2 = _get_next_key_block(efuses, block, block_name_list)
|
|
951
|
+
if not key_block_2:
|
|
952
|
+
raise esptool.FatalError(f"{base_keypurpose} requires two free keyblocks")
|
|
953
|
+
|
|
954
|
+
postfix = (
|
|
955
|
+
["_1", "_2"] if base_keypurpose.startswith("XTS_AES_256") else ["_H", "_L"]
|
|
956
|
+
)
|
|
957
|
+
keypurpose_list[i] = f"{base_keypurpose}{postfix[0]}"
|
|
958
|
+
datafile_list[i] = io.BytesIO(data[:32])
|
|
959
|
+
block_name_list[i] = block_name
|
|
960
|
+
|
|
961
|
+
keypurpose_list.insert(i + 1, f"{base_keypurpose}{postfix[1]}")
|
|
962
|
+
datafile_list.insert(i + 1, io.BytesIO(data[32:]))
|
|
963
|
+
block_name_list.insert(i + 1, key_block_2.name)
|
|
964
|
+
|
|
965
|
+
return block_name_list, datafile_list, keypurpose_list
|
|
@@ -450,5 +450,6 @@ class EfuseKeyPurposeField(EfuseField):
|
|
|
450
450
|
raw_val = int(self.check_format(str(new_value)))
|
|
451
451
|
str_new_value = self.get_name(raw_val)
|
|
452
452
|
if self.name == "KEY_PURPOSE_5" and str_new_value.startswith("XTS_AES"):
|
|
453
|
+
# see SOC_EFUSE_BLOCK9_KEY_PURPOSE_QUIRK in esp-idf
|
|
453
454
|
raise esptool.FatalError(f"{self.name} can not have {str_new_value} key due to a hardware bug (please see TRM for more details)")
|
|
454
455
|
return super(EfuseKeyPurposeField, self).save(raw_val)
|
|
@@ -26,6 +26,7 @@ from ..base_operations import (
|
|
|
26
26
|
read_protect_efuse,
|
|
27
27
|
summary,
|
|
28
28
|
write_protect_efuse,
|
|
29
|
+
adjust_key_data_for_blocks,
|
|
29
30
|
)
|
|
30
31
|
|
|
31
32
|
|
|
@@ -224,15 +225,12 @@ def burn_key(esp, efuses, args, digest=None):
|
|
|
224
225
|
0 : len([name for name in args.keypurpose if name is not None]) :
|
|
225
226
|
]
|
|
226
227
|
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
"should be the same."
|
|
234
|
-
% (len(block_name_list), len(datafile_list), len(keypurpose_list))
|
|
235
|
-
)
|
|
228
|
+
block_name_list, datafile_list, keypurpose_list = adjust_key_data_for_blocks(
|
|
229
|
+
efuses,
|
|
230
|
+
block_name_list,
|
|
231
|
+
datafile_list,
|
|
232
|
+
keypurpose_list,
|
|
233
|
+
)
|
|
236
234
|
|
|
237
235
|
print("Burn keys to blocks:")
|
|
238
236
|
for block_name, datafile, keypurpose in zip(
|
|
@@ -8,7 +8,7 @@ import binascii
|
|
|
8
8
|
import struct
|
|
9
9
|
import sys
|
|
10
10
|
import time
|
|
11
|
-
|
|
11
|
+
from typing import List, Tuple, Optional
|
|
12
12
|
from bitstring import BitArray
|
|
13
13
|
|
|
14
14
|
import esptool
|
|
@@ -403,10 +403,12 @@ class EfuseMacField(EfuseField):
|
|
|
403
403
|
|
|
404
404
|
# fmt: off
|
|
405
405
|
class EfuseKeyPurposeField(EfuseField):
|
|
406
|
-
|
|
406
|
+
key_purpose_len = 5 # bits for key purpose
|
|
407
|
+
KeyPurposeType = Tuple[str, int, Optional[str], Optional[str], str]
|
|
408
|
+
KEY_PURPOSES: List[KeyPurposeType] = [
|
|
407
409
|
("USER", 0, None, None, "no_need_rd_protect"), # User purposes (software-only use)
|
|
408
|
-
("ECDSA_KEY", 1, None, "Reverse", "need_rd_protect"), # ECDSA key P256
|
|
409
410
|
("ECDSA_KEY_P256", 1, None, "Reverse", "need_rd_protect"), # ECDSA key P256
|
|
411
|
+
("ECDSA_KEY", 1, None, "Reverse", "need_rd_protect"), # ECDSA key P256
|
|
410
412
|
("RESERVED", 1, None, None, "no_need_rd_protect"), # Reserved
|
|
411
413
|
("XTS_AES_256_KEY_1", 2, None, "Reverse", "need_rd_protect"), # XTS_AES_256_KEY_1 (flash/PSRAM encryption)
|
|
412
414
|
("XTS_AES_256_KEY_2", 3, None, "Reverse", "need_rd_protect"), # XTS_AES_256_KEY_2 (flash/PSRAM encryption)
|
|
@@ -422,12 +424,21 @@ class EfuseKeyPurposeField(EfuseField):
|
|
|
422
424
|
("KM_INIT_KEY", 12, None, None, "need_rd_protect"), # init key that is used for the generation of AES/ECDSA key
|
|
423
425
|
("XTS_AES_256_PSRAM_KEY_1", 13, None, "Reverse", "need_rd_protect"), # XTS_AES_256_PSRAM_KEY_1 (PSRAM encryption)
|
|
424
426
|
("XTS_AES_256_PSRAM_KEY_2", 14, None, "Reverse", "need_rd_protect"), # XTS_AES_256_PSRAM_KEY_1 (PSRAM encryption)
|
|
425
|
-
|
|
427
|
+
("XTS_AES_256_PSRAM_KEY", -2, "VIRTUAL", None, "no_need_rd_protect"), # Virtual purpose splits to XTS_AES_256_PSRAM_KEY_1 and XTS_AES_256_PSRAM_KEY_1
|
|
426
428
|
("XTS_AES_128_PSRAM_KEY", 15, None, "Reverse", "need_rd_protect"), # XTS_AES_128_PSRAM_KEY (PSRAM encryption)
|
|
427
429
|
("ECDSA_KEY_P192", 16, None, "Reverse", "need_rd_protect"), # ECDSA key P192
|
|
428
430
|
("ECDSA_KEY_P384_L", 17, None, "Reverse", "need_rd_protect"), # ECDSA key P384 low
|
|
429
431
|
("ECDSA_KEY_P384_H", 18, None, "Reverse", "need_rd_protect"), # ECDSA key P384 high
|
|
432
|
+
("ECDSA_KEY_P384", -3, "VIRTUAL", None, "need_rd_protect"), # Virtual purpose splits to ECDSA_KEY_P384_L and ECDSA_KEY_P384_H
|
|
430
433
|
]
|
|
434
|
+
CUSTOM_KEY_PURPOSES: List[KeyPurposeType] = []
|
|
435
|
+
for id in range(0, 1 << key_purpose_len):
|
|
436
|
+
if id not in [p[1] for p in KEY_PURPOSES]:
|
|
437
|
+
CUSTOM_KEY_PURPOSES.append((f"CUSTOM_{id}", id, None, None, "no_need_rd_protect"))
|
|
438
|
+
CUSTOM_KEY_PURPOSES.append((f"CUSTOM_DIGEST_{id}", id, "DIGEST", None, "no_need_rd_protect"))
|
|
439
|
+
CUSTOM_KEY_PURPOSES.append(("CUSTOM_MAX", (1 << key_purpose_len) - 1, None, None, "no_need_rd_protect"))
|
|
440
|
+
CUSTOM_KEY_PURPOSES.append(("CUSTOM_DIGEST_MAX", (1 << key_purpose_len) - 1, "DIGEST", None, "no_need_rd_protect"))
|
|
441
|
+
KEY_PURPOSES += CUSTOM_KEY_PURPOSES
|
|
431
442
|
# fmt: on
|
|
432
443
|
KEY_PURPOSES_NAME = [name[0] for name in KEY_PURPOSES]
|
|
433
444
|
DIGEST_KEY_PURPOSES = [name[0] for name in KEY_PURPOSES if name[2] == "DIGEST"]
|
|
@@ -470,7 +481,4 @@ class EfuseKeyPurposeField(EfuseField):
|
|
|
470
481
|
|
|
471
482
|
def save(self, new_value):
|
|
472
483
|
raw_val = int(self.check_format(str(new_value)))
|
|
473
|
-
str_new_value = self.get_name(raw_val)
|
|
474
|
-
if self.name == "KEY_PURPOSE_5" and str_new_value.startswith("XTS_AES"):
|
|
475
|
-
raise esptool.FatalError(f"{self.name} can not have {str_new_value} key due to a hardware bug (please see TRM for more details)")
|
|
476
484
|
return super(EfuseKeyPurposeField, self).save(raw_val)
|
|
@@ -0,0 +1,390 @@
|
|
|
1
|
+
# This file includes the operations with eFuses for ESP32-C5 chip
|
|
2
|
+
#
|
|
3
|
+
# SPDX-FileCopyrightText: 2024 Espressif Systems (Shanghai) CO LTD
|
|
4
|
+
#
|
|
5
|
+
# SPDX-License-Identifier: GPL-2.0-or-later
|
|
6
|
+
|
|
7
|
+
import argparse
|
|
8
|
+
import os # noqa: F401. It is used in IDF scripts
|
|
9
|
+
import traceback
|
|
10
|
+
|
|
11
|
+
import espsecure
|
|
12
|
+
|
|
13
|
+
import esptool
|
|
14
|
+
|
|
15
|
+
from . import fields
|
|
16
|
+
from .. import util
|
|
17
|
+
from ..base_operations import (
|
|
18
|
+
add_common_commands,
|
|
19
|
+
add_force_write_always,
|
|
20
|
+
add_show_sensitive_info_option,
|
|
21
|
+
burn_bit,
|
|
22
|
+
burn_block_data,
|
|
23
|
+
burn_efuse,
|
|
24
|
+
check_error,
|
|
25
|
+
dump,
|
|
26
|
+
read_protect_efuse,
|
|
27
|
+
summary,
|
|
28
|
+
write_protect_efuse,
|
|
29
|
+
adjust_key_data_for_blocks,
|
|
30
|
+
)
|
|
31
|
+
|
|
32
|
+
|
|
33
|
+
def protect_options(p):
|
|
34
|
+
p.add_argument(
|
|
35
|
+
"--no-write-protect",
|
|
36
|
+
help="Disable write-protecting of the key. The key remains writable. "
|
|
37
|
+
"(The keys use the RS coding scheme that does not support "
|
|
38
|
+
"post-write data changes. Forced write can damage RS encoding bits.) "
|
|
39
|
+
"The write-protecting of keypurposes does not depend on the option, "
|
|
40
|
+
"it will be set anyway.",
|
|
41
|
+
action="store_true",
|
|
42
|
+
)
|
|
43
|
+
p.add_argument(
|
|
44
|
+
"--no-read-protect",
|
|
45
|
+
help="Disable read-protecting of the key. The key remains readable software."
|
|
46
|
+
"The key with keypurpose[USER, RESERVED and *_DIGEST] "
|
|
47
|
+
"will remain readable anyway. For the rest keypurposes the read-protection "
|
|
48
|
+
"will be defined the option (Read-protect by default).",
|
|
49
|
+
action="store_true",
|
|
50
|
+
)
|
|
51
|
+
|
|
52
|
+
|
|
53
|
+
def add_commands(subparsers, efuses):
|
|
54
|
+
add_common_commands(subparsers, efuses)
|
|
55
|
+
burn_key = subparsers.add_parser(
|
|
56
|
+
"burn_key", help="Burn the key block with the specified name"
|
|
57
|
+
)
|
|
58
|
+
protect_options(burn_key)
|
|
59
|
+
add_force_write_always(burn_key)
|
|
60
|
+
add_show_sensitive_info_option(burn_key)
|
|
61
|
+
burn_key.add_argument(
|
|
62
|
+
"block",
|
|
63
|
+
help="Key block to burn",
|
|
64
|
+
action="append",
|
|
65
|
+
choices=efuses.BLOCKS_FOR_KEYS,
|
|
66
|
+
)
|
|
67
|
+
burn_key.add_argument(
|
|
68
|
+
"keyfile",
|
|
69
|
+
help="File containing 256 bits of binary key data. For the ECDSA_KEY purpose use PEM file.",
|
|
70
|
+
action="append",
|
|
71
|
+
type=argparse.FileType("rb"),
|
|
72
|
+
)
|
|
73
|
+
burn_key.add_argument(
|
|
74
|
+
"keypurpose",
|
|
75
|
+
help="Purpose to set.",
|
|
76
|
+
action="append",
|
|
77
|
+
choices=fields.EfuseKeyPurposeField.KEY_PURPOSES_NAME,
|
|
78
|
+
)
|
|
79
|
+
for _ in efuses.BLOCKS_FOR_KEYS:
|
|
80
|
+
burn_key.add_argument(
|
|
81
|
+
"block",
|
|
82
|
+
help="Key block to burn",
|
|
83
|
+
nargs="?",
|
|
84
|
+
action="append",
|
|
85
|
+
metavar="BLOCK",
|
|
86
|
+
choices=efuses.BLOCKS_FOR_KEYS,
|
|
87
|
+
)
|
|
88
|
+
burn_key.add_argument(
|
|
89
|
+
"keyfile",
|
|
90
|
+
help="File containing 256 bits of binary key data. For the ECDSA_KEY purpose use PEM file.",
|
|
91
|
+
nargs="?",
|
|
92
|
+
action="append",
|
|
93
|
+
metavar="KEYFILE",
|
|
94
|
+
type=argparse.FileType("rb"),
|
|
95
|
+
)
|
|
96
|
+
burn_key.add_argument(
|
|
97
|
+
"keypurpose",
|
|
98
|
+
help="Purpose to set.",
|
|
99
|
+
nargs="?",
|
|
100
|
+
action="append",
|
|
101
|
+
metavar="KEYPURPOSE",
|
|
102
|
+
choices=fields.EfuseKeyPurposeField.KEY_PURPOSES_NAME,
|
|
103
|
+
)
|
|
104
|
+
|
|
105
|
+
burn_key_digest = subparsers.add_parser(
|
|
106
|
+
"burn_key_digest",
|
|
107
|
+
help="Parse a RSA public key and burn the digest to key efuse block",
|
|
108
|
+
)
|
|
109
|
+
protect_options(burn_key_digest)
|
|
110
|
+
add_force_write_always(burn_key_digest)
|
|
111
|
+
add_show_sensitive_info_option(burn_key_digest)
|
|
112
|
+
burn_key_digest.add_argument(
|
|
113
|
+
"block",
|
|
114
|
+
help="Key block to burn",
|
|
115
|
+
action="append",
|
|
116
|
+
choices=efuses.BLOCKS_FOR_KEYS,
|
|
117
|
+
)
|
|
118
|
+
burn_key_digest.add_argument(
|
|
119
|
+
"keyfile",
|
|
120
|
+
help="Key file to digest (PEM format)",
|
|
121
|
+
action="append",
|
|
122
|
+
type=argparse.FileType("rb"),
|
|
123
|
+
)
|
|
124
|
+
burn_key_digest.add_argument(
|
|
125
|
+
"keypurpose",
|
|
126
|
+
help="Purpose to set.",
|
|
127
|
+
action="append",
|
|
128
|
+
choices=fields.EfuseKeyPurposeField.DIGEST_KEY_PURPOSES,
|
|
129
|
+
)
|
|
130
|
+
for _ in efuses.BLOCKS_FOR_KEYS:
|
|
131
|
+
burn_key_digest.add_argument(
|
|
132
|
+
"block",
|
|
133
|
+
help="Key block to burn",
|
|
134
|
+
nargs="?",
|
|
135
|
+
action="append",
|
|
136
|
+
metavar="BLOCK",
|
|
137
|
+
choices=efuses.BLOCKS_FOR_KEYS,
|
|
138
|
+
)
|
|
139
|
+
burn_key_digest.add_argument(
|
|
140
|
+
"keyfile",
|
|
141
|
+
help="Key file to digest (PEM format)",
|
|
142
|
+
nargs="?",
|
|
143
|
+
action="append",
|
|
144
|
+
metavar="KEYFILE",
|
|
145
|
+
type=argparse.FileType("rb"),
|
|
146
|
+
)
|
|
147
|
+
burn_key_digest.add_argument(
|
|
148
|
+
"keypurpose",
|
|
149
|
+
help="Purpose to set.",
|
|
150
|
+
nargs="?",
|
|
151
|
+
action="append",
|
|
152
|
+
metavar="KEYPURPOSE",
|
|
153
|
+
choices=fields.EfuseKeyPurposeField.DIGEST_KEY_PURPOSES,
|
|
154
|
+
)
|
|
155
|
+
|
|
156
|
+
p = subparsers.add_parser(
|
|
157
|
+
"set_flash_voltage",
|
|
158
|
+
help="Permanently set the internal flash voltage regulator "
|
|
159
|
+
"to either 1.8V, 3.3V or OFF. "
|
|
160
|
+
"This means GPIO45 can be high or low at reset without "
|
|
161
|
+
"changing the flash voltage.",
|
|
162
|
+
)
|
|
163
|
+
p.add_argument("voltage", help="Voltage selection", choices=["1.8V", "3.3V", "OFF"])
|
|
164
|
+
|
|
165
|
+
p = subparsers.add_parser(
|
|
166
|
+
"burn_custom_mac", help="Burn a 48-bit Custom MAC Address to EFUSE BLOCK3."
|
|
167
|
+
)
|
|
168
|
+
p.add_argument(
|
|
169
|
+
"mac",
|
|
170
|
+
help="Custom MAC Address to burn given in hexadecimal format with bytes "
|
|
171
|
+
"separated by colons (e.g. AA:CD:EF:01:02:03).",
|
|
172
|
+
type=fields.base_fields.CheckArgValue(efuses, "CUSTOM_MAC"),
|
|
173
|
+
)
|
|
174
|
+
add_force_write_always(p)
|
|
175
|
+
|
|
176
|
+
p = subparsers.add_parser("get_custom_mac", help="Prints the Custom MAC Address.")
|
|
177
|
+
|
|
178
|
+
|
|
179
|
+
def burn_custom_mac(esp, efuses, args):
|
|
180
|
+
efuses["CUSTOM_MAC"].save(args.mac)
|
|
181
|
+
if not efuses.burn_all(check_batch_mode=True):
|
|
182
|
+
return
|
|
183
|
+
get_custom_mac(esp, efuses, args)
|
|
184
|
+
print("Successful")
|
|
185
|
+
|
|
186
|
+
|
|
187
|
+
def get_custom_mac(esp, efuses, args):
|
|
188
|
+
print("Custom MAC Address: {}".format(efuses["CUSTOM_MAC"].get()))
|
|
189
|
+
|
|
190
|
+
|
|
191
|
+
def set_flash_voltage(esp, efuses, args):
|
|
192
|
+
raise esptool.FatalError("set_flash_voltage is not supported!")
|
|
193
|
+
|
|
194
|
+
|
|
195
|
+
def adc_info(esp, efuses, args):
|
|
196
|
+
print("Block version:", efuses.get_block_version())
|
|
197
|
+
if efuses.get_block_version() >= 1:
|
|
198
|
+
for efuse in efuses:
|
|
199
|
+
if efuse.category == "calibration":
|
|
200
|
+
print(f"{efuse.name:<30} = ", efuses[efuse.name].get())
|
|
201
|
+
|
|
202
|
+
|
|
203
|
+
def burn_key(esp, efuses, args, digest=None):
|
|
204
|
+
if digest is None:
|
|
205
|
+
datafile_list = args.keyfile[
|
|
206
|
+
0 : len([name for name in args.keyfile if name is not None]) :
|
|
207
|
+
]
|
|
208
|
+
else:
|
|
209
|
+
datafile_list = digest[0 : len([name for name in digest if name is not None]) :]
|
|
210
|
+
efuses.force_write_always = args.force_write_always
|
|
211
|
+
block_name_list = args.block[
|
|
212
|
+
0 : len([name for name in args.block if name is not None]) :
|
|
213
|
+
]
|
|
214
|
+
keypurpose_list = args.keypurpose[
|
|
215
|
+
0 : len([name for name in args.keypurpose if name is not None]) :
|
|
216
|
+
]
|
|
217
|
+
|
|
218
|
+
block_name_list, datafile_list, keypurpose_list = adjust_key_data_for_blocks(
|
|
219
|
+
efuses,
|
|
220
|
+
block_name_list,
|
|
221
|
+
datafile_list,
|
|
222
|
+
keypurpose_list,
|
|
223
|
+
)
|
|
224
|
+
|
|
225
|
+
print("Burn keys to blocks:")
|
|
226
|
+
for block_name, datafile, keypurpose in zip(
|
|
227
|
+
block_name_list, datafile_list, keypurpose_list
|
|
228
|
+
):
|
|
229
|
+
efuse = None
|
|
230
|
+
for block in efuses.blocks:
|
|
231
|
+
if block_name == block.name or block_name in block.alias:
|
|
232
|
+
efuse = efuses[block.name]
|
|
233
|
+
if efuse is None:
|
|
234
|
+
raise esptool.FatalError("Unknown block name - %s" % (block_name))
|
|
235
|
+
num_bytes = efuse.bit_len // 8
|
|
236
|
+
|
|
237
|
+
block_num = efuses.get_index_block_by_name(block_name)
|
|
238
|
+
block = efuses.blocks[block_num]
|
|
239
|
+
|
|
240
|
+
if digest is None:
|
|
241
|
+
data = datafile.read()
|
|
242
|
+
else:
|
|
243
|
+
data = datafile
|
|
244
|
+
|
|
245
|
+
print(" - %s" % (efuse.name), end=" ")
|
|
246
|
+
revers_msg = None
|
|
247
|
+
if efuses[block.key_purpose_name].need_reverse(keypurpose):
|
|
248
|
+
revers_msg = f"\tReversing byte order for {keypurpose} hardware peripheral"
|
|
249
|
+
data = data[::-1]
|
|
250
|
+
print(
|
|
251
|
+
"-> [{}]".format(
|
|
252
|
+
util.hexify(data, " ")
|
|
253
|
+
if args.show_sensitive_info
|
|
254
|
+
else " ".join(["??"] * len(data))
|
|
255
|
+
)
|
|
256
|
+
)
|
|
257
|
+
if revers_msg:
|
|
258
|
+
print(revers_msg)
|
|
259
|
+
if len(data) != num_bytes:
|
|
260
|
+
raise esptool.FatalError(
|
|
261
|
+
"Incorrect key file size %d. Key file must be %d bytes (%d bits) "
|
|
262
|
+
"of raw binary key data." % (len(data), num_bytes, num_bytes * 8)
|
|
263
|
+
)
|
|
264
|
+
|
|
265
|
+
if efuses[block.key_purpose_name].need_rd_protect(keypurpose):
|
|
266
|
+
read_protect = False if args.no_read_protect else True
|
|
267
|
+
else:
|
|
268
|
+
read_protect = False
|
|
269
|
+
write_protect = not args.no_write_protect
|
|
270
|
+
|
|
271
|
+
# using efuse instead of a block gives the advantage of checking it as the whole field.
|
|
272
|
+
efuse.save(data)
|
|
273
|
+
|
|
274
|
+
disable_wr_protect_key_purpose = False
|
|
275
|
+
if efuses[block.key_purpose_name].get() != keypurpose:
|
|
276
|
+
if efuses[block.key_purpose_name].is_writeable():
|
|
277
|
+
print(
|
|
278
|
+
"\t'%s': '%s' -> '%s'."
|
|
279
|
+
% (
|
|
280
|
+
block.key_purpose_name,
|
|
281
|
+
efuses[block.key_purpose_name].get(),
|
|
282
|
+
keypurpose,
|
|
283
|
+
)
|
|
284
|
+
)
|
|
285
|
+
efuses[block.key_purpose_name].save(keypurpose)
|
|
286
|
+
disable_wr_protect_key_purpose = True
|
|
287
|
+
else:
|
|
288
|
+
raise esptool.FatalError(
|
|
289
|
+
"It is not possible to change '%s' to '%s' "
|
|
290
|
+
"because write protection bit is set."
|
|
291
|
+
% (block.key_purpose_name, keypurpose)
|
|
292
|
+
)
|
|
293
|
+
else:
|
|
294
|
+
print("\t'%s' is already '%s'." % (block.key_purpose_name, keypurpose))
|
|
295
|
+
if efuses[block.key_purpose_name].is_writeable():
|
|
296
|
+
disable_wr_protect_key_purpose = True
|
|
297
|
+
|
|
298
|
+
if disable_wr_protect_key_purpose:
|
|
299
|
+
print("\tDisabling write to '%s'." % block.key_purpose_name)
|
|
300
|
+
efuses[block.key_purpose_name].disable_write()
|
|
301
|
+
|
|
302
|
+
if read_protect:
|
|
303
|
+
print("\tDisabling read to key block")
|
|
304
|
+
efuse.disable_read()
|
|
305
|
+
|
|
306
|
+
if write_protect:
|
|
307
|
+
print("\tDisabling write to key block")
|
|
308
|
+
efuse.disable_write()
|
|
309
|
+
print("")
|
|
310
|
+
|
|
311
|
+
if not write_protect:
|
|
312
|
+
print("Keys will remain writeable (due to --no-write-protect)")
|
|
313
|
+
if args.no_read_protect:
|
|
314
|
+
print("Keys will remain readable (due to --no-read-protect)")
|
|
315
|
+
|
|
316
|
+
if not efuses.burn_all(check_batch_mode=True):
|
|
317
|
+
return
|
|
318
|
+
print("Successful")
|
|
319
|
+
|
|
320
|
+
|
|
321
|
+
def burn_key_digest(esp, efuses, args):
|
|
322
|
+
digest_list = []
|
|
323
|
+
datafile_list = args.keyfile[
|
|
324
|
+
0 : len([name for name in args.keyfile if name is not None]) :
|
|
325
|
+
]
|
|
326
|
+
block_list = args.block[
|
|
327
|
+
0 : len([block for block in args.block if block is not None]) :
|
|
328
|
+
]
|
|
329
|
+
for block_name, datafile in zip(block_list, datafile_list):
|
|
330
|
+
efuse = None
|
|
331
|
+
for block in efuses.blocks:
|
|
332
|
+
if block_name == block.name or block_name in block.alias:
|
|
333
|
+
efuse = efuses[block.name]
|
|
334
|
+
if efuse is None:
|
|
335
|
+
raise esptool.FatalError("Unknown block name - %s" % (block_name))
|
|
336
|
+
num_bytes = efuse.bit_len // 8
|
|
337
|
+
digest = espsecure._digest_sbv2_public_key(datafile)
|
|
338
|
+
if len(digest) != num_bytes:
|
|
339
|
+
raise esptool.FatalError(
|
|
340
|
+
"Incorrect digest size %d. Digest must be %d bytes (%d bits) "
|
|
341
|
+
"of raw binary key data." % (len(digest), num_bytes, num_bytes * 8)
|
|
342
|
+
)
|
|
343
|
+
digest_list.append(digest)
|
|
344
|
+
burn_key(esp, efuses, args, digest=digest_list)
|
|
345
|
+
|
|
346
|
+
|
|
347
|
+
def espefuse(esp, efuses, args, command):
|
|
348
|
+
parser = argparse.ArgumentParser()
|
|
349
|
+
subparsers = parser.add_subparsers(dest="operation")
|
|
350
|
+
add_commands(subparsers, efuses)
|
|
351
|
+
try:
|
|
352
|
+
cmd_line_args = parser.parse_args(command.split())
|
|
353
|
+
except SystemExit:
|
|
354
|
+
traceback.print_stack()
|
|
355
|
+
raise esptool.FatalError('"{}" - incorrect command'.format(command))
|
|
356
|
+
if cmd_line_args.operation == "execute_scripts":
|
|
357
|
+
configfiles = cmd_line_args.configfiles
|
|
358
|
+
index = cmd_line_args.index
|
|
359
|
+
# copy arguments from args to cmd_line_args
|
|
360
|
+
vars(cmd_line_args).update(vars(args))
|
|
361
|
+
if cmd_line_args.operation == "execute_scripts":
|
|
362
|
+
cmd_line_args.configfiles = configfiles
|
|
363
|
+
cmd_line_args.index = index
|
|
364
|
+
if cmd_line_args.operation is None:
|
|
365
|
+
parser.print_help()
|
|
366
|
+
parser.exit(1)
|
|
367
|
+
operation_func = globals()[cmd_line_args.operation]
|
|
368
|
+
# each 'operation' is a module-level function of the same name
|
|
369
|
+
operation_func(esp, efuses, cmd_line_args)
|
|
370
|
+
|
|
371
|
+
|
|
372
|
+
def execute_scripts(esp, efuses, args):
|
|
373
|
+
efuses.batch_mode_cnt += 1
|
|
374
|
+
del args.operation
|
|
375
|
+
scripts = args.scripts
|
|
376
|
+
del args.scripts
|
|
377
|
+
|
|
378
|
+
for file in scripts:
|
|
379
|
+
with open(file.name, "r") as file:
|
|
380
|
+
exec(compile(file.read(), file.name, "exec"))
|
|
381
|
+
|
|
382
|
+
if args.debug:
|
|
383
|
+
for block in efuses.blocks:
|
|
384
|
+
data = block.get_bitstring(from_read=False)
|
|
385
|
+
block.print_block(data, "regs_for_burn", args.debug)
|
|
386
|
+
|
|
387
|
+
efuses.batch_mode_cnt -= 1
|
|
388
|
+
if not efuses.burn_all(check_batch_mode=True):
|
|
389
|
+
return
|
|
390
|
+
print("Successful")
|