├── .gitattributes
├── .gitignore
├── LICENSE
├── PartTool.Designer.cs
├── PartTool.cs
├── PartTool.resx
├── Properties
├── AssemblyInfo.cs
├── Resources.Designer.cs
├── Resources.resx
├── Settings.Designer.cs
└── Settings.settings
├── README.md
├── docs
├── screen_copy.jpg
├── screen_expert.jpg
├── screen_flash.jpg
├── screen_fuse.jpg
├── screen_info.jpg
└── screen_partition.jpg
├── esp_tools_gui.csproj
├── esp_tools_gui.sln
├── exes
├── ESP32py.ico
├── cxfreeze.zip
├── espefuse.exe
├── espefuse.py
├── espefuse.spec
├── espsecure.exe
├── espsecure.py
├── esptool.exe
├── esptool.py
├── gen_esp32part.exe
├── gen_esp32part.py
├── parttool.exe
├── parttool.py
├── python3.dll
├── python310.dll
└── setup_esp.py
├── images
├── add.png
├── add32.png
├── burn.png
├── burn32.png
├── esp32.jpg
├── export.png
├── export32.png
├── import.png
├── import32.png
├── kchart.png
└── kde-folder-open.png
└── src
├── App.config
├── App.cs
├── Connecting.Designer.cs
├── Connecting.cs
├── Connecting.resx
├── ESP32.ico
├── MainPage.Designer.cs
├── MainPage.cs
├── MainPage.resx
├── Tool.cs
├── ToolEfuse.cs
├── ToolPart.cs
├── ToolPartition.cs
├── ToolSecure.cs
└── ToolTool.cs
/.gitattributes:
--------------------------------------------------------------------------------
1 | # Auto detect text files and perform LF normalization
2 | * text=auto
3 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | ## Ignore Visual Studio temporary files, build results, and
2 | ## files generated by popular Visual Studio add-ons.
3 | ##
4 | ## Get latest from https://github.com/github/gitignore/blob/master/VisualStudio.gitignore
5 |
6 | # User-specific files
7 | *.rsuser
8 | *.suo
9 | *.user
10 | *.userosscache
11 | *.sln.docstates
12 |
13 | # User-specific files (MonoDevelop/Xamarin Studio)
14 | *.userprefs
15 |
16 | # Mono auto generated files
17 | mono_crash.*
18 |
19 | # Build results
20 | [Dd]ebug/
21 | [Dd]ebugPublic/
22 | [Rr]elease/
23 | [Rr]eleases/
24 | x64/
25 | x86/
26 | [Aa][Rr][Mm]/
27 | [Aa][Rr][Mm]64/
28 | bld/
29 | [Bb]in/
30 | [Oo]bj/
31 | [Ll]og/
32 |
33 | # Visual Studio 2015/2017 cache/options directory
34 | .vs/
35 | # Uncomment if you have tasks that create the project's static files in wwwroot
36 | #wwwroot/
37 |
38 | # Visual Studio 2017 auto generated files
39 | Generated\ Files/
40 |
41 | # MSTest test Results
42 | [Tt]est[Rr]esult*/
43 | [Bb]uild[Ll]og.*
44 |
45 | # NUnit
46 | *.VisualState.xml
47 | TestResult.xml
48 | nunit-*.xml
49 |
50 | # Build Results of an ATL Project
51 | [Dd]ebugPS/
52 | [Rr]eleasePS/
53 | dlldata.c
54 |
55 | # Benchmark Results
56 | BenchmarkDotNet.Artifacts/
57 |
58 | # .NET Core
59 | project.lock.json
60 | project.fragment.lock.json
61 | artifacts/
62 |
63 | # StyleCop
64 | StyleCopReport.xml
65 |
66 | # Files built by Visual Studio
67 | *_i.c
68 | *_p.c
69 | *_h.h
70 | *.ilk
71 | *.meta
72 | *.obj
73 | *.iobj
74 | *.pch
75 | *.pdb
76 | *.ipdb
77 | *.pgc
78 | *.pgd
79 | *.rsp
80 | *.sbr
81 | *.tlb
82 | *.tli
83 | *.tlh
84 | *.tmp
85 | *.tmp_proj
86 | *_wpftmp.csproj
87 | *.log
88 | *.vspscc
89 | *.vssscc
90 | .builds
91 | *.pidb
92 | *.svclog
93 | *.scc
94 |
95 | # Chutzpah Test files
96 | _Chutzpah*
97 |
98 | # Visual C++ cache files
99 | ipch/
100 | *.aps
101 | *.ncb
102 | *.opendb
103 | *.opensdf
104 | *.sdf
105 | *.cachefile
106 | *.VC.db
107 | *.VC.VC.opendb
108 |
109 | # Visual Studio profiler
110 | *.psess
111 | *.vsp
112 | *.vspx
113 | *.sap
114 |
115 | # Visual Studio Trace Files
116 | *.e2e
117 |
118 | # TFS 2012 Local Workspace
119 | $tf/
120 |
121 | # Guidance Automation Toolkit
122 | *.gpState
123 |
124 | # ReSharper is a .NET coding add-in
125 | _ReSharper*/
126 | *.[Rr]e[Ss]harper
127 | *.DotSettings.user
128 |
129 | # JustCode is a .NET coding add-in
130 | .JustCode
131 |
132 | # TeamCity is a build add-in
133 | _TeamCity*
134 |
135 | # DotCover is a Code Coverage Tool
136 | *.dotCover
137 |
138 | # AxoCover is a Code Coverage Tool
139 | .axoCover/*
140 | !.axoCover/settings.json
141 |
142 | # Visual Studio code coverage results
143 | *.coverage
144 | *.coveragexml
145 |
146 | # NCrunch
147 | _NCrunch_*
148 | .*crunch*.local.xml
149 | nCrunchTemp_*
150 |
151 | # MightyMoose
152 | *.mm.*
153 | AutoTest.Net/
154 |
155 | # Web workbench (sass)
156 | .sass-cache/
157 |
158 | # Installshield output folder
159 | [Ee]xpress/
160 |
161 | # DocProject is a documentation generator add-in
162 | DocProject/buildhelp/
163 | DocProject/Help/*.HxT
164 | DocProject/Help/*.HxC
165 | DocProject/Help/*.hhc
166 | DocProject/Help/*.hhk
167 | DocProject/Help/*.hhp
168 | DocProject/Help/Html2
169 | DocProject/Help/html
170 |
171 | # Click-Once directory
172 | publish/
173 |
174 | # Publish Web Output
175 | *.[Pp]ublish.xml
176 | *.azurePubxml
177 | # Note: Comment the next line if you want to checkin your web deploy settings,
178 | # but database connection strings (with potential passwords) will be unencrypted
179 | *.pubxml
180 | *.publishproj
181 |
182 | # Microsoft Azure Web App publish settings. Comment the next line if you want to
183 | # checkin your Azure Web App publish settings, but sensitive information contained
184 | # in these scripts will be unencrypted
185 | PublishScripts/
186 |
187 | # NuGet Packages
188 | *.nupkg
189 | # NuGet Symbol Packages
190 | *.snupkg
191 | # The packages folder can be ignored because of Package Restore
192 | **/[Pp]ackages/*
193 | # except build/, which is used as an MSBuild target.
194 | !**/[Pp]ackages/build/
195 | # Uncomment if necessary however generally it will be regenerated when needed
196 | #!**/[Pp]ackages/repositories.config
197 | # NuGet v3's project.json files produces more ignorable files
198 | *.nuget.props
199 | *.nuget.targets
200 |
201 | # Microsoft Azure Build Output
202 | csx/
203 | *.build.csdef
204 |
205 | # Microsoft Azure Emulator
206 | ecf/
207 | rcf/
208 |
209 | # Windows Store app package directories and files
210 | AppPackages/
211 | BundleArtifacts/
212 | Package.StoreAssociation.xml
213 | _pkginfo.txt
214 | *.appx
215 | *.appxbundle
216 | *.appxupload
217 |
218 | # Visual Studio cache files
219 | # files ending in .cache can be ignored
220 | *.[Cc]ache
221 | # but keep track of directories ending in .cache
222 | !?*.[Cc]ache/
223 |
224 | # Others
225 | ClientBin/
226 | ~$*
227 | *~
228 | *.dbmdl
229 | *.dbproj.schemaview
230 | *.jfm
231 | *.pfx
232 | *.publishsettings
233 | orleans.codegen.cs
234 |
235 | # Including strong name files can present a security risk
236 | # (https://github.com/github/gitignore/pull/2483#issue-259490424)
237 | #*.snk
238 |
239 | # Since there are multiple workflows, uncomment next line to ignore bower_components
240 | # (https://github.com/github/gitignore/pull/1529#issuecomment-104372622)
241 | #bower_components/
242 |
243 | # RIA/Silverlight projects
244 | Generated_Code/
245 |
246 | # Backup & report files from converting an old project file
247 | # to a newer Visual Studio version. Backup files are not needed,
248 | # because we have git ;-)
249 | _UpgradeReport_Files/
250 | Backup*/
251 | UpgradeLog*.XML
252 | UpgradeLog*.htm
253 | ServiceFabricBackup/
254 | *.rptproj.bak
255 |
256 | # SQL Server files
257 | *.mdf
258 | *.ldf
259 | *.ndf
260 |
261 | # Business Intelligence projects
262 | *.rdl.data
263 | *.bim.layout
264 | *.bim_*.settings
265 | *.rptproj.rsuser
266 | *- [Bb]ackup.rdl
267 | *- [Bb]ackup ([0-9]).rdl
268 | *- [Bb]ackup ([0-9][0-9]).rdl
269 |
270 | # Microsoft Fakes
271 | FakesAssemblies/
272 |
273 | # GhostDoc plugin setting file
274 | *.GhostDoc.xml
275 |
276 | # Node.js Tools for Visual Studio
277 | .ntvs_analysis.dat
278 | node_modules/
279 |
280 | # Visual Studio 6 build log
281 | *.plg
282 |
283 | # Visual Studio 6 workspace options file
284 | *.opt
285 |
286 | # Visual Studio 6 auto-generated workspace file (contains which files were open etc.)
287 | *.vbw
288 |
289 | # Visual Studio LightSwitch build output
290 | **/*.HTMLClient/GeneratedArtifacts
291 | **/*.DesktopClient/GeneratedArtifacts
292 | **/*.DesktopClient/ModelManifest.xml
293 | **/*.Server/GeneratedArtifacts
294 | **/*.Server/ModelManifest.xml
295 | _Pvt_Extensions
296 |
297 | # Paket dependency manager
298 | .paket/paket.exe
299 | paket-files/
300 |
301 | # FAKE - F# Make
302 | .fake/
303 |
304 | # CodeRush personal settings
305 | .cr/personal
306 |
307 | # Python Tools for Visual Studio (PTVS)
308 | __pycache__/
309 | *.pyc
310 |
311 | # Cake - Uncomment if you are using it
312 | # tools/**
313 | # !tools/packages.config
314 |
315 | # Tabs Studio
316 | *.tss
317 |
318 | # Telerik's JustMock configuration file
319 | *.jmconfig
320 |
321 | # BizTalk build output
322 | *.btp.cs
323 | *.btm.cs
324 | *.odx.cs
325 | *.xsd.cs
326 |
327 | # OpenCover UI analysis results
328 | OpenCover/
329 |
330 | # Azure Stream Analytics local run output
331 | ASALocalRun/
332 |
333 | # MSBuild Binary and Structured Log
334 | *.binlog
335 |
336 | # NVidia Nsight GPU debugger configuration file
337 | *.nvuser
338 |
339 | # MFractors (Xamarin productivity tool) working folder
340 | .mfractor/
341 |
342 | # Local History for Visual Studio
343 | .localhistory/
344 |
345 | # BeatPulse healthcheck temp database
346 | healthchecksdb
347 |
348 | # Backup folder for Package Reference Convert tool in Visual Studio 2017
349 | MigrationBackup/
350 | exes/build
351 |
--------------------------------------------------------------------------------
/PartTool.Designer.cs:
--------------------------------------------------------------------------------
1 | namespace esp_tools_gui
2 | {
3 | partial class PartTool
4 | {
5 | ///
6 | /// Required designer variable.
7 | ///
8 | private System.ComponentModel.IContainer components = null;
9 |
10 | ///
11 | /// Clean up any resources being used.
12 | ///
13 | /// true if managed resources should be disposed; otherwise, false.
14 | protected override void Dispose(bool disposing)
15 | {
16 | if (disposing && (components != null))
17 | {
18 | components.Dispose();
19 | }
20 | base.Dispose(disposing);
21 | }
22 |
23 | #region Windows Form Designer generated code
24 |
25 | ///
26 | /// Required method for Designer support - do not modify
27 | /// the contents of this method with the code editor.
28 | ///
29 | private void InitializeComponent()
30 | {
31 | this.components = new System.ComponentModel.Container();
32 | System.Windows.Forms.TreeNode treeNode1 = new System.Windows.Forms.TreeNode("Partition Name");
33 | System.Windows.Forms.TreeNode treeNode2 = new System.Windows.Forms.TreeNode("Partitions", new System.Windows.Forms.TreeNode[] {
34 | treeNode1});
35 | System.ComponentModel.ComponentResourceManager resources = new System.ComponentModel.ComponentResourceManager(typeof(PartTool));
36 | this.trackBarOta = new System.Windows.Forms.TrackBar();
37 | this.label1 = new System.Windows.Forms.Label();
38 | this.progressBar1 = new System.Windows.Forms.ProgressBar();
39 | this.labelProgress = new System.Windows.Forms.Label();
40 | this.checkBoxOta = new System.Windows.Forms.CheckBox();
41 | this.checkBoxNvs = new System.Windows.Forms.CheckBox();
42 | this.trackBarNvs = new System.Windows.Forms.TrackBar();
43 | this.checkBoxEeprom = new System.Windows.Forms.CheckBox();
44 | this.trackBarEeprom = new System.Windows.Forms.TrackBar();
45 | this.checkBoxSpiffs = new System.Windows.Forms.CheckBox();
46 | this.trackBarSpiffs = new System.Windows.Forms.TrackBar();
47 | this.labelOta = new System.Windows.Forms.Label();
48 | this.labelNvs = new System.Windows.Forms.Label();
49 | this.labelEeprom = new System.Windows.Forms.Label();
50 | this.labelSpiffs = new System.Windows.Forms.Label();
51 | this.button1 = new System.Windows.Forms.Button();
52 | this.button2 = new System.Windows.Forms.Button();
53 | this.button3 = new System.Windows.Forms.Button();
54 | this.saveFileDialog1 = new System.Windows.Forms.SaveFileDialog();
55 | this.labelOta1 = new System.Windows.Forms.Label();
56 | this.trackBarOta1 = new System.Windows.Forms.TrackBar();
57 | this.checkBoxOtaLock = new System.Windows.Forms.CheckBox();
58 | this.openFileDialog1 = new System.Windows.Forms.OpenFileDialog();
59 | this.button4 = new System.Windows.Forms.Button();
60 | this.button5 = new System.Windows.Forms.Button();
61 | this.groupBox1 = new System.Windows.Forms.GroupBox();
62 | this.button6 = new System.Windows.Forms.Button();
63 | this.textBox2 = new System.Windows.Forms.TextBox();
64 | this.label3 = new System.Windows.Forms.Label();
65 | this.textBox1 = new System.Windows.Forms.TextBox();
66 | this.label2 = new System.Windows.Forms.Label();
67 | this.treeView1 = new System.Windows.Forms.TreeView();
68 | this.imageList1 = new System.Windows.Forms.ImageList(this.components);
69 | this.trackBarOtaD = new System.Windows.Forms.TrackBar();
70 | this.checkBoxOtaD = new System.Windows.Forms.CheckBox();
71 | this.labelOtaD = new System.Windows.Forms.Label();
72 | this.labelFfat = new System.Windows.Forms.Label();
73 | this.checkBoxFfat = new System.Windows.Forms.CheckBox();
74 | this.trackBarFfat = new System.Windows.Forms.TrackBar();
75 | ((System.ComponentModel.ISupportInitialize)(this.trackBarOta)).BeginInit();
76 | ((System.ComponentModel.ISupportInitialize)(this.trackBarNvs)).BeginInit();
77 | ((System.ComponentModel.ISupportInitialize)(this.trackBarEeprom)).BeginInit();
78 | ((System.ComponentModel.ISupportInitialize)(this.trackBarSpiffs)).BeginInit();
79 | ((System.ComponentModel.ISupportInitialize)(this.trackBarOta1)).BeginInit();
80 | this.groupBox1.SuspendLayout();
81 | ((System.ComponentModel.ISupportInitialize)(this.trackBarOtaD)).BeginInit();
82 | ((System.ComponentModel.ISupportInitialize)(this.trackBarFfat)).BeginInit();
83 | this.SuspendLayout();
84 | //
85 | // trackBarOta
86 | //
87 | this.trackBarOta.LargeChange = 1000;
88 | this.trackBarOta.Location = new System.Drawing.Point(90, 20);
89 | this.trackBarOta.Maximum = 4000;
90 | this.trackBarOta.Name = "trackBarOta";
91 | this.trackBarOta.Size = new System.Drawing.Size(377, 45);
92 | this.trackBarOta.SmallChange = 4;
93 | this.trackBarOta.TabIndex = 0;
94 | this.trackBarOta.TickFrequency = 80;
95 | this.trackBarOta.TickStyle = System.Windows.Forms.TickStyle.Both;
96 | this.trackBarOta.Scroll += new System.EventHandler(this.trackBarOta_Scroll);
97 | this.trackBarOta.ValueChanged += new System.EventHandler(this.trackBarOta_ValueChanged);
98 | //
99 | // label1
100 | //
101 | this.label1.AutoSize = true;
102 | this.label1.Location = new System.Drawing.Point(30, 377);
103 | this.label1.Name = "label1";
104 | this.label1.Size = new System.Drawing.Size(91, 13);
105 | this.label1.TabIndex = 1;
106 | this.label1.Text = "Used / Total size:";
107 | //
108 | // progressBar1
109 | //
110 | this.progressBar1.Location = new System.Drawing.Point(12, 393);
111 | this.progressBar1.MarqueeAnimationSpeed = 200;
112 | this.progressBar1.Name = "progressBar1";
113 | this.progressBar1.Size = new System.Drawing.Size(484, 23);
114 | this.progressBar1.Style = System.Windows.Forms.ProgressBarStyle.Continuous;
115 | this.progressBar1.TabIndex = 2;
116 | //
117 | // labelProgress
118 | //
119 | this.labelProgress.AutoSize = true;
120 | this.labelProgress.Location = new System.Drawing.Point(381, 376);
121 | this.labelProgress.Name = "labelProgress";
122 | this.labelProgress.Size = new System.Drawing.Size(54, 13);
123 | this.labelProgress.TabIndex = 3;
124 | this.labelProgress.Text = "0 / 4120k";
125 | //
126 | // checkBoxOta
127 | //
128 | this.checkBoxOta.AutoSize = true;
129 | this.checkBoxOta.Checked = true;
130 | this.checkBoxOta.CheckState = System.Windows.Forms.CheckState.Checked;
131 | this.checkBoxOta.Location = new System.Drawing.Point(12, 48);
132 | this.checkBoxOta.Name = "checkBoxOta";
133 | this.checkBoxOta.Size = new System.Drawing.Size(48, 17);
134 | this.checkBoxOta.TabIndex = 4;
135 | this.checkBoxOta.Text = "OTA";
136 | this.checkBoxOta.UseVisualStyleBackColor = true;
137 | this.checkBoxOta.CheckedChanged += new System.EventHandler(this.checkBoxOta_CheckedChanged);
138 | //
139 | // checkBoxNvs
140 | //
141 | this.checkBoxNvs.AutoSize = true;
142 | this.checkBoxNvs.Checked = true;
143 | this.checkBoxNvs.CheckState = System.Windows.Forms.CheckState.Checked;
144 | this.checkBoxNvs.Location = new System.Drawing.Point(12, 177);
145 | this.checkBoxNvs.Name = "checkBoxNvs";
146 | this.checkBoxNvs.Size = new System.Drawing.Size(48, 17);
147 | this.checkBoxNvs.TabIndex = 6;
148 | this.checkBoxNvs.Text = "NVS";
149 | this.checkBoxNvs.UseVisualStyleBackColor = true;
150 | this.checkBoxNvs.CheckedChanged += new System.EventHandler(this.checkBoxNvs_CheckedChanged);
151 | //
152 | // trackBarNvs
153 | //
154 | this.trackBarNvs.LargeChange = 1000;
155 | this.trackBarNvs.Location = new System.Drawing.Point(90, 164);
156 | this.trackBarNvs.Maximum = 4000;
157 | this.trackBarNvs.Name = "trackBarNvs";
158 | this.trackBarNvs.Size = new System.Drawing.Size(377, 45);
159 | this.trackBarNvs.SmallChange = 4;
160 | this.trackBarNvs.TabIndex = 5;
161 | this.trackBarNvs.TickFrequency = 80;
162 | this.trackBarNvs.TickStyle = System.Windows.Forms.TickStyle.Both;
163 | this.trackBarNvs.ValueChanged += new System.EventHandler(this.trackBarNvs_ValueChanged);
164 | //
165 | // checkBoxEeprom
166 | //
167 | this.checkBoxEeprom.AutoSize = true;
168 | this.checkBoxEeprom.Location = new System.Drawing.Point(12, 228);
169 | this.checkBoxEeprom.Name = "checkBoxEeprom";
170 | this.checkBoxEeprom.Size = new System.Drawing.Size(72, 17);
171 | this.checkBoxEeprom.TabIndex = 8;
172 | this.checkBoxEeprom.Text = "EEPROM";
173 | this.checkBoxEeprom.UseVisualStyleBackColor = true;
174 | this.checkBoxEeprom.CheckedChanged += new System.EventHandler(this.checkBoxEeprom_CheckedChanged);
175 | //
176 | // trackBarEeprom
177 | //
178 | this.trackBarEeprom.Enabled = false;
179 | this.trackBarEeprom.LargeChange = 1000;
180 | this.trackBarEeprom.Location = new System.Drawing.Point(90, 215);
181 | this.trackBarEeprom.Maximum = 4000;
182 | this.trackBarEeprom.Name = "trackBarEeprom";
183 | this.trackBarEeprom.Size = new System.Drawing.Size(377, 45);
184 | this.trackBarEeprom.SmallChange = 4;
185 | this.trackBarEeprom.TabIndex = 7;
186 | this.trackBarEeprom.TickFrequency = 80;
187 | this.trackBarEeprom.TickStyle = System.Windows.Forms.TickStyle.Both;
188 | this.trackBarEeprom.ValueChanged += new System.EventHandler(this.trackBarEeprom_ValueChanged);
189 | //
190 | // checkBoxSpiffs
191 | //
192 | this.checkBoxSpiffs.AutoSize = true;
193 | this.checkBoxSpiffs.Location = new System.Drawing.Point(12, 279);
194 | this.checkBoxSpiffs.Name = "checkBoxSpiffs";
195 | this.checkBoxSpiffs.Size = new System.Drawing.Size(62, 17);
196 | this.checkBoxSpiffs.TabIndex = 10;
197 | this.checkBoxSpiffs.Text = "SPIFFS";
198 | this.checkBoxSpiffs.UseVisualStyleBackColor = true;
199 | this.checkBoxSpiffs.CheckedChanged += new System.EventHandler(this.checkBoxSpiffs_CheckedChanged);
200 | //
201 | // trackBarSpiffs
202 | //
203 | this.trackBarSpiffs.Enabled = false;
204 | this.trackBarSpiffs.LargeChange = 1000;
205 | this.trackBarSpiffs.Location = new System.Drawing.Point(90, 266);
206 | this.trackBarSpiffs.Maximum = 4000;
207 | this.trackBarSpiffs.Name = "trackBarSpiffs";
208 | this.trackBarSpiffs.Size = new System.Drawing.Size(377, 45);
209 | this.trackBarSpiffs.SmallChange = 4;
210 | this.trackBarSpiffs.TabIndex = 9;
211 | this.trackBarSpiffs.TickFrequency = 80;
212 | this.trackBarSpiffs.TickStyle = System.Windows.Forms.TickStyle.Both;
213 | this.trackBarSpiffs.ValueChanged += new System.EventHandler(this.trackBarSpiffs_ValueChanged);
214 | //
215 | // labelOta
216 | //
217 | this.labelOta.AutoSize = true;
218 | this.labelOta.Location = new System.Drawing.Point(465, 34);
219 | this.labelOta.Name = "labelOta";
220 | this.labelOta.Size = new System.Drawing.Size(31, 13);
221 | this.labelOta.TabIndex = 11;
222 | this.labelOta.Text = "100k";
223 | //
224 | // labelNvs
225 | //
226 | this.labelNvs.AutoSize = true;
227 | this.labelNvs.Location = new System.Drawing.Point(465, 177);
228 | this.labelNvs.Name = "labelNvs";
229 | this.labelNvs.Size = new System.Drawing.Size(31, 13);
230 | this.labelNvs.TabIndex = 12;
231 | this.labelNvs.Text = "100k";
232 | //
233 | // labelEeprom
234 | //
235 | this.labelEeprom.AutoSize = true;
236 | this.labelEeprom.Location = new System.Drawing.Point(465, 228);
237 | this.labelEeprom.Name = "labelEeprom";
238 | this.labelEeprom.Size = new System.Drawing.Size(31, 13);
239 | this.labelEeprom.TabIndex = 13;
240 | this.labelEeprom.Text = "100k";
241 | //
242 | // labelSpiffs
243 | //
244 | this.labelSpiffs.AutoSize = true;
245 | this.labelSpiffs.Location = new System.Drawing.Point(465, 279);
246 | this.labelSpiffs.Name = "labelSpiffs";
247 | this.labelSpiffs.Size = new System.Drawing.Size(31, 13);
248 | this.labelSpiffs.TabIndex = 14;
249 | this.labelSpiffs.Text = "100k";
250 | //
251 | // button1
252 | //
253 | this.button1.Image = global::esp_tools_gui.Properties.Resources.export32;
254 | this.button1.ImageAlign = System.Drawing.ContentAlignment.TopCenter;
255 | this.button1.Location = new System.Drawing.Point(118, 433);
256 | this.button1.Name = "button1";
257 | this.button1.Size = new System.Drawing.Size(100, 55);
258 | this.button1.TabIndex = 15;
259 | this.button1.Text = "Export Table";
260 | this.button1.TextAlign = System.Drawing.ContentAlignment.BottomCenter;
261 | this.button1.UseVisualStyleBackColor = true;
262 | this.button1.Click += new System.EventHandler(this.button1_Click);
263 | //
264 | // button2
265 | //
266 | this.button2.Image = global::esp_tools_gui.Properties.Resources.burn32;
267 | this.button2.ImageAlign = System.Drawing.ContentAlignment.TopCenter;
268 | this.button2.Location = new System.Drawing.Point(224, 433);
269 | this.button2.Name = "button2";
270 | this.button2.Size = new System.Drawing.Size(100, 55);
271 | this.button2.TabIndex = 16;
272 | this.button2.Text = "Burn Table";
273 | this.button2.TextAlign = System.Drawing.ContentAlignment.BottomCenter;
274 | this.button2.UseVisualStyleBackColor = true;
275 | this.button2.Click += new System.EventHandler(this.button2_Click);
276 | //
277 | // button3
278 | //
279 | this.button3.Location = new System.Drawing.Point(12, 496);
280 | this.button3.Name = "button3";
281 | this.button3.Size = new System.Drawing.Size(484, 30);
282 | this.button3.TabIndex = 17;
283 | this.button3.Text = "Cancel";
284 | this.button3.UseVisualStyleBackColor = true;
285 | this.button3.Click += new System.EventHandler(this.button3_Click);
286 | //
287 | // saveFileDialog1
288 | //
289 | this.saveFileDialog1.Filter = "bin-File|*.bin|csv-File|*.csv";
290 | this.saveFileDialog1.RestoreDirectory = true;
291 | this.saveFileDialog1.Title = "Save Partition Table";
292 | //
293 | // labelOta1
294 | //
295 | this.labelOta1.AutoSize = true;
296 | this.labelOta1.Location = new System.Drawing.Point(465, 76);
297 | this.labelOta1.Name = "labelOta1";
298 | this.labelOta1.Size = new System.Drawing.Size(31, 13);
299 | this.labelOta1.TabIndex = 20;
300 | this.labelOta1.Text = "100k";
301 | //
302 | // trackBarOta1
303 | //
304 | this.trackBarOta1.Enabled = false;
305 | this.trackBarOta1.LargeChange = 1000;
306 | this.trackBarOta1.Location = new System.Drawing.Point(90, 62);
307 | this.trackBarOta1.Maximum = 4000;
308 | this.trackBarOta1.Name = "trackBarOta1";
309 | this.trackBarOta1.Size = new System.Drawing.Size(377, 45);
310 | this.trackBarOta1.SmallChange = 4;
311 | this.trackBarOta1.TabIndex = 18;
312 | this.trackBarOta1.TickFrequency = 80;
313 | this.trackBarOta1.TickStyle = System.Windows.Forms.TickStyle.Both;
314 | this.trackBarOta1.ValueChanged += new System.EventHandler(this.trackBarOta1_ValueChanged);
315 | //
316 | // checkBoxOtaLock
317 | //
318 | this.checkBoxOtaLock.AutoSize = true;
319 | this.checkBoxOtaLock.Checked = true;
320 | this.checkBoxOtaLock.CheckState = System.Windows.Forms.CheckState.Checked;
321 | this.checkBoxOtaLock.Location = new System.Drawing.Point(33, 72);
322 | this.checkBoxOtaLock.Name = "checkBoxOtaLock";
323 | this.checkBoxOtaLock.Size = new System.Drawing.Size(50, 17);
324 | this.checkBoxOtaLock.TabIndex = 21;
325 | this.checkBoxOtaLock.Text = "Lock";
326 | this.checkBoxOtaLock.UseVisualStyleBackColor = true;
327 | this.checkBoxOtaLock.CheckedChanged += new System.EventHandler(this.checkBoxOtaLock_CheckedChanged);
328 | //
329 | // openFileDialog1
330 | //
331 | this.openFileDialog1.FileName = "openFileDialog1";
332 | this.openFileDialog1.Filter = "bin-File|*.bin|csv-File|*.csv";
333 | this.openFileDialog1.FilterIndex = 2;
334 | this.openFileDialog1.RestoreDirectory = true;
335 | this.openFileDialog1.Title = "Import Partition Table";
336 | //
337 | // button4
338 | //
339 | this.button4.BackgroundImageLayout = System.Windows.Forms.ImageLayout.Zoom;
340 | this.button4.Image = global::esp_tools_gui.Properties.Resources.import32;
341 | this.button4.ImageAlign = System.Drawing.ContentAlignment.TopCenter;
342 | this.button4.Location = new System.Drawing.Point(12, 433);
343 | this.button4.Name = "button4";
344 | this.button4.Size = new System.Drawing.Size(100, 55);
345 | this.button4.TabIndex = 22;
346 | this.button4.Text = "Import Table";
347 | this.button4.TextAlign = System.Drawing.ContentAlignment.BottomCenter;
348 | this.button4.UseVisualStyleBackColor = true;
349 | this.button4.Click += new System.EventHandler(this.button4_Click);
350 | //
351 | // button5
352 | //
353 | this.button5.Image = global::esp_tools_gui.Properties.Resources.add32;
354 | this.button5.ImageAlign = System.Drawing.ContentAlignment.TopCenter;
355 | this.button5.Location = new System.Drawing.Point(330, 433);
356 | this.button5.Name = "button5";
357 | this.button5.Size = new System.Drawing.Size(166, 55);
358 | this.button5.TabIndex = 23;
359 | this.button5.Text = "Add to Arduino IDE";
360 | this.button5.TextAlign = System.Drawing.ContentAlignment.BottomCenter;
361 | this.button5.UseVisualStyleBackColor = true;
362 | this.button5.Click += new System.EventHandler(this.button5_Click);
363 | //
364 | // groupBox1
365 | //
366 | this.groupBox1.Controls.Add(this.button6);
367 | this.groupBox1.Controls.Add(this.textBox2);
368 | this.groupBox1.Controls.Add(this.label3);
369 | this.groupBox1.Controls.Add(this.textBox1);
370 | this.groupBox1.Controls.Add(this.label2);
371 | this.groupBox1.Controls.Add(this.treeView1);
372 | this.groupBox1.Location = new System.Drawing.Point(531, 13);
373 | this.groupBox1.Name = "groupBox1";
374 | this.groupBox1.Size = new System.Drawing.Size(485, 513);
375 | this.groupBox1.TabIndex = 24;
376 | this.groupBox1.TabStop = false;
377 | this.groupBox1.Text = "Partitions";
378 | //
379 | // button6
380 | //
381 | this.button6.Image = global::esp_tools_gui.Properties.Resources.add32;
382 | this.button6.ImageAlign = System.Drawing.ContentAlignment.MiddleLeft;
383 | this.button6.Location = new System.Drawing.Point(332, 461);
384 | this.button6.Name = "button6";
385 | this.button6.Size = new System.Drawing.Size(146, 46);
386 | this.button6.TabIndex = 24;
387 | this.button6.Text = "Add to Arduino IDE";
388 | this.button6.TextAlign = System.Drawing.ContentAlignment.MiddleRight;
389 | this.button6.UseVisualStyleBackColor = true;
390 | this.button6.Click += new System.EventHandler(this.button6_Click);
391 | //
392 | // textBox2
393 | //
394 | this.textBox2.Location = new System.Drawing.Point(79, 487);
395 | this.textBox2.Name = "textBox2";
396 | this.textBox2.Size = new System.Drawing.Size(247, 20);
397 | this.textBox2.TabIndex = 5;
398 | //
399 | // label3
400 | //
401 | this.label3.AutoSize = true;
402 | this.label3.Location = new System.Drawing.Point(7, 490);
403 | this.label3.Name = "label3";
404 | this.label3.Size = new System.Drawing.Size(63, 13);
405 | this.label3.TabIndex = 4;
406 | this.label3.Text = "Description:";
407 | //
408 | // textBox1
409 | //
410 | this.textBox1.Location = new System.Drawing.Point(79, 461);
411 | this.textBox1.Name = "textBox1";
412 | this.textBox1.ReadOnly = true;
413 | this.textBox1.Size = new System.Drawing.Size(97, 20);
414 | this.textBox1.TabIndex = 3;
415 | //
416 | // label2
417 | //
418 | this.label2.AutoSize = true;
419 | this.label2.Location = new System.Drawing.Point(7, 464);
420 | this.label2.Name = "label2";
421 | this.label2.Size = new System.Drawing.Size(66, 13);
422 | this.label2.TabIndex = 2;
423 | this.label2.Text = "Table name:";
424 | //
425 | // treeView1
426 | //
427 | this.treeView1.ImageIndex = 5;
428 | this.treeView1.ImageList = this.imageList1;
429 | this.treeView1.Indent = 20;
430 | this.treeView1.ItemHeight = 16;
431 | this.treeView1.Location = new System.Drawing.Point(6, 19);
432 | this.treeView1.Name = "treeView1";
433 | treeNode1.ImageIndex = 4;
434 | treeNode1.Name = "Knoten2";
435 | treeNode1.Text = "Partition Name";
436 | treeNode2.Name = "Knoten0";
437 | treeNode2.Text = "Partitions";
438 | this.treeView1.Nodes.AddRange(new System.Windows.Forms.TreeNode[] {
439 | treeNode2});
440 | this.treeView1.SelectedImageIndex = 0;
441 | this.treeView1.Size = new System.Drawing.Size(472, 436);
442 | this.treeView1.TabIndex = 1;
443 | //
444 | // imageList1
445 | //
446 | this.imageList1.ImageStream = ((System.Windows.Forms.ImageListStreamer)(resources.GetObject("imageList1.ImageStream")));
447 | this.imageList1.TransparentColor = System.Drawing.Color.Transparent;
448 | this.imageList1.Images.SetKeyName(0, "add.png");
449 | this.imageList1.Images.SetKeyName(1, "burn.png");
450 | this.imageList1.Images.SetKeyName(2, "export.png");
451 | this.imageList1.Images.SetKeyName(3, "import.png");
452 | this.imageList1.Images.SetKeyName(4, "kchart.png");
453 | this.imageList1.Images.SetKeyName(5, "kde-folder-open.png");
454 | //
455 | // trackBarOtaD
456 | //
457 | this.trackBarOtaD.Enabled = false;
458 | this.trackBarOtaD.LargeChange = 1000;
459 | this.trackBarOtaD.Location = new System.Drawing.Point(90, 113);
460 | this.trackBarOtaD.Maximum = 128;
461 | this.trackBarOtaD.Name = "trackBarOtaD";
462 | this.trackBarOtaD.Size = new System.Drawing.Size(377, 45);
463 | this.trackBarOtaD.SmallChange = 4;
464 | this.trackBarOtaD.TabIndex = 25;
465 | this.trackBarOtaD.TickFrequency = 80;
466 | this.trackBarOtaD.TickStyle = System.Windows.Forms.TickStyle.Both;
467 | //
468 | // checkBoxOtaD
469 | //
470 | this.checkBoxOtaD.AutoSize = true;
471 | this.checkBoxOtaD.Checked = true;
472 | this.checkBoxOtaD.CheckState = System.Windows.Forms.CheckState.Checked;
473 | this.checkBoxOtaD.Enabled = false;
474 | this.checkBoxOtaD.Location = new System.Drawing.Point(12, 123);
475 | this.checkBoxOtaD.Name = "checkBoxOtaD";
476 | this.checkBoxOtaD.Size = new System.Drawing.Size(71, 17);
477 | this.checkBoxOtaD.TabIndex = 26;
478 | this.checkBoxOtaD.Text = "OTAData";
479 | this.checkBoxOtaD.UseVisualStyleBackColor = true;
480 | //
481 | // labelOtaD
482 | //
483 | this.labelOtaD.AutoSize = true;
484 | this.labelOtaD.Location = new System.Drawing.Point(465, 127);
485 | this.labelOtaD.Name = "labelOtaD";
486 | this.labelOtaD.Size = new System.Drawing.Size(31, 13);
487 | this.labelOtaD.TabIndex = 27;
488 | this.labelOtaD.Text = "100k";
489 | //
490 | // labelFfat
491 | //
492 | this.labelFfat.AutoSize = true;
493 | this.labelFfat.Location = new System.Drawing.Point(465, 330);
494 | this.labelFfat.Name = "labelFfat";
495 | this.labelFfat.Size = new System.Drawing.Size(31, 13);
496 | this.labelFfat.TabIndex = 30;
497 | this.labelFfat.Text = "100k";
498 | //
499 | // checkBoxFfat
500 | //
501 | this.checkBoxFfat.AutoSize = true;
502 | this.checkBoxFfat.Location = new System.Drawing.Point(12, 330);
503 | this.checkBoxFfat.Name = "checkBoxFfat";
504 | this.checkBoxFfat.Size = new System.Drawing.Size(52, 17);
505 | this.checkBoxFfat.TabIndex = 29;
506 | this.checkBoxFfat.Text = "FFAT";
507 | this.checkBoxFfat.UseVisualStyleBackColor = true;
508 | this.checkBoxFfat.CheckedChanged += new System.EventHandler(this.checkBoxFfat_CheckedChanged);
509 | //
510 | // trackBarFfat
511 | //
512 | this.trackBarFfat.Enabled = false;
513 | this.trackBarFfat.LargeChange = 1000;
514 | this.trackBarFfat.Location = new System.Drawing.Point(90, 317);
515 | this.trackBarFfat.Maximum = 4000;
516 | this.trackBarFfat.Name = "trackBarFfat";
517 | this.trackBarFfat.Size = new System.Drawing.Size(377, 45);
518 | this.trackBarFfat.SmallChange = 4;
519 | this.trackBarFfat.TabIndex = 28;
520 | this.trackBarFfat.TickFrequency = 80;
521 | this.trackBarFfat.TickStyle = System.Windows.Forms.TickStyle.Both;
522 | this.trackBarFfat.ValueChanged += new System.EventHandler(this.trackBarFfat_ValueChanged);
523 | //
524 | // PartTool
525 | //
526 | this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F);
527 | this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
528 | this.ClientSize = new System.Drawing.Size(1044, 547);
529 | this.Controls.Add(this.groupBox1);
530 | this.Controls.Add(this.labelFfat);
531 | this.Controls.Add(this.checkBoxFfat);
532 | this.Controls.Add(this.trackBarFfat);
533 | this.Controls.Add(this.labelOtaD);
534 | this.Controls.Add(this.checkBoxOtaD);
535 | this.Controls.Add(this.trackBarOtaD);
536 | this.Controls.Add(this.button5);
537 | this.Controls.Add(this.button4);
538 | this.Controls.Add(this.checkBoxOtaLock);
539 | this.Controls.Add(this.labelOta1);
540 | this.Controls.Add(this.trackBarOta1);
541 | this.Controls.Add(this.button3);
542 | this.Controls.Add(this.button2);
543 | this.Controls.Add(this.button1);
544 | this.Controls.Add(this.labelSpiffs);
545 | this.Controls.Add(this.labelEeprom);
546 | this.Controls.Add(this.labelNvs);
547 | this.Controls.Add(this.labelOta);
548 | this.Controls.Add(this.checkBoxSpiffs);
549 | this.Controls.Add(this.trackBarSpiffs);
550 | this.Controls.Add(this.checkBoxEeprom);
551 | this.Controls.Add(this.trackBarEeprom);
552 | this.Controls.Add(this.checkBoxNvs);
553 | this.Controls.Add(this.trackBarNvs);
554 | this.Controls.Add(this.checkBoxOta);
555 | this.Controls.Add(this.labelProgress);
556 | this.Controls.Add(this.progressBar1);
557 | this.Controls.Add(this.label1);
558 | this.Controls.Add(this.trackBarOta);
559 | this.FormBorderStyle = System.Windows.Forms.FormBorderStyle.FixedDialog;
560 | this.MaximizeBox = false;
561 | this.MinimizeBox = false;
562 | this.Name = "PartTool";
563 | this.StartPosition = System.Windows.Forms.FormStartPosition.CenterParent;
564 | this.Text = "PartTool";
565 | this.Load += new System.EventHandler(this.PartTool_Load);
566 | ((System.ComponentModel.ISupportInitialize)(this.trackBarOta)).EndInit();
567 | ((System.ComponentModel.ISupportInitialize)(this.trackBarNvs)).EndInit();
568 | ((System.ComponentModel.ISupportInitialize)(this.trackBarEeprom)).EndInit();
569 | ((System.ComponentModel.ISupportInitialize)(this.trackBarSpiffs)).EndInit();
570 | ((System.ComponentModel.ISupportInitialize)(this.trackBarOta1)).EndInit();
571 | this.groupBox1.ResumeLayout(false);
572 | this.groupBox1.PerformLayout();
573 | ((System.ComponentModel.ISupportInitialize)(this.trackBarOtaD)).EndInit();
574 | ((System.ComponentModel.ISupportInitialize)(this.trackBarFfat)).EndInit();
575 | this.ResumeLayout(false);
576 | this.PerformLayout();
577 |
578 | }
579 |
580 | #endregion
581 |
582 | private System.Windows.Forms.TrackBar trackBarOta;
583 | private System.Windows.Forms.Label label1;
584 | private System.Windows.Forms.ProgressBar progressBar1;
585 | private System.Windows.Forms.Label labelProgress;
586 | private System.Windows.Forms.CheckBox checkBoxOta;
587 | private System.Windows.Forms.CheckBox checkBoxNvs;
588 | private System.Windows.Forms.TrackBar trackBarNvs;
589 | private System.Windows.Forms.CheckBox checkBoxEeprom;
590 | private System.Windows.Forms.TrackBar trackBarEeprom;
591 | private System.Windows.Forms.CheckBox checkBoxSpiffs;
592 | private System.Windows.Forms.TrackBar trackBarSpiffs;
593 | private System.Windows.Forms.Label labelOta;
594 | private System.Windows.Forms.Label labelNvs;
595 | private System.Windows.Forms.Label labelEeprom;
596 | private System.Windows.Forms.Label labelSpiffs;
597 | private System.Windows.Forms.Button button1;
598 | private System.Windows.Forms.Button button2;
599 | private System.Windows.Forms.Button button3;
600 | private System.Windows.Forms.SaveFileDialog saveFileDialog1;
601 | private System.Windows.Forms.Label labelOta1;
602 | private System.Windows.Forms.TrackBar trackBarOta1;
603 | private System.Windows.Forms.CheckBox checkBoxOtaLock;
604 | private System.Windows.Forms.Button button4;
605 | private System.Windows.Forms.OpenFileDialog openFileDialog1;
606 | private System.Windows.Forms.Button button5;
607 | private System.Windows.Forms.GroupBox groupBox1;
608 | private System.Windows.Forms.TreeView treeView1;
609 | private System.Windows.Forms.ImageList imageList1;
610 | private System.Windows.Forms.Button button6;
611 | private System.Windows.Forms.TextBox textBox2;
612 | private System.Windows.Forms.Label label3;
613 | private System.Windows.Forms.TextBox textBox1;
614 | private System.Windows.Forms.Label label2;
615 | private System.Windows.Forms.TrackBar trackBarOtaD;
616 | private System.Windows.Forms.CheckBox checkBoxOtaD;
617 | private System.Windows.Forms.Label labelOtaD;
618 | private System.Windows.Forms.Label labelFfat;
619 | private System.Windows.Forms.CheckBox checkBoxFfat;
620 | private System.Windows.Forms.TrackBar trackBarFfat;
621 | }
622 | }
--------------------------------------------------------------------------------
/PartTool.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.ComponentModel;
4 | using System.Data;
5 | using System.Drawing;
6 | using System.IO;
7 | using System.Linq;
8 | using System.Text;
9 | using System.Text.RegularExpressions;
10 | using System.Threading.Tasks;
11 | using System.Windows.Forms;
12 |
13 | namespace esp_tools_gui
14 | {
15 | public partial class PartTool : Form
16 | {
17 | static int flashSizeBytes = 0;
18 | static int flashSizeKB = 0;
19 |
20 | private ToolPartition partition;
21 |
22 | public static int BaseAddress = 0x9000;
23 |
24 | public static int Eeprom = 0;
25 | public static int Nvs = 0;
26 | public static int Ota0 = 0;
27 | public static int Ota1 = 0;
28 | public static int Otad = 8 * 1024;
29 | public static bool OtaEnabled = false;
30 | public static int Spiffs = 0;
31 | public static int Ffat = 0;
32 |
33 | public PartTool(int flashMB, ToolPartition partitionTool)
34 | {
35 | InitializeComponent();
36 | flashSizeBytes = flashMB * 1024 * 1024;
37 | flashSizeKB = flashMB * 1024;
38 |
39 | progressBar1.Value = 0;
40 | progressBar1.Maximum = flashSizeKB;
41 |
42 | partition = partitionTool;
43 |
44 | this.Width /= 2;
45 | }
46 |
47 | private void PartTool_Load(object sender, EventArgs e)
48 | {
49 | trackBarOta.SmallChange = 64;
50 | trackBarOta1.SmallChange = 64;
51 | trackBarOtaD.SmallChange = 1;
52 | trackBarOta.TickFrequency = 256;
53 | trackBarOta1.TickFrequency = 256;
54 | trackBarOtaD.TickFrequency = 8;
55 |
56 | trackBarEeprom.SmallChange = 4;
57 | trackBarNvs.SmallChange = 4;
58 | trackBarEeprom.TickFrequency = 4;
59 | trackBarNvs.TickFrequency = 4;
60 |
61 | trackBarSpiffs.SmallChange = 4;
62 | trackBarSpiffs.TickFrequency = 128;
63 | trackBarFfat.SmallChange = 4;
64 | trackBarFfat.TickFrequency = 128;
65 | Calculate();
66 | }
67 |
68 | public int Calculate()
69 | {
70 | int total = 0;
71 | int free = 0;
72 | total = BaseAddress;
73 | if (checkBoxNvs.Checked) total += Nvs;
74 | if (checkBoxOta.Checked) total += Otad + Ota0 + Ota1;
75 | else total += Ota0;
76 | if (checkBoxEeprom.Checked) total += Eeprom;
77 | if (checkBoxSpiffs.Checked) total += Spiffs;
78 | if (checkBoxFfat.Checked) total += Ffat;
79 | total /= 1024;
80 | free = flashSizeKB - total;
81 |
82 | progressBar1.Value = Math.Min(progressBar1.Maximum, total);
83 | if(total > progressBar1.Maximum)
84 | {
85 | labelProgress.ForeColor = Color.DarkRed;
86 | }
87 | else
88 | {
89 | labelProgress.ForeColor = Color.Black;
90 | }
91 | labelProgress.Text = total + "kb / " + flashSizeKB + "kb";
92 |
93 | labelOta.Text = trackBarOta.Value + "kb";
94 | if (checkBoxOtaLock.Checked)
95 | {
96 | labelOta1.Text = trackBarOta.Value + "kb";
97 | trackBarOta1.Value = trackBarOta.Value;
98 | }
99 | else
100 | {
101 | labelOta1.Text = trackBarOta1.Value + "kb";
102 | }
103 | labelOtaD.Text = trackBarOtaD.Value + "kb";
104 | labelNvs.Text = (checkBoxNvs.Checked ? trackBarNvs.Value.ToString() : "0") + "kb";
105 | labelEeprom.Text = (checkBoxEeprom.Checked ? trackBarEeprom.Value.ToString() : "0") + "kb";
106 | labelSpiffs.Text = (checkBoxSpiffs.Checked ? trackBarSpiffs.Value.ToString() : "0") + "kb";
107 | labelFfat.Text = (checkBoxFfat.Checked ? trackBarFfat.Value.ToString() : "0") + "kb";
108 |
109 | if (free < 0) return free;
110 |
111 | trackBarEeprom.Maximum = trackBarEeprom.Value + free;
112 | trackBarNvs.Maximum = trackBarNvs.Value + free;
113 | if (checkBoxOta.Checked)
114 | trackBarOta.Maximum = trackBarOta.Value + free / 2;
115 | else
116 | trackBarOta.Maximum = trackBarOta.Value + free;
117 | trackBarOta1.Maximum = trackBarOta1.Value + free;
118 | trackBarSpiffs.Maximum = trackBarSpiffs.Value + free;
119 | trackBarFfat.Maximum = trackBarFfat.Value + free;
120 |
121 | return free;
122 | }
123 |
124 | public void SetEeprom(int size)
125 | {
126 | Eeprom = size;
127 | if (!trackBarEeprom.Enabled) checkBoxEeprom.Checked = true;
128 | if (size / 1024 > trackBarEeprom.Maximum) trackBarEeprom.Maximum = size / 1024;
129 | trackBarEeprom.Value = size / 1024;
130 | Calculate();
131 | }
132 | public void SetNvs(int size)
133 | {
134 | Nvs = size;
135 | if (size / 1024 > trackBarNvs.Maximum) trackBarNvs.Maximum = size / 1024;
136 | trackBarNvs.Value = size / 1024;
137 | Calculate();
138 | }
139 | public void SetOta0(int size, bool? useOta)
140 | {
141 | Ota0 = size;
142 | if (size / 1024 > trackBarOta.Maximum) trackBarOta.Maximum = size / 1024;
143 | trackBarOta.Value = size / 1024;
144 | if (useOta != null)
145 | {
146 | OtaEnabled = (bool)useOta;
147 | checkBoxOta.Checked = (bool)useOta;
148 | if (useOta == true)
149 | {
150 | Ota1 = size;
151 | }
152 | else
153 | {
154 | Ota1 = 0;
155 | }
156 | }
157 | Calculate();
158 | }
159 | public void SetOta1(int size)
160 | {
161 | Ota1 = size;
162 | if (size / 1024 > trackBarOta1.Maximum) trackBarOta1.Maximum = size / 1024;
163 | trackBarOta1.Value = size / 1024;
164 | checkBoxOta.Checked = true;
165 | checkBoxOtaLock.Checked = (Ota1 == Ota0);
166 | OtaEnabled = true;
167 | Calculate();
168 | }
169 | public void SetOtaD(int size)
170 | {
171 | //Otad = size;
172 | if (size / 1024 > trackBarOtaD.Maximum) trackBarOtaD.Maximum = size / 1024;
173 | trackBarOtaD.Minimum = 0;
174 | trackBarOtaD.Value = size / 1024;
175 | checkBoxOtaD.Checked = true;
176 | Calculate();
177 | }
178 |
179 | public void SetSpiffs(int size)
180 | {
181 | Spiffs = size;
182 | if (!trackBarSpiffs.Enabled) checkBoxSpiffs.Checked = true;
183 | if (size / 1024 > trackBarSpiffs.Maximum) trackBarSpiffs.Maximum = size / 1024;
184 | trackBarSpiffs.Value = size / 1024;
185 | Calculate();
186 | }
187 |
188 | public void SetFfat(int size)
189 | {
190 | Ffat = size;
191 | if (!trackBarFfat.Enabled) checkBoxFfat.Checked = true;
192 | if (size / 1024 > trackBarFfat.Maximum) trackBarFfat.Maximum = size / 1024;
193 | trackBarFfat.Value = size / 1024;
194 | Calculate();
195 | }
196 |
197 | private void trackBarOta_ValueChanged(object sender, EventArgs e)
198 | {
199 | Ota0 = (trackBarOta.Value - trackBarOta.Value % 64) * 1024;
200 | trackBarOta.Value = Ota0 / 1024;
201 | if (checkBoxOtaLock.Checked)
202 | {
203 | Ota1 = Ota0;
204 | if (Ota0 / 1024 > trackBarOta1.Maximum) trackBarOta1.Maximum = Ota0 / 1024;
205 | trackBarOta1.Value = Ota0 / 1024;
206 | if (trackBarOta.Value > trackBarOta1.Maximum) trackBarOta1.Maximum = trackBarOta.Value;
207 | trackBarOta1.Value = trackBarOta.Value;
208 | }
209 | Calculate();
210 | }
211 |
212 | private void trackBarOta1_ValueChanged(object sender, EventArgs e)
213 | {
214 | if (!checkBoxOtaLock.Checked)
215 | {
216 | Ota1 = (trackBarOta1.Value - (trackBarOta1.Value % 64)) * 1024;
217 | trackBarOta1.Value = Ota1 / 1024;
218 | Calculate();
219 | }
220 | }
221 |
222 | private void trackBarNvs_ValueChanged(object sender, EventArgs e)
223 | {
224 | Nvs = (trackBarNvs.Value - trackBarNvs.Value % 4) * 1024;
225 | trackBarNvs.Value = Nvs / 1024;
226 | Calculate();
227 | }
228 |
229 | private void trackBarEeprom_ValueChanged(object sender, EventArgs e)
230 | {
231 | Eeprom = (trackBarEeprom.Value - trackBarEeprom.Value % 4) * 1024;
232 | trackBarEeprom.Value = Eeprom / 1024;
233 | Calculate();
234 | }
235 |
236 | private void trackBarSpiffs_ValueChanged(object sender, EventArgs e)
237 | {
238 | Spiffs = (trackBarSpiffs.Value - trackBarSpiffs.Value % 4) * 1024;
239 | trackBarSpiffs.Value = Spiffs / 1024;
240 | Calculate();
241 | }
242 |
243 | private void trackBarFfat_ValueChanged(object sender, EventArgs e)
244 | {
245 | Ffat = (trackBarFfat.Value - trackBarFfat.Value % 4) * 1024;
246 | trackBarFfat.Value = Ffat / 1024;
247 | Calculate();
248 | }
249 |
250 | private void checkBoxOta_CheckedChanged(object sender, EventArgs e)
251 | {
252 | OtaEnabled = checkBoxOta.Checked;
253 | checkBoxOtaLock.Enabled = checkBoxOta.Checked;
254 | if (checkBoxOta.Checked)
255 | {
256 | trackBarOta1.Enabled = !checkBoxOtaLock.Checked;
257 | Ota1 = Ota0;
258 | Calculate();
259 | }
260 | else
261 | {
262 | trackBarOta1.Enabled = false;
263 | Ota1 = 0;
264 | Calculate();
265 | }
266 | }
267 |
268 | private void checkBoxNvs_CheckedChanged(object sender, EventArgs e)
269 | {
270 | if (checkBoxNvs.Checked)
271 | {
272 | Nvs = trackBarNvs.Value * 1024;
273 | trackBarNvs.Enabled = true;
274 | Calculate();
275 | }
276 | else
277 | {
278 | Nvs = 0;
279 | trackBarNvs.Enabled = false;
280 | Calculate();
281 | }
282 | }
283 |
284 | private void checkBoxEeprom_CheckedChanged(object sender, EventArgs e)
285 | {
286 | if (checkBoxEeprom.Checked)
287 | {
288 | Eeprom = trackBarEeprom.Value * 1024;
289 | trackBarEeprom.Enabled = true;
290 | Calculate();
291 | }
292 | else
293 | {
294 | Eeprom = 0;
295 | trackBarEeprom.Enabled = false;
296 | Calculate();
297 | }
298 | }
299 |
300 | private void checkBoxSpiffs_CheckedChanged(object sender, EventArgs e)
301 | {
302 | if (checkBoxSpiffs.Checked)
303 | {
304 | Spiffs = trackBarSpiffs.Value * 1024;
305 | trackBarSpiffs.Enabled = true;
306 | Calculate();
307 | }
308 | else
309 | {
310 | Spiffs = 0;
311 | trackBarSpiffs.Enabled = false;
312 | Calculate();
313 | }
314 | }
315 |
316 | private void checkBoxFfat_CheckedChanged(object sender, EventArgs e)
317 | {
318 | if (checkBoxFfat.Checked)
319 | {
320 | Ffat = trackBarFfat.Value * 1024;
321 | trackBarFfat.Enabled = true;
322 | Calculate();
323 | }
324 | else
325 | {
326 | Ffat = 0;
327 | trackBarFfat.Enabled = false;
328 | Calculate();
329 | }
330 | }
331 |
332 | private void button3_Click(object sender, EventArgs e)
333 | {
334 | if (groupBox1.Left == progressBar1.Left)
335 | {
336 | groupBox1.Left = this.Width + 100;
337 | }
338 | else
339 | {
340 | DialogResult = DialogResult.Cancel;
341 | this.Close();
342 | }
343 | }
344 |
345 | private void button2_Click(object sender, EventArgs e)
346 | {
347 | DialogResult = DialogResult.Yes;
348 | Close();
349 | }
350 |
351 | private void trackBarOta_Scroll(object sender, EventArgs e)
352 | {
353 |
354 | }
355 |
356 | private void button1_Click(object sender, EventArgs e)
357 | {
358 | if (saveFileDialog1.ShowDialog() == DialogResult.OK)
359 | {
360 | SavePartition(saveFileDialog1.FileName);
361 | }
362 | }
363 |
364 | private async void SavePartition(string filename)
365 | {
366 | await partition.CreatePartition(Nvs, Ota0, Ota1, Eeprom, Spiffs, Ffat);
367 | File.Copy(partition.GetPartitionPath(filename.EndsWith(".bin")), filename, true);
368 | }
369 |
370 | private void checkBoxOtaLock_CheckedChanged(object sender, EventArgs e)
371 | {
372 | trackBarOta1.Enabled = !checkBoxOtaLock.Checked;
373 | }
374 |
375 | private int convertCSVInteger(string inString)
376 | {
377 | if(inString.StartsWith("0x"))
378 | {
379 | return Convert.ToInt32(inString.Trim(), 16);
380 | }
381 | else
382 | {
383 | int multiplier = 0;
384 | if(inString.Contains("K"))
385 | {
386 | inString = inString.Replace("K", "");
387 | multiplier = 1024;
388 | }
389 | else if (inString.Contains("M"))
390 | {
391 | inString = inString.Replace("M", "");
392 | multiplier = 1024 * 1024;
393 | }
394 | return Convert.ToInt32(inString.Trim(), 10) * multiplier;
395 | }
396 | }
397 |
398 | private async void button4_Click(object sender, EventArgs e)
399 | {
400 | openFileDialog1.Title = "Import partition table";
401 |
402 | if (openFileDialog1.ShowDialog() != DialogResult.OK) return;
403 |
404 | if(await partition.ImportTable(openFileDialog1.FileName))
405 | {
406 | var csv = File.ReadAllLines(partition.GetPartitionPath(false));
407 | foreach(var line in csv)
408 | {
409 | if (line.StartsWith("#")) continue;
410 | var items = line.Split(',');
411 | if (items.Count() < 5) continue;
412 | switch(items[0].Trim())
413 | {
414 | case "nvs": SetNvs(convertCSVInteger(items[4])); break;
415 | case "app0": SetOta0(convertCSVInteger(items[4]), null); break;
416 | case "app1": SetOta1(convertCSVInteger(items[4])); break;
417 | case "eeprom": SetEeprom(convertCSVInteger(items[4])); break;
418 | case "ffat": SetFfat(convertCSVInteger(items[4])); break;
419 | case "spiffs": SetSpiffs(convertCSVInteger(items[4])); break;
420 | case "otadata": Otad = convertCSVInteger(items[4]); break;
421 | default: MessageBox.Show("Error: can't import this partition: " + items[0].Trim() + " - it will be ignored", "Import partitions"); break;
422 | }
423 |
424 | /*
425 | nvs, data, nvs, 0x9000, 0x5000,
426 | otadata, data, ota, 0xe000, 0x2000,
427 | app0, app, ota_0, 0x10000, 0x180000,
428 | app1, app, ota_1, 0x190000, 0x100000,
429 | eeprom, data, 0x99, 0x310000, 0x1000,
430 | spiffs, data, spiffs, 0x311000, 0x16f000,
431 | */
432 | }
433 | }
434 | else
435 | {
436 | MessageBox.Show("Unable to import partition table " + openFileDialog1.FileName, "Import");
437 | }
438 | }
439 |
440 | private void button5_Click(object sender, EventArgs e)
441 | {
442 | treeView1.Nodes.Clear();
443 | openFileDialog1.Title = "Select partition file to insert into Arduino IDE:";
444 | openFileDialog1.FilterIndex = 1;
445 |
446 | if (sender == button6)
447 | {
448 | // do not open the dialog again
449 | }
450 | else
451 | {
452 | if (openFileDialog1.ShowDialog() != DialogResult.OK) return;
453 | }
454 |
455 | textBox1.Text = Path.GetFileNameWithoutExtension(openFileDialog1.FileName);
456 |
457 | var appData = EnterPartitionFolder();
458 | if (appData == "") return;
459 |
460 | var dirs = Directory.GetDirectories(appData);
461 | foreach(var d in dirs)
462 | {
463 | var boardsFile = File.ReadAllLines(Path.Combine(d, "boards.txt"));
464 | TreeNode tn = treeView1.Nodes.Add(Path.GetFileName(d), Path.GetFileName(d), 5);
465 | List boards = new List();
466 | foreach(var l in boardsFile)
467 | {
468 | var m = Regex.Match(l, @"([a-zA-Z0-9_]*).name=");
469 | if (m.Groups.Count > 1)
470 | {
471 | boards.Add(m.Groups[1].Value);
472 | tn.Nodes.Add(m.Groups[1].Value, m.Groups[1].Value, 5);
473 | }
474 | }
475 | boards.ForEach(x => {
476 | List tn2 = new List();
477 | foreach (var l in boardsFile)
478 | {
479 | var m = Regex.Match(l, @"^" + x + @".menu.PartitionScheme.([a-zA-Z0-9_]*)=(.*)");
480 | if (m.Groups.Count > 2)
481 | {
482 | tn2.Add(tn.Nodes[x].Nodes.Add(m.Groups[1].Value, m.Groups[2].Value, 5));
483 | //tn.Nodes.Add(m.Groups[1].Value, m.Groups[1].Value, 5);
484 | }
485 | }
486 | if(tn2.Count > 0)
487 | {
488 | foreach (var l in boardsFile)
489 | {
490 | tn2.ForEach(y =>
491 | {
492 | var m = Regex.Match(l, @"^" + x + @".menu.PartitionScheme." + y.Name + @"\." + @"([a-zA-Z0-9_.]*)=(.*)");
493 | if (m.Groups.Count > 2)
494 | {
495 | y.Nodes.Add(m.Groups[1].Value, m.Groups[1].Value + ":" + m.Groups[2].Value, 4);
496 | //tn.Nodes.Add(m.Groups[1].Value, m.Groups[1].Value, 5);
497 | }
498 | });
499 | }
500 | }
501 | else
502 | {
503 | tn.Nodes[x].Remove();
504 | }
505 | });
506 |
507 | }
508 |
509 | groupBox1.Visible = true;
510 | groupBox1.Left = progressBar1.Left;
511 | }
512 |
513 | private string EnterSubFolder(string mainFolder, string subFolder, bool showError = true)
514 | {
515 | if(!Directory.Exists(Path.Combine(mainFolder, subFolder)))
516 | {
517 | if(showError) MessageBox.Show("Folder " + Path.Combine(mainFolder, subFolder) + " not found");
518 | return "";
519 | }
520 | return Path.Combine(mainFolder, subFolder);
521 | }
522 |
523 | private string EnterPartitionFolder()
524 | {
525 | var appData = Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData);
526 | var isLocal = EnterSubFolder(appData, "local", false);
527 | if (isLocal == "") appData = EnterSubFolder(appData, "../local");
528 | else appData = isLocal;
529 | appData = EnterSubFolder(appData, "Arduino15");
530 | if (appData != "") appData = EnterSubFolder(appData, "packages");
531 | if (appData != "") appData = EnterSubFolder(appData, "esp32");
532 | if (appData != "") appData = EnterSubFolder(appData, "hardware");
533 | if (appData != "") appData = EnterSubFolder(appData, "esp32");
534 | return appData;
535 | }
536 |
537 | private void button6_Click(object sender, EventArgs e)
538 | {
539 | if (textBox2.Text.Length < 3)
540 | {
541 | MessageBox.Show("Add a description for your partition", "No description", MessageBoxButtons.OK, MessageBoxIcon.Exclamation);
542 | return;
543 | }
544 | if (treeView1.Nodes.Count == 0 || treeView1.Nodes[0].Nodes.Count == 0)
545 | {
546 | MessageBox.Show("No board found inside this directory.", "No board", MessageBoxButtons.OK, MessageBoxIcon.Exclamation);
547 | return;
548 | }
549 | TreeNode editNode = null;
550 | int partitionSize = GetSizeFromFile(openFileDialog1.FileName);
551 |
552 | for (var j = 0; j < treeView1.Nodes[0].Nodes.Count; j++)
553 | {
554 | if (treeView1.Nodes[0].Nodes[j].IsSelected)
555 | {
556 | editNode = treeView1.Nodes[0].Nodes[j];
557 | break;
558 | }
559 | }
560 | if (editNode == null)
561 | {
562 | MessageBox.Show("Please select the board to copy the new partition.", "No board", MessageBoxButtons.OK, MessageBoxIcon.Exclamation);
563 | return;
564 | }
565 | if (partitionSize == 0)
566 | {
567 | MessageBox.Show("Unable to detect partition size of OTA0", "invalid partition file", MessageBoxButtons.OK, MessageBoxIcon.Exclamation);
568 | return;
569 | }
570 |
571 | var appData = EnterPartitionFolder();
572 | appData = EnterSubFolder(appData, editNode.Parent.Text);
573 | if (appData == "") return;
574 | var boardsFile = File.ReadAllLines(Path.Combine(appData, "boards.txt")).ToList();
575 | List boards = new List();
576 | bool boardFound = false;
577 | bool partitionsFound = false;
578 | int lineIndex = 0;
579 | int index = 0;
580 | boardsFile.ForEach(l => {
581 | index++;
582 | if(lineIndex > 0)
583 | {
584 |
585 | }
586 | else if (!boardFound)
587 | {
588 | var m = Regex.Match(l, @"([a-zA-Z0-9_]*).name=");
589 | if (m.Groups.Count > 1 && m.Groups[1].Value == editNode.Text)
590 | {
591 | boardFound = true;
592 | }
593 | }
594 | else
595 | {
596 | if (!partitionsFound)
597 | {
598 | if (Regex.IsMatch(l, @"^" + editNode.Text + @".menu.PartitionScheme."))
599 | {
600 | partitionsFound = true;
601 | }
602 | }
603 | else
604 | {
605 | if (!Regex.IsMatch(l, @"^" + editNode.Text + @".menu.PartitionScheme."))
606 | {
607 | lineIndex = index - 1;
608 | }
609 | }
610 | }
611 | });
612 | if(lineIndex > 0)
613 | {
614 | boardsFile.Insert(lineIndex, editNode.Text + ".menu.PartitionScheme." + textBox1.Text + ".upload.maximum_size=" + partitionSize);
615 | boardsFile.Insert(lineIndex, editNode.Text + ".menu.PartitionScheme." + textBox1.Text + ".build.partitions=" + textBox1.Text);
616 | boardsFile.Insert(lineIndex, editNode.Text + ".menu.PartitionScheme." + textBox1.Text + "=" + textBox2.Text);
617 |
618 | File.WriteAllLines(Path.Combine(appData, "boards.txt"), boardsFile);
619 |
620 | button5_Click(sender, e);
621 | }
622 | else
623 | {
624 | MessageBox.Show("Unable to find partition scheme on this board", "index not found", MessageBoxButtons.OK, MessageBoxIcon.Exclamation);
625 | return;
626 | }
627 | }
628 |
629 | private int GetSizeFromFile(string file)
630 | {
631 | if (file.EndsWith(".bin"))
632 | {
633 | var bytes = File.ReadAllBytes(file);
634 | for (var j = 0; j < 16; j++)
635 | {
636 | if(Encoding.ASCII.GetString(bytes, 12 + 32 * j, 10).Trim('\0') == "app0")
637 | {
638 | int size = 0;
639 | for(var k=0;k<4;k++)
640 | {
641 | size = (size << 8) + bytes[11 + 32 * j - k];
642 | }
643 | return size;
644 | }
645 | }
646 | }
647 | else
648 | {
649 | var lines = File.ReadAllLines(file);
650 | }
651 | return 0;
652 | }
653 | }
654 | }
655 |
--------------------------------------------------------------------------------
/PartTool.resx:
--------------------------------------------------------------------------------
1 |
2 |
3 |
62 |
63 |
64 |
65 |
66 |
67 |
68 |
69 |
70 |
71 |
72 |
73 |
74 |
75 |
76 |
77 |
78 |
79 |
80 |
81 |
82 |
83 |
84 |
85 |
86 |
87 |
88 |
89 |
90 |
91 |
92 |
93 |
94 |
95 |
96 |
97 |
98 |
99 |
100 |
101 |
102 |
103 |
104 |
105 |
106 |
107 |
108 |
109 | text/microsoft-resx
110 |
111 |
112 | 2.0
113 |
114 |
115 | System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
116 |
117 |
118 | System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
119 |
120 |
121 | 17, 17
122 |
123 |
124 | 153, 17
125 |
126 |
127 | 293, 17
128 |
129 |
130 |
131 | AAEAAAD/////AQAAAAAAAAAMAgAAAFdTeXN0ZW0uV2luZG93cy5Gb3JtcywgVmVyc2lvbj00LjAuMC4w
132 | LCBDdWx0dXJlPW5ldXRyYWwsIFB1YmxpY0tleVRva2VuPWI3N2E1YzU2MTkzNGUwODkFAQAAACZTeXN0
133 | ZW0uV2luZG93cy5Gb3Jtcy5JbWFnZUxpc3RTdHJlYW1lcgEAAAAERGF0YQcCAgAAAAkDAAAADwMAAACO
134 | EwAAAk1TRnQBSQFMAgEBBgEAARABAAEQAQABEAEAARABAAT/AREBAAj/AUIBTQE2BwABNgMAASgDAAFA
135 | AwABIAMAAQEBAAEQBgABEJoAAf8BfwH/AX8BvQF3AVoBawE5AWcBWgFrAb0BdwH/AX9uAAH/AX8BoAEB
136 | AQABAgFAAQIBgAECAWABAgEgAQIBwAEBAYABAQFAAQEB/wF/BgABtQFWAbUBVgG1AVYBtQFWAbUBVgG1
137 | AVYBtQFWAbUBVgG1AVYBtQFWAbUBVgG1AVYBtQFWAbUBVgG1AVZEAAEZAWMBHQEBAaMBAQEAAQIBIAEC
138 | ARUBVwGcAXMB0QFGAaABAQGgAQEBYAEBAYwBYQH/AX8EAAFTAX8BDwF/AQ8BfwEPAX8BDwF/AQ8BfwEP
139 | AX8BDwF/AQ8BfwEPAX8BDwF/AQ8BfwEPAX8BDwF/AVMBf0IAAZwBcwEcAQEBHAEBAc0BBQGsAQEBBAEC
140 | AQABAgHAAQEBIAECASABAgGgASEBgAEhAQgBUQEpAWEB/wF/AgAB7QF+AagBfgGoAX4BqAF+AagBfgGo
141 | AX4BqAF+AagBfgGoAX4BqAF+AagBfgGoAX4BqAF+AagBfgHtAX5CAAEcAQEBGwEBARsBAQEbAQEBXAEJ
142 | AS0BCgEMAQIBoAECAWMBIgFjASIBZAFIAkQBxwFEAYYBTAE5AWcCAAHKAX4BhQF+AYUBfgGFAX4BhQF+
143 | AYUBfgGFAX4BhQF+AYUBfgGFAX4BhQF+AYUBfgGFAX4BhQF+AcoBfkIAARsBAQH4AQABGQEFAfkBAAH5
144 | AQAB+AEAAToBCQHAAQIBIwFAAQIBPAECATgBAgE0Aa0BWQECATwB3gF7AgAByQF6AYUBegGFAXoBhQF6
145 | AYUBegGFAXoBhQF6AYUBegGFAXoBhQF6AYUBegGFAXoBhQF6AYUBegHJAXpCAAH5AQAB1gEAAVUBFQHT
146 | AQAB1AEAAdQBAAHVAQABkAEAAQIBQAEBASwBEAFmAQABVAEAAVQBAAFwBAABqAF6AWQBegFkAXoBZAF6
147 | AWQBegFkAXoBZAF6AWQBegFkAXoBZAF6AWQBegFkAXoBZAF6AWQBegGoAXpCAAHWAQABvQEVAT0BAQE9
148 | AS4B1QEAAY8BAAGPAQABawEAAVMBdgEAAUwBAAFMAQABbAEAAWwBAAFsAgABmQF7AYcBdgFjAXoBYwF6
149 | AWMBegFjAXoBYwF6AWMBegFjAXoBYwF6AWMBegFjAXoBYwF6AWMBegFjAXoBhwF2QgABsgEAARwBAQEc
150 | AQEBHAEBARwBAQEdATIB0wEAAY0BAAEhAWABIQFQAQABYAEAAWABAAFkAQABZAIAAYgBcgFmAXYBQgF2
151 | AUIBdgFCAXYBQgF2AUIBdgFCAXYBQgF2AUIBdgFCAXYBQgF2AUIBdgFCAXYBQgF2AWYBdkIAAd0BTgEb
152 | AQEBGwEBARsBAQEbAQEBGwEBARsBAQFrAQABjQEAAYwBXQFrAV0BCAFZAYQBVAHWAW4GAAHNAXoBzQF6
153 | Ac0BegHNAXoBzQF6Ac0BegHNAXoBzQF6Ac4BegHOAXoBzgF6Ac4BegHOAXpGAAH5AQAB+QEAARkBBQE6
154 | AQkBOgEJAToBCQE6AQUBagEAAYwBUQFKAVEB5wFICgABDgF/AQ4BfwEOAX8BDgF/AQ8BfwEPAX8BLwF/
155 | AS8BfwEPAX8BDgF/AQ4BfwEOAX8BDgF/SAAB2AEpAVYBFQGXASEB+AEpARkBMgEZATYBSBEAAQ4BfwEO
156 | AX8BDgF/AQ4BfwEOAX8BDwF/AQ8BfwEPAX8BDgF/AQ4BfwEOAX8BDgF/AQ4Bf04AAd4BewFXAT4B9gEx
157 | Ab4BdxAAAS8BfwEvAX8BLwF/AS8BfwFHAWYBRwFmAUcBZgFHAWYBRwFmAUcBZgFHAWYBRwFmAUcBZmYA
158 | AUgBZgFIAWYBSAFm+gAB/wF/Af8BfwG9AXcBnAFzATkBZwH3AV4B1gFaAfcBXgFaAWsBnAFzAd4BewH/
159 | AX8B/wF/BAAB/wF/Ab0BdwGcAXMBnAFzAZwBcwGcAXMBnAFzAZwBcwGcAXMB/wF/DAAB/wF/Ab0BdwGc
160 | AXMBnAFzAZwBcwGcAXMBnAFzAZwBcwGcAXMB/wF/DAAB/wF/Af8BfwH/AX8B/wF/Af8BfwH/AX8B/wF/
161 | Af8BfwH/AX8B/wF/Af8BfwH/AX8B/wF/Af8BfwH/AX8KAAEKAWUBCQFhAY0BZQGuAWEBlAFuAbYBcgEK
162 | AWkKAAH/AX8B/wF/Af8BfwH/AX8B/wF/Af8BfwH/AX8B/wF/Ad4BewFaAWsBnAFzCgAB/wF/Af8BfwH/
163 | AX8B/wF/Af8BfwH/AX8B/wF/Af8BfwHeAXsBWgFrAZwBcwgAAf8BfwEsAU4BTQFSAU0BUgFNAVIBbQFW
164 | AW0BVgFtAVYBbQFWAW0BVgFtAVYBbQFWAU0BUgFNAVIBTAFSASwBTggAAekBYAF7AW8BegFvAfYBXgFx
165 | AVIB9gFeAVoBawH/AX8BMgFuCAAB/wF/Af8BfwH/AX8B/wF/Af8BfwH/AX8B/wF/Af8BfwHeAnsBbwG9
166 | AXcBGAFjCAAB/wF/Af8BfwH/AX8B/wF/Af8BfwH/AX8B/wF/Af8BfwHeAnsBbwG9AXcBGAFjCAAB6wFF
167 | AQsBSgEsAU4BLAFOAUwBUgFNAVIBTQFSAU0BUgFNAVIBTQFSAUwBUgEsAU4BLAFKAQsBSgHrAUUGAAHI
168 | AWQBnAFzAc0BTQGxAX8BsQF/AbIBfwGyAX8B0gF/AZMBVgFaAW8BMgFuBgAB/wF/Af8BfwH/AX8B/wF/
169 | Af8BfwH/AX8B/wF/Af8BfwHeAXsBvQF3Af8BfwG9AXcBnAFzBgAB/wF/Af8BfwH/AX8B/wF/Af8BfwH/
170 | AX8B/wF/Af8BfwHeAXsBvQF3Af8BfwG9AXcBnAFzBgABDAFKASwBTgFNAVIBTQFSAW0BVgFuAVYBjgFa
171 | AY4BWgGOAVoBbQFWAW0BVgFNAVIBTAFSASwBTgELAUoEAAHpAWQBewFzAUoBSQGOAX8BSwF7ASkBewEp
172 | AXsBKQF7AUsBewGQAX8BcgFSARgBZwHIAWQEAAH/AX8B/wF/Ad4BewH/AX8B/wF/Af8BfwH/AX8B/wF/
173 | Af8BfwE0ASYBvQF3AZwBcwGcAXMB3gF7BAAB/wF/Af8BfwHeAXsB/wF/Af8BfwH/AX8B/wF/Af8BfwH/
174 | AX8B3gF7Ab0BdwGcAXMBnAFzAd4BewQAASwBTgFNAVIBbQFWAY4BWgGOAVoBrgFeAa8BXgGvAV4BrwFe
175 | AY4BXgGOAVoBjgFaAW0BVgFNAVIBLAFOBAAB6QFoAXsBbwGtAXIBCAF3AUkBfwEIAXcBCAF3AQgBdwEI
176 | AXcBhAFgAdcBfwE5AWcBtQF2BAAB/wF/Af8BfwHeAXsB/wF/Af8BfwH/AX8B/wF/Af8BfwH/AX8B+wE6
177 | AZsBQgFbAWsB3gF7AZwBcwQAAf8BfwH/AX8B3gF7Af8BfwH/AX8B/wF/Af8BfwH/AX8B/wF/Af8BfwHb
178 | AT4B6gEUAd4BewGcAXMEAAFNAVIBbgFWAY4BWgGvAV4BrwFiAc8BYgHQAWYB0AFmAdABZgHPAWIBrwFi
179 | Aa8BXgGOAVoBbQFWAU0BUgIAAf8BfwHpAWQBMQFOAcUBaAGmAXAByQF+AWYBdgFGAXIBRgFyAWYBcgGF
180 | AVwBYwFAAbUBWgF0AXYEAAH/AX8B/wF/Ad4BewH/AX8B/wF/Af8BfwH/AX8B/wF/Af8BfwG5AToBmgE+
181 | AVgBNgENAREBnAFzBAAB/wF/Af8BfwHeAXsB/wF/Af8BfwH/AX8B/wF/Af8BfwFNAR0BWQE6AbsBQgHp
182 | ARQB/wF/AZwBcwQAAW4BVgGOAV4BrwFeAc8BYgHQAWYB8AFmAfABagHwAWoB8AFqAfABZgEgAQMB4AEC
183 | ASABAwGOAVoBbQFWAgABewF3AbUBbgGFAUABhQFgAYYBYAEGAXIBpQFxAaUBcQHnAXwBxwF5AbgBfwFk
184 | AUQB7wFFAY0BZQQAAf8BfwH/AX8B3gF7Ad4BewH/AX8B/wF/AQwBEQGzASEBNwEyAVkBOgFZATYBNwEy
185 | AdUBKQFyAR0EAAH/AX8B/wF/Ad4BewHeAXsB/wF/Af8BfwH/AX8BswEhARYBLgFYATYBeQE6AZoBPgFY
186 | ATIBswEhBAABjgFaAa8BXgHPAWIB8AFmAfABagERAWsBEQFrAREBbwEAAQMBoAECAYABBgFgAQoBgAEG
187 | AcABAgGOAVoCAAH/AX8BKwFlAa4BSQGFAVQBpwFkAYUBcQGIAXkBIwFtAegBfAGnAWABBwFpAWQBRAG1
188 | AVYBSwFtBAAB/wF/Af8BfwHeAXsB3gF7Ad4BewH/AX8B7AEQAfUBLQF4AToBeQE+AVgBOgEWAS4BtAEl
189 | AXEBGQHtAQwCAAH/AX8B/wF/Ad4BewHeAXsB3gF7AXwBawEvAREBkgEdAdUBKQEXATIBOAEyATcBMgH2
190 | ASkBUQEZBAABjgFeAc8BYgHQAWYB8AFqAREBawERAW8BMQFvATEBbwGgAQIB4AESAeABIgH/AX8BIAEj
191 | AcABCgHAAQIEAAEqAWkBewFvAWUBUAFLAWUBbAFxAWwBcQGCAWgBogFsAUsBZQERAW4BZAFAAVoBawHI
192 | AWgEAAH/AX8B/wF/Ad4BewHeAXsB3gF7Ad4BewFPAR0BVgE+AZgBQgG5AUYBuQFGAZgBQgF3AT4BVgE6
193 | ATcBNgIAAf8BfwH/AX8B3gF7Ad4BewHeAXsBOwFfAbIBKQFWAToBdwE+AZkBQgGZAUIBmQFCAXcBPgE1
194 | ATYEAAGvAV4BzwFiAfABZgERAWsBEQFvATIBcwEyAXMBgAECAcABAgEgAQ4BAAEaAf8BfwEgARoBAAEK
195 | AcABAgQAAd4BfwH/AX8BZAFEAREBagERAW4BjwF+AaMBbAFRAXoBEQFqAfABYQEpAT0BewFvAcgBZAQA
196 | Af8BfwH/AX8BvQF3Ad4BewHeAXsB3gF7AbgBTgEvAREB7AEQAZgBRgHaAU4B2gFKAdkBTgGcAXMEAAH/
197 | AX8B/wF/Ab0BdwHeAXsB3gF7Ad4BewHeAXsBmAFCAbkBRgG5AUoB2QFKAdkBSgG5AUoBuAFGBAABQgEI
198 | AUIBCAFCAQgBQgEIAWMBDAFjAQwBYwEMAUABAgFgAQIB/wF/Af8BfwH/AX8B/wF/Af8BfwHAAQIGAAF0
199 | AXIB/wF/AYYBSAHXAXIB0QF6ARcBewHXAXIB1gFuAccBPAGcAXMByAFgBgAB/wF/Af8BfwG9AXcBvQF3
200 | Ad4BewHeAXsB3gF7Ad4BewHeAXsBGwFbATwBVwExAREB/wF/AZwBcwQAAf8BfwH/AX8BvQF3Ab0BdwHe
201 | AXsB3gF7Ad4BewHeAXsBcwEVARsBUwEbAVMBTwEdAf8BfwGcAXMGAAFKASkBSgEpAUoBKQFKASkBSgEp
202 | AQgBIQH/AX8BBgEbAWgBMwEGATcB/wF/AYgBQwFIAS8BoAECBgAB/wF/AXQBcgH/AX8BewFzAYwBSQGE
203 | AUABzwFNAXsBbwHeAXsByAFgCAAB/wF/Af8BfwG9AXcBvQF3Ab0BdwHeAXsB3gF7Ad4BewHeAXsBGgFb
204 | ARsBXwHeAXsB3gF7AZwBcwQAAf8BfwH/AX8BvQF3Ab0BdwG9AXcB3gF7Ad4BewHeAXsB3gF7Ad4BewGe
205 | AWMBkwEdAd4BewGcAXMUAAFgAQIBcAFDAU4BQwH/AX8BkAFHAXABQwFiAQoIAAH/AX8B/wF/ASoBYQEq
206 | AV0BlQFuAekBXAHoAVwB6AFcCgAB/wF/Af8BfwG9AXcBvQF3Ab0BdwG9AXcBvQF3Ad4BewHeAXsB3gF7
207 | Ad4BewHeAXsB3gF7AZwBcwQAAf8BfwH/AX8BvQF3Ab0BdwG9AXcBvQF3Ab0BdwHeAXsB3gF7Ad4BewHe
208 | AXsB3gF7Ad4BewGcAXMWAAEgAQIBlAFTAbgBYwGAAQIBVAFTEAAB/wF/ATkBcwH/AX8OAAH/AX8B/wF/
209 | Af8BfwH/AX8B/wF/Af8BfwH/AX8B/wF/Af8BfwH/AX8B/wF/Af8BfwH/AX8BvQF3BAAB/wF/Af8BfwH/
210 | AX8B/wF/Af8BfwH/AX8B/wF/Af8BfwH/AX8B/wF/Af8BfwH/AX8B/wF/Ab0Bd4IAAUIBTQE+BwABPgMA
211 | ASgDAAFAAwABIAMAAQEBAAEBBgABARYAA/8BAAT/BAAB8AEPAv8EAAHgAQMBgAUAAcABAQGABQABgAEA
212 | AYAFAAGAAQABgAUAAYABAAGABQABgAEBAYAFAAGAAQEGAAGAAQEGAAGAAQEBwAEBBAABwAEHAcABAQQA
213 | AeABPwHAAQEEAAH8AT8BwAEBBAAC/wHHAf8EAAT/BAAC/wHAAQEBgAEfAYABHwGAAQAB+AEPAYABDwGA
214 | AQ8CAAHwAQcBgAEHAYABBwGAAQAB4AEDAYABAwGAAQMBgAEAAcABAQGAAQEBgAEBAYABAAHAAQEBgAEB
215 | AYABAQGAAQABgAEBAYABAQGAAQEBgAEAAYABAQGAAQEBgAEBAYABAAGAAQEBgAEAAYABAQGAAQABwAEB
216 | AYABAAGAAQEBgAEAAcABAQGAAQEBgAEBAYABAAHgAQMBgAEBAYABAQHAAQAB4AEHAYABAQGAAQEB/wGA
217 | AfABDwGAAQEBgAEBAf8BwQH+AT8BgAEBAYABAQj/Cw==
218 |
219 |
220 |
--------------------------------------------------------------------------------
/Properties/AssemblyInfo.cs:
--------------------------------------------------------------------------------
1 | using System.Reflection;
2 | using System.Runtime.CompilerServices;
3 | using System.Runtime.InteropServices;
4 |
5 | // Allgemeine Informationen über eine Assembly werden über die folgenden
6 | // Attribute gesteuert. Ändern Sie diese Attributwerte, um die Informationen zu ändern,
7 | // die einer Assembly zugeordnet sind.
8 | [assembly: AssemblyTitle("ESP tools GUI")]
9 | [assembly: AssemblyDescription("Windows GUI for the ESP tools")]
10 | [assembly: AssemblyConfiguration("")]
11 | [assembly: AssemblyCompany("-")]
12 | [assembly: AssemblyProduct("ESP Tools")]
13 | [assembly: AssemblyCopyright("Adriano")]
14 | [assembly: AssemblyTrademark("-")]
15 | [assembly: AssemblyCulture("")]
16 |
17 | // Durch Festlegen von ComVisible auf "false" werden die Typen in dieser Assembly unsichtbar
18 | // für COM-Komponenten. Wenn Sie auf einen Typ in dieser Assembly von
19 | // COM aus zugreifen müssen, sollten Sie das ComVisible-Attribut für diesen Typ auf "True" festlegen.
20 | [assembly: ComVisible(false)]
21 |
22 | // Die folgende GUID bestimmt die ID der Typbibliothek, wenn dieses Projekt für COM verfügbar gemacht wird
23 | [assembly: Guid("a5894196-3790-42a7-82f7-f7cc926368bd")]
24 |
25 | // Versionsinformationen für eine Assembly bestehen aus den folgenden vier Werten:
26 | //
27 | // Hauptversion
28 | // Nebenversion
29 | // Buildnummer
30 | // Revision
31 | //
32 | [assembly: AssemblyVersion("0.3.0.0")]
33 | [assembly: AssemblyFileVersion("0.3.0.0")]
34 |
--------------------------------------------------------------------------------
/Properties/Resources.Designer.cs:
--------------------------------------------------------------------------------
1 | //------------------------------------------------------------------------------
2 | //
3 | // Dieser Code wurde von einem Tool generiert.
4 | // Laufzeitversion:4.0.30319.42000
5 | //
6 | // Änderungen an dieser Datei können falsches Verhalten verursachen und gehen verloren, wenn
7 | // der Code erneut generiert wird.
8 | //
9 | //------------------------------------------------------------------------------
10 |
11 | namespace esp_tools_gui.Properties {
12 | using System;
13 |
14 |
15 | ///
16 | /// Eine stark typisierte Ressourcenklasse zum Suchen von lokalisierten Zeichenfolgen usw.
17 | ///
18 | // Diese Klasse wurde von der StronglyTypedResourceBuilder automatisch generiert
19 | // -Klasse über ein Tool wie ResGen oder Visual Studio automatisch generiert.
20 | // Um einen Member hinzuzufügen oder zu entfernen, bearbeiten Sie die .ResX-Datei und führen dann ResGen
21 | // mit der /str-Option erneut aus, oder Sie erstellen Ihr VS-Projekt neu.
22 | [global::System.CodeDom.Compiler.GeneratedCodeAttribute("System.Resources.Tools.StronglyTypedResourceBuilder", "16.0.0.0")]
23 | [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
24 | [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()]
25 | public class Resources {
26 |
27 | private static global::System.Resources.ResourceManager resourceMan;
28 |
29 | private static global::System.Globalization.CultureInfo resourceCulture;
30 |
31 | [global::System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")]
32 | internal Resources() {
33 | }
34 |
35 | ///
36 | /// Gibt die zwischengespeicherte ResourceManager-Instanz zurück, die von dieser Klasse verwendet wird.
37 | ///
38 | [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)]
39 | public static global::System.Resources.ResourceManager ResourceManager {
40 | get {
41 | if (object.ReferenceEquals(resourceMan, null)) {
42 | global::System.Resources.ResourceManager temp = new global::System.Resources.ResourceManager("esp_tools_gui.Properties.Resources", typeof(Resources).Assembly);
43 | resourceMan = temp;
44 | }
45 | return resourceMan;
46 | }
47 | }
48 |
49 | ///
50 | /// Überschreibt die CurrentUICulture-Eigenschaft des aktuellen Threads für alle
51 | /// Ressourcenzuordnungen, die diese stark typisierte Ressourcenklasse verwenden.
52 | ///
53 | [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)]
54 | public static global::System.Globalization.CultureInfo Culture {
55 | get {
56 | return resourceCulture;
57 | }
58 | set {
59 | resourceCulture = value;
60 | }
61 | }
62 |
63 | ///
64 | /// Sucht eine lokalisierte Ressource vom Typ System.Drawing.Bitmap.
65 | ///
66 | public static System.Drawing.Bitmap add {
67 | get {
68 | object obj = ResourceManager.GetObject("add", resourceCulture);
69 | return ((System.Drawing.Bitmap)(obj));
70 | }
71 | }
72 |
73 | ///
74 | /// Sucht eine lokalisierte Ressource vom Typ System.Drawing.Bitmap.
75 | ///
76 | public static System.Drawing.Bitmap add32 {
77 | get {
78 | object obj = ResourceManager.GetObject("add32", resourceCulture);
79 | return ((System.Drawing.Bitmap)(obj));
80 | }
81 | }
82 |
83 | ///
84 | /// Sucht eine lokalisierte Ressource vom Typ System.Drawing.Bitmap.
85 | ///
86 | public static System.Drawing.Bitmap burn {
87 | get {
88 | object obj = ResourceManager.GetObject("burn", resourceCulture);
89 | return ((System.Drawing.Bitmap)(obj));
90 | }
91 | }
92 |
93 | ///
94 | /// Sucht eine lokalisierte Ressource vom Typ System.Drawing.Bitmap.
95 | ///
96 | public static System.Drawing.Bitmap burn32 {
97 | get {
98 | object obj = ResourceManager.GetObject("burn32", resourceCulture);
99 | return ((System.Drawing.Bitmap)(obj));
100 | }
101 | }
102 |
103 | ///
104 | /// Sucht eine lokalisierte Ressource vom Typ System.Drawing.Bitmap.
105 | ///
106 | public static System.Drawing.Bitmap export {
107 | get {
108 | object obj = ResourceManager.GetObject("export", resourceCulture);
109 | return ((System.Drawing.Bitmap)(obj));
110 | }
111 | }
112 |
113 | ///
114 | /// Sucht eine lokalisierte Ressource vom Typ System.Drawing.Bitmap.
115 | ///
116 | public static System.Drawing.Bitmap export32 {
117 | get {
118 | object obj = ResourceManager.GetObject("export32", resourceCulture);
119 | return ((System.Drawing.Bitmap)(obj));
120 | }
121 | }
122 |
123 | ///
124 | /// Sucht eine lokalisierte Ressource vom Typ System.Drawing.Bitmap.
125 | ///
126 | public static System.Drawing.Bitmap import {
127 | get {
128 | object obj = ResourceManager.GetObject("import", resourceCulture);
129 | return ((System.Drawing.Bitmap)(obj));
130 | }
131 | }
132 |
133 | ///
134 | /// Sucht eine lokalisierte Ressource vom Typ System.Drawing.Bitmap.
135 | ///
136 | public static System.Drawing.Bitmap import32 {
137 | get {
138 | object obj = ResourceManager.GetObject("import32", resourceCulture);
139 | return ((System.Drawing.Bitmap)(obj));
140 | }
141 | }
142 | }
143 | }
144 |
--------------------------------------------------------------------------------
/Properties/Resources.resx:
--------------------------------------------------------------------------------
1 |
2 |
3 |
62 |
63 |
64 |
65 |
66 |
67 |
68 |
69 |
70 |
71 |
72 |
73 |
74 |
75 |
76 |
77 |
78 |
79 |
80 |
81 |
82 |
83 |
84 |
85 |
86 |
87 |
88 |
89 |
90 |
91 |
92 |
93 |
94 |
95 |
96 |
97 |
98 |
99 |
100 |
101 |
102 |
103 |
104 |
105 |
106 |
107 |
108 |
109 | text/microsoft-resx
110 |
111 |
112 | 2.0
113 |
114 |
115 | System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
116 |
117 |
118 | System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
119 |
120 |
121 |
122 | ..\images\export.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a
123 |
124 |
125 | ..\images\add.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a
126 |
127 |
128 | ..\images\import.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a
129 |
130 |
131 | ..\images\burn.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a
132 |
133 |
134 | ..\images\add32.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a
135 |
136 |
137 | ..\images\burn32.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a
138 |
139 |
140 | ..\images\export32.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a
141 |
142 |
143 | ..\images\import32.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a
144 |
145 |
--------------------------------------------------------------------------------
/Properties/Settings.Designer.cs:
--------------------------------------------------------------------------------
1 | //------------------------------------------------------------------------------
2 | //
3 | // Dieser Code wurde von einem Tool generiert.
4 | // Laufzeitversion:4.0.30319.42000
5 | //
6 | // Änderungen an dieser Datei können falsches Verhalten verursachen und gehen verloren, wenn
7 | // der Code erneut generiert wird.
8 | //
9 | //------------------------------------------------------------------------------
10 |
11 | namespace esp_tools_gui.Properties {
12 |
13 |
14 | [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()]
15 | [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.VisualStudio.Editors.SettingsDesigner.SettingsSingleFileGenerator", "16.3.0.0")]
16 | internal sealed partial class Settings : global::System.Configuration.ApplicationSettingsBase {
17 |
18 | private static Settings defaultInstance = ((Settings)(global::System.Configuration.ApplicationSettingsBase.Synchronized(new Settings())));
19 |
20 | public static Settings Default {
21 | get {
22 | return defaultInstance;
23 | }
24 | }
25 |
26 | [global::System.Configuration.UserScopedSettingAttribute()]
27 | [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
28 | [global::System.Configuration.DefaultSettingValueAttribute("")]
29 | public string comport {
30 | get {
31 | return ((string)(this["comport"]));
32 | }
33 | set {
34 | this["comport"] = value;
35 | }
36 | }
37 |
38 | [global::System.Configuration.UserScopedSettingAttribute()]
39 | [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
40 | [global::System.Configuration.DefaultSettingValueAttribute("115200")]
41 | public string combaud {
42 | get {
43 | return ((string)(this["combaud"]));
44 | }
45 | set {
46 | this["combaud"] = value;
47 | }
48 | }
49 | }
50 | }
51 |
--------------------------------------------------------------------------------
/Properties/Settings.settings:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 | 115200
10 |
11 |
12 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # ESPToolsGUI (beta)
2 | ESP Tools GUI for Windows
3 | This is just a GUI interface for the espressif python scripts.
4 |
5 | The scripts are converted to exe and the GUI just calls them over the console.
6 |
7 | 
8 |
9 | This is the first version, just to test and get some data... So the todo list is really big!
10 |
11 | In future, it should be possible to write efuses and change partition size.
12 |
13 | You can compile it by yourself (as it is not signed) or download it from the releases.
14 |
15 | | | |
16 | |--------|--------|
17 | |  |  |
18 | |  |  |
19 |
20 | ## Links
21 | ESP Tools - all Python scripts:
22 | https://github.com/espressif/esptool/wiki
23 |
24 | CX Freeze - converter to catch console output to GUI:
25 | https://github.com/anthony-tuininga/cx_Freeze
26 |
27 |
--------------------------------------------------------------------------------
/docs/screen_copy.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Adrianotiger/ESPToolsGUI/68f96feab419b5950a8643faa6f8b4c7992c05be/docs/screen_copy.jpg
--------------------------------------------------------------------------------
/docs/screen_expert.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Adrianotiger/ESPToolsGUI/68f96feab419b5950a8643faa6f8b4c7992c05be/docs/screen_expert.jpg
--------------------------------------------------------------------------------
/docs/screen_flash.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Adrianotiger/ESPToolsGUI/68f96feab419b5950a8643faa6f8b4c7992c05be/docs/screen_flash.jpg
--------------------------------------------------------------------------------
/docs/screen_fuse.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Adrianotiger/ESPToolsGUI/68f96feab419b5950a8643faa6f8b4c7992c05be/docs/screen_fuse.jpg
--------------------------------------------------------------------------------
/docs/screen_info.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Adrianotiger/ESPToolsGUI/68f96feab419b5950a8643faa6f8b4c7992c05be/docs/screen_info.jpg
--------------------------------------------------------------------------------
/docs/screen_partition.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Adrianotiger/ESPToolsGUI/68f96feab419b5950a8643faa6f8b4c7992c05be/docs/screen_partition.jpg
--------------------------------------------------------------------------------
/esp_tools_gui.csproj:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | Debug
6 | AnyCPU
7 | {C01973FB-BEF4-4DBA-AB73-E2804C840489}
8 | WinExe
9 | esp_tools_gui
10 | esp_tools_gui
11 | v4.7.2
12 | 512
13 | true
14 | true
15 | publish\
16 | true
17 | Disk
18 | false
19 | Foreground
20 | 7
21 | Days
22 | false
23 | false
24 | true
25 | 0
26 | 1.0.0.%2a
27 | false
28 | false
29 | true
30 |
31 |
32 | AnyCPU
33 | true
34 | full
35 | false
36 | bin\Debug\
37 | DEBUG;TRACE
38 | prompt
39 | 4
40 |
41 |
42 | AnyCPU
43 | pdbonly
44 | true
45 | bin\Release\
46 | TRACE
47 | prompt
48 | 4
49 |
50 |
51 | esp_tools_gui.App
52 |
53 |
54 | src\ESP32.ico
55 |
56 |
57 |
58 | PreserveNewest
59 |
60 |
61 |
62 | SettingsSingleFileGenerator
63 | Settings.Designer.cs
64 |
65 |
66 |
67 |
68 |
69 |
70 |
71 |
72 |
73 |
74 |
75 |
76 |
77 |
78 | Form
79 |
80 |
81 | PartTool.cs
82 |
83 |
84 |
85 | Form
86 |
87 |
88 | Connecting.cs
89 |
90 |
91 | Form
92 |
93 |
94 | MainPage.cs
95 |
96 |
97 |
98 | True
99 | True
100 | Resources.resx
101 |
102 |
103 | True
104 | True
105 | Settings.settings
106 |
107 |
108 |
109 |
110 |
111 |
112 |
113 |
114 |
115 |
116 | PartTool.cs
117 |
118 |
119 | Connecting.cs
120 | Designer
121 |
122 |
123 | MainPage.cs
124 |
125 |
126 | PublicResXFileCodeGenerator
127 | Resources.Designer.cs
128 | Designer
129 |
130 |
131 |
132 |
133 | False
134 | Microsoft .NET Framework 4.7.2 %28x86 und x64%29
135 | true
136 |
137 |
138 | False
139 | .NET Framework 3.5 SP1
140 | false
141 |
142 |
143 |
144 |
145 | PreserveNewest
146 |
147 |
148 | PreserveNewest
149 |
150 |
151 | PreserveNewest
152 |
153 |
154 | PreserveNewest
155 |
156 |
157 |
158 |
159 | PreserveNewest
160 |
161 |
162 |
163 |
164 |
165 |
166 |
167 |
168 |
169 |
170 | PreserveNewest
171 |
172 |
173 | PreserveNewest
174 |
175 |
176 |
177 |
178 |
179 |
--------------------------------------------------------------------------------
/esp_tools_gui.sln:
--------------------------------------------------------------------------------
1 |
2 | Microsoft Visual Studio Solution File, Format Version 12.00
3 | # Visual Studio Version 16
4 | VisualStudioVersion = 16.0.29326.143
5 | MinimumVisualStudioVersion = 10.0.40219.1
6 | Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "esp_tools_gui", "esp_tools_gui.csproj", "{C01973FB-BEF4-4DBA-AB73-E2804C840489}"
7 | EndProject
8 | Global
9 | GlobalSection(SolutionConfigurationPlatforms) = preSolution
10 | Debug|Any CPU = Debug|Any CPU
11 | Release|Any CPU = Release|Any CPU
12 | EndGlobalSection
13 | GlobalSection(ProjectConfigurationPlatforms) = postSolution
14 | {C01973FB-BEF4-4DBA-AB73-E2804C840489}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
15 | {C01973FB-BEF4-4DBA-AB73-E2804C840489}.Debug|Any CPU.Build.0 = Debug|Any CPU
16 | {C01973FB-BEF4-4DBA-AB73-E2804C840489}.Release|Any CPU.ActiveCfg = Release|Any CPU
17 | {C01973FB-BEF4-4DBA-AB73-E2804C840489}.Release|Any CPU.Build.0 = Release|Any CPU
18 | EndGlobalSection
19 | GlobalSection(SolutionProperties) = preSolution
20 | HideSolutionNode = FALSE
21 | EndGlobalSection
22 | GlobalSection(ExtensibilityGlobals) = postSolution
23 | SolutionGuid = {67AACDBD-4391-44A8-A76D-C26D13AAACC4}
24 | EndGlobalSection
25 | EndGlobal
26 |
--------------------------------------------------------------------------------
/exes/ESP32py.ico:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Adrianotiger/ESPToolsGUI/68f96feab419b5950a8643faa6f8b4c7992c05be/exes/ESP32py.ico
--------------------------------------------------------------------------------
/exes/cxfreeze.zip:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Adrianotiger/ESPToolsGUI/68f96feab419b5950a8643faa6f8b4c7992c05be/exes/cxfreeze.zip
--------------------------------------------------------------------------------
/exes/espefuse.exe:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Adrianotiger/ESPToolsGUI/68f96feab419b5950a8643faa6f8b4c7992c05be/exes/espefuse.exe
--------------------------------------------------------------------------------
/exes/espefuse.py:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env python
2 | #
3 | # SPDX-FileCopyrightText: 2014-2022 Fredrik Ahlberg, Angus Gratton,
4 | # Espressif Systems (Shanghai) CO LTD, other contributors as noted.
5 | #
6 | # SPDX-License-Identifier: GPL-2.0-or-later
7 |
8 | # This executable script is a thin wrapper around the main functionality
9 | # in the espefuse Python package
10 |
11 | # When updating this script, please also update esptool.py and espsecure.py
12 |
13 | import contextlib
14 | import os
15 | import sys
16 |
17 | if os.name != "nt":
18 | # Linux/macOS: remove current script directory to avoid importing this file
19 | # as a module; we want to import the installed espefuse module instead
20 | with contextlib.suppress(ValueError):
21 | if sys.path[0].endswith("/bin"):
22 | sys.path.pop(0)
23 | sys.path.remove(os.path.dirname(sys.executable))
24 |
25 | # Linux/macOS: delete imported module entry to force Python to load
26 | # the module from scratch; this enables importing espefuse module in
27 | # other Python scripts
28 | with contextlib.suppress(KeyError):
29 | del sys.modules["espefuse"]
30 |
31 | import espefuse
32 |
33 | if __name__ == "__main__":
34 | espefuse._main()
35 |
--------------------------------------------------------------------------------
/exes/espefuse.spec:
--------------------------------------------------------------------------------
1 | # -*- mode: python ; coding: utf-8 -*-
2 |
3 | block_cipher = None
4 |
5 |
6 | a = Analysis(['espefuse.py'],
7 | pathex=['C:\\Users\\apetrucci.GG.000\\Source\\Repos\\esp_tools_gui\\ESPToolsGUI\\exes'],
8 | binaries=[],
9 | datas=[],
10 | hiddenimports=[],
11 | hookspath=[],
12 | runtime_hooks=[],
13 | excludes=[],
14 | win_no_prefer_redirects=False,
15 | win_private_assemblies=False,
16 | cipher=block_cipher,
17 | noarchive=False)
18 | pyz = PYZ(a.pure, a.zipped_data,
19 | cipher=block_cipher)
20 | exe = EXE(pyz,
21 | a.scripts,
22 | a.binaries,
23 | a.zipfiles,
24 | a.datas,
25 | [],
26 | name='espefuse',
27 | debug=False,
28 | bootloader_ignore_signals=False,
29 | strip=False,
30 | upx=True,
31 | upx_exclude=[],
32 | runtime_tmpdir=None,
33 | console=True )
34 |
--------------------------------------------------------------------------------
/exes/espsecure.exe:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Adrianotiger/ESPToolsGUI/68f96feab419b5950a8643faa6f8b4c7992c05be/exes/espsecure.exe
--------------------------------------------------------------------------------
/exes/espsecure.py:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env python
2 | #
3 | # SPDX-FileCopyrightText: 2014-2022 Fredrik Ahlberg, Angus Gratton,
4 | # Espressif Systems (Shanghai) CO LTD, other contributors as noted.
5 | #
6 | # SPDX-License-Identifier: GPL-2.0-or-later
7 |
8 | # This executable script is a thin wrapper around the main functionality
9 | # in the espsecure Python package
10 |
11 | # When updating this script, please also update esptool.py and espefuse.py
12 |
13 | import contextlib
14 | import os
15 | import sys
16 |
17 | if os.name != "nt":
18 | # Linux/macOS: remove current script directory to avoid importing this file
19 | # as a module; we want to import the installed espsecure module instead
20 | with contextlib.suppress(ValueError):
21 | if sys.path[0].endswith("/bin"):
22 | sys.path.pop(0)
23 | sys.path.remove(os.path.dirname(sys.executable))
24 |
25 | # Linux/macOS: delete imported module entry to force Python to load
26 | # the module from scratch; this enables importing espsecure module in
27 | # other Python scripts
28 | with contextlib.suppress(KeyError):
29 | del sys.modules["espsecure"]
30 |
31 | import espsecure
32 |
33 | if __name__ == "__main__":
34 | espsecure._main()
35 |
--------------------------------------------------------------------------------
/exes/esptool.exe:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Adrianotiger/ESPToolsGUI/68f96feab419b5950a8643faa6f8b4c7992c05be/exes/esptool.exe
--------------------------------------------------------------------------------
/exes/esptool.py:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env python
2 | #
3 | # SPDX-FileCopyrightText: 2014-2022 Fredrik Ahlberg, Angus Gratton,
4 | # Espressif Systems (Shanghai) CO LTD, other contributors as noted.
5 | #
6 | # SPDX-License-Identifier: GPL-2.0-or-later
7 |
8 | # This executable script is a thin wrapper around the main functionality
9 | # in the esptool Python package
10 |
11 | # When updating this script, please also update espefuse.py and espsecure.py
12 |
13 | import contextlib
14 | import os
15 | import sys
16 |
17 | if os.name != "nt":
18 | # Linux/macOS: remove current script directory to avoid importing this file
19 | # as a module; we want to import the installed esptool module instead
20 | with contextlib.suppress(ValueError):
21 | if sys.path[0].endswith("/bin"):
22 | sys.path.pop(0)
23 | sys.path.remove(os.path.dirname(sys.executable))
24 |
25 | # Linux/macOS: delete imported module entry to force Python to load
26 | # the module from scratch; this enables importing esptool module in
27 | # other Python scripts
28 | with contextlib.suppress(KeyError):
29 | del sys.modules["esptool"]
30 |
31 | import esptool
32 |
33 | if __name__ == "__main__":
34 | esptool._main()
35 |
--------------------------------------------------------------------------------
/exes/gen_esp32part.exe:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Adrianotiger/ESPToolsGUI/68f96feab419b5950a8643faa6f8b4c7992c05be/exes/gen_esp32part.exe
--------------------------------------------------------------------------------
/exes/gen_esp32part.py:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env python
2 | #
3 | # ESP32 partition table generation tool
4 | #
5 | # Converts partition tables to/from CSV and binary formats.
6 | #
7 | # See https://docs.espressif.com/projects/esp-idf/en/latest/api-guides/partition-tables.html
8 | # for explanation of partition table structure and uses.
9 | #
10 | # SPDX-FileCopyrightText: 2016-2021 Espressif Systems (Shanghai) CO LTD
11 | # SPDX-License-Identifier: Apache-2.0
12 |
13 | from __future__ import division, print_function, unicode_literals
14 |
15 | import argparse
16 | import binascii
17 | import errno
18 | import hashlib
19 | import os
20 | import re
21 | import struct
22 | import sys
23 |
24 | MAX_PARTITION_LENGTH = 0xC00 # 3K for partition data (96 entries) leaves 1K in a 4K sector for signature
25 | MD5_PARTITION_BEGIN = b'\xEB\xEB' + b'\xFF' * 14 # The first 2 bytes are like magic numbers for MD5 sum
26 | PARTITION_TABLE_SIZE = 0x1000 # Size of partition table
27 |
28 | MIN_PARTITION_SUBTYPE_APP_OTA = 0x10
29 | NUM_PARTITION_SUBTYPE_APP_OTA = 16
30 |
31 | __version__ = '1.2'
32 |
33 | APP_TYPE = 0x00
34 | DATA_TYPE = 0x01
35 |
36 | TYPES = {
37 | 'app': APP_TYPE,
38 | 'data': DATA_TYPE,
39 | }
40 |
41 |
42 | def get_ptype_as_int(ptype):
43 | """ Convert a string which might be numeric or the name of a partition type to an integer """
44 | try:
45 | return TYPES[ptype]
46 | except KeyError:
47 | try:
48 | return int(ptype, 0)
49 | except TypeError:
50 | return ptype
51 |
52 |
53 | # Keep this map in sync with esp_partition_subtype_t enum in esp_partition.h
54 | SUBTYPES = {
55 | APP_TYPE: {
56 | 'factory': 0x00,
57 | 'test': 0x20,
58 | },
59 | DATA_TYPE: {
60 | 'ota': 0x00,
61 | 'phy': 0x01,
62 | 'nvs': 0x02,
63 | 'coredump': 0x03,
64 | 'nvs_keys': 0x04,
65 | 'efuse': 0x05,
66 | 'undefined': 0x06,
67 | 'esphttpd': 0x80,
68 | 'fat': 0x81,
69 | 'spiffs': 0x82,
70 | },
71 | }
72 |
73 |
74 | def get_subtype_as_int(ptype, subtype):
75 | """ Convert a string which might be numeric or the name of a partition subtype to an integer """
76 | try:
77 | return SUBTYPES[get_ptype_as_int(ptype)][subtype]
78 | except KeyError:
79 | try:
80 | return int(subtype, 0)
81 | except TypeError:
82 | return subtype
83 |
84 |
85 | ALIGNMENT = {
86 | APP_TYPE: 0x10000,
87 | DATA_TYPE: 0x1000,
88 | }
89 |
90 |
91 | def get_alignment_for_type(ptype):
92 | return ALIGNMENT.get(ptype, ALIGNMENT[DATA_TYPE])
93 |
94 |
95 | def get_partition_type(ptype):
96 | if ptype == 'app':
97 | return APP_TYPE
98 | if ptype == 'data':
99 | return DATA_TYPE
100 | raise InputError('Invalid partition type')
101 |
102 |
103 | def add_extra_subtypes(csv):
104 | for line_no in csv:
105 | try:
106 | fields = [line.strip() for line in line_no.split(',')]
107 | for subtype, subtype_values in SUBTYPES.items():
108 | if (int(fields[2], 16) in subtype_values.values() and subtype == get_partition_type(fields[0])):
109 | raise ValueError('Found duplicate value in partition subtype')
110 | SUBTYPES[TYPES[fields[0]]][fields[1]] = int(fields[2], 16)
111 | except InputError as err:
112 | raise InputError('Error parsing custom subtypes: %s' % err)
113 |
114 |
115 | quiet = False
116 | md5sum = True
117 | secure = False
118 | offset_part_table = 0
119 |
120 |
121 | def status(msg):
122 | """ Print status message to stderr """
123 | if not quiet:
124 | critical(msg)
125 |
126 |
127 | def critical(msg):
128 | """ Print critical message to stderr """
129 | sys.stderr.write(msg)
130 | sys.stderr.write('\n')
131 |
132 |
133 | class PartitionTable(list):
134 | def __init__(self):
135 | super(PartitionTable, self).__init__(self)
136 |
137 | @classmethod
138 | def from_file(cls, f):
139 | data = f.read()
140 | data_is_binary = data[0:2] == PartitionDefinition.MAGIC_BYTES
141 | if data_is_binary:
142 | status('Parsing binary partition input...')
143 | return cls.from_binary(data), True
144 |
145 | data = data.decode()
146 | status('Parsing CSV input...')
147 | return cls.from_csv(data), False
148 |
149 | @classmethod
150 | def from_csv(cls, csv_contents):
151 | res = PartitionTable()
152 | lines = csv_contents.splitlines()
153 |
154 | def expand_vars(f):
155 | f = os.path.expandvars(f)
156 | m = re.match(r'(? 1)
233 |
234 | # print sorted duplicate partitions by name
235 | if len(duplicates) != 0:
236 | critical('A list of partitions that have the same name:')
237 | for p in sorted(self, key=lambda x:x.name):
238 | if len(duplicates.intersection([p.name])) != 0:
239 | critical('%s' % (p.to_csv()))
240 | raise InputError('Partition names must be unique')
241 |
242 | # check for overlaps
243 | last = None
244 | for p in sorted(self, key=lambda x:x.offset):
245 | if p.offset < offset_part_table + PARTITION_TABLE_SIZE:
246 | raise InputError('Partition offset 0x%x is below 0x%x' % (p.offset, offset_part_table + PARTITION_TABLE_SIZE))
247 | if last is not None and p.offset < last.offset + last.size:
248 | raise InputError('Partition at 0x%x overlaps 0x%x-0x%x' % (p.offset, last.offset, last.offset + last.size - 1))
249 | last = p
250 |
251 | # check that otadata should be unique
252 | otadata_duplicates = [p for p in self if p.type == TYPES['data'] and p.subtype == SUBTYPES[DATA_TYPE]['ota']]
253 | if len(otadata_duplicates) > 1:
254 | for p in otadata_duplicates:
255 | critical('%s' % (p.to_csv()))
256 | raise InputError('Found multiple otadata partitions. Only one partition can be defined with type="data"(1) and subtype="ota"(0).')
257 |
258 | if len(otadata_duplicates) == 1 and otadata_duplicates[0].size != 0x2000:
259 | p = otadata_duplicates[0]
260 | critical('%s' % (p.to_csv()))
261 | raise InputError('otadata partition must have size = 0x2000')
262 |
263 | def flash_size(self):
264 | """ Return the size that partitions will occupy in flash
265 | (ie the offset the last partition ends at)
266 | """
267 | try:
268 | last = sorted(self, reverse=True)[0]
269 | except IndexError:
270 | return 0 # empty table!
271 | return last.offset + last.size
272 |
273 | def verify_size_fits(self, flash_size_bytes: int) -> None:
274 | """ Check that partition table fits into the given flash size.
275 | Raises InputError otherwise.
276 | """
277 | table_size = self.flash_size()
278 | if flash_size_bytes < table_size:
279 | mb = 1024 * 1024
280 | raise InputError('Partitions tables occupies %.1fMB of flash (%d bytes) which does not fit in configured '
281 | "flash size %dMB. Change the flash size in menuconfig under the 'Serial Flasher Config' menu." %
282 | (table_size / mb, table_size, flash_size_bytes / mb))
283 |
284 | @classmethod
285 | def from_binary(cls, b):
286 | md5 = hashlib.md5()
287 | result = cls()
288 | for o in range(0,len(b),32):
289 | data = b[o:o + 32]
290 | if len(data) != 32:
291 | raise InputError('Partition table length must be a multiple of 32 bytes')
292 | if data == b'\xFF' * 32:
293 | return result # got end marker
294 | if md5sum and data[:2] == MD5_PARTITION_BEGIN[:2]: # check only the magic number part
295 | if data[16:] == md5.digest():
296 | continue # the next iteration will check for the end marker
297 | else:
298 | raise InputError("MD5 checksums don't match! (computed: 0x%s, parsed: 0x%s)" % (md5.hexdigest(), binascii.hexlify(data[16:])))
299 | else:
300 | md5.update(data)
301 | result.append(PartitionDefinition.from_binary(data))
302 | raise InputError('Partition table is missing an end-of-table marker')
303 |
304 | def to_binary(self):
305 | result = b''.join(e.to_binary() for e in self)
306 | if md5sum:
307 | result += MD5_PARTITION_BEGIN + hashlib.md5(result).digest()
308 | if len(result) >= MAX_PARTITION_LENGTH:
309 | raise InputError('Binary partition table length (%d) longer than max' % len(result))
310 | result += b'\xFF' * (MAX_PARTITION_LENGTH - len(result)) # pad the sector, for signing
311 | return result
312 |
313 | def to_csv(self, simple_formatting=False):
314 | rows = ['# ESP-IDF Partition Table',
315 | '# Name, Type, SubType, Offset, Size, Flags']
316 | rows += [x.to_csv(simple_formatting) for x in self]
317 | return '\n'.join(rows) + '\n'
318 |
319 |
320 | class PartitionDefinition(object):
321 | MAGIC_BYTES = b'\xAA\x50'
322 |
323 | # dictionary maps flag name (as used in CSV flags list, property name)
324 | # to bit set in flags words in binary format
325 | FLAGS = {
326 | 'encrypted': 0
327 | }
328 |
329 | # add subtypes for the 16 OTA slot values ("ota_XX, etc.")
330 | for ota_slot in range(NUM_PARTITION_SUBTYPE_APP_OTA):
331 | SUBTYPES[TYPES['app']]['ota_%d' % ota_slot] = MIN_PARTITION_SUBTYPE_APP_OTA + ota_slot
332 |
333 | def __init__(self):
334 | self.name = ''
335 | self.type = None
336 | self.subtype = None
337 | self.offset = None
338 | self.size = None
339 | self.encrypted = False
340 |
341 | @classmethod
342 | def from_csv(cls, line, line_no):
343 | """ Parse a line from the CSV """
344 | line_w_defaults = line + ',,,,' # lazy way to support default fields
345 | fields = [f.strip() for f in line_w_defaults.split(',')]
346 |
347 | res = PartitionDefinition()
348 | res.line_no = line_no
349 | res.name = fields[0]
350 | res.type = res.parse_type(fields[1])
351 | res.subtype = res.parse_subtype(fields[2])
352 | res.offset = res.parse_address(fields[3])
353 | res.size = res.parse_address(fields[4])
354 | if res.size is None:
355 | raise InputError("Size field can't be empty")
356 |
357 | flags = fields[5].split(':')
358 | for flag in flags:
359 | if flag in cls.FLAGS:
360 | setattr(res, flag, True)
361 | elif len(flag) > 0:
362 | raise InputError("CSV flag column contains unknown flag '%s'" % (flag))
363 |
364 | return res
365 |
366 | def __eq__(self, other):
367 | return self.name == other.name and self.type == other.type \
368 | and self.subtype == other.subtype and self.offset == other.offset \
369 | and self.size == other.size
370 |
371 | def __repr__(self):
372 | def maybe_hex(x):
373 | return '0x%x' % x if x is not None else 'None'
374 | return "PartitionDefinition('%s', 0x%x, 0x%x, %s, %s)" % (self.name, self.type, self.subtype or 0,
375 | maybe_hex(self.offset), maybe_hex(self.size))
376 |
377 | def __str__(self):
378 | return "Part '%s' %d/%d @ 0x%x size 0x%x" % (self.name, self.type, self.subtype, self.offset or -1, self.size or -1)
379 |
380 | def __cmp__(self, other):
381 | return self.offset - other.offset
382 |
383 | def __lt__(self, other):
384 | return self.offset < other.offset
385 |
386 | def __gt__(self, other):
387 | return self.offset > other.offset
388 |
389 | def __le__(self, other):
390 | return self.offset <= other.offset
391 |
392 | def __ge__(self, other):
393 | return self.offset >= other.offset
394 |
395 | def parse_type(self, strval):
396 | if strval == '':
397 | raise InputError("Field 'type' can't be left empty.")
398 | return parse_int(strval, TYPES)
399 |
400 | def parse_subtype(self, strval):
401 | if strval == '':
402 | if self.type == TYPES['app']:
403 | raise InputError('App partition cannot have an empty subtype')
404 | return SUBTYPES[DATA_TYPE]['undefined']
405 | return parse_int(strval, SUBTYPES.get(self.type, {}))
406 |
407 | def parse_address(self, strval):
408 | if strval == '':
409 | return None # PartitionTable will fill in default
410 | return parse_int(strval)
411 |
412 | def verify(self):
413 | if self.type is None:
414 | raise ValidationError(self, 'Type field is not set')
415 | if self.subtype is None:
416 | raise ValidationError(self, 'Subtype field is not set')
417 | if self.offset is None:
418 | raise ValidationError(self, 'Offset field is not set')
419 | align = get_alignment_for_type(self.type)
420 | if self.offset % align:
421 | raise ValidationError(self, 'Offset 0x%x is not aligned to 0x%x' % (self.offset, align))
422 | if self.size % align and secure and self.type == APP_TYPE:
423 | raise ValidationError(self, 'Size 0x%x is not aligned to 0x%x' % (self.size, align))
424 | if self.size is None:
425 | raise ValidationError(self, 'Size field is not set')
426 |
427 | if self.name in TYPES and TYPES.get(self.name, '') != self.type:
428 | critical("WARNING: Partition has name '%s' which is a partition type, but does not match this partition's "
429 | 'type (0x%x). Mistake in partition table?' % (self.name, self.type))
430 | all_subtype_names = []
431 | for names in (t.keys() for t in SUBTYPES.values()):
432 | all_subtype_names += names
433 | if self.name in all_subtype_names and SUBTYPES.get(self.type, {}).get(self.name, '') != self.subtype:
434 | critical("WARNING: Partition has name '%s' which is a partition subtype, but this partition has "
435 | 'non-matching type 0x%x and subtype 0x%x. Mistake in partition table?' % (self.name, self.type, self.subtype))
436 |
437 | STRUCT_FORMAT = b'<2sBBLL16sL'
438 |
439 | @classmethod
440 | def from_binary(cls, b):
441 | if len(b) != 32:
442 | raise InputError('Partition definition length must be exactly 32 bytes. Got %d bytes.' % len(b))
443 | res = cls()
444 | (magic, res.type, res.subtype, res.offset,
445 | res.size, res.name, flags) = struct.unpack(cls.STRUCT_FORMAT, b)
446 | if b'\x00' in res.name: # strip null byte padding from name string
447 | res.name = res.name[:res.name.index(b'\x00')]
448 | res.name = res.name.decode()
449 | if magic != cls.MAGIC_BYTES:
450 | raise InputError('Invalid magic bytes (%r) for partition definition' % magic)
451 | for flag,bit in cls.FLAGS.items():
452 | if flags & (1 << bit):
453 | setattr(res, flag, True)
454 | flags &= ~(1 << bit)
455 | if flags != 0:
456 | critical('WARNING: Partition definition had unknown flag(s) 0x%08x. Newer binary format?' % flags)
457 | return res
458 |
459 | def get_flags_list(self):
460 | return [flag for flag in self.FLAGS.keys() if getattr(self, flag)]
461 |
462 | def to_binary(self):
463 | flags = sum((1 << self.FLAGS[flag]) for flag in self.get_flags_list())
464 | return struct.pack(self.STRUCT_FORMAT,
465 | self.MAGIC_BYTES,
466 | self.type, self.subtype,
467 | self.offset, self.size,
468 | self.name.encode(),
469 | flags)
470 |
471 | def to_csv(self, simple_formatting=False):
472 | def addr_format(a, include_sizes):
473 | if not simple_formatting and include_sizes:
474 | for (val, suffix) in [(0x100000, 'M'), (0x400, 'K')]:
475 | if a % val == 0:
476 | return '%d%s' % (a // val, suffix)
477 | return '0x%x' % a
478 |
479 | def lookup_keyword(t, keywords):
480 | for k,v in keywords.items():
481 | if simple_formatting is False and t == v:
482 | return k
483 | return '%d' % t
484 |
485 | def generate_text_flags():
486 | """ colon-delimited list of flags """
487 | return ':'.join(self.get_flags_list())
488 |
489 | return ','.join([self.name,
490 | lookup_keyword(self.type, TYPES),
491 | lookup_keyword(self.subtype, SUBTYPES.get(self.type, {})),
492 | addr_format(self.offset, False),
493 | addr_format(self.size, True),
494 | generate_text_flags()])
495 |
496 |
497 | def parse_int(v, keywords={}):
498 | """Generic parser for integer fields - int(x,0) with provision for
499 | k/m/K/M suffixes and 'keyword' value lookup.
500 | """
501 | try:
502 | for letter, multiplier in [('k', 1024), ('m', 1024 * 1024)]:
503 | if v.lower().endswith(letter):
504 | return parse_int(v[:-1], keywords) * multiplier
505 | return int(v, 0)
506 | except ValueError:
507 | if len(keywords) == 0:
508 | raise InputError('Invalid field value %s' % v)
509 | try:
510 | return keywords[v.lower()]
511 | except KeyError:
512 | raise InputError("Value '%s' is not valid. Known keywords: %s" % (v, ', '.join(keywords)))
513 |
514 |
515 | def main():
516 | global quiet
517 | global md5sum
518 | global offset_part_table
519 | global secure
520 | parser = argparse.ArgumentParser(description='ESP32 partition table utility')
521 |
522 | parser.add_argument('--flash-size', help='Optional flash size limit, checks partition table fits in flash',
523 | nargs='?', choices=['1MB', '2MB', '4MB', '8MB', '16MB', '32MB', '64MB', '128MB'])
524 | parser.add_argument('--disable-md5sum', help='Disable md5 checksum for the partition table', default=False, action='store_true')
525 | parser.add_argument('--no-verify', help="Don't verify partition table fields", action='store_true')
526 | parser.add_argument('--verify', '-v', help='Verify partition table fields (deprecated, this behaviour is '
527 | 'enabled by default and this flag does nothing.', action='store_true')
528 | parser.add_argument('--quiet', '-q', help="Don't print non-critical status messages to stderr", action='store_true')
529 | parser.add_argument('--offset', '-o', help='Set offset partition table', default='0x8000')
530 | parser.add_argument('--secure', help='Require app partitions to be suitable for secure boot', action='store_true')
531 | parser.add_argument('--extra-partition-subtypes', help='Extra partition subtype entries', nargs='*')
532 | parser.add_argument('input', help='Path to CSV or binary file to parse.', type=argparse.FileType('rb'))
533 | parser.add_argument('output', help='Path to output converted binary or CSV file. Will use stdout if omitted.',
534 | nargs='?', default='-')
535 |
536 | args = parser.parse_args()
537 |
538 | quiet = args.quiet
539 | md5sum = not args.disable_md5sum
540 | secure = args.secure
541 | offset_part_table = int(args.offset, 0)
542 | if args.extra_partition_subtypes:
543 | add_extra_subtypes(args.extra_partition_subtypes)
544 |
545 | table, input_is_binary = PartitionTable.from_file(args.input)
546 |
547 | if not args.no_verify:
548 | status('Verifying table...')
549 | table.verify()
550 |
551 | if args.flash_size:
552 | size_mb = int(args.flash_size.replace('MB', ''))
553 | table.verify_size_fits(size_mb * 1024 * 1024)
554 |
555 | # Make sure that the output directory is created
556 | output_dir = os.path.abspath(os.path.dirname(args.output))
557 |
558 | if not os.path.exists(output_dir):
559 | try:
560 | os.makedirs(output_dir)
561 | except OSError as exc:
562 | if exc.errno != errno.EEXIST:
563 | raise
564 |
565 | if input_is_binary:
566 | output = table.to_csv()
567 | with sys.stdout if args.output == '-' else open(args.output, 'w') as f:
568 | f.write(output)
569 | else:
570 | output = table.to_binary()
571 | try:
572 | stdout_binary = sys.stdout.buffer # Python 3
573 | except AttributeError:
574 | stdout_binary = sys.stdout
575 | with stdout_binary if args.output == '-' else open(args.output, 'wb') as f:
576 | f.write(output)
577 |
578 |
579 | class InputError(RuntimeError):
580 | def __init__(self, e):
581 | super(InputError, self).__init__(e)
582 |
583 |
584 | class ValidationError(InputError):
585 | def __init__(self, partition, message):
586 | super(ValidationError, self).__init__(
587 | 'Partition %s invalid: %s' % (partition.name, message))
588 |
589 |
590 | if __name__ == '__main__':
591 | try:
592 | main()
593 | except InputError as e:
594 | print(e, file=sys.stderr)
595 | sys.exit(2)
--------------------------------------------------------------------------------
/exes/parttool.exe:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Adrianotiger/ESPToolsGUI/68f96feab419b5950a8643faa6f8b4c7992c05be/exes/parttool.exe
--------------------------------------------------------------------------------
/exes/parttool.py:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env python
2 | #
3 | # parttool is used to perform partition level operations - reading,
4 | # writing, erasing and getting info about the partition.
5 | #
6 | # SPDX-FileCopyrightText: 2018-2022 Espressif Systems (Shanghai) CO LTD
7 | # SPDX-License-Identifier: Apache-2.0
8 | from __future__ import division, print_function
9 |
10 | import argparse
11 | import os
12 | import re
13 | import subprocess
14 | import sys
15 | import tempfile
16 |
17 | import gen_esp32part as gen
18 |
19 | __version__ = '2.0'
20 |
21 | COMPONENTS_PATH = os.path.expandvars(os.path.join('$IDF_PATH', 'components'))
22 | ESPTOOL_PY = os.path.join(COMPONENTS_PATH, 'esptool_py', 'esptool', 'esptool.py')
23 |
24 | PARTITION_TABLE_OFFSET = 0x8000
25 |
26 |
27 | quiet = False
28 |
29 |
30 | def status(msg):
31 | if not quiet:
32 | print(msg)
33 |
34 |
35 | class _PartitionId():
36 |
37 | def __init__(self, name=None, p_type=None, subtype=None, part_list=None):
38 | self.name = name
39 | self.type = p_type
40 | self.subtype = subtype
41 | self.part_list = part_list
42 |
43 |
44 | class PartitionName(_PartitionId):
45 |
46 | def __init__(self, name):
47 | _PartitionId.__init__(self, name=name)
48 |
49 |
50 | class PartitionType(_PartitionId):
51 |
52 | def __init__(self, p_type, subtype, part_list=None):
53 | _PartitionId.__init__(self, p_type=p_type, subtype=subtype, part_list=part_list)
54 |
55 |
56 | PARTITION_BOOT_DEFAULT = _PartitionId()
57 |
58 |
59 | class ParttoolTarget():
60 |
61 | def __init__(self, port=None, baud=None, partition_table_offset=PARTITION_TABLE_OFFSET, partition_table_file=None,
62 | esptool_args=[], esptool_write_args=[], esptool_read_args=[], esptool_erase_args=[]):
63 | self.port = port
64 | self.baud = baud
65 |
66 | gen.offset_part_table = partition_table_offset
67 |
68 | def parse_esptool_args(esptool_args):
69 | results = list()
70 | for arg in esptool_args:
71 | pattern = re.compile(r'(.+)=(.+)')
72 | result = pattern.match(arg)
73 | try:
74 | key = result.group(1)
75 | value = result.group(2)
76 | results.extend(['--' + key, value])
77 | except AttributeError:
78 | results.extend(['--' + arg])
79 | return results
80 |
81 | self.esptool_args = parse_esptool_args(esptool_args)
82 | self.esptool_write_args = parse_esptool_args(esptool_write_args)
83 | self.esptool_read_args = parse_esptool_args(esptool_read_args)
84 | self.esptool_erase_args = parse_esptool_args(esptool_erase_args)
85 |
86 | if partition_table_file:
87 | partition_table = None
88 | with open(partition_table_file, 'rb') as f:
89 | input_is_binary = (f.read(2) == gen.PartitionDefinition.MAGIC_BYTES)
90 | f.seek(0)
91 | if input_is_binary:
92 | partition_table = gen.PartitionTable.from_binary(f.read())
93 |
94 | if partition_table is None:
95 | with open(partition_table_file, 'r') as f:
96 | f.seek(0)
97 | partition_table = gen.PartitionTable.from_csv(f.read())
98 | else:
99 | temp_file = tempfile.NamedTemporaryFile(delete=False)
100 | temp_file.close()
101 |
102 | try:
103 | self._call_esptool(['read_flash', str(partition_table_offset), str(gen.MAX_PARTITION_LENGTH), temp_file.name])
104 | with open(temp_file.name, 'rb') as f:
105 | partition_table = gen.PartitionTable.from_binary(f.read())
106 | finally:
107 | os.unlink(temp_file.name)
108 |
109 | self.partition_table = partition_table
110 |
111 | # set `out` to None to redirect the output to the STDOUT
112 | # otherwise set `out` to file descriptor
113 | # beware that the method does not close the file descriptor
114 | def _call_esptool(self, args, out=None):
115 | esptool_args = [sys.executable, ESPTOOL_PY] + self.esptool_args
116 |
117 | if self.port:
118 | esptool_args += ['--port', self.port]
119 |
120 | if self.baud:
121 | esptool_args += ['--baud', str(self.baud)]
122 |
123 | esptool_args += args
124 |
125 | print('Running %s...' % (' '.join(esptool_args)))
126 | try:
127 | subprocess.check_call(esptool_args, stdout=out, stderr=subprocess.STDOUT)
128 | except subprocess.CalledProcessError as e:
129 | print('An exception: **', str(e), '** occurred in _call_esptool.', file=out)
130 | raise e
131 |
132 | def get_partition_info(self, partition_id):
133 | partition = None
134 |
135 | if partition_id.name:
136 | partition = self.partition_table.find_by_name(partition_id.name)
137 | elif partition_id.type and partition_id.subtype:
138 | partition = list(self.partition_table.find_by_type(partition_id.type, partition_id.subtype))
139 | if not partition_id.part_list:
140 | partition = partition[0]
141 | else: # default boot partition
142 | search = ['factory'] + ['ota_{}'.format(d) for d in range(16)]
143 | for subtype in search:
144 | partition = next(self.partition_table.find_by_type('app', subtype), None)
145 | if partition:
146 | break
147 |
148 | if not partition:
149 | raise Exception('Partition does not exist')
150 |
151 | return partition
152 |
153 | def erase_partition(self, partition_id):
154 | partition = self.get_partition_info(partition_id)
155 | self._call_esptool(['erase_region', str(partition.offset), str(partition.size)] + self.esptool_erase_args)
156 |
157 | def read_partition(self, partition_id, output):
158 | partition = self.get_partition_info(partition_id)
159 | self._call_esptool(['read_flash', str(partition.offset), str(partition.size), output] + self.esptool_read_args)
160 |
161 | def write_partition(self, partition_id, input):
162 | self.erase_partition(partition_id)
163 |
164 | partition = self.get_partition_info(partition_id)
165 |
166 | with open(input, 'rb') as input_file:
167 | content_len = len(input_file.read())
168 |
169 | if content_len > partition.size:
170 | raise Exception('Input file size exceeds partition size')
171 |
172 | self._call_esptool(['write_flash', str(partition.offset), input] + self.esptool_write_args)
173 |
174 |
175 | def _write_partition(target, partition_id, input):
176 | target.write_partition(partition_id, input)
177 | partition = target.get_partition_info(partition_id)
178 | status("Written contents of file '{}' at offset 0x{:x}".format(input, partition.offset))
179 |
180 |
181 | def _read_partition(target, partition_id, output):
182 | target.read_partition(partition_id, output)
183 | partition = target.get_partition_info(partition_id)
184 | status("Read partition '{}' contents from device at offset 0x{:x} to file '{}'"
185 | .format(partition.name, partition.offset, output))
186 |
187 |
188 | def _erase_partition(target, partition_id):
189 | target.erase_partition(partition_id)
190 | partition = target.get_partition_info(partition_id)
191 | status("Erased partition '{}' at offset 0x{:x}".format(partition.name, partition.offset))
192 |
193 |
194 | def _get_partition_info(target, partition_id, info):
195 | try:
196 | partitions = target.get_partition_info(partition_id)
197 | if not isinstance(partitions, list):
198 | partitions = [partitions]
199 | except Exception:
200 | return
201 |
202 | infos = []
203 |
204 | try:
205 | for p in partitions:
206 | info_dict = {
207 | 'name': '{}'.format(p.name),
208 | 'type': '{}'.format(p.type),
209 | 'subtype': '{}'.format(p.subtype),
210 | 'offset': '0x{:x}'.format(p.offset),
211 | 'size': '0x{:x}'.format(p.size),
212 | 'encrypted': '{}'.format(p.encrypted)
213 | }
214 | for i in info:
215 | infos += [info_dict[i]]
216 | except KeyError:
217 | raise RuntimeError('Request for unknown partition info {}'.format(i))
218 |
219 | print(' '.join(infos))
220 |
221 |
222 | def main():
223 | global quiet
224 |
225 | parser = argparse.ArgumentParser('ESP-IDF Partitions Tool')
226 |
227 | parser.add_argument('--quiet', '-q', help='suppress stderr messages', action='store_true')
228 | parser.add_argument('--esptool-args', help='additional main arguments for esptool', nargs='+')
229 | parser.add_argument('--esptool-write-args', help='additional subcommand arguments when writing to flash', nargs='+')
230 | parser.add_argument('--esptool-read-args', help='additional subcommand arguments when reading flash', nargs='+')
231 | parser.add_argument('--esptool-erase-args', help='additional subcommand arguments when erasing regions of flash', nargs='+')
232 |
233 | # By default the device attached to the specified port is queried for the partition table. If a partition table file
234 | # is specified, that is used instead.
235 | parser.add_argument('--port', '-p', help='port where the target device of the command is connected to; the partition table is sourced from this device \
236 | when the partition table file is not defined')
237 | parser.add_argument('--baud', '-b', help='baudrate to use', type=int)
238 |
239 | parser.add_argument('--partition-table-offset', '-o', help='offset to read the partition table from', type=str)
240 | parser.add_argument('--partition-table-file', '-f', help='file (CSV/binary) to read the partition table from; \
241 | overrides device attached to specified port as the partition table source when defined')
242 |
243 | partition_selection_parser = argparse.ArgumentParser(add_help=False)
244 |
245 | # Specify what partition to perform the operation on. This can either be specified using the
246 | # partition name or the first partition that matches the specified type/subtype
247 | partition_selection_args = partition_selection_parser.add_mutually_exclusive_group()
248 |
249 | partition_selection_args.add_argument('--partition-name', '-n', help='name of the partition')
250 | partition_selection_args.add_argument('--partition-type', '-t', help='type of the partition')
251 | partition_selection_args.add_argument('--partition-boot-default', '-d', help='select the default boot partition \
252 | using the same fallback logic as the IDF bootloader', action='store_true')
253 |
254 | partition_selection_parser.add_argument('--partition-subtype', '-s', help='subtype of the partition')
255 | partition_selection_parser.add_argument('--extra-partition-subtypes', help='Extra partition subtype entries', nargs='*')
256 |
257 | subparsers = parser.add_subparsers(dest='operation', help='run parttool -h for additional help')
258 |
259 | # Specify the supported operations
260 | read_part_subparser = subparsers.add_parser('read_partition', help='read partition from device and dump contents into a file',
261 | parents=[partition_selection_parser])
262 | read_part_subparser.add_argument('--output', help='file to dump the read partition contents to')
263 |
264 | write_part_subparser = subparsers.add_parser('write_partition', help='write contents of a binary file to partition on device',
265 | parents=[partition_selection_parser])
266 | write_part_subparser.add_argument('--input', help='file whose contents are to be written to the partition offset')
267 |
268 | subparsers.add_parser('erase_partition', help='erase the contents of a partition on the device', parents=[partition_selection_parser])
269 |
270 | print_partition_info_subparser = subparsers.add_parser('get_partition_info', help='get partition information', parents=[partition_selection_parser])
271 | print_partition_info_subparser.add_argument('--info', help='type of partition information to get',
272 | choices=['name', 'type', 'subtype', 'offset', 'size', 'encrypted'], default=['offset', 'size'], nargs='+')
273 | print_partition_info_subparser.add_argument('--part_list', help='Get a list of partitions suitable for a given type', action='store_true')
274 |
275 | args = parser.parse_args()
276 | quiet = args.quiet
277 |
278 | # No operation specified, display help and exit
279 | if args.operation is None:
280 | if not quiet:
281 | parser.print_help()
282 | sys.exit(1)
283 |
284 | # Prepare the partition to perform operation on
285 | if args.partition_name:
286 | partition_id = PartitionName(args.partition_name)
287 | elif args.partition_type:
288 | if not args.partition_subtype:
289 | raise RuntimeError('--partition-subtype should be defined when --partition-type is defined')
290 | partition_id = PartitionType(args.partition_type, args.partition_subtype, getattr(args, 'part_list', None))
291 | elif args.partition_boot_default:
292 | partition_id = PARTITION_BOOT_DEFAULT
293 | else:
294 | raise RuntimeError('Partition to operate on should be defined using --partition-name OR \
295 | partition-type,--partition-subtype OR partition-boot-default')
296 |
297 | # Prepare the device to perform operation on
298 | target_args = {}
299 |
300 | if args.port:
301 | target_args['port'] = args.port
302 |
303 | if args.baud:
304 | target_args['baud'] = args.baud
305 |
306 | if args.partition_table_file:
307 | target_args['partition_table_file'] = args.partition_table_file
308 |
309 | if args.partition_table_offset:
310 | target_args['partition_table_offset'] = int(args.partition_table_offset, 0)
311 |
312 | if args.esptool_args:
313 | target_args['esptool_args'] = args.esptool_args
314 |
315 | if args.esptool_write_args:
316 | target_args['esptool_write_args'] = args.esptool_write_args
317 |
318 | if args.esptool_read_args:
319 | target_args['esptool_read_args'] = args.esptool_read_args
320 |
321 | if args.esptool_erase_args:
322 | target_args['esptool_erase_args'] = args.esptool_erase_args
323 |
324 | if args.extra_partition_subtypes:
325 | gen.add_extra_subtypes(args.extra_partition_subtypes)
326 |
327 | target = ParttoolTarget(**target_args)
328 |
329 | # Create the operation table and execute the operation
330 | common_args = {'target':target, 'partition_id':partition_id}
331 | parttool_ops = {
332 | 'erase_partition':(_erase_partition, []),
333 | 'read_partition':(_read_partition, ['output']),
334 | 'write_partition':(_write_partition, ['input']),
335 | 'get_partition_info':(_get_partition_info, ['info'])
336 | }
337 |
338 | (op, op_args) = parttool_ops[args.operation]
339 |
340 | for op_arg in op_args:
341 | common_args.update({op_arg:vars(args)[op_arg]})
342 |
343 | if quiet:
344 | # If exceptions occur, suppress and exit quietly
345 | try:
346 | op(**common_args)
347 | except Exception:
348 | sys.exit(2)
349 | else:
350 | try:
351 | op(**common_args)
352 | except gen.InputError as e:
353 | print(e, file=sys.stderr)
354 | sys.exit(2)
355 |
356 |
357 | if __name__ == '__main__':
358 | main()
--------------------------------------------------------------------------------
/exes/python3.dll:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Adrianotiger/ESPToolsGUI/68f96feab419b5950a8643faa6f8b4c7992c05be/exes/python3.dll
--------------------------------------------------------------------------------
/exes/python310.dll:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Adrianotiger/ESPToolsGUI/68f96feab419b5950a8643faa6f8b4c7992c05be/exes/python310.dll
--------------------------------------------------------------------------------
/exes/setup_esp.py:
--------------------------------------------------------------------------------
1 | from cx_Freeze import setup, Executable
2 |
3 | executables = [
4 | Executable("gen_esp32part.py", base="Console", icon="ESP32py.ico"),
5 | Executable("parttool.py", base="Console", icon="ESP32py.ico")
6 | ]
7 |
8 | packages = ["idna", "encodings"]
9 | options = {
10 | 'build_exe': {
11 | 'packages':packages,
12 | 'include_files': ['ESP32py.ico']
13 | },
14 | }
15 |
16 | setup(
17 | name = "Esp32 Tool",
18 | options = options,
19 | version = "1.0",
20 | description = 'Espressif ESP32 tool',
21 | executables = executables
22 | )
--------------------------------------------------------------------------------
/images/add.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Adrianotiger/ESPToolsGUI/68f96feab419b5950a8643faa6f8b4c7992c05be/images/add.png
--------------------------------------------------------------------------------
/images/add32.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Adrianotiger/ESPToolsGUI/68f96feab419b5950a8643faa6f8b4c7992c05be/images/add32.png
--------------------------------------------------------------------------------
/images/burn.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Adrianotiger/ESPToolsGUI/68f96feab419b5950a8643faa6f8b4c7992c05be/images/burn.png
--------------------------------------------------------------------------------
/images/burn32.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Adrianotiger/ESPToolsGUI/68f96feab419b5950a8643faa6f8b4c7992c05be/images/burn32.png
--------------------------------------------------------------------------------
/images/esp32.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Adrianotiger/ESPToolsGUI/68f96feab419b5950a8643faa6f8b4c7992c05be/images/esp32.jpg
--------------------------------------------------------------------------------
/images/export.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Adrianotiger/ESPToolsGUI/68f96feab419b5950a8643faa6f8b4c7992c05be/images/export.png
--------------------------------------------------------------------------------
/images/export32.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Adrianotiger/ESPToolsGUI/68f96feab419b5950a8643faa6f8b4c7992c05be/images/export32.png
--------------------------------------------------------------------------------
/images/import.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Adrianotiger/ESPToolsGUI/68f96feab419b5950a8643faa6f8b4c7992c05be/images/import.png
--------------------------------------------------------------------------------
/images/import32.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Adrianotiger/ESPToolsGUI/68f96feab419b5950a8643faa6f8b4c7992c05be/images/import32.png
--------------------------------------------------------------------------------
/images/kchart.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Adrianotiger/ESPToolsGUI/68f96feab419b5950a8643faa6f8b4c7992c05be/images/kchart.png
--------------------------------------------------------------------------------
/images/kde-folder-open.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Adrianotiger/ESPToolsGUI/68f96feab419b5950a8643faa6f8b4c7992c05be/images/kde-folder-open.png
--------------------------------------------------------------------------------
/src/App.config:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 | 115200
23 |
24 |
25 |
26 |
--------------------------------------------------------------------------------
/src/App.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.Linq;
4 | using System.Text;
5 | using System.Threading.Tasks;
6 |
7 | namespace esp_tools_gui
8 | {
9 | class App
10 | {
11 | public static MainPage form;
12 |
13 | [STAThread]
14 | static void Main() {
15 |
16 | form = new MainPage();
17 | form.ShowDialog();
18 | }
19 | }
20 | }
21 |
--------------------------------------------------------------------------------
/src/Connecting.Designer.cs:
--------------------------------------------------------------------------------
1 | namespace esp_tools_gui
2 | {
3 | partial class Connecting
4 | {
5 | ///
6 | /// Required designer variable.
7 | ///
8 | private System.ComponentModel.IContainer components = null;
9 |
10 | ///
11 | /// Clean up any resources being used.
12 | ///
13 | /// true if managed resources should be disposed; otherwise, false.
14 | protected override void Dispose(bool disposing)
15 | {
16 | if (disposing && (components != null))
17 | {
18 | components.Dispose();
19 | }
20 | base.Dispose(disposing);
21 | }
22 |
23 | #region Windows Form Designer generated code
24 |
25 | ///
26 | /// Required method for Designer support - do not modify
27 | /// the contents of this method with the code editor.
28 | ///
29 | private void InitializeComponent()
30 | {
31 | this.components = new System.ComponentModel.Container();
32 | System.ComponentModel.ComponentResourceManager resources = new System.ComponentModel.ComponentResourceManager(typeof(Connecting));
33 | this.TitleLabel = new System.Windows.Forms.Label();
34 | this.progressBar1 = new System.Windows.Forms.ProgressBar();
35 | this.label2 = new System.Windows.Forms.Label();
36 | this.ConnectionLabel = new System.Windows.Forms.Label();
37 | this.timer1 = new System.Windows.Forms.Timer(this.components);
38 | this.linkLabel1 = new System.Windows.Forms.LinkLabel();
39 | this.SuspendLayout();
40 | //
41 | // TitleLabel
42 | //
43 | this.TitleLabel.AutoSize = true;
44 | this.TitleLabel.Font = new System.Drawing.Font("Microsoft Sans Serif", 21.75F, System.Drawing.FontStyle.Bold, System.Drawing.GraphicsUnit.Point, ((byte)(0)));
45 | this.TitleLabel.Location = new System.Drawing.Point(145, 9);
46 | this.TitleLabel.Name = "TitleLabel";
47 | this.TitleLabel.Size = new System.Drawing.Size(172, 33);
48 | this.TitleLabel.TabIndex = 0;
49 | this.TitleLabel.Text = "Connecting";
50 | //
51 | // progressBar1
52 | //
53 | this.progressBar1.Location = new System.Drawing.Point(28, 54);
54 | this.progressBar1.Name = "progressBar1";
55 | this.progressBar1.Size = new System.Drawing.Size(405, 14);
56 | this.progressBar1.Style = System.Windows.Forms.ProgressBarStyle.Continuous;
57 | this.progressBar1.TabIndex = 1;
58 | this.progressBar1.Value = 100;
59 | //
60 | // label2
61 | //
62 | this.label2.AutoSize = true;
63 | this.label2.Location = new System.Drawing.Point(189, 82);
64 | this.label2.Name = "label2";
65 | this.label2.Size = new System.Drawing.Size(85, 13);
66 | this.label2.TabIndex = 2;
67 | this.label2.Text = "Request started:";
68 | //
69 | // ConnectionLabel
70 | //
71 | this.ConnectionLabel.Location = new System.Drawing.Point(28, 95);
72 | this.ConnectionLabel.Name = "ConnectionLabel";
73 | this.ConnectionLabel.Size = new System.Drawing.Size(405, 37);
74 | this.ConnectionLabel.TabIndex = 3;
75 | this.ConnectionLabel.Text = "-";
76 | this.ConnectionLabel.TextAlign = System.Drawing.ContentAlignment.MiddleCenter;
77 | //
78 | // timer1
79 | //
80 | this.timer1.Interval = 30;
81 | this.timer1.Tick += new System.EventHandler(this.timer1_Tick);
82 | //
83 | // linkLabel1
84 | //
85 | this.linkLabel1.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Right)));
86 | this.linkLabel1.AutoSize = true;
87 | this.linkLabel1.LinkColor = System.Drawing.Color.Navy;
88 | this.linkLabel1.Location = new System.Drawing.Point(422, 4);
89 | this.linkLabel1.Name = "linkLabel1";
90 | this.linkLabel1.Size = new System.Drawing.Size(32, 13);
91 | this.linkLabel1.TabIndex = 4;
92 | this.linkLabel1.TabStop = true;
93 | this.linkLabel1.Text = "Abort";
94 | this.linkLabel1.Visible = false;
95 | this.linkLabel1.LinkClicked += new System.Windows.Forms.LinkLabelLinkClickedEventHandler(this.linkLabel1_LinkClicked);
96 | //
97 | // Connecting
98 | //
99 | this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F);
100 | this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
101 | this.BackColor = System.Drawing.SystemColors.InactiveCaption;
102 | this.ClientSize = new System.Drawing.Size(458, 141);
103 | this.Controls.Add(this.linkLabel1);
104 | this.Controls.Add(this.ConnectionLabel);
105 | this.Controls.Add(this.label2);
106 | this.Controls.Add(this.progressBar1);
107 | this.Controls.Add(this.TitleLabel);
108 | this.FormBorderStyle = System.Windows.Forms.FormBorderStyle.None;
109 | this.Icon = ((System.Drawing.Icon)(resources.GetObject("$this.Icon")));
110 | this.Name = "Connecting";
111 | this.Opacity = 0.9D;
112 | this.ShowIcon = false;
113 | this.StartPosition = System.Windows.Forms.FormStartPosition.CenterParent;
114 | this.Text = "Request";
115 | this.TopMost = true;
116 | this.Load += new System.EventHandler(this.Connecting_Load);
117 | this.ResumeLayout(false);
118 | this.PerformLayout();
119 |
120 | }
121 |
122 | #endregion
123 |
124 | private System.Windows.Forms.Label TitleLabel;
125 | private System.Windows.Forms.ProgressBar progressBar1;
126 | private System.Windows.Forms.Label label2;
127 | private System.Windows.Forms.Label ConnectionLabel;
128 | private System.Windows.Forms.Timer timer1;
129 | private System.Windows.Forms.LinkLabel linkLabel1;
130 | }
131 | }
--------------------------------------------------------------------------------
/src/Connecting.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.ComponentModel;
4 | using System.Data;
5 | using System.Drawing;
6 | using System.Linq;
7 | using System.Text;
8 | using System.Threading.Tasks;
9 | using System.Windows.Forms;
10 |
11 | namespace esp_tools_gui
12 | {
13 | public partial class Connecting : Form
14 | {
15 | private static bool Stop = false;
16 | public Connecting(string tool, string text)
17 | {
18 | InitializeComponent();
19 |
20 | Opacity = 0.0;
21 | TitleLabel.Text = tool;
22 | ConnectionLabel.Text = text;
23 | progressBar1.Value = 0;
24 | timer1.Enabled = true;
25 | Stop = false;
26 | }
27 |
28 | private void timer1_Tick(object sender, EventArgs e)
29 | {
30 | if (Opacity < 1.0) Opacity += 0.05;
31 | if (progressBar1.Value < progressBar1.Maximum) progressBar1.Value++;
32 | else if (linkLabel1.Visible == false) linkLabel1.Visible = true;
33 | if (Stop)
34 | {
35 | timer1.Enabled = false;
36 | this.Close();
37 | }
38 | }
39 |
40 | public static void Terminate()
41 | {
42 | Stop = true;
43 | }
44 |
45 | private void Connecting_Load(object sender, EventArgs e)
46 | {
47 | Top -= 200;
48 | }
49 |
50 | private void linkLabel1_LinkClicked(object sender, LinkLabelLinkClickedEventArgs e)
51 | {
52 | Stop = true;
53 | }
54 | }
55 | }
56 |
--------------------------------------------------------------------------------
/src/ESP32.ico:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Adrianotiger/ESPToolsGUI/68f96feab419b5950a8643faa6f8b4c7992c05be/src/ESP32.ico
--------------------------------------------------------------------------------
/src/MainPage.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.ComponentModel;
4 | using System.Data;
5 | using System.Diagnostics;
6 | using System.Drawing;
7 | using System.IO;
8 | using System.IO.Ports;
9 | using System.Linq;
10 | using System.Management;
11 | using System.Reflection;
12 | using System.Text;
13 | using System.Text.RegularExpressions;
14 | using System.Threading.Tasks;
15 | using System.Windows.Forms;
16 |
17 | namespace esp_tools_gui
18 | {
19 | public partial class MainPage : Form
20 | {
21 | private static StringBuilder outStr;
22 | private ToolEfuse efuse;
23 | private ToolTool tool;
24 | private ToolSecure secure;
25 | private ToolPartition partition;
26 | private ToolPart partition2;
27 | private bool HasError = false;
28 | private bool isScrolling = false;
29 |
30 | private delegate void SafeCallDelegate(object sender, CustomEventArgs a);
31 |
32 | public MainPage()
33 | {
34 | InitializeComponent();
35 |
36 | outStr = new StringBuilder();
37 | richTextBox1.Text = "";
38 |
39 | efuse = new ToolEfuse();
40 | tool = new ToolTool();
41 | secure = new ToolSecure();
42 | partition = new ToolPartition();
43 | partition2 = new ToolPart();
44 |
45 | efuse.ConsoleEvent += HandleCustomEvent;
46 | tool.ConsoleEvent += HandleCustomEvent;
47 | secure.ConsoleEvent += HandleCustomEvent;
48 | partition.ConsoleEvent += HandleCustomEvent;
49 | partition2.ConsoleEvent += HandleCustomEvent;
50 |
51 | richTextBoxFlashHex.MouseWheel += RichTextBox_MouseWheel;
52 | richTextBoxFlashLine.MouseWheel += RichTextBox_MouseWheel;
53 | richTextBoxFlashData.MouseWheel += RichTextBox_MouseWheel;
54 |
55 | ExpertComboboxTool.SelectedIndex = 0;
56 | }
57 |
58 | protected override void OnLoad(EventArgs e)
59 | {
60 | base.OnLoad(e);
61 | this.Text += " - (v." + Application.ProductVersion + ")";
62 | }
63 |
64 | private void MainPage_Load(object sender, EventArgs e)
65 | {
66 | using (var searcher = new ManagementObjectSearcher("SELECT * FROM WIN32_SerialPort"))
67 | {
68 | string[] portnames = SerialPort.GetPortNames();
69 | var ports2 = searcher.Get().Cast().ToList();
70 | var tList = (from n in portnames
71 | join p in ports2 on n equals p["DeviceID"].ToString() into joinedList
72 | from sub in joinedList.DefaultIfEmpty()
73 | select new ComPort{ PortId=n, Info=sub==null?"":sub["Caption"].ToString() }).ToList();
74 |
75 | tList.ForEach((t)=> { comboBox1.Items.Add(t); });
76 | }
77 | comboBox1.SelectedIndex = 0;
78 | if(comboBox1.Items.Count > 0) Tool._com = ((ComPort)comboBox1.Items[0]).PortId;
79 | foreach (ComPort i in comboBox1.Items)
80 | {
81 | if(Properties.Settings.Default.comport == i.ToString())
82 | {
83 | comboBox1.SelectedItem = i;
84 | Tool._com = i.PortId;
85 | break;
86 | }
87 | }
88 | comboBox2.Text = Properties.Settings.Default.combaud;
89 |
90 | Tool._baud = Properties.Settings.Default.combaud;
91 |
92 | Application.DoEvents();
93 |
94 | comboBox1.TextChanged += (s, ev) =>
95 | {
96 | Tool._com = ((s as ComboBox).SelectedItem as ComPort).PortId;
97 | Properties.Settings.Default.comport = (s as ComboBox).Text;
98 | Properties.Settings.Default.Save();
99 | };
100 | comboBox2.TextChanged += (s, ev) =>
101 | {
102 | Tool._baud = Properties.Settings.Default.combaud;
103 | Properties.Settings.Default.combaud = (s as ComboBox).Text;
104 | Properties.Settings.Default.Save();
105 | };
106 | }
107 |
108 | public class ComPort
109 | {
110 | public string PortId { get; set; }
111 | public string Info { get; set; }
112 | public override string ToString()
113 | {
114 | if (Info.Length > 1)
115 | {
116 | return PortId + " - " + Info;
117 | }
118 | else
119 | {
120 | return PortId;
121 | }
122 | }
123 | }
124 |
125 | private void button1_Click(object sender, EventArgs e)
126 | {
127 | HasError = false;
128 | splitContainer3.Panel2Collapsed = false;
129 | progressBar1.Value = 20;
130 | progressBar1.Visible = true;
131 | FillInfoTab();
132 | if (HasError)
133 | {
134 | return;
135 | }
136 | tabControl1.SelectedIndex = 0;
137 | progressBar1.Value = 50;
138 | Application.DoEvents();
139 | FillPartitionTab();
140 | if (HasError)
141 | {
142 | return;
143 | }
144 | progressBar1.Value = 80;
145 | tabControl1.SelectedIndex++;
146 | Application.DoEvents();
147 | FillEFuseTab();
148 | if (HasError)
149 | {
150 | return;
151 | }
152 | progressBar1.Value = 100;
153 | tabControl1.SelectedIndex++;
154 | Application.DoEvents();
155 | // todo: read something...
156 | progressBar1.Value = 100;
157 | Application.DoEvents();
158 | progressBar1.Visible = false;
159 | tabControl1.Enabled = true;
160 | }
161 |
162 | private void FillInfoTab()
163 | {
164 | tool.Parse("--after no_reset flash_id");
165 | infoTextboxChipType.Text = tool.ChipType;
166 | infoTextboxChip.Text = tool.Chip;
167 | infoTextboxFeature.Text = tool.Features;
168 | infoTextboxCrystal.Text = tool.Crystal;
169 | infoTextboxMac.Text = tool.MAC;
170 | infoTextboxFlash.Text = tool.Flash;
171 | }
172 |
173 | private void FillPartitionTab()
174 | {
175 | tool.ReadPartitionTable();
176 | partitionChart.Series[0].Points.Clear();
177 | partitionListview.Items.Clear();
178 | foreach (var p in tool.Partitions)
179 | {
180 | var lv = partitionListview.Items.Add(p.Name);
181 | lv.SubItems.Add(p.GetTypeName());
182 | lv.SubItems.Add(p.GetSubTypeName());
183 | lv.SubItems.Add("0x" + p.Offset.ToString("X"));
184 | lv.SubItems.Add(p.GetSize());
185 | lv.SubItems.Add("0x" + p.Flags.ToString("X"));
186 |
187 | var point = new System.Windows.Forms.DataVisualization.Charting.DataPoint(0.0, p.Size);
188 | point.AxisLabel = p.Name;
189 | partitionChart.Series[0].Points.Add(point);
190 | }
191 | }
192 |
193 | private void FillEFuseTab()
194 | {
195 | efuse.Parse("summary");
196 | tableLayoutPanel1.RowCount = 11;
197 | tableLayoutPanel1.Controls.Clear();
198 | int row = 0;
199 | foreach (var f in efuse.Fuses)
200 | {
201 | if (row > 10) tableLayoutPanel1.RowCount++;
202 | var l = new Label { Text = f.Key + ":", Parent = tableLayoutPanel1, Dock = DockStyle.Fill, BackColor = Color.AliceBlue };
203 | tableLayoutPanel1.SetRow(l, row);
204 | tableLayoutPanel1.SetColumn(l, 0);
205 | tableLayoutPanel1.SetColumnSpan(l, 4);
206 | row++;
207 | foreach (var v in efuse.Fuses[f.Key])
208 | {
209 | if (row > 10) tableLayoutPanel1.RowCount++;
210 | var l2 = new Label { Text = v.Title, Parent = tableLayoutPanel1, Dock = DockStyle.Fill };
211 | tableLayoutPanel1.SetRow(l2, row);
212 | tableLayoutPanel1.SetColumn(l2, 0);
213 | l2 = new Label { Text = v.Description, Parent = tableLayoutPanel1, Dock = DockStyle.Fill };
214 | tableLayoutPanel1.SetRow(l2, row);
215 | tableLayoutPanel1.SetColumn(l2, 1);
216 | var t2 = new TextBox { Text = v.Value, Parent = tableLayoutPanel1, Dock = DockStyle.Fill, ReadOnly = true };
217 | tableLayoutPanel1.SetRow(t2, row);
218 | tableLayoutPanel1.SetColumn(t2, 2);
219 | l2 = new Label { Text = v.ReadWrite, Parent = tableLayoutPanel1, Dock = DockStyle.Fill };
220 | tableLayoutPanel1.SetRow(l2, row);
221 | tableLayoutPanel1.SetColumn(l2, 3);
222 | row++;
223 | }
224 | }
225 | tableLayoutPanel1.RowStyles.Clear();
226 | }
227 |
228 |
229 | private async void comboBox3_KeyPress(object sender, KeyPressEventArgs e)
230 | {
231 | if (e.KeyChar == '\r')
232 | {
233 | var text = (sender as ComboBox).Text;
234 | switch (ExpertComboboxTool.Text)
235 | {
236 | case "esptool": await tool.Execute(text); break;
237 | case "espefuse": await efuse.Execute(text); break;
238 | case "espsecure": await secure.Execute(text); break;
239 | case "gen_esp32part": await partition.Execute(text); break;
240 | case "parttool": await partition2.Execute(text); break;
241 | }
242 |
243 | for(var k=0;k 1) comboBox3.Items.Insert(0, text);
253 | }
254 | }
255 |
256 | void HandleCustomEvent(object sender, CustomEventArgs a)
257 | {
258 | if (richTextBox1.InvokeRequired)
259 | {
260 | this.BeginInvoke(new SafeCallDelegate(HandleCustomEvent), new object[] { sender, a });
261 | return;
262 | }
263 | if (a.input.Length > 0)
264 | {
265 | string txt;
266 | txt = "\r\n > " + a.input + "\r\n";
267 | richTextBox1.SelectionColor = Color.White;
268 | richTextBox1.AppendText(txt);
269 | richTextBox1.SelectionColor = richTextBox1.ForeColor;
270 | richTextBox1.ScrollToCaret();
271 | }
272 | if(a.error.Length > 0)
273 | {
274 | string txt;
275 | txt = "\r\n [E] " + a.error + "\r\n";
276 | richTextBox1.SelectionColor = Color.LightCoral;
277 | richTextBox1.AppendText(txt);
278 | richTextBox1.SelectionColor = richTextBox1.ForeColor;
279 | richTextBox1.ScrollToCaret();
280 | HasError = true;
281 | }
282 | if(a.output.Length > 0)
283 | {
284 | string txt;
285 | txt = a.output;
286 | if (txt.Contains("fatal error")) HasError = true;
287 | //else txt = a.output + "\r\n";
288 | richTextBox1.AppendText(txt);
289 | if(txt.Contains("\r\n")) richTextBox1.ScrollToCaret();
290 | }
291 | }
292 |
293 | private void LinkLabel_LinkClicked(object sender, LinkLabelLinkClickedEventArgs e)
294 | {
295 | Process.Start((sender as LinkLabel).Text);
296 | }
297 |
298 | private void groupBox1_Enter(object sender, EventArgs e)
299 | {
300 |
301 | }
302 |
303 | private void button3_Click(object sender, EventArgs e)
304 | {
305 |
306 | }
307 |
308 | private void readFlashToolStripMenuItem_Click(object sender, EventArgs e)
309 | {
310 | if(partitionListview.SelectedIndices.Count == 1)
311 | {
312 | int index = partitionListview.SelectedIndices[0];
313 | Regex re = new Regex(@"(\d+)(\.\d+)?\s*");
314 | var m = re.Matches(partitionListview.Items[index].SubItems[4].Text);
315 | if (m.Count >= 1)
316 | {
317 | int address = Convert.ToInt32(partitionListview.Items[index].SubItems[3].Text, 16);
318 | int size = (int)(double.Parse(m[0].Value) * 1024);
319 |
320 | numericUpDownFlashAddr.Value = address;
321 | numericUpDownFlashCount.Value = size;
322 |
323 | tabControl1.SelectedIndex = 3;
324 | buttonReadFlash_Click(sender, e);
325 | }
326 | }
327 | }
328 |
329 | private void RichTextBox_MouseWheel(object sender, MouseEventArgs e)
330 | {
331 | if (e.Delta < 0)
332 | {
333 | if (vScrollBar1.Value < vScrollBar1.Maximum) vScrollBar1.Value++;
334 | }
335 | else if (e.Delta > 0)
336 | {
337 | if (vScrollBar1.Value > 0) vScrollBar1.Value--;
338 | }
339 | }
340 |
341 | private void vScrollBar1_Scroll(object sender, ScrollEventArgs e)
342 | {
343 |
344 | }
345 |
346 | private void vScrollBar1_ValueChanged(object sender, EventArgs e)
347 | {
348 | if (isScrolling) return;
349 | int line = richTextBoxFlashLine.GetFirstCharIndexFromLine(vScrollBar1.Value);
350 | if (line < 0) return;
351 | richTextBoxFlashLine.Select(line, 8);
352 | }
353 |
354 | private void richTextBoxFlashData_SelectionChanged(object sender, EventArgs e)
355 | {
356 | if (isScrolling) return;
357 | isScrolling = true;
358 | int line = richTextBoxFlashData.GetLineFromCharIndex(richTextBoxFlashData.SelectionStart);
359 | int charX0 = richTextBoxFlashData.GetFirstCharIndexFromLine(line);
360 | //if (richTextBoxFlashHex.SelectionStart > 2) charX0 += 1;
361 | int charSelection = (richTextBoxFlashData.SelectionStart - charX0);
362 | richTextBoxFlashLine.Select(richTextBoxFlashLine.GetFirstCharIndexFromLine(line), 8);
363 | richTextBoxFlashHex.Select(richTextBoxFlashHex.GetFirstCharIndexFromLine(line) + charSelection * 3 + 1, 2);
364 | vScrollBar1.Value = line;
365 | Application.DoEvents();
366 | isScrolling = false;
367 | }
368 |
369 | private void richTextBoxFlashLine_SelectionChanged(object sender, EventArgs e)
370 | {
371 | if (isScrolling) return;
372 | isScrolling = true;
373 | int line = richTextBoxFlashLine.GetLineFromCharIndex(richTextBoxFlashLine.SelectionStart);
374 | int charX0 = richTextBoxFlashLine.GetFirstCharIndexFromLine(line);
375 | richTextBoxFlashData.SelectionStart = richTextBoxFlashData.GetFirstCharIndexFromLine(line);
376 | richTextBoxFlashHex.SelectionStart = richTextBoxFlashHex.GetFirstCharIndexFromLine(line);
377 | vScrollBar1.Value = line;
378 | Application.DoEvents();
379 | isScrolling = false;
380 | }
381 |
382 | private void richTextBoxFlashHex_SelectionChanged(object sender, EventArgs e)
383 | {
384 | if (isScrolling) return;
385 | isScrolling = true;
386 | int line = richTextBoxFlashHex.GetLineFromCharIndex(richTextBoxFlashHex.SelectionStart);
387 | int charX0 = richTextBoxFlashHex.GetFirstCharIndexFromLine(line);
388 | if (richTextBoxFlashHex.SelectionStart > 2) charX0 += 1;
389 | int charSelection = (richTextBoxFlashHex.SelectionStart - charX0) / 3;
390 | richTextBoxFlashLine.Select(richTextBoxFlashLine.GetFirstCharIndexFromLine(line), 8);
391 | richTextBoxFlashData.Select(richTextBoxFlashData.GetFirstCharIndexFromLine(line) + charSelection, 1);
392 | vScrollBar1.Value = line;
393 | Application.DoEvents();
394 | isScrolling = false;
395 | }
396 |
397 | private async void editPartitionTableToolStripMenuItem_Click(object sender, EventArgs e)
398 | {
399 | Regex re = new Regex(@"(\d+)(\.\d+)?\s*");
400 | var m = re.Matches(tool.Flash);
401 |
402 | if (m.Count > 0)
403 | {
404 | PartTool pt = new PartTool(int.Parse(m[0].Value), partition);
405 | foreach (ListViewItem lv in partitionListview.Items)
406 | {
407 | m = re.Matches(lv.SubItems[4].Text);
408 | double size = double.Parse(m[0].Value);
409 | if (m.Count > 1) double.Parse(m[0].Value + "." + m[1].Value);
410 | if (lv.SubItems[4].Text.IndexOf("k") > 0) size *= 1024;
411 | if (lv.SubItems[4].Text.IndexOf("M") > 0) size *= 1024 * 1024;
412 | size = Convert.ToInt32(size);
413 | switch (lv.Text.Replace("\0", "").Trim())
414 | {
415 | case "nvs":
416 | pt.SetNvs(int.Parse(size.ToString()));
417 | break;
418 | case "eeprom":
419 | pt.SetEeprom(int.Parse(size.ToString()));
420 | break;
421 | case "app0":
422 | pt.SetOta0(int.Parse(size.ToString()), null);
423 | break;
424 | case "app1":
425 | pt.SetOta1(int.Parse(size.ToString()));
426 | break;
427 | case "otadata":
428 | pt.SetOtaD(int.Parse(size.ToString()));
429 | break;
430 | case "ffat":
431 | pt.SetFfat(int.Parse(size.ToString()));
432 | break;
433 | case "spiffs":
434 | pt.SetSpiffs(int.Parse(size.ToString()));
435 | break;
436 | }
437 | }
438 | if (pt.ShowDialog() == DialogResult.Yes)
439 | {
440 | var res = partition.CreatePartition(PartTool.Nvs, PartTool.Ota0, PartTool.Ota1, PartTool.Eeprom, PartTool.Spiffs, PartTool.Ffat);
441 | await tool.Execute("--before default_reset --after hard_reset write_flash 0x8000 part.bin");
442 | FillPartitionTab();
443 | }
444 | }
445 | else
446 | {
447 | MessageBox.Show("Unable to get flash size. Connect device before execute this function.", "Error");
448 | }
449 | }
450 |
451 | private void buttonReadFlash_Click(object sender, EventArgs e)
452 | {
453 | isScrolling = true;
454 | var startAddr = (int)numericUpDownFlashAddr.Value;
455 | var TotalRead = (int)numericUpDownFlashCount.Value;
456 | int ToRead = TotalRead;
457 | richTextBoxFlashHex.Clear();
458 | richTextBoxFlashLine.Clear();
459 | richTextBoxFlashData.Clear();
460 |
461 | vScrollBar1.Value = 1;
462 | vScrollBar1.Maximum = TotalRead / 16;
463 |
464 | int voids = -(startAddr % 16);
465 | int lineNumber = startAddr + voids;
466 | char t;
467 |
468 | //do
469 | {
470 | String s1 = "", s2 = "", s3 = "";
471 | if (ToRead > 0x10000) ToRead = 0x8000;
472 | var bytes = ReadFlashPart(startAddr, ToRead);
473 | TotalRead -= ToRead;
474 | if (voids > 0) voids = 0;
475 | int lines = ToRead / 16;
476 |
477 | for (var j = 0; j < lines; j++)
478 | {
479 | s1 += "0x" + lineNumber.ToString("X6") + "\n";
480 |
481 | for (var k = 0; k < 16; k++)
482 | {
483 | s2 += " ";
484 | if (voids < 0)
485 | {
486 | s2 += " ";
487 | }
488 | else if (voids > bytes.Length)
489 | {
490 | s2 += " ";
491 | }
492 | else
493 | {
494 | s2 += bytes[voids].ToString("X2");
495 | }
496 | voids++;
497 | }
498 | s2 += "\n";
499 |
500 | voids -= 16;
501 | for (var k = 0; k < 16; k++)
502 | {
503 | if (voids < 0)
504 | {
505 | s3 += " ";
506 | }
507 | else if (voids > bytes.Length)
508 | {
509 | s3 += " ";
510 | }
511 | else
512 | {
513 | t = ((char)bytes[voids]);
514 | if (t >= 0x20)
515 | s3 += ((char)bytes[voids]).ToString();
516 | else
517 | s3 += ".";
518 | }
519 | voids++;
520 | }
521 | s3 += "\n";
522 | lineNumber += 16;
523 | }
524 |
525 | richTextBoxFlashLine.AppendText(s1);
526 | richTextBoxFlashHex.AppendText(s2);
527 | richTextBoxFlashData.AppendText(s3);
528 |
529 | startAddr += ToRead;
530 | ToRead = TotalRead;
531 | }// while (ToRead > 0);
532 |
533 | int totalLines = richTextBoxFlashData.Lines.Length;
534 | double lineHeight = richTextBoxFlashData.PreferredSize.Height * 1.0 / totalLines;
535 | int visibleLines = (int)(richTextBoxFlashData.Height / lineHeight);
536 | vScrollBar1.Maximum = Math.Max(1, totalLines);
537 | isScrolling = false;
538 | vScrollBar1.Value = 0;
539 | }
540 |
541 | private Byte[] ReadFlashPart(int startAddr, int bytes)
542 | {
543 | return tool.ReadMemory(startAddr, bytes);
544 | }
545 |
546 | private async void ereasePartitionToolStripMenuItem_Click(object sender, EventArgs e)
547 | {
548 | if (partitionListview.SelectedIndices.Count == 1)
549 | {
550 | if(MessageBox.Show("Do you really want erease this partition? All data will be ereased.", "Clear partition", MessageBoxButtons.YesNoCancel, MessageBoxIcon.Question) == DialogResult.Yes)
551 | {
552 | int index = partitionListview.SelectedIndices[0];
553 | Regex re = new Regex(@"(\d+)(\.\d+)?\s*");
554 | var m = re.Matches(partitionListview.Items[index].SubItems[4].Text);
555 | if (m.Count >= 1)
556 | {
557 | int address = Convert.ToInt32(partitionListview.Items[index].SubItems[3].Text, 16);
558 | int size = (int)(double.Parse(m[0].Value) * 1024);
559 |
560 | await tool.Execute("erase_region 0x" + address.ToString("X") + " 0x" + size.ToString("X"));
561 | }
562 | }
563 | }
564 | }
565 |
566 | private void contextMenuStripPartition_Opening(object sender, CancelEventArgs e)
567 | {
568 |
569 | }
570 |
571 | private void button2_Click(object sender, EventArgs e)
572 | {
573 | editPartitionTableToolStripMenuItem_Click(sender, e);
574 | }
575 | }
576 |
577 | public class CustomEventArgs
578 | {
579 | public string input { get; set; } = "";
580 | public string output { get; set; } = "";
581 | public string error { get; set; } = "";
582 | }
583 | }
584 |
--------------------------------------------------------------------------------
/src/Tool.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.Diagnostics;
4 | using System.IO;
5 | using System.IO.Compression;
6 | using System.Linq;
7 | using System.Reflection;
8 | using System.Text;
9 | using System.Text.RegularExpressions;
10 | using System.Threading;
11 | using System.Threading.Tasks;
12 | using System.Windows.Forms.DataVisualization.Charting;
13 |
14 | namespace esp_tools_gui
15 | {
16 | public class Tool
17 | {
18 | private string _exe;
19 |
20 | public static string _com = "";
21 | public static string _baud = "";
22 |
23 | private StringBuilder _outStr = new StringBuilder();
24 | protected readonly static string ExePath = Path.Combine(Directory.GetCurrentDirectory(), "exes");
25 | protected readonly static string PythonDll = "python310.dll";
26 | private bool _useComArgs = true;
27 |
28 | public event EventHandler ConsoleEvent;
29 |
30 | public Tool(string executable, bool AddComArgs)
31 | {
32 | _exe = executable;
33 | _useComArgs = AddComArgs;
34 | }
35 | private String GetComParam()
36 | {
37 | if (_useComArgs)
38 | return "--port " + _com + " --baud " + _baud + " ";
39 | else
40 | return "";
41 | }
42 |
43 | public async Task Execute(string args)
44 | {
45 | Connecting conn = new Connecting(_exe, GetComParam() + args);
46 | CancellationTokenSource cts = new CancellationTokenSource();
47 |
48 | var t = Task.Run(() =>
49 | {
50 | string tempExeName = Path.Combine(ExePath, _exe);
51 |
52 | if (!File.Exists(Path.Combine(ExePath, PythonDll)) || !Directory.Exists(Path.Combine(ExePath, "lib")))
53 | {
54 | if (File.Exists(Path.Combine(ExePath, PythonDll)))
55 | File.Delete(Path.Combine(ExePath, PythonDll));
56 | if (Directory.Exists(Path.Combine(ExePath, "lib")))
57 | Directory.Delete(Path.Combine(ExePath, "lib"), true);
58 | ZipFile.ExtractToDirectory(Path.Combine(ExePath, "cxfreeze.zip"), ExePath);
59 | }
60 |
61 | if (!File.Exists(Path.Combine(ExePath, PythonDll)))
62 | {
63 | ConsoleEvent.Invoke(this, new CustomEventArgs { error = "Python DLL is not loaded." });
64 | }
65 | else if (!File.Exists(tempExeName))
66 | {
67 | var errMsg = "[" + _exe + "] File '" + _exe + "' not found in directory " + ExePath + "! Unable to start request.";
68 | ConsoleEvent.Invoke(this, new CustomEventArgs { error = errMsg });
69 | }
70 | else if (_com.Length < 3)
71 | {
72 | var errMsg = "[" + _exe + "] COM port is invalid (" + _com + ") - please select the right port and try again.";
73 | ConsoleEvent.Invoke(this, new CustomEventArgs { error = errMsg });
74 | }
75 | else
76 | {
77 | int procId = 0;
78 | var stopwatch = new Stopwatch();
79 | stopwatch.Start();
80 | using (var p = new Process())
81 | {
82 | try
83 | {
84 | using (cts.Token.Register(()=> { p.Kill(); p.WaitForExit(500); p.Close(); p.Dispose(); }))
85 | {
86 | _outStr.Clear();
87 | _outStr.Append(" >>> " + _exe + " " + GetComParam() + args + "\r\n");
88 | ConsoleEvent.Invoke(this, new CustomEventArgs { input = _exe + " " + GetComParam() + args });
89 | p.StartInfo = new ProcessStartInfo
90 | {
91 | FileName = tempExeName,
92 | UseShellExecute = false,
93 | WorkingDirectory = ExePath,
94 | WindowStyle = ProcessWindowStyle.Hidden,
95 | CreateNoWindow = true,
96 | Arguments = GetComParam() + args,
97 | RedirectStandardOutput = true,
98 | RedirectStandardError = true
99 | };
100 |
101 | //p.StartInfo.RedirectStandardError = true;
102 | //p.OutputDataReceived += new DataReceivedEventHandler(OutputHandler);
103 | p.ErrorDataReceived += new DataReceivedEventHandler(ErrorHandler);
104 | p.Start();
105 | //p.BeginOutputReadLine();
106 | p.BeginErrorReadLine();
107 | procId = p.Id;
108 |
109 | int dataReceived = 0;
110 | var sTemp = "";
111 | var outputReadTask = Task.Run(() =>
112 | {
113 | int iCh = 0;
114 | var s2 = "";
115 | var s3 = "";
116 | try
117 | {
118 | do
119 | {
120 | iCh = p.StandardOutput.Read();
121 | if (iCh >= 0)
122 | {
123 | if (iCh == 8)
124 | {
125 | s3 = "\r\n";
126 | s2 = " ";
127 | }
128 | else
129 | {
130 | s2 = s3 + char.ConvertFromUtf32(iCh);
131 | if (s3.Length > 0) s3 = "";
132 | }
133 | sTemp += s2;
134 | }
135 | } while (iCh >= 0);
136 | }
137 | catch (Exception e)
138 | {
139 | var errMsg = "[" + _exe + "] Exception: " + e.Message;
140 | ConsoleEvent.Invoke(this, new CustomEventArgs { error = errMsg });
141 | }
142 | });
143 |
144 | do
145 | {
146 | try
147 | {
148 | if (sTemp.Length > 0)
149 | {
150 | dataReceived++;
151 | var s = sTemp;
152 | sTemp = "";
153 | _outStr.Append(s);
154 | ConsoleEvent.Invoke(this, new CustomEventArgs { output = s });
155 | }
156 | else
157 | {
158 | p.WaitForExit(200);
159 | }
160 | }
161 | catch (Exception) { }
162 |
163 | if (dataReceived == 0 && stopwatch.ElapsedMilliseconds > 3000)
164 | {
165 | ConsoleEvent.Invoke(this, new CustomEventArgs { error = "Request timeout." });
166 | break;
167 | }
168 | } while (!p.HasExited);
169 | if (sTemp.Length > 0)
170 | {
171 | _outStr.Append(sTemp);
172 | ConsoleEvent.Invoke(this, new CustomEventArgs { output = sTemp });
173 | }
174 | }
175 | }
176 | catch(Exception ex)
177 | {
178 | ConsoleEvent.Invoke(this, new CustomEventArgs { error = ex.Message });
179 | }
180 | try
181 | {
182 | p.Close();
183 | }
184 | catch (Exception) { }
185 | }
186 |
187 | stopwatch.Stop();
188 | long elapsed_time = stopwatch.ElapsedMilliseconds;
189 | ConsoleEvent.Invoke(this, new CustomEventArgs { input = " [ execution time ] " + (elapsed_time / 1000.0) + " s" });
190 |
191 | try
192 | {
193 | if (Process.GetProcessesByName(_exe.Replace(".exe", "")).Length > 0)
194 | {
195 | Process.GetProcessesByName(_exe.Replace(".exe", ""))[0].Kill();
196 | }
197 | }
198 | catch (Exception) { }
199 | }
200 |
201 | Connecting.Terminate();
202 | }, cts.Token);
203 |
204 | conn.ShowDialog();
205 | if(!t.IsCompleted) // was aborted
206 | {
207 | ConsoleEvent.Invoke(this, new CustomEventArgs { error = "Request aborted." });
208 | cts.Cancel();
209 | t.Wait(500);
210 | }
211 |
212 | return await Task.FromResult(_outStr.ToString());
213 | }
214 |
215 | public string GetExePath()
216 | {
217 | return ExePath;
218 | }
219 |
220 | public string RegexSimple(string beginsWith, string txt)
221 | {
222 | var found = Regex.Match(txt, "(" + beginsWith + " )(.*]?)");
223 | if (found.Groups.Count == 3)
224 | {
225 | return found.Groups[2].ToString().Trim();
226 | }
227 | else return "";
228 | }
229 |
230 | public List RegexFuse(string line)
231 | {
232 | List values = new List();
233 | var found = Regex.Match(line, @"([a-zA-Z0-9_]*)[ ]*(.*)[\=](.*) ([R|W|\/]*) (.*)");
234 | if(found.Groups.Count > 4)
235 | {
236 | values.Add(found.Groups[1].Value.Trim());
237 | values.Add(found.Groups[2].Value.Trim());
238 | values.Add(found.Groups[3].Value.Trim());
239 | values.Add(found.Groups[4].Value.Trim());
240 | }
241 | return values;
242 | //XPD_SDIO_FORCE Ignore MTDI pin (GPIO12) for VDD_SDIO on reset = 0 R/W (0x0)
243 | }
244 |
245 | private void OutputHandler(object sender, DataReceivedEventArgs e)
246 | {
247 | // Prepend line numbers to each line of the output.
248 | if (e.Data != null)
249 | {
250 | ConsoleEvent.Invoke(this, new CustomEventArgs { output = e.Data });
251 | _outStr.Append("\r\n" + e.Data);
252 | }
253 | }
254 |
255 | private void ErrorHandler(object sender, DataReceivedEventArgs e)
256 | {
257 | // Prepend line numbers to each line of the output.
258 | if (e.Data != null)
259 | {
260 | ConsoleEvent.Invoke(this, new CustomEventArgs { error = e.Data });
261 | _outStr.Append("\r\n" + e.Data);
262 | }
263 | }
264 | }
265 | }
266 |
--------------------------------------------------------------------------------
/src/ToolEfuse.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.Linq;
4 | using System.Text;
5 | using System.Threading.Tasks;
6 |
7 | namespace esp_tools_gui
8 | {
9 | class ToolEfuse : Tool
10 | {
11 | public Dictionary> Fuses = new Dictionary>();
12 |
13 | public ToolEfuse() : base("espefuse.exe", true)
14 | {
15 |
16 | }
17 |
18 | public async void Parse(string args)
19 | {
20 | var str = await Execute(args);
21 | if(args.Contains("summary"))
22 | {
23 | //ChipType = RegexSimple("Detecting chip type...", str);
24 | var substr = str.Split(new string[] { ":\r" }, StringSplitOptions.RemoveEmptyEntries);
25 | var first = true;
26 | List eFuseList;
27 | Fuses.Clear();
28 | var nextTitle = "";
29 | foreach(var block in substr)
30 | {
31 | var lines = block.Split(new string[] { "\n" }, StringSplitOptions.RemoveEmptyEntries);
32 | if(first)
33 | {
34 | nextTitle = lines[lines.Length - 1];
35 | first = false;
36 | }
37 | else
38 | {
39 | eFuseList = new List();
40 | Fuses.Add(nextTitle, eFuseList);
41 | nextTitle = lines.Last();
42 | var memLine = "";
43 | foreach (var line in lines)
44 | {
45 | var values = RegexFuse(memLine + line);
46 | if(values.Count >= 3)
47 | {
48 | eFuseList.Add(new EFuse { Title = values[0], Description = values[1], Value = values[2], ReadWrite = values[3] });
49 | memLine = "";
50 | }
51 | else
52 | {
53 | memLine = line.Trim();
54 | }
55 | }
56 | }
57 | }
58 | }
59 | }
60 | }
61 |
62 | class EFuse
63 | {
64 | public string Title { get; set; } = "";
65 | public string Description { get; set; } = "";
66 | public string Value { get; set; } = "";
67 | public string ReadWrite { get; set; } = "";
68 | }
69 | }
70 |
--------------------------------------------------------------------------------
/src/ToolPart.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.Linq;
4 | using System.Text;
5 | using System.Threading.Tasks;
6 |
7 | namespace esp_tools_gui
8 | {
9 | class ToolPart : Tool
10 | {
11 | public ToolPart() : base("parttool.exe", true)
12 | {
13 |
14 | }
15 | }
16 | }
17 |
--------------------------------------------------------------------------------
/src/ToolPartition.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.IO;
4 | using System.Linq;
5 | using System.Text;
6 | using System.Threading.Tasks;
7 |
8 | namespace esp_tools_gui
9 | {
10 | public class ToolPartition : Tool
11 | {
12 | public ToolPartition() : base("gen_esp32part.exe", false)
13 | {
14 |
15 | }
16 |
17 | public async Task CreatePartition(int nvs, int ota0, int ota1, int eeprom, int spiffs, int ffat)
18 | {
19 | int addr = 0x9000;
20 | String text = "# Name, Type, SubType, Offset, Size, Flags\n";
21 | if(nvs > 0)
22 | {
23 | text += "nvs, data, nvs, 0x" + addr.ToString("x") + ", 0x" + nvs.ToString("x") + ",\n";
24 | addr += nvs;
25 | }
26 | text += "otadata, data, ota, 0x" + addr.ToString("x") + ", 0x" + (PartTool.Otad).ToString("x") + ",\n";
27 | addr += PartTool.Otad;
28 | text += "app0, app, ota_0, 0x" + addr.ToString("x") + ", 0x" + ota0.ToString("x") + ",\n";
29 | addr += ota0;
30 | if (ota1 > 0)
31 | {
32 | text += "app1, app, ota_1, 0x" + addr.ToString("x") + ", 0x" + ota1.ToString("x") + ",\n";
33 | addr += ota1;
34 | }
35 | if (eeprom > 0)
36 | {
37 | text += "eeprom, data, 0x99, 0x" + addr.ToString("x") + ", 0x" + eeprom.ToString("x") + ",\n";
38 | addr += eeprom;
39 | }
40 | if (spiffs > 0)
41 | {
42 | text += "spiffs, data, spiffs, 0x" + addr.ToString("x") + ", 0x" + spiffs.ToString("x") + ",\n";
43 | addr += spiffs;
44 | }
45 | if (ffat > 0)
46 | {
47 | text += "ffat, data, fat, 0x" + addr.ToString("x") + ", 0x" + ffat.ToString("x") + ",\n";
48 | addr += ffat;
49 | }
50 |
51 | String csvFile = GetPartitionPath(false);
52 | String binFile = GetPartitionPath(true);
53 |
54 | if (File.Exists(csvFile)) File.Delete(csvFile);
55 | if (File.Exists(binFile)) File.Delete(binFile);
56 | File.WriteAllText(csvFile, text);
57 |
58 | return await Execute("part.csv part.bin");
59 |
60 | /*
61 | nvs, data, nvs, 0x9000, 0x5000,
62 | otadata, data, ota, 0xe000, 0x2000,
63 | app0, app, ota_0, 0x10000, 0x140000,
64 | app1, app, ota_1, 0x150000,0x140000,
65 | spiffs, data, spiffs, 0x290000,0x170000,
66 | */
67 | }
68 |
69 | public string GetPartitionPath(bool bin)
70 | {
71 | if(bin)
72 | {
73 | return ExePath + "\\part.bin";
74 | }
75 | else
76 | {
77 | return ExePath + "\\part.csv";
78 | }
79 | }
80 |
81 | public async Task ImportTable(string filename)
82 | {
83 | String csvFile = GetPartitionPath(false);
84 | String binFile = GetPartitionPath(true);
85 |
86 | if (File.Exists(csvFile)) File.Delete(csvFile);
87 | if (File.Exists(binFile)) File.Delete(binFile);
88 |
89 | if(filename.EndsWith(".bin"))
90 | {
91 | File.Copy(filename, binFile);
92 | await Execute("part.bin part.csv");
93 | }
94 | else if(filename.EndsWith(".csv"))
95 | {
96 | File.Copy(filename, csvFile);
97 | await Execute("part.csv part.bin");
98 | }
99 | else
100 | {
101 | return false;
102 | }
103 | return true;
104 | }
105 | }
106 | }
107 |
--------------------------------------------------------------------------------
/src/ToolSecure.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.Linq;
4 | using System.Text;
5 | using System.Threading.Tasks;
6 |
7 | namespace esp_tools_gui
8 | {
9 | class ToolSecure : Tool
10 | {
11 | public ToolSecure() : base("espsecure.exe", true)
12 | {
13 |
14 | }
15 | }
16 | }
17 |
--------------------------------------------------------------------------------
/src/ToolTool.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.IO;
4 | using System.Linq;
5 | using System.Text;
6 | using System.Threading.Tasks;
7 |
8 | namespace esp_tools_gui
9 | {
10 | class ToolTool : Tool
11 | {
12 | public String ChipType { get; set; } = "";
13 | public String Chip { get; set; } = "";
14 | public String Features { get; set; } = "";
15 | public String Crystal { get; set; } = "";
16 | public String MAC { get; set; } = "";
17 | public String Flash { get; set; } = "";
18 |
19 | public List Partitions { get; set; } = new List();
20 |
21 | public ToolTool() : base("esptool.exe", true)
22 | {
23 |
24 | }
25 |
26 | public async void Parse(string args)
27 | {
28 | var str = await Execute(args);
29 | if (args.Contains("chip_id"))
30 | {
31 | ChipType = RegexSimple("Detecting chip type...", str);
32 | Chip = RegexSimple("Chip is", str);
33 | Features = RegexSimple("Features:", str);
34 | Crystal = RegexSimple("Crystal is", str);
35 | MAC = RegexSimple("MAC:", str);
36 | }
37 |
38 | if (args.Contains("flash_id"))
39 | {
40 | ChipType = RegexSimple("Detecting chip type...", str);
41 | Chip = RegexSimple("Chip is", str);
42 | Features = RegexSimple("Features:", str);
43 | Crystal = RegexSimple("Crystal is", str);
44 | MAC = RegexSimple("MAC:", str);
45 | Flash = RegexSimple("Detected flash size:", str);
46 | }
47 | }
48 |
49 | public Byte[] ReadMemory(int startAddress, int size)
50 | {
51 | String start = startAddress.ToString("x");
52 | String total = size.ToString("x");
53 | Parse("read_flash 0x" + start + " 0x" + total + " temp.bin");
54 |
55 | if(startAddress == 0x8000 && size == 0x400) // read partition info
56 | {
57 | try
58 | {
59 | string binFile = Path.Combine(ExePath, "temp.bin");
60 | using (FileStream fs2 = new FileStream(binFile, FileMode.Open))
61 | {
62 | using (BinaryReader r = new BinaryReader(fs2))
63 | {
64 | Int16 startPart;
65 | Partitions.Clear();
66 |
67 | do
68 | {
69 | var p = new Partition();
70 |
71 | startPart = r.ReadByte();
72 | if (startPart != 0xaa) break;
73 | p.Flags = r.ReadByte();
74 | p.Type = r.ReadByte();
75 | p.Subtype = r.ReadByte();
76 | p.Offset = r.ReadUInt32();
77 | p.Size = r.ReadUInt32();
78 | p.Name = Encoding.UTF8.GetString(r.ReadBytes(20), 0, 20);
79 | Partitions.Add(p);
80 | } while (startPart == 0xaa);
81 | }
82 | }
83 | }
84 | catch (Exception)
85 | {
86 | // todo: failed to open image... command was not successfully
87 | }
88 | }
89 |
90 | return File.ReadAllBytes(ExePath + "\\temp.bin");
91 | }
92 |
93 | public void ReadPartitionTable()
94 | {
95 | ReadMemory(0x8000, 0x400);
96 | }
97 | }
98 |
99 |
100 | class Partition
101 | {
102 | public int Type { get; set; }
103 | public int Subtype { get; set; }
104 | public uint Offset { get; set; }
105 | public uint Size {get; set;}
106 | public int Flags { get; set; }
107 | public string Name { get; set; }
108 |
109 | public string GetTypeName()
110 | {
111 | if (Type == 0) return "APP";
112 | else if (Type == 1) return "DATA";
113 | else return "CUSTOM " + Type;
114 | }
115 |
116 | public string GetSubTypeName()
117 | {
118 | if (Type == 0)
119 | {
120 | if (Subtype == 0) return "FACTORY";
121 | else if(Subtype < 0x20) return "OTA_" + (Subtype - 0x10).ToString("X");
122 | else if (Subtype == 0x20) return "OTA_TEST";
123 | else return "OTA_? " + Subtype.ToString("X");
124 | }
125 | else if (Type == 1)
126 | {
127 | switch(Subtype)
128 | {
129 | case 0: return "OTA";
130 | case 1: return "PHY";
131 | case 2: return "NVS";
132 | case 4: return "NVS_KEYS";
133 | default: return "UNKNOWN " + Subtype.ToString("X");
134 | }
135 | }
136 | else return Type.ToString();
137 | }
138 |
139 | public string GetSize()
140 | {
141 | double size = Size;
142 | if (size < 1000) return size.ToString("0") + " bytes";
143 | size = size / 1024;
144 | /*if (size < 1000)*/ return size.ToString("0.000") + " kb";
145 | //size = size / 1024;
146 | //return size.ToString("0.000") + " Mb";
147 | }
148 | }
149 | }
150 |
--------------------------------------------------------------------------------