diff --git a/tools/esptool_py/CHANGELOG.md b/tools/esptool_py/CHANGELOG.md deleted file mode 100644 index f3d16e0b4c..0000000000 --- a/tools/esptool_py/CHANGELOG.md +++ /dev/null @@ -1,255 +0,0 @@ -## v4.8.1 (2024-09-25) - -### Bug Fixes - -- **esp32c2**: Add esp32c2 eco4 rom magic value -- **packaging**: Correctly exclude the unwanted sub/modules - -## v4.8.0 (2024-09-18) - -### New Features - -- **espefuse**: Supports wafer efuse versions for esp32c61 -- **esptool**: add new command SFDP read -- **esptool**: Add option to retry connection in a loop -- **efuse**: Updates efuse table for esp32c5 -- **efuse**: Updates efuse table for esp32p4 -- **esp32c61**: Added stub flasher support -- **cli**: add autocompletions -- **esptool**: allow picking UART by VID/PID/Name -- **esp32c5**: Add USB-serial/JTAG stub support -- **esp32c5**: Add UART stub support -- **esptool**: Print key_purpose name for get_security_info cmd -- **espefuse**: Adds support extend efuse table by user CSV file -- **espefuse**: Adds efuse dump formats: separated(default) and united(new) -- **espefuse**: Adds incompatible eFuse settings check for S3 -- **reset**: Apply reconnections to the whole reset sequence, not line transitions -- **reset**: Automatically reconnect if port disconnects during reset -- **esp32-p4**: Add ECO1 magic number -- **espsecure**: Add support for secure boot v2 using ECDSA-P384 signatures -- **write_flash**: retry flashing if chip disconnects -- **espefuse**: Allow filtering efuses based on command line arguments -- **esploader**: Enable context manager for esp instances -- **espefuse**: Added check for correctness of written data -- **espefuse**: Improves help for burn_efuse cmd -- **esp32s3**: clear boot control register on hard reset -- **esp32-p4**: add spi-connection restriction to ROM class -- add UF2 IDs for ESP32-C5 and ESP32-C61 -- **espefuse**: Updates efuses for C5 and C61 -- **esp32c61**: add c61 basic flash support (no_stub) -- **esp32c5**: skipped the stub check for esp32c5 mp -- **esp32c5**: base support of esp32c5 mp (no stub) -- Added warning when secure boot enabled -- **cmds/write_flash**: Recalculated SHA digest for image binary -- print flash voltage in flash_id command -- **esptool**: Adds wafer and pkg versions -- **espefuse**: Update adc_info commands for all chips -- **espefuse**: Adds new efuses for esp32p4 -- **espefuse**: Allow the espefuse.py to work when coding scheme == 3 -- **err_defs**: Add ROM bootloader flash error definitions -- Use ruff instead of flake8 and black both in pre-commit and CI -- **esp32p4**: Enable USB-serial/JTAG in flasher stub -- **espefuse**: Postpone some efuses to burn them at the very end -- add advisory port locking -- **espefuse**: check_error --recover chip even if there are num_errors -- **espefuse**: Adds new efuses for esp32c6 and esp32h2 -- **esp32c5**: add target esp32c5 beta3 - -### Bug Fixes - -- **esptool**: Fix esp32c61 flash frequency config -- **esptool**: Fix incorrect chip version for esp32c5 -- **write_flash**: Verify if files will fit against the real flash size when possible -- **remote_ports**: Disable reset sequence when a socket is used -- **bitstring**: Restricted bitstring dependency to fix 32-bit compatibility -- **esp32_d0wdr2_v3**: Print correct chip name -- pass error message to exception in OTG mode -- **bin_image**: add check for ELF file segment when saving RAM segments -- **docs**: Add a note about entering manual bootloader mode -- **esp32c5**: Fix MAC reading for esptool -- Erase non-aligned bytes with --no-stub -- **esp32-c5**: Use a longer reset delay with usb-serial/jtag to stabilize boot-up -- **espefuse**: Use stub class if stub flasher is running -- Do not append SHA256 when `--ram-only-header` -- **elf2image**: add ELF flags to merge condition -- ram_only_header: pad flash segment to next boundary -- sort segments if ram_only_header is used -- **espefuse**: Fix efuse base addr for esp32c5 MP -- fix type annotation to comply with mypy -- **espefuse**: Fix burn_key for ECDSA_KEY, it can read pem file -- **secure_download_mode**: Disable secure boot detection and print more info -- **esptool**: clear boot control register on ESP32-S3 -- **intelhex**: catch unicode decode errors when converting hex to binary -- ROM doesn't attach in-package flash chips -- close file gracefully in espsecure -- Fixed glitches on RTS line when no_reset option on Windows -- **merge_bin**: treat files starting with colon as raw files -- Index image segments from 0 instead of 1 -- **read_flash**: add flash size arg to enable reading past 2MB without stub -- **read_flash**: flush transmit buffer less often to inrease throughput -- **esptool**: Proper alignment for SoCs with offset load -- ignore resetting on unsupported ports -- **esptool**: Remove the shebang from uf2_writer.py - -### Code Refactoring - -- Migrated esp_rfc2217_server into standalone subpackage -- **test/esptool**: Updated tests according to SHA recomputation for binary -- **style**: Comply with black>=24.0.0 - -## v4.7.0 (2023-12-13) - -### New Features - -- **test_esptool**: Added test for embedded and detected flash size match -- **spi_connection**: Support --spi-connection on all chips -- **espefuse**: Support XTS_AES_256_KEY key_purpose for ESP32P4 -- **xip_psram**: support xip psram feature on esp32p4 -- add support for intel hex format -- **esp32p4**: Stub flasher support -- **elf2image**: add ram-only-header argument -- **rfc2217_server**: Add hard reset sequence -- **espefuse**: Adds efuse ADC calibration data for ESP32H2 -- **espefuse**: Update the way to complete the operation -- add support for get_security_info on esp32c3 ECO7 -- **loader**: Added hints for some serial port issues when rising port error -- Add support for Python 3.12 -- **esp32c3**: Support ECO6 and ECO7 magic numbers -- **merge_bin**: add support for uf2 format -- **esp32-s3**: Support >16MB quad flash chips -- **efuse**: Update key purpose table and tests -- **efuse**: ESP32P4 adds ecdsa_key support -- **espefuse**: Add support for esp32p4 chip -- **esptool**: added target to esp32p4 -- **espsecure**: Allow prompting for HSM PIN in read_hsm_config -- **esptool**: Add new packages for ESP32C3 and flash efuses -- **esptool**: Add tests for get_chip_features -- **esptool**: Add PICO package for ESP32S3 and flash/psram efuses -- **get_security_info**: Improved the output format and added more details - -### Bug Fixes - -- **esp32c2**: Added get_flash_cap and get_flash_vendor -- **testloadram**: Windows assertion error -- fixed exit() to be used from right module -- **esp32c2**: Recommend using higher baud rate if connection fails -- **test_esptool**: Fixed connection issue on Windows -- **esptool**: Rephrase the --ram-only-header command message -- **load_ram**: check for overlaps in bss section -- **tests/intelhex**: make sure file is closed on Windows -- **spi_connection**: Unattach previously attached SPI flash -- **espefuse**: Fix ECDSA_FORCE_USE_HARDWARE_K for ECDSA key (esp32h2) -- **loader**: Could not open serial port message adjusted -- **flasher_stub**: fix usb-serial-jtag enabled non-related intr source -- **bin_image**: Check only ELF sections when searching for .flash.appdesc -- **danger-github**: Fir Danger GitHub token permission -- Fix redirection of STDOUT -- **autodetection**: Remove the ESP32-S2 ROM class from get_security_info autodetection -- assert in esp32 exclusive workaround -- **elf2image**: fix text/rodata mapping overlap issue on uni-idrom bus chips -- **dangerGH**: Update token permissions - allow Danger to add comments to PR -- **expand file args**: Correctly print the expanded command -- **esp32-c2**: Enable flashing in secure download mode - -### Code Refactoring - -- **stub_flasher**: Cleanup, make adding new targets easier - -## v4.6.2 (2023-06-12) - -### Bug Fixes - -- **CH9102F**: Suggest to install new serial drivers if writing to RAM fails -- **compressed upload**: Accept short data blocks with only Adler-32 bytes - -## v4.6.1 (2023-06-01) - -### Bug Fixes - -- **ESP32-S3**: Correct RTC WDT registers to fix resets during flashing - -## v4.6 (2023-05-29) - -### New Features - -- **esptool**: add option to dump whole flash based on detected size - -### Bug Fixes - -- inconsistent usage of dirs separator -- USB-JTAG-Serial PID detection error -- Set flash parameters even with --flash_size keep -- **ESP32-C6**: Fix get_pkg_version and get_{major,minor}_chip_version - -## v4.5.1 (2023-02-28) - -### Bug Fixes - -- **ESP32-S3**: Temporarily disable increasing CPU freq -- Unknown chip (ID or magic number) error -- **ESP32-S3**: Lower CPU freq to improve flasher stub stability -- **rfc2217_server**: Use new reset sequences - -## v4.5 (2023-02-10) - -### New Features - -- **stub**: Add ESP32-S3 octal flash support -- **esp32h2**: Enable USB-JTAG/Serial mode in the stub flasher -- **bootloader reset**: Allow custom reset strategy setting with a config file -- Allow configuration with a config file -- **bootloader reset**: Tighter transitions on Unix systems -- **ci**: Publish development releases with custom pipeline -- **esp32c6 stub**: Increase CPU frequency and write/read speeds over USB-JTAG/Serial -- **esp32c6 stub**: Enable USB-JTAG/Serial -- **flash_id**: Print the flash type if available for the chip - -### Bug Fixes - -- **cmds**: Make clear that flash type is from eFuse and not detection -- **load config file**: Sort unknown config options -- **esp32c6**: Workaround for bad MSPI frequency in HS mode -- **flasher_stub**: Correct boundaries for SPIWrite4B and SPIRead4B -- **secure download mode**: Reconnect if ROM refuses to respond -- **secure download mode**: Fix SDM detection on S2/S3 -- **ci**: Merge two "ci" directories and build_tools into one -- **ci**: The development release job should not run by default -- **setup**: Use latest reedsolo package which can be installed with Python3.10 and Cython -- **write_flash**: Fix `--erase-all` option -- **espefuse**: Close serial port even when espefuse fails -- **espefuse**: Fix compatibility with Bitstring>=4 - -### Code Refactoring - -- Comply with black 23.1 style -- Optimize unnecessary chip interrogations -- **connection attempt**: Decouple reset sequence settings - -## v4.4 (2022-11-21) - -### New Features - -- **flasher_stub**: Increase CPU frequency and write/read speeds over native USB (USB-OTG) -- **flasher_stub**: Increase CPU frequency and write/read speeds over USB-JTAG/Serial -- Readable error message for serial-related issues -- Detect Guru Meditation errors - -### Bug Fixes - -- Add workaround for breaking changes of bitstring==4 -- close unused ports while get_default_connected_device - -## v4.3 (2022-09-14) - -### New Features - -- **image_info**: Print application information if possible -- Add Macronix flash memory density definitions -- **write_flash**: Prevent flashing incompatible images -- Recover from serial errors when flashing -- Add stub flasher error messages definitions -- **image_info**: Image type autodetection - -### Code Refactoring - -- **elf2image**: Simplify bootloader image selection diff --git a/tools/esptool_py/CONTRIBUTING.rst b/tools/esptool_py/CONTRIBUTING.rst deleted file mode 100644 index de0ca91ed8..0000000000 --- a/tools/esptool_py/CONTRIBUTING.rst +++ /dev/null @@ -1,182 +0,0 @@ -Contributions Guide -=================== - -We welcome contributions to the ``esptool.py`` project! - -How to Contribute ------------------ - -Contributions to ``esptool.py`` - fixing bugs, adding features, adding documentation - are welcome. We accept contributions via `Github Pull Requests `_. - -.. _development-setup: - -Development Setup ------------------ - -Development mode allows you to run the latest development version from the `esptool.py repository on GitHub `_. - -.. code-block:: sh - - $ git clone https://github.com/espressif/esptool.git - $ cd esptool - $ pip install --user -e . - -This will install ``esptool.py``’s dependencies and create some executable script wrappers in the user’s ``bin`` directory. The wrappers will run the scripts found in the git working directory directly, so any time the working directory contents change it will pick up the new versions. - -It’s also possible to run the scripts directly from the working directory with this Development Mode installation. - -To also install additional tools needed for actually developing and testing ``esptool.py``, run this command to install a development copy of ``esptool.py`` *plus* packages useful for development: - -:: - - $ pip install --user -e ".[dev]" - -(This command uses the “extras” feature of setuptools.) - -Reporting Issues ----------------- - -Please report bugs in ``esptool.py`` if you find them. However, before reporting a bug please check through the following: - -* `Troubleshooting Guide `_ - common problems and known issues. - -* `Existing Open Issues `_ - someone might have already encountered this. - -If you don’t find anything, please `open a new issue `_. - -Sending Feature Requests ------------------------- - -Feel free to post feature requests. It’s helpful if you can explain exactly why the feature would be useful. - -There are usually some outstanding feature requests in the `existing issues list `_, feel free to add comments to them. - -Before Contributing -------------------- - -Before sending us a Pull Request, please consider this list of points: - -* Have you tried running ``esptool.py`` test suite locally? - -* Is the code adequately commented for people to understand how it is structured? - -* Is there documentation or examples that go with code contributions? - -* Are comments and documentation written in clear English, with no spelling or grammar errors? - -* If the contribution contains multiple commits, are they grouped together into logical changes (one major change per pull request)? Are any commits with names like "fixed typo" `squashed into previous commits `_? - -* If you're unsure about any of these points, please open the Pull Request anyhow and then ask us for feedback. - -Code Style & Static Analysis -^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - -Please follow these coding standards when writing code for ``esptool.py``: - -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``. Then enable the ``pre-commit`` and ``commit-msg`` git hooks: - -:: - - $ python -m pip install pre-commit - $ 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. 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. - - -Ruff -"""" - -``esptool.py`` is `PEP8 `_ compliant and enforces this style guide. For compliance checking, we use `ruff `_. -``Ruff`` also auto-format files in the same style as previously used ``black``. - - -``Ruff`` 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 ruff`` (this tool is 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. - -Shinx-lint -"""""""""" - -The documentation is checked for stylistic and formal issues by ``sphinx-lint``. - - -Codespell check -""""""""""""""" - -This repository utilizes an automatic `spell checker `_ integrated into the pre-commit process. If any spelling issues are detected, the recommended corrections will be applied automatically to the file, ready for commit. -In the event of false positives, you can adjust the configuration in the `.codespell.rc`. To exclude files from the spell check, utilize the `skip` keyword followed by comma-separated paths to the files (wildcards are supported). Additionally, to exclude specific words from the spell check, employ the `ignore-words-list` keyword followed by comma-separated words to be skipped. - - -Automated Integration Tests -^^^^^^^^^^^^^^^^^^^^^^^^^^^ - -The test directory contains a `pytest `_ integration suite with some integration tests for ``esptool.py``, ``espefuse.py``, and ``espsecure.py``. - -It is necessary to have ``esptool.py`` installed (see `Development Setup`_) in your environment in order to run these tests. - -The following tests run automatically by GitHub Actions for each Pull Request. You can run them locally to check for regressions in the respective functionality: - -* ``test_imagegen.py`` tests the ``elf2image`` command -* ``test_image_info.py`` tests the ``image_info`` command -* ``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 external 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: - -* ``test_esptool.py`` contains integration tests for ``esptool.py`` and needs to be run against real Espressif hardware with the following format: - - ``pytest test_esptool.py --port --chip --baud `` - - For example, to run all tests on an ESP32 board connected to /dev/ttyUSB0, at 230400bps: - - ``pytest test_esptool.py --port /dev/ttyUSB0 --chip esp32 --baud 230400`` - - Or to run the TestFlashing suite only (using the pytest ``-k`` option to select tests based on their name) on an ESP8266 board connected to /dev/ttyUSB2, at 460800bps: - - ``pytest test_esptool.py --port /dev/ttyUSB2 --chip esp8266 --baud 460800 -k TestFlashing`` - - .. note:: - - Some tests might fail at higher baud rates on some hardware. - -* ``test_esptool_sdm.py`` contains integration tests for ``esptool.py`` with chips in secure download mode. It needs to be run against real Espressif hardware (with active SDM). The command line format is the same as for ``test_esptool.py``. - -The following tests are not run automatically by GitHub Actions, but can be run locally in a command line: - -* ``test_espefuse.py`` tests ``espefuse.py`` functionality. To run it: - - ``pytest test_espefuse.py --chip `` - - These test use the ``--virt`` virtual mode of ``espefuse.py`` to safely test the functionality without a connection to a chip and without the possibility of affecting the actual eFuses in a real hardware. - - .. warning:: - - 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 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 --------------------- - -.. note:: - - If you are developing the stub flasher and plan to send a pull request, please use the latest toolchains available. - -After you open the Pull Request, there will probably be some discussion in the comments field of the request itself. - -Once the Pull Request is ready to merge, it will first be merged into our internal git system for in-house automated testing. - -If this process passes, it will be merged onto the public github repository, hooray! diff --git a/tools/esptool_py/LICENSE b/tools/esptool_py/LICENSE deleted file mode 100644 index d159169d10..0000000000 --- a/tools/esptool_py/LICENSE +++ /dev/null @@ -1,339 +0,0 @@ - GNU GENERAL PUBLIC LICENSE - Version 2, June 1991 - - Copyright (C) 1989, 1991 Free Software Foundation, Inc., - 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - Everyone is permitted to copy and distribute verbatim copies - of this license document, but changing it is not allowed. - - Preamble - - The licenses for most software are designed to take away your -freedom to share and change it. By contrast, the GNU General Public -License is intended to guarantee your freedom to share and change free -software--to make sure the software is free for all its users. This -General Public License applies to most of the Free Software -Foundation's software and to any other program whose authors commit to -using it. (Some other Free Software Foundation software is covered by -the GNU Lesser General Public License instead.) You can apply it to -your programs, too. - - When we speak of free software, we are referring to freedom, not -price. Our General Public Licenses are designed to make sure that you -have the freedom to distribute copies of free software (and charge for -this service if you wish), that you receive source code or can get it -if you want it, that you can change the software or use pieces of it -in new free programs; and that you know you can do these things. - - To protect your rights, we need to make restrictions that forbid -anyone to deny you these rights or to ask you to surrender the rights. -These restrictions translate to certain responsibilities for you if you -distribute copies of the software, or if you modify it. - - For example, if you distribute copies of such a program, whether -gratis or for a fee, you must give the recipients all the rights that -you have. You must make sure that they, too, receive or can get the -source code. And you must show them these terms so they know their -rights. - - We protect your rights with two steps: (1) copyright the software, and -(2) offer you this license which gives you legal permission to copy, -distribute and/or modify the software. - - Also, for each author's protection and ours, we want to make certain -that everyone understands that there is no warranty for this free -software. If the software is modified by someone else and passed on, we -want its recipients to know that what they have is not the original, so -that any problems introduced by others will not reflect on the original -authors' reputations. - - Finally, any free program is threatened constantly by software -patents. We wish to avoid the danger that redistributors of a free -program will individually obtain patent licenses, in effect making the -program proprietary. To prevent this, we have made it clear that any -patent must be licensed for everyone's free use or not licensed at all. - - The precise terms and conditions for copying, distribution and -modification follow. - - GNU GENERAL PUBLIC LICENSE - TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION - - 0. This License applies to any program or other work which contains -a notice placed by the copyright holder saying it may be distributed -under the terms of this General Public License. The "Program", below, -refers to any such program or work, and a "work based on the Program" -means either the Program or any derivative work under copyright law: -that is to say, a work containing the Program or a portion of it, -either verbatim or with modifications and/or translated into another -language. (Hereinafter, translation is included without limitation in -the term "modification".) Each licensee is addressed as "you". - -Activities other than copying, distribution and modification are not -covered by this License; they are outside its scope. The act of -running the Program is not restricted, and the output from the Program -is covered only if its contents constitute a work based on the -Program (independent of having been made by running the Program). -Whether that is true depends on what the Program does. - - 1. You may copy and distribute verbatim copies of the Program's -source code as you receive it, in any medium, provided that you -conspicuously and appropriately publish on each copy an appropriate -copyright notice and disclaimer of warranty; keep intact all the -notices that refer to this License and to the absence of any warranty; -and give any other recipients of the Program a copy of this License -along with the Program. - -You may charge a fee for the physical act of transferring a copy, and -you may at your option offer warranty protection in exchange for a fee. - - 2. You may modify your copy or copies of the Program or any portion -of it, thus forming a work based on the Program, and copy and -distribute such modifications or work under the terms of Section 1 -above, provided that you also meet all of these conditions: - - a) You must cause the modified files to carry prominent notices - stating that you changed the files and the date of any change. - - b) You must cause any work that you distribute or publish, that in - whole or in part contains or is derived from the Program or any - part thereof, to be licensed as a whole at no charge to all third - parties under the terms of this License. - - c) If the modified program normally reads commands interactively - when run, you must cause it, when started running for such - interactive use in the most ordinary way, to print or display an - announcement including an appropriate copyright notice and a - notice that there is no warranty (or else, saying that you provide - a warranty) and that users may redistribute the program under - these conditions, and telling the user how to view a copy of this - License. (Exception: if the Program itself is interactive but - does not normally print such an announcement, your work based on - the Program is not required to print an announcement.) - -These requirements apply to the modified work as a whole. If -identifiable sections of that work are not derived from the Program, -and can be reasonably considered independent and separate works in -themselves, then this License, and its terms, do not apply to those -sections when you distribute them as separate works. But when you -distribute the same sections as part of a whole which is a work based -on the Program, the distribution of the whole must be on the terms of -this License, whose permissions for other licensees extend to the -entire whole, and thus to each and every part regardless of who wrote it. - -Thus, it is not the intent of this section to claim rights or contest -your rights to work written entirely by you; rather, the intent is to -exercise the right to control the distribution of derivative or -collective works based on the Program. - -In addition, mere aggregation of another work not based on the Program -with the Program (or with a work based on the Program) on a volume of -a storage or distribution medium does not bring the other work under -the scope of this License. - - 3. You may copy and distribute the Program (or a work based on it, -under Section 2) in object code or executable form under the terms of -Sections 1 and 2 above provided that you also do one of the following: - - a) Accompany it with the complete corresponding machine-readable - source code, which must be distributed under the terms of Sections - 1 and 2 above on a medium customarily used for software interchange; or, - - b) Accompany it with a written offer, valid for at least three - years, to give any third party, for a charge no more than your - cost of physically performing source distribution, a complete - machine-readable copy of the corresponding source code, to be - distributed under the terms of Sections 1 and 2 above on a medium - customarily used for software interchange; or, - - c) Accompany it with the information you received as to the offer - to distribute corresponding source code. (This alternative is - allowed only for noncommercial distribution and only if you - received the program in object code or executable form with such - an offer, in accord with Subsection b above.) - -The source code for a work means the preferred form of the work for -making modifications to it. For an executable work, complete source -code means all the source code for all modules it contains, plus any -associated interface definition files, plus the scripts used to -control compilation and installation of the executable. However, as a -special exception, the source code distributed need not include -anything that is normally distributed (in either source or binary -form) with the major components (compiler, kernel, and so on) of the -operating system on which the executable runs, unless that component -itself accompanies the executable. - -If distribution of executable or object code is made by offering -access to copy from a designated place, then offering equivalent -access to copy the source code from the same place counts as -distribution of the source code, even though third parties are not -compelled to copy the source along with the object code. - - 4. You may not copy, modify, sublicense, or distribute the Program -except as expressly provided under this License. Any attempt -otherwise to copy, modify, sublicense or distribute the Program is -void, and will automatically terminate your rights under this License. -However, parties who have received copies, or rights, from you under -this License will not have their licenses terminated so long as such -parties remain in full compliance. - - 5. You are not required to accept this License, since you have not -signed it. However, nothing else grants you permission to modify or -distribute the Program or its derivative works. These actions are -prohibited by law if you do not accept this License. Therefore, by -modifying or distributing the Program (or any work based on the -Program), you indicate your acceptance of this License to do so, and -all its terms and conditions for copying, distributing or modifying -the Program or works based on it. - - 6. Each time you redistribute the Program (or any work based on the -Program), the recipient automatically receives a license from the -original licensor to copy, distribute or modify the Program subject to -these terms and conditions. You may not impose any further -restrictions on the recipients' exercise of the rights granted herein. -You are not responsible for enforcing compliance by third parties to -this License. - - 7. If, as a consequence of a court judgment or allegation of patent -infringement or for any other reason (not limited to patent issues), -conditions are imposed on you (whether by court order, agreement or -otherwise) that contradict the conditions of this License, they do not -excuse you from the conditions of this License. If you cannot -distribute so as to satisfy simultaneously your obligations under this -License and any other pertinent obligations, then as a consequence you -may not distribute the Program at all. For example, if a patent -license would not permit royalty-free redistribution of the Program by -all those who receive copies directly or indirectly through you, then -the only way you could satisfy both it and this License would be to -refrain entirely from distribution of the Program. - -If any portion of this section is held invalid or unenforceable under -any particular circumstance, the balance of the section is intended to -apply and the section as a whole is intended to apply in other -circumstances. - -It is not the purpose of this section to induce you to infringe any -patents or other property right claims or to contest validity of any -such claims; this section has the sole purpose of protecting the -integrity of the free software distribution system, which is -implemented by public license practices. Many people have made -generous contributions to the wide range of software distributed -through that system in reliance on consistent application of that -system; it is up to the author/donor to decide if he or she is willing -to distribute software through any other system and a licensee cannot -impose that choice. - -This section is intended to make thoroughly clear what is believed to -be a consequence of the rest of this License. - - 8. If the distribution and/or use of the Program is restricted in -certain countries either by patents or by copyrighted interfaces, the -original copyright holder who places the Program under this License -may add an explicit geographical distribution limitation excluding -those countries, so that distribution is permitted only in or among -countries not thus excluded. In such case, this License incorporates -the limitation as if written in the body of this License. - - 9. The Free Software Foundation may publish revised and/or new versions -of the General Public License from time to time. Such new versions will -be similar in spirit to the present version, but may differ in detail to -address new problems or concerns. - -Each version is given a distinguishing version number. If the Program -specifies a version number of this License which applies to it and "any -later version", you have the option of following the terms and conditions -either of that version or of any later version published by the Free -Software Foundation. If the Program does not specify a version number of -this License, you may choose any version ever published by the Free Software -Foundation. - - 10. If you wish to incorporate parts of the Program into other free -programs whose distribution conditions are different, write to the author -to ask for permission. For software which is copyrighted by the Free -Software Foundation, write to the Free Software Foundation; we sometimes -make exceptions for this. Our decision will be guided by the two goals -of preserving the free status of all derivatives of our free software and -of promoting the sharing and reuse of software generally. - - NO WARRANTY - - 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY -FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN -OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES -PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED -OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF -MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS -TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE -PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, -REPAIR OR CORRECTION. - - 12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING -WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR -REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, -INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING -OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED -TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY -YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER -PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE -POSSIBILITY OF SUCH DAMAGES. - - END OF TERMS AND CONDITIONS - - How to Apply These Terms to Your New Programs - - If you develop a new program, and you want it to be of the greatest -possible use to the public, the best way to achieve this is to make it -free software which everyone can redistribute and change under these terms. - - To do so, attach the following notices to the program. It is safest -to attach them to the start of each source file to most effectively -convey the exclusion of warranty; and each file should have at least -the "copyright" line and a pointer to where the full notice is found. - - - Copyright (C) - - 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. - -Also add information on how to contact you by electronic and paper mail. - -If the program is interactive, make it output a short notice like this -when it starts in an interactive mode: - - Gnomovision version 69, Copyright (C) year name of author - Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'. - This is free software, and you are welcome to redistribute it - under certain conditions; type `show c' for details. - -The hypothetical commands `show w' and `show c' should show the appropriate -parts of the General Public License. Of course, the commands you use may -be called something other than `show w' and `show c'; they could even be -mouse-clicks or menu items--whatever suits your program. - -You should also get your employer (if you work as a programmer) or your -school, if any, to sign a "copyright disclaimer" for the program, if -necessary. Here is a sample; alter the names: - - Yoyodyne, Inc., hereby disclaims all copyright interest in the program - `Gnomovision' (which makes passes at compilers) written by James Hacker. - - , 1 April 1989 - Ty Coon, President of Vice - -This General Public License does not permit incorporating your program into -proprietary programs. If your program is a subroutine library, you may -consider it more useful to permit linking proprietary applications with the -library. If this is what you want to do, use the GNU Lesser General -Public License instead of this License. diff --git a/tools/esptool_py/MANIFEST.in b/tools/esptool_py/MANIFEST.in deleted file mode 100644 index f135efaa6f..0000000000 --- a/tools/esptool_py/MANIFEST.in +++ /dev/null @@ -1,11 +0,0 @@ -include README.md -include LICENSE -include esptool/targets/stub_flasher/1/* -include esptool/targets/stub_flasher/2/* -include espefuse/efuse_defs/*.yaml -# 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 .github -prune docs -exclude .git* diff --git a/tools/esptool_py/README.md b/tools/esptool_py/README.md deleted file mode 100644 index afb83bc198..0000000000 --- a/tools/esptool_py/README.md +++ /dev/null @@ -1,21 +0,0 @@ -# esptool.py - -A Python-based, open-source, platform-independent utility to communicate with the ROM bootloader in Espressif chips. - -[![Test esptool](https://github.com/espressif/esptool/actions/workflows/test_esptool.yml/badge.svg?branch=master)](https://github.com/espressif/esptool/actions/workflows/test_esptool.yml) [![Build esptool](https://github.com/espressif/esptool/actions/workflows/build_esptool.yml/badge.svg?branch=master)](https://github.com/espressif/esptool/actions/workflows/build_esptool.yml) - -## Documentation - -Visit the [documentation](https://docs.espressif.com/projects/esptool/) or run `esptool.py -h`. - -## Contribute - -If you're interested in contributing to esptool.py, please check the [contributions guide](https://docs.espressif.com/projects/esptool/en/latest/contributing.html). - -## About - -esptool.py was initially created by Fredrik Ahlberg (@[themadinventor](https://github.com/themadinventor/)), and later maintained by Angus Gratton (@[projectgus](https://github.com/projectgus/)). It is now supported by Espressif Systems. It has also received improvements from many members of the community. - -## License - -This document and the attached source code are released as Free Software under GNU General Public License Version 2 or later. See the accompanying [LICENSE file](https://github.com/espressif/esptool/blob/master/LICENSE) for a copy. diff --git a/tools/esptool_py/ci/Sign-File.ps1 b/tools/esptool_py/ci/Sign-File.ps1 deleted file mode 100644 index 09094096ac..0000000000 --- a/tools/esptool_py/ci/Sign-File.ps1 +++ /dev/null @@ -1,78 +0,0 @@ -[CmdletBinding()] -param ( - [Parameter()] - [String] - $Path -) - - -function FindSignTool { - $SignTool = "signtool.exe" - if (Get-Command $SignTool -ErrorAction SilentlyContinue) { - return $SignTool - } - $SignTool = "${env:ProgramFiles(x86)}\Windows Kits\10\bin\x64\signtool.exe" - if (Test-Path -Path $SignTool -PathType Leaf) { - return $SignTool - } - $SignTool = "${env:ProgramFiles(x86)}\Windows Kits\10\bin\x86\signtool.exe" - if (Test-Path -Path $SignTool -PathType Leaf) { - return $SignTool - } - $sdkVers = "10.0.22000.0", "10.0.20348.0", "10.0.19041.0", "10.0.17763.0" - Foreach ($ver in $sdkVers) - { - $SignTool = "${env:ProgramFiles(x86)}\Windows Kits\10\bin\${ver}\x64\signtool.exe" - if (Test-Path -Path $SignTool -PathType Leaf) { - return $SignTool - } - } - "signtool.exe not found" - Exit 1 -} - -function SignEsptool { - param( - [Parameter()] - [String] - $Path - ) - - $SignTool = FindSignTool - "Using: $SignTool" - $CertificateFile = [system.io.path]::GetTempPath() + "certificate.pfx" - - if ($null -eq $env:CERTIFICATE) { - "CERTIFICATE variable not set, unable to sign the file" - Exit 1 - } - - if ("" -eq $env:CERTIFICATE) { - "CERTIFICATE variable is empty, unable to sign the file" - Exit 1 - } - - $SignParameters = @("sign", "/tr", 'http://timestamp.digicert.com', "/td", "SHA256", "/f", $CertificateFile, "/fd", "SHA256") - if ($env:CERTIFICATE_PASSWORD) { - "CERTIFICATE_PASSWORD detected, using the password" - $SignParameters += "/p" - $SignParameters += $env:CERTIFICATE_PASSWORD - } - $SignParameters += $Path - - [byte[]]$CertificateBytes = [convert]::FromBase64String($env:CERTIFICATE) - [IO.File]::WriteAllBytes($CertificateFile, $CertificateBytes) - - &$SignTool $SignParameters - - if (0 -eq $LASTEXITCODE) { - Remove-Item $CertificateFile - } else { - Remove-Item $CertificateFile - "Signing failed" - Exit 1 - } - -} - -SignEsptool ${Path} diff --git a/tools/esptool_py/ci/download_flasher_stubs.py b/tools/esptool_py/ci/download_flasher_stubs.py deleted file mode 100755 index 8f34c41296..0000000000 --- a/tools/esptool_py/ci/download_flasher_stubs.py +++ /dev/null @@ -1,91 +0,0 @@ -#!/usr/bin/env python -# -# SPDX-FileCopyrightText: 2024 Espressif Systems (Shanghai) CO LTD -# SPDX-License-Identifier: GPL-2.0-or-later - -import glob -import os -import urllib.request - -STUBS = ( - { - "STUB_SET_VERSION": "1", - "DOWNLOAD_URL": "https://github.com/espressif/esptool-legacy-flasher-stub/releases/download", - "TAG_URL": "https://github.com/espressif/esptool-legacy-flasher-stub/releases/tag", - "VERSION": "v1.3.0", - "FILE_LIST": ( - "esp32", - "esp32c2", - "esp32c3", - "esp32c5", - "esp32c5beta3", - "esp32c6", - "esp32c61", - "esp32c6beta", - "esp32h2", - "esp32h2beta1", - "esp32h2beta2", - "esp32p4", - "esp32s2", - "esp32s3", - "esp32s3beta2", - "esp8266", - ), - "LICENSE": "released as Free Software under GNU General Public License Version 2 or later", - }, - { - "STUB_SET_VERSION": "2", - "DOWNLOAD_URL": "https://github.com/esp-rs/esp-flasher-stub/releases/download", - "TAG_URL": "https://github.com/esp-rs/esp-flasher-stub/releases/tag", - "VERSION": "v0.3.0", - "FILE_LIST": ( - "esp32", - "esp32c2", - "esp32c3", - "esp32c6", - "esp32h2", - "esp32s2", - "esp32s3", - ), - "LICENSE": "dual licensed under the Apache License Version 2.0 or the MIT license", - }, -) - -DESTINATION_DIR = os.path.join("esptool", "targets", "stub_flasher") - -README_TEMPLATE = """# Licensing - -The binaries in JSON format distributed in this directory are {LICENSE}. They were released at {URL} from where the sources can be obtained. -""" - - -def main(): - for stub_set in STUBS: - dest_sub_dir = os.path.join(DESTINATION_DIR, stub_set["STUB_SET_VERSION"]) - - """ The directory is cleaned up so we would detect if a stub was just committed into the repository but the - name was not added into the FILE_LIST of STUBS. This would be an unwanted state because the checker would not - detect any changes in that stub.""" - for old_file in glob.glob(os.path.join(dest_sub_dir, "*.json")): - print(f"Removing old file {old_file}") - os.remove(old_file) - - for file_name in stub_set["FILE_LIST"]: - file = ".".join((file_name, "json")) - url = "/".join((stub_set["DOWNLOAD_URL"], stub_set["VERSION"], file)) - dest = os.path.join(dest_sub_dir, file) - print(f"Downloading {url} to {dest}") - urllib.request.urlretrieve(url, dest) - - with open(os.path.join(dest_sub_dir, "README.md"), "w") as f: - print(f"Writing README to {f.name}") - f.write( - README_TEMPLATE.format( - LICENSE=stub_set["LICENSE"], - URL="/".join((stub_set["TAG_URL"], stub_set["VERSION"])), - ) - ) - - -if __name__ == "__main__": - main() diff --git a/tools/esptool_py/ci/espressif.ico b/tools/esptool_py/ci/espressif.ico deleted file mode 100644 index c5550f148c..0000000000 Binary files a/tools/esptool_py/ci/espressif.ico and /dev/null differ diff --git a/tools/esptool_py/ci/gh_changelog_template.md.j2 b/tools/esptool_py/ci/gh_changelog_template.md.j2 deleted file mode 100644 index 5dc2df5db3..0000000000 --- a/tools/esptool_py/ci/gh_changelog_template.md.j2 +++ /dev/null @@ -1,28 +0,0 @@ -{# This changelog template is used for automatically generated GH release notes. #} -{# It is passed to commitizen's --template option in a GH Actions workflow run. #} - -{% for entry in tree %} - -{% for change_key, changes in entry.changes.items() %} - -{% if change_key %} -### {{ change_key }} -{% endif %} - -{% for change in changes %} -{% if change.scope %} -- **{{ change.scope }}**: {{ change.message }} -{% elif change.message %} -- {{ change.message }} -{% endif %} -{% endfor %} -{% endfor %} -{% endfor %} - -Thanks to , and others for contributing to this release! - -# Results of checking the release against common anti-virus SW - - - -The failures are probably false positives. You can mark esptool as safe in your anti-virus SW, or [install esptool from source](https://docs.espressif.com/projects/esptool/en/latest/installation.html). diff --git a/tools/esptool_py/ci/patch_dev_release.py b/tools/esptool_py/ci/patch_dev_release.py deleted file mode 100644 index 9cd9feff7e..0000000000 --- a/tools/esptool_py/ci/patch_dev_release.py +++ /dev/null @@ -1,40 +0,0 @@ -# SPDX-FileCopyrightText: 2022-2023 Espressif Systems (Shanghai) CO LTD -# -# SPDX-License-Identifier: GPL-2.0-or-later - -import argparse -import re - -LINE_RE = re.compile(r"^__version__ = ['\"]([^'\"]*)['\"]") -NEW_LINE = '__version__ = "{}"\n' - - -def patch_file(path, new_version): - assert ".dev" in new_version - new_version = new_version.lstrip("v") - - with open(path, "r") as fin: - lines = fin.readlines() - - for i, line in enumerate(lines, start=0): - m = LINE_RE.search(line) - if m: - lines[i] = NEW_LINE.format(new_version) - break - - with open(path, "w") as fout: - fout.writelines(lines) - - -def main(): - parser = argparse.ArgumentParser() - parser.add_argument("file", help="Path to script with __version__") - parser.add_argument( - "--version", help="Development version specifier to patch the version to" - ) - args = parser.parse_args() - patch_file(args.file, args.version) - - -if __name__ == "__main__": - main() diff --git a/tools/esptool_py/ci/setup_softhsm2.sh b/tools/esptool_py/ci/setup_softhsm2.sh deleted file mode 100755 index de81498378..0000000000 --- a/tools/esptool_py/ci/setup_softhsm2.sh +++ /dev/null @@ -1,7 +0,0 @@ -#!/bin/bash - -# Init tokens for tests -softhsm2-util --init-token --label softhsm-test-token --pin 1234 --so-pin 123456 --slot 0 -softhsm2-util --init-token --label softhsm-test-token-1 --pin 1234 --so-pin 123456 --slot 1 -softhsm2-util --init-token --label softhsm-test-token-2 --pin 1234 --so-pin 123456 --slot 2 -softhsm2-util --init-token --label softhsm-test-token-3 --pin 1234 --so-pin 123456 --slot 3 diff --git a/tools/esptool_py/docs/README.md b/tools/esptool_py/docs/README.md deleted file mode 100644 index e9f747d071..0000000000 --- a/tools/esptool_py/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/tools/esptool_py/docs/_static/esptool_versions.js b/tools/esptool_py/docs/_static/esptool_versions.js deleted file mode 100644 index 409ecf2e9b..0000000000 --- a/tools/esptool_py/docs/_static/esptool_versions.js +++ /dev/null @@ -1,17 +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" }, - { text: "ESP32-C2", value: "esp32c2" }, - { text: "ESP32-C6", value: "esp32c6" }, - { text: "ESP32-H2", value: "esp32h2" }, - { text: "ESP32-P4", value: "esp32p4" }, - ] -}; diff --git a/tools/esptool_py/docs/conf_common.py b/tools/esptool_py/docs/conf_common.py deleted file mode 100644 index 03e69fc861..0000000000 --- a/tools/esptool_py/docs/conf_common.py +++ /dev/null @@ -1,50 +0,0 @@ -from esp_docs.conf_docs import * # noqa: F403,F401 - -languages = ["en"] -idf_targets = [ - "esp8266", - "esp32", - "esp32s2", - "esp32s3", - "esp32c3", - "esp32c2", - "esp32c6", - "esp32h2", - "esp32p4", -] - -# 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/*", -] - -conditional_include_dict = { - "esp8266": ESP8266_DOCS, - "esp32": ESP32_DOCS, - "esp32s2": ESP32_DOCS, - "esp32c3": ESP32_DOCS, - "esp32s3": ESP32_DOCS, - "esp32c2": ESP32_DOCS, - "esp32c6": ESP32_DOCS, - "esp32h2": ESP32_DOCS, - "esp32p4": ESP32_DOCS, -} - -# Extra options required by sphinx_idf_theme -project_slug = "esptool" - -versions_url = "./_static/esptool_versions.js" diff --git a/tools/esptool_py/docs/en/about.rst b/tools/esptool_py/docs/en/about.rst deleted file mode 100644 index d26acadd8c..0000000000 --- a/tools/esptool_py/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/tools/esptool_py/docs/en/advanced-topics/boot-mode-selection.rst b/tools/esptool_py/docs/en/advanced-topics/boot-mode-selection.rst deleted file mode 100644 index dfa4a04e37..0000000000 --- a/tools/esptool_py/docs/en/advanced-topics/boot-mode-selection.rst +++ /dev/null @@ -1,365 +0,0 @@ -{IDF_TARGET_STRAP_BOOT_GPIO:default="GPIO9", esp32="GPIO0", esp32s2="GPIO0", esp32s3="GPIO0", esp32p4="GPIO35"} - -{IDF_TARGET_STRAP_BOOT_2_GPIO:default="GPIO8", esp32="GPIO2", esp32s2="GPIO46", esp32s3="GPIO46", esp32p4="GPIO36"} - -{IDF_TARGET_BOOTLOADER_OFFSET:default="0", esp32="1000", esp32s2="1000", esp32p4="2000"} - -.. _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. - - .. list-table:: - :widths: 10 25 - :header-rows: 1 - - * - {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:: esp32 or esp32s2 or esp32s3 - - {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 or esp32c2 or esp32h2 or esp32c6 or esp32p4 - - {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 ``{IDF_TARGET_STRAP_BOOT_GPIO}`` 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: - -.. list-table:: - :header-rows: 1 - - * - 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. - -.. note:: - - If esptool is able to reset the chip but for some reason the chip is not entering into bootloader mode then hold down the Boot button (or pull down ``{IDF_TARGET_STRAP_BOOT_GPIO}``) while you start esptool and keep it down during reset. - -.. 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:: not esp8266 - - Boot Log - -------- - - Boot Mode Message - ^^^^^^^^^^^^^^^^^ - - After reset, the second line printed by the {IDF_TARGET_NAME} 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 under RESET_REASON enum `__. - The value can be read in {IDF_TARGET_NAME} 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: - - .. only:: esp32 - - - ``0x01`` - GPIO5 - - ``0x02`` - MTDO (GPIO15) - - ``0x04`` - GPIO4 - - ``0x08`` - GPIO2 - - ``0x10`` - GPIO0 - - ``0x20`` - MTDI (GPIO12) - - .. only:: not esp32 - - - ``0x04`` - {IDF_TARGET_STRAP_BOOT_2_GPIO} - - ``0x08`` - {IDF_TARGET_STRAP_BOOT_GPIO} - - 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)`` or ``DOWNLOAD(USB/UART0)`` - {IDF_TARGET_NAME} is in download flashing mode (suitable for esptool) - - ``SPI_FAST_FLASH_BOOT`` - This is the normal SPI flash boot mode. - - Other modes (including ``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 {IDF_TARGET_STRAP_BOOT_2_GPIO} has been pulled high when {IDF_TARGET_STRAP_BOOT_GPIO} is low). - - .. only:: esp32 - - .. 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, {IDF_TARGET_BOOTLOADER_OFFSET} - - This fatal error indicates that the bootloader tried to read the software bootloader header at address 0x{IDF_TARGET_BOOTLOADER_OFFSET} but failed to read valid data. Possible reasons for this include: - - .. list:: - - - There isn't actually a bootloader at offset 0x{IDF_TARGET_BOOTLOADER_OFFSET} (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. - - Flash encryption is enabled but the bootloader is plaintext. Alternatively, flash encryption is disabled but the bootloader is encrypted ciphertext. - - :esp32: - Boot mode accidentally set to ``HSPI_FLASH_BOOT``, which uses different SPI flash pins. Check {IDF_TARGET_STRAP_BOOT_2_GPIO} (see above). - :esp32: - 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. - - - Software Bootloader Header Info - """"""""""""""""""""""""""""""" - - .. only:: esp32 - - :: - - 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 - - - .. only:: not esp32 - - :: - - SPIWP:0xee - 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 0x{IDF_TARGET_BOOTLOADER_OFFSET}: - - .. list:: - - :esp32: - ``configsip: N`` indicates SPI flash config: - - :esp32: - 0 for default SPI flash - :esp32: - 1 if booting from the HSPI bus (due to eFuse configuration) - :esp32: - 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. - :esp32: - ``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 {IDF_TARGET_PATH_NAME} 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/tools/esptool_py/docs/en/advanced-topics/diag/command_packet_format.diag b/tools/esptool_py/docs/en/advanced-topics/diag/command_packet_format.diag deleted file mode 100644 index ffb09c03a7..0000000000 --- a/tools/esptool_py/docs/en/advanced-topics/diag/command_packet_format.diag +++ /dev/null @@ -1,13 +0,0 @@ -packetdiag command_packet_format{ - colwidth = 16 - node_width = 50 - node_height = 50 - default_fontsize = 16 - - 0: "0x00"; - 1: "Cmd"; - 2-3: "Size"; - 4-7: "Checksum"; - 8-15: "Data" [color = lightgrey]; - 16-31: "..." [color = lightgrey]; -} diff --git a/tools/esptool_py/docs/en/advanced-topics/diag/download_procedure_chart.diag b/tools/esptool_py/docs/en/advanced-topics/diag/download_procedure_chart.diag deleted file mode 100644 index 5bbc2081b1..0000000000 --- a/tools/esptool_py/docs/en/advanced-topics/diag/download_procedure_chart.diag +++ /dev/null @@ -1,39 +0,0 @@ -blockdiag download_procedure_diagram { - node_height = 40; - node_width = 150; - span_width = 40; - span_height = 45; - default_fontsize = 12 - orientation = portrait; - edge_layout = flowchart; - default_group_color = none; - - // nodes - start [label = "Start", shape = flowchart.terminator]; - sync [label = "Synchronization", shape = box]; - success_cond [label = "Success?", shape = flowchart.condition]; - erase_data [label = "Erase data", shape = box]; - transmit_data [label = "Transmit data", shape = box]; - finish_cond [label = "Finish?", shape = flowchart.condition]; - transmit_finish [label = "Transmit finish frame", shape = box]; - finish [label = "Finish", shape = flowchart.terminator]; - // fake nodes to adjust shape and edge label position - succ_fin [shape = none]; - fincon_fin [shape = none]; - - // edges - start -> sync -> success_cond; - success_cond -> erase_data [label = "Yes"]; - erase_data -> transmit_data; - transmit_data -> finish_cond; - success_cond -- succ_fin [label = "Timeout"]; - finish_cond -> transmit_finish [label = "Yes"]; - finish_cond -- fincon_fin [label = "Failure"]; - succ_fin -- fincon_fin; - fincon_fin -> finish; - transmit_finish -> finish; - - // group - group{transmit_finish, fincon_fin}; - group{erase_data, succ_fin}; -} diff --git a/tools/esptool_py/docs/en/advanced-topics/diag/response_packet_format.diag b/tools/esptool_py/docs/en/advanced-topics/diag/response_packet_format.diag deleted file mode 100644 index 8a0b009042..0000000000 --- a/tools/esptool_py/docs/en/advanced-topics/diag/response_packet_format.diag +++ /dev/null @@ -1,13 +0,0 @@ -packetdiag command_packet_format{ - colwidth = 16 - node_width = 50 - node_height = 50 - default_fontsize = 16 - - 0: "0x01"; - 1: "Cmd"; - 2-3: "Size"; - 4-7: "Value"; - 8-15: "Data" [color = lightgrey]; - 16-31: "..." [color = lightgrey]; -} diff --git a/tools/esptool_py/docs/en/advanced-topics/firmware-image-format.rst b/tools/esptool_py/docs/en/advanced-topics/firmware-image-format.rst deleted file mode 100644 index 10d81bb576..0000000000 --- a/tools/esptool_py/docs/en/advanced-topics/firmware-image-format.rst +++ /dev/null @@ -1,174 +0,0 @@ -{IDF_TARGET_FLASH_FREQ_F:default="80", esp32c2="60", esp32h2="48"} - -{IDF_TARGET_FLASH_FREQ_0:default="40", esp32c2="30", esp32h2="24"} - -{IDF_TARGET_FLASH_FREQ_1:default="26", esp32c2="20", esp32h2="16"} - -{IDF_TARGET_FLASH_FREQ_2:default="20", esp32c2="15", esp32h2="12"} - -{IDF_TARGET_BOOTLOADER_OFFSET:default="0x0", esp32="0x1000", esp32s2="0x1000", esp32p4="0x2000"} - - -.. _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:: esp32s2 or esp32s3 or esp32p4 - - +--------+------------------------------------------------------------------------------------------------+ - | 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, | - | | ``5`` = 32MB, ``6`` = 64MB, ``7`` = 128MB") | - | | | - | | Low four bits - Flash frequency (``0`` = {IDF_TARGET_FLASH_FREQ_0}MHz, ``1`` = {IDF_TARGET_FLASH_FREQ_1}MHz, ``2`` = {IDF_TARGET_FLASH_FREQ_2}MHz, ``0xf`` = {IDF_TARGET_FLASH_FREQ_F}MHz) | - +--------+------------------------------------------------------------------------------------------------+ - | 4-7 | Entry point address | - +--------+------------------------------------------------------------------------------------------------+ - - -.. only:: esp32c6 - - +--------+------------------------------------------------------------------------------------------------+ - | 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`` = 80MHz, ``0`` = 40MHz, ``2`` = 20MHz) | - +--------+------------------------------------------------------------------------------------------------+ - | 4-7 | Entry point address | - +--------+------------------------------------------------------------------------------------------------+ - - .. note:: - Flash frequency with value ``0`` can mean either 80MHz or 40MHz based on MSPI clock source mode. - - -.. only:: not (esp8266 or esp32c6 or esp32s3 or esp32s2 or esp32p4) - - +--------+------------------------------------------------------------------------------------------------+ - | 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`` = {IDF_TARGET_FLASH_FREQ_0}MHz, ``1`` = {IDF_TARGET_FLASH_FREQ_1}MHz, ``2`` = {IDF_TARGET_FLASH_FREQ_2}MHz, ``0xf`` = {IDF_TARGET_FLASH_FREQ_F}MHz) | - +--------+------------------------------------------------------------------------------------------------+ - | 4-7 | Entry point address | - +--------+------------------------------------------------------------------------------------------------+ - - -``esptool.py`` overrides the 2nd and 3rd (counted from 0) bytes according to the SPI flash info provided through the command line option. These bytes are only overridden if this is a bootloader image (an image written to a correct bootloader offset of {IDF_TARGET_BOOTLOADER_OFFSET}), in this case, the appended SHA256 digest is also updated to reflect the header changes. Generating images without SHA256 digest 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/tools/esptool_py/docs/en/advanced-topics/index.rst b/tools/esptool_py/docs/en/advanced-topics/index.rst deleted file mode 100644 index 7f1d79e21b..0000000000 --- a/tools/esptool_py/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/tools/esptool_py/docs/en/advanced-topics/serial-protocol.rst b/tools/esptool_py/docs/en/advanced-topics/serial-protocol.rst deleted file mode 100644 index 48c85eec93..0000000000 --- a/tools/esptool_py/docs/en/advanced-topics/serial-protocol.rst +++ /dev/null @@ -1,507 +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. - -.. packetdiag:: diag/command_packet_format.diag - :caption: Command packet format - :align: center - - -+--------+-------------+--------------------------------------------------------------------------------------------------------------------+ -| 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: - -.. packetdiag:: diag/response_packet_format.diag - :caption: Command packet format - :align: center - -+--------+-------------+--------------------------------------------------------------------------------------------------------------+ -| Byte | Name | Comment | -+========+=============+==============================================================================================================+ -| 0 | Direction | Always ``0x01`` for responses | -+--------+-------------+--------------------------------------------------------------------------------------------------------------+ -| 1 | Command | Same value as Command identifier in the request packet that triggered 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 | Description | 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 commands 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 ----------------------- - -.. blockdiag:: diag/download_procedure_chart.diag - :caption: Download procedure flow chart - :align: center - - -.. note:: - This flow chart is used to illustrate the download procedure (writing to flash), other commands have different flows. - -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 sending this command before interacting with SPI flash is optional. On {IDF_TARGET_NAME} ROM 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: - - .. only:: esp32 - - * 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/tools/esptool_py/docs/en/advanced-topics/spi-flash-modes.rst b/tools/esptool_py/docs/en/advanced-topics/spi-flash-modes.rst deleted file mode 100644 index 22b54766de..0000000000 --- a/tools/esptool_py/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/tools/esptool_py/docs/en/conf.py b/tools/esptool_py/docs/en/conf.py deleted file mode 100644 index 0362dfc3e0..0000000000 --- a/tools/esptool_py/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/tools/esptool_py/docs/en/contributing.rst b/tools/esptool_py/docs/en/contributing.rst deleted file mode 100644 index c7fcb94cfb..0000000000 --- a/tools/esptool_py/docs/en/contributing.rst +++ /dev/null @@ -1,3 +0,0 @@ -.. _contribute: - -.. include:: ../../CONTRIBUTING.rst diff --git a/tools/esptool_py/docs/en/espefuse/adc-info-cmd.rst b/tools/esptool_py/docs/en/espefuse/adc-info-cmd.rst deleted file mode 100644 index e7c11f22ce..0000000000 --- a/tools/esptool_py/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/tools/esptool_py/docs/en/espefuse/burn-bit-cmd.rst b/tools/esptool_py/docs/en/espefuse/burn-bit-cmd.rst deleted file mode 100644 index 11b180bf41..0000000000 --- a/tools/esptool_py/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/tools/esptool_py/docs/en/espefuse/burn-block-data-cmd.rst b/tools/esptool_py/docs/en/espefuse/burn-block-data-cmd.rst deleted file mode 100644 index 0b09519600..0000000000 --- a/tools/esptool_py/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/tools/esptool_py/docs/en/espefuse/burn-custom-mac-cmd.rst b/tools/esptool_py/docs/en/espefuse/burn-custom-mac-cmd.rst deleted file mode 100644 index fe1ea178a0..0000000000 --- a/tools/esptool_py/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 diff --git a/tools/esptool_py/docs/en/espefuse/burn-efuse-cmd.rst b/tools/esptool_py/docs/en/espefuse/burn-efuse-cmd.rst deleted file mode 100644 index 4d6446d9c7..0000000000 --- a/tools/esptool_py/docs/en/espefuse/burn-efuse-cmd.rst +++ /dev/null @@ -1,105 +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`` - -Optional arguments: - -* ``--force``. Suppress an error to burn eFuses. The tool checks for incompatible eFuse states to prevent them from burning and potentially **bricking the chip**. Use this flag only if you are sure. This will suppress the eFuse incompatibility error. - -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/tools/esptool_py/docs/en/espefuse/burn-key-cmd.rst b/tools/esptool_py/docs/en/espefuse/burn-key-cmd.rst deleted file mode 100644 index c6a7714c26..0000000000 --- a/tools/esptool_py/docs/en/espefuse/burn-key-cmd.rst +++ /dev/null @@ -1,345 +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 and not esp32h2: - ``Keyfile``. It is a raw binary file. The length of binary key depends on the key purpose option. - :esp32h2: - ``Keyfile``. It is a raw binary file. The length of binary key depends on the key purpose option. For the ``ECDSA_KEY`` purpose use ``PEM`` file. - :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. - - ``--show-sensitive-info``. Show data to be burned (may expose sensitive data). Enabled if --debug is used. Use this option to see the byte order of the data being written. - -.. only:: esp32 - - {IDF_TARGET_NAME} supports 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 access 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:: not esp32 and not esp32c2 - - {IDF_TARGET_NAME} supports 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. - :esp32h2: - ECDSA_KEY. It can be ECDSA private keys based on NIST192p or NIST256p curve. The private key is extracted from the given file and written into a eFuse block with write and read protection enabled. This private key shall be used by ECDSA accelerator for the signing purpose. - - 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:: esp32h2 - - {IDF_TARGET_NAME} has the ECDSA accelerator for signature purposes and supports private keys based on the NIST192p or NIST256p curve. These two commands below can be used to generate such keys (``PEM`` file). The ``burn_key`` command with the ``ECDSA_KEY`` purpose takes the ``PEM`` file and writes the private key into a eFuse block. The key is written to the block in reverse byte order. - - For NIST192p, the private key is 192 bits long, so 8 padding bytes ("0x00") are added. - - .. code-block:: none - - > espsecure.py generate_signing_key -v 2 -s ecdsa192 ecdsa192.pem - ECDSA NIST192p private key in PEM format written to ecdsa192.pem - - .. code-block:: none - - > espsecure.py generate_signing_key -v 2 -s ecdsa256 ecdsa256.pem - ECDSA NIST256p private key in PEM format written to ecdsa256.pem - -.. 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 === - Sensitive data will be hidden (see --show-sensitive-info) - Burn keys to blocks: - - BLOCK1 -> [?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ??] - 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 === - Sensitive data will be hidden (see --show-sensitive-info) - Burn keys to blocks: - - BLOCK1 -> [?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ??] - 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 === - Sensitive data will be hidden (see --show-sensitive-info) - Burn keys to blocks: - - BLOCK_KEY0 -> [?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ??] - 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 -> [?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ??] - 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 === - Sensitive data will be hidden (see --show-sensitive-info) - Burn keys to blocks: - - BLOCK_KEY0_HI_128 -> [?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ??] - Disabling write to key block - - - Batch mode is enabled, the burn will be done at the end of the command. - - === Run "burn_key" command === - Sensitive data will be hidden (see --show-sensitive-info) - Burn keys to blocks: - - BLOCK_KEY0_LOW_128 -> [?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ??] - 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/tools/esptool_py/docs/en/espefuse/burn-key-digest-cmd.rst b/tools/esptool_py/docs/en/espefuse/burn-key-digest-cmd.rst deleted file mode 100644 index 4402a8c92c..0000000000 --- a/tools/esptool_py/docs/en/espefuse/burn-key-digest-cmd.rst +++ /dev/null @@ -1,174 +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. - - ``--show-sensitive-info``. Show data to be burned (may expose sensitive data). Enabled if --debug is used. Use this option to see the byte order of the data being written. - -.. 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 === - Sensitive data will be hidden (see --show-sensitive-info) - - BLOCK2 -> [?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ??] - 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 === - Sensitive data will be hidden (see --show-sensitive-info) - Burn keys to blocks: - - BLOCK_KEY0_HI_128 -> [?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ??] - 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 === - Sensitive data will be hidden (see --show-sensitive-info) - Burn keys to blocks: - - BLOCK_KEY0 -> [?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ??] - 'KEY_PURPOSE_0': 'USER' -> 'SECURE_BOOT_DIGEST0'. - Disabling write to 'KEY_PURPOSE_0'. - Disabling write to key block - - - BLOCK_KEY1 -> [?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ??] - 'KEY_PURPOSE_1': 'USER' -> 'SECURE_BOOT_DIGEST1'. - Disabling write to 'KEY_PURPOSE_1'. - Disabling write to key block - - - BLOCK_KEY2 -> [?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ??] - '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/tools/esptool_py/docs/en/espefuse/check-error-cmd.rst b/tools/esptool_py/docs/en/espefuse/check-error-cmd.rst deleted file mode 100644 index 0723adf2c2..0000000000 --- a/tools/esptool_py/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/tools/esptool_py/docs/en/espefuse/dump-cmd.rst b/tools/esptool_py/docs/en/espefuse/dump-cmd.rst deleted file mode 100644 index 8f841ccb8e..0000000000 --- a/tools/esptool_py/docs/en/espefuse/dump-cmd.rst +++ /dev/null @@ -1,126 +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: - -- ``--format`` - Selects the dump format: - - ``default`` - Usual console eFuse dump; - - ``joint`` - All eFuse blocks are stored in one file; - - ``split`` - Each eFuse block is placed in its own file. The tool will create multiple files based on the given the ``--file_name`` argument. Example: "--file_name /path/blk.bin", blk0.bin, blk1.bin ... blkN.bin. Use the ``burn_block_data`` cmd to write it back to another chip. -- ``--file_name`` - The path to the file in which to save the dump, if not specified, output to the console. - -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 --format split --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 - -To save all eFuse blocks in one file, use the following command: - -.. code-block:: none - - > espefuse.py dump --format joint --file_name backup/chip1/efuses.bin - - === Run "dump" command === - backup/chip1/efuses.bin diff --git a/tools/esptool_py/docs/en/espefuse/execute-scripts-cmd.rst b/tools/esptool_py/docs/en/espefuse/execute-scripts-cmd.rst deleted file mode 100644 index 81319a354a..0000000000 --- a/tools/esptool_py/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/tools/esptool_py/docs/en/espefuse/get-custom-mac-cmd.rst b/tools/esptool_py/docs/en/espefuse/get-custom-mac-cmd.rst deleted file mode 100644 index 3077e991e7..0000000000 --- a/tools/esptool_py/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/tools/esptool_py/docs/en/espefuse/inc/summary_ESP32-C2.rst b/tools/esptool_py/docs/en/espefuse/inc/summary_ESP32-C2.rst deleted file mode 100644 index f42d80d43a..0000000000 --- a/tools/esptool_py/docs/en/espefuse/inc/summary_ESP32-C2.rst +++ /dev/null @@ -1,67 +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) - ---------------------------------------------------------------------------------------- - Config fuses: - WR_DIS (BLOCK0) Disable programming of individual eFuses = 0 R/W (0x00) - RD_DIS (BLOCK0) Disable reading from BlOCK3 = 0 R/W (0b00) - UART_PRINT_CONTROL (BLOCK0) Set the default UARTboot message output mode = Enable R/W (0b00) - DIS_DIRECT_BOOT (BLOCK0) This bit set means disable direct_boot mode = False R/W (0b0) - - Flash fuses: - FORCE_SEND_RESUME (BLOCK0) Set this bit to force ROM code to send a resume co = False R/W (0b0) - mmand during SPI boot - FLASH_TPUW (BLOCK0) Configures flash waiting time after power-up; in u = 0 R/W (0x0) - nit of ms. If the value is less than 15; the waiti - ng time is the configurable value. Otherwise; the - waiting time is twice the configurable value - - Identity fuses: - DISABLE_WAFER_VERSION_MAJOR (BLOCK0) Disables check of wafer version major = False R/W (0b0) - DISABLE_BLK_VERSION_MAJOR (BLOCK0) Disables check of blk version major = False R/W (0b0) - WAFER_VERSION_MINOR (BLOCK2) WAFER_VERSION_MINOR = 0 R/W (0x0) - WAFER_VERSION_MAJOR (BLOCK2) WAFER_VERSION_MAJOR = 1 R/W (0b01) - PKG_VERSION (BLOCK2) EFUSE_PKG_VERSION = 1 R/W (0b001) - BLK_VERSION_MINOR (BLOCK2) Minor version of BLOCK2 = No calib R/W (0b000) - BLK_VERSION_MAJOR (BLOCK2) Major version of BLOCK2 = 0 R/W (0b00) - - Jtag fuses: - DIS_PAD_JTAG (BLOCK0) Set this bit to disable pad jtag = False R/W (0b0) - - Mac fuses: - CUSTOM_MAC_USED (BLOCK0) True if MAC_CUSTOM is burned = False R/W (0b0) - CUSTOM_MAC (BLOCK1) Custom MAC address - = 00:00:00:00:00:00 (OK) R/W - MAC (BLOCK2) MAC address - = 10:97:bd:f0:e5:28 (OK) R/W - - Security fuses: - DIS_DOWNLOAD_ICACHE (BLOCK0) The bit be set to disable icache in download mode = False R/W (0b0) - DIS_DOWNLOAD_MANUAL_ENCRYPT (BLOCK0) The bit be set to disable manual encryption = False R/W (0b0) - SPI_BOOT_CRYPT_CNT (BLOCK0) Enables flash encryption when 1 or 3 bits are set = Disable R/W (0b000) - and disables otherwise - XTS_KEY_LENGTH_256 (BLOCK0) Flash encryption key length = 128 bits key R/W (0b0) - DIS_DOWNLOAD_MODE (BLOCK0) Set this bit to disable download mode (boot_mode[3 = False R/W (0b0) - :0] = 0; 1; 2; 4; 5; 6; 7) - ENABLE_SECURITY_DOWNLOAD (BLOCK0) Set this bit to enable secure UART download mode = False R/W (0b0) - SECURE_BOOT_EN (BLOCK0) The bit be set to enable secure boot = False R/W (0b0) - SECURE_VERSION (BLOCK0) Secure version for anti-rollback = 0 R/W (0x0) - 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 fuses: - WDT_DELAY_SEL (BLOCK0) RTC watchdog timeout threshold; in unit of slow cl = 40000 R/W (0b00) - ock cycle diff --git a/tools/esptool_py/docs/en/espefuse/inc/summary_ESP32-C3.rst b/tools/esptool_py/docs/en/espefuse/inc/summary_ESP32-C3.rst deleted file mode 100644 index c20b5c58df..0000000000 --- a/tools/esptool_py/docs/en/espefuse/inc/summary_ESP32-C3.rst +++ /dev/null @@ -1,154 +0,0 @@ -.. code-block:: none - - > espefuse.py -p PORT summary - - Connecting.... - Detecting chip type... ESP32-C3 - - === Run "summary" command === - EFUSE_NAME (Block) Description = [Meaningful Value] [Readable/Writeable] (Hex Value) - ---------------------------------------------------------------------------------------- - Calibration fuses: - K_RTC_LDO (BLOCK1) BLOCK1 K_RTC_LDO = -36 R/W (0b1001001) - K_DIG_LDO (BLOCK1) BLOCK1 K_DIG_LDO = -64 R/W (0b1010000) - V_RTC_DBIAS20 (BLOCK1) BLOCK1 voltage of rtc dbias20 = -40 R/W (0x8a) - V_DIG_DBIAS20 (BLOCK1) BLOCK1 voltage of digital dbias20 = -76 R/W (0x93) - DIG_DBIAS_HVT (BLOCK1) BLOCK1 digital dbias when hvt = -28 R/W (0b10111) - THRES_HVT (BLOCK1) BLOCK1 pvt threshold when hvt = 2000 R/W (0b0111110100) - TEMP_CALIB (BLOCK2) Temperature calibration data = -7.2 R/W (0b101001000) - OCODE (BLOCK2) ADC OCode = 78 R/W (0x4e) - ADC1_INIT_CODE_ATTEN0 (BLOCK2) ADC1 init code at atten0 = 1560 R/W (0b0110000110) - ADC1_INIT_CODE_ATTEN1 (BLOCK2) ADC1 init code at atten1 = -108 R/W (0b1000011011) - ADC1_INIT_CODE_ATTEN2 (BLOCK2) ADC1 init code at atten2 = -232 R/W (0b1000111010) - ADC1_INIT_CODE_ATTEN3 (BLOCK2) ADC1 init code at atten3 = -696 R/W (0b1010101110) - ADC1_CAL_VOL_ATTEN0 (BLOCK2) ADC1 calibration voltage at atten0 = -212 R/W (0b1000110101) - ADC1_CAL_VOL_ATTEN1 (BLOCK2) ADC1 calibration voltage at atten1 = 52 R/W (0b0000001101) - ADC1_CAL_VOL_ATTEN2 (BLOCK2) ADC1 calibration voltage at atten2 = -152 R/W (0b1000100110) - ADC1_CAL_VOL_ATTEN3 (BLOCK2) ADC1 calibration voltage at atten3 = -284 R/W (0b1001000111) - - Config fuses: - WR_DIS (BLOCK0) Disable programming of individual eFuses = 0 R/W (0x00000000) - RD_DIS (BLOCK0) Disable reading from BlOCK4-10 = 0 R/W (0b0000000) - DIS_ICACHE (BLOCK0) Set this bit to disable Icache = False R/W (0b0) - DIS_TWAI (BLOCK0) Set this bit to disable CAN function = False R/W (0b0) - DIS_DIRECT_BOOT (BLOCK0) Disable direct boot mode = False R/W (0b0) - UART_PRINT_CONTROL (BLOCK0) Set the default UARTboot message output mode = Enable R/W (0b00) - ERR_RST_ENABLE (BLOCK0) Use BLOCK0 to check error record registers = with check R/W (0b1) - 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 - BLOCK_SYS_DATA2 (BLOCK10) System data part 2 (reserved) - = 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 - - Flash fuses: - FLASH_TPUW (BLOCK0) Configures flash waiting time after power-up; in u = 0 R/W (0x0) - nit of ms. If the value is less than 15; the waiti - ng time is the configurable value; Otherwise; the - waiting time is twice the configurable value - FORCE_SEND_RESUME (BLOCK0) Set this bit to force ROM code to send a resume co = False R/W (0b0) - mmand during SPI boot - - Identity fuses: - DISABLE_WAFER_VERSION_MAJOR (BLOCK0) Disables check of wafer version major = False R/W (0b0) - DISABLE_BLK_VERSION_MAJOR (BLOCK0) Disables check of blk version major = False R/W (0b0) - WAFER_VERSION_MINOR_LO (BLOCK1) WAFER_VERSION_MINOR least significant bits = 3 R/W (0b011) - PKG_VERSION (BLOCK1) Package version = 0 R/W (0b000) - BLK_VERSION_MINOR (BLOCK1) BLK_VERSION_MINOR = 2 R/W (0b010) - WAFER_VERSION_MINOR_HI (BLOCK1) WAFER_VERSION_MINOR most significant bit = False R/W (0b0) - WAFER_VERSION_MAJOR (BLOCK1) WAFER_VERSION_MAJOR = 0 R/W (0b00) - OPTIONAL_UNIQUE_ID (BLOCK2) Optional unique 128-bit ID - = 25 60 04 96 c3 fd 41 6f be ed 2c 51 1d e3 7e 21 R/W - BLK_VERSION_MAJOR (BLOCK2) BLK_VERSION_MAJOR of BLOCK2 = With calibration R/W (0b01) - WAFER_VERSION_MINOR (BLOCK0) calc WAFER VERSION MINOR = WAFER_VERSION_MINOR_HI = 3 R/W (0x3) - << 3 + WAFER_VERSION_MINOR_LO (read only) - - Jtag fuses: - SOFT_DIS_JTAG (BLOCK0) Set these bits to disable JTAG in the soft way (od = 0 R/W (0b000) - d number 1 means disable ). JTAG can be enabled in - HMAC module - DIS_PAD_JTAG (BLOCK0) Set this bit to disable JTAG in the hard way. JTAG = False R/W (0b0) - is disabled permanently - - Mac fuses: - MAC (BLOCK1) MAC address - = 58:cf:79:0f:96:8c (OK) R/W - CUSTOM_MAC (BLOCK3) Custom MAC address - = 00:00:00:00:00:00 (OK) R/W - - Security fuses: - DIS_DOWNLOAD_ICACHE (BLOCK0) Set this bit to disable Icache in download mode (b = False R/W (0b0) - oot_mode[3:0] is 0; 1; 2; 3; 6; 7) - DIS_FORCE_DOWNLOAD (BLOCK0) Set this bit to disable the function that forces c = False R/W (0b0) - hip into download mode - DIS_DOWNLOAD_MANUAL_ENCRYPT (BLOCK0) Set this bit to disable flash encryption when in d = False R/W (0b0) - ownload boot modes - SPI_BOOT_CRYPT_CNT (BLOCK0) Enables flash encryption when 1 or 3 bits are set = Disable R/W (0b000) - and disables otherwise - SECURE_BOOT_KEY_REVOKE0 (BLOCK0) Revoke 1st secure boot key = False R/W (0b0) - SECURE_BOOT_KEY_REVOKE1 (BLOCK0) Revoke 2nd secure boot key = False R/W (0b0) - SECURE_BOOT_KEY_REVOKE2 (BLOCK0) Revoke 3rd secure boot key = False R/W (0b0) - KEY_PURPOSE_0 (BLOCK0) Purpose of Key0 = USER R/W (0x0) - KEY_PURPOSE_1 (BLOCK0) Purpose of Key1 = USER R/W (0x0) - KEY_PURPOSE_2 (BLOCK0) Purpose of Key2 = USER R/W (0x0) - KEY_PURPOSE_3 (BLOCK0) Purpose of Key3 = USER R/W (0x0) - KEY_PURPOSE_4 (BLOCK0) Purpose of Key4 = USER R/W (0x0) - KEY_PURPOSE_5 (BLOCK0) Purpose of Key5 = USER R/W (0x0) - SECURE_BOOT_EN (BLOCK0) Set this bit to enable secure boot = False R/W (0b0) - SECURE_BOOT_AGGRESSIVE_REVOKE (BLOCK0) Set this bit to enable revoking aggressive secure = False R/W (0b0) - boot - DIS_DOWNLOAD_MODE (BLOCK0) Set this bit to disable download mode (boot_mode[3 = False R/W (0b0) - :0] = 0; 1; 2; 3; 6; 7) - ENABLE_SECURITY_DOWNLOAD (BLOCK0) Set this bit to enable secure UART download mode = False R/W (0b0) - SECURE_VERSION (BLOCK0) Secure version (used by ESP-IDF anti-rollback feat = 0 R/W (0x0000) - ure) - BLOCK_KEY0 (BLOCK4) - Purpose: USER - 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) - Purpose: USER - 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) - Purpose: USER - 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) - Purpose: USER - 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) - Purpose: USER - 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) - Purpose: USER - 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 - - Spi Pad fuses: - SPI_PAD_CONFIG_CLK (BLOCK1) SPI PAD CLK = 0 R/W (0b000000) - SPI_PAD_CONFIG_Q (BLOCK1) SPI PAD Q(D1) = 0 R/W (0b000000) - SPI_PAD_CONFIG_D (BLOCK1) SPI PAD D(D0) = 0 R/W (0b000000) - SPI_PAD_CONFIG_CS (BLOCK1) SPI PAD CS = 0 R/W (0b000000) - SPI_PAD_CONFIG_HD (BLOCK1) SPI PAD HD(D3) = 0 R/W (0b000000) - SPI_PAD_CONFIG_WP (BLOCK1) SPI PAD WP(D2) = 0 R/W (0b000000) - SPI_PAD_CONFIG_DQS (BLOCK1) SPI PAD DQS = 0 R/W (0b000000) - SPI_PAD_CONFIG_D4 (BLOCK1) SPI PAD D4 = 0 R/W (0b000000) - SPI_PAD_CONFIG_D5 (BLOCK1) SPI PAD D5 = 0 R/W (0b000000) - SPI_PAD_CONFIG_D6 (BLOCK1) SPI PAD D6 = 0 R/W (0b000000) - SPI_PAD_CONFIG_D7 (BLOCK1) SPI PAD D7 = 0 R/W (0b000000) - - Usb fuses: - DIS_USB_JTAG (BLOCK0) Set this bit to disable function of usb switch to = False R/W (0b0) - jtag in module of usb device - DIS_USB_SERIAL_JTAG (BLOCK0) USB-Serial-JTAG = Enable R/W (0b0) - USB_EXCHG_PINS (BLOCK0) Set this bit to exchange USB D+ and D- pins = False R/W (0b0) - DIS_USB_SERIAL_JTAG_ROM_PRINT (BLOCK0) USB printing = Enable R/W (0b0) - DIS_USB_SERIAL_JTAG_DOWNLOAD_MODE (BLOCK0) Disable UART download mode through USB-Serial-JTAG = False R/W (0b0) - - Vdd fuses: - VDD_SPI_AS_GPIO (BLOCK0) Set this bit to vdd spi pin function as gpio = False R/W (0b0) - - Wdt fuses: - WDT_DELAY_SEL (BLOCK0) RTC watchdog timeout threshold; in unit of slow cl = 40000 R/W (0b00) - ock cycle diff --git a/tools/esptool_py/docs/en/espefuse/inc/summary_ESP32-C6.rst b/tools/esptool_py/docs/en/espefuse/inc/summary_ESP32-C6.rst deleted file mode 100644 index fdfc78bcec..0000000000 --- a/tools/esptool_py/docs/en/espefuse/inc/summary_ESP32-C6.rst +++ /dev/null @@ -1,155 +0,0 @@ -.. code-block:: none - - > espefuse.py -p PORT summary - - Connecting.... - Detecting chip type... ESP32-C6 - - === Run "summary" command === - EFUSE_NAME (Block) Description = [Meaningful Value] [Readable/Writeable] (Hex Value) - ---------------------------------------------------------------------------------------- - Config fuses: - WR_DIS (BLOCK0) Disable programming of individual eFuses = 0 R/W (0x00000000) - RD_DIS (BLOCK0) Disable reading from BlOCK4-10 = 0 R/W (0b0000000) - SWAP_UART_SDIO_EN (BLOCK0) Represents whether pad of uart and sdio is swapped = False R/W (0b0) - or not. 1: swapped. 0: not swapped - DIS_ICACHE (BLOCK0) Represents whether icache is disabled or enabled. = False R/W (0b0) - 1: disabled. 0: enabled - DIS_TWAI (BLOCK0) Represents whether TWAI function is disabled or en = False R/W (0b0) - abled. 1: disabled. 0: enabled - DIS_DIRECT_BOOT (BLOCK0) Represents whether direct boot mode is disabled or = False R/W (0b0) - enabled. 1: disabled. 0: enabled - UART_PRINT_CONTROL (BLOCK0) Set the default UARTboot message output mode = Enable R/W (0b00) - 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 - BLOCK_SYS_DATA2 (BLOCK10) System data part 2 (reserved) - = 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 - - Flash fuses: - FLASH_TPUW (BLOCK0) Represents the flash waiting time after power-up; = 0 R/W (0x0) - in unit of ms. When the value less than 15; the wa - iting time is the programmed value. Otherwise; the - waiting time is 2 times the programmed value - FORCE_SEND_RESUME (BLOCK0) Represents whether ROM code is forced to send a re = False R/W (0b0) - sume command during SPI boot. 1: forced. 0:not for - ced - FLASH_CAP (BLOCK1) = 0 R/W (0b000) - FLASH_TEMP (BLOCK1) = 0 R/W (0b00) - FLASH_VENDOR (BLOCK1) = 0 R/W (0b000) - - Identity fuses: - DISABLE_WAFER_VERSION_MAJOR (BLOCK0) Disables check of wafer version major = False R/W (0b0) - DISABLE_BLK_VERSION_MAJOR (BLOCK0) Disables check of blk version major = False R/W (0b0) - WAFER_VERSION_MINOR (BLOCK1) = 0 R/W (0x0) - WAFER_VERSION_MAJOR (BLOCK1) = 0 R/W (0b00) - BLK_VERSION_MINOR (BLOCK1) BLK_VERSION_MINOR of BLOCK2 = 0 R/W (0b000) - BLK_VERSION_MAJOR (BLOCK1) BLK_VERSION_MAJOR of BLOCK2 = 0 R/W (0b00) - PKG_VERSION (BLOCK1) Package version = 0 R/W (0b000) - OPTIONAL_UNIQUE_ID (BLOCK2) Optional unique 128-bit ID - = 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 R/W - - Jtag fuses: - JTAG_SEL_ENABLE (BLOCK0) Represents whether the selection between usb_to_jt = False R/W (0b0) - ag and pad_to_jtag through strapping gpio15 when b - oth EFUSE_DIS_PAD_JTAG and EFUSE_DIS_USB_JTAG are - equal to 0 is enabled or disabled. 1: enabled. 0: - disabled - SOFT_DIS_JTAG (BLOCK0) Represents whether JTAG is disabled in soft way. O = 0 R/W (0b000) - dd number: disabled. Even number: enabled - DIS_PAD_JTAG (BLOCK0) Represents whether JTAG is disabled in the hard wa = False R/W (0b0) - y(permanently). 1: disabled. 0: enabled - - Mac fuses: - MAC (BLOCK1) MAC address - = 60:55:f9:f6:03:24 (OK) R/W - MAC_EXT (BLOCK1) Stores the extended bits of MAC address = 00:00 (OK) R/W - CUSTOM_MAC (BLOCK3) Custom MAC - = 00:00:00:00:00:00 (OK) R/W - - Security fuses: - DIS_DOWNLOAD_ICACHE (BLOCK0) Represents whether icache is disabled or enabled i = False R/W (0b0) - n Download mode. 1: disabled. 0: enabled - DIS_FORCE_DOWNLOAD (BLOCK0) Represents whether the function that forces chip i = False R/W (0b0) - nto download mode is disabled or enabled. 1: disab - led. 0: enabled - SPI_DOWNLOAD_MSPI_DIS (BLOCK0) Represents whether SPI0 controller during boot_mod = False R/W (0b0) - e_download is disabled or enabled. 1: disabled. 0: - enabled - DIS_DOWNLOAD_MANUAL_ENCRYPT (BLOCK0) Represents whether flash encrypt function is disab = False R/W (0b0) - led or enabled(except in SPI boot mode). 1: disabl - ed. 0: enabled - SPI_BOOT_CRYPT_CNT (BLOCK0) Enables flash encryption when 1 or 3 bits are set = Disable R/W (0b000) - and disables otherwise - SECURE_BOOT_KEY_REVOKE0 (BLOCK0) Revoke 1st secure boot key = False R/W (0b0) - SECURE_BOOT_KEY_REVOKE1 (BLOCK0) Revoke 2nd secure boot key = False R/W (0b0) - SECURE_BOOT_KEY_REVOKE2 (BLOCK0) Revoke 3rd secure boot key = False R/W (0b0) - KEY_PURPOSE_0 (BLOCK0) Represents the purpose of Key0 = USER R/W (0x0) - KEY_PURPOSE_1 (BLOCK0) Represents the purpose of Key1 = USER R/W (0x0) - KEY_PURPOSE_2 (BLOCK0) Represents the purpose of Key2 = USER R/W (0x0) - KEY_PURPOSE_3 (BLOCK0) Represents the purpose of Key3 = USER R/W (0x0) - KEY_PURPOSE_4 (BLOCK0) Represents the purpose of Key4 = USER R/W (0x0) - KEY_PURPOSE_5 (BLOCK0) Represents the purpose of Key5 = USER R/W (0x0) - SEC_DPA_LEVEL (BLOCK0) Represents the spa secure level by configuring the = 0 R/W (0b00) - clock random divide mode - CRYPT_DPA_ENABLE (BLOCK0) Represents whether anti-dpa attack is enabled. 1:e = False R/W (0b0) - nabled. 0: disabled - SECURE_BOOT_EN (BLOCK0) Represents whether secure boot is enabled or disab = False R/W (0b0) - led. 1: enabled. 0: disabled - SECURE_BOOT_AGGRESSIVE_REVOKE (BLOCK0) Represents whether revoking aggressive secure boot = False R/W (0b0) - is enabled or disabled. 1: enabled. 0: disabled - DIS_DOWNLOAD_MODE (BLOCK0) Represents whether Download mode is disabled or en = False R/W (0b0) - abled. 1: disabled. 0: enabled - ENABLE_SECURITY_DOWNLOAD (BLOCK0) Represents whether security download is enabled or = False R/W (0b0) - disabled. 1: enabled. 0: disabled - SECURE_VERSION (BLOCK0) Represents the version used by ESP-IDF anti-rollba = 0 R/W (0x0000) - ck feature - SECURE_BOOT_DISABLE_FAST_WAKE (BLOCK0) Represents whether FAST VERIFY ON WAKE is disabled = False R/W (0b0) - or enabled when Secure Boot is enabled. 1: disabl - ed. 0: enabled - BLOCK_KEY0 (BLOCK4) - Purpose: USER - 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) - Purpose: USER - 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) - Purpose: USER - 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) - Purpose: USER - 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) - Purpose: USER - 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) - Purpose: USER - 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 - - Usb fuses: - DIS_USB_JTAG (BLOCK0) Represents whether the function of usb switch to j = False R/W (0b0) - tag is disabled or enabled. 1: disabled. 0: enable - d - DIS_USB_SERIAL_JTAG (BLOCK0) Represents whether USB-Serial-JTAG is disabled or = False R/W (0b0) - enabled. 1: disabled. 0: enabled - USB_EXCHG_PINS (BLOCK0) Represents whether the D+ and D- pins is exchanged = False R/W (0b0) - . 1: exchanged. 0: not exchanged - DIS_USB_SERIAL_JTAG_ROM_PRINT (BLOCK0) Represents whether print from USB-Serial-JTAG is d = False R/W (0b0) - isabled or enabled. 1: disabled. 0: enabled - DIS_USB_SERIAL_JTAG_DOWNLOAD_MODE (BLOCK0) Represents whether the USB-Serial-JTAG download fu = False R/W (0b0) - nction is disabled or enabled. 1: disabled. 0: ena - bled - - Vdd fuses: - VDD_SPI_AS_GPIO (BLOCK0) Represents whether vdd spi pin is functioned as gp = False R/W (0b0) - io. 1: functioned. 0: not functioned - - Wdt fuses: - WDT_DELAY_SEL (BLOCK0) Represents whether RTC watchdog timeout threshold = 0 R/W (0b00) - is selected at startup. 1: selected. 0: not select - ed diff --git a/tools/esptool_py/docs/en/espefuse/inc/summary_ESP32-H2.rst b/tools/esptool_py/docs/en/espefuse/inc/summary_ESP32-H2.rst deleted file mode 100644 index 53c48e830e..0000000000 --- a/tools/esptool_py/docs/en/espefuse/inc/summary_ESP32-H2.rst +++ /dev/null @@ -1,155 +0,0 @@ -.. code-block:: none - - > espefuse.py -p PORT summary - - Connecting.... - Detecting chip type... ESP32-H2 - - === Run "summary" command === - EFUSE_NAME (Block) Description = [Meaningful Value] [Readable/Writeable] (Hex Value) - ---------------------------------------------------------------------------------------- - Config fuses: - WR_DIS (BLOCK0) Disable programming of individual eFuses = 0 R/W (0x00000000) - RD_DIS (BLOCK0) Disable reading from BlOCK4-10 = 0 R/W (0b0000000) - DIS_ICACHE (BLOCK0) Represents whether icache is disabled or enabled. = False R/W (0b0) - 1: disabled. 0: enabled - POWERGLITCH_EN (BLOCK0) Represents whether power glitch function is enable = False R/W (0b0) - d. 1: enabled. 0: disabled - DIS_TWAI (BLOCK0) Represents whether TWAI function is disabled or en = False R/W (0b0) - abled. 1: disabled. 0: enabled - DIS_DIRECT_BOOT (BLOCK0) Represents whether direct boot mode is disabled or = False R/W (0b0) - enabled. 1: disabled. 0: enabled - UART_PRINT_CONTROL (BLOCK0) Set the default UARTboot message output mode = Enable R/W (0b00) - HYS_EN_PAD0 (BLOCK0) Set bits to enable hysteresis function of PAD0~5 = 0 R/W (0b000000) - HYS_EN_PAD1 (BLOCK0) Set bits to enable hysteresis function of PAD6~27 = 0 R/W (0b0000000000000000000000) - 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 - BLOCK_SYS_DATA2 (BLOCK10) System data part 2 (reserved) - = 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 - - Flash fuses: - FLASH_TPUW (BLOCK0) Represents the flash waiting time after power-up; = 0 R/W (0x0) - in unit of ms. When the value less than 15; the wa - iting time is the programmed value. Otherwise; the - waiting time is 2 times the programmed value - FORCE_SEND_RESUME (BLOCK0) Represents whether ROM code is forced to send a re = False R/W (0b0) - sume command during SPI boot. 1: forced. 0:not for - ced - FLASH_CAP (BLOCK1) = 0 R/W (0b000) - FLASH_TEMP (BLOCK1) = 0 R/W (0b00) - FLASH_VENDOR (BLOCK1) = 0 R/W (0b000) - - Identity fuses: - WAFER_VERSION_MINOR (BLOCK1) = 0 R/W (0b000) - WAFER_VERSION_MAJOR (BLOCK1) = 0 R/W (0b00) - DISABLE_WAFER_VERSION_MAJOR (BLOCK1) Disables check of wafer version major = False R/W (0b0) - PKG_VERSION (BLOCK1) Package version = 0 R/W (0b000) - OPTIONAL_UNIQUE_ID (BLOCK2) 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_MINOR (BLOCK2) BLK_VERSION_MINOR of BLOCK2 = 0 R/W (0b000) - BLK_VERSION_MAJOR (BLOCK2) BLK_VERSION_MAJOR of BLOCK2 = 0 R/W (0b00) - DISABLE_BLK_VERSION_MAJOR (BLOCK2) Disables check of blk version major = False R/W (0b0) - - Jtag 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 gpio25 when b - oth EFUSE_DIS_PAD_JTAG and EFUSE_DIS_USB_JTAG are - equal to 0 - SOFT_DIS_JTAG (BLOCK0) Represents whether JTAG is disabled in soft way. O = 0 R/W (0b000) - dd number: disabled. Even number: enabled - DIS_PAD_JTAG (BLOCK0) Represents whether JTAG is disabled in the hard wa = False R/W (0b0) - y(permanently). 1: disabled. 0: enabled - - Mac fuses: - MAC (BLOCK1) MAC address - = 60:55:f9:f7:2c:05 (OK) R/W - MAC_EXT (BLOCK1) Stores the extended bits of MAC address = ff:fe (OK) R/W - CUSTOM_MAC (BLOCK3) Custom MAC - = 00:00:00:00:00:00 (OK) R/W - - Security fuses: - DIS_FORCE_DOWNLOAD (BLOCK0) Represents whether the function that forces chip i = False R/W (0b0) - nto download mode is disabled or enabled. 1: disab - led. 0: enabled - SPI_DOWNLOAD_MSPI_DIS (BLOCK0) Represents whether SPI0 controller during boot_mod = False R/W (0b0) - e_download is disabled or enabled. 1: disabled. 0: - enabled - DIS_DOWNLOAD_MANUAL_ENCRYPT (BLOCK0) Represents whether flash encrypt function is disab = False R/W (0b0) - led or enabled(except in SPI boot mode). 1: disabl - ed. 0: enabled - SPI_BOOT_CRYPT_CNT (BLOCK0) Enables flash encryption when 1 or 3 bits are set = Disable R/W (0b000) - and disables otherwise - SECURE_BOOT_KEY_REVOKE0 (BLOCK0) Revoke 1st secure boot key = False R/W (0b0) - SECURE_BOOT_KEY_REVOKE1 (BLOCK0) Revoke 2nd secure boot key = False R/W (0b0) - SECURE_BOOT_KEY_REVOKE2 (BLOCK0) Revoke 3rd secure boot key = False R/W (0b0) - KEY_PURPOSE_0 (BLOCK0) Represents the purpose of Key0 = USER R/W (0x0) - KEY_PURPOSE_1 (BLOCK0) Represents the purpose of Key1 = USER R/W (0x0) - KEY_PURPOSE_2 (BLOCK0) Represents the purpose of Key2 = USER R/W (0x0) - KEY_PURPOSE_3 (BLOCK0) Represents the purpose of Key3 = USER R/W (0x0) - KEY_PURPOSE_4 (BLOCK0) Represents the purpose of Key4 = USER R/W (0x0) - KEY_PURPOSE_5 (BLOCK0) Represents the purpose of Key5 = USER R/W (0x0) - SEC_DPA_LEVEL (BLOCK0) Represents the spa secure level by configuring the = 0 R/W (0b00) - clock random divide mode - ECDSA_FORCE_USE_HARDWARE_K (BLOCK0) Represents whether hardware random number k is for = False R/W (0b0) - ced used in ESDCA. 1: force used. 0: not force use - d - CRYPT_DPA_ENABLE (BLOCK0) Represents whether anti-dpa attack is enabled. 1:e = False R/W (0b0) - nabled. 0: disabled - SECURE_BOOT_EN (BLOCK0) Represents whether secure boot is enabled or disab = False R/W (0b0) - led. 1: enabled. 0: disabled - SECURE_BOOT_AGGRESSIVE_REVOKE (BLOCK0) Represents whether revoking aggressive secure boot = False R/W (0b0) - is enabled or disabled. 1: enabled. 0: disabled - DIS_DOWNLOAD_MODE (BLOCK0) Represents whether Download mode is disabled or en = False R/W (0b0) - abled. 1: disabled. 0: enabled - ENABLE_SECURITY_DOWNLOAD (BLOCK0) Represents whether security download is enabled or = False R/W (0b0) - disabled. 1: enabled. 0: disabled - SECURE_VERSION (BLOCK0) Represents the version used by ESP-IDF anti-rollba = 0 R/W (0x0000) - ck feature - SECURE_BOOT_DISABLE_FAST_WAKE (BLOCK0) Represents whether FAST VERIFY ON WAKE is disabled = False R/W (0b0) - or enabled when Secure Boot is enabled. 1: disabl - ed. 0: enabled - BLOCK_KEY0 (BLOCK4) - Purpose: USER - 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) - Purpose: USER - 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) - Purpose: USER - 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) - Purpose: USER - 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) - Purpose: USER - 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) - Purpose: USER - 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 - - Usb fuses: - DIS_USB_JTAG (BLOCK0) Represents whether the function of usb switch to j = False R/W (0b0) - tag is disabled or enabled. 1: disabled. 0: enable - d - USB_EXCHG_PINS (BLOCK0) Represents whether the D+ and D- pins is exchanged = False R/W (0b0) - . 1: exchanged. 0: not exchanged - DIS_USB_SERIAL_JTAG_ROM_PRINT (BLOCK0) Set this bit to disable USB-Serial-JTAG print duri = False R/W (0b0) - ng rom boot - DIS_USB_SERIAL_JTAG_DOWNLOAD_MODE (BLOCK0) Represents whether the USB-Serial-JTAG download fu = False R/W (0b0) - nction is disabled or enabled. 1: disabled. 0: ena - bled - - Vdd fuses: - VDD_SPI_AS_GPIO (BLOCK0) Represents whether vdd spi pin is functioned as gp = False R/W (0b0) - io. 1: functioned. 0: not functioned - - Wdt fuses: - WDT_DELAY_SEL (BLOCK0) Represents whether RTC watchdog timeout threshold = 0 R/W (0b00) - is selected at startup. 1: selected. 0: not select - ed diff --git a/tools/esptool_py/docs/en/espefuse/inc/summary_ESP32-P4.rst b/tools/esptool_py/docs/en/espefuse/inc/summary_ESP32-P4.rst deleted file mode 100644 index e03d5f06ac..0000000000 --- a/tools/esptool_py/docs/en/espefuse/inc/summary_ESP32-P4.rst +++ /dev/null @@ -1,175 +0,0 @@ -.. code-block:: none - - > espefuse.py -p PORT summary - - Connecting.... - Detecting chip type... ESP32-P4 - - === Run "summary" command === - EFUSE_NAME (Block) Description = [Meaningful Value] [Readable/Writeable] (Hex Value) - ---------------------------------------------------------------------------------------- - Config fuses: - WR_DIS (BLOCK0) Disable programming of individual eFuses = 0 R/W (0x00000000) - RD_DIS (BLOCK0) Disable reading from BlOCK4-10 = 0 R/W (0b0000000) - POWERGLITCH_EN (BLOCK0) Represents whether power glitch function is enable = False R/W (0b0) - d. 1: enabled. 0: disabled - DIS_TWAI (BLOCK0) Represents whether TWAI function is disabled or en = False R/W (0b0) - abled. 1: disabled. 0: enabled - KM_HUK_GEN_STATE_LOW (BLOCK0) Set this bit to control validation of HUK generate = 0 R/W (0b000000) - mode. Odd of 1 is invalid; even of 1 is valid - KM_HUK_GEN_STATE_HIGH (BLOCK0) Set this bit to control validation of HUK generate = 0 R/W (0b000) - mode. Odd of 1 is invalid; even of 1 is valid - KM_RND_SWITCH_CYCLE (BLOCK0) Set bits to control key manager random number swit = 0 R/W (0b00) - ch cycle. 0: control by register. 1: 8 km clk cycl - es. 2: 16 km cycles. 3: 32 km cycles - KM_DEPLOY_ONLY_ONCE (BLOCK0) Set each bit to control whether corresponding key = 0 R/W (0x0) - can only be deployed once. 1 is true; 0 is false. - Bit0: ecdsa. Bit1: xts. Bit2: hmac. Bit3: ds - DIS_DIRECT_BOOT (BLOCK0) Represents whether direct boot mode is disabled or = False R/W (0b0) - enabled. 1: disabled. 0: enabled - UART_PRINT_CONTROL (BLOCK0) Represents the type of UART printing. 00: force en = 0 R/W (0b00) - able printing. 01: enable printing when GPIO8 is r - eset at low level. 10: enable printing when GPIO8 - is reset at high level. 11: force disable printing - HYS_EN_PAD (BLOCK0) Represents whether the hysteresis function of corr = False R/W (0b0) - esponding PAD is enabled. 1: enabled. 0:disabled - DCDC_VSET (BLOCK0) Set the dcdc voltage default = 0 R/W (0b00000) - PXA0_TIEH_SEL_0 (BLOCK0) TBD = 0 R/W (0b00) - PXA0_TIEH_SEL_1 (BLOCK0) TBD = 0 R/W (0b00) - PXA0_TIEH_SEL_2 (BLOCK0) TBD = 0 R/W (0b00) - PXA0_TIEH_SEL_3 (BLOCK0) TBD = 0 R/W (0b00) - KM_DISABLE_DEPLOY_MODE (BLOCK0) TBD = 0 R/W (0x0) - HP_PWR_SRC_SEL (BLOCK0) HP system power source select. 0:LDO. 1: DCDC = False R/W (0b0) - DCDC_VSET_EN (BLOCK0) Select dcdc vset use efuse_dcdc_vset = False R/W (0b0) - DIS_SWD (BLOCK0) Set this bit to disable super-watchdog = False R/W (0b0) - BLOCK_SYS_DATA1 (BLOCK2) System data part 1 - = 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_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 - BLOCK_SYS_DATA2 (BLOCK10) System data part 2 (reserved) - = 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 - - Flash fuses: - FLASH_TYPE (BLOCK0) The type of interfaced flash. 0: four data lines; = False R/W (0b0) - 1: eight data lines - FLASH_PAGE_SIZE (BLOCK0) Set flash page size = 0 R/W (0b00) - FLASH_ECC_EN (BLOCK0) Set this bit to enable ecc for flash boot = False R/W (0b0) - FLASH_TPUW (BLOCK0) Represents the flash waiting time after power-up; = 0 R/W (0x0) - in unit of ms. When the value less than 15; the wa - iting time is the programmed value. Otherwise; the - waiting time is 2 times the programmed value - FORCE_SEND_RESUME (BLOCK0) Represents whether ROM code is forced to send a re = False R/W (0b0) - sume command during SPI boot. 1: forced. 0:not for - ced - - Jtag fuses: - JTAG_SEL_ENABLE (BLOCK0) Represents whether the selection between usb_to_jt = False R/W (0b0) - ag and pad_to_jtag through strapping gpio15 when b - oth EFUSE_DIS_PAD_JTAG and EFUSE_DIS_USB_JTAG are - equal to 0 is enabled or disabled. 1: enabled. 0: - disabled - SOFT_DIS_JTAG (BLOCK0) Represents whether JTAG is disabled in soft way. O = 0 R/W (0b000) - dd number: disabled. Even number: enabled - DIS_PAD_JTAG (BLOCK0) Represents whether JTAG is disabled in the hard wa = False R/W (0b0) - y(permanently). 1: disabled. 0: enabled - - Mac fuses: - MAC (BLOCK1) MAC address - = 00:00:00:00:00:00 (OK) R/W - MAC_EXT (BLOCK1) Stores the extended bits of MAC address = 00:00 (OK) R/W - MAC_EUI64 (BLOCK1) calc MAC_EUI64 = MAC[0]:MAC[1]:MAC[2]:MAC_EXT[0]:M - = 00:00:00:00:00:00:00:00 (OK) R/W - AC_EXT[1]:MAC[3]:MAC[4]:MAC[5] - - Security fuses: - DIS_FORCE_DOWNLOAD (BLOCK0) Represents whether the function that forces chip i = False R/W (0b0) - nto download mode is disabled or enabled. 1: disab - led. 0: enabled - SPI_DOWNLOAD_MSPI_DIS (BLOCK0) Set this bit to disable accessing MSPI flash/MSPI = False R/W (0b0) - ram by SYS AXI matrix during boot_mode_download - DIS_DOWNLOAD_MANUAL_ENCRYPT (BLOCK0) Represents whether flash encrypt function is disab = False R/W (0b0) - led or enabled(except in SPI boot mode). 1: disabl - ed. 0: enabled - FORCE_USE_KEY_MANAGER_KEY (BLOCK0) Set each bit to control whether corresponding key = 0 R/W (0x0) - must come from key manager.. 1 is true; 0 is false - . Bit0: ecdsa. Bit1: xts. Bit2: hmac. Bit3: ds - FORCE_DISABLE_SW_INIT_KEY (BLOCK0) Set this bit to disable software written init key; = False R/W (0b0) - and force use efuse_init_key - XTS_KEY_LENGTH_256 (BLOCK0) Set this bit to configure flash encryption use xts = False R/W (0b0) - -128 key; else use xts-256 key - SPI_BOOT_CRYPT_CNT (BLOCK0) Enables flash encryption when 1 or 3 bits are set = Disable R/W (0b000) - and disables otherwise - SECURE_BOOT_KEY_REVOKE0 (BLOCK0) Revoke 1st secure boot key = False R/W (0b0) - SECURE_BOOT_KEY_REVOKE1 (BLOCK0) Revoke 2nd secure boot key = False R/W (0b0) - SECURE_BOOT_KEY_REVOKE2 (BLOCK0) Revoke 3rd secure boot key = False R/W (0b0) - KEY_PURPOSE_0 (BLOCK0) Represents the purpose of Key0 = USER R/W (0x0) - KEY_PURPOSE_1 (BLOCK0) Represents the purpose of Key1 = USER R/W (0x0) - KEY_PURPOSE_2 (BLOCK0) Represents the purpose of Key2 = USER R/W (0x0) - KEY_PURPOSE_3 (BLOCK0) Represents the purpose of Key3 = USER R/W (0x0) - KEY_PURPOSE_4 (BLOCK0) Represents the purpose of Key4 = USER R/W (0x0) - KEY_PURPOSE_5 (BLOCK0) Represents the purpose of Key5 = USER R/W (0x0) - SEC_DPA_LEVEL (BLOCK0) Represents the spa secure level by configuring the = 0 R/W (0b00) - clock random divide mode - ECDSA_ENABLE_SOFT_K (BLOCK0) Represents whether hardware random number k is for = False R/W (0b0) - ced used in ESDCA. 1: force used. 0: not force use - d - CRYPT_DPA_ENABLE (BLOCK0) Represents whether anti-dpa attack is enabled. 1:e = False R/W (0b0) - nabled. 0: disabled - SECURE_BOOT_EN (BLOCK0) Represents whether secure boot is enabled or disab = False R/W (0b0) - led. 1: enabled. 0: disabled - SECURE_BOOT_AGGRESSIVE_REVOKE (BLOCK0) Represents whether revoking aggressive secure boot = False R/W (0b0) - is enabled or disabled. 1: enabled. 0: disabled - DIS_DOWNLOAD_MODE (BLOCK0) Represents whether Download mode is disabled or en = False R/W (0b0) - abled. 1: disabled. 0: enabled - LOCK_KM_KEY (BLOCK0) TBD = False R/W (0b0) - ENABLE_SECURITY_DOWNLOAD (BLOCK0) Represents whether security download is enabled or = False R/W (0b0) - disabled. 1: enabled. 0: disabled - SECURE_VERSION (BLOCK0) Represents the version used by ESP-IDF anti-rollba = 0 R/W (0x0000) - ck feature - SECURE_BOOT_DISABLE_FAST_WAKE (BLOCK0) Represents whether FAST VERIFY ON WAKE is disabled = False R/W (0b0) - or enabled when Secure Boot is enabled. 1: disabl - ed. 0: enabled - BLOCK_KEY0 (BLOCK4) - Purpose: USER - 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) - Purpose: USER - 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) - Purpose: USER - 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) - Purpose: USER - 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) - Purpose: USER - 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) - Purpose: USER - 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 - - Usb fuses: - USB_DEVICE_EXCHG_PINS (BLOCK0) Enable usb device exchange pins of D+ and D- = False R/W (0b0) - USB_OTG11_EXCHG_PINS (BLOCK0) Enable usb otg11 exchange pins of D+ and D- = False R/W (0b0) - DIS_USB_JTAG (BLOCK0) Represents whether the function of usb switch to j = False R/W (0b0) - tag is disabled or enabled. 1: disabled. 0: enable - d - USB_PHY_SEL (BLOCK0) TBD = False R/W (0b0) - DIS_USB_OTG_DOWNLOAD_MODE (BLOCK0) Set this bit to disable download via USB-OTG = False R/W (0b0) - DIS_USB_SERIAL_JTAG_ROM_PRINT (BLOCK0) Represents whether print from USB-Serial-JTAG is d = False R/W (0b0) - isabled or enabled. 1: disabled. 0: enabled - DIS_USB_SERIAL_JTAG_DOWNLOAD_MODE (BLOCK0) Represents whether the USB-Serial-JTAG download fu = False R/W (0b0) - nction is disabled or enabled. 1: disabled. 0: ena - bled - - Wdt fuses: - WDT_DELAY_SEL (BLOCK0) Represents whether RTC watchdog timeout threshold = 0 R/W (0b00) - is selected at startup. 1: selected. 0: not select - ed - DIS_WDT (BLOCK0) Set this bit to disable watch dog = False R/W (0b0) diff --git a/tools/esptool_py/docs/en/espefuse/inc/summary_ESP32-S2.rst b/tools/esptool_py/docs/en/espefuse/inc/summary_ESP32-S2.rst deleted file mode 100644 index 8589c36207..0000000000 --- a/tools/esptool_py/docs/en/espefuse/inc/summary_ESP32-S2.rst +++ /dev/null @@ -1,172 +0,0 @@ -.. code-block:: none - - > espefuse.py -p PORT summary - - Connecting.... - Detecting chip type... ESP32-S2 - - === Run "summary" command === - EFUSE_NAME (Block) Description = [Meaningful Value] [Readable/Writeable] (Hex Value) - ---------------------------------------------------------------------------------------- - Calibration fuses: - ADC_CALIB (BLOCK2) 4 bit of ADC calibration = 0 R/W (0x0) - TEMP_CALIB (BLOCK2) Temperature calibration data = 3.2 R/W (0b000100000) - RTCCALIB_V1IDX_A10H (BLOCK2) = 55 R/W (0x37) - RTCCALIB_V1IDX_A11H (BLOCK2) = 51 R/W (0x33) - RTCCALIB_V1IDX_A12H (BLOCK2) = 52 R/W (0x34) - RTCCALIB_V1IDX_A13H (BLOCK2) = 53 R/W (0x35) - RTCCALIB_V1IDX_A20H (BLOCK2) = 56 R/W (0x38) - RTCCALIB_V1IDX_A21H (BLOCK2) = 55 R/W (0x37) - RTCCALIB_V1IDX_A22H (BLOCK2) = 55 R/W (0x37) - RTCCALIB_V1IDX_A23H (BLOCK2) = 59 R/W (0x3b) - RTCCALIB_V1IDX_A10L (BLOCK2) = 25 R/W (0b011001) - RTCCALIB_V1IDX_A11L (BLOCK2) = 17 R/W (0b010001) - RTCCALIB_V1IDX_A12L (BLOCK2) = 14 R/W (0b001110) - RTCCALIB_V1IDX_A13L (BLOCK2) = 7 R/W (0b000111) - RTCCALIB_V1IDX_A20L (BLOCK2) = 19 R/W (0b010011) - RTCCALIB_V1IDX_A21L (BLOCK2) = 14 R/W (0b001110) - RTCCALIB_V1IDX_A22L (BLOCK2) = 10 R/W (0b001010) - RTCCALIB_V1IDX_A23L (BLOCK2) = 6 R/W (0b000110) - - Config fuses: - WR_DIS (BLOCK0) Disable programming of individual eFuses = 0 R/W (0x00000000) - RD_DIS (BLOCK0) Disable reading from BlOCK4-10 = 0 R/W (0b0000000) - DIS_ICACHE (BLOCK0) Set this bit to disable Icache = False R/W (0b0) - DIS_DCACHE (BLOCK0) Set this bit to disable Dcache = False R/W (0b0) - DIS_TWAI (BLOCK0) Set this bit to disable the TWAI Controller functi = False R/W (0b0) - on - DIS_BOOT_REMAP (BLOCK0) Disables capability to Remap RAM to ROM address sp = False R/W (0b0) - ace - DIS_LEGACY_SPI_BOOT (BLOCK0) Set this bit to disable Legacy SPI boot mode = False R/W (0b0) - UART_PRINT_CHANNEL (BLOCK0) Selects the default UART for printing boot message = UART0 R/W (0b0) - s - UART_PRINT_CONTROL (BLOCK0) Set the default UART boot message output mode = Enable R/W (0b00) - PIN_POWER_SELECTION (BLOCK0) Set default power supply for GPIO33-GPIO37; set wh = VDD3P3_CPU R/W (0b0) - en SPI flash is initialized - 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 - BLOCK_SYS_DATA2 (BLOCK10) System data part 2 (reserved) - = 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 - - Flash fuses: - FLASH_TPUW (BLOCK0) Configures flash startup delay after SoC power-up; = 0 R/W (0x0) - in unit of (ms/2). When the value is 15; delay is - 7.5 ms - FLASH_TYPE (BLOCK0) SPI flash type = 4 data lines R/W (0b0) - FORCE_SEND_RESUME (BLOCK0) If set; forces ROM code to send an SPI flash resum = False R/W (0b0) - e command during SPI boot - FLASH_VERSION (BLOCK1) Flash version = 1 R/W (0x1) - - Identity fuses: - BLOCK0_VERSION (BLOCK0) BLOCK0 efuse version = 0 R/W (0b00) - DISABLE_WAFER_VERSION_MAJOR (BLOCK0) Disables check of wafer version major = False R/W (0b0) - DISABLE_BLK_VERSION_MAJOR (BLOCK0) Disables check of blk version major = False R/W (0b0) - WAFER_VERSION_MAJOR (BLOCK1) WAFER_VERSION_MAJOR = 0 R/W (0b00) - WAFER_VERSION_MINOR_HI (BLOCK1) WAFER_VERSION_MINOR most significant bit = False R/W (0b0) - BLK_VERSION_MAJOR (BLOCK1) BLK_VERSION_MAJOR = 0 R/W (0b00) - PSRAM_VERSION (BLOCK1) PSRAM version = 0 R/W (0x0) - PKG_VERSION (BLOCK1) Package version = 0 R/W (0x0) - WAFER_VERSION_MINOR_LO (BLOCK1) WAFER_VERSION_MINOR least significant bits = 0 R/W (0b000) - OPTIONAL_UNIQUE_ID (BLOCK2) Optional unique 128-bit ID - = d9 8f 05 d0 86 77 53 db 80 6c ee 40 df 5d ef b0 R/W - BLK_VERSION_MINOR (BLOCK2) BLK_VERSION_MINOR of BLOCK2 = ADC calib V1 R/W (0b001) - WAFER_VERSION_MINOR (BLOCK0) calc WAFER VERSION MINOR = WAFER_VERSION_MINOR_HI = 0 R/W (0x0) - << 3 + WAFER_VERSION_MINOR_LO (read only) - - Jtag 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) - - Mac fuses: - MAC (BLOCK1) MAC address - = 7c:df:a1:00:48:34 (OK) R/W - CUSTOM_MAC (BLOCK3) Custom MAC - = 00:00:00:00:00:00 (OK) R/W - - Security fuses: - 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) Set this bit to disable the function that forces c = False R/W (0b0) - hip into download mode - DIS_DOWNLOAD_MANUAL_ENCRYPT (BLOCK0) Disables flash encryption when in download boot mo = False R/W (0b0) - des - SPI_BOOT_CRYPT_CNT (BLOCK0) Enables flash encryption when 1 or 3 bits are set = Disable R/W (0b000) - and disabled otherwise - SECURE_BOOT_KEY_REVOKE0 (BLOCK0) Revoke 1st secure boot key = False R/W (0b0) - SECURE_BOOT_KEY_REVOKE1 (BLOCK0) Revoke 2nd secure boot key = False R/W (0b0) - SECURE_BOOT_KEY_REVOKE2 (BLOCK0) Revoke 3rd secure boot key = False R/W (0b0) - KEY_PURPOSE_0 (BLOCK0) Purpose of KEY0 = USER R/W (0x0) - KEY_PURPOSE_1 (BLOCK0) Purpose of KEY1 = USER R/W (0x0) - KEY_PURPOSE_2 (BLOCK0) Purpose of KEY2 = USER R/W (0x0) - KEY_PURPOSE_3 (BLOCK0) Purpose of KEY3 = USER R/W (0x0) - KEY_PURPOSE_4 (BLOCK0) Purpose of KEY4 = USER R/W (0x0) - KEY_PURPOSE_5 (BLOCK0) Purpose of KEY5 = USER R/W (0x0) - SECURE_BOOT_EN (BLOCK0) Set this bit to enable secure boot = False R/W (0b0) - SECURE_BOOT_AGGRESSIVE_REVOKE (BLOCK0) Set this bit to enable aggressive secure boot key = False R/W (0b0) - revocation mode - DIS_DOWNLOAD_MODE (BLOCK0) Set this bit to disable all download boot modes = False R/W (0b0) - ENABLE_SECURITY_DOWNLOAD (BLOCK0) Set this bit to enable secure UART download mode ( = False R/W (0b0) - read/write flash only) - SECURE_VERSION (BLOCK0) Secure version (used by ESP-IDF anti-rollback feat = 0 R/W (0x0000) - ure) - BLOCK_KEY0 (BLOCK4) - Purpose: USER - 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) - Purpose: USER - 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) - Purpose: USER - 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) - Purpose: USER - 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) - Purpose: USER - 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) - Purpose: USER - 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 - - Spi Pad fuses: - SPI_PAD_CONFIG_CLK (BLOCK1) SPI_PAD_configure CLK = 0 R/W (0b000000) - SPI_PAD_CONFIG_Q (BLOCK1) SPI_PAD_configure Q(D1) = 0 R/W (0b000000) - SPI_PAD_CONFIG_D (BLOCK1) SPI_PAD_configure D(D0) = 0 R/W (0b000000) - SPI_PAD_CONFIG_CS (BLOCK1) SPI_PAD_configure CS = 0 R/W (0b000000) - SPI_PAD_CONFIG_HD (BLOCK1) SPI_PAD_configure HD(D3) = 0 R/W (0b000000) - SPI_PAD_CONFIG_WP (BLOCK1) SPI_PAD_configure WP(D2) = 0 R/W (0b000000) - SPI_PAD_CONFIG_DQS (BLOCK1) SPI_PAD_configure DQS = 0 R/W (0b000000) - SPI_PAD_CONFIG_D4 (BLOCK1) SPI_PAD_configure D4 = 0 R/W (0b000000) - SPI_PAD_CONFIG_D5 (BLOCK1) SPI_PAD_configure D5 = 0 R/W (0b000000) - SPI_PAD_CONFIG_D6 (BLOCK1) SPI_PAD_configure D6 = 0 R/W (0b000000) - SPI_PAD_CONFIG_D7 (BLOCK1) SPI_PAD_configure D7 = 0 R/W (0b000000) - - Usb fuses: - DIS_USB (BLOCK0) Set this bit to disable USB OTG function = False R/W (0b0) - USB_EXCHG_PINS (BLOCK0) Set this bit to exchange USB D+ and D- pins = False R/W (0b0) - USB_EXT_PHY_ENABLE (BLOCK0) Set this bit to enable external USB PHY = False R/W (0b0) - USB_FORCE_NOPERSIST (BLOCK0) If set; forces USB BVALID to 1 = False R/W (0b0) - DIS_USB_DOWNLOAD_MODE (BLOCK0) Set this bit to disable use of USB OTG in UART dow = False R/W (0b0) - nload boot mode - - Vdd fuses: - VDD_SPI_XPD (BLOCK0) If VDD_SPI_FORCE is 1; this value determines if th = False R/W (0b0) - e VDD_SPI regulator is powered on - VDD_SPI_TIEH (BLOCK0) If VDD_SPI_FORCE is 1; determines VDD_SPI voltage - = VDD_SPI connects to 1.8 V LDO R/W (0b0) - VDD_SPI_FORCE (BLOCK0) Set this bit to use XPD_VDD_PSI_REG and VDD_SPI_TI = False R/W (0b0) - EH to configure VDD_SPI LDO - - Wdt fuses: - WDT_DELAY_SEL (BLOCK0) RTC watchdog timeout threshold; in unit of slow cl = 40000 R/W (0b00) - ock cycle - - 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/tools/esptool_py/docs/en/espefuse/inc/summary_ESP32-S3.rst b/tools/esptool_py/docs/en/espefuse/inc/summary_ESP32-S3.rst deleted file mode 100644 index dbd4b05859..0000000000 --- a/tools/esptool_py/docs/en/espefuse/inc/summary_ESP32-S3.rst +++ /dev/null @@ -1,163 +0,0 @@ -.. code-block:: none - - > espefuse.py -p PORT summary - - Connecting.... - Detecting chip type... ESP32-S3 - - === Run "summary" command === - EFUSE_NAME (Block) Description = [Meaningful Value] [Readable/Writeable] (Hex Value) - ---------------------------------------------------------------------------------------- - Config fuses: - WR_DIS (BLOCK0) Disable programming of individual eFuses = 0 R/W (0x00000000) - RD_DIS (BLOCK0) Disable reading from BlOCK4-10 = 0 R/W (0b0000000) - DIS_ICACHE (BLOCK0) Set this bit to disable Icache = False R/W (0b0) - DIS_DCACHE (BLOCK0) Set this bit to disable Dcache = False R/W (0b0) - DIS_TWAI (BLOCK0) Set this bit to disable CAN function = False R/W (0b0) - DIS_APP_CPU (BLOCK0) Disable app cpu = False R/W (0b0) - DIS_DIRECT_BOOT (BLOCK0) Disable direct boot mode = False R/W (0b0) - UART_PRINT_CONTROL (BLOCK0) Set the default UART boot message output mode = Enable R/W (0b00) - PIN_POWER_SELECTION (BLOCK0) Set default power supply for GPIO33-GPIO37; set wh = VDD3P3_CPU R/W (0b0) - en SPI flash is initialized - 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 - BLOCK_SYS_DATA2 (BLOCK10) System data part 2 (reserved) - = 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 - - Flash fuses: - FLASH_TPUW (BLOCK0) Configures flash waiting time after power-up; in u = 0 R/W (0x0) - nit of ms. If the value is less than 15; the waiti - ng time is the configurable value. Otherwise; the - waiting time is twice the configurable value - FLASH_ECC_MODE (BLOCK0) Flash ECC mode in ROM = 16to18 byte R/W (0b0) - FLASH_TYPE (BLOCK0) SPI flash type = 4 data lines R/W (0b0) - FLASH_PAGE_SIZE (BLOCK0) Set Flash page size = 0 R/W (0b00) - FLASH_ECC_EN (BLOCK0) Set 1 to enable ECC for flash boot = False R/W (0b0) - FORCE_SEND_RESUME (BLOCK0) Set this bit to force ROM code to send a resume co = False R/W (0b0) - mmand during SPI boot - - Identity fuses: - DISABLE_WAFER_VERSION_MAJOR (BLOCK0) Disables check of wafer version major = False R/W (0b0) - DISABLE_BLK_VERSION_MAJOR (BLOCK0) Disables check of blk version major = False R/W (0b0) - WAFER_VERSION_MINOR_LO (BLOCK1) WAFER_VERSION_MINOR least significant bits = 0 R/W (0b000) - PKG_VERSION (BLOCK1) Package version = 0 R/W (0b000) - BLK_VERSION_MINOR (BLOCK1) BLK_VERSION_MINOR = 0 R/W (0b000) - WAFER_VERSION_MINOR_HI (BLOCK1) WAFER_VERSION_MINOR most significant bit = False R/W (0b0) - WAFER_VERSION_MAJOR (BLOCK1) WAFER_VERSION_MAJOR = 0 R/W (0b00) - OPTIONAL_UNIQUE_ID (BLOCK2) 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) BLK_VERSION_MAJOR of BLOCK2 = No calib R/W (0b00) - WAFER_VERSION_MINOR (BLOCK0) calc WAFER VERSION MINOR = WAFER_VERSION_MINOR_HI = 0 R/W (0x0) - << 3 + WAFER_VERSION_MINOR_LO (read only) - - Jtag fuses: - SOFT_DIS_JTAG (BLOCK0) Set these bits to disable JTAG in the soft way (od = 0 R/W (0b000) - d number 1 means disable ). JTAG can be enabled in - HMAC module - DIS_PAD_JTAG (BLOCK0) Set this bit to disable JTAG in the hard way. JTAG = False R/W (0b0) - is disabled permanently - STRAP_JTAG_SEL (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 - - Mac fuses: - MAC (BLOCK1) MAC address - = 7c:df:a1:e0:00:58 (OK) R/W - CUSTOM_MAC (BLOCK3) Custom MAC - = 00:00:00:00:00:00 (OK) R/W - - Security fuses: - DIS_DOWNLOAD_ICACHE (BLOCK0) Set this bit to disable Icache in download mode (b = False R/W (0b0) - oot_mode[3:0] is 0; 1; 2; 3; 6; 7) - DIS_DOWNLOAD_DCACHE (BLOCK0) Set this bit to disable Dcache in download mode ( = False R/W (0b0) - boot_mode[3:0] is 0; 1; 2; 3; 6; 7) - DIS_FORCE_DOWNLOAD (BLOCK0) Set this bit to disable the function that forces c = False R/W (0b0) - hip into download mode - DIS_DOWNLOAD_MANUAL_ENCRYPT (BLOCK0) Set this bit to disable flash encryption when in d = False R/W (0b0) - ownload boot modes - SPI_BOOT_CRYPT_CNT (BLOCK0) Enables flash encryption when 1 or 3 bits are set = Disable R/W (0b000) - and disabled otherwise - SECURE_BOOT_KEY_REVOKE0 (BLOCK0) Revoke 1st secure boot key = False R/W (0b0) - SECURE_BOOT_KEY_REVOKE1 (BLOCK0) Revoke 2nd secure boot key = False R/W (0b0) - SECURE_BOOT_KEY_REVOKE2 (BLOCK0) Revoke 3rd secure boot key = False R/W (0b0) - KEY_PURPOSE_0 (BLOCK0) Purpose of Key0 = USER R/W (0x0) - KEY_PURPOSE_1 (BLOCK0) Purpose of Key1 = USER R/W (0x0) - KEY_PURPOSE_2 (BLOCK0) Purpose of Key2 = USER R/W (0x0) - KEY_PURPOSE_3 (BLOCK0) Purpose of Key3 = USER R/W (0x0) - KEY_PURPOSE_4 (BLOCK0) Purpose of Key4 = USER R/W (0x0) - KEY_PURPOSE_5 (BLOCK0) Purpose of Key5 = USER R/W (0x0) - SECURE_BOOT_EN (BLOCK0) Set this bit to enable secure boot = False R/W (0b0) - SECURE_BOOT_AGGRESSIVE_REVOKE (BLOCK0) Set this bit to enable revoking aggressive secure = False R/W (0b0) - boot - DIS_DOWNLOAD_MODE (BLOCK0) Set this bit to disable download mode (boot_mode[3 = False R/W (0b0) - :0] = 0; 1; 2; 3; 6; 7) - ENABLE_SECURITY_DOWNLOAD (BLOCK0) Set this bit to enable secure UART download mode = False R/W (0b0) - SECURE_VERSION (BLOCK0) Secure version (used by ESP-IDF anti-rollback feat = 0 R/W (0x0000) - ure) - BLOCK_KEY0 (BLOCK4) - Purpose: USER - 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) - Purpose: USER - 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) - Purpose: USER - 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) - Purpose: USER - 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) - Purpose: USER - 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) - Purpose: USER - 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 - - Spi Pad fuses: - SPI_PAD_CONFIG_CLK (BLOCK1) SPI_PAD_configure CLK = 0 R/W (0b000000) - SPI_PAD_CONFIG_Q (BLOCK1) SPI_PAD_configure Q(D1) = 0 R/W (0b000000) - SPI_PAD_CONFIG_D (BLOCK1) SPI_PAD_configure D(D0) = 0 R/W (0b000000) - SPI_PAD_CONFIG_CS (BLOCK1) SPI_PAD_configure CS = 0 R/W (0b000000) - SPI_PAD_CONFIG_HD (BLOCK1) SPI_PAD_configure HD(D3) = 0 R/W (0b000000) - SPI_PAD_CONFIG_WP (BLOCK1) SPI_PAD_configure WP(D2) = 0 R/W (0b000000) - SPI_PAD_CONFIG_DQS (BLOCK1) SPI_PAD_configure DQS = 0 R/W (0b000000) - SPI_PAD_CONFIG_D4 (BLOCK1) SPI_PAD_configure D4 = 0 R/W (0b000000) - SPI_PAD_CONFIG_D5 (BLOCK1) SPI_PAD_configure D5 = 0 R/W (0b000000) - SPI_PAD_CONFIG_D6 (BLOCK1) SPI_PAD_configure D6 = 0 R/W (0b000000) - SPI_PAD_CONFIG_D7 (BLOCK1) SPI_PAD_configure D7 = 0 R/W (0b000000) - - Usb fuses: - DIS_USB_OTG (BLOCK0) Set this bit to disable USB function = False R/W (0b0) - USB_EXCHG_PINS (BLOCK0) Set this bit to exchange USB D+ and D- pins = False R/W (0b0) - USB_EXT_PHY_ENABLE (BLOCK0) Set this bit to enable external PHY = False R/W (0b0) - DIS_USB_JTAG (BLOCK0) Set this bit to disable function of usb switch to = False R/W (0b0) - jtag in module of usb device - DIS_USB_SERIAL_JTAG (BLOCK0) Set this bit to disable usb device = False R/W (0b0) - USB_PHY_SEL (BLOCK0) This bit is used to switch internal PHY and extern - = internal PHY is assigned to USB Device while external PHY is assigned to USB OTG R/W (0b0) - al PHY for USB OTG and USB Device - DIS_USB_SERIAL_JTAG_ROM_PRINT (BLOCK0) USB printing = Enable R/W (0b0) - DIS_USB_SERIAL_JTAG_DOWNLOAD_MODE (BLOCK0) Set this bit to disable UART download mode through = False R/W (0b0) - USB - DIS_USB_OTG_DOWNLOAD_MODE (BLOCK0) Set this bit to disable download through USB-OTG = False R/W (0b0) - - Vdd fuses: - VDD_SPI_XPD (BLOCK0) SPI regulator power up signal = False R/W (0b0) - VDD_SPI_TIEH (BLOCK0) If VDD_SPI_FORCE is 1; determines VDD_SPI voltage - = VDD_SPI connects to 1.8 V LDO R/W (0b0) - VDD_SPI_FORCE (BLOCK0) Set this bit and force to use the configuration of = False R/W (0b0) - eFuse to configure VDD_SPI - - Wdt fuses: - WDT_DELAY_SEL (BLOCK0) RTC watchdog timeout threshold; in unit of slow cl = 40000 R/W (0b00) - ock cycle - - 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/tools/esptool_py/docs/en/espefuse/inc/summary_ESP32.rst b/tools/esptool_py/docs/en/espefuse/inc/summary_ESP32.rst deleted file mode 100644 index ff4d018f07..0000000000 --- a/tools/esptool_py/docs/en/espefuse/inc/summary_ESP32.rst +++ /dev/null @@ -1,90 +0,0 @@ -.. code-block:: none - - > espefuse.py -p PORT summary - - Connecting........__ - Detecting chip type... ESP32 - - === Run "summary" command === - EFUSE_NAME (Block) Description = [Meaningful Value] [Readable/Writeable] (Hex Value) - ---------------------------------------------------------------------------------------- - Calibration fuses: - ADC_VREF (BLOCK0): True ADC reference voltage = 1121 R/W (0b00011) - - Config fuses: - WR_DIS (BLOCK0): Efuse write disable mask = 0 R/W (0x0000) - RD_DIS (BLOCK0): Disable reading from BlOCK1-3 = 0 R/W (0x0) - DISABLE_APP_CPU (BLOCK0): Disables APP CPU = False R/W (0b0) - DISABLE_BT (BLOCK0): Disables Bluetooth = False R/W (0b0) - DIS_CACHE (BLOCK0): Disables cache = False R/W (0b0) - CHIP_CPU_FREQ_LOW (BLOCK0): If set alongside EFUSE_RD_CHIP_CPU_FREQ_RATED; the = False R/W (0b0) - ESP32's max CPU frequency is rated for 160MHz. 24 - 0MHz otherwise - CHIP_CPU_FREQ_RATED (BLOCK0): If set; the ESP32's maximum CPU frequency has been = True R/W (0b1) - rated - BLK3_PART_RESERVE (BLOCK0): BLOCK3 partially served for ADC calibration data = False R/W (0b0) - CLK8M_FREQ (BLOCK0): 8MHz clock freq override = 51 R/W (0x33) - VOL_LEVEL_HP_INV (BLOCK0): This field stores the voltage level for CPU to run = 0 R/W (0b00) - at 240 MHz; or for flash/PSRAM to run at 80 MHz.0 - x0: level 7; 0x1: level 6; 0x2: level 5; 0x3: leve - l 4. (RO) - CODING_SCHEME (BLOCK0): Efuse variable block length scheme - = NONE (BLK1-3 len=256 bits) R/W (0b00) - CONSOLE_DEBUG_DISABLE (BLOCK0): Disable ROM BASIC interpreter fallback = True R/W (0b1) - DISABLE_SDIO_HOST (BLOCK0): = False R/W (0b0) - DISABLE_DL_CACHE (BLOCK0): Disable flash cache in UART bootloader = False R/W (0b0) - - Flash fuses: - FLASH_CRYPT_CNT (BLOCK0): Flash encryption is enabled if this field has an o = 0 R/W (0b0000000) - dd number of bits set - FLASH_CRYPT_CONFIG (BLOCK0): Flash encryption config (key tweak bits) = 0 R/W (0x0) - - Identity fuses: - CHIP_PACKAGE_4BIT (BLOCK0): Chip package identifier #4bit = False R/W (0b0) - CHIP_PACKAGE (BLOCK0): Chip package identifier = 1 R/W (0b001) - CHIP_VER_REV1 (BLOCK0): bit is set to 1 for rev1 silicon = True R/W (0b1) - CHIP_VER_REV2 (BLOCK0): = True R/W (0b1) - WAFER_VERSION_MINOR (BLOCK0): = 0 R/W (0b00) - WAFER_VERSION_MAJOR (BLOCK0): calc WAFER VERSION MAJOR from CHIP_VER_REV1 and CH = 3 R/W (0b011) - IP_VER_REV2 and apb_ctl_date (read only) - PKG_VERSION (BLOCK0): calc Chip package = CHIP_PACKAGE_4BIT << 3 + CHIP_ = 1 R/W (0x1) - PACKAGE (read only) - - Jtag fuses: - JTAG_DISABLE (BLOCK0): Disable JTAG = False R/W (0b0) - - Mac fuses: - MAC (BLOCK0): MAC address - = 94:b9:7e:5a:6e:58 (CRC 0xe2 OK) R/W - MAC_CRC (BLOCK0): CRC8 for MAC address = 226 R/W (0xe2) - MAC_VERSION (BLOCK3): Version of the MAC field = 0 R/W (0x00) - - Security fuses: - UART_DOWNLOAD_DIS (BLOCK0): Disable UART download mode. Valid for ESP32 V3 and = False R/W (0b0) - newer; only - 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) - 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) - KEY_STATUS (BLOCK0): Usage of efuse block 3 (reserved) = False R/W (0b0) - SECURE_VERSION (BLOCK3): Secure version for anti-rollback = 0 R/W (0x00000000) - 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 00 00 00 00 00 00 00 00 R/W - BLOCK2 (BLOCK2): Security 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 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 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 R/W - - Spi Pad fuses: - SPI_PAD_CONFIG_HD (BLOCK0): read for SPI_pad_config_hd = 0 R/W (0b00000) - 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_CS0 (BLOCK0): Override SD_CMD pad (GPIO11/SPICS0) = 0 R/W (0b00000) - - Vdd fuses: - XPD_SDIO_REG (BLOCK0): read for XPD_SDIO_REG = False R/W (0b0) - XPD_SDIO_TIEH (BLOCK0): If XPD_SDIO_FORCE & XPD_SDIO_REG = 1.8V R/W (0b0) - XPD_SDIO_FORCE (BLOCK0): Ignore MTDI pin (GPIO12) for VDD_SDIO on reset = False R/W (0b0) - - Flash voltage (VDD_SDIO) determined by GPIO12 on reset (High for 1.8V, Low/NC for 3.3V) diff --git a/tools/esptool_py/docs/en/espefuse/index.rst b/tools/esptool_py/docs/en/espefuse/index.rst deleted file mode 100644 index 26e19cb496..0000000000 --- a/tools/esptool_py/docs/en/espefuse/index.rst +++ /dev/null @@ -1,177 +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. -- ``--extend-efuse-table`` - CSV file from `ESP-IDF `_ (esp_efuse_custom_table.csv). - -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 is always None. - * ``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 - -Extend Efuse Table ------------------- - -This tool supports the use of `CSV files `_ from the `ESP-IDF `_ (e.g., ``esp_efuse_custom_table.csv``) to add custom eFuse fields. You can use this argument with any supported commands to access these custom eFuses. - -.. code-block:: none - - > espefuse.py -c esp32 --extend-efuse-table path/esp_efuse_custom_table.csv summary - -Below is an example of an ``esp_efuse_custom_table.csv`` file. This example demonstrates how to define single eFuse fields, ``structured eFuse fields`` and ``non-sequential bit fields``: - -.. code-block:: none - - MODULE_VERSION, EFUSE_BLK3, 56, 8, Module version - DEVICE_ROLE, EFUSE_BLK3, 64, 3, Device role - SETTING_1, EFUSE_BLK3, 67, 6, [SETTING_1_ALT_NAME] Setting 1 - SETTING_2, EFUSE_BLK3, 73, 5, Setting 2 - ID_NUM, EFUSE_BLK3, 140, 8, [MY_ID_NUM] comment - , EFUSE_BLK3, 132, 8, [MY_ID_NUM] comment - , EFUSE_BLK3, 122, 8, [MY_ID_NUM] comment - CUSTOM_SECURE_VERSION, EFUSE_BLK3, 78, 16, Custom secure version - ID_NUMK, EFUSE_BLK3, 150, 8, [MY_ID_NUMK] comment - , EFUSE_BLK3, 182, 8, [MY_ID_NUMK] comment - MY_DATA, EFUSE_BLK3, 190, 10, My data - MY_DATA.FIELD1, EFUSE_BLK3, 190, 7, Field1 - -When you include this CSV file, the tool will generate a new section in the summary called ``User fuses``. - -.. code-block:: none - - User fuses: - MODULE_VERSION (BLOCK3) Module version (56-63) = 0 R/W (0x00) - DEVICE_ROLE (BLOCK3) Device role (64-66) = 0 R/W (0b000) - SETTING_1 (BLOCK3) [SETTING_1_ALT_NAME] Setting 1 (67-72) = 0 R/W (0b000000) - SETTING_2 (BLOCK3) Setting 2 (73-77) = 0 R/W (0b00000) - ID_NUM_0 (BLOCK3) [MY_ID_NUM] comment (140-147) = 0 R/W (0x00) - ID_NUM_1 (BLOCK3) [MY_ID_NUM] comment (132-139) = 0 R/W (0x00) - ID_NUM_2 (BLOCK3) [MY_ID_NUM] comment (122-129) = 0 R/W (0x00) - CUSTOM_SECURE_VERSION (BLOCK3) Custom secure version (78-93) = 0 R/W (0x0000) - ID_NUMK_0 (BLOCK3) [MY_ID_NUMK] comment (150-157) = 0 R/W (0x00) - ID_NUMK_1 (BLOCK3) [MY_ID_NUMK] comment (182-189) = 0 R/W (0x00) - MY_DATA (BLOCK3) My data (190-199) = 0 R/W (0b0000000000) - MY_DATA_FIELD1 (BLOCK3) Field1 (190-196) = 0 R/W (0b0000000) - -You can reference these fields using the names and aliases provided in the CSV file. For non-sequential bits, the names are modified slightly with the addition of _0 and _1 postfixes for every sub-field, to ensure safer handling. - -For the current example, you can reference the custom fields with the following names: MODULE_VERSION, DEVICE_ROLE, SETTING_1, SETTING_2, ID_NUM_0, ID_NUM_1, ID_NUM_2, CUSTOM_SECURE_VERSION, ID_NUMK_0, ID_NUMK_1, MY_DATA, MY_DATA_FIELD1; and alises: SETTING_1_ALT_NAME, MY_ID_NUM_0, MY_ID_NUM_1, MY_ID_NUM_2, MY_ID_NUMK_0, MY_ID_NUMK_1. - -For convenience, the espefuse summary command includes the used bit range of the field in a comment, such as ``(150-157)`` len = 8 bits. - -For more details on the structure and usage of the CSV file, refer to the `eFuse Manager `_ chapter in the ESP-IDF documentation. - -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/tools/esptool_py/docs/en/espefuse/read-write-protections-cmd.rst b/tools/esptool_py/docs/en/espefuse/read-write-protections-cmd.rst deleted file mode 100644 index e1611e538b..0000000000 --- a/tools/esptool_py/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 receive 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/tools/esptool_py/docs/en/espefuse/set-flash-voltage-cmd.rst b/tools/esptool_py/docs/en/espefuse/set-flash-voltage-cmd.rst deleted file mode 100644 index 6340858cae..0000000000 --- a/tools/esptool_py/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:: not esp32 and not esp32s2 and not esp32s3 - - .. 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/tools/esptool_py/docs/en/espefuse/summary-cmd.rst b/tools/esptool_py/docs/en/espefuse/summary-cmd.rst deleted file mode 100644 index 195083ebdd..0000000000 --- a/tools/esptool_py/docs/en/espefuse/summary-cmd.rst +++ /dev/null @@ -1,146 +0,0 @@ -.. _summary-cmd: - -Summary -======= - -The ``espefuse.py summary`` command reads the eFuses from the chip and outputs them in text or json format. It is also possible to save it to a file. The command also supports eFuse filtering by name. - -Optional arguments: - -- ``--format`` - Select the summary format: - - ``summary`` - text format (default option). - - ``json`` - json format. Usage ``--format json``. - - ``value_only`` - only the value of the eFuse specified as an argument will be displayed. For more information, refer to the :ref:`Filtering eFuses ` section. -- ``--file`` - File to save the efuse summary. Usage ``--file efuses.json``. -- List of eFuses to filter. For more information, refer to the :ref:`Filtering eFuses ` section. - -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 - -.. _filtering-eFuses: - -Filtering Efuses and Displaying Only the Value ----------------------------------------------- - -The ``espefuse.py summary`` command supports filtering eFuses by name. The eFuses to filter needs to be specified as positional arguments. If no eFuses are specified, complete summary will be displayed. Example: - -.. code-block:: none - - > espefuse.py summary ABS_DONE_0 BLOCK1 - - === Run "summary" command === - EFUSE_NAME (Block) Description = [Meaningful Value] [Readable/Writeable] (Hex Value) - ---------------------------------------------------------------------------------------- - Security fuses: - ABS_DONE_0 (BLOCK0) Secure boot V1 is enabled for bootloader image = 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 00 00 00 00 00 00 00 00 R/W - -If ``--format value_only`` is specified, only the value of the eFuse specified as an argument will be displayed. Only one eFuse can be specified as an argument for this format. Example: - -.. code-block:: none - - > espefuse.py summary --format value_only MAC - - === Run "summary" command === - 00:00:00:00:00:00 (CRC 0x00 OK) diff --git a/tools/esptool_py/docs/en/espsecure/index.rst b/tools/esptool_py/docs/en/espsecure/index.rst deleted file mode 100644 index c03b3478e1..0000000000 --- a/tools/esptool_py/docs/en/espsecure/index.rst +++ /dev/null @@ -1,80 +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``. - -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 - -.. note:: - In case you are using ESP-IDF, then an unsigned application can be generated by disabling ``CONFIG_SECURE_BOOT_BUILD_SIGNED_BINARIES`` configuration option in the project settings. - -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. - -To access an HSM token of a selected slot, you will also need to pass in the token User PIN and thus you will be prompted to type in the User PIN. -Alternatively, you could also add a ``credentials`` field in the HSM config file to store the (plaintext) User PIN to automate the signing workflow. - -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/tools/esptool_py/docs/en/esptool/advanced-commands.rst b/tools/esptool_py/docs/en/esptool/advanced-commands.rst deleted file mode 100644 index 905739ba27..0000000000 --- a/tools/esptool_py/docs/en/esptool/advanced-commands.rst +++ /dev/null @@ -1,172 +0,0 @@ -{IDF_TARGET_BOOTLOADER_OFFSET:default="0x0", esp32="0x1000", esp32s2="0x1000", esp32p4="0x2000"} - -.. _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. Command also supports ``.hex`` file created by ``merge_bin`` command from supported ``.bin`` files. - -:: - - 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 commands. 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! - -.. _read-flash-sfdp: - -Read Serial Flash Discoverable Parameters (SFDP) ------------------------------------------------- - -The Serial Flash Discoverable Parameters (SFDP) store essential vendor-specific configuration data of the flash memory chip. These parameters help identify and interact with different flash devices. Usage: - -:: - esptool.py read_flash_sfdp 16 4 - -This will read 4 bytes from SFDP address 16. - -.. 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/tools/esptool_py/docs/en/esptool/advanced-options.rst b/tools/esptool_py/docs/en/esptool/advanced-options.rst deleted file mode 100644 index db47b8aa04..0000000000 --- a/tools/esptool_py/docs/en/esptool/advanced-options.rst +++ /dev/null @@ -1,158 +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 or esp32c6 or esp32h2 or esp32p4: * ``--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. - - -Connect Loop ------------- - -Esptool supports connection loops, where the user can specify how many times to try to open a port. The delay between retries is 0.1 seconds. This can be useful for example when the chip is in deep sleep or esptool was started before the chip was connected to the PC. A connection loop can be created by setting the ``ESPTOOL_OPEN_PORT_ATTEMPTS`` environment variable. -This feature can also be enabled by using the ``open_port_attempts`` configuration option, for more details regarding config options see :ref:`Configuration file ` section. -There are 3 possible values for this option: - -.. list:: - - * ``0`` will keep trying to connect to the chip indefinitely - * ``1`` will try to connect to the chip only once (default) - * ``N`` will try to connect to the chip N times - - -.. note:: - - This option is only available if both the ``--port`` and ``--chip`` arguments are set. - - - -.. _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:: not esp8266 - - 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. - - .. only:: esp32 - - 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. - - .. only:: esp32 - - 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. - - .. note:: - - Some GPIO pins might be shared with other peripherals. Therefore, some SPI pad pin configurations might not work reliably or at all. Use a different combination of pins if you encounter issues. - -Specifying Arguments via File ------------------------------ -.. _specify_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. - -.. note:: PowerShell users - - Because of `splatting `__ in PowerShell (method of passing a collection of parameter values to a command as a unit) there is a need to add quotes around @filename.txt ("@filename.txt") to be correctly resolved. - -Filtering serial ports ----------------------- -.. _filtering_serial_ports: - -``--port-filter =`` allows limiting ports that will be tried. This can be useful when esptool is run on a system -with many serial ports. There are a few different types that can be combined. A port must match all specified FilterTypes, and must match -at least one FilterValue for each specified FilterType to be considered. Example filter configurations: - -.. list:: - - * ``--port-filter vid=0x303A`` matches ports with the Espressif USB VID. - * ``--port-filter vid=0x303A --port-filter vid=0x0403`` matches Espressif and FTDI ports by VID. - * ``--port-filter vid=0x303A --port-filter pid=0x0002`` matches Espressif ESP32-S2 in USB-OTG mode by VID and PID. - * ``--port-filter vid=0x303A --port-filter pid=0x1001`` matches Espressif USB-Serial/JTAG unit used by multiple chips by VID and PID. - * ``--port-filter name=ttyUSB`` matches ports where the port name contains the specified text. - -See also the `Espressif USB customer-allocated PID repository `_ diff --git a/tools/esptool_py/docs/en/esptool/basic-commands.rst b/tools/esptool_py/docs/en/esptool/basic-commands.rst deleted file mode 100644 index 8e16df7b42..0000000000 --- a/tools/esptool_py/docs/en/esptool/basic-commands.rst +++ /dev/null @@ -1,344 +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 - - -It is also possible to autodetect flash size by using ``ALL`` as size. The above example with autodetection would look like this: - -:: - - esptool.py -p PORT -b 460800 read_flash 0 ALL flash_contents.bin - - -.. note:: - - When using the ``read_flash`` command in combination with the ``--no-stub`` argument, it may be necessary to also set the ``--flash_size`` argument to ensure proper reading of the flash contents by the ROM. - - -.. 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. Overwriting these values via the ``write_flash`` command will produce an image with a recalculated SHA256 digest, otherwise, the image SHA256 digest would be invalidated by rewriting the image header. There is an option to skip appending a SHA256 digest after the image with ``--dont-append-digest`` argument of the ``elf2image`` command. - -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``. - - The ``--ram-only-header`` configuration is mainly applicable for use within the Espressif's SIMPLE_BOOT option from 3rd party OSes such as ZephyrOS and NuttX OS. - This option makes only the RAM segments visible to the ROM bootloader placing them at the beginning of the file and altering the segment count from the image header with the quantity of these segments, and also writing only their checksum. This segment placement may result in a more fragmented binary because of flash alignment constraints. - It is strongly recommended to use this configuration with care, because the image built must then handle the basic hardware initialization and the flash mapping for code execution after ROM bootloader boot it. - -.. _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``. Command also supports ``.hex`` file created by ``merge_bin`` command from supported ``.bin`` files. - -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 the given binary file is an application and a valid `ESP-IDF application header `__ is detected in the image, specific fields describing the application are also displayed. - - If the given binary file is a bootloader and a valid `ESP-IDF bootloader header `__ is detected in the image, specific fields describing the bootloader 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 based on the selected output format. - -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 written to flash with ``esptool.py write_flash 0x0 merged-flash.bin``. - - -**Common 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 ``--format`` option will change the format of the output file. For more information about formats see formats description below. -* The input files can be in either ``bin`` or ``hex`` format and they will be automatically converted to type selected by ``--format`` argument. -* It is possible to append options from a text file with ``@filename`` (see the advanced options page :ref:`Specifying Arguments via File ` section for details). 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 - - -HEX Output Format -^^^^^^^^^^^^^^^^^ - -The output of the command will be in `Intel Hex format `__. The gaps between the files won't be padded. - -Intel Hex format offers distinct advantages when compared to the binary format, primarily in the following areas: - -* **Transport**: Intel Hex files are represented in ASCII text format, significantly increasing the likelihood of flawless transfers across various mediums. -* **Size**: Data is carefully allocated to specific memory addresses eliminating the need for unnecessary padding. Binary images often lack detailed addressing information, leading to the inclusion of data for all memory locations from the file's initial address to its end. -* **Validity Checks**: Each line in an Intel Hex file has a checksum to help find errors and make sure data stays unchanged. - -.. code:: sh - - esptool.py --chip {IDF_TARGET_NAME} merge_bin --format hex -o merged-flash.hex --flash_mode dio --flash_size 4MB 0x1000 bootloader.bin 0x8000 partition-table.bin 0x10000 app.bin - -.. note:: - - Please note that during the conversion to the `Intel Hex` format, the binary input file is treated as a black box. The conversion process does not consider the actual contents of the binary file. This means that the `Intel Hex` file will contain the same data as the binary file (including the padding), but the data will be represented in a different format. - When merging multiple files, the `Intel Hex` format, unlike the binary format, does not include any padding between the input files. - It is recommended to merge multiple files instead of converting one already merged to get smaller merged outputs. - -RAW Output Format -^^^^^^^^^^^^^^^^^ - -The output of the command will be in ``raw`` format and gaps between individual files will be filled with `0xFF` bytes (same as unwritten flash contents). - -.. 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. - - -**RAW options:** - -* 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. -* The ``--target-offset 0xNNN`` option will create a merged binary that should be flashed at the specified offset, instead of at offset 0x0. - - -UF2 Output Format -^^^^^^^^^^^^^^^^^ - -This command will generate a UF2 (`USB Flashing Format `_) binary. -This UF2 file can be copied to a USB mass storage device exposed by another ESP running the `ESP USB Bridge `_ project. The bridge MCU will use it to flash the target MCU. This is as simple copying (or "drag-and-dropping") the file to the exposed disk accessed by a file explorer in your machine. - -Gaps between the files will be filled with `0x00` bytes. - -**UF2 options:** - -* The ``--chunk-size`` option will set what portion of 512 byte block will be used for data. A common value is 256 bytes. By default, the largest possible value will be used. -* The ``--md5-disable`` option will disable MD5 checksums at the end of each block. This can be useful for integration with e.g. `tinyuf2 `__. - -.. code:: sh - - esptool.py --chip {IDF_TARGET_NAME} merge_bin --format uf2 -o merged-flash.uf2 --flash_mode dio --flash_size 4MB 0x1000 bootloader.bin 0x8000 partition-table.bin 0x10000 app.bin - - -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` - * :ref:`read-flash-sfdp` - :esp8266: * :ref:`chip-id` - :esp8266: * :ref:`make-image` - :esp8266: * :ref:`run` diff --git a/tools/esptool_py/docs/en/esptool/basic-options.rst b/tools/esptool_py/docs/en/esptool/basic-options.rst deleted file mode 100644 index 5d9bb4c468..0000000000 --- a/tools/esptool_py/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/tools/esptool_py/docs/en/esptool/configuration-file.rst b/tools/esptool_py/docs/en/esptool/configuration-file.rst deleted file mode 100644 index 1583f86d17..0000000000 --- a/tools/esptool_py/docs/en/esptool/configuration-file.rst +++ /dev/null @@ -1,150 +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 of 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 | -+------------------------------+-----------------------------------------------------------+----------+ -| open_port_attempts | Number of attempts to open the port (0 - infinite) | 1 | -+------------------------------+-----------------------------------------------------------+----------+ -| 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/tools/esptool_py/docs/en/esptool/entering-bootloader.rst b/tools/esptool_py/docs/en/esptool/entering-bootloader.rst deleted file mode 100644 index 4e5a95837a..0000000000 --- a/tools/esptool_py/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/tools/esptool_py/docs/en/esptool/flash-modes.rst b/tools/esptool_py/docs/en/esptool/flash-modes.rst deleted file mode 100644 index b9d18686d0..0000000000 --- a/tools/esptool_py/docs/en/esptool/flash-modes.rst +++ /dev/null @@ -1,120 +0,0 @@ -{IDF_TARGET_BOOTLOADER_OFFSET:default="0x0", esp32="0x1000", esp32s2="0x1000", esp32p4="0x2000"} - -{IDF_TARGET_FLASH_FREQ_F:default="80", esp32c2="60", esp32h2="48"} - -{IDF_TARGET_FLASH_FREQ_0:default="40", esp32c2="30", esp32h2="24"} - -{IDF_TARGET_FLASH_FREQ:default="``40m``, ``26m``, ``20m``, ``80m``", esp32c2="``30m``, ``20m``, ``15m``, ``60m``", esp32h2="``24m``, ``16m``, ``12m``, ``48m``", esp32c6="``40m``, ``20m``, ``80m``"} - - -.. _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``, {IDF_TARGET_FLASH_FREQ} (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 {IDF_TARGET_FLASH_FREQ_0}MHz clock speeds, but you can try lower values if the device won't boot. The highest {IDF_TARGET_FLASH_FREQ_F}MHz 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 or esp32c6 or esp32c2 or esp32h2 - - Valid values are: ``keep``, ``detect``, ``1MB``, ``2MB``, ``4MB``, ``8MB``, ``16MB`` - -.. only:: esp32s2 or esp32s3 or esp32p4 - - Valid values are: ``keep``, ``detect``, ``1MB``, ``2MB``, ``4MB``, ``8MB``, ``16MB``, ``32MB``, ``64MB``, ``128MB`` - -.. 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/tools/esptool_py/docs/en/esptool/flasher-stub.rst b/tools/esptool_py/docs/en/esptool/flasher-stub.rst deleted file mode 100644 index c2f179be7c..0000000000 --- a/tools/esptool_py/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/tools/esptool_py/docs/en/esptool/flashing-firmware.rst b/tools/esptool_py/docs/en/esptool/flashing-firmware.rst deleted file mode 100644 index 78a6c575d0..0000000000 --- a/tools/esptool_py/docs/en/esptool/flashing-firmware.rst +++ /dev/null @@ -1,107 +0,0 @@ -{IDF_TARGET_BOOTLOADER_OFFSET:default="0x0", esp32="0x1000", esp32s2="0x1000", esp32p4="0x2000"} - -.. _flashing: - -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 devices 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, for example:: - - Project build complete. To flash, run this command: - python esptool.py -p (PORT) -b 460800 --before default_reset --after hard_reset --chip {IDF_TARGET_PATH_NAME} write_flash --flash_mode dio --flash_size detect --flash_freq 40m {IDF_TARGET_BOOTLOADER_OFFSET} 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, you will see something like: - -:: - - “.../.platformio/penv/bin/python2.7” “.../.platformio/packages/tool-esptoolpy/esptool.py” --chip {IDF_TARGET_PATH_NAME} --port “/dev/cu.usbserial001” --baud 921600 --before default_reset --after hard_reset write_flash -z --flash_mode dio --flash_freq 40m --flash_size detect {IDF_TARGET_BOOTLOADER_OFFSET} .../.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 {IDF_TARGET_PATH_NAME} write_flash --flash_mode dio --flash_size detect --flash_freq 40m {IDF_TARGET_BOOTLOADER_OFFSET} 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/tools/esptool_py/docs/en/esptool/index.rst b/tools/esptool_py/docs/en/esptool/index.rst deleted file mode 100644 index 495896fb99..0000000000 --- a/tools/esptool_py/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/tools/esptool_py/docs/en/esptool/remote-serial-ports.rst b/tools/esptool_py/docs/en/esptool/remote-serial-ports.rst deleted file mode 100644 index 5863516f03..0000000000 --- a/tools/esptool_py/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, to read information about your chip's SPI flash, run: - -:: - - 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/tools/esptool_py/docs/en/esptool/scripting.rst b/tools/esptool_py/docs/en/esptool/scripting.rst deleted file mode 100644 index e4e96608d2..0000000000 --- a/tools/esptool_py/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/tools/esptool_py/docs/en/esptool/serial-connection.rst b/tools/esptool_py/docs/en/esptool/serial-connection.rst deleted file mode 100644 index 32eed2754b..0000000000 --- a/tools/esptool_py/docs/en/esptool/serial-connection.rst +++ /dev/null @@ -1,53 +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:: esp32c2 - - .. note:: - - You might experience issues when using low baud rates on {IDF_TARGET_NAME}. If you encounter any problems when connecting, please use at least 115200 or higher. - -.. 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/tools/esptool_py/docs/en/index.rst b/tools/esptool_py/docs/en/index.rst deleted file mode 100644 index 201b71bf14..0000000000 --- a/tools/esptool_py/docs/en/index.rst +++ /dev/null @@ -1,55 +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. For example, to read information about your chip's SPI flash, run: - - :: - - $ 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 - Resources - About diff --git a/tools/esptool_py/docs/en/installation.rst b/tools/esptool_py/docs/en/installation.rst deleted file mode 100644 index 9e201d9d37..0000000000 --- a/tools/esptool_py/docs/en/installation.rst +++ /dev/null @@ -1,108 +0,0 @@ -Installation and Dependencies -============================= - -.. _installation: - -How to Install --------------- - -Global Installation -^^^^^^^^^^^^^^^^^^^ - -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. - -Virtual Environment Installation -^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - -To ensure that ``esptool.py`` is used in isolation, and any changes made during its usage won't affect other Python environments or SDK installations, it is advised to install it in a virtual environment and use it directly if possible (more information in the :ref:`flashing` article). - -Creating a virtual environment (venv) is a good practice. This is particularly helpful for users who may be concerned about interfering with existing installations (e.g. in an environment of a development-setup framework). Here's a quick guide: - -- Create a virtual environment and choose its name, e.g. 'esptoolenv': ``python -m venv esptoolenv`` -- Activate the virtual environment: - - - On Windows: ``esptoolenv\Scripts\activate`` - - On Linux or MacOS: ``source esptoolenv/bin/activate`` - -- Install the latest ``esptool.py`` version within the active virtual environment: ``pip install esptool`` -- You can now use it within this virtual environment without affecting your system-wide installations: ``esptool.py `` -- When you're done using ``esptool.py``, deactivate the virtual environment: ``deactivate``. The environment can be reused by activating it again. -- If you no longer need the virtual environment, you can remove it by deleting the ``esptoolenv`` directory. - -How to Update -------------- - -Standalone -^^^^^^^^^^ - -If you are using ``esptool.py`` as a standalone tool (as a global installation or in a virtual environment), updating to the latest version released on the `PyPI `_ index is simple: - -:: - - $ pip install --upgrade esptool - -As a Component -^^^^^^^^^^^^^^ - -If ``esptool.py`` is installed as a component of a development framework (e.g. `ESP-IDF `_, `Arduino `_, or `PlatformIO `_), it is advised to follow the update guide of used framework for instructions and not to update the tool directly. - -If updating directly is unavoidable, make sure you update to a compatible version by staying on the same MAJOR version number (explained in the :ref:`versions` article). For instance, if your currently installed ``esptool.py`` is ``v3.3.1``, only update to ``v3.*.*``. You risk introducing incompatible changes by updating to ``v4.*.*`` or higher. - -:: - - $ pip install esptool==3.3.2 - -Shell completions ------------------ - -To activate autocompletion, you can manually add commands provided below to your shell's config file -or run them in your current terminal session for one-time activation. -You will likely have to restart or re-login for the autocompletion to start working. - -bash: -:: - - eval "$(register-python-argcomplete esptool.py espsecure.py espefuse.py)" - -zsh: - -To activate completions in zsh, first make sure `compinit` is marked for -autoload and run autoload: - -.. code-block:: bash - - autoload -U compinit - compinit - -Afterwards you can enable completions for esptool.py, espsecure.py and espefuse.py: - -:: - - eval "$(register-python-argcomplete esptool.py espsecure.py espefuse.py)" - -fish: - -Not required to be in the config file, only run once - -:: - - register-python-argcomplete --shell fish esptool.py espsecure.py espefuse.py >~/.config/fish/completions/esptool.py.fish - -Other shells nor OS Windows are not supported. diff --git a/tools/esptool_py/docs/en/resources.rst b/tools/esptool_py/docs/en/resources.rst deleted file mode 100644 index 13add7041e..0000000000 --- a/tools/esptool_py/docs/en/resources.rst +++ /dev/null @@ -1,40 +0,0 @@ -.. _resources: - -Resources -========= - - -Useful Links -------------- - -* The `esp32.com forum `_ is a place to ask questions and find community resources. - -* Check the `Issues `_ section on GitHub if you find a bug or have a feature request. Please check existing `issues `_ before opening a new one. - -* Several `books `_ have been written about the ESP8266 or ESP32 series of SoCs and they are listed on `Espressif `__ web site. - -* If you're interested in contributing to esptool.py, please check the :ref:`contribute` page. - -* For additional {IDF_TARGET_NAME} product related information, please refer to the `documentation `_ section of `Espressif `__ web site. - -Webinars and Trainings ----------------------- - -Mastering the Basics of Espressif Chips: An In-Depth Look at Chip Flashing -^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - -The content of this webinar is designed for developers, engineers and hobbyists interested in getting a better understanding of how to use esptool.py or other tools for the development with the ESP8266 or ESP32 series of SoCs. - -It offers an in-depth look at the inner mechanisms of esptool.py, including the :ref:`boot-mode` process. - -.. image:: https://img.youtube.com/vi/zh-Y_s4X6zs/maxresdefault.jpg - :alt: Mastering the Basics of Espressif Chips: An In-Depth Look at Chip Flashing - :target: https://www.youtube.com/watch?v=zh-Y_s4X6zs - -DevCon22: esptool.py: Espressif's Swiss Army Knife -^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -This talk aims to show how simple, yet powerful, esptool.py is, and how to use it to tame your ESP. - -.. image:: https://img.youtube.com/vi/GjWGKzu3XTk/maxresdefault.jpg - :alt: DevCon22: esptool.py: Espressif's Swiss Army Knife - :target: https://www.youtube.com/watch?v=GjWGKzu3XTk diff --git a/tools/esptool_py/docs/en/troubleshooting.rst b/tools/esptool_py/docs/en/troubleshooting.rst deleted file mode 100644 index 5f6fbead0f..0000000000 --- a/tools/esptool_py/docs/en/troubleshooting.rst +++ /dev/null @@ -1,223 +0,0 @@ -{IDF_TARGET_BOOTLOADER_OFFSET:default="0x0", esp32="0x1000", esp32s2="0x1000", esp32p4="0x2000"} - -.. _troubleshooting: - -Troubleshooting -=============== - -Flashing problems can be fiddly to troubleshoot. The underlying issue can be caused by the drivers, OS, hardware, or even a combination of these. If your board is a custom design, check the `ESP Hardware Design Guidelines `_ or consider using our `free-of-charge schematic and PCB review service `_. - -Try the following suggestions if your issues persist: - -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. - -.. only:: not esp8266 and not esp32 and not esp32c2 - - Issues and Debugging in USB-Serial/JTAG or USB-OTG modes - -------------------------------------------------------- - - When working with ESP chips that implement a `USB-Serial/JTAG `_ or a `USB-OTG `_ console (you are not using a classic USB-to-Serial adapter), it's essential to be aware of potential issues related to the loaded application interfering with or reprogramming the GPIO pins used for USB communication. - - If the application accidentally reconfigures the USB peripheral pins or disables the USB peripheral, the device disappears from the system. You can also encounter unstable flashing or errors like ``OSError: [Errno 71] Protocol error``. - - If that happens, try to :ref:`manually enter the download mode ` and then use the :ref:`erase_flash ` command to wipe the flash memory. Then, make sure to fix the issue in the application before flashing again. - - On boards with two USB ports (usually marked as USB and UART), you can use the USB port for flashing while listening on the UART port for debugging purposes. This setup is useful for retrieving core dumps or the reset reason in the event of a crash. To implement this, connect the UART port to another instance of any of the `serial terminal programs`_, while repeating the failing action over the USB port. You'll be able to monitor the crash log without interference from the USB port used for communication or it disappearing due to a firmware crash. - If your devkit doesn't have a dedicated USB port connected to an on-board USB-to-UART bridge, you can use a separate adapter to connect to the UART pins on the board. - -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. - -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. - -Some of the most common pySerial error causes are: - -.. list:: - - * 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. - * You don't have permission to access the port. - -On Linux, read and write access the serial port over USB is necessary. You can add your user to the ``dialout`` or ``uucp`` group to grant access to the serial port. See `Adding user to dialout or uucp on Linux `_. diff --git a/tools/esptool_py/docs/en/versions.rst b/tools/esptool_py/docs/en/versions.rst deleted file mode 100644 index 648701e066..0000000000 --- a/tools/esptool_py/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/tools/esptool_py/docs/requirements.txt b/tools/esptool_py/docs/requirements.txt deleted file mode 100644 index 948dda348e..0000000000 --- a/tools/esptool_py/docs/requirements.txt +++ /dev/null @@ -1 +0,0 @@ -esp-docs~=1.5 diff --git a/tools/esptool_py/docs/utils.sh b/tools/esptool_py/docs/utils.sh deleted file mode 100644 index 84f3748997..0000000000 --- a/tools/esptool_py/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/tools/esptool_py/esp_rfc2217_server.py b/tools/esptool_py/esp_rfc2217_server.py deleted file mode 100755 index 4d97247592..0000000000 --- a/tools/esptool_py/esp_rfc2217_server.py +++ /dev/null @@ -1,56 +0,0 @@ -#!/usr/bin/env python -# -# SPDX-FileCopyrightText: 2014-2024 Fredrik Ahlberg, Angus Gratton, -# Espressif Systems (Shanghai) CO LTD, other contributors as noted. -# -# SPDX-License-Identifier: BSD-3-Clause - -# This executable script is a thin wrapper around the main functionality -# in the esp_rfc2217_server Python package - -# When updating this script, please also update esptool.py, espefuse.py and espsecure.py - -################################################################################### -# Redirect data from a TCP/IP connection to a serial port and vice versa using RFC 2217. -# -# This is a modified version of rfc2217_server.py provided by the pyserial package -# (pythonhosted.org/pyserial/examples.html#single-port-tcp-ip-serial-bridge-rfc-2217). -# It uses a custom PortManager to properly apply the RTS & DTR signals -# for resetting ESP chips. -# -# Run the following command on the server side to make -# connection between /dev/ttyUSB1 and TCP port 4000: -# -# python esp_rfc2217_server.py -p 4000 /dev/ttyUSB1 -# -# Esptool can connect to the ESP device through that server as it is -# demonstrated in the following example: -# -# esptool.py --port rfc2217://localhost:4000?ign_set_control flash_id -# - -import contextlib -import os -import sys - -if os.name != "nt": - # Linux/macOS: remove current script directory to avoid importing this file - # as a module; we want to import the installed esp_rfc2217_server module instead - with contextlib.suppress(ValueError): - 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 esp_rfc2217_server module in - # other Python scripts - with contextlib.suppress(KeyError): - del sys.modules["esp_rfc2217_server"] - -import esp_rfc2217_server - -if __name__ == "__main__": - esp_rfc2217_server.main() diff --git a/tools/esptool_py/esp_rfc2217_server/__init__.py b/tools/esptool_py/esp_rfc2217_server/__init__.py deleted file mode 100644 index 4c489ec284..0000000000 --- a/tools/esptool_py/esp_rfc2217_server/__init__.py +++ /dev/null @@ -1,124 +0,0 @@ -# SPDX-FileCopyrightText: 2009-2015 Chris Liechti -# SPDX-FileContributor: 2020-2024 Espressif Systems (Shanghai) CO LTD -# SPDX-License-Identifier: BSD-3-Clause -# -# Redirect data from a TCP/IP connection to a serial port and vice versa using RFC 2217. - -################################################################################### -# redirect data from a TCP/IP connection to a serial port and vice versa -# using RFC 2217 -# -# (C) 2009-2015 Chris Liechti -# -# SPDX-License-Identifier: BSD-3-Clause - -import logging -import socket -import sys -import serial - -from esp_rfc2217_server.redirector import Redirector - - -def main(): - import argparse - - parser = argparse.ArgumentParser( - description="RFC 2217 Serial to Network (TCP/IP) redirector.", - epilog="NOTE: no security measures are implemented. " - "Anyone can remotely connect to this service over the network.\n" - "Only one connection at once is supported. " - "When the connection is terminated it waits for the next connect.", - ) - - parser.add_argument("SERIALPORT") - - parser.add_argument( - "-p", - "--localport", - type=int, - help="local TCP port, default: %(default)s", - metavar="TCPPORT", - default=2217, - ) - - parser.add_argument( - "-v", - "--verbose", - dest="verbosity", - action="count", - help="print more diagnostic messages (option can be given multiple times)", - default=0, - ) - - parser.add_argument( - "--r0", - help="Use delays necessary for ESP32 revision 0 chips", - action="store_true", - ) - - args = parser.parse_args() - - if args.verbosity > 3: - args.verbosity = 3 - level = (logging.WARNING, logging.INFO, logging.DEBUG, logging.NOTSET)[ - args.verbosity - ] - logging.basicConfig(level=logging.INFO) - # logging.getLogger('root').setLevel(logging.INFO) - logging.getLogger("rfc2217").setLevel(level) - - # connect to serial port - ser = serial.serial_for_url(args.SERIALPORT, do_not_open=True, exclusive=True) - ser.timeout = 3 # required so that the reader thread can exit - # reset control line as no _remote_ "terminal" has been connected yet - ser.dtr = False - ser.rts = False - - logging.info(" RFC 2217 TCP/IP to Serial redirector - type Ctrl-C / BREAK to quit") - - try: - ser.open() - except serial.SerialException as e: - logging.error(" Could not open serial port {}: {}".format(ser.name, e)) - sys.exit(1) - - logging.info(" Serving serial port: {}".format(ser.name)) - settings = ser.get_settings() - - srv = socket.socket(socket.AF_INET, socket.SOCK_STREAM) - srv.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1) - srv.bind(("", args.localport)) - srv.listen(1) - logging.info(" TCP/IP port: {}".format(args.localport)) - while True: - try: - client_socket, addr = srv.accept() - logging.info("Connected by {}:{}".format(addr[0], addr[1])) - client_socket.setsockopt(socket.IPPROTO_TCP, socket.TCP_NODELAY, 1) - ser.rts = True - ser.dtr = True - # enter network <-> serial loop - r = Redirector(ser, client_socket, args.verbosity > 0, args.r0) - try: - r.shortcircuit() - finally: - logging.info("Disconnected") - r.stop() - client_socket.close() - ser.dtr = False - ser.rts = False - # Restore port settings (may have been changed by RFC 2217 - # capable client) - ser.apply_settings(settings) - except KeyboardInterrupt: - sys.stdout.write("\n") - break - except socket.error as msg: - logging.error(str(msg)) - - logging.info("--- exit ---") - - -if __name__ == "__main__": - main() diff --git a/tools/esptool_py/esp_rfc2217_server/__main__.py b/tools/esptool_py/esp_rfc2217_server/__main__.py deleted file mode 100644 index 2f041e64ce..0000000000 --- a/tools/esptool_py/esp_rfc2217_server/__main__.py +++ /dev/null @@ -1,9 +0,0 @@ -# SPDX-FileCopyrightText: 2014-2024 Fredrik Ahlberg, Angus Gratton, -# Espressif Systems (Shanghai) CO LTD, other contributors as noted. -# -# SPDX-License-Identifier: BSD-3-Clause - -import esp_rfc2217_server - -if __name__ == "__main__": - esp_rfc2217_server.main() diff --git a/tools/esptool_py/esp_rfc2217_server/esp_port_manager.py b/tools/esptool_py/esp_rfc2217_server/esp_port_manager.py deleted file mode 100644 index 29f1046384..0000000000 --- a/tools/esptool_py/esp_rfc2217_server/esp_port_manager.py +++ /dev/null @@ -1,97 +0,0 @@ -# SPDX-FileCopyrightText: 2014-2024 Fredrik Ahlberg, Angus Gratton, -# Espressif Systems (Shanghai) CO LTD, other contributors as noted. -# -# SPDX-License-Identifier: BSD-3-Clause -import os -import threading -from esptool.reset import ( - ClassicReset, - CustomReset, - DEFAULT_RESET_DELAY, - HardReset, - UnixTightReset, -) -import serial -import serial.rfc2217 -from serial.rfc2217 import ( - COM_PORT_OPTION, - SET_CONTROL, - SET_CONTROL_DTR_OFF, - SET_CONTROL_DTR_ON, - SET_CONTROL_RTS_OFF, - SET_CONTROL_RTS_ON, -) - -from esptool.config import load_config_file - -cfg, _ = load_config_file(verbose=True) -cfg = cfg["esptool"] - - -class EspPortManager(serial.rfc2217.PortManager): - """ - The beginning of the reset sequence is detected and the proper reset sequence - is applied in a thread. The rest of the reset sequence received is just ignored - and not sent to the serial port. - """ - - 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_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" - reset_thread.start() - return - elif suboption[2:3] in [ - SET_CONTROL_DTR_ON, - SET_CONTROL_RTS_ON, - SET_CONTROL_RTS_OFF, - ]: - return - # only in cases not handled above do the original implementation in PortManager - super(EspPortManager, self)._telnet_process_subnegotiation(suboption) - - 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): - """ - The reset logic is used from esptool.py because the RTS and DTR signals - cannot be retransmitted through RFC 2217 with proper timing. - """ - if self.logger: - self.logger.info("Activating reset in thread") - - delay = DEFAULT_RESET_DELAY - if self.esp32r0_delay: - 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)() diff --git a/tools/esptool_py/esp_rfc2217_server/redirector.py b/tools/esptool_py/esp_rfc2217_server/redirector.py deleted file mode 100644 index aa2c643a25..0000000000 --- a/tools/esptool_py/esp_rfc2217_server/redirector.py +++ /dev/null @@ -1,89 +0,0 @@ -# SPDX-FileCopyrightText: 2014-2024 Fredrik Ahlberg, Angus Gratton, -# Espressif Systems (Shanghai) CO LTD, other contributors as noted. -# -# SPDX-License-Identifier: BSD-3-Clause -import threading -import time -import logging -import socket - -from esp_rfc2217_server.esp_port_manager import EspPortManager - - -class Redirector(object): - def __init__(self, serial_instance, socket, debug=False, esp32r0delay=False): - self.serial = serial_instance - self.socket = socket - self._write_lock = threading.Lock() - self.rfc2217 = EspPortManager( - self.serial, - self, - esp32r0delay, - logger=logging.getLogger("rfc2217.server") if debug else None, - ) - self.log = logging.getLogger("redirector") - self.force_exit = False - - def statusline_poller(self): - self.log.debug("status line poll thread started") - while self.alive: - time.sleep(1) - self.rfc2217.check_modem_lines() - self.log.debug("status line poll thread terminated") - - def shortcircuit(self): - """connect the serial port to the TCP port by copying everything - from one side to the other""" - self.alive = True - self.thread_read = threading.Thread(target=self.reader) - self.thread_read.daemon = True - self.thread_read.name = "serial->socket" - self.thread_read.start() - self.thread_poll = threading.Thread(target=self.statusline_poller) - self.thread_poll.daemon = True - self.thread_poll.name = "status line poll" - self.thread_poll.start() - self.writer() - - def reader(self): - """loop forever and copy serial->socket""" - self.log.debug("reader thread started") - while self.alive: - try: - data = self.serial.read(self.serial.in_waiting or 1) - if data: - # escape outgoing data when needed (Telnet IAC (0xff) character) - self.write(b"".join(self.rfc2217.escape(data))) - except socket.error as msg: - self.log.error("{}".format(msg)) - # probably got disconnected - break - self.alive = False - self.log.debug("reader thread terminated") - - def write(self, data): - """thread safe socket write with no data escaping. used to send telnet stuff""" - with self._write_lock: - self.socket.sendall(data) - - def writer(self): - """loop forever and copy socket->serial""" - while self.alive: - try: - data = self.socket.recv(1024) - if not data: - break - self.serial.write(b"".join(self.rfc2217.filter(data))) - except socket.error as msg: - self.log.error("{}".format(msg)) - # probably got disconnected - break - self.stop() - - def stop(self): - """Stop copying""" - self.log.debug("stopping") - if self.alive: - self.alive = False - self.thread_read.join() - self.thread_poll.join() diff --git a/tools/esptool_py/espefuse.py b/tools/esptool_py/espefuse.py deleted file mode 100755 index 2222d4e55c..0000000000 --- a/tools/esptool_py/espefuse.py +++ /dev/null @@ -1,37 +0,0 @@ -#!/usr/bin/env python -# -# SPDX-FileCopyrightText: 2014-2022 Fredrik Ahlberg, Angus Gratton, -# Espressif Systems (Shanghai) CO LTD, other contributors as noted. -# -# SPDX-License-Identifier: GPL-2.0-or-later - -# This executable script is a thin wrapper around the main functionality -# in the espefuse Python package - -# When updating this script, please also update esptool.py and espsecure.py - -import contextlib -import os -import sys - -if os.name != "nt": - # 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): - 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 - # other Python scripts - with contextlib.suppress(KeyError): - del sys.modules["espefuse"] - -import espefuse - -if __name__ == "__main__": - espefuse._main() diff --git a/tools/esptool_py/espefuse/__init__.py b/tools/esptool_py/espefuse/__init__.py deleted file mode 100755 index 518e96566e..0000000000 --- a/tools/esptool_py/espefuse/__init__.py +++ /dev/null @@ -1,367 +0,0 @@ -# SPDX-FileCopyrightText: 2016-2022 Espressif Systems (Shanghai) CO LTD -# -# SPDX-License-Identifier: GPL-2.0-or-later -# PYTHON_ARGCOMPLETE_OK - -import argparse -import os -import sys -from collections import namedtuple -from io import StringIO - -import espefuse.efuse.esp32 as esp32_efuse -import espefuse.efuse.esp32c2 as esp32c2_efuse -import espefuse.efuse.esp32c3 as esp32c3_efuse -import espefuse.efuse.esp32c5 as esp32c5_efuse -import espefuse.efuse.esp32c5beta3 as esp32c5beta3_efuse -import espefuse.efuse.esp32c6 as esp32c6_efuse -import espefuse.efuse.esp32c61 as esp32c61_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 - -import esptool - -DefChip = namedtuple("DefChip", ["chip_name", "efuse_lib", "chip_class"]) - -SUPPORTED_BURN_COMMANDS = [ - "read_protect_efuse", - "write_protect_efuse", - "burn_efuse", - "burn_block_data", - "burn_bit", - "burn_key", - "burn_key_digest", - "burn_custom_mac", - "set_flash_voltage", - "execute_scripts", -] - -SUPPORTED_READ_COMMANDS = [ - "summary", - "dump", - "get_custom_mac", - "adc_info", - "check_error", -] - -SUPPORTED_COMMANDS = SUPPORTED_READ_COMMANDS + SUPPORTED_BURN_COMMANDS - -SUPPORTED_CHIPS = { - "esp32": DefChip("ESP32", esp32_efuse, esptool.targets.ESP32ROM), - "esp32c2": DefChip("ESP32-C2", esp32c2_efuse, esptool.targets.ESP32C2ROM), - "esp32c3": DefChip("ESP32-C3", esp32c3_efuse, esptool.targets.ESP32C3ROM), - "esp32c6": DefChip("ESP32-C6", esp32c6_efuse, esptool.targets.ESP32C6ROM), - "esp32c61": DefChip("ESP32-C61", esp32c61_efuse, esptool.targets.ESP32C61ROM), - "esp32c5": DefChip("ESP32-C5", esp32c5_efuse, esptool.targets.ESP32C5ROM), - "esp32c5beta3": DefChip( - "ESP32-C5(beta3)", esp32c5beta3_efuse, esptool.targets.ESP32C5BETA3ROM - ), - "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 - ), - "esp32s2": DefChip("ESP32-S2", esp32s2_efuse, esptool.targets.ESP32S2ROM), - "esp32s3": DefChip("ESP32-S3", esp32s3_efuse, esptool.targets.ESP32S3ROM), - "esp32s3beta2": DefChip( - "ESP32-S3(beta2)", esp32s3beta2_efuse, esptool.targets.ESP32S3BETA2ROM - ), -} - - -def get_esp( - port, - baud, - connect_mode, - chip="auto", - skip_connect=False, - virt=False, - debug=False, - virt_efuse_file=None, -): - if chip not in ["auto"] + list(SUPPORTED_CHIPS.keys()): - raise esptool.FatalError("get_esp: Unsupported chip (%s)" % chip) - if virt: - efuse = SUPPORTED_CHIPS.get(chip, SUPPORTED_CHIPS["esp32"]).efuse_lib - esp = efuse.EmulateEfuseController(virt_efuse_file, debug) - else: - if chip == "auto" and not skip_connect: - esp = esptool.cmds.detect_chip(port, baud, connect_mode) - else: - esp = SUPPORTED_CHIPS.get(chip, SUPPORTED_CHIPS["esp32"]).chip_class( - port if not skip_connect else StringIO(), baud - ) - if not skip_connect: - esp.connect(connect_mode) - if esp.sync_stub_detected: - esp = esp.STUB_CLASS(esp) - return esp - - -def get_efuses( - esp, - skip_connect=False, - debug_mode=False, - do_not_confirm=False, - extend_efuse_table=None, -): - for name in SUPPORTED_CHIPS: - if SUPPORTED_CHIPS[name].chip_name == esp.CHIP_NAME: - efuse = SUPPORTED_CHIPS[name].efuse_lib - return ( - efuse.EspEfuses( - esp, skip_connect, debug_mode, do_not_confirm, extend_efuse_table - ), - efuse.operations, - ) - else: - raise esptool.FatalError("get_efuses: Unsupported chip (%s)" % esp.CHIP_NAME) - - -def split_on_groups(all_args): - """ - This function splits the all_args list into groups, - where each item is a cmd with all its args. - - Example: - all_args: - ['burn_key_digest', 'secure_images/ecdsa256_secure_boot_signing_key_v2.pem', - 'burn_key', 'BLOCK_KEY0', 'images/efuse/128bit_key', - 'XTS_AES_128_KEY_DERIVED_FROM_128_EFUSE_BITS'] - - used_cmds: ['burn_key_digest', 'burn_key'] - groups: - [['burn_key_digest', 'secure_images/ecdsa256_secure_boot_signing_key_v2.pem'], - ['burn_key', 'BLOCK_KEY0', 'images/efuse/128bit_key', - 'XTS_AES_128_KEY_DERIVED_FROM_128_EFUSE_BITS']] - """ - - groups = [] - cmd = [] - used_cmds = [] - for item in all_args: - if item in SUPPORTED_COMMANDS: - used_cmds.append(item) - if cmd != []: - groups.append(cmd) - cmd = [] - cmd.append(item) - if cmd: - groups.append(cmd) - return groups, used_cmds - - -def main(custom_commandline=None, esp=None): - """ - Main function for espefuse - - custom_commandline - Optional override for default arguments parsing - (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__, - prog="espefuse", - add_help=False, - ) - - init_parser.add_argument( - "--chip", - "-c", - help="Target chip type", - choices=["auto"] + list(SUPPORTED_CHIPS.keys()), - default=os.environ.get("ESPTOOL_CHIP", "auto"), - ) - - init_parser.add_argument( - "--baud", - "-b", - help="Serial port baud rate used when flashing/reading", - type=esptool.arg_auto_int, - default=os.environ.get("ESPTOOL_BAUD", esptool.loader.ESPLoader.ESP_ROM_BAUD), - ) - - init_parser.add_argument( - "--port", - "-p", - help="Serial port device", - default=os.environ.get("ESPTOOL_PORT", esptool.loader.ESPLoader.DEFAULT_PORT), - ) - - init_parser.add_argument( - "--before", - help="What to do before connecting to the chip", - choices=["default_reset", "usb_reset", "no_reset", "no_reset_no_sync"], - default="default_reset", - ) - - init_parser.add_argument( - "--debug", - "-d", - help="Show debugging information (loglevel=DEBUG)", - action="store_true", - ) - init_parser.add_argument( - "--virt", - help="For host tests, the tool will work in the virtual mode " - "(without connecting to a chip).", - action="store_true", - ) - init_parser.add_argument( - "--path-efuse-file", - help="For host tests, saves efuse memory to file.", - type=str, - default=None, - ) - init_parser.add_argument( - "--do-not-confirm", - help="Do not pause for confirmation before permanently writing efuses. " - "Use with caution.", - action="store_true", - ) - init_parser.add_argument( - "--postpone", - help="Postpone burning some efuses from BLOCK0 at the end, " - "(efuses which disable access to blocks or chip).", - action="store_true", - ) - init_parser.add_argument( - "--extend-efuse-table", - help="CSV file from ESP-IDF (esp_efuse_custom_table.csv)", - type=argparse.FileType("r"), - default=None, - ) - - common_args, remaining_args = init_parser.parse_known_args(custom_commandline) - debug_mode = common_args.debug - just_print_help = [ - True for arg in remaining_args if arg in ["--help", "-h"] - ] or remaining_args == [] - - print("espefuse.py v{}".format(esptool.__version__)) - - 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, - common_args.extend_efuse_table, - ) - - parser = argparse.ArgumentParser(parents=[init_parser]) - subparsers = parser.add_subparsers( - dest="operation", help="Run espefuse.py {command} -h for additional help" - ) - - efuse_operations.add_commands(subparsers, efuses) - - # Enable argcomplete only on Unix-like systems - if sys.platform != "win32": - try: - import argcomplete - - argcomplete.autocomplete(parser) - except ImportError: - pass - - grouped_remaining_args, used_cmds = split_on_groups(remaining_args) - if len(grouped_remaining_args) == 0: - parser.print_help() - parser.exit(1) - there_are_multiple_burn_commands_in_args = ( - sum(cmd in SUPPORTED_BURN_COMMANDS for cmd in used_cmds) > 1 - ) - if there_are_multiple_burn_commands_in_args: - efuses.batch_mode_cnt += 1 - - efuses.postpone = common_args.postpone - - try: - for rem_args in grouped_remaining_args: - args, unused_args = parser.parse_known_args(rem_args, namespace=common_args) - if args.operation is None: - parser.print_help() - parser.exit(1) - assert ( - len(unused_args) == 0 - ), 'Not all commands were recognized "{}"'.format(unused_args) - - 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: - efuses.batch_mode_cnt -= 1 - if not efuses.burn_all(check_batch_mode=True): - raise esptool.FatalError("BURN was not done") - print("Successful") - - if ( - sum(cmd in SUPPORTED_BURN_COMMANDS for cmd in used_cmds) > 0 - and sum(cmd in SUPPORTED_READ_COMMANDS for cmd in used_cmds) > 0 - ): - # [burn_cmd1] [burn_cmd2] [read_cmd1] [burn_cmd3] [read_cmd2] - print("\n=== Run read commands after burn commands ===") - for rem_args in grouped_remaining_args: - args, unused_args = parser.parse_known_args( - rem_args, namespace=common_args - ) - current_cmd = args.operation - if current_cmd in SUPPORTED_READ_COMMANDS: - print(f"\n=== Run {args.operation} command ===") - operation_func = vars(efuse_operations)[current_cmd] - operation_func(esp, efuses, args) - finally: - if not external_esp and not common_args.virt and esp._port: - esp._port.close() - - -def _main(): - try: - main() - except esptool.FatalError as e: - print("\nA fatal error occurred: %s" % e) - sys.exit(2) - - -if __name__ == "__main__": - _main() diff --git a/tools/esptool_py/espefuse/__main__.py b/tools/esptool_py/espefuse/__main__.py deleted file mode 100644 index 596cf6567e..0000000000 --- a/tools/esptool_py/espefuse/__main__.py +++ /dev/null @@ -1,8 +0,0 @@ -# SPDX-FileCopyrightText: 2016-2022 Espressif Systems (Shanghai) CO LTD -# -# SPDX-License-Identifier: GPL-2.0-or-later - -import espefuse - -if __name__ == "__main__": - espefuse._main() diff --git a/tools/esptool_py/espefuse/efuse/__init__.py b/tools/esptool_py/espefuse/efuse/__init__.py deleted file mode 100644 index e69de29bb2..0000000000 diff --git a/tools/esptool_py/espefuse/efuse/base_fields.py b/tools/esptool_py/espefuse/efuse/base_fields.py deleted file mode 100644 index 654d0fd668..0000000000 --- a/tools/esptool_py/espefuse/efuse/base_fields.py +++ /dev/null @@ -1,871 +0,0 @@ -# This file describes the common eFuses structures for chips -# -# SPDX-FileCopyrightText: 2020-2022 Espressif Systems (Shanghai) CO LTD -# -# SPDX-License-Identifier: GPL-2.0-or-later - -import binascii -import sys - -from bitstring import BitArray, BitStream, CreationError - -import esptool - -from . import util -from typing import List - - -class CheckArgValue(object): - def __init__(self, efuses, name): - self.efuses = efuses - self.name = name - - def __call__(self, new_value_str): - def check_arg_value(efuse, new_value): - if efuse.efuse_type.startswith("bool"): - new_value = 1 if new_value is None else int(new_value, 0) - if new_value != 1: - raise esptool.FatalError( - "New value is not accepted for efuse '{}' " - "(will always burn 0->1), given value={}".format( - efuse.name, new_value - ) - ) - elif efuse.efuse_type.startswith(("int", "uint")): - if efuse.efuse_class == "bitcount": - if new_value is None: - # find the first unset bit and set it - old_value = efuse.get_raw() - new_value = old_value - bit = 1 - while new_value == old_value: - new_value = bit | old_value - bit <<= 1 - else: - new_value = int(new_value, 0) - else: - if new_value is None: - raise esptool.FatalError( - "New value required for efuse '{}' (given None)".format( - efuse.name - ) - ) - new_value = int(new_value, 0) - if new_value == 0: - raise esptool.FatalError( - "New value should not be 0 for '{}' " - "(given value= {})".format(efuse.name, new_value) - ) - elif efuse.efuse_type.startswith("bytes"): - if new_value is None: - raise esptool.FatalError( - "New value required for efuse '{}' (given None)".format( - efuse.name - ) - ) - if len(new_value) * 8 != efuse.bitarray.len: - raise esptool.FatalError( - "The length of efuse '{}' ({} bits) " - "(given len of the new value= {} bits)".format( - efuse.name, efuse.bitarray.len, len(new_value) * 8 - ) - ) - else: - raise esptool.FatalError( - "The '{}' type for the '{}' efuse is not supported yet.".format( - efuse.efuse_type, efuse.name - ) - ) - return new_value - - efuse = self.efuses[self.name] - new_value = efuse.check_format(new_value_str) - return check_arg_value(efuse, new_value) - - -class EfuseProtectBase(object): - # This class is used by EfuseBlockBase and EfuseFieldBase - - 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): - 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 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(blk_part)) == 0 - - def disable_read(self): - num_bit = self.read_disable_bit - if num_bit is None: - raise esptool.FatalError("This efuse cannot be read-disabled") - if not self.parent["RD_DIS"].is_writeable(): - raise esptool.FatalError( - "This efuse cannot be read-disabled due the to RD_DIS field is " - "already write-disabled" - ) - self.parent["RD_DIS"].save(self.get_read_disable_mask()) - - def is_writeable(self): - num_bit = self.write_disable_bit - if num_bit is None: - return True # write cannot be disabled - return (self.parent["WR_DIS"].get() & (1 << num_bit)) == 0 - - def disable_write(self): - num_bit = self.write_disable_bit - if not self.parent["WR_DIS"].is_writeable(): - raise esptool.FatalError( - "This efuse cannot be write-disabled due to the WR_DIS field is " - "already write-disabled" - ) - self.parent["WR_DIS"].save(1 << num_bit) - - def check_wr_rd_protect(self): - if not self.is_readable(): - error_msg = "\t{} is read-protected.".format(self.name) - "The written value can not be read, the efuse/block looks as all 0.\n" - error_msg += "\tBurn in this case may damage an already written value." - self.parent.print_error_msg(error_msg) - if not self.is_writeable(): - error_msg = "\t{} is write-protected. Burn is not possible.".format( - self.name - ) - self.parent.print_error_msg(error_msg) - - -class EfuseBlockBase(EfuseProtectBase): - def __init__(self, parent, param, skip_read=False): - self.parent = parent - self.name = param.name - self.alias = param.alias - self.id = param.id - self.rd_addr = param.rd_addr - self.wr_addr = param.wr_addr - self.write_disable_bit = param.write_disable_bit - self.read_disable_bit = param.read_disable_bit - self.len = param.len - self.key_purpose_name = param.key_purpose - bit_block_len = self.get_block_len() * 8 - self.bitarray = BitStream(bit_block_len) - self.bitarray.set(0) - self.wr_bitarray = BitStream(bit_block_len) - self.wr_bitarray.set(0) - self.fail = False - self.num_errors = 0 - if self.id == 0: - self.err_bitarray = BitStream(bit_block_len) - self.err_bitarray.set(0) - else: - self.err_bitarray = None - - if not skip_read: - self.read() - - def get_block_len(self): - coding_scheme = self.get_coding_scheme() - if coding_scheme == self.parent.REGS.CODING_SCHEME_NONE: - return self.len * 4 - elif coding_scheme == self.parent.REGS.CODING_SCHEME_34: - return (self.len * 3 // 4) * 4 - elif coding_scheme == self.parent.REGS.CODING_SCHEME_RS: - return self.len * 4 - else: - raise esptool.FatalError( - "Coding scheme (%d) not supported" % (coding_scheme) - ) - - def get_coding_scheme(self): - if self.id == 0: - return self.parent.REGS.CODING_SCHEME_NONE - else: - return self.parent.coding_scheme - - def get_raw(self, from_read=True): - if from_read: - return self.bitarray.bytes - else: - return self.wr_bitarray.bytes - - def get(self, from_read=True): - self.get_bitstring(from_read=from_read) - - def get_bitstring(self, from_read=True): - if from_read: - return self.bitarray - else: - return self.wr_bitarray - - def convert_to_bitstring(self, new_data): - if isinstance(new_data, BitArray): - return new_data - else: - return BitArray(bytes=new_data, length=len(new_data) * 8) - - def get_words(self): - def get_offsets(self): - return [x + self.rd_addr for x in range(0, self.get_block_len(), 4)] - - return [self.parent.read_reg(offs) for offs in get_offsets(self)] - - def read(self, print_info=True): - words = self.get_words() - data = BitArray() - for word in reversed(words): - data.append("uint:32=%d" % word) - self.bitarray.overwrite(data, pos=0) - if print_info: - self.print_block(self.bitarray, "read_regs") - - def print_block(self, bit_string, comment, debug=False): - if self.parent.debug or debug: - bit_string.pos = 0 - print( - "%-15s (%-16s) [%-2d] %s:" - % (self.name, " ".join(self.alias)[:16], self.id, comment), - " ".join( - [ - "%08x" % word - for word in bit_string.readlist( - "%d*uint:32" % (bit_string.len / 32) - )[::-1] - ] - ), - ) - - def check_wr_data(self): - wr_data = self.wr_bitarray - if wr_data.all(False): - # nothing to burn - if self.parent.debug: - print("[{:02}] {:20} nothing to burn".format(self.id, self.name)) - return False - if len(wr_data.bytes) != len(self.bitarray.bytes): - raise esptool.FatalError( - "Data does not fit: the block%d size is %d bytes, data is %d bytes" - % (self.id, len(self.bitarray.bytes), len(wr_data.bytes)) - ) - self.check_wr_rd_protect() - - if self.get_bitstring().all(False): - print( - "[{:02}] {:20} is empty, will burn the new value".format( - self.id, self.name - ) - ) - else: - # the written block in chip is not empty - if self.get_bitstring() == wr_data: - print( - "[{:02}] {:20} is already written the same value, " - "continue with EMPTY_BLOCK".format(self.id, self.name) - ) - wr_data.set(0) - else: - print("[{:02}] {:20} is not empty".format(self.id, self.name)) - print("\t(written ):", self.get_bitstring()) - print("\t(to write):", wr_data) - mask = self.get_bitstring() & wr_data - if mask == wr_data: - print( - "\tAll wr_data bits are set in the written block, " - "continue with EMPTY_BLOCK." - ) - wr_data.set(0) - else: - coding_scheme = self.get_coding_scheme() - if coding_scheme == self.parent.REGS.CODING_SCHEME_NONE: - print("\t(coding scheme = NONE)") - elif coding_scheme == self.parent.REGS.CODING_SCHEME_RS: - print("\t(coding scheme = RS)") - error_msg = ( - "\tBurn into %s is forbidden " - "(RS coding scheme does not allow this)." % (self.name) - ) - self.parent.print_error_msg(error_msg) - elif coding_scheme == self.parent.REGS.CODING_SCHEME_34: - print("\t(coding scheme = 3/4)") - data_can_not_be_burn = False - for i in range(0, self.get_bitstring().len, 6 * 8): - rd_chunk = self.get_bitstring()[i : i + 6 * 8 :] - wr_chunk = wr_data[i : i + 6 * 8 :] - if rd_chunk.any(True): - if wr_chunk.any(True): - print( - "\twritten chunk [%d] and wr_chunk " - "are not empty. " % (i // (6 * 8)), - end="", - ) - if rd_chunk == wr_chunk: - print( - "wr_chunk == rd_chunk. " - "Continue with empty chunk." - ) - wr_data[i : i + 6 * 8 :].set(0) - else: - print("wr_chunk != rd_chunk. Can not burn.") - print("\twritten ", rd_chunk) - print("\tto write", wr_chunk) - data_can_not_be_burn = True - if data_can_not_be_burn: - error_msg = ( - "\tBurn into %s is forbidden " - "(3/4 coding scheme does not allow this)." % (self.name) - ) - self.parent.print_error_msg(error_msg) - else: - raise esptool.FatalError( - "The coding scheme ({}) is not supported".format( - coding_scheme - ) - ) - - def save(self, new_data): - # new_data will be checked by check_wr_data() during burn_all() - # new_data (bytes) = [0][1][2] ... [N] (original data) - # in string format = [0] [1] [2] ... [N] (util.hexify(data, " ")) - # in hex format = 0x[N]....[2][1][0] (from bitstring print(data)) - # in reg format = [3][2][1][0] ... [N][][][] (as it will be in the device) - # in bitstring = [N] ... [2][1][0] (to get a correct bitstring - # need to reverse new_data) - # *[x] - means a byte. - data = BitStream(bytes=new_data[::-1], length=len(new_data) * 8) - if self.parent.debug: - print( - "\twritten : {} ->\n\tto write: {}".format(self.get_bitstring(), data) - ) - self.wr_bitarray.overwrite(self.wr_bitarray | data, pos=0) - - def burn_words(self, words): - for burns in range(3): - self.parent.efuse_controller_setup() - if self.parent.debug: - print("Write data to BLOCK%d" % (self.id)) - write_reg_addr = self.wr_addr - for word in words: - # for ep32s2: using EFUSE_PGM_DATA[0..7]_REG for writing data - # 32 bytes to EFUSE_PGM_DATA[0..7]_REG - # 12 bytes to EFUSE_CHECK_VALUE[0..2]_REG. These regs are next after - # EFUSE_PGM_DATA_REG - # for esp32: - # each block has the special regs EFUSE_BLK[0..3]_WDATA[0..7]_REG - # for writing data - if self.parent.debug: - print("Addr 0x%08x, data=0x%08x" % (write_reg_addr, word)) - self.parent.write_reg(write_reg_addr, word) - write_reg_addr += 4 - - self.parent.write_efuses(self.id) - for _ in range(5): - self.parent.efuse_read() - self.parent.get_coding_scheme_warnings(silent=True) - if self.fail or self.num_errors: - print( - "Error in BLOCK%d, re-burn it again (#%d), to fix it. " - "fail_bit=%d, num_errors=%d" - % (self.id, burns, self.fail, self.num_errors) - ) - break - if not self.fail and self.num_errors == 0: - self.read(print_info=False) - if self.wr_bitarray & self.bitarray != self.wr_bitarray: - # if the required bits are not set then we need to re-burn it again. - if burns < 2: - print( - f"\nRepeat burning BLOCK{self.id} (#{burns + 2}) because not all bits were set" - ) - continue - else: - print( - f"\nAfter {burns + 1} attempts, the required data was not set to BLOCK{self.id}" - ) - break - - def burn(self): - if self.wr_bitarray.all(False): - # nothing to burn - return - before_burn_bitarray = self.bitarray[:] - assert before_burn_bitarray is not self.bitarray - self.print_block(self.wr_bitarray, "to_write") - words = self.apply_coding_scheme() - self.burn_words(words) - self.read() - if not self.is_readable(): - print( - "{} ({}) is read-protected. " - "Read back the burn value is not possible.".format( - self.name, self.alias - ) - ) - if self.bitarray.all(False): - print("Read all '0'") - else: - # Should never happen - raise esptool.FatalError( - "The {} is read-protected but not all '0' ({})".format( - self.name, self.bitarray.hex - ) - ) - else: - if self.wr_bitarray == self.bitarray: - print("BURN BLOCK%-2d - OK (write block == read block)" % self.id) - elif ( - self.wr_bitarray & self.bitarray == self.wr_bitarray - and self.bitarray & before_burn_bitarray == before_burn_bitarray - ): - print("BURN BLOCK%-2d - OK (all write block bits are set)" % self.id) - else: - # Happens only when an efuse is written and read-protected - # in one command - self.print_block(self.wr_bitarray, "Expected") - self.print_block(self.bitarray, "Real ") - # Read-protected BLK0 values are reported back as zeros, - # raise error only for other blocks - if self.id != 0: - raise esptool.FatalError( - "Burn {} ({}) was not successful".format(self.name, self.alias) - ) - self.wr_bitarray.set(0) - - -class EspEfusesBase(object): - """ - Wrapper object to manage the efuse fields in a connected ESP bootloader - """ - - _esp = None - blocks: List[EfuseBlockBase] = [] - efuses: List = [] - coding_scheme = None - force_write_always = None - batch_mode_cnt = 0 - postpone = False - - def __iter__(self): - return self.efuses.__iter__() - - def get_crystal_freq(self): - return self._esp.get_crystal_freq() - - def read_efuse(self, n): - """Read the nth word of the ESP3x EFUSE region.""" - return self._esp.read_efuse(n) - - def read_reg(self, addr): - return self._esp.read_reg(addr) - - def write_reg(self, addr, value, mask=0xFFFFFFFF, delay_us=0, delay_after_us=0): - return self._esp.write_reg(addr, value, mask, delay_us, delay_after_us) - - def update_reg(self, addr, mask, new_val): - return self._esp.update_reg(addr, mask, new_val) - - def efuse_controller_setup(self): - pass - - def reconnect_chip(self, esp): - print("Re-connecting...") - baudrate = esp._port.baudrate - port = esp._port.port - esp._port.close() - return esptool.cmds.detect_chip(port, baudrate) - - def get_index_block_by_name(self, name): - for block in self.blocks: - if block.name == name or name in block.alias: - return block.id - return None - - def read_blocks(self): - for block in self.blocks: - block.read() - - def update_efuses(self): - for efuse in self.efuses: - efuse.update(self.blocks[efuse.block].bitarray) - - def postpone_efuses_from_block0_to_burn(self, block): - postpone_efuses = {} - - if block.id != 0: - return postpone_efuses - - # We need to check this list of efuses. If we are going to burn an efuse - # from this list, then we need to split the burn operation into two - # steps. The first step involves burning efuses not in this list. In - # case of an error during this step, we can recover by burning the - # efuses from this list at the very end. This approach provides the - # ability to recover efuses if an error occurs during the initial burn - # operation. - - # List the efuses here that must be burned at the very end, such as read - # and write protection fields, as well as efuses that disable - # communication with the espefuse tool. - efuses_list = ["WR_DIS", "RD_DIS"] - if self._esp.CHIP_NAME == "ESP32": - # Efuses below disables communication with the espefuse tool. - efuses_list.append("UART_DOWNLOAD_DIS") - # other efuses that are better to burn at the very end. - efuses_list.append("ABS_DONE_1") - efuses_list.append("FLASH_CRYPT_CNT") - else: - # Efuses below disables communication with the espefuse tool. - efuses_list.append("ENABLE_SECURITY_DOWNLOAD") - efuses_list.append("DIS_DOWNLOAD_MODE") - # other efuses that are better to burn at the very end. - efuses_list.append("SPI_BOOT_CRYPT_CNT") - efuses_list.append("SECURE_BOOT_EN") - - def get_raw_value_from_write(self, efuse_name): - return self[efuse_name].get_bitstring(from_read=False) - - for efuse_name in efuses_list: - postpone_efuses[efuse_name] = get_raw_value_from_write(self, efuse_name) - - if any(value != 0 for value in postpone_efuses.values()): - if self.debug: - print("These BLOCK0 efuses will be burned later at the very end:") - print(postpone_efuses) - # exclude these efuses from the first burn (postpone them till the end). - for key_name in postpone_efuses.keys(): - self[key_name].reset() - return postpone_efuses - - def recover_postponed_efuses_from_block0_to_burn(self, postpone_efuses): - if any(value != 0 for value in postpone_efuses.values()): - print("Burn postponed efuses from BLOCK0.") - for key_name in postpone_efuses.keys(): - self[key_name].save(postpone_efuses[key_name]) - - def burn_all(self, check_batch_mode=False): - if check_batch_mode: - if self.batch_mode_cnt != 0: - print( - "\nBatch mode is enabled, " - "the burn will be done at the end of the command." - ) - return False - print("\nCheck all blocks for burn...") - print("idx, BLOCK_NAME, Conclusion") - have_wr_data_for_burn = False - for block in self.blocks: - block.check_wr_data() - if not have_wr_data_for_burn and block.get_bitstring(from_read=False).any( - True - ): - have_wr_data_for_burn = True - if not have_wr_data_for_burn: - print("Nothing to burn, see messages above.") - return True - EspEfusesBase.confirm("", self.do_not_confirm) - - def burn_block(block, postponed_efuses): - old_fail = block.fail - old_num_errors = block.num_errors - block.burn() - if (block.fail and old_fail != block.fail) or ( - block.num_errors and block.num_errors > old_num_errors - ): - if postponed_efuses: - print("The postponed efuses were not burned due to an error.") - print("\t1. Try to fix a coding error by this cmd:") - print("\t 'espefuse.py check_error --recovery'") - command_string = " ".join( - f"{key} {value}" - for key, value in postponed_efuses.items() - if value.any(True) - ) - print("\t2. Then run the cmd to burn all postponed efuses:") - print(f"\t 'espefuse.py burn_efuse {command_string}'") - - raise esptool.FatalError("Error(s) were detected in eFuses") - - # Burn from BLKn -> BLK0. Because BLK0 can set rd or/and wr protection bits. - for block in reversed(self.blocks): - postponed_efuses = ( - self.postpone_efuses_from_block0_to_burn(block) - if self.postpone - else None - ) - - burn_block(block, postponed_efuses) - - if postponed_efuses: - self.recover_postponed_efuses_from_block0_to_burn(postponed_efuses) - burn_block(block, postponed_efuses) - - print("Reading updated efuses...") - self.read_coding_scheme() - self.read_blocks() - self.update_efuses() - return True - - @staticmethod - def confirm(action, do_not_confirm): - print( - "%s%s\nThis is an irreversible operation!" - % (action, "" if action.endswith("\n") else ". ") - ) - if not do_not_confirm: - print("Type 'BURN' (all capitals) to continue.") - # required for Pythons which disable line buffering, ie mingw in mintty - sys.stdout.flush() - yes = input() - if yes != "BURN": - print("Aborting.") - sys.exit(0) - - def print_error_msg(self, error_msg): - if self.force_write_always is not None: - if not self.force_write_always: - error_msg += "(use '--force-write-always' option to ignore it)" - if self.force_write_always: - print(error_msg, "Skipped because '--force-write-always' option.") - 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 - - def is_efuses_incompatible_for_burn(self): - # Overwrite this function for a specific target if you want to check if a certain eFuse(s) can be burned. - return False - - -class EfuseFieldBase(EfuseProtectBase): - def __init__(self, parent, param): - self.category = param.category - self.parent = parent - self.block = param.block - self.word = param.word - self.pos = param.pos - self.write_disable_bit = param.write_disable_bit - self.read_disable_bit = param.read_disable_bit - self.name = param.name - self.efuse_class = param.class_type - 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 - 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 - else: - if self.efuse_type.startswith("bytes"): - if new_value_str.startswith("0x"): - # cmd line: 0x0102030405060708 .... 112233ff (hex) - # regs: 112233ff ... 05060708 01020304 - # BLK: ff 33 22 11 ... 08 07 06 05 04 03 02 01 - return binascii.unhexlify(new_value_str[2:])[::-1] - else: - # cmd line: 0102030405060708 .... 112233ff (string) - # regs: 04030201 08070605 ... ff332211 - # BLK: 01 02 03 04 05 06 07 08 ... 11 22 33 ff - return binascii.unhexlify(new_value_str) - else: - return new_value_str - - def convert_to_bitstring(self, new_value): - if isinstance(new_value, BitArray): - return new_value - else: - if self.efuse_type.startswith("bytes"): - # new_value (bytes) = [0][1][2] ... [N] - # (original data) - # in string format = [0] [1] [2] ... [N] - # (util.hexify(data, " ")) - # in hex format = 0x[N]....[2][1][0] - # (from bitstring print(data)) - # in reg format = [3][2][1][0] ... [N][][][] - # (as it will be in the device) - # in bitstring = [N] ... [2][1][0] - # (to get a correct bitstring need to reverse new_value) - # *[x] - means a byte. - return BitArray(bytes=new_value[::-1], length=len(new_value) * 8) - else: - try: - return BitArray(self.efuse_type + "={}".format(new_value)) - except CreationError as err: - print( - "New value '{}' is not suitable for {} ({})".format( - new_value, self.name, self.efuse_type - ) - ) - raise esptool.FatalError(err) - - def check_new_value(self, bitarray_new_value): - bitarray_old_value = self.get_bitstring() | self.get_bitstring(from_read=False) - - if not bitarray_new_value.any(True) and not bitarray_old_value.any(True): - return - - if bitarray_new_value.len != bitarray_old_value.len: - raise esptool.FatalError( - "For {} efuse, the length of the new value is wrong, " - "expected {} bits, was {} bits.".format( - self.name, bitarray_old_value.len, bitarray_new_value.len - ) - ) - if ( - bitarray_new_value == bitarray_old_value - or bitarray_new_value & self.get_bitstring() == bitarray_new_value - ): - error_msg = "\tThe same value for {} ".format(self.name) - error_msg += "is already burned. Do not change the efuse." - print(error_msg) - bitarray_new_value.set(0) - elif bitarray_new_value == self.get_bitstring(from_read=False): - error_msg = "\tThe same value for {} ".format(self.name) - error_msg += "is already prepared for the burn operation." - print(error_msg) - bitarray_new_value.set(0) - else: - if self.name not in ["WR_DIS", "RD_DIS"]: - # WR_DIS, RD_DIS fields can have already set bits. - # Do not need to check below condition for them. - if bitarray_new_value | bitarray_old_value != bitarray_new_value: - error_msg = "\tNew value contains some bits that cannot be cleared " - error_msg += "(value will be {})".format( - bitarray_old_value | bitarray_new_value - ) - self.parent.print_error_msg(error_msg) - self.check_wr_rd_protect() - - def save_to_block(self, bitarray_field): - block = self.parent.blocks[self.block] - wr_bitarray_temp = block.wr_bitarray.copy() - position = wr_bitarray_temp.length - ( - self.word * 32 + self.pos + bitarray_field.len - ) - wr_bitarray_temp.overwrite(bitarray_field, pos=position) - block.wr_bitarray |= wr_bitarray_temp - - def save(self, new_value): - bitarray_field = self.convert_to_bitstring(new_value) - self.check_new_value(bitarray_field) - self.save_to_block(bitarray_field) - - def update(self, bit_array_block): - 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 - ( - self.word * 32 + self.pos + field_len - ) - self.bitarray.overwrite(bit_array_block.read(field_len), pos=0) - err_bitarray = self.parent.blocks[self.block].err_bitarray - if err_bitarray is not None: - err_bitarray.pos = err_bitarray.length - ( - self.word * 32 + self.pos + field_len - ) - self.fail = not err_bitarray.read(field_len).all(False) - else: - self.fail = self.parent.blocks[self.block].fail - self.num_errors = self.parent.blocks[self.block].num_errors - - def get_raw(self, from_read=True): - """Return the raw (unformatted) numeric value of the efuse bits - - Returns a simple integer or (for some subclasses) a bitstring. - type: int or bool -> int - type: bytes -> bytearray - """ - return self.get_bitstring(from_read).read(self.efuse_type) - - def get(self, from_read=True): - """Get a formatted version of the efuse value, suitable for display - type: int or bool -> int - type: bytes -> string "01 02 03 04 05 06 07 08 ... ". - Byte order [0] ... [N]. dump regs: 0x04030201 0x08070605 ... - """ - if self.efuse_type.startswith("bytes"): - return util.hexify(self.get_bitstring(from_read).bytes[::-1], " ") - else: - return self.get_raw(from_read) - - def get_meaning(self, from_read=True): - """Get the meaning of efuse from dict if possible, suitable for display""" - if self.dict_value: - try: - return self.dict_value[self.get_raw(from_read)] - except KeyError: - pass - return self.get(from_read) - - def get_bitstring(self, from_read=True): - if from_read: - self.bitarray.pos = 0 - return self.bitarray - else: - field_len = self.bitarray.len - block = self.parent.blocks[self.block] - block.wr_bitarray.pos = block.wr_bitarray.length - ( - self.word * 32 + self.pos + field_len - ) - return block.wr_bitarray.read(self.bitarray.len) - - 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 - - def reset(self): - # resets a efuse that is prepared for burning - bitarray_field = self.convert_to_bitstring(0) - block = self.parent.blocks[self.block] - wr_bitarray_temp = block.wr_bitarray.copy() - position = wr_bitarray_temp.length - ( - self.word * 32 + self.pos + bitarray_field.len - ) - wr_bitarray_temp.overwrite(bitarray_field, pos=position) - block.wr_bitarray = wr_bitarray_temp diff --git a/tools/esptool_py/espefuse/efuse/base_operations.py b/tools/esptool_py/espefuse/efuse/base_operations.py deleted file mode 100644 index 60f18dc5e5..0000000000 --- a/tools/esptool_py/espefuse/efuse/base_operations.py +++ /dev/null @@ -1,804 +0,0 @@ -# This file includes the common operations with eFuses for chips -# -# SPDX-FileCopyrightText: 2020-2022 Espressif Systems (Shanghai) CO LTD -# -# SPDX-License-Identifier: GPL-2.0-or-later - -import argparse -import os -import json -import sys - -from bitstring import BitStream - -import esptool - -from . import base_fields -from . import util - - -def add_common_commands(subparsers, efuses): - class ActionEfuseValuePair(argparse.Action): - def __init__(self, option_strings, dest, nargs=None, **kwargs): - self._nargs = nargs - self._choices = kwargs.get("efuse_choices") - self.efuses = kwargs.get("efuses") - del kwargs["efuse_choices"] - del kwargs["efuses"] - super(ActionEfuseValuePair, self).__init__( - option_strings, dest, nargs=nargs, **kwargs - ) - - def __call__(self, parser, namespace, values, option_string=None): - def check_efuse_name(efuse_name, efuse_list): - if efuse_name not in self._choices: - raise esptool.FatalError( - "Invalid the efuse name '{}'. " - "Available the efuse names: {}".format( - efuse_name, self._choices - ) - ) - - efuse_value_pairs = {} - if len(values) > 1: - if len(values) % 2: - raise esptool.FatalError( - "The list does not have a valid pair (name value) {}".format( - values - ) - ) - for i in range(0, len(values), 2): - efuse_name, new_value = values[i : i + 2 :] - check_efuse_name(efuse_name, self._choices) - check_arg = base_fields.CheckArgValue(self.efuses, efuse_name) - efuse_value_pairs[efuse_name] = check_arg(new_value) - else: - # For the case of compatibility, when only the efuse_name is given - # Fields with 'bitcount' and 'bool' types can be without new_value arg - efuse_name = values[0] - check_efuse_name(efuse_name, self._choices) - check_arg = base_fields.CheckArgValue(self.efuses, efuse_name) - efuse_value_pairs[efuse_name] = check_arg(None) - setattr(namespace, self.dest, efuse_value_pairs) - - burn = subparsers.add_parser( - "burn_efuse", help="Burn the efuse with the specified name" - ) - burn.add_argument( - "name_value_pairs", - help="Name of efuse field and new value pairs to burn. EFUSE_NAME: " - "[{}].".format(", ".join([e.name for e in efuses.efuses])), - action=ActionEfuseValuePair, - nargs="+", - metavar="[EFUSE_NAME VALUE]", - 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, - ) - burn.add_argument( - "--force", - help="Suppress an error to burn eFuses", - action="store_true", - ) - - read_protect_efuse = subparsers.add_parser( - "read_protect_efuse", - help="Disable readback for the efuse with the specified name", - ) - read_protect_efuse.add_argument( - "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] - + [ - 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( - "write_protect_efuse", - help="Disable writing to the efuse with the specified name", - ) - write_protect_efuse.add_argument( - "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] - + [ - 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( - "burn_block_data", - help="Burn non-key data to EFUSE blocks. " - "(Don't use this command to burn key data for Flash Encryption or " - "ESP32 Secure Boot V1, as the byte order of keys is swapped (use burn_key)).", - ) - add_force_write_always(burn_block_data) - burn_block_data.add_argument( - "--offset", "-o", help="Byte offset in the efuse block", type=int, default=0 - ) - burn_block_data.add_argument( - "block", - help="Efuse block to burn.", - action="append", - choices=efuses.BURN_BLOCK_DATA_NAMES, - ) - burn_block_data.add_argument( - "datafile", - help="File containing data to burn into the efuse block", - action="append", - type=argparse.FileType("rb"), - ) - for _ in range(0, len(efuses.BURN_BLOCK_DATA_NAMES)): - burn_block_data.add_argument( - "block", - help="Efuse block to burn.", - metavar="BLOCK", - nargs="?", - action="append", - choices=efuses.BURN_BLOCK_DATA_NAMES, - ) - burn_block_data.add_argument( - "datafile", - nargs="?", - help="File containing data to burn into the efuse block", - metavar="DATAFILE", - action="append", - type=argparse.FileType("rb"), - ) - - set_bit_cmd = subparsers.add_parser("burn_bit", help="Burn bit in the efuse block.") - add_force_write_always(set_bit_cmd) - set_bit_cmd.add_argument( - "block", help="Efuse block to burn.", choices=efuses.BURN_BLOCK_DATA_NAMES - ) - set_bit_cmd.add_argument( - "bit_number", - help="Bit number in the efuse block [0..BLK_LEN-1]", - nargs="+", - type=int, - ) - - subparsers.add_parser( - "adc_info", - help="Display information about ADC calibration data stored in efuse.", - ) - - dump_cmd = subparsers.add_parser("dump", help="Dump raw hex values of all eFuses") - dump_cmd.add_argument( - "--format", - help="Select the dump format: " - "default - usual console eFuse dump; " - "joint - all eFuse blocks are stored in one file; " - "split - each eFuse block is placed into its own file. The tool will create multiple files based on " - "the given --file_name (/path/blk.bin): blk0.bin, blk1.bin ... blkN.bin. Use the burn_block_data cmd " - "to write it back to another chip.", - choices=["default", "split", "joint"], - default="default", - ) - dump_cmd.add_argument( - "--file_name", - help="The path to the file in which to save the dump, if not specified, output to the console.", - default=sys.stdout, - ) - - summary_cmd = subparsers.add_parser( - "summary", help="Print human-readable summary of efuse values" - ) - summary_cmd.add_argument( - "--format", - help="Select the summary format", - choices=["summary", "json", "value_only"], - default="summary", - ) - summary_cmd.add_argument( - "--file", - help="File to save the efuse summary", - type=argparse.FileType("w"), - default=sys.stdout, - ) - summary_cmd.add_argument( - "efuses_to_show", - help="The efuses to show. If not provided, all efuses will be shown.", - nargs="*", - ) - - execute_scripts = subparsers.add_parser( - "execute_scripts", help="Executes scripts to burn at one time." - ) - execute_scripts.add_argument( - "scripts", - help="The special format of python scripts.", - nargs="+", - type=argparse.FileType("r"), - ) - execute_scripts.add_argument( - "--index", - help="integer index. " - "It allows to retrieve unique data per chip from configfiles " - "and then burn them (ex. CUSTOM_MAC, UNIQUE_ID).", - type=int, - ) - execute_scripts.add_argument( - "--configfiles", - help="List of configfiles with data", - nargs="?", - action="append", - type=argparse.FileType("r"), - ) - - check_error_cmd = subparsers.add_parser("check_error", help="Checks eFuse errors") - check_error_cmd.add_argument( - "--recovery", - help="Recovery of BLOCKs after encoding errors", - action="store_true", - ) - - -def add_force_write_always(p): - p.add_argument( - "--force-write-always", - help="Write the efuse even if it looks like it's 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.", - action="store_true", - ) - - -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 or json summary of efuse contents""" - ROW_FORMAT = "%-50s %-50s%s = %s %s %s" - human_output = args.format in ["summary", "value_only"] - value_only = args.format == "value_only" - if value_only and len(args.efuses_to_show) != 1: - raise esptool.FatalError( - "The 'value_only' format can be used exactly for one efuse." - ) - do_filtering = bool(args.efuses_to_show) - json_efuse = {} - summary_efuse = [] - if args.file != sys.stdout: - print("Saving efuse values to " + args.file.name) - if human_output and not value_only: - summary_efuse.append( - ROW_FORMAT.replace("-50", "-12") - % ( - "EFUSE_NAME (Block)", - "Description", - "", - "[Meaningful Value]", - "[Readable/Writeable]", - "(Hex Value)", - ) - ) - summary_efuse.append("-" * 88) - for category in sorted(set(e.category for e in efuses), key=lambda c: c.title()): - if human_output and not value_only: - summary_efuse.append(f"{category.title()} fuses:") - for e in (e for e in efuses if e.category == category): - if e.efuse_type.startswith("bytes"): - raw = "" - else: - raw = "({})".format(e.get_bitstring()) - (readable, writeable) = (e.is_readable(), e.is_writeable()) - if readable and writeable: - perms = "R/W" - elif readable: - perms = "R/-" - elif writeable: - perms = "-/W" - else: - perms = "-/-" - base_value = e.get_meaning() - value = str(base_value) - if not readable: - 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 - and (not do_filtering or e.name in args.efuses_to_show) - and not value_only - ): - summary_efuse.append( - ROW_FORMAT - % ( - e.get_info(), - e.description[:50], - "\n " if len(value) > 20 else "", - value, - perms, - raw, - ) - ) - desc_len = len(e.description[50:]) - if desc_len: - desc_len += 50 - for i in range(50, desc_len, 50): - summary_efuse.append( - f"{'':<50} {e.description[i : (50 + i)]:<50}" - ) - elif human_output and value_only and e.name in args.efuses_to_show: - summary_efuse.append(f"{value}") - elif args.format == "json" and ( - not do_filtering or e.name in args.efuses_to_show - ): - json_efuse[e.name] = { - "name": e.name, - "value": base_value if readable else value, - "readable": readable, - "writeable": writeable, - "description": e.description, - "category": e.category, - "block": e.block, - "word": e.word, - "pos": e.pos, - "efuse_type": e.efuse_type, - "bit_len": e.bit_len, - } - if human_output and not value_only: - # Remove empty category if efuses are filtered and there are none to show - if do_filtering and summary_efuse[-1] == f"{category.title()} fuses:": - summary_efuse.pop() - else: - summary_efuse.append("") - if human_output and not value_only: - summary_efuse.append(efuses.summary()) - warnings = efuses.get_coding_scheme_warnings() - if warnings: - summary_efuse.append( - "WARNING: Coding scheme has encoding bit error warnings" - ) - if human_output: - for line in summary_efuse: - print(line, file=args.file) - if args.file != sys.stdout: - args.file.close() - print("Done") - elif args.format == "json": - json.dump(json_efuse, args.file, sort_keys=True, indent=4) - print("") - - -def dump(esp, efuses, args): - """Dump raw efuse data registers""" - dump_file = args.file_name - to_console = args.file_name == sys.stdout - - def output_block_to_file(block, f, to_console): - block_dump = BitStream(block.get_bitstring()) - block_dump.byteswap() - if to_console: - f.write(block_dump.hex + "\n") - else: - block_dump.tofile(f) - - if args.format == "default": - if to_console: - # for "espefuse.py dump" cmd - for block in efuses.blocks: - block.print_block(block.get_bitstring(), "dump", debug=True) - return - else: - # for back compatibility to support "espefuse.py dump --file_name dump.bin" - args.format = "split" - - if args.format == "split": - # each efuse block is placed into its own file - for block in efuses.blocks: - if not to_console: - file_dump_name = args.file_name - fname, fextension = os.path.splitext(file_dump_name) - file_dump_name = f"{fname}{block.id}{fextension}" - print(f"Dump efuse block{block.id} -> {file_dump_name}") - dump_file = open(file_dump_name, "wb") - output_block_to_file(block, dump_file, to_console) - if not to_console: - dump_file.close() - elif args.format == "joint": - # all efuse blocks are stored in one file - if not to_console: - print(f"Dump efuse blocks -> {args.file_name}") - dump_file = open(args.file_name, "wb") - for block in efuses.blocks: - output_block_to_file(block, dump_file, to_console) - if not to_console: - dump_file.close() - - -def burn_efuse(esp, efuses, args): - def print_attention(blocked_efuses_after_burn): - if len(blocked_efuses_after_burn): - print( - " ATTENTION! This BLOCK uses NOT the NONE coding scheme " - "and after 'BURN', these efuses can not be burned in the feature:" - ) - for i in range(0, len(blocked_efuses_after_burn), 5): - print( - " ", - "".join("{}".format(blocked_efuses_after_burn[i : i + 5 :])), - ) - - efuse_name_list = [name for name in args.name_value_pairs.keys()] - burn_efuses_list = [efuses[name] for name in efuse_name_list] - old_value_list = [efuses[name].get_raw() for name in efuse_name_list] - new_value_list = [value for value in args.name_value_pairs.values()] - util.check_duplicate_name_in_list(efuse_name_list) - - attention = "" - print("The efuses to burn:") - for block in efuses.blocks: - burn_list_a_block = [e for e in burn_efuses_list if e.block == block.id] - if len(burn_list_a_block): - print(" from BLOCK%d" % (block.id)) - for field in burn_list_a_block: - print(" - %s" % (field.name)) - if ( - efuses.blocks[field.block].get_coding_scheme() - != efuses.REGS.CODING_SCHEME_NONE - ): - using_the_same_block_names = [ - e.name for e in efuses if e.block == field.block - ] - wr_names = [e.name for e in burn_list_a_block] - blocked_efuses_after_burn = [ - name - for name in using_the_same_block_names - if name not in wr_names - ] - attention = " (see 'ATTENTION!' above)" - if attention: - print_attention(blocked_efuses_after_burn) - - print("\nBurning efuses{}:".format(attention)) - for efuse, new_value in zip(burn_efuses_list, new_value_list): - print( - "\n - '{}' ({}) {} -> {}".format( - efuse.name, - efuse.description, - efuse.get_bitstring(), - efuse.convert_to_bitstring(new_value), - ) - ) - efuse.save(new_value) - - print() - if "ENABLE_SECURITY_DOWNLOAD" in efuse_name_list: - print( - "ENABLE_SECURITY_DOWNLOAD -> 1: eFuses will not be read back " - "for confirmation because this mode disables " - "any SRAM and register operations." - ) - print(" espefuse will not work.") - print(" esptool can read/write only flash.") - - if "DIS_DOWNLOAD_MODE" in efuse_name_list: - print( - "DIS_DOWNLOAD_MODE -> 1: eFuses will not be read back for " - "confirmation because this mode disables any communication with the chip." - ) - print( - " espefuse/esptool will not work because " - "they will not be able to connect to the chip." - ) - - if ( - esp.CHIP_NAME == "ESP32" - and esp.get_chip_revision() >= 300 - and "UART_DOWNLOAD_DIS" in efuse_name_list - ): - print( - "UART_DOWNLOAD_DIS -> 1: eFuses will be read for confirmation, " - "but after that connection to the chip will become impossible." - ) - print(" espefuse/esptool will not work.") - - if efuses.is_efuses_incompatible_for_burn(): - if args.force: - print("Ignore incompatible eFuse settings.") - else: - raise esptool.FatalError( - "Incompatible eFuse settings detected, abort. (use --force flag to skip it)." - ) - - if not efuses.burn_all(check_batch_mode=True): - return - - print("Checking efuses...") - raise_error = False - for efuse, old_value, new_value in zip( - burn_efuses_list, old_value_list, new_value_list - ): - if not efuse.is_readable(): - print( - "Efuse %s is read-protected. Read back the burn value is not possible." - % efuse.name - ) - else: - new_value = efuse.convert_to_bitstring(new_value) - burned_value = efuse.get_bitstring() - if burned_value != new_value: - print( - burned_value, - "->", - new_value, - "Efuse %s failed to burn. Protected?" % efuse.name, - ) - raise_error = True - if raise_error: - raise esptool.FatalError("The burn was not successful.") - else: - print("Successful") - - -def read_protect_efuse(esp, efuses, args): - util.check_duplicate_name_in_list(args.efuse_name) - - for efuse_name in args.efuse_name: - efuse = efuses[efuse_name] - if not efuse.is_readable(): - print("Efuse %s is already read protected" % efuse.name) - else: - if esp.CHIP_NAME == "ESP32": - if ( - efuse_name == "BLOCK2" - and not efuses["ABS_DONE_0"].get() - and esp.get_chip_revision() >= 300 - ): - if efuses["ABS_DONE_1"].get(): - raise esptool.FatalError( - "Secure Boot V2 is on (ABS_DONE_1 = True), " - "BLOCK2 must be readable, stop this operation!" - ) - else: - print( - "If Secure Boot V2 is used, BLOCK2 must be readable, " - "please stop this operation!" - ) - elif esp.CHIP_NAME == "ESP32-C2": - error = ( - not efuses["XTS_KEY_LENGTH_256"].get() - and efuse_name == "BLOCK_KEY0" - ) - error |= efuses["SECURE_BOOT_EN"].get() and efuse_name in [ - "BLOCK_KEY0", - "BLOCK_KEY0_HI_128", - ] - if error: - raise esptool.FatalError( - "%s must be readable, stop this operation!" % efuse_name - ) - else: - for block in efuses.Blocks.BLOCKS: - block = efuses.Blocks.get(block) - if block.name == efuse_name and block.key_purpose is not None: - if not efuses[block.key_purpose].need_rd_protect( - efuses[block.key_purpose].get() - ): - raise esptool.FatalError( - "%s must be readable, stop this operation!" % efuse_name - ) - break - # make full list of which efuses will be disabled - # (ie share a read disable bit) - all_disabling = [ - e for e in efuses if e.read_disable_bit == efuse.read_disable_bit - ] - names = ", ".join(e.name for e in all_disabling) - print( - "Permanently read-disabling efuse%s %s" - % ("s" if len(all_disabling) > 1 else "", names) - ) - efuse.disable_read() - - if not efuses.burn_all(check_batch_mode=True): - return - - print("Checking efuses...") - raise_error = False - for efuse_name in args.efuse_name: - efuse = efuses[efuse_name] - if efuse.is_readable(): - print("Efuse %s is not read-protected." % efuse.name) - raise_error = True - if raise_error: - raise esptool.FatalError("The burn was not successful.") - else: - print("Successful") - - -def write_protect_efuse(esp, efuses, args): - util.check_duplicate_name_in_list(args.efuse_name) - for efuse_name in args.efuse_name: - efuse = efuses[efuse_name] - if not efuse.is_writeable(): - print("Efuse %s is already write protected" % efuse.name) - else: - # make full list of which efuses will be disabled - # (ie share a write disable bit) - all_disabling = [ - e for e in efuses if e.write_disable_bit == efuse.write_disable_bit - ] - names = ", ".join(e.name for e in all_disabling) - print( - "Permanently write-disabling efuse%s %s" - % ("s" if len(all_disabling) > 1 else "", names) - ) - efuse.disable_write() - - if not efuses.burn_all(check_batch_mode=True): - return - - print("Checking efuses...") - raise_error = False - for efuse_name in args.efuse_name: - efuse = efuses[efuse_name] - if efuse.is_writeable(): - print("Efuse %s is not write-protected." % efuse.name) - raise_error = True - if raise_error: - raise esptool.FatalError("The burn was not successful.") - else: - print("Successful") - - -def burn_block_data(esp, efuses, args): - block_name_list = args.block[ - 0 : len([name for name in args.block if name is not None]) : - ] - datafile_list = args.datafile[ - 0 : len([name for name in args.datafile if name is not None]) : - ] - efuses.force_write_always = args.force_write_always - - util.check_duplicate_name_in_list(block_name_list) - if args.offset and len(block_name_list) > 1: - raise esptool.FatalError( - "The 'offset' option is not applicable when a few blocks are passed. " - "With 'offset', should only one block be used." - ) - else: - offset = args.offset - if offset: - num_block = efuses.get_index_block_by_name(block_name_list[0]) - block = efuses.blocks[num_block] - num_bytes = block.get_block_len() - if offset >= num_bytes: - raise esptool.FatalError( - "Invalid offset: the block%d only holds %d bytes." - % (block.id, num_bytes) - ) - if len(block_name_list) != len(datafile_list): - raise esptool.FatalError( - "The number of block_name (%d) and datafile (%d) should be the same." - % (len(block_name_list), len(datafile_list)) - ) - - for block_name, datafile in zip(block_name_list, datafile_list): - num_block = efuses.get_index_block_by_name(block_name) - block = efuses.blocks[num_block] - data = datafile.read() - num_bytes = block.get_block_len() - if offset != 0: - data = (b"\x00" * offset) + data - data = data + (b"\x00" * (num_bytes - len(data))) - if len(data) != num_bytes: - raise esptool.FatalError( - "Data does not fit: the block%d size is %d bytes, " - "data file is %d bytes, offset %d" - % (block.id, num_bytes, len(data), offset) - ) - print( - "[{:02}] {:20} size={:02} bytes, offset={:02} - > [{}].".format( - block.id, block.name, len(data), offset, util.hexify(data, " ") - ) - ) - block.save(data) - - if not efuses.burn_all(check_batch_mode=True): - return - print("Successful") - - -def burn_bit(esp, efuses, args): - efuses.force_write_always = args.force_write_always - num_block = efuses.get_index_block_by_name(args.block) - block = efuses.blocks[num_block] - data_block = BitStream(block.get_block_len() * 8) - data_block.set(0) - try: - data_block.set(True, args.bit_number) - except IndexError: - raise esptool.FatalError( - "%s has bit_number in [0..%d]" % (args.block, data_block.len - 1) - ) - data_block.reverse() - print( - "bit_number: " - "[%-03d]........................................................[0]" - % (data_block.len - 1) - ) - print("BLOCK%-2d :" % block.id, data_block) - block.print_block(data_block, "regs_to_write", debug=True) - block.save(data_block.bytes[::-1]) - - if not efuses.burn_all(check_batch_mode=True): - return - print("Successful") - - -def get_error_summary(efuses): - efuses.get_coding_scheme_warnings() - error_in_blocks = any(blk.fail or blk.num_errors != 0 for blk in efuses.blocks) - 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/tools/esptool_py/espefuse/efuse/csv_table_parser.py b/tools/esptool_py/espefuse/efuse/csv_table_parser.py deleted file mode 100644 index 4bebbb02ab..0000000000 --- a/tools/esptool_py/espefuse/efuse/csv_table_parser.py +++ /dev/null @@ -1,266 +0,0 @@ -# This file helps to parse CSV eFuse tables -# -# SPDX-FileCopyrightText: 2024 Espressif Systems (Shanghai) CO LTD -# -# SPDX-License-Identifier: GPL-2.0-or-later - -import os -import re -import sys - - -class CSVFuseTable(list): - @classmethod - def from_csv(cls, csv_contents): - res = CSVFuseTable() - lines = csv_contents.splitlines() - - def expand_vars(f): - f = os.path.expandvars(f) - m = re.match(r"(? 1) - for dname in duplicates: - i_count = 0 - for p in res: - if p.field_name != dname: - continue - if len(duplicates.intersection([p.field_name])) != 0: - p.field_name = f"{p.field_name}_{i_count}" - if p.alt_names: - p.alt_names = f"{p.alt_names}_{i_count}" - i_count += 1 - else: - i_count = 0 - - for p in res: - p.field_name = p.field_name.replace(".", "_") - if p.alt_names: - p.alt_names = p.alt_names.replace(".", "_") - res.verify_duplicate_name() - return res - - def verify_duplicate_name(self): - # check on duplicate name - names = [p.field_name for p in self] - names += [name.replace(".", "_") for name in names if "." in name] - duplicates = set(n for n in names if names.count(n) > 1) - - # print sorted duplicate partitions by name - if len(duplicates) != 0: - fl_error = False - for p in self: - field_name = p.field_name + p.group - if field_name != "" and len(duplicates.intersection([field_name])) != 0: - fl_error = True - print( - f"Field at {p.field_name}, {p.efuse_block}, " - f"{p.bit_start}, {p.bit_count} have duplicate field_name" - ) - if fl_error is True: - raise InputError("Field names must be unique") - - def check_struct_field_name(self): - # check that structured fields have a root field - for p in self: - if "." in p.field_name: - name = "" - for sub in p.field_name.split(".")[:-1]: - name = sub if name == "" else name + "." + sub - missed_name = True - for d in self: - if ( - p is not d - and p.efuse_block == d.efuse_block - and name == d.field_name - ): - missed_name = False - if missed_name: - raise InputError(f"{name} is not found") - - def verify(self, type_table=None): - def check(p, n): - left = n.bit_start - right = n.bit_start + n.bit_count - 1 - start = p.bit_start - end = p.bit_start + p.bit_count - 1 - if left <= start <= right: - if left <= end <= right: - return "included in" # [n [p...p] n] - return "intersected with" # [n [p..n]..p] - if left <= end <= right: - return "intersected with" # [p..[n..p] n] - if start <= left and right <= end: - return "wraps" # [p [n...n] p] - return "ok" # [p] [n] or [n] [p] - - def print_error(p, n, state): - raise InputError( - f"Field at {p.field_name}, {p.efuse_block}, {p.bit_start}, {p.bit_count} {state} {n.field_name}, {n.efuse_block}, {n.bit_start}, {n.bit_count}" - ) - - for p in self: - p.verify(type_table) - - self.verify_duplicate_name() - if type_table != "custom_table": - # check will be done for common and custom tables together - self.check_struct_field_name() - - # check for overlaps - for p in self: - for n in self: - if p is not n and p.efuse_block == n.efuse_block: - state = check(p, n) - if state != "ok": - if "." in p.field_name: - name = "" - for sub in p.field_name.split("."): - name = sub if name == "" else name + "." + sub - for d in self: - if ( - p is not d - and p.efuse_block == d.efuse_block - and name == d.field_name - ): - state = check(p, d) - if state == "included in": - break - elif state != "intersected with": - state = "out of range" - print_error(p, d, state) - continue - elif "." in n.field_name: - continue - print_error(p, n, state) - - -class FuseDefinition(object): - def __init__(self): - self.field_name = "" - self.group = "" - self.efuse_block = "" - self.bit_start = None - self.bit_count = None - self.define = None - self.comment = "" - self.alt_names = "" - self.MAX_BITS_OF_BLOCK = 256 - - @classmethod - def from_csv(cls, line): - """Parse a line from the CSV""" - line_w_defaults = line + ",,,," - fields = [f.strip() for f in line_w_defaults.split(",")] - - res = FuseDefinition() - res.field_name = fields[0] - res.efuse_block = res.parse_block(fields[1]) - res.bit_start = res.parse_num(fields[2]) - res.bit_count = res.parse_bit_count(fields[3]) - if res.bit_count is None or res.bit_count == 0: - raise InputError("Field bit_count can't be empty") - res.comment = fields[4].rstrip("\\").rstrip() - res.comment += f" ({res.bit_start}-{res.bit_start + res.bit_count - 1})" - res.alt_names = res.get_alt_names(res.comment) - return res - - def parse_num(self, strval): - if strval == "": - return None - return self.parse_int(strval) - - def parse_bit_count(self, strval): - if strval == "MAX_BLK_LEN": - self.define = strval - return self.MAX_BITS_OF_BLOCK - else: - return self.parse_num(strval) - - def parse_int(self, v): - try: - return int(v, 0) - except ValueError: - raise InputError(f"Invalid field value {v}") - - def parse_block(self, strval): - if strval == "": - raise InputError("Field 'efuse_block' can't be left empty.") - return self.parse_int(strval.lstrip("EFUSE_BLK")) - - def verify(self, type_table): - if self.efuse_block is None: - raise ValidationError(self, "efuse_block field is not set") - if self.bit_count is None: - raise ValidationError(self, "bit_count field is not set") - max_bits = self.MAX_BITS_OF_BLOCK - if self.bit_start + self.bit_count > max_bits: - raise ValidationError( - self, - f"The field is outside the boundaries(max_bits = {max_bits}) of the {self.efuse_block} block", - ) - - def get_bit_count(self, check_define=True): - if check_define is True and self.define is not None: - return self.define - else: - return self.bit_count - - def get_alt_names(self, comment): - result = re.search(r"^\[(.*?)\]", comment) - if result: - return result.group(1) - return "" - - -class InputError(RuntimeError): - def __init__(self, e): - super(InputError, self).__init__(e) - - -class ValidationError(InputError): - def __init__(self, p, message): - super(ValidationError, self).__init__( - f"Entry {p.field_name} invalid: {message}" - ) diff --git a/tools/esptool_py/espefuse/efuse/emulate_efuse_controller_base.py b/tools/esptool_py/espefuse/efuse/emulate_efuse_controller_base.py deleted file mode 100644 index 232bfaad83..0000000000 --- a/tools/esptool_py/espefuse/efuse/emulate_efuse_controller_base.py +++ /dev/null @@ -1,225 +0,0 @@ -# This file describes eFuses controller for ESP32 chip -# -# SPDX-FileCopyrightText: 2020-2022 Espressif Systems (Shanghai) CO LTD -# -# SPDX-License-Identifier: GPL-2.0-or-later - -import re - -from bitstring import BitStream - - -class EmulateEfuseControllerBase(object): - """The class for virtual efuse operations. Using for HOST_TEST.""" - - CHIP_NAME = "" - mem = None - debug = False - Blocks = None - Fields = None - REGS = None - - def __init__(self, efuse_file=None, debug=False): - self.debug = debug - self.efuse_file = efuse_file - if self.efuse_file: - try: - self.mem = BitStream( - bytes=open(self.efuse_file, "rb").read(), - length=self.REGS.EFUSE_MEM_SIZE * 8, - ) - except (ValueError, FileNotFoundError): - # the file is empty or does not fit the length. - self.mem = BitStream(length=self.REGS.EFUSE_MEM_SIZE * 8) - self.mem.set(0) - self.mem.tofile(open(self.efuse_file, "a+b")) - else: - # efuse_file is not provided - # it means we do not want to keep the result of efuse operations - self.mem = BitStream(self.REGS.EFUSE_MEM_SIZE * 8) - self.mem.set(0) - - """ esptool method start >> """ - - 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})" - - def get_chip_revision(self): - return self.get_major_chip_version() * 100 + self.get_minor_chip_version() - - def read_efuse(self, n, block=0): - """Read the nth word of the ESP3x EFUSE region.""" - blk = self.Blocks.get(self.Blocks.BLOCKS[block]) - return self.read_reg(blk.rd_addr + (4 * n)) - - def read_reg(self, addr): - self.mem.pos = self.mem.length - ((addr - self.REGS.DR_REG_EFUSE_BASE) * 8 + 32) - return self.mem.read("uint:32") - - def write_reg(self, addr, value, mask=0xFFFFFFFF, delay_us=0, delay_after_us=0): - self.mem.pos = self.mem.length - ((addr - self.REGS.DR_REG_EFUSE_BASE) * 8 + 32) - self.mem.overwrite("uint:32={}".format(value & mask)) - self.handle_writing_event(addr, value) - - def update_reg(self, addr, mask, new_val): - position = self.mem.length - ((addr - self.REGS.DR_REG_EFUSE_BASE) * 8 + 32) - self.mem.pos = position - cur_val = self.mem.read("uint:32") - self.mem.pos = position - self.mem.overwrite("uint:32={}".format(cur_val | (new_val & mask))) - - def write_efuse(self, n, value, block=0): - """Write the nth word of the ESP3x EFUSE region.""" - blk = self.Blocks.get(self.Blocks.BLOCKS[block]) - self.write_reg(blk.wr_addr + (4 * n), value) - - """ << esptool method end """ - - def handle_writing_event(self, addr, value): - self.save_to_file() - - def save_to_file(self): - if self.efuse_file: - with open(self.efuse_file, "wb") as f: - self.mem.tofile(f) - - def handle_coding_scheme(self, blk, data): - return data - - def copy_blocks_wr_regs_to_rd_regs(self, updated_block=None): - for b in reversed(self.Blocks.BLOCKS): - blk = self.Blocks.get(b) - if updated_block is not None: - if blk.id != updated_block: - continue - data = self.read_block(blk.id, wr_regs=True) - if self.debug: - print(blk.name, data.hex) - plain_data = self.handle_coding_scheme(blk, data) - plain_data = self.check_wr_protection_area(blk.id, plain_data) - self.update_block(blk, plain_data) - - def clean_blocks_wr_regs(self): - for b in self.Blocks.BLOCKS: - blk = self.Blocks.get(b) - for offset in range(0, blk.len * 4, 4): - wr_addr = blk.wr_addr + offset - self.write_reg(wr_addr, 0) - - def read_field(self, name, bitstring=True): - for field in self.Fields.EFUSES: - if field.name == name: - self.read_block(field.block) - block = self.read_block(field.block) - if field.type.startswith("bool"): - field_len = 1 - else: - field_len = int(re.search(r"\d+", field.type).group()) - if field.type.startswith("bytes"): - field_len *= 8 - block.pos = block.length - (field.word * 32 + field.pos + field_len) - if bitstring: - return block.read(field_len) - else: - return block.read(field.type) - return None - - def get_bitlen_of_block(self, blk, wr=False): - return 32 * blk.len - - def read_block(self, idx, wr_regs=False): - block = None - for b in self.Blocks.BLOCKS: - blk = self.Blocks.get(b) - if blk.id == idx: - blk_len_bits = self.get_bitlen_of_block(blk, wr=wr_regs) - addr = blk.wr_addr if wr_regs else blk.rd_addr - self.mem.pos = self.mem.length - ( - (addr - self.REGS.DR_REG_EFUSE_BASE) * 8 + blk_len_bits - ) - block = self.mem.read(blk_len_bits) - break - return block - - def update_block(self, blk, wr_data): - wr_data = self.read_block(blk.id) | wr_data - self.overwrite_mem_from_block(blk, wr_data) - - def overwrite_mem_from_block(self, blk, wr_data): - self.mem.pos = self.mem.length - ( - (blk.rd_addr - self.REGS.DR_REG_EFUSE_BASE) * 8 + wr_data.len - ) - self.mem.overwrite(wr_data) - - def check_wr_protection_area(self, num_blk, wr_data): - # checks fields which have the write protection bit. - # if the write protection bit is set, we need to protect that area from changes. - write_disable_bit = self.read_field("WR_DIS", bitstring=False) - mask_wr_data = BitStream(len(wr_data)) - mask_wr_data.set(0) - blk = self.Blocks.get(self.Blocks.BLOCKS[num_blk]) - if blk.write_disable_bit is not None and write_disable_bit & ( - 1 << blk.write_disable_bit - ): - mask_wr_data.set(1) - else: - 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 - ): - data = self.read_field(field.name) - data.set(1) - mask_wr_data.pos = mask_wr_data.length - ( - field.word * 32 + field.pos + data.len - ) - mask_wr_data.overwrite(data) - mask_wr_data.invert() - return wr_data & mask_wr_data - - def check_rd_protection_area(self): - # checks fields which have the read protection bits. - # if the read protection bit is set then we need to reset this field to 0. - read_disable_bit = self.read_field("RD_DIS", bitstring=False) - for b in self.Blocks.BLOCKS: - blk = self.Blocks.get(b) - block = self.read_block(blk.id) - if blk.read_disable_bit is not None and read_disable_bit & ( - 1 << blk.read_disable_bit - ): - block.set(0) - else: - for field in self.Fields.EFUSES: - if ( - blk.id == field.block - and field.read_disable_bit is not None - and read_disable_bit & (1 << field.read_disable_bit) - ): - raw_data = self.read_field(field.name) - raw_data.set(0) - block.pos = block.length - ( - field.word * 32 + field.pos + raw_data.length - ) - block.overwrite(BitStream(raw_data.length)) - self.overwrite_mem_from_block(blk, block) - - def clean_mem(self): - self.mem.set(0) - if self.efuse_file: - with open(self.efuse_file, "wb") as f: - self.mem.tofile(f) - - -class FatalError(RuntimeError): - """ - Wrapper class for runtime errors that aren't caused by internal bugs - """ - - def __init__(self, message): - RuntimeError.__init__(self, message) - - @staticmethod - def WithResult(message, result): - return FatalError(result) diff --git a/tools/esptool_py/espefuse/efuse/esp32/__init__.py b/tools/esptool_py/espefuse/efuse/esp32/__init__.py deleted file mode 100644 index a3b55a8023..0000000000 --- a/tools/esptool_py/espefuse/efuse/esp32/__init__.py +++ /dev/null @@ -1,3 +0,0 @@ -from . import operations -from .emulate_efuse_controller import EmulateEfuseController -from .fields import EspEfuses diff --git a/tools/esptool_py/espefuse/efuse/esp32/emulate_efuse_controller.py b/tools/esptool_py/espefuse/efuse/esp32/emulate_efuse_controller.py deleted file mode 100644 index 03011fa59f..0000000000 --- a/tools/esptool_py/espefuse/efuse/esp32/emulate_efuse_controller.py +++ /dev/null @@ -1,140 +0,0 @@ -# This file describes eFuses controller for ESP32 chip -# -# SPDX-FileCopyrightText: 2020-2022 Espressif Systems (Shanghai) CO LTD -# -# SPDX-License-Identifier: GPL-2.0-or-later - -import time - -from .mem_definition import EfuseDefineBlocks, EfuseDefineFields, EfuseDefineRegisters -from ..emulate_efuse_controller_base import EmulateEfuseControllerBase, FatalError - - -class EmulateEfuseController(EmulateEfuseControllerBase): - """The class for virtual efuse operations. Using for HOST_TEST.""" - - CHIP_NAME = "ESP32" - mem = None - debug = False - - def __init__(self, efuse_file=None, debug=False): - self.Blocks = EfuseDefineBlocks - self.Fields = EfuseDefineFields(None) - self.REGS = EfuseDefineRegisters - super(EmulateEfuseController, self).__init__(efuse_file, debug) - - """ esptool method start >> """ - - def get_major_chip_version(self): - return 3 - - def get_minor_chip_version(self): - return 0 - - def get_crystal_freq(self): - return 40 # MHz (common for all chips) - - def read_reg(self, addr): - if addr == self.REGS.APB_CTL_DATE_ADDR: - return self.REGS.APB_CTL_DATE_V << self.REGS.APB_CTL_DATE_S - else: - return super(EmulateEfuseController, self).read_reg(addr) - - """ << esptool method end """ - - def send_burn_cmd(self): - def wait_idle(): - deadline = time.time() + self.REGS.EFUSE_BURN_TIMEOUT - while time.time() < deadline: - if self.read_reg(self.REGS.EFUSE_REG_CMD) == 0: - return - raise FatalError( - "Timed out waiting for Efuse controller command to complete" - ) - - self.write_reg(self.REGS.EFUSE_REG_CMD, self.REGS.EFUSE_CMD_WRITE) - wait_idle() - self.write_reg(self.REGS.EFUSE_REG_CONF, self.REGS.EFUSE_CONF_READ) - self.write_reg(self.REGS.EFUSE_REG_CMD, self.REGS.EFUSE_CMD_READ) - wait_idle() - - def handle_writing_event(self, addr, value): - if addr == self.REGS.EFUSE_REG_CMD: - if value == self.REGS.EFUSE_CMD_WRITE: - self.write_reg(addr, 0) - elif value == self.REGS.EFUSE_CMD_READ: - self.copy_blocks_wr_regs_to_rd_regs() - self.clean_blocks_wr_regs() - self.check_rd_protection_area() - self.write_reg(addr, 0) - self.save_to_file() - - def read_raw_coding_scheme(self): - coding_scheme = ( - self.read_efuse(self.REGS.EFUSE_CODING_SCHEME_WORD) - & self.REGS.EFUSE_CODING_SCHEME_MASK - ) - if coding_scheme == self.REGS.CODING_SCHEME_NONE_RECOVERY: - return self.REGS.CODING_SCHEME_NONE - else: - return coding_scheme - - def write_raw_coding_scheme(self, value): - self.write_efuse( - self.REGS.EFUSE_CODING_SCHEME_WORD, - value & self.REGS.EFUSE_CODING_SCHEME_MASK, - ) - self.send_burn_cmd() - if value != self.read_raw_coding_scheme(): - raise FatalError( - "Error during a burning process to set the new coding scheme" - ) - print("Set coding scheme = %d" % self.read_raw_coding_scheme()) - - def get_bitlen_of_block(self, blk, wr=False): - if blk.id == 0: - return 32 * blk.len - else: - coding_scheme = self.read_raw_coding_scheme() - if coding_scheme == self.REGS.CODING_SCHEME_NONE: - return 32 * blk.len - elif coding_scheme == self.REGS.CODING_SCHEME_34: - if wr: - return 32 * 8 - else: - return 32 * blk.len * 3 // 4 - else: - raise FatalError( - "The {} coding scheme is not supported".format(coding_scheme) - ) - - def handle_coding_scheme(self, blk, data): - # it verifies the coding scheme part of data and returns just data - if blk.id != 0 and self.read_raw_coding_scheme() == self.REGS.CODING_SCHEME_34: - # CODING_SCHEME 3/4 applied only for BLK1..3 - # Takes 24 byte sequence to be represented in 3/4 encoding, - # returns 8 words suitable for writing "encoded" to an efuse block - data.pos = 0 - for _ in range(0, 4): - xor_res = 0 - mul_res = 0 - chunk_data = data.readlist("8*uint:8") - chunk_data = chunk_data[::-1] - for i in range(0, 6): - byte_data = chunk_data[i] - xor_res ^= byte_data - mul_res += (i + 1) * bin(byte_data).count("1") - if xor_res != chunk_data[6] or mul_res != chunk_data[7]: - print( - "xor_res ", - xor_res, - chunk_data[6], - "mul_res", - mul_res, - chunk_data[7], - ) - raise FatalError("Error in coding scheme data") - # cut the coded data - for i in range(0, 4): - del data[i * 6 * 8 : (i * 6 * 8) + 16] - return data diff --git a/tools/esptool_py/espefuse/efuse/esp32/fields.py b/tools/esptool_py/espefuse/efuse/esp32/fields.py deleted file mode 100644 index c1a625bcb2..0000000000 --- a/tools/esptool_py/espefuse/efuse/esp32/fields.py +++ /dev/null @@ -1,477 +0,0 @@ -# This file describes eFuses for ESP32 chip -# -# SPDX-FileCopyrightText: 2020-2022 Espressif Systems (Shanghai) CO LTD -# -# SPDX-License-Identifier: GPL-2.0-or-later - -import binascii -import struct -import time - -import esptool - -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 the same as len of a block. - return self.len - - def __init__(self, parent, param, skip_read=False): - if skip_read: - parent.coding_scheme = parent.REGS.CODING_SCHEME_NONE - else: - if parent.coding_scheme is None: - 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 self.get_coding_scheme() == self.parent.REGS.CODING_SCHEME_34: - # CODING_SCHEME 3/4 applied only for BLK1..3 - # Takes 24 byte sequence to be represented in 3/4 encoding, - # returns 8 words suitable for writing "encoded" to an efuse block - if len(data) != 24: - raise esptool.FatalError("Should take 24 bytes for 3/4 encoding.") - data = data[:24] - outbits = b"" - while len(data) > 0: # process in chunks of 6 bytes - bits = data[0:6] - data = data[6:] - xor_res = 0 - mul_res = 0 - index = 1 - for b in struct.unpack("B" * 6, bits): - xor_res ^= b - mul_res += index * util.popcnt(b) - index += 1 - outbits += bits - outbits += struct.pack("BB", xor_res, mul_res) - words = struct.unpack("<" + "I" * (len(outbits) // 4), outbits) - # returns 8 words - else: - # CODING_SCHEME NONE applied for BLK0 and BLK1..3 - # BLK0 len = 7 words, BLK1..3 len = 8 words. - words = struct.unpack("<" + ("I" * (len(data) // 4)), data) - # returns 7 words for BLK0 or 8 words for BLK1..3 - 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, - extend_efuse_table=None, - ): - self.Blocks = EfuseDefineBlocks() - self.Fields = EfuseDefineFields(extend_efuse_table) - 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": - raise esptool.FatalError( - "Expected the 'esp' param for ESP32 chip but got for '%s'." - % (esp.CHIP_NAME) - ) - 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] - if skip_connect: - self.efuses += [ - EfuseField.convert(self, efuse) for efuse in self.Fields.KEYBLOCKS_256 - ] - self.efuses += [ - EfuseField.convert(self, efuse) for efuse in self.Fields.CUSTOM_MAC - ] - self.efuses += [ - EfuseField.convert(self, efuse) for efuse in self.Fields.ADC_CALIBRATION - ] - else: - if self.coding_scheme == self.REGS.CODING_SCHEME_NONE: - self.efuses += [ - EfuseField.convert(self, efuse) - for efuse in self.Fields.KEYBLOCKS_256 - ] - elif self.coding_scheme == self.REGS.CODING_SCHEME_34: - self.efuses += [ - EfuseField.convert(self, efuse) - for efuse in self.Fields.KEYBLOCKS_192 - ] - else: - raise esptool.FatalError( - "The coding scheme (%d) - is not supported" % self.coding_scheme - ) - if self["MAC_VERSION"].get() == 1: - self.efuses += [ - EfuseField.convert(self, efuse) for efuse in self.Fields.CUSTOM_MAC - ] - if self["BLK3_PART_RESERVE"].get(): - self.efuses += [ - EfuseField.convert(self, efuse) - for efuse in self.Fields.ADC_CALIBRATION - ] - 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.CUSTOM_MAC: - 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.CUSTOM_MAC - ] - new_fields = True - for efuse in self.Fields.ADC_CALIBRATION: - 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.ADC_CALIBRATION - ] - 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): - coding_scheme = ( - self.read_efuse(self.REGS.EFUSE_CODING_SCHEME_WORD) - & self.REGS.EFUSE_CODING_SCHEME_MASK - ) - if coding_scheme == self.REGS.CODING_SCHEME_NONE_RECOVERY: - self.coding_scheme = self.REGS.CODING_SCHEME_NONE - else: - self.coding_scheme = coding_scheme - - def print_status_regs(self): - print("") - print( - "{:27} 0x{:08x}".format( - "EFUSE_REG_DEC_STATUS", self.read_reg(self.REGS.EFUSE_REG_DEC_STATUS) - ) - ) - - def write_efuses(self, block): - """Write the values in the efuse write registers to - the efuse hardware, then refresh the efuse read registers. - """ - - # Configure clock - apb_freq = self.get_crystal_freq() - clk_sel0, clk_sel1, dac_clk_div = self.REGS.EFUSE_CLK_SETTINGS[apb_freq] - - self.update_reg( - self.REGS.EFUSE_DAC_CONF_REG, self.REGS.EFUSE_DAC_CLK_DIV_MASK, dac_clk_div - ) - self.update_reg( - self.REGS.EFUSE_CLK_REG, self.REGS.EFUSE_CLK_SEL0_MASK, clk_sel0 - ) - self.update_reg( - self.REGS.EFUSE_CLK_REG, self.REGS.EFUSE_CLK_SEL1_MASK, clk_sel1 - ) - - self.write_reg(self.REGS.EFUSE_REG_CONF, self.REGS.EFUSE_CONF_WRITE) - self.write_reg(self.REGS.EFUSE_REG_CMD, self.REGS.EFUSE_CMD_WRITE) - - self.efuse_read() - return self.get_coding_scheme_warnings(silent=True) - - def wait_efuse_idle(self): - deadline = time.time() + self.REGS.EFUSE_BURN_TIMEOUT - while time.time() < deadline: - if self.read_reg(self.REGS.EFUSE_REG_CMD) == 0: - return - raise esptool.FatalError( - "Timed out waiting for Efuse controller command to complete" - ) - - def efuse_read(self): - self.wait_efuse_idle() - self.write_reg(self.REGS.EFUSE_REG_CONF, self.REGS.EFUSE_CONF_READ) - self.write_reg(self.REGS.EFUSE_REG_CMD, self.REGS.EFUSE_CMD_READ) - self.wait_efuse_idle() - - def get_coding_scheme_warnings(self, silent=False): - """Check if the coding scheme has detected any errors. - Meaningless for default coding scheme (0) - """ - err = ( - self.read_reg(self.REGS.EFUSE_REG_DEC_STATUS) - & self.REGS.EFUSE_REG_DEC_STATUS_MASK - ) - for block in self.blocks: - if block.id != 0: - block.num_errors = 0 - block.fail = err != 0 - if not silent and block.fail: - print( - "Error(s) in BLOCK%d [ERRORS:%d FAIL:%d]" - % (block.id, block.num_errors, block.fail) - ) - if (self.debug or err) and not silent: - self.print_status_regs() - return err != 0 - - 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)" - elif self["XPD_SDIO_REG"].get() == 0: - output = "Flash voltage (VDD_SDIO) internal regulator disabled by efuse." - elif self["XPD_SDIO_TIEH"].get() == 0: - output = "Flash voltage (VDD_SDIO) set to 1.8V by efuse." - else: - output = "Flash voltage (VDD_SDIO) set to 3.3V by efuse." - return output - - -class EfuseField(base_fields.EfuseFieldBase): - @staticmethod - def convert(parent, efuse): - return { - "mac": EfuseMacField, - "spipin": EfuseSpiPinField, - "vref": EfuseVRefField, - "adc_tp": EfuseAdcPointCalibration, - "wafer": EfuseWafer, - "pkg": EfusePkg, - }.get(efuse.class_type, EfuseField)(parent, efuse) - - -class EfuseMacField(EfuseField): - """ - Supports: MAC and CUSTOM_MAC fields. - (if MAC_VERSION == 1 then the CUSTOM_MAC is used) - """ - - 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!" - ) - if new_value_str.count(":") != 5: - raise esptool.FatalError( - "MAC Address needs to be a 6-byte hexadecimal format " - "separated by colons (:)!" - ) - hexad = new_value_str.replace(":", "") - if len(hexad) != 12: - raise esptool.FatalError( - "MAC Address needs to be a 6-byte hexadecimal number " - "(12 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!") - return bindata - - @staticmethod - def get_and_check(raw_mac, stored_crc): - computed_crc = EfuseMacField.calc_crc(raw_mac) - if computed_crc == stored_crc: - valid_msg = "(CRC 0x%02x OK)" % stored_crc - else: - valid_msg = "(CRC 0x%02x invalid - calculated 0x%02x)" % ( - stored_crc, - computed_crc, - ) - return "%s %s" % (util.hexify(raw_mac, ":"), valid_msg) - - @staticmethod - def calc_crc(raw_mac): - """ - This algorithm is the equivalent of esp_crc8() in ESP32 ROM code - - This is CRC-8 w/ inverted polynomial value 0x8C & initial value 0x00. - """ - result = 0x00 - for b in struct.unpack("B" * 6, raw_mac): - result ^= b - for _ in range(8): - lsb = result & 1 - result >>= 1 - if lsb != 0: - result ^= 0x8C - return result - - def get(self, from_read=True): - if self.name == "CUSTOM_MAC": - mac = self.get_raw(from_read)[::-1] - stored_crc = self.parent["CUSTOM_MAC_CRC"].get(from_read) - else: - mac = self.get_raw(from_read) - stored_crc = self.parent["MAC_CRC"].get(from_read) - return EfuseMacField.get_and_check(mac, stored_crc) - - 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": - # Writing the BLK3: - # - MAC_VERSION = 1 - # - CUSTOM_MAC = AB:CD:EF:01:02:03 - # - CUSTOM_MAC_CRC = crc8(CUSTOM_MAC) - mac_version = self.parent["MAC_VERSION"] - if mac_version.get() == 0: - mac_version_value = 1 - print_field(mac_version, hex(mac_version_value)) - mac_version.save(mac_version_value) - else: - if mac_version.get() != 1: - if not self.parent.force_write_always: - raise esptool.FatalError( - "MAC_VERSION = {}, should be 0 or 1.".format( - mac_version.get() - ) - ) - - bitarray_mac = self.convert_to_bitstring(new_value) - print_field(self, bitarray_mac) - super(EfuseMacField, self).save(new_value) - - crc_val = self.calc_crc(new_value) - crc_field = self.parent["CUSTOM_MAC_CRC"] - print_field(crc_field, hex(crc_val)) - crc_field.save(crc_val) - else: - # Writing the BLK0 default MAC is not possible, - # as it's written in the factory. - raise esptool.FatalError("Writing Factory MAC address is not supported") - - -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 - ) & self.parent.REGS.APB_CTL_DATE_V - combine_value = (rev_bit2 << 2) | (rev_bit1 << 1) | rev_bit0 - - revision = { - 0: 0, - 1: 1, - 3: 2, - 7: 3, - }.get(combine_value, 0) - return revision - - def save(self, new_value): - raise esptool.FatalError("Burning %s is not supported" % self.name) - - -class EfusePkg(EfuseField): - def get(self, from_read=True): - lo_bits = self.parent["CHIP_PACKAGE"].get(from_read) - hi_bits = self.parent["CHIP_PACKAGE_4BIT"].get(from_read) - return (hi_bits << 3) + lo_bits - - def save(self, new_value): - raise esptool.FatalError("Burning %s is not supported" % self.name) - - -class EfuseSpiPinField(EfuseField): - def get(self, from_read=True): - val = self.get_raw(from_read) - if val >= 30: - val += 2 # values 30,31 map to 32, 33 - return val - - def check_format(self, new_value_str): - if new_value_str is None: - return new_value_str - - new_value_int = int(new_value_str, 0) - - if new_value_int in [30, 31]: - raise esptool.FatalError( - "IO pins 30 & 31 cannot be set for SPI flash. 0-29, 32 & 33 only." - ) - elif new_value_int > 33: - raise esptool.FatalError( - "IO pin %d cannot be set for SPI flash. 0-29, 32 & 33 only." - % new_value_int - ) - elif new_value_int in [32, 33]: - return str(new_value_int - 2) - else: - return new_value_str - - -class EfuseVRefField(EfuseField): - VREF_OFFSET = 1100 # ideal efuse value in mV - VREF_STEP_SIZE = 7 # 1 count in efuse == 7mV - VREF_SIGN_BIT = 0x10 - VREF_MAG_BITS = 0x0F - - def get(self, from_read=True): - val = self.get_raw(from_read) - # sign-magnitude format - if val & self.VREF_SIGN_BIT: - val = -(val & self.VREF_MAG_BITS) - else: - val = val & self.VREF_MAG_BITS - val *= self.VREF_STEP_SIZE - return self.VREF_OFFSET + val - - def save(self, new_value): - raise esptool.FatalError("Writing to VRef is not supported.") - - -class EfuseAdcPointCalibration(EfuseField): - TP_OFFSET = { # See TP_xxxx_OFFSET in esp_adc_cal.c in ESP-IDF - "ADC1_TP_LOW": 278, - "ADC2_TP_LOW": 421, - "ADC1_TP_HIGH": 3265, - "ADC2_TP_HIGH": 3406, - } - SIGN_BIT = (0x40, 0x100) # LOW, HIGH (2s complement format) - STEP_SIZE = 4 - - def get(self, from_read=True): - idx = 0 if self.name.endswith("LOW") else 1 - sign_bit = self.SIGN_BIT[idx] - offset = self.TP_OFFSET[self.name] - raw = self.get_raw() - delta = (raw & (sign_bit - 1)) - (raw & sign_bit) - return offset + (delta * self.STEP_SIZE) diff --git a/tools/esptool_py/espefuse/efuse/esp32/mem_definition.py b/tools/esptool_py/espefuse/efuse/esp32/mem_definition.py deleted file mode 100644 index 60f30935a7..0000000000 --- a/tools/esptool_py/espefuse/efuse/esp32/mem_definition.py +++ /dev/null @@ -1,179 +0,0 @@ -# This file describes eFuses fields and registers for ESP32 chip -# -# SPDX-FileCopyrightText: 2020-2022 Espressif Systems (Shanghai) CO LTD -# -# SPDX-License-Identifier: GPL-2.0-or-later - -import copy -import os - -import yaml - -from ..mem_definition_base import ( - EfuseBlocksBase, - EfuseFieldsBase, - EfuseRegistersBase, - Field, -) - - -class EfuseDefineRegisters(EfuseRegistersBase): - EFUSE_MEM_SIZE = 0x011C + 4 - - # EFUSE registers & command/conf values - DR_REG_EFUSE_BASE = 0x3FF5A000 - EFUSE_REG_CONF = DR_REG_EFUSE_BASE + 0x0FC - EFUSE_CONF_WRITE = 0x5A5A - EFUSE_CONF_READ = 0x5AA5 - EFUSE_REG_CMD = DR_REG_EFUSE_BASE + 0x104 - EFUSE_CMD_OP_MASK = 0x3 - EFUSE_CMD_WRITE = 0x2 - EFUSE_CMD_READ = 0x1 - - # 3/4 Coding scheme warnings registers - EFUSE_REG_DEC_STATUS = DR_REG_EFUSE_BASE + 0x11C - EFUSE_REG_DEC_STATUS_MASK = 0xFFF - - # Coding Scheme - EFUSE_CODING_SCHEME_WORD = 6 - EFUSE_CODING_SCHEME_MASK = 0x3 - - # Efuse clock control - EFUSE_DAC_CONF_REG = DR_REG_EFUSE_BASE + 0x118 - EFUSE_CLK_REG = DR_REG_EFUSE_BASE + 0x0F8 - EFUSE_DAC_CLK_DIV_MASK = 0xFF - EFUSE_CLK_SEL0_MASK = 0x00FF - EFUSE_CLK_SEL1_MASK = 0xFF00 - - EFUSE_CLK_SETTINGS = { - # APB freq: clk_sel0, clk_sel1, dac_clk_div - # Taken from TRM chapter "eFuse Controller": Timing Configuration - # 80 is here for completeness only as esptool never sets an 80MHz APB clock - 26: (250, 255, 52), - 40: (160, 255, 80), - 80: (80, 128, 100), - } - - DR_REG_SYSCON_BASE = 0x3FF66000 - APB_CTL_DATE_ADDR = DR_REG_SYSCON_BASE + 0x7C - APB_CTL_DATE_V = 0x1 - APB_CTL_DATE_S = 31 - - EFUSE_BLK0_RDATA3_REG = DR_REG_EFUSE_BASE + 0x00C - EFUSE_RD_CHIP_VER_REV1 = 1 << 15 - - EFUSE_BLK0_RDATA5_REG = DR_REG_EFUSE_BASE + 0x014 - EFUSE_RD_CHIP_VER_REV2 = 1 << 20 - - -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), - ("BLOCK1", ["flash_encryption"], 1, __base_regs + 0x038, __base_regs + 0x098, 7, 0, 8, None), - ("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 = [] - for block in self.BLOCKS: - blk = self.get(block) - if blk.name: - list_of_names.append(blk.name) - return list_of_names - - -class EfuseDefineFields(EfuseFieldsBase): - def __init__(self, extend_efuse_table) -> 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, extend_efuse_table) - - 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/tools/esptool_py/espefuse/efuse/esp32/operations.py b/tools/esptool_py/espefuse/efuse/esp32/operations.py deleted file mode 100644 index e0f419a1c1..0000000000 --- a/tools/esptool_py/espefuse/efuse/esp32/operations.py +++ /dev/null @@ -1,365 +0,0 @@ -# This file includes the operations with eFuses for ESP32 chip -# -# SPDX-FileCopyrightText: 2020-2022 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 add_commands(subparsers, efuses): - add_common_commands(subparsers, efuses) - p = subparsers.add_parser( - "burn_key", - help="Burn a 256-bit key to EFUSE: %s" % ", ".join(efuses.BLOCKS_FOR_KEYS), - ) - p.add_argument( - "--no-protect-key", - help="Disable default read- and write-protecting of the key. " - "If this option is not set, once the key is flashed " - "it cannot be read back or changed.", - 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), ' - '"secure_boot_v1" (block2), "secure_boot_v2" (block2)', - action="append", - choices=efuses.BLOCKS_FOR_KEYS, - ) - p.add_argument( - "keyfile", - help="File containing 256 bits of binary key data", - action="append", - type=argparse.FileType("rb"), - ) - for _ in efuses.BLOCKS_FOR_KEYS: - p.add_argument( - "block", - help='Key block to burn. "flash_encryption" (block1), ' - '"secure_boot_v1" (block2), "secure_boot_v2" (block2)', - metavar="BLOCK", - nargs="?", - action="append", - choices=efuses.BLOCKS_FOR_KEYS, - ) - p.add_argument( - "keyfile", - help="File containing 256 bits of binary key data", - metavar="KEYFILE", - nargs="?", - action="append", - type=argparse.FileType("rb"), - ) - - burn_key_digest = subparsers.add_parser( - "burn_key_digest", - help="Parse a RSA public key and burn the digest " - "to eFuse for use with Secure Boot V2", - ) - burn_key_digest.add_argument( - "keyfile", help="Key file to digest (PEM format)", type=argparse.FileType("rb") - ) - burn_key_digest.add_argument( - "--no-protect-key", - help="Disable default write-protecting of the key digest. " - "If this option is not set, once the key is flashed it cannot be changed.", - 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", - help="Permanently set the internal flash voltage regulator " - "to either 1.8V, 3.3V or OFF. This means GPIO12 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): - # Writing to BLK3: - # - MAC_VERSION = 1 - # - CUSTOM_MAC = AA:CD:EF:01:02:03 - # - CUSTOM_MAC_CRC = crc8(CUSTOM_MAC) - efuses["CUSTOM_MAC"].save(args.mac) - if not efuses.burn_all(check_batch_mode=True): - return - get_custom_mac(esp, efuses, args) - print("Successful") - - -def get_custom_mac(esp, efuses, args): - version = efuses["MAC_VERSION"].get() - if version > 0: - print( - "Custom MAC Address version {}: {}".format( - version, efuses["CUSTOM_MAC"].get() - ) - ) - else: - print("Custom MAC Address is not set in the device.") - - -def set_flash_voltage(esp, efuses, args): - sdio_force = efuses["XPD_SDIO_FORCE"] - sdio_tieh = efuses["XPD_SDIO_TIEH"] - sdio_reg = efuses["XPD_SDIO_REG"] - - # check efuses aren't burned in a way which makes this impossible - if args.voltage == "OFF" and sdio_reg.get() != 0: - raise esptool.FatalError( - "Can't set flash regulator to OFF as XPD_SDIO_REG efuse is already burned" - ) - - if args.voltage == "1.8V" and sdio_tieh.get() != 0: - raise esptool.FatalError( - "Can't set regulator to 1.8V is XPD_SDIO_TIEH efuse is already burned" - ) - - if args.voltage == "OFF": - msg = "Disable internal flash voltage regulator (VDD_SDIO). " - "SPI flash will need to be powered from an external source.\n" - "The following efuse is burned: XPD_SDIO_FORCE.\n" - "It is possible to later re-enable the internal regulator (%s) " % ( - "to 3.3V" if sdio_tieh.get() != 0 else "to 1.8V or 3.3V" - ) - "by burning an additional efuse" - elif args.voltage == "1.8V": - msg = "Set internal flash voltage regulator (VDD_SDIO) to 1.8V.\n" - "The following efuses are burned: XPD_SDIO_FORCE, XPD_SDIO_REG.\n" - "It is possible to later increase the voltage to 3.3V (permanently) " - "by burning additional efuse XPD_SDIO_TIEH" - elif args.voltage == "3.3V": - msg = "Enable internal flash voltage regulator (VDD_SDIO) to 3.3V.\n" - "The following efuses are burned: XPD_SDIO_FORCE, XPD_SDIO_REG, XPD_SDIO_TIEH." - print(msg) - sdio_force.save(1) # Disable GPIO12 - if args.voltage != "OFF": - sdio_reg.save(1) # Enable internal regulator - if args.voltage == "3.3V": - sdio_tieh.save(1) - print("VDD_SDIO setting complete.") - if not efuses.burn_all(check_batch_mode=True): - return - print("Successful") - - -def adc_info(esp, efuses, args): - adc_vref = efuses["ADC_VREF"] - blk3_reserve = efuses["BLK3_PART_RESERVE"] - - vref_raw = adc_vref.get_raw() - if vref_raw == 0: - print("ADC VRef calibration: None (1100mV nominal)") - else: - print("ADC VRef calibration: %dmV" % adc_vref.get()) - - if blk3_reserve.get(): - print("ADC readings stored in efuse BLOCK3:") - print(" ADC1 Low reading (150mV): %d" % efuses["ADC1_TP_LOW"].get()) - print(" ADC1 High reading (850mV): %d" % efuses["ADC1_TP_HIGH"].get()) - print(" ADC2 Low reading (150mV): %d" % efuses["ADC2_TP_LOW"].get()) - print(" ADC2 High reading (850mV): %d" % efuses["ADC2_TP_HIGH"].get()) - - -def burn_key(esp, efuses, args): - datafile_list = args.keyfile[ - 0 : len([keyfile for keyfile in args.keyfile if keyfile is not None]) : - ] - block_name_list = args.block[ - 0 : len([block for block in args.block if block is not None]) : - ] - efuses.force_write_always = args.force_write_always - no_protect_key = args.no_protect_key - - util.check_duplicate_name_in_list(block_name_list) - if len(block_name_list) != len(datafile_list): - raise esptool.FatalError( - "The number of blocks (%d) and datafile (%d) should be the same." - % (len(block_name_list), len(datafile_list)) - ) - - print("Burn keys to blocks:") - for block_name, datafile in zip(block_name_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 - data = datafile.read() - revers_msg = None - if block_name in ("flash_encryption", "secure_boot_v1"): - revers_msg = "\tReversing the byte order" - data = data[::-1] - 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: - 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) - ) - - efuse.save(data) - - if block_name in ("flash_encryption", "secure_boot_v1"): - if not no_protect_key: - print("\tDisabling read to key block") - efuse.disable_read() - - if not no_protect_key: - print("\tDisabling write to key block") - efuse.disable_write() - print("") - - if args.no_protect_key: - print("Key is left unprotected as per --no-protect-key argument.") - - msg = "Burn keys in efuse blocks.\n" - if no_protect_key: - msg += ( - "The key block will left readable and writeable (due to --no-protect-key)" - ) - else: - msg += "The key block will be read and write protected " - "(no further changes or readback)" - print(msg, "\n") - if not efuses.burn_all(check_batch_mode=True): - return - print("Successful") - - -def burn_key_digest(esp, efuses, args): - if efuses.coding_scheme == efuses.REGS.CODING_SCHEME_34: - raise esptool.FatalError("burn_key_digest only works with 'None' coding scheme") - - chip_revision = esp.get_chip_revision() - if chip_revision < 300: - raise esptool.FatalError( - "Incorrect chip revision for Secure boot v2. " - "Detected: v%d.%d. Expected: >= v3.0" - % (chip_revision / 100, chip_revision % 100) - ) - - digest = espsecure._digest_sbv2_public_key(args.keyfile) - efuse = efuses["BLOCK2"] - num_bytes = efuse.bit_len // 8 - 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) - ) - 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: - print("Disabling write to efuse %s..." % (efuse.name)) - efuse.disable_write() - - if not efuses.burn_all(check_batch_mode=True): - return - print("Successful") - - -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/tools/esptool_py/espefuse/efuse/esp32c2/__init__.py b/tools/esptool_py/espefuse/efuse/esp32c2/__init__.py deleted file mode 100644 index a3b55a8023..0000000000 --- a/tools/esptool_py/espefuse/efuse/esp32c2/__init__.py +++ /dev/null @@ -1,3 +0,0 @@ -from . import operations -from .emulate_efuse_controller import EmulateEfuseController -from .fields import EspEfuses diff --git a/tools/esptool_py/espefuse/efuse/esp32c2/emulate_efuse_controller.py b/tools/esptool_py/espefuse/efuse/esp32c2/emulate_efuse_controller.py deleted file mode 100644 index a7d4693e45..0000000000 --- a/tools/esptool_py/espefuse/efuse/esp32c2/emulate_efuse_controller.py +++ /dev/null @@ -1,139 +0,0 @@ -# This file describes eFuses controller for ESP32-C2 chip -# -# SPDX-FileCopyrightText: 2021-2022 Espressif Systems (Shanghai) CO LTD -# -# SPDX-License-Identifier: GPL-2.0-or-later - -from bitstring import BitStream - -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-C2" - mem = None - debug = False - - def __init__(self, efuse_file=None, debug=False): - self.Blocks = EfuseDefineBlocks - self.Fields = EfuseDefineFields(None) - 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 1 - - def get_minor_chip_version(self): - return 0 - - def get_crystal_freq(self): - return 40 # MHz - - 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 - - def check_rd_protection_area(self): - # checks fields which have the read protection bits. - # if the read protection bit is set then we need to reset this field to 0. - - def get_read_disable_mask(blk): - mask = 0 - if isinstance(blk.read_disable_bit, list): - for i in blk.read_disable_bit: - mask |= 1 << i - else: - mask = 1 << blk.read_disable_bit - return mask - - read_disable_bit = self.read_field("RD_DIS", bitstring=False) - for b in self.Blocks.BLOCKS: - blk = self.Blocks.get(b) - block = self.read_block(blk.id) - if ( - blk.read_disable_bit is not None - and read_disable_bit & get_read_disable_mask(blk) - ): - if isinstance(blk.read_disable_bit, list): - if read_disable_bit & (1 << blk.read_disable_bit[0]): - block.set( - 0, [i for i in range(blk.len * 32 // 2, blk.len * 32)] - ) - if read_disable_bit & (1 << blk.read_disable_bit[1]): - block.set(0, [i for i in range(0, blk.len * 32 // 2)]) - else: - block.set(0) - else: - for field in self.Fields.EFUSES: - if ( - blk.id == field.block - and field.read_disable_bit is not None - and read_disable_bit & get_read_disable_mask(field) - ): - raw_data = self.read_field(field.name) - raw_data.set(0) - block.pos = block.length - ( - field.word * 32 + field.pos + raw_data.length - ) - block.overwrite(BitStream(raw_data.length)) - self.overwrite_mem_from_block(blk, block) diff --git a/tools/esptool_py/espefuse/efuse/esp32c2/fields.py b/tools/esptool_py/espefuse/efuse/esp32c2/fields.py deleted file mode 100644 index a9fe33cce4..0000000000 --- a/tools/esptool_py/espefuse/efuse/esp32c2/fields.py +++ /dev/null @@ -1,388 +0,0 @@ -# This file describes eFuses for ESP32-C2 chip -# -# SPDX-FileCopyrightText: 2021-2022 Espressif Systems (Shanghai) CO LTD -# -# SPDX-License-Identifier: GPL-2.0-or-later - -import binascii -import struct -import sys -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, - extend_efuse_table=None, - ): - self.Blocks = EfuseDefineBlocks() - self.Fields = EfuseDefineFields(extend_efuse_table) - 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-C2": - raise esptool.FatalError( - "Expected the 'esp' param for ESP32-C2 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: - if self["BLK_VERSION_MINOR"].get() == 1: - self.efuses += [ - 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 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_ERR_REG", self.read_reg(self.REGS.EFUSE_RD_RS_ERR_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") - sys.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") - sys.exit(0) # finish without errors - raise - - def set_efuse_timing(self): - """Set timing registers for burning efuses""" - # Configure clock - xtal_freq = self.get_crystal_freq() - if xtal_freq not in [26, 40]: - raise esptool.FatalError( - "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 - ) - - tpgm_inactive_val = 200 if xtal_freq == 40 else 130 - self.update_reg( - self.REGS.EFUSE_WR_TIM_CONF0_REG, - self.REGS.EFUSE_TPGM_INACTIVE_M, - tpgm_inactive_val, - ) - - 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_ERR_REG + offs * 4) - for offs in range(1) - ] - 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!" - ) - if new_value_str.count(":") != 5: - raise esptool.FatalError( - "MAC Address needs to be a 6-byte hexadecimal format " - "separated by colons (:)!" - ) - hexad = new_value_str.replace(":", "") - if len(hexad) != 12: - raise esptool.FatalError( - "MAC Address needs to be a 6-byte hexadecimal number " - "(12 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!") - 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] - 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: - raise esptool.FatalError("Writing Factory MAC address is not supported") - - -class EfuseKeyPurposeField(EfuseField): - # fmt: off - KEY_PURPOSES = [ - ("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] - DIGEST_KEY_PURPOSES = [name[0] for name in KEY_PURPOSES if name[2] == "DIGEST"] diff --git a/tools/esptool_py/espefuse/efuse/esp32c2/mem_definition.py b/tools/esptool_py/espefuse/efuse/esp32c2/mem_definition.py deleted file mode 100644 index 47cd18c047..0000000000 --- a/tools/esptool_py/espefuse/efuse/esp32c2/mem_definition.py +++ /dev/null @@ -1,147 +0,0 @@ -# This file describes eFuses fields and registers for ESP32-C2 chip -# -# SPDX-FileCopyrightText: 2021-2022 Espressif Systems (Shanghai) CO LTD -# -# SPDX-License-Identifier: GPL-2.0-or-later - -import copy -import os - -import yaml - -from ..mem_definition_base import ( - EfuseBlocksBase, - EfuseFieldsBase, - EfuseRegistersBase, -) - - -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 - 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 - - 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_WR_TIM_CONF2_REG = DR_REG_EFUSE_BASE + 0x118 - EFUSE_PWR_OFF_NUM_S = 0 - EFUSE_PWR_OFF_NUM_M = 0xFFFF << EFUSE_PWR_OFF_NUM_S - - EFUSE_WR_TIM_CONF0_REG = DR_REG_EFUSE_BASE + 0x110 - 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 - - 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), - ("BLOCK1", ["BLOCK1"], 1, __base_rd_regs + 0x034, __base_wr_regs, 5, None, 3, None), - ("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 = [] - 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 - - def get_blocks_for_keys(self): - return ["BLOCK_KEY0"] - - -class EfuseDefineFields(EfuseFieldsBase): - def __init__(self, extend_efuse_table) -> 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, extend_efuse_table) - - 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/tools/esptool_py/espefuse/efuse/esp32c2/operations.py b/tools/esptool_py/espefuse/efuse/esp32c2/operations.py deleted file mode 100644 index d23f6a721b..0000000000 --- a/tools/esptool_py/espefuse/efuse/esp32c2/operations.py +++ /dev/null @@ -1,351 +0,0 @@ -# This file includes the operations with eFuses for ESP32-C2 chip -# -# SPDX-FileCopyrightText: 2021-2022 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.", - 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 128/256 bits of binary key data", - 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 range(1): - 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 128/256 bits of binary key data", - 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 an ECDSA public key and burn the digest " - "to higher 128-bits of BLOCK_KEY0", - ) - 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") - ) - - 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 BLOCK1." - ) - 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): - efuses["CUSTOM_MAC"].save(args.mac) - efuses["CUSTOM_MAC_USED"].save(1) - if not efuses.burn_all(check_batch_mode=True): - return - get_custom_mac(esp, efuses, args) - print("Successful") - - -def get_custom_mac(esp, efuses, args): - print("Custom MAC Address: {}".format(efuses["CUSTOM_MAC"].get())) - - -def set_flash_voltage(esp, efuses, args): - raise esptool.FatalError("set_flash_voltage is not supported!") - - -def adc_info(esp, efuses, args): - print("") - # fmt: off - if efuses["BLK_VERSION_MINOR"].get() == 1: - print("Temperature Sensor Calibration = {}C".format(efuses["TEMP_CALIB"].get())) - print("ADC OCode = ", efuses["OCODE"].get()) - print("ADC1:") - print("INIT_CODE_ATTEN0 = ", efuses["ADC1_INIT_CODE_ATTEN0"].get()) - print("INIT_CODE_ATTEN3 = ", efuses["ADC1_INIT_CODE_ATTEN3"].get()) - print("CAL_VOL_ATTEN0 = ", efuses["ADC1_CAL_VOL_ATTEN0"].get()) - print("CAL_VOL_ATTEN3 = ", efuses["ADC1_CAL_VOL_ATTEN3"].get()) - else: - print("BLK_VERSION_MINOR = {}".format(efuses["BLK_VERSION_MINOR"].get_meaning())) - # fmt: on - - -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(keypurpose_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)) - ) - - assert 1 <= len(block_name_list) <= 2, "Unexpected case" - - if len(block_name_list) == 2: - incompatible = True if "XTS_AES_128_KEY" in keypurpose_list else False - permitted_purposes = [ - "XTS_AES_128_KEY_DERIVED_FROM_128_EFUSE_BITS", - "SECURE_BOOT_DIGEST", - ] - incompatible |= ( - keypurpose_list[0] in permitted_purposes - and keypurpose_list[1] not in permitted_purposes - ) - if incompatible: - raise esptool.FatalError( - "These keypurposes are incompatible %s" % (keypurpose_list) - ) - - print("Burn keys to blocks:") - for datafile, keypurpose in zip(datafile_list, keypurpose_list): - data = datafile if isinstance(datafile, bytes) else datafile.read() - - if keypurpose == "XTS_AES_128_KEY_DERIVED_FROM_128_EFUSE_BITS": - efuse = efuses["BLOCK_KEY0_LOW_128"] - elif keypurpose == "SECURE_BOOT_DIGEST": - efuse = efuses["BLOCK_KEY0_HI_128"] - if len(data) == 32: - print( - "\tProgramming only left-most 128-bits from SHA256 hash of " - "public key to highest 128-bits of BLOCK KEY0" - ) - data = data[:16] - elif len(data) != efuse.bit_len // 8: - raise esptool.FatalError( - "Wrong length of this file for SECURE_BOOT_DIGEST. " - "Got %d (expected %d or %d)" % (len(data), 32, efuse.bit_len // 8) - ) - assert len(data) == 16, "Only 16 bytes expected" - else: - efuse = efuses["BLOCK_KEY0"] - - num_bytes = efuse.bit_len // 8 - - print(" - %s" % (efuse.name), end=" ") - revers_msg = None - if keypurpose.startswith("XTS_AES_"): - revers_msg = "\tReversing byte order for AES-XTS 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 keypurpose.startswith("XTS_AES_"): - 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) - - if keypurpose == "XTS_AES_128_KEY": - if efuses["XTS_KEY_LENGTH_256"].get(): - print("\t'XTS_KEY_LENGTH_256' is already '1'") - else: - print("\tXTS_KEY_LENGTH_256 -> 1") - efuses["XTS_KEY_LENGTH_256"].save(1) - - 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): - datafile = args.keyfile - args.keypurpose = ["SECURE_BOOT_DIGEST"] - args.block = ["BLOCK_KEY0"] - digest = espsecure._digest_sbv2_public_key(datafile) - digest = digest[:16] - num_bytes = efuses["BLOCK_KEY0_HI_128"].bit_len // 8 - 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) - ) - burn_key(esp, efuses, args, digest=[digest]) - - -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/tools/esptool_py/espefuse/efuse/esp32c3/__init__.py b/tools/esptool_py/espefuse/efuse/esp32c3/__init__.py deleted file mode 100644 index a3b55a8023..0000000000 --- a/tools/esptool_py/espefuse/efuse/esp32c3/__init__.py +++ /dev/null @@ -1,3 +0,0 @@ -from . import operations -from .emulate_efuse_controller import EmulateEfuseController -from .fields import EspEfuses diff --git a/tools/esptool_py/espefuse/efuse/esp32c3/emulate_efuse_controller.py b/tools/esptool_py/espefuse/efuse/esp32c3/emulate_efuse_controller.py deleted file mode 100644 index fca2f102b2..0000000000 --- a/tools/esptool_py/espefuse/efuse/esp32c3/emulate_efuse_controller.py +++ /dev/null @@ -1,92 +0,0 @@ -# This file describes eFuses controller for ESP32-C3 chip -# -# SPDX-FileCopyrightText: 2020-2022 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-C3" - mem = None - debug = False - - def __init__(self, efuse_file=None, debug=False): - self.Blocks = EfuseDefineBlocks - self.Fields = EfuseDefineFields(None) - 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 4 - - 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/tools/esptool_py/espefuse/efuse/esp32c3/fields.py b/tools/esptool_py/espefuse/efuse/esp32c3/fields.py deleted file mode 100644 index f367540a80..0000000000 --- a/tools/esptool_py/espefuse/efuse/esp32c3/fields.py +++ /dev/null @@ -1,454 +0,0 @@ -# This file describes eFuses for ESP32-C3 chip -# -# SPDX-FileCopyrightText: 2020-2022 Espressif Systems (Shanghai) CO LTD -# -# SPDX-License-Identifier: GPL-2.0-or-later - -import binascii -import struct -import sys -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, - extend_efuse_table=None, - ): - self.Blocks = EfuseDefineBlocks() - self.Fields = EfuseDefineFields(extend_efuse_table) - 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-C3": - raise esptool.FatalError( - "Expected the 'esp' param for ESP32-C3 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: - if self["BLK_VERSION_MAJOR"].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") - sys.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") - sys.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 - ) - - 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.""" - 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_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 - - 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, - "wafer": EfuseWafer, - }.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): - raise esptool.FatalError("Burning %s is not supported" % self.name) - - -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!" - ) - if new_value_str.count(":") != 5: - raise esptool.FatalError( - "MAC Address needs to be a 6-byte hexadecimal format " - "separated by colons (:)!" - ) - hexad = new_value_str.replace(":", "") - if len(hexad) != 12: - raise esptool.FatalError( - "MAC Address needs to be a 6-byte hexadecimal number " - "(12 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!") - 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] - 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("Writing Factory MAC address 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 - ("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) - ] -# 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))) - 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/tools/esptool_py/espefuse/efuse/esp32c3/mem_definition.py b/tools/esptool_py/espefuse/efuse/esp32c3/mem_definition.py deleted file mode 100644 index bd13bd7738..0000000000 --- a/tools/esptool_py/espefuse/efuse/esp32c3/mem_definition.py +++ /dev/null @@ -1,189 +0,0 @@ -# This file describes eFuses fields and registers for ESP32-C3 chip -# -# SPDX-FileCopyrightText: 2020-2022 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 = 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 - 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 - - # 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_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, extend_efuse_table) -> 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, extend_efuse_table) - - 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/tools/esptool_py/espefuse/efuse/esp32c3/operations.py b/tools/esptool_py/espefuse/efuse/esp32c3/operations.py deleted file mode 100644 index ff63109570..0000000000 --- a/tools/esptool_py/espefuse/efuse/esp32c3/operations.py +++ /dev/null @@ -1,404 +0,0 @@ -# This file includes the operations with eFuses for ESP32-C3 chip -# -# SPDX-FileCopyrightText: 2020-2022 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", - 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", - 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): - efuses["CUSTOM_MAC"].save(args.mac) - if not efuses.burn_all(check_batch_mode=True): - return - get_custom_mac(esp, efuses, args) - print("Successful") - - -def get_custom_mac(esp, efuses, args): - print("Custom MAC Address: {}".format(efuses["CUSTOM_MAC"].get())) - - -def set_flash_voltage(esp, efuses, args): - raise esptool.FatalError("set_flash_voltage is not supported!") - - -def adc_info(esp, efuses, args): - print("") - # fmt: off - if efuses["BLK_VERSION_MAJOR"].get() == 1: - print("Temperature Sensor Calibration = {}C".format(efuses["TEMP_CALIB"].get())) - print("ADC OCode = ", efuses["OCODE"].get()) - print("ADC1:") - print("INIT_CODE_ATTEN0 = ", efuses["ADC1_INIT_CODE_ATTEN0"].get()) - print("INIT_CODE_ATTEN1 = ", efuses["ADC1_INIT_CODE_ATTEN1"].get()) - print("INIT_CODE_ATTEN2 = ", efuses["ADC1_INIT_CODE_ATTEN2"].get()) - print("INIT_CODE_ATTEN3 = ", efuses["ADC1_INIT_CODE_ATTEN3"].get()) - print("CAL_VOL_ATTEN0 = ", efuses["ADC1_CAL_VOL_ATTEN0"].get()) - print("CAL_VOL_ATTEN1 = ", efuses["ADC1_CAL_VOL_ATTEN1"].get()) - print("CAL_VOL_ATTEN2 = ", efuses["ADC1_CAL_VOL_ATTEN2"].get()) - print("CAL_VOL_ATTEN3 = ", efuses["ADC1_CAL_VOL_ATTEN3"].get()) - else: - print("BLK_VERSION_MAJOR = {}".format(efuses["BLK_VERSION_MAJOR"].get_meaning())) - # fmt: on - - -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: - 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" - 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/tools/esptool_py/espefuse/efuse/esp32c5/__init__.py b/tools/esptool_py/espefuse/efuse/esp32c5/__init__.py deleted file mode 100644 index a3b55a8023..0000000000 --- a/tools/esptool_py/espefuse/efuse/esp32c5/__init__.py +++ /dev/null @@ -1,3 +0,0 @@ -from . import operations -from .emulate_efuse_controller import EmulateEfuseController -from .fields import EspEfuses diff --git a/tools/esptool_py/espefuse/efuse/esp32c5/emulate_efuse_controller.py b/tools/esptool_py/espefuse/efuse/esp32c5/emulate_efuse_controller.py deleted file mode 100644 index f81caeb70e..0000000000 --- a/tools/esptool_py/espefuse/efuse/esp32c5/emulate_efuse_controller.py +++ /dev/null @@ -1,92 +0,0 @@ -# This file describes eFuses controller for ESP32-C5 chip -# -# SPDX-FileCopyrightText: 2024 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-C5" - mem = None - debug = False - - def __init__(self, efuse_file=None, debug=False): - self.Blocks = EfuseDefineBlocks - self.Fields = EfuseDefineFields(None) - 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/tools/esptool_py/espefuse/efuse/esp32c5/fields.py b/tools/esptool_py/espefuse/efuse/esp32c5/fields.py deleted file mode 100644 index b61ba6077b..0000000000 --- a/tools/esptool_py/espefuse/efuse/esp32c5/fields.py +++ /dev/null @@ -1,464 +0,0 @@ -# This file describes eFuses for ESP32-C5 chip -# -# SPDX-FileCopyrightText: 2024 Espressif Systems (Shanghai) CO LTD -# -# SPDX-License-Identifier: GPL-2.0-or-later - -import binascii -import struct -import sys -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, - extend_efuse_table=None, - ): - self.Blocks = EfuseDefineBlocks() - self.Fields = EfuseDefineFields(extend_efuse_table) - 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-C5": - raise esptool.FatalError( - "Expected the 'esp' param for ESP32-C5 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: - # 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") - sys.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") - sys.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 not in [40, 48]: - raise esptool.FatalError( - "The eFuse supports only xtal=40M and 48M (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: - 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, - "wafer": EfuseWafer, - }.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): - raise esptool.FatalError("Burning %s is not supported" % self.name) - - -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 - ("RESERVED", 1, 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) - ("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) - ] -# 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))) - 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/tools/esptool_py/espefuse/efuse/esp32c5/mem_definition.py b/tools/esptool_py/espefuse/efuse/esp32c5/mem_definition.py deleted file mode 100644 index 0520328baf..0000000000 --- a/tools/esptool_py/espefuse/efuse/esp32c5/mem_definition.py +++ /dev/null @@ -1,169 +0,0 @@ -# This file describes eFuses fields and registers for ESP32-C5 chip -# -# SPDX-FileCopyrightText: 2024 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 = 0x600B4800 - 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, extend_efuse_table) -> 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, extend_efuse_table) - - 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/tools/esptool_py/espefuse/efuse/esp32c5/operations.py b/tools/esptool_py/espefuse/efuse/esp32c5/operations.py deleted file mode 100644 index 1fca6bcb69..0000000000 --- a/tools/esptool_py/espefuse/efuse/esp32c5/operations.py +++ /dev/null @@ -1,395 +0,0 @@ -# This file includes the operations with eFuses for ESP32-C5 chip -# -# SPDX-FileCopyrightText: 2024 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): - efuses["CUSTOM_MAC"].save(args.mac) - if not efuses.burn_all(check_batch_mode=True): - return - get_custom_mac(esp, efuses, args) - print("Successful") - - -def get_custom_mac(esp, efuses, args): - print("Custom MAC Address: {}".format(efuses["CUSTOM_MAC"].get())) - - -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, and 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/tools/esptool_py/espefuse/efuse/esp32c5beta3/__init__.py b/tools/esptool_py/espefuse/efuse/esp32c5beta3/__init__.py deleted file mode 100644 index a3b55a8023..0000000000 --- a/tools/esptool_py/espefuse/efuse/esp32c5beta3/__init__.py +++ /dev/null @@ -1,3 +0,0 @@ -from . import operations -from .emulate_efuse_controller import EmulateEfuseController -from .fields import EspEfuses diff --git a/tools/esptool_py/espefuse/efuse/esp32c5beta3/emulate_efuse_controller.py b/tools/esptool_py/espefuse/efuse/esp32c5beta3/emulate_efuse_controller.py deleted file mode 100644 index 3fdab6f816..0000000000 --- a/tools/esptool_py/espefuse/efuse/esp32c5beta3/emulate_efuse_controller.py +++ /dev/null @@ -1,92 +0,0 @@ -# This file describes eFuses controller for ESP32-C5 beta3 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-C5(beta3)" - mem = None - debug = False - - def __init__(self, efuse_file=None, debug=False): - self.Blocks = EfuseDefineBlocks - self.Fields = EfuseDefineFields(None) - 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/tools/esptool_py/espefuse/efuse/esp32c5beta3/fields.py b/tools/esptool_py/espefuse/efuse/esp32c5beta3/fields.py deleted file mode 100644 index 351d73667a..0000000000 --- a/tools/esptool_py/espefuse/efuse/esp32c5beta3/fields.py +++ /dev/null @@ -1,464 +0,0 @@ -# This file describes eFuses for ESP32-C5 beta3 chip -# -# SPDX-FileCopyrightText: 2023 Espressif Systems (Shanghai) CO LTD -# -# SPDX-License-Identifier: GPL-2.0-or-later - -import binascii -import struct -import sys -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, - extend_efuse_table=None, - ): - self.Blocks = EfuseDefineBlocks() - self.Fields = EfuseDefineFields(extend_efuse_table) - 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-C5(beta3)": - raise esptool.FatalError( - "Expected the 'esp' param for ESP32-C5(beta3) 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: - # 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") - sys.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") - sys.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 not in [40, 48]: - raise esptool.FatalError( - "The eFuse supports only xtal=40M and 48M (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: - 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, - "wafer": EfuseWafer, - }.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): - raise esptool.FatalError("Burning %s is not supported" % self.name) - - -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 - ("RESERVED", 1, 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) - ("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) - ] -# 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))) - 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/tools/esptool_py/espefuse/efuse/esp32c5beta3/mem_definition.py b/tools/esptool_py/espefuse/efuse/esp32c5beta3/mem_definition.py deleted file mode 100644 index 67ffff60ed..0000000000 --- a/tools/esptool_py/espefuse/efuse/esp32c5beta3/mem_definition.py +++ /dev/null @@ -1,169 +0,0 @@ -# This file describes eFuses fields and registers for ESP32-C5 beta3 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 = 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 - 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, extend_efuse_table) -> 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, extend_efuse_table) - - 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/tools/esptool_py/espefuse/efuse/esp32c5beta3/operations.py b/tools/esptool_py/espefuse/efuse/esp32c5beta3/operations.py deleted file mode 100644 index fbd721bd63..0000000000 --- a/tools/esptool_py/espefuse/efuse/esp32c5beta3/operations.py +++ /dev/null @@ -1,395 +0,0 @@ -# This file includes the operations with eFuses for ESP32-C5 beta3 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): - efuses["CUSTOM_MAC"].save(args.mac) - if not efuses.burn_all(check_batch_mode=True): - return - get_custom_mac(esp, efuses, args) - print("Successful") - - -def get_custom_mac(esp, efuses, args): - print("Custom MAC Address: {}".format(efuses["CUSTOM_MAC"].get())) - - -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, and 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/tools/esptool_py/espefuse/efuse/esp32c6/__init__.py b/tools/esptool_py/espefuse/efuse/esp32c6/__init__.py deleted file mode 100644 index a3b55a8023..0000000000 --- a/tools/esptool_py/espefuse/efuse/esp32c6/__init__.py +++ /dev/null @@ -1,3 +0,0 @@ -from . import operations -from .emulate_efuse_controller import EmulateEfuseController -from .fields import EspEfuses diff --git a/tools/esptool_py/espefuse/efuse/esp32c6/emulate_efuse_controller.py b/tools/esptool_py/espefuse/efuse/esp32c6/emulate_efuse_controller.py deleted file mode 100644 index 47c403ce8a..0000000000 --- a/tools/esptool_py/espefuse/efuse/esp32c6/emulate_efuse_controller.py +++ /dev/null @@ -1,92 +0,0 @@ -# This file describes eFuses controller for ESP32-C6 chip -# -# SPDX-FileCopyrightText: 2022 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-C6" - mem = None - debug = False - - def __init__(self, efuse_file=None, debug=False): - self.Blocks = EfuseDefineBlocks - self.Fields = EfuseDefineFields(None) - 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/tools/esptool_py/espefuse/efuse/esp32c6/fields.py b/tools/esptool_py/espefuse/efuse/esp32c6/fields.py deleted file mode 100644 index 70df55cecd..0000000000 --- a/tools/esptool_py/espefuse/efuse/esp32c6/fields.py +++ /dev/null @@ -1,463 +0,0 @@ -# This file describes eFuses for ESP32-C6 chip -# -# SPDX-FileCopyrightText: 2022 Espressif Systems (Shanghai) CO LTD -# -# SPDX-License-Identifier: GPL-2.0-or-later - -import binascii -import struct -import sys -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, - extend_efuse_table=None, - ): - self.Blocks = EfuseDefineBlocks() - self.Fields = EfuseDefineFields(extend_efuse_table) - 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-C6": - raise esptool.FatalError( - "Expected the 'esp' param for ESP32-C6 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: - 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") - sys.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") - sys.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 - ) - - 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: - 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, - "wafer": EfuseWafer, - }.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): - raise esptool.FatalError("Burning %s is not supported" % self.name) - - -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) - ("RESERVED", 1, 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) - ("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) - ] -# 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))) - 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/tools/esptool_py/espefuse/efuse/esp32c6/mem_definition.py b/tools/esptool_py/espefuse/efuse/esp32c6/mem_definition.py deleted file mode 100644 index 4574fdf63e..0000000000 --- a/tools/esptool_py/espefuse/efuse/esp32c6/mem_definition.py +++ /dev/null @@ -1,169 +0,0 @@ -# This file describes eFuses fields and registers for ESP32-C6 chip -# -# SPDX-FileCopyrightText: 2022 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 = 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 - 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, extend_efuse_table) -> 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, extend_efuse_table) - - 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/tools/esptool_py/espefuse/efuse/esp32c6/operations.py b/tools/esptool_py/espefuse/efuse/esp32c6/operations.py deleted file mode 100644 index 9307ecac3b..0000000000 --- a/tools/esptool_py/espefuse/efuse/esp32c6/operations.py +++ /dev/null @@ -1,411 +0,0 @@ -# This file includes the operations with eFuses for ESP32-C6 chip -# -# SPDX-FileCopyrightText: 2022 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", - 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", - 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): - efuses["CUSTOM_MAC"].save(args.mac) - if not efuses.burn_all(check_batch_mode=True): - return - get_custom_mac(esp, efuses, args) - print("Successful") - - -def get_custom_mac(esp, efuses, args): - print("Custom MAC Address: {}".format(efuses["CUSTOM_MAC"].get())) - - -def set_flash_voltage(esp, efuses, args): - raise esptool.FatalError("set_flash_voltage is not supported!") - - -def adc_info(esp, efuses, args): - print("") - # fmt: off - if efuses["BLK_VERSION_MINOR"].get() == 1: - print("Temperature Sensor Calibration = {}C".format(efuses["TEMP_CALIB"].get())) - print("ADC OCode = ", efuses["OCODE"].get()) - print("ADC1:") - print("INIT_CODE_ATTEN0 = ", efuses['ADC1_INIT_CODE_ATTEN0'].get()) - print("INIT_CODE_ATTEN1 = ", efuses['ADC1_INIT_CODE_ATTEN1'].get()) - print("INIT_CODE_ATTEN2 = ", efuses['ADC1_INIT_CODE_ATTEN2'].get()) - print("INIT_CODE_ATTEN3 = ", efuses['ADC1_INIT_CODE_ATTEN3'].get()) - print("CAL_VOL_ATTEN0 = ", efuses['ADC1_CAL_VOL_ATTEN0'].get()) - print("CAL_VOL_ATTEN1 = ", efuses['ADC1_CAL_VOL_ATTEN1'].get()) - print("CAL_VOL_ATTEN2 = ", efuses['ADC1_CAL_VOL_ATTEN2'].get()) - print("CAL_VOL_ATTEN3 = ", efuses['ADC1_CAL_VOL_ATTEN3'].get()) - print("INIT_CODE_ATTEN0_CH0 = ", efuses['ADC1_INIT_CODE_ATTEN0_CH0'].get()) - print("INIT_CODE_ATTEN0_CH1 = ", efuses['ADC1_INIT_CODE_ATTEN0_CH1'].get()) - print("INIT_CODE_ATTEN0_CH2 = ", efuses['ADC1_INIT_CODE_ATTEN0_CH2'].get()) - print("INIT_CODE_ATTEN0_CH3 = ", efuses['ADC1_INIT_CODE_ATTEN0_CH3'].get()) - print("INIT_CODE_ATTEN0_CH4 = ", efuses['ADC1_INIT_CODE_ATTEN0_CH4'].get()) - print("INIT_CODE_ATTEN0_CH5 = ", efuses['ADC1_INIT_CODE_ATTEN0_CH5'].get()) - print("INIT_CODE_ATTEN0_CH6 = ", efuses['ADC1_INIT_CODE_ATTEN0_CH6'].get()) - else: - print("BLK_VERSION_MINOR = {}".format(efuses["BLK_VERSION_MINOR"].get_meaning())) - # fmt: on - - -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: - 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" - 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/tools/esptool_py/espefuse/efuse/esp32c61/__init__.py b/tools/esptool_py/espefuse/efuse/esp32c61/__init__.py deleted file mode 100644 index a3b55a8023..0000000000 --- a/tools/esptool_py/espefuse/efuse/esp32c61/__init__.py +++ /dev/null @@ -1,3 +0,0 @@ -from . import operations -from .emulate_efuse_controller import EmulateEfuseController -from .fields import EspEfuses diff --git a/tools/esptool_py/espefuse/efuse/esp32c61/emulate_efuse_controller.py b/tools/esptool_py/espefuse/efuse/esp32c61/emulate_efuse_controller.py deleted file mode 100644 index 1118daadae..0000000000 --- a/tools/esptool_py/espefuse/efuse/esp32c61/emulate_efuse_controller.py +++ /dev/null @@ -1,92 +0,0 @@ -# This file describes eFuses controller for ESP32-C61 chip -# -# SPDX-FileCopyrightText: 2024 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-C61" - mem = None - debug = False - - def __init__(self, efuse_file=None, debug=False): - self.Blocks = EfuseDefineBlocks - self.Fields = EfuseDefineFields(None) - 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/tools/esptool_py/espefuse/efuse/esp32c61/fields.py b/tools/esptool_py/espefuse/efuse/esp32c61/fields.py deleted file mode 100644 index 5f6fe7b8cb..0000000000 --- a/tools/esptool_py/espefuse/efuse/esp32c61/fields.py +++ /dev/null @@ -1,466 +0,0 @@ -# This file describes eFuses for ESP32-C61 chip -# -# SPDX-FileCopyrightText: 2024 Espressif Systems (Shanghai) CO LTD -# -# SPDX-License-Identifier: GPL-2.0-or-later - -import binascii -import struct -import sys -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, - extend_efuse_table=None, - ): - self.Blocks = EfuseDefineBlocks() - self.Fields = EfuseDefineFields(extend_efuse_table) - 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-C61": - raise esptool.FatalError( - "Expected the 'esp' param for ESP32-C61 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: - # 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") - sys.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") - sys.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 - ) - - 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: - 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, - "wafer": EfuseWafer, - }.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): - raise esptool.FatalError("Burning %s is not supported" % self.name) - - -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) - ("XTS_AES_256_KEY", -1, "VIRTUAL", None, "no_need_rd_protect"), # Virtual purpose splits to XTS_AES_256_KEY_1 and XTS_AES_256_KEY_2 - ] -# 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))) - 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/tools/esptool_py/espefuse/efuse/esp32c61/mem_definition.py b/tools/esptool_py/espefuse/efuse/esp32c61/mem_definition.py deleted file mode 100644 index 2f8f818a53..0000000000 --- a/tools/esptool_py/espefuse/efuse/esp32c61/mem_definition.py +++ /dev/null @@ -1,159 +0,0 @@ -# This file describes eFuses fields and registers for ESP32-C61 chip -# -# SPDX-FileCopyrightText: 2024 Espressif Systems (Shanghai) CO LTD -# -# SPDX-License-Identifier: GPL-2.0-or-later - -import os -from typing import List - -import yaml - -from ..mem_definition_base import ( - EfuseBlocksBase, - EfuseFieldsBase, - EfuseRegistersBase, -) - - -class EfuseDefineRegisters(EfuseRegistersBase): - EFUSE_MEM_SIZE = 0x01FC + 4 - - # EFUSE registers & command/conf values - DR_REG_EFUSE_BASE = 0x600B4800 - 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, extend_efuse_table) -> 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: List = [] - - 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, extend_efuse_table) - - 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/tools/esptool_py/espefuse/efuse/esp32c61/operations.py b/tools/esptool_py/espefuse/efuse/esp32c61/operations.py deleted file mode 100644 index 2306565554..0000000000 --- a/tools/esptool_py/espefuse/efuse/esp32c61/operations.py +++ /dev/null @@ -1,462 +0,0 @@ -# This file includes the operations with eFuses for ESP32-C61 chip -# -# SPDX-FileCopyrightText: 2024 Espressif Systems (Shanghai) CO LTD -# -# SPDX-License-Identifier: GPL-2.0-or-later - -import argparse -import io -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): - efuses["CUSTOM_MAC"].save(args.mac) - if not efuses.burn_all(check_batch_mode=True): - return - get_custom_mac(esp, efuses, args) - print("Successful") - - -def get_custom_mac(esp, efuses, args): - print("Custom MAC Address: {}".format(efuses["CUSTOM_MAC"].get())) - - -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 key_block_is_unused(block, key_purpose_block): - if not block.is_readable() or not block.is_writeable(): - return False - - if key_purpose_block.get() != "USER" or not key_purpose_block.is_writeable(): - return False - - if not block.get_bitstring().all(False): - return False - - return True - - -def get_next_key_block(efuses, current_key_block, block_name_list): - key_blocks = [b for b in efuses.blocks if b.key_purpose_name] - start = key_blocks.index(current_key_block) - - # Sort key blocks so that we pick the next free block (and loop around if necessary) - key_blocks = key_blocks[start:] + key_blocks[0:start] - - # Exclude any other blocks that will be be burned - key_blocks = [b for b in key_blocks if b.name not in block_name_list] - - for block in key_blocks: - key_purpose_block = efuses[block.key_purpose_name] - if key_block_is_unused(block, key_purpose_block): - return block - - return None - - -def split_512_bit_key(efuses, block_name_list, datafile_list, keypurpose_list): - i = keypurpose_list.index("XTS_AES_256_KEY") - block_name = block_name_list[i] - - block_num = efuses.get_index_block_by_name(block_name) - block = efuses.blocks[block_num] - - data = datafile_list[i].read() - if len(data) != 64: - raise esptool.FatalError( - "Incorrect key file size %d, XTS_AES_256_KEY should be 64 bytes" % len(data) - ) - - key_block_2 = get_next_key_block(efuses, block, block_name_list) - if not key_block_2: - raise esptool.FatalError("XTS_AES_256_KEY requires two free keyblocks") - - keypurpose_list.append("XTS_AES_256_KEY_1") - datafile_list.append(io.BytesIO(data[:32])) - block_name_list.append(block_name) - - keypurpose_list.append("XTS_AES_256_KEY_2") - datafile_list.append(io.BytesIO(data[32:])) - block_name_list.append(key_block_2.name) - - keypurpose_list.pop(i) - datafile_list.pop(i) - block_name_list.pop(i) - - -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]) : - ] - - if "XTS_AES_256_KEY" in keypurpose_list: - # XTS_AES_256_KEY is not an actual HW key purpose, needs to be split into - # XTS_AES_256_KEY_1 and XTS_AES_256_KEY_2 - split_512_bit_key(efuses, block_name_list, datafile_list, keypurpose_list) - - 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, and 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/tools/esptool_py/espefuse/efuse/esp32h2/__init__.py b/tools/esptool_py/espefuse/efuse/esp32h2/__init__.py deleted file mode 100644 index a3b55a8023..0000000000 --- a/tools/esptool_py/espefuse/efuse/esp32h2/__init__.py +++ /dev/null @@ -1,3 +0,0 @@ -from . import operations -from .emulate_efuse_controller import EmulateEfuseController -from .fields import EspEfuses diff --git a/tools/esptool_py/espefuse/efuse/esp32h2/emulate_efuse_controller.py b/tools/esptool_py/espefuse/efuse/esp32h2/emulate_efuse_controller.py deleted file mode 100644 index b482eab097..0000000000 --- a/tools/esptool_py/espefuse/efuse/esp32h2/emulate_efuse_controller.py +++ /dev/null @@ -1,92 +0,0 @@ -# This file describes eFuses controller for ESP32-H2 chip -# -# SPDX-FileCopyrightText: 2022 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-H2" - mem = None - debug = False - - def __init__(self, efuse_file=None, debug=False): - self.Blocks = EfuseDefineBlocks - self.Fields = EfuseDefineFields(None) - 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 32 # MHz - - 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/tools/esptool_py/espefuse/efuse/esp32h2/fields.py b/tools/esptool_py/espefuse/efuse/esp32h2/fields.py deleted file mode 100644 index 91ef6c15ca..0000000000 --- a/tools/esptool_py/espefuse/efuse/esp32h2/fields.py +++ /dev/null @@ -1,465 +0,0 @@ -# This file describes eFuses for ESP32-H2 chip -# -# SPDX-FileCopyrightText: 2022 Espressif Systems (Shanghai) CO LTD -# -# SPDX-License-Identifier: GPL-2.0-or-later - -import binascii -import struct -import sys -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, - extend_efuse_table=None, - ): - self.Blocks = EfuseDefineBlocks() - self.Fields = EfuseDefineFields(extend_efuse_table) - 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-H2": - raise esptool.FatalError( - "Expected the 'esp' param for ESP32-H2 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: - if self["BLK_VERSION_MINOR"].get() == 2: - 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") - sys.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") - sys.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() - # Based on `CONFIG_SOC_XTAL_SUPPORT_32M=y` for this target from ESP-IDF configuration - if apb_freq != 32: - raise esptool.FatalError( - "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: - 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, - "wafer": EfuseWafer, - }.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): - raise esptool.FatalError("Burning %s is not supported" % self.name) - - -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(":", "") - 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 - ("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) - ("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) - ] -# 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))) - 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/tools/esptool_py/espefuse/efuse/esp32h2/mem_definition.py b/tools/esptool_py/espefuse/efuse/esp32h2/mem_definition.py deleted file mode 100644 index 87663e95f7..0000000000 --- a/tools/esptool_py/espefuse/efuse/esp32h2/mem_definition.py +++ /dev/null @@ -1,169 +0,0 @@ -# This file describes eFuses fields and registers for ESP32-H2 chip -# -# SPDX-FileCopyrightText: 2022 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 = 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 - 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, extend_efuse_table) -> 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, extend_efuse_table) - - 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/tools/esptool_py/espefuse/efuse/esp32h2/operations.py b/tools/esptool_py/espefuse/efuse/esp32h2/operations.py deleted file mode 100644 index 2aac7448b7..0000000000 --- a/tools/esptool_py/espefuse/efuse/esp32h2/operations.py +++ /dev/null @@ -1,424 +0,0 @@ -# This file includes the operations with eFuses for ESP32-H2 chip -# -# SPDX-FileCopyrightText: 2022 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): - efuses["CUSTOM_MAC"].save(args.mac) - if not efuses.burn_all(check_batch_mode=True): - return - get_custom_mac(esp, efuses, args) - print("Successful") - - -def get_custom_mac(esp, efuses, args): - print("Custom MAC Address: {}".format(efuses["CUSTOM_MAC"].get())) - - -def set_flash_voltage(esp, efuses, args): - raise esptool.FatalError("set_flash_voltage is not supported!") - - -def adc_info(esp, efuses, args): - print("") - # fmt: off - if efuses["BLK_VERSION_MINOR"].get() == 2: - print("Temperature Sensor Calibration = {}C".format(efuses["TEMP_CALIB"].get())) - print("") - print("ADC1:") - print("AVE_INITCODE_ATTEN0 = ", efuses["ADC1_AVE_INITCODE_ATTEN0"].get()) - print("AVE_INITCODE_ATTEN1 = ", efuses["ADC1_AVE_INITCODE_ATTEN1"].get()) - print("AVE_INITCODE_ATTEN2 = ", efuses["ADC1_AVE_INITCODE_ATTEN2"].get()) - print("AVE_INITCODE_ATTEN3 = ", efuses["ADC1_AVE_INITCODE_ATTEN3"].get()) - print("HI_DOUT_ATTEN0 = ", efuses["ADC1_HI_DOUT_ATTEN0"].get()) - print("HI_DOUT_ATTEN1 = ", efuses["ADC1_HI_DOUT_ATTEN1"].get()) - print("HI_DOUT_ATTEN2 = ", efuses["ADC1_HI_DOUT_ATTEN2"].get()) - print("HI_DOUT_ATTEN3 = ", efuses["ADC1_HI_DOUT_ATTEN3"].get()) - print("CH0_ATTEN0_INITCODE_DIFF = ", efuses["ADC1_CH0_ATTEN0_INITCODE_DIFF"].get()) - print("CH1_ATTEN0_INITCODE_DIFF = ", efuses["ADC1_CH1_ATTEN0_INITCODE_DIFF"].get()) - print("CH2_ATTEN0_INITCODE_DIFF = ", efuses["ADC1_CH2_ATTEN0_INITCODE_DIFF"].get()) - print("CH3_ATTEN0_INITCODE_DIFF = ", efuses["ADC1_CH3_ATTEN0_INITCODE_DIFF"].get()) - print("CH4_ATTEN0_INITCODE_DIFF = ", efuses["ADC1_CH4_ATTEN0_INITCODE_DIFF"].get()) - else: - print("BLK_VERSION_MINOR = {}".format(efuses["BLK_VERSION_MINOR"].get())) - # fmt: on - - -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 keypurpose == "ECDSA_KEY": - if efuses["ECDSA_FORCE_USE_HARDWARE_K"].get() == 0: - # For ECDSA key purpose block permanently enable - # the hardware TRNG supplied k mode (most secure mode) - print("\tECDSA_FORCE_USE_HARDWARE_K: 0 -> 1") - efuses["ECDSA_FORCE_USE_HARDWARE_K"].save(1) - else: - print("\tECDSA_FORCE_USE_HARDWARE_K is already '1'") - - 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/tools/esptool_py/espefuse/efuse/esp32h2beta1/__init__.py b/tools/esptool_py/espefuse/efuse/esp32h2beta1/__init__.py deleted file mode 100644 index a3b55a8023..0000000000 --- a/tools/esptool_py/espefuse/efuse/esp32h2beta1/__init__.py +++ /dev/null @@ -1,3 +0,0 @@ -from . import operations -from .emulate_efuse_controller import EmulateEfuseController -from .fields import EspEfuses diff --git a/tools/esptool_py/espefuse/efuse/esp32h2beta1/emulate_efuse_controller.py b/tools/esptool_py/espefuse/efuse/esp32h2beta1/emulate_efuse_controller.py deleted file mode 100644 index 1c336cbfea..0000000000 --- a/tools/esptool_py/espefuse/efuse/esp32h2beta1/emulate_efuse_controller.py +++ /dev/null @@ -1,92 +0,0 @@ -# This file describes eFuses controller for ESP32-H2 chip -# -# SPDX-FileCopyrightText: 2021-2022 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-H2(beta1)" - mem = None - debug = False - - def __init__(self, efuse_file=None, debug=False): - self.Blocks = EfuseDefineBlocks - self.Fields = EfuseDefineFields(None) - 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 32 # 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/tools/esptool_py/espefuse/efuse/esp32h2beta1/fields.py b/tools/esptool_py/espefuse/efuse/esp32h2beta1/fields.py deleted file mode 100644 index 90fb72bb58..0000000000 --- a/tools/esptool_py/espefuse/efuse/esp32h2beta1/fields.py +++ /dev/null @@ -1,465 +0,0 @@ -# This file describes eFuses for ESP32-H2 chip -# -# SPDX-FileCopyrightText: 2021-2022 Espressif Systems (Shanghai) CO LTD -# -# SPDX-License-Identifier: GPL-2.0-or-later - -import binascii -import struct -import sys -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, - extend_efuse_table=None, - ): - self.Blocks = EfuseDefineBlocks() - self.Fields = EfuseDefineFields(extend_efuse_table) - 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-H2(beta1)": - raise esptool.FatalError( - "Expected the 'esp' param for ESP32-H2(beta1) 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: - if self["BLK_VERSION_MINOR"].get() == 2: - 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") - sys.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") - sys.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 != 32: - raise esptool.FatalError( - "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: - 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, - "wafer": EfuseWafer, - }.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): - raise esptool.FatalError("Burning %s is not supported" % self.name) - - -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") - raise esptool.FatalError("Writing Factory MAC address 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 - ("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) - ] -# 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))) - 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/tools/esptool_py/espefuse/efuse/esp32h2beta1/mem_definition.py b/tools/esptool_py/espefuse/efuse/esp32h2beta1/mem_definition.py deleted file mode 100644 index 73bfb370ed..0000000000 --- a/tools/esptool_py/espefuse/efuse/esp32h2beta1/mem_definition.py +++ /dev/null @@ -1,156 +0,0 @@ -# This file describes eFuses fields and registers for ESP32-H2 chip -# -# SPDX-FileCopyrightText: 2021-2022 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 -from typing import List - - -class EfuseDefineRegisters(EfuseRegistersBase): - 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 - 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, extend_efuse_table) -> 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: List = [] - - 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, extend_efuse_table) - - 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/tools/esptool_py/espefuse/efuse/esp32h2beta1/operations.py b/tools/esptool_py/espefuse/efuse/esp32h2beta1/operations.py deleted file mode 100644 index f884b8aa55..0000000000 --- a/tools/esptool_py/espefuse/efuse/esp32h2beta1/operations.py +++ /dev/null @@ -1,407 +0,0 @@ -# This file includes the operations with eFuses for ESP32-H2 chip -# -# SPDX-FileCopyrightText: 2021-2022 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", - 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", - 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): - efuses["CUSTOM_MAC"].save(args.mac) - if not efuses.burn_all(check_batch_mode=True): - return - get_custom_mac(esp, efuses, args) - print("Successful") - - -def get_custom_mac(esp, efuses, args): - print("Custom MAC Address: {}".format(efuses["CUSTOM_MAC"].get())) - - -def set_flash_voltage(esp, efuses, args): - raise esptool.FatalError("set_flash_voltage is not supported!") - - -def adc_info(esp, efuses, args): - print("") - # fmt: off - if efuses["BLK_VERSION_MINOR"].get() == 2: - print("Temperature Sensor Calibration = {}C".format(efuses["TEMP_CALIB"].get())) - print("") - print("ADC1:") - print("AVE_INITCODE_ATTEN0 = ", efuses["ADC1_AVE_INITCODE_ATTEN0"].get()) - print("AVE_INITCODE_ATTEN1 = ", efuses["ADC1_AVE_INITCODE_ATTEN1"].get()) - print("AVE_INITCODE_ATTEN2 = ", efuses["ADC1_AVE_INITCODE_ATTEN2"].get()) - print("AVE_INITCODE_ATTEN3 = ", efuses["ADC1_AVE_INITCODE_ATTEN3"].get()) - print("HI_DOUT_ATTEN0 = ", efuses["ADC1_HI_DOUT_ATTEN0"].get()) - print("HI_DOUT_ATTEN1 = ", efuses["ADC1_HI_DOUT_ATTEN1"].get()) - print("HI_DOUT_ATTEN2 = ", efuses["ADC1_HI_DOUT_ATTEN2"].get()) - print("HI_DOUT_ATTEN3 = ", efuses["ADC1_HI_DOUT_ATTEN3"].get()) - print("CH0_ATTEN0_INITCODE_DIFF = ", efuses["ADC1_CH0_ATTEN0_INITCODE_DIFF"].get()) - print("CH1_ATTEN0_INITCODE_DIFF = ", efuses["ADC1_CH1_ATTEN0_INITCODE_DIFF"].get()) - print("CH2_ATTEN0_INITCODE_DIFF = ", efuses["ADC1_CH2_ATTEN0_INITCODE_DIFF"].get()) - print("CH3_ATTEN0_INITCODE_DIFF = ", efuses["ADC1_CH3_ATTEN0_INITCODE_DIFF"].get()) - print("CH4_ATTEN0_INITCODE_DIFF = ", efuses["ADC1_CH4_ATTEN0_INITCODE_DIFF"].get()) - else: - print("BLK_VERSION_MINOR = {}".format(efuses["BLK_VERSION_MINOR"].get())) - # fmt: on - - -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: - 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" - 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/tools/esptool_py/espefuse/efuse/esp32p4/__init__.py b/tools/esptool_py/espefuse/efuse/esp32p4/__init__.py deleted file mode 100644 index a3b55a8023..0000000000 --- a/tools/esptool_py/espefuse/efuse/esp32p4/__init__.py +++ /dev/null @@ -1,3 +0,0 @@ -from . import operations -from .emulate_efuse_controller import EmulateEfuseController -from .fields import EspEfuses diff --git a/tools/esptool_py/espefuse/efuse/esp32p4/emulate_efuse_controller.py b/tools/esptool_py/espefuse/efuse/esp32p4/emulate_efuse_controller.py deleted file mode 100644 index adae384df3..0000000000 --- a/tools/esptool_py/espefuse/efuse/esp32p4/emulate_efuse_controller.py +++ /dev/null @@ -1,92 +0,0 @@ -# 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(None) - 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/tools/esptool_py/espefuse/efuse/esp32p4/fields.py b/tools/esptool_py/espefuse/efuse/esp32p4/fields.py deleted file mode 100644 index e28d788dc8..0000000000 --- a/tools/esptool_py/espefuse/efuse/esp32p4/fields.py +++ /dev/null @@ -1,442 +0,0 @@ -# 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 sys -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, - extend_efuse_table=None, - ): - self.Blocks = EfuseDefineBlocks() - self.Fields = EfuseDefineFields(extend_efuse_table) - 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") - sys.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") - sys.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 - ("XTS_AES_256_KEY", -1, "VIRTUAL", None, "no_need_rd_protect"), # Virtual purpose splits to XTS_AES_256_KEY_1 and XTS_AES_256_KEY_2 - ] -# 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/tools/esptool_py/espefuse/efuse/esp32p4/mem_definition.py b/tools/esptool_py/espefuse/efuse/esp32p4/mem_definition.py deleted file mode 100644 index c1427e516a..0000000000 --- a/tools/esptool_py/espefuse/efuse/esp32p4/mem_definition.py +++ /dev/null @@ -1,159 +0,0 @@ -# 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, -) -from typing import List - - -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, extend_efuse_table) -> 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: List = [] - - 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, extend_efuse_table) - - 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/tools/esptool_py/espefuse/efuse/esp32p4/operations.py b/tools/esptool_py/espefuse/efuse/esp32p4/operations.py deleted file mode 100644 index b24a735121..0000000000 --- a/tools/esptool_py/espefuse/efuse/esp32p4/operations.py +++ /dev/null @@ -1,458 +0,0 @@ -# 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 io -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 key_block_is_unused(block, key_purpose_block): - if not block.is_readable() or not block.is_writeable(): - return False - - if key_purpose_block.get() != "USER" or not key_purpose_block.is_writeable(): - return False - - if not block.get_bitstring().all(False): - return False - - return True - - -def get_next_key_block(efuses, current_key_block, block_name_list): - key_blocks = [b for b in efuses.blocks if b.key_purpose_name] - start = key_blocks.index(current_key_block) - - # Sort key blocks so that we pick the next free block (and loop around if necessary) - key_blocks = key_blocks[start:] + key_blocks[0:start] - - # Exclude any other blocks that will be be burned - key_blocks = [b for b in key_blocks if b.name not in block_name_list] - - for block in key_blocks: - key_purpose_block = efuses[block.key_purpose_name] - if key_block_is_unused(block, key_purpose_block): - return block - - return None - - -def split_512_bit_key(efuses, block_name_list, datafile_list, keypurpose_list): - i = keypurpose_list.index("XTS_AES_256_KEY") - block_name = block_name_list[i] - - block_num = efuses.get_index_block_by_name(block_name) - block = efuses.blocks[block_num] - - data = datafile_list[i].read() - if len(data) != 64: - raise esptool.FatalError( - "Incorrect key file size %d, XTS_AES_256_KEY should be 64 bytes" % len(data) - ) - - key_block_2 = get_next_key_block(efuses, block, block_name_list) - if not key_block_2: - raise esptool.FatalError("XTS_AES_256_KEY requires two free keyblocks") - - keypurpose_list.append("XTS_AES_256_KEY_1") - datafile_list.append(io.BytesIO(data[:32])) - block_name_list.append(block_name) - - keypurpose_list.append("XTS_AES_256_KEY_2") - datafile_list.append(io.BytesIO(data[32:])) - block_name_list.append(key_block_2.name) - - keypurpose_list.pop(i) - datafile_list.pop(i) - block_name_list.pop(i) - - -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]) : - ] - - if "XTS_AES_256_KEY" in keypurpose_list: - # XTS_AES_256_KEY is not an actual HW key purpose, needs to be split into - # XTS_AES_256_KEY_1 and XTS_AES_256_KEY_2 - split_512_bit_key(efuses, block_name_list, datafile_list, keypurpose_list) - - 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/tools/esptool_py/espefuse/efuse/esp32s2/__init__.py b/tools/esptool_py/espefuse/efuse/esp32s2/__init__.py deleted file mode 100644 index a3b55a8023..0000000000 --- a/tools/esptool_py/espefuse/efuse/esp32s2/__init__.py +++ /dev/null @@ -1,3 +0,0 @@ -from . import operations -from .emulate_efuse_controller import EmulateEfuseController -from .fields import EspEfuses diff --git a/tools/esptool_py/espefuse/efuse/esp32s2/emulate_efuse_controller.py b/tools/esptool_py/espefuse/efuse/esp32s2/emulate_efuse_controller.py deleted file mode 100644 index 6c88ed54ba..0000000000 --- a/tools/esptool_py/espefuse/efuse/esp32s2/emulate_efuse_controller.py +++ /dev/null @@ -1,92 +0,0 @@ -# This file describes eFuses controller for ESP32-S2 chip -# -# SPDX-FileCopyrightText: 2020-2022 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-S2" - mem = None - debug = False - - def __init__(self, efuse_file=None, debug=False): - self.Blocks = EfuseDefineBlocks - self.Fields = EfuseDefineFields(None) - 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 1 - - 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": None, - "api_version": None, - } - - """ << 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/tools/esptool_py/espefuse/efuse/esp32s2/fields.py b/tools/esptool_py/espefuse/efuse/esp32s2/fields.py deleted file mode 100644 index 1339fdb143..0000000000 --- a/tools/esptool_py/espefuse/efuse/esp32s2/fields.py +++ /dev/null @@ -1,498 +0,0 @@ -# This file describes eFuses for ESP32S2 chip -# -# SPDX-FileCopyrightText: 2020-2022 Espressif Systems (Shanghai) CO LTD -# -# SPDX-License-Identifier: GPL-2.0-or-later - -import binascii -import struct -import sys -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, - extend_efuse_table=None, - ): - self.Blocks = EfuseDefineBlocks() - self.Fields = EfuseDefineFields(extend_efuse_table) - 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-S2": - raise esptool.FatalError( - "Expected the 'esp' param for ESP32-S2 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: - 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") - sys.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") - sys.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() - ( - EFUSE_TSUP_A, - EFUSE_TPGM, - EFUSE_THP_A, - EFUSE_TPGM_INACTIVE, - ) = self.REGS.EFUSE_PROGRAMMING_TIMING_PARAMETERS[apb_freq] - self.update_reg( - self.REGS.EFUSE_WR_TIM_CONF1_REG, self.REGS.EFUSE_TSUP_A_M, EFUSE_TSUP_A - ) - self.update_reg( - self.REGS.EFUSE_WR_TIM_CONF0_REG, self.REGS.EFUSE_TPGM_M, EFUSE_TPGM - ) - self.update_reg( - self.REGS.EFUSE_WR_TIM_CONF0_REG, self.REGS.EFUSE_THP_A_M, EFUSE_THP_A - ) - self.update_reg( - self.REGS.EFUSE_WR_TIM_CONF0_REG, - self.REGS.EFUSE_TPGM_INACTIVE_M, - EFUSE_TPGM_INACTIVE, - ) - - ( - EFUSE_DAC_CLK_DIV, - EFUSE_PWR_ON_NUM, - EFUSE_PWR_OFF_NUM, - ) = self.REGS.VDDQ_TIMING_PARAMETERS[apb_freq] - self.update_reg( - self.REGS.EFUSE_DAC_CONF_REG, - self.REGS.EFUSE_DAC_CLK_DIV_M, - EFUSE_DAC_CLK_DIV, - ) - self.update_reg( - self.REGS.EFUSE_WR_TIM_CONF1_REG, - self.REGS.EFUSE_PWR_ON_NUM_M, - EFUSE_PWR_ON_NUM, - ) - self.update_reg( - self.REGS.EFUSE_WR_TIM_CONF2_REG, - self.REGS.EFUSE_PWR_OFF_NUM_M, - EFUSE_PWR_OFF_NUM, - ) - - EFUSE_TSUR_A, EFUSE_TRD, EFUSE_THR_A = self.REGS.EFUSE_READING_PARAMETERS[ - apb_freq - ] - # self.update_reg( - # self.REGS.EFUSE_RD_TIM_CONF_REG, self.REGS.EFUSE_TSUR_A_M, EFUSE_TSUR_A - # ) - self.update_reg( - self.REGS.EFUSE_RD_TIM_CONF_REG, self.REGS.EFUSE_TRD_M, EFUSE_TRD - ) - self.update_reg( - self.REGS.EFUSE_RD_TIM_CONF_REG, self.REGS.EFUSE_THR_A_M, EFUSE_THR_A - ) - - 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): - if self["VDD_SPI_FORCE"].get() == 0: - output = "Flash voltage (VDD_SPI) determined by GPIO45 on reset " - 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 " - 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: - output = "Flash voltage (VDD_SPI) set to 1.8V by efuse." - else: - output = "Flash voltage (VDD_SPI) set to 3.3V by efuse." - return output - - -class EfuseField(base_fields.EfuseFieldBase): - @staticmethod - def convert(parent, efuse): - return { - "mac": EfuseMacField, - "keypurpose": EfuseKeyPurposeField, - "t_sensor": EfuseTempSensor, - "adc_tp": EfuseAdcPointCalibration, - "wafer": EfuseWafer, - }.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): - raise esptool.FatalError("Burning %s is not supported" % self.name) - - -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!" - ) - if new_value_str.count(":") != 5: - raise esptool.FatalError( - "MAC Address needs to be a 6-byte hexadecimal format " - "separated by colons (:)!" - ) - hexad = new_value_str.replace(":", "") - if len(hexad) != 12: - raise esptool.FatalError( - "MAC Address needs to be a 6-byte hexadecimal number " - "(12 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!") - 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] - 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("Writing Factory MAC address 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 - ("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) - ("XTS_AES_256_KEY", -1, "VIRTUAL", None, "no_need_rd_protect"), # Virtual purpose splits to XTS_AES_256_KEY_1 and XTS_AES_256_KEY_2 - ] -# 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 save(self, new_value): - raw_val = int(self.check_format(str(new_value))) - return super(EfuseKeyPurposeField, self).save(raw_val) diff --git a/tools/esptool_py/espefuse/efuse/esp32s2/mem_definition.py b/tools/esptool_py/espefuse/efuse/esp32s2/mem_definition.py deleted file mode 100644 index 4799751db9..0000000000 --- a/tools/esptool_py/espefuse/efuse/esp32s2/mem_definition.py +++ /dev/null @@ -1,208 +0,0 @@ -# This file describes eFuses fields and registers for ESP32 chip -# -# SPDX-FileCopyrightText: 2020-2022 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 = 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 - 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 + 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 - - 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_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 - - EFUSE_RD_TIM_CONF_REG = DR_REG_EFUSE_BASE + 0x1EC - EFUSE_TSUR_A_S = 16 - EFUSE_TSUR_A_M = 0xFF << EFUSE_TSUR_A_S - EFUSE_TRD_S = 8 - EFUSE_TRD_M = 0xFF << EFUSE_TRD_S - EFUSE_THR_A_S = 0 - EFUSE_THR_A_M = 0xFF << EFUSE_THR_A_S - - EFUSE_WR_TIM_CONF0_REG = DR_REG_EFUSE_BASE + 0x1F0 - EFUSE_TPGM_S = 16 - EFUSE_TPGM_M = 0xFFFF << EFUSE_TPGM_S - EFUSE_TPGM_INACTIVE_S = 8 - EFUSE_TPGM_INACTIVE_M = 0xFF << EFUSE_TPGM_INACTIVE_S - EFUSE_THP_A_S = 0 - EFUSE_THP_A_M = 0xFF << EFUSE_THP_A_S - - # EFUSE_WR_TIM_CONF1_REG - EFUSE_PWR_ON_NUM_S = 8 - EFUSE_PWR_ON_NUM_M = 0xFFFF << EFUSE_PWR_ON_NUM_S - EFUSE_TSUP_A_S = 0 - EFUSE_TSUP_A_M = 0xFF << EFUSE_TSUP_A_S - - # EFUSE_WR_TIM_CONF2_REG - EFUSE_PWR_OFF_NUM_S = 0 - EFUSE_PWR_OFF_NUM_M = 0xFFFF << EFUSE_PWR_OFF_NUM_S - - # Configure clock - EFUSE_PROGRAMMING_TIMING_PARAMETERS = { - # APB Frequency: ( EFUSE_TSUP_A, EFUSE_TPGM, EFUSE_THP_A, EFUSE_TPGM_INACTIVE ) - # Taken from TRM chapter "eFuse Controller": eFuse-Programming Timing - 80: (0x2, 0x320, 0x2, 0x4), - 40: (0x1, 0x190, 0x1, 0x2), - 20: (0x1, 0xC8, 0x1, 0x1), - } - - VDDQ_TIMING_PARAMETERS = { - # APB Frequency: ( EFUSE_DAC_CLK_DIV, EFUSE_PWR_ON_NUM, EFUSE_PWR_OFF_NUM ) - # Taken from TRM chapter "eFuse Controller": eFuse VDDQ Timing Setting - 80: (0xA0, 0xA200, 0x100), - 40: (0x50, 0x5100, 0x80), - 20: (0x28, 0x2880, 0x40), - } - - EFUSE_READING_PARAMETERS = { - # APB Frequency: ( EFUSE_TSUR_A, EFUSE_TRD, EFUSE_THR_A ) - # Taken from TRM chapter "eFuse Controller": eFuse-Read Timing - 80: (0x2, 0x4, 0x2), - 40: (0x1, 0x2, 0x1), - 20: (0x1, 0x1, 0x1), - } - - -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, extend_efuse_table) -> 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, extend_efuse_table) - - 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/tools/esptool_py/espefuse/efuse/esp32s2/operations.py b/tools/esptool_py/espefuse/efuse/esp32s2/operations.py deleted file mode 100644 index 3f015e2216..0000000000 --- a/tools/esptool_py/espefuse/efuse/esp32s2/operations.py +++ /dev/null @@ -1,521 +0,0 @@ -# This file includes the operations with eFuses for ESP32S2 chip -# -# SPDX-FileCopyrightText: 2020-2022 Espressif Systems (Shanghai) CO LTD -# -# SPDX-License-Identifier: GPL-2.0-or-later - -import argparse -import io -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", - 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", - 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): - efuses["CUSTOM_MAC"].save(args.mac) - if not efuses.burn_all(check_batch_mode=True): - return - get_custom_mac(esp, efuses, args) - print("Successful") - - -def get_custom_mac(esp, efuses, args): - print("Custom MAC Address: {}".format(efuses["CUSTOM_MAC"].get())) - - -def set_flash_voltage(esp, efuses, args): - sdio_force = efuses["VDD_SPI_FORCE"] - sdio_tieh = efuses["VDD_SPI_TIEH"] - sdio_reg = efuses["VDD_SPI_XPD"] - - # check efuses aren't burned in a way which makes this impossible - if args.voltage == "OFF" and sdio_reg.get() != 0: - raise esptool.FatalError( - "Can't set flash regulator to OFF as VDD_SPI_XPD efuse is already burned" - ) - - if args.voltage == "1.8V" and sdio_tieh.get() != 0: - raise esptool.FatalError( - "Can't set regulator to 1.8V is VDD_SPI_TIEH efuse is already burned" - ) - - if args.voltage == "OFF": - msg = "Disable internal flash voltage regulator (VDD_SPI). SPI flash will " - "need to be powered from an external source.\n" - "The following efuse is burned: VDD_SPI_FORCE.\n" - "It is possible to later re-enable the internal regulator (%s) " % ( - "to 3.3V" if sdio_tieh.get() != 0 else "to 1.8V or 3.3V" - ) - "by burning an additional efuse" - elif args.voltage == "1.8V": - msg = "Set internal flash voltage regulator (VDD_SPI) to 1.8V.\n" - "The following efuses are burned: VDD_SPI_FORCE, VDD_SPI_XPD.\n" - "It is possible to later increase the voltage to 3.3V (permanently) " - "by burning additional efuse VDD_SPI_TIEH" - elif args.voltage == "3.3V": - msg = "Enable internal flash voltage regulator (VDD_SPI) to 3.3V.\n" - "The following efuses are burned: VDD_SPI_FORCE, VDD_SPI_XPD, VDD_SPI_TIEH." - print(msg) - - sdio_force.save(1) # Disable GPIO45 - if args.voltage != "OFF": - sdio_reg.save(1) # Enable internal regulator - if args.voltage == "3.3V": - sdio_tieh.save(1) - print("VDD_SPI setting complete.") - - if not efuses.burn_all(check_batch_mode=True): - return - print("Successful") - - -def adc_info(esp, efuses, args): - print("") - # fmt: off - if efuses["BLK_VERSION_MINOR"].get() == 1: - print("Temperature Sensor Calibration = {}C".format(efuses["TEMP_CALIB"].get())) - print("TADC_CALIB = {}C".format(efuses["ADC_CALIB"].get())) - print("RTCCALIB_V1IDX_A10H = ", efuses["RTCCALIB_V1IDX_A10H"].get()) - print("RTCCALIB_V1IDX_A11H = ", efuses["RTCCALIB_V1IDX_A11H"].get()) - print("RTCCALIB_V1IDX_A12H = ", efuses["RTCCALIB_V1IDX_A12H"].get()) - print("RTCCALIB_V1IDX_A13H = ", efuses["RTCCALIB_V1IDX_A13H"].get()) - print("RTCCALIB_V1IDX_A20H = ", efuses["RTCCALIB_V1IDX_A20H"].get()) - print("RTCCALIB_V1IDX_A21H = ", efuses["RTCCALIB_V1IDX_A21H"].get()) - print("RTCCALIB_V1IDX_A22H = ", efuses["RTCCALIB_V1IDX_A22H"].get()) - print("RTCCALIB_V1IDX_A23H = ", efuses["RTCCALIB_V1IDX_A23H"].get()) - print("RTCCALIB_V1IDX_A10L = ", efuses["RTCCALIB_V1IDX_A10L"].get()) - print("RTCCALIB_V1IDX_A11L = ", efuses["RTCCALIB_V1IDX_A11L"].get()) - print("RTCCALIB_V1IDX_A12L = ", efuses["RTCCALIB_V1IDX_A12L"].get()) - print("RTCCALIB_V1IDX_A13L = ", efuses["RTCCALIB_V1IDX_A13L"].get()) - print("RTCCALIB_V1IDX_A20L = ", efuses["RTCCALIB_V1IDX_A20L"].get()) - print("RTCCALIB_V1IDX_A21L = ", efuses["RTCCALIB_V1IDX_A21L"].get()) - print("RTCCALIB_V1IDX_A22L = ", efuses["RTCCALIB_V1IDX_A22L"].get()) - print("RTCCALIB_V1IDX_A23L = ", efuses["RTCCALIB_V1IDX_A23L"].get()) - else: - print("BLK_VERSION_MINOR = ", efuses["BLK_VERSION_MINOR"].get_meaning()) - # fmt: on - - -def key_block_is_unused(block, key_purpose_block): - if not block.is_readable() or not block.is_writeable(): - return False - - if key_purpose_block.get() != "USER" or not key_purpose_block.is_writeable(): - return False - - if not block.get_bitstring().all(False): - return False - - return True - - -def get_next_key_block(efuses, current_key_block, block_name_list): - key_blocks = [b for b in efuses.blocks if b.key_purpose_name] - start = key_blocks.index(current_key_block) - - # Sort key blocks so that we pick the next free block (and loop around if necessary) - key_blocks = key_blocks[start:] + key_blocks[0:start] - - # Exclude any other blocks that will be be burned - key_blocks = [b for b in key_blocks if b.name not in block_name_list] - - for block in key_blocks: - key_purpose_block = efuses[block.key_purpose_name] - if key_block_is_unused(block, key_purpose_block): - return block - - return None - - -def split_512_bit_key(efuses, block_name_list, datafile_list, keypurpose_list): - i = keypurpose_list.index("XTS_AES_256_KEY") - block_name = block_name_list[i] - - block_num = efuses.get_index_block_by_name(block_name) - block = efuses.blocks[block_num] - - data = datafile_list[i].read() - if len(data) != 64: - raise esptool.FatalError( - "Incorrect key file size %d, XTS_AES_256_KEY should be 64 bytes" % len(data) - ) - - key_block_2 = get_next_key_block(efuses, block, block_name_list) - if not key_block_2: - raise esptool.FatalError("XTS_AES_256_KEY requires two free keyblocks") - - keypurpose_list.append("XTS_AES_256_KEY_1") - datafile_list.append(io.BytesIO(data[:32])) - block_name_list.append(block_name) - - keypurpose_list.append("XTS_AES_256_KEY_2") - datafile_list.append(io.BytesIO(data[32:])) - block_name_list.append(key_block_2.name) - - keypurpose_list.pop(i) - datafile_list.pop(i) - block_name_list.pop(i) - - -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]) : - ] - - if "XTS_AES_256_KEY" in keypurpose_list: - # XTS_AES_256_KEY is not an actual HW key purpose, needs to be split into - # XTS_AES_256_KEY_1 and XTS_AES_256_KEY_2 - split_512_bit_key(efuses, block_name_list, datafile_list, keypurpose_list) - - 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: - 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" - 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/tools/esptool_py/espefuse/efuse/esp32s3/__init__.py b/tools/esptool_py/espefuse/efuse/esp32s3/__init__.py deleted file mode 100644 index a3b55a8023..0000000000 --- a/tools/esptool_py/espefuse/efuse/esp32s3/__init__.py +++ /dev/null @@ -1,3 +0,0 @@ -from . import operations -from .emulate_efuse_controller import EmulateEfuseController -from .fields import EspEfuses diff --git a/tools/esptool_py/espefuse/efuse/esp32s3/emulate_efuse_controller.py b/tools/esptool_py/espefuse/efuse/esp32s3/emulate_efuse_controller.py deleted file mode 100644 index 9446c6af33..0000000000 --- a/tools/esptool_py/espefuse/efuse/esp32s3/emulate_efuse_controller.py +++ /dev/null @@ -1,92 +0,0 @@ -# This file describes eFuses controller for ESP32-S3 chip -# -# SPDX-FileCopyrightText: 2020-2022 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-S3" - mem = None - debug = False - - def __init__(self, efuse_file=None, debug=False): - self.Blocks = EfuseDefineBlocks - self.Fields = EfuseDefineFields(None) - 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 2 - - 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/tools/esptool_py/espefuse/efuse/esp32s3/fields.py b/tools/esptool_py/espefuse/efuse/esp32s3/fields.py deleted file mode 100644 index 9bb4eeaf30..0000000000 --- a/tools/esptool_py/espefuse/efuse/esp32s3/fields.py +++ /dev/null @@ -1,489 +0,0 @@ -# This file describes eFuses for ESP32-S3 chip -# -# SPDX-FileCopyrightText: 2020-2022 Espressif Systems (Shanghai) CO LTD -# -# SPDX-License-Identifier: GPL-2.0-or-later - -import binascii -import struct -import sys -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, - extend_efuse_table=None, - ): - self.Blocks = EfuseDefineBlocks() - self.Fields = EfuseDefineFields(extend_efuse_table) - 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-S3": - raise esptool.FatalError( - "Expected the 'esp' param for ESP32-S3 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: - if self["BLK_VERSION_MAJOR"].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") - sys.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") - sys.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 - ) - - 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: - 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): - if self["VDD_SPI_FORCE"].get() == 0: - output = "Flash voltage (VDD_SPI) determined by GPIO45 on reset " - 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 " - 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: - output = "Flash voltage (VDD_SPI) set to 1.8V by efuse." - else: - output = "Flash voltage (VDD_SPI) set to 3.3V by efuse." - return output - - def is_efuses_incompatible_for_burn(self): - # getting chip version: self._esp.get_chip_revision() - if ( - ( - self["DIS_USB_JTAG"].get() - and self["DIS_USB_SERIAL_JTAG"].get(from_read=False) - ) - or ( - self["DIS_USB_JTAG"].get(from_read=False) - and self["DIS_USB_SERIAL_JTAG"].get() - ) - or ( - self["DIS_USB_JTAG"].get(from_read=False) - and self["DIS_USB_SERIAL_JTAG"].get(from_read=False) - ) - ): - print( - "DIS_USB_JTAG and DIS_USB_SERIAL_JTAG cannot be set together due to a bug in the ROM bootloader!" - ) - return True - return False - - -class EfuseField(base_fields.EfuseFieldBase): - @staticmethod - def convert(parent, efuse): - return { - "mac": EfuseMacField, - "keypurpose": EfuseKeyPurposeField, - "t_sensor": EfuseTempSensor, - "adc_tp": EfuseAdcPointCalibration, - "wafer": EfuseWafer, - }.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): - raise esptool.FatalError("Burning %s is not supported" % self.name) - - -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!" - ) - if new_value_str.count(":") != 5: - raise esptool.FatalError( - "MAC Address needs to be a 6-byte hexadecimal format " - "separated by colons (:)!" - ) - hexad = new_value_str.replace(":", "") - if len(hexad) != 12: - raise esptool.FatalError( - "MAC Address needs to be a 6-byte hexadecimal number " - "(12 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!") - 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] - 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 sensible, - # as it's written in the factory. - raise esptool.FatalError("Writing Factory MAC address 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 - ("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) - ("XTS_AES_256_KEY", -1, "VIRTUAL", None, "no_need_rd_protect"), # Virtual purpose splits to XTS_AES_256_KEY_1 and XTS_AES_256_KEY_2 - ] -# 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))) - 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/tools/esptool_py/espefuse/efuse/esp32s3/mem_definition.py b/tools/esptool_py/espefuse/efuse/esp32s3/mem_definition.py deleted file mode 100644 index 11aecfa651..0000000000 --- a/tools/esptool_py/espefuse/efuse/esp32s3/mem_definition.py +++ /dev/null @@ -1,170 +0,0 @@ -# This file describes eFuses fields and registers for ESP32-S3 chip -# -# SPDX-FileCopyrightText: 2020-2022 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_ADDR_MASK = 0x00000FFF - 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 - 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 + 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 - - 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, extend_efuse_table) -> 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, extend_efuse_table) - - 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/tools/esptool_py/espefuse/efuse/esp32s3/operations.py b/tools/esptool_py/espefuse/efuse/esp32s3/operations.py deleted file mode 100644 index 912ae3f0c0..0000000000 --- a/tools/esptool_py/espefuse/efuse/esp32s3/operations.py +++ /dev/null @@ -1,521 +0,0 @@ -# This file includes the operations with eFuses for ESP32-S3 chip -# -# SPDX-FileCopyrightText: 2020-2022 Espressif Systems (Shanghai) CO LTD -# -# SPDX-License-Identifier: GPL-2.0-or-later - -import argparse -import io -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", - 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", - 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): - efuses["CUSTOM_MAC"].save(args.mac) - if not efuses.burn_all(check_batch_mode=True): - return - get_custom_mac(esp, efuses, args) - print("Successful") - - -def get_custom_mac(esp, efuses, args): - print("Custom MAC Address: {}".format(efuses["CUSTOM_MAC"].get())) - - -def set_flash_voltage(esp, efuses, args): - sdio_force = efuses["VDD_SPI_FORCE"] - sdio_tieh = efuses["VDD_SPI_TIEH"] - sdio_reg = efuses["VDD_SPI_XPD"] - - # check efuses aren't burned in a way which makes this impossible - if args.voltage == "OFF" and sdio_reg.get() != 0: - raise esptool.FatalError( - "Can't set flash regulator to OFF as VDD_SPI_XPD efuse is already burned" - ) - - if args.voltage == "1.8V" and sdio_tieh.get() != 0: - raise esptool.FatalError( - "Can't set regulator to 1.8V is VDD_SPI_TIEH efuse is already burned" - ) - - if args.voltage == "OFF": - msg = "Disable internal flash voltage regulator (VDD_SPI). " - "SPI flash will need to be powered from an external source.\n" - "The following efuse is burned: VDD_SPI_FORCE.\n" - "It is possible to later re-enable the internal regulator (%s) " % ( - "to 3.3V" if sdio_tieh.get() != 0 else "to 1.8V or 3.3V" - ) - "by burning an additional efuse" - elif args.voltage == "1.8V": - msg = "Set internal flash voltage regulator (VDD_SPI) to 1.8V.\n" - "The following efuses are burned: VDD_SPI_FORCE, VDD_SPI_XPD.\n" - "It is possible to later increase the voltage to 3.3V (permanently) " - "by burning additional efuse VDD_SPI_TIEH" - elif args.voltage == "3.3V": - msg = "Enable internal flash voltage regulator (VDD_SPI) to 3.3V.\n" - "The following efuses are burned: VDD_SPI_FORCE, VDD_SPI_XPD, VDD_SPI_TIEH." - print(msg) - - sdio_force.save(1) # Disable GPIO45 - if args.voltage != "OFF": - sdio_reg.save(1) # Enable internal regulator - if args.voltage == "3.3V": - sdio_tieh.save(1) - print("VDD_SPI setting complete.") - if not efuses.burn_all(check_batch_mode=True): - return - print("Successful") - - -def adc_info(esp, efuses, args): - print("") - # fmt: off - if efuses["BLK_VERSION_MAJOR"].get() == 1: - print("Temperature Sensor Calibration = {}C".format(efuses["TEMP_CALIB"].get())) - print("ADC OCode = ", efuses["OCODE"].get()) - print("ADC1:") - print("INIT_CODE_ATTEN0 = ", efuses["ADC1_INIT_CODE_ATTEN0"].get()) - print("INIT_CODE_ATTEN1 = ", efuses["ADC1_INIT_CODE_ATTEN1"].get()) - print("INIT_CODE_ATTEN2 = ", efuses["ADC1_INIT_CODE_ATTEN2"].get()) - print("INIT_CODE_ATTEN3 = ", efuses["ADC1_INIT_CODE_ATTEN3"].get()) - print("CAL_VOL_ATTEN0 = ", efuses["ADC1_CAL_VOL_ATTEN0"].get()) - print("CAL_VOL_ATTEN1 = ", efuses["ADC1_CAL_VOL_ATTEN1"].get()) - print("CAL_VOL_ATTEN2 = ", efuses["ADC1_CAL_VOL_ATTEN2"].get()) - print("CAL_VOL_ATTEN3 = ", efuses["ADC1_CAL_VOL_ATTEN3"].get()) - print("ADC2:") - print("INIT_CODE_ATTEN0 = ", efuses["ADC2_INIT_CODE_ATTEN0"].get()) - print("INIT_CODE_ATTEN1 = ", efuses["ADC2_INIT_CODE_ATTEN1"].get()) - print("INIT_CODE_ATTEN2 = ", efuses["ADC2_INIT_CODE_ATTEN2"].get()) - print("INIT_CODE_ATTEN3 = ", efuses["ADC2_INIT_CODE_ATTEN3"].get()) - print("CAL_VOL_ATTEN0 = ", efuses["ADC2_CAL_VOL_ATTEN0"].get()) - print("CAL_VOL_ATTEN1 = ", efuses["ADC2_CAL_VOL_ATTEN1"].get()) - print("CAL_VOL_ATTEN2 = ", efuses["ADC2_CAL_VOL_ATTEN2"].get()) - else: - print("BLK_VERSION_MAJOR = ", efuses["BLK_VERSION_MAJOR"].get_meaning()) - # fmt: on - - -def key_block_is_unused(block, key_purpose_block): - if not block.is_readable() or not block.is_writeable(): - return False - - if key_purpose_block.get() != "USER" or not key_purpose_block.is_writeable(): - return False - - if not block.get_bitstring().all(False): - return False - - return True - - -def get_next_key_block(efuses, current_key_block, block_name_list): - key_blocks = [b for b in efuses.blocks if b.key_purpose_name] - start = key_blocks.index(current_key_block) - - # Sort key blocks so that we pick the next free block (and loop around if necessary) - key_blocks = key_blocks[start:] + key_blocks[0:start] - - # Exclude any other blocks that will be be burned - key_blocks = [b for b in key_blocks if b.name not in block_name_list] - - for block in key_blocks: - key_purpose_block = efuses[block.key_purpose_name] - if key_block_is_unused(block, key_purpose_block): - return block - - return None - - -def split_512_bit_key(efuses, block_name_list, datafile_list, keypurpose_list): - i = keypurpose_list.index("XTS_AES_256_KEY") - block_name = block_name_list[i] - - block_num = efuses.get_index_block_by_name(block_name) - block = efuses.blocks[block_num] - - data = datafile_list[i].read() - if len(data) != 64: - raise esptool.FatalError( - "Incorrect key file size %d, XTS_AES_256_KEY should be 64 bytes" % len(data) - ) - - key_block_2 = get_next_key_block(efuses, block, block_name_list) - if not key_block_2: - raise esptool.FatalError("XTS_AES_256_KEY requires two free keyblocks") - - keypurpose_list.append("XTS_AES_256_KEY_1") - datafile_list.append(io.BytesIO(data[:32])) - block_name_list.append(block_name) - - keypurpose_list.append("XTS_AES_256_KEY_2") - datafile_list.append(io.BytesIO(data[32:])) - block_name_list.append(key_block_2.name) - - keypurpose_list.pop(i) - datafile_list.pop(i) - block_name_list.pop(i) - - -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]) : - ] - - if "XTS_AES_256_KEY" in keypurpose_list: - # XTS_AES_256_KEY is not an actual HW key purpose, needs to be split into - # XTS_AES_256_KEY_1 and XTS_AES_256_KEY_2 - split_512_bit_key(efuses, block_name_list, datafile_list, keypurpose_list) - - 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: - 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" - 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/tools/esptool_py/espefuse/efuse/esp32s3beta2/__init__.py b/tools/esptool_py/espefuse/efuse/esp32s3beta2/__init__.py deleted file mode 100644 index a3b55a8023..0000000000 --- a/tools/esptool_py/espefuse/efuse/esp32s3beta2/__init__.py +++ /dev/null @@ -1,3 +0,0 @@ -from . import operations -from .emulate_efuse_controller import EmulateEfuseController -from .fields import EspEfuses diff --git a/tools/esptool_py/espefuse/efuse/esp32s3beta2/emulate_efuse_controller.py b/tools/esptool_py/espefuse/efuse/esp32s3beta2/emulate_efuse_controller.py deleted file mode 100644 index 949fc562b9..0000000000 --- a/tools/esptool_py/espefuse/efuse/esp32s3beta2/emulate_efuse_controller.py +++ /dev/null @@ -1,92 +0,0 @@ -# This file describes eFuses controller for ESP32-S3(beta2) chip -# -# SPDX-FileCopyrightText: 2020-2022 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-S3(beta2)" - mem = None - debug = False - - def __init__(self, efuse_file=None, debug=False): - self.Blocks = EfuseDefineBlocks - self.Fields = EfuseDefineFields(None) - 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 2 - - 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/tools/esptool_py/espefuse/efuse/esp32s3beta2/fields.py b/tools/esptool_py/espefuse/efuse/esp32s3beta2/fields.py deleted file mode 100644 index 28e03e9cfe..0000000000 --- a/tools/esptool_py/espefuse/efuse/esp32s3beta2/fields.py +++ /dev/null @@ -1,489 +0,0 @@ -# This file describes eFuses for ESP32-S3 chip -# -# SPDX-FileCopyrightText: 2020-2022 Espressif Systems (Shanghai) CO LTD -# -# SPDX-License-Identifier: GPL-2.0-or-later - -import binascii -import struct -import sys -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, - extend_efuse_table=None, - ): - self.Blocks = EfuseDefineBlocks() - self.Fields = EfuseDefineFields(extend_efuse_table) - 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-S3(beta2)": - raise esptool.FatalError( - "Expected the 'esp' param for ESP32-S3(beta2) 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: - if self["BLK_VERSION_MAJOR"].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") - sys.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") - sys.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 - ) - - 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: - 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): - if self["VDD_SPI_FORCE"].get() == 0: - output = "Flash voltage (VDD_SPI) determined by GPIO45 on reset " - 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 " - 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: - output = "Flash voltage (VDD_SPI) set to 1.8V by efuse." - else: - output = "Flash voltage (VDD_SPI) set to 3.3V by efuse." - return output - - def is_efuses_incompatible_for_burn(self): - # getting chip version: self._esp.get_chip_revision() - if ( - ( - self["DIS_USB_JTAG"].get(from_read=True) - and self["DIS_USB_SERIAL_JTAG"].get(from_read=False) - ) - or ( - self["DIS_USB_JTAG"].get(from_read=False) - and self["DIS_USB_SERIAL_JTAG"].get(from_read=True) - ) - or ( - self["DIS_USB_JTAG"].get(from_read=False) - and self["DIS_USB_SERIAL_JTAG"].get(from_read=False) - ) - ): - print( - "DIS_USB_JTAG and DIS_USB_SERIAL_JTAG cannot be set together due to a bug in the ROM bootloader" - ) - return True - return False - - -class EfuseField(base_fields.EfuseFieldBase): - @staticmethod - def convert(parent, efuse): - return { - "mac": EfuseMacField, - "keypurpose": EfuseKeyPurposeField, - "t_sensor": EfuseTempSensor, - "adc_tp": EfuseAdcPointCalibration, - "wafer": EfuseWafer, - }.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): - raise esptool.FatalError("Burning %s is not supported" % self.name) - - -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!" - ) - if new_value_str.count(":") != 5: - raise esptool.FatalError( - "MAC Address needs to be a 6-byte hexadecimal format " - "separated by colons (:)!" - ) - hexad = new_value_str.replace(":", "") - if len(hexad) != 12: - raise esptool.FatalError( - "MAC Address needs to be a 6-byte hexadecimal number " - "(12 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!") - 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] - 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("Writing Factory MAC address 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 - ("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) - ("XTS_AES_256_KEY", -1, "VIRTUAL", None, "no_need_rd_protect"), # Virtual purpose splits to XTS_AES_256_KEY_1 and XTS_AES_256_KEY_2 - ] -# 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))) - 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/tools/esptool_py/espefuse/efuse/esp32s3beta2/mem_definition.py b/tools/esptool_py/espefuse/efuse/esp32s3beta2/mem_definition.py deleted file mode 100644 index 0fb1ec8bad..0000000000 --- a/tools/esptool_py/espefuse/efuse/esp32s3beta2/mem_definition.py +++ /dev/null @@ -1,171 +0,0 @@ -# This file describes eFuses fields and registers for ESP32-S3(beta2) chip -# -# SPDX-FileCopyrightText: 2020-2022 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_ADDR_MASK = 0x00000FFF - 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 - 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 + 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 - - 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, extend_efuse_table) -> 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, extend_efuse_table) - - 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/tools/esptool_py/espefuse/efuse/esp32s3beta2/operations.py b/tools/esptool_py/espefuse/efuse/esp32s3beta2/operations.py deleted file mode 100644 index 229a929023..0000000000 --- a/tools/esptool_py/espefuse/efuse/esp32s3beta2/operations.py +++ /dev/null @@ -1,521 +0,0 @@ -# This file includes the operations with eFuses for ESP32-S3(beta2) chip -# -# SPDX-FileCopyrightText: 2020-2022 Espressif Systems (Shanghai) CO LTD -# -# SPDX-License-Identifier: GPL-2.0-or-later - -import argparse -import io -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", - 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", - 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): - efuses["CUSTOM_MAC"].save(args.mac) - if not efuses.burn_all(check_batch_mode=True): - return - get_custom_mac(esp, efuses, args) - print("Successful") - - -def get_custom_mac(esp, efuses, args): - print("Custom MAC Address: {}".format(efuses["CUSTOM_MAC"].get())) - - -def set_flash_voltage(esp, efuses, args): - sdio_force = efuses["VDD_SPI_FORCE"] - sdio_tieh = efuses["VDD_SPI_TIEH"] - sdio_reg = efuses["VDD_SPI_XPD"] - - # check efuses aren't burned in a way which makes this impossible - if args.voltage == "OFF" and sdio_reg.get() != 0: - raise esptool.FatalError( - "Can't set flash regulator to OFF as VDD_SPI_XPD efuse is already burned" - ) - - if args.voltage == "1.8V" and sdio_tieh.get() != 0: - raise esptool.FatalError( - "Can't set regulator to 1.8V is VDD_SPI_TIEH efuse is already burned" - ) - - if args.voltage == "OFF": - msg = "Disable internal flash voltage regulator (VDD_SPI). " - "SPI flash will need to be powered from an external source.\n" - "The following efuse is burned: VDD_SPI_FORCE.\n" - "It is possible to later re-enable the internal regulator (%s) " % ( - "to 3.3V" if sdio_tieh.get() != 0 else "to 1.8V or 3.3V" - ) - "by burning an additional efuse" - elif args.voltage == "1.8V": - msg = "Set internal flash voltage regulator (VDD_SPI) to 1.8V.\n" - "The following efuses are burned: VDD_SPI_FORCE, VDD_SPI_XPD.\n" - "It is possible to later increase the voltage to 3.3V (permanently) " - "by burning additional efuse VDD_SPI_TIEH" - elif args.voltage == "3.3V": - msg = "Enable internal flash voltage regulator (VDD_SPI) to 3.3V.\n" - "The following efuses are burned: VDD_SPI_FORCE, VDD_SPI_XPD, VDD_SPI_TIEH." - print(msg) - - sdio_force.save(1) # Disable GPIO45 - if args.voltage != "OFF": - sdio_reg.save(1) # Enable internal regulator - if args.voltage == "3.3V": - sdio_tieh.save(1) - print("VDD_SPI setting complete.") - if not efuses.burn_all(check_batch_mode=True): - return - print("Successful") - - -def adc_info(esp, efuses, args): - print("") - # fmt: off - if efuses["BLK_VERSION_MAJOR"].get() == 1: - print("Temperature Sensor Calibration = {}C".format(efuses["TEMP_CALIB"].get())) - print("ADC OCode = ", efuses["OCODE"].get()) - print("ADC1:") - print("INIT_CODE_ATTEN0 = ", efuses["ADC1_INIT_CODE_ATTEN0"].get()) - print("INIT_CODE_ATTEN1 = ", efuses["ADC1_INIT_CODE_ATTEN1"].get()) - print("INIT_CODE_ATTEN2 = ", efuses["ADC1_INIT_CODE_ATTEN2"].get()) - print("INIT_CODE_ATTEN3 = ", efuses["ADC1_INIT_CODE_ATTEN3"].get()) - print("CAL_VOL_ATTEN0 = ", efuses["ADC1_CAL_VOL_ATTEN0"].get()) - print("CAL_VOL_ATTEN1 = ", efuses["ADC1_CAL_VOL_ATTEN1"].get()) - print("CAL_VOL_ATTEN2 = ", efuses["ADC1_CAL_VOL_ATTEN2"].get()) - print("CAL_VOL_ATTEN3 = ", efuses["ADC1_CAL_VOL_ATTEN3"].get()) - print("ADC2:") - print("INIT_CODE_ATTEN0 = ", efuses["ADC2_INIT_CODE_ATTEN0"].get()) - print("INIT_CODE_ATTEN1 = ", efuses["ADC2_INIT_CODE_ATTEN1"].get()) - print("INIT_CODE_ATTEN2 = ", efuses["ADC2_INIT_CODE_ATTEN2"].get()) - print("INIT_CODE_ATTEN3 = ", efuses["ADC2_INIT_CODE_ATTEN3"].get()) - print("CAL_VOL_ATTEN0 = ", efuses["ADC2_CAL_VOL_ATTEN0"].get()) - print("CAL_VOL_ATTEN1 = ", efuses["ADC2_CAL_VOL_ATTEN1"].get()) - print("CAL_VOL_ATTEN2 = ", efuses["ADC2_CAL_VOL_ATTEN2"].get()) - else: - print("BLK_VERSION_MAJOR = ", efuses["BLK_VERSION_MAJOR"].get_meaning()) - # fmt: on - - -def key_block_is_unused(block, key_purpose_block): - if not block.is_readable() or not block.is_writeable(): - return False - - if key_purpose_block.get() != "USER" or not key_purpose_block.is_writeable(): - return False - - if not block.get_bitstring().all(False): - return False - - return True - - -def get_next_key_block(efuses, current_key_block, block_name_list): - key_blocks = [b for b in efuses.blocks if b.key_purpose_name] - start = key_blocks.index(current_key_block) - - # Sort key blocks so that we pick the next free block (and loop around if necessary) - key_blocks = key_blocks[start:] + key_blocks[0:start] - - # Exclude any other blocks that will be be burned - key_blocks = [b for b in key_blocks if b.name not in block_name_list] - - for block in key_blocks: - key_purpose_block = efuses[block.key_purpose_name] - if key_block_is_unused(block, key_purpose_block): - return block - - return None - - -def split_512_bit_key(efuses, block_name_list, datafile_list, keypurpose_list): - i = keypurpose_list.index("XTS_AES_256_KEY") - block_name = block_name_list[i] - - block_num = efuses.get_index_block_by_name(block_name) - block = efuses.blocks[block_num] - - data = datafile_list[i].read() - if len(data) != 64: - raise esptool.FatalError( - "Incorrect key file size %d, XTS_AES_256_KEY should be 64 bytes" % len(data) - ) - - key_block_2 = get_next_key_block(efuses, block, block_name_list) - if not key_block_2: - raise esptool.FatalError("XTS_AES_256_KEY requires two free keyblocks") - - keypurpose_list.append("XTS_AES_256_KEY_1") - datafile_list.append(io.BytesIO(data[:32])) - block_name_list.append(block_name) - - keypurpose_list.append("XTS_AES_256_KEY_2") - datafile_list.append(io.BytesIO(data[32:])) - block_name_list.append(key_block_2.name) - - keypurpose_list.pop(i) - datafile_list.pop(i) - block_name_list.pop(i) - - -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]) : - ] - - if "XTS_AES_256_KEY" in keypurpose_list: - # XTS_AES_256_KEY is not an actual HW key purpose, needs to be split into - # XTS_AES_256_KEY_1 and XTS_AES_256_KEY_2 - split_512_bit_key(efuses, block_name_list, datafile_list, keypurpose_list) - - 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: - 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" - 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/tools/esptool_py/espefuse/efuse/mem_definition_base.py b/tools/esptool_py/espefuse/efuse/mem_definition_base.py deleted file mode 100644 index f6e2bdc0b2..0000000000 --- a/tools/esptool_py/espefuse/efuse/mem_definition_base.py +++ /dev/null @@ -1,232 +0,0 @@ -# This file describes eFuses fields and registers for ESP32 chip -# -# SPDX-FileCopyrightText: 2020-2022 Espressif Systems (Shanghai) CO LTD -# -# SPDX-License-Identifier: GPL-2.0-or-later - -from collections import Counter, namedtuple -import esptool -from typing import Optional, List - -from .csv_table_parser import CSVFuseTable - - -class EfuseRegistersBase(object): - # Coding Scheme values - CODING_SCHEME_NONE = 0 - CODING_SCHEME_34 = 1 - CODING_SCHEME_REPEAT = 2 - CODING_SCHEME_NONE_RECOVERY = 3 - CODING_SCHEME_RS = 4 - - EFUSE_BURN_TIMEOUT = 0.250 # seconds - - -class EfuseBlocksBase(object): - BLOCKS: Optional[List] = None - NamedtupleBlock = namedtuple( - "NamedtupleBlock", - "name alias id rd_addr wr_addr write_disable_bit " - "read_disable_bit len key_purpose", - ) - - @staticmethod - def get(tuple_block): - return EfuseBlocksBase.NamedtupleBlock._make(tuple_block) - - def get_blocks_for_keys(self): - list_of_names = [] - for block in self.BLOCKS: - blk = self.get(block) - if blk.id > 0: - 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 Field: - name = "" - block = 0 - word = None - pos = None - bit_len = 0 - alt_names: List[str] = [] - type = "" - write_disable_bit = None - read_disable_bit = None - category = "config" - class_type = "" - description = "" - dictionary = None - - -class EfuseFieldsBase(object): - def __init__(self, e_desc, extend_efuse_table_file) -> None: - self.ALL_EFUSES: List = [] - - 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) - - if self.extend_efuses(extend_efuse_table_file): - self.check_name_duplicates() - - def check_name_duplicates(self): - names = [n.name for n in self.ALL_EFUSES] - for n in self.ALL_EFUSES: - if n.alt_names: - names.extend(n.alt_names) - - name_counts = Counter(names) - duplicates = {name for name, count in name_counts.items() if count > 1} - if duplicates: - print("Names that are not unique: " + ", ".join(duplicates)) - raise esptool.FatalError("Duplicate names found in eFuses") - - def extend_efuses(self, extend_efuse_table_file): - if extend_efuse_table_file: - table = CSVFuseTable.from_csv(extend_efuse_table_file.read()) - for p in table: - item = Field() - item.name = p.field_name - item.block = p.efuse_block - item.word = p.bit_start // 32 - item.pos = p.bit_start % 32 - item.bit_len = p.bit_count - if p.bit_count == 1: - str_type = "bool" - else: - if p.bit_count > 32 and p.bit_count % 8 == 0: - str_type = f"bytes:{p.bit_count // 8}" - else: - str_type = f"uint:{p.bit_count}" - item.type = str_type - item.write_disable_bit = None - item.read_disable_bit = None - if item.block != 0: - # look for an already configured field associated with this field - # to take the WR_DIS and RID_DIS bits - for field in self.ALL_EFUSES: - if field.block == item.block: - if field.write_disable_bit is not None: - item.write_disable_bit = field.write_disable_bit - if field.read_disable_bit is not None: - item.read_disable_bit = field.read_disable_bit - if ( - item.read_disable_bit is not None - and item.write_disable_bit is not None - ): - break - item.category = "User" - item.description = p.comment - item.alt_names = p.alt_names.split(" ") if p.alt_names else [] - item.dictionary = "" - self.ALL_EFUSES.append(item) - return True - return False diff --git a/tools/esptool_py/espefuse/efuse/util.py b/tools/esptool_py/espefuse/efuse/util.py deleted file mode 100644 index 004e03b295..0000000000 --- a/tools/esptool_py/espefuse/efuse/util.py +++ /dev/null @@ -1,47 +0,0 @@ -# This file consists of the common useful functions for eFuse -# -# SPDX-FileCopyrightText: 2020-2022 Espressif Systems (Shanghai) CO LTD -# -# SPDX-License-Identifier: GPL-2.0-or-later - -import esptool - - -def hexify(bitstring, separator=""): - as_bytes = tuple(b for b in bitstring) - return separator.join(("%02x" % b) for b in as_bytes) - - -def popcnt(b): - """Return number of "1" bits set in 'b'""" - return len([x for x in bin(b) if x == "1"]) - - -def check_duplicate_name_in_list(name_list): - duples_name = [name for i, name in enumerate(name_list) if name in name_list[:i]] - if duples_name != []: - raise esptool.FatalError( - "Found repeated {} in the name list".format(duples_name) - ) - - -class SdkConfig(object): - def __init__(self, path_to_file): - self.sdkconfig = dict() - if path_to_file is None: - return - with open(path_to_file, "r") as file: - for line in file.readlines(): - if line.startswith("#"): - continue - config = line.strip().split("=", 1) - if len(config) == 2: - self.sdkconfig[config[0]] = ( - True if config[1] == "y" else config[1].strip('"') - ) - - def __getitem__(self, config_name): - try: - return self.sdkconfig[config_name] - except KeyError: - return False diff --git a/tools/esptool_py/espefuse/efuse_defs/esp32.yaml b/tools/esptool_py/espefuse/efuse_defs/esp32.yaml deleted file mode 100644 index cfae99038f..0000000000 --- a/tools/esptool_py/espefuse/efuse_defs/esp32.yaml +++ /dev/null @@ -1,64 +0,0 @@ -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/tools/esptool_py/espefuse/efuse_defs/esp32c2.yaml b/tools/esptool_py/espefuse/efuse_defs/esp32c2.yaml deleted file mode 100644 index e89e354fce..0000000000 --- a/tools/esptool_py/espefuse/efuse_defs/esp32c2.yaml +++ /dev/null @@ -1,53 +0,0 @@ -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/tools/esptool_py/espefuse/efuse_defs/esp32c3.yaml b/tools/esptool_py/espefuse/efuse_defs/esp32c3.yaml deleted file mode 100644 index 035f30c5b5..0000000000 --- a/tools/esptool_py/espefuse/efuse_defs/esp32c3.yaml +++ /dev/null @@ -1,112 +0,0 @@ -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/tools/esptool_py/espefuse/efuse_defs/esp32c5.yaml b/tools/esptool_py/espefuse/efuse_defs/esp32c5.yaml deleted file mode 100644 index 31af46a56d..0000000000 --- a/tools/esptool_py/espefuse/efuse_defs/esp32c5.yaml +++ /dev/null @@ -1,104 +0,0 @@ -VER_NO: b09fa417de505238a601eddce188b696 -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_DIS0_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]'} - RESERVE_0_39 : {show: n, blk : 0, word: 1, pos : 7, len : 1, start : 39, 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_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]'} - RESERVE_0_42 : {show: n, blk : 0, word: 1, pos: 10, len : 1, start : 42, 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_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 : '', 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 threshold 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 threshold 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]'} - RESERVE_0_59 : {show: n, blk : 0, word: 1, pos: 27, len : 5, start : 59, type : 'uint:5', wr_dis: null, rd_dis: null, alt : '', dict : '', desc: Reserved; it was created by set_missed_fields_in_regs func, rloc: 'EFUSE_RD_REPEAT_DATA0_REG[31:27]', bloc: 'B7[7:3]'} - KM_DISABLE_DEPLOY_MODE : {show: y, blk : 0, word: 2, pos : 0, len : 4, start : 64, type : 'uint:4', wr_dis : 1, rd_dis: null, alt : '', dict : '', desc: 'Represents whether the deploy mode of key manager is disable or not. \\ 1: disabled \\ 0: enabled.\\', rloc: 'EFUSE_RD_REPEAT_DATA1_REG[3:0]', bloc: 'B8[3:0]'} - KM_RND_SWITCH_CYCLE : {show: y, blk : 0, word: 2, pos : 4, len : 2, start : 68, type : 'uint:2', wr_dis : 1, rd_dis: null, alt : '', dict : '', desc: 'Set the 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[5:4]', bloc: 'B8[5:4]'} - KM_DEPLOY_ONLY_ONCE : {show: y, blk : 0, word: 2, pos : 6, len : 4, start : 70, type : 'uint:4', wr_dis : 1, 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. bit 0: ecsda; bit 1: xts; bit2: hmac; bit3: ds', rloc: 'EFUSE_RD_REPEAT_DATA1_REG[9:6]', bloc: 'B8[7:6],B9[1:0]'} - FORCE_USE_KEY_MANAGER_KEY : {show: y, blk : 0, word: 2, pos: 10, len : 4, start : 74, type : 'uint:4', wr_dis : 1, 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. bit 0: ecsda; bit 1: xts; bit2: hmac; bit3: ds', rloc: 'EFUSE_RD_REPEAT_DATA1_REG[13:10]', bloc: 'B9[5:2]'} - FORCE_DISABLE_SW_INIT_KEY : {show: y, blk : 0, word: 2, pos: 14, len : 1, start : 78, type : bool, wr_dis : 1, 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[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 : 3, rd_dis: null, alt : '', dict : '', desc: 'Represents the threshold level of the RTC watchdog STG0 timeout.\\ 0: Original threshold configuration value of STG0 *2 \\1: Original threshold configuration value of STG0 *4 \\2: Original threshold configuration value of STG0 *8 \\3: Original threshold configuration value of STG0 *16 \\', 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]'} - RESERVE_0_114 : {show: n, blk : 0, word: 3, pos: 18, len : 2, start: 114, 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_DATA2_REG[19:18]', bloc: 'B14[3:2]'} - 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]'} - RESERVE_0_118 : {show: n, blk : 0, word: 3, pos: 22, len : 5, start: 118, type : 'uint:5', 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[26:22]', bloc: 'B14[7:6],B15[2:0]'} - KM_XTS_KEY_LENGTH_256 : {show: y, blk : 0, word: 3, pos: 27, len : 1, start: 123, type : bool, wr_dis : 1, rd_dis: null, alt : '', dict : '', desc: Set this bitto configure flash encryption use xts-128 key. else use xts-256 key, 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 : 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 : '', 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 : 1, rd_dis: null, alt : '', dict : '', desc: 'Represetns whether to lock the efuse xts key.\\ 1. Lock\\ 0: Unlock\\', 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: Disable\\ 0: Enable\\', 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_PAD : {show: y, blk : 0, word: 4, pos: 26, len : 1, start: 154, type : bool, wr_dis : 2, 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]'} - XTS_DPA_PSEUDO_LEVEL : {show: y, blk : 0, word: 4, pos: 27, len : 2, start: 155, type : 'uint:2', wr_dis : 14, rd_dis: null, alt : '', dict : '', desc: 'Represents the pseudo round level of xts-aes anti-dpa attack.\\ 3: High.\\ 2: Moderate 1. Low\\ 0: Disabled\\', rloc: 'EFUSE_RD_REPEAT_DATA3_REG[28:27]', bloc: 'B19[4:3]'} - XTS_DPA_CLK_ENABLE : {show: y, blk : 0, word: 4, pos: 29, len : 1, start: 157, type : bool, wr_dis : 14, rd_dis: null, alt : '', dict : '', desc: 'Represents whether xts-aes anti-dpa attack clock is enabled.\\ 1. Enable.\\ 0: Disable.\\', rloc: 'EFUSE_RD_REPEAT_DATA3_REG[29]', bloc: 'B19[5]'} - RESERVE_0_158 : {show: n, blk : 0, word: 4, pos: 30, len : 2, start: 158, 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_DATA3_REG[31:30]', bloc: 'B19[7:6]'} - HUK_GEN_STATE : {show: y, blk : 0, word: 5, pos : 0, len : 9, start: 160, type : 'uint:9', wr_dis : 19, rd_dis: null, alt : '', dict : '', desc: Set the bits to control validation of HUK generate mode.\\ Odd of 1 is invalid.\\ Even of 1 is valid.\\, rloc: 'EFUSE_RD_REPEAT_DATA4_REG[8:0]', bloc: 'B20,B21[0]'} - XTAL_48M_SEL : {show: y, blk : 0, word: 5, pos : 9, len : 3, start: 169, type : 'uint:3', wr_dis : 17, rd_dis: null, alt : '', dict : '', desc: 'Represents whether XTAL frequency is 48MHz or not. If not; 40MHz XTAL will be used. If this field contains Odd number bit 1: Enable 48MHz XTAL\ Even number bit 1: Enable 40MHz XTAL', rloc: 'EFUSE_RD_REPEAT_DATA4_REG[11:9]', bloc: 'B21[3:1]'} - XTAL_48M_SEL_MODE : {show: y, blk : 0, word: 5, pos: 12, len : 1, start: 172, type : bool, wr_dis : 17, rd_dis: null, alt : '', dict : '', desc: 'Specify the XTAL frequency selection is decided by eFuse or strapping-PAD-state. 1: eFuse\\ 0: strapping-PAD-state', rloc: 'EFUSE_RD_REPEAT_DATA4_REG[12]', bloc: 'B21[4]'} - ECDSA_DISABLE_P192 : {show: y, blk : 0, word: 5, pos: 13, len : 1, start: 173, type : bool, wr_dis : 14, rd_dis: null, alt : '', dict : '', desc: 'Represents whether to disable P192 curve in ECDSA.\\ 1: Disabled.\\ 0: Not disable', rloc: 'EFUSE_RD_REPEAT_DATA4_REG[13]', bloc: 'B21[5]'} - ECC_FORCE_CONST_TIME : {show: y, blk : 0, word: 5, pos: 14, len : 1, start: 174, type : bool, wr_dis : 14, rd_dis: null, alt : '', dict : '', desc: 'Represents whether to force ecc to use const-time calculation mode. \\ 1: Enable. \\ 0: Disable', rloc: 'EFUSE_RD_REPEAT_DATA4_REG[14]', bloc: 'B21[6]'} - RESERVE_0_175 : {show: n, blk : 0, word: 5, pos: 15, len : 17, start: 175, type : 'uint:17', 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:15]', bloc: 'B21[7],B22,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_SYS0_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: Represents the extended bits of MAC address, rloc: 'EFUSE_RD_MAC_SYS1_REG[31:16]', bloc: 'B6,B7'} - WAFER_VERSION_MINOR : {show: y, blk : 1, word: 2, pos : 0, len : 4, start : 64, type : 'uint:4', wr_dis : 20, rd_dis: null, alt : '', dict : '', desc: Minor chip version, rloc: 'EFUSE_RD_MAC_SYS2_REG[3:0]', bloc: 'B8[3:0]'} - WAFER_VERSION_MAJOR : {show: y, blk : 1, word: 2, pos : 4, len : 2, start : 68, type : 'uint:2', wr_dis : 20, rd_dis: null, alt : '', dict : '', desc: Minor chip version, rloc: 'EFUSE_RD_MAC_SYS2_REG[5:4]', bloc: 'B8[5:4]'} - DISABLE_WAFER_VERSION_MAJOR : {show: y, blk : 1, word: 2, pos : 6, len : 1, start : 70, type : bool, wr_dis : 20, rd_dis: null, alt : '', dict : '', desc: Disables check of wafer version major, rloc: 'EFUSE_RD_MAC_SYS2_REG[6]', bloc: 'B8[6]'} - DISABLE_BLK_VERSION_MAJOR : {show: y, blk : 1, word: 2, pos : 7, len : 1, start : 71, type : bool, wr_dis : 20, rd_dis: null, alt : '', dict : '', desc: Disables check of blk version major, rloc: 'EFUSE_RD_MAC_SYS2_REG[7]', bloc: 'B8[7]'} - BLK_VERSION_MINOR : {show: y, blk : 1, word: 2, pos : 8, len : 3, start : 72, type : 'uint:3', wr_dis : 20, rd_dis: null, alt : '', dict : '', desc: BLK_VERSION_MINOR of BLOCK2, rloc: 'EFUSE_RD_MAC_SYS2_REG[10:8]', bloc: 'B9[2:0]'} - BLK_VERSION_MAJOR : {show: y, blk : 1, word: 2, pos: 11, len : 2, start : 75, type : 'uint:2', wr_dis : 20, rd_dis: null, alt : '', dict : '', desc: BLK_VERSION_MAJOR of BLOCK2, rloc: 'EFUSE_RD_MAC_SYS2_REG[12:11]', bloc: 'B9[4:3]'} - FLASH_CAP : {show: y, blk : 1, word: 2, pos: 13, len : 3, start : 77, type : 'uint:3', wr_dis : 20, rd_dis: null, alt : '', dict : '', desc: Flash capacity, rloc: 'EFUSE_RD_MAC_SYS2_REG[15:13]', bloc: 'B9[7:5]'} - FLASH_VENDOR : {show: y, blk : 1, word: 2, pos: 16, len : 3, start : 80, type : 'uint:3', wr_dis : 20, rd_dis: null, alt : '', dict : '', desc: Flash vendor, rloc: 'EFUSE_RD_MAC_SYS2_REG[18:16]', bloc: 'B10[2:0]'} - PSRAM_CAP : {show: y, blk : 1, word: 2, pos: 19, len : 3, start : 83, type : 'uint:3', wr_dis : 20, rd_dis: null, alt : '', dict : '', desc: Psram capacity, rloc: 'EFUSE_RD_MAC_SYS2_REG[21:19]', bloc: 'B10[5:3]'} - PSRAM_VENDOR : {show: y, blk : 1, word: 2, pos: 22, len : 2, start : 86, type : 'uint:2', wr_dis : 20, rd_dis: null, alt : '', dict : '', desc: Psram vendor, rloc: 'EFUSE_RD_MAC_SYS2_REG[23:22]', bloc: 'B10[7:6]'} - TEMP : {show: y, blk : 1, word: 2, pos: 24, len : 2, start : 88, type : 'uint:2', wr_dis : 20, rd_dis: null, alt : '', dict : '', desc: Temp (die embedded inside), rloc: 'EFUSE_RD_MAC_SYS2_REG[25:24]', bloc: 'B11[1:0]'} - PKG_VERSION : {show: y, blk : 1, word: 2, pos: 26, len : 3, start : 90, type : 'uint:3', wr_dis : 20, rd_dis: null, alt : '', dict : '', desc: Package version, rloc: 'EFUSE_RD_MAC_SYS2_REG[28:26]', bloc: 'B11[4:2]'} - PA_TRIM_VERSION : {show: y, blk : 1, word: 2, pos: 29, len : 3, start : 93, type : 'uint:3', wr_dis : 20, rd_dis: null, alt : '', dict : '', desc: PADC CAL PA trim version, rloc: 'EFUSE_RD_MAC_SYS2_REG[31:29]', bloc: 'B11[7:5]'} - TRIM_N_BIAS : {show: y, blk : 1, word: 3, pos : 0, len : 5, start : 96, type : 'uint:5', wr_dis : 20, rd_dis: null, alt : '', dict : '', desc: PADC CAL N bias, rloc: 'EFUSE_RD_MAC_SYS3_REG[4:0]', bloc: 'B12[4:0]'} - TRIM_P_BIAS : {show: y, blk : 1, word: 3, pos : 5, len : 5, start: 101, type : 'uint:5', wr_dis : 20, rd_dis: null, alt : '', dict : '', desc: PADC CAL P bias, rloc: 'EFUSE_RD_MAC_SYS3_REG[9:5]', bloc: 'B12[7:5],B13[1:0]'} - RESERVED_1_106 : {show: n, blk : 1, word: 3, pos: 10, len : 8, start: 106, type : 'uint:8', wr_dis : 20, rd_dis: null, alt : '', dict : '', desc: reserved, rloc: 'EFUSE_RD_MAC_SYS3_REG[17:10]', bloc: 'B13[7:2],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: Represents the first 14-bit of zeroth part of system data, rloc: 'EFUSE_RD_MAC_SYS3_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: Represents the first 14-bit of zeroth part of system data, rloc: EFUSE_RD_MAC_SYS4_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: Represents the second 32-bit of zeroth part of system data, rloc: EFUSE_RD_MAC_SYS5_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 : 9, start: 128, type : 'uint:9', wr_dis : 21, rd_dis: null, alt : '', dict : '', desc: reserved, 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]'} - RESERVED_2_145 : {show: n, blk : 2, word: 4, pos: 17, len : 15, start: 145, type : 'uint:15', wr_dis : 21, rd_dis: null, alt : '', dict : '', desc: reserved, rloc: 'EFUSE_RD_SYS_PART1_DATA4_REG[31:17]', bloc: 'B18[7:1],B19'} - SYS_DATA_PART1_5 : {show: n, blk : 2, word: 5, pos : 0, len : 32, start: 160, type : 'uint:32', wr_dis : 21, rd_dis: null, alt : '', dict : '', desc: Represents the zeroth 32-bit of first part of system data, rloc: EFUSE_RD_SYS_PART1_DATA5_REG, bloc: 'B20,B21,B22,B23'} - SYS_DATA_PART1_6 : {show: n, blk : 2, word: 6, pos : 0, len : 32, start: 192, type : 'uint:32', wr_dis : 21, rd_dis: null, alt : '', dict : '', desc: Represents the zeroth 32-bit of first part of system data, rloc: EFUSE_RD_SYS_PART1_DATA6_REG, bloc: 'B24,B25,B26,B27'} - SYS_DATA_PART1_7 : {show: n, blk : 2, word: 7, pos : 0, len : 32, start: 224, type : 'uint:32', wr_dis : 21, rd_dis: null, alt : '', dict : '', desc: Represents the zeroth 32-bit of first part of system data, rloc: EFUSE_RD_SYS_PART1_DATA7_REG, bloc: 'B28,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, 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/tools/esptool_py/espefuse/efuse_defs/esp32c5beta3.yaml b/tools/esptool_py/espefuse/efuse_defs/esp32c5beta3.yaml deleted file mode 100644 index 31af46a56d..0000000000 --- a/tools/esptool_py/espefuse/efuse_defs/esp32c5beta3.yaml +++ /dev/null @@ -1,104 +0,0 @@ -VER_NO: b09fa417de505238a601eddce188b696 -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_DIS0_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]'} - RESERVE_0_39 : {show: n, blk : 0, word: 1, pos : 7, len : 1, start : 39, 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_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]'} - RESERVE_0_42 : {show: n, blk : 0, word: 1, pos: 10, len : 1, start : 42, 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_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 : '', 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 threshold 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 threshold 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]'} - RESERVE_0_59 : {show: n, blk : 0, word: 1, pos: 27, len : 5, start : 59, type : 'uint:5', wr_dis: null, rd_dis: null, alt : '', dict : '', desc: Reserved; it was created by set_missed_fields_in_regs func, rloc: 'EFUSE_RD_REPEAT_DATA0_REG[31:27]', bloc: 'B7[7:3]'} - KM_DISABLE_DEPLOY_MODE : {show: y, blk : 0, word: 2, pos : 0, len : 4, start : 64, type : 'uint:4', wr_dis : 1, rd_dis: null, alt : '', dict : '', desc: 'Represents whether the deploy mode of key manager is disable or not. \\ 1: disabled \\ 0: enabled.\\', rloc: 'EFUSE_RD_REPEAT_DATA1_REG[3:0]', bloc: 'B8[3:0]'} - KM_RND_SWITCH_CYCLE : {show: y, blk : 0, word: 2, pos : 4, len : 2, start : 68, type : 'uint:2', wr_dis : 1, rd_dis: null, alt : '', dict : '', desc: 'Set the 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[5:4]', bloc: 'B8[5:4]'} - KM_DEPLOY_ONLY_ONCE : {show: y, blk : 0, word: 2, pos : 6, len : 4, start : 70, type : 'uint:4', wr_dis : 1, 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. bit 0: ecsda; bit 1: xts; bit2: hmac; bit3: ds', rloc: 'EFUSE_RD_REPEAT_DATA1_REG[9:6]', bloc: 'B8[7:6],B9[1:0]'} - FORCE_USE_KEY_MANAGER_KEY : {show: y, blk : 0, word: 2, pos: 10, len : 4, start : 74, type : 'uint:4', wr_dis : 1, 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. bit 0: ecsda; bit 1: xts; bit2: hmac; bit3: ds', rloc: 'EFUSE_RD_REPEAT_DATA1_REG[13:10]', bloc: 'B9[5:2]'} - FORCE_DISABLE_SW_INIT_KEY : {show: y, blk : 0, word: 2, pos: 14, len : 1, start : 78, type : bool, wr_dis : 1, 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[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 : 3, rd_dis: null, alt : '', dict : '', desc: 'Represents the threshold level of the RTC watchdog STG0 timeout.\\ 0: Original threshold configuration value of STG0 *2 \\1: Original threshold configuration value of STG0 *4 \\2: Original threshold configuration value of STG0 *8 \\3: Original threshold configuration value of STG0 *16 \\', 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]'} - RESERVE_0_114 : {show: n, blk : 0, word: 3, pos: 18, len : 2, start: 114, 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_DATA2_REG[19:18]', bloc: 'B14[3:2]'} - 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]'} - RESERVE_0_118 : {show: n, blk : 0, word: 3, pos: 22, len : 5, start: 118, type : 'uint:5', 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[26:22]', bloc: 'B14[7:6],B15[2:0]'} - KM_XTS_KEY_LENGTH_256 : {show: y, blk : 0, word: 3, pos: 27, len : 1, start: 123, type : bool, wr_dis : 1, rd_dis: null, alt : '', dict : '', desc: Set this bitto configure flash encryption use xts-128 key. else use xts-256 key, 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 : 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 : '', 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 : 1, rd_dis: null, alt : '', dict : '', desc: 'Represetns whether to lock the efuse xts key.\\ 1. Lock\\ 0: Unlock\\', 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: Disable\\ 0: Enable\\', 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_PAD : {show: y, blk : 0, word: 4, pos: 26, len : 1, start: 154, type : bool, wr_dis : 2, 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]'} - XTS_DPA_PSEUDO_LEVEL : {show: y, blk : 0, word: 4, pos: 27, len : 2, start: 155, type : 'uint:2', wr_dis : 14, rd_dis: null, alt : '', dict : '', desc: 'Represents the pseudo round level of xts-aes anti-dpa attack.\\ 3: High.\\ 2: Moderate 1. Low\\ 0: Disabled\\', rloc: 'EFUSE_RD_REPEAT_DATA3_REG[28:27]', bloc: 'B19[4:3]'} - XTS_DPA_CLK_ENABLE : {show: y, blk : 0, word: 4, pos: 29, len : 1, start: 157, type : bool, wr_dis : 14, rd_dis: null, alt : '', dict : '', desc: 'Represents whether xts-aes anti-dpa attack clock is enabled.\\ 1. Enable.\\ 0: Disable.\\', rloc: 'EFUSE_RD_REPEAT_DATA3_REG[29]', bloc: 'B19[5]'} - RESERVE_0_158 : {show: n, blk : 0, word: 4, pos: 30, len : 2, start: 158, 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_DATA3_REG[31:30]', bloc: 'B19[7:6]'} - HUK_GEN_STATE : {show: y, blk : 0, word: 5, pos : 0, len : 9, start: 160, type : 'uint:9', wr_dis : 19, rd_dis: null, alt : '', dict : '', desc: Set the bits to control validation of HUK generate mode.\\ Odd of 1 is invalid.\\ Even of 1 is valid.\\, rloc: 'EFUSE_RD_REPEAT_DATA4_REG[8:0]', bloc: 'B20,B21[0]'} - XTAL_48M_SEL : {show: y, blk : 0, word: 5, pos : 9, len : 3, start: 169, type : 'uint:3', wr_dis : 17, rd_dis: null, alt : '', dict : '', desc: 'Represents whether XTAL frequency is 48MHz or not. If not; 40MHz XTAL will be used. If this field contains Odd number bit 1: Enable 48MHz XTAL\ Even number bit 1: Enable 40MHz XTAL', rloc: 'EFUSE_RD_REPEAT_DATA4_REG[11:9]', bloc: 'B21[3:1]'} - XTAL_48M_SEL_MODE : {show: y, blk : 0, word: 5, pos: 12, len : 1, start: 172, type : bool, wr_dis : 17, rd_dis: null, alt : '', dict : '', desc: 'Specify the XTAL frequency selection is decided by eFuse or strapping-PAD-state. 1: eFuse\\ 0: strapping-PAD-state', rloc: 'EFUSE_RD_REPEAT_DATA4_REG[12]', bloc: 'B21[4]'} - ECDSA_DISABLE_P192 : {show: y, blk : 0, word: 5, pos: 13, len : 1, start: 173, type : bool, wr_dis : 14, rd_dis: null, alt : '', dict : '', desc: 'Represents whether to disable P192 curve in ECDSA.\\ 1: Disabled.\\ 0: Not disable', rloc: 'EFUSE_RD_REPEAT_DATA4_REG[13]', bloc: 'B21[5]'} - ECC_FORCE_CONST_TIME : {show: y, blk : 0, word: 5, pos: 14, len : 1, start: 174, type : bool, wr_dis : 14, rd_dis: null, alt : '', dict : '', desc: 'Represents whether to force ecc to use const-time calculation mode. \\ 1: Enable. \\ 0: Disable', rloc: 'EFUSE_RD_REPEAT_DATA4_REG[14]', bloc: 'B21[6]'} - RESERVE_0_175 : {show: n, blk : 0, word: 5, pos: 15, len : 17, start: 175, type : 'uint:17', 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:15]', bloc: 'B21[7],B22,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_SYS0_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: Represents the extended bits of MAC address, rloc: 'EFUSE_RD_MAC_SYS1_REG[31:16]', bloc: 'B6,B7'} - WAFER_VERSION_MINOR : {show: y, blk : 1, word: 2, pos : 0, len : 4, start : 64, type : 'uint:4', wr_dis : 20, rd_dis: null, alt : '', dict : '', desc: Minor chip version, rloc: 'EFUSE_RD_MAC_SYS2_REG[3:0]', bloc: 'B8[3:0]'} - WAFER_VERSION_MAJOR : {show: y, blk : 1, word: 2, pos : 4, len : 2, start : 68, type : 'uint:2', wr_dis : 20, rd_dis: null, alt : '', dict : '', desc: Minor chip version, rloc: 'EFUSE_RD_MAC_SYS2_REG[5:4]', bloc: 'B8[5:4]'} - DISABLE_WAFER_VERSION_MAJOR : {show: y, blk : 1, word: 2, pos : 6, len : 1, start : 70, type : bool, wr_dis : 20, rd_dis: null, alt : '', dict : '', desc: Disables check of wafer version major, rloc: 'EFUSE_RD_MAC_SYS2_REG[6]', bloc: 'B8[6]'} - DISABLE_BLK_VERSION_MAJOR : {show: y, blk : 1, word: 2, pos : 7, len : 1, start : 71, type : bool, wr_dis : 20, rd_dis: null, alt : '', dict : '', desc: Disables check of blk version major, rloc: 'EFUSE_RD_MAC_SYS2_REG[7]', bloc: 'B8[7]'} - BLK_VERSION_MINOR : {show: y, blk : 1, word: 2, pos : 8, len : 3, start : 72, type : 'uint:3', wr_dis : 20, rd_dis: null, alt : '', dict : '', desc: BLK_VERSION_MINOR of BLOCK2, rloc: 'EFUSE_RD_MAC_SYS2_REG[10:8]', bloc: 'B9[2:0]'} - BLK_VERSION_MAJOR : {show: y, blk : 1, word: 2, pos: 11, len : 2, start : 75, type : 'uint:2', wr_dis : 20, rd_dis: null, alt : '', dict : '', desc: BLK_VERSION_MAJOR of BLOCK2, rloc: 'EFUSE_RD_MAC_SYS2_REG[12:11]', bloc: 'B9[4:3]'} - FLASH_CAP : {show: y, blk : 1, word: 2, pos: 13, len : 3, start : 77, type : 'uint:3', wr_dis : 20, rd_dis: null, alt : '', dict : '', desc: Flash capacity, rloc: 'EFUSE_RD_MAC_SYS2_REG[15:13]', bloc: 'B9[7:5]'} - FLASH_VENDOR : {show: y, blk : 1, word: 2, pos: 16, len : 3, start : 80, type : 'uint:3', wr_dis : 20, rd_dis: null, alt : '', dict : '', desc: Flash vendor, rloc: 'EFUSE_RD_MAC_SYS2_REG[18:16]', bloc: 'B10[2:0]'} - PSRAM_CAP : {show: y, blk : 1, word: 2, pos: 19, len : 3, start : 83, type : 'uint:3', wr_dis : 20, rd_dis: null, alt : '', dict : '', desc: Psram capacity, rloc: 'EFUSE_RD_MAC_SYS2_REG[21:19]', bloc: 'B10[5:3]'} - PSRAM_VENDOR : {show: y, blk : 1, word: 2, pos: 22, len : 2, start : 86, type : 'uint:2', wr_dis : 20, rd_dis: null, alt : '', dict : '', desc: Psram vendor, rloc: 'EFUSE_RD_MAC_SYS2_REG[23:22]', bloc: 'B10[7:6]'} - TEMP : {show: y, blk : 1, word: 2, pos: 24, len : 2, start : 88, type : 'uint:2', wr_dis : 20, rd_dis: null, alt : '', dict : '', desc: Temp (die embedded inside), rloc: 'EFUSE_RD_MAC_SYS2_REG[25:24]', bloc: 'B11[1:0]'} - PKG_VERSION : {show: y, blk : 1, word: 2, pos: 26, len : 3, start : 90, type : 'uint:3', wr_dis : 20, rd_dis: null, alt : '', dict : '', desc: Package version, rloc: 'EFUSE_RD_MAC_SYS2_REG[28:26]', bloc: 'B11[4:2]'} - PA_TRIM_VERSION : {show: y, blk : 1, word: 2, pos: 29, len : 3, start : 93, type : 'uint:3', wr_dis : 20, rd_dis: null, alt : '', dict : '', desc: PADC CAL PA trim version, rloc: 'EFUSE_RD_MAC_SYS2_REG[31:29]', bloc: 'B11[7:5]'} - TRIM_N_BIAS : {show: y, blk : 1, word: 3, pos : 0, len : 5, start : 96, type : 'uint:5', wr_dis : 20, rd_dis: null, alt : '', dict : '', desc: PADC CAL N bias, rloc: 'EFUSE_RD_MAC_SYS3_REG[4:0]', bloc: 'B12[4:0]'} - TRIM_P_BIAS : {show: y, blk : 1, word: 3, pos : 5, len : 5, start: 101, type : 'uint:5', wr_dis : 20, rd_dis: null, alt : '', dict : '', desc: PADC CAL P bias, rloc: 'EFUSE_RD_MAC_SYS3_REG[9:5]', bloc: 'B12[7:5],B13[1:0]'} - RESERVED_1_106 : {show: n, blk : 1, word: 3, pos: 10, len : 8, start: 106, type : 'uint:8', wr_dis : 20, rd_dis: null, alt : '', dict : '', desc: reserved, rloc: 'EFUSE_RD_MAC_SYS3_REG[17:10]', bloc: 'B13[7:2],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: Represents the first 14-bit of zeroth part of system data, rloc: 'EFUSE_RD_MAC_SYS3_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: Represents the first 14-bit of zeroth part of system data, rloc: EFUSE_RD_MAC_SYS4_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: Represents the second 32-bit of zeroth part of system data, rloc: EFUSE_RD_MAC_SYS5_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 : 9, start: 128, type : 'uint:9', wr_dis : 21, rd_dis: null, alt : '', dict : '', desc: reserved, 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]'} - RESERVED_2_145 : {show: n, blk : 2, word: 4, pos: 17, len : 15, start: 145, type : 'uint:15', wr_dis : 21, rd_dis: null, alt : '', dict : '', desc: reserved, rloc: 'EFUSE_RD_SYS_PART1_DATA4_REG[31:17]', bloc: 'B18[7:1],B19'} - SYS_DATA_PART1_5 : {show: n, blk : 2, word: 5, pos : 0, len : 32, start: 160, type : 'uint:32', wr_dis : 21, rd_dis: null, alt : '', dict : '', desc: Represents the zeroth 32-bit of first part of system data, rloc: EFUSE_RD_SYS_PART1_DATA5_REG, bloc: 'B20,B21,B22,B23'} - SYS_DATA_PART1_6 : {show: n, blk : 2, word: 6, pos : 0, len : 32, start: 192, type : 'uint:32', wr_dis : 21, rd_dis: null, alt : '', dict : '', desc: Represents the zeroth 32-bit of first part of system data, rloc: EFUSE_RD_SYS_PART1_DATA6_REG, bloc: 'B24,B25,B26,B27'} - SYS_DATA_PART1_7 : {show: n, blk : 2, word: 7, pos : 0, len : 32, start: 224, type : 'uint:32', wr_dis : 21, rd_dis: null, alt : '', dict : '', desc: Represents the zeroth 32-bit of first part of system data, rloc: EFUSE_RD_SYS_PART1_DATA7_REG, bloc: 'B28,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, 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/tools/esptool_py/espefuse/efuse_defs/esp32c6.yaml b/tools/esptool_py/espefuse/efuse_defs/esp32c6.yaml deleted file mode 100644 index db8be540b6..0000000000 --- a/tools/esptool_py/espefuse/efuse_defs/esp32c6.yaml +++ /dev/null @@ -1,112 +0,0 @@ -VER_NO: df46b69f0ed3913114ba53d3a0b2b843 -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 threshold 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 threshold 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'} - ACTIVE_HP_DBIAS : {show: y, blk : 1, word: 2, pos : 0, len : 5, start : 64, type : 'uint:5', wr_dis : 20, rd_dis: null, alt : '', dict : '', desc: Stores the active hp dbias, rloc: 'EFUSE_RD_MAC_SPI_SYS_2_REG[4:0]', bloc: 'B8[4:0]'} - ACTIVE_LP_DBIAS : {show: y, blk : 1, word: 2, pos : 5, len : 5, start : 69, type : 'uint:5', wr_dis : 20, rd_dis: null, alt : '', dict : '', desc: Stores the active lp dbias, rloc: 'EFUSE_RD_MAC_SPI_SYS_2_REG[9:5]', bloc: 'B8[7:5],B9[1:0]'} - LSLP_HP_DBG : {show: y, blk : 1, word: 2, pos: 10, len : 2, start : 74, type : 'uint:2', wr_dis : 20, rd_dis: null, alt : '', dict : '', desc: Stores the lslp hp dbg, rloc: 'EFUSE_RD_MAC_SPI_SYS_2_REG[11:10]', bloc: 'B9[3:2]'} - LSLP_HP_DBIAS : {show: y, blk : 1, word: 2, pos: 12, len : 4, start : 76, type : 'uint:4', wr_dis : 20, rd_dis: null, alt : '', dict : '', desc: Stores the lslp hp dbias, rloc: 'EFUSE_RD_MAC_SPI_SYS_2_REG[15:12]', bloc: 'B9[7:4]'} - DSLP_LP_DBG : {show: y, blk : 1, word: 2, pos: 16, len : 3, start : 80, type : 'uint:3', wr_dis : 20, rd_dis: null, alt : '', dict : '', desc: Stores the dslp lp dbg, rloc: 'EFUSE_RD_MAC_SPI_SYS_2_REG[18:16]', bloc: 'B10[2:0]'} - DSLP_LP_DBIAS : {show: y, blk : 1, word: 2, pos: 19, len : 4, start : 83, type : 'uint:4', wr_dis : 20, rd_dis: null, alt : '', dict : '', desc: Stores the dslp lp dbias, rloc: 'EFUSE_RD_MAC_SPI_SYS_2_REG[22:19]', bloc: 'B10[6:3]'} - DBIAS_VOL_GAP : {show: y, blk : 1, word: 2, pos: 23, len : 5, start : 87, type : 'uint:5', wr_dis : 20, rd_dis: null, alt : '', dict : '', desc: Stores the hp and lp dbias vol gap, rloc: 'EFUSE_RD_MAC_SPI_SYS_2_REG[27:23]', bloc: 'B10[7],B11[3:0]'} - SPI_PAD_CONF_1 : {show: n, blk : 1, word: 2, pos: 28, len : 4, start : 92, type : 'uint:4', 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:28]', bloc: 'B11[7:4]'} - 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/tools/esptool_py/espefuse/efuse_defs/esp32c61.yaml b/tools/esptool_py/espefuse/efuse_defs/esp32c61.yaml deleted file mode 100644 index 3cbd2660e3..0000000000 --- a/tools/esptool_py/espefuse/efuse_defs/esp32c61.yaml +++ /dev/null @@ -1,84 +0,0 @@ -VER_NO: e564f8042b56a475a7714bb28ecdadfa -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_DIS0_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_ICACHE : {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 icache is disabled or enabled.\\ 1: disabled\\ 0: enabled\\', rloc: 'EFUSE_RD_REPEAT_DATA0_REG[7]', bloc: 'B4[7]'} - DIS_USB_JTAG : {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 the function of usb switch to jtag is disabled or enabled.\\ 1: disabled\\ 0: enabled\\', rloc: 'EFUSE_RD_REPEAT_DATA0_REG[8]', bloc: 'B5[0]'} - DIS_USB_SERIAL_JTAG : {show: n, blk : 0, word: 1, pos : 9, len : 1, start : 41, 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[9]', bloc: 'B5[1]'} - DIS_FORCE_DOWNLOAD : {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 the function that forces chip into download mode is disabled or enabled.\\ 1: disabled\\ 0: enabled\\', rloc: 'EFUSE_RD_REPEAT_DATA0_REG[10]', bloc: 'B5[2]'} - SPI_DOWNLOAD_MSPI_DIS : {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 SPI0 controller during boot_mode_download is disabled or enabled.\\ 1: disabled\\ 0: enabled\\', rloc: 'EFUSE_RD_REPEAT_DATA0_REG[11]', bloc: 'B5[3]'} - JTAG_SEL_ENABLE : {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 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[12]', bloc: 'B5[4]'} - DIS_PAD_JTAG : {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 JTAG is disabled in the hard way(permanently).\\ 1: disabled\\ 0: enabled\\', rloc: 'EFUSE_RD_REPEAT_DATA0_REG[13]', bloc: 'B5[5]'} - DIS_DOWNLOAD_MANUAL_ENCRYPT : {show: y, blk : 0, word: 1, pos: 14, len : 1, start : 46, 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[14]', bloc: 'B5[6]'} - USB_DREFH : {show: n, blk : 0, word: 1, pos: 15, len : 2, start : 47, type : 'uint:2', wr_dis : 30, rd_dis: null, alt : '', dict : '', desc: Represents the single-end input threshold vrefh; 1.76 V to 2 V with step of 80 mV, rloc: 'EFUSE_RD_REPEAT_DATA0_REG[16:15]', bloc: 'B5[7],B6[0]'} - USB_DREFL : {show: n, blk : 0, word: 1, pos: 17, len : 2, start : 49, type : 'uint:2', wr_dis : 30, rd_dis: null, alt : '', dict : '', desc: Represents the single-end input threshold vrefl; 1.76 V to 2 V with step of 80 mV, rloc: 'EFUSE_RD_REPEAT_DATA0_REG[18:17]', bloc: 'B6[2:1]'} - USB_EXCHG_PINS : {show: y, blk : 0, word: 1, pos: 19, len : 1, start : 51, 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[19]', bloc: 'B6[3]'} - VDD_SPI_AS_GPIO : {show: y, blk : 0, word: 1, pos: 20, len : 1, start : 52, 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[20]', bloc: 'B6[4]'} - WDT_DELAY_SEL : {show: y, blk : 0, word: 1, pos: 21, len : 2, start : 53, type : 'uint:2', wr_dis : 3, rd_dis: null, alt : '', dict : '', desc: 'Represents the threshold level of the RTC watchdog STG0 timeout.\\ 0: Original threshold configuration value of STG0 *2 \\1: Original threshold configuration value of STG0 *4 \\2: Original threshold configuration value of STG0 *8 \\3: Original threshold configuration value of STG0 *16 \\', rloc: 'EFUSE_RD_REPEAT_DATA0_REG[22:21]', bloc: 'B6[6:5]'} - SPI_BOOT_CRYPT_CNT : {show: y, blk : 0, word: 1, pos: 23, len : 3, start : 55, 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_DATA0_REG[25:23]', bloc: 'B6[7],B7[1:0]'} - SECURE_BOOT_KEY_REVOKE0 : {show: y, blk : 0, word: 1, pos: 26, len : 1, start : 58, type : bool, wr_dis : 5, rd_dis: null, alt : '', dict : '', desc: Revoke 1st secure boot key, rloc: 'EFUSE_RD_REPEAT_DATA0_REG[26]', bloc: 'B7[2]'} - SECURE_BOOT_KEY_REVOKE1 : {show: y, blk : 0, word: 1, pos: 27, len : 1, start : 59, type : bool, wr_dis : 6, rd_dis: null, alt : '', dict : '', desc: Revoke 2nd secure boot key, rloc: 'EFUSE_RD_REPEAT_DATA0_REG[27]', bloc: 'B7[3]'} - SECURE_BOOT_KEY_REVOKE2 : {show: y, blk : 0, word: 1, pos: 28, len : 1, start : 60, type : bool, wr_dis : 7, rd_dis: null, alt : '', dict : '', desc: Revoke 3rd secure boot key, rloc: 'EFUSE_RD_REPEAT_DATA0_REG[28]', bloc: 'B7[4]'} - RESERVE_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; it was created by set_missed_fields_in_regs func, rloc: 'EFUSE_RD_REPEAT_DATA0_REG[31:29]', bloc: 'B7[7:5]'} - KEY_PURPOSE_0 : {show: y, blk : 0, word: 2, pos : 0, len : 4, start : 64, 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[3:0]', bloc: 'B8[3:0]'} - KEY_PURPOSE_1 : {show: y, blk : 0, word: 2, pos : 4, len : 4, start : 68, 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[7:4]', bloc: 'B8[7:4]'} - KEY_PURPOSE_2 : {show: y, blk : 0, word: 2, pos : 8, len : 4, start : 72, type : 'uint:4', wr_dis : 10, rd_dis: null, alt : KEY2_PURPOSE, dict : '', desc: Represents the purpose of Key2, rloc: 'EFUSE_RD_REPEAT_DATA1_REG[11:8]', bloc: 'B9[3:0]'} - KEY_PURPOSE_3 : {show: y, blk : 0, word: 2, pos: 12, len : 4, start : 76, type : 'uint:4', wr_dis : 11, rd_dis: null, alt : KEY3_PURPOSE, dict : '', desc: Represents the purpose of Key3, rloc: 'EFUSE_RD_REPEAT_DATA1_REG[15:12]', bloc: 'B9[7:4]'} - KEY_PURPOSE_4 : {show: y, blk : 0, word: 2, pos: 16, len : 4, start : 80, type : 'uint:4', wr_dis : 12, rd_dis: null, alt : KEY4_PURPOSE, dict : '', desc: Represents the purpose of Key4, rloc: 'EFUSE_RD_REPEAT_DATA1_REG[19:16]', bloc: 'B10[3:0]'} - KEY_PURPOSE_5 : {show: y, blk : 0, word: 2, pos: 20, len : 4, start : 84, type : 'uint:4', wr_dis : 13, rd_dis: null, alt : KEY5_PURPOSE, dict : '', desc: Represents the purpose of Key5, rloc: 'EFUSE_RD_REPEAT_DATA1_REG[23:20]', bloc: 'B10[7:4]'} - SEC_DPA_LEVEL : {show: y, blk : 0, word: 2, pos: 24, len : 2, start : 88, 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_DATA1_REG[25:24]', bloc: 'B11[1:0]'} - SECURE_BOOT_EN : {show: y, blk : 0, word: 2, pos: 26, len : 1, start : 90, 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_DATA1_REG[26]', bloc: 'B11[2]'} - SECURE_BOOT_AGGRESSIVE_REVOKE : {show: y, blk : 0, word: 2, pos: 27, len : 1, start : 91, 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_DATA1_REG[27]', bloc: 'B11[3]'} - FLASH_TPUW : {show: y, blk : 0, word: 2, pos: 28, len : 4, start : 92, 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 programmed value. Otherwise; the waiting time is 2 times the programmed value, rloc: 'EFUSE_RD_REPEAT_DATA1_REG[31:28]', bloc: 'B11[7:4]'} - DIS_DOWNLOAD_MODE : {show: y, blk : 0, word: 3, pos : 0, len : 1, start : 96, type : bool, wr_dis : 18, rd_dis: null, alt : '', dict : '', desc: 'Represents whether Download mode is disable or enable.\\ 1. Disable\\ 0: Enable\\', rloc: 'EFUSE_RD_REPEAT_DATA2_REG[0]', bloc: 'B12[0]'} - DIS_DIRECT_BOOT : {show: y, blk : 0, word: 3, pos : 1, len : 1, start : 97, type : bool, wr_dis : 18, rd_dis: null, alt : '', dict : '', desc: 'Represents whether direct boot mode is disabled or enabled.\\ 1. Disable\\ 0: Enable\\', rloc: 'EFUSE_RD_REPEAT_DATA2_REG[1]', bloc: 'B12[1]'} - DIS_USB_SERIAL_JTAG_ROM_PRINT : {show: y, blk : 0, word: 3, pos : 2, len : 1, start : 98, type : bool, wr_dis : 18, rd_dis: null, alt : '', dict : '', desc: 'Represents whether print from USB-Serial-JTAG is disabled or enabled.\\ 1. Disable\\ 0: Enable\\', rloc: 'EFUSE_RD_REPEAT_DATA2_REG[2]', bloc: 'B12[2]'} - DIS_USB_SERIAL_JTAG_DOWNLOAD_MODE: {show: y, blk : 0, word: 3, pos : 3, len : 1, start : 99, type : bool, wr_dis : 18, rd_dis: null, alt : '', dict : '', desc: 'Represents whether the USB-Serial-JTAG download function is disabled or enabled.\\ 1: Disable\\ 0: Enable\\', rloc: 'EFUSE_RD_REPEAT_DATA2_REG[3]', bloc: 'B12[3]'} - ENABLE_SECURITY_DOWNLOAD : {show: y, blk : 0, word: 3, pos : 4, len : 1, start: 100, type : bool, wr_dis : 18, rd_dis: null, alt : '', dict : '', desc: 'Represents whether security download is enabled or disabled.\\ 1: Enable\\ 0: Disable\\', rloc: 'EFUSE_RD_REPEAT_DATA2_REG[4]', bloc: 'B12[4]'} - UART_PRINT_CONTROL : {show: y, blk : 0, word: 3, pos : 5, len : 2, start: 101, type : 'uint:2', wr_dis : 18, rd_dis: null, alt : '', dict : '', desc: Represents the types of UART printing, rloc: 'EFUSE_RD_REPEAT_DATA2_REG[6:5]', bloc: 'B12[6:5]'} - FORCE_SEND_RESUME : {show: y, blk : 0, word: 3, pos : 7, len : 1, start: 103, 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, rloc: 'EFUSE_RD_REPEAT_DATA2_REG[7]', bloc: 'B12[7]'} - SECURE_VERSION : {show: y, blk : 0, word: 3, pos : 8, len : 16, start: 104, 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_DATA2_REG[23:8]', bloc: 'B13,B14'} - SECURE_BOOT_DISABLE_FAST_WAKE : {show: y, blk : 0, word: 3, pos: 24, len : 1, start: 120, type : bool, wr_dis : 18, rd_dis: null, alt : '', dict : '', desc: Represents whether FAST_VERIFY_ON_WAKE is disable or enable when Secure Boot is enable, rloc: 'EFUSE_RD_REPEAT_DATA2_REG[24]', bloc: 'B15[0]'} - HYS_EN_PAD : {show: y, blk : 0, word: 3, pos: 25, len : 1, start: 121, type : bool, wr_dis : 2, rd_dis: null, alt : '', dict : '', desc: 'Represents whether the hysteresis function of corresponding PAD is enabled.\\ 1: enabled\\ 0:disabled\\', rloc: 'EFUSE_RD_REPEAT_DATA2_REG[25]', bloc: 'B15[1]'} - XTS_DPA_CLK_ENABLE : {show: y, blk : 0, word: 3, pos: 26, len : 1, start: 122, type : bool, wr_dis : 14, rd_dis: null, alt : '', dict : '', desc: 'Represents whether anti-dpa attack clock function is enabled.\\ 1. Enable\\ 0: Disable\\', rloc: 'EFUSE_RD_REPEAT_DATA2_REG[26]', bloc: 'B15[2]'} - XTS_DPA_PSEUDO_LEVEL : {show: y, blk : 0, word: 3, pos: 27, len : 2, start: 123, type : 'uint:2', wr_dis : 14, rd_dis: null, alt : '', dict : '', desc: 'Represents the anti-dpa attack pseudo function level.\\ 3:High\\ 2: Moderate\\ 1: Low\\ 0: Decided by register configuration\\', rloc: 'EFUSE_RD_REPEAT_DATA2_REG[28:27]', bloc: 'B15[4:3]'} - DIS_WIFI6 : {show: y, blk : 0, word: 3, pos: 29, len : 1, start: 125, type : bool, wr_dis : 2, rd_dis: null, alt : '', dict : '', desc: 'Represents whether the WiFi 6 feature is enable or disable.\\ 1: WiFi 6 is disable\\ 0: WiFi 6 is enabled.\\', rloc: 'EFUSE_RD_REPEAT_DATA2_REG[29]', bloc: 'B15[5]'} - ECDSA_DISABLE_P192 : {show: y, blk : 0, word: 3, pos: 30, len : 1, start: 126, type : bool, wr_dis : 14, rd_dis: null, alt : '', dict : '', desc: 'Represents whether to disable P192 curve in ECDSA.\\ 1: Disabled.\\ 0: Not disable', rloc: 'EFUSE_RD_REPEAT_DATA2_REG[30]', bloc: 'B15[6]'} - ECC_FORCE_CONST_TIME : {show: y, blk : 0, word: 3, pos: 31, len : 1, start: 127, type : bool, wr_dis : 14, rd_dis: null, alt : '', dict : '', desc: 'Represents whether to force ecc to use const-time calculation mode. \\ 1: Enable. \\ 0: Disable', rloc: 'EFUSE_RD_REPEAT_DATA2_REG[31]', bloc: 'B15[7]'} - REPEAT_DATA3 : {show: n, blk : 0, word: 4, pos : 0, len : 32, start: 128, type : 'uint:32', wr_dis: null, rd_dis: null, alt : '', dict : '', desc: Reserved, rloc: EFUSE_RD_REPEAT_DATA3_REG, bloc: 'B16,B17,B18,B19'} - REPEAT_DATA4 : {show: n, blk : 0, word: 5, pos : 0, len : 32, start: 160, type : 'uint:32', wr_dis: null, rd_dis: null, alt : '', dict : '', desc: Reserved, rloc: EFUSE_RD_REPEAT_DATA4_REG, bloc: 'B20,B21,B22,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_SYS0_REG, bloc: 'B0,B1,B2,B3,B4,B5'} - C61_NO_EXTENTION : {show: n, blk : 1, word: 1, pos: 16, len : 16, start : 48, type : 'uint:16', wr_dis : 20, rd_dis: null, alt : '', dict : '', desc: Reserved, rloc: 'EFUSE_RD_MAC_SYS1_REG[31:16]', bloc: 'B6,B7'} - WAFER_VERSION_MINOR : {show: y, blk : 1, word: 2, pos : 0, len : 4, start : 64, type : 'uint:4', wr_dis : 20, rd_dis: null, alt : '', dict : '', desc: Minor chip version, rloc: 'EFUSE_RD_MAC_SYS2_REG[3:0]', bloc: 'B8[3:0]'} - WAFER_VERSION_MAJOR : {show: y, blk : 1, word: 2, pos : 4, len : 2, start : 68, type : 'uint:2', wr_dis : 20, rd_dis: null, alt : '', dict : '', desc: Major chip version, rloc: 'EFUSE_RD_MAC_SYS2_REG[5:4]', bloc: 'B8[5:4]'} - DISABLE_WAFER_VERSION_MAJOR : {show: y, blk : 1, word: 2, pos : 6, len : 1, start : 70, type : bool, wr_dis : 20, rd_dis: null, alt : '', dict : '', desc: Disables check of wafer version major, rloc: 'EFUSE_RD_MAC_SYS2_REG[6]', bloc: 'B8[6]'} - DISABLE_BLK_VERSION_MAJOR : {show: y, blk : 1, word: 2, pos : 7, len : 1, start : 71, type : bool, wr_dis : 20, rd_dis: null, alt : '', dict : '', desc: Disables check of blk version major, rloc: 'EFUSE_RD_MAC_SYS2_REG[7]', bloc: 'B8[7]'} - BLK_VERSION_MINOR : {show: y, blk : 1, word: 2, pos : 8, len : 3, start : 72, type : 'uint:3', wr_dis : 20, rd_dis: null, alt : '', dict : '', desc: BLK_VERSION_MINOR of BLOCK2, rloc: 'EFUSE_RD_MAC_SYS2_REG[10:8]', bloc: 'B9[2:0]'} - BLK_VERSION_MAJOR : {show: y, blk : 1, word: 2, pos: 11, len : 2, start : 75, type : 'uint:2', wr_dis : 20, rd_dis: null, alt : '', dict : '', desc: BLK_VERSION_MAJOR of BLOCK2, rloc: 'EFUSE_RD_MAC_SYS2_REG[12:11]', bloc: 'B9[4:3]'} - FLASH_CAP : {show: y, blk : 1, word: 2, pos: 13, len : 3, start : 77, type : 'uint:3', wr_dis : 20, rd_dis: null, alt : '', dict : '', desc: Flash capacity, rloc: 'EFUSE_RD_MAC_SYS2_REG[15:13]', bloc: 'B9[7:5]'} - FLASH_VENDOR : {show: y, blk : 1, word: 2, pos: 16, len : 3, start : 80, type : 'uint:3', wr_dis : 20, rd_dis: null, alt : '', dict : '', desc: Flash vendor, rloc: 'EFUSE_RD_MAC_SYS2_REG[18:16]', bloc: 'B10[2:0]'} - PSRAM_CAP : {show: y, blk : 1, word: 2, pos: 19, len : 3, start : 83, type : 'uint:3', wr_dis : 20, rd_dis: null, alt : '', dict : '', desc: PSRAM capacity, rloc: 'EFUSE_RD_MAC_SYS2_REG[21:19]', bloc: 'B10[5:3]'} - PSRAM_VENDOR : {show: y, blk : 1, word: 2, pos: 22, len : 2, start : 86, type : 'uint:2', wr_dis : 20, rd_dis: null, alt : '', dict : '', desc: PSRAM vendor, rloc: 'EFUSE_RD_MAC_SYS2_REG[23:22]', bloc: 'B10[7:6]'} - TEMP : {show: y, blk : 1, word: 2, pos: 24, len : 2, start : 88, type : 'uint:2', wr_dis : 20, rd_dis: null, alt : '', dict : '', desc: Temperature, rloc: 'EFUSE_RD_MAC_SYS2_REG[25:24]', bloc: 'B11[1:0]'} - PKG_VERSION : {show: y, blk : 1, word: 2, pos: 26, len : 3, start : 90, type : 'uint:3', wr_dis : 20, rd_dis: null, alt : '', dict : '', desc: Package version, rloc: 'EFUSE_RD_MAC_SYS2_REG[28:26]', bloc: 'B11[4:2]'} - RESERVED_1_93 : {show: n, blk : 1, word: 2, pos: 29, len : 3, start : 93, type : 'uint:3', wr_dis : 20, rd_dis: null, alt : '', dict : '', desc: reserved, rloc: 'EFUSE_RD_MAC_SYS2_REG[31:29]', bloc: 'B11[7:5]'} - 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_SYS3_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: Represents the first 14-bit of zeroth part of system data, rloc: 'EFUSE_RD_MAC_SYS3_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: Represents the first 14-bit of zeroth part of system data, rloc: EFUSE_RD_MAC_SYS4_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: Represents the second 32-bit of zeroth part of system data, rloc: EFUSE_RD_MAC_SYS5_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'} - SYS_DATA_PART1_4 : {show: n, blk : 2, word: 4, pos : 0, len : 32, start: 128, type : 'uint:32', wr_dis : 21, rd_dis: null, alt : '', dict : '', desc: Represents the zeroth 32-bit of first part of system data, rloc: EFUSE_RD_SYS_PART1_DATA4_REG, bloc: 'B16,B17,B18,B19'} - SYS_DATA_PART1_5 : {show: n, blk : 2, word: 5, pos : 0, len : 32, start: 160, type : 'uint:32', wr_dis : 21, rd_dis: null, alt : '', dict : '', desc: Represents the zeroth 32-bit of first part of system data, rloc: EFUSE_RD_SYS_PART1_DATA5_REG, bloc: 'B20,B21,B22,B23'} - SYS_DATA_PART1_6 : {show: n, blk : 2, word: 6, pos : 0, len : 32, start: 192, type : 'uint:32', wr_dis : 21, rd_dis: null, alt : '', dict : '', desc: Represents the zeroth 32-bit of first part of system data, rloc: EFUSE_RD_SYS_PART1_DATA6_REG, bloc: 'B24,B25,B26,B27'} - SYS_DATA_PART1_7 : {show: n, blk : 2, word: 7, pos : 0, len : 32, start: 224, type : 'uint:32', wr_dis : 21, rd_dis: null, alt : '', dict : '', desc: Represents the zeroth 32-bit of first part of system data, rloc: EFUSE_RD_SYS_PART1_DATA7_REG, bloc: 'B28,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, 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/tools/esptool_py/espefuse/efuse_defs/esp32h2.yaml b/tools/esptool_py/espefuse/efuse_defs/esp32h2.yaml deleted file mode 100644 index 7dddf5108e..0000000000 --- a/tools/esptool_py/espefuse/efuse_defs/esp32h2.yaml +++ /dev/null @@ -1,106 +0,0 @@ -VER_NO: ef562916e77cf77203c1a4c0cff35ac5 -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 threshold 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 threshold 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: Stores 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: Stores 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: Stores RF Calibration data. RXIQ data 1, rloc: 'EFUSE_RD_MAC_SYS_2_REG[16:10]', bloc: 'B9[7:2],B10[0]'} - ACTIVE_HP_DBIAS : {show: y, blk : 1, word: 2, pos: 17, len : 5, start : 81, type : 'uint:5', wr_dis : 20, rd_dis: null, alt : '', dict : '', desc: Stores the PMU active hp dbias, rloc: 'EFUSE_RD_MAC_SYS_2_REG[21:17]', bloc: 'B10[5:1]'} - ACTIVE_LP_DBIAS : {show: y, blk : 1, word: 2, pos: 22, len : 5, start : 86, type : 'uint:5', wr_dis : 20, rd_dis: null, alt : '', dict : '', desc: Stores the PMU active lp dbias, rloc: 'EFUSE_RD_MAC_SYS_2_REG[26:22]', bloc: 'B10[7:6],B11[2:0]'} - DSLP_DBIAS : {show: y, blk : 1, word: 2, pos: 27, len : 4, start : 91, type : 'uint:4', wr_dis : 20, rd_dis: null, alt : '', dict : '', desc: Stores the PMU sleep dbias, rloc: 'EFUSE_RD_MAC_SYS_2_REG[30:27]', bloc: 'B11[6:3]'} - DBIAS_VOL_GAP : {show: y, blk : 1, word: 2, pos: 31, len : 5, start : 95, type : 'uint:5', wr_dis : 20, rd_dis: null, alt : '', dict : '', desc: Stores the low 1 bit of dbias_vol_gap, rloc: 'EFUSE_RD_MAC_SYS_2_REG[31]', bloc: 'B11[7],B12[3:0]'} - MAC_RESERVED_2 : {show: n, blk : 1, word: 3, pos : 4, len : 14, start: 100, type : 'uint:14', wr_dis : 20, rd_dis: null, alt : '', dict : '', desc: Reserved, rloc: 'EFUSE_RD_MAC_SYS_3_REG[17:4]', bloc: 'B12[7:4],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: Stores the wafer version minor, 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: Stores the wafer version major, 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: Stores the flash cap, 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: Stores the flash temp, 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: Stores the flash vendor, 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/tools/esptool_py/espefuse/efuse_defs/esp32p4.yaml b/tools/esptool_py/espefuse/efuse_defs/esp32p4.yaml deleted file mode 100644 index e4ffea60d7..0000000000 --- a/tools/esptool_py/espefuse/efuse_defs/esp32p4.yaml +++ /dev/null @@ -1,106 +0,0 @@ -VER_NO: d4a48929387e281bd05db8cfb3a85f60 -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 : 30, 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 : 30, 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 : 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: 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 : 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: 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 : 2, 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 : 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_DEVICE_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: 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 : 30, 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 : 30, rd_dis: null, alt : '', dict : '', desc: TBD, rloc: 'EFUSE_RD_REPEAT_DATA0_REG[25]', bloc: 'B7[1]'} - KM_HUK_GEN_STATE : {show: y, blk : 0, word: 1, pos: 26, len : 9, start : 58, type : 'uint:9', wr_dis : 19, 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],B8[2:0]'} - KM_RND_SWITCH_CYCLE : {show: y, blk : 0, word: 2, pos : 3, len : 2, start : 67, type : 'uint:2', wr_dis : 1, 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 : 1, 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 : 1, 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 : 1, 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 : 1, 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 : 2, 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_ENABLE_SOFT_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]'} - 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 : 18, 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 : 18, 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 : 18, 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 : 18, 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 : 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 : '', 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 : 1, 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 : 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 : '', 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 : 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_PAD : {show: y, blk : 0, word: 4, pos: 26, len : 1, start: 154, type : bool, wr_dis : 2, 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 : 2, rd_dis: null, alt : '', 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 : 2, rd_dis: null, alt : '', 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 : 2, rd_dis: null, alt : '', 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 : 2, rd_dis: null, alt : '', 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 : 1, 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 : 30, rd_dis: null, alt : '', dict : '', desc: Represents the usb device single-end input low threshold; 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 : 30, rd_dis: null, alt : '', dict : '', desc: Represents the usb otg11 single-end input low threshold; 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 : 3, 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 : 2, 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 : 2, 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'} - RESERVED_1_16 : {show: n, blk : 1, word: 1, pos: 16, len : 16, start : 48, type : 'uint:16', 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'} - WAFER_VERSION_MINOR : {show: y, blk : 1, word: 2, pos : 0, len : 4, start : 64, type : 'uint:4', wr_dis : 20, rd_dis: null, alt : '', dict : '', desc: Minor chip version, rloc: 'EFUSE_RD_MAC_SYS_2_REG[3:0]', bloc: 'B8[3:0]'} - WAFER_VERSION_MAJOR : {show: y, blk : 1, word: 2, pos : 4, len : 2, start : 68, type : 'uint:2', wr_dis : 20, rd_dis: null, alt : '', dict : '', desc: Major chip version, rloc: 'EFUSE_RD_MAC_SYS_2_REG[5:4]', bloc: 'B8[5:4]'} - DISABLE_WAFER_VERSION_MAJOR : {show: y, blk : 1, word: 2, pos : 6, len : 1, start : 70, type : bool, wr_dis : 20, rd_dis: null, alt : '', dict : '', desc: Disables check of wafer version major, rloc: 'EFUSE_RD_MAC_SYS_2_REG[6]', bloc: 'B8[6]'} - DISABLE_BLK_VERSION_MAJOR : {show: y, blk : 1, word: 2, pos : 7, len : 1, start : 71, type : bool, wr_dis : 20, rd_dis: null, alt : '', dict : '', desc: Disables check of blk version major, rloc: 'EFUSE_RD_MAC_SYS_2_REG[7]', bloc: 'B8[7]'} - BLK_VERSION_MINOR : {show: y, blk : 1, word: 2, pos : 8, len : 3, start : 72, type : 'uint:3', wr_dis : 20, rd_dis: null, alt : '', dict : '', desc: BLK_VERSION_MINOR of BLOCK2, rloc: 'EFUSE_RD_MAC_SYS_2_REG[10:8]', bloc: 'B9[2:0]'} - BLK_VERSION_MAJOR : {show: y, blk : 1, word: 2, pos: 11, len : 2, start : 75, type : 'uint:2', wr_dis : 20, rd_dis: null, alt : '', dict : '', desc: BLK_VERSION_MAJOR of BLOCK2, rloc: 'EFUSE_RD_MAC_SYS_2_REG[12:11]', bloc: 'B9[4:3]'} - PSRAM_CAP : {show: y, blk : 1, word: 2, pos: 13, len : 3, start : 77, type : 'uint:3', wr_dis : 20, rd_dis: null, alt : '', dict : '', desc: PSRAM capacity, rloc: 'EFUSE_RD_MAC_SYS_2_REG[15:13]', bloc: 'B9[7:5]'} - TEMP : {show: y, blk : 1, word: 2, pos: 16, len : 2, start : 80, type : 'uint:2', wr_dis : 20, rd_dis: null, alt : '', dict : '', desc: Operating temperature of the ESP chip, rloc: 'EFUSE_RD_MAC_SYS_2_REG[17:16]', bloc: 'B10[1:0]'} - PSRAM_VENDOR : {show: y, blk : 1, word: 2, pos: 18, len : 2, start : 82, type : 'uint:2', wr_dis : 20, rd_dis: null, alt : '', dict : '', desc: PSRAM vendor, rloc: 'EFUSE_RD_MAC_SYS_2_REG[19:18]', bloc: 'B10[3:2]'} - PKG_VERSION : {show: y, blk : 1, word: 2, pos: 20, len : 3, start : 84, type : 'uint:3', wr_dis : 20, rd_dis: null, alt : '', dict : '', desc: Package version, rloc: 'EFUSE_RD_MAC_SYS_2_REG[22:20]', bloc: 'B10[6:4]'} - RESERVED_1_87 : {show: n, blk : 1, word: 2, pos: 23, len : 9, start : 87, type : 'uint:9', wr_dis : 20, rd_dis: null, alt : '', dict : '', desc: reserved, rloc: 'EFUSE_RD_MAC_SYS_2_REG[31:23]', bloc: 'B10[7],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'} - 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'} - SYS_DATA_PART1_4 : {show: n, blk : 2, word: 4, pos : 0, len : 32, start: 128, type : 'uint:32', wr_dis : 21, rd_dis: null, alt : '', dict : '', desc: Stores the fourth 32 bits of the first part of system data, rloc: EFUSE_RD_SYS_PART1_DATA4_REG, bloc: 'B16,B17,B18,B19'} - SYS_DATA_PART1_5 : {show: n, blk : 2, word: 5, pos : 0, len : 32, start: 160, type : 'uint:32', wr_dis : 21, rd_dis: null, alt : '', dict : '', desc: Stores the fifth 32 bits of the first part of system data, rloc: EFUSE_RD_SYS_PART1_DATA5_REG, bloc: 'B20,B21,B22,B23'} - SYS_DATA_PART1_6 : {show: n, blk : 2, word: 6, pos : 0, len : 32, start: 192, type : 'uint:32', wr_dis : 21, rd_dis: null, alt : '', dict : '', desc: Stores the sixth 32 bits of the first part of system data, rloc: EFUSE_RD_SYS_PART1_DATA6_REG, bloc: 'B24,B25,B26,B27'} - SYS_DATA_PART1_7 : {show: n, blk : 2, word: 7, pos : 0, len : 32, start: 224, type : 'uint:32', wr_dis : 21, rd_dis: null, alt : '', dict : '', desc: Stores the seventh 32 bits of the first part of system data, rloc: EFUSE_RD_SYS_PART1_DATA7_REG, bloc: 'B28,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, 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/tools/esptool_py/espefuse/efuse_defs/esp32s2.yaml b/tools/esptool_py/espefuse/efuse_defs/esp32s2.yaml deleted file mode 100644 index 45b5900e48..0000000000 --- a/tools/esptool_py/espefuse/efuse_defs/esp32s2.yaml +++ /dev/null @@ -1,119 +0,0 @@ -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/tools/esptool_py/espefuse/efuse_defs/esp32s3.yaml b/tools/esptool_py/espefuse/efuse_defs/esp32s3.yaml deleted file mode 100644 index 4d4c69511d..0000000000 --- a/tools/esptool_py/espefuse/efuse_defs/esp32s3.yaml +++ /dev/null @@ -1,134 +0,0 @@ -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/tools/esptool_py/espsecure.py b/tools/esptool_py/espsecure.py deleted file mode 100755 index 29b8e48e83..0000000000 --- a/tools/esptool_py/espsecure.py +++ /dev/null @@ -1,37 +0,0 @@ -#!/usr/bin/env python -# -# SPDX-FileCopyrightText: 2014-2022 Fredrik Ahlberg, Angus Gratton, -# Espressif Systems (Shanghai) CO LTD, other contributors as noted. -# -# SPDX-License-Identifier: GPL-2.0-or-later - -# This executable script is a thin wrapper around the main functionality -# in the espsecure Python package - -# When updating this script, please also update esptool.py and espefuse.py - -import contextlib -import os -import sys - -if os.name != "nt": - # 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): - 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 - # other Python scripts - with contextlib.suppress(KeyError): - del sys.modules["espsecure"] - -import espsecure - -if __name__ == "__main__": - espsecure._main() diff --git a/tools/esptool_py/espsecure/__init__.py b/tools/esptool_py/espsecure/__init__.py deleted file mode 100755 index 81688c104d..0000000000 --- a/tools/esptool_py/espsecure/__init__.py +++ /dev/null @@ -1,1918 +0,0 @@ -# SPDX-FileCopyrightText: 2016-2023 Espressif Systems (Shanghai) CO LTD -# -# SPDX-License-Identifier: GPL-2.0-or-later -# PYTHON_ARGCOMPLETE_OK -import argparse -import hashlib -import operator -import os -import struct -import sys -import tempfile -import zlib -from collections import namedtuple -from io import IOBase - -from cryptography import exceptions -from cryptography.hazmat.backends import default_backend -from cryptography.hazmat.primitives import hashes -from cryptography.hazmat.primitives import serialization -from cryptography.hazmat.primitives.asymmetric import ec, padding, rsa, utils -from cryptography.hazmat.primitives.ciphers import Cipher, algorithms, modes -from cryptography.utils import int_to_bytes - -import ecdsa - -import esptool - -SIG_BLOCK_MAGIC = 0xE7 - -# Scheme used in Secure Boot V2 -SIG_BLOCK_VERSION_RSA = 0x02 -SIG_BLOCK_VERSION_ECDSA = 0x03 - -# SHA scheme used in Secure Boot V2 ECDSA signature blocks -ECDSA_SHA_256 = 0x0 -ECDSA_SHA_384 = 0x1 - -# Curve IDs used in Secure Boot V2 ECDSA signature blocks -CURVE_ID_P192 = 1 -CURVE_ID_P256 = 2 -CURVE_ID_P384 = 3 - -SECTOR_SIZE = 4096 -SIG_BLOCK_SIZE = ( - 1216 # Refer to secure boot v2 signature block format for more details. -) - - -def get_chunks(source, chunk_len): - """Returns an iterator over 'chunk_len' chunks of 'source'""" - return (source[i : i + chunk_len] for i in range(0, len(source), chunk_len)) - - -def endian_swap_words(source): - """Endian-swap each word in 'source' bitstring""" - assert len(source) % 4 == 0 - words = "I" * (len(source) // 4) - return struct.pack("<" + words, *struct.unpack(">" + words, source)) - - -def swap_word_order(source): - """Swap the order of the words in 'source' bitstring""" - assert len(source) % 4 == 0 - words = "I" * (len(source) // 4) - return struct.pack(words, *reversed(struct.unpack(words, source))) - - -def _load_hardware_key(keyfile): - """Load a 128/256/512-bit key, similar to stored in efuse, from a file - - 128-bit keys will be extended to 256-bit using the SHA256 of the key - 192-bit keys will be extended to 256-bit using the same algorithm used - by hardware if 3/4 Coding Scheme is set. - """ - key = keyfile.read() - if len(key) not in [16, 24, 32, 64]: - raise esptool.FatalError( - "Key file contains wrong length (%d bytes), 16, 24, 32 or 64 expected." - % len(key) - ) - if len(key) == 16: - key = _sha256_digest(key) - print("Using 128-bit key (extended)") - elif len(key) == 24: - key = key + key[8:16] - assert len(key) == 32 - print("Using 192-bit key (extended)") - elif len(key) == 32: - print("Using 256-bit key") - else: - print("Using 512-bit key") - return key - - -def digest_secure_bootloader(args): - """Calculate the digest of a bootloader image, in the same way the hardware - secure boot engine would do so. Can be used with a pre-loaded key to update a - secure bootloader.""" - _check_output_is_not_input(args.keyfile, args.output) - _check_output_is_not_input(args.image, args.output) - _check_output_is_not_input(args.iv, args.output) - if args.iv is not None: - print("WARNING: --iv argument is for TESTING PURPOSES ONLY") - iv = args.iv.read(128) - else: - iv = os.urandom(128) - plaintext_image = args.image.read() - args.image.seek(0) - - # secure boot engine reads in 128 byte blocks (ie SHA512 block - # size), but also doesn't look for any appended SHA-256 digest - fw_image = esptool.bin_image.ESP32FirmwareImage(args.image) - if fw_image.append_digest: - if len(plaintext_image) % 128 <= 32: - # ROM bootloader will read to the end of the 128 byte block, but not - # to the end of the SHA-256 digest at the end - new_len = len(plaintext_image) - (len(plaintext_image) % 128) - plaintext_image = plaintext_image[:new_len] - - # if image isn't 128 byte multiple then pad with 0xFF (ie unwritten flash) - # as this is what the secure boot engine will see - if len(plaintext_image) % 128 != 0: - plaintext_image += b"\xFF" * (128 - (len(plaintext_image) % 128)) - - plaintext = iv + plaintext_image - - # Secure Boot digest algorithm in hardware uses AES256 ECB to - # produce a ciphertext, then feeds output through SHA-512 to - # produce the digest. Each block in/out of ECB is reordered - # (due to hardware quirks not for security.) - - key = _load_hardware_key(args.keyfile) - backend = default_backend() - cipher = Cipher(algorithms.AES(key), modes.ECB(), backend=backend) - encryptor = cipher.encryptor() - digest = hashlib.sha512() - - for block in get_chunks(plaintext, 16): - block = block[::-1] # reverse each input block - - cipher_block = encryptor.update(block) - # reverse and then byte swap each word in the output block - cipher_block = cipher_block[::-1] - for block in get_chunks(cipher_block, 4): - # Python hashlib can build each SHA block internally - digest.update(block[::-1]) - - if args.output is None: - args.output = os.path.splitext(args.image.name)[0] + "-digest-0x0000.bin" - with open(args.output, "wb") as f: - f.write(iv) - digest = digest.digest() - for word in get_chunks(digest, 4): - f.write(word[::-1]) # swap word order in the result - f.write(b"\xFF" * (0x1000 - f.tell())) # pad to 0x1000 - f.write(plaintext_image) - print("digest+image written to %s" % args.output) - - -def _generate_ecdsa_signing_key(curve_id, keyfile): - sk = ecdsa.SigningKey.generate(curve=curve_id) - with open(keyfile, "wb") as f: - f.write(sk.to_pem()) - - -def generate_signing_key(args): - if os.path.exists(args.keyfile): - raise esptool.FatalError("ERROR: Key file %s already exists" % args.keyfile) - if args.version == "1": - if hasattr(args, "scheme"): - if args.scheme != "ecdsa256" and args.scheme is not None: - raise esptool.FatalError("ERROR: V1 only supports ECDSA256") - """ - Generate an ECDSA signing key for signing secure boot images (post-bootloader) - """ - _generate_ecdsa_signing_key(ecdsa.NIST256p, args.keyfile) - print("ECDSA NIST256p private key in PEM format written to %s" % args.keyfile) - elif args.version == "2": - if args.scheme == "rsa3072" or args.scheme is None: - """Generate a RSA 3072 signing key for signing secure boot images""" - private_key = rsa.generate_private_key( - public_exponent=65537, key_size=3072, backend=default_backend() - ).private_bytes( - encoding=serialization.Encoding.PEM, - format=serialization.PrivateFormat.TraditionalOpenSSL, - encryption_algorithm=serialization.NoEncryption(), - ) - with open(args.keyfile, "wb") as f: - f.write(private_key) - print(f"RSA 3072 private key in PEM format written to {args.keyfile}") - elif args.scheme == "ecdsa192": - """Generate a ECDSA 192 signing key for signing secure boot images""" - _generate_ecdsa_signing_key(ecdsa.NIST192p, args.keyfile) - print(f"ECDSA NIST192p private key in PEM format written to {args.keyfile}") - elif args.scheme == "ecdsa256": - """Generate a ECDSA 256 signing key for signing secure boot images""" - _generate_ecdsa_signing_key(ecdsa.NIST256p, args.keyfile) - print(f"ECDSA NIST256p private key in PEM format written to {args.keyfile}") - elif args.scheme == "ecdsa384": - """Generate a ECDSA 384 signing key for signing secure boot images""" - _generate_ecdsa_signing_key(ecdsa.NIST384p, args.keyfile) - print(f"ECDSA NIST384p private key in PEM format written to {args.keyfile}") - else: - raise esptool.FatalError("ERROR: Unsupported signing scheme {args.scheme}") - - -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 = load_ecdsa_signing_key(keyfile) - if sk.curve != ecdsa.NIST256p: - raise esptool.FatalError( - "Signing key uses incorrect curve. ESP32 Secure Boot only supports " - "NIST256p (openssl calls this curve 'prime256v1')" - ) - return sk - - -def _load_ecdsa_verifying_key(keyfile): - """Load ECDSA verifying key for Secure Boot V1 only""" - 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 " - "NIST256p (openssl calls this curve 'prime256v1')" - ) - return vk - - -def _load_sbv2_signing_key(keydata): - """ - Load Secure Boot V2 signing key - - can be rsa.RSAPrivateKey or ec.EllipticCurvePrivateKey - """ - sk = serialization.load_pem_private_key( - keydata, password=None, backend=default_backend() - ) - if isinstance(sk, rsa.RSAPrivateKey): - if sk.key_size != 3072: - raise esptool.FatalError( - "Key file has length %d bits. Secure boot v2 only supports RSA-3072." - % sk.key_size - ) - return sk - if isinstance(sk, ec.EllipticCurvePrivateKey): - if not isinstance(sk.curve, (ec.SECP192R1, ec.SECP256R1, ec.SECP384R1)): - raise esptool.FatalError( - "Key file uses incorrect curve. Secure Boot V2 + ECDSA only supports " - "NIST192p, NIST256p, NIST384p (aka prime192v1 / secp192r1, prime256v1 / secp256r1, secp384r1)" - ) - return sk - - raise esptool.FatalError("Unsupported signing key for Secure Boot V2") - - -def _load_sbv2_pub_key(keydata): - """ - Load Secure Boot V2 public key, can be rsa.RSAPublicKey or ec.EllipticCurvePublicKey - """ - vk = serialization.load_pem_public_key(keydata, backend=default_backend()) - if isinstance(vk, rsa.RSAPublicKey): - if vk.key_size != 3072: - raise esptool.FatalError( - "Key file has length %d bits. Secure boot v2 only supports RSA-3072." - % vk.key_size - ) - return vk - if isinstance(vk, ec.EllipticCurvePublicKey): - if not isinstance(vk.curve, (ec.SECP192R1, ec.SECP256R1, ec.SECP384R1)): - raise esptool.FatalError( - "Key file uses incorrect curve. Secure Boot V2 + ECDSA only supports " - "NIST192p, NIST256p, NIST384p (aka prime192v1 / secp192r1, prime256v1 / secp256r1, secp384r1)" - ) - return vk - - raise esptool.FatalError("Unsupported public key for Secure Boot V2") - - -def _get_sbv2_pub_key(keyfile): - key_data = keyfile.read() - if ( - b"-BEGIN RSA PRIVATE KEY" in key_data - or b"-BEGIN EC PRIVATE KEY" in key_data - or b"-BEGIN PRIVATE KEY" in key_data - ): - return _load_sbv2_signing_key(key_data).public_key() - elif b"-BEGIN PUBLIC KEY" in key_data: - vk = _load_sbv2_pub_key(key_data) - else: - raise esptool.FatalError( - "Verification key does not appear to be an RSA Private or " - "Public key in PEM format. Unsupported" - ) - return vk - - -def _get_sbv2_rsa_primitives(public_key): - primitives = namedtuple("primitives", ["n", "e", "m", "rinv"]) - numbers = public_key.public_numbers() - primitives.n = numbers.n # - primitives.e = numbers.e # two public key components - - # Note: this cheats and calls a private 'rsa' method to get the modular - # inverse calculation. - primitives.m = -rsa._modinv(primitives.n, 1 << 32) - - rr = 1 << (public_key.key_size * 2) - primitives.rinv = rr % primitives.n - return primitives - - -def _microecc_format(a, b, curve_len): - """ - Given two numbers (curve coordinates or (r,s) signature), write them out as a - little-endian byte sequence suitable for micro-ecc - "native little endian" mode - """ - byte_len = int(curve_len / 8) - ab = int_to_bytes(a, byte_len)[::-1] + int_to_bytes(b, byte_len)[::-1] - assert len(ab) in [48, 64, 96] - return ab - - -def sign_data(args): - if args.keyfile: - _check_output_is_not_input(args.keyfile, args.output) - _check_output_is_not_input(args.datafile, args.output) - if args.version == "1": - return sign_secure_boot_v1(args) - elif args.version == "2": - return sign_secure_boot_v2(args) - - -def sign_secure_boot_v1(args): - """ - Sign a data file with a ECDSA private key, append binary signature to file contents - """ - binary_content = args.datafile.read() - - if args.hsm: - raise esptool.FatalError( - "Secure Boot V1 does not support signing using an " - "external Hardware Security Module (HSM)" - ) - - if args.signature: - print("Pre-calculated signatures found") - if len(args.pub_key) > 1: - raise esptool.FatalError("Secure Boot V1 only supports one signing key") - signature = args.signature[0].read() - # get verifying/public key - vk = _load_ecdsa_verifying_key(args.pub_key[0]) - else: - if len(args.keyfile) > 1: - raise esptool.FatalError("Secure Boot V1 only supports one signing key") - sk = _load_ecdsa_signing_key(args.keyfile[0]) - - # calculate signature of binary data - signature = sk.sign_deterministic(binary_content, hashlib.sha256) - # get verifying/public key - vk = sk.get_verifying_key() - - # back-verify signature - vk.verify(signature, binary_content, hashlib.sha256) # throws exception on failure - if args.output is None or os.path.abspath(args.output) == os.path.abspath( - args.datafile.name - ): # append signature to input file - args.datafile.close() - outfile = open(args.datafile.name, "ab") - else: # write file & signature to new file - outfile = open(args.output, "wb") - outfile.write(binary_content) - outfile.write( - struct.pack("I", 0) - ) # Version indicator, allow for different curves/formats later - outfile.write(signature) - outfile.close() - print("Signed %d bytes of data from %s" % (len(binary_content), args.datafile.name)) - - -def sign_secure_boot_v2(args): - """ - Sign a firmware app image with an RSA private key using RSA-PSS, - or ECDSA private key using P192 or P256 or P384. - - Write output file with a Secure Boot V2 header appended. - """ - SIG_BLOCK_MAX_COUNT = 3 - contents = args.datafile.read() - sig_block_num = 0 - signature_sector = b"" - - signature = args.signature - pub_key = args.pub_key - - if len(contents) % SECTOR_SIZE != 0: - if args.signature: - raise esptool.FatalError( - "Secure Boot V2 requires the signature block to start " - "from a 4KB aligned sector " - "but the datafile supplied is not sector aligned." - ) - else: - pad_by = SECTOR_SIZE - (len(contents) % SECTOR_SIZE) - print( - f"Padding data contents by {pad_by} bytes " - "so signature sector aligns at sector boundary" - ) - contents += b"\xff" * pad_by - - elif args.append_signatures: - while sig_block_num < SIG_BLOCK_MAX_COUNT: - sig_block = validate_signature_block(contents, sig_block_num) - if sig_block is None: - break - signature_sector += ( - sig_block # Signature sector is populated with already valid blocks - ) - sig_block_num += 1 - - if len(signature_sector) % SIG_BLOCK_SIZE != 0: - raise esptool.FatalError("Incorrect signature sector size") - - if sig_block_num == 0: - print( - "No valid signature blocks found. " - "Discarding --append-signature and proceeding to sign the image afresh." - ) - else: - print( - f"{sig_block_num} valid signature block(s) already present " - "in the signature sector." - ) - if sig_block_num == SIG_BLOCK_MAX_COUNT: - raise esptool.FatalError( - f"Upto {SIG_BLOCK_MAX_COUNT} signature blocks are supported. " - "(For ESP32-ECO3 only 1 signature block is supported)" - ) - - # Signature stripped off the content - # (the legitimate blocks are included in signature_sector) - contents = contents[: len(contents) - SECTOR_SIZE] - - if args.hsm: - if args.hsm_config is None: - raise esptool.FatalError( - "Config file is required to generate signature using an external HSM." - ) - import espsecure.esp_hsm_sign as hsm - - try: - config = hsm.read_hsm_config(args.hsm_config) - except Exception as e: - raise esptool.FatalError(f"Incorrect HSM config file format ({e})") - if pub_key is None: - pub_key = extract_pubkey_from_hsm(config) - signature = generate_signature_using_hsm(config, contents) - - if signature: - print("Pre-calculated signatures found") - key_count = len(pub_key) - if len(signature) != key_count: - raise esptool.FatalError( - f"Number of public keys ({key_count}) not equal to " - f"the number of signatures {len(signature)}." - ) - else: - key_count = len(args.keyfile) - - empty_signature_blocks = SIG_BLOCK_MAX_COUNT - sig_block_num - if key_count > empty_signature_blocks: - raise esptool.FatalError( - f"Number of keys({key_count}) more than the empty signature blocks." - f"({empty_signature_blocks})" - ) - - print(f"{key_count} signing key(s) found.") - - # Generate signature block using pre-calculated signatures - if signature: - signature_block = generate_signature_block_using_pre_calculated_signature( - signature, pub_key, contents - ) - # Generate signature block by signing using private keys - else: - signature_block = generate_signature_block_using_private_key( - args.keyfile, contents - ) - - if signature_block is None or len(signature_block) == 0: - raise esptool.FatalError("Signature Block generation failed") - - signature_sector += signature_block - - if ( - len(signature_sector) < 0 - and len(signature_sector) > SIG_BLOCK_SIZE * 3 - and len(signature_sector) % SIG_BLOCK_SIZE != 0 - ): - raise esptool.FatalError("Incorrect signature sector generation") - - total_sig_blocks = len(signature_sector) // SIG_BLOCK_SIZE - - # Pad signature_sector to sector - signature_sector = signature_sector + ( - b"\xff" * (SECTOR_SIZE - len(signature_sector)) - ) - if len(signature_sector) != SECTOR_SIZE: - raise esptool.FatalError("Incorrect signature sector size") - - # Write to output file, or append to existing file - if args.output is None: - args.datafile.close() - args.output = args.datafile.name - with open(args.output, "wb") as f: - f.write(contents + signature_sector) - print( - f"Signed {len(contents)} bytes of data from {args.datafile.name}. " - f"Signature sector now has {total_sig_blocks} signature blocks." - ) - - -def generate_signature_using_hsm(config, contents): - import espsecure.esp_hsm_sign as hsm - - session = hsm.establish_session(config) - # get the private key - private_key = hsm.get_privkey_info(session, config) - # Sign payload - signature = hsm.sign_payload(private_key, contents) - hsm.close_connection(session) - temp_signature_file = tempfile.TemporaryFile() - temp_signature_file.write(signature) - temp_signature_file.seek(0) - return [temp_signature_file] - - -def generate_signature_block_using_pre_calculated_signature( - signature, pub_key, contents -): - signature_blocks = b"" - for sig, pk in zip(signature, pub_key): - try: - public_key = _get_sbv2_pub_key(pk) - signature = sig.read() - if isinstance(public_key, rsa.RSAPublicKey): - # Calculate digest of data file - digest = _sha256_digest(contents) - # RSA signature - rsa_primitives = _get_sbv2_rsa_primitives(public_key) - # Verify the signature - public_key.verify( - signature, - digest, - padding.PSS(mgf=padding.MGF1(hashes.SHA256()), salt_length=32), - utils.Prehashed(hashes.SHA256()), - ) - - signature_block = generate_rsa_signature_block( - digest, rsa_primitives, signature - ) - else: - # ECDSA signature - numbers = public_key.public_numbers() - if isinstance(numbers.curve, ec.SECP192R1): - curve_len = 192 - curve_id = CURVE_ID_P192 - hash_type = hashes.SHA256() - digest = _sha256_digest(contents) - elif isinstance(numbers.curve, ec.SECP256R1): - curve_len = 256 - curve_id = CURVE_ID_P256 - hash_type = hashes.SHA256() - digest = _sha256_digest(contents) - elif isinstance(numbers.curve, ec.SECP384R1): - curve_len = 384 - curve_id = CURVE_ID_P384 - hash_type = hashes.SHA384() - digest = _sha384_digest(contents) - else: - raise esptool.FatalError("Invalid ECDSA curve instance.") - - # Verify the signature - public_key.verify( - signature, digest, ec.ECDSA(utils.Prehashed(hash_type)) - ) - - pubkey_point = _microecc_format(numbers.x, numbers.y, curve_len) - r, s = utils.decode_dss_signature(signature) - signature_rs = _microecc_format(r, s, curve_len) - signature_block = generate_ecdsa_signature_block( - digest, curve_id, pubkey_point, signature_rs - ) - except exceptions.InvalidSignature: - raise esptool.FatalError( - "Signature verification failed: Invalid Signature\n" - "The pre-calculated signature has not been signed " - "using the given public key" - ) - signature_block += struct.pack("> 5 - key ^= ((mul1 * addr) | ((mul2 * addr) & mul2_mask)) & tweak_range - return int.to_bytes(key, length=32, byteorder="big", signed=False) - - -def generate_flash_encryption_key(args): - print("Writing %d random bits to key file %s" % (args.keylen, args.key_file.name)) - args.key_file.write(os.urandom(args.keylen // 8)) - - -def _flash_encryption_operation_esp32( - output_file, input_file, flash_address, keyfile, flash_crypt_conf, do_decrypt -): - key = _load_hardware_key(keyfile) - - if flash_address % 16 != 0: - raise esptool.FatalError( - "Starting flash address 0x%x must be a multiple of 16" % flash_address - ) - - if flash_crypt_conf == 0: - print("WARNING: Setting FLASH_CRYPT_CONF to zero is not recommended") - - tweak_range = _flash_encryption_tweak_range_bits(flash_crypt_conf) - key = int.from_bytes(key, byteorder="big", signed=False) - - backend = default_backend() - - cipher = None - block_offs = flash_address - while True: - block = input_file.read(16) - if len(block) == 0: - break - elif len(block) < 16: - if do_decrypt: - raise esptool.FatalError("Data length is not a multiple of 16 bytes") - pad = 16 - len(block) - block = block + os.urandom(pad) - print( - "Note: Padding with %d bytes of random data " - "(encrypted data must be multiple of 16 bytes long)" % pad - ) - - if block_offs % 32 == 0 or cipher is None: - # each bit of the flash encryption key is XORed with tweak bits - # derived from the offset of 32 byte block of flash - block_key = _flash_encryption_tweak_key(key, block_offs, tweak_range) - - if cipher is None: # first pass - cipher = Cipher(algorithms.AES(block_key), modes.ECB(), backend=backend) - - # note AES is used inverted for flash encryption, so - # "decrypting" flash uses AES encrypt algorithm and vice - # versa. (This does not weaken AES.) - actor = cipher.encryptor() if do_decrypt else cipher.decryptor() - else: - # performance hack: changing the key using pyca-cryptography API - # requires recreating'actor'. - # With openssl backend, this re-initializes the openssl cipher context. - # To save some time, manually call EVP_CipherInit_ex() in the openssl - # backend to update the key. - # If it fails, fall back to recreating the entire context via public API - try: - backend = actor._ctx._backend - res = backend._lib.EVP_CipherInit_ex( - actor._ctx._ctx, - backend._ffi.NULL, - backend._ffi.NULL, - backend._ffi.from_buffer(block_key), - backend._ffi.NULL, - actor._ctx._operation, - ) - backend.openssl_assert(res != 0) - except AttributeError: - # backend is not an openssl backend, or implementation has changed: - # fall back to the slow safe version - cipher.algorithm.key = block_key - actor = cipher.encryptor() if do_decrypt else cipher.decryptor() - - block = block[::-1] # reverse input block byte order - block = actor.update(block) - - output_file.write(block[::-1]) # reverse output block byte order - block_offs += 16 - - -def _flash_encryption_operation_aes_xts( - output_file, input_file, flash_address, keyfile, do_decrypt -): - """ - Apply the AES-XTS algorithm with the hardware addressing scheme used by Espressif - - key = AES-XTS key (32 or 64 bytes) - flash_address = address in flash to encrypt at. Must be multiple of 16 bytes. - indata = Data to encrypt/decrypt. Must be multiple of 16 bytes. - encrypt = True to Encrypt indata, False to decrypt indata. - - Returns a bitstring of the ciphertext or plaintext result. - """ - - backend = default_backend() - key = _load_hardware_key(keyfile) - indata = input_file.read() - - if flash_address % 16 != 0: - raise esptool.FatalError( - "Starting flash address 0x%x must be a multiple of 16" % flash_address - ) - - if len(indata) % 16 != 0: - raise esptool.FatalError( - "Input data length (%d) must be a multiple of 16" % len(indata) - ) - - if len(indata) == 0: - raise esptool.FatalError("Input data must be longer than 0") - - # left pad for a 1024-bit aligned address - pad_left = flash_address % 0x80 - indata = (b"\x00" * pad_left) + indata - - # right pad for full 1024-bit blocks - pad_right = len(indata) % 0x80 - if pad_right > 0: - pad_right = 0x80 - pad_right - indata = indata + (b"\x00" * pad_right) - - inblocks = _split_blocks(indata, 0x80) # split into 1024 bit blocks - - output = [] - for inblock in inblocks: # for each block - tweak = struct.pack(" 0: - if not self.file_obj: - self.file_obj = open(self.path, "wb") - self.file_obj.write(payload) - - def close(self): - if self.file_obj: - self.file_obj.close() - self.file_obj = None - - @property - def name(self): - return self.path - - -def main(custom_commandline=None): - """ - Main function for espsecure - - custom_commandline - Optional override for default arguments parsing - (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']. - """ - parser = argparse.ArgumentParser( - description="espsecure.py v%s - ESP32 Secure Boot & Flash Encryption tool" - % esptool.__version__, - prog="espsecure", - ) - - subparsers = parser.add_subparsers( - dest="operation", help="Run espsecure.py {command} -h for additional help" - ) - - p = subparsers.add_parser( - "digest_secure_bootloader", - help="Take a bootloader binary image and a secure boot key, " - "and output a combined digest+binary suitable for flashing along " - "with the precalculated secure boot key.", - ) - p.add_argument( - "--keyfile", - "-k", - help="256 bit key for secure boot digest.", - type=argparse.FileType("rb"), - required=True, - ) - p.add_argument("--output", "-o", help="Output file for signed digest image.") - p.add_argument( - "--iv", - help="128 byte IV file. Supply a file for testing purposes only, " - "if not supplied an IV will be randomly generated.", - type=argparse.FileType("rb"), - ) - p.add_argument( - "image", - help="Bootloader image file to calculate digest from", - type=argparse.FileType("rb"), - ) - - p = subparsers.add_parser( - "generate_signing_key", - help="Generate a private key for signing secure boot images " - "as per the secure boot version. " - "Key file is generated in PEM format, " - "Secure Boot V1 - ECDSA NIST256p private key. " - "Secure Boot V2 - RSA 3072, ECDSA NIST384p, ECDSA NIST256p, ECDSA NIST192p private key.", - ) - p.add_argument( - "--version", - "-v", - help="Version of the secure boot signing scheme to use.", - choices=["1", "2"], - default="1", - ) - p.add_argument( - "--scheme", - "-s", - help="Scheme of secure boot signing.", - choices=["rsa3072", "ecdsa192", "ecdsa256", "ecdsa384"], - required=False, - ) - p.add_argument( - "keyfile", help="Filename for private key file (embedded public key)" - ) - - p = subparsers.add_parser( - "sign_data", - help="Sign a data file for use with secure boot. " - "Signing algorithm is deterministic ECDSA w/ SHA-512 (V1) " - "or either RSA-PSS or ECDSA w/ SHA-256 or ECDSA w/ SHA-384 (V2).", - ) - p.add_argument( - "--version", - "-v", - help="Version of the secure boot signing scheme to use.", - choices=["1", "2"], - required=True, - ) - p.add_argument( - "--keyfile", - "-k", - help="Private key file for signing. Key is in PEM format.", - type=argparse.FileType("rb"), - nargs="+", - ) - p.add_argument( - "--append_signatures", - "-a", - help="Append signature block(s) to already signed image. " - "Not valid for ESP32 and ESP32-C2.", - action="store_true", - ) - p.add_argument( - "--hsm", - help="Use an external Hardware Security Module " - "to generate signature using PKCS#11 interface.", - action="store_true", - ) - p.add_argument( - "--hsm-config", - help="Config file for the external Hardware Security Module " - "to be used to generate signature.", - default=None, - ) - p.add_argument( - "--pub-key", - help="Public key files corresponding to the private key used to generate " - "the pre-calculated signatures. Keys should be in PEM format.", - type=argparse.FileType("rb"), - nargs="+", - ) - p.add_argument( - "--signature", - help="Pre-calculated signatures. " - "Signatures generated using external private keys e.g. keys stored in HSM.", - type=argparse.FileType("rb"), - nargs="+", - default=None, - ) - p.add_argument( - "--output", - "-o", - help="Output file for signed digest image. Default is to sign the input file.", - ) - p.add_argument( - "datafile", - help="File to sign. For version 1, this can be any file. " - "For version 2, this must be a valid app image.", - type=argparse.FileType("rb"), - ) - - p = subparsers.add_parser( - "verify_signature", - help='Verify a data file previously signed by "sign_data", ' - "using the public key.", - ) - p.add_argument( - "--version", - "-v", - help="Version of the secure boot scheme to use.", - choices=["1", "2"], - required=True, - ) - p.add_argument( - "--hsm", - help="Use an external Hardware Security Module " - "to verify signature using PKCS#11 interface.", - action="store_true", - ) - p.add_argument( - "--hsm-config", - help="Config file for the external Hardware Security Module " - "to be used to verify signature.", - default=None, - ) - p.add_argument( - "--keyfile", - "-k", - help="Public key file for verification. " - "Can be private or public key in PEM format.", - type=argparse.FileType("rb"), - ) - p.add_argument( - "datafile", - help="Signed data file to verify signature.", - type=argparse.FileType("rb"), - ) - - p = subparsers.add_parser( - "extract_public_key", - help="Extract the public verification key for signatures, " - "save it as a raw binary file.", - ) - p.add_argument( - "--version", - "-v", - help="Version of the secure boot signing scheme to use.", - choices=["1", "2"], - default="1", - ) - p.add_argument( - "--keyfile", - "-k", - help="Private key file (PEM format) to extract the " - "public verification key from.", - type=argparse.FileType("rb"), - required=True, - ) - p.add_argument( - "public_keyfile", help="File to save new public key into", type=OutFileType() - ) - - # Kept for compatibility purpose. We can deprecate this in a future release - p = subparsers.add_parser( - "digest_rsa_public_key", - help="Generate an SHA-256 digest of the RSA public key. " - "This digest is burned into the eFuse and asserts the legitimacy " - "of the public key for Secure boot v2.", - ) - p.add_argument( - "--keyfile", - "-k", - help="Public key file for verification. " - "Can be private or public key in PEM format.", - type=argparse.FileType("rb"), - required=True, - ) - p.add_argument("--output", "-o", help="Output file for the digest.", required=True) - - p = subparsers.add_parser( - "digest_sbv2_public_key", - help="Generate an SHA-256 digest of the public key. " - "This digest is burned into the eFuse and asserts the legitimacy " - "of the public key for Secure boot v2.", - ) - p.add_argument( - "--keyfile", - "-k", - help="Public key file for verification. " - "Can be private or public key in PEM format.", - type=argparse.FileType("rb"), - required=True, - ) - p.add_argument("--output", "-o", help="Output file for the digest.", required=True) - - p = subparsers.add_parser( - "signature_info_v2", - help="Reads the signature block and provides the signature block information.", - ) - p.add_argument( - "datafile", - help="Secure boot v2 signed data file.", - type=argparse.FileType("rb"), - ) - - 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 (only secure boot v1) " - "or flash encryption key.", - ) - p.add_argument( - "--keyfile", - "-k", - help="Private key file (PEM format) to generate a digest from.", - type=argparse.FileType("rb"), - required=True, - ) - p.add_argument( - "--keylen", - "-l", - help="Length of private key digest file to generate (in bits). " - "3/4 Coding Scheme requires 192 bit key.", - choices=[192, 256], - default=256, - type=int, - ) - p.add_argument( - "digest_file", help="File to write 32 byte digest into", type=OutFileType() - ) - - p = subparsers.add_parser( - "generate_flash_encryption_key", - help="Generate a development-use flash encryption key with random data.", - ) - p.add_argument( - "--keylen", - "-l", - help="Length of private key digest file to generate (in bits). " - "3/4 Coding Scheme requires 192 bit key.", - choices=[128, 192, 256, 512], - default=256, - type=int, - ) - p.add_argument( - "key_file", - help="File to write 16, 24, 32 or 64 byte key into", - type=OutFileType(), - ) - - p = subparsers.add_parser( - "decrypt_flash_data", - help="Decrypt some data read from encrypted flash (using known key)", - ) - p.add_argument( - "encrypted_file", - help="File with encrypted flash contents", - type=argparse.FileType("rb"), - ) - p.add_argument( - "--aes_xts", - "-x", - help="Decrypt data using AES-XTS as used on " - "ESP32-S2, ESP32-C2, ESP32-C3, ESP32-C6, ESP32-C5, ESP32-C61 and ESP32-P4", - action="store_true", - ) - p.add_argument( - "--keyfile", - "-k", - help="File with flash encryption key", - type=argparse.FileType("rb"), - required=True, - ) - p.add_argument( - "--output", - "-o", - help="Output file for plaintext data.", - type=OutFileType(), - required=True, - ) - p.add_argument( - "--address", - "-a", - help="Address offset in flash that file was read from.", - required=True, - type=esptool.arg_auto_int, - ) - p.add_argument( - "--flash_crypt_conf", - help="Override FLASH_CRYPT_CONF efuse value (default is 0XF).", - required=False, - default=0xF, - type=esptool.arg_auto_int, - ) - - p = subparsers.add_parser( - "encrypt_flash_data", - help="Encrypt some data suitable for encrypted flash (using known key)", - ) - p.add_argument( - "--aes_xts", - "-x", - help="Encrypt data using AES-XTS as used on " - "ESP32-S2, ESP32-C2, ESP32-C3, ESP32-C6, ESP32-C5, ESP32-C61 and ESP32-P4", - action="store_true", - ) - p.add_argument( - "--keyfile", - "-k", - help="File with flash encryption key", - type=argparse.FileType("rb"), - required=True, - ) - p.add_argument( - "--output", - "-o", - help="Output file for encrypted data.", - type=OutFileType(), - required=True, - ) - p.add_argument( - "--address", - "-a", - help="Address offset in flash where file will be flashed.", - required=True, - type=esptool.arg_auto_int, - ) - p.add_argument( - "--flash_crypt_conf", - help="Override FLASH_CRYPT_CONF efuse value (default is 0XF).", - required=False, - default=0xF, - type=esptool.arg_auto_int, - ) - p.add_argument( - "plaintext_file", - help="File with plaintext content for encrypting", - type=argparse.FileType("rb"), - ) - - # Enable argcomplete only on Unix-like systems - if sys.platform != "win32": - try: - import argcomplete - - argcomplete.autocomplete(parser) - except ImportError: - pass - - args = parser.parse_args(custom_commandline) - print("espsecure.py v%s" % esptool.__version__) - if args.operation is None: - parser.print_help() - parser.exit(1) - - try: - # each 'operation' is a module-level function of the same name - operation_func = globals()[args.operation] - operation_func(args) - finally: - for arg_name in vars(args): - obj = getattr(args, arg_name) - if isinstance(obj, (OutFileType, IOBase)): - obj.close() - elif isinstance(obj, list): - for f in [o for o in obj if isinstance(o, IOBase)]: - f.close() - - -def _main(): - try: - 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__": - _main() diff --git a/tools/esptool_py/espsecure/__main__.py b/tools/esptool_py/espsecure/__main__.py deleted file mode 100644 index 00f62cab9e..0000000000 --- a/tools/esptool_py/espsecure/__main__.py +++ /dev/null @@ -1,8 +0,0 @@ -# SPDX-FileCopyrightText: 2016-2022 Espressif Systems (Shanghai) CO LTD -# -# SPDX-License-Identifier: GPL-2.0-or-later - -import espsecure - -if __name__ == "__main__": - espsecure._main() diff --git a/tools/esptool_py/espsecure/esp_hsm_sign/__init__.py b/tools/esptool_py/espsecure/esp_hsm_sign/__init__.py deleted file mode 100644 index d255116adf..0000000000 --- a/tools/esptool_py/espsecure/esp_hsm_sign/__init__.py +++ /dev/null @@ -1,180 +0,0 @@ -# SPDX-FileCopyrightText: 2023 Espressif Systems (Shanghai) CO LTD -# -# SPDX-License-Identifier: GPL-2.0-or-later - -import binascii -import configparser -import os -import sys -from getpass import getpass - -try: - import pkcs11 - from .exceptions import handle_exceptions -except ImportError: - raise ImportError( - "python-pkcs11 package is not installed. " - "Please install it using the required packages with command: " - "pip install 'esptool[hsm]'" - ) - -import cryptography.hazmat.primitives.asymmetric.ec as EC -import cryptography.hazmat.primitives.asymmetric.rsa as RSA - -import ecdsa - - -def read_hsm_config(configfile): - config = configparser.ConfigParser() - config.read(configfile) - - section = "hsm_config" - if not config.has_section(section): - raise configparser.NoSectionError(section) - - 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] - - -def establish_session(config): - print("Trying to establish a session with the HSM.") - try: - if os.path.exists(config["pkcs11_lib"]): - lib = pkcs11.lib(config["pkcs11_lib"]) - else: - print(f'LIB file does not exist at {config["pkcs11_lib"]}') - sys.exit(1) - for slot in lib.get_slots(token_present=True): - if slot.slot_id == int(config["slot"]): - break - - token = slot.get_token() - session = token.open(rw=True, user_pin=config["credentials"]) - print(f'Session creation successful with HSM slot {int(config["slot"])}.') - return session - - except pkcs11.exceptions.PKCS11Error as e: - handle_exceptions(e) - print("Session establishment failed") - sys.exit(1) - - -def get_privkey_info(session, config): - try: - private_key = session.get_key( - object_class=pkcs11.constants.ObjectClass.PRIVATE_KEY, label=config["label"] - ) - print(f'Got private key metadata with label {config["label"]}.') - return private_key - - except pkcs11.exceptions.PKCS11Error as e: - handle_exceptions(e) - print("Failed to get the private key") - sys.exit(1) - - -def get_pubkey(session, config): - print("Trying to extract public key from the HSM.") - try: - if "label_pubkey" in config: - public_key_label = config["label_pubkey"] - else: - print( - "Config option 'label_pubkey' not found, " - "using config option 'label' for public key." - ) - public_key_label = config["label"] - - public_key = session.get_key( - object_class=pkcs11.constants.ObjectClass.PUBLIC_KEY, - label=public_key_label, - ) - if public_key.key_type == pkcs11.mechanisms.KeyType.RSA: - exponent = public_key[pkcs11.Attribute.PUBLIC_EXPONENT] - modulus = public_key[pkcs11.Attribute.MODULUS] - e = int.from_bytes(exponent, byteorder="big") - n = int.from_bytes(modulus, byteorder="big") - public_key = RSA.RSAPublicNumbers(e, n).public_key() - - elif public_key.key_type == pkcs11.mechanisms.KeyType.EC: - ecpoints, _ = ecdsa.der.remove_octet_string( - public_key[pkcs11.Attribute.EC_POINT] - ) - public_key = EC.EllipticCurvePublicKey.from_encoded_point( - EC.SECP256R1(), ecpoints - ) - - else: - print("Incorrect public key algorithm") - sys.exit(1) - - print(f"Got public key with label {public_key_label}.") - return public_key - - except pkcs11.exceptions.PKCS11Error as e: - handle_exceptions(e) - print("Failed to extract the public key") - sys.exit(1) - - -def sign_payload(private_key, payload): - try: - print("Signing payload using the HSM.") - key_type = private_key.key_type - mechanism, mechanism_params = get_mechanism(key_type) - signature = private_key.sign( - data=payload, mechanism=mechanism, mechanism_param=mechanism_params - ) - - if len(signature) != 0: - print("Signature generation successful.") - - if key_type == pkcs11.mechanisms.KeyType.EC: - r = int(binascii.hexlify(signature[:32]), 16) - s = int(binascii.hexlify(signature[32:]), 16) - - # der encoding in case of ecdsa signatures - signature = ecdsa.der.encode_sequence( - ecdsa.der.encode_integer(r), ecdsa.der.encode_integer(s) - ) - - return signature - - except pkcs11.exceptions.PKCS11Error as e: - handle_exceptions(e, mechanism) - print("Payload Signing Failed") - sys.exit(1) - - -def get_mechanism(key_type): - if key_type == pkcs11.mechanisms.KeyType.RSA: - return pkcs11.mechanisms.Mechanism.SHA256_RSA_PKCS_PSS, ( - pkcs11.mechanisms.Mechanism.SHA256, - pkcs11.MGF.SHA256, - 32, - ) - elif key_type == pkcs11.mechanisms.KeyType.EC: - return pkcs11.mechanisms.Mechanism.ECDSA_SHA256, None - else: - print("Invalid signing key mechanism") - sys.exit(1) - - -def close_connection(session): - try: - session.close() - print("Connection closed successfully") - except pkcs11.exceptions.PKCS11Error as e: - handle_exceptions(e) - print("Failed to close the HSM session") - sys.exit(1) diff --git a/tools/esptool_py/espsecure/esp_hsm_sign/exceptions.py b/tools/esptool_py/espsecure/esp_hsm_sign/exceptions.py deleted file mode 100644 index 47ba8e3b03..0000000000 --- a/tools/esptool_py/espsecure/esp_hsm_sign/exceptions.py +++ /dev/null @@ -1,50 +0,0 @@ -# SPDX-FileCopyrightText: 2023 Espressif Systems (Shanghai) CO LTD -# -# SPDX-License-Identifier: GPL-2.0-or-later - -from pkcs11.exceptions import ( - AlreadyInitialized, - AnotherUserAlreadyLoggedIn, - ArgumentsBad, - DeviceRemoved, - DomainParamsInvalid, - FunctionFailed, - MechanismInvalid, - NoSuchKey, - NoSuchToken, - OperationNotInitialized, - SessionClosed, -) - - -def handle_exceptions(e, info=""): - exception_type = e.__class__ - if exception_type == MechanismInvalid: - print("The External HSM does not support the given mechanism", info) - elif exception_type == FunctionFailed: - print( - "Please ensure proper configuration, privileges and environment variables" - ) - elif exception_type == AlreadyInitialized: - print("pkcs11 is already initialized with another library") - elif exception_type == AnotherUserAlreadyLoggedIn: - print("Another User has been already logged in") - elif exception_type == ArgumentsBad: - print("Please check the arguments supplied to the function") - elif exception_type == DomainParamsInvalid: - print("Invalid or unsupported domain parameters were supplied to the function") - elif exception_type == DeviceRemoved: - print( - "The token has been removed from its slot during " - "the execution of the function" - ) - elif exception_type == NoSuchToken: - print("No such token found") - elif exception_type == NoSuchKey: - print("No such key found") - elif exception_type == OperationNotInitialized: - print("Operation not Initialized") - elif exception_type == SessionClosed: - print("Session already closed") - else: - print(e.__class__, info) diff --git a/tools/esptool_py/esptool.py b/tools/esptool_py/esptool.py deleted file mode 100755 index ee3fdc90f7..0000000000 --- a/tools/esptool_py/esptool.py +++ /dev/null @@ -1,37 +0,0 @@ -#!/usr/bin/env python -# -# SPDX-FileCopyrightText: 2014-2022 Fredrik Ahlberg, Angus Gratton, -# Espressif Systems (Shanghai) CO LTD, other contributors as noted. -# -# SPDX-License-Identifier: GPL-2.0-or-later - -# This executable script is a thin wrapper around the main functionality -# in the esptool Python package - -# When updating this script, please also update espefuse.py and espsecure.py - -import contextlib -import os -import sys - -if os.name != "nt": - # 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): - 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 - # other Python scripts - with contextlib.suppress(KeyError): - del sys.modules["esptool"] - -import esptool - -if __name__ == "__main__": - esptool._main() diff --git a/tools/esptool_py/esptool/__init__.py b/tools/esptool_py/esptool/__init__.py deleted file mode 100644 index 7f919bc3f4..0000000000 --- a/tools/esptool_py/esptool/__init__.py +++ /dev/null @@ -1,1337 +0,0 @@ -# SPDX-FileCopyrightText: 2014-2022 Fredrik Ahlberg, Angus Gratton, -# Espressif Systems (Shanghai) CO LTD, other contributors as noted. -# -# SPDX-License-Identifier: GPL-2.0-or-later -# PYTHON_ARGCOMPLETE_OK -__all__ = [ - "chip_id", - "detect_chip", - "dump_mem", - "elf2image", - "erase_flash", - "erase_region", - "flash_id", - "get_security_info", - "image_info", - "load_ram", - "make_image", - "merge_bin", - "read_flash", - "read_flash_status", - "read_mac", - "read_mem", - "run", - "verify_flash", - "version", - "write_flash", - "write_flash_status", - "write_mem", -] - -__version__ = "4.8.1" - -import argparse -import inspect -import os -import shlex -import sys -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, - dump_mem, - elf2image, - erase_flash, - erase_region, - flash_id, - read_flash_sfdp, - get_security_info, - image_info, - load_ram, - make_image, - merge_bin, - read_flash, - read_flash_status, - read_mac, - read_mem, - run, - verify_flash, - version, - write_flash, - write_flash_status, - write_mem, -) -from esptool.config import load_config_file -from esptool.loader import ( - DEFAULT_CONNECT_ATTEMPTS, - DEFAULT_OPEN_PORT_ATTEMPTS, - StubFlasher, - ESPLoader, - list_ports, -) -from esptool.targets import CHIP_DEFS, CHIP_LIST, ESP32ROM -from esptool.util import ( - FatalError, - NotImplementedInROMError, - flash_size_bytes, - strip_chip_name, -) -from itertools import chain, cycle, repeat - -import serial - - -def main(argv=None, esp=None): - """ - Main function for esptool - - argv - Optional override for default arguments parsing (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. "-b 115200" thus becomes ['-b', '115200']. - - esp - Optional override of the connected device previously - returned by get_default_connected_device() - """ - - external_esp = esp is not None - - parser = argparse.ArgumentParser( - description="esptool.py v%s - Espressif chips ROM Bootloader Utility" - % __version__, - prog="esptool", - ) - - parser.add_argument( - "--chip", - "-c", - help="Target chip type", - type=strip_chip_name, - choices=["auto"] + CHIP_LIST, - default=os.environ.get("ESPTOOL_CHIP", "auto"), - ) - - parser.add_argument( - "--port", - "-p", - help="Serial port device", - default=os.environ.get("ESPTOOL_PORT", None), - ) - - parser.add_argument( - "--baud", - "-b", - help="Serial port baud rate used when flashing/reading", - type=arg_auto_int, - default=os.environ.get("ESPTOOL_BAUD", ESPLoader.ESP_ROM_BAUD), - ) - - parser.add_argument( - "--port-filter", - action="append", - help="Serial port device filter, can be vid=NUMBER, pid=NUMBER, name=SUBSTRING", - type=str, - default=[], - ) - - parser.add_argument( - "--before", - help="What to do before connecting to the chip", - choices=["default_reset", "usb_reset", "no_reset", "no_reset_no_sync"], - default=os.environ.get("ESPTOOL_BEFORE", "default_reset"), - ) - - parser.add_argument( - "--after", - "-a", - help="What to do after esptool.py is finished", - choices=["hard_reset", "soft_reset", "no_reset", "no_reset_stub"], - default=os.environ.get("ESPTOOL_AFTER", "hard_reset"), - ) - - parser.add_argument( - "--no-stub", - help="Disable launching the flasher stub, only talk to ROM bootloader. " - "Some features will not be available.", - action="store_true", - ) - - # --stub-version can be set with --no-stub so the tests wouldn't fail if this option is implied globally - parser.add_argument( - "--stub-version", - default=os.environ.get("ESPTOOL_STUB_VERSION", StubFlasher.STUB_SUBDIRS[0]), - choices=StubFlasher.STUB_SUBDIRS, - # not a public option and is not subject to the semantic versioning policy - help=argparse.SUPPRESS, - ) - - parser.add_argument( - "--trace", - "-t", - help="Enable trace-level output of esptool.py interactions.", - action="store_true", - ) - - parser.add_argument( - "--override-vddsdio", - help="Override ESP32 VDDSDIO internal voltage regulator (use with care)", - choices=ESP32ROM.OVERRIDE_VDDSDIO_CHOICES, - nargs="?", - ) - - parser.add_argument( - "--connect-attempts", - help=( - "Number of attempts to connect, negative or 0 for infinite. " - "Default: %d." % DEFAULT_CONNECT_ATTEMPTS - ), - type=int, - default=os.environ.get("ESPTOOL_CONNECT_ATTEMPTS", DEFAULT_CONNECT_ATTEMPTS), - ) - - subparsers = parser.add_subparsers( - dest="operation", help="Run esptool.py {command} -h for additional help" - ) - - def add_spi_connection_arg(parent): - parent.add_argument( - "--spi-connection", - "-sc", - help="Override default SPI Flash connection. " - "Value can be SPI, HSPI or a comma-separated list of 5 I/O numbers " - "to use for SPI flash (CLK,Q,D,HD,CS). Not supported with ESP8266.", - action=SpiConnectionAction, - ) - - 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", action=AutoHex2BinAction - ) - - parser_dump_mem = subparsers.add_parser( - "dump_mem", help="Dump arbitrary memory to disk" - ) - parser_dump_mem.add_argument("address", help="Base address", type=arg_auto_int) - parser_dump_mem.add_argument( - "size", help="Size of region to dump", type=arg_auto_int - ) - parser_dump_mem.add_argument("filename", help="Name of binary dump") - - parser_read_mem = subparsers.add_parser( - "read_mem", help="Read arbitrary memory location" - ) - parser_read_mem.add_argument("address", help="Address to read", type=arg_auto_int) - - parser_write_mem = subparsers.add_parser( - "write_mem", help="Read-modify-write to arbitrary memory location" - ) - parser_write_mem.add_argument("address", help="Address to write", type=arg_auto_int) - parser_write_mem.add_argument("value", help="Value", type=arg_auto_int) - parser_write_mem.add_argument( - "mask", - help="Mask of bits to write", - type=arg_auto_int, - nargs="?", - default="0xFFFFFFFF", - ) - - def add_spi_flash_subparsers( - parent: argparse.ArgumentParser, - allow_keep: bool, - auto_detect: bool, - size_only: bool = False, - ): - """Add common parser arguments for SPI flash properties""" - extra_keep_args = ["keep"] if allow_keep else [] - - if auto_detect and allow_keep: - extra_fs_message = ", detect, or keep" - flash_sizes = ["detect", "keep"] - elif auto_detect: - extra_fs_message = ", or detect" - flash_sizes = ["detect"] - elif allow_keep: - extra_fs_message = ", or keep" - flash_sizes = ["keep"] - else: - extra_fs_message = "" - flash_sizes = [] - - if not size_only: - parent.add_argument( - "--flash_freq", - "-ff", - help="SPI Flash frequency", - choices=extra_keep_args - + [ - "80m", - "60m", - "48m", - "40m", - "30m", - "26m", - "24m", - "20m", - "16m", - "15m", - "12m", - ], - default=os.environ.get("ESPTOOL_FF", "keep" if allow_keep else None), - ) - parent.add_argument( - "--flash_mode", - "-fm", - help="SPI Flash mode", - choices=extra_keep_args + ["qio", "qout", "dio", "dout"], - default=os.environ.get("ESPTOOL_FM", "keep" if allow_keep else "qio"), - ) - - parent.add_argument( - "--flash_size", - "-fs", - help="SPI Flash size in MegaBytes " - "(1MB, 2MB, 4MB, 8MB, 16MB, 32MB, 64MB, 128MB) " - "plus ESP8266-only (256KB, 512KB, 2MB-c1, 4MB-c1)" + extra_fs_message, - choices=flash_sizes - + [ - "256KB", - "512KB", - "1MB", - "2MB", - "2MB-c1", - "4MB", - "4MB-c1", - "8MB", - "16MB", - "32MB", - "64MB", - "128MB", - ], - default=os.environ.get("ESPTOOL_FS", "keep" if allow_keep else "1MB"), - ) - add_spi_connection_arg(parent) - - parser_write_flash = subparsers.add_parser( - "write_flash", help="Write a binary blob to flash" - ) - - parser_write_flash.add_argument( - "addr_filename", - metavar="
", - help="Address followed by binary filename, separated by space", - action=AddrFilenamePairAction, - ) - parser_write_flash.add_argument( - "--erase-all", - "-e", - help="Erase all regions of flash (not just write areas) before programming", - action="store_true", - ) - - add_spi_flash_subparsers(parser_write_flash, allow_keep=True, auto_detect=True) - parser_write_flash.add_argument( - "--no-progress", "-p", help="Suppress progress output", action="store_true" - ) - parser_write_flash.add_argument( - "--verify", - help="Verify just-written data on flash " - "(mostly superfluous, data is read back during flashing)", - action="store_true", - ) - parser_write_flash.add_argument( - "--encrypt", - help="Apply flash encryption when writing data " - "(required correct efuse settings)", - action="store_true", - ) - # In order to not break backward compatibility, - # our list of encrypted files to flash is a new parameter - parser_write_flash.add_argument( - "--encrypt-files", - metavar="
", - help="Files to be encrypted on the flash. " - "Address followed by binary filename, separated by space.", - action=AddrFilenamePairAction, - ) - parser_write_flash.add_argument( - "--ignore-flash-encryption-efuse-setting", - help="Ignore flash encryption efuse settings ", - action="store_true", - ) - parser_write_flash.add_argument( - "--force", - help="Force write, skip security and compatibility checks. Use with caution!", - action="store_true", - ) - - compress_args = parser_write_flash.add_mutually_exclusive_group(required=False) - compress_args.add_argument( - "--compress", - "-z", - help="Compress data in transfer (default unless --no-stub is specified)", - action="store_true", - default=None, - ) - compress_args.add_argument( - "--no-compress", - "-u", - help="Disable data compression during transfer " - "(default if --no-stub is specified)", - action="store_true", - ) - - subparsers.add_parser("run", help="Run application code in flash") - - parser_image_info = subparsers.add_parser( - "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( - "--version", - "-v", - help="Output format version (1 - legacy, 2 - extended)", - choices=["1", "2"], - default="1", - ) - - parser_make_image = subparsers.add_parser( - "make_image", help="Create an application image from binary files" - ) - parser_make_image.add_argument("output", help="Output image file") - parser_make_image.add_argument( - "--segfile", "-f", action="append", help="Segment input file" - ) - parser_make_image.add_argument( - "--segaddr", - "-a", - action="append", - help="Segment base address", - type=arg_auto_int, - ) - parser_make_image.add_argument( - "--entrypoint", - "-e", - help="Address of entry point", - type=arg_auto_int, - default=0, - ) - - parser_elf2image = subparsers.add_parser( - "elf2image", help="Create an application image from ELF file" - ) - parser_elf2image.add_argument("input", help="Input ELF file") - parser_elf2image.add_argument( - "--output", - "-o", - help="Output filename prefix (for version 1 image), " - "or filename (for version 2 single image)", - type=str, - ) - parser_elf2image.add_argument( - "--version", - "-e", - help="Output image version", - choices=["1", "2", "3"], - default="1", - ) - parser_elf2image.add_argument( - # it kept for compatibility - # Minimum chip revision (deprecated, consider using --min-rev-full) - "--min-rev", - "-r", - help=argparse.SUPPRESS, - type=int, - choices=range(256), - metavar="{0, ... 255}", - default=0, - ) - parser_elf2image.add_argument( - "--min-rev-full", - help="Minimal chip revision (in format: major * 100 + minor)", - type=int, - choices=range(65536), - metavar="{0, ... 65535}", - default=0, - ) - parser_elf2image.add_argument( - "--max-rev-full", - help="Maximal chip revision (in format: major * 100 + minor)", - type=int, - choices=range(65536), - metavar="{0, ... 65535}", - default=65535, - ) - parser_elf2image.add_argument( - "--secure-pad", - action="store_true", - help="Pad image so once signed it will end on a 64KB boundary. " - "For Secure Boot v1 images only.", - ) - parser_elf2image.add_argument( - "--secure-pad-v2", - action="store_true", - help="Pad image to 64KB, so once signed its signature sector will" - "start at the next 64K block. For Secure Boot v2 images only.", - ) - parser_elf2image.add_argument( - "--elf-sha256-offset", - help="If set, insert SHA256 hash (32 bytes) of the input ELF file " - "at specified offset in the binary.", - type=arg_auto_int, - default=None, - ) - parser_elf2image.add_argument( - "--dont-append-digest", - dest="append_digest", - help="Don't append a SHA256 digest of the entire image after the checksum. " - "This argument is not supported and ignored for ESP8266.", - action="store_false", - default=True, - ) - parser_elf2image.add_argument( - "--use_segments", - help="If set, ELF segments will be used instead of ELF sections " - "to generate the image.", - action="store_true", - ) - parser_elf2image.add_argument( - "--flash-mmu-page-size", - help="Change flash MMU page size.", - choices=["64KB", "32KB", "16KB", "8KB"], - ) - parser_elf2image.add_argument( - "--pad-to-size", - help="The block size with which the final binary image after padding " - "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. Implies --dont-append-digest", - action="store_true", - default=None, - ) - - add_spi_flash_subparsers(parser_elf2image, allow_keep=False, auto_detect=False) - - subparsers.add_parser("read_mac", help="Read MAC address from OTP ROM") - - subparsers.add_parser("chip_id", help="Read Chip ID from OTP ROM") - - parser_flash_id = subparsers.add_parser( - "flash_id", help="Read SPI flash manufacturer and device ID" - ) - add_spi_connection_arg(parser_flash_id) - - parser_read_status = subparsers.add_parser( - "read_flash_status", help="Read SPI flash status register" - ) - - add_spi_connection_arg(parser_read_status) - parser_read_status.add_argument( - "--bytes", - help="Number of bytes to read (1-3)", - type=int, - choices=[1, 2, 3], - default=2, - ) - - parser_write_status = subparsers.add_parser( - "write_flash_status", help="Write SPI flash status register" - ) - - add_spi_connection_arg(parser_write_status) - parser_write_status.add_argument( - "--non-volatile", - help="Write non-volatile bits (use with caution)", - action="store_true", - ) - parser_write_status.add_argument( - "--bytes", - help="Number of status bytes to write (1-3)", - type=int, - choices=[1, 2, 3], - default=2, - ) - parser_write_status.add_argument("value", help="New value", type=arg_auto_int) - - parser_read_flash = subparsers.add_parser( - "read_flash", help="Read SPI flash content" - ) - add_spi_flash_subparsers( - parser_read_flash, allow_keep=True, auto_detect=True, size_only=True - ) - 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. 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( - "--no-progress", "-p", help="Suppress progress output", action="store_true" - ) - - parser_verify_flash = subparsers.add_parser( - "verify_flash", help="Verify a binary blob against flash" - ) - parser_verify_flash.add_argument( - "addr_filename", - help="Address and binary file to verify there, separated by space", - action=AddrFilenamePairAction, - ) - parser_verify_flash.add_argument( - "--diff", "-d", help="Show differences", choices=["no", "yes"], default="no" - ) - add_spi_flash_subparsers(parser_verify_flash, allow_keep=True, auto_detect=True) - - parser_erase_flash = subparsers.add_parser( - "erase_flash", help="Perform Chip Erase on SPI flash" - ) - parser_erase_flash.add_argument( - "--force", - help="Erase flash even if security features are enabled. Use with caution!", - action="store_true", - ) - add_spi_connection_arg(parser_erase_flash) - - parser_erase_region = subparsers.add_parser( - "erase_region", help="Erase a region of the flash" - ) - parser_erase_region.add_argument( - "--force", - help="Erase region even if security features are enabled. Use with caution!", - action="store_true", - ) - add_spi_connection_arg(parser_erase_region) - parser_erase_region.add_argument( - "address", help="Start address (must be multiple of 4096)", type=arg_auto_int - ) - parser_erase_region.add_argument( - "size", - 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_read_flash_sfdp = subparsers.add_parser( - "read_flash_sfdp", - help="Read SPI flash SFDP (Serial Flash Discoverable Parameters)", - ) - add_spi_flash_subparsers(parser_read_flash_sfdp, allow_keep=True, auto_detect=True) - parser_read_flash_sfdp.add_argument("addr", type=arg_auto_int) - parser_read_flash_sfdp.add_argument("bytes", type=int) - - parser_merge_bin = subparsers.add_parser( - "merge_bin", - help="Merge multiple raw binary files into a single file for later flashing", - ) - - parser_merge_bin.add_argument( - "--output", "-o", help="Output filename", type=str, required=True - ) - parser_merge_bin.add_argument( - "--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) - - 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, - ) - 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.", - choices=[ - "256KB", - "512KB", - "1MB", - "2MB", - "4MB", - "8MB", - "16MB", - "32MB", - "64MB", - "128MB", - ], - ) - parser_merge_bin.add_argument( - "addr_filename", - metavar="
", - help="Address followed by binary filename, separated by space", - action=AddrFilenamePairAction, - ) - - subparsers.add_parser("get_security_info", help="Get some security-related data") - - subparsers.add_parser("version", help="Print esptool version") - - # internal sanity check - every operation matches a module function of the same name - for operation in subparsers.choices.keys(): - assert operation in globals(), "%s should be a module function" % operation - - # Enable argcomplete only on Unix-like systems - if sys.platform != "win32": - try: - import argcomplete - - argcomplete.autocomplete(parser) - except ImportError: - pass - - argv = expand_file_arguments(argv or sys.argv[1:]) - - args = parser.parse_args(argv) - print("esptool.py v%s" % __version__) - load_config_file(verbose=True) - - StubFlasher.set_preferred_stub_subdir(args.stub_version) - - # Parse filter arguments into separate lists - args.filterVids = [] - args.filterPids = [] - args.filterNames = [] - for f in args.port_filter: - kvp = f.split("=") - if len(kvp) != 2: - raise FatalError("Option --port-filter argument must consist of key=value") - if kvp[0] == "vid": - args.filterVids.append(arg_auto_int(kvp[1])) - elif kvp[0] == "pid": - args.filterPids.append(arg_auto_int(kvp[1])) - elif kvp[0] == "name": - args.filterNames.append(kvp[1]) - else: - raise FatalError("Option --port-filter argument key not recognized") - - # operation function can take 1 arg (args), 2 args (esp, arg) - # or be a member function of the ESPLoader class. - - if args.operation is None: - parser.print_help() - sys.exit(1) - - # Forbid the usage of both --encrypt, which means encrypt all the given files, - # and --encrypt-files, which represents the list of files to encrypt. - # The reason is that allowing both at the same time increases the chances of - # having contradictory lists (e.g. one file not available in one of list). - if ( - args.operation == "write_flash" - and args.encrypt - and args.encrypt_files is not None - ): - raise FatalError( - "Options --encrypt and --encrypt-files " - "must not be specified at the same time." - ) - - operation_func = globals()[args.operation] - operation_args = inspect.getfullargspec(operation_func).args - - if ( - operation_args[0] == "esp" - ): # operation function takes an ESPLoader connection object - if args.before != "no_reset_no_sync": - initial_baud = min( - ESPLoader.ESP_ROM_BAUD, args.baud - ) # don't sync faster than the default baud rate - else: - initial_baud = args.baud - - if args.port is None: - ser_list = get_port_list(args.filterVids, args.filterPids, args.filterNames) - print("Found %d serial ports" % len(ser_list)) - else: - ser_list = [args.port] - open_port_attempts = os.environ.get( - "ESPTOOL_OPEN_PORT_ATTEMPTS", DEFAULT_OPEN_PORT_ATTEMPTS - ) - try: - open_port_attempts = int(open_port_attempts) - except ValueError: - raise SystemExit("Invalid value for ESPTOOL_OPEN_PORT_ATTEMPTS") - if open_port_attempts != 1: - if args.port is None or args.chip == "auto": - print( - "WARNING: The ESPTOOL_OPEN_PORT_ATTEMPTS (open_port_attempts) option can only be used with --port and --chip arguments." - ) - else: - esp = esp or connect_loop( - args.port, - initial_baud, - args.chip, - open_port_attempts, - args.trace, - args.before, - ) - esp = esp or get_default_connected_device( - ser_list, - port=args.port, - connect_attempts=args.connect_attempts, - initial_baud=initial_baud, - chip=args.chip, - trace=args.trace, - before=args.before, - ) - - if esp is None: - raise FatalError( - "Could not connect to an Espressif device " - "on any of the %d available serial ports." % len(ser_list) - ) - - if esp.secure_download_mode: - print("Chip is %s in Secure Download Mode" % esp.CHIP_NAME) - else: - print("Chip is %s" % (esp.get_chip_description())) - print("Features: %s" % ", ".join(esp.get_chip_features())) - print("Crystal is %dMHz" % esp.get_crystal_freq()) - read_mac(esp, args) - - if not args.no_stub: - if esp.secure_download_mode: - print( - "WARNING: Stub loader is not supported in Secure Download Mode, " - "setting --no-stub" - ) - args.no_stub = True - elif not esp.IS_STUB and esp.stub_is_disabled: - print( - "WARNING: Stub loader has been disabled for compatibility, " - "setting --no-stub" - ) - args.no_stub = True - else: - 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) - - if args.baud > initial_baud: - try: - esp.change_baud(args.baud) - except NotImplementedInROMError: - print( - "WARNING: ROM doesn't support changing baud rate. " - "Keeping initial baud rate %d" % initial_baud - ) - - def _define_spi_conn(spi_connection): - """Prepare SPI configuration string and value for flash_spi_attach()""" - clk, q, d, hd, cs = spi_connection - spi_config_txt = f"CLK:{clk}, Q:{q}, D:{d}, HD:{hd}, CS:{cs}" - value = (hd << 24) | (cs << 18) | (d << 12) | (q << 6) | clk - return spi_config_txt, value - - # Override the common SPI flash parameter stuff if configured to do so - if hasattr(args, "spi_connection") and args.spi_connection is not None: - spi_config = args.spi_connection - if args.spi_connection == "SPI": - value = 0 - elif args.spi_connection == "HSPI": - value = 1 - else: - esp.check_spi_connection(args.spi_connection) - # Encode the pin numbers as a 32-bit integer with packed 6-bit values, - # the same way the ESP ROM takes them - spi_config, value = _define_spi_conn(args.spi_connection) - print(f"Configuring SPI flash mode ({spi_config})...") - esp.flash_spi_attach(value) - elif args.no_stub: - if esp.CHIP_NAME != "ESP32" or esp.secure_download_mode: - print("Enabling default SPI flash mode...") - # ROM loader doesn't enable flash unless we explicitly do it - esp.flash_spi_attach(0) - else: - # ROM doesn't attach in-package flash chips - spi_chip_pads = esp.get_chip_spi_pads() - spi_config_txt, value = _define_spi_conn(spi_chip_pads) - if spi_chip_pads != (0, 0, 0, 0, 0): - print( - "Attaching flash from eFuses' SPI pads configuration" - f"({spi_config_txt})..." - ) - else: - print("Enabling default SPI flash mode...") - esp.flash_spi_attach(value) - - # XMC chip startup sequence - XMC_VENDOR_ID = 0x20 - - def is_xmc_chip_strict(): - id = esp.flash_id() - rdid = ((id & 0xFF) << 16) | ((id >> 16) & 0xFF) | (id & 0xFF00) - - vendor_id = (rdid >> 16) & 0xFF - mfid = (rdid >> 8) & 0xFF - cpid = rdid & 0xFF - - if vendor_id != XMC_VENDOR_ID: - return False - - matched = False - if mfid == 0x40: - if cpid >= 0x13 and cpid <= 0x20: - matched = True - elif mfid == 0x41: - if cpid >= 0x17 and cpid <= 0x20: - matched = True - elif mfid == 0x50: - if cpid >= 0x15 and cpid <= 0x16: - matched = True - return matched - - def flash_xmc_startup(): - # If the RDID value is a valid XMC one, may skip the flow - fast_check = True - if fast_check and is_xmc_chip_strict(): - return # Successful XMC flash chip boot-up detected by RDID, skipping. - - sfdp_mfid_addr = 0x10 - mf_id = esp.read_spiflash_sfdp(sfdp_mfid_addr, 8) - if mf_id != XMC_VENDOR_ID: # Non-XMC chip detected by SFDP Read, skipping. - return - - print( - "WARNING: XMC flash chip boot-up failure detected! " - "Running XMC25QHxxC startup flow" - ) - esp.run_spiflash_command(0xB9) # Enter DPD - esp.run_spiflash_command(0x79) # Enter UDPD - esp.run_spiflash_command(0xFF) # Exit UDPD - time.sleep(0.002) # Delay tXUDPD - esp.run_spiflash_command(0xAB) # Release Power-Down - time.sleep(0.00002) - # Check for success - if not is_xmc_chip_strict(): - print("WARNING: XMC flash boot-up fix failed.") - print("XMC flash chip boot-up fix successful!") - - # Check flash chip connection - if not esp.secure_download_mode: - try: - flash_id = esp.flash_id() - if flash_id in (0xFFFFFF, 0x000000): - print( - "WARNING: Failed to communicate with the flash chip, " - "read/write operations will fail. " - "Try checking the chip connections or removing " - "any other hardware connected to IOs." - ) - if ( - hasattr(args, "spi_connection") - and args.spi_connection is not None - ): - print( - "Some GPIO pins might be used by other peripherals, " - "try using another --spi-connection combination." - ) - - except FatalError as e: - raise FatalError(f"Unable to verify flash chip connection ({e}).") - - # Check if XMC SPI flash chip booted-up successfully, fix if not - if not esp.secure_download_mode: - try: - flash_xmc_startup() - except FatalError as e: - esp.trace(f"Unable to perform XMC flash chip startup sequence ({e}).") - - if hasattr(args, "flash_size"): - print("Configuring 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) - if not esp.IS_STUB: - print( - "WARNING: In case of failure, please set a specific --flash_size." - ) - 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 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 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." - ) - - try: - operation_func(esp, args) - finally: - try: # Clean up AddrFilenamePairAction files - for address, argfile in args.addr_filename: - argfile.close() - except AttributeError: - pass - - # Handle post-operation behaviour (reset or other) - if operation_func == load_ram: - # the ESP is now running the loaded image, so let it run - print("Exiting immediately.") - elif args.after == "hard_reset": - esp.hard_reset() - elif args.after == "soft_reset": - print("Soft resetting...") - # flash_finish will trigger a soft reset - esp.soft_reset(False) - elif args.after == "no_reset_stub": - print("Staying in flasher stub.") - else: # args.after == 'no_reset' - print("Staying in bootloader.") - if esp.IS_STUB: - esp.soft_reset(True) # exit stub back to ROM loader - - if not external_esp: - esp._port.close() - - else: - operation_func(args) - - -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(vids=[], pids=[], names=[]): - if list_ports is None: - raise FatalError( - "Listing all serial ports is currently not available. " - "Please try to specify the port when running esptool.py or update " - "the pyserial package to the latest version" - ) - ports = [] - for port in list_ports.comports(): - if sys.platform == "darwin" and port.device.endswith( - ("Bluetooth-Incoming-Port", "wlan-debug") - ): - continue - if vids and (port.vid is None or port.vid not in vids): - continue - if pids and (port.pid is None or port.pid not in pids): - continue - if names and ( - port.name is None or all(name not in port.name for name in names) - ): - continue - ports.append(port.device) - return sorted(ports) - - -def expand_file_arguments(argv): - """ - Any argument starting with "@" gets replaced with all values read from a text file. - Text file arguments can be split by newline or by space. - Values are added "as-is", as if they were specified in this order - on the command line. - """ - new_args = [] - expanded = False - for arg in argv: - if arg.startswith("@"): - expanded = True - with open(arg[1:], "r") as f: - for line in f.readlines(): - new_args += shlex.split(line) - else: - new_args.append(arg) - if expanded: - print(f"esptool.py {' '.join(new_args)}") - return new_args - return argv - - -def connect_loop( - port: str, - initial_baud: int, - chip: str, - max_retries: int, - trace: bool = False, - before: str = "default_reset", -): - chip_class = CHIP_DEFS[chip] - esp = None - print(f"Serial port {port}") - - first = True - ten_cycle = cycle(chain(repeat(False, 9), (True,))) - retry_loop = chain( - repeat(False, max_retries - 1), (True,) if max_retries else cycle((False,)) - ) - - for last, every_tenth in zip(retry_loop, ten_cycle): - try: - esp = chip_class(port, initial_baud, trace) - if not first: - # break the retrying line - print("") - esp.connect(before) - return esp - except ( - FatalError, - serial.serialutil.SerialException, - IOError, - OSError, - ) as err: - if esp and esp._port: - esp._port.close() - esp = None - if first: - print(err) - print("Retrying failed connection", end="", flush=True) - first = False - if last: - raise err - if every_tenth: - # print a dot every second - print(".", end="", flush=True) - time.sleep(0.1) - - -def get_default_connected_device( - serial_list, - port, - connect_attempts, - initial_baud, - chip="auto", - trace=False, - before="default_reset", -): - _esp = None - for each_port in reversed(serial_list): - print("Serial port %s" % each_port) - try: - if chip == "auto": - _esp = detect_chip( - each_port, initial_baud, before, trace, connect_attempts - ) - else: - chip_class = CHIP_DEFS[chip] - _esp = chip_class(each_port, initial_baud, trace) - _esp.connect(before, connect_attempts) - break - except (FatalError, OSError) as err: - if port is not None: - raise - print("%s failed to connect: %s" % (each_port, err)) - if _esp and _esp._port: - _esp._port.close() - _esp = None - return _esp - - -class SpiConnectionAction(argparse.Action): - """ - Custom action to parse 'spi connection' override. - Values are SPI, HSPI, or a sequence of 5 pin numbers separated by commas. - """ - - def __call__(self, parser, namespace, value, option_string=None): - if value.upper() in ["SPI", "HSPI"]: - values = value.upper() - elif "," in value: - values = value.split(",") - if len(values) != 5: - raise argparse.ArgumentError( - self, - f"{value} is not a valid list of comma-separate pin numbers. " - "Must be 5 numbers - CLK,Q,D,HD,CS.", - ) - try: - values = tuple(int(v, 0) for v in values) - except ValueError: - raise argparse.ArgumentError( - self, - f"{values} is not a valid argument. " - "All pins must be numeric values", - ) - else: - raise argparse.ArgumentError( - self, - f"{value} is not a valid spi-connection value. " - "Values are SPI, HSPI, or a sequence of 5 pin numbers - CLK,Q,D,HD,CS.", - ) - setattr(namespace, self.dest, values) - - -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""" - - def __init__(self, option_strings, dest, nargs="+", **kwargs): - super(AddrFilenamePairAction, self).__init__( - option_strings, dest, nargs, **kwargs - ) - - def __call__(self, parser, namespace, values, option_string=None): - # validate pair arguments - pairs = [] - for i in range(0, len(values), 2): - try: - address = int(values[i], 0) - except ValueError: - raise argparse.ArgumentError( - self, 'Address "%s" must be a number' % values[i] - ) - try: - argfile = open(values[i + 1], "rb") - except IOError as e: - raise argparse.ArgumentError(self, e) - except IndexError: - raise argparse.ArgumentError( - self, - "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 - end = 0 - for address, argfile in sorted(pairs, key=lambda x: x[0]): - argfile.seek(0, 2) # seek to end - size = argfile.tell() - argfile.seek(0) - sector_start = address & ~(ESPLoader.FLASH_SECTOR_SIZE - 1) - sector_end = ( - (address + size + ESPLoader.FLASH_SECTOR_SIZE - 1) - & ~(ESPLoader.FLASH_SECTOR_SIZE - 1) - ) - 1 - if sector_start < end: - message = "Detected overlap at address: 0x%x for file: %s" % ( - address, - argfile.name, - ) - raise argparse.ArgumentError(self, message) - end = sector_end - setattr(namespace, self.dest, pairs) - - -def _main(): - try: - main() - except FatalError as e: - print(f"\nA fatal error occurred: {e}") - sys.exit(2) - except serial.serialutil.SerialException as e: - print(f"\nA serial exception error occurred: {e}") - print( - "Note: This error originates from pySerial. " - "It is likely not a problem with esptool, " - "but with the hardware connection or drivers." - ) - print( - "For troubleshooting steps visit: " - "https://docs.espressif.com/projects/esptool/en/latest/troubleshooting.html" - ) - sys.exit(1) - except StopIteration: - print(traceback.format_exc()) - print("A fatal error occurred: The chip stopped responding.") - sys.exit(2) - - -if __name__ == "__main__": - _main() diff --git a/tools/esptool_py/esptool/__main__.py b/tools/esptool_py/esptool/__main__.py deleted file mode 100644 index 11e3bce1bf..0000000000 --- a/tools/esptool_py/esptool/__main__.py +++ /dev/null @@ -1,9 +0,0 @@ -# SPDX-FileCopyrightText: 2014-2022 Fredrik Ahlberg, Angus Gratton, -# Espressif Systems (Shanghai) CO LTD, other contributors as noted. -# -# SPDX-License-Identifier: GPL-2.0-or-later - -import esptool - -if __name__ == "__main__": - esptool._main() diff --git a/tools/esptool_py/esptool/bin_image.py b/tools/esptool_py/esptool/bin_image.py deleted file mode 100644 index 7ac9ed3c9c..0000000000 --- a/tools/esptool_py/esptool/bin_image.py +++ /dev/null @@ -1,1424 +0,0 @@ -# SPDX-FileCopyrightText: 2014-2022 Fredrik Ahlberg, Angus Gratton, -# Espressif Systems (Shanghai) CO LTD, other contributors as noted. -# -# SPDX-License-Identifier: GPL-2.0-or-later - -import binascii -import copy -import hashlib -import io -import os -import re -import struct -import tempfile -from typing import IO, Optional - -from intelhex import HexRecordError, IntelHex - -from .loader import ESPLoader -from .targets import ( - ESP32C2ROM, - ESP32C3ROM, - ESP32C5ROM, - ESP32C5BETA3ROM, - ESP32C6BETAROM, - ESP32C6ROM, - ESP32C61ROM, - ESP32H2BETA1ROM, - ESP32H2BETA2ROM, - ESP32H2ROM, - ESP32P4ROM, - ESP32ROM, - ESP32S2ROM, - ESP32S3BETA2ROM, - ESP32S3ROM, - ESP8266ROM, -) -from .util import FatalError, byte, pad_to - - -def align_file_position(f, size): - """Align the position in the file to the next block of specified size""" - align = (size - 1) - (f.tell() % size) - f.seek(align, 1) - - -def intel_hex_to_bin(file: IO[bytes], start_addr: Optional[int] = None) -> IO[bytes]: - """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) - try: - 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 - except (HexRecordError, UnicodeDecodeError): - # file started with HEX magic but the rest was not according to the standard - return file - - -def LoadFirmwareImage(chip, image_file): - """ - Load a firmware image. Can be for any supported SoC. - - ESP8266 images will be examined to determine if they are original ROM firmware - images (ESP8266ROMFirmwareImage) or "v2" OTA bootloader images. - - Returns a BaseFirmwareImage subclass, either ESP8266ROMFirmwareImage (v1) - or ESP8266V2FirmwareImage (v2). - """ - - def select_image_class(f, chip): - chip = re.sub(r"[-()]", "", chip.lower()) - if chip != "esp8266": - return { - "esp32": ESP32FirmwareImage, - "esp32s2": ESP32S2FirmwareImage, - "esp32s3beta2": ESP32S3BETA2FirmwareImage, - "esp32s3": ESP32S3FirmwareImage, - "esp32c3": ESP32C3FirmwareImage, - "esp32c6beta": ESP32C6BETAFirmwareImage, - "esp32h2beta1": ESP32H2BETA1FirmwareImage, - "esp32h2beta2": ESP32H2BETA2FirmwareImage, - "esp32c2": ESP32C2FirmwareImage, - "esp32c6": ESP32C6FirmwareImage, - "esp32c61": ESP32C61FirmwareImage, - "esp32c5": ESP32C5FirmwareImage, - "esp32c5beta3": ESP32C5BETA3FirmwareImage, - "esp32h2": ESP32H2FirmwareImage, - "esp32p4": ESP32P4FirmwareImage, - }[chip](f) - else: # Otherwise, ESP8266 so look at magic to determine the image type - magic = ord(f.read(1)) - f.seek(0) - if magic == ESPLoader.ESP_IMAGE_MAGIC: - return ESP8266ROMFirmwareImage(f) - elif magic == ESP8266V2FirmwareImage.IMAGE_V2_MAGIC: - return ESP8266V2FirmwareImage(f) - else: - raise FatalError("Invalid image magic number: %d" % magic) - - if isinstance(image_file, str): - with open(image_file, "rb") as f: - return select_image_class(f, chip) - return select_image_class(image_file, chip) - - -class ImageSegment(object): - """Wrapper class for a segment in an ESP image - (very similar to a section in an ELFImage also)""" - - def __init__(self, addr, data, file_offs=None, flags=0, align=4): - self.addr = addr - self.data = data - self.file_offs = file_offs - self.flags = flags - self.align = align - self.include_in_checksum = True - if self.addr != 0: - self.pad_to_alignment( - 4 - ) # pad all "real" ImageSegments 4 byte aligned length - - def copy_with_new_addr(self, new_addr): - """Return a new ImageSegment with same data, but mapped at - a new address.""" - return ImageSegment(new_addr, self.data, 0) - - def split_image(self, split_len): - """Return a new ImageSegment which splits "split_len" bytes - from the beginning of the data. Remaining bytes are kept in - this segment object (and the start address is adjusted to match.)""" - result = copy.copy(self) - result.data = self.data[:split_len] - self.data = self.data[split_len:] - self.addr += split_len - self.file_offs = None - result.file_offs = None - return result - - def __repr__(self): - r = "len 0x%05x load 0x%08x" % (len(self.data), self.addr) - if self.file_offs is not None: - r += " file_offs 0x%08x" % (self.file_offs) - return r - - def get_memory_type(self, image): - """ - Return a list describing the memory type(s) that is covered by this - segment's start address. - """ - return [ - map_range[2] - for map_range in image.ROM_LOADER.MEMORY_MAP - if map_range[0] <= self.addr < map_range[1] - ] - - def pad_to_alignment(self, alignment): - self.data = pad_to(self.data, alignment, b"\x00") - - def addr_align(self, alignment): - end_addr = self.addr + len(self.data) - addr_mod = end_addr % alignment - if addr_mod != 0: - end_addr += alignment - addr_mod - return end_addr - - def pad_to_addr(self, addr): - pad = addr - (self.addr + len(self.data)) - if pad > 0: - self.data += b"\x00" * pad - - -class ELFSection(ImageSegment): - """Wrapper class for a section in an ELF image, has a section - name as well as the common properties of an ImageSegment.""" - - def __init__(self, name, addr, data, flags, align=4): - super(ELFSection, self).__init__(addr, data, flags=flags, align=align) - self.name = name.decode("utf-8") - - def __repr__(self): - return "%s %s" % (self.name, super(ELFSection, self).__repr__()) - - -class BaseFirmwareImage(object): - SEG_HEADER_LEN = 8 - SHA256_DIGEST_LEN = 32 - ELF_FLAG_WRITE = 0x1 - ELF_FLAG_READ = 0x2 - ELF_FLAG_EXEC = 0x4 - - """ Base class with common firmware image functions """ - - def __init__(self): - self.segments = [] - self.entrypoint = 0 - self.elf_sha256 = None - self.elf_sha256_offset = 0 - self.pad_to_size = 0 - - def load_common_header(self, load_file, expected_magic): - ( - magic, - segments, - self.flash_mode, - self.flash_size_freq, - self.entrypoint, - ) = struct.unpack(" 16: - raise FatalError( - "Invalid segment count %d (max 16). " - "Usually this indicates a linker script problem." % len(self.segments) - ) - - def load_segment(self, f, is_irom_segment=False): - """Load the next segment from the image file""" - file_offs = f.tell() - (offset, size) = struct.unpack(" 0x40200000 or offset < 0x3FFE0000 or size > 65536: - print("WARNING: Suspicious segment 0x%x, length %d" % (offset, size)) - - def maybe_patch_segment_data(self, f, segment_data): - """ - If SHA256 digest of the ELF file needs to be inserted into this segment, do so. - Returns segment data. - """ - segment_len = len(segment_data) - file_pos = f.tell() # file_pos is position in the .bin file - if ( - self.elf_sha256_offset >= file_pos - and self.elf_sha256_offset < file_pos + segment_len - ): - # SHA256 digest needs to be patched into this binary segment, - # calculate offset of the digest inside the binary segment. - patch_offset = self.elf_sha256_offset - file_pos - # Sanity checks - if ( - patch_offset < self.SEG_HEADER_LEN - or patch_offset + self.SHA256_DIGEST_LEN > segment_len - ): - raise FatalError( - "Cannot place SHA256 digest on segment boundary" - "(elf_sha256_offset=%d, file_pos=%d, segment_size=%d)" - % (self.elf_sha256_offset, file_pos, segment_len) - ) - # offset relative to the data part - patch_offset -= self.SEG_HEADER_LEN - if ( - segment_data[patch_offset : patch_offset + self.SHA256_DIGEST_LEN] - != b"\x00" * self.SHA256_DIGEST_LEN - ): - raise FatalError( - "Contents of segment at SHA256 digest offset 0x%x are not all zero." - " Refusing to overwrite." % self.elf_sha256_offset - ) - assert len(self.elf_sha256) == self.SHA256_DIGEST_LEN - segment_data = ( - segment_data[0:patch_offset] - + self.elf_sha256 - + segment_data[patch_offset + self.SHA256_DIGEST_LEN :] - ) - return segment_data - - def save_segment(self, f, segment, checksum=None): - """ - Save the next segment to the image file, - return next checksum value if provided - """ - segment_data = self.maybe_patch_segment_data(f, segment.data) - f.write(struct.pack(" 0: - if len(irom_segments) != 1: - raise FatalError( - "Found %d segments that could be irom0. Bad ELF file?" - % len(irom_segments) - ) - return irom_segments[0] - return None - - def get_non_irom_segments(self): - irom_segment = self.get_irom_segment() - return [s for s in self.segments if s != irom_segment] - - def sort_segments(self): - if not self.segments: - return # nothing to sort - self.segments = sorted(self.segments, key=lambda s: s.addr) - - def merge_adjacent_segments(self): - if not self.segments: - return # nothing to merge - - segments = [] - # The easiest way to merge the sections is the browse them backward. - for i in range(len(self.segments) - 1, 0, -1): - # elem is the previous section, the one `next_elem` may need to be - # merged in - elem = self.segments[i - 1] - next_elem = self.segments[i] - elem_pad_addr = elem.addr_align(next_elem.align) - - # When creating the images from 3rd-party frameworks ELFs, the merging - # could bring together segments with incompatible alignment requirements. - # At this point, we add padding so the resulting placement respects the - # original alignment requirements of those segments. - if self.ROM_LOADER != ESP8266ROM and self.ram_only_header: - if ( - elem_pad_addr != elem.addr + len(elem.data) - and elem_pad_addr == next_elem.addr - ): - print( - "Info: inserting %d bytes padding between %s and %s" - % ( - next_elem.addr - (elem.addr + len(elem.data)), - elem.name, - next_elem.name, - ) - ) - elem.pad_to_addr(elem_pad_addr) - if all( - ( - elem.get_memory_type(self) == next_elem.get_memory_type(self), - elem.include_in_checksum == next_elem.include_in_checksum, - next_elem.addr == elem.addr + len(elem.data), - next_elem.flags & self.ELF_FLAG_EXEC - == elem.flags & self.ELF_FLAG_EXEC, - ) - ): - # Merge any segment that ends where the next one starts, - # without spanning memory types - # - # (don't 'pad' any gaps here as they may be excluded from the image - # due to 'noinit' or other reasons.) - elem.data += next_elem.data - else: - # The section next_elem cannot be merged into the previous one, - # which means it needs to be part of the final segments. - # As we are browsing the list backward, the elements need to be - # inserted at the beginning of the final list. - segments.insert(0, next_elem) - - # The first segment will always be here as it cannot be merged into any - # "previous" section. - segments.insert(0, self.segments[0]) - - # note: we could sort segments here as well, but the ordering of segments is - # sometimes important for other reasons (like embedded ELF SHA-256), - # so we assume that the linker script will have produced any adjacent sections - # in linear order in the ELF, anyhow. - self.segments = segments - - def set_mmu_page_size(self, size): - """ - If supported, this should be overridden by the chip-specific class. - Gets called in elf2image. - """ - print( - "WARNING: Changing MMU page size is not supported on {}! " - "Defaulting to 64KB.".format(self.ROM_LOADER.CHIP_NAME) - ) - - -class ESP8266ROMFirmwareImage(BaseFirmwareImage): - """'Version 1' firmware image, segments loaded directly by the ROM bootloader.""" - - ROM_LOADER = ESP8266ROM - - def __init__(self, load_file=None): - super(ESP8266ROMFirmwareImage, self).__init__() - self.flash_mode = 0 - self.flash_size_freq = 0 - self.version = 1 - - if load_file is not None: - segments = self.load_common_header(load_file, ESPLoader.ESP_IMAGE_MAGIC) - - for _ in range(segments): - self.load_segment(load_file) - self.checksum = self.read_checksum(load_file) - - self.verify() - - def default_output_name(self, input_file): - """Derive a default output name from the ELF name.""" - return input_file + "-" - - def save(self, basename): - """Save a set of V1 images for flashing. Parameter is a base filename.""" - # IROM data goes in its own plain binary file - irom_segment = self.get_irom_segment() - if irom_segment is not None: - with open( - "%s0x%05x.bin" - % (basename, irom_segment.addr - ESP8266ROM.IROM_MAP_START), - "wb", - ) as f: - f.write(irom_segment.data) - - # everything but IROM goes at 0x00000 in an image file - normal_segments = self.get_non_irom_segments() - with open("%s0x00000.bin" % basename, "wb") as f: - self.write_common_header(f, normal_segments) - checksum = ESPLoader.ESP_CHECKSUM_MAGIC - for segment in normal_segments: - checksum = self.save_segment(f, segment, checksum) - self.append_checksum(f, checksum) - - -ESP8266ROM.BOOTLOADER_IMAGE = ESP8266ROMFirmwareImage - - -class ESP8266V2FirmwareImage(BaseFirmwareImage): - """'Version 2' firmware image, segments loaded by software bootloader stub - (ie Espressif bootloader or rboot) - """ - - ROM_LOADER = ESP8266ROM - # First byte of the "v2" application image - IMAGE_V2_MAGIC = 0xEA - - # First 'segment' value in a "v2" application image, - # appears to be a constant version value? - IMAGE_V2_SEGMENT = 4 - - def __init__(self, load_file=None): - super(ESP8266V2FirmwareImage, self).__init__() - self.version = 2 - if load_file is not None: - segments = self.load_common_header(load_file, self.IMAGE_V2_MAGIC) - if segments != self.IMAGE_V2_SEGMENT: - # segment count is not really segment count here, - # but we expect to see '4' - print( - 'Warning: V2 header has unexpected "segment" count %d (usually 4)' - % segments - ) - - # irom segment comes before the second header - # - # the file is saved in the image with a zero load address - # in the header, so we need to calculate a load address - irom_segment = self.load_segment(load_file, True) - # for actual mapped addr, add ESP8266ROM.IROM_MAP_START + flashing_addr + 8 - irom_segment.addr = 0 - irom_segment.include_in_checksum = False - - first_flash_mode = self.flash_mode - first_flash_size_freq = self.flash_size_freq - first_entrypoint = self.entrypoint - # load the second header - - segments = self.load_common_header(load_file, ESPLoader.ESP_IMAGE_MAGIC) - - if first_flash_mode != self.flash_mode: - print( - "WARNING: Flash mode value in first header (0x%02x) disagrees " - "with second (0x%02x). Using second value." - % (first_flash_mode, self.flash_mode) - ) - if first_flash_size_freq != self.flash_size_freq: - print( - "WARNING: Flash size/freq value in first header (0x%02x) disagrees " - "with second (0x%02x). Using second value." - % (first_flash_size_freq, self.flash_size_freq) - ) - if first_entrypoint != self.entrypoint: - print( - "WARNING: Entrypoint address in first header (0x%08x) disagrees " - "with second header (0x%08x). Using second value." - % (first_entrypoint, self.entrypoint) - ) - - # load all the usual segments - for _ in range(segments): - self.load_segment(load_file) - self.checksum = self.read_checksum(load_file) - - self.verify() - - def default_output_name(self, input_file): - """Derive a default output name from the ELF name.""" - irom_segment = self.get_irom_segment() - if irom_segment is not None: - irom_offs = irom_segment.addr - ESP8266ROM.IROM_MAP_START - else: - irom_offs = 0 - return "%s-0x%05x.bin" % ( - os.path.splitext(input_file)[0], - irom_offs & ~(ESPLoader.FLASH_SECTOR_SIZE - 1), - ) - - def save(self, filename): - with open(filename, "wb") as f: - # Save first header for irom0 segment - f.write( - struct.pack( - b" 0: - last_addr = flash_segments[0].addr - for segment in flash_segments[1:]: - if segment.addr // self.IROM_ALIGN == last_addr // self.IROM_ALIGN: - raise FatalError( - "Segment loaded at 0x%08x lands in same 64KB flash mapping " - "as segment loaded at 0x%08x. Can't generate binary. " - "Suggest changing linker script or ELF to merge sections." - % (segment.addr, last_addr) - ) - last_addr = segment.addr - - def get_alignment_data_needed(segment): - # Actual alignment (in data bytes) required for a segment header: - # positioned so that after we write the next 8 byte header, - # file_offs % IROM_ALIGN == segment.addr % IROM_ALIGN - # - # (this is because the segment's vaddr may not be IROM_ALIGNed, - # more likely is aligned IROM_ALIGN+0x18 - # to account for the binary file header - align_past = (segment.addr % self.IROM_ALIGN) - self.SEG_HEADER_LEN - pad_len = (self.IROM_ALIGN - (f.tell() % self.IROM_ALIGN)) + align_past - if pad_len == 0 or pad_len == self.IROM_ALIGN: - return 0 # already aligned - - # subtract SEG_HEADER_LEN a second time, - # as the padding block has a header as well - pad_len -= self.SEG_HEADER_LEN - if pad_len < 0: - pad_len += self.IROM_ALIGN - return pad_len - - 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 - 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) - # Some chips have a non-zero load offset (eg. 0x1000) - # therefore we shift the ROM segments "-load_offset" - # so it will be aligned properly after it is flashed - if pad_len < self.ROM_LOADER.BOOTLOADER_FLASH_OFFSET: - # in case pad_len does not fit minimum alignment, - # pad it to next aligned boundary - pad_len += self.IROM_ALIGN - - pad_len -= self.ROM_LOADER.BOOTLOADER_FLASH_OFFSET - pad_segment = ImageSegment(0, b"\x00" * pad_len, f.tell()) - self.save_segment(f, pad_segment) - total_segments += 1 - # check the alignment - assert (f.tell() + 8 + self.ROM_LOADER.BOOTLOADER_FLASH_OFFSET) % ( - self.IROM_ALIGN - ) == segment.addr % self.IROM_ALIGN - # 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 - - if self.secure_pad: - # pad the image so that after signing it will end on a a 64KB boundary. - # This ensures all mapped flash content will be verified. - if not self.append_digest: - raise FatalError( - "secure_pad only applies if a SHA-256 digest " - "is also appended to the image" - ) - align_past = (f.tell() + self.SEG_HEADER_LEN) % self.IROM_ALIGN - # 16 byte aligned checksum - # (force the alignment to simplify calculations) - checksum_space = 16 - if self.secure_pad == "1": - # after checksum: SHA-256 digest + - # (to be added by signing process) version, - # signature + 12 trailing bytes due to alignment - space_after_checksum = 32 + 4 + 64 + 12 - elif self.secure_pad == "2": # Secure Boot V2 - # after checksum: SHA-256 digest + - # signature sector, - # but we place signature sector after the 64KB boundary - space_after_checksum = 32 - pad_len = ( - self.IROM_ALIGN - align_past - checksum_space - space_after_checksum - ) % self.IROM_ALIGN - pad_segment = ImageSegment(0, b"\x00" * pad_len, f.tell()) - - checksum = self.save_segment(f, pad_segment, checksum) - total_segments += 1 - - if not self.ram_only_header: - # done writing segments - self.append_checksum(f, checksum) - image_length = f.tell() - - if self.secure_pad: - assert ((image_length + space_after_checksum) % self.IROM_ALIGN) == 0 - - # 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) - 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 - f.seek(0) - digest = hashlib.sha256() - digest.update(f.read(image_length)) - f.write(digest.digest()) - - if self.pad_to_size: - image_length = f.tell() - if image_length % self.pad_to_size != 0: - pad_by = self.pad_to_size - (image_length % self.pad_to_size) - f.write(b"\xff" * pad_by) - - with open(filename, "wb") as real_file: - real_file.write(f.getvalue()) - - def load_extended_header(self, load_file): - def split_byte(n): - return (n & 0x0F, (n >> 4) & 0x0F) - - fields = list( - struct.unpack(self.EXTENDED_HEADER_STRUCT_FMT, load_file.read(16)) - ) - - self.wp_pin = fields[0] - - # SPI pin drive stengths are two per byte - self.clk_drv, self.q_drv = split_byte(fields[1]) - self.d_drv, self.cs_drv = split_byte(fields[2]) - self.hd_drv, self.wp_drv = split_byte(fields[3]) - - self.chip_id = fields[4] - if self.chip_id != self.ROM_LOADER.IMAGE_CHIP_ID: - print( - ( - "Unexpected chip id in image. Expected %d but value was %d. " - "Is this image for a different chip model?" - ) - % (self.ROM_LOADER.IMAGE_CHIP_ID, self.chip_id) - ) - - self.min_rev = fields[5] - self.min_rev_full = fields[6] - self.max_rev_full = fields[7] - - append_digest = fields[-1] # last byte is append_digest - if append_digest in [0, 1]: - self.append_digest = append_digest == 1 - else: - raise RuntimeError( - "Invalid value for append_digest field (0x%02x). Should be 0 or 1.", - append_digest, - ) - - def save_extended_header(self, save_file): - def join_byte(ln, hn): - return (ln & 0x0F) + ((hn & 0x0F) << 4) - - append_digest = 1 if self.append_digest else 0 - - fields = [ - self.wp_pin, - join_byte(self.clk_drv, self.q_drv), - join_byte(self.d_drv, self.cs_drv), - join_byte(self.hd_drv, self.wp_drv), - self.ROM_LOADER.IMAGE_CHIP_ID, - self.min_rev, - self.min_rev_full, - self.max_rev_full, - ] - fields += [0] * 4 # padding - fields += [append_digest] - - packed = struct.pack(self.EXTENDED_HEADER_STRUCT_FMT, *fields) - save_file.write(packed) - - -class ESP8266V3FirmwareImage(ESP32FirmwareImage): - """ESP8266 V3 firmware image is very similar to ESP32 image""" - - EXTENDED_HEADER_STRUCT_FMT = "B" * 16 - - def is_flash_addr(self, addr): - return addr > ESP8266ROM.IROM_MAP_START - - def save(self, filename): - total_segments = 0 - with io.BytesIO() as f: # write file to memory first - self.write_common_header(f, self.segments) - - checksum = ESPLoader.ESP_CHECKSUM_MAGIC - - # split segments into flash-mapped vs ram-loaded, - # and take copies so we can mutate them - flash_segments = [ - copy.deepcopy(s) - for s in sorted(self.segments, key=lambda s: s.addr) - if self.is_flash_addr(s.addr) and len(s.data) - ] - ram_segments = [ - copy.deepcopy(s) - for s in sorted(self.segments, key=lambda s: s.addr) - if not self.is_flash_addr(s.addr) and len(s.data) - ] - - # 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 - if len(flash_segments) > 0: - last_addr = flash_segments[0].addr - for segment in flash_segments[1:]: - if segment.addr // self.IROM_ALIGN == last_addr // self.IROM_ALIGN: - raise FatalError( - "Segment loaded at 0x%08x lands in same 64KB flash mapping " - "as segment loaded at 0x%08x. Can't generate binary. " - "Suggest changing linker script or ELF to merge sections." - % (segment.addr, last_addr) - ) - last_addr = segment.addr - - # 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] - # remove 8 bytes empty data for insert segment header - if isinstance(segment, ELFSection) and segment.name == ".flash.rodata": - segment.data = segment.data[8:] - # write the flash segment - checksum = self.save_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 - - # done writing segments - self.append_checksum(f, checksum) - image_length = f.tell() - - # 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.append_digest: - # calculate the SHA256 of the whole file and append it - f.seek(0) - digest = hashlib.sha256() - digest.update(f.read(image_length)) - f.write(digest.digest()) - - with open(filename, "wb") as real_file: - real_file.write(f.getvalue()) - - def load_extended_header(self, load_file): - def split_byte(n): - return (n & 0x0F, (n >> 4) & 0x0F) - - fields = list( - struct.unpack(self.EXTENDED_HEADER_STRUCT_FMT, load_file.read(16)) - ) - - self.wp_pin = fields[0] - - # SPI pin drive stengths are two per byte - self.clk_drv, self.q_drv = split_byte(fields[1]) - self.d_drv, self.cs_drv = split_byte(fields[2]) - self.hd_drv, self.wp_drv = split_byte(fields[3]) - - if fields[15] in [0, 1]: - self.append_digest = fields[15] == 1 - else: - raise RuntimeError( - "Invalid value for append_digest field (0x%02x). Should be 0 or 1.", - fields[15], - ) - - # remaining fields in the middle should all be zero - if any(f for f in fields[4:15] if f != 0): - print( - "Warning: some reserved header fields have non-zero values. " - "This image may be from a newer esptool.py?" - ) - - -ESP32ROM.BOOTLOADER_IMAGE = ESP32FirmwareImage - - -class ESP32S2FirmwareImage(ESP32FirmwareImage): - """ESP32S2 Firmware Image almost exactly the same as ESP32FirmwareImage""" - - ROM_LOADER = ESP32S2ROM - - -ESP32S2ROM.BOOTLOADER_IMAGE = ESP32S2FirmwareImage - - -class ESP32S3BETA2FirmwareImage(ESP32FirmwareImage): - """ESP32S3 Firmware Image almost exactly the same as ESP32FirmwareImage""" - - ROM_LOADER = ESP32S3BETA2ROM - - -ESP32S3BETA2ROM.BOOTLOADER_IMAGE = ESP32S3BETA2FirmwareImage - - -class ESP32S3FirmwareImage(ESP32FirmwareImage): - """ESP32S3 Firmware Image almost exactly the same as ESP32FirmwareImage""" - - ROM_LOADER = ESP32S3ROM - - -ESP32S3ROM.BOOTLOADER_IMAGE = ESP32S3FirmwareImage - - -class ESP32C3FirmwareImage(ESP32FirmwareImage): - """ESP32C3 Firmware Image almost exactly the same as ESP32FirmwareImage""" - - ROM_LOADER = ESP32C3ROM - - -ESP32C3ROM.BOOTLOADER_IMAGE = ESP32C3FirmwareImage - - -class ESP32C6BETAFirmwareImage(ESP32FirmwareImage): - """ESP32C6 Firmware Image almost exactly the same as ESP32FirmwareImage""" - - ROM_LOADER = ESP32C6BETAROM - - -ESP32C6BETAROM.BOOTLOADER_IMAGE = ESP32C6BETAFirmwareImage - - -class ESP32H2BETA1FirmwareImage(ESP32FirmwareImage): - """ESP32H2 Firmware Image almost exactly the same as ESP32FirmwareImage""" - - ROM_LOADER = ESP32H2BETA1ROM - - -ESP32H2BETA1ROM.BOOTLOADER_IMAGE = ESP32H2BETA1FirmwareImage - - -class ESP32H2BETA2FirmwareImage(ESP32FirmwareImage): - """ESP32H2 Firmware Image almost exactly the same as ESP32FirmwareImage""" - - ROM_LOADER = ESP32H2BETA2ROM - - -ESP32H2BETA2ROM.BOOTLOADER_IMAGE = ESP32H2BETA2FirmwareImage - - -class ESP32C2FirmwareImage(ESP32FirmwareImage): - """ESP32C2 Firmware Image almost exactly the same as ESP32FirmwareImage""" - - ROM_LOADER = ESP32C2ROM - - def set_mmu_page_size(self, size): - if size not in [16384, 32768, 65536]: - raise FatalError( - "{} bytes is not a valid ESP32-C2 page size, " - "select from 64KB, 32KB, 16KB.".format(size) - ) - self.IROM_ALIGN = size - - -ESP32C2ROM.BOOTLOADER_IMAGE = ESP32C2FirmwareImage - - -class ESP32C6FirmwareImage(ESP32FirmwareImage): - """ESP32C6 Firmware Image almost exactly the same as ESP32FirmwareImage""" - - ROM_LOADER = ESP32C6ROM - - def set_mmu_page_size(self, size): - if size not in [8192, 16384, 32768, 65536]: - raise FatalError( - "{} bytes is not a valid ESP32-C6 page size, " - "select from 64KB, 32KB, 16KB, 8KB.".format(size) - ) - self.IROM_ALIGN = size - - -ESP32C6ROM.BOOTLOADER_IMAGE = ESP32C6FirmwareImage - - -class ESP32C61FirmwareImage(ESP32C6FirmwareImage): - """ESP32C61 Firmware Image almost exactly the same as ESP32C6FirmwareImage""" - - ROM_LOADER = ESP32C61ROM - - -ESP32C61ROM.BOOTLOADER_IMAGE = ESP32C61FirmwareImage - - -class ESP32C5FirmwareImage(ESP32C6FirmwareImage): - """ESP32C5 Firmware Image almost exactly the same as ESP32C6FirmwareImage""" - - ROM_LOADER = ESP32C5ROM - - -ESP32C5ROM.BOOTLOADER_IMAGE = ESP32C5FirmwareImage - - -class ESP32C5BETA3FirmwareImage(ESP32C6FirmwareImage): - """ESP32C5BETA3 Firmware Image almost exactly the same as ESP32C6FirmwareImage""" - - ROM_LOADER = ESP32C5BETA3ROM - - -ESP32C5BETA3ROM.BOOTLOADER_IMAGE = ESP32C5BETA3FirmwareImage - - -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""" - - ROM_LOADER = ESP32H2ROM - - -ESP32H2ROM.BOOTLOADER_IMAGE = ESP32H2FirmwareImage - - -class ELFFile(object): - SEC_TYPE_PROGBITS = 0x01 - SEC_TYPE_STRTAB = 0x03 - SEC_TYPE_NOBITS = 0x08 # e.g. .bss section - SEC_TYPE_INITARRAY = 0x0E - SEC_TYPE_FINIARRAY = 0x0F - - PROG_SEC_TYPES = (SEC_TYPE_PROGBITS, SEC_TYPE_INITARRAY, SEC_TYPE_FINIARRAY) - - LEN_SEC_HEADER = 0x28 - - SEG_TYPE_LOAD = 0x01 - LEN_SEG_HEADER = 0x20 - - def __init__(self, name): - # Load sections from the ELF file - self.name = name - with open(self.name, "rb") as f: - self._read_elf_file(f) - - def get_section(self, section_name): - for s in self.sections: - if s.name == section_name: - return s - raise ValueError("No section %s in ELF file" % section_name) - - def _read_elf_file(self, f): - # read the ELF file header - LEN_FILE_HEADER = 0x34 - try: - ( - ident, - _type, - machine, - _version, - self.entrypoint, - _phoff, - shoff, - _flags, - _ehsize, - _phentsize, - _phnum, - shentsize, - shnum, - shstrndx, - ) = struct.unpack("<16sHHLLLLLHHHHHH", f.read(LEN_FILE_HEADER)) - except struct.error as e: - raise FatalError( - "Failed to read a valid ELF header from %s: %s" % (self.name, e) - ) - - if byte(ident, 0) != 0x7F or ident[1:4] != b"ELF": - raise FatalError("%s has invalid ELF magic header" % self.name) - if machine not in [0x5E, 0xF3]: - raise FatalError( - "%s does not appear to be an Xtensa or an RISCV ELF file. " - "e_machine=%04x" % (self.name, machine) - ) - if shentsize != self.LEN_SEC_HEADER: - raise FatalError( - "%s has unexpected section header entry size 0x%x (not 0x%x)" - % (self.name, shentsize, self.LEN_SEC_HEADER) - ) - if shnum == 0: - raise FatalError("%s has 0 section headers" % (self.name)) - self._read_sections(f, shoff, shnum, shstrndx) - self._read_segments(f, _phoff, _phnum, shstrndx) - - def _read_sections(self, f, section_header_offs, section_header_count, shstrndx): - f.seek(section_header_offs) - len_bytes = section_header_count * self.LEN_SEC_HEADER - section_header = f.read(len_bytes) - if len(section_header) == 0: - raise FatalError( - "No section header found at offset %04x in ELF file." - % section_header_offs - ) - if len(section_header) != (len_bytes): - raise FatalError( - "Only read 0x%x bytes from section header (expected 0x%x.) " - "Truncated ELF file?" % (len(section_header), len_bytes) - ) - - # walk through the section header and extract all sections - section_header_offsets = range(0, len(section_header), self.LEN_SEC_HEADER) - - def read_section_header(offs): - ( - name_offs, - sec_type, - _flags, - lma, - sec_offs, - size, - link, - info, - align, - ) = struct.unpack_from(" 0 - ] - self.sections = prog_sections - self.nobits_sections = [ - ELFSection(lookup_string(n_offs), lma, b"", flags=_flags, align=align) - for (n_offs, _type, lma, size, offs, _flags, align) in nobits_secitons - if lma != 0 and size > 0 - ] - - def _read_segments(self, f, segment_header_offs, segment_header_count, shstrndx): - f.seek(segment_header_offs) - len_bytes = segment_header_count * self.LEN_SEG_HEADER - segment_header = f.read(len_bytes) - if len(segment_header) == 0: - raise FatalError( - "No segment header found at offset %04x in ELF file." - % segment_header_offs - ) - if len(segment_header) != (len_bytes): - raise FatalError( - "Only read 0x%x bytes from segment header (expected 0x%x.) " - "Truncated ELF file?" % (len(segment_header), len_bytes) - ) - - # walk through the segment header and extract all segments - segment_header_offsets = range(0, len(segment_header), self.LEN_SEG_HEADER) - - def read_segment_header(offs): - ( - seg_type, - seg_offs, - _vaddr, - lma, - size, - _memsize, - _flags, - _align, - ) = struct.unpack_from(" 0 - ] - self.segments = prog_segments - - def sha256(self): - # return SHA256 hash of the input ELF file - sha256 = hashlib.sha256() - with open(self.name, "rb") as f: - sha256.update(f.read()) - return sha256.digest() diff --git a/tools/esptool_py/esptool/cmds.py b/tools/esptool_py/esptool/cmds.py deleted file mode 100644 index 4948c9890f..0000000000 --- a/tools/esptool_py/esptool/cmds.py +++ /dev/null @@ -1,1474 +0,0 @@ -# SPDX-FileCopyrightText: 2014-2022 Fredrik Ahlberg, Angus Gratton, -# Espressif Systems (Shanghai) CO LTD, other contributors as noted. -# -# SPDX-License-Identifier: GPL-2.0-or-later - -import hashlib -import io -import os -import struct -import sys -import time -import zlib -import itertools - -from intelhex import IntelHex -from serial import SerialException - -from .bin_image import ELFFile, ImageSegment, LoadFirmwareImage -from .bin_image import ( - ESP8266ROMFirmwareImage, - ESP8266V2FirmwareImage, - ESP8266V3FirmwareImage, -) -from .loader import ( - DEFAULT_CONNECT_ATTEMPTS, - DEFAULT_TIMEOUT, - ERASE_WRITE_TIMEOUT_PER_MB, - ESPLoader, - timeout_per_mb, -) -from .targets import CHIP_DEFS, CHIP_LIST, ROM_LIST -from .uf2_writer import UF2Writer -from .util import ( - FatalError, - NotImplementedInROMError, - NotSupportedError, - UnsupportedCommandError, -) -from .util import ( - div_roundup, - flash_size_bytes, - get_file_size, - hexify, - pad_to, - print_overwrite, -) - -DETECTED_FLASH_SIZES = { - 0x12: "256KB", - 0x13: "512KB", - 0x14: "1MB", - 0x15: "2MB", - 0x16: "4MB", - 0x17: "8MB", - 0x18: "16MB", - 0x19: "32MB", - 0x1A: "64MB", - 0x1B: "128MB", - 0x1C: "256MB", - 0x20: "64MB", - 0x21: "128MB", - 0x22: "256MB", - 0x32: "256KB", - 0x33: "512KB", - 0x34: "1MB", - 0x35: "2MB", - 0x36: "4MB", - 0x37: "8MB", - 0x38: "16MB", - 0x39: "32MB", - 0x3A: "64MB", -} - -FLASH_MODES = {"qio": 0, "qout": 1, "dio": 2, "dout": 3} - - -def detect_chip( - port=ESPLoader.DEFAULT_PORT, - baud=ESPLoader.ESP_ROM_BAUD, - connect_mode="default_reset", - trace_enabled=False, - connect_attempts=DEFAULT_CONNECT_ATTEMPTS, -): - """Use serial access to detect the chip type. - - First, get_security_info command is sent to detect the ID of the chip - (supported only by ESP32-C3 and later, works even in the Secure Download Mode). - If this fails, we reconnect and fall-back to reading the magic number. - It's mapped at a specific ROM address and has a different value on each chip model. - This way we use one memory read and compare it to the magic number for each chip. - - This routine automatically performs ESPLoader.connect() (passing - connect_mode parameter) as part of querying the chip. - """ - inst = None - detect_port = ESPLoader(port, baud, trace_enabled=trace_enabled) - if detect_port.serial_port.startswith("rfc2217:"): - detect_port.USES_RFC2217 = True - detect_port.connect(connect_mode, connect_attempts, detecting=True) - try: - 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", "ESP32-S2") - ]: - # cmd not supported on ESP8266 and ESP32 + ESP32-S2 doesn't return chip_id - if chip_id == cls.IMAGE_CHIP_ID: - inst = cls(detect_port._port, baud, trace_enabled=trace_enabled) - try: - inst.read_reg( - ESPLoader.CHIP_DETECT_MAGIC_REG_ADDR - ) # Dummy read to check Secure Download mode - 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: - # UnsupportedCommandError: ESP8266/ESP32 ROM - # struct.error: ESP32-S2 - # FatalError: ESP8266/ESP32 STUB - print(" Unsupported detection protocol, switching and trying again...") - try: - # ESP32/ESP8266 are reset after an unsupported command, need to reconnect - # (not needed on ESP32-S2) - if not isinstance(e, struct.error): - detect_port.connect( - connect_mode, connect_attempts, detecting=True, warnings=False - ) - print("Detecting chip type...", end="") - sys.stdout.flush() - chip_magic_value = detect_port.read_reg( - ESPLoader.CHIP_DETECT_MAGIC_REG_ADDR - ) - - for cls in ROM_LIST: - if chip_magic_value in cls.CHIP_DETECT_MAGIC_VALUE: - 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. " - "Probably this means Secure Download Mode is enabled, " - "autodetection will not work. Need to manually specify the chip." - ) - finally: - if inst is not None: - print(" %s" % inst.CHIP_NAME, end="") - if detect_port.sync_stub_detected: - inst = inst.STUB_CLASS(inst) - inst.sync_stub_detected = True - print("") # end line - return inst - raise FatalError( - f"{err_msg} Failed to autodetect chip type." - "\nProbably it is unsupported by this version of esptool." - ) - - -# "Operation" commands, executable at command line. One function each -# -# Each function takes either two args (, ) or a single -# argument. - - -def load_ram(esp, args): - image = LoadFirmwareImage(esp.CHIP_NAME, args.filename) - - print("RAM boot...") - for seg in image.segments: - size = len(seg.data) - print("Downloading %d bytes at %08x..." % (size, seg.addr), end=" ") - sys.stdout.flush() - esp.mem_begin( - size, div_roundup(size, esp.ESP_RAM_BLOCK), esp.ESP_RAM_BLOCK, seg.addr - ) - - seq = 0 - while len(seg.data) > 0: - esp.mem_block(seg.data[0 : esp.ESP_RAM_BLOCK], seq) - seg.data = seg.data[esp.ESP_RAM_BLOCK :] - seq += 1 - print("done!") - - print("All segments done, executing at %08x" % image.entrypoint) - esp.mem_finish(image.entrypoint) - - -def read_mem(esp, args): - print("0x%08x = 0x%08x" % (args.address, esp.read_reg(args.address))) - - -def write_mem(esp, args): - esp.write_reg(args.address, args.value, args.mask, 0) - print("Wrote %08x, mask %08x to %08x" % (args.value, args.mask, args.address)) - - -def dump_mem(esp, args): - with open(args.filename, "wb") as f: - for i in range(args.size // 4): - d = esp.read_reg(args.address + (i * 4)) - f.write(struct.pack(b"> 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 " - f"(FlashID={flash_id:#x}, SizeID={size_id:#x}), defaulting to 4MB" - ) - else: - print("Auto-detected Flash size:", flash_size) - args.flash_size = flash_size - return flash_size - - -def _update_image_flash_params(esp, address, args, image): - """ - Modify the flash mode & size bytes if this looks like an executable bootloader image - """ - if len(image) < 8: - return image # not long enough to be a bootloader image - - # unpack the (potential) image header - magic, _, flash_mode, flash_size_freq = struct.unpack("BBBB", image[:4]) - if address != esp.BOOTLOADER_FLASH_OFFSET: - return image # not flashing bootloader offset, so don't modify this - - if (args.flash_mode, args.flash_freq, args.flash_size) == ("keep",) * 3: - return image # all settings are 'keep', not modifying anything - - # easy check if this is an image: does it start with a magic byte? - if magic != esp.ESP_IMAGE_MAGIC: - print( - "Warning: Image file at 0x%x doesn't look like an image file, " - "so not changing any flash settings." % address - ) - return image - - # make sure this really is an image, and not just data that - # starts with esp.ESP_IMAGE_MAGIC (mostly a problem for encrypted - # images that happen to start with a magic byte - try: - test_image = esp.BOOTLOADER_IMAGE(io.BytesIO(image)) - test_image.verify() - except Exception: - print( - "Warning: Image file at 0x%x is not a valid %s image, " - "so not changing any flash settings." % (address, esp.CHIP_NAME) - ) - return image - - # After the 8-byte header comes the extended header for chips others than ESP8266. - # The 15th byte of the extended header indicates if the image is protected by - # a SHA256 checksum. In that case we recalculate the SHA digest after modifying the header. - sha_appended = args.chip != "esp8266" and image[8 + 15] == 1 - - if args.flash_mode != "keep": - flash_mode = FLASH_MODES[args.flash_mode] - - flash_freq = flash_size_freq & 0x0F - if args.flash_freq != "keep": - flash_freq = esp.parse_flash_freq_arg(args.flash_freq) - - flash_size = flash_size_freq & 0xF0 - if args.flash_size != "keep": - flash_size = esp.parse_flash_size_arg(args.flash_size) - - flash_params = struct.pack(b"BB", flash_mode, flash_size + flash_freq) - if flash_params != image[2:4]: - print("Flash params set to 0x%04x" % struct.unpack(">H", flash_params)) - image = image[0:2] + flash_params + image[4:] - - # recalculate the SHA digest if it was appended - if sha_appended: - # Since the changes are only made for images located in the bootloader offset, - # we can assume that the image is always a bootloader image. - # For merged binaries, we check the bootloader SHA when parameters are changed. - image_object = esp.BOOTLOADER_IMAGE(io.BytesIO(image)) - # get the image header, extended header (if present) and data - image_data_before_sha = image[: image_object.data_length] - # get the image data after the SHA digest (primary for merged binaries) - image_data_after_sha = image[ - (image_object.data_length + image_object.SHA256_DIGEST_LEN) : - ] - - sha_digest_calculated = hashlib.sha256(image_data_before_sha).digest() - image = bytes( - itertools.chain( - image_data_before_sha, sha_digest_calculated, image_data_after_sha - ) - ) - - # get the SHA digest newly stored in the image and compare it to the calculated one - image_stored_sha = image[ - image_object.data_length : image_object.data_length - + image_object.SHA256_DIGEST_LEN - ] - - if hexify(sha_digest_calculated) == hexify(image_stored_sha): - print("SHA digest in image updated") - else: - print( - "WARNING: SHA recalculation for binary failed!\n" - f"\tExpected calculated SHA: {hexify(sha_digest_calculated)}\n" - f"\tSHA stored in binary: {hexify(image_stored_sha)}" - ) - - return image - - -def write_flash(esp, args): - # set args.compress based on default behaviour: - # -> if either --compress or --no-compress is set, honour that - # -> otherwise, set --compress unless --no-stub is set - if args.compress is None and not args.no_compress: - args.compress = not args.no_stub - - if not args.force and esp.CHIP_NAME != "ESP8266" and not esp.secure_download_mode: - # Check if secure boot is active - if esp.get_secure_boot_enabled(): - for address, _ in args.addr_filename: - if address < 0x8000: - raise FatalError( - "Secure Boot detected, writing to flash regions < 0x8000 " - "is disabled to protect the bootloader. " - "Use --force to override, " - "please use with caution, otherwise it may brick your device!" - ) - # Check if chip_id and min_rev in image are valid for the target in use - for _, argfile in args.addr_filename: - try: - image = LoadFirmwareImage(esp.CHIP_NAME, argfile) - except (FatalError, struct.error, RuntimeError): - continue - finally: - argfile.seek(0) # LoadFirmwareImage changes the file handle position - if image.chip_id != esp.IMAGE_CHIP_ID: - raise FatalError( - f"{argfile.name} is not an {esp.CHIP_NAME} image. " - "Use --force to flash anyway." - ) - - # this logic below decides which min_rev to use, min_rev or min/max_rev_full - if image.max_rev_full == 0: # image does not have max/min_rev_full fields - use_rev_full_fields = False - elif image.max_rev_full == 65535: # image has default value of max_rev_full - use_rev_full_fields = True - if ( - image.min_rev_full == 0 and image.min_rev != 0 - ): # min_rev_full is not set, min_rev is used - use_rev_full_fields = False - else: # max_rev_full set to a version - use_rev_full_fields = True - - if use_rev_full_fields: - rev = esp.get_chip_revision() - if rev < image.min_rev_full or rev > image.max_rev_full: - error_str = f"{argfile.name} requires chip revision in range " - error_str += ( - f"[v{image.min_rev_full // 100}.{image.min_rev_full % 100} - " - ) - if image.max_rev_full == 65535: - error_str += "max rev not set] " - else: - error_str += ( - f"v{image.max_rev_full // 100}.{image.max_rev_full % 100}] " - ) - error_str += f"(this chip is revision v{rev // 100}.{rev % 100})" - raise FatalError(f"{error_str}. Use --force to flash anyway.") - else: - # In IDF, image.min_rev is set based on Kconfig option. - # For C3 chip, image.min_rev is the Minor revision - # while for the rest chips it is the Major revision. - if esp.CHIP_NAME == "ESP32-C3": - rev = esp.get_minor_chip_version() - else: - rev = esp.get_major_chip_version() - if rev < image.min_rev: - raise FatalError( - f"{argfile.name} requires chip revision " - f"{image.min_rev} or higher (this chip is revision {rev}). " - "Use --force to flash anyway." - ) - - # In case we have encrypted files to write, - # we first do few sanity checks before actual flash - if args.encrypt or args.encrypt_files is not None: - do_write = True - - if not esp.secure_download_mode: - if esp.get_encrypted_download_disabled(): - raise FatalError( - "This chip has encrypt functionality " - "in UART download mode disabled. " - "This is the Flash Encryption configuration for Production mode " - "instead of Development mode." - ) - - crypt_cfg_efuse = esp.get_flash_crypt_config() - - if crypt_cfg_efuse is not None and crypt_cfg_efuse != 0xF: - print("Unexpected FLASH_CRYPT_CONFIG value: 0x%x" % (crypt_cfg_efuse)) - do_write = False - - enc_key_valid = esp.is_flash_encryption_key_valid() - - if not enc_key_valid: - print("Flash encryption key is not programmed") - do_write = False - - # Determine which files list contain the ones to encrypt - files_to_encrypt = args.addr_filename if args.encrypt else args.encrypt_files - - for address, argfile in files_to_encrypt: - if address % esp.FLASH_ENCRYPTED_WRITE_ALIGN: - print( - "File %s address 0x%x is not %d byte aligned, can't flash encrypted" - % (argfile.name, address, esp.FLASH_ENCRYPTED_WRITE_ALIGN) - ) - do_write = False - - if not do_write and not args.ignore_flash_encryption_efuse_setting: - raise FatalError( - "Can't perform encrypted flash write, " - "consult Flash Encryption documentation for more information" - ) - else: - if not args.force and esp.CHIP_NAME != "ESP8266": - # ESP32 does not support `get_security_info()` and `secure_download_mode` - if ( - esp.CHIP_NAME != "ESP32" - and esp.secure_download_mode - and bin(esp.get_security_info()["flash_crypt_cnt"]).count("1") & 1 != 0 - ): - raise FatalError( - "WARNING: Detected flash encryption and " - "secure download mode enabled.\n" - "Flashing plaintext binary may brick your device! " - "Use --force to override the warning." - ) - - if ( - not esp.secure_download_mode - and esp.get_encrypted_download_disabled() - and esp.get_flash_encryption_enabled() - ): - raise FatalError( - "WARNING: Detected flash encryption enabled and " - "download manual encrypt disabled.\n" - "Flashing plaintext binary may brick your device! " - "Use --force to override the warning." - ) - - set_flash_size = ( - flash_size_bytes(args.flash_size) - if args.flash_size not in ["detect", "keep"] - else None - ) - if esp.secure_download_mode: - flash_end = set_flash_size - else: # Check against real flash chip size if not in SDM - flash_end_str = detect_flash_size(esp) - flash_end = flash_size_bytes(flash_end_str) - if set_flash_size and set_flash_size > flash_end: - print( - f"WARNING: Set --flash_size {args.flash_size} " - f"is larger than the available flash size of {flash_end_str}." - ) - - # Verify file sizes fit in the set --flash_size, or real flash size if smaller - flash_end = min(set_flash_size, flash_end) if set_flash_size else flash_end - if flash_end is not None: - for address, argfile in args.addr_filename: - argfile.seek(0, os.SEEK_END) - if address + argfile.tell() > flash_end: - raise FatalError( - f"File {argfile.name} (length {argfile.tell()}) at offset " - f"{address} will not fit in {flash_end} bytes of flash. " - "Change the --flash_size argument, or flashing address." - ) - argfile.seek(0) - - if args.erase_all: - erase_flash(esp, args) - else: - for address, argfile in args.addr_filename: - argfile.seek(0, os.SEEK_END) - write_end = address + argfile.tell() - argfile.seek(0) - bytes_over = address % esp.FLASH_SECTOR_SIZE - if bytes_over != 0: - print( - "WARNING: Flash address {:#010x} is not aligned " - "to a {:#x} byte flash sector. " - "{:#x} bytes before this address will be erased.".format( - address, esp.FLASH_SECTOR_SIZE, bytes_over - ) - ) - # Print the address range of to-be-erased flash memory region - print( - "Flash will be erased from {:#010x} to {:#010x}...".format( - address - bytes_over, - div_roundup(write_end, esp.FLASH_SECTOR_SIZE) - * esp.FLASH_SECTOR_SIZE - - 1, - ) - ) - - """ Create a list describing all the files we have to flash. - Each entry holds an "encrypt" flag marking whether the file needs encryption or not. - This list needs to be sorted. - - First, append to each entry of our addr_filename list the flag args.encrypt - E.g., if addr_filename is [(0x1000, "partition.bin"), (0x8000, "bootloader")], - all_files will be [ - (0x1000, "partition.bin", args.encrypt), - (0x8000, "bootloader", args.encrypt) - ], - where, of course, args.encrypt is either True or False - """ - all_files = [ - (offs, filename, args.encrypt) for (offs, filename) in args.addr_filename - ] - - """ - Now do the same with encrypt_files list, if defined. - In this case, the flag is True - """ - if args.encrypt_files is not None: - encrypted_files_flag = [ - (offs, filename, True) for (offs, filename) in args.encrypt_files - ] - - # Concatenate both lists and sort them. - # As both list are already sorted, we could simply do a merge instead, - # but for the sake of simplicity and because the lists are very small, - # let's use sorted. - all_files = sorted(all_files + encrypted_files_flag, key=lambda x: x[0]) - - for address, argfile, encrypted in all_files: - compress = args.compress - - # Check whether we can compress the current file before flashing - if compress and encrypted: - print("\nWARNING: - compress and encrypt options are mutually exclusive ") - print("Will flash %s uncompressed" % argfile.name) - compress = False - - image = argfile.read() - - if len(image) == 0: - print("WARNING: File %s is empty" % argfile.name) - continue - - image = pad_to(image, esp.FLASH_ENCRYPTED_WRITE_ALIGN if encrypted else 4) - - if args.no_stub: - print("Erasing flash...") - - # It is not possible to write to not aligned addresses without stub, - # so there are added 0xFF (erase) bytes at the beginning of the image - # to align it. - bytes_over = address % esp.FLASH_SECTOR_SIZE - address -= bytes_over - image = b"\xFF" * bytes_over + image - - if not esp.secure_download_mode and not esp.get_secure_boot_enabled(): - image = _update_image_flash_params(esp, address, args, image) - else: - print( - "WARNING: Security features enabled, so not changing any flash settings." - ) - calcmd5 = hashlib.md5(image).hexdigest() - uncsize = len(image) - if compress: - uncimage = image - image = zlib.compress(uncimage, 9) - original_image = image # Save the whole image in case retry is needed - # Try again if reconnect was successful - for attempt in range(1, esp.WRITE_FLASH_ATTEMPTS + 1): - try: - if compress: - # Decompress the compressed binary a block at a time, - # to dynamically calculate the timeout based on the real write size - decompress = zlib.decompressobj() - blocks = esp.flash_defl_begin(uncsize, len(image), address) - else: - blocks = esp.flash_begin( - uncsize, address, begin_rom_encrypted=encrypted - ) - argfile.seek(0) # in case we need it again - seq = 0 - bytes_sent = 0 # bytes sent on wire - bytes_written = 0 # bytes written to flash - t = time.time() - - timeout = DEFAULT_TIMEOUT - - while len(image) > 0: - print_overwrite( - "Writing at 0x%08x... (%d %%)" - % (address + bytes_written, 100 * (seq + 1) // blocks) - ) - sys.stdout.flush() - block = image[0 : esp.FLASH_WRITE_SIZE] - if compress: - # feeding each compressed block into the decompressor lets us - # see block-by-block how much will be written - block_uncompressed = len(decompress.decompress(block)) - bytes_written += block_uncompressed - block_timeout = max( - DEFAULT_TIMEOUT, - timeout_per_mb( - ERASE_WRITE_TIMEOUT_PER_MB, block_uncompressed - ), - ) - if not esp.IS_STUB: - timeout = block_timeout # ROM code writes block to flash before ACKing - esp.flash_defl_block(block, seq, timeout=timeout) - if esp.IS_STUB: - # Stub ACKs when block is received, - # then writes to flash while receiving the block after it - timeout = block_timeout - else: - # Pad the last block - block = block + b"\xff" * (esp.FLASH_WRITE_SIZE - len(block)) - if encrypted: - esp.flash_encrypt_block(block, seq) - else: - esp.flash_block(block, seq) - bytes_written += len(block) - bytes_sent += len(block) - image = image[esp.FLASH_WRITE_SIZE :] - seq += 1 - break - except SerialException: - if attempt == esp.WRITE_FLASH_ATTEMPTS or encrypted: - # Already retried once or encrypted mode is disabled because of security reasons - raise - print("\nLost connection, retrying...") - esp._port.close() - print("Waiting for the chip to reconnect", end="") - for _ in range(DEFAULT_CONNECT_ATTEMPTS): - try: - time.sleep(1) - esp._port.open() - print() # Print new line which was suppressed by print(".") - esp.connect() - if esp.IS_STUB: - # Hack to bypass the stub overwrite check - esp.IS_STUB = False - # Reflash stub because chip was reset - esp = esp.run_stub() - image = original_image - break - except SerialException: - print(".", end="") - sys.stdout.flush() - else: - raise # Reconnect limit reached - - if esp.IS_STUB: - # Stub only writes each block to flash after 'ack'ing the receive, - # so do a final dummy operation which will not be 'ack'ed - # until the last block has actually been written out to flash - esp.read_reg(ESPLoader.CHIP_DETECT_MAGIC_REG_ADDR, timeout=timeout) - - t = time.time() - t - speed_msg = "" - if compress: - if t > 0.0: - speed_msg = " (effective %.1f kbit/s)" % (uncsize / t * 8 / 1000) - print_overwrite( - "Wrote %d bytes (%d compressed) at 0x%08x in %.1f seconds%s..." - % (uncsize, bytes_sent, address, t, speed_msg), - last_line=True, - ) - else: - if t > 0.0: - speed_msg = " (%.1f kbit/s)" % (bytes_written / t * 8 / 1000) - print_overwrite( - "Wrote %d bytes at 0x%08x in %.1f seconds%s..." - % (bytes_written, address, t, speed_msg), - last_line=True, - ) - - if not encrypted and not esp.secure_download_mode: - try: - res = esp.flash_md5sum(address, uncsize) - if res != calcmd5: - print("File md5: %s" % calcmd5) - print("Flash md5: %s" % res) - print( - "MD5 of 0xFF is %s" - % (hashlib.md5(b"\xff" * uncsize).hexdigest()) - ) - raise FatalError("MD5 of file does not match data in flash!") - else: - print("Hash of data verified.") - except NotImplementedInROMError: - pass - - print("\nLeaving...") - - if esp.IS_STUB: - # skip sending flash_finish to ROM loader here, - # as it causes the loader to exit and run user code - esp.flash_begin(0, 0) - - # Get the "encrypted" flag for the last file flashed - # Note: all_files list contains triplets like: - # (address: Integer, filename: String, encrypted: Boolean) - last_file_encrypted = all_files[-1][2] - - # Check whether the last file flashed was compressed or not - if args.compress and not last_file_encrypted: - esp.flash_defl_finish(False) - else: - esp.flash_finish(False) - - if args.verify: - print("Verifying just-written flash...") - print( - "(This option is deprecated, " - "flash contents are now always read back after flashing.)" - ) - # If some encrypted files have been flashed, - # print a warning saying that we won't check them - if args.encrypt or args.encrypt_files is not None: - print("WARNING: - cannot verify encrypted files, they will be ignored") - # Call verify_flash function only if there is at least - # one non-encrypted file flashed - if not args.encrypt: - verify_flash(esp, args) - - -def image_info(args): - def v2(): - def get_key_from_value(dict, val): - """Get key from value in dictionary""" - for key, value in dict.items(): - if value == val: - return key - return None - - print() - title = "{} image header".format(args.chip.upper()) - print(title) - print("=" * len(title)) - print("Image version: {}".format(image.version)) - print( - "Entry point: {:#8x}".format(image.entrypoint) - if image.entrypoint != 0 - else "Entry point not set" - ) - - print("Segments: {}".format(len(image.segments))) - - # Flash size - flash_s_bits = image.flash_size_freq & 0xF0 # high four bits - flash_s = get_key_from_value(image.ROM_LOADER.FLASH_SIZES, flash_s_bits) - print( - "Flash size: {}".format(flash_s) - if flash_s is not None - else "WARNING: Invalid flash size ({:#02x})".format(flash_s_bits) - ) - - # Flash frequency - flash_fr_bits = image.flash_size_freq & 0x0F # low four bits - flash_fr = get_key_from_value(image.ROM_LOADER.FLASH_FREQUENCY, flash_fr_bits) - print( - "Flash freq: {}".format(flash_fr) - if flash_fr is not None - else "WARNING: Invalid flash frequency ({:#02x})".format(flash_fr_bits) - ) - - # Flash mode - flash_mode = get_key_from_value(FLASH_MODES, image.flash_mode) - print( - "Flash mode: {}".format(flash_mode.upper()) - if flash_mode is not None - else "WARNING: Invalid flash mode ({})".format(image.flash_mode) - ) - - # Extended header (ESP32 and later only) - if args.chip != "esp8266": - print() - title = "{} extended image header".format(args.chip.upper()) - print(title) - print("=" * len(title)) - 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}, " - "cs0_drv: {:#02x}, hd_drv: {:#02x}, wp_drv: {:#02x}".format( - image.clk_drv, - image.q_drv, - image.d_drv, - image.cs_drv, - image.hd_drv, - image.wp_drv, - ) - ) - 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}, " - f"(legacy min_rev = {image.min_rev})" - ) - print( - "Maximal chip revision: " - f"v{image.max_rev_full // 100}.{image.max_rev_full % 100}" - ) - print() - - # Segments overview - title = "Segments information" - print(title) - print("=" * len(title)) - headers_str = "{:>7} {:>7} {:>10} {:>10} {:10}" - print( - headers_str.format( - "Segment", "Length", "Load addr", "File offs", "Memory types" - ) - ) - print( - "{} {} {} {} {}".format("-" * 7, "-" * 7, "-" * 10, "-" * 10, "-" * 12) - ) - format_str = "{:7} {:#07x} {:#010x} {:#010x} {}" - app_desc = None - bootloader_desc = None - for idx, seg in enumerate(image.segments): - 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) - ) - print() - - # Footer - title = f"{args.chip.upper()} image footer" - print(title) - print("=" * len(title)) - calc_checksum = image.calculate_checksum() - print( - "Checksum: {:#02x} ({})".format( - image.checksum, - ( - "valid" - if image.checksum == calc_checksum - else "invalid - calculated {:02x}".format(calc_checksum) - ), - ) - ) - try: - digest_msg = "Not appended" - if image.append_digest: - is_valid = image.stored_digest == image.calc_digest - digest_msg = "{} ({})".format( - hexify(image.calc_digest, uppercase=False), - "valid" if is_valid else "invalid", - ) - print("Validation hash: {}".format(digest_msg)) - except AttributeError: - pass # ESP8266 image has no append_digest field - - if app_desc: - APP_DESC_STRUCT_FMT = "