esptool 5.1.0__tar.gz → 5.2.dev1__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (170) hide show
  1. {esptool-5.1.0/esptool.egg-info → esptool-5.2.dev1}/PKG-INFO +2 -2
  2. {esptool-5.1.0 → esptool-5.2.dev1}/espefuse/__init__.py +4 -3
  3. {esptool-5.1.0 → esptool-5.2.dev1}/espefuse/efuse/esp32p4/emulate_efuse_controller.py +1 -1
  4. {esptool-5.1.0 → esptool-5.2.dev1}/espefuse/efuse/esp32p4/fields.py +94 -5
  5. {esptool-5.1.0 → esptool-5.2.dev1}/espefuse/efuse/esp32p4/mem_definition.py +15 -0
  6. esptool-5.2.dev1/espefuse/efuse/esp32s31/__init__.py +5 -0
  7. esptool-5.2.dev1/espefuse/efuse/esp32s31/emulate_efuse_controller.py +92 -0
  8. esptool-5.2.dev1/espefuse/efuse/esp32s31/fields.py +443 -0
  9. esptool-5.2.dev1/espefuse/efuse/esp32s31/mem_definition.py +158 -0
  10. esptool-5.2.dev1/espefuse/efuse/esp32s31/operations.py +297 -0
  11. {esptool-5.1.0 → esptool-5.2.dev1}/espefuse/efuse_defs/esp32p4_v3.0.yaml +56 -14
  12. esptool-5.2.dev1/espefuse/efuse_defs/esp32s31.yaml +122 -0
  13. {esptool-5.1.0 → esptool-5.2.dev1}/espefuse/efuse_interface.py +2 -0
  14. {esptool-5.1.0 → esptool-5.2.dev1}/espsecure/__init__.py +1 -5
  15. {esptool-5.1.0 → esptool-5.2.dev1}/espsecure/esp_hsm_sign/__init__.py +5 -3
  16. {esptool-5.1.0 → esptool-5.2.dev1}/esptool/__init__.py +48 -4
  17. {esptool-5.1.0 → esptool-5.2.dev1}/esptool/bin_image.py +11 -0
  18. {esptool-5.1.0 → esptool-5.2.dev1}/esptool/cmds.py +2 -1
  19. {esptool-5.1.0 → esptool-5.2.dev1}/esptool/targets/__init__.py +2 -0
  20. {esptool-5.1.0 → esptool-5.2.dev1}/esptool/targets/esp32c2.py +20 -19
  21. {esptool-5.1.0 → esptool-5.2.dev1}/esptool/targets/esp32c3.py +10 -1
  22. {esptool-5.1.0 → esptool-5.2.dev1}/esptool/targets/esp32c5.py +18 -3
  23. {esptool-5.1.0 → esptool-5.2.dev1}/esptool/targets/esp32c6.py +23 -4
  24. {esptool-5.1.0 → esptool-5.2.dev1}/esptool/targets/esp32c61.py +13 -0
  25. {esptool-5.1.0 → esptool-5.2.dev1}/esptool/targets/esp32p4.py +12 -2
  26. esptool-5.2.dev1/esptool/targets/esp32s31.py +221 -0
  27. {esptool-5.1.0 → esptool-5.2.dev1}/esptool/targets/stub_flasher/1/README.md +1 -1
  28. esptool-5.2.dev1/esptool/targets/stub_flasher/1/esp32c5.json +8 -0
  29. {esptool-5.1.0 → esptool-5.2.dev1/esptool.egg-info}/PKG-INFO +2 -2
  30. {esptool-5.1.0 → esptool-5.2.dev1}/esptool.egg-info/SOURCES.txt +7 -0
  31. {esptool-5.1.0 → esptool-5.2.dev1}/esptool.egg-info/requires.txt +1 -1
  32. {esptool-5.1.0 → esptool-5.2.dev1}/pyproject.toml +1 -1
  33. esptool-5.1.0/esptool/targets/stub_flasher/1/esp32c5.json +0 -8
  34. {esptool-5.1.0 → esptool-5.2.dev1}/LICENSE +0 -0
  35. {esptool-5.1.0 → esptool-5.2.dev1}/MANIFEST.in +0 -0
  36. {esptool-5.1.0 → esptool-5.2.dev1}/README.md +0 -0
  37. {esptool-5.1.0 → esptool-5.2.dev1}/esp_rfc2217_server/__init__.py +0 -0
  38. {esptool-5.1.0 → esptool-5.2.dev1}/esp_rfc2217_server/__main__.py +0 -0
  39. {esptool-5.1.0 → esptool-5.2.dev1}/esp_rfc2217_server/esp_port_manager.py +0 -0
  40. {esptool-5.1.0 → esptool-5.2.dev1}/esp_rfc2217_server/redirector.py +0 -0
  41. {esptool-5.1.0 → esptool-5.2.dev1}/esp_rfc2217_server.py +0 -0
  42. {esptool-5.1.0 → esptool-5.2.dev1}/espefuse/__main__.py +0 -0
  43. {esptool-5.1.0 → esptool-5.2.dev1}/espefuse/cli_util.py +0 -0
  44. {esptool-5.1.0 → esptool-5.2.dev1}/espefuse/efuse/__init__.py +0 -0
  45. {esptool-5.1.0 → esptool-5.2.dev1}/espefuse/efuse/base_fields.py +0 -0
  46. {esptool-5.1.0 → esptool-5.2.dev1}/espefuse/efuse/base_operations.py +0 -0
  47. {esptool-5.1.0 → esptool-5.2.dev1}/espefuse/efuse/csv_table_parser.py +0 -0
  48. {esptool-5.1.0 → esptool-5.2.dev1}/espefuse/efuse/emulate_efuse_controller_base.py +0 -0
  49. {esptool-5.1.0 → esptool-5.2.dev1}/espefuse/efuse/esp32/__init__.py +0 -0
  50. {esptool-5.1.0 → esptool-5.2.dev1}/espefuse/efuse/esp32/emulate_efuse_controller.py +0 -0
  51. {esptool-5.1.0 → esptool-5.2.dev1}/espefuse/efuse/esp32/fields.py +0 -0
  52. {esptool-5.1.0 → esptool-5.2.dev1}/espefuse/efuse/esp32/mem_definition.py +0 -0
  53. {esptool-5.1.0 → esptool-5.2.dev1}/espefuse/efuse/esp32/operations.py +0 -0
  54. {esptool-5.1.0 → esptool-5.2.dev1}/espefuse/efuse/esp32c2/__init__.py +0 -0
  55. {esptool-5.1.0 → esptool-5.2.dev1}/espefuse/efuse/esp32c2/emulate_efuse_controller.py +0 -0
  56. {esptool-5.1.0 → esptool-5.2.dev1}/espefuse/efuse/esp32c2/fields.py +0 -0
  57. {esptool-5.1.0 → esptool-5.2.dev1}/espefuse/efuse/esp32c2/mem_definition.py +0 -0
  58. {esptool-5.1.0 → esptool-5.2.dev1}/espefuse/efuse/esp32c2/operations.py +0 -0
  59. {esptool-5.1.0 → esptool-5.2.dev1}/espefuse/efuse/esp32c3/__init__.py +0 -0
  60. {esptool-5.1.0 → esptool-5.2.dev1}/espefuse/efuse/esp32c3/emulate_efuse_controller.py +0 -0
  61. {esptool-5.1.0 → esptool-5.2.dev1}/espefuse/efuse/esp32c3/fields.py +0 -0
  62. {esptool-5.1.0 → esptool-5.2.dev1}/espefuse/efuse/esp32c3/mem_definition.py +0 -0
  63. {esptool-5.1.0 → esptool-5.2.dev1}/espefuse/efuse/esp32c3/operations.py +0 -0
  64. {esptool-5.1.0 → esptool-5.2.dev1}/espefuse/efuse/esp32c5/__init__.py +0 -0
  65. {esptool-5.1.0 → esptool-5.2.dev1}/espefuse/efuse/esp32c5/emulate_efuse_controller.py +0 -0
  66. {esptool-5.1.0 → esptool-5.2.dev1}/espefuse/efuse/esp32c5/fields.py +0 -0
  67. {esptool-5.1.0 → esptool-5.2.dev1}/espefuse/efuse/esp32c5/mem_definition.py +0 -0
  68. {esptool-5.1.0 → esptool-5.2.dev1}/espefuse/efuse/esp32c5/operations.py +0 -0
  69. {esptool-5.1.0 → esptool-5.2.dev1}/espefuse/efuse/esp32c6/__init__.py +0 -0
  70. {esptool-5.1.0 → esptool-5.2.dev1}/espefuse/efuse/esp32c6/emulate_efuse_controller.py +0 -0
  71. {esptool-5.1.0 → esptool-5.2.dev1}/espefuse/efuse/esp32c6/fields.py +0 -0
  72. {esptool-5.1.0 → esptool-5.2.dev1}/espefuse/efuse/esp32c6/mem_definition.py +0 -0
  73. {esptool-5.1.0 → esptool-5.2.dev1}/espefuse/efuse/esp32c6/operations.py +0 -0
  74. {esptool-5.1.0 → esptool-5.2.dev1}/espefuse/efuse/esp32c61/__init__.py +0 -0
  75. {esptool-5.1.0 → esptool-5.2.dev1}/espefuse/efuse/esp32c61/emulate_efuse_controller.py +0 -0
  76. {esptool-5.1.0 → esptool-5.2.dev1}/espefuse/efuse/esp32c61/fields.py +0 -0
  77. {esptool-5.1.0 → esptool-5.2.dev1}/espefuse/efuse/esp32c61/mem_definition.py +0 -0
  78. {esptool-5.1.0 → esptool-5.2.dev1}/espefuse/efuse/esp32c61/operations.py +0 -0
  79. {esptool-5.1.0 → esptool-5.2.dev1}/espefuse/efuse/esp32h2/__init__.py +0 -0
  80. {esptool-5.1.0 → esptool-5.2.dev1}/espefuse/efuse/esp32h2/emulate_efuse_controller.py +0 -0
  81. {esptool-5.1.0 → esptool-5.2.dev1}/espefuse/efuse/esp32h2/fields.py +0 -0
  82. {esptool-5.1.0 → esptool-5.2.dev1}/espefuse/efuse/esp32h2/mem_definition.py +0 -0
  83. {esptool-5.1.0 → esptool-5.2.dev1}/espefuse/efuse/esp32h2/operations.py +0 -0
  84. {esptool-5.1.0 → esptool-5.2.dev1}/espefuse/efuse/esp32h21/__init__.py +0 -0
  85. {esptool-5.1.0 → esptool-5.2.dev1}/espefuse/efuse/esp32h21/emulate_efuse_controller.py +0 -0
  86. {esptool-5.1.0 → esptool-5.2.dev1}/espefuse/efuse/esp32h21/fields.py +0 -0
  87. {esptool-5.1.0 → esptool-5.2.dev1}/espefuse/efuse/esp32h21/mem_definition.py +0 -0
  88. {esptool-5.1.0 → esptool-5.2.dev1}/espefuse/efuse/esp32h21/operations.py +0 -0
  89. {esptool-5.1.0 → esptool-5.2.dev1}/espefuse/efuse/esp32h4/__init__.py +0 -0
  90. {esptool-5.1.0 → esptool-5.2.dev1}/espefuse/efuse/esp32h4/emulate_efuse_controller.py +0 -0
  91. {esptool-5.1.0 → esptool-5.2.dev1}/espefuse/efuse/esp32h4/fields.py +0 -0
  92. {esptool-5.1.0 → esptool-5.2.dev1}/espefuse/efuse/esp32h4/mem_definition.py +0 -0
  93. {esptool-5.1.0 → esptool-5.2.dev1}/espefuse/efuse/esp32h4/operations.py +0 -0
  94. {esptool-5.1.0 → esptool-5.2.dev1}/espefuse/efuse/esp32p4/__init__.py +0 -0
  95. {esptool-5.1.0 → esptool-5.2.dev1}/espefuse/efuse/esp32p4/operations.py +0 -0
  96. {esptool-5.1.0 → esptool-5.2.dev1}/espefuse/efuse/esp32s2/__init__.py +0 -0
  97. {esptool-5.1.0 → esptool-5.2.dev1}/espefuse/efuse/esp32s2/emulate_efuse_controller.py +0 -0
  98. {esptool-5.1.0 → esptool-5.2.dev1}/espefuse/efuse/esp32s2/fields.py +0 -0
  99. {esptool-5.1.0 → esptool-5.2.dev1}/espefuse/efuse/esp32s2/mem_definition.py +0 -0
  100. {esptool-5.1.0 → esptool-5.2.dev1}/espefuse/efuse/esp32s2/operations.py +0 -0
  101. {esptool-5.1.0 → esptool-5.2.dev1}/espefuse/efuse/esp32s3/__init__.py +0 -0
  102. {esptool-5.1.0 → esptool-5.2.dev1}/espefuse/efuse/esp32s3/emulate_efuse_controller.py +0 -0
  103. {esptool-5.1.0 → esptool-5.2.dev1}/espefuse/efuse/esp32s3/fields.py +0 -0
  104. {esptool-5.1.0 → esptool-5.2.dev1}/espefuse/efuse/esp32s3/mem_definition.py +0 -0
  105. {esptool-5.1.0 → esptool-5.2.dev1}/espefuse/efuse/esp32s3/operations.py +0 -0
  106. {esptool-5.1.0 → esptool-5.2.dev1}/espefuse/efuse/mem_definition_base.py +0 -0
  107. {esptool-5.1.0 → esptool-5.2.dev1}/espefuse/efuse/util.py +0 -0
  108. {esptool-5.1.0 → esptool-5.2.dev1}/espefuse/efuse_defs/esp32.yaml +0 -0
  109. {esptool-5.1.0 → esptool-5.2.dev1}/espefuse/efuse_defs/esp32c2.yaml +0 -0
  110. {esptool-5.1.0 → esptool-5.2.dev1}/espefuse/efuse_defs/esp32c3.yaml +0 -0
  111. {esptool-5.1.0 → esptool-5.2.dev1}/espefuse/efuse_defs/esp32c5.yaml +0 -0
  112. {esptool-5.1.0 → esptool-5.2.dev1}/espefuse/efuse_defs/esp32c6.yaml +0 -0
  113. {esptool-5.1.0 → esptool-5.2.dev1}/espefuse/efuse_defs/esp32c61.yaml +0 -0
  114. {esptool-5.1.0 → esptool-5.2.dev1}/espefuse/efuse_defs/esp32h2.yaml +0 -0
  115. {esptool-5.1.0 → esptool-5.2.dev1}/espefuse/efuse_defs/esp32h21.yaml +0 -0
  116. {esptool-5.1.0 → esptool-5.2.dev1}/espefuse/efuse_defs/esp32h2_v0.0_v1.1.yaml +0 -0
  117. {esptool-5.1.0 → esptool-5.2.dev1}/espefuse/efuse_defs/esp32h4.yaml +0 -0
  118. {esptool-5.1.0 → esptool-5.2.dev1}/espefuse/efuse_defs/esp32p4.yaml +0 -0
  119. {esptool-5.1.0 → esptool-5.2.dev1}/espefuse/efuse_defs/esp32s2.yaml +0 -0
  120. {esptool-5.1.0 → esptool-5.2.dev1}/espefuse/efuse_defs/esp32s3.yaml +0 -0
  121. {esptool-5.1.0 → esptool-5.2.dev1}/espefuse.py +0 -0
  122. {esptool-5.1.0 → esptool-5.2.dev1}/espsecure/__main__.py +0 -0
  123. {esptool-5.1.0 → esptool-5.2.dev1}/espsecure/esp_hsm_sign/exceptions.py +0 -0
  124. {esptool-5.1.0 → esptool-5.2.dev1}/espsecure.py +0 -0
  125. {esptool-5.1.0 → esptool-5.2.dev1}/esptool/__main__.py +0 -0
  126. {esptool-5.1.0 → esptool-5.2.dev1}/esptool/cli_util.py +0 -0
  127. {esptool-5.1.0 → esptool-5.2.dev1}/esptool/config.py +0 -0
  128. {esptool-5.1.0 → esptool-5.2.dev1}/esptool/loader.py +0 -0
  129. {esptool-5.1.0 → esptool-5.2.dev1}/esptool/logger.py +0 -0
  130. {esptool-5.1.0 → esptool-5.2.dev1}/esptool/reset.py +0 -0
  131. {esptool-5.1.0 → esptool-5.2.dev1}/esptool/targets/esp32.py +0 -0
  132. {esptool-5.1.0 → esptool-5.2.dev1}/esptool/targets/esp32h2.py +0 -0
  133. {esptool-5.1.0 → esptool-5.2.dev1}/esptool/targets/esp32h21.py +0 -0
  134. {esptool-5.1.0 → esptool-5.2.dev1}/esptool/targets/esp32h4.py +0 -0
  135. {esptool-5.1.0 → esptool-5.2.dev1}/esptool/targets/esp32s2.py +0 -0
  136. {esptool-5.1.0 → esptool-5.2.dev1}/esptool/targets/esp32s3.py +0 -0
  137. {esptool-5.1.0 → esptool-5.2.dev1}/esptool/targets/esp8266.py +0 -0
  138. {esptool-5.1.0 → esptool-5.2.dev1}/esptool/targets/stub_flasher/1/esp32.json +0 -0
  139. {esptool-5.1.0 → esptool-5.2.dev1}/esptool/targets/stub_flasher/1/esp32c2.json +0 -0
  140. {esptool-5.1.0 → esptool-5.2.dev1}/esptool/targets/stub_flasher/1/esp32c3.json +0 -0
  141. {esptool-5.1.0 → esptool-5.2.dev1}/esptool/targets/stub_flasher/1/esp32c6.json +0 -0
  142. {esptool-5.1.0 → esptool-5.2.dev1}/esptool/targets/stub_flasher/1/esp32c61.json +0 -0
  143. {esptool-5.1.0 → esptool-5.2.dev1}/esptool/targets/stub_flasher/1/esp32h2.json +0 -0
  144. {esptool-5.1.0 → esptool-5.2.dev1}/esptool/targets/stub_flasher/1/esp32p4.json +0 -0
  145. {esptool-5.1.0 → esptool-5.2.dev1}/esptool/targets/stub_flasher/1/esp32p4rc1.json +0 -0
  146. {esptool-5.1.0 → esptool-5.2.dev1}/esptool/targets/stub_flasher/1/esp32s2.json +0 -0
  147. {esptool-5.1.0 → esptool-5.2.dev1}/esptool/targets/stub_flasher/1/esp32s3.json +0 -0
  148. {esptool-5.1.0 → esptool-5.2.dev1}/esptool/targets/stub_flasher/1/esp8266.json +0 -0
  149. {esptool-5.1.0 → esptool-5.2.dev1}/esptool/targets/stub_flasher/2/LICENSE-APACHE +0 -0
  150. {esptool-5.1.0 → esptool-5.2.dev1}/esptool/targets/stub_flasher/2/LICENSE-MIT +0 -0
  151. {esptool-5.1.0 → esptool-5.2.dev1}/esptool/targets/stub_flasher/2/README.md +0 -0
  152. {esptool-5.1.0 → esptool-5.2.dev1}/esptool/targets/stub_flasher/2/esp32.json +0 -0
  153. {esptool-5.1.0 → esptool-5.2.dev1}/esptool/targets/stub_flasher/2/esp32c2.json +0 -0
  154. {esptool-5.1.0 → esptool-5.2.dev1}/esptool/targets/stub_flasher/2/esp32c3.json +0 -0
  155. {esptool-5.1.0 → esptool-5.2.dev1}/esptool/targets/stub_flasher/2/esp32c5.json +0 -0
  156. {esptool-5.1.0 → esptool-5.2.dev1}/esptool/targets/stub_flasher/2/esp32c6.json +0 -0
  157. {esptool-5.1.0 → esptool-5.2.dev1}/esptool/targets/stub_flasher/2/esp32c61.json +0 -0
  158. {esptool-5.1.0 → esptool-5.2.dev1}/esptool/targets/stub_flasher/2/esp32h2.json +0 -0
  159. {esptool-5.1.0 → esptool-5.2.dev1}/esptool/targets/stub_flasher/2/esp32p4.json +0 -0
  160. {esptool-5.1.0 → esptool-5.2.dev1}/esptool/targets/stub_flasher/2/esp32s2.json +0 -0
  161. {esptool-5.1.0 → esptool-5.2.dev1}/esptool/targets/stub_flasher/2/esp32s3.json +0 -0
  162. {esptool-5.1.0 → esptool-5.2.dev1}/esptool/targets/stub_flasher/2/esp8266.json +0 -0
  163. {esptool-5.1.0 → esptool-5.2.dev1}/esptool/uf2_writer.py +0 -0
  164. {esptool-5.1.0 → esptool-5.2.dev1}/esptool/util.py +0 -0
  165. {esptool-5.1.0 → esptool-5.2.dev1}/esptool.egg-info/dependency_links.txt +0 -0
  166. {esptool-5.1.0 → esptool-5.2.dev1}/esptool.egg-info/entry_points.txt +0 -0
  167. {esptool-5.1.0 → esptool-5.2.dev1}/esptool.egg-info/top_level.txt +0 -0
  168. {esptool-5.1.0 → esptool-5.2.dev1}/esptool.py +0 -0
  169. {esptool-5.1.0 → esptool-5.2.dev1}/setup.cfg +0 -0
  170. {esptool-5.1.0 → esptool-5.2.dev1}/setup.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: esptool
