Source tree reorganization: - Move StarForth v3 engine to v3/ (src/, include/, Makefile) - Move kernel to kernel/ (src/, include/, linker/, Makefile) - Create v4/ skeleton for F18-ISA golden model (DECOMPOSITION.md, JUSTIFICATION.md) - Move FABRIC-0..4.md to docs/fabric/ - Move ONTOLOGY.md and ROADMAP.md to docs/ Board infrastructure: - Add boards/ser5/, boards/raspi/, boards/milkv/, boards/zynq7020/ - Each board has board.mk (ISA, CPU flags, boot recipe) and README.md - Root Makefile becomes thin dispatcher: boot_image, all, clean, docs take TARGET - make boot_image TARGET=SER5|RASPI|MILKV builds one GPT/MBR image per board - ZYNQ7020 target exists but stops with clear error (ARMv7 port not built yet) - scripts/mkdiskimage.sh builds disk images for all boards Docs pipeline: - docs/book/ with LaTeX master (main.tex) and Makefile - pandoc converts Markdown to LaTeX at build time - Two Lua filters: table-widths.lua (wide tables wrap), code-breaks.lua (inline code breaks) - make docs builds single PDF (754 pages, 0 missing characters) - make docs TARGET=<board> adds board appendix - build/docs/<book|board>/meta.tex stamps git commit into PDF Bug fixes: - 42 include paths that only worked by accident now use correct relative paths - clang-18 hardcode replaced with configurable CC variable (fixed aarch64 build) - Pi 5: kernel_2712.img linked at 0x80000, .bss zeroed, memory reserved - Doxyfile, .clang-tidy, README.md, Kconfig paths updated Verified: - Hosted v3 build passes 1012 tests, 0 failures - SER5 image boots in QEMU (OVMF), POST passes, K exact (65536 = Q48_ONE) - Milk-V image boots in QEMU (OpenSBI + U-Boot + bootefi), POST passes - make clean TARGET=<board> removes only that board and its ISA objects - make all builds all boards, hosted v3, and docs in one run Co-authored-by: Junie <junie@jetbrains.com>
154 lines
5.6 KiB
C
154 lines
5.6 KiB
C
/*
|
||
StarForth — Steady-State Virtual Machine Runtime
|
||
|
||
Copyright (c) 2023–2025 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_loader.h - Block Capsule Loader and Executor (M7.1)
|
||
*
|
||
* Parses a capsule payload for "Block <num>" headers and writes each
|
||
* block's content into the correct ramdrive slot, then executes the
|
||
* entry block and zeros the ramdrive slots afterward.
|
||
*
|
||
* Format:
|
||
* Block <decimal>\n
|
||
* <content: up to 1024 bytes of FORTH source>
|
||
* Block <decimal>\n
|
||
* ...
|
||
*
|
||
* Blocks may appear in any order; block numbers are arbitrary.
|
||
* Content exceeding 1024 bytes is truncated with a warning.
|
||
*/
|
||
|
||
#ifndef STARKERNEL_CAPSULE_LOADER_H
|
||
#define STARKERNEL_CAPSULE_LOADER_H
|
||
|
||
#include <stdint.h>
|
||
#include "starkernel/capsule.h"
|
||
#include "starkernel/capsule_run.h"
|
||
|
||
#ifdef __cplusplus
|
||
extern "C" {
|
||
#endif
|
||
|
||
/**
|
||
* capsule_load_blocks - Parse a capsule payload and write blocks to the ramdrive
|
||
*
|
||
* For each "Block <num>" header found in the payload:
|
||
* 1. Zero the 1024-byte ramdrive slot for block <num>
|
||
* 2. Copy content bytes into the slot (excess beyond 1024 silently dropped)
|
||
* 3. Mark the slot dirty via blk_update()
|
||
*
|
||
* Content between headers may be text or binary.
|
||
* Anything before the first "Block <num>" header is ignored.
|
||
*
|
||
* @param payload Raw capsule payload bytes (not null-terminated)
|
||
* @param length Payload length in bytes
|
||
* @param out_entry_block If non-NULL, receives the first block number found
|
||
* (the execution entry point); set to 0 if no blocks found
|
||
* @return Number of blocks written, or -1 on invalid input
|
||
*/
|
||
int capsule_load_blocks(const uint8_t *payload, uint64_t length,
|
||
uint32_t *out_entry_block);
|
||
|
||
/**
|
||
* capsule_clear_blocks - Zero all ramdrive slots referenced in a capsule payload
|
||
*
|
||
* Re-parses the payload for "Block <num>" headers and zeros each
|
||
* corresponding 1024-byte ramdrive slot. NOT called by capsule_exec_init()
|
||
* (fixed 2026-09-10 -- see its own doc comment): callers that specifically
|
||
* want a capsule's block range freed for reuse (e.g. kernel_main.c, right
|
||
* after Mama's own init.4th birth, to free that range for interactive
|
||
* block-editor use) call this themselves, explicitly, after exec returns.
|
||
*
|
||
* @param payload Raw capsule payload bytes
|
||
* @param length Payload length in bytes
|
||
*/
|
||
void capsule_clear_blocks(const uint8_t *payload, uint64_t length);
|
||
|
||
/**
|
||
* capsule_exec_payload - Parse, populate block device, and execute a payload
|
||
*
|
||
* For each "Block <num>" section: write content to block device (warn+truncate
|
||
* if > 1KB), then execute line-by-line via vm_interpret. No LOAD is injected.
|
||
*
|
||
* @param vm_opaque VM to execute on
|
||
* @param payload Raw payload bytes
|
||
* @param length Payload length in bytes
|
||
* @return 0 on success, -1 on execution error
|
||
*/
|
||
int capsule_exec_payload(void *vm_opaque, const uint8_t *payload, uint64_t length);
|
||
|
||
/**
|
||
* capsule_exec_init - Load and execute an init capsule
|
||
*
|
||
* Full init sequence:
|
||
* 1. Locate capsule by colon-separated name in the capsule directory
|
||
* 2. Validate content hash
|
||
* 3. capsule_exec_payload: populate block device + execute content
|
||
*
|
||
* Block content is NOT cleared afterward (fixed 2026-09-10): it stays
|
||
* resident in ramdrive storage so a subsequent Standard BLOCK/LOAD on the
|
||
* same block number reads back what EXEC just wrote, matching FORTH-79
|
||
* block-persistence semantics. Callers that specifically want the old
|
||
* "free this capsule's block range" behavior (e.g. kernel_main.c freeing
|
||
* init.4th's range for later interactive block-editor use) call
|
||
* capsule_clear_blocks() themselves, explicitly, after this returns.
|
||
*
|
||
* @param vm VM to execute on
|
||
* @param capsule_name Colon-separated capsule name, e.g. "init.4th"
|
||
* @param dir Capsule directory header
|
||
* @param descs Capsule descriptor array
|
||
* @param names Capsule name entry array (parallel to descs)
|
||
* @param arena Capsule payload arena
|
||
* @return CAPSULE_RUN_OK on success, error code otherwise
|
||
*/
|
||
CapsuleRunResult capsule_exec_init(
|
||
void *vm,
|
||
const char *capsule_name,
|
||
const CapsuleDirHeader *dir,
|
||
const CapsuleDesc *descs,
|
||
const CapsuleNameEntry *names,
|
||
const uint8_t *arena
|
||
);
|
||
|
||
#ifdef __STARKERNEL__
|
||
/**
|
||
* capsule_blk_init - Initialize block subsystem and attach the kernel ramdrive.
|
||
*
|
||
* Establishes the unified block address space:
|
||
* LBN 0..2047: fast RAM (ram_buf)
|
||
* LBN 2048..2048+1023: ramdrive (krd_buf, volatile, 1024 blocks)
|
||
*
|
||
* @param vm Opaque VM pointer (mama VM)
|
||
* @param ram_buf Buffer for fast RAM blocks (must be >= BLK_RAM_BLOCKS * 1024 bytes)
|
||
* @param ram_size Size of ram_buf in bytes
|
||
* @param krd_buf Pre-zeroed buffer for ramdrive (must be >= 1024 * 1024 bytes)
|
||
* @return 0 on success, non-zero on failure
|
||
*/
|
||
int capsule_blk_init(void *vm, uint8_t *ram_buf, size_t ram_size, uint8_t *krd_buf);
|
||
#endif /* __STARKERNEL__ */
|
||
|
||
#ifdef __cplusplus
|
||
}
|
||
#endif
|
||
|
||
#endif /* STARKERNEL_CAPSULE_LOADER_H */
|