storage: AHCI, GPT/MBR partitions, and a disk a PC can boot
q35 stopped with "no root filesystem" because its disk is SATA, like every PC since 2008, and SchOS only had IDE. And SchFS could only sit on a whole raw device, so nothing could boot from a disk that also carried an ESP. - include/blkdev.h, kernel/dev/blkdev.c: a registry of block devices found at probe time, numbered from 4. A disk's GPT (or MBR) is read when it registers, and each partition becomes a device whose block 0 is the partition's first sector. SchFS needs no format change to live in a partition; a Linux SchFS driver will see the same bytes on /dev/sdX2. SchFS has its own GPT type: 47138FA9-B79C-47A6-9F7D-AC1F7F572D5E. - AHCI driver, written from the AHCI 1.3.1 spec: BIOS handoff, COMRESET when the link is down, IDENTIFY, 48-bit DMA read/write, FLUSH. Completion is polled, so the root disk does not depend on interrupt routing. - USB sticks also register as usb0, so their partitions are found. - The root probe tries registered devices between USB and IDE, SchFS-typed partitions first. - make disk / tools/posix/mkdisk.sh: a GPT image with a 64 MB ESP and a SchFS partition, ready to dd to a stick or a disk. Tested in QEMU q35: the old two-disk setup roots on sata1; disk.img as the only SATA disk roots on sata0p2; disk.img as a USB stick (firmware boots from it) roots on usb0p2. Writes survive sync in each case. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01HH7xukt4aaiGj1nQEAoQf1
This commit is contained in:
parent
7e8d5e2821
commit
d7352c0db0
10 changed files with 1027 additions and 17 deletions
73
tools/posix/mkdisk.sh
Normal file
73
tools/posix/mkdisk.sh
Normal file
|
|
@ -0,0 +1,73 @@
|
|||
#!/bin/sh
|
||||
# SPDX-License-Identifier: GPL-2.0-or-later
|
||||
#
|
||||
# Build a partitioned SchOS disk: the image a real machine boots from.
|
||||
#
|
||||
# tools/posix/mkdisk.sh <esp-dir> <schfs.img> <output.img>
|
||||
#
|
||||
# A GUID partition table with two entries:
|
||||
#
|
||||
# 1 EFI system partition FAT, holding <esp-dir> (the loader and kernel)
|
||||
# 2 SchFS <schfs.img>, byte for byte, typed
|
||||
# 47138FA9-B79C-47A6-9F7D-AC1F7F572D5E
|
||||
#
|
||||
# This is the layout every UEFI machine expects: the firmware finds the ESP by
|
||||
# its type and runs EFI/BOOT/BOOTX64.EFI from it, and the kernel finds the root
|
||||
# by scanning the same table -- the SchFS type first, anything else after (see
|
||||
# rootdev_mount() in kernel/proc/proc.c). Write it to a USB stick or a disk
|
||||
# with dd and it boots; attach it to QEMU's q35 as its only disk and it boots
|
||||
# the same way.
|
||||
#
|
||||
# The SchFS partition holds the volume unchanged. A filesystem addresses
|
||||
# blocks from the start of whatever it is on, and the kernel hands a partition
|
||||
# to it as a device whose block 0 is the partition's first sector -- so the
|
||||
# image mkschfs writes for a whole disk is already the right content for a
|
||||
# partition, and so is anything a Linux SchFS driver is given as /dev/sdX2.
|
||||
#
|
||||
# Needs sfdisk (util-linux) and mtools. Nothing here needs root or loop
|
||||
# devices: the FAT is built in a file and copied in at its offset.
|
||||
|
||||
set -eu
|
||||
|
||||
esp=$1
|
||||
vol=$2
|
||||
out=$3
|
||||
|
||||
SCHFS_TYPE=47138FA9-B79C-47A6-9F7D-AC1F7F572D5E
|
||||
ESP_TYPE=C12A7328-F81F-11D2-BA4B-00A0C93EC93B
|
||||
|
||||
for t in sfdisk mformat mcopy; do
|
||||
command -v $t >/dev/null || { echo "mkdisk: needs $t" >&2; exit 1; }
|
||||
done
|
||||
|
||||
# Sizes in 512-byte sectors. The ESP is 64 MB, which leaves room for the
|
||||
# kernel to grow by an order of magnitude; partitions start on 1 MB
|
||||
# boundaries, which is what every partitioning tool does and what flash
|
||||
# media erase in.
|
||||
esp_mb=64
|
||||
esp_start=2048
|
||||
esp_sectors=$((esp_mb * 2048))
|
||||
vol_bytes=$(wc -c < "$vol")
|
||||
vol_start=$((esp_start + esp_sectors))
|
||||
vol_sectors=$(( (vol_bytes + 511) / 512 ))
|
||||
# 1 MB at the end for the backup GPT, rounded the same way.
|
||||
total=$((vol_start + vol_sectors + 2048))
|
||||
|
||||
rm -f "$out" "$out.esp"
|
||||
dd if=/dev/zero of="$out" bs=512 count=0 seek=$total 2>/dev/null
|
||||
|
||||
sfdisk --quiet --label gpt "$out" <<EOF
|
||||
start=$esp_start, size=$esp_sectors, type=$ESP_TYPE, name="EFI system"
|
||||
start=$vol_start, size=$vol_sectors, type=$SCHFS_TYPE, name="SchOS"
|
||||
EOF
|
||||
|
||||
# The ESP, built apart and copied in.
|
||||
dd if=/dev/zero of="$out.esp" bs=1M count=$esp_mb 2>/dev/null
|
||||
mformat -i "$out.esp" -F -v SCHOS ::
|
||||
mcopy -i "$out.esp" -s "$esp"/* ::
|
||||
dd if="$out.esp" of="$out" bs=512 seek=$esp_start conv=notrunc 2>/dev/null
|
||||
rm -f "$out.esp"
|
||||
|
||||
dd if="$vol" of="$out" bs=512 seek=$vol_start conv=notrunc 2>/dev/null
|
||||
|
||||
echo "mkdisk: $out -- ESP ${esp_mb} MB, SchFS $((vol_bytes >> 20)) MB"
|
||||
Loading…
Reference in a new issue