kernel/ATA+MBR: Dynamically generate device names + create devices for MBR partitions
All checks were successful
continuous-integration/drone/pr Build is passing

This commit is contained in:
apio 2023-06-16 21:30:50 +02:00
parent 72b8ebe02c
commit 738b218a49
Signed by: apio
GPG Key ID: B8A7D06E42258954
11 changed files with 161 additions and 3 deletions

View File

@ -729,11 +729,21 @@ namespace ATA
static u32 next_minor = 0; static u32 next_minor = 0;
Result<String> ATA::Drive::create_drive_name(SharedPtr<ATA::Drive> drive)
{
static u32 cd_index = 0;
static u32 sd_index = 0;
return String::format("%s%d"_sv, drive->m_is_atapi ? "cd" : "sd", drive->m_is_atapi ? cd_index++ : sd_index++);
}
Result<SharedPtr<Device>> ATADevice::create(SharedPtr<ATA::Drive> drive) Result<SharedPtr<Device>> ATADevice::create(SharedPtr<ATA::Drive> drive)
{ {
auto device = TRY(adopt_shared_if_nonnull(new (std::nothrow) ATADevice())); auto device = TRY(adopt_shared_if_nonnull(new (std::nothrow) ATADevice()));
device->m_drive = drive; device->m_drive = drive;
TRY(DeviceRegistry::register_special_device(DeviceRegistry::Disk, next_minor++, device, "cdrom", 0400)); device->m_device_path = TRY(ATA::Drive::create_drive_name(drive));
TRY(DeviceRegistry::register_special_device(DeviceRegistry::Disk, next_minor++, device,
device->m_device_path.chars(), 0400));
return (SharedPtr<Device>)device; return (SharedPtr<Device>)device;
} }

View File

@ -159,6 +159,8 @@ namespace ATA
Result<void> read_lba(u64 lba, void* out, usize nblocks); Result<void> read_lba(u64 lba, void* out, usize nblocks);
static Result<String> create_drive_name(SharedPtr<ATA::Drive> drive);
private: private:
bool identify_ata(); bool identify_ata();
@ -289,7 +291,7 @@ class ATADevice : public Device
{ {
public: public:
// Initializer for DeviceRegistry. // Initializer for DeviceRegistry.
static Result<void> create(SharedPtr<ATA::Drive> drive); static Result<SharedPtr<Device>> create(SharedPtr<ATA::Drive> drive);
Result<usize> read(u8*, usize, usize) const override; Result<usize> read(u8*, usize, usize) const override;
@ -313,9 +315,20 @@ class ATADevice : public Device
return m_drive->capacity(); return m_drive->capacity();
} }
Result<usize> block_size() const override
{
return m_drive->block_size();
}
StringView device_path() const override
{
return m_device_path.view();
}
virtual ~ATADevice() = default; virtual ~ATADevice() = default;
private: private:
ATADevice() = default; ATADevice() = default;
SharedPtr<ATA::Drive> m_drive; SharedPtr<ATA::Drive> m_drive;
String m_device_path;
}; };

View File

