Files
LithosAnanake/v4/system/blocks.c
T
rajamesandClaude Opus 5.5 bcfd6556a8 fix(v4.0.0): storage -- what the review of step 6 found
A block request with fewer than two values on the stack is refused; it
had acted on whatever the stack ring held and stopped the node.

Bare metal: when the kernel's chain takes the place of POST's block RAM
the node's two buffers are emptied, so it no longer holds POST's copy of
a block; and the chain's fast RAM is cleared, so a node cannot read what
was in the kernel's heap.

blocks.c is built with each test under that test's own warnings and
sanitizers; it had been left out of both.  The hosted link cleans its
object directory first: it had linked the withdrawn store_v3.o left there
from the day before.

node.h and DECOMPOSITION.md D-19 no longer describe the message device or
the four registers as current.  MESH.md 8.5 records two findings for
ruling: a node's own copy of a block, and a block read over a node's code.

From a clean build: make -C v4 test, sanitize and hosted-check pass;
amd64, aarch64 and riscv64 boot, POST 538 of 538, same hashes, blocks 1
and 2047 clean at the prompt: logs/20261007-085017, -085254, -085636.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-07 08:58:52 -04:00

55 lines
2.1 KiB
C

/* blocks.c -- the kernel serves a node's block requests. See blocks.h.
*
* This is the one file of v4's that includes v3's headers: every block goes
* through v3's own calls.
*/
#include "v4/blocks.h"
#include "block_subsystem.h"
int v4_blocks_serve(v4_node *n, v4_cell request)
{
v4_cell addr, num;
uint32_t block;
uint8_t *b;
unsigned i;
int status;
if (request != V4_REQ_BLOCK_READ && request != V4_REQ_BLOCK_WRITE) return 0;
if (n->ds.depth < 2u) { /* not both arguments: nothing is done with what is there */
v4_dstack_reset(&n->ds);
v4_dstack_push(&n->ds, (v4_cell)V4_BLOCK_REFUSED);
return 1;
}
addr = v4_dstack_pop(&n->ds);
num = v4_dstack_pop(&n->ds);
block = (uint32_t)num;
if (!v4_node_addr_ok(addr) || !v4_node_addr_ok(addr + (v4_cell)(V4_BLOCK_CELLS - 1u))) {
status = V4_BLOCK_REFUSED;
} else if (num < 1 || (uint64_t)num > 0xFFFFFFFFull || !blk_is_valid(block)) {
status = V4_BLOCK_RANGE;
} else if (request == V4_REQ_BLOCK_READ) {
b = blk_get_buffer(block, 0);
status = b ? V4_BLOCK_OK : V4_BLOCK_REFUSED;
if (b)
for (i = 0; i < V4_BLOCK_CELLS; i++)
n->mem[addr + (v4_cell)i] = (v4_cell)((v4_ucell)b[4u * i] | ((v4_ucell)b[4u * i + 1u] << 8)
| ((v4_ucell)b[4u * i + 2u] << 16) | ((v4_ucell)b[4u * i + 3u] << 24));
} else {
b = blk_get_buffer(block, 1);
status = V4_BLOCK_REFUSED;
if (b) {
for (i = 0; i < V4_BLOCK_CELLS; i++) {
v4_ucell w = (v4_ucell)n->mem[addr + (v4_cell)i];
b[4u * i] = (uint8_t)(w & 0xFFu);
b[4u * i + 1u] = (uint8_t)((w >> 8) & 0xFFu);
b[4u * i + 2u] = (uint8_t)((w >> 16) & 0xFFu);
b[4u * i + 3u] = (uint8_t)((w >> 24) & 0xFFu);
}
if (blk_update(block) == BLK_OK && blk_flush(block) == BLK_OK) status = V4_BLOCK_OK;
}
}
v4_dstack_push(&n->ds, (v4_cell)status);
return 1;
}