mirror of
https://github.com/LadybirdBrowser/ladybird.git
synced 2024-11-13 11:42:38 +03:00
Kernel/FATFS: Implement fat_write
This commit is contained in:
parent
a6a1508601
commit
0f828768bb
Notes:
sideshowbarker
2024-07-17 08:43:11 +09:00
Author: https://github.com/implicitfield Commit: https://github.com/SerenityOS/serenity/commit/0f828768bb Pull-request: https://github.com/SerenityOS/serenity/pull/23907 Reviewed-by: https://github.com/Hendiadyoin1 Reviewed-by: https://github.com/cqundefine Reviewed-by: https://github.com/nico Reviewed-by: https://github.com/timschumi ✅
@ -365,6 +365,67 @@ ErrorOr<u32> FATFS::fat_read(u32 cluster)
|
|||||||
return cluster_number(*fat_sector, cluster, entry_offset);
|
return cluster_number(*fat_sector, cluster, entry_offset);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
ErrorOr<void> FATFS::fat_write(u32 cluster, u32 value)
|
||||||
|
{
|
||||||
|
dbgln_if(FAT_DEBUG, "FATFS: Writing FAT entry for cluster {} with value {}", cluster, value);
|
||||||
|
|
||||||
|
u32 fat_offset = fat_offset_for_cluster(cluster);
|
||||||
|
u32 fat_sector_index = m_parameter_block->common_bpb()->reserved_sector_count + (fat_offset / m_device_block_size);
|
||||||
|
u32 entry_offset = fat_offset % m_device_block_size;
|
||||||
|
|
||||||
|
// See the comment in fat_read().
|
||||||
|
bool need_extra_block = m_fat_version == FATVersion::FAT12 && entry_offset == m_device_block_size - 1;
|
||||||
|
size_t buffer_size = m_device_block_size;
|
||||||
|
if (need_extra_block)
|
||||||
|
buffer_size += m_device_block_size;
|
||||||
|
|
||||||
|
auto fat_sector = TRY(KBuffer::try_create_with_size("FATFS: FAT read buffer"sv, buffer_size));
|
||||||
|
auto fat_sector_buffer = UserOrKernelBuffer::for_kernel_buffer(fat_sector->data());
|
||||||
|
|
||||||
|
MutexLocker locker(m_lock);
|
||||||
|
|
||||||
|
if (need_extra_block)
|
||||||
|
TRY(read_blocks(fat_sector_index, 2, fat_sector_buffer));
|
||||||
|
else
|
||||||
|
TRY(read_block(fat_sector_index, &fat_sector_buffer, m_device_block_size));
|
||||||
|
|
||||||
|
switch (m_fat_version) {
|
||||||
|
case FATVersion::FAT12: {
|
||||||
|
auto write_misaligned_u16 = [&](u16 word) {
|
||||||
|
*bit_cast<u8*>(&fat_sector->data()[entry_offset]) = word & 0xFF;
|
||||||
|
*(bit_cast<u8*>(&fat_sector->data()[entry_offset]) + 1) = word >> 8;
|
||||||
|
};
|
||||||
|
u16 existing_bytes_le = 0;
|
||||||
|
ByteReader::load<u16>(fat_sector->bytes().offset(entry_offset), existing_bytes_le);
|
||||||
|
u16 existing_bytes = AK::convert_between_host_and_little_endian(existing_bytes_le);
|
||||||
|
if (cluster % 2 == 0) {
|
||||||
|
existing_bytes &= 0xF000;
|
||||||
|
existing_bytes |= static_cast<u16>(value) & 0xFFF;
|
||||||
|
} else {
|
||||||
|
existing_bytes &= 0x000F;
|
||||||
|
existing_bytes |= static_cast<u16>(value) << 4;
|
||||||
|
}
|
||||||
|
write_misaligned_u16(AK::convert_between_host_and_little_endian(existing_bytes));
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case FATVersion::FAT16: {
|
||||||
|
*bit_cast<u16*>(&fat_sector->data()[entry_offset]) = AK::convert_between_host_and_little_endian(static_cast<u16>(value));
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case FATVersion::FAT32: {
|
||||||
|
*bit_cast<u32*>(&fat_sector->data()[entry_offset]) = AK::convert_between_host_and_little_endian(value);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (need_extra_block)
|
||||||
|
TRY(write_blocks(fat_sector_index, 2, fat_sector_buffer));
|
||||||
|
else
|
||||||
|
TRY(write_block(fat_sector_index, fat_sector_buffer, m_device_block_size));
|
||||||
|
|
||||||
|
return {};
|
||||||
|
}
|
||||||
|
|
||||||
u8 FATFS::internal_file_type_to_directory_entry_type(DirectoryEntryView const& entry) const
|
u8 FATFS::internal_file_type_to_directory_entry_type(DirectoryEntryView const& entry) const
|
||||||
{
|
{
|
||||||
FATAttributes attrib = static_cast<FATAttributes>(entry.file_type);
|
FATAttributes attrib = static_cast<FATAttributes>(entry.file_type);
|
||||||
|
@ -88,6 +88,7 @@ private:
|
|||||||
u32 cluster_number(KBuffer const& fat_sector, u32 entry_cluster_number, u32 entry_offset) const;
|
u32 cluster_number(KBuffer const& fat_sector, u32 entry_cluster_number, u32 entry_offset) const;
|
||||||
|
|
||||||
ErrorOr<u32> fat_read(u32 cluster);
|
ErrorOr<u32> fat_read(u32 cluster);
|
||||||
|
ErrorOr<void> fat_write(u32 cluster, u32 value);
|
||||||
|
|
||||||
OwnPtr<KBuffer> m_boot_record;
|
OwnPtr<KBuffer> m_boot_record;
|
||||||
OwnPtr<DOSBIOSParameterBlock> m_parameter_block;
|
OwnPtr<DOSBIOSParameterBlock> m_parameter_block;
|
||||||
|
Loading…
Reference in New Issue
Block a user