mirror of
https://github.com/vk496/MeshCore.git
synced 2026-09-10 13:46:31 +00:00
ota: seeder storage protocol (pull-to-folder) + motatool serve storage handlers
Add the device->host WRITE half of the mota-seeder link so a device can capture a .mota it is fetching off-mesh into the host folder (the same --dir used for serving), stored as <mid>.mota — e.g. to grab an exact copy of a device's firmware to build a delta against firmware you don't otherwise have. - MotaSeederProto: OP_STAT / OP_BEGIN / OP_WRITE / OP_SREAD / OP_FIN (keyed by mid). Resume needs no host bookkeeping: BEGIN 0xFF-fills the file; on reconnect the device SREADs the leaves and re-requests only missing blocks (same as flash resume). Partial = <midhex>.mota.part, published to <midhex>.mota on FIN. - motatool `serve --dir <folder>` now also handles the storage ops on the same folder/connection (SeederCore gains the store dir; serve_loop frames the variable-length WRITE). Host round-trip test added. Firmware side (FolderMotaStore + `ota pull <#> <dest>` + pause/resume) follows.
This commit is contained in:
@@ -21,8 +21,19 @@
|
||||
// MotaDesc wire (38 B): mid[4] target_id(4) fw_version(4) codec(1) flags(1) total_size(4)
|
||||
// leaves_off(4) block_count(4) payload_off(4) payload_size(4)
|
||||
//
|
||||
// status: 0 = OK, non-zero = error (idx out of range, read past EOF, ...). On error the response carries
|
||||
// no payload (just magic+op+status+xsum).
|
||||
// --- STORAGE ops (device -> host WRITE): "pull to folder". The device is fetching a `.mota` off the mesh
|
||||
// (e.g. a neighbour's self-served firmware it has no local copy of) and streams it into the host folder as
|
||||
// `<mid>.mota`, so the exact image can be captured for later delta-building. The device still initiates.
|
||||
// Resume needs NO host bookkeeping: OP_BEGIN 0xFF-fills the file and, on reconnect, the device OP_SREADs the
|
||||
// merkle leaves and re-requests only the missing blocks (identical to flash-resume). All keyed by mid[4].
|
||||
// OP_STAT 0x04 args: mid(4) resp payload: present(1) total_size(4)
|
||||
// OP_BEGIN 0x05 args: mid(4) total_size(4) resp: status OK (create/truncate, 0xFF-filled)
|
||||
// OP_WRITE 0x06 args: mid(4) off(4) len(2) data(len) resp: status OK
|
||||
// OP_SREAD 0x07 args: mid(4) off(4) len(2) resp payload: len bytes (0xFF = never written)
|
||||
// OP_FIN 0x08 args: mid(4) resp: status OK (validate + make servable)
|
||||
//
|
||||
// status: 0 = OK, non-zero = error (idx out of range, read past EOF, no such stored file, ...). On error the
|
||||
// response carries no payload (just magic+op+status+xsum).
|
||||
|
||||
namespace mesh {
|
||||
namespace ota {
|
||||
@@ -35,10 +46,17 @@ static const uint8_t MOTA_SEEDER_RSP_MAGIC1 = 's';
|
||||
static const uint8_t MS_OP_COUNT = 0x01;
|
||||
static const uint8_t MS_OP_DESCRIBE = 0x02;
|
||||
static const uint8_t MS_OP_READ = 0x03;
|
||||
static const uint8_t MS_OP_STAT = 0x04; // storage: does <mid>.mota exist on the host? + its size
|
||||
static const uint8_t MS_OP_BEGIN = 0x05; // storage: create/truncate <mid>.mota (0xFF-filled)
|
||||
static const uint8_t MS_OP_WRITE = 0x06; // storage: write bytes at offset
|
||||
static const uint8_t MS_OP_SREAD = 0x07; // storage: read bytes back (resume: recompute missing blocks)
|
||||
static const uint8_t MS_OP_FIN = 0x08; // storage: transfer complete — validate + make servable
|
||||
|
||||
static const uint8_t MS_STATUS_OK = 0x00;
|
||||
static const uint8_t MS_STATUS_ERR = 0x01;
|
||||
|
||||
static const uint16_t MOTA_DESC_WIRE = 38; // bytes of a MotaDesc on the wire (see layout above)
|
||||
static const uint16_t MOTA_SEEDER_WRITE_MAX = 512; // max data bytes per OP_WRITE/OP_SREAD (bounds frames)
|
||||
|
||||
} // namespace ota
|
||||
} // namespace mesh
|
||||
|
||||
Reference in New Issue
Block a user