3
- Version: 5.1.0
3
+ Version: 5.2.dev1
4
4
  Summary: A serial utility for flashing, provisioning, and interacting with Espressif SoCs.
5
5
  Author: Fredrik Ahlberg (themadinventor), Angus Gratton (projectgus), Espressif Systems
6
6
  License: GPLv2+
@@ -31,7 +31,7 @@ Requires-Dist: pyserial>=3.3
31
31
  Requires-Dist: reedsolo<1.8,>=1.5.3
32
32
  Requires-Dist: PyYAML>=5.1
33
33
  Requires-Dist: intelhex
34
- Requires-Dist: rich_click
34
+ Requires-Dist: rich_click<1.9.0
35
35
  Requires-Dist: click<9
36
36
  Provides-Extra: dev
37
37
  Requires-Dist: pyelftools; extra == "dev"
@@ -93,9 +93,10 @@ __all__ = [
93
93
  "Use with caution!",
94
94
  )
95
95
  @click.option(
96
- "--postpone",
97
- is_flag=True,
98
- help="Postpone burning some eFuses from BLOCK0 at the end.",
96
+ "--postpone/--no-postpone",
97
+ default=True,
98
+ help="Postpone burning some eFuses from BLOCK0 at the end "
99
+ "(enabled by default, can be disabled with --no-postpone).",
99
100
  )
