forked from Bananymous/banan-os
Kernel: StorageDevice and Ext2 "support" writing
This commit is contained in:
parent
3efbe22a1b
commit
6ed9651176
1
disk.sh
1
disk.sh
|
@ -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
|
||||||
|
|
||||||
|
|
|
@ -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; }
|
||||||
|
|
||||||
|
|
|
@ -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;
|
||||||
|
|
|
@ -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;
|
||||||
|
|
||||||
|
|
|
@ -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 {};
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
|
@ -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++)
|
||||||
|
|
|
@ -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 {};
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
Loading…
Reference in New Issue