@@ -58,16 +58,28 @@ int fat16_mount(int portno, uint32_t partition_lba, fat16_fs_t* fs) {
5858}
5959
6060uint16_t fat16_read_fat_fs (fat16_fs_t * fs , uint16_t cluster ) {
61- uint32_t fat_offset = cluster * 2 ;
62- uint32_t fat_sector = fs -> fat_start + (fat_offset / fs -> bs .bytes_per_sector );
63- uint32_t ent_offset = fat_offset % fs -> bs .bytes_per_sector ;
64-
6561 uint8_t buf [512 ];
66- ahci_read_sector (fs -> portno , fat_sector , buf , 1 );
62+ uint32_t offset = cluster * 2 ;
63+ uint32_t sector = fs -> fat_start + offset / fs -> bs .bytes_per_sector ;
64+
65+ ahci_read_sector (fs -> portno , sector , buf , 1 );
66+ return * (uint16_t * )(buf + (offset % fs -> bs .bytes_per_sector ));
67+ }
6768
68- return * (uint16_t * )& buf [ent_offset ];
69+ // HELPERS ============
70+ static inline uint32_t fat16_cluster_lba (fat16_fs_t * fs , uint16_t cluster ) {
71+ return fs -> data_start + (cluster - 2 ) * fs -> bs .sectors_per_cluster ;
6972}
7073
74+ static inline int fat16_dir_valid (fat16_dir_entry_t * e ) {
75+ if (e -> name [0 ] == 0x00 ) return 0 ; // end
76+ if (e -> name [0 ] == 0xE5 ) return -1 ; // deleted
77+ if (e -> attr == 0x0F ) return -1 ; // LFN
78+ if (e -> attr & 0x08 ) return -1 ; // volume label
79+ return 1 ;
80+ }
81+ // END =========
82+
7183void fat16_list_root (fat16_fs_t * fs ) {
7284 uint8_t buf [512 ];
7385
@@ -159,24 +171,18 @@ int fat16_find_in_dir(
159171) {
160172 uint8_t buf [512 ];
161173 char fatname [11 ];
162-
163174 fat16_format_name (name , fatname );
164175
165- // ---------------- ROOT DIRECTORY ------ ----------
176+ // ---------- ROOT DIRECTORY ----------
166177 if (current_cluster == 0 ) {
167178 for (uint32_t i = 0 ; i < fs -> root_dir_sectors ; i ++ ) {
168179 ahci_read_sector (fs -> portno , fs -> root_dir_start + i , buf , 1 );
169180 fat16_dir_entry_t * e = (fat16_dir_entry_t * )buf ;
170181
171- for (int j = 0 ; j < 16 ; j ++ ) {
172- if (e [j ].name [0 ] == 0x00 )
173- return -1 ; // end of directory
174- if (e [j ].name [0 ] == 0xE5 )
175- continue ; // deleted
176- if (e [j ].attr & 0x08 )
177- continue ; // volume label
178- if (e [j ].attr == 0x0F )
179- continue ; // LFN
182+ for (int j = 0 ; j < DIR_ENTRIES_PER_SECTOR ; j ++ ) {
183+ int v = fat16_dir_valid (& e [j ]);
184+ if (v == 0 ) return -1 ;
185+ if (v < 0 ) continue ;
180186
181187 if (memcmp (e [j ].name , fatname , 11 ) == 0 ) {
182188 * out = e [j ];
@@ -187,27 +193,20 @@ int fat16_find_in_dir(
187193 return -1 ;
188194 }
189195
190- // ---------------- SUBDIRECTORY ------ ----------
196+ // ---------- SUBDIRECTORY ----------
191197 uint16_t cluster = current_cluster ;
192198
193- while (cluster < 0xFFF8 ) {
194- uint32_t lba =
195- fs -> data_start +
196- (cluster - 2 ) * fs -> bs .sectors_per_cluster ;
199+ while (cluster < FAT16_EOC ) {
200+ uint32_t lba = fat16_cluster_lba (fs , cluster );
197201
198202 for (uint32_t s = 0 ; s < fs -> bs .sectors_per_cluster ; s ++ ) {
199203 ahci_read_sector (fs -> portno , lba + s , buf , 1 );
200204 fat16_dir_entry_t * e = (fat16_dir_entry_t * )buf ;
201205
202- for (int j = 0 ; j < 16 ; j ++ ) {
203- if (e [j ].name [0 ] == 0x00 )
204- return -1 ;
205- if (e [j ].name [0 ] == 0xE5 )
206- continue ;
207- if (e [j ].attr & 0x08 )
208- continue ;
209- if (e [j ].attr == 0x0F )
210- continue ;
206+ for (int j = 0 ; j < DIR_ENTRIES_PER_SECTOR ; j ++ ) {
207+ int v = fat16_dir_valid (& e [j ]);
208+ if (v == 0 ) return -1 ;
209+ if (v < 0 ) continue ;
211210
212211 if (memcmp (e [j ].name , fatname , 11 ) == 0 ) {
213212 * out = e [j ];
@@ -345,28 +344,38 @@ int fat16_read(fat16_file_t* f, uint8_t* out, uint32_t size) {
345344 uint8_t sector [512 ];
346345
347346 while (read < size && f -> pos < f -> entry .filesize ) {
348- uint32_t cluster_offset =
349- f -> pos / ( f -> fs -> bs .sectors_per_cluster * 512 ) ;
347+ uint32_t cluster_size =
348+ f -> fs -> bs .sectors_per_cluster * 512 ;
350349
351- uint16_t cluster = f -> entry .first_cluster ;
352- for (uint32_t i = 0 ; i < cluster_offset ; i ++ )
350+ uint32_t cluster_index = f -> pos / cluster_size ;
351+ uint32_t sector_in_cluster =
352+ (f -> pos / 512 ) % f -> fs -> bs .sectors_per_cluster ;
353+
354+ uint16_t cluster = f -> cluster ;
355+
356+ // Advance cluster only when needed
357+ while (cluster_index -- ) {
353358 cluster = fat16_read_fat_fs (f -> fs , cluster );
359+ }
354360
355361 uint32_t lba =
356- f -> fs -> data_start +
357- (cluster - 2 ) * f -> fs -> bs .sectors_per_cluster ;
362+ fat16_cluster_lba (f -> fs , cluster ) + sector_in_cluster ;
358363
359364 ahci_read_sector (f -> fs -> portno , lba , sector , 1 );
360365
361366 uint32_t off = f -> pos % 512 ;
362367 uint32_t to_copy = 512 - off ;
368+
363369 if (to_copy > size - read )
364370 to_copy = size - read ;
371+ if (to_copy > f -> entry .filesize - f -> pos )
372+ to_copy = f -> entry .filesize - f -> pos ;
365373
366374 memcpy (out + read , sector + off , to_copy );
367375
368376 f -> pos += to_copy ;
369377 read += to_copy ;
378+ f -> cluster = cluster ;
370379 }
371380
372381 return read ;
0 commit comments