From 0aa1f1c2d6226ee61b8db71630d571bd78758246 Mon Sep 17 00:00:00 2001 From: Conrad Pankoff Date: Tue, 4 Jun 2019 22:03:35 +1000 Subject: [PATCH] Kernel: Parse cmdline for root filesystem e.g. root=/dev/hda1 This introduces very basic handling of the kernel command line to choose the root filesystem at startup. Given that we currently only support a single IDE hard drive, it's hard-coded to look for `/dev/hda` at the start of the argument. If there is nothing following this, or if the parameter is empty, init_stage2 will try to load the ext2 filesystem from the start of the device. This is intended to be the default behaviour when running development builds, as it is faster to set up and doesn't require a working grub installation. If `/dev/hda` is followed by a number, init_stage2 will try to read an MBR partition header from the drive, then load the requested partition. It will reject non-numeric trailing data, and anything outside of partitions one through four. --- Kernel/grub.cfg | 2 +- Kernel/init.cpp | 56 ++++++++++++++++++++++++++++++++++++------------- 2 files changed, 43 insertions(+), 15 deletions(-) diff --git a/Kernel/grub.cfg b/Kernel/grub.cfg index 31a55e9aff..9348f629c9 100644 --- a/Kernel/grub.cfg +++ b/Kernel/grub.cfg @@ -2,5 +2,5 @@ timeout=0 menuentry 'Serenity' { root=hd0,1 - multiboot /boot/kernel root=hd0,1 + multiboot /boot/kernel root=/dev/hda1 } diff --git a/Kernel/init.cpp b/Kernel/init.cpp index 7939bd8670..423ca7838d 100644 --- a/Kernel/init.cpp +++ b/Kernel/init.cpp @@ -69,26 +69,54 @@ VFS* vfs; auto dev_random = make(); auto dev_ptmx = make(); - // TODO: decide what drive/partition to use based on cmdline from - // bootloader. currently hardcoded to the equivalent of hd0,1. + auto root = KParams::the().get("root"); + if (root.is_empty()) { + root = "/dev/hda"; + } + + if (!root.starts_with("/dev/hda")) { + kprintf("init_stage2: root filesystem must be on the first IDE hard drive (/dev/hda)\n"); + hang(); + } auto dev_hd0 = IDEDiskDevice::create(); - MBRPartitionTable dev_hd0pt(dev_hd0.copy_ref()); - if (!dev_hd0pt.initialize()) { - kprintf("init_stage2: couldn't read MBR from disk"); - hang(); + Retained root_dev = dev_hd0.copy_ref(); + + root = root.substring(strlen("/dev/hda"), root.length() - strlen("/dev/hda")); + + if (root.length()) { + bool ok; + unsigned partition_number = root.to_uint(ok); + + if (!ok) { + kprintf("init_stage2: couldn't parse partition number from root kernel parameter\n"); + hang(); + } + + if (partition_number < 1 || partition_number > 4) { + kprintf("init_stage2: invalid partition number %d; expected 1 to 4\n", partition_number); + hang(); + } + + MBRPartitionTable mbr(root_dev.copy_ref()); + if (!mbr.initialize()) { + kprintf("init_stage2: couldn't read MBR from disk\n"); + hang(); + } + + auto partition = mbr.partition(partition_number); + if (!partition) { + kprintf("init_stage2: couldn't get partition %d\n", partition_number); + hang(); + } + + root_dev = *partition; } - auto dev_hd0p1 = dev_hd0pt.partition(1); - if (!dev_hd0p1) { - kprintf("init_stage2: couldn't get first partition"); - hang(); - } - - auto e2fs = Ext2FS::create(*dev_hd0p1.copy_ref()); + auto e2fs = Ext2FS::create(root_dev.copy_ref()); if (!e2fs->initialize()) { - kprintf("init_stage2: couldn't open root filesystem"); + kprintf("init_stage2: couldn't open root filesystem\n"); hang(); }