wip(kernel): Artemis grows to fill the stick at its first boot -- metadata only, capped at 256 GiB (#92, Task 2) [skip ci]
Not yet accepted (plan 2026-10-29-stick-5, Task 2, step 3). - gpt.c: the writer, gpt_grow_last() -- the backup entry array and header to the disk's end, the last partition to the last usable sector (whole MiB, capped), both headers' CRCs, the backup before the primary, the protective MBR's size; gpt_alternate_lba(). - sk_v4_grow.c: the volume grown to its partition -- its fence (the Artemis signature, Zuse's genesis marker) moved to the new top, the header last; the partition grown no further than the BAM tracks (the block subsystem places the fence by the device's size, so a volume must fill it). - sk_v4_identity.c: a stick of 8 GB or more whose GPT ends short of the disk is grown before its partitions are opened; "Artemis: grown to fill the stick" / "under 8 GB -- not grown" / "past 256 GiB ... left unused". - block_subsystem: blk_volume_compute_totals() (compute_totals_from_B, public) and blk_subsys_set_format_bam_for(); v3's behaviour unchanged. - mkartemis --bam-for, mkdiskimage.sh --bam-for, kernel/Makefile STICK_GROW_MIN_BYTES / STICK_ARTEMIS_CAP_GIB: the stick's and data stick's Artemis BAM sized for 256 GiB (6144 devblocks). STICK.md 5a: 256 GiB (R1). After: stick_grow PASS (16 GiB: 12129370 user blocks, 8 s POST to prompt; second boot not grown, recognised; sfdisk --verify: no errors), stick_small PASS, check_images.sh PASS. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01GE3SDvQn5EoxdGufk84zz2
This commit is contained in:
@@ -122,9 +122,13 @@ gains the partitions below). Three partitions:
|
||||
- **The minimum stick: 8 GB.** Sticks on the shelf are 16–64 GB; 8 GB is the floor.
|
||||
- **The identity partition stays 500 MiB.** About half a million 1 KiB blocks for Zuse's keys and
|
||||
her own pool.
|
||||
- **Artemis grows to fill the stick at its first boot (§5a),** up to **2 TiB** for the partition
|
||||
(the block layer numbers 1 KiB blocks with 32 bits: 4 TiB is its hard limit; 2 TiB keeps a margin
|
||||
and is past any thumb drive). Space past 2 TiB is left unused, and the boot says so.
|
||||
- **Artemis grows to fill the stick at its first boot (§5a),** up to **256 GiB** for the partition
|
||||
(**amended 2026-10-29**, Captain Bob: "256 GiB is ruled" -- plan
|
||||
`plans/2026-10-29-stick-5-proxy-zuse-and-real-zuse.md`, R1. This said 2 TiB: the block layer
|
||||
numbers 1 KiB blocks with 32 bits, so 4 TiB is its hard limit, but the block subsystem keeps two
|
||||
bytes of kernel heap per block and the heap is 2 GiB, so a 2 TiB Artemis could not attach; 256 GiB
|
||||
takes about 384 MiB. The stick's Artemis is formatted with a BAM sized for 256 GiB, so growth
|
||||
writes metadata only.) Space past 256 GiB is left unused, and the boot says so.
|
||||
- **A stick under 8 GB** is not grown: it runs at the 2 GiB it was written with, and the boot says
|
||||
so.
|
||||
- **The Artemis partition is formatted when the image is built (my call),** not on first boot:
|
||||
@@ -168,7 +172,7 @@ Before genesis, on a stick whose GPT ends where the 2 GiB image ended and whose
|
||||
first boot of a freshly written stick), the kernel grows Artemis:
|
||||
|
||||
- It moves the backup GPT header and entry array to the disk's end, extends the Artemis partition's
|
||||
last LBA to the end of the usable space (capped at 2 TiB of partition), and rewrites both headers
|
||||
last LBA to the end of the usable space (capped at 256 GiB of partition, amended -- §4), and rewrites both headers
|
||||
with their CRCs (the GPT writer; `INSTALL` reuses it).
|
||||
- It grows Artemis's volume to the partition: its `STFR` header's size, its free map for the new
|
||||
blocks, and its metadata fence (with the genesis marker's slot) moved to the new top, as the block
|
||||
|
||||
+16
-5
@@ -270,6 +270,14 @@ STICK_IMAGE_MIB := 2048
|
||||
STICK_ESP_MIB := 64
|
||||
STICK_IDENT_MIB := 500
|
||||
DATASTICK_MIB := 1536
|
||||
# Growth (STICK.md 5a; plan 2026-10-29-stick-5, R1: "256 GiB is ruled"): a stick of at least
|
||||
# STICK_GROW_MIN_BYTES grows its Artemis partition to fill it, at most STICK_ARTEMIS_CAP_GIB; the
|
||||
# stick's and data stick's Artemis are formatted with a BAM sized for that cap, so growth writes
|
||||
# metadata only. The kernel is built with both (-D, below).
|
||||
STICK_GROW_MIN_BYTES := 8000000000
|
||||
STICK_ARTEMIS_CAP_GIB := 256
|
||||
STICK_ARTEMIS_CAP_SECTORS := 536870912
|
||||
# (256 GiB in 512-byte sectors: keep the two in step)
|
||||
DATASTICK_IMG = $(BUILD_DIR)/datastick.img
|
||||
# STICK_PAIR -- a minted pair (e.g. disk/zuse-scratch) whose identity and Artemis images become
|
||||
# the PC stick's partitions, byte for byte, instead of a blank identity and a fresh Artemis.
|
||||
@@ -706,7 +714,8 @@ endif
|
||||
V4_DEFAULT ?= 1
|
||||
ifeq ($(STARFORTH_V4),1)
|
||||
V4_DEFS := -DSTARFORTH_V4=1 -DSK_V4_DEFAULT=$(V4_DEFAULT) -Iv4/include \
|
||||
-DV4_CELL_BITS=64 -DV4_NODE_WORDS=16384 -DV4_DATA_RING=30 -DV4_RET_RING=31 -DV4_ROM_WORDS=4096
|
||||
-DV4_CELL_BITS=64 -DV4_NODE_WORDS=16384 -DV4_DATA_RING=30 -DV4_RET_RING=31 -DV4_ROM_WORDS=4096 \
|
||||
-DSTICK_GROW_MIN_BYTES=$(STICK_GROW_MIN_BYTES)ULL -DSTICK_ARTEMIS_CAP_GIB=$(STICK_ARTEMIS_CAP_GIB)ULL
|
||||
KERNEL_CFLAGS += $(V4_DEFS)
|
||||
LOADER_CFLAGS += $(V4_DEFS)
|
||||
|
||||
@@ -714,8 +723,8 @@ V4_ENGINE_SRCS := $(addprefix v4/src/,node.c exec.c stack.c iword.c heat.c guard
|
||||
V4_ROM_C := $(BUILD_DIR)/v4_rom_64.c
|
||||
V4_MAP_C := $(BUILD_DIR)/v4_map_64.c
|
||||
|
||||
LOADER_EXTRA_SRCS += $(KERNEL_SRC)/v4/sk_v4.c $(KERNEL_SRC)/v4/sk_v4_identity.c $(KERNEL_SRC)/v4/sk_v4_marker.c
|
||||
KERNEL_EXTRA_SRCS += $(KERNEL_SRC)/v4/sk_v4.c $(KERNEL_SRC)/v4/sk_v4_identity.c $(KERNEL_SRC)/v4/sk_v4_marker.c
|
||||
LOADER_EXTRA_SRCS += $(KERNEL_SRC)/v4/sk_v4.c $(KERNEL_SRC)/v4/sk_v4_identity.c $(KERNEL_SRC)/v4/sk_v4_marker.c $(KERNEL_SRC)/v4/sk_v4_grow.c
|
||||
KERNEL_EXTRA_SRCS += $(KERNEL_SRC)/v4/sk_v4.c $(KERNEL_SRC)/v4/sk_v4_identity.c $(KERNEL_SRC)/v4/sk_v4_marker.c $(KERNEL_SRC)/v4/sk_v4_grow.c
|
||||
# v4/system/boot.c is the boot the hosted v4 system runs too: the ROM
|
||||
# assembles the system, then the capsules from this kernel's own capsule
|
||||
# directory, then the prompt.
|
||||
@@ -816,7 +825,8 @@ $(MKARTEMIS_BIN): $(MKARTEMIS_SRC) $(wildcard v3/include/*.h) kernel/include/sta
|
||||
.PHONY: datastick
|
||||
datastick: $(MKARTEMIS_BIN)
|
||||
@bash scripts/mkdiskimage.sh --out $(DATASTICK_IMG) --table gpt --size-mib $(DATASTICK_MIB) \
|
||||
--label DATASTICK --starship $(STICK_IDENT_MIB) --mkartemis $(MKARTEMIS_BIN) --esp-mib 0
|
||||
--label DATASTICK --starship $(STICK_IDENT_MIB) --mkartemis $(MKARTEMIS_BIN) --esp-mib 0 \
|
||||
--bam-for $(STICK_ARTEMIS_CAP_SECTORS)
|
||||
|
||||
# zusestick -- Zuse's minted pair as a stick, fresh every time it is made (the ZUSEDISK default).
|
||||
.PHONY: zusestick
|
||||
@@ -1493,7 +1503,8 @@ boot_image: all $(if $(BOARD_STICK),$(MKARTEMIS_BIN))
|
||||
@bash scripts/mkdiskimage.sh --out $(BOARD_OUT)/$(BOARD_IMAGE) --table gpt \
|
||||
$(if $(BOARD_STICK),$(if $(STICK_PAIR),--esp-mib $(STICK_ESP_MIB) --starship-from \
|
||||
$(STICK_PAIR)/zuse-thumb-ident.img $(STICK_PAIR)/artemis.img,--size-mib $(STICK_IMAGE_MIB) \
|
||||
--starship $(STICK_IDENT_MIB) --mkartemis $(MKARTEMIS_BIN) --esp-mib $(STICK_ESP_MIB)), \
|
||||
--starship $(STICK_IDENT_MIB) --mkartemis $(MKARTEMIS_BIN) --esp-mib $(STICK_ESP_MIB) \
|
||||
--bam-for $(STICK_ARTEMIS_CAP_SECTORS)), \
|
||||
--size-mib $(BOOT_IMAGE_SIZE_MIB)) \
|
||||
--label LITHOS \
|
||||
$(LOADER_EFI):/EFI/BOOT/$(EFI_BOOTNAME) \
|
||||
|
||||
@@ -33,6 +33,22 @@ int gpt_read(blkio_dev_t *disk, gpt_part_t *parts, unsigned max, unsigned *count
|
||||
* returned GPT_OK: which disk it was, so a stick can be told from another. */
|
||||
void gpt_disk_guid(uint8_t guid[16]);
|
||||
|
||||
/* The backup header's LBA (header bytes 32..39) of the last gpt_read that
|
||||
* returned GPT_OK: a disk whose backup header is not its last sector is larger
|
||||
* than the table written to it. */
|
||||
uint64_t gpt_alternate_lba(void);
|
||||
|
||||
/* Grow the partition of `type` -- which must be the disk's last -- to the end
|
||||
* of `disk` (plan 2026-10-29-stick-5, Task 2): the backup entry array and
|
||||
* header moved to the disk's last sectors, the partition's last LBA to the
|
||||
* last usable sector before them (on a whole MiB, at most `max_part_sectors`
|
||||
* long), both headers rewritten with their CRCs -- the backup first, so a
|
||||
* write torn between them leaves the old primary valid -- and the protective
|
||||
* MBR's size. GPT_OK with `*new_last_lba` the partition's last LBA (unchanged,
|
||||
* and nothing written, when the backup header is already the disk's last
|
||||
* sector); GPT_BAD or GPT_EIO otherwise. */
|
||||
int gpt_grow_last(blkio_dev_t *disk, const uint8_t type[16], uint64_t max_part_sectors, uint64_t *new_last_lba);
|
||||
|
||||
/* The index of the first partition of `type`, or -1. */
|
||||
int gpt_find(const gpt_part_t *parts, unsigned count, const uint8_t type[16]);
|
||||
|
||||
|
||||
@@ -0,0 +1,23 @@
|
||||
/* sk_v4_grow.h -- Artemis grows to fill the stick at its first boot
|
||||
* (docs/v4.0.0/STICK.md 5a; plan 2026-10-29-stick-5, Task 2).
|
||||
*
|
||||
* Built only with STARFORTH_V4=1 (Kconfig.kernel).
|
||||
*/
|
||||
#ifndef STARKERNEL_V4_SK_V4_GROW_H
|
||||
#define STARKERNEL_V4_SK_V4_GROW_H
|
||||
|
||||
#include <stdint.h>
|
||||
#include "blkio.h"
|
||||
|
||||
/* How far the Artemis partition `art` may grow, in 512-byte sectors: no
|
||||
* further than `cap_sectors`, nor than its volume's BAM can track. 0 when
|
||||
* `art` holds no STFR v2 volume. Reads only. */
|
||||
uint64_t sk_v4_grow_cap_sectors(blkio_dev_t *art, uint64_t cap_sectors);
|
||||
|
||||
/* Grow the volume on `art` to fill its partition: its fence (the Artemis
|
||||
* signature, Zuse's genesis marker) moved to the new top, then its header.
|
||||
* Metadata only. 1 when grown, 0 when it already fills the partition, -1 on
|
||||
* an error -- the old header then still names the old volume, whole. */
|
||||
int sk_v4_grow_artemis(blkio_dev_t *art);
|
||||
|
||||
#endif /* STARKERNEL_V4_SK_V4_GROW_H */
|
||||
+125
-2
@@ -7,8 +7,13 @@
|
||||
* a block device of a StarshipOS partition: its block 0 is the partition's
|
||||
* first 1 KiB, and nothing past its end can be reached through it. The
|
||||
* identity and Artemis formats inside a partition are exactly those of a raw
|
||||
* drive today. Reads only. 512-byte logical sectors only (the stick and its
|
||||
* data stick); docs/v4.0.0/plans/2026-10-26-stick-2-gpt-reader.md.
|
||||
* drive today. 512-byte logical sectors only (the stick and its data stick);
|
||||
* docs/v4.0.0/plans/2026-10-26-stick-2-gpt-reader.md.
|
||||
*
|
||||
* The writer (plan 2026-10-29-stick-5, Task 2; STICK.md 5a): the stick's last
|
||||
* partition grown to the end of a disk larger than the image written to it --
|
||||
* the backup header and entry array moved to the disk's end, both headers
|
||||
* rewritten with their CRCs, the backup before the primary.
|
||||
*/
|
||||
#include "starkernel/gpt.h"
|
||||
#include "console.h"
|
||||
@@ -51,6 +56,7 @@ static uint64_t le64(const uint8_t *p) { return (uint64_t)le32(p) | (uint64_t)le
|
||||
static uint8_t g_gpt_hdr_block[BLKIO_FORTH_BLOCK_SIZE];
|
||||
static uint8_t g_gpt_entries[GPT_ENTRIES_MAX];
|
||||
static uint8_t g_gpt_disk_guid[16]; /* the DiskGUID of the last gpt_read that gave GPT_OK */
|
||||
static uint64_t g_gpt_alternate_lba; /* and its backup header's LBA */
|
||||
|
||||
int gpt_read(blkio_dev_t *disk, gpt_part_t *parts, unsigned max, unsigned *count)
|
||||
{
|
||||
@@ -125,6 +131,7 @@ int gpt_read(blkio_dev_t *disk, gpt_part_t *parts, unsigned max, unsigned *count
|
||||
}
|
||||
*count = n;
|
||||
memcpy(g_gpt_disk_guid, h + 56, 16);
|
||||
g_gpt_alternate_lba = le64(h + 32);
|
||||
return GPT_OK;
|
||||
}
|
||||
|
||||
@@ -140,6 +147,122 @@ int gpt_find(const gpt_part_t *parts, unsigned count, const uint8_t type[16])
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* ---- the writer: growing the last partition to the disk's end ---------- */
|
||||
|
||||
static void put_le32(uint8_t *p, uint32_t v) { p[0] = (uint8_t)v; p[1] = (uint8_t)(v >> 8); p[2] = (uint8_t)(v >> 16); p[3] = (uint8_t)(v >> 24); }
|
||||
static void put_le64(uint8_t *p, uint64_t v) { put_le32(p, (uint32_t)v); put_le32(p + 4, (uint32_t)(v >> 32)); }
|
||||
|
||||
static uint8_t g_gpt_rmw[BLKIO_FORTH_BLOCK_SIZE];
|
||||
|
||||
/* Write `n` 512-byte sectors from `src` at sector `lba`: each through a
|
||||
* read-modify-write of the 1 KiB block that holds it, so a sector at an odd
|
||||
* LBA (the backup header, the backup entry array) is written alone. */
|
||||
static int put_sectors(blkio_dev_t *disk, uint64_t lba, const uint8_t *src, uint32_t n)
|
||||
{
|
||||
uint32_t i;
|
||||
for (i = 0; i < n; i++) {
|
||||
uint64_t s = lba + i;
|
||||
uint32_t blk = (uint32_t)(s / 2u);
|
||||
if (blkio_read(disk, blk, g_gpt_rmw) != BLKIO_OK) return -1;
|
||||
memcpy(g_gpt_rmw + (s % 2u) * GPT_SECTOR, src + (size_t)i * GPT_SECTOR, GPT_SECTOR);
|
||||
if (blkio_write(disk, blk, g_gpt_rmw) != BLKIO_OK) return -1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
uint64_t gpt_alternate_lba(void)
|
||||
{
|
||||
return g_gpt_alternate_lba;
|
||||
}
|
||||
|
||||
int gpt_grow_last(blkio_dev_t *disk, const uint8_t type[16], uint64_t max_part_sectors, uint64_t *new_last_lba)
|
||||
{
|
||||
static gpt_part_t parts[16];
|
||||
static uint8_t hdr[GPT_SECTOR], bak[GPT_SECTOR];
|
||||
const uint8_t *h = g_gpt_hdr_block + GPT_SECTOR;
|
||||
uint8_t *mbr = g_gpt_hdr_block, *e = (uint8_t *)0;
|
||||
uint64_t disk_sectors, alt, ent_lba, new_alt, new_ent, new_last_usable, first, last, want, top = 0;
|
||||
uint32_t nent, esize, ent_sectors, i;
|
||||
unsigned count;
|
||||
size_t ebytes;
|
||||
int rc;
|
||||
|
||||
rc = gpt_read(disk, parts, 16u, &count);
|
||||
if (rc != GPT_OK) return rc == GPT_NONE ? GPT_BAD : rc;
|
||||
nent = le32(h + 80);
|
||||
esize = le32(h + 84);
|
||||
ebytes = (size_t)nent * esize;
|
||||
ent_sectors = (uint32_t)((ebytes + GPT_SECTOR - 1u) / GPT_SECTOR);
|
||||
ent_lba = le64(h + 72);
|
||||
alt = le64(h + 32);
|
||||
disk_sectors = (uint64_t)disk->total_blocks * (BLKIO_FORTH_BLOCK_SIZE / GPT_SECTOR);
|
||||
|
||||
/* the partition of `type`, which must be the last on the disk */
|
||||
for (i = 0; i < nent; i++) {
|
||||
uint8_t *x = g_gpt_entries + (size_t)i * esize;
|
||||
static const uint8_t zero[16];
|
||||
if (memcmp(x, zero, 16) == 0) continue;
|
||||
if (le64(x + 40) > top) top = le64(x + 40);
|
||||
if (!e && memcmp(x, type, 16) == 0) e = x;
|
||||
}
|
||||
if (!e) return GPT_BAD;
|
||||
first = le64(e + 32);
|
||||
last = le64(e + 40);
|
||||
*new_last_lba = last;
|
||||
if (alt == disk_sectors - 1u) return GPT_OK; /* already ends at the disk's end */
|
||||
if (alt > disk_sectors - 1u || last != top) return GPT_BAD;
|
||||
|
||||
/* the backup entry array and header at the disk's end; the partition to
|
||||
* the last usable sector before them, on whole MiB, at most max sectors */
|
||||
new_alt = disk_sectors - 1u;
|
||||
new_ent = new_alt - ent_sectors;
|
||||
new_last_usable = new_ent - 1u;
|
||||
if (new_last_usable < last) return GPT_BAD;
|
||||
want = new_last_usable - first + 1u;
|
||||
if (want > max_part_sectors) want = max_part_sectors;
|
||||
want -= want % 2048u;
|
||||
if (first + want - 1u > last) {
|
||||
last = first + want - 1u;
|
||||
put_le64(e + 40, last);
|
||||
}
|
||||
|
||||
/* the primary header, then the backup: each with its own LBAs and CRC */
|
||||
memcpy(hdr, h, GPT_SECTOR);
|
||||
put_le64(hdr + 32, new_alt);
|
||||
put_le64(hdr + 48, new_last_usable);
|
||||
put_le32(hdr + 88, gpt_crc32(g_gpt_entries, ebytes));
|
||||
memcpy(bak, hdr, GPT_SECTOR);
|
||||
put_le64(bak + 24, new_alt);
|
||||
put_le64(bak + 32, 1u);
|
||||
put_le64(bak + 72, new_ent);
|
||||
put_le32(hdr + 16, 0u);
|
||||
put_le32(hdr + 16, gpt_crc32(hdr, le32(hdr + 12)));
|
||||
put_le32(bak + 16, 0u);
|
||||
put_le32(bak + 16, gpt_crc32(bak, le32(bak + 12)));
|
||||
|
||||
/* the backup before the primary: a write torn between them leaves the old
|
||||
* primary, which still checks out, and the next boot grows again */
|
||||
if (put_sectors(disk, new_ent, g_gpt_entries, ent_sectors) != 0 ||
|
||||
put_sectors(disk, new_alt, bak, 1u) != 0 || disk->vt->flush(disk) != BLKIO_OK)
|
||||
return GPT_EIO;
|
||||
if (put_sectors(disk, ent_lba, g_gpt_entries, ent_sectors) != 0 ||
|
||||
put_sectors(disk, 1u, hdr, 1u) != 0 || disk->vt->flush(disk) != BLKIO_OK)
|
||||
return GPT_EIO;
|
||||
|
||||
/* the protective MBR's partition covers the disk (as many sectors as fit) */
|
||||
for (i = 0; i < 4u; i++) {
|
||||
uint8_t *p = mbr + 446u + 16u * i;
|
||||
if (p[4] == 0xEEu) {
|
||||
put_le32(p + 12, disk_sectors - 1u > 0xFFFFFFFFu ? 0xFFFFFFFFu : (uint32_t)(disk_sectors - 1u));
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (put_sectors(disk, 0u, mbr, 1u) != 0 || disk->vt->flush(disk) != BLKIO_OK) return GPT_EIO;
|
||||
|
||||
*new_last_lba = last;
|
||||
return GPT_OK;
|
||||
}
|
||||
|
||||
/* ---- a partition as a blkio device ------------------------------------- */
|
||||
|
||||
static int part_open(blkio_dev_t *dev, const blkio_params_t *p)
|
||||
|
||||
@@ -0,0 +1,94 @@
|
||||
/* sk_v4_grow.c -- Artemis grows to fill the stick at its first boot
|
||||
* (docs/v4.0.0/STICK.md 5a; plan 2026-10-29-stick-5, Task 2).
|
||||
*
|
||||
* Metadata only: the volume's header, and its fence -- the top-of-volume
|
||||
* system metadata, which holds the Artemis signature and Zuse's genesis
|
||||
* marker (artemis_sig.c, blk_meta_zone_read/write) -- moved to the new top.
|
||||
* The volume's data blocks are never written, and its BAM is not resized: the
|
||||
* image is built with a BAM sized for the cap (mkartemis --bam-for), so the
|
||||
* new blocks are tracked already and read as free.
|
||||
*
|
||||
* The block subsystem places a volume's fence by its device's size, not by
|
||||
* its header (blk_format_or_load_disk), so a volume always fills its
|
||||
* partition: the partition is grown no further than the BAM can track
|
||||
* (sk_v4_grow_cap_sectors), then the volume to the partition.
|
||||
*/
|
||||
#include "starkernel/v4/sk_v4_grow.h"
|
||||
#include "block_subsystem.h"
|
||||
#include <string.h>
|
||||
|
||||
static union {
|
||||
uint8_t bytes[4096];
|
||||
blk_volume_meta_t meta;
|
||||
} g_hdr;
|
||||
static uint8_t g_move[4096];
|
||||
|
||||
static int dev_rw4k(blkio_dev_t *dev, uint64_t devblock, uint8_t *buf, int write)
|
||||
{
|
||||
uint32_t base = (uint32_t)devblock * 4u, k;
|
||||
for (k = 0; k < 4u; k++) {
|
||||
int rc = write ? blkio_write(dev, base + k, buf + k * 1024u)
|
||||
: blkio_read(dev, base + k, buf + k * 1024u);
|
||||
if (rc != BLKIO_OK) return -1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int read_header(blkio_dev_t *art)
|
||||
{
|
||||
if (dev_rw4k(art, 0u, g_hdr.bytes, 0) != 0) return -1;
|
||||
if (g_hdr.meta.magic != 0x53544652u || g_hdr.meta.version != 2u ||
|
||||
g_hdr.meta.bam_devblocks == 0u || g_hdr.meta.meta_fence_blocks == 0u)
|
||||
return -1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* The most devblocks a volume with this header's BAM can be: no more Forth
|
||||
* blocks in its payload than the BAM tracks (compute_totals_from_B). */
|
||||
static uint64_t bam_cover_devblocks(const blk_volume_meta_t *m)
|
||||
{
|
||||
uint64_t tracked = 32768ULL * m->bam_devblocks;
|
||||
return tracked / 3u + 1u + m->bam_devblocks + m->reloc_devblocks + m->meta_fence_blocks;
|
||||
}
|
||||
|
||||
uint64_t sk_v4_grow_cap_sectors(blkio_dev_t *art, uint64_t cap_sectors)
|
||||
{
|
||||
uint64_t cover;
|
||||
if (read_header(art) != 0) return 0;
|
||||
cover = bam_cover_devblocks(&g_hdr.meta) * 8u; /* 4 KiB devblocks, in 512-byte sectors */
|
||||
return cover < cap_sectors ? cover : cap_sectors;
|
||||
}
|
||||
|
||||
int sk_v4_grow_artemis(blkio_dev_t *art)
|
||||
{
|
||||
blkio_info_t info;
|
||||
uint64_t old_t, new_t, f, k, old_total;
|
||||
|
||||
if (read_header(art) != 0) return -1;
|
||||
if (blkio_info(art, &info) != BLKIO_OK) return -1;
|
||||
old_t = g_hdr.meta.total_devblocks;
|
||||
new_t = info.total_blocks / 4u;
|
||||
if (new_t <= old_t) return 0; /* not grown: it fills its partition */
|
||||
if (new_t > bam_cover_devblocks(&g_hdr.meta)) return -1;
|
||||
f = g_hdr.meta.meta_fence_blocks;
|
||||
/* the old and new fences never overlap (a partition grows by whole MiB,
|
||||
* 256 devblocks, past a 128-devblock fence), so a copy torn by a power
|
||||
* loss is simply done again from the old top at the next boot */
|
||||
if (f >= old_t || new_t - old_t < f) return -1;
|
||||
|
||||
/* the fence to the new top, devblock by devblock */
|
||||
for (k = 0; k < f; k++) {
|
||||
if (dev_rw4k(art, old_t - 1u - k, g_move, 0) != 0) return -1;
|
||||
if (dev_rw4k(art, new_t - 1u - k, g_move, 1) != 0) return -1;
|
||||
}
|
||||
if (blkio_flush(art) != BLKIO_OK) return -1;
|
||||
|
||||
/* the header last: until it is written, the old header names the old top */
|
||||
old_total = g_hdr.meta.total_blocks;
|
||||
g_hdr.meta.total_devblocks = new_t;
|
||||
blk_volume_compute_totals(&g_hdr.meta);
|
||||
g_hdr.meta.free_blocks += g_hdr.meta.total_blocks - old_total;
|
||||
if (dev_rw4k(art, 0u, g_hdr.bytes, 1) != 0) return -1;
|
||||
if (blkio_flush(art) != BLKIO_OK) return -1;
|
||||
return 1;
|
||||
}
|
||||
@@ -22,6 +22,12 @@
|
||||
* Zuse exists -- reads her back, then writes the version 2 marker
|
||||
* (sk_v4_marker.c) naming her.
|
||||
*
|
||||
* Growth (plan 2026-10-29-stick-5, Task 2; STICK.md 5a): a stick of at least
|
||||
* 8 GB whose GPT ends short of the disk -- a stick larger than the image
|
||||
* written to it -- has its Artemis partition grown to fill it (capped at
|
||||
* 256 GiB, and at what its BAM tracks: sk_v4_grow.c), then Artemis's volume
|
||||
* grown to the partition, before anything on it is read. Metadata only.
|
||||
*
|
||||
* Not here (the plan's "not in this gate"): WIREBIND identities, EJECT,
|
||||
* ACL-ZUSE-BOOT.
|
||||
*/
|
||||
@@ -39,6 +45,7 @@
|
||||
#include "starkernel/kbd_input.h"
|
||||
#include "starkernel/gpt.h"
|
||||
#include "starkernel/v4/sk_v4_marker.h"
|
||||
#include "starkernel/v4/sk_v4_grow.h"
|
||||
#ifdef ARCH_AMD64
|
||||
#include "starkernel/ioapic.h"
|
||||
#include "starkernel/i8042.h"
|
||||
@@ -149,6 +156,45 @@ static int sk_v4_is_this_stick(unsigned nparts)
|
||||
return !g_stick_in;
|
||||
}
|
||||
|
||||
/* Growth's limits, from kernel/Makefile (-D): the stick at least this big,
|
||||
* Artemis's partition at most this big */
|
||||
#define SK_V4_GROW_MIN_BYTES STICK_GROW_MIN_BYTES
|
||||
#define SK_V4_CAP_SECTORS (STICK_ARTEMIS_CAP_GIB * 2097152ULL)
|
||||
|
||||
/* This system's stick, its GPT just read (g_gpt_parts, *nparts): when the
|
||||
* stick is larger than its GPT (its backup header is not the disk's last
|
||||
* sector) and at least 8 GB, the Artemis partition is grown to fill it, and
|
||||
* the GPT read again. Returns 0, or -1 when the GPT cannot be read again. */
|
||||
static int sk_v4_grow_stick(sk_v4_drive_t *d, unsigned *nparts)
|
||||
{
|
||||
static int said_small;
|
||||
uint64_t disk_sectors = (uint64_t)d->raw.total_blocks * (BLKIO_FORTH_BLOCK_SIZE / 512u);
|
||||
uint64_t cap, new_last, first;
|
||||
int ai = gpt_find(g_gpt_parts, *nparts, gpt_type_starship_artemis);
|
||||
|
||||
if (ai < 0 || gpt_alternate_lba() == disk_sectors - 1u) return 0; /* the GPT fills the stick */
|
||||
if (disk_sectors * 512u < SK_V4_GROW_MIN_BYTES) {
|
||||
if (!said_small) {
|
||||
console_println("Artemis: the stick is under 8 GB -- not grown");
|
||||
said_small = 1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
first = g_gpt_parts[ai].first_lba;
|
||||
if (gpt_part_open(&d->art, &d->art_state, &d->raw, &g_gpt_parts[ai]) != BLKIO_OK) return 0;
|
||||
cap = sk_v4_grow_cap_sectors(&d->art, SK_V4_CAP_SECTORS);
|
||||
if (cap == 0) return 0; /* no Artemis volume: the signature check refuses it */
|
||||
if (gpt_grow_last(&d->raw, gpt_type_starship_artemis, cap, &new_last) != GPT_OK)
|
||||
console_println("GPT: the stick's table could not be grown");
|
||||
else if (new_last - first + 1u >= SK_V4_CAP_SECTORS && first + SK_V4_CAP_SECTORS + 2048u < disk_sectors)
|
||||
console_println("Artemis: past 256 GiB of the stick is left unused");
|
||||
if (gpt_read(&d->raw, g_gpt_parts, SK_V4_GPT_PARTS, nparts) != GPT_OK ||
|
||||
gpt_find(g_gpt_parts, *nparts, gpt_type_starship_identity) < 0 ||
|
||||
gpt_find(g_gpt_parts, *nparts, gpt_type_starship_artemis) < 0)
|
||||
return -1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Zuse's session begins on @p dev: the console is hers, and the screen with
|
||||
* it (docs/v4.0.0/STICK.md 2). @p line says how she was found. */
|
||||
static void sk_v4_login(blkio_dev_t *dev, const uint8_t seed[32], const uint8_t pubkey[32],
|
||||
@@ -241,6 +287,10 @@ static int sk_v4_drive_arrived(sk_v4_drive_t *d)
|
||||
console_println("USB: a drive that is not this system's stick -- not used");
|
||||
return 1;
|
||||
}
|
||||
if (sk_v4_grow_stick(d, &nparts) != 0) {
|
||||
console_println("GPT: the stick's grown table does not read back");
|
||||
return 1;
|
||||
}
|
||||
if (gpt_part_open(&d->art, &d->art_state, &d->raw,
|
||||
&g_gpt_parts[gpt_find(g_gpt_parts, nparts, gpt_type_starship_artemis)]) != BLKIO_OK ||
|
||||
gpt_part_open(&d->part, &d->part_state, &d->raw,
|
||||
@@ -249,6 +299,13 @@ static int sk_v4_drive_arrived(sk_v4_drive_t *d)
|
||||
return 1;
|
||||
}
|
||||
|
||||
/* Artemis's volume fills its partition, grown with it (STICK.md 5a) */
|
||||
{
|
||||
int g = sk_v4_grow_artemis(&d->art);
|
||||
if (g > 0) console_println("Artemis: grown to fill the stick");
|
||||
else if (g < 0) console_println("Artemis: the stick's volume could not be grown");
|
||||
}
|
||||
|
||||
/* Artemis first: formatted and signed at build (STICK.md 4); a
|
||||
* signature that does not check out is not used, nor is the stick */
|
||||
if (artemis_sig_check(&d->art, &asig) != ARTEMIS_SIG_OK) {
|
||||
|
||||
@@ -0,0 +1,165 @@
|
||||
[2J[01;01H[=3h[2J[01;01H[2J[01;01H[=3h[2J[01;01H[2J[01;01H[=3h[2J[01;01HBdsDxe: loading Boot0001 "UEFI QEMU QEMU USB HARDDRIVE 1-0000:00:03.0-1" from PciRoot(0x0)/Pci(0x3,0x0)/USB(0x0,0x0)
|
||||
BdsDxe: starting Boot0001 "UEFI QEMU QEMU USB HARDDRIVE 1-0000:00:03.0-1" from PciRoot(0x0)/Pci(0x3,0x0)/USB(0x0,0x0)
|
||||
[2J[01;01H[=3h[2J[01;01HStarKernel UEFI Loader
|
||||
Loading kernel from ESP...
|
||||
[CKPT 001] Entered efi_main - ConOut live
|
||||
RAW SERIAL UP
|
||||
[CKPT 002] Serial (COM1) initialized
|
||||
Monolithic build - kernel linked directly
|
||||
Collecting boot information...
|
||||
CmdLine: from starforth.cfg
|
||||
CmdLine: parsed OK
|
||||
[CKPT 004] Command line parsed
|
||||
[CKPT 005] Kernel stack allocation decided
|
||||
[CKPT 006] Boot info collected (ACPI table located)
|
||||
GOP: linear framebuffer found
|
||||
[CKPT 007] GOP: linear framebuffer found
|
||||
[CKPT 008] About to enter ExitBootServices retry loop
|
||||
EBS...
|
||||
EBS OK
|
||||
Calling kernel_main (monolithic)...
|
||||
|
||||
|
||||
_____ _ _ __ _
|
||||
/ ____| | | |/ / | |
|
||||
| (___ | |_ __ _ _ __| ' / ___ _ __ _ __ ___| |
|
||||
\___ \| __/ _` | '__| < / _ \ '__| '_ \ / _ \ |
|
||||
____) | || (_| | | | . \ __/ | | | | | __/ |
|
||||
|_____/ \__\__,_|_| |_|\_\___|_| |_| |_|\___|_|
|
||||
|
||||
LithosAnanke v4.0.0-alpha.3 amd64
|
||||
Architecture: amd64
|
||||
Build: Nov 8 2026 11:58:08
|
||||
|
||||
UEFI BootServices: EXITED
|
||||
Console: serial line is a 16550 at port 0x00000000000003f8 (COM1, probed)
|
||||
|
||||
=== StarKernel Boot Information ===
|
||||
Memory map entries: 128
|
||||
Total memory: 1023 MB
|
||||
Usable memory: 965 MB
|
||||
===================================
|
||||
|
||||
PMM initialized.
|
||||
PMM statistics:
|
||||
Total pages: 248623
|
||||
Free pages : 247096
|
||||
Used pages : 1527
|
||||
Total MB : 971
|
||||
Free MB : 965
|
||||
Used MB : 5
|
||||
|
||||
VMM initialized (mapped RAM, CR3 switched)
|
||||
VMM initialized (mapped RAM, CR3 switched)
|
||||
VMM self-test: mapped OK at 0xffff800000000000
|
||||
VMM self-test complete.
|
||||
|
||||
IDT installed.
|
||||
|
||||
APIC: init...
|
||||
APIC: IA32_APIC_BASE MSR=0x00000000fee00900
|
||||
APIC: stale-ISR drain: 0 EOI(s) issued
|
||||
APIC: initialized (xAPIC MMIO, TPR=0, SIVR=0x1FF, EOI-clear)
|
||||
APIC: init done
|
||||
|
||||
I/O APIC: init...
|
||||
I/O APIC: base=0xfec00000, gsi_base=0, overrides=5
|
||||
override: source=00 gsi=2 flags=0x0000
|
||||
override: source=05 gsi=5 flags=0x000d
|
||||
override: source=09 gsi=9 flags=0x000d
|
||||
override: source=0a gsi=10 flags=0x000d
|
||||
override: source=0b gsi=11 flags=0x000d
|
||||
i8042: keyboard ACKed enable-scanning
|
||||
i8042: IRQ1 enabled in controller config byte
|
||||
I/O APIC: keyboard IRQ1 routed (masked)
|
||||
|
||||
Timer: init...
|
||||
Timer: init start
|
||||
Timer: PM_TMR_BLK discovered from FADT at port 1544
|
||||
Timer: VM mode detected (hypervisor present).
|
||||
Timer: HPET calibration disabled (VM-exit MMIO would poison timing).
|
||||
Timer: WARNING: invariant TSC not present under hypervisor.
|
||||
Timer: continuing in RELATIVE mode (no determinism guarantees).
|
||||
Timer: RDTSCP not present; using RDTSC (less serialized).
|
||||
Timer: CPUID frequency unavailable; trying PM Timer...
|
||||
Timer: trust=1 (0=NONE,1=REL,2=ABS), TSC=2048803536 Hz
|
||||
Timer: init done
|
||||
|
||||
Kernel heap initialized.
|
||||
Heap statistics:
|
||||
Total bytes: 536870872
|
||||
Free bytes: 536870872
|
||||
Used bytes: 0
|
||||
Peak bytes: 0
|
||||
Heap base addr: 24641536
|
||||
Heap end addr: 561512448
|
||||
|
||||
Heartbeat: init...
|
||||
APIC Timer: calibrating...
|
||||
APIC Timer: apic_hz=980690917, tick_hz=100, initial_count=9806909
|
||||
APIC Timer: configured (masked, ready to start)
|
||||
Heartbeat: init done
|
||||
Kernel initialization complete.
|
||||
Boot successful!
|
||||
|
||||
Boot disk: a StarshipOS stick
|
||||
System: StarForth v4 (system=v4)
|
||||
StarForth v4: one host node, the F18-derived engine
|
||||
V4: capsule v4:sys:map-64.f18 signature: missing (unsigned)
|
||||
PARITY:V4_F18 name=v4:sys:map-64.f18 capsule_hash=0x949eb6a1e9260e49
|
||||
V4: capsule v4:sys:core.f18 signature: missing (unsigned)
|
||||
PARITY:V4_F18 name=v4:sys:core.f18 capsule_hash=0xb8f167892ec18c28
|
||||
V4: capsule v4:sys:input.f18 signature: missing (unsigned)
|
||||
PARITY:V4_F18 name=v4:sys:input.f18 capsule_hash=0x85d3ec486d929a79
|
||||
V4: capsule v4:sys:dict.f18 signature: missing (unsigned)
|
||||
PARITY:V4_F18 name=v4:sys:dict.f18 capsule_hash=0x1379bd3b5de811dc
|
||||
V4: capsule v4:sys:codegen.f18 signature: missing (unsigned)
|
||||
PARITY:V4_F18 name=v4:sys:codegen.f18 capsule_hash=0x36d2ae84d2911b90
|
||||
V4: capsule v4:sys:compile.f18 signature: missing (unsigned)
|
||||
PARITY:V4_F18 name=v4:sys:compile.f18 capsule_hash=0x11145c4c2ab819d8
|
||||
V4: capsule v4:sys:quit.f18 signature: missing (unsigned)
|
||||
PARITY:V4_F18 name=v4:sys:quit.f18 capsule_hash=0x43cadf3b21ddbf3e
|
||||
V4: capsule v4:sys:forth.f18 signature: missing (unsigned)
|
||||
PARITY:V4_F18 name=v4:sys:forth.f18 capsule_hash=0x16cab4a1268b85da
|
||||
V4: capsule v4:sys:numout.f18 signature: missing (unsigned)
|
||||
PARITY:V4_F18 name=v4:sys:numout.f18 capsule_hash=0x85a240ad3fb2b299
|
||||
V4: capsule v4:sys:words.f18 signature: missing (unsigned)
|
||||
PARITY:V4_F18 name=v4:sys:words.f18 capsule_hash=0xb1d381f927d9f14e
|
||||
V4: capsule v4:sys:system.f18 signature: missing (unsigned)
|
||||
PARITY:V4_F18 name=v4:sys:system.f18 capsule_hash=0xd92203664c2915bd
|
||||
V4: capsule v4:sys:qmath.f18 signature: missing (unsigned)
|
||||
PARITY:V4_F18 name=v4:sys:qmath.f18 capsule_hash=0xdb4140713dd857f3
|
||||
V4: capsule v4:sys:blocks.f18 signature: missing (unsigned)
|
||||
PARITY:V4_F18 name=v4:sys:blocks.f18 capsule_hash=0x76307ef48678dc2a
|
||||
V4: capsule v4:sys:log.f18 signature: missing (unsigned)
|
||||
PARITY:V4_F18 name=v4:sys:log.f18 capsule_hash=0xfc6540e6b824a52b
|
||||
V4: capsule v4:sys:acl.f18 signature: missing (unsigned)
|
||||
PARITY:V4_F18 name=v4:sys:acl.f18 capsule_hash=0x6845aa048db7eb22
|
||||
V4: capsule v4:sys:end.f18 signature: missing (unsigned)
|
||||
PARITY:V4_F18 name=v4:sys:end.f18 capsule_hash=0x5ef01312c07b79cc
|
||||
PARITY:V4_ROM words=2372 rom_hash=0x87b23d3ae2643c8d instructions=59145258
|
||||
V4: capsule v4:forth79.4th signature: missing (unsigned)
|
||||
PARITY:V4_CAPSULE name=v4:forth79.4th capsule_id=0x4055641ee17d176b capsule_hash=0x4055641ee17d176b dict_hash=0x033e1c05c09a1df8
|
||||
PARITY:V4_POST tests=538 pass=538 fail=0
|
||||
PARITY:V4_SYSTEM word_count=317 dict_hash=0xfec8c47cfc6f437f
|
||||
PARITY:OK
|
||||
POST: PASSED
|
||||
[32m[HADES][INFO ] [0m[KRELTSC: 0] blk: raw device LBN 2048..3071 (1024 blocks)
|
||||
PCI: init...
|
||||
PCI: ECAM mapped (amd64)
|
||||
virtio-rng: no device on PCI bus 0
|
||||
rng: backend = rdrand
|
||||
entropy: ready
|
||||
virtio-input: no device on PCI bus 0
|
||||
Starting heartbeat...
|
||||
APIC Timer: started (LVT=0x00020020 ICR=9806909)
|
||||
I/O APIC: keyboard IRQ1 unmasked
|
||||
Heartbeat running.
|
||||
blkio_usb: MSC device ready
|
||||
Artemis: grown to fill the stick
|
||||
[32m[HADES][INFO ] [0m[KRELTSC: 16230636740] blk: disk 'StarForth Volume' v2 LBN 3072..12132441 (12129370 us
|
||||
Artemis: the stick's partition attached
|
||||
[32m[HADES][INFO ] [0m[KRELTSC: 16247512130] blk: disk 'StarForth Volume' v2 LBN 12132442..12515983 (383542
|
||||
[32m[HADES][INFO ] [0m[KRELTSC: 16269128656] MINT verify: identity reads back correctly
|
||||
[38;2;255;165;0m[Hera][39m Zuse: genesis minted onto attached thumbdrive
|
||||
[38;2;255;165;0m[zuse@Hera][39m [38;2;85;255;255mok> [39m
|
||||
@@ -0,0 +1,163 @@
|
||||
[2J[01;01H[=3h[2J[01;01H[2J[01;01H[=3h[2J[01;01H[2J[01;01H[=3h[2J[01;01HBdsDxe: loading Boot0001 "UEFI QEMU QEMU USB HARDDRIVE 1-0000:00:03.0-1" from PciRoot(0x0)/Pci(0x3,0x0)/USB(0x0,0x0)
|
||||
BdsDxe: starting Boot0001 "UEFI QEMU QEMU USB HARDDRIVE 1-0000:00:03.0-1" from PciRoot(0x0)/Pci(0x3,0x0)/USB(0x0,0x0)
|
||||
[2J[01;01H[=3h[2J[01;01HStarKernel UEFI Loader
|
||||
Loading kernel from ESP...
|
||||
[CKPT 001] Entered efi_main - ConOut live
|
||||
RAW SERIAL UP
|
||||
[CKPT 002] Serial (COM1) initialized
|
||||
Monolithic build - kernel linked directly
|
||||
Collecting boot information...
|
||||
CmdLine: from starforth.cfg
|
||||
CmdLine: parsed OK
|
||||
[CKPT 004] Command line parsed
|
||||
[CKPT 005] Kernel stack allocation decided
|
||||
[CKPT 006] Boot info collected (ACPI table located)
|
||||
GOP: linear framebuffer found
|
||||
[CKPT 007] GOP: linear framebuffer found
|
||||
[CKPT 008] About to enter ExitBootServices retry loop
|
||||
EBS...
|
||||
EBS OK
|
||||
Calling kernel_main (monolithic)...
|
||||
|
||||
|
||||
_____ _ _ __ _
|
||||
/ ____| | | |/ / | |
|
||||
| (___ | |_ __ _ _ __| ' / ___ _ __ _ __ ___| |
|
||||
\___ \| __/ _` | '__| < / _ \ '__| '_ \ / _ \ |
|
||||
____) | || (_| | | | . \ __/ | | | | | __/ |
|
||||
|_____/ \__\__,_|_| |_|\_\___|_| |_| |_|\___|_|
|
||||
|
||||
LithosAnanke v4.0.0-alpha.3 amd64
|
||||
Architecture: amd64
|
||||
Build: Nov 8 2026 11:58:08
|
||||
|
||||
UEFI BootServices: EXITED
|
||||
Console: serial line is a 16550 at port 0x00000000000003f8 (COM1, probed)
|
||||
|
||||
=== StarKernel Boot Information ===
|
||||
Memory map entries: 128
|
||||
Total memory: 1023 MB
|
||||
Usable memory: 965 MB
|
||||
===================================
|
||||
|
||||
PMM initialized.
|
||||
PMM statistics:
|
||||
Total pages: 248623
|
||||
Free pages : 247096
|
||||
Used pages : 1527
|
||||
Total MB : 971
|
||||
Free MB : 965
|
||||
Used MB : 5
|
||||
|
||||
VMM initialized (mapped RAM, CR3 switched)
|
||||
VMM initialized (mapped RAM, CR3 switched)
|
||||
VMM self-test: mapped OK at 0xffff800000000000
|
||||
VMM self-test complete.
|
||||
|
||||
IDT installed.
|
||||
|
||||
APIC: init...
|
||||
APIC: IA32_APIC_BASE MSR=0x00000000fee00900
|
||||
APIC: stale-ISR drain: 0 EOI(s) issued
|
||||
APIC: initialized (xAPIC MMIO, TPR=0, SIVR=0x1FF, EOI-clear)
|
||||
APIC: init done
|
||||
|
||||
I/O APIC: init...
|
||||
I/O APIC: base=0xfec00000, gsi_base=0, overrides=5
|
||||
override: source=00 gsi=2 flags=0x0000
|
||||
override: source=05 gsi=5 flags=0x000d
|
||||
override: source=09 gsi=9 flags=0x000d
|
||||
override: source=0a gsi=10 flags=0x000d
|
||||
override: source=0b gsi=11 flags=0x000d
|
||||
i8042: keyboard ACKed enable-scanning
|
||||
i8042: IRQ1 enabled in controller config byte
|
||||
I/O APIC: keyboard IRQ1 routed (masked)
|
||||
|
||||
Timer: init...
|
||||
Timer: init start
|
||||
Timer: PM_TMR_BLK discovered from FADT at port 1544
|
||||
Timer: VM mode detected (hypervisor present).
|
||||
Timer: HPET calibration disabled (VM-exit MMIO would poison timing).
|
||||
Timer: WARNING: invariant TSC not present under hypervisor.
|
||||
Timer: continuing in RELATIVE mode (no determinism guarantees).
|
||||
Timer: RDTSCP not present; using RDTSC (less serialized).
|
||||
Timer: CPUID frequency unavailable; trying PM Timer...
|
||||
Timer: trust=1 (0=NONE,1=REL,2=ABS), TSC=2031442736 Hz
|
||||
Timer: init done
|
||||
|
||||
Kernel heap initialized.
|
||||
Heap statistics:
|
||||
Total bytes: 536870872
|
||||
Free bytes: 536870872
|
||||
Used bytes: 0
|
||||
Peak bytes: 0
|
||||
Heap base addr: 24641536
|
||||
Heap end addr: 561512448
|
||||
|
||||
Heartbeat: init...
|
||||
APIC Timer: calibrating...
|
||||
APIC Timer: apic_hz=975597517, tick_hz=100, initial_count=9755975
|
||||
APIC Timer: configured (masked, ready to start)
|
||||
Heartbeat: init done
|
||||
Kernel initialization complete.
|
||||
Boot successful!
|
||||
|
||||
Boot disk: a StarshipOS stick
|
||||
System: StarForth v4 (system=v4)
|
||||
StarForth v4: one host node, the F18-derived engine
|
||||
V4: capsule v4:sys:map-64.f18 signature: missing (unsigned)
|
||||
PARITY:V4_F18 name=v4:sys:map-64.f18 capsule_hash=0x949eb6a1e9260e49
|
||||
V4: capsule v4:sys:core.f18 signature: missing (unsigned)
|
||||
PARITY:V4_F18 name=v4:sys:core.f18 capsule_hash=0xb8f167892ec18c28
|
||||
V4: capsule v4:sys:input.f18 signature: missing (unsigned)
|
||||
PARITY:V4_F18 name=v4:sys:input.f18 capsule_hash=0x85d3ec486d929a79
|
||||
V4: capsule v4:sys:dict.f18 signature: missing (unsigned)
|
||||
PARITY:V4_F18 name=v4:sys:dict.f18 capsule_hash=0x1379bd3b5de811dc
|
||||
V4: capsule v4:sys:codegen.f18 signature: missing (unsigned)
|
||||
PARITY:V4_F18 name=v4:sys:codegen.f18 capsule_hash=0x36d2ae84d2911b90
|
||||
V4: capsule v4:sys:compile.f18 signature: missing (unsigned)
|
||||
PARITY:V4_F18 name=v4:sys:compile.f18 capsule_hash=0x11145c4c2ab819d8
|
||||
V4: capsule v4:sys:quit.f18 signature: missing (unsigned)
|
||||
PARITY:V4_F18 name=v4:sys:quit.f18 capsule_hash=0x43cadf3b21ddbf3e
|
||||
V4: capsule v4:sys:forth.f18 signature: missing (unsigned)
|
||||
PARITY:V4_F18 name=v4:sys:forth.f18 capsule_hash=0x16cab4a1268b85da
|
||||
V4: capsule v4:sys:numout.f18 signature: missing (unsigned)
|
||||
PARITY:V4_F18 name=v4:sys:numout.f18 capsule_hash=0x85a240ad3fb2b299
|
||||
V4: capsule v4:sys:words.f18 signature: missing (unsigned)
|
||||
PARITY:V4_F18 name=v4:sys:words.f18 capsule_hash=0xb1d381f927d9f14e
|
||||
V4: capsule v4:sys:system.f18 signature: missing (unsigned)
|
||||
PARITY:V4_F18 name=v4:sys:system.f18 capsule_hash=0xd92203664c2915bd
|
||||
V4: capsule v4:sys:qmath.f18 signature: missing (unsigned)
|
||||
PARRITY:V4_F18 name=v4:sys:qmath.f18 capsule_hash=0xdb4140713dd857f3
|
||||
V4: capsule v4:sys:blocks.f18 signature: missing (unsigned)
|
||||
PARITY:V4_F18 name=v4:sys:blocks.f18 capsule_hash=0x76307ef48678dc2a
|
||||
V4: capsule v4:sys:log.f18 signature: missing (unsigned)
|
||||
PARITY:V4_F18 name=v4:sys:log.f18 capsule_hash=0xfc6540e6b824a52b
|
||||
V4: capsule v4:sys:acl.f18 signature: missing (unsigned)
|
||||
PARITY:V4_F18 name=v4:sys:acl.f18 capsule_hash=0x6845aa048db7eb22
|
||||
V4: capsule v4:sys:end.f18 signature: missing (unsigned)
|
||||
PARITY:V4_F18 name=v4:sys:end.f18 capsule_hash=0x5ef01312c07b79cc
|
||||
PARITY:V4_ROM words=2372 rom_hash=0x87b23d3ae2643c8d instructions=59145258
|
||||
V4: capsule v4:forth79.4th signature: missing (unsigned)
|
||||
PARITY:V4_CAPSULE name=v4:forth79.4th capsule_id=0x4055641ee17d176b capsule_hash=0x4055641ee17d176b dict_hash=0x033e1c05c09a1df8
|
||||
PARITY:V4_POST tests=538 pass=538 fail=0
|
||||
PARITY:V4_SYSTEM word_count=317 dict_hash=0xfec8c47cfc6f437f
|
||||
PARITY:OK
|
||||
POST: PASSED
|
||||
[32m[HADES][INFO ] [0m[KRELTSC: 0] blk: raw device LBN 2048..3071 (1024 blocks)
|
||||
PCI: init...
|
||||
PCI: ECAM mapped (amd64)
|
||||
virtio-rng: no device on PCI bus 0
|
||||
rng: backend = rdrand
|
||||
entropy: ready
|
||||
virtio-input: no device on PCI bus 0
|
||||
Starting heartbeat...
|
||||
APIC Timer: started (LVT=0x00020020 ICR=9755975)
|
||||
I/O APIC: keyboard IRQ1 unmasked
|
||||
Heartbeat running.
|
||||
blkio_usb: MSC device ready
|
||||
[32m[HADES][INFO ] [0m[KRELTSC: 15850556752] blk: disk 'StarForth Volume' v2 LBN 3072..12132441 (12129370 us
|
||||
Artemis: the stick's partition attached
|
||||
[32m[HADES][INFO ] [0m[KRELTSC: 15868168832] blk: disk 'StarForth Volume' v2 LBN 12132442..12515983 (383542
|
||||
[38;2;255;165;0m[Hera][39m Zuse: identity confirmed from attached thumbdrive
|
||||
[38;2;255;165;0m[zuse@Hera][39m [38;2;85;255;255mok> [39m
|
||||
@@ -0,0 +1,165 @@
|
||||
[2J[01;01H[=3h[2J[01;01H[2J[01;01H[=3h[2J[01;01H[2J[01;01H[=3h[2J[01;01HBdsDxe: loading Boot0001 "UEFI QEMU QEMU USB HARDDRIVE 1-0000:00:03.0-1" from PciRoot(0x0)/Pci(0x3,0x0)/USB(0x0,0x0)
|
||||
BdsDxe: starting Boot0001 "UEFI QEMU QEMU USB HARDDRIVE 1-0000:00:03.0-1" from PciRoot(0x0)/Pci(0x3,0x0)/USB(0x0,0x0)
|
||||
[2J[01;01H[=3h[2J[01;01HStarKernel UEFI Loader
|
||||
Loading kernel from ESP...
|
||||
[CKPT 001] Entered efi_main - ConOut live
|
||||
RAW SERIAL UP
|
||||
[CKPT 002] Serial (COM1) initialized
|
||||
Monolithic build - kernel linked directly
|
||||
Collecting boot information...
|
||||
CmdLine: from starforth.cfg
|
||||
CmdLine: parsed OK
|
||||
[CKPT 004] Command line parsed
|
||||
[CKPT 005] Kernel stack allocation decided
|
||||
[CKPT 006] Boot info collected (ACPI table located)
|
||||
GOP: linear framebuffer found
|
||||
[CKPT 007] GOP: linear framebuffer found
|
||||
[CKPT 008] About to enter ExitBootServices retry loop
|
||||
EBS...
|
||||
EBS OK
|
||||
Calling kernel_main (monolithic)...
|
||||
|
||||
|
||||
_____ _ _ __ _
|
||||
/ ____| | | |/ / | |
|
||||
| (___ | |_ __ _ _ __| ' / ___ _ __ _ __ ___| |
|
||||
\___ \| __/ _` | '__| < / _ \ '__| '_ \ / _ \ |
|
||||
____) | || (_| | | | . \ __/ | | | | | __/ |
|
||||
|_____/ \__\__,_|_| |_|\_\___|_| |_| |_|\___|_|
|
||||
|
||||
LithosAnanke v4.0.0-alpha.3 amd64
|
||||
Architecture: amd64
|
||||
Build: Nov 8 2026 12:01:37
|
||||
|
||||
UEFI BootServices: EXITED
|
||||
Console: serial line is a 16550 at port 0x00000000000003f8 (COM1, probed)
|
||||
|
||||
=== StarKernel Boot Information ===
|
||||
Memory map entries: 128
|
||||
Total memory: 1023 MB
|
||||
Usable memory: 965 MB
|
||||
===================================
|
||||
|
||||
PMM initialized.
|
||||
PMM statistics:
|
||||
Total pages: 248623
|
||||
Free pages : 247096
|
||||
Used pages : 1527
|
||||
Total MB : 971
|
||||
Free MB : 965
|
||||
Used MB : 5
|
||||
|
||||
VMM initialized (mapped RAM, CR3 switched)
|
||||
VMM initialized (mapped RAM, CR3 switched)
|
||||
VMM self-test: mapped OK at 0xffff800000000000
|
||||
VMM self-test complete.
|
||||
|
||||
IDT installed.
|
||||
|
||||
APIC: init...
|
||||
APIC: IA32_APIC_BASE MSR=0x00000000fee00900
|
||||
APIC: stale-ISR drain: 0 EOI(s) issued
|
||||
APIC: initialized (xAPIC MMIO, TPR=0, SIVR=0x1FF, EOI-clear)
|
||||
APIC: init done
|
||||
|
||||
I/O APIC: init...
|
||||
I/O APIC: base=0xfec00000, gsi_base=0, overrides=5
|
||||
override: source=00 gsi=2 flags=0x0000
|
||||
override: source=05 gsi=5 flags=0x000d
|
||||
override: source=09 gsi=9 flags=0x000d
|
||||
override: source=0a gsi=10 flags=0x000d
|
||||
override: source=0b gsi=11 flags=0x000d
|
||||
i8042: keyboard ACKed enable-scanning
|
||||
i8042: IRQ1 enabled in controller config byte
|
||||
I/O APIC: keyboard IRQ1 routed (masked)
|
||||
|
||||
Timer: init...
|
||||
Timer: init start
|
||||
Timer: PM_TMR_BLK discovered from FADT at port 1544
|
||||
Timer: VM mode detected (hypervisor present).
|
||||
Timer: HPET calibration disabled (VM-exit MMIO would poison timing).
|
||||
Timer: WARNING: invariant TSC not present under hypervisor.
|
||||
Timer: continuing in RELATIVE mode (no determinism guarantees).
|
||||
Timer: RDTSCP not present; using RDTSC (less serialized).
|
||||
Timer: CPUID frequency unavailable; trying PM Timer...
|
||||
Timer: trust=1 (0=NONE,1=REL,2=ABS), TSC=2090125821 Hz
|
||||
Timer: init done
|
||||
|
||||
Kernel heap initialized.
|
||||
Heap statistics:
|
||||
Total bytes: 536870872
|
||||
Free bytes: 536870872
|
||||
Used bytes: 0
|
||||
Peak bytes: 0
|
||||
Heap base addr: 24641536
|
||||
Heap end addr: 561512448
|
||||
|
||||
Heartbeat: init...
|
||||
APIC Timer: calibrating...
|
||||
APIC Timer: apic_hz=999200110, tick_hz=100, initial_count=9992001
|
||||
APIC Timer: configured (masked, ready to start)
|
||||
Heartbeat: init done
|
||||
Kernel initialization complete.
|
||||
Boot successful!
|
||||
|
||||
Boot disk: a StarshipOS stick
|
||||
System: StarForth v4 (system=v4)
|
||||
StarForth v4: one host node, the F18-derived engine
|
||||
V4: capsule v4:sys:map-64.f18 signature: missing (unsigned)
|
||||
PARITY:V4_F18 name=v4:sys:map-64.f18 capsule_hash=0x949eb6a1e9260e49
|
||||
V4: capsule v4:sys:core.f18 signature: missing (unsigned)
|
||||
PARITY:V4_F18 name=v4:sys:core.f18 capsule_hash=0xb8f167892ec18c28
|
||||
V4: capsule v4:sys:input.f18 signature: missing (unsigned)
|
||||
PARITY:V4_F18 name=v4:sys:input.f18 capsule_hash=0x85d3ec486d929a79
|
||||
V4: capsule v4:sys:dict.f18 signature: missing (unsigned)
|
||||
PARITY:V4_F18 name=v4:sys:dict.f18 capsule_hash=0x1379bd3b5de811dc
|
||||
V4: capsule v4:sys:codegen.f18 signature: missing (unsigned)
|
||||
PARITY:V4_F18 name=v4:sys:codegen.f18 capsule_hash=0x36d2ae84d2911b90
|
||||
V4: capsule v4:sys:compile.f18 signature: missing (unsigned)
|
||||
PARITY:V4_F18 name=v4:sys:compile.f18 capsule_hash=0x11145c4c2ab819d8
|
||||
V4: capsule v4:sys:quit.f18 signature: missing (unsigned)
|
||||
PARITY:V4_F18 name=v4:sys:quit.f18 capsule_hash=0x43cadf3b21ddbf3e
|
||||
V4: capsule v4:sys:forth.f18 signature: missing (unsigned)
|
||||
PARITY:V4_F18 name=v4:sys:forth.f18 capsule_hash=0x16cab4a1268b85da
|
||||
V4: capsule v4:sys:numout.f18 signature: missing (unsigned)
|
||||
PARITY:V4_F18 name=v4:sys:numout.f18 capsule_hash=0x85a240ad3fb2b299
|
||||
V4: capsule v4:sys:words.f18 signature: missing (unsigned)
|
||||
PARITY:V4_F18 name=v4:sys:words.f18 capsule_hash=0xb1d381f927d9f14e
|
||||
V4: capsule v4:sys:system.f18 signature: missing (unsigned)
|
||||
PARITY:V4_F18 name=v4:sys:system.f18 capsule_hash=0xd92203664c2915bd
|
||||
V4: capsule v4:sys:qmath.f18 signature: missing (unsigned)
|
||||
PARITY:V4_F18 name=v4:sys:qmath.f18 capsule_hash=0xdb4140713dd857f3
|
||||
V4: capsule v4:sys:blocks.f18 signature: missing (unsigned)
|
||||
PARITY:V4_F18 name=v4:sys:blocks.f18 capsule_hash=0x76307ef48678dc2a
|
||||
V4: capsule v4:sys:log.f18 signature: missing (unsigned)
|
||||
PARITY:V4_F18 name=v4:sys:log.f18 capsule_hash=0xfc6540e6b824a52b
|
||||
V4: capsule v4:sys:acl.f18 signature: missing (unsigned)
|
||||
PARITY:V4_F18 name=v4:sys:acl.f18 capsule_hash=0x6845aa048db7eb22
|
||||
V4: capsule v4:sys:end.f18 signature: missing (unsigned)
|
||||
PARITY:V4_F18 name=v4:sys:end.f18 capsule_hash=0x5ef01312c07b79cc
|
||||
PARITY:V4_ROM words=2372 rom_hash=0x87b23d3ae2643c8d instructions=59145258
|
||||
V4: capsule v4:forth79.4th signature: missing (unsigned)
|
||||
PARITY:V4_CAPSULE name=v4:forth79.4th capsule_id=0x4055641ee17d176b capsule_hash=0x4055641ee17d176b dict_hash=0x033e1c05c09a1df8
|
||||
PARITY:V4_POST tests=538 pass=538 fail=0
|
||||
PARITY:V4_SYSTEM word_count=317 dict_hash=0xfec8c47cfc6f437f
|
||||
PARITY:OK
|
||||
POST: PASSED
|
||||
[32m[HADES][INFO ] [0m[KRELTSC: 0] blk: raw device LBN 2048..3071 (1024 blocks)
|
||||
PCI: init...
|
||||
PCI: ECAM mapped (amd64)
|
||||
virtio-rng: no device on PCI bus 0
|
||||
rng: backend = rdrand
|
||||
entropy: ready
|
||||
virtio-input: no device on PCI bus 0
|
||||
Starting heartbeat...
|
||||
APIC Timer: started (LVT=0x00020020 ICR=9992001)
|
||||
I/O APIC: keyboard IRQ1 unmasked
|
||||
Heartbeat running.
|
||||
blkio_usb: MSC device ready
|
||||
Artemis: the stick is under 8 GB -- not grown
|
||||
[32m[HADES][INFO ] [0m[KRELTSC: 15571534696] blk: disk 'StarForth Volume' v2 LBN 3072..1122393 (1119322 user
|
||||
Artemis: the stick's partition attached
|
||||
[32m[HADES][INFO ] [0m[KRELTSC: 15591872270] blk: disk 'StarForth Volume' v2 LBN 1122394..1505935 (383542 us
|
||||
[32m[HADES][INFO ] [0m[KRELTSC: 15623585180] MINT verify: identity reads back correctly
|
||||
[38;2;255;165;0m[Hera][39m Zuse: genesis minted onto attached thumbdrive
|
||||
[38;2;255;165;0m[zuse@Hera][39m [38;2;85;255;255mok> [39m
|
||||
@@ -17,11 +17,12 @@
|
||||
# --table gpt -> partition type "EFI System" (UEFI firmware, U-Boot bootefi)
|
||||
#
|
||||
# The StarshipOS stick and data stick (docs/v4.0.0/STICK.md 4; --table gpt only):
|
||||
# --starship IDENT_MIB --mkartemis TOOL --esp-mib E
|
||||
# --starship IDENT_MIB --mkartemis TOOL --esp-mib E [--bam-for SECTORS]
|
||||
# lays out an ESP of E MiB holding the SRC:DEST files (E=0: no ESP, no files),
|
||||
# then a StarshipOS identity partition of IDENT_MIB MiB (all zeros), then a
|
||||
# StarshipOS Artemis partition to the last whole MiB before the backup GPT,
|
||||
# formatted and signed by TOOL (tools/mkartemis.c). Every partition starts and
|
||||
# formatted and signed by TOOL (tools/mkartemis.c) -- with --bam-for, its BAM sized for an Artemis
|
||||
# of SECTORS, so it can grow that far on a larger stick (STICK.md 5a). Every partition starts and
|
||||
# ends on a whole MiB, so on 1 KiB blocks, as the kernel's GPT reader needs.
|
||||
#
|
||||
# Zuse's minted pair as a stick (docs/v4.0.0/plans/2026-10-27-stick-4-one-disk.md, Task 1):
|
||||
@@ -38,7 +39,7 @@
|
||||
# root, no loop devices.
|
||||
set -euo pipefail
|
||||
|
||||
OUT="" TABLE="" SIZE_MIB="" LABEL="" IDENT_MIB="" MKARTEMIS="" ESP_MIB="" FROM_IDENT="" FROM_ART=""
|
||||
OUT="" TABLE="" SIZE_MIB="" LABEL="" IDENT_MIB="" MKARTEMIS="" ESP_MIB="" FROM_IDENT="" FROM_ART="" BAM_FOR=""
|
||||
while [ $# -gt 0 ]; do
|
||||
case "$1" in
|
||||
--out) OUT="$2"; shift 2 ;;
|
||||
@@ -48,6 +49,7 @@ while [ $# -gt 0 ]; do
|
||||
--starship) IDENT_MIB="$2"; shift 2 ;;
|
||||
--mkartemis) MKARTEMIS="$2"; shift 2 ;;
|
||||
--esp-mib) ESP_MIB="$2"; shift 2 ;;
|
||||
--bam-for) BAM_FOR="$2"; shift 2 ;;
|
||||
--starship-from) FROM_IDENT="$2"; FROM_ART="$3"; shift 3 ;;
|
||||
--) shift; break ;;
|
||||
-*) echo "mkdiskimage.sh: unknown option $1" >&2; exit 2 ;;
|
||||
@@ -119,7 +121,8 @@ if [ -n "$IDENT_MIB" ]; then
|
||||
dd if="$FROM_IDENT" of="$OUT" bs=1M seek=$(( IDENT_START / 2048 )) conv=notrunc,sparse status=none
|
||||
dd if="$FROM_ART" of="$OUT" bs=1M seek=$(( ART_START / 2048 )) conv=notrunc,sparse status=none
|
||||
else
|
||||
"$MKARTEMIS" --format "$OUT" --first-lba "$ART_START" --sectors "$ART_SECTORS" >/dev/null || {
|
||||
"$MKARTEMIS" --format "$OUT" --first-lba "$ART_START" --sectors "$ART_SECTORS" \
|
||||
${BAM_FOR:+--bam-for "$BAM_FOR"} >/dev/null || {
|
||||
echo "mkdiskimage.sh: formatting Artemis failed" >&2; rm -f "$OUT"; exit 1; }
|
||||
fi
|
||||
if [ "$ESP_MIB" = 0 ]; then
|
||||
|
||||
+22
-6
@@ -10,10 +10,14 @@
|
||||
* kernel writes. Zuse's genesis marker is not written: the first boot does
|
||||
* that. docs/v4.0.0/plans/2026-10-27-stick-3-images.md.
|
||||
*
|
||||
* mkartemis --format IMG --first-lba L --sectors N
|
||||
* mkartemis --format IMG --first-lba L --sectors N [--bam-for M]
|
||||
* mkartemis --check IMG --first-lba L --sectors N
|
||||
*
|
||||
* L and N count 512-byte sectors; both must be even (1 KiB blocks).
|
||||
* L, N and M count 512-byte sectors; L and N must be even (1 KiB blocks).
|
||||
* --bam-for M sizes the volume's BAM as for a volume of M sectors, so it can
|
||||
* grow that far on a larger stick with no BAM to move (docs/v4.0.0/STICK.md
|
||||
* 5a; plan 2026-10-29-stick-5, R1 and Task 2). --check reports the BAM's
|
||||
* size in 4 KiB devblocks.
|
||||
*/
|
||||
#define _GNU_SOURCE
|
||||
#include <errno.h>
|
||||
@@ -111,7 +115,7 @@ static uint8_t g_ram[(size_t)BLK_RAM_BLOCKS * BLK_FORTH_SIZE];
|
||||
|
||||
static int usage(void)
|
||||
{
|
||||
fprintf(stderr, "usage: mkartemis --format|--check IMG --first-lba L --sectors N\n");
|
||||
fprintf(stderr, "usage: mkartemis --format|--check IMG --first-lba L --sectors N [--bam-for M]\n");
|
||||
return 2;
|
||||
}
|
||||
|
||||
@@ -140,6 +144,8 @@ static int attach(blkio_dev_t *dev, uint32_t *start_lbn, uint32_t *count)
|
||||
* header is read from the disk itself and judged as attach judges it
|
||||
* (block_subsystem.c blk_format_or_load_disk): blk_get_volume_meta would give
|
||||
* the geometry computed in memory for a blank disk, magic and all. */
|
||||
static uint32_t g_bam_devblocks; /* the BAM's size, as check_volume read it */
|
||||
|
||||
static int check_volume(blkio_dev_t *dev, uint32_t *count, artemis_sig_t *sig)
|
||||
{
|
||||
static uint8_t hdr[BLK_DEVICE_SECTOR];
|
||||
@@ -160,6 +166,7 @@ static int check_volume(blkio_dev_t *dev, uint32_t *count, artemis_sig_t *sig)
|
||||
fprintf(stderr, "mkartemis: the Artemis signature does not check out (%d)\n", (int)src);
|
||||
else
|
||||
rc = 0;
|
||||
g_bam_devblocks = meta.bam_devblocks;
|
||||
blk_subsys_shutdown();
|
||||
return rc;
|
||||
}
|
||||
@@ -167,7 +174,7 @@ static int check_volume(blkio_dev_t *dev, uint32_t *count, artemis_sig_t *sig)
|
||||
int main(int argc, char **argv)
|
||||
{
|
||||
const char *mode, *img;
|
||||
unsigned long long first_lba, sectors;
|
||||
unsigned long long first_lba, sectors, bam_for = 0;
|
||||
range_t r;
|
||||
blkio_dev_t dev;
|
||||
blkio_params_t params;
|
||||
@@ -175,7 +182,8 @@ int main(int argc, char **argv)
|
||||
artemis_sig_t sig;
|
||||
int i, format;
|
||||
|
||||
if (argc != 7 || strcmp(argv[3], "--first-lba") != 0 || strcmp(argv[5], "--sectors") != 0) return usage();
|
||||
if ((argc != 7 && argc != 9) || strcmp(argv[3], "--first-lba") != 0 || strcmp(argv[5], "--sectors") != 0)
|
||||
return usage();
|
||||
mode = argv[1];
|
||||
img = argv[2];
|
||||
if (strcmp(mode, "--format") == 0) format = 1;
|
||||
@@ -185,6 +193,12 @@ int main(int argc, char **argv)
|
||||
fprintf(stderr, "mkartemis: --first-lba and --sectors take a number of sectors\n");
|
||||
return 1;
|
||||
}
|
||||
if (argc == 9) {
|
||||
if (!format || strcmp(argv[7], "--bam-for") != 0 || parse_count(argv[8], &bam_for) != 0 || bam_for < sectors) {
|
||||
fprintf(stderr, "mkartemis: --bam-for takes a number of sectors, at least --sectors, with --format\n");
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
if (first_lba % 2u != 0u || sectors % 2u != 0u || sectors == 0u || sectors / 2u > 0xFFFFFFFFull) {
|
||||
fprintf(stderr, "mkartemis: the partition must start and end on a 1 KiB block (even LBA and sector count)\n");
|
||||
return 1;
|
||||
@@ -202,6 +216,7 @@ int main(int argc, char **argv)
|
||||
|
||||
sf_time_init();
|
||||
if (format) {
|
||||
blk_subsys_set_format_bam_for(bam_for / 8u); /* sectors -> 4 KiB devblocks */
|
||||
if (attach(&dev, &start_lbn, &count) != 0) return 1;
|
||||
if (artemis_sig_check(&dev, &sig) != ARTEMIS_SIG_BLANK) {
|
||||
fprintf(stderr, "mkartemis: the partition is not blank -- not formatted\n");
|
||||
@@ -221,7 +236,8 @@ int main(int argc, char **argv)
|
||||
printf("mkartemis: formatted %u blocks, STFR v2, signature stamped, read back ok\n", r.blocks);
|
||||
} else {
|
||||
if (check_volume(&dev, &count, &sig) != 0) return 1;
|
||||
printf("mkartemis: STFR v2, %u user blocks, signature ok, disk_uuid ", count);
|
||||
printf("mkartemis: STFR v2, %u user blocks, bam %u devblocks, signature ok, disk_uuid ",
|
||||
count, g_bam_devblocks);
|
||||
for (i = 0; i < 16; i++) printf("%02x", sig.disk_uuid[i]);
|
||||
printf("\n");
|
||||
}
|
||||
|
||||
@@ -591,6 +591,18 @@ int blk_subsys_add_raw_device(uint8_t *buf, uint32_t nblocks);
|
||||
* by the disk's owner before any write to that slot will succeed. */
|
||||
int blk_subsys_confirm_format(uint32_t lbn);
|
||||
|
||||
/* blk_volume_compute_totals - a volume's tracked/total block counts from its
|
||||
* total_devblocks, bam_devblocks, reloc_devblocks and meta_fence_blocks, as a
|
||||
* fresh format computes them. For a volume grown to fill a larger partition
|
||||
* (the v4 stick, plan 2026-10-29-stick-5, Task 2). */
|
||||
void blk_volume_compute_totals(blk_volume_meta_t *m);
|
||||
|
||||
/* blk_subsys_set_format_bam_for - size the BAM of the next fresh format for a
|
||||
* volume of `total_devblocks` 4 KiB devblocks, when that is more than the
|
||||
* disk's own: the volume can later grow that far with no BAM of its own to
|
||||
* move (mkartemis --bam-for). 0, the default, sizes it for the disk. */
|
||||
void blk_subsys_set_format_bam_for(uint64_t total_devblocks);
|
||||
|
||||
#ifdef __cplusplus
|
||||
} /* extern "C" */
|
||||
#endif
|
||||
|
||||
@@ -386,6 +386,20 @@ static void compute_totals_from_B(blk_volume_meta_t *m) {
|
||||
* blk_compute_fresh_geometry()). */
|
||||
}
|
||||
|
||||
/* compute_totals_from_B, for a volume grown on its disk (the v4 stick:
|
||||
* docs/v4.0.0/plans/2026-10-29-stick-5-proxy-zuse-and-real-zuse.md, Task 2). */
|
||||
void blk_volume_compute_totals(blk_volume_meta_t *m) {
|
||||
if (m) compute_totals_from_B(m);
|
||||
}
|
||||
|
||||
/* The BAM a fresh format sizes: for this many devblocks when it is more than
|
||||
* the disk's own (0: the disk's). Only mkartemis sets it (--bam-for). */
|
||||
static uint64_t g_format_bam_for;
|
||||
|
||||
void blk_subsys_set_format_bam_for(uint64_t total_devblocks) {
|
||||
g_format_bam_for = total_devblocks;
|
||||
}
|
||||
|
||||
/* ===== physical BAM I/O (sync to/from slot->bam[]) ===== */
|
||||
|
||||
/*
|
||||
@@ -530,7 +544,8 @@ static void blk_compute_fresh_geometry(blk_dev_slot_t *slot) {
|
||||
strncpy(slot->vol_meta.label, "StarForth Volume", sizeof(slot->vol_meta.label) - 1);
|
||||
slot->vol_meta.total_devblocks = (uint64_t) udiv_floor(slot->total_blkio_blocks_1k, 4);
|
||||
slot->vol_meta.bam_start = 1;
|
||||
slot->vol_meta.bam_devblocks = choose_B(slot->vol_meta.total_devblocks);
|
||||
slot->vol_meta.bam_devblocks = choose_B(g_format_bam_for > slot->vol_meta.total_devblocks
|
||||
? g_format_bam_for : slot->vol_meta.total_devblocks);
|
||||
slot->vol_meta.reloc_start = slot->vol_meta.bam_start + slot->vol_meta.bam_devblocks;
|
||||
/* One devblock (4 KiB): a 4-byte count prefix + up to BLK_RELOC_MAX_ENTRIES
|
||||
* 8-byte {home_lbn, actual_lbn} pairs -- see this file's own doc comment
|
||||
|
||||
Reference in New Issue
Block a user