Kernel: StorageDevice and Ext2 "support" writing

This commit is contained in:
Bananymous 2023-03-23 12:54:59 +02:00
parent 3efbe22a1b
commit 6ed9651176
7 changed files with 88 additions and 3 deletions

View File

@ -53,6 +53,7 @@ sudo mount $PARTITION2 $MOUNT_DIR
sudo cp -r ${SYSROOT}/* ${MOUNT_DIR}/ sudo cp -r ${SYSROOT}/* ${MOUNT_DIR}/
sudo mkdir -p ${MOUNT_DIR}/usr/share/ sudo mkdir -p ${MOUNT_DIR}/usr/share/
sudo cp -r fonts ${MOUNT_DIR}/usr/share/ sudo cp -r fonts ${MOUNT_DIR}/usr/share/
sudo mkdir -p ${MOUNT_DIR}/mnt/
sudo grub-install --no-floppy --target=i386-pc --modules="normal ext2 multiboot" --boot-directory=${MOUNT_DIR}/boot $LOOP_DEV sudo grub-install --no-floppy --target=i386-pc --modules="normal ext2 multiboot" --boot-directory=${MOUNT_DIR}/boot $LOOP_DEV

View File

@ -182,6 +182,7 @@ namespace Kernel
BAN::ErrorOr<Ext2::Inode> read_inode(uint32_t); BAN::ErrorOr<Ext2::Inode> read_inode(uint32_t);
BAN::ErrorOr<BAN::Vector<uint8_t>> read_block(uint32_t); BAN::ErrorOr<BAN::Vector<uint8_t>> read_block(uint32_t);
BAN::ErrorOr<void> write_block(uint32_t, BAN::Span<const uint8_t>);
const Ext2::Superblock& superblock() const { return m_superblock; } const Ext2::Superblock& superblock() const { return m_superblock; }

View File

@ -14,6 +14,7 @@ namespace Kernel
{ {
public: public:
virtual BAN::ErrorOr<void> read_sectors(uint64_t, uint8_t, uint8_t*) override; virtual BAN::ErrorOr<void> read_sectors(uint64_t, uint8_t, uint8_t*) override;
virtual BAN::ErrorOr<void> write_sectors(uint64_t, uint8_t, const uint8_t*) override;
virtual uint32_t sector_size() const override { return sector_words * 2; } virtual uint32_t sector_size() const override { return sector_words * 2; }
virtual uint64_t total_size() const override { return lba_count * sector_size(); } virtual uint64_t total_size() const override { return lba_count * sector_size(); }
@ -49,6 +50,7 @@ namespace Kernel
uint8_t read(uint16_t); uint8_t read(uint16_t);
void read_buffer(uint16_t, uint16_t*, size_t); void read_buffer(uint16_t, uint16_t*, size_t);
void write(uint16_t, uint8_t); void write(uint16_t, uint8_t);
void write_buffer(uint16_t, const uint16_t*, size_t);
BAN::ErrorOr<void> wait(bool); BAN::ErrorOr<void> wait(bool);
BAN::Error error(); BAN::Error error();
}; };
@ -63,6 +65,7 @@ namespace Kernel
BAN::ErrorOr<void> initialize(); BAN::ErrorOr<void> initialize();
BAN::ErrorOr<void> read(ATADevice*, uint64_t, uint8_t, uint8_t*); BAN::ErrorOr<void> read(ATADevice*, uint64_t, uint8_t, uint8_t*);
BAN::ErrorOr<void> write(ATADevice*, uint64_t, uint8_t, const uint8_t*);
private: private:
SpinLock m_lock; SpinLock m_lock;

View File

@ -29,6 +29,7 @@ namespace Kernel
const StorageDevice& device() const { return m_device; } const StorageDevice& device() const { return m_device; }
BAN::ErrorOr<void> read_sectors(uint64_t lba, uint8_t sector_count, uint8_t* buffer); BAN::ErrorOr<void> read_sectors(uint64_t lba, uint8_t sector_count, uint8_t* buffer);
BAN::ErrorOr<void> write_sectors(uint64_t lba, uint8_t sector_count, const uint8_t* buffer);
bool is_used() const { uint8_t zero[16] {}; return memcmp(&m_type, zero, 16); } bool is_used() const { uint8_t zero[16] {}; return memcmp(&m_type, zero, 16); }
private: private:
@ -47,6 +48,7 @@ namespace Kernel
BAN::ErrorOr<void> initialize_partitions(); BAN::ErrorOr<void> initialize_partitions();
virtual BAN::ErrorOr<void> read_sectors(uint64_t lba, uint8_t sector_count, uint8_t* buffer) = 0; virtual BAN::ErrorOr<void> read_sectors(uint64_t lba, uint8_t sector_count, uint8_t* buffer) = 0;
virtual BAN::ErrorOr<void> write_sectors(uint64_t lba, uint8_t sector_count, const uint8_t* buffer) = 0;
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;

View File

@ -212,7 +212,7 @@ namespace Kernel
return block; return block;
} }
ASSERT(false); ASSERT_NOT_REACHED();
} }
BAN::ErrorOr<size_t> Ext2Inode::read(size_t offset, void* buffer, size_t count) BAN::ErrorOr<size_t> Ext2Inode::read(size_t offset, void* buffer, size_t count)
@ -458,9 +458,9 @@ namespace Kernel
BAN::ErrorOr<BAN::Vector<uint8_t>> Ext2FS::read_block(uint32_t block) BAN::ErrorOr<BAN::Vector<uint8_t>> Ext2FS::read_block(uint32_t block)
{ {
const uint32_t sector_size = m_partition.device().sector_size(); const uint32_t sector_size = m_partition.device().sector_size();
uint32_t block_size = 1024 << m_superblock.log_block_size; const uint32_t block_size = 1024 << m_superblock.log_block_size;
ASSERT(block_size % sector_size == 0); ASSERT(block_size % sector_size == 0);
uint32_t sectors_per_block = block_size / sector_size; const uint32_t sectors_per_block = block_size / sector_size;
BAN::Vector<uint8_t> block_buffer; BAN::Vector<uint8_t> block_buffer;
TRY(block_buffer.resize(block_size)); TRY(block_buffer.resize(block_size));
@ -470,4 +470,17 @@ namespace Kernel
return block_buffer; return block_buffer;
} }
BAN::ErrorOr<void> Ext2FS::write_block(uint32_t block, BAN::Span<const uint8_t> data)
{
const uint32_t sector_size = m_partition.device().sector_size();
const uint32_t block_size = 1024 << m_superblock.log_block_size;
ASSERT(block_size % sector_size == 0);
ASSERT(data.size() <= block_size);
const uint32_t sectors_per_block = block_size / sector_size;
TRY(m_partition.write_sectors(block * sectors_per_block, sectors_per_block, data.data()));
return {};
}
} }

View File

@ -33,6 +33,8 @@
#define ATA_STATUS_BSY 0x80 #define ATA_STATUS_BSY 0x80
#define ATA_COMMAND_READ_SECTORS 0x20 #define ATA_COMMAND_READ_SECTORS 0x20
#define ATA_COMMAND_WRITE_SECTORS 0x30
#define ATA_COMMAND_CACHE_FLUSH 0xE7
#define ATA_COMMAND_IDENTIFY 0xEC #define ATA_COMMAND_IDENTIFY 0xEC
#define ATA_COMMAND_IDENTIFY_PACKET 0xA1 #define ATA_COMMAND_IDENTIFY_PACKET 0xA1
@ -216,12 +218,53 @@ namespace Kernel
return {}; return {};
} }
BAN::ErrorOr<void> ATAController::write(ATADevice* device, uint64_t lba, uint8_t sector_count, const uint8_t* buffer)
{
if (lba + sector_count > device->lba_count)
return BAN::Error::from_c_string("Attempted to read outside of the device boundaries");
LockGuard _(m_lock);
if (lba < (1 << 28))
{
// LBA28
device->bus->write(ATA_PORT_DRIVE_SELECT, 0xE0 | device->slave_bit | ((lba >> 24) & 0x0F));
device->bus->write(ATA_PORT_SECTOR_COUNT, sector_count);
device->bus->write(ATA_PORT_LBA0, (uint8_t)(lba >> 0));
device->bus->write(ATA_PORT_LBA1, (uint8_t)(lba >> 8));
device->bus->write(ATA_PORT_LBA2, (uint8_t)(lba >> 16));
device->bus->write(ATA_PORT_COMMAND, ATA_COMMAND_WRITE_SECTORS);
for (uint32_t sector = 0; sector < sector_count; sector++)
{
TRY(device->bus->wait(false));
device->bus->write_buffer(ATA_PORT_DATA, (uint16_t*)buffer + sector * device->sector_words, device->sector_words);
}
}
else
{
// LBA48
ASSERT(false);
}
device->bus->write(ATA_PORT_COMMAND, ATA_COMMAND_CACHE_FLUSH);
TRY(device->bus->wait(false));
return {};
}
BAN::ErrorOr<void> ATADevice::read_sectors(uint64_t lba, uint8_t sector_count, uint8_t* buffer) BAN::ErrorOr<void> ATADevice::read_sectors(uint64_t lba, uint8_t sector_count, uint8_t* buffer)
{ {
TRY(controller->read(this, lba, sector_count, buffer)); TRY(controller->read(this, lba, sector_count, buffer));
return {}; return {};
} }
BAN::ErrorOr<void> ATADevice::write_sectors(uint64_t lba, uint8_t sector_count, const uint8_t* buffer)
{
TRY(controller->write(this, lba, sector_count, buffer));
return {};
}
uint8_t ATABus::read(uint16_t port) uint8_t ATABus::read(uint16_t port)
{ {
if (port <= 0x07) if (port <= 0x07)
@ -249,6 +292,18 @@ namespace Kernel
ASSERT_NOT_REACHED(); ASSERT_NOT_REACHED();
} }
void ATABus::write_buffer(uint16_t port, const uint16_t* buffer, size_t words)
{
uint16_t io_port = 0;
if (port <= 0x07)
io_port = base + port;
if (0x10 <= port && port <= 0x11)
io_port = ctrl + port - 0x10;
ASSERT(io_port);
for (size_t i = 0; i < words; i++)
IO::outw(io_port, buffer[i]);
}
BAN::ErrorOr<void> ATABus::wait(bool wait_drq) BAN::ErrorOr<void> ATABus::wait(bool wait_drq)
{ {
for (uint32_t i = 0; i < 4; i++) for (uint32_t i = 0; i < 4; i++)

View File

@ -167,6 +167,7 @@ namespace Kernel
for (uint32_t i = 0; i < header.partition_entry_count; i++) for (uint32_t i = 0; i < header.partition_entry_count; i++)
{ {
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);
ASSERT((uintptr_t)&entry % 2 == 0);
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);
@ -205,4 +206,13 @@ namespace Kernel
return {}; return {};
} }
BAN::ErrorOr<void> StorageDevice::Partition::write_sectors(uint64_t lba, uint8_t sector_count, const uint8_t* buffer)
{
const uint32_t sectors_in_partition = m_lba_end - m_lba_start;
if (lba + sector_count > sectors_in_partition)
return BAN::Error::from_c_string("Attempted to read outside of the partition boundaries");
TRY(m_device.write_sectors(m_lba_start + lba, sector_count, buffer));
return {};
}
} }