Files
LithosAnanake/include/starkernel/capsule.h
T
Robert Allan JamesandClaude Sonnet 5 b031b802e3 Rename FABRIC series: FABRIC.md->0, FABRIC-2.md->1, FABRIC-3.md->2, FABRIC-4.md unchanged
FABRIC.md -> FABRIC-0.md
FABRIC-2.md -> FABRIC-1.md
FABRIC-3.md -> FABRIC-2.md (the current/living document)
FABRIC-4.md unchanged (new #3 to follow separately)

Every cross-reference repo-wide updated to match, including doc-comment
citations inside kernel source (.c/.h) files -- done via an ordered
placeholder substitution (FABRIC-3.md->placeholder2, FABRIC-2.md->
placeholder1, FABRIC.md->placeholder0, then placeholders resolved to
final names) in a single pass per file to avoid double-shifting
already-renamed references.

One line in capsules/font.4th grew past the 64-char block-format limit
as a side effect of the longer filename; shortened it and reverified
with mkcapsule --lint (34/34 pass) before rebuilding.

Verified 3-arch boot to ok> (amd64/aarch64/riscv64, each in the
foreground) after the fix; logs and DoE CSVs from this session's
verification runs included per this repo's own audit-artifact
convention.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_019YcT3H2PQeyujrzjqS3Var
2026-09-04 11:22:51 -04:00

305 lines
11 KiB
C
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
/*
StarForth — Steady-State Virtual Machine Runtime
Copyright (c) 20232025 Robert A. James
All rights reserved.
This file is part of the StarForth project.
Licensed under the StarForth License, Version 1.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at:
https://github.com/star.4th@proton.me/StarForth/LICENSE.txt
This software is provided "AS IS", WITHOUT WARRANTY OF ANY KIND,
express or implied, including but not limited to the warranties of
merchantability, fitness for a particular purpose, and noninfringement.
See the License for the specific language governing permissions and
limitations under the License.
*/
/**
* capsule.h - Init Capsule Architecture (M7.1)
*
* Content-addressed, immutable init capsules for VM birth.
* See docs/lithosananke/M7.1.md for full specification.
*
* Key invariants:
* - Exactly ONE production (p) INIT defines a baby VM
* - capsule_id == content_hash (content-addressed)
* - No shared/implicit base INITs
* - DOMAIN is Mama-only, PERSONALITY is baby-only
*/
#ifndef STARKERNEL_CAPSULE_H
#define STARKERNEL_CAPSULE_H
#include <stdint.h>
#include <stddef.h>
#ifdef __cplusplus
extern "C" {
#endif
/*===========================================================================
* Constants
*===========================================================================*/
/** Magic signatures */
#define CAPSULE_DESC_MAGIC 0x53504143ULL /* 'CAPS' little-endian */
#define CAPSULE_DIR_MAGIC 0x44504143ULL /* 'CAPD' little-endian */
/** Version */
#define CAPSULE_VERSION_0 0
/** Limits */
#define CAPSULE_MAX_COUNT 256
/** Maximum capsule name length (colon-separated path, null-terminated) */
#define CAPSULE_NAME_MAX 512
/*===========================================================================
* Hash Algorithm Enum
*===========================================================================*/
typedef enum {
CAPSULE_HASH_XXHASH64 = 0,
CAPSULE_HASH_SHA256 = 1,
CAPSULE_HASH_BLAKE3 = 2,
} CapsuleHashAlg;
/*===========================================================================
* Flags
*===========================================================================*/
/** State flags */
#define CAPSULE_FLAG_ACTIVE 0x00000001 /* Eligible for use */
#define CAPSULE_FLAG_REVOKED 0x00000002 /* Birth-blocked forever */
#define CAPSULE_FLAG_DEPRECATED 0x00000004 /* Eligible but discouraged */
#define CAPSULE_FLAG_PINNED 0x00000008 /* Immune to GC */
/** Mode flags (D2: babies carry both) */
#define CAPSULE_FLAG_PRODUCTION 0x00000010 /* (p) truth-bearing */
#define CAPSULE_FLAG_EXPERIMENT 0x00000020 /* (e) workload only */
/** Mama init flag (exactly one capsule must have this) */
#define CAPSULE_FLAG_MAMA_INIT 0x00000040 /* (m) Mama's init */
/** Contributor capsule flag (FABRIC-2.md §I.5, 2026-09-04) -- path-match
* on capsules/contrib/, mirrors FLAG_MAMA_INIT's own exact-match pattern
* in mkcapsule.c's flags_from_name(). Trust-tier enforcement (QEMU-vs-
* real-hardware, decided in conversation) is a runtime check in
* capsule_validate()'s callers, not encoded in this bit itself -- the
* bit only marks "this capsule's provenance is a contributor, not this
* project's own source," same as CAPSULE_FLAG_PRODUCTION/_EXPERIMENT
* mark mode, not policy. */
#define CAPSULE_FLAG_CONTRIB 0x00000080 /* (c) contributor-submitted */
/** Validate mode flags.
* Mama: neither (p) nor (e) may be set.
* Babies: at least one of (p) or (e) must be set (both is fine — D2). */
#define CAPSULE_MODE_VALID(f) \
((((f) & CAPSULE_FLAG_MAMA_INIT) != 0) ? \
(!((f) & (CAPSULE_FLAG_PRODUCTION | CAPSULE_FLAG_EXPERIMENT))) : \
(((f) & CAPSULE_FLAG_PRODUCTION) || ((f) & CAPSULE_FLAG_EXPERIMENT)))
/** Check if capsule is Mama's init */
#define CAPSULE_IS_MAMA_INIT(f) \
(((f) & CAPSULE_FLAG_MAMA_INIT) && ((f) & CAPSULE_FLAG_ACTIVE))
/** Birth eligibility: active and not revoked (flag type irrelevant — D2) */
#define CAPSULE_BIRTH_ELIGIBLE(f) \
(((f) & CAPSULE_FLAG_ACTIVE) && \
!((f) & CAPSULE_FLAG_REVOKED))
/** DoE eligibility: experiment, active, not revoked */
#define CAPSULE_DOE_ELIGIBLE(f) \
(((f) & CAPSULE_FLAG_EXPERIMENT) && \
((f) & CAPSULE_FLAG_ACTIVE) && \
!((f) & CAPSULE_FLAG_REVOKED))
/*===========================================================================
* Magic Field Packing
*
* bits 0..31 : 'CAPS' (0x53504143 little-endian)
* bits 32..39 : version (0 for v0)
* bits 40..47 : hashAlg (enum CapsuleHashAlg)
* bits 48..63 : reserved (zero)
*===========================================================================*/
#define CAPSULE_MAGIC_PACK(ver, alg) \
(CAPSULE_DESC_MAGIC | ((uint64_t)(ver) << 32) | ((uint64_t)(alg) << 40))
#define CAPSULE_MAGIC_GET_SIG(m) ((uint32_t)((m) & 0xFFFFFFFFULL))
#define CAPSULE_MAGIC_GET_VERSION(m) ((uint8_t)(((m) >> 32) & 0xFF))
#define CAPSULE_MAGIC_GET_HASHALG(m) ((uint8_t)(((m) >> 40) & 0xFF))
/*===========================================================================
* CapsuleDesc - Capsule Descriptor (64 bytes, cache-line aligned)
*===========================================================================*/
typedef struct __attribute__((aligned(64))) {
uint64_t magic; /* 0x00: 'CAPS' | ver | hashAlg | reserved */
uint64_t capsule_id; /* 0x08: == content_hash (content-addressed) */
uint64_t content_hash; /* 0x10: hash of payload bytes */
uint64_t offset; /* 0x18: byte offset into payload arena */
uint64_t length; /* 0x20: payload length in bytes */
uint32_t flags; /* 0x28: state + policy bits */
uint32_t owner_vm; /* 0x2C: 0 = mama, else child VM ID */
uint64_t birth_count; /* 0x30: how many VMs born from this */
uint64_t created_ns; /* 0x38: monotonic timestamp at registration */
} CapsuleDesc; /* 0x40 = 64 bytes */
/*===========================================================================
* CapsuleNameEntry - Capsule Name (parallel array to CapsuleDesc[])
*
* Indexed 1:1 with capsule_descriptors[]. Name is the full relative path
* from the capsule root with '/' replaced by ':', e.g.:
* "core:init.4th"
* "experiments:doe-l8:init-l8-diverse.4th"
* "production:myvm.4th"
*===========================================================================*/
typedef struct {
char name[CAPSULE_NAME_MAX]; /* null-terminated, colon-separated path */
} CapsuleNameEntry;
/*===========================================================================
* CapsuleSigEntry - Ed25519 signature (parallel array to CapsuleDesc[])
*
* Milestone 6 (Phase 8): each capsule's payload bytes (the same bytes
* content_hash already covers), signed by mkcapsule at build time with
* the snakeoil intermediate's private key. has_sig=0 for a capsule built
* before this feature existed or otherwise unsigned -- a real, distinct
* state, not "signature is all-zero bytes" (which sig[64] full of 0x00
* would otherwise look ambiguous with). Indexed 1:1 with
* capsule_descriptors[], same convention as CapsuleNameEntry.
*===========================================================================*/
typedef struct {
uint8_t sig[64]; /* raw Ed25519 R||S, see ed25519_sign()/ed25519_verify() */
uint8_t has_sig; /* 0 = no signature present, 1 = sig[] is real */
uint8_t _pad[7];
} CapsuleSigEntry;
/*===========================================================================
* CapsuleDirHeader - Directory Header
*===========================================================================*/
typedef struct {
uint64_t magic; /* 'CAPD' | ver | reserved */
uint64_t arena_base; /* phys or virt base of payload arena */
uint64_t arena_size; /* bytes */
uint32_t desc_count; /* current number of descriptors */
uint32_t desc_capacity; /* max (fixed at compile time for Phase A) */
uint32_t name_count; /* == desc_count, kept separate for validation */
uint32_t reserved; /* padding */
uint64_t dir_hash; /* hash of descriptor table (for parity) */
} CapsuleDirHeader;
/*===========================================================================
* Validation
*===========================================================================*/
typedef enum {
CAPSULE_VALID = 0,
CAPSULE_ERR_BAD_MAGIC,
CAPSULE_ERR_BAD_VERSION,
CAPSULE_ERR_BAD_HASH_ALG,
CAPSULE_ERR_BOUNDS,
CAPSULE_ERR_MODE_INVALID,
CAPSULE_ERR_REVOKED_ACTIVE,
CAPSULE_ERR_HASH_MISMATCH,
CAPSULE_ERR_NULL_PTR,
} CapsuleValidateResult;
/**
* capsule_validate - Validate a capsule descriptor
*
* @param desc Capsule descriptor to validate
* @param arena_base Base address of payload arena
* @param arena_size Size of payload arena in bytes
* @param verify_hash If true, recompute and compare content hash
* @return CAPSULE_VALID on success, error code otherwise
*/
CapsuleValidateResult capsule_validate(
const CapsuleDesc *desc,
const uint8_t *arena_base,
uint64_t arena_size,
int verify_hash
);
/**
* capsule_validate_result_str - Get string for validation result
*/
const char *capsule_validate_result_str(CapsuleValidateResult result);
/*===========================================================================
* Lookup
*===========================================================================*/
/**
* capsule_find_by_id - Find capsule by content hash ID
*
* @param dir Directory header
* @param descs Descriptor array
* @param id Capsule ID (content hash) to find
* @return Pointer to descriptor, or NULL if not found
*/
const CapsuleDesc *capsule_find_by_id(
const CapsuleDirHeader *dir,
const CapsuleDesc *descs,
uint64_t id
);
/**
* capsule_find_by_name - Find capsule by colon-separated name
*
* @param dir Directory header
* @param descs Descriptor array
* @param names Name entry array (parallel to descs)
* @param name Colon-separated capsule name, e.g. "core:init.4th"
* @return Pointer to descriptor, or NULL if not found
*/
const CapsuleDesc *capsule_find_by_name(
const CapsuleDirHeader *dir,
const CapsuleDesc *descs,
const CapsuleNameEntry *names,
const char *name
);
/**
* capsule_get_payload - Get pointer to capsule payload bytes
*
* @param desc Capsule descriptor
* @param arena_base Base address of payload arena
* @return Pointer to payload bytes, or NULL on error
*/
const uint8_t *capsule_get_payload(
const CapsuleDesc *desc,
const uint8_t *arena_base
);
/**
* capsule_find_mama_init - Find the Mama init capsule
*
* Searches the descriptor array for the capsule with CAPSULE_FLAG_MAMA_INIT.
* There must be exactly one such capsule.
*
* @param dir Directory header
* @param descs Descriptor array
* @return Pointer to Mama's init descriptor, or NULL if not found
*/
const CapsuleDesc *capsule_find_mama_init(
const CapsuleDirHeader *dir,
const CapsuleDesc *descs
);
#ifdef __cplusplus
}
#endif
#endif /* STARKERNEL_CAPSULE_H */