100
101
  @click.option(
101
102
  "--extend-efuse-table",
@@ -27,7 +27,7 @@ class EmulateEfuseController(EmulateEfuseControllerBase):
27
27
  """ esptool method start >>"""
28
28
 
29
29
  def get_major_chip_version(self):
30
- return 0
30
+ return 3
31
31
 
32
32
  def get_minor_chip_version(self):
33
33
  return 0
@@ -290,9 +290,50 @@ class EfuseField(base_fields.EfuseFieldBase):
290
290
  "t_sensor": EfuseTempSensor,
291
291
  "adc_tp": EfuseAdcPointCalibration,
292
292
  "wafer": EfuseWafer,
293
+ "recovery_bootloader": EfuseBtldrRecoveryField,
293
294
  }.get(efuse.class_type, EfuseField)(parent, efuse)
294
295
 
295
296
 
297
+ class EfuseBtldrRecoveryField(EfuseField):
298
+ """
299
+ Handles composite recovery bootloader flash sector fields for ESP32-P4 ECO5 (v3.0).
300
+ Combines/splits the following eFuse fields:
301
+ - RECOVERY_BOOTLOADER_FLASH_SECTOR_0_1 (bits 1:0, uint:2)
302
+ - RECOVERY_BOOTLOADER_FLASH_SECTOR_2_2 (bit 2, bool)
303
+ - RECOVERY_BOOTLOADER_FLASH_SECTOR_3_6 (bits 6:3, uint:4)
304
+ - RECOVERY_BOOTLOADER_FLASH_SECTOR_7_7 (bit 7, bool)
305
+ - RECOVERY_BOOTLOADER_FLASH_SECTOR_8_10 (bits 10:8, uint:3)
306
+ - RECOVERY_BOOTLOADER_FLASH_SECTOR_11_11(bit 11, bool)
307
+ """
308
+
309
+ FIELD_ORDER = [
310
+ ("RECOVERY_BOOTLOADER_FLASH_SECTOR_0_1", 0, 2),
311
+ ("RECOVERY_BOOTLOADER_FLASH_SECTOR_2_2", 2, 1),
312
+ ("RECOVERY_BOOTLOADER_FLASH_SECTOR_3_6", 3, 4),
313
+ ("RECOVERY_BOOTLOADER_FLASH_SECTOR_7_7", 7, 1),
314
+ ("RECOVERY_BOOTLOADER_FLASH_SECTOR_8_10", 8, 3),
315
+ ("RECOVERY_BOOTLOADER_FLASH_SECTOR_11_11", 11, 1),
316
+ ]
317
+
318
+ def get(self, from_read=True):
319
+ value = 0
320
+ for field_name, bit_offset, bit_len in self.FIELD_ORDER:
321
+ field = self.parent[field_name]
322
+ field_val = field.get(from_read)
323
+ assert field.bit_len == bit_len
324
+ value |= (field_val & ((1 << bit_len) - 1)) << bit_offset
325
+ return value
326
+
327
+ def save(self, new_value):
328
+ for field_name, bit_offset, bit_len in self.FIELD_ORDER:
329
+ field = self.parent[field_name]
330
+ field_val = (new_value >> bit_offset) & ((1 << bit_len) - 1)
331
+ field.save(field_val)
332
+ log.print(
333
+ f"\t - '{field.name}' {field.get_bitstring()} -> {field.get_bitstring(from_read=False)}"
334
+ )
335
+
336
+
296
337
  class EfuseWafer(EfuseField):
