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 mkdir -p ${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
|
||||
|
||||
|
|
|
@ -182,6 +182,7 @@ namespace Kernel
|
|||
|
||||
BAN::ErrorOr<Ext2::Inode> read_inode(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; }
|
||||
|
||||
|
|
|
@ -14,6 +14,7 @@ namespace Kernel
|
|||
{
|
||||
public:
|
||||
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 uint64_t total_size() const override { return lba_count * sector_size(); }
|
||||
|
||||
|
@ -49,6 +50,7 @@ namespace Kernel
|
|||
uint8_t read(uint16_t);
|
||||
void read_buffer(uint16_t, uint16_t*, size_t);
|
||||
void write(uint16_t, uint8_t);
|
||||
void write_buffer(uint16_t, const uint16_t*, size_t);
|
||||
BAN::ErrorOr<void> wait(bool);
|
||||
BAN::Error error();
|
||||
};
|
||||
|
@ -63,6 +65,7 @@ namespace Kernel
|
|||
BAN::ErrorOr<void> initialize();
|
||||
|
||||
BAN::ErrorOr<void> read(ATADevice*, uint64_t, uint8_t, uint8_t*);
|
||||
BAN::ErrorOr<void> write(ATADevice*, uint64_t, uint8_t, const uint8_t*);
|
||||
|
||||
private:
|
||||
SpinLock m_lock;
|
||||
|
|
|
@ -29,6 +29,7 @@ namespace Kernel
|
|||
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> 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); }
|
||||
|
||||
private:
|
||||
|
@ -47,6 +48,7 @@ namespace Kernel
|
|||
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> write_sectors(uint64_t lba, uint8_t sector_count, const uint8_t* buffer) = 0;
|
||||
virtual uint32_t sector_size() const = 0;
|
||||
virtual uint64_t total_size() const = 0;
|
||||
|
||||
|
|
|
@ -212,7 +212,7 @@ namespace Kernel
|
|||
return block;
|
||||
}
|
||||
|
||||
ASSERT(false);
|
||||
ASSERT_NOT_REACHED();
|
||||
}
|
||||
|
||||
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)
|
||||
{
|
||||
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);
|
||||
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;
|
||||
TRY(block_buffer.resize(block_size));
|
||||
|
@ -470,4 +470,17 @@ namespace Kernel
|
|||
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_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_PACKET 0xA1
|
||||
|
||||
|
@ -216,12 +218,53 @@ namespace Kernel
|
|||
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)
|
||||
{
|
||||
TRY(controller->read(this, lba, sector_count, buffer));
|
||||
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)
|
||||
{
|
||||
if (port <= 0x07)
|
||||
|
@ -249,6 +292,18 @@ namespace Kernel
|
|||
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)
|
||||
{
|
||||
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++)
|
||||
{
|
||||
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];
|
||||
BAN::UTF8::from_codepoints(entry.partition_name, 36, utf8_name);
|
||||
|
@ -205,4 +206,13 @@ namespace Kernel
|
|||
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