@ -1,19 +1,66 @@
#include "fs/MBR.h" #include "fs/MBR.h"
#include "Log.h" #include "Log.h"
#include <luna/CType.h>
static Result<String> create_partition_name(SharedPtr<Device> host_device, u32 partition_index)
{
auto host_path = host_device->device_path();
char last = host_path[host_path.length() - 1];
if (_isdigit(last)) return String::format("%sp%d"_sv, host_path.chars(), partition_index);
return String::format("%s%d"_sv, host_path.chars(), partition_index);
}
namespace MBR namespace MBR
{ {
Result<void> PartitionDevice::create(SharedPtr<Device> host_device, usize start_block, usize num_blocks,
u32 partition_index)
{
static u32 next_minor = 0;
auto device = TRY(adopt_shared_if_nonnull(new (std::nothrow) PartitionDevice()));
device->m_host_device = host_device;
device->m_start_offset = start_block * device->m_block_size;
device->m_num_blocks = num_blocks;
device->m_device_path = TRY(create_partition_name(host_device, partition_index));
return DeviceRegistry::register_special_device(DeviceRegistry::DiskPartition, next_minor++, device,
device->m_device_path.chars(), 0400);
}
Result<usize> PartitionDevice::read(u8* buf, usize offset, usize length) const
{
if (length == 0) return 0;
if (offset > size()) return 0;
if (offset + length > size()) length = size() - offset;
return m_host_device->read(buf, m_start_offset + offset, length);
}
Result<usize> PartitionDevice::write(const u8* buf, usize offset, usize length)
{
if (length == 0) return 0;
if (offset > size()) return 0;
if (offset + length > size()) length = size() - offset;
return m_host_device->write(buf, m_start_offset + offset, length);
}
Result<bool> identify(SharedPtr<Device> device) Result<bool> identify(SharedPtr<Device> device)
{ {
// Cannot read a partition table from a character device! Who is even coming up with this silliness? // Cannot read a partition table from a character device! Who is even coming up with this silliness?
if (!device->is_block_device()) return false; if (!device->is_block_device()) return false;
DiskHeader hdr; DiskHeader hdr;
usize nread = TRY(device->read((u8*)&hdr, 0, sizeof(hdr))); const usize nread = TRY(device->read((u8*)&hdr, 0, sizeof(hdr)));
check(nread == 512); check(nread == 512);
if (hdr.signature[0] != MBR_SIGNATURE_1 || hdr.signature[1] != MBR_SIGNATURE_2) return false; if (hdr.signature[0] != MBR_SIGNATURE_1 || hdr.signature[1] != MBR_SIGNATURE_2) return false;
u32 partition_index = 0;
for (int i = 0; i < 4; i++) for (int i = 0; i < 4; i++)
{ {
const auto& part = hdr.partitions[i]; const auto& part = hdr.partitions[i];
@ -22,6 +69,8 @@ namespace MBR
bool bootable = part.attributes & MBR_BOOTABLE; bool bootable = part.attributes & MBR_BOOTABLE;
kinfoln("mbr: Partition #%d is active: bootable=%d, type=%x, start=%d, sectors=%d", i, bootable, kinfoln("mbr: Partition #%d is active: bootable=%d, type=%x, start=%d, sectors=%d", i, bootable,
part.partition_type, part.start_lba, part.num_sectors); part.partition_type, part.start_lba, part.num_sectors);
TRY(PartitionDevice::create(device, part.start_lba, part.num_sectors, partition_index++));
} }
return true; return true;

View File

@ -1,6 +1,7 @@
#pragma once #pragma once
#include "fs/devices/DeviceRegistry.h" #include "fs/devices/DeviceRegistry.h"
#include <luna/String.h>
#include <luna/Types.h> #include <luna/Types.h>
#define MBR_BOOTABLE 0x80 #define MBR_BOOTABLE 0x80
@ -29,6 +30,53 @@ namespace MBR
u8 signature[2]; u8 signature[2];
}; };
class PartitionDevice : public Device
{
public:
// Initializer for DeviceRegistry.
static Result<void> create(SharedPtr<Device> host_device, usize start_block, usize num_blocks,
u32 partition_index);
Result<usize> read(u8*, usize, usize) const override;
Result<usize> write(const u8* buf, usize offset, usize length) override;
bool blocking() const override
{
return false;
}
bool is_block_device() const override
{
return true;
}
usize size() const override
{
return m_num_blocks * m_block_size;
}
Result<usize> block_size() const override
{
return m_block_size;
}
StringView device_path() const override
{
return m_device_path.view();
}
virtual ~PartitionDevice() = default;
private:
PartitionDevice() = default;
SharedPtr<Device> m_host_device;
usize m_block_size { 512ul };
usize m_start_offset;
usize m_num_blocks;
String m_device_path;
};
static_assert(sizeof(DiskHeader) == 512ul); static_assert(sizeof(DiskHeader) == 512ul);
Result<bool> identify(SharedPtr<Device> device); Result<bool> identify(SharedPtr<Device> device);

View File

@ -17,5 +17,10 @@ class ConsoleDevice : public Device
Result<u64> ioctl(int request, void* arg) override; Result<u64> ioctl(int request, void* arg) override;
StringView device_path() const override
{
return "console";
}
virtual ~ConsoleDevice() = default; virtual ~ConsoleDevice() = default;
}; };

View File

@ -1,4 +1,5 @@
#pragma once #pragma once
#include "Log.h"
#include <luna/Result.h> #include <luna/Result.h>
class Device class Device
@ -23,6 +24,17 @@ class Device
return false; return false;
} }
virtual Result<usize> block_size() const
{
// Block devices should override this function.
kwarnln("Device::block_size() was called on a character device or block device without block size");
return err(ENOTSUP);
}
// Path in devfs.
virtual StringView device_path() const = 0;
virtual bool blocking() const = 0; virtual bool blocking() const = 0;
virtual ~Device() = default; virtual ~Device() = default;

View File

@ -14,6 +14,7 @@ namespace DeviceRegistry
Memory = 2, Memory = 2,
Framebuffer = 3, Framebuffer = 3,
Disk = 4, Disk = 4,
DiskPartition = 5,
}; };
Result<SharedPtr<Device>> fetch_special_device(u32 major, u32 minor); Result<SharedPtr<Device>> fetch_special_device(u32 major, u32 minor);

View File

@ -22,5 +22,10 @@ class FramebufferDevice : public Device
usize size() const override; usize size() const override;
StringView device_path() const override
{
return "fb0";
}
virtual ~FramebufferDevice() = default; virtual ~FramebufferDevice() = default;
}; };

View File

@ -24,5 +24,10 @@ class FullDevice : public Device
return false; return false;
} }
StringView device_path() const override
{
return "full";
}
virtual ~FullDevice() = default; virtual ~FullDevice() = default;
}; };

View File

@ -22,5 +22,10 @@ class NullDevice : public Device
return false; return false;
} }
StringView device_path() const override
{
return "null";
}
virtual ~NullDevice() = default; virtual ~NullDevice() = default;
}; };

View File

@ -24,5 +24,10 @@ class ZeroDevice : public Device
return false; return false;
} }
StringView device_path() const override
{
return "zero";
}
virtual ~ZeroDevice() = default; virtual ~ZeroDevice() = default;
}; };