mirror of
https://github.com/RGBCube/serenity
synced 2025-05-23 15:35:08 +00:00
Kernel: Implement MBR partition loader (#168)
This implements a basic MBR partition loader, which removes the reliance on a hard-coded filesystem offset in the stage2 init.
This commit is contained in:
parent
466a817950
commit
c02b8b715d
4 changed files with 133 additions and 9 deletions
61
Kernel/Devices/MBRPartitionTable.cpp
Normal file
61
Kernel/Devices/MBRPartitionTable.cpp
Normal file
|
@ -0,0 +1,61 @@
|
|||
#include <AK/ByteBuffer.h>
|
||||
#include <Kernel/Devices/MBRPartitionTable.h>
|
||||
|
||||
#define MBR_DEBUG
|
||||
|
||||
MBRPartitionTable::MBRPartitionTable(Retained<DiskDevice>&& device)
|
||||
: m_device(move(device))
|
||||
{
|
||||
}
|
||||
|
||||
MBRPartitionTable::~MBRPartitionTable()
|
||||
{
|
||||
}
|
||||
|
||||
const MBRPartitionHeader& MBRPartitionTable::header() const
|
||||
{
|
||||
return *reinterpret_cast<const MBRPartitionHeader*>(m_cached_header);
|
||||
}
|
||||
|
||||
bool MBRPartitionTable::initialize()
|
||||
{
|
||||
if (!m_device->read_block(0, m_cached_header)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
auto& header = this->header();
|
||||
|
||||
#ifdef MBR_DEBUG
|
||||
kprintf("MBRPartitionTable::initialize: mbr_signature=%#x\n", header.mbr_signature);
|
||||
#endif
|
||||
|
||||
if (header.mbr_signature != MBR_SIGNATURE) {
|
||||
kprintf("MBRPartitionTable::initialize: bad mbr signature %#x\n", header.mbr_signature);
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
RetainPtr<DiskPartition> MBRPartitionTable::partition(unsigned index)
|
||||
{
|
||||
ASSERT(index >= 1 && index <= 4);
|
||||
|
||||
auto& header = this->header();
|
||||
auto& entry = header.entry[index - 1];
|
||||
|
||||
if (header.mbr_signature != MBR_SIGNATURE) {
|
||||
kprintf("MBRPartitionTable::initialize: bad mbr signature - not initalized? %#x\n", header.mbr_signature);
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
#ifdef MBR_DEBUG
|
||||
kprintf("MBRPartitionTable::partition: status=%#x offset=%#x\n", entry.status, entry.offset);
|
||||
#endif
|
||||
|
||||
if (entry.status == 0x00) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
return DiskPartition::create(m_device.copy_ref(), entry.offset);
|
||||
}
|
47
Kernel/Devices/MBRPartitionTable.h
Normal file
47
Kernel/Devices/MBRPartitionTable.h
Normal file
|
@ -0,0 +1,47 @@
|
|||
#pragma once
|
||||
|
||||
#include <AK/RetainPtr.h>
|
||||
#include <AK/Vector.h>
|
||||
#include <Kernel/Devices/DiskDevice.h>
|
||||
#include <Kernel/Devices/DiskPartition.h>
|
||||
|
||||
#define MBR_SIGNATURE 0xaa55
|
||||
|
||||
struct MBRPartitionEntry {
|
||||
byte status;
|
||||
byte chs1[3];
|
||||
byte type;
|
||||
byte chs2[3];
|
||||
dword offset;
|
||||
dword length;
|
||||
} __attribute__((packed));
|
||||
|
||||
struct MBRPartitionHeader {
|
||||
byte code1[218];
|
||||
word ts_zero;
|
||||
byte ts_drive, ts_seconds, ts_minutes, ts_hours;
|
||||
byte code2[216];
|
||||
dword disk_signature;
|
||||
word disk_signature_zero;
|
||||
MBRPartitionEntry entry[4];
|
||||
word mbr_signature;
|
||||
} __attribute__((packed));
|
||||
|
||||
class MBRPartitionTable {
|
||||
AK_MAKE_ETERNAL
|
||||
|
||||
public:
|
||||
MBRPartitionTable(Retained<DiskDevice>&& device);
|
||||
~MBRPartitionTable();
|
||||
|
||||
bool initialize();
|
||||
RetainPtr<DiskPartition> partition(unsigned index);
|
||||
|
||||
private:
|
||||
Retained<DiskDevice> m_device;
|
||||
|
||||
ByteBuffer read_header() const;
|
||||
const MBRPartitionHeader& header() const;
|
||||
|
||||
byte m_cached_header[512];
|
||||
};
|
|
@ -66,6 +66,7 @@ VFS_OBJS = \
|
|||
Devices/RandomDevice.o \
|
||||
Devices/DebugLogDevice.o \
|
||||
Devices/DiskPartition.o \
|
||||
Devices/MBRPartitionTable.o \
|
||||
FileSystem/FileSystem.o \
|
||||
FileSystem/DiskBackedFileSystem.o \
|
||||
FileSystem/Ext2FileSystem.o \
|
||||
|
|
|
@ -6,6 +6,7 @@
|
|||
#include "Process.h"
|
||||
#include "PIC.h"
|
||||
#include <Kernel/Devices/IDEDiskDevice.h>
|
||||
#include <Kernel/Devices/MBRPartitionTable.h>
|
||||
#include <Kernel/Devices/DiskPartition.h>
|
||||
#include "KSyms.h"
|
||||
#include <Kernel/Devices/NullDevice.h>
|
||||
|
@ -58,11 +59,6 @@ VFS* vfs;
|
|||
}
|
||||
#endif
|
||||
|
||||
// TODO: delete this magic number. this block offset corresponds to a
|
||||
// partition that starts at 32k into an MBR disk. this value is also specified
|
||||
// in sync.sh, but should ideally be read from the MBR header at startup.
|
||||
#define PARTITION_OFFSET 62
|
||||
|
||||
[[noreturn]] static void init_stage2()
|
||||
{
|
||||
Syscall::initialize();
|
||||
|
@ -71,10 +67,29 @@ VFS* vfs;
|
|||
auto dev_full = make<FullDevice>();
|
||||
auto dev_random = make<RandomDevice>();
|
||||
auto dev_ptmx = make<PTYMultiplexer>();
|
||||
|
||||
// TODO: decide what drive/partition to use based on cmdline from
|
||||
// bootloader. currently hardcoded to the equivalent of hd0,1.
|
||||
|
||||
auto dev_hd0 = IDEDiskDevice::create();
|
||||
auto dev_hd0p1 = DiskPartition::create(dev_hd0.copy_ref(), PARTITION_OFFSET);
|
||||
auto e2fs = Ext2FS::create(dev_hd0p1.copy_ref());
|
||||
e2fs->initialize();
|
||||
|
||||
MBRPartitionTable dev_hd0pt(dev_hd0.copy_ref());
|
||||
if (!dev_hd0pt.initialize()) {
|
||||
kprintf("init_stage2: couldn't read MBR from disk");
|
||||
hang();
|
||||
}
|
||||
|
||||
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());
|
||||
if (!e2fs->initialize()) {
|
||||
kprintf("init_stage2: couldn't open root filesystem");
|
||||
hang();
|
||||
}
|
||||
|
||||
vfs->mount_root(e2fs.copy_ref());
|
||||
|
||||
|
@ -89,7 +104,7 @@ VFS* vfs;
|
|||
|
||||
auto* system_server_process = Process::create_user_process("/bin/SystemServer", (uid_t)100, (gid_t)100, (pid_t)0, error, { }, { }, tty0);
|
||||
if (error != 0) {
|
||||
dbgprintf("error spawning SystemServer: %d\n", error);
|
||||
dbgprintf("init_stage2: error spawning SystemServer: %d\n", error);
|
||||
hang();
|
||||
}
|
||||
system_server_process->set_priority(Process::HighPriority);
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue