skip to content
==> src/snapshot.c <==
1/* Snapshot v3, section by section. */
2#include "mesh/snapshot.h"
3#include "mesh/abi.h"
4#include "mesh/prog_table.h"
5
6#include <stdlib.h>
7#include <string.h>
8
9static uint32_t w32(const uint8_t *b, size_t o) { return (uint32_t)b[o] | (uint32_t)b[o + 1] << 8 | (uint32_t)b[o + 2] << 16 | (uint32_t)b[o + 3] << 24; }
10
11static void mb_append(mesh_buf *out, mesh_mailbox mb, size_t off, size_t len) {
12    size_t at = out->len;
13    mesh_buf_zeros(out, len);
14    mesh_mailbox_read(mb, off, (uint8_t *)out->data + at, len);
15}
16
17void mesh_snapshot(mesh_buf *s, mesh_mailbox mb, mesh_host_block *host) {
18    size_t start = s->len;
19    mesh_buf_zeros(s, MESH_SN_HEAD_BYTES);
20    mb_append(s, mb, 0, MESH_H_BYTES);
21    uint32_t count = 0;
22    for (uint32_t slot = 0; slot < MESH_PROG_SLOTS; slot++) {
23        if (mesh_mailbox_get(mb, mesh_prog_entry(slot) + MESH_PT_STATE) == MESH_ST_EMPTY) continue;
24        uint8_t entry[MESH_PT_BYTES];
25        mesh_pt_read_entry(mb, slot, entry);
26        uint32_t nodes = w32(entry, MESH_PT_NODES), view_off = w32(entry, MESH_PT_VIEW_OFF);
27        uint32_t snap = w32(entry, MESH_PT_SNAP_BYTES), vb = w32(entry, MESH_PT_VIEW_BYTES);
28        if (nodes > MESH_PROG_MAX_NODES) nodes = MESH_PROG_MAX_NODES;
29        if (snap > vb) snap = vb;
30        mesh_buf_u32le(s, slot);
31        mesh_buf_u32le(s, (uint32_t)mesh_section_bytes(nodes, snap));
32        mesh_buf_u32le(s, nodes);
33        mesh_buf_u32le(s, snap);
34        mesh_buf_put(s, entry, MESH_PT_BYTES);
35        mb_append(s, mb, mesh_prog_ctl(slot), MESH_SC_CTL_BYTES);
36        mb_append(s, mb, mesh_prog_ext(slot), MESH_PX_BYTES);
37        mb_append(s, mb, mesh_node_rec(slot, 0), (size_t)MESH_NODE_STRIDE * nodes);
38        size_t padded = ((size_t)snap + 3) / 4 * 4;
39        if (snap > 0) {
40            size_t at = s->len;
41            mb_append(s, mb, view_off, padded);
42            memset(s->data + at + snap, 0, padded - snap); /* zero padded, not the view's next bytes */
43        }
44        count++;
45    }
46    uint32_t host_at = (uint32_t)(s->len - start);
47    size_t at = s->len;
48    mesh_buf_zeros(s, MESH_SNAP_HOST);
49    mesh_host_block_bytes(host, (uint8_t *)s->data + at);
50    uint32_t total = (uint32_t)(s->len - start);
51    const uint32_t v[4][2] = {{MESH_SN_TOTAL, total}, {MESH_SN_COUNT, count}, {MESH_SN_VERSION, MESH_SNAP_VERSION}, {MESH_SN_HOST_AT, host_at}};
52    for (int i = 0; i < 4; i++)
53        for (int b = 0; b < 4; b++) s->data[start + v[i][0] + (size_t)b] = (char)(v[i][1] >> (8 * b));
54}