Use internal bootloader staging regardless of RAK app storage

This commit is contained in:
mikecarper committed 2026-09-29 03:27:10 -07:00
1 parent 346cf2fd1f
commit 5c4b6d6301
2 files changed
+48 -2

No files matched your search

+5 -2
View File
@@ -597,11 +597,14 @@ bool handle_ota_command(const char* command, char* reply, mesh::MainBoard& board
return true;
}
#elif defined(OTA_RAK_AUTO_STORE)
if (c.fetch_store.usesExternal() && !(bl.storage_flags & OTA_BL_STORAGE_QSPI)) {
// Bootloader packages passed their separate privileged checks above and
// select internal staging when their manifest arrives. The currently
// selected application backend must not veto that transition.
if (!selboot && c.fetch_store.usesExternal() && !(bl.storage_flags & OTA_BL_STORAGE_QSPI)) {
strcpy(reply, "ERR bootloader cannot apply from detected QSPI storage");
return true;
}
if (!c.fetch_store.usesExternal() && !c.fetch_store.usesInternal()) {
if (!selboot && !c.fetch_store.usesExternal() && !c.fetch_store.usesInternal()) {
snprintf(reply, 160, "ERR OTA storage unsafe: %s", c.fetch_store.selectionReason());
return true;
}
+43
View File
@@ -10,6 +10,49 @@ ROOT = Path(__file__).resolve().parents[1]
class AdaptiveBootloaderTest(unittest.TestCase):
def test_cli_uses_application_storage_gate_only_for_applications(self):
cli = (ROOT / "src/helpers/ota/OtaCli.cpp").read_text()
error = cli.index('ERR bootloader cannot apply from detected QSPI storage')
start = cli.rfind('#elif defined(OTA_RAK_AUTO_STORE)', 0, error)
end = cli.index('#elif defined(OTA_QSPI_STORE)', error)
gate = cli[cli.index('\n', start) + 1:end]
source = r'''
#include <cassert>
#include <cstdio>
#include <cstring>
#include <cstdint>
constexpr uint8_t OTA_BL_STORAGE_QSPI = 4;
struct Store {
int mode;
bool usesExternal() { return mode == 1; }
bool usesInternal() { return mode == 0; }
const char* selectionReason() { return "unsafe wiring"; }
};
bool rejected(bool selboot, int mode, uint8_t flags) {
struct { Store fetch_store; } c = {{mode}};
struct { uint8_t storage_flags; } bl = {flags};
char reply[160];
''' + gate + r'''
return false;
}
int main() {
// The CLI has already required exact identity and privileged boot caps.
assert(!rejected(true, 1, 0x0A)); // canonical bootloader, external app store
assert(!rejected(true, 0, 0x0A));
assert(!rejected(true, 2, 0x0A)); // optional NOR is irrelevant to internal boot staging
assert(rejected(false, 1, 0x0A)); // app still needs the external capability
assert(rejected(false, 2, 0x1E)); // unsafe application store remains rejected
assert(!rejected(false, 1, 0x1E));
assert(!rejected(false, 0, 0x0A));
}
'''
with tempfile.TemporaryDirectory() as directory:
path = Path(directory)
(path / "cli.cpp").write_text(source)
subprocess.run(["g++", "-std=c++17", "-Wall", "-Wextra", "-Werror",
str(path / "cli.cpp"), "-o", str(path / "cli")], check=True)
subprocess.run([str(path / "cli")], check=True)
def test_storage_switch_and_manual_resume(self):
header = (ROOT / "src/helpers/ota/OtaStoreAdaptiveNrf52.h").read_text()
body = header[header.index("class OtaStoreAdaptiveNrf52"):