From 6cd7b32beead35591ba9624a719b10659205b3e9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jakub=20Hlusi=C4=8Dka?= Date: Sat, 24 Jan 2026 00:42:16 +0100 Subject: [PATCH] Mount EKV on a separate partition --- firmware/Cargo.lock | 236 +++++++++++++++------------ firmware/acid-firmware/Cargo.toml | 35 +++- firmware/acid-firmware/src/main.rs | 53 ++++-- firmware/acid-firmware/src/ui/mod.rs | 153 +++++++++++++++-- firmware/acid-firmware/ui/main.slint | 1 + 5 files changed, 330 insertions(+), 148 deletions(-) diff --git a/firmware/Cargo.lock b/firmware/Cargo.lock index 6eda6ff..b821890 100644 --- a/firmware/Cargo.lock +++ b/firmware/Cargo.lock @@ -14,12 +14,14 @@ dependencies = [ "const-gen", "critical-section", "data-encoding-macro", + "ekv", "embassy-embedded-hal", "embassy-executor", "embassy-sync 0.7.2", "embassy-time", "embedded-cli", - "embedded-io 0.6.1", + "embedded-io 0.7.1", + "embedded-storage-async", "embuild", "enumset", "esp-alloc", @@ -30,6 +32,7 @@ dependencies = [ "esp-radio", "esp-rtos", "esp-storage", + "esp-sync", "gix", "hmac", "i-slint-common", @@ -41,9 +44,9 @@ dependencies = [ "mutually_exclusive_features", "panic-rtt-target", "password-hash 0.1.0", - "paste", + "pastey 0.2.1", "printf-compat", - "rand_core 0.6.4", + "rand_core 0.9.5", "rmk", "rtt-target", "sha2", @@ -407,7 +410,7 @@ dependencies = [ "log", "num-rational", "num-traits", - "pastey", + "pastey 0.1.1", "rayon", "thiserror 2.0.18", "v_frame", @@ -760,9 +763,9 @@ dependencies = [ [[package]] name = "cc" -version = "1.2.53" +version = "1.2.54" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "755d2fce177175ffca841e9a06afdb2c4ab0f593d53b4dee48147dfaade85932" +checksum = "6354c81bbfd62d9cfa9cb3c773c2b7b2a3a482d569de977fd0e961f6e7c00583" dependencies = [ "find-msvc-tools", "jobserver", @@ -1564,6 +1567,16 @@ version = "1.15.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "48c757948c5ede0e46177b7add2e67155f70e33c07fea8284df6576da70b3719" +[[package]] +name = "ekv" +version = "1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ab888debca410aa6f2726fb363926ca73539378c5e8880c8f08f35ae4b24d938" +dependencies = [ + "embassy-sync 0.6.2", + "heapless 0.8.0", +] + [[package]] name = "elliptic-curve" version = "0.13.8" @@ -2275,6 +2288,7 @@ dependencies = [ "embassy-sync 0.6.2", "embassy-sync 0.7.2", "esp-metadata-generated", + "log", "riscv", "xtensa-lx", ] @@ -2806,9 +2820,9 @@ dependencies = [ [[package]] name = "gix" -version = "0.76.0" +version = "0.78.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0da205378175c7e08c1d9357be8e6056c541d5907c29842d025b2a732ce06d52" +checksum = "3428a03ace494ae40308bd3df0b37e7eb7403e24389f27abdff30abf2b5adf17" dependencies = [ "gix-actor", "gix-attributes", @@ -2819,6 +2833,7 @@ dependencies = [ "gix-diff", "gix-dir", "gix-discover", + "gix-error", "gix-features", "gix-filter", "gix-fs", @@ -2855,9 +2870,9 @@ dependencies = [ [[package]] name = "gix-actor" -version = "0.36.1" +version = "0.38.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "636ca0d7bf8f7ad8ba84a5dda8312c8944b275be09d88b072e08f57d3e47c1e8" +checksum = "b50ce5433eaa46187349e59089eea71b0397caa71991b2fa3e124120426d7d15" dependencies = [ "bstr", "gix-date", @@ -2869,9 +2884,9 @@ dependencies = [ [[package]] name = "gix-attributes" -version = "0.29.0" +version = "0.30.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f47dabf8a50f1558c3a55d978440c7c4f22f87ac897bef03b4edbc96f6115966" +checksum = "f868f013fee0ebb5c85fae848c34a0b9ef7438acfbaec0c82a3cdbd5eac730a0" dependencies = [ "bstr", "gix-glob", @@ -2895,18 +2910,18 @@ dependencies = [ [[package]] name = "gix-chunk" -version = "0.4.12" +version = "0.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5c356b3825677cb6ff579551bb8311a81821e184453cbd105e2fc5311b288eeb" +checksum = "63e516efaac951ed21115b11d5514b120c26ccb493d0c0b9ea6cc10edf4fdf44" dependencies = [ - "thiserror 2.0.18", + "gix-error", ] [[package]] name = "gix-command" -version = "0.6.5" +version = "0.7.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "46f9c425730a654835351e6da8c3c69ba1804f8b8d4e96d027254151138d5c64" +checksum = "745bc165b7da500acc26d24888379ae0dfd1ecabe3a47420cdcb92feefb0561d" dependencies = [ "bstr", "gix-path", @@ -2917,22 +2932,22 @@ dependencies = [ [[package]] name = "gix-commitgraph" -version = "0.31.0" +version = "0.32.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "efdcba8048045baf15225daf949d597c3e6183d130245e22a7fbd27084abe63a" +checksum = "d0dda2e4d5a61d4a16a780f61f2b7e9406ad1f8da97c35c09ef501f3fdf74de0" dependencies = [ "bstr", "gix-chunk", + "gix-error", "gix-hash", "memmap2", - "thiserror 2.0.18", ] [[package]] name = "gix-config" -version = "0.49.0" +version = "0.51.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7f15f96a354d296b505575870c4ebe279552a67132b61223869181d11894859d" +checksum = "9a153dd4f5789fdf242e19e3f7105f2a114df198570225976fe4a108bac9dee4" dependencies = [ "bstr", "gix-config-value", @@ -2950,9 +2965,9 @@ dependencies = [ [[package]] name = "gix-config-value" -version = "0.16.0" +version = "0.17.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2409cffa4fe8b303847d5b6ba8df9da9ba65d302fc5ee474ea0cac5afde79840" +checksum = "563361198101cedc975fe5760c91ac2e4126eec22216e81b659b45289feaf1ea" dependencies = [ "bitflags 2.10.0", "bstr", @@ -2963,22 +2978,22 @@ dependencies = [ [[package]] name = "gix-date" -version = "0.11.1" +version = "0.13.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c0a1259955c76335c9d1a8c511811b10dbc800ffeeca3daea1e0aadd0c98f6b7" +checksum = "12553b32d1da25671f31c0b084bf1e5cb6d5ef529254d04ec33cdc890bd7f687" dependencies = [ "bstr", + "gix-error", "itoa", "jiff", "smallvec", - "thiserror 2.0.18", ] [[package]] name = "gix-diff" -version = "0.56.0" +version = "0.58.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3ebc8f56f3300d3c5f98d927b11762ef98e35ddbf9ebf3bdbdb53dbc6d9cbb7e" +checksum = "26bcd367b2c5dbf6bec9ce02ca59eab179fc82cf39f15ec83549ee25c255c99f" dependencies = [ "bstr", "gix-attributes", @@ -3000,9 +3015,9 @@ dependencies = [ [[package]] name = "gix-dir" -version = "0.18.0" +version = "0.20.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "40d285a847a95b3c76c0f7b17143bdc68c917d3f9f772bfd4c83fbadb7497067" +checksum = "004129e2c93798141d68ff08cb7f1b3d909c0212747fb8b05c8989635ba90a4e" dependencies = [ "bstr", "gix-discover", @@ -3020,14 +3035,13 @@ dependencies = [ [[package]] name = "gix-discover" -version = "0.44.0" +version = "0.46.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3f2fe2922c3358a93f5e5b62c1c6d856f59ed863f5fd2da1929f66567d3b0e12" +checksum = "950b027b861c6863ddf1b075672ec1ef2006b95c4d12284fc1ec4cdb1ab6639e" dependencies = [ "bstr", "dunce", "gix-fs", - "gix-hash", "gix-path", "gix-ref", "gix-sec", @@ -3035,10 +3049,19 @@ dependencies = [ ] [[package]] -name = "gix-features" -version = "0.45.2" +name = "gix-error" +version = "0.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d56aad357ae016449434705033df644ac6253dfcf1281aad3af3af9e907560d1" +checksum = "7dffc9ca4dfa4f519a3d2cf1c038919160544923577ac60f45bcb602a24d82c6" +dependencies = [ + "bstr", +] + +[[package]] +name = "gix-features" +version = "0.46.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6a407957e21dc5e6c87086e50e5114a2f9240f9cb11699588a6d900d53cb6c70" dependencies = [ "crc32fast", "crossbeam-channel", @@ -3056,9 +3079,9 @@ dependencies = [ [[package]] name = "gix-filter" -version = "0.23.0" +version = "0.25.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "22c005832d42de07bacdef53d3b87f6067e765b9753f85788655a1b4a20fc2b6" +checksum = "7240442915cdd74e1f889566695ce0d0c23c7185b13318a1232ce646af0d18ad" dependencies = [ "bstr", "encoding_rs", @@ -3077,9 +3100,9 @@ dependencies = [ [[package]] name = "gix-fs" -version = "0.18.2" +version = "0.19.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "785b9c499e46bc78d7b81c148c21b3fca18655379ee729a856ed19ce50d359ec" +checksum = "ba74fa163d3b2ba821d5cd207d55fe3daac3d1099613a8559c812d2b15b3c39a" dependencies = [ "bstr", "fastrand", @@ -3091,9 +3114,9 @@ dependencies = [ [[package]] name = "gix-glob" -version = "0.23.0" +version = "0.24.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e8546300aee4c65c5862c22a3e321124a69b654a61a8b60de546a9284812b7e2" +checksum = "b03e6cd88cc0dc1eafa1fddac0fb719e4e74b6ea58dd016e71125fde4a326bee" dependencies = [ "bitflags 2.10.0", "bstr", @@ -3103,9 +3126,9 @@ dependencies = [ [[package]] name = "gix-hash" -version = "0.21.2" +version = "0.22.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e153930f42ccdab8a3306b1027cd524879f6a8996cd0c474d18b0e56cae7714d" +checksum = "2b8e11ea6bbd0fd4ab4a1c66812dd3cc25921a41315b120f352997725a4c79d6" dependencies = [ "faster-hex", "gix-features", @@ -3115,9 +3138,9 @@ dependencies = [ [[package]] name = "gix-hashtable" -version = "0.11.0" +version = "0.12.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "222f7428636020bef272a87ed833ea48bf5fb3193f99852ae16fbb5a602bd2f0" +checksum = "52f1eecdd006390cbed81f105417dbf82a6fe40842022006550f2e32484101da" dependencies = [ "gix-hash", "hashbrown 0.16.1", @@ -3126,9 +3149,9 @@ dependencies = [ [[package]] name = "gix-ignore" -version = "0.18.0" +version = "0.19.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dfa727fdf54fd9fb53fa3fbb1a5c17172d3073e8e336bf155f3cac3e25b81b21" +checksum = "8953d87c13267e296d547f0fc7eaa8aa8fa5b2a9a34ab1cd5857f25240c7d299" dependencies = [ "bstr", "gix-glob", @@ -3139,9 +3162,9 @@ dependencies = [ [[package]] name = "gix-index" -version = "0.44.0" +version = "0.46.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "015374c00aff762bb21dafbb73a2267583392b320cb4aef156805838752a4152" +checksum = "e31c6b3664efe5916c539c50e610f9958f2993faf8e29fa5a40fb80b6ac8486a" dependencies = [ "bitflags 2.10.0", "bstr", @@ -3167,9 +3190,9 @@ dependencies = [ [[package]] name = "gix-lock" -version = "20.0.1" +version = "21.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "115268ae5e3b3b7bc7fc77260eecee05acca458e45318ca45d35467fa81a3ac5" +checksum = "e16d406220ef9df105645a9ddcaa42e8c882ba920344ace866d0403570aea599" dependencies = [ "gix-tempfile", "gix-utils", @@ -3178,9 +3201,9 @@ dependencies = [ [[package]] name = "gix-object" -version = "0.53.0" +version = "0.55.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7ec9557a30ab9abfec4d67975413e3099509ed5da599c901ea40f7da52755128" +checksum = "4d3f705c977d90ace597049252ae1d7fec907edc0fa7616cc91bf5508d0f4006" dependencies = [ "bstr", "gix-actor", @@ -3199,12 +3222,11 @@ dependencies = [ [[package]] name = "gix-odb" -version = "0.73.0" +version = "0.75.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6a7eb6f7017bf94ce8cf00da03a8a32d4199fcbee6940c5bba213ca98d01d78f" +checksum = "1d59882d2fdab5e609b0c452a6ef9a3bd12ef6b694be4f82ab8f126ad0969864" dependencies = [ "arc-swap", - "gix-date", "gix-features", "gix-fs", "gix-hash", @@ -3220,12 +3242,13 @@ dependencies = [ [[package]] name = "gix-pack" -version = "0.63.0" +version = "0.65.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bb0811847c93e98e1694ae0f519fb52af62da1cebeaf0a764840e392c6e41b38" +checksum = "8c44db57ebbbeaad9972c2a60662142660427a1f0a7529314d53fefb4fedad24" dependencies = [ "clru", "gix-chunk", + "gix-error", "gix-features", "gix-hash", "gix-hashtable", @@ -3239,9 +3262,9 @@ dependencies = [ [[package]] name = "gix-packetline" -version = "0.20.0" +version = "0.21.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fad0ffb982a289888087a165d3e849cbac724f2aa5431236b050dd2cb9c7de31" +checksum = "6c333badf342e9c2392800a96b9f2cf5bcb33906d2577d6ec923756ff4008a3f" dependencies = [ "bstr", "faster-hex", @@ -3251,9 +3274,9 @@ dependencies = [ [[package]] name = "gix-path" -version = "0.10.22" +version = "0.11.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7cb06c3e4f8eed6e24fd915fa93145e28a511f4ea0e768bae16673e05ed3f366" +checksum = "c7c3cd795cad18c7acbc6bafe34bfb34ac7273ee81133793f9d1516dd9faf922" dependencies = [ "bstr", "gix-trace", @@ -3263,9 +3286,9 @@ dependencies = [ [[package]] name = "gix-pathspec" -version = "0.14.0" +version = "0.15.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ed9e0c881933c37a7ef45288d6c5779c4a7b3ad240b4c37657e1d9829eb90085" +checksum = "3df6fd8e514d8b99ec5042ee17909a17750ccf54d0b8b30c850954209c800322" dependencies = [ "bitflags 2.10.0", "bstr", @@ -3278,9 +3301,9 @@ dependencies = [ [[package]] name = "gix-protocol" -version = "0.54.0" +version = "0.56.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "21348ce0b01fb5e3850e9014733d5ddf6bfeebb100967246572e6b02a29a4fef" +checksum = "54f20837b0c70b65f6ac77886be033de3b69d5879f99128b47c42665ab0a17c2" dependencies = [ "bstr", "gix-date", @@ -3308,9 +3331,9 @@ dependencies = [ [[package]] name = "gix-ref" -version = "0.56.0" +version = "0.58.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "16f21c66e188cb95207d30c9b2d21b0d234f570dbb97d8fd493081b6990dcb9d" +checksum = "5cf780dcd9ac99fd3fcfc8523479a0e2ffd55f5e0be63e5e3248fb7e46cff966" dependencies = [ "gix-actor", "gix-features", @@ -3329,11 +3352,12 @@ dependencies = [ [[package]] name = "gix-refspec" -version = "0.34.0" +version = "0.36.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "853157fd71394f7f382af2e28a7cd78c5c7bd28b7c5d7de7272e1ec97a869159" +checksum = "60ce400a770a7952e45267803192cc2d1fe0afa08e2c08dde32e04c7908c6e61" dependencies = [ "bstr", + "gix-error", "gix-glob", "gix-hash", "gix-revision", @@ -3344,27 +3368,28 @@ dependencies = [ [[package]] name = "gix-revision" -version = "0.38.0" +version = "0.40.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "63c1956637d13fe273178f425c04b0458ea678c150cb8ed325957a63cb1136f6" +checksum = "c719cf7d669439e1fca735bd1c4de54d43c5d30e8883fd6063c4924b213d70c9" dependencies = [ "bstr", "gix-commitgraph", "gix-date", + "gix-error", "gix-hash", "gix-object", "gix-revwalk", - "thiserror 2.0.18", ] [[package]] name = "gix-revwalk" -version = "0.24.0" +version = "0.26.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "276d6ce81e71c18e6c9c3de2c5015e85a7495d1bf33e0a7587e997b8bd040715" +checksum = "194a50b30aa0c6e6de43c723359c5809a96275a3aa92d323ef7f58b1cdd60f16" dependencies = [ "gix-commitgraph", "gix-date", + "gix-error", "gix-hash", "gix-hashtable", "gix-object", @@ -3374,9 +3399,9 @@ dependencies = [ [[package]] name = "gix-sec" -version = "0.12.2" +version = "0.13.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ea9962ed6d9114f7f100efe038752f41283c225bb507a2888903ac593dffa6be" +checksum = "beeb3bc63696cf7acb5747a361693ebdbcaf25b5d27d2308f38e9782983e7bce" dependencies = [ "bitflags 2.10.0", "gix-path", @@ -3386,9 +3411,9 @@ dependencies = [ [[package]] name = "gix-shallow" -version = "0.7.0" +version = "0.8.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9c1c467fb9f7ec1d33613c2ea5482de514bcb84b8222a793cdc4c71955832356" +checksum = "f4f4660fed3786d28e7e57d31b2de9ab3bf846068e187ccc52ee513de19a0073" dependencies = [ "bstr", "gix-hash", @@ -3398,9 +3423,9 @@ dependencies = [ [[package]] name = "gix-status" -version = "0.23.0" +version = "0.25.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1084eb17030ddbda1705c94ff6f79678dd7f15762deda74edf0f38e33711079c" +checksum = "b0c994dbca7f038cfcde6337673523bab6e6b4f544b5046f5120a02bdeafff33" dependencies = [ "bstr", "filetime", @@ -3421,9 +3446,9 @@ dependencies = [ [[package]] name = "gix-submodule" -version = "0.23.0" +version = "0.25.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fe0b0d02a3c5968a2d86de2a56ab28c3b50aa28d8324d49383b7bd71d26e6d84" +checksum = "db1840fe723c6264ee596e5a179e1b9a2df59351f09bae9cea570a472a790bc0" dependencies = [ "bstr", "gix-config", @@ -3436,9 +3461,9 @@ dependencies = [ [[package]] name = "gix-tempfile" -version = "20.0.1" +version = "21.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ad89218e74850f42d364ed3877c7291f0474c8533502df91bb877ecc5cb0dd40" +checksum = "d280bba7c547170e42d5228fc6e76c191fb5a7c88808ff61af06460404d1fd91" dependencies = [ "dashmap", "gix-fs", @@ -3455,9 +3480,9 @@ checksum = "6e42a4c2583357721ba2d887916e78df504980f22f1182df06997ce197b89504" [[package]] name = "gix-transport" -version = "0.51.0" +version = "0.53.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "03c5445af84383b949856a36accfde9f90bdfc10bb1f640f105917f9d5419509" +checksum = "de1064c7ffa5a915014a6a5b71fbc5299462ae655348bed23e083b4a735076c3" dependencies = [ "bstr", "gix-command", @@ -3471,9 +3496,9 @@ dependencies = [ [[package]] name = "gix-traverse" -version = "0.50.0" +version = "0.52.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c1f7582730a236aba16b4c9a5e9ac64bcbe7f155a38ae5938320de96760beb23" +checksum = "37f8b53b4c56b01c43a4491c4edfe2ce66c654eb86232205172ceb1650d21c55" dependencies = [ "bitflags 2.10.0", "gix-commitgraph", @@ -3488,12 +3513,11 @@ dependencies = [ [[package]] name = "gix-url" -version = "0.34.0" +version = "0.35.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cff1996dfb9430b3699d89224c674169c1ae355eacc52bf30a03c0b8bffe73d9" +checksum = "1ca2e50308a8373069e71970939f43ea4a1b5f422cf807d048ebcf07dcc02b2c" dependencies = [ "bstr", - "gix-features", "gix-path", "percent-encoding", "thiserror 2.0.18", @@ -3512,23 +3536,21 @@ dependencies = [ [[package]] name = "gix-validate" -version = "0.10.1" +version = "0.11.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5b1e63a5b516e970a594f870ed4571a8fdcb8a344e7bd407a20db8bd61dbfde4" +checksum = "0ec1eff98d91941f47766367cba1be746bab662bad761d9891ae6f7882f7840b" dependencies = [ "bstr", - "thiserror 2.0.18", ] [[package]] name = "gix-worktree" -version = "0.45.0" +version = "0.47.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e0ac49293df83b81da60ad8313f0376a5a7d6b11739ea7e97c0e1ba17b63d2a6" +checksum = "ef2ad658586ec0039b03e96c664f08b7cb7a2b7cca6947a9c856c9ed59b807b1" dependencies = [ "bstr", "gix-attributes", - "gix-features", "gix-fs", "gix-glob", "gix-hash", @@ -5421,6 +5443,12 @@ version = "0.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "35fb2e5f958ec131621fdd531e9fc186ed768cbe395337403ae56c17a74c68ec" +[[package]] +name = "pastey" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b867cad97c0791bbd3aaa6472142568c6c9e8f71937e98379f584cfb0cf35bec" + [[package]] name = "pathdiff" version = "0.2.3" @@ -5725,9 +5753,9 @@ dependencies = [ [[package]] name = "prodash" -version = "30.0.1" +version = "31.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5a6efc566849d3d9d737c5cb06cc50e48950ebe3d3f9d70631490fff3a07b139" +checksum = "962200e2d7d551451297d9fdce85138374019ada198e30ea9ede38034e27604c" dependencies = [ "parking_lot", ] @@ -5777,9 +5805,9 @@ checksum = "a993555f31e5a609f617c12db6250dedcac1b0a85076912c436e6fc9b2c8e6a3" [[package]] name = "quote" -version = "1.0.43" +version = "1.0.44" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dc74d9a594b72ae6656596548f56f667211f8a97b3d4c3d467150794690dc40a" +checksum = "21b2ebcf727b7760c461f091f9f0f539b77b8e87f2fd88131e7f1b433b3cece4" dependencies = [ "proc-macro2", ] diff --git a/firmware/acid-firmware/Cargo.toml b/firmware/acid-firmware/Cargo.toml index 4bb0bbc..2dc4fe9 100644 --- a/firmware/acid-firmware/Cargo.toml +++ b/firmware/acid-firmware/Cargo.toml @@ -30,6 +30,8 @@ limit-fps = [] develop = ["limit-fps", "alt-log"] develop-usb = ["limit-fps", "usb-log", "no-usb", "ble"] probe = ["limit-fps", "rtt-log", "no-usb", "ble"] +# Formats the EKV database on boot. +format-db = [] [dependencies] rmk = { version = "0.8.2", default-features = false, features = [ @@ -47,19 +49,20 @@ esp-backtrace = { version = "0.18", default-features = false, features = [ "println", ] } esp-hal = { version = "1.0", features = ["esp32s3", "unstable", "psram", "log-04"] } -esp-storage = { version = "0.8.0", features = ["esp32s3"] } -esp-alloc = { version = "0.9.0", features = ["nightly"] } -esp-println = { version = "0.16.0", features = ["esp32s3", "log-04"] } +esp-storage = { version = "0.8", features = ["esp32s3"] } +esp-alloc = { version = "0.9", features = ["nightly"] } +esp-println = { version = "0.16", features = ["esp32s3", "log-04"] } esp-radio = { version = "0.17", features = ["esp32s3", "unstable", "ble"], optional = true } esp-rtos = { version = "0.2", features = ["esp32s3", "esp-radio", "embassy"] } esp-bootloader-esp-idf = { version = "0.4", features = ["esp32s3", "log-04"] } -bt-hci = { version = "0.6", optional = true } -rand_core = { version = "0.6", default-features = false } +esp-sync = { version = "0.1.1", features = ["esp32s3", "log-04"] } +bt-hci = { version = "0.6", optional = true } # Must be updated with esp-radio and rmk +rand_core = { version = "0.9", default-features = false } static_cell = "2" lazy_static = { version = "1.5.0", features = ["spin_no_std"], default-features = false } log = "0.4.29" bitflags = "2.10.0" -paste = "1.0.15" +paste = { package = "pastey", version = "0.2.1" } itertools = { version = "0.14.0", default-features = false } bytemuck = "1.24.0" slint = { version = "1.14.1", default-features = false, features = ["compat-1-2", "libm", "log", "unsafe-single-threaded", "renderer-software"]} @@ -70,18 +73,32 @@ xkbcommon = { git = "https://github.com/Limeth/xkbcommon-rs", branch = "esp32s3" rtt-target = { version = "0.6.2", features = ["log"], optional = true } panic-rtt-target = { version = "0.2.0", optional = true } enumset = "1.1.10" -printf-compat = { version = "0.2.1", default-features = false } +printf-compat = { version = "0.2.1", default-features = false } # Kept older because of the outdated esp toolchain's VaList spectre-api-sys = { git = "https://github.com/Limeth/spectre-api-sys" } sha2 = { version = "0.10.9", default-features = false } password-hash = { path = "../password-hash", default-features = false } hmac = "0.12.1" data-encoding-macro = "0.1.19" +embedded-storage-async = "0.4.1" # Crates for serial UART CLI embedded-cli = { version = "0.2.1", default-features = false, features = ["help", "macros"] } -embedded-io = "0.6.1" +embedded-io = "0.7" mutually_exclusive_features = "0.1.0" +[dependencies.ekv] +version = "1.0.0" +features = [ + # TODO: "defmt", + "crc", + "max-page-count-2048", + "max-key-size-256", + "max-value-size-65536", + # These must adhere to `FlashStorage`'s parameters. + "align-4", + "page-size-4096", +] + [build-dependencies] xz2 = "0.1.7" json = "0.12" @@ -89,7 +106,7 @@ const-gen = "1.6" embuild = "0.33" cc = "1.2.9" slint-build = "1.14.1" -gix = { version = "0.76.0", default-features = false, features = ["max-performance", "status"] } +gix = { version = "0.78", default-features = false, features = ["max-performance", "status"] } indoc = "2.0.7" [[bin]] diff --git a/firmware/acid-firmware/src/main.rs b/firmware/acid-firmware/src/main.rs index cd84d45..f006656 100644 --- a/firmware/acid-firmware/src/main.rs +++ b/firmware/acid-firmware/src/main.rs @@ -22,10 +22,13 @@ use core::sync::atomic::{AtomicBool, Ordering}; use alloc::boxed::Box; use alloc::vec; +use embassy_embedded_hal::adapter::BlockingAsync; +use embassy_embedded_hal::flash::partition::Partition; use embassy_executor::Spawner; use embassy_sync::blocking_mutex; use embassy_sync::blocking_mutex::raw::CriticalSectionRawMutex; use embassy_sync::channel::Channel; +use embassy_sync::mutex::Mutex; use embassy_sync::signal::Signal; use embassy_time::Duration; use esp_alloc::{HeapRegion, MemoryCapability}; @@ -39,6 +42,7 @@ use esp_hal::lcd_cam::LcdCam; use esp_hal::lcd_cam::lcd::dpi::Dpi; use esp_hal::mcpwm::{McPwm, PeripheralClockConfig}; use esp_hal::psram::{FlashFreq, PsramConfig, PsramSize, SpiRamFreq, SpiTimingConfigCoreClock}; +use esp_hal::rng::TrngSource; use esp_hal::sha::{Sha, ShaBackend}; use esp_hal::system::Stack; use esp_hal::timer::timg::TimerGroup; @@ -196,16 +200,16 @@ async fn main(_spawner: Spawner) { info!("ESP-RTOS started!"); + // Enable the TRNG source, so `Trng` can be constructed. + let _trng_source = TrngSource::new(peripherals.RNG, peripherals.ADC1); + #[cfg(feature = "ble")] let mut host_resources = rmk::HostResources::new(); #[cfg(feature = "ble")] let stack = { - // Enable the TRNG source, so `Trng` can be constructed. use bt_hci::controller::ExternalController; - use esp_hal::rng::TrngSource; use esp_radio::{Controller as RadioController, ble::controller::BleConnector}; - let _trng_source = TrngSource::new(peripherals.RNG, peripherals.ADC1); let mut rng = esp_hal::rng::Trng::try_new().unwrap(); static RADIO: StaticCell> = StaticCell::new(); let radio = RADIO.init(esp_radio::init().unwrap()); @@ -241,16 +245,31 @@ async fn main(_spawner: Spawner) { }; // Initialize the flash - let flash = FlashStorage::new(peripherals.FLASH) - // Flash memory may not be written to while another core is executing from it. - // By default, `FlashStorage` is configured to abort the operation and log an error message. - // However, it can also be configured to auto-park the other core, such that writing to - // flash succeeds. - // Alternatively, XiP from PSRAM could be used along with the `multicore_ignore` strategy, - // to avoid having to park the other core, which could result in better performance. - // Invalid configuration would then present itself as freezing/UB. - .multicore_auto_park(); - let flash = async_flash_wrapper(flash); + static FLASH: StaticCell>> = + StaticCell::new(); + let flash = FLASH.init_with(|| { + let flash = FlashStorage::new(peripherals.FLASH) + // Flash memory may not be written to while another core is executing from it. + // By default, `FlashStorage` is configured to abort the operation and log an error message. + // However, it can also be configured to auto-park the other core, such that writing to + // flash succeeds. + // Alternatively, XiP from PSRAM could be used along with the `multicore_ignore` strategy, + // to avoid having to park the other core, which could result in better performance. + // Invalid configuration would then present itself as freezing/UB. + .multicore_auto_park(); + + Mutex::::new(async_flash_wrapper(flash)) + }); + const FLASH_SIZE_TOTAL: u32 = 16 * 1024 * 1024; + const FLASH_PART_FIRMWARE_OFFSET: u32 = 0; + const FLASH_PART_FIRMWARE_SIZE: u32 = 0x3f0000; + const FLASH_PART_RMK_OFFSET: u32 = FLASH_PART_FIRMWARE_OFFSET + FLASH_PART_FIRMWARE_SIZE; + const FLASH_PART_RMK_SIZE_IN_SECTORS: u32 = 16; + const FLASH_PART_RMK_SIZE: u32 = FLASH_PART_RMK_SIZE_IN_SECTORS * FlashStorage::SECTOR_SIZE; + const FLASH_PART_ACID_OFFSET: u32 = FLASH_PART_RMK_OFFSET + FLASH_PART_RMK_SIZE; + const FLASH_PART_ACID_SIZE: u32 = FLASH_SIZE_TOTAL - FLASH_PART_ACID_OFFSET; + let flash_part_rmk = Partition::new(flash, FLASH_PART_RMK_OFFSET, FLASH_PART_RMK_SIZE); + let flash_part_acid = Partition::new(flash, FLASH_PART_ACID_OFFSET, FLASH_PART_ACID_SIZE); info!("Flash memory configured!"); @@ -296,8 +315,8 @@ async fn main(_spawner: Spawner) { // RMK config let vial_config = VialConfig::new(VIAL_KEYBOARD_ID, VIAL_KEYBOARD_DEF, &[(0, 0), (1, 1)]); let storage_config = StorageConfig { - start_addr: 0x3f0000, - num_sectors: 16, + start_addr: 0, + num_sectors: FLASH_PART_RMK_SIZE_IN_SECTORS as u8, ..Default::default() }; let rmk_config = RmkConfig { @@ -313,7 +332,7 @@ async fn main(_spawner: Spawner) { let mut per_key_config = PositionalConfig::default(); let (keymap, mut storage) = initialize_keymap_and_storage( &mut default_keymap, - flash, + flash_part_rmk, &storage_config, &mut behavior_config, &mut per_key_config, @@ -379,7 +398,7 @@ async fn main(_spawner: Spawner) { window: RefCell::new(None), framebuffer: framebuffer_ptr, }; - spawner.must_spawn(ui::run_renderer_task(slint_backend)); + spawner.must_spawn(ui::run_renderer_task(slint_backend, flash_part_acid)); }); }, ); diff --git a/firmware/acid-firmware/src/ui/mod.rs b/firmware/acid-firmware/src/ui/mod.rs index 0ceff2b..7b94113 100644 --- a/firmware/acid-firmware/src/ui/mod.rs +++ b/firmware/acid-firmware/src/ui/mod.rs @@ -1,8 +1,17 @@ // #![cfg_attr(not(feature = "simulator"), no_main)] +use core::ops::{Deref, DerefMut}; + use alloc::{boxed::Box, ffi::CString}; +use ekv::{Database, MountError, flash::PageID}; +use embassy_embedded_hal::{adapter::BlockingAsync, flash::partition::Partition}; +use embassy_sync::blocking_mutex::raw::{CriticalSectionRawMutex, RawMutex}; use embassy_time::{Duration, Instant}; +use embedded_storage_async::nor_flash::{NorFlash, ReadNorFlash}; +use esp_hal::rng::Trng; +use esp_storage::FlashStorage; use log::{info, warn}; +use rmk::futures::TryFutureExt; use slint::SharedString; use spectre_api_sys::{SpectreAlgorithm, SpectreCounter, SpectreKeyPurpose, SpectreUserKey}; @@ -15,8 +24,114 @@ pub mod window_adapter; slint::include_modules!(); +type PartitionAcid = + Partition<'static, CriticalSectionRawMutex, BlockingAsync>>; + +// Workaround for alignment requirements. +#[repr(C, align(4))] +struct AlignedBuf(pub [u8; N]); + +struct EkvFlash { + flash: T, + buffer: Box>, +} + +impl EkvFlash { + fn new(flash: T) -> Self { + Self { + flash, + buffer: { + // Allocate the buffer directly on the heap. + let buffer = Box::new_zeroed(); + unsafe { buffer.assume_init() } + }, + } + } +} + +impl Deref for EkvFlash { + type Target = T; + + fn deref(&self) -> &Self::Target { + &self.flash + } +} + +impl DerefMut for EkvFlash { + fn deref_mut(&mut self) -> &mut Self::Target { + &mut self.flash + } +} + +impl ekv::flash::Flash for EkvFlash { + type Error = T::Error; + + fn page_count(&self) -> usize { + ekv::config::MAX_PAGE_COUNT + } + + async fn erase( + &mut self, + page_id: PageID, + ) -> Result<(), as ekv::flash::Flash>::Error> { + self.flash + .erase( + (page_id.index() * ekv::config::PAGE_SIZE) as u32, + ((page_id.index() + 1) * ekv::config::PAGE_SIZE) as u32, + ) + .await + } + + async fn read( + &mut self, + page_id: PageID, + offset: usize, + data: &mut [u8], + ) -> Result<(), as ekv::flash::Flash>::Error> { + let address = page_id.index() * ekv::config::PAGE_SIZE + offset; + self.flash + .read(address as u32, &mut self.buffer.0[..data.len()]) + .await?; + data.copy_from_slice(&self.buffer.0[..data.len()]); + Ok(()) + } + + async fn write( + &mut self, + page_id: PageID, + offset: usize, + data: &[u8], + ) -> Result<(), as ekv::flash::Flash>::Error> { + let address = page_id.index() * ekv::config::PAGE_SIZE + offset; + self.buffer.0[..data.len()].copy_from_slice(data); + self.flash + .write(address as u32, &self.buffer.0[..data.len()]) + .await + } +} + #[embassy_executor::task] -pub async fn run_renderer_task(backend: SlintBackend) { +pub async fn run_renderer_task(backend: SlintBackend, flash_part_acid: PartitionAcid) { + let mut db_config = ekv::Config::default(); + db_config.random_seed = Trng::try_new() + .expect("A `TrngSource` was not initialized before constructing this `Trng`.") + .random(); + let mut db = Database::<_, esp_sync::RawMutex>::new(EkvFlash::new(flash_part_acid), db_config); + + #[cfg(feature = "format-db")] + { + warn!("Formatting EKV database..."); + db.format() + .await + .unwrap_or_else(|error| panic!("Failed to format the EKV database: {error:?}")); + warn!("EKV database formatted successfully."); + } + + match db.mount().await { + Ok(()) => info!("EKV database mounted."), + Err(error) => panic!("Failed to mount the EKV database: {error:?}"), + }; + slint::platform::set_platform(Box::new(backend)).expect("backend already initialized"); let main = AppWindow::new().unwrap(); @@ -57,21 +172,23 @@ pub async fn run_renderer_task(backend: SlintBackend) { } }); - // Instead of having a `loop` in the non-async `SlintBackend::run_event_loop`, we achieve - // async by having only one iteration of the loop run, and `await`ing here. - // The following block is analogous to `main.run()`. - { - main.show().unwrap(); - - loop { - slint::run_event_loop().unwrap(); - SIGNAL_LCD_SUBMIT.signal(()); - #[cfg(feature = "limit-fps")] - embassy_time::Timer::after(FRAME_DURATION_MIN).await; - SIGNAL_UI_RENDER.wait().await; - } - - #[expect(unreachable_code)] - main.hide().unwrap(); - } + run_event_loop(main).await; +} + +/// Instead of having a `loop` in the non-async `SlintBackend::run_event_loop`, we achieve +/// async by having only one iteration of the loop run, and `await`ing here. +/// The following block is analogous to `main.run()`. +async fn run_event_loop(main: AppWindow) { + main.show().unwrap(); + + loop { + slint::run_event_loop().unwrap(); + SIGNAL_LCD_SUBMIT.signal(()); + #[cfg(feature = "limit-fps")] + embassy_time::Timer::after(FRAME_DURATION_MIN).await; + SIGNAL_UI_RENDER.wait().await; + } + + #[expect(unreachable_code)] + main.hide().unwrap(); } diff --git a/firmware/acid-firmware/ui/main.slint b/firmware/acid-firmware/ui/main.slint index fbbd715..e7528f4 100644 --- a/firmware/acid-firmware/ui/main.slint +++ b/firmware/acid-firmware/ui/main.slint @@ -14,6 +14,7 @@ import { Button, VerticalBox, LineEdit, GridBox } from "std-widgets.slint"; import "../fonts/IBM_Plex_Mono/IBMPlexMono-Regular.ttf"; /* +TODO: A bigger stack for the 2nd core might be needed to prevent crashing. export enum AppState { PasswordForm, }