Compare commits
7 Commits
5e9b21bdce
...
d98782a10c
Author | SHA1 | Date |
---|---|---|
Bananymous | d98782a10c | |
Bananymous | f86c9584f9 | |
Bananymous | 52807366bf | |
Bananymous | b437d4eb41 | |
Bananymous | 8b7f3f1fb2 | |
Bananymous | c607f5385e | |
Bananymous | 543a8bd7c6 |
|
@ -0,0 +1,25 @@
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <BAN/Optional.h>
|
||||||
|
#include <BAN/StringView.h>
|
||||||
|
|
||||||
|
#include <string.h>
|
||||||
|
|
||||||
|
namespace BAN
|
||||||
|
{
|
||||||
|
|
||||||
|
struct GUID
|
||||||
|
{
|
||||||
|
uint32_t component1 { 0 };
|
||||||
|
uint16_t component2 { 0 };
|
||||||
|
uint16_t component3 { 0 };
|
||||||
|
uint8_t component45[8] { };
|
||||||
|
|
||||||
|
bool operator==(const GUID& other) const
|
||||||
|
{
|
||||||
|
return memcmp(this, &other, sizeof(GUID)) == 0;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
static_assert(sizeof(GUID) == 16);
|
||||||
|
|
||||||
|
}
|
|
@ -41,7 +41,7 @@ read_from_disk:
|
||||||
call drive_has_int13_ext
|
call drive_has_int13_ext
|
||||||
|
|
||||||
# prepare disk read packet
|
# prepare disk read packet
|
||||||
mov $disk_address_packet, %si
|
movw $disk_address_packet, %si
|
||||||
movb $0x10, 0x00(%si) # packet size
|
movb $0x10, 0x00(%si) # packet size
|
||||||
movb $0x00, 0x01(%si) # always 0
|
movb $0x00, 0x01(%si) # always 0
|
||||||
movw %cx, 0x02(%si) # lba count
|
movw %cx, 0x02(%si) # lba count
|
||||||
|
|
|
@ -236,6 +236,10 @@ ext2_read_inode:
|
||||||
movl (ext2_inode_size), %ecx
|
movl (ext2_inode_size), %ecx
|
||||||
rep movsb
|
rep movsb
|
||||||
|
|
||||||
|
# reset indirect cache to zero
|
||||||
|
movl $0, (ext2_inode_indirect_number)
|
||||||
|
|
||||||
|
.ext2_read_inode_done:
|
||||||
popal
|
popal
|
||||||
ret
|
ret
|
||||||
|
|
||||||
|
@ -249,6 +253,7 @@ ext2_data_block_index:
|
||||||
pushl %ecx
|
pushl %ecx
|
||||||
pushl %edx
|
pushl %edx
|
||||||
pushl %esi
|
pushl %esi
|
||||||
|
pushl %edi
|
||||||
|
|
||||||
# calculate max data blocks
|
# calculate max data blocks
|
||||||
movl (ext2_inode_buffer + i_size), %ecx
|
movl (ext2_inode_buffer + i_size), %ecx
|
||||||
|
@ -309,6 +314,25 @@ ext2_data_block_index:
|
||||||
# ebx := index
|
# ebx := index
|
||||||
# cx := depth
|
# cx := depth
|
||||||
.ext2_data_block_index_indirect:
|
.ext2_data_block_index_indirect:
|
||||||
|
# calculate cache index ((index & 0xFF) | depth)
|
||||||
|
movl %ebx, %edx
|
||||||
|
andl $(~(EXT2_BLOCK_SIZE / 4 - 1)), %edx
|
||||||
|
orw %cx, %dx
|
||||||
|
|
||||||
|
# check whether this block is already cached
|
||||||
|
cmpl $0, (ext2_inode_indirect_number)
|
||||||
|
je .ext2_data_block_index_indirect_no_cache
|
||||||
|
cmpl %edx, (ext2_inode_indirect_number)
|
||||||
|
je .ext2_data_block_index_indirect_cached
|
||||||
|
|
||||||
|
.ext2_data_block_index_indirect_no_cache:
|
||||||
|
# update cache block number, will be cached when found
|
||||||
|
movl %edx, (ext2_inode_indirect_number)
|
||||||
|
|
||||||
|
# eax := current block
|
||||||
|
# ebx := index
|
||||||
|
# cx := depth
|
||||||
|
.ext2_data_block_index_indirect_loop:
|
||||||
call ext2_read_block
|
call ext2_read_block
|
||||||
|
|
||||||
# store depth and index
|
# store depth and index
|
||||||
|
@ -342,7 +366,13 @@ ext2_data_block_index:
|
||||||
popl %ebx
|
popl %ebx
|
||||||
popw %cx
|
popw %cx
|
||||||
|
|
||||||
loop .ext2_data_block_index_indirect
|
loop .ext2_data_block_index_indirect_loop
|
||||||
|
|
||||||
|
# cache last read block
|
||||||
|
movw $ext2_block_buffer, %si
|
||||||
|
movw $ext2_inode_indirect_buffer, %di
|
||||||
|
movw $EXT2_BLOCK_SIZE, %cx
|
||||||
|
rep movsb
|
||||||
|
|
||||||
jmp .ext2_data_block_index_done
|
jmp .ext2_data_block_index_done
|
||||||
|
|
||||||
|
@ -358,7 +388,13 @@ ext2_data_block_index:
|
||||||
movl $0, %eax
|
movl $0, %eax
|
||||||
jmp .ext2_data_block_index_done
|
jmp .ext2_data_block_index_done
|
||||||
|
|
||||||
|
.ext2_data_block_index_indirect_cached:
|
||||||
|
movl $ext2_inode_indirect_buffer, %esi
|
||||||
|
andl $(EXT2_BLOCK_SIZE / 4 - 1), %ebx
|
||||||
|
movl (%esi, %ebx, 4), %eax
|
||||||
|
|
||||||
.ext2_data_block_index_done:
|
.ext2_data_block_index_done:
|
||||||
|
popl %edi
|
||||||
popl %esi
|
popl %esi
|
||||||
popl %edx
|
popl %edx
|
||||||
popl %ecx
|
popl %ecx
|
||||||
|
@ -681,9 +717,15 @@ ext2_looking_for_msg:
|
||||||
|
|
||||||
.section .bss
|
.section .bss
|
||||||
|
|
||||||
|
.align EXT2_BLOCK_SIZE
|
||||||
ext2_block_buffer:
|
ext2_block_buffer:
|
||||||
.skip EXT2_BLOCK_SIZE
|
.skip EXT2_BLOCK_SIZE
|
||||||
|
|
||||||
|
ext2_inode_indirect_buffer:
|
||||||
|
.skip EXT2_BLOCK_SIZE
|
||||||
|
ext2_inode_indirect_number:
|
||||||
|
.skip 4
|
||||||
|
|
||||||
ext2_partition_first_sector:
|
ext2_partition_first_sector:
|
||||||
.skip 8
|
.skip 8
|
||||||
|
|
||||||
|
|
|
@ -59,6 +59,7 @@ set(KERNEL_SOURCES
|
||||||
kernel/Storage/ATA/ATAController.cpp
|
kernel/Storage/ATA/ATAController.cpp
|
||||||
kernel/Storage/ATA/ATADevice.cpp
|
kernel/Storage/ATA/ATADevice.cpp
|
||||||
kernel/Storage/DiskCache.cpp
|
kernel/Storage/DiskCache.cpp
|
||||||
|
kernel/Storage/Partition.cpp
|
||||||
kernel/Storage/StorageDevice.cpp
|
kernel/Storage/StorageDevice.cpp
|
||||||
kernel/Syscall.cpp
|
kernel/Syscall.cpp
|
||||||
kernel/Syscall.S
|
kernel/Syscall.S
|
||||||
|
|
|
@ -25,6 +25,12 @@ namespace Kernel
|
||||||
|
|
||||||
class BlockDevice : public Device
|
class BlockDevice : public Device
|
||||||
{
|
{
|
||||||
|
public:
|
||||||
|
virtual BAN::ErrorOr<void> read_blocks(uint64_t first_block, size_t block_count, BAN::ByteSpan) = 0;
|
||||||
|
virtual BAN::ErrorOr<void> write_blocks(uint64_t first_block, size_t block_count, BAN::ConstByteSpan) = 0;
|
||||||
|
|
||||||
|
virtual blksize_t blksize() const = 0;
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
BlockDevice(mode_t mode, uid_t uid, gid_t gid)
|
BlockDevice(mode_t mode, uid_t uid, gid_t gid)
|
||||||
: Device(mode, uid, gid)
|
: Device(mode, uid, gid)
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include <BAN/HashMap.h>
|
#include <BAN/HashMap.h>
|
||||||
#include <kernel/Storage/StorageDevice.h>
|
#include <kernel/Device/Device.h>
|
||||||
#include <kernel/FS/FileSystem.h>
|
#include <kernel/FS/FileSystem.h>
|
||||||
#include <kernel/FS/Ext2/Inode.h>
|
#include <kernel/FS/Ext2/Inode.h>
|
||||||
|
|
||||||
|
@ -45,13 +45,13 @@ namespace Kernel
|
||||||
};
|
};
|
||||||
|
|
||||||
public:
|
public:
|
||||||
static BAN::ErrorOr<Ext2FS*> create(Partition&);
|
static BAN::ErrorOr<Ext2FS*> create(BAN::RefPtr<BlockDevice>);
|
||||||
|
|
||||||
virtual BAN::RefPtr<Inode> root_inode() override { return m_root_inode; }
|
virtual BAN::RefPtr<Inode> root_inode() override { return m_root_inode; }
|
||||||
|
|
||||||
private:
|
private:
|
||||||
Ext2FS(Partition& partition)
|
Ext2FS(BAN::RefPtr<BlockDevice> block_device)
|
||||||
: m_partition(partition)
|
: m_block_device(block_device)
|
||||||
{}
|
{}
|
||||||
|
|
||||||
BAN::ErrorOr<void> initialize_superblock();
|
BAN::ErrorOr<void> initialize_superblock();
|
||||||
|
@ -106,7 +106,7 @@ namespace Kernel
|
||||||
private:
|
private:
|
||||||
RecursiveSpinLock m_lock;
|
RecursiveSpinLock m_lock;
|
||||||
|
|
||||||
Partition& m_partition;
|
BAN::RefPtr<BlockDevice> m_block_device;
|
||||||
|
|
||||||
BAN::RefPtr<Inode> m_root_inode;
|
BAN::RefPtr<Inode> m_root_inode;
|
||||||
BAN::Vector<uint32_t> m_superblock_backups;
|
BAN::Vector<uint32_t> m_superblock_backups;
|
||||||
|
|
|
@ -24,19 +24,19 @@ namespace Kernel
|
||||||
class TmpInode : public Inode
|
class TmpInode : public Inode
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
virtual ino_t ino() const override final { return m_ino; }
|
virtual ino_t ino() const override { return m_ino; }
|
||||||
virtual Mode mode() const override final { return Mode(m_inode_info.mode); }
|
virtual Mode mode() const override { return Mode(m_inode_info.mode); }
|
||||||
virtual nlink_t nlink() const override final { return m_inode_info.nlink; }
|
virtual nlink_t nlink() const override { return m_inode_info.nlink; }
|
||||||
virtual uid_t uid() const override { return m_inode_info.uid; }
|
virtual uid_t uid() const override { return m_inode_info.uid; }
|
||||||
virtual gid_t gid() const override { return m_inode_info.gid; }
|
virtual gid_t gid() const override { return m_inode_info.gid; }
|
||||||
virtual off_t size() const override final { return m_inode_info.size; }
|
virtual off_t size() const override { return m_inode_info.size; }
|
||||||
virtual timespec atime() const override final { return m_inode_info.atime; }
|
virtual timespec atime() const override { return m_inode_info.atime; }
|
||||||
virtual timespec mtime() const override final { return m_inode_info.mtime; }
|
virtual timespec mtime() const override { return m_inode_info.mtime; }
|
||||||
virtual timespec ctime() const override final { return m_inode_info.ctime; }
|
virtual timespec ctime() const override { return m_inode_info.ctime; }
|
||||||
virtual blksize_t blksize() const override final { return PAGE_SIZE; }
|
virtual blksize_t blksize() const override { return PAGE_SIZE; }
|
||||||
virtual blkcnt_t blocks() const override final { return m_inode_info.blocks; }
|
virtual blkcnt_t blocks() const override { return m_inode_info.blocks; }
|
||||||
virtual dev_t dev() const override { return 0; } // TODO
|
virtual dev_t dev() const override { return 0; } // TODO
|
||||||
virtual dev_t rdev() const override { return 0; } // TODO
|
virtual dev_t rdev() const override { return 0; } // TODO
|
||||||
|
|
||||||
public:
|
public:
|
||||||
static BAN::ErrorOr<BAN::RefPtr<TmpInode>> create_from_existing(TmpFileSystem&, ino_t, const TmpInodeInfo&);
|
static BAN::ErrorOr<BAN::RefPtr<TmpInode>> create_from_existing(TmpFileSystem&, ino_t, const TmpInodeInfo&);
|
||||||
|
|
|
@ -0,0 +1,53 @@
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <BAN/GUID.h>
|
||||||
|
#include <kernel/Device/Device.h>
|
||||||
|
|
||||||
|
namespace Kernel
|
||||||
|
{
|
||||||
|
|
||||||
|
class Partition final : public BlockDevice
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
static BAN::ErrorOr<BAN::RefPtr<Partition>> create(BAN::RefPtr<BlockDevice>, const BAN::GUID& type, const BAN::GUID& guid, uint64_t first_block, uint64_t last_block, uint64_t attr, const char* label, uint32_t index);
|
||||||
|
|
||||||
|
const BAN::GUID& partition_type() const { return m_type; }
|
||||||
|
const BAN::GUID& partition_guid() const { return m_guid; }
|
||||||
|
const BAN::RefPtr<BlockDevice> device() const { return m_device; }
|
||||||
|
|
||||||
|
virtual blksize_t blksize() const { return m_device->blksize(); }
|
||||||
|
|
||||||
|
BAN::ErrorOr<void> read_sectors(uint64_t first_block, size_t block_count, BAN::ByteSpan buffer) { return read_blocks(first_block, block_count, buffer); }
|
||||||
|
BAN::ErrorOr<void> write_sectors(uint64_t first_block, size_t block_count, BAN::ConstByteSpan buffer) { return write_blocks(first_block, block_count, buffer); }
|
||||||
|
|
||||||
|
virtual BAN::ErrorOr<void> read_blocks(uint64_t first_block, size_t block_count, BAN::ByteSpan) override;
|
||||||
|
virtual BAN::ErrorOr<void> write_blocks(uint64_t first_block, size_t block_count, BAN::ConstByteSpan) override;
|
||||||
|
|
||||||
|
virtual BAN::StringView name() const override { return m_name; }
|
||||||
|
|
||||||
|
private:
|
||||||
|
Partition(BAN::RefPtr<BlockDevice>, const BAN::GUID&, const BAN::GUID&, uint64_t, uint64_t, uint64_t, const char*, uint32_t);
|
||||||
|
|
||||||
|
private:
|
||||||
|
BAN::RefPtr<BlockDevice> m_device;
|
||||||
|
const BAN::GUID m_type;
|
||||||
|
const BAN::GUID m_guid;
|
||||||
|
const uint64_t m_first_block;
|
||||||
|
const uint64_t m_last_block;
|
||||||
|
const uint64_t m_attributes;
|
||||||
|
char m_label[36 * 4 + 1];
|
||||||
|
const BAN::String m_name;
|
||||||
|
|
||||||
|
public:
|
||||||
|
virtual bool is_partition() const override { return true; }
|
||||||
|
|
||||||
|
virtual dev_t rdev() const override { return m_rdev; }
|
||||||
|
|
||||||
|
protected:
|
||||||
|
virtual BAN::ErrorOr<size_t> read_impl(off_t, BAN::ByteSpan) override;
|
||||||
|
|
||||||
|
private:
|
||||||
|
const dev_t m_rdev;
|
||||||
|
};
|
||||||
|
|
||||||
|
}
|
|
@ -3,63 +3,11 @@
|
||||||
#include <BAN/Vector.h>
|
#include <BAN/Vector.h>
|
||||||
#include <kernel/Device/Device.h>
|
#include <kernel/Device/Device.h>
|
||||||
#include <kernel/Storage/DiskCache.h>
|
#include <kernel/Storage/DiskCache.h>
|
||||||
|
#include <kernel/Storage/Partition.h>
|
||||||
|
|
||||||
namespace Kernel
|
namespace Kernel
|
||||||
{
|
{
|
||||||
|
|
||||||
struct GUID
|
|
||||||
{
|
|
||||||
uint32_t data1;
|
|
||||||
uint16_t data2;
|
|
||||||
uint16_t data3;
|
|
||||||
uint8_t data4[8];
|
|
||||||
};
|
|
||||||
|
|
||||||
class StorageDevice;
|
|
||||||
|
|
||||||
class Partition final : public BlockDevice
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
static BAN::ErrorOr<BAN::RefPtr<Partition>> create(StorageDevice&, const GUID& type, const GUID& guid, uint64_t start, uint64_t end, uint64_t attr, const char* label, uint32_t index);
|
|
||||||
|
|
||||||
const GUID& partition_type() const { return m_type; }
|
|
||||||
const GUID& partition_guid() const { return m_guid; }
|
|
||||||
uint64_t lba_start() const { return m_lba_start; }
|
|
||||||
uint64_t lba_end() const { return m_lba_end; }
|
|
||||||
uint64_t attributes() const { return m_attributes; }
|
|
||||||
const char* label() const { return m_label; }
|
|
||||||
const StorageDevice& device() const { return m_device; }
|
|
||||||
|
|
||||||
BAN::ErrorOr<void> read_sectors(uint64_t lba, uint8_t sector_count, BAN::ByteSpan);
|
|
||||||
BAN::ErrorOr<void> write_sectors(uint64_t lba, uint8_t sector_count, BAN::ConstByteSpan);
|
|
||||||
|
|
||||||
virtual BAN::StringView name() const override { return m_name; }
|
|
||||||
|
|
||||||
private:
|
|
||||||
Partition(StorageDevice&, const GUID&, const GUID&, uint64_t, uint64_t, uint64_t, const char*, uint32_t);
|
|
||||||
|
|
||||||
private:
|
|
||||||
StorageDevice& m_device;
|
|
||||||
const GUID m_type;
|
|
||||||
const GUID m_guid;
|
|
||||||
const uint64_t m_lba_start;
|
|
||||||
const uint64_t m_lba_end;
|
|
||||||
const uint64_t m_attributes;
|
|
||||||
char m_label[36 * 4 + 1];
|
|
||||||
const BAN::String m_name;
|
|
||||||
|
|
||||||
public:
|
|
||||||
virtual bool is_partition() const override { return true; }
|
|
||||||
|
|
||||||
virtual dev_t rdev() const override { return m_rdev; }
|
|
||||||
|
|
||||||
protected:
|
|
||||||
virtual BAN::ErrorOr<size_t> read_impl(off_t, BAN::ByteSpan) override;
|
|
||||||
|
|
||||||
private:
|
|
||||||
const dev_t m_rdev;
|
|
||||||
};
|
|
||||||
|
|
||||||
class StorageDevice : public BlockDevice
|
class StorageDevice : public BlockDevice
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
|
@ -70,9 +18,13 @@ namespace Kernel
|
||||||
|
|
||||||
BAN::ErrorOr<void> initialize_partitions();
|
BAN::ErrorOr<void> initialize_partitions();
|
||||||
|
|
||||||
BAN::ErrorOr<void> read_sectors(uint64_t lba, uint64_t sector_count, BAN::ByteSpan);
|
virtual BAN::ErrorOr<void> read_blocks(uint64_t lba, size_t sector_count, BAN::ByteSpan buffer) override { return read_sectors(lba, sector_count, buffer); }
|
||||||
BAN::ErrorOr<void> write_sectors(uint64_t lba, uint64_t sector_count, BAN::ConstByteSpan);
|
virtual BAN::ErrorOr<void> write_blocks(uint64_t lba, size_t sector_count, BAN::ConstByteSpan buffer) override { return write_sectors(lba, sector_count, buffer); }
|
||||||
|
|
||||||
|
BAN::ErrorOr<void> read_sectors(uint64_t lba, size_t sector_count, BAN::ByteSpan);
|
||||||
|
BAN::ErrorOr<void> write_sectors(uint64_t lba, size_t sector_count, BAN::ConstByteSpan);
|
||||||
|
|
||||||
|
virtual blksize_t blksize() const { return sector_size(); }
|
||||||
virtual uint32_t sector_size() const = 0;
|
virtual uint32_t sector_size() const = 0;
|
||||||
virtual uint64_t total_size() const = 0;
|
virtual uint64_t total_size() const = 0;
|
||||||
|
|
||||||
|
|
|
@ -9,9 +9,9 @@
|
||||||
namespace Kernel
|
namespace Kernel
|
||||||
{
|
{
|
||||||
|
|
||||||
BAN::ErrorOr<Ext2FS*> Ext2FS::create(Partition& partition)
|
BAN::ErrorOr<Ext2FS*> Ext2FS::create(BAN::RefPtr<BlockDevice> block_device)
|
||||||
{
|
{
|
||||||
Ext2FS* ext2fs = new Ext2FS(partition);
|
Ext2FS* ext2fs = new Ext2FS(block_device);
|
||||||
if (ext2fs == nullptr)
|
if (ext2fs == nullptr)
|
||||||
return BAN::Error::from_errno(ENOMEM);
|
return BAN::Error::from_errno(ENOMEM);
|
||||||
BAN::ScopeGuard guard([ext2fs] { delete ext2fs; });
|
BAN::ScopeGuard guard([ext2fs] { delete ext2fs; });
|
||||||
|
@ -25,7 +25,7 @@ namespace Kernel
|
||||||
{
|
{
|
||||||
// Read superblock from disk
|
// Read superblock from disk
|
||||||
{
|
{
|
||||||
const uint32_t sector_size = m_partition.device().sector_size();
|
const uint32_t sector_size = m_block_device->blksize();
|
||||||
ASSERT(1024 % sector_size == 0);
|
ASSERT(1024 % sector_size == 0);
|
||||||
|
|
||||||
const uint32_t lba = 1024 / sector_size;
|
const uint32_t lba = 1024 / sector_size;
|
||||||
|
@ -34,7 +34,7 @@ namespace Kernel
|
||||||
BAN::Vector<uint8_t> superblock_buffer;
|
BAN::Vector<uint8_t> superblock_buffer;
|
||||||
TRY(superblock_buffer.resize(sector_count * sector_size));
|
TRY(superblock_buffer.resize(sector_count * sector_size));
|
||||||
|
|
||||||
TRY(m_partition.read_sectors(lba, sector_count, superblock_buffer.span()));
|
TRY(m_block_device->read_blocks(lba, sector_count, superblock_buffer.span()));
|
||||||
|
|
||||||
memcpy(&m_superblock, superblock_buffer.data(), sizeof(Ext2::Superblock));
|
memcpy(&m_superblock, superblock_buffer.data(), sizeof(Ext2::Superblock));
|
||||||
}
|
}
|
||||||
|
@ -272,35 +272,35 @@ namespace Kernel
|
||||||
{
|
{
|
||||||
LockGuard _(m_lock);
|
LockGuard _(m_lock);
|
||||||
|
|
||||||
const uint32_t sector_size = m_partition.device().sector_size();
|
const uint32_t sector_size = m_block_device->blksize();
|
||||||
const uint32_t block_size = this->block_size();
|
const uint32_t block_size = this->block_size();
|
||||||
const uint32_t sectors_per_block = block_size / sector_size;
|
const uint32_t sectors_per_block = block_size / sector_size;
|
||||||
const uint32_t sectors_before = 2048 / sector_size;
|
const uint32_t sectors_before = 2048 / sector_size;
|
||||||
|
|
||||||
ASSERT(block >= 2);
|
ASSERT(block >= 2);
|
||||||
ASSERT(buffer.size() >= block_size);
|
ASSERT(buffer.size() >= block_size);
|
||||||
MUST(m_partition.read_sectors(sectors_before + (block - 2) * sectors_per_block, sectors_per_block, buffer.span()));
|
MUST(m_block_device->read_blocks(sectors_before + (block - 2) * sectors_per_block, sectors_per_block, buffer.span()));
|
||||||
}
|
}
|
||||||
|
|
||||||
void Ext2FS::write_block(uint32_t block, const BlockBufferWrapper& buffer)
|
void Ext2FS::write_block(uint32_t block, const BlockBufferWrapper& buffer)
|
||||||
{
|
{
|
||||||
LockGuard _(m_lock);
|
LockGuard _(m_lock);
|
||||||
|
|
||||||
const uint32_t sector_size = m_partition.device().sector_size();
|
const uint32_t sector_size = m_block_device->blksize();
|
||||||
const uint32_t block_size = this->block_size();
|
const uint32_t block_size = this->block_size();
|
||||||
const uint32_t sectors_per_block = block_size / sector_size;
|
const uint32_t sectors_per_block = block_size / sector_size;
|
||||||
const uint32_t sectors_before = 2048 / sector_size;
|
const uint32_t sectors_before = 2048 / sector_size;
|
||||||
|
|
||||||
ASSERT(block >= 2);
|
ASSERT(block >= 2);
|
||||||
ASSERT(buffer.size() >= block_size);
|
ASSERT(buffer.size() >= block_size);
|
||||||
MUST(m_partition.write_sectors(sectors_before + (block - 2) * sectors_per_block, sectors_per_block, buffer.span()));
|
MUST(m_block_device->write_blocks(sectors_before + (block - 2) * sectors_per_block, sectors_per_block, buffer.span()));
|
||||||
}
|
}
|
||||||
|
|
||||||
void Ext2FS::sync_superblock()
|
void Ext2FS::sync_superblock()
|
||||||
{
|
{
|
||||||
LockGuard _(m_lock);
|
LockGuard _(m_lock);
|
||||||
|
|
||||||
const uint32_t sector_size = m_partition.device().sector_size();
|
const uint32_t sector_size = m_block_device->blksize();
|
||||||
ASSERT(1024 % sector_size == 0);
|
ASSERT(1024 % sector_size == 0);
|
||||||
|
|
||||||
const uint32_t superblock_bytes =
|
const uint32_t superblock_bytes =
|
||||||
|
@ -313,11 +313,11 @@ namespace Kernel
|
||||||
|
|
||||||
auto superblock_buffer = get_block_buffer();
|
auto superblock_buffer = get_block_buffer();
|
||||||
|
|
||||||
MUST(m_partition.read_sectors(lba, sector_count, superblock_buffer.span()));
|
MUST(m_block_device->read_blocks(lba, sector_count, superblock_buffer.span()));
|
||||||
if (memcmp(superblock_buffer.data(), &m_superblock, superblock_bytes))
|
if (memcmp(superblock_buffer.data(), &m_superblock, superblock_bytes))
|
||||||
{
|
{
|
||||||
memcpy(superblock_buffer.data(), &m_superblock, superblock_bytes);
|
memcpy(superblock_buffer.data(), &m_superblock, superblock_bytes);
|
||||||
MUST(m_partition.write_sectors(lba, sector_count, superblock_buffer.span()));
|
MUST(m_block_device->write_blocks(lba, sector_count, superblock_buffer.span()));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -23,7 +23,9 @@ namespace Kernel
|
||||||
root = root.substring(5);
|
root = root.substring(5);
|
||||||
|
|
||||||
auto partition_inode = MUST(DevFileSystem::get().root_inode()->find_inode(root));
|
auto partition_inode = MUST(DevFileSystem::get().root_inode()->find_inode(root));
|
||||||
s_instance->m_root_fs = MUST(Ext2FS::create(*(Partition*)partition_inode.ptr()));
|
if (!partition_inode->is_device() || !reinterpret_cast<Device*>(partition_inode.ptr())->is_partition())
|
||||||
|
Kernel::panic("Specified root '/dev/{}' does not name a partition", root);
|
||||||
|
s_instance->m_root_fs = MUST(Ext2FS::create(reinterpret_cast<BlockDevice*>(partition_inode.ptr())));
|
||||||
|
|
||||||
Credentials root_creds { 0, 0, 0, 0 };
|
Credentials root_creds { 0, 0, 0, 0 };
|
||||||
MUST(s_instance->mount(root_creds, &DevFileSystem::get(), "/dev"sv));
|
MUST(s_instance->mount(root_creds, &DevFileSystem::get(), "/dev"sv));
|
||||||
|
@ -40,17 +42,18 @@ namespace Kernel
|
||||||
return *s_instance;
|
return *s_instance;
|
||||||
}
|
}
|
||||||
|
|
||||||
BAN::ErrorOr<void> VirtualFileSystem::mount(const Credentials& credentials, BAN::StringView partition, BAN::StringView target)
|
BAN::ErrorOr<void> VirtualFileSystem::mount(const Credentials& credentials, BAN::StringView block_device_path, BAN::StringView target)
|
||||||
{
|
{
|
||||||
auto partition_file = TRY(file_from_absolute_path(credentials, partition, true));
|
auto block_device_file = TRY(file_from_absolute_path(credentials, block_device_path, true));
|
||||||
if (!partition_file.inode->is_device())
|
if (!block_device_file.inode->is_device())
|
||||||
return BAN::Error::from_errno(ENOTBLK);
|
return BAN::Error::from_errno(ENOTBLK);
|
||||||
|
|
||||||
Device* device = (Device*)partition_file.inode.ptr();
|
auto* device = reinterpret_cast<Device*>(block_device_file.inode.ptr());
|
||||||
if (!device->is_partition())
|
if (!device->mode().ifblk())
|
||||||
return BAN::Error::from_errno(ENOTBLK);
|
return BAN::Error::from_errno(ENOTBLK);
|
||||||
|
|
||||||
auto* file_system = TRY(Ext2FS::create(*(Partition*)device));
|
auto* block_device = reinterpret_cast<BlockDevice*>(device);
|
||||||
|
auto* file_system = TRY(Ext2FS::create(block_device));
|
||||||
return mount(credentials, file_system, target);
|
return mount(credentials, file_system, target);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,70 @@
|
||||||
|
#include <kernel/Storage/Partition.h>
|
||||||
|
|
||||||
|
#include <sys/sysmacros.h>
|
||||||
|
|
||||||
|
namespace Kernel
|
||||||
|
{
|
||||||
|
|
||||||
|
BAN::ErrorOr<BAN::RefPtr<Partition>> Partition::create(BAN::RefPtr<BlockDevice> device, const BAN::GUID& type, const BAN::GUID& guid, uint64_t first_block, uint64_t last_block, uint64_t attr, const char* label, uint32_t index)
|
||||||
|
{
|
||||||
|
auto partition_ptr = new Partition(device, type, guid, first_block, last_block, attr, label, index);
|
||||||
|
if (partition_ptr == nullptr)
|
||||||
|
return BAN::Error::from_errno(ENOMEM);
|
||||||
|
return BAN::RefPtr<Partition>::adopt(partition_ptr);
|
||||||
|
}
|
||||||
|
|
||||||
|
Partition::Partition(BAN::RefPtr<BlockDevice> device, const BAN::GUID& type, const BAN::GUID& guid, uint64_t first_block, uint64_t last_block, uint64_t attr, const char* label, uint32_t index)
|
||||||
|
: BlockDevice(0660, 0, 0)
|
||||||
|
, m_device(device)
|
||||||
|
, m_type(type)
|
||||||
|
, m_guid(guid)
|
||||||
|
, m_first_block(first_block)
|
||||||
|
, m_last_block(last_block)
|
||||||
|
, m_attributes(attr)
|
||||||
|
, m_name(BAN::String::formatted("{}{}", device->name(), index))
|
||||||
|
, m_rdev(makedev(major(device->rdev()), index))
|
||||||
|
{
|
||||||
|
memcpy(m_label, label, sizeof(m_label));
|
||||||
|
}
|
||||||
|
|
||||||
|
BAN::ErrorOr<void> Partition::read_blocks(uint64_t first_block, size_t block_count, BAN::ByteSpan buffer)
|
||||||
|
{
|
||||||
|
ASSERT(buffer.size() >= block_count * m_device->blksize());
|
||||||
|
const uint32_t blocks_in_partition = m_last_block - m_first_block + 1;
|
||||||
|
if (first_block + block_count > blocks_in_partition)
|
||||||
|
return BAN::Error::from_error_code(ErrorCode::Storage_Boundaries);
|
||||||
|
TRY(m_device->read_blocks(m_first_block + first_block, block_count, buffer));
|
||||||
|
return {};
|
||||||
|
}
|
||||||
|
|
||||||
|
BAN::ErrorOr<void> Partition::write_blocks(uint64_t first_block, size_t block_count, BAN::ConstByteSpan buffer)
|
||||||
|
{
|
||||||
|
ASSERT(buffer.size() >= block_count * m_device->blksize());
|
||||||
|
const uint32_t blocks_in_partition = m_last_block - m_first_block + 1;
|
||||||
|
if (m_first_block + block_count > blocks_in_partition)
|
||||||
|
return BAN::Error::from_error_code(ErrorCode::Storage_Boundaries);
|
||||||
|
TRY(m_device->write_blocks(m_first_block + first_block, block_count, buffer));
|
||||||
|
return {};
|
||||||
|
}
|
||||||
|
|
||||||
|
BAN::ErrorOr<size_t> Partition::read_impl(off_t offset, BAN::ByteSpan buffer)
|
||||||
|
{
|
||||||
|
ASSERT(offset >= 0);
|
||||||
|
|
||||||
|
if (offset % m_device->blksize() || buffer.size() % m_device->blksize())
|
||||||
|
return BAN::Error::from_errno(ENOTSUP);
|
||||||
|
|
||||||
|
const uint32_t blocks_in_partition = m_last_block - m_first_block + 1;
|
||||||
|
uint32_t first_block = offset / m_device->blksize();
|
||||||
|
uint32_t block_count = buffer.size() / m_device->blksize();
|
||||||
|
|
||||||
|
if (first_block >= blocks_in_partition)
|
||||||
|
return 0;
|
||||||
|
if (first_block + block_count > blocks_in_partition)
|
||||||
|
block_count = blocks_in_partition - first_block;
|
||||||
|
|
||||||
|
TRY(read_blocks(first_block, block_count, buffer));
|
||||||
|
return block_count * m_device->blksize();
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -9,12 +9,6 @@
|
||||||
#include <kernel/Storage/StorageDevice.h>
|
#include <kernel/Storage/StorageDevice.h>
|
||||||
#include <kernel/Thread.h>
|
#include <kernel/Thread.h>
|
||||||
|
|
||||||
#include <sys/sysmacros.h>
|
|
||||||
|
|
||||||
#define ATA_DEVICE_PRIMARY 0x1F0
|
|
||||||
#define ATA_DEVICE_SECONDARY 0x170
|
|
||||||
#define ATA_DEVICE_SLAVE_BIT 0x10
|
|
||||||
|
|
||||||
namespace Kernel
|
namespace Kernel
|
||||||
{
|
{
|
||||||
|
|
||||||
|
@ -29,7 +23,7 @@ namespace Kernel
|
||||||
BAN::LittleEndian<uint64_t> alternate_lba;
|
BAN::LittleEndian<uint64_t> alternate_lba;
|
||||||
BAN::LittleEndian<uint64_t> first_usable_lba;
|
BAN::LittleEndian<uint64_t> first_usable_lba;
|
||||||
BAN::LittleEndian<uint64_t> last_usable_lba;
|
BAN::LittleEndian<uint64_t> last_usable_lba;
|
||||||
GUID disk_guid;
|
BAN::GUID disk_guid;
|
||||||
BAN::LittleEndian<uint64_t> partition_entry_lba;
|
BAN::LittleEndian<uint64_t> partition_entry_lba;
|
||||||
BAN::LittleEndian<uint32_t> partition_entry_count;
|
BAN::LittleEndian<uint32_t> partition_entry_count;
|
||||||
BAN::LittleEndian<uint32_t> partition_entry_size;
|
BAN::LittleEndian<uint32_t> partition_entry_size;
|
||||||
|
@ -38,8 +32,8 @@ namespace Kernel
|
||||||
|
|
||||||
struct PartitionEntry
|
struct PartitionEntry
|
||||||
{
|
{
|
||||||
GUID partition_type_guid;
|
BAN::GUID partition_type_guid;
|
||||||
GUID unique_partition_guid;
|
BAN::GUID unique_partition_guid;
|
||||||
BAN::LittleEndian<uint64_t> starting_lba;
|
BAN::LittleEndian<uint64_t> starting_lba;
|
||||||
BAN::LittleEndian<uint64_t> ending_lba;
|
BAN::LittleEndian<uint64_t> ending_lba;
|
||||||
BAN::LittleEndian<uint64_t> attributes;
|
BAN::LittleEndian<uint64_t> attributes;
|
||||||
|
@ -180,15 +174,15 @@ namespace Kernel
|
||||||
{
|
{
|
||||||
const PartitionEntry& entry = *(const PartitionEntry*)(entry_array.data() + header.partition_entry_size * i);
|
const PartitionEntry& entry = *(const PartitionEntry*)(entry_array.data() + header.partition_entry_size * i);
|
||||||
|
|
||||||
GUID zero {};
|
BAN::GUID zero {};
|
||||||
if (memcmp(&entry.partition_type_guid, &zero, sizeof(GUID)) == 0)
|
if (memcmp(&entry.partition_type_guid, &zero, sizeof(BAN::GUID)) == 0)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
char utf8_name[36 * 4 + 1];
|
char utf8_name[36 * 4 + 1];
|
||||||
BAN::UTF8::from_codepoints(entry.partition_name, 36, utf8_name);
|
BAN::UTF8::from_codepoints(entry.partition_name, 36, utf8_name);
|
||||||
|
|
||||||
auto partition = TRY(Partition::create(
|
auto partition = TRY(Partition::create(
|
||||||
*this,
|
this,
|
||||||
entry.partition_type_guid,
|
entry.partition_type_guid,
|
||||||
entry.unique_partition_guid,
|
entry.unique_partition_guid,
|
||||||
entry.starting_lba,
|
entry.starting_lba,
|
||||||
|
@ -206,68 +200,6 @@ namespace Kernel
|
||||||
return {};
|
return {};
|
||||||
}
|
}
|
||||||
|
|
||||||
BAN::ErrorOr<BAN::RefPtr<Partition>> Partition::create(StorageDevice& device, const GUID& type, const GUID& guid, uint64_t start, uint64_t end, uint64_t attr, const char* label, uint32_t index)
|
|
||||||
{
|
|
||||||
auto partition_ptr = new Partition(device, type, guid, start, end, attr, label, index);
|
|
||||||
if (partition_ptr == nullptr)
|
|
||||||
return BAN::Error::from_errno(ENOMEM);
|
|
||||||
return BAN::RefPtr<Partition>::adopt(partition_ptr);
|
|
||||||
}
|
|
||||||
|
|
||||||
Partition::Partition(StorageDevice& device, const GUID& type, const GUID& guid, uint64_t start, uint64_t end, uint64_t attr, const char* label, uint32_t index)
|
|
||||||
: BlockDevice(0660, 0, 0)
|
|
||||||
, m_device(device)
|
|
||||||
, m_type(type)
|
|
||||||
, m_guid(guid)
|
|
||||||
, m_lba_start(start)
|
|
||||||
, m_lba_end(end)
|
|
||||||
, m_attributes(attr)
|
|
||||||
, m_name(BAN::String::formatted("{}{}", device.name(), index))
|
|
||||||
, m_rdev(makedev(major(device.rdev()), index))
|
|
||||||
{
|
|
||||||
memcpy(m_label, label, sizeof(m_label));
|
|
||||||
}
|
|
||||||
|
|
||||||
BAN::ErrorOr<void> Partition::read_sectors(uint64_t lba, uint8_t sector_count, BAN::ByteSpan buffer)
|
|
||||||
{
|
|
||||||
ASSERT(buffer.size() >= sector_count * m_device.sector_size());
|
|
||||||
const uint32_t sectors_in_partition = m_lba_end - m_lba_start;
|
|
||||||
if (lba + sector_count > sectors_in_partition)
|
|
||||||
return BAN::Error::from_error_code(ErrorCode::Storage_Boundaries);
|
|
||||||
TRY(m_device.read_sectors(m_lba_start + lba, sector_count, buffer));
|
|
||||||
return {};
|
|
||||||
}
|
|
||||||
|
|
||||||
BAN::ErrorOr<void> Partition::write_sectors(uint64_t lba, uint8_t sector_count, BAN::ConstByteSpan buffer)
|
|
||||||
{
|
|
||||||
ASSERT(buffer.size() >= sector_count * m_device.sector_size());
|
|
||||||
const uint32_t sectors_in_partition = m_lba_end - m_lba_start;
|
|
||||||
if (lba + sector_count > sectors_in_partition)
|
|
||||||
return BAN::Error::from_error_code(ErrorCode::Storage_Boundaries);
|
|
||||||
TRY(m_device.write_sectors(m_lba_start + lba, sector_count, buffer));
|
|
||||||
return {};
|
|
||||||
}
|
|
||||||
|
|
||||||
BAN::ErrorOr<size_t> Partition::read_impl(off_t offset, BAN::ByteSpan buffer)
|
|
||||||
{
|
|
||||||
ASSERT(offset >= 0);
|
|
||||||
|
|
||||||
if (offset % m_device.sector_size() || buffer.size() % m_device.sector_size())
|
|
||||||
return BAN::Error::from_errno(ENOTSUP);
|
|
||||||
|
|
||||||
const uint32_t sectors_in_partition = m_lba_end - m_lba_start;
|
|
||||||
uint32_t lba = offset / m_device.sector_size();
|
|
||||||
uint32_t sector_count = buffer.size() / m_device.sector_size();
|
|
||||||
|
|
||||||
if (lba == sectors_in_partition)
|
|
||||||
return 0;
|
|
||||||
if (lba + sector_count > sectors_in_partition)
|
|
||||||
sector_count = sectors_in_partition - lba;
|
|
||||||
|
|
||||||
TRY(read_sectors(lba, sector_count, buffer));
|
|
||||||
return sector_count * m_device.sector_size();
|
|
||||||
}
|
|
||||||
|
|
||||||
StorageDevice::~StorageDevice()
|
StorageDevice::~StorageDevice()
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
@ -287,7 +219,7 @@ namespace Kernel
|
||||||
return {};
|
return {};
|
||||||
}
|
}
|
||||||
|
|
||||||
BAN::ErrorOr<void> StorageDevice::read_sectors(uint64_t lba, uint64_t sector_count, BAN::ByteSpan buffer)
|
BAN::ErrorOr<void> StorageDevice::read_sectors(uint64_t lba, size_t sector_count, BAN::ByteSpan buffer)
|
||||||
{
|
{
|
||||||
ASSERT(buffer.size() >= sector_count * sector_size());
|
ASSERT(buffer.size() >= sector_count * sector_size());
|
||||||
|
|
||||||
|
@ -313,7 +245,7 @@ namespace Kernel
|
||||||
return {};
|
return {};
|
||||||
}
|
}
|
||||||
|
|
||||||
BAN::ErrorOr<void> StorageDevice::write_sectors(uint64_t lba, uint64_t sector_count, BAN::ConstByteSpan buffer)
|
BAN::ErrorOr<void> StorageDevice::write_sectors(uint64_t lba, size_t sector_count, BAN::ConstByteSpan buffer)
|
||||||
{
|
{
|
||||||
ASSERT(buffer.size() >= sector_count * sector_size());
|
ASSERT(buffer.size() >= sector_count * sector_size());
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue