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;
|
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;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -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;
|
||||||
};
|
};
|
||||||
|
@ -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;
|
||||||
|
@ -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);
|
||||||
|
@ -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;
|
||||||
};
|
};
|
||||||
|
@ -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;
|
||||||
|
@ -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);
|
||||||
|
@ -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;
|
||||||
};
|
};
|
||||||
|
@ -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;
|
||||||
};
|
};
|
||||||
|
@ -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;
|
||||||
};
|
};
|
||||||
|
@ -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;
|
||||||
};
|
};
|
||||||
|
Loading…
Reference in New Issue
Block a user