summaryrefslogtreecommitdiff
path: root/Kernel/Devices
diff options
context:
space:
mode:
authorConrad Pankoff <deoxxa@fknsrs.biz>2019-06-02 22:57:44 +1000
committerAndreas Kling <awesomekling@gmail.com>2019-06-02 14:57:44 +0200
commitc02b8b715da8e1a6604b8b58c5c66cf44f823f77 (patch)
tree842727cb55fad1c9dd3e2fa3d1cb7df9e1356215 /Kernel/Devices
parent466a8179506647d33ee4511c6945f111d31d9500 (diff)
downloadserenity-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.cpp61
-rw-r--r--Kernel/Devices/MBRPartitionTable.h47
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];
+};