kernel/ATA+MBR: Dynamically generate device names + create devices for MBR partitions
All checks were successful
continuous-integration/drone/pr Build is passing
All checks were successful
continuous-integration/drone/pr Build is passing
This commit is contained in:
parent
72b8ebe02c
commit
738b218a49
@ -729,11 +729,21 @@ namespace ATA
|
||||
|
||||
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)
|
||||
{
|
||||
auto device = TRY(adopt_shared_if_nonnull(new (std::nothrow) ATADevice()));
|
||||
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;
|
||||
}
|
||||
|
||||
|
@ -159,6 +159,8 @@ namespace ATA
|
||||
|
||||
Result<void> read_lba(u64 lba, void* out, usize nblocks);
|
||||
|
||||
static Result<String> create_drive_name(SharedPtr<ATA::Drive> drive);
|
||||
|
||||
private:
|
||||
bool identify_ata();
|
||||
|
||||
@ -289,7 +291,7 @@ class ATADevice : public Device
|
||||
{
|
||||
public:
|
||||
// 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;
|
||||
|
||||
@ -313,9 +315,20 @@ class ATADevice : public Device
|
||||
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;
|
||||
|
||||
private:
|
||||
ATADevice() = default;
|
||||
SharedPtr<ATA::Drive> m_drive;
|
||||
String m_device_path;
|
||||
};
|
||||
|
@ -1,19 +1,66 @@
|
||||
#include "fs/MBR.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
|
||||
{
|
||||
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)
|
||||
{
|
||||
// Cannot read a partition table from a character device! Who is even coming up with this silliness?
|
||||
if (!device->is_block_device()) return false;
|
||||
|
||||
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);
|
||||
|
||||
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++)
|
||||
{
|
||||
const auto& part = hdr.partitions[i];
|
||||
@ -22,6 +69,8 @@ namespace MBR
|
||||
bool bootable = part.attributes & MBR_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);
|
||||
|
||||
TRY(PartitionDevice::create(device, part.start_lba, part.num_sectors, partition_index++));
|
||||
}
|
||||
|
||||
return true;
|
||||
|
@ -1,6 +1,7 @@
|
||||
#pragma once
|
||||
|
||||
#include "fs/devices/DeviceRegistry.h"
|
||||
#include <luna/String.h>
|
||||
#include <luna/Types.h>
|
||||
|
||||
#define MBR_BOOTABLE 0x80
|
||||
@ -29,6 +30,53 @@ namespace MBR
|
||||
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);
|
||||
|
||||
Result<bool> identify(SharedPtr<Device> device);
|
||||
|
@ -17,5 +17,10 @@ class ConsoleDevice : public Device
|
||||
|
||||
Result<u64> ioctl(int request, void* arg) override;
|
||||
|
||||
StringView device_path() const override
|
||||
{
|
||||
return "console";
|
||||
}
|
||||
|
||||
virtual ~ConsoleDevice() = default;
|
||||
};
|
||||
|
@ -1,4 +1,5 @@
|
||||
#pragma once
|
||||
#include "Log.h"
|
||||
#include <luna/Result.h>
|
||||
|
||||
class Device
|
||||
@ -23,6 +24,17 @@ class Device
|
||||
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 ~Device() = default;
|
||||
|
@ -14,6 +14,7 @@ namespace DeviceRegistry
|
||||
Memory = 2,
|
||||
Framebuffer = 3,
|
||||
Disk = 4,
|
||||
DiskPartition = 5,
|
||||
};
|
||||
|
||||
Result<SharedPtr<Device>> fetch_special_device(u32 major, u32 minor);
|
||||
|
@ -22,5 +22,10 @@ class FramebufferDevice : public Device
|
||||
|
||||
usize size() const override;
|
||||
|
||||
StringView device_path() const override
|
||||
{
|
||||
return "fb0";
|
||||
}
|
||||
|
||||
virtual ~FramebufferDevice() = default;
|
||||
};
|
||||
|
@ -24,5 +24,10 @@ class FullDevice : public Device
|
||||
return false;
|
||||
}
|
||||
|
||||
StringView device_path() const override
|
||||
{
|
||||
return "full";
|
||||
}
|
||||
|
||||
virtual ~FullDevice() = default;
|
||||
};
|
||||
|
@ -22,5 +22,10 @@ class NullDevice : public Device
|
||||
return false;
|
||||
}
|
||||
|
||||
StringView device_path() const override
|
||||
{
|
||||
return "null";
|
||||
}
|
||||
|
||||
virtual ~NullDevice() = default;
|
||||
};
|
||||
|
@ -24,5 +24,10 @@ class ZeroDevice : public Device
|
||||
return false;
|
||||
}
|
||||
|
||||
StringView device_path() const override
|
||||
{
|
||||
return "zero";
|
||||
}
|
||||
|
||||
virtual ~ZeroDevice() = default;
|
||||
};
|
||||
|
Loading…
Reference in New Issue
Block a user