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
|
|
@ -14,6 +14,7 @@
|
|||
#include "file.h"
|
||||
#include "posix.h"
|
||||
#include "errno.h"
|
||||
#include "blkdev.h"
|
||||
|
||||
// Verify myproc()->fs_base offset matches the hardcoded 0x688 in trapasm.S.
|
||||
_Static_assert(__builtin_offsetof(struct proc, fs_base) == 0x18,
|
||||
|
|
@ -884,6 +885,8 @@ rootdev_usable(uint dev)
|
|||
return ramdisk_present();
|
||||
if (dev == USBDISK_DEV)
|
||||
return usb_storage_present();
|
||||
if (dev >= BLKDEV_FIRST)
|
||||
return blkdev_present(dev);
|
||||
// iderw() panics on an absent drive rather than failing, so a probe has to
|
||||
// ask first. That is the whole reason ide_disk_present() exists.
|
||||
return ide_disk_present((int)dev);
|
||||
|
|
@ -892,16 +895,27 @@ rootdev_usable(uint dev)
|
|||
static void
|
||||
rootdev_mount(void)
|
||||
{
|
||||
static const struct { uint dev; const char *what; } cand[] = {
|
||||
// The fixed devices, with the registered ones -- SATA, NVMe, and every
|
||||
// partition on them -- between USB and IDE. A partition GPT types as SchFS
|
||||
// goes ahead of the rest of the registry, because it was labelled that way
|
||||
// on purpose; the others are probed too, so a volume in an untyped or MBR
|
||||
// partition, or on a whole unpartitioned disk, still boots.
|
||||
struct { uint dev; const char *what; } cand[4 + 2 * NBLKDEV];
|
||||
int ncand = 0;
|
||||
#ifdef RAMDISK_ROOT
|
||||
{ RAMDISK_DEV, "ramdisk" },
|
||||
cand[ncand].dev = RAMDISK_DEV; cand[ncand++].what = "ramdisk";
|
||||
#endif
|
||||
{ USBDISK_DEV, "USB disk" },
|
||||
{ 1, "IDE disk 1" },
|
||||
{ 0, "IDE disk 0" },
|
||||
};
|
||||
cand[ncand].dev = USBDISK_DEV; cand[ncand++].what = "USB disk";
|
||||
for (int pass = 0; pass < 2; pass++)
|
||||
for (int i = 0, d; (d = blkdev_nth(i)) >= 0; i++)
|
||||
if (blkdev_is_schfs(d) == !pass) {
|
||||
cand[ncand].dev = d;
|
||||
cand[ncand++].what = blkdev_name(d);
|
||||
}
|
||||
cand[ncand].dev = 1; cand[ncand++].what = "IDE disk 1";
|
||||
cand[ncand].dev = 0; cand[ncand++].what = "IDE disk 0";
|
||||
|
||||
for (int i = 0; i < (int)NELEM(cand); i++) {
|
||||
for (int i = 0; i < ncand; i++) {
|
||||
if (!rootdev_usable(cand[i].dev))
|
||||
continue;
|
||||
schfs_kmount(cand[i].dev);
|
||||
|
|
@ -922,7 +936,7 @@ rootdev_mount(void)
|
|||
// which is how the first version of this message came out as
|
||||
// `%-11s device 1596400`. See print_int() in kernel/core/console.c.
|
||||
cprintf("root: no SchFS volume on any candidate device. Looked at:\n");
|
||||
for (int i = 0; i < (int)NELEM(cand); i++)
|
||||
for (int i = 0; i < ncand; i++)
|
||||
cprintf(" device %d, %s: %s\n", cand[i].dev, cand[i].what,
|
||||
rootdev_usable(cand[i].dev) ? "present, but no SchFS on it"
|
||||
: "not present");
|
||||
|
|
|
|||
Loading…
Reference in a new issue