CDC Badge OS
Firmware for the CDC Badge v1.0 hardware security key
Loading...
Searching...
No Matches
PluginStorage.cpp
Go to the documentation of this file.
2#include "cdc_core/Raii.h"
4#include "cdc_log.h"
5
6#include "esp_vfs.h"
7#include "esp_vfs_fat.h"
8#include "esp_partition.h"
9
10#include <algorithm>
11#include <cerrno>
12#include <cstring>
13#include <cstdio>
14#include <dirent.h>
15#include <sys/stat.h>
16
17namespace cdc::plugin_manager {
18
19static const char* TAG = "PLG_STO";
20static const char* PARTITION_LABEL = "plugins";
21static const char* MOUNT_POINT = "/plugins";
22
23static wl_handle_t s_wl_handle = WL_INVALID_HANDLE;
24static bool s_mounted = false;
25
27{
28 if (s_mounted) return true;
29
30 const esp_vfs_fat_mount_config_t cfg = {
31 .format_if_mount_failed = true,
32 .max_files = 5,
33 .allocation_unit_size = CONFIG_WL_SECTOR_SIZE,
34 .disk_status_check_enable = false,
35 .use_one_fat = false,
36 };
37
38 esp_err_t err = esp_vfs_fat_spiflash_mount_rw_wl(
40 if (err != ESP_OK) {
41 LOG_E(TAG, "mount failed: 0x%x", err);
42 return false;
43 }
44
45 LOG_I(TAG, "mounted %s on %s", PARTITION_LABEL, MOUNT_POINT);
46 s_mounted = true;
47 return true;
48}
49
51{
52 if (!s_mounted) return;
53 esp_vfs_fat_spiflash_unmount_rw_wl(MOUNT_POINT, s_wl_handle);
54 s_wl_handle = WL_INVALID_HANDLE;
55 s_mounted = false;
56}
57
59{
60 return MOUNT_POINT;
61}
62
63static bool ends_with(const char* s, size_t s_len, const char* suffix, size_t suf_len)
64{
65 return s_len > suf_len && std::strcmp(s + s_len - suf_len, suffix) == 0;
66}
67
68std::vector<std::string> PluginStorage::listPluginIds()
69{
70 std::vector<std::string> ids;
71 if (!s_mounted) return ids;
72
73 DIR* dir = opendir(MOUNT_POINT);
74 if (!dir) {
75 LOG_W(TAG, "opendir failed");
76 return ids;
77 }
78
79 while (struct dirent* ent = readdir(dir)) {
80 const char* name = ent->d_name;
81 size_t len = std::strlen(name);
82 std::string id;
83 if (ends_with(name, len, ".aot", 4)) {
84 id.assign(name, len - 4);
85 } else if (ends_with(name, len, ".wasm", 5)) {
86 id.assign(name, len - 5);
87 } else {
88 continue;
89 }
90 if (std::find(ids.begin(), ids.end(), id) != ids.end()) continue;
91
92 std::string meta = metaPath(id);
93 struct stat st;
94 if (stat(meta.c_str(), &st) == 0 && (st.st_mode & S_IFREG)) {
95 ids.push_back(std::move(id));
96 }
97 }
98
99 closedir(dir);
100 return ids;
101}
102
103std::string PluginStorage::binaryPath(const std::string& id)
104{
105#if FEATURE_PLUGIN_AOT
106 std::string aot = aotPath(id);
107 struct stat st;
108 if (stat(aot.c_str(), &st) == 0 && (st.st_mode & S_IFREG)) {
109 return aot;
110 }
111#endif
112 return wasmPath(id);
113}
114
115std::string PluginStorage::wasmPath(const std::string& id)
116{
117 return std::string(MOUNT_POINT) + "/" + id + ".wasm";
118}
119
120std::string PluginStorage::aotPath(const std::string& id)
121{
122 return std::string(MOUNT_POINT) + "/" + id + ".aot";
123}
124
125std::string PluginStorage::metaPath(const std::string& id)
126{
127 return std::string(MOUNT_POINT) + "/" + id + ".meta";
128}
129
130std::string PluginStorage::langPath(const std::string& id)
131{
132 return std::string(MOUNT_POINT) + "/" + id + ".lang";
133}
134
135std::string PluginStorage::disabledPath(const std::string& id)
136{
137 return std::string(MOUNT_POINT) + "/" + id + ".disabled";
138}
139
140bool PluginStorage::isDisabled(const std::string& id)
141{
142 struct stat st;
143 const std::string path = disabledPath(id);
144 return stat(path.c_str(), &st) == 0 && (st.st_mode & S_IFREG);
145}
146
147bool PluginStorage::setDisabled(const std::string& id, bool disabled)
148{
149 const std::string path = disabledPath(id);
150 if (!disabled) {
151 errno = 0;
152 return std::remove(path.c_str()) == 0 || errno == ENOENT;
153 }
154
155 auto fp = ::cdc::core::openFile(path.c_str(), "wb");
156 if (!fp) return false;
157 static constexpr char kMarker[] = "disabled\n";
158 return std::fwrite(kMarker, 1, sizeof(kMarker) - 1, fp.get()) == sizeof(kMarker) - 1;
159}
160
161bool PluginStorage::stats(uint64_t& free_bytes, uint64_t& total_bytes)
162{
163 if (!s_mounted) return false;
164 return esp_vfs_fat_info(MOUNT_POINT, &total_bytes, &free_bytes) == ESP_OK;
165}
166
167} // namespace cdc::plugin_manager
Mounts the FAT-FS partition that holds plugin .wasm + .meta files.
char name[cdc::hal::ISecureElement::RMEM_NAME_LEN]
Shared RAII wrappers for firmware resources.
CDC Log: logging over TinyUSB CDC and UART.
#define LOG_W(tag, fmt,...)
Definition cdc_log.h:146
#define LOG_I(tag, fmt,...)
Definition cdc_log.h:147
#define LOG_E(tag, fmt,...)
Definition cdc_log.h:145
static bool mount()
Mount the plugins partition. Auto-formats if empty.
static const char * basePath()
Returns the VFS path prefix, e.g. "/plugins".
static std::string langPath(const std::string &id)
Returns the full VFS path of <id>.lang (translation overlay).
static void unmount()
Unmount the plugins partition (rarely used; mostly tests).
static std::string aotPath(const std::string &id)
Returns the full VFS path of <id>.aot.
static bool stats(uint64_t &free_bytes, uint64_t &total_bytes)
Returns the free and total bytes on the plugins partition.
static bool isDisabled(const std::string &id)
True when the plugin has a persistent disabled marker.
static bool setDisabled(const std::string &id, bool disabled)
Create or remove the persistent disabled marker for a plugin.
static std::string disabledPath(const std::string &id)
Returns the full VFS path of <id>.disabled.
static std::vector< std::string > listPluginIds()
Discover all installed plugin ids. A plugin is recognised by the presence of both <id>....
static std::string wasmPath(const std::string &id)
Returns the full VFS path of <id>.wasm.
static std::string metaPath(const std::string &id)
Returns the full VFS path of <id>.meta.
static std::string binaryPath(const std::string &id)
Returns the path that should be loaded for <id>: <id>.aot if it exists on disk, otherwise <id>....
FilePtr openFile(const char *path, const char *mode) noexcept
Open a FILE* and wrap it in a FilePtr.
Definition Raii.h:87
static const char * MOUNT_POINT
static bool ends_with(const char *s, size_t s_len, const char *suffix, size_t suf_len)
static wl_handle_t s_wl_handle
static const char * PARTITION_LABEL
static const char * TAG