esp32tool 1.0.0 → 1.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +25 -15
- package/css/dark.css +11 -0
- package/css/style.css +199 -0
- package/dist/esp_loader.js +6 -0
- package/dist/index.d.ts +2 -1
- package/dist/index.js +1 -1
- package/dist/partition.d.ts +8 -0
- package/dist/partition.js +32 -0
- package/dist/wasm/filesystems.d.ts +42 -6
- package/dist/wasm/filesystems.js +427 -34
- package/dist/web/esp32-CijhsJH1.js +1 -0
- package/dist/web/esp32c2-C17SM4gO.js +1 -0
- package/dist/web/esp32c3-DxRGijbg.js +1 -0
- package/dist/web/esp32c5-3mDOIGa4.js +1 -0
- package/dist/web/esp32c6-h6U0SQTm.js +1 -0
- package/dist/web/esp32c61-BKtexhPZ.js +1 -0
- package/dist/web/esp32h2-RtuWSEmP.js +1 -0
- package/dist/web/esp32p4-5nkIjxqJ.js +1 -0
- package/dist/web/esp32p4r3-CpHBYEwI.js +1 -0
- package/dist/web/esp32s2-IiDBtXxo.js +1 -0
- package/dist/web/esp32s3-6yv5yxum.js +1 -0
- package/dist/web/esp8266-CUwxJpGa.js +1 -0
- package/dist/web/index.js +1 -7265
- package/index.html +32 -0
- package/js/modules/esp32-CijhsJH1.js +1 -0
- package/js/modules/esp32c2-C17SM4gO.js +1 -0
- package/js/modules/esp32c3-DxRGijbg.js +1 -0
- package/js/modules/esp32c5-3mDOIGa4.js +1 -0
- package/js/modules/esp32c6-h6U0SQTm.js +1 -0
- package/js/modules/esp32c61-BKtexhPZ.js +1 -0
- package/js/modules/esp32h2-RtuWSEmP.js +1 -0
- package/js/modules/esp32p4-5nkIjxqJ.js +1 -0
- package/js/modules/esp32p4r3-CpHBYEwI.js +1 -0
- package/js/modules/esp32s2-IiDBtXxo.js +1 -0
- package/js/modules/esp32s3-6yv5yxum.js +1 -0
- package/js/modules/esp8266-CUwxJpGa.js +1 -0
- package/js/modules/esptool.js +1 -7265
- package/js/script.js +635 -140
- package/package.json +1 -1
- package/src/esp_loader.ts +8 -0
- package/src/index.ts +8 -0
- package/src/partition.ts +38 -0
- package/src/wasm/filesystems.ts +513 -54
- package/dist/web/esp32-D955RjN9.js +0 -16
- package/dist/web/esp32c2-CJkxHDQi.js +0 -16
- package/dist/web/esp32c3-BhUHzH0o.js +0 -16
- package/dist/web/esp32c5-Chs0HtmA.js +0 -16
- package/dist/web/esp32c6-D6mPN6ut.js +0 -16
- package/dist/web/esp32c61-CQiYCWAs.js +0 -16
- package/dist/web/esp32h2-LsKJE9AS.js +0 -16
- package/dist/web/esp32p4-7nWC-HiD.js +0 -16
- package/dist/web/esp32p4r3-CwiPecZW.js +0 -16
- package/dist/web/esp32s2-CtqVheSJ.js +0 -16
- package/dist/web/esp32s3-CRbtB0QR.js +0 -16
- package/dist/web/esp8266-nEkNAo8K.js +0 -16
- package/js/modules/esp32-D955RjN9.js +0 -16
- package/js/modules/esp32c2-CJkxHDQi.js +0 -16
- package/js/modules/esp32c3-BhUHzH0o.js +0 -16
- package/js/modules/esp32c5-Chs0HtmA.js +0 -16
- package/js/modules/esp32c6-D6mPN6ut.js +0 -16
- package/js/modules/esp32c61-CQiYCWAs.js +0 -16
- package/js/modules/esp32h2-LsKJE9AS.js +0 -16
- package/js/modules/esp32p4-7nWC-HiD.js +0 -16
- package/js/modules/esp32p4r3-CwiPecZW.js +0 -16
- package/js/modules/esp32s2-CtqVheSJ.js +0 -16
- package/js/modules/esp32s3-CRbtB0QR.js +0 -16
- package/js/modules/esp8266-nEkNAo8K.js +0 -16
package/README.md
CHANGED
|
@@ -1,31 +1,41 @@
|
|
|
1
1
|
|
|
2
|
-
# ESP32Tool
|
|
3
2
|
|
|
4
|
-
|
|
3
|
+
# 🚀 ESP32Tool – The Ultimate ESP Filesystem Powerhouse
|
|
5
4
|
|
|
6
|
-
**
|
|
7
|
-
- Supports all common filesystems
|
|
8
|
-
- Upload and download files easily – no complicated steps
|
|
9
|
-
- Custom, high-performance flash access (up to 10x faster than esptool.py)
|
|
10
|
-
- Automatic resume on read errors – no more broken flash operations
|
|
5
|
+
**Flash. Manage. Dominate. All in your browser.**
|
|
11
6
|
|
|
12
|
-
|
|
7
|
+
Meet **ESP32Tool** – your all-in-one, next-gen solution for ESP device management. Experience seamless firmware flashing, backup, and now, full filesystem control with just a few clicks. No drivers, no command line, no limits!
|
|
13
8
|
|
|
14
|
-
|
|
9
|
+
---
|
|
10
|
+
|
|
11
|
+
✨ **What makes ESP32Tool shine?**
|
|
12
|
+
|
|
13
|
+
- **Universal Filesystem Support:** Instantly detect, read, and write to LittleFS, SPIFFS, and FATFS – all major ESP filesystems, fully supported!
|
|
14
|
+
- **Total File Control:** Effortlessly add or delete individual files. Upload, download, organize – your ESP, your rules.
|
|
15
|
+
- **Lightning Fast:** Custom, high-performance flash access – up to 10x faster than esptool.py!
|
|
16
|
+
- **Rock-Solid Reliability:** Automatic resume on read errors. No more broken operations, ever.
|
|
17
|
+
- **Plug & Play:** Manage your ESP directly in the browser. No software installation needed.
|
|
18
|
+
- **Offline Ready:** Prefer desktop? Grab the Electron app from our [releases](https://github.com/Jason2866/esp32tool/releases).
|
|
19
|
+
|
|
20
|
+
> **Try it now:** [jason2866.github.io/esp32tool](https://jason2866.github.io/esp32tool)
|
|
15
21
|
|
|
16
22
|
---
|
|
17
23
|
|
|
18
|
-
##
|
|
24
|
+
## 🛠️ Developer Quickstart
|
|
19
25
|
|
|
20
26
|
1. Clone this repository
|
|
21
27
|
2. Install dependencies: `npm install`
|
|
22
|
-
3. Start the
|
|
23
|
-
4. Open
|
|
28
|
+
3. Start the dev environment: `script/develop`
|
|
29
|
+
4. Open [http://localhost:5004/](http://localhost:5004/) in your browser
|
|
24
30
|
|
|
25
31
|
---
|
|
26
32
|
|
|
27
|
-
##
|
|
33
|
+
## 🏆 Our Story
|
|
28
34
|
|
|
29
|
-
|
|
35
|
+
Born from the minds of [Melissa LeBlanc-Williams](https://github.com/makermelissa), [Nabu Casa](https://www.nabucasa.com), Adafruit, and now supercharged by Jason2866, ESP32Tool has evolved into the most advanced, browser-based ESP management suite. With every update, we push the boundaries of what’s possible for your ESP devices.
|
|
36
|
+
|
|
37
|
+
**Latest update:** December 2025 – Now with full LittleFS, SPIFFS, and FATFS support, plus file add/delete magic!
|
|
38
|
+
|
|
39
|
+
---
|
|
30
40
|
|
|
31
|
-
|
|
41
|
+
© Adafruit, Nabu Casa & Johann Obermeier
|
package/css/dark.css
CHANGED
|
@@ -154,3 +154,14 @@ input {
|
|
|
154
154
|
.littlefs-fs-button:hover {
|
|
155
155
|
background-color: #71ae1e;
|
|
156
156
|
}
|
|
157
|
+
|
|
158
|
+
/* ESP8266 Info Box - Dark Mode */
|
|
159
|
+
.esp8266-info .info-box {
|
|
160
|
+
background-color: #2a2a2a;
|
|
161
|
+
border-color: #00a7e9;
|
|
162
|
+
color: #e0e0e0;
|
|
163
|
+
}
|
|
164
|
+
|
|
165
|
+
.esp8266-info .info-box strong {
|
|
166
|
+
color: #00a7e9;
|
|
167
|
+
}
|
package/css/style.css
CHANGED
|
@@ -521,6 +521,17 @@ div.clear {
|
|
|
521
521
|
cursor: pointer;
|
|
522
522
|
}
|
|
523
523
|
|
|
524
|
+
#commands .partition-table #butOpenFSManager {
|
|
525
|
+
background-color: #8ec641;
|
|
526
|
+
color: white;
|
|
527
|
+
border-color: #8ec641;
|
|
528
|
+
}
|
|
529
|
+
|
|
530
|
+
#commands .partition-table #butOpenFSManager:hover {
|
|
531
|
+
background-color: #71ae1e;
|
|
532
|
+
border-color: #71ae1e;
|
|
533
|
+
}
|
|
534
|
+
|
|
524
535
|
#commands .partition-table .progress-bar {
|
|
525
536
|
width: 400px;
|
|
526
537
|
margin-bottom: 10px;
|
|
@@ -561,6 +572,50 @@ div.clear {
|
|
|
561
572
|
border-color: #00a7e9;
|
|
562
573
|
}
|
|
563
574
|
|
|
575
|
+
/* ESP8266 Filesystem Info Box */
|
|
576
|
+
.esp8266-info {
|
|
577
|
+
width: 100%;
|
|
578
|
+
margin-top: 15px;
|
|
579
|
+
}
|
|
580
|
+
|
|
581
|
+
.esp8266-info .info-box {
|
|
582
|
+
background-color: #f8f9fa;
|
|
583
|
+
border: 2px solid #00a7e9;
|
|
584
|
+
border-radius: 8px;
|
|
585
|
+
padding: 15px 20px;
|
|
586
|
+
text-align: left;
|
|
587
|
+
}
|
|
588
|
+
|
|
589
|
+
.esp8266-info .info-box strong {
|
|
590
|
+
display: block;
|
|
591
|
+
font-size: 16px;
|
|
592
|
+
margin-bottom: 10px;
|
|
593
|
+
color: #00a7e9;
|
|
594
|
+
}
|
|
595
|
+
|
|
596
|
+
.esp8266-info .info-box p {
|
|
597
|
+
margin: 8px 0;
|
|
598
|
+
line-height: 1.5;
|
|
599
|
+
}
|
|
600
|
+
|
|
601
|
+
.esp8266-info .info-box ul {
|
|
602
|
+
margin: 10px 0;
|
|
603
|
+
padding-left: 20px;
|
|
604
|
+
list-style-type: none;
|
|
605
|
+
}
|
|
606
|
+
|
|
607
|
+
.esp8266-info .info-box ul li {
|
|
608
|
+
margin: 5px 0;
|
|
609
|
+
padding-left: 0;
|
|
610
|
+
}
|
|
611
|
+
|
|
612
|
+
.esp8266-info .info-box ul li strong {
|
|
613
|
+
display: inline;
|
|
614
|
+
font-size: 14px;
|
|
615
|
+
color: inherit;
|
|
616
|
+
margin: 0;
|
|
617
|
+
}
|
|
618
|
+
|
|
564
619
|
.justify {
|
|
565
620
|
display: flex;
|
|
566
621
|
justify-content: space-between;
|
|
@@ -868,3 +923,147 @@ div.clear {
|
|
|
868
923
|
color: #fff;
|
|
869
924
|
border-color: #71ae1e;
|
|
870
925
|
}
|
|
926
|
+
|
|
927
|
+
/* File Viewer Modal Styles */
|
|
928
|
+
.file-viewer-content {
|
|
929
|
+
max-width: 900px;
|
|
930
|
+
width: 90vw;
|
|
931
|
+
max-height: 90vh;
|
|
932
|
+
display: flex;
|
|
933
|
+
flex-direction: column;
|
|
934
|
+
padding: 0;
|
|
935
|
+
overflow: hidden;
|
|
936
|
+
text-align: left;
|
|
937
|
+
}
|
|
938
|
+
|
|
939
|
+
.file-viewer-header {
|
|
940
|
+
display: flex;
|
|
941
|
+
justify-content: space-between;
|
|
942
|
+
align-items: center;
|
|
943
|
+
padding: 20px 30px;
|
|
944
|
+
border-bottom: 2px solid #e0e0e0;
|
|
945
|
+
}
|
|
946
|
+
|
|
947
|
+
.file-viewer-header h2 {
|
|
948
|
+
margin: 0;
|
|
949
|
+
font-size: 20px;
|
|
950
|
+
color: #333;
|
|
951
|
+
}
|
|
952
|
+
|
|
953
|
+
.close-button {
|
|
954
|
+
background: none;
|
|
955
|
+
border: none;
|
|
956
|
+
font-size: 28px;
|
|
957
|
+
color: #999;
|
|
958
|
+
cursor: pointer;
|
|
959
|
+
padding: 0;
|
|
960
|
+
width: 32px;
|
|
961
|
+
height: 32px;
|
|
962
|
+
display: flex;
|
|
963
|
+
align-items: center;
|
|
964
|
+
justify-content: center;
|
|
965
|
+
border-radius: 50%;
|
|
966
|
+
transition: all 0.2s;
|
|
967
|
+
}
|
|
968
|
+
|
|
969
|
+
.close-button:hover {
|
|
970
|
+
background-color: #f0f0f0;
|
|
971
|
+
color: #333;
|
|
972
|
+
}
|
|
973
|
+
|
|
974
|
+
.file-viewer-info {
|
|
975
|
+
display: flex;
|
|
976
|
+
justify-content: space-between;
|
|
977
|
+
padding: 12px 30px;
|
|
978
|
+
background-color: #f8f8f8;
|
|
979
|
+
font-size: 13px;
|
|
980
|
+
color: #666;
|
|
981
|
+
border-bottom: 1px solid #e0e0e0;
|
|
982
|
+
}
|
|
983
|
+
|
|
984
|
+
.file-viewer-tabs {
|
|
985
|
+
display: flex;
|
|
986
|
+
padding: 0 30px;
|
|
987
|
+
background-color: #f8f8f8;
|
|
988
|
+
border-bottom: 2px solid #e0e0e0;
|
|
989
|
+
}
|
|
990
|
+
|
|
991
|
+
.tab-button {
|
|
992
|
+
background: none;
|
|
993
|
+
border: none;
|
|
994
|
+
padding: 12px 24px;
|
|
995
|
+
font-size: 14px;
|
|
996
|
+
font-weight: 600;
|
|
997
|
+
color: #666;
|
|
998
|
+
cursor: pointer;
|
|
999
|
+
border-bottom: 3px solid transparent;
|
|
1000
|
+
transition: all 0.2s;
|
|
1001
|
+
margin-bottom: -2px;
|
|
1002
|
+
}
|
|
1003
|
+
|
|
1004
|
+
.tab-button:hover {
|
|
1005
|
+
color: #333;
|
|
1006
|
+
background-color: rgba(113, 174, 30, 0.1);
|
|
1007
|
+
}
|
|
1008
|
+
|
|
1009
|
+
.tab-button.active {
|
|
1010
|
+
color: #71ae1e;
|
|
1011
|
+
border-bottom-color: #71ae1e;
|
|
1012
|
+
}
|
|
1013
|
+
|
|
1014
|
+
.file-viewer-body {
|
|
1015
|
+
flex: 1;
|
|
1016
|
+
overflow: auto;
|
|
1017
|
+
padding: 20px 30px;
|
|
1018
|
+
background-color: #fff;
|
|
1019
|
+
min-height: 300px;
|
|
1020
|
+
max-height: calc(90vh - 250px);
|
|
1021
|
+
text-align: left;
|
|
1022
|
+
}
|
|
1023
|
+
|
|
1024
|
+
.file-viewer-body pre {
|
|
1025
|
+
margin: 0;
|
|
1026
|
+
font-family: "SF Mono", "Menlo", "Monaco", "Consolas", "Liberation Mono", "Courier New", monospace;
|
|
1027
|
+
font-size: 13px;
|
|
1028
|
+
line-height: 1.5;
|
|
1029
|
+
white-space: pre;
|
|
1030
|
+
overflow-x: auto;
|
|
1031
|
+
color: #333;
|
|
1032
|
+
tab-size: 4;
|
|
1033
|
+
text-align: left;
|
|
1034
|
+
}
|
|
1035
|
+
|
|
1036
|
+
.file-viewer-body .hex-view {
|
|
1037
|
+
font-family: "SF Mono", "Menlo", "Monaco", "Consolas", "Liberation Mono", "Courier New", monospace;
|
|
1038
|
+
font-size: 12px;
|
|
1039
|
+
line-height: 1.6;
|
|
1040
|
+
}
|
|
1041
|
+
|
|
1042
|
+
.hex-line {
|
|
1043
|
+
display: flex;
|
|
1044
|
+
margin-bottom: 2px;
|
|
1045
|
+
}
|
|
1046
|
+
|
|
1047
|
+
.hex-offset {
|
|
1048
|
+
color: #999;
|
|
1049
|
+
margin-right: 20px;
|
|
1050
|
+
min-width: 80px;
|
|
1051
|
+
}
|
|
1052
|
+
|
|
1053
|
+
.hex-bytes {
|
|
1054
|
+
color: #333;
|
|
1055
|
+
margin-right: 20px;
|
|
1056
|
+
min-width: 400px;
|
|
1057
|
+
}
|
|
1058
|
+
|
|
1059
|
+
.hex-ascii {
|
|
1060
|
+
color: #666;
|
|
1061
|
+
}
|
|
1062
|
+
|
|
1063
|
+
.file-viewer-footer {
|
|
1064
|
+
padding: 20px 30px;
|
|
1065
|
+
border-top: 2px solid #e0e0e0;
|
|
1066
|
+
display: flex;
|
|
1067
|
+
justify-content: flex-end;
|
|
1068
|
+
gap: 10px;
|
|
1069
|
+
}
|
package/dist/esp_loader.js
CHANGED
|
@@ -107,6 +107,9 @@ export class ESPLoader extends EventTarget {
|
|
|
107
107
|
// Don't await this promise so it doesn't block rest of method.
|
|
108
108
|
this.readLoop();
|
|
109
109
|
}
|
|
110
|
+
// Drain input buffer first for CP210x compatibility on Windows
|
|
111
|
+
// This helps clear any stale data before sync
|
|
112
|
+
await this.drainInputBuffer(200);
|
|
110
113
|
// Clear buffer again after starting read loop
|
|
111
114
|
await this.flushSerialBuffers();
|
|
112
115
|
await this.sync();
|
|
@@ -156,6 +159,9 @@ export class ESPLoader extends EventTarget {
|
|
|
156
159
|
catch (error) {
|
|
157
160
|
// GET_SECURITY_INFO not supported, fall back to magic value detection
|
|
158
161
|
this.logger.debug(`GET_SECURITY_INFO failed, using magic value detection: ${error}`);
|
|
162
|
+
// Drain input buffer for CP210x compatibility on Windows
|
|
163
|
+
// This ensures all error responses are cleared before continuing
|
|
164
|
+
await this.drainInputBuffer(200);
|
|
159
165
|
// Clear input buffer and re-sync to recover from failed command
|
|
160
166
|
this._inputBuffer.length = 0;
|
|
161
167
|
await sleep(SYNC_TIMEOUT);
|
package/dist/index.d.ts
CHANGED
|
@@ -6,5 +6,6 @@ export { CHIP_FAMILY_ESP32, CHIP_FAMILY_ESP32S2, CHIP_FAMILY_ESP32S3, CHIP_FAMIL
|
|
|
6
6
|
export declare const connect: (logger: Logger) => Promise<ESPLoader>;
|
|
7
7
|
export { parsePartitionTable, getPartitionTableOffset, formatSize, } from "./partition";
|
|
8
8
|
export type { Partition } from "./partition";
|
|
9
|
-
export { FilesystemType, detectFilesystemType, detectFilesystemFromImage, getDefaultBlockSize, getBlockSizeCandidates, LITTLEFS_DEFAULT_BLOCK_SIZE, LITTLEFS_BLOCK_SIZE_CANDIDATES, FATFS_DEFAULT_BLOCK_SIZE, FATFS_BLOCK_SIZE_CANDIDATES, } from "./wasm/filesystems";
|
|
9
|
+
export { FilesystemType, detectFilesystemType, detectFilesystemFromImage, getDefaultBlockSize, getBlockSizeCandidates, getESP8266FilesystemLayout, scanESP8266Filesystem, LITTLEFS_DEFAULT_BLOCK_SIZE, LITTLEFS_BLOCK_SIZE_CANDIDATES, FATFS_DEFAULT_BLOCK_SIZE, FATFS_BLOCK_SIZE_CANDIDATES, ESP8266_LITTLEFS_BLOCK_SIZE, ESP8266_LITTLEFS_BLOCK_SIZE_CANDIDATES, ESP8266_LITTLEFS_PAGE_SIZE, ESP8266_SPIFFS_PAGE_SIZE, ESP8266_SPIFFS_BLOCK_SIZE, } from "./wasm/filesystems";
|
|
10
|
+
export type { ESP8266FilesystemLayout } from "./wasm/filesystems";
|
|
10
11
|
export { SpiffsFS, SpiffsBuildConfig, SpiffsReader, DEFAULT_SPIFFS_CONFIG, type SpiffsFile, type SpiffsBuildConfigOptions, } from "./lib/spiffs/index";
|
package/dist/index.js
CHANGED
|
@@ -11,5 +11,5 @@ export const connect = async (logger) => {
|
|
|
11
11
|
return new ESPLoader(port, logger);
|
|
12
12
|
};
|
|
13
13
|
export { parsePartitionTable, getPartitionTableOffset, formatSize, } from "./partition";
|
|
14
|
-
export { FilesystemType, detectFilesystemType, detectFilesystemFromImage, getDefaultBlockSize, getBlockSizeCandidates, LITTLEFS_DEFAULT_BLOCK_SIZE, LITTLEFS_BLOCK_SIZE_CANDIDATES, FATFS_DEFAULT_BLOCK_SIZE, FATFS_BLOCK_SIZE_CANDIDATES, } from "./wasm/filesystems";
|
|
14
|
+
export { FilesystemType, detectFilesystemType, detectFilesystemFromImage, getDefaultBlockSize, getBlockSizeCandidates, getESP8266FilesystemLayout, scanESP8266Filesystem, LITTLEFS_DEFAULT_BLOCK_SIZE, LITTLEFS_BLOCK_SIZE_CANDIDATES, FATFS_DEFAULT_BLOCK_SIZE, FATFS_BLOCK_SIZE_CANDIDATES, ESP8266_LITTLEFS_BLOCK_SIZE, ESP8266_LITTLEFS_BLOCK_SIZE_CANDIDATES, ESP8266_LITTLEFS_PAGE_SIZE, ESP8266_SPIFFS_PAGE_SIZE, ESP8266_SPIFFS_BLOCK_SIZE, } from "./wasm/filesystems";
|
|
15
15
|
export { SpiffsFS, SpiffsBuildConfig, SpiffsReader, DEFAULT_SPIFFS_CONFIG, } from "./lib/spiffs/index";
|
package/dist/partition.d.ts
CHANGED
|
@@ -24,3 +24,11 @@ export declare function getPartitionTableOffset(): number;
|
|
|
24
24
|
* Format size in human-readable format
|
|
25
25
|
*/
|
|
26
26
|
export declare function formatSize(bytes: number): string;
|
|
27
|
+
/**
|
|
28
|
+
* Detect filesystem type from image data
|
|
29
|
+
* Returns the detected filesystem type: 'littlefs', 'fatfs', 'spiffs', or 'unknown'
|
|
30
|
+
*
|
|
31
|
+
* This is a wrapper around detectFilesystemFromImage from filesystems.ts
|
|
32
|
+
* with fallback to partition subtype if detection fails.
|
|
33
|
+
*/
|
|
34
|
+
export declare function detectFilesystemType(data: Uint8Array, partitionSubtype?: number): string;
|
package/dist/partition.js
CHANGED
|
@@ -2,6 +2,7 @@
|
|
|
2
2
|
* ESP32 Partition Table Parser
|
|
3
3
|
* Based on ESP-IDF partition table format
|
|
4
4
|
*/
|
|
5
|
+
import { detectFilesystemFromImage, FilesystemType } from "./wasm/filesystems";
|
|
5
6
|
// Partition types
|
|
6
7
|
const PARTITION_TYPES = {
|
|
7
8
|
0x00: "app",
|
|
@@ -39,6 +40,7 @@ const DATA_SUBTYPES = {
|
|
|
39
40
|
0x80: "esphttpd",
|
|
40
41
|
0x81: "fat",
|
|
41
42
|
0x82: "spiffs",
|
|
43
|
+
0x83: "littlefs",
|
|
42
44
|
};
|
|
43
45
|
const PARTITION_TABLE_OFFSET = 0x8000; // Default partition table offset
|
|
44
46
|
const PARTITION_ENTRY_SIZE = 32;
|
|
@@ -127,3 +129,33 @@ export function formatSize(bytes) {
|
|
|
127
129
|
return `${(bytes / (1024 * 1024)).toFixed(2)} MB`;
|
|
128
130
|
}
|
|
129
131
|
}
|
|
132
|
+
/**
|
|
133
|
+
* Detect filesystem type from image data
|
|
134
|
+
* Returns the detected filesystem type: 'littlefs', 'fatfs', 'spiffs', or 'unknown'
|
|
135
|
+
*
|
|
136
|
+
* This is a wrapper around detectFilesystemFromImage from filesystems.ts
|
|
137
|
+
* with fallback to partition subtype if detection fails.
|
|
138
|
+
*/
|
|
139
|
+
export function detectFilesystemType(data, partitionSubtype) {
|
|
140
|
+
// Use the centralized detection function from filesystems.ts
|
|
141
|
+
const fsType = detectFilesystemFromImage(data);
|
|
142
|
+
// If detection succeeded, return the result
|
|
143
|
+
if (fsType !== FilesystemType.UNKNOWN) {
|
|
144
|
+
return fsType.toLowerCase();
|
|
145
|
+
}
|
|
146
|
+
// Fall back to partition table subtype if no clear signature found
|
|
147
|
+
if (partitionSubtype !== undefined) {
|
|
148
|
+
if (partitionSubtype === 0x81) {
|
|
149
|
+
return "fatfs";
|
|
150
|
+
}
|
|
151
|
+
else if (partitionSubtype === 0x82) {
|
|
152
|
+
// Subtype 0x82 can be either SPIFFS or LittleFS, default to SPIFFS
|
|
153
|
+
return "spiffs";
|
|
154
|
+
}
|
|
155
|
+
else if (partitionSubtype === 0x83) {
|
|
156
|
+
return "littlefs";
|
|
157
|
+
}
|
|
158
|
+
}
|
|
159
|
+
// Default to unknown
|
|
160
|
+
return "unknown";
|
|
161
|
+
}
|
|
@@ -3,6 +3,39 @@ export declare const LITTLEFS_DEFAULT_BLOCK_SIZE = 4096;
|
|
|
3
3
|
export declare const LITTLEFS_BLOCK_SIZE_CANDIDATES: number[];
|
|
4
4
|
export declare const FATFS_DEFAULT_BLOCK_SIZE = 4096;
|
|
5
5
|
export declare const FATFS_BLOCK_SIZE_CANDIDATES: number[];
|
|
6
|
+
export declare const ESP8266_LITTLEFS_BLOCK_SIZE = 8192;
|
|
7
|
+
export declare const ESP8266_LITTLEFS_BLOCK_SIZE_CANDIDATES: number[];
|
|
8
|
+
export declare const ESP8266_LITTLEFS_PAGE_SIZE = 256;
|
|
9
|
+
export declare const ESP8266_SPIFFS_PAGE_SIZE = 256;
|
|
10
|
+
export declare const ESP8266_SPIFFS_BLOCK_SIZE = 8192;
|
|
11
|
+
/**
|
|
12
|
+
* ESP8266 filesystem layout information
|
|
13
|
+
*/
|
|
14
|
+
export interface ESP8266FilesystemLayout {
|
|
15
|
+
start: number;
|
|
16
|
+
end: number;
|
|
17
|
+
size: number;
|
|
18
|
+
page: number;
|
|
19
|
+
block: number;
|
|
20
|
+
}
|
|
21
|
+
/**
|
|
22
|
+
* Scan ESP8266 flash for filesystem by detecting filesystem signatures
|
|
23
|
+
* Reads actual block_count from LittleFS superblock for accurate size detection
|
|
24
|
+
*
|
|
25
|
+
* @param flashData - Flash data starting at scanOffset
|
|
26
|
+
* @param scanOffset - The offset in flash where this data starts
|
|
27
|
+
* @param flashSize - Total flash size in bytes
|
|
28
|
+
* @returns Detected filesystem layout or null
|
|
29
|
+
*/
|
|
30
|
+
export declare function scanESP8266Filesystem(flashData: Uint8Array, scanOffset: number, flashSize: number): ESP8266FilesystemLayout | null;
|
|
31
|
+
/**
|
|
32
|
+
* Get common ESP8266 filesystem layouts as fallback
|
|
33
|
+
* Used when we can't scan the actual flash
|
|
34
|
+
*
|
|
35
|
+
* @param flashSizeMB - Flash size in megabytes
|
|
36
|
+
* @returns Array of possible filesystem layouts (most common first)
|
|
37
|
+
*/
|
|
38
|
+
export declare function getESP8266FilesystemLayout(flashSizeMB: number): ESP8266FilesystemLayout[];
|
|
6
39
|
/**
|
|
7
40
|
* Filesystem types based on partition subtype
|
|
8
41
|
*/
|
|
@@ -20,14 +53,17 @@ export declare enum FilesystemType {
|
|
|
20
53
|
export declare function detectFilesystemType(partition: Partition): FilesystemType;
|
|
21
54
|
/**
|
|
22
55
|
* Detect filesystem type from image data
|
|
23
|
-
*
|
|
56
|
+
* Properly validates LittleFS superblock structure at correct offsets
|
|
57
|
+
*
|
|
58
|
+
* @param imageData - Binary filesystem image data
|
|
59
|
+
* @param chipName - Optional chip name for ESP8266-specific detection (e.g. "ESP8266")
|
|
24
60
|
*/
|
|
25
|
-
export declare function detectFilesystemFromImage(imageData: Uint8Array): FilesystemType;
|
|
61
|
+
export declare function detectFilesystemFromImage(imageData: Uint8Array, chipName?: string): FilesystemType;
|
|
26
62
|
/**
|
|
27
|
-
* Get appropriate block size for filesystem type
|
|
63
|
+
* Get appropriate block size for filesystem type and chip
|
|
28
64
|
*/
|
|
29
|
-
export declare function getDefaultBlockSize(fsType: FilesystemType): number;
|
|
65
|
+
export declare function getDefaultBlockSize(fsType: FilesystemType, chipName?: string): number;
|
|
30
66
|
/**
|
|
31
|
-
* Get block size candidates for filesystem type
|
|
67
|
+
* Get block size candidates for filesystem type and chip
|
|
32
68
|
*/
|
|
33
|
-
export declare function getBlockSizeCandidates(fsType: FilesystemType): number[];
|
|
69
|
+
export declare function getBlockSizeCandidates(fsType: FilesystemType, chipName?: string): number[];
|