diff --git a/.github/pull_request_template.md b/.github/pull_request_template.md index 7685f2935..34be8e5f4 100644 --- a/.github/pull_request_template.md +++ b/.github/pull_request_template.md @@ -1,15 +1,20 @@ -(Please delete any lines which don't apply) - -# Description of change + # This change fixes the following bug(s): + # I have tested this change with the following hardware & software combinations: + -(Operating system(s), development board name(s), ESP8266 and/or ESP32.) +# I have run the esptool.py automated integration tests with this change and the above hardware: + diff --git a/.github/workflows/build_esptool.yml b/.github/workflows/build_esptool.yml index 380732915..1a833c956 100644 --- a/.github/workflows/build_esptool.yml +++ b/.github/workflows/build_esptool.yml @@ -1,6 +1,10 @@ name: Build esptool -on: [push, pull_request] +on: + workflow_dispatch: + push: + paths-ignore: + - '.github/**' # Ignore changes towards the .github directory jobs: build-esptool-binaries: @@ -8,21 +12,16 @@ jobs: runs-on: ${{ matrix.os }} strategy: matrix: - os: [macos-latest, ubuntu-latest, windows-latest] + os: [ubuntu-latest] include: - - os: macos-latest - TARGET: macos - SEPARATOR: ':' - os: ubuntu-latest TARGET: linux-amd64 SEPARATOR: ':' - - os: windows-latest - TARGET: win64 - EXTEN: .exe - SEPARATOR: ';' env: DISTPATH: esptool-${{ matrix.TARGET }} - STUBS_DIR: /esptool/targets/stub_flasher/ + STUBS_DIR: ./esptool/targets/stub_flasher/ + EFUSE_DIR: ./espefuse/efuse_defs/ + PIP_EXTRA_INDEX_URL: "https://dl.espressif.com/pypi" steps: - name: Checkout repository uses: actions/checkout@master @@ -35,23 +34,30 @@ jobs: python -m pip install --upgrade pip pip install pyinstaller pip install --user -e . + - name: Build stub + if: matrix.os == 'ubuntu-latest' + run: | + export TOOLCHAIN_DIR=$HOME/toolchain + export ESP8266_BINDIR=$TOOLCHAIN_DIR/xtensa-lx106-elf/bin + export ESP32_BINDIR=$TOOLCHAIN_DIR/xtensa-esp32-elf/bin + export ESP32S2_BINDIR=$TOOLCHAIN_DIR/xtensa-esp32s2-elf/bin + export ESP32S3_BINDIR=$TOOLCHAIN_DIR/xtensa-esp32s3-elf/bin + export ESP32C3_BINDIR=$TOOLCHAIN_DIR/riscv32-esp-elf/bin + export PATH=$PATH:$ESP8266_BINDIR:$ESP32_BINDIR:$ESP32S2_BINDIR:$ESP32S3_BINDIR:$ESP32C3_BINDIR + ./ci/setup_ci_build_env.sh + make -C flasher_stub V=1 + - name: Archive stubs artifact + if: matrix.os == 'ubuntu-latest' + uses: actions/upload-artifact@master + with: + name: stubs + path: /home/runner/work/esptool/esptool/flasher_stub/build - name: Build with PyInstaller run: | - pyinstaller --distpath ./${{ env.DISTPATH }} -F --icon=ci/espressif.ico --add-data=".${{ env.STUBS_DIR }}*.json${{ matrix.SEPARATOR }}${{ env.STUBS_DIR }}" esptool.py - pyinstaller --distpath ./${{ env.DISTPATH }} -F --icon=ci/espressif.ico espefuse.py + pyinstaller --distpath ./${{ env.DISTPATH }} -F --icon=ci/espressif.ico --add-data="${{ env.STUBS_DIR }}*.json${{ matrix.SEPARATOR }}${{ env.STUBS_DIR }}" esptool.py + pyinstaller --distpath ./${{ env.DISTPATH }} -F --icon=ci/espressif.ico --add-data="${{ env.EFUSE_DIR }}*.yaml${{ matrix.SEPARATOR }}${{ env.EFUSE_DIR }}" espefuse.py pyinstaller --distpath ./${{ env.DISTPATH }} -F --icon=ci/espressif.ico espsecure.py pyinstaller --distpath ./${{ env.DISTPATH }} -F --icon=ci/espressif.ico esp_rfc2217_server.py - - name: Sign binaries - if: matrix.os == 'windows-latest' && github.event_name != 'pull_request' - env: - CERTIFICATE: ${{ secrets.CERTIFICATE }} - CERTIFICATE_PASSWORD: ${{ secrets.CERTIFICATE_PASSWORD }} - shell: pwsh - run: | - ./ci/Sign-File.ps1 -Path ./${{ env.DISTPATH }}/esptool.exe - ./ci/Sign-File.ps1 -Path ./${{ env.DISTPATH }}/espefuse.exe - ./ci/Sign-File.ps1 -Path ./${{ env.DISTPATH }}/espsecure.exe - ./ci/Sign-File.ps1 -Path ./${{ env.DISTPATH }}/esp_rfc2217_server.exe - name: Test binaries shell: bash run: | @@ -61,13 +67,40 @@ jobs: ./${{ env.DISTPATH }}/esp_rfc2217_server${{ matrix.EXTEN }} -h - name: Add license and readme shell: bash - run: mv LICENSE README.md ./${{ env.DISTPATH }} + run: cp LICENSE README.md ./${{ env.DISTPATH }} - name: Archive artifact uses: actions/upload-artifact@master with: name: ${{ env.DISTPATH }} path: ${{ env.DISTPATH }} + push_stubs: + name: Commit changed files + needs: build-esptool-binaries + runs-on: ubuntu-latest + steps: + - name: Checkout repository + uses: actions/checkout@master + with: + fetch-depth: 0 + - name: Download builded stubs + uses: actions/download-artifact@master + with: + name: stubs + path: ./mv_stubs + - name: Display structure of downloaded files + run: | + ls -R + - name: Move stubs in folder + run: | + rm ./esptool/targets/stub_flasher/* + cp -R ./mv_stubs/*.json ./esptool/targets/stub_flasher + ls -R ./esptool/targets/stub_flasher + rm -rf ./mv_stubs + - uses: stefanzweifel/git-auto-commit-action@v4 + with: + commit_message: Stubs updated + create_release: name: Create GitHub release if: startsWith(github.ref, 'refs/tags/') diff --git a/.github/workflows/dangerjs.yml b/.github/workflows/dangerjs.yml new file mode 100644 index 000000000..ab9f002a6 --- /dev/null +++ b/.github/workflows/dangerjs.yml @@ -0,0 +1,22 @@ +name: DangerJS Check +on: + pull_request_target: + types: [opened, edited, reopened, synchronize] + +permissions: + pull-requests: write + contents: write + +jobs: + pull-request-style-linter: + runs-on: ubuntu-latest + steps: + - name: Check out PR head + uses: actions/checkout@v3 + with: + ref: ${{ github.event.pull_request.head.sha }} + + - name: DangerJS pull request linter + uses: espressif/github-actions/danger_pr_review@master + env: + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} diff --git a/.github/workflows/dev_release_esptool_pypi.yml b/.github/workflows/dev_release_esptool_pypi.yml new file mode 100644 index 000000000..a443a1323 --- /dev/null +++ b/.github/workflows/dev_release_esptool_pypi.yml @@ -0,0 +1,42 @@ +# This workflow will upload an esptool Python package when a dev release tag (e.g. "v4.7.dev2") is pushed + +name: PyPI dev release + +on: + push: + tags: + - v*.*.dev* + +jobs: + build_and_upload: + + runs-on: ubuntu-latest + + if: startsWith(github.ref, 'refs/tags/') && contains(github.ref_name, 'dev') + + steps: + - uses: actions/checkout@master + - name: Set up Python 3.8 + uses: actions/setup-python@master + with: + python-version: '3.8' + - name: Install dependencies + run: | + python -m pip install --upgrade pip + python -m pip install twine setuptools + + - name: Create development release ${{ github.ref_name }} + env: + TWINE_USERNAME: __token__ + TWINE_PASSWORD: ${{ secrets.PYPI_PASSWORD }} + TWINE_NON_INTERACTIVE: true + run: | + DEV_VERSION=$(echo "${{ github.ref_name }}" | grep -oE 'dev[0-9]+' | sed 's/dev//') + python ci/patch_dev_release.py --dev-no ${DEV_VERSION} esptool/__init__.py + git diff + python -m pip download esptool==$(python setup.py -V) && echo "Version ${{ github.ref_name }} already published, skipping..." && exit 1 + + echo "Packaging and publishing new esptool development release: ${{ github.ref_name }}" + python setup.py sdist + tar -ztvf dist/* + twine upload dist/* diff --git a/.github/workflows/test_esptool.yml b/.github/workflows/test_esptool.yml deleted file mode 100644 index fb1947b35..000000000 --- a/.github/workflows/test_esptool.yml +++ /dev/null @@ -1,77 +0,0 @@ -name: Test esptool - -on: [push, pull_request] - -jobs: - test_esptool: - runs-on: ubuntu-latest - - strategy: - matrix: - python-version: ['3.7', '3.8', '3.9', '3.10'] - - steps: - - name: Checkout ref commit - uses: actions/checkout@master - - - name: Set up Python ${{ matrix.python-version }} - uses: actions/setup-python@master - with: - python-version: ${{ matrix.python-version }} - - - name: SoftHSM2 setup - run: | - sudo apt-get update - sudo apt-get install -y softhsm2 - sudo chmod -R a+rx /etc/softhsm - sudo chmod a+r /etc/softhsm/softhsm2.conf - sudo chown -R $(whoami) /var/lib/softhsm - ./ci/setup_softhsm2.sh || exit 1 - - - name: Test python components (fast) - run: | - python setup.py build - pip install --extra-index-url https://dl.espressif.com/pypi -e .[dev,hsm] - pytest test/test_imagegen.py - pytest test/test_espsecure.py - pytest test/test_espsecure_hsm.py - pytest test/test_merge_bin.py - pytest test/test_image_info.py - pytest test/test_modules.py - - - name: Check the installed versions can run - run: | - esptool.py --help - espefuse.py --help - espsecure.py --help - - - name: Build stub (Python 3.7 only) - if: matrix.python-version == 3.7 - run: | - export TOOLCHAIN_DIR=$HOME/toolchain - - export ESP8266_BINDIR=$TOOLCHAIN_DIR/xtensa-lx106-elf/bin - export ESP32_BINDIR=$TOOLCHAIN_DIR/xtensa-esp32-elf/bin - export ESP32S2_BINDIR=$TOOLCHAIN_DIR/xtensa-esp32s2-elf/bin - export ESP32S3_BINDIR=$TOOLCHAIN_DIR/xtensa-esp32s3-elf/bin - export ESP32C3_BINDIR=$TOOLCHAIN_DIR/riscv32-esp-elf/bin - - export PATH=$PATH:$ESP8266_BINDIR:$ESP32_BINDIR:$ESP32S2_BINDIR:$ESP32S3_BINDIR:$ESP32C3_BINDIR - - ./ci/setup_ci_build_env.sh - make -C flasher_stub V=1 - cd flasher_stub && python ./compare_stubs.py - - lint_esptool: - runs-on: ubuntu-latest - steps: - - name: Checkout - uses: actions/checkout@master - - - name: Lint with flake8 - run: | - pip install --extra-index-url https://dl.espressif.com/pypi -e .[dev] - python -m flake8 - - - name: Check formatting with Black - uses: psf/black@stable diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml deleted file mode 100644 index b631db632..000000000 --- a/.gitlab-ci.yml +++ /dev/null @@ -1,464 +0,0 @@ -# Gitlab CI config -# -# Note: When updating, please also update test_esptool.yml GH Actions workflow file -stages: - - test - - report - - build_docs - - deploy_docs - - deploy_development_package - -# cache the pip download directory in all jobs -variables: - PIP_CACHE_DIR: "$CI_PROJECT_DIR/.cache/pip" - PIP_EXTRA_INDEX_URL: "https://dl.espressif.com/pypi" - -cache: - paths: - - "$CI_PROJECT_DIR/.cache/pip" - -.test_template: &test_template - stage: test - image: python:3.7-bullseye - tags: - - host_test - dependencies: [] - before_script: - - pip install -e .[dev] --prefer-binary - -version_check: - <<: *test_template - only: - - tags - script: - - VERSION=$(esptool.py version | head -n 1) - - | - if [[ "$VERSION" != *"$CI_COMMIT_TAG" ]] - then - echo "Version number and git tag do not match!" - exit 1 - fi - -.host_tests_template: &host_tests_template - <<: *test_template - artifacts: - when: always - paths: - - "**/.coverage*" - - ".coverage*" - expire_in: 1 week - reports: - junit: test/report.xml - -host_tests: - <<: *host_tests_template - variables: - PYTHONPATH: "$PYTHONPATH:${CI_PROJECT_DIR}/test" - COVERAGE_PROCESS_START: "${CI_PROJECT_DIR}/test/.covconf" - PYTEST_ADDOPTS: "-sv --junitxml=test/report.xml --color=yes" - script: - - coverage run --parallel-mode -m pytest ${CI_PROJECT_DIR}/test/test_imagegen.py - - coverage run --parallel-mode -m pytest ${CI_PROJECT_DIR}/test/test_espsecure.py - - coverage run --parallel-mode -m pytest ${CI_PROJECT_DIR}/test/test_merge_bin.py - - coverage run --parallel-mode -m pytest ${CI_PROJECT_DIR}/test/test_image_info.py - - coverage run --parallel-mode -m pytest ${CI_PROJECT_DIR}/test/test_modules.py - - coverage run --parallel-mode -m pytest ${CI_PROJECT_DIR}/test/test_espefuse.py --chip esp32 - - coverage run --parallel-mode -m pytest ${CI_PROJECT_DIR}/test/test_espefuse.py --chip esp32c2 - - coverage run --parallel-mode -m pytest ${CI_PROJECT_DIR}/test/test_espefuse.py --chip esp32c3 - - coverage run --parallel-mode -m pytest ${CI_PROJECT_DIR}/test/test_espefuse.py --chip esp32s2 - - coverage run --parallel-mode -m pytest ${CI_PROJECT_DIR}/test/test_espefuse.py --chip esp32s3 - - coverage run --parallel-mode -m pytest ${CI_PROJECT_DIR}/test/test_espefuse.py --chip esp32s3beta2 - - coverage run --parallel-mode -m pytest ${CI_PROJECT_DIR}/test/test_espefuse.py --chip esp32h2beta1 - - coverage run --parallel-mode -m pytest ${CI_PROJECT_DIR}/test/test_espefuse.py --chip esp32c6 - - coverage run --parallel-mode -m pytest ${CI_PROJECT_DIR}/test/test_espefuse.py --chip esp32h2 - # some .coverage files in sub-directories are not collected on some runners, move them first - - find . -mindepth 2 -type f -name ".coverage*" -print -exec mv --backup=numbered {} . \; - -# A new job "host_test_hsm" is created for the test "test_espsecure_hsm.py" which runs an ubuntu image, -# because python-pkcs11 (v0.7.0) package is compiled using GLIBC_2.34 but docker image python:3.7-bullseye -# support versions only upto GLIBC_2.31. -host_tests_hsm: - <<: *host_tests_template - image: ubuntu:latest - variables: - COVERAGE_PROCESS_START: "${CI_PROJECT_DIR}/test/.covconf" - PYTEST_ADDOPTS: "-sv --junitxml=test/report.xml --color=yes" - before_script: - - apt-get update - - apt-get install -y python3 python3-pip softhsm2 - - ./ci/setup_softhsm2.sh || exit 1 - - pip3 install -e .[dev,hsm] --prefer-binary - script: - - coverage run --parallel-mode -m pytest ${CI_PROJECT_DIR}/test/test_espsecure_hsm.py - -check_python_style: - stage: test - image: python:3.7-bullseye - tags: - - host_test - artifacts: - reports: - codequality: code_quality_report.json - when: on_failure - script: - # This step installs any 'dev' dependencies (ie flake8, Black) - # The runner should cache the downloads, so still quite fast. - - pip install -e .[dev] --prefer-binary - - python -m flake8 --exit-zero --format gl-codeclimate --output-file code_quality_report.json - - python -m flake8 - - python -m black --check --diff . - -.run_esptool: &run_esptool | - esptool.py --help - espefuse.py --help - espsecure.py --help - python esptool.py --help - python espefuse.py --help - python espsecure.py --help - python -m esptool --help - python -m espefuse --help - python -m espsecure --help - -# Check all the scripts can run when installed, collect coverage -check_install_coverage: - <<: *test_template - artifacts: - when: always - paths: - - "**/.coverage*" - - ".coverage*" - expire_in: 1 week - script: - - coverage run --parallel-mode setup.py install - - coverage run --parallel-mode esptool.py --help - - coverage run --parallel-mode espefuse.py --help - - coverage run --parallel-mode espsecure.py --help - - *run_esptool - -# Check all the scripts can run when installed -check_install: - <<: *test_template - before_script: - - pip install . - script: - - *run_esptool - -# Check all the scripts can run when installed in editable mode -check_install_editable: - <<: *test_template - before_script: - - pip install -e . - script: - - *run_esptool - -# Check all the scripts can run when installed in Python user install directory -check_install_system: - <<: *test_template - before_script: - - pip install --user . - script: - - python esptool.py --help - - python espefuse.py --help - - python espsecure.py --help - - python -m esptool --help - - python -m espefuse --help - - python -m espsecure --help - -# Check all the scripts can run when installed in virtual environment -check_install_venv: - <<: *test_template - before_script: - - python -m venv test_env - - source test_env/bin/activate - - python -m pip install . - script: - - *run_esptool - -# Check the stub can build and that a stub built in CI has the same contents -# as the one embedded in esptool -check_stub_build: - <<: *test_template - artifacts: - when: always - paths: - - flasher_stub/build/ - - "**/.coverage*" - - ".coverage*" - expire_in: 1 week - variables: - TOOLCHAIN_DIR: "/root/.espressif/dist" - - ESP8266_BINDIR: "${TOOLCHAIN_DIR}/xtensa-lx106-elf/bin" - ESP32_BINDIR: "${TOOLCHAIN_DIR}/xtensa-esp32-elf/bin" - ESP32S2_BINDIR: "${TOOLCHAIN_DIR}/xtensa-esp32s2-elf/bin" - ESP32S3_BINDIR: "${TOOLCHAIN_DIR}/xtensa-esp32s3-elf/bin" - ESP32C3_BINDIR: "${TOOLCHAIN_DIR}/riscv32-esp-elf/bin" - - TOOLCHAIN_PATHS: "${ESP8266_BINDIR}:${ESP32_BINDIR}:${ESP32S2_BINDIR}:${ESP32S3_BINDIR}:${ESP32C3_BINDIR}" - script: - - ./ci/setup_ci_build_env.sh - - make -C flasher_stub V=1 PATH="${TOOLCHAIN_PATHS}:${PATH}" - - cd flasher_stub && coverage run --parallel-mode ./compare_stubs.py - -.target_esptool_test: - stage: test - image: python:3.7-bullseye - variables: - PYTHONPATH: "$PYTHONPATH:${CI_PROJECT_DIR}/test" - COVERAGE_PROCESS_START: "${CI_PROJECT_DIR}/test/.covconf" - PYTEST_ADDOPTS: "-sv --junitxml=test/report.xml --color=yes" - before_script: - - pip install -e .[dev] --prefer-binary - artifacts: - reports: - junit: test/report.xml - when: always - paths: - - test/*.out - - "**/.coverage*" - - ".coverage*" - expire_in: 1 week - -# ESP8266 -target_esp8266: - extends: .target_esptool_test - tags: - - esptool_esp8266_target - script: - - coverage run --parallel-mode -m pytest ${CI_PROJECT_DIR}/test/test_esptool.py --port /dev/serial_ports/ESP8266 --chip esp8266 --baud 115200 - -# ESP32 -target_esp32: - extends: .target_esptool_test - tags: - - esptool_esp32_target - script: - # libffi (needed for espsecure) version keeps changing in python docker images, add a symlink to the installed version - - ln -sfn /usr/lib/arm-linux-gnueabihf/libffi.so.7.1.0 /usr/lib/arm-linux-gnueabihf/libffi.so.6 - - coverage run --parallel-mode -m pytest ${CI_PROJECT_DIR}/test/test_esptool.py --port /dev/serial_ports/ESP32 --chip esp32 --baud 115200 - -# ESP32S2 -target_esp32s2: - extends: .target_esptool_test - tags: - - esptool_esp32s2_target - script: - - coverage run --parallel-mode -m pytest ${CI_PROJECT_DIR}/test/test_esptool.py --port /dev/serial_ports/ESP32S2 --chip esp32s2 --baud 115200 - -target_esp32s2_usbcdc: - extends: .target_esptool_test - tags: - - esptool_esp32s2_cdc_target - script: - - coverage run --parallel-mode -m pytest ${CI_PROJECT_DIR}/test/test_esptool.py --port /dev/serial_ports/ESP32S2_USBCDC --chip esp32s2 --baud 115200 - -# ESP32C3 -target_esp32c3: - extends: .target_esptool_test - tags: - - esptool_esp32c3_target - script: - - coverage run --parallel-mode -m pytest ${CI_PROJECT_DIR}/test/test_esptool.py --port /dev/serial_ports/ESP32C3 --chip esp32c3 --baud 115200 - -target_esp32c3_jtag_serial: - extends: .target_esptool_test - tags: - - esptool_esp32c3_jtag_serial_target - script: - - coverage run --parallel-mode -m pytest ${CI_PROJECT_DIR}/test/test_esptool.py --port /dev/serial_ports/ESP32C3_JTAG_SERIAL --preload-port /dev/serial_ports/ESP32C3_PRELOAD --chip esp32c3 --baud 115200 - -# ESP32S3 -target_esp32s3: - extends: .target_esptool_test - tags: - - esptool_esp32s3_target - script: - - coverage run --parallel-mode -m pytest ${CI_PROJECT_DIR}/test/test_esptool.py --port /dev/serial_ports/ESP32S3 --chip esp32s3 --baud 115200 - -target_esp32s3_32MB: - extends: .target_esptool_test - tags: - - esptool_esp32s3_32MB_target - variables: - ESPTOOL_TEST_FLASH_SIZE: "32" - script: - - coverage run --parallel-mode -m pytest ${CI_PROJECT_DIR}/test/test_esptool.py --port /dev/serial_ports/ESP32S3_32MB --chip esp32s3 --baud 115200 - -target_esp32s3_usbcdc: - extends: .target_esptool_test - tags: - - esptool_esp32s3_cdc_target - script: - - coverage run --parallel-mode -m pytest ${CI_PROJECT_DIR}/test/test_esptool.py --port /dev/serial_ports/ESP32S3_USBCDC --chip esp32s3 --baud 115200 - -target_esp32s3_jtag_serial: - extends: .target_esptool_test - tags: - - esptool_esp32s3_jtag_serial_target - script: - - coverage run --parallel-mode -m pytest ${CI_PROJECT_DIR}/test/test_esptool.py --port /dev/serial_ports/ESP32S3_JTAG_SERIAL --preload-port /dev/serial_ports/ESP32S3_PRELOAD --chip esp32s3 --baud 115200 - -# ESP32C2 -target_esp32c2_40mhz: - extends: .target_esptool_test - tags: - - esptool_esp32c2_40mhz_target - script: - - coverage run --parallel-mode -m pytest ${CI_PROJECT_DIR}/test/test_esptool.py --port /dev/serial_ports/ESP32C2_40MHZ --chip esp32c2 --baud 115200 - -target_esp32c2_26mhz: - extends: .target_esptool_test - tags: - - esptool_esp32c2_26mhz_target - script: - - coverage run --parallel-mode -m pytest ${CI_PROJECT_DIR}/test/test_esptool.py --port /dev/serial_ports/ESP32C2_26MHZ --chip esp32c2 --baud 115200 - -# ESP32C6 -target_esp32c6: - extends: .target_esptool_test - tags: - - esptool_esp32c6_target - script: - - coverage run --parallel-mode -m pytest ${CI_PROJECT_DIR}/test/test_esptool.py --port /dev/serial_ports/ESP32C6 --chip esp32c6 --baud 115200 - -target_esp32c6_jtag_serial: - extends: .target_esptool_test - tags: - - esptool_esp32c6_jtag_serial_target - script: - - coverage run --parallel-mode -m pytest ${CI_PROJECT_DIR}/test/test_esptool.py --port /dev/serial_ports/ESP32C6_JTAG_SERIAL --preload-port /dev/serial_ports/ESP32C6_PRELOAD --chip esp32c6 --baud 115200 - -# ESP32H2 -target_esp32h2: - extends: .target_esptool_test - tags: - - esptool_esp32h2_target - script: - - coverage run --parallel-mode -m pytest ${CI_PROJECT_DIR}/test/test_esptool.py --port /dev/serial_ports/ESP32H2 --chip esp32h2 --baud 115200 - -target_esp32h2_jtag_serial: - extends: .target_esptool_test - tags: - - esptool_esp32h2_jtag_serial_target - script: - - coverage run --parallel-mode -m pytest ${CI_PROJECT_DIR}/test/test_esptool.py --port /dev/serial_ports/ESP32H2_JTAG_SERIAL --preload-port /dev/serial_ports/ESP32H2_PRELOAD --chip esp32h2 --baud 115200 - -combine_reports: - stage: report - image: python:3.7-bullseye - tags: - - host_test - artifacts: - reports: - coverage_report: - coverage_format: cobertura - path: cobertura_report.xml - when: always - paths: - - ".coverage*" - - cobertura_report.xml - - ./html_report/ - expire_in: 1 week - coverage: '/(?i)total.*? (100(?:\.0+)?\%|[1-9]?\d(?:\.\d+)?\%)$/' - variables: - LC_ALL: C.UTF-8 - before_script: - - pip install -e .[dev] --prefer-binary - script: - # all .coverage files in sub-directories are moved to the parent dir first - - find . -mindepth 2 -type f -name ".coverage*" -print -exec mv --backup=numbered {} . \; - - coverage combine - - coverage report --precision=2 - - coverage html -d html_report --precision=2 - - coverage xml -o cobertura_report.xml - -build_docs: - stage: build_docs - image: python:3.7-bullseye - tags: - - build_docs - only: - changes: - - "docs/**/*" - - "CONTRIBUTING.rst" - needs: [] - artifacts: - when: always - paths: - - docs/_build/*/*/*.txt - - docs/_build/*/*/html/* - expire_in: 4 days - script: - - cd docs - - pip install -r requirements.txt --prefer-binary - - build-docs -l en -t {esp8266,esp32,esp32s2,esp32c3,esp32s3} - -.deploy_docs_template: - stage: deploy_docs - image: python:3.7-bullseye - tags: - - deploy - needs: - - build_docs - only: - changes: - - "docs/**/*" - - "CONTRIBUTING.rst" - script: - - source ${CI_PROJECT_DIR}/docs/utils.sh - - add_doc_server_ssh_keys $DOCS_DEPLOY_PRIVATEKEY $DOCS_DEPLOY_SERVER $DOCS_DEPLOY_SERVER_USER - - export GIT_VER=$(git describe --always) - - pip install -r ${CI_PROJECT_DIR}/docs/requirements.txt --prefer-binary - - deploy-docs - -deploy_docs_preview: - extends: - - .deploy_docs_template - except: - refs: - - master - variables: - TYPE: "preview" - DOCS_BUILD_DIR: "${CI_PROJECT_DIR}/docs/_build/" - DOCS_DEPLOY_PRIVATEKEY: "$DOCS_DEPLOY_KEY" - DOCS_DEPLOY_SERVER: "$DOCS_SERVER" - DOCS_DEPLOY_SERVER_USER: "$DOCS_SERVER_USER" - DOCS_DEPLOY_PATH: "$DOCS_PATH" - DOCS_DEPLOY_URL_BASE: "https://$DOCS_PREVIEW_SERVER_URL/docs/esptool" - -deploy_docs_production: - extends: - - .deploy_docs_template - only: - refs: - - master - variables: - TYPE: "production" - DOCS_BUILD_DIR: "${CI_PROJECT_DIR}/docs/_build/" - DOCS_DEPLOY_PRIVATEKEY: "$DOCS_PROD_DEPLOY_KEY" - DOCS_DEPLOY_SERVER: "$DOCS_PROD_SERVER" - DOCS_DEPLOY_SERVER_USER: "$DOCS_PROD_SERVER_USER" - DOCS_DEPLOY_PATH: "$DOCS_PROD_PATH" - DOCS_DEPLOY_URL_BASE: "https://docs.espressif.com/projects/esptool" - -deploy_dev_package: - <<: *test_template - rules: - - if: $CI_DEV_PUBLISH != null && $CI_COMMIT_BRANCH == $CI_DEFAULT_BRANCH - variables: - TWINE_NON_INTERACTIVE: "true" - TWINE_USERNAME: __token__ - TWINE_PASSWORD: ${PYPI_ESPTOOL_TOKEN} - stage: deploy_development_package - dependencies: [] - script: - - python -m pip install --upgrade pip - - python -m pip install twine setuptools - - python ci/patch_dev_release.py --dev-no ${CI_DEV_PUBLISH} esptool/__init__.py - # check what has been changed with git - - git diff - - python setup.py sdist - # skip release if it has already been released (with failure) - - python -m pip download esptool==$(python setup.py -V) && exit 1 - - tar -ztvf dist/* - - python -m twine upload dist/* diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml deleted file mode 100644 index edf3b57c9..000000000 --- a/.pre-commit-config.yaml +++ /dev/null @@ -1,9 +0,0 @@ -repos: - - repo: https://github.com/PyCQA/flake8 - rev: 4.0.1 - hooks: - - id: flake8 - - repo: https://github.com/psf/black - rev: 22.3.0 - hooks: - - id: black diff --git a/CONTRIBUTING.rst b/CONTRIBUTING.rst index 415627def..6b9d5536e 100644 --- a/CONTRIBUTING.rst +++ b/CONTRIBUTING.rst @@ -78,15 +78,20 @@ Pre-commit checks `pre-commit `_ is a framework for managing pre-commit hooks. These hooks help to identify simple issues before committing code for review. -To use the tool, first install ``pre-commit`` and then the git hooks: +To use the tool, first install ``pre-commit``. Then enable the ``pre-commit`` and ``commit-msg`` git hooks: :: $ python -m pip install pre-commit - $ pre-commit install + $ pre-commit install -t pre-commit -t commit-msg On the first commit ``pre-commit`` will install the hooks, subsequent checks will be significantly faster. If an error is found an appropriate error message will be displayed. If the error was with ``black`` then the tool will fix them for you automatically. Review the changes and re-stage for commit if you are happy with them. +Conventional Commits +"""""""""""""""""""" + +``esptool.py`` complies with the `Conventional Commits standard `_. Every commit message is checked with `Conventional Precommit Linter `_, ensuring it adheres to the standard. + Flake8 """""" @@ -97,7 +102,7 @@ Black All files should be formatted using the `Black `_ auto-formatter. -``Black`` and ``flake8`` tools will be automatically run by ``pre-commit`` if that is configured. To check your code manually before submitting, run ``python -m flake8`` and ``black .`` (the tools are installed as part of the development requirements shown at the beginning of this document). +``Black``, ``flake8``, and ``Conventional Precommit Linter`` tools will be automatically run by ``pre-commit`` if that is configured. To check your code manually before submitting, run ``python -m flake8`` and ``black .`` (the tools are installed as part of the development requirements shown at the beginning of this document). When you submit a Pull Request, the GitHub Actions automated build system will run automated checks using these tools. @@ -115,6 +120,7 @@ The following tests run automatically by GitHub Actions for each Pull Request. Y * ``test_mergebin.py`` tests the ``merge_bin`` command * ``test_modules.py`` tests the modules used by ``esptool.py`` for regressions * ``test_espsecure.py`` tests ``espsecure.py`` functionality +* ``test_espsecure_hsm.py`` tests support of extarnal HSM signing in ``espsecure.py``. These tests require additional prerequisites, see ``SoftHSM2 setup`` in the `tests workflow definition `_ for more information. The following tests are not run automatically by GitHub Actions, because they need real connected hardware. Therefore, they need to be run locally in a command line: @@ -146,7 +152,7 @@ The following tests are not run automatically by GitHub Actions, but can be run Do not attempt to run these tests on real hardware! You risk damaging or destroying the ESP chip! -The whole test suite (without the tests needing an actual hardware) can be easily run with the following command in the esptool root folder: ``pytest --ignore=test/test_esptool.py`` +The whole test suite (without the tests needing an actual hardware or installation of additional prerequisites) can be easily run with the following command in the esptool root folder: ``pytest -m host_test`` Pull Request Process diff --git a/MANIFEST.in b/MANIFEST.in deleted file mode 100644 index 0f6d078f6..000000000 --- a/MANIFEST.in +++ /dev/null @@ -1,10 +0,0 @@ -include README.md -include LICENSE -include esptool/targets/stub_flasher/*.json -# sdist includes test/test*.py by default, but esptool.py tests -# are so far only intended to run from the git repo itself -prune test -prune flasher_stub -prune .github -prune docs -exclude .git* diff --git a/docs/README.md b/docs/README.md deleted file mode 100644 index e9f747d07..000000000 --- a/docs/README.md +++ /dev/null @@ -1,17 +0,0 @@ -# Documentation Source Folder - -This folder contains source files of **esptool documentation**. - -The sources do not render well in GitHub and some information is not visible at all. - -Use actual documentation generated within about 20 minutes on each commit: - -# Hosted Documentation - -* English: https://docs.espressif.com/projects/esptool/ - -The above URL is for the master branch latest version. Click the drop-down in the bottom left to choose a particular version. - -# Building Documentation - -The documentation is built using the python package `esp-docs`, which can be installed by running `pip install esp-docs`. Running `build-docs --help` will give a summary of available options. For more information see the `esp-docs` documentation at https://github.com/espressif/esp-docs/blob/master/README.md diff --git a/docs/_static/esptool_versions.js b/docs/_static/esptool_versions.js deleted file mode 100644 index 6bc1a1887..000000000 --- a/docs/_static/esptool_versions.js +++ /dev/null @@ -1,13 +0,0 @@ -var DOCUMENTATION_VERSIONS = { - DEFAULTS: { has_targets: false, - supported_targets: [ "esp32" ] - }, - VERSIONS: [ ], - IDF_TARGETS: [ - { text: "ESP8266", value: "esp8266" }, - { text: "ESP32", value: "esp32" }, - { text: "ESP32-S2", value: "esp32s2" }, - { text: "ESP32-S3", value: "esp32s3" }, - { text: "ESP32-C3", value: "esp32c3" }, - ] -}; diff --git a/docs/conf_common.py b/docs/conf_common.py deleted file mode 100644 index afd4cdd55..000000000 --- a/docs/conf_common.py +++ /dev/null @@ -1,42 +0,0 @@ -from esp_docs.conf_docs import * # noqa: F403,F401 - -languages = ["en"] -idf_targets = ["esp8266", "esp32", "esp32s2", "esp32s3", "esp32c3"] - -# link roles config -github_repo = "espressif/esptool" - -# context used by sphinx_idf_theme -html_context["github_user"] = "espressif" -html_context["github_repo"] = "esptool" - -html_static_path = ["../_static"] - -# Conditional content -extensions += ["esp_docs.esp_extensions.dummy_build_system"] - -ESP8266_DOCS = [] - -ESP32_DOCS = [ - "espefuse/*", - "espsecure/*", -] - -ESP32S2_DOCS = ESP32_DOCS - -ESP32C3_DOCS = ESP32S2_DOCS - -ESP32S3_DOCS = ESP32S2_DOCS - -conditional_include_dict = { - "esp8266": ESP8266_DOCS, - "esp32": ESP32_DOCS, - "esp32s2": ESP32S2_DOCS, - "esp32c3": ESP32C3_DOCS, - "esp32s3": ESP32S3_DOCS, -} - -# Extra options required by sphinx_idf_theme -project_slug = "esptool" - -versions_url = "./_static/esptool_versions.js" diff --git a/docs/en/about.rst b/docs/en/about.rst deleted file mode 100644 index d26acadd8..000000000 --- a/docs/en/about.rst +++ /dev/null @@ -1,6 +0,0 @@ -About -===== - -Esptool was started by Fredrik Ahlberg (`themadinventor `_) as an unofficial community project. Later, it was maintained by Angus Gratton (`projectgus `_). It is now supported by `Espressif Systems `_. - -Esptool source code and this documentation are released as Free Software under GNU General Public License Version 2 or later. See `the LICENSE `_ for a copy. diff --git a/docs/en/advanced-topics/boot-mode-selection.rst b/docs/en/advanced-topics/boot-mode-selection.rst deleted file mode 100644 index d8d99a7b6..000000000 --- a/docs/en/advanced-topics/boot-mode-selection.rst +++ /dev/null @@ -1,323 +0,0 @@ -{IDF_TARGET_STRAP_BOOT_GPIO:default="GPIO0", esp32="GPIO0", esp32s2="GPIO0", esp32s3="GPIO0", esp32c3="GPIO9"} - -{IDF_TARGET_STRAP_BOOT_2_GPIO:default="GPIO2", esp32="GPIO2", esp32s2="GPIO46", esp32s3="GPIO46", esp32c3="GPIO8"} - -.. _boot-mode: - -Boot Mode Selection -=================== - -This guide explains how to select the boot mode correctly and describes the boot log messages of {IDF_TARGET_NAME}. - -.. only:: esp8266 - - On many development boards with built-in USB/Serial, this is done for you and ``esptool`` can automatically reset the board into bootloader mode. For other configurations, you will need to follow these steps: - - Required Pins - ------------- - - The following ESP8266 pins must be in a known state for either normal (flash boot) or serial bootloader operation. Most development boards or modules make necessary connections already, internally: - - +--------+--------------------------------------------------------------------------------------------------------------------+ - | GPIO | State | - +========+====================================================================================================================+ - | 15 | Pulled Low/GND (directly connected to GND, or external pull-down resistor) | - +--------+--------------------------------------------------------------------------------------------------------------------+ - | 2 | Pull-up resistor High/VCC, or No Connection (pin has internal weak pullup, external pullup resistor is optional) | - +--------+--------------------------------------------------------------------------------------------------------------------+ - - If these pins are set differently to shown, nothing on the ESP8266 will work as expected. See `ESP8266 Pin List document `__ to see what boot modes are enabled for different pin combinations. - - When the ESP8266 goes into serial bootloader mode, the Boot ROM switches GPIO2 to an output and the UART TX signal is also output to this pin. For this reason GPIO2 should not be directly connected to VCC. Similarly, make sure GPIO2 is not connected to another peripheral where this may cause an issue when in download mode. - - Select Bootloader Mode - ---------------------- - - The ESP8266 will enter the serial bootloader when GPIO0 is held low on reset. Otherwise it will run the program in flash. - - +---------------+----------------------------------------+ - | GPIO0 Input | Mode | - +===============+========================================+ - | Low/GND | ROM serial bootloader for esptool | - +---------------+----------------------------------------+ - | High/VCC | Normal execution mode | - +---------------+----------------------------------------+ - - Many configurations use a "Flash" button that pulls GPIO0 low when pressed. - -.. only:: not esp8266 - - .. warning:: - - The {IDF_TARGET_NAME} has a 45k ohm internal pull-up/pull-down resistor at {IDF_TARGET_STRAP_BOOT_GPIO} (and other pins). If you want to connect a switch button to enter the boot mode, this has to be a strong pull-down. For example a 10k resistor to GND. - - Information about {IDF_TARGET_NAME} strapping pins can also be found in the `{IDF_TARGET_NAME} Datasheet `__, section "Strapping Pins". - - On many development boards with built-in USB/Serial, ``esptool.py`` can automatically reset the board into bootloader mode. For other configurations or custom hardware, you will need to check the orientation of some "strapping pins" to get the correct boot mode: - - Select Bootloader Mode - ---------------------- - - {IDF_TARGET_STRAP_BOOT_GPIO} - ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - - The {IDF_TARGET_NAME} will enter the serial bootloader when {IDF_TARGET_STRAP_BOOT_GPIO} is held low on reset. Otherwise it will run the program in flash. - - +---------------+----------------------------------------+ - | {IDF_TARGET_STRAP_BOOT_GPIO} Input | Mode | - +===============+========================================+ - | Low/GND | ROM serial bootloader for esptool | - +---------------+----------------------------------------+ - | High/VCC | Normal execution mode | - +---------------+----------------------------------------+ - - {IDF_TARGET_STRAP_BOOT_GPIO} has an internal pullup resistor, so if it is left unconnected then it will pull high. - - Many boards use a button marked "Flash" (or "BOOT" on some Espressif development boards) that pulls {IDF_TARGET_STRAP_BOOT_GPIO} low when pressed. - - {IDF_TARGET_STRAP_BOOT_2_GPIO} - ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - - .. only:: not esp32c3 - - {IDF_TARGET_STRAP_BOOT_2_GPIO} must also be either left unconnected/floating, or driven Low, in order to enter the serial bootloader. - - .. only:: esp32c3 - - {IDF_TARGET_STRAP_BOOT_2_GPIO} must also be driven High, in order to enter the serial bootloader reliably. The strapping combination of {IDF_TARGET_STRAP_BOOT_2_GPIO} = 0 and {IDF_TARGET_STRAP_BOOT_GPIO} = 0 is invalid and will trigger unexpected behavior. - - In normal boot mode ({IDF_TARGET_STRAP_BOOT_GPIO} high), {IDF_TARGET_STRAP_BOOT_2_GPIO} is ignored. - - - Other Pins - ^^^^^^^^^^ - - .. only:: not esp32 - - As well as the above mentioned pins, other ones influence the serial bootloader, please consult the `{IDF_TARGET_NAME} Datasheet `__, section "Strapping Pins". - - .. only:: esp32 - - As well as {IDF_TARGET_STRAP_BOOT_GPIO} and {IDF_TARGET_STRAP_BOOT_2_GPIO}, the following pins influence the serial bootloader mode: - - +-------------+--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ - | GPIO | Meaning | - +=============+============================================================================================================================================================================================================================================================================================+ - | 12 (MTDI) | If driven High, flash voltage (VDD_SDIO) is 1.8V not default 3.3V. Has internal pull-down, so unconnected = Low = 3.3V. May prevent flashing and/or booting if 3.3V flash is used and this pin is pulled high, causing the flash to brownout. See the datasheet for more details. | - +-------------+--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ - | 15 (MTDO) | If driven Low, silences boot messages printed by the ROM bootloader. Has an internal pull-up, so unconnected = High = normal output. | - +-------------+--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ - - For more information, consult the `{IDF_TARGET_NAME} Datasheet `__, section "Strapping Pins". - -.. _automatic-bootloader: - -Automatic Bootloader --------------------- - -``esptool.py`` resets {IDF_TARGET_NAME} automatically by asserting ``DTR`` and ``RTS`` control lines of the USB to serial converter chip, i.e., FTDI, CP210x, or CH340x. The ``DTR`` and ``RTS`` control lines are in turn connected to ``{IDF_TARGET_STRAP_BOOT_GPIO}`` and ``EN`` (``CHIP_PU``) pins of {IDF_TARGET_NAME}, thus changes in the voltage levels of ``DTR`` and ``RTS`` will boot the {IDF_TARGET_NAME} into Firmware Download mode. - -.. note:: - - When developing ``esptool.py``, keep in mind ``DTR`` and ``RTS`` are active low signals, i.e., ``True`` = pin @ 0V, ``False`` = pin @ VCC. - -As an example of auto-reset curcuitry implementation, check the `schematic `_ of the ESP32 DevKitC development board: - -- The **Micro USB 5V & USB-UART** section shows the ``DTR`` and ``RTS`` control lines of the USB to serial converter chip connected to ``GPIO0`` and ``EN`` pins of the ESP module. -- Some OS and/or drivers may activate ``RTS`` and or ``DTR`` automatically when opening the serial port (true only for some serial terminal programs, not ``esptool.py``), pulling them low together and holding the ESP in reset. If ``RTS`` is wired directly to ``EN`` then RTS/CTS "hardware flow control" needs to be disabled in the serial program to avoid this. - An additional circuitry is implemented in order to avoid this problem - if both ``RTS`` and ``DTR`` are asserted together, this doesn't reset the chip. The schematic shows this specific circuit with two transistors and its truth table. -- If this circuitry is implemented (all Espressif boards have it), adding a capacitor between the ``EN`` pin and ``GND`` (in the 1uF-10uF range) is necessary for the reset circuitry to work reliably. This is shown in the **ESP32 Module** section of the schematic. -- The **Switch Button** section shows buttons needed for :ref:`manually switching to bootloader `. - -Make the following connections for ``esptool`` to automatically enter the bootloader of an {IDF_TARGET_NAME} chip: - -+-------------+--------------+ -| ESP Pin | Serial Pin | -+=============+==============+ -| EN | RTS | -+-------------+--------------+ -| {IDF_TARGET_STRAP_BOOT_GPIO} | DTR | -+-------------+--------------+ - -In Linux serial ports by default will assert RTS when nothing is attached to them. This can hold the {IDF_TARGET_NAME} in a reset loop which may cause some serial adapters to subsequently reset loop. This functionality can be disabled by disabling ``HUPCL`` (ie ``sudo stty -F /dev/ttyUSB0 -hupcl``). - -(Some third party {IDF_TARGET_NAME} development boards use an automatic reset circuit for ``EN`` & ``{IDF_TARGET_STRAP_BOOT_GPIO}`` pins, but don't add a capacitor on the ``EN`` pin. This results in unreliable automatic reset, especially on Windows. Adding a 1uF (or higher) value capacitor between ``EN`` pin and ``GND`` may make automatic reset more reliable.) - -In general, you should have no problems with the official Espressif development boards. However, ``esptool.py`` is not able to reset your hardware automatically in the following cases: - -- Your hardware does not have the ``DTR`` and ``RTS`` lines connected to ``{IDF_TARGET_STRAP_BOOT_GPIO}`` and ``EN`` (``CHIP_PU``) -- The ``DTR`` and ``RTS`` lines are configured differently -- There are no such serial control lines at all - -.. _manual-bootloader: - -Manual Bootloader ------------------ - -Depending on the kind of hardware you have, it may also be possible to manually put your {IDF_TARGET_NAME} board into Firmware Download mode (reset). - -- For development boards produced by Espressif, this information can be found in the respective getting started guides or user guides. For example, to manually reset a development board, hold down the **Boot** button (``{IDF_TARGET_STRAP_BOOT_GPIO}``) and press the **EN** button (``EN`` (``CHIP_PU``)). -- For other types of hardware, try pulling ``{IDF_TARGET_STRAP_BOOT_GPIO}`` down. - -.. only:: esp8266 - - .. _boot-log-esp8266: - - Boot Log - -------- - - The ESP8266 boot rom writes a log to the UART when booting. The timing is a little bit unusual: ``74880 baud`` (see :ref:`serial-port-settings`). - - :: - - ets Jan 8 2014,rst cause 1, boot mode:(3,7) - - load 0x40100000, len 24236, room 16 - tail 12 - chksum 0xb7 - ho 0 tail 12 room 4 - load 0x3ffe8000, len 3008, room 12 - tail 4 - chksum 0x2c - load 0x3ffe8bc0, len 4816, room 4 - tail 12 - chksum 0x46 - csum 0x46 - - - Explanation - ^^^^^^^^^^^ - - **rst_cause:** - - +---------------+----------------------------------------+ - | Value | Meaning | - +===============+========================================+ - | 1 | power-on | - +---------------+----------------------------------------+ - | 2 | external-reset | - +---------------+----------------------------------------+ - | 4 | hardware watchdog-reset | - +---------------+----------------------------------------+ - - - **The first parameter of boot_mode:** - - +-------------------------+----------------------------------------------+ - | Value | Meaning | - +=========================+==============================================+ - | 1 (eg. boot mode:(1,x)) | UART download mode (download FW into Flash) | - +-------------------------+----------------------------------------------+ - | 2 (eg. boot mode:(3,x)) | Boot from flash mode | - +-------------------------+----------------------------------------------+ - - **chksum:** - - If value of “chksum” == value of “csum”, it means flash has been read correctly during booting. - - The rest of boot messages are used internally by Espressif. - -.. only:: esp32 - - Boot Log - -------- - - Boot Mode Message - ^^^^^^^^^^^^^^^^^ - - After reset, the second line printed by the ESP32 ROM (at 115200bps) is a reset & boot mode message: - - :: - - ets Jun 8 2016 00:22:57 - rst:0x1 (POWERON_RESET),boot:0x3 (DOWNLOAD_BOOT(UART0/UART1/SDIO_REI_REO_V2)) - - ``rst:0xNN (REASON)`` is an enumerated value (and description) of the reason for the reset. `A mapping between the hex value and each reason can be found in the ESP-IDF source `__. - The value can be read in ESP32 code via the `get_reset_reason() ROM function `__. - - ``boot:0xNN (DESCRIPTION)`` is the hex value of the strapping pins, as represented in the `GPIO_STRAP register `__. - The individual bit values are as follows: - - - ``0x01`` - GPIO5 - - ``0x02`` - MTDO (GPIO15) - - ``0x04`` - GPIO4 - - ``0x08`` - GPIO2 - - ``0x10`` - GPIO0 - - ``0x20`` - MTDI (GPIO12) - - If the pin was high on reset, the bit value will be set. If it was low on reset, the bit will be cleared. - - A number of boot mode strings can be shown depending on which bits are set: - - - ``DOWNLOAD_BOOT(UART0/UART1/SDIO_REI_REO_V2)`` - ESP32 is in download flashing mode (suitable for esptool) - - ``SPI_FAST_FLASH_BOOT`` - This is the normal SPI flash boot mode. - - Other modes (including ``HSPI_FLASH_BOOT``, ``SPI_FLASH_BOOT``, ``SDIO_REI_FEO_V1_BOOT``, ``ATE_BOOT``) may be shown here. This indicates an unsupported boot mode has been selected. - Consult the strapping pins shown above (in most cases, one of these modes is selected if GPIO2 has been pulled high when GPIO0 is low). - - .. note:: - - ``GPIO_STRAP`` register includes GPIO 4 but this pin is not used by any supported boot mode and be set either high or low for all supported boot modes. - - Later Boot Messages - ^^^^^^^^^^^^^^^^^^^ - - Later output from the ROM bootloader depends on the strapping pins and - the boot mode. Some common output includes: - - Early Flash Read Error - """""""""""""""""""""" - - :: - - flash read err, 1000 - - This fatal error indicates that the bootloader tried to read the software bootloader header at address 0x1000 but failed to read valid data. Possible reasons for this include: - - - There isn't actually a bootloader at offset 0x1000 (maybe the bootloader was flashed to the wrong offset by mistake, or the flash has been erased and no bootloader has been flashed yet.) - - Physical problem with the connection to the flash chip, or flash chip power. - - Boot mode accidentally set to ``HSPI_FLASH_BOOT``, which uses different SPI flash pins. Check GPIO2 (see above). - - VDDSDIO has been enabled at 1.8V (due to MTDI/GPIO12, see above), but this flash chip requires 3.3V so it's browning out. - - Flash encryption is enabled but the bootloader is plaintext. Alternatively, flash encryption is disabled but the bootloader is encrypted ciphertext. - - Software Bootloader Header Info - """"""""""""""""""""""""""""""" - - :: - - configsip: 0, SPIWP:0x00 - clk_drv:0x00,q_drv:0x00,d_drv:0x00,cs0_drv:0x00,hd_drv:0x00,wp_drv:0x00 - mode:DIO, clock div:1 - - This is normal boot output based on a combination of efuse values and information read from the bootloader header at flash offset 0x1000: - - - ``configsip: N`` indicates SPI flash config: - - 0 for default SPI flash - - 1 if booting from the HSPI bus (due to EFUSE configuration) - - Any other value indicates that SPI flash pins have been remapped via efuse (the value is the value read from efuse, consult :ref:`espefuse docs ` to get an easier to read representation of these pin mappings). - - ``SPIWP:0xNN`` indicates a custom ``WP`` pin value, which is stored in the bootloader header. This pin value is only used if SPI flash pins have been remapped via efuse (as shown in the ``configsip`` value). - All custom pin values but WP are encoded in the configsip byte loaded from efuse, and WP is supplied in the bootloader header. - - ``clk_drv:0x00,q_drv:0x00,d_drv:0x00,cs0_drv:0x00,hd_drv:0x00,wp_drv:0x00`` Custom GPIO drive strength values for SPI flash pins. These are read from the bootloader header in flash. Not currently supported. - - ``mode: AAA, clock div: N``. SPI flash access mode. Read from the bootloader header, correspond to the ``--flash_mode`` and ``--flash_freq`` arguments supplied to ``esptool.py write_flash`` or ``esptool.py elf2image``. - - ``mode`` can be DIO, DOUT, QIO, or QOUT. *QIO and QOUT are not supported here*, to boot in a Quad I/O mode the ROM bootloader should load the software bootloader in a Dual I/O mode and then the ESP-IDF software bootloader enables Quad I/O based on the detected flash chip mode. - - ``clock div: N`` is the SPI flash clock frequency divider. This is an integer clock divider value from an 80MHz APB clock, based on the supplied ``--flash_freq`` argument (ie 80MHz=1, 40MHz=2, etc). - The ROM bootloader actually loads the software bootloader at a lower frequency than the flash_freq value. The initial APB clock frequency is equal to the crystal frequency, so with a 40MHz crystal the SPI clock used to load the software bootloader will be half the configured value (40MHz/2=20MHz). - When the software bootloader starts it sets the APB clock to 80MHz causing the SPI clock frequency to match the value set when flashing. - - Software Bootloader Load Segments - """"""""""""""""""""""""""""""""" - - :: - - load:0x3fff0008,len:8 - load:0x3fff0010,len:3680 - load:0x40078000,len:8364 - load:0x40080000,len:252 - entry 0x40080034 - - These entries are printed as the ROM bootloader loads each segment in the software bootloader image. The load address and length of each segment is printed. - - You can compare these values to the software bootloader image by running ``esptool.py --chip esp32 image_info /path/to/bootloader.bin`` to dump image info including a summary of each segment. Corresponding details will also be found in the bootloader ELF file headers. - - If there is a problem with the SPI flash chip addressing mode, the values printed by the bootloader here may be corrupted. - - The final line shows the entry point address of the software bootloader, where the ROM bootloader will call as it hands over control. diff --git a/docs/en/advanced-topics/firmware-image-format.rst b/docs/en/advanced-topics/firmware-image-format.rst deleted file mode 100644 index 529df3d5f..000000000 --- a/docs/en/advanced-topics/firmware-image-format.rst +++ /dev/null @@ -1,125 +0,0 @@ -.. _image-format: - -Firmware Image Format -===================== - -This is technical documentation for the firmware image format used by the ROM bootloader. These are the images created by ``esptool.py elf2image``. - -.. only:: esp8266 - - The firmware file consists of a header, a variable number of data segments and a footer. Multi-byte fields are little-endian. - -.. only:: not esp8266 - - The firmware file consists of a header, an extended header, a variable number of data segments and a footer. Multi-byte fields are little-endian. - -File Header ------------ - -The image header is 8 bytes long: - -.. only:: esp8266 - - +--------+--------------------------------------------------------------------------------------------------+ - | Byte | Description | - +========+==================================================================================================+ - | 0 | Magic number (always ``0xE9``) | - +--------+--------------------------------------------------------------------------------------------------+ - | 1 | Number of segments | - +--------+--------------------------------------------------------------------------------------------------+ - | 2 | SPI Flash Mode (``0`` = QIO, ``1`` = QOUT, ``2`` = DIO, ``3`` = DOUT) | - +--------+--------------------------------------------------------------------------------------------------+ - | 3 | High four bits - Flash size (``0`` = 512KB, ``1`` = 256KB, ``2`` = 1MB, ``3`` = 2MB, ``4`` = 4MB,| - | | ``5`` = 2MB-c1, ``6`` = 4MB-c1, ``8`` = 8MB, ``9`` = 16MB) | - | | | - | | Low four bits - Flash frequency (``0`` = 40MHz, ``1`` = 26MHz, ``2`` = 20MHz, ``0xf`` = 80MHz) | - +--------+--------------------------------------------------------------------------------------------------+ - | 4-7 | Entry point address | - +--------+--------------------------------------------------------------------------------------------------+ - -.. only:: not esp8266 - - +--------+--------------------------------------------------------------------------------------------------+ - | Byte | Description | - +========+==================================================================================================+ - | 0 | Magic number (always ``0xE9``) | - +--------+--------------------------------------------------------------------------------------------------+ - | 1 | Number of segments | - +--------+--------------------------------------------------------------------------------------------------+ - | 2 | SPI Flash Mode (``0`` = QIO, ``1`` = QOUT, ``2`` = DIO, ``3`` = DOUT) | - +--------+--------------------------------------------------------------------------------------------------+ - | 3 | High four bits - Flash size (``0`` = 1MB, ``1`` = 2MB, ``2`` = 4MB, ``3`` = 8MB, ``4`` = 16MB) | - | | | - | | Low four bits - Flash frequency (``0`` = 40MHz, ``1`` = 26MHz, ``2`` = 20MHz, ``0xf`` = 80MHz) | - +--------+--------------------------------------------------------------------------------------------------+ - | 4-7 | Entry point address | - +--------+--------------------------------------------------------------------------------------------------+ - -.. only:: esp32c2 or esp32h2 - - .. fail_when_new_target_added:: - - TODO: Update flash frequency lists to be esp32c2 or esp32h2 specific - -``esptool.py`` overrides the 2nd and 3rd (start from 0) bytes according to the SPI flash info provided through command line option, but only if there is no SHA256 digest appended after the image. Therefore, if you would like to change SPI flash info during flashing, i.e. with the ``esptool.py write_flash`` command, then generate images without SHA256 digests. This can be achieved by running ``esptool.py elf2image`` with the ``--dont-append-digest`` argument. - -.. only:: esp8266 - - Individual segments come right after this header. - -.. only:: not esp8266 - - Extended File Header - -------------------- - - The 16-byte long extended header comes right after the image header, individual segments come right after it: - - +--------+---------------------------------------------------------------------------------------------------------+ - | Byte | Description | - +========+=========================================================================================================+ - | 0 | WP pin when SPI pins set via efuse (read by ROM bootloader) | - +--------+---------------------------------------------------------------------------------------------------------+ - | 1-3 | Drive settings for the SPI flash pins (read by ROM bootloader) | - +--------+---------------------------------------------------------------------------------------------------------+ - | 4-5 | Chip ID (which ESP device is this image for) | - +--------+---------------------------------------------------------------------------------------------------------+ - | 6 | Minimal chip revision supported by the image (deprecated, use the following field) | - +--------+---------------------------------------------------------------------------------------------------------+ - | 7-8 | Minimal chip revision supported by the image (in format: major * 100 + minor) | - +--------+---------------------------------------------------------------------------------------------------------+ - | 9-10 | Maximal chip revision supported by the image (in format: major * 100 + minor) | - +--------+---------------------------------------------------------------------------------------------------------+ - | 11-14 | Reserved bytes in additional header space, currently unused | - +--------+---------------------------------------------------------------------------------------------------------+ - | 15 | Hash appended (If 1, SHA256 digest is appended after the checksum) | - +--------+---------------------------------------------------------------------------------------------------------+ - -Segment -------- - -+---------+-----------------+ -| Byte | Description | -+=========+=================+ -| 0-3 | Memory offset | -+---------+-----------------+ -| 4-7 | Segment size | -+---------+-----------------+ -| 8...n | Data | -+---------+-----------------+ - -Footer ------- - -The file is padded with zeros until its size is one byte less than a multiple of 16 bytes. A last byte (thus making the file size a multiple of 16) is the checksum of the data of all segments. The checksum is defined as the xor-sum of all bytes and the byte ``0xEF``. - -.. only:: not esp8266 - - If ``hash appended`` in the extended file header is ``0x01``, a SHA256 digest “simple hash” (of the entire image) is appended after the checksum. This digest is separate to secure boot and only used for detecting corruption. The SPI flash info cannot be changed during flashing if hash is appended after the image. - - If secure boot is enabled, a signature is also appended (and the simple hash is included in the signed data). This image signature is `Secure Boot V1 `_ and `Secure Boot V2 `_ specific. - - -Analyzing a Binary Image ------------------------- - -To analyze a binary image and get a complete summary of its headers and segments, use the :ref:`image_info ` command with the ``--version 2`` option. diff --git a/docs/en/advanced-topics/index.rst b/docs/en/advanced-topics/index.rst deleted file mode 100644 index 7f1d79e21..000000000 --- a/docs/en/advanced-topics/index.rst +++ /dev/null @@ -1,12 +0,0 @@ -Advanced Topics -=============== - -This sections contains advanced topics and technical documentation useful if you're developing ``esptool`` or hacking system internals: - -.. toctree:: - :maxdepth: 1 - - Firmware Image Format - Serial Protocol - SPI Flash Modes - Boot Mode Selection diff --git a/docs/en/advanced-topics/serial-protocol.rst b/docs/en/advanced-topics/serial-protocol.rst deleted file mode 100644 index 03d930baa..000000000 --- a/docs/en/advanced-topics/serial-protocol.rst +++ /dev/null @@ -1,488 +0,0 @@ -{IDF_TARGET_SECURITY_INFO:default="32 bits ``flags``, 1 byte ``flash_crypt_cnt``, 7x1 byte ``key_purposes``, 32-bit word ``chip_id``, 32-bit word ``eco_version``", esp32s2="32 bits ``flags``, 1 byte ``flash_crypt_cnt``, 7x1 byte ``key_purposes`` "} - -Serial Protocol -=============== - -This is technical documentation for the serial protocol used by the UART bootloader in the {IDF_TARGET_NAME} ROM and the esptool :ref:`stub loader ` program. - -The UART bootloader runs on chip reset if certain strapping pins are set. See :ref:`entering-the-bootloader` for details of this process. - -.. only:: not esp8266 - - The {IDF_TARGET_NAME} ROM loader serial protocol is similar to ESP8266, although {IDF_TARGET_NAME} adds some additional commands and some slightly different behaviour. - -By default, esptool uploads a stub "software loader" to the IRAM of the chip. The stub loader then replaces the ROM loader for all future interactions. This standardizes much of the behaviour. Pass ``--no-stub`` to esptool in order to disable the stub loader. See :ref:`stub` for more information. - -.. note:: - - There are differences in the serial protocol between ESP chips! To switch to documentation for a different chip, choose the desired target from the dropdown menu in the upper left corner. - -Packet Description ------------------- - -The host computer sends a SLIP encoded command request to the ESP chip. The ESP chip responds to the request with a SLIP encoded response packet, including status information and any data as a payload. - -.. _low-level-protocol: - -Low Level Protocol -^^^^^^^^^^^^^^^^^^ - -The bootloader protocol uses `SLIP `_ packet framing for data transmissions in both directions. - -Each SLIP packet begins and ends with ``0xC0``. Within the packet, all occurrences of ``0xC0`` and ``0xDB`` are replaced with ``0xDB 0xDC`` and ``0xDB 0xDD``, respectively. The replacing is to be done **after** the checksum and lengths are calculated, so the packet length may be longer than the ``size`` field below. - -Command Packet -^^^^^^^^^^^^^^ - -Each command is a SLIP packet initiated by the host and results in a response packet. Inside the packet, the packet consists of a header and a variable-length body. All multi-byte fields are little-endian. - -+--------+-------------+--------------------------------------------------------------------------------------------------------------------+ -| Byte | Name | Comment | -+========+=============+====================================================================================================================+ -| 0 | Direction | Always ``0x00`` for requests | -+--------+-------------+--------------------------------------------------------------------------------------------------------------------+ -| 1 | Command | Command identifier (see `Commands`_). | -+--------+-------------+--------------------------------------------------------------------------------------------------------------------+ -| 2-3 | Size | Length of Data field, in bytes. | -+--------+-------------+--------------------------------------------------------------------------------------------------------------------+ -| 4-7 | Checksum | Simple checksum of part of the data field (only used for some commands, see `Checksum`_). | -+--------+-------------+--------------------------------------------------------------------------------------------------------------------+ -| 8..n | Data | Variable length data payload (0-65535 bytes, as indicated by Size parameter). Usage depends on specific command. | -+--------+-------------+--------------------------------------------------------------------------------------------------------------------+ - -Response Packet -^^^^^^^^^^^^^^^ - -Each received command will result in a response SLIP packet sent from the ESP chip to the host. Contents of the response packet is: - -+--------+-------------+--------------------------------------------------------------------------------------------------------------+ -| Byte | Name | Comment | -+========+=============+==============================================================================================================+ -| 0 | Direction | Always ``0x01`` for responses | -+--------+-------------+--------------------------------------------------------------------------------------------------------------+ -| 1 | Command | Same value as Command identifier in the request packet that trigged the response | -+--------+-------------+--------------------------------------------------------------------------------------------------------------+ -| 2-3 | Size | Size of data field. At least the length of the `Status Bytes`_ (2 or 4 bytes, see below). | -+--------+-------------+--------------------------------------------------------------------------------------------------------------+ -| 4-7 | Value | Response value used by READ_REG command (see below). Zero otherwise. | -+--------+-------------+--------------------------------------------------------------------------------------------------------------+ -| 8..n | Data | Variable length data payload. Length indicated by "Size" field. | -+--------+-------------+--------------------------------------------------------------------------------------------------------------+ - -Status bytes -"""""""""""" - -The final bytes of the Data payload indicate command status: - -.. only:: esp8266 - - For stub loader and ESP8266 ROM loader the final two bytes indicate status (most commands return at least a two byte Data payload): - -.. only:: not esp8266 - - For stub loader the final two bytes indicate status (most commands return at least a two byte Data payload): - -+----------+----------+-----------------------------------------------------+ -| Byte | Name | Comment | -+==========+==========+=====================================================+ -| Size-2 | Status | Status flag, success (``0``) or failure (``1``) | -+----------+----------+-----------------------------------------------------+ -| Size-1 | Error | If Status is 1, this indicates the type of error. | -+----------+----------+-----------------------------------------------------+ - -.. only:: not esp8266 - - For {IDF_TARGET_NAME} ROM (only, not the stub loader) the final four bytes are used, but only the first two bytes contain status information: - - +----------+------------+---------------------------------------------------+ - | Byte | Name | Comment | - +==========+============+===================================================+ - | Size-4 | Status | Status flag, success (``0``) or failure (``1``) | - +----------+------------+---------------------------------------------------+ - | Size-3 | Error | If Status 1, this indicates the type of error. | - +----------+------------+---------------------------------------------------+ - | Size-2 | Reserved | | - +----------+------------+---------------------------------------------------+ - | Size-1 | Reserved | | - +----------+------------+---------------------------------------------------+ - -ROM Loader Errors -""""""""""""""""" - -The ROM loader sends the following error values - -+----------+---------------------------------------------------------------------------+ -| Value | Meaning | -+==========+===========================================================================+ -| ``0x05`` | "Received message is invalid" (parameters or length field is invalid) | -+----------+---------------------------------------------------------------------------+ -| ``0x06`` | "Failed to act on received message" | -+----------+---------------------------------------------------------------------------+ -| ``0x07`` | "Invalid CRC in message" | -+----------+---------------------------------------------------------------------------+ -| ``0x08`` | "Flash write error" - after writing a block of data to flash, | -| | the ROM loader reads the value back and the 8-bit CRC is compared | -| | to the data read from flash. If they don't match, this error is returned. | -+----------+---------------------------------------------------------------------------+ -| ``0x09`` | "Flash read error" - SPI read failed | -+----------+---------------------------------------------------------------------------+ -| ``0x0a`` | "Flash read length error" - SPI read request length is too long | -+----------+---------------------------------------------------------------------------+ -| ``0x0b`` | "Deflate error" (compressed uploads only) | -+----------+---------------------------------------------------------------------------+ - -Stub Loader Status & Error -"""""""""""""""""""""""""" - -If the stub loader is used: - -- The status response is always 2 bytes regardless of chip type. -- Stub loader error codes are entirely different to the ROM loader codes. They all take the form ``0xC*``, or ``0xFF`` for "unimplemented command". (`Full list here `_). - -After sending a command, the host should continue to read response packets until one is received where the Command field matches the request's Command field, or a timeout is exceeded. - -Commands -^^^^^^^^ - -Supported by stub loader and ROM loader -""""""""""""""""""""""""""""""""""""""" - -.. only:: esp8266 - - +------------+----------------+-------------------------------------------------------+------------------------------------------------------------------------------------------------------------------------------------+------------------------------------------------+ - | Byte | Name | Description | Input Data | Output Data | - +============+================+=======================================================+====================================================================================================================================+================================================+ - | ``0x02`` | FLASH_BEGIN | `Begin Flash Download <#writing-data>`__ | Four 32-bit words: size to erase, number of data packets, data size in one packet, flash offset. | | - +------------+----------------+-------------------------------------------------------+------------------------------------------------------------------------------------------------------------------------------------+------------------------------------------------+ - | ``0x03`` | FLASH_DATA | `Flash Download Data <#writing-data>`__ | Four 32-bit words: data size, sequence number, ``0``, ``0``, then data. Uses `Checksum`_. | | - +------------+----------------+-------------------------------------------------------+------------------------------------------------------------------------------------------------------------------------------------+------------------------------------------------+ - | ``0x04`` | FLASH_END | `Finish Flash Download <#writing-data>`__ | One 32-bit word: ``0`` to reboot, ``1`` to run user code. Not necessary to send this command if you wish to stay in the loader | | - +------------+----------------+-------------------------------------------------------+------------------------------------------------------------------------------------------------------------------------------------+------------------------------------------------+ - | ``0x05`` | MEM_BEGIN | `Begin RAM Download Start <#writing-data>`__ | Total size, number of data packets, data size in one packet, memory offset | | - +------------+----------------+-------------------------------------------------------+------------------------------------------------------------------------------------------------------------------------------------+------------------------------------------------+ - | ``0x06`` | MEM_END | `Finish RAM Download <#writing-data>`__ | Two 32-bit words: execute flag, entry point address | | - +------------+----------------+-------------------------------------------------------+------------------------------------------------------------------------------------------------------------------------------------+------------------------------------------------+ - | ``0x07`` | MEM_DATA | `RAM Download Data <#writing-data>`__ | Four 32-bit words: data size, sequence number, ``0``, ``0``, then data. Uses `Checksum`_. | | - +------------+----------------+-------------------------------------------------------+------------------------------------------------------------------------------------------------------------------------------------+------------------------------------------------+ - | ``0x08`` | SYNC | `Sync Frame <#initial-synchronisation>`__ | 36 bytes: ``0x07 0x07 0x12 0x20``, followed by 32 x ``0x55`` | | - +------------+----------------+-------------------------------------------------------+------------------------------------------------------------------------------------------------------------------------------------+------------------------------------------------+ - | ``0x09`` | WRITE_REG | `Write 32-bit memory address <#32-bit-readwrite>`__ | Four 32-bit words: address, value, mask and delay (in microseconds) | | - +------------+----------------+-------------------------------------------------------+------------------------------------------------------------------------------------------------------------------------------------+------------------------------------------------+ - | ``0x0a`` | READ_REG | `Read 32-bit memory address <#32-bit-readwrite>`__ | Address as 32-bit word | Read data as 32-bit word in ``value`` field. | - +------------+----------------+-------------------------------------------------------+------------------------------------------------------------------------------------------------------------------------------------+------------------------------------------------+ - -.. only:: esp32 - - +------------+----------------------+----------------------------------------------------------------+------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+-----------------------------------------------------------------------------------------------------------------------------------+ - | Byte | Name | Description | Input Data | Output Data | - +============+======================+================================================================+================================================================================================================================================================================================================================================+===================================================================================================================================+ - | ``0x02`` | FLASH_BEGIN | `Begin Flash Download <#writing-data>`__ | Four 32-bit words: size to erase, number of data packets, data size in one packet, flash offset. | | - +------------+----------------------+----------------------------------------------------------------+------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+-----------------------------------------------------------------------------------------------------------------------------------+ - | ``0x03`` | FLASH_DATA | `Flash Download Data <#writing-data>`__ | Four 32-bit words: data size, sequence number, ``0``, ``0``, then data. Uses `Checksum`_. | | - +------------+----------------------+----------------------------------------------------------------+------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+-----------------------------------------------------------------------------------------------------------------------------------+ - | ``0x04`` | FLASH_END | `Finish Flash Download <#writing-data>`__ | One 32-bit word: ``0`` to reboot, ``1`` to run user code. Not necessary to send this command if you wish to stay in the loader | | - +------------+----------------------+----------------------------------------------------------------+------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+-----------------------------------------------------------------------------------------------------------------------------------+ - | ``0x05`` | MEM_BEGIN | `Begin RAM Download Start <#writing-data>`__ | Total size, number of data packets, data size in one packet, memory offset | | - +------------+----------------------+----------------------------------------------------------------+------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+-----------------------------------------------------------------------------------------------------------------------------------+ - | ``0x06`` | MEM_END | `Finish RAM Download <#writing-data>`__ | Two 32-bit words: execute flag, entry point address | | - +------------+----------------------+----------------------------------------------------------------+------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+-----------------------------------------------------------------------------------------------------------------------------------+ - | ``0x07`` | MEM_DATA | `RAM Download Data <#writing-data>`__ | Four 32-bit words: data size, sequence number, ``0``, ``0``, then data. Uses `Checksum`_. | | - +------------+----------------------+----------------------------------------------------------------+------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+-----------------------------------------------------------------------------------------------------------------------------------+ - | ``0x08`` | SYNC | `Sync Frame <#initial-synchronisation>`__ | 36 bytes: ``0x07 0x07 0x12 0x20``, followed by 32 x ``0x55`` | | - +------------+----------------------+----------------------------------------------------------------+------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+-----------------------------------------------------------------------------------------------------------------------------------+ - | ``0x09`` | WRITE_REG | `Write 32-bit memory address <#32-bit-readwrite>`__ | Four 32-bit words: address, value, mask and delay (in microseconds) | | - +------------+----------------------+----------------------------------------------------------------+------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+-----------------------------------------------------------------------------------------------------------------------------------+ - | ``0x0a`` | READ_REG | `Read 32-bit memory address <#32-bit-readwrite>`__ | Address as 32-bit word | Read data as 32-bit word in ``value`` field. | - +------------+----------------------+----------------------------------------------------------------+------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+-----------------------------------------------------------------------------------------------------------------------------------+ - | ``0x0b`` | SPI_SET_PARAMS | `Configure SPI flash <#spi-set-parameters>`__ | Six 32-bit words: id, total size in bytes, block size, sector size, page size, status mask. | | - +------------+----------------------+----------------------------------------------------------------+------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+-----------------------------------------------------------------------------------------------------------------------------------+ - | ``0x0d`` | SPI_ATTACH | `Attach SPI flash <#spi-attach-command>`__ | 32-bit word: Zero for normal SPI flash. A second 32-bit word (should be ``0``) is passed to ROM loader only. | | - +------------+----------------------+----------------------------------------------------------------+------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+-----------------------------------------------------------------------------------------------------------------------------------+ - | ``0x0f`` | CHANGE_BAUDRATE | `Change Baud rate <#initial-synchronisation>`__ | Two 32-bit words: new baud rate, ``0`` if we are talking to the ROM loader or the current/old baud rate if we are talking to the stub loader. | | - +------------+----------------------+----------------------------------------------------------------+------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+-----------------------------------------------------------------------------------------------------------------------------------+ - | ``0x10`` | FLASH_DEFL_BEGIN | `Begin compressed flash download <#writing-data>`__ | Four 32-bit words: uncompressed size, number of data packets, data packet size, flash offset. With stub loader the uncompressed size is exact byte count to be written, whereas on ROM bootloader it is rounded up to flash erase block size. | | - +------------+----------------------+----------------------------------------------------------------+------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+-----------------------------------------------------------------------------------------------------------------------------------+ - | ``0x11`` | FLASH_DEFL_DATA | `Compressed flash download data <#writing-data>`__ | Four 32-bit words: data size, sequence number, ``0``, ``0``, then data. Uses `Checksum`_. | Error code ``0xC1`` on checksum error. | - +------------+----------------------+----------------------------------------------------------------+------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+-----------------------------------------------------------------------------------------------------------------------------------+ - | ``0x12`` | FLASH_DEFL_END | `End compressed flash download <#writing-data>`__ | One 32-bit word: ``0`` to reboot, ``1`` to run user code. Not necessary to send this command if you wish to stay in the loader. | | - +------------+----------------------+----------------------------------------------------------------+------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+-----------------------------------------------------------------------------------------------------------------------------------+ - | ``0x13`` | SPI_FLASH_MD5 | `Calculate MD5 of flash region <#verifying-uploaded-data>`__ | Four 32-bit words: address, size, ``0``, ``0`` | Body contains 16 raw bytes of MD5 followed by 2 status bytes (stub loader) or 32 hex-coded ASCII (ROM loader) of calculated MD5 | - +------------+----------------------+----------------------------------------------------------------+------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+-----------------------------------------------------------------------------------------------------------------------------------+ - -.. only:: not esp8266 and not esp32 - - +------------+----------------------+----------------------------------------------------------------+------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+-----------------------------------------------------------------------------------------------------------------------------------+ - | Byte | Name | Description | Input Data | Output Data | - +============+======================+================================================================+================================================================================================================================================================================================================================================+===================================================================================================================================+ - | ``0x02`` | FLASH_BEGIN | `Begin Flash Download <#writing-data>`__ | Four 32-bit words: size to erase, number of data packets, data size in one packet, flash offset. A fifth 32-bit word passed to ROM loader only: ``1`` to begin encrypted flash, ``0`` to not. | | - +------------+----------------------+----------------------------------------------------------------+------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+-----------------------------------------------------------------------------------------------------------------------------------+ - | ``0x03`` | FLASH_DATA | `Flash Download Data <#writing-data>`__ | Four 32-bit words: data size, sequence number, ``0``, ``0``, then data. Uses `Checksum`_. | | - +------------+----------------------+----------------------------------------------------------------+------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+-----------------------------------------------------------------------------------------------------------------------------------+ - | ``0x04`` | FLASH_END | `Finish Flash Download <#writing-data>`__ | One 32-bit word: ``0`` to reboot, ``1`` to run user code. Not necessary to send this command if you wish to stay in the loader | | - +------------+----------------------+----------------------------------------------------------------+------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+-----------------------------------------------------------------------------------------------------------------------------------+ - | ``0x05`` | MEM_BEGIN | `Begin RAM Download Start <#writing-data>`__ | Total size, number of data packets, data size in one packet, memory offset | | - +------------+----------------------+----------------------------------------------------------------+------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+-----------------------------------------------------------------------------------------------------------------------------------+ - | ``0x06`` | MEM_END | `Finish RAM Download <#writing-data>`__ | Two 32-bit words: execute flag, entry point address | | - +------------+----------------------+----------------------------------------------------------------+------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+-----------------------------------------------------------------------------------------------------------------------------------+ - | ``0x07`` | MEM_DATA | `RAM Download Data <#writing-data>`__ | Four 32-bit words: data size, sequence number, ``0``, ``0``, then data. Uses `Checksum`_. | | - +------------+----------------------+----------------------------------------------------------------+------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+-----------------------------------------------------------------------------------------------------------------------------------+ - | ``0x08`` | SYNC | `Sync Frame <#initial-synchronisation>`__ | 36 bytes: ``0x07 0x07 0x12 0x20``, followed by 32 x ``0x55`` | | - +------------+----------------------+----------------------------------------------------------------+------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+-----------------------------------------------------------------------------------------------------------------------------------+ - | ``0x09`` | WRITE_REG | `Write 32-bit memory address <#32-bit-readwrite>`__ | Four 32-bit words: address, value, mask and delay (in microseconds) | | - +------------+----------------------+----------------------------------------------------------------+------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+-----------------------------------------------------------------------------------------------------------------------------------+ - | ``0x0a`` | READ_REG | `Read 32-bit memory address <#32-bit-readwrite>`__ | Address as 32-bit word | Read data as 32-bit word in ``value`` field. | - +------------+----------------------+----------------------------------------------------------------+------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+-----------------------------------------------------------------------------------------------------------------------------------+ - | ``0x0b`` | SPI_SET_PARAMS | `Configure SPI flash <#spi-set-parameters>`__ | Six 32-bit words: id, total size in bytes, block size, sector size, page size, status mask. | | - +------------+----------------------+----------------------------------------------------------------+------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+-----------------------------------------------------------------------------------------------------------------------------------+ - | ``0x0d`` | SPI_ATTACH | `Attach SPI flash <#spi-attach-command>`__ | 32-bit word: Zero for normal SPI flash. A second 32-bit word (should be ``0``) is passed to ROM loader only. | | - +------------+----------------------+----------------------------------------------------------------+------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+-----------------------------------------------------------------------------------------------------------------------------------+ - | ``0x0f`` | CHANGE_BAUDRATE | `Change Baud rate <#initial-synchronisation>`__ | Two 32-bit words: new baud rate, ``0`` if we are talking to the ROM loader or the current/old baud rate if we are talking to the stub loader. | | - +------------+----------------------+----------------------------------------------------------------+------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+-----------------------------------------------------------------------------------------------------------------------------------+ - | ``0x10`` | FLASH_DEFL_BEGIN | `Begin compressed flash download <#writing-data>`__ | Four 32-bit words: uncompressed size, number of data packets, data packet size, flash offset. With stub loader the uncompressed size is exact byte count to be written, whereas on ROM bootloader it is rounded up to flash erase block size. | | - | | | | A fifth 32-bit word passed to ROM loader only: ``1`` to begin encrypted flash, ``0`` to not. | | - +------------+----------------------+----------------------------------------------------------------+------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+-----------------------------------------------------------------------------------------------------------------------------------+ - | ``0x11`` | FLASH_DEFL_DATA | `Compressed flash download data <#writing-data>`__ | Four 32-bit words: data size, sequence number, ``0``, ``0``, then data. Uses `Checksum`_. | Error code ``0xC1`` on checksum error. | - +------------+----------------------+----------------------------------------------------------------+------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+-----------------------------------------------------------------------------------------------------------------------------------+ - | ``0x12`` | FLASH_DEFL_END | `End compressed flash download <#writing-data>`__ | One 32-bit word: ``0`` to reboot, ``1`` to run user code. Not necessary to send this command if you wish to stay in the loader. | | - +------------+----------------------+----------------------------------------------------------------+------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+-----------------------------------------------------------------------------------------------------------------------------------+ - | ``0x13`` | SPI_FLASH_MD5 | `Calculate MD5 of flash region <#verifying-uploaded-data>`__ | Four 32-bit words: address, size, ``0``, ``0`` | Body contains 16 raw bytes of MD5 followed by 2 status bytes (stub loader) or 32 hex-coded ASCII (ROM loader) of calculated MD5 | - +------------+----------------------+----------------------------------------------------------------+------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+-----------------------------------------------------------------------------------------------------------------------------------+ - | ``0x14`` | GET_SECURITY_INFO | Read chip security info | | {IDF_TARGET_SECURITY_INFO} | - +------------+----------------------+----------------------------------------------------------------+------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+-----------------------------------------------------------------------------------------------------------------------------------+ - -Supported by stub loader only -""""""""""""""""""""""""""""" - -ROM loaders will not recognise these commands. - -+------------+-------------------+-----------------------------------+-------------------------------------------------------------------------------------------------------------------------+----------+ -| Byte | Name | Descripton | Input | Output | -+============+===================+===================================+=========================================================================================================================+==========+ -| ``0xd0`` | ERASE_FLASH | Erase entire flash chip | | | -+------------+-------------------+-----------------------------------+-------------------------------------------------------------------------------------------------------------------------+----------+ -| ``0xd1`` | ERASE_REGION | Erase flash region | Two 32-bit words: flash offset to erase, erase size in bytes. Both must be multiples of flash sector size. | | -+------------+-------------------+-----------------------------------+-------------------------------------------------------------------------------------------------------------------------+----------+ -| ``0xd2`` | READ_FLASH | `Read flash <#reading-flash>`__ | Four 32-bit words: flash offset, read length, flash sector size, read packet size, maximum number of un-acked packets | | -+------------+-------------------+-----------------------------------+-------------------------------------------------------------------------------------------------------------------------+----------+ -| ``0xd3`` | RUN_USER_CODE | Exits loader and runs user code | | | -+------------+-------------------+-----------------------------------+-------------------------------------------------------------------------------------------------------------------------+----------+ - -Checksum -^^^^^^^^ - -The checksum field is ignored (can be zero) for all comands except for MEM_DATA, FLASH_DATA, and FLASH_DEFL_DATA. - -Each of the ``_DATA`` command packets (like ``FLASH_DEFL_DATA``, ``MEM_DATA``) has the same "data payload" format: - -+---------+--------------------------+----------------------------------------------------------------+ -| Bytes | Name | Format | -+=========+==========================+================================================================+ -| 0-3 | "Data to write" length | Little endian 32-bit word. | -+---------+--------------------------+----------------------------------------------------------------+ -| 4-7 | Sequence number | Little endian 32-bit word. The sequence numbers are 0 based. | -+---------+--------------------------+----------------------------------------------------------------+ -| 8-15 | 0 | Two words of all zeroes, unused. | -+---------+--------------------------+----------------------------------------------------------------+ -| 16- | "Data to write" | Length given at beginning of payload. | -+---------+--------------------------+----------------------------------------------------------------+ - -The checksum is only applied to this final "data to write" section, not the first 16 bytes of data. - -To calculate checksum, start with seed value 0xEF and XOR each individual byte in the "data to write". The 8-bit result is stored in the checksum field of the packet header (as a little endian 32-bit value). - -.. note:: - - Because this checksum is not adequate to ensure valid data, the SPI_FLASH_MD5 command was added to validate flash contents after flashing. It is recommended that this command is always used. See `Verifying Uploaded Data`_, below. - -Functional Description ----------------------- - -Initial Synchronisation -^^^^^^^^^^^^^^^^^^^^^^^ -.. list:: - - :esp8266: * The ESP chip is reset into UART bootloader mode. The host starts by sending SYNC commands. These commands have a large data payload which is also used by the ESP chip to detect the configured baud rate. The ESP8266 will initialise at 74800bps with a 26MHz crystal and 115200bps with a 40MHz crystal. However the sync packets can be sent at any baud rate, and the UART peripheral will detect this. - :not esp8266: * The ESP chip is reset into UART bootloader mode. The host starts by sending SYNC commands. These commands have a large data payload which is also used by the ESP chip to detect the configured baud rate. {IDF_TARGET_NAME} always initialises at 115200bps. However the sync packets can be sent at any baud rate, and the UART peripheral will detect this. - * The host should wait until it sees a valid response to a SYNC command, indicating the ESP chip is correctly communicating. - * Esptool then (by default) uses the "RAM Download" sequence to upload :ref:`stub loader ` code to IRAM of the chip. The MEM_END command contains the entry-point address to run the stub loader. - The stub loader then sends a custom SLIP packet of the sequence OHAI (``0xC0 0x4F 0x48 0x41 0x49 0xC0``), indicating that it is now running. This is the only unsolicited packet ever sent by the ESP. - If the ``--no-stub`` argument is supplied to esptool, this entire step is skipped. - * esptool then uses READ_REG commands to read various addresses on the chip, to identify chip subtype, revision, etc. - :not esp8266: * For commands which need to use the flash, the {IDF_TARGET_NAME} ROM an stub loader requires the SPI_ATTACH and SPI_SET_PARAMS commands. See `SPI Configuration Commands`_. - :esp8266: * For stub loader, the host can send a CHANGE_BAUD command to set the baud rate to an explicit value. Compared to auto-detecting during the SYNC pulse, this can be more reliable for setting very high baud rate. Esptool tries to sync at (maximum) 115200bps and then sends this command to go to a higher baud rate, if requested. - :not esp8266: * For stub loader and/or {IDF_TARGET_NAME} ROM loader, the host can send a CHANGE_BAUD command to set the baud rate to an explicit value. Compared to auto-detecting during the SYNC pulse, this can be more reliable for setting very high baud rate. Esptool tries to sync at (maximum) 115200bps and then sends this command to go to a higher baud rate, if requested. - -Writing Data -^^^^^^^^^^^^ - -(Includes RAM Download, Flash Download, Compressed Flash Download.) - -.. list:: - - * RAM Download (MEM_BEGIN, MEM_DATA, MEM_END) loads data into the ESP chip memory space and (optionally) executes it. - * Flash Download (FLASH_BEGIN, FLASH_DATA) flashes data into the ESP SPI flash. - :esp8266: * Compressed Flash Download is the same, only the data is compressed using the gzip Deflate algorithm to reduce serial overhead. Not supported on ESP8266 ROM loader. - :not esp8266: * Compressed Flash Download is the same, only the data is compressed using the gzip Deflate algorithm to reduce serial overhead. - -All three of these sequences follow a similar pattern: - -* A _BEGIN command (FLASH_BEGIN, etc) is sent which contains basic parameters for the flash erase size, start address to write to, etc. The uploader also needs to specify how many "blocks" of data (ie individual data packets) will be sent, and how big each packet is. -* One or more _DATA commands (FLASH_DATA, etc) is sent where the data payload contains the actual data to write to flash/RAM. In the case of Compressed Flash Downloads, the data is compressed using the gzip deflate algorithm. The number of _DATA commands is specified in the _BEGIN command, as is the size of each _DATA payload. - The last data block should be padded to the block size with 0xFF bytes. -* An _END command (FLASH_END, etc) is sent to exit the bootloader and optionally reset the chip (or jump to an address in RAM, in the case of MEM_END). Not necessary to send after flashing if you wish to continue sending other or different commands. - -It's not necessary to send flash erase commands before sending commands to write to flash, etc. The ROM loaders erase the to-be-written region in response to the FLASH_BEGIN command. -The stub loader does just-in-time erasing as it writes data, to maximise overall flashing performance (each block of data is read into RAM via serial while the previous block is simultaneously being written to flash, and 4KB and 64KB erases are done as needed before writing to flash). - -The block size chosen should be small enough to fit into RAM of the device. Esptool uses 16KB which gives good performance when used with the stub loader. - -.. only:: esp8266 - - Erase Size Bug - """""""""""""" - - On ESP8266 ROM loader only (not stub loader), there is a bug in the interpretation of the FLASH_BEGIN "erase size" parameter. Consult the ``ESP8266ROM.get_erase_size()`` function in esptool for the algorithm which works around this bug and provides the correct erase size parameter to send to the ESP8266. - - This workaround is not needed if the ESP8266 is running the stub loader. - -Verifying Uploaded Data -""""""""""""""""""""""" - -.. only:: esp8266 - - The 8-bit checksum used in the upload protocol is not sufficient to ensure valid flash contents after upload. The uploader should send the SPI_FLASH_MD5 command (not supported on ESP8266 ROM loader) or use another method to verify flash contents. - -.. only:: not esp8266 - - The 8-bit checksum used in the upload protocol is not sufficient to ensure valid flash contents after upload. The uploader should send the SPI_FLASH_MD5 command or use another method to verify flash contents. - -The SPI_FLASH_MD5 command passes the start address in flash and the size of data to calculate. The MD5 value is returned in the response payload, before the status bytes. - -.. only:: not esp8266 - - Note that the {IDF_TARGET_NAME} ROM loader returns the md5sum as 32 hex encoded ASCII bytes, whereas the stub loader returns the md5sum as 16 raw data bytes of MD5 followed by 2 status bytes. - -SPI Configuration Commands -^^^^^^^^^^^^^^^^^^^^^^^^^^ - -SPI Attach command -"""""""""""""""""" - -The SPI _ATTACH command enables the SPI flash interface. It takes a 32-bit data payload which is used to determine which SPI peripheral and pins should be used to connect to SPI flash. - -.. only:: esp8266 - - On the ESP8266 stub loader sending this command before interacting with SPI flash is optional. On ESP8266 ROM loader this command is not supported (SPI flash is enabled when the FLASH_BEGIN command is sent). - - +------------------+----------------------------------------------------------------------------------------------------------------------------------+ - | Value | Meaning | - +==================+==================================================================================================================================+ - | 0 | Default SPI flash interface | - +------------------+----------------------------------------------------------------------------------------------------------------------------------+ - | 1 | HSPI interface | - +------------------+----------------------------------------------------------------------------------------------------------------------------------+ - -.. only:: not esp8266 - - On the {IDF_TARGET_NAME} stub loader, it is required to send this command before interacting with SPI flash. - - +------------------+----------------------------------------------------------------------------------------------------------------------------------+ - | Value | Meaning | - +==================+==================================================================================================================================+ - | 0 | Default SPI flash interface | - +------------------+----------------------------------------------------------------------------------------------------------------------------------+ - | 1 | HSPI interface | - +------------------+----------------------------------------------------------------------------------------------------------------------------------+ - | (other values) | Pin numbers as 6-bit values, packed into a 30-bit value. Order (from MSB): HD pin, Q pin, D pin, CS pin, CLK pin. | - +------------------+----------------------------------------------------------------------------------------------------------------------------------+ - - The "Default SPI flash interface" uses pins configured via the ``SPI_PAD_CONFIG_xxx`` efuses (if unset, these efuses are all zero and the default SPI flash pins given in the datasheet are used.) - - When writing the values of each pin as 6-bit numbers packed into the data word, each 6-bit value uses the following representation: - - * Pin numbers 0 through 30 are represented as themselves. - * Pin numbers 32 & 33 are represented as values 30 & 31. - * It is not possible to represent pins 30 & 31 or pins higher than 33. This is the same 6-bit representation used by the ``SPI_PAD_CONFIG_xxx`` efuses. - - On {IDF_TARGET_NAME} ROM loader only, there is an additional 4 bytes in the data payload of this command. These bytes should all be set to zero. - -SPI Set Parameters -"""""""""""""""""" - -The SPI_SET_PARAMS command sets some parameters of the attached SPI flash chip (sizes, etc). - -.. only:: esp8266 - - This command is not supported by the ESP8266 ROM loader. - -All the values which are passed except total size are hardcoded, and most are not used when writing to flash. See `flash_set_parameters function `__ in esptool for the values which it sends. - -32-bit Read/Write -^^^^^^^^^^^^^^^^^ - -The 32-bit read/write commands (READ_REG, WRITE_REG) allow word-oriented reading and writing of memory and register data. - -These commands can be used to manipulate peripherals in arbitrary ways. For example, the esptool "flash id" functionality is implemented by manipulating the SPI peripheral registers to send a JEDEC flash ID command to the flash chip and read the response. - -Reading Flash -^^^^^^^^^^^^^ - -The stub loader implements a READ_FLASH command. This command behaves differently to other commands, including the ROM loader's READ_FLASH command: - -* The host sends the READ_FLASH command and the data payload contains the offset, read size, size of each individual packet of data, and the maximum number of "un-acknowledged" data packets which can be in flight at one time. -* The stub loader will send a standard response packet, with no additional data payload. -* Now the stub loader will start sending SLIP packets with raw data (of the size requested in the command). There is no metadata included with these SLIP packets. -* After each SLIP packet is received, the host should send back a 4 byte raw SLIP acknowledgement packet with the total number of bytes which have been received. There is no header or other metadata included with these SLIP packets. -* The stub loader may send up to a maximum number (specified by the host in the READ_FLASH commands) of data packets before waiting for the first acknowledgement packet. No more than this "max in flight" limit can be un-acknowledged at any one time. -* After all data packets are acknowledged received, the stub loader sends a 16 byte MD5 digest of all the data which was read from flash. This is also sent as a raw SLIP packet, with no metadata. - -After the read flash process is complete, the stub loader goes back to normal command/response operation. - -The ROM loader read flash command is more normal but also much slower to read data. - -.. _tracing-communications: - -Tracing Esptool Serial Communications -------------------------------------- - -esptool has a ``--trace`` option which can be supplied in the first group of arguments (before the command). This will dump all traffic sent and received via the serial port to the console. - -Here is a sample extract, showing a READ_REG command and response: - -:: - - TRACE +0.000 command op=0x0a data len=4 wait_response=1 timeout=3.000 data=1400f43f - TRACE +0.000 Write 14 bytes: c0000a0400000000001400f43fc0 - TRACE +0.005 Read 1 bytes: c0 - TRACE +0.000 Read 11 bytes: 010a0200620100000000c0 - TRACE +0.000 Received full packet: 010a0200620100000000 - -The +X.XXX value is the time delta (in seconds) since the last trace line. - -Values are printed in hexadecimal. If more than 16 bytes is printed at one time, a split display is used with hexadecimal bytes on the left and ASCII on the right. Non-printable characters are represented as ``.`` in ASCII: - -Note that multiple protocol layers are represented in the logs. The "Write X bytes" lines show exactly which bytes are being sent "over the wire", including SLIP framing. Similarly the "Read X bytes" lines show what bytes are being read over the wire, including any SLIP framing. -Once a full SLIP packet is read, the same bytes - as a SLIP payload with any escaping removed - appear in the "Received full packet" log lines. - -Here is a second example showing part of the initial synchronization sequence (lots of 0x55 bytes which are ``U`` in ASCII): - -:: - - TRACE +0.000 Write 46 bytes: - c000082400000000 0007071220555555 | ...$........ UUU - 5555555555555555 5555555555555555 | UUUUUUUUUUUUUUUU - 5555555555555555 5555555555c0 | UUUUUUUUUUUUU. - TRACE +0.011 Read 1 bytes: c0 - TRACE +0.000 Read 63 bytes: - 0108040007122055 00000000c0c00108 | ...... U........ - 0400071220550000 0000c0c001080400 | .... U.......... - 0712205500000000 c0c0010804000712 | .. U............ - 205500000000c0c0 01080400071220 | U............ - TRACE +0.000 Received full packet: 010804000712205500000000 - TRACE +0.000 Received full packet: 010804000712205500000000 - -.. important:: - - If you don't plan to use the esptool stub loader, pass ``--no-stub --trace`` to see interactions with the chip's built-in ROM loader only. Otherwise, the trace will show the full binary upload of the loader. - -In addition to this trace feature, most operating systems have "system call trace" or "port trace" features which can be used to dump serial interactions. diff --git a/docs/en/advanced-topics/spi-flash-modes.rst b/docs/en/advanced-topics/spi-flash-modes.rst deleted file mode 100644 index 22b54766d..000000000 --- a/docs/en/advanced-topics/spi-flash-modes.rst +++ /dev/null @@ -1,114 +0,0 @@ -.. _spi-flash-modes: - -SPI Flash Modes -=============== - -The ESP chips support four different SPI flash access modes: DIO, DOUT, QIO & QOUT. These can be set via the ``--flash_mode`` option of ``esptool.py write_flash``. - -These options control how many I/O pins are used for communication with the attached SPI flash chip, and which SPI commands are used. - -ESP chips use these commands when reading or executing code and data from the SPI flash chip. Data is read and then cached internally to the chip. - -Summary -------- - -In order of performance: - -+------------+---------------+----------------------------------+-----------------------------------+ -| Option | Mode Name | Pins Used | Speed (ESP device) | -+============+===============+==================================+===================================+ -| ``qio`` | Quad I/O | 4 pins used for address & data | Fastest. | -+------------+---------------+----------------------------------+-----------------------------------+ -| ``qout`` | Quad Output | 4 pins used for data. | Approx 15% slower than ``qio``. | -+------------+---------------+----------------------------------+-----------------------------------+ -| ``dio`` | Dual I/O | 2 pins used for address & data | Approx 45% slower than ``qio``. | -+------------+---------------+----------------------------------+-----------------------------------+ -| ``dout`` | Dual Output | 2 pins used for data. | Approx 50% slower than ``qio``. | -+------------+---------------+----------------------------------+-----------------------------------+ - -In general, choose the fastest option for flash_mode that works with your device. Not all devices support all modes. See FAQ below for details. - -Mode Descriptions ------------------ - -Normal SPI -^^^^^^^^^^ - -A traditional "single" SPI (Serial Peripheral Interface) bus uses 4 pins for communication: - -* Clock (CLK) -* Master Out Slave In (MOSI) -* Master In Slave Out (MISO) -* Chip Select (CS) - -`Wikipedia has a fairly complete description `__. - -All of these signals are unidirectional. In single SPI mode, data is sent from the device to the host using the MISO pin and from the host to the device using the MOSI pin. - -The maximum data rate for normal SPI is the clock rate in bits - so a 40MHz clock = 40Mbits/sec = 5Mbytes/sec. - -Dual SPI -^^^^^^^^ - -To improve performance, SPI flash manufacturers introduced "Dual SPI". In Dual SPI modes, the MOSI & MISO pins are both used to read or write data simultaneously with two bits per clock cycle. This doubles the data rate for some commands, compared to single SPI. - -In ``dout`` mode, the host uses the "Dual Output Fast Read" (3BH) command to read data. Each read command and the read address is sent from the host to the flash chip via normal SPI, but then the host reads the data via both the MOSI & MISO pins simultaneously with two bits per clock. -This doubles the data transfer rate compared to single SPI which only uses MISO to read data. - -In ``dio`` mode, the host uses the "Dual I/O Fast Read" (BBH) command to read data. Each read command is sent from the host to the flash chip via normal SPI, but then the address is sent to the flash chip via both the MOSI & MISO pins with two bits per clock. -After this, the host reads the data bits with two bits per clock in the same way as "Dual Output Fast Read". - -For ESP chips, 32 bytes is read per command and ``dio`` mode is approximately 5% faster than ``dout``. - -Consult the datasheet for your particular SPI flash chip to determine if it supports either or both of these commands. - -Quad SPI -^^^^^^^^ - -To further improve the performance of SPI flash data transfers, SPI flash manufacturers introduced "Quad SPI" mode. This mode added two additional pins (otherwise used for flash chip ``WP`` and ``HOLD`` signals) for data transfers. This allows double the data rate of dual SPI. - -Not all flash chips support Quad SPI modes, and not all ESP chips have these pins wired up to the SPI flash chip. Some flash chips require special commands to enable quad modes (see below). - -In ``qout`` mode, the host uses the "Quad Output Fast Read" (6BH) command to read data. This command is the same as "Dual Output Fast Read", only data is read on 4 pins instead of 2 with 4 bits per clock cycle. This makes the data transfer exactly twice as fast as "Dual Output Fast Read". - -In ``qio`` mode, the host uses the "Quad I/O Fast Read" (EBH) command to read data. This command is the same as "Dual I/O Fast Read", only both address & data are transferred on 4 pins instead of 2 with 4 bits per clock cycle. -This makes both the address & data transfer exactly twice as fast as "Dual I/O Fast Read". - -Frequently Asked Questions --------------------------- - -Why don't qio & qout modes work with my Espressif chip/module? -^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - -It is usually one of the following reasons: - -* The WP and HOLD pins of the SPI flash chip are not wired to the correct GPIOs of the Espressif chip. These pins must be connected correctly for quad modes to work, and not all boards/modules connect them at all. -* The SPI flash chip does not support quad modes. Look up the flash chip datasheet to see which modes it supports. You can identify the flash chip visually, or by using the :ref:`esptool.py flash_id ` command. -* Quad mode is not enabled correctly for this chip model. SPI flash is not a standard, so every manufacturer implements their chip differently. Most flash chips require certain commands to be sent in order to enable Quad SPI modes, and these commands vary. - For Espressif chips, this often means that the chip first boots in a Dual SPI mode and then software detects the chip type and tries to enable Quad SPI mode. - If the particular chip model is not supported by the software then it won't be able to enter quad mode. - -Why does qout/dout mode work but qio/dio mode doesn't work? -^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - -Some SPI flash chip models only support the "Dual Output Fast Read" and/or "Quad Output Fast Read" commands, not their Dual I/O & Quad I/O equivalents. - -Will my code run half as fast in Dual SPI mode compared to Quad SPI? -^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - -No. Espressif chips execute code directly from flash, however because reading from flash is slow the data is cached transparently in RAM. Flash read commands are only sent went a cache miss occurs. -However, refilling the cache with a Dual SPI read is approximately half as fast as its Quad SPI equivalent. - -If you can't use the Quad SPI modes, make sure you are configuring the fastest SPI Flash clock rate that works reliably on your board/module. An 80MHz SPI clock in Dual I/O mode is faster than a 40MHz SPI clock in Quad I/O mode. - -How is flash mode communicated to the Espressif chip? -^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - -The bootloader .bin file, flashed to the SPI flash, contains a header which has flash speed, flash mode, and some other metadata. The initial host mode is determined by ROM code when it reads this header after reset. -Passing the ``--flash_mode`` argument to esptool will update this header when the file is being written to flash. - -This only determines the mode which is used for the initial boot from reset. Software may then configure the flash mode differently as part of the boot process. - -For example, on ESP32 if ESP-IDF is configured for qio/qout mode then the IDF software bootloader is actually flashed with a dio/dout mode. -When ROM code boots this bootloader from flash, the bootloader software checks the flash chip model and enables the correct Quad SPI mode for the rest of the boot process. -This is because of the multiple different ways to enable Quad SPI on different chip models. diff --git a/docs/en/conf.py b/docs/en/conf.py deleted file mode 100644 index 0362dfc3e..000000000 --- a/docs/en/conf.py +++ /dev/null @@ -1,29 +0,0 @@ -# -*- coding: utf-8 -*- -# -# English Language RTD & Sphinx config file -# -# Uses ../conf_common.py for most non-language-specific settings. - -# Importing conf_common adds all the non-language-specific -# parts to this conf module - -import datetime - -try: - from conf_common import * # noqa: F403,F401 -except ImportError: - import os - import sys - - sys.path.insert(0, os.path.abspath("../")) - from conf_common import * # noqa: F403,F401 - -# General information about the project. -project = "esptool.py" -copyright = "2016 - {}, Espressif Systems (Shanghai) Co., Ltd".format( - datetime.datetime.now().year -) - -# The language for content autogenerated by Sphinx. Refer to documentation -# for a list of supported languages. -language = "en" diff --git a/docs/en/contributing.rst b/docs/en/contributing.rst deleted file mode 100644 index ac7b6bcf3..000000000 --- a/docs/en/contributing.rst +++ /dev/null @@ -1 +0,0 @@ -.. include:: ../../CONTRIBUTING.rst diff --git a/docs/en/espefuse/adc-info-cmd.rst b/docs/en/espefuse/adc-info-cmd.rst deleted file mode 100644 index e7c11f22c..000000000 --- a/docs/en/espefuse/adc-info-cmd.rst +++ /dev/null @@ -1,60 +0,0 @@ -.. _adc-info-cmd: - -Adc Info -======== - -The ``espefuse.py adc_info`` command displays information about ADC calibration data stored in eFuse. - -.. only:: esp32 - - .. code-block:: none - - > espefuse.py adc_info - - === Run "adc_info" command === - ADC VRef calibration: 1121mV - -.. only:: esp32c3 or esp32s2 or esp32s3 - - .. code-block:: none - - > espefuse.py adc_info - - === Run "adc_info" command === - Temperature Sensor Calibration = -2.1C - - ADC1 readings stored in efuse BLOCK2: - MODE0 D1 reading (250mV): 76 - MODE0 D2 reading (600mV): 340 - MODE1 D1 reading (250mV): -100 - MODE1 D2 reading (800mV): 356 - MODE2 D1 reading (250mV): 116 - MODE2 D2 reading (1000mV): -136 - MODE3 D1 reading (250mV): 8 - MODE3 D2 reading (2000mV): 304 - - ADC2 readings stored in efuse BLOCK2: - MODE0 D1 reading (250mV): 0 - MODE0 D2 reading (600mV): 168 - MODE1 D1 reading (250mV): 0 - MODE1 D2 reading (800mV): 300 - MODE2 D1 reading (250mV): 0 - MODE2 D2 reading (1000mV): -404 - MODE3 D1 reading (250mV): 0 - MODE3 D2 reading (2000mV): -32 - -.. only:: esp32c2 - - .. code-block:: none - - > espefuse.py adc_info - - === Run "adc_info" command === - RF_REF_I_BIAS_CONFIG: 0 - LDO_VOL_BIAS_CONFIG_LOW: 0 - LDO_VOL_BIAS_CONFIG_HIGH: 0 - PVT_LOW: 0 - PVT_HIGH: 0 - ADC_CALIBRATION_0: 0 - ADC_CALIBRATION_1: 0 - ADC_CALIBRATION_2: 0 diff --git a/docs/en/espefuse/burn-bit-cmd.rst b/docs/en/espefuse/burn-bit-cmd.rst deleted file mode 100644 index 13f22ede6..000000000 --- a/docs/en/espefuse/burn-bit-cmd.rst +++ /dev/null @@ -1,74 +0,0 @@ -.. _burn-bit-cmd: - -Burn Bit -======== - -The ``espefuse.py burn_bit`` command burns bits in efuse blocks by bit number. This is useful when the fields are not represented in the eFuse table. - -Positional arguments: - -- ``block`` - Efuse block. -- ``bit number`` - Bit number in the efuse block [0..BLK_LEN-1] (list of numbers, like 10 15 18 17 5 etc.). - -Optional arguments: - -- ``--force-write-always``. Burn it even if it looks like it is already been written, or is write protected. Note that this option can not disable write protection, or clear any bit which has already been set. - -Usage ------ - -Burning bits to BLOCK2: - -.. code-block:: none - - > espefuse.py burn_bit BLOCK2 15 16 17 18 19 20 - - === Run "burn_bit" command === - bit_number: [255]........................................................[0] - BLOCK2 : 0x00000000000000000000000000000000000000000000000000000000001f8000 - BLOCK2 (secure_boot_v1 s) [2 ] regs_to_write: 001f8000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 - - Check all blocks for burn... - idx, BLOCK_NAME, Conclusion - [02] BLOCK2 is empty, will burn the new value - . - This is an irreversible operation! - Type 'BURN' (all capitals) to continue. - BURN - BURN BLOCK2 - OK (write block == read block) - Reading updated efuses... - Successful - -Burning In Multiple Blocks -^^^^^^^^^^^^^^^^^^^^^^^^^^ - -.. code-block:: none - - > espefuse.py --virt burn_bit BLOCK2 15 16 17 18 19 20 \ - burn_bit BLOCK3 15 16 17 18 19 20 - - === Run "burn_bit" command === - bit_number: [255]........................................................[0] - BLOCK2 : 0x00000000000000000000000000000000000000000000000000000000001f8000 - BLOCK2 (secure_boot_v1 s) [2 ] regs_to_write: 001f8000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 - - Batch mode is enabled, the burn will be done at the end of the command. - - === Run "burn_bit" command === - bit_number: [255]........................................................[0] - BLOCK3 : 0x00000000000000000000000000000000000000000000000000000000001f8000 - BLOCK3 ( ) [3 ] regs_to_write: 001f8000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 - - Batch mode is enabled, the burn will be done at the end of the command. - - Check all blocks for burn... - idx, BLOCK_NAME, Conclusion - [02] BLOCK2 is empty, will burn the new value - [03] BLOCK3 is empty, will burn the new value - . - This is an irreversible operation! - Type 'BURN' (all capitals) to continue. - BURN - BURN BLOCK3 - OK (write block == read block) - BURN BLOCK2 - OK (write block == read block) - Reading updated efuses... diff --git a/docs/en/espefuse/burn-block-data-cmd.rst b/docs/en/espefuse/burn-block-data-cmd.rst deleted file mode 100644 index 333c5db84..000000000 --- a/docs/en/espefuse/burn-block-data-cmd.rst +++ /dev/null @@ -1,59 +0,0 @@ -.. _burn-block-data-cmd: - -Burn Block Data -=============== - -The ``espefuse.py burn_block_data`` command allows writing arbitrary data (non-key data) from a file into an eFuse block, for software use. - -This command is available in ``espefuse.py`` v2.6 and newer. - -Positional arguments: - -* ``Name of key block`` -* ``Datafile``. File containing data to burn into the efuse block. The file size can be smaller than the eFuse block size. - -It can be list of blocks and datafiles (like BLOCK1 datafile1.bin BLOCK2 datafile2.bin etc.). - -Optional arguments: - -* ``--force-write-always``. Write the eFuse key even if it looks like it is already been written, or is write protected. Note that this option can't disable write protection, or clear any bit which has already been set. -* ``--offset``. Byte offset in the eFuse block. - -**Example:** Write to eFuse BLOCK3 from binary file ``device_id.bin``, starting at eFuse byte offset 6: - -.. code-block:: none - - > espefuse.py -p PORT burn_block_data --offset 6 BLOCK3 device_id.bin - - === Run "burn_block_data" command === - [03] BLOCK3 size=32 bytes, offset=06 - > [00 00 00 00 00 00 00 01 02 03 04 05 06 07 08 09 0a 0b 0c 0d 0e 0f 00 00 00 00 00 00 00 00 00 00]. - - Check all blocks for burn... - idx, BLOCK_NAME, Conclusion - [03] BLOCK3 is empty, will burn the new value - . - This is an irreversible operation! - Type 'BURN' (all capitals) to continue. - BURN - BURN BLOCK3 - OK (write block == read block) - Reading updated efuses... - Successful - -Peculiarities -------------- - -1. Data is written to the eFuse block in normal byte order (treating the eFuse block as if it was an array of bytes). It can be read back in firmware using eFuse API or from the eFuse read registers (but these reads must be always be complete register words, 4-byte aligned). - -.. code-block:: none - - > espefuse.py dump - ... - BLOCK3 ( ) [3 ] read_regs: 00000000 01000000 05040302 09080706 0d0c0b0a 00000f0e 00000000 00000000 - - > espefuse.py summary - .... - BLOCK3 (BLOCK3): Variable Block 3 - = 00 00 00 00 00 00 00 01 02 03 04 05 06 07 08 09 0a 0b 0c 0d 0e 0f 00 00 00 00 00 00 00 00 00 00 R/W - -2. Part of the eFuse block can be written at a time. The ``--offset`` argument allows writing to a byte offset inside the eFuse block itself. -3. This command is not suitable for writing key data which will be used by flash encryption or secure boot hardware, use ``burn_key`` for this. diff --git a/docs/en/espefuse/burn-custom-mac-cmd.rst b/docs/en/espefuse/burn-custom-mac-cmd.rst deleted file mode 100644 index 3ccebfae6..000000000 --- a/docs/en/espefuse/burn-custom-mac-cmd.rst +++ /dev/null @@ -1,120 +0,0 @@ -.. _burn-custom-mac-cmd: - -Burn Custom Mac -=============== - -The ``espefuse.py burn_custom_mac`` command burns a 48-bit Custom MAC Address. - -Positional arguments: - -* ``MAC``. Custom MAC Address (``CUSTOM_MAC``) to burn given in hexadecimal format with bytes separated by colons (e.g. AA:CD:EF:01:02:03) - -Optional arguments: - -* ``--force-write-always``. Write the eFuse key even if it looks like it is already been written, or is write protected. Note that this option can't disable write protection, or clear any bit which has already been set. - -If ``CUSTOM_MAC`` is placed in an eFuse block with a coding scheme and already has data then it is not possible to write new data without breaking the encoding. The correct way is to contact Espressif to order chips with ``CUSTOM_MAC`` pre-burned from the factory. Another way is, it is not recommended, to use the ``--force-write-always`` flag to ignore the encoding violation. - -.. only:: esp32 - - This command burns a few eFuse fields: - - 1. ``CUSTOM_MAC`` - 2. ``MAC_VERSION`` = 1 - 3. ``CUSTOM_MAC_CRC`` = crc8(``CUSTOM_MAC``) - - .. code-block:: none - - > espefuse.py burn_custom_mac 48:63:92:15:72:16 - - === Run "burn_custom_mac" command === - - 'MAC_VERSION' (Version of the MAC field) 0x00 -> 0x1 - - 'CUSTOM_MAC' (Custom MAC) 0x000000000000 -> 0x167215926348 - - 'CUSTOM_MAC_CRC' (CRC of custom MAC) 0x00 -> 0x75 - - Check all blocks for burn... - idx, BLOCK_NAME, Conclusion - [03] BLOCK3 is empty, will burn the new value - . - This is an irreversible operation! - Type 'BURN' (all capitals) to continue. - BURN - BURN BLOCK3 - OK (write block == read block) - Reading updated efuses... - Custom MAC Address version 1: 48:63:92:15:72:16 (CRC 0x75 OK) - Successful - - > espefuse.py summary - ... - MAC_VERSION (BLOCK3): Version of the MAC field = Custom MAC in BLOCK3 R/W (0x01) - CUSTOM_MAC (BLOCK3): Custom MAC - = 48:63:92:15:72:16 (CRC 0x75 OK) R/W - CUSTOM_MAC_CRC (BLOCK3): CRC of custom MAC = 117 R/W (0x75) - ... - BLOCK3 (BLOCK3): Variable Block 3 - = 75 48 63 92 15 72 16 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 01 00 00 00 00 00 00 00 00 R/W - -.. only:: esp32c2 - - This command burns a few eFuse fields: - - 1. ``CUSTOM_MAC`` - 2. ``CUSTOM_MAC_USED`` = 1 - - .. code-block:: none - - > espefuse.py burn_custom_mac 48:63:92:15:72:16 - - === Run "burn_custom_mac" command === - - 'CUSTOM_MAC' (Custom MAC addr) 0x000000000000 -> 0x167215926348 - - Check all blocks for burn... - idx, BLOCK_NAME, Conclusion - [00] BLOCK0 is not empty - (written ): 0x0000000000000080 - (to write): 0x0400000000000000 - (coding scheme = NONE) - [01] BLOCK1 is empty, will burn the new value - . - This is an irreversible operation! - Type 'BURN' (all capitals) to continue. - BURN - BURN BLOCK1 - OK (write block == read block) - BURN BLOCK0 - OK (all write block bits are set) - Reading updated efuses... - Custom MAC Address: 48:63:92:15:72:16 (OK) - Successful - - > espefuse.py summary - ... - CUSTOM_MAC_USED (BLOCK0) Enable CUSTOM_MAC programming = True R/W (0b1) - CUSTOM_MAC (BLOCK1) Custom MAC addr - = 48:63:92:15:72:16 (OK) R/W - -.. only:: esp32c3 or esp32s2 or esp32s3 - - This command burns a given MAC to ``CUSTOM_MAC`` field. - - .. code-block:: none - - > espefuse.py burn_custom_mac 48:63:92:15:72:16 - - === Run "burn_custom_mac" command === - - 'CUSTOM_MAC' (Custom MAC Address) 0x000000000000 -> 0x167215926348 - - Check all blocks for burn... - idx, BLOCK_NAME, Conclusion - [03] BLOCK_USR_DATA is empty, will burn the new value - . - This is an irreversible operation! - Type 'BURN' (all capitals) to continue. - BURN - BURN BLOCK3 - OK (write block == read block) - Reading updated efuses... - Custom MAC Address: 48:63:92:15:72:16 (OK) - Successful - - > espefuse.py summary - ... - CUSTOM_MAC (BLOCK3) Custom MAC Address - = 48:63:92:15:72:16 (OK) R/W \ No newline at end of file diff --git a/docs/en/espefuse/burn-efuse-cmd.rst b/docs/en/espefuse/burn-efuse-cmd.rst deleted file mode 100644 index b5d974316..000000000 --- a/docs/en/espefuse/burn-efuse-cmd.rst +++ /dev/null @@ -1,101 +0,0 @@ -.. _burn-efuse-cmd: - -Burn Efuse -========== - -The ``espefuse.py burn_efuse`` command burns eFuses. The arguments to ``burn_efuse`` are eFuse names (as shown in summary output) and new values. - -Positional arguments: - -- ``eFuse name`` -- ``value`` - -It can be list of eFuse names and values (like EFUSE_NAME1 1 EFUSE_NAME2 7 EFUSE_NAME3 10 etc.). - -New values can be a numeric value in decimal or hex (with "0x" prefix). eFuse bits can only be burned from 0 to 1, attempting to set any back to 0 will have no effect. Most eFuses have a limited bit width (many are only 1-bit flags). Longer eFuses (MAC addresses, keys) can be set with this command, but it's better to use a specific command (``burn_custom_mac``, ``burn_key``) for a specific field. - -This command supports simultaneous burning of multiple eFuses, it doesn't matter if they are from different eFuse blocks or not. The format is the same as for burning just one eFuse, just list the eFuse name and value pairs, see the example below. - -.. code-block:: none - - > espefuse.py --port /dev/ttyUSB0 burn_efuse DIS_USB_JTAG 1 VDD_SPI_AS_GPIO 1 - - === Run "burn_efuse" command === - The efuses to burn: - from BLOCK0 - - DIS_USB_JTAG - - VDD_SPI_AS_GPIO - - Burning efuses: - - - 'DIS_USB_JTAG' (Disables USB JTAG. JTAG access via pads is controlled separately) 0b0 -> 0b1 - - 'VDD_SPI_AS_GPIO' (Set this bit to vdd spi pin function as gpio) 0b0 -> 0b1 - - Check all blocks for burn... - idx, BLOCK_NAME, Conclusion - [00] BLOCK0 is empty, will burn the new value - . - This is an irreversible operation! - Type 'BURN' (all capitals) to continue. - -By default, ``espefuse.py`` will ask you to type ``BURN`` before it permanently sets eFuses. The ``--do-not-confirm`` option allows you to bypass this. - -.. code-block:: none - - BURN - BURN BLOCK0 - OK (write block == read block) - Reading updated efuses... - Checking efuses... - Successful - -.. _espefuse-spi-flash-pins: - -SPI Flash Pins --------------- - -The following efuses configure the SPI flash pins which are used to boot: - -.. only:: esp32 - - .. code-block:: none - - SPI_PAD_CONFIG_CLK Override SD_CLK pad (GPIO6/SPICLK) = 0 R/W (0x0) - SPI_PAD_CONFIG_Q Override SD_DATA_0 pad (GPIO7/SPIQ) = 0 R/W (0x0) - SPI_PAD_CONFIG_D Override SD_DATA_1 pad (GPIO8/SPID) = 0 R/W (0x0) - SPI_PAD_CONFIG_HD Override SD_DATA_2 pad (GPIO9/SPIHD) = 0 R/W (0x0) - SPI_PAD_CONFIG_CS0 Override SD_CMD pad (GPIO11/SPICS0) = 0 R/W (0x0) - -.. only:: not esp32 - - .. code-block:: none - - Spi_Pad_Config fuses: - SPI_PAD_CONFIG_CLK (BLOCK1) SPI CLK pad = 0 R/W (0b000000) - SPI_PAD_CONFIG_Q (BLOCK1) SPI Q (D1) pad = 0 R/W (0b000000) - SPI_PAD_CONFIG_D (BLOCK1) SPI D (D0) pad = 0 R/W (0b000000) - SPI_PAD_CONFIG_CS (BLOCK1) SPI CS pad = 0 R/W (0b000000) - SPI_PAD_CONFIG_HD (BLOCK1) SPI HD (D3) pad = 0 R/W (0b000000) - SPI_PAD_CONFIG_WP (BLOCK1) SPI WP (D2) pad = 0 R/W (0b000000) - SPI_PAD_CONFIG_DQS (BLOCK1) SPI DQS pad = 0 R/W (0b000000) - SPI_PAD_CONFIG_D4 (BLOCK1) SPI D4 pad = 0 R/W (0b000000) - SPI_PAD_CONFIG_D5 (BLOCK1) SPI D5 pad = 0 R/W (0b000000) - SPI_PAD_CONFIG_D6 (BLOCK1) SPI D6 pad = 0 R/W (0b000000) - SPI_PAD_CONFIG_D7 (BLOCK1) SPI D7 pad = 0 R/W (0b000000) - -On {IDF_TARGET_NAME} chips without integrated SPI flash, these eFuses are left zero at the factory. This causes the default GPIO pins (shown in the summary output above) to be used for the SPI flash. - -On {IDF_TARGET_NAME} chips with integrated internal SPI flash, these eFuses are burned in the factory to the GPIO numbers where the flash is connected. These values override the defaults on boot. - -In order to change the SPI flash pin configuration, these eFuses can be burned to the GPIO numbers where the flash is connected. If at least one of these eFuses is burned, all of of them must be set to the correct values. - -If these eFuses are burned, GPIO1 (U0TXD pin) is no longer consulted to set the boot mode from SPI to HSPI flash on reset. - -These pins can be set to any GPIO number in the range 0-29, 32 or 33. Values 30 and 31 cannot be set. The "raw" hex value for pins 32, 33 is 30, 31 (this is visible in the summary output if these pins are configured for any SPI I/Os.) - -For example: - -.. code-block:: none - - SPI_PAD_CONFIG_CS0 Override SD_CMD pad (GPIO11/SPICS0) = 32 R/W (0x1e) - -If using the ``burn_efuse`` command to configure these pins, always specify the actual GPIO number you wish to set. diff --git a/docs/en/espefuse/burn-key-cmd.rst b/docs/en/espefuse/burn-key-cmd.rst deleted file mode 100644 index b3a394f5c..000000000 --- a/docs/en/espefuse/burn-key-cmd.rst +++ /dev/null @@ -1,321 +0,0 @@ -.. _burn-key-cmd: - -Burn Key -======== - -The ``espefuse.py burn_key`` command burns keys to eFuse blocks: - -.. list:: - - :esp32: - `Secure Boot V1 `_ - - `Secure Boot V2 `_ - - `Flash Encryption `_ - - etc. - -Positional arguments: - -.. list:: - - - ``block`` - Name of key block. - :esp32: - ``Keyfile``. It is a raw binary file. It must contain 256 bits of binary key if the coding scheme is ``None`` and 128 bits if ``3/4``. - :not esp32: - ``Keyfile``. It is a raw binary file. The length of binary key depends on the key purpose option. - :not esp32: - ``Key purpose``. The purpose of this key. - -.. only:: esp32 - - It can be list of key blocks and keyfiles (like BLOCK1 file1.bin BLOCK2 file2.bin etc.). - -.. only:: not esp32 - - It can be list of key blocks and keyfiles and key purposes (like BLOCK_KEY1 file1.bin USER BLOCK_KEY2 file2.bin USER etc.). - -Optional arguments: - -.. list:: - - :esp32: - ``--no-protect-key``. Disable default read and write protecting of the key. If this option is not set, once the key is flashed it can not be read back. - :not esp32: - ``--no-write-protect``. Disable write-protecting of the key. The key remains writable. The keys use the RS coding scheme that does not support post-write data changes. Forced write can damage RS encoding bits. The write-protecting of keypurposes does not depend on the option, it will be set anyway. - :not esp32: - ``--no-read-protect``. Disable read-protecting of the key. The key remains readable software. The key with keypurpose [USER, RESERVED and .._DIGEST] will remain readable anyway, but for the rest keypurposes the read-protection will be defined by this option (Read-protect by default). - - ``--force-write-always``. Write the eFuse key even if it looks like it is already been written, or is write protected. Note that this option can't disable write protection, or clear any bit which has already been set. - -.. only:: esp32 - - {IDF_TARGET_NAME} supportes keys: - - * Secure boot key. Use ``secure_boot_v1`` or ``secure_boot_v2`` as block name. The key is placed in BLOCK2. - * Flash encryption key. Use ``flash_encryption`` as block name. The key is placed in BLOCK1. - - Keys for ``flash_encryption`` and ``secure_boot_v1`` will be burned as read and write protected. The hardware will still have access to them. These keys are burned in reversed byte order. - - Key for ``secure_boot_v2`` will be burned only as write protected. The key must be readable because the software need acces to it. - - .. warning:: - - Do not use the names ``BLOCK1`` and ``BLOCK2`` to burn flash encryption and secure boot v2 keys because byte order will be incorrect and read protection will not meet security requirements. - -.. only:: esp32c3 or esp32s2 or esp32s3 - - {IDF_TARGET_NAME} supportes eFuse key purposes. This means that each eFuse block has a special eFuse field that indicates which key is in the eFuse block. During the burn operation this eFuse key purpose is burned as well with write protection (the ``--no-write-protect`` flag has no effect on this field). The {IDF_TARGET_NAME} chip supports the following key purposes: - - .. list:: - - - USER. - - RESERVED. - :esp32s2 or esp32s3: - XTS_AES_256_KEY_1. The first 256 bits of 512bit flash encryption key. - :esp32s2 or esp32s3: - XTS_AES_256_KEY_2. The second 256 bits of 512bit flash encryption key. - - XTS_AES_128_KEY. 256 bit flash encryption key. - - HMAC_DOWN_ALL. - - HMAC_DOWN_JTAG. - - HMAC_DOWN_DIGITAL_SIGNATURE. - - HMAC_UP. - - SECURE_BOOT_DIGEST0. 1 secure boot key. - - SECURE_BOOT_DIGEST1. 2 secure boot key. - - SECURE_BOOT_DIGEST2. 3 secure boot key. - :esp32s2 or esp32s3: - XTS_AES_256_KEY. This is a virtual key purpose for flash encryption key. This allows you to write a whole 512-bit key into two blocks with ``XTS_AES_256_KEY_1`` and ``XTS_AES_256_KEY_2`` purposes without splitting the key file. - -.. only:: esp32c2 - - {IDF_TARGET_NAME} has only one eFuse key block (256 bits long). It is block #3 - ``BLOCK_KEY0``. This block can have user, flash encryption, secure boot keys. This chip does not have any eFuse key purpose fields, but we use the key purpose option to distinguish between such keys. The key purpose option determines protection and byte order for key. - - .. list:: - - - USER - - XTS_AES_128_KEY. 256 bits flash encryption key. The secure boot key can not be used with this option. In addition, eFuse ``XTS_KEY_LENGTH_256`` is set to 1, which means that the flash encryption key is 256 bits long. - - XTS_AES_128_KEY_DERIVED_FROM_128_EFUSE_BITS. 128 bits flash encryption key. The 128 bits of this key will be burned to the low part of the eFuse block. These bits will be read protected. - - SECURE_BOOT_DIGEST. Secure boot key. The first 128 bits of key will be burned to the high part of the eFuse block. - - {IDF_TARGET_NAME} can have in eFuse block the following combination of keys: - - 1. Both, Flash encryption (low 128 bits of eFuse block) and Secure boot key (high 128 bits of eFuse block). - 2. only Flash encryption (low 128 bits of eFuse block), rest part of eFuse block is not possible to use in future. - 3. only Flash encryption key (256 bits long), whole eFuse key block. - 4. only Secure boot key (high 128 bits of eFuse block). - 5. no keys, used for user purposes. Chip does not have security features. - -.. only:: not esp32 - - All keys will be burned with write protection if ``--no-write-protect`` is not used. - - Only flash encryption key is read protected if ``--no-read-protect`` is not used. - - All keys, except flash encryption, will be burned in direct byte order. The encryption key is written in reverse byte order for compatibility with encryption hardware. - -.. only:: esp32 - - Key Coding Scheme - ^^^^^^^^^^^^^^^^^ - - When the ``None`` coding scheme is in use, keys are 256-bits (32 bytes) long. When 3/4 Coding Scheme is in use (``CODING_SCHEME`` eFuse has value 1 not 0), keys are 192-bits (24 bytes) long and an additional 64 bits of error correction data are also written. - espefuse v2.6 or newer supports the 3/4 Coding Scheme. The key file must be the appropriate length for the coding scheme currently in use. - -Unprotected Keys -^^^^^^^^^^^^^^^^ - -By default, when an encryption key block is burned it is also read and write protected. - -.. only:: esp32 - - The ``--no-protect-key`` option will disable this behaviour (you can separately read or write protect the key later). - -.. only:: not esp32 - - The ``--no-read-protect`` and ``--no-write-protect`` options will disable this behaviour (you can separately read or write protect the key later). - -.. note:: - - Leaving a key unprotected may compromise its use as a security feature. - -.. code-block:: none - - espefuse.py burn_key secure_boot_v1 secure_boot_key_v1.bin - -.. only:: esp32 - - Note that the hardware flash encryption and secure boot v1 features require the key to be written to the eFuse block in reversed byte order, compared to the order used by the AES algorithm on the host. Using corresponding block name, the tool automatically reverses the bytes when writing. For this reason, an unprotected key will read back in the reverse order. - -Force Writing a Key -^^^^^^^^^^^^^^^^^^^ - -Normally, a key will only be burned if the efuse block has not been previously written to. The ``--force-write-always`` option can be used to ignore this and try to burn the key anyhow. - -Note that this option is still limited by the eFuse hardware - hardware does not allow any eFuse bits to be cleared 1->0, and can not write anything to write protected eFuse blocks. - -Usage ------ - -.. only:: esp32 - - .. code-block:: none - - > espefuse.py burn_key flash_encryption 256bit_fe_key.bin - - === Run "burn_key" command === - Burn keys to blocks: - - BLOCK1 -> [1f 1e 1d 1c 1b 1a 19 18 17 16 15 14 13 12 11 10 0f 0e 0d 0c 0b 0a 09 08 07 06 05 04 03 02 01 00] - Reversing the byte order - Disabling read to key block - Disabling write to key block - - Burn keys in efuse blocks. - The key block will be read and write protected - - Check all blocks for burn... - idx, BLOCK_NAME, Conclusion - [00] BLOCK0 is empty, will burn the new value - [01] BLOCK1 is empty, will burn the new value - . - This is an irreversible operation! - Type 'BURN' (all capitals) to continue. - BURN - BURN BLOCK1 - OK (write block == read block) - BURN BLOCK0 - OK (write block == read block) - Reading updated efuses... - Successful - - .. code-block:: none - - > espefuse.py summary - ... - BLOCK1 (BLOCK1): Flash encryption key - = ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? -/- - - Byte order for flash encryption key is reversed. Content of flash encryption key file ("256bit_fe_key.bin"): - - .. code-block:: none - - 0001 0203 0405 0607 0809 0a0b 0c0d 0e0f 1011 1213 1415 1617 1819 1a1b 1c1d 1e1f - - When the ``no protection`` option is used then you can see the burned key: - - .. code-block:: none - - > espefuse.py burn_key flash_encryption 256bit_fe_key.bin --no-protect-key - - === Run "burn_key" command === - Burn keys to blocks: - - BLOCK1 -> [1f 1e 1d 1c 1b 1a 19 18 17 16 15 14 13 12 11 10 0f 0e 0d 0c 0b 0a 09 08 07 06 05 04 03 02 01 00] - Reversing the byte order - - Key is left unprotected as per --no-protect-key argument. - Burn keys in efuse blocks. - The key block will left readable and writeable (due to --no-protect-key) - - Check all blocks for burn... - idx, BLOCK_NAME, Conclusion - [01] BLOCK1 is empty, will burn the new value - . - This is an irreversible operation! - Type 'BURN' (all capitals) to continue. - BURN - BURN BLOCK1 - OK (write block == read block) - Reading updated efuses... - Successful - - .. code-block:: none - - > espefuse.py summary - ... - BLOCK1 (BLOCK1): Flash encryption key - = 1f 1e 1d 1c 1b 1a 19 18 17 16 15 14 13 12 11 10 0f 0e 0d 0c 0b 0a 09 08 07 06 05 04 03 02 01 00 R/W - -.. only:: esp32s2 or esp32s3 - - Burning XTS_AES_256_KEY: - - The first 256 bit of the key goes to given BLOCK (here it is ``BLOCK_KEY0``) with key purpose = ``XTS_AES_256_KEY_1``. The last 256 bit of the key will be burned to the first free key block after BLOCK (here it is ``BLOCK_KEY1``) and set key purpose to ``XTS_AES_256_KEY_2`` for this block. - - This example uses ``--no-read-protect`` to expose the byte order written into eFuse blocks. - - Content of flash encryption key file (``512bits_0.bin``): - - .. code-block:: none - - 0001 0203 0405 0607 0809 0a0b 0c0d 0e0f 1011 1213 1415 1617 1819 1a1b 1c1d 1e1f - 2021 2223 2425 2627 2829 2a2b 2c2d 2e2f 3031 3233 3435 3637 3839 3a3b 3c3d 3e3f - - .. code-block:: none - - > espefuse.py burn_key BLOCK_KEY0 ~/esp/tests/efuse/512bits_0.bin XTS_AES_256_KEY --no-read-protect - - === Run "burn_key" command === - Burn keys to blocks: - - BLOCK_KEY0 -> [1f 1e 1d 1c 1b 1a 19 18 17 16 15 14 13 12 11 10 0f 0e 0d 0c 0b 0a 09 08 07 06 05 04 03 02 01 00] - Reversing byte order for AES-XTS hardware peripheral - 'KEY_PURPOSE_0': 'USER' -> 'XTS_AES_256_KEY_1'. - Disabling write to 'KEY_PURPOSE_0'. - Disabling write to key block - - - BLOCK_KEY1 -> [3f 3e 3d 3c 3b 3a 39 38 37 36 35 34 33 32 31 30 2f 2e 2d 2c 2b 2a 29 28 27 26 25 24 23 22 21 20] - Reversing byte order for AES-XTS hardware peripheral - 'KEY_PURPOSE_1': 'USER' -> 'XTS_AES_256_KEY_2'. - Disabling write to 'KEY_PURPOSE_1'. - Disabling write to key block - - Keys will remain readable (due to --no-read-protect) - - Check all blocks for burn... - idx, BLOCK_NAME, Conclusion - [00] BLOCK0 is empty, will burn the new value - [04] BLOCK_KEY0 is empty, will burn the new value - [05] BLOCK_KEY1 is empty, will burn the new value - . - This is an irreversible operation! - Type 'BURN' (all capitals) to continue. - BURN - BURN BLOCK5 - OK (write block == read block) - BURN BLOCK4 - OK (write block == read block) - BURN BLOCK0 - OK (write block == read block) - Reading updated efuses... - Successful - - > espefuse.py summary - ... - KEY_PURPOSE_0 (BLOCK0) KEY0 purpose = XTS_AES_256_KEY_1 R/- (0x2) - KEY_PURPOSE_1 (BLOCK0) KEY1 purpose = XTS_AES_256_KEY_2 R/- (0x3) - ... - BLOCK_KEY0 (BLOCK4) - Purpose: XTS_AES_256_KEY_1 - Encryption key0 or user data - = 1f 1e 1d 1c 1b 1a 19 18 17 16 15 14 13 12 11 10 0f 0e 0d 0c 0b 0a 09 08 07 06 05 04 03 02 01 00 R/- - BLOCK_KEY1 (BLOCK5) - Purpose: XTS_AES_256_KEY_2 - Encryption key1 or user data - = 3f 3e 3d 3c 3b 3a 39 38 37 36 35 34 33 32 31 30 2f 2e 2d 2c 2b 2a 29 28 27 26 25 24 23 22 21 20 R/- - -.. only:: esp32c2 - - .. code-block:: none - - > espefuse.py -c esp32c2 \ - burn_key_digest secure_images/ecdsa256_secure_boot_signing_key_v2.pem \ - burn_key BLOCK_KEY0 images/efuse/128bit_key.bin XTS_AES_128_KEY_DERIVED_FROM_128_EFUSE_BITS - - === Run "burn_key_digest" command === - Burn keys to blocks: - - BLOCK_KEY0_HI_128 -> [bf 0f 6a f6 8b d3 6d 8b 53 b3 da a9 33 f6 0a 04] - Disabling write to key block - - - Batch mode is enabled, the burn will be done at the end of the command. - - === Run "burn_key" command === - Burn keys to blocks: - - BLOCK_KEY0_LOW_128 -> [0f 0e 0d 0c 0b 0a 09 08 07 06 05 04 03 02 01 00] - Reversing byte order for AES-XTS hardware peripheral - Disabling read to key block - Disabling write to key block - The same value for WR_DIS is already burned. Do not change the efuse. - - Batch mode is enabled, the burn will be done at the end of the command. - - Check all blocks for burn... - idx, BLOCK_NAME, Conclusion - [00] BLOCK0 is empty, will burn the new value - [03] BLOCK_KEY0 is empty, will burn the new value - . - This is an irreversible operation! - Type 'BURN' (all capitals) to continue. - BURN - BURN BLOCK3 - OK (write block == read block) - BURN BLOCK0 - OK (write block == read block) - Reading updated efuses... diff --git a/docs/en/espefuse/burn-key-digest-cmd.rst b/docs/en/espefuse/burn-key-digest-cmd.rst deleted file mode 100644 index 3ea1e2476..000000000 --- a/docs/en/espefuse/burn-key-digest-cmd.rst +++ /dev/null @@ -1,170 +0,0 @@ -.. _burn-key-digest-cmd: - -Burn key Digest -=============== - -The ``espefuse.py burn_key_digest`` command parses a RSA public key and burns the digest to eFuse block for use with `Secure Boot V2 `_. - -Positional arguments: - -.. list:: - - :not esp32 and not esp32c2: - ``block`` - Name of key block. - - ``Keyfile``. Key file to digest (PEM format). - :not esp32 and not esp32c2: - ``Key purpose``. The purpose of this key [``SECURE_BOOT_DIGEST0``, ``SECURE_BOOT_DIGEST1``, ``SECURE_BOOT_DIGEST2``]. - -.. only:: not esp32 and not esp32c2 - - It can be list of blocks and keyfiles and key purposes (like BLOCK_KEY0 keyfile0.pem SECURE_BOOT_DIGEST0 BLOCK_KEY1 keyfile1.pem SECURE_BOOT_DIGEST1 etc.). - -Optional arguments: - -.. list:: - - :esp32: - ``--no-protect-key``. Disable default read and write protecting of the key. - :not esp32: - ``--no-write-protect``. Disable write-protecting of the key. The key remains writable. The keys use the RS coding scheme that does not support post-write data changes. Forced write can damage RS encoding bits. The write-protecting of keypurposes does not depend on the option, it will be set anyway. - :not esp32: - ``--no-read-protect``. Disable read-protecting of the key. This option does not change anything, because Secure Boot keys are readable anyway. - - ``--force-write-always``. Write the eFuse key even if it looks like it is already been written, or is write protected. Note that this option can't disable write protection, or clear any bit which has already been set. - -.. only:: esp32 - - {IDF_TARGET_NAME} must have chip version > 3 (v300) and coding scheme = ``None`` otherwise an error will be shown. The key will be burned to BLOCK2. - -.. only:: esp32c2 - - The key will be burned to BLOCK3. - -The secure boot v2 key(s) will be readable and write protected. - -Usage ------ - -.. only:: esp32 - - .. code-block:: none - - > espefuse.py burn_key_digest secure_boot_key_v2_0.pem - - === Run "burn_key_digest" command === - - BLOCK2 -> [a2 cd 39 85 df 00 d7 95 07 0f f6 7c 8b ab e1 7d 39 11 95 c4 5b 37 6e 7b f0 ec 04 5e 36 30 02 5d] - Disabling write to efuse BLOCK2... - - Check all blocks for burn... - idx, BLOCK_NAME, Conclusion - [00] BLOCK0 is empty, will burn the new value - [02] BLOCK2 is empty, will burn the new value - . - This is an irreversible operation! - Type 'BURN' (all capitals) to continue. - BURN - BURN BLOCK2 - OK (write block == read block) - BURN BLOCK0 - OK (write block == read block) - Reading updated efuses... - Successful - - > espefuse.py summary - ... - BLOCK2 (BLOCK2): Secure boot key - = a2 cd 39 85 df 00 d7 95 07 0f f6 7c 8b ab e1 7d 39 11 95 c4 5b 37 6e 7b f0 ec 04 5e 36 30 02 5d R/- - -.. only:: esp32c2 - - See :ref:`perform-multiple-operations` for how to burn flash encryption and secure boot keys to the same eFuse key block at the same time. - - .. code-block:: none - - > espefuse.py burn_key_digest secure_boot_v2_ecdsa192.pem - - === Run "burn_key_digest" command === - Burn keys to blocks: - - BLOCK_KEY0_HI_128 -> [02 c2 bd 9c 1a b4 b7 44 22 59 c6 d3 12 0b 79 1f] - Disabling write to key block - - Check all blocks for burn... - idx, BLOCK_NAME, Conclusion - [00] BLOCK0 is empty, will burn the new value - [03] BLOCK_KEY0 is empty, will burn the new value - . - This is an irreversible operation! - Type 'BURN' (all capitals) to continue. - BURN - BURN BLOCK3 - OK (write block == read block) - BURN BLOCK0 - OK (write block == read block) - Reading updated efuses... - Successful - - > espefuse.py summary - ... - XTS_KEY_LENGTH_256 (BLOCK0) Flash encryption key length = 128 bits key R/W (0b0) - ... - BLOCK_KEY0 (BLOCK3) BLOCK_KEY0 - 256-bits. 256-bit key of Flash Encryp - = 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 02 c2 bd 9c 1a b4 b7 44 22 59 c6 d3 12 0b 79 1f R/- - tion - BLOCK_KEY0_LOW_128 (BLOCK3) BLOCK_KEY0 - lower 128-bits. 128-bit key of Flash - = 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 R/- - Encryption - BLOCK_KEY0_HI_128 (BLOCK3) BLOCK_KEY0 - higher 128-bits. 128-bits key of Secu - = 02 c2 bd 9c 1a b4 b7 44 22 59 c6 d3 12 0b 79 1f R/- - re Boot. - -.. only:: esp32c3 or esp32s2 or esp32s3 - - .. code-block:: none - - > espefuse.py burn_key_digest \ - BLOCK_KEY0 ~/esp/tests/efuse/secure_boot_key_v2_0.pem SECURE_BOOT_DIGEST0 \ - BLOCK_KEY1 ~/esp/tests/efuse/secure_boot_key_v2_1.pem SECURE_BOOT_DIGEST1 \ - BLOCK_KEY2 ~/esp/tests/efuse/secure_boot_key_v2_2.pem SECURE_BOOT_DIGEST2 - - === Run "burn_key_digest" command === - Burn keys to blocks: - - BLOCK_KEY0 -> [a2 cd 39 85 df 00 d7 95 07 0f f6 7c 8b ab e1 7d 39 11 95 c4 5b 37 6e 7b f0 ec 04 5e 36 30 02 5d] - 'KEY_PURPOSE_0': 'USER' -> 'SECURE_BOOT_DIGEST0'. - Disabling write to 'KEY_PURPOSE_0'. - Disabling write to key block - - - BLOCK_KEY1 -> [a3 cd 39 85 df 00 d7 95 07 0f f6 7c 8b ab e1 7d 39 11 95 c4 5b 37 6e 7b f0 ec 04 5e 36 30 02 5d] - 'KEY_PURPOSE_1': 'USER' -> 'SECURE_BOOT_DIGEST1'. - Disabling write to 'KEY_PURPOSE_1'. - Disabling write to key block - - - BLOCK_KEY2 -> [a4 cd 39 85 df 00 d7 95 07 0f f6 7c 8b ab e1 7d 39 11 95 c4 5b 37 6e 7b f0 ec 04 5e 36 30 02 5d] - 'KEY_PURPOSE_2': 'USER' -> 'SECURE_BOOT_DIGEST2'. - Disabling write to 'KEY_PURPOSE_2'. - Disabling write to key block - - Check all blocks for burn... - idx, BLOCK_NAME, Conclusion - [00] BLOCK0 is empty, will burn the new value - [04] BLOCK_KEY0 is empty, will burn the new value - [05] BLOCK_KEY1 is empty, will burn the new value - [06] BLOCK_KEY2 is empty, will burn the new value - . - This is an irreversible operation! - Type 'BURN' (all capitals) to continue. - BURN - BURN BLOCK6 - OK (write block == read block) - BURN BLOCK5 - OK (write block == read block) - BURN BLOCK4 - OK (write block == read block) - BURN BLOCK0 - OK (write block == read block) - Reading updated efuses... - Successful - - > espefuse.py summary - - KEY_PURPOSE_0 (BLOCK0) KEY0 purpose = SECURE_BOOT_DIGEST0 R/- (0x9) - KEY_PURPOSE_1 (BLOCK0) KEY1 purpose = SECURE_BOOT_DIGEST1 R/- (0xa) - KEY_PURPOSE_2 (BLOCK0) KEY2 purpose = SECURE_BOOT_DIGEST2 R/- (0xb) - ... - BLOCK_KEY0 (BLOCK4) - Purpose: SECURE_BOOT_DIGEST0 - Encryption key0 or user data - = a2 cd 39 85 df 00 d7 95 07 0f f6 7c 8b ab e1 7d 39 11 95 c4 5b 37 6e 7b f0 ec 04 5e 36 30 02 5d R/- - BLOCK_KEY1 (BLOCK5) - Purpose: SECURE_BOOT_DIGEST1 - Encryption key1 or user data - = a3 cd 39 85 df 00 d7 95 07 0f f6 7c 8b ab e1 7d 39 11 95 c4 5b 37 6e 7b f0 ec 04 5e 36 30 02 5d R/- - BLOCK_KEY2 (BLOCK6) - Purpose: SECURE_BOOT_DIGEST2 - Encryption key2 or user data - = a4 cd 39 85 df 00 d7 95 07 0f f6 7c 8b ab e1 7d 39 11 95 c4 5b 37 6e 7b f0 ec 04 5e 36 30 02 5d R/- diff --git a/docs/en/espefuse/check-error-cmd.rst b/docs/en/espefuse/check-error-cmd.rst deleted file mode 100644 index 8d3a56003..000000000 --- a/docs/en/espefuse/check-error-cmd.rst +++ /dev/null @@ -1,107 +0,0 @@ -.. _check-error-cmd: - -Check Error -=========== - -The ``espefuse.py check_error`` command checks eFuse errors. It triggers several reads to force the eFuse controller to reload eFuses and update status registers. This command can be run after burn operations to make sure that there is not errors. - -Optional argument: - -* ``--recovery``. It repairs encoding errors in eFuse blocks, if possible. - -The summary log below shows an error in BLOCK0. - -.. code-block:: none - - > espefuse.py summary - ... - WDT_DELAY_SEL (BLOCK0)[FAIL:1] Selects RTC WDT timeout threshold at startup = False R/W (0b0) - ... - Error(s) in BLOCK0 [ERRORS:1 FAIL:1] - - BLOCK0 ( ) [0 ] err__regs: 00000400 00000000 00000000 00000000 00000000 00000000 - EFUSE_RD_RS_ERR0_REG 0x00000000 - EFUSE_RD_RS_ERR1_REG 0x00000000 - WARNING: Coding scheme has encoding bit error warnings - -Usage ------ - -Checks the status registers of eFuse blocks and throws an error if there is an error. - -.. code-block:: none - - > espefuse.py check_error - - Error(s) in BLOCK1 [ERRORS:0 FAIL:1] - Error(s) in BLOCK2 [ERRORS:1 FAIL:1] - Error(s) in BLOCK3 [ERRORS:1 FAIL:1] - - BLOCK0 ( ) [0 ] err__regs: 00000000 00000000 00000000 00000000 00000000 00000000 - EFUSE_RD_RS_ERR0_REG 0x00008990 - EFUSE_RD_RS_ERR1_REG 0x00000000 - - === Run "check_error" command === - Error(s) in BLOCK1 [ERRORS:0 FAIL:1] - Error(s) in BLOCK2 [ERRORS:1 FAIL:1] - Error(s) in BLOCK3 [ERRORS:1 FAIL:1] - - BLOCK0 ( ) [0 ] err__regs: 00000000 00000000 00000000 00000000 00000000 00000000 - EFUSE_RD_RS_ERR0_REG 0x00008990 - EFUSE_RD_RS_ERR1_REG 0x00000000 - - A fatal error occurred: Error(s) were detected in eFuses - -Repairs encoding errors in eFuse blocks, if possible. - -.. code-block:: none - - > espefuse.py check_error --recovery - - Error(s) in BLOCK1 [ERRORS:0 FAIL:1] - Error(s) in BLOCK2 [ERRORS:1 FAIL:1] - Error(s) in BLOCK3 [ERRORS:1 FAIL:1] - - BLOCK0 ( ) [0 ] err__regs: 00000000 00000000 00000000 00000000 00000000 00000000 - EFUSE_RD_RS_ERR0_REG 0x00008990 - EFUSE_RD_RS_ERR1_REG 0x00000000 - - === Run "check_error" command === - Error(s) in BLOCK1 [ERRORS:0 FAIL:1] - Error(s) in BLOCK2 [ERRORS:1 FAIL:1] - Error(s) in BLOCK3 [ERRORS:1 FAIL:1] - - BLOCK0 ( ) [0 ] err__regs: 00000000 00000000 00000000 00000000 00000000 00000000 - EFUSE_RD_RS_ERR0_REG 0x00008990 - EFUSE_RD_RS_ERR1_REG 0x00000000 - Recovery of block coding errors. - This is an irreversible operation! - Type 'BURN' (all capitals) to continue. - BURN - Error in BLOCK3, re-burn it again (#0), to fix it. fail_bit=1, num_errors=0 - Error in BLOCK3, re-burn it again (#1), to fix it. fail_bit=1, num_errors=0 - Error in BLOCK3, re-burn it again (#2), to fix it. fail_bit=1, num_errors=0 - BURN BLOCK3 - OK (write block == read block) - Error in BLOCK2, re-burn it again (#0), to fix it. fail_bit=1, num_errors=1 - Error in BLOCK2, re-burn it again (#1), to fix it. fail_bit=1, num_errors=1 - Error in BLOCK2, re-burn it again (#2), to fix it. fail_bit=1, num_errors=1 - BURN BLOCK2 - OK (write block == read block) - Error in BLOCK1, re-burn it again (#0), to fix it. fail_bit=1, num_errors=0 - Error in BLOCK1, re-burn it again (#1), to fix it. fail_bit=1, num_errors=0 - Error in BLOCK1, re-burn it again (#2), to fix it. fail_bit=1, num_errors=0 - BURN BLOCK1 - OK (write block == read block) - Error(s) in BLOCK1 [ERRORS:0 FAIL:1] - Error(s) in BLOCK2 [ERRORS:1 FAIL:1] - Error(s) in BLOCK3 [ERRORS:0 FAIL:1] - - BLOCK0 ( ) [0 ] err__regs: 00000000 00000000 00000000 00000000 00000000 00000000 - EFUSE_RD_RS_ERR0_REG 0x00008890 - EFUSE_RD_RS_ERR1_REG 0x00000000 - - A fatal error occurred: Error(s) were detected in eFuses - -If all errors are fixed, then this message is displayed: - -.. code-block:: none - - No errors detected diff --git a/docs/en/espefuse/dump-cmd.rst b/docs/en/espefuse/dump-cmd.rst deleted file mode 100644 index a1a09a277..000000000 --- a/docs/en/espefuse/dump-cmd.rst +++ /dev/null @@ -1,114 +0,0 @@ -.. _dump-cmd: - -Dump -==== - -The ``espefuse.py dump`` command allows: - -- display raw values of eFuse registers, grouped by block. Output corresponds directly to eFuse register values in the `register space `__. -- save dump into files. - -Optional arguments: - -- ``--file_name`` - Saves dump for each block into separate file. Provide the common path name like /path/blk.bin, it will create: blk0.bin, blk1.bin ... blkN.bin. Then using ``burn_block_data`` command these dump files can be written to another chip. - -Raw Values Of Efuse Registers ------------------------------ - -The number of blocks depends on the chips and can vary from 4 to 11. A block can have different names, which can be used with ``burn_key`` or ``burn_block_data``. - -The order of registers in the dump: - -.. code-block:: none - - REG_0 REG_1 REG_2 REG_3 REG_4 REG_5 - BLOCK0 ( ) [0 ] read_regs: 00000000 00000000 00000000 00000000 00000000 00000000 - -.. only:: esp32 - - .. code-block:: none - - > espefuse.py dump - - Detecting chip type... Unsupported detection protocol, switching and trying again... - Connecting.... - Detecting chip type... ESP32 - BLOCK0 ( ) [0 ] read_regs: 00000000 7e5a6e58 00e294b9 0000a200 00000333 00100000 00000004 - BLOCK1 (flash_encryption) [1 ] read_regs: 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 - BLOCK2 (secure_boot_v1 s) [2 ] read_regs: 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 - BLOCK3 ( ) [3 ] read_regs: 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 - - EFUSE_REG_DEC_STATUS 0x00000000 - -.. only:: esp32c2 - - .. code-block:: none - - > espefuse.py dump - - Connecting......... - Detecting chip type... ESP32-C2 - BLOCK0 (BLOCK0 ) [0 ] read_regs: 00000000 00000000 - BLOCK1 (BLOCK1 ) [1 ] read_regs: 11efcdab 00000000 00000000 - BLOCK2 (BLOCK2 ) [2 ] read_regs: 558000a4 000094b5 00000000 00000000 00000000 00000000 00000000 00000000 - BLOCK_KEY0 (BLOCK3 ) [3 ] read_regs: 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 - - BLOCK0 (BLOCK0 ) [0 ] err__regs: 00000000 00000000 - EFUSE_RD_RS_ERR_REG 0x00000000 - -.. only:: not esp32 and not esp32c2 - - .. code-block:: none - - > espefuse.py dump - - Connecting.... - Detecting chip type... ESP32-C3 - BLOCK0 ( ) [0 ] read_regs: 00000000 00000000 00000000 00000000 00000000 00000000 - MAC_SPI_8M_0 (BLOCK1 ) [1 ] read_regs: 00000000 00000000 00000000 00000000 00000000 00000000 - BLOCK_SYS_DATA (BLOCK2 ) [2 ] read_regs: 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 - BLOCK_USR_DATA (BLOCK3 ) [3 ] read_regs: 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 - BLOCK_KEY0 (BLOCK4 ) [4 ] read_regs: 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 - BLOCK_KEY1 (BLOCK5 ) [5 ] read_regs: 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 - BLOCK_KEY2 (BLOCK6 ) [6 ] read_regs: 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 - BLOCK_KEY3 (BLOCK7 ) [7 ] read_regs: 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 - BLOCK_KEY4 (BLOCK8 ) [8 ] read_regs: 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 - BLOCK_KEY5 (BLOCK9 ) [9 ] read_regs: 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 - BLOCK_SYS_DATA2 (BLOCK10 ) [10] read_regs: 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 - - BLOCK0 ( ) [0 ] err__regs: 00000000 00000000 00000000 00000000 00000000 00000000 - EFUSE_RD_RS_ERR0_REG 0x00000000 - EFUSE_RD_RS_ERR1_REG 0x00000000 - -In the last lines, which are separated from the main dump, you can see the encoding scheme status for each block. If there are all zeros, then there are no coding scheme errors. - -Save Dump To Files ------------------- - -This command saves dump for each block into a separate file. You need to provide the common path name ``/chip1/blk.bin``, it will create files in the given directory (the directory must exist): /chip1/blk0.bin, /chip1/blk1.bin - /chip1/blkN.bin. Use ``burn_block_data`` command to write them back to another chip. Note that some blocks may be read-protected, in which case the data in the block will be zero. - -.. code-block:: none - - > espefuse.py dump --file_name backup/chip1/blk.bin - - === Run "dump" command === - backup/chip1/blk0.bin - backup/chip1/blk1.bin - backup/chip1/blk2.bin - backup/chip1/blk3.bin - backup/chip1/blk4.bin - backup/chip1/blk5.bin - backup/chip1/blk6.bin - backup/chip1/blk7.bin - backup/chip1/blk8.bin - backup/chip1/blk9.bin - backup/chip1/blk10.bin - -These dump files can be written to another chip: - -.. code-block:: none - - > espefuse.py burn_block_data BLOCK0 backup/chip1/blk0.bin \ - BLOCK1 backup/chip1/blk1.bin \ - BLOCK2 backup/chip1/blk2.bin - \ No newline at end of file diff --git a/docs/en/espefuse/execute-scripts-cmd.rst b/docs/en/espefuse/execute-scripts-cmd.rst deleted file mode 100644 index 81319a354..000000000 --- a/docs/en/espefuse/execute-scripts-cmd.rst +++ /dev/null @@ -1,119 +0,0 @@ -.. _execute-scripts-cmd: - -Execute Scripts -=============== - -The ``espefuse.py execute_scripts`` command executes scripts to burn at one time. - -Positional arguments: - -- ``scripts`` - it is special format of python scripts (receives list of files, like script1.py script2.py etc.). - -Optional arguments: - -- ``--index`` - integer index. It allows to retrieve unique data per chip from configfiles and then burn them (ex. CUSTOM_MAC, UNIQUE_ID). -- ``--configfiles`` - List of configfiles with data (receives list of configfiles, like configfile1.py configfile2.py etc.). - -.. code-block:: none - - > espefuse.py execute_scripts efuse_script1.py efuse_script2.py ... - -This command allows burning all needed efuses at one time based on your own python script and control issues during the burn process if so it will abort the burn process. This command has a few arguments: - -* ``scripts`` is a list of scripts. The special format of python scripts can be executed inside ``espefuse.py``. -* ``--index`` integer index (it means the number of chip in the batch in the range 1 - the max number of chips in the batch). It allows to retrieve unique data per chip from configfiles and then burn them (ex. CUSTOM_MAC, UNIQUE_ID). -* ``--configfiles`` List of configfiles with data. - -Below you can see some examples of the script. This script file is run from ``espefuse.py`` as ``exec(open(file.name).read())`` it means that some functions and imported libs are available for using like ``os``. Please use only provided functions. -If you want to use other libs in the script you can add them manually. - -Inside this script, you can call all commands which are available in CLI, see ``espefuse.py --help``. To run a efuse command you need to call ``espefuse(esp, efuses, args, 'burn_efuse DISABLE_DL_DECRYPT 1')``. This command will not burn eFuses immediately, the burn occurs at the end of all scripts. -If necessary, you can call ``efuses.burn_all()`` which prompts ``Type 'BURN' (all capitals) to continue.``. To skip this check and go without confirmation just add the ``--do-not-confirm`` flag to the ``execute_scripts`` command. - -This command supports nesting. This means that one script can be called from another script (see the test case ``test_execute_scripts_nesting`` in ``esptool/test/test_espefuse.py``). - -.. code-block:: none - - > espefuse.py execute_scripts efuse_script1.py --do-not-confirm - -Additionally, you can implement some checks based on the value of efuses. To get value of an efuse use ``efuses['FLASH_CRYPT_CNT'].get()``. Some eFuses have a dictionary to convert from a value to a human-readable as it looks in the table is printed by the ``summary`` command. -See how it is done (for ESP32) for ``CODING_SCHEME`` when ``get_meaning()`` is called: - -* 0: ``NONE (BLK1-3 len=256 bits)`` -* 1: ``3/4 (BLK1-3 len=192 bits)`` -* 2: ``REPEAT (BLK1-3 len=128 bits) not supported`` -* 3: ``NONE (BLK1-3 len=256 bits)`` - -.. code:: python - - print("connected chip: %s, coding scheme %s" % (esp.get_chip_description(), efuses["CODING_SCHEME"].get_meaning())) - if os.path.exists("flash_encryption_key.bin"): - espefuse(esp, efuses, args, "burn_key flash_encryption flash_encryption_key.bin") - else: - raise esptool.FatalError("The 'flash_encryption_key.bin' file is missing in the project directory") - - espefuse(esp, efuses, args, 'burn_efuse FLASH_CRYPT_CNT 0x7') - - current_flash_crypt_cnt = efuses['FLASH_CRYPT_CNT'].get() - if current_flash_crypt_cnt in [0, 3]: - espefuse(esp, efuses, args, 'burn_efuse FLASH_CRYPT_CNT') - - espefuse(esp, efuses, args, 'burn_efuse DISABLE_DL_ENCRYPT 1') - - espefuse(esp, efuses, args, 'burn_efuse DISABLE_DL_DECRYPT 1') - - espefuse(esp, efuses, args, 'burn_efuse DISABLE_DL_CACHE 1') - - espefuse(esp, efuses, args, 'burn_efuse JTAG_DISABLE 1') - ... - -After ``efuses.burn_all()``, all needed efuses will be burnt to chip in order ``BLK_MAX`` to ``BLK_0``. This order prevents cases when protection is set before the value goes to a block. Please note this while developing your scripts. -Upon completion, the new eFuses will be read back, and will be done some checks of written eFuses by ``espefuse.py``. In production, you might need to check that all written efuses are set properly, see the example below. - -The script `execute_efuse_script.py `__ burns some efuses and checks them after reading back. To check read and write protection, ``is_readable()`` and ``is_writeable()`` are called. - -Burn Unique Data Per Chip -^^^^^^^^^^^^^^^^^^^^^^^^^ - -In case you are running the ``execute_scripts`` command from your production script, you may need to pass ``index`` to get the unique data for each chip from the ``configfiles`` (* .txt, * .json, etc.). The espefuse command will be like this, where ``{index}`` means the number of chip in the batch, you increment it by your own script in the range 1 - the max number of chips in the batch: - -.. code-block:: none - - espefuse.py execute_scripts efuse_script2.py --do-not-confirm --index {index} --configfiles mac_addresses.json unique_id.json - -The example of a script to burn custom_mac address and unique_id getting them from configfiles. - -.. code:: python - - # efuse_script2.py - - mac_addresses = json.load(args.configfiles[0]) - unique_id = json.load(args.configfiles[1]) - - mac_val = mac_addresses[str(args.index)] - cmd = 'burn_custom_mac {}'.format(mac_val) - print(cmd) - espefuse(esp, efuses, args, cmd) - - unique_id_val = unique_id[str(args.index)] - cmd = 'burn_efuse UNIQUE_ID {}'.format(unique_id_val) - print(cmd) - espefuse(esp, efuses, args, cmd) - -The example of a script to burn custom_mac address that generated right in the script. - -.. code:: python - - # efuse_script2.py - - step = 4 - base_mac = '0xAABBCCDD0000' - mac = '' - for index in range(100): - mac = "{:012X}".format(int(base_mac, 16) + (args.index - 1) * step) - mac = ':'.join(mac[k] + mac [k + 1] for k in range(0, len(mac), 2)) - break - - cmd = 'burn_custom_mac mac' - print(cmd) - espefuse(esp, efuses, args, cmd) diff --git a/docs/en/espefuse/get-custom-mac-cmd.rst b/docs/en/espefuse/get-custom-mac-cmd.rst deleted file mode 100644 index 3077e991e..000000000 --- a/docs/en/espefuse/get-custom-mac-cmd.rst +++ /dev/null @@ -1,30 +0,0 @@ -.. _get-custom-mac-cmd: - -Get Custom Mac -============== - -The ``espefuse.py burn_custom_mac`` command prints the Custom MAC Address (``CUSTOM_MAC``). - -The chips also have a factory MAC address (eFuse name ``MAC``), which is written at the factory. It can not be changed with this tool. - -.. only:: esp32 - - .. code-block:: none - - > espefuse.py get_custom_mac - - === Run "get_custom_mac" command === - Custom MAC Address version 1: 48:63:92:15:72:16 (CRC 0x75 OK) - - If the custom MAC address is not burned, then you will see the message "Custom MAC Address is not set in the device". And in the summary, those eFuses associated with custom MAC addresses will not show up. - -.. only:: not esp32 - - .. code-block:: none - - > espefuse.py get_custom_mac - - === Run "get_custom_mac" command === - Custom MAC Address: 48:63:92:15:72:16 (OK) - - If the custom MAC address is not burned, then you will see the message "Custom MAC Address: 00:00:00:00:00:00 (OK)". diff --git a/docs/en/espefuse/inc/summary_ESP32-C2.rst b/docs/en/espefuse/inc/summary_ESP32-C2.rst deleted file mode 100644 index 47c4efc6e..000000000 --- a/docs/en/espefuse/inc/summary_ESP32-C2.rst +++ /dev/null @@ -1,79 +0,0 @@ -.. code-block:: none - - > espefuse.py -p PORT summary - - Connecting................... - Detecting chip type... ESP32-C2 - - === Run "summary" command === - EFUSE_NAME (Block) Description = [Meaningful Value] [Readable/Writeable] (Hex Value) - ---------------------------------------------------------------------------------------- - Adc_Calib fuses: - ADC_CALIBRATION_0 (BLOCK2) = 0 R/W (0b0000000000000000000000) - ADC_CALIBRATION_1 (BLOCK2) = 0 R/W (0x00000000) - ADC_CALIBRATION_2 (BLOCK2) = 0 R/W (0x00000000) - - Config fuses: - UART_PRINT_CONTROL (BLOCK0) Set UART boot message output mode = Force print R/W (0b00) - FORCE_SEND_RESUME (BLOCK0) Force ROM code to send a resume cmd during SPI boo = False R/W (0b0) - t - DIS_DIRECT_BOOT (BLOCK0) Disable direct_boot mode = False R/W (0b0) - - Efuse fuses: - WR_DIS (BLOCK0) Disables programming of individual eFuses = 0 R/W (0x00) - RD_DIS (BLOCK0) Disables software reading from BLOCK3 = 0 R/W (0b00) - - Flash Config fuses: - FLASH_TPUW (BLOCK0) Configures flash startup delay after SoC power-up, = 0 R/W (0x0) - unit is (ms/2). When the value is 15, delay is 7. - 5 ms - - Identity fuses: - SECURE_VERSION (BLOCK0) Secure version (anti-rollback feature) = 0 R/W (0x0) - CUSTOM_MAC_USED (BLOCK0) Enable CUSTOM_MAC programming = False R/W (0b0) - CUSTOM_MAC (BLOCK1) Custom MAC addr - = 00:00:00:00:00:00 (OK) R/W - MAC (BLOCK2) Factory MAC Address - = 94:b5:55:80:00:d0 (OK) R/W - WAFER_VERSION (BLOCK2) WAFER version = (revision 0) R/W (0b000) - PKG_VERSION (BLOCK2) Package version = ESP32-C2 R/W (0b000) - BLK_VERSION_MINOR (BLOCK2) Version of BLOCK2 = No calibration R/W (0b000) - - Jtag Config fuses: - DIS_PAD_JTAG (BLOCK0) Permanently disable JTAG access via padsUSB JTAG i = False R/W (0b0) - s controlled separately - - Ldo fuses: - LDO_VOL_BIAS_CONFIG_LOW (BLOCK2) = 0 R/W (0b000) - LDO_VOL_BIAS_CONFIG_HIGH (BLOCK2) = 0 R/W (0b000000000000000000000000000) - - Pvt fuses: - PVT_LOW (BLOCK2) = 0 R/W (0b00000) - PVT_HIGH (BLOCK2) = 0 R/W (0b0000000000) - - Rf fuses: - RF_REF_I_BIAS_CONFIG (BLOCK2) = 0 R/W (0b000) - - Security fuses: - DIS_DOWNLOAD_ICACHE (BLOCK0) Disables iCache in download mode = False R/W (0b0) - DIS_DOWNLOAD_MANUAL_ENCRYPT (BLOCK0) Disables flash encryption in Download boot modes = False R/W (0b0) - SPI_BOOT_CRYPT_CNT (BLOCK0) Enables encryption and decryption, when an SPI boo = Disable R/W (0b000) - t mode is set. Enabled when 1 or 3 bits are set,dis - abled otherwise - XTS_KEY_LENGTH_256 (BLOCK0) Flash encryption key length = 128 bits key R/W (0b0) - DIS_DOWNLOAD_MODE (BLOCK0) Disables all Download boot modes = False R/W (0b0) - ENABLE_SECURITY_DOWNLOAD (BLOCK0) Enables secure UART download mode (read/write flas = False R/W (0b0) - h only) - SECURE_BOOT_EN (BLOCK0) Configures secure boot = Flase R/W (0b0) - BLOCK_KEY0 (BLOCK3) BLOCK_KEY0 - 256-bits. 256-bit key of Flash Encryp - = 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 R/W - tion - BLOCK_KEY0_LOW_128 (BLOCK3) BLOCK_KEY0 - lower 128-bits. 128-bit key of Flash - = 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 R/W - Encryption - BLOCK_KEY0_HI_128 (BLOCK3) BLOCK_KEY0 - higher 128-bits. 128-bits key of Secu - = 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 R/W - re Boot. - - Wdt Config fuses: - WDT_DELAY_SEL (BLOCK0) RTC WDT timeout threshold = 0 R/W (0b00) diff --git a/docs/en/espefuse/inc/summary_ESP32-C3.rst b/docs/en/espefuse/inc/summary_ESP32-C3.rst deleted file mode 100644 index c5ef0b91a..000000000 --- a/docs/en/espefuse/inc/summary_ESP32-C3.rst +++ /dev/null @@ -1,136 +0,0 @@ -.. code-block:: none - - > espefuse.py -p PORT summary - - Connecting.... - Detecting chip type... ESP32-C3 - EFUSE_NAME (Block) Description = [Meaningful Value] [Readable/Writeable] (Hex Value) - ---------------------------------------------------------------------------------------- - Config fuses: - DIS_ICACHE (BLOCK0) Disables ICache = False R/W (0b0) - DIS_DOWNLOAD_ICACHE (BLOCK0) Disables Icache when SoC is in Download mode = False R/W (0b0) - DIS_FORCE_DOWNLOAD (BLOCK0) Disables forcing chip into Download mode = False R/W (0b0) - DIS_CAN (BLOCK0) Disables the TWAI Controller hardware = False R/W (0b0) - VDD_SPI_AS_GPIO (BLOCK0) Set this bit to vdd spi pin function as gpio = False R/W (0b0) - BTLC_GPIO_ENABLE (BLOCK0) Enable btlc gpio = 0 R/W (0b00) - POWERGLITCH_EN (BLOCK0) Set this bit to enable power glitch function = False R/W (0b0) - POWER_GLITCH_DSENSE (BLOCK0) Sample delay configuration of power glitch = 0 R/W (0b00) - DIS_DIRECT_BOOT (BLOCK0) Disables direct boot mode = False R/W (0b0) - DIS_USB_SERIAL_JTAG_ROM_PRINT (BLOCK0) Selects the default UART for printing boot msg = UART0 R/W (0b0) - UART_PRINT_CONTROL (BLOCK0) Sets the default UART boot message output mode = Enabled R/W (0b00) - FORCE_SEND_RESUME (BLOCK0) Force ROM code to send a resume command during SPI = False R/W (0b0) - bootduring SPI boot - BLOCK_USR_DATA (BLOCK3) User data - = 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 R/W - - Efuse fuses: - WR_DIS (BLOCK0) Disables programming of individual eFuses = 0 R/W (0x00000000) - RD_DIS (BLOCK0) Disables software reading from BLOCK4-10 = 0 R/W (0b0000000) - - Flash Config fuses: - FLASH_TPUW (BLOCK0) Configures flash startup delay after SoC power-up, = 0 R/W (0x0) - unit is (ms/2). When the value is 15, delay is 7. - 5 ms - FLASH_ECC_MODE (BLOCK0) Set this bit to set flsah ecc mode. - = flash ecc 16to18 byte mode R/W (0b0) - FLASH_TYPE (BLOCK0) Selects SPI flash type = 4 data lines R/W (0b0) - FLASH_PAGE_SIZE (BLOCK0) Flash page size = 0 R/W (0b00) - FLASH_ECC_EN (BLOCK0) Enable ECC for flash boot = False R/W (0b0) - - Identity fuses: - SECURE_VERSION (BLOCK0) Secure version (used by ESP-IDF anti-rollback feat = 0 R/W (0x0000) - ure) - MAC (BLOCK1) Factory MAC Address - = 7c:df:a1:40:40:08: (OK) R/W - WAFER_VERSION (BLOCK1) WAFER version = (revision 0) R/W (0b000) - PKG_VERSION (BLOCK1) Package version = ESP32-C3 R/W (0x0) - BLOCK1_VERSION (BLOCK1) BLOCK1 efuse version = 0 R/W (0b000) - OPTIONAL_UNIQUE_ID (BLOCK2)(0 errors): Optional unique 128-bit ID - = 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 R/W - BLK_VERSION_MAJOR (BLOCK2) Version of BLOCK2 = No calibration R/W (0b000) - CUSTOM_MAC (BLOCK3) Custom MAC Address - = 00:00:00:00:00:00 (OK) R/W - - Jtag Config fuses: - JTAG_SEL_ENABLE (BLOCK0) Set this bit to enable selection between usb_to_jt = False R/W (0b0) - ag and pad_to_jtag through strapping gpio10 when b - oth reg_dis_usb_jtag and reg_dis_pad_jtag are equa - l to 0. - SOFT_DIS_JTAG (BLOCK0) Software disables JTAG. When software disabled, JT = 0 R/W (0b000) - AG can be activated temporarily by HMAC peripheral - DIS_PAD_JTAG (BLOCK0) Permanently disable JTAG access via pads. USB JTAG = False R/W (0b0) - is controlled separately. - - Security fuses: - DIS_DOWNLOAD_MANUAL_ENCRYPT (BLOCK0) Disables flash encryption when in download boot mo = False R/W (0b0) - des - SPI_BOOT_CRYPT_CNT (BLOCK0) Enables encryption and decryption, when an SPI boo = Disable R/W (0b000) - t mode is set. Enabled when 1 or 3 bits are set,di - sabled otherwise - SECURE_BOOT_KEY_REVOKE0 (BLOCK0) If set, revokes use of secure boot key digest 0 = False R/W (0b0) - SECURE_BOOT_KEY_REVOKE1 (BLOCK0) If set, revokes use of secure boot key digest 1 = False R/W (0b0) - SECURE_BOOT_KEY_REVOKE2 (BLOCK0) If set, revokes use of secure boot key digest 2 = False R/W (0b0) - KEY_PURPOSE_0 (BLOCK0) KEY0 purpose = USER R/W (0x0) - KEY_PURPOSE_1 (BLOCK0) KEY1 purpose = USER R/W (0x0) - KEY_PURPOSE_2 (BLOCK0) KEY2 purpose = USER R/W (0x0) - KEY_PURPOSE_3 (BLOCK0) KEY3 purpose = USER R/W (0x0) - KEY_PURPOSE_4 (BLOCK0) KEY4 purpose = USER R/W (0x0) - KEY_PURPOSE_5 (BLOCK0) KEY5 purpose = USER R/W (0x0) - SECURE_BOOT_EN (BLOCK0) Enables secure boot = False R/W (0b0) - SECURE_BOOT_AGGRESSIVE_REVOKE (BLOCK0) Enables aggressive secure boot key revocation mode = False R/W (0b0) - DIS_DOWNLOAD_MODE (BLOCK0) Disables all Download boot modes = False R/W (0b0) - ENABLE_SECURITY_DOWNLOAD (BLOCK0) Enables secure UART download mode (read/write flas = False R/W (0b0) - h only) - BLOCK_KEY0 (BLOCK4)(0 errors): - Purpose: USER - Encryption key0 or user data - = 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 R/W - BLOCK_KEY1 (BLOCK5)(0 errors): - Purpose: USER - Encryption key1 or user data - = 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 R/W - BLOCK_KEY2 (BLOCK6)(0 errors): - Purpose: USER - Encryption key2 or user data - = 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 R/W - BLOCK_KEY3 (BLOCK7)(0 errors): - Purpose: USER - Encryption key3 or user data - = 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 R/W - BLOCK_KEY4 (BLOCK8)(0 errors): - Purpose: USER - Encryption key4 or user data - = 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 R/W - BLOCK_KEY5 (BLOCK9)(0 errors): - Purpose: USER - Encryption key5 or user data - = 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 R/W - BLOCK_SYS_DATA2 (BLOCK10)(0 errors): System data (part 2) - = 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 R/W - - Spi_Pad_Config fuses: - SPI_PAD_CONFIG_CLK (BLOCK1) SPI CLK pad = 0 R/W (0b000000) - SPI_PAD_CONFIG_Q (BLOCK1) SPI Q (D1) pad = 0 R/W (0b000000) - SPI_PAD_CONFIG_D (BLOCK1) SPI D (D0) pad = 0 R/W (0b000000) - SPI_PAD_CONFIG_CS (BLOCK1) SPI CS pad = 0 R/W (0b000000) - SPI_PAD_CONFIG_HD (BLOCK1) SPI HD (D3) pad = 0 R/W (0b000000) - SPI_PAD_CONFIG_WP (BLOCK1) SPI WP (D2) pad = 0 R/W (0b000000) - SPI_PAD_CONFIG_DQS (BLOCK1) SPI DQS pad = 0 R/W (0b000000) - SPI_PAD_CONFIG_D4 (BLOCK1) SPI D4 pad = 0 R/W (0b000000) - SPI_PAD_CONFIG_D5 (BLOCK1) SPI D5 pad = 0 R/W (0b000000) - SPI_PAD_CONFIG_D6 (BLOCK1) SPI D6 pad = 0 R/W (0b000000) - SPI_PAD_CONFIG_D7 (BLOCK1) SPI D7 pad = 0 R/W (0b000000) - - Usb Config fuses: - DIS_USB_JTAG (BLOCK0) Disables USB JTAG. JTAG access via pads is control = False R/W (0b0) - led separately - DIS_USB_DEVICE (BLOCK0) Disables USB DEVICE = False R/W (0b0) - DIS_USB (BLOCK0) Disables the USB OTG hardware = False R/W (0b0) - USB_EXCHG_PINS (BLOCK0) Exchanges USB D+ and D- pins = False R/W (0b0) - DIS_USB_SERIAL_JTAG_DOWNLOAD_MODE (BLOCK0) Disables download through USB-Serial-JTAG = False R/W (0b0) - - Vdd_Spi Config fuses: - PIN_POWER_SELECTION (BLOCK0) GPIO33-GPIO37 power supply selection in ROM code = VDD3P3_CPU R/W (0b0) - - Wdt Config fuses: - WDT_DELAY_SEL (BLOCK0) Selects RTC WDT timeout threshold at startup = False R/W (0b0) diff --git a/docs/en/espefuse/inc/summary_ESP32-S2.rst b/docs/en/espefuse/inc/summary_ESP32-S2.rst deleted file mode 100644 index cfc61535f..000000000 --- a/docs/en/espefuse/inc/summary_ESP32-S2.rst +++ /dev/null @@ -1,152 +0,0 @@ -.. code-block:: none - - > espefuse.py -p PORT summary - - Connecting.... - Detecting chip type... ESP32-S2 - EFUSE_NAME (Block) Description = [Meaningful Value] [Readable/Writeable] (Hex Value) - ---------------------------------------------------------------------------------------- - Calibration fuses: - TEMP_SENSOR_CAL (BLOCK2) Temperature calibration = -9.200000000000001 R/W (0b101011100) - ADC1_MODE0_D2 (BLOCK2) ADC1 calibration 1 = -28 R/W (0x87) - ADC1_MODE1_D2 (BLOCK2) ADC1 calibration 2 = -28 R/W (0x87) - ADC1_MODE2_D2 (BLOCK2) ADC1 calibration 3 = -28 R/W (0x87) - ADC1_MODE3_D2 (BLOCK2) ADC1 calibration 4 = -24 R/W (0x86) - ADC2_MODE0_D2 (BLOCK2) ADC2 calibration 5 = 12 R/W (0x03) - ADC2_MODE1_D2 (BLOCK2) ADC2 calibration 6 = 8 R/W (0x02) - ADC2_MODE2_D2 (BLOCK2) ADC2 calibration 7 = 12 R/W (0x03) - ADC2_MODE3_D2 (BLOCK2) ADC2 calibration 8 = 16 R/W (0x04) - ADC1_MODE0_D1 (BLOCK2) ADC1 calibration 9 = -20 R/W (0b100101) - ADC1_MODE1_D1 (BLOCK2) ADC1 calibration 10 = -12 R/W (0b100011) - ADC1_MODE2_D1 (BLOCK2) ADC1 calibration 11 = -12 R/W (0b100011) - ADC1_MODE3_D1 (BLOCK2) ADC1 calibration 12 = -4 R/W (0b100001) - ADC2_MODE0_D1 (BLOCK2) ADC2 calibration 13 = -12 R/W (0b100011) - ADC2_MODE1_D1 (BLOCK2) ADC2 calibration 14 = -8 R/W (0b100010) - ADC2_MODE2_D1 (BLOCK2) ADC2 calibration 15 = -8 R/W (0b100010) - ADC2_MODE3_D1 (BLOCK2) ADC2 calibration 16 = -4 R/W (0b100001) - - Config fuses: - DIS_RTC_RAM_BOOT (BLOCK0) Disables boot from RTC RAM = False R/W (0b0) - DIS_ICACHE (BLOCK0) Disables ICache = False R/W (0b0) - DIS_DCACHE (BLOCK0) Disables DCache = False R/W (0b0) - DIS_DOWNLOAD_ICACHE (BLOCK0) Disables Icache when SoC is in Download mode = False R/W (0b0) - DIS_DOWNLOAD_DCACHE (BLOCK0) Disables Dcache when SoC is in Download mode = False R/W (0b0) - DIS_FORCE_DOWNLOAD (BLOCK0) Disables forcing chip into Download mode = False R/W (0b0) - DIS_CAN (BLOCK0) Disables the TWAI Controller hardware = False R/W (0b0) - DIS_BOOT_REMAP (BLOCK0) Disables capability to Remap RAM to ROM address sp = False R/W (0b0) - ace - FLASH_TPUW (BLOCK0) Configures flash startup delay after SoC power-up, = 0 R/W (0x0) - unit is (ms/2). When the value is 15, delay is 7. - 5 ms - DIS_LEGACY_SPI_BOOT (BLOCK0) Disables Legacy SPI boot mode = False R/W (0b0) - UART_PRINT_CHANNEL (BLOCK0) Selects the default UART for printing boot msg = UART0 R/W (0b0) - DIS_USB_DOWNLOAD_MODE (BLOCK0) Disables use of USB in UART download boot mode = False R/W (0b0) - UART_PRINT_CONTROL (BLOCK0) Sets the default UART boot message output mode = Enabled R/W (0b00) - FLASH_TYPE (BLOCK0) Selects SPI flash type = 4 data lines R/W (0b0) - FORCE_SEND_RESUME (BLOCK0) Forces ROM code to send an SPI flash resume comman = False R/W (0b0) - d during SPI boot - BLOCK_USR_DATA (BLOCK3) User data - = 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 R/W - - Efuse fuses: - WR_DIS (BLOCK0) Disables programming of individual eFuses = 0 R/W (0x00000000) - RD_DIS (BLOCK0) Disables software reading from BLOCK4-10 = 0 R/W (0b0000000) - - Identity fuses: - BLOCK0_VERSION (BLOCK0) BLOCK0 efuse version = 0 R/W (0b00) - SECURE_VERSION (BLOCK0) Secure version (used by ESP-IDF anti-rollback feat = 0 R/W (0x0000) - ure) - MAC (BLOCK1) Factory MAC Address - = 7c:df:a1:00:3a:6e: (OK) R/W - WAFER_VERSION (BLOCK1) WAFER version = A R/W (0b000) - PKG_VERSION (BLOCK1) Package version - = ESP32-S2, QFN 7x7 56 pins R/W (0x0) - BLOCK1_VERSION (BLOCK1) BLOCK1 efuse version = 0 R/W (0b000) - OPTIONAL_UNIQUE_ID (BLOCK2)(0 errors): Optional unique 128-bit ID - = 7d 33 b8 bb 0b 13 b3 c8 71 37 0e e8 7c ab d5 92 R/W - BLK_VERSION_MINOR (BLOCK2) Version of BLOCK2 = With calibration R/W (0b001) - CUSTOM_MAC (BLOCK3) Custom MAC Address - = 00:00:00:00:00:00 (OK) R/W - - Security fuses: - SOFT_DIS_JTAG (BLOCK0) Software disables JTAG. When software disabled, JT = False R/W (0b0) - AG can be activated temporarily by HMAC peripheral - HARD_DIS_JTAG (BLOCK0) Hardware disables JTAG permanently = False R/W (0b0) - DIS_DOWNLOAD_MANUAL_ENCRYPT (BLOCK0) Disables flash encryption when in download boot mo = False R/W (0b0) - des - SPI_BOOT_CRYPT_CNT (BLOCK0) Enables encryption and decryption, when an SPI boo = Disable R/W (0b000) - t mode is set. Enabled when 1 or 3 bits are set,di - sabled otherwise - SECURE_BOOT_KEY_REVOKE0 (BLOCK0) If set, revokes use of secure boot key digest 0 = False R/W (0b0) - SECURE_BOOT_KEY_REVOKE1 (BLOCK0) If set, revokes use of secure boot key digest 1 = False R/W (0b0) - SECURE_BOOT_KEY_REVOKE2 (BLOCK0) If set, revokes use of secure boot key digest 2 = False R/W (0b0) - KEY_PURPOSE_0 (BLOCK0) KEY0 purpose = USER R/W (0x0) - KEY_PURPOSE_1 (BLOCK0) KEY1 purpose = USER R/W (0x0) - KEY_PURPOSE_2 (BLOCK0) KEY2 purpose = USER R/W (0x0) - KEY_PURPOSE_3 (BLOCK0) KEY3 purpose = USER R/W (0x0) - KEY_PURPOSE_4 (BLOCK0) KEY4 purpose = USER R/W (0x0) - KEY_PURPOSE_5 (BLOCK0) KEY5 purpose = USER R/W (0x0) - SECURE_BOOT_EN (BLOCK0) Enables secure boot = False R/W (0b0) - SECURE_BOOT_AGGRESSIVE_REVOKE (BLOCK0) Enables aggressive secure boot key revocation mode = False R/W (0b0) - DIS_DOWNLOAD_MODE (BLOCK0) Disables all Download boot modes = False R/W (0b0) - ENABLE_SECURITY_DOWNLOAD (BLOCK0) Enables secure UART download mode (read/write flas = False R/W (0b0) - h only) - BLOCK_KEY0 (BLOCK4)(0 errors): - Purpose: USER - Encryption key0 or user data - = 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 R/W - BLOCK_KEY1 (BLOCK5)(0 errors): - Purpose: USER - Encryption key1 or user data - = 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 R/W - BLOCK_KEY2 (BLOCK6)(0 errors): - Purpose: USER - Encryption key2 or user data - = 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 R/W - BLOCK_KEY3 (BLOCK7)(0 errors): - Purpose: USER - Encryption key3 or user data - = 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 R/W - BLOCK_KEY4 (BLOCK8)(0 errors): - Purpose: USER - Encryption key4 or user data - = 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 R/W - BLOCK_KEY5 (BLOCK9)(0 errors): - Purpose: USER - Encryption key5 or user data - = 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 R/W - BLOCK_SYS_DATA2 (BLOCK10) System data (part 2) - = 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 R/W - - Spi_Pad_Config fuses: - SPI_PAD_CONFIG_CLK (BLOCK1) SPI CLK pad = 0 R/W (0b000000) - SPI_PAD_CONFIG_Q (BLOCK1) SPI Q (D1) pad = 0 R/W (0b000000) - SPI_PAD_CONFIG_D (BLOCK1) SPI D (D0) pad = 0 R/W (0b000000) - SPI_PAD_CONFIG_CS (BLOCK1) SPI CS pad = 0 R/W (0b000000) - SPI_PAD_CONFIG_HD (BLOCK1) SPI HD (D3) pad = 0 R/W (0b000000) - SPI_PAD_CONFIG_WP (BLOCK1) SPI WP (D2) pad = 0 R/W (0b000000) - SPI_PAD_CONFIG_DQS (BLOCK1) SPI DQS pad = 0 R/W (0b000000) - SPI_PAD_CONFIG_D4 (BLOCK1) SPI D4 pad = 0 R/W (0b000000) - SPI_PAD_CONFIG_D5 (BLOCK1) SPI D5 pad = 0 R/W (0b000000) - SPI_PAD_CONFIG_D6 (BLOCK1) SPI D6 pad = 0 R/W (0b000000) - SPI_PAD_CONFIG_D7 (BLOCK1) SPI D7 pad = 0 R/W (0b000000) - - Usb Config fuses: - DIS_USB (BLOCK0) Disables the USB OTG hardware = False R/W (0b0) - USB_EXCHG_PINS (BLOCK0) Exchanges USB D+ and D- pins = False R/W (0b0) - EXT_PHY_ENABLE (BLOCK0) Enables external USB PHY = False R/W (0b0) - USB_FORCE_NOPERSIST (BLOCK0) Forces to set USB BVALID to 1 = False R/W (0b0) - - Vdd_Spi Config fuses: - VDD_SPI_FORCE (BLOCK0) Force using VDD_SPI_XPD and VDD_SPI_TIEH to config = False R/W (0b0) - ure VDD_SPI LDO - VDD_SPI_XPD (BLOCK0) The VDD_SPI regulator is powered on = False R/W (0b0) - VDD_SPI_TIEH (BLOCK0) The VDD_SPI power supply voltage at reset = Connect to 1.8V LDO R/W (0b0) - PIN_POWER_SELECTION (BLOCK0) Sets default power supply for GPIO33..37, set when = VDD3P3_CPU R/W (0b0) - SPI flash is initialized - - Wdt Config fuses: - WDT_DELAY_SEL (BLOCK0) Selects RTC WDT timeout threshold at startup = 0 R/W (0b00) - - Flash voltage (VDD_SPI) determined by GPIO45 on reset (GPIO45=High: VDD_SPI pin is powered from internal 1.8V LDO - GPIO45=Low or NC: VDD_SPI pin is powered directly from VDD3P3_RTC_IO via resistor Rspi. Typically this voltage is 3.3 V). diff --git a/docs/en/espefuse/inc/summary_ESP32-S3.rst b/docs/en/espefuse/inc/summary_ESP32-S3.rst deleted file mode 100644 index 603f64239..000000000 --- a/docs/en/espefuse/inc/summary_ESP32-S3.rst +++ /dev/null @@ -1,151 +0,0 @@ -.. code-block:: none - - > espefuse.py -p PORT summary - - Connecting.... - Detecting chip type... ESP32-S3 - EFUSE_NAME (Block) Description = [Meaningful Value] [Readable/Writeable] (Hex Value) - ---------------------------------------------------------------------------------------- - Calibration fuses: - TEMP_SENSOR_CAL (BLOCK2) Temperature calibration = -9.200000000000001 R/W (0b101011100) - ADC1_MODE0_D2 (BLOCK2) ADC1 calibration 1 = -28 R/W (0x87) - ADC1_MODE1_D2 (BLOCK2) ADC1 calibration 2 = -28 R/W (0x87) - ADC1_MODE2_D2 (BLOCK2) ADC1 calibration 3 = -28 R/W (0x87) - ADC1_MODE3_D2 (BLOCK2) ADC1 calibration 4 = -24 R/W (0x86) - ADC2_MODE0_D2 (BLOCK2) ADC2 calibration 5 = 12 R/W (0x03) - ADC2_MODE1_D2 (BLOCK2) ADC2 calibration 6 = 8 R/W (0x02) - ADC2_MODE2_D2 (BLOCK2) ADC2 calibration 7 = 12 R/W (0x03) - ADC2_MODE3_D2 (BLOCK2) ADC2 calibration 8 = 16 R/W (0x04) - ADC1_MODE0_D1 (BLOCK2) ADC1 calibration 9 = -20 R/W (0b100101) - ADC1_MODE1_D1 (BLOCK2) ADC1 calibration 10 = -12 R/W (0b100011) - ADC1_MODE2_D1 (BLOCK2) ADC1 calibration 11 = -12 R/W (0b100011) - ADC1_MODE3_D1 (BLOCK2) ADC1 calibration 12 = -4 R/W (0b100001) - ADC2_MODE0_D1 (BLOCK2) ADC2 calibration 13 = -12 R/W (0b100011) - ADC2_MODE1_D1 (BLOCK2) ADC2 calibration 14 = -8 R/W (0b100010) - ADC2_MODE2_D1 (BLOCK2) ADC2 calibration 15 = -8 R/W (0b100010) - ADC2_MODE3_D1 (BLOCK2) ADC2 calibration 16 = -4 R/W (0b100001) - - Config fuses: - DIS_ICACHE (BLOCK0) Disables ICache = False R/W (0b0) - DIS_DCACHE (BLOCK0) Disables DCache = False R/W (0b0) - DIS_DOWNLOAD_ICACHE (BLOCK0) Disables Icache when SoC is in Download mode = False R/W (0b0) - DIS_DOWNLOAD_DCACHE (BLOCK0) Disables Dcache when SoC is in Download mode = False R/W (0b0) - DIS_FORCE_DOWNLOAD (BLOCK0) Disables forcing chip into Download mode = False R/W (0b0) - DIS_CAN (BLOCK0) Disables the TWAI Controller hardware = False R/W (0b0) - DIS_BOOT_REMAP (BLOCK0) Disables capability to Remap RAM to ROM address sp = False R/W (0b0) - ace - FLASH_TPUW (BLOCK0) Configures flash startup delay after SoC power-up, = 0 R/W (0x0) - unit is (ms/2). When the value is 15, delay is 7. - 5 ms - DIS_DIRECT_BOOT (BLOCK0) Disables direct boot mode = False R/W (0b0) - DIS_USB_SERIAL_JTAG_ROM_PRINT (BLOCK0) Selects the default UART for printing boot msg = UART0 R/W (0b0) - DIS_USB_SERIAL_JTAG_DOWNLOAD_MODE (BLOCK0) Disables download through USB-Serial-JTAG = False R/W (0b0) - UART_PRINT_CONTROL (BLOCK0) Sets the default UART boot message output mode = Enabled R/W (0b00) - FLASH_TYPE (BLOCK0) Selects SPI flash type = 4 data lines R/W (0b0) - FORCE_SEND_RESUME (BLOCK0) Forces ROM code to send an SPI flash resume comman = False R/W (0b0) - d during SPI boot - BLOCK_USR_DATA (BLOCK3) User data - = 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 R/W - - Efuse fuses: - WR_DIS (BLOCK0) Disables programming of individual eFuses = 0 R/W (0x00000000) - RD_DIS (BLOCK0) Disables software reading from BLOCK4-10 = 0 R/W (0b0000000) - - Identity fuses: - BLOCK0_VERSION (BLOCK0) BLOCK0 efuse version = 0 R/W (0b00) - SECURE_VERSION (BLOCK0) Secure version (used by ESP-IDF anti-rollback feat = 0 R/W (0x0000) - ure) - MAC (BLOCK1) Factory MAC Address - = 7c:df:a1:00:3a:6e: (OK) R/W - WAFER_VERSION (BLOCK1) WAFER version = A R/W (0b000) - PKG_VERSION (BLOCK1) Package version - = ESP32-S3, QFN 7x7 56 pins R/W (0x0) - BLOCK1_VERSION (BLOCK1) BLOCK1 efuse version = 0 R/W (0b000) - OPTIONAL_UNIQUE_ID (BLOCK2)(0 errors): Optional unique 128-bit ID - = 7d 33 b8 bb 0b 13 b3 c8 71 37 0e e8 7c ab d5 92 R/W - BLK_VERSION_MAJOR (BLOCK2) Version of BLOCK2 = With calibration R/W (0b001) - CUSTOM_MAC (BLOCK3) Custom MAC Address - = 00:00:00:00:00:00 (OK) R/W - - Security fuses: - SOFT_DIS_JTAG (BLOCK0) Software disables JTAG. When software disabled, JT = False R/W (0b000) - AG can be activated temporarily by HMAC peripheral - HARD_DIS_JTAG (BLOCK0) Hardware disables JTAG permanently = False R/W (0b0) - DIS_DOWNLOAD_MANUAL_ENCRYPT (BLOCK0) Disables flash encryption when in download boot mo = False R/W (0b0) - des - SPI_BOOT_CRYPT_CNT (BLOCK0) Enables encryption and decryption, when an SPI boo = Disable R/W (0b000) - t mode is set. Enabled when 1 or 3 bits are set,di - sabled otherwise - SECURE_BOOT_KEY_REVOKE0 (BLOCK0) If set, revokes use of secure boot key digest 0 = False R/W (0b0) - SECURE_BOOT_KEY_REVOKE1 (BLOCK0) If set, revokes use of secure boot key digest 1 = False R/W (0b0) - SECURE_BOOT_KEY_REVOKE2 (BLOCK0) If set, revokes use of secure boot key digest 2 = False R/W (0b0) - KEY_PURPOSE_0 (BLOCK0) KEY0 purpose = USER R/W (0x0) - KEY_PURPOSE_1 (BLOCK0) KEY1 purpose = USER R/W (0x0) - KEY_PURPOSE_2 (BLOCK0) KEY2 purpose = USER R/W (0x0) - KEY_PURPOSE_3 (BLOCK0) KEY3 purpose = USER R/W (0x0) - KEY_PURPOSE_4 (BLOCK0) KEY4 purpose = USER R/W (0x0) - KEY_PURPOSE_5 (BLOCK0) KEY5 purpose = USER R/W (0x0) - SECURE_BOOT_EN (BLOCK0) Enables secure boot = False R/W (0b0) - SECURE_BOOT_AGGRESSIVE_REVOKE (BLOCK0) Enables aggressive secure boot key revocation mode = False R/W (0b0) - DIS_DOWNLOAD_MODE (BLOCK0) Disables all Download boot modes = False R/W (0b0) - ENABLE_SECURITY_DOWNLOAD (BLOCK0) Enables secure UART download mode (read/write flas = False R/W (0b0) - h only) - BLOCK_KEY0 (BLOCK4)(0 errors): - Purpose: USER - Encryption key0 or user data - = 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 R/W - BLOCK_KEY1 (BLOCK5)(0 errors): - Purpose: USER - Encryption key1 or user data - = 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 R/W - BLOCK_KEY2 (BLOCK6)(0 errors): - Purpose: USER - Encryption key2 or user data - = 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 R/W - BLOCK_KEY3 (BLOCK7)(0 errors): - Purpose: USER - Encryption key3 or user data - = 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 R/W - BLOCK_KEY4 (BLOCK8)(0 errors): - Purpose: USER - Encryption key4 or user data - = 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 R/W - BLOCK_KEY5 (BLOCK9)(0 errors): - Purpose: USER - Encryption key5 or user data - = 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 R/W - BLOCK_SYS_DATA2 (BLOCK10) System data (part 2) - = 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 R/W - - Spi_Pad_Config fuses: - SPI_PAD_CONFIG_CLK (BLOCK1) SPI CLK pad = 0 R/W (0b000000) - SPI_PAD_CONFIG_Q (BLOCK1) SPI Q (D1) pad = 0 R/W (0b000000) - SPI_PAD_CONFIG_D (BLOCK1) SPI D (D0) pad = 0 R/W (0b000000) - SPI_PAD_CONFIG_CS (BLOCK1) SPI CS pad = 0 R/W (0b000000) - SPI_PAD_CONFIG_HD (BLOCK1) SPI HD (D3) pad = 0 R/W (0b000000) - SPI_PAD_CONFIG_WP (BLOCK1) SPI WP (D2) pad = 0 R/W (0b000000) - SPI_PAD_CONFIG_DQS (BLOCK1) SPI DQS pad = 0 R/W (0b000000) - SPI_PAD_CONFIG_D4 (BLOCK1) SPI D4 pad = 0 R/W (0b000000) - SPI_PAD_CONFIG_D5 (BLOCK1) SPI D5 pad = 0 R/W (0b000000) - SPI_PAD_CONFIG_D6 (BLOCK1) SPI D6 pad = 0 R/W (0b000000) - SPI_PAD_CONFIG_D7 (BLOCK1) SPI D7 pad = 0 R/W (0b000000) - - Usb Config fuses: - DIS_USB (BLOCK0) Disables the USB OTG hardware = False R/W (0b0) - USB_EXCHG_PINS (BLOCK0) Exchanges USB D+ and D- pins = False R/W (0b0) - EXT_PHY_ENABLE (BLOCK0) Enables external USB PHY = False R/W (0b0) - USB_FORCE_NOPERSIST (BLOCK0) Forces to set USB BVALID to 1 = False R/W (0b0) - - Vdd_Spi Config fuses: - VDD_SPI_FORCE (BLOCK0) Force using VDD_SPI_XPD and VDD_SPI_TIEH to config = False R/W (0b0) - ure VDD_SPI LDO - VDD_SPI_XPD (BLOCK0) The VDD_SPI regulator is powered on = False R/W (0b0) - VDD_SPI_TIEH (BLOCK0) The VDD_SPI power supply voltage at reset = Connect to 1.8V LDO R/W (0b0) - PIN_POWER_SELECTION (BLOCK0) Sets default power supply for GPIO33..37, set when = VDD3P3_CPU R/W (0b0) - SPI flash is initialized - - Wdt Config fuses: - WDT_DELAY_SEL (BLOCK0) Selects RTC WDT timeout threshold at startup = 0 R/W (0b00) - - Flash voltage (VDD_SPI) determined by GPIO45 on reset (GPIO45=High: VDD_SPI pin is powered from internal 1.8V LDO - GPIO45=Low or NC: VDD_SPI pin is powered directly from VDD3P3_RTC_IO via resistor Rspi. Typically this voltage is 3.3 V). diff --git a/docs/en/espefuse/inc/summary_ESP32.rst b/docs/en/espefuse/inc/summary_ESP32.rst deleted file mode 100644 index 575cdb91a..000000000 --- a/docs/en/espefuse/inc/summary_ESP32.rst +++ /dev/null @@ -1,64 +0,0 @@ -.. code-block:: none - - > espefuse.py -p PORT summary - - Connecting........__ - Detecting chip type... ESP32 - EFUSE_NAME (Block) Description = [Meaningful Value] [Readable/Writeable] (Hex Value) - ---------------------------------------------------------------------------------------- - Calibration fuses: - BLK3_PART_RESERVE (BLOCK0): BLOCK3 partially served for ADC calibration data = True R/W (0b1) - ADC_VREF (BLOCK0): Voltage reference calibration = 1114 R/W (0b00010) - ADC1_TP_LOW (BLOCK3): ADC1 150mV reading = 346 R/W (0b0010001) - ADC1_TP_HIGH (BLOCK3): ADC1 850mV reading = 3285 R/W (0b000000101) - ADC2_TP_LOW (BLOCK3): ADC2 150mV reading = 449 R/W (0b0000111) - ADC2_TP_HIGH (BLOCK3): ADC2 850mV reading = 3362 R/W (0b111110101) - - Config fuses: - XPD_SDIO_FORCE (BLOCK0): Ignore MTDI pin (GPIO12) for VDD_SDIO on reset = False R/W (0b0) - XPD_SDIO_REG (BLOCK0): If XPD_SDIO_FORCE, enable VDD_SDIO reg on reset = False R/W (0b0) - XPD_SDIO_TIEH (BLOCK0): If XPD_SDIO_FORCE & XPD_SDIO_REG = 1.8V R/W (0b0) - CLK8M_FREQ (BLOCK0): 8MHz clock freq override = 53 R/W (0x35) - SPI_PAD_CONFIG_CLK (BLOCK0): Override SD_CLK pad (GPIO6/SPICLK) = 0 R/W (0b00000) - SPI_PAD_CONFIG_Q (BLOCK0): Override SD_DATA_0 pad (GPIO7/SPIQ) = 0 R/W (0b00000) - SPI_PAD_CONFIG_D (BLOCK0): Override SD_DATA_1 pad (GPIO8/SPID) = 0 R/W (0b00000) - SPI_PAD_CONFIG_HD (BLOCK0): Override SD_DATA_2 pad (GPIO9/SPIHD) = 0 R/W (0b00000) - SPI_PAD_CONFIG_CS0 (BLOCK0): Override SD_CMD pad (GPIO11/SPICS0) = 0 R/W (0b00000) - DISABLE_SDIO_HOST (BLOCK0): Disable SDIO host = False R/W (0b0) - - Efuse fuses: - WR_DIS (BLOCK0): Efuse write disable mask = 0 R/W (0x0000) - RD_DIS (BLOCK0): Efuse read disable mask = 0 R/W (0x0) - CODING_SCHEME (BLOCK0): Efuse variable block length scheme - = 3/4 (BLK1-3 len=192 bits) R/W (0b01) - KEY_STATUS (BLOCK0): Usage of efuse block 3 (reserved) = False R/W (0b0) - - Identity fuses: - MAC (BLOCK0): Factory MAC Address - = 84:0d:8e:18:8e:44 (CRC 0xad OK) R/W - MAC_CRC (BLOCK0): CRC8 for factory MAC address = 173 R/W (0xad) - CHIP_VER_REV1 (BLOCK0): Silicon Revision 1 = True R/W (0b1) - CHIP_VER_REV2 (BLOCK0): Silicon Revision 2 = False R/W (0b0) - CHIP_VERSION (BLOCK0): Reserved for future chip versions = 2 R/W (0b10) - CHIP_PACKAGE (BLOCK0): Chip package identifier = 0 R/W (0b000) - MAC_VERSION (BLOCK3): Version of the MAC field = 0 R/W (0x00) - - Security fuses: - FLASH_CRYPT_CNT (BLOCK0): Flash encryption mode counter = 0 R/W (0b0000000) - UART_DOWNLOAD_DIS (BLOCK0): Disable UART download mode (ESP32 rev3 only) = False R/W (0b0) - FLASH_CRYPT_CONFIG (BLOCK0): Flash encryption config (key tweak bits) = 0 R/W (0x0) - CONSOLE_DEBUG_DISABLE (BLOCK0): Disable ROM BASIC interpreter fallback = True R/W (0b1) - ABS_DONE_0 (BLOCK0): Secure boot V1 is enabled for bootloader image = False R/W (0b0) - ABS_DONE_1 (BLOCK0): Secure boot V2 is enabled for bootloader image = False R/W (0b0) - JTAG_DISABLE (BLOCK0): Disable JTAG = False R/W (0b0) - DISABLE_DL_ENCRYPT (BLOCK0): Disable flash encryption in UART bootloader = False R/W (0b0) - DISABLE_DL_DECRYPT (BLOCK0): Disable flash decryption in UART bootloader = False R/W (0b0) - DISABLE_DL_CACHE (BLOCK0): Disable flash cache in UART bootloader = False R/W (0b0) - BLOCK1 (BLOCK1): Flash encryption key - = 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 R/W - BLOCK2 (BLOCK2): Secure boot key - = 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 R/W - BLOCK3 (BLOCK3): Variable Block 3 - = 00 00 00 00 00 00 00 00 00 00 00 00 91 02 87 fa 00 00 00 00 00 00 00 00 R/W - - Flash voltage (VDD_SDIO) determined by GPIO12 on reset (High for 1.8V, Low/NC for 3.3V). diff --git a/docs/en/espefuse/index.rst b/docs/en/espefuse/index.rst deleted file mode 100644 index 7c8c40c88..000000000 --- a/docs/en/espefuse/index.rst +++ /dev/null @@ -1,124 +0,0 @@ -.. _espefuse: - -espefuse.py -=========== - -``espefuse.py`` is a tool for communicating with Espressif chips for the purpose of reading/writing ("burning") the one-time-programmable eFuses. Burning occurs only in one direction from 0 to 1 (never cleared 1->0). - -.. warning:: - - Because eFuse is one-time-programmable, it is possible to permanently damage or "brick" your {IDF_TARGET_NAME} using this tool. Use it with great care. - -For more details about Espressif chips eFuse features, see the `Technical Reference Manual `__. - -``espefuse.py`` is installed alongside ``esptool.py``, so if ``esptool.py`` (v2.0 or newer) is available on the PATH then ``espefuse.py`` should be as well. - -Initial State of Efuses ------------------------ - -On relatively new chip, most eFuses are unburned (value 0). Some eFuses are already burned at the factory stage: - -- MAC (Factory MAC Address). -- ADC calibration -- Chip package and revision. -- etc. - -Supported Commands ------------------- - -.. toctree:: - :maxdepth: 1 - - dump - summary - burn_efuse - burn_block_data - burn_bit - read_protect_efuse and write_protect_efuse - burn_key - burn_key_digest - burn_custom_mac - get_custom_mac - adc_info - set_flash_voltage - execute_scripts - check_error - -Optional General Arguments Of Commands --------------------------------------- - -- ``-h``, ``--help`` - Show help message and exit. Use ``-h`` to see a summary of all available commands and command line options. To see all options for a particular chip and command, add ``-c {IDF_TARGET_NAME}`` and ``-h`` to the command name, i.e. ``espefuse.py -c {IDF_TARGET_NAME} burn_key -h``. -- ``--chip``, ``-c`` - Target chip type. If this argument is omitted, the tool automatically detects the chip type when connected. But if the command has a help option, the chip is not connected, and the default chip is ``esp32``, please specify the specific type of chip to get the correct help. Example of usage: ``-c esp32``, ``-c esp32c3``, ``-c esp32s2`` and others. -- ``--baud``, ``-b`` - Serial port baud rate, the same as for esptool. -- ``--port``, ``-p`` - Serial port device, ``-p /dev/ttyUSB0`` (Linux and macOS) or ``-p COM1`` (Windows). -- ``--before`` - What to do before connecting to the chip: ``default_reset``, ``no_reset``, ``esp32r1``, ``no_reset_no_sync``. -- ``--debug``, ``-d`` - Show debugging information. -- ``--virt`` - For host tests. The tool will work in the virtual mode (without connecting to a chip). -- ``--path-efuse-file`` - For host tests. Use it together with ``--virt`` option. The tool will work in the virtual mode (without connecting to a chip) and save eFuse memory to a given file. If the file does not exists the tool creates it. To reset written eFuses just delete the file. Usage: ``--path-efuse-file efuse_memory.bin``. -- ``--do-not-confirm`` - Do not pause for confirmation before permanently writing eFuses. Use with caution. If this option is not used, a manual confirmation step is required, you need to enter the word ``BURN`` to continue burning. - -Virtual mode -^^^^^^^^^^^^ - -This mode is enabled with the ``--virt`` flag (need to specify chip with ``--chip``). This helps to test commands without physical access to the chip. Burned data is not saved between commands. Using ``--path-efuse-file``, you can save the written data to a file. Delete the file to clear eFuses. - -Confirmation -^^^^^^^^^^^^ - -Each burn operation requires manual confirmation, you need to type the word ``BURN`` to continue burning. Using the ``--do-not-confirm`` option allows to skip it. - -Coding Scheme -------------- - -The coding scheme helps the eFuse controller to detect an error of the eFuse blocks. There are special registers that indicate that there is an error in the block. - -{IDF_TARGET_NAME} supports the following coding schemes: - -.. only:: esp32 - - * ``None`` no need any special encoding data. BLOCK0. - * ``3/4``, requires encoding data. The BLOCK length is reduced from 256 bits to 192 bits. - * ``Repeat`` not supported by this tool and IDF. The BLOCK length is reduced from 256 bits to 128 bits. - - BLOCK1-3 can have any of this coding scheme. It depends on the ``CODING_SCHEME`` eFuse. - -.. only:: not esp32 - - * ``None`` no need any special encoding data, but internally it copies data four times. BLOCK0. - * ``RS`` (Reed-Solomon), it uses 6 bytes of automatic error correction. - - Rest eFuse blocks from BLOCK1 to BLOCK(max) have ``RS`` coding scheme. - -This tool automatically adds encoding data to the burning data if it requires. Encoded data is calculated individually for each block. - -All coding schemes (except ``None``) require additional encoding data to be provided at write time. Due to the encoding data, such blocks cannot be overwritten again without breaking the block's coding scheme. Use the :ref:`perform-multiple-operations` feature or list multiple eFuses/keys. - -Burning Efuse -------------- - -Burning occurs in order from BLOCK(max) to BLOCK0. This prevents read/write protection from being set before the data is set. After burning, the tool reads the written data back and compares the original data, and additionally checks the status of the coding scheme, if there are any errors, it re-burns the data again to correct it. - -.. _perform-multiple-operations: - -Perform Multiple Operations In A Single Espefuse Run ----------------------------------------------------- - -Some eFuse blocks have an encoding scheme (Reed-Solomon or 3/4) that requires encoded data, making these blocks only writable once. If you need to write multiple keys/eFuses to one block using different commands, you can use this feature - multiple commands. This feature burns given data once at the end of all commands. All commands supported by version v3.2 or later are supported to be chained together. - -The example below shows how to use the two commands ``burn_key_digest`` and ``burn_key`` to write the Secure Boot key and Flash Encryption key into one BLOCK3 for the ``ESP32-C2`` chip. Using these commands individually will result in only one key being written correctly. - -.. code-block:: none - - > espefuse.py -c esp32c2 \ - burn_key_digest secure_images/ecdsa256_secure_boot_signing_key_v2.pem \ - burn_key BLOCK_KEY0 images/efuse/128bit_key.bin XTS_AES_128_KEY_DERIVED_FROM_128_EFUSE_BITS - -Recommendations ---------------- - -1. The `Technical Reference Manual `__ has a recommendation for reducing the number of burn operations as much as possible. The tool supports several ways to do this: - - - Combine multiple commands into one with this :ref:`perform-multiple-operations` feature. - - Most commands support getting a list of arguments (eFuse names, keys). - -3. Make sure the power supply is stable because this may cause burning problems. diff --git a/docs/en/espefuse/read-write-protections-cmd.rst b/docs/en/espefuse/read-write-protections-cmd.rst deleted file mode 100644 index c6c6364cb..000000000 --- a/docs/en/espefuse/read-write-protections-cmd.rst +++ /dev/null @@ -1,81 +0,0 @@ -.. _read-write-protections-cmd: - -Read Write Protection -===================== - -There are two commands (to get the correct list of eFuse fields that can be protected, specify the chip with ``--chip``): - -- ``espefuse.py read_protect_efuse``. It sets read protection for given eFuse names. -- ``espefuse.py write_protect_efuse``. It sets write protection for given eFuse names. - -Positional arguments: - -- eFuse name. It can recieve a list of eFuse names (like EFUSE_NAME1 EFUSE_NAME2 etc.). - -Read protection prevents software from reading eFuse fields, only hardware can access such eFuses. Such eFuses are read as zero and the data is marked as ``??`` in this tool. - -Write protection prevents further changes of eFuse fields. - -Not all eFuses have read and write protections. See the help for these commands for the eFuse names that can be protected. - -eFuses are often read/write protected as a group, so protecting one of eFuse will result in some related eFuses becoming protected. The tool will show the full list of eFuses that will be protected. - -Read and Write Protection Status -^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - -The ``R/W`` output indicates a protection status of a specific eFuse field/block: - -- ``-/W`` indicates that read protection is set. Value of such eFuse field will always show all-zeroes, even though hardware may use the correct value. In espefuse v2.6 and newer, read-protected eFuse values are displayed as question marks (``??``). On earlier versions, they are displayed as zeroes. - - .. code-block:: none - - BLOCK1 (BLOCK1): - = ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? -/W - -- ``R/-`` indicates that write protection is set. No further bits can be set. -- ``-/-`` means both read and write protection are set. - -Usage ------ - -.. code-block:: none - - > espefuse.py read_protect_efuse BLOCK2 BLOCK3 MAC_VERSION - - === Run "read_protect_efuse" command === - If Secure Boot V2 is used, BLOCK2 must be readable, please stop this operation! - Permanently read-disabling efuse BLOCK2 - Permanently read-disabling efuses MAC_VERSION, BLOCK3 - Permanently read-disabling efuses MAC_VERSION, BLOCK3 - - Check all blocks for burn... - idx, BLOCK_NAME, Conclusion - [00] BLOCK0 is empty, will burn the new value - . - This is an irreversible operation! - Type 'BURN' (all capitals) to continue. - BURN - BURN BLOCK0 - OK (write block == read block) - Reading updated efuses... - Checking efuses... - Successful - -.. code-block:: none - - > espefuse.py write_protect_efuse WR_DIS FLASH_CRYPT_CNT - - === Run "write_protect_efuse" command === - Permanently write-disabling efuse WR_DIS - Permanently write-disabling efuses FLASH_CRYPT_CNT, UART_DOWNLOAD_DIS - - Check all blocks for burn... - idx, BLOCK_NAME, Conclusion - [00] BLOCK0 is empty, will burn the new value - . - This is an irreversible operation! - Type 'BURN' (all capitals) to continue. - BURN - BURN BLOCK0 - OK (write block == read block) - Reading updated efuses... - Checking efuses... - Successful diff --git a/docs/en/espefuse/set-flash-voltage-cmd.rst b/docs/en/espefuse/set-flash-voltage-cmd.rst deleted file mode 100644 index 719a76c6c..000000000 --- a/docs/en/espefuse/set-flash-voltage-cmd.rst +++ /dev/null @@ -1,161 +0,0 @@ -.. _set-flash-voltage-cmd: - -Set Flash Voltage -================= - -{IDF_TARGET_VDD_SPI:default="VDD_SPI",esp32="VDD_SDIO"} -{IDF_TARGET_VDD_FORCE:default="VDD_SPI_FORCE",esp32="XPD_SDIO_FORCE"} -{IDF_TARGET_VDD_TIEH:default="VDD_SPI_TIEH",esp32="XPD_SDIO_TIEH"} -{IDF_TARGET_VDD_REG:default="VDD_SPI_XPD",esp32="XPD_SDIO_REG"} -{IDF_TARGET_VDD_GPIO:default="GPIO45",esp32="GPIO12"} - -The ``espefuse.py set_flash_voltage`` command permanently sets the internal flash voltage regulator to either 1.8V, 3.3V or OFF. This means a GPIO can be high or low at reset without changing the flash voltage. - -Positional arguments: - -- ``voltage`` - Voltage selection ['1.8V', '3.3V', 'OFF']. - -.. only:: esp32c2 or esp32c3 - - .. note:: - - This command is not supported. The tool prints the error ``set_flash_voltage not supported!``. - -Setting Flash Voltage ({IDF_TARGET_VDD_SPI}) -^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - -After reset, the default {IDF_TARGET_NAME} behaviour is to enable and configure the flash voltage regulator ({IDF_TARGET_VDD_SPI}) based on the level of the MTDI pin ({IDF_TARGET_VDD_GPIO}). - -The default behaviour on reset is: - -+--------------------+--------------------+ -| MTDI | Internal Regulator | -+====================+====================+ -| Low or unconnected | Enabled at 3.3V | -+--------------------+--------------------+ -| High | Enabled at 1.8V | -+--------------------+--------------------+ - -.. only:: esp32 - - Consult ESP32 Technical Reference Manual chapter 4.8.1 "{IDF_TARGET_VDD_SPI} Power Domain" for details. - -.. only:: not esp32 - - Consult {IDF_TARGET_NAME} Technical Reference Manual for details. - -A combination of 3 efuses (``{IDF_TARGET_VDD_FORCE}``, ``{IDF_TARGET_VDD_REG}``, ``{IDF_TARGET_VDD_TIEH}``) can be burned in order to override this behaviour and disable {IDF_TARGET_VDD_SPI} regulator, or set it to a fixed voltage. These efuses can be burned with individual ``burn_efuse`` commands, but the ``set_flash_voltage`` command makes it easier: - -Disable {IDF_TARGET_VDD_SPI} Regulator -^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - -.. code-block:: none - - espefuse.py set_flash_voltage OFF - -Once set: - -* {IDF_TARGET_VDD_SPI} regulator always disabled. -* MTDI pin ({IDF_TARGET_VDD_GPIO}) is ignored. -* Flash must be powered externally and voltage supplied to {IDF_TARGET_VDD_SPI} pin of {IDF_TARGET_NAME}. -* Efuse ``{IDF_TARGET_VDD_FORCE}`` is burned. - -Fixed 1.8V {IDF_TARGET_VDD_SPI} -^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - -.. code-block:: none - - espefuse.py set_flash_voltage 1.8V - -Once set: - -* {IDF_TARGET_VDD_SPI} regulator always enables at 1.8V. -* MTDI pin ({IDF_TARGET_VDD_GPIO}) is ignored. -* External voltage should not be supplied to {IDF_TARGET_VDD_SPI}. -* Efuses ``{IDF_TARGET_VDD_FORCE}`` and ``{IDF_TARGET_VDD_REG}`` are burned. - -Fixed 3.3V {IDF_TARGET_VDD_SPI} -^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - -.. code-block:: none - - espefuse.py set_flash_voltage 3.3V - -Once set: - -* {IDF_TARGET_VDD_SPI} regulator always enables at 3.3V. -* MTDI pin ({IDF_TARGET_VDD_GPIO}) is ignored. -* External voltage should not be supplied to {IDF_TARGET_VDD_SPI}. -* Efuses ``{IDF_TARGET_VDD_FORCE}``, ``{IDF_TARGET_VDD_REG}``, ``{IDF_TARGET_VDD_TIEH}`` are burned. - -Subsequent Changes -^^^^^^^^^^^^^^^^^^ - -Once an efuse is burned it cannot be un-burned. However, changes can be made by burning additional efuses: - -* ``set_flash_voltage OFF`` can be changed to ``1.8V`` or ``3.3V`` -* ``set_flash_voltage 1.8V`` can be changed to ``3.3V`` - - -.. only:: esp32s2 or esp32s3 - - .. code-block:: none - - > espefuse.py set_flash_voltage 1.8V - - === Run "set_flash_voltage" command === - Set internal flash voltage regulator (VDD_SPI) to 1.8V. - - VDD_SPI setting complete. - - Check all blocks for burn... - idx, BLOCK_NAME, Conclusion - [00] BLOCK0 is empty, will burn the new value - . - This is an irreversible operation! - Type 'BURN' (all capitals) to continue. - BURN - BURN BLOCK0 - OK (write block == read block) - Reading updated efuses... - Successful - - - .. code-block:: none - - > espefuse.py set_flash_voltage 3.3V - - === Run "set_flash_voltage" command === - Enable internal flash voltage regulator (VDD_SPI) to 3.3V. - - VDD_SPI setting complete. - - Check all blocks for burn... - idx, BLOCK_NAME, Conclusion - [00] BLOCK0 is empty, will burn the new value - . - This is an irreversible operation! - Type 'BURN' (all capitals) to continue. - BURN - BURN BLOCK0 - OK (write block == read block) - Reading updated efuses... - Successful - - - .. code-block:: none - - > espefuse.py set_flash_voltage OFF - - === Run "set_flash_voltage" command === - Disable internal flash voltage regulator (VDD_SPI). SPI flash will - VDD_SPI setting complete. - - Check all blocks for burn... - idx, BLOCK_NAME, Conclusion - [00] BLOCK0 is empty, will burn the new value - . - This is an irreversible operation! - Type 'BURN' (all capitals) to continue. - BURN - BURN BLOCK0 - OK (write block == read block) - Reading updated efuses... - Successful diff --git a/docs/en/espefuse/summary-cmd.rst b/docs/en/espefuse/summary-cmd.rst deleted file mode 100644 index 5e5d46962..000000000 --- a/docs/en/espefuse/summary-cmd.rst +++ /dev/null @@ -1,114 +0,0 @@ -.. _summary-cmd: - -Summary -======= - -The ``espefuse.py summary`` command reads all eFuses from the chip and outputs them in text or json format. It is also possible to save it to a file. - -Optional arguments: - -- ``--format`` - Select the summary format: ``summary`` - text format (default option), ``json`` - json format. Usage ``--format json``. -- ``--file`` - File to save the efuse summary. Usage ``--file efuses.json``. - -Text Format Summary -------------------- - -The text format of summary consists of 3 main columns: - -1. This column consists of the eFuse name and additional information: the block name associated with this eFuse field and encoding errors (if any). -2. Description of eFuse field. -3. This column has human readable value, read/write protection status, raw value (hexadecimal or binary). - -Read and Write Protection Status -^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - -The ``R/W`` output indicates a protection status of a specific eFuse field/block: - -- ``-/W`` indicates that read protection is set. Value of such eFuse field will always show all-zeroes, even though hardware may use the correct value. In espefuse v2.6 and newer, read-protected eFuse values are displayed as question marks (``??``). On earlier versions, they are displayed as zeroes. - - .. code-block:: none - - BLOCK1 (BLOCK1): - = ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? -/W - -- ``R/-`` indicates that write protection is set. No further bits can be set. -- ``-/-`` means both read and write protection are set. - -Some eFuses have no protection at all, and some eFuses have only one read or write protection. There is no mark in the summary to expose it. - -Display Efuse Summary -^^^^^^^^^^^^^^^^^^^^^ - -The eFuse summary may vary from version to version of this tool and differ for different chips. Below is the summary for the {IDF_TARGET_NAME} chip. - -For details on the meaning of each eFuse value, refer to the `Technical Reference Manual `__. - -.. include:: inc/summary_{IDF_TARGET_NAME}.rst - -Json Format Summary -------------------- - -The json representation of eFuses for the ESP32 chip is shown below. - -.. code-block:: none - - > espefuse.py summary --format json - - { - "ABS_DONE_0": { - "bit_len": 1, - "block": 0, - "category": "security", - "description": "Secure boot V1 is enabled for bootloader image", - "efuse_type": "bool", - "name": "ABS_DONE_0", - "pos": 4, - "readable": true, - "value": false, - "word": 6, - "writeable": true - }, - "BLOCK1": { - "bit_len": 256, - "block": 1, - "category": "security", - "description": "Flash encryption key", - "efuse_type": "bytes:32", - "name": "BLOCK1", - "pos": 0, - "readable": true, - "value": "00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00", - "word": 0, - "writeable": true - }, - ... - "CODING_SCHEME": { - "bit_len": 2, - "block": 0, - "category": "efuse", - "description": "Efuse variable block length scheme", - "efuse_type": "uint:2", - "name": "CODING_SCHEME", - "pos": 0, - "readable": true, - "value": "NONE (BLK1-3 len=256 bits)", - "word": 6, - "writeable": true - }, - .... - } - -Save Json Format Summary To File --------------------------------- - -.. code-block:: none - - > espefuse.py summary --format json --file efuses.json - - Connecting.......... - Detecting chip type... Unsupported detection protocol, switching and trying again... - Connecting.... - Detecting chip type... ESP32 - - === Run "summary" command === - Saving efuse values to efuses.json diff --git a/docs/en/espsecure/index.rst b/docs/en/espsecure/index.rst deleted file mode 100644 index 9b5b63f88..000000000 --- a/docs/en/espsecure/index.rst +++ /dev/null @@ -1,78 +0,0 @@ -.. _espsecure: - -espsecure.py -============ - -``espsecure.py`` is a tool for manipulating data that relates to the secure boot and flash encryption features of ESP32 and later Espressif chips. - -For more details, see the ESP-IDF documentation which explains this tool and how to use it to enable the relevant features: - -* `Secure Boot `_ -* `Flash Encryption `_ - -.. _hsm_signing: - -Remote Signing using an external HSM ------------------------------------- - -An external Hardware Security Module (HSM) can be used for remote signing of images in secure boot v2 scheme. - -You must install ``esptool.py`` package with the ``hsm`` extra using the command, ``pip install 'esptool[hsm]'`` to use this feature. - -``esp_hsm_sign`` provides a PKCS #11 interface to communicate with the external HSM and is integrated in ``espsecure.py``. - -Refer to `Signing using an External HSM `_ to generate a Secure Boot V2 format unsigned firmware image. - -The following command should be used to get an image signed using an external HSM. :: - - python espsecure.py sign_data --version 2 --hsm --hsm-config --output - -The above command first extracts the public key from the HSM, generates a signature for an image using the HSM, and then creates a signature block and appends it to the image to generate a signed image. - -If the public key is not stored in the external HSM, you can specify the ``--pub-key`` argument to supply the public key. :: - - python espsecure.py sign_data --version 2 --hsm --hsm-config --pub-key --output - -Verifying the Signed Image -~~~~~~~~~~~~~~~~~~~~~~~~~~ - -Once the signed image is generated, we can verify it using the following command: :: - - python espsecure.py verify_signature --version 2 --hsm --hsm-config - -If the public key is not stored in the external HSM, you can specify the ``--keyfile`` argument to supply the public key. :: - - python espsecure.py verify_signature --version 2 --keyfile - - -HSM config file -~~~~~~~~~~~~~~~ - -An HSM config file is required with the fields (``pkcs11_lib``, ``credentials``, ``slot``, ``label``, ``label_pubkey``) -populated corresponding to the HSM used. - -Below is a sample HSM config file (``hsm_config.ini``) for using `SoftHSMv2 `_ as an external HSM: :: - - # hsm_config.ini - - # Config file for the external Hardware Security Module - # to be used to generate signature. - - [hsm_config] - - # PKCS11 shared object/library module of the HSM vendor - pkcs11_lib = /usr/local/lib/softhsm/libsofthsm2.so - - # HSM login credentials - credentials = 1234 - - # Slot number to be used - slot = 1108821954 - - # Label of the object used to store the private key - label = Private Key for Digital Signature - - # Label of the object used to store corresponding public key - # label_pubkey is the same as label if the label for public key - # is not explicitly specified while key-pair generation. - label_pubkey = Public Key for Digital Signature diff --git a/docs/en/esptool/advanced-commands.rst b/docs/en/esptool/advanced-commands.rst deleted file mode 100644 index a5dd1562e..000000000 --- a/docs/en/esptool/advanced-commands.rst +++ /dev/null @@ -1,160 +0,0 @@ -{IDF_TARGET_BOOTLOADER_OFFSET:default="0x0", esp8266="0x0", esp32="0x1000", esp32s2="0x1000", esp32s3="0x0", esp32c3="0x0"} - -.. _advanced-commands: - -Advanced Commands -================= - -The ``write_flash``, ``read_flash``, ``erase_flash``, ``erase_region``, ``read_mac``, ``flash_id``, ``elf2image``, ``image_info`` and ``merge_bin`` commands are all documented in the :ref:`commands` section. - -The following less common commands are for more advanced users. - -.. _verify-flash: - -Verify Flash Data: verify_flash -------------------------------- - -The ``verify_flash`` command allows you to verify that data in flash matches a local file. - -The ``write_flash`` command always verifies the MD5 hash of data which is written to flash, so additional verification is not usually needed. However, if you wish to perform a byte-by-byte verification of the flash contents (and optionally print the differences to the console) then you can do so with this command: - -:: - - esptool.py verify_flash --diff yes 0x40000 my_app.elf-0x40000.bin - - -The ``--diff yes`` option specifies that if the files are different, the details should be printed to the console. - -.. note:: - - .. list:: - - * If verifying a default boot image (offset {IDF_TARGET_BOOTLOADER_OFFSET} for {IDF_TARGET_NAME}) then any ``--flash_mode``, ``--flash_size`` and ``--flash_freq`` arguments which were passed to `write_flash` must also be passed to ``verify_flash``. Otherwise, ``verify_flash`` will detect mismatches in the header of the image file. - * Another way to compare flash contents is to use the ``read_flash`` command, and then use binary diffing tools on the host. - -.. _dump-mem: - -Dump a Memory Region to File: dump_mem --------------------------------------- - -The ``dump_mem`` command will dump a region from the chip's memory space to a file. For example, to dump the ROM (64 kB) from an ESP8266: - -:: - - esptool.py dump_mem 0x40000000 65536 iram0.bin - -.. _load-ram: - -Load a Binary to RAM: load_ram ------------------------------- - -The ``load_ram`` command allows the loading of an executable binary image (created with the ``elf2image`` or ``make_image`` commands) directly into RAM, and then immediately executes the program contained within it. - -:: - - esptool.py --no-stub load_ram ./test/images/helloworld-esp8266.bin - -.. note:: - - * The binary image must only contain IRAM- and DRAM-resident segments. Any SPI flash mapped segments will not load correctly and the image will probably crash. The ``image_info`` command can be used to check the binary image contents. - * Because the software loader is resident in IRAM and DRAM, this limits the region where a new program may be loaded. An error will be printed if the new program overlaps with the software loader in RAM. Older esptool versions may hang. Pass ``esptool.py --no-stub`` to avoid this problem. - * Due to a limitation in the ROM loader, when using ``--no-stub`` any very early serial output from a program may be lost if the program resets or reconfigures the UART. To avoid this problem, a program can be compiled with ``ets_delay_us(1)`` as the very first statement after the entry point. - -.. _read-mem-write-mem: - -Read or Write RAM: read_mem / write_mem ---------------------------------------- - -The ``read_mem`` & ``write_mem`` commands allow reading and writing single words (4 bytes) of RAM. This can be used to "peek" and "poke" at registers. - -:: - - esptool.py write_mem 0x400C0000 0xabad1dea - -:: - - esptool.py read_mem 0x400C0000 - -.. _read-flash-status: - -Read Flash Chip Registers: read_flash_status --------------------------------------------- - -This command is intended for use when debugging hardware flash chip-related problems. It allows sending a ``RDSR``, ``RDSR2`` and/or ``RDSR3`` commands to the flash chip to read the status register contents. This can be used to check write protection status, for example: - -:: - - esptool.py read_flash_status --bytes 2 - -The ``--bytes`` argument determines how many status register bytes are read. - -* ``--bytes 1`` sends the most common ``RDSR`` command (05h) and returns a single byte of status. -* ``--bytes 2`` sends both ``RDSR`` (05h) and ``RDSR2`` (35h), reads one byte of status from each, and returns a two byte status. -* ``--bytes 3`` sends ``RDSR`` (05h), ``RDSR2`` (35h), and ``RDSR3`` (15h), reads one byte of status from each, and returns a 3 byte status. - -.. note:: - - Not all flash chips support all of these comands. Consult the specific flash chip datasheet for details. - -.. _write-flash-status: - -Write Flash Chip Registers: write_flash_status ------------------------------------------------ - -This command is intended for use when debugging hardware flash chip-related problems. It allows sending ``WRSR``, ``WRSR2`` and/or ``WRSR3`` commands to the flash chip to write the status register contents. This can be used to clear write protection bits, for example: - -:: - - esptool.py write_flash_status --bytes 2 --non-volatile 0 - -The ``--bytes`` option is similar to the corresponding option for ``read_flash_status`` and causes a mix of ``WRSR`` (01h), ``WRSR2`` (31h), and ``WRSR3`` (11h) commands to be sent to the chip. If ``--bytes 2`` is used then ``WRSR`` is sent first with a 16-bit argument and then with an 8-bit argument, as different flash chips use this command differently. -Otherwise, each command is accompanied by 8-bits of the new status register value. - -A second option ``--non-volatile`` can be used in order to send a ``WREN`` (06h) command before writing the status. This may allow non-volatile status register bits to be set or cleared. If the ``--non-volatile`` option is not supplied, a ``WEVSR`` (50h) command is sent instead of ``WREN``. - -.. note:: - - Consult the specific flash chip datasheet for details about which commands are recognised by a particular chip. - -.. warning:: - - Setting status bits (particularly non-volatile ones) can have permanent side effects for some flash chips, so check carefully before using this command to set any bits! - -.. only:: esp8266 - - .. _chip-id: - - Read the Chip ID: chip_id - ------------------------- - - The ``chip_id`` command allows you to read a 4 byte ID which forms part of the MAC address. It is usually better to use ``read_mac`` to identify a chip. - - On {IDF_TARGET_NAME}, output is the same as the ``system_get_chip_id()`` SDK function. The chip ID is four bytes long, the lower three bytes are the final bytes of the MAC address. The upper byte is zero. - - :: - - esptool.py chip_id - - .. _make-image: - - Assemble a Firmware Image: make_image - ------------------------------------- - - ``make_image`` allows you to manually assemble a firmware image from binary segments (such as those extracted from objcopy). For example: - - :: - - esptool.py --chip esp8266 make_image -f app.text.bin -a 0x40100000 -f app.data.bin -a 0x3ffe8000 -f app.rodata.bin -a 0x3ffe8c00 app.flash.bin - - This command does not require a serial connection. - - .. note:: - - In general, it is better to create an ELF image (including any binary data as part of the ELF, by using objcopy or other tools) and then use ``elf2image`` to generate the ``.bin`` file. - - .. _run: - - Boot Application Code: run - -------------------------- - - The ``run`` command immediately exits the bootloader and attempts to boot the normal application code. diff --git a/docs/en/esptool/advanced-options.rst b/docs/en/esptool/advanced-options.rst deleted file mode 100644 index 8d8b8e483..000000000 --- a/docs/en/esptool/advanced-options.rst +++ /dev/null @@ -1,106 +0,0 @@ -.. _advanced-options: - -Advanced Options -================ - -The following advanced configuration options can be used for all esptool commands (they are placed before the command name on the command line). - -For basic/fundamental configuration options, see the :ref:`options` page. - -Reset Modes ------------ - -By default, esptool tries to hard reset the chip into bootloader mode before it starts and hard resets the chip to run the normal program once it is complete. The ``--before`` and ``--after`` options allow this behavior to be changed: - -Reset Before Operation -^^^^^^^^^^^^^^^^^^^^^^ - -The ``--before`` argument allows you to specify whether the chip needs resetting into bootloader mode before esptool talks to it. - -.. list:: - - * ``--before default_reset`` is the default, which uses DTR & RTS serial control lines (see :ref:`entering-the-bootloader`) to try to reset the chip into bootloader mode. - * ``--before no_reset`` will skip DTR/RTS control signal assignments and just start sending a serial synchronisation command to the chip. This is useful if your chip doesn't have DTR/RTS, or for some serial interfaces (like Arduino board onboard serial) which behave differently when DTR/RTS are toggled. - * ``--before no_reset_no_sync`` will skip DTR/RTS control signal assignments and skip also the serial synchronization command. This is useful if your chip is already running the :ref:`stub bootloader ` and you want to avoid resetting the chip and uploading the stub again. - :esp32c3 or esp32s3: * ``--before usb_reset`` will use custom reset sequence for USB-JTAG-Serial (used for example for ESP chips connected through the USB-JTAG-Serial peripheral). Usually, this option doesn't have to be used directly. Esptool should be able to detect connection through USB-JTAG-Serial. - -Reset After Operation -^^^^^^^^^^^^^^^^^^^^^ - -The ``--after`` argument allows you to specify whether the chip should be reset after the esptool operation completes: - -.. list:: - - * ``--after hard_reset`` is the default. The DTR serial control line is used to reset the chip into a normal boot sequence. - :esp8266:* ``--after soft_reset`` This runs the user firmware, but any subsequent reset will return to the serial bootloader. This was the reset behaviour in esptool v1.x. - * ``--after no_reset`` leaves the chip in the serial bootloader, no reset is performed. - * ``--after no_reset_stub`` leaves the chip in the stub bootloader, no reset is performed. - -.. _disable_stub: - -Disabling the Stub Loader -------------------------- - -The ``--no-stub`` option disables uploading of a software "stub loader" that manages flash operations, and only talks directly to the loader in ROM. - -Passing ``--no-stub`` will disable certain options, as not all options are implemented in every chip's ROM loader. - -.. only:: esp32 - - Overriding SPI Flash Connections - -------------------------------- - - The optional ``--spi-connection`` argument overrides the SPI flash connection configuration on ESP32. This means that the SPI flash can be connected to other pins, or esptool can be used to communicate with a different SPI flash chip to the default. - - Supply the ``--spi-connection`` argument after the ``esptool.py`` command, ie ``esptool.py flash_id --spi-connection HSPI``. - - Default Behavior - ^^^^^^^^^^^^^^^^ - - If the ``--spi-connection`` argument is not provided, the SPI flash is configured to use :ref:`pin numbers set in efuse `. These are the same SPI flash pins that are used during a normal boot. - - The only exception to this is if the ``--no-stub`` option is also provided. In this case, efuse values are ignored and ``--spi-connection`` will default to ``--spi-connection SPI`` unless set to a different value. - - SPI Mode - ^^^^^^^^ - - ``--spi-connection SPI`` uses the default SPI pins: - - * CLK = GPIO 6 - * Q = GPIO 7 - * D = GPIO 8 - * HD = GPIO 9 - * CS = GPIO 11 - - During normal booting, this configuration is selected if all SPI pin efuses are unset and GPIO1 (U0TXD) is not pulled low (default). - - This is the normal pin configuration for ESP32 chips that do not contain embedded flash. - - HSPI Mode - ^^^^^^^^^ - - ``--spi-connection HSPI`` uses the HSPI peripheral instead of the SPI peripheral for SPI flash communications, via the following HSPI pins: - - * CLK = GPIO 14 - * Q = GPIO 12 - * D = GPIO 13 - * HD = GPIO 4 - * CS = GPIO 15 - - During normal booting, this configuration is selected if all SPI pin efuses are unset and GPIO1 (U0TXD) is pulled low on reset. - - Custom SPI Pin Configuration - ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - - ``--spi-connection ,,,,`` allows a custom list of pins to be configured for the SPI flash connection. This can be used to emulate the flash configuration equivalent to a particular set of SPI pin efuses being burned. The values supplied are GPIO numbers. - - For example, ``--spi-connection 6,17,8,11,16`` sets an identical configuration to the factory efuse configuration for ESP32s with embedded flash. - - When setting a custom pin configuration, the SPI peripheral (not HSPI) will be used unless the ``CLK`` pin value is set to 14 (HSPI CLK), in which case the HSPI peripheral will be used. - -Specifying Arguments via File ------------------------------ - -Anywhere on the esptool command line, you can specify a file name as ``@filename.txt`` to read one or more arguments from text file ``filename.txt``. Arguments can be separated by newlines or spaces, quotes can be used to enclose arguments that span multiple words. Arguments read from the text file are expanded exactly as if they had appeared in that order on the esptool command line. - -An example of this is available in the :ref:`merge_bin ` command description. diff --git a/docs/en/esptool/basic-commands.rst b/docs/en/esptool/basic-commands.rst deleted file mode 100644 index 8246d73ff..000000000 --- a/docs/en/esptool/basic-commands.rst +++ /dev/null @@ -1,272 +0,0 @@ -.. _commands: - -Basic Commands -============== - -Write Binary Data to Flash: write_flash ----------------------------------------- - -Binary data can be written to the ESP's flash chip via the serial ``write_flash`` command: - -:: - - esptool.py --port COM4 write_flash 0x1000 my_app-0x01000.bin - -Multiple flash addresses and file names can be given on the same command line: - -:: - - esptool.py --port COM4 write_flash 0x00000 my_app.elf-0x00000.bin 0x40000 my_app.elf-0x40000.bin - -The ``--chip`` argument is optional when writing to flash, esptool will detect the type of chip when it connects to the serial port. - -The ``--port`` argument is documented under :ref:`serial-port`. - -.. only:: esp8266 - - The next arguments to ``write_flash`` are one or more pairs of offset (address) and file name. When generating ESP8266 "version 1" images, the file names created by ``elf2image`` include the flash offsets as part of the file name. - For other types of images, consult your SDK documentation to determine the files to flash at which offsets. - -.. only:: not esp8266 - - The next arguments to ``write_flash`` are one or more pairs of offset (address) and file name. Consult your SDK documentation to determine the files to flash at which offsets. - -Numeric values passed to write_flash (and other commands) can be specified either in hex (ie 0x1000), or in decimal (ie 4096). - -See the :ref:`troubleshooting` section if the ``write_flash`` command is failing, or the flashed module fails to boot. - -Setting Flash Mode and Size -^^^^^^^^^^^^^^^^^^^^^^^^^^^ - -You may also need to specify arguments for :ref:`flash mode and flash size `, if you wish to override the defaults. For example: - -:: - - esptool.py --port /dev/ttyUSB0 write_flash --flash_mode qio --flash_size 32m 0x0 bootloader.bin 0x1000 my_app.bin - -Since esptool v2.0, these options are not often needed as the default is to keep the flash mode and size from the ``.bin`` image file. See the :ref:`flash-modes` section for more details. - -Compression -^^^^^^^^^^^ - -By default, the serial transfer data is compressed for better performance. The ``-u/--no-compress`` option disables this behaviour. - -Erasing Flash Before Write -^^^^^^^^^^^^^^^^^^^^^^^^^^ - -To successfully write data into flash, all 4096-byte memory sectors (the smallest erasable unit) affected by the operation have to be erased first. As a result, when the flashing offset address or the data are not 4096-byte aligned, more memory is erased than actually needed. -Esptool will display information about which flash memory sectors will be erased. - -Use the ``-e/--erase-all`` option to erase all flash sectors (not just the write areas) before programming. - -.. only:: not esp8266 - - Bootloader Protection - ^^^^^^^^^^^^^^^^^^^^^ - - Flashing into the bootloader region (``0x0`` -> ``0x8000``) is disabled by default if active `Secure Boot `_ is detected. - This is a safety measure to prevent accidentally overwriting the secure bootloader, which **can ultimately lead to bricking the device**. - - This behavior can be overridden with the ``--force`` option. **Use this only at your own risk and only if you know what you are doing!** - - - Encrypted Flash Protection - ^^^^^^^^^^^^^^^^^^^^^^^^^^ - - .. only:: esp32 - - Overwriting the encrypted firmware (bootloader, application, etc.) without the ``--encrypt`` option is disabled, if `Flash Encryption `_ is enabled and Encrypted Download being disabled (efuse bit ``EFUSE_DISABLE_DL_ENCRYPT`` is set). - - .. only:: not esp32 - - Overwriting the encrypted firmware (bootloader, application, etc.) without the ``--encrypt`` option is disabled, if: - - * `Flash Encryption `_ and Secure Download Mode are enabled or - * `Flash Encryption `_ is enabled but Encrypted Download is disabled (efuse bit ``EFUSE_DIS_DOWNLOAD_MANUAL_ENCRYPT`` is set). - - This is a safety measure to prevent accidentally overwriting the encrypted firmware with a plaintext binary, which **can ultimately lead to bricking the device**. - - This behavior can be overridden with the ``--force`` option. **Use this option provided that the flash encryption key is generated external to the device and you could perform the encryption on the host machine.** - - Flashing an Incompatible Image - ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - - ``esptool.py`` checks every binary before flashing. If a valid firmware image is detected, the ``Chip ID`` and ``Minimum chip revision`` fields in its :ref:`header ` are compared against the actually connected chip. - If the image turns out to be incompatible with the chip in use or requires a newer chip revision, flashing is stopped. - - This behavior can be overridden with the ``--force`` option. - -Read Flash Contents: read_flash --------------------------------- - -The read_flash command allows reading back the contents of flash. The arguments to the command are an address, a size, and a filename to dump the output to. For example, to read a full 2MB of attached flash: - -:: - - esptool.py -p PORT -b 460800 read_flash 0 0x200000 flash_contents.bin - -.. note:: - - If ``write_flash`` updated the boot image's :ref:`flash mode and flash size ` during flashing then these bytes may be different when read back. - -.. _erase_flash: - -Erase Flash: erase_flash & erase_region ---------------------------------------- - -To erase the entire flash chip (all data replaced with 0xFF bytes): - -:: - - esptool.py erase_flash - -To erase a region of the flash, starting at address 0x20000 with length 0x4000 bytes (16KB): - -:: - - esptool.py erase_region 0x20000 0x4000 - -The address and length must both be multiples of the SPI flash erase sector size. This is 0x1000 (4096) bytes for supported flash chips. - -.. only:: not esp8266 - - Flash Protection - ^^^^^^^^^^^^^^^^ - - Erasing the flash chip is disabled by default if either active `Secure Boot `_ or - `Flash Encryption `_ is detected. - This is a safety measure to prevent accidentally deleting the secure bootloader or encrypted data, which **can ultimately lead to bricking the device**. - - This behavior can be overridden with the ``--force`` option. **Use this only at your own risk and only if you know what you are doing!** - -Read Built-in MAC Address: read_mac ------------------------------------- - -:: - - esptool.py read_mac - -.. _read-spi-flash-id: - -Read SPI Flash ID: flash_id ---------------------------- - -:: - - esptool.py flash_id - -Example output: - -:: - - Manufacturer: e0 - Device: 4016 - Detected flash size: 4MB - -Refer to `flashrom source code `__ for flash chip manufacturer name and part number. - -.. _elf-2-image: - -Convert ELF to Binary: elf2image --------------------------------- - -The ``elf2image`` command converts an ELF file (from compiler/linker output) into the binary executable images which can be flashed and then booted into: - -:: - - esptool.py --chip {IDF_TARGET_NAME} elf2image my_app.elf - -This command does not require a serial connection. - -``elf2image`` also accepts the `Flash Modes <#flash-modes>`__ arguments ``--flash_freq`` and ``--flash_mode``, which can be used to set the default values in the image header. This is important when generating any image which will be booted directly by the chip. -These values can also be overwritten via the ``write_flash`` command, see the `write_flash command <#write-binary-data-to-flash-write-flash>`__ for details. However, if you want to overwrite these values via the ``write_flash`` command then use the ``--dont-append-digest`` argument of the ``elf2image`` command in order to skip appending a SHA256 digest after the image. The SHA256 digest would be invalidated by rewriting the image header, therefore, it is not allowed. - -By default, ``elf2image`` uses the sections in the ELF file to generate each segment in the binary executable. To use segments (PHDRs) instead, pass the ``--use_segments`` option. - -.. only:: esp8266 - - The default command output for {IDF_TARGET_NAME} is two binary files: ``my_app.elf-0x00000.bin`` and ``my_app.elf-0x40000.bin``. You can alter the firmware file name prefix using the ``--output/-o`` option. - - ``elf2image`` can also produce a "version 2" image file suitable for use with a software bootloader stub such as `rboot `__ or the Espressif bootloader program. You can't flash a "version 2" image without also flashing a suitable bootloader. - - :: - - esptool.py --chip {IDF_TARGET_NAME} elf2image --version=2 -o my_app-ota.bin my_app.elf - -.. only:: not esp8266 - - For {IDF_TARGET_NAME}, elf2image produces a single output binary "image file". By default this has the same name as the .elf file, with a .bin extension. For example: - - :: - - esptool.py --chip {IDF_TARGET_NAME} elf2image my_esp_app.elf - - In the above example, the output image file would be called ``my_esp_app.bin``. - -.. _image-info: - -Output .bin Image Details: image_info -------------------------------------- - -The ``image_info`` command outputs some information (load addresses, sizes, etc) about a ``.bin`` file created by ``elf2image``. - -To view more information about the image, such as set flash size, frequency and mode, or extended header information, use the ``--version 2`` option. This extended output will become the default in a future major release. - -This information corresponds to the headers described in :ref:`image-format`. - -:: - - esptool.py image_info --version 2 my_esp_app.bin - -.. only:: not esp8266 - - If a valid `ESP-IDF application header `__ is detected in the image, specific fields describing the application are also displayed. - -.. _merge-bin: - -Merge Binaries for Flashing: merge_bin --------------------------------------- - -The ``merge_bin`` command will merge multiple binary files (of any kind) into a single file that can be flashed to a device later. Any gaps between the input files are padded with 0xFF bytes (same as unwritten flash contents). - -For example: - -:: - - esptool.py --chip {IDF_TARGET_NAME} merge_bin -o merged-flash.bin --flash_mode dio --flash_size 4MB 0x1000 bootloader.bin 0x8000 partition-table.bin 0x10000 app.bin - -Will create a file ``merged-flash.bin`` with the contents of the other 3 files. This file can be later be written to flash with ``esptool.py write_flash 0x0 merged-flash.bin``. - -.. note: - - Because gaps between the input files are padded with 0xFF bytes, when the merged binary is written then any flash sectors between the individual files will be erased. To avoid this, write the files individually. - -**Options:** - -* The ``merge_bin`` command supports the same ``--flash_mode``, ``--flash_size`` and ``--flash_freq`` options as the ``write_flash`` command to override the bootloader flash header (see above for details). - These options are applied to the output file contents in the same way as when writing to flash. Make sure to pass the ``--chip`` parameter if using these options, as the supported values and the bootloader offset both depend on the chip. -* The ``--target-offset 0xNNN`` option will create a merged binary that should be flashed at the specified offset, instead of at offset 0x0. -* The ``--fill-flash-size SIZE`` option will pad the merged binary with 0xFF bytes to the full flash specified size, for example ``--fill-flash-size 4MB`` will create a 4MB binary file. -* It is possible to append options from a text file with ``@filename``. As an example, this can be conveniently used with the ESP-IDF build system, which produces a ``flash_args`` file in the build directory of a project: - -.. code:: sh - - cd build # The build directory of an ESP-IDF project - esptool.py --chip {IDF_TARGET_NAME} merge_bin -o merged-flash.bin @flash_args - -Advanced Commands ------------------ - -The following commands are less commonly used, or only of interest to advanced users. They are documented in the :ref:`advanced-commands` section: - -.. list:: - - * :ref:`verify-flash` - * :ref:`dump-mem` - * :ref:`load-ram` - * :ref:`read-mem-write-mem` - * :ref:`read-flash-status` - * :ref:`write-flash-status` - :esp8266: * :ref:`chip-id` - :esp8266: * :ref:`make-image` - :esp8266: * :ref:`run` diff --git a/docs/en/esptool/basic-options.rst b/docs/en/esptool/basic-options.rst deleted file mode 100644 index 5d9bb4c46..000000000 --- a/docs/en/esptool/basic-options.rst +++ /dev/null @@ -1,56 +0,0 @@ -.. _options: - -Basic Options -============= - -These are the basic/fundamental esptool options needed to define the communication with an ESP target. For advanced configuration options, see the :ref:`advanced-options` page. - -.. _chip-type: - -Chip Type ---------- - -* The target chip type can be selected using the ``--chip``/ ``-c`` option, e.g. ``esptool.py --chip {IDF_TARGET_PATH_NAME} ``. -* A default chip type can be specified by setting the ``ESPTOOL_CHIP`` environment variable. -* If no ``-c`` option or ``ESPTOOL_CHIP`` value is specified, ``esptool.py`` automatically detects the chip type when connecting. -* Binary image generation commands, such as :ref:`elf2image ` or :ref:`merge_bin `, require the chip type to be specified. - -.. _serial-port: - -Serial Port ------------ - -* The serial port is selected using the ``-p`` option, like ``-p /dev/ttyUSB0`` (Linux and macOS) or ``-p COM1`` (Windows). -* A default serial port can be specified by setting the ``ESPTOOL_PORT`` environment variable. -* If no ``-p`` option or ``ESPTOOL_PORT`` value is specified, ``esptool.py`` will enumerate all connected serial ports and try each one until it finds an Espressif device connected. - -.. note:: - - Windows and macOS may require drivers to be installed for a particular USB/serial adapter, before a serial port is available. Consult the documentation for your particular device. - On macOS, you can also consult `System Information `__'s list of USB devices to identify the manufacturer or device ID when the adapter is plugged in. - On Windows, you can use `Windows Update or Device Manager `__ to find a driver. - -If using Cygwin or WSL on Windows, you have to convert the Windows-style name into a Unix-style path (``COM1`` -> ``/dev/ttyS0``, and so on). (This is not necessary if using ESP-IDF with the supplied Windows MSYS2 environment, -this environment uses a native Windows Python which accepts COM ports as-is.) - -In Linux, the current user may not have access to serial ports and a "Permission Denied" or "Port doesn't exist" errors may appear. -On most Linux distributions, the solution is to add the user to the ``dialout`` group (check e.g. ``ls -l /dev/ttyUSB0`` to find the group) with a command like ``sudo usermod -a -G dialout $USER``. -You can call ``su - $USER`` to enable read and write permissions for the serial port without having to log out and back in again. -Check your Linux distribution's documentation for more information. - -Baud Rate ---------- - -The default esptool baud rate is 115200bps. Different rates may be set using ``-b 921600`` (or another baud rate of your choice). A default baud rate can also be specified using the ``ESPTOOL_BAUD`` environment variable. This can speed up ``write_flash`` and ``read_flash`` operations. - -The baud rate is limited to 115200 when esptool establishes the initial connection, higher speeds are only used for data transfers. - -Most hardware configurations will work with ``-b 230400``, some with ``-b 460800``, ``-b 921600`` and/or ``-b 1500000`` or higher. - -.. only:: esp8266 - - If you have connectivity problems then you can also set baud rates below 115200. You can also choose 74880, which is the :ref:`usual baud rate used by the ESP8266 ` to output :ref:`boot-log-esp8266` information. - -.. only:: not esp8266 - - If you have connectivity problems then you can also set baud rates below 115200. diff --git a/docs/en/esptool/configuration-file.rst b/docs/en/esptool/configuration-file.rst deleted file mode 100644 index c538c608a..000000000 --- a/docs/en/esptool/configuration-file.rst +++ /dev/null @@ -1,148 +0,0 @@ -.. _config: - -Configuration File -================== - -``esptool.py`` relies on serial communication when connecting to, reading from, or writing to an ESP chip. -To ensure this two-way serial connection works properly, ``esptool.py`` is tuned with several pre-defined -variables describing the timings and other nuances when sending or receiving data. -These variables have been finely tuned to work in absolute majority of environments. -However, it is impossible to cover all of the existing combinations of hardware, OS, and drivers. -Sometimes little tweaking is necessary to cover even the most extreme edge cases. - -These options can be specified in a configuration file. This makes it easy to run -``esptool.py`` with custom settings, and also allows for specification of options -that are otherwise not available to a user without having to tamper with the source code. - -File Location -------------- - -The default name for a configuration file is ``esptool.cfg``. First, the same -directory ``esptool.py`` is being run in is inspected. - -If a configuration file is not found here, the current user's OS configuration directory is inspected next: - - - Linux: ``/home//.config/esptool/`` - - MacOS ``/Users//.config/esptool/`` - - Windows: ``c:\Users\\AppData\Local\esptool\`` - -If a configuration file is still not found, the last inspected location is the home directory: - - - Linux: ``/home//`` - - MacOS ``/Users//`` - - Windows: ``c:\Users\\`` - -On Windows, the home directory can be set with the ``HOME`` or ``USERPROFILE`` environment variables. -Therefore, the Windows configuration directory location also depends on these. - -A different location for the configuration file can be specified with the ``ESPTOOL_CFGFILE`` -environment variable, e.g. ``ESPTOOL_CFGFILE = ~/custom_config.cfg``. -This overrides the search priorities described above. - -``esptool.py`` will read settings from other usual configuration files if no other -configuration file is used. It will automatically read from ``setup.cfg`` or -``tox.ini`` if they exist. - -As a result, the order of priority of inspected configuration files is: - -#. a file specified with the ``ESPTOOL_CFGFILE`` environment variable -#. ``esptool.cfg`` -#. ``setup.cfg`` -#. ``tox.ini`` - -Syntax ------- - -An ``esptool.py`` configuration file is in .ini file format: it must be -introduced by an ``[esptool]`` header to be recognized as valid. -This section then contains ``name = value`` entries. -Lines beginning with ``#`` or ``;`` are ignored as comments. - -Delay and timeout options accept float values, -other numeric options are integers. Strings don't need quotes. - -Sample configuration file: - -.. code-block:: text - - # esptool.cfg file to configure internal settings of esptool - [esptool] - chip_erase_timeout = 140 - serial_write_timeout = 8.5 - connect_attempts = 7 - write_block_attempts = 2 - reset_delay = 0.75 - # Overriding the default reset sequence to work in an abnormal environment - custom_reset_sequence = D0|R1|W0.1|D1|R0|W0.5|D0 - -Options -------- - -Complete list configurable options: - -+------------------------------+-----------------------------------------------------------+----------+ -| Option | Description | Default | -+==============================+===========================================================+==========+ -| timeout | Timeout for most flash operations | 3 s | -+------------------------------+-----------------------------------------------------------+----------+ -| chip_erase_timeout | Timeout for a full chip erase | 120 s | -+------------------------------+-----------------------------------------------------------+----------+ -| max_timeout | The longest any command can run | 240 s | -+------------------------------+-----------------------------------------------------------+----------+ -| sync_timeout | Timeout for syncing with the bootloader | 0.1 s | -+------------------------------+-----------------------------------------------------------+----------+ -| md5_timeout_per_mb | Timeout (per megabyte) for calculating md5sum | 8 s | -+------------------------------+-----------------------------------------------------------+----------+ -| erase_region_timeout_per_mb | Timeout (per megabyte) for erasing a region | 30 s | -+------------------------------+-----------------------------------------------------------+----------+ -| erase_write_timeout_per_mb | Timeout (per megabyte) for erasing and writing data | 40 s | -+------------------------------+-----------------------------------------------------------+----------+ -| mem_end_rom_timeout | Short timeout for ESP_MEM_END | 0.2 s | -+------------------------------+-----------------------------------------------------------+----------+ -| serial_write_timeout | Timeout for serial port write | 10 s | -+------------------------------+-----------------------------------------------------------+----------+ -| connect_attempts | Default number of times to try connection | 7 | -+------------------------------+-----------------------------------------------------------+----------+ -| write_block_attempts | Number of times to try writing a data block | 3 | -+------------------------------+-----------------------------------------------------------+----------+ -| reset_delay | Time to wait before the boot pin is released after reset | 0.05 s | -+------------------------------+-----------------------------------------------------------+----------+ -| custom_reset_sequence | Custom reset sequence for resetting into the bootloader | | -+------------------------------+-----------------------------------------------------------+----------+ - -Custom Reset Sequence ---------------------- - -The ``custom_reset_sequence`` configuration option allows you to define a reset sequence which will get -used when an :ref:`automatic reset into the serial bootloader ` is performed. - -The sequence is defined with a string in the following format: - -- Consists of individual commands divided by ``|`` (e.g. ``R0|D1|W0.5``). -- Commands (e.g. ``R0``) are defined by a code (``R``) and an argument (``0``). - -+------+-----------------------------------------------------------+-----------------+ -| Code | Action | Argument | -+======+===========================================================+=================+ -| D | Set DTR control line | ``1``/``0`` | -+------+-----------------------------------------------------------+-----------------+ -| R | Set RTS control line | ``1``/``0`` | -+------+-----------------------------------------------------------+-----------------+ -| U | Set DTR and RTS control lines at the same time | ``0,0``/``0,1`` | -| | (Unix-like systems only) | ``1,0``/``1,1`` | -+------+-----------------------------------------------------------+-----------------+ -| W | Wait for ``N`` seconds (where ``N`` is a float) | ``N`` | -+------+-----------------------------------------------------------+-----------------+ - - -For example: ``D0|R1|W0.1|D1|R0|W0.5|D0`` represents the following classic reset sequence: - -.. code-block:: python - - _setDTR(False) # IO0=HIGH - _setRTS(True) # EN=LOW, chip in reset - time.sleep(0.1) - _setDTR(True) # IO0=LOW - _setRTS(False) # EN=HIGH, chip out of reset - time.sleep(0.05) - _setDTR(False) # IO0=HIGH, done diff --git a/docs/en/esptool/entering-bootloader.rst b/docs/en/esptool/entering-bootloader.rst deleted file mode 100644 index 4e5a95837..000000000 --- a/docs/en/esptool/entering-bootloader.rst +++ /dev/null @@ -1,25 +0,0 @@ -.. _entering-the-bootloader: - -Entering the Bootloader -======================= - -Espressif chips have to be reset in a certain way in order to launch the serial bootloader, only then can ``esptool.py`` communicate with the ESP chip. - -On some development boards (including NodeMCU, WeMOS, HUZZAH Feather, Core Board, ESP32-WROVER-KIT), esptool can :ref:`automatically trigger a reset into the serial bootloader ` - in which case you don't need to read this section. - -For everyone else, three things must happen to enter the serial bootloader (firmware download mode) - a reset, required pins set correctly, and a correct strapping pin pulled low. For more information, see the detailed :ref:`Boot Mode Selection` guide. - -Boot Mode ---------- - -Espressif chips choose the boot mode each time they reset. A reset event can happen in one of several ways: - -.. list:: - - * Power applied to chip. - :esp8266: * The nRESET pin was low and is pulled high. - * The CH_PD/EN pin ("enable") pin was low and is pulled high. - -.. only:: esp8266 - - On {IDF_TARGET_NAME}, both the nRESET and CH_PD pins must be pulled high for the chip to start operating. diff --git a/docs/en/esptool/flash-modes.rst b/docs/en/esptool/flash-modes.rst deleted file mode 100644 index 675673d8f..000000000 --- a/docs/en/esptool/flash-modes.rst +++ /dev/null @@ -1,113 +0,0 @@ -{IDF_TARGET_BOOTLOADER_OFFSET:default="0x0", esp8266="0x0", esp32="0x1000", esp32s2="0x1000", esp32s3="0x0", esp32c3="0x0"} - -.. _flash-modes: - -Flash Modes -=========== - -``write_flash`` and some other commands accept command line arguments to set bootloader flash mode, flash size and flash clock frequency. The chip needs correct mode, frequency and size settings in order to run correctly - although there is some flexibility. -A header at the beginning of a bootable image contains these values. - -To override these values, the options ``--flash_mode``, ``--flash_size`` and/or ``--flash_freq`` must appear after ``write_flash`` on the command line, for example: - -:: - - esptool.py --port /dev/ttyUSB1 write_flash --flash_mode dio --flash_size 4MB 0x0 bootloader.bin - -These options are only consulted when flashing a bootable image to an {IDF_TARGET_NAME} at offset {IDF_TARGET_BOOTLOADER_OFFSET}. These are addresses used by the ROM bootloader to load from flash. When flashing at all other offsets, these arguments are not used. - -Flash Mode (--flash_mode, -fm) -------------------------------- - -These set Quad Flash I/O or Dual Flash I/O modes. Valid values are ``keep``, ``qio``, ``qout``, ``dio``, ``dout``. The default is ``keep``, which keeps whatever value is already in the image file. This parameter can also be specified using the environment variable ``ESPTOOL_FM``. - -.. only:: esp8266 - - Most boards use ``qio`` mode. Some ESP8266 modules, including the ESP-12E modules on some (not all) NodeMCU boards, are dual I/O and the firmware will only boot when flashed with ``--flash_mode dio``. - -.. only:: not esp8266 - - Most {IDF_TARGET_NAME} modules use ``qio``, but are also dual I/O. - -In ``qio`` mode, two additional GPIOs (9 and 10) are used for SPI flash communications. If flash mode is set to ``dio`` then these pins are available for other purposes. - -For a full explanation of these modes, see the :ref:`SPI Flash Modes page `. - -Flash Frequency (--flash_freq, -ff) ------------------------------------- - -Clock frequency for SPI flash interactions. Valid values are ``keep``, ``40m``, ``26m``, ``20m``, ``80m`` (MHz). The default is ``keep``, which keeps whatever value is already in the image file. This parameter can also be specified using the environment variable ``ESPTOOL_FF``. - -The flash chip connected to most chips works with 40MHz clock speeds, but you can try lower values if the device won't boot. The highest 80MHz flash clock speed will give the best performance, but may cause crashing if the flash or board design is not capable of this speed. - -Flash Size (--flash_size, -fs) -------------------------------- - -Size of the SPI flash, given in megabytes. - -.. only:: esp8266 - - Valid values are: ``keep``, ``detect``, ``256KB``, ``512KB``, ``1MB``, ``2MB``, ``4MB``, ``2MB-c1``, ``4MB-c1``, ``8MB``, ``16MB`` - -.. only:: esp32 or esp32c3 - - Valid values are: ``keep``, ``detect``, ``1MB``, ``2MB``, ``4MB``, ``8MB``, ``16MB`` - -.. only:: esp32s2 or esp32s3 - - Valid values are: ``keep``, ``detect``, ``1MB``, ``2MB``, ``4MB``, ``8MB``, ``16MB``, ``32MB``, ``64MB`` - -.. note:: - - Esptool uses power of two units, so in IEC units the size arguments are Mebibytes, although Espressif's technical documentation doesn't use the Mebi- prefix. This is due to compatibility reasons and to keep consistent with flash manufacturers. - -.. only:: esp8266 - - For ESP8266, some :ref:`additional sizes & layouts for OTA "firmware slots" are available `. - -The default ``--flash_size`` parameter is ``keep``. This means that if no ``--flash_size`` argument is passed when flashing a bootloader, the value in the bootloader .bin file header is kept instead of detecting the actual flash size and updating the header. - -To enable automatic flash size detection based on SPI flash ID, add the argument ``esptool.py [...] write_flash [...] -fs detect``. If detection fails, a warning is printed and a default value of of ``4MB`` (4 megabytes) is used. - -If flash size is not successfully detected, you can find the flash size by using the ``flash_id`` command and then looking up the ID from the output (see :ref:`Read SPI flash id `). -Alternatively, read off the silkscreen labelling of the flash chip and search for its datasheet. - -The default ``flash_size`` parameter can also be overridden using the environment variable ``ESPTOOL_FS``. - -.. only:: esp8266 - - The ESP8266 SDK stores WiFi configuration at the "end" of flash, and it finds the end using this size. However there is no downside to specifying a smaller flash size than you really have, as long as you don't need to write an image larger than this size. - - ESP-12, ESP-12E and ESP-12F modules (and boards that use them such as NodeMCU, HUZZAH, etc.) usually have at least 4 megabyte / ``4MB`` (sometimes labelled 32 megabit) flash. - - .. _esp8266-and-flash-size: - - If using OTA, some additional sizes & layouts for OTA "firmware slots" are available. If not using OTA updates then you can ignore these extra sizes: - - +-------------------+-----------------------+-----------------+-----------------+ - | flash_size arg | Number of OTA slots | OTA Slot Size | Non-OTA Space | - +===================+=======================+=================+=================+ - | 256KB | 1 (no OTA) | 256KB | N/A | - +-------------------+-----------------------+-----------------+-----------------+ - | 512KB | 1 (no OTA) | 512KB | N/A | - +-------------------+-----------------------+-----------------+-----------------+ - | 1MB | 2 | 512KB | 0KB | - +-------------------+-----------------------+-----------------+-----------------+ - | 2MB | 2 | 512KB | 1024KB | - +-------------------+-----------------------+-----------------+-----------------+ - | 4MB | 2 | 512KB | 3072KB | - +-------------------+-----------------------+-----------------+-----------------+ - | 2MB-c1 | 2 | 1024KB | 0KB | - +-------------------+-----------------------+-----------------+-----------------+ - | 4MB-c1 | 2 | 1024KB | 2048KB | - +-------------------+-----------------------+-----------------+-----------------+ - | 8MB [^] | 2 | 1024KB | 6144KB | - +-------------------+-----------------------+-----------------+-----------------+ - | 16MB [^] | 2 | 1024KB | 14336KB | - +-------------------+-----------------------+-----------------+-----------------+ - - - [^] Support for 8MB & 16MB flash size is not present in all ESP8266 SDKs. If your SDK doesn't support these flash sizes, use ``--flash_size 4MB``. - -.. only:: not esp8266 - - The ESP-IDF flashes a partition table to the flash at offset 0x8000. All of the partitions in this table must fit inside the configured flash size, otherwise the {IDF_TARGET_NAME} will not work correctly. diff --git a/docs/en/esptool/flasher-stub.rst b/docs/en/esptool/flasher-stub.rst deleted file mode 100644 index c2f179be7..000000000 --- a/docs/en/esptool/flasher-stub.rst +++ /dev/null @@ -1,24 +0,0 @@ -.. _stub: - -Flasher Stub -============ - -``esptool.py`` is a serial flasher utility. It communicates with the ROM bootloader in `Espressif SoCs `_ in order to load user applications or read chip data via serial port. - -The ROM bootloader is burned into the ESP chip during manufacturing and cannot be updated. A new version is issued only when a new chip revision is released. - -``esptool.py`` works around the limitations imposed by a fixed ROM bootloader by implementing a flasher stub (also known as "stub loader" or just "stub"). It is a small application used as a temporary substitute or extension for the ROM. - -When ``esptool.py`` connects to a chip, it first uploads the flasher stub, which basically replaces the original bootloader. All following operations are then handled by the stub. - -Benefits --------- - -The flasher stub behaves the same as the original bootloader, but uses more heavily optimized UART routines. - -The main benefit is improved performance of flashing and some other operations (like reading flash). Additionally, there are a few commands which are only available when using the stub loader (such as :ref:`erase_flash and erase_region `). It also allows to work around any bugs in ROM bootloaders. - -Disabling the Stub Loader -------------------------- - -There might be cases where it is necessary to disable the stub loader (e.g. debugging). To do that, run ``esptool.py`` with the ``--no-stub`` argument. All operations will then be handled by the original ROM bootloader. See the related :ref:`advanced options page `. diff --git a/docs/en/esptool/flashing-firmware.rst b/docs/en/esptool/flashing-firmware.rst deleted file mode 100644 index e99675840..000000000 --- a/docs/en/esptool/flashing-firmware.rst +++ /dev/null @@ -1,103 +0,0 @@ -Flashing Firmware -================= - -Esptool is used under the hood of many development frameworks for Espressif SoCs, such as `ESP-IDF `_, `Arduino `_, or `PlatformIO `_. -After the resulting firmware binary files are compiled, esptool is used to flash these into the device. - -Sometimes there might be a need to comfortably flash a bigger amount of decives with the same binaries or to share flashing instructions with a third party. -It is possible to compile the firmware just once and then repeatedly use esptool (manually or :ref:`in a custom script `) to flash the files. - -Sharing these instructions and below mentioned assets with a third party (for example a manufacturer) should suffice to allow reproducible and quick flashing of your application into an Espressif chip. - -.. note:: - - The following texts are just an example, please see the documentation of the development framework of your choice for precise instructions. - -Prerequisites -------------- - -* Installed esptool, see the :ref:`installation guide ` for instructions. -* All of the compiled binary files in a known location. -* Espressif chip connected to your computer. - -Binary Files Location ---------------------- - -The generated binary files are usually stored in the ``build`` folder of your project. - -For example, when building the `hello-world example project `_ in ESP-IDF, the resulting app binary can be found in ``.../esp-idf/examples/get-started/hello_world/build/hello_world.bin``. -The same applies to the bootloader and the partition table. - -The location of generated binaries depends on the used development framework. If you are unsure of the location, see the generated esptool `command <#command>`__ containing the full paths. - -Command -------- - -Compile and upload your firmware once with your preferred framework. The detailed esptool command will be displayed in the output right before the flashing happens. - -It is also possible to assemble the command manually, please see the :ref:`esptool usage documentation` for more information. - -ESP-IDF -^^^^^^^ - -ESP-IDF outputs the full esptool command used for flashing after the build is finished:: - - Project build complete. To flash, run this command: - python esptool.py -p (PORT) -b 460800 --before default_reset --after hard_reset --chip esp32 write_flash --flash_mode dio --flash_size detect --flash_freq 40m 0x1000 build/bootloader/bootloader.bin 0x8000 build/partition_table/partition-table.bin 0x10000 build/hello_world.bin - or run 'idf.py -p (PORT) flash' - -Arduino -^^^^^^^ - -The full esptool command is hidden from the user by default. To expose it, open the preferences window and check the ``Show verbose output during: upload`` option. A full command will be shown while uploading the sketch. - -PlatformIO -^^^^^^^^^^ - -To do a verbose upload and see the exact esptool invocation, run ``pio run -v -t upload`` in the terminal. In the generated output, there is the full esptool command, e.g.: - -:: - - “.../.platformio/penv/bin/python2.7” “.../.platformio/packages/tool-esptoolpy/esptool.py” --chip esp32 --port “/dev/cu.usbserial001” --baud 921600 --before default_reset --after hard_reset write_flash -z --flash_mode dio --flash_freq 40m --flash_size detect 0x1000 .../.platformio/packages/framework-arduinoespressif32/tools/sdk/bin/bootloader_dio_40m.bin 0x8000 .../project_folder/.pio/build/esp32doit-devkit-v1/partitions.bin 0xe000 .../.platformio/packages/framework-arduinoespressif32/tools/partitions/boot_app0.bin 0x10000 .pio/build/esp32doit-devkit-v1/firmware.bin - - -Flashing --------- - -If you split the output, you’ll find the ``write_flash`` command with a list of paths to binary files and their respective flashing offsets. If necessary, change the paths to the actual file locations. - -Change ``PORT`` to the name of :ref:`actually used serial port ` and run the command. A successful flash looks like this:: - - $ python esptool.py -p /dev/tty.usbserial-0001 -b 460800 --before default_reset --after hard_reset --chip esp32 write_flash --flash_mode dio --flash_size detect --flash_freq 40m 0x1000 build/bootloader/bootloader.bin 0x8000 build/partition_table/partition-table.bin 0x10000 build/hello_world.bin - esptool.py v3.2-dev - Serial port /dev/tty.usbserial-0001 - Connecting......... - Chip is ESP32-D0WD (revision 1) - Features: WiFi, BT, Dual Core, 240MHz, VRef calibration in efuse, Coding Scheme None - Crystal is 40MHz - MAC: de:ad:be:ef:1d:ea - Uploading stub... - Running stub... - Stub running... - Changing baud rate to 460800 - Changed. - Configuring flash size... - Auto-detected Flash size: 16MB - Flash will be erased from 0x00001000 to 0x00007fff... - Flash will be erased from 0x00008000 to 0x00008fff... - Flash will be erased from 0x00010000 to 0x00039fff... - Flash params set to 0x0240 - Compressed 25536 bytes to 15935... - Wrote 25536 bytes (15935 compressed) at 0x00001000 in 0.7 seconds (effective 275.5 kbit/s)... - Hash of data verified. - Compressed 3072 bytes to 103... - Wrote 3072 bytes (103 compressed) at 0x00008000 in 0.1 seconds (effective 334.1 kbit/s)... - Hash of data verified. - Compressed 169232 bytes to 89490... - Wrote 169232 bytes (89490 compressed) at 0x00010000 in 2.6 seconds (effective 513.0 kbit/s)... - Hash of data verified. - - Leaving... - Hard resetting via RTS pin... - -It is now possible to unplug the flashed device and repeat the process by connecting another one and running the command again. diff --git a/docs/en/esptool/index.rst b/docs/en/esptool/index.rst deleted file mode 100644 index 495896fb9..000000000 --- a/docs/en/esptool/index.rst +++ /dev/null @@ -1,31 +0,0 @@ -.. _esptool: - -esptool.py -========== - -Use ``esptool.py -h`` to see a summary of all available commands and command line options. - -To see all options for a particular command, append ``-h`` to the command name. ie ``esptool.py write_flash -h``. - -.. toctree:: - :maxdepth: 1 - - Basic Options - Basic Commands - Advanced Options - Advanced Commands - Flasher Stub - Flash Modes - Entering the Bootloader - Serial Connection - Configuration File - Remote Serial Ports - Flashing Firmware - Scripting - -.. only:: not esp8266 - - Instructions for other tools bundled with esptool: - - * :ref:`espefuse` - * :ref:`espsecure` diff --git a/docs/en/esptool/remote-serial-ports.rst b/docs/en/esptool/remote-serial-ports.rst deleted file mode 100644 index f0f75ce3b..000000000 --- a/docs/en/esptool/remote-serial-ports.rst +++ /dev/null @@ -1,62 +0,0 @@ -Remote Serial Ports -=================== - -It is possible to connect to any networked remote serial port that supports `RFC2217 `__ (Telnet) protocol. To do this, specify the serial port to esptool as ``rfc2217://:``. For example: - -:: - - esptool.py --port rfc2217://192.168.1.77:4000 flash_id - -Custom baud rates and DTR/RTS automatic resetting are supported over the RFC2217 protocol, the same as for a local serial port. - -Pyserial Example Servers ------------------------- - -PySerial (which is a dependency of esptool) includes two RFC2217 example programs - `a single-port example `__ and a `multi-port example `__. -These example servers can run on any OS that supports pyserial, and are the simplest way to connect to an Espressif SoC over the network. - -There is an issue with `automatic resetting due to network latency `__. In order to work around this issue, a modified version of the single-port server example called ``esp_rfc2217_server.py`` is provided with esptool. - -On server: - -:: - - esp_rfc2217_server.py -p 4000 /dev/ttyUSB1 - -On client: - -:: - - esptool.py --port rfc2217://ADDRESS_OF_SERVER:4000?ign_set_control flash_id - - -Raw Sockets ------------ - -For servers or hardware network/serial adapters which don't support the full RFC2217, it is also possible to specify ``--port socket://:`` syntax for a simple "raw TCP socket" protocol. - -These raw sockets don't support setting the baud rate or automatic resetting into the bootloader. If using this mode, don't pass the ``--baud`` option to esptool. You need to set the baud rate manually on the server, and manually reset the chip into the bootloader mode (or use some other signalling/control method to tell the server to do so). - -Here's a very basic example using the common Linux/OSX command line "netcat" and "stty" commands: - -On server: - -:: - - stty -F /dev/ttyUSB1 230400 # set baud rate - nc -p 4000 -lk < /dev/ttyUSB1 > /dev/ttyUSB1 - -On client: - -:: - - esptool.py -p socket://localhost:4000 flash_id - -.. note:: - - Using RFC2217 is strongly recommended where possible. - -More Details ------------- - -All of the remote serial port support comes via pyserial. Read more `here `__. (Please keep in mind that the link points to documentation for the most recent pyserial version. You may have an older version.) diff --git a/docs/en/esptool/scripting.rst b/docs/en/esptool/scripting.rst deleted file mode 100644 index e4e96608d..000000000 --- a/docs/en/esptool/scripting.rst +++ /dev/null @@ -1,14 +0,0 @@ -.. _scripting: - -Embedding into Custom Scripts -============================= - -``esptool.py``, ``espefuse.py``, and ``espsecure.py`` can easily be integrated into Python applications or called from other Python scripts. - -While it currently does have a poor Python API, something which `#208 `_ will address, it allows for passing CLI arguments to ``esptool.main()``. This workaround makes integration very straightforward as you can pass exactly the same arguments as you would on the CLI: - -.. code-block:: python - - command = ['--baud', '460800', 'read_flash', '0', '0x200000', 'flash_contents.bin'] - print('Using command %s' % ' '.join(command)) - esptool.main(command) diff --git a/docs/en/esptool/serial-connection.rst b/docs/en/esptool/serial-connection.rst deleted file mode 100644 index ed710edd4..000000000 --- a/docs/en/esptool/serial-connection.rst +++ /dev/null @@ -1,47 +0,0 @@ -{IDF_TARGET_BAUD_RATE:default="115200", esp8266="74880 "} - -Serial Connection -================= - -The ROM serial bootloader of Espressif chips uses a 3.3V UART serial connection. Many development boards make the serial connections for you onboard. - -However, if you are wiring the chip yourself to a USB/Serial adapter or similar then the following connections must be made: - -+---------------------+-------------------+ -| ESP Chip Pin | Serial Port Pin | -+=====================+===================+ -| TX | RX (receive) | -+---------------------+-------------------+ -| RX | TX (transmit) | -+---------------------+-------------------+ -| Ground | Ground | -+---------------------+-------------------+ - -Note that TX (transmit) on the ESP chip is connected to RX (receive) on the serial port connection, and vice versa. - -Do not connect the chip to 5V TTL serial adapters, and especially not to "standard" RS-232 adapters! 3.3V serial only!  - -.. _serial-port-settings: - -Serial Port Settings --------------------- - -When communicating with the {IDF_TARGET_NAME} ROM serial bootloader, the following serial port settings are recommended: - -+---------------------+-------------------+  -| Baud rate | {IDF_TARGET_BAUD_RATE} | -+---------------------+-------------------+ -| Data bits | 8 | -+---------------------+-------------------+ -| Stop bits | 1 | -+---------------------+-------------------+ -| Parity | None | -+---------------------+-------------------+ -| Flow control | None | -+---------------------+-------------------+ - -.. only:: esp8266 - - .. note:: - - Baud rate {IDF_TARGET_BAUD_RATE} is what the {IDF_TARGET_NAME} bootloader uses. The apps on top of the Espressif SDK (e.g. Arduino sketch) talk at 115200 if not specified otherwise. diff --git a/docs/en/index.rst b/docs/en/index.rst deleted file mode 100644 index b1c49be3c..000000000 --- a/docs/en/index.rst +++ /dev/null @@ -1,54 +0,0 @@ -Esptool.py Documentation -======================== - -This is the documentation for ``esptool.py`` - a Python-based, open source, platform independent utility to communicate with the ROM bootloader in `Espressif SoCs `_. - -``esptool.py``, ``espefuse.py`` and ``espsecure.py`` are a complete toolset for working with Espressif chips. They can do a number of things, for example: - -* Read, write, erase, and verify binary data stored in flash. -* Read chip features and other related data such as MAC address or flash chip ID. -* Read and write the one-time-programmable efuses. -* Prepare binary executable images ready for flashing. -* Analyze, assemble, and merge binary images. - -This document describes using ``esptool.py`` with the {IDF_TARGET_NAME} SoC. To switch to a different SoC target, choose target from the dropdown in the upper left. - -Quick Start ------------ - -Getting started is easy: - -1) Install ``esptool.py``: - - :: - - $ pip install esptool - - For detailed instructions, see :ref:`installation`. - - -2) Connect an Espressif chip to your computer. - -3) Run ``esptool.py`` commands: - - :: - - $ esptool.py -p PORT flash_id - - Replace ``PORT`` with the name of used serial port. If connection fails, see :ref:`troubleshooting`. - -More Information ----------------- - -.. toctree:: - :maxdepth: 1 - - Installation - Esptool - :not esp8266:Espefuse - :not esp8266:Espsecure - Advanced Topics - Troubleshooting - Contribute - Versions - About diff --git a/docs/en/installation.rst b/docs/en/installation.rst deleted file mode 100644 index 7fe9f876e..000000000 --- a/docs/en/installation.rst +++ /dev/null @@ -1,23 +0,0 @@ -.. _installation: - -Installation and Dependencies -============================= - -You will need `Python 3.7 or newer `_ installed on your system to use the latest version of ``esptool.py``. -If your use case requires Python 2.7, 3.4, 3.5, or 3.6, please use ``esptool.py`` v3.3.* instead. - -The latest stable esptool release can be installed from `PyPI `_ via pip: - -:: - - $ pip install esptool - -With some Python installations this may not work and you’ll receive an error, try ``python -m pip install esptool`` or ``pip3 install esptool``, or consult your `Python installation manual `_ for information about how to access pip. - -`Setuptools `_ is also a requirement which is not available on all systems by default. You can install it by a package manager of your operating system, or by ``pip install setuptools``. - -After installing, you will have ``esptool.py`` installed into the default Python executables directory and you should be able to run it with the command ``esptool.py`` or ``python -m esptool``. Please note that probably only ``python -m esptool`` will work for Pythons installed from Windows Store. - -.. note:: - - If you actually plan to do development work with esptool itself, see :ref:`development-setup` for more information. diff --git a/docs/en/troubleshooting.rst b/docs/en/troubleshooting.rst deleted file mode 100644 index 35037e9e5..000000000 --- a/docs/en/troubleshooting.rst +++ /dev/null @@ -1,203 +0,0 @@ -{IDF_TARGET_BOOTLOADER_OFFSET:default="0x0", esp8266="0x0", esp32="0x1000", esp32s2="0x1000", esp32s3="0x0", esp32c3="0x0"} - -.. _troubleshooting: - -Troubleshooting -=============== - -Flashing problems can be fiddly to troubleshoot. Try the suggestions here if you're having problems: - -Bootloader Won't Respond ------------------------- - -If you see errors like "Failed to connect" then your chip is probably not entering the bootloader properly: - -* Check you are passing the correct serial port on the command line. -* Check you have permissions to access the serial port, and other software (such as modem-manager on Linux) is not trying to interact with it. A common pitfall is leaving a serial terminal accessing this port open in another window and forgetting about it. -* Check the chip is receiving 3.3V from a stable power source (see `Insufficient Power`_ for more details.) -* Check that all pins are connected as described in :ref:`boot-mode`. Check the voltages at each pin with a multimeter, "high" pins should be close to 3.3V and "low" pins should be close to 0V. -* If you have connected other devices to GPIO pins, try removing them and see if esptool starts working. -* Try using a slower baud rate (``-b 9600`` is a very slow value that you can use to verify it's not a baud rate problem). - -Writing to Flash Fails Part Way Through ---------------------------------------- - -If flashing fails with random errors part way through, retry with a lower baud rate. - -Power stability problems may also cause this (see `Insufficient Power`_.) - -Writing to Flash Succeeds but Program Doesn't Run -------------------------------------------------- - -If esptool can flash your module with ``write_flash`` but your program doesn't run, check the following: - -Wrong Flash Mode -^^^^^^^^^^^^^^^^ - -Some devices only support the ``dio`` flash mode. Writing to flash with ``qio`` mode will succeed but the chip can't read the flash back to run - so nothing happens on boot. Try passing the ``-fm dio`` option to ``write_flash``. - -See the :ref:`spi-flash-modes` page for a full description of the flash modes and how to determine which ones are supported on your device. - -Insufficient Power -^^^^^^^^^^^^^^^^^^ - -The 3.3V power supply for the ESP chip has to supply large amounts of current (up to 70mA continuous, 200-300mA peak, might be slightly higher). You also need sufficient capacitance on the power circuit to meet large spikes of power demand. - -Insufficient Capacitance -'''''''''''''''''''''''' - -If you're using a pre-made development board or module then the built-in power regulator & capacitors are usually good enough, provided the input power supply is adequate. - -.. note:: - - This is not true for some very simple pin breakout modules - `similar to this `_. These breakouts do not integrate enough capacitance to work reliably without additional components. - Surface mount OEM modules like ESP-WROOM02 and ESP-WROOM32 require an external bulk capacitor on the PCB to be reliable, consult the module datasheet. - -Power Supply Rating -''''''''''''''''''' - -It is possible to have a power supply that supplies enough current for the serial bootloader stage with esptool, but not enough for normal firmware operation. You may see the 3.3V VCC voltage droop down if you measure it with a multimeter, but you can have problems even if this isn't happening. - -Try swapping in a 3.3V supply with a higher current rating, add capacitors to the power line, and/or shorten any 3.3V power wires. - -The 3.3V output from FTDI FT232R chips/adapters or Arduino boards *do not* supply sufficient current to power an ESP chip (it may seem to work sometimes, but it won't work reliably). Other USB TTL/serial adapters may also be marginal. - -Missing Bootloader -^^^^^^^^^^^^^^^^^^ -.. only:: esp8266 - - The `ESP8266 SDK `_ uses a small firmware bootloader program. The hardware bootloader in ROM loads this firmware bootloader from flash, and then it runs the program. - On ESP8266, firmware bootloader image (with a filename like ``boot_v1.x.bin``) has to be flashed at offset {IDF_TARGET_BOOTLOADER_OFFSET}. If the firmware bootloader is missing then the ESP8266 will not boot. - - Refer to ESP8266 SDK documentation for details regarding which binaries need to be flashed at which offsets. - -.. only:: not esp8266 - - `ESP-IDF `_ and uses a small firmware bootloader program. The hardware bootloader in ROM loads this firmware bootloader from flash, and then it runs the program. - On {IDF_TARGET_NAME}, the bootloader image should be flashed by ESP-IDF at offset {IDF_TARGET_BOOTLOADER_OFFSET}. - - Refer to ESP-IDF documentation for details regarding which binaries need to be flashed at which offsets. - -SPI Pins Which Must Be Disconnected -^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - -Compared to the ROM bootloader that esptool talks to, a running firmware uses more of the chip's pins to access the SPI flash. - -If you set "Quad I/O" mode (``-fm qio``, the esptool default) then GPIOs 7, 8, 9 & 10 are used for reading the SPI flash and must be otherwise disconnected. - -If you set "Dual I/O" mode (``-fm dio``) then GPIOs 7 & 8 are used for reading the SPI flash and must be otherwise disconnected. - -Try disconnecting anything from those pins (and/or swap to Dual I/O mode if you were previously using Quad I/O mode but want to attach things to GPIOs 9 & 10). Note that if GPIOs 9 & 10 are also connected to input pins on the SPI flash chip, they may still be unsuitable for use as general purpose I/O. - -In addition to these pins, GPIOs 6 & 11 are also used to access the SPI flash (in all modes). However flashing will usually fail completely if these pins are connected incorrectly. - -Early Stage Crash ------------------ - -.. only:: esp8266 - - Use any of `serial terminal programs`_ to view the boot log. (ESP8266 baud rate is 74880bps). See if the program is crashing during early startup or outputting an error message. - -.. only:: not esp8266 - - Use any of `serial terminal programs`_ to view the boot log. ({IDF_TARGET_NAME} baud rate is 115200bps). See if the program is crashing during early startup or outputting an error message. - -Serial Terminal Programs ------------------------- - -There are many serial terminal programs suitable for debugging & serial interaction. The pySerial module (which is required for ``esptool``) includes one such command line terminal program - miniterm.py. For more details `see the related pySerial documentation `_ or run ``miniterm -h``. -For exact serial port configuration values, see :ref:`serial-port-settings`. - -.. only:: esp8266 - - Note that not every serial program supports the unusual ESP8266 74880bps "boot log" baud rate. Support is especially sparse on Linux. miniterm.py supports this baud rate on all platforms. - -Tracing Esptool Interactions ----------------------------- - -Running ``esptool.py --trace`` will dump all serial interactions to the standard output (this is *a lot* of output). This can be helpful when debugging issues with the serial connection, or when providing information for bug reports. - -See :ref:`the related Advanced Topics page ` for more information. - -Configuration File ------------------- - -Although ``esptool.py`` has been tuned to work in the widest possible range of environments, an incompatible combination of hardware, OS, and drivers might cause it to fail. If you suspect this is the case, a custom configuration of internal variables might be necessary. - -These variables and options can be specified in a configuration file. See :ref:`the related Configuration File page ` for more information. - -Common Errors -------------- - -This is a non-exhaustive list of the most common esptool errors together with explanations of possible causes and fixes. Before reading any error-specific advice, it is highly recommended to go through all of the `Troubleshooting`_ section first. - -No serial data received. -^^^^^^^^^^^^^^^^^^^^^^^^ - -Esptool didn't receive any byte of data or a successful :ref:`slip packet `. This error usually implies some kind of a hardware issue. This may be because the hardware is not working properly at all, the RX/TX serial lines are not connected, or because there is some problem with :ref:`resetting into the download mode `. - -.. only:: esp8266 - - .. attention:: - - There is a known issue regarding ESP8266 with the CH340 USB-to-serial converter (this includes NodeMCU and Wemos D1 mini devkits) on Linux. The regression affects only certain kernel versions. See `#653 `_ for details. - - On ESP8266, this error might be the result of a wrong boot mode. If your devkit supports this, try resetting into the download mode manually. See :ref:`manual-bootloader` for instructions. - -.. only:: not esp8266 - - Wrong boot mode detected (0xXX)! The chip needs to be in download mode. - ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - - Communication with the chip works (the ROM boot log is detected), but it is not being reset into the download mode automatically. - - To resolve this, check the autoreset circuitry (if your board has it), or try resetting into the download mode manually. See :ref:`manual-bootloader` for instructions. - - Download mode successfully detected, but getting no sync reply: The serial TX path seems to be down. - ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - - The chip successfully resets into the download mode and sends data to the host computer, but doesn't receive any response sent by ``esptool``. This implies a problem with the TX line running from the host to the ESP device. Double-check your board or breadboard circuit for any problems. - -Invalid head of packet (0xXX): Possible serial noise or corruption. -^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - -This error is usually caused by one of the following reasons: - -.. list:: - - :esp8266: * The chip is not resetting into the download mode. If the chip runs in a normal boot from flash mode, the ROM writes a log to UART when booting (see :ref:`ESP8266 boot log ` for more information). This data in the serial buffer result in "Invalid head of packet". You can verify this by connecting with any of `Serial Terminal Programs`_ and seeing what data is the chip sending. If this turns out to be true, check the autoreset circuitry (if your board has it), or try resetting into the download mode manually. See :ref:`manual-bootloader` for instructions. - * Using bad quality USB cable. - * Sometimes breadboards can short the SPI flash pins on the board and cause this kind of problem. Try removing your development board from the breadboard. - * The chip might be browning out during flashing. FTDI chips' internal 3.3V regulator is not enough to power an ESP, see `Insufficient Power`_. - -Other things to try: - -.. list:: - - * Try to sync and communicate at a much lower baud rate, e.g. ``esptool.py --baud 9600 ...``. - * Try `tracing the interactions `_ running ``esptool.py --trace ...`` and see if anything is received back at all. - * Try skipping chip autodetection by specifying the chip type, run ``esptool.py --chip {IDF_TARGET_NAME} ...``. - -If none of the above mentioned fixes help and your problem persists, please `open a new issue `_. - -A serial exception error occurred -^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - -``esptool.py`` uses the `pySerial `_ Python module for accessing the serial port. -If pySerial cannot operate normally, it raises an error and terminates. Some of the most common pySerial error causes are: - -.. list:: - - * You don't have permission to access the port. - * The port is being already used by other software. - * The port doesn't exist. - * The device gets unexpectedly disconnected. - * The necessary serial port drivers are not installed or are faulty. - -An example of a pySerial error: - -.. code-block:: none - - A serial exception error occurred: read failed: [Errno 6] Device not configured - -Errors originating from pySerial are, therefore, not a problem with ``esptool.py``, but are usually caused by a problem with hardware or drivers. diff --git a/docs/en/versions.rst b/docs/en/versions.rst deleted file mode 100644 index 648701e06..000000000 --- a/docs/en/versions.rst +++ /dev/null @@ -1,48 +0,0 @@ -.. _versions: - -Versions -======== - -Starting from ``v4.0.0``, ``esptool.py`` adopts the `semantic versioning specification `_, following the ``MAJOR.MINOR.PATCH`` version number. - -Major release ``v4`` is under active development, receiving new features and bugfixes, while ``v3`` only keeps receiving important bugfixes. - -There are no support periods defined and bugfixes are not planned, therefore it is strongly recommended to install the latest version possible. - -.. note:: - - The following information is directed mainly towards package maintainers. Regular users should always use the most recent version of ``esptool.py`` to benefit from the latest features and bugfixes. - -Use the latest esptool (recommended) ------------------------------------- - -If your use case doesn't impose any constraints on ``esptool.py``, the latest release should be always used. -To see the latest available version and its release notes, visit the `release page on GitHub `_. - -To get the latest possible version, simply define your dependency as ``esptool`` (without any release operator and a version identifier). - -Use the latest bugfix release of a minor esptool release --------------------------------------------------------- - -Some use cases might require a specific ``esptool.py`` version without getting new features, but with automatic bugfixes. - -This can be achieved by defining your dependency as ``esptool~=4.0.1`` (explicitly stating the ``MAJOR``, ``MINOR``, and ``PATCH`` numbers). -This notation selects the latest version of ``esptool.py``, greater than or equal to ``v4.0.1``, but still in the ``v4.0.*`` version (this compatible release clause is approximately equivalent to the pair of comparison clauses ``>= 4.0.1``, ``== 4.0.*``). -So, for example, ``v4.1.0`` won't be downloaded. More information about compatible release clauses `can be found here `_. - -Use the latest esptool without any future breaking change ---------------------------------------------------------- - -If you also want to get new features (instead of just bugfixes), define your version requirement as ``esptool~=4.0`` (explicitly stating only the ``MAJOR`` and ``MINOR`` numbers). This way the latest minor versions (``>= 4.0``, ``== 4.*``) are automatically installed. -Backward-compatibility is still ensured, because ``esptool.py`` respects the semantic versioning specification (which states that breaking changes should occur only in ``MAJOR`` versions). - -Use the previous major esptool release (only if you cannot upgrade) -------------------------------------------------------------------- - -If your use case is not compatible with the latest ``MAJOR`` release of ``esptool.py``, a previous compatible version has to be specified. -This can be achieved by defining your dependency as ``esptool~=3.0`` (explicitly stating your desired ``MAJOR`` number and at least also the ``MINOR`` number, ``PATCH`` can also be specified). - -Use a specific esptool release ------------------------------- - -If a very specific release is required, define your dependency as ``esptool==4.1.2``. This specific version will be used and no new features or bugfixes will be automatically installed. diff --git a/docs/requirements.txt b/docs/requirements.txt deleted file mode 100644 index 3be65005f..000000000 --- a/docs/requirements.txt +++ /dev/null @@ -1 +0,0 @@ -esp-docs==1.0.* diff --git a/docs/utils.sh b/docs/utils.sh deleted file mode 100644 index 84f374899..000000000 --- a/docs/utils.sh +++ /dev/null @@ -1,18 +0,0 @@ -# Bash helper functions for adding SSH keys - -function add_ssh_keys() { - local key_string="${1}" - mkdir -p ~/.ssh - chmod 700 ~/.ssh - echo -n "${key_string}" >~/.ssh/id_rsa_base64 - base64 --decode --ignore-garbage ~/.ssh/id_rsa_base64 >~/.ssh/id_rsa - chmod 600 ~/.ssh/id_rsa -} - -function add_doc_server_ssh_keys() { - local key_string="${1}" - local server_url="${2}" - local server_user="${3}" - add_ssh_keys "${key_string}" - echo -e "Host ${server_url}\n\tStrictHostKeyChecking no\n\tUser ${server_user}\n" >>~/.ssh/config -} diff --git a/esp_rfc2217_server.py b/esp_rfc2217_server.py index 61a6fc166..8b9a1678e 100755 --- a/esp_rfc2217_server.py +++ b/esp_rfc2217_server.py @@ -30,11 +30,21 @@ # SPDX-License-Identifier: BSD-3-Clause import logging +import os import socket import sys import threading import time +from esptool.config import load_config_file +from esptool.reset import ( + ClassicReset, + CustomReset, + DEFAULT_RESET_DELAY, + HardReset, + UnixTightReset, +) + import serial import serial.rfc2217 from serial.rfc2217 import ( @@ -46,6 +56,9 @@ SET_CONTROL_RTS_ON, ) +cfg, _ = load_config_file(verbose=True) +cfg = cfg["esptool"] + class EspPortManager(serial.rfc2217.PortManager): """ @@ -56,14 +69,23 @@ class EspPortManager(serial.rfc2217.PortManager): def __init__(self, serial_port, connection, esp32r0_delay, logger=None): self.esp32r0_delay = esp32r0_delay + self.is_download_mode = False super(EspPortManager, self).__init__(serial_port, connection, logger) def _telnet_process_subnegotiation(self, suboption): if suboption[0:1] == COM_PORT_OPTION and suboption[1:2] == SET_CONTROL: if suboption[2:3] == SET_CONTROL_DTR_OFF: + self.is_download_mode = False self.serial.dtr = False return - elif suboption[2:3] == SET_CONTROL_RTS_ON and not self.serial.dtr: + elif suboption[2:3] == SET_CONTROL_RTS_OFF and not self.is_download_mode: + reset_thread = threading.Thread(target=self._hard_reset_thread) + reset_thread.daemon = True + reset_thread.name = "hard_reset_thread" + reset_thread.start() + return + elif suboption[2:3] == SET_CONTROL_DTR_ON and not self.is_download_mode: + self.is_download_mode = True reset_thread = threading.Thread(target=self._reset_thread) reset_thread.daemon = True reset_thread.name = "reset_thread" @@ -78,15 +100,13 @@ def _telnet_process_subnegotiation(self, suboption): # only in cases not handled above do the original implementation in PortManager super(EspPortManager, self)._telnet_process_subnegotiation(suboption) - def _setDTR(self, state): - self.serial.setDTR(state) - - def _setRTS(self, state): - self.serial.setRTS(state) - # Work-around for adapters on Windows using the usbser.sys driver: - # generate a dummy change to DTR so that the set-control-line-state - # request is sent with the updated RTS state and the same DTR state - self.serial.setDTR(self.serial.dtr) + def _hard_reset_thread(self): + """ + The reset logic used for hard resetting the chip. + """ + if self.logger: + self.logger.info("Activating hard reset in thread") + HardReset(self.serial)() def _reset_thread(self): """ @@ -95,17 +115,18 @@ def _reset_thread(self): """ if self.logger: self.logger.info("Activating reset in thread") - self._setDTR(False) # IO0=HIGH - self._setRTS(True) # EN=LOW, chip in reset - time.sleep(0.1) - if self.esp32r0_delay: - time.sleep(1.2) - self._setDTR(True) # IO0=LOW - self._setRTS(False) # EN=HIGH, chip out of reset + + delay = DEFAULT_RESET_DELAY if self.esp32r0_delay: - time.sleep(0.4) - time.sleep(0.05) - self._setDTR(False) # IO0=HIGH, done + delay += 0.5 + + cfg_custom_reset_sequence = cfg.get("custom_reset_sequence") + if cfg_custom_reset_sequence is not None: + CustomReset(self.serial, cfg_custom_reset_sequence)() + elif os.name != "nt": + UnixTightReset(self.serial, delay)() + else: + ClassicReset(self.serial, delay)() class Redirector(object): @@ -186,7 +207,7 @@ def stop(self): self.thread_poll.join() -if __name__ == "__main__": +def main(): import argparse parser = argparse.ArgumentParser( @@ -284,3 +305,7 @@ def stop(self): logging.error(str(msg)) logging.info("--- exit ---") + + +if __name__ == "__main__": + main() diff --git a/espefuse.py b/espefuse.py index 9b8633a22..2222d4e55 100755 --- a/espefuse.py +++ b/espefuse.py @@ -18,9 +18,12 @@ # Linux/macOS: remove current script directory to avoid importing this file # as a module; we want to import the installed espefuse module instead with contextlib.suppress(ValueError): - if sys.path[0].endswith("/bin"): - sys.path.pop(0) - sys.path.remove(os.path.dirname(sys.executable)) + executable_dir = os.path.dirname(sys.executable) + sys.path = [ + path + for path in sys.path + if not path.endswith(("/bin", "/sbin")) and path != executable_dir + ] # Linux/macOS: delete imported module entry to force Python to load # the module from scratch; this enables importing espefuse module in diff --git a/espefuse/__init__.py b/espefuse/__init__.py index 20357ee81..777d53f41 100755 --- a/espefuse/__init__.py +++ b/espefuse/__init__.py @@ -14,6 +14,7 @@ import espefuse.efuse.esp32c6 as esp32c6_efuse import espefuse.efuse.esp32h2 as esp32h2_efuse import espefuse.efuse.esp32h2beta1 as esp32h2beta1_efuse +import espefuse.efuse.esp32p4 as esp32p4_efuse import espefuse.efuse.esp32s2 as esp32s2_efuse import espefuse.efuse.esp32s3 as esp32s3_efuse import espefuse.efuse.esp32s3beta2 as esp32s3beta2_efuse @@ -49,6 +50,7 @@ "esp32c3": DefChip("ESP32-C3", esp32c3_efuse, esptool.targets.ESP32C3ROM), "esp32c6": DefChip("ESP32-C6", esp32c6_efuse, esptool.targets.ESP32C6ROM), "esp32h2": DefChip("ESP32-H2", esp32h2_efuse, esptool.targets.ESP32H2ROM), + "esp32p4": DefChip("ESP32-P4", esp32p4_efuse, esptool.targets.ESP32P4ROM), "esp32h2beta1": DefChip( "ESP32-H2(beta1)", esp32h2beta1_efuse, esptool.targets.ESP32H2BETA1ROM ), @@ -132,7 +134,7 @@ def split_on_groups(all_args): return groups, used_cmds -def main(custom_commandline=None): +def main(custom_commandline=None, esp=None): """ Main function for espefuse @@ -140,7 +142,13 @@ def main(custom_commandline=None): (that uses sys.argv), can be a list of custom arguments as strings. Arguments and their values need to be added as individual items to the list e.g. "--port /dev/ttyUSB1" thus becomes ['--port', '/dev/ttyUSB1']. + + esp - Optional override of the connected device previously + returned by esptool.get_default_connected_device() """ + + external_esp = esp is not None + init_parser = argparse.ArgumentParser( description="espefuse.py v%s - [ESP32xx] efuse get/set tool" % esptool.__version__, @@ -211,22 +219,24 @@ def main(custom_commandline=None): print("espefuse.py v{}".format(esptool.__version__)) - try: - esp = get_esp( - common_args.port, - common_args.baud, - common_args.before, - common_args.chip, - just_print_help, - common_args.virt, - common_args.debug, - common_args.path_efuse_file, - ) - except esptool.FatalError as e: - raise esptool.FatalError( - f"{e}\nPlease make sure that you have specified " - "the right port with the --port argument" - ) # TODO: Require the --port argument in the next major release, ESPTOOL-490 + if not external_esp: + try: + esp = get_esp( + common_args.port, + common_args.baud, + common_args.before, + common_args.chip, + just_print_help, + common_args.virt, + common_args.debug, + common_args.path_efuse_file, + ) + except esptool.FatalError as e: + raise esptool.FatalError( + f"{e}\nPlease make sure that you have specified " + "the right port with the --port argument" + ) + # TODO: Require the --port argument in the next major release, ESPTOOL-490 efuses, efuse_operations = get_efuses( esp, just_print_help, debug_mode, common_args.do_not_confirm @@ -262,6 +272,13 @@ def main(custom_commandline=None): operation_func = vars(efuse_operations)[args.operation] # each 'operation' is a module-level function of the same name print('\n=== Run "{}" command ==='.format(args.operation)) + + if hasattr(args, "show_sensitive_info"): + if args.show_sensitive_info or args.debug: + args.show_sensitive_info = True + else: + print("Sensitive data will be hidden (see --show-sensitive-info)") + operation_func(esp, efuses, args) if there_are_multiple_burn_commands_in_args: @@ -269,7 +286,7 @@ def main(custom_commandline=None): if not efuses.burn_all(check_batch_mode=True): raise esptool.FatalError("BURN was not done") finally: - if not common_args.virt and esp._port: + if not external_esp and not common_args.virt and esp._port: esp._port.close() diff --git a/espefuse/efuse/base_fields.py b/espefuse/efuse/base_fields.py index 9569fe775..ab12f0312 100644 --- a/espefuse/efuse/base_fields.py +++ b/espefuse/efuse/base_fields.py @@ -5,7 +5,6 @@ # SPDX-License-Identifier: GPL-2.0-or-later import binascii -import re import sys from bitstring import BitArray, BitStream, CreationError @@ -85,21 +84,34 @@ def check_arg_value(efuse, new_value): class EfuseProtectBase(object): # This class is used by EfuseBlockBase and EfuseFieldBase - def get_read_disable_mask(self): + def get_read_disable_mask(self, blk_part=None): + """Returns mask of read protection bits + blk_part: + - None: Calculate mask for all read protection bits. + - a number: Calculate mask only for specific item in read protection list. + """ mask = 0 if isinstance(self.read_disable_bit, list): - for i in self.read_disable_bit: - mask |= 1 << i + if blk_part is None: + for i in self.read_disable_bit: + mask |= 1 << i + else: + mask |= 1 << self.read_disable_bit[blk_part] else: mask = 1 << self.read_disable_bit return mask - def is_readable(self): + def get_count_read_disable_bits(self): + """Returns the number of read protection bits used by the field""" + # On the C2 chip, BLOCK_KEY0 has two read protection bits [0, 1]. + return bin(self.get_read_disable_mask()).count("1") + + def is_readable(self, blk_part=None): """Return true if the efuse is readable by software""" num_bit = self.read_disable_bit if num_bit is None: return True # read cannot be disabled - return (self.parent["RD_DIS"].get() & (self.get_read_disable_mask())) == 0 + return (self.parent["RD_DIS"].get() & self.get_read_disable_mask(blk_part)) == 0 def disable_read(self): num_bit = self.read_disable_bit @@ -538,6 +550,10 @@ def print_error_msg(self, error_msg): else: raise esptool.FatalError(error_msg) + def get_block_errors(self, block_num): + """Returns (error count, failure boolean flag)""" + return self.blocks[block_num].num_errors, self.blocks[block_num].fail + class EfuseFieldBase(EfuseProtectBase): def __init__(self, parent, param): @@ -553,19 +569,17 @@ def __init__(self, parent, param): self.efuse_type = param.type self.description = param.description self.dict_value = param.dictionary + self.bit_len = param.bit_len + self.alt_names = param.alt_names self.fail = False self.num_errors = 0 - if self.efuse_type.startswith("bool"): - field_len = 1 - else: - field_len = int(re.search(r"\d+", self.efuse_type).group()) - if self.efuse_type.startswith("bytes"): - field_len *= 8 - self.bitarray = BitStream(field_len) - self.bit_len = field_len + self.bitarray = BitStream(self.bit_len) self.bitarray.set(0) self.update(self.parent.blocks[self.block].bitarray) + def is_field_calculated(self): + return self.word is None or self.pos is None + def check_format(self, new_value_str): if new_value_str is None: return new_value_str @@ -658,8 +672,10 @@ def save(self, new_value): self.save_to_block(bitarray_field) def update(self, bit_array_block): - if self.word is None or self.pos is None: - self.bitarray.overwrite(self.convert_to_bitstring(self.get()), pos=0) + if self.is_field_calculated(): + self.bitarray.overwrite( + self.convert_to_bitstring(self.check_format(self.get())), pos=0 + ) return field_len = self.bitarray.len bit_array_block.pos = bit_array_block.length - ( @@ -721,3 +737,18 @@ def burn(self, new_value): # Burn a efuse. Added for compatibility reason. self.save(new_value) self.parent.burn_all() + + def get_info(self): + output = f"{self.name} (BLOCK{self.block})" + if self.block == 0: + if self.fail: + output += "[error]" + else: + errs, fail = self.parent.get_block_errors(self.block) + if errs != 0 or fail: + output += "[error]" + if self.efuse_class == "keyblock": + name = self.parent.blocks[self.block].key_purpose_name + if name is not None: + output += f"\n Purpose: {self.parent[name].get()}\n " + return output diff --git a/espefuse/efuse/base_operations.py b/espefuse/efuse/base_operations.py index b1c30dbb4..5e3475e49 100644 --- a/espefuse/efuse/base_operations.py +++ b/espefuse/efuse/base_operations.py @@ -71,7 +71,8 @@ def check_efuse_name(efuse_name, efuse_list): metavar="[EFUSE_NAME VALUE] [{} VALUE".format( " VALUE] [".join([e.name for e in efuses.efuses]) ), - efuse_choices=[e.name for e in efuses.efuses], + efuse_choices=[e.name for e in efuses.efuses] + + [name for e in efuses.efuses for name in e.alt_names if name != ""], efuses=efuses, ) @@ -83,7 +84,14 @@ def check_efuse_name(efuse_name, efuse_list): "efuse_name", help="Name of efuse register to burn", nargs="+", - choices=[e.name for e in efuses.efuses if e.read_disable_bit is not None], + choices=[e.name for e in efuses.efuses if e.read_disable_bit is not None] + + [ + name + for e in efuses.efuses + if e.read_disable_bit is not None + for name in e.alt_names + if name != "" + ], ) write_protect_efuse = subparsers.add_parser( @@ -94,7 +102,14 @@ def check_efuse_name(efuse_name, efuse_list): "efuse_name", help="Name of efuse register to burn", nargs="+", - choices=[e.name for e in efuses.efuses if e.write_disable_bit is not None], + choices=[e.name for e in efuses.efuses if e.write_disable_bit is not None] + + [ + name + for e in efuses.efuses + if e.write_disable_bit is not None + for name in e.alt_names + if name != "" + ], ) burn_block_data = subparsers.add_parser( @@ -220,6 +235,16 @@ def add_force_write_always(p): ) +def add_show_sensitive_info_option(p): + p.add_argument( + "--show-sensitive-info", + help="Show data to be burned (may expose sensitive data). " + "Enabled if --debug is used.", + action="store_true", + default=False, + ) + + def summary(esp, efuses, args): """Print a human-readable summary of efuse contents""" ROW_FORMAT = "%-50s %-50s%s = %s %s %s" @@ -261,7 +286,17 @@ def summary(esp, efuses, args): base_value = e.get_meaning() value = str(base_value) if not readable: - value = value.replace("0", "?") + count_read_disable_bits = e.get_count_read_disable_bits() + if count_read_disable_bits == 2: + # On the C2 chip, BLOCK_KEY0 has two read protection bits [0, 1] + # related to the lower and higher part of the block. + v = [value[: (len(value) // 2)], value[(len(value) // 2) :]] + for i in range(count_read_disable_bits): + if not e.is_readable(blk_part=i): + v[i] = v[i].replace("0", "?") + value = "".join(v) + else: + value = value.replace("0", "?") if human_output: print( ROW_FORMAT @@ -648,26 +683,49 @@ def burn_bit(esp, efuses, args): print("Successful") -def check_error(esp, efuses, args): +def get_error_summary(efuses): error_in_blocks = efuses.get_coding_scheme_warnings() - if args.recovery: - if error_in_blocks: - confirmed = False - for block in reversed(efuses.blocks): - if block.fail or block.num_errors > 0: - if not block.get_bitstring().all(False): - block.save(block.get_bitstring().bytes[::-1]) - if not confirmed: - confirmed = True - efuses.confirm( - "Recovery of block coding errors", args.do_not_confirm - ) - block.burn() - # Reset the recovery flag to run check_error() without it, - # just to check the new state of eFuse blocks. - args.recovery = False - check_error(esp, efuses, args) - else: - if error_in_blocks: - raise esptool.FatalError("Error(s) were detected in eFuses") + if not error_in_blocks: + return False + writable = True + for blk in efuses.blocks: + if blk.fail or blk.num_errors: + if blk.id == 0: + for field in efuses: + if field.block == blk.id and (field.fail or field.num_errors): + wr = "writable" if field.is_writeable() else "not writable" + writable &= wr == "writable" + name = field.name + val = field.get() + print(f"BLOCK{field.block:<2}: {name:<40} = {val:<8} ({wr})") + else: + wr = "writable" if blk.is_writeable() else "not writable" + writable &= wr == "writable" + name = f"{blk.name} [ERRORS:{blk.num_errors} FAIL:{int(blk.fail)}]" + val = str(blk.get_bitstring()) + print(f"BLOCK{blk.id:<2}: {name:<40} = {val:<8} ({wr})") + if not writable and error_in_blocks: + print("Not all errors can be fixed because some fields are write-protected!") + return True + + +def check_error(esp, efuses, args): + error_in_blocks = get_error_summary(efuses) + if args.recovery and error_in_blocks: + confirmed = False + for block in reversed(efuses.blocks): + if block.fail or block.num_errors > 0: + if not block.get_bitstring().all(False): + block.save(block.get_bitstring().bytes[::-1]) + if not confirmed: + confirmed = True + efuses.confirm( + "Recovery of block coding errors", args.do_not_confirm + ) + block.burn() + if confirmed: + efuses.update_efuses() + error_in_blocks = get_error_summary(efuses) + if error_in_blocks: + raise esptool.FatalError("Error(s) were detected in eFuses") print("No errors detected") diff --git a/espefuse/efuse/emulate_efuse_controller_base.py b/espefuse/efuse/emulate_efuse_controller_base.py index d1c200f0f..232bfaad8 100644 --- a/espefuse/efuse/emulate_efuse_controller_base.py +++ b/espefuse/efuse/emulate_efuse_controller_base.py @@ -109,8 +109,7 @@ def clean_blocks_wr_regs(self): self.write_reg(wr_addr, 0) def read_field(self, name, bitstring=True): - for e in self.Fields.EFUSES: - field = self.Fields.get(e) + for field in self.Fields.EFUSES: if field.name == name: self.read_block(field.block) block = self.read_block(field.block) @@ -166,8 +165,7 @@ def check_wr_protection_area(self, num_blk, wr_data): ): mask_wr_data.set(1) else: - for e in self.Fields.EFUSES: - field = self.Fields.get(e) + for field in self.Fields.EFUSES: if blk.id == field.block and field.block == num_blk: if field.write_disable_bit is not None and write_disable_bit & ( 1 << field.write_disable_bit @@ -193,8 +191,7 @@ def check_rd_protection_area(self): ): block.set(0) else: - for e in self.Fields.EFUSES: - field = self.Fields.get(e) + for field in self.Fields.EFUSES: if ( blk.id == field.block and field.read_disable_bit is not None diff --git a/espefuse/efuse/esp32/emulate_efuse_controller.py b/espefuse/efuse/esp32/emulate_efuse_controller.py index 35923cfb1..da7cd44d6 100644 --- a/espefuse/efuse/esp32/emulate_efuse_controller.py +++ b/espefuse/efuse/esp32/emulate_efuse_controller.py @@ -16,11 +16,11 @@ class EmulateEfuseController(EmulateEfuseControllerBase): CHIP_NAME = "ESP32" mem = None debug = False - Blocks = EfuseDefineBlocks - Fields = EfuseDefineFields - REGS = EfuseDefineRegisters def __init__(self, efuse_file=None, debug=False): + self.Blocks = EfuseDefineBlocks + self.Fields = EfuseDefineFields() + self.REGS = EfuseDefineRegisters super(EmulateEfuseController, self).__init__(efuse_file, debug) """ esptool method start >> """ diff --git a/espefuse/efuse/esp32/fields.py b/espefuse/efuse/esp32/fields.py index ceb160c19..7ca5fc356 100644 --- a/espefuse/efuse/esp32/fields.py +++ b/espefuse/efuse/esp32/fields.py @@ -65,16 +65,15 @@ class EspEfuses(base_fields.EspEfusesBase): Wrapper object to manage the efuse fields in a connected ESP bootloader """ - Blocks = EfuseDefineBlocks() - Fields = EfuseDefineFields() - REGS = EfuseDefineRegisters - BURN_BLOCK_DATA_NAMES = Blocks.get_burn_block_data_names() - BLOCKS_FOR_KEYS = Blocks.get_blocks_for_keys() - debug = False do_not_confirm = False def __init__(self, esp, skip_connect=False, debug=False, do_not_confirm=False): + self.Blocks = EfuseDefineBlocks() + self.Fields = EfuseDefineFields() + self.REGS = EfuseDefineRegisters + self.BURN_BLOCK_DATA_NAMES = self.Blocks.get_burn_block_data_names() + self.BLOCKS_FOR_KEYS = self.Blocks.get_blocks_for_keys() self._esp = esp self.debug = debug self.do_not_confirm = do_not_confirm @@ -89,44 +88,26 @@ def __init__(self, esp, skip_connect=False, debug=False, do_not_confirm=False): ] if not skip_connect: self.get_coding_scheme_warnings() - self.efuses = [ - EfuseField.from_tuple( - self, self.Fields.get(efuse), self.Fields.get(efuse).class_type - ) - for efuse in self.Fields.EFUSES - ] + self.efuses = [EfuseField.convert(self, efuse) for efuse in self.Fields.EFUSES] if skip_connect: self.efuses += [ - EfuseField.from_tuple( - self, self.Fields.get(efuse), self.Fields.get(efuse).class_type - ) - for efuse in self.Fields.KEYBLOCKS_256 + EfuseField.convert(self, efuse) for efuse in self.Fields.KEYBLOCKS_256 ] self.efuses += [ - EfuseField.from_tuple( - self, self.Fields.get(efuse), self.Fields.get(efuse).class_type - ) - for efuse in self.Fields.CUSTOM_MAC + EfuseField.convert(self, efuse) for efuse in self.Fields.CUSTOM_MAC ] self.efuses += [ - EfuseField.from_tuple( - self, self.Fields.get(efuse), self.Fields.get(efuse).class_type - ) - for efuse in self.Fields.ADC_CALIBRATION + EfuseField.convert(self, efuse) for efuse in self.Fields.ADC_CALIBRATION ] else: if self.coding_scheme == self.REGS.CODING_SCHEME_NONE: self.efuses += [ - EfuseField.from_tuple( - self, self.Fields.get(efuse), self.Fields.get(efuse).class_type - ) + EfuseField.convert(self, efuse) for efuse in self.Fields.KEYBLOCKS_256 ] elif self.coding_scheme == self.REGS.CODING_SCHEME_34: self.efuses += [ - EfuseField.from_tuple( - self, self.Fields.get(efuse), self.Fields.get(efuse).class_type - ) + EfuseField.convert(self, efuse) for efuse in self.Fields.KEYBLOCKS_192 ] else: @@ -135,54 +116,43 @@ def __init__(self, esp, skip_connect=False, debug=False, do_not_confirm=False): ) if self["MAC_VERSION"].get() == 1: self.efuses += [ - EfuseField.from_tuple( - self, self.Fields.get(efuse), self.Fields.get(efuse).class_type - ) - for efuse in self.Fields.CUSTOM_MAC + EfuseField.convert(self, efuse) for efuse in self.Fields.CUSTOM_MAC ] if self["BLK3_PART_RESERVE"].get(): self.efuses += [ - EfuseField.from_tuple( - self, self.Fields.get(efuse), self.Fields.get(efuse).class_type - ) + EfuseField.convert(self, efuse) for efuse in self.Fields.ADC_CALIBRATION ] self.efuses += [ - EfuseField.from_tuple( - self, self.Fields.get(efuse), self.Fields.get(efuse).class_type - ) - for efuse in self.Fields.CALC + EfuseField.convert(self, efuse) for efuse in self.Fields.CALC ] def __getitem__(self, efuse_name): """Return the efuse field with the given name""" for e in self.efuses: - if efuse_name == e.name: + if efuse_name == e.name or any(x == efuse_name for x in e.alt_names): return e new_fields = False for efuse in self.Fields.CUSTOM_MAC: - e = self.Fields.get(efuse) - if e.name == efuse_name: + if efuse.name == efuse_name or any( + x == efuse_name for x in efuse.alt_names + ): self.efuses += [ - EfuseField.from_tuple( - self, self.Fields.get(efuse), self.Fields.get(efuse).class_type - ) - for efuse in self.Fields.CUSTOM_MAC + EfuseField.convert(self, efuse) for efuse in self.Fields.CUSTOM_MAC ] new_fields = True for efuse in self.Fields.ADC_CALIBRATION: - e = self.Fields.get(efuse) - if e.name == efuse_name: + if efuse.name == efuse_name or any( + x == efuse_name for x in efuse.alt_names + ): self.efuses += [ - EfuseField.from_tuple( - self, self.Fields.get(efuse), self.Fields.get(efuse).class_type - ) + EfuseField.convert(self, efuse) for efuse in self.Fields.ADC_CALIBRATION ] new_fields = True if new_fields: for e in self.efuses: - if efuse_name == e.name: + if efuse_name == e.name or any(x == efuse_name for x in e.alt_names): return e raise KeyError @@ -263,8 +233,7 @@ def get_coding_scheme_warnings(self, silent=False): def summary(self): if self["XPD_SDIO_FORCE"].get() == 0: - output = "Flash voltage (VDD_SDIO) determined by GPIO12 on reset " - "(High for 1.8V, Low/NC for 3.3V)." + output = "Flash voltage (VDD_SDIO) determined by GPIO12 on reset (High for 1.8V, Low/NC for 3.3V)" elif self["XPD_SDIO_REG"].get() == 0: output = "Flash voltage (VDD_SDIO) internal regulator disabled by efuse." elif self["XPD_SDIO_TIEH"].get() == 0: @@ -276,7 +245,7 @@ def summary(self): class EfuseField(base_fields.EfuseFieldBase): @staticmethod - def from_tuple(parent, efuse_tuple, type_class): + def convert(parent, efuse): return { "mac": EfuseMacField, "spipin": EfuseSpiPinField, @@ -284,10 +253,7 @@ def from_tuple(parent, efuse_tuple, type_class): "adc_tp": EfuseAdcPointCalibration, "wafer": EfuseWafer, "pkg": EfusePkg, - }.get(type_class, EfuseField)(parent, efuse_tuple) - - def get_info(self): - return "%s (BLOCK%d):" % (self.name, self.block) + }.get(efuse.class_type, EfuseField)(parent, efuse) class EfuseMacField(EfuseField): @@ -402,7 +368,9 @@ def print_field(e, new_value): class EfuseWafer(EfuseField): def get(self, from_read=True): rev_bit0 = self.parent["CHIP_VER_REV1"].get(from_read) + assert self.parent["CHIP_VER_REV1"].bit_len == 1 rev_bit1 = self.parent["CHIP_VER_REV2"].get(from_read) + assert self.parent["CHIP_VER_REV2"].bit_len == 1 apb_ctl_date = self.parent.read_reg(self.parent.REGS.APB_CTL_DATE_ADDR) rev_bit2 = ( apb_ctl_date >> self.parent.REGS.APB_CTL_DATE_S diff --git a/espefuse/efuse/esp32/mem_definition.py b/espefuse/efuse/esp32/mem_definition.py index 0e09030c5..7d29a010a 100644 --- a/espefuse/efuse/esp32/mem_definition.py +++ b/espefuse/efuse/esp32/mem_definition.py @@ -4,7 +4,17 @@ # # SPDX-License-Identifier: GPL-2.0-or-later -from ..mem_definition_base import EfuseBlocksBase, EfuseFieldsBase, EfuseRegistersBase +import copy +import os + +import yaml + +from ..mem_definition_base import ( + EfuseBlocksBase, + EfuseFieldsBase, + EfuseRegistersBase, + Field, +) class EfuseDefineRegisters(EfuseRegistersBase): @@ -56,11 +66,10 @@ class EfuseDefineRegisters(EfuseRegistersBase): EFUSE_RD_CHIP_VER_REV2 = 1 << 20 -# fmt: off class EfuseDefineBlocks(EfuseBlocksBase): - __base_regs = EfuseDefineRegisters.DR_REG_EFUSE_BASE # List of efuse blocks + # fmt: off BLOCKS = [ # Name, Alias, Index, Read address, Write address, Write protect bit, Read protect bit, Len, key_purpose ("BLOCK0", [], 0, __base_regs + 0x000, __base_regs + 0x01C, None, None, 7, None), @@ -68,6 +77,7 @@ class EfuseDefineBlocks(EfuseBlocksBase): ("BLOCK2", ["secure_boot_v1", "secure_boot_v2"], 2, __base_regs + 0x058, __base_regs + 0x0B8, 8, 1, 8, None), ("BLOCK3", [], 3, __base_regs + 0x078, __base_regs + 0x0D8, 9, 2, 8, None), ] + # fmt: on def get_burn_block_data_names(self): list_of_names = [] @@ -79,87 +89,91 @@ def get_burn_block_data_names(self): class EfuseDefineFields(EfuseFieldsBase): - - # Lists of efuse fields - EFUSES = [ - # Name Category Block Word Pos Type:len WR_DIS RD_DIS Class Description Dictionary - ('WR_DIS', "efuse", 0, 0, 0, "uint:16", 1, None, None, "Efuse write disable mask", None), - ('RD_DIS', "efuse", 0, 0, 16, "uint:4", 0, None, None, "Efuse read disable mask", None), - ('CODING_SCHEME', "efuse", 0, 6, 0, "uint:2", 10, 3, None, "Efuse variable block length scheme", - {0: "NONE (BLK1-3 len=256 bits)", - 1: "3/4 (BLK1-3 len=192 bits)", - 2: "REPEAT (BLK1-3 len=128 bits) not supported", - 3: "NONE (BLK1-3 len=256 bits)"}), - ('KEY_STATUS', "efuse", 0, 6, 10, "bool", 10, 3, None, "Usage of efuse block 3 (reserved)", None), - ('MAC', "identity", 0, 1, 0, "bytes:6", 3, None, "mac", "Factory MAC Address", None), - ('MAC_CRC', "identity", 0, 2, 16, "uint:8", 3, None, None, "CRC8 for factory MAC address", None), - ('CHIP_VER_REV1', "identity", 0, 3, 15, "bool", 3, None, None, "Silicon Revision 1", None), - ('CHIP_VER_REV2', "identity", 0, 5, 20, "bool", 6, None, None, "Silicon Revision 2", None), - ("WAFER_VERSION_MINOR", "identity", 0, 5, 24, "uint:2", 6, None, None, "WAFER VERSION MINOR", None), - ('CHIP_PACKAGE', "identity", 0, 3, 9, "uint:3", 3, None, None, "Chip package identifier", None), - ('CHIP_PACKAGE_4BIT', "identity", 0, 3, 2, "uint:1", 3, None, None, "Chip package identifier #4bit", None), - ('XPD_SDIO_FORCE', "config", 0, 4, 16, "bool", 5, None, None, "Ignore MTDI pin (GPIO12) for VDD_SDIO on reset", None), - ('XPD_SDIO_REG', "config", 0, 4, 14, "bool", 5, None, None, "If XPD_SDIO_FORCE, enable VDD_SDIO reg on reset", None), - ('XPD_SDIO_TIEH', "config", 0, 4, 15, "bool", 5, None, None, "If XPD_SDIO_FORCE & XPD_SDIO_REG", - {1: "3.3V", - 0: "1.8V"}), - ('CLK8M_FREQ', "config", 0, 4, 0, "uint:8", None, None, None, "8MHz clock freq override", None), - ('SPI_PAD_CONFIG_CLK', "config", 0, 5, 0, "uint:5", 6, None, "spipin", "Override SD_CLK pad (GPIO6/SPICLK)", None), - ('SPI_PAD_CONFIG_Q', "config", 0, 5, 5, "uint:5", 6, None, "spipin", "Override SD_DATA_0 pad (GPIO7/SPIQ)", None), - ('SPI_PAD_CONFIG_D', "config", 0, 5, 10, "uint:5", 6, None, "spipin", "Override SD_DATA_1 pad (GPIO8/SPID)", None), - ('SPI_PAD_CONFIG_HD', "config", 0, 3, 4, "uint:5", 6, None, "spipin", "Override SD_DATA_2 pad (GPIO9/SPIHD)", None), - ('SPI_PAD_CONFIG_CS0', "config", 0, 5, 15, "uint:5", 6, None, "spipin", "Override SD_CMD pad (GPIO11/SPICS0)", None), - ('DISABLE_SDIO_HOST', "config", 0, 6, 3, "bool", None, None, None, "Disable SDIO host", None), - ('FLASH_CRYPT_CNT', "security", 0, 0, 20, "uint:7", 2, None, "bitcount", "Flash encryption mode counter", None), - ('UART_DOWNLOAD_DIS', "security", 0, 0, 27, "bool", 2, None, None, "Disable UART download mode (ESP32 rev3 only)", None), - ('FLASH_CRYPT_CONFIG', "security", 0, 5, 28, "uint:4", 10, 3, None, "Flash encryption config (key tweak bits)", None), - ('CONSOLE_DEBUG_DISABLE', "security", 0, 6, 2, "bool", 15, None, None, "Disable ROM BASIC interpreter fallback", None), - ('ABS_DONE_0', "security", 0, 6, 4, "bool", 12, None, None, "Secure boot V1 is enabled for bootloader image", None), - ('ABS_DONE_1', "security", 0, 6, 5, "bool", 13, None, None, "Secure boot V2 is enabled for bootloader image", None), - ('JTAG_DISABLE', "security", 0, 6, 6, "bool", 14, None, None, "Disable JTAG", None), - ('DISABLE_DL_ENCRYPT', "security", 0, 6, 7, "bool", 15, None, None, "Disable flash encryption in UART bootloader", None), - ('DISABLE_DL_DECRYPT', "security", 0, 6, 8, "bool", 15, None, None, "Disable flash decryption in UART bootloader", None), - ('DISABLE_DL_CACHE', "security", 0, 6, 9, "bool", 15, None, None, "Disable flash cache in UART bootloader", None), - ('BLK3_PART_RESERVE', "calibration", 0, 3, 14, "bool", 10, 3, None, "BLOCK3 partially served for ADC calibration data", None), - ('ADC_VREF', "calibration", 0, 4, 8, "uint:5", 0, None, "vref", "Voltage reference calibration", None), - ('MAC_VERSION', "identity", 3, 5, 24, "uint:8", 9, 2, None, "Version of the MAC field", - {1: "Custom MAC in BLOCK3"}), - ] - - # if MAC_VERSION is set "1", these efuse fields are in BLOCK3: - CUSTOM_MAC = [ - # Name Category Block Word Pos Type:len WR_DIS RD_DIS Class Description Dictionary - ('CUSTOM_MAC', "identity", 3, 0, 8, "bytes:6", 9, 2, "mac", "Custom MAC", None), - ('CUSTOM_MAC_CRC', "identity", 3, 0, 0, "uint:8", 9, 2, None, "CRC of custom MAC", None), - ] - - # The len of fields depends on coding scheme: for CODING_SCHEME_NONE - KEYBLOCKS_256 = [ - # Name Category Block Word Pos Type:len WR_DIS RD_DIS Class Description Dictionary - ('BLOCK1', "security", 1, 0, 0, "bytes:32", 7, 0, "keyblock", "Flash encryption key", None), - ('BLOCK2', "security", 2, 0, 0, "bytes:32", 8, 1, "keyblock", "Secure boot key", None), - ('BLOCK3', "security", 3, 0, 0, "bytes:32", 9, 2, "keyblock", "Variable Block 3", None), - ] - - # The len of fields depends on coding scheme: for CODING_SCHEME_34 - KEYBLOCKS_192 = [ - # Name Category Block Word Pos Type:len WR_DIS RD_DIS Class Description Dictionary - ('BLOCK1', "security", 1, 0, 0, "bytes:24", 7, 0, "keyblock", "Flash encryption key", None), - ('BLOCK2', "security", 2, 0, 0, "bytes:24", 8, 1, "keyblock", "Secure boot key", None), - ('BLOCK3', "security", 3, 0, 0, "bytes:24", 9, 2, "keyblock", "Variable Block 3", None), - ] - - # if BLK3_PART_RESERVE is set, these efuse fields are in BLOCK3: - ADC_CALIBRATION = [ - # Name Category Block Word Pos Type:len WR_DIS RD_DIS Class Description Dictionary - ('ADC1_TP_LOW', "calibration", 3, 3, 0, "uint:7", 9, 2, "adc_tp", "ADC1 150mV reading", None), - ('ADC1_TP_HIGH', "calibration", 3, 3, 7, "uint:9", 9, 2, "adc_tp", "ADC1 850mV reading", None), - ('ADC2_TP_LOW', "calibration", 3, 3, 16, "uint:7", 9, 2, "adc_tp", "ADC2 150mV reading", None), - ('ADC2_TP_HIGH', "calibration", 3, 3, 23, "uint:9", 9, 2, "adc_tp", "ADC2 850mV reading", None), - ] - - CALC = [ - ("WAFER_VERSION_MAJOR", "identity", 0, None, None, "uint:3", None, None, "wafer", "calc WAFER VERSION MAJOR from CHIP_VER_REV1 and CHIP_VER_REV2 and apb_ctl_date (read only)", None), - ('PKG_VERSION', "identity", 0, None, None, "uint:4", None, None, "pkg", "calc Chip package = CHIP_PACKAGE_4BIT << 3 + CHIP_PACKAGE (read only)", None), - ] -# fmt: on + def __init__(self) -> None: + self.EFUSES = [] + # if MAC_VERSION is set "1", these efuse fields are in BLOCK3: + self.CUSTOM_MAC = [] + # The len of fields depends on coding scheme: for CODING_SCHEME_NONE + self.KEYBLOCKS_256 = [] + # The len of fields depends on coding scheme: for CODING_SCHEME_34 + self.KEYBLOCKS_192 = [] + # if BLK3_PART_RESERVE is set, these efuse fields are in BLOCK3: + self.ADC_CALIBRATION = [] + + self.CALC = [] + + dir_name = os.path.dirname(os.path.abspath(__file__)) + dir_name, file_name = os.path.split(dir_name) + file_name = file_name + ".yaml" + dir_name, _ = os.path.split(dir_name) + efuse_file = os.path.join(dir_name, "efuse_defs", file_name) + with open(f"{efuse_file}", "r") as r_file: + e_desc = yaml.safe_load(r_file) + super().__init__(e_desc) + + for i, efuse in enumerate(self.ALL_EFUSES): + if efuse.name == "BLOCK1" or efuse.name == "BLOCK2": + self.KEYBLOCKS_256.append(efuse) + BLOCK = copy.deepcopy(efuse) + BLOCK.type = "bytes:24" + BLOCK.bit_len = 24 * 8 + self.KEYBLOCKS_192.append(BLOCK) + self.ALL_EFUSES[i] = None + + elif efuse.name == "MAC_VERSION": + # A field from BLOCK3, It is used as a template + BLOCK3 = copy.deepcopy(efuse) + BLOCK3.name = "BLOCK3" + BLOCK3.block = 3 + BLOCK3.word = 0 + BLOCK3.pos = 0 + BLOCK3.bit_len = 32 * 8 + BLOCK3.type = "bytes:32" + BLOCK3.category = "security" + BLOCK3.class_type = "keyblock" + BLOCK3.description = "Variable Block 3" + self.KEYBLOCKS_256.append(BLOCK3) + + BLOCK3 = copy.deepcopy(BLOCK3) + BLOCK3.type = "bytes:24" + BLOCK3.bit_len = 24 * 8 + self.KEYBLOCKS_192.append(BLOCK3) + + elif efuse.category == "calibration" and efuse.block == 3: + self.ADC_CALIBRATION.append(efuse) + self.ALL_EFUSES[i] = None + + elif efuse.name in ["CUSTOM_MAC_CRC", "CUSTOM_MAC"]: + self.CUSTOM_MAC.append(efuse) + self.ALL_EFUSES[i] = None + + elif efuse.category == "spi pad": + efuse.class_type = "spipin" + + f = Field() + f.name = "WAFER_VERSION_MAJOR" + f.block = 0 + f.bit_len = 3 + f.type = f"uint:{f.bit_len}" + f.category = "identity" + f.class_type = "wafer" + f.description = "calc WAFER VERSION MAJOR from CHIP_VER_REV1 and CHIP_VER_REV2 and apb_ctl_date (read only)" + self.CALC.append(f) + + f = Field() + f.name = "PKG_VERSION" + f.block = 0 + f.bit_len = 4 + f.type = f"uint:{f.bit_len}" + f.category = "identity" + f.class_type = "pkg" + f.description = ( + "calc Chip package = CHIP_PACKAGE_4BIT << 3 + CHIP_PACKAGE (read only)" + ) + self.CALC.append(f) + + for efuse in self.ALL_EFUSES: + if efuse is not None: + self.EFUSES.append(efuse) + + self.ALL_EFUSES = [] diff --git a/espefuse/efuse/esp32/operations.py b/espefuse/efuse/esp32/operations.py index 69b288f4f..e0f419a1c 100644 --- a/espefuse/efuse/esp32/operations.py +++ b/espefuse/efuse/esp32/operations.py @@ -17,6 +17,7 @@ from ..base_operations import ( add_common_commands, add_force_write_always, + add_show_sensitive_info_option, burn_bit, burn_block_data, burn_efuse, @@ -42,6 +43,7 @@ def add_commands(subparsers, efuses): action="store_true", ) add_force_write_always(p) + add_show_sensitive_info_option(p) p.add_argument( "block", help='Key block to burn. "flash_encryption" (block1), ' @@ -89,6 +91,7 @@ def add_commands(subparsers, efuses): action="store_true", ) add_force_write_always(burn_key_digest) + add_show_sensitive_info_option(burn_key_digest) p = subparsers.add_parser( "set_flash_voltage", @@ -230,7 +233,14 @@ def burn_key(esp, efuses, args): if block_name in ("flash_encryption", "secure_boot_v1"): revers_msg = "\tReversing the byte order" data = data[::-1] - print(" - %s -> [%s]" % (efuse.name, util.hexify(data, " "))) + print(" - %s" % (efuse.name), end=" ") + print( + "-> [{}]".format( + util.hexify(data, " ") + if args.show_sensitive_info + else " ".join(["??"] * len(data)) + ) + ) if revers_msg: print(revers_msg) if len(data) != num_bytes: @@ -290,7 +300,14 @@ def burn_key_digest(esp, efuses, args): "Digest must be %d bytes (%d bits) of raw binary key data." % (len(digest), num_bytes, num_bytes * 8) ) - print(" - %s -> [%s]" % (efuse.name, util.hexify(digest, " "))) + print(" - %s" % (efuse.name), end=" ") + print( + "-> [{}]".format( + util.hexify(digest, " ") + if args.show_sensitive_info + else " ".join(["??"] * len(digest)) + ) + ) efuse.save(digest) if not args.no_protect_key: diff --git a/espefuse/efuse/esp32c2/emulate_efuse_controller.py b/espefuse/efuse/esp32c2/emulate_efuse_controller.py index 1a15f8496..26796dff8 100644 --- a/espefuse/efuse/esp32c2/emulate_efuse_controller.py +++ b/espefuse/efuse/esp32c2/emulate_efuse_controller.py @@ -18,13 +18,13 @@ class EmulateEfuseController(EmulateEfuseControllerBase): CHIP_NAME = "ESP32-C2" mem = None debug = False - Blocks = EfuseDefineBlocks - Fields = EfuseDefineFields - REGS = EfuseDefineRegisters def __init__(self, efuse_file=None, debug=False): + self.Blocks = EfuseDefineBlocks + self.Fields = EfuseDefineFields() + self.REGS = EfuseDefineRegisters super(EmulateEfuseController, self).__init__(efuse_file, debug) - self.write_reg(self.REGS.EFUSE_STATUS_REG, 1) + self.write_reg(self.REGS.EFUSE_CMD_REG, 0) """ esptool method start >>""" @@ -55,10 +55,10 @@ def handle_writing_event(self, addr, value): self.clean_blocks_wr_regs() self.check_rd_protection_area() self.write_reg(addr, 0) - self.write_reg(self.REGS.EFUSE_STATUS_REG, 1) + self.write_reg(self.REGS.EFUSE_CMD_REG, 0) elif value == self.REGS.EFUSE_READ_CMD: self.write_reg(addr, 0) - self.write_reg(self.REGS.EFUSE_STATUS_REG, 1) + self.write_reg(self.REGS.EFUSE_CMD_REG, 0) self.save_to_file() def get_bitlen_of_block(self, blk, wr=False): @@ -124,8 +124,7 @@ def get_read_disable_mask(blk): else: block.set(0) else: - for e in self.Fields.EFUSES: - field = self.Fields.get(e) + for field in self.Fields.EFUSES: if ( blk.id == field.block and field.read_disable_bit is not None diff --git a/espefuse/efuse/esp32c2/fields.py b/espefuse/efuse/esp32c2/fields.py index f05ee082d..dda997e58 100644 --- a/espefuse/efuse/esp32c2/fields.py +++ b/espefuse/efuse/esp32c2/fields.py @@ -54,16 +54,15 @@ class EspEfuses(base_fields.EspEfusesBase): Wrapper object to manage the efuse fields in a connected ESP bootloader """ - Blocks = EfuseDefineBlocks() - Fields = EfuseDefineFields() - REGS = EfuseDefineRegisters - BURN_BLOCK_DATA_NAMES = Blocks.get_burn_block_data_names() - BLOCKS_FOR_KEYS = Blocks.get_blocks_for_keys() - debug = False do_not_confirm = False def __init__(self, esp, skip_connect=False, debug=False, do_not_confirm=False): + self.Blocks = EfuseDefineBlocks() + self.Fields = EfuseDefineFields() + self.REGS = EfuseDefineRegisters + self.BURN_BLOCK_DATA_NAMES = self.Blocks.get_burn_block_data_names() + self.BLOCKS_FOR_KEYS = self.Blocks.get_blocks_for_keys() self._esp = esp self.debug = debug self.do_not_confirm = do_not_confirm @@ -85,53 +84,40 @@ def __init__(self, esp, skip_connect=False, debug=False, do_not_confirm=False): ] if not skip_connect: self.get_coding_scheme_warnings() - self.efuses = [ - EfuseField.from_tuple( - self, self.Fields.get(efuse), self.Fields.get(efuse).class_type - ) - for efuse in self.Fields.EFUSES - ] + self.efuses = [EfuseField.convert(self, efuse) for efuse in self.Fields.EFUSES] self.efuses += [ - EfuseField.from_tuple( - self, self.Fields.get(efuse), self.Fields.get(efuse).class_type - ) - for efuse in self.Fields.KEYBLOCKS + EfuseField.convert(self, efuse) for efuse in self.Fields.KEYBLOCKS ] if skip_connect: self.efuses += [ - EfuseField.from_tuple( - self, self.Fields.get(efuse), self.Fields.get(efuse).class_type - ) + EfuseField.convert(self, efuse) for efuse in self.Fields.BLOCK2_CALIBRATION_EFUSES ] else: if self["BLK_VERSION_MINOR"].get() == 1: self.efuses += [ - EfuseField.from_tuple( - self, self.Fields.get(efuse), self.Fields.get(efuse).class_type - ) + EfuseField.convert(self, efuse) for efuse in self.Fields.BLOCK2_CALIBRATION_EFUSES ] def __getitem__(self, efuse_name): """Return the efuse field with the given name""" for e in self.efuses: - if efuse_name == e.name: + if efuse_name == e.name or any(x == efuse_name for x in e.alt_names): return e new_fields = False for efuse in self.Fields.BLOCK2_CALIBRATION_EFUSES: - e = self.Fields.get(efuse) - if e.name == efuse_name: + if efuse.name == efuse_name or any( + x == efuse_name for x in efuse.alt_names + ): self.efuses += [ - EfuseField.from_tuple( - self, self.Fields.get(efuse), self.Fields.get(efuse).class_type - ) + EfuseField.convert(self, efuse) for efuse in self.Fields.BLOCK2_CALIBRATION_EFUSES ] new_fields = True if new_fields: for e in self.efuses: - if efuse_name == e.name: + if efuse_name == e.name or any(x == efuse_name for x in e.alt_names): return e raise KeyError @@ -147,10 +133,6 @@ def print_status_regs(self): ) ) - def get_block_errors(self, block_num): - """Returns (error count, failure boolean flag)""" - return self.blocks[block_num].num_errors, self.blocks[block_num].fail - def efuse_controller_setup(self): self.set_efuse_timing() self.clear_pgm_registers() @@ -170,9 +152,13 @@ def clear_pgm_registers(self): def wait_efuse_idle(self): deadline = time.time() + self.REGS.EFUSE_BURN_TIMEOUT while time.time() < deadline: - # if self.read_reg(self.REGS.EFUSE_CMD_REG) == 0: - if self.read_reg(self.REGS.EFUSE_STATUS_REG) & 0x7 == 1: - return + cmds = self.REGS.EFUSE_PGM_CMD | self.REGS.EFUSE_READ_CMD + if self.read_reg(self.REGS.EFUSE_CMD_REG) & cmds == 0: + if self.read_reg(self.REGS.EFUSE_CMD_REG) & cmds == 0: + # Due to a hardware error, we have to read READ_CMD again + # to make sure the efuse clock is normal. + # For PGM_CMD it is not necessary. + return raise esptool.FatalError( "Timed out waiting for Efuse controller command to complete" ) @@ -238,6 +224,13 @@ def set_efuse_timing(self): "The eFuse supports only xtal=26M and 40M (xtal was %d)" % xtal_freq ) + self.update_reg(self.REGS.EFUSE_DAC_CONF_REG, self.REGS.EFUSE_DAC_NUM_M, 0xFF) + self.update_reg( + self.REGS.EFUSE_DAC_CONF_REG, self.REGS.EFUSE_DAC_CLK_DIV_M, 0x28 + ) + self.update_reg( + self.REGS.EFUSE_WR_TIM_CONF1_REG, self.REGS.EFUSE_PWR_ON_NUM_M, 0x3000 + ) self.update_reg( self.REGS.EFUSE_WR_TIM_CONF2_REG, self.REGS.EFUSE_PWR_OFF_NUM_M, 0x190 ) @@ -260,12 +253,9 @@ def get_coding_scheme_warnings(self, silent=False): self.read_reg(self.REGS.EFUSE_RD_REPEAT_ERR_REG + offs * 4) for offs in range(1) ] - data = BitArray() + block.err_bitarray.pos = 0 for word in reversed(words): - data.append("uint:32=%d" % word) - # pos=32 because EFUSE_WR_DIS goes first it is 32bit long - # and not under error control - block.err_bitarray.overwrite(data, pos=32) + block.err_bitarray.overwrite(BitArray("uint:32=%d" % word)) block.num_errors = block.err_bitarray.count(True) block.fail = block.num_errors != 0 else: @@ -296,28 +286,13 @@ def summary(self): class EfuseField(base_fields.EfuseFieldBase): @staticmethod - def from_tuple(parent, efuse_tuple, type_class): + def convert(parent, efuse): return { "mac": EfuseMacField, "keypurpose": EfuseKeyPurposeField, "t_sensor": EfuseTempSensor, "adc_tp": EfuseAdcPointCalibration, - }.get(type_class, EfuseField)(parent, efuse_tuple) - - def get_info(self): - output = "%s (BLOCK%d)" % (self.name, self.block) - errs, fail = self.parent.get_block_errors(self.block) - if errs != 0 or fail: - output += ( - "[FAIL:%d]" % (fail) - if self.block == 0 - else "[ERRS:%d FAIL:%d]" % (errs, fail) - ) - if self.efuse_class == "keyblock": - name = self.parent.blocks[self.block].key_purpose_name - if name is not None: - output += "\n Purpose: %s\n " % (self.parent[name].get()) - return output + }.get(efuse.class_type, EfuseField)(parent, efuse) class EfuseTempSensor(EfuseField): @@ -393,22 +368,13 @@ def print_field(e, new_value): class EfuseKeyPurposeField(EfuseField): KEY_PURPOSES = [ - ("USER", 0, None), # User purposes (software-only use) - ( - "XTS_AES_128_KEY", - 1, - None, - ), # (whole 256bits) XTS_AES_128_KEY (flash/PSRAM encryption) - ( - "XTS_AES_128_KEY_DERIVED_FROM_128_EFUSE_BITS", - 2, - None, - ), # (lo 128bits) XTS_AES_128_KEY (flash/PSRAM encryption) - ( - "SECURE_BOOT_DIGEST", - 3, - "DIGEST", - ), # (hi 128bits)SECURE_BOOT_DIGEST (Secure Boot key digest) + # fmt: off + ("USER", 0, None), # User purposes (software-only use) + ("XTS_AES_128_KEY", 1, None), # (whole 256bits) flash/PSRAM encryption + ("XTS_AES_128_KEY_DERIVED_FROM_128_EFUSE_BITS", 2, None), # (lo 128bits) flash/PSRAM encryption + ("SECURE_BOOT_DIGEST", 3, "DIGEST"), + # (hi 128bits) Secure Boot key digest + # fmt: on ] KEY_PURPOSES_NAME = [name[0] for name in KEY_PURPOSES] diff --git a/espefuse/efuse/esp32c2/mem_definition.py b/espefuse/efuse/esp32c2/mem_definition.py index 0127ddc7a..7adb0111f 100644 --- a/espefuse/efuse/esp32c2/mem_definition.py +++ b/espefuse/efuse/esp32c2/mem_definition.py @@ -4,36 +4,43 @@ # # SPDX-License-Identifier: GPL-2.0-or-later -from ..mem_definition_base import EfuseBlocksBase, EfuseFieldsBase, EfuseRegistersBase +import copy +import os +import yaml + +from ..mem_definition_base import ( + EfuseBlocksBase, + EfuseFieldsBase, + EfuseRegistersBase, +) -# fmt: off -class EfuseDefineRegisters(EfuseRegistersBase): - EFUSE_MEM_SIZE = (0x01FC + 4) +class EfuseDefineRegisters(EfuseRegistersBase): + EFUSE_MEM_SIZE = 0x01FC + 4 # EFUSE registers & command/conf values - DR_REG_EFUSE_BASE = 0x60008800 - EFUSE_PGM_DATA0_REG = DR_REG_EFUSE_BASE - EFUSE_PGM_CHECK_VALUE0_REG = DR_REG_EFUSE_BASE + 0x020 - EFUSE_CLK_REG = DR_REG_EFUSE_BASE + 0x88 - EFUSE_CONF_REG = DR_REG_EFUSE_BASE + 0x8C - EFUSE_STATUS_REG = DR_REG_EFUSE_BASE + 0x90 - EFUSE_CMD_REG = DR_REG_EFUSE_BASE + 0x94 + DR_REG_EFUSE_BASE = 0x60008800 + EFUSE_PGM_DATA0_REG = DR_REG_EFUSE_BASE + EFUSE_PGM_CHECK_VALUE0_REG = DR_REG_EFUSE_BASE + 0x020 + EFUSE_CLK_REG = DR_REG_EFUSE_BASE + 0x88 + EFUSE_CONF_REG = DR_REG_EFUSE_BASE + 0x8C + EFUSE_STATUS_REG = DR_REG_EFUSE_BASE + 0x90 + EFUSE_CMD_REG = DR_REG_EFUSE_BASE + 0x94 EFUSE_RD_REPEAT_ERR_REG = DR_REG_EFUSE_BASE + 0x80 - EFUSE_RD_RS_ERR_REG = DR_REG_EFUSE_BASE + 0x84 - EFUSE_WRITE_OP_CODE = 0x5A5A - EFUSE_READ_OP_CODE = 0x5AA5 - EFUSE_PGM_CMD_MASK = 0x3 - EFUSE_PGM_CMD = 0x2 - EFUSE_READ_CMD = 0x1 + EFUSE_RD_RS_ERR_REG = DR_REG_EFUSE_BASE + 0x84 + EFUSE_WRITE_OP_CODE = 0x5A5A + EFUSE_READ_OP_CODE = 0x5AA5 + EFUSE_PGM_CMD_MASK = 0x3 + EFUSE_PGM_CMD = 0x2 + EFUSE_READ_CMD = 0x1 BLOCK_ERRORS = [ # error_reg, err_num_mask, err_num_offs, fail_bit - (EFUSE_RD_REPEAT_ERR_REG, None, None, None), # BLOCK0 - (EFUSE_RD_RS_ERR_REG, 0x7, 0, 3), # BLOCK1 - (EFUSE_RD_RS_ERR_REG, 0x7, 4, 7), # BLOCK2 - (EFUSE_RD_RS_ERR_REG, 0x7, 8, 11), # BLOCK3 + (EFUSE_RD_REPEAT_ERR_REG, None, None, None), # BLOCK0 + (EFUSE_RD_RS_ERR_REG, 0x7, 0, 3), # BLOCK1 + (EFUSE_RD_RS_ERR_REG, 0x7, 4, 7), # BLOCK2 + (EFUSE_RD_RS_ERR_REG, 0x7, 8, 11), # BLOCK3 ] EFUSE_WR_TIM_CONF2_REG = DR_REG_EFUSE_BASE + 0x118 @@ -44,12 +51,24 @@ class EfuseDefineRegisters(EfuseRegistersBase): EFUSE_TPGM_INACTIVE_S = 8 EFUSE_TPGM_INACTIVE_M = 0xFF << EFUSE_TPGM_INACTIVE_S + EFUSE_WR_TIM_CONF1_REG = DR_REG_EFUSE_BASE + 0x114 + EFUSE_PWR_ON_NUM_S = 8 + EFUSE_PWR_ON_NUM_M = 0x0000FFFF << EFUSE_PWR_ON_NUM_S -class EfuseDefineBlocks(EfuseBlocksBase): + EFUSE_DAC_CONF_REG = DR_REG_EFUSE_BASE + 0x108 + EFUSE_DAC_CLK_DIV_S = 0 + EFUSE_DAC_CLK_DIV_M = 0xFF << EFUSE_DAC_CLK_DIV_S + # EFUSE_DAC_CONF_REG + EFUSE_DAC_NUM_S = 9 + EFUSE_DAC_NUM_M = 0xFF << EFUSE_DAC_NUM_S + + +class EfuseDefineBlocks(EfuseBlocksBase): __base_rd_regs = EfuseDefineRegisters.DR_REG_EFUSE_BASE __base_wr_regs = EfuseDefineRegisters.EFUSE_PGM_DATA0_REG # List of efuse blocks + # fmt: off BLOCKS = [ # Name, Alias, Index, Read address, Write address, Write protect bit, Read protect bit, Len, key_purpose ("BLOCK0", ["BLOCK0"], 0, __base_rd_regs + 0x02C, __base_wr_regs, None, None, 2, None), @@ -57,6 +76,7 @@ class EfuseDefineBlocks(EfuseBlocksBase): ("BLOCK2", ["BLOCK2"], 2, __base_rd_regs + 0x040, __base_wr_regs, 6, None, 8, None), ("BLOCK_KEY0", ["BLOCK3"], 3, __base_rd_regs + 0x060, __base_wr_regs, 7, [0, 1], 8, None), ] + # fmt: on def get_burn_block_data_names(self): list_of_names = [] @@ -70,87 +90,58 @@ def get_burn_block_data_names(self): return list_of_names def get_blocks_for_keys(self): - return ['BLOCK_KEY0'] + return ["BLOCK_KEY0"] class EfuseDefineFields(EfuseFieldsBase): - - # List of efuse fields from TRM the chapter eFuse Controller. - EFUSES = [ - # - # Parameters in BLOCK0 - # Name Category Block Word Pos Type:len WR_DIS RD_DIS Class Description Dictionary - ("WR_DIS", "efuse", 0, 0, 0, "uint:8", None, None, None, "Disables programming of individual eFuses", None), - ("RD_DIS", "efuse", 0, 1, 0, "uint:2", 0, None, None, "Disables software reading from BLOCK3", None), - ("WDT_DELAY_SEL", "WDT config", 0, 1, 2, "uint:2", 1, None, None, "RTC WDT timeout threshold", None), - ("DIS_PAD_JTAG", "jtag config", 0, 1, 4, "bool", 1, None, None, "Permanently disable JTAG access via pads" - "USB JTAG is controlled separately", None), - ("DIS_DOWNLOAD_ICACHE", "security", 0, 1, 5, "bool", 1, None, None, "Disables iCache in download mode", None), - ("DIS_DOWNLOAD_MANUAL_ENCRYPT", "security", 0, 1, 6, "bool", 2, None, None, "Disables flash encryption in Download boot modes", - None), - ("SPI_BOOT_CRYPT_CNT", "security", 0, 1, 7, "uint:3", 2, None, None, "Enables encryption and decryption, when an SPI boot" - "mode is set. Enabled when 1 or 3 bits are set," - "disabled otherwise", - {0: "Disable", - 1: "Enable", - 3: "Disable", - 7: "Enable"}), - ("XTS_KEY_LENGTH_256", "security", 0, 1, 10, "bool", 2, None, None, "Flash encryption key length", - {0: "128 bits key", - 1: "256 bits key"}), - ("UART_PRINT_CONTROL", "config", 0, 1, 11, "uint:2", 3, None, None, "Set UART boot message output mode", - {0: "Force print", - 1: "Low-level print controlled by GPIO 8", - 3: "High-level print controlled by GPIO 8", - 7: "Print force disabled"}), - ("FORCE_SEND_RESUME", "config", 0, 1, 13, "bool", 3, None, None, "Force ROM code to send a resume cmd during SPI boot", - None), - ("DIS_DOWNLOAD_MODE", "security", 0, 1, 14, "bool", 3, None, None, "Disables all Download boot modes", None), - ("DIS_DIRECT_BOOT", "config", 0, 1, 15, "bool", 3, None, None, "Disable direct_boot mode", None), - ("ENABLE_SECURITY_DOWNLOAD", "security", 0, 1, 16, "bool", 3, None, None, "Enables secure UART download mode " - "(read/write flash only)", None), - ("FLASH_TPUW", "flash config", 0, 1, 17, "uint:4", 3, None, None, "Configures flash startup delay after SoC power-up, " - "unit is (ms/2). When the value is 15, delay is 7.5 ms", - None), - ("SECURE_BOOT_EN", "security", 0, 1, 21, "bool", 2, None, None, "Configures secure boot", None), - ("SECURE_VERSION", "identity", 0, 1, 22, "uint:4", 4, None, "bitcount", "Secure version (anti-rollback feature)", None), - ("CUSTOM_MAC_USED", "identity", 0, 1, 26, "bool", 4, None, None, "Enable CUSTOM_MAC programming", None), - ("DISABLE_WAFER_VERSION_MAJOR", "config", 0, 1, 27, "bool", 4, None, None, "Disables check of wafer version major", None), - ("DISABLE_BLK_VERSION_MAJOR", "config", 0, 1, 28, "bool", 4, None, None, "Disables check of blk version major", None), - - # - # Parameters in BLOCK1 - # Name Category Block Word Pos Type:len WR_DIS RD_DIS Class Description Dictionary - ("CUSTOM_MAC", "identity", 1, 0, 0, "bytes:6", 5, None, 'mac', "Custom MAC addr", None), - - # - # Parameters in BLOCK2 - # Name Category Block Word Pos Type:len WR_DIS RD_DIS Class Description Dictionary - ("MAC", "identity", 2, 0, 0, "bytes:6", 6, None, 'mac', "Factory MAC Address", None), - ("WAFER_VERSION_MINOR", "identity", 2, 1, 16, "uint:4", 6, None, None, "Minor WAFER version", None), - ("WAFER_VERSION_MAJOR", "identity", 2, 1, 20, "uint:2", 6, None, None, "Major WAFER version", None), - ("PKG_VERSION", "identity", 2, 1, 22, "uint:3", 6, None, None, "Package version", None), - ("BLK_VERSION_MINOR", "identity", 2, 1, 25, "uint:3", 6, None, None, "Minor version of BLOCK2", - {0: "No calibration", 1: "With calibration"}), - - ("BLK_VERSION_MAJOR", "identity", 2, 1, 28, "uint:2", 6, None, None, "Major version of BLOCK2", None), - ("LDO_VOL_BIAS_CONFIG_HIGH", "ldo", 2, 2, 0, "uint:27", 6, None, None, "", None), - ("PVT_LOW", "pvt", 2, 2, 27, "uint:5", 6, None, None, "", None), - ("PVT_HIGH", "pvt", 2, 3, 0, "uint:10", 6, None, None, "", None), - ("ADC_CALIBRATION_0", "adc_calib", 2, 3, 10, "uint:22", 6, None, None, "", None), - ("ADC_CALIBRATION_1", "adc_calib", 2, 4, 0, "uint:32", 6, None, None, "", None), - ("ADC_CALIBRATION_2", "adc_calib", 2, 5, 0, "uint:32", 6, None, None, "", None), - ] - - KEYBLOCKS = [ - # Name Category Block Word Pos Type:len WR_DIS RD_DIS Class Description Dictionary - ('BLOCK_KEY0', "security", 3, 0, 0, "bytes:32", 7, [0, 1], "keyblock", "BLOCK_KEY0 - 256-bits. 256-bit key of Flash Encryption", None), - ('BLOCK_KEY0_LOW_128', "security", 3, 0, 0, "bytes:16", 7, 0, "keyblock", "BLOCK_KEY0 - lower 128-bits. 128-bit key of Flash Encryption", None), - ('BLOCK_KEY0_HI_128', "security", 3, 4, 0, "bytes:16", 7, 1, "keyblock", "BLOCK_KEY0 - higher 128-bits. 128-bits key of Secure Boot.", None), - ] - - # if BLK_VERSION_MINOR is 1, these efuse fields are in BLOCK2 - BLOCK2_CALIBRATION_EFUSES = [ - # Name Category Block Word Pos Type:len WR_DIS RD_DIS Class Description Dictionary - ] -# fmt: on + def __init__(self) -> None: + # List of efuse fields from TRM the chapter eFuse Controller. + self.EFUSES = [] + + self.KEYBLOCKS = [] + + # if BLK_VERSION_MINOR is 1, these efuse fields are in BLOCK2 + self.BLOCK2_CALIBRATION_EFUSES = [] + + dir_name = os.path.dirname(os.path.abspath(__file__)) + dir_name, file_name = os.path.split(dir_name) + file_name = file_name + ".yaml" + dir_name, _ = os.path.split(dir_name) + efuse_file = os.path.join(dir_name, "efuse_defs", file_name) + with open(f"{efuse_file}", "r") as r_file: + e_desc = yaml.safe_load(r_file) + super().__init__(e_desc) + + for i, efuse in enumerate(self.ALL_EFUSES): + if efuse.name in ["BLOCK_KEY0"]: + self.KEYBLOCKS.append(efuse) + BLOCK_KEY0_LOW_128 = copy.deepcopy(efuse) + BLOCK_KEY0_LOW_128.name = "BLOCK_KEY0_LOW_128" + BLOCK_KEY0_LOW_128.type = "bytes:16" + BLOCK_KEY0_LOW_128.bit_len = 16 * 8 + BLOCK_KEY0_LOW_128.description = ( + "BLOCK_KEY0 - lower 128-bits. 128-bit key of Flash Encryption" + ) + BLOCK_KEY0_LOW_128.read_disable_bit = efuse.read_disable_bit[0] + self.KEYBLOCKS.append(BLOCK_KEY0_LOW_128) + BLOCK_KEY0_HI_128 = copy.deepcopy(efuse) + BLOCK_KEY0_HI_128.name = "BLOCK_KEY0_HI_128" + BLOCK_KEY0_HI_128.word = 4 + BLOCK_KEY0_HI_128.type = "bytes:16" + BLOCK_KEY0_HI_128.bit_len = 16 * 8 + BLOCK_KEY0_HI_128.description = ( + "BLOCK_KEY0 - higher 128-bits. 128-bits key of Secure Boot" + ) + BLOCK_KEY0_HI_128.read_disable_bit = efuse.read_disable_bit[1] + self.KEYBLOCKS.append(BLOCK_KEY0_HI_128) + self.ALL_EFUSES[i] = None + + elif efuse.category == "calibration": + self.BLOCK2_CALIBRATION_EFUSES.append(efuse) + self.ALL_EFUSES[i] = None + + for efuse in self.ALL_EFUSES: + if efuse is not None: + self.EFUSES.append(efuse) + + self.ALL_EFUSES = [] diff --git a/espefuse/efuse/esp32c2/operations.py b/espefuse/efuse/esp32c2/operations.py index 3fc19dcc8..fb7324e97 100644 --- a/espefuse/efuse/esp32c2/operations.py +++ b/espefuse/efuse/esp32c2/operations.py @@ -17,6 +17,7 @@ from ..base_operations import ( add_common_commands, add_force_write_always, + add_show_sensitive_info_option, burn_bit, burn_block_data, burn_efuse, @@ -52,6 +53,7 @@ def add_commands(subparsers, efuses): ) protect_options(burn_key) add_force_write_always(burn_key) + add_show_sensitive_info_option(burn_key) burn_key.add_argument( "block", help="Key block to burn", @@ -103,6 +105,7 @@ def add_commands(subparsers, efuses): ) protect_options(burn_key_digest) add_force_write_always(burn_key_digest) + add_show_sensitive_info_option(burn_key_digest) burn_key_digest.add_argument( "keyfile", help="Key file to digest (PEM format)", type=argparse.FileType("rb") ) @@ -239,7 +242,13 @@ def burn_key(esp, efuses, args, digest=None): if keypurpose.startswith("XTS_AES_"): revers_msg = "\tReversing byte order for AES-XTS hardware peripheral" data = data[::-1] - print("-> [%s]" % (util.hexify(data, " "))) + print( + "-> [{}]".format( + util.hexify(data, " ") + if args.show_sensitive_info + else " ".join(["??"] * len(data)) + ) + ) if revers_msg: print(revers_msg) if len(data) != num_bytes: diff --git a/espefuse/efuse/esp32c3/emulate_efuse_controller.py b/espefuse/efuse/esp32c3/emulate_efuse_controller.py index 71381a23d..2d812a10d 100644 --- a/espefuse/efuse/esp32c3/emulate_efuse_controller.py +++ b/espefuse/efuse/esp32c3/emulate_efuse_controller.py @@ -16,13 +16,13 @@ class EmulateEfuseController(EmulateEfuseControllerBase): CHIP_NAME = "ESP32-C3" mem = None debug = False - Blocks = EfuseDefineBlocks - Fields = EfuseDefineFields - REGS = EfuseDefineRegisters def __init__(self, efuse_file=None, debug=False): + self.Blocks = EfuseDefineBlocks + self.Fields = EfuseDefineFields() + self.REGS = EfuseDefineRegisters super(EmulateEfuseController, self).__init__(efuse_file, debug) - self.write_reg(self.REGS.EFUSE_STATUS_REG, 1) + self.write_reg(self.REGS.EFUSE_CMD_REG, 0) """ esptool method start >>""" @@ -53,10 +53,10 @@ def handle_writing_event(self, addr, value): self.clean_blocks_wr_regs() self.check_rd_protection_area() self.write_reg(addr, 0) - self.write_reg(self.REGS.EFUSE_STATUS_REG, 1) + self.write_reg(self.REGS.EFUSE_CMD_REG, 0) elif value == self.REGS.EFUSE_READ_CMD: self.write_reg(addr, 0) - self.write_reg(self.REGS.EFUSE_STATUS_REG, 1) + self.write_reg(self.REGS.EFUSE_CMD_REG, 0) self.save_to_file() def get_bitlen_of_block(self, blk, wr=False): diff --git a/espefuse/efuse/esp32c3/fields.py b/espefuse/efuse/esp32c3/fields.py index 48ab06249..7a09c65c5 100644 --- a/espefuse/efuse/esp32c3/fields.py +++ b/espefuse/efuse/esp32c3/fields.py @@ -54,16 +54,15 @@ class EspEfuses(base_fields.EspEfusesBase): Wrapper object to manage the efuse fields in a connected ESP bootloader """ - Blocks = EfuseDefineBlocks() - Fields = EfuseDefineFields() - REGS = EfuseDefineRegisters - BURN_BLOCK_DATA_NAMES = Blocks.get_burn_block_data_names() - BLOCKS_FOR_KEYS = Blocks.get_blocks_for_keys() - debug = False do_not_confirm = False def __init__(self, esp, skip_connect=False, debug=False, do_not_confirm=False): + self.Blocks = EfuseDefineBlocks() + self.Fields = EfuseDefineFields() + self.REGS = EfuseDefineRegisters + self.BURN_BLOCK_DATA_NAMES = self.Blocks.get_burn_block_data_names() + self.BLOCKS_FOR_KEYS = self.Blocks.get_blocks_for_keys() self._esp = esp self.debug = debug self.do_not_confirm = do_not_confirm @@ -85,59 +84,43 @@ def __init__(self, esp, skip_connect=False, debug=False, do_not_confirm=False): ] if not skip_connect: self.get_coding_scheme_warnings() - self.efuses = [ - EfuseField.from_tuple( - self, self.Fields.get(efuse), self.Fields.get(efuse).class_type - ) - for efuse in self.Fields.EFUSES - ] + self.efuses = [EfuseField.convert(self, efuse) for efuse in self.Fields.EFUSES] self.efuses += [ - EfuseField.from_tuple( - self, self.Fields.get(efuse), self.Fields.get(efuse).class_type - ) - for efuse in self.Fields.KEYBLOCKS + EfuseField.convert(self, efuse) for efuse in self.Fields.KEYBLOCKS ] if skip_connect: self.efuses += [ - EfuseField.from_tuple( - self, self.Fields.get(efuse), self.Fields.get(efuse).class_type - ) + EfuseField.convert(self, efuse) for efuse in self.Fields.BLOCK2_CALIBRATION_EFUSES ] else: if self["BLK_VERSION_MAJOR"].get() == 1: self.efuses += [ - EfuseField.from_tuple( - self, self.Fields.get(efuse), self.Fields.get(efuse).class_type - ) + EfuseField.convert(self, efuse) for efuse in self.Fields.BLOCK2_CALIBRATION_EFUSES ] self.efuses += [ - EfuseField.from_tuple( - self, self.Fields.get(efuse), self.Fields.get(efuse).class_type - ) - for efuse in self.Fields.CALC + EfuseField.convert(self, efuse) for efuse in self.Fields.CALC ] def __getitem__(self, efuse_name): """Return the efuse field with the given name""" for e in self.efuses: - if efuse_name == e.name: + if efuse_name == e.name or any(x == efuse_name for x in e.alt_names): return e new_fields = False for efuse in self.Fields.BLOCK2_CALIBRATION_EFUSES: - e = self.Fields.get(efuse) - if e.name == efuse_name: + if efuse.name == efuse_name or any( + x == efuse_name for x in efuse.alt_names + ): self.efuses += [ - EfuseField.from_tuple( - self, self.Fields.get(efuse), self.Fields.get(efuse).class_type - ) + EfuseField.convert(self, efuse) for efuse in self.Fields.BLOCK2_CALIBRATION_EFUSES ] new_fields = True if new_fields: for e in self.efuses: - if efuse_name == e.name: + if efuse_name == e.name or any(x == efuse_name for x in e.alt_names): return e raise KeyError @@ -158,10 +141,6 @@ def print_status_regs(self): ) ) - def get_block_errors(self, block_num): - """Returns (error count, failure boolean flag)""" - return self.blocks[block_num].num_errors, self.blocks[block_num].fail - def efuse_controller_setup(self): self.set_efuse_timing() self.clear_pgm_registers() @@ -181,9 +160,13 @@ def clear_pgm_registers(self): def wait_efuse_idle(self): deadline = time.time() + self.REGS.EFUSE_BURN_TIMEOUT while time.time() < deadline: - # if self.read_reg(self.REGS.EFUSE_CMD_REG) == 0: - if self.read_reg(self.REGS.EFUSE_STATUS_REG) & 0x7 == 1: - return + cmds = self.REGS.EFUSE_PGM_CMD | self.REGS.EFUSE_READ_CMD + if self.read_reg(self.REGS.EFUSE_CMD_REG) & cmds == 0: + if self.read_reg(self.REGS.EFUSE_CMD_REG) & cmds == 0: + # Due to a hardware error, we have to read READ_CMD again + # to make sure the efuse clock is normal. + # For PGM_CMD it is not necessary. + return raise esptool.FatalError( "Timed out waiting for Efuse controller command to complete" ) @@ -249,6 +232,13 @@ def set_efuse_timing(self): "The eFuse supports only xtal=40M (xtal was %d)" % apb_freq ) + self.update_reg(self.REGS.EFUSE_DAC_CONF_REG, self.REGS.EFUSE_DAC_NUM_M, 0xFF) + self.update_reg( + self.REGS.EFUSE_DAC_CONF_REG, self.REGS.EFUSE_DAC_CLK_DIV_M, 0x28 + ) + self.update_reg( + self.REGS.EFUSE_WR_TIM_CONF1_REG, self.REGS.EFUSE_PWR_ON_NUM_M, 0x3000 + ) self.update_reg( self.REGS.EFUSE_WR_TIM_CONF2_REG, self.REGS.EFUSE_PWR_OFF_NUM_M, 0x190 ) @@ -262,12 +252,9 @@ def get_coding_scheme_warnings(self, silent=False): self.read_reg(self.REGS.EFUSE_RD_REPEAT_ERR0_REG + offs * 4) for offs in range(5) ] - data = BitArray() + block.err_bitarray.pos = 0 for word in reversed(words): - data.append("uint:32=%d" % word) - # pos=32 because EFUSE_WR_DIS goes first it is 32bit long - # and not under error control - block.err_bitarray.overwrite(data, pos=32) + block.err_bitarray.overwrite(BitArray("uint:32=%d" % word)) block.num_errors = block.err_bitarray.count(True) block.fail = block.num_errors != 0 else: @@ -302,35 +289,22 @@ def summary(self): class EfuseField(base_fields.EfuseFieldBase): @staticmethod - def from_tuple(parent, efuse_tuple, type_class): + def convert(parent, efuse): return { "mac": EfuseMacField, "keypurpose": EfuseKeyPurposeField, "t_sensor": EfuseTempSensor, "adc_tp": EfuseAdcPointCalibration, "wafer": EfuseWafer, - }.get(type_class, EfuseField)(parent, efuse_tuple) - - def get_info(self): - output = "%s (BLOCK%d)" % (self.name, self.block) - errs, fail = self.parent.get_block_errors(self.block) - if errs != 0 or fail: - output += ( - "[FAIL:%d]" % (fail) - if self.block == 0 - else "[ERRS:%d FAIL:%d]" % (errs, fail) - ) - if self.efuse_class == "keyblock": - name = self.parent.blocks[self.block].key_purpose_name - if name is not None: - output += "\n Purpose: %s\n " % (self.parent[name].get()) - return output + }.get(efuse.class_type, EfuseField)(parent, efuse) class EfuseWafer(EfuseField): def get(self, from_read=True): hi_bits = self.parent["WAFER_VERSION_MINOR_HI"].get(from_read) + assert self.parent["WAFER_VERSION_MINOR_HI"].bit_len == 1 lo_bits = self.parent["WAFER_VERSION_MINOR_LO"].get(from_read) + assert self.parent["WAFER_VERSION_MINOR_LO"].bit_len == 3 return (hi_bits << 3) + lo_bits def save(self, new_value): @@ -459,6 +433,14 @@ def get(self, from_read=True): return p[0] return "FORBIDDEN_STATE" + def get_name(self, raw_val): + for key in self.KEY_PURPOSES: + if key[1] == raw_val: + return key[0] + def save(self, new_value): raw_val = int(self.check_format(str(new_value))) + str_new_value = self.get_name(raw_val) + if self.name == "KEY_PURPOSE_5" and str_new_value.startswith("XTS_AES"): + raise esptool.FatalError(f"{self.name} can not have {str_new_value} key due to a hardware bug (please see TRM for more details)") return super(EfuseKeyPurposeField, self).save(raw_val) diff --git a/espefuse/efuse/esp32c3/mem_definition.py b/espefuse/efuse/esp32c3/mem_definition.py index a0405a13b..610d64e17 100644 --- a/espefuse/efuse/esp32c3/mem_definition.py +++ b/espefuse/efuse/esp32c3/mem_definition.py @@ -4,24 +4,31 @@ # # SPDX-License-Identifier: GPL-2.0-or-later -from ..mem_definition_base import EfuseBlocksBase, EfuseFieldsBase, EfuseRegistersBase +import os +import yaml + +from ..mem_definition_base import ( + EfuseBlocksBase, + EfuseFieldsBase, + EfuseRegistersBase, + Field, +) -# fmt: off -class EfuseDefineRegisters(EfuseRegistersBase): - EFUSE_MEM_SIZE = (0x01FC + 4) +class EfuseDefineRegisters(EfuseRegistersBase): + EFUSE_MEM_SIZE = 0x01FC + 4 # EFUSE registers & command/conf values - DR_REG_EFUSE_BASE = 0x60008800 - EFUSE_PGM_DATA0_REG = DR_REG_EFUSE_BASE - EFUSE_CHECK_VALUE0_REG = DR_REG_EFUSE_BASE + 0x020 - EFUSE_CLK_REG = DR_REG_EFUSE_BASE + 0x1C8 - EFUSE_CONF_REG = DR_REG_EFUSE_BASE + 0x1CC - EFUSE_STATUS_REG = DR_REG_EFUSE_BASE + 0x1D0 - EFUSE_CMD_REG = DR_REG_EFUSE_BASE + 0x1D4 - EFUSE_RD_RS_ERR0_REG = DR_REG_EFUSE_BASE + 0x1C0 - EFUSE_RD_RS_ERR1_REG = DR_REG_EFUSE_BASE + 0x1C4 + DR_REG_EFUSE_BASE = 0x60008800 + EFUSE_PGM_DATA0_REG = DR_REG_EFUSE_BASE + EFUSE_CHECK_VALUE0_REG = DR_REG_EFUSE_BASE + 0x020 + EFUSE_CLK_REG = DR_REG_EFUSE_BASE + 0x1C8 + EFUSE_CONF_REG = DR_REG_EFUSE_BASE + 0x1CC + EFUSE_STATUS_REG = DR_REG_EFUSE_BASE + 0x1D0 + EFUSE_CMD_REG = DR_REG_EFUSE_BASE + 0x1D4 + EFUSE_RD_RS_ERR0_REG = DR_REG_EFUSE_BASE + 0x1C0 + EFUSE_RD_RS_ERR1_REG = DR_REG_EFUSE_BASE + 0x1C4 EFUSE_RD_REPEAT_ERR0_REG = DR_REG_EFUSE_BASE + 0x17C EFUSE_RD_REPEAT_ERR1_REG = DR_REG_EFUSE_BASE + 0x180 EFUSE_RD_REPEAT_ERR2_REG = DR_REG_EFUSE_BASE + 0x184 @@ -32,53 +39,65 @@ class EfuseDefineRegisters(EfuseRegistersBase): EFUSE_WR_TIM_CONF1_REG = DR_REG_EFUSE_BASE + 0x1F0 EFUSE_WR_TIM_CONF2_REG = DR_REG_EFUSE_BASE + 0x1F4 EFUSE_DATE_REG = DR_REG_EFUSE_BASE + 0x1FC - EFUSE_WRITE_OP_CODE = 0x5A5A - EFUSE_READ_OP_CODE = 0x5AA5 - EFUSE_PGM_CMD_MASK = 0x3 - EFUSE_PGM_CMD = 0x2 - EFUSE_READ_CMD = 0x1 + EFUSE_WRITE_OP_CODE = 0x5A5A + EFUSE_READ_OP_CODE = 0x5AA5 + EFUSE_PGM_CMD_MASK = 0x3 + EFUSE_PGM_CMD = 0x2 + EFUSE_READ_CMD = 0x1 # this chip has a design error so fail_bit is shifted by one block but err_num is in the correct place BLOCK_FAIL_BIT = [ # error_reg, fail_bit - (EFUSE_RD_REPEAT_ERR0_REG, None), # BLOCK0 - (EFUSE_RD_RS_ERR0_REG, 7), # MAC_SPI_8M_0 - (EFUSE_RD_RS_ERR0_REG, 11), # BLOCK_SYS_DATA - (EFUSE_RD_RS_ERR0_REG, 15), # BLOCK_USR_DATA - (EFUSE_RD_RS_ERR0_REG, 19), # BLOCK_KEY0 - (EFUSE_RD_RS_ERR0_REG, 23), # BLOCK_KEY1 - (EFUSE_RD_RS_ERR0_REG, 27), # BLOCK_KEY2 - (EFUSE_RD_RS_ERR0_REG, 31), # BLOCK_KEY3 - (EFUSE_RD_RS_ERR1_REG, 3), # BLOCK_KEY4 - (EFUSE_RD_RS_ERR1_REG, 7), # BLOCK_KEY5 - (EFUSE_RD_RS_ERR1_REG, None), # BLOCK_SYS_DATA2 + (EFUSE_RD_REPEAT_ERR0_REG, None), # BLOCK0 + (EFUSE_RD_RS_ERR0_REG, 7), # MAC_SPI_8M_0 + (EFUSE_RD_RS_ERR0_REG, 11), # BLOCK_SYS_DATA + (EFUSE_RD_RS_ERR0_REG, 15), # BLOCK_USR_DATA + (EFUSE_RD_RS_ERR0_REG, 19), # BLOCK_KEY0 + (EFUSE_RD_RS_ERR0_REG, 23), # BLOCK_KEY1 + (EFUSE_RD_RS_ERR0_REG, 27), # BLOCK_KEY2 + (EFUSE_RD_RS_ERR0_REG, 31), # BLOCK_KEY3 + (EFUSE_RD_RS_ERR1_REG, 3), # BLOCK_KEY4 + (EFUSE_RD_RS_ERR1_REG, 7), # BLOCK_KEY5 + (EFUSE_RD_RS_ERR1_REG, None), # BLOCK_SYS_DATA2 ] BLOCK_NUM_ERRORS = [ # error_reg, err_num_mask, err_num_offs - (EFUSE_RD_REPEAT_ERR0_REG, None, None), # BLOCK0 - (EFUSE_RD_RS_ERR0_REG, 0x7, 0), # MAC_SPI_8M_0 - (EFUSE_RD_RS_ERR0_REG, 0x7, 4), # BLOCK_SYS_DATA - (EFUSE_RD_RS_ERR0_REG, 0x7, 8), # BLOCK_USR_DATA - (EFUSE_RD_RS_ERR0_REG, 0x7, 12), # BLOCK_KEY0 - (EFUSE_RD_RS_ERR0_REG, 0x7, 16), # BLOCK_KEY1 - (EFUSE_RD_RS_ERR0_REG, 0x7, 20), # BLOCK_KEY2 - (EFUSE_RD_RS_ERR0_REG, 0x7, 24), # BLOCK_KEY3 - (EFUSE_RD_RS_ERR0_REG, 0x7, 28), # BLOCK_KEY4 - (EFUSE_RD_RS_ERR1_REG, 0x7, 0), # BLOCK_KEY5 - (EFUSE_RD_RS_ERR1_REG, 0x7, 4), # BLOCK_SYS_DATA2 + (EFUSE_RD_REPEAT_ERR0_REG, None, None), # BLOCK0 + (EFUSE_RD_RS_ERR0_REG, 0x7, 0), # MAC_SPI_8M_0 + (EFUSE_RD_RS_ERR0_REG, 0x7, 4), # BLOCK_SYS_DATA + (EFUSE_RD_RS_ERR0_REG, 0x7, 8), # BLOCK_USR_DATA + (EFUSE_RD_RS_ERR0_REG, 0x7, 12), # BLOCK_KEY0 + (EFUSE_RD_RS_ERR0_REG, 0x7, 16), # BLOCK_KEY1 + (EFUSE_RD_RS_ERR0_REG, 0x7, 20), # BLOCK_KEY2 + (EFUSE_RD_RS_ERR0_REG, 0x7, 24), # BLOCK_KEY3 + (EFUSE_RD_RS_ERR0_REG, 0x7, 28), # BLOCK_KEY4 + (EFUSE_RD_RS_ERR1_REG, 0x7, 0), # BLOCK_KEY5 + (EFUSE_RD_RS_ERR1_REG, 0x7, 4), # BLOCK_SYS_DATA2 ] # EFUSE_WR_TIM_CONF2_REG EFUSE_PWR_OFF_NUM_S = 0 EFUSE_PWR_OFF_NUM_M = 0xFFFF << EFUSE_PWR_OFF_NUM_S + # EFUSE_WR_TIM_CONF1_REG + EFUSE_PWR_ON_NUM_S = 8 + EFUSE_PWR_ON_NUM_M = 0x0000FFFF << EFUSE_PWR_ON_NUM_S -class EfuseDefineBlocks(EfuseBlocksBase): + # EFUSE_DAC_CONF_REG + EFUSE_DAC_CLK_DIV_S = 0 + EFUSE_DAC_CLK_DIV_M = 0xFF << EFUSE_DAC_CLK_DIV_S + # EFUSE_DAC_CONF_REG + EFUSE_DAC_NUM_S = 9 + EFUSE_DAC_NUM_M = 0xFF << EFUSE_DAC_NUM_S + + +class EfuseDefineBlocks(EfuseBlocksBase): __base_rd_regs = EfuseDefineRegisters.DR_REG_EFUSE_BASE __base_wr_regs = EfuseDefineRegisters.EFUSE_PGM_DATA0_REG # List of efuse blocks + # fmt: off BLOCKS = [ # Name, Alias, Index, Read address, Write address, Write protect bit, Read protect bit, Len, key_purpose ("BLOCK0", [], 0, __base_rd_regs + 0x02C, __base_wr_regs, None, None, 6, None), @@ -93,6 +112,7 @@ class EfuseDefineBlocks(EfuseBlocksBase): ("BLOCK_KEY5", ["BLOCK9"], 9, __base_rd_regs + 0x13C, __base_wr_regs, 28, 5, 8, "KEY_PURPOSE_5"), ("BLOCK_SYS_DATA2", ["BLOCK10"], 10, __base_rd_regs + 0x15C, __base_wr_regs, 29, 6, 8, None), ] + # fmt: on def get_burn_block_data_names(self): list_of_names = [] @@ -107,141 +127,63 @@ def get_burn_block_data_names(self): class EfuseDefineFields(EfuseFieldsBase): - - # List of efuse fields from TRM the chapter eFuse Controller. - EFUSES = [ - # - # Table 51: Parameters in BLOCK0 - # Name Category Block Word Pos Type:len WR_DIS RD_DIS Class Description Dictionary - ("WR_DIS", "efuse", 0, 0, 0, "uint:32", None, None, None, "Disables programming of individual eFuses", None), - ("RD_DIS", "efuse", 0, 1, 0, "uint:7", 0, None, None, "Disables software reading from BLOCK4-10", None), - ("DIS_ICACHE", "config", 0, 1, 8, "bool", 2, None, None, "Disables ICache", None), - ("DIS_USB_JTAG", "usb config", 0, 1, 9, "bool", 2, None, None, "Disables USB JTAG. " - "JTAG access via pads is controlled separately", None), - ("DIS_DOWNLOAD_ICACHE", "config", 0, 1, 10, "bool", 2, None, None, "Disables Icache when SoC is in Download mode", None), - ("DIS_USB_DEVICE", "usb config", 0, 1, 11, "bool", 2, None, None, "Disables USB DEVICE", None), - ("DIS_FORCE_DOWNLOAD", "config", 0, 1, 12, "bool", 2, None, None, "Disables forcing chip into Download mode", None), - ("DIS_CAN", "config", 0, 1, 14, "bool", 2, None, None, "Disables the TWAI Controller hardware", None), - ("SOFT_DIS_JTAG", "jtag config", 0, 1, 16, "uint:3", 2, None, None, "Software disables JTAG. When software disabled, " - "JTAG can be activated temporarily by HMAC peripheral", - None), - ("DIS_PAD_JTAG", "jtag config", 0, 1, 19, "bool", 2, None, None, "Permanently disable JTAG access via pads. " - "USB JTAG is controlled separately.", None), - ("DIS_DOWNLOAD_MANUAL_ENCRYPT", "security", 0, 1, 20, "bool", 2, None, None, "Disables flash encryption when in download boot modes", - None), - ("USB_EXCHG_PINS", "usb config", 0, 1, 25, "bool", 30, None, None, "Exchanges USB D+ and D- pins", None), - ("VDD_SPI_AS_GPIO", "config", 0, 1, 26, "bool", 30, None, None, "Set this bit to vdd spi pin function as gpio", None), - ("BTLC_GPIO_ENABLE", "config", 0, 1, 27, "uint:2", 30, None, None, "Enable btlc gpio", None), - ("POWERGLITCH_EN", "config", 0, 1, 29, "bool", 30, None, None, "Set this bit to enable power glitch function", None), - ("POWER_GLITCH_DSENSE", "config", 0, 1, 30, "uint:2", 30, None, None, "Sample delay configuration of power glitch", None), - ("WDT_DELAY_SEL", "WDT config", 0, 2, 16, "bool", 3, None, None, "Selects RTC WDT timeout threshold at startup", None), - ("SPI_BOOT_CRYPT_CNT", "security", 0, 2, 18, "uint:3", 4, None, "bitcount", "Enables encryption and decryption, when an SPI boot " - "mode is set. Enabled when 1 or 3 bits are set," - "disabled otherwise", - {0: "Disable", - 1: "Enable", - 3: "Disable", - 7: "Enable"}), - ("SECURE_BOOT_KEY_REVOKE0", "security", 0, 2, 21, "bool", 5, None, None, "If set, revokes use of secure boot key digest 0", None), - ("SECURE_BOOT_KEY_REVOKE1", "security", 0, 2, 22, "bool", 6, None, None, "If set, revokes use of secure boot key digest 1", None), - ("SECURE_BOOT_KEY_REVOKE2", "security", 0, 2, 23, "bool", 7, None, None, "If set, revokes use of secure boot key digest 2", None), - ("KEY_PURPOSE_0", "security", 0, 2, 24, "uint:4", 8, None, "keypurpose", "KEY0 purpose", None), - ("KEY_PURPOSE_1", "security", 0, 2, 28, "uint:4", 9, None, "keypurpose", "KEY1 purpose", None), - ("KEY_PURPOSE_2", "security", 0, 3, 0, "uint:4", 10, None, "keypurpose", "KEY2 purpose", None), - ("KEY_PURPOSE_3", "security", 0, 3, 4, "uint:4", 11, None, "keypurpose", "KEY3 purpose", None), - ("KEY_PURPOSE_4", "security", 0, 3, 8, "uint:4", 12, None, "keypurpose", "KEY4 purpose", None), - ("KEY_PURPOSE_5", "security", 0, 3, 12, "uint:4", 13, None, "keypurpose", "KEY5 purpose", None), - ("SECURE_BOOT_EN", "security", 0, 3, 20, "bool", 15, None, None, "Enables secure boot", None), - ("SECURE_BOOT_AGGRESSIVE_REVOKE", "security", 0, 3, 21, "bool", 16, None, None, "Enables aggressive secure boot key revocation mode", - None), - ("FLASH_TPUW", "flash config", 0, 3, 28, "uint:4", 18, None, None, "Configures flash startup delay after SoC power-up, " - "unit is (ms/2). When the value is 15, delay is 7.5 ms", - None), - ("DIS_DOWNLOAD_MODE", "security", 0, 4, 0, "bool", 18, None, None, "Disables all Download boot modes", None), - ("DIS_DIRECT_BOOT", "config", 0, 4, 1, "bool", 18, None, None, "Disables direct boot mode", None), - ("DIS_USB_SERIAL_JTAG_ROM_PRINT", "config", 0, 4, 2, "bool", 18, None, None, "Disables USB-Serial-JTAG ROM printing", None), - ("DIS_USB_SERIAL_JTAG_DOWNLOAD_MODE", "usb config", 0, 4, 4, "bool", 18, None, None, "Disables USB-Serial-JTAG download feature in " - "UART download boot mode", None), - ("ENABLE_SECURITY_DOWNLOAD", "security", 0, 4, 5, "bool", 18, None, None, "Enables secure UART download mode " - "(read/write flash only)", None), - ("UART_PRINT_CONTROL", "config", 0, 4, 6, "uint:2", 18, None, None, "Sets the default UART boot message output mode", - {0: "Enabled", - 1: "Enable when GPIO8 is low at reset", - 2: "Enable when GPIO8 is high at reset", - 3: "Disabled"}), - ("FORCE_SEND_RESUME", "config", 0, 4, 13, "bool", 18, None, None, "Force ROM code to send a resume command during SPI boot" - "during SPI boot", None), - ("SECURE_VERSION", "identity", 0, 4, 14, "uint:16", 18, None, "bitcount", "Secure version (used by ESP-IDF anti-rollback feature)", - None), - ("ERR_RST_ENABLE", "config", 0, 4, 31, "bool", 19, None, None, "Use BLOCK0 to check error record registers", - {0: "without check", - 1: "with check"}), - ("DISABLE_WAFER_VERSION_MAJOR", "config", 0, 5, 0, "bool", 19, None, None, "Disables check of wafer version major", None), - ("DISABLE_BLK_VERSION_MAJOR", "config", 0, 5, 1, "bool", 19, None, None, "Disables check of blk version major", None), - # - # Table 53: Parameters in BLOCK1-10 - # Name Category Block Word Pos Type:len WR_DIS RD_DIS Class Description Dictionary - ("MAC", "identity", 1, 0, 0, "bytes:6", 20, None, "mac", "Factory MAC Address", None), - ("SPI_PAD_CONFIG_CLK", "spi_pad_config", 1, 1, 16, "uint:6", 20, None, None, "SPI CLK pad", None), - ("SPI_PAD_CONFIG_Q", "spi_pad_config", 1, 1, 22, "uint:6", 20, None, None, "SPI Q (D1) pad", None), - ("SPI_PAD_CONFIG_D", "spi_pad_config", 1, 1, 28, "uint:6", 20, None, None, "SPI D (D0) pad", None), - ("SPI_PAD_CONFIG_CS", "spi_pad_config", 1, 2, 2, "uint:6", 20, None, None, "SPI CS pad", None), - ("SPI_PAD_CONFIG_HD", "spi_pad_config", 1, 2, 8, "uint:6", 20, None, None, "SPI HD (D3) pad", None), - ("SPI_PAD_CONFIG_WP", "spi_pad_config", 1, 2, 14, "uint:6", 20, None, None, "SPI WP (D2) pad", None), - ("SPI_PAD_CONFIG_DQS", "spi_pad_config", 1, 2, 20, "uint:6", 20, None, None, "SPI DQS pad", None), - ("SPI_PAD_CONFIG_D4", "spi_pad_config", 1, 2, 26, "uint:6", 20, None, None, "SPI D4 pad", None), - ("SPI_PAD_CONFIG_D5", "spi_pad_config", 1, 3, 0, "uint:6", 20, None, None, "SPI D5 pad", None), - ("SPI_PAD_CONFIG_D6", "spi_pad_config", 1, 3, 6, "uint:6", 20, None, None, "SPI D6 pad", None), - ("SPI_PAD_CONFIG_D7", "spi_pad_config", 1, 3, 12, "uint:6", 20, None, None, "SPI D7 pad", None), - - ("WAFER_VERSION_MINOR_LO", "identity", 1, 3, 18, "uint:3", 20, None, None, "WAFER_VERSION_MINOR least significant bits", None), - ("PKG_VERSION", "identity", 1, 3, 21, "uint:3", 20, None, None, "Package version", None), - ("BLK_VERSION_MINOR", "identity", 1, 3, 24, "uint:3", 20, None, None, "BLOCK version minor", None), - ("WAFER_VERSION_MINOR_HI", "identity", 1, 5, 23, "uint:1", 20, None, None, "WAFER_VERSION_MINOR most significant bits", None), - ("WAFER_VERSION_MAJOR", "identity", 1, 5, 24, "uint:2", 20, None, None, "WAFER_VERSION_MAJOR", None), - - ("OPTIONAL_UNIQUE_ID", "identity", 2, 0, 0, "bytes:16", 21, None, "keyblock", "Optional unique 128-bit ID", None), - ("BLK_VERSION_MAJOR", "identity", 2, 4, 0, "uint:2", 21, None, None, "BLOCK version major", - {0: "No calibration", - 1: "With calibration"}), - ("CUSTOM_MAC", "identity", 3, 6, 8, "bytes:6", 22, None, "mac", "Custom MAC Address", None), - ] - - KEYBLOCKS = [ - # Name Category Block Word Pos Type:len WR_DIS RD_DIS Class Description Dictionary - ('BLOCK_USR_DATA', "config", 3, 0, 0, "bytes:32", 22, None, None, "User data", None), - ('BLOCK_KEY0', "security", 4, 0, 0, "bytes:32", 23, 0, "keyblock", "Encryption key0 or user data", None), - ('BLOCK_KEY1', "security", 5, 0, 0, "bytes:32", 24, 1, "keyblock", "Encryption key1 or user data", None), - ('BLOCK_KEY2', "security", 6, 0, 0, "bytes:32", 25, 2, "keyblock", "Encryption key2 or user data", None), - ('BLOCK_KEY3', "security", 7, 0, 0, "bytes:32", 26, 3, "keyblock", "Encryption key3 or user data", None), - ('BLOCK_KEY4', "security", 8, 0, 0, "bytes:32", 27, 4, "keyblock", "Encryption key4 or user data", None), - ('BLOCK_KEY5', "security", 9, 0, 0, "bytes:32", 28, 5, "keyblock", "Encryption key5 or user data", None), - ('BLOCK_SYS_DATA2', "security", 10, 0, 0, "bytes:32", 29, 6, "keyblock", "System data (part 2)", None), - ] - - # if BLK_VERSION_MAJOR is 1, these efuse fields are in BLOCK2 - BLOCK2_CALIBRATION_EFUSES = [ - # Name Category Block Word Pos Type:len WR_DIS RD_DIS Class Description Dictionary - ('TEMP_SENSOR_CAL', "calibration", 2, 4, 7, "uint:9", 21, None, "t_sensor", "Temperature calibration", None), - ('ADC1_MODE0_D2', "calibration", 2, 4, 16, "uint:8", 21, None, "adc_tp", "ADC1 calibration 1", None), - ('ADC1_MODE1_D2', "calibration", 2, 4, 24, "uint:8", 21, None, "adc_tp", "ADC1 calibration 2", None), - ('ADC1_MODE2_D2', "calibration", 2, 5, 0, "uint:8", 21, None, "adc_tp", "ADC1 calibration 3", None), - ('ADC1_MODE3_D2', "calibration", 2, 5, 8, "uint:8", 21, None, "adc_tp", "ADC1 calibration 4", None), - ('ADC2_MODE0_D2', "calibration", 2, 5, 16, "uint:8", 21, None, "adc_tp", "ADC2 calibration 5", None), - ('ADC2_MODE1_D2', "calibration", 2, 5, 24, "uint:8", 21, None, "adc_tp", "ADC2 calibration 6", None), - ('ADC2_MODE2_D2', "calibration", 2, 6, 0, "uint:8", 21, None, "adc_tp", "ADC2 calibration 7", None), - ('ADC2_MODE3_D2', "calibration", 2, 6, 8, "uint:8", 21, None, "adc_tp", "ADC2 calibration 8", None), - ('ADC1_MODE0_D1', "calibration", 2, 6, 16, "uint:6", 21, None, "adc_tp", "ADC1 calibration 9", None), - ('ADC1_MODE1_D1', "calibration", 2, 6, 22, "uint:6", 21, None, "adc_tp", "ADC1 calibration 10", None), - ('ADC1_MODE2_D1', "calibration", 2, 6, 28, "uint:6", 21, None, "adc_tp", "ADC1 calibration 11", None), - ('ADC1_MODE3_D1', "calibration", 2, 7, 2, "uint:6", 21, None, "adc_tp", "ADC1 calibration 12", None), - ('ADC2_MODE0_D1', "calibration", 2, 7, 8, "uint:6", 21, None, "adc_tp", "ADC2 calibration 13", None), - ('ADC2_MODE1_D1', "calibration", 2, 7, 14, "uint:6", 21, None, "adc_tp", "ADC2 calibration 14", None), - ('ADC2_MODE2_D1', "calibration", 2, 7, 20, "uint:6", 21, None, "adc_tp", "ADC2 calibration 15", None), - ('ADC2_MODE3_D1', "calibration", 2, 7, 26, "uint:6", 21, None, "adc_tp", "ADC2 calibration 16", None), - ] - - CALC = [ - ("WAFER_VERSION_MINOR", "identity", 0, None, None, "uint:4", None, None, "wafer", "calc WAFER VERSION MINOR = WAFER_VERSION_MINOR_HI << 3 + WAFER_VERSION_MINOR_LO (read only)", None), - ] -# fmt: on + def __init__(self) -> None: + # List of efuse fields from TRM the chapter eFuse Controller. + self.EFUSES = [] + + self.KEYBLOCKS = [] + + # if BLK_VERSION_MAJOR is 1, these efuse fields are in BLOCK2 + self.BLOCK2_CALIBRATION_EFUSES = [] + + self.CALC = [] + + dir_name = os.path.dirname(os.path.abspath(__file__)) + dir_name, file_name = os.path.split(dir_name) + file_name = file_name + ".yaml" + dir_name, _ = os.path.split(dir_name) + efuse_file = os.path.join(dir_name, "efuse_defs", file_name) + with open(f"{efuse_file}", "r") as r_file: + e_desc = yaml.safe_load(r_file) + super().__init__(e_desc) + + for i, efuse in enumerate(self.ALL_EFUSES): + if efuse.name in [ + "BLOCK_USR_DATA", + "BLOCK_KEY0", + "BLOCK_KEY1", + "BLOCK_KEY2", + "BLOCK_KEY3", + "BLOCK_KEY4", + "BLOCK_KEY5", + "BLOCK_SYS_DATA2", + ]: + if efuse.name == "BLOCK_USR_DATA": + efuse.bit_len = 256 + efuse.type = "bytes:32" + self.KEYBLOCKS.append(efuse) + self.ALL_EFUSES[i] = None + + elif efuse.category == "calibration": + self.BLOCK2_CALIBRATION_EFUSES.append(efuse) + self.ALL_EFUSES[i] = None + + # It is not functional, a bug in the hardware + elif efuse.name == "JTAG_SEL_ENABLE": + self.ALL_EFUSES[i] = None + + f = Field() + f.name = "WAFER_VERSION_MINOR" + f.block = 0 + f.bit_len = 4 + f.type = f"uint:{f.bit_len}" + f.category = "identity" + f.class_type = "wafer" + f.description = "calc WAFER VERSION MINOR = WAFER_VERSION_MINOR_HI << 3 + WAFER_VERSION_MINOR_LO (read only)" + self.CALC.append(f) + + for efuse in self.ALL_EFUSES: + if efuse is not None: + self.EFUSES.append(efuse) + + self.ALL_EFUSES = [] diff --git a/espefuse/efuse/esp32c3/operations.py b/espefuse/efuse/esp32c3/operations.py index 29353d095..59f446904 100644 --- a/espefuse/efuse/esp32c3/operations.py +++ b/espefuse/efuse/esp32c3/operations.py @@ -17,6 +17,7 @@ from ..base_operations import ( add_common_commands, add_force_write_always, + add_show_sensitive_info_option, burn_bit, burn_block_data, burn_efuse, @@ -55,6 +56,7 @@ def add_commands(subparsers, efuses): ) protect_options(burn_key) add_force_write_always(burn_key) + add_show_sensitive_info_option(burn_key) burn_key.add_argument( "block", help="Key block to burn", @@ -105,6 +107,7 @@ def add_commands(subparsers, efuses): ) protect_options(burn_key_digest) add_force_write_always(burn_key_digest) + add_show_sensitive_info_option(burn_key_digest) burn_key_digest.add_argument( "block", help="Key block to burn", @@ -276,7 +279,13 @@ def burn_key(esp, efuses, args, digest=None): if efuses[block.key_purpose_name].need_reverse(keypurpose): revers_msg = "\tReversing byte order for AES-XTS hardware peripheral" data = data[::-1] - print("-> [%s]" % (util.hexify(data, " "))) + print( + "-> [{}]".format( + util.hexify(data, " ") + if args.show_sensitive_info + else " ".join(["??"] * len(data)) + ) + ) if revers_msg: print(revers_msg) if len(data) != num_bytes: diff --git a/espefuse/efuse/esp32c6/emulate_efuse_controller.py b/espefuse/efuse/esp32c6/emulate_efuse_controller.py index e22bb7578..a9e7d4d4a 100644 --- a/espefuse/efuse/esp32c6/emulate_efuse_controller.py +++ b/espefuse/efuse/esp32c6/emulate_efuse_controller.py @@ -16,13 +16,13 @@ class EmulateEfuseController(EmulateEfuseControllerBase): CHIP_NAME = "ESP32-C6" mem = None debug = False - Blocks = EfuseDefineBlocks - Fields = EfuseDefineFields - REGS = EfuseDefineRegisters def __init__(self, efuse_file=None, debug=False): + self.Blocks = EfuseDefineBlocks + self.Fields = EfuseDefineFields() + self.REGS = EfuseDefineRegisters super(EmulateEfuseController, self).__init__(efuse_file, debug) - self.write_reg(self.REGS.EFUSE_STATUS_REG, 1) + self.write_reg(self.REGS.EFUSE_CMD_REG, 0) """ esptool method start >>""" @@ -53,10 +53,10 @@ def handle_writing_event(self, addr, value): self.clean_blocks_wr_regs() self.check_rd_protection_area() self.write_reg(addr, 0) - self.write_reg(self.REGS.EFUSE_STATUS_REG, 1) + self.write_reg(self.REGS.EFUSE_CMD_REG, 0) elif value == self.REGS.EFUSE_READ_CMD: self.write_reg(addr, 0) - self.write_reg(self.REGS.EFUSE_STATUS_REG, 1) + self.write_reg(self.REGS.EFUSE_CMD_REG, 0) self.save_to_file() def get_bitlen_of_block(self, blk, wr=False): diff --git a/espefuse/efuse/esp32c6/fields.py b/espefuse/efuse/esp32c6/fields.py index 14a878199..a62004f1a 100644 --- a/espefuse/efuse/esp32c6/fields.py +++ b/espefuse/efuse/esp32c6/fields.py @@ -54,16 +54,15 @@ class EspEfuses(base_fields.EspEfusesBase): Wrapper object to manage the efuse fields in a connected ESP bootloader """ - Blocks = EfuseDefineBlocks() - Fields = EfuseDefineFields() - REGS = EfuseDefineRegisters - BURN_BLOCK_DATA_NAMES = Blocks.get_burn_block_data_names() - BLOCKS_FOR_KEYS = Blocks.get_blocks_for_keys() - debug = False do_not_confirm = False def __init__(self, esp, skip_connect=False, debug=False, do_not_confirm=False): + self.Blocks = EfuseDefineBlocks() + self.Fields = EfuseDefineFields() + self.REGS = EfuseDefineRegisters + self.BURN_BLOCK_DATA_NAMES = self.Blocks.get_burn_block_data_names() + self.BLOCKS_FOR_KEYS = self.Blocks.get_blocks_for_keys() self._esp = esp self.debug = debug self.do_not_confirm = do_not_confirm @@ -85,59 +84,43 @@ def __init__(self, esp, skip_connect=False, debug=False, do_not_confirm=False): ] if not skip_connect: self.get_coding_scheme_warnings() - self.efuses = [ - EfuseField.from_tuple( - self, self.Fields.get(efuse), self.Fields.get(efuse).class_type - ) - for efuse in self.Fields.EFUSES - ] + self.efuses = [EfuseField.convert(self, efuse) for efuse in self.Fields.EFUSES] self.efuses += [ - EfuseField.from_tuple( - self, self.Fields.get(efuse), self.Fields.get(efuse).class_type - ) - for efuse in self.Fields.KEYBLOCKS + EfuseField.convert(self, efuse) for efuse in self.Fields.KEYBLOCKS ] if skip_connect: self.efuses += [ - EfuseField.from_tuple( - self, self.Fields.get(efuse), self.Fields.get(efuse).class_type - ) + EfuseField.convert(self, efuse) for efuse in self.Fields.BLOCK2_CALIBRATION_EFUSES ] else: - if self["BLK_VERSION_MAJOR"].get() == 1: + if self["BLK_VERSION_MINOR"].get() == 1: self.efuses += [ - EfuseField.from_tuple( - self, self.Fields.get(efuse), self.Fields.get(efuse).class_type - ) + EfuseField.convert(self, efuse) for efuse in self.Fields.BLOCK2_CALIBRATION_EFUSES ] self.efuses += [ - EfuseField.from_tuple( - self, self.Fields.get(efuse), self.Fields.get(efuse).class_type - ) - for efuse in self.Fields.CALC + EfuseField.convert(self, efuse) for efuse in self.Fields.CALC ] def __getitem__(self, efuse_name): """Return the efuse field with the given name""" for e in self.efuses: - if efuse_name == e.name: + if efuse_name == e.name or any(x == efuse_name for x in e.alt_names): return e new_fields = False for efuse in self.Fields.BLOCK2_CALIBRATION_EFUSES: - e = self.Fields.get(efuse) - if e.name == efuse_name: + if efuse.name == efuse_name or any( + x == efuse_name for x in efuse.alt_names + ): self.efuses += [ - EfuseField.from_tuple( - self, self.Fields.get(efuse), self.Fields.get(efuse).class_type - ) + EfuseField.convert(self, efuse) for efuse in self.Fields.BLOCK2_CALIBRATION_EFUSES ] new_fields = True if new_fields: for e in self.efuses: - if efuse_name == e.name: + if efuse_name == e.name or any(x == efuse_name for x in e.alt_names): return e raise KeyError @@ -158,10 +141,6 @@ def print_status_regs(self): ) ) - def get_block_errors(self, block_num): - """Returns (error count, failure boolean flag)""" - return self.blocks[block_num].num_errors, self.blocks[block_num].fail - def efuse_controller_setup(self): self.set_efuse_timing() self.clear_pgm_registers() @@ -181,9 +160,13 @@ def clear_pgm_registers(self): def wait_efuse_idle(self): deadline = time.time() + self.REGS.EFUSE_BURN_TIMEOUT while time.time() < deadline: - # if self.read_reg(self.REGS.EFUSE_CMD_REG) == 0: - if self.read_reg(self.REGS.EFUSE_STATUS_REG) & 0x7 == 1: - return + cmds = self.REGS.EFUSE_PGM_CMD | self.REGS.EFUSE_READ_CMD + if self.read_reg(self.REGS.EFUSE_CMD_REG) & cmds == 0: + if self.read_reg(self.REGS.EFUSE_CMD_REG) & cmds == 0: + # Due to a hardware error, we have to read READ_CMD again + # to make sure the efuse clock is normal. + # For PGM_CMD it is not necessary. + return raise esptool.FatalError( "Timed out waiting for Efuse controller command to complete" ) @@ -249,12 +232,21 @@ def set_efuse_timing(self): "The eFuse supports only xtal=40M (xtal was %d)" % apb_freq ) + self.update_reg(self.REGS.EFUSE_DAC_CONF_REG, self.REGS.EFUSE_DAC_NUM_M, 0xFF) + self.update_reg( + self.REGS.EFUSE_DAC_CONF_REG, self.REGS.EFUSE_DAC_CLK_DIV_M, 0x28 + ) + self.update_reg( + self.REGS.EFUSE_WR_TIM_CONF1_REG, self.REGS.EFUSE_PWR_ON_NUM_M, 0x3000 + ) self.update_reg( self.REGS.EFUSE_WR_TIM_CONF2_REG, self.REGS.EFUSE_PWR_OFF_NUM_M, 0x190 ) def get_coding_scheme_warnings(self, silent=False): """Check if the coding scheme has detected any errors.""" + old_addr_reg = 0 + reg_value = 0 ret_fail = False for block in self.blocks: if block.id == 0: @@ -262,29 +254,22 @@ def get_coding_scheme_warnings(self, silent=False): self.read_reg(self.REGS.EFUSE_RD_REPEAT_ERR0_REG + offs * 4) for offs in range(5) ] - data = BitArray() + block.err_bitarray.pos = 0 for word in reversed(words): - data.append("uint:32=%d" % word) - # pos=32 because EFUSE_WR_DIS goes first it is 32bit long - # and not under error control - block.err_bitarray.overwrite(data, pos=32) + block.err_bitarray.overwrite(BitArray("uint:32=%d" % word)) block.num_errors = block.err_bitarray.count(True) block.fail = block.num_errors != 0 else: - addr_reg_f, fail_bit = self.REGS.BLOCK_FAIL_BIT[block.id] - if fail_bit is None: - block.fail = False - else: - block.fail = self.read_reg(addr_reg_f) & (1 << fail_bit) != 0 - - addr_reg_n, num_mask, num_offs = self.REGS.BLOCK_NUM_ERRORS[block.id] - if num_mask is None or num_offs is None: - block.num_errors = 0 - else: - block.num_errors = ( - self.read_reg(addr_reg_n) >> num_offs - ) & num_mask - + addr_reg, err_num_mask, err_num_offs, fail_bit = self.REGS.BLOCK_ERRORS[ + block.id + ] + if err_num_mask is None or err_num_offs is None or fail_bit is None: + continue + if addr_reg != old_addr_reg: + old_addr_reg = addr_reg + reg_value = self.read_reg(addr_reg) + block.fail = reg_value & (1 << fail_bit) != 0 + block.num_errors = (reg_value >> err_num_offs) & err_num_mask ret_fail |= block.fail if not silent and (block.fail or block.num_errors): print( @@ -302,35 +287,22 @@ def summary(self): class EfuseField(base_fields.EfuseFieldBase): @staticmethod - def from_tuple(parent, efuse_tuple, type_class): + def convert(parent, efuse): return { "mac": EfuseMacField, "keypurpose": EfuseKeyPurposeField, "t_sensor": EfuseTempSensor, "adc_tp": EfuseAdcPointCalibration, "wafer": EfuseWafer, - }.get(type_class, EfuseField)(parent, efuse_tuple) - - def get_info(self): - output = "%s (BLOCK%d)" % (self.name, self.block) - errs, fail = self.parent.get_block_errors(self.block) - if errs != 0 or fail: - output += ( - "[FAIL:%d]" % (fail) - if self.block == 0 - else "[ERRS:%d FAIL:%d]" % (errs, fail) - ) - if self.efuse_class == "keyblock": - name = self.parent.blocks[self.block].key_purpose_name - if name is not None: - output += "\n Purpose: %s\n " % (self.parent[name].get()) - return output + }.get(efuse.class_type, EfuseField)(parent, efuse) class EfuseWafer(EfuseField): def get(self, from_read=True): hi_bits = self.parent["WAFER_VERSION_MINOR_HI"].get(from_read) + assert self.parent["WAFER_VERSION_MINOR_HI"].bit_len == 1 lo_bits = self.parent["WAFER_VERSION_MINOR_LO"].get(from_read) + assert self.parent["WAFER_VERSION_MINOR_LO"].bit_len == 3 return (hi_bits << 3) + lo_bits def save(self, new_value): @@ -358,23 +330,27 @@ def check_format(self, new_value_str): raise esptool.FatalError( "Required MAC Address in AA:CD:EF:01:02:03 format!" ) - if new_value_str.count(":") != 5: + num_bytes = 8 if self.name == "MAC_EUI64" else 6 + if new_value_str.count(":") != num_bytes - 1: raise esptool.FatalError( - "MAC Address needs to be a 6-byte hexadecimal format " + f"MAC Address needs to be a {num_bytes}-byte hexadecimal format " "separated by colons (:)!" ) - hexad = new_value_str.replace(":", "") - if len(hexad) != 12: + hexad = new_value_str.replace(":", "").split(" ", 1)[0] + hexad = hexad.split(" ", 1)[0] if self.is_field_calculated() else hexad + if len(hexad) != num_bytes * 2: raise esptool.FatalError( - "MAC Address needs to be a 6-byte hexadecimal number " - "(12 hexadecimal characters)!" + f"MAC Address needs to be a {num_bytes}-byte hexadecimal number " + f"({num_bytes * 2} hexadecimal characters)!" ) # order of bytearray = b'\xaa\xcd\xef\x01\x02\x03', bindata = binascii.unhexlify(hexad) - # unicast address check according to - # https://tools.ietf.org/html/rfc7042#section-2.1 - if esptool.util.byte(bindata, 0) & 0x01: - raise esptool.FatalError("Custom MAC must be a unicast MAC!") + + if not self.is_field_calculated(): + # unicast address check according to + # https://tools.ietf.org/html/rfc7042#section-2.1 + if esptool.util.byte(bindata, 0) & 0x01: + raise esptool.FatalError("Custom MAC must be a unicast MAC!") return bindata def check(self): @@ -388,6 +364,13 @@ def check(self): def get(self, from_read=True): if self.name == "CUSTOM_MAC": mac = self.get_raw(from_read)[::-1] + elif self.name == "MAC": + mac = self.get_raw(from_read) + elif self.name == "MAC_EUI64": + mac = self.parent["MAC"].get_bitstring(from_read).copy() + mac_ext = self.parent["MAC_EXT"].get_bitstring(from_read) + mac.insert(mac_ext, 24) + mac = mac.bytes else: mac = self.get_raw(from_read) return "%s %s" % (util.hexify(mac, ":"), self.check()) @@ -407,7 +390,7 @@ def print_field(e, new_value): else: # Writing the BLOCK1 (MAC_SPI_8M_0) default MAC is not possible, # as it's written in the factory. - raise esptool.FatalError("Writing Factory MAC address is not supported") + raise esptool.FatalError(f"Burning {self.name} is not supported") # fmt: off @@ -459,6 +442,14 @@ def get(self, from_read=True): return p[0] return "FORBIDDEN_STATE" + def get_name(self, raw_val): + for key in self.KEY_PURPOSES: + if key[1] == raw_val: + return key[0] + def save(self, new_value): raw_val = int(self.check_format(str(new_value))) + str_new_value = self.get_name(raw_val) + if self.name == "KEY_PURPOSE_5" and str_new_value.startswith("XTS_AES"): + raise esptool.FatalError(f"{self.name} can not have {str_new_value} key due to a hardware bug (please see TRM for more details)") return super(EfuseKeyPurposeField, self).save(raw_val) diff --git a/espefuse/efuse/esp32c6/mem_definition.py b/espefuse/efuse/esp32c6/mem_definition.py index 890653888..25e4caf01 100644 --- a/espefuse/efuse/esp32c6/mem_definition.py +++ b/espefuse/efuse/esp32c6/mem_definition.py @@ -4,24 +4,31 @@ # # SPDX-License-Identifier: GPL-2.0-or-later -from ..mem_definition_base import EfuseBlocksBase, EfuseFieldsBase, EfuseRegistersBase +import os +import yaml + +from ..mem_definition_base import ( + EfuseBlocksBase, + EfuseFieldsBase, + EfuseRegistersBase, + Field, +) -# fmt: off -class EfuseDefineRegisters(EfuseRegistersBase): - EFUSE_MEM_SIZE = (0x01FC + 4) +class EfuseDefineRegisters(EfuseRegistersBase): + EFUSE_MEM_SIZE = 0x01FC + 4 # EFUSE registers & command/conf values - DR_REG_EFUSE_BASE = 0x600B0800 - EFUSE_PGM_DATA0_REG = DR_REG_EFUSE_BASE - EFUSE_CHECK_VALUE0_REG = DR_REG_EFUSE_BASE + 0x020 - EFUSE_CLK_REG = DR_REG_EFUSE_BASE + 0x1C8 - EFUSE_CONF_REG = DR_REG_EFUSE_BASE + 0x1CC - EFUSE_STATUS_REG = DR_REG_EFUSE_BASE + 0x1D0 - EFUSE_CMD_REG = DR_REG_EFUSE_BASE + 0x1D4 - EFUSE_RD_RS_ERR0_REG = DR_REG_EFUSE_BASE + 0x1C0 - EFUSE_RD_RS_ERR1_REG = DR_REG_EFUSE_BASE + 0x1C4 + DR_REG_EFUSE_BASE = 0x600B0800 + EFUSE_PGM_DATA0_REG = DR_REG_EFUSE_BASE + EFUSE_CHECK_VALUE0_REG = DR_REG_EFUSE_BASE + 0x020 + EFUSE_CLK_REG = DR_REG_EFUSE_BASE + 0x1C8 + EFUSE_CONF_REG = DR_REG_EFUSE_BASE + 0x1CC + EFUSE_STATUS_REG = DR_REG_EFUSE_BASE + 0x1D0 + EFUSE_CMD_REG = DR_REG_EFUSE_BASE + 0x1D4 + EFUSE_RD_RS_ERR0_REG = DR_REG_EFUSE_BASE + 0x1C0 + EFUSE_RD_RS_ERR1_REG = DR_REG_EFUSE_BASE + 0x1C4 EFUSE_RD_REPEAT_ERR0_REG = DR_REG_EFUSE_BASE + 0x17C EFUSE_RD_REPEAT_ERR1_REG = DR_REG_EFUSE_BASE + 0x180 EFUSE_RD_REPEAT_ERR2_REG = DR_REG_EFUSE_BASE + 0x184 @@ -32,53 +39,49 @@ class EfuseDefineRegisters(EfuseRegistersBase): EFUSE_WR_TIM_CONF1_REG = DR_REG_EFUSE_BASE + 0x1F0 EFUSE_WR_TIM_CONF2_REG = DR_REG_EFUSE_BASE + 0x1F4 EFUSE_DATE_REG = DR_REG_EFUSE_BASE + 0x1FC - EFUSE_WRITE_OP_CODE = 0x5A5A - EFUSE_READ_OP_CODE = 0x5AA5 - EFUSE_PGM_CMD_MASK = 0x3 - EFUSE_PGM_CMD = 0x2 - EFUSE_READ_CMD = 0x1 - - # this chip has a design error so fail_bit is shifted by one block but err_num is in the correct place - BLOCK_FAIL_BIT = [ - # error_reg, fail_bit - (EFUSE_RD_REPEAT_ERR0_REG, None), # BLOCK0 - (EFUSE_RD_RS_ERR0_REG, 7), # MAC_SPI_8M_0 - (EFUSE_RD_RS_ERR0_REG, 11), # BLOCK_SYS_DATA - (EFUSE_RD_RS_ERR0_REG, 15), # BLOCK_USR_DATA - (EFUSE_RD_RS_ERR0_REG, 19), # BLOCK_KEY0 - (EFUSE_RD_RS_ERR0_REG, 23), # BLOCK_KEY1 - (EFUSE_RD_RS_ERR0_REG, 27), # BLOCK_KEY2 - (EFUSE_RD_RS_ERR0_REG, 31), # BLOCK_KEY3 - (EFUSE_RD_RS_ERR1_REG, 3), # BLOCK_KEY4 - (EFUSE_RD_RS_ERR1_REG, 7), # BLOCK_KEY5 - (EFUSE_RD_RS_ERR1_REG, None), # BLOCK_SYS_DATA2 - ] - - BLOCK_NUM_ERRORS = [ - # error_reg, err_num_mask, err_num_offs - (EFUSE_RD_REPEAT_ERR0_REG, None, None), # BLOCK0 - (EFUSE_RD_RS_ERR0_REG, 0x7, 0), # MAC_SPI_8M_0 - (EFUSE_RD_RS_ERR0_REG, 0x7, 4), # BLOCK_SYS_DATA - (EFUSE_RD_RS_ERR0_REG, 0x7, 8), # BLOCK_USR_DATA - (EFUSE_RD_RS_ERR0_REG, 0x7, 12), # BLOCK_KEY0 - (EFUSE_RD_RS_ERR0_REG, 0x7, 16), # BLOCK_KEY1 - (EFUSE_RD_RS_ERR0_REG, 0x7, 20), # BLOCK_KEY2 - (EFUSE_RD_RS_ERR0_REG, 0x7, 24), # BLOCK_KEY3 - (EFUSE_RD_RS_ERR0_REG, 0x7, 28), # BLOCK_KEY4 - (EFUSE_RD_RS_ERR1_REG, 0x7, 0), # BLOCK_KEY5 - (EFUSE_RD_RS_ERR1_REG, 0x7, 4), # BLOCK_SYS_DATA2 + EFUSE_WRITE_OP_CODE = 0x5A5A + EFUSE_READ_OP_CODE = 0x5AA5 + EFUSE_PGM_CMD_MASK = 0x3 + EFUSE_PGM_CMD = 0x2 + EFUSE_READ_CMD = 0x1 + + BLOCK_ERRORS = [ + # error_reg, err_num_mask, err_num_offs, fail_bit + (EFUSE_RD_REPEAT_ERR0_REG, None, None, None), # BLOCK0 + (EFUSE_RD_RS_ERR0_REG, 0x7, 0, 3), # MAC_SPI_8M_0 + (EFUSE_RD_RS_ERR0_REG, 0x7, 4, 7), # BLOCK_SYS_DATA + (EFUSE_RD_RS_ERR0_REG, 0x7, 8, 11), # BLOCK_USR_DATA + (EFUSE_RD_RS_ERR0_REG, 0x7, 12, 15), # BLOCK_KEY0 + (EFUSE_RD_RS_ERR0_REG, 0x7, 16, 19), # BLOCK_KEY1 + (EFUSE_RD_RS_ERR0_REG, 0x7, 20, 23), # BLOCK_KEY2 + (EFUSE_RD_RS_ERR0_REG, 0x7, 24, 27), # BLOCK_KEY3 + (EFUSE_RD_RS_ERR0_REG, 0x7, 28, 31), # BLOCK_KEY4 + (EFUSE_RD_RS_ERR1_REG, 0x7, 0, 3), # BLOCK_KEY5 + (EFUSE_RD_RS_ERR1_REG, 0x7, 4, 7), # BLOCK_SYS_DATA2 ] # EFUSE_WR_TIM_CONF2_REG EFUSE_PWR_OFF_NUM_S = 0 EFUSE_PWR_OFF_NUM_M = 0xFFFF << EFUSE_PWR_OFF_NUM_S + # EFUSE_WR_TIM_CONF1_REG + EFUSE_PWR_ON_NUM_S = 8 + EFUSE_PWR_ON_NUM_M = 0x0000FFFF << EFUSE_PWR_ON_NUM_S -class EfuseDefineBlocks(EfuseBlocksBase): + # EFUSE_DAC_CONF_REG + EFUSE_DAC_CLK_DIV_S = 0 + EFUSE_DAC_CLK_DIV_M = 0xFF << EFUSE_DAC_CLK_DIV_S + + # EFUSE_DAC_CONF_REG + EFUSE_DAC_NUM_S = 9 + EFUSE_DAC_NUM_M = 0xFF << EFUSE_DAC_NUM_S + +class EfuseDefineBlocks(EfuseBlocksBase): __base_rd_regs = EfuseDefineRegisters.DR_REG_EFUSE_BASE __base_wr_regs = EfuseDefineRegisters.EFUSE_PGM_DATA0_REG # List of efuse blocks + # fmt: off BLOCKS = [ # Name, Alias, Index, Read address, Write address, Write protect bit, Read protect bit, Len, key_purpose ("BLOCK0", [], 0, __base_rd_regs + 0x02C, __base_wr_regs, None, None, 6, None), @@ -93,6 +96,7 @@ class EfuseDefineBlocks(EfuseBlocksBase): ("BLOCK_KEY5", ["BLOCK9"], 9, __base_rd_regs + 0x13C, __base_wr_regs, 28, 5, 8, "KEY_PURPOSE_5"), ("BLOCK_SYS_DATA2", ["BLOCK10"], 10, __base_rd_regs + 0x15C, __base_wr_regs, 29, 6, 8, None), ] + # fmt: on def get_burn_block_data_names(self): list_of_names = [] @@ -107,155 +111,59 @@ def get_burn_block_data_names(self): class EfuseDefineFields(EfuseFieldsBase): - - # List of efuse fields from TRM the chapter eFuse Controller. - EFUSES = [ - # - # Table 51: Parameters in BLOCK0 - # Name Category Block Word Pos Type:len WR_DIS RD_DIS Class Description Dictionary - ("WR_DIS", "efuse", 0, 0, 0, "uint:32", None, None, None, "Disables programming of individual eFuses", None), - ("RD_DIS", "efuse", 0, 1, 0, "uint:7", 0, None, None, "Disables software reading from BLOCK4-10", None), - ("DIS_ICACHE", "config", 0, 1, 8, "bool", 2, None, None, "Disables ICache", None), - ("DIS_USB_JTAG", "usb config", 0, 1, 9, "bool", 2, None, None, "Disables USB JTAG. " - "JTAG access via pads is controlled separately", None), - ("DIS_DOWNLOAD_ICACHE", "config", 0, 1, 10, "bool", 2, None, None, "Disables Icache when SoC is in Download mode", None), - ("DIS_USB_DEVICE", "usb config", 0, 1, 11, "bool", 2, None, None, "Disables USB DEVICE", None), - ("DIS_FORCE_DOWNLOAD", "config", 0, 1, 12, "bool", 2, None, None, "Disables forcing chip into Download mode", None), - ("DIS_USB", "usb config", 0, 1, 13, "bool", 2, None, None, "Disables the USB OTG hardware", None), - ("DIS_CAN", "config", 0, 1, 14, "bool", 2, None, None, "Disables the TWAI Controller hardware", None), - ("JTAG_SEL_ENABLE", "jtag config", 0, 1, 15, "bool", 2, None, None, "Set this bit to enable selection between " - "usb_to_jtag and pad_to_jtag through strapping " - "gpio10 when both reg_dis_usb_jtag and " - "reg_dis_pad_jtag are equal to 0.", None), - ("SOFT_DIS_JTAG", "jtag config", 0, 1, 16, "uint:3", 2, None, None, "Software disables JTAG. When software disabled, " - "JTAG can be activated temporarily by HMAC peripheral", - None), - ("DIS_PAD_JTAG", "jtag config", 0, 1, 19, "bool", 2, None, None, "Permanently disable JTAG access via pads. " - "USB JTAG is controlled separately.", None), - ("DIS_DOWNLOAD_MANUAL_ENCRYPT", "security", 0, 1, 20, "bool", 2, None, None, "Disables flash encryption when in download boot modes", - None), - ("USB_EXCHG_PINS", "usb config", 0, 1, 25, "bool", 30, None, None, "Exchanges USB D+ and D- pins", None), - ("VDD_SPI_AS_GPIO", "config", 0, 1, 26, "bool", 30, None, None, "Set this bit to vdd spi pin function as gpio", None), - ("BTLC_GPIO_ENABLE", "config", 0, 1, 27, "uint:2", 30, None, None, "Enable btlc gpio", None), - ("POWERGLITCH_EN", "config", 0, 1, 29, "bool", 30, None, None, "Set this bit to enable power glitch function", None), - ("POWER_GLITCH_DSENSE", "config", 0, 1, 30, "uint:2", 30, None, None, "Sample delay configuration of power glitch", None), - ("WDT_DELAY_SEL", "WDT config", 0, 2, 16, "bool", 3, None, None, "Selects RTC WDT timeout threshold at startup", None), - ("SPI_BOOT_CRYPT_CNT", "security", 0, 2, 18, "uint:3", 4, None, "bitcount", "Enables encryption and decryption, when an SPI boot " - "mode is set. Enabled when 1 or 3 bits are set," - "disabled otherwise", - {0: "Disable", - 1: "Enable", - 3: "Disable", - 7: "Enable"}), - ("SECURE_BOOT_KEY_REVOKE0", "security", 0, 2, 21, "bool", 5, None, None, "If set, revokes use of secure boot key digest 0", None), - ("SECURE_BOOT_KEY_REVOKE1", "security", 0, 2, 22, "bool", 6, None, None, "If set, revokes use of secure boot key digest 1", None), - ("SECURE_BOOT_KEY_REVOKE2", "security", 0, 2, 23, "bool", 7, None, None, "If set, revokes use of secure boot key digest 2", None), - ("KEY_PURPOSE_0", "security", 0, 2, 24, "uint:4", 8, None, "keypurpose", "KEY0 purpose", None), - ("KEY_PURPOSE_1", "security", 0, 2, 28, "uint:4", 9, None, "keypurpose", "KEY1 purpose", None), - ("KEY_PURPOSE_2", "security", 0, 3, 0, "uint:4", 10, None, "keypurpose", "KEY2 purpose", None), - ("KEY_PURPOSE_3", "security", 0, 3, 4, "uint:4", 11, None, "keypurpose", "KEY3 purpose", None), - ("KEY_PURPOSE_4", "security", 0, 3, 8, "uint:4", 12, None, "keypurpose", "KEY4 purpose", None), - ("KEY_PURPOSE_5", "security", 0, 3, 12, "uint:4", 13, None, "keypurpose", "KEY5 purpose", None), - ("SECURE_BOOT_EN", "security", 0, 3, 20, "bool", 15, None, None, "Enables secure boot", None), - ("SECURE_BOOT_AGGRESSIVE_REVOKE", "security", 0, 3, 21, "bool", 16, None, None, "Enables aggressive secure boot key revocation mode", - None), - ("FLASH_TPUW", "flash config", 0, 3, 28, "uint:4", 18, None, None, "Configures flash startup delay after SoC power-up, " - "unit is (ms/2). When the value is 15, delay is 7.5 ms", - None), - ("DIS_DOWNLOAD_MODE", "security", 0, 4, 0, "bool", 18, None, None, "Disables all Download boot modes", None), - ("DIS_DIRECT_BOOT", "config", 0, 4, 1, "bool", 18, None, None, "Disables direct boot mode", None), - ("UART_PRINT_CHANNEL", "config", 0, 4, 2, "bool", 18, None, None, "Selects the default UART for printing boot msg", - {0: "UART0", - 1: "UART1"}), - ("FLASH_ECC_MODE", "flash config", 0, 4, 3, "bool", 18, None, None, "Set this bit to set flsah ecc mode.", - {0: "flash ecc 16to18 byte mode", - 1: "flash ecc 16to17 byte mode"}), - ("DIS_USB_DOWNLOAD_MODE", "usb config", 0, 4, 4, "bool", 18, None, None, "Disables use of USB in UART download boot mode", None), - ("ENABLE_SECURITY_DOWNLOAD", "security", 0, 4, 5, "bool", 18, None, None, "Enables secure UART download mode " - "(read/write flash only)", None), - ("UART_PRINT_CONTROL", "config", 0, 4, 6, "uint:2", 18, None, None, "Sets the default UART boot message output mode", - {0: "Enabled", - 1: "Enable when GPIO8 is low at reset", - 2: "Enable when GPIO8 is high at reset", - 3: "Disabled"}), - ("PIN_POWER_SELECTION", "VDD_SPI config", 0, 4, 8, "bool", 18, None, None, "GPIO33-GPIO37 power supply selection in ROM code", - {0: "VDD3P3_CPU", - 1: "VDD_SPI"}), - ("FLASH_TYPE", "flash config", 0, 4, 9, "bool", 18, None, None, "Selects SPI flash type", - {0: "4 data lines", - 1: "8 data lines"}), - ("FLASH_PAGE_SIZE", "flash config", 0, 4, 10, "uint:2", 18, None, None, "Flash page size", None), - ("FLASH_ECC_EN", "flash config", 0, 4, 12, "bool", 18, None, None, "Enable ECC for flash boot", None), - ("FORCE_SEND_RESUME", "config", 0, 4, 13, "bool", 18, None, None, "Force ROM code to send a resume command during SPI boot" - "during SPI boot", None), - ("SECURE_VERSION", "identity", 0, 4, 14, "uint:16", 18, None, "bitcount", "Secure version (used by ESP-IDF anti-rollback feature)", - None), - ("DISABLE_WAFER_VERSION_MAJOR", "config", 0, 5, 0, "bool", 19, None, None, "Disables check of wafer version major", None), - ("DISABLE_BLK_VERSION_MAJOR", "config", 0, 5, 1, "bool", 19, None, None, "Disables check of blk version major", None), - # - # Table 53: Parameters in BLOCK1-10 - # Name Category Block Word Pos Type:len WR_DIS RD_DIS Class Description Dictionary - ("MAC", "identity", 1, 0, 0, "bytes:6", 20, None, "mac", "Factory MAC Address", None), - ("SPI_PAD_CONFIG_CLK", "spi_pad_config", 1, 1, 16, "uint:6", 20, None, None, "SPI CLK pad", None), - ("SPI_PAD_CONFIG_Q", "spi_pad_config", 1, 1, 22, "uint:6", 20, None, None, "SPI Q (D1) pad", None), - ("SPI_PAD_CONFIG_D", "spi_pad_config", 1, 1, 28, "uint:6", 20, None, None, "SPI D (D0) pad", None), - ("SPI_PAD_CONFIG_CS", "spi_pad_config", 1, 2, 2, "uint:6", 20, None, None, "SPI CS pad", None), - ("SPI_PAD_CONFIG_HD", "spi_pad_config", 1, 2, 8, "uint:6", 20, None, None, "SPI HD (D3) pad", None), - ("SPI_PAD_CONFIG_WP", "spi_pad_config", 1, 2, 14, "uint:6", 20, None, None, "SPI WP (D2) pad", None), - ("SPI_PAD_CONFIG_DQS", "spi_pad_config", 1, 2, 20, "uint:6", 20, None, None, "SPI DQS pad", None), - ("SPI_PAD_CONFIG_D4", "spi_pad_config", 1, 2, 26, "uint:6", 20, None, None, "SPI D4 pad", None), - ("SPI_PAD_CONFIG_D5", "spi_pad_config", 1, 3, 0, "uint:6", 20, None, None, "SPI D5 pad", None), - ("SPI_PAD_CONFIG_D6", "spi_pad_config", 1, 3, 6, "uint:6", 20, None, None, "SPI D6 pad", None), - ("SPI_PAD_CONFIG_D7", "spi_pad_config", 1, 3, 12, "uint:6", 20, None, None, "SPI D7 pad", None), - - ("WAFER_VERSION_MINOR_LO", "identity", 1, 3, 18, "uint:3", 20, None, None, "WAFER_VERSION_MINOR least significant bits", None), - ("PKG_VERSION", "identity", 1, 3, 21, "uint:3", 20, None, None, "Package version", None), - ("BLK_VERSION_MINOR", "identity", 1, 3, 24, "uint:3", 20, None, None, "BLOCK version minor", None), - ("WAFER_VERSION_MINOR_HI", "identity", 1, 5, 23, "uint:1", 20, None, None, "WAFER_VERSION_MINOR most significant bits", None), - ("WAFER_VERSION_MAJOR", "identity", 1, 5, 24, "uint:2", 20, None, None, "WAFER_VERSION_MAJOR", None), - - ("OPTIONAL_UNIQUE_ID", "identity", 2, 0, 0, "bytes:16", 21, None, "keyblock", "Optional unique 128-bit ID", None), - ("BLK_VERSION_MAJOR", "identity", 2, 4, 0, "uint:2", 21, None, None, "BLOCK version major", - {0: "No calibration", - 1: "With calibration"}), - ("CUSTOM_MAC", "identity", 3, 6, 8, "bytes:6", 22, None, "mac", "Custom MAC Address", None), - ] - - KEYBLOCKS = [ - # Name Category Block Word Pos Type:len WR_DIS RD_DIS Class Description Dictionary - ('BLOCK_USR_DATA', "config", 3, 0, 0, "bytes:32", 22, None, None, "User data", None), - ('BLOCK_KEY0', "security", 4, 0, 0, "bytes:32", 23, 0, "keyblock", "Encryption key0 or user data", None), - ('BLOCK_KEY1', "security", 5, 0, 0, "bytes:32", 24, 1, "keyblock", "Encryption key1 or user data", None), - ('BLOCK_KEY2', "security", 6, 0, 0, "bytes:32", 25, 2, "keyblock", "Encryption key2 or user data", None), - ('BLOCK_KEY3', "security", 7, 0, 0, "bytes:32", 26, 3, "keyblock", "Encryption key3 or user data", None), - ('BLOCK_KEY4', "security", 8, 0, 0, "bytes:32", 27, 4, "keyblock", "Encryption key4 or user data", None), - ('BLOCK_KEY5', "security", 9, 0, 0, "bytes:32", 28, 5, "keyblock", "Encryption key5 or user data", None), - ('BLOCK_SYS_DATA2', "security", 10, 0, 0, "bytes:32", 29, 6, "keyblock", "System data (part 2)", None), - ] - - # if BLK_VERSION_MAJOR is 1, these efuse fields are in BLOCK2 - BLOCK2_CALIBRATION_EFUSES = [ - # Name Category Block Word Pos Type:len WR_DIS RD_DIS Class Description Dictionary - ('TEMP_SENSOR_CAL', "calibration", 2, 4, 7, "uint:9", 21, None, "t_sensor", "Temperature calibration", None), - ('ADC1_MODE0_D2', "calibration", 2, 4, 16, "uint:8", 21, None, "adc_tp", "ADC1 calibration 1", None), - ('ADC1_MODE1_D2', "calibration", 2, 4, 24, "uint:8", 21, None, "adc_tp", "ADC1 calibration 2", None), - ('ADC1_MODE2_D2', "calibration", 2, 5, 0, "uint:8", 21, None, "adc_tp", "ADC1 calibration 3", None), - ('ADC1_MODE3_D2', "calibration", 2, 5, 8, "uint:8", 21, None, "adc_tp", "ADC1 calibration 4", None), - ('ADC2_MODE0_D2', "calibration", 2, 5, 16, "uint:8", 21, None, "adc_tp", "ADC2 calibration 5", None), - ('ADC2_MODE1_D2', "calibration", 2, 5, 24, "uint:8", 21, None, "adc_tp", "ADC2 calibration 6", None), - ('ADC2_MODE2_D2', "calibration", 2, 6, 0, "uint:8", 21, None, "adc_tp", "ADC2 calibration 7", None), - ('ADC2_MODE3_D2', "calibration", 2, 6, 8, "uint:8", 21, None, "adc_tp", "ADC2 calibration 8", None), - ('ADC1_MODE0_D1', "calibration", 2, 6, 16, "uint:6", 21, None, "adc_tp", "ADC1 calibration 9", None), - ('ADC1_MODE1_D1', "calibration", 2, 6, 22, "uint:6", 21, None, "adc_tp", "ADC1 calibration 10", None), - ('ADC1_MODE2_D1', "calibration", 2, 6, 28, "uint:6", 21, None, "adc_tp", "ADC1 calibration 11", None), - ('ADC1_MODE3_D1', "calibration", 2, 7, 2, "uint:6", 21, None, "adc_tp", "ADC1 calibration 12", None), - ('ADC2_MODE0_D1', "calibration", 2, 7, 8, "uint:6", 21, None, "adc_tp", "ADC2 calibration 13", None), - ('ADC2_MODE1_D1', "calibration", 2, 7, 14, "uint:6", 21, None, "adc_tp", "ADC2 calibration 14", None), - ('ADC2_MODE2_D1', "calibration", 2, 7, 20, "uint:6", 21, None, "adc_tp", "ADC2 calibration 15", None), - ('ADC2_MODE3_D1', "calibration", 2, 7, 26, "uint:6", 21, None, "adc_tp", "ADC2 calibration 16", None), - ] - - CALC = [ - ("WAFER_VERSION_MINOR", "identity", 0, None, None, "uint:4", None, None, "wafer", "calc WAFER VERSION MINOR = WAFER_VERSION_MINOR_HI << 3 + WAFER_VERSION_MINOR_LO (read only)", None), - ] -# fmt: on + def __init__(self) -> None: + # List of efuse fields from TRM the chapter eFuse Controller. + self.EFUSES = [] + + self.KEYBLOCKS = [] + + # if BLK_VERSION_MINOR is 1, these efuse fields are in BLOCK2 + self.BLOCK2_CALIBRATION_EFUSES = [] + + self.CALC = [] + + dir_name = os.path.dirname(os.path.abspath(__file__)) + dir_name, file_name = os.path.split(dir_name) + file_name = file_name + ".yaml" + dir_name, _ = os.path.split(dir_name) + efuse_file = os.path.join(dir_name, "efuse_defs", file_name) + with open(f"{efuse_file}", "r") as r_file: + e_desc = yaml.safe_load(r_file) + super().__init__(e_desc) + + for i, efuse in enumerate(self.ALL_EFUSES): + if efuse.name in [ + "BLOCK_USR_DATA", + "BLOCK_KEY0", + "BLOCK_KEY1", + "BLOCK_KEY2", + "BLOCK_KEY3", + "BLOCK_KEY4", + "BLOCK_KEY5", + "BLOCK_SYS_DATA2", + ]: + if efuse.name == "BLOCK_USR_DATA": + efuse.bit_len = 256 + efuse.type = "bytes:32" + self.KEYBLOCKS.append(efuse) + self.ALL_EFUSES[i] = None + + elif efuse.category == "calibration": + self.BLOCK2_CALIBRATION_EFUSES.append(efuse) + self.ALL_EFUSES[i] = None + + f = Field() + f.name = "MAC_EUI64" + f.block = 1 + f.bit_len = 64 + f.type = f"bytes:{f.bit_len // 8}" + f.category = "MAC" + f.class_type = "mac" + f.description = "calc MAC_EUI64 = MAC[0]:MAC[1]:MAC[2]:MAC_EXT[0]:MAC_EXT[1]:MAC[3]:MAC[4]:MAC[5]" + self.CALC.append(f) + + for efuse in self.ALL_EFUSES: + if efuse is not None: + self.EFUSES.append(efuse) + + self.ALL_EFUSES = [] diff --git a/espefuse/efuse/esp32c6/operations.py b/espefuse/efuse/esp32c6/operations.py index 5905e5186..f8e450fa0 100644 --- a/espefuse/efuse/esp32c6/operations.py +++ b/espefuse/efuse/esp32c6/operations.py @@ -17,6 +17,7 @@ from ..base_operations import ( add_common_commands, add_force_write_always, + add_show_sensitive_info_option, burn_bit, burn_block_data, burn_efuse, @@ -55,6 +56,7 @@ def add_commands(subparsers, efuses): ) protect_options(burn_key) add_force_write_always(burn_key) + add_show_sensitive_info_option(burn_key) burn_key.add_argument( "block", help="Key block to burn", @@ -105,6 +107,7 @@ def add_commands(subparsers, efuses): ) protect_options(burn_key_digest) add_force_write_always(burn_key_digest) + add_show_sensitive_info_option(burn_key_digest) burn_key_digest.add_argument( "block", help="Key block to burn", @@ -191,38 +194,29 @@ def set_flash_voltage(esp, efuses, args): def adc_info(esp, efuses, args): print("") # fmt: off - if efuses["BLK_VERSION_MAJOR"].get() == 1: - print("Temperature Sensor Calibration = {}C".format(efuses["TEMP_SENSOR_CAL"].get())) + if efuses["BLK_VERSION_MINOR"].get() == 1: + print("Temperature Sensor Calibration = {}C".format(efuses["TEMP_CALIB"].get())) print("") - print("ADC1 readings stored in efuse BLOCK2:") - print(" MODE0 D1 reading (250mV): {}".format(efuses["ADC1_MODE0_D1"].get())) - print(" MODE0 D2 reading (600mV): {}".format(efuses["ADC1_MODE0_D2"].get())) - - print(" MODE1 D1 reading (250mV): {}".format(efuses["ADC1_MODE1_D1"].get())) - print(" MODE1 D2 reading (800mV): {}".format(efuses["ADC1_MODE1_D2"].get())) - - print(" MODE2 D1 reading (250mV): {}".format(efuses["ADC1_MODE2_D1"].get())) - print(" MODE2 D2 reading (1000mV): {}".format(efuses["ADC1_MODE2_D2"].get())) - - print(" MODE3 D1 reading (250mV): {}".format(efuses["ADC1_MODE3_D1"].get())) - print(" MODE3 D2 reading (2000mV): {}".format(efuses["ADC1_MODE3_D2"].get())) - - print("") - print("ADC2 readings stored in efuse BLOCK2:") - print(" MODE0 D1 reading (250mV): {}".format(efuses["ADC2_MODE0_D1"].get())) - print(" MODE0 D2 reading (600mV): {}".format(efuses["ADC2_MODE0_D2"].get())) - - print(" MODE1 D1 reading (250mV): {}".format(efuses["ADC2_MODE1_D1"].get())) - print(" MODE1 D2 reading (800mV): {}".format(efuses["ADC2_MODE1_D2"].get())) - - print(" MODE2 D1 reading (250mV): {}".format(efuses["ADC2_MODE2_D1"].get())) - print(" MODE2 D2 reading (1000mV): {}".format(efuses["ADC2_MODE2_D2"].get())) - - print(" MODE3 D1 reading (250mV): {}".format(efuses["ADC2_MODE3_D1"].get())) - print(" MODE3 D2 reading (2000mV): {}".format(efuses["ADC2_MODE3_D2"].get())) + print("ADC1 Calibration data stored in efuse BLOCK2:") + print(f"OCODE: {efuses['OCODE'].get()}") + print(f"INIT_CODE_ATTEN0: {efuses['ADC1_INIT_CODE_ATTEN0'].get()}") + print(f"INIT_CODE_ATTEN1: {efuses['ADC1_INIT_CODE_ATTEN1'].get()}") + print(f"INIT_CODE_ATTEN2: {efuses['ADC1_INIT_CODE_ATTEN2'].get()}") + print(f"INIT_CODE_ATTEN3: {efuses['ADC1_INIT_CODE_ATTEN3'].get()}") + print(f"CAL_VOL_ATTEN0: {efuses['ADC1_CAL_VOL_ATTEN0'].get()}") + print(f"CAL_VOL_ATTEN1: {efuses['ADC1_CAL_VOL_ATTEN1'].get()}") + print(f"CAL_VOL_ATTEN2: {efuses['ADC1_CAL_VOL_ATTEN2'].get()}") + print(f"CAL_VOL_ATTEN3: {efuses['ADC1_CAL_VOL_ATTEN3'].get()}") + print(f"INIT_CODE_ATTEN0_CH0: {efuses['ADC1_INIT_CODE_ATTEN0_CH0'].get()}") + print(f"INIT_CODE_ATTEN0_CH1: {efuses['ADC1_INIT_CODE_ATTEN0_CH1'].get()}") + print(f"INIT_CODE_ATTEN0_CH2: {efuses['ADC1_INIT_CODE_ATTEN0_CH2'].get()}") + print(f"INIT_CODE_ATTEN0_CH3: {efuses['ADC1_INIT_CODE_ATTEN0_CH3'].get()}") + print(f"INIT_CODE_ATTEN0_CH4: {efuses['ADC1_INIT_CODE_ATTEN0_CH4'].get()}") + print(f"INIT_CODE_ATTEN0_CH5: {efuses['ADC1_INIT_CODE_ATTEN0_CH5'].get()}") + print(f"INIT_CODE_ATTEN0_CH6: {efuses['ADC1_INIT_CODE_ATTEN0_CH6'].get()}") else: - print("BLK_VERSION_MAJOR = {}".format(efuses["BLK_VERSION_MAJOR"].get_meaning())) + print("BLK_VERSION_MINOR = {}".format(efuses["BLK_VERSION_MINOR"].get_meaning())) # fmt: on @@ -276,7 +270,13 @@ def burn_key(esp, efuses, args, digest=None): if efuses[block.key_purpose_name].need_reverse(keypurpose): revers_msg = "\tReversing byte order for AES-XTS hardware peripheral" data = data[::-1] - print("-> [%s]" % (util.hexify(data, " "))) + print( + "-> [{}]".format( + util.hexify(data, " ") + if args.show_sensitive_info + else " ".join(["??"] * len(data)) + ) + ) if revers_msg: print(revers_msg) if len(data) != num_bytes: diff --git a/espefuse/efuse/esp32h2/emulate_efuse_controller.py b/espefuse/efuse/esp32h2/emulate_efuse_controller.py index c4c839da6..c8d3cd91a 100644 --- a/espefuse/efuse/esp32h2/emulate_efuse_controller.py +++ b/espefuse/efuse/esp32h2/emulate_efuse_controller.py @@ -16,13 +16,13 @@ class EmulateEfuseController(EmulateEfuseControllerBase): CHIP_NAME = "ESP32-H2" mem = None debug = False - Blocks = EfuseDefineBlocks - Fields = EfuseDefineFields - REGS = EfuseDefineRegisters def __init__(self, efuse_file=None, debug=False): + self.Blocks = EfuseDefineBlocks + self.Fields = EfuseDefineFields() + self.REGS = EfuseDefineRegisters super(EmulateEfuseController, self).__init__(efuse_file, debug) - self.write_reg(self.REGS.EFUSE_STATUS_REG, 1) + self.write_reg(self.REGS.EFUSE_CMD_REG, 0) """ esptool method start >>""" @@ -53,10 +53,10 @@ def handle_writing_event(self, addr, value): self.clean_blocks_wr_regs() self.check_rd_protection_area() self.write_reg(addr, 0) - self.write_reg(self.REGS.EFUSE_STATUS_REG, 1) + self.write_reg(self.REGS.EFUSE_CMD_REG, 0) elif value == self.REGS.EFUSE_READ_CMD: self.write_reg(addr, 0) - self.write_reg(self.REGS.EFUSE_STATUS_REG, 1) + self.write_reg(self.REGS.EFUSE_CMD_REG, 0) self.save_to_file() def get_bitlen_of_block(self, blk, wr=False): diff --git a/espefuse/efuse/esp32h2/fields.py b/espefuse/efuse/esp32h2/fields.py index 45bd29f01..add5db76f 100644 --- a/espefuse/efuse/esp32h2/fields.py +++ b/espefuse/efuse/esp32h2/fields.py @@ -54,16 +54,15 @@ class EspEfuses(base_fields.EspEfusesBase): Wrapper object to manage the efuse fields in a connected ESP bootloader """ - Blocks = EfuseDefineBlocks() - Fields = EfuseDefineFields() - REGS = EfuseDefineRegisters - BURN_BLOCK_DATA_NAMES = Blocks.get_burn_block_data_names() - BLOCKS_FOR_KEYS = Blocks.get_blocks_for_keys() - debug = False do_not_confirm = False def __init__(self, esp, skip_connect=False, debug=False, do_not_confirm=False): + self.Blocks = EfuseDefineBlocks() + self.Fields = EfuseDefineFields() + self.REGS = EfuseDefineRegisters + self.BURN_BLOCK_DATA_NAMES = self.Blocks.get_burn_block_data_names() + self.BLOCKS_FOR_KEYS = self.Blocks.get_blocks_for_keys() self._esp = esp self.debug = debug self.do_not_confirm = do_not_confirm @@ -85,59 +84,43 @@ def __init__(self, esp, skip_connect=False, debug=False, do_not_confirm=False): ] if not skip_connect: self.get_coding_scheme_warnings() - self.efuses = [ - EfuseField.from_tuple( - self, self.Fields.get(efuse), self.Fields.get(efuse).class_type - ) - for efuse in self.Fields.EFUSES - ] + self.efuses = [EfuseField.convert(self, efuse) for efuse in self.Fields.EFUSES] self.efuses += [ - EfuseField.from_tuple( - self, self.Fields.get(efuse), self.Fields.get(efuse).class_type - ) - for efuse in self.Fields.KEYBLOCKS + EfuseField.convert(self, efuse) for efuse in self.Fields.KEYBLOCKS ] if skip_connect: self.efuses += [ - EfuseField.from_tuple( - self, self.Fields.get(efuse), self.Fields.get(efuse).class_type - ) + EfuseField.convert(self, efuse) for efuse in self.Fields.BLOCK2_CALIBRATION_EFUSES ] else: - if self["BLK_VERSION_MAJOR"].get() == 1: + if self["BLK_VERSION_MINOR"].get() == 2: self.efuses += [ - EfuseField.from_tuple( - self, self.Fields.get(efuse), self.Fields.get(efuse).class_type - ) + EfuseField.convert(self, efuse) for efuse in self.Fields.BLOCK2_CALIBRATION_EFUSES ] self.efuses += [ - EfuseField.from_tuple( - self, self.Fields.get(efuse), self.Fields.get(efuse).class_type - ) - for efuse in self.Fields.CALC + EfuseField.convert(self, efuse) for efuse in self.Fields.CALC ] def __getitem__(self, efuse_name): """Return the efuse field with the given name""" for e in self.efuses: - if efuse_name == e.name: + if efuse_name == e.name or any(x == efuse_name for x in e.alt_names): return e new_fields = False for efuse in self.Fields.BLOCK2_CALIBRATION_EFUSES: - e = self.Fields.get(efuse) - if e.name == efuse_name: + if efuse.name == efuse_name or any( + x == efuse_name for x in efuse.alt_names + ): self.efuses += [ - EfuseField.from_tuple( - self, self.Fields.get(efuse), self.Fields.get(efuse).class_type - ) + EfuseField.convert(self, efuse) for efuse in self.Fields.BLOCK2_CALIBRATION_EFUSES ] new_fields = True if new_fields: for e in self.efuses: - if efuse_name == e.name: + if efuse_name == e.name or any(x == efuse_name for x in e.alt_names): return e raise KeyError @@ -158,10 +141,6 @@ def print_status_regs(self): ) ) - def get_block_errors(self, block_num): - """Returns (error count, failure boolean flag)""" - return self.blocks[block_num].num_errors, self.blocks[block_num].fail - def efuse_controller_setup(self): self.set_efuse_timing() self.clear_pgm_registers() @@ -181,9 +160,13 @@ def clear_pgm_registers(self): def wait_efuse_idle(self): deadline = time.time() + self.REGS.EFUSE_BURN_TIMEOUT while time.time() < deadline: - # if self.read_reg(self.REGS.EFUSE_CMD_REG) == 0: - if self.read_reg(self.REGS.EFUSE_STATUS_REG) & 0x7 == 1: - return + cmds = self.REGS.EFUSE_PGM_CMD | self.REGS.EFUSE_READ_CMD + if self.read_reg(self.REGS.EFUSE_CMD_REG) & cmds == 0: + if self.read_reg(self.REGS.EFUSE_CMD_REG) & cmds == 0: + # Due to a hardware error, we have to read READ_CMD again + # to make sure the efuse clock is normal. + # For PGM_CMD it is not necessary. + return raise esptool.FatalError( "Timed out waiting for Efuse controller command to complete" ) @@ -250,12 +233,21 @@ def set_efuse_timing(self): "The eFuse supports only xtal=32M (xtal was %d)" % apb_freq ) + self.update_reg(self.REGS.EFUSE_DAC_CONF_REG, self.REGS.EFUSE_DAC_NUM_M, 0xFF) + self.update_reg( + self.REGS.EFUSE_DAC_CONF_REG, self.REGS.EFUSE_DAC_CLK_DIV_M, 0x28 + ) + self.update_reg( + self.REGS.EFUSE_WR_TIM_CONF1_REG, self.REGS.EFUSE_PWR_ON_NUM_M, 0x3000 + ) self.update_reg( self.REGS.EFUSE_WR_TIM_CONF2_REG, self.REGS.EFUSE_PWR_OFF_NUM_M, 0x190 ) def get_coding_scheme_warnings(self, silent=False): """Check if the coding scheme has detected any errors.""" + old_addr_reg = 0 + reg_value = 0 ret_fail = False for block in self.blocks: if block.id == 0: @@ -263,29 +255,22 @@ def get_coding_scheme_warnings(self, silent=False): self.read_reg(self.REGS.EFUSE_RD_REPEAT_ERR0_REG + offs * 4) for offs in range(5) ] - data = BitArray() + block.err_bitarray.pos = 0 for word in reversed(words): - data.append("uint:32=%d" % word) - # pos=32 because EFUSE_WR_DIS goes first it is 32bit long - # and not under error control - block.err_bitarray.overwrite(data, pos=32) + block.err_bitarray.overwrite(BitArray("uint:32=%d" % word)) block.num_errors = block.err_bitarray.count(True) block.fail = block.num_errors != 0 else: - addr_reg_f, fail_bit = self.REGS.BLOCK_FAIL_BIT[block.id] - if fail_bit is None: - block.fail = False - else: - block.fail = self.read_reg(addr_reg_f) & (1 << fail_bit) != 0 - - addr_reg_n, num_mask, num_offs = self.REGS.BLOCK_NUM_ERRORS[block.id] - if num_mask is None or num_offs is None: - block.num_errors = 0 - else: - block.num_errors = ( - self.read_reg(addr_reg_n) >> num_offs - ) & num_mask - + addr_reg, err_num_mask, err_num_offs, fail_bit = self.REGS.BLOCK_ERRORS[ + block.id + ] + if err_num_mask is None or err_num_offs is None or fail_bit is None: + continue + if addr_reg != old_addr_reg: + old_addr_reg = addr_reg + reg_value = self.read_reg(addr_reg) + block.fail = reg_value & (1 << fail_bit) != 0 + block.num_errors = (reg_value >> err_num_offs) & err_num_mask ret_fail |= block.fail if not silent and (block.fail or block.num_errors): print( @@ -303,35 +288,22 @@ def summary(self): class EfuseField(base_fields.EfuseFieldBase): @staticmethod - def from_tuple(parent, efuse_tuple, type_class): + def convert(parent, efuse): return { "mac": EfuseMacField, "keypurpose": EfuseKeyPurposeField, "t_sensor": EfuseTempSensor, "adc_tp": EfuseAdcPointCalibration, "wafer": EfuseWafer, - }.get(type_class, EfuseField)(parent, efuse_tuple) - - def get_info(self): - output = "%s (BLOCK%d)" % (self.name, self.block) - errs, fail = self.parent.get_block_errors(self.block) - if errs != 0 or fail: - output += ( - "[FAIL:%d]" % (fail) - if self.block == 0 - else "[ERRS:%d FAIL:%d]" % (errs, fail) - ) - if self.efuse_class == "keyblock": - name = self.parent.blocks[self.block].key_purpose_name - if name is not None: - output += "\n Purpose: %s\n " % (self.parent[name].get()) - return output + }.get(efuse.class_type, EfuseField)(parent, efuse) class EfuseWafer(EfuseField): def get(self, from_read=True): hi_bits = self.parent["WAFER_VERSION_MINOR_HI"].get(from_read) + assert self.parent["WAFER_VERSION_MINOR_HI"].bit_len == 1 lo_bits = self.parent["WAFER_VERSION_MINOR_LO"].get(from_read) + assert self.parent["WAFER_VERSION_MINOR_LO"].bit_len == 3 return (hi_bits << 3) + lo_bits def save(self, new_value): @@ -359,23 +331,27 @@ def check_format(self, new_value_str): raise esptool.FatalError( "Required MAC Address in AA:CD:EF:01:02:03 format!" ) - if new_value_str.count(":") != 5: + num_bytes = 8 if self.name == "MAC_EUI64" else 6 + if new_value_str.count(":") != num_bytes - 1: raise esptool.FatalError( - "MAC Address needs to be a 6-byte hexadecimal format " + f"MAC Address needs to be a {num_bytes}-byte hexadecimal format " "separated by colons (:)!" ) hexad = new_value_str.replace(":", "") - if len(hexad) != 12: + hexad = hexad.split(" ", 1)[0] if self.is_field_calculated() else hexad + if len(hexad) != num_bytes * 2: raise esptool.FatalError( - "MAC Address needs to be a 6-byte hexadecimal number " - "(12 hexadecimal characters)!" + f"MAC Address needs to be a {num_bytes}-byte hexadecimal number " + f"({num_bytes * 2} hexadecimal characters)!" ) # order of bytearray = b'\xaa\xcd\xef\x01\x02\x03', bindata = binascii.unhexlify(hexad) - # unicast address check according to - # https://tools.ietf.org/html/rfc7042#section-2.1 - if esptool.util.byte(bindata, 0) & 0x01: - raise esptool.FatalError("Custom MAC must be a unicast MAC!") + + if not self.is_field_calculated(): + # unicast address check according to + # https://tools.ietf.org/html/rfc7042#section-2.1 + if esptool.util.byte(bindata, 0) & 0x01: + raise esptool.FatalError("Custom MAC must be a unicast MAC!") return bindata def check(self): @@ -389,6 +365,13 @@ def check(self): def get(self, from_read=True): if self.name == "CUSTOM_MAC": mac = self.get_raw(from_read)[::-1] + elif self.name == "MAC": + mac = self.get_raw(from_read) + elif self.name == "MAC_EUI64": + mac = self.parent["MAC"].get_bitstring(from_read).copy() + mac_ext = self.parent["MAC_EXT"].get_bitstring(from_read) + mac.insert(mac_ext, 24) + mac = mac.bytes else: mac = self.get_raw(from_read) return "%s %s" % (util.hexify(mac, ":"), self.check()) @@ -408,14 +391,15 @@ def print_field(e, new_value): else: # Writing the BLOCK1 (MAC_SPI_8M_0) default MAC is not possible, # as it's written in the factory. - raise esptool.FatalError("Writing Factory MAC address is not supported") + raise esptool.FatalError(f"Burning {self.name} is not supported") # fmt: off class EfuseKeyPurposeField(EfuseField): KEY_PURPOSES = [ ("USER", 0, None, None, "no_need_rd_protect"), # User purposes (software-only use) - ("RESERVED", 1, None, None, "no_need_rd_protect"), # Reserved + ("ECDSA_KEY", 1, None, "Reverse", "need_rd_protect"), # ECDSA key + ("RESERVED", 2, None, None, "no_need_rd_protect"), # Reserved ("XTS_AES_128_KEY", 4, None, "Reverse", "need_rd_protect"), # XTS_AES_128_KEY (flash/PSRAM encryption) ("HMAC_DOWN_ALL", 5, None, None, "need_rd_protect"), # HMAC Downstream mode ("HMAC_DOWN_JTAG", 6, None, None, "need_rd_protect"), # JTAG soft enable key (uses HMAC Downstream mode) @@ -460,6 +444,14 @@ def get(self, from_read=True): return p[0] return "FORBIDDEN_STATE" + def get_name(self, raw_val): + for key in self.KEY_PURPOSES: + if key[1] == raw_val: + return key[0] + def save(self, new_value): raw_val = int(self.check_format(str(new_value))) + str_new_value = self.get_name(raw_val) + if self.name == "KEY_PURPOSE_5" and str_new_value in ["XTS_AES_128_KEY", "ECDSA_KEY"]: + raise esptool.FatalError(f"{self.name} can not have {str_new_value} key due to a hardware bug (please see TRM for more details)") return super(EfuseKeyPurposeField, self).save(raw_val) diff --git a/espefuse/efuse/esp32h2/mem_definition.py b/espefuse/efuse/esp32h2/mem_definition.py index a49ce9a0d..d08a71f0c 100644 --- a/espefuse/efuse/esp32h2/mem_definition.py +++ b/espefuse/efuse/esp32h2/mem_definition.py @@ -4,24 +4,31 @@ # # SPDX-License-Identifier: GPL-2.0-or-later -from ..mem_definition_base import EfuseBlocksBase, EfuseFieldsBase, EfuseRegistersBase +import os +import yaml + +from ..mem_definition_base import ( + EfuseBlocksBase, + EfuseFieldsBase, + EfuseRegistersBase, + Field, +) -# fmt: off -class EfuseDefineRegisters(EfuseRegistersBase): - EFUSE_MEM_SIZE = (0x01FC + 4) +class EfuseDefineRegisters(EfuseRegistersBase): + EFUSE_MEM_SIZE = 0x01FC + 4 # EFUSE registers & command/conf values - DR_REG_EFUSE_BASE = 0x600B0800 - EFUSE_PGM_DATA0_REG = DR_REG_EFUSE_BASE - EFUSE_CHECK_VALUE0_REG = DR_REG_EFUSE_BASE + 0x020 - EFUSE_CLK_REG = DR_REG_EFUSE_BASE + 0x1C8 - EFUSE_CONF_REG = DR_REG_EFUSE_BASE + 0x1CC - EFUSE_STATUS_REG = DR_REG_EFUSE_BASE + 0x1D0 - EFUSE_CMD_REG = DR_REG_EFUSE_BASE + 0x1D4 - EFUSE_RD_RS_ERR0_REG = DR_REG_EFUSE_BASE + 0x1C0 - EFUSE_RD_RS_ERR1_REG = DR_REG_EFUSE_BASE + 0x1C4 + DR_REG_EFUSE_BASE = 0x600B0800 + EFUSE_PGM_DATA0_REG = DR_REG_EFUSE_BASE + EFUSE_CHECK_VALUE0_REG = DR_REG_EFUSE_BASE + 0x020 + EFUSE_CLK_REG = DR_REG_EFUSE_BASE + 0x1C8 + EFUSE_CONF_REG = DR_REG_EFUSE_BASE + 0x1CC + EFUSE_STATUS_REG = DR_REG_EFUSE_BASE + 0x1D0 + EFUSE_CMD_REG = DR_REG_EFUSE_BASE + 0x1D4 + EFUSE_RD_RS_ERR0_REG = DR_REG_EFUSE_BASE + 0x1C0 + EFUSE_RD_RS_ERR1_REG = DR_REG_EFUSE_BASE + 0x1C4 EFUSE_RD_REPEAT_ERR0_REG = DR_REG_EFUSE_BASE + 0x17C EFUSE_RD_REPEAT_ERR1_REG = DR_REG_EFUSE_BASE + 0x180 EFUSE_RD_REPEAT_ERR2_REG = DR_REG_EFUSE_BASE + 0x184 @@ -32,53 +39,49 @@ class EfuseDefineRegisters(EfuseRegistersBase): EFUSE_WR_TIM_CONF1_REG = DR_REG_EFUSE_BASE + 0x1F0 EFUSE_WR_TIM_CONF2_REG = DR_REG_EFUSE_BASE + 0x1F4 EFUSE_DATE_REG = DR_REG_EFUSE_BASE + 0x1FC - EFUSE_WRITE_OP_CODE = 0x5A5A - EFUSE_READ_OP_CODE = 0x5AA5 - EFUSE_PGM_CMD_MASK = 0x3 - EFUSE_PGM_CMD = 0x2 - EFUSE_READ_CMD = 0x1 - - # this chip has a design error so fail_bit is shifted by one block but err_num is in the correct place - BLOCK_FAIL_BIT = [ - # error_reg, fail_bit - (EFUSE_RD_REPEAT_ERR0_REG, None), # BLOCK0 - (EFUSE_RD_RS_ERR0_REG, 7), # MAC_SPI_8M_0 - (EFUSE_RD_RS_ERR0_REG, 11), # BLOCK_SYS_DATA - (EFUSE_RD_RS_ERR0_REG, 15), # BLOCK_USR_DATA - (EFUSE_RD_RS_ERR0_REG, 19), # BLOCK_KEY0 - (EFUSE_RD_RS_ERR0_REG, 23), # BLOCK_KEY1 - (EFUSE_RD_RS_ERR0_REG, 27), # BLOCK_KEY2 - (EFUSE_RD_RS_ERR0_REG, 31), # BLOCK_KEY3 - (EFUSE_RD_RS_ERR1_REG, 3), # BLOCK_KEY4 - (EFUSE_RD_RS_ERR1_REG, 7), # BLOCK_KEY5 - (EFUSE_RD_RS_ERR1_REG, None), # BLOCK_SYS_DATA2 - ] - - BLOCK_NUM_ERRORS = [ - # error_reg, err_num_mask, err_num_offs - (EFUSE_RD_REPEAT_ERR0_REG, None, None), # BLOCK0 - (EFUSE_RD_RS_ERR0_REG, 0x7, 0), # MAC_SPI_8M_0 - (EFUSE_RD_RS_ERR0_REG, 0x7, 4), # BLOCK_SYS_DATA - (EFUSE_RD_RS_ERR0_REG, 0x7, 8), # BLOCK_USR_DATA - (EFUSE_RD_RS_ERR0_REG, 0x7, 12), # BLOCK_KEY0 - (EFUSE_RD_RS_ERR0_REG, 0x7, 16), # BLOCK_KEY1 - (EFUSE_RD_RS_ERR0_REG, 0x7, 20), # BLOCK_KEY2 - (EFUSE_RD_RS_ERR0_REG, 0x7, 24), # BLOCK_KEY3 - (EFUSE_RD_RS_ERR0_REG, 0x7, 28), # BLOCK_KEY4 - (EFUSE_RD_RS_ERR1_REG, 0x7, 0), # BLOCK_KEY5 - (EFUSE_RD_RS_ERR1_REG, 0x7, 4), # BLOCK_SYS_DATA2 + EFUSE_WRITE_OP_CODE = 0x5A5A + EFUSE_READ_OP_CODE = 0x5AA5 + EFUSE_PGM_CMD_MASK = 0x3 + EFUSE_PGM_CMD = 0x2 + EFUSE_READ_CMD = 0x1 + + BLOCK_ERRORS = [ + # error_reg, err_num_mask, err_num_offs, fail_bit + (EFUSE_RD_REPEAT_ERR0_REG, None, None, None), # BLOCK0 + (EFUSE_RD_RS_ERR0_REG, 0x7, 0, 3), # MAC_SPI_8M_0 + (EFUSE_RD_RS_ERR0_REG, 0x7, 4, 7), # BLOCK_SYS_DATA + (EFUSE_RD_RS_ERR0_REG, 0x7, 8, 11), # BLOCK_USR_DATA + (EFUSE_RD_RS_ERR0_REG, 0x7, 12, 15), # BLOCK_KEY0 + (EFUSE_RD_RS_ERR0_REG, 0x7, 16, 19), # BLOCK_KEY1 + (EFUSE_RD_RS_ERR0_REG, 0x7, 20, 23), # BLOCK_KEY2 + (EFUSE_RD_RS_ERR0_REG, 0x7, 24, 27), # BLOCK_KEY3 + (EFUSE_RD_RS_ERR0_REG, 0x7, 28, 31), # BLOCK_KEY4 + (EFUSE_RD_RS_ERR1_REG, 0x7, 0, 3), # BLOCK_KEY5 + (EFUSE_RD_RS_ERR1_REG, 0x7, 4, 7), # BLOCK_SYS_DATA2 ] # EFUSE_WR_TIM_CONF2_REG EFUSE_PWR_OFF_NUM_S = 0 EFUSE_PWR_OFF_NUM_M = 0xFFFF << EFUSE_PWR_OFF_NUM_S + # EFUSE_WR_TIM_CONF1_REG + EFUSE_PWR_ON_NUM_S = 8 + EFUSE_PWR_ON_NUM_M = 0x0000FFFF << EFUSE_PWR_ON_NUM_S -class EfuseDefineBlocks(EfuseBlocksBase): + # EFUSE_DAC_CONF_REG + EFUSE_DAC_CLK_DIV_S = 0 + EFUSE_DAC_CLK_DIV_M = 0xFF << EFUSE_DAC_CLK_DIV_S + + # EFUSE_DAC_CONF_REG + EFUSE_DAC_NUM_S = 9 + EFUSE_DAC_NUM_M = 0xFF << EFUSE_DAC_NUM_S + +class EfuseDefineBlocks(EfuseBlocksBase): __base_rd_regs = EfuseDefineRegisters.DR_REG_EFUSE_BASE __base_wr_regs = EfuseDefineRegisters.EFUSE_PGM_DATA0_REG # List of efuse blocks + # fmt: off BLOCKS = [ # Name, Alias, Index, Read address, Write address, Write protect bit, Read protect bit, Len, key_purpose ("BLOCK0", [], 0, __base_rd_regs + 0x02C, __base_wr_regs, None, None, 6, None), @@ -93,6 +96,7 @@ class EfuseDefineBlocks(EfuseBlocksBase): ("BLOCK_KEY5", ["BLOCK9"], 9, __base_rd_regs + 0x13C, __base_wr_regs, 28, 5, 8, "KEY_PURPOSE_5"), ("BLOCK_SYS_DATA2", ["BLOCK10"], 10, __base_rd_regs + 0x15C, __base_wr_regs, 29, 6, 8, None), ] + # fmt: on def get_burn_block_data_names(self): list_of_names = [] @@ -107,152 +111,59 @@ def get_burn_block_data_names(self): class EfuseDefineFields(EfuseFieldsBase): - - # List of efuse fields from TRM the chapter eFuse Controller. - EFUSES = [ - # - # Table 51: Parameters in BLOCK0 - # Name Category Block Word Pos Type:len WR_DIS RD_DIS Class Description Dictionary - ("WR_DIS", "efuse", 0, 0, 0, "uint:32", None, None, None, "Disables programming of individual eFuses", None), - ("RD_DIS", "efuse", 0, 1, 0, "uint:7", 0, None, None, "Disables software reading from BLOCK4-10", None), - ("DIS_ICACHE", "config", 0, 1, 8, "bool", 2, None, None, "Disables ICache", None), - ("DIS_USB_JTAG", "usb config", 0, 1, 9, "bool", 2, None, None, "Disables USB JTAG. " - "JTAG access via pads is controlled separately", None), - ("DIS_DOWNLOAD_ICACHE", "config", 0, 1, 10, "bool", 2, None, None, "Disables Icache when SoC is in Download mode", None), - ("DIS_USB_DEVICE", "usb config", 0, 1, 11, "bool", 2, None, None, "Disables USB DEVICE", None), - ("DIS_FORCE_DOWNLOAD", "config", 0, 1, 12, "bool", 2, None, None, "Disables forcing chip into Download mode", None), - ("DIS_USB", "usb config", 0, 1, 13, "bool", 2, None, None, "Disables the USB OTG hardware", None), - ("DIS_CAN", "config", 0, 1, 14, "bool", 2, None, None, "Disables the TWAI Controller hardware", None), - ("JTAG_SEL_ENABLE", "jtag config", 0, 1, 15, "bool", 2, None, None, "Set this bit to enable selection between " - "usb_to_jtag and pad_to_jtag through strapping " - "gpio10 when both reg_dis_usb_jtag and " - "reg_dis_pad_jtag are equal to 0.", None), - ("SOFT_DIS_JTAG", "jtag config", 0, 1, 16, "uint:3", 2, None, None, "Software disables JTAG. When software disabled, " - "JTAG can be activated temporarily by HMAC peripheral", - None), - ("DIS_PAD_JTAG", "jtag config", 0, 1, 19, "bool", 2, None, None, "Permanently disable JTAG access via pads. " - "USB JTAG is controlled separately.", None), - ("DIS_DOWNLOAD_MANUAL_ENCRYPT", "security", 0, 1, 20, "bool", 2, None, None, "Disables flash encryption when in download boot modes", - None), - ("USB_EXCHG_PINS", "usb config", 0, 1, 25, "bool", 30, None, None, "Exchanges USB D+ and D- pins", None), - ("VDD_SPI_AS_GPIO", "config", 0, 1, 26, "bool", 30, None, None, "Set this bit to vdd spi pin function as gpio", None), - ("BTLC_GPIO_ENABLE", "config", 0, 1, 27, "uint:2", 30, None, None, "Enable btlc gpio", None), - ("POWERGLITCH_EN", "config", 0, 1, 29, "bool", 30, None, None, "Set this bit to enable power glitch function", None), - ("POWER_GLITCH_DSENSE", "config", 0, 1, 30, "uint:2", 30, None, None, "Sample delay configuration of power glitch", None), - ("WDT_DELAY_SEL", "WDT config", 0, 2, 16, "bool", 3, None, None, "Selects RTC WDT timeout threshold at startup", None), - ("SPI_BOOT_CRYPT_CNT", "security", 0, 2, 18, "uint:3", 4, None, "bitcount", "Enables encryption and decryption, when an SPI boot " - "mode is set. Enabled when 1 or 3 bits are set," - "disabled otherwise", - {0: "Disable", - 1: "Enable", - 3: "Disable", - 7: "Enable"}), - ("SECURE_BOOT_KEY_REVOKE0", "security", 0, 2, 21, "bool", 5, None, None, "If set, revokes use of secure boot key digest 0", None), - ("SECURE_BOOT_KEY_REVOKE1", "security", 0, 2, 22, "bool", 6, None, None, "If set, revokes use of secure boot key digest 1", None), - ("SECURE_BOOT_KEY_REVOKE2", "security", 0, 2, 23, "bool", 7, None, None, "If set, revokes use of secure boot key digest 2", None), - ("KEY_PURPOSE_0", "security", 0, 2, 24, "uint:4", 8, None, "keypurpose", "KEY0 purpose", None), - ("KEY_PURPOSE_1", "security", 0, 2, 28, "uint:4", 9, None, "keypurpose", "KEY1 purpose", None), - ("KEY_PURPOSE_2", "security", 0, 3, 0, "uint:4", 10, None, "keypurpose", "KEY2 purpose", None), - ("KEY_PURPOSE_3", "security", 0, 3, 4, "uint:4", 11, None, "keypurpose", "KEY3 purpose", None), - ("KEY_PURPOSE_4", "security", 0, 3, 8, "uint:4", 12, None, "keypurpose", "KEY4 purpose", None), - ("KEY_PURPOSE_5", "security", 0, 3, 12, "uint:4", 13, None, "keypurpose", "KEY5 purpose", None), - ("SECURE_BOOT_EN", "security", 0, 3, 20, "bool", 15, None, None, "Enables secure boot", None), - ("SECURE_BOOT_AGGRESSIVE_REVOKE", "security", 0, 3, 21, "bool", 16, None, None, "Enables aggressive secure boot key revocation mode", - None), - ("FLASH_TPUW", "flash config", 0, 3, 28, "uint:4", 18, None, None, "Configures flash startup delay after SoC power-up, " - "unit is (ms/2). When the value is 15, delay is 7.5 ms", - None), - ("DIS_DOWNLOAD_MODE", "security", 0, 4, 0, "bool", 18, None, None, "Disables all Download boot modes", None), - ("DIS_DIRECT_BOOT", "config", 0, 4, 1, "bool", 18, None, None, "Disables direct boot mode", None), - ("UART_PRINT_CHANNEL", "config", 0, 4, 2, "bool", 18, None, None, "Selects the default UART for printing boot msg", - {0: "UART0", - 1: "UART1"}), - ("FLASH_ECC_MODE", "flash config", 0, 4, 3, "bool", 18, None, None, "Set this bit to set flsah ecc mode.", - {0: "flash ecc 16to18 byte mode", - 1: "flash ecc 16to17 byte mode"}), - ("DIS_USB_DOWNLOAD_MODE", "usb config", 0, 4, 4, "bool", 18, None, None, "Disables use of USB in UART download boot mode", None), - ("ENABLE_SECURITY_DOWNLOAD", "security", 0, 4, 5, "bool", 18, None, None, "Enables secure UART download mode " - "(read/write flash only)", None), - ("UART_PRINT_CONTROL", "config", 0, 4, 6, "uint:2", 18, None, None, "Sets the default UART boot message output mode", - {0: "Enabled", - 1: "Enable when GPIO8 is low at reset", - 2: "Enable when GPIO8 is high at reset", - 3: "Disabled"}), - ("PIN_POWER_SELECTION", "VDD_SPI config", 0, 4, 8, "bool", 18, None, None, "GPIO33-GPIO37 power supply selection in ROM code", - {0: "VDD3P3_CPU", - 1: "VDD_SPI"}), - ("FLASH_PAGE_SIZE", "flash config", 0, 4, 10, "uint:2", 18, None, None, "Flash page size", None), - ("FLASH_ECC_EN", "flash config", 0, 4, 12, "bool", 18, None, None, "Enable ECC for flash boot", None), - ("FORCE_SEND_RESUME", "config", 0, 4, 13, "bool", 18, None, None, "Force ROM code to send a resume command during SPI boot" - "during SPI boot", None), - ("SECURE_VERSION", "identity", 0, 4, 14, "uint:16", 18, None, "bitcount", "Secure version (used by ESP-IDF anti-rollback feature)", - None), - ("DISABLE_WAFER_VERSION_MAJOR", "config", 0, 5, 0, "bool", 19, None, None, "Disables check of wafer version major", None), - ("DISABLE_BLK_VERSION_MAJOR", "config", 0, 5, 1, "bool", 19, None, None, "Disables check of blk version major", None), - # - # Table 53: Parameters in BLOCK1-10 - # Name Category Block Word Pos Type:len WR_DIS RD_DIS Class Description Dictionary - ("MAC", "identity", 1, 0, 0, "bytes:6", 20, None, "mac", "Factory MAC Address", None), - ("SPI_PAD_CONFIG_CLK", "spi_pad_config", 1, 1, 16, "uint:6", 20, None, None, "SPI CLK pad", None), - ("SPI_PAD_CONFIG_Q", "spi_pad_config", 1, 1, 22, "uint:6", 20, None, None, "SPI Q (D1) pad", None), - ("SPI_PAD_CONFIG_D", "spi_pad_config", 1, 1, 28, "uint:6", 20, None, None, "SPI D (D0) pad", None), - ("SPI_PAD_CONFIG_CS", "spi_pad_config", 1, 2, 2, "uint:6", 20, None, None, "SPI CS pad", None), - ("SPI_PAD_CONFIG_HD", "spi_pad_config", 1, 2, 8, "uint:6", 20, None, None, "SPI HD (D3) pad", None), - ("SPI_PAD_CONFIG_WP", "spi_pad_config", 1, 2, 14, "uint:6", 20, None, None, "SPI WP (D2) pad", None), - ("SPI_PAD_CONFIG_DQS", "spi_pad_config", 1, 2, 20, "uint:6", 20, None, None, "SPI DQS pad", None), - ("SPI_PAD_CONFIG_D4", "spi_pad_config", 1, 2, 26, "uint:6", 20, None, None, "SPI D4 pad", None), - ("SPI_PAD_CONFIG_D5", "spi_pad_config", 1, 3, 0, "uint:6", 20, None, None, "SPI D5 pad", None), - ("SPI_PAD_CONFIG_D6", "spi_pad_config", 1, 3, 6, "uint:6", 20, None, None, "SPI D6 pad", None), - ("SPI_PAD_CONFIG_D7", "spi_pad_config", 1, 3, 12, "uint:6", 20, None, None, "SPI D7 pad", None), - - ("WAFER_VERSION_MINOR_LO", "identity", 1, 3, 18, "uint:3", 20, None, None, "WAFER_VERSION_MINOR least significant bits", None), - ("PKG_VERSION", "identity", 1, 3, 21, "uint:3", 20, None, None, "Package version", None), - ("BLK_VERSION_MINOR", "identity", 1, 3, 24, "uint:3", 20, None, None, "BLOCK version minor", None), - ("WAFER_VERSION_MINOR_HI", "identity", 1, 5, 23, "uint:1", 20, None, None, "WAFER_VERSION_MINOR most significant bits", None), - ("WAFER_VERSION_MAJOR", "identity", 1, 5, 24, "uint:2", 20, None, None, "WAFER_VERSION_MAJOR", None), - - ("OPTIONAL_UNIQUE_ID", "identity", 2, 0, 0, "bytes:16", 21, None, "keyblock", "Optional unique 128-bit ID", None), - ("BLK_VERSION_MAJOR", "identity", 2, 4, 0, "uint:2", 21, None, None, "BLOCK version major", - {0: "No calibration", - 1: "With calibration"}), - ("CUSTOM_MAC", "identity", 3, 6, 8, "bytes:6", 22, None, "mac", "Custom MAC Address", None), - ] - - KEYBLOCKS = [ - # Name Category Block Word Pos Type:len WR_DIS RD_DIS Class Description Dictionary - ('BLOCK_USR_DATA', "config", 3, 0, 0, "bytes:32", 22, None, None, "User data", None), - ('BLOCK_KEY0', "security", 4, 0, 0, "bytes:32", 23, 0, "keyblock", "Encryption key0 or user data", None), - ('BLOCK_KEY1', "security", 5, 0, 0, "bytes:32", 24, 1, "keyblock", "Encryption key1 or user data", None), - ('BLOCK_KEY2', "security", 6, 0, 0, "bytes:32", 25, 2, "keyblock", "Encryption key2 or user data", None), - ('BLOCK_KEY3', "security", 7, 0, 0, "bytes:32", 26, 3, "keyblock", "Encryption key3 or user data", None), - ('BLOCK_KEY4', "security", 8, 0, 0, "bytes:32", 27, 4, "keyblock", "Encryption key4 or user data", None), - ('BLOCK_KEY5', "security", 9, 0, 0, "bytes:32", 28, 5, "keyblock", "Encryption key5 or user data", None), - ('BLOCK_SYS_DATA2', "security", 10, 0, 0, "bytes:32", 29, 6, "keyblock", "System data (part 2)", None), - ] - - # if BLK_VERSION_MAJOR is 1, these efuse fields are in BLOCK2 - BLOCK2_CALIBRATION_EFUSES = [ - # Name Category Block Word Pos Type:len WR_DIS RD_DIS Class Description Dictionary - ('TEMP_SENSOR_CAL', "calibration", 2, 4, 7, "uint:9", 21, None, "t_sensor", "Temperature calibration", None), - ('ADC1_MODE0_D2', "calibration", 2, 4, 16, "uint:8", 21, None, "adc_tp", "ADC1 calibration 1", None), - ('ADC1_MODE1_D2', "calibration", 2, 4, 24, "uint:8", 21, None, "adc_tp", "ADC1 calibration 2", None), - ('ADC1_MODE2_D2', "calibration", 2, 5, 0, "uint:8", 21, None, "adc_tp", "ADC1 calibration 3", None), - ('ADC1_MODE3_D2', "calibration", 2, 5, 8, "uint:8", 21, None, "adc_tp", "ADC1 calibration 4", None), - ('ADC2_MODE0_D2', "calibration", 2, 5, 16, "uint:8", 21, None, "adc_tp", "ADC2 calibration 5", None), - ('ADC2_MODE1_D2', "calibration", 2, 5, 24, "uint:8", 21, None, "adc_tp", "ADC2 calibration 6", None), - ('ADC2_MODE2_D2', "calibration", 2, 6, 0, "uint:8", 21, None, "adc_tp", "ADC2 calibration 7", None), - ('ADC2_MODE3_D2', "calibration", 2, 6, 8, "uint:8", 21, None, "adc_tp", "ADC2 calibration 8", None), - ('ADC1_MODE0_D1', "calibration", 2, 6, 16, "uint:6", 21, None, "adc_tp", "ADC1 calibration 9", None), - ('ADC1_MODE1_D1', "calibration", 2, 6, 22, "uint:6", 21, None, "adc_tp", "ADC1 calibration 10", None), - ('ADC1_MODE2_D1', "calibration", 2, 6, 28, "uint:6", 21, None, "adc_tp", "ADC1 calibration 11", None), - ('ADC1_MODE3_D1', "calibration", 2, 7, 2, "uint:6", 21, None, "adc_tp", "ADC1 calibration 12", None), - ('ADC2_MODE0_D1', "calibration", 2, 7, 8, "uint:6", 21, None, "adc_tp", "ADC2 calibration 13", None), - ('ADC2_MODE1_D1', "calibration", 2, 7, 14, "uint:6", 21, None, "adc_tp", "ADC2 calibration 14", None), - ('ADC2_MODE2_D1', "calibration", 2, 7, 20, "uint:6", 21, None, "adc_tp", "ADC2 calibration 15", None), - ('ADC2_MODE3_D1', "calibration", 2, 7, 26, "uint:6", 21, None, "adc_tp", "ADC2 calibration 16", None), - ] - - CALC = [ - ("WAFER_VERSION_MINOR", "identity", 0, None, None, "uint:4", None, None, "wafer", "calc WAFER VERSION MINOR = WAFER_VERSION_MINOR_HI << 3 + WAFER_VERSION_MINOR_LO (read only)", None), - ] -# fmt: on + def __init__(self) -> None: + # List of efuse fields from TRM the chapter eFuse Controller. + self.EFUSES = [] + + self.KEYBLOCKS = [] + + # if BLK_VERSION_MINOR is 2, these efuse fields are in BLOCK2 + self.BLOCK2_CALIBRATION_EFUSES = [] + + self.CALC = [] + + dir_name = os.path.dirname(os.path.abspath(__file__)) + dir_name, file_name = os.path.split(dir_name) + file_name = file_name + ".yaml" + dir_name, _ = os.path.split(dir_name) + efuse_file = os.path.join(dir_name, "efuse_defs", file_name) + with open(f"{efuse_file}", "r") as r_file: + e_desc = yaml.safe_load(r_file) + super().__init__(e_desc) + + for i, efuse in enumerate(self.ALL_EFUSES): + if efuse.name in [ + "BLOCK_USR_DATA", + "BLOCK_KEY0", + "BLOCK_KEY1", + "BLOCK_KEY2", + "BLOCK_KEY3", + "BLOCK_KEY4", + "BLOCK_KEY5", + "BLOCK_SYS_DATA2", + ]: + if efuse.name == "BLOCK_USR_DATA": + efuse.bit_len = 256 + efuse.type = "bytes:32" + self.KEYBLOCKS.append(efuse) + self.ALL_EFUSES[i] = None + + elif efuse.category == "calibration": + self.BLOCK2_CALIBRATION_EFUSES.append(efuse) + self.ALL_EFUSES[i] = None + + f = Field() + f.name = "MAC_EUI64" + f.block = 1 + f.bit_len = 64 + f.type = f"bytes:{f.bit_len // 8}" + f.category = "MAC" + f.class_type = "mac" + f.description = "calc MAC_EUI64 = MAC[0]:MAC[1]:MAC[2]:MAC_EXT[0]:MAC_EXT[1]:MAC[3]:MAC[4]:MAC[5]" + self.CALC.append(f) + + for efuse in self.ALL_EFUSES: + if efuse is not None: + self.EFUSES.append(efuse) + + self.ALL_EFUSES = [] diff --git a/espefuse/efuse/esp32h2/operations.py b/espefuse/efuse/esp32h2/operations.py index cc8ba64be..d9445d152 100644 --- a/espefuse/efuse/esp32h2/operations.py +++ b/espefuse/efuse/esp32h2/operations.py @@ -17,6 +17,7 @@ from ..base_operations import ( add_common_commands, add_force_write_always, + add_show_sensitive_info_option, burn_bit, burn_block_data, burn_efuse, @@ -55,6 +56,7 @@ def add_commands(subparsers, efuses): ) protect_options(burn_key) add_force_write_always(burn_key) + add_show_sensitive_info_option(burn_key) burn_key.add_argument( "block", help="Key block to burn", @@ -63,7 +65,7 @@ def add_commands(subparsers, efuses): ) burn_key.add_argument( "keyfile", - help="File containing 256 bits of binary key data", + help="File containing 256 bits of binary key data. For the ECDSA_KEY purpose use PEM file.", action="append", type=argparse.FileType("rb"), ) @@ -84,7 +86,7 @@ def add_commands(subparsers, efuses): ) burn_key.add_argument( "keyfile", - help="File containing 256 bits of binary key data", + help="File containing 256 bits of binary key data. For the ECDSA_KEY purpose use PEM file.", nargs="?", action="append", metavar="KEYFILE", @@ -105,6 +107,7 @@ def add_commands(subparsers, efuses): ) protect_options(burn_key_digest) add_force_write_always(burn_key_digest) + add_show_sensitive_info_option(burn_key_digest) burn_key_digest.add_argument( "block", help="Key block to burn", @@ -152,9 +155,8 @@ def add_commands(subparsers, efuses): p = subparsers.add_parser( "set_flash_voltage", help="Permanently set the internal flash voltage regulator " - "to either 1.8V, 3.3V or OFF. " - "This means GPIO45 can be high or low at reset without " - "changing the flash voltage.", + "to either 1.8V, 3.3V or OFF. This means GPIO45 can be high or low " + "at reset without changing the flash voltage.", ) p.add_argument("voltage", help="Voltage selection", choices=["1.8V", "3.3V", "OFF"]) @@ -191,38 +193,28 @@ def set_flash_voltage(esp, efuses, args): def adc_info(esp, efuses, args): print("") # fmt: off - if efuses["BLK_VERSION_MAJOR"].get() == 1: - print("Temperature Sensor Calibration = {}C".format(efuses["TEMP_SENSOR_CAL"].get())) + if efuses["BLK_VERSION_MINOR"].get() == 2: + print("Temperature Sensor Calibration = {}C".format(efuses["TEMP_CALIB"].get())) print("") print("ADC1 readings stored in efuse BLOCK2:") - print(" MODE0 D1 reading (250mV): {}".format(efuses["ADC1_MODE0_D1"].get())) - print(" MODE0 D2 reading (600mV): {}".format(efuses["ADC1_MODE0_D2"].get())) - - print(" MODE1 D1 reading (250mV): {}".format(efuses["ADC1_MODE1_D1"].get())) - print(" MODE1 D2 reading (800mV): {}".format(efuses["ADC1_MODE1_D2"].get())) - - print(" MODE2 D1 reading (250mV): {}".format(efuses["ADC1_MODE2_D1"].get())) - print(" MODE2 D2 reading (1000mV): {}".format(efuses["ADC1_MODE2_D2"].get())) - - print(" MODE3 D1 reading (250mV): {}".format(efuses["ADC1_MODE3_D1"].get())) - print(" MODE3 D2 reading (2000mV): {}".format(efuses["ADC1_MODE3_D2"].get())) - - print("") - print("ADC2 readings stored in efuse BLOCK2:") - print(" MODE0 D1 reading (250mV): {}".format(efuses["ADC2_MODE0_D1"].get())) - print(" MODE0 D2 reading (600mV): {}".format(efuses["ADC2_MODE0_D2"].get())) - - print(" MODE1 D1 reading (250mV): {}".format(efuses["ADC2_MODE1_D1"].get())) - print(" MODE1 D2 reading (800mV): {}".format(efuses["ADC2_MODE1_D2"].get())) - - print(" MODE2 D1 reading (250mV): {}".format(efuses["ADC2_MODE2_D1"].get())) - print(" MODE2 D2 reading (1000mV): {}".format(efuses["ADC2_MODE2_D2"].get())) - - print(" MODE3 D1 reading (250mV): {}".format(efuses["ADC2_MODE3_D1"].get())) - print(" MODE3 D2 reading (2000mV): {}".format(efuses["ADC2_MODE3_D2"].get())) + print(" AVE_INITCODE_ATTEN0: {}".format(efuses["ADC1_AVE_INITCODE_ATTEN0"].get())) + print(" AVE_INITCODE_ATTEN1: {}".format(efuses["ADC1_AVE_INITCODE_ATTEN1"].get())) + print(" AVE_INITCODE_ATTEN2: {}".format(efuses["ADC1_AVE_INITCODE_ATTEN2"].get())) + print(" AVE_INITCODE_ATTEN3: {}".format(efuses["ADC1_AVE_INITCODE_ATTEN3"].get())) + + print(" HI_DOUT_ATTEN0: {}".format(efuses["ADC1_HI_DOUT_ATTEN0"].get())) + print(" HI_DOUT_ATTEN1: {}".format(efuses["ADC1_HI_DOUT_ATTEN1"].get())) + print(" HI_DOUT_ATTEN2: {}".format(efuses["ADC1_HI_DOUT_ATTEN2"].get())) + print(" HI_DOUT_ATTEN3: {}".format(efuses["ADC1_HI_DOUT_ATTEN3"].get())) + + print(" CH0_ATTEN0_INITCODE_DIFF: {}".format(efuses["ADC1_CH0_ATTEN0_INITCODE_DIFF"].get())) + print(" CH1_ATTEN0_INITCODE_DIFF: {}".format(efuses["ADC1_CH1_ATTEN0_INITCODE_DIFF"].get())) + print(" CH2_ATTEN0_INITCODE_DIFF: {}".format(efuses["ADC1_CH2_ATTEN0_INITCODE_DIFF"].get())) + print(" CH3_ATTEN0_INITCODE_DIFF: {}".format(efuses["ADC1_CH3_ATTEN0_INITCODE_DIFF"].get())) + print(" CH4_ATTEN0_INITCODE_DIFF: {}".format(efuses["ADC1_CH4_ATTEN0_INITCODE_DIFF"].get())) else: - print("BLK_VERSION_MAJOR = {}".format(efuses["BLK_VERSION_MAJOR"].get_meaning())) + print("BLK_VERSION_MINOR = {}".format(efuses["BLK_VERSION_MINOR"].get())) # fmt: on @@ -267,16 +259,29 @@ def burn_key(esp, efuses, args, digest=None): block = efuses.blocks[block_num] if digest is None: - data = datafile.read() + if keypurpose == "ECDSA_KEY": + sk = espsecure.load_ecdsa_signing_key(datafile) + data = sk.to_string() + if len(data) == 24: + # the private key is 24 bytes long for NIST192p, add 8 bytes of padding + data = b"\x00" * 8 + data + else: + data = datafile.read() else: data = datafile print(" - %s" % (efuse.name), end=" ") revers_msg = None if efuses[block.key_purpose_name].need_reverse(keypurpose): - revers_msg = "\tReversing byte order for AES-XTS hardware peripheral" + revers_msg = f"\tReversing byte order for {keypurpose} hardware peripheral" data = data[::-1] - print("-> [%s]" % (util.hexify(data, " "))) + print( + "-> [{}]".format( + util.hexify(data, " ") + if args.show_sensitive_info + else " ".join(["??"] * len(data)) + ) + ) if revers_msg: print(revers_msg) if len(data) != num_bytes: diff --git a/espefuse/efuse/esp32h2beta1/emulate_efuse_controller.py b/espefuse/efuse/esp32h2beta1/emulate_efuse_controller.py index 1f98087d3..b81e8e08f 100644 --- a/espefuse/efuse/esp32h2beta1/emulate_efuse_controller.py +++ b/espefuse/efuse/esp32h2beta1/emulate_efuse_controller.py @@ -16,13 +16,13 @@ class EmulateEfuseController(EmulateEfuseControllerBase): CHIP_NAME = "ESP32-H2(beta1)" mem = None debug = False - Blocks = EfuseDefineBlocks - Fields = EfuseDefineFields - REGS = EfuseDefineRegisters def __init__(self, efuse_file=None, debug=False): + self.Blocks = EfuseDefineBlocks + self.Fields = EfuseDefineFields() + self.REGS = EfuseDefineRegisters super(EmulateEfuseController, self).__init__(efuse_file, debug) - self.write_reg(self.REGS.EFUSE_STATUS_REG, 1) + self.write_reg(self.REGS.EFUSE_CMD_REG, 0) """ esptool method start >>""" @@ -53,10 +53,10 @@ def handle_writing_event(self, addr, value): self.clean_blocks_wr_regs() self.check_rd_protection_area() self.write_reg(addr, 0) - self.write_reg(self.REGS.EFUSE_STATUS_REG, 1) + self.write_reg(self.REGS.EFUSE_CMD_REG, 0) elif value == self.REGS.EFUSE_READ_CMD: self.write_reg(addr, 0) - self.write_reg(self.REGS.EFUSE_STATUS_REG, 1) + self.write_reg(self.REGS.EFUSE_CMD_REG, 0) self.save_to_file() def get_bitlen_of_block(self, blk, wr=False): diff --git a/espefuse/efuse/esp32h2beta1/fields.py b/espefuse/efuse/esp32h2beta1/fields.py index 587bf3263..3e8f28928 100644 --- a/espefuse/efuse/esp32h2beta1/fields.py +++ b/espefuse/efuse/esp32h2beta1/fields.py @@ -54,16 +54,15 @@ class EspEfuses(base_fields.EspEfusesBase): Wrapper object to manage the efuse fields in a connected ESP bootloader """ - Blocks = EfuseDefineBlocks() - Fields = EfuseDefineFields() - REGS = EfuseDefineRegisters - BURN_BLOCK_DATA_NAMES = Blocks.get_burn_block_data_names() - BLOCKS_FOR_KEYS = Blocks.get_blocks_for_keys() - debug = False do_not_confirm = False def __init__(self, esp, skip_connect=False, debug=False, do_not_confirm=False): + self.Blocks = EfuseDefineBlocks() + self.Fields = EfuseDefineFields() + self.REGS = EfuseDefineRegisters + self.BURN_BLOCK_DATA_NAMES = self.Blocks.get_burn_block_data_names() + self.BLOCKS_FOR_KEYS = self.Blocks.get_blocks_for_keys() self._esp = esp self.debug = debug self.do_not_confirm = do_not_confirm @@ -85,53 +84,43 @@ def __init__(self, esp, skip_connect=False, debug=False, do_not_confirm=False): ] if not skip_connect: self.get_coding_scheme_warnings() - self.efuses = [ - EfuseField.from_tuple( - self, self.Fields.get(efuse), self.Fields.get(efuse).class_type - ) - for efuse in self.Fields.EFUSES - ] + self.efuses = [EfuseField.convert(self, efuse) for efuse in self.Fields.EFUSES] self.efuses += [ - EfuseField.from_tuple( - self, self.Fields.get(efuse), self.Fields.get(efuse).class_type - ) - for efuse in self.Fields.KEYBLOCKS + EfuseField.convert(self, efuse) for efuse in self.Fields.KEYBLOCKS ] if skip_connect: self.efuses += [ - EfuseField.from_tuple( - self, self.Fields.get(efuse), self.Fields.get(efuse).class_type - ) + EfuseField.convert(self, efuse) for efuse in self.Fields.BLOCK2_CALIBRATION_EFUSES ] else: - if self["BLOCK2_VERSION"].get() == 1: + if self["BLK_VERSION_MAJOR"].get() == 1: self.efuses += [ - EfuseField.from_tuple( - self, self.Fields.get(efuse), self.Fields.get(efuse).class_type - ) + EfuseField.convert(self, efuse) for efuse in self.Fields.BLOCK2_CALIBRATION_EFUSES ] + self.efuses += [ + EfuseField.convert(self, efuse) for efuse in self.Fields.CALC + ] def __getitem__(self, efuse_name): """Return the efuse field with the given name""" for e in self.efuses: - if efuse_name == e.name: + if efuse_name == e.name or any(x == efuse_name for x in e.alt_names): return e new_fields = False for efuse in self.Fields.BLOCK2_CALIBRATION_EFUSES: - e = self.Fields.get(efuse) - if e.name == efuse_name: + if efuse.name == efuse_name or any( + x == efuse_name for x in efuse.alt_names + ): self.efuses += [ - EfuseField.from_tuple( - self, self.Fields.get(efuse), self.Fields.get(efuse).class_type - ) + EfuseField.convert(self, efuse) for efuse in self.Fields.BLOCK2_CALIBRATION_EFUSES ] new_fields = True if new_fields: for e in self.efuses: - if efuse_name == e.name: + if efuse_name == e.name or any(x == efuse_name for x in e.alt_names): return e raise KeyError @@ -152,10 +141,6 @@ def print_status_regs(self): ) ) - def get_block_errors(self, block_num): - """Returns (error count, failure boolean flag)""" - return self.blocks[block_num].num_errors, self.blocks[block_num].fail - def efuse_controller_setup(self): self.set_efuse_timing() self.clear_pgm_registers() @@ -175,9 +160,13 @@ def clear_pgm_registers(self): def wait_efuse_idle(self): deadline = time.time() + self.REGS.EFUSE_BURN_TIMEOUT while time.time() < deadline: - # if self.read_reg(self.REGS.EFUSE_CMD_REG) == 0: - if self.read_reg(self.REGS.EFUSE_STATUS_REG) & 0x7 == 1: - return + cmds = self.REGS.EFUSE_PGM_CMD | self.REGS.EFUSE_READ_CMD + if self.read_reg(self.REGS.EFUSE_CMD_REG) & cmds == 0: + if self.read_reg(self.REGS.EFUSE_CMD_REG) & cmds == 0: + # Due to a hardware error, we have to read READ_CMD again + # to make sure the efuse clock is normal. + # For PGM_CMD it is not necessary. + return raise esptool.FatalError( "Timed out waiting for Efuse controller command to complete" ) @@ -243,6 +232,13 @@ def set_efuse_timing(self): "The eFuse supports only xtal=32M (xtal was %d)" % apb_freq ) + self.update_reg(self.REGS.EFUSE_DAC_CONF_REG, self.REGS.EFUSE_DAC_NUM_M, 0xFF) + self.update_reg( + self.REGS.EFUSE_DAC_CONF_REG, self.REGS.EFUSE_DAC_CLK_DIV_M, 0x28 + ) + self.update_reg( + self.REGS.EFUSE_WR_TIM_CONF1_REG, self.REGS.EFUSE_PWR_ON_NUM_M, 0x3000 + ) self.update_reg( self.REGS.EFUSE_WR_TIM_CONF2_REG, self.REGS.EFUSE_PWR_OFF_NUM_M, 0x190 ) @@ -258,12 +254,9 @@ def get_coding_scheme_warnings(self, silent=False): self.read_reg(self.REGS.EFUSE_RD_REPEAT_ERR0_REG + offs * 4) for offs in range(5) ] - data = BitArray() + block.err_bitarray.pos = 0 for word in reversed(words): - data.append("uint:32=%d" % word) - # pos=32 because EFUSE_WR_DIS goes first it is 32bit long - # and not under error control - block.err_bitarray.overwrite(data, pos=32) + block.err_bitarray.overwrite(BitArray("uint:32=%d" % word)) block.num_errors = block.err_bitarray.count(True) block.fail = block.num_errors != 0 else: @@ -294,28 +287,26 @@ def summary(self): class EfuseField(base_fields.EfuseFieldBase): @staticmethod - def from_tuple(parent, efuse_tuple, type_class): + def convert(parent, efuse): return { "mac": EfuseMacField, "keypurpose": EfuseKeyPurposeField, "t_sensor": EfuseTempSensor, "adc_tp": EfuseAdcPointCalibration, - }.get(type_class, EfuseField)(parent, efuse_tuple) + "wafer": EfuseWafer, + }.get(efuse.class_type, EfuseField)(parent, efuse) - def get_info(self): - output = "%s (BLOCK%d)" % (self.name, self.block) - errs, fail = self.parent.get_block_errors(self.block) - if errs != 0 or fail: - output += ( - "[FAIL:%d]" % (fail) - if self.block == 0 - else "[ERRS:%d FAIL:%d]" % (errs, fail) - ) - if self.efuse_class == "keyblock": - name = self.parent.blocks[self.block].key_purpose_name - if name is not None: - output += "\n Purpose: %s\n " % (self.parent[name].get()) - return output + +class EfuseWafer(EfuseField): + def get(self, from_read=True): + hi_bits = self.parent["WAFER_VERSION_MINOR_HI"].get(from_read) + assert self.parent["WAFER_VERSION_MINOR_HI"].bit_len == 1 + lo_bits = self.parent["WAFER_VERSION_MINOR_LO"].get(from_read) + assert self.parent["WAFER_VERSION_MINOR_LO"].bit_len == 3 + return (hi_bits << 3) + lo_bits + + def save(self, new_value): + raise esptool.FatalError("Burning %s is not supported" % self.name) class EfuseTempSensor(EfuseField): @@ -339,23 +330,27 @@ def check_format(self, new_value_str): raise esptool.FatalError( "Required MAC Address in AA:CD:EF:01:02:03 format!" ) - if new_value_str.count(":") != 5: + num_bytes = 8 if self.name == "MAC_EUI64" else 6 + if new_value_str.count(":") != num_bytes - 1: raise esptool.FatalError( - "MAC Address needs to be a 6-byte hexadecimal format " + f"MAC Address needs to be a {num_bytes}-byte hexadecimal format " "separated by colons (:)!" ) - hexad = new_value_str.replace(":", "") - if len(hexad) != 12: + hexad = new_value_str.replace(":", "").split(" ", 1)[0] + hexad = hexad.split(" ", 1)[0] if self.is_field_calculated() else hexad + if len(hexad) != num_bytes * 2: raise esptool.FatalError( - "MAC Address needs to be a 6-byte hexadecimal number " - "(12 hexadecimal characters)!" + f"MAC Address needs to be a {num_bytes}-byte hexadecimal number " + f"({num_bytes * 2} hexadecimal characters)!" ) # order of bytearray = b'\xaa\xcd\xef\x01\x02\x03', bindata = binascii.unhexlify(hexad) - # unicast address check according to - # https://tools.ietf.org/html/rfc7042#section-2.1 - if esptool.util.byte(bindata, 0) & 0x01: - raise esptool.FatalError("Custom MAC must be a unicast MAC!") + + if not self.is_field_calculated(): + # unicast address check according to + # https://tools.ietf.org/html/rfc7042#section-2.1 + if esptool.util.byte(bindata, 0) & 0x01: + raise esptool.FatalError("Custom MAC must be a unicast MAC!") return bindata def check(self): @@ -368,11 +363,14 @@ def check(self): def get(self, from_read=True): if self.name == "CUSTOM_MAC": - mac = self.get_raw(from_read)[::-1] + self.parent["MAC_EXT"].get_raw( - from_read - ) + mac = self.get_raw(from_read)[::-1] elif self.name == "MAC": - mac = self.get_raw(from_read) + self.parent["MAC_EXT"].get_raw(from_read) + mac = self.get_raw(from_read) + elif self.name == "MAC_EUI64": + mac = self.parent["MAC"].get_bitstring(from_read).copy() + mac_ext = self.parent["MAC_EXT"].get_bitstring(from_read) + mac.insert(mac_ext, 24) + mac = mac.bytes else: mac = self.get_raw(from_read) return "%s %s" % (util.hexify(mac, ":"), self.check()) @@ -392,6 +390,7 @@ def print_field(e, new_value): else: # Writing the BLOCK1 (MAC_SPI_8M_0) default MAC is not possible, # as it's written in the factory. + raise esptool.FatalError(f"Burning {self.name} is not supported") raise esptool.FatalError("Writing Factory MAC address is not supported") @@ -400,8 +399,6 @@ class EfuseKeyPurposeField(EfuseField): KEY_PURPOSES = [ ("USER", 0, None, None, "no_need_rd_protect"), # User purposes (software-only use) ("RESERVED", 1, None, None, "no_need_rd_protect"), # Reserved - ("XTS_AES_256_KEY_1", 2, None, "Reverse", "need_rd_protect"), # XTS_AES_256_KEY_1 (flash/PSRAM encryption) - ("XTS_AES_256_KEY_2", 3, None, "Reverse", "need_rd_protect"), # XTS_AES_256_KEY_2 (flash/PSRAM encryption) ("XTS_AES_128_KEY", 4, None, "Reverse", "need_rd_protect"), # XTS_AES_128_KEY (flash/PSRAM encryption) ("HMAC_DOWN_ALL", 5, None, None, "need_rd_protect"), # HMAC Downstream mode ("HMAC_DOWN_JTAG", 6, None, None, "need_rd_protect"), # JTAG soft enable key (uses HMAC Downstream mode) @@ -447,6 +444,14 @@ def get(self, from_read=True): return p[0] return "FORBIDDEN_STATE" + def get_name(self, raw_val): + for key in self.KEY_PURPOSES: + if key[1] == raw_val: + return key[0] + def save(self, new_value): raw_val = int(self.check_format(str(new_value))) + str_new_value = self.get_name(raw_val) + if self.name == "KEY_PURPOSE_5" and str_new_value.startswith("XTS_AES"): + raise esptool.FatalError(f"{self.name} can not have {str_new_value} key due to a hardware bug (please see TRM for more details)") return super(EfuseKeyPurposeField, self).save(raw_val) diff --git a/espefuse/efuse/esp32h2beta1/mem_definition.py b/espefuse/efuse/esp32h2beta1/mem_definition.py index 58aff675f..ee2f00697 100644 --- a/espefuse/efuse/esp32h2beta1/mem_definition.py +++ b/espefuse/efuse/esp32h2beta1/mem_definition.py @@ -4,24 +4,26 @@ # # SPDX-License-Identifier: GPL-2.0-or-later +import os + +import yaml + from ..mem_definition_base import EfuseBlocksBase, EfuseFieldsBase, EfuseRegistersBase -# fmt: off class EfuseDefineRegisters(EfuseRegistersBase): - - EFUSE_MEM_SIZE = (0x01FC + 4) + EFUSE_MEM_SIZE = 0x01FC + 4 # EFUSE registers & command/conf values - DR_REG_EFUSE_BASE = 0x6001A000 - EFUSE_PGM_DATA0_REG = DR_REG_EFUSE_BASE - EFUSE_CHECK_VALUE0_REG = DR_REG_EFUSE_BASE + 0x020 - EFUSE_CLK_REG = DR_REG_EFUSE_BASE + 0x1C8 - EFUSE_CONF_REG = DR_REG_EFUSE_BASE + 0x1CC - EFUSE_STATUS_REG = DR_REG_EFUSE_BASE + 0x1D0 - EFUSE_CMD_REG = DR_REG_EFUSE_BASE + 0x1D4 - EFUSE_RD_RS_ERR0_REG = DR_REG_EFUSE_BASE + 0x1C0 - EFUSE_RD_RS_ERR1_REG = DR_REG_EFUSE_BASE + 0x1C4 + DR_REG_EFUSE_BASE = 0x6001A000 + EFUSE_PGM_DATA0_REG = DR_REG_EFUSE_BASE + EFUSE_CHECK_VALUE0_REG = DR_REG_EFUSE_BASE + 0x020 + EFUSE_CLK_REG = DR_REG_EFUSE_BASE + 0x1C8 + EFUSE_CONF_REG = DR_REG_EFUSE_BASE + 0x1CC + EFUSE_STATUS_REG = DR_REG_EFUSE_BASE + 0x1D0 + EFUSE_CMD_REG = DR_REG_EFUSE_BASE + 0x1D4 + EFUSE_RD_RS_ERR0_REG = DR_REG_EFUSE_BASE + 0x1C0 + EFUSE_RD_RS_ERR1_REG = DR_REG_EFUSE_BASE + 0x1C4 EFUSE_RD_REPEAT_ERR0_REG = DR_REG_EFUSE_BASE + 0x17C EFUSE_RD_REPEAT_ERR1_REG = DR_REG_EFUSE_BASE + 0x180 EFUSE_RD_REPEAT_ERR2_REG = DR_REG_EFUSE_BASE + 0x184 @@ -32,37 +34,49 @@ class EfuseDefineRegisters(EfuseRegistersBase): EFUSE_WR_TIM_CONF1_REG = DR_REG_EFUSE_BASE + 0x1F0 EFUSE_WR_TIM_CONF2_REG = DR_REG_EFUSE_BASE + 0x1F4 EFUSE_DATE_REG = DR_REG_EFUSE_BASE + 0x1FC - EFUSE_WRITE_OP_CODE = 0x5A5A - EFUSE_READ_OP_CODE = 0x5AA5 - EFUSE_PGM_CMD_MASK = 0x3 - EFUSE_PGM_CMD = 0x2 - EFUSE_READ_CMD = 0x1 + EFUSE_WRITE_OP_CODE = 0x5A5A + EFUSE_READ_OP_CODE = 0x5AA5 + EFUSE_PGM_CMD_MASK = 0x3 + EFUSE_PGM_CMD = 0x2 + EFUSE_READ_CMD = 0x1 BLOCK_ERRORS = [ # error_reg, err_num_mask, err_num_offs, fail_bit - (EFUSE_RD_REPEAT_ERR0_REG, None, None, None), # BLOCK0 - (EFUSE_RD_RS_ERR0_REG, 0x7, 0, 3), # MAC_SPI_8M_0 - (EFUSE_RD_RS_ERR0_REG, 0x7, 4, 7), # BLOCK_SYS_DATA - (EFUSE_RD_RS_ERR0_REG, 0x7, 8, 11), # BLOCK_USR_DATA - (EFUSE_RD_RS_ERR0_REG, 0x7, 12, 15), # BLOCK_KEY0 - (EFUSE_RD_RS_ERR0_REG, 0x7, 16, 19), # BLOCK_KEY1 - (EFUSE_RD_RS_ERR0_REG, 0x7, 20, 23), # BLOCK_KEY2 - (EFUSE_RD_RS_ERR0_REG, 0x7, 24, 27), # BLOCK_KEY3 - (EFUSE_RD_RS_ERR0_REG, 0x7, 28, 31), # BLOCK_KEY4 - (EFUSE_RD_RS_ERR1_REG, 0x7, 0, 3), # BLOCK_KEY5 - (EFUSE_RD_RS_ERR1_REG, 0x7, 4, 7), # BLOCK_SYS_DATA2 + (EFUSE_RD_REPEAT_ERR0_REG, None, None, None), # BLOCK0 + (EFUSE_RD_RS_ERR0_REG, 0x7, 0, 3), # MAC_SPI_8M_0 + (EFUSE_RD_RS_ERR0_REG, 0x7, 4, 7), # BLOCK_SYS_DATA + (EFUSE_RD_RS_ERR0_REG, 0x7, 8, 11), # BLOCK_USR_DATA + (EFUSE_RD_RS_ERR0_REG, 0x7, 12, 15), # BLOCK_KEY0 + (EFUSE_RD_RS_ERR0_REG, 0x7, 16, 19), # BLOCK_KEY1 + (EFUSE_RD_RS_ERR0_REG, 0x7, 20, 23), # BLOCK_KEY2 + (EFUSE_RD_RS_ERR0_REG, 0x7, 24, 27), # BLOCK_KEY3 + (EFUSE_RD_RS_ERR0_REG, 0x7, 28, 31), # BLOCK_KEY4 + (EFUSE_RD_RS_ERR1_REG, 0x7, 0, 3), # BLOCK_KEY5 + (EFUSE_RD_RS_ERR1_REG, 0x7, 4, 7), # BLOCK_SYS_DATA2 ] # EFUSE_WR_TIM_CONF2_REG EFUSE_PWR_OFF_NUM_S = 0 EFUSE_PWR_OFF_NUM_M = 0xFFFF << EFUSE_PWR_OFF_NUM_S + # EFUSE_WR_TIM_CONF1_REG + EFUSE_PWR_ON_NUM_S = 8 + EFUSE_PWR_ON_NUM_M = 0x0000FFFF << EFUSE_PWR_ON_NUM_S -class EfuseDefineBlocks(EfuseBlocksBase): + # EFUSE_DAC_CONF_REG + EFUSE_DAC_CLK_DIV_S = 0 + EFUSE_DAC_CLK_DIV_M = 0xFF << EFUSE_DAC_CLK_DIV_S + # EFUSE_DAC_CONF_REG + EFUSE_DAC_NUM_S = 9 + EFUSE_DAC_NUM_M = 0xFF << EFUSE_DAC_NUM_S + + +class EfuseDefineBlocks(EfuseBlocksBase): __base_rd_regs = EfuseDefineRegisters.DR_REG_EFUSE_BASE __base_wr_regs = EfuseDefineRegisters.EFUSE_PGM_DATA0_REG # List of efuse blocks + # fmt: off BLOCKS = [ # Name, Alias, Index, Read address, Write address, Write protect bit, Read protect bit, Len, key_purpose ("BLOCK0", [], 0, __base_rd_regs + 0x02C, __base_wr_regs, None, None, 6, None), @@ -77,6 +91,7 @@ class EfuseDefineBlocks(EfuseBlocksBase): ("BLOCK_KEY5", ["BLOCK9"], 9, __base_rd_regs + 0x13C, __base_wr_regs, 28, 5, 8, "KEY_PURPOSE_5"), ("BLOCK_SYS_DATA2", ["BLOCK10"], 10, __base_rd_regs + 0x15C, __base_wr_regs, 29, 6, 8, None), ] + # fmt: on def get_burn_block_data_names(self): list_of_names = [] @@ -91,137 +106,50 @@ def get_burn_block_data_names(self): class EfuseDefineFields(EfuseFieldsBase): - - # List of efuse fields from TRM the chapter eFuse Controller. - EFUSES = [ - # - # Table 51: Parameters in BLOCK0 - # Name Category Block Word Pos Type:len WR_DIS RD_DIS Class Description Dictionary - ("WR_DIS", "efuse", 0, 0, 0, "uint:32", None, None, None, "Disables programming of individual eFuses", None), - ("RD_DIS", "efuse", 0, 1, 0, "uint:7", 0, None, None, "Disables software reading from BLOCK4-10", None), - ("DIS_ICACHE", "config", 0, 1, 8, "bool", 2, None, None, "Disables ICache", None), - ("DIS_USB_JTAG", "usb config", 0, 1, 9, "bool", 2, None, None, "Disables USB JTAG. " - "JTAG access via pads is controlled separately", None), - ("DIS_DOWNLOAD_ICACHE", "config", 0, 1, 10, "bool", 2, None, None, "Disables Icache when SoC is in Download mode", None), - ("DIS_USB_DEVICE", "usb config", 0, 1, 11, "bool", 2, None, None, "Disables USB DEVICE", None), - ("DIS_FORCE_DOWNLOAD", "config", 0, 1, 12, "bool", 2, None, None, "Disables forcing chip into Download mode", None), - ("DIS_CAN", "config", 0, 1, 14, "bool", 2, None, None, "Disables the TWAI Controller hardware", None), - ("JTAG_SEL_ENABLE", "jtag config", 0, 1, 15, "bool", 2, None, None, "Set this bit to enable selection between " - "usb_to_jtag and pad_to_jtag through strapping " - "gpio10 when both reg_dis_usb_jtag and " - "reg_dis_pad_jtag are equal to 0.", None), - ("SOFT_DIS_JTAG", "jtag config", 0, 1, 16, "uint:3", 2, None, None, "Software disables JTAG. When software disabled, " - "JTAG can be activated temporarily by HMAC peripheral", - None), - ("DIS_PAD_JTAG", "jtag config", 0, 1, 19, "bool", 2, None, None, "Permanently disable JTAG access via pads. " - "USB JTAG is controlled separately.", None), - ("DIS_DOWNLOAD_MANUAL_ENCRYPT", "security", 0, 1, 20, "bool", 2, None, None, "Disables flash encryption when in download boot modes", - None), - ("USB_EXCHG_PINS", "usb config", 0, 1, 25, "bool", 30, None, None, "Exchanges USB D+ and D- pins", None), - ("VDD_SPI_AS_GPIO", "config", 0, 1, 26, "bool", 30, None, None, "Set this bit to vdd spi pin function as gpio", None), - ("BTLC_GPIO_ENABLE", "config", 0, 1, 27, "uint:2", 30, None, None, "Enable btlc gpio", None), - ("POWERGLITCH_EN", "config", 0, 1, 29, "bool", 30, None, None, "Set this bit to enable power glitch function", None), - ("POWER_GLITCH_DSENSE", "config", 0, 1, 30, "uint:2", 30, None, None, "Sample delay configuration of power glitch", None), - ("WDT_DELAY_SEL", "WDT config", 0, 2, 16, "bool", 3, None, None, "Selects RTC WDT timeout threshold at startup", None), - ("SPI_BOOT_CRYPT_CNT", "security", 0, 2, 18, "uint:3", 4, None, "bitcount", "Enables encryption and decryption, when an SPI boot " - "mode is set. Enabled when 1 or 3 bits are set," - "disabled otherwise", - {0: "Disable", - 1: "Enable", - 3: "Disable", - 7: "Enable"}), - ("SECURE_BOOT_KEY_REVOKE0", "security", 0, 2, 21, "bool", 5, None, None, "If set, revokes use of secure boot key digest 0", None), - ("SECURE_BOOT_KEY_REVOKE1", "security", 0, 2, 22, "bool", 6, None, None, "If set, revokes use of secure boot key digest 1", None), - ("SECURE_BOOT_KEY_REVOKE2", "security", 0, 2, 23, "bool", 7, None, None, "If set, revokes use of secure boot key digest 2", None), - ("KEY_PURPOSE_0", "security", 0, 2, 24, "uint:4", 8, None, "keypurpose", "KEY0 purpose", None), - ("KEY_PURPOSE_1", "security", 0, 2, 28, "uint:4", 9, None, "keypurpose", "KEY1 purpose", None), - ("KEY_PURPOSE_2", "security", 0, 3, 0, "uint:4", 10, None, "keypurpose", "KEY2 purpose", None), - ("KEY_PURPOSE_3", "security", 0, 3, 4, "uint:4", 11, None, "keypurpose", "KEY3 purpose", None), - ("KEY_PURPOSE_4", "security", 0, 3, 8, "uint:4", 12, None, "keypurpose", "KEY4 purpose", None), - ("KEY_PURPOSE_5", "security", 0, 3, 12, "uint:4", 13, None, "keypurpose", "KEY5 purpose", None), - ("SECURE_BOOT_EN", "security", 0, 3, 20, "bool", 15, None, None, "Enables secure boot", None), - ("SECURE_BOOT_AGGRESSIVE_REVOKE", "security", 0, 3, 21, "bool", 16, None, None, "Enables aggressive secure boot key revocation mode", - None), - ("FLASH_TPUW", "flash config", 0, 3, 28, "uint:4", 18, None, None, "Configures flash startup delay after SoC power-up, " - "unit is (ms/2). When the value is 15, delay is 7.5 ms", - None), - ("DIS_DOWNLOAD_MODE", "security", 0, 4, 0, "bool", 18, None, None, "Disables all Download boot modes", None), - ("DIS_DIRECT_BOOT", "config", 0, 4, 1, "bool", 18, None, None, "Disables direct boot mode", None), - ("DIS_USB_SERIAL_JTAG_ROM_PRINT", "config", 0, 4, 2, "bool", 18, None, None, "Disables USB-Serial-JTAG ROM printing", None), - ("DIS_USB_SERIAL_JTAG_DOWNLOAD_MODE", "usb config", 0, 4, 4, "bool", 18, None, None, "Disables USB-Serial-JTAG download feature in " - "UART download boot mode", None), - ("ENABLE_SECURITY_DOWNLOAD", "security", 0, 4, 5, "bool", 18, None, None, "Enables secure UART download mode " - "(read/write flash only)", None), - ("UART_PRINT_CONTROL", "config", 0, 4, 6, "uint:2", 18, None, None, "Sets the default UART boot message output mode", - {0: "Enabled", - 1: "Enable when GPIO8 is low at reset", - 2: "Enable when GPIO8 is high at reset", - 3: "Disabled"}), - ("FORCE_SEND_RESUME", "config", 0, 4, 13, "bool", 18, None, None, "Force ROM code to send a resume command during SPI boot" - "during SPI boot", None), - ("SECURE_VERSION", "identity", 0, 4, 14, "uint:16", 18, None, "bitcount", "Secure version (used by ESP-IDF anti-rollback feature)", - None), - ("DISABLE_WAFER_VERSION_MAJOR", "config", 0, 5, 0, "bool", 19, None, None, "Disables check of wafer version major", None), - ("DISABLE_BLK_VERSION_MAJOR", "config", 0, 5, 1, "bool", 19, None, None, "Disables check of blk version major", None), - # - # Table 53: Parameters in BLOCK1-10 - # Name Category Block Word Pos Type:len WR_DIS RD_DIS Class Description Dictionary - ("MAC", "identity", 1, 0, 0, "bytes:6", 20, None, "mac", "Factory MAC Address", None), - ("SPI_PAD_CONFIG_CLK", "spi_pad_config", 1, 1, 16, "uint:6", 20, None, None, "SPI CLK pad", None), - ("SPI_PAD_CONFIG_Q", "spi_pad_config", 1, 1, 22, "uint:6", 20, None, None, "SPI Q (D1) pad", None), - ("SPI_PAD_CONFIG_D", "spi_pad_config", 1, 1, 28, "uint:6", 20, None, None, "SPI D (D0) pad", None), - ("SPI_PAD_CONFIG_CS", "spi_pad_config", 1, 2, 2, "uint:6", 20, None, None, "SPI CS pad", None), - ("SPI_PAD_CONFIG_HD", "spi_pad_config", 1, 2, 8, "uint:6", 20, None, None, "SPI HD (D3) pad", None), - ("SPI_PAD_CONFIG_WP", "spi_pad_config", 1, 2, 14, "uint:6", 20, None, None, "SPI WP (D2) pad", None), - ("SPI_PAD_CONFIG_DQS", "spi_pad_config", 1, 2, 20, "uint:6", 20, None, None, "SPI DQS pad", None), - ("SPI_PAD_CONFIG_D4", "spi_pad_config", 1, 2, 26, "uint:6", 20, None, None, "SPI D4 pad", None), - ("SPI_PAD_CONFIG_D5", "spi_pad_config", 1, 3, 0, "uint:6", 20, None, None, "SPI D5 pad", None), - ("SPI_PAD_CONFIG_D6", "spi_pad_config", 1, 3, 6, "uint:6", 20, None, None, "SPI D6 pad", None), - ("SPI_PAD_CONFIG_D7", "spi_pad_config", 1, 3, 12, "uint:6", 20, None, None, "SPI D7 pad", None), - ("WAFER_VERSION", "identity", 1, 3, 18, "uint:3", 20, None, None, "WAFER version", - {0: "(revision 0)", 1: "(revision 1)"}), - ("PKG_VERSION", "identity", 1, 3, 21, "uint:4", 20, None, None, "Package version", - {0: "ESP32-H2(beta1)"}), - ("BLOCK1_VERSION", "identity", 1, 3, 24, "uint:3", 20, None, None, "BLOCK1 efuse version", None), - ("MAC_EXT", "identity", 1, 3, 27, "bytes:2", 20, None, "mac", "MAC extension", None), - ("OPTIONAL_UNIQUE_ID", "identity", 2, 0, 0, "bytes:16", 21, None, "keyblock", "Optional unique 128-bit ID", None), - ("BLOCK2_VERSION", "identity", 2, 4, 4, "uint:3", 21, None, None, "Version of BLOCK2", - {0: "No calibration", - 1: "With calibration"}), - ("CUSTOM_MAC", "identity", 3, 6, 8, "bytes:6", 22, None, "mac", "Custom MAC Address", None), - ] - - KEYBLOCKS = [ - # Name Category Block Word Pos Type:len WR_DIS RD_DIS Class Description Dictionary - ('BLOCK_USR_DATA', "config", 3, 0, 0, "bytes:32", 22, None, None, "User data", None), - ('BLOCK_KEY0', "security", 4, 0, 0, "bytes:32", 23, 0, "keyblock", "Encryption key0 or user data", None), - ('BLOCK_KEY1', "security", 5, 0, 0, "bytes:32", 24, 1, "keyblock", "Encryption key1 or user data", None), - ('BLOCK_KEY2', "security", 6, 0, 0, "bytes:32", 25, 2, "keyblock", "Encryption key2 or user data", None), - ('BLOCK_KEY3', "security", 7, 0, 0, "bytes:32", 26, 3, "keyblock", "Encryption key3 or user data", None), - ('BLOCK_KEY4', "security", 8, 0, 0, "bytes:32", 27, 4, "keyblock", "Encryption key4 or user data", None), - ('BLOCK_KEY5', "security", 9, 0, 0, "bytes:32", 28, 5, "keyblock", "Encryption key5 or user data", None), - ('BLOCK_SYS_DATA2', "security", 10, 0, 0, "bytes:32", 29, 6, "keyblock", "System data (part 2)", None), - ] - - # if BLOCK2_VERSION is 1, these efuse fields are in BLOCK2 - BLOCK2_CALIBRATION_EFUSES = [ - # Name Category Block Word Pos Type:len WR_DIS RD_DIS Class Description Dictionary - ('TEMP_SENSOR_CAL', "calibration", 2, 4, 7, "uint:9", 21, None, "t_sensor", "Temperature calibration", None), - ('ADC1_MODE0_D2', "calibration", 2, 4, 16, "uint:8", 21, None, "adc_tp", "ADC1 calibration 1", None), - ('ADC1_MODE1_D2', "calibration", 2, 4, 24, "uint:8", 21, None, "adc_tp", "ADC1 calibration 2", None), - ('ADC1_MODE2_D2', "calibration", 2, 5, 0, "uint:8", 21, None, "adc_tp", "ADC1 calibration 3", None), - ('ADC1_MODE3_D2', "calibration", 2, 5, 8, "uint:8", 21, None, "adc_tp", "ADC1 calibration 4", None), - ('ADC2_MODE0_D2', "calibration", 2, 5, 16, "uint:8", 21, None, "adc_tp", "ADC2 calibration 5", None), - ('ADC2_MODE1_D2', "calibration", 2, 5, 24, "uint:8", 21, None, "adc_tp", "ADC2 calibration 6", None), - ('ADC2_MODE2_D2', "calibration", 2, 6, 0, "uint:8", 21, None, "adc_tp", "ADC2 calibration 7", None), - ('ADC2_MODE3_D2', "calibration", 2, 6, 8, "uint:8", 21, None, "adc_tp", "ADC2 calibration 8", None), - ('ADC1_MODE0_D1', "calibration", 2, 6, 16, "uint:6", 21, None, "adc_tp", "ADC1 calibration 9", None), - ('ADC1_MODE1_D1', "calibration", 2, 6, 22, "uint:6", 21, None, "adc_tp", "ADC1 calibration 10", None), - ('ADC1_MODE2_D1', "calibration", 2, 6, 28, "uint:6", 21, None, "adc_tp", "ADC1 calibration 11", None), - ('ADC1_MODE3_D1', "calibration", 2, 7, 2, "uint:6", 21, None, "adc_tp", "ADC1 calibration 12", None), - ('ADC2_MODE0_D1', "calibration", 2, 7, 8, "uint:6", 21, None, "adc_tp", "ADC2 calibration 13", None), - ('ADC2_MODE1_D1', "calibration", 2, 7, 14, "uint:6", 21, None, "adc_tp", "ADC2 calibration 14", None), - ('ADC2_MODE2_D1', "calibration", 2, 7, 20, "uint:6", 21, None, "adc_tp", "ADC2 calibration 15", None), - ('ADC2_MODE3_D1', "calibration", 2, 7, 26, "uint:6", 21, None, "adc_tp", "ADC2 calibration 16", None), - ] -# fmt: on + def __init__(self) -> None: + # List of efuse fields from TRM the chapter eFuse Controller. + self.EFUSES = [] + + self.KEYBLOCKS = [] + + # if BLK_VERSION_MAJOR is 1, these efuse fields are in BLOCK2 + self.BLOCK2_CALIBRATION_EFUSES = [] + + self.CALC = [] + + dir_name = os.path.dirname(os.path.abspath(__file__)) + dir_name, file_name = os.path.split(dir_name) + file_name = file_name + ".yaml" + dir_name, _ = os.path.split(dir_name) + efuse_file = os.path.join(dir_name, "efuse_defs", file_name) + efuse_file = efuse_file.replace("esp32h2beta1", "esp32h2") + with open(f"{efuse_file}", "r") as r_file: + e_desc = yaml.safe_load(r_file) + super().__init__(e_desc) + + for i, efuse in enumerate(self.ALL_EFUSES): + if efuse.name in [ + "BLOCK_USR_DATA", + "BLOCK_KEY0", + "BLOCK_KEY1", + "BLOCK_KEY2", + "BLOCK_KEY3", + "BLOCK_KEY4", + "BLOCK_KEY5", + "BLOCK_SYS_DATA2", + ]: + if efuse.name == "BLOCK_USR_DATA": + efuse.bit_len = 256 + efuse.type = "bytes:32" + self.KEYBLOCKS.append(efuse) + self.ALL_EFUSES[i] = None + + elif efuse.category == "calibration": + self.BLOCK2_CALIBRATION_EFUSES.append(efuse) + self.ALL_EFUSES[i] = None + + for efuse in self.ALL_EFUSES: + if efuse is not None: + self.EFUSES.append(efuse) + + self.ALL_EFUSES = [] diff --git a/espefuse/efuse/esp32h2beta1/operations.py b/espefuse/efuse/esp32h2beta1/operations.py index 9d10f2dd4..9f602544a 100644 --- a/espefuse/efuse/esp32h2beta1/operations.py +++ b/espefuse/efuse/esp32h2beta1/operations.py @@ -17,6 +17,7 @@ from ..base_operations import ( add_common_commands, add_force_write_always, + add_show_sensitive_info_option, burn_bit, burn_block_data, burn_efuse, @@ -55,6 +56,7 @@ def add_commands(subparsers, efuses): ) protect_options(burn_key) add_force_write_always(burn_key) + add_show_sensitive_info_option(burn_key) burn_key.add_argument( "block", help="Key block to burn", @@ -105,6 +107,7 @@ def add_commands(subparsers, efuses): ) protect_options(burn_key_digest) add_force_write_always(burn_key_digest) + add_show_sensitive_info_option(burn_key_digest) burn_key_digest.add_argument( "block", help="Key block to burn", @@ -163,8 +166,7 @@ def add_commands(subparsers, efuses): p.add_argument( "mac", help="Custom MAC Address to burn given in hexadecimal format with bytes " - "separated by colons (e.g. AA:CD:EF:01:02:03). " - "Final CUSTOM_MAC = CUSTOM_MAC[48] + MAC_EXT[16]", + "separated by colons (e.g. AA:CD:EF:01:02:03).", type=fields.base_fields.CheckArgValue(efuses, "CUSTOM_MAC"), ) add_force_write_always(p) @@ -191,7 +193,7 @@ def set_flash_voltage(esp, efuses, args): def adc_info(esp, efuses, args): print("") # fmt: off - if efuses["BLOCK2_VERSION"].get() == 1: + if efuses["BLK_VERSION_MAJOR"].get() == 1: print("Temperature Sensor Calibration = {}C".format(efuses["TEMP_SENSOR_CAL"].get())) print("") @@ -222,7 +224,7 @@ def adc_info(esp, efuses, args): print(" MODE3 D1 reading (250mV): {}".format(efuses["ADC2_MODE3_D1"].get())) print(" MODE3 D2 reading (2000mV): {}".format(efuses["ADC2_MODE3_D2"].get())) else: - print("BLOCK2_VERSION = {}".format(efuses["BLOCK2_VERSION"].get_meaning())) + print("BLK_VERSION_MAJOR = {}".format(efuses["BLK_VERSION_MAJOR"].get_meaning())) # fmt: on @@ -276,7 +278,13 @@ def burn_key(esp, efuses, args, digest=None): if efuses[block.key_purpose_name].need_reverse(keypurpose): revers_msg = "\tReversing byte order for AES-XTS hardware peripheral" data = data[::-1] - print("-> [%s]" % (util.hexify(data, " "))) + print( + "-> [{}]".format( + util.hexify(data, " ") + if args.show_sensitive_info + else " ".join(["??"] * len(data)) + ) + ) if revers_msg: print(revers_msg) if len(data) != num_bytes: diff --git a/espefuse/efuse/esp32p4/__init__.py b/espefuse/efuse/esp32p4/__init__.py new file mode 100644 index 000000000..a3b55a802 --- /dev/null +++ b/espefuse/efuse/esp32p4/__init__.py @@ -0,0 +1,3 @@ +from . import operations +from .emulate_efuse_controller import EmulateEfuseController +from .fields import EspEfuses diff --git a/espefuse/efuse/esp32p4/emulate_efuse_controller.py b/espefuse/efuse/esp32p4/emulate_efuse_controller.py new file mode 100644 index 000000000..aa670aff7 --- /dev/null +++ b/espefuse/efuse/esp32p4/emulate_efuse_controller.py @@ -0,0 +1,92 @@ +# This file describes eFuses controller for ESP32-P4 chip +# +# SPDX-FileCopyrightText: 2023 Espressif Systems (Shanghai) CO LTD +# +# SPDX-License-Identifier: GPL-2.0-or-later + +import reedsolo + +from .mem_definition import EfuseDefineBlocks, EfuseDefineFields, EfuseDefineRegisters +from ..emulate_efuse_controller_base import EmulateEfuseControllerBase, FatalError + + +class EmulateEfuseController(EmulateEfuseControllerBase): + """The class for virtual efuse operation. Using for HOST_TEST.""" + + CHIP_NAME = "ESP32-P4" + mem = None + debug = False + + def __init__(self, efuse_file=None, debug=False): + self.Blocks = EfuseDefineBlocks + self.Fields = EfuseDefineFields() + self.REGS = EfuseDefineRegisters + super(EmulateEfuseController, self).__init__(efuse_file, debug) + self.write_reg(self.REGS.EFUSE_CMD_REG, 0) + + """ esptool method start >>""" + + def get_major_chip_version(self): + return 0 + + def get_minor_chip_version(self): + return 0 + + def get_crystal_freq(self): + return 40 # MHz (common for all chips) + + def get_security_info(self): + return { + "flags": 0, + "flash_crypt_cnt": 0, + "key_purposes": 0, + "chip_id": 0, + "api_version": 0, + } + + """ << esptool method end """ + + def handle_writing_event(self, addr, value): + if addr == self.REGS.EFUSE_CMD_REG: + if value & self.REGS.EFUSE_PGM_CMD: + self.copy_blocks_wr_regs_to_rd_regs(updated_block=(value >> 2) & 0xF) + self.clean_blocks_wr_regs() + self.check_rd_protection_area() + self.write_reg(addr, 0) + self.write_reg(self.REGS.EFUSE_CMD_REG, 0) + elif value == self.REGS.EFUSE_READ_CMD: + self.write_reg(addr, 0) + self.write_reg(self.REGS.EFUSE_CMD_REG, 0) + self.save_to_file() + + def get_bitlen_of_block(self, blk, wr=False): + if blk.id == 0: + if wr: + return 32 * 8 + else: + return 32 * blk.len + else: + if wr: + rs_coding = 32 * 3 + return 32 * 8 + rs_coding + else: + return 32 * blk.len + + def handle_coding_scheme(self, blk, data): + if blk.id != 0: + # CODING_SCHEME RS applied only for all blocks except BLK0. + coded_bytes = 12 + data.pos = coded_bytes * 8 + plain_data = data.readlist("32*uint:8")[::-1] + # takes 32 bytes + # apply RS encoding + rs = reedsolo.RSCodec(coded_bytes) + # 32 byte of data + 12 bytes RS + calc_encoded_data = list(rs.encode([x for x in plain_data])) + data.pos = 0 + if calc_encoded_data != data.readlist("44*uint:8")[::-1]: + raise FatalError("Error in coding scheme data") + data = data[coded_bytes * 8 :] + if blk.len < 8: + data = data[(8 - blk.len) * 32 :] + return data diff --git a/espefuse/efuse/esp32p4/fields.py b/espefuse/efuse/esp32p4/fields.py new file mode 100644 index 000000000..b79816208 --- /dev/null +++ b/espefuse/efuse/esp32p4/fields.py @@ -0,0 +1,433 @@ +# This file describes eFuses for ESP32-P4 chip +# +# SPDX-FileCopyrightText: 2023 Espressif Systems (Shanghai) CO LTD +# +# SPDX-License-Identifier: GPL-2.0-or-later + +import binascii +import struct +import time + +from bitstring import BitArray + +import esptool + +import reedsolo + +from .mem_definition import EfuseDefineBlocks, EfuseDefineFields, EfuseDefineRegisters +from .. import base_fields +from .. import util + + +class EfuseBlock(base_fields.EfuseBlockBase): + def len_of_burn_unit(self): + # The writing register window is 8 registers for any blocks. + # len in bytes + return 8 * 4 + + def __init__(self, parent, param, skip_read=False): + parent.read_coding_scheme() + super(EfuseBlock, self).__init__(parent, param, skip_read=skip_read) + + def apply_coding_scheme(self): + data = self.get_raw(from_read=False)[::-1] + if len(data) < self.len_of_burn_unit(): + add_empty_bytes = self.len_of_burn_unit() - len(data) + data = data + (b"\x00" * add_empty_bytes) + if self.get_coding_scheme() == self.parent.REGS.CODING_SCHEME_RS: + # takes 32 bytes + # apply RS encoding + rs = reedsolo.RSCodec(12) + # 32 byte of data + 12 bytes RS + encoded_data = rs.encode([x for x in data]) + words = struct.unpack("<" + "I" * 11, encoded_data) + # returns 11 words (8 words of data + 3 words of RS coding) + else: + # takes 32 bytes + words = struct.unpack("<" + ("I" * (len(data) // 4)), data) + # returns 8 words + return words + + +class EspEfuses(base_fields.EspEfusesBase): + """ + Wrapper object to manage the efuse fields in a connected ESP bootloader + """ + + debug = False + do_not_confirm = False + + def __init__(self, esp, skip_connect=False, debug=False, do_not_confirm=False): + self.Blocks = EfuseDefineBlocks() + self.Fields = EfuseDefineFields() + self.REGS = EfuseDefineRegisters + self.BURN_BLOCK_DATA_NAMES = self.Blocks.get_burn_block_data_names() + self.BLOCKS_FOR_KEYS = self.Blocks.get_blocks_for_keys() + self._esp = esp + self.debug = debug + self.do_not_confirm = do_not_confirm + if esp.CHIP_NAME != "ESP32-P4": + raise esptool.FatalError( + "Expected the 'esp' param for ESP32-P4 chip but got for '%s'." + % (esp.CHIP_NAME) + ) + if not skip_connect: + flags = self._esp.get_security_info()["flags"] + GET_SECURITY_INFO_FLAG_SECURE_DOWNLOAD_ENABLE = 1 << 2 + if flags & GET_SECURITY_INFO_FLAG_SECURE_DOWNLOAD_ENABLE: + raise esptool.FatalError( + "Secure Download Mode is enabled. The tool can not read eFuses." + ) + self.blocks = [ + EfuseBlock(self, self.Blocks.get(block), skip_read=skip_connect) + for block in self.Blocks.BLOCKS + ] + if not skip_connect: + self.get_coding_scheme_warnings() + self.efuses = [EfuseField.convert(self, efuse) for efuse in self.Fields.EFUSES] + self.efuses += [ + EfuseField.convert(self, efuse) for efuse in self.Fields.KEYBLOCKS + ] + if skip_connect: + self.efuses += [ + EfuseField.convert(self, efuse) + for efuse in self.Fields.BLOCK2_CALIBRATION_EFUSES + ] + else: + # TODO add processing of self.Fields.BLOCK2_CALIBRATION_EFUSES + # if self["BLK_VERSION_MINOR"].get() == 1: + # self.efuses += [ + # EfuseField.convert(self, efuse) + # for efuse in self.Fields.BLOCK2_CALIBRATION_EFUSES + # ] + self.efuses += [ + EfuseField.convert(self, efuse) for efuse in self.Fields.CALC + ] + + def __getitem__(self, efuse_name): + """Return the efuse field with the given name""" + for e in self.efuses: + if efuse_name == e.name or any(x == efuse_name for x in e.alt_names): + return e + new_fields = False + for efuse in self.Fields.BLOCK2_CALIBRATION_EFUSES: + if efuse.name == efuse_name or any( + x == efuse_name for x in efuse.alt_names + ): + self.efuses += [ + EfuseField.convert(self, efuse) + for efuse in self.Fields.BLOCK2_CALIBRATION_EFUSES + ] + new_fields = True + if new_fields: + for e in self.efuses: + if efuse_name == e.name or any(x == efuse_name for x in e.alt_names): + return e + raise KeyError + + def read_coding_scheme(self): + self.coding_scheme = self.REGS.CODING_SCHEME_RS + + def print_status_regs(self): + print("") + self.blocks[0].print_block(self.blocks[0].err_bitarray, "err__regs", debug=True) + print( + "{:27} 0x{:08x}".format( + "EFUSE_RD_RS_ERR0_REG", self.read_reg(self.REGS.EFUSE_RD_RS_ERR0_REG) + ) + ) + print( + "{:27} 0x{:08x}".format( + "EFUSE_RD_RS_ERR1_REG", self.read_reg(self.REGS.EFUSE_RD_RS_ERR1_REG) + ) + ) + + def efuse_controller_setup(self): + self.set_efuse_timing() + self.clear_pgm_registers() + self.wait_efuse_idle() + + def write_efuses(self, block): + self.efuse_program(block) + return self.get_coding_scheme_warnings(silent=True) + + def clear_pgm_registers(self): + self.wait_efuse_idle() + for r in range( + self.REGS.EFUSE_PGM_DATA0_REG, self.REGS.EFUSE_PGM_DATA0_REG + 32, 4 + ): + self.write_reg(r, 0) + + def wait_efuse_idle(self): + deadline = time.time() + self.REGS.EFUSE_BURN_TIMEOUT + while time.time() < deadline: + cmds = self.REGS.EFUSE_PGM_CMD | self.REGS.EFUSE_READ_CMD + if self.read_reg(self.REGS.EFUSE_CMD_REG) & cmds == 0: + if self.read_reg(self.REGS.EFUSE_CMD_REG) & cmds == 0: + # Due to a hardware error, we have to read READ_CMD again + # to make sure the efuse clock is normal. + # For PGM_CMD it is not necessary. + return + raise esptool.FatalError( + "Timed out waiting for Efuse controller command to complete" + ) + + def efuse_program(self, block): + self.wait_efuse_idle() + self.write_reg(self.REGS.EFUSE_CONF_REG, self.REGS.EFUSE_WRITE_OP_CODE) + self.write_reg(self.REGS.EFUSE_CMD_REG, self.REGS.EFUSE_PGM_CMD | (block << 2)) + self.wait_efuse_idle() + self.clear_pgm_registers() + self.efuse_read() + + def efuse_read(self): + self.wait_efuse_idle() + self.write_reg(self.REGS.EFUSE_CONF_REG, self.REGS.EFUSE_READ_OP_CODE) + # need to add a delay after triggering EFUSE_READ_CMD, as ROM loader checks some + # efuse registers after each command is completed + # if ENABLE_SECURITY_DOWNLOAD or DIS_DOWNLOAD_MODE is enabled by the current cmd, then we need to try to reconnect to the chip. + try: + self.write_reg( + self.REGS.EFUSE_CMD_REG, self.REGS.EFUSE_READ_CMD, delay_after_us=1000 + ) + self.wait_efuse_idle() + except esptool.FatalError: + secure_download_mode_before = self._esp.secure_download_mode + + try: + self._esp = self.reconnect_chip(self._esp) + except esptool.FatalError: + print("Can not re-connect to the chip") + if not self["DIS_DOWNLOAD_MODE"].get() and self[ + "DIS_DOWNLOAD_MODE" + ].get(from_read=False): + print( + "This is the correct behavior as we are actually burning " + "DIS_DOWNLOAD_MODE which disables the connection to the chip" + ) + print("DIS_DOWNLOAD_MODE is enabled") + print("Successful") + exit(0) # finish without errors + raise + + print("Established a connection with the chip") + if self._esp.secure_download_mode and not secure_download_mode_before: + print("Secure download mode is enabled") + if not self["ENABLE_SECURITY_DOWNLOAD"].get() and self[ + "ENABLE_SECURITY_DOWNLOAD" + ].get(from_read=False): + print( + "espefuse tool can not continue to work in Secure download mode" + ) + print("ENABLE_SECURITY_DOWNLOAD is enabled") + print("Successful") + exit(0) # finish without errors + raise + + def set_efuse_timing(self): + """Set timing registers for burning efuses""" + # Configure clock + apb_freq = self.get_crystal_freq() + if apb_freq != 40: + raise esptool.FatalError( + "The eFuse supports only xtal=40M (xtal was %d)" % apb_freq + ) + # keep default timing settings + + def get_coding_scheme_warnings(self, silent=False): + """Check if the coding scheme has detected any errors.""" + old_addr_reg = 0 + reg_value = 0 + ret_fail = False + for block in self.blocks: + if block.id == 0: + words = [ + self.read_reg(self.REGS.EFUSE_RD_REPEAT_ERR0_REG + offs * 4) + for offs in range(5) + ] + block.err_bitarray.pos = 0 + for word in reversed(words): + block.err_bitarray.overwrite(BitArray("uint:32=%d" % word)) + block.num_errors = block.err_bitarray.count(True) + block.fail = block.num_errors != 0 + else: + addr_reg, err_num_mask, err_num_offs, fail_bit = self.REGS.BLOCK_ERRORS[ + block.id + ] + if err_num_mask is None or err_num_offs is None or fail_bit is None: + continue + if addr_reg != old_addr_reg: + old_addr_reg = addr_reg + reg_value = self.read_reg(addr_reg) + block.fail = reg_value & (1 << fail_bit) != 0 + block.num_errors = (reg_value >> err_num_offs) & err_num_mask + ret_fail |= block.fail + if not silent and (block.fail or block.num_errors): + print( + "Error(s) in BLOCK%d [ERRORS:%d FAIL:%d]" + % (block.id, block.num_errors, block.fail) + ) + if (self.debug or ret_fail) and not silent: + self.print_status_regs() + return ret_fail + + def summary(self): + # TODO add support set_flash_voltage - "Flash voltage (VDD_SPI)" + return "" + + +class EfuseField(base_fields.EfuseFieldBase): + @staticmethod + def convert(parent, efuse): + return { + "mac": EfuseMacField, + "keypurpose": EfuseKeyPurposeField, + "t_sensor": EfuseTempSensor, + "adc_tp": EfuseAdcPointCalibration, + }.get(efuse.class_type, EfuseField)(parent, efuse) + + +class EfuseTempSensor(EfuseField): + def get(self, from_read=True): + value = self.get_bitstring(from_read) + sig = -1 if value[0] else 1 + return sig * value[1:].uint * 0.1 + + +class EfuseAdcPointCalibration(EfuseField): + def get(self, from_read=True): + STEP_SIZE = 4 + value = self.get_bitstring(from_read) + sig = -1 if value[0] else 1 + return sig * value[1:].uint * STEP_SIZE + + +class EfuseMacField(EfuseField): + def check_format(self, new_value_str): + if new_value_str is None: + raise esptool.FatalError( + "Required MAC Address in AA:CD:EF:01:02:03 format!" + ) + num_bytes = 8 if self.name == "MAC_EUI64" else 6 + if new_value_str.count(":") != num_bytes - 1: + raise esptool.FatalError( + f"MAC Address needs to be a {num_bytes}-byte hexadecimal format " + "separated by colons (:)!" + ) + hexad = new_value_str.replace(":", "").split(" ", 1)[0] + hexad = hexad.split(" ", 1)[0] if self.is_field_calculated() else hexad + if len(hexad) != num_bytes * 2: + raise esptool.FatalError( + f"MAC Address needs to be a {num_bytes}-byte hexadecimal number " + f"({num_bytes * 2} hexadecimal characters)!" + ) + # order of bytearray = b'\xaa\xcd\xef\x01\x02\x03', + bindata = binascii.unhexlify(hexad) + + if not self.is_field_calculated(): + # unicast address check according to + # https://tools.ietf.org/html/rfc7042#section-2.1 + if esptool.util.byte(bindata, 0) & 0x01: + raise esptool.FatalError("Custom MAC must be a unicast MAC!") + return bindata + + def check(self): + errs, fail = self.parent.get_block_errors(self.block) + if errs != 0 or fail: + output = "Block%d has ERRORS:%d FAIL:%d" % (self.block, errs, fail) + else: + output = "OK" + return "(" + output + ")" + + def get(self, from_read=True): + if self.name == "CUSTOM_MAC": + mac = self.get_raw(from_read)[::-1] + elif self.name == "MAC": + mac = self.get_raw(from_read) + elif self.name == "MAC_EUI64": + mac = self.parent["MAC"].get_bitstring(from_read).copy() + mac_ext = self.parent["MAC_EXT"].get_bitstring(from_read) + mac.insert(mac_ext, 24) + mac = mac.bytes + else: + mac = self.get_raw(from_read) + return "%s %s" % (util.hexify(mac, ":"), self.check()) + + def save(self, new_value): + def print_field(e, new_value): + print( + " - '{}' ({}) {} -> {}".format( + e.name, e.description, e.get_bitstring(), new_value + ) + ) + + if self.name == "CUSTOM_MAC": + bitarray_mac = self.convert_to_bitstring(new_value) + print_field(self, bitarray_mac) + super(EfuseMacField, self).save(new_value) + else: + # Writing the BLOCK1 (MAC_SPI_8M_0) default MAC is not possible, + # as it's written in the factory. + raise esptool.FatalError(f"Burning {self.name} is not supported") + + +# fmt: off +class EfuseKeyPurposeField(EfuseField): + KEY_PURPOSES = [ + ("USER", 0, None, None, "no_need_rd_protect"), # User purposes (software-only use) + ("ECDSA_KEY", 1, None, "Reverse", "need_rd_protect"), # ECDSA key + ("XTS_AES_256_KEY_1", 2, None, "Reverse", "need_rd_protect"), # XTS_AES_256_KEY_1 (flash/PSRAM encryption) + ("XTS_AES_256_KEY_2", 3, None, "Reverse", "need_rd_protect"), # XTS_AES_256_KEY_2 (flash/PSRAM encryption) + ("XTS_AES_128_KEY", 4, None, "Reverse", "need_rd_protect"), # XTS_AES_128_KEY (flash/PSRAM encryption) + ("HMAC_DOWN_ALL", 5, None, None, "need_rd_protect"), # HMAC Downstream mode + ("HMAC_DOWN_JTAG", 6, None, None, "need_rd_protect"), # JTAG soft enable key (uses HMAC Downstream mode) + ("HMAC_DOWN_DIGITAL_SIGNATURE", 7, None, None, "need_rd_protect"), # Digital Signature peripheral key (uses HMAC Downstream mode) + ("HMAC_UP", 8, None, None, "need_rd_protect"), # HMAC Upstream mode + ("SECURE_BOOT_DIGEST0", 9, "DIGEST", None, "no_need_rd_protect"), # SECURE_BOOT_DIGEST0 (Secure Boot key digest) + ("SECURE_BOOT_DIGEST1", 10, "DIGEST", None, "no_need_rd_protect"), # SECURE_BOOT_DIGEST1 (Secure Boot key digest) + ("SECURE_BOOT_DIGEST2", 11, "DIGEST", None, "no_need_rd_protect"), # SECURE_BOOT_DIGEST2 (Secure Boot key digest) + ("KM_INIT_KEY", 12, None, None, "need_rd_protect"), # init key that is used for the generation of AES/ECDSA key + ] +# fmt: on + KEY_PURPOSES_NAME = [name[0] for name in KEY_PURPOSES] + DIGEST_KEY_PURPOSES = [name[0] for name in KEY_PURPOSES if name[2] == "DIGEST"] + + def check_format(self, new_value_str): + # str convert to int: "XTS_AES_128_KEY" - > str(4) + # if int: 4 -> str(4) + raw_val = new_value_str + for purpose_name in self.KEY_PURPOSES: + if purpose_name[0] == new_value_str: + raw_val = str(purpose_name[1]) + break + if raw_val.isdigit(): + if int(raw_val) not in [p[1] for p in self.KEY_PURPOSES if p[1] > 0]: + raise esptool.FatalError("'%s' can not be set (value out of range)" % raw_val) + else: + raise esptool.FatalError("'%s' unknown name" % raw_val) + return raw_val + + def need_reverse(self, new_key_purpose): + for key in self.KEY_PURPOSES: + if key[0] == new_key_purpose: + return key[3] == "Reverse" + + def need_rd_protect(self, new_key_purpose): + for key in self.KEY_PURPOSES: + if key[0] == new_key_purpose: + return key[4] == "need_rd_protect" + + def get(self, from_read=True): + for p in self.KEY_PURPOSES: + if p[1] == self.get_raw(from_read): + return p[0] + return "FORBIDDEN_STATE" + + def get_name(self, raw_val): + for key in self.KEY_PURPOSES: + if key[1] == raw_val: + return key[0] + + def save(self, new_value): + raw_val = int(self.check_format(str(new_value))) + return super(EfuseKeyPurposeField, self).save(raw_val) diff --git a/espefuse/efuse/esp32p4/mem_definition.py b/espefuse/efuse/esp32p4/mem_definition.py new file mode 100644 index 000000000..1d56f8d86 --- /dev/null +++ b/espefuse/efuse/esp32p4/mem_definition.py @@ -0,0 +1,169 @@ +# This file describes eFuses fields and registers for ESP32-P4 chip +# +# SPDX-FileCopyrightText: 2023 Espressif Systems (Shanghai) CO LTD +# +# SPDX-License-Identifier: GPL-2.0-or-later + +import os + +import yaml + +from ..mem_definition_base import ( + EfuseBlocksBase, + EfuseFieldsBase, + EfuseRegistersBase, + Field, +) + + +class EfuseDefineRegisters(EfuseRegistersBase): + EFUSE_MEM_SIZE = 0x01FC + 4 + + # EFUSE registers & command/conf values + DR_REG_EFUSE_BASE = 0x5012D000 + EFUSE_PGM_DATA0_REG = DR_REG_EFUSE_BASE + EFUSE_CHECK_VALUE0_REG = DR_REG_EFUSE_BASE + 0x020 + EFUSE_CLK_REG = DR_REG_EFUSE_BASE + 0x1C8 + EFUSE_CONF_REG = DR_REG_EFUSE_BASE + 0x1CC + EFUSE_STATUS_REG = DR_REG_EFUSE_BASE + 0x1D0 + EFUSE_CMD_REG = DR_REG_EFUSE_BASE + 0x1D4 + EFUSE_RD_RS_ERR0_REG = DR_REG_EFUSE_BASE + 0x1C0 + EFUSE_RD_RS_ERR1_REG = DR_REG_EFUSE_BASE + 0x1C4 + EFUSE_RD_REPEAT_ERR0_REG = DR_REG_EFUSE_BASE + 0x17C + EFUSE_RD_REPEAT_ERR1_REG = DR_REG_EFUSE_BASE + 0x180 + EFUSE_RD_REPEAT_ERR2_REG = DR_REG_EFUSE_BASE + 0x184 + EFUSE_RD_REPEAT_ERR3_REG = DR_REG_EFUSE_BASE + 0x188 + EFUSE_RD_REPEAT_ERR4_REG = DR_REG_EFUSE_BASE + 0x18C + EFUSE_DAC_CONF_REG = DR_REG_EFUSE_BASE + 0x1E8 + EFUSE_RD_TIM_CONF_REG = DR_REG_EFUSE_BASE + 0x1EC + EFUSE_WR_TIM_CONF1_REG = DR_REG_EFUSE_BASE + 0x1F0 + EFUSE_WR_TIM_CONF2_REG = DR_REG_EFUSE_BASE + 0x1F4 + EFUSE_DATE_REG = DR_REG_EFUSE_BASE + 0x1FC + EFUSE_WRITE_OP_CODE = 0x5A5A + EFUSE_READ_OP_CODE = 0x5AA5 + EFUSE_PGM_CMD_MASK = 0x3 + EFUSE_PGM_CMD = 0x2 + EFUSE_READ_CMD = 0x1 + + BLOCK_ERRORS = [ + # error_reg, err_num_mask, err_num_offs, fail_bit + (EFUSE_RD_REPEAT_ERR0_REG, None, None, None), # BLOCK0 + (EFUSE_RD_RS_ERR0_REG, 0x7, 0, 3), # MAC_SPI_8M_0 + (EFUSE_RD_RS_ERR0_REG, 0x7, 4, 7), # BLOCK_SYS_DATA + (EFUSE_RD_RS_ERR0_REG, 0x7, 8, 11), # BLOCK_USR_DATA + (EFUSE_RD_RS_ERR0_REG, 0x7, 12, 15), # BLOCK_KEY0 + (EFUSE_RD_RS_ERR0_REG, 0x7, 16, 19), # BLOCK_KEY1 + (EFUSE_RD_RS_ERR0_REG, 0x7, 20, 23), # BLOCK_KEY2 + (EFUSE_RD_RS_ERR0_REG, 0x7, 24, 27), # BLOCK_KEY3 + (EFUSE_RD_RS_ERR0_REG, 0x7, 28, 31), # BLOCK_KEY4 + (EFUSE_RD_RS_ERR1_REG, 0x7, 0, 3), # BLOCK_KEY5 + (EFUSE_RD_RS_ERR1_REG, 0x7, 4, 7), # BLOCK_SYS_DATA2 + ] + + # EFUSE_WR_TIM_CONF2_REG + EFUSE_PWR_OFF_NUM_S = 0 + EFUSE_PWR_OFF_NUM_M = 0xFFFF << EFUSE_PWR_OFF_NUM_S + + # EFUSE_WR_TIM_CONF1_REG + EFUSE_PWR_ON_NUM_S = 8 + EFUSE_PWR_ON_NUM_M = 0x0000FFFF << EFUSE_PWR_ON_NUM_S + + # EFUSE_DAC_CONF_REG + EFUSE_DAC_CLK_DIV_S = 0 + EFUSE_DAC_CLK_DIV_M = 0xFF << EFUSE_DAC_CLK_DIV_S + + # EFUSE_DAC_CONF_REG + EFUSE_DAC_NUM_S = 9 + EFUSE_DAC_NUM_M = 0xFF << EFUSE_DAC_NUM_S + + +class EfuseDefineBlocks(EfuseBlocksBase): + __base_rd_regs = EfuseDefineRegisters.DR_REG_EFUSE_BASE + __base_wr_regs = EfuseDefineRegisters.EFUSE_PGM_DATA0_REG + # List of efuse blocks + # fmt: off + BLOCKS = [ + # Name, Alias, Index, Read address, Write address, Write protect bit, Read protect bit, Len, key_purpose + ("BLOCK0", [], 0, __base_rd_regs + 0x02C, __base_wr_regs, None, None, 6, None), + ("MAC_SPI_8M_0", ["BLOCK1"], 1, __base_rd_regs + 0x044, __base_wr_regs, 20, None, 6, None), + ("BLOCK_SYS_DATA", ["BLOCK2"], 2, __base_rd_regs + 0x05C, __base_wr_regs, 21, None, 8, None), + ("BLOCK_USR_DATA", ["BLOCK3"], 3, __base_rd_regs + 0x07C, __base_wr_regs, 22, None, 8, None), + ("BLOCK_KEY0", ["BLOCK4"], 4, __base_rd_regs + 0x09C, __base_wr_regs, 23, 0, 8, "KEY_PURPOSE_0"), + ("BLOCK_KEY1", ["BLOCK5"], 5, __base_rd_regs + 0x0BC, __base_wr_regs, 24, 1, 8, "KEY_PURPOSE_1"), + ("BLOCK_KEY2", ["BLOCK6"], 6, __base_rd_regs + 0x0DC, __base_wr_regs, 25, 2, 8, "KEY_PURPOSE_2"), + ("BLOCK_KEY3", ["BLOCK7"], 7, __base_rd_regs + 0x0FC, __base_wr_regs, 26, 3, 8, "KEY_PURPOSE_3"), + ("BLOCK_KEY4", ["BLOCK8"], 8, __base_rd_regs + 0x11C, __base_wr_regs, 27, 4, 8, "KEY_PURPOSE_4"), + ("BLOCK_KEY5", ["BLOCK9"], 9, __base_rd_regs + 0x13C, __base_wr_regs, 28, 5, 8, "KEY_PURPOSE_5"), + ("BLOCK_SYS_DATA2", ["BLOCK10"], 10, __base_rd_regs + 0x15C, __base_wr_regs, 29, 6, 8, None), + ] + # fmt: on + + def get_burn_block_data_names(self): + list_of_names = [] + for block in self.BLOCKS: + blk = self.get(block) + if blk.name: + list_of_names.append(blk.name) + if blk.alias: + for alias in blk.alias: + list_of_names.append(alias) + return list_of_names + + +class EfuseDefineFields(EfuseFieldsBase): + def __init__(self) -> None: + # List of efuse fields from TRM the chapter eFuse Controller. + self.EFUSES = [] + + self.KEYBLOCKS = [] + + # if BLK_VERSION_MINOR is 1, these efuse fields are in BLOCK2 + self.BLOCK2_CALIBRATION_EFUSES = [] + + self.CALC = [] + + dir_name = os.path.dirname(os.path.abspath(__file__)) + dir_name, file_name = os.path.split(dir_name) + file_name = file_name + ".yaml" + dir_name, _ = os.path.split(dir_name) + efuse_file = os.path.join(dir_name, "efuse_defs", file_name) + with open(f"{efuse_file}", "r") as r_file: + e_desc = yaml.safe_load(r_file) + super().__init__(e_desc) + + for i, efuse in enumerate(self.ALL_EFUSES): + if efuse.name in [ + "BLOCK_USR_DATA", + "BLOCK_KEY0", + "BLOCK_KEY1", + "BLOCK_KEY2", + "BLOCK_KEY3", + "BLOCK_KEY4", + "BLOCK_KEY5", + "BLOCK_SYS_DATA2", + ]: + if efuse.name == "BLOCK_USR_DATA": + efuse.bit_len = 256 + efuse.type = "bytes:32" + self.KEYBLOCKS.append(efuse) + self.ALL_EFUSES[i] = None + + elif efuse.category == "calibration": + self.BLOCK2_CALIBRATION_EFUSES.append(efuse) + self.ALL_EFUSES[i] = None + + f = Field() + f.name = "MAC_EUI64" + f.block = 1 + f.bit_len = 64 + f.type = f"bytes:{f.bit_len // 8}" + f.category = "MAC" + f.class_type = "mac" + f.description = "calc MAC_EUI64 = MAC[0]:MAC[1]:MAC[2]:MAC_EXT[0]:MAC_EXT[1]:MAC[3]:MAC[4]:MAC[5]" + self.CALC.append(f) + + for efuse in self.ALL_EFUSES: + if efuse is not None: + self.EFUSES.append(efuse) + + self.ALL_EFUSES = [] diff --git a/espefuse/efuse/esp32p4/operations.py b/espefuse/efuse/esp32p4/operations.py new file mode 100644 index 000000000..093a04802 --- /dev/null +++ b/espefuse/efuse/esp32p4/operations.py @@ -0,0 +1,391 @@ +# This file includes the operations with eFuses for ESP32-P4 chip +# +# SPDX-FileCopyrightText: 2023 Espressif Systems (Shanghai) CO LTD +# +# SPDX-License-Identifier: GPL-2.0-or-later + +import argparse +import os # noqa: F401. It is used in IDF scripts +import traceback + +import espsecure + +import esptool + +from . import fields +from .. import util +from ..base_operations import ( + add_common_commands, + add_force_write_always, + add_show_sensitive_info_option, + burn_bit, + burn_block_data, + burn_efuse, + check_error, + dump, + read_protect_efuse, + summary, + write_protect_efuse, +) + + +def protect_options(p): + p.add_argument( + "--no-write-protect", + help="Disable write-protecting of the key. The key remains writable. " + "(The keys use the RS coding scheme that does not support " + "post-write data changes. Forced write can damage RS encoding bits.) " + "The write-protecting of keypurposes does not depend on the option, " + "it will be set anyway.", + action="store_true", + ) + p.add_argument( + "--no-read-protect", + help="Disable read-protecting of the key. The key remains readable software." + "The key with keypurpose[USER, RESERVED and *_DIGEST] " + "will remain readable anyway. For the rest keypurposes the read-protection " + "will be defined the option (Read-protect by default).", + action="store_true", + ) + + +def add_commands(subparsers, efuses): + add_common_commands(subparsers, efuses) + burn_key = subparsers.add_parser( + "burn_key", help="Burn the key block with the specified name" + ) + protect_options(burn_key) + add_force_write_always(burn_key) + add_show_sensitive_info_option(burn_key) + burn_key.add_argument( + "block", + help="Key block to burn", + action="append", + choices=efuses.BLOCKS_FOR_KEYS, + ) + burn_key.add_argument( + "keyfile", + help="File containing 256 bits of binary key data. For the ECDSA_KEY purpose use PEM file.", + action="append", + type=argparse.FileType("rb"), + ) + burn_key.add_argument( + "keypurpose", + help="Purpose to set.", + action="append", + choices=fields.EfuseKeyPurposeField.KEY_PURPOSES_NAME, + ) + for _ in efuses.BLOCKS_FOR_KEYS: + burn_key.add_argument( + "block", + help="Key block to burn", + nargs="?", + action="append", + metavar="BLOCK", + choices=efuses.BLOCKS_FOR_KEYS, + ) + burn_key.add_argument( + "keyfile", + help="File containing 256 bits of binary key data. For the ECDSA_KEY purpose use PEM file.", + nargs="?", + action="append", + metavar="KEYFILE", + type=argparse.FileType("rb"), + ) + burn_key.add_argument( + "keypurpose", + help="Purpose to set.", + nargs="?", + action="append", + metavar="KEYPURPOSE", + choices=fields.EfuseKeyPurposeField.KEY_PURPOSES_NAME, + ) + + burn_key_digest = subparsers.add_parser( + "burn_key_digest", + help="Parse a RSA public key and burn the digest to key efuse block", + ) + protect_options(burn_key_digest) + add_force_write_always(burn_key_digest) + add_show_sensitive_info_option(burn_key_digest) + burn_key_digest.add_argument( + "block", + help="Key block to burn", + action="append", + choices=efuses.BLOCKS_FOR_KEYS, + ) + burn_key_digest.add_argument( + "keyfile", + help="Key file to digest (PEM format)", + action="append", + type=argparse.FileType("rb"), + ) + burn_key_digest.add_argument( + "keypurpose", + help="Purpose to set.", + action="append", + choices=fields.EfuseKeyPurposeField.DIGEST_KEY_PURPOSES, + ) + for _ in efuses.BLOCKS_FOR_KEYS: + burn_key_digest.add_argument( + "block", + help="Key block to burn", + nargs="?", + action="append", + metavar="BLOCK", + choices=efuses.BLOCKS_FOR_KEYS, + ) + burn_key_digest.add_argument( + "keyfile", + help="Key file to digest (PEM format)", + nargs="?", + action="append", + metavar="KEYFILE", + type=argparse.FileType("rb"), + ) + burn_key_digest.add_argument( + "keypurpose", + help="Purpose to set.", + nargs="?", + action="append", + metavar="KEYPURPOSE", + choices=fields.EfuseKeyPurposeField.DIGEST_KEY_PURPOSES, + ) + + p = subparsers.add_parser( + "set_flash_voltage", + help="Permanently set the internal flash voltage regulator " + "to either 1.8V, 3.3V or OFF. " + "This means GPIO45 can be high or low at reset without " + "changing the flash voltage.", + ) + p.add_argument("voltage", help="Voltage selection", choices=["1.8V", "3.3V", "OFF"]) + + p = subparsers.add_parser( + "burn_custom_mac", help="Burn a 48-bit Custom MAC Address to EFUSE BLOCK3." + ) + p.add_argument( + "mac", + help="Custom MAC Address to burn given in hexadecimal format with bytes " + "separated by colons (e.g. AA:CD:EF:01:02:03).", + type=fields.base_fields.CheckArgValue(efuses, "CUSTOM_MAC"), + ) + add_force_write_always(p) + + p = subparsers.add_parser("get_custom_mac", help="Prints the Custom MAC Address.") + + +def burn_custom_mac(esp, efuses, args): + print("Not supported yet") + + +def get_custom_mac(esp, efuses, args): + print("Not supported yet") + + +def set_flash_voltage(esp, efuses, args): + raise esptool.FatalError("set_flash_voltage is not supported!") + + +def adc_info(esp, efuses, args): + print("not supported yet") + + +def burn_key(esp, efuses, args, digest=None): + if digest is None: + datafile_list = args.keyfile[ + 0 : len([name for name in args.keyfile if name is not None]) : + ] + else: + datafile_list = digest[0 : len([name for name in digest if name is not None]) :] + efuses.force_write_always = args.force_write_always + block_name_list = args.block[ + 0 : len([name for name in args.block if name is not None]) : + ] + keypurpose_list = args.keypurpose[ + 0 : len([name for name in args.keypurpose if name is not None]) : + ] + + util.check_duplicate_name_in_list(block_name_list) + if len(block_name_list) != len(datafile_list) or len(block_name_list) != len( + keypurpose_list + ): + raise esptool.FatalError( + "The number of blocks (%d), datafile (%d) and keypurpose (%d) " + "should be the same." + % (len(block_name_list), len(datafile_list), len(keypurpose_list)) + ) + + print("Burn keys to blocks:") + for block_name, datafile, keypurpose in zip( + block_name_list, datafile_list, keypurpose_list + ): + efuse = None + for block in efuses.blocks: + if block_name == block.name or block_name in block.alias: + efuse = efuses[block.name] + if efuse is None: + raise esptool.FatalError("Unknown block name - %s" % (block_name)) + num_bytes = efuse.bit_len // 8 + + block_num = efuses.get_index_block_by_name(block_name) + block = efuses.blocks[block_num] + + if digest is None: + if keypurpose == "ECDSA_KEY": + sk = espsecure.load_ecdsa_signing_key(datafile) + data = sk.to_string() + if len(data) == 24: + # the private key is 24 bytes long for NIST192p, add 8 bytes of padding + data = b"\x00" * 8 + data + else: + data = datafile.read() + else: + data = datafile + + print(" - %s" % (efuse.name), end=" ") + revers_msg = None + if efuses[block.key_purpose_name].need_reverse(keypurpose): + revers_msg = f"\tReversing byte order for {keypurpose} hardware peripheral" + data = data[::-1] + print( + "-> [{}]".format( + util.hexify(data, " ") + if args.show_sensitive_info + else " ".join(["??"] * len(data)) + ) + ) + if revers_msg: + print(revers_msg) + if len(data) != num_bytes: + raise esptool.FatalError( + "Incorrect key file size %d. Key file must be %d bytes (%d bits) " + "of raw binary key data." % (len(data), num_bytes, num_bytes * 8) + ) + + if efuses[block.key_purpose_name].need_rd_protect(keypurpose): + read_protect = False if args.no_read_protect else True + else: + read_protect = False + write_protect = not args.no_write_protect + + # using efuse instead of a block gives the advantage of checking it as the whole field. + efuse.save(data) + + disable_wr_protect_key_purpose = False + if efuses[block.key_purpose_name].get() != keypurpose: + if efuses[block.key_purpose_name].is_writeable(): + print( + "\t'%s': '%s' -> '%s'." + % ( + block.key_purpose_name, + efuses[block.key_purpose_name].get(), + keypurpose, + ) + ) + efuses[block.key_purpose_name].save(keypurpose) + disable_wr_protect_key_purpose = True + else: + raise esptool.FatalError( + "It is not possible to change '%s' to '%s' " + "because write protection bit is set." + % (block.key_purpose_name, keypurpose) + ) + else: + print("\t'%s' is already '%s'." % (block.key_purpose_name, keypurpose)) + if efuses[block.key_purpose_name].is_writeable(): + disable_wr_protect_key_purpose = True + + if disable_wr_protect_key_purpose: + print("\tDisabling write to '%s'." % block.key_purpose_name) + efuses[block.key_purpose_name].disable_write() + + if read_protect: + print("\tDisabling read to key block") + efuse.disable_read() + + if write_protect: + print("\tDisabling write to key block") + efuse.disable_write() + print("") + + if not write_protect: + print("Keys will remain writeable (due to --no-write-protect)") + if args.no_read_protect: + print("Keys will remain readable (due to --no-read-protect)") + + if not efuses.burn_all(check_batch_mode=True): + return + print("Successful") + + +def burn_key_digest(esp, efuses, args): + digest_list = [] + datafile_list = args.keyfile[ + 0 : len([name for name in args.keyfile if name is not None]) : + ] + block_list = args.block[ + 0 : len([block for block in args.block if block is not None]) : + ] + for block_name, datafile in zip(block_list, datafile_list): + efuse = None + for block in efuses.blocks: + if block_name == block.name or block_name in block.alias: + efuse = efuses[block.name] + if efuse is None: + raise esptool.FatalError("Unknown block name - %s" % (block_name)) + num_bytes = efuse.bit_len // 8 + digest = espsecure._digest_sbv2_public_key(datafile) + if len(digest) != num_bytes: + raise esptool.FatalError( + "Incorrect digest size %d. Digest must be %d bytes (%d bits) " + "of raw binary key data." % (len(digest), num_bytes, num_bytes * 8) + ) + digest_list.append(digest) + burn_key(esp, efuses, args, digest=digest_list) + + +def espefuse(esp, efuses, args, command): + parser = argparse.ArgumentParser() + subparsers = parser.add_subparsers(dest="operation") + add_commands(subparsers, efuses) + try: + cmd_line_args = parser.parse_args(command.split()) + except SystemExit: + traceback.print_stack() + raise esptool.FatalError('"{}" - incorrect command'.format(command)) + if cmd_line_args.operation == "execute_scripts": + configfiles = cmd_line_args.configfiles + index = cmd_line_args.index + # copy arguments from args to cmd_line_args + vars(cmd_line_args).update(vars(args)) + if cmd_line_args.operation == "execute_scripts": + cmd_line_args.configfiles = configfiles + cmd_line_args.index = index + if cmd_line_args.operation is None: + parser.print_help() + parser.exit(1) + operation_func = globals()[cmd_line_args.operation] + # each 'operation' is a module-level function of the same name + operation_func(esp, efuses, cmd_line_args) + + +def execute_scripts(esp, efuses, args): + efuses.batch_mode_cnt += 1 + del args.operation + scripts = args.scripts + del args.scripts + + for file in scripts: + with open(file.name, "r") as file: + exec(compile(file.read(), file.name, "exec")) + + if args.debug: + for block in efuses.blocks: + data = block.get_bitstring(from_read=False) + block.print_block(data, "regs_for_burn", args.debug) + + efuses.batch_mode_cnt -= 1 + if not efuses.burn_all(check_batch_mode=True): + return + print("Successful") diff --git a/espefuse/efuse/esp32s2/emulate_efuse_controller.py b/espefuse/efuse/esp32s2/emulate_efuse_controller.py index 749fd424f..497c91a5f 100644 --- a/espefuse/efuse/esp32s2/emulate_efuse_controller.py +++ b/espefuse/efuse/esp32s2/emulate_efuse_controller.py @@ -16,13 +16,13 @@ class EmulateEfuseController(EmulateEfuseControllerBase): CHIP_NAME = "ESP32-S2" mem = None debug = False - Blocks = EfuseDefineBlocks - Fields = EfuseDefineFields - REGS = EfuseDefineRegisters def __init__(self, efuse_file=None, debug=False): + self.Blocks = EfuseDefineBlocks + self.Fields = EfuseDefineFields() + self.REGS = EfuseDefineRegisters super(EmulateEfuseController, self).__init__(efuse_file, debug) - self.write_reg(self.REGS.EFUSE_STATUS_REG, 1) + self.write_reg(self.REGS.EFUSE_CMD_REG, 0) """ esptool method start >>""" @@ -53,10 +53,10 @@ def handle_writing_event(self, addr, value): self.clean_blocks_wr_regs() self.check_rd_protection_area() self.write_reg(addr, 0) - self.write_reg(self.REGS.EFUSE_STATUS_REG, 1) + self.write_reg(self.REGS.EFUSE_CMD_REG, 0) elif value == self.REGS.EFUSE_READ_CMD: self.write_reg(addr, 0) - self.write_reg(self.REGS.EFUSE_STATUS_REG, 1) + self.write_reg(self.REGS.EFUSE_CMD_REG, 0) self.save_to_file() def get_bitlen_of_block(self, blk, wr=False): diff --git a/espefuse/efuse/esp32s2/fields.py b/espefuse/efuse/esp32s2/fields.py index 4bc7af9a7..a4113848b 100644 --- a/espefuse/efuse/esp32s2/fields.py +++ b/espefuse/efuse/esp32s2/fields.py @@ -54,16 +54,15 @@ class EspEfuses(base_fields.EspEfusesBase): Wrapper object to manage the efuse fields in a connected ESP bootloader """ - Blocks = EfuseDefineBlocks() - Fields = EfuseDefineFields() - REGS = EfuseDefineRegisters - BURN_BLOCK_DATA_NAMES = Blocks.get_burn_block_data_names() - BLOCKS_FOR_KEYS = Blocks.get_blocks_for_keys() - debug = False do_not_confirm = False def __init__(self, esp, skip_connect=False, debug=False, do_not_confirm=False): + self.Blocks = EfuseDefineBlocks() + self.Fields = EfuseDefineFields() + self.REGS = EfuseDefineRegisters + self.BURN_BLOCK_DATA_NAMES = self.Blocks.get_burn_block_data_names() + self.BLOCKS_FOR_KEYS = self.Blocks.get_blocks_for_keys() self._esp = esp self.debug = debug self.do_not_confirm = do_not_confirm @@ -85,59 +84,43 @@ def __init__(self, esp, skip_connect=False, debug=False, do_not_confirm=False): ] if not skip_connect: self.get_coding_scheme_warnings() - self.efuses = [ - EfuseField.from_tuple( - self, self.Fields.get(efuse), self.Fields.get(efuse).class_type - ) - for efuse in self.Fields.EFUSES - ] + self.efuses = [EfuseField.convert(self, efuse) for efuse in self.Fields.EFUSES] self.efuses += [ - EfuseField.from_tuple( - self, self.Fields.get(efuse), self.Fields.get(efuse).class_type - ) - for efuse in self.Fields.KEYBLOCKS + EfuseField.convert(self, efuse) for efuse in self.Fields.KEYBLOCKS ] if skip_connect: self.efuses += [ - EfuseField.from_tuple( - self, self.Fields.get(efuse), self.Fields.get(efuse).class_type - ) + EfuseField.convert(self, efuse) for efuse in self.Fields.BLOCK2_CALIBRATION_EFUSES ] else: if self["BLK_VERSION_MINOR"].get() == 1: self.efuses += [ - EfuseField.from_tuple( - self, self.Fields.get(efuse), self.Fields.get(efuse).class_type - ) + EfuseField.convert(self, efuse) for efuse in self.Fields.BLOCK2_CALIBRATION_EFUSES ] self.efuses += [ - EfuseField.from_tuple( - self, self.Fields.get(efuse), self.Fields.get(efuse).class_type - ) - for efuse in self.Fields.CALC + EfuseField.convert(self, efuse) for efuse in self.Fields.CALC ] def __getitem__(self, efuse_name): """Return the efuse field with the given name""" for e in self.efuses: - if efuse_name == e.name: + if efuse_name == e.name or any(x == efuse_name for x in e.alt_names): return e new_fields = False for efuse in self.Fields.BLOCK2_CALIBRATION_EFUSES: - e = self.Fields.get(efuse) - if e.name == efuse_name: + if efuse.name == efuse_name or any( + x == efuse_name for x in efuse.alt_names + ): self.efuses += [ - EfuseField.from_tuple( - self, self.Fields.get(efuse), self.Fields.get(efuse).class_type - ) + EfuseField.convert(self, efuse) for efuse in self.Fields.BLOCK2_CALIBRATION_EFUSES ] new_fields = True if new_fields: for e in self.efuses: - if efuse_name == e.name: + if efuse_name == e.name or any(x == efuse_name for x in e.alt_names): return e raise KeyError @@ -158,10 +141,6 @@ def print_status_regs(self): ) ) - def get_block_errors(self, block_num): - """Returns (error count, failure boolean flag)""" - return self.blocks[block_num].num_errors, self.blocks[block_num].fail - def efuse_controller_setup(self): self.set_efuse_timing() self.clear_pgm_registers() @@ -181,9 +160,13 @@ def clear_pgm_registers(self): def wait_efuse_idle(self): deadline = time.time() + self.REGS.EFUSE_BURN_TIMEOUT while time.time() < deadline: - # if self.read_reg(self.EFUSE_CMD_REG) == 0: - if self.read_reg(self.REGS.EFUSE_STATUS_REG) & 0x7 == 1: - return + cmds = self.REGS.EFUSE_PGM_CMD | self.REGS.EFUSE_READ_CMD + if self.read_reg(self.REGS.EFUSE_CMD_REG) & cmds == 0: + if self.read_reg(self.REGS.EFUSE_CMD_REG) & cmds == 0: + # Due to a hardware error, we have to read READ_CMD again + # to make sure the efuse clock is normal. + # For PGM_CMD it is not necessary. + return raise esptool.FatalError( "Timed out waiting for Efuse controller command to complete" ) @@ -310,12 +293,9 @@ def get_coding_scheme_warnings(self, silent=False): self.read_reg(self.REGS.EFUSE_RD_REPEAT_ERR0_REG + offs * 4) for offs in range(5) ] - data = BitArray() + block.err_bitarray.pos = 0 for word in reversed(words): - data.append("uint:32=%d" % word) - # pos=32 because EFUSE_WR_DIS goes first it is 32bit long - # and not under error control - block.err_bitarray.overwrite(data, pos=32) + block.err_bitarray.overwrite(BitArray("uint:32=%d" % word)) block.num_errors = block.err_bitarray.count(True) block.fail = block.num_errors != 0 else: @@ -342,9 +322,10 @@ def get_coding_scheme_warnings(self, silent=False): def summary(self): if self["VDD_SPI_FORCE"].get() == 0: output = "Flash voltage (VDD_SPI) determined by GPIO45 on reset " - "(GPIO45=High: VDD_SPI pin is powered from internal 1.8V LDO\n" + output += "(GPIO45=High: VDD_SPI pin is powered from internal 1.8V LDO\n" output += "GPIO45=Low or NC: VDD_SPI pin is powered directly from " - "VDD3P3_RTC_IO via resistor Rspi. Typically this voltage is 3.3 V)." + output += "VDD3P3_RTC_IO via resistor Rspi. " + output += "Typically this voltage is 3.3 V)." elif self["VDD_SPI_XPD"].get() == 0: output = "Flash voltage (VDD_SPI) internal regulator disabled by efuse." elif self["VDD_SPI_TIEH"].get() == 0: @@ -356,35 +337,22 @@ def summary(self): class EfuseField(base_fields.EfuseFieldBase): @staticmethod - def from_tuple(parent, efuse_tuple, type_class): + def convert(parent, efuse): return { "mac": EfuseMacField, "keypurpose": EfuseKeyPurposeField, "t_sensor": EfuseTempSensor, "adc_tp": EfuseAdcPointCalibration, "wafer": EfuseWafer, - }.get(type_class, EfuseField)(parent, efuse_tuple) - - def get_info(self): - output = "%s (BLOCK%d)" % (self.name, self.block) - errs, fail = self.parent.get_block_errors(self.block) - if errs != 0 or fail: - output += ( - "[FAIL:%d]" % (fail) - if self.block == 0 - else "[ERRS:%d FAIL:%d]" % (errs, fail) - ) - if self.efuse_class == "keyblock": - name = self.parent.blocks[self.block].key_purpose_name - if name is not None: - output += "\n Purpose: %s\n " % (self.parent[name].get()) - return output + }.get(efuse.class_type, EfuseField)(parent, efuse) class EfuseWafer(EfuseField): def get(self, from_read=True): hi_bits = self.parent["WAFER_VERSION_MINOR_HI"].get(from_read) + assert self.parent["WAFER_VERSION_MINOR_HI"].bit_len == 1 lo_bits = self.parent["WAFER_VERSION_MINOR_LO"].get(from_read) + assert self.parent["WAFER_VERSION_MINOR_LO"].bit_len == 3 return (hi_bits << 3) + lo_bits def save(self, new_value): diff --git a/espefuse/efuse/esp32s2/mem_definition.py b/espefuse/efuse/esp32s2/mem_definition.py index 94642ad3c..b83ea9139 100644 --- a/espefuse/efuse/esp32s2/mem_definition.py +++ b/espefuse/efuse/esp32s2/mem_definition.py @@ -4,24 +4,31 @@ # # SPDX-License-Identifier: GPL-2.0-or-later -from ..mem_definition_base import EfuseBlocksBase, EfuseFieldsBase, EfuseRegistersBase +import os +import yaml + +from ..mem_definition_base import ( + EfuseBlocksBase, + EfuseFieldsBase, + EfuseRegistersBase, + Field, +) -# fmt: off -class EfuseDefineRegisters(EfuseRegistersBase): - EFUSE_MEM_SIZE = (0x01FC + 4) +class EfuseDefineRegisters(EfuseRegistersBase): + EFUSE_MEM_SIZE = 0x01FC + 4 # EFUSE registers & command/conf values - DR_REG_EFUSE_BASE = 0x3f41A000 - EFUSE_PGM_DATA0_REG = DR_REG_EFUSE_BASE - EFUSE_CHECK_VALUE0_REG = DR_REG_EFUSE_BASE + 0x020 - EFUSE_CLK_REG = DR_REG_EFUSE_BASE + 0x1c8 - EFUSE_CONF_REG = DR_REG_EFUSE_BASE + 0x1cc - EFUSE_STATUS_REG = DR_REG_EFUSE_BASE + 0x1d0 - EFUSE_CMD_REG = DR_REG_EFUSE_BASE + 0x1d4 - EFUSE_RD_RS_ERR0_REG = DR_REG_EFUSE_BASE + 0x194 - EFUSE_RD_RS_ERR1_REG = DR_REG_EFUSE_BASE + 0x198 + DR_REG_EFUSE_BASE = 0x3F41A000 + EFUSE_PGM_DATA0_REG = DR_REG_EFUSE_BASE + EFUSE_CHECK_VALUE0_REG = DR_REG_EFUSE_BASE + 0x020 + EFUSE_CLK_REG = DR_REG_EFUSE_BASE + 0x1C8 + EFUSE_CONF_REG = DR_REG_EFUSE_BASE + 0x1CC + EFUSE_STATUS_REG = DR_REG_EFUSE_BASE + 0x1D0 + EFUSE_CMD_REG = DR_REG_EFUSE_BASE + 0x1D4 + EFUSE_RD_RS_ERR0_REG = DR_REG_EFUSE_BASE + 0x194 + EFUSE_RD_RS_ERR1_REG = DR_REG_EFUSE_BASE + 0x198 EFUSE_RD_REPEAT_ERR0_REG = DR_REG_EFUSE_BASE + 0x17C EFUSE_RD_REPEAT_ERR1_REG = DR_REG_EFUSE_BASE + 0x180 EFUSE_RD_REPEAT_ERR2_REG = DR_REG_EFUSE_BASE + 0x184 @@ -32,28 +39,28 @@ class EfuseDefineRegisters(EfuseRegistersBase): EFUSE_WR_TIM_CONF1_REG = DR_REG_EFUSE_BASE + 0x1F4 EFUSE_WR_TIM_CONF2_REG = DR_REG_EFUSE_BASE + 0x1F8 EFUSE_DATE_REG = DR_REG_EFUSE_BASE + 0x1FC - EFUSE_WRITE_OP_CODE = 0x5A5A - EFUSE_READ_OP_CODE = 0x5AA5 - EFUSE_PGM_CMD_MASK = 0x3 - EFUSE_PGM_CMD = 0x2 - EFUSE_READ_CMD = 0x1 + EFUSE_WRITE_OP_CODE = 0x5A5A + EFUSE_READ_OP_CODE = 0x5AA5 + EFUSE_PGM_CMD_MASK = 0x3 + EFUSE_PGM_CMD = 0x2 + EFUSE_READ_CMD = 0x1 BLOCK_ERRORS = [ # error_reg, err_num_mask, err_num_offs, fail_bit - (EFUSE_RD_REPEAT_ERR0_REG, None, None, None), # BLOCK0 - (EFUSE_RD_RS_ERR0_REG, 0x7, 0, 3), # MAC_SPI_8M_0 - (EFUSE_RD_RS_ERR0_REG, 0x7, 4, 7), # BLOCK_SYS_DATA - (EFUSE_RD_RS_ERR0_REG, 0x7, 8, 11), # BLOCK_USR_DATA - (EFUSE_RD_RS_ERR0_REG, 0x7, 12, 15), # BLOCK_KEY0 - (EFUSE_RD_RS_ERR0_REG, 0x7, 16, 19), # BLOCK_KEY1 - (EFUSE_RD_RS_ERR0_REG, 0x7, 20, 23), # BLOCK_KEY2 - (EFUSE_RD_RS_ERR0_REG, 0x7, 24, 27), # BLOCK_KEY3 - (EFUSE_RD_RS_ERR0_REG, 0x7, 28, 31), # BLOCK_KEY4 - (EFUSE_RD_RS_ERR1_REG, 0x7, 0, 3), # BLOCK_KEY5 - (EFUSE_RD_RS_ERR1_REG, 0x7, 4, 7), # BLOCK_SYS_DATA2 + (EFUSE_RD_REPEAT_ERR0_REG, None, None, None), # BLOCK0 + (EFUSE_RD_RS_ERR0_REG, 0x7, 0, 3), # MAC_SPI_8M_0 + (EFUSE_RD_RS_ERR0_REG, 0x7, 4, 7), # BLOCK_SYS_DATA + (EFUSE_RD_RS_ERR0_REG, 0x7, 8, 11), # BLOCK_USR_DATA + (EFUSE_RD_RS_ERR0_REG, 0x7, 12, 15), # BLOCK_KEY0 + (EFUSE_RD_RS_ERR0_REG, 0x7, 16, 19), # BLOCK_KEY1 + (EFUSE_RD_RS_ERR0_REG, 0x7, 20, 23), # BLOCK_KEY2 + (EFUSE_RD_RS_ERR0_REG, 0x7, 24, 27), # BLOCK_KEY3 + (EFUSE_RD_RS_ERR0_REG, 0x7, 28, 31), # BLOCK_KEY4 + (EFUSE_RD_RS_ERR1_REG, 0x7, 0, 3), # BLOCK_KEY5 + (EFUSE_RD_RS_ERR1_REG, 0x7, 4, 7), # BLOCK_SYS_DATA2 ] - EFUSE_DAC_CONF_REG = DR_REG_EFUSE_BASE + 0x1e8 + EFUSE_DAC_CONF_REG = DR_REG_EFUSE_BASE + 0x1E8 EFUSE_DAC_CLK_DIV_S = 0 EFUSE_DAC_CLK_DIV_M = 0xFF << EFUSE_DAC_CLK_DIV_S @@ -89,7 +96,7 @@ class EfuseDefineRegisters(EfuseRegistersBase): # Taken from TRM chapter "eFuse Controller": eFuse-Programming Timing 80: (0x2, 0x320, 0x2, 0x4), 40: (0x1, 0x190, 0x1, 0x2), - 20: (0x1, 0xC8, 0x1, 0x1), + 20: (0x1, 0xC8, 0x1, 0x1), } VDDQ_TIMING_PARAMETERS = { @@ -110,10 +117,10 @@ class EfuseDefineRegisters(EfuseRegistersBase): class EfuseDefineBlocks(EfuseBlocksBase): - __base_rd_regs = EfuseDefineRegisters.DR_REG_EFUSE_BASE __base_wr_regs = EfuseDefineRegisters.EFUSE_PGM_DATA0_REG # List of efuse blocks + # fmt: off BLOCKS = [ # Name, Alias, Index, Read address, Write address, Write protect bit, Read protect bit, Len, key_purpose ("BLOCK0", [], 0, __base_rd_regs + 0x02C, __base_wr_regs, None, None, 6, None), @@ -128,6 +135,7 @@ class EfuseDefineBlocks(EfuseBlocksBase): ("BLOCK_KEY5", ["BLOCK9"], 9, __base_rd_regs + 0x13C, __base_wr_regs, 28, 5, 8, "KEY_PURPOSE_5"), ("BLOCK_SYS_DATA2", ["BLOCK10"], 10, __base_rd_regs + 0x15C, __base_wr_regs, 29, 6, 8, None), ] + # fmt: on def get_burn_block_data_names(self): list_of_names = [] @@ -142,167 +150,59 @@ def get_burn_block_data_names(self): class EfuseDefineFields(EfuseFieldsBase): - - # List of efuse fields from TRM the chapter eFuse Controller. - EFUSES = [ - # - # Table 51: Parameters in BLOCK0 - # Name Category Block Word Pos Type:len WR_DIS RD_DIS Class Description Dictionary - ("WR_DIS", "efuse", 0, 0, 0, "uint:32", None, None, None, "Disables programming of individual eFuses", None), - ("RD_DIS", "efuse", 0, 1, 0, "uint:7", 0, None, None, "Disables software reading from BLOCK4-10", None), - ("DIS_RTC_RAM_BOOT", "config", 0, 1, 7, "bool", 1, None, None, "Disables boot from RTC RAM", None), - ("DIS_ICACHE", "config", 0, 1, 8, "bool", 2, None, None, "Disables ICache", None), - ("DIS_DCACHE", "config", 0, 1, 9, "bool", 2, None, None, "Disables DCache", None), - ("DIS_DOWNLOAD_ICACHE", "config", 0, 1, 10, "bool", 2, None, None, "Disables Icache when SoC is in Download mode", None), - ("DIS_DOWNLOAD_DCACHE", "config", 0, 1, 11, "bool", 2, None, None, "Disables Dcache when SoC is in Download mode", None), - ("DIS_FORCE_DOWNLOAD", "config", 0, 1, 12, "bool", 2, None, None, "Disables forcing chip into Download mode", None), - ("DIS_USB", "usb config", 0, 1, 13, "bool", 2, None, None, "Disables the USB OTG hardware", None), - ("DIS_CAN", "config", 0, 1, 14, "bool", 2, None, None, "Disables the TWAI Controller hardware", None), - ("DIS_BOOT_REMAP", "config", 0, 1, 15, "bool", 2, None, None, "Disables capability to Remap RAM to ROM address space", - None), - ("SOFT_DIS_JTAG", "security", 0, 1, 17, "bool", 2, None, None, "Software disables JTAG. When software disabled, " - "JTAG can be activated temporarily by HMAC peripheral", - None), - ("HARD_DIS_JTAG", "security", 0, 1, 18, "bool", 2, None, None, "Hardware disables JTAG permanently", None), - ("DIS_DOWNLOAD_MANUAL_ENCRYPT", "security", 0, 1, 19, "bool", 2, None, None, "Disables flash encryption when in download boot modes", - None), - ("USB_EXCHG_PINS", "usb config", 0, 1, 24, "bool", 30, None, None, "Exchanges USB D+ and D- pins", None), - ("EXT_PHY_ENABLE", "usb config", 0, 1, 25, "bool", 30, None, None, "Enables external USB PHY", None), - ("USB_FORCE_NOPERSIST", "usb config", 0, 1, 26, "bool", 30, None, None, "Forces to set USB BVALID to 1", None), - ("BLOCK0_VERSION", "identity", 0, 1, 27, "uint:2", 30, None, None, "BLOCK0 efuse version", None), - ("VDD_SPI_FORCE", "VDD_SPI config", 0, 2, 6, "bool", 3, None, None, "Force using VDD_SPI_XPD and VDD_SPI_TIEH " - "to configure VDD_SPI LDO", None), - ("VDD_SPI_XPD", "VDD_SPI config", 0, 2, 4, "bool", 3, None, None, "The VDD_SPI regulator is powered on", None), - ("VDD_SPI_TIEH", "VDD_SPI config", 0, 2, 5, "bool", 3, None, None, "The VDD_SPI power supply voltage at reset", - {0: "Connect to 1.8V LDO", - 1: "Connect to VDD3P3_RTC_IO"}), - ("WDT_DELAY_SEL", "WDT config", 0, 2, 16, "uint:2", 3, None, None, "Selects RTC WDT timeout threshold at startup", None), - ("SPI_BOOT_CRYPT_CNT", "security", 0, 2, 18, "uint:3", 4, None, "bitcount", "Enables encryption and decryption, when an SPI boot " - "mode is set. Enabled when 1 or 3 bits are set," - "disabled otherwise", - - {0: "Disable", - 1: "Enable", - 3: "Disable", - 7: "Enable"}), - ("SECURE_BOOT_KEY_REVOKE0", "security", 0, 2, 21, "bool", 5, None, None, "If set, revokes use of secure boot key digest 0", None), - ("SECURE_BOOT_KEY_REVOKE1", "security", 0, 2, 22, "bool", 6, None, None, "If set, revokes use of secure boot key digest 1", None), - ("SECURE_BOOT_KEY_REVOKE2", "security", 0, 2, 23, "bool", 7, None, None, "If set, revokes use of secure boot key digest 2", None), - ("KEY_PURPOSE_0", "security", 0, 2, 24, "uint:4", 8, None, "keypurpose", "KEY0 purpose", None), - ("KEY_PURPOSE_1", "security", 0, 2, 28, "uint:4", 9, None, "keypurpose", "KEY1 purpose", None), - ("KEY_PURPOSE_2", "security", 0, 3, 0, "uint:4", 10, None, "keypurpose", "KEY2 purpose", None), - ("KEY_PURPOSE_3", "security", 0, 3, 4, "uint:4", 11, None, "keypurpose", "KEY3 purpose", None), - ("KEY_PURPOSE_4", "security", 0, 3, 8, "uint:4", 12, None, "keypurpose", "KEY4 purpose", None), - ("KEY_PURPOSE_5", "security", 0, 3, 12, "uint:4", 13, None, "keypurpose", "KEY5 purpose", None), - ("SECURE_BOOT_EN", "security", 0, 3, 20, "bool", 15, None, None, "Enables secure boot", None), - ("SECURE_BOOT_AGGRESSIVE_REVOKE", "security", 0, 3, 21, "bool", 16, None, None, "Enables aggressive secure boot key revocation mode", - None), - ("FLASH_TPUW", "config", 0, 3, 28, "uint:4", 18, None, None, "Configures flash startup delay after SoC power-up, " - "unit is (ms/2). When the value is 15, delay is 7.5 ms", - None), - ("DIS_DOWNLOAD_MODE", "security", 0, 4, 0, "bool", 18, None, None, "Disables all Download boot modes", None), - ("DIS_LEGACY_SPI_BOOT", "config", 0, 4, 1, "bool", 18, None, None, "Disables Legacy SPI boot mode", None), - ("UART_PRINT_CHANNEL", "config", 0, 4, 2, "bool", 18, None, None, "Selects the default UART for printing boot msg", - - {0: "UART0", - 1: "UART1"}), - ("DIS_USB_DOWNLOAD_MODE", "config", 0, 4, 4, "bool", 18, None, None, "Disables use of USB in UART download boot mode", None), - ("ENABLE_SECURITY_DOWNLOAD", "security", 0, 4, 5, "bool", 18, None, None, "Enables secure UART download mode " - "(read/write flash only)", None), - ("UART_PRINT_CONTROL", "config", 0, 4, 6, "uint:2", 18, None, None, "Sets the default UART boot message output mode", - - {0: "Enabled", - 1: "Enable when GPIO 46 is low at reset", - 2: "Enable when GPIO 46 is high at rest", - 3: "Disabled"}), - ("PIN_POWER_SELECTION", "VDD_SPI config", 0, 4, 8, "bool", 18, None, None, "Sets default power supply for GPIO33..37, " - "set when SPI flash is initialized", - - {0: "VDD3P3_CPU", - 1: "VDD_SPI"}), - ("FLASH_TYPE", "config", 0, 4, 9, "bool", 18, None, None, "Selects SPI flash type", - - {0: "4 data lines", - 1: "8 data lines"}), - ("FORCE_SEND_RESUME", "config", 0, 4, 10, "bool", 18, None, None, "Forces ROM code to send an SPI flash resume command " - "during SPI boot", None), - ("SECURE_VERSION", "identity", 0, 4, 11, "uint:16", 18, None, "bitcount", "Secure version (used by ESP-IDF anti-rollback feature)", - None), - ("DISABLE_WAFER_VERSION_MAJOR", "config", 0, 5, 0, "bool", 19, None, None, "Disables check of wafer version major", None), - ("DISABLE_BLK_VERSION_MAJOR", "config", 0, 5, 1, "bool", 19, None, None, "Disables check of blk version major", None), - # - # Table 53: Parameters in BLOCK1-10 - # Name Category Block Word Pos Type:len WR_DIS RD_DIS Class Description Dictionary - ("MAC", "identity", 1, 0, 0, "bytes:6", 20, None, "mac", "Factory MAC Address", None), - ("SPI_PAD_CONFIG_CLK", "spi_pad_config", 1, 1, 16, "uint:6", 20, None, None, "SPI CLK pad", None), - ("SPI_PAD_CONFIG_Q", "spi_pad_config", 1, 1, 22, "uint:6", 20, None, None, "SPI Q (D1) pad", None), - ("SPI_PAD_CONFIG_D", "spi_pad_config", 1, 1, 28, "uint:6", 20, None, None, "SPI D (D0) pad", None), - ("SPI_PAD_CONFIG_CS", "spi_pad_config", 1, 2, 2, "uint:6", 20, None, None, "SPI CS pad", None), - ("SPI_PAD_CONFIG_HD", "spi_pad_config", 1, 2, 8, "uint:6", 20, None, None, "SPI HD (D3) pad", None), - ("SPI_PAD_CONFIG_WP", "spi_pad_config", 1, 2, 14, "uint:6", 20, None, None, "SPI WP (D2) pad", None), - ("SPI_PAD_CONFIG_DQS", "spi_pad_config", 1, 2, 20, "uint:6", 20, None, None, "SPI DQS pad", None), - ("SPI_PAD_CONFIG_D4", "spi_pad_config", 1, 2, 26, "uint:6", 20, None, None, "SPI D4 pad", None), - ("SPI_PAD_CONFIG_D5", "spi_pad_config", 1, 3, 0, "uint:6", 20, None, None, "SPI D5 pad", None), - ("SPI_PAD_CONFIG_D6", "spi_pad_config", 1, 3, 6, "uint:6", 20, None, None, "SPI D6 pad", None), - ("SPI_PAD_CONFIG_D7", "spi_pad_config", 1, 3, 12, "uint:6", 20, None, None, "SPI D7 pad", None), - - ("WAFER_VERSION_MAJOR", "identity", 1, 3, 18, "uint:2", 20, None, None, "WAFER_VERSION_MAJOR", None), - ("WAFER_VERSION_MINOR_HI", "identity", 1, 3, 20, "uint:1", 20, None, None, "WAFER_VERSION_MINOR most significant bits", None), - ("FLASH_VERSION", "identity", 1, 3, 21, "uint:4", 20, None, None, "Flash version", - {0: "No Embedded Flash", - 1: "Embedded Flash 2MB", - 2: "Embedded Flash 4MB"}), - ("BLK_VERSION_MAJOR", "identity", 1, 3, 25, "uint:2", 20, None, None, "BLOCK version major", None), - ("PSRAM_VERSION", "identity", 1, 3, 28, "uint:4", 20, None, None, "PSRAM version", - {0: "No Embedded PSRAM", - 1: "Embedded PSRAM 2MB", - 2: "Embedded PSRAM 4MB"}), - ("PKG_VERSION", "identity", 1, 4, 0, "uint:4", 20, None, None, "Package version", None), - ("WAFER_VERSION_MINOR_LO", "identity", 1, 4, 4, "uint:3", 20, None, None, "WAFER_VERSION_MINOR least significant bits", None), - - ('OPTIONAL_UNIQUE_ID', "identity", 2, 0, 0, "bytes:16", 21, None, "keyblock", "Optional unique 128-bit ID", None), - ("BLK_VERSION_MINOR", "identity", 2, 4, 4, "uint:3", 21, None, None, "BLOCK version minor", - {0: "No calibration", - 1: "With ADC calibration V1", - 2: "With ADC calibration V2"}), - ("CUSTOM_MAC", "identity", 3, 6, 8, "bytes:6", 22, None, "mac", "Custom MAC Address", None), - ] - - KEYBLOCKS = [ - # Name Category Block Word Pos Type:len WR_DIS RD_DIS Class Description Dictionary - ('BLOCK_USR_DATA', "config", 3, 0, 0, "bytes:32", 22, None, None, "User data", None), - ('BLOCK_KEY0', "security", 4, 0, 0, "bytes:32", 23, 0, "keyblock", "Encryption key0 or user data", None), - ('BLOCK_KEY1', "security", 5, 0, 0, "bytes:32", 24, 1, "keyblock", "Encryption key1 or user data", None), - ('BLOCK_KEY2', "security", 6, 0, 0, "bytes:32", 25, 2, "keyblock", "Encryption key2 or user data", None), - ('BLOCK_KEY3', "security", 7, 0, 0, "bytes:32", 26, 3, "keyblock", "Encryption key3 or user data", None), - ('BLOCK_KEY4', "security", 8, 0, 0, "bytes:32", 27, 4, "keyblock", "Encryption key4 or user data", None), - ('BLOCK_KEY5', "security", 9, 0, 0, "bytes:32", 28, 5, "keyblock", "Encryption key5 or user data", None), - ('BLOCK_SYS_DATA2', "security", 10, 0, 0, "bytes:32", 29, 6, None, "System data (part 2)", None), - ] - - # if BLK_VERSION_MINOR is 1, these efuse fields are in BLOCK2 - BLOCK2_CALIBRATION_EFUSES = [ - # Name Category Block Word Pos Type:len WR_DIS RD_DIS Class Description Dictionary - ('TEMP_SENSOR_CAL', "calibration", 2, 4, 7, "uint:9", 21, None, "t_sensor", "Temperature calibration", None), - ('ADC1_MODE0_D2', "calibration", 2, 4, 16, "uint:8", 21, None, "adc_tp", "ADC1 calibration 1", None), - ('ADC1_MODE1_D2', "calibration", 2, 4, 24, "uint:8", 21, None, "adc_tp", "ADC1 calibration 2", None), - ('ADC1_MODE2_D2', "calibration", 2, 5, 0, "uint:8", 21, None, "adc_tp", "ADC1 calibration 3", None), - ('ADC1_MODE3_D2', "calibration", 2, 5, 8, "uint:8", 21, None, "adc_tp", "ADC1 calibration 4", None), - ('ADC2_MODE0_D2', "calibration", 2, 5, 16, "uint:8", 21, None, "adc_tp", "ADC2 calibration 5", None), - ('ADC2_MODE1_D2', "calibration", 2, 5, 24, "uint:8", 21, None, "adc_tp", "ADC2 calibration 6", None), - ('ADC2_MODE2_D2', "calibration", 2, 6, 0, "uint:8", 21, None, "adc_tp", "ADC2 calibration 7", None), - ('ADC2_MODE3_D2', "calibration", 2, 6, 8, "uint:8", 21, None, "adc_tp", "ADC2 calibration 8", None), - ('ADC1_MODE0_D1', "calibration", 2, 6, 16, "uint:6", 21, None, "adc_tp", "ADC1 calibration 9", None), - ('ADC1_MODE1_D1', "calibration", 2, 6, 22, "uint:6", 21, None, "adc_tp", "ADC1 calibration 10", None), - ('ADC1_MODE2_D1', "calibration", 2, 6, 28, "uint:6", 21, None, "adc_tp", "ADC1 calibration 11", None), - ('ADC1_MODE3_D1', "calibration", 2, 7, 2, "uint:6", 21, None, "adc_tp", "ADC1 calibration 12", None), - ('ADC2_MODE0_D1', "calibration", 2, 7, 8, "uint:6", 21, None, "adc_tp", "ADC2 calibration 13", None), - ('ADC2_MODE1_D1', "calibration", 2, 7, 14, "uint:6", 21, None, "adc_tp", "ADC2 calibration 14", None), - ('ADC2_MODE2_D1', "calibration", 2, 7, 20, "uint:6", 21, None, "adc_tp", "ADC2 calibration 15", None), - ('ADC2_MODE3_D1', "calibration", 2, 7, 26, "uint:6", 21, None, "adc_tp", "ADC2 calibration 16", None), - ] - - CALC = [ - ("WAFER_VERSION_MINOR", "identity", 0, None, None, "uint:4", None, None, "wafer", "calc WAFER VERSION MINOR = WAFER_VERSION_MINOR_HI << 3 + WAFER_VERSION_MINOR_LO (read only)", None), - ] -# fmt: on + def __init__(self) -> None: + # List of efuse fields from TRM the chapter eFuse Controller. + self.EFUSES = [] + + self.KEYBLOCKS = [] + + # if BLK_VERSION_MINOR is 1, these efuse fields are in BLOCK2 + self.BLOCK2_CALIBRATION_EFUSES = [] + + self.CALC = [] + + dir_name = os.path.dirname(os.path.abspath(__file__)) + dir_name, file_name = os.path.split(dir_name) + file_name = file_name + ".yaml" + dir_name, _ = os.path.split(dir_name) + efuse_file = os.path.join(dir_name, "efuse_defs", file_name) + with open(f"{efuse_file}", "r") as r_file: + e_desc = yaml.safe_load(r_file) + super().__init__(e_desc) + + for i, efuse in enumerate(self.ALL_EFUSES): + if efuse.name in [ + "BLOCK_USR_DATA", + "BLOCK_KEY0", + "BLOCK_KEY1", + "BLOCK_KEY2", + "BLOCK_KEY3", + "BLOCK_KEY4", + "BLOCK_KEY5", + "BLOCK_SYS_DATA2", + ]: + if efuse.name == "BLOCK_USR_DATA": + efuse.bit_len = 256 + efuse.type = "bytes:32" + self.KEYBLOCKS.append(efuse) + self.ALL_EFUSES[i] = None + + elif efuse.category == "calibration": + self.BLOCK2_CALIBRATION_EFUSES.append(efuse) + self.ALL_EFUSES[i] = None + + f = Field() + f.name = "WAFER_VERSION_MINOR" + f.block = 0 + f.bit_len = 4 + f.type = f"uint:{f.bit_len}" + f.category = "identity" + f.class_type = "wafer" + f.description = "calc WAFER VERSION MINOR = WAFER_VERSION_MINOR_HI << 3 + WAFER_VERSION_MINOR_LO (read only)" + self.CALC.append(f) + + for efuse in self.ALL_EFUSES: + if efuse is not None: + self.EFUSES.append(efuse) + + self.ALL_EFUSES = [] diff --git a/espefuse/efuse/esp32s2/operations.py b/espefuse/efuse/esp32s2/operations.py index 26cb23007..5ccfac3c9 100644 --- a/espefuse/efuse/esp32s2/operations.py +++ b/espefuse/efuse/esp32s2/operations.py @@ -18,6 +18,7 @@ from ..base_operations import ( add_common_commands, add_force_write_always, + add_show_sensitive_info_option, burn_bit, burn_block_data, burn_efuse, @@ -56,6 +57,7 @@ def add_commands(subparsers, efuses): ) protect_options(burn_key) add_force_write_always(burn_key) + add_show_sensitive_info_option(burn_key) burn_key.add_argument( "block", help="Key block to burn", @@ -106,6 +108,7 @@ def add_commands(subparsers, efuses): ) protect_options(burn_key_digest) add_force_write_always(burn_key_digest) + add_show_sensitive_info_option(burn_key_digest) burn_key_digest.add_argument( "block", help="Key block to burn", @@ -385,7 +388,13 @@ def burn_key(esp, efuses, args, digest=None): if efuses[block.key_purpose_name].need_reverse(keypurpose): revers_msg = "\tReversing byte order for AES-XTS hardware peripheral" data = data[::-1] - print("-> [%s]" % (util.hexify(data, " "))) + print( + "-> [{}]".format( + util.hexify(data, " ") + if args.show_sensitive_info + else " ".join(["??"] * len(data)) + ) + ) if revers_msg: print(revers_msg) if len(data) != num_bytes: diff --git a/espefuse/efuse/esp32s3/emulate_efuse_controller.py b/espefuse/efuse/esp32s3/emulate_efuse_controller.py index 69e8bafac..7e767b954 100644 --- a/espefuse/efuse/esp32s3/emulate_efuse_controller.py +++ b/espefuse/efuse/esp32s3/emulate_efuse_controller.py @@ -16,13 +16,13 @@ class EmulateEfuseController(EmulateEfuseControllerBase): CHIP_NAME = "ESP32-S3" mem = None debug = False - Blocks = EfuseDefineBlocks - Fields = EfuseDefineFields - REGS = EfuseDefineRegisters def __init__(self, efuse_file=None, debug=False): + self.Blocks = EfuseDefineBlocks + self.Fields = EfuseDefineFields() + self.REGS = EfuseDefineRegisters super(EmulateEfuseController, self).__init__(efuse_file, debug) - self.write_reg(self.REGS.EFUSE_STATUS_REG, 1) + self.write_reg(self.REGS.EFUSE_CMD_REG, 0) """ esptool method start >>""" @@ -53,10 +53,10 @@ def handle_writing_event(self, addr, value): self.clean_blocks_wr_regs() self.check_rd_protection_area() self.write_reg(addr, 0) - self.write_reg(self.REGS.EFUSE_STATUS_REG, 1) + self.write_reg(self.REGS.EFUSE_CMD_REG, 0) elif value == self.REGS.EFUSE_READ_CMD: self.write_reg(addr, 0) - self.write_reg(self.REGS.EFUSE_STATUS_REG, 1) + self.write_reg(self.REGS.EFUSE_CMD_REG, 0) self.save_to_file() def get_bitlen_of_block(self, blk, wr=False): diff --git a/espefuse/efuse/esp32s3/fields.py b/espefuse/efuse/esp32s3/fields.py index a96f0cc07..604c4a45c 100644 --- a/espefuse/efuse/esp32s3/fields.py +++ b/espefuse/efuse/esp32s3/fields.py @@ -54,16 +54,15 @@ class EspEfuses(base_fields.EspEfusesBase): Wrapper object to manage the efuse fields in a connected ESP bootloader """ - Blocks = EfuseDefineBlocks() - Fields = EfuseDefineFields() - REGS = EfuseDefineRegisters - BURN_BLOCK_DATA_NAMES = Blocks.get_burn_block_data_names() - BLOCKS_FOR_KEYS = Blocks.get_blocks_for_keys() - debug = False do_not_confirm = False def __init__(self, esp, skip_connect=False, debug=False, do_not_confirm=False): + self.Blocks = EfuseDefineBlocks() + self.Fields = EfuseDefineFields() + self.REGS = EfuseDefineRegisters + self.BURN_BLOCK_DATA_NAMES = self.Blocks.get_burn_block_data_names() + self.BLOCKS_FOR_KEYS = self.Blocks.get_blocks_for_keys() self._esp = esp self.debug = debug self.do_not_confirm = do_not_confirm @@ -85,59 +84,43 @@ def __init__(self, esp, skip_connect=False, debug=False, do_not_confirm=False): ] if not skip_connect: self.get_coding_scheme_warnings() - self.efuses = [ - EfuseField.from_tuple( - self, self.Fields.get(efuse), self.Fields.get(efuse).class_type - ) - for efuse in self.Fields.EFUSES - ] + self.efuses = [EfuseField.convert(self, efuse) for efuse in self.Fields.EFUSES] self.efuses += [ - EfuseField.from_tuple( - self, self.Fields.get(efuse), self.Fields.get(efuse).class_type - ) - for efuse in self.Fields.KEYBLOCKS + EfuseField.convert(self, efuse) for efuse in self.Fields.KEYBLOCKS ] if skip_connect: self.efuses += [ - EfuseField.from_tuple( - self, self.Fields.get(efuse), self.Fields.get(efuse).class_type - ) + EfuseField.convert(self, efuse) for efuse in self.Fields.BLOCK2_CALIBRATION_EFUSES ] else: if self["BLK_VERSION_MAJOR"].get() == 1: self.efuses += [ - EfuseField.from_tuple( - self, self.Fields.get(efuse), self.Fields.get(efuse).class_type - ) + EfuseField.convert(self, efuse) for efuse in self.Fields.BLOCK2_CALIBRATION_EFUSES ] self.efuses += [ - EfuseField.from_tuple( - self, self.Fields.get(efuse), self.Fields.get(efuse).class_type - ) - for efuse in self.Fields.CALC + EfuseField.convert(self, efuse) for efuse in self.Fields.CALC ] def __getitem__(self, efuse_name): """Return the efuse field with the given name""" for e in self.efuses: - if efuse_name == e.name: + if efuse_name == e.name or any(x == efuse_name for x in e.alt_names): return e new_fields = False for efuse in self.Fields.BLOCK2_CALIBRATION_EFUSES: - e = self.Fields.get(efuse) - if e.name == efuse_name: + if efuse.name == efuse_name or any( + x == efuse_name for x in efuse.alt_names + ): self.efuses += [ - EfuseField.from_tuple( - self, self.Fields.get(efuse), self.Fields.get(efuse).class_type - ) + EfuseField.convert(self, efuse) for efuse in self.Fields.BLOCK2_CALIBRATION_EFUSES ] new_fields = True if new_fields: for e in self.efuses: - if efuse_name == e.name: + if efuse_name == e.name or any(x == efuse_name for x in e.alt_names): return e raise KeyError @@ -158,10 +141,6 @@ def print_status_regs(self): ) ) - def get_block_errors(self, block_num): - """Returns (error count, failure boolean flag)""" - return self.blocks[block_num].num_errors, self.blocks[block_num].fail - def efuse_controller_setup(self): self.set_efuse_timing() self.clear_pgm_registers() @@ -181,9 +160,13 @@ def clear_pgm_registers(self): def wait_efuse_idle(self): deadline = time.time() + self.REGS.EFUSE_BURN_TIMEOUT while time.time() < deadline: - # if self.read_reg(self.EFUSE_CMD_REG) == 0: - if self.read_reg(self.REGS.EFUSE_STATUS_REG) & 0x7 == 1: - return + cmds = self.REGS.EFUSE_PGM_CMD | self.REGS.EFUSE_READ_CMD + if self.read_reg(self.REGS.EFUSE_CMD_REG) & cmds == 0: + if self.read_reg(self.REGS.EFUSE_CMD_REG) & cmds == 0: + # Due to a hardware error, we have to read READ_CMD again + # to make sure the efuse clock is normal. + # For PGM_CMD it is not necessary. + return raise esptool.FatalError( "Timed out waiting for Efuse controller command to complete" ) @@ -249,6 +232,13 @@ def set_efuse_timing(self): "The eFuse supports only xtal=40M (xtal was %d)" % apb_freq ) + self.update_reg(self.REGS.EFUSE_DAC_CONF_REG, self.REGS.EFUSE_DAC_NUM_M, 0xFF) + self.update_reg( + self.REGS.EFUSE_DAC_CONF_REG, self.REGS.EFUSE_DAC_CLK_DIV_M, 0x28 + ) + self.update_reg( + self.REGS.EFUSE_WR_TIM_CONF1_REG, self.REGS.EFUSE_PWR_ON_NUM_M, 0x3000 + ) self.update_reg( self.REGS.EFUSE_WR_TIM_CONF2_REG, self.REGS.EFUSE_PWR_OFF_NUM_M, 0x190 ) @@ -264,12 +254,9 @@ def get_coding_scheme_warnings(self, silent=False): self.read_reg(self.REGS.EFUSE_RD_REPEAT_ERR0_REG + offs * 4) for offs in range(5) ] - data = BitArray() + block.err_bitarray.pos = 0 for word in reversed(words): - data.append("uint:32=%d" % word) - # pos=32 because EFUSE_WR_DIS goes first it is 32bit long - # and not under error control - block.err_bitarray.overwrite(data, pos=32) + block.err_bitarray.overwrite(BitArray("uint:32=%d" % word)) block.num_errors = block.err_bitarray.count(True) block.fail = block.num_errors != 0 else: @@ -296,9 +283,10 @@ def get_coding_scheme_warnings(self, silent=False): def summary(self): if self["VDD_SPI_FORCE"].get() == 0: output = "Flash voltage (VDD_SPI) determined by GPIO45 on reset " - "(GPIO45=High: VDD_SPI pin is powered from internal 1.8V LDO\n" + output += "(GPIO45=High: VDD_SPI pin is powered from internal 1.8V LDO\n" output += "GPIO45=Low or NC: VDD_SPI pin is powered directly from " - "VDD3P3_RTC_IO via resistor Rspi. Typically this voltage is 3.3 V)." + output += "VDD3P3_RTC_IO via resistor Rspi. " + output += "Typically this voltage is 3.3 V)." elif self["VDD_SPI_XPD"].get() == 0: output = "Flash voltage (VDD_SPI) internal regulator disabled by efuse." elif self["VDD_SPI_TIEH"].get() == 0: @@ -310,35 +298,22 @@ def summary(self): class EfuseField(base_fields.EfuseFieldBase): @staticmethod - def from_tuple(parent, efuse_tuple, type_class): + def convert(parent, efuse): return { "mac": EfuseMacField, "keypurpose": EfuseKeyPurposeField, "t_sensor": EfuseTempSensor, "adc_tp": EfuseAdcPointCalibration, "wafer": EfuseWafer, - }.get(type_class, EfuseField)(parent, efuse_tuple) - - def get_info(self): - output = "%s (BLOCK%d)" % (self.name, self.block) - errs, fail = self.parent.get_block_errors(self.block) - if errs != 0 or fail: - output += ( - "[FAIL:%d]" % (fail) - if self.block == 0 - else "[ERRS:%d FAIL:%d]" % (errs, fail) - ) - if self.efuse_class == "keyblock": - name = self.parent.blocks[self.block].key_purpose_name - if name is not None: - output += "\n Purpose: %s\n " % (self.parent[name].get()) - return output + }.get(efuse.class_type, EfuseField)(parent, efuse) class EfuseWafer(EfuseField): def get(self, from_read=True): hi_bits = self.parent["WAFER_VERSION_MINOR_HI"].get(from_read) + assert self.parent["WAFER_VERSION_MINOR_HI"].bit_len == 1 lo_bits = self.parent["WAFER_VERSION_MINOR_LO"].get(from_read) + assert self.parent["WAFER_VERSION_MINOR_LO"].bit_len == 3 return (hi_bits << 3) + lo_bits def save(self, new_value): @@ -471,6 +446,14 @@ def get(self, from_read=True): return p[0] return "FORBIDDEN_STATE" + def get_name(self, raw_val): + for key in self.KEY_PURPOSES: + if key[1] == raw_val: + return key[0] + def save(self, new_value): raw_val = int(self.check_format(str(new_value))) + str_new_value = self.get_name(raw_val) + if self.name == "KEY_PURPOSE_5" and str_new_value.startswith("XTS_AES"): + raise esptool.FatalError(f"{self.name} can not have {str_new_value} key due to a hardware bug (please see TRM for more details)") return super(EfuseKeyPurposeField, self).save(raw_val) diff --git a/espefuse/efuse/esp32s3/mem_definition.py b/espefuse/efuse/esp32s3/mem_definition.py index b4e19a76c..54c88712c 100644 --- a/espefuse/efuse/esp32s3/mem_definition.py +++ b/espefuse/efuse/esp32s3/mem_definition.py @@ -4,25 +4,32 @@ # # SPDX-License-Identifier: GPL-2.0-or-later -from ..mem_definition_base import EfuseBlocksBase, EfuseFieldsBase, EfuseRegistersBase +import os +import yaml + +from ..mem_definition_base import ( + EfuseBlocksBase, + EfuseFieldsBase, + EfuseRegistersBase, + Field, +) -# fmt: off -class EfuseDefineRegisters(EfuseRegistersBase): +class EfuseDefineRegisters(EfuseRegistersBase): EFUSE_ADDR_MASK = 0x00000FFF - EFUSE_MEM_SIZE = (0x01FC + 4) + EFUSE_MEM_SIZE = 0x01FC + 4 # EFUSE registers & command/conf values - DR_REG_EFUSE_BASE = 0x60007000 - EFUSE_PGM_DATA0_REG = DR_REG_EFUSE_BASE - EFUSE_CHECK_VALUE0_REG = DR_REG_EFUSE_BASE + 0x020 - EFUSE_CLK_REG = DR_REG_EFUSE_BASE + 0x1C8 - EFUSE_CONF_REG = DR_REG_EFUSE_BASE + 0x1CC - EFUSE_STATUS_REG = DR_REG_EFUSE_BASE + 0x1D0 - EFUSE_CMD_REG = DR_REG_EFUSE_BASE + 0x1D4 - EFUSE_RD_RS_ERR0_REG = DR_REG_EFUSE_BASE + 0x1C0 - EFUSE_RD_RS_ERR1_REG = DR_REG_EFUSE_BASE + 0x1C4 + DR_REG_EFUSE_BASE = 0x60007000 + EFUSE_PGM_DATA0_REG = DR_REG_EFUSE_BASE + EFUSE_CHECK_VALUE0_REG = DR_REG_EFUSE_BASE + 0x020 + EFUSE_CLK_REG = DR_REG_EFUSE_BASE + 0x1C8 + EFUSE_CONF_REG = DR_REG_EFUSE_BASE + 0x1CC + EFUSE_STATUS_REG = DR_REG_EFUSE_BASE + 0x1D0 + EFUSE_CMD_REG = DR_REG_EFUSE_BASE + 0x1D4 + EFUSE_RD_RS_ERR0_REG = DR_REG_EFUSE_BASE + 0x1C0 + EFUSE_RD_RS_ERR1_REG = DR_REG_EFUSE_BASE + 0x1C4 EFUSE_RD_REPEAT_ERR0_REG = DR_REG_EFUSE_BASE + 0x17C EFUSE_RD_REPEAT_ERR1_REG = DR_REG_EFUSE_BASE + 0x180 EFUSE_RD_REPEAT_ERR2_REG = DR_REG_EFUSE_BASE + 0x184 @@ -33,37 +40,49 @@ class EfuseDefineRegisters(EfuseRegistersBase): EFUSE_WR_TIM_CONF1_REG = DR_REG_EFUSE_BASE + 0x1F4 EFUSE_WR_TIM_CONF2_REG = DR_REG_EFUSE_BASE + 0x1F8 EFUSE_DATE_REG = DR_REG_EFUSE_BASE + 0x1FC - EFUSE_WRITE_OP_CODE = 0x5A5A - EFUSE_READ_OP_CODE = 0x5AA5 - EFUSE_PGM_CMD_MASK = 0x3 - EFUSE_PGM_CMD = 0x2 - EFUSE_READ_CMD = 0x1 + EFUSE_WRITE_OP_CODE = 0x5A5A + EFUSE_READ_OP_CODE = 0x5AA5 + EFUSE_PGM_CMD_MASK = 0x3 + EFUSE_PGM_CMD = 0x2 + EFUSE_READ_CMD = 0x1 BLOCK_ERRORS = [ # error_reg, err_num_mask, err_num_offs, fail_bit - (EFUSE_RD_REPEAT_ERR0_REG, None, None, None), # BLOCK0 - (EFUSE_RD_RS_ERR0_REG, 0x7, 0, 3), # MAC_SPI_8M_0 - (EFUSE_RD_RS_ERR0_REG, 0x7, 4, 7), # BLOCK_SYS_DATA - (EFUSE_RD_RS_ERR0_REG, 0x7, 8, 11), # BLOCK_USR_DATA - (EFUSE_RD_RS_ERR0_REG, 0x7, 12, 15), # BLOCK_KEY0 - (EFUSE_RD_RS_ERR0_REG, 0x7, 16, 19), # BLOCK_KEY1 - (EFUSE_RD_RS_ERR0_REG, 0x7, 20, 23), # BLOCK_KEY2 - (EFUSE_RD_RS_ERR0_REG, 0x7, 24, 27), # BLOCK_KEY3 - (EFUSE_RD_RS_ERR0_REG, 0x7, 28, 31), # BLOCK_KEY4 - (EFUSE_RD_RS_ERR1_REG, 0x7, 0, 3), # BLOCK_KEY5 - (EFUSE_RD_RS_ERR1_REG, 0x7, 4, 7), # BLOCK_SYS_DATA2 + (EFUSE_RD_REPEAT_ERR0_REG, None, None, None), # BLOCK0 + (EFUSE_RD_RS_ERR0_REG, 0x7, 0, 3), # MAC_SPI_8M_0 + (EFUSE_RD_RS_ERR0_REG, 0x7, 4, 7), # BLOCK_SYS_DATA + (EFUSE_RD_RS_ERR0_REG, 0x7, 8, 11), # BLOCK_USR_DATA + (EFUSE_RD_RS_ERR0_REG, 0x7, 12, 15), # BLOCK_KEY0 + (EFUSE_RD_RS_ERR0_REG, 0x7, 16, 19), # BLOCK_KEY1 + (EFUSE_RD_RS_ERR0_REG, 0x7, 20, 23), # BLOCK_KEY2 + (EFUSE_RD_RS_ERR0_REG, 0x7, 24, 27), # BLOCK_KEY3 + (EFUSE_RD_RS_ERR0_REG, 0x7, 28, 31), # BLOCK_KEY4 + (EFUSE_RD_RS_ERR1_REG, 0x7, 0, 3), # BLOCK_KEY5 + (EFUSE_RD_RS_ERR1_REG, 0x7, 4, 7), # BLOCK_SYS_DATA2 ] # EFUSE_WR_TIM_CONF2_REG EFUSE_PWR_OFF_NUM_S = 0 EFUSE_PWR_OFF_NUM_M = 0xFFFF << EFUSE_PWR_OFF_NUM_S + # EFUSE_WR_TIM_CONF1_REG + EFUSE_PWR_ON_NUM_S = 8 + EFUSE_PWR_ON_NUM_M = 0x0000FFFF << EFUSE_PWR_ON_NUM_S -class EfuseDefineBlocks(EfuseBlocksBase): + # EFUSE_DAC_CONF_REG + EFUSE_DAC_CLK_DIV_S = 0 + EFUSE_DAC_CLK_DIV_M = 0xFF << EFUSE_DAC_CLK_DIV_S + # EFUSE_DAC_CONF_REG + EFUSE_DAC_NUM_S = 9 + EFUSE_DAC_NUM_M = 0xFF << EFUSE_DAC_NUM_S + + +class EfuseDefineBlocks(EfuseBlocksBase): __base_rd_regs = EfuseDefineRegisters.DR_REG_EFUSE_BASE __base_wr_regs = EfuseDefineRegisters.EFUSE_PGM_DATA0_REG # List of efuse blocks + # fmt: off BLOCKS = [ # Name, Alias, Index, Read address, Write address, Write protect bit, Read protect bit, Len, key_purpose ("BLOCK0", [], 0, __base_rd_regs + 0x02C, __base_wr_regs, None, None, 6, None), @@ -78,6 +97,7 @@ class EfuseDefineBlocks(EfuseBlocksBase): ("BLOCK_KEY5", ["BLOCK9"], 9, __base_rd_regs + 0x13C, __base_wr_regs, 28, 5, 8, "KEY_PURPOSE_5"), ("BLOCK_SYS_DATA2", ["BLOCK10"], 10, __base_rd_regs + 0x15C, __base_wr_regs, 29, 6, 8, None), ] + # fmt: on def get_burn_block_data_names(self): list_of_names = [] @@ -92,163 +112,59 @@ def get_burn_block_data_names(self): class EfuseDefineFields(EfuseFieldsBase): - - # List of efuse fields from TRM the chapter eFuse Controller. - EFUSES = [ - # - # Table 51: Parameters in BLOCK0 - # Name Category Block Word Pos Type:len WR_DIS RD_DIS Class Description Dictionary - ("WR_DIS", "efuse", 0, 0, 0, "uint:32", None, None, None, "Disables programming of individual eFuses", None), - ("RD_DIS", "efuse", 0, 1, 0, "uint:7", 0, None, None, "Disables software reading from BLOCK4-10", None), - ("DIS_ICACHE", "config", 0, 1, 8, "bool", 2, None, None, "Disables ICache", None), - ("DIS_DCACHE", "config", 0, 1, 9, "bool", 2, None, None, "Disables DCache", None), - ("DIS_DOWNLOAD_ICACHE", "config", 0, 1, 10, "bool", 2, None, None, "Disables Icache when SoC is in Download mode", None), - ("DIS_DOWNLOAD_DCACHE", "config", 0, 1, 11, "bool", 2, None, None, "Disables Dcache when SoC is in Download mode", None), - ("DIS_FORCE_DOWNLOAD", "config", 0, 1, 12, "bool", 2, None, None, "Disables forcing chip into Download mode", None), - ("DIS_USB", "usb config", 0, 1, 13, "bool", 2, None, None, "Disables the USB OTG hardware", None), - ("DIS_CAN", "config", 0, 1, 14, "bool", 2, None, None, "Disables the TWAI Controller hardware", None), - ("DIS_APP_CPU", "config", 0, 1, 15, "bool", 2, None, None, "Disables APP CPU", None), - ("SOFT_DIS_JTAG", "security", 0, 1, 16, "uint:3", 31, None, None, "Software disables JTAG by programming " - "odd number of 1 bit(s). " - "JTAG can be re-enabled via HMAC peripheral", - None), - ("HARD_DIS_JTAG", "security", 0, 1, 19, "bool", 2, None, None, "Hardware disables JTAG permanently", None), - - ("DIS_DOWNLOAD_MANUAL_ENCRYPT", "security", 0, 1, 20, "bool", 2, None, None, "Disables flash encryption when in download boot modes", - None), - ("USB_EXCHG_PINS", "usb config", 0, 1, 25, "bool", 30, None, None, "Exchanges USB D+ and D- pins", None), - ("EXT_PHY_ENABLE", "usb config", 0, 1, 26, "bool", 30, None, None, "Enables external USB PHY", None), - ("BTLC_GPIO_ENABLE", "usb config", 0, 1, 27, "uint:2", 30, None, None, "Enables BTLC GPIO", None), - ("VDD_SPI_XPD", "VDD_SPI config", 0, 2, 4, "bool", 3, None, None, "The VDD_SPI regulator is powered on", None), - ("VDD_SPI_TIEH", "VDD_SPI config", 0, 2, 5, "bool", 3, None, None, "The VDD_SPI power supply voltage at reset", - {0: "Connect to 1.8V LDO", - 1: "Connect to VDD_RTC_IO"}), - ("VDD_SPI_FORCE", "VDD_SPI config", 0, 2, 6, "bool", 3, None, None, "Force using VDD_SPI_XPD and VDD_SPI_TIEH " - "to configure VDD_SPI LDO", None), - ("WDT_DELAY_SEL", "WDT config", 0, 2, 16, "uint:2", 3, None, None, "Selects RTC WDT timeout threshold at startup", None), - ("SPI_BOOT_CRYPT_CNT", "security", 0, 2, 18, "uint:3", 4, None, "bitcount", "Enables encryption and decryption, when an SPI boot " - "mode is set. Enabled when 1 or 3 bits are set," - "disabled otherwise", - {0: "Disable", - 1: "Enable", - 3: "Disable", - 7: "Enable"}), - ("SECURE_BOOT_KEY_REVOKE0", "security", 0, 2, 21, "bool", 5, None, None, "Revokes use of secure boot key digest 0", None), - ("SECURE_BOOT_KEY_REVOKE1", "security", 0, 2, 22, "bool", 6, None, None, "Revokes use of secure boot key digest 1", None), - ("SECURE_BOOT_KEY_REVOKE2", "security", 0, 2, 23, "bool", 7, None, None, "Revokes use of secure boot key digest 2", None), - ("KEY_PURPOSE_0", "security", 0, 2, 24, "uint:4", 8, None, "keypurpose", "KEY0 purpose", None), - ("KEY_PURPOSE_1", "security", 0, 2, 28, "uint:4", 9, None, "keypurpose", "KEY1 purpose", None), - ("KEY_PURPOSE_2", "security", 0, 3, 0, "uint:4", 10, None, "keypurpose", "KEY2 purpose", None), - ("KEY_PURPOSE_3", "security", 0, 3, 4, "uint:4", 11, None, "keypurpose", "KEY3 purpose", None), - ("KEY_PURPOSE_4", "security", 0, 3, 8, "uint:4", 12, None, "keypurpose", "KEY4 purpose", None), - ("KEY_PURPOSE_5", "security", 0, 3, 12, "uint:4", 13, None, "keypurpose", "KEY5 purpose", None), - ("SECURE_BOOT_EN", "security", 0, 3, 20, "bool", 15, None, None, "Enables secure boot", None), - ("SECURE_BOOT_AGGRESSIVE_REVOKE", "security", 0, 3, 21, "bool", 16, None, None, "Enables aggressive secure boot key revocation mode", - None), - ("DIS_USB_JTAG", "usb config", 0, 3, 22, "bool", 2, None, None, "Disable usb_serial_jtag-to-jtag function", None), - ("DIS_USB_SERIAL_JTAG", "usb config", 0, 3, 23, "bool", 2, None, None, "Disable usb_serial_jtag module", None), - ("STRAP_JTAG_SEL", "security", 0, 3, 24, "bool", 2, None, None, "Enable selection between usb_to_jtag" - "or pad_to_jtag through GPIO3", None), - ("USB_PHY_SEL", "usb config", 0, 3, 25, "bool", 2, None, None, "Select internal/external PHY for USB OTG" - "and usb_serial_jtag", None), - ("FLASH_TPUW", "config", 0, 3, 28, "uint:4", 18, None, None, "Configures flash startup delay after SoC power-up, " - "unit is (ms/2). When the value is 15, delay is 7.5 ms", - None), - ("DIS_DOWNLOAD_MODE", "security", 0, 4, 0, "bool", 18, None, None, "Disables all Download boot modes", None), - ("DIS_DIRECT_BOOT", "config", 0, 4, 1, "bool", 18, None, None, "Disables direct boot mode", None), - ("DIS_USB_SERIAL_JTAG_ROM_PRINT", "config", 0, 4, 2, "bool", 18, None, None, "Disables USB-Serial-JTAG ROM printing", None), - ("FLASH_ECC_MODE", "config", 0, 4, 3, "bool", 18, None, None, "Configures the ECC mode for SPI flash", - {0: "16-byte to 18-byte mode", - 1: "16-byte to 17-byte mode"}), - ("DIS_USB_SERIAL_JTAG_DOWNLOAD_MODE", "config", 0, 4, 4, "bool", 18, None, None, "Disables USB-Serial-JTAG download feature in " - "UART download boot mode", None), - ("ENABLE_SECURITY_DOWNLOAD", "security", 0, 4, 5, "bool", 18, None, None, "Enables secure UART download mode " - "(read/write flash only)", None), - ("UART_PRINT_CONTROL", "config", 0, 4, 6, "uint:2", 18, None, None, "Sets the default UART boot message output mode", - {0: "Enabled", - 1: "Enable when GPIO 46 is low at reset", - 2: "Enable when GPIO 46 is high at rest", - 3: "Disabled"}), - ("PIN_POWER_SELECTION", "VDD_SPI config", 0, 4, 8, "bool", 18, None, None, "Sets default power supply for GPIO33..37", - {0: "VDD3P3_CPU", - 1: "VDD_SPI"}), - ("FLASH_TYPE", "config", 0, 4, 9, "bool", 18, None, None, "Selects SPI flash type", - {0: "4 data lines", - 1: "8 data lines"}), - ("FLASH_PAGE_SIZE", "config", 0, 4, 10, "uint:2", 18, None, None, "Sets the size of flash page", None), - ("FLASH_ECC_EN", "config", 0, 4, 12, "bool", 18, None, None, "Enables ECC in Flash boot mode", None), - ("FORCE_SEND_RESUME", "config", 0, 4, 13, "bool", 18, None, None, "Forces ROM code to send an SPI flash resume command " - "during SPI boot", None), - ("SECURE_VERSION", "identity", 0, 4, 14, "uint:16", 18, None, "bitcount", "Secure version (used by ESP-IDF anti-rollback feature)", - None), - ("DIS_USB_OTG_DOWNLOAD_MODE", "config", 0, 4, 31, "bool", 19, None, None, "Disables USB-OTG download feature in " - "UART download boot mode", None), - ("DISABLE_WAFER_VERSION_MAJOR", "config", 0, 5, 0, "bool", 19, None, None, "Disables check of wafer version major", None), - ("DISABLE_BLK_VERSION_MAJOR", "config", 0, 5, 1, "bool", 19, None, None, "Disables check of blk version major", None), - # - # Table 53: Parameters in BLOCK1-10 - # Name Category Block Word Pos Type:len WR_DIS RD_DIS Class Description Dictionary - ("MAC", "identity", 1, 0, 0, "bytes:6", 20, None, "mac", "Factory MAC Address", None), - ("SPI_PAD_CONFIG_CLK", "spi_pad_config", 1, 1, 16, "uint:6", 20, None, None, "SPI CLK pad", None), - ("SPI_PAD_CONFIG_Q", "spi_pad_config", 1, 1, 22, "uint:6", 20, None, None, "SPI Q (D1) pad", None), - ("SPI_PAD_CONFIG_D", "spi_pad_config", 1, 1, 28, "uint:6", 20, None, None, "SPI D (D0) pad", None), - ("SPI_PAD_CONFIG_CS", "spi_pad_config", 1, 2, 2, "uint:6", 20, None, None, "SPI CS pad", None), - ("SPI_PAD_CONFIG_HD", "spi_pad_config", 1, 2, 8, "uint:6", 20, None, None, "SPI HD (D3) pad", None), - ("SPI_PAD_CONFIG_WP", "spi_pad_config", 1, 2, 14, "uint:6", 20, None, None, "SPI WP (D2) pad", None), - ("SPI_PAD_CONFIG_DQS", "spi_pad_config", 1, 2, 20, "uint:6", 20, None, None, "SPI DQS pad", None), - ("SPI_PAD_CONFIG_D4", "spi_pad_config", 1, 2, 26, "uint:6", 20, None, None, "SPI D4 pad", None), - ("SPI_PAD_CONFIG_D5", "spi_pad_config", 1, 3, 0, "uint:6", 20, None, None, "SPI D5 pad", None), - ("SPI_PAD_CONFIG_D6", "spi_pad_config", 1, 3, 6, "uint:6", 20, None, None, "SPI D6 pad", None), - ("SPI_PAD_CONFIG_D7", "spi_pad_config", 1, 3, 12, "uint:6", 20, None, None, "SPI D7 pad", None), - - ("WAFER_VERSION_MINOR_LO", "identity", 1, 3, 18, "uint:3", 20, None, None, "WAFER_VERSION_MINOR least significant bits", None), - ("PKG_VERSION", "identity", 1, 3, 21, "uint:3", 20, None, None, "Package version", None), - ("BLK_VERSION_MINOR", "identity", 1, 3, 24, "uint:3", 20, None, None, "BLOCK version minor", None), - ("WAFER_VERSION_MINOR_HI", "identity", 1, 5, 23, "uint:1", 20, None, None, "WAFER_VERSION_MINOR most significant bits", None), - ("WAFER_VERSION_MAJOR", "identity", 1, 5, 24, "uint:2", 20, None, None, "WAFER_VERSION_MAJOR", None), - - ("OPTIONAL_UNIQUE_ID", "identity", 2, 0, 0, "bytes:16", 21, None, "keyblock", "Optional unique 128-bit ID", None), - ("BLK_VERSION_MAJOR", "identity", 2, 4, 0, "uint:2", 21, None, None, "BLOCK version major", - {0: "No calibration", - 1: "With calibration"}), - ("CUSTOM_MAC", "identity", 3, 6, 8, "bytes:6", 22, None, "mac", "Custom MAC Address", None), - ] - - KEYBLOCKS = [ - # Name Category Block Word Pos Type:len WR_DIS RD_DIS Class Description Dictionary - ('BLOCK_USR_DATA', "config", 3, 0, 0, "bytes:32", 22, None, None, "User data", None), - ('BLOCK_KEY0', "security", 4, 0, 0, "bytes:32", 23, 0, "keyblock", "Encryption key0 or user data", None), - ('BLOCK_KEY1', "security", 5, 0, 0, "bytes:32", 24, 1, "keyblock", "Encryption key1 or user data", None), - ('BLOCK_KEY2', "security", 6, 0, 0, "bytes:32", 25, 2, "keyblock", "Encryption key2 or user data", None), - ('BLOCK_KEY3', "security", 7, 0, 0, "bytes:32", 26, 3, "keyblock", "Encryption key3 or user data", None), - ('BLOCK_KEY4', "security", 8, 0, 0, "bytes:32", 27, 4, "keyblock", "Encryption key4 or user data", None), - ('BLOCK_KEY5', "security", 9, 0, 0, "bytes:32", 28, 5, "keyblock", "Encryption key5 or user data", None), - ('BLOCK_SYS_DATA2', "security", 10, 0, 0, "bytes:32", 29, 6, None, "System data (part 2)", None), - ] - - # if BLK_VERSION_MAJOR is 1, these efuse fields are in BLOCK2 - BLOCK2_CALIBRATION_EFUSES = [ - # Name Category Block Word Pos Type:len WR_DIS RD_DIS Class Description Dictionary - ('TEMP_SENSOR_CAL', "calibration", 2, 4, 7, "uint:9", 21, None, "t_sensor", "??? Temperature calibration", None), - ('ADC1_MODE0_D2', "calibration", 2, 4, 16, "uint:8", 21, None, "adc_tp", "??? ADC1 calibration 1", None), - ('ADC1_MODE1_D2', "calibration", 2, 4, 24, "uint:8", 21, None, "adc_tp", "??? ADC1 calibration 2", None), - ('ADC1_MODE2_D2', "calibration", 2, 5, 0, "uint:8", 21, None, "adc_tp", "??? ADC1 calibration 3", None), - ('ADC1_MODE3_D2', "calibration", 2, 5, 8, "uint:8", 21, None, "adc_tp", "??? ADC1 calibration 4", None), - ('ADC2_MODE0_D2', "calibration", 2, 5, 16, "uint:8", 21, None, "adc_tp", "??? ADC2 calibration 5", None), - ('ADC2_MODE1_D2', "calibration", 2, 5, 24, "uint:8", 21, None, "adc_tp", "??? ADC2 calibration 6", None), - ('ADC2_MODE2_D2', "calibration", 2, 6, 0, "uint:8", 21, None, "adc_tp", "??? ADC2 calibration 7", None), - ('ADC2_MODE3_D2', "calibration", 2, 6, 8, "uint:8", 21, None, "adc_tp", "??? ADC2 calibration 8", None), - ('ADC1_MODE0_D1', "calibration", 2, 6, 16, "uint:6", 21, None, "adc_tp", "??? ADC1 calibration 9", None), - ('ADC1_MODE1_D1', "calibration", 2, 6, 22, "uint:6", 21, None, "adc_tp", "??? ADC1 calibration 10", None), - ('ADC1_MODE2_D1', "calibration", 2, 6, 28, "uint:6", 21, None, "adc_tp", "??? ADC1 calibration 11", None), - ('ADC1_MODE3_D1', "calibration", 2, 7, 2, "uint:6", 21, None, "adc_tp", "??? ADC1 calibration 12", None), - ('ADC2_MODE0_D1', "calibration", 2, 7, 8, "uint:6", 21, None, "adc_tp", "??? ADC2 calibration 13", None), - ('ADC2_MODE1_D1', "calibration", 2, 7, 14, "uint:6", 21, None, "adc_tp", "??? ADC2 calibration 14", None), - ('ADC2_MODE2_D1', "calibration", 2, 7, 20, "uint:6", 21, None, "adc_tp", "??? ADC2 calibration 15", None), - ('ADC2_MODE3_D1', "calibration", 2, 7, 26, "uint:6", 21, None, "adc_tp", "??? ADC2 calibration 16", None), - ] - - CALC = [ - ("WAFER_VERSION_MINOR", "identity", 0, None, None, "uint:4", None, None, "wafer", "calc WAFER VERSION MINOR = WAFER_VERSION_MINOR_HI << 3 + WAFER_VERSION_MINOR_LO (read only)", None), - ] -# fmt: on + def __init__(self) -> None: + # List of efuse fields from TRM the chapter eFuse Controller. + self.EFUSES = [] + + self.KEYBLOCKS = [] + + # if BLK_VERSION_MAJOR is 1, these efuse fields are in BLOCK2 + self.BLOCK2_CALIBRATION_EFUSES = [] + + self.CALC = [] + + dir_name = os.path.dirname(os.path.abspath(__file__)) + dir_name, file_name = os.path.split(dir_name) + file_name = file_name + ".yaml" + dir_name, _ = os.path.split(dir_name) + efuse_file = os.path.join(dir_name, "efuse_defs", file_name) + with open(f"{efuse_file}", "r") as r_file: + e_desc = yaml.safe_load(r_file) + super().__init__(e_desc) + + for i, efuse in enumerate(self.ALL_EFUSES): + if efuse.name in [ + "BLOCK_USR_DATA", + "BLOCK_KEY0", + "BLOCK_KEY1", + "BLOCK_KEY2", + "BLOCK_KEY3", + "BLOCK_KEY4", + "BLOCK_KEY5", + "BLOCK_SYS_DATA2", + ]: + if efuse.name == "BLOCK_USR_DATA": + efuse.bit_len = 256 + efuse.type = "bytes:32" + self.KEYBLOCKS.append(efuse) + self.ALL_EFUSES[i] = None + + elif efuse.category == "calibration": + self.BLOCK2_CALIBRATION_EFUSES.append(efuse) + self.ALL_EFUSES[i] = None + + f = Field() + f.name = "WAFER_VERSION_MINOR" + f.block = 0 + f.bit_len = 4 + f.type = f"uint:{f.bit_len}" + f.category = "identity" + f.class_type = "wafer" + f.description = "calc WAFER VERSION MINOR = WAFER_VERSION_MINOR_HI << 3 + WAFER_VERSION_MINOR_LO (read only)" + self.CALC.append(f) + + for efuse in self.ALL_EFUSES: + if efuse is not None: + self.EFUSES.append(efuse) + + self.ALL_EFUSES = [] diff --git a/espefuse/efuse/esp32s3/operations.py b/espefuse/efuse/esp32s3/operations.py index 56be216c1..9331374da 100644 --- a/espefuse/efuse/esp32s3/operations.py +++ b/espefuse/efuse/esp32s3/operations.py @@ -18,6 +18,7 @@ from ..base_operations import ( add_common_commands, add_force_write_always, + add_show_sensitive_info_option, burn_bit, burn_block_data, burn_efuse, @@ -57,6 +58,7 @@ def add_commands(subparsers, efuses): ) protect_options(burn_key) add_force_write_always(burn_key) + add_show_sensitive_info_option(burn_key) burn_key.add_argument( "block", help="Key block to burn", @@ -107,6 +109,7 @@ def add_commands(subparsers, efuses): ) protect_options(burn_key_digest) add_force_write_always(burn_key_digest) + add_show_sensitive_info_option(burn_key_digest) burn_key_digest.add_argument( "block", help="Key block to burn", @@ -384,7 +387,13 @@ def burn_key(esp, efuses, args, digest=None): if efuses[block.key_purpose_name].need_reverse(keypurpose): revers_msg = "\tReversing byte order for AES-XTS hardware peripheral" data = data[::-1] - print("-> [%s]" % (util.hexify(data, " "))) + print( + "-> [{}]".format( + util.hexify(data, " ") + if args.show_sensitive_info + else " ".join(["??"] * len(data)) + ) + ) if revers_msg: print(revers_msg) if len(data) != num_bytes: diff --git a/espefuse/efuse/esp32s3beta2/emulate_efuse_controller.py b/espefuse/efuse/esp32s3beta2/emulate_efuse_controller.py index 48f9305a4..0d81c0832 100644 --- a/espefuse/efuse/esp32s3beta2/emulate_efuse_controller.py +++ b/espefuse/efuse/esp32s3beta2/emulate_efuse_controller.py @@ -16,13 +16,13 @@ class EmulateEfuseController(EmulateEfuseControllerBase): CHIP_NAME = "ESP32-S3(beta2)" mem = None debug = False - Blocks = EfuseDefineBlocks - Fields = EfuseDefineFields - REGS = EfuseDefineRegisters def __init__(self, efuse_file=None, debug=False): + self.Blocks = EfuseDefineBlocks + self.Fields = EfuseDefineFields() + self.REGS = EfuseDefineRegisters super(EmulateEfuseController, self).__init__(efuse_file, debug) - self.write_reg(self.REGS.EFUSE_STATUS_REG, 1) + self.write_reg(self.REGS.EFUSE_CMD_REG, 0) """ esptool method start >>""" @@ -53,10 +53,10 @@ def handle_writing_event(self, addr, value): self.clean_blocks_wr_regs() self.check_rd_protection_area() self.write_reg(addr, 0) - self.write_reg(self.REGS.EFUSE_STATUS_REG, 1) + self.write_reg(self.REGS.EFUSE_CMD_REG, 0) elif value == self.REGS.EFUSE_READ_CMD: self.write_reg(addr, 0) - self.write_reg(self.REGS.EFUSE_STATUS_REG, 1) + self.write_reg(self.REGS.EFUSE_CMD_REG, 0) self.save_to_file() def get_bitlen_of_block(self, blk, wr=False): diff --git a/espefuse/efuse/esp32s3beta2/fields.py b/espefuse/efuse/esp32s3beta2/fields.py index 952e72927..26abb9f1f 100644 --- a/espefuse/efuse/esp32s3beta2/fields.py +++ b/espefuse/efuse/esp32s3beta2/fields.py @@ -54,16 +54,15 @@ class EspEfuses(base_fields.EspEfusesBase): Wrapper object to manage the efuse fields in a connected ESP bootloader """ - Blocks = EfuseDefineBlocks() - Fields = EfuseDefineFields() - REGS = EfuseDefineRegisters - BURN_BLOCK_DATA_NAMES = Blocks.get_burn_block_data_names() - BLOCKS_FOR_KEYS = Blocks.get_blocks_for_keys() - debug = False do_not_confirm = False def __init__(self, esp, skip_connect=False, debug=False, do_not_confirm=False): + self.Blocks = EfuseDefineBlocks() + self.Fields = EfuseDefineFields() + self.REGS = EfuseDefineRegisters + self.BURN_BLOCK_DATA_NAMES = self.Blocks.get_burn_block_data_names() + self.BLOCKS_FOR_KEYS = self.Blocks.get_blocks_for_keys() self._esp = esp self.debug = debug self.do_not_confirm = do_not_confirm @@ -85,59 +84,43 @@ def __init__(self, esp, skip_connect=False, debug=False, do_not_confirm=False): ] if not skip_connect: self.get_coding_scheme_warnings() - self.efuses = [ - EfuseField.from_tuple( - self, self.Fields.get(efuse), self.Fields.get(efuse).class_type - ) - for efuse in self.Fields.EFUSES - ] + self.efuses = [EfuseField.convert(self, efuse) for efuse in self.Fields.EFUSES] self.efuses += [ - EfuseField.from_tuple( - self, self.Fields.get(efuse), self.Fields.get(efuse).class_type - ) - for efuse in self.Fields.KEYBLOCKS + EfuseField.convert(self, efuse) for efuse in self.Fields.KEYBLOCKS ] if skip_connect: self.efuses += [ - EfuseField.from_tuple( - self, self.Fields.get(efuse), self.Fields.get(efuse).class_type - ) + EfuseField.convert(self, efuse) for efuse in self.Fields.BLOCK2_CALIBRATION_EFUSES ] else: if self["BLK_VERSION_MAJOR"].get() == 1: self.efuses += [ - EfuseField.from_tuple( - self, self.Fields.get(efuse), self.Fields.get(efuse).class_type - ) + EfuseField.convert(self, efuse) for efuse in self.Fields.BLOCK2_CALIBRATION_EFUSES ] self.efuses += [ - EfuseField.from_tuple( - self, self.Fields.get(efuse), self.Fields.get(efuse).class_type - ) - for efuse in self.Fields.CALC + EfuseField.convert(self, efuse) for efuse in self.Fields.CALC ] def __getitem__(self, efuse_name): """Return the efuse field with the given name""" for e in self.efuses: - if efuse_name == e.name: + if efuse_name == e.name or any(x == efuse_name for x in e.alt_names): return e new_fields = False for efuse in self.Fields.BLOCK2_CALIBRATION_EFUSES: - e = self.Fields.get(efuse) - if e.name == efuse_name: + if efuse.name == efuse_name or any( + x == efuse_name for x in efuse.alt_names + ): self.efuses += [ - EfuseField.from_tuple( - self, self.Fields.get(efuse), self.Fields.get(efuse).class_type - ) + EfuseField.convert(self, efuse) for efuse in self.Fields.BLOCK2_CALIBRATION_EFUSES ] new_fields = True if new_fields: for e in self.efuses: - if efuse_name == e.name: + if efuse_name == e.name or any(x == efuse_name for x in e.alt_names): return e raise KeyError @@ -158,10 +141,6 @@ def print_status_regs(self): ) ) - def get_block_errors(self, block_num): - """Returns (error count, failure boolean flag)""" - return self.blocks[block_num].num_errors, self.blocks[block_num].fail - def efuse_controller_setup(self): self.set_efuse_timing() self.clear_pgm_registers() @@ -181,9 +160,13 @@ def clear_pgm_registers(self): def wait_efuse_idle(self): deadline = time.time() + self.REGS.EFUSE_BURN_TIMEOUT while time.time() < deadline: - # if self.read_reg(self.EFUSE_CMD_REG) == 0: - if self.read_reg(self.REGS.EFUSE_STATUS_REG) & 0x7 == 1: - return + cmds = self.REGS.EFUSE_PGM_CMD | self.REGS.EFUSE_READ_CMD + if self.read_reg(self.REGS.EFUSE_CMD_REG) & cmds == 0: + if self.read_reg(self.REGS.EFUSE_CMD_REG) & cmds == 0: + # Due to a hardware error, we have to read READ_CMD again + # to make sure the efuse clock is normal. + # For PGM_CMD it is not necessary. + return raise esptool.FatalError( "Timed out waiting for Efuse controller command to complete" ) @@ -249,6 +232,13 @@ def set_efuse_timing(self): "The eFuse supports only xtal=40M (xtal was %d)" % apb_freq ) + self.update_reg(self.REGS.EFUSE_DAC_CONF_REG, self.REGS.EFUSE_DAC_NUM_M, 0xFF) + self.update_reg( + self.REGS.EFUSE_DAC_CONF_REG, self.REGS.EFUSE_DAC_CLK_DIV_M, 0x28 + ) + self.update_reg( + self.REGS.EFUSE_WR_TIM_CONF1_REG, self.REGS.EFUSE_PWR_ON_NUM_M, 0x3000 + ) self.update_reg( self.REGS.EFUSE_WR_TIM_CONF2_REG, self.REGS.EFUSE_PWR_OFF_NUM_M, 0x190 ) @@ -264,12 +254,9 @@ def get_coding_scheme_warnings(self, silent=False): self.read_reg(self.REGS.EFUSE_RD_REPEAT_ERR0_REG + offs * 4) for offs in range(5) ] - data = BitArray() + block.err_bitarray.pos = 0 for word in reversed(words): - data.append("uint:32=%d" % word) - # pos=32 because EFUSE_WR_DIS goes first it is 32bit long - # and not under error control - block.err_bitarray.overwrite(data, pos=32) + block.err_bitarray.overwrite(BitArray("uint:32=%d" % word)) block.num_errors = block.err_bitarray.count(True) block.fail = block.num_errors != 0 else: @@ -296,9 +283,10 @@ def get_coding_scheme_warnings(self, silent=False): def summary(self): if self["VDD_SPI_FORCE"].get() == 0: output = "Flash voltage (VDD_SPI) determined by GPIO45 on reset " - "(GPIO45=High: VDD_SPI pin is powered from internal 1.8V LDO\n" + output += "(GPIO45=High: VDD_SPI pin is powered from internal 1.8V LDO\n" output += "GPIO45=Low or NC: VDD_SPI pin is powered directly from " - "VDD3P3_RTC_IO via resistor Rspi. Typically this voltage is 3.3 V)." + output += "VDD3P3_RTC_IO via resistor Rspi. " + output += "Typically this voltage is 3.3 V)." elif self["VDD_SPI_XPD"].get() == 0: output = "Flash voltage (VDD_SPI) internal regulator disabled by efuse." elif self["VDD_SPI_TIEH"].get() == 0: @@ -310,35 +298,22 @@ def summary(self): class EfuseField(base_fields.EfuseFieldBase): @staticmethod - def from_tuple(parent, efuse_tuple, type_class): + def convert(parent, efuse): return { "mac": EfuseMacField, "keypurpose": EfuseKeyPurposeField, "t_sensor": EfuseTempSensor, "adc_tp": EfuseAdcPointCalibration, "wafer": EfuseWafer, - }.get(type_class, EfuseField)(parent, efuse_tuple) - - def get_info(self): - output = "%s (BLOCK%d)" % (self.name, self.block) - errs, fail = self.parent.get_block_errors(self.block) - if errs != 0 or fail: - output += ( - "[FAIL:%d]" % (fail) - if self.block == 0 - else "[ERRS:%d FAIL:%d]" % (errs, fail) - ) - if self.efuse_class == "keyblock": - name = self.parent.blocks[self.block].key_purpose_name - if name is not None: - output += "\n Purpose: %s\n " % (self.parent[name].get()) - return output + }.get(efuse.class_type, EfuseField)(parent, efuse) class EfuseWafer(EfuseField): def get(self, from_read=True): hi_bits = self.parent["WAFER_VERSION_MINOR_HI"].get(from_read) + assert self.parent["WAFER_VERSION_MINOR_HI"].bit_len == 1 lo_bits = self.parent["WAFER_VERSION_MINOR_LO"].get(from_read) + assert self.parent["WAFER_VERSION_MINOR_LO"].bit_len == 3 return (hi_bits << 3) + lo_bits def save(self, new_value): @@ -471,6 +446,14 @@ def get(self, from_read=True): return p[0] return "FORBIDDEN_STATE" + def get_name(self, raw_val): + for key in self.KEY_PURPOSES: + if key[1] == raw_val: + return key[0] + def save(self, new_value): raw_val = int(self.check_format(str(new_value))) + str_new_value = self.get_name(raw_val) + if self.name == "KEY_PURPOSE_5" and str_new_value.startswith("XTS_AES"): + raise esptool.FatalError(f"{self.name} can not have {str_new_value} key due to a hardware bug (please see TRM for more details)") return super(EfuseKeyPurposeField, self).save(raw_val) diff --git a/espefuse/efuse/esp32s3beta2/mem_definition.py b/espefuse/efuse/esp32s3beta2/mem_definition.py index a551fce89..eabf76781 100644 --- a/espefuse/efuse/esp32s3beta2/mem_definition.py +++ b/espefuse/efuse/esp32s3beta2/mem_definition.py @@ -4,25 +4,32 @@ # # SPDX-License-Identifier: GPL-2.0-or-later -from ..mem_definition_base import EfuseBlocksBase, EfuseFieldsBase, EfuseRegistersBase +import os +import yaml + +from ..mem_definition_base import ( + EfuseBlocksBase, + EfuseFieldsBase, + EfuseRegistersBase, + Field, +) -# fmt: off -class EfuseDefineRegisters(EfuseRegistersBase): +class EfuseDefineRegisters(EfuseRegistersBase): EFUSE_ADDR_MASK = 0x00000FFF - EFUSE_MEM_SIZE = (0x01FC + 4) + EFUSE_MEM_SIZE = 0x01FC + 4 # EFUSE registers & command/conf values - DR_REG_EFUSE_BASE = 0x6001A000 - EFUSE_PGM_DATA0_REG = DR_REG_EFUSE_BASE - EFUSE_CHECK_VALUE0_REG = DR_REG_EFUSE_BASE + 0x020 - EFUSE_CLK_REG = DR_REG_EFUSE_BASE + 0x1C8 - EFUSE_CONF_REG = DR_REG_EFUSE_BASE + 0x1CC - EFUSE_STATUS_REG = DR_REG_EFUSE_BASE + 0x1D0 - EFUSE_CMD_REG = DR_REG_EFUSE_BASE + 0x1D4 - EFUSE_RD_RS_ERR0_REG = DR_REG_EFUSE_BASE + 0x1C0 - EFUSE_RD_RS_ERR1_REG = DR_REG_EFUSE_BASE + 0x1C4 + DR_REG_EFUSE_BASE = 0x6001A000 + EFUSE_PGM_DATA0_REG = DR_REG_EFUSE_BASE + EFUSE_CHECK_VALUE0_REG = DR_REG_EFUSE_BASE + 0x020 + EFUSE_CLK_REG = DR_REG_EFUSE_BASE + 0x1C8 + EFUSE_CONF_REG = DR_REG_EFUSE_BASE + 0x1CC + EFUSE_STATUS_REG = DR_REG_EFUSE_BASE + 0x1D0 + EFUSE_CMD_REG = DR_REG_EFUSE_BASE + 0x1D4 + EFUSE_RD_RS_ERR0_REG = DR_REG_EFUSE_BASE + 0x1C0 + EFUSE_RD_RS_ERR1_REG = DR_REG_EFUSE_BASE + 0x1C4 EFUSE_RD_REPEAT_ERR0_REG = DR_REG_EFUSE_BASE + 0x17C EFUSE_RD_REPEAT_ERR1_REG = DR_REG_EFUSE_BASE + 0x180 EFUSE_RD_REPEAT_ERR2_REG = DR_REG_EFUSE_BASE + 0x184 @@ -33,37 +40,49 @@ class EfuseDefineRegisters(EfuseRegistersBase): EFUSE_WR_TIM_CONF1_REG = DR_REG_EFUSE_BASE + 0x1F4 EFUSE_WR_TIM_CONF2_REG = DR_REG_EFUSE_BASE + 0x1F8 EFUSE_DATE_REG = DR_REG_EFUSE_BASE + 0x1FC - EFUSE_WRITE_OP_CODE = 0x5A5A - EFUSE_READ_OP_CODE = 0x5AA5 - EFUSE_PGM_CMD_MASK = 0x3 - EFUSE_PGM_CMD = 0x2 - EFUSE_READ_CMD = 0x1 + EFUSE_WRITE_OP_CODE = 0x5A5A + EFUSE_READ_OP_CODE = 0x5AA5 + EFUSE_PGM_CMD_MASK = 0x3 + EFUSE_PGM_CMD = 0x2 + EFUSE_READ_CMD = 0x1 BLOCK_ERRORS = [ # error_reg, err_num_mask, err_num_offs, fail_bit - (EFUSE_RD_REPEAT_ERR0_REG, None, None, None), # BLOCK0 - (EFUSE_RD_RS_ERR0_REG, 0x7, 0, 3), # MAC_SPI_8M_0 - (EFUSE_RD_RS_ERR0_REG, 0x7, 4, 7), # BLOCK_SYS_DATA - (EFUSE_RD_RS_ERR0_REG, 0x7, 8, 11), # BLOCK_USR_DATA - (EFUSE_RD_RS_ERR0_REG, 0x7, 12, 15), # BLOCK_KEY0 - (EFUSE_RD_RS_ERR0_REG, 0x7, 16, 19), # BLOCK_KEY1 - (EFUSE_RD_RS_ERR0_REG, 0x7, 20, 23), # BLOCK_KEY2 - (EFUSE_RD_RS_ERR0_REG, 0x7, 24, 27), # BLOCK_KEY3 - (EFUSE_RD_RS_ERR0_REG, 0x7, 28, 31), # BLOCK_KEY4 - (EFUSE_RD_RS_ERR1_REG, 0x7, 0, 3), # BLOCK_KEY5 - (EFUSE_RD_RS_ERR1_REG, 0x7, 4, 7), # BLOCK_SYS_DATA2 + (EFUSE_RD_REPEAT_ERR0_REG, None, None, None), # BLOCK0 + (EFUSE_RD_RS_ERR0_REG, 0x7, 0, 3), # MAC_SPI_8M_0 + (EFUSE_RD_RS_ERR0_REG, 0x7, 4, 7), # BLOCK_SYS_DATA + (EFUSE_RD_RS_ERR0_REG, 0x7, 8, 11), # BLOCK_USR_DATA + (EFUSE_RD_RS_ERR0_REG, 0x7, 12, 15), # BLOCK_KEY0 + (EFUSE_RD_RS_ERR0_REG, 0x7, 16, 19), # BLOCK_KEY1 + (EFUSE_RD_RS_ERR0_REG, 0x7, 20, 23), # BLOCK_KEY2 + (EFUSE_RD_RS_ERR0_REG, 0x7, 24, 27), # BLOCK_KEY3 + (EFUSE_RD_RS_ERR0_REG, 0x7, 28, 31), # BLOCK_KEY4 + (EFUSE_RD_RS_ERR1_REG, 0x7, 0, 3), # BLOCK_KEY5 + (EFUSE_RD_RS_ERR1_REG, 0x7, 4, 7), # BLOCK_SYS_DATA2 ] # EFUSE_WR_TIM_CONF2_REG EFUSE_PWR_OFF_NUM_S = 0 EFUSE_PWR_OFF_NUM_M = 0xFFFF << EFUSE_PWR_OFF_NUM_S + # EFUSE_WR_TIM_CONF1_REG + EFUSE_PWR_ON_NUM_S = 8 + EFUSE_PWR_ON_NUM_M = 0x0000FFFF << EFUSE_PWR_ON_NUM_S -class EfuseDefineBlocks(EfuseBlocksBase): + # EFUSE_DAC_CONF_REG + EFUSE_DAC_CLK_DIV_S = 0 + EFUSE_DAC_CLK_DIV_M = 0xFF << EFUSE_DAC_CLK_DIV_S + # EFUSE_DAC_CONF_REG + EFUSE_DAC_NUM_S = 9 + EFUSE_DAC_NUM_M = 0xFF << EFUSE_DAC_NUM_S + + +class EfuseDefineBlocks(EfuseBlocksBase): __base_rd_regs = EfuseDefineRegisters.DR_REG_EFUSE_BASE __base_wr_regs = EfuseDefineRegisters.EFUSE_PGM_DATA0_REG # List of efuse blocks + # fmt: off BLOCKS = [ # Name, Alias, Index, Read address, Write address, Write protect bit, Read protect bit, Len, key_purpose ("BLOCK0", [], 0, __base_rd_regs + 0x02C, __base_wr_regs, None, None, 6, None), @@ -78,6 +97,7 @@ class EfuseDefineBlocks(EfuseBlocksBase): ("BLOCK_KEY5", ["BLOCK9"], 9, __base_rd_regs + 0x13C, __base_wr_regs, 28, 5, 8, "KEY_PURPOSE_5"), ("BLOCK_SYS_DATA2", ["BLOCK10"], 10, __base_rd_regs + 0x15C, __base_wr_regs, 29, 6, 8, None), ] + # fmt: on def get_burn_block_data_names(self): list_of_names = [] @@ -92,157 +112,60 @@ def get_burn_block_data_names(self): class EfuseDefineFields(EfuseFieldsBase): - - # List of efuse fields from TRM the chapter eFuse Controller. - EFUSES = [ - # - # Table 51: Parameters in BLOCK0 - # Name Category Block Word Pos Type:len WR_DIS RD_DIS Class Description Dictionary - ("WR_DIS", "efuse", 0, 0, 0, "uint:32", None, None, None, "Disables programming of individual eFuses", None), - ("RD_DIS", "efuse", 0, 1, 0, "uint:7", 0, None, None, "Disables software reading from BLOCK4-10", None), - ("DIS_ICACHE", "config", 0, 1, 8, "bool", 2, None, None, "Disables ICache", None), - ("DIS_DCACHE", "config", 0, 1, 9, "bool", 2, None, None, "Disables DCache", None), - ("DIS_DOWNLOAD_ICACHE", "config", 0, 1, 10, "bool", 2, None, None, "Disables Icache when SoC is in Download mode", None), - ("DIS_DOWNLOAD_DCACHE", "config", 0, 1, 11, "bool", 2, None, None, "Disables Dcache when SoC is in Download mode", None), - ("DIS_FORCE_DOWNLOAD", "config", 0, 1, 12, "bool", 2, None, None, "Disables forcing chip into Download mode", None), - ("DIS_USB", "usb config", 0, 1, 13, "bool", 2, None, None, "Disables the USB OTG hardware", None), - ("DIS_CAN", "config", 0, 1, 14, "bool", 2, None, None, "Disables the TWAI Controller hardware", None), - ("DIS_APP_CPU", "config", 0, 1, 15, "bool", 2, None, None, "Disables APP CPU", None), - ("SOFT_DIS_JTAG", "security", 0, 1, 16, "uint:3", 31, None, None, "Software disables JTAG by programming " - "odd number of 1 bit(s). " - "JTAG can be re-enabled via HMAC peripheral", - None), - ("HARD_DIS_JTAG", "security", 0, 1, 19, "bool", 2, None, None, "Hardware disables JTAG permanently", None), - - ("DIS_DOWNLOAD_MANUAL_ENCRYPT", "security", 0, 1, 20, "bool", 2, None, None, "Disables flash encryption when in download boot modes", - None), - ("USB_EXCHG_PINS", "usb config", 0, 1, 25, "bool", 30, None, None, "Exchanges USB D+ and D- pins", None), - ("EXT_PHY_ENABLE", "usb config", 0, 1, 26, "bool", 30, None, None, "Enables external USB PHY", None), - ("BTLC_GPIO_ENABLE", "usb config", 0, 1, 27, "uint:2", 30, None, None, "Enables BTLC GPIO", None), - ("VDD_SPI_XPD", "VDD_SPI config", 0, 2, 4, "bool", 3, None, None, "The VDD_SPI regulator is powered on", None), - ("VDD_SPI_TIEH", "VDD_SPI config", 0, 2, 5, "bool", 3, None, None, "The VDD_SPI power supply voltage at reset", - {0: "Connect to 1.8V LDO", - 1: "Connect to VDD_RTC_IO"}), - ("VDD_SPI_FORCE", "VDD_SPI config", 0, 2, 6, "bool", 3, None, None, "Force using VDD_SPI_XPD and VDD_SPI_TIEH " - "to configure VDD_SPI LDO", None), - ("WDT_DELAY_SEL", "WDT config", 0, 2, 16, "uint:2", 3, None, None, "Selects RTC WDT timeout threshold at startup", None), - ("SPI_BOOT_CRYPT_CNT", "security", 0, 2, 18, "uint:3", 4, None, "bitcount", "Enables encryption and decryption, when an SPI boot " - "mode is set. Enabled when 1 or 3 bits are set," - "disabled otherwise", - {0: "Disable", - 1: "Enable", - 3: "Disable", - 7: "Enable"}), - ("SECURE_BOOT_KEY_REVOKE0", "security", 0, 2, 21, "bool", 5, None, None, "Revokes use of secure boot key digest 0", None), - ("SECURE_BOOT_KEY_REVOKE1", "security", 0, 2, 22, "bool", 6, None, None, "Revokes use of secure boot key digest 1", None), - ("SECURE_BOOT_KEY_REVOKE2", "security", 0, 2, 23, "bool", 7, None, None, "Revokes use of secure boot key digest 2", None), - ("KEY_PURPOSE_0", "security", 0, 2, 24, "uint:4", 8, None, "keypurpose", "KEY0 purpose", None), - ("KEY_PURPOSE_1", "security", 0, 2, 28, "uint:4", 9, None, "keypurpose", "KEY1 purpose", None), - ("KEY_PURPOSE_2", "security", 0, 3, 0, "uint:4", 10, None, "keypurpose", "KEY2 purpose", None), - ("KEY_PURPOSE_3", "security", 0, 3, 4, "uint:4", 11, None, "keypurpose", "KEY3 purpose", None), - ("KEY_PURPOSE_4", "security", 0, 3, 8, "uint:4", 12, None, "keypurpose", "KEY4 purpose", None), - ("KEY_PURPOSE_5", "security", 0, 3, 12, "uint:4", 13, None, "keypurpose", "KEY5 purpose", None), - ("SECURE_BOOT_EN", "security", 0, 3, 20, "bool", 15, None, None, "Enables secure boot", None), - ("SECURE_BOOT_AGGRESSIVE_REVOKE", "security", 0, 3, 21, "bool", 16, None, None, "Enables aggressive secure boot key revocation mode", - None), - ("FLASH_TPUW", "config", 0, 3, 28, "uint:4", 18, None, None, "Configures flash startup delay after SoC power-up, " - "unit is (ms/2). When the value is 15, delay is 7.5 ms", - None), - ("DIS_DOWNLOAD_MODE", "security", 0, 4, 0, "bool", 18, None, None, "Disables all Download boot modes", None), - ("DIS_DIRECT_BOOT", "config", 0, 4, 1, "bool", 18, None, None, "Disables direct boot mode", None), - ("DIS_USB_SERIAL_JTAG_ROM_PRINT", "config", 0, 4, 2, "bool", 18, None, None, "Disables USB-Serial-JTAG ROM printing", None), - ("FLASH_ECC_MODE", "config", 0, 4, 3, "bool", 18, None, None, "Configures the ECC mode for SPI flash", - {0: "16-byte to 18-byte mode", - 1: "16-byte to 17-byte mode"}), - ("DIS_USB_SERIAL_JTAG_DOWNLOAD_MODE", "config", 0, 4, 4, "bool", 18, None, None, "Disables USB-Serial-JTAG download feature in " - "UART download boot mode", None), - ("ENABLE_SECURITY_DOWNLOAD", "security", 0, 4, 5, "bool", 18, None, None, "Enables secure UART download mode " - "(read/write flash only)", None), - ("UART_PRINT_CONTROL", "config", 0, 4, 6, "uint:2", 18, None, None, "Sets the default UART boot message output mode", - {0: "Enabled", - 1: "Enable when GPIO 46 is low at reset", - 2: "Enable when GPIO 46 is high at rest", - 3: "Disabled"}), - ("PIN_POWER_SELECTION", "VDD_SPI config", 0, 4, 8, "bool", 18, None, None, "Sets default power supply for GPIO33..37", - {0: "VDD3P3_CPU", - 1: "VDD_SPI"}), - ("FLASH_TYPE", "config", 0, 4, 9, "bool", 18, None, None, "Selects SPI flash type", - {0: "4 data lines", - 1: "8 data lines"}), - ("FLASH_PAGE_SIZE", "config", 0, 4, 10, "uint:2", 18, None, None, "Sets the size of flash page", None), - ("FLASH_ECC_EN", "config", 0, 4, 12, "bool", 18, None, None, "Enables ECC in Flash boot mode", None), - ("FORCE_SEND_RESUME", "config", 0, 4, 13, "bool", 18, None, None, "Forces ROM code to send an SPI flash resume command " - "during SPI boot", None), - ("SECURE_VERSION", "identity", 0, 4, 14, "uint:16", 18, None, "bitcount", "Secure version (used by ESP-IDF anti-rollback feature)", - None), - ("DIS_USB_OTG_DOWNLOAD_MODE", "config", 0, 4, 31, "bool", 19, None, None, "Disables USB-OTG download feature in " - "UART download boot mode", None), - ("DISABLE_WAFER_VERSION_MAJOR", "config", 0, 5, 0, "bool", 19, None, None, "Disables check of wafer version major", None), - ("DISABLE_BLK_VERSION_MAJOR", "config", 0, 5, 1, "bool", 19, None, None, "Disables check of blk version major", None), - # - # Table 53: Parameters in BLOCK1-10 - # Name Category Block Word Pos Type:len WR_DIS RD_DIS Class Description Dictionary - ("MAC", "identity", 1, 0, 0, "bytes:6", 20, None, "mac", "Factory MAC Address", None), - ("SPI_PAD_CONFIG_CLK", "spi_pad_config", 1, 1, 16, "uint:6", 20, None, None, "SPI CLK pad", None), - ("SPI_PAD_CONFIG_Q", "spi_pad_config", 1, 1, 22, "uint:6", 20, None, None, "SPI Q (D1) pad", None), - ("SPI_PAD_CONFIG_D", "spi_pad_config", 1, 1, 28, "uint:6", 20, None, None, "SPI D (D0) pad", None), - ("SPI_PAD_CONFIG_CS", "spi_pad_config", 1, 2, 2, "uint:6", 20, None, None, "SPI CS pad", None), - ("SPI_PAD_CONFIG_HD", "spi_pad_config", 1, 2, 8, "uint:6", 20, None, None, "SPI HD (D3) pad", None), - ("SPI_PAD_CONFIG_WP", "spi_pad_config", 1, 2, 14, "uint:6", 20, None, None, "SPI WP (D2) pad", None), - ("SPI_PAD_CONFIG_DQS", "spi_pad_config", 1, 2, 20, "uint:6", 20, None, None, "SPI DQS pad", None), - ("SPI_PAD_CONFIG_D4", "spi_pad_config", 1, 2, 26, "uint:6", 20, None, None, "SPI D4 pad", None), - ("SPI_PAD_CONFIG_D5", "spi_pad_config", 1, 3, 0, "uint:6", 20, None, None, "SPI D5 pad", None), - ("SPI_PAD_CONFIG_D6", "spi_pad_config", 1, 3, 6, "uint:6", 20, None, None, "SPI D6 pad", None), - ("SPI_PAD_CONFIG_D7", "spi_pad_config", 1, 3, 12, "uint:6", 20, None, None, "SPI D7 pad", None), - - ("WAFER_VERSION_MINOR_LO", "identity", 1, 3, 18, "uint:3", 20, None, None, "WAFER_VERSION_MINOR least significant bits", None), - ("PKG_VERSION", "identity", 1, 3, 21, "uint:3", 20, None, None, "Package version", None), - ("BLK_VERSION_MINOR", "identity", 1, 3, 24, "uint:3", 20, None, None, "BLOCK version minor", None), - ("WAFER_VERSION_MINOR_HI", "identity", 1, 5, 23, "uint:1", 20, None, None, "WAFER_VERSION_MINOR most significant bits", None), - ("WAFER_VERSION_MAJOR", "identity", 1, 5, 24, "uint:2", 20, None, None, "WAFER_VERSION_MAJOR", None), - - ("OPTIONAL_UNIQUE_ID", "identity", 2, 0, 0, "bytes:16", 21, None, "keyblock", "Optional unique 128-bit ID", None), - ("BLK_VERSION_MAJOR", "identity", 2, 4, 0, "uint:2", 21, None, None, "BLOCK version major", - {0: "No calibration", - 1: "With calibration"}), - ("CUSTOM_MAC", "identity", 3, 6, 8, "bytes:6", 22, None, "mac", "Custom MAC Address", None), - ] - - KEYBLOCKS = [ - # Name Category Block Word Pos Type:len WR_DIS RD_DIS Class Description Dictionary - ('BLOCK_USR_DATA', "config", 3, 0, 0, "bytes:32", 22, None, None, "User data", None), - ('BLOCK_KEY0', "security", 4, 0, 0, "bytes:32", 23, 0, "keyblock", "Encryption key0 or user data", None), - ('BLOCK_KEY1', "security", 5, 0, 0, "bytes:32", 24, 1, "keyblock", "Encryption key1 or user data", None), - ('BLOCK_KEY2', "security", 6, 0, 0, "bytes:32", 25, 2, "keyblock", "Encryption key2 or user data", None), - ('BLOCK_KEY3', "security", 7, 0, 0, "bytes:32", 26, 3, "keyblock", "Encryption key3 or user data", None), - ('BLOCK_KEY4', "security", 8, 0, 0, "bytes:32", 27, 4, "keyblock", "Encryption key4 or user data", None), - ('BLOCK_KEY5', "security", 9, 0, 0, "bytes:32", 28, 5, "keyblock", "Encryption key5 or user data", None), - ('BLOCK_SYS_DATA2', "security", 10, 0, 0, "bytes:32", 29, 6, None, "System data (part 2)", None), - ] - - # if BLK_VERSION_MAJOR is 1, these efuse fields are in BLOCK2 - BLOCK2_CALIBRATION_EFUSES = [ - # Name Category Block Word Pos Type:len WR_DIS RD_DIS Class Description Dictionary - ('TEMP_SENSOR_CAL', "calibration", 2, 4, 7, "uint:9", 21, None, "t_sensor", "??? Temperature calibration", None), - ('ADC1_MODE0_D2', "calibration", 2, 4, 16, "uint:8", 21, None, "adc_tp", "??? ADC1 calibration 1", None), - ('ADC1_MODE1_D2', "calibration", 2, 4, 24, "uint:8", 21, None, "adc_tp", "??? ADC1 calibration 2", None), - ('ADC1_MODE2_D2', "calibration", 2, 5, 0, "uint:8", 21, None, "adc_tp", "??? ADC1 calibration 3", None), - ('ADC1_MODE3_D2', "calibration", 2, 5, 8, "uint:8", 21, None, "adc_tp", "??? ADC1 calibration 4", None), - ('ADC2_MODE0_D2', "calibration", 2, 5, 16, "uint:8", 21, None, "adc_tp", "??? ADC2 calibration 5", None), - ('ADC2_MODE1_D2', "calibration", 2, 5, 24, "uint:8", 21, None, "adc_tp", "??? ADC2 calibration 6", None), - ('ADC2_MODE2_D2', "calibration", 2, 6, 0, "uint:8", 21, None, "adc_tp", "??? ADC2 calibration 7", None), - ('ADC2_MODE3_D2', "calibration", 2, 6, 8, "uint:8", 21, None, "adc_tp", "??? ADC2 calibration 8", None), - ('ADC1_MODE0_D1', "calibration", 2, 6, 16, "uint:6", 21, None, "adc_tp", "??? ADC1 calibration 9", None), - ('ADC1_MODE1_D1', "calibration", 2, 6, 22, "uint:6", 21, None, "adc_tp", "??? ADC1 calibration 10", None), - ('ADC1_MODE2_D1', "calibration", 2, 6, 28, "uint:6", 21, None, "adc_tp", "??? ADC1 calibration 11", None), - ('ADC1_MODE3_D1', "calibration", 2, 7, 2, "uint:6", 21, None, "adc_tp", "??? ADC1 calibration 12", None), - ('ADC2_MODE0_D1', "calibration", 2, 7, 8, "uint:6", 21, None, "adc_tp", "??? ADC2 calibration 13", None), - ('ADC2_MODE1_D1', "calibration", 2, 7, 14, "uint:6", 21, None, "adc_tp", "??? ADC2 calibration 14", None), - ('ADC2_MODE2_D1', "calibration", 2, 7, 20, "uint:6", 21, None, "adc_tp", "??? ADC2 calibration 15", None), - ('ADC2_MODE3_D1', "calibration", 2, 7, 26, "uint:6", 21, None, "adc_tp", "??? ADC2 calibration 16", None), - ] - - CALC = [ - ("WAFER_VERSION_MINOR", "identity", 0, None, None, "uint:4", None, None, "wafer", "calc WAFER VERSION MINOR = WAFER_VERSION_MINOR_HI << 3 + WAFER_VERSION_MINOR_LO (read only)", None), - ] -# fmt: on + def __init__(self) -> None: + # List of efuse fields from TRM the chapter eFuse Controller. + self.EFUSES = [] + + self.KEYBLOCKS = [] + + # if BLK_VERSION_MAJOR is 1, these efuse fields are in BLOCK2 + self.BLOCK2_CALIBRATION_EFUSES = [] + + self.CALC = [] + + dir_name = os.path.dirname(os.path.abspath(__file__)) + dir_name, file_name = os.path.split(dir_name) + file_name = file_name + ".yaml" + dir_name, _ = os.path.split(dir_name) + efuse_file = os.path.join(dir_name, "efuse_defs", file_name) + efuse_file = efuse_file.replace("esp32s3beta2", "esp32s3") + with open(f"{efuse_file}", "r") as r_file: + e_desc = yaml.safe_load(r_file) + super().__init__(e_desc) + + for i, efuse in enumerate(self.ALL_EFUSES): + if efuse.name in [ + "BLOCK_USR_DATA", + "BLOCK_KEY0", + "BLOCK_KEY1", + "BLOCK_KEY2", + "BLOCK_KEY3", + "BLOCK_KEY4", + "BLOCK_KEY5", + "BLOCK_SYS_DATA2", + ]: + if efuse.name == "BLOCK_USR_DATA": + efuse.bit_len = 256 + efuse.type = "bytes:32" + self.KEYBLOCKS.append(efuse) + self.ALL_EFUSES[i] = None + + elif efuse.category == "calibration": + self.BLOCK2_CALIBRATION_EFUSES.append(efuse) + self.ALL_EFUSES[i] = None + + f = Field() + f.name = "WAFER_VERSION_MINOR" + f.block = 0 + f.bit_len = 4 + f.type = f"uint:{f.bit_len}" + f.category = "identity" + f.class_type = "wafer" + f.description = "calc WAFER VERSION MINOR = WAFER_VERSION_MINOR_HI << 3 + WAFER_VERSION_MINOR_LO (read only)" + self.CALC.append(f) + + for efuse in self.ALL_EFUSES: + if efuse is not None: + self.EFUSES.append(efuse) + + self.ALL_EFUSES = [] diff --git a/espefuse/efuse/esp32s3beta2/operations.py b/espefuse/efuse/esp32s3beta2/operations.py index e94fa9cae..e17d773e1 100644 --- a/espefuse/efuse/esp32s3beta2/operations.py +++ b/espefuse/efuse/esp32s3beta2/operations.py @@ -18,6 +18,7 @@ from ..base_operations import ( add_common_commands, add_force_write_always, + add_show_sensitive_info_option, burn_bit, burn_block_data, burn_efuse, @@ -57,6 +58,7 @@ def add_commands(subparsers, efuses): ) protect_options(burn_key) add_force_write_always(burn_key) + add_show_sensitive_info_option(burn_key) burn_key.add_argument( "block", help="Key block to burn", @@ -107,6 +109,7 @@ def add_commands(subparsers, efuses): ) protect_options(burn_key_digest) add_force_write_always(burn_key_digest) + add_show_sensitive_info_option(burn_key_digest) burn_key_digest.add_argument( "block", help="Key block to burn", @@ -384,7 +387,13 @@ def burn_key(esp, efuses, args, digest=None): if efuses[block.key_purpose_name].need_reverse(keypurpose): revers_msg = "\tReversing byte order for AES-XTS hardware peripheral" data = data[::-1] - print("-> [%s]" % (util.hexify(data, " "))) + print( + "-> [{}]".format( + util.hexify(data, " ") + if args.show_sensitive_info + else " ".join(["??"] * len(data)) + ) + ) if revers_msg: print(revers_msg) if len(data) != num_bytes: diff --git a/espefuse/efuse/mem_definition_base.py b/espefuse/efuse/mem_definition_base.py index 1d1f4ebf6..21ae698b3 100644 --- a/espefuse/efuse/mem_definition_base.py +++ b/espefuse/efuse/mem_definition_base.py @@ -43,13 +43,129 @@ def get_blocks_for_keys(self): return list_of_names +class Field: + name = "" + block = 0 + word = None + pos = None + bit_len = 0 + alt_names = [] + type = "" + write_disable_bit = None + read_disable_bit = None + category = "config" + class_type = "" + description = "" + dictionary = None + + class EfuseFieldsBase(object): - NamedtupleField = namedtuple( - "Efuse", - "name category block word pos type write_disable_bit " - "read_disable_bit class_type description dictionary", - ) + def __init__(self, e_desc) -> None: + self.ALL_EFUSES = [] - @staticmethod - def get(tuple_field): - return EfuseFieldsBase.NamedtupleField._make(tuple_field) + def set_category_and_class_type(efuse, name): + def includes(name, names): + return any([word in name for word in names]) + + if name.startswith("SPI_PAD_CONFIG"): + efuse.category = "spi pad" + + elif "USB" in name: + efuse.category = "usb" + + elif "WDT" in name: + efuse.category = "wdt" + + elif "JTAG" in name: + efuse.category = "jtag" + + elif includes(name, ["FLASH", "FORCE_SEND_RESUME"]): + efuse.category = "flash" + + elif includes(name, ["VDD_SPI_", "XPD"]): + efuse.category = "vdd" + + elif "MAC" in name: + efuse.category = "MAC" + if name in ["MAC", "CUSTOM_MAC", "MAC_EXT"]: + efuse.class_type = "mac" + + elif includes( + name, + [ + "BLOCK_KEY0", + "BLOCK_KEY1", + "BLOCK_KEY2", + "BLOCK_KEY3", + "BLOCK_KEY4", + "BLOCK_KEY5", + "BLOCK1", + "BLOCK2", + ], + ): + efuse.category = "security" + efuse.class_type = "keyblock" + + elif includes( + name, + [ + "KEY", + "SECURE", + "DOWNLOAD", + "SPI_BOOT_CRYPT_CNT", + "KEY_PURPOSE", + "SECURE_VERSION", + "DPA", + "ECDSA", + "FLASH_CRYPT_CNT", + "ENCRYPT", + "DECRYPT", + "ABS_DONE", + ], + ): + efuse.category = "security" + if name.startswith("KEY_PURPOSE"): + efuse.class_type = "keypurpose" + elif includes( + name, ["FLASH_CRYPT_CNT", "SPI_BOOT_CRYPT_CNT", "SECURE_VERSION"] + ): + efuse.class_type = "bitcount" + + elif includes(name, ["VERSION", "WAFER", "_ID", "PKG", "PACKAGE", "REV"]): + efuse.category = "identity" + if name == "OPTIONAL_UNIQUE_ID": + efuse.class_type = "keyblock" + + elif includes(name, ["ADC", "LDO", "DBIAS", "_HVT", "CALIB", "OCODE"]): + efuse.category = "calibration" + if name == "ADC_VREF": + efuse.class_type = "vref" + return + if includes(name, ["ADC", "LDO", "DBIAS", "_HVT"]): + efuse.class_type = "adc_tp" + elif name == "TEMP_CALIB": + efuse.class_type = "t_sensor" + + for e_name in e_desc["EFUSES"]: + data_dict = e_desc["EFUSES"][e_name] + if data_dict["show"] == "y": + d = Field() + d.name = e_name + d.block = data_dict["blk"] + d.word = data_dict["word"] + d.pos = data_dict["pos"] + d.bit_len = data_dict["len"] + d.type = data_dict["type"] + d.write_disable_bit = data_dict["wr_dis"] + d.read_disable_bit = ( + [int(x) for x in data_dict["rd_dis"].split(" ")] + if isinstance(data_dict["rd_dis"], str) + else data_dict["rd_dis"] + ) + d.description = data_dict["desc"] + d.alt_names = data_dict["alt"].split(" ") if data_dict["alt"] else [] + d.dictionary = ( + eval(data_dict["dict"]) if data_dict["dict"] != "" else None + ) + set_category_and_class_type(d, e_name) + self.ALL_EFUSES.append(d) diff --git a/espefuse/efuse_defs/esp32.yaml b/espefuse/efuse_defs/esp32.yaml new file mode 100644 index 000000000..cfae99038 --- /dev/null +++ b/espefuse/efuse_defs/esp32.yaml @@ -0,0 +1,64 @@ +VER_NO: 369d2d860d34e777c0f7d545a7dfc3c4 +EFUSES: + WR_DIS : {show: y, blk : 0, word: 0, pos : 0, len : 16, start : 0, type : 'uint:16', wr_dis : 1, rd_dis: null, alt : '', dict : '', desc: Efuse write disable mask, rloc: 'EFUSE_BLK0_RDATA0_REG[15:0]', bloc: 'B0,B1'} + RD_DIS : {show: y, blk : 0, word: 0, pos: 16, len : 4, start : 16, type : 'uint:4', wr_dis : 0, rd_dis: null, alt : '', dict : '', desc: Disable reading from BlOCK1-3, rloc: 'EFUSE_BLK0_RDATA0_REG[19:16]', bloc: 'B2[3:0]'} + FLASH_CRYPT_CNT : {show: y, blk : 0, word: 0, pos: 20, len : 7, start : 20, type : 'uint:7', wr_dis : 2, rd_dis: null, alt : '', dict : '', desc: Flash encryption is enabled if this field has an odd number of bits set, rloc: 'EFUSE_BLK0_RDATA0_REG[26:20]', bloc: 'B2[7:4],B3[2:0]'} + UART_DOWNLOAD_DIS : {show: y, blk : 0, word: 0, pos: 27, len : 1, start : 27, type : bool, wr_dis : 2, rd_dis: null, alt : '', dict : '', desc: Disable UART download mode. Valid for ESP32 V3 and newer; only, rloc: 'EFUSE_BLK0_RDATA0_REG[27]', bloc: 'B3[3]'} + RESERVED_0_28 : {show: n, blk : 0, word: 0, pos: 28, len : 4, start : 28, type : 'uint:4', wr_dis: null, rd_dis: null, alt : '', dict : '', desc: reserved, rloc: 'EFUSE_BLK0_RDATA0_REG[31:28]', bloc: 'B3[7:4]'} + MAC : {show: y, blk : 0, word: 1, pos : 0, len : 48, start : 32, type : 'bytes:6', wr_dis : 3, rd_dis: null, alt : MAC_FACTORY, dict : '', desc: MAC address, rloc: EFUSE_BLK0_RDATA1_REG, bloc: 'B4,B5,B6,B7,B8,B9'} + MAC_CRC : {show: y, blk : 0, word: 2, pos: 16, len : 8, start : 80, type : 'uint:8', wr_dis : 3, rd_dis: null, alt : MAC_FACTORY_CRC, dict : '', desc: CRC8 for MAC address, rloc: 'EFUSE_BLK0_RDATA2_REG[23:16]', bloc: B10} + RESERVE_0_88 : {show: n, blk : 0, word: 2, pos: 24, len : 8, start : 88, type : 'uint:8', wr_dis: null, rd_dis: null, alt : '', dict : '', desc: Reserved; it was created by set_missed_fields_in_regs func, rloc: 'EFUSE_BLK0_RDATA2_REG[31:24]', bloc: B11} + DISABLE_APP_CPU : {show: y, blk : 0, word: 3, pos : 0, len : 1, start : 96, type : bool, wr_dis : 3, rd_dis: null, alt : CHIP_VER_DIS_APP_CPU, dict : '', desc: Disables APP CPU, rloc: 'EFUSE_BLK0_RDATA3_REG[0]', bloc: 'B12[0]'} + DISABLE_BT : {show: y, blk : 0, word: 3, pos : 1, len : 1, start : 97, type : bool, wr_dis : 3, rd_dis: null, alt : CHIP_VER_DIS_BT, dict : '', desc: Disables Bluetooth, rloc: 'EFUSE_BLK0_RDATA3_REG[1]', bloc: 'B12[1]'} + CHIP_PACKAGE_4BIT : {show: y, blk : 0, word: 3, pos : 2, len : 1, start : 98, type : bool, wr_dis: null, rd_dis: null, alt : CHIP_VER_PKG_4BIT, dict : '', desc: 'Chip package identifier #4bit', rloc: 'EFUSE_BLK0_RDATA3_REG[2]', bloc: 'B12[2]'} + DIS_CACHE : {show: y, blk : 0, word: 3, pos : 3, len : 1, start : 99, type : bool, wr_dis : 3, rd_dis: null, alt : CHIP_VER_DIS_CACHE, dict : '', desc: Disables cache, rloc: 'EFUSE_BLK0_RDATA3_REG[3]', bloc: 'B12[3]'} + SPI_PAD_CONFIG_HD : {show: y, blk : 0, word: 3, pos : 4, len : 5, start: 100, type : 'uint:5', wr_dis: null, rd_dis: null, alt : '', dict : '', desc: read for SPI_pad_config_hd, rloc: 'EFUSE_BLK0_RDATA3_REG[8:4]', bloc: 'B12[7:4],B13[0]'} + CHIP_PACKAGE : {show: y, blk : 0, word: 3, pos : 9, len : 3, start: 105, type : 'uint:3', wr_dis: null, rd_dis: null, alt : CHIP_VER_PKG, dict : '', desc: Chip package identifier, rloc: 'EFUSE_BLK0_RDATA3_REG[11:9]', bloc: 'B13[3:1]'} + CHIP_CPU_FREQ_LOW : {show: y, blk : 0, word: 3, pos: 12, len : 1, start: 108, type : bool, wr_dis: null, rd_dis: null, alt : '', dict : '', desc: If set alongside EFUSE_RD_CHIP_CPU_FREQ_RATED; the ESP32's max CPU frequency is rated for 160MHz. 240MHz otherwise, rloc: 'EFUSE_BLK0_RDATA3_REG[12]', bloc: 'B13[4]'} + CHIP_CPU_FREQ_RATED : {show: y, blk : 0, word: 3, pos: 13, len : 1, start: 109, type : bool, wr_dis: null, rd_dis: null, alt : '', dict : '', desc: If set; the ESP32's maximum CPU frequency has been rated, rloc: 'EFUSE_BLK0_RDATA3_REG[13]', bloc: 'B13[5]'} + BLK3_PART_RESERVE : {show: y, blk : 0, word: 3, pos: 14, len : 1, start: 110, type : bool, wr_dis : 10, rd_dis : 3, alt : '', dict : '', desc: BLOCK3 partially served for ADC calibration data, rloc: 'EFUSE_BLK0_RDATA3_REG[14]', bloc: 'B13[6]'} + CHIP_VER_REV1 : {show: y, blk : 0, word: 3, pos: 15, len : 1, start: 111, type : bool, wr_dis: null, rd_dis: null, alt : '', dict : '', desc: bit is set to 1 for rev1 silicon, rloc: 'EFUSE_BLK0_RDATA3_REG[15]', bloc: 'B13[7]'} + RESERVE_0_112 : {show: n, blk : 0, word: 3, pos: 16, len : 16, start: 112, type : 'uint:16', wr_dis: null, rd_dis: null, alt : '', dict : '', desc: Reserved; it was created by set_missed_fields_in_regs func, rloc: 'EFUSE_BLK0_RDATA3_REG[31:16]', bloc: 'B14,B15'} + CLK8M_FREQ : {show: y, blk : 0, word: 4, pos : 0, len : 8, start: 128, type : 'uint:8', wr_dis : 4, rd_dis: null, alt : CK8M_FREQ, dict : '', desc: 8MHz clock freq override, rloc: 'EFUSE_BLK0_RDATA4_REG[7:0]', bloc: B16} + ADC_VREF : {show: y, blk : 0, word: 4, pos : 8, len : 5, start: 136, type : 'uint:5', wr_dis : 4, rd_dis: null, alt : '', dict : '', desc: True ADC reference voltage, rloc: 'EFUSE_BLK0_RDATA4_REG[12:8]', bloc: 'B17[4:0]'} + RESERVE_0_141 : {show: n, blk : 0, word: 4, pos: 13, len : 1, start: 141, type : bool, wr_dis: null, rd_dis: null, alt : '', dict : '', desc: Reserved; it was created by set_missed_fields_in_regs func, rloc: 'EFUSE_BLK0_RDATA4_REG[13]', bloc: 'B17[5]'} + XPD_SDIO_REG : {show: y, blk : 0, word: 4, pos: 14, len : 1, start: 142, type : bool, wr_dis : 5, rd_dis: null, alt : '', dict : '', desc: read for XPD_SDIO_REG, rloc: 'EFUSE_BLK0_RDATA4_REG[14]', bloc: 'B17[6]'} + XPD_SDIO_TIEH : {show: y, blk : 0, word: 4, pos: 15, len : 1, start: 143, type : bool, wr_dis : 5, rd_dis: null, alt : SDIO_TIEH, dict: '{1: "3.3V", 0: "1.8V"}', desc: If XPD_SDIO_FORCE & XPD_SDIO_REG, rloc: 'EFUSE_BLK0_RDATA4_REG[15]', bloc: 'B17[7]'} + XPD_SDIO_FORCE : {show: y, blk : 0, word: 4, pos: 16, len : 1, start: 144, type : bool, wr_dis : 5, rd_dis: null, alt : SDIO_FORCE, dict : '', desc: Ignore MTDI pin (GPIO12) for VDD_SDIO on reset, rloc: 'EFUSE_BLK0_RDATA4_REG[16]', bloc: 'B18[0]'} + RESERVE_0_145 : {show: n, blk : 0, word: 4, pos: 17, len : 15, start: 145, type : 'uint:15', wr_dis: null, rd_dis: null, alt : '', dict : '', desc: Reserved; it was created by set_missed_fields_in_regs func, rloc: 'EFUSE_BLK0_RDATA4_REG[31:17]', bloc: 'B18[7:1],B19'} + SPI_PAD_CONFIG_CLK : {show: y, blk : 0, word: 5, pos : 0, len : 5, start: 160, type : 'uint:5', wr_dis : 6, rd_dis: null, alt : '', dict : '', desc: Override SD_CLK pad (GPIO6/SPICLK), rloc: 'EFUSE_BLK0_RDATA5_REG[4:0]', bloc: 'B20[4:0]'} + SPI_PAD_CONFIG_Q : {show: y, blk : 0, word: 5, pos : 5, len : 5, start: 165, type : 'uint:5', wr_dis : 6, rd_dis: null, alt : '', dict : '', desc: Override SD_DATA_0 pad (GPIO7/SPIQ), rloc: 'EFUSE_BLK0_RDATA5_REG[9:5]', bloc: 'B20[7:5],B21[1:0]'} + SPI_PAD_CONFIG_D : {show: y, blk : 0, word: 5, pos: 10, len : 5, start: 170, type : 'uint:5', wr_dis : 6, rd_dis: null, alt : '', dict : '', desc: Override SD_DATA_1 pad (GPIO8/SPID), rloc: 'EFUSE_BLK0_RDATA5_REG[14:10]', bloc: 'B21[6:2]'} + SPI_PAD_CONFIG_CS0 : {show: y, blk : 0, word: 5, pos: 15, len : 5, start: 175, type : 'uint:5', wr_dis : 6, rd_dis: null, alt : '', dict : '', desc: Override SD_CMD pad (GPIO11/SPICS0), rloc: 'EFUSE_BLK0_RDATA5_REG[19:15]', bloc: 'B21[7],B22[3:0]'} + CHIP_VER_REV2 : {show: y, blk : 0, word: 5, pos: 20, len : 1, start: 180, type : bool, wr_dis: null, rd_dis: null, alt : '', dict : '', desc: '', rloc: 'EFUSE_BLK0_RDATA5_REG[20]', bloc: 'B22[4]'} + RESERVE_0_181 : {show: n, blk : 0, word: 5, pos: 21, len : 1, start: 181, type : bool, wr_dis: null, rd_dis: null, alt : '', dict : '', desc: Reserved; it was created by set_missed_fields_in_regs func, rloc: 'EFUSE_BLK0_RDATA5_REG[21]', bloc: 'B22[5]'} + VOL_LEVEL_HP_INV : {show: y, blk : 0, word: 5, pos: 22, len : 2, start: 182, type : 'uint:2', wr_dis : 3, rd_dis: null, alt : '', dict : '', desc: 'This field stores the voltage level for CPU to run at 240 MHz; or for flash/PSRAM to run at 80 MHz.0x0: level 7; 0x1: level 6; 0x2: level 5; 0x3: level 4. (RO)', rloc: 'EFUSE_BLK0_RDATA5_REG[23:22]', bloc: 'B22[7:6]'} + WAFER_VERSION_MINOR : {show: y, blk : 0, word: 5, pos: 24, len : 2, start: 184, type : 'uint:2', wr_dis: null, rd_dis: null, alt : '', dict : '', desc: '', rloc: 'EFUSE_BLK0_RDATA5_REG[25:24]', bloc: 'B23[1:0]'} + RESERVE_0_186 : {show: n, blk : 0, word: 5, pos: 26, len : 2, start: 186, type : 'uint:2', wr_dis: null, rd_dis: null, alt : '', dict : '', desc: Reserved; it was created by set_missed_fields_in_regs func, rloc: 'EFUSE_BLK0_RDATA5_REG[27:26]', bloc: 'B23[3:2]'} + FLASH_CRYPT_CONFIG : {show: y, blk : 0, word: 5, pos: 28, len : 4, start: 188, type : 'uint:4', wr_dis : 10, rd_dis : 3, alt : ENCRYPT_CONFIG, dict : '', desc: Flash encryption config (key tweak bits), rloc: 'EFUSE_BLK0_RDATA5_REG[31:28]', bloc: 'B23[7:4]'} + CODING_SCHEME : {show: y, blk : 0, word: 6, pos : 0, len : 2, start: 192, type : 'uint:2', wr_dis : 10, rd_dis : 3, alt : '', dict: '{0: "NONE (BLK1-3 len=256 bits)", 1: "3/4 (BLK1-3 len=192 bits)", 2: "REPEAT (BLK1-3 len=128 bits) not supported", 3: "NONE (BLK1-3 len=256 bits)"}', desc: Efuse variable block length scheme, rloc: 'EFUSE_BLK0_RDATA6_REG[1:0]', bloc: 'B24[1:0]'} + CONSOLE_DEBUG_DISABLE: {show: y, blk : 0, word: 6, pos : 2, len : 1, start: 194, type : bool, wr_dis : 15, rd_dis: null, alt : '', dict : '', desc: Disable ROM BASIC interpreter fallback, rloc: 'EFUSE_BLK0_RDATA6_REG[2]', bloc: 'B24[2]'} + DISABLE_SDIO_HOST : {show: y, blk : 0, word: 6, pos : 3, len : 1, start: 195, type : bool, wr_dis: null, rd_dis: null, alt : '', dict : '', desc: '', rloc: 'EFUSE_BLK0_RDATA6_REG[3]', bloc: 'B24[3]'} + ABS_DONE_0 : {show: y, blk : 0, word: 6, pos : 4, len : 1, start: 196, type : bool, wr_dis : 12, rd_dis: null, alt : '', dict : '', desc: Secure boot V1 is enabled for bootloader image, rloc: 'EFUSE_BLK0_RDATA6_REG[4]', bloc: 'B24[4]'} + ABS_DONE_1 : {show: y, blk : 0, word: 6, pos : 5, len : 1, start: 197, type : bool, wr_dis : 13, rd_dis: null, alt : '', dict : '', desc: Secure boot V2 is enabled for bootloader image, rloc: 'EFUSE_BLK0_RDATA6_REG[5]', bloc: 'B24[5]'} + JTAG_DISABLE : {show: y, blk : 0, word: 6, pos : 6, len : 1, start: 198, type : bool, wr_dis : 14, rd_dis: null, alt : DISABLE_JTAG, dict : '', desc: Disable JTAG, rloc: 'EFUSE_BLK0_RDATA6_REG[6]', bloc: 'B24[6]'} + DISABLE_DL_ENCRYPT : {show: y, blk : 0, word: 6, pos : 7, len : 1, start: 199, type : bool, wr_dis : 15, rd_dis: null, alt : '', dict : '', desc: Disable flash encryption in UART bootloader, rloc: 'EFUSE_BLK0_RDATA6_REG[7]', bloc: 'B24[7]'} + DISABLE_DL_DECRYPT : {show: y, blk : 0, word: 6, pos : 8, len : 1, start: 200, type : bool, wr_dis : 15, rd_dis: null, alt : '', dict : '', desc: Disable flash decryption in UART bootloader, rloc: 'EFUSE_BLK0_RDATA6_REG[8]', bloc: 'B25[0]'} + DISABLE_DL_CACHE : {show: y, blk : 0, word: 6, pos : 9, len : 1, start: 201, type : bool, wr_dis : 15, rd_dis: null, alt : '', dict : '', desc: Disable flash cache in UART bootloader, rloc: 'EFUSE_BLK0_RDATA6_REG[9]', bloc: 'B25[1]'} + KEY_STATUS : {show: y, blk : 0, word: 6, pos: 10, len : 1, start: 202, type : bool, wr_dis : 10, rd_dis : 3, alt : '', dict : '', desc: Usage of efuse block 3 (reserved), rloc: 'EFUSE_BLK0_RDATA6_REG[10]', bloc: 'B25[2]'} + RESERVE_0_203 : {show: n, blk : 0, word: 6, pos: 11, len : 21, start: 203, type : 'uint:21', wr_dis: null, rd_dis: null, alt : '', dict : '', desc: Reserved; it was created by set_missed_fields_in_regs func, rloc: 'EFUSE_BLK0_RDATA6_REG[31:11]', bloc: 'B25[7:3],B26,B27'} + BLOCK1 : {show: y, blk : 1, word: 0, pos : 0, len: 256, start : 0, type: 'bytes:32', wr_dis : 7, rd_dis : 0, alt : ENCRYPT_FLASH_KEY, dict : '', desc: Flash encryption key, rloc: EFUSE_BLK1_RDATA0_REG, bloc: 'B0,B1,B2,B3,B4,B5,B6,B7,B8,B9,B10,B11,B12,B13,B14,B15,B16,B17,B18,B19,B20,B21,B22,B23,B24,B25,B26,B27,B28,B29,B30,B31'} + BLOCK2 : {show: y, blk : 2, word: 0, pos : 0, len: 256, start : 0, type: 'bytes:32', wr_dis : 8, rd_dis : 1, alt : SECURE_BOOT_KEY, dict : '', desc: Security boot key, rloc: EFUSE_BLK2_RDATA0_REG, bloc: 'B0,B1,B2,B3,B4,B5,B6,B7,B8,B9,B10,B11,B12,B13,B14,B15,B16,B17,B18,B19,B20,B21,B22,B23,B24,B25,B26,B27,B28,B29,B30,B31'} + CUSTOM_MAC_CRC : {show: y, blk : 3, word: 0, pos : 0, len : 8, start : 0, type : 'uint:8', wr_dis : 9, rd_dis : 2, alt : MAC_CUSTOM_CRC, dict : '', desc: CRC8 for custom MAC address, rloc: 'EFUSE_BLK3_RDATA0_REG[7:0]', bloc: B0} + CUSTOM_MAC : {show: y, blk : 3, word: 0, pos : 8, len : 48, start : 8, type : 'bytes:6', wr_dis : 9, rd_dis : 2, alt : MAC_CUSTOM, dict : '', desc: Custom MAC address, rloc: 'EFUSE_BLK3_RDATA0_REG[31:8]', bloc: 'B1,B2,B3,B4,B5,B6'} + RESERVED_3_56 : {show: n, blk : 3, word: 1, pos: 24, len : 8, start : 56, type : 'uint:8', wr_dis : 9, rd_dis : 2, alt : '', dict : '', desc: reserved, rloc: 'EFUSE_BLK3_RDATA1_REG[31:24]', bloc: B7} + BLK3_RESERVED_2 : {show: n, blk : 3, word: 2, pos : 0, len : 32, start : 64, type : 'uint:32', wr_dis : 9, rd_dis : 2, alt : '', dict : '', desc: read for BLOCK3, rloc: EFUSE_BLK3_RDATA2_REG, bloc: 'B8,B9,B10,B11'} + ADC1_TP_LOW : {show: y, blk : 3, word: 3, pos : 0, len : 7, start : 96, type : 'uint:7', wr_dis : 9, rd_dis : 2, alt : '', dict : '', desc: ADC1 Two Point calibration low point. Only valid if EFUSE_RD_BLK3_PART_RESERVE, rloc: 'EFUSE_BLK3_RDATA3_REG[6:0]', bloc: 'B12[6:0]'} + ADC1_TP_HIGH : {show: y, blk : 3, word: 3, pos : 7, len : 9, start: 103, type : 'uint:9', wr_dis : 9, rd_dis : 2, alt : '', dict : '', desc: ADC1 Two Point calibration high point. Only valid if EFUSE_RD_BLK3_PART_RESERVE, rloc: 'EFUSE_BLK3_RDATA3_REG[15:7]', bloc: 'B12[7],B13'} + ADC2_TP_LOW : {show: y, blk : 3, word: 3, pos: 16, len : 7, start: 112, type : 'uint:7', wr_dis : 9, rd_dis : 2, alt : '', dict : '', desc: ADC2 Two Point calibration low point. Only valid if EFUSE_RD_BLK3_PART_RESERVE, rloc: 'EFUSE_BLK3_RDATA3_REG[22:16]', bloc: 'B14[6:0]'} + ADC2_TP_HIGH : {show: y, blk : 3, word: 3, pos: 23, len : 9, start: 119, type : 'uint:9', wr_dis : 9, rd_dis : 2, alt : '', dict : '', desc: ADC2 Two Point calibration high point. Only valid if EFUSE_RD_BLK3_PART_RESERVE, rloc: 'EFUSE_BLK3_RDATA3_REG[31:23]', bloc: 'B14[7],B15'} + SECURE_VERSION : {show: y, blk : 3, word: 4, pos : 0, len : 32, start: 128, type : 'uint:32', wr_dis : 9, rd_dis : 2, alt : '', dict : '', desc: Secure version for anti-rollback, rloc: EFUSE_BLK3_RDATA4_REG, bloc: 'B16,B17,B18,B19'} + RESERVED_3_160 : {show: n, blk : 3, word: 5, pos : 0, len : 24, start: 160, type : 'uint:24', wr_dis : 9, rd_dis : 2, alt : '', dict : '', desc: reserved, rloc: 'EFUSE_BLK3_RDATA5_REG[23:0]', bloc: 'B20,B21,B22'} + MAC_VERSION : {show: y, blk : 3, word: 5, pos: 24, len : 8, start: 184, type : 'uint:8', wr_dis : 9, rd_dis : 2, alt : MAC_CUSTOM_VER, dict: '{1: "Custom MAC in BLOCK3"}', desc: Version of the MAC field, rloc: 'EFUSE_BLK3_RDATA5_REG[31:24]', bloc: B23} + BLK3_RESERVED_6 : {show: n, blk : 3, word: 6, pos : 0, len : 32, start: 192, type : 'uint:32', wr_dis : 9, rd_dis : 2, alt : '', dict : '', desc: read for BLOCK3, rloc: EFUSE_BLK3_RDATA6_REG, bloc: 'B24,B25,B26,B27'} + BLK3_RESERVED_7 : {show: n, blk : 3, word: 7, pos : 0, len : 32, start: 224, type : 'uint:32', wr_dis : 9, rd_dis : 2, alt : '', dict : '', desc: read for BLOCK3, rloc: EFUSE_BLK3_RDATA7_REG, bloc: 'B28,B29,B30,B31'} diff --git a/espefuse/efuse_defs/esp32c2.yaml b/espefuse/efuse_defs/esp32c2.yaml new file mode 100644 index 000000000..e89e354fc --- /dev/null +++ b/espefuse/efuse_defs/esp32c2.yaml @@ -0,0 +1,53 @@ +VER_NO: 897499b0349a608b895d467abbcf006b +EFUSES: + WR_DIS : {show: y, blk : 0, word: 0, pos : 0, len : 8, start : 0, type : 'uint:8', wr_dis: null, rd_dis: null, alt : '', dict : '', desc: Disable programming of individual eFuses, rloc: 'EFUSE_RD_WR_DIS_REG[7:0]', bloc: B0} + RESERVED_0_8 : {show: n, blk : 0, word: 0, pos : 8, len : 24, start : 8, type : 'uint:24', wr_dis: null, rd_dis: null, alt : '', dict : '', desc: '', rloc: 'EFUSE_RD_WR_DIS_REG[31:8]', bloc: 'B1,B2,B3'} + RD_DIS : {show: y, blk : 0, word: 1, pos : 0, len : 2, start : 32, type : 'uint:2', wr_dis : 0, rd_dis: null, alt : '', dict : '', desc: Disable reading from BlOCK3, rloc: 'EFUSE_RD_REPEAT_DATA0_REG[1:0]', bloc: 'B1[1:0]'} + WDT_DELAY_SEL : {show: y, blk : 0, word: 1, pos : 2, len : 2, start : 34, type : 'uint:2', wr_dis : 1, rd_dis: null, alt : '', dict: '{0: "40000", 1: "80000", 2: "160000", 3: "320000"}', desc: RTC watchdog timeout threshold; in unit of slow clock cycle, rloc: 'EFUSE_RD_REPEAT_DATA0_REG[3:2]', bloc: 'B1[3:2]'} + DIS_PAD_JTAG : {show: y, blk : 0, word: 1, pos : 4, len : 1, start : 36, type : bool, wr_dis : 1, rd_dis: null, alt : '', dict : '', desc: Set this bit to disable pad jtag, rloc: 'EFUSE_RD_REPEAT_DATA0_REG[4]', bloc: 'B1[4]'} + DIS_DOWNLOAD_ICACHE : {show: y, blk : 0, word: 1, pos : 5, len : 1, start : 37, type : bool, wr_dis : 1, rd_dis: null, alt : '', dict : '', desc: The bit be set to disable icache in download mode, rloc: 'EFUSE_RD_REPEAT_DATA0_REG[5]', bloc: 'B1[5]'} + DIS_DOWNLOAD_MANUAL_ENCRYPT: {show: y, blk : 0, word: 1, pos : 6, len : 1, start : 38, type : bool, wr_dis : 2, rd_dis: null, alt : '', dict : '', desc: The bit be set to disable manual encryption, rloc: 'EFUSE_RD_REPEAT_DATA0_REG[6]', bloc: 'B1[6]'} + SPI_BOOT_CRYPT_CNT : {show: y, blk : 0, word: 1, pos : 7, len : 3, start : 39, type : 'uint:3', wr_dis : 2, rd_dis: null, alt : '', dict: '{0: "Disable", 1: "Enable", 3: "Disable", 7: "Enable"}', desc: Enables flash encryption when 1 or 3 bits are set and disables otherwise, rloc: 'EFUSE_RD_REPEAT_DATA0_REG[9:7]', bloc: 'B1[7],B2[1:0]'} + XTS_KEY_LENGTH_256 : {show: y, blk : 0, word: 1, pos: 10, len : 1, start : 42, type : bool, wr_dis : 2, rd_dis: null, alt : '', dict: '{0: "128 bits key", 1: "256 bits key"}', desc: Flash encryption key length, rloc: 'EFUSE_RD_REPEAT_DATA0_REG[10]', bloc: 'B2[2]'} + UART_PRINT_CONTROL : {show: y, blk : 0, word: 1, pos: 11, len : 2, start : 43, type : 'uint:2', wr_dis : 3, rd_dis: null, alt : '', dict: '{0: "Enable", 1: "Enable when GPIO8 is low at reset", 2: "Enable when GPIO8 is high at reset", 3: "Disable"}', desc: Set the default UARTboot message output mode, rloc: 'EFUSE_RD_REPEAT_DATA0_REG[12:11]', bloc: 'B2[4:3]'} + FORCE_SEND_RESUME : {show: y, blk : 0, word: 1, pos: 13, len : 1, start : 45, type : bool, wr_dis : 3, rd_dis: null, alt : '', dict : '', desc: Set this bit to force ROM code to send a resume command during SPI boot, rloc: 'EFUSE_RD_REPEAT_DATA0_REG[13]', bloc: 'B2[5]'} + DIS_DOWNLOAD_MODE : {show: y, blk : 0, word: 1, pos: 14, len : 1, start : 46, type : bool, wr_dis : 3, rd_dis: null, alt : '', dict : '', desc: 'Set this bit to disable download mode (boot_mode[3:0] = 0; 1; 2; 4; 5; 6; 7)', rloc: 'EFUSE_RD_REPEAT_DATA0_REG[14]', bloc: 'B2[6]'} + DIS_DIRECT_BOOT : {show: y, blk : 0, word: 1, pos: 15, len : 1, start : 47, type : bool, wr_dis : 3, rd_dis: null, alt : '', dict : '', desc: This bit set means disable direct_boot mode, rloc: 'EFUSE_RD_REPEAT_DATA0_REG[15]', bloc: 'B2[7]'} + ENABLE_SECURITY_DOWNLOAD : {show: y, blk : 0, word: 1, pos: 16, len : 1, start : 48, type : bool, wr_dis : 3, rd_dis: null, alt : '', dict : '', desc: Set this bit to enable secure UART download mode, rloc: 'EFUSE_RD_REPEAT_DATA0_REG[16]', bloc: 'B3[0]'} + FLASH_TPUW : {show: y, blk : 0, word: 1, pos: 17, len : 4, start : 49, type : 'uint:4', wr_dis : 3, rd_dis: null, alt : '', dict : '', desc: Configures flash waiting time after power-up; in unit of ms. If the value is less than 15; the waiting time is the configurable value. Otherwise; the waiting time is twice the configurable value, rloc: 'EFUSE_RD_REPEAT_DATA0_REG[20:17]', bloc: 'B3[4:1]'} + SECURE_BOOT_EN : {show: y, blk : 0, word: 1, pos: 21, len : 1, start : 53, type : bool, wr_dis : 2, rd_dis: null, alt : '', dict : '', desc: The bit be set to enable secure boot, rloc: 'EFUSE_RD_REPEAT_DATA0_REG[21]', bloc: 'B3[5]'} + SECURE_VERSION : {show: y, blk : 0, word: 1, pos: 22, len : 4, start : 54, type : 'uint:4', wr_dis : 4, rd_dis: null, alt : '', dict : '', desc: Secure version for anti-rollback, rloc: 'EFUSE_RD_REPEAT_DATA0_REG[25:22]', bloc: 'B3[7:6],B4[1:0]'} + CUSTOM_MAC_USED : {show: y, blk : 0, word: 1, pos: 26, len : 1, start : 58, type : bool, wr_dis : 4, rd_dis: null, alt : ENABLE_CUSTOM_MAC, dict : '', desc: True if MAC_CUSTOM is burned, rloc: 'EFUSE_RD_REPEAT_DATA0_REG[26]', bloc: 'B4[2]'} + DISABLE_WAFER_VERSION_MAJOR: {show: y, blk : 0, word: 1, pos: 27, len : 1, start : 59, type : bool, wr_dis : 4, rd_dis: null, alt : '', dict : '', desc: Disables check of wafer version major, rloc: 'EFUSE_RD_REPEAT_DATA0_REG[27]', bloc: 'B4[3]'} + DISABLE_BLK_VERSION_MAJOR : {show: y, blk : 0, word: 1, pos: 28, len : 1, start : 60, type : bool, wr_dis : 4, rd_dis: null, alt : '', dict : '', desc: Disables check of blk version major, rloc: 'EFUSE_RD_REPEAT_DATA0_REG[28]', bloc: 'B4[4]'} + RESERVED_0_61 : {show: n, blk : 0, word: 1, pos: 29, len : 3, start : 61, type : 'uint:3', wr_dis: null, rd_dis: null, alt : '', dict : '', desc: reserved, rloc: 'EFUSE_RD_REPEAT_DATA0_REG[31:29]', bloc: 'B4[7:5]'} + CUSTOM_MAC : {show: y, blk : 1, word: 0, pos : 0, len : 48, start : 0, type : 'bytes:6', wr_dis : 5, rd_dis: null, alt: MAC_CUSTOM USER_DATA_MAC_CUSTOM, dict : '', desc: Custom MAC address, rloc: EFUSE_RD_BLK1_DATA0_REG, bloc: 'B0,B1,B2,B3,B4,B5'} + RESERVED_1_48 : {show: n, blk : 1, word: 1, pos: 16, len : 16, start : 48, type : 'uint:16', wr_dis : 5, rd_dis: null, alt : '', dict : '', desc: reserved, rloc: 'EFUSE_RD_BLK1_DATA1_REG[31:16]', bloc: 'B6,B7'} + SYSTEM_DATA2 : {show: n, blk : 1, word: 2, pos : 0, len : 24, start : 64, type : 'uint:24', wr_dis : 5, rd_dis: null, alt : '', dict : '', desc: 'Stores the bits [64:87] of system data', rloc: 'EFUSE_RD_BLK1_DATA2_REG[23:0]', bloc: 'B8,B9,B10'} + MAC : {show: y, blk : 2, word: 0, pos : 0, len : 48, start : 0, type : 'bytes:6', wr_dis : 6, rd_dis: null, alt : MAC_FACTORY, dict : '', desc: MAC address, rloc: EFUSE_RD_BLK2_DATA0_REG, bloc: 'B0,B1,B2,B3,B4,B5'} + WAFER_VERSION_MINOR : {show: y, blk : 2, word: 1, pos: 16, len : 4, start : 48, type : 'uint:4', wr_dis : 6, rd_dis: null, alt : '', dict : '', desc: WAFER_VERSION_MINOR, rloc: 'EFUSE_RD_BLK2_DATA1_REG[19:16]', bloc: 'B6[3:0]'} + WAFER_VERSION_MAJOR : {show: y, blk : 2, word: 1, pos: 20, len : 2, start : 52, type : 'uint:2', wr_dis : 6, rd_dis: null, alt : '', dict : '', desc: WAFER_VERSION_MAJOR, rloc: 'EFUSE_RD_BLK2_DATA1_REG[21:20]', bloc: 'B6[5:4]'} + PKG_VERSION : {show: y, blk : 2, word: 1, pos: 22, len : 3, start : 54, type : 'uint:3', wr_dis : 6, rd_dis: null, alt : '', dict : '', desc: EFUSE_PKG_VERSION, rloc: 'EFUSE_RD_BLK2_DATA1_REG[24:22]', bloc: 'B6[7:6],B7[0]'} + BLK_VERSION_MINOR : {show: y, blk : 2, word: 1, pos: 25, len : 3, start : 57, type : 'uint:3', wr_dis : 6, rd_dis: null, alt : '', dict: '{0: "No calib", 1: "With calib"}', desc: Minor version of BLOCK2, rloc: 'EFUSE_RD_BLK2_DATA1_REG[27:25]', bloc: 'B7[3:1]'} + BLK_VERSION_MAJOR : {show: y, blk : 2, word: 1, pos: 28, len : 2, start : 60, type : 'uint:2', wr_dis : 6, rd_dis: null, alt : '', dict : '', desc: Major version of BLOCK2, rloc: 'EFUSE_RD_BLK2_DATA1_REG[29:28]', bloc: 'B7[5:4]'} + OCODE : {show: y, blk : 2, word: 1, pos: 30, len : 7, start : 62, type : 'uint:7', wr_dis : 6, rd_dis: null, alt : '', dict : '', desc: OCode, rloc: 'EFUSE_RD_BLK2_DATA1_REG[31:30]', bloc: 'B7[7:6],B8[4:0]'} + TEMP_CALIB : {show: y, blk : 2, word: 2, pos : 5, len : 9, start : 69, type : 'uint:9', wr_dis : 6, rd_dis: null, alt : '', dict : '', desc: Temperature calibration data, rloc: 'EFUSE_RD_BLK2_DATA2_REG[13:5]', bloc: 'B8[7:5],B9[5:0]'} + ADC1_INIT_CODE_ATTEN0 : {show: y, blk : 2, word: 2, pos: 14, len : 8, start : 78, type : 'uint:8', wr_dis : 6, rd_dis: null, alt : '', dict : '', desc: ADC1 init code at atten0, rloc: 'EFUSE_RD_BLK2_DATA2_REG[21:14]', bloc: 'B9[7:6],B10[5:0]'} + ADC1_INIT_CODE_ATTEN3 : {show: y, blk : 2, word: 2, pos: 22, len : 5, start : 86, type : 'uint:5', wr_dis : 6, rd_dis: null, alt : '', dict : '', desc: ADC1 init code at atten3, rloc: 'EFUSE_RD_BLK2_DATA2_REG[26:22]', bloc: 'B10[7:6],B11[2:0]'} + ADC1_CAL_VOL_ATTEN0 : {show: y, blk : 2, word: 2, pos: 27, len : 8, start : 91, type : 'uint:8', wr_dis : 6, rd_dis: null, alt : '', dict : '', desc: ADC1 calibration voltage at atten0, rloc: 'EFUSE_RD_BLK2_DATA2_REG[31:27]', bloc: 'B11[7:3],B12[2:0]'} + ADC1_CAL_VOL_ATTEN3 : {show: y, blk : 2, word: 3, pos : 3, len : 6, start : 99, type : 'uint:6', wr_dis : 6, rd_dis: null, alt : '', dict : '', desc: ADC1 calibration voltage at atten3, rloc: 'EFUSE_RD_BLK2_DATA3_REG[8:3]', bloc: 'B12[7:3],B13[0]'} + DIG_DBIAS_HVT : {show: y, blk : 2, word: 3, pos : 9, len : 5, start: 105, type : 'uint:5', wr_dis : 6, rd_dis: null, alt : '', dict : '', desc: BLOCK2 digital dbias when hvt, rloc: 'EFUSE_RD_BLK2_DATA3_REG[13:9]', bloc: 'B13[5:1]'} + DIG_LDO_SLP_DBIAS2 : {show: y, blk : 2, word: 3, pos: 14, len : 7, start: 110, type : 'uint:7', wr_dis : 6, rd_dis: null, alt : '', dict : '', desc: BLOCK2 DIG_LDO_DBG0_DBIAS2, rloc: 'EFUSE_RD_BLK2_DATA3_REG[20:14]', bloc: 'B13[7:6],B14[4:0]'} + DIG_LDO_SLP_DBIAS26 : {show: y, blk : 2, word: 3, pos: 21, len : 8, start: 117, type : 'uint:8', wr_dis : 6, rd_dis: null, alt : '', dict : '', desc: BLOCK2 DIG_LDO_DBG0_DBIAS26, rloc: 'EFUSE_RD_BLK2_DATA3_REG[28:21]', bloc: 'B14[7:5],B15[4:0]'} + DIG_LDO_ACT_DBIAS26 : {show: y, blk : 2, word: 3, pos: 29, len : 6, start: 125, type : 'uint:6', wr_dis : 6, rd_dis: null, alt : '', dict : '', desc: BLOCK2 DIG_LDO_ACT_DBIAS26, rloc: 'EFUSE_RD_BLK2_DATA3_REG[31:29]', bloc: 'B15[7:5],B16[2:0]'} + DIG_LDO_ACT_STEPD10 : {show: y, blk : 2, word: 4, pos : 3, len : 4, start: 131, type : 'uint:4', wr_dis : 6, rd_dis: null, alt : '', dict : '', desc: BLOCK2 DIG_LDO_ACT_STEPD10, rloc: 'EFUSE_RD_BLK2_DATA4_REG[6:3]', bloc: 'B16[6:3]'} + RTC_LDO_SLP_DBIAS13 : {show: y, blk : 2, word: 4, pos : 7, len : 7, start: 135, type : 'uint:7', wr_dis : 6, rd_dis: null, alt : '', dict : '', desc: BLOCK2 DIG_LDO_SLP_DBIAS13, rloc: 'EFUSE_RD_BLK2_DATA4_REG[13:7]', bloc: 'B16[7],B17[5:0]'} + RTC_LDO_SLP_DBIAS29 : {show: y, blk : 2, word: 4, pos: 14, len : 9, start: 142, type : 'uint:9', wr_dis : 6, rd_dis: null, alt : '', dict : '', desc: BLOCK2 DIG_LDO_SLP_DBIAS29, rloc: 'EFUSE_RD_BLK2_DATA4_REG[22:14]', bloc: 'B17[7:6],B18[6:0]'} + RTC_LDO_SLP_DBIAS31 : {show: y, blk : 2, word: 4, pos: 23, len : 6, start: 151, type : 'uint:6', wr_dis : 6, rd_dis: null, alt : '', dict : '', desc: BLOCK2 DIG_LDO_SLP_DBIAS31, rloc: 'EFUSE_RD_BLK2_DATA4_REG[28:23]', bloc: 'B18[7],B19[4:0]'} + RTC_LDO_ACT_DBIAS31 : {show: y, blk : 2, word: 4, pos: 29, len : 6, start: 157, type : 'uint:6', wr_dis : 6, rd_dis: null, alt : '', dict : '', desc: BLOCK2 DIG_LDO_ACT_DBIAS31, rloc: 'EFUSE_RD_BLK2_DATA4_REG[31:29]', bloc: 'B19[7:5],B20[2:0]'} + RTC_LDO_ACT_DBIAS13 : {show: y, blk : 2, word: 5, pos : 3, len : 8, start: 163, type : 'uint:8', wr_dis : 6, rd_dis: null, alt : '', dict : '', desc: BLOCK2 DIG_LDO_ACT_DBIAS13, rloc: 'EFUSE_RD_BLK2_DATA5_REG[10:3]', bloc: 'B20[7:3],B21[2:0]'} + RESERVED_2_171 : {show: n, blk : 2, word: 5, pos: 11, len : 21, start: 171, type : 'uint:21', wr_dis : 6, rd_dis: null, alt : '', dict : '', desc: reserved, rloc: 'EFUSE_RD_BLK2_DATA5_REG[31:11]', bloc: 'B21[7:3],B22,B23'} + ADC_CALIBRATION_3 : {show: y, blk : 2, word: 6, pos : 0, len : 11, start: 192, type : 'uint:11', wr_dis : 6, rd_dis: null, alt : '', dict : '', desc: 'Store the bit [86:96] of ADC calibration data', rloc: 'EFUSE_RD_BLK2_DATA6_REG[10:0]', bloc: 'B24,B25[2:0]'} + BLK2_RESERVED_DATA_0 : {show: n, blk : 2, word: 6, pos: 11, len : 21, start: 203, type : 'uint:21', wr_dis : 6, rd_dis: null, alt : '', dict : '', desc: 'Store the bit [0:20] of block2 reserved data', rloc: 'EFUSE_RD_BLK2_DATA6_REG[31:11]', bloc: 'B25[7:3],B26,B27'} + BLK2_RESERVED_DATA_1 : {show: n, blk : 2, word: 7, pos : 0, len : 32, start: 224, type : 'uint:32', wr_dis : 6, rd_dis: null, alt : '', dict : '', desc: 'Store the bit [21:52] of block2 reserved data', rloc: EFUSE_RD_BLK2_DATA7_REG, bloc: 'B28,B29,B30,B31'} + BLOCK_KEY0 : {show: y, blk : 3, word: 0, pos : 0, len: 256, start : 0, type: 'bytes:32', wr_dis : 7, rd_dis : 0 1, alt : KEY0, dict : '', desc: BLOCK_KEY0 - 256-bits. 256-bit key of Flash Encryption, rloc: EFUSE_RD_BLK3_DATA0_REG, bloc: 'B0,B1,B2,B3,B4,B5,B6,B7,B8,B9,B10,B11,B12,B13,B14,B15,B16,B17,B18,B19,B20,B21,B22,B23,B24,B25,B26,B27,B28,B29,B30,B31'} diff --git a/espefuse/efuse_defs/esp32c3.yaml b/espefuse/efuse_defs/esp32c3.yaml new file mode 100644 index 000000000..035f30c5b --- /dev/null +++ b/espefuse/efuse_defs/esp32c3.yaml @@ -0,0 +1,112 @@ +VER_NO: 4622cf9245401eca0eb1df8122449a6d +EFUSES: + WR_DIS : {show: y, blk : 0, word: 0, pos : 0, len : 32, start : 0, type : 'uint:32', wr_dis: null, rd_dis: null, alt : '', dict : '', desc: Disable programming of individual eFuses, rloc: EFUSE_RD_WR_DIS_REG, bloc: 'B0,B1,B2,B3'} + RD_DIS : {show: y, blk : 0, word: 1, pos : 0, len : 7, start : 32, type : 'uint:7', wr_dis : 0, rd_dis: null, alt : '', dict : '', desc: Disable reading from BlOCK4-10, rloc: 'EFUSE_RD_REPEAT_DATA0_REG[6:0]', bloc: 'B4[6:0]'} + DIS_RTC_RAM_BOOT : {show: n, blk : 0, word: 1, pos : 7, len : 1, start : 39, type : bool, wr_dis : 1, rd_dis: null, alt : '', dict : '', desc: Set this bit to disable boot from RTC RAM, rloc: 'EFUSE_RD_REPEAT_DATA0_REG[7]', bloc: 'B4[7]'} + DIS_ICACHE : {show: y, blk : 0, word: 1, pos : 8, len : 1, start : 40, type : bool, wr_dis : 2, rd_dis: null, alt : '', dict : '', desc: Set this bit to disable Icache, rloc: 'EFUSE_RD_REPEAT_DATA0_REG[8]', bloc: 'B5[0]'} + DIS_USB_JTAG : {show: y, blk : 0, word: 1, pos : 9, len : 1, start : 41, type : bool, wr_dis : 2, rd_dis: null, alt : '', dict : '', desc: Set this bit to disable function of usb switch to jtag in module of usb device, rloc: 'EFUSE_RD_REPEAT_DATA0_REG[9]', bloc: 'B5[1]'} + DIS_DOWNLOAD_ICACHE : {show: y, blk : 0, word: 1, pos: 10, len : 1, start : 42, type : bool, wr_dis : 2, rd_dis: null, alt : '', dict : '', desc: 'Set this bit to disable Icache in download mode (boot_mode[3:0] is 0; 1; 2; 3; 6; 7)', rloc: 'EFUSE_RD_REPEAT_DATA0_REG[10]', bloc: 'B5[2]'} + DIS_USB_SERIAL_JTAG : {show: y, blk : 0, word: 1, pos: 11, len : 1, start : 43, type : bool, wr_dis : 2, rd_dis: null, alt : DIS_USB_DEVICE, dict: '{0: "Enable", 1: "Disable"}', desc: USB-Serial-JTAG, rloc: 'EFUSE_RD_REPEAT_DATA0_REG[11]', bloc: 'B5[3]'} + DIS_FORCE_DOWNLOAD : {show: y, blk : 0, word: 1, pos: 12, len : 1, start : 44, type : bool, wr_dis : 2, rd_dis: null, alt : '', dict : '', desc: Set this bit to disable the function that forces chip into download mode, rloc: 'EFUSE_RD_REPEAT_DATA0_REG[12]', bloc: 'B5[4]'} + RPT4_RESERVED6 : {show: n, blk : 0, word: 1, pos: 13, len : 1, start : 45, type : bool, wr_dis: null, rd_dis: null, alt : '', dict : '', desc: Reserved (used for four backups method), rloc: 'EFUSE_RD_REPEAT_DATA0_REG[13]', bloc: 'B5[5]'} + DIS_TWAI : {show: y, blk : 0, word: 1, pos: 14, len : 1, start : 46, type : bool, wr_dis : 2, rd_dis: null, alt : DIS_CAN, dict : '', desc: Set this bit to disable CAN function, rloc: 'EFUSE_RD_REPEAT_DATA0_REG[14]', bloc: 'B5[6]'} + JTAG_SEL_ENABLE : {show: y, blk : 0, word: 1, pos: 15, len : 1, start : 47, type : bool, wr_dis : 2, rd_dis: null, alt : '', dict : '', desc: Set this bit to enable selection between usb_to_jtag and pad_to_jtag through strapping gpio10 when both reg_dis_usb_jtag and reg_dis_pad_jtag are equal to 0, rloc: 'EFUSE_RD_REPEAT_DATA0_REG[15]', bloc: 'B5[7]'} + SOFT_DIS_JTAG : {show: y, blk : 0, word: 1, pos: 16, len : 3, start : 48, type : 'uint:3', wr_dis : 31, rd_dis: null, alt : '', dict : '', desc: Set these bits to disable JTAG in the soft way (odd number 1 means disable ). JTAG can be enabled in HMAC module, rloc: 'EFUSE_RD_REPEAT_DATA0_REG[18:16]', bloc: 'B6[2:0]'} + DIS_PAD_JTAG : {show: y, blk : 0, word: 1, pos: 19, len : 1, start : 51, type : bool, wr_dis : 2, rd_dis: null, alt : '', dict : '', desc: Set this bit to disable JTAG in the hard way. JTAG is disabled permanently, rloc: 'EFUSE_RD_REPEAT_DATA0_REG[19]', bloc: 'B6[3]'} + DIS_DOWNLOAD_MANUAL_ENCRYPT : {show: y, blk : 0, word: 1, pos: 20, len : 1, start : 52, type : bool, wr_dis : 2, rd_dis: null, alt : '', dict : '', desc: Set this bit to disable flash encryption when in download boot modes, rloc: 'EFUSE_RD_REPEAT_DATA0_REG[20]', bloc: 'B6[4]'} + USB_DREFH : {show: n, blk : 0, word: 1, pos: 21, len : 2, start : 53, type : 'uint:2', wr_dis : 30, rd_dis: null, alt : '', dict : '', desc: Controls single-end input threshold vrefh; 1.76 V to 2 V with step of 80 mV; stored in eFuse, rloc: 'EFUSE_RD_REPEAT_DATA0_REG[22:21]', bloc: 'B6[6:5]'} + USB_DREFL : {show: n, blk : 0, word: 1, pos: 23, len : 2, start : 55, type : 'uint:2', wr_dis : 30, rd_dis: null, alt : '', dict : '', desc: Controls single-end input threshold vrefl; 0.8 V to 1.04 V with step of 80 mV; stored in eFuse, rloc: 'EFUSE_RD_REPEAT_DATA0_REG[24:23]', bloc: 'B6[7],B7[0]'} + USB_EXCHG_PINS : {show: y, blk : 0, word: 1, pos: 25, len : 1, start : 57, type : bool, wr_dis : 30, rd_dis: null, alt : '', dict : '', desc: Set this bit to exchange USB D+ and D- pins, rloc: 'EFUSE_RD_REPEAT_DATA0_REG[25]', bloc: 'B7[1]'} + VDD_SPI_AS_GPIO : {show: y, blk : 0, word: 1, pos: 26, len : 1, start : 58, type : bool, wr_dis : 30, rd_dis: null, alt : '', dict : '', desc: Set this bit to vdd spi pin function as gpio, rloc: 'EFUSE_RD_REPEAT_DATA0_REG[26]', bloc: 'B7[2]'} + BTLC_GPIO_ENABLE : {show: n, blk : 0, word: 1, pos: 27, len : 2, start : 59, type : 'uint:2', wr_dis : 30, rd_dis: null, alt : '', dict : '', desc: Enable btlc gpio, rloc: 'EFUSE_RD_REPEAT_DATA0_REG[28:27]', bloc: 'B7[4:3]'} + POWERGLITCH_EN : {show: n, blk : 0, word: 1, pos: 29, len : 1, start : 61, type : bool, wr_dis : 3, rd_dis: null, alt : '', dict : '', desc: Set this bit to enable power glitch function, rloc: 'EFUSE_RD_REPEAT_DATA0_REG[29]', bloc: 'B7[5]'} + POWER_GLITCH_DSENSE : {show: n, blk : 0, word: 1, pos: 30, len : 2, start : 62, type : 'uint:2', wr_dis : 3, rd_dis: null, alt : '', dict : '', desc: Sample delay configuration of power glitch, rloc: 'EFUSE_RD_REPEAT_DATA0_REG[31:30]', bloc: 'B7[7:6]'} + RPT4_RESERVED2 : {show: n, blk : 0, word: 2, pos : 0, len : 16, start : 64, type : 'uint:16', wr_dis: null, rd_dis: null, alt : '', dict : '', desc: Reserved (used for four backups method), rloc: 'EFUSE_RD_REPEAT_DATA1_REG[15:0]', bloc: 'B8,B9'} + WDT_DELAY_SEL : {show: y, blk : 0, word: 2, pos: 16, len : 2, start : 80, type : 'uint:2', wr_dis : 3, rd_dis: null, alt : '', dict: '{0: "40000", 1: "80000", 2: "160000", 3: "320000"}', desc: RTC watchdog timeout threshold; in unit of slow clock cycle, rloc: 'EFUSE_RD_REPEAT_DATA1_REG[17:16]', bloc: 'B10[1:0]'} + SPI_BOOT_CRYPT_CNT : {show: y, blk : 0, word: 2, pos: 18, len : 3, start : 82, type : 'uint:3', wr_dis : 4, rd_dis: null, alt : '', dict: '{0: "Disable", 1: "Enable", 3: "Disable", 7: "Enable"}', desc: Enables flash encryption when 1 or 3 bits are set and disables otherwise, rloc: 'EFUSE_RD_REPEAT_DATA1_REG[20:18]', bloc: 'B10[4:2]'} + SECURE_BOOT_KEY_REVOKE0 : {show: y, blk : 0, word: 2, pos: 21, len : 1, start : 85, type : bool, wr_dis : 5, rd_dis: null, alt : '', dict : '', desc: Revoke 1st secure boot key, rloc: 'EFUSE_RD_REPEAT_DATA1_REG[21]', bloc: 'B10[5]'} + SECURE_BOOT_KEY_REVOKE1 : {show: y, blk : 0, word: 2, pos: 22, len : 1, start : 86, type : bool, wr_dis : 6, rd_dis: null, alt : '', dict : '', desc: Revoke 2nd secure boot key, rloc: 'EFUSE_RD_REPEAT_DATA1_REG[22]', bloc: 'B10[6]'} + SECURE_BOOT_KEY_REVOKE2 : {show: y, blk : 0, word: 2, pos: 23, len : 1, start : 87, type : bool, wr_dis : 7, rd_dis: null, alt : '', dict : '', desc: Revoke 3rd secure boot key, rloc: 'EFUSE_RD_REPEAT_DATA1_REG[23]', bloc: 'B10[7]'} + KEY_PURPOSE_0 : {show: y, blk : 0, word: 2, pos: 24, len : 4, start : 88, type : 'uint:4', wr_dis : 8, rd_dis: null, alt : KEY0_PURPOSE, dict : '', desc: Purpose of Key0, rloc: 'EFUSE_RD_REPEAT_DATA1_REG[27:24]', bloc: 'B11[3:0]'} + KEY_PURPOSE_1 : {show: y, blk : 0, word: 2, pos: 28, len : 4, start : 92, type : 'uint:4', wr_dis : 9, rd_dis: null, alt : KEY1_PURPOSE, dict : '', desc: Purpose of Key1, rloc: 'EFUSE_RD_REPEAT_DATA1_REG[31:28]', bloc: 'B11[7:4]'} + KEY_PURPOSE_2 : {show: y, blk : 0, word: 3, pos : 0, len : 4, start : 96, type : 'uint:4', wr_dis : 10, rd_dis: null, alt : KEY2_PURPOSE, dict : '', desc: Purpose of Key2, rloc: 'EFUSE_RD_REPEAT_DATA2_REG[3:0]', bloc: 'B12[3:0]'} + KEY_PURPOSE_3 : {show: y, blk : 0, word: 3, pos : 4, len : 4, start: 100, type : 'uint:4', wr_dis : 11, rd_dis: null, alt : KEY3_PURPOSE, dict : '', desc: Purpose of Key3, rloc: 'EFUSE_RD_REPEAT_DATA2_REG[7:4]', bloc: 'B12[7:4]'} + KEY_PURPOSE_4 : {show: y, blk : 0, word: 3, pos : 8, len : 4, start: 104, type : 'uint:4', wr_dis : 12, rd_dis: null, alt : KEY4_PURPOSE, dict : '', desc: Purpose of Key4, rloc: 'EFUSE_RD_REPEAT_DATA2_REG[11:8]', bloc: 'B13[3:0]'} + KEY_PURPOSE_5 : {show: y, blk : 0, word: 3, pos: 12, len : 4, start: 108, type : 'uint:4', wr_dis : 13, rd_dis: null, alt : KEY5_PURPOSE, dict : '', desc: Purpose of Key5, rloc: 'EFUSE_RD_REPEAT_DATA2_REG[15:12]', bloc: 'B13[7:4]'} + RPT4_RESERVED3 : {show: n, blk : 0, word: 3, pos: 16, len : 4, start: 112, type : 'uint:4', wr_dis: null, rd_dis: null, alt : '', dict : '', desc: Reserved (used for four backups method), rloc: 'EFUSE_RD_REPEAT_DATA2_REG[19:16]', bloc: 'B14[3:0]'} + SECURE_BOOT_EN : {show: y, blk : 0, word: 3, pos: 20, len : 1, start: 116, type : bool, wr_dis : 15, rd_dis: null, alt : '', dict : '', desc: Set this bit to enable secure boot, rloc: 'EFUSE_RD_REPEAT_DATA2_REG[20]', bloc: 'B14[4]'} + SECURE_BOOT_AGGRESSIVE_REVOKE : {show: y, blk : 0, word: 3, pos: 21, len : 1, start: 117, type : bool, wr_dis : 16, rd_dis: null, alt : '', dict : '', desc: Set this bit to enable revoking aggressive secure boot, rloc: 'EFUSE_RD_REPEAT_DATA2_REG[21]', bloc: 'B14[5]'} + RPT4_RESERVED0 : {show: n, blk : 0, word: 3, pos: 22, len : 6, start: 118, type : 'uint:6', wr_dis: null, rd_dis: null, alt : '', dict : '', desc: Reserved (used for four backups method), rloc: 'EFUSE_RD_REPEAT_DATA2_REG[27:22]', bloc: 'B14[7:6],B15[3:0]'} + FLASH_TPUW : {show: y, blk : 0, word: 3, pos: 28, len : 4, start: 124, type : 'uint:4', wr_dis : 18, rd_dis: null, alt : '', dict : '', desc: Configures flash waiting time after power-up; in unit of ms. If the value is less than 15; the waiting time is the configurable value; Otherwise; the waiting time is twice the configurable value, rloc: 'EFUSE_RD_REPEAT_DATA2_REG[31:28]', bloc: 'B15[7:4]'} + DIS_DOWNLOAD_MODE : {show: y, blk : 0, word: 4, pos : 0, len : 1, start: 128, type : bool, wr_dis : 18, rd_dis: null, alt : '', dict : '', desc: 'Set this bit to disable download mode (boot_mode[3:0] = 0; 1; 2; 3; 6; 7)', rloc: 'EFUSE_RD_REPEAT_DATA3_REG[0]', bloc: 'B16[0]'} + DIS_DIRECT_BOOT : {show: y, blk : 0, word: 4, pos : 1, len : 1, start: 129, type : bool, wr_dis : 18, rd_dis: null, alt : DIS_LEGACY_SPI_BOOT, dict : '', desc: Disable direct boot mode, rloc: 'EFUSE_RD_REPEAT_DATA3_REG[1]', bloc: 'B16[1]'} + DIS_USB_SERIAL_JTAG_ROM_PRINT : {show: y, blk : 0, word: 4, pos : 2, len : 1, start: 130, type : bool, wr_dis : 18, rd_dis: null, alt : UART_PRINT_CHANNEL, dict: '{0: "Enable", 1: "Disable"}', desc: USB printing, rloc: 'EFUSE_RD_REPEAT_DATA3_REG[2]', bloc: 'B16[2]'} + FLASH_ECC_MODE : {show: n, blk : 0, word: 4, pos : 3, len : 1, start: 131, type : bool, wr_dis : 18, rd_dis: null, alt : '', dict: '{0: "ROM would Enable Flash ECC 16to18 byte mode", 1: "ROM would use 16to17 byte mode"}', desc: ECC mode in ROM, rloc: 'EFUSE_RD_REPEAT_DATA3_REG[3]', bloc: 'B16[3]'} + DIS_USB_SERIAL_JTAG_DOWNLOAD_MODE: {show: y, blk : 0, word: 4, pos : 4, len : 1, start: 132, type : bool, wr_dis : 18, rd_dis: null, alt : DIS_USB_DOWNLOAD_MODE, dict : '', desc: Disable UART download mode through USB-Serial-JTAG, rloc: 'EFUSE_RD_REPEAT_DATA3_REG[4]', bloc: 'B16[4]'} + ENABLE_SECURITY_DOWNLOAD : {show: y, blk : 0, word: 4, pos : 5, len : 1, start: 133, type : bool, wr_dis : 18, rd_dis: null, alt : '', dict : '', desc: Set this bit to enable secure UART download mode, rloc: 'EFUSE_RD_REPEAT_DATA3_REG[5]', bloc: 'B16[5]'} + UART_PRINT_CONTROL : {show: y, blk : 0, word: 4, pos : 6, len : 2, start: 134, type : 'uint:2', wr_dis : 18, rd_dis: null, alt : '', dict: '{0: "Enable", 1: "Enable when GPIO8 is low at reset", 2: "Enable when GPIO8 is high at reset", 3: "Disable"}', desc: Set the default UARTboot message output mode, rloc: 'EFUSE_RD_REPEAT_DATA3_REG[7:6]', bloc: 'B16[7:6]'} + PIN_POWER_SELECTION : {show: n, blk : 0, word: 4, pos : 8, len : 1, start: 136, type : bool, wr_dis : 18, rd_dis: null, alt : '', dict: '{0: "VDD3P3_CPU", 1: "VDD_SPI"}', desc: GPIO33-GPIO37 power supply selection in ROM code, rloc: 'EFUSE_RD_REPEAT_DATA3_REG[8]', bloc: 'B17[0]'} + FLASH_TYPE : {show: n, blk : 0, word: 4, pos : 9, len : 1, start: 137, type : bool, wr_dis : 18, rd_dis: null, alt : '', dict: '{0: "4 data lines", 1: "8 data lines"}', desc: Maximum lines of SPI flash, rloc: 'EFUSE_RD_REPEAT_DATA3_REG[9]', bloc: 'B17[1]'} + FLASH_PAGE_SIZE : {show: n, blk : 0, word: 4, pos: 10, len : 2, start: 138, type : 'uint:2', wr_dis : 18, rd_dis: null, alt : '', dict : '', desc: Set Flash page size, rloc: 'EFUSE_RD_REPEAT_DATA3_REG[11:10]', bloc: 'B17[3:2]'} + FLASH_ECC_EN : {show: n, blk : 0, word: 4, pos: 12, len : 1, start: 140, type : bool, wr_dis : 18, rd_dis: null, alt : '', dict : '', desc: Set 1 to enable ECC for flash boot, rloc: 'EFUSE_RD_REPEAT_DATA3_REG[12]', bloc: 'B17[4]'} + FORCE_SEND_RESUME : {show: y, blk : 0, word: 4, pos: 13, len : 1, start: 141, type : bool, wr_dis : 18, rd_dis: null, alt : '', dict : '', desc: Set this bit to force ROM code to send a resume command during SPI boot, rloc: 'EFUSE_RD_REPEAT_DATA3_REG[13]', bloc: 'B17[5]'} + SECURE_VERSION : {show: y, blk : 0, word: 4, pos: 14, len : 16, start: 142, type : 'uint:16', wr_dis : 18, rd_dis: null, alt : '', dict : '', desc: Secure version (used by ESP-IDF anti-rollback feature), rloc: 'EFUSE_RD_REPEAT_DATA3_REG[29:14]', bloc: 'B17[7:6],B18,B19[5:0]'} + RESERVED_0_158 : {show: n, blk : 0, word: 4, pos: 30, len : 1, start: 158, type : bool, wr_dis: null, rd_dis: null, alt : '', dict : '', desc: reserved, rloc: 'EFUSE_RD_REPEAT_DATA3_REG[30]', bloc: 'B19[6]'} + ERR_RST_ENABLE : {show: y, blk : 0, word: 4, pos: 31, len : 1, start: 159, type : bool, wr_dis : 19, rd_dis: null, alt : '', dict: '{0: "without check", 1: "with check"}', desc: Use BLOCK0 to check error record registers, rloc: 'EFUSE_RD_REPEAT_DATA3_REG[31]', bloc: 'B19[7]'} + DISABLE_WAFER_VERSION_MAJOR : {show: y, blk : 0, word: 5, pos : 0, len : 1, start: 160, type : bool, wr_dis : 19, rd_dis: null, alt : '', dict : '', desc: Disables check of wafer version major, rloc: 'EFUSE_RD_REPEAT_DATA4_REG[0]', bloc: 'B20[0]'} + DISABLE_BLK_VERSION_MAJOR : {show: y, blk : 0, word: 5, pos : 1, len : 1, start: 161, type : bool, wr_dis : 19, rd_dis: null, alt : '', dict : '', desc: Disables check of blk version major, rloc: 'EFUSE_RD_REPEAT_DATA4_REG[1]', bloc: 'B20[1]'} + RESERVED_0_162 : {show: n, blk : 0, word: 5, pos : 2, len : 22, start: 162, type : 'uint:22', wr_dis: null, rd_dis: null, alt : '', dict : '', desc: reserved, rloc: 'EFUSE_RD_REPEAT_DATA4_REG[23:2]', bloc: 'B20[7:2],B21,B22'} + MAC : {show: y, blk : 1, word: 0, pos : 0, len : 48, start : 0, type : 'bytes:6', wr_dis : 20, rd_dis: null, alt : MAC_FACTORY, dict : '', desc: MAC address, rloc: EFUSE_RD_MAC_SPI_SYS_0_REG, bloc: 'B0,B1,B2,B3,B4,B5'} + SPI_PAD_CONFIG_CLK : {show: y, blk : 1, word: 1, pos: 16, len : 6, start : 48, type : 'uint:6', wr_dis : 20, rd_dis: null, alt : '', dict : '', desc: SPI PAD CLK, rloc: 'EFUSE_RD_MAC_SPI_SYS_1_REG[21:16]', bloc: 'B6[5:0]'} + SPI_PAD_CONFIG_Q : {show: y, blk : 1, word: 1, pos: 22, len : 6, start : 54, type : 'uint:6', wr_dis : 20, rd_dis: null, alt : '', dict : '', desc: SPI PAD Q(D1), rloc: 'EFUSE_RD_MAC_SPI_SYS_1_REG[27:22]', bloc: 'B6[7:6],B7[3:0]'} + SPI_PAD_CONFIG_D : {show: y, blk : 1, word: 1, pos: 28, len : 6, start : 60, type : 'uint:6', wr_dis : 20, rd_dis: null, alt : '', dict : '', desc: SPI PAD D(D0), rloc: 'EFUSE_RD_MAC_SPI_SYS_1_REG[31:28]', bloc: 'B7[7:4],B8[1:0]'} + SPI_PAD_CONFIG_CS : {show: y, blk : 1, word: 2, pos : 2, len : 6, start : 66, type : 'uint:6', wr_dis : 20, rd_dis: null, alt : '', dict : '', desc: SPI PAD CS, rloc: 'EFUSE_RD_MAC_SPI_SYS_2_REG[7:2]', bloc: 'B8[7:2]'} + SPI_PAD_CONFIG_HD : {show: y, blk : 1, word: 2, pos : 8, len : 6, start : 72, type : 'uint:6', wr_dis : 20, rd_dis: null, alt : '', dict : '', desc: SPI PAD HD(D3), rloc: 'EFUSE_RD_MAC_SPI_SYS_2_REG[13:8]', bloc: 'B9[5:0]'} + SPI_PAD_CONFIG_WP : {show: y, blk : 1, word: 2, pos: 14, len : 6, start : 78, type : 'uint:6', wr_dis : 20, rd_dis: null, alt : '', dict : '', desc: SPI PAD WP(D2), rloc: 'EFUSE_RD_MAC_SPI_SYS_2_REG[19:14]', bloc: 'B9[7:6],B10[3:0]'} + SPI_PAD_CONFIG_DQS : {show: y, blk : 1, word: 2, pos: 20, len : 6, start : 84, type : 'uint:6', wr_dis : 20, rd_dis: null, alt : '', dict : '', desc: SPI PAD DQS, rloc: 'EFUSE_RD_MAC_SPI_SYS_2_REG[25:20]', bloc: 'B10[7:4],B11[1:0]'} + SPI_PAD_CONFIG_D4 : {show: y, blk : 1, word: 2, pos: 26, len : 6, start : 90, type : 'uint:6', wr_dis : 20, rd_dis: null, alt : '', dict : '', desc: SPI PAD D4, rloc: 'EFUSE_RD_MAC_SPI_SYS_2_REG[31:26]', bloc: 'B11[7:2]'} + SPI_PAD_CONFIG_D5 : {show: y, blk : 1, word: 3, pos : 0, len : 6, start : 96, type : 'uint:6', wr_dis : 20, rd_dis: null, alt : '', dict : '', desc: SPI PAD D5, rloc: 'EFUSE_RD_MAC_SPI_SYS_3_REG[5:0]', bloc: 'B12[5:0]'} + SPI_PAD_CONFIG_D6 : {show: y, blk : 1, word: 3, pos : 6, len : 6, start: 102, type : 'uint:6', wr_dis : 20, rd_dis: null, alt : '', dict : '', desc: SPI PAD D6, rloc: 'EFUSE_RD_MAC_SPI_SYS_3_REG[11:6]', bloc: 'B12[7:6],B13[3:0]'} + SPI_PAD_CONFIG_D7 : {show: y, blk : 1, word: 3, pos: 12, len : 6, start: 108, type : 'uint:6', wr_dis : 20, rd_dis: null, alt : '', dict : '', desc: SPI PAD D7, rloc: 'EFUSE_RD_MAC_SPI_SYS_3_REG[17:12]', bloc: 'B13[7:4],B14[1:0]'} + WAFER_VERSION_MINOR_LO : {show: y, blk : 1, word: 3, pos: 18, len : 3, start: 114, type : 'uint:3', wr_dis : 20, rd_dis: null, alt : '', dict : '', desc: WAFER_VERSION_MINOR least significant bits, rloc: 'EFUSE_RD_MAC_SPI_SYS_3_REG[20:18]', bloc: 'B14[4:2]'} + PKG_VERSION : {show: y, blk : 1, word: 3, pos: 21, len : 3, start: 117, type : 'uint:3', wr_dis : 20, rd_dis: null, alt : '', dict : '', desc: Package version, rloc: 'EFUSE_RD_MAC_SPI_SYS_3_REG[23:21]', bloc: 'B14[7:5]'} + BLK_VERSION_MINOR : {show: y, blk : 1, word: 3, pos: 24, len : 3, start: 120, type : 'uint:3', wr_dis : 20, rd_dis: null, alt : '', dict : '', desc: BLK_VERSION_MINOR, rloc: 'EFUSE_RD_MAC_SPI_SYS_3_REG[26:24]', bloc: 'B15[2:0]'} + FLASH_CAP : {show: y, blk : 1, word: 3, pos: 27, len : 3, start: 123, type : 'uint:3', wr_dis : 20, rd_dis: null, alt : '', dict: '{0: "None", 1: "4M", 2: "2M", 3: "1M", 4: "8M"}', desc: Flash capacity, rloc: 'EFUSE_RD_MAC_SPI_SYS_3_REG[29:27]', bloc: 'B15[5:3]'} + FLASH_TEMP : {show: y, blk : 1, word: 3, pos: 30, len : 2, start: 126, type : 'uint:2', wr_dis : 20, rd_dis: null, alt : '', dict: '{0: "None", 1: "105C", 2: "85C"}', desc: Flash temperature, rloc: 'EFUSE_RD_MAC_SPI_SYS_3_REG[31:30]', bloc: 'B15[7:6]'} + FLASH_VENDOR : {show: y, blk : 1, word: 4, pos : 0, len : 3, start: 128, type : 'uint:3', wr_dis : 20, rd_dis: null, alt : '', dict: '{0: "None", 1: "XMC", 2: "GD", 3: "FM", 4: "TT", 5: "ZBIT"}', desc: Flash vendor, rloc: 'EFUSE_RD_MAC_SPI_SYS_4_REG[2:0]', bloc: 'B16[2:0]'} + RESERVED_1_131 : {show: n, blk : 1, word: 4, pos : 3, len : 4, start: 131, type : 'uint:4', wr_dis : 20, rd_dis: null, alt : '', dict : '', desc: reserved, rloc: 'EFUSE_RD_MAC_SPI_SYS_4_REG[6:3]', bloc: 'B16[6:3]'} + K_RTC_LDO : {show: y, blk : 1, word: 4, pos : 7, len : 7, start: 135, type : 'uint:7', wr_dis : 20, rd_dis: null, alt : '', dict : '', desc: BLOCK1 K_RTC_LDO, rloc: 'EFUSE_RD_MAC_SPI_SYS_4_REG[13:7]', bloc: 'B16[7],B17[5:0]'} + K_DIG_LDO : {show: y, blk : 1, word: 4, pos: 14, len : 7, start: 142, type : 'uint:7', wr_dis : 20, rd_dis: null, alt : '', dict : '', desc: BLOCK1 K_DIG_LDO, rloc: 'EFUSE_RD_MAC_SPI_SYS_4_REG[20:14]', bloc: 'B17[7:6],B18[4:0]'} + V_RTC_DBIAS20 : {show: y, blk : 1, word: 4, pos: 21, len : 8, start: 149, type : 'uint:8', wr_dis : 20, rd_dis: null, alt : '', dict : '', desc: BLOCK1 voltage of rtc dbias20, rloc: 'EFUSE_RD_MAC_SPI_SYS_4_REG[28:21]', bloc: 'B18[7:5],B19[4:0]'} + V_DIG_DBIAS20 : {show: y, blk : 1, word: 4, pos: 29, len : 8, start: 157, type : 'uint:8', wr_dis : 20, rd_dis: null, alt : '', dict : '', desc: BLOCK1 voltage of digital dbias20, rloc: 'EFUSE_RD_MAC_SPI_SYS_4_REG[31:29]', bloc: 'B19[7:5],B20[4:0]'} + DIG_DBIAS_HVT : {show: y, blk : 1, word: 5, pos : 5, len : 5, start: 165, type : 'uint:5', wr_dis : 20, rd_dis: null, alt : '', dict : '', desc: BLOCK1 digital dbias when hvt, rloc: 'EFUSE_RD_MAC_SPI_SYS_5_REG[9:5]', bloc: 'B20[7:5],B21[1:0]'} + THRES_HVT : {show: y, blk : 1, word: 5, pos: 10, len : 10, start: 170, type : 'uint:10', wr_dis : 20, rd_dis: null, alt : '', dict : '', desc: BLOCK1 pvt threshold when hvt, rloc: 'EFUSE_RD_MAC_SPI_SYS_5_REG[19:10]', bloc: 'B21[7:2],B22[3:0]'} + RESERVED_1_180 : {show: n, blk : 1, word: 5, pos: 20, len : 3, start: 180, type : 'uint:3', wr_dis : 20, rd_dis: null, alt : '', dict : '', desc: reserved, rloc: 'EFUSE_RD_MAC_SPI_SYS_5_REG[22:20]', bloc: 'B22[6:4]'} + WAFER_VERSION_MINOR_HI : {show: y, blk : 1, word: 5, pos: 23, len : 1, start: 183, type : bool, wr_dis : 20, rd_dis: null, alt : '', dict : '', desc: WAFER_VERSION_MINOR most significant bit, rloc: 'EFUSE_RD_MAC_SPI_SYS_5_REG[23]', bloc: 'B22[7]'} + WAFER_VERSION_MAJOR : {show: y, blk : 1, word: 5, pos: 24, len : 2, start: 184, type : 'uint:2', wr_dis : 20, rd_dis: null, alt : '', dict : '', desc: WAFER_VERSION_MAJOR, rloc: 'EFUSE_RD_MAC_SPI_SYS_5_REG[25:24]', bloc: 'B23[1:0]'} + RESERVED_1_186 : {show: n, blk : 1, word: 5, pos: 26, len : 6, start: 186, type : 'uint:6', wr_dis : 20, rd_dis: null, alt : '', dict : '', desc: reserved, rloc: 'EFUSE_RD_MAC_SPI_SYS_5_REG[31:26]', bloc: 'B23[7:2]'} + OPTIONAL_UNIQUE_ID : {show: y, blk : 2, word: 0, pos : 0, len: 128, start : 0, type: 'bytes:16', wr_dis : 21, rd_dis: null, alt : '', dict : '', desc: Optional unique 128-bit ID, rloc: EFUSE_RD_SYS_PART1_DATA0_REG, bloc: 'B0,B1,B2,B3,B4,B5,B6,B7,B8,B9,B10,B11,B12,B13,B14,B15'} + BLK_VERSION_MAJOR : {show: y, blk : 2, word: 4, pos : 0, len : 2, start: 128, type : 'uint:2', wr_dis : 21, rd_dis: null, alt : '', dict: '{0: "No calibration", 1: "With calibration"}', desc: BLK_VERSION_MAJOR of BLOCK2, rloc: 'EFUSE_RD_SYS_PART1_DATA4_REG[1:0]', bloc: 'B16[1:0]'} + RESERVED_2_130 : {show: n, blk : 2, word: 4, pos : 2, len : 1, start: 130, type : bool, wr_dis : 21, rd_dis: null, alt : '', dict : '', desc: reserved, rloc: 'EFUSE_RD_SYS_PART1_DATA4_REG[2]', bloc: 'B16[2]'} + TEMP_CALIB : {show: y, blk : 2, word: 4, pos : 3, len : 9, start: 131, type : 'uint:9', wr_dis : 21, rd_dis: null, alt : '', dict : '', desc: Temperature calibration data, rloc: 'EFUSE_RD_SYS_PART1_DATA4_REG[11:3]', bloc: 'B16[7:3],B17[3:0]'} + OCODE : {show: y, blk : 2, word: 4, pos: 12, len : 8, start: 140, type : 'uint:8', wr_dis : 21, rd_dis: null, alt : '', dict : '', desc: ADC OCode, rloc: 'EFUSE_RD_SYS_PART1_DATA4_REG[19:12]', bloc: 'B17[7:4],B18[3:0]'} + ADC1_INIT_CODE_ATTEN0 : {show: y, blk : 2, word: 4, pos: 20, len : 10, start: 148, type : 'uint:10', wr_dis : 21, rd_dis: null, alt : '', dict : '', desc: ADC1 init code at atten0, rloc: 'EFUSE_RD_SYS_PART1_DATA4_REG[29:20]', bloc: 'B18[7:4],B19[5:0]'} + ADC1_INIT_CODE_ATTEN1 : {show: y, blk : 2, word: 4, pos: 30, len : 10, start: 158, type : 'uint:10', wr_dis : 21, rd_dis: null, alt : '', dict : '', desc: ADC1 init code at atten1, rloc: 'EFUSE_RD_SYS_PART1_DATA4_REG[31:30]', bloc: 'B19[7:6],B20'} + ADC1_INIT_CODE_ATTEN2 : {show: y, blk : 2, word: 5, pos : 8, len : 10, start: 168, type : 'uint:10', wr_dis : 21, rd_dis: null, alt : '', dict : '', desc: ADC1 init code at atten2, rloc: 'EFUSE_RD_SYS_PART1_DATA5_REG[17:8]', bloc: 'B21,B22[1:0]'} + ADC1_INIT_CODE_ATTEN3 : {show: y, blk : 2, word: 5, pos: 18, len : 10, start: 178, type : 'uint:10', wr_dis : 21, rd_dis: null, alt : '', dict : '', desc: ADC1 init code at atten3, rloc: 'EFUSE_RD_SYS_PART1_DATA5_REG[27:18]', bloc: 'B22[7:2],B23[3:0]'} + ADC1_CAL_VOL_ATTEN0 : {show: y, blk : 2, word: 5, pos: 28, len : 10, start: 188, type : 'uint:10', wr_dis : 21, rd_dis: null, alt : '', dict : '', desc: ADC1 calibration voltage at atten0, rloc: 'EFUSE_RD_SYS_PART1_DATA5_REG[31:28]', bloc: 'B23[7:4],B24[5:0]'} + ADC1_CAL_VOL_ATTEN1 : {show: y, blk : 2, word: 6, pos : 6, len : 10, start: 198, type : 'uint:10', wr_dis : 21, rd_dis: null, alt : '', dict : '', desc: ADC1 calibration voltage at atten1, rloc: 'EFUSE_RD_SYS_PART1_DATA6_REG[15:6]', bloc: 'B24[7:6],B25'} + ADC1_CAL_VOL_ATTEN2 : {show: y, blk : 2, word: 6, pos: 16, len : 10, start: 208, type : 'uint:10', wr_dis : 21, rd_dis: null, alt : '', dict : '', desc: ADC1 calibration voltage at atten2, rloc: 'EFUSE_RD_SYS_PART1_DATA6_REG[25:16]', bloc: 'B26,B27[1:0]'} + ADC1_CAL_VOL_ATTEN3 : {show: y, blk : 2, word: 6, pos: 26, len : 10, start: 218, type : 'uint:10', wr_dis : 21, rd_dis: null, alt : '', dict : '', desc: ADC1 calibration voltage at atten3, rloc: 'EFUSE_RD_SYS_PART1_DATA6_REG[31:26]', bloc: 'B27[7:2],B28[3:0]'} + RESERVED_2_228 : {show: n, blk : 2, word: 7, pos : 4, len : 28, start: 228, type : 'uint:28', wr_dis : 21, rd_dis: null, alt : '', dict : '', desc: reserved, rloc: 'EFUSE_RD_SYS_PART1_DATA7_REG[31:4]', bloc: 'B28[7:4],B29,B30,B31'} + BLOCK_USR_DATA : {show: y, blk : 3, word: 0, pos : 0, len: 192, start : 0, type: 'bytes:24', wr_dis : 22, rd_dis: null, alt : USER_DATA, dict : '', desc: User data, rloc: EFUSE_RD_USR_DATA0_REG, bloc: 'B0,B1,B2,B3,B4,B5,B6,B7,B8,B9,B10,B11,B12,B13,B14,B15,B16,B17,B18,B19,B20,B21,B22,B23'} + RESERVED_3_192 : {show: n, blk : 3, word: 6, pos : 0, len : 8, start: 192, type : 'uint:8', wr_dis : 22, rd_dis: null, alt : '', dict : '', desc: reserved, rloc: 'EFUSE_RD_USR_DATA6_REG[7:0]', bloc: B24} + CUSTOM_MAC : {show: y, blk : 3, word: 6, pos : 8, len : 48, start: 200, type : 'bytes:6', wr_dis : 22, rd_dis: null, alt: MAC_CUSTOM USER_DATA_MAC_CUSTOM, dict : '', desc: Custom MAC address, rloc: 'EFUSE_RD_USR_DATA6_REG[31:8]', bloc: 'B25,B26,B27,B28,B29,B30'} + RESERVED_3_248 : {show: n, blk : 3, word: 7, pos: 24, len : 8, start: 248, type : 'uint:8', wr_dis : 22, rd_dis: null, alt : '', dict : '', desc: reserved, rloc: 'EFUSE_RD_USR_DATA7_REG[31:24]', bloc: B31} + BLOCK_KEY0 : {show: y, blk : 4, word: 0, pos : 0, len: 256, start : 0, type: 'bytes:32', wr_dis : 23, rd_dis : 0, alt : KEY0, dict : '', desc: Key0 or user data, rloc: EFUSE_RD_KEY0_DATA0_REG, bloc: 'B0,B1,B2,B3,B4,B5,B6,B7,B8,B9,B10,B11,B12,B13,B14,B15,B16,B17,B18,B19,B20,B21,B22,B23,B24,B25,B26,B27,B28,B29,B30,B31'} + BLOCK_KEY1 : {show: y, blk : 5, word: 0, pos : 0, len: 256, start : 0, type: 'bytes:32', wr_dis : 24, rd_dis : 1, alt : KEY1, dict : '', desc: Key1 or user data, rloc: EFUSE_RD_KEY1_DATA0_REG, bloc: 'B0,B1,B2,B3,B4,B5,B6,B7,B8,B9,B10,B11,B12,B13,B14,B15,B16,B17,B18,B19,B20,B21,B22,B23,B24,B25,B26,B27,B28,B29,B30,B31'} + BLOCK_KEY2 : {show: y, blk : 6, word: 0, pos : 0, len: 256, start : 0, type: 'bytes:32', wr_dis : 25, rd_dis : 2, alt : KEY2, dict : '', desc: Key2 or user data, rloc: EFUSE_RD_KEY2_DATA0_REG, bloc: 'B0,B1,B2,B3,B4,B5,B6,B7,B8,B9,B10,B11,B12,B13,B14,B15,B16,B17,B18,B19,B20,B21,B22,B23,B24,B25,B26,B27,B28,B29,B30,B31'} + BLOCK_KEY3 : {show: y, blk : 7, word: 0, pos : 0, len: 256, start : 0, type: 'bytes:32', wr_dis : 26, rd_dis : 3, alt : KEY3, dict : '', desc: Key3 or user data, rloc: EFUSE_RD_KEY3_DATA0_REG, bloc: 'B0,B1,B2,B3,B4,B5,B6,B7,B8,B9,B10,B11,B12,B13,B14,B15,B16,B17,B18,B19,B20,B21,B22,B23,B24,B25,B26,B27,B28,B29,B30,B31'} + BLOCK_KEY4 : {show: y, blk : 8, word: 0, pos : 0, len: 256, start : 0, type: 'bytes:32', wr_dis : 27, rd_dis : 4, alt : KEY4, dict : '', desc: Key4 or user data, rloc: EFUSE_RD_KEY4_DATA0_REG, bloc: 'B0,B1,B2,B3,B4,B5,B6,B7,B8,B9,B10,B11,B12,B13,B14,B15,B16,B17,B18,B19,B20,B21,B22,B23,B24,B25,B26,B27,B28,B29,B30,B31'} + BLOCK_KEY5 : {show: y, blk : 9, word: 0, pos : 0, len: 256, start : 0, type: 'bytes:32', wr_dis : 28, rd_dis : 5, alt : KEY5, dict : '', desc: Key5 or user data, rloc: EFUSE_RD_KEY5_DATA0_REG, bloc: 'B0,B1,B2,B3,B4,B5,B6,B7,B8,B9,B10,B11,B12,B13,B14,B15,B16,B17,B18,B19,B20,B21,B22,B23,B24,B25,B26,B27,B28,B29,B30,B31'} + BLOCK_SYS_DATA2 : {show: y, blk: 10, word: 0, pos : 0, len: 256, start : 0, type: 'bytes:32', wr_dis : 29, rd_dis : 6, alt : SYS_DATA_PART2, dict : '', desc: System data part 2 (reserved), rloc: EFUSE_RD_SYS_PART2_DATA0_REG, bloc: 'B0,B1,B2,B3,B4,B5,B6,B7,B8,B9,B10,B11,B12,B13,B14,B15,B16,B17,B18,B19,B20,B21,B22,B23,B24,B25,B26,B27,B28,B29,B30,B31'} diff --git a/espefuse/efuse_defs/esp32c6.yaml b/espefuse/efuse_defs/esp32c6.yaml new file mode 100644 index 000000000..aee94306f --- /dev/null +++ b/espefuse/efuse_defs/esp32c6.yaml @@ -0,0 +1,106 @@ +VER_NO: 709e8ea096e8a03a10006d40d5451a49 +EFUSES: + WR_DIS : {show: y, blk : 0, word: 0, pos : 0, len : 32, start : 0, type : 'uint:32', wr_dis: null, rd_dis: null, alt : '', dict : '', desc: Disable programming of individual eFuses, rloc: EFUSE_RD_WR_DIS_REG, bloc: 'B0,B1,B2,B3'} + RD_DIS : {show: y, blk : 0, word: 1, pos : 0, len : 7, start : 32, type : 'uint:7', wr_dis : 0, rd_dis: null, alt : '', dict : '', desc: Disable reading from BlOCK4-10, rloc: 'EFUSE_RD_REPEAT_DATA0_REG[6:0]', bloc: 'B4[6:0]'} + SWAP_UART_SDIO_EN : {show: y, blk : 0, word: 1, pos : 7, len : 1, start : 39, type : bool, wr_dis : 2, rd_dis: null, alt : '', dict : '', desc: 'Represents whether pad of uart and sdio is swapped or not. 1: swapped. 0: not swapped', rloc: 'EFUSE_RD_REPEAT_DATA0_REG[7]', bloc: 'B4[7]'} + DIS_ICACHE : {show: y, blk : 0, word: 1, pos : 8, len : 1, start : 40, type : bool, wr_dis : 2, rd_dis: null, alt : '', dict : '', desc: 'Represents whether icache is disabled or enabled. 1: disabled. 0: enabled', rloc: 'EFUSE_RD_REPEAT_DATA0_REG[8]', bloc: 'B5[0]'} + DIS_USB_JTAG : {show: y, blk : 0, word: 1, pos : 9, len : 1, start : 41, type : bool, wr_dis : 2, rd_dis: null, alt : '', dict : '', desc: 'Represents whether the function of usb switch to jtag is disabled or enabled. 1: disabled. 0: enabled', rloc: 'EFUSE_RD_REPEAT_DATA0_REG[9]', bloc: 'B5[1]'} + DIS_DOWNLOAD_ICACHE : {show: y, blk : 0, word: 1, pos: 10, len : 1, start : 42, type : bool, wr_dis : 2, rd_dis: null, alt : '', dict : '', desc: 'Represents whether icache is disabled or enabled in Download mode. 1: disabled. 0: enabled', rloc: 'EFUSE_RD_REPEAT_DATA0_REG[10]', bloc: 'B5[2]'} + DIS_USB_SERIAL_JTAG : {show: y, blk : 0, word: 1, pos: 11, len : 1, start : 43, type : bool, wr_dis : 2, rd_dis: null, alt : '', dict : '', desc: 'Represents whether USB-Serial-JTAG is disabled or enabled. 1: disabled. 0: enabled', rloc: 'EFUSE_RD_REPEAT_DATA0_REG[11]', bloc: 'B5[3]'} + DIS_FORCE_DOWNLOAD : {show: y, blk : 0, word: 1, pos: 12, len : 1, start : 44, type : bool, wr_dis : 2, rd_dis: null, alt : '', dict : '', desc: 'Represents whether the function that forces chip into download mode is disabled or enabled. 1: disabled. 0: enabled', rloc: 'EFUSE_RD_REPEAT_DATA0_REG[12]', bloc: 'B5[4]'} + SPI_DOWNLOAD_MSPI_DIS : {show: y, blk : 0, word: 1, pos: 13, len : 1, start : 45, type : bool, wr_dis : 17, rd_dis: null, alt : '', dict : '', desc: 'Represents whether SPI0 controller during boot_mode_download is disabled or enabled. 1: disabled. 0: enabled', rloc: 'EFUSE_RD_REPEAT_DATA0_REG[13]', bloc: 'B5[5]'} + DIS_TWAI : {show: y, blk : 0, word: 1, pos: 14, len : 1, start : 46, type : bool, wr_dis : 2, rd_dis: null, alt : DIS_CAN, dict : '', desc: 'Represents whether TWAI function is disabled or enabled. 1: disabled. 0: enabled', rloc: 'EFUSE_RD_REPEAT_DATA0_REG[14]', bloc: 'B5[6]'} + JTAG_SEL_ENABLE : {show: y, blk : 0, word: 1, pos: 15, len : 1, start : 47, type : bool, wr_dis : 2, rd_dis: null, alt : '', dict : '', desc: 'Represents whether the selection between usb_to_jtag and pad_to_jtag through strapping gpio15 when both EFUSE_DIS_PAD_JTAG and EFUSE_DIS_USB_JTAG are equal to 0 is enabled or disabled. 1: enabled. 0: disabled', rloc: 'EFUSE_RD_REPEAT_DATA0_REG[15]', bloc: 'B5[7]'} + SOFT_DIS_JTAG : {show: y, blk : 0, word: 1, pos: 16, len : 3, start : 48, type : 'uint:3', wr_dis : 31, rd_dis: null, alt : '', dict : '', desc: 'Represents whether JTAG is disabled in soft way. Odd number: disabled. Even number: enabled', rloc: 'EFUSE_RD_REPEAT_DATA0_REG[18:16]', bloc: 'B6[2:0]'} + DIS_PAD_JTAG : {show: y, blk : 0, word: 1, pos: 19, len : 1, start : 51, type : bool, wr_dis : 2, rd_dis: null, alt : '', dict : '', desc: 'Represents whether JTAG is disabled in the hard way(permanently). 1: disabled. 0: enabled', rloc: 'EFUSE_RD_REPEAT_DATA0_REG[19]', bloc: 'B6[3]'} + DIS_DOWNLOAD_MANUAL_ENCRYPT : {show: y, blk : 0, word: 1, pos: 20, len : 1, start : 52, type : bool, wr_dis : 2, rd_dis: null, alt : '', dict : '', desc: 'Represents whether flash encrypt function is disabled or enabled(except in SPI boot mode). 1: disabled. 0: enabled', rloc: 'EFUSE_RD_REPEAT_DATA0_REG[20]', bloc: 'B6[4]'} + USB_DREFH : {show: n, blk : 0, word: 1, pos: 21, len : 2, start : 53, type : 'uint:2', wr_dis : 30, rd_dis: null, alt : '', dict : '', desc: Represents the single-end input threhold vrefh; 1.76 V to 2 V with step of 80 mV, rloc: 'EFUSE_RD_REPEAT_DATA0_REG[22:21]', bloc: 'B6[6:5]'} + USB_DREFL : {show: n, blk : 0, word: 1, pos: 23, len : 2, start : 55, type : 'uint:2', wr_dis : 30, rd_dis: null, alt : '', dict : '', desc: Represents the single-end input threhold vrefl; 1.76 V to 2 V with step of 80 mV, rloc: 'EFUSE_RD_REPEAT_DATA0_REG[24:23]', bloc: 'B6[7],B7[0]'} + USB_EXCHG_PINS : {show: y, blk : 0, word: 1, pos: 25, len : 1, start : 57, type : bool, wr_dis : 30, rd_dis: null, alt : '', dict : '', desc: 'Represents whether the D+ and D- pins is exchanged. 1: exchanged. 0: not exchanged', rloc: 'EFUSE_RD_REPEAT_DATA0_REG[25]', bloc: 'B7[1]'} + VDD_SPI_AS_GPIO : {show: y, blk : 0, word: 1, pos: 26, len : 1, start : 58, type : bool, wr_dis : 30, rd_dis: null, alt : '', dict : '', desc: 'Represents whether vdd spi pin is functioned as gpio. 1: functioned. 0: not functioned', rloc: 'EFUSE_RD_REPEAT_DATA0_REG[26]', bloc: 'B7[2]'} + RPT4_RESERVED0_2 : {show: n, blk : 0, word: 1, pos: 27, len : 2, start : 59, type : 'uint:2', wr_dis: null, rd_dis: null, alt : '', dict : '', desc: Reserved, rloc: 'EFUSE_RD_REPEAT_DATA0_REG[28:27]', bloc: 'B7[4:3]'} + RPT4_RESERVED0_1 : {show: n, blk : 0, word: 1, pos: 29, len : 1, start : 61, type : bool, wr_dis: null, rd_dis: null, alt : '', dict : '', desc: Reserved, rloc: 'EFUSE_RD_REPEAT_DATA0_REG[29]', bloc: 'B7[5]'} + RPT4_RESERVED0_0 : {show: n, blk : 0, word: 1, pos: 30, len : 2, start : 62, type : 'uint:2', wr_dis: null, rd_dis: null, alt : '', dict : '', desc: Reserved, rloc: 'EFUSE_RD_REPEAT_DATA0_REG[31:30]', bloc: 'B7[7:6]'} + RPT4_RESERVED1_0 : {show: n, blk : 0, word: 2, pos : 0, len : 16, start : 64, type : 'uint:16', wr_dis: null, rd_dis: null, alt : '', dict : '', desc: Reserved, rloc: 'EFUSE_RD_REPEAT_DATA1_REG[15:0]', bloc: 'B8,B9'} + WDT_DELAY_SEL : {show: y, blk : 0, word: 2, pos: 16, len : 2, start : 80, type : 'uint:2', wr_dis : 3, rd_dis: null, alt : '', dict : '', desc: 'Represents whether RTC watchdog timeout threshold is selected at startup. 1: selected. 0: not selected', rloc: 'EFUSE_RD_REPEAT_DATA1_REG[17:16]', bloc: 'B10[1:0]'} + SPI_BOOT_CRYPT_CNT : {show: y, blk : 0, word: 2, pos: 18, len : 3, start : 82, type : 'uint:3', wr_dis : 4, rd_dis: null, alt : '', dict: '{0: "Disable", 1: "Enable", 3: "Disable", 7: "Enable"}', desc: Enables flash encryption when 1 or 3 bits are set and disables otherwise, rloc: 'EFUSE_RD_REPEAT_DATA1_REG[20:18]', bloc: 'B10[4:2]'} + SECURE_BOOT_KEY_REVOKE0 : {show: y, blk : 0, word: 2, pos: 21, len : 1, start : 85, type : bool, wr_dis : 5, rd_dis: null, alt : '', dict : '', desc: Revoke 1st secure boot key, rloc: 'EFUSE_RD_REPEAT_DATA1_REG[21]', bloc: 'B10[5]'} + SECURE_BOOT_KEY_REVOKE1 : {show: y, blk : 0, word: 2, pos: 22, len : 1, start : 86, type : bool, wr_dis : 6, rd_dis: null, alt : '', dict : '', desc: Revoke 2nd secure boot key, rloc: 'EFUSE_RD_REPEAT_DATA1_REG[22]', bloc: 'B10[6]'} + SECURE_BOOT_KEY_REVOKE2 : {show: y, blk : 0, word: 2, pos: 23, len : 1, start : 87, type : bool, wr_dis : 7, rd_dis: null, alt : '', dict : '', desc: Revoke 3rd secure boot key, rloc: 'EFUSE_RD_REPEAT_DATA1_REG[23]', bloc: 'B10[7]'} + KEY_PURPOSE_0 : {show: y, blk : 0, word: 2, pos: 24, len : 4, start : 88, type : 'uint:4', wr_dis : 8, rd_dis: null, alt : KEY0_PURPOSE, dict : '', desc: Represents the purpose of Key0, rloc: 'EFUSE_RD_REPEAT_DATA1_REG[27:24]', bloc: 'B11[3:0]'} + KEY_PURPOSE_1 : {show: y, blk : 0, word: 2, pos: 28, len : 4, start : 92, type : 'uint:4', wr_dis : 9, rd_dis: null, alt : KEY1_PURPOSE, dict : '', desc: Represents the purpose of Key1, rloc: 'EFUSE_RD_REPEAT_DATA1_REG[31:28]', bloc: 'B11[7:4]'} + KEY_PURPOSE_2 : {show: y, blk : 0, word: 3, pos : 0, len : 4, start : 96, type : 'uint:4', wr_dis : 10, rd_dis: null, alt : KEY2_PURPOSE, dict : '', desc: Represents the purpose of Key2, rloc: 'EFUSE_RD_REPEAT_DATA2_REG[3:0]', bloc: 'B12[3:0]'} + KEY_PURPOSE_3 : {show: y, blk : 0, word: 3, pos : 4, len : 4, start: 100, type : 'uint:4', wr_dis : 11, rd_dis: null, alt : KEY3_PURPOSE, dict : '', desc: Represents the purpose of Key3, rloc: 'EFUSE_RD_REPEAT_DATA2_REG[7:4]', bloc: 'B12[7:4]'} + KEY_PURPOSE_4 : {show: y, blk : 0, word: 3, pos : 8, len : 4, start: 104, type : 'uint:4', wr_dis : 12, rd_dis: null, alt : KEY4_PURPOSE, dict : '', desc: Represents the purpose of Key4, rloc: 'EFUSE_RD_REPEAT_DATA2_REG[11:8]', bloc: 'B13[3:0]'} + KEY_PURPOSE_5 : {show: y, blk : 0, word: 3, pos: 12, len : 4, start: 108, type : 'uint:4', wr_dis : 13, rd_dis: null, alt : KEY5_PURPOSE, dict : '', desc: Represents the purpose of Key5, rloc: 'EFUSE_RD_REPEAT_DATA2_REG[15:12]', bloc: 'B13[7:4]'} + SEC_DPA_LEVEL : {show: y, blk : 0, word: 3, pos: 16, len : 2, start: 112, type : 'uint:2', wr_dis : 14, rd_dis: null, alt : DPA_SEC_LEVEL, dict : '', desc: Represents the spa secure level by configuring the clock random divide mode, rloc: 'EFUSE_RD_REPEAT_DATA2_REG[17:16]', bloc: 'B14[1:0]'} + CRYPT_DPA_ENABLE : {show: y, blk : 0, word: 3, pos: 18, len : 1, start: 114, type : bool, wr_dis : 1, rd_dis: null, alt : '', dict : '', desc: 'Represents whether anti-dpa attack is enabled. 1:enabled. 0: disabled', rloc: 'EFUSE_RD_REPEAT_DATA2_REG[18]', bloc: 'B14[2]'} + RPT4_RESERVED2_1 : {show: n, blk : 0, word: 3, pos: 19, len : 1, start: 115, type : bool, wr_dis: null, rd_dis: null, alt : '', dict : '', desc: Reserved, rloc: 'EFUSE_RD_REPEAT_DATA2_REG[19]', bloc: 'B14[3]'} + SECURE_BOOT_EN : {show: y, blk : 0, word: 3, pos: 20, len : 1, start: 116, type : bool, wr_dis : 15, rd_dis: null, alt : '', dict : '', desc: 'Represents whether secure boot is enabled or disabled. 1: enabled. 0: disabled', rloc: 'EFUSE_RD_REPEAT_DATA2_REG[20]', bloc: 'B14[4]'} + SECURE_BOOT_AGGRESSIVE_REVOKE : {show: y, blk : 0, word: 3, pos: 21, len : 1, start: 117, type : bool, wr_dis : 16, rd_dis: null, alt : '', dict : '', desc: 'Represents whether revoking aggressive secure boot is enabled or disabled. 1: enabled. 0: disabled', rloc: 'EFUSE_RD_REPEAT_DATA2_REG[21]', bloc: 'B14[5]'} + RPT4_RESERVED2_0 : {show: n, blk : 0, word: 3, pos: 22, len : 6, start: 118, type : 'uint:6', wr_dis: null, rd_dis: null, alt : '', dict : '', desc: Reserved, rloc: 'EFUSE_RD_REPEAT_DATA2_REG[27:22]', bloc: 'B14[7:6],B15[3:0]'} + FLASH_TPUW : {show: y, blk : 0, word: 3, pos: 28, len : 4, start: 124, type : 'uint:4', wr_dis : 18, rd_dis: null, alt : '', dict : '', desc: Represents the flash waiting time after power-up; in unit of ms. When the value less than 15; the waiting time is the programmed value. Otherwise; the waiting time is 2 times the programmed value, rloc: 'EFUSE_RD_REPEAT_DATA2_REG[31:28]', bloc: 'B15[7:4]'} + DIS_DOWNLOAD_MODE : {show: y, blk : 0, word: 4, pos : 0, len : 1, start: 128, type : bool, wr_dis : 18, rd_dis: null, alt : '', dict : '', desc: 'Represents whether Download mode is disabled or enabled. 1: disabled. 0: enabled', rloc: 'EFUSE_RD_REPEAT_DATA3_REG[0]', bloc: 'B16[0]'} + DIS_DIRECT_BOOT : {show: y, blk : 0, word: 4, pos : 1, len : 1, start: 129, type : bool, wr_dis : 18, rd_dis: null, alt : '', dict : '', desc: 'Represents whether direct boot mode is disabled or enabled. 1: disabled. 0: enabled', rloc: 'EFUSE_RD_REPEAT_DATA3_REG[1]', bloc: 'B16[1]'} + DIS_USB_SERIAL_JTAG_ROM_PRINT : {show: y, blk : 0, word: 4, pos : 2, len : 1, start: 130, type : bool, wr_dis : 18, rd_dis: null, alt : DIS_USB_PRINT, dict : '', desc: 'Represents whether print from USB-Serial-JTAG is disabled or enabled. 1: disabled. 0: enabled', rloc: 'EFUSE_RD_REPEAT_DATA3_REG[2]', bloc: 'B16[2]'} + RPT4_RESERVED3_5 : {show: n, blk : 0, word: 4, pos : 3, len : 1, start: 131, type : bool, wr_dis: null, rd_dis: null, alt : '', dict : '', desc: Reserved, rloc: 'EFUSE_RD_REPEAT_DATA3_REG[3]', bloc: 'B16[3]'} + DIS_USB_SERIAL_JTAG_DOWNLOAD_MODE: {show: y, blk : 0, word: 4, pos : 4, len : 1, start: 132, type : bool, wr_dis : 18, rd_dis: null, alt : '', dict : '', desc: 'Represents whether the USB-Serial-JTAG download function is disabled or enabled. 1: disabled. 0: enabled', rloc: 'EFUSE_RD_REPEAT_DATA3_REG[4]', bloc: 'B16[4]'} + ENABLE_SECURITY_DOWNLOAD : {show: y, blk : 0, word: 4, pos : 5, len : 1, start: 133, type : bool, wr_dis : 18, rd_dis: null, alt : '', dict : '', desc: 'Represents whether security download is enabled or disabled. 1: enabled. 0: disabled', rloc: 'EFUSE_RD_REPEAT_DATA3_REG[5]', bloc: 'B16[5]'} + UART_PRINT_CONTROL : {show: y, blk : 0, word: 4, pos : 6, len : 2, start: 134, type : 'uint:2', wr_dis : 18, rd_dis: null, alt : '', dict: '{0: "Enable", 1: "Enable when GPIO8 is low at reset", 2: "Enable when GPIO8 is high at reset", 3: "Disable"}', desc: Set the default UARTboot message output mode, rloc: 'EFUSE_RD_REPEAT_DATA3_REG[7:6]', bloc: 'B16[7:6]'} + RPT4_RESERVED3_4 : {show: n, blk : 0, word: 4, pos : 8, len : 1, start: 136, type : bool, wr_dis: null, rd_dis: null, alt : '', dict : '', desc: Reserved, rloc: 'EFUSE_RD_REPEAT_DATA3_REG[8]', bloc: 'B17[0]'} + RPT4_RESERVED3_3 : {show: n, blk : 0, word: 4, pos : 9, len : 1, start: 137, type : bool, wr_dis: null, rd_dis: null, alt : '', dict : '', desc: Reserved, rloc: 'EFUSE_RD_REPEAT_DATA3_REG[9]', bloc: 'B17[1]'} + RPT4_RESERVED3_2 : {show: n, blk : 0, word: 4, pos: 10, len : 2, start: 138, type : 'uint:2', wr_dis: null, rd_dis: null, alt : '', dict : '', desc: Reserved, rloc: 'EFUSE_RD_REPEAT_DATA3_REG[11:10]', bloc: 'B17[3:2]'} + RPT4_RESERVED3_1 : {show: n, blk : 0, word: 4, pos: 12, len : 1, start: 140, type : bool, wr_dis: null, rd_dis: null, alt : '', dict : '', desc: Reserved, rloc: 'EFUSE_RD_REPEAT_DATA3_REG[12]', bloc: 'B17[4]'} + FORCE_SEND_RESUME : {show: y, blk : 0, word: 4, pos: 13, len : 1, start: 141, type : bool, wr_dis : 18, rd_dis: null, alt : '', dict : '', desc: 'Represents whether ROM code is forced to send a resume command during SPI boot. 1: forced. 0:not forced', rloc: 'EFUSE_RD_REPEAT_DATA3_REG[13]', bloc: 'B17[5]'} + SECURE_VERSION : {show: y, blk : 0, word: 4, pos: 14, len : 16, start: 142, type : 'uint:16', wr_dis : 18, rd_dis: null, alt : '', dict : '', desc: Represents the version used by ESP-IDF anti-rollback feature, rloc: 'EFUSE_RD_REPEAT_DATA3_REG[29:14]', bloc: 'B17[7:6],B18,B19[5:0]'} + SECURE_BOOT_DISABLE_FAST_WAKE : {show: y, blk : 0, word: 4, pos: 30, len : 1, start: 158, type : bool, wr_dis : 19, rd_dis: null, alt : '', dict : '', desc: 'Represents whether FAST VERIFY ON WAKE is disabled or enabled when Secure Boot is enabled. 1: disabled. 0: enabled', rloc: 'EFUSE_RD_REPEAT_DATA3_REG[30]', bloc: 'B19[6]'} + RPT4_RESERVED3_0 : {show: n, blk : 0, word: 4, pos: 31, len : 1, start: 159, type : bool, wr_dis: null, rd_dis: null, alt : '', dict : '', desc: Reserved, rloc: 'EFUSE_RD_REPEAT_DATA3_REG[31]', bloc: 'B19[7]'} + DISABLE_WAFER_VERSION_MAJOR : {show: y, blk : 0, word: 5, pos : 0, len : 1, start: 160, type : bool, wr_dis : 19, rd_dis: null, alt : '', dict : '', desc: Disables check of wafer version major, rloc: 'EFUSE_RD_REPEAT_DATA4_REG[0]', bloc: 'B20[0]'} + DISABLE_BLK_VERSION_MAJOR : {show: y, blk : 0, word: 5, pos : 1, len : 1, start: 161, type : bool, wr_dis : 19, rd_dis: null, alt : '', dict : '', desc: Disables check of blk version major, rloc: 'EFUSE_RD_REPEAT_DATA4_REG[1]', bloc: 'B20[1]'} + RESERVED_0_162 : {show: n, blk : 0, word: 5, pos : 2, len : 22, start: 162, type : 'uint:22', wr_dis: null, rd_dis: null, alt : '', dict : '', desc: reserved, rloc: 'EFUSE_RD_REPEAT_DATA4_REG[23:2]', bloc: 'B20[7:2],B21,B22'} + RPT4_RESERVED4_0 : {show: n, blk : 0, word: 5, pos: 24, len : 8, start: 184, type : 'uint:8', wr_dis: null, rd_dis: null, alt : '', dict : '', desc: Reserved, rloc: 'EFUSE_RD_REPEAT_DATA4_REG[31:24]', bloc: B23} + MAC : {show: y, blk : 1, word: 0, pos : 0, len : 48, start : 0, type : 'bytes:6', wr_dis : 20, rd_dis: null, alt : MAC_FACTORY, dict : '', desc: MAC address, rloc: EFUSE_RD_MAC_SPI_SYS_0_REG, bloc: 'B0,B1,B2,B3,B4,B5'} + MAC_EXT : {show: y, blk : 1, word: 1, pos: 16, len : 16, start : 48, type : 'bytes:2', wr_dis : 20, rd_dis: null, alt : '', dict : '', desc: Stores the extended bits of MAC address, rloc: 'EFUSE_RD_MAC_SPI_SYS_1_REG[31:16]', bloc: 'B6,B7'} + MAC_SPI_RESERVED : {show: n, blk : 1, word: 2, pos : 0, len : 14, start : 64, type : 'uint:14', wr_dis : 20, rd_dis: null, alt : '', dict : '', desc: Reserved, rloc: 'EFUSE_RD_MAC_SPI_SYS_2_REG[13:0]', bloc: 'B8,B9[5:0]'} + SPI_PAD_CONF_1 : {show: n, blk : 1, word: 2, pos: 14, len : 18, start : 78, type : 'uint:18', wr_dis : 20, rd_dis: null, alt : '', dict : '', desc: Stores the first part of SPI_PAD_CONF, rloc: 'EFUSE_RD_MAC_SPI_SYS_2_REG[31:14]', bloc: 'B9[7:6],B10,B11'} + SPI_PAD_CONF_2 : {show: n, blk : 1, word: 3, pos : 0, len : 18, start : 96, type : 'uint:18', wr_dis : 20, rd_dis: null, alt : '', dict : '', desc: Stores the second part of SPI_PAD_CONF, rloc: 'EFUSE_RD_MAC_SPI_SYS_3_REG[17:0]', bloc: 'B12,B13,B14[1:0]'} + WAFER_VERSION_MINOR : {show: y, blk : 1, word: 3, pos: 18, len : 4, start: 114, type : 'uint:4', wr_dis : 20, rd_dis: null, alt : '', dict : '', desc: '', rloc: 'EFUSE_RD_MAC_SPI_SYS_3_REG[21:18]', bloc: 'B14[5:2]'} + WAFER_VERSION_MAJOR : {show: y, blk : 1, word: 3, pos: 22, len : 2, start: 118, type : 'uint:2', wr_dis : 20, rd_dis: null, alt : '', dict : '', desc: '', rloc: 'EFUSE_RD_MAC_SPI_SYS_3_REG[23:22]', bloc: 'B14[7:6]'} + PKG_VERSION : {show: y, blk : 1, word: 3, pos: 24, len : 3, start: 120, type : 'uint:3', wr_dis : 20, rd_dis: null, alt : '', dict : '', desc: Package version, rloc: 'EFUSE_RD_MAC_SPI_SYS_3_REG[26:24]', bloc: 'B15[2:0]'} + BLK_VERSION_MINOR : {show: y, blk : 1, word: 3, pos: 27, len : 3, start: 123, type : 'uint:3', wr_dis : 20, rd_dis: null, alt : '', dict : '', desc: BLK_VERSION_MINOR of BLOCK2, rloc: 'EFUSE_RD_MAC_SPI_SYS_3_REG[29:27]', bloc: 'B15[5:3]'} + BLK_VERSION_MAJOR : {show: y, blk : 1, word: 3, pos: 30, len : 2, start: 126, type : 'uint:2', wr_dis : 20, rd_dis: null, alt : '', dict : '', desc: BLK_VERSION_MAJOR of BLOCK2, rloc: 'EFUSE_RD_MAC_SPI_SYS_3_REG[31:30]', bloc: 'B15[7:6]'} + FLASH_CAP : {show: y, blk : 1, word: 4, pos : 0, len : 3, start: 128, type : 'uint:3', wr_dis : 20, rd_dis: null, alt : '', dict : '', desc: '', rloc: 'EFUSE_RD_MAC_SPI_SYS_4_REG[2:0]', bloc: 'B16[2:0]'} + FLASH_TEMP : {show: y, blk : 1, word: 4, pos : 3, len : 2, start: 131, type : 'uint:2', wr_dis : 20, rd_dis: null, alt : '', dict : '', desc: '', rloc: 'EFUSE_RD_MAC_SPI_SYS_4_REG[4:3]', bloc: 'B16[4:3]'} + FLASH_VENDOR : {show: y, blk : 1, word: 4, pos : 5, len : 3, start: 133, type : 'uint:3', wr_dis : 20, rd_dis: null, alt : '', dict : '', desc: '', rloc: 'EFUSE_RD_MAC_SPI_SYS_4_REG[7:5]', bloc: 'B16[7:5]'} + RESERVED_1_136 : {show: n, blk : 1, word: 4, pos : 8, len : 24, start: 136, type : 'uint:24', wr_dis : 20, rd_dis: null, alt : '', dict : '', desc: reserved, rloc: 'EFUSE_RD_MAC_SPI_SYS_4_REG[31:8]', bloc: 'B17,B18,B19'} + SYS_DATA_PART0_2 : {show: n, blk : 1, word: 5, pos : 0, len : 32, start: 160, type : 'uint:32', wr_dis : 20, rd_dis: null, alt : '', dict : '', desc: Stores the second 32 bits of the zeroth part of system data, rloc: EFUSE_RD_MAC_SPI_SYS_5_REG, bloc: 'B20,B21,B22,B23'} + OPTIONAL_UNIQUE_ID : {show: y, blk : 2, word: 0, pos : 0, len: 128, start : 0, type: 'bytes:16', wr_dis : 21, rd_dis: null, alt : '', dict : '', desc: Optional unique 128-bit ID, rloc: EFUSE_RD_SYS_PART1_DATA0_REG, bloc: 'B0,B1,B2,B3,B4,B5,B6,B7,B8,B9,B10,B11,B12,B13,B14,B15'} + TEMP_CALIB : {show: y, blk : 2, word: 4, pos : 0, len : 9, start: 128, type : 'uint:9', wr_dis : 21, rd_dis: null, alt : '', dict : '', desc: Temperature calibration data, rloc: 'EFUSE_RD_SYS_PART1_DATA4_REG[8:0]', bloc: 'B16,B17[0]'} + OCODE : {show: y, blk : 2, word: 4, pos : 9, len : 8, start: 137, type : 'uint:8', wr_dis : 21, rd_dis: null, alt : '', dict : '', desc: ADC OCode, rloc: 'EFUSE_RD_SYS_PART1_DATA4_REG[16:9]', bloc: 'B17[7:1],B18[0]'} + ADC1_INIT_CODE_ATTEN0 : {show: y, blk : 2, word: 4, pos: 17, len : 10, start: 145, type : 'uint:10', wr_dis : 21, rd_dis: null, alt : '', dict : '', desc: ADC1 init code at atten0, rloc: 'EFUSE_RD_SYS_PART1_DATA4_REG[26:17]', bloc: 'B18[7:1],B19[2:0]'} + ADC1_INIT_CODE_ATTEN1 : {show: y, blk : 2, word: 4, pos: 27, len : 10, start: 155, type : 'uint:10', wr_dis : 21, rd_dis: null, alt : '', dict : '', desc: ADC1 init code at atten1, rloc: 'EFUSE_RD_SYS_PART1_DATA4_REG[31:27]', bloc: 'B19[7:3],B20[4:0]'} + ADC1_INIT_CODE_ATTEN2 : {show: y, blk : 2, word: 5, pos : 5, len : 10, start: 165, type : 'uint:10', wr_dis : 21, rd_dis: null, alt : '', dict : '', desc: ADC1 init code at atten2, rloc: 'EFUSE_RD_SYS_PART1_DATA5_REG[14:5]', bloc: 'B20[7:5],B21[6:0]'} + ADC1_INIT_CODE_ATTEN3 : {show: y, blk : 2, word: 5, pos: 15, len : 10, start: 175, type : 'uint:10', wr_dis : 21, rd_dis: null, alt : '', dict : '', desc: ADC1 init code at atten3, rloc: 'EFUSE_RD_SYS_PART1_DATA5_REG[24:15]', bloc: 'B21[7],B22,B23[0]'} + ADC1_CAL_VOL_ATTEN0 : {show: y, blk : 2, word: 5, pos: 25, len : 10, start: 185, type : 'uint:10', wr_dis : 21, rd_dis: null, alt : '', dict : '', desc: ADC1 calibration voltage at atten0, rloc: 'EFUSE_RD_SYS_PART1_DATA5_REG[31:25]', bloc: 'B23[7:1],B24[2:0]'} + ADC1_CAL_VOL_ATTEN1 : {show: y, blk : 2, word: 6, pos : 3, len : 10, start: 195, type : 'uint:10', wr_dis : 21, rd_dis: null, alt : '', dict : '', desc: ADC1 calibration voltage at atten1, rloc: 'EFUSE_RD_SYS_PART1_DATA6_REG[12:3]', bloc: 'B24[7:3],B25[4:0]'} + ADC1_CAL_VOL_ATTEN2 : {show: y, blk : 2, word: 6, pos: 13, len : 10, start: 205, type : 'uint:10', wr_dis : 21, rd_dis: null, alt : '', dict : '', desc: ADC1 calibration voltage at atten2, rloc: 'EFUSE_RD_SYS_PART1_DATA6_REG[22:13]', bloc: 'B25[7:5],B26[6:0]'} + ADC1_CAL_VOL_ATTEN3 : {show: y, blk : 2, word: 6, pos: 23, len : 10, start: 215, type : 'uint:10', wr_dis : 21, rd_dis: null, alt : '', dict : '', desc: ADC1 calibration voltage at atten3, rloc: 'EFUSE_RD_SYS_PART1_DATA6_REG[31:23]', bloc: 'B26[7],B27,B28[0]'} + ADC1_INIT_CODE_ATTEN0_CH0 : {show: y, blk : 2, word: 7, pos : 1, len : 4, start: 225, type : 'uint:4', wr_dis : 21, rd_dis: null, alt : '', dict : '', desc: ADC1 init code at atten0 ch0, rloc: 'EFUSE_RD_SYS_PART1_DATA7_REG[4:1]', bloc: 'B28[4:1]'} + ADC1_INIT_CODE_ATTEN0_CH1 : {show: y, blk : 2, word: 7, pos : 5, len : 4, start: 229, type : 'uint:4', wr_dis : 21, rd_dis: null, alt : '', dict : '', desc: ADC1 init code at atten0 ch1, rloc: 'EFUSE_RD_SYS_PART1_DATA7_REG[8:5]', bloc: 'B28[7:5],B29[0]'} + ADC1_INIT_CODE_ATTEN0_CH2 : {show: y, blk : 2, word: 7, pos : 9, len : 4, start: 233, type : 'uint:4', wr_dis : 21, rd_dis: null, alt : '', dict : '', desc: ADC1 init code at atten0 ch2, rloc: 'EFUSE_RD_SYS_PART1_DATA7_REG[12:9]', bloc: 'B29[4:1]'} + ADC1_INIT_CODE_ATTEN0_CH3 : {show: y, blk : 2, word: 7, pos: 13, len : 4, start: 237, type : 'uint:4', wr_dis : 21, rd_dis: null, alt : '', dict : '', desc: ADC1 init code at atten0 ch3, rloc: 'EFUSE_RD_SYS_PART1_DATA7_REG[16:13]', bloc: 'B29[7:5],B30[0]'} + ADC1_INIT_CODE_ATTEN0_CH4 : {show: y, blk : 2, word: 7, pos: 17, len : 4, start: 241, type : 'uint:4', wr_dis : 21, rd_dis: null, alt : '', dict : '', desc: ADC1 init code at atten0 ch4, rloc: 'EFUSE_RD_SYS_PART1_DATA7_REG[20:17]', bloc: 'B30[4:1]'} + ADC1_INIT_CODE_ATTEN0_CH5 : {show: y, blk : 2, word: 7, pos: 21, len : 4, start: 245, type : 'uint:4', wr_dis : 21, rd_dis: null, alt : '', dict : '', desc: ADC1 init code at atten0 ch5, rloc: 'EFUSE_RD_SYS_PART1_DATA7_REG[24:21]', bloc: 'B30[7:5],B31[0]'} + ADC1_INIT_CODE_ATTEN0_CH6 : {show: y, blk : 2, word: 7, pos: 25, len : 4, start: 249, type : 'uint:4', wr_dis : 21, rd_dis: null, alt : '', dict : '', desc: ADC1 init code at atten0 ch6, rloc: 'EFUSE_RD_SYS_PART1_DATA7_REG[28:25]', bloc: 'B31[4:1]'} + RESERVED_2_253 : {show: n, blk : 2, word: 7, pos: 29, len : 3, start: 253, type : 'uint:3', wr_dis : 21, rd_dis: null, alt : '', dict : '', desc: reserved, rloc: 'EFUSE_RD_SYS_PART1_DATA7_REG[31:29]', bloc: 'B31[7:5]'} + BLOCK_USR_DATA : {show: y, blk : 3, word: 0, pos : 0, len: 192, start : 0, type: 'bytes:24', wr_dis : 22, rd_dis: null, alt : USER_DATA, dict : '', desc: User data, rloc: EFUSE_RD_USR_DATA0_REG, bloc: 'B0,B1,B2,B3,B4,B5,B6,B7,B8,B9,B10,B11,B12,B13,B14,B15,B16,B17,B18,B19,B20,B21,B22,B23'} + RESERVED_3_192 : {show: n, blk : 3, word: 6, pos : 0, len : 8, start: 192, type : 'uint:8', wr_dis : 22, rd_dis: null, alt : '', dict : '', desc: reserved, rloc: 'EFUSE_RD_USR_DATA6_REG[7:0]', bloc: B24} + CUSTOM_MAC : {show: y, blk : 3, word: 6, pos : 8, len : 48, start: 200, type : 'bytes:6', wr_dis : 22, rd_dis: null, alt: MAC_CUSTOM USER_DATA_MAC_CUSTOM, dict : '', desc: Custom MAC, rloc: 'EFUSE_RD_USR_DATA6_REG[31:8]', bloc: 'B25,B26,B27,B28,B29,B30'} + RESERVED_3_248 : {show: n, blk : 3, word: 7, pos: 24, len : 8, start: 248, type : 'uint:8', wr_dis : 22, rd_dis: null, alt : '', dict : '', desc: reserved, rloc: 'EFUSE_RD_USR_DATA7_REG[31:24]', bloc: B31} + BLOCK_KEY0 : {show: y, blk : 4, word: 0, pos : 0, len: 256, start : 0, type: 'bytes:32', wr_dis : 23, rd_dis : 0, alt : KEY0, dict : '', desc: Key0 or user data, rloc: EFUSE_RD_KEY0_DATA0_REG, bloc: 'B0,B1,B2,B3,B4,B5,B6,B7,B8,B9,B10,B11,B12,B13,B14,B15,B16,B17,B18,B19,B20,B21,B22,B23,B24,B25,B26,B27,B28,B29,B30,B31'} + BLOCK_KEY1 : {show: y, blk : 5, word: 0, pos : 0, len: 256, start : 0, type: 'bytes:32', wr_dis : 24, rd_dis : 1, alt : KEY1, dict : '', desc: Key1 or user data, rloc: EFUSE_RD_KEY1_DATA0_REG, bloc: 'B0,B1,B2,B3,B4,B5,B6,B7,B8,B9,B10,B11,B12,B13,B14,B15,B16,B17,B18,B19,B20,B21,B22,B23,B24,B25,B26,B27,B28,B29,B30,B31'} + BLOCK_KEY2 : {show: y, blk : 6, word: 0, pos : 0, len: 256, start : 0, type: 'bytes:32', wr_dis : 25, rd_dis : 2, alt : KEY2, dict : '', desc: Key2 or user data, rloc: EFUSE_RD_KEY2_DATA0_REG, bloc: 'B0,B1,B2,B3,B4,B5,B6,B7,B8,B9,B10,B11,B12,B13,B14,B15,B16,B17,B18,B19,B20,B21,B22,B23,B24,B25,B26,B27,B28,B29,B30,B31'} + BLOCK_KEY3 : {show: y, blk : 7, word: 0, pos : 0, len: 256, start : 0, type: 'bytes:32', wr_dis : 26, rd_dis : 3, alt : KEY3, dict : '', desc: Key3 or user data, rloc: EFUSE_RD_KEY3_DATA0_REG, bloc: 'B0,B1,B2,B3,B4,B5,B6,B7,B8,B9,B10,B11,B12,B13,B14,B15,B16,B17,B18,B19,B20,B21,B22,B23,B24,B25,B26,B27,B28,B29,B30,B31'} + BLOCK_KEY4 : {show: y, blk : 8, word: 0, pos : 0, len: 256, start : 0, type: 'bytes:32', wr_dis : 27, rd_dis : 4, alt : KEY4, dict : '', desc: Key4 or user data, rloc: EFUSE_RD_KEY4_DATA0_REG, bloc: 'B0,B1,B2,B3,B4,B5,B6,B7,B8,B9,B10,B11,B12,B13,B14,B15,B16,B17,B18,B19,B20,B21,B22,B23,B24,B25,B26,B27,B28,B29,B30,B31'} + BLOCK_KEY5 : {show: y, blk : 9, word: 0, pos : 0, len: 256, start : 0, type: 'bytes:32', wr_dis : 28, rd_dis : 5, alt : KEY5, dict : '', desc: Key5 or user data, rloc: EFUSE_RD_KEY5_DATA0_REG, bloc: 'B0,B1,B2,B3,B4,B5,B6,B7,B8,B9,B10,B11,B12,B13,B14,B15,B16,B17,B18,B19,B20,B21,B22,B23,B24,B25,B26,B27,B28,B29,B30,B31'} + BLOCK_SYS_DATA2 : {show: y, blk: 10, word: 0, pos : 0, len: 256, start : 0, type: 'bytes:32', wr_dis : 29, rd_dis : 6, alt : SYS_DATA_PART2, dict : '', desc: System data part 2 (reserved), rloc: EFUSE_RD_SYS_PART2_DATA0_REG, bloc: 'B0,B1,B2,B3,B4,B5,B6,B7,B8,B9,B10,B11,B12,B13,B14,B15,B16,B17,B18,B19,B20,B21,B22,B23,B24,B25,B26,B27,B28,B29,B30,B31'} diff --git a/espefuse/efuse_defs/esp32h2.yaml b/espefuse/efuse_defs/esp32h2.yaml new file mode 100644 index 000000000..a86a01895 --- /dev/null +++ b/espefuse/efuse_defs/esp32h2.yaml @@ -0,0 +1,103 @@ +VER_NO: b69ddcfb39a412df490e3facbbfb46b2 +EFUSES: + WR_DIS : {show: y, blk : 0, word: 0, pos : 0, len : 32, start : 0, type : 'uint:32', wr_dis: null, rd_dis: null, alt : '', dict : '', desc: Disable programming of individual eFuses, rloc: EFUSE_RD_WR_DIS_REG, bloc: 'B0,B1,B2,B3'} + RD_DIS : {show: y, blk : 0, word: 1, pos : 0, len : 7, start : 32, type : 'uint:7', wr_dis : 0, rd_dis: null, alt : '', dict : '', desc: Disable reading from BlOCK4-10, rloc: 'EFUSE_RD_REPEAT_DATA0_REG[6:0]', bloc: 'B4[6:0]'} + RPT4_RESERVED0_4 : {show: n, blk : 0, word: 1, pos : 7, len : 1, start : 39, type : bool, wr_dis: null, rd_dis: null, alt : '', dict : '', desc: Reserved, rloc: 'EFUSE_RD_REPEAT_DATA0_REG[7]', bloc: 'B4[7]'} + DIS_ICACHE : {show: y, blk : 0, word: 1, pos : 8, len : 1, start : 40, type : bool, wr_dis : 2, rd_dis: null, alt : '', dict : '', desc: 'Represents whether icache is disabled or enabled. 1: disabled. 0: enabled', rloc: 'EFUSE_RD_REPEAT_DATA0_REG[8]', bloc: 'B5[0]'} + DIS_USB_JTAG : {show: y, blk : 0, word: 1, pos : 9, len : 1, start : 41, type : bool, wr_dis : 2, rd_dis: null, alt : '', dict : '', desc: 'Represents whether the function of usb switch to jtag is disabled or enabled. 1: disabled. 0: enabled', rloc: 'EFUSE_RD_REPEAT_DATA0_REG[9]', bloc: 'B5[1]'} + POWERGLITCH_EN : {show: y, blk : 0, word: 1, pos: 10, len : 1, start : 42, type : bool, wr_dis : 2, rd_dis: null, alt : '', dict : '', desc: 'Represents whether power glitch function is enabled. 1: enabled. 0: disabled', rloc: 'EFUSE_RD_REPEAT_DATA0_REG[10]', bloc: 'B5[2]'} + DIS_USB_SERIAL_JTAG : {show: n, blk : 0, word: 1, pos: 11, len : 1, start : 43, type : bool, wr_dis : 2, rd_dis: null, alt : '', dict : '', desc: 'Represents whether USB-Serial-JTAG is disabled or enabled. 1: disabled. 0: enabled', rloc: 'EFUSE_RD_REPEAT_DATA0_REG[11]', bloc: 'B5[3]'} + DIS_FORCE_DOWNLOAD : {show: y, blk : 0, word: 1, pos: 12, len : 1, start : 44, type : bool, wr_dis : 2, rd_dis: null, alt : '', dict : '', desc: 'Represents whether the function that forces chip into download mode is disabled or enabled. 1: disabled. 0: enabled', rloc: 'EFUSE_RD_REPEAT_DATA0_REG[12]', bloc: 'B5[4]'} + SPI_DOWNLOAD_MSPI_DIS : {show: y, blk : 0, word: 1, pos: 13, len : 1, start : 45, type : bool, wr_dis : 2, rd_dis: null, alt : '', dict : '', desc: 'Represents whether SPI0 controller during boot_mode_download is disabled or enabled. 1: disabled. 0: enabled', rloc: 'EFUSE_RD_REPEAT_DATA0_REG[13]', bloc: 'B5[5]'} + DIS_TWAI : {show: y, blk : 0, word: 1, pos: 14, len : 1, start : 46, type : bool, wr_dis : 2, rd_dis: null, alt : DIS_CAN, dict : '', desc: 'Represents whether TWAI function is disabled or enabled. 1: disabled. 0: enabled', rloc: 'EFUSE_RD_REPEAT_DATA0_REG[14]', bloc: 'B5[6]'} + JTAG_SEL_ENABLE : {show: y, blk : 0, word: 1, pos: 15, len : 1, start : 47, type : bool, wr_dis : 2, rd_dis: null, alt : '', dict : '', desc: Set this bit to enable selection between usb_to_jtag and pad_to_jtag through strapping gpio25 when both EFUSE_DIS_PAD_JTAG and EFUSE_DIS_USB_JTAG are equal to 0, rloc: 'EFUSE_RD_REPEAT_DATA0_REG[15]', bloc: 'B5[7]'} + SOFT_DIS_JTAG : {show: y, blk : 0, word: 1, pos: 16, len : 3, start : 48, type : 'uint:3', wr_dis : 31, rd_dis: null, alt : '', dict : '', desc: 'Represents whether JTAG is disabled in soft way. Odd number: disabled. Even number: enabled', rloc: 'EFUSE_RD_REPEAT_DATA0_REG[18:16]', bloc: 'B6[2:0]'} + DIS_PAD_JTAG : {show: y, blk : 0, word: 1, pos: 19, len : 1, start : 51, type : bool, wr_dis : 2, rd_dis: null, alt : '', dict : '', desc: 'Represents whether JTAG is disabled in the hard way(permanently). 1: disabled. 0: enabled', rloc: 'EFUSE_RD_REPEAT_DATA0_REG[19]', bloc: 'B6[3]'} + DIS_DOWNLOAD_MANUAL_ENCRYPT : {show: y, blk : 0, word: 1, pos: 20, len : 1, start : 52, type : bool, wr_dis : 2, rd_dis: null, alt : '', dict : '', desc: 'Represents whether flash encrypt function is disabled or enabled(except in SPI boot mode). 1: disabled. 0: enabled', rloc: 'EFUSE_RD_REPEAT_DATA0_REG[20]', bloc: 'B6[4]'} + USB_DREFH : {show: n, blk : 0, word: 1, pos: 21, len : 2, start : 53, type : 'uint:2', wr_dis : 30, rd_dis: null, alt : '', dict : '', desc: Represents the single-end input threhold vrefh; 1.76 V to 2 V with step of 80 mV, rloc: 'EFUSE_RD_REPEAT_DATA0_REG[22:21]', bloc: 'B6[6:5]'} + USB_DREFL : {show: n, blk : 0, word: 1, pos: 23, len : 2, start : 55, type : 'uint:2', wr_dis : 30, rd_dis: null, alt : '', dict : '', desc: Represents the single-end input threhold vrefl; 1.76 V to 2 V with step of 80 mV, rloc: 'EFUSE_RD_REPEAT_DATA0_REG[24:23]', bloc: 'B6[7],B7[0]'} + USB_EXCHG_PINS : {show: y, blk : 0, word: 1, pos: 25, len : 1, start : 57, type : bool, wr_dis : 30, rd_dis: null, alt : '', dict : '', desc: 'Represents whether the D+ and D- pins is exchanged. 1: exchanged. 0: not exchanged', rloc: 'EFUSE_RD_REPEAT_DATA0_REG[25]', bloc: 'B7[1]'} + VDD_SPI_AS_GPIO : {show: y, blk : 0, word: 1, pos: 26, len : 1, start : 58, type : bool, wr_dis : 30, rd_dis: null, alt : '', dict : '', desc: 'Represents whether vdd spi pin is functioned as gpio. 1: functioned. 0: not functioned', rloc: 'EFUSE_RD_REPEAT_DATA0_REG[26]', bloc: 'B7[2]'} + RPT4_RESERVED0_2 : {show: n, blk : 0, word: 1, pos: 27, len : 2, start : 59, type : 'uint:2', wr_dis: null, rd_dis: null, alt : '', dict : '', desc: Reserved, rloc: 'EFUSE_RD_REPEAT_DATA0_REG[28:27]', bloc: 'B7[4:3]'} + RPT4_RESERVED0_1 : {show: n, blk : 0, word: 1, pos: 29, len : 1, start : 61, type : bool, wr_dis: null, rd_dis: null, alt : '', dict : '', desc: Reserved, rloc: 'EFUSE_RD_REPEAT_DATA0_REG[29]', bloc: 'B7[5]'} + RPT4_RESERVED0_0 : {show: n, blk : 0, word: 1, pos: 30, len : 2, start : 62, type : 'uint:2', wr_dis: null, rd_dis: null, alt : '', dict : '', desc: Reserved, rloc: 'EFUSE_RD_REPEAT_DATA0_REG[31:30]', bloc: 'B7[7:6]'} + RPT4_RESERVED1_1 : {show: n, blk : 0, word: 2, pos : 0, len : 16, start : 64, type : 'uint:16', wr_dis: null, rd_dis: null, alt : '', dict : '', desc: Reserved, rloc: 'EFUSE_RD_REPEAT_DATA1_REG[15:0]', bloc: 'B8,B9'} + WDT_DELAY_SEL : {show: y, blk : 0, word: 2, pos: 16, len : 2, start : 80, type : 'uint:2', wr_dis : 3, rd_dis: null, alt : '', dict : '', desc: 'Represents whether RTC watchdog timeout threshold is selected at startup. 1: selected. 0: not selected', rloc: 'EFUSE_RD_REPEAT_DATA1_REG[17:16]', bloc: 'B10[1:0]'} + SPI_BOOT_CRYPT_CNT : {show: y, blk : 0, word: 2, pos: 18, len : 3, start : 82, type : 'uint:3', wr_dis : 4, rd_dis: null, alt : '', dict: '{0: "Disable", 1: "Enable", 3: "Disable", 7: "Enable"}', desc: Enables flash encryption when 1 or 3 bits are set and disables otherwise, rloc: 'EFUSE_RD_REPEAT_DATA1_REG[20:18]', bloc: 'B10[4:2]'} + SECURE_BOOT_KEY_REVOKE0 : {show: y, blk : 0, word: 2, pos: 21, len : 1, start : 85, type : bool, wr_dis : 5, rd_dis: null, alt : '', dict : '', desc: Revoke 1st secure boot key, rloc: 'EFUSE_RD_REPEAT_DATA1_REG[21]', bloc: 'B10[5]'} + SECURE_BOOT_KEY_REVOKE1 : {show: y, blk : 0, word: 2, pos: 22, len : 1, start : 86, type : bool, wr_dis : 6, rd_dis: null, alt : '', dict : '', desc: Revoke 2nd secure boot key, rloc: 'EFUSE_RD_REPEAT_DATA1_REG[22]', bloc: 'B10[6]'} + SECURE_BOOT_KEY_REVOKE2 : {show: y, blk : 0, word: 2, pos: 23, len : 1, start : 87, type : bool, wr_dis : 7, rd_dis: null, alt : '', dict : '', desc: Revoke 3rd secure boot key, rloc: 'EFUSE_RD_REPEAT_DATA1_REG[23]', bloc: 'B10[7]'} + KEY_PURPOSE_0 : {show: y, blk : 0, word: 2, pos: 24, len : 4, start : 88, type : 'uint:4', wr_dis : 8, rd_dis: null, alt : KEY0_PURPOSE, dict : '', desc: Represents the purpose of Key0, rloc: 'EFUSE_RD_REPEAT_DATA1_REG[27:24]', bloc: 'B11[3:0]'} + KEY_PURPOSE_1 : {show: y, blk : 0, word: 2, pos: 28, len : 4, start : 92, type : 'uint:4', wr_dis : 9, rd_dis: null, alt : KEY1_PURPOSE, dict : '', desc: Represents the purpose of Key1, rloc: 'EFUSE_RD_REPEAT_DATA1_REG[31:28]', bloc: 'B11[7:4]'} + KEY_PURPOSE_2 : {show: y, blk : 0, word: 3, pos : 0, len : 4, start : 96, type : 'uint:4', wr_dis : 10, rd_dis: null, alt : KEY2_PURPOSE, dict : '', desc: Represents the purpose of Key2, rloc: 'EFUSE_RD_REPEAT_DATA2_REG[3:0]', bloc: 'B12[3:0]'} + KEY_PURPOSE_3 : {show: y, blk : 0, word: 3, pos : 4, len : 4, start: 100, type : 'uint:4', wr_dis : 11, rd_dis: null, alt : KEY3_PURPOSE, dict : '', desc: Represents the purpose of Key3, rloc: 'EFUSE_RD_REPEAT_DATA2_REG[7:4]', bloc: 'B12[7:4]'} + KEY_PURPOSE_4 : {show: y, blk : 0, word: 3, pos : 8, len : 4, start: 104, type : 'uint:4', wr_dis : 12, rd_dis: null, alt : KEY4_PURPOSE, dict : '', desc: Represents the purpose of Key4, rloc: 'EFUSE_RD_REPEAT_DATA2_REG[11:8]', bloc: 'B13[3:0]'} + KEY_PURPOSE_5 : {show: y, blk : 0, word: 3, pos: 12, len : 4, start: 108, type : 'uint:4', wr_dis : 13, rd_dis: null, alt : KEY5_PURPOSE, dict : '', desc: Represents the purpose of Key5, rloc: 'EFUSE_RD_REPEAT_DATA2_REG[15:12]', bloc: 'B13[7:4]'} + SEC_DPA_LEVEL : {show: y, blk : 0, word: 3, pos: 16, len : 2, start: 112, type : 'uint:2', wr_dis : 14, rd_dis: null, alt : '', dict : '', desc: Represents the spa secure level by configuring the clock random divide mode, rloc: 'EFUSE_RD_REPEAT_DATA2_REG[17:16]', bloc: 'B14[1:0]'} + ECDSA_FORCE_USE_HARDWARE_K : {show: y, blk : 0, word: 3, pos: 18, len : 1, start: 114, type : bool, wr_dis : 17, rd_dis: null, alt : '', dict : '', desc: 'Represents whether hardware random number k is forced used in ESDCA. 1: force used. 0: not force used', rloc: 'EFUSE_RD_REPEAT_DATA2_REG[18]', bloc: 'B14[2]'} + CRYPT_DPA_ENABLE : {show: y, blk : 0, word: 3, pos: 19, len : 1, start: 115, type : bool, wr_dis : 14, rd_dis: null, alt : '', dict : '', desc: 'Represents whether anti-dpa attack is enabled. 1:enabled. 0: disabled', rloc: 'EFUSE_RD_REPEAT_DATA2_REG[19]', bloc: 'B14[3]'} + SECURE_BOOT_EN : {show: y, blk : 0, word: 3, pos: 20, len : 1, start: 116, type : bool, wr_dis : 15, rd_dis: null, alt : '', dict : '', desc: 'Represents whether secure boot is enabled or disabled. 1: enabled. 0: disabled', rloc: 'EFUSE_RD_REPEAT_DATA2_REG[20]', bloc: 'B14[4]'} + SECURE_BOOT_AGGRESSIVE_REVOKE : {show: y, blk : 0, word: 3, pos: 21, len : 1, start: 117, type : bool, wr_dis : 16, rd_dis: null, alt : '', dict : '', desc: 'Represents whether revoking aggressive secure boot is enabled or disabled. 1: enabled. 0: disabled', rloc: 'EFUSE_RD_REPEAT_DATA2_REG[21]', bloc: 'B14[5]'} + RPT4_RESERVED2_0 : {show: n, blk : 0, word: 3, pos: 22, len : 6, start: 118, type : 'uint:6', wr_dis: null, rd_dis: null, alt : '', dict : '', desc: Reserved, rloc: 'EFUSE_RD_REPEAT_DATA2_REG[27:22]', bloc: 'B14[7:6],B15[3:0]'} + FLASH_TPUW : {show: y, blk : 0, word: 3, pos: 28, len : 4, start: 124, type : 'uint:4', wr_dis : 18, rd_dis: null, alt : '', dict : '', desc: Represents the flash waiting time after power-up; in unit of ms. When the value less than 15; the waiting time is the programmed value. Otherwise; the waiting time is 2 times the programmed value, rloc: 'EFUSE_RD_REPEAT_DATA2_REG[31:28]', bloc: 'B15[7:4]'} + DIS_DOWNLOAD_MODE : {show: y, blk : 0, word: 4, pos : 0, len : 1, start: 128, type : bool, wr_dis : 18, rd_dis: null, alt : '', dict : '', desc: 'Represents whether Download mode is disabled or enabled. 1: disabled. 0: enabled', rloc: 'EFUSE_RD_REPEAT_DATA3_REG[0]', bloc: 'B16[0]'} + DIS_DIRECT_BOOT : {show: y, blk : 0, word: 4, pos : 1, len : 1, start: 129, type : bool, wr_dis : 18, rd_dis: null, alt : '', dict : '', desc: 'Represents whether direct boot mode is disabled or enabled. 1: disabled. 0: enabled', rloc: 'EFUSE_RD_REPEAT_DATA3_REG[1]', bloc: 'B16[1]'} + DIS_USB_SERIAL_JTAG_ROM_PRINT : {show: y, blk : 0, word: 4, pos : 2, len : 1, start: 130, type : bool, wr_dis : 18, rd_dis: null, alt : DIS_USB_PRINT, dict : '', desc: Set this bit to disable USB-Serial-JTAG print during rom boot, rloc: 'EFUSE_RD_REPEAT_DATA3_REG[2]', bloc: 'B16[2]'} + RPT4_RESERVED3_5 : {show: n, blk : 0, word: 4, pos : 3, len : 1, start: 131, type : bool, wr_dis: null, rd_dis: null, alt : '', dict : '', desc: Reserved, rloc: 'EFUSE_RD_REPEAT_DATA3_REG[3]', bloc: 'B16[3]'} + DIS_USB_SERIAL_JTAG_DOWNLOAD_MODE: {show: y, blk : 0, word: 4, pos : 4, len : 1, start: 132, type : bool, wr_dis : 18, rd_dis: null, alt : '', dict : '', desc: 'Represents whether the USB-Serial-JTAG download function is disabled or enabled. 1: disabled. 0: enabled', rloc: 'EFUSE_RD_REPEAT_DATA3_REG[4]', bloc: 'B16[4]'} + ENABLE_SECURITY_DOWNLOAD : {show: y, blk : 0, word: 4, pos : 5, len : 1, start: 133, type : bool, wr_dis : 18, rd_dis: null, alt : '', dict : '', desc: 'Represents whether security download is enabled or disabled. 1: enabled. 0: disabled', rloc: 'EFUSE_RD_REPEAT_DATA3_REG[5]', bloc: 'B16[5]'} + UART_PRINT_CONTROL : {show: y, blk : 0, word: 4, pos : 6, len : 2, start: 134, type : 'uint:2', wr_dis : 18, rd_dis: null, alt : '', dict: '{0: "Enable", 1: "Enable when GPIO8 is low at reset", 2: "Enable when GPIO8 is high at reset", 3: "Disable"}', desc: Set the default UARTboot message output mode, rloc: 'EFUSE_RD_REPEAT_DATA3_REG[7:6]', bloc: 'B16[7:6]'} + FORCE_SEND_RESUME : {show: y, blk : 0, word: 4, pos : 8, len : 1, start: 136, type : bool, wr_dis : 18, rd_dis: null, alt : '', dict : '', desc: 'Represents whether ROM code is forced to send a resume command during SPI boot. 1: forced. 0:not forced', rloc: 'EFUSE_RD_REPEAT_DATA3_REG[8]', bloc: 'B17[0]'} + SECURE_VERSION : {show: y, blk : 0, word: 4, pos : 9, len : 16, start: 137, type : 'uint:16', wr_dis : 18, rd_dis: null, alt : '', dict : '', desc: Represents the version used by ESP-IDF anti-rollback feature, rloc: 'EFUSE_RD_REPEAT_DATA3_REG[24:9]', bloc: 'B17[7:1],B18,B19[0]'} + SECURE_BOOT_DISABLE_FAST_WAKE : {show: y, blk : 0, word: 4, pos: 25, len : 1, start: 153, type : bool, wr_dis : 18, rd_dis: null, alt : '', dict : '', desc: 'Represents whether FAST VERIFY ON WAKE is disabled or enabled when Secure Boot is enabled. 1: disabled. 0: enabled', rloc: 'EFUSE_RD_REPEAT_DATA3_REG[25]', bloc: 'B19[1]'} + HYS_EN_PAD0 : {show: y, blk : 0, word: 4, pos: 26, len : 6, start: 154, type : 'uint:6', wr_dis : 19, rd_dis: null, alt : '', dict : '', desc: Set bits to enable hysteresis function of PAD0~5, rloc: 'EFUSE_RD_REPEAT_DATA3_REG[31:26]', bloc: 'B19[7:2]'} + HYS_EN_PAD1 : {show: y, blk : 0, word: 5, pos : 0, len : 22, start: 160, type : 'uint:22', wr_dis : 19, rd_dis: null, alt : '', dict : '', desc: Set bits to enable hysteresis function of PAD6~27, rloc: 'EFUSE_RD_REPEAT_DATA4_REG[21:0]', bloc: 'B20,B21,B22[5:0]'} + RPT4_RESERVED4_1 : {show: n, blk : 0, word: 5, pos: 22, len : 2, start: 182, type : 'uint:2', wr_dis: null, rd_dis: null, alt : '', dict : '', desc: Reserved, rloc: 'EFUSE_RD_REPEAT_DATA4_REG[23:22]', bloc: 'B22[7:6]'} + RPT4_RESERVED4_0 : {show: n, blk : 0, word: 5, pos: 24, len : 8, start: 184, type : 'uint:8', wr_dis: null, rd_dis: null, alt : '', dict : '', desc: Reserved, rloc: 'EFUSE_RD_REPEAT_DATA4_REG[31:24]', bloc: B23} + MAC : {show: y, blk : 1, word: 0, pos : 0, len : 48, start : 0, type : 'bytes:6', wr_dis : 20, rd_dis: null, alt : MAC_FACTORY, dict : '', desc: MAC address, rloc: EFUSE_RD_MAC_SYS_0_REG, bloc: 'B0,B1,B2,B3,B4,B5'} + MAC_EXT : {show: y, blk : 1, word: 1, pos: 16, len : 16, start : 48, type : 'bytes:2', wr_dis : 20, rd_dis: null, alt : '', dict : '', desc: Stores the extended bits of MAC address, rloc: 'EFUSE_RD_MAC_SYS_1_REG[31:16]', bloc: 'B6,B7'} + RXIQ_VERSION : {show: y, blk : 1, word: 2, pos : 0, len : 3, start : 64, type : 'uint:3', wr_dis : 20, rd_dis: null, alt : '', dict : '', desc: RF Calibration data. RXIQ version, rloc: 'EFUSE_RD_MAC_SYS_2_REG[2:0]', bloc: 'B8[2:0]'} + RXIQ_0 : {show: y, blk : 1, word: 2, pos : 3, len : 7, start : 67, type : 'uint:7', wr_dis : 20, rd_dis: null, alt : '', dict : '', desc: RF Calibration data. RXIQ data 0, rloc: 'EFUSE_RD_MAC_SYS_2_REG[9:3]', bloc: 'B8[7:3],B9[1:0]'} + RXIQ_1 : {show: y, blk : 1, word: 2, pos: 10, len : 7, start : 74, type : 'uint:7', wr_dis : 20, rd_dis: null, alt : '', dict : '', desc: RF Calibration data. RXIQ data 1, rloc: 'EFUSE_RD_MAC_SYS_2_REG[16:10]', bloc: 'B9[7:2],B10[0]'} + RESERVED_1_81 : {show: n, blk : 1, word: 2, pos: 17, len : 15, start : 81, type : 'uint:15', wr_dis : 20, rd_dis: null, alt : '', dict : '', desc: reserved, rloc: 'EFUSE_RD_MAC_SYS_2_REG[31:17]', bloc: 'B10[7:1],B11'} + MAC_RESERVED_2 : {show: n, blk : 1, word: 3, pos : 0, len : 18, start : 96, type : 'uint:18', wr_dis : 20, rd_dis: null, alt : '', dict : '', desc: Reserved, rloc: 'EFUSE_RD_MAC_SYS_3_REG[17:0]', bloc: 'B12,B13,B14[1:0]'} + WAFER_VERSION_MINOR : {show: y, blk : 1, word: 3, pos: 18, len : 3, start: 114, type : 'uint:3', wr_dis : 20, rd_dis: null, alt : '', dict : '', desc: '', rloc: 'EFUSE_RD_MAC_SYS_3_REG[20:18]', bloc: 'B14[4:2]'} + WAFER_VERSION_MAJOR : {show: y, blk : 1, word: 3, pos: 21, len : 2, start: 117, type : 'uint:2', wr_dis : 20, rd_dis: null, alt : '', dict : '', desc: '', rloc: 'EFUSE_RD_MAC_SYS_3_REG[22:21]', bloc: 'B14[6:5]'} + DISABLE_WAFER_VERSION_MAJOR : {show: y, blk : 1, word: 3, pos: 23, len : 1, start: 119, type : bool, wr_dis : 20, rd_dis: null, alt : '', dict : '', desc: Disables check of wafer version major, rloc: 'EFUSE_RD_MAC_SYS_3_REG[23]', bloc: 'B14[7]'} + FLASH_CAP : {show: y, blk : 1, word: 3, pos: 24, len : 3, start: 120, type : 'uint:3', wr_dis : 20, rd_dis: null, alt : '', dict : '', desc: '', rloc: 'EFUSE_RD_MAC_SYS_3_REG[26:24]', bloc: 'B15[2:0]'} + FLASH_TEMP : {show: y, blk : 1, word: 3, pos: 27, len : 2, start: 123, type : 'uint:2', wr_dis : 20, rd_dis: null, alt : '', dict : '', desc: '', rloc: 'EFUSE_RD_MAC_SYS_3_REG[28:27]', bloc: 'B15[4:3]'} + FLASH_VENDOR : {show: y, blk : 1, word: 3, pos: 29, len : 3, start: 125, type : 'uint:3', wr_dis : 20, rd_dis: null, alt : '', dict : '', desc: '', rloc: 'EFUSE_RD_MAC_SYS_3_REG[31:29]', bloc: 'B15[7:5]'} + PKG_VERSION : {show: y, blk : 1, word: 4, pos : 0, len : 3, start: 128, type : 'uint:3', wr_dis : 20, rd_dis: null, alt : '', dict : '', desc: Package version, rloc: 'EFUSE_RD_MAC_SYS_4_REG[2:0]', bloc: 'B16[2:0]'} + RESERVED_1_131 : {show: n, blk : 1, word: 4, pos : 3, len : 29, start: 131, type : 'uint:29', wr_dis : 20, rd_dis: null, alt : '', dict : '', desc: reserved, rloc: 'EFUSE_RD_MAC_SYS_4_REG[31:3]', bloc: 'B16[7:3],B17,B18,B19'} + SYS_DATA_PART0_2 : {show: n, blk : 1, word: 5, pos : 0, len : 32, start: 160, type : 'uint:32', wr_dis : 20, rd_dis: null, alt : '', dict : '', desc: Stores the second 32 bits of the zeroth part of system data, rloc: EFUSE_RD_MAC_SYS_5_REG, bloc: 'B20,B21,B22,B23'} + OPTIONAL_UNIQUE_ID : {show: y, blk : 2, word: 0, pos : 0, len: 128, start : 0, type: 'bytes:16', wr_dis : 21, rd_dis: null, alt : '', dict : '', desc: Optional unique 128-bit ID, rloc: EFUSE_RD_SYS_PART1_DATA0_REG, bloc: 'B0,B1,B2,B3,B4,B5,B6,B7,B8,B9,B10,B11,B12,B13,B14,B15'} + RESERVED_2_128 : {show: n, blk : 2, word: 4, pos : 0, len : 2, start: 128, type : 'uint:2', wr_dis : 21, rd_dis: null, alt : '', dict : '', desc: reserved, rloc: 'EFUSE_RD_SYS_PART1_DATA4_REG[1:0]', bloc: 'B16[1:0]'} + BLK_VERSION_MINOR : {show: y, blk : 2, word: 4, pos : 2, len : 3, start: 130, type : 'uint:3', wr_dis : 21, rd_dis: null, alt : '', dict : '', desc: 'BLK_VERSION_MINOR of BLOCK2. 1: RF Calibration data in BLOCK1', rloc: 'EFUSE_RD_SYS_PART1_DATA4_REG[4:2]', bloc: 'B16[4:2]'} + BLK_VERSION_MAJOR : {show: y, blk : 2, word: 4, pos : 5, len : 2, start: 133, type : 'uint:2', wr_dis : 21, rd_dis: null, alt : '', dict : '', desc: BLK_VERSION_MAJOR of BLOCK2, rloc: 'EFUSE_RD_SYS_PART1_DATA4_REG[6:5]', bloc: 'B16[6:5]'} + DISABLE_BLK_VERSION_MAJOR : {show: y, blk : 2, word: 4, pos : 7, len : 1, start: 135, type : bool, wr_dis : 21, rd_dis: null, alt : '', dict : '', desc: Disables check of blk version major, rloc: 'EFUSE_RD_SYS_PART1_DATA4_REG[7]', bloc: 'B16[7]'} + TEMP_CALIB : {show: y, blk : 2, word: 4, pos : 8, len : 9, start: 136, type : 'uint:9', wr_dis : 21, rd_dis: null, alt : '', dict : '', desc: Temperature calibration data, rloc: 'EFUSE_RD_SYS_PART1_DATA4_REG[16:8]', bloc: 'B17,B18[0]'} + ADC1_AVE_INITCODE_ATTEN0 : {show: y, blk : 2, word: 4, pos: 17, len : 10, start: 145, type : 'uint:10', wr_dis : 21, rd_dis: null, alt : '', dict : '', desc: ADC1 calibration data, rloc: 'EFUSE_RD_SYS_PART1_DATA4_REG[26:17]', bloc: 'B18[7:1],B19[2:0]'} + ADC1_AVE_INITCODE_ATTEN1 : {show: y, blk : 2, word: 4, pos: 27, len : 10, start: 155, type : 'uint:10', wr_dis : 21, rd_dis: null, alt : '', dict : '', desc: ADC1 calibration data, rloc: 'EFUSE_RD_SYS_PART1_DATA4_REG[31:27]', bloc: 'B19[7:3],B20[4:0]'} + ADC1_AVE_INITCODE_ATTEN2 : {show: y, blk : 2, word: 5, pos : 5, len : 10, start: 165, type : 'uint:10', wr_dis : 21, rd_dis: null, alt : '', dict : '', desc: ADC1 calibration data, rloc: 'EFUSE_RD_SYS_PART1_DATA5_REG[14:5]', bloc: 'B20[7:5],B21[6:0]'} + ADC1_AVE_INITCODE_ATTEN3 : {show: y, blk : 2, word: 5, pos: 15, len : 10, start: 175, type : 'uint:10', wr_dis : 21, rd_dis: null, alt : '', dict : '', desc: ADC1 calibration data, rloc: 'EFUSE_RD_SYS_PART1_DATA5_REG[24:15]', bloc: 'B21[7],B22,B23[0]'} + ADC1_HI_DOUT_ATTEN0 : {show: y, blk : 2, word: 5, pos: 25, len : 10, start: 185, type : 'uint:10', wr_dis : 21, rd_dis: null, alt : '', dict : '', desc: ADC1 calibration data, rloc: 'EFUSE_RD_SYS_PART1_DATA5_REG[31:25]', bloc: 'B23[7:1],B24[2:0]'} + ADC1_HI_DOUT_ATTEN1 : {show: y, blk : 2, word: 6, pos : 3, len : 10, start: 195, type : 'uint:10', wr_dis : 21, rd_dis: null, alt : '', dict : '', desc: ADC1 calibration data, rloc: 'EFUSE_RD_SYS_PART1_DATA6_REG[12:3]', bloc: 'B24[7:3],B25[4:0]'} + ADC1_HI_DOUT_ATTEN2 : {show: y, blk : 2, word: 6, pos: 13, len : 10, start: 205, type : 'uint:10', wr_dis : 21, rd_dis: null, alt : '', dict : '', desc: ADC1 calibration data, rloc: 'EFUSE_RD_SYS_PART1_DATA6_REG[22:13]', bloc: 'B25[7:5],B26[6:0]'} + ADC1_HI_DOUT_ATTEN3 : {show: y, blk : 2, word: 6, pos: 23, len : 10, start: 215, type : 'uint:10', wr_dis : 21, rd_dis: null, alt : '', dict : '', desc: ADC1 calibration data, rloc: 'EFUSE_RD_SYS_PART1_DATA6_REG[31:23]', bloc: 'B26[7],B27,B28[0]'} + ADC1_CH0_ATTEN0_INITCODE_DIFF : {show: y, blk : 2, word: 7, pos : 1, len : 4, start: 225, type : 'uint:4', wr_dis : 21, rd_dis: null, alt : '', dict : '', desc: ADC1 calibration data, rloc: 'EFUSE_RD_SYS_PART1_DATA7_REG[4:1]', bloc: 'B28[4:1]'} + ADC1_CH1_ATTEN0_INITCODE_DIFF : {show: y, blk : 2, word: 7, pos : 5, len : 4, start: 229, type : 'uint:4', wr_dis : 21, rd_dis: null, alt : '', dict : '', desc: ADC1 calibration data, rloc: 'EFUSE_RD_SYS_PART1_DATA7_REG[8:5]', bloc: 'B28[7:5],B29[0]'} + ADC1_CH2_ATTEN0_INITCODE_DIFF : {show: y, blk : 2, word: 7, pos : 9, len : 4, start: 233, type : 'uint:4', wr_dis : 21, rd_dis: null, alt : '', dict : '', desc: ADC1 calibration data, rloc: 'EFUSE_RD_SYS_PART1_DATA7_REG[12:9]', bloc: 'B29[4:1]'} + ADC1_CH3_ATTEN0_INITCODE_DIFF : {show: y, blk : 2, word: 7, pos: 13, len : 4, start: 237, type : 'uint:4', wr_dis : 21, rd_dis: null, alt : '', dict : '', desc: ADC1 calibration data, rloc: 'EFUSE_RD_SYS_PART1_DATA7_REG[16:13]', bloc: 'B29[7:5],B30[0]'} + ADC1_CH4_ATTEN0_INITCODE_DIFF : {show: y, blk : 2, word: 7, pos: 17, len : 4, start: 241, type : 'uint:4', wr_dis : 21, rd_dis: null, alt : '', dict : '', desc: ADC1 calibration data, rloc: 'EFUSE_RD_SYS_PART1_DATA7_REG[20:17]', bloc: 'B30[4:1]'} + RESERVED_2_245 : {show: n, blk : 2, word: 7, pos: 21, len : 11, start: 245, type : 'uint:11', wr_dis : 21, rd_dis: null, alt : '', dict : '', desc: reserved, rloc: 'EFUSE_RD_SYS_PART1_DATA7_REG[31:21]', bloc: 'B30[7:5],B31'} + BLOCK_USR_DATA : {show: y, blk : 3, word: 0, pos : 0, len: 192, start : 0, type: 'bytes:24', wr_dis : 22, rd_dis: null, alt : USER_DATA, dict : '', desc: User data, rloc: EFUSE_RD_USR_DATA0_REG, bloc: 'B0,B1,B2,B3,B4,B5,B6,B7,B8,B9,B10,B11,B12,B13,B14,B15,B16,B17,B18,B19,B20,B21,B22,B23'} + RESERVED_3_192 : {show: n, blk : 3, word: 6, pos : 0, len : 8, start: 192, type : 'uint:8', wr_dis : 22, rd_dis: null, alt : '', dict : '', desc: reserved, rloc: 'EFUSE_RD_USR_DATA6_REG[7:0]', bloc: B24} + CUSTOM_MAC : {show: y, blk : 3, word: 6, pos : 8, len : 48, start: 200, type : 'bytes:6', wr_dis : 22, rd_dis: null, alt: MAC_CUSTOM USER_DATA_MAC_CUSTOM, dict : '', desc: Custom MAC, rloc: 'EFUSE_RD_USR_DATA6_REG[31:8]', bloc: 'B25,B26,B27,B28,B29,B30'} + RESERVED_3_248 : {show: n, blk : 3, word: 7, pos: 24, len : 8, start: 248, type : 'uint:8', wr_dis : 22, rd_dis: null, alt : '', dict : '', desc: reserved, rloc: 'EFUSE_RD_USR_DATA7_REG[31:24]', bloc: B31} + BLOCK_KEY0 : {show: y, blk : 4, word: 0, pos : 0, len: 256, start : 0, type: 'bytes:32', wr_dis : 23, rd_dis : 0, alt : KEY0, dict : '', desc: Key0 or user data, rloc: EFUSE_RD_KEY0_DATA0_REG, bloc: 'B0,B1,B2,B3,B4,B5,B6,B7,B8,B9,B10,B11,B12,B13,B14,B15,B16,B17,B18,B19,B20,B21,B22,B23,B24,B25,B26,B27,B28,B29,B30,B31'} + BLOCK_KEY1 : {show: y, blk : 5, word: 0, pos : 0, len: 256, start : 0, type: 'bytes:32', wr_dis : 24, rd_dis : 1, alt : KEY1, dict : '', desc: Key1 or user data, rloc: EFUSE_RD_KEY1_DATA0_REG, bloc: 'B0,B1,B2,B3,B4,B5,B6,B7,B8,B9,B10,B11,B12,B13,B14,B15,B16,B17,B18,B19,B20,B21,B22,B23,B24,B25,B26,B27,B28,B29,B30,B31'} + BLOCK_KEY2 : {show: y, blk : 6, word: 0, pos : 0, len: 256, start : 0, type: 'bytes:32', wr_dis : 25, rd_dis : 2, alt : KEY2, dict : '', desc: Key2 or user data, rloc: EFUSE_RD_KEY2_DATA0_REG, bloc: 'B0,B1,B2,B3,B4,B5,B6,B7,B8,B9,B10,B11,B12,B13,B14,B15,B16,B17,B18,B19,B20,B21,B22,B23,B24,B25,B26,B27,B28,B29,B30,B31'} + BLOCK_KEY3 : {show: y, blk : 7, word: 0, pos : 0, len: 256, start : 0, type: 'bytes:32', wr_dis : 26, rd_dis : 3, alt : KEY3, dict : '', desc: Key3 or user data, rloc: EFUSE_RD_KEY3_DATA0_REG, bloc: 'B0,B1,B2,B3,B4,B5,B6,B7,B8,B9,B10,B11,B12,B13,B14,B15,B16,B17,B18,B19,B20,B21,B22,B23,B24,B25,B26,B27,B28,B29,B30,B31'} + BLOCK_KEY4 : {show: y, blk : 8, word: 0, pos : 0, len: 256, start : 0, type: 'bytes:32', wr_dis : 27, rd_dis : 4, alt : KEY4, dict : '', desc: Key4 or user data, rloc: EFUSE_RD_KEY4_DATA0_REG, bloc: 'B0,B1,B2,B3,B4,B5,B6,B7,B8,B9,B10,B11,B12,B13,B14,B15,B16,B17,B18,B19,B20,B21,B22,B23,B24,B25,B26,B27,B28,B29,B30,B31'} + BLOCK_KEY5 : {show: y, blk : 9, word: 0, pos : 0, len: 256, start : 0, type: 'bytes:32', wr_dis : 28, rd_dis : 5, alt : KEY5, dict : '', desc: Key5 or user data, rloc: EFUSE_RD_KEY5_DATA0_REG, bloc: 'B0,B1,B2,B3,B4,B5,B6,B7,B8,B9,B10,B11,B12,B13,B14,B15,B16,B17,B18,B19,B20,B21,B22,B23,B24,B25,B26,B27,B28,B29,B30,B31'} + BLOCK_SYS_DATA2 : {show: y, blk: 10, word: 0, pos : 0, len: 256, start : 0, type: 'bytes:32', wr_dis : 29, rd_dis : 6, alt : SYS_DATA_PART2, dict : '', desc: System data part 2 (reserved), rloc: EFUSE_RD_SYS_PART2_DATA0_REG, bloc: 'B0,B1,B2,B3,B4,B5,B6,B7,B8,B9,B10,B11,B12,B13,B14,B15,B16,B17,B18,B19,B20,B21,B22,B23,B24,B25,B26,B27,B28,B29,B30,B31'} diff --git a/espefuse/efuse_defs/esp32p4.yaml b/espefuse/efuse_defs/esp32p4.yaml new file mode 100644 index 000000000..fe10b2eda --- /dev/null +++ b/espefuse/efuse_defs/esp32p4.yaml @@ -0,0 +1,91 @@ +VER_NO: 95ae7b662df04208c40c69564ea06a28 +EFUSES: + WR_DIS : {show: y, blk : 0, word: 0, pos : 0, len : 32, start : 0, type : 'uint:32', wr_dis: null, rd_dis: null, alt : '', dict : '', desc: Disable programming of individual eFuses, rloc: EFUSE_RD_WR_DIS_REG, bloc: 'B0,B1,B2,B3'} + RD_DIS : {show: y, blk : 0, word: 1, pos : 0, len : 7, start : 32, type : 'uint:7', wr_dis : 0, rd_dis: null, alt : '', dict : '', desc: Disable reading from BlOCK4-10, rloc: 'EFUSE_RD_REPEAT_DATA0_REG[6:0]', bloc: 'B4[6:0]'} + USB_DEVICE_EXCHG_PINS : {show: y, blk : 0, word: 1, pos : 7, len : 1, start : 39, type : bool, wr_dis: null, rd_dis: null, alt : '', dict : '', desc: Enable usb device exchange pins of D+ and D-, rloc: 'EFUSE_RD_REPEAT_DATA0_REG[7]', bloc: 'B4[7]'} + USB_OTG11_EXCHG_PINS : {show: y, blk : 0, word: 1, pos : 8, len : 1, start : 40, type : bool, wr_dis: null, rd_dis: null, alt : '', dict : '', desc: Enable usb otg11 exchange pins of D+ and D-, rloc: 'EFUSE_RD_REPEAT_DATA0_REG[8]', bloc: 'B5[0]'} + DIS_USB_JTAG : {show: y, blk : 0, word: 1, pos : 9, len : 1, start : 41, type : bool, wr_dis: null, rd_dis: null, alt : '', dict : '', desc: 'Represents whether the function of usb switch to jtag is disabled or enabled. 1: disabled. 0: enabled', rloc: 'EFUSE_RD_REPEAT_DATA0_REG[9]', bloc: 'B5[1]'} + POWERGLITCH_EN : {show: y, blk : 0, word: 1, pos: 10, len : 1, start : 42, type : bool, wr_dis: null, rd_dis: null, alt : '', dict : '', desc: 'Represents whether power glitch function is enabled. 1: enabled. 0: disabled', rloc: 'EFUSE_RD_REPEAT_DATA0_REG[10]', bloc: 'B5[2]'} + DIS_USB_SERIAL_JTAG : {show: n, blk : 0, word: 1, pos: 11, len : 1, start : 43, type : bool, wr_dis: null, rd_dis: null, alt : '', dict : '', desc: 'Represents whether USB-Serial-JTAG is disabled or enabled. 1: disabled. 0: enabled', rloc: 'EFUSE_RD_REPEAT_DATA0_REG[11]', bloc: 'B5[3]'} + DIS_FORCE_DOWNLOAD : {show: y, blk : 0, word: 1, pos: 12, len : 1, start : 44, type : bool, wr_dis: null, rd_dis: null, alt : '', dict : '', desc: 'Represents whether the function that forces chip into download mode is disabled or enabled. 1: disabled. 0: enabled', rloc: 'EFUSE_RD_REPEAT_DATA0_REG[12]', bloc: 'B5[4]'} + SPI_DOWNLOAD_MSPI_DIS : {show: y, blk : 0, word: 1, pos: 13, len : 1, start : 45, type : bool, wr_dis: null, rd_dis: null, alt : '', dict : '', desc: Set this bit to disable accessing MSPI flash/MSPI ram by SYS AXI matrix during boot_mode_download, rloc: 'EFUSE_RD_REPEAT_DATA0_REG[13]', bloc: 'B5[5]'} + DIS_TWAI : {show: y, blk : 0, word: 1, pos: 14, len : 1, start : 46, type : bool, wr_dis: null, rd_dis: null, alt : '', dict : '', desc: 'Represents whether TWAI function is disabled or enabled. 1: disabled. 0: enabled', rloc: 'EFUSE_RD_REPEAT_DATA0_REG[14]', bloc: 'B5[6]'} + JTAG_SEL_ENABLE : {show: y, blk : 0, word: 1, pos: 15, len : 1, start : 47, type : bool, wr_dis: null, rd_dis: null, alt : '', dict : '', desc: 'Represents whether the selection between usb_to_jtag and pad_to_jtag through strapping gpio15 when both EFUSE_DIS_PAD_JTAG and EFUSE_DIS_USB_JTAG are equal to 0 is enabled or disabled. 1: enabled. 0: disabled', rloc: 'EFUSE_RD_REPEAT_DATA0_REG[15]', bloc: 'B5[7]'} + SOFT_DIS_JTAG : {show: y, blk : 0, word: 1, pos: 16, len : 3, start : 48, type : 'uint:3', wr_dis: null, rd_dis: null, alt : '', dict : '', desc: 'Represents whether JTAG is disabled in soft way. Odd number: disabled. Even number: enabled', rloc: 'EFUSE_RD_REPEAT_DATA0_REG[18:16]', bloc: 'B6[2:0]'} + DIS_PAD_JTAG : {show: y, blk : 0, word: 1, pos: 19, len : 1, start : 51, type : bool, wr_dis: null, rd_dis: null, alt : '', dict : '', desc: 'Represents whether JTAG is disabled in the hard way(permanently). 1: disabled. 0: enabled', rloc: 'EFUSE_RD_REPEAT_DATA0_REG[19]', bloc: 'B6[3]'} + DIS_DOWNLOAD_MANUAL_ENCRYPT : {show: y, blk : 0, word: 1, pos: 20, len : 1, start : 52, type : bool, wr_dis: null, rd_dis: null, alt : '', dict : '', desc: 'Represents whether flash encrypt function is disabled or enabled(except in SPI boot mode). 1: disabled. 0: enabled', rloc: 'EFUSE_RD_REPEAT_DATA0_REG[20]', bloc: 'B6[4]'} + USB_DEVICE_DREFH : {show: n, blk : 0, word: 1, pos: 21, len : 2, start : 53, type : 'uint:2', wr_dis: null, rd_dis: null, alt : '', dict : '', desc: USB intphy of usb device signle-end input high threshold; 1.76V to 2V. Step by 80mV, rloc: 'EFUSE_RD_REPEAT_DATA0_REG[22:21]', bloc: 'B6[6:5]'} + USB_OTG11_DREFH : {show: n, blk : 0, word: 1, pos: 23, len : 2, start : 55, type : 'uint:2', wr_dis: null, rd_dis: null, alt : '', dict : '', desc: USB intphy of usb otg11 signle-end input high threshold; 1.76V to 2V. Step by 80mV, rloc: 'EFUSE_RD_REPEAT_DATA0_REG[24:23]', bloc: 'B6[7],B7[0]'} + USB_PHY_SEL : {show: y, blk : 0, word: 1, pos: 25, len : 1, start : 57, type : bool, wr_dis: null, rd_dis: null, alt : '', dict : '', desc: TBD, rloc: 'EFUSE_RD_REPEAT_DATA0_REG[25]', bloc: 'B7[1]'} + KM_HUK_GEN_STATE_LOW : {show: y, blk : 0, word: 1, pos: 26, len : 6, start : 58, type : 'uint:6', wr_dis: null, rd_dis: null, alt : '', dict : '', desc: Set this bit to control validation of HUK generate mode. Odd of 1 is invalid; even of 1 is valid, rloc: 'EFUSE_RD_REPEAT_DATA0_REG[31:26]', bloc: 'B7[7:2]'} + KM_HUK_GEN_STATE_HIGH : {show: y, blk : 0, word: 2, pos : 0, len : 3, start : 64, type : 'uint:3', wr_dis: null, rd_dis: null, alt : '', dict : '', desc: Set this bit to control validation of HUK generate mode. Odd of 1 is invalid; even of 1 is valid, rloc: 'EFUSE_RD_REPEAT_DATA1_REG[2:0]', bloc: 'B8[2:0]'} + KM_RND_SWITCH_CYCLE : {show: y, blk : 0, word: 2, pos : 3, len : 2, start : 67, type : 'uint:2', wr_dis: null, rd_dis: null, alt : '', dict : '', desc: 'Set bits to control key manager random number switch cycle. 0: control by register. 1: 8 km clk cycles. 2: 16 km cycles. 3: 32 km cycles', rloc: 'EFUSE_RD_REPEAT_DATA1_REG[4:3]', bloc: 'B8[4:3]'} + KM_DEPLOY_ONLY_ONCE : {show: y, blk : 0, word: 2, pos : 5, len : 4, start : 69, type : 'uint:4', wr_dis: null, rd_dis: null, alt : '', dict : '', desc: 'Set each bit to control whether corresponding key can only be deployed once. 1 is true; 0 is false. Bit0: ecdsa. Bit1: xts. Bit2: hmac. Bit3: ds', rloc: 'EFUSE_RD_REPEAT_DATA1_REG[8:5]', bloc: 'B8[7:5],B9[0]'} + FORCE_USE_KEY_MANAGER_KEY : {show: y, blk : 0, word: 2, pos : 9, len : 4, start : 73, type : 'uint:4', wr_dis: null, rd_dis: null, alt : '', dict : '', desc: 'Set each bit to control whether corresponding key must come from key manager.. 1 is true; 0 is false. Bit0: ecdsa. Bit1: xts. Bit2: hmac. Bit3: ds', rloc: 'EFUSE_RD_REPEAT_DATA1_REG[12:9]', bloc: 'B9[4:1]'} + FORCE_DISABLE_SW_INIT_KEY : {show: y, blk : 0, word: 2, pos: 13, len : 1, start : 77, type : bool, wr_dis: null, rd_dis: null, alt : '', dict : '', desc: Set this bit to disable software written init key; and force use efuse_init_key, rloc: 'EFUSE_RD_REPEAT_DATA1_REG[13]', bloc: 'B9[5]'} + XTS_KEY_LENGTH_256 : {show: y, blk : 0, word: 2, pos: 14, len : 1, start : 78, type : bool, wr_dis: null, rd_dis: null, alt : '', dict : '', desc: Set this bit to configure flash encryption use xts-128 key; else use xts-256 key, rloc: 'EFUSE_RD_REPEAT_DATA1_REG[14]', bloc: 'B9[6]'} + RESERVE_0_79 : {show: n, blk : 0, word: 2, pos: 15, len : 1, start : 79, type : bool, wr_dis: null, rd_dis: null, alt : '', dict : '', desc: Reserved; it was created by set_missed_fields_in_regs func, rloc: 'EFUSE_RD_REPEAT_DATA1_REG[15]', bloc: 'B9[7]'} + WDT_DELAY_SEL : {show: y, blk : 0, word: 2, pos: 16, len : 2, start : 80, type : 'uint:2', wr_dis: null, rd_dis: null, alt : '', dict : '', desc: 'Represents whether RTC watchdog timeout threshold is selected at startup. 1: selected. 0: not selected', rloc: 'EFUSE_RD_REPEAT_DATA1_REG[17:16]', bloc: 'B10[1:0]'} + SPI_BOOT_CRYPT_CNT : {show: y, blk : 0, word: 2, pos: 18, len : 3, start : 82, type : 'uint:3', wr_dis : 4, rd_dis: null, alt : '', dict: '{0: "Disable", 1: "Enable", 3: "Disable", 7: "Enable"}', desc: Enables flash encryption when 1 or 3 bits are set and disables otherwise, rloc: 'EFUSE_RD_REPEAT_DATA1_REG[20:18]', bloc: 'B10[4:2]'} + SECURE_BOOT_KEY_REVOKE0 : {show: y, blk : 0, word: 2, pos: 21, len : 1, start : 85, type : bool, wr_dis : 5, rd_dis: null, alt : '', dict : '', desc: Revoke 1st secure boot key, rloc: 'EFUSE_RD_REPEAT_DATA1_REG[21]', bloc: 'B10[5]'} + SECURE_BOOT_KEY_REVOKE1 : {show: y, blk : 0, word: 2, pos: 22, len : 1, start : 86, type : bool, wr_dis : 6, rd_dis: null, alt : '', dict : '', desc: Revoke 2nd secure boot key, rloc: 'EFUSE_RD_REPEAT_DATA1_REG[22]', bloc: 'B10[6]'} + SECURE_BOOT_KEY_REVOKE2 : {show: y, blk : 0, word: 2, pos: 23, len : 1, start : 87, type : bool, wr_dis : 7, rd_dis: null, alt : '', dict : '', desc: Revoke 3rd secure boot key, rloc: 'EFUSE_RD_REPEAT_DATA1_REG[23]', bloc: 'B10[7]'} + KEY_PURPOSE_0 : {show: y, blk : 0, word: 2, pos: 24, len : 4, start : 88, type : 'uint:4', wr_dis : 8, rd_dis: null, alt : KEY0_PURPOSE, dict : '', desc: Represents the purpose of Key0, rloc: 'EFUSE_RD_REPEAT_DATA1_REG[27:24]', bloc: 'B11[3:0]'} + KEY_PURPOSE_1 : {show: y, blk : 0, word: 2, pos: 28, len : 4, start : 92, type : 'uint:4', wr_dis : 9, rd_dis: null, alt : KEY1_PURPOSE, dict : '', desc: Represents the purpose of Key1, rloc: 'EFUSE_RD_REPEAT_DATA1_REG[31:28]', bloc: 'B11[7:4]'} + KEY_PURPOSE_2 : {show: y, blk : 0, word: 3, pos : 0, len : 4, start : 96, type : 'uint:4', wr_dis : 10, rd_dis: null, alt : KEY2_PURPOSE, dict : '', desc: Represents the purpose of Key2, rloc: 'EFUSE_RD_REPEAT_DATA2_REG[3:0]', bloc: 'B12[3:0]'} + KEY_PURPOSE_3 : {show: y, blk : 0, word: 3, pos : 4, len : 4, start: 100, type : 'uint:4', wr_dis : 11, rd_dis: null, alt : KEY3_PURPOSE, dict : '', desc: Represents the purpose of Key3, rloc: 'EFUSE_RD_REPEAT_DATA2_REG[7:4]', bloc: 'B12[7:4]'} + KEY_PURPOSE_4 : {show: y, blk : 0, word: 3, pos : 8, len : 4, start: 104, type : 'uint:4', wr_dis : 12, rd_dis: null, alt : KEY4_PURPOSE, dict : '', desc: Represents the purpose of Key4, rloc: 'EFUSE_RD_REPEAT_DATA2_REG[11:8]', bloc: 'B13[3:0]'} + KEY_PURPOSE_5 : {show: y, blk : 0, word: 3, pos: 12, len : 4, start: 108, type : 'uint:4', wr_dis : 13, rd_dis: null, alt : KEY5_PURPOSE, dict : '', desc: Represents the purpose of Key5, rloc: 'EFUSE_RD_REPEAT_DATA2_REG[15:12]', bloc: 'B13[7:4]'} + SEC_DPA_LEVEL : {show: y, blk : 0, word: 3, pos: 16, len : 2, start: 112, type : 'uint:2', wr_dis: null, rd_dis: null, alt : '', dict : '', desc: Represents the spa secure level by configuring the clock random divide mode, rloc: 'EFUSE_RD_REPEAT_DATA2_REG[17:16]', bloc: 'B14[1:0]'} + ECDSA_ENABLE_SOFT_K : {show: y, blk : 0, word: 3, pos: 18, len : 1, start: 114, type : bool, wr_dis: null, rd_dis: null, alt : '', dict : '', desc: 'Represents whether hardware random number k is forced used in ESDCA. 1: force used. 0: not force used', rloc: 'EFUSE_RD_REPEAT_DATA2_REG[18]', bloc: 'B14[2]'} + CRYPT_DPA_ENABLE : {show: y, blk : 0, word: 3, pos: 19, len : 1, start: 115, type : bool, wr_dis: null, rd_dis: null, alt : '', dict : '', desc: 'Represents whether anti-dpa attack is enabled. 1:enabled. 0: disabled', rloc: 'EFUSE_RD_REPEAT_DATA2_REG[19]', bloc: 'B14[3]'} + SECURE_BOOT_EN : {show: y, blk : 0, word: 3, pos: 20, len : 1, start: 116, type : bool, wr_dis: null, rd_dis: null, alt : '', dict : '', desc: 'Represents whether secure boot is enabled or disabled. 1: enabled. 0: disabled', rloc: 'EFUSE_RD_REPEAT_DATA2_REG[20]', bloc: 'B14[4]'} + SECURE_BOOT_AGGRESSIVE_REVOKE : {show: y, blk : 0, word: 3, pos: 21, len : 1, start: 117, type : bool, wr_dis: null, rd_dis: null, alt : '', dict : '', desc: 'Represents whether revoking aggressive secure boot is enabled or disabled. 1: enabled. 0: disabled', rloc: 'EFUSE_RD_REPEAT_DATA2_REG[21]', bloc: 'B14[5]'} + RESERVE_0_118 : {show: n, blk : 0, word: 3, pos: 22, len : 1, start: 118, type : bool, wr_dis: null, rd_dis: null, alt : '', dict : '', desc: Reserved; it was created by set_missed_fields_in_regs func, rloc: 'EFUSE_RD_REPEAT_DATA2_REG[22]', bloc: 'B14[6]'} + FLASH_TYPE : {show: y, blk : 0, word: 3, pos: 23, len : 1, start: 119, type : bool, wr_dis: null, rd_dis: null, alt : '', dict : '', desc: 'The type of interfaced flash. 0: four data lines; 1: eight data lines', rloc: 'EFUSE_RD_REPEAT_DATA2_REG[23]', bloc: 'B14[7]'} + FLASH_PAGE_SIZE : {show: y, blk : 0, word: 3, pos: 24, len : 2, start: 120, type : 'uint:2', wr_dis: null, rd_dis: null, alt : '', dict : '', desc: Set flash page size, rloc: 'EFUSE_RD_REPEAT_DATA2_REG[25:24]', bloc: 'B15[1:0]'} + FLASH_ECC_EN : {show: y, blk : 0, word: 3, pos: 26, len : 1, start: 122, type : bool, wr_dis: null, rd_dis: null, alt : '', dict : '', desc: Set this bit to enable ecc for flash boot, rloc: 'EFUSE_RD_REPEAT_DATA2_REG[26]', bloc: 'B15[2]'} + DIS_USB_OTG_DOWNLOAD_MODE : {show: y, blk : 0, word: 3, pos: 27, len : 1, start: 123, type : bool, wr_dis: null, rd_dis: null, alt : '', dict : '', desc: Set this bit to disable download via USB-OTG, rloc: 'EFUSE_RD_REPEAT_DATA2_REG[27]', bloc: 'B15[3]'} + FLASH_TPUW : {show: y, blk : 0, word: 3, pos: 28, len : 4, start: 124, type : 'uint:4', wr_dis: null, rd_dis: null, alt : '', dict : '', desc: Represents the flash waiting time after power-up; in unit of ms. When the value less than 15; the waiting time is the programmed value. Otherwise; the waiting time is 2 times the programmed value, rloc: 'EFUSE_RD_REPEAT_DATA2_REG[31:28]', bloc: 'B15[7:4]'} + DIS_DOWNLOAD_MODE : {show: y, blk : 0, word: 4, pos : 0, len : 1, start: 128, type : bool, wr_dis: null, rd_dis: null, alt : '', dict : '', desc: 'Represents whether Download mode is disabled or enabled. 1: disabled. 0: enabled', rloc: 'EFUSE_RD_REPEAT_DATA3_REG[0]', bloc: 'B16[0]'} + DIS_DIRECT_BOOT : {show: y, blk : 0, word: 4, pos : 1, len : 1, start: 129, type : bool, wr_dis: null, rd_dis: null, alt : '', dict : '', desc: 'Represents whether direct boot mode is disabled or enabled. 1: disabled. 0: enabled', rloc: 'EFUSE_RD_REPEAT_DATA3_REG[1]', bloc: 'B16[1]'} + DIS_USB_SERIAL_JTAG_ROM_PRINT : {show: y, blk : 0, word: 4, pos : 2, len : 1, start: 130, type : bool, wr_dis: null, rd_dis: null, alt : '', dict : '', desc: 'Represents whether print from USB-Serial-JTAG is disabled or enabled. 1: disabled. 0: enabled', rloc: 'EFUSE_RD_REPEAT_DATA3_REG[2]', bloc: 'B16[2]'} + LOCK_KM_KEY : {show: y, blk : 0, word: 4, pos : 3, len : 1, start: 131, type : bool, wr_dis: null, rd_dis: null, alt : '', dict : '', desc: TBD, rloc: 'EFUSE_RD_REPEAT_DATA3_REG[3]', bloc: 'B16[3]'} + DIS_USB_SERIAL_JTAG_DOWNLOAD_MODE: {show: y, blk : 0, word: 4, pos : 4, len : 1, start: 132, type : bool, wr_dis: null, rd_dis: null, alt : '', dict : '', desc: 'Represents whether the USB-Serial-JTAG download function is disabled or enabled. 1: disabled. 0: enabled', rloc: 'EFUSE_RD_REPEAT_DATA3_REG[4]', bloc: 'B16[4]'} + ENABLE_SECURITY_DOWNLOAD : {show: y, blk : 0, word: 4, pos : 5, len : 1, start: 133, type : bool, wr_dis: null, rd_dis: null, alt : '', dict : '', desc: 'Represents whether security download is enabled or disabled. 1: enabled. 0: disabled', rloc: 'EFUSE_RD_REPEAT_DATA3_REG[5]', bloc: 'B16[5]'} + UART_PRINT_CONTROL : {show: y, blk : 0, word: 4, pos : 6, len : 2, start: 134, type : 'uint:2', wr_dis: null, rd_dis: null, alt : '', dict : '', desc: 'Represents the type of UART printing. 00: force enable printing. 01: enable printing when GPIO8 is reset at low level. 10: enable printing when GPIO8 is reset at high level. 11: force disable printing', rloc: 'EFUSE_RD_REPEAT_DATA3_REG[7:6]', bloc: 'B16[7:6]'} + FORCE_SEND_RESUME : {show: y, blk : 0, word: 4, pos : 8, len : 1, start: 136, type : bool, wr_dis: null, rd_dis: null, alt : '', dict : '', desc: 'Represents whether ROM code is forced to send a resume command during SPI boot. 1: forced. 0:not forced', rloc: 'EFUSE_RD_REPEAT_DATA3_REG[8]', bloc: 'B17[0]'} + SECURE_VERSION : {show: y, blk : 0, word: 4, pos : 9, len : 16, start: 137, type : 'uint:16', wr_dis: null, rd_dis: null, alt : '', dict : '', desc: Represents the version used by ESP-IDF anti-rollback feature, rloc: 'EFUSE_RD_REPEAT_DATA3_REG[24:9]', bloc: 'B17[7:1],B18,B19[0]'} + SECURE_BOOT_DISABLE_FAST_WAKE : {show: y, blk : 0, word: 4, pos: 25, len : 1, start: 153, type : bool, wr_dis: null, rd_dis: null, alt : '', dict : '', desc: 'Represents whether FAST VERIFY ON WAKE is disabled or enabled when Secure Boot is enabled. 1: disabled. 0: enabled', rloc: 'EFUSE_RD_REPEAT_DATA3_REG[25]', bloc: 'B19[1]'} + HYS_EN_PAD : {show: y, blk : 0, word: 4, pos: 26, len : 1, start: 154, type : bool, wr_dis: null, rd_dis: null, alt : '', dict : '', desc: 'Represents whether the hysteresis function of corresponding PAD is enabled. 1: enabled. 0:disabled', rloc: 'EFUSE_RD_REPEAT_DATA3_REG[26]', bloc: 'B19[2]'} + DCDC_VSET : {show: y, blk : 0, word: 4, pos: 27, len : 5, start: 155, type : 'uint:5', wr_dis: null, rd_dis: null, alt : '', dict : '', desc: Set the dcdc voltage default, rloc: 'EFUSE_RD_REPEAT_DATA3_REG[31:27]', bloc: 'B19[7:3]'} + PXA0_TIEH_SEL_0 : {show: y, blk : 0, word: 5, pos : 0, len : 2, start: 160, type : 'uint:2', wr_dis: null, rd_dis: null, alt : 0PXA_TIEH_SEL_0, dict : '', desc: TBD, rloc: 'EFUSE_RD_REPEAT_DATA4_REG[1:0]', bloc: 'B20[1:0]'} + PXA0_TIEH_SEL_1 : {show: y, blk : 0, word: 5, pos : 2, len : 2, start: 162, type : 'uint:2', wr_dis: null, rd_dis: null, alt : 0PXA_TIEH_SEL_1, dict : '', desc: TBD, rloc: 'EFUSE_RD_REPEAT_DATA4_REG[3:2]', bloc: 'B20[3:2]'} + PXA0_TIEH_SEL_2 : {show: y, blk : 0, word: 5, pos : 4, len : 2, start: 164, type : 'uint:2', wr_dis: null, rd_dis: null, alt : 0PXA_TIEH_SEL_2, dict : '', desc: TBD, rloc: 'EFUSE_RD_REPEAT_DATA4_REG[5:4]', bloc: 'B20[5:4]'} + PXA0_TIEH_SEL_3 : {show: y, blk : 0, word: 5, pos : 6, len : 2, start: 166, type : 'uint:2', wr_dis: null, rd_dis: null, alt : 0PXA_TIEH_SEL_3, dict : '', desc: TBD, rloc: 'EFUSE_RD_REPEAT_DATA4_REG[7:6]', bloc: 'B20[7:6]'} + KM_DISABLE_DEPLOY_MODE : {show: y, blk : 0, word: 5, pos : 8, len : 4, start: 168, type : 'uint:4', wr_dis: null, rd_dis: null, alt : '', dict : '', desc: TBD, rloc: 'EFUSE_RD_REPEAT_DATA4_REG[11:8]', bloc: 'B21[3:0]'} + USB_DEVICE_DREFL : {show: n, blk : 0, word: 5, pos: 12, len : 2, start: 172, type : 'uint:2', wr_dis: null, rd_dis: null, alt : '', dict : '', desc: Represents the usb device single-end input low threhold; 0.8 V to 1.04 V with step of 80 mV, rloc: 'EFUSE_RD_REPEAT_DATA4_REG[13:12]', bloc: 'B21[5:4]'} + USB_OTG11_DREFL : {show: n, blk : 0, word: 5, pos: 14, len : 2, start: 174, type : 'uint:2', wr_dis: null, rd_dis: null, alt : '', dict : '', desc: Represents the usb otg11 single-end input low threhold; 0.8 V to 1.04 V with step of 80 mV, rloc: 'EFUSE_RD_REPEAT_DATA4_REG[15:14]', bloc: 'B21[7:6]'} + RESERVE_0_176 : {show: n, blk : 0, word: 5, pos: 16, len : 2, start: 176, type : 'uint:2', wr_dis: null, rd_dis: null, alt : '', dict : '', desc: Reserved; it was created by set_missed_fields_in_regs func, rloc: 'EFUSE_RD_REPEAT_DATA4_REG[17:16]', bloc: 'B22[1:0]'} + HP_PWR_SRC_SEL : {show: y, blk : 0, word: 5, pos: 18, len : 1, start: 178, type : bool, wr_dis: null, rd_dis: null, alt : '', dict : '', desc: 'HP system power source select. 0:LDO. 1: DCDC', rloc: 'EFUSE_RD_REPEAT_DATA4_REG[18]', bloc: 'B22[2]'} + DCDC_VSET_EN : {show: y, blk : 0, word: 5, pos: 19, len : 1, start: 179, type : bool, wr_dis: null, rd_dis: null, alt : '', dict : '', desc: Select dcdc vset use efuse_dcdc_vset, rloc: 'EFUSE_RD_REPEAT_DATA4_REG[19]', bloc: 'B22[3]'} + DIS_WDT : {show: y, blk : 0, word: 5, pos: 20, len : 1, start: 180, type : bool, wr_dis: null, rd_dis: null, alt : '', dict : '', desc: Set this bit to disable watch dog, rloc: 'EFUSE_RD_REPEAT_DATA4_REG[20]', bloc: 'B22[4]'} + DIS_SWD : {show: y, blk : 0, word: 5, pos: 21, len : 1, start: 181, type : bool, wr_dis: null, rd_dis: null, alt : '', dict : '', desc: Set this bit to disable super-watchdog, rloc: 'EFUSE_RD_REPEAT_DATA4_REG[21]', bloc: 'B22[5]'} + RESERVE_0_182 : {show: n, blk : 0, word: 5, pos: 22, len : 10, start: 182, type : 'uint:10', wr_dis: null, rd_dis: null, alt : '', dict : '', desc: Reserved; it was created by set_missed_fields_in_regs func, rloc: 'EFUSE_RD_REPEAT_DATA4_REG[31:22]', bloc: 'B22[7:6],B23'} + MAC : {show: y, blk : 1, word: 0, pos : 0, len : 48, start : 0, type : 'bytes:6', wr_dis : 20, rd_dis: null, alt : MAC_FACTORY, dict : '', desc: MAC address, rloc: EFUSE_RD_MAC_SYS_0_REG, bloc: 'B0,B1,B2,B3,B4,B5'} + MAC_EXT : {show: y, blk : 1, word: 1, pos: 16, len : 16, start : 48, type : 'bytes:2', wr_dis : 20, rd_dis: null, alt : '', dict : '', desc: Stores the extended bits of MAC address, rloc: 'EFUSE_RD_MAC_SYS_1_REG[31:16]', bloc: 'B6,B7'} + MAC_RESERVED_1 : {show: n, blk : 1, word: 2, pos : 0, len : 14, start : 64, type : 'uint:14', wr_dis : 20, rd_dis: null, alt : '', dict : '', desc: Reserved, rloc: 'EFUSE_RD_MAC_SYS_2_REG[13:0]', bloc: 'B8,B9[5:0]'} + MAC_RESERVED_0 : {show: n, blk : 1, word: 2, pos: 14, len : 18, start : 78, type : 'uint:18', wr_dis : 20, rd_dis: null, alt : '', dict : '', desc: Reserved, rloc: 'EFUSE_RD_MAC_SYS_2_REG[31:14]', bloc: 'B9[7:6],B10,B11'} + MAC_RESERVED_2 : {show: n, blk : 1, word: 3, pos : 0, len : 18, start : 96, type : 'uint:18', wr_dis : 20, rd_dis: null, alt : '', dict : '', desc: Reserved, rloc: 'EFUSE_RD_MAC_SYS_3_REG[17:0]', bloc: 'B12,B13,B14[1:0]'} + SYS_DATA_PART0_0 : {show: n, blk : 1, word: 3, pos: 18, len : 14, start: 114, type : 'uint:14', wr_dis : 20, rd_dis: null, alt : '', dict : '', desc: Stores the first 14 bits of the zeroth part of system data, rloc: 'EFUSE_RD_MAC_SYS_3_REG[31:18]', bloc: 'B14[7:2],B15'} + SYS_DATA_PART0_1 : {show: n, blk : 1, word: 4, pos : 0, len : 32, start: 128, type : 'uint:32', wr_dis : 20, rd_dis: null, alt : '', dict : '', desc: Stores the first 32 bits of the zeroth part of system data, rloc: EFUSE_RD_MAC_SYS_4_REG, bloc: 'B16,B17,B18,B19'} + SYS_DATA_PART0_2 : {show: n, blk : 1, word: 5, pos : 0, len : 32, start: 160, type : 'uint:32', wr_dis : 20, rd_dis: null, alt : '', dict : '', desc: Stores the second 32 bits of the zeroth part of system data, rloc: EFUSE_RD_MAC_SYS_5_REG, bloc: 'B20,B21,B22,B23'} + BLOCK_SYS_DATA1 : {show: y, blk : 2, word: 0, pos : 0, len: 256, start : 0, type: 'bytes:32', wr_dis : 21, rd_dis: null, alt : SYS_DATA_PART1, dict : '', desc: System data part 1, rloc: EFUSE_RD_SYS_PART1_DATA0_REG, bloc: 'B0,B1,B2,B3,B4,B5,B6,B7,B8,B9,B10,B11,B12,B13,B14,B15,B16,B17,B18,B19,B20,B21,B22,B23,B24,B25,B26,B27,B28,B29,B30,B31'} + BLOCK_USR_DATA : {show: y, blk : 3, word: 0, pos : 0, len: 256, start : 0, type: 'bytes:32', wr_dis : 22, rd_dis: null, alt : USER_DATA, dict : '', desc: User data, rloc: EFUSE_RD_USR_DATA0_REG, bloc: 'B0,B1,B2,B3,B4,B5,B6,B7,B8,B9,B10,B11,B12,B13,B14,B15,B16,B17,B18,B19,B20,B21,B22,B23,B24,B25,B26,B27,B28,B29,B30,B31'} + BLOCK_KEY0 : {show: y, blk : 4, word: 0, pos : 0, len: 256, start : 0, type: 'bytes:32', wr_dis : 23, rd_dis : 0, alt : KEY0, dict : '', desc: Key0 or user data, rloc: EFUSE_RD_KEY0_DATA0_REG, bloc: 'B0,B1,B2,B3,B4,B5,B6,B7,B8,B9,B10,B11,B12,B13,B14,B15,B16,B17,B18,B19,B20,B21,B22,B23,B24,B25,B26,B27,B28,B29,B30,B31'} + BLOCK_KEY1 : {show: y, blk : 5, word: 0, pos : 0, len: 256, start : 0, type: 'bytes:32', wr_dis : 24, rd_dis : 1, alt : KEY1, dict : '', desc: Key1 or user data, rloc: EFUSE_RD_KEY1_DATA0_REG, bloc: 'B0,B1,B2,B3,B4,B5,B6,B7,B8,B9,B10,B11,B12,B13,B14,B15,B16,B17,B18,B19,B20,B21,B22,B23,B24,B25,B26,B27,B28,B29,B30,B31'} + BLOCK_KEY2 : {show: y, blk : 6, word: 0, pos : 0, len: 256, start : 0, type: 'bytes:32', wr_dis : 25, rd_dis : 2, alt : KEY2, dict : '', desc: Key2 or user data, rloc: EFUSE_RD_KEY2_DATA0_REG, bloc: 'B0,B1,B2,B3,B4,B5,B6,B7,B8,B9,B10,B11,B12,B13,B14,B15,B16,B17,B18,B19,B20,B21,B22,B23,B24,B25,B26,B27,B28,B29,B30,B31'} + BLOCK_KEY3 : {show: y, blk : 7, word: 0, pos : 0, len: 256, start : 0, type: 'bytes:32', wr_dis : 26, rd_dis : 3, alt : KEY3, dict : '', desc: Key3 or user data, rloc: EFUSE_RD_KEY3_DATA0_REG, bloc: 'B0,B1,B2,B3,B4,B5,B6,B7,B8,B9,B10,B11,B12,B13,B14,B15,B16,B17,B18,B19,B20,B21,B22,B23,B24,B25,B26,B27,B28,B29,B30,B31'} + BLOCK_KEY4 : {show: y, blk : 8, word: 0, pos : 0, len: 256, start : 0, type: 'bytes:32', wr_dis : 27, rd_dis : 4, alt : KEY4, dict : '', desc: Key4 or user data, rloc: EFUSE_RD_KEY4_DATA0_REG, bloc: 'B0,B1,B2,B3,B4,B5,B6,B7,B8,B9,B10,B11,B12,B13,B14,B15,B16,B17,B18,B19,B20,B21,B22,B23,B24,B25,B26,B27,B28,B29,B30,B31'} + BLOCK_KEY5 : {show: y, blk : 9, word: 0, pos : 0, len: 256, start : 0, type: 'bytes:32', wr_dis : 28, rd_dis : 5, alt : KEY5, dict : '', desc: Key5 or user data, rloc: EFUSE_RD_KEY5_DATA0_REG, bloc: 'B0,B1,B2,B3,B4,B5,B6,B7,B8,B9,B10,B11,B12,B13,B14,B15,B16,B17,B18,B19,B20,B21,B22,B23,B24,B25,B26,B27,B28,B29,B30,B31'} + BLOCK_SYS_DATA2 : {show: y, blk: 10, word: 0, pos : 0, len: 256, start : 0, type: 'bytes:32', wr_dis : 29, rd_dis : 6, alt : SYS_DATA_PART2, dict : '', desc: System data part 2 (reserved), rloc: EFUSE_RD_SYS_PART2_DATA0_REG, bloc: 'B0,B1,B2,B3,B4,B5,B6,B7,B8,B9,B10,B11,B12,B13,B14,B15,B16,B17,B18,B19,B20,B21,B22,B23,B24,B25,B26,B27,B28,B29,B30,B31'} diff --git a/espefuse/efuse_defs/esp32s2.yaml b/espefuse/efuse_defs/esp32s2.yaml new file mode 100644 index 000000000..45b5900e4 --- /dev/null +++ b/espefuse/efuse_defs/esp32s2.yaml @@ -0,0 +1,119 @@ +VER_NO: 888a61f6f500d9c7ee0aa32016b0bee7 +EFUSES: + WR_DIS : {show: y, blk : 0, word: 0, pos : 0, len : 32, start : 0, type : 'uint:32', wr_dis: null, rd_dis: null, alt : '', dict : '', desc: Disable programming of individual eFuses, rloc: EFUSE_RD_WR_DIS_REG, bloc: 'B0,B1,B2,B3'} + RD_DIS : {show: y, blk : 0, word: 1, pos : 0, len : 7, start : 32, type : 'uint:7', wr_dis : 0, rd_dis: null, alt : '', dict : '', desc: Disable reading from BlOCK4-10, rloc: 'EFUSE_RD_REPEAT_DATA0_REG[6:0]', bloc: 'B4[6:0]'} + DIS_RTC_RAM_BOOT : {show: n, blk : 0, word: 1, pos : 7, len : 1, start : 39, type : bool, wr_dis : 1, rd_dis: null, alt : '', dict : '', desc: Reserved, rloc: 'EFUSE_RD_REPEAT_DATA0_REG[7]', bloc: 'B4[7]'} + DIS_ICACHE : {show: y, blk : 0, word: 1, pos : 8, len : 1, start : 40, type : bool, wr_dis : 2, rd_dis: null, alt : '', dict : '', desc: Set this bit to disable Icache, rloc: 'EFUSE_RD_REPEAT_DATA0_REG[8]', bloc: 'B5[0]'} + DIS_DCACHE : {show: y, blk : 0, word: 1, pos : 9, len : 1, start : 41, type : bool, wr_dis : 2, rd_dis: null, alt : '', dict : '', desc: Set this bit to disable Dcache, rloc: 'EFUSE_RD_REPEAT_DATA0_REG[9]', bloc: 'B5[1]'} + DIS_DOWNLOAD_ICACHE : {show: y, blk : 0, word: 1, pos: 10, len : 1, start : 42, type : bool, wr_dis : 2, rd_dis: null, alt : '', dict : '', desc: Disables Icache when SoC is in Download mode, rloc: 'EFUSE_RD_REPEAT_DATA0_REG[10]', bloc: 'B5[2]'} + DIS_DOWNLOAD_DCACHE : {show: y, blk : 0, word: 1, pos: 11, len : 1, start : 43, type : bool, wr_dis : 2, rd_dis: null, alt : '', dict : '', desc: Disables Dcache when SoC is in Download mode, rloc: 'EFUSE_RD_REPEAT_DATA0_REG[11]', bloc: 'B5[3]'} + DIS_FORCE_DOWNLOAD : {show: y, blk : 0, word: 1, pos: 12, len : 1, start : 44, type : bool, wr_dis : 2, rd_dis: null, alt : '', dict : '', desc: Set this bit to disable the function that forces chip into download mode, rloc: 'EFUSE_RD_REPEAT_DATA0_REG[12]', bloc: 'B5[4]'} + DIS_USB : {show: y, blk : 0, word: 1, pos: 13, len : 1, start : 45, type : bool, wr_dis : 2, rd_dis: null, alt : '', dict : '', desc: Set this bit to disable USB OTG function, rloc: 'EFUSE_RD_REPEAT_DATA0_REG[13]', bloc: 'B5[5]'} + DIS_TWAI : {show: y, blk : 0, word: 1, pos: 14, len : 1, start : 46, type : bool, wr_dis : 2, rd_dis: null, alt : DIS_CAN, dict : '', desc: Set this bit to disable the TWAI Controller function, rloc: 'EFUSE_RD_REPEAT_DATA0_REG[14]', bloc: 'B5[6]'} + DIS_BOOT_REMAP : {show: y, blk : 0, word: 1, pos: 15, len : 1, start : 47, type : bool, wr_dis : 2, rd_dis: null, alt : '', dict : '', desc: Disables capability to Remap RAM to ROM address space, rloc: 'EFUSE_RD_REPEAT_DATA0_REG[15]', bloc: 'B5[7]'} + RPT4_RESERVED5 : {show: n, blk : 0, word: 1, pos: 16, len : 1, start : 48, type : bool, wr_dis: null, rd_dis: null, alt : '', dict : '', desc: Reserved (used for four backups method), rloc: 'EFUSE_RD_REPEAT_DATA0_REG[16]', bloc: 'B6[0]'} + SOFT_DIS_JTAG : {show: y, blk : 0, word: 1, pos: 17, len : 1, start : 49, type : bool, wr_dis : 2, rd_dis: null, alt : '', dict : '', desc: Software disables JTAG. When software disabled; JTAG can be activated temporarily by HMAC peripheral, rloc: 'EFUSE_RD_REPEAT_DATA0_REG[17]', bloc: 'B6[1]'} + HARD_DIS_JTAG : {show: y, blk : 0, word: 1, pos: 18, len : 1, start : 50, type : bool, wr_dis : 2, rd_dis: null, alt : '', dict : '', desc: Hardware disables JTAG permanently, rloc: 'EFUSE_RD_REPEAT_DATA0_REG[18]', bloc: 'B6[2]'} + DIS_DOWNLOAD_MANUAL_ENCRYPT : {show: y, blk : 0, word: 1, pos: 19, len : 1, start : 51, type : bool, wr_dis : 2, rd_dis: null, alt : '', dict : '', desc: Disables flash encryption when in download boot modes, rloc: 'EFUSE_RD_REPEAT_DATA0_REG[19]', bloc: 'B6[3]'} + USB_DREFH : {show: n, blk : 0, word: 1, pos: 20, len : 2, start : 52, type : 'uint:2', wr_dis : 30, rd_dis: null, alt : '', dict : '', desc: Controls single-end input threshold vrefh; 1.76 V to 2 V with step of 80 mV; stored in eFuse, rloc: 'EFUSE_RD_REPEAT_DATA0_REG[21:20]', bloc: 'B6[5:4]'} + USB_DREFL : {show: n, blk : 0, word: 1, pos: 22, len : 2, start : 54, type : 'uint:2', wr_dis : 30, rd_dis: null, alt : '', dict : '', desc: Controls single-end input threshold vrefl; 0.8 V to 1.04 V with step of 80 mV; stored in eFuse, rloc: 'EFUSE_RD_REPEAT_DATA0_REG[23:22]', bloc: 'B6[7:6]'} + USB_EXCHG_PINS : {show: y, blk : 0, word: 1, pos: 24, len : 1, start : 56, type : bool, wr_dis : 30, rd_dis: null, alt : '', dict : '', desc: Set this bit to exchange USB D+ and D- pins, rloc: 'EFUSE_RD_REPEAT_DATA0_REG[24]', bloc: 'B7[0]'} + USB_EXT_PHY_ENABLE : {show: y, blk : 0, word: 1, pos: 25, len : 1, start : 57, type : bool, wr_dis : 30, rd_dis: null, alt : EXT_PHY_ENABLE, dict : '', desc: Set this bit to enable external USB PHY, rloc: 'EFUSE_RD_REPEAT_DATA0_REG[25]', bloc: 'B7[1]'} + USB_FORCE_NOPERSIST : {show: y, blk : 0, word: 1, pos: 26, len : 1, start : 58, type : bool, wr_dis : 30, rd_dis: null, alt : '', dict : '', desc: If set; forces USB BVALID to 1, rloc: 'EFUSE_RD_REPEAT_DATA0_REG[26]', bloc: 'B7[2]'} + BLOCK0_VERSION : {show: y, blk : 0, word: 1, pos: 27, len : 2, start : 59, type : 'uint:2', wr_dis : 30, rd_dis: null, alt : '', dict : '', desc: BLOCK0 efuse version, rloc: 'EFUSE_RD_REPEAT_DATA0_REG[28:27]', bloc: 'B7[4:3]'} + VDD_SPI_MODECURLIM : {show: n, blk : 0, word: 1, pos: 29, len : 1, start : 61, type : bool, wr_dis : 3, rd_dis: null, alt : '', dict : '', desc: SPI regulator switches current limit mode, rloc: 'EFUSE_RD_REPEAT_DATA0_REG[29]', bloc: 'B7[5]'} + VDD_SPI_DREFH : {show: n, blk : 0, word: 1, pos: 30, len : 2, start : 62, type : 'uint:2', wr_dis : 3, rd_dis: null, alt : '', dict : '', desc: SPI regulator high voltage reference, rloc: 'EFUSE_RD_REPEAT_DATA0_REG[31:30]', bloc: 'B7[7:6]'} + VDD_SPI_DREFM : {show: n, blk : 0, word: 2, pos : 0, len : 2, start : 64, type : 'uint:2', wr_dis : 3, rd_dis: null, alt : '', dict : '', desc: SPI regulator medium voltage reference, rloc: 'EFUSE_RD_REPEAT_DATA1_REG[1:0]', bloc: 'B8[1:0]'} + VDD_SPI_DREFL : {show: n, blk : 0, word: 2, pos : 2, len : 2, start : 66, type : 'uint:2', wr_dis : 3, rd_dis: null, alt : '', dict : '', desc: SPI regulator low voltage reference, rloc: 'EFUSE_RD_REPEAT_DATA1_REG[3:2]', bloc: 'B8[3:2]'} + VDD_SPI_XPD : {show: y, blk : 0, word: 2, pos : 4, len : 1, start : 68, type : bool, wr_dis : 3, rd_dis: null, alt : '', dict : '', desc: If VDD_SPI_FORCE is 1; this value determines if the VDD_SPI regulator is powered on, rloc: 'EFUSE_RD_REPEAT_DATA1_REG[4]', bloc: 'B8[4]'} + VDD_SPI_TIEH : {show: y, blk : 0, word: 2, pos : 5, len : 1, start : 69, type : bool, wr_dis : 3, rd_dis: null, alt : '', dict: '{0: "VDD_SPI connects to 1.8 V LDO", 1: "VDD_SPI connects to VDD3P3_RTC_IO"}', desc: If VDD_SPI_FORCE is 1; determines VDD_SPI voltage, rloc: 'EFUSE_RD_REPEAT_DATA1_REG[5]', bloc: 'B8[5]'} + VDD_SPI_FORCE : {show: y, blk : 0, word: 2, pos : 6, len : 1, start : 70, type : bool, wr_dis : 3, rd_dis: null, alt : '', dict : '', desc: Set this bit to use XPD_VDD_PSI_REG and VDD_SPI_TIEH to configure VDD_SPI LDO, rloc: 'EFUSE_RD_REPEAT_DATA1_REG[6]', bloc: 'B8[6]'} + VDD_SPI_EN_INIT : {show: n, blk : 0, word: 2, pos : 7, len : 1, start : 71, type : bool, wr_dis : 2, rd_dis: null, alt : '', dict : '', desc: 'Set SPI regulator to 0 to configure init[1:0]=0', rloc: 'EFUSE_RD_REPEAT_DATA1_REG[7]', bloc: 'B8[7]'} + VDD_SPI_ENCURLIM : {show: n, blk : 0, word: 2, pos : 8, len : 1, start : 72, type : bool, wr_dis : 2, rd_dis: null, alt : '', dict : '', desc: Set SPI regulator to 1 to enable output current limit, rloc: 'EFUSE_RD_REPEAT_DATA1_REG[8]', bloc: 'B9[0]'} + VDD_SPI_DCURLIM : {show: n, blk : 0, word: 2, pos : 9, len : 3, start : 73, type : 'uint:3', wr_dis : 2, rd_dis: null, alt : '', dict : '', desc: Tunes the current limit threshold of SPI regulator when tieh=0; about 800 mA/(8+d), rloc: 'EFUSE_RD_REPEAT_DATA1_REG[11:9]', bloc: 'B9[3:1]'} + VDD_SPI_INIT : {show: n, blk : 0, word: 2, pos: 12, len : 2, start : 76, type : 'uint:2', wr_dis : 2, rd_dis: null, alt : '', dict: '{0: "no resistance", 1: "6K", 2: "4K", 3: "2K"}', desc: Adds resistor from LDO output to ground, rloc: 'EFUSE_RD_REPEAT_DATA1_REG[13:12]', bloc: 'B9[5:4]'} + VDD_SPI_DCAP : {show: n, blk : 0, word: 2, pos: 14, len : 2, start : 78, type : 'uint:2', wr_dis : 2, rd_dis: null, alt : '', dict : '', desc: Prevents SPI regulator from overshoot, rloc: 'EFUSE_RD_REPEAT_DATA1_REG[15:14]', bloc: 'B9[7:6]'} + WDT_DELAY_SEL : {show: y, blk : 0, word: 2, pos: 16, len : 2, start : 80, type : 'uint:2', wr_dis : 3, rd_dis: null, alt : '', dict: '{0: "40000", 1: "80000", 2: "160000", 3: "320000"}', desc: RTC watchdog timeout threshold; in unit of slow clock cycle, rloc: 'EFUSE_RD_REPEAT_DATA1_REG[17:16]', bloc: 'B10[1:0]'} + SPI_BOOT_CRYPT_CNT : {show: y, blk : 0, word: 2, pos: 18, len : 3, start : 82, type : 'uint:3', wr_dis : 4, rd_dis: null, alt : '', dict: '{0: "Disable", 1: "Enable", 3: "Disable", 7: "Enable"}', desc: Enables flash encryption when 1 or 3 bits are set and disabled otherwise, rloc: 'EFUSE_RD_REPEAT_DATA1_REG[20:18]', bloc: 'B10[4:2]'} + SECURE_BOOT_KEY_REVOKE0 : {show: y, blk : 0, word: 2, pos: 21, len : 1, start : 85, type : bool, wr_dis : 5, rd_dis: null, alt : '', dict : '', desc: Revoke 1st secure boot key, rloc: 'EFUSE_RD_REPEAT_DATA1_REG[21]', bloc: 'B10[5]'} + SECURE_BOOT_KEY_REVOKE1 : {show: y, blk : 0, word: 2, pos: 22, len : 1, start : 86, type : bool, wr_dis : 6, rd_dis: null, alt : '', dict : '', desc: Revoke 2nd secure boot key, rloc: 'EFUSE_RD_REPEAT_DATA1_REG[22]', bloc: 'B10[6]'} + SECURE_BOOT_KEY_REVOKE2 : {show: y, blk : 0, word: 2, pos: 23, len : 1, start : 87, type : bool, wr_dis : 7, rd_dis: null, alt : '', dict : '', desc: Revoke 3rd secure boot key, rloc: 'EFUSE_RD_REPEAT_DATA1_REG[23]', bloc: 'B10[7]'} + KEY_PURPOSE_0 : {show: y, blk : 0, word: 2, pos: 24, len : 4, start : 88, type : 'uint:4', wr_dis : 8, rd_dis: null, alt : KEY0_PURPOSE, dict : '', desc: Purpose of KEY0, rloc: 'EFUSE_RD_REPEAT_DATA1_REG[27:24]', bloc: 'B11[3:0]'} + KEY_PURPOSE_1 : {show: y, blk : 0, word: 2, pos: 28, len : 4, start : 92, type : 'uint:4', wr_dis : 9, rd_dis: null, alt : KEY1_PURPOSE, dict : '', desc: Purpose of KEY1, rloc: 'EFUSE_RD_REPEAT_DATA1_REG[31:28]', bloc: 'B11[7:4]'} + KEY_PURPOSE_2 : {show: y, blk : 0, word: 3, pos : 0, len : 4, start : 96, type : 'uint:4', wr_dis : 10, rd_dis: null, alt : KEY2_PURPOSE, dict : '', desc: Purpose of KEY2, rloc: 'EFUSE_RD_REPEAT_DATA2_REG[3:0]', bloc: 'B12[3:0]'} + KEY_PURPOSE_3 : {show: y, blk : 0, word: 3, pos : 4, len : 4, start: 100, type : 'uint:4', wr_dis : 11, rd_dis: null, alt : KEY3_PURPOSE, dict : '', desc: Purpose of KEY3, rloc: 'EFUSE_RD_REPEAT_DATA2_REG[7:4]', bloc: 'B12[7:4]'} + KEY_PURPOSE_4 : {show: y, blk : 0, word: 3, pos : 8, len : 4, start: 104, type : 'uint:4', wr_dis : 12, rd_dis: null, alt : KEY4_PURPOSE, dict : '', desc: Purpose of KEY4, rloc: 'EFUSE_RD_REPEAT_DATA2_REG[11:8]', bloc: 'B13[3:0]'} + KEY_PURPOSE_5 : {show: y, blk : 0, word: 3, pos: 12, len : 4, start: 108, type : 'uint:4', wr_dis : 13, rd_dis: null, alt : KEY5_PURPOSE, dict : '', desc: Purpose of KEY5, rloc: 'EFUSE_RD_REPEAT_DATA2_REG[15:12]', bloc: 'B13[7:4]'} + KEY_PURPOSE_6 : {show: n, blk : 0, word: 3, pos: 16, len : 4, start: 112, type : 'uint:4', wr_dis : 14, rd_dis: null, alt : '', dict : '', desc: Purpose of KEY6, rloc: 'EFUSE_RD_REPEAT_DATA2_REG[19:16]', bloc: 'B14[3:0]'} + SECURE_BOOT_EN : {show: y, blk : 0, word: 3, pos: 20, len : 1, start: 116, type : bool, wr_dis : 15, rd_dis: null, alt : '', dict : '', desc: Set this bit to enable secure boot, rloc: 'EFUSE_RD_REPEAT_DATA2_REG[20]', bloc: 'B14[4]'} + SECURE_BOOT_AGGRESSIVE_REVOKE: {show: y, blk : 0, word: 3, pos: 21, len : 1, start: 117, type : bool, wr_dis : 16, rd_dis: null, alt : '', dict : '', desc: Set this bit to enable aggressive secure boot key revocation mode, rloc: 'EFUSE_RD_REPEAT_DATA2_REG[21]', bloc: 'B14[5]'} + RPT4_RESERVED1 : {show: n, blk : 0, word: 3, pos: 22, len : 6, start: 118, type : 'uint:6', wr_dis: null, rd_dis: null, alt : '', dict : '', desc: Reserved (used for four backups method), rloc: 'EFUSE_RD_REPEAT_DATA2_REG[27:22]', bloc: 'B14[7:6],B15[3:0]'} + FLASH_TPUW : {show: y, blk : 0, word: 3, pos: 28, len : 4, start: 124, type : 'uint:4', wr_dis : 18, rd_dis: null, alt : '', dict : '', desc: Configures flash startup delay after SoC power-up; in unit of (ms/2). When the value is 15; delay is 7.5 ms, rloc: 'EFUSE_RD_REPEAT_DATA2_REG[31:28]', bloc: 'B15[7:4]'} + DIS_DOWNLOAD_MODE : {show: y, blk : 0, word: 4, pos : 0, len : 1, start: 128, type : bool, wr_dis : 18, rd_dis: null, alt : '', dict : '', desc: Set this bit to disable all download boot modes, rloc: 'EFUSE_RD_REPEAT_DATA3_REG[0]', bloc: 'B16[0]'} + DIS_LEGACY_SPI_BOOT : {show: y, blk : 0, word: 4, pos : 1, len : 1, start: 129, type : bool, wr_dis : 18, rd_dis: null, alt : '', dict : '', desc: Set this bit to disable Legacy SPI boot mode, rloc: 'EFUSE_RD_REPEAT_DATA3_REG[1]', bloc: 'B16[1]'} + UART_PRINT_CHANNEL : {show: y, blk : 0, word: 4, pos : 2, len : 1, start: 130, type : bool, wr_dis : 18, rd_dis: null, alt : '', dict: '{0: "UART0", 1: "UART1"}', desc: Selects the default UART for printing boot messages, rloc: 'EFUSE_RD_REPEAT_DATA3_REG[2]', bloc: 'B16[2]'} + RPT4_RESERVED3 : {show: n, blk : 0, word: 4, pos : 3, len : 1, start: 131, type : bool, wr_dis: null, rd_dis: null, alt : '', dict : '', desc: Reserved (used for four backups method), rloc: 'EFUSE_RD_REPEAT_DATA3_REG[3]', bloc: 'B16[3]'} + DIS_USB_DOWNLOAD_MODE : {show: y, blk : 0, word: 4, pos : 4, len : 1, start: 132, type : bool, wr_dis : 18, rd_dis: null, alt : '', dict : '', desc: Set this bit to disable use of USB OTG in UART download boot mode, rloc: 'EFUSE_RD_REPEAT_DATA3_REG[4]', bloc: 'B16[4]'} + ENABLE_SECURITY_DOWNLOAD : {show: y, blk : 0, word: 4, pos : 5, len : 1, start: 133, type : bool, wr_dis : 18, rd_dis: null, alt : '', dict : '', desc: Set this bit to enable secure UART download mode (read/write flash only), rloc: 'EFUSE_RD_REPEAT_DATA3_REG[5]', bloc: 'B16[5]'} + UART_PRINT_CONTROL : {show: y, blk : 0, word: 4, pos : 6, len : 2, start: 134, type : 'uint:2', wr_dis : 18, rd_dis: null, alt : '', dict: '{0: "Enable", 1: "Enable when GPIO46 is low at reset", 2: "Enable when GPIO46 is high at reset", 3: "Disable"}', desc: Set the default UART boot message output mode, rloc: 'EFUSE_RD_REPEAT_DATA3_REG[7:6]', bloc: 'B16[7:6]'} + PIN_POWER_SELECTION : {show: y, blk : 0, word: 4, pos : 8, len : 1, start: 136, type : bool, wr_dis : 18, rd_dis: null, alt : '', dict: '{0: "VDD3P3_CPU", 1: "VDD_SPI"}', desc: Set default power supply for GPIO33-GPIO37; set when SPI flash is initialized, rloc: 'EFUSE_RD_REPEAT_DATA3_REG[8]', bloc: 'B17[0]'} + FLASH_TYPE : {show: y, blk : 0, word: 4, pos : 9, len : 1, start: 137, type : bool, wr_dis : 18, rd_dis: null, alt : '', dict: '{0: "4 data lines", 1: "8 data lines"}', desc: SPI flash type, rloc: 'EFUSE_RD_REPEAT_DATA3_REG[9]', bloc: 'B17[1]'} + FORCE_SEND_RESUME : {show: y, blk : 0, word: 4, pos: 10, len : 1, start: 138, type : bool, wr_dis : 18, rd_dis: null, alt : '', dict : '', desc: If set; forces ROM code to send an SPI flash resume command during SPI boot, rloc: 'EFUSE_RD_REPEAT_DATA3_REG[10]', bloc: 'B17[2]'} + SECURE_VERSION : {show: y, blk : 0, word: 4, pos: 11, len : 16, start: 139, type : 'uint:16', wr_dis : 18, rd_dis: null, alt : '', dict : '', desc: Secure version (used by ESP-IDF anti-rollback feature), rloc: 'EFUSE_RD_REPEAT_DATA3_REG[26:11]', bloc: 'B17[7:3],B18,B19[2:0]'} + RPT4_RESERVED2 : {show: n, blk : 0, word: 4, pos: 27, len : 5, start: 155, type : 'uint:5', wr_dis: null, rd_dis: null, alt : '', dict : '', desc: Reserved (used for four backups method), rloc: 'EFUSE_RD_REPEAT_DATA3_REG[31:27]', bloc: 'B19[7:3]'} + DISABLE_WAFER_VERSION_MAJOR : {show: y, blk : 0, word: 5, pos : 0, len : 1, start: 160, type : bool, wr_dis: null, rd_dis: null, alt : '', dict : '', desc: Disables check of wafer version major, rloc: 'EFUSE_RD_REPEAT_DATA4_REG[0]', bloc: 'B20[0]'} + DISABLE_BLK_VERSION_MAJOR : {show: y, blk : 0, word: 5, pos : 1, len : 1, start: 161, type : bool, wr_dis: null, rd_dis: null, alt : '', dict : '', desc: Disables check of blk version major, rloc: 'EFUSE_RD_REPEAT_DATA4_REG[1]', bloc: 'B20[1]'} + RESERVED_0_162 : {show: n, blk : 0, word: 5, pos : 2, len : 22, start: 162, type : 'uint:22', wr_dis: null, rd_dis: null, alt : '', dict : '', desc: reserved, rloc: 'EFUSE_RD_REPEAT_DATA4_REG[23:2]', bloc: 'B20[7:2],B21,B22'} + MAC : {show: y, blk : 1, word: 0, pos : 0, len : 48, start : 0, type : 'bytes:6', wr_dis : 20, rd_dis: null, alt : MAC_FACTORY, dict : '', desc: MAC address, rloc: EFUSE_RD_MAC_SPI_SYS_0_REG, bloc: 'B0,B1,B2,B3,B4,B5'} + SPI_PAD_CONFIG_CLK : {show: y, blk : 1, word: 1, pos: 16, len : 6, start : 48, type : 'uint:6', wr_dis : 20, rd_dis: null, alt : '', dict : '', desc: SPI_PAD_configure CLK, rloc: 'EFUSE_RD_MAC_SPI_SYS_1_REG[21:16]', bloc: 'B6[5:0]'} + SPI_PAD_CONFIG_Q : {show: y, blk : 1, word: 1, pos: 22, len : 6, start : 54, type : 'uint:6', wr_dis : 20, rd_dis: null, alt : '', dict : '', desc: SPI_PAD_configure Q(D1), rloc: 'EFUSE_RD_MAC_SPI_SYS_1_REG[27:22]', bloc: 'B6[7:6],B7[3:0]'} + SPI_PAD_CONFIG_D : {show: y, blk : 1, word: 1, pos: 28, len : 6, start : 60, type : 'uint:6', wr_dis : 20, rd_dis: null, alt : '', dict : '', desc: SPI_PAD_configure D(D0), rloc: 'EFUSE_RD_MAC_SPI_SYS_1_REG[31:28]', bloc: 'B7[7:4],B8[1:0]'} + SPI_PAD_CONFIG_CS : {show: y, blk : 1, word: 2, pos : 2, len : 6, start : 66, type : 'uint:6', wr_dis : 20, rd_dis: null, alt : '', dict : '', desc: SPI_PAD_configure CS, rloc: 'EFUSE_RD_MAC_SPI_SYS_2_REG[7:2]', bloc: 'B8[7:2]'} + SPI_PAD_CONFIG_HD : {show: y, blk : 1, word: 2, pos : 8, len : 6, start : 72, type : 'uint:6', wr_dis : 20, rd_dis: null, alt : '', dict : '', desc: SPI_PAD_configure HD(D3), rloc: 'EFUSE_RD_MAC_SPI_SYS_2_REG[13:8]', bloc: 'B9[5:0]'} + SPI_PAD_CONFIG_WP : {show: y, blk : 1, word: 2, pos: 14, len : 6, start : 78, type : 'uint:6', wr_dis : 20, rd_dis: null, alt : '', dict : '', desc: SPI_PAD_configure WP(D2), rloc: 'EFUSE_RD_MAC_SPI_SYS_2_REG[19:14]', bloc: 'B9[7:6],B10[3:0]'} + SPI_PAD_CONFIG_DQS : {show: y, blk : 1, word: 2, pos: 20, len : 6, start : 84, type : 'uint:6', wr_dis : 20, rd_dis: null, alt : '', dict : '', desc: SPI_PAD_configure DQS, rloc: 'EFUSE_RD_MAC_SPI_SYS_2_REG[25:20]', bloc: 'B10[7:4],B11[1:0]'} + SPI_PAD_CONFIG_D4 : {show: y, blk : 1, word: 2, pos: 26, len : 6, start : 90, type : 'uint:6', wr_dis : 20, rd_dis: null, alt : '', dict : '', desc: SPI_PAD_configure D4, rloc: 'EFUSE_RD_MAC_SPI_SYS_2_REG[31:26]', bloc: 'B11[7:2]'} + SPI_PAD_CONFIG_D5 : {show: y, blk : 1, word: 3, pos : 0, len : 6, start : 96, type : 'uint:6', wr_dis : 20, rd_dis: null, alt : '', dict : '', desc: SPI_PAD_configure D5, rloc: 'EFUSE_RD_MAC_SPI_SYS_3_REG[5:0]', bloc: 'B12[5:0]'} + SPI_PAD_CONFIG_D6 : {show: y, blk : 1, word: 3, pos : 6, len : 6, start: 102, type : 'uint:6', wr_dis : 20, rd_dis: null, alt : '', dict : '', desc: SPI_PAD_configure D6, rloc: 'EFUSE_RD_MAC_SPI_SYS_3_REG[11:6]', bloc: 'B12[7:6],B13[3:0]'} + SPI_PAD_CONFIG_D7 : {show: y, blk : 1, word: 3, pos: 12, len : 6, start: 108, type : 'uint:6', wr_dis : 20, rd_dis: null, alt : '', dict : '', desc: SPI_PAD_configure D7, rloc: 'EFUSE_RD_MAC_SPI_SYS_3_REG[17:12]', bloc: 'B13[7:4],B14[1:0]'} + WAFER_VERSION_MAJOR : {show: y, blk : 1, word: 3, pos: 18, len : 2, start: 114, type : 'uint:2', wr_dis : 20, rd_dis: null, alt : '', dict : '', desc: WAFER_VERSION_MAJOR, rloc: 'EFUSE_RD_MAC_SPI_SYS_3_REG[19:18]', bloc: 'B14[3:2]'} + WAFER_VERSION_MINOR_HI : {show: y, blk : 1, word: 3, pos: 20, len : 1, start: 116, type : bool, wr_dis : 20, rd_dis: null, alt : '', dict : '', desc: WAFER_VERSION_MINOR most significant bit, rloc: 'EFUSE_RD_MAC_SPI_SYS_3_REG[20]', bloc: 'B14[4]'} + FLASH_VERSION : {show: y, blk : 1, word: 3, pos: 21, len : 4, start: 117, type : 'uint:4', wr_dis : 20, rd_dis: null, alt : '', dict : '', desc: Flash version, rloc: 'EFUSE_RD_MAC_SPI_SYS_3_REG[24:21]', bloc: 'B14[7:5],B15[0]'} + BLK_VERSION_MAJOR : {show: y, blk : 1, word: 3, pos: 25, len : 2, start: 121, type : 'uint:2', wr_dis : 20, rd_dis: null, alt : '', dict : '', desc: BLK_VERSION_MAJOR, rloc: 'EFUSE_RD_MAC_SPI_SYS_3_REG[26:25]', bloc: 'B15[2:1]'} + RESERVED_1_123 : {show: n, blk : 1, word: 3, pos: 27, len : 1, start: 123, type : bool, wr_dis : 20, rd_dis: null, alt : '', dict : '', desc: reserved, rloc: 'EFUSE_RD_MAC_SPI_SYS_3_REG[27]', bloc: 'B15[3]'} + PSRAM_VERSION : {show: y, blk : 1, word: 3, pos: 28, len : 4, start: 124, type : 'uint:4', wr_dis : 20, rd_dis: null, alt : '', dict : '', desc: PSRAM version, rloc: 'EFUSE_RD_MAC_SPI_SYS_3_REG[31:28]', bloc: 'B15[7:4]'} + PKG_VERSION : {show: y, blk : 1, word: 4, pos : 0, len : 4, start: 128, type : 'uint:4', wr_dis : 20, rd_dis: null, alt : '', dict : '', desc: Package version, rloc: 'EFUSE_RD_MAC_SPI_SYS_4_REG[3:0]', bloc: 'B16[3:0]'} + WAFER_VERSION_MINOR_LO : {show: y, blk : 1, word: 4, pos : 4, len : 3, start: 132, type : 'uint:3', wr_dis : 20, rd_dis: null, alt : '', dict : '', desc: WAFER_VERSION_MINOR least significant bits, rloc: 'EFUSE_RD_MAC_SPI_SYS_4_REG[6:4]', bloc: 'B16[6:4]'} + RESERVED_1_135 : {show: n, blk : 1, word: 4, pos : 7, len : 25, start: 135, type : 'uint:25', wr_dis : 20, rd_dis: null, alt : '', dict : '', desc: reserved, rloc: 'EFUSE_RD_MAC_SPI_SYS_4_REG[31:7]', bloc: 'B16[7],B17,B18,B19'} + SYS_DATA_PART0_2 : {show: n, blk : 1, word: 5, pos : 0, len : 32, start: 160, type : 'uint:32', wr_dis : 20, rd_dis: null, alt : '', dict : '', desc: Stores the second part of the zeroth part of system data, rloc: EFUSE_RD_MAC_SPI_SYS_5_REG, bloc: 'B20,B21,B22,B23'} + OPTIONAL_UNIQUE_ID : {show: y, blk : 2, word: 0, pos : 0, len: 128, start : 0, type: 'bytes:16', wr_dis : 21, rd_dis: null, alt : '', dict : '', desc: Optional unique 128-bit ID, rloc: EFUSE_RD_SYS_PART1_DATA0_REG, bloc: 'B0,B1,B2,B3,B4,B5,B6,B7,B8,B9,B10,B11,B12,B13,B14,B15'} + ADC_CALIB : {show: y, blk : 2, word: 4, pos : 0, len : 4, start: 128, type : 'uint:4', wr_dis : 21, rd_dis: null, alt : '', dict : '', desc: 4 bit of ADC calibration, rloc: 'EFUSE_RD_SYS_PART1_DATA4_REG[3:0]', bloc: 'B16[3:0]'} + BLK_VERSION_MINOR : {show: y, blk : 2, word: 4, pos : 4, len : 3, start: 132, type : 'uint:3', wr_dis : 21, rd_dis: null, alt : '', dict: '{0: "No calib", 1: "ADC calib V1", 2: "ADC calib V2"}', desc: BLK_VERSION_MINOR of BLOCK2, rloc: 'EFUSE_RD_SYS_PART1_DATA4_REG[6:4]', bloc: 'B16[6:4]'} + TEMP_CALIB : {show: y, blk : 2, word: 4, pos : 7, len : 9, start: 135, type : 'uint:9', wr_dis : 21, rd_dis: null, alt : '', dict : '', desc: Temperature calibration data, rloc: 'EFUSE_RD_SYS_PART1_DATA4_REG[15:7]', bloc: 'B16[7],B17'} + RTCCALIB_V1IDX_A10H : {show: y, blk : 2, word: 4, pos: 16, len : 8, start: 144, type : 'uint:8', wr_dis : 21, rd_dis: null, alt : '', dict : '', desc: '', rloc: 'EFUSE_RD_SYS_PART1_DATA4_REG[23:16]', bloc: B18} + RTCCALIB_V1IDX_A11H : {show: y, blk : 2, word: 4, pos: 24, len : 8, start: 152, type : 'uint:8', wr_dis : 21, rd_dis: null, alt : '', dict : '', desc: '', rloc: 'EFUSE_RD_SYS_PART1_DATA4_REG[31:24]', bloc: B19} + RTCCALIB_V1IDX_A12H : {show: y, blk : 2, word: 5, pos : 0, len : 8, start: 160, type : 'uint:8', wr_dis : 21, rd_dis: null, alt : '', dict : '', desc: '', rloc: 'EFUSE_RD_SYS_PART1_DATA5_REG[7:0]', bloc: B20} + RTCCALIB_V1IDX_A13H : {show: y, blk : 2, word: 5, pos : 8, len : 8, start: 168, type : 'uint:8', wr_dis : 21, rd_dis: null, alt : '', dict : '', desc: '', rloc: 'EFUSE_RD_SYS_PART1_DATA5_REG[15:8]', bloc: B21} + RTCCALIB_V1IDX_A20H : {show: y, blk : 2, word: 5, pos: 16, len : 8, start: 176, type : 'uint:8', wr_dis : 21, rd_dis: null, alt : '', dict : '', desc: '', rloc: 'EFUSE_RD_SYS_PART1_DATA5_REG[23:16]', bloc: B22} + RTCCALIB_V1IDX_A21H : {show: y, blk : 2, word: 5, pos: 24, len : 8, start: 184, type : 'uint:8', wr_dis : 21, rd_dis: null, alt : '', dict : '', desc: '', rloc: 'EFUSE_RD_SYS_PART1_DATA5_REG[31:24]', bloc: B23} + RTCCALIB_V1IDX_A22H : {show: y, blk : 2, word: 6, pos : 0, len : 8, start: 192, type : 'uint:8', wr_dis : 21, rd_dis: null, alt : '', dict : '', desc: '', rloc: 'EFUSE_RD_SYS_PART1_DATA6_REG[7:0]', bloc: B24} + RTCCALIB_V1IDX_A23H : {show: y, blk : 2, word: 6, pos : 8, len : 8, start: 200, type : 'uint:8', wr_dis : 21, rd_dis: null, alt : '', dict : '', desc: '', rloc: 'EFUSE_RD_SYS_PART1_DATA6_REG[15:8]', bloc: B25} + RTCCALIB_V1IDX_A10L : {show: y, blk : 2, word: 6, pos: 16, len : 6, start: 208, type : 'uint:6', wr_dis : 21, rd_dis: null, alt : '', dict : '', desc: '', rloc: 'EFUSE_RD_SYS_PART1_DATA6_REG[21:16]', bloc: 'B26[5:0]'} + RTCCALIB_V1IDX_A11L : {show: y, blk : 2, word: 6, pos: 22, len : 6, start: 214, type : 'uint:6', wr_dis : 21, rd_dis: null, alt : '', dict : '', desc: '', rloc: 'EFUSE_RD_SYS_PART1_DATA6_REG[27:22]', bloc: 'B26[7:6],B27[3:0]'} + RTCCALIB_V1IDX_A12L : {show: y, blk : 2, word: 6, pos: 28, len : 6, start: 220, type : 'uint:6', wr_dis : 21, rd_dis: null, alt : '', dict : '', desc: '', rloc: 'EFUSE_RD_SYS_PART1_DATA6_REG[31:28]', bloc: 'B27[7:4],B28[1:0]'} + RTCCALIB_V1IDX_A13L : {show: y, blk : 2, word: 7, pos : 2, len : 6, start: 226, type : 'uint:6', wr_dis : 21, rd_dis: null, alt : '', dict : '', desc: '', rloc: 'EFUSE_RD_SYS_PART1_DATA7_REG[7:2]', bloc: 'B28[7:2]'} + RTCCALIB_V1IDX_A20L : {show: y, blk : 2, word: 7, pos : 8, len : 6, start: 232, type : 'uint:6', wr_dis : 21, rd_dis: null, alt : '', dict : '', desc: '', rloc: 'EFUSE_RD_SYS_PART1_DATA7_REG[13:8]', bloc: 'B29[5:0]'} + RTCCALIB_V1IDX_A21L : {show: y, blk : 2, word: 7, pos: 14, len : 6, start: 238, type : 'uint:6', wr_dis : 21, rd_dis: null, alt : '', dict : '', desc: '', rloc: 'EFUSE_RD_SYS_PART1_DATA7_REG[19:14]', bloc: 'B29[7:6],B30[3:0]'} + RTCCALIB_V1IDX_A22L : {show: y, blk : 2, word: 7, pos: 20, len : 6, start: 244, type : 'uint:6', wr_dis : 21, rd_dis: null, alt : '', dict : '', desc: '', rloc: 'EFUSE_RD_SYS_PART1_DATA7_REG[25:20]', bloc: 'B30[7:4],B31[1:0]'} + RTCCALIB_V1IDX_A23L : {show: y, blk : 2, word: 7, pos: 26, len : 6, start: 250, type : 'uint:6', wr_dis : 21, rd_dis: null, alt : '', dict : '', desc: '', rloc: 'EFUSE_RD_SYS_PART1_DATA7_REG[31:26]', bloc: 'B31[7:2]'} + BLOCK_USR_DATA : {show: y, blk : 3, word: 0, pos : 0, len: 192, start : 0, type: 'bytes:24', wr_dis : 22, rd_dis: null, alt : USER_DATA, dict : '', desc: User data, rloc: EFUSE_RD_USR_DATA0_REG, bloc: 'B0,B1,B2,B3,B4,B5,B6,B7,B8,B9,B10,B11,B12,B13,B14,B15,B16,B17,B18,B19,B20,B21,B22,B23'} + RESERVED_3_192 : {show: n, blk : 3, word: 6, pos : 0, len : 8, start: 192, type : 'uint:8', wr_dis : 22, rd_dis: null, alt : '', dict : '', desc: reserved, rloc: 'EFUSE_RD_USR_DATA6_REG[7:0]', bloc: B24} + CUSTOM_MAC : {show: y, blk : 3, word: 6, pos : 8, len : 48, start: 200, type : 'bytes:6', wr_dis : 22, rd_dis: null, alt: MAC_CUSTOM USER_DATA_MAC_CUSTOM, dict : '', desc: Custom MAC, rloc: 'EFUSE_RD_USR_DATA6_REG[31:8]', bloc: 'B25,B26,B27,B28,B29,B30'} + RESERVED_3_248 : {show: n, blk : 3, word: 7, pos: 24, len : 8, start: 248, type : 'uint:8', wr_dis : 22, rd_dis: null, alt : '', dict : '', desc: reserved, rloc: 'EFUSE_RD_USR_DATA7_REG[31:24]', bloc: B31} + BLOCK_KEY0 : {show: y, blk : 4, word: 0, pos : 0, len: 256, start : 0, type: 'bytes:32', wr_dis : 23, rd_dis : 0, alt : KEY0, dict : '', desc: Key0 or user data, rloc: EFUSE_RD_KEY0_DATA0_REG, bloc: 'B0,B1,B2,B3,B4,B5,B6,B7,B8,B9,B10,B11,B12,B13,B14,B15,B16,B17,B18,B19,B20,B21,B22,B23,B24,B25,B26,B27,B28,B29,B30,B31'} + BLOCK_KEY1 : {show: y, blk : 5, word: 0, pos : 0, len: 256, start : 0, type: 'bytes:32', wr_dis : 24, rd_dis : 1, alt : KEY1, dict : '', desc: Key1 or user data, rloc: EFUSE_RD_KEY1_DATA0_REG, bloc: 'B0,B1,B2,B3,B4,B5,B6,B7,B8,B9,B10,B11,B12,B13,B14,B15,B16,B17,B18,B19,B20,B21,B22,B23,B24,B25,B26,B27,B28,B29,B30,B31'} + BLOCK_KEY2 : {show: y, blk : 6, word: 0, pos : 0, len: 256, start : 0, type: 'bytes:32', wr_dis : 25, rd_dis : 2, alt : KEY2, dict : '', desc: Key2 or user data, rloc: EFUSE_RD_KEY2_DATA0_REG, bloc: 'B0,B1,B2,B3,B4,B5,B6,B7,B8,B9,B10,B11,B12,B13,B14,B15,B16,B17,B18,B19,B20,B21,B22,B23,B24,B25,B26,B27,B28,B29,B30,B31'} + BLOCK_KEY3 : {show: y, blk : 7, word: 0, pos : 0, len: 256, start : 0, type: 'bytes:32', wr_dis : 26, rd_dis : 3, alt : KEY3, dict : '', desc: Key3 or user data, rloc: EFUSE_RD_KEY3_DATA0_REG, bloc: 'B0,B1,B2,B3,B4,B5,B6,B7,B8,B9,B10,B11,B12,B13,B14,B15,B16,B17,B18,B19,B20,B21,B22,B23,B24,B25,B26,B27,B28,B29,B30,B31'} + BLOCK_KEY4 : {show: y, blk : 8, word: 0, pos : 0, len: 256, start : 0, type: 'bytes:32', wr_dis : 27, rd_dis : 4, alt : KEY4, dict : '', desc: Key4 or user data, rloc: EFUSE_RD_KEY4_DATA0_REG, bloc: 'B0,B1,B2,B3,B4,B5,B6,B7,B8,B9,B10,B11,B12,B13,B14,B15,B16,B17,B18,B19,B20,B21,B22,B23,B24,B25,B26,B27,B28,B29,B30,B31'} + BLOCK_KEY5 : {show: y, blk : 9, word: 0, pos : 0, len: 256, start : 0, type: 'bytes:32', wr_dis : 28, rd_dis : 5, alt : KEY5, dict : '', desc: Key5 or user data, rloc: EFUSE_RD_KEY5_DATA0_REG, bloc: 'B0,B1,B2,B3,B4,B5,B6,B7,B8,B9,B10,B11,B12,B13,B14,B15,B16,B17,B18,B19,B20,B21,B22,B23,B24,B25,B26,B27,B28,B29,B30,B31'} + BLOCK_SYS_DATA2 : {show: y, blk: 10, word: 0, pos : 0, len: 256, start : 0, type: 'bytes:32', wr_dis : 29, rd_dis : 6, alt : SYS_DATA_PART2, dict : '', desc: System data part 2 (reserved), rloc: EFUSE_RD_SYS_PART2_DATA0_REG, bloc: 'B0,B1,B2,B3,B4,B5,B6,B7,B8,B9,B10,B11,B12,B13,B14,B15,B16,B17,B18,B19,B20,B21,B22,B23,B24,B25,B26,B27,B28,B29,B30,B31'} diff --git a/espefuse/efuse_defs/esp32s3.yaml b/espefuse/efuse_defs/esp32s3.yaml new file mode 100644 index 000000000..4d4c69511 --- /dev/null +++ b/espefuse/efuse_defs/esp32s3.yaml @@ -0,0 +1,134 @@ +VER_NO: f75f74727101326a187188a23f4a6c70 +EFUSES: + WR_DIS : {show: y, blk : 0, word: 0, pos : 0, len : 32, start : 0, type : 'uint:32', wr_dis: null, rd_dis: null, alt : '', dict : '', desc: Disable programming of individual eFuses, rloc: EFUSE_RD_WR_DIS_REG, bloc: 'B0,B1,B2,B3'} + RD_DIS : {show: y, blk : 0, word: 1, pos : 0, len : 7, start : 32, type : 'uint:7', wr_dis : 0, rd_dis: null, alt : '', dict : '', desc: Disable reading from BlOCK4-10, rloc: 'EFUSE_RD_REPEAT_DATA0_REG[6:0]', bloc: 'B4[6:0]'} + DIS_RTC_RAM_BOOT : {show: n, blk : 0, word: 1, pos : 7, len : 1, start : 39, type : bool, wr_dis : 1, rd_dis: null, alt : '', dict : '', desc: Set this bit to disable boot from RTC RAM, rloc: 'EFUSE_RD_REPEAT_DATA0_REG[7]', bloc: 'B4[7]'} + DIS_ICACHE : {show: y, blk : 0, word: 1, pos : 8, len : 1, start : 40, type : bool, wr_dis : 2, rd_dis: null, alt : '', dict : '', desc: Set this bit to disable Icache, rloc: 'EFUSE_RD_REPEAT_DATA0_REG[8]', bloc: 'B5[0]'} + DIS_DCACHE : {show: y, blk : 0, word: 1, pos : 9, len : 1, start : 41, type : bool, wr_dis : 2, rd_dis: null, alt : '', dict : '', desc: Set this bit to disable Dcache, rloc: 'EFUSE_RD_REPEAT_DATA0_REG[9]', bloc: 'B5[1]'} + DIS_DOWNLOAD_ICACHE : {show: y, blk : 0, word: 1, pos: 10, len : 1, start : 42, type : bool, wr_dis : 2, rd_dis: null, alt : '', dict : '', desc: 'Set this bit to disable Icache in download mode (boot_mode[3:0] is 0; 1; 2; 3; 6; 7)', rloc: 'EFUSE_RD_REPEAT_DATA0_REG[10]', bloc: 'B5[2]'} + DIS_DOWNLOAD_DCACHE : {show: y, blk : 0, word: 1, pos: 11, len : 1, start : 43, type : bool, wr_dis : 2, rd_dis: null, alt : '', dict : '', desc: 'Set this bit to disable Dcache in download mode ( boot_mode[3:0] is 0; 1; 2; 3; 6; 7)', rloc: 'EFUSE_RD_REPEAT_DATA0_REG[11]', bloc: 'B5[3]'} + DIS_FORCE_DOWNLOAD : {show: y, blk : 0, word: 1, pos: 12, len : 1, start : 44, type : bool, wr_dis : 2, rd_dis: null, alt : '', dict : '', desc: Set this bit to disable the function that forces chip into download mode, rloc: 'EFUSE_RD_REPEAT_DATA0_REG[12]', bloc: 'B5[4]'} + DIS_USB_OTG : {show: y, blk : 0, word: 1, pos: 13, len : 1, start : 45, type : bool, wr_dis : 2, rd_dis: null, alt : DIS_USB, dict : '', desc: Set this bit to disable USB function, rloc: 'EFUSE_RD_REPEAT_DATA0_REG[13]', bloc: 'B5[5]'} + DIS_TWAI : {show: y, blk : 0, word: 1, pos: 14, len : 1, start : 46, type : bool, wr_dis : 2, rd_dis: null, alt : DIS_CAN, dict : '', desc: Set this bit to disable CAN function, rloc: 'EFUSE_RD_REPEAT_DATA0_REG[14]', bloc: 'B5[6]'} + DIS_APP_CPU : {show: y, blk : 0, word: 1, pos: 15, len : 1, start : 47, type : bool, wr_dis : 2, rd_dis: null, alt : '', dict : '', desc: Disable app cpu, rloc: 'EFUSE_RD_REPEAT_DATA0_REG[15]', bloc: 'B5[7]'} + SOFT_DIS_JTAG : {show: y, blk : 0, word: 1, pos: 16, len : 3, start : 48, type : 'uint:3', wr_dis : 31, rd_dis: null, alt : '', dict : '', desc: Set these bits to disable JTAG in the soft way (odd number 1 means disable ). JTAG can be enabled in HMAC module, rloc: 'EFUSE_RD_REPEAT_DATA0_REG[18:16]', bloc: 'B6[2:0]'} + DIS_PAD_JTAG : {show: y, blk : 0, word: 1, pos: 19, len : 1, start : 51, type : bool, wr_dis : 2, rd_dis: null, alt : HARD_DIS_JTAG, dict : '', desc: Set this bit to disable JTAG in the hard way. JTAG is disabled permanently, rloc: 'EFUSE_RD_REPEAT_DATA0_REG[19]', bloc: 'B6[3]'} + DIS_DOWNLOAD_MANUAL_ENCRYPT : {show: y, blk : 0, word: 1, pos: 20, len : 1, start : 52, type : bool, wr_dis : 2, rd_dis: null, alt : '', dict : '', desc: Set this bit to disable flash encryption when in download boot modes, rloc: 'EFUSE_RD_REPEAT_DATA0_REG[20]', bloc: 'B6[4]'} + USB_DREFH : {show: n, blk : 0, word: 1, pos: 21, len : 2, start : 53, type : 'uint:2', wr_dis : 30, rd_dis: null, alt : '', dict : '', desc: Controls single-end input threshold vrefh; 1.76 V to 2 V with step of 80 mV; stored in eFuse, rloc: 'EFUSE_RD_REPEAT_DATA0_REG[22:21]', bloc: 'B6[6:5]'} + USB_DREFL : {show: n, blk : 0, word: 1, pos: 23, len : 2, start : 55, type : 'uint:2', wr_dis : 30, rd_dis: null, alt : '', dict : '', desc: Controls single-end input threshold vrefl; 0.8 V to 1.04 V with step of 80 mV; stored in eFuse, rloc: 'EFUSE_RD_REPEAT_DATA0_REG[24:23]', bloc: 'B6[7],B7[0]'} + USB_EXCHG_PINS : {show: y, blk : 0, word: 1, pos: 25, len : 1, start : 57, type : bool, wr_dis : 30, rd_dis: null, alt : '', dict : '', desc: Set this bit to exchange USB D+ and D- pins, rloc: 'EFUSE_RD_REPEAT_DATA0_REG[25]', bloc: 'B7[1]'} + USB_EXT_PHY_ENABLE : {show: y, blk : 0, word: 1, pos: 26, len : 1, start : 58, type : bool, wr_dis : 30, rd_dis: null, alt : EXT_PHY_ENABLE, dict : '', desc: Set this bit to enable external PHY, rloc: 'EFUSE_RD_REPEAT_DATA0_REG[26]', bloc: 'B7[2]'} + BTLC_GPIO_ENABLE : {show: n, blk : 0, word: 1, pos: 27, len : 2, start : 59, type : 'uint:2', wr_dis : 30, rd_dis: null, alt : '', dict : '', desc: Bluetooth GPIO signal output security level control, rloc: 'EFUSE_RD_REPEAT_DATA0_REG[28:27]', bloc: 'B7[4:3]'} + VDD_SPI_MODECURLIM : {show: n, blk : 0, word: 1, pos: 29, len : 1, start : 61, type : bool, wr_dis : 3, rd_dis: null, alt : '', dict : '', desc: SPI regulator switches current limit mode, rloc: 'EFUSE_RD_REPEAT_DATA0_REG[29]', bloc: 'B7[5]'} + VDD_SPI_DREFH : {show: n, blk : 0, word: 1, pos: 30, len : 2, start : 62, type : 'uint:2', wr_dis : 3, rd_dis: null, alt : '', dict : '', desc: SPI regulator high voltage reference, rloc: 'EFUSE_RD_REPEAT_DATA0_REG[31:30]', bloc: 'B7[7:6]'} + VDD_SPI_DREFM : {show: n, blk : 0, word: 2, pos : 0, len : 2, start : 64, type : 'uint:2', wr_dis : 3, rd_dis: null, alt : '', dict : '', desc: SPI regulator medium voltage reference, rloc: 'EFUSE_RD_REPEAT_DATA1_REG[1:0]', bloc: 'B8[1:0]'} + VDD_SPI_DREFL : {show: n, blk : 0, word: 2, pos : 2, len : 2, start : 66, type : 'uint:2', wr_dis : 3, rd_dis: null, alt : '', dict : '', desc: SPI regulator low voltage reference, rloc: 'EFUSE_RD_REPEAT_DATA1_REG[3:2]', bloc: 'B8[3:2]'} + VDD_SPI_XPD : {show: y, blk : 0, word: 2, pos : 4, len : 1, start : 68, type : bool, wr_dis : 3, rd_dis: null, alt : '', dict : '', desc: SPI regulator power up signal, rloc: 'EFUSE_RD_REPEAT_DATA1_REG[4]', bloc: 'B8[4]'} + VDD_SPI_TIEH : {show: y, blk : 0, word: 2, pos : 5, len : 1, start : 69, type : bool, wr_dis : 3, rd_dis: null, alt : '', dict: '{0: "VDD_SPI connects to 1.8 V LDO", 1: "VDD_SPI connects to VDD3P3_RTC_IO"}', desc: If VDD_SPI_FORCE is 1; determines VDD_SPI voltage, rloc: 'EFUSE_RD_REPEAT_DATA1_REG[5]', bloc: 'B8[5]'} + VDD_SPI_FORCE : {show: y, blk : 0, word: 2, pos : 6, len : 1, start : 70, type : bool, wr_dis : 3, rd_dis: null, alt : '', dict : '', desc: Set this bit and force to use the configuration of eFuse to configure VDD_SPI, rloc: 'EFUSE_RD_REPEAT_DATA1_REG[6]', bloc: 'B8[6]'} + VDD_SPI_EN_INIT : {show: n, blk : 0, word: 2, pos : 7, len : 1, start : 71, type : bool, wr_dis : 3, rd_dis: null, alt : '', dict : '', desc: 'Set SPI regulator to 0 to configure init[1:0]=0', rloc: 'EFUSE_RD_REPEAT_DATA1_REG[7]', bloc: 'B8[7]'} + VDD_SPI_ENCURLIM : {show: n, blk : 0, word: 2, pos : 8, len : 1, start : 72, type : bool, wr_dis : 3, rd_dis: null, alt : '', dict : '', desc: Set SPI regulator to 1 to enable output current limit, rloc: 'EFUSE_RD_REPEAT_DATA1_REG[8]', bloc: 'B9[0]'} + VDD_SPI_DCURLIM : {show: n, blk : 0, word: 2, pos : 9, len : 3, start : 73, type : 'uint:3', wr_dis : 3, rd_dis: null, alt : '', dict : '', desc: Tunes the current limit threshold of SPI regulator when tieh=0; about 800 mA/(8+d), rloc: 'EFUSE_RD_REPEAT_DATA1_REG[11:9]', bloc: 'B9[3:1]'} + VDD_SPI_INIT : {show: n, blk : 0, word: 2, pos: 12, len : 2, start : 76, type : 'uint:2', wr_dis : 3, rd_dis: null, alt : '', dict: '{0: "no resistance", 1: "6K", 2: "4K", 3: "2K"}', desc: Adds resistor from LDO output to ground, rloc: 'EFUSE_RD_REPEAT_DATA1_REG[13:12]', bloc: 'B9[5:4]'} + VDD_SPI_DCAP : {show: n, blk : 0, word: 2, pos: 14, len : 2, start : 78, type : 'uint:2', wr_dis : 3, rd_dis: null, alt : '', dict : '', desc: Prevents SPI regulator from overshoot, rloc: 'EFUSE_RD_REPEAT_DATA1_REG[15:14]', bloc: 'B9[7:6]'} + WDT_DELAY_SEL : {show: y, blk : 0, word: 2, pos: 16, len : 2, start : 80, type : 'uint:2', wr_dis : 3, rd_dis: null, alt : '', dict: '{0: "40000", 1: "80000", 2: "160000", 3: "320000"}', desc: RTC watchdog timeout threshold; in unit of slow clock cycle, rloc: 'EFUSE_RD_REPEAT_DATA1_REG[17:16]', bloc: 'B10[1:0]'} + SPI_BOOT_CRYPT_CNT : {show: y, blk : 0, word: 2, pos: 18, len : 3, start : 82, type : 'uint:3', wr_dis : 4, rd_dis: null, alt : '', dict: '{0: "Disable", 1: "Enable", 3: "Disable", 7: "Enable"}', desc: Enables flash encryption when 1 or 3 bits are set and disabled otherwise, rloc: 'EFUSE_RD_REPEAT_DATA1_REG[20:18]', bloc: 'B10[4:2]'} + SECURE_BOOT_KEY_REVOKE0 : {show: y, blk : 0, word: 2, pos: 21, len : 1, start : 85, type : bool, wr_dis : 5, rd_dis: null, alt : '', dict : '', desc: Revoke 1st secure boot key, rloc: 'EFUSE_RD_REPEAT_DATA1_REG[21]', bloc: 'B10[5]'} + SECURE_BOOT_KEY_REVOKE1 : {show: y, blk : 0, word: 2, pos: 22, len : 1, start : 86, type : bool, wr_dis : 6, rd_dis: null, alt : '', dict : '', desc: Revoke 2nd secure boot key, rloc: 'EFUSE_RD_REPEAT_DATA1_REG[22]', bloc: 'B10[6]'} + SECURE_BOOT_KEY_REVOKE2 : {show: y, blk : 0, word: 2, pos: 23, len : 1, start : 87, type : bool, wr_dis : 7, rd_dis: null, alt : '', dict : '', desc: Revoke 3rd secure boot key, rloc: 'EFUSE_RD_REPEAT_DATA1_REG[23]', bloc: 'B10[7]'} + KEY_PURPOSE_0 : {show: y, blk : 0, word: 2, pos: 24, len : 4, start : 88, type : 'uint:4', wr_dis : 8, rd_dis: null, alt : KEY0_PURPOSE, dict : '', desc: Purpose of Key0, rloc: 'EFUSE_RD_REPEAT_DATA1_REG[27:24]', bloc: 'B11[3:0]'} + KEY_PURPOSE_1 : {show: y, blk : 0, word: 2, pos: 28, len : 4, start : 92, type : 'uint:4', wr_dis : 9, rd_dis: null, alt : KEY1_PURPOSE, dict : '', desc: Purpose of Key1, rloc: 'EFUSE_RD_REPEAT_DATA1_REG[31:28]', bloc: 'B11[7:4]'} + KEY_PURPOSE_2 : {show: y, blk : 0, word: 3, pos : 0, len : 4, start : 96, type : 'uint:4', wr_dis : 10, rd_dis: null, alt : KEY2_PURPOSE, dict : '', desc: Purpose of Key2, rloc: 'EFUSE_RD_REPEAT_DATA2_REG[3:0]', bloc: 'B12[3:0]'} + KEY_PURPOSE_3 : {show: y, blk : 0, word: 3, pos : 4, len : 4, start: 100, type : 'uint:4', wr_dis : 11, rd_dis: null, alt : KEY3_PURPOSE, dict : '', desc: Purpose of Key3, rloc: 'EFUSE_RD_REPEAT_DATA2_REG[7:4]', bloc: 'B12[7:4]'} + KEY_PURPOSE_4 : {show: y, blk : 0, word: 3, pos : 8, len : 4, start: 104, type : 'uint:4', wr_dis : 12, rd_dis: null, alt : KEY4_PURPOSE, dict : '', desc: Purpose of Key4, rloc: 'EFUSE_RD_REPEAT_DATA2_REG[11:8]', bloc: 'B13[3:0]'} + KEY_PURPOSE_5 : {show: y, blk : 0, word: 3, pos: 12, len : 4, start: 108, type : 'uint:4', wr_dis : 13, rd_dis: null, alt : KEY5_PURPOSE, dict : '', desc: Purpose of Key5, rloc: 'EFUSE_RD_REPEAT_DATA2_REG[15:12]', bloc: 'B13[7:4]'} + RPT4_RESERVED0 : {show: n, blk : 0, word: 3, pos: 16, len : 4, start: 112, type : 'uint:4', wr_dis: null, rd_dis: null, alt : '', dict : '', desc: Reserved (used for four backups method), rloc: 'EFUSE_RD_REPEAT_DATA2_REG[19:16]', bloc: 'B14[3:0]'} + SECURE_BOOT_EN : {show: y, blk : 0, word: 3, pos: 20, len : 1, start: 116, type : bool, wr_dis : 15, rd_dis: null, alt : '', dict : '', desc: Set this bit to enable secure boot, rloc: 'EFUSE_RD_REPEAT_DATA2_REG[20]', bloc: 'B14[4]'} + SECURE_BOOT_AGGRESSIVE_REVOKE : {show: y, blk : 0, word: 3, pos: 21, len : 1, start: 117, type : bool, wr_dis : 16, rd_dis: null, alt : '', dict : '', desc: Set this bit to enable revoking aggressive secure boot, rloc: 'EFUSE_RD_REPEAT_DATA2_REG[21]', bloc: 'B14[5]'} + DIS_USB_JTAG : {show: y, blk : 0, word: 3, pos: 22, len : 1, start: 118, type : bool, wr_dis : 2, rd_dis: null, alt : '', dict : '', desc: Set this bit to disable function of usb switch to jtag in module of usb device, rloc: 'EFUSE_RD_REPEAT_DATA2_REG[22]', bloc: 'B14[6]'} + DIS_USB_SERIAL_JTAG : {show: y, blk : 0, word: 3, pos: 23, len : 1, start: 119, type : bool, wr_dis : 2, rd_dis: null, alt : DIS_USB_DEVICE, dict : '', desc: Set this bit to disable usb device, rloc: 'EFUSE_RD_REPEAT_DATA2_REG[23]', bloc: 'B14[7]'} + STRAP_JTAG_SEL : {show: y, blk : 0, word: 3, pos: 24, len : 1, start: 120, type : bool, wr_dis : 2, rd_dis: null, alt : '', dict : '', desc: Set this bit to enable selection between usb_to_jtag and pad_to_jtag through strapping gpio10 when both reg_dis_usb_jtag and reg_dis_pad_jtag are equal to 0, rloc: 'EFUSE_RD_REPEAT_DATA2_REG[24]', bloc: 'B15[0]'} + USB_PHY_SEL : {show: y, blk : 0, word: 3, pos: 25, len : 1, start: 121, type : bool, wr_dis : 2, rd_dis: null, alt : '', dict: '{0: "internal PHY is assigned to USB Device while external PHY is assigned to USB OTG", 1: "internal PHY is assigned to USB OTG while external PHY is assigned to USB Device"}', desc: This bit is used to switch internal PHY and external PHY for USB OTG and USB Device, rloc: 'EFUSE_RD_REPEAT_DATA2_REG[25]', bloc: 'B15[1]'} + POWER_GLITCH_DSENSE : {show: n, blk : 0, word: 3, pos: 26, len : 2, start: 122, type : 'uint:2', wr_dis : 17, rd_dis: null, alt : '', dict : '', desc: Sample delay configuration of power glitch, rloc: 'EFUSE_RD_REPEAT_DATA2_REG[27:26]', bloc: 'B15[3:2]'} + FLASH_TPUW : {show: y, blk : 0, word: 3, pos: 28, len : 4, start: 124, type : 'uint:4', wr_dis : 18, rd_dis: null, alt : '', dict : '', desc: Configures flash waiting time after power-up; in unit of ms. If the value is less than 15; the waiting time is the configurable value. Otherwise; the waiting time is twice the configurable value, rloc: 'EFUSE_RD_REPEAT_DATA2_REG[31:28]', bloc: 'B15[7:4]'} + DIS_DOWNLOAD_MODE : {show: y, blk : 0, word: 4, pos : 0, len : 1, start: 128, type : bool, wr_dis : 18, rd_dis: null, alt : '', dict : '', desc: 'Set this bit to disable download mode (boot_mode[3:0] = 0; 1; 2; 3; 6; 7)', rloc: 'EFUSE_RD_REPEAT_DATA3_REG[0]', bloc: 'B16[0]'} + DIS_DIRECT_BOOT : {show: y, blk : 0, word: 4, pos : 1, len : 1, start: 129, type : bool, wr_dis : 18, rd_dis: null, alt : DIS_LEGACY_SPI_BOOT, dict : '', desc: Disable direct boot mode, rloc: 'EFUSE_RD_REPEAT_DATA3_REG[1]', bloc: 'B16[1]'} + DIS_USB_SERIAL_JTAG_ROM_PRINT : {show: y, blk : 0, word: 4, pos : 2, len : 1, start: 130, type : bool, wr_dis : 18, rd_dis: null, alt : UART_PRINT_CHANNEL, dict: '{0: "Enable", 1: "Disable"}', desc: USB printing, rloc: 'EFUSE_RD_REPEAT_DATA3_REG[2]', bloc: 'B16[2]'} + FLASH_ECC_MODE : {show: y, blk : 0, word: 4, pos : 3, len : 1, start: 131, type : bool, wr_dis : 18, rd_dis: null, alt : '', dict: '{0: "16to18 byte", 1: "16to17 byte"}', desc: Flash ECC mode in ROM, rloc: 'EFUSE_RD_REPEAT_DATA3_REG[3]', bloc: 'B16[3]'} + DIS_USB_SERIAL_JTAG_DOWNLOAD_MODE: {show: y, blk : 0, word: 4, pos : 4, len : 1, start: 132, type : bool, wr_dis : 18, rd_dis: null, alt : DIS_USB_DOWNLOAD_MODE, dict : '', desc: Set this bit to disable UART download mode through USB, rloc: 'EFUSE_RD_REPEAT_DATA3_REG[4]', bloc: 'B16[4]'} + ENABLE_SECURITY_DOWNLOAD : {show: y, blk : 0, word: 4, pos : 5, len : 1, start: 133, type : bool, wr_dis : 18, rd_dis: null, alt : '', dict : '', desc: Set this bit to enable secure UART download mode, rloc: 'EFUSE_RD_REPEAT_DATA3_REG[5]', bloc: 'B16[5]'} + UART_PRINT_CONTROL : {show: y, blk : 0, word: 4, pos : 6, len : 2, start: 134, type : 'uint:2', wr_dis : 18, rd_dis: null, alt : '', dict: '{0: "Enable", 1: "Enable when GPIO46 is low at reset", 2: "Enable when GPIO46 is high at reset", 3: "Disable"}', desc: Set the default UART boot message output mode, rloc: 'EFUSE_RD_REPEAT_DATA3_REG[7:6]', bloc: 'B16[7:6]'} + PIN_POWER_SELECTION : {show: y, blk : 0, word: 4, pos : 8, len : 1, start: 136, type : bool, wr_dis : 18, rd_dis: null, alt : '', dict: '{0: "VDD3P3_CPU", 1: "VDD_SPI"}', desc: Set default power supply for GPIO33-GPIO37; set when SPI flash is initialized, rloc: 'EFUSE_RD_REPEAT_DATA3_REG[8]', bloc: 'B17[0]'} + FLASH_TYPE : {show: y, blk : 0, word: 4, pos : 9, len : 1, start: 137, type : bool, wr_dis : 18, rd_dis: null, alt : '', dict: '{0: "4 data lines", 1: "8 data lines"}', desc: SPI flash type, rloc: 'EFUSE_RD_REPEAT_DATA3_REG[9]', bloc: 'B17[1]'} + FLASH_PAGE_SIZE : {show: y, blk : 0, word: 4, pos: 10, len : 2, start: 138, type : 'uint:2', wr_dis : 18, rd_dis: null, alt : '', dict : '', desc: Set Flash page size, rloc: 'EFUSE_RD_REPEAT_DATA3_REG[11:10]', bloc: 'B17[3:2]'} + FLASH_ECC_EN : {show: y, blk : 0, word: 4, pos: 12, len : 1, start: 140, type : bool, wr_dis : 18, rd_dis: null, alt : '', dict : '', desc: Set 1 to enable ECC for flash boot, rloc: 'EFUSE_RD_REPEAT_DATA3_REG[12]', bloc: 'B17[4]'} + FORCE_SEND_RESUME : {show: y, blk : 0, word: 4, pos: 13, len : 1, start: 141, type : bool, wr_dis : 18, rd_dis: null, alt : '', dict : '', desc: Set this bit to force ROM code to send a resume command during SPI boot, rloc: 'EFUSE_RD_REPEAT_DATA3_REG[13]', bloc: 'B17[5]'} + SECURE_VERSION : {show: y, blk : 0, word: 4, pos: 14, len : 16, start: 142, type : 'uint:16', wr_dis : 18, rd_dis: null, alt : '', dict : '', desc: Secure version (used by ESP-IDF anti-rollback feature), rloc: 'EFUSE_RD_REPEAT_DATA3_REG[29:14]', bloc: 'B17[7:6],B18,B19[5:0]'} + POWERGLITCH_EN : {show: n, blk : 0, word: 4, pos: 30, len : 1, start: 158, type : bool, wr_dis : 17, rd_dis: null, alt : '', dict : '', desc: Set this bit to enable power glitch function, rloc: 'EFUSE_RD_REPEAT_DATA3_REG[30]', bloc: 'B19[6]'} + DIS_USB_OTG_DOWNLOAD_MODE : {show: y, blk : 0, word: 4, pos: 31, len : 1, start: 159, type : bool, wr_dis : 19, rd_dis: null, alt : '', dict : '', desc: Set this bit to disable download through USB-OTG, rloc: 'EFUSE_RD_REPEAT_DATA3_REG[31]', bloc: 'B19[7]'} + DISABLE_WAFER_VERSION_MAJOR : {show: y, blk : 0, word: 5, pos : 0, len : 1, start: 160, type : bool, wr_dis : 19, rd_dis: null, alt : '', dict : '', desc: Disables check of wafer version major, rloc: 'EFUSE_RD_REPEAT_DATA4_REG[0]', bloc: 'B20[0]'} + DISABLE_BLK_VERSION_MAJOR : {show: y, blk : 0, word: 5, pos : 1, len : 1, start: 161, type : bool, wr_dis : 19, rd_dis: null, alt : '', dict : '', desc: Disables check of blk version major, rloc: 'EFUSE_RD_REPEAT_DATA4_REG[1]', bloc: 'B20[1]'} + RESERVED_0_162 : {show: n, blk : 0, word: 5, pos : 2, len : 22, start: 162, type : 'uint:22', wr_dis: null, rd_dis: null, alt : '', dict : '', desc: reserved, rloc: 'EFUSE_RD_REPEAT_DATA4_REG[23:2]', bloc: 'B20[7:2],B21,B22'} + MAC : {show: y, blk : 1, word: 0, pos : 0, len : 48, start : 0, type : 'bytes:6', wr_dis : 20, rd_dis: null, alt : MAC_FACTORY, dict : '', desc: MAC address, rloc: EFUSE_RD_MAC_SPI_SYS_0_REG, bloc: 'B0,B1,B2,B3,B4,B5'} + SPI_PAD_CONFIG_CLK : {show: y, blk : 1, word: 1, pos: 16, len : 6, start : 48, type : 'uint:6', wr_dis : 20, rd_dis: null, alt : '', dict : '', desc: SPI_PAD_configure CLK, rloc: 'EFUSE_RD_MAC_SPI_SYS_1_REG[21:16]', bloc: 'B6[5:0]'} + SPI_PAD_CONFIG_Q : {show: y, blk : 1, word: 1, pos: 22, len : 6, start : 54, type : 'uint:6', wr_dis : 20, rd_dis: null, alt : '', dict : '', desc: SPI_PAD_configure Q(D1), rloc: 'EFUSE_RD_MAC_SPI_SYS_1_REG[27:22]', bloc: 'B6[7:6],B7[3:0]'} + SPI_PAD_CONFIG_D : {show: y, blk : 1, word: 1, pos: 28, len : 6, start : 60, type : 'uint:6', wr_dis : 20, rd_dis: null, alt : '', dict : '', desc: SPI_PAD_configure D(D0), rloc: 'EFUSE_RD_MAC_SPI_SYS_1_REG[31:28]', bloc: 'B7[7:4],B8[1:0]'} + SPI_PAD_CONFIG_CS : {show: y, blk : 1, word: 2, pos : 2, len : 6, start : 66, type : 'uint:6', wr_dis : 20, rd_dis: null, alt : '', dict : '', desc: SPI_PAD_configure CS, rloc: 'EFUSE_RD_MAC_SPI_SYS_2_REG[7:2]', bloc: 'B8[7:2]'} + SPI_PAD_CONFIG_HD : {show: y, blk : 1, word: 2, pos : 8, len : 6, start : 72, type : 'uint:6', wr_dis : 20, rd_dis: null, alt : '', dict : '', desc: SPI_PAD_configure HD(D3), rloc: 'EFUSE_RD_MAC_SPI_SYS_2_REG[13:8]', bloc: 'B9[5:0]'} + SPI_PAD_CONFIG_WP : {show: y, blk : 1, word: 2, pos: 14, len : 6, start : 78, type : 'uint:6', wr_dis : 20, rd_dis: null, alt : '', dict : '', desc: SPI_PAD_configure WP(D2), rloc: 'EFUSE_RD_MAC_SPI_SYS_2_REG[19:14]', bloc: 'B9[7:6],B10[3:0]'} + SPI_PAD_CONFIG_DQS : {show: y, blk : 1, word: 2, pos: 20, len : 6, start : 84, type : 'uint:6', wr_dis : 20, rd_dis: null, alt : '', dict : '', desc: SPI_PAD_configure DQS, rloc: 'EFUSE_RD_MAC_SPI_SYS_2_REG[25:20]', bloc: 'B10[7:4],B11[1:0]'} + SPI_PAD_CONFIG_D4 : {show: y, blk : 1, word: 2, pos: 26, len : 6, start : 90, type : 'uint:6', wr_dis : 20, rd_dis: null, alt : '', dict : '', desc: SPI_PAD_configure D4, rloc: 'EFUSE_RD_MAC_SPI_SYS_2_REG[31:26]', bloc: 'B11[7:2]'} + SPI_PAD_CONFIG_D5 : {show: y, blk : 1, word: 3, pos : 0, len : 6, start : 96, type : 'uint:6', wr_dis : 20, rd_dis: null, alt : '', dict : '', desc: SPI_PAD_configure D5, rloc: 'EFUSE_RD_MAC_SPI_SYS_3_REG[5:0]', bloc: 'B12[5:0]'} + SPI_PAD_CONFIG_D6 : {show: y, blk : 1, word: 3, pos : 6, len : 6, start: 102, type : 'uint:6', wr_dis : 20, rd_dis: null, alt : '', dict : '', desc: SPI_PAD_configure D6, rloc: 'EFUSE_RD_MAC_SPI_SYS_3_REG[11:6]', bloc: 'B12[7:6],B13[3:0]'} + SPI_PAD_CONFIG_D7 : {show: y, blk : 1, word: 3, pos: 12, len : 6, start: 108, type : 'uint:6', wr_dis : 20, rd_dis: null, alt : '', dict : '', desc: SPI_PAD_configure D7, rloc: 'EFUSE_RD_MAC_SPI_SYS_3_REG[17:12]', bloc: 'B13[7:4],B14[1:0]'} + WAFER_VERSION_MINOR_LO : {show: y, blk : 1, word: 3, pos: 18, len : 3, start: 114, type : 'uint:3', wr_dis : 20, rd_dis: null, alt : '', dict : '', desc: WAFER_VERSION_MINOR least significant bits, rloc: 'EFUSE_RD_MAC_SPI_SYS_3_REG[20:18]', bloc: 'B14[4:2]'} + PKG_VERSION : {show: y, blk : 1, word: 3, pos: 21, len : 3, start: 117, type : 'uint:3', wr_dis : 20, rd_dis: null, alt : '', dict : '', desc: Package version, rloc: 'EFUSE_RD_MAC_SPI_SYS_3_REG[23:21]', bloc: 'B14[7:5]'} + BLK_VERSION_MINOR : {show: y, blk : 1, word: 3, pos: 24, len : 3, start: 120, type : 'uint:3', wr_dis : 20, rd_dis: null, alt : '', dict : '', desc: BLK_VERSION_MINOR, rloc: 'EFUSE_RD_MAC_SPI_SYS_3_REG[26:24]', bloc: 'B15[2:0]'} + FLASH_CAP : {show: y, blk : 1, word: 3, pos: 27, len : 3, start: 123, type : 'uint:3', wr_dis : 20, rd_dis: null, alt : '', dict: '{0: "None", 1: "8M", 2: "4M"}', desc: Flash capacity, rloc: 'EFUSE_RD_MAC_SPI_SYS_3_REG[29:27]', bloc: 'B15[5:3]'} + FLASH_TEMP : {show: y, blk : 1, word: 3, pos: 30, len : 2, start: 126, type : 'uint:2', wr_dis : 20, rd_dis: null, alt : '', dict: '{0: "None", 1: "105C", 2: "85C"}', desc: Flash temperature, rloc: 'EFUSE_RD_MAC_SPI_SYS_3_REG[31:30]', bloc: 'B15[7:6]'} + FLASH_VENDOR : {show: y, blk : 1, word: 4, pos : 0, len : 3, start: 128, type : 'uint:3', wr_dis : 20, rd_dis: null, alt : '', dict: '{0: "None", 1: "XMC", 2: "GD", 3: "FM", 4: "TT", 5: "BY"}', desc: Flash vendor, rloc: 'EFUSE_RD_MAC_SPI_SYS_4_REG[2:0]', bloc: 'B16[2:0]'} + PSRAM_CAP : {show: y, blk : 1, word: 4, pos : 3, len : 2, start: 131, type : 'uint:2', wr_dis : 20, rd_dis: null, alt : '', dict: '{0: "None", 1: "8M", 2: "2M"}', desc: PSRAM capacity, rloc: 'EFUSE_RD_MAC_SPI_SYS_4_REG[4:3]', bloc: 'B16[4:3]'} + PSRAM_TEMP : {show: y, blk : 1, word: 4, pos : 5, len : 2, start: 133, type : 'uint:2', wr_dis : 20, rd_dis: null, alt : '', dict: '{0: "None", 1: "105C", 2: "85C"}', desc: PSRAM temperature, rloc: 'EFUSE_RD_MAC_SPI_SYS_4_REG[6:5]', bloc: 'B16[6:5]'} + PSRAM_VENDOR : {show: y, blk : 1, word: 4, pos : 7, len : 2, start: 135, type : 'uint:2', wr_dis : 20, rd_dis: null, alt : '', dict: '{0: "None", 1: "AP_3v3", 2: "AP_1v8"}', desc: PSRAM vendor, rloc: 'EFUSE_RD_MAC_SPI_SYS_4_REG[8:7]', bloc: 'B16[7],B17[0]'} + RESERVED_1_137 : {show: n, blk : 1, word: 4, pos : 9, len : 4, start: 137, type : 'uint:4', wr_dis : 20, rd_dis: null, alt : '', dict : '', desc: reserved, rloc: 'EFUSE_RD_MAC_SPI_SYS_4_REG[12:9]', bloc: 'B17[4:1]'} + K_RTC_LDO : {show: y, blk : 1, word: 4, pos: 13, len : 7, start: 141, type : 'uint:7', wr_dis : 20, rd_dis: null, alt : '', dict : '', desc: BLOCK1 K_RTC_LDO, rloc: 'EFUSE_RD_MAC_SPI_SYS_4_REG[19:13]', bloc: 'B17[7:5],B18[3:0]'} + K_DIG_LDO : {show: y, blk : 1, word: 4, pos: 20, len : 7, start: 148, type : 'uint:7', wr_dis : 20, rd_dis: null, alt : '', dict : '', desc: BLOCK1 K_DIG_LDO, rloc: 'EFUSE_RD_MAC_SPI_SYS_4_REG[26:20]', bloc: 'B18[7:4],B19[2:0]'} + V_RTC_DBIAS20 : {show: y, blk : 1, word: 4, pos: 27, len : 8, start: 155, type : 'uint:8', wr_dis : 20, rd_dis: null, alt : '', dict : '', desc: BLOCK1 voltage of rtc dbias20, rloc: 'EFUSE_RD_MAC_SPI_SYS_4_REG[31:27]', bloc: 'B19[7:3],B20[2:0]'} + V_DIG_DBIAS20 : {show: y, blk : 1, word: 5, pos : 3, len : 8, start: 163, type : 'uint:8', wr_dis : 20, rd_dis: null, alt : '', dict : '', desc: BLOCK1 voltage of digital dbias20, rloc: 'EFUSE_RD_MAC_SPI_SYS_5_REG[10:3]', bloc: 'B20[7:3],B21[2:0]'} + DIG_DBIAS_HVT : {show: y, blk : 1, word: 5, pos: 11, len : 5, start: 171, type : 'uint:5', wr_dis : 20, rd_dis: null, alt : '', dict : '', desc: BLOCK1 digital dbias when hvt, rloc: 'EFUSE_RD_MAC_SPI_SYS_5_REG[15:11]', bloc: 'B21[7:3]'} + RESERVED_1_176 : {show: n, blk : 1, word: 5, pos: 16, len : 7, start: 176, type : 'uint:7', wr_dis : 20, rd_dis: null, alt : '', dict : '', desc: reserved, rloc: 'EFUSE_RD_MAC_SPI_SYS_5_REG[22:16]', bloc: 'B22[6:0]'} + WAFER_VERSION_MINOR_HI : {show: y, blk : 1, word: 5, pos: 23, len : 1, start: 183, type : bool, wr_dis : 20, rd_dis: null, alt : '', dict : '', desc: WAFER_VERSION_MINOR most significant bit, rloc: 'EFUSE_RD_MAC_SPI_SYS_5_REG[23]', bloc: 'B22[7]'} + WAFER_VERSION_MAJOR : {show: y, blk : 1, word: 5, pos: 24, len : 2, start: 184, type : 'uint:2', wr_dis : 20, rd_dis: null, alt : '', dict : '', desc: WAFER_VERSION_MAJOR, rloc: 'EFUSE_RD_MAC_SPI_SYS_5_REG[25:24]', bloc: 'B23[1:0]'} + ADC2_CAL_VOL_ATTEN3 : {show: y, blk : 1, word: 5, pos: 26, len : 6, start: 186, type : 'uint:6', wr_dis : 20, rd_dis: null, alt : '', dict : '', desc: ADC2 calibration voltage at atten3, rloc: 'EFUSE_RD_MAC_SPI_SYS_5_REG[31:26]', bloc: 'B23[7:2]'} + OPTIONAL_UNIQUE_ID : {show: y, blk : 2, word: 0, pos : 0, len: 128, start : 0, type: 'bytes:16', wr_dis : 21, rd_dis: null, alt : '', dict : '', desc: Optional unique 128-bit ID, rloc: EFUSE_RD_SYS_PART1_DATA0_REG, bloc: 'B0,B1,B2,B3,B4,B5,B6,B7,B8,B9,B10,B11,B12,B13,B14,B15'} + BLK_VERSION_MAJOR : {show: y, blk : 2, word: 4, pos : 0, len : 2, start: 128, type : 'uint:2', wr_dis : 21, rd_dis: null, alt : '', dict: '{0: "No calib", 1: "ADC calib V1"}', desc: BLK_VERSION_MAJOR of BLOCK2, rloc: 'EFUSE_RD_SYS_PART1_DATA4_REG[1:0]', bloc: 'B16[1:0]'} + RESERVED_2_130 : {show: n, blk : 2, word: 4, pos : 2, len : 2, start: 130, type : 'uint:2', wr_dis : 21, rd_dis: null, alt : '', dict : '', desc: reserved, rloc: 'EFUSE_RD_SYS_PART1_DATA4_REG[3:2]', bloc: 'B16[3:2]'} + TEMP_CALIB : {show: y, blk : 2, word: 4, pos : 4, len : 9, start: 132, type : 'uint:9', wr_dis : 21, rd_dis: null, alt : '', dict : '', desc: Temperature calibration data, rloc: 'EFUSE_RD_SYS_PART1_DATA4_REG[12:4]', bloc: 'B16[7:4],B17[4:0]'} + OCODE : {show: y, blk : 2, word: 4, pos: 13, len : 8, start: 141, type : 'uint:8', wr_dis : 21, rd_dis: null, alt : '', dict : '', desc: ADC OCode, rloc: 'EFUSE_RD_SYS_PART1_DATA4_REG[20:13]', bloc: 'B17[7:5],B18[4:0]'} + ADC1_INIT_CODE_ATTEN0 : {show: y, blk : 2, word: 4, pos: 21, len : 8, start: 149, type : 'uint:8', wr_dis : 21, rd_dis: null, alt : '', dict : '', desc: ADC1 init code at atten0, rloc: 'EFUSE_RD_SYS_PART1_DATA4_REG[28:21]', bloc: 'B18[7:5],B19[4:0]'} + ADC1_INIT_CODE_ATTEN1 : {show: y, blk : 2, word: 4, pos: 29, len : 6, start: 157, type : 'uint:6', wr_dis : 21, rd_dis: null, alt : '', dict : '', desc: ADC1 init code at atten1, rloc: 'EFUSE_RD_SYS_PART1_DATA4_REG[31:29]', bloc: 'B19[7:5],B20[2:0]'} + ADC1_INIT_CODE_ATTEN2 : {show: y, blk : 2, word: 5, pos : 3, len : 6, start: 163, type : 'uint:6', wr_dis : 21, rd_dis: null, alt : '', dict : '', desc: ADC1 init code at atten2, rloc: 'EFUSE_RD_SYS_PART1_DATA5_REG[8:3]', bloc: 'B20[7:3],B21[0]'} + ADC1_INIT_CODE_ATTEN3 : {show: y, blk : 2, word: 5, pos : 9, len : 6, start: 169, type : 'uint:6', wr_dis : 21, rd_dis: null, alt : '', dict : '', desc: ADC1 init code at atten3, rloc: 'EFUSE_RD_SYS_PART1_DATA5_REG[14:9]', bloc: 'B21[6:1]'} + ADC2_INIT_CODE_ATTEN0 : {show: y, blk : 2, word: 5, pos: 15, len : 8, start: 175, type : 'uint:8', wr_dis : 21, rd_dis: null, alt : '', dict : '', desc: ADC2 init code at atten0, rloc: 'EFUSE_RD_SYS_PART1_DATA5_REG[22:15]', bloc: 'B21[7],B22[6:0]'} + ADC2_INIT_CODE_ATTEN1 : {show: y, blk : 2, word: 5, pos: 23, len : 6, start: 183, type : 'uint:6', wr_dis : 21, rd_dis: null, alt : '', dict : '', desc: ADC2 init code at atten1, rloc: 'EFUSE_RD_SYS_PART1_DATA5_REG[28:23]', bloc: 'B22[7],B23[4:0]'} + ADC2_INIT_CODE_ATTEN2 : {show: y, blk : 2, word: 5, pos: 29, len : 6, start: 189, type : 'uint:6', wr_dis : 21, rd_dis: null, alt : '', dict : '', desc: ADC2 init code at atten2, rloc: 'EFUSE_RD_SYS_PART1_DATA5_REG[31:29]', bloc: 'B23[7:5],B24[2:0]'} + ADC2_INIT_CODE_ATTEN3 : {show: y, blk : 2, word: 6, pos : 3, len : 6, start: 195, type : 'uint:6', wr_dis : 21, rd_dis: null, alt : '', dict : '', desc: ADC2 init code at atten3, rloc: 'EFUSE_RD_SYS_PART1_DATA6_REG[8:3]', bloc: 'B24[7:3],B25[0]'} + ADC1_CAL_VOL_ATTEN0 : {show: y, blk : 2, word: 6, pos : 9, len : 8, start: 201, type : 'uint:8', wr_dis : 21, rd_dis: null, alt : '', dict : '', desc: ADC1 calibration voltage at atten0, rloc: 'EFUSE_RD_SYS_PART1_DATA6_REG[16:9]', bloc: 'B25[7:1],B26[0]'} + ADC1_CAL_VOL_ATTEN1 : {show: y, blk : 2, word: 6, pos: 17, len : 8, start: 209, type : 'uint:8', wr_dis : 21, rd_dis: null, alt : '', dict : '', desc: ADC1 calibration voltage at atten1, rloc: 'EFUSE_RD_SYS_PART1_DATA6_REG[24:17]', bloc: 'B26[7:1],B27[0]'} + ADC1_CAL_VOL_ATTEN2 : {show: y, blk : 2, word: 6, pos: 25, len : 8, start: 217, type : 'uint:8', wr_dis : 21, rd_dis: null, alt : '', dict : '', desc: ADC1 calibration voltage at atten2, rloc: 'EFUSE_RD_SYS_PART1_DATA6_REG[31:25]', bloc: 'B27[7:1],B28[0]'} + ADC1_CAL_VOL_ATTEN3 : {show: y, blk : 2, word: 7, pos : 1, len : 8, start: 225, type : 'uint:8', wr_dis : 21, rd_dis: null, alt : '', dict : '', desc: ADC1 calibration voltage at atten3, rloc: 'EFUSE_RD_SYS_PART1_DATA7_REG[8:1]', bloc: 'B28[7:1],B29[0]'} + ADC2_CAL_VOL_ATTEN0 : {show: y, blk : 2, word: 7, pos : 9, len : 8, start: 233, type : 'uint:8', wr_dis : 21, rd_dis: null, alt : '', dict : '', desc: ADC2 calibration voltage at atten0, rloc: 'EFUSE_RD_SYS_PART1_DATA7_REG[16:9]', bloc: 'B29[7:1],B30[0]'} + ADC2_CAL_VOL_ATTEN1 : {show: y, blk : 2, word: 7, pos: 17, len : 7, start: 241, type : 'uint:7', wr_dis : 21, rd_dis: null, alt : '', dict : '', desc: ADC2 calibration voltage at atten1, rloc: 'EFUSE_RD_SYS_PART1_DATA7_REG[23:17]', bloc: 'B30[7:1]'} + ADC2_CAL_VOL_ATTEN2 : {show: y, blk : 2, word: 7, pos: 24, len : 7, start: 248, type : 'uint:7', wr_dis : 21, rd_dis: null, alt : '', dict : '', desc: ADC2 calibration voltage at atten2, rloc: 'EFUSE_RD_SYS_PART1_DATA7_REG[30:24]', bloc: 'B31[6:0]'} + RESERVED_2_255 : {show: n, blk : 2, word: 7, pos: 31, len : 1, start: 255, type : bool, wr_dis : 21, rd_dis: null, alt : '', dict : '', desc: reserved, rloc: 'EFUSE_RD_SYS_PART1_DATA7_REG[31]', bloc: 'B31[7]'} + BLOCK_USR_DATA : {show: y, blk : 3, word: 0, pos : 0, len: 192, start : 0, type: 'bytes:24', wr_dis : 22, rd_dis: null, alt : USER_DATA, dict : '', desc: User data, rloc: EFUSE_RD_USR_DATA0_REG, bloc: 'B0,B1,B2,B3,B4,B5,B6,B7,B8,B9,B10,B11,B12,B13,B14,B15,B16,B17,B18,B19,B20,B21,B22,B23'} + RESERVED_3_192 : {show: n, blk : 3, word: 6, pos : 0, len : 8, start: 192, type : 'uint:8', wr_dis : 22, rd_dis: null, alt : '', dict : '', desc: reserved, rloc: 'EFUSE_RD_USR_DATA6_REG[7:0]', bloc: B24} + CUSTOM_MAC : {show: y, blk : 3, word: 6, pos : 8, len : 48, start: 200, type : 'bytes:6', wr_dis : 22, rd_dis: null, alt: MAC_CUSTOM USER_DATA_MAC_CUSTOM, dict : '', desc: Custom MAC, rloc: 'EFUSE_RD_USR_DATA6_REG[31:8]', bloc: 'B25,B26,B27,B28,B29,B30'} + RESERVED_3_248 : {show: n, blk : 3, word: 7, pos: 24, len : 8, start: 248, type : 'uint:8', wr_dis : 22, rd_dis: null, alt : '', dict : '', desc: reserved, rloc: 'EFUSE_RD_USR_DATA7_REG[31:24]', bloc: B31} + BLOCK_KEY0 : {show: y, blk : 4, word: 0, pos : 0, len: 256, start : 0, type: 'bytes:32', wr_dis : 23, rd_dis : 0, alt : KEY0, dict : '', desc: Key0 or user data, rloc: EFUSE_RD_KEY0_DATA0_REG, bloc: 'B0,B1,B2,B3,B4,B5,B6,B7,B8,B9,B10,B11,B12,B13,B14,B15,B16,B17,B18,B19,B20,B21,B22,B23,B24,B25,B26,B27,B28,B29,B30,B31'} + BLOCK_KEY1 : {show: y, blk : 5, word: 0, pos : 0, len: 256, start : 0, type: 'bytes:32', wr_dis : 24, rd_dis : 1, alt : KEY1, dict : '', desc: Key1 or user data, rloc: EFUSE_RD_KEY1_DATA0_REG, bloc: 'B0,B1,B2,B3,B4,B5,B6,B7,B8,B9,B10,B11,B12,B13,B14,B15,B16,B17,B18,B19,B20,B21,B22,B23,B24,B25,B26,B27,B28,B29,B30,B31'} + BLOCK_KEY2 : {show: y, blk : 6, word: 0, pos : 0, len: 256, start : 0, type: 'bytes:32', wr_dis : 25, rd_dis : 2, alt : KEY2, dict : '', desc: Key2 or user data, rloc: EFUSE_RD_KEY2_DATA0_REG, bloc: 'B0,B1,B2,B3,B4,B5,B6,B7,B8,B9,B10,B11,B12,B13,B14,B15,B16,B17,B18,B19,B20,B21,B22,B23,B24,B25,B26,B27,B28,B29,B30,B31'} + BLOCK_KEY3 : {show: y, blk : 7, word: 0, pos : 0, len: 256, start : 0, type: 'bytes:32', wr_dis : 26, rd_dis : 3, alt : KEY3, dict : '', desc: Key3 or user data, rloc: EFUSE_RD_KEY3_DATA0_REG, bloc: 'B0,B1,B2,B3,B4,B5,B6,B7,B8,B9,B10,B11,B12,B13,B14,B15,B16,B17,B18,B19,B20,B21,B22,B23,B24,B25,B26,B27,B28,B29,B30,B31'} + BLOCK_KEY4 : {show: y, blk : 8, word: 0, pos : 0, len: 256, start : 0, type: 'bytes:32', wr_dis : 27, rd_dis : 4, alt : KEY4, dict : '', desc: Key4 or user data, rloc: EFUSE_RD_KEY4_DATA0_REG, bloc: 'B0,B1,B2,B3,B4,B5,B6,B7,B8,B9,B10,B11,B12,B13,B14,B15,B16,B17,B18,B19,B20,B21,B22,B23,B24,B25,B26,B27,B28,B29,B30,B31'} + BLOCK_KEY5 : {show: y, blk : 9, word: 0, pos : 0, len: 256, start : 0, type: 'bytes:32', wr_dis : 28, rd_dis : 5, alt : KEY5, dict : '', desc: Key5 or user data, rloc: EFUSE_RD_KEY5_DATA0_REG, bloc: 'B0,B1,B2,B3,B4,B5,B6,B7,B8,B9,B10,B11,B12,B13,B14,B15,B16,B17,B18,B19,B20,B21,B22,B23,B24,B25,B26,B27,B28,B29,B30,B31'} + BLOCK_SYS_DATA2 : {show: y, blk: 10, word: 0, pos : 0, len: 256, start : 0, type: 'bytes:32', wr_dis : 29, rd_dis : 6, alt : SYS_DATA_PART2, dict : '', desc: System data part 2 (reserved), rloc: EFUSE_RD_SYS_PART2_DATA0_REG, bloc: 'B0,B1,B2,B3,B4,B5,B6,B7,B8,B9,B10,B11,B12,B13,B14,B15,B16,B17,B18,B19,B20,B21,B22,B23,B24,B25,B26,B27,B28,B29,B30,B31'} diff --git a/espsecure.py b/espsecure.py index c58eabf15..29b8e48e8 100755 --- a/espsecure.py +++ b/espsecure.py @@ -18,9 +18,12 @@ # Linux/macOS: remove current script directory to avoid importing this file # as a module; we want to import the installed espsecure module instead with contextlib.suppress(ValueError): - if sys.path[0].endswith("/bin"): - sys.path.pop(0) - sys.path.remove(os.path.dirname(sys.executable)) + executable_dir = os.path.dirname(sys.executable) + sys.path = [ + path + for path in sys.path + if not path.endswith(("/bin", "/sbin")) and path != executable_dir + ] # Linux/macOS: delete imported module entry to force Python to load # the module from scratch; this enables importing espsecure module in diff --git a/espsecure/__init__.py b/espsecure/__init__.py index 73656f5ea..3e5ef2039 100755 --- a/espsecure/__init__.py +++ b/espsecure/__init__.py @@ -200,9 +200,23 @@ def generate_signing_key(args): ) +def load_ecdsa_signing_key(keyfile): + """Load ECDSA signing key""" + try: + sk = ecdsa.SigningKey.from_pem(keyfile.read()) + except ValueError: + raise esptool.FatalError( + "Incorrect ECDSA private key specified. " + "Please check algorithm and/or format." + ) + if sk.curve not in [ecdsa.NIST192p, ecdsa.NIST256p]: + raise esptool.FatalError("Supports NIST192p and NIST256p keys only") + return sk + + def _load_ecdsa_signing_key(keyfile): """Load ECDSA signing key for Secure Boot V1 only""" - sk = ecdsa.SigningKey.from_pem(keyfile.read()) + sk = load_ecdsa_signing_key(keyfile) if sk.curve != ecdsa.NIST256p: raise esptool.FatalError( "Signing key uses incorrect curve. ESP32 Secure Boot only supports " @@ -213,7 +227,13 @@ def _load_ecdsa_signing_key(keyfile): def _load_ecdsa_verifying_key(keyfile): """Load ECDSA verifying key for Secure Boot V1 only""" - vk = ecdsa.VerifyingKey.from_pem(keyfile.read()) + try: + vk = ecdsa.VerifyingKey.from_pem(keyfile.read()) + except ValueError: + raise esptool.FatalError( + "Incorrect ECDSA public key specified. " + "Please check algorithm and/or format." + ) if vk.curve != ecdsa.NIST256p: raise esptool.FatalError( "Signing key uses incorrect curve. ESP32 Secure Boot only supports " @@ -1637,7 +1657,8 @@ def main(custom_commandline=None): p = subparsers.add_parser( "digest_private_key", help="Generate an SHA-256 digest of the private signing key. " - "This can be used as a reproducible secure bootloader or flash encryption key.", + "This can be used as a reproducible secure bootloader (only secure boot v1) " + "or flash encryption key.", ) p.add_argument( "--keyfile", @@ -1691,7 +1712,7 @@ def main(custom_commandline=None): "--aes_xts", "-x", help="Decrypt data using AES-XTS as used on " - "ESP32-S2, ESP32-C2, ESP32-C3 and ESP32-C6", + "ESP32-S2, ESP32-C2, ESP32-C3, ESP32-C6 and ESP32-P4", action="store_true", ) p.add_argument( @@ -1731,7 +1752,7 @@ def main(custom_commandline=None): "--aes_xts", "-x", help="Encrypt data using AES-XTS as used on " - "ESP32-S2, ESP32-C2, ESP32-C3 and ESP32-C6", + "ESP32-S2, ESP32-C2, ESP32-C3, ESP32-C6 and ESP32-P4", action="store_true", ) p.add_argument( @@ -1791,6 +1812,16 @@ def _main(): except esptool.FatalError as e: print("\nA fatal error occurred: %s" % e) sys.exit(2) + except ValueError as e: + try: + if [arg for arg in e.args if "Could not deserialize key data." in arg]: + print( + "Note: This error originates from the cryptography module. " + "It is likely not a problem with espsecure, " + "please make sure you are using a compatible OpenSSL backend." + ) + finally: + raise if __name__ == "__main__": diff --git a/espsecure/esp_hsm_sign/__init__.py b/espsecure/esp_hsm_sign/__init__.py index baf88241a..d255116ad 100644 --- a/espsecure/esp_hsm_sign/__init__.py +++ b/espsecure/esp_hsm_sign/__init__.py @@ -6,6 +6,7 @@ import configparser import os import sys +from getpass import getpass try: import pkcs11 @@ -31,11 +32,17 @@ def read_hsm_config(configfile): if not config.has_section(section): raise configparser.NoSectionError(section) - section_options = ["pkcs11_lib", "credentials", "slot", "label"] + section_options = ["pkcs11_lib", "slot", "label"] for option in section_options: if not config.has_option(section, option): raise configparser.NoOptionError(option, section) + # If the config file does not contain the "credentials" option, + # prompt the user for the HSM PIN + if not config.has_option(section, "credentials"): + hsm_pin = getpass("Please enter the PIN of your HSM:\n") + config.set(section, "credentials", hsm_pin) + return config[section] diff --git a/esptool.py b/esptool.py index 60e5bd339..ee3fdc90f 100755 --- a/esptool.py +++ b/esptool.py @@ -18,9 +18,12 @@ # Linux/macOS: remove current script directory to avoid importing this file # as a module; we want to import the installed esptool module instead with contextlib.suppress(ValueError): - if sys.path[0].endswith("/bin"): - sys.path.pop(0) - sys.path.remove(os.path.dirname(sys.executable)) + executable_dir = os.path.dirname(sys.executable) + sys.path = [ + path + for path in sys.path + if not path.endswith(("/bin", "/sbin")) and path != executable_dir + ] # Linux/macOS: delete imported module entry to force Python to load # the module from scratch; this enables importing esptool module in diff --git a/esptool/__init__.py b/esptool/__init__.py index 88a021813..206b6fadd 100644 --- a/esptool/__init__.py +++ b/esptool/__init__.py @@ -28,7 +28,7 @@ "write_mem", ] -__version__ = "4.6-dev" +__version__ = "4.7-dev" import argparse import inspect @@ -38,7 +38,9 @@ import time import traceback +from esptool.bin_image import intel_hex_to_bin from esptool.cmds import ( + DETECTED_FLASH_SIZES, chip_id, detect_chip, detect_flash_size, @@ -184,7 +186,9 @@ def add_spi_connection_arg(parent): parser_load_ram = subparsers.add_parser( "load_ram", help="Download an image to RAM and execute" ) - parser_load_ram.add_argument("filename", help="Firmware image") + parser_load_ram.add_argument( + "filename", help="Firmware image", action=AutoHex2BinAction + ) parser_dump_mem = subparsers.add_parser( "dump_mem", help="Dump arbitrary memory to disk" @@ -354,9 +358,11 @@ def add_spi_flash_subparsers(parent, allow_keep, auto_detect): subparsers.add_parser("run", help="Run application code in flash") parser_image_info = subparsers.add_parser( - "image_info", help="Dump headers from an application image" + "image_info", help="Dump headers from a binary file (bootloader or application)" + ) + parser_image_info.add_argument( + "filename", help="Image file to parse", action=AutoHex2BinAction ) - parser_image_info.add_argument("filename", help="Image file to parse") parser_image_info.add_argument( "--version", "-v", @@ -476,6 +482,17 @@ def add_spi_flash_subparsers(parent, allow_keep, auto_detect): "must be aligned to. Value 0xFF is used for padding, similar to erase_flash", default=None, ) + parser_elf2image.add_argument( + "--ram-only-header", + help="Order segments of the output so IRAM and DRAM are placed at the " + "beginning and force the main header segment number to RAM segments " + "quantity. This will make the other segments invisible to the ROM " + "loader. Use this argument with care because the ROM loader will load " + "only the RAM segments although the other segments being present in " + "the output.", + action="store_true", + default=None, + ) add_spi_flash_subparsers(parser_elf2image, allow_keep=False, auto_detect=False) @@ -526,7 +543,9 @@ def add_spi_flash_subparsers(parent, allow_keep, auto_detect): add_spi_connection_arg(parser_read_flash) parser_read_flash.add_argument("address", help="Start address", type=arg_auto_int) parser_read_flash.add_argument( - "size", help="Size of region to dump", type=arg_auto_int + "size", + help="Size of region to dump. Use `ALL` to read to the end of flash.", + type=arg_auto_size, ) parser_read_flash.add_argument("filename", help="Name of binary dump") parser_read_flash.add_argument( @@ -570,8 +589,9 @@ def add_spi_flash_subparsers(parent, allow_keep, auto_detect): ) parser_erase_region.add_argument( "size", - help="Size of region to erase (must be multiple of 4096)", - type=arg_auto_int, + help="Size of region to erase (must be multiple of 4096). " + "Use `ALL` to erase to the end of flash.", + type=arg_auto_size, ) parser_merge_bin = subparsers.add_parser( @@ -583,18 +603,36 @@ def add_spi_flash_subparsers(parent, allow_keep, auto_detect): "--output", "-o", help="Output filename", type=str, required=True ) parser_merge_bin.add_argument( - "--format", "-f", help="Format of the output file", choices="raw", default="raw" - ) # for future expansion + "--format", + "-f", + help="Format of the output file", + choices=["raw", "uf2", "hex"], + default="raw", + ) + uf2_group = parser_merge_bin.add_argument_group("UF2 format") + uf2_group.add_argument( + "--chunk-size", + help="Specify the used data part of the 512 byte UF2 block. " + "A common value is 256. By default the largest possible value will be used.", + default=None, + type=arg_auto_chunk_size, + ) + uf2_group.add_argument( + "--md5-disable", + help="Disable MD5 checksum in UF2 output", + action="store_true", + ) add_spi_flash_subparsers(parser_merge_bin, allow_keep=True, auto_detect=False) - parser_merge_bin.add_argument( + raw_group = parser_merge_bin.add_argument_group("RAW format") + raw_group.add_argument( "--target-offset", "-t", help="Target offset where the output file will be flashed", type=arg_auto_int, default=0, ) - parser_merge_bin.add_argument( + raw_group.add_argument( "--fill-flash-size", help="If set, the final binary file will be padded with FF " "bytes up to this flash size.", @@ -709,7 +747,16 @@ def add_spi_flash_subparsers(parent, allow_keep, auto_detect): ) args.no_stub = True else: - esp = esp.run_stub() + try: + esp = esp.run_stub() + except Exception: + # The CH9102 bridge (PID: 0x55D4) can have issues on MacOS + if sys.platform == "darwin" and esp._get_pid() == 0x55D4: + print( + "\nNote: If issues persist, " + "try installing the WCH USB-to-Serial MacOS driver." + ) + raise if args.override_vddsdio: esp.override_vddsdio(args.override_vddsdio) @@ -811,18 +858,45 @@ def flash_xmc_startup(): if hasattr(args, "flash_size"): print("Configuring flash size...") - detect_flash_size(esp, args) - if args.flash_size != "keep": # TODO: should set this even with 'keep' - esp.flash_set_parameters(flash_size_bytes(args.flash_size)) + if args.flash_size == "detect": + flash_size = detect_flash_size(esp, args) + elif args.flash_size == "keep": + flash_size = detect_flash_size(esp, args=None) + else: + flash_size = args.flash_size + + if flash_size is not None: # Secure download mode + esp.flash_set_parameters(flash_size_bytes(flash_size)) # Check if stub supports chosen flash size - if esp.IS_STUB and args.flash_size in ("32MB", "64MB", "128MB"): + if ( + esp.IS_STUB + and esp.CHIP_NAME != "ESP32-S3" + and flash_size_bytes(flash_size) > 16 * 1024 * 1024 + ): print( "WARNING: Flasher stub doesn't fully support flash size larger " "than 16MB, in case of failure use --no-stub." ) + if getattr(args, "size", "") == "all": + if esp.secure_download_mode: + raise FatalError( + "Detecting flash size is not supported in secure download mode. " + "Set an exact size value." + ) + # detect flash size + flash_id = esp.flash_id() + size_id = flash_id >> 16 + size_str = DETECTED_FLASH_SIZES.get(size_id) + if size_str is None: + raise FatalError( + "Detecting flash size failed. Set an exact size value." + ) + print(f"Detected flash size: {size_str}") + args.size = flash_size_bytes(size_str) + if esp.IS_STUB and hasattr(args, "address") and hasattr(args, "size"): - if args.address + args.size > 0x1000000: + if esp.CHIP_NAME != "ESP32-S3" and args.address + args.size > 0x1000000: print( "WARNING: Flasher stub doesn't fully support flash size larger " "than 16MB, in case of failure use --no-stub." @@ -865,6 +939,18 @@ def arg_auto_int(x): return int(x, 0) +def arg_auto_size(x): + x = x.lower() + return x if x == "all" else arg_auto_int(x) + + +def arg_auto_chunk_size(string: str) -> int: + num = int(string, 0) + if num & 3 != 0: + raise argparse.ArgumentTypeError("Chunk size should be a 4-byte aligned number") + return num + + def get_port_list(): if list_ports is None: raise FatalError( @@ -893,7 +979,7 @@ def expand_file_arguments(argv): else: new_args.append(arg) if expanded: - print("esptool %s" % (" ".join(new_args[1:]))) + print(f"esptool.py {' '.join(new_args)}") return new_args return argv @@ -976,6 +1062,20 @@ def __call__(self, parser, namespace, value, option_string=None): setattr(namespace, self.dest, value) +class AutoHex2BinAction(argparse.Action): + """Custom parser class for auto conversion of input files from hex to bin""" + + def __call__(self, parser, namespace, value, option_string=None): + try: + with open(value, "rb") as f: + # if hex file was detected replace hex file with converted temp bin + # otherwise keep the original file + value = intel_hex_to_bin(f).name + except IOError as e: + raise argparse.ArgumentError(self, e) + setattr(namespace, self.dest, value) + + class AddrFilenamePairAction(argparse.Action): """Custom parser class for the address/filename pairs passed as arguments""" @@ -1004,6 +1104,8 @@ def __call__(self, parser, namespace, values, option_string=None): "Must be pairs of an address " "and the binary filename to write there", ) + # check for intel hex files and convert them to bin + argfile = intel_hex_to_bin(argfile, address) pairs.append((address, argfile)) # Sort the addresses and check for overlapping diff --git a/esptool/bin_image.py b/esptool/bin_image.py index b001a1eae..b011b55b5 100644 --- a/esptool/bin_image.py +++ b/esptool/bin_image.py @@ -10,6 +10,10 @@ import os import re import struct +import tempfile +from typing import BinaryIO, Optional + +from intelhex import IntelHex from .loader import ESPLoader from .targets import ( @@ -20,6 +24,7 @@ ESP32H2BETA1ROM, ESP32H2BETA2ROM, ESP32H2ROM, + ESP32P4ROM, ESP32ROM, ESP32S2ROM, ESP32S3BETA2ROM, @@ -35,6 +40,23 @@ def align_file_position(f, size): f.seek(align, 1) +def intel_hex_to_bin(file: BinaryIO, start_addr: Optional[int] = None) -> BinaryIO: + """Convert IntelHex file to temp binary file with padding from start_addr + If hex file was detected return temp bin file object; input file otherwise""" + INTEL_HEX_MAGIC = b":" + magic = file.read(1) + file.seek(0) + if magic == INTEL_HEX_MAGIC: + ih = IntelHex() + ih.loadhex(file.name) + file.close() + bin = tempfile.NamedTemporaryFile(suffix=".bin", delete=False) + ih.tobinfile(bin, start=start_addr) + return bin + else: + return file + + def LoadFirmwareImage(chip, image_file): """ Load a firmware image. Can be for any supported SoC. @@ -61,6 +83,7 @@ def select_image_class(f, chip): "esp32c2": ESP32C2FirmwareImage, "esp32c6": ESP32C6FirmwareImage, "esp32h2": ESP32H2FirmwareImage, + "esp32p4": ESP32P4FirmwareImage, }[chip](f) else: # Otherwise, ESP8266 so look at magic to determine the image type magic = ord(f.read(1)) @@ -248,6 +271,20 @@ def save_segment(self, f, segment, checksum=None): if checksum is not None: return ESPLoader.checksum(segment_data, checksum) + def save_flash_segment(self, f, segment, checksum=None): + """ + Save the next segment to the image file, return next checksum value if provided + """ + if self.ROM_LOADER.CHIP_NAME == "ESP32": + # Work around a bug in ESP-IDF 2nd stage bootloader, that it didn't map the + # last MMU page, if an IROM/DROM segment was < 0x24 bytes + # over the page boundary. + segment_end_pos = f.tell() + len(segment.data) + self.SEG_HEADER_LEN + segment_len_remainder = segment_end_pos % self.IROM_ALIGN + if segment_len_remainder < 0x24: + segment.data += b"\x00" * (0x24 - segment_len_remainder) + return self.save_segment(f, segment, checksum) + def read_checksum(self, f): """Return ESPLoader checksum from end of just-read image""" # Skip the padding. The checksum is stored in the last byte so that the @@ -555,7 +592,7 @@ class ESP32FirmwareImage(BaseFirmwareImage): IROM_ALIGN = 65536 - def __init__(self, load_file=None, append_digest=True): + def __init__(self, load_file=None, append_digest=True, ram_only_header=False): super(ESP32FirmwareImage, self).__init__() self.secure_pad = None self.flash_mode = 0 @@ -573,6 +610,7 @@ def __init__(self, load_file=None, append_digest=True): self.min_rev = 0 self.min_rev_full = 0 self.max_rev_full = 0 + self.ram_only_header = ram_only_header self.append_digest = append_digest @@ -632,14 +670,24 @@ def save(self, filename): if not self.is_flash_addr(s.addr) ] - # Patch to support 761 union bus memmap // TODO: ESPTOOL-512 + # Patch to support ESP32-C6 union bus memmap # move ".flash.appdesc" segment to the top of the flash segment for segment in flash_segments: - if segment.name == ".flash.appdesc": + if isinstance(segment, ELFSection) and segment.name == ".flash.appdesc": flash_segments.remove(segment) flash_segments.insert(0, segment) break + # For the bootloader image + # move ".dram0.bootdesc" segment to the top of the ram segment + # So bootdesc will be at the very top of the binary at 0x20 offset + # (in the first segment). + for segment in ram_segments: + if segment.name == ".dram0.bootdesc": + ram_segments.remove(segment) + ram_segments.insert(0, segment) + break + # check for multiple ELF sections that are mapped in the same # flash mapping region. This is usually a sign of a broken linker script, # but if you have a legitimate use case then let us know @@ -675,33 +723,61 @@ def get_alignment_data_needed(segment): pad_len += self.IROM_ALIGN return pad_len - # try to fit each flash segment on a 64kB aligned boundary - # by padding with parts of the non-flash segments... - while len(flash_segments) > 0: - segment = flash_segments[0] - pad_len = get_alignment_data_needed(segment) - if pad_len > 0: # need to pad - if len(ram_segments) > 0 and pad_len > self.SEG_HEADER_LEN: - pad_segment = ram_segments[0].split_image(pad_len) - if len(ram_segments[0].data) == 0: - ram_segments.pop(0) - else: - pad_segment = ImageSegment(0, b"\x00" * pad_len, f.tell()) - checksum = self.save_segment(f, pad_segment, checksum) + if self.ram_only_header: + # write RAM segments first in order to get only RAM segments quantity + # and checksum (ROM bootloader will only care for RAM segments and its + # correct checksums) + for segment in ram_segments: + checksum = self.save_segment(f, segment, checksum) total_segments += 1 - else: + self.append_checksum(f, checksum) + + # reversing to match the same section order from linker script + flash_segments.reverse() + for segment in flash_segments: + pad_len = get_alignment_data_needed(segment) + while pad_len > 0: + pad_segment = ImageSegment(0, b"\x00" * pad_len, f.tell()) + self.save_segment(f, pad_segment) + total_segments += 1 + pad_len = get_alignment_data_needed(segment) # write the flash segment assert ( f.tell() + 8 ) % self.IROM_ALIGN == segment.addr % self.IROM_ALIGN - checksum = self.save_flash_segment(f, segment, checksum) - flash_segments.pop(0) + # save the flash segment but not saving its checksum neither + # saving the number of flash segments, since ROM bootloader + # should "not see" them + self.save_flash_segment(f, segment) + total_segments += 1 + else: # not self.ram_only_header + # try to fit each flash segment on a 64kB aligned boundary + # by padding with parts of the non-flash segments... + while len(flash_segments) > 0: + segment = flash_segments[0] + pad_len = get_alignment_data_needed(segment) + if pad_len > 0: # need to pad + if len(ram_segments) > 0 and pad_len > self.SEG_HEADER_LEN: + pad_segment = ram_segments[0].split_image(pad_len) + if len(ram_segments[0].data) == 0: + ram_segments.pop(0) + else: + pad_segment = ImageSegment(0, b"\x00" * pad_len, f.tell()) + checksum = self.save_segment(f, pad_segment, checksum) + total_segments += 1 + else: + # write the flash segment + assert ( + f.tell() + 8 + ) % self.IROM_ALIGN == segment.addr % self.IROM_ALIGN + checksum = self.save_flash_segment(f, segment, checksum) + flash_segments.pop(0) + total_segments += 1 + + # flash segments all written, so write any remaining RAM segments + for segment in ram_segments: + checksum = self.save_segment(f, segment, checksum) total_segments += 1 - - # flash segments all written, so write any remaining RAM segments - for segment in ram_segments: - checksum = self.save_segment(f, segment, checksum) - total_segments += 1 if self.secure_pad: # pad the image so that after signing it will end on a a 64KB boundary. @@ -733,8 +809,9 @@ def get_alignment_data_needed(segment): checksum = self.save_segment(f, pad_segment, checksum) total_segments += 1 - # done writing segments - self.append_checksum(f, checksum) + if not self.ram_only_header: + # done writing segments + self.append_checksum(f, checksum) image_length = f.tell() if self.secure_pad: @@ -743,7 +820,12 @@ def get_alignment_data_needed(segment): # kinda hacky: go back to the initial header and write the new segment count # that includes padding segments. This header is not checksummed f.seek(1) - f.write(bytes([total_segments])) + if self.ram_only_header: + # Update the header with the RAM segments quantity as it should be + # visible by the ROM bootloader + f.write(bytes([len(ram_segments)])) + else: + f.write(bytes([total_segments])) if self.append_digest: # calculate the SHA256 of the whole file and append it @@ -761,19 +843,6 @@ def get_alignment_data_needed(segment): with open(filename, "wb") as real_file: real_file.write(f.getvalue()) - def save_flash_segment(self, f, segment, checksum=None): - """ - Save the next segment to the image file, return next checksum value if provided - """ - segment_end_pos = f.tell() + len(segment.data) + self.SEG_HEADER_LEN - segment_len_remainder = segment_end_pos % self.IROM_ALIGN - if segment_len_remainder < 0x24: - # Work around a bug in ESP-IDF 2nd stage bootloader, that it didn't map the - # last MMU page, if an IROM/DROM segment was < 0x24 bytes - # over the page boundary. - segment.data += b"\x00" * (0x24 - segment_len_remainder) - return self.save_segment(f, segment, checksum) - def load_extended_header(self, load_file): def split_byte(n): return (n & 0x0F, (n >> 4) & 0x0F) @@ -803,13 +872,6 @@ def split_byte(n): self.min_rev_full = fields[6] self.max_rev_full = fields[7] - # reserved fields in the middle should all be zero - if any(f for f in fields[8:-1] if f != 0): - print( - "Warning: some reserved header fields have non-zero values. " - "This image may be from a newer esptool.py?" - ) - append_digest = fields[-1] # last byte is append_digest if append_digest in [0, 1]: self.append_digest = append_digest == 1 @@ -1052,6 +1114,15 @@ def set_mmu_page_size(self, size): ESP32C6ROM.BOOTLOADER_IMAGE = ESP32C6FirmwareImage +class ESP32P4FirmwareImage(ESP32FirmwareImage): + """ESP32P4 Firmware Image almost exactly the same as ESP32FirmwareImage""" + + ROM_LOADER = ESP32P4ROM + + +ESP32P4ROM.BOOTLOADER_IMAGE = ESP32P4FirmwareImage + + class ESP32H2FirmwareImage(ESP32C6FirmwareImage): """ESP32H2 Firmware Image almost exactly the same as ESP32FirmwareImage""" diff --git a/esptool/cmds.py b/esptool/cmds.py index 26416eae1..3a6f914e0 100644 --- a/esptool/cmds.py +++ b/esptool/cmds.py @@ -11,6 +11,8 @@ import time import zlib +from intelhex import IntelHex + from .bin_image import ELFFile, ImageSegment, LoadFirmwareImage from .bin_image import ( ESP8266ROMFirmwareImage, @@ -25,6 +27,7 @@ timeout_per_mb, ) from .targets import CHIP_DEFS, CHIP_LIST, ROM_LIST +from .uf2_writer import UF2Writer from .util import ( FatalError, NotImplementedInROMError, @@ -34,6 +37,7 @@ from .util import ( div_roundup, flash_size_bytes, + get_file_size, hexify, pad_to, print_overwrite, @@ -95,7 +99,7 @@ def detect_chip( print("Detecting chip type...", end="") chip_id = detect_port.get_chip_id() for cls in [ - n for n in ROM_LIST if n.CHIP_NAME not in ("ESP8266", "ESP32", "ESP32S2") + n for n in ROM_LIST if n.CHIP_NAME not in ("ESP8266", "ESP32", "ESP32-S2") ]: # cmd not supported on ESP8266 and ESP32 + ESP32-S2 doesn't return chip_id if chip_id == cls.IMAGE_CHIP_ID: @@ -107,6 +111,9 @@ def detect_chip( except UnsupportedCommandError: inst.secure_download_mode = True inst._post_connect() + break + else: + err_msg = f"Unexpected chip ID value {chip_id}." except (UnsupportedCommandError, struct.error, FatalError) as e: # UnsupportedCommmanddError: ESP8266/ESP32 ROM # struct.error: ESP32-S2 @@ -130,6 +137,9 @@ def detect_chip( inst = cls(detect_port._port, baud, trace_enabled=trace_enabled) inst._post_connect() inst.check_chip_id() + break + else: + err_msg = f"Unexpected chip magic value {chip_magic_value:#010x}." except UnsupportedCommandError: raise FatalError( "Unsupported Command Error received. " @@ -145,8 +155,8 @@ def detect_chip( print("") # end line return inst raise FatalError( - "Unexpected CHIP magic value 0x%08x. Failed to autodetect chip type." - % (chip_magic_value) + f"{err_msg} Failed to autodetect chip type." + "\nProbably it is unsupported by this version of esptool." ) @@ -202,24 +212,30 @@ def dump_mem(esp, args): print("Done!") -def detect_flash_size(esp, args): - if args.flash_size == "detect": - if esp.secure_download_mode: +def detect_flash_size(esp, args=None): + # TODO: Remove the dependency on args in the next major release (v5.0) + if esp.secure_download_mode: + if args is not None and args.flash_size == "detect": raise FatalError( "Detecting flash size is not supported in secure download mode. " "Need to manually specify flash size." ) - flash_id = esp.flash_id() - size_id = flash_id >> 16 - args.flash_size = DETECTED_FLASH_SIZES.get(size_id) - if args.flash_size is None: + else: + return None + flash_id = esp.flash_id() + size_id = flash_id >> 16 + flash_size = DETECTED_FLASH_SIZES.get(size_id) + if args is not None and args.flash_size == "detect": + if flash_size is None: + flash_size = "4MB" print( - "Warning: Could not auto-detect Flash size (FlashID=0x%x, SizeID=0x%x)," - " defaulting to 4MB" % (flash_id, size_id) + "Warning: Could not auto-detect Flash size " + f"(FlashID={flash_id:#x}, SizeID={size_id:#x}), defaulting to 4MB" ) - args.flash_size = "4MB" else: - print("Auto-detected Flash size:", args.flash_size) + print("Auto-detected Flash size:", flash_size) + args.flash_size = flash_size + return flash_size def _update_image_flash_params(esp, address, args, image): @@ -450,8 +466,10 @@ def write_flash(esp, args): ) # verify file sizes fit in flash - if args.flash_size != "keep": # TODO: check this even with 'keep' - flash_end = flash_size_bytes(args.flash_size) + flash_end = flash_size_bytes( + detect_flash_size(esp) if args.flash_size == "keep" else args.flash_size + ) + if flash_end is not None: # Not in secure download mode for address, argfile in args.addr_filename: argfile.seek(0, os.SEEK_END) if address + argfile.tell() > flash_end: @@ -723,7 +741,10 @@ def get_key_from_value(dict, val): title = "{} extended image header".format(args.chip.upper()) print(title) print("=" * len(title)) - print("WP pin: {:#02x}".format(image.wp_pin)) + print( + f"WP pin: {image.wp_pin:#02x}", + *["(disabled)"] if image.wp_pin == image.WP_PIN_DISABLED else [], + ) print( "Flash pins drive settings: " "clk_drv: {:#02x}, q_drv: {:#02x}, d_drv: {:#02x}, " @@ -736,7 +757,15 @@ def get_key_from_value(dict, val): image.wp_drv, ) ) - print("Chip ID: {}".format(image.chip_id)) + try: + chip = next( + chip + for chip in CHIP_DEFS.values() + if getattr(chip, "IMAGE_CHIP_ID", None) == image.chip_id + ) + print(f"Chip ID: {image.chip_id} ({chip.CHIP_NAME})") + except StopIteration: + print(f"Chip ID: {image.chip_id} (Unknown ID)") print( "Minimal chip revision: " f"v{image.min_rev_full // 100}.{image.min_rev_full % 100}, " @@ -763,11 +792,16 @@ def get_key_from_value(dict, val): ) format_str = "{:7} {:#07x} {:#010x} {:#010x} {}" app_desc = None + bootloader_desc = None for idx, seg in enumerate(image.segments, start=1): segs = seg.get_memory_type(image) seg_name = ", ".join(segs) if "DROM" in segs: # The DROM segment starts with the esp_app_desc_t struct app_desc = seg.data[:256] + elif "DRAM" in segs: + # The DRAM segment starts with the esp_bootloader_desc_t struct + if len(seg.data) >= 80: + bootloader_desc = seg.data[:80] print( format_str.format(idx, len(seg.data), seg.addr, seg.file_offs, seg_name) ) @@ -825,6 +859,27 @@ def get_key_from_value(dict, val): print(f'ESP-IDF: {idf_ver.decode("utf-8")}') print(f"Secure version: {secure_version}") + elif bootloader_desc: + BOOTLOADER_DESC_STRUCT_FMT = " 0: + print("Secure Boot Key Revocation Status:\n") + for i in revoked_keys: + print(f"\tSecure Boot Key{i} is Revoked\n") + + else: + print("Secure Boot: Disabled") + + flash_crypt_cnt = bin(si["flash_crypt_cnt"]) + if (flash_crypt_cnt.count("1") % 2) != 0: + print("Flash Encryption: Enabled") + else: + print("Flash Encryption: Disabled") + + CRYPT_CNT_STRING = "SPI Boot Crypt Count (SPI_BOOT_CRYPT_CNT)" + if esp.CHIP_NAME == "esp32": + CRYPT_CNT_STRING = "Flash Crypt Count (FLASH_CRYPT_CNT)" + + print(f"{CRYPT_CNT_STRING}: {si['flash_crypt_cnt']:#x}") + + if get_security_flag_status("DIS_DOWNLOAD_DCACHE", flags): + print("Dcache in UART download mode: Disabled") + + if get_security_flag_status("DIS_DOWNLOAD_ICACHE", flags): + print("Icache in UART download mode: Disabled") + + hard_dis_jtag = get_security_flag_status("HARD_DIS_JTAG", flags) + soft_dis_jtag = get_security_flag_status("SOFT_DIS_JTAG", flags) + if hard_dis_jtag: + print("JTAG: Permenantly Disabled") + elif soft_dis_jtag: + print("JTAG: Software Access Disabled") + if get_security_flag_status("DIS_USB", flags): + print("USB Access: Disabled") def merge_bin(args): @@ -1145,9 +1287,9 @@ def merge_bin(args): msg = ( "Please specify the chip argument" if args.chip == "auto" - else "Invalid chip choice: '{}'".format(args.chip) + else f"Invalid chip choice: '{args.chip}'" ) - msg = msg + " (choose from {})".format(", ".join(CHIP_LIST)) + msg = f"{msg} (choose from {', '.join(CHIP_LIST)})" raise FatalError(msg) # sort the files by offset. @@ -1158,31 +1300,57 @@ def merge_bin(args): first_addr = input_files[0][0] if first_addr < args.target_offset: raise FatalError( - "Output file target offset is 0x%x. Input file offset 0x%x is before this." - % (args.target_offset, first_addr) + f"Output file target offset is {args.target_offset:#x}. " + f"Input file offset {first_addr:#x} is before this." ) - if args.format != "raw": - raise FatalError( - "This version of esptool only supports the 'raw' output format" + if args.format == "uf2": + with UF2Writer( + chip_class.UF2_FAMILY_ID, + args.output, + args.chunk_size, + md5_enabled=not args.md5_disable, + ) as writer: + for addr, argfile in input_files: + print(f"Adding {argfile.name} at {addr:#x}") + image = argfile.read() + image = _update_image_flash_params(chip_class, addr, args, image) + writer.add_file(addr, image) + print( + f"Wrote {os.path.getsize(args.output):#x} bytes to file {args.output}, " + f"ready to be flashed with any ESP USB Bridge" ) - with open(args.output, "wb") as of: + elif args.format == "raw": + with open(args.output, "wb") as of: - def pad_to(flash_offs): - # account for output file offset if there is any - of.write(b"\xFF" * (flash_offs - args.target_offset - of.tell())) + def pad_to(flash_offs): + # account for output file offset if there is any + of.write(b"\xFF" * (flash_offs - args.target_offset - of.tell())) + for addr, argfile in input_files: + pad_to(addr) + image = argfile.read() + image = _update_image_flash_params(chip_class, addr, args, image) + of.write(image) + if args.fill_flash_size: + pad_to(flash_size_bytes(args.fill_flash_size)) + print( + f"Wrote {of.tell():#x} bytes to file {args.output}, " + f"ready to flash to offset {args.target_offset:#x}" + ) + elif args.format == "hex": + out = IntelHex() for addr, argfile in input_files: - pad_to(addr) + ihex = IntelHex() image = argfile.read() image = _update_image_flash_params(chip_class, addr, args, image) - of.write(image) - if args.fill_flash_size: - pad_to(flash_size_bytes(args.fill_flash_size)) + ihex.frombytes(image, addr) + out.merge(ihex) + out.write_hex_file(args.output) print( - "Wrote 0x%x bytes to file %s, ready to flash to offset 0x%x" - % (of.tell(), args.output, args.target_offset) + f"Wrote {os.path.getsize(args.output):#x} bytes to file {args.output}, " + f"ready to flash to offset {args.target_offset:#x}" ) diff --git a/esptool/loader.py b/esptool/loader.py index eb6402369..bd1fcbab2 100644 --- a/esptool/loader.py +++ b/esptool/loader.py @@ -97,13 +97,13 @@ # Number of times to try writing a data block WRITE_BLOCK_ATTEMPTS = cfg.getint("write_block_attempts", 3) -STUBS_DIR = os.path.join(os.path.dirname(__file__), "./targets/stub_flasher/") +STUBS_DIR = os.path.join(os.path.dirname(__file__), "targets", "stub_flasher") def get_stub_json_path(chip_name): chip_name = strip_chip_name(chip_name) chip_name = chip_name.replace("esp", "") - return STUBS_DIR + "stub_flasher_" + chip_name + ".json" + return os.path.join(STUBS_DIR, f"stub_flasher_{chip_name}.json") def timeout_per_mb(seconds_per_mb, size_bytes): @@ -184,8 +184,6 @@ class ESPLoader(object): CHIP_NAME = "Espressif device" IS_STUB = False - FPGA_SLOW_BOOT = False - DEFAULT_PORT = "/dev/ttyUSB0" USES_RFC2217 = False @@ -295,13 +293,45 @@ def __init__(self, port=DEFAULT_PORT, baud=ESP_ROM_BAUD, trace_enabled=False): "flash_id": None, "chip_id": None, "uart_no": None, + "usb_pid": None, } if isinstance(port, str): try: self._port = serial.serial_for_url(port) - except serial.serialutil.SerialException: - raise FatalError(f"Could not open {port}, the port doesn't exist") + except serial.serialutil.SerialException as e: + port_issues = [ + [ # does not exist error + re.compile(r"Errno 2|FileNotFoundError", re.IGNORECASE), + "Check if the port is correct and ESP connected", + ], + [ # busy port error + re.compile(r"Access is denied", re.IGNORECASE), + "Check if the port is not used by another task", + ], + ] + if sys.platform.startswith("linux"): + port_issues.append( + [ # permission denied error + re.compile(r"Permission denied", re.IGNORECASE), + ( + "Try to add user into dialout group: " + "sudo usermod -a -G dialout $USER" + ), + ], + ) + + hint_msg = "" + for port_issue in port_issues: + if port_issue[0].search(str(e)): + hint_msg = f"\nHint: {port_issue[1]}\n" + break + + raise FatalError( + f"Could not open {port}, the port is busy or doesn't exist." + f"\n({e})\n" + f"{hint_msg}" + ) else: self._port = port self._slip_reader = slip_reader(self._port, self.trace) @@ -475,6 +505,9 @@ def sync(self): self.sync_stub_detected &= val == 0 def _get_pid(self): + if self.cache["usb_pid"] is not None: + return self.cache["usb_pid"] + if list_ports is None: print( "\nListing all serial ports is currently not available. " @@ -494,16 +527,19 @@ def _get_pid(self): if active_port.startswith("/dev/") and os.path.islink(active_port): active_port = os.path.realpath(active_port) + active_ports = [active_port] + # The "cu" (call-up) device has to be used for outgoing communication on MacOS if sys.platform == "darwin" and "tty" in active_port: - active_port = [active_port, active_port.replace("tty", "cu")] + active_ports.append(active_port.replace("tty", "cu")) ports = list_ports.comports() for p in ports: - if p.device in active_port: + if p.device in active_ports: + self.cache["usb_pid"] = p.pid return p.pid print( - "\nFailed to get PID of a device on {}, " - "using standard reset sequence.".format(active_port) + f"\nFailed to get PID of a device on {active_port}, " + "using standard reset sequence." ) def _connect_attempt(self, reset_strategy, mode="default_reset"): @@ -590,7 +626,7 @@ def _construct_reset_strategy_sequence(self, mode): # This FPGA delay is for Espressif internal use if ( - self.FPGA_SLOW_BOOT + self.CHIP_NAME == "ESP32" and os.environ.get("ESPTOOL_ENV_FPGA", "").strip() == "1" ): delay = extra_delay = 7 diff --git a/esptool/targets/__init__.py b/esptool/targets/__init__.py index 9d76ca543..dd1ba485d 100644 --- a/esptool/targets/__init__.py +++ b/esptool/targets/__init__.py @@ -6,6 +6,7 @@ from .esp32h2 import ESP32H2ROM from .esp32h2beta1 import ESP32H2BETA1ROM from .esp32h2beta2 import ESP32H2BETA2ROM +from .esp32p4 import ESP32P4ROM from .esp32s2 import ESP32S2ROM from .esp32s3 import ESP32S3ROM from .esp32s3beta2 import ESP32S3BETA2ROM @@ -25,6 +26,7 @@ "esp32c2": ESP32C2ROM, "esp32c6": ESP32C6ROM, "esp32h2": ESP32H2ROM, + "esp32p4": ESP32P4ROM, } CHIP_LIST = list(CHIP_DEFS.keys()) diff --git a/esptool/targets/esp32.py b/esptool/targets/esp32.py index b805ed453..e9c66da52 100644 --- a/esptool/targets/esp32.py +++ b/esptool/targets/esp32.py @@ -17,8 +17,6 @@ class ESP32ROM(ESPLoader): IMAGE_CHIP_ID = 0 IS_STUB = False - FPGA_SLOW_BOOT = True - CHIP_DETECT_MAGIC_VALUE = [0x00F01D83] IROM_MAP_START = 0x400D0000 @@ -105,6 +103,8 @@ class ESP32ROM(ESPLoader): FLASH_ENCRYPTED_WRITE_ALIGN = 32 + UF2_FAMILY_ID = 0x1C5F21B0 + """ Try to read the BLOCK1 (encryption key) and check if it is valid """ def is_flash_encryption_key_valid(self): @@ -283,8 +283,10 @@ def read_efuse(self, n): def chip_id(self): raise NotSupportedError(self, "chip_id") - def read_mac(self): + def read_mac(self, mac_type="BASE_MAC"): """Read MAC from EFUSE region""" + if mac_type != "BASE_MAC": + return None words = [self.read_efuse(2), self.read_efuse(1)] bitstring = struct.pack(">II", *words) bitstring = bitstring[2:8] # trim the 2 byte CRC @@ -359,6 +361,7 @@ def get_rom_cal_crystal_freq(self): return rom_calculated_freq def change_baud(self, baud): + assert self.CHIP_NAME == "ESP32", "This workaround should only apply to ESP32" # It's a workaround to avoid esp32 CK_8M frequency drift. rom_calculated_freq = self.get_rom_cal_crystal_freq() valid_freq = 40000000 if rom_calculated_freq > 33000000 else 26000000 diff --git a/esptool/targets/esp32c2.py b/esptool/targets/esp32c2.py index f70d4a826..ff8341869 100644 --- a/esptool/targets/esp32c2.py +++ b/esptool/targets/esp32c2.py @@ -61,6 +61,8 @@ class ESP32C2ROM(ESP32C3ROM): [0x4037C000, 0x403C0000, "IRAM"], ] + UF2_FAMILY_ID = 0x2B88D29C + def get_pkg_version(self): num_word = 1 return (self.read_reg(self.EFUSE_BLOCK2_ADDR + (4 * num_word)) >> 22) & 0x07 @@ -110,7 +112,7 @@ def change_baud(self, baud): def _post_connect(self): # ESP32C2 ECO0 is no longer supported by the flasher stub - if self.get_chip_revision() == 0: + if not self.secure_download_mode and self.get_chip_revision() == 0: self.stub_is_disabled = True self.IS_STUB = False diff --git a/esptool/targets/esp32c3.py b/esptool/targets/esp32c3.py index 3db0dea74..47191b0c2 100644 --- a/esptool/targets/esp32c3.py +++ b/esptool/targets/esp32c3.py @@ -14,8 +14,6 @@ class ESP32C3ROM(ESP32ROM): CHIP_NAME = "ESP32-C3" IMAGE_CHIP_ID = 5 - FPGA_SLOW_BOOT = False - IROM_MAP_START = 0x42000000 IROM_MAP_END = 0x42800000 DROM_MAP_START = 0x3C000000 @@ -31,8 +29,8 @@ class ESP32C3ROM(ESP32ROM): BOOTLOADER_FLASH_OFFSET = 0x0 - # Magic value for ESP32C3 eco 1+2 and ESP32C3 eco3 respectivly - CHIP_DETECT_MAGIC_VALUE = [0x6921506F, 0x1B31506F] + # Magic values for ESP32-C3 eco 1+2, eco 3, eco 6, and eco 7 respectively + CHIP_DETECT_MAGIC_VALUE = [0x6921506F, 0x1B31506F, 0x4881606F, 0x4361606F] UART_DATE_REG_ADDR = 0x60000000 + 0x7C @@ -75,10 +73,15 @@ class ESP32C3ROM(ESP32ROM): UARTDEV_BUF_NO = 0x3FCDF07C # Variable in ROM .bss which indicates the port in use UARTDEV_BUF_NO_USB_JTAG_SERIAL = 3 # The above var when USB-JTAG/Serial is used - RTC_CNTL_WDT_WKEY = 0x50D83AA1 RTCCNTL_BASE_REG = 0x60008000 + RTC_CNTL_SWD_CONF_REG = RTCCNTL_BASE_REG + 0x00AC + RTC_CNTL_SWD_AUTO_FEED_EN = 1 << 31 + RTC_CNTL_SWD_WPROTECT_REG = RTCCNTL_BASE_REG + 0x00B0 + RTC_CNTL_SWD_WKEY = 0x8F1D312A + RTC_CNTL_WDTCONFIG0_REG = RTCCNTL_BASE_REG + 0x0090 RTC_CNTL_WDTWPROTECT_REG = RTCCNTL_BASE_REG + 0x00A8 + RTC_CNTL_WDT_WKEY = 0x50D83AA1 MEMORY_MAP = [ [0x00000000, 0x00010000, "PADDING"], @@ -94,6 +97,8 @@ class ESP32C3ROM(ESP32ROM): [0x600FE000, 0x60100000, "MEM_INTERNAL2"], ] + UF2_FAMILY_ID = 0xD42BA06C + def get_pkg_version(self): num_word = 3 return (self.read_reg(self.EFUSE_BLOCK1_ADDR + (4 * num_word)) >> 21) & 0x07 @@ -109,16 +114,39 @@ def get_major_chip_version(self): num_word = 5 return (self.read_reg(self.EFUSE_BLOCK1_ADDR + (4 * num_word)) >> 24) & 0x03 + def get_flash_cap(self): + num_word = 3 + return (self.read_reg(self.EFUSE_BLOCK1_ADDR + (4 * num_word)) >> 27) & 0x07 + + def get_flash_vendor(self): + num_word = 4 + vendor_id = (self.read_reg(self.EFUSE_BLOCK1_ADDR + (4 * num_word)) >> 0) & 0x07 + return {1: "XMC", 2: "GD", 3: "FM", 4: "TT", 5: "ZBIT"}.get(vendor_id, "") + def get_chip_description(self): chip_name = { - 0: "ESP32-C3", + 0: "ESP32-C3 (QFN32)", + 1: "ESP8685 (QFN28)", + 2: "ESP32-C3 AZ (QFN32)", + 3: "ESP8686 (QFN24)", }.get(self.get_pkg_version(), "unknown ESP32-C3") major_rev = self.get_major_chip_version() minor_rev = self.get_minor_chip_version() return f"{chip_name} (revision v{major_rev}.{minor_rev})" def get_chip_features(self): - return ["WiFi", "BLE"] + features = ["WiFi", "BLE"] + + flash = { + 0: None, + 1: "Embedded Flash 4MB", + 2: "Embedded Flash 2MB", + 3: "Embedded Flash 1MB", + 4: "Embedded Flash 8MB", + }.get(self.get_flash_cap(), "Unknown Embedded Flash") + if flash is not None: + features += [flash + f" ({self.get_flash_vendor()})"] + return features def get_crystal_freq(self): # ESP32C3 XTAL is fixed to 40MHz @@ -129,7 +157,10 @@ def override_vddsdio(self, new_voltage): "VDD_SDIO overrides are not supported for ESP32-C3" ) - def read_mac(self): + def read_mac(self, mac_type="BASE_MAC"): + """Read MAC from EFUSE region""" + if mac_type != "BASE_MAC": + return None mac0 = self.read_reg(self.MAC_EFUSE_REG) mac1 = self.read_reg(self.MAC_EFUSE_REG + 4) # only bottom 16 bits are MAC bitstring = struct.pack(">II", mac1, mac0)[2:] @@ -175,17 +206,27 @@ def uses_usb_jtag_serial(self): return False # Can't detect USB-JTAG/Serial in secure download mode return self.get_uart_no() == self.UARTDEV_BUF_NO_USB_JTAG_SERIAL - def disable_rtc_watchdog(self): - # When USB-JTAG/Serial is used, the RTC watchdog is not reset - # and can then reset the board during flashing. Disable it. + def disable_watchdogs(self): + # When USB-JTAG/Serial is used, the RTC WDT and SWD watchdog are not reset + # and can then reset the board during flashing. Disable or autofeed them. if self.uses_usb_jtag_serial(): + # Disable RTC WDT self.write_reg(self.RTC_CNTL_WDTWPROTECT_REG, self.RTC_CNTL_WDT_WKEY) self.write_reg(self.RTC_CNTL_WDTCONFIG0_REG, 0) self.write_reg(self.RTC_CNTL_WDTWPROTECT_REG, 0) + # Automatically feed SWD + self.write_reg(self.RTC_CNTL_SWD_WPROTECT_REG, self.RTC_CNTL_SWD_WKEY) + self.write_reg( + self.RTC_CNTL_SWD_CONF_REG, + self.read_reg(self.RTC_CNTL_SWD_CONF_REG) + | self.RTC_CNTL_SWD_AUTO_FEED_EN, + ) + self.write_reg(self.RTC_CNTL_SWD_WPROTECT_REG, 0) + def _post_connect(self): if not self.sync_stub_detected: # Don't run if stub is reused - self.disable_rtc_watchdog() + self.disable_watchdogs() class ESP32C3StubLoader(ESP32C3ROM): diff --git a/esptool/targets/esp32c6.py b/esptool/targets/esp32c6.py index 0c4575ebf..c18bf9d1f 100644 --- a/esptool/targets/esp32c6.py +++ b/esptool/targets/esp32c6.py @@ -13,8 +13,6 @@ class ESP32C6ROM(ESP32C3ROM): CHIP_NAME = "ESP32-C6" IMAGE_CHIP_ID = 13 - FPGA_SLOW_BOOT = False - IROM_MAP_START = 0x42000000 IROM_MAP_END = 0x42800000 DROM_MAP_START = 0x42800000 @@ -76,6 +74,11 @@ class ESP32C6ROM(ESP32C3ROM): RTC_CNTL_WDTCONFIG0_REG = DR_REG_LP_WDT_BASE + 0x0 # LP_WDT_RWDT_CONFIG0_REG RTC_CNTL_WDTWPROTECT_REG = DR_REG_LP_WDT_BASE + 0x0018 # LP_WDT_RWDT_WPROTECT_REG + RTC_CNTL_SWD_CONF_REG = DR_REG_LP_WDT_BASE + 0x001C # LP_WDT_SWD_CONFIG_REG + RTC_CNTL_SWD_AUTO_FEED_EN = 1 << 18 + RTC_CNTL_SWD_WPROTECT_REG = DR_REG_LP_WDT_BASE + 0x0020 # LP_WDT_SWD_WPROTECT_REG + RTC_CNTL_SWD_WKEY = 0x50D83AA1 # LP_WDT_SWD_WKEY, same as WDT key in this case + FLASH_FREQUENCY = { "80m": 0x0, # workaround for wrong mspi HS div value in ROM "40m": 0x0, @@ -96,24 +99,24 @@ class ESP32C6ROM(ESP32C3ROM): [0x600FE000, 0x60100000, "MEM_INTERNAL2"], ] + UF2_FAMILY_ID = 0x540DDF62 + def get_pkg_version(self): num_word = 3 - return (self.read_reg(self.EFUSE_BLOCK1_ADDR + (4 * num_word)) >> 21) & 0x07 + return (self.read_reg(self.EFUSE_BLOCK1_ADDR + (4 * num_word)) >> 24) & 0x07 def get_minor_chip_version(self): - hi_num_word = 5 - hi = (self.read_reg(self.EFUSE_BLOCK1_ADDR + (4 * hi_num_word)) >> 23) & 0x01 - low_num_word = 3 - low = (self.read_reg(self.EFUSE_BLOCK1_ADDR + (4 * low_num_word)) >> 18) & 0x07 - return (hi << 3) + low + num_word = 3 + return (self.read_reg(self.EFUSE_BLOCK1_ADDR + (4 * num_word)) >> 18) & 0x0F def get_major_chip_version(self): - num_word = 5 - return (self.read_reg(self.EFUSE_BLOCK1_ADDR + (4 * num_word)) >> 24) & 0x03 + num_word = 3 + return (self.read_reg(self.EFUSE_BLOCK1_ADDR + (4 * num_word)) >> 22) & 0x03 def get_chip_description(self): chip_name = { - 0: "ESP32-C6", + 0: "ESP32-C6 (QFN40)", + 1: "ESP32-C6FH4 (QFN32)", }.get(self.get_pkg_version(), "unknown ESP32-C6") major_rev = self.get_major_chip_version() minor_rev = self.get_minor_chip_version() @@ -131,11 +134,22 @@ def override_vddsdio(self, new_voltage): "VDD_SDIO overrides are not supported for ESP32-C6" ) - def read_mac(self): + def read_mac(self, mac_type="BASE_MAC"): + """Read MAC from EFUSE region""" mac0 = self.read_reg(self.MAC_EFUSE_REG) mac1 = self.read_reg(self.MAC_EFUSE_REG + 4) # only bottom 16 bits are MAC - bitstring = struct.pack(">II", mac1, mac0)[2:] - return tuple(bitstring) + base_mac = struct.pack(">II", mac1, mac0)[2:] + ext_mac = struct.pack(">H", (mac1 >> 16) & 0xFFFF) + eui64 = base_mac[0:3] + ext_mac + base_mac[3:6] + # BASE MAC: 60:55:f9:f7:2c:a2 + # EUI64 MAC: 60:55:f9:ff:fe:f7:2c:a2 + # EXT_MAC: ff:fe + macs = { + "BASE_MAC": tuple(base_mac), + "EUI64": tuple(eui64), + "MAC_EXT": tuple(ext_mac), + } + return macs.get(mac_type, None) def get_flash_crypt_config(self): return None # doesn't exist on ESP32-C6 diff --git a/esptool/targets/esp32c6beta.py b/esptool/targets/esp32c6beta.py index 4c4b6bebd..b6e100bb4 100644 --- a/esptool/targets/esp32c6beta.py +++ b/esptool/targets/esp32c6beta.py @@ -16,7 +16,8 @@ class ESP32C6BETAROM(ESP32C3ROM): def get_chip_description(self): chip_name = { - 0: "ESP32-C6", + 0: "ESP32-C6 (QFN40)", + 1: "ESP32-C6FH4 (QFN32)", }.get(self.get_pkg_version(), "unknown ESP32-C6") major_rev = self.get_major_chip_version() minor_rev = self.get_minor_chip_version() diff --git a/esptool/targets/esp32h2.py b/esptool/targets/esp32h2.py index a37617e1d..66600c7da 100644 --- a/esptool/targets/esp32h2.py +++ b/esptool/targets/esp32h2.py @@ -13,6 +13,15 @@ class ESP32H2ROM(ESP32C6ROM): # Magic value for ESP32H2 CHIP_DETECT_MAGIC_VALUE = [0xD7B73E80] + DR_REG_LP_WDT_BASE = 0x600B1C00 + RTC_CNTL_WDTCONFIG0_REG = DR_REG_LP_WDT_BASE + 0x0 # LP_WDT_RWDT_CONFIG0_REG + RTC_CNTL_WDTWPROTECT_REG = DR_REG_LP_WDT_BASE + 0x001C # LP_WDT_RWDT_WPROTECT_REG + + RTC_CNTL_SWD_CONF_REG = DR_REG_LP_WDT_BASE + 0x0020 # LP_WDT_SWD_CONFIG_REG + RTC_CNTL_SWD_AUTO_FEED_EN = 1 << 18 + RTC_CNTL_SWD_WPROTECT_REG = DR_REG_LP_WDT_BASE + 0x0024 # LP_WDT_SWD_WPROTECT_REG + RTC_CNTL_SWD_WKEY = 0x50D83AA1 # LP_WDT_SWD_WKEY, same as WDT key in this case + FLASH_FREQUENCY = { "48m": 0xF, "24m": 0x0, @@ -20,12 +29,19 @@ class ESP32H2ROM(ESP32C6ROM): "12m": 0x2, } + UF2_FAMILY_ID = 0x332726F6 + def get_pkg_version(self): + num_word = 4 + return (self.read_reg(self.EFUSE_BLOCK1_ADDR + (4 * num_word)) >> 0) & 0x07 + + def get_minor_chip_version(self): + num_word = 3 + return (self.read_reg(self.EFUSE_BLOCK1_ADDR + (4 * num_word)) >> 18) & 0x07 + + def get_major_chip_version(self): num_word = 3 - block1_addr = self.EFUSE_BASE + 0x044 - word3 = self.read_reg(block1_addr + (4 * num_word)) - pkg_version = (word3 >> 21) & 0x0F - return pkg_version + return (self.read_reg(self.EFUSE_BLOCK1_ADDR + (4 * num_word)) >> 21) & 0x03 def get_chip_description(self): chip_name = { @@ -36,7 +52,7 @@ def get_chip_description(self): return f"{chip_name} (revision v{major_rev}.{minor_rev})" def get_chip_features(self): - return ["BLE"] + return ["BLE", "IEEE802.15.4"] def get_crystal_freq(self): # ESP32H2 XTAL is fixed to 32MHz diff --git a/esptool/targets/esp32h2beta1.py b/esptool/targets/esp32h2beta1.py index 66b6df902..49e38e44a 100644 --- a/esptool/targets/esp32h2beta1.py +++ b/esptool/targets/esp32h2beta1.py @@ -76,19 +76,16 @@ class ESP32H2BETA1ROM(ESP32C3ROM): } def get_pkg_version(self): - num_word = 3 - return (self.read_reg(self.EFUSE_BLOCK1_ADDR + (4 * num_word)) >> 21) & 0x0F + num_word = 4 + return (self.read_reg(self.EFUSE_BLOCK1_ADDR + (4 * num_word)) >> 0) & 0x07 def get_minor_chip_version(self): - hi_num_word = 5 - hi = (self.read_reg(self.EFUSE_BLOCK1_ADDR + (4 * hi_num_word)) >> 23) & 0x01 - low_num_word = 3 - low = (self.read_reg(self.EFUSE_BLOCK1_ADDR + (4 * low_num_word)) >> 18) & 0x07 - return (hi << 3) + low + num_word = 3 + return (self.read_reg(self.EFUSE_BLOCK1_ADDR + (4 * num_word)) >> 18) & 0x07 def get_major_chip_version(self): - num_word = 5 - return (self.read_reg(self.EFUSE_BLOCK1_ADDR + (4 * num_word)) >> 24) & 0x03 + num_word = 3 + return (self.read_reg(self.EFUSE_BLOCK1_ADDR + (4 * num_word)) >> 21) & 0x03 def get_chip_description(self): chip_name = { @@ -109,7 +106,10 @@ def override_vddsdio(self, new_voltage): "VDD_SDIO overrides are not supported for ESP32-H2" ) - def read_mac(self): + def read_mac(self, mac_type="BASE_MAC"): + """Read MAC from EFUSE region""" + if mac_type != "BASE_MAC": + return None mac0 = self.read_reg(self.MAC_EFUSE_REG) mac1 = self.read_reg(self.MAC_EFUSE_REG + 4) # only bottom 16 bits are MAC bitstring = struct.pack(">II", mac1, mac0)[2:] diff --git a/esptool/targets/esp32p4.py b/esptool/targets/esp32p4.py new file mode 100644 index 000000000..0791ab65a --- /dev/null +++ b/esptool/targets/esp32p4.py @@ -0,0 +1,192 @@ +# SPDX-FileCopyrightText: 2023 Fredrik Ahlberg, Angus Gratton, +# Espressif Systems (Shanghai) CO LTD, other contributors as noted. +# +# SPDX-License-Identifier: GPL-2.0-or-later + +import struct + +from .esp32 import ESP32ROM +from ..loader import ESPLoader +from ..util import FatalError, NotImplementedInROMError + + +class ESP32P4ROM(ESP32ROM): + CHIP_NAME = "ESP32-P4" + IMAGE_CHIP_ID = 18 + + IROM_MAP_START = 0x40000000 + IROM_MAP_END = 0x4C000000 + DROM_MAP_START = 0x40000000 + DROM_MAP_END = 0x4C000000 + + BOOTLOADER_FLASH_OFFSET = 0x2000 # First 2 sectors are reserved for FE purposes + + CHIP_DETECT_MAGIC_VALUE = [0x0] + + UART_DATE_REG_ADDR = 0x500CA000 + 0x8C + + EFUSE_BASE = 0x5012D000 + EFUSE_BLOCK1_ADDR = EFUSE_BASE + 0x044 + MAC_EFUSE_REG = EFUSE_BASE + 0x044 + + SPI_REG_BASE = 0x5008D000 # SPIMEM1 + SPI_USR_OFFS = 0x18 + SPI_USR1_OFFS = 0x1C + SPI_USR2_OFFS = 0x20 + SPI_MOSI_DLEN_OFFS = 0x24 + SPI_MISO_DLEN_OFFS = 0x28 + SPI_W0_OFFS = 0x58 + + EFUSE_RD_REG_BASE = EFUSE_BASE + 0x030 # BLOCK0 read base address + + EFUSE_PURPOSE_KEY0_REG = EFUSE_BASE + 0x34 + EFUSE_PURPOSE_KEY0_SHIFT = 24 + EFUSE_PURPOSE_KEY1_REG = EFUSE_BASE + 0x34 + EFUSE_PURPOSE_KEY1_SHIFT = 28 + EFUSE_PURPOSE_KEY2_REG = EFUSE_BASE + 0x38 + EFUSE_PURPOSE_KEY2_SHIFT = 0 + EFUSE_PURPOSE_KEY3_REG = EFUSE_BASE + 0x38 + EFUSE_PURPOSE_KEY3_SHIFT = 4 + EFUSE_PURPOSE_KEY4_REG = EFUSE_BASE + 0x38 + EFUSE_PURPOSE_KEY4_SHIFT = 8 + EFUSE_PURPOSE_KEY5_REG = EFUSE_BASE + 0x38 + EFUSE_PURPOSE_KEY5_SHIFT = 12 + + EFUSE_DIS_DOWNLOAD_MANUAL_ENCRYPT_REG = EFUSE_RD_REG_BASE + EFUSE_DIS_DOWNLOAD_MANUAL_ENCRYPT = 1 << 20 + + EFUSE_SPI_BOOT_CRYPT_CNT_REG = EFUSE_BASE + 0x034 + EFUSE_SPI_BOOT_CRYPT_CNT_MASK = 0x7 << 18 + + EFUSE_SECURE_BOOT_EN_REG = EFUSE_BASE + 0x038 + EFUSE_SECURE_BOOT_EN_MASK = 1 << 20 + + PURPOSE_VAL_XTS_AES256_KEY_1 = 2 + PURPOSE_VAL_XTS_AES256_KEY_2 = 3 + PURPOSE_VAL_XTS_AES128_KEY = 4 + + SUPPORTS_ENCRYPTED_FLASH = True + + FLASH_ENCRYPTED_WRITE_ALIGN = 16 + + MEMORY_MAP = [ + [0x00000000, 0x00010000, "PADDING"], + [0x40000000, 0x4C000000, "DROM"], + [0x4FF00000, 0x4FFA0000, "DRAM"], + [0x4FF00000, 0x4FFA0000, "BYTE_ACCESSIBLE"], + [0x4FC00000, 0x4FC20000, "DROM_MASK"], + [0x4FC00000, 0x4FC20000, "IROM_MASK"], + [0x40000000, 0x4C000000, "IROM"], + [0x4FF00000, 0x4FFA0000, "IRAM"], + [0x50108000, 0x50110000, "RTC_IRAM"], + [0x50108000, 0x50110000, "RTC_DRAM"], + [0x600FE000, 0x60100000, "MEM_INTERNAL2"], + ] + + UF2_FAMILY_ID = 0x3D308E94 + + def get_pkg_version(self): + # ESP32P4 TODO + return 0 + + def get_minor_chip_version(self): + # ESP32P4 TODO + return 0 + + def get_major_chip_version(self): + # ESP32P4 TODO + return 0 + + def get_chip_description(self): + chip_name = { + 0: "ESP32-P4", + }.get(self.get_pkg_version(), "unknown ESP32-P4") + major_rev = self.get_major_chip_version() + minor_rev = self.get_minor_chip_version() + return f"{chip_name} (revision v{major_rev}.{minor_rev})" + + def get_chip_features(self): + return ["High-Performance MCU"] + + def get_crystal_freq(self): + # ESP32P4 XTAL is fixed to 40MHz + return 40 + + def override_vddsdio(self, new_voltage): + raise NotImplementedInROMError( + "VDD_SDIO overrides are not supported for ESP32-P4" + ) + + def read_mac(self, mac_type="BASE_MAC"): + """Read MAC from EFUSE region""" + if mac_type != "BASE_MAC": + return None + mac0 = self.read_reg(self.MAC_EFUSE_REG) + mac1 = self.read_reg(self.MAC_EFUSE_REG + 4) # only bottom 16 bits are MAC + bitstring = struct.pack(">II", mac1, mac0)[2:] + return tuple(bitstring) + + def get_flash_crypt_config(self): + return None # doesn't exist on ESP32-P4 + + def get_secure_boot_enabled(self): + return ( + self.read_reg(self.EFUSE_SECURE_BOOT_EN_REG) + & self.EFUSE_SECURE_BOOT_EN_MASK + ) + + def get_key_block_purpose(self, key_block): + if key_block < 0 or key_block > 5: + raise FatalError("Valid key block numbers must be in range 0-5") + + reg, shift = [ + (self.EFUSE_PURPOSE_KEY0_REG, self.EFUSE_PURPOSE_KEY0_SHIFT), + (self.EFUSE_PURPOSE_KEY1_REG, self.EFUSE_PURPOSE_KEY1_SHIFT), + (self.EFUSE_PURPOSE_KEY2_REG, self.EFUSE_PURPOSE_KEY2_SHIFT), + (self.EFUSE_PURPOSE_KEY3_REG, self.EFUSE_PURPOSE_KEY3_SHIFT), + (self.EFUSE_PURPOSE_KEY4_REG, self.EFUSE_PURPOSE_KEY4_SHIFT), + (self.EFUSE_PURPOSE_KEY5_REG, self.EFUSE_PURPOSE_KEY5_SHIFT), + ][key_block] + return (self.read_reg(reg) >> shift) & 0xF + + def is_flash_encryption_key_valid(self): + # Need to see either an AES-128 key or two AES-256 keys + purposes = [self.get_key_block_purpose(b) for b in range(6)] + + if any(p == self.PURPOSE_VAL_XTS_AES128_KEY for p in purposes): + return True + + return any(p == self.PURPOSE_VAL_XTS_AES256_KEY_1 for p in purposes) and any( + p == self.PURPOSE_VAL_XTS_AES256_KEY_2 for p in purposes + ) + + def change_baud(self, baud): + ESPLoader.change_baud(self, baud) + + def _post_connect(self): + pass + # TODO: Disable watchdogs when USB modes are supported in the stub + # if not self.sync_stub_detected: # Don't run if stub is reused + # self.disable_watchdogs() + + +class ESP32P4StubLoader(ESP32P4ROM): + """Access class for ESP32P4 stub loader, runs on top of ROM. + + (Basically the same as ESP32StubLoader, but different base class. + Can possibly be made into a mixin.) + """ + + FLASH_WRITE_SIZE = 0x4000 # matches MAX_WRITE_BLOCK in stub_loader.c + STATUS_BYTES_LENGTH = 2 # same as ESP8266, different to ESP32 ROM + IS_STUB = True + + def __init__(self, rom_loader): + self.secure_download_mode = rom_loader.secure_download_mode + self._port = rom_loader._port + self._trace_enabled = rom_loader._trace_enabled + self.cache = rom_loader.cache + self.flush_input() # resets _slip_reader + + +ESP32P4ROM.STUB_CLASS = ESP32P4StubLoader diff --git a/esptool/targets/esp32s2.py b/esptool/targets/esp32s2.py index bffd55331..cd361f918 100644 --- a/esptool/targets/esp32s2.py +++ b/esptool/targets/esp32s2.py @@ -16,8 +16,6 @@ class ESP32S2ROM(ESP32ROM): CHIP_NAME = "ESP32-S2" IMAGE_CHIP_ID = 2 - FPGA_SLOW_BOOT = False - IROM_MAP_START = 0x40080000 IROM_MAP_END = 0x40B80000 DROM_MAP_START = 0x3F000000 @@ -101,6 +99,8 @@ class ESP32S2ROM(ESP32ROM): [0x50000000, 0x50002000, "RTC_DATA"], ] + UF2_FAMILY_ID = 0xBFDD4EEE + def get_pkg_version(self): num_word = 4 return (self.read_reg(self.EFUSE_BLOCK1_ADDR + (4 * num_word)) >> 0) & 0x0F @@ -120,10 +120,16 @@ def get_flash_version(self): num_word = 3 return (self.read_reg(self.EFUSE_BLOCK1_ADDR + (4 * num_word)) >> 21) & 0x0F + def get_flash_cap(self): + return self.get_flash_version() + def get_psram_version(self): num_word = 3 return (self.read_reg(self.EFUSE_BLOCK1_ADDR + (4 * num_word)) >> 28) & 0x0F + def get_psram_cap(self): + return self.get_psram_version() + def get_block2_version(self): # BLK_VERSION_MINOR num_word = 4 @@ -137,7 +143,7 @@ def get_chip_description(self): 102: "ESP32-S2FNR2", 100: "ESP32-S2R2", }.get( - self.get_flash_version() + self.get_psram_version() * 100, + self.get_flash_cap() + self.get_psram_cap() * 100, "unknown ESP32-S2", ) major_rev = self.get_major_chip_version() @@ -154,14 +160,14 @@ def get_chip_features(self): 0: "No Embedded Flash", 1: "Embedded Flash 2MB", 2: "Embedded Flash 4MB", - }.get(self.get_flash_version(), "Unknown Embedded Flash") + }.get(self.get_flash_cap(), "Unknown Embedded Flash") features += [flash_version] psram_version = { 0: "No Embedded PSRAM", 1: "Embedded PSRAM 2MB", 2: "Embedded PSRAM 4MB", - }.get(self.get_psram_version(), "Unknown Embedded PSRAM") + }.get(self.get_psram_cap(), "Unknown Embedded PSRAM") features += [psram_version] block2_version = { @@ -182,7 +188,10 @@ def override_vddsdio(self, new_voltage): "VDD_SDIO overrides are not supported for ESP32-S2" ) - def read_mac(self): + def read_mac(self, mac_type="BASE_MAC"): + """Read MAC from EFUSE region""" + if mac_type != "BASE_MAC": + return None mac0 = self.read_reg(self.MAC_EFUSE_REG) mac1 = self.read_reg(self.MAC_EFUSE_REG + 4) # only bottom 16 bits are MAC bitstring = struct.pack(">II", mac1, mac0)[2:] diff --git a/esptool/targets/esp32s3.py b/esptool/targets/esp32s3.py index 660537b51..3dc785216 100644 --- a/esptool/targets/esp32s3.py +++ b/esptool/targets/esp32s3.py @@ -19,8 +19,6 @@ class ESP32S3ROM(ESP32ROM): CHIP_DETECT_MAGIC_VALUE = [0x9] - FPGA_SLOW_BOOT = False - IROM_MAP_START = 0x42000000 IROM_MAP_END = 0x44000000 DROM_MAP_START = 0x3C000000 @@ -83,10 +81,15 @@ class ESP32S3ROM(ESP32ROM): UARTDEV_BUF_NO_USB_OTG = 3 # The above var when USB-OTG is used UARTDEV_BUF_NO_USB_JTAG_SERIAL = 4 # The above var when USB-JTAG/Serial is used - RTC_CNTL_WDT_WKEY = 0x50D83AA1 RTCCNTL_BASE_REG = 0x60008000 - RTC_CNTL_WDTCONFIG0_REG = RTCCNTL_BASE_REG + 0x0090 + RTC_CNTL_SWD_CONF_REG = RTCCNTL_BASE_REG + 0x00B4 + RTC_CNTL_SWD_AUTO_FEED_EN = 1 << 31 + RTC_CNTL_SWD_WPROTECT_REG = RTCCNTL_BASE_REG + 0x00B8 + RTC_CNTL_SWD_WKEY = 0x8F1D312A + + RTC_CNTL_WDTCONFIG0_REG = RTCCNTL_BASE_REG + 0x0098 RTC_CNTL_WDTWPROTECT_REG = RTCCNTL_BASE_REG + 0x00B0 + RTC_CNTL_WDT_WKEY = 0x50D83AA1 USB_RAM_BLOCK = 0x800 # Max block size USB-OTG is used @@ -112,6 +115,8 @@ class ESP32S3ROM(ESP32ROM): [0x50000000, 0x50002000, "RTC_DATA"], ] + UF2_FAMILY_ID = 0xC47E5767 + def get_pkg_version(self): num_word = 3 return (self.read_reg(self.EFUSE_BLOCK1_ADDR + (4 * num_word)) >> 21) & 0x07 @@ -160,10 +165,53 @@ def get_raw_major_chip_version(self): def get_chip_description(self): major_rev = self.get_major_chip_version() minor_rev = self.get_minor_chip_version() - return f"{self.CHIP_NAME} (revision v{major_rev}.{minor_rev})" + pkg_version = self.get_pkg_version() + + chip_name = { + 0: "ESP32-S3 (QFN56)", + 1: "ESP32-S3-PICO-1 (LGA56)", + }.get(pkg_version, "unknown ESP32-S3") + + return f"{chip_name} (revision v{major_rev}.{minor_rev})" + + def get_flash_cap(self): + num_word = 3 + return (self.read_reg(self.EFUSE_BLOCK1_ADDR + (4 * num_word)) >> 27) & 0x07 + + def get_flash_vendor(self): + num_word = 4 + vendor_id = (self.read_reg(self.EFUSE_BLOCK1_ADDR + (4 * num_word)) >> 0) & 0x07 + return {1: "XMC", 2: "GD", 3: "FM", 4: "TT", 5: "BY"}.get(vendor_id, "") + + def get_psram_cap(self): + num_word = 4 + return (self.read_reg(self.EFUSE_BLOCK1_ADDR + (4 * num_word)) >> 3) & 0x03 + + def get_psram_vendor(self): + num_word = 4 + vendor_id = (self.read_reg(self.EFUSE_BLOCK1_ADDR + (4 * num_word)) >> 7) & 0x03 + return {1: "AP_3v3", 2: "AP_1v8"}.get(vendor_id, "") def get_chip_features(self): - return ["WiFi", "BLE"] + features = ["WiFi", "BLE"] + + flash = { + 0: None, + 1: "Embedded Flash 8MB", + 2: "Embedded Flash 4MB", + }.get(self.get_flash_cap(), "Unknown Embedded Flash") + if flash is not None: + features += [flash + f" ({self.get_flash_vendor()})"] + + psram = { + 0: None, + 1: "Embedded PSRAM 8MB", + 2: "Embedded PSRAM 2MB", + }.get(self.get_psram_cap(), "Unknown Embedded PSRAM") + if psram is not None: + features += [psram + f" ({self.get_psram_vendor()})"] + + return features def get_crystal_freq(self): # ESP32S3 XTAL is fixed to 40MHz @@ -208,7 +256,10 @@ def override_vddsdio(self, new_voltage): "VDD_SDIO overrides are not supported for ESP32-S3" ) - def read_mac(self): + def read_mac(self, mac_type="BASE_MAC"): + """Read MAC from EFUSE region""" + if mac_type != "BASE_MAC": + return None mac0 = self.read_reg(self.MAC_EFUSE_REG) mac1 = self.read_reg(self.MAC_EFUSE_REG + 4) # only bottom 16 bits are MAC bitstring = struct.pack(">II", mac1, mac0)[2:] @@ -238,19 +289,29 @@ def uses_usb_jtag_serial(self): return False # can't detect USB-JTAG/Serial in secure download mode return self.get_uart_no() == self.UARTDEV_BUF_NO_USB_JTAG_SERIAL - def disable_rtc_watchdog(self): - # When USB-JTAG/Serial is used, the RTC watchdog is not reset - # and can then reset the board during flashing. Disable it. + def disable_watchdogs(self): + # When USB-JTAG/Serial is used, the RTC WDT and SWD watchdog are not reset + # and can then reset the board during flashing. Disable them. if self.uses_usb_jtag_serial(): + # Disable RTC WDT self.write_reg(self.RTC_CNTL_WDTWPROTECT_REG, self.RTC_CNTL_WDT_WKEY) self.write_reg(self.RTC_CNTL_WDTCONFIG0_REG, 0) self.write_reg(self.RTC_CNTL_WDTWPROTECT_REG, 0) + # Automatically feed SWD + self.write_reg(self.RTC_CNTL_SWD_WPROTECT_REG, self.RTC_CNTL_SWD_WKEY) + self.write_reg( + self.RTC_CNTL_SWD_CONF_REG, + self.read_reg(self.RTC_CNTL_SWD_CONF_REG) + | self.RTC_CNTL_SWD_AUTO_FEED_EN, + ) + self.write_reg(self.RTC_CNTL_SWD_WPROTECT_REG, 0) + def _post_connect(self): if self.uses_usb_otg(): self.ESP_RAM_BLOCK = self.USB_RAM_BLOCK if not self.sync_stub_detected: # Don't run if stub is reused - self.disable_rtc_watchdog() + self.disable_watchdogs() def _check_if_can_reset(self): """ diff --git a/esptool/targets/esp32s3beta2.py b/esptool/targets/esp32s3beta2.py index b7958bd53..f91bb3cb2 100644 --- a/esptool/targets/esp32s3beta2.py +++ b/esptool/targets/esp32s3beta2.py @@ -14,11 +14,6 @@ class ESP32S3BETA2ROM(ESP32S3ROM): EFUSE_BASE = 0x6001A000 # BLOCK0 read base address - def get_chip_description(self): - major_rev = self.get_major_chip_version() - minor_rev = self.get_minor_chip_version() - return f"{self.CHIP_NAME} (revision v{major_rev}.{minor_rev})" - class ESP32S3BETA2StubLoader(ESP32S3BETA2ROM): """Access class for ESP32S3 stub loader, runs on top of ROM. diff --git a/esptool/targets/esp8266.py b/esptool/targets/esp8266.py index f9966634d..e686abf6e 100644 --- a/esptool/targets/esp8266.py +++ b/esptool/targets/esp8266.py @@ -60,6 +60,8 @@ class ESP8266ROM(ESPLoader): [0x40201010, 0x402E1010, "IROM"], ] + UF2_FAMILY_ID = 0x7EAB61ED + def get_efuses(self): # Return the 128 bits of ESP8266 efuse as a single Python integer result = self.read_reg(0x3FF0005C) << 96 @@ -131,8 +133,10 @@ def chip_id(self): id1 = self.read_reg(self.ESP_OTP_MAC1) return (id0 >> 24) | ((id1 & 0xFFFFFF) << 8) - def read_mac(self): + def read_mac(self, mac_type="BASE_MAC"): """Read MAC from OTP ROM""" + if mac_type != "BASE_MAC": + return None mac0 = self.read_reg(self.ESP_OTP_MAC0) mac1 = self.read_reg(self.ESP_OTP_MAC1) mac3 = self.read_reg(self.ESP_OTP_MAC3) diff --git a/esptool/targets/stub_flasher/stub_flasher_32.json b/esptool/targets/stub_flasher/stub_flasher_32.json index 3e87d813c..23a283fa9 100644 --- a/esptool/targets/stub_flasher/stub_flasher_32.json +++ b/esptool/targets/stub_flasher/stub_flasher_32.json @@ -1,7 +1,7 @@ { "entry": 1074521560, - "text": "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", + "text": "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", "text_start": 1074520064, - "data": "GOv8P9jnC0Bx6AtA8+wLQO3oC0CP6AtA7egLQEnpC0AG6gtAeOoLQCHqC0CB5wtAo+kLQPjpC0Bn6QtAmuoLQI7pC0Ca6gtAXegLQLPoC0Dt6AtASekLQHfoC0BM6wtAs+wLQKXmC0DX7AtApeYLQKXmC0Cl5gtApeYLQKXmC0Cl5gtApeYLQKXmC0Dz6gtApeYLQM3rC0Cz7AtA", + "data": "DMD8P9jnC0Br6AtAA+0LQPLoC0CL6AtA8ugLQFHpC0Ae6gtAkOoLQDnqC0CB5wtAtukLQBDqC0B06QtAtOoLQJ7pC0C06gtAWegLQLboC0Dy6AtAUekLQHHoC0Bk6wtAxewLQKTmC0Dn7AtApOYLQKTmC0Ck5gtApOYLQKTmC0Ck5gtApOYLQKTmC0AL6wtApOYLQOXrC0DF7AtA", "data_start": 1073605544 } \ No newline at end of file diff --git a/esptool/targets/stub_flasher/stub_flasher_32c2.json b/esptool/targets/stub_flasher/stub_flasher_32c2.json index 07887d4d1..365c705ff 100644 --- a/esptool/targets/stub_flasher/stub_flasher_32c2.json +++ b/esptool/targets/stub_flasher/stub_flasher_32c2.json @@ -1,7 +1,7 @@ { "entry": 1077413304, - "text": "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", + "text": "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", "text_start": 1077411840, - "data": "GGvKP+AIOEAsCThAhAk4QCgKOECUCjhAQgo4QKgHOEDkCThAJAo4QJgJOEBYBzhAzAk4QFgHOEC6CDhA/gg4QCwJOECECThAzAg4QBIIOEBCCDhAyAg4QOYMOEAsCThArAs4QJoMOECkBjhAxAw4QKQGOECkBjhApAY4QKQGOECkBjhApAY4QKQGOECkBjhASAs4QKQGOEDICzhAmgw4QA==", + "data": "DEDKP+AIOEAsCThAhAk4QCgKOECUCjhAQgo4QKgHOEDkCThAJAo4QJgJOEBYBzhAzAk4QFgHOEC6CDhA/gg4QCwJOECECThAzAg4QBIIOEBCCDhAyAg4QOwMOEAsCThArAs4QKAMOECkBjhAygw4QKQGOECkBjhApAY4QKQGOECkBjhApAY4QKQGOECkBjhASAs4QKQGOEDICzhAoAw4QA==", "data_start": 1070295976 } \ No newline at end of file diff --git a/esptool/targets/stub_flasher/stub_flasher_32c3.json b/esptool/targets/stub_flasher/stub_flasher_32c3.json index 8426a637a..3edf1457e 100644 --- a/esptool/targets/stub_flasher/stub_flasher_32c3.json +++ b/esptool/targets/stub_flasher/stub_flasher_32c3.json @@ -1,7 +1,7 @@ { "entry": 1077413532, - "text": "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", + "text": "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", "text_start": 1077411840, - "data": "IGvIP1YKOECmCjhA/go4QKILOEAODDhAvAs4QCIJOEBeCzhAngs4QBILOEDSCDhARgs4QNIIOEAwCjhAdgo4QKYKOED+CjhAQgo4QIYJOEC2CThAPgo4QGAOOECmCjhAJg04QBgOOEASCDhAQA44QBIIOEASCDhAEgg4QBIIOEASCDhAEgg4QBIIOEASCDhAwgw4QBIIOEBEDThAGA44QA==", + "data": "FEDIP4wKOEDcCjhANAs4QNgLOEBEDDhA8gs4QD4JOECUCzhA1As4QEgLOEDuCDhAfAs4QO4IOEBmCjhArAo4QNwKOEA0CzhAeAo4QKIJOEDsCThAdAo4QJwOOEDcCjhAXA04QFQOOEAuCDhAfA44QC4IOEAuCDhALgg4QC4IOEAuCDhALgg4QC4IOEAuCDhA+Aw4QC4IOEB6DThAVA44QA==", "data_start": 1070164912 } \ No newline at end of file diff --git a/esptool/targets/stub_flasher/stub_flasher_32c6.json b/esptool/targets/stub_flasher/stub_flasher_32c6.json index 2bf3accf8..fa81d618f 100644 --- a/esptool/targets/stub_flasher/stub_flasher_32c6.json +++ b/esptool/targets/stub_flasher/stub_flasher_32c6.json @@ -1,7 +1,7 @@ { "entry": 1082132112, - "text": "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", + "text": "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", "text_start": 1082130432, - "data": "HCuEQCoKgEB6CoBA0gqAQHYLgEDiC4BAkAuAQPYIgEAyC4BAcguAQOYKgECmCIBAGguAQKYIgEAECoBASgqAQHoKgEDSCoBAFgqAQFoJgECKCYBAEgqAQDQOgEB6CoBA+gyAQOwNgEDmB4BAFA6AQOYHgEDmB4BA5geAQOYHgEDmB4BA5geAQOYHgEDmB4BAlgyAQOYHgEAYDYBA7A2AQA==", + "data": "EACEQD4KgECOCoBA5gqAQIoLgED2C4BApAuAQAoJgEBGC4BAhguAQPoKgEC6CIBALguAQLoIgEAYCoBAXgqAQI4KgEDmCoBAKgqAQG4JgECeCYBAJgqAQE4OgECOCoBADg2AQAYOgED6B4BALg6AQPoHgED6B4BA+geAQPoHgED6B4BA+geAQPoHgED6B4BAqgyAQPoHgEAsDYBABg6AQA==", "data_start": 1082469292 } \ No newline at end of file diff --git a/esptool/targets/stub_flasher/stub_flasher_32c6beta.json b/esptool/targets/stub_flasher/stub_flasher_32c6beta.json index 4709f9ddc..94fd3da07 100644 --- a/esptool/targets/stub_flasher/stub_flasher_32c6beta.json +++ b/esptool/targets/stub_flasher/stub_flasher_32c6beta.json @@ -1,7 +1,7 @@ { "entry": 1077413318, - "text": "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", + "text": "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", "text_start": 1077411840, - "data": "GGvIP/gIOEBECThAnAk4QEAKOECsCjhAWgo4QMAHOED8CThAPAo4QLAJOEBwBzhA5Ak4QHAHOEDSCDhAFgk4QEQJOECcCThA5Ag4QCoIOEBaCDhA4Ag4QP4MOEBECThAxAs4QLIMOEC8BjhA3Aw4QLwGOEC8BjhAvAY4QLwGOEC8BjhAvAY4QLwGOEC8BjhAYAs4QLwGOEDgCzhAsgw4QA==", + "data": "DEDIP/gIOEBECThAnAk4QEAKOECsCjhAWgo4QMAHOED8CThAPAo4QLAJOEBwBzhA5Ak4QHAHOEDSCDhAFgk4QEQJOECcCThA5Ag4QCoIOEBaCDhA4Ag4QAQNOEBECThAxAs4QLgMOEC8BjhA4gw4QLwGOEC8BjhAvAY4QLwGOEC8BjhAvAY4QLwGOEC8BjhAYAs4QLwGOEDgCzhAuAw4QA==", "data_start": 1070164904 } \ No newline at end of file diff --git a/esptool/targets/stub_flasher/stub_flasher_32h2.json b/esptool/targets/stub_flasher/stub_flasher_32h2.json index f003a550b..b3b637395 100644 --- a/esptool/targets/stub_flasher/stub_flasher_32h2.json +++ b/esptool/targets/stub_flasher/stub_flasher_32h2.json @@ -1,7 +1,7 @@ { "entry": 1082132112, - "text": "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", + "text": "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", "text_start": 1082130432, - "data": "HCuDQCoKgEB6CoBA0gqAQHYLgEDiC4BAkAuAQPYIgEAyC4BAcguAQOYKgECmCIBAGguAQKYIgEAECoBASgqAQHoKgEDSCoBAFgqAQFoJgECKCYBAEgqAQDQOgEB6CoBA+gyAQOwNgEDmB4BAFA6AQOYHgEDmB4BA5geAQOYHgEDmB4BA5geAQOYHgEDmB4BAlgyAQOYHgEAYDYBA7A2AQA==", + "data": "EACDQD4KgECOCoBA5gqAQIoLgED2C4BApAuAQAoJgEBGC4BAhguAQPoKgEC6CIBALguAQLoIgEAYCoBAXgqAQI4KgEDmCoBAKgqAQG4JgECeCYBAJgqAQE4OgECOCoBADg2AQAYOgED6B4BALg6AQPoHgED6B4BA+geAQPoHgED6B4BA+geAQPoHgED6B4BAqgyAQPoHgEAsDYBABg6AQA==", "data_start": 1082403756 } \ No newline at end of file diff --git a/esptool/targets/stub_flasher/stub_flasher_32h2beta1.json b/esptool/targets/stub_flasher/stub_flasher_32h2beta1.json index 37d29e8fb..6d4ec72b1 100644 --- a/esptool/targets/stub_flasher/stub_flasher_32h2beta1.json +++ b/esptool/targets/stub_flasher/stub_flasher_32h2beta1.json @@ -1,7 +1,7 @@ { "entry": 1077413318, - "text": "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", + "text": "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", "text_start": 1077411840, - "data": "GGvIP/gIOEBECThAnAk4QEAKOECsCjhAWgo4QMAHOED8CThAPAo4QLAJOEBwBzhA5Ak4QHAHOEDSCDhAFgk4QEQJOECcCThA5Ag4QCoIOEBaCDhA4Ag4QP4MOEBECThAxAs4QLIMOEC8BjhA3Aw4QLwGOEC8BjhAvAY4QLwGOEC8BjhAvAY4QLwGOEC8BjhAYAs4QLwGOEDgCzhAsgw4QA==", + "data": "DEDIP/gIOEBECThAnAk4QEAKOECsCjhAWgo4QMAHOED8CThAPAo4QLAJOEBwBzhA5Ak4QHAHOEDSCDhAFgk4QEQJOECcCThA5Ag4QCoIOEBaCDhA4Ag4QAQNOEBECThAxAs4QLgMOEC8BjhA4gw4QLwGOEC8BjhAvAY4QLwGOEC8BjhAvAY4QLwGOEC8BjhAYAs4QLwGOEDgCzhAuAw4QA==", "data_start": 1070164904 } \ No newline at end of file diff --git a/esptool/targets/stub_flasher/stub_flasher_32h2beta2.json b/esptool/targets/stub_flasher/stub_flasher_32h2beta2.json index f7cc1cecd..cd438aba0 100644 --- a/esptool/targets/stub_flasher/stub_flasher_32h2beta2.json +++ b/esptool/targets/stub_flasher/stub_flasher_32h2beta2.json @@ -1,7 +1,7 @@ { "entry": 1077413318, - "text": "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", + "text": "ARG3BwBgTsaDqYcASsg3Scg/JspSxAbOIsy3BABgfVoTCQkAwEwTdPQ/DeDyQGJEI6g0AUJJ0kSySSJKBWGCgIhAgycJABN19Q+Cl30U4xlE/8m/EwcADJRBqodjGOUAhUeFxiOgBQB5VYKABUdjh+YACUZjjcYAfVWCgEIFEwewDUGFY5XnAolHnMH1t5MGwA1jFtUAmMETBQAMgoCTBtANfVVjldcAmMETBbANgoC3dck/QRGThQW6BsZhP2NFBQa3d8k/k4eHsQOnBwgD1kcIE3X1D5MGFgDCBsGCI5LXCDKXIwCnAAPXRwiRZ5OHBwRjHvcCN/fIPxMHh7GhZ7qXA6YHCLc2yT+3d8k/k4eHsZOGhrVjH+YAI6bHCCOg1wgjkgcIIaD5V+MG9fyyQEEBgoAjptcII6DnCN23NycAYHxLnYv1/zc3AGB8S52L9f+CgEERBsbdN7cnAGAjpgcCNwcACJjDmEN9/8hXskATRfX/BYlBAYKAQREGxtk/fd03BwBAtycAYJjDNycAYBxD/f+yQEEBgoBBESLEN8TIP5MHxABKwAOpBwEGxibCYwoJBEU3OcW9RxMExACBRGPWJwEERL2Ik7QUAH03hT8cRDcGgAATl8cAmeA3BgABt/b/AHWPtyYAYNjCkMKYQn3/QUeR4AVHMwnpQLqXIygkARzEskAiRJJEAklBAYKAQREGxhMHAAxjEOUCEwWwDZcAyP/ngIDjEwXADbJAQQEXA8j/ZwCD4hMHsA3jGOX+lwDI/+eAgOETBdANxbdBESLEJsIGxiqEswS1AGMXlACyQCJEkkRBAYKAA0UEAAUERTfttxMFAAwXA8j/ZwAD3jVxJstOx/1yhWn9dCLNSslSxVbDBs+ThIT6FpGThwkHppcYCLOE5wAqiSaFLoSXAMj/54BgWpOHCQcYCAVqupezikdBMeQFZ311kwWF+pMHBwcTBYX5FAiqlzOF1wCTBwcHrpezhdcAKsaXAMj/54AgVzJFwUWhPwFFhWIWkfpAakTaREpJukkqSppKDWGCgKKJY3OKAIVpTobWhUqFlwDI/+eA4OITdfUPAe1OhtaFJoWXAMj/54BgUk6ZMwQ0QVG3EwUwBlW/MXH9ck7XUtVW017PBt8i3SbbStla0WLNZstqyW7HqokWkRMFAAIuirKKtosCypcAyP/ngCBNhWdj4FcThWR9dBMEhPqThwQHopcYCDOE5wAihZcAyP/ngKBLfXsTDDv5kwyL+ROHBAeThwQHFAhil+aXAUkzDNcAs4zXAFJNY3xNCWNxqQNBqFU1poUIAaU9cT0mhgwBIoWXAMj/54CAR6aZJpljdUkDswepQWPxdwOzBCpBY/OaANaEJoYMAU6FlwDI/+eAQNQTdfUPVd0CzIFEeV2NTaMJAQBihZcAyP/ngMDDffkDRTEB5oUFMWNPBQDj4p3+hWeThwcHppcYCLqX2pcjiqf4hQTxt+MVpf2RR+OF9PYFZ311kwcHB5MFhfoTBYX5FAiqlzOF1wCTBwcHrpezhdcAKsaXAMj/54CgPe0zMkXBRX07zTMTBQAClwDI/+eAQDuFYhaR+lBqVNpUSlm6WSpamloKW/pLakzaTEpNuk0pYYKAAREGziLMnTk3BM4/bAATBQT/lwDI/+eAwMqqhwVFleeyR5P3ByA+xkE5NycAYBxHtwZAABMFBP/VjxzHskWXAMj/54BAyDM1oADyQGJEBWGCgEERt8fIPwbGk4fHAAVHI4DnABPXxQCYxwVnfRfMw8jH+Y06laqVsYGMyyOqBwBBNxnBEwVQDLJAQQGCgAERIsw3xMg/kwfEACbKxEdOxgbOSsiqiRMExABj85UAroSpwAMpRAAmmRNZyQAcSGNV8AAcRGNe+QLpNn3dSEAmhs6FlwDI/+eAQLsTdfUPAcWTB0AMXMhcQKaXXMBcRIWPXMTyQGJE0kRCSbJJBWGCgOE+bb+3V0FJGXGTh/eEAUU+zobeotym2srYztbS1NbS2tDezuLM5srqyO7GlwDI/+eAIK23R8g/N3fJP5OHBwATB4e6Y+XnFK0xkUVoCD05jTG398g/k4eHsSFnPpcjIPcItwU4QLcHOECThwcLAUaThQUAN0nIPxVFIyD5AJcAyP/ngEAgNwcAYFxHEwUAArd5yT+T5xcQXMeXAMj/54AAH5cAyP/ngAAwt0cAYJxfk4mJsRMJCQAJ5fGL4RcTtRcAgUWXAMj/54AgsMFnt8TIP/0XEwcAEIVmQWa3BQABAUWThMQAt0rIPw1qlwDI/+eA4KoTi8oAJpqDp8kI9d+Dq8kIhUcjpgkIIwLxAoPHGwAJRyMT4QKjAvECAtRNR2OL5wZRR2OJ5wYpR2Of5wCDxzsAA8crAKIH2Y8RR2OW5wCDp4sAnEM+1KU2oUVIEDU+g8c7AAPHKwCiB9mPEWdBB2N+9wITBbANlwDI/+eAwJITBcANlwDI/+eAAJITBeAOlwDI/+eAQJElNr23I6AHAJEHRb3JRyMT8QJ9twPHGwDRRmPn5gKFRmPm5gABTBME8A+dqHkXE3f3D8lG4+jm/rd2yT8KB5OGxro2lxhDAoeTBgcDk/b2DxFG42nW/BMH9wITd/cPjUZj7uYIt3bJPwoHk4aGvzaXGEMChxMHQAJjmucQAtQdRAFFlwDI/+eAoIgBRSU8aTxhPKFFSBB9FK00ffABTAFEE3X0DwU0E3X8Dyk8tTzjEQTsg8cbAElHY2D3LglH43n36vUXk/f3Dz1H42P36jd3yT+KBxMHh8C6l5xDgocFRJ3rcBCBRQFFlwDI/+eAQIgd4dFFaBAxNAFEMagFRIHvlwDI/+eAQI0zNKAAKaAhR2OF5wAFRAFMYbcDrIsAA6TLALNnjADSB/X3sTFl9cFsIpz9HH19MwWMQF3cs3eVAZXjwWwzBYxAY+aMAv18MwWMQF3QMYGXAMj/54DgiV35ZpT1tzGBlwDI/+eA4Ihd8WqU0bdBgZcAyP/ngCCIWfkzBJRBwbchR+OK5/ABTBMEAAw5t0FHzb9BRwVE453n9oOlywADpYsAcTK5v0FHBUTjk+f2A6cLAZFnY+PnHIOlSwEDpYsACTGBt0FHBUTjlOf0g6cLARFnY2T3GgOnywCDpUsBA6WLADOE5wLxPiOsBAAjJIqwCb8DxwQAYw4HEAOniwDBFxMEAAxjE/cAwEgBR5MG8A5jRvcCg8dbAAPHSwABTKIH2Y8Dx2sAQgddj4PHewDiB9mP44T25hMEEAyFtTOG6wADRoYBBQexjuG3g8cEAPHD3ERjmAcSwEgjgAQAVb1hR2OW5wKDp8sBA6eLAYOmSwEDpgsBg6XLAAOliwCX8Mf/54DgeCqMMzSgAAG9AUwFRCm1EUcFROOd5+YDpYsAgUWX8Mf/54Bgeam1E/f3AOMcB+yT3EcAE4SLAAFMfV3jfJzdSESX8Mf/54CgYhhEVEAQQPmOYwenARxCE0f3/32P2Y4UwgUMQQTZvxFHWb1BRwVE45/n4IOniwADp0sBIyT5ACMi6QD1s4MlSQDBF5Hlic8BTBMEYAxJswMniQBjZvcGE/c3AOMQB+YDKIkAAUYBRzMF6ECzhuUAY2n3AOMMBtQjJKkAIyLZALGzM4brABBOEQeQwgVG6b8hRwVE45nn2gMkiQAZwBMEgAwjJAkAIyIJADM0gABhuwFMEwQgDCm7AUwTBIAMCbsBTBMEkAwpsxMHIA1jg+cMEwdADeOW57wDxDsAg8crACIEXYyX8Mf/54CAYQOsxABBFGNzhAEijOMEDLrAQGKUMYCcSGNV8ACcRGNa9Arv8K/idd3IQGKGk4WLAZfwx//ngIBdAcWTB0AM3MjcQOKX3MDcRLOHh0HcxJfwx//ngGBcub4JZRMFBXEDrMsAA6SLAJfwx//ngCBNtwcAYNhLtwYAAcEWk1dHARIHdY+9i9mPs4eHAwFFs9WHApfwx//ngABOEwWAPpfwx//ngMBJAb6DpksBA6YLAYOlywADpYsA7/Cv+O28g8U7AIPHKwAThYsBogXdjcEVrTrVtO/wD9yBtwPEOwCDxysAE4yLASIEXYzcREEUxeORR4VLY/6HCJMHkAzcyGW8A6cNACLQBUizh+xAPtaDJ4qwY3P0AA1IQsY6xO/wj9ciRzJIN8XIP+KFfBCThsoAEBATBUUCl/DH/+eAgEs398g/kwjHAIJXA6eIsIOlDQAdjB2PPpyyVyOk6LCqi76VI6C9AJOHygCdjQHFoWdjlvUAWoXZOCOgbQEJxNxEmcPjQHD5Y98LAJMHcAyFv4VLt33JP7fMyD+TjY26k4zMAOm/45oLoNxE44cHoJMHgAyxt4OniwDjkAegAUWX8Mf/54DgOgllEwUFcZfwx//ngAA3l/DH/+eAADvxugOkywDjCwScAUWX8Mf/54BAOBMFgD6X8Mf/54CANAKUbbr2UGZU1lRGWbZZJlqWWgZb9ktmTNZMRk22TQlhgoAAAA==", "text_start": 1077411840, - "data": "GGvIP/gIOEBECThAnAk4QEAKOECsCjhAWgo4QMAHOED8CThAPAo4QLAJOEBwBzhA5Ak4QHAHOEDSCDhAFgk4QEQJOECcCThA5Ag4QCoIOEBaCDhA4Ag4QP4MOEBECThAxAs4QLIMOEC8BjhA3Aw4QLwGOEC8BjhAvAY4QLwGOEC8BjhAvAY4QLwGOEC8BjhAYAs4QLwGOEDgCzhAsgw4QA==", + "data": "DEDIP/gIOEBECThAnAk4QEAKOECsCjhAWgo4QMAHOED8CThAPAo4QLAJOEBwBzhA5Ak4QHAHOEDSCDhAFgk4QEQJOECcCThA5Ag4QCoIOEBaCDhA4Ag4QAQNOEBECThAxAs4QLgMOEC8BjhA4gw4QLwGOEC8BjhAvAY4QLwGOEC8BjhAvAY4QLwGOEC8BjhAYAs4QLwGOEDgCzhAuAw4QA==", "data_start": 1070164904 } \ No newline at end of file diff --git a/esptool/targets/stub_flasher/stub_flasher_32p4.json b/esptool/targets/stub_flasher/stub_flasher_32p4.json new file mode 100644 index 000000000..6ed0687a3 --- /dev/null +++ b/esptool/targets/stub_flasher/stub_flasher_32p4.json @@ -0,0 +1,7 @@ +{ + "entry": 1341195718, + "text": "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", + "text_start": 1341194240, + "data": "DAD1T+4I8U86CfFPkgnxTzYK8U+iCvFPUArxT7YH8U/yCfFPMgrxT6YJ8U9mB/FP2gnxT2YH8U/ICPFPDAnxTzoJ8U+SCfFP2gjxTyAI8U9QCPFP1gjxT/oM8U86CfFPugvxT64M8U+yBvFP2AzxT7IG8U+yBvFPsgbxT7IG8U+yBvFPsgbxT7IG8U+yBvFPVgvxT7IG8U/WC/FPrgzxTw==", + "data_start": 1341533096 +} \ No newline at end of file diff --git a/esptool/targets/stub_flasher/stub_flasher_32s2.json b/esptool/targets/stub_flasher/stub_flasher_32s2.json index de8cdc22c..cdb47ab4a 100644 --- a/esptool/targets/stub_flasher/stub_flasher_32s2.json +++ b/esptool/targets/stub_flasher/stub_flasher_32s2.json @@ -1,7 +1,7 @@ { "entry": 1073907696, - "text": "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", + "text": "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", "text_start": 1073905664, - "data": "ZCv9PzaLAkDBiwJAhpACQEqMAkDjiwJASowCQKmMAkByjQJA5Y0CQI2NAkDAigJAC40CQGSNAkDMjAJACI4CQPaMAkAIjgJAr4sCQA6MAkBKjAJAqYwCQMeLAkACiwJAx44CQD2QAkDYiQJAZZACQNiJAkDYiQJA2IkCQNiJAkDYiQJA2IkCQNiJAkDYiQJAZI4CQNiJAkBZjwJAPZACQA==", + "data": "WAD9PzeLAkDJiwJAjpACQFKMAkDqiwJAUowCQLGMAkB6jQJA7Y0CQJWNAkDBigJAE40CQGyNAkDUjAJAEI4CQP6MAkAQjgJAt4sCQBaMAkBSjAJAsYwCQM+LAkADiwJA044CQEaQAkDWiQJAbZACQNaJAkDWiQJA1okCQNaJAkDWiQJA1okCQNaJAkDWiQJAcI4CQNaJAkBljwJARpACQA==", "data_start": 1073622012 } \ No newline at end of file diff --git a/esptool/targets/stub_flasher/stub_flasher_32s3.json b/esptool/targets/stub_flasher/stub_flasher_32s3.json index e38c81aba..6c4a6ec69 100644 --- a/esptool/targets/stub_flasher/stub_flasher_32s3.json +++ b/esptool/targets/stub_flasher/stub_flasher_32s3.json @@ -1,7 +1,7 @@ { - "entry": 1077381816, - "text": "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", + "entry": 1077381692, + "text": "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", "text_start": 1077379072, - "data": "ZCvKP2qON0BLjzdAGpQ3QNaPN0BrjzdA1o83QDWQN0ACkTdAc5E3QB2RN0D1jTdAmJA3QPSQN0BYkDdAlpE3QIKQN0CWkTdAOY83QJaPN0DWjzdANZA3QFGPN0A2jjdAVJI3QNGTN0ASjTdA+ZM3QBKNN0ASjTdAEo03QBKNN0ASjTdAEo03QBKNN0ASjTdA75E3QBKNN0DpkjdA0ZM3QAQInwAAAAAAAAAYAQQIBQAAAAAAAAAIAQQIBgAAAAAAAAAAAQQIIQAAAAAAIAAAEQQI3AAAAAAAIAAAEQQIDAAAAAAAIAAAAQQIEgAAAAAAIAAAESAoDAAQAQAA", - "data_start": 1070279676 + "data": "WADKPxqON0DvjjdAs5M3QHmPN0APjzdAeY83QNmPN0CmkDdAGJE3QMGQN0CljTdAPJA3QJiQN0D8jzdAPJE3QCaQN0A8kTdA3Y43QDqPN0B5jzdA2Y83QPWON0DmjTdA/JE3QHmTN0C8jDdAmZM3QLyMN0C8jDdAvIw3QLyMN0C8jDdAvIw3QLyMN0C8jDdAlpE3QLyMN0CRkjdAeZM3QAQInwAAAAAAAAAYAQQIBQAAAAAAAAAIAQQIBgAAAAAAAAAAAQQIIQAAAAAAIAAAEQQI3AAAAAAAIAAAEQQIDAAAAAAAIAAAAQQIEgAAAAAAIAAAESAoDAAQAQAA", + "data_start": 1070279672 } \ No newline at end of file diff --git a/esptool/targets/stub_flasher/stub_flasher_32s3beta2.json b/esptool/targets/stub_flasher/stub_flasher_32s3beta2.json index 3df188605..09ea66aa0 100644 --- a/esptool/targets/stub_flasher/stub_flasher_32s3beta2.json +++ b/esptool/targets/stub_flasher/stub_flasher_32s3beta2.json @@ -1,7 +1,7 @@ { - "entry": 1077381308, - "text": "FIADYACAA2BIAMo/BIADYDZBAIH7/wxJwCAAmQjGBAAAgfj/wCAAqAiB9/+goHSICOAIACH2/8AgAIgCJ+jhHfAAAAAIAABgHAAAYBAAAGA2QQAh/P/AIAA4AkH7/8AgACgEICCUnOJB6P9GBAAMODCIAcAgAKgIiASgoHTgCAALImYC6Ib0/yHx/8AgADkCHfAAAOwryz9kq8o/hIAAAEBAAACk68o/8CvLPzZBALH5/yCgdBARIOUQAZYaBoH2/5KhAZCZEZqYwCAAuAmR8/+goHSaiMAgAJIYAJCQ9BvJwMD0wCAAwlgAmpvAIACiSQDAIACSGACB6v+QkPSAgPSHmUeB5f+SoQGQmRGamMAgAMgJoeX/seP/h5wXxgEAfOiHGt7GCADAIACJCsAgALkJRgIAwCAAuQrAIACJCZHX/5qIDAnAIACSWAAd8AAAVCAAYFQwAGA2QQCR/f/AIACICYCAJFZI/5H6/8AgAIgJgIAkVkj/HfAAAAAsIABgACAAYAAAAAg2QQAQESCl/P8h+v8MCMAgAIJiAJH6/4H4/8AgAJJoAMAgAJgIVnn/wCAAiAJ88oAiMCAgBB3wAAAAAEA2QQAQESDl+/8Wav+B7P+R+//AIACSaADAIACYCFZ5/x3wAABYAMo/////AAQgAGA2QQAh/P84QhaDBhARIGX4/xb6BQz4DAQ3qA2YIoCZEIKgAZBIg0BAdBARICX6/xARICXz/4giDBtAmBGQqwHMFICrAbHt/7CZELHs/8AgAJJrAJHO/8AgAKJpAMAgAKgJVnr/HAkMGkCag5AzwJqIOUKJIh3wAACMqQRANkEAIKIggf3/4AgAHfAAAHDi+j8IIABgWNIEQHjSBEA2YQAQESAl7P8x+f+9Aa0Dgfr/4AgATQoMEuzqiAGSogCQiBCJARARIKXw/5Hy/6CiAcAgAIgJoIggwCAAiQm4Aa0Dge7/4AgAoCSDHfAAAP8PAAA2QQCBwP8MGZJIADCcQZkokfv/ORgpODAwtJoiKjMwPEEMAilYOUgQESAl+P8tCowaIqDFHfAAAOziBEA2QQBBsf9YNFAzYxZjBFgUWlNQXEFGAQAQESCl6/+IRKYYBIgkh6XvEBEg5eP/Fmr/qBTNA70CgfH/4AgAoKB0jEpSoMRSZAVYFDpVWRRYNDBVwFk0HfAAtJwEQDZBAIH+/+AIAIIKGAwJgsj8DBKAKZMd8DZBAIH4/+AIAIIKGAwJgsj9DBKAKZMd8DZBABARICX+/yKgAcxqEBEg5fv/LQogIAQd8AD4K8s/9CvLPxAADGBgAAxg//P//zZBABARIKX8/xZaBKH4/4gKvNiB9/+YCLxpsfb/fMzAIACIC5CQFMCIEJCIIMAgAIkLiAqx8f8MOmCqEcAgAJgLoIgQoe7/oJkQkIggwCAAiQsd8FDzzj9EAMo/TADKP1SfBEBAnwRAhKAEQDZhAHzIrQKHky0x9//GBQAAqAMMHL0Bgff/4AgAgej+ogEAiAjgCACoA4Hz/+AIAOYa3cYKAAAAZgMmDAPNAQwrMmEAge7/4AgAmAGB6P83mQ2oCGYaCDHm/8AgAKJDAJkIHfBAAMo/AADKP+CeBEA2QQAh/P+B3P/IAqgIsfr/gfv/4AgADAiJAh3wUJgEQDZBABARIGXr/4y6gfL/iAiMSBARIKX8/xARIKXo/xYqAKKgBIH2/+AIAB3wIJgEQDZBABARIGXo/7wakeb/iAkbqKkJkeX/DAqKmSJJAILIwQwZgKmDoIB0zIqir0CqIiCYk5zZEBEgZff/RgUArQKB7//gCAAQESCl4v+MShARIOX3/x3wAAA2QQCioMAQESDl+f8d8AAANkEAgqDArQKHkhGioNsQESBl+P+ioNxGBAAAAACCoNuHkggQESAl9/+ioN0QESCl9v8d8DZBADoyxgIAAKICABsiEBEgpfv/N5LxHfAAAACgdgNAzOMEQMB2A0BAdwNANiEhotEQgfr/4AgARgsAAAAMFEBEEUBDY80EvQGtAoH1/+AIAKCgdPxazQQQsSCi0RCB8f/gCABKIkAzwFYD/SKiCxAisCCiILLREIHs/+AIAK0CHAsQESCl9/8tA4YAACKgYx3wAADYnwRASEgEQOSfBEBUSARANkEAEBEgZdT/rIoME0F2//AzAYyyqASB9v/gCACtA8YJAK0DgfT/4AgAqASB8//gCAAGCQAQESClz/8MGPCIASwDoIODrQgWkgCB7P/gCACGAQAAgej/4AgAHfAYmQRANkEhYqEHwGYRGmZZBgwFYtEQrQVSZhoQESBl+P8MGECIEUe4AkZFAK0Ggbv/4AgAhjQAAJKkHVBzwOCZERqZQHdjiQnNB70BIKIggbT/4AgAkqQd4JkRGpmgoHSICYyqDAiCZhZ9CIYWAAAAkqQd4JkREJmAgmkAEBEg5eP/vQetARARIGXn/xARIOXi/80HELEgYKYggaL/4AgAkqQd4JkRGpmICXAigHBVgDe1sJKhB8CZERqZmAmAdcCXtwJG3P+G5v8MCIJGbKKkGxCqoIHL/+AIAFYK/7KiC6IGbBC7sBARIKWjAPfqEvZHD7KiDRC7sHq7oksAG3eG8f9867eawWZHCIImGje4Aoe1nCKiCxAisGC2IK0CgYL/4AgAEBEgZdn/rQIcCxARIOXc/xARIGXY/wwaEBEgZeb/HfAAAMo/T0hBSbCAAGChOthQkIAAYPwryz+sgDdAmCAMYHCCN0BIhDdACAAIYIAhDGAQgDdAEIADYFCAN0AMAABgOEAAYP//AAAsgQBgjIAAABBAAAAALMs/ECzLP1AAyj9UAMo/XCzLPxQAAGDw//8A/CvLP2Qryj9wAMo/+E0EQEgxBEA4SARAKKAEQKyfBEBsOgRAAOEEQHDmBEDQtgRALKMEQCypBEAEXARA9IsEQOThBEB44gRABOIEQGiVBEC0+ARAXPoEQND4BEAsVANA7FsEQDbhACHL/wwKKcGB5//gCAAQESDlrf8WagQxvv5Bvf7AIAAoA1G9/ikEwCAAKAVht/6ioGQpBmG5/mAiEGKkAGAiIMAgACkFgdn/4AgASAR8wkAiEEKgAkAiIMAgACJjABARIOWl/6wqIbP/MbP/QbP/wCAAOQIMA8AgADkEwCAAOQKGAQBJAksixgEAIaj/Maz/DAQ3Mu0QESClwP8MS6LBMBARICXE/yKhARARIGW//0HK/ZAiESokwCAASQIxof8hov05AhARIOWg/y0KFvoFIaj+wan+qAIMK4Gr/uAIADGZ/7Ga/xwaDAzAIACpA4Gw/+AIAAwa8KoBgSP/4AgAsZP/qAIMFYGr/+AIAKgCgRv/4AgAqAKBqP/gCAAxjf/AIAAoA1AiIMAgACkDhhgAEBEgpZj/vBoxh/8cGrGH/8AgAKJjACDCIIGZ/+AIADGE/wxFwCAAKAMMGlAiIMAgACkD8KoBxggAAACxfv/NCgxagY//4AgAMXv/UqEBwCAAKAMsClAiIMAgACkDgf7+4AgAgYr/4AgAIXT/wCAAKALMuhzDMCIQIsL4DBMgo4MMC4GD/+AIAPFt/wwdDByyoAHioQBA3REAzBFguwGioACBfP/gCAAhaP8qRCHT/WLSK8YXAAAAAFFk/sAgADIFADAwdBbTBAwa8KoBwCAAIkUAgd/+4AgAoqJxwKoRgWf/4AgAgWz/4AgAcVb/fOjAIAA4B3z6gDMQEKoBwCAAOQeBZv/gCACBZv/gCACtAoFl/+AIAMAgACgEFqL5DAfAIAA4BAwSwCAAeQQiQSQiAwEMKHmhIkElglETHDd3EiQcR3cSIWaSISIDA3IDAoAiEXAiIGZCEigjwCAAKAIpoYYBAAAAHCIiURMQESBloP+yoAiiwSQQESDlo/+yAwMiAwKAuxEgWyAhMP8gIPRXshqioMAQESClnv+ioO4QESAlnv8QESDlnP8G2v8iAwEcRyc3N/YiGwbjAAAiwi8gIHS2QgIGJQBxIv9wIqAoAqACAAAiwv4gIHQcJye3AkbZAHEc/3AioCgCoAIAcsIwcHB0tlfFhtMALEkMByKgwJcVAobRAHmhDHKtBxARIGWX/60HEBEg5Zb/EBEgZZX/EBEgJZX/DIuiwSQiwv8QESBlmP9WIv1GLgAMElYlMMLBEL0FrQWBGP/gCABWKi8cS6LBEBARICWW/4aaAAwSVvUtgRL/4AgAoCWDxrQAJoUEDBLGsgAoI3gzcIIggIC0Vtj+EBEg5WH/eiKcCgb4/6CsQYEH/+AIAFZK/XLX8HCiwMwnBogAAKCA9FYY/oYDAKCg9YEA/+AIAFY6+1B3wAwVAFURcKLAdzXlBgQAAACgrEGB9/7gCABWSvly1/BwosBWp/7GdwAADAcioMAmhQIGlgAMBy0HRpQAJrX1BmoADBImtQIGjgC4M6gjDAcQESAljf+gJ4OGiQAMGWa1X4hDIKkRDAcioMKHugIGhwC4U6gjkmEREBEg5Vv/kiERoJeDRg4ADBlmtTSIQyCpEQwHIqDCh7oCRnwAKDO4U6gjIHiCkmEREBEg5Vj/ISP9DAiSIRGJYiLSK3JiAqCYgy0JBm8AkR39DAeiCQAioMZ3mgKGbQB4I7LF8CKgwLeXAiIpBQwHkqDvRgIAeoOCCBgbd4CZMLcn8oIDBXIDBICIEXCIIHIDBgB3EYB3IIIDB4CIAXCIIICZwIKgwQwHkCiTxlkAgQX9IqDGkggAfQkWmRWYOAwHIqDIdxkCBlMAKFiSSABGTgAciQwHDBKXFQIGTgD4c+hj2FPIQ7gzqCOBnf7gCAAMCH0KoCiDBkcAAAAMEiZFAsZBAKgjDAuBlP7gCAAGIAAAUJA0DAcioMB3GQKGPQBQVEGLw3z4Rg8AqDyCYRKSYRHCYRCBhP7gCADCIRCCIRIoLHgcqAySIRFwchAmAg3AIADYCiAoMNAiECB3IMAgAHkKG5nCzBBXOb7Gk/9mRQJGkv8MByKgwIYmAAwSJrUCxiEAIWf+iFN4I4kCIWb+eQIMAgYdAKFi/gwH6AoMGbLF8I0HLQewKZPgiYMgiBAioMZ3mGDBXP59CNgMIqDJtz1TsPAUIqDAVq8ELQiGAgAAKoOIaEsiiQeNCSp+IP3AtzLtFmjd+Qx5CsZz/wwSZoUYIUz+giIAjBiCoMgMB3kCIUj+eQIMEoAngwwHRgEAAAwHIqD/IKB0EBEgJWP/cKB0EBEgZWL/EBEgJWH/VtK6IgMBHCcnNx/2MgLG5/4iwv0gIHQM9ye3Akbk/nE3/nAioCgCoAIAAHKg0ncSX3Kg1HeSAgYhAMbc/igzOCMQESDlP/+NClZKtqKiccCqEYJhEoEw/uAIAHEp/pEp/sAgAHgHgiEScLQ1wHcRkHcQcLsgILuCrQgwu8KBNf7gCACio+iBJP7gCABGyP4AANhTyEO4M6gjEBEgpWv/hsP+ALIDAyIDAoC7ESC7ILLL8KLDGBARIGUx/4a8/gAiAwNyAwKAIhFwIiCBI/7gCABxcfwiwvCIN4AiYxYSrYgXioKAjEFGAwAAAIJhEhARICUb/4IhEpInBKYZBZInApeo5xARICUT/xZq/6gXzQKywxiBEv7gCACMOjKgxDlXOBcqMzkXODcgI8ApN4EM/uAIAIae/gAAAHIDAiLDGDIDAwwZgDMRcDMgMsPwxiMAce39gf376Ac5seCIwIlBiCYMGYezAQw5kmER4mEQEBEgJRP/geX9kiER4iEQoeT93Qi9ApkBwsEs8sEQgmESgfX94AgAuCadCqixgiESoLvAuSagM8C4B6oiqEEMDKq7DBq5B5DKg4C7wMDQdFaMAMLbgMCtkxZqAa0IgmESkmEREBEgpR//giESkiERgmcAUS38eDWMo5CPMZCIwNYoAFbH9dapADEo/CKgxylTRgAAjDmcBwZq/hZXmlEj/CKgyClVhmb+ADEg/CKgySlThmP+AAAoI1ZymBARIKU1/6KiccCqEYG4/eAIABARIOUk/4HJ/eAIAIZZ/gAAKDMW8pUQESAlM/+io+iBr/3gCAAQESBlIv/gAgAGUf4AEBEgpSH/HfAAADZBAJ0CgqDAKAOHmQ/MMgwShgcADAIpA3zihg8AJhIHJiIYhgMAAACCoNuAKSOHmSoMIikDfPJGCAAAACKg3CeZCgwSKQMtCAYEAAAAgqDdfPKHmQYMEikDIqDbHfAAAA==", + "entry": 1077381188, + "text": "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", "text_start": 1077379072, - "data": "ZCvKP1qMN0DnjDdAvpE3QHGNN0AHjTdAcY03QNGNN0CejjdAEI83QLmON0DlizdANI43QJCON0D0jTdANI83QB6ON0A0jzdA1Yw3QDKNN0BxjTdA0Y03QO2MN0AmjDdA9I83QHWRN0ACizdAnZE3QAKLN0ACizdAAos3QAKLN0ACizdAAos3QAKLN0ACizdAjo83QAKLN0CKkDdAdZE3QA==", - "data_start": 1070279676 + "data": "WADKP7OLN0BHjDdAFJE3QNOMN0BnjDdA04w3QDKNN0D/jTdAcY43QBqON0A9izdAk403QPGNN0BVjTdAlI43QH6NN0CUjjdANYw3QJSMN0DTjDdAMo03QE2MN0B/izdAWI83QNqQN0BWijdA+pA3QFaKN0BWijdAVoo3QFaKN0BWijdAVoo3QFaKN0BWijdA8443QFaKN0DtjzdA2pA3QA==", + "data_start": 1070279668 } \ No newline at end of file diff --git a/esptool/targets/stub_flasher/stub_flasher_8266.json b/esptool/targets/stub_flasher/stub_flasher_8266.json index 8d42b24af..95e6e9e53 100644 --- a/esptool/targets/stub_flasher/stub_flasher_8266.json +++ b/esptool/targets/stub_flasher/stub_flasher_8266.json @@ -1,7 +1,7 @@ { "entry": 1074843652, - "text": "qBAAQAH//0Z0AAAAkIH/PwgB/z+AgAAAhIAAAEBAAABIQf8/lIH/PzH5/xLB8CAgdAJhA4XvATKv/pZyA1H0/0H2/zH0/yAgdDA1gEpVwCAAaANCFQBAMPQbQ0BA9MAgAEJVADo2wCAAIkMAIhUAMev/ICD0N5I/Ieb/Meb/Qen/OjLAIABoA1Hm/yeWEoYAAAAAAMAgACkEwCAAWQNGAgDAIABZBMAgACkDMdv/OiIMA8AgADJSAAgxEsEQDfAAoA0AAJiB/z8Agf4/T0hBSais/z+krP8/KNAQQEzqEEAMAABg//8AAAAQAAAAAAEAAAAAAYyAAAAQQAAAAAD//wBAAAAAgf4/BIH+PxAnAAAUAABg//8PAKis/z8Igf4/uKz/PwCAAAA4KQAAkI//PwiD/z8Qg/8/rKz/P5yv/z8wnf8/iK//P5gbAAAACAAAYAkAAFAOAABQEgAAPCkAALCs/z+0rP8/1Kr/PzspAADwgf8/DK//P5Cu/z+ACwAAEK7/P5Ct/z8BAAAAAAAAALAVAADx/wAAmKz/P5iq/z+8DwBAiA8AQKgPAEBYPwBAREYAQCxMAEB4SABAAEoAQLRJAEDMLgBA2DkAQEjfAECQ4QBATCYAQIRJAEAhvP+SoRCQEcAiYSMioAACYUPCYULSYUHiYUDyYT8B6f/AAAAhsv8xs/8MBAYBAABJAksiNzL4hbUBIqCMDEMqIcWnAYW0ASF8/8F6/zGr/yoswCAAyQIhqP8MBDkCMaj/DFIB2f/AAAAxpv8ioQHAIABIAyAkIMAgACkDIqAgAdP/wAAAAdL/wAAAAdL/wAAAcZ3/UZ7/QZ7/MZ7/YqEADAIBzf/AAAAhnP8xYv8qI8AgADgCFnP/wCAA2AIMA8AgADkCDBIiQYQiDQEMJCJBhUJRQzJhIiaSCRwzNxIghggAAAAiDQMyDQKAIhEwIiBmQhEoLcAgACgCImEiBgEAHCIiUUOFqAEioIQMgxoiBZsBIg0DMg0CgCIRMDIgIX//N7ITIqDAxZUBIqDuRZUBxaUBRtz/AAAiDQEMtEeSAgaZACc0Q2ZiAsbLAPZyIGYyAoZxAPZCCGYiAsZWAEbKAGZCAgaHAGZSAsarAIbGACaCefaCAoarAAyUR5ICho8AZpICBqMABsAAHCRHkgJGfAAnNCcM9EeSAoY+ACc0CwzUR5IChoMAxrcAAGayAkZLABwUR5ICRlgARrMAQqDRRxJoJzQRHDRHkgJGOABCoNBHEk/GrAAAQqDSR5IChi8AMqDTN5ICRpcFRqcALEIMDieTAgZqBUYrACKgAEWIASKgAAWIAYWYAUWYASKghDKgCBoiC8yFigFW3P0MDs0ORpsAAMwThl8FRpUAJoMCxpMABmAFAWn/wAAA+sycIsaPAAAAICxBAWb/wAAAVhIj8t/w8CzAzC+GaQUAIDD0VhP+4Sv/hgMAICD1AV7/wAAAVtIg4P/A8CzA9z7qhgMAICxBAVf/wAAAVlIf8t/w8CzAVq/+RloFJoOAxgEAAABmswJG3f8MDsKgwIZ4AAAAZrMCRkQFBnIAAMKgASazAgZwACItBDEX/+KgAMKgwiezAsZuADhdKC1FdgFGPAUAwqABJrMChmYAMi0EIQ7/4qAAwqDCN7ICRmUAKD0MHCDjgjhdKC2FcwEx9/4MBEljMtMr6SMgxIMGWgAAIfP+DA5CAgDCoMbnlALGWADIUigtMsPwMCLAQqDAIMSTIs0YTQJioO/GAQBSBAAbRFBmMCBUwDcl8TINBVINBCINBoAzEQAiEVBDIEAyICINBwwOgCIBMCIgICbAMqDBIMOThkMAAAAh2f4MDjICAMKgxueTAsY+ADgywqDI5xMCBjwA4kIAyFIGOgAcggwODBwnEwIGNwAGCQVmQwKGDwVGMAAwIDQMDsKgwOcSAoYwADD0QYvtzQJ888YMACg+MmExAQL/wAAASC4oHmIuACAkEDIhMSYEDsAgAFImAEBDMFBEEEAiIMAgACkGG8zizhD3PMjGgf9mQwJGgP8Gov9mswIG+QTGFgAAAGHA/gwOSAYMFTLD8C0OQCWDMF6DUCIQwqDG55JLcbn+7QKIB8KgyTc4PjBQFMKgwKLNGIzVBgwAWiooAktVKQRLRAwSUJjANzXtFmLaSQaZB8Zn/2aDAoblBAwcDA7GAQAAAOKgAMKg/8AgdMVeAeAgdIVeAQVvAVZMwCINAQzzNxIxJzMVZkICxq4EZmIChrMEJjICxvn+BhkAABwjN5ICxqgEMqDSNxJFHBM3EgJG8/5GGQAhlP7oPdItAgHA/sAAACGS/sAgADgCIZH+ICMQ4CKC0D0gxYoBPQItDAG5/sAAACKj6AG2/sAAAMbj/lhdSE04PSItAoVqAQbg/gAyDQMiDQKAMxEgMyAyw/AizRgFSQHG2f4AAABSzRhSYSQiDQMyDQKAIhEwIiAiwvAiYSoMH4Z0BCF3/nGW/rIiAGEy/oKgAyInApIhKoJhJ7DGwCc5BAwaomEnsmE2hTkBsiE2cW3+UiEkYiEqcEvAykRqVQuEUmElgmEshwQCxk0Ed7sCRkwEmO2iLRBSLRUobZJhKKJhJlJhKTxTyH3iLRT4/SezAkbuAzFc/jAioCgCoAIAMUL+DA4MEumT6YMp0ymj4mEm/Q7iYSjNDkYGAHIhJwwTcGEEfMRgQ5NtBDliXQtyISQG4AMAgiEkkiElITP+l7jZMggAG3g5goYGAKIhJwwjMGoQfMUMFGBFg20EOWJdC0bUA3IhJFIhJSEo/le321IHAPiCWZKALxEc81oiQmExUmE0smE2G9cFeQEME0IhMVIhNLIhNlYSASKgICBVEFaFAPAgNCLC+CA1g/D0QYv/DBJhLv4AH0AAUqFXNg8AD0BA8JEMBvBigzBmIJxGDB8GAQAAANIhJCEM/ixDOWJdCwabAF0Ltjwehg4AciEnfMNwYQQMEmAjg20CDDOGFQBdC9IhJEYAAP0GgiElh73bG90LLSICAAAcQAAioYvMIO4gtjzkbQ9x+P3gICQptyAhQSnH4ONBwsz9VuIfwCAkJzwoRhEAkiEnfMOQYQQMEmAjg20CDFMh7P05Yn0NxpQDAAAAXQvSISRGAAD9BqIhJae90RvdCy0iAgAAHEAAIqGLzCDuIMAgJCc84cAgJAACQODgkSKv+CDMEPKgABacBoYMAAAAciEnfMNwYQQMEmAjg20CDGMG5//SISRdC4IhJYe94BvdCy0iAgAAHEAAIqEg7iCLzLaM5CHM/cLM+PoyIeP9KiPiQgDg6EGGDAAAAJIhJwwTkGEEfMRgNINtAwxzxtT/0iEkXQuiISUhv/2nvd1B1v0yDQD6IkoiMkIAG90b//ZPAobc/yHt/Xz28hIcIhIdIGYwYGD0Z58Hxh0A0iEkXQssc8Y/ALaMIAYPAHIhJ3zDcGEEDBJgI4NtAjwzBrz/AABdC9IhJEYAAP0GgiElh73ZG90LLSICAAAcQAAioYvMIO4gtozkbQ/gkHSSYSjg6EHCzPj9BkYCADxDhtQC0iEkXQsha/0nte+iISgLb6JFABtVFoYHVrz4hhwADJPGywJdC9IhJEYAAP0GIWH9J7XqhgYAciEnfMNwYQQMEmAjg20CLGPGmf8AANIhJF0LgiElh73ekVb90GjAUCnAZ7IBbQJnvwFtD00G0D0gUCUgUmE0YmE1smE2Abz9wAAAYiE1UiE0siE2at1qVWBvwFZm+UbQAv0GJjIIxgQAANIhJF0LDKMhb/05Yn0NBhcDAAAMDyYSAkYgACKhICJnESwEIYL9QmcSMqAFUmE0YmE1cmEzsmE2Aab9wAAAciEzsiE2YiE1UiE0PQcioJBCoAhCQ1gLIhszVlL/IqBwDJMyR+gLIht3VlL/HJRyoViRVf0MeEYCAAB6IpoigkIALQMbMkeT8SFq/TFq/QyEBgEAQkIAGyI3kvdGYQEhZ/36IiICACc8HUYPAAAAoiEnfMOgYQQMEmAjg20CDLMGVP/SISRdCyFc/foiYiElZ73bG90LPTIDAAAcQAAzoTDuIDICAIvMNzzhIVT9QVT9+iIyAgAMEgATQAAioUBPoAsi4CIQMMzAAANA4OCRSAQxLf0qJDA/oCJjERv/9j8Cht7/IUf9QqEgDANSYTSyYTYBaP3AAAB9DQwPUiE0siE2RhUAAACCISd8w4BhBAwSYCODbQIM4wa0AnIhJF0LkiEll7fgG3cLJyICAAAcQAAioSDuIIvMtjzkITP9QRL9+iIiAgDgMCQqRCEw/cLM/SokMkIA4ONBG/8hC/0yIhM3P9McMzJiE90HbQ8GHQEATAQyoAAiwURSYTRiYTWyYTZyYTMBQ/3AAAByITOB/fwioWCAh4JBHv0qKPoiDAMiwhiCYTIBO/3AAACCITIhGf1CpIAqKPoiDAMiwhgBNf3AAACoz4IhMvAqoCIiEYr/omEtImEuTQ9SITRiITVyITOyITbGAwAiD1gb/xAioDIiERszMmIRMiEuQC/ANzLmDAIpESkBrQIME+BDEZLBREr5mA9KQSop8CIRGzMpFJqqZrPlMeb8OiKMEvYqKyHW/EKm0EBHgoLIWCqIIqC8KiSCYSsMCXzzQmE5ImEwxkMAAF0L0iEkRgAA/QYsM8aZAACiISuCCgCCYTcWiA4QKKB4Ahv3+QL9CAwC8CIRImE4QiE4cCAEImEvC/9AIiBwcUFWX/4Mp4c3O3B4EZB3IAB3EXBwMUIhMHJhLwwacbb8ABhAAKqhKoRwiJDw+hFyo/+GAgAAQiEvqiJCWAD6iCe38gYgAHIhOSCAlIqHoqCwQan8qohAiJBymAzMZzJYDH0DMsP+IClBoaP88qSwxgoAIIAEgIfAQiE5fPeAhzCKhPCIgKCIkHKYDMx3MlgMMHMgMsP+giE3C4iCYTdCITcMuCAhQYeUyCAgBCB3wHz6IiE5cHowenIipLAqdyGO/CB3kJJXDEIhKxuZG0RCYStyIS6XFwLGvf+CIS0mKALGmQBGggAM4seyAsYwAJIhJdApwKYiAoYlACGj/OAwlEF9/CojQCKQIhIMADIRMCAxlvIAMCkxFjIFJzwCRiQAhhIAAAyjx7NEkZj8fPgAA0DgYJFgYAQgKDAqJpoiQCKQIpIMG3PWggYrYz0HZ7zdhgYAoiEnfMOgYQQMEmAjg20CHAPGdv4AANIhJF0LYiElZ73eIg0AGz0AHEAAIqEg7iCLzAzi3QPHMgLG2v8GCAAiDQEyzAgAE0AAMqEiDQDSzQIAHEAAIqEgIyAg7iDCzBAhdfzgMJRhT/wqI2AikDISDAAzETAgMZaiADA5MSAghEYJAAAAgWz8DKR89xs0AARA4ECRQEAEICcwKiSKImAikCKSDE0DliL+AANA4OCRMMzAImEoDPMnIxUhOvxyISj6MiFe/Bv/KiNyQgAGNAAAgiEoZrga3H8cCZJhKAYBANIhJF0LHBMhL/x89jliBkH+MVP8KiMiwvAiAgAiYSYnPB0GDgCiISd8w6BhBAwSYCODbQIcI8Y1/gAA0iEkXQtiISVnvd4b3QstIgIAciEmABxAACKhi8wg7iB3POGCISYxQPySISgMFgAYQABmoZozC2Yyw/DgJhBiAwAACEDg4JEqZiE5/IDMwCovDANmuQwxDPz6QzE1/Do0MgMATQZSYTRiYTWyYTYBSfzAAABiITVSITRq/7IhNoYAAAAMD3EB/EInEWInEmpkZ78Chnj/95YHhgIA0iEkXQscU0bJ/wDxIfwhIvw9D1JhNGJhNbJhNnJhMwE1/MAAAHIhMyEL/DInEUInEjo/ATD8wAAAsiE2YiE1UiE0Mer7KMMLIinD8ej7eM/WN7iGPgFiISUM4tA2wKZDDkG2+1A0wKYjAkZNAMYyAseyAoYuAKYjAkYlAEHc++AglEAikCISvAAyETAgMZYSATApMRZSBSc8AsYkAAYTAAAAAAyjx7NEfPiSpLAAA0DgYJFgYAQgKDAqJpoiQCKQIpIMG3PWggYrYz0HZ7zdhgYAciEnfMNwYQQMEmAjg20CHHPG1P0AANIhJF0LgiElh73eIg0AGz0AHEAAIqEg7iCLzAzi3QPHMgKG2/8GCAAAACINAYs8ABNAADKhIg0AK90AHEAAIqEgIyAg7iDCzBBBr/vgIJRAIpAiErwAIhEg8DGWjwAgKTHw8ITGCAAMo3z3YqSwGyMAA0DgMJEwMATw9zD682r/QP+Q8p8MPQKWL/4AAkDg4JEgzMAioP/3ogLGQACGAgAAHIMG0wDSISRdCyFp+ye17/JFAG0PG1VG6wAM4scyGTINASINAIAzESAjIAAcQAAioSDuICvdwswQMYr74CCUqiIwIpAiEgwAIhEgMDEgKTHWEwIMpBskAARA4ECRQEAEMDkwOjRBf/uKM0AzkDKTDE0ClvP9/QMAAkDg4JEgzMB3g3xioA7HNhpCDQEiDQCARBEgJCAAHEAAIqEg7iDSzQLCzBBBcPvgIJSqIkAikEISDABEEUAgMUBJMdYSAgymG0YABkDgYJFgYAQgKTAqJmFl+4oiYCKQIpIMbQSW8v0yRQAABEDg4JFAzMB3AggbVf0CRgIAAAAiRQErVQZz//BghGb2AoazACKu/ypmIYH74GYRaiIoAiJhJiF/+3IhJmpi+AYWhwV3PBzGDQCCISd8w4BhBAwSYCODbQIck4Zb/QDSISRdC5IhJZe93xvdCy0iAgCiISYAHEAAIqGLzCDuIKc84WIhJgwSABZAACKhCyLgIhBgzMAABkDg4JEq/wzix7IChjAAciEl0CfApiICxiUAQTP74CCUQCKQItIPIhIMADIRMCAxlgIBMCkxFkIFJzwChiQAxhIAAAAMo8ezRJFW+3z4AANA4GCRYGAEICgwKiaaIkAikCKSDBtz1oIGK2M9B2e83YYGAIIhJ3zDgGEEDBJgI4NtAhyjxiv9AADSISRdC5IhJZe93iINABs9ABxAACKhIO4gi8wM4t0DxzICBtv/BggAAAAiDQGLPAATQAAyoSINACvdABxAACKhICMgIO4gwswQYQb74CCUYCKQItIPMhIMADMRMCAxloIAMDkxICCExggAgSv7DKR89xs0AARA4ECRQEAEICcwKiSKImAikCKSDE0DliL+AANA4OCRMMzAMSH74CIRKjM4AzJhJjEf+6IhJiojKAIiYSgWCganPB5GDgByISd8w3BhBAwSYCODbQIcs8b3/AAAANIhJF0LgiElh73dG90LLSICAJIhJgAcQAAioYvMIO4glzzhoiEmDBIAGkAAIqFiISgLIuAiECpmAApA4OCRoMzAYmEocen6giEocHXAkiEsMeb6gCfAkCIQOiJyYSk9BSe1AT0CQZ36+jNtDze0bQYSACHH+ixTOWLGbQA8UyHE+n0NOWIMJgZsAF0L0iEkRgAA/QYhkvonteGiISliIShyISxgKsAx0PpwIhAqIyICABuqIkUAomEpG1ULb1Yf/QYMAAAyAgBixv0yRQAyAgEyRQEyAgI7IjJFAjtV9jbjFgYBMgIAMkUAZiYFIgIBIkUBalX9BqKgsHz5gqSwcqEABr3+IaP6KLIH4gIGl/zAICQnPCBGDwCCISd8w4BhBAwSYCODbQIsAwas/AAAXQvSISRGAAD9BpIhJZe92RvdCy0iAgAAHEAAIqGLzCDuIMAgJCc84cAgJAACQODgkXyCIMwQfQ1GAQAAC3fCzPiiISR3ugL2jPEht/oxt/pNDFJhNHJhM7JhNgWVAAsisiE2ciEzUiE0IO4QDA8WLAaGDAAAAIIhJ3zDgGEEDBJgI4NtAiyTBg8AciEkXQuSISWXt+AbdwsnIgIAABxAACKhIO4gi8y2jOTgMHTCzPjg6EEGCgCiISd8w6BhBAwSYCODbQIsoyFm+jliRg8AciEkXQtiISVnt9syBwAbd0Fg+hv/KKSAIhEwIiAppPZPCEbe/wByISRdCyFa+iwjOWIMBoYBAHIhJF0LfPYmFhVLJsxyhgMAAAt3wsz4giEkd7gC9ozxgU/6IX/6MX/6yXhNDFJhNGJhNXJhM4JhMrJhNoWGAIIhMpIhKKIhJgsimeiSISng4hCiaBByITOiISRSITSyITZiITX5+OJoFJJoFaDXwLDFwP0GllYOMWz6+NgtDMV+APDg9E0C8PD1fQwMeGIhNbIhNkYlAAAAkgIAogIC6umSAgHqmZru+v7iAgOampr/mp7iAgSa/5qe4gIFmv+anuICBpr/mp7iAgea/5ru6v+LIjqSRznAQCNBsCKwsJBgRgIAADICABsiOu7q/yo5vQJHM+8xTvotDkJhMWJhNXJhM4JhMrJhNgV2ADFI+u0CLQ+FdQBCITFyITOyITZAd8CCITJBQfpiITX9AoyHLQuwOMDG5v8AAAD/ESEI+urv6dL9BtxW+KLw7sB87+D3g0YCAAAAAAwM3Qzyr/0xNPpSISooI2IhJNAiwNBVwNpm0RD6KSM4DXEP+lJhKspTWQ1wNcAMAgwV8CWDYmEkICB0VoIAQtOAQCWDFpIAwQX6LQzFKQDJDYIhKtHs+Yz4KD0WsgDwLzHwIsDWIgDGhPvWjwAioMcpXQY6AABWTw4oPcwSRlH6IqDIhgAAIqDJKV3GTfooLYwSBkz6Ie75ARv6wAAAAR76wAAAhkf6yD3MHMZF+iKj6AEV+sAAAMAMAAZC+gDiYSIMfEaU+gEV+sAAAAwcDAMGCAAAyC34PfAsICAgtMwSxpv6Ri77Mi0DIi0CRTMAMqAADBwgw4PGKft4fWhtWF1ITTg9KC0MDAH7+cAAAO0CDBLgwpOGJfsAAAH1+cAAAAwMBh/7ACHI+UhdOC1JAiHG+TkCBvr/QcT5DAI4BMKgyDDCgykEQcD5PQwMHCkEMMKDBhP7xzICxvP9xvr9KD0WIvLGF/oCIUOSoRDCIULSIUHiIUDyIT+aEQ3wAAAIAABgHAAAYAAAAGAQAABgIfz/EsHw6QHAIADoAgkxySHZESH4/8AgAMgCwMB0nOzRmvlGBAAAADH0/8AgACgDOA0gIHTAAwALzGYM6ob0/yHv/wgxwCAA6QLIIdgR6AESwRAN8AAAAPgCAGAQAgBgAAIAYAAAAAgh/P/AIAA4AjAwJFZD/yH5/0H6/8AgADkCMff/wCAASQPAIABIA1Z0/8AgACgCDBMgIAQwIjAN8AAAgAAAAABA////AAQCAGASwfDJIcFw+QkxKEzZERaCCEX6/xYiCChMDPMMDSejDCgsMCIQDBMg04PQ0HQQESBF+P8WYv8h3v8x7v/AIAA5AsAgADIiAFZj/zHX/8AgACgDICAkVkL/KCwx5f9AQhEhZfnQMoMh5P8gJBBB5P/AIAApBCHP/8AgADkCwCAAOAJWc/8MEhwD0COT3QIoTNAiwClMKCza0tksCDHIIdgREsEQDfAAAABMSgBAEsHgyWHBRfn5Mfg86UEJcdlR7QL3swH9AxYfBNgc2t/Q3EEGAQAAAIXy/yhMphIEKCwnrfJF7f8Wkv8oHE0PPQ4B7v/AAAAgIHSMMiKgxClcKBxIPPoi8ETAKRxJPAhxyGHYUehB+DESwSAN8AAAAP8PAABRKvkSwfAJMQwUQkUAMExBSSVB+v85FSk1MDC0SiIqIyAsQSlFDAIiZQUBXPnAAAAIMTKgxSAjkxLBEA3wAAAAMDsAQBLB8AkxMqDAN5IRIqDbAfv/wAAAIqDcRgQAAAAAMqDbN5IIAfb/wAAAIqDdAfT/wAAACDESwRAN8AAAABLB8Mkh2REJMc0COtJGAgAAIgwAwswBxfr/15zzAiEDwiEC2BESwRAN8AAAWBAAAHAQAAAYmABAHEsAQDSYAEAAmQBAkfv/EsHgyWHpQfkxCXHZUZARwO0CItEQzQMB9f/AAADx+viGCgDdDMe/Ad0PTQ09AS0OAfD/wAAAICB0/EJNDT0BItEQAez/wAAA0O6A0MzAVhz9IeX/MtEQECKAAef/wAAAIeH/HAMaIgX1/y0MBgEAAAAioGOR3f+aEQhxyGHYUehB+DESwSAN8AASwfAioMAJMQG6/8AAAAgxEsEQDfAAAABsEAAAaBAAAHQQAAB4EAAAfBAAAIAQAACQEAAAmA8AQIw7AEASweCR/P/5Mf0CIcb/yWHZUQlx6UGQEcAaIjkCMfL/LAIaM0kDQfD/0tEQGkTCoABSZADCbRoB8P/AAABh6v8hwPgaZmgGZ7ICxkkALQ0Btv/AAAAhs/8x5f8qQRozSQNGPgAAAGGv/zHf/xpmaAYaM+gDwCbA57ICIOIgYd3/PQEaZlkGTQ7wLyABqP/AAAAx2P8gIHQaM1gDjLIMBEJtFu0ExhIAAAAAQdH/6v8aRFkEBfH/PQ4tAYXj/0Xw/00OPQHQLSABmv/AAABhyf/qzBpmWAYhk/8aIigCJ7y8McL/UCzAGjM4AzeyAkbd/0bq/0KgAEJNbCG5/xAigAG//8AAAFYC/2G5/yINbBBmgDgGRQcA9+IR9k4OQbH/GkTqNCJDABvuxvH/Mq/+N5LBJk4pIXv/0D0gECKAAX7/wAAABej/IXb/HAMaIkXa/0Xn/ywCAav4wAAAhgUAYXH/Ui0aGmZoBme1yFc8AgbZ/8bv/wCRoP+aEQhxyGHYUehB+DESwSAN8F0CQqDAKANHlQ7MMgwShgYADAIpA3ziDfAmEgUmIhHGCwBCoNstBUeVKQwiKQMGCAAioNwnlQgMEikDLQQN8ABCoN188keVCwwSKQMioNsN8AB88g3wAAC2IzBtAlD2QEDzQEe1KVBEwAAUQAAzoQwCNzYEMGbAGyLwIhEwMUELRFbE/jc2ARsiDfAAjJMN8Dc2DAwSDfAAAAAAAERJVjAMAg3wtiMoUPJAQPNAR7UXUETAABRAADOhNzICMCLAMDFBQsT/VgT/NzICMCLADfDMUwAAAERJVjAMAg3wAAAAABRA5sQJIDOBACKhDfAAAAAyoQwCDfAA", + "text": "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", "text_start": 1074843648, - "data": "CIH+PwUFBAACAwcAAwMLALnXEEDv1xBAHdgQQLrYEEBo5xBAHtkQQHTZEEDA2RBAaOcQQILaEED/2hBAwNsQQGjnEEBo5xBAWNwQQGjnEEA33xBAAOAQQDvgEEBo5xBAaOcQQNfgEEBo5xBAv+EQQGXiEECj4xBAY+QQQDTlEEBo5xBAaOcQQGjnEEBo5xBAYuYQQGjnEEBX5xBAkN0QQI/YEECm5RBAq9oQQPzZEEBo5xBA7OYQQDHnEEBo5xBAaOcQQGjnEEBo5xBAaOcQQGjnEEBo5xBAaOcQQCLaEEBf2hBAvuUQQAEAAAACAAAAAwAAAAQAAAAFAAAABwAAAAkAAAANAAAAEQAAABkAAAAhAAAAMQAAAEEAAABhAAAAgQAAAMEAAAABAQAAgQEAAAECAAABAwAAAQQAAAEGAAABCAAAAQwAAAEQAAABGAAAASAAAAEwAAABQAAAAWAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAEAAAABAAAAAgAAAAIAAAADAAAAAwAAAAQAAAAEAAAABQAAAAUAAAAGAAAABgAAAAcAAAAHAAAACAAAAAgAAAAJAAAACQAAAAoAAAAKAAAACwAAAAsAAAAMAAAADAAAAA0AAAANAAAAAAAAAAAAAAADAAAABAAAAAUAAAAGAAAABwAAAAgAAAAJAAAACgAAAAsAAAANAAAADwAAABEAAAATAAAAFwAAABsAAAAfAAAAIwAAACsAAAAzAAAAOwAAAEMAAABTAAAAYwAAAHMAAACDAAAAowAAAMMAAADjAAAAAgEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABAAAAAQAAAAEAAAABAAAAAgAAAAIAAAACAAAAAgAAAAMAAAADAAAAAwAAAAMAAAAEAAAABAAAAAQAAAAEAAAABQAAAAUAAAAFAAAABQAAAAAAAAAAAAAAAAAAABAREgAIBwkGCgULBAwDDQIOAQ8AAQEAAAEAAAAEAAAA", + "data": "CIH+PwUFBAACAwcAAwMLANTXEEAL2BBAOdgQQNbYEECF5xBAOtkQQJDZEEDc2RBAhecQQKLaEEAf2xBA4NsQQIXnEECF5xBAeNwQQIXnEEBV3xBAHOAQQFfgEECF5xBAhecQQPPgEECF5xBA2+EQQIHiEEDA4xBAf+QQQFDlEECF5xBAhecQQIXnEECF5xBAfuYQQIXnEEB05xBAsN0QQKnYEEDC5RBAydoQQBvaEECF5xBACOcQQE/nEECF5xBAhecQQIXnEECF5xBAhecQQIXnEECF5xBAhecQQELaEEB/2hBA2uUQQAEAAAACAAAAAwAAAAQAAAAFAAAABwAAAAkAAAANAAAAEQAAABkAAAAhAAAAMQAAAEEAAABhAAAAgQAAAMEAAAABAQAAgQEAAAECAAABAwAAAQQAAAEGAAABCAAAAQwAAAEQAAABGAAAASAAAAEwAAABQAAAAWAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAEAAAABAAAAAgAAAAIAAAADAAAAAwAAAAQAAAAEAAAABQAAAAUAAAAGAAAABgAAAAcAAAAHAAAACAAAAAgAAAAJAAAACQAAAAoAAAAKAAAACwAAAAsAAAAMAAAADAAAAA0AAAANAAAAAAAAAAAAAAADAAAABAAAAAUAAAAGAAAABwAAAAgAAAAJAAAACgAAAAsAAAANAAAADwAAABEAAAATAAAAFwAAABsAAAAfAAAAIwAAACsAAAAzAAAAOwAAAEMAAABTAAAAYwAAAHMAAACDAAAAowAAAMMAAADjAAAAAgEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABAAAAAQAAAAEAAAABAAAAAgAAAAIAAAACAAAAAgAAAAMAAAADAAAAAwAAAAMAAAAEAAAABAAAAAQAAAAEAAAABQAAAAUAAAAFAAAABQAAAAAAAAAAAAAAAAAAABAREgAIBwkGCgULBAwDDQIOAQ8AAQEAAAEAAAAEAAAA", "data_start": 1073720488 } \ No newline at end of file diff --git a/esptool/uf2_writer.py b/esptool/uf2_writer.py new file mode 100644 index 000000000..554c8450c --- /dev/null +++ b/esptool/uf2_writer.py @@ -0,0 +1,96 @@ +#!/usr/bin/env python +# +# SPDX-FileCopyrightText: 2020-2023 Espressif Systems (Shanghai) CO LTD +# SPDX-License-Identifier: GPL-2.0-or-later +# Code was originally licensed under Apache 2.0 before the release of ESP-IDF v5.2 + +import hashlib +import os +import struct +from typing import List + +from esptool.util import div_roundup + + +class UF2Writer(object): + # The UF2 format is described here: https://github.com/microsoft/uf2 + UF2_BLOCK_SIZE = 512 + # max value of CHUNK_SIZE reduced by optional parts. Currently, MD5_PART only. + UF2_DATA_SIZE = 476 + UF2_MD5_PART_SIZE = 24 + UF2_FIRST_MAGIC = 0x0A324655 + UF2_SECOND_MAGIC = 0x9E5D5157 + UF2_FINAL_MAGIC = 0x0AB16F30 + UF2_FLAG_FAMILYID_PRESENT = 0x00002000 + UF2_FLAG_MD5_PRESENT = 0x00004000 + + def __init__( + self, + chip_id: int, + output_file: os.PathLike, + chunk_size: int, + md5_enabled: bool = True, + ) -> None: + if not md5_enabled: + self.UF2_MD5_PART_SIZE = 0 + self.UF2_FLAG_MD5_PRESENT = 0x00000000 + self.md5_enabled = md5_enabled + self.chip_id = chip_id + self.CHUNK_SIZE = ( + self.UF2_DATA_SIZE - self.UF2_MD5_PART_SIZE + if chunk_size is None + else chunk_size + ) + self.f = open(output_file, "wb") + + def __enter__(self) -> "UF2Writer": + return self + + def __exit__(self, exc_type: str, exc_val: int, exc_tb: List) -> None: + if self.f: + self.f.close() + + @staticmethod + def _to_uint32(num: int) -> bytes: + return struct.pack(" None: + assert len_chunk > 0 + assert len_chunk <= self.CHUNK_SIZE + assert block_no < blocks + block = struct.pack( + " None: + blocks = div_roundup(len(image), self.CHUNK_SIZE) + chunks = [ + image[i : i + self.CHUNK_SIZE] + for i in range(0, len(image), self.CHUNK_SIZE) + ] + for i, chunk in enumerate(chunks): + len_chunk = len(chunk) + self._write_block(addr, chunk, len_chunk, i, blocks) + addr += len_chunk diff --git a/esptool/util.py b/esptool/util.py index 66d9bd45e..ecd41c0d9 100644 --- a/esptool/util.py +++ b/esptool/util.py @@ -3,6 +3,7 @@ # # SPDX-License-Identifier: GPL-2.0-or-later +import os import re import struct import sys @@ -33,6 +34,8 @@ def flash_size_bytes(size): """Given a flash size of the type passed in args.flash_size (ie 512KB or 1MB) then return the size in bytes. """ + if size is None: + return None if "MB" in size: return int(size[: size.index("MB")]) * 1024 * 1024 elif "KB" in size: @@ -65,7 +68,7 @@ def print_overwrite(message, last_line=False): If output is not a TTY (for example redirected a pipe), no overwriting happens and this function is the same as print(). """ - if sys.stdout.isatty(): + if hasattr(sys.stdout, "isatty") and sys.stdout.isatty(): print("\r%s" % message, end="\n" if last_line else "") else: print(message) @@ -87,6 +90,15 @@ def strip_chip_name(chip_name): return re.sub(r"[-()]", "", chip_name.lower()) +def get_file_size(path_to_file): + """Returns the file size in bytes""" + file_size = 0 + with open(path_to_file, "rb") as f: + f.seek(0, os.SEEK_END) + file_size = f.tell() + return file_size + + class FatalError(RuntimeError): """ Wrapper class for runtime errors that aren't caused by internal bugs, but by diff --git a/flasher_stub/Makefile b/flasher_stub/Makefile index 934f8574a..8f4948c50 100644 --- a/flasher_stub/Makefile +++ b/flasher_stub/Makefile @@ -1,7 +1,7 @@ # Makefile to compile the flasher stub program # # Note that YOU DO NOT NEED TO COMPILE THIS IN ORDER TO JUST USE -# esptool.py - a precompiled version is embedded in esptool.py, +# esptool.py - a precompiled version is included in esptool.py, # so if you don't want to modify the stub code then you are good to go. # # See the comments in the top of the Makefile for parameters that @@ -38,6 +38,10 @@ CROSS_32S2 ?= xtensa-esp32s2-elf- CROSS_32S3 ?= xtensa-esp32s3-elf- CROSS_ESPRISCV32 ?= riscv32-esp-elf- +# extra CFLAGS to be passed on the compiler, in addition to the stock ones +EXTRA_CFLAGS ?= +EXTRA_CFLAGS_ESPRISCV32 ?= + # Python command to invoke wrap_stub.py WRAP_STUB ?= ./wrap_stub.py @@ -65,27 +69,60 @@ STUB_ELF_32H2_BETA_2 = $(BUILD_DIR)/$(STUB)_32h2beta2.elf STUB_ELF_32C2 = $(BUILD_DIR)/$(STUB)_32c2.elf STUB_ELF_32C6 = $(BUILD_DIR)/$(STUB)_32c6.elf STUB_ELF_32H2 = $(BUILD_DIR)/$(STUB)_32h2.elf +STUB_ELF_32P4 = $(BUILD_DIR)/$(STUB)_32p4.elf -.PHONY: all esp32 clean embed embed_esp32 +STUBS_ELF = +ifneq ($(WITHOUT_ESP8266),1) +STUBS_ELF += \ + $(STUB_ELF_8266) +endif -all: $(STUB_ELF_8266) $(STUB_ELF_32) $(STUB_ELF_32S2) $(STUB_ELF_32S3_BETA_2) $(STUB_ELF_32S3) $(STUB_ELF_32C3) $(STUB_ELF_32C6BETA) $(STUB_ELF_32H2_BETA_1) $(STUB_ELF_32H2_BETA_2) $(STUB_ELF_32C2) $(STUB_ELF_32C6) $(STUB_ELF_32H2) - @echo " WRAP $^ -> $(BUILD_DIR)" - $(Q) $(WRAP_STUB) $^ +ifneq ($(WITHOUT_ESP32_XTENSA),1) +STUBS_ELF += \ + $(STUB_ELF_32) \ + $(STUB_ELF_32S2) \ + $(STUB_ELF_32S3_BETA_2) \ + $(STUB_ELF_32S3) +endif -esp32: $(STUB_ELF_32) $(STUB_ELF_32S2) $(STUB_ELF_32S3_BETA_2) $(STUB_ELF_32S3) $(STUB_ELF_32C3) $(STUB_ELF_32C6BETA) $(STUB_ELF_32H2_BETA_1) $(STUB_ELF_32H2_BETA_2) $(STUB_ELF_32C2) $(STUB_ELF_32C6) $(STUB_ELF_32H2) - @echo " WRAP $^ -> $(BUILD_DIR)" - $(Q) $(WRAP_STUB) $^ +ifneq ($(WITHOUT_ESP32_RISCV32),1) +STUBS_ELF += \ + $(STUB_ELF_32C3) \ + $(STUB_ELF_32C6BETA) \ + $(STUB_ELF_32H2_BETA_1) \ + $(STUB_ELF_32H2_BETA_2) \ + $(STUB_ELF_32C2) \ + $(STUB_ELF_32C6) \ + $(STUB_ELF_32H2) \ + $(STUB_ELF_32P4) +endif + +.PHONY: all clean install + +all: $(STUBS_ELF:.elf=.json) + +install: $(patsubst $(BUILD_DIR)/%.elf,$(ESPTOOL_STUBS_DIR)/%.json,$(STUBS_ELF)) $(BUILD_DIR): $(Q) mkdir $@ +$(BUILD_DIR)/%.json: $(BUILD_DIR)/%.elf + @echo " WRAP $^ -> $(BUILD_DIR)" + $(Q) $(WRAP_STUB) $^ + +$(ESPTOOL_STUBS_DIR)/%.json: $(BUILD_DIR)/%.json + @echo " INSTALL $^ -> $@" + $(Q) cp $^ $@ + CFLAGS = -std=c99 -Wall -Werror -Os \ -mtext-section-literals -mlongcalls -nostdlib -fno-builtin -flto \ - -Wl,-static -g -ffunction-sections -Wl,--gc-sections -Iinclude -Lld + -Wl,-static -g -ffunction-sections -Wl,--gc-sections -Iinclude -Lld \ + $(EXTRA_CFLAGS) CFLAGS_ESPRISCV32 = -std=c99 -Wall -Werror -Os \ - -march=rv32imc -msmall-data-limit=0 \ + -march=rv32imc -mabi=ilp32 -msmall-data-limit=0 \ -nostdlib -fno-builtin -flto \ - -Wl,-static -g -ffunction-sections -Wl,--gc-sections -Iinclude -Lld + -Wl,-static -g -ffunction-sections -Wl,--gc-sections -Iinclude -Lld \ + $(EXTRA_CFLAGS_ESPRISCV32) LDLIBS = -lgcc $(STUB_ELF_8266): $(SRCS) $(SRCS_8266) $(BUILD_DIR) ld/stub_8266.ld | Makefile @@ -136,13 +173,9 @@ $(STUB_ELF_32H2): $(SRCS) $(BUILD_DIR) ld/stub_32h2.ld @echo " CC(32H2) $^ -> $@" $(Q) $(CROSS_ESPRISCV32)gcc $(CFLAGS_ESPRISCV32) -DESP32H2=1 -Tstub_32h2.ld -Wl,-Map=$(@:.elf=.map) -o $@ $(filter %.c, $^) $(LDLIBS) -embed: $(STUB_ELF_8266) $(STUB_ELF_32) $(STUB_ELF_32S2) $(STUB_ELF_32S3_BETA_2) $(STUB_ELF_32S3) $(STUB_ELF_32C3) $(STUB_ELF_32C6BETA) $(STUB_ELF_32H2_BETA_1) $(STUB_ELF_32H2_BETA_2) $(STUB_ELF_32C2) $(STUB_ELF_32C6) $(STUB_ELF_32H2) - @echo " WRAP $^ -> $(ESPTOOL_STUBS_DIR)" - $(Q) $(WRAP_STUB) --embed $^ - -embed_esp32: $(STUB_ELF_32) $(STUB_ELF_32S2) $(STUB_ELF_32S3_BETA_2) $(STUB_ELF_32S3) $(STUB_ELF_32C3) $(STUB_ELF_32C6BETA) $(STUB_ELF_32H2_BETA_1) $(STUB_ELF_32H2_BETA_2) $(STUB_ELF_32C2) $(STUB_ELF_32C6) $(STUB_ELF_32H2) - @echo " WRAP $^ -> $(ESPTOOL_STUBS_DIR)" - $(Q) $(WRAP_STUB) --embed $^ +$(STUB_ELF_32P4): $(SRCS) $(BUILD_DIR) ld/stub_32p4.ld + @echo " CC(32P4) $^ -> $@" + $(Q) $(CROSS_ESPRISCV32)gcc $(CFLAGS_ESPRISCV32) -DESP32P4=1 -Tstub_32p4.ld -Wl,-Map=$(@:.elf=.map) -o $@ $(filter %.c, $^) $(LDLIBS) clean: $(Q) rm -rf $(BUILD_DIR) diff --git a/flasher_stub/README.md b/flasher_stub/README.md index 5b7f4e2cf..052909c3f 100644 --- a/flasher_stub/README.md +++ b/flasher_stub/README.md @@ -28,13 +28,13 @@ If you want to build the stub to test modifications or updates, here's how: * Set any other environment variables you'd like to override in the Makefile. -* To build type `make`. To build only for the ESP32 family, type `make esp32` (this negates the need of an ESP8266 toolchain). +* To build type `make`. To build only for the ESP32 family, type `make WITHOUT_ESP8266=1` (this negates the need of an ESP8266 toolchain). Activating an ESP-IDF environment takes care of most of these steps (only the ESP8266 gcc toolchain has to be manually added to PATH). # To Test -To test the built stub, you can run `make embed` (or `make embed_esp32`), which will update the stubs in `esptool.py` to the newly compiled ones. Or there are some convenience wrappers to make testing quicker to iterate on: +To test the built stub, you can run `make install` (or `make install WITHOUT_ESP8266=1`), which will update the stubs in `esptool.py` to the newly compiled ones. Or there are some convenience wrappers to make testing quicker to iterate on: * Running `esptool_test_stub.py` is the same as running `esptool.py`, only it uses the just-compiled stubs from the build directory. diff --git a/flasher_stub/include/rom_functions.h b/flasher_stub/include/rom_functions.h index 84a920344..6259dae88 100644 --- a/flasher_stub/include/rom_functions.h +++ b/flasher_stub/include/rom_functions.h @@ -107,6 +107,10 @@ SpiFlashOpResult SPI_Encrypt_Write(uint32_t flash_addr, const void* data, uint32 #if ESP32S2_OR_LATER uint32_t GetSecurityInfoProc(int* pMsg, int* pnErr, uint8_t *buf); // pMsg and pnErr unused in ROM +#if ESP32C3 +extern uint32_t _rom_eco_version; // rom constant to define ECO version +uint32_t GetSecurityInfoProcNewEco(int* pMsg, int* pnErr, uint8_t *buf); // GetSecurityInfo for C3 ECO7+ +#endif // ESP32C3 SpiFlashOpResult SPI_read_status_high(esp_rom_spiflash_chip_t *spi, uint32_t *status); #else /* Note: On ESP32 this was a static function whose first argument was elided by the diff --git a/flasher_stub/include/soc_support.h b/flasher_stub/include/soc_support.h index db3739be4..f57a740dc 100644 --- a/flasher_stub/include/soc_support.h +++ b/flasher_stub/include/soc_support.h @@ -55,11 +55,24 @@ #define IS_RISCV 1 #endif // ESP32H2 +#ifdef ESP32P4 +// TODO: Add support for USB modes when MP is available +// #define WITH_USB_JTAG_SERIAL 1 +// #define WITH_USB_OTG 1 +#define IS_RISCV 1 +#endif // ESP32P4 + // Increase CPU freq to speed up read/write operations over USB -#define USE_MAX_CPU_FREQ (WITH_USB_JTAG_SERIAL || WITH_USB_OTG) +// Disabled on the S3 due to stability issues, would require dbias adjustment. +// https://github.com/espressif/esptool/issues/832, https://github.com/espressif/esptool/issues/808 +#define USE_MAX_CPU_FREQ ((WITH_USB_JTAG_SERIAL || WITH_USB_OTG) && !ESP32S3) + +// Later chips don't support ets_efuse_get_spiconfig. +#define SUPPORT_CONFIG_SPI (ESP32 || ESP32S2 || ESP32S3 || ESP32S3BETA2 || ESP32C3 || ESP32H2BETA1 || ESP32H2BETA2 || ESP32C6BETA) /********************************************************** * Per-SOC based peripheral register base addresses + * Sync with reg_base.h in ESP-IDF */ #ifdef ESP8266 #define UART_BASE_REG 0x60000000 /* UART0 */ @@ -153,6 +166,13 @@ #define DR_REG_LP_WDT_BASE 0x600B1C00 #endif +#ifdef ESP32P4 +#define UART_BASE_REG 0x500CA000 /* UART0 */ +#define SPI_BASE_REG 0x5008D000 /* SPI peripheral 1, used for SPI flash */ +#define SPI0_BASE_REG 0x5008C000 /* SPI peripheral 0, inner state machine */ +#define GPIO_BASE_REG 0x500E0000 +#endif + /********************************************************** * UART peripheral * @@ -323,23 +343,39 @@ #ifdef ESP32S3 #define RTC_CNTL_OPTION1_REG (RTCCNTL_BASE_REG + 0x012C) -#define RTC_CNTL_WDTCONFIG0_REG (RTCCNTL_BASE_REG + 0x0090) // RTC_CNTL_RTC_WDTCONFIG0_REG +#define RTC_CNTL_WDTCONFIG0_REG (RTCCNTL_BASE_REG + 0x0098) // RTC_CNTL_RTC_WDTCONFIG0_REG #define RTC_CNTL_WDTWPROTECT_REG (RTCCNTL_BASE_REG + 0x00B0) // RTC_CNTL_RTC_WDTWPROTECT_REG +#define RTC_CNTL_SWD_CONF_REG (RTCCNTL_BASE_REG + 0x00B4) +#define RTC_CNTL_SWD_WPROTECT_REG (RTCCNTL_BASE_REG + 0x00B8) +#define RTC_CNTL_SWD_WKEY 0x8F1D312A +#define RTC_CNTL_SWD_AUTO_FEED_EN (1 << 31) #endif #ifdef ESP32C3 #define RTC_CNTL_WDTCONFIG0_REG (RTCCNTL_BASE_REG + 0x0090) #define RTC_CNTL_WDTWPROTECT_REG (RTCCNTL_BASE_REG + 0x00A8) +#define RTC_CNTL_SWD_CONF_REG (RTCCNTL_BASE_REG + 0x00AC) +#define RTC_CNTL_SWD_WPROTECT_REG (RTCCNTL_BASE_REG + 0x00B0) +#define RTC_CNTL_SWD_WKEY 0x8F1D312A +#define RTC_CNTL_SWD_AUTO_FEED_EN (1 << 31) #endif #ifdef ESP32C6 #define RTC_CNTL_WDTCONFIG0_REG (DR_REG_LP_WDT_BASE + 0x0) // LP_WDT_RWDT_CONFIG0_REG #define RTC_CNTL_WDTWPROTECT_REG (DR_REG_LP_WDT_BASE + 0x0018) // LP_WDT_RWDT_WPROTECT_REG +#define RTC_CNTL_SWD_CONF_REG (DR_REG_LP_WDT_BASE + 0x001C) // LP_WDT_SWD_CONFIG_REG +#define RTC_CNTL_SWD_WPROTECT_REG (DR_REG_LP_WDT_BASE + 0x0020) // LP_WDT_SWD_WPROTECT_REG +#define RTC_CNTL_SWD_WKEY 0x50D83AA1 +#define RTC_CNTL_SWD_AUTO_FEED_EN (1 << 18) #endif #ifdef ESP32H2 #define RTC_CNTL_WDTCONFIG0_REG (DR_REG_LP_WDT_BASE + 0x0) // LP_WDT_RWDT_CONFIG0_REG -#define RTC_CNTL_WDTWPROTECT_REG (DR_REG_LP_WDT_BASE + 0x0018) // LP_WDT_RWDT_WPROTECT_REG +#define RTC_CNTL_WDTWPROTECT_REG (DR_REG_LP_WDT_BASE + 0x001C) // LP_WDT_RWDT_WPROTECT_REG +#define RTC_CNTL_SWD_CONF_REG (DR_REG_LP_WDT_BASE + 0x0020) // LP_WDT_SWD_CONFIG_REG +#define RTC_CNTL_SWD_WPROTECT_REG (DR_REG_LP_WDT_BASE + 0x0024) // LP_WDT_SWD_WPROTECT_REG +#define RTC_CNTL_SWD_WKEY 0x50D83AA1 +#define RTC_CNTL_SWD_AUTO_FEED_EN (1 << 18) #endif #define RTC_CNTL_WDT_WKEY 0x50D83AA1 @@ -349,20 +385,6 @@ * SYSTEM registers */ -#ifdef ESP32S3 -#define SYSTEM_CPU_PER_CONF_REG (SYSTEM_BASE_REG + 0x010) -#define SYSTEM_CPUPERIOD_SEL_M ((SYSTEM_CPUPERIOD_SEL_V)<<(SYSTEM_CPUPERIOD_SEL_S)) -#define SYSTEM_CPUPERIOD_SEL_V 0x3 -#define SYSTEM_CPUPERIOD_SEL_S 0 -#define SYSTEM_CPUPERIOD_MAX 2 // CPU_CLK frequency is 240 MHz - -#define SYSTEM_SYSCLK_CONF_REG (SYSTEM_BASE_REG + 0x060) -#define SYSTEM_SOC_CLK_SEL_M ((SYSTEM_SOC_CLK_SEL_V)<<(SYSTEM_SOC_CLK_SEL_S)) -#define SYSTEM_SOC_CLK_SEL_V 0x3 -#define SYSTEM_SOC_CLK_SEL_S 10 -#define SYSTEM_SOC_CLK_MAX 1 -#endif // ESP32S3 - #ifdef ESP32C3 #define SYSTEM_CPU_PER_CONF_REG (SYSTEM_BASE_REG + 0x008) #define SYSTEM_CPUPERIOD_SEL_M ((SYSTEM_CPUPERIOD_SEL_V)<<(SYSTEM_CPUPERIOD_SEL_S)) @@ -418,3 +440,28 @@ #if ESP32S3_OR_LATER #define SECURITY_INFO_BYTES 20 #endif // ESP32S3_OR_LATER + +/********************************************************** + * Per-SOC address of the rom_spiflash_legacy_funcs symbol in ROM + * Can be retrieved with gdb: "info address rom_spiflash_legacy_funcs" + */ + +#if ESP32 || ESP32S2 || ESP32S3 +#define ROM_SPIFLASH_LEGACY 0x3ffae270 +#endif // ESP32 || ESP32S2 || ESP32S3 + +#if ESP32C3 || ESP32C6BETA || ESP32C2 || ESP32C6 +#define ROM_SPIFLASH_LEGACY 0x3fcdfff4 +#endif // ESP32C3 || ESP32C6BETA || ESP32C2 || ESP32C6 + +#if ESP32H2BETA1 || ESP32H2BETA2 +#define ROM_SPIFLASH_LEGACY 0x3fcdfff0 +#endif // ESP32H2BETA1 || ESP32H2BETA2 + +#if ESP32H2 +#define ROM_SPIFLASH_LEGACY 0x4084fff0 +#endif // ESP32H2 + +#if ESP32P4 +#define ROM_SPIFLASH_LEGACY 0x4ff3ffec +#endif // ESP32P4 diff --git a/flasher_stub/include/stub_flasher.h b/flasher_stub/include/stub_flasher.h index 79b8a24d8..3cf1f6310 100644 --- a/flasher_stub/include/stub_flasher.h +++ b/flasher_stub/include/stub_flasher.h @@ -6,9 +6,8 @@ * SPDX-FileContributor: 2016-2022 Espressif Systems (Shanghai) CO LTD */ -#ifndef STUB_FLASHER_H_ -#define STUB_FLASHER_H_ - +#pragma once +#include #include /* Maximum write block size, used for various buffers. */ @@ -22,8 +21,9 @@ #define SECTORS_PER_BLOCK (FLASH_BLOCK_SIZE / FLASH_SECTOR_SIZE) /* 32-bit addressing is supported only by ESP32S3 */ -#if defined(ESP32S3) +#if defined(ESP32S3) && !defined(ESP32S3BETA2) #define FLASH_MAX_SIZE 64*1024*1024 +extern bool large_flash_mode; #else #define FLASH_MAX_SIZE 16*1024*1024 #endif @@ -108,5 +108,3 @@ typedef enum { ESP_CMD_NOT_IMPLEMENTED = 0xFF, } esp_command_error; - -#endif /* STUB_FLASHER_H_ */ diff --git a/flasher_stub/ld/rom_32c3.ld b/flasher_stub/ld/rom_32c3.ld index 40f112d41..ecaaf4928 100755 --- a/flasher_stub/ld/rom_32c3.ld +++ b/flasher_stub/ld/rom_32c3.ld @@ -67,6 +67,7 @@ send_packet = 0x400000a8; recv_packet = 0x400000ac; GetUartDevice = 0x400000b0; GetSecurityInfoProc = 0x4004b9da; +GetSecurityInfoProcNewEco = 0x4004d51e; /* manually added from esp32c3eco7-20230720; new address of function for eco7+ */ UartDwnLdProc = 0x400000b4; Uart_Init = 0x400000b8; ets_set_user_start = 0x400000bc; @@ -2197,4 +2198,3 @@ _global_impure_ptr = 0x3fcdffdc; */ _rom_chip_id = 0x40000010; _rom_eco_version = 0x40000014; - diff --git a/flasher_stub/ld/rom_32h2.ld b/flasher_stub/ld/rom_32h2.ld index b736e491b..accb0adcf 100755 --- a/flasher_stub/ld/rom_32h2.ld +++ b/flasher_stub/ld/rom_32h2.ld @@ -1,8 +1,3 @@ -/* - * SPDX-FileCopyrightText: 2022 Espressif Systems (Shanghai) CO LTD - * - * SPDX-License-Identifier: GPL-2.0-or-later - */ /* ROM function interface esp32h2.rom.ld for esp32h2 * * @@ -22,7 +17,7 @@ PROVIDE ( SPI_read_status_high = esp_rom_spiflash_read_statushigh); PROVIDE ( SPI_write_status = esp_rom_spiflash_write_status); PROVIDE ( SPIRead = esp_rom_spiflash_read); PROVIDE ( SPIParamCfg = esp_rom_spiflash_config_param); -PROVIDE ( SPIEraseChip = esp_rom_spiflash_erase_chip); +PROVIDE ( SPIEraseChip = esp_rom_spiflash_erase_chip); PROVIDE ( SPIEraseSector = esp_rom_spiflash_erase_sector); PROVIDE ( SPIEraseBlock = esp_rom_spiflash_erase_block); PROVIDE ( SPI_Write_Encrypt_Enable = esp_rom_spiflash_write_encrypted_enable); diff --git a/flasher_stub/ld/rom_32p4.ld b/flasher_stub/ld/rom_32p4.ld new file mode 100644 index 000000000..51ac8cded --- /dev/null +++ b/flasher_stub/ld/rom_32p4.ld @@ -0,0 +1,619 @@ +/* ROM function interface esp32p4.rom.ld for esp32p4 + * + * + * Generated from ./target/esp32p4/interface-esp32p4.yml md5sum f6516bd9708d890f63db87f8aed53ca7 + * + * Compatible with ROM where ECO version equal or greater to 0. + * + * THIS FILE WAS AUTOMATICALLY GENERATED. DO NOT EDIT. + */ + +/*************************************** + Group common + ***************************************/ + +PROVIDE ( SPIWrite = esp_rom_spiflash_write); +PROVIDE ( SPI_read_status_high = esp_rom_spiflash_read_statushigh); +PROVIDE ( SPI_write_status = esp_rom_spiflash_write_status); +PROVIDE ( SPIRead = esp_rom_spiflash_read); +PROVIDE ( SPIParamCfg = esp_rom_spiflash_config_param); +PROVIDE ( SPIEraseChip = esp_rom_spiflash_erase_chip); +PROVIDE ( SPIEraseSector = esp_rom_spiflash_erase_sector); +PROVIDE ( SPIEraseBlock = esp_rom_spiflash_erase_block); +PROVIDE ( SPI_Write_Encrypt_Enable = esp_rom_spiflash_write_encrypted_enable); +PROVIDE ( SPI_Write_Encrypt_Disable = esp_rom_spiflash_write_encrypted_disable); +PROVIDE ( SPI_Encrypt_Write = esp_rom_spiflash_write_encrypted); + +/*************************************** + Group common + ***************************************/ + +/* Functions */ +rtc_get_reset_reason = 0x4fc00018; +rtc_get_wakeup_cause = 0x4fc0001c; +pmu_enable_unhold_pads = 0x4fc00020; +ets_printf = 0x4fc00024; +ets_install_putc1 = 0x4fc00028; +ets_install_putc2 = 0x4fc0002c; +ets_install_uart_printf = 0x4fc00030; +ets_install_usb_printf = 0x4fc00034; +ets_get_printf_channel = 0x4fc00038; +ets_delay_us = 0x4fc0003c; +ets_get_cpu_frequency = 0x4fc00040; +ets_update_cpu_frequency = 0x4fc00044; +ets_install_lock = 0x4fc00048; +UartRxString = 0x4fc0004c; +UartGetCmdLn = 0x4fc00050; +uart_tx_one_char = 0x4fc00054; +uart_tx_one_char2 = 0x4fc00058; +uart_tx_one_char3 = 0x4fc0005c; +uart_rx_one_char = 0x4fc00060; +uart_rx_one_char_block = 0x4fc00064; +uart_rx_intr_handler = 0x4fc00068; +uart_rx_readbuff = 0x4fc0006c; +uartAttach = 0x4fc00070; +uart_tx_flush = 0x4fc00074; +uart_tx_wait_idle = 0x4fc00078; +uart_div_modify = 0x4fc0007c; +ets_write_char_uart = 0x4fc00080; +uart_tx_switch = 0x4fc00084; +uart_buff_switch = 0x4fc00088; +roundup2 = 0x4fc0008c; +multofup = 0x4fc00090; +software_reset = 0x4fc00094; +software_reset_cpu = 0x4fc00098; +ets_clk_assist_debug_clock_enable = 0x4fc0009c; +clear_super_wdt_reset_flag = 0x4fc000a0; +disable_default_watchdog = 0x4fc000a4; +ets_set_appcpu_boot_addr = 0x4fc000a8; +send_packet = 0x4fc000ac; +recv_packet = 0x4fc000b0; +GetUartDevice = 0x4fc000b4; +UartDwnLdProc = 0x4fc000b8; +GetSecurityInfoProc = 0x4fc000bc; +Uart_Init = 0x4fc000c0; +ets_set_user_start = 0x4fc000c4; +/* Data (.data, .bss, .rodata) */ +ets_rom_layout_p = 0x4fc1fffc; +ets_ops_table_ptr = 0x4ff3fff4; +g_saved_pc = 0x4ff3fff8; + + +/*************************************** + Group miniz + ***************************************/ + +/* Functions */ +mz_adler32 = 0x4fc000c8; +mz_free = 0x4fc000cc; +tdefl_compress = 0x4fc000d0; +tdefl_compress_buffer = 0x4fc000d4; +tdefl_compress_mem_to_heap = 0x4fc000d8; +tdefl_compress_mem_to_mem = 0x4fc000dc; +tdefl_compress_mem_to_output = 0x4fc000e0; +tdefl_get_adler32 = 0x4fc000e4; +tdefl_get_prev_return_status = 0x4fc000e8; +tdefl_init = 0x4fc000ec; +tdefl_write_image_to_png_file_in_memory = 0x4fc000f0; +tdefl_write_image_to_png_file_in_memory_ex = 0x4fc000f4; +tinfl_decompress = 0x4fc000f8; +tinfl_decompress_mem_to_callback = 0x4fc000fc; +tinfl_decompress_mem_to_heap = 0x4fc00100; +tinfl_decompress_mem_to_mem = 0x4fc00104; + + +/*************************************** + Group spi_extmem_common + ***************************************/ + +/* Functions */ +esp_rom_spi_cmd_config = 0x4fc00108; +esp_rom_spi_cmd_start = 0x4fc0010c; +esp_rom_spi_set_op_mode = 0x4fc00110; +esp_rom_spi_set_dtr_swap_mode = 0x4fc00114; + + +/*************************************** + Group spiflash_legacy + ***************************************/ + +/* Functions */ +esp_rom_spiflash_wait_idle = 0x4fc00118; +esp_rom_spiflash_write_encrypted = 0x4fc0011c; +esp_rom_spiflash_write_encrypted_dest = 0x4fc00120; +esp_rom_spiflash_write_encrypted_enable = 0x4fc00124; +esp_rom_spiflash_write_encrypted_disable = 0x4fc00128; +esp_rom_spiflash_erase_chip = 0x4fc0012c; +_esp_rom_spiflash_erase_sector = 0x4fc00130; +_esp_rom_spiflash_erase_block = 0x4fc00134; +_esp_rom_spiflash_write = 0x4fc00138; +_esp_rom_spiflash_read = 0x4fc0013c; +_esp_rom_spiflash_unlock = 0x4fc00140; +_SPIEraseArea = 0x4fc00144; +_SPI_write_enable = 0x4fc00148; +esp_rom_spiflash_erase_sector = 0x4fc0014c; +esp_rom_spiflash_erase_block = 0x4fc00150; +esp_rom_spiflash_write = 0x4fc00154; +esp_rom_spiflash_read = 0x4fc00158; +esp_rom_spiflash_unlock = 0x4fc0015c; +SPIEraseArea = 0x4fc00160; +SPI_write_enable = 0x4fc00164; +esp_rom_spiflash_config_param = 0x4fc00168; +esp_rom_spiflash_read_user_cmd = 0x4fc0016c; +esp_rom_spiflash_select_qio_pins = 0x4fc00170; +esp_rom_spi_flash_auto_sus_res = 0x4fc00174; +esp_rom_spi_flash_send_resume = 0x4fc00178; +esp_rom_spi_flash_update_id = 0x4fc0017c; +esp_rom_spiflash_config_clk = 0x4fc00180; +esp_rom_spiflash_config_readmode = 0x4fc00184; +esp_rom_spiflash_read_status = 0x4fc00188; +esp_rom_spiflash_read_statushigh = 0x4fc0018c; +esp_rom_spiflash_write_status = 0x4fc00190; +esp_rom_spiflash_write_disable = 0x4fc00194; +spi_cache_mode_switch = 0x4fc00198; +spi_common_set_dummy_output = 0x4fc0019c; +spi_common_set_flash_cs_timing = 0x4fc001a0; +esp_rom_spi_set_address_bit_len = 0x4fc001a4; +SPILock = 0x4fc001a8; +SPIMasterReadModeCnfig = 0x4fc001ac; +SPI_Common_Command = 0x4fc001b0; +SPI_WakeUp = 0x4fc001b4; +SPI_block_erase = 0x4fc001b8; +SPI_chip_erase = 0x4fc001bc; +SPI_init = 0x4fc001c0; +SPI_page_program = 0x4fc001c4; +SPI_read_data = 0x4fc001c8; +SPI_sector_erase = 0x4fc001cc; +SelectSpiFunction = 0x4fc001d0; +SetSpiDrvs = 0x4fc001d4; +Wait_SPI_Idle = 0x4fc001d8; +spi_dummy_len_fix = 0x4fc001dc; +Disable_QMode = 0x4fc001e0; +Enable_QMode = 0x4fc001e4; +spi_flash_attach = 0x4fc001e8; +spi_flash_get_chip_size = 0x4fc001ec; +spi_flash_guard_set = 0x4fc001f0; +spi_flash_guard_get = 0x4fc001f4; +spi_flash_read_encrypted = 0x4fc001f8; +/* Data (.data, .bss, .rodata) */ +rom_spiflash_legacy_funcs = 0x4ff3ffec; +rom_spiflash_legacy_data = 0x4ff3ffe8; +g_flash_guard_ops = 0x4ff3fff0; + + +/*************************************** + Group hal_systimer + ***************************************/ + +/* Functions */ +systimer_hal_init = 0x4fc00228; +systimer_hal_deinit = 0x4fc0022c; +systimer_hal_set_tick_rate_ops = 0x4fc00230; +systimer_hal_get_counter_value = 0x4fc00234; +systimer_hal_get_time = 0x4fc00238; +systimer_hal_set_alarm_target = 0x4fc0023c; +systimer_hal_set_alarm_period = 0x4fc00240; +systimer_hal_get_alarm_value = 0x4fc00244; +systimer_hal_enable_alarm_int = 0x4fc00248; +systimer_hal_on_apb_freq_update = 0x4fc0024c; +systimer_hal_counter_value_advance = 0x4fc00250; +systimer_hal_enable_counter = 0x4fc00254; +systimer_hal_select_alarm_mode = 0x4fc00258; +systimer_hal_connect_alarm_counter = 0x4fc0025c; +systimer_hal_counter_can_stall_by_cpu = 0x4fc00260; + + +/*************************************** + Group cache + ***************************************/ + +/* Functions */ +Cache_Get_L1_ICache_Line_Size = 0x4fc003c4; +Cache_Get_L1_DCache_Line_Size = 0x4fc003c8; +Cache_Get_L2_Cache_Line_Size = 0x4fc003cc; +Cache_Get_Mode = 0x4fc003d0; +Cache_Set_L2_Cache_Mode = 0x4fc003d4; +Cache_Address_Through_Cache = 0x4fc003d8; +ROM_Boot_Cache_Init = 0x4fc003dc; +Cache_Sync_Addr = 0x4fc003e0; +Cache_Invalidate_Addr = 0x4fc003e4; +Cache_Invalidate_Addr_Gid = 0x4fc003e8; +Cache_Clean_Addr = 0x4fc003ec; +Cache_Clean_Addr_Gid = 0x4fc003f0; +Cache_WriteBack_Addr = 0x4fc003f4; +Cache_WriteBack_Addr_Gid = 0x4fc003f8; +Cache_WriteBack_Invalidate_Addr = 0x4fc003fc; +Cache_WriteBack_Invalidate_Addr_Gid = 0x4fc00400; +Cache_Invalidate_All = 0x4fc00404; +Cache_Invalidate_All_Gid = 0x4fc00408; +Cache_Clean_All = 0x4fc0040c; +Cache_Clean_All_Gid = 0x4fc00410; +Cache_WriteBack_All = 0x4fc00414; +Cache_WriteBack_All_Gid = 0x4fc00418; +Cache_WriteBack_Invalidate_All = 0x4fc0041c; +Cache_WriteBack_Invalidate_All_Gid = 0x4fc00420; +Cache_Mask_All = 0x4fc00424; +Cache_Suspend_L1_CORE0_ICache_Autoload = 0x4fc00428; +Cache_Resume_L1_CORE0_ICache_Autoload = 0x4fc0042c; +Cache_Suspend_L1_CORE1_ICache_Autoload = 0x4fc00430; +Cache_Resume_L1_CORE1_ICache_Autoload = 0x4fc00434; +Cache_Suspend_L1_DCache_Autoload = 0x4fc00438; +Cache_Resume_L1_DCache_Autoload = 0x4fc0043c; +Cache_Suspend_L2_Cache_Autoload = 0x4fc00440; +Cache_Resume_L2_Cache_Autoload = 0x4fc00444; +Cache_Start_L1_CORE0_ICache_Preload = 0x4fc00448; +Cache_L1_CORE0_ICache_Preload_Done = 0x4fc0044c; +Cache_End_L1_CORE0_ICache_Preload = 0x4fc00450; +Cache_Start_L1_CORE1_ICache_Preload = 0x4fc00454; +Cache_L1_CORE1_ICache_Preload_Done = 0x4fc00458; +Cache_End_L1_CORE1_ICache_Preload = 0x4fc0045c; +Cache_Start_L1_DCache_Preload = 0x4fc00460; +Cache_L1_DCache_Preload_Done = 0x4fc00464; +Cache_End_L1_DCache_Preload = 0x4fc00468; +Cache_Start_L2_Cache_Preload = 0x4fc0046c; +Cache_L2_Cache_Preload_Done = 0x4fc00470; +Cache_End_L2_Cache_Preload = 0x4fc00474; +Cache_Config_L1_CORE0_ICache_Autoload = 0x4fc00478; +Cache_Enable_L1_CORE0_ICache_Autoload = 0x4fc0047c; +Cache_Disable_L1_CORE0_ICache_Autoload = 0x4fc00480; +Cache_Config_L1_CORE1_ICache_Autoload = 0x4fc00484; +Cache_Enable_L1_CORE1_ICache_Autoload = 0x4fc00488; +Cache_Disable_L1_CORE1_ICache_Autoload = 0x4fc0048c; +Cache_Config_L1_DCache_Autoload = 0x4fc00490; +Cache_Enable_L1_DCache_Autoload = 0x4fc00494; +Cache_Disable_L1_DCache_Autoload = 0x4fc00498; +Cache_Config_L2_Cache_Autoload = 0x4fc0049c; +Cache_Enable_L2_Cache_Autoload = 0x4fc004a0; +Cache_Disable_L2_Cache_Autoload = 0x4fc004a4; +Cache_Enable_L1_CORE0_ICache_PreLock = 0x4fc004a8; +Cache_Disable_L1_CORE0_ICache_PreLock = 0x4fc004ac; +Cache_Enable_L1_CORE1_ICache_PreLock = 0x4fc004b0; +Cache_Disable_L1_CORE1_ICache_PreLock = 0x4fc004b4; +Cache_Enable_L1_DCache_PreLock = 0x4fc004b8; +Cache_Disable_L1_DCache_PreLock = 0x4fc004bc; +Cache_Enable_L2_Cache_PreLock = 0x4fc004c0; +Cache_Disable_L2_Cache_PreLock = 0x4fc004c4; +Cache_Lock_Addr = 0x4fc004c8; +Cache_Unlock_Addr = 0x4fc004cc; +Cache_Disable_L1_CORE0_ICache = 0x4fc004d0; +Cache_Enable_L1_CORE0_ICache = 0x4fc004d4; +Cache_Suspend_L1_CORE0_ICache = 0x4fc004d8; +Cache_Resume_L1_CORE0_ICache = 0x4fc004dc; +Cache_Disable_L1_CORE1_ICache = 0x4fc004e0; +Cache_Enable_L1_CORE1_ICache = 0x4fc004e4; +Cache_Suspend_L1_CORE1_ICache = 0x4fc004e8; +Cache_Resume_L1_CORE1_ICache = 0x4fc004ec; +Cache_Disable_L1_DCache = 0x4fc004f0; +Cache_Enable_L1_DCache = 0x4fc004f4; +Cache_Suspend_L1_DCache = 0x4fc004f8; +Cache_Resume_L1_DCache = 0x4fc004fc; +Cache_Disable_L2_Cache = 0x4fc00500; +Cache_Enable_L2_Cache = 0x4fc00504; +Cache_Suspend_L2_Cache = 0x4fc00508; +Cache_Resume_L2_Cache = 0x4fc0050c; +Cache_FLASH_MMU_Init = 0x4fc00510; +Cache_PSRAM_MMU_Init = 0x4fc00514; +Cache_FLASH_MMU_Set = 0x4fc00518; +Cache_FLASH_MMU_Set_Secure = 0x4fc0051c; +Cache_PSRAM_MMU_Set = 0x4fc00520; +Cache_PSRAM_MMU_Set_Secure = 0x4fc00524; +Cache_Count_Flash_Pages = 0x4fc00528; +Cache_Flash_To_SPIRAM_Copy = 0x4fc0052c; +Cache_Travel_Tag_Memory = 0x4fc00530; +Cache_Travel_Tag_Memory2 = 0x4fc00534; +Cache_Get_Virtual_Addr = 0x4fc00538; +Cache_Set_IDROM_MMU_Size = 0x4fc0053c; +flash2spiram_instruction_offset = 0x4fc00540; +flash2spiram_rodata_offset = 0x4fc00544; +flash_instr_rodata_start_page = 0x4fc00548; +flash_instr_rodata_end_page = 0x4fc0054c; +Cache_Set_IDROM_MMU_Info = 0x4fc00550; +Cache_Get_IROM_MMU_End = 0x4fc00554; +Cache_Get_DROM_MMU_End = 0x4fc00558; +/* Data (.data, .bss, .rodata) */ +rom_cache_op_cb = 0x4ff3ffdc; +rom_cache_internal_table_ptr = 0x4ff3ffd8; + + +/*************************************** + Group clock + ***************************************/ + +/* Functions */ +ets_clk_get_xtal_freq = 0x4fc0055c; +ets_clk_get_cpu_freq = 0x4fc00560; + + +/*************************************** + Group gpio + ***************************************/ + +/* Functions */ +gpio_set_output_level = 0x4fc00564; +gpio_get_input_level = 0x4fc00568; +gpio_matrix_in = 0x4fc0056c; +gpio_matrix_out = 0x4fc00570; +gpio_bypass_matrix_in = 0x4fc00574; +gpio_output_disable = 0x4fc00578; +gpio_output_enable = 0x4fc0057c; +gpio_pad_input_disable = 0x4fc00580; +gpio_pad_input_enable = 0x4fc00584; +gpio_pad_pulldown = 0x4fc00588; +gpio_pad_pullup = 0x4fc0058c; +gpio_pad_select_gpio = 0x4fc00590; +gpio_pad_set_drv = 0x4fc00594; +gpio_pad_unhold = 0x4fc00598; +gpio_pad_hold = 0x4fc0059c; +gpio_lppad_select_mux = 0x4fc005a0; +gpio_ded_pad_set_drv = 0x4fc005a4; +gpio_ded_pad_pullup = 0x4fc005a8; +gpio_ded_pad_pulldown = 0x4fc005ac; +gpio_ded_pad_hold = 0x4fc005b0; +gpio_ded_pad_unhold = 0x4fc005b4; + + +/*************************************** + Group interrupts + ***************************************/ + +/* Functions */ +esprv_intc_int_set_priority = 0x4fc005b8; +esprv_intc_int_set_threshold = 0x4fc005bc; +esprv_intc_int_enable = 0x4fc005c0; +esprv_intc_int_disable = 0x4fc005c4; +esprv_intc_int_set_type = 0x4fc005c8; +PROVIDE( intr_handler_set = 0x4fc005cc ); +intr_matrix_set = 0x4fc005d0; +ets_intr_lock = 0x4fc005d4; +ets_intr_unlock = 0x4fc005d8; +ets_isr_attach = 0x4fc005dc; +ets_isr_mask = 0x4fc005e0; +ets_isr_unmask = 0x4fc005e4; + + +/*************************************** + Group crypto + ***************************************/ + +/* Functions */ +md5_vector = 0x4fc005e8; +MD5Init = 0x4fc005ec; +MD5Update = 0x4fc005f0; +MD5Final = 0x4fc005f4; +crc32_le = 0x4fc005f8; +crc16_le = 0x4fc005fc; +crc8_le = 0x4fc00600; +crc32_be = 0x4fc00604; +crc16_be = 0x4fc00608; +crc8_be = 0x4fc0060c; +esp_crc8 = 0x4fc00610; +ets_sha_enable = 0x4fc00614; +ets_sha_disable = 0x4fc00618; +ets_sha_get_state = 0x4fc0061c; +ets_sha_init = 0x4fc00620; +ets_sha_process = 0x4fc00624; +ets_sha_starts = 0x4fc00628; +ets_sha_update = 0x4fc0062c; +ets_sha_finish = 0x4fc00630; +ets_sha_clone = 0x4fc00634; +ets_hmac_enable = 0x4fc00638; +ets_hmac_disable = 0x4fc0063c; +ets_hmac_calculate_message = 0x4fc00640; +ets_hmac_calculate_downstream = 0x4fc00644; +ets_hmac_invalidate_downstream = 0x4fc00648; +ets_jtag_enable_temporarily = 0x4fc0064c; +ets_aes_enable = 0x4fc00650; +ets_aes_disable = 0x4fc00654; +ets_aes_setkey = 0x4fc00658; +ets_aes_block = 0x4fc0065c; +ets_aes_setkey_dec = 0x4fc00660; +ets_aes_setkey_enc = 0x4fc00664; +ets_bigint_enable = 0x4fc00668; +ets_bigint_disable = 0x4fc0066c; +ets_bigint_multiply = 0x4fc00670; +ets_bigint_modmult = 0x4fc00674; +ets_bigint_modexp = 0x4fc00678; +ets_bigint_wait_finish = 0x4fc0067c; +ets_bigint_getz = 0x4fc00680; +ets_ds_enable = 0x4fc00684; +ets_ds_disable = 0x4fc00688; +ets_ds_start_sign = 0x4fc0068c; +ets_ds_is_busy = 0x4fc00690; +ets_ds_finish_sign = 0x4fc00694; +ets_ds_encrypt_params = 0x4fc00698; +ets_mgf1_sha256 = 0x4fc0069c; +/* Data (.data, .bss, .rodata) */ +crc32_le_table_ptr = 0x4fc1fff8; +crc16_le_table_ptr = 0x4fc1fff4; +crc8_le_table_ptr = 0x4fc1fff0; +crc32_be_table_ptr = 0x4fc1ffec; +crc16_be_table_ptr = 0x4fc1ffe8; +crc8_be_table_ptr = 0x4fc1ffe4; + + +/*************************************** + Group efuse + ***************************************/ + +/* Functions */ +ets_efuse_read = 0x4fc006a0; +ets_efuse_program = 0x4fc006a4; +ets_efuse_clear_program_registers = 0x4fc006a8; +ets_efuse_write_key = 0x4fc006ac; +ets_efuse_get_read_register_address = 0x4fc006b0; +ets_efuse_get_key_purpose = 0x4fc006b4; +ets_efuse_key_block_unused = 0x4fc006b8; +ets_efuse_find_unused_key_block = 0x4fc006bc; +ets_efuse_rs_calculate = 0x4fc006c0; +ets_efuse_count_unused_key_blocks = 0x4fc006c4; +ets_efuse_secure_boot_enabled = 0x4fc006c8; +ets_efuse_secure_boot_aggressive_revoke_enabled = 0x4fc006cc; +ets_efuse_cache_encryption_enabled = 0x4fc006d0; +ets_efuse_download_modes_disabled = 0x4fc006d4; +ets_efuse_find_purpose = 0x4fc006d8; +ets_efuse_force_send_resume = 0x4fc006dc; +ets_efuse_get_flash_delay_us = 0x4fc006e0; +ets_efuse_get_uart_print_control = 0x4fc006e4; +ets_efuse_direct_boot_mode_disabled = 0x4fc006e8; +ets_efuse_security_download_modes_enabled = 0x4fc006ec; +ets_efuse_jtag_disabled = 0x4fc006f0; +ets_efuse_usb_print_is_disabled = 0x4fc006f4; +ets_efuse_usb_download_mode_disabled = 0x4fc006f8; +ets_efuse_usb_device_disabled = 0x4fc006fc; +ets_efuse_get_km_huk_gen_state = 0x4fc00700; +ets_efuse_get_km_deploy_only_once = 0x4fc00704; +ets_efuse_get_force_use_km_key = 0x4fc00708; +ets_efuse_xts_key_length_256 = 0x4fc0070c; +ets_efuse_get_km_key_lock = 0x4fc00710; + + +/*************************************** + Group key_mgr + ***************************************/ + +/* Functions */ +esp_rom_check_recover_key = 0x4fc00714; +esp_rom_km_huk_conf = 0x4fc00718; +esp_rom_km_huk_risk = 0x4fc0071c; + + +/*************************************** + Group secureboot + ***************************************/ + +/* Functions */ +ets_emsa_pss_verify = 0x4fc00720; +ets_rsa_pss_verify = 0x4fc00724; +ets_ecdsa_verify = 0x4fc00728; +ets_secure_boot_verify_bootloader_with_keys = 0x4fc0072c; +ets_secure_boot_verify_signature = 0x4fc00730; +ets_secure_boot_read_key_digests = 0x4fc00734; +ets_secure_boot_revoke_public_key_digest = 0x4fc00738; + + +/*************************************** + Group usb_device_uart + ***************************************/ + +/* Functions */ +usb_serial_device_rx_one_char = 0x4fc008b0; +usb_serial_device_rx_one_char_block = 0x4fc008b4; +usb_serial_device_tx_flush = 0x4fc008b8; +usb_serial_device_tx_one_char = 0x4fc008bc; + + +/*************************************** + Group usb_dwcotg_uart + ***************************************/ + +/* Functions */ +Uart_Init_USB = 0x4fc008c0; +usb_serial_otg_rx_one_char = 0x4fc008c4; +usb_serial_otg_rx_one_char_block = 0x4fc008c8; +usb_serial_otg_tx_flush = 0x4fc008cc; +usb_serial_otg_tx_one_char = 0x4fc008d0; +/* Data (.data, .bss, .rodata) */ +uart_acm_dev = 0x4ff3ffd4; + + +/*************************************** + Group usb_dwcotg_module + ***************************************/ + +/* Functions */ +cdc_acm_class_handle_req = 0x4fc008d4; +cdc_acm_init = 0x4fc008d8; +cdc_acm_fifo_fill = 0x4fc008dc; +cdc_acm_rx_fifo_cnt = 0x4fc008e0; +cdc_acm_fifo_read = 0x4fc008e4; +cdc_acm_irq_tx_enable = 0x4fc008e8; +cdc_acm_irq_tx_disable = 0x4fc008ec; +cdc_acm_irq_state_enable = 0x4fc008f0; +cdc_acm_irq_state_disable = 0x4fc008f4; +cdc_acm_irq_tx_ready = 0x4fc008f8; +cdc_acm_irq_rx_enable = 0x4fc008fc; +cdc_acm_irq_rx_disable = 0x4fc00900; +cdc_acm_irq_rx_ready = 0x4fc00904; +cdc_acm_irq_is_pending = 0x4fc00908; +cdc_acm_irq_callback_set = 0x4fc0090c; +cdc_acm_line_ctrl_set = 0x4fc00910; +cdc_acm_line_ctrl_get = 0x4fc00914; +cdc_acm_poll_out = 0x4fc00918; +chip_usb_dw_did_persist = 0x4fc0091c; +chip_usb_dw_init = 0x4fc00920; +chip_usb_detach = 0x4fc00924; +chip_usb_dw_prepare_persist = 0x4fc00928; +chip_usb_get_persist_flags = 0x4fc0092c; +chip_usb_set_persist_flags = 0x4fc00930; +cpio_start = 0x4fc00934; +cpio_feed = 0x4fc00938; +cpio_done = 0x4fc0093c; +cpio_destroy = 0x4fc00940; +dfu_flash_init = 0x4fc00944; +dfu_flash_erase = 0x4fc00948; +dfu_flash_program = 0x4fc0094c; +dfu_flash_read = 0x4fc00950; +dfu_flash_attach = 0x4fc00954; +dfu_cpio_callback = 0x4fc00958; +dfu_updater_get_err = 0x4fc0095c; +dfu_updater_clear_err = 0x4fc00960; +dfu_updater_enable = 0x4fc00964; +dfu_updater_begin = 0x4fc00968; +dfu_updater_feed = 0x4fc0096c; +dfu_updater_end = 0x4fc00970; +dfu_updater_set_raw_addr = 0x4fc00974; +dfu_updater_flash_read = 0x4fc00978; +usb_dc_prepare_persist = 0x4fc0097c; +usb_dw_isr_handler = 0x4fc00980; +usb_dc_attach = 0x4fc00984; +usb_dc_detach = 0x4fc00988; +usb_dc_reset = 0x4fc0098c; +usb_dc_set_address = 0x4fc00990; +usb_dc_ep_check_cap = 0x4fc00994; +usb_dc_ep_configure = 0x4fc00998; +usb_dc_ep_set_stall = 0x4fc0099c; +usb_dc_ep_clear_stall = 0x4fc009a0; +usb_dc_ep_halt = 0x4fc009a4; +usb_dc_ep_is_stalled = 0x4fc009a8; +usb_dc_ep_enable = 0x4fc009ac; +usb_dc_ep_disable = 0x4fc009b0; +usb_dc_ep_flush = 0x4fc009b4; +usb_dc_ep_write_would_block = 0x4fc009b8; +usb_dc_ep_write = 0x4fc009bc; +usb_dc_ep_read_wait = 0x4fc009c0; +usb_dc_ep_read_continue = 0x4fc009c4; +usb_dc_ep_read = 0x4fc009c8; +usb_dc_ep_set_callback = 0x4fc009cc; +usb_dc_set_status_callback = 0x4fc009d0; +usb_dc_ep_mps = 0x4fc009d4; +usb_dc_check_poll_for_interrupts = 0x4fc009d8; +mac_addr_to_serial_str_desc = 0x4fc009dc; +usb_set_current_descriptor = 0x4fc009e0; +usb_get_descriptor = 0x4fc009e4; +usb_dev_resume = 0x4fc009e8; +usb_dev_get_configuration = 0x4fc009ec; +usb_set_config = 0x4fc009f0; +usb_deconfig = 0x4fc009f4; +usb_enable = 0x4fc009f8; +usb_disable = 0x4fc009fc; +usb_write_would_block = 0x4fc00a00; +usb_write = 0x4fc00a04; +usb_read = 0x4fc00a08; +usb_ep_set_stall = 0x4fc00a0c; +usb_ep_clear_stall = 0x4fc00a10; +usb_ep_read_wait = 0x4fc00a14; +usb_ep_read_continue = 0x4fc00a18; +usb_transfer_ep_callback = 0x4fc00a1c; +usb_transfer = 0x4fc00a20; +usb_cancel_transfer = 0x4fc00a24; +usb_transfer_sync = 0x4fc00a28; +usb_dfu_set_detach_cb = 0x4fc00a2c; +dfu_class_handle_req = 0x4fc00a30; +dfu_status_cb = 0x4fc00a34; +dfu_custom_handle_req = 0x4fc00a38; +usb_dfu_init = 0x4fc00a3c; +usb_dfu_force_detach = 0x4fc00a40; +usb_dev_deinit = 0x4fc00a44; +usb_dw_ctrl_deinit = 0x4fc00a48; +/* Data (.data, .bss, .rodata) */ +s_usb_osglue = 0x4ff3ffc8; diff --git a/flasher_stub/ld/stub_32.ld b/flasher_stub/ld/stub_32.ld index ca812c887..9ab825585 100644 --- a/flasher_stub/ld/stub_32.ld +++ b/flasher_stub/ld/stub_32.ld @@ -1,20 +1,3 @@ -/* - * Copyright (c) 2016 Cesanta Software Limited - * All rights reserved - * - * This program is free software; you can redistribute it and/or modify it under - * the terms of the GNU General Public License as published by the Free Software - * Foundation; either version 2 of the License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS - * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License along with - * this program; if not, write to the Free Software Foundation, Inc., 51 Franklin - * Street, Fifth Floor, Boston, MA 02110-1301 USA. - */ - /* Note: stub is deliberately loaded close to the very top of available RAM, to reduce change of colliding with anything else... */ diff --git a/flasher_stub/ld/stub_32c3.ld b/flasher_stub/ld/stub_32c3.ld index b7c3e88aa..dc9d4201e 100644 --- a/flasher_stub/ld/stub_32c3.ld +++ b/flasher_stub/ld/stub_32c3.ld @@ -1,9 +1,3 @@ -/* - * SPDX-FileCopyrightText: 2019-2022 Espressif Systems (Shanghai) CO LTD - * - * SPDX-License-Identifier: GPL-2.0-or-later - */ - MEMORY { iram : org = 0x40380000, len = 0x4000 dram : org = 0x3FC84000, len = 0x18000 diff --git a/flasher_stub/ld/stub_32c6.ld b/flasher_stub/ld/stub_32c6.ld index 994a010fb..91b8d3137 100644 --- a/flasher_stub/ld/stub_32c6.ld +++ b/flasher_stub/ld/stub_32c6.ld @@ -1,20 +1,3 @@ -/* - * Copyright (c) 2022 Espressif Systems (Shanghai) PTE LTD - * All rights reserved - * - * This program is free software; you can redistribute it and/or modify it under - * the terms of the GNU General Public License as published by the Free Software - * Foundation; either version 2 of the License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS - * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License along with - * this program; if not, write to the Free Software Foundation, Inc., 51 Franklin - * Street, Fifth Floor, Boston, MA 02110-1301 USA. - */ - MEMORY { iram : org = 0x40800000, len = 0x4000 dram : org = 0x40840000, len = 0x18000 diff --git a/flasher_stub/ld/stub_32c6_beta.ld b/flasher_stub/ld/stub_32c6_beta.ld index 89ab54df1..5acb1029b 100644 --- a/flasher_stub/ld/stub_32c6_beta.ld +++ b/flasher_stub/ld/stub_32c6_beta.ld @@ -1,9 +1,3 @@ -/* - * SPDX-FileCopyrightText: 2019-2022 Espressif Systems (Shanghai) CO LTD - * - * SPDX-License-Identifier: GPL-2.0-or-later - */ - MEMORY { iram : org = 0x40380000, len = 0x4000 dram : org = 0x3FC84000, len = 0x18000 diff --git a/flasher_stub/ld/stub_32h2.ld b/flasher_stub/ld/stub_32h2.ld index 16559d807..c94f5939e 100644 --- a/flasher_stub/ld/stub_32h2.ld +++ b/flasher_stub/ld/stub_32h2.ld @@ -1,9 +1,3 @@ -/* - * SPDX-FileCopyrightText: 2022 Espressif Systems (Shanghai) CO LTD - * - * SPDX-License-Identifier: GPL-2.0-or-later - */ - MEMORY { iram : org = 0x40800000, len = 0x4000 dram : org = 0x40830000, len = 0x18000 diff --git a/flasher_stub/ld/stub_32h2_beta_1.ld b/flasher_stub/ld/stub_32h2_beta_1.ld index da6e273bf..62b16372c 100644 --- a/flasher_stub/ld/stub_32h2_beta_1.ld +++ b/flasher_stub/ld/stub_32h2_beta_1.ld @@ -1,9 +1,3 @@ -/* - * SPDX-FileCopyrightText: 2019-2022 Espressif Systems (Shanghai) CO LTD - * - * SPDX-License-Identifier: GPL-2.0-or-later - */ - MEMORY { iram : org = 0x40380000, len = 0x4000 dram : org = 0x3FC84000, len = 0x18000 diff --git a/flasher_stub/ld/stub_32h2_beta_2.ld b/flasher_stub/ld/stub_32h2_beta_2.ld index 07876ae6e..903b497ee 100644 --- a/flasher_stub/ld/stub_32h2_beta_2.ld +++ b/flasher_stub/ld/stub_32h2_beta_2.ld @@ -1,9 +1,3 @@ -/* - * SPDX-FileCopyrightText: 2019-2022 Espressif Systems (Shanghai) CO LTD - * - * SPDX-License-Identifier: GPL-2.0-or-later - */ - MEMORY { iram : org = 0x40380000, len = 0x4000 dram : org = 0x3FC84000, len = 0x18000 diff --git a/flasher_stub/ld/stub_32p4.ld b/flasher_stub/ld/stub_32p4.ld new file mode 100644 index 000000000..bf7e46a4e --- /dev/null +++ b/flasher_stub/ld/stub_32p4.ld @@ -0,0 +1,26 @@ +MEMORY { + iram : org = 0x4FF10000, len = 0x4000 + dram : org = 0x4FF50000, len = 0x18000 +} + +ENTRY(stub_main) + +SECTIONS { + .text : ALIGN(4) { + *(.literal) + *(.text .text.*) + } > iram + + .bss : ALIGN(4) { + _bss_start = ABSOLUTE(.); + *(.bss) + _bss_end = ABSOLUTE(.); + } > dram + + .data : ALIGN(4) { + *(.data) + *(.rodata .rodata.*) + } > dram +} + +INCLUDE "rom_32p4.ld" diff --git a/flasher_stub/ld/stub_32s2.ld b/flasher_stub/ld/stub_32s2.ld index 06a32ff37..ccec2b79c 100644 --- a/flasher_stub/ld/stub_32s2.ld +++ b/flasher_stub/ld/stub_32s2.ld @@ -1,9 +1,3 @@ -/* - * SPDX-FileCopyrightText: 2019-2022 Espressif Systems (Shanghai) CO LTD - * - * SPDX-License-Identifier: GPL-2.0-or-later - */ - MEMORY { iram : org = 0x40028000, len = 0x18000 dram : org = 0x3FFD0000, len = 0x28000 diff --git a/flasher_stub/ld/stub_32s3.ld b/flasher_stub/ld/stub_32s3.ld index 08eaae1ec..98cce2284 100644 --- a/flasher_stub/ld/stub_32s3.ld +++ b/flasher_stub/ld/stub_32s3.ld @@ -1,9 +1,3 @@ -/* - * SPDX-FileCopyrightText: 2019-2022 Espressif Systems (Shanghai) CO LTD - * - * SPDX-License-Identifier: GPL-2.0-or-later - */ - MEMORY { iram : org = 0x40378000, len = 0x18000 dram : org = 0x3FCA0000, len = 0x28000 diff --git a/flasher_stub/ld/stub_32s3_beta_2.ld b/flasher_stub/ld/stub_32s3_beta_2.ld index 86f5405fa..5105e30d9 100644 --- a/flasher_stub/ld/stub_32s3_beta_2.ld +++ b/flasher_stub/ld/stub_32s3_beta_2.ld @@ -1,9 +1,3 @@ -/* - * SPDX-FileCopyrightText: 2019-2022 Espressif Systems (Shanghai) CO LTD - * - * SPDX-License-Identifier: GPL-2.0-or-later - */ - MEMORY { iram : org = 0x40378000, len = 0x18000 dram : org = 0x3FCA0000, len = 0x28000 diff --git a/flasher_stub/ld/stub_8266.ld b/flasher_stub/ld/stub_8266.ld index 9f837a456..a42b9b25e 100644 --- a/flasher_stub/ld/stub_8266.ld +++ b/flasher_stub/ld/stub_8266.ld @@ -1,20 +1,3 @@ -/* - * Copyright (c) 2016 Cesanta Software Limited - * All rights reserved - * - * This program is free software; you can redistribute it and/or modify it under - * the terms of the GNU General Public License as published by the Free Software - * Foundation; either version 2 of the License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS - * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License along with - * this program; if not, write to the Free Software Foundation, Inc., 51 Franklin - * Street, Fifth Floor, Boston, MA 02110-1301 USA. - */ - /* Note: stub is deliberately loaded close to the very top of available RAM, to reduce change of colliding with anything else... */ diff --git a/flasher_stub/stub_commands.c b/flasher_stub/stub_commands.c index 169c266b9..11340e19d 100644 --- a/flasher_stub/stub_commands.c +++ b/flasher_stub/stub_commands.c @@ -49,7 +49,7 @@ int handle_flash_erase(uint32_t addr, uint32_t len) { while (len > 0 && (addr % FLASH_BLOCK_SIZE != 0)) { #if defined(ESP32S3) && !defined(ESP32S3BETA2) - if (ets_efuse_flash_octal_mode()) { + if (large_flash_mode) { if (esp_rom_opiflash_erase_sector(addr / FLASH_SECTOR_SIZE) != 0) return 0x35; } else { if (SPIEraseSector(addr / FLASH_SECTOR_SIZE) != 0) return 0x35; @@ -63,7 +63,7 @@ int handle_flash_erase(uint32_t addr, uint32_t len) { while (len > FLASH_BLOCK_SIZE) { #if defined(ESP32S3) && !defined(ESP32S3BETA2) - if (ets_efuse_flash_octal_mode()) { + if (large_flash_mode) { if (esp_rom_opiflash_erase_block_64k(addr / FLASH_BLOCK_SIZE) != 0) return 0x36; } else { if (SPIEraseBlock(addr / FLASH_BLOCK_SIZE) != 0) return 0x36; @@ -77,7 +77,7 @@ int handle_flash_erase(uint32_t addr, uint32_t len) { while (len > 0) { #if defined(ESP32S3) && !defined(ESP32S3BETA2) - if (ets_efuse_flash_octal_mode()) { + if (large_flash_mode) { if (esp_rom_opiflash_erase_sector(addr / FLASH_SECTOR_SIZE) != 0) return 0x37; } else { if (SPIEraseSector(addr / FLASH_SECTOR_SIZE) != 0) return 0x37; @@ -112,7 +112,7 @@ void handle_flash_read(uint32_t addr, uint32_t len, uint32_t block_size, uint32_t n = len - num_sent; if (n > block_size) n = block_size; #if defined(ESP32S3) && !defined(ESP32S3BETA2) - if (ets_efuse_flash_octal_mode()) { + if (large_flash_mode) { res = SPIRead4B(1, addr, buf, n); } else { res = SPIRead(addr, (uint32_t *)buf, n); @@ -152,7 +152,7 @@ int handle_flash_get_md5sum(uint32_t addr, uint32_t len) { n = FLASH_SECTOR_SIZE; } #if defined(ESP32S3) && !defined(ESP32S3BETA2) - if (ets_efuse_flash_octal_mode()) { + if (large_flash_mode) { res = SPIRead4B(1, addr, buf, n); } else { res = SPIRead(addr, (uint32_t *)buf, n); @@ -254,7 +254,14 @@ esp_command_error handle_get_security_info() uint8_t buf[SECURITY_INFO_BYTES]; esp_command_error ret; + #ifdef ESP32C3 + if (_rom_eco_version >= 7) + ret = GetSecurityInfoProcNewEco(NULL, NULL, buf); + else + ret = GetSecurityInfoProc(NULL, NULL, buf); + #else ret = GetSecurityInfoProc(NULL, NULL, buf); + #endif // ESP32C3 if (ret == ESP_OK) SLIP_send_frame_data_buf(buf, sizeof(buf)); return ret; diff --git a/flasher_stub/stub_flasher.c b/flasher_stub/stub_flasher.c index 69edd7cda..6b5885039 100644 --- a/flasher_stub/stub_flasher.c +++ b/flasher_stub/stub_flasher.c @@ -108,17 +108,41 @@ static void reset_cpu_freq() #endif // USE_MAX_CPU_FREQ #if WITH_USB_JTAG_SERIAL -static void disable_rtc_watchdog() +static void disable_watchdogs() { if (stub_uses_usb_jtag_serial()) { WRITE_REG(RTC_CNTL_WDTWPROTECT_REG, RTC_CNTL_WDT_WKEY); // Disable write protection WRITE_REG(RTC_CNTL_WDTCONFIG0_REG, 0x0); // Disable RTC watchdog WRITE_REG(RTC_CNTL_WDTWPROTECT_REG, 0x0); // Re-enable write protection + + WRITE_REG(RTC_CNTL_SWD_WPROTECT_REG, RTC_CNTL_SWD_WKEY); // Disable write protection + REG_SET_MASK(RTC_CNTL_SWD_CONF_REG, RTC_CNTL_SWD_AUTO_FEED_EN); // Autofeed super watchdog + WRITE_REG(RTC_CNTL_SWD_WPROTECT_REG, 0x0); // Re-enable write protection } } #endif // WITH_USB_JTAG_SERIAL +#if ESP32S3 && !ESP32S3BETA2 +bool large_flash_mode = false; + +bool flash_larger_than_16mb() +{ + uint32_t flash_id; + esp_rom_opiflash_exec_cmd(1, SPI_FLASH_FASTRD_MODE, + CMD_RDID, 8, + 0, 0, + 0, + NULL, 0, + (uint8_t *)&flash_id, 24, + ESP_ROM_OPIFLASH_SEL_CS0, + false); + + uint8_t flid_lowbyte = (flash_id >> 16) & 0xFF; + return ((flid_lowbyte >= 0x19 && flid_lowbyte < 0x30) || (flid_lowbyte >= 0x39)); // See DETECTED_FLASH_SIZES in esptool +} +#endif // ESP32S3 + static void stub_handle_rx_byte(char byte) { int16_t r = SLIP_recv_byte(byte, (slip_state_t *)&ub.state); @@ -442,65 +466,72 @@ void stub_main() { const uint32_t greeting = 0x4941484f; /* OHAI */ - /* this points to stub_main now, clear for next boot */ + /* This points to stub_main now, clear for next boot. */ ets_set_user_start(0); + /* Increase CPU frequency and flashing speed if supported. */ #if USE_MAX_CPU_FREQ set_max_cpu_freq(); #endif // USE_MAX_CPU_FREQ + /* Disable all watchdogs to prevent the chip from resetting during longer operations. */ #if WITH_USB_JTAG_SERIAL - disable_rtc_watchdog(); + disable_watchdogs(); #endif // WITH_USB_JTAG_SERIAL - /* zero bss */ + /* Zero the bss region. */ for(uint32_t *p = &_bss_start; p < &_bss_end; p++) { *p = 0; } + /* Send the OHAI greeting, stub will be reported as running. */ SLIP_send(&greeting, 4); + /* Configure the interrupts for receiving data from esptool on the host. */ ub.reading_buf = ub.buf_a; stub_io_init(&stub_handle_rx_byte); /* Configure default SPI flash functionality. Can be overriden later by esptool.py. */ -#ifdef ESP8266 - SelectSpiFunction(); - - spi_flash_attach(); -#else -#if !ESP32C2 && !ESP32C6 && !ESP32H2 - uint32_t spiconfig = ets_efuse_get_spiconfig(); -#else - // ESP32C2/ESP32C6 doesn't support get spiconfig. - uint32_t spiconfig = 0; -#endif - uint32_t strapping = READ_REG(GPIO_STRAP_REG); - /* If GPIO1 (U0TXD) is pulled low and no other boot mode is - set in efuse, assume HSPI flash mode (same as normal boot) - */ - if (spiconfig == 0 && (strapping & 0x1c) == 0x08) { - spiconfig = 1; /* HSPI flash mode */ - } - spi_flash_attach(spiconfig, 0); -#endif -#if ESP32S3 && !ESP32S3BETA2 - // Initialize OPI flash driver only when flash is detected octal. Otherwise, we don't need to - // initialize such a driver - if (ets_efuse_flash_octal_mode()) { - static const esp_rom_opiflash_def_t flash_driver = OPIFLASH_DRIVER(); - esp_rom_opiflash_legacy_driver_init(&flash_driver); - esp_rom_opiflash_wait_idle(); - } -#endif //ESP32S3 && !ESP32S3BETA2 - SPIParamCfg(0, FLASH_MAX_SIZE, FLASH_BLOCK_SIZE, FLASH_SECTOR_SIZE, - FLASH_PAGE_SIZE, FLASH_STATUS_MASK); + #ifdef ESP8266 + SelectSpiFunction(); + spi_flash_attach(); + #else + #if SUPPORT_CONFIG_SPI + uint32_t spiconfig = ets_efuse_get_spiconfig(); + #else + uint32_t spiconfig = 0; + #endif // SUPPORT_CONFIG_SPI + uint32_t strapping = READ_REG(GPIO_STRAP_REG); + /* If GPIO1 (U0TXD) is pulled low and no other boot mode is + set in efuse, assume HSPI flash mode (same as normal boot) + */ + if (spiconfig == 0 && (strapping & 0x1c) == 0x08) { + spiconfig = 1; /* HSPI flash mode */ + } + spi_flash_attach(spiconfig, 0); + #endif // ESP8266 + + /* Initialize the OPI flash driver if supported. */ + #if ESP32S3 && !ESP32S3BETA2 + large_flash_mode = ets_efuse_flash_octal_mode() || flash_larger_than_16mb(); + + // Initialize OPI flash driver only when flash is detected octal or quad larger than 16MB. + // Otherwise, we don't need to initialize such a driver + if (large_flash_mode) { + static const esp_rom_opiflash_def_t flash_driver = OPIFLASH_DRIVER(); + esp_rom_opiflash_legacy_driver_init(&flash_driver); + esp_rom_opiflash_wait_idle(); + } + #endif //ESP32S3 && !ESP32S3BETA2 + SPIParamCfg(0, FLASH_MAX_SIZE, FLASH_BLOCK_SIZE, FLASH_SECTOR_SIZE, + FLASH_PAGE_SIZE, FLASH_STATUS_MASK); + /* Configurations are done, now run the loop to receive and handle commands. */ cmd_loop(); - /* if cmd_loop returns, it's due to ESP_RUN_USER_CODE command. */ - + /* If cmd_loop returns, it's due to ESP_RUN_USER_CODE command. */ + /* Decrease CPU frequency back to the saved value before the stub flasher returns. */ #if USE_MAX_CPU_FREQ reset_cpu_freq(); #endif // USE_MAX_CPU_FREQ diff --git a/flasher_stub/stub_io.c b/flasher_stub/stub_io.c index 409c24f8d..6cff6c377 100644 --- a/flasher_stub/stub_io.c +++ b/flasher_stub/stub_io.c @@ -71,7 +71,7 @@ static void stub_configure_rx_uart(void) WRITE_REG(INTERRUPT_CORE0_USB_DEVICE_INT_MAP_REG, ETS_USB_INUM); #endif // IS_RISCV ets_isr_attach(ETS_USB_INUM, jtag_serial_isr, NULL); - REG_SET_MASK(USB_DEVICE_INT_ENA_REG, USB_DEVICE_SERIAL_OUT_RECV_PKT_INT_ENA); + WRITE_REG(USB_DEVICE_INT_ENA_REG, USB_DEVICE_SERIAL_OUT_RECV_PKT_INT_ENA); ets_isr_unmask(1 << ETS_USB_INUM); return; } diff --git a/flasher_stub/stub_write_flash.c b/flasher_stub/stub_write_flash.c index b166976d8..e925d9f74 100644 --- a/flasher_stub/stub_write_flash.c +++ b/flasher_stub/stub_write_flash.c @@ -96,15 +96,7 @@ static void spi_write_enable(void) } #if ESP32_OR_LATER -#if ESP32C3 || ESP32C6BETA || ESP32C2 || ESP32C6 -static esp_rom_spiflash_chip_t *flashchip = (esp_rom_spiflash_chip_t *)0x3fcdfff4; -#elif ESP32H2BETA1 || ESP32H2BETA2 -static esp_rom_spiflash_chip_t *flashchip = (esp_rom_spiflash_chip_t *)0x3fcdfff0; -#elif ESP32H2 -static esp_rom_spiflash_chip_t *flashchip = (esp_rom_spiflash_chip_t *)0x4084fff0; -#else -static esp_rom_spiflash_chip_t *flashchip = (esp_rom_spiflash_chip_t *)0x3ffae270; -#endif +static esp_rom_spiflash_chip_t *flashchip = (esp_rom_spiflash_chip_t *)ROM_SPIFLASH_LEGACY; /* Stub version of SPIUnlock() that replaces version in ROM. @@ -126,7 +118,7 @@ SpiFlashOpResult SPIUnlock(void) if (SPI_read_status_high(&status) != SPI_FLASH_RESULT_OK) { return SPI_FLASH_RESULT_ERR; } -#endif +#endif // ESP32S2_OR_LATER /* Clear all bits except QIE, if it is set. (This is different from ROM SPIUnlock, which keeps all bits as-is.) @@ -142,7 +134,7 @@ SpiFlashOpResult SPIUnlock(void) return SPI_FLASH_RESULT_OK; } -#endif +#endif // ESP32_OR_LATER #if defined(ESP32S3) && !defined(ESP32S3BETA2) static esp_rom_spiflash_result_t page_program_internal(int spi_num, uint32_t spi_addr, uint8_t* addr_source, uint32_t byte_length) @@ -203,7 +195,7 @@ static esp_rom_spiflash_result_t SPIWrite4B(int spi_num, uint32_t target, uint8_ esp_rom_opiflash_wait_idle(); return ESP_ROM_SPIFLASH_RESULT_OK; } -#endif // ESP32S3 +#endif // defined(ESP32S3) && !defined(ESP32S3BETA2) esp_command_error handle_flash_begin(uint32_t total_size, uint32_t offset) { fs.in_flash_mode = true; @@ -214,7 +206,7 @@ esp_command_error handle_flash_begin(uint32_t total_size, uint32_t offset) { fs.last_error = ESP_OK; #if defined(ESP32S3) && !defined(ESP32S3BETA2) - if (ets_efuse_flash_octal_mode()) { + if (large_flash_mode) { esp_rom_opiflash_wait_idle(); } else { if (SPIUnlock() != 0) { @@ -266,14 +258,14 @@ static void start_next_erase(void) spi_write_enable(); spi_wait_ready(); #if defined(ESP32S3) && !defined(ESP32S3BETA2) - if (ets_efuse_flash_octal_mode()) { + if (large_flash_mode) { if (block_erase) { if (fs.next_erase_sector * FLASH_SECTOR_SIZE < (1 << 24)) { esp_rom_opiflash_wait_idle(); esp_rom_opiflash_wren(); esp_rom_opiflash_exec_cmd(1, SPI_FLASH_SLOWRD_MODE, - CMD_LARGE_BLOCK_ERASE, 8, + CMD_LARGE_BLOCK_ERASE, 8, fs.next_erase_sector * FLASH_SECTOR_SIZE, 24, 0, NULL, 0, @@ -291,7 +283,7 @@ static void start_next_erase(void) esp_rom_opiflash_wren(); esp_rom_opiflash_exec_cmd(1, SPI_FLASH_SLOWRD_MODE, - CMD_SECTOR_ERASE, 8, + CMD_SECTOR_ERASE, 8, fs.next_erase_sector * FLASH_SECTOR_SIZE, 24, 0, NULL, 0, @@ -354,14 +346,14 @@ void handle_flash_data(void *data_buf, uint32_t length) { /* do the actual write */ #if defined(ESP32S3) && !defined(ESP32S3BETA2) - if (ets_efuse_flash_octal_mode()) { + if (large_flash_mode){ res = SPIWrite4B(1, fs.next_write, data_buf, length); } else { res = SPIWrite(fs.next_write, data_buf, length); } #else res = SPIWrite(fs.next_write, data_buf, length); - #endif // ESP32S3 + #endif // defined(ESP32S3) && !defined(ESP32S3BETA2) if (res != 0) fs.last_error = ESP_FAILED_SPI_OP; fs.next_write += length; @@ -423,6 +415,13 @@ void handle_flash_encrypt_data(void *data_buf, uint32_t length) { #endif // !ESP8266 void handle_flash_deflated_data(void *data_buf, uint32_t length) { + /* if all data has been uploaded and another block comes, + accept it only if it is part of a 4-byte Adler-32 checksum */ + if (fs.remaining == 0 && length > 4) { + fs.last_error = ESP_TOO_MUCH_DATA; + return; + } + static uint8_t out_buf[32768]; static uint8_t *next_out = out_buf; int status = TINFL_STATUS_NEEDS_MORE_INPUT; @@ -464,9 +463,6 @@ void handle_flash_deflated_data(void *data_buf, uint32_t length) { if (status == TINFL_STATUS_DONE && fs.remaining > 0) { fs.last_error = ESP_NOT_ENOUGH_DATA; } - if (status != TINFL_STATUS_DONE && fs.remaining == 0) { - fs.last_error = ESP_TOO_MUCH_DATA; - } } esp_command_error handle_flash_end(void) diff --git a/flasher_stub/wrap_stub.py b/flasher_stub/wrap_stub.py index d206a9599..504d9f883 100755 --- a/flasher_stub/wrap_stub.py +++ b/flasher_stub/wrap_stub.py @@ -17,8 +17,7 @@ import esptool # noqa: E402 THIS_DIR = os.path.dirname(__file__) -BUILD_DIR = os.path.join(THIS_DIR, "./build/") -STUBS_DIR = os.path.join(THIS_DIR, "../esptool/targets/stub_flasher/") +BUILD_DIR = os.path.join(THIS_DIR, "build") def wrap_stub(elf_file): @@ -67,8 +66,7 @@ def default(self, obj): return json.JSONEncoder.default(self, obj) for filename, stub_data in stubs_dict.items(): - DIR = STUBS_DIR if args.embed else BUILD_DIR - with open(DIR + filename, "w") as outfile: + with open(os.path.join(BUILD_DIR, filename), "w") as outfile: json.dump(stub_data, outfile, cls=BytesEncoder, indent=4) @@ -79,9 +77,6 @@ def stub_name(filename): if __name__ == "__main__": parser = argparse.ArgumentParser() - parser.add_argument( - "--embed", help="Embed stub json files into esptool.py", action="store_true" - ) parser.add_argument("elf_files", nargs="+", help="Stub ELF files to convert") args = parser.parse_args() diff --git a/setup.py b/setup.py index 4b4d0490b..0f1b2826b 100644 --- a/setup.py +++ b/setup.py @@ -38,7 +38,7 @@ def find_version(*file_paths): if os.name != "nt": - scripts = ["esptool.py", "espefuse.py", "espsecure.py"] + scripts = ["esptool.py", "espefuse.py", "espsecure.py", "esp_rfc2217_server.py"] entry_points = {} else: scripts = [] @@ -47,6 +47,7 @@ def find_version(*file_paths): "esptool.py=esptool.__init__:_main", "espsecure.py=espsecure.__init__:_main", "espefuse.py=espefuse.__init__:_main", + "esp_rfc2217_server.py=esp_rfc2217_server:main", ], } @@ -100,6 +101,8 @@ def find_version(*file_paths): "Programming Language :: Python :: 3.8", "Programming Language :: Python :: 3.9", "Programming Language :: Python :: 3.10", + "Programming Language :: Python :: 3.11", + "Programming Language :: Python :: 3.12", ], python_requires=">=3.7", setup_requires=(["wheel"] if "bdist_wheel" in sys.argv else []), @@ -114,6 +117,7 @@ def find_version(*file_paths): "pre-commit", "pytest", "pytest-rerunfailures", + "requests", ], "hsm": [ "python-pkcs11", @@ -124,7 +128,9 @@ def find_version(*file_paths): "cryptography>=2.1.4", "ecdsa>=0.16.0", "pyserial>=3.0", - "reedsolo>=1.5.3,<=1.6.0", + "reedsolo>=1.5.3,<1.8", + "PyYAML>=5.1", + "intelhex", ], packages=find_packages(), include_package_data=True, diff --git a/test/.covconf b/test/.covconf index 07eaf71da..a36bbba25 100644 --- a/test/.covconf +++ b/test/.covconf @@ -1,2 +1,8 @@ [run] parallel = true + +[paths] +source = + ./ + ./ + C:\GitLab-Runner\builds\*\*\espressif\esptool\ \ No newline at end of file diff --git a/test/conftest.py b/test/conftest.py index 9cc2ff08a..b87fe5624 100644 --- a/test/conftest.py +++ b/test/conftest.py @@ -40,6 +40,18 @@ def pytest_configure(config): global arg_reset_port arg_reset_port = config.getoption("--reset-port") + # register custom markers + config.addinivalue_line( + "markers", + "host_test: mark esptool tests that run on the host machine only " + "(don't require a real chip connected).", + ) + + config.addinivalue_line( + "markers", + "quick_test: mark esptool tests checking basic functionality.", + ) + def need_to_install_package_err(): pytest.exit( diff --git a/test/images/bootloader_esp32_v5_2.bin b/test/images/bootloader_esp32_v5_2.bin new file mode 100644 index 000000000..d7a5cfb96 Binary files /dev/null and b/test/images/bootloader_esp32_v5_2.bin differ diff --git a/test/images/esp32c3_header_min_rev.bin b/test/images/esp32c3_header_min_rev.bin index 9c556e3ef..1422b596f 100644 Binary files a/test/images/esp32c3_header_min_rev.bin and b/test/images/esp32c3_header_min_rev.bin differ diff --git a/test/images/ram_helloworld/helloworld-esp32p4.bin b/test/images/ram_helloworld/helloworld-esp32p4.bin new file mode 100644 index 000000000..20dcef2b6 Binary files /dev/null and b/test/images/ram_helloworld/helloworld-esp32p4.bin differ diff --git a/test/images/ram_helloworld/source/Makefile b/test/images/ram_helloworld/source/Makefile index 050b2ce48..2d7eca65a 100644 --- a/test/images/ram_helloworld/source/Makefile +++ b/test/images/ram_helloworld/source/Makefile @@ -27,12 +27,13 @@ APP_ELF_32C3 = $(BUILD_DIR)/$(APP)-esp32c3.elf APP_ELF_32C2 = $(BUILD_DIR)/$(APP)-esp32c2.elf APP_ELF_32C6 = $(BUILD_DIR)/$(APP)-esp32c6.elf APP_ELF_32H2 = $(BUILD_DIR)/$(APP)-esp32h2.elf +APP_ELF_32P4 = $(BUILD_DIR)/$(APP)-esp32p4.elf .PHONY: all esp32 clean -all: $(APP_ELF_8266) $(APP_ELF_32) $(APP_ELF_32S2) $(APP_ELF_32C3) $(APP_ELF_32S3) $(APP_ELF_32C2) $(APP_ELF_32C6) $(APP_ELF_32H2) +all: $(APP_ELF_8266) $(APP_ELF_32) $(APP_ELF_32S2) $(APP_ELF_32C3) $(APP_ELF_32S3) $(APP_ELF_32C2) $(APP_ELF_32C6) $(APP_ELF_32H2) $(APP_ELF_32P4) -esp32: $(APP_ELF_32) $(APP_ELF_32S2) $(APP_ELF_32C3) $(APP_ELF_32S3) $(APP_ELF_32C2) $(APP_ELF_32C6) $(APP_ELF_32H2) +esp32: $(APP_ELF_32) $(APP_ELF_32S2) $(APP_ELF_32C3) $(APP_ELF_32S3) $(APP_ELF_32C2) $(APP_ELF_32C6) $(APP_ELF_32H2) $(APP_ELF_32P4) $(BUILD_DIR): $(Q) mkdir $@ @@ -82,5 +83,9 @@ $(APP_ELF_32H2): $(SRCS) $(BUILD_DIR) ld/app_32h2.ld @echo " CC(32H2) $^ -> $@" $(Q) $(CROSS_ESPRISCV32)gcc $(CFLAGS_ESPRISCV32) -DESP32H2=1 -Tapp_32h2.ld -Wl,-Map=$(@:.elf=.map) -o $@ $(filter %.c, $^) $(LDLIBS) +$(APP_ELF_32P4): $(SRCS) $(BUILD_DIR) ld/app_32p4.ld + @echo " CC(32P4) $^ -> $@" + $(Q) $(CROSS_ESPRISCV32)gcc $(CFLAGS_ESPRISCV32) -DESP32P4=1 -Tapp_32p4.ld -Wl,-Map=$(@:.elf=.map) -o $@ $(filter %.c, $^) $(LDLIBS) + clean: $(Q) rm -rf $(BUILD_DIR) diff --git a/test/images/ram_helloworld/source/ld/app_32.ld b/test/images/ram_helloworld/source/ld/app_32.ld index ab5e15f7d..2301e0bea 100644 --- a/test/images/ram_helloworld/source/ld/app_32.ld +++ b/test/images/ram_helloworld/source/ld/app_32.ld @@ -1,20 +1,3 @@ -/* - * Copyright (c) 2016 Cesanta Software Limited - * All rights reserved - * - * This program is free software; you can redistribute it and/or modify it under - * the terms of the GNU General Public License as published by the Free Software - * Foundation; either version 2 of the License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS - * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License along with - * this program; if not, write to the Free Software Foundation, Inc., 51 Franklin - * Street, Fifth Floor, Boston, MA 02110-1301 USA. - */ - MEMORY { iram : org = 0x4008c000, len = 0x1000 dram : org = 0x3ffc0000, len = 0xc000 diff --git a/test/images/ram_helloworld/source/ld/app_32c2.ld b/test/images/ram_helloworld/source/ld/app_32c2.ld index f9bb37b4e..cb792b06c 100644 --- a/test/images/ram_helloworld/source/ld/app_32c2.ld +++ b/test/images/ram_helloworld/source/ld/app_32c2.ld @@ -1,10 +1,3 @@ -/* - * SPDX-FileCopyrightText: 2023 Espressif Systems (Shanghai) CO LTD - * - * SPDX-License-Identifier: GPL-2.0-or-later - */ - - MEMORY { iram : org = 0x40390000, len = 0x100 dram : org = 0x3FCD0000, len = 0x100 diff --git a/test/images/ram_helloworld/source/ld/app_32c3.ld b/test/images/ram_helloworld/source/ld/app_32c3.ld index a28a8a3aa..b9e1fe9db 100644 --- a/test/images/ram_helloworld/source/ld/app_32c3.ld +++ b/test/images/ram_helloworld/source/ld/app_32c3.ld @@ -1,9 +1,3 @@ -/* - * SPDX-FileCopyrightText: 2019-2022 Espressif Systems (Shanghai) CO LTD - * - * SPDX-License-Identifier: GPL-2.0-or-later - */ - MEMORY { iram : org = 0x403DFD00, len = 0x100 dram : org = 0x3FCDFD00, len = 0x100 diff --git a/test/images/ram_helloworld/source/ld/app_32c6.ld b/test/images/ram_helloworld/source/ld/app_32c6.ld index 91055f1ab..a046073a6 100644 --- a/test/images/ram_helloworld/source/ld/app_32c6.ld +++ b/test/images/ram_helloworld/source/ld/app_32c6.ld @@ -1,9 +1,3 @@ -/* - * SPDX-FileCopyrightText: 2023 Espressif Systems (Shanghai) CO LTD - * - * SPDX-License-Identifier: GPL-2.0-or-later - */ - MEMORY { iram : org = 0x40860000, len = 0x100 dram : org = 0x40870000, len = 0x100 diff --git a/test/images/ram_helloworld/source/ld/app_32h2.ld b/test/images/ram_helloworld/source/ld/app_32h2.ld index 766286255..1409330d1 100644 --- a/test/images/ram_helloworld/source/ld/app_32h2.ld +++ b/test/images/ram_helloworld/source/ld/app_32h2.ld @@ -1,9 +1,3 @@ -/* - * SPDX-FileCopyrightText: 2023 Espressif Systems (Shanghai) CO LTD - * - * SPDX-License-Identifier: GPL-2.0-or-later - */ - MEMORY { iram : org = 0x40804000, len = 0x100 dram : org = 0x40848000, len = 0x100 diff --git a/test/images/ram_helloworld/source/ld/app_32p4.ld b/test/images/ram_helloworld/source/ld/app_32p4.ld new file mode 100644 index 000000000..1a4589dd7 --- /dev/null +++ b/test/images/ram_helloworld/source/ld/app_32p4.ld @@ -0,0 +1,26 @@ +MEMORY { + iram : org = 0x4FF60000, len = 0x100 + dram : org = 0x4FF70000, len = 0x100 +} + +ENTRY(ram_main) + +SECTIONS { + .text : ALIGN(4) { + *(.literal) + *(.text .text.*) + } > iram + + .bss : ALIGN(4) { + _bss_start = ABSOLUTE(.); + *(.bss) + _bss_end = ABSOLUTE(.); + } > dram + + .data : ALIGN(4) { + *(.data) + *(.rodata .rodata.*) + } > dram +} + +INCLUDE "../../../../flasher_stub/ld/rom_32p4.ld" diff --git a/test/images/ram_helloworld/source/ld/app_32s2.ld b/test/images/ram_helloworld/source/ld/app_32s2.ld index 76811c12a..7caf884cd 100644 --- a/test/images/ram_helloworld/source/ld/app_32s2.ld +++ b/test/images/ram_helloworld/source/ld/app_32s2.ld @@ -1,9 +1,3 @@ -/* - * SPDX-FileCopyrightText: 2019-2022 Espressif Systems (Shanghai) CO LTD - * - * SPDX-License-Identifier: GPL-2.0-or-later - */ - MEMORY { iram : org = 0x40020000, len = 0x8000 dram : org = 0x3FFC8000, len = 0x8000 diff --git a/test/images/ram_helloworld/source/ld/app_32s3.ld b/test/images/ram_helloworld/source/ld/app_32s3.ld index 4d3d5da4d..ca263a1ef 100644 --- a/test/images/ram_helloworld/source/ld/app_32s3.ld +++ b/test/images/ram_helloworld/source/ld/app_32s3.ld @@ -1,9 +1,3 @@ -/* - * SPDX-FileCopyrightText: 2019-2022 Espressif Systems (Shanghai) CO LTD - * - * SPDX-License-Identifier: GPL-2.0-or-later - */ - MEMORY { iram : org = 0x40380000, len = 0x100 dram : org = 0x3FCA0000, len = 0x100 diff --git a/test/images/ram_helloworld/source/ld/app_8266.ld b/test/images/ram_helloworld/source/ld/app_8266.ld index 218b9e191..3b7a1e04d 100644 --- a/test/images/ram_helloworld/source/ld/app_8266.ld +++ b/test/images/ram_helloworld/source/ld/app_8266.ld @@ -1,20 +1,3 @@ -/* - * Copyright (c) 2016 Cesanta Software Limited - * All rights reserved - * - * This program is free software; you can redistribute it and/or modify it under - * the terms of the GNU General Public License as published by the Free Software - * Foundation; either version 2 of the License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS - * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License along with - * this program; if not, write to the Free Software Foundation, Inc., 51 Franklin - * Street, Fifth Floor, Boston, MA 02110-1301 USA. - */ - MEMORY { iram : org = 0x40108000, len = 0x2000 dram : org = 0x3FFE8000, len = 0x100 diff --git a/test/test_espefuse.py b/test/test_espefuse.py index 7179e711e..cb8ada0d0 100755 --- a/test/test_espefuse.py +++ b/test/test_espefuse.py @@ -1,7 +1,7 @@ # HOST_TEST for espefuse.py using the pytest framework # # Supports esp32, esp32s2, esp32s3beta2, esp32s3, -# esp32c3, esp32h2beta1, esp32c2, esp32c6 +# esp32c3, esp32h2beta1, esp32c2, esp32c6, esp32p4 # # How to use: # @@ -36,9 +36,9 @@ from conftest import arg_chip, arg_port, arg_reset_port, need_to_install_package_err TEST_DIR = os.path.abspath(os.path.dirname(__file__)) -IMAGES_DIR = os.path.join(TEST_DIR, "images/efuse/") -S_IMAGES_DIR = os.path.join(TEST_DIR, "secure_images/") -EFUSE_S_DIR = os.path.join(TEST_DIR, "efuse_scripts/") +IMAGES_DIR = os.path.join(TEST_DIR, "images", "efuse") +S_IMAGES_DIR = os.path.join(TEST_DIR, "secure_images") +EFUSE_S_DIR = os.path.join(TEST_DIR, "efuse_scripts") import pytest @@ -63,10 +63,11 @@ print("Running espefuse.py tests...") +@pytest.mark.host_test class EfuseTestCase: def setup_method(self): if reset_port is None: - self.efuse_file = tempfile.NamedTemporaryFile() + self.efuse_file = tempfile.NamedTemporaryFile(delete=False) self.base_cmd = ( f"{sys.executable} -m espefuse --chip {arg_chip} " f"--virt --path-efuse-file {self.efuse_file.name} -d" @@ -81,6 +82,7 @@ def setup_method(self): def teardown_method(self): if reset_port is None: self.efuse_file.close() + os.unlink(self.efuse_file.name) def reset_efuses(self): # reset and zero efuses @@ -178,12 +180,13 @@ def test_summary(self): def test_summary_json(self): self.espefuse_py("summary --format json") + @pytest.mark.skipif( + arg_chip == "esp32p4", reason="No Custom MAC Address defined yet" + ) def test_get_custom_mac(self): self.espefuse_py("get_custom_mac -h") if arg_chip == "esp32": right_msg = "Custom MAC Address is not set in the device." - elif arg_chip == "esp32h2beta1": - right_msg = "Custom MAC Address: 00:00:00:00:00:00:00:00 (OK)" else: right_msg = "Custom MAC Address: 00:00:00:00:00:00 (OK)" self.espefuse_py("get_custom_mac", check_msg=right_msg) @@ -277,9 +280,10 @@ def test_read_protect_efuse4(self): ret_code=2, ) else: + key1_purpose = "USER" if arg_chip in ["esp32p4"] else "RESERVED" self.espefuse_py( f"burn_key BLOCK_KEY0 {IMAGES_DIR}/256bit USER \ - BLOCK_KEY1 {IMAGES_DIR}/256bit RESERVED \ + BLOCK_KEY1 {IMAGES_DIR}/256bit {key1_purpose} \ BLOCK_KEY2 {IMAGES_DIR}/256bit SECURE_BOOT_DIGEST0 \ BLOCK_KEY3 {IMAGES_DIR}/256bit SECURE_BOOT_DIGEST1 \ BLOCK_KEY4 {IMAGES_DIR}/256bit SECURE_BOOT_DIGEST2 \ @@ -343,8 +347,12 @@ def test_write_protect_efuse(self): efuse_lists = """RD_DIS DIS_DOWNLOAD_ICACHE XTS_KEY_LENGTH_256 UART_PRINT_CONTROL""" efuse_lists2 = "RD_DIS DIS_DOWNLOAD_ICACHE" + elif arg_chip == "esp32p4": + efuse_lists = """RD_DIS KEY_PURPOSE_0 SECURE_BOOT_KEY_REVOKE0 + SPI_BOOT_CRYPT_CNT""" + efuse_lists2 = "RD_DIS KEY_PURPOSE_0 KEY_PURPOSE_2" else: - efuse_lists = """RD_DIS DIS_ICACHE DIS_DOWNLOAD_ICACHE DIS_FORCE_DOWNLOAD + efuse_lists = """RD_DIS DIS_ICACHE DIS_FORCE_DOWNLOAD DIS_CAN SOFT_DIS_JTAG DIS_DOWNLOAD_MANUAL_ENCRYPT USB_EXCHG_PINS WDT_DELAY_SEL SPI_BOOT_CRYPT_CNT SECURE_BOOT_KEY_REVOKE0 SECURE_BOOT_KEY_REVOKE1 @@ -352,14 +360,18 @@ def test_write_protect_efuse(self): KEY_PURPOSE_2 KEY_PURPOSE_3 KEY_PURPOSE_4 KEY_PURPOSE_5 SECURE_BOOT_EN SECURE_BOOT_AGGRESSIVE_REVOKE FLASH_TPUW DIS_DOWNLOAD_MODE - ENABLE_SECURITY_DOWNLOAD - UART_PRINT_CONTROL MAC SPI_PAD_CONFIG_CLK SPI_PAD_CONFIG_Q - SPI_PAD_CONFIG_D SPI_PAD_CONFIG_CS SPI_PAD_CONFIG_HD - SPI_PAD_CONFIG_WP SPI_PAD_CONFIG_DQS SPI_PAD_CONFIG_D4 - SPI_PAD_CONFIG_D5 SPI_PAD_CONFIG_D6 SPI_PAD_CONFIG_D7 - OPTIONAL_UNIQUE_ID + ENABLE_SECURITY_DOWNLOAD UART_PRINT_CONTROL + MAC OPTIONAL_UNIQUE_ID BLOCK_USR_DATA BLOCK_KEY0 BLOCK_KEY1 BLOCK_KEY2 BLOCK_KEY3 BLOCK_KEY4 BLOCK_KEY5""" + if arg_chip not in ["esp32h2", "esp32h2beta1"] and arg_chip not in [ + "esp32c6" + ]: + efuse_lists += """ DIS_DOWNLOAD_ICACHE + SPI_PAD_CONFIG_CLK SPI_PAD_CONFIG_Q + SPI_PAD_CONFIG_D SPI_PAD_CONFIG_CS SPI_PAD_CONFIG_HD + SPI_PAD_CONFIG_WP SPI_PAD_CONFIG_DQS SPI_PAD_CONFIG_D4 + SPI_PAD_CONFIG_D5 SPI_PAD_CONFIG_D6 SPI_PAD_CONFIG_D7""" efuse_lists2 = "RD_DIS DIS_ICACHE" self.espefuse_py(f"write_protect_efuse {efuse_lists}") output = self.espefuse_py(f"write_protect_efuse {efuse_lists2}") @@ -376,23 +388,18 @@ def test_write_protect_efuse2(self): ) +@pytest.mark.skipif(arg_chip == "esp32p4", reason="No Custom MAC Address defined yet") class TestBurnCustomMacCommands(EfuseTestCase): def test_burn_custom_mac(self): self.espefuse_py("burn_custom_mac -h") cmd = "burn_custom_mac AA:CD:EF:11:22:33" + mac = "aa:cd:ef:11:22:33" if arg_chip == "esp32": self.espefuse_py( - cmd, - check_msg="Custom MAC Address version 1: " - "aa:cd:ef:11:22:33 (CRC 0x63 OK)", + cmd, check_msg=f"Custom MAC Address version 1: {mac} (CRC 0x63 OK)" ) else: - mac_custom = ( - "aa:cd:ef:11:22:33:00:00" - if arg_chip == "esp32h2beta1" - else "aa:cd:ef:11:22:33" - ) - self.espefuse_py(cmd, check_msg=f"Custom MAC Address: {mac_custom} (OK)") + self.espefuse_py(cmd, check_msg=f"Custom MAC Address: {mac} (OK)") def test_burn_custom_mac2(self): self.espefuse_py( @@ -433,7 +440,7 @@ def test_burn_custom_mac_with_34_coding_scheme(self): @pytest.mark.skipif( - arg_chip in ["esp32c2", "esp32h2beta1", "esp32c3", "esp32c6", "esp32h2"], + arg_chip in ["esp32c2", "esp32h2beta1", "esp32c3", "esp32c6", "esp32h2", "esp32p4"], reason=f"TODO: add support set_flash_voltage for {arg_chip}", ) class TestSetFlashVoltageCommands(EfuseTestCase): @@ -619,6 +626,9 @@ def test_set_spi_flash_pin_efuses(self): assert "(Override SD_CMD pad (GPIO11/SPICS0)) 0b00000 -> 0b11111" in output assert "BURN BLOCK0 - OK (all write block bits are set)" in output + @pytest.mark.skipif( + arg_chip == "esp32p4", reason="No Custom MAC Address defined yet" + ) def test_burn_mac_custom_efuse(self): crc_msg = "(OK)" self.espefuse_py("burn_efuse -h") @@ -639,13 +649,11 @@ def test_burn_mac_custom_efuse(self): ret_code=2, ) self.espefuse_py("burn_efuse CUSTOM_MAC AA:CD:EF:01:02:03") - if arg_chip in ["esp32h2beta2", "esp32h2beta1"]: - self.espefuse_py( - "get_custom_mac", check_msg=f"aa:cd:ef:01:02:03:00:00 {crc_msg}" - ) - else: - self.espefuse_py("get_custom_mac", check_msg=f"aa:cd:ef:01:02:03 {crc_msg}") + self.espefuse_py("get_custom_mac", check_msg=f"aa:cd:ef:01:02:03 {crc_msg}") + @pytest.mark.skipif( + arg_chip == "esp32p4", reason="No such eFuses, will be defined later" + ) def test_burn_efuse(self): self.espefuse_py("burn_efuse -h") if arg_chip == "esp32": @@ -680,20 +688,19 @@ def test_burn_efuse(self): output = self.espefuse_py("summary -d") assert ( "read_regs: d6eae168 8f843a26 c9145f69 2328ad5a " - "00000000 00000000 00000000 00000000" in output - ) + "00000000 00000000 00000000 00000000" + ) in output assert "= 68 e1 ea d6 26 3a 84 8f 69 5f 14 c9 5a ad 28 23 R/W" in output efuse_from_blk2 = "BLK_VERSION_MAJOR" if arg_chip == "esp32s2": efuse_from_blk2 = "BLK_VERSION_MINOR" - if arg_chip == "esp32h2beta1": - efuse_from_blk2 = "BLOCK2_VERSION" - self.espefuse_py( - f"burn_efuse {efuse_from_blk2} 1", - check_msg="Burn into BLOCK_SYS_DATA is forbidden " - "(RS coding scheme does not allow this).", - ret_code=2, - ) + if arg_chip != "esp32c6": + self.espefuse_py( + f"burn_efuse {efuse_from_blk2} 1", + check_msg="Burn into BLOCK_SYS_DATA is forbidden " + "(RS coding scheme does not allow this).", + ret_code=2, + ) blk1 = "BLOCK_KEY1" blk2 = "BLOCK_KEY2" output = self.espefuse_py( @@ -707,12 +714,12 @@ def test_burn_efuse(self): output = self.espefuse_py("summary -d") assert ( "read_regs: 112233ff 11110000 11111111 11111111 " - "11111111 08091111 04050607 00010203" in output - ) + "11111111 08091111 04050607 00010203" + ) in output assert ( "= ff 33 22 11 00 00 11 11 11 11 11 11 11 11 11 11 " - "11 11 11 11 11 11 09 08 07 06 05 04 03 02 01 00 R/W" in output - ) + "11 11 11 11 11 11 09 08 07 06 05 04 03 02 01 00 R/W" + ) in output if blk2 is not None: output = self.espefuse_py( @@ -726,12 +733,12 @@ def test_burn_efuse(self): output = self.espefuse_py("summary -d") assert ( "read_regs: 03020100 07060504 11110908 11111111 " - "11111111 11111111 00001111 ff332211" in output - ) + "11111111 11111111 00001111 ff332211" + ) in output assert ( "= 00 01 02 03 04 05 06 07 08 09 11 11 11 11 11 11 " - "11 11 11 11 11 11 11 11 11 11 00 00 11 22 33 ff R/W" in output - ) + "11 11 11 11 11 11 11 11 11 11 00 00 11 22 33 ff R/W" + ) in output @pytest.mark.skipif( arg_chip != "esp32", reason="3/4 coding scheme is only in esp32" @@ -811,8 +818,15 @@ def test_burn_key_1_key_block(self): self.espefuse_py(f"burn_key BLOCK_KEY0 {IMAGES_DIR}/256bit XTS_AES_128_KEY") output = self.espefuse_py("summary -d") - assert "[3 ] read_regs: 00000000 00000000 00000000 00000000 " - "00000000 00000000 00000000 00000000" in output + assert ( + "[3 ] read_regs: 00000000 00000000 00000000 00000000 " + "00000000 00000000 00000000 00000000" + ) in output + + assert ( + "= ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? " + "?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? -/-" + ) in output @pytest.mark.skipif(arg_chip != "esp32c2", reason="ESP32-C2-only") def test_burn_key_one_key_block_with_fe_and_sb_keys(self): @@ -830,8 +844,10 @@ def test_burn_key_one_key_block_with_fe_and_sb_keys(self): f"BLOCK_KEY0 {IMAGES_DIR}/128bit_key SECURE_BOOT_DIGEST --no-read-protect" ) output = self.espefuse_py("summary -d") - assert "[3 ] read_regs: 0c0d0e0f 08090a0b 04050607 00010203 " - "03020100 07060504 0b0a0908 0f0e0d0c" in output + assert ( + "[3 ] read_regs: 0c0d0e0f 08090a0b 04050607 00010203 " + "03020100 07060504 0b0a0908 0f0e0d0c" + ) in output self.espefuse_py( f"burn_key BLOCK_KEY0 {IMAGES_DIR}/128bit_key " @@ -839,8 +855,17 @@ def test_burn_key_one_key_block_with_fe_and_sb_keys(self): f"BLOCK_KEY0 {IMAGES_DIR}/128bit_key SECURE_BOOT_DIGEST" ) output = self.espefuse_py("summary -d") - assert "[3 ] read_regs: 00000000 00000000 00000000 00000000 " - "03020100 07060504 0b0a0908 0f0e0d0c" in output + assert ( + "[3 ] read_regs: 00000000 00000000 00000000 00000000 " + "03020100 07060504 0b0a0908 0f0e0d0c" + ) in output + + assert ( + "= ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? " + "00 01 02 03 04 05 06 07 08 09 0a 0b 0c 0d 0e 0f -/-" + ) in output + assert "= ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? -/-" in output + assert "= 00 01 02 03 04 05 06 07 08 09 0a 0b 0c 0d 0e 0f R/-" in output @pytest.mark.skipif( arg_chip @@ -849,10 +874,10 @@ def test_burn_key_one_key_block_with_fe_and_sb_keys(self): "esp32s3", "esp32s3beta1", "esp32c3", - "esp32h2beta2", "esp32h2beta1", "esp32c6", "esp32h2", + "esp32p4", ], reason="Only chips with 6 keys", ) @@ -861,7 +886,10 @@ def test_burn_key_with_6_keys(self): BLOCK_KEY0 {IMAGES_DIR}/256bit XTS_AES_256_KEY_1 \ BLOCK_KEY1 {IMAGES_DIR}/256bit_1 XTS_AES_256_KEY_2 \ BLOCK_KEY2 {IMAGES_DIR}/256bit_2 XTS_AES_128_KEY" - if arg_chip in ["esp32c3", "esp32c6", "esp32h2"]: + if arg_chip in ["esp32c3", "esp32c6"] or arg_chip in [ + "esp32h2", + "esp32h2beta1", + ]: cmd = cmd.replace("XTS_AES_256_KEY_1", "XTS_AES_128_KEY") cmd = cmd.replace("XTS_AES_256_KEY_2", "XTS_AES_128_KEY") self.espefuse_py(cmd + " --no-read-protect --no-write-protect") @@ -876,12 +904,18 @@ def test_burn_key_with_6_keys(self): self.espefuse_py(cmd) output = self.espefuse_py("summary -d") - assert "[4 ] read_regs: 00000000 00000000 00000000 00000000 " - "00000000 00000000 00000000 00000000" in output - assert "[5 ] read_regs: 00000000 00000000 00000000 00000000 " - "00000000 00000000 00000000 00000000" in output - assert "[6 ] read_regs: 00000000 00000000 00000000 00000000 " - "00000000 00000000 00000000 00000000" in output + assert ( + "[4 ] read_regs: 00000000 00000000 00000000 00000000 " + "00000000 00000000 00000000 00000000" + ) in output + assert ( + "[5 ] read_regs: 00000000 00000000 00000000 00000000 " + "00000000 00000000 00000000 00000000" + ) in output + assert ( + "[6 ] read_regs: 00000000 00000000 00000000 00000000 " + "00000000 00000000 00000000 00000000" + ) in output self.espefuse_py( f"burn_key \ @@ -956,20 +990,19 @@ def test_burn_key_512bit_non_consecutive_blocks(self): f"burn_key \ BLOCK_KEY2 {IMAGES_DIR}/256bit XTS_AES_128_KEY" ) - self.espefuse_py( - f"burn_key \ - BLOCK_KEY3 {IMAGES_DIR}/256bit USER --no-read-protect --no-write-protect" - ) self.espefuse_py( f"burn_key \ BLOCK_KEY4 {IMAGES_DIR}/256bit SECURE_BOOT_DIGEST0" ) - self.espefuse_py( f"burn_key \ BLOCK_KEY1 {IMAGES_DIR}/256bit_1_256bit_2_combined \ XTS_AES_256_KEY --no-read-protect --no-write-protect" ) + self.espefuse_py( + f"burn_key \ + BLOCK_KEY5 {IMAGES_DIR}/256bit USER --no-read-protect --no-write-protect" + ) # Second half of key should burn to first available key block (BLOCK_KEY5) output = self.espefuse_py("summary -d") @@ -980,10 +1013,14 @@ def test_burn_key_512bit_non_consecutive_blocks(self): output, f"{IMAGES_DIR}/256bit_2", reverse_order=True ) - assert "[5 ] read_regs: bcbd11bf b8b9babb b4b5b6b7 " - "b0b1b2b3 acadaeaf a8a9aaab a4a5a6a7 11a1a2a3" in output - assert "[9 ] read_regs: bcbd22bf b8b9babb b4b5b6b7 " - "b0b1b2b3 acadaeaf a8a9aaab a4a5a6a7 22a1a2a3" in output + assert ( + "[5 ] read_regs: bcbd11bf b8b9babb b4b5b6b7 " + "b0b1b2b3 acadaeaf a8a9aaab a4a5a6a7 11a1a2a3" + ) in output + assert ( + "[7 ] read_regs: bcbd22bf b8b9babb b4b5b6b7 " + "b0b1b2b3 acadaeaf a8a9aaab a4a5a6a7 22a1a2a3" + ) in output @pytest.mark.skipif( arg_chip not in ["esp32s2", "esp32s3"], @@ -1009,10 +1046,71 @@ def test_burn_key_512bit_non_consecutive_blocks_loop_around(self): output, f"{IMAGES_DIR}/256bit_2", reverse_order=True ) - assert "[5 ] read_regs: bcbd11bf b8b9babb b4b5b6b7 b0b1b2b3 " - "acadaeaf a8a9aaab a4a5a6a7 11a1a2a3" in output - assert "[4 ] read_regs: bcbd22bf b8b9babb b4b5b6b7 b0b1b2b3 " - "acadaeaf a8a9aaab a4a5a6a7 22a1a2a3" in output + assert ( + "[5 ] read_regs: bcbd11bf b8b9babb b4b5b6b7 b0b1b2b3 " + "acadaeaf a8a9aaab a4a5a6a7 11a1a2a3" + ) in output + assert ( + "[4 ] read_regs: bcbd22bf b8b9babb b4b5b6b7 b0b1b2b3 " + "acadaeaf a8a9aaab a4a5a6a7 22a1a2a3" + ) in output + + @pytest.mark.skipif( + arg_chip not in ["esp32h2", "esp32p4"], + reason="These chips support ECDSA_KEY", + ) + def test_burn_key_ecdsa_key(self): + self.espefuse_py( + f"burn_key \ + BLOCK_KEY0 {S_IMAGES_DIR}/ecdsa192_secure_boot_signing_key_v2.pem \ + ECDSA_KEY \ + BLOCK_KEY1 {S_IMAGES_DIR}/ecdsa256_secure_boot_signing_key_v2.pem \ + ECDSA_KEY" + ) + output = self.espefuse_py("summary -d") + assert 2 == output.count( + "= ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? " + "?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? -/-" + ) + assert ( + "[4 ] read_regs: 00000000 00000000 00000000 00000000 " + "00000000 00000000 00000000 00000000" + ) in output + assert ( + "[5 ] read_regs: 00000000 00000000 00000000 00000000 " + "00000000 00000000 00000000 00000000" + ) in output + + @pytest.mark.skipif( + arg_chip not in ["esp32h2", "esp32p4"], + reason="These chips support ECDSA_KEY", + ) + def test_burn_key_ecdsa_key_check_byte_order(self): + self.espefuse_py( + f"burn_key \ + BLOCK_KEY0 {S_IMAGES_DIR}/ecdsa192_secure_boot_signing_key_v2.pem \ + ECDSA_KEY \ + BLOCK_KEY1 {S_IMAGES_DIR}/ecdsa256_secure_boot_signing_key_v2.pem \ + ECDSA_KEY \ + --no-read-protect" + ) + output = self.espefuse_py("summary -d") + assert ( + "= c8 c4 5d 62 9e 05 05 bd cb 04 a4 7c 06 f5 86 14 " + "cb 23 81 23 95 b7 71 4f 00 00 00 00 00 00 00 00 R/-" + ) in output + assert ( + "= fc 6b ec 75 64 37 7d 3b 88 8d 34 05 ed 91 06 1b " + "38 c2 50 84 7a 08 9d c3 66 6a 06 90 23 8b 54 b4 R/-" + ) in output + assert ( + "[4 ] read_regs: 625dc4c8 bd05059e 7ca404cb 1486f506 " + "238123cb 4f71b795 00000000 00000000" + ) in output + assert ( + "[5 ] read_regs: 75ec6bfc 3b7d3764 05348d88 1b0691ed " + "8450c238 c39d087a 90066a66 b4548b23" + ) in output class TestBurnBlockDataCommands(EfuseTestCase): @@ -1035,8 +1133,10 @@ def test_burn_block_data_with_3_key_blocks(self): BLOCK3 {IMAGES_DIR}/256bit" ) output = self.espefuse_py("summary -d") - assert "[3 ] read_regs: a3a2a1a0 a7a6a5a4 abaaa9a8 afaeadac " - "b3b2b1b0 b7b6b5b4 bbbab9b8 bfbebdbc" in output + assert ( + "[3 ] read_regs: a3a2a1a0 a7a6a5a4 abaaa9a8 afaeadac " + "b3b2b1b0 b7b6b5b4 bbbab9b8 bfbebdbc" + ) in output self.check_data_block_in_log(output, f"{IMAGES_DIR}/256bit") self.espefuse_py( @@ -1067,10 +1167,14 @@ def test_burn_block_data_with_1_key_block(self): output = self.espefuse_py("summary -d") assert "[0 ] read_regs: 00000001 0000000c" in output assert "[1 ] read_regs: 03020100 07060504 000a0908" in output - assert "[2 ] read_regs: a3a2a1a0 a7a6a5a4 abaaa9a8 afaeadac " - "b3b2b1b0 b7b6b5b4 bbbab9b8 bfbebdbc" in output - assert "[3 ] read_regs: a3a2a1a0 a7a6a5a4 abaaa9a8 afaeadac " - "b3b2b1b0 b7b6b5b4 bbbab9b8 bfbebdbc" in output + assert ( + "[2 ] read_regs: a3a2a1a0 a7a6a5a4 abaaa9a8 afaeadac " + "b3b2b1b0 b7b6b5b4 bbbab9b8 bfbebdbc" + ) in output + assert ( + "[3 ] read_regs: a3a2a1a0 a7a6a5a4 abaaa9a8 afaeadac " + "b3b2b1b0 b7b6b5b4 bbbab9b8 bfbebdbc" + ) in output @pytest.mark.skipif( arg_chip @@ -1079,10 +1183,10 @@ def test_burn_block_data_with_1_key_block(self): "esp32s3", "esp32s3beta1", "esp32c3", - "esp32h2beta2", "esp32h2beta1", "esp32c6", "esp32h2", + "esp32p4", ], reason="Only chip with 6 keys", ) @@ -1097,8 +1201,10 @@ def test_burn_block_data_with_6_keys(self): "[0 ] read_regs: 00000000 07060500 00000908 00000000 13000000 00161514" in output ) - assert "[3 ] read_regs: a3a2a1a0 a7a6a5a4 abaaa9a8 afaeadac " - "b3b2b1b0 b7b6b5b4 bbbab9b8 bfbebdbc" in output + assert ( + "[3 ] read_regs: a3a2a1a0 a7a6a5a4 abaaa9a8 afaeadac " + "b3b2b1b0 b7b6b5b4 bbbab9b8 bfbebdbc" + ) in output self.check_data_block_in_log(output, f"{IMAGES_DIR}/256bit") self.espefuse_py( @@ -1195,8 +1301,10 @@ def test_burn_block_data_with_offset_1_key_block(self): f"burn_block_data --offset {offset} BLOCK2 {IMAGES_DIR}/192bit_1" ) output = self.espefuse_py("summary -d") - assert "[2 ] read_regs: 00000000 00110000 05000000 09080706 " - "0d0c0b0a 11100f0e 15141312 00002116" in output + assert ( + "[2 ] read_regs: 00000000 00110000 05000000 09080706 " + "0d0c0b0a 11100f0e 15141312 00002116" + ) in output offset = 8 self.espefuse_py( @@ -1213,10 +1321,10 @@ def test_burn_block_data_with_offset_1_key_block(self): "esp32s3", "esp32s3beta1", "esp32c3", - "esp32h2beta2", "esp32h2beta1", "esp32c6", "esp32h2", + "esp32p4", ], reason="Only chips with 6 keys", ) @@ -1309,8 +1417,10 @@ def test_burn_key_digest(self): f"burn_key_digest {S_IMAGES_DIR}/rsa_secure_boot_signing_key.pem" ) output = self.espefuse_py("summary -d") - assert " = cb 27 91 a3 71 b0 c0 32 2b f7 37 04 78 ba 09 62 " - "22 4c ab 1c f2 28 78 79 e4 29 67 3e 7d a8 44 63 R/-" in output + assert ( + " = cb 27 91 a3 71 b0 c0 32 2b f7 37 04 78 ba 09 62 " + "22 4c ab 1c f2 28 78 79 e4 29 67 3e 7d a8 44 63 R/-" + ) in output else: self.espefuse_py( f"burn_key_digest {S_IMAGES_DIR}/rsa_secure_boot_signing_key.pem", @@ -1352,8 +1462,10 @@ def test_burn_key_digest1(self): ) output = self.espefuse_py("summary -d") assert " = 1e 3d 15 16 96 ca 7f 22 a6 e8 8b d5 27 a0 3b 3b R/-" in output - assert " = 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 " - "1e 3d 15 16 96 ca 7f 22 a6 e8 8b d5 27 a0 3b 3b R/-" in output + assert ( + " = 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 " + "1e 3d 15 16 96 ca 7f 22 a6 e8 8b d5 27 a0 3b 3b R/-" + ) in output def test_burn_key_digest2(self): # python espsecure.py generate_signing_key --version 2 @@ -1364,8 +1476,10 @@ def test_burn_key_digest2(self): ) output = self.espefuse_py("summary -d") assert " = bf 0f 6a f6 8b d3 6d 8b 53 b3 da a9 33 f6 0a 04 R/-" in output - assert " = 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 " - "bf 0f 6a f6 8b d3 6d 8b 53 b3 da a9 33 f6 0a 04 R/-" in output + assert ( + " = 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 " + "bf 0f 6a f6 8b d3 6d 8b 53 b3 da a9 33 f6 0a 04 R/-" + ) in output def test_burn_key_from_digest1(self): # python espsecure.py digest_sbv2_public_key --keyfile @@ -1376,8 +1490,10 @@ def test_burn_key_from_digest1(self): f"{S_IMAGES_DIR}/ecdsa192_public_key_digest_v2.bin SECURE_BOOT_DIGEST" ) output = self.espefuse_py("summary -d") - assert " = 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 " - "1e 3d 15 16 96 ca 7f 22 a6 e8 8b d5 27 a0 3b 3b R/-" in output + assert ( + " = 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 " + "1e 3d 15 16 96 ca 7f 22 a6 e8 8b d5 27 a0 3b 3b R/-" + ) in output def test_burn_key_from_digest2(self): # python espsecure.py digest_sbv2_public_key --keyfile @@ -1388,8 +1504,10 @@ def test_burn_key_from_digest2(self): f"{S_IMAGES_DIR}/ecdsa256_public_key_digest_v2.bin SECURE_BOOT_DIGEST" ) output = self.espefuse_py("summary -d") - assert " = 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 " - "bf 0f 6a f6 8b d3 6d 8b 53 b3 da a9 33 f6 0a 04 R/-" in output + assert ( + " = 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 " + "bf 0f 6a f6 8b d3 6d 8b 53 b3 da a9 33 f6 0a 04 R/-" + ) in output @pytest.mark.skipif( @@ -1399,10 +1517,10 @@ def test_burn_key_from_digest2(self): "esp32s3", "esp32s3beta1", "esp32c3", - "esp32h2beta2", "esp32h2beta1", "esp32c6", "esp32h2", + "esp32p4", ], reason="Supports 6 key blocks", ) @@ -1511,10 +1629,10 @@ def test_burn_bit_for_chips_with_1_key_block(self): "esp32s3", "esp32s3beta1", "esp32c3", - "esp32h2beta2", "esp32h2beta1", "esp32c6", "esp32h2", + "esp32p4", ], reason="Only chip with 6 keys", ) @@ -1591,12 +1709,18 @@ def test_1_secure_boot_v1(self): secure_boot_v1 {IMAGES_DIR}/256bit_1" ) output = self.espefuse_py("summary -d") - assert "[1 ] read_regs: 00000000 00000000 00000000 00000000 " - "00000000 00000000 00000000 00000000" in output - assert "[2 ] read_regs: 00000000 00000000 00000000 00000000 " - "00000000 00000000 00000000 00000000" in output - assert "[3 ] read_regs: 00000000 00000000 00000000 00000000 " - "00000000 00000000 00000000 00000000" in output + assert ( + "[1 ] read_regs: 00000000 00000000 00000000 00000000 " + "00000000 00000000 00000000 00000000" + ) in output + assert ( + "[2 ] read_regs: 00000000 00000000 00000000 00000000 " + "00000000 00000000 00000000 00000000" + ) in output + assert ( + "[3 ] read_regs: 00000000 00000000 00000000 00000000 " + "00000000 00000000 00000000 00000000" + ) in output def test_2_secure_boot_v1(self): if arg_chip == "esp32": @@ -1619,8 +1743,10 @@ def test_2_secure_boot_v1(self): secure_boot_v2 {IMAGES_DIR}/256bit_1" ) output = self.espefuse_py("summary -d") - assert "[1 ] read_regs: 00000000 00000000 00000000 00000000 " - "00000000 00000000 00000000 00000000" in output + assert ( + "[1 ] read_regs: 00000000 00000000 00000000 00000000 " + "00000000 00000000 00000000 00000000" + ) in output self.check_data_block_in_log( output, f"{IMAGES_DIR}/256bit_1", reverse_order=False ) @@ -1637,14 +1763,20 @@ def teardown_class(self): # Restore the stored working directory os.chdir(self.stored_dir) - @pytest.mark.skipif(arg_chip == "esp32c2", reason="TODO: Add tests for esp32c2") + @pytest.mark.skipif( + arg_chip in ["esp32c2", "esp32p4"], + reason="These chips do not have eFuses used in this test", + ) def test_execute_scripts_with_check_that_only_one_burn(self): self.espefuse_py("execute_scripts -h") name = arg_chip if arg_chip in ["esp32", "esp32c2"] else "esp32xx" os.chdir(os.path.join(TEST_DIR, "efuse_scripts", name)) self.espefuse_py("execute_scripts execute_efuse_script2.py") - @pytest.mark.skipif(arg_chip == "esp32c2", reason="TODO: Add tests for esp32c2") + @pytest.mark.skipif( + arg_chip in ["esp32c2", "esp32p4"], + reason="These chips do not have eFuses used in this test", + ) def test_execute_scripts_with_check(self): self.espefuse_py("execute_scripts -h") name = arg_chip if arg_chip in ["esp32", "esp32c2"] else "esp32xx" @@ -1662,11 +1794,15 @@ def test_execute_scripts_with_index_and_config(self): self.espefuse_py(cmd) output = self.espefuse_py("summary -d") if arg_chip in ["esp32", "esp32c2"]: - assert "[3 ] read_regs: e00007ff 00000000 00000000 00000000 " - "00000000 00000000 00000000 00000000" in output + assert ( + "[3 ] read_regs: e00007ff 00000000 00000000 00000000 " + "00000000 00000000 00000000 00000000" + ) in output else: - assert "[8 ] read_regs: e00007ff 00000000 00000000 00000000 " - "00000000 00000000 00000000 00000000" in output + assert ( + "[8 ] read_regs: e00007ff 00000000 00000000 00000000 " + "00000000 00000000 00000000 00000000" + ) in output def test_execute_scripts_nesting(self): os.chdir(TEST_DIR) @@ -1679,15 +1815,23 @@ def test_execute_scripts_nesting(self): self.espefuse_py(cmd) output = self.espefuse_py("summary -d") if arg_chip in ["esp32", "esp32c2"]: - assert "[2 ] read_regs: 10000000 00000000 00000000 00000000 " - "00000000 00000000 00000000 00000000" in output - assert "[3 ] read_regs: ffffffff 00000000 00000000 00000000 " - "00000000 00000000 00000000 00000000" in output + assert ( + "[2 ] read_regs: 10000000 00000000 00000000 00000000 " + "00000000 00000000 00000000 00000000" + ) in output + assert ( + "[3 ] read_regs: ffffffff 00000000 00000000 00000000 " + "00000000 00000000 00000000 00000000" + ) in output else: - assert "[7 ] read_regs: 10000000 00000000 00000000 00000000 " - "00000000 00000000 00000000 00000000" in output - assert "[8 ] read_regs: ffffffff 00000000 00000000 00000000 " - "00000000 00000000 00000000 00000000" in output + assert ( + "[7 ] read_regs: 10000000 00000000 00000000 00000000 " + "00000000 00000000 00000000 00000000" + ) in output + assert ( + "[8 ] read_regs: ffffffff 00000000 00000000 00000000 " + "00000000 00000000 00000000 00000000" + ) in output class TestMultipleCommands(EfuseTestCase): @@ -1736,8 +1880,10 @@ def test_1_esp32c2(self): summary" ) output = self.espefuse_py("summary -d") - assert "[3 ] read_regs: 0c0d0e0f 08090a0b 04050607 00010203 " - "f66a0fbf 8b6dd38b a9dab353 040af633" in output + assert ( + "[3 ] read_regs: 0c0d0e0f 08090a0b 04050607 00010203 " + "f66a0fbf 8b6dd38b a9dab353 040af633" + ) in output assert " = 0f 0e 0d 0c 0b 0a 09 08 07 06 05 04 03 02 01 00 R/-" in output assert " = bf 0f 6a f6 8b d3 6d 8b 53 b3 da a9 33 f6 0a 04 R/-" in output @@ -1752,8 +1898,10 @@ def test_2_esp32c2(self): summary" ) output = self.espefuse_py("summary -d") - assert "[3 ] read_regs: 00000000 00000000 00000000 00000000 " - "f66a0fbf 8b6dd38b a9dab353 040af633" in output + assert ( + "[3 ] read_regs: 00000000 00000000 00000000 00000000 " + "f66a0fbf 8b6dd38b a9dab353 040af633" + ) in output assert " = ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? -/-" in output assert " = bf 0f 6a f6 8b d3 6d 8b 53 b3 da a9 33 f6 0a 04 R/-" in output @@ -1778,3 +1926,54 @@ def test_not_burn_cmds(self): adc_info \ check_error" ) + + +@pytest.mark.skipif( + arg_chip not in ["esp32c3", "esp32c6", "esp32h2", "esp32s3"], + reason="These chips have a hardware bug that limits the use of the KEY5", +) +class TestKeyPurposes(EfuseTestCase): + def test_burn_xts_aes_key_purpose(self): + self.espefuse_py( + "burn_efuse KEY_PURPOSE_5 XTS_AES_128_KEY", + check_msg="A fatal error occurred: " + "KEY_PURPOSE_5 can not have XTS_AES_128_KEY " + "key due to a hardware bug (please see TRM for more details)", + ret_code=2, + ) + + @pytest.mark.skipif( + arg_chip != "esp32h2", reason="esp32h2 can not have ECDSA key in KEY5" + ) + def test_burn_ecdsa_key_purpose(self): + self.espefuse_py( + "burn_efuse KEY_PURPOSE_5 ECDSA_KEY", + check_msg="A fatal error occurred: " + "KEY_PURPOSE_5 can not have ECDSA_KEY " + "key due to a hardware bug (please see TRM for more details)", + ret_code=2, + ) + + def test_burn_xts_aes_key(self): + self.espefuse_py( + f"burn_key \ + BLOCK_KEY5 {IMAGES_DIR}/256bit XTS_AES_128_KEY", + check_msg="A fatal error occurred: " + "KEY_PURPOSE_5 can not have XTS_AES_128_KEY " + "key due to a hardware bug (please see TRM for more details)", + ret_code=2, + ) + + @pytest.mark.skipif( + arg_chip != "esp32h2", reason="esp32h2 can not have ECDSA key in KEY5" + ) + def test_burn_ecdsa_key(self): + self.espefuse_py( + f"burn_key \ + BLOCK_KEY5 {S_IMAGES_DIR}/ecdsa192_secure_boot_signing_key_v2.pem \ + ECDSA_KEY", + check_msg="A fatal error occurred: " + "KEY_PURPOSE_5 can not have ECDSA_KEY " + "key due to a hardware bug (please see TRM for more details)", + ret_code=2, + ) diff --git a/test/test_espsecure.py b/test/test_espsecure.py index f2c213a9d..90045ff40 100755 --- a/test/test_espsecure.py +++ b/test/test_espsecure.py @@ -24,6 +24,7 @@ TEST_DIR = os.path.abspath(os.path.dirname(__file__)) +@pytest.mark.host_test class EspSecureTestCase: def run_espsecure(self, args): """ @@ -181,7 +182,9 @@ def test_sign_v1_with_pre_calculated_signature(self): # Sign using pre-calculated signature + Verify signing_pubkey = "ecdsa_secure_boot_signing_pubkey.pem" pre_calculated_signature = "pre_calculated_bootloader_signature.bin" - with tempfile.NamedTemporaryFile() as output_file: + + try: + output_file = tempfile.NamedTemporaryFile(delete=False) args = self.SignArgs( "1", None, @@ -199,6 +202,9 @@ def test_sign_v1_with_pre_calculated_signature(self): "1", False, None, self._open(signing_pubkey), output_file ) espsecure.verify_signature(args) + finally: + output_file.close() + os.unlink(output_file.name) def test_sign_v2_data(self): signing_keys = [ @@ -207,7 +213,8 @@ def test_sign_v2_data(self): "ecdsa_secure_boot_signing_key.pem", ] for key in signing_keys: - with tempfile.NamedTemporaryFile() as output_file: + try: + output_file = tempfile.NamedTemporaryFile(delete=False) args = self.SignArgs( "2", [self._open(key)], @@ -223,10 +230,14 @@ def test_sign_v2_data(self): args = self.VerifyArgs("2", False, None, self._open(key), output_file) espsecure.verify_signature(args) + finally: + output_file.close() + os.unlink(output_file.name) def test_sign_v2_multiple_keys(self): # 3 keys + Verify with 3rd key - with tempfile.NamedTemporaryFile() as output_file: + try: + output_file = tempfile.NamedTemporaryFile(delete=False) args = self.SignArgs( "2", [ @@ -272,11 +283,15 @@ def test_sign_v2_multiple_keys(self): output_file, ) espsecure.verify_signature(args) + finally: + output_file.close() + os.unlink(output_file.name) def test_sign_v2_append_signatures(self): # Append signatures + Verify with an appended key # (bootloader_signed_v2.bin already signed with rsa_secure_boot_signing_key.pem) - with tempfile.NamedTemporaryFile() as output_file: + try: + output_file = tempfile.NamedTemporaryFile(delete=False) args = self.SignArgs( "2", [ @@ -321,10 +336,15 @@ def test_sign_v2_append_signatures(self): output_file, ) espsecure.verify_signature(args) + finally: + output_file.close() + os.unlink(output_file.name) def test_sign_v2_append_signatures_multiple_steps(self): # similar to previous test, but sign in two invocations - with tempfile.NamedTemporaryFile() as output_file1, tempfile.NamedTemporaryFile() as output_file2: # noqa E501 + try: + output_file1 = tempfile.NamedTemporaryFile(delete=False) + output_file2 = tempfile.NamedTemporaryFile(delete=False) args = self.SignArgs( "2", [self._open("rsa_secure_boot_signing_key2.pem")], @@ -379,6 +399,11 @@ def test_sign_v2_append_signatures_multiple_steps(self): output_file2, ) espsecure.verify_signature(args) + finally: + output_file1.close() + os.unlink(output_file1.name) + output_file2.close() + os.unlink(output_file2.name) def test_sign_v2_with_pre_calculated_signature(self): # Sign using pre-calculated signature + Verify @@ -393,7 +418,8 @@ def test_sign_v2_with_pre_calculated_signature(self): "pre_calculated_bootloader_signature_ecdsa256.bin", ] for pub_key, signature in zip(signing_keys, pre_calculated_signatures): - with tempfile.NamedTemporaryFile() as output_file: + try: + output_file = tempfile.NamedTemporaryFile(delete=False) args = self.SignArgs( "2", None, @@ -411,6 +437,9 @@ def test_sign_v2_with_pre_calculated_signature(self): "2", False, None, self._open(pub_key), output_file ) espsecure.verify_signature(args) + finally: + output_file.close() + os.unlink(output_file.name) def test_sign_v2_with_multiple_pre_calculated_signatures(self): # Sign using multiple pre-calculated signatures + Verify @@ -424,7 +453,8 @@ def test_sign_v2_with_multiple_pre_calculated_signatures(self): "pre_calculated_bootloader_signature_rsa.bin", "pre_calculated_bootloader_signature_rsa.bin", ] - with tempfile.NamedTemporaryFile() as output_file: + try: + output_file = tempfile.NamedTemporaryFile(delete=False) args = self.SignArgs( "2", None, @@ -442,6 +472,9 @@ def test_sign_v2_with_multiple_pre_calculated_signatures(self): "2", False, None, self._open(signing_pubkeys[0]), output_file ) espsecure.verify_signature(args) + finally: + output_file.close() + os.unlink(output_file.name) def test_verify_signature_signing_key(self): # correct key v1 diff --git a/test/test_esptool.py b/test/test_esptool.py index 7724c07e4..c625ea983 100755 --- a/test/test_esptool.py +++ b/test/test_esptool.py @@ -24,6 +24,8 @@ import time from socket import AF_INET, SOCK_STREAM, socket from time import sleep +from typing import List +from unittest.mock import MagicMock # Link command line options --port, --chip, --baud, --with-trace, and --preload-port from conftest import ( @@ -230,17 +232,21 @@ def teardown_class(self): def readback(self, offset, length): """Read contents of flash back, return to caller.""" - with tempfile.NamedTemporaryFile() as tf: # need a file we can read into + dump_file = tempfile.NamedTemporaryFile(delete=False) # a file we can read into + try: self.run_esptool( - f"--before default_reset read_flash {offset} {length} {tf.name}" + f"--before default_reset read_flash {offset} {length} {dump_file.name}" ) - with open(tf.name, "rb") as f: + with open(dump_file.name, "rb") as f: rb = f.read() - assert length == len( - rb - ), f"read_flash length {length} offset {offset:#x} yielded {len(rb)} bytes!" - return rb + assert length == len( + rb + ), f"read_flash length {length} offset {offset:#x} yielded {len(rb)} bytes!" + return rb + finally: + dump_file.close() + os.unlink(dump_file.name) def verify_readback(self, offset, length, compare_to, is_bootloader=False): rb = self.readback(offset, length) @@ -266,11 +272,14 @@ def verify_readback(self, offset, length, compare_to, is_bootloader=False): @pytest.mark.skipif(arg_chip != "esp32", reason="ESP32 only") class TestFlashEncryption(EsptoolTestCase): def valid_key_present(self): - esp = esptool.ESP32ROM(arg_port) - esp.connect() - efuses, _ = espefuse.get_efuses(esp=esp) - blk1_rd_en = efuses["BLOCK1"].is_readable() - return not blk1_rd_en + try: + esp = esptool.ESP32ROM(arg_port) + esp.connect() + efuses, _ = espefuse.get_efuses(esp=esp) + blk1_rd_en = efuses["BLOCK1"].is_readable() + return not blk1_rd_en + finally: + esp._port.close() def test_blank_efuse_encrypt_write_abort(self): """ @@ -366,10 +375,12 @@ def test_blank_efuse_encrypt_write_continue2(self): class TestFlashing(EsptoolTestCase): + @pytest.mark.quick_test def test_short_flash(self): self.run_esptool("write_flash 0x0 images/one_kb.bin") self.verify_readback(0, 1024, "images/one_kb.bin") + @pytest.mark.quick_test def test_highspeed_flash(self): self.run_esptool("write_flash 0x0 images/fifty_kb.bin", baud=921600) self.verify_readback(0, 50 * 1024, "images/fifty_kb.bin") @@ -379,6 +390,42 @@ def test_adjacent_flash(self): self.verify_readback(0, 4096, "images/sector.bin") self.verify_readback(4096, 50 * 1024, "images/fifty_kb.bin") + def test_short_flash_hex(self): + _, f = tempfile.mkstemp(suffix=".hex") + try: + self.run_esptool(f"merge_bin --format hex 0x0 images/one_kb.bin -o {f}") + self.run_esptool(f"write_flash 0x0 {f}") + self.verify_readback(0, 1024, "images/one_kb.bin") + finally: + os.unlink(f) + + def test_adjacent_flash_hex(self): + _, f1 = tempfile.mkstemp(suffix=".hex") + _, f2 = tempfile.mkstemp(suffix=".hex") + try: + self.run_esptool(f"merge_bin --format hex 0x0 images/sector.bin -o {f1}") + self.run_esptool( + f"merge_bin --format hex 0x1000 images/fifty_kb.bin -o {f2}" + ) + self.run_esptool(f"write_flash 0x0 {f1} 0x1000 {f2}") + self.verify_readback(0, 4096, "images/sector.bin") + self.verify_readback(4096, 50 * 1024, "images/fifty_kb.bin") + finally: + os.unlink(f1) + os.unlink(f2) + + def test_adjacent_flash_mixed(self): + _, f = tempfile.mkstemp(suffix=".hex") + try: + self.run_esptool( + f"merge_bin --format hex 0x1000 images/fifty_kb.bin -o {f}" + ) + self.run_esptool(f"write_flash 0x0 images/sector.bin 0x1000 {f}") + self.verify_readback(0, 4096, "images/sector.bin") + self.verify_readback(4096, 50 * 1024, "images/fifty_kb.bin") + finally: + os.unlink(f) + def test_adjacent_independent_flash(self): self.run_esptool("write_flash 0x0 images/sector.bin") self.verify_readback(0, 4096, "images/sector.bin") @@ -423,6 +470,7 @@ def test_correct_offset(self): ct = f.read() assert last_sector == ct + @pytest.mark.quick_test def test_no_compression_flash(self): self.run_esptool( "write_flash -u 0x0 images/sector.bin 0x1000 images/fifty_kb.bin" @@ -430,6 +478,7 @@ def test_no_compression_flash(self): self.verify_readback(0, 4096, "images/sector.bin") self.verify_readback(4096, 50 * 1024, "images/fifty_kb.bin") + @pytest.mark.quick_test @pytest.mark.skipif(arg_chip == "esp8266", reason="Added in ESP32") def test_compressed_nostub_flash(self): self.run_esptool( @@ -465,18 +514,24 @@ def test_length_not_aligned_4bytes(self): def test_length_not_aligned_4bytes_no_compression(self): self.run_esptool("write_flash -u 0x0 images/not_4_byte_aligned.bin") + @pytest.mark.quick_test + @pytest.mark.host_test def test_write_overlap(self): output = self.run_esptool_error( "write_flash 0x0 images/bootloader_esp32.bin 0x1000 images/one_kb.bin" ) assert "Detected overlap at address: 0x1000 " in output + @pytest.mark.quick_test + @pytest.mark.host_test def test_repeated_address(self): output = self.run_esptool_error( "write_flash 0x0 images/one_kb.bin 0x0 images/one_kb.bin" ) assert "Detected overlap at address: 0x0 " in output + @pytest.mark.quick_test + @pytest.mark.host_test def test_write_sector_overlap(self): # These two 1KB files don't overlap, # but they do both touch sector at 0x1000 so should fail @@ -492,19 +547,30 @@ def test_write_no_overlap(self): assert "Detected overlap at address" not in output def test_compressible_file(self): - with tempfile.NamedTemporaryFile() as f: + try: + input_file = tempfile.NamedTemporaryFile(delete=False) file_size = 1024 * 1024 - f.write(b"\x00" * file_size) - self.run_esptool(f"write_flash 0x10000 {f.name}") + input_file.write(b"\x00" * file_size) + input_file.close() + self.run_esptool(f"write_flash 0x10000 {input_file.name}") + finally: + os.unlink(input_file.name) def test_compressible_non_trivial_file(self): - with tempfile.NamedTemporaryFile() as f: + try: + input_file = tempfile.NamedTemporaryFile(delete=False) file_size = 1000 * 1000 same_bytes = 8000 for _ in range(file_size // same_bytes): - f.write(struct.pack("B", random.randrange(0, 1 << 8)) * same_bytes) - self.run_esptool(f"write_flash 0x10000 {f.name}") + input_file.write( + struct.pack("B", random.randrange(0, 1 << 8)) * same_bytes + ) + input_file.close() + self.run_esptool(f"write_flash 0x10000 {input_file.name}") + finally: + os.unlink(input_file.name) + @pytest.mark.quick_test def test_zero_length(self): # Zero length files are skipped with a warning output = self.run_esptool( @@ -513,6 +579,7 @@ def test_zero_length(self): self.verify_readback(0x10000, 1024, "images/one_kb.bin") assert "zerolength.bin is empty" in output + @pytest.mark.quick_test def test_single_byte(self): self.run_esptool("write_flash 0x0 images/onebyte.bin") self.verify_readback(0x0, 1, "images/onebyte.bin") @@ -568,10 +635,11 @@ def test_flash_with_min_max_rev(self): ) assert ( "images/esp32c3_header_min_rev.bin " - "requires chip revision in range [v0.10 - max rev not set]" in output + "requires chip revision in range [v2.55 - max rev not set]" in output ) assert "Use --force to flash anyway." in output + @pytest.mark.quick_test def test_erase_before_write(self): output = self.run_esptool("write_flash --erase-all 0x0 images/one_kb.bin") assert "Chip erase completed successfully" in output @@ -586,14 +654,16 @@ class TestSecurityInfo(EsptoolTestCase): def test_show_security_info(self): res = self.run_esptool("get_security_info") assert "Flags" in res - assert "Flash_Crypt_Cnt" in res - assert "Key_Purposes" in res + assert "Crypt Count" in res + assert "Key Purposes" in res if arg_chip != "esp32s2": esp = esptool.get_default_connected_device( [arg_port], arg_port, 10, 115200, arg_chip ) - assert f"Chip_ID: {esp.IMAGE_CHIP_ID}" in res - assert "Api_Version" in res + assert f"Chip ID: {esp.IMAGE_CHIP_ID}" in res + assert "API Version" in res + assert "Secure Boot" in res + assert "Flash Encryption" in res class TestFlashSizes(EsptoolTestCase): @@ -613,6 +683,8 @@ def test_large_no_compression(self): self.run_esptool("write_flash -u -fs 4MB 0x280000 images/one_mb.bin") self.verify_readback(0x280000, 0x100000, "images/one_mb.bin") + @pytest.mark.quick_test + @pytest.mark.host_test def test_invalid_size_arg(self): self.run_esptool_error("write_flash -fs 10MB 0x6000 images/one_kb.bin") @@ -650,23 +722,29 @@ def test_flash_size_keep(self): class TestFlashDetection(EsptoolTestCase): + @pytest.mark.quick_test def test_flash_id(self): """Test manufacturer and device response of flash detection.""" res = self.run_esptool("flash_id") assert "Manufacturer:" in res assert "Device:" in res + @pytest.mark.quick_test def test_flash_id_expand_args(self): """ Test manufacturer and device response of flash detection with expandable arg """ - with tempfile.NamedTemporaryFile() as tf: - tf.write(b"flash_id\n") - tf.seek(0) - res = self.run_esptool(f"@{tf.name}") + try: + arg_file = tempfile.NamedTemporaryFile(delete=False) + arg_file.write(b"flash_id\n") + arg_file.close() + res = self.run_esptool(f"@{arg_file.name}") assert "Manufacturer:" in res assert "Device:" in res + finally: + os.unlink(arg_file.name) + @pytest.mark.quick_test def test_flash_id_trace(self): """Test trace functionality on flash detection, running without stub""" res = self.run_esptool("--trace flash_id") @@ -686,6 +764,9 @@ def test_flash_id_trace(self): assert "Device:" in res +@pytest.mark.skipif( + os.name == "nt", reason="Temporarily disabled on windows" +) # TODO: ESPTOOL-673 class TestStubReuse(EsptoolTestCase): def test_stub_reuse_with_synchronization(self): """Keep the flasher stub running and reuse it the next time.""" @@ -716,6 +797,7 @@ def test_stub_reuse_without_synchronization(self): class TestErase(EsptoolTestCase): + @pytest.mark.quick_test def test_chip_erase(self): self.run_esptool("write_flash 0x10000 images/one_kb.bin") self.verify_readback(0x10000, 0x400, "images/one_kb.bin") @@ -734,6 +816,10 @@ def test_region_erase(self): empty = self.readback(0x10000, 0x1000) assert empty == b"\xFF" * 0x1000 + def test_region_erase_all(self): + res = self.run_esptool("erase_region 0x0 ALL") + assert re.search(r"Detected flash size: \d+[KM]B", res) is not None + def test_large_region_erase(self): # verifies that erasing a large region doesn't time out self.run_esptool("erase_region 0x0 0x100000") @@ -758,6 +844,7 @@ def test_overlap(self): class TestVerifyCommand(EsptoolTestCase): + @pytest.mark.quick_test def test_verify_success(self): self.run_esptool("write_flash 0x5000 images/one_kb.bin") self.run_esptool("verify_flash 0x5000 images/one_kb.bin") @@ -776,6 +863,7 @@ def test_verify_unaligned_length(self): class TestReadIdentityValues(EsptoolTestCase): + @pytest.mark.quick_test def test_read_mac(self): output = self.run_esptool("read_mac") mac = re.search(r"[0-9a-f:]{17}", output) @@ -795,6 +883,7 @@ def test_read_chip_id(self): class TestMemoryOperations(EsptoolTestCase): + @pytest.mark.quick_test def test_memory_dump(self): output = self.run_esptool("dump_mem 0x50000000 128 memout.bin") assert "Read 128 bytes" in output @@ -847,6 +936,7 @@ def test_keep_does_not_change_settings(self): arg_chip not in ["esp8266", "esp32", "esp32c3"], reason="Don't run for every chip, so other bootloader images are not needed", ) + @pytest.mark.quick_test def test_detect_size_changes_size(self): self.run_esptool( f"write_flash -fs detect {self.flash_offset:#x} {self.BL_IMAGE}" @@ -896,6 +986,16 @@ def test_explicit_set_size_freq_mode(self): class TestLoadRAM(EsptoolTestCase): # flashing an application not supporting USB-CDC will make # /dev/ttyACM0 disappear and USB-CDC tests will not work anymore + + def verify_output(self, expected_out: List[bytes]): + """Verify that at least one element of expected_out is in serial output""" + with serial.serial_for_url(arg_port, arg_baud) as p: + p.timeout = 5 + output = p.read(100) + print(f"Output: {output}") + assert any(item in output for item in expected_out) + + @pytest.mark.quick_test def test_load_ram(self): """Verify load_ram command @@ -903,15 +1003,28 @@ def test_load_ram(self): "Hello world!\n" to the serial port. """ self.run_esptool(f"load_ram images/ram_helloworld/helloworld-{arg_chip}.bin") - p = serial.serial_for_url(arg_port, arg_baud) - p.timeout = 5 - output = p.read(100) - print(f"Output: {output}") - assert ( - b"Hello world!" in output # xtensa - or b'\xce?\x13\x05\x04\xd0\x97A\x11"\xc4\x06\xc67\x04' in output # RISC-V + self.verify_output( + [b"Hello world!", b'\xce?\x13\x05\x04\xd0\x97A\x11"\xc4\x06\xc67\x04'] ) - p.close() + + def test_load_ram_hex(self): + """Verify load_ram command with hex file as input + + The "hello world" binary programs for each chip print + "Hello world!\n" to the serial port. + """ + _, f = tempfile.mkstemp(suffix=".hex") + try: + self.run_esptool( + f"merge_bin --format hex -o {f} 0x0 " + f"images/ram_helloworld/helloworld-{arg_chip}.bin" + ) + self.run_esptool(f"load_ram {f}") + self.verify_output( + [b"Hello world!", b'\xce?\x13\x05\x04\xd0\x97A\x11"\xc4\x06\xc67\x04'] + ) + finally: + os.unlink(f) class TestDeepSleepFlash(EsptoolTestCase): @@ -941,6 +1054,7 @@ class TestBootloaderHeaderRewriteCases(EsptoolTestCase): arg_chip not in ["esp8266", "esp32", "esp32c3"], reason="Don't run on every chip, so other bootloader images are not needed", ) + @pytest.mark.quick_test def test_flash_header_rewrite(self): bl_offset = 0x1000 if arg_chip in ("esp32", "esp32s2") else 0 bl_image = f"images/bootloader_{arg_chip}.bin" @@ -977,6 +1091,7 @@ def _check_output(self, output): assert f"Detecting chip type... {expected_chip_name}" in output assert f"Chip is {expected_chip_name}" in output + @pytest.mark.quick_test def test_auto_detect(self): output = self.run_esptool("chip_id", chip="auto") self._check_output(output) @@ -984,6 +1099,7 @@ def test_auto_detect(self): @pytest.mark.flaky(reruns=5) @pytest.mark.skipif(arg_preload_port is not False, reason="USB-to-UART bridge only") +@pytest.mark.skipif(os.name == "nt", reason="Linux/MacOS only") class TestVirtualPort(TestAutoDetect): def test_auto_detect_virtual_port(self): with ESPRFC2217Server() as server: @@ -1005,6 +1121,7 @@ def test_highspeed_flash_virtual_port(self): self.verify_readback(0, 50 * 1024, "images/fifty_kb.bin") +@pytest.mark.quick_test class TestReadWriteMemory(EsptoolTestCase): def _test_read_write(self, esp): # find the start of one of these named memory regions @@ -1035,19 +1152,26 @@ def _test_read_write(self, esp): assert esp.read_reg(test_addr) == 0x555 finally: esp.write_reg(test_addr, val) # write the original value, non-destructive + esp._port.close() def test_read_write_memory_rom(self): - esp = esptool.get_default_connected_device( - [arg_port], arg_port, 10, 115200, arg_chip - ) - self._test_read_write(esp) + try: + esp = esptool.get_default_connected_device( + [arg_port], arg_port, 10, 115200, arg_chip + ) + self._test_read_write(esp) + finally: + esp._port.close() def test_read_write_memory_stub(self): - esp = esptool.get_default_connected_device( - [arg_port], arg_port, 10, 115200, arg_chip - ) - esp = esp.run_stub() - self._test_read_write(esp) + try: + esp = esptool.get_default_connected_device( + [arg_port], arg_port, 10, 115200, arg_chip + ) + esp = esp.run_stub() + self._test_read_write(esp) + finally: + esp._port.close() @pytest.mark.skipif( arg_chip != "esp32", reason="Could be unsupported by different flash" @@ -1063,11 +1187,31 @@ def test_read_write_flash_status(self): assert f"After flash status: {match.group(1)}" in res def test_read_chip_description(self): - esp = esptool.get_default_connected_device( - [arg_port], arg_port, 10, 115200, arg_chip - ) - chip = esp.get_chip_description() - assert "unknown" not in chip.lower() + try: + esp = esptool.get_default_connected_device( + [arg_port], arg_port, 10, 115200, arg_chip + ) + chip = esp.get_chip_description() + assert "unknown" not in chip.lower() + finally: + esp._port.close() + + def test_read_get_chip_features(self): + try: + esp = esptool.get_default_connected_device( + [arg_port], arg_port, 10, 115200, arg_chip + ) + + if hasattr(esp, "get_flash_cap") and esp.get_flash_cap() == 0: + esp.get_flash_cap = MagicMock(return_value=1) + if hasattr(esp, "get_psram_cap") and esp.get_psram_cap() == 0: + esp.get_psram_cap = MagicMock(return_value=1) + + features = ", ".join(esp.get_chip_features()) + assert "Unknown Embedded Flash" not in features + assert "Unknown Embedded PSRAM" not in features + finally: + esp._port.close() @pytest.mark.skipif( @@ -1107,6 +1251,7 @@ def test_make_image(self): @pytest.mark.skipif(arg_chip != "esp32", reason="Don't need to test multiple times") +@pytest.mark.quick_test class TestConfigFile(EsptoolTestCase): class ConfigFile: """ @@ -1134,6 +1279,7 @@ def __exit__(self, exc_type, exc_value, exc_tb): "serial_write_timeout = 12" ) + @pytest.mark.host_test def test_load_config_file(self): # Test a valid file is loaded config_file_path = os.path.join(os.getcwd(), "esptool.cfg") @@ -1171,6 +1317,7 @@ def test_load_config_file(self): output = self.run_esptool("version") assert f"Loaded custom configuration from {config_file_path}" in output + @pytest.mark.host_test def test_load_config_file_with_env_var(self): config_file_path = os.path.join(TEST_DIR, "custom_file.ini") with self.ConfigFile(config_file_path, self.dummy_config): diff --git a/test/test_image_info.py b/test/test_image_info.py index 1436cb4f5..3dac7310a 100755 --- a/test/test_image_info.py +++ b/test/test_image_info.py @@ -2,6 +2,7 @@ import os.path import subprocess import sys +import tempfile from conftest import need_to_install_package_err @@ -12,7 +13,7 @@ except ImportError: need_to_install_package_err() -IMAGES_DIR = os.path.join(os.path.abspath(os.path.dirname(__file__)), "images/") +IMAGES_DIR = os.path.join(os.path.abspath(os.path.dirname(__file__)), "images") ESP8266_BIN = "not_4_byte_aligned.bin" @@ -22,6 +23,7 @@ def read_image(filename): return f.read() +@pytest.mark.host_test class TestImageInfo: def run_image_info(self, chip, file, version=None): """Runs image_info on a binary file. @@ -39,7 +41,9 @@ def run_image_info(self, chip, file, version=None): ] if version is not None: cmd += ["--version", str(version)] - cmd += ["".join([IMAGES_DIR, file])] + # if path was passed use the whole path + # if file does not exists try to use file from IMAGES_DIR directory + cmd += [file] if os.path.isfile(file) else ["".join([IMAGES_DIR, os.sep, file])] print("\nExecuting {}".format(" ".join(cmd))) try: @@ -85,8 +89,8 @@ def test_v2_esp32c3(self): assert "Flash mode: DIO" in out, "Wrong flash mode" # Extended header - assert "WP pin: 0xee" in out, "Wrong WP pin" - assert "Chip ID: 5" in out, "Wrong chip ID" + assert "WP pin: 0xee (disabled)" in out, "Wrong WP pin" + assert "Chip ID: 5 (ESP32-C3)" in out, "Wrong chip ID" assert ( "clk_drv: 0x0, q_drv: 0x0, d_drv: 0x0, " "cs0_drv: 0x0, hd_drv: 0x0, wp_drv: 0x0" in out @@ -178,3 +182,53 @@ def test_application_info(self): assert "Application information" not in out out = self.run_image_info("auto", ESP8266_BIN, "2") assert "Application information" not in out + + def test_bootloader_info(self): + # This bootloader binary is built from "hello_world" project + # with default settings, IDF version is v5.2. + out = self.run_image_info("esp32", "bootloader_esp32_v5_2.bin", "2") + assert "File size: 26768 (bytes)" in out + assert "Bootloader information" in out + assert "Bootloader version: 1" in out + assert "ESP-IDF: v5.2-dev-254-g1950b15" in out + assert "Compile time: Apr 25 2023 00:13:32" in out + + def test_intel_hex(self): + # This bootloader binary is built from "hello_world" project + # with default settings, IDF version is v5.2. + # File is converted to Intel Hex using merge_bin + + def convert_bin2hex(file): + subprocess.check_output( + [ + sys.executable, + "-m", + "esptool", + "--chip", + "esp32", + "merge_bin", + "--format", + "hex", + "0x0", + "".join([IMAGES_DIR, os.sep, "bootloader_esp32_v5_2.bin"]), + "-o", + file, + ] + ) + + fd, file = tempfile.mkstemp(suffix=".hex") + try: + convert_bin2hex(file) + out = self.run_image_info("esp32", file, "2") + assert "File size: 26768 (bytes)" in out + assert "Bootloader information" in out + assert "Bootloader version: 1" in out + assert "ESP-IDF: v5.2-dev-254-g1950b15" in out + assert "Compile time: Apr 25 2023 00:13:32" in out + finally: + try: + # make sure that file was closed before removing it + os.close(fd) + except OSError: + pass + os.unlink(file) diff --git a/test/test_imagegen.py b/test/test_imagegen.py index d1d5c0c20..9756e3fc9 100755 --- a/test/test_imagegen.py +++ b/test/test_imagegen.py @@ -1,6 +1,7 @@ import hashlib import os import os.path +import re import struct import subprocess import sys @@ -36,6 +37,7 @@ def segment_matches_section(segment, section): return section.header.sh_addr == segment.addr and sh_size == len(segment.data) +@pytest.mark.host_test class BaseTestCase: @classmethod def setup_class(self): @@ -112,7 +114,7 @@ def assertImageContainsSection(self, image, elf, section_name): f" segment(s) in bin image (image segments: {image.segments})" ) - def assertImageInfo(self, binpath, chip="esp8266"): + def assertImageInfo(self, binpath, chip="esp8266", assert_sha=False): """ Run esptool.py image_info on a binary file, assert no red flags about contents. @@ -125,7 +127,13 @@ def assertImageInfo(self, binpath, chip="esp8266"): except subprocess.CalledProcessError as e: print(e.output) raise - assert "invalid" not in output, "Checksum calculation should be valid" + assert re.search( + r"Checksum: [a-fA-F0-9]{2} \(valid\)", output + ), "Checksum calculation should be valid" + if assert_sha: + assert re.search( + r"Validation Hash: [a-fA-F0-9]{64} \(valid\)", output + ), "SHA256 should be valid" assert ( "warning" not in output.lower() ), "Should be no warnings in image_info output" @@ -266,7 +274,11 @@ def _test_elf2image(self, elfpath, binpath, extra_args=[]): try: self.run_elf2image("esp32", elfpath, extra_args=extra_args) image = esptool.bin_image.LoadFirmwareImage("esp32", binpath) - self.assertImageInfo(binpath, "esp32") + self.assertImageInfo( + binpath, + "esp32", + True if "--ram-only-header" not in extra_args else False, + ) return image finally: try_delete(binpath) @@ -321,6 +333,13 @@ def test_use_segments(self): image = self._test_elf2image(ELF, BIN, ["--use_segments"]) assert len(image.segments) == 2 + def test_ram_only_header(self): + ELF = "esp32-app-template.elf" + BIN = "esp32-app-template.bin" + # --ram-only-header produces just 2 visible segments in the bin + image = self._test_elf2image(ELF, BIN, ["--ram-only-header"]) + assert len(image.segments) == 2 + class TestESP8266FlashHeader(BaseTestCase): def test_2mb(self): diff --git a/test/test_merge_bin.py b/test/test_merge_bin.py index 1c2d96ebb..83abbff92 100755 --- a/test/test_merge_bin.py +++ b/test/test_merge_bin.py @@ -1,9 +1,14 @@ +import filecmp +import hashlib import itertools import os import os.path +import random +import struct import subprocess import sys import tempfile +from functools import partial IMAGES_DIR = os.path.join(os.path.abspath(os.path.dirname(__file__)), "images") @@ -13,6 +18,8 @@ try: from esptool.util import byte + from esptool.uf2_writer import UF2Writer + from esptool.targets import CHIP_DEFS except ImportError: need_to_install_package_err() @@ -22,6 +29,7 @@ def read_image(filename): return f.read() +@pytest.mark.host_test class TestMergeBin: def run_merge_bin(self, chip, offsets_names, options=[]): """Run merge_bin on a list of (offset, filename) tuples @@ -188,3 +196,305 @@ def test_fill_flash_size_w_target_offset(self): assert bootloader == merged[: len(bootloader)] assert helloworld == merged[0xF000 : 0xF000 + len(helloworld)] self.assertAllFF(merged[0xF000 + len(helloworld) :]) + + def test_merge_mixed(self): + # convert bootloader to hex + hex = self.run_merge_bin( + "esp32", + [(0x1000, "bootloader_esp32.bin")], + options=["--format", "hex"], + ) + # create a temp file with hex content + with tempfile.NamedTemporaryFile(suffix=".hex", delete=False) as f: + f.write(hex) + # merge hex file with bin file + # output to bin file should be the same as in merge bin + bin + try: + merged = self.run_merge_bin( + "esp32", + [(0x1000, f.name), (0x10000, "ram_helloworld/helloworld-esp32.bin")], + ["--target-offset", "0x1000", "--fill-flash-size", "2MB"], + ) + finally: + os.unlink(f.name) + # full length is without target-offset arg + assert len(merged) == 0x200000 - 0x1000 + + bootloader = read_image("bootloader_esp32.bin") + helloworld = read_image("ram_helloworld/helloworld-esp32.bin") + assert bootloader == merged[: len(bootloader)] + assert helloworld == merged[0xF000 : 0xF000 + len(helloworld)] + self.assertAllFF(merged[0xF000 + len(helloworld) :]) + + def test_merge_bin2hex(self): + merged = self.run_merge_bin( + "esp32", + [ + (0x1000, "bootloader_esp32.bin"), + ], + options=["--format", "hex"], + ) + lines = merged.splitlines() + # hex format - :0300300002337A1E + # :03 0030 00 02337A 1E + # ^data_cnt/2 ^addr ^type ^data ^checksum + + # check for starting address - 0x1000 passed from arg + assert lines[0][3:7] == b"1000" + # pick a random line for testing the format + line = lines[random.randrange(0, len(lines))] + assert line[0] == ord(":") + data_len = int(b"0x" + line[1:3], 16) + # : + len + addr + type + data + checksum + assert len(line) == 1 + 2 + 4 + 2 + data_len * 2 + 2 + # last line is allways :00000001FF + assert lines[-1] == b":00000001FF" + # convert back and verify the result against the source bin file + with tempfile.NamedTemporaryFile(suffix=".hex", delete=False) as hex: + hex.write(merged) + merged_bin = self.run_merge_bin( + "esp32", + [(0x1000, hex.name)], + options=["--format", "raw"], + ) + source = read_image("bootloader_esp32.bin") + # verify that padding was done correctly + assert b"\xFF" * 0x1000 == merged_bin[:0x1000] + # verify the file itself + assert source == merged_bin[0x1000:] + + +class UF2Block(object): + def __init__(self, bs): + self.length = len(bs) + + # See https://github.com/microsoft/uf2 for the format + first_part = "<" + "I" * 8 + # payload is between + last_part = "