From 0327ab6a2b3e8382ee5b738d50f8ccf77185d1f7 Mon Sep 17 00:00:00 2001 From: Byron Lathi Date: Wed, 6 Dec 2023 21:02:41 -0800 Subject: [PATCH] Handle non-aligned reads --- sw/kernel/filesystems/fat32_c.c | 57 ++++++++++++++++++++++++++++----- sw/test_code/fs_test/main.c | 5 +++ 2 files changed, 54 insertions(+), 8 deletions(-) diff --git a/sw/kernel/filesystems/fat32_c.c b/sw/kernel/filesystems/fat32_c.c index d5334d1..6518553 100644 --- a/sw/kernel/filesystems/fat32_c.c +++ b/sw/kernel/filesystems/fat32_c.c @@ -66,6 +66,9 @@ size_t fat32_file_read(int8_t fd, void* buf, size_t nbytes) { uint16_t i; uint8_t error; size_t offset; + size_t leftover_length; + size_t bytes_read = 0; + size_t clusters; struct pcb* pcb = get_pcb_ptr(); struct file_desc* fdesc = &pcb->file_desc_array[fd]; uint32_t cluster_seq = fdesc->file_pos >> 9; @@ -85,16 +88,54 @@ size_t fat32_file_read(int8_t fd, void* buf, size_t nbytes) { cluster = fat32_next_cluster(cluster); } - offset = fdesc->file_pos % 512; + // This is an upper bound. It is possible that a 512 chunk can span + // 2 clusters, but the first one will already be handled. + clusters = nbytes >> 9; - if (offset + nbytes > 512) { - cprintf("Need to do something about this!\n"); + + /* Handle first unaligned block */ + offset = fdesc->file_pos % 512; + leftover_length = 512 - offset; + + if (leftover_length != 0) { + if (nbytes <= leftover_length) { + fat32_read_cluster(cluster, sd_buf); + memcpy(buf, sd_buf + offset, nbytes); + bytes_read += nbytes; + fdesc->file_pos += bytes_read; + return bytes_read; + } else { + fat32_read_cluster(cluster, sd_buf); + memcpy(buf, sd_buf + offset, leftover_length); + bytes_read += leftover_length; + fdesc->file_pos += bytes_read; + } } - - fat32_read_cluster(cluster, sd_buf); - memcpy(buf, sd_buf + offset, nbytes); - fdesc->file_pos += nbytes; - return nbytes; + + + /* Handle middle aligned blocks */ + for (i = 0; i < clusters; i++) { + cluster = fat32_next_cluster(cluster); + if (cluster >= 0xffffff00) { + // cprintf("Last cluster in file!\n"); + } + + if (nbytes - bytes_read > 512) { + leftover_length = 512; + } else { + leftover_length = nbytes - bytes_read; + } + + fat32_read_cluster(cluster, sd_buf); + memcpy((uint8_t*)buf+bytes_read, sd_buf, leftover_length); + bytes_read += leftover_length; + fdesc->file_pos += bytes_read; + if (bytes_read == nbytes) { + return bytes_read; + } + } + + return bytes_read; } int8_t fat32_read_cluster(uint32_t cluster, void* buf) { diff --git a/sw/test_code/fs_test/main.c b/sw/test_code/fs_test/main.c index 71b9da9..974fa85 100644 --- a/sw/test_code/fs_test/main.c +++ b/sw/test_code/fs_test/main.c @@ -16,6 +16,11 @@ int main(void) { fd = fat32_file_open("VERYLA~1TXT"); cprintf("fd: %x\n", fd); + nbytes = fat32_file_read(fd, data, 123); + for (i = 0; i < nbytes; i++) { + cprintf("%c", data[i]); + } + while ((nbytes = fat32_file_read(fd, data, 256))){ for (i = 0; i < nbytes; i++) { cprintf("%c", data[i]);