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>
55 lines
2.1 KiB
C
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;
|
|
}
|