diff options
author | Conrad Pankoff <deoxxa@fknsrs.biz> | 2019-06-02 22:57:44 +1000 |
---|---|---|
committer | Andreas Kling <awesomekling@gmail.com> | 2019-06-02 14:57:44 +0200 |
commit | c02b8b715da8e1a6604b8b58c5c66cf44f823f77 (patch) | |
tree | 842727cb55fad1c9dd3e2fa3d1cb7df9e1356215 /Kernel/Devices | |
parent | 466a8179506647d33ee4511c6945f111d31d9500 (diff) | |
download | serenity-c02b8b715da8e1a6604b8b58c5c66cf44f823f77.zip |
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.
Diffstat (limited to 'Kernel/Devices')
-rw-r--r-- | Kernel/Devices/MBRPartitionTable.cpp | 61 | ||||
-rw-r--r-- | Kernel/Devices/MBRPartitionTable.h | 47 |
2 files changed, 108 insertions, 0 deletions
diff --git a/Kernel/Devices/MBRPartitionTable.cpp b/Kernel/Devices/MBRPartitionTable.cpp new file mode 100644 index 0000000000..369be452e1 --- /dev/null +++ b/Kernel/Devices/MBRPartitionTable.cpp @@ -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); +} diff --git a/Kernel/Devices/MBRPartitionTable.h b/Kernel/Devices/MBRPartitionTable.h new file mode 100644 index 0000000000..a3ad937b2c --- /dev/null +++ b/Kernel/Devices/MBRPartitionTable.h @@ -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]; +}; |