Files
LithosAnanke/kernel/include/starkernel/gpt.h
T
Claude 9700a7b404 fix: gpt_read checks every entry, and says when there are more than max (#180)
gpt_read() stopped at max used entries (16 for the identity code, 4 in the
mint): a disk whose StarshipOS partitions came after the first max read as
having none, and the entries after max were never range-checked.

Now every entry is checked and every used one counted; a good table with more
used entries than max is GPT_MANY (the first max in parts), and the identity
code says "GPT: a USB drive has more than 16 partitions -- not used". Other
callers treat anything but GPT_OK as before.

Tested first, seen to fail: qemu_session.py gpt_many -- a data stick with its
two partitions as entries 17 and 18 after 16 others, and the same with an entry
19 past the usable range: both "not this system's stick" before (silently cut,
entry 19 never checked; logs/20261112-162236). After: "more than 16
partitions" and "a damaged partition table" (logs/20261112-162921).
Regressions: gpt_bad_entries, gpt_foreign PASS. gpt_zuse FAILS, on a stale
expectation unrelated to this change -- an identity-only GPT drive with no
system stick has been held silently as a possible real Zuse since #92 Task 4;
its log is kept here. The gpt_many images are made before the boot: a first
version made them after, failed in sgdisk and left its QEMU running, stopped
by hand (logs/20261112-162003).

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_017RzZgrf7V7Zk2iczBXDRbm
2026-11-12 16:41:00 +00:00

93 lines
4.8 KiB
C

/* SPDX-License-Identifier: LicenseRef-Starship-1.0
* Copyright (c) 2023-2026 Robert A. James
*/
/* gpt.h -- the GPT reader, and a block device of one partition.
* docs/v4.0.0/STICK.md 3 and 4; docs/v4.0.0/plans/2026-10-26-stick-2-gpt-reader.md.
*/
#ifndef STARKERNEL_GPT_H
#define STARKERNEL_GPT_H
#include <stdint.h>
#include <stddef.h>
#include "blkio.h"
/* The two StarshipOS partition types, as their GUIDs are on disk. */
extern const uint8_t gpt_type_starship_identity[16]; /* 23BEBFE1-4817-4CF3-A537-9069BF159788 */
extern const uint8_t gpt_type_starship_artemis[16]; /* BCD7B586-1C8E-4EEF-86A3-273A8D8EE624 */
typedef struct {
uint8_t type[16];
uint64_t first_lba;
uint64_t last_lba;
} gpt_part_t;
#define GPT_OK 0 /* a valid GPT */
#define GPT_NONE 1 /* not a GPT disk -- no protective MBR -- (or one whose sectors are not 512 bytes): read it raw */
#define GPT_BAD 2 /* a protective MBR, but its header or entry array does not check out: not used */
#define GPT_EIO 3 /* its first block could not be read: not used; gpt_write_one: nothing was written */
#define GPT_PART 4 /* gpt_write_one only: a write failed after others were made -- the disk is changed (#168) */
#define GPT_MANY 5 /* gpt_read: a valid GPT with more used entries than max -- every entry checked, none cut (#180) */
/* Read `disk`'s protective MBR, primary GPT header and partition-entry array,
* checking both CRC-32s, the revision, the sizes and the geometry, and every
* entry's range. On GPT_OK, `*count` partitions with a non-zero type (at most
* `max`) are in `parts`. GPT_MANY when the table is good but has more used
* entries than `max`: the first `max` are in `parts`, `*count` is `max`, and the
* caller says so rather than taking the disk as having only those (#180).
* Reads only. */
int gpt_read(blkio_dev_t *disk, gpt_part_t *parts, unsigned max, unsigned *count);
/* The DiskGUID (header bytes 56..71, as on disk) of the last gpt_read that
* 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);
/* Write a new GPT on `disk` with one partition of `type` (plan
* 2026-10-29-stick-5, Task 4: the real Zuse's stick): at LBA 2048, at most
* `part_sectors` long (on a whole MiB, no further than the disk allows), a
* fresh DiskGUID (into `disk_guid`) and partition GUID from the RNG, 128
* entries, the backup header and entries at the disk's end, the protective
* MBR written last (the old one zeroed first, so a write torn anywhere leaves
* no table). Nothing inside the partition is written. GPT_OK; GPT_BAD for a
* disk whose sectors are not 512 bytes or that is too small (nothing written);
* GPT_EIO when its first write failed (nothing written, the disk as it was);
* GPT_PART when a later write or a flush failed (the disk is changed: its old
* table is gone). The caller says which (#168). */
int gpt_write_one(blkio_dev_t *disk, const uint8_t type[16], uint64_t part_sectors, uint8_t disk_guid[16]);
/* 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]);
/* A partition as a block device: its block n is the disk's block
* first_fblock + n; blocks past fblocks are refused. */
typedef struct {
blkio_dev_t *disk;
uint32_t first_fblock;
uint32_t fblocks;
} gpt_part_dev_t;
/* Open `dev` as partition `p` of `disk`, its state in `st` (which must live
* as long as `dev`). BLKIO_EINVAL for a partition that does not start and end
* on a 1 KiB block, or that runs past the disk. */
int gpt_part_open(blkio_dev_t *dev, gpt_part_dev_t *st, blkio_dev_t *disk, const gpt_part_t *p);
/* CRC-32 (IEEE 802.3, reflected, polynomial 0xEDB88320), as GPT uses. */
uint32_t gpt_crc32(const void *buf, size_t len);
#endif /* STARKERNEL_GPT_H */