297
338
  def get(self, from_read=True):
298
339
  hi_bits = self.parent["WAFER_VERSION_MAJOR_HI"].get(from_read)
@@ -389,10 +430,11 @@ class EfuseMacField(EfuseField):
389
430
 
390
431
  # fmt: off
391
432
  class EfuseKeyPurposeField(EfuseField):
392
- key_purpose_len = 4 # bits for key purpose
433
+ key_purpose_len = 5 # bits for key purpose
393
434
  KeyPurposeType = tuple[str, int, str | None, str | None, str]
394
435
  KEY_PURPOSES: list[KeyPurposeType] = [
395
436
  ("USER", 0, None, None, "no_need_rd_protect"), # User purposes (software-only use)
437
+ ("ECDSA_KEY_P256", 1, None, "Reverse", "need_rd_protect"), # ECDSA key P256
396
438
  ("ECDSA_KEY", 1, None, "Reverse", "need_rd_protect"), # ECDSA key
397
439
  ("XTS_AES_256_KEY_1", 2, None, "Reverse", "need_rd_protect"), # XTS_AES_256_KEY_1 (flash/PSRAM encryption)
398
440
  ("XTS_AES_256_KEY_2", 3, None, "Reverse", "need_rd_protect"), # XTS_AES_256_KEY_2 (flash/PSRAM encryption)
@@ -406,6 +448,10 @@ class EfuseKeyPurposeField(EfuseField):
406
448
  ("SECURE_BOOT_DIGEST2", 11, "DIGEST", None, "no_need_rd_protect"), # SECURE_BOOT_DIGEST2 (Secure Boot key digest)
407
449
  ("KM_INIT_KEY", 12, None, None, "need_rd_protect"), # init key that is used for the generation of AES/ECDSA key
408
450
  ("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
451
+ ("ECDSA_KEY_P192", 16, None, "Reverse", "need_rd_protect"), # ECDSA key P192
452
+ ("ECDSA_KEY_P384_L", 17, None, "Reverse", "need_rd_protect"), # ECDSA key P384 low
453
+ ("ECDSA_KEY_P384_H", 18, None, "Reverse", "need_rd_protect"), # ECDSA key P384 high
454
+ ("ECDSA_KEY_P384", -3, "VIRTUAL", None, "need_rd_protect"), # Virtual purpose splits to ECDSA_KEY_P384_L and ECDSA_KEY_P384_H
409
455
  ]
410
456
  CUSTOM_KEY_PURPOSES: list[KeyPurposeType] = []
411
457
  for id in range(0, 1 << key_purpose_len):
@@ -445,9 +491,25 @@ class EfuseKeyPurposeField(EfuseField):
445
491
  return key[4] == "need_rd_protect"
446
492
 
447
493
  def get(self, from_read=True):
448
- for p in self.KEY_PURPOSES:
449
- if p[1] == self.get_raw(from_read):
450
- return p[0]
494
+ # Handle special case for KEY_PURPOSE_<digit>_H fields (e.g., KEY_PURPOSE_0_H ... KEY_PURPOSE_9_H)
495
+ if self.name.startswith("KEY_PURPOSE_") and self.name.endswith("_H"):
496
+ return self.get_raw(from_read)
497
+ else:
498
+ if any(
499
+ efuse is not None
500
+ and getattr(efuse, "name", None) == "KEY_PURPOSE_0_H"
501
+ for efuse in self.parent
502
+ ): # check if the hi bit field for KEY_PURPOSE_.. exists
503
+ hi_bits = self.parent[f"{self.name}_H"].get_raw(from_read)
504
+ assert self.parent[f"{self.name}_H"].bit_len == 1
505
+ lo_bits = self.parent[f"{self.name}"].get_raw(from_read)
506
+ assert self.parent[f"{self.name}"].bit_len == 4
507
+ raw_val = (hi_bits << 4) + lo_bits
508
+ else:
509
+ raw_val = self.get_raw(from_read)
510
+ for p in self.KEY_PURPOSES:
511
+ if p[1] == raw_val:
512
+ return p[0]
451
513
  return "FORBIDDEN_STATE"
452
514
 
453
515
  def get_name(self, raw_val):
@@ -457,4 +519,31 @@ class EfuseKeyPurposeField(EfuseField):
457
519
 
458
520
  def save(self, new_value):
459
521
  raw_val = int(self.check_format(str(new_value)))
460
- return super().save(raw_val)
522
+ # Check if _H field exists (5-bit key purpose split into lo/hi)
523
+ if (any(
524
+ efuse is not None
525
+ and getattr(efuse, "name", None) == "KEY_PURPOSE_0_H"
526
+ for efuse in self.parent
527
+ )
528
+ and self.name.startswith("KEY_PURPOSE_")
529
+ and not self.name.endswith("_H")
530
+ ):
531
+ FIELD_ORDER = [
532
+ (self.name, 0), # lo bits (bits 0-3)
533
+ (f"{self.name}_H", 4), # hi bit (bit 4)
534
+ ]
535
+ for field_name, bit_offset in FIELD_ORDER:
536
+ field = self.parent[field_name]
537
+ field_val = (raw_val >> bit_offset) & ((1 << field.bit_len) - 1)
538
+ print(field_val, field_name)
539
+ if field_val != 0:
540
+ if field_name.endswith("_H"):
541
+ field.save(field_val)
542
+ else:
543
+ super().save(field_val)
544
+ log.print(
545
+ f"\t - '{field.name}' {field.get_bitstring()} -> {field.get_bitstring(from_read=False)}"
546
+ )
547
+ else:
548
+ # Single field, just save as usual
549
+ super().save(raw_val)
@@ -160,6 +160,21 @@ class EfuseDefineFields(EfuseFieldsBase):
160
160
  f.description = "calc WAFER VERSION MAJOR from (WAFER_VERSION_MAJOR_HI << 2) + WAFER_VERSION_MAJOR_LO (read only)"
161
161
  self.CALC.append(f)
162
162
 
163
+ if any(
164
+ efuse is not None
165
+ and getattr(efuse, "name", None) == "RECOVERY_BOOTLOADER_FLASH_SECTOR_0_1"
166
+ for efuse in self.ALL_EFUSES
167
+ ):
168
+ f = Field()
169
+ f.name = "RECOVERY_BOOTLOADER_FLASH_SECTOR"
170
+ f.block = 0
171
+ f.bit_len = 12
172
+ f.type = f"uint:{f.bit_len}"
173
+ f.category = "config"
174
+ f.class_type = "recovery_bootloader"
175
+ f.description = "recovery_bootloader = RECOVERY_BOOTLOADER_FLASH_SECTOR_0_1 + 2_2 + 3_6 + 7_7 + 8_10 + 11_11"
176
+ self.CALC.append(f)
177
+
163
178
  for efuse in self.ALL_EFUSES:
164
179
  if efuse is not None:
165
180
  self.EFUSES.append(efuse)
@@ -0,0 +1,5 @@
1
+ from . import operations
2
+ from .emulate_efuse_controller import EmulateEfuseController
3
+ from .fields import EspEfuses
4
+
5
+ commands = operations.ESP32S31Commands
@@ -0,0 +1,92 @@
1
+ # This file describes eFuses controller for ESP32-S31 chip
2
+ #
3
+ # SPDX-FileCopyrightText: 2025 Espressif Systems (Shanghai) CO LTD
4
+ #
5
+ # SPDX-License-Identifier: GPL-2.0-or-later
6
+
7
+ import reedsolo
8
+
9
+ from .mem_definition import EfuseDefineBlocks, EfuseDefineFields, EfuseDefineRegisters
10
+ from ..emulate_efuse_controller_base import EmulateEfuseControllerBase, FatalError
11
+
12
+
13
+ class EmulateEfuseController(EmulateEfuseControllerBase):
14
+ """The class for virtual efuse operation. Using for HOST_TEST."""
15
+
16
+ CHIP_NAME = "ESP32-S31"
17
+ mem = None
18
+ debug = False
19
+
20
+ def __init__(self, efuse_file=None, debug=False):
21
+ self.Blocks = EfuseDefineBlocks
22
+ self.Fields = EfuseDefineFields(None)
23
+ self.REGS = EfuseDefineRegisters
24
+ super().__init__(efuse_file, debug)
25
+ self.write_reg(self.REGS.EFUSE_CMD_REG, 0)
26
+
27
+ """ esptool method start >>"""
28
+
29
+ def get_major_chip_version(self):
30
+ return 0
31
+
32
+ def get_minor_chip_version(self):
33
+ return 0
34
+
35
+ def get_crystal_freq(self):
36
+ return 40 # MHz
37
+
38
+ def get_security_info(self):
39
+ return {
40
+ "flags": 0,
41
+ "flash_crypt_cnt": 0,
42
+ "key_purposes": 0,
43
+ "chip_id": 0,
44
+ "api_version": 0,
45
+ }
46
+
47
+ """ << esptool method end """
48
+
49
+ def handle_writing_event(self, addr, value):
50
+ if addr == self.REGS.EFUSE_CMD_REG:
51
+ if value & self.REGS.EFUSE_PGM_CMD:
52
+ self.copy_blocks_wr_regs_to_rd_regs(updated_block=(value >> 2) & 0xF)
53
+ self.clean_blocks_wr_regs()
54
+ self.check_rd_protection_area()
55
+ self.write_reg(addr, 0)
56
+ self.write_reg(self.REGS.EFUSE_CMD_REG, 0)
57
+ elif value == self.REGS.EFUSE_READ_CMD:
58
+ self.write_reg(addr, 0)
59
+ self.write_reg(self.REGS.EFUSE_CMD_REG, 0)
60
+ self.save_to_file()
61
+
62
+ def get_bitlen_of_block(self, blk, wr=False):
63
+ if blk.id == 0:
64
+ if wr:
65
+ return 32 * 8
66
+ else:
67
+ return 32 * blk.len
68
+ else:
69
+ if wr:
70
+ rs_coding = 32 * 3
71
+ return 32 * 8 + rs_coding
72
+ else:
73
+ return 32 * blk.len
74
+
75
+ def handle_coding_scheme(self, blk, data):
76
+ if blk.id != 0:
77
+ # CODING_SCHEME RS applied only for all blocks except BLK0.
78
+ coded_bytes = 12
79
+ data.pos = coded_bytes * 8
80
+ plain_data = data.readlist("32*uint:8")[::-1]
81
+ # takes 32 bytes
82
+ # apply RS encoding
83
+ rs = reedsolo.RSCodec(coded_bytes)
84
+ # 32 byte of data + 12 bytes RS
85
+ calc_encoded_data = list(rs.encode([x for x in plain_data]))
86
+ data.pos = 0
87
+ if calc_encoded_data != data.readlist("44*uint:8")[::-1]:
88
+ raise FatalError("Error in coding scheme data")
89
+ data = data[coded_bytes * 8 :]
90
+ if blk.len < 8:
91
+ data = data[(8 - blk.len) * 32 :]
92
+ return data