1 /***************************************************************************
2 * Copyright (c) 2024 Microsoft Corporation
3 *
4 * This program and the accompanying materials are made available under the
5 * terms of the MIT License which is available at
6 * https://opensource.org/licenses/MIT.
7 *
8 * SPDX-License-Identifier: MIT
9 **************************************************************************/
10
11
12 /**************************************************************************/
13 /**************************************************************************/
14 /** */
15 /** FileX Component */
16 /** */
17 /** Media */
18 /** */
19 /**************************************************************************/
20 /**************************************************************************/
21
22 #define FX_SOURCE_CODE
23
24
25 /* Include necessary system files. */
26
27 #include "fx_api.h"
28 #include "fx_system.h"
29 #include "fx_media.h"
30 #include "fx_utility.h"
31
32
33 /**************************************************************************/
34 /* */
35 /* FUNCTION RELEASE */
36 /* */
37 /* _fx_media_open PORTABLE C */
38 /* 6.2.0 */
39 /* AUTHOR */
40 /* */
41 /* William E. Lamie, Microsoft Corporation */
42 /* */
43 /* DESCRIPTION */
44 /* */
45 /* This function opens the specified media with the supplied device */
46 /* driver. The specified media must conform to the FAT compatible */
47 /* file format, which is verified during the media open process. In */
48 /* addition, the supplied FileX device driver must also conform to */
49 /* the FileX device driver specification. */
50 /* */
51 /* The FAT boot sector (512 bytes) that is verified by this */
52 /* function must look like the following: */
53 /* */
54 /* Byte Offset Meaning Size */
55 /* */
56 /* 0x000 Jump Instructions 3 */
57 /* 0x003 OEM Name 8 */
58 /* 0x00B *Bytes per Sector 2 */
59 /* 0x00D *Sectors per Cluster 1 */
60 /* 0x00E *Reserved Sectors 2 */
61 /* 0x010 *Number of FATs 1 */
62 /* 0x011 *Max Root Dir Entries 2 */
63 /* 0x013 *Number of Sectors 2 */
64 /* 0x015 Media Type 1 */
65 /* 0x016 *Sectors per FAT 2 */
66 /* 0x018 *Sectors per Track 2 */
67 /* 0x01A *Number of Heads 2 */
68 /* 0x01C *Hidden Sectors 4 */
69 /* 0x020 *Huge Sectors 4 */
70 /* 0x024 Drive Number 1 */
71 /* 0x025 Reserved 1 */
72 /* 0x026 Boot Signature 1 */
73 /* 0x027 Volume ID 4 */
74 /* 0x02B Volume Label 11 */
75 /* 0x036 File System Type 8 */
76 /* ... ... ... */
77 /* 0x1FE **Signature (0x55aa) 2 */
78 /* */
79 /* * Denotes which elements of the boot record */
80 /* FileX uses. */
81 /* */
82 /* **Denotes the element is checked by the I/O */
83 /* driver. This eliminates the need for a minimum */
84 /* 512-byte buffer for FileX. */
85 /* */
86 /* Note: All values above are in little endian format, i.e. the LSB is */
87 /* in the lowest address. */
88 /* */
89 /* INPUT */
90 /* */
91 /* media_ptr Media control block pointer */
92 /* media_name Pointer to media name string */
93 /* media_driver Media driver entry function */
94 /* driver_info_ptr Optional information pointer */
95 /* supplied to media driver */
96 /* memory_ptr Pointer to memory used by the */
97 /* FileX for this media. */
98 /* memory_size Size of media memory - must */
99 /* at least 512 bytes and */
100 /* one sector size. */
101 /* */
102 /* OUTPUT */
103 /* */
104 /* return status */
105 /* */
106 /* CALLS */
107 /* */
108 /* I/O Driver */
109 /* _fx_utility_16_unsigned_read Read 16-bit unsigned value */
110 /* _fx_utility_32_unsigned_read Read 32-bit unsigned value */
111 /* _fx_utility_logical_sector_flush Invalidate log sector cache */
112 /* _fx_media_boot_info_extract Extract media information */
113 /* _fx_utility_FAT_entry_read Pickup FAT entry contents */
114 /* tx_mutex_create Create protection mutex */
115 /* */
116 /* CALLED BY */
117 /* */
118 /* Application Code */
119 /* */
120 /* RELEASE HISTORY */
121 /* */
122 /* DATE NAME DESCRIPTION */
123 /* */
124 /* 05-19-2020 William E. Lamie Initial Version 6.0 */
125 /* 09-30-2020 William E. Lamie Modified comment(s), and */
126 /* added conditional to */
127 /* disable force memset, */
128 /* build options and cache, */
129 /* resulting in version 6.1 */
130 /* 01-31-2022 William E. Lamie Modified comment(s), fixed */
131 /* errors without cache, */
132 /* resulting in version 6.1.10 */
133 /* 10-31-2022 Tiejun Zhou Modified comment(s), */
134 /* fixed memory buffer when */
135 /* cache is disabled, */
136 /* resulting in version 6.2.0 */
137 /* */
138 /**************************************************************************/
_fx_media_open(FX_MEDIA * media_ptr,CHAR * media_name,VOID (* media_driver)(FX_MEDIA *),VOID * driver_info_ptr,VOID * memory_ptr,ULONG memory_size)139 UINT _fx_media_open(FX_MEDIA *media_ptr, CHAR *media_name,
140 VOID (*media_driver)(FX_MEDIA *), VOID *driver_info_ptr,
141 VOID *memory_ptr, ULONG memory_size)
142 {
143
144 FX_MEDIA_PTR tail_ptr;
145 ULONG cluster_number;
146 ULONG FAT_entry, FAT_sector, FAT_read_sectors;
147 ULONG i, j;
148 #ifndef FX_DISABLE_CACHE
149 FX_CACHED_SECTOR *cache_entry_ptr;
150 #endif /* FX_DISABLE_CACHE */
151 UINT status;
152 UINT additional_info_sector;
153 UCHAR *original_memory_ptr;
154 ULONG bytes_in_buffer;
155 FX_INT_SAVE_AREA
156
157
158 #ifndef FX_DISABLE_BUILD_OPTIONS
159 /* Reference the version ID and option words to ensure they are linked in. */
160 if ((_fx_system_build_options_1 | _fx_system_build_options_2 | _fx_system_build_options_3) == 0 ||
161 _fx_version_id[0] == 0)
162 {
163
164 /* We should never get here! */
165 return(FX_NOT_IMPLEMENTED);
166 }
167 #endif /* FX_DISABLE_BUILD_OPTIONS */
168
169 #ifdef FX_DISABLE_FORCE_MEMORY_OPERATION
170 _fx_utility_memory_set((UCHAR *)media_ptr, 0, sizeof(FX_MEDIA));
171 #endif /* FX_DISABLE_FORCE_MEMORY_OPERATION */
172 #ifdef FX_DISABLE_CACHE
173 media_ptr -> fx_media_memory_buffer_sector = (ULONG64)-1;
174 #endif /* FX_DISABLE_CACHE */
175
176 /* Save the basic information in the media control block. */
177 media_ptr -> fx_media_name = media_name;
178 media_ptr -> fx_media_driver_entry = media_driver;
179 media_ptr -> fx_media_memory_buffer = (UCHAR *)memory_ptr;
180 media_ptr -> fx_media_memory_size = memory_size;
181 #ifndef FX_DISABLE_FORCE_MEMORY_OPERATION
182 media_ptr -> fx_media_disable_burst_cache = FX_FALSE;
183 media_ptr -> fx_media_FAT_type = 0;
184 #endif /* FX_DISABLE_FORCE_MEMORY_OPERATION */
185
186 /* Save the original memory pointer. */
187 original_memory_ptr = (UCHAR *)memory_ptr;
188
189 #ifndef FX_MEDIA_STATISTICS_DISABLE
190
191 /* Clear the optional media statistics. */
192 media_ptr -> fx_media_directory_attributes_reads = 0;
193 media_ptr -> fx_media_directory_attributes_sets = 0;
194 media_ptr -> fx_media_directory_creates = 0;
195 media_ptr -> fx_media_directory_default_gets = 0;
196 media_ptr -> fx_media_directory_default_sets = 0;
197 media_ptr -> fx_media_directory_deletes = 0;
198 media_ptr -> fx_media_directory_first_entry_finds = 0;
199 media_ptr -> fx_media_directory_first_full_entry_finds = 0;
200 media_ptr -> fx_media_directory_information_gets = 0;
201 media_ptr -> fx_media_directory_local_path_clears = 0;
202 media_ptr -> fx_media_directory_local_path_gets = 0;
203 media_ptr -> fx_media_directory_local_path_restores = 0;
204 media_ptr -> fx_media_directory_local_path_sets = 0;
205 media_ptr -> fx_media_directory_name_tests = 0;
206 media_ptr -> fx_media_directory_next_entry_finds = 0;
207 media_ptr -> fx_media_directory_next_full_entry_finds = 0;
208 media_ptr -> fx_media_directory_renames = 0;
209 media_ptr -> fx_media_file_allocates = 0;
210 media_ptr -> fx_media_file_attributes_reads = 0;
211 media_ptr -> fx_media_file_attributes_sets = 0;
212 media_ptr -> fx_media_file_best_effort_allocates = 0;
213 media_ptr -> fx_media_file_closes = 0;
214 media_ptr -> fx_media_file_creates = 0;
215 media_ptr -> fx_media_file_deletes = 0;
216 media_ptr -> fx_media_file_opens = 0;
217 media_ptr -> fx_media_file_reads = 0;
218 media_ptr -> fx_media_file_relative_seeks = 0;
219 media_ptr -> fx_media_file_renames = 0;
220 media_ptr -> fx_media_file_seeks = 0;
221 media_ptr -> fx_media_file_truncates = 0;
222 media_ptr -> fx_media_file_truncate_releases = 0;
223 media_ptr -> fx_media_file_writes = 0;
224 media_ptr -> fx_media_aborts = 0;
225 media_ptr -> fx_media_flushes = 0;
226 media_ptr -> fx_media_reads = 0;
227 media_ptr -> fx_media_writes = 0;
228 media_ptr -> fx_media_directory_entry_reads = 0;
229 media_ptr -> fx_media_directory_entry_writes = 0;
230 media_ptr -> fx_media_directory_searches = 0;
231 #ifndef FX_MEDIA_DISABLE_SEARCH_CACHE
232 media_ptr -> fx_media_directory_search_cache_hits = 0;
233 #endif
234 media_ptr -> fx_media_directory_free_searches = 0;
235 media_ptr -> fx_media_fat_entry_reads = 0;
236 media_ptr -> fx_media_fat_entry_writes = 0;
237 media_ptr -> fx_media_fat_entry_cache_read_hits = 0;
238 media_ptr -> fx_media_fat_entry_cache_read_misses = 0;
239 media_ptr -> fx_media_fat_entry_cache_write_hits = 0;
240 media_ptr -> fx_media_fat_entry_cache_write_misses = 0;
241 media_ptr -> fx_media_fat_cache_flushes = 0;
242 media_ptr -> fx_media_fat_sector_reads = 0;
243 media_ptr -> fx_media_fat_sector_writes = 0;
244 media_ptr -> fx_media_logical_sector_reads = 0;
245 media_ptr -> fx_media_logical_sector_writes = 0;
246 media_ptr -> fx_media_logical_sector_cache_read_hits = 0;
247 media_ptr -> fx_media_logical_sector_cache_read_misses = 0;
248 media_ptr -> fx_media_driver_read_requests = 0;
249 media_ptr -> fx_media_driver_write_requests = 0;
250 media_ptr -> fx_media_driver_boot_read_requests = 0;
251 media_ptr -> fx_media_driver_boot_write_requests = 0;
252 media_ptr -> fx_media_driver_release_sectors_requests = 0;
253 media_ptr -> fx_media_driver_flush_requests = 0;
254 #endif
255 #ifdef FX_ENABLE_FAULT_TOLERANT
256 media_ptr -> fx_media_fault_tolerant_enabled = FX_FALSE;
257 media_ptr -> fx_media_fault_tolerant_state = 0;
258 #endif /* FX_ENABLE_FAULT_TOLERANT */
259
260 /* If trace is enabled, insert this event into the trace buffer. */
261 FX_TRACE_IN_LINE_INSERT(FX_TRACE_MEDIA_OPEN, media_ptr, media_driver, memory_ptr, memory_size, FX_TRACE_MEDIA_EVENTS, 0, 0)
262
263 /* Initialize the supplied media I/O driver. First, build the
264 initialize driver request. */
265 media_ptr -> fx_media_driver_request = FX_DRIVER_INIT;
266 media_ptr -> fx_media_driver_status = FX_IO_ERROR;
267 media_ptr -> fx_media_driver_info = driver_info_ptr;
268 media_ptr -> fx_media_driver_write_protect = FX_FALSE;
269 media_ptr -> fx_media_driver_free_sector_update = FX_FALSE;
270 media_ptr -> fx_media_driver_data_sector_read = FX_FALSE;
271
272 /* If trace is enabled, insert this event into the trace buffer. */
273 FX_TRACE_IN_LINE_INSERT(FX_TRACE_INTERNAL_IO_DRIVER_INIT, media_ptr, 0, 0, 0, FX_TRACE_INTERNAL_EVENTS, 0, 0)
274
275 /* Call the specified I/O driver with the initialize request. */
276 (media_ptr -> fx_media_driver_entry) (media_ptr);
277
278 /* Determine if the I/O driver initialized successfully. */
279 if (media_ptr -> fx_media_driver_status != FX_SUCCESS)
280 {
281
282 /* Return the driver error status. */
283 return(FX_IO_ERROR);
284 }
285
286 #ifndef FX_MEDIA_STATISTICS_DISABLE
287
288 /* Increment the number of driver boot read requests. */
289 media_ptr -> fx_media_driver_boot_read_requests++;
290 #endif
291
292 /* Read the boot sector from the device. Build the read boot sector
293 command. */
294 media_ptr -> fx_media_driver_request = FX_DRIVER_BOOT_READ;
295 media_ptr -> fx_media_driver_status = FX_IO_ERROR;
296 media_ptr -> fx_media_driver_buffer = memory_ptr;
297 media_ptr -> fx_media_driver_sectors = 1;
298 media_ptr -> fx_media_driver_sector_type = FX_BOOT_SECTOR;
299
300 /* If trace is enabled, insert this event into the trace buffer. */
301 FX_TRACE_IN_LINE_INSERT(FX_TRACE_INTERNAL_IO_DRIVER_BOOT_READ, media_ptr, memory_ptr, 0, 0, FX_TRACE_INTERNAL_EVENTS, 0, 0)
302
303 /* Invoke the driver to read the boot sector. */
304 (media_ptr -> fx_media_driver_entry) (media_ptr);
305
306 /* Determine if the boot sector was read correctly. */
307 if (media_ptr -> fx_media_driver_status != FX_SUCCESS)
308 {
309
310 /* Build the "uninitialize" I/O driver request. */
311 media_ptr -> fx_media_driver_request = FX_DRIVER_UNINIT;
312 media_ptr -> fx_media_driver_status = FX_IO_ERROR;
313
314 /* If trace is enabled, insert this event into the trace buffer. */
315 FX_TRACE_IN_LINE_INSERT(FX_TRACE_INTERNAL_IO_DRIVER_UNINIT, media_ptr, 0, 0, 0, FX_TRACE_INTERNAL_EVENTS, 0, 0)
316
317 /* Call the specified I/O driver with the uninitialize request. */
318 (media_ptr -> fx_media_driver_entry) (media_ptr);
319
320 /* Return the boot sector error status. */
321 return(FX_BOOT_ERROR);
322 }
323
324 /* Extract and validate the media parameters from the boot sector. */
325 if (_fx_media_boot_info_extract(media_ptr) != FX_SUCCESS)
326 {
327
328 /* Build the "uninitialize" I/O driver request. */
329 media_ptr -> fx_media_driver_request = FX_DRIVER_UNINIT;
330 media_ptr -> fx_media_driver_status = FX_IO_ERROR;
331
332 /* If trace is enabled, insert this event into the trace buffer. */
333 FX_TRACE_IN_LINE_INSERT(FX_TRACE_INTERNAL_IO_DRIVER_UNINIT, media_ptr, 0, 0, 0, FX_TRACE_INTERNAL_EVENTS, 0, 0)
334
335 /* Call the specified I/O driver with the uninitialize request. */
336 (media_ptr -> fx_media_driver_entry) (media_ptr);
337
338 /* Return the invalid media error status. */
339 return(FX_MEDIA_INVALID);
340 }
341
342 /* Pickup the additional info sector number. This will only be used in FAT32 situations. */
343 additional_info_sector = _fx_utility_16_unsigned_read(&media_ptr -> fx_media_driver_buffer[48]);
344
345 /* Is there at least one? */
346 if (memory_size < media_ptr -> fx_media_bytes_per_sector)
347 {
348
349 /* Build the "uninitialize" I/O driver request. */
350 media_ptr -> fx_media_driver_request = FX_DRIVER_UNINIT;
351 media_ptr -> fx_media_driver_status = FX_IO_ERROR;
352
353 /* If trace is enabled, insert this event into the trace buffer. */
354 FX_TRACE_IN_LINE_INSERT(FX_TRACE_INTERNAL_IO_DRIVER_UNINIT, media_ptr, 0, 0, 0, FX_TRACE_INTERNAL_EVENTS, 0, 0)
355
356 /* Call the specified I/O driver with the uninitialize request. */
357 (media_ptr -> fx_media_driver_entry) (media_ptr);
358
359 /* Error in the buffer size supplied by user. */
360 return(FX_BUFFER_ERROR);
361 }
362
363 #ifndef FX_DISABLE_CACHE
364 /* Determine how many logical sectors can be cached with user's supplied
365 buffer area - there must be at least enough for one sector! */
366 media_ptr -> fx_media_sector_cache_size = memory_size / media_ptr -> fx_media_bytes_per_sector;
367
368 /* If trace is enabled, register this object. */
369 FX_TRACE_OBJECT_REGISTER(FX_TRACE_OBJECT_TYPE_MEDIA, media_ptr, media_name, FX_MAX_FAT_CACHE, media_ptr -> fx_media_sector_cache_size)
370
371 /* Adjust the internal cache to fit the fixed number of sector cache control blocks
372 built into the media control block. */
373 if (media_ptr -> fx_media_sector_cache_size > FX_MAX_SECTOR_CACHE)
374 {
375
376 /* Adjust the number of cache sectors downward. If this is insufficient,
377 the FX_MAX_SECTOR_CACHE constant in FX_API.H must be changed and the FileX
378 library must be rebuilt. */
379 media_ptr -> fx_media_sector_cache_size = FX_MAX_SECTOR_CACHE;
380 }
381
382 /* Otherwise, everything is okay. Initialize the data structures for managing the
383 logical sector cache. */
384 i = (UINT)media_ptr -> fx_media_sector_cache_size;
385 cache_entry_ptr = media_ptr -> fx_media_sector_cache;
386 while (i--)
387 {
388
389 /* Initialize each of the cache entries. */
390 cache_entry_ptr -> fx_cached_sector_memory_buffer = (UCHAR *)memory_ptr;
391 cache_entry_ptr -> fx_cached_sector = (~(ULONG64)0);
392 cache_entry_ptr -> fx_cached_sector_buffer_dirty = FX_FALSE;
393 cache_entry_ptr -> fx_cached_sector_valid = FX_FALSE;
394 cache_entry_ptr -> fx_cached_sector_next_used = cache_entry_ptr + 1;
395
396 /* Move to the next cache sector entry. */
397 cache_entry_ptr++;
398
399 /* Update the memory pointer to the next buffer slot. */
400 memory_ptr = (VOID *)(((UCHAR *)memory_ptr) + media_ptr -> fx_media_bytes_per_sector);
401 }
402
403 /* Backup to the last cache entry to set its next pointer to NULL. */
404 cache_entry_ptr--;
405 cache_entry_ptr -> fx_cached_sector_next_used = FX_NULL;
406
407 /* Remember the last memory address used by the caching logic. */
408 media_ptr -> fx_media_sector_cache_end = ((UCHAR *)memory_ptr) - 1;
409
410 /* Setup the head pointer of the list. */
411 media_ptr -> fx_media_sector_cache_list_ptr = media_ptr -> fx_media_sector_cache;
412
413 /* Setup the bit map that keeps track of the valid hashed cache logical sectors. */
414 media_ptr -> fx_media_sector_cache_hashed_sector_valid = 0;
415
416 /* Clear the counter of the number of outstanding dirty sectors. */
417 media_ptr -> fx_media_sector_cache_dirty_count = 0;
418
419 /* Determine if the logical sector cache should be managed by the hash function
420 instead of the linear search. The cache must be a power of 2 that is between the
421 minimum and maximum cache size. */
422 if ((media_ptr -> fx_media_sector_cache_size >= FX_SECTOR_CACHE_HASH_ENABLE) &&
423 ((media_ptr -> fx_media_sector_cache_size ^ (media_ptr -> fx_media_sector_cache_size - 1)) ==
424 (media_ptr -> fx_media_sector_cache_size | (media_ptr -> fx_media_sector_cache_size - 1))))
425 {
426
427
428 /* Set the logical sector cache hash flag. When this flag is set, the logical
429 sector cache is accessed with a hash function instead of a linear search. */
430 media_ptr -> fx_media_sector_cache_hashed = FX_TRUE;
431 media_ptr -> fx_media_sector_cache_hash_mask =
432 ((media_ptr -> fx_media_sector_cache_size / FX_SECTOR_CACHE_DEPTH) - 1);
433 }
434 else
435 {
436
437 /* Clear the logical sector cache flag. */
438 media_ptr -> fx_media_sector_cache_hashed = FX_FALSE;
439 }
440 #else
441 media_ptr -> fx_media_memory_buffer = memory_ptr;
442 #endif /* FX_DISABLE_CACHE */
443
444 #ifndef FX_DISABLE_FORCE_MEMORY_OPERATION
445 /* Initialize the FAT cache entry array. */
446 for (i = 0; i < FX_MAX_FAT_CACHE; i++)
447 {
448
449 /* Clear entry in the FAT cache. */
450 media_ptr -> fx_media_fat_cache[i].fx_fat_cache_entry_cluster = 0;
451 media_ptr -> fx_media_fat_cache[i].fx_fat_cache_entry_value = 0;
452 media_ptr -> fx_media_fat_cache[i].fx_fat_cache_entry_dirty = 0;
453 }
454
455 /* Initialize the secondary FAT update map. */
456 for (i = 0; i < FX_FAT_MAP_SIZE; i++)
457 {
458
459 /* Clear bit map entry for secondary FAT update. */
460 media_ptr -> fx_media_fat_secondary_update_map[i] = 0;
461 }
462 #endif /* FX_DISABLE_FORCE_MEMORY_OPERATION */
463
464
465 /* Root_sector_start has been computed */
466 media_ptr -> fx_media_root_sector_start = media_ptr -> fx_media_reserved_sectors +
467 (media_ptr -> fx_media_number_of_FATs *
468 media_ptr -> fx_media_sectors_per_FAT);
469
470 /* Calculate the number of directory sectors. */
471 media_ptr -> fx_media_root_sectors =
472 ((media_ptr -> fx_media_root_directory_entries * FX_DIR_ENTRY_SIZE) +
473 media_ptr -> fx_media_bytes_per_sector - 1) /
474 media_ptr -> fx_media_bytes_per_sector;
475
476 /* Calculate the starting data sector. */
477 media_ptr -> fx_media_data_sector_start = media_ptr -> fx_media_root_sector_start +
478 media_ptr -> fx_media_root_sectors;
479
480 /* Calculate the total number of clusters. */
481 media_ptr -> fx_media_total_clusters = (ULONG)((media_ptr -> fx_media_total_sectors - media_ptr -> fx_media_data_sector_start) /
482 media_ptr -> fx_media_sectors_per_cluster);
483
484 /* Determine if a 12-bit FAT is in use. */
485 if (media_ptr -> fx_media_total_clusters < FX_12_BIT_FAT_SIZE)
486 {
487
488 /* Yes, 12-bit FAT is present. Set flag accordingly. */
489 media_ptr -> fx_media_12_bit_FAT = FX_TRUE;
490 media_ptr -> fx_media_32_bit_FAT = FX_FALSE;
491
492 /* No additional information sector in FAT12. */
493 media_ptr -> fx_media_FAT32_additional_info_sector = 0;
494
495 /* Set FAT last and FAT reserved. */
496 media_ptr -> fx_media_fat_reserved = FX_RESERVED_1;
497 media_ptr -> fx_media_fat_last = FX_LAST_CLUSTER_2;
498 }
499 else if (media_ptr -> fx_media_total_clusters < FX_16_BIT_FAT_SIZE)
500 {
501
502 /* A 16-bit FAT is present. Set flag accordingly. */
503 media_ptr -> fx_media_12_bit_FAT = FX_FALSE;
504 media_ptr -> fx_media_32_bit_FAT = FX_FALSE;
505
506 /* No additional information sector in FAT16. */
507 media_ptr -> fx_media_FAT32_additional_info_sector = 0;
508
509 /* Set FAT last and FAT reserved. */
510 media_ptr -> fx_media_fat_reserved = FX_RESERVED_1;
511 media_ptr -> fx_media_fat_last = FX_LAST_CLUSTER_2;
512 }
513 else
514 {
515
516 /* Yes, a 32-bit FAT is present. */
517 media_ptr -> fx_media_12_bit_FAT = FX_FALSE;
518 media_ptr -> fx_media_32_bit_FAT = FX_TRUE;
519
520 /* Save the additional information sector FAT32. This was read from the boot
521 sector earlier in this routine. */
522 media_ptr -> fx_media_FAT32_additional_info_sector = additional_info_sector;
523
524 /* Set FAT last and FAT reserved. */
525 media_ptr -> fx_media_fat_reserved = FX_RESERVED_1_32;
526 media_ptr -> fx_media_fat_last = FX_LAST_CLUSTER_2_32;
527 }
528
529 /* Determine if a 32-bit FAT is present. If so, calculate the size of the root directory (since
530 it is variable in FAT32. */
531 if (media_ptr -> fx_media_32_bit_FAT == FX_TRUE)
532 {
533
534 /* Root First cluster starts from at least cluster 2, or higher. */
535 if (media_ptr -> fx_media_root_cluster_32 < FX_FAT_ENTRY_START)
536 {
537 return(FX_MEDIA_INVALID);
538 }
539
540 /* Calculate logical number of root dir sector. */
541 media_ptr -> fx_media_root_sector_start = media_ptr -> fx_media_data_sector_start +
542 (media_ptr -> fx_media_root_cluster_32 - FX_FAT_ENTRY_START) *
543 media_ptr -> fx_media_sectors_per_cluster;
544
545 /* Calculate maximum possible value for fx_media_root_directory_entries */
546 i = 0;
547 for (cluster_number = media_ptr -> fx_media_root_cluster_32;;)
548 {
549
550 status = _fx_utility_FAT_entry_read(media_ptr, cluster_number, &FAT_entry);
551 i++;
552 /* Determine if the read was successful. */
553 if (status != FX_SUCCESS)
554 {
555
556 /* Build the "uninitialize" I/O driver request. */
557 media_ptr -> fx_media_driver_request = FX_DRIVER_UNINIT;
558 media_ptr -> fx_media_driver_status = FX_IO_ERROR;
559
560 /* If trace is enabled, insert this event into the trace buffer. */
561 FX_TRACE_IN_LINE_INSERT(FX_TRACE_INTERNAL_IO_DRIVER_UNINIT, media_ptr, 0, 0, 0, FX_TRACE_INTERNAL_EVENTS, 0, 0)
562
563 /* Call the specified I/O driver with the uninitialize request. */
564 (media_ptr -> fx_media_driver_entry) (media_ptr);
565
566 return(FX_FAT_READ_ERROR);
567 }
568
569 if ((cluster_number == FAT_entry) || (i > media_ptr -> fx_media_total_clusters))
570 {
571
572 /* Build the "uninitialize" I/O driver request. */
573 media_ptr -> fx_media_driver_request = FX_DRIVER_UNINIT;
574 media_ptr -> fx_media_driver_status = FX_IO_ERROR;
575
576 /* If trace is enabled, insert this event into the trace buffer. */
577 FX_TRACE_IN_LINE_INSERT(FX_TRACE_INTERNAL_IO_DRIVER_UNINIT, media_ptr, 0, 0, 0, FX_TRACE_INTERNAL_EVENTS, 0, 0)
578
579 /* Call the specified I/O driver with the uninitialize request. */
580 (media_ptr -> fx_media_driver_entry) (media_ptr);
581
582 return(FX_FAT_READ_ERROR);
583 }
584 if (FAT_entry >= FX_RESERVED_1_32)
585 {
586 break;
587 }
588 cluster_number = FAT_entry;
589 }
590
591 /* Calculate the number of directory entries. */
592 media_ptr -> fx_media_root_directory_entries = (i * media_ptr -> fx_media_sectors_per_cluster *
593 media_ptr -> fx_media_bytes_per_sector) / FX_DIR_ENTRY_SIZE;
594 }
595
596 #ifndef FX_DISABLE_FORCE_MEMORY_OPERATION
597 /* Calculate the number of available clusters. */
598 media_ptr -> fx_media_available_clusters = 0;
599
600 /* Set the cluster search start to an invalid value. */
601 media_ptr -> fx_media_cluster_search_start = 0;
602 #endif /* FX_DISABLE_FORCE_MEMORY_OPERATION */
603
604 /* Determine if there is 32-bit FAT additional information sector. */
605 if (media_ptr -> fx_media_FAT32_additional_info_sector)
606 {
607
608 UCHAR *buffer_ptr;
609 ULONG signature;
610
611
612 /* Yes, read the FAT32 additional information sector to get the available cluster count and
613 the hint for the first available cluster. */
614
615 #ifndef FX_DISABLE_CACHE
616 /* Setup a pointer to the first cached entry's buffer. */
617 buffer_ptr = (media_ptr -> fx_media_sector_cache_list_ptr) -> fx_cached_sector_memory_buffer;
618
619 /* Invalidate this cache entry. */
620 (media_ptr -> fx_media_sector_cache_list_ptr) -> fx_cached_sector = (~((ULONG64) 0));
621 (media_ptr -> fx_media_sector_cache_list_ptr) -> fx_cached_sector_valid = FX_FALSE;
622 #else
623 buffer_ptr = media_ptr -> fx_media_memory_buffer;
624 media_ptr -> fx_media_memory_buffer_sector = (ULONG64)-1;
625 #endif /* FX_DISABLE_CACHE */
626
627 /* Read the FAT32 additional information sector from the device. */
628 media_ptr -> fx_media_driver_request = FX_DRIVER_READ;
629 media_ptr -> fx_media_driver_status = FX_IO_ERROR;
630 media_ptr -> fx_media_driver_buffer = buffer_ptr;
631 media_ptr -> fx_media_driver_logical_sector = media_ptr -> fx_media_FAT32_additional_info_sector;
632 media_ptr -> fx_media_driver_sectors = 1;
633 media_ptr -> fx_media_driver_sector_type = FX_DIRECTORY_SECTOR;
634
635 #ifndef FX_MEDIA_STATISTICS_DISABLE
636
637 /* Increment the number of driver read sector(s) requests. */
638 media_ptr -> fx_media_driver_read_requests++;
639 #endif
640
641 /* If trace is enabled, insert this event into the trace buffer. */
642 FX_TRACE_IN_LINE_INSERT(FX_TRACE_INTERNAL_IO_DRIVER_READ, media_ptr, media_ptr -> fx_media_FAT32_additional_info_sector, 1, buffer_ptr, FX_TRACE_INTERNAL_EVENTS, 0, 0)
643
644 /* Invoke the driver to read the FAT32 additional information sector. */
645 (media_ptr -> fx_media_driver_entry) (media_ptr);
646
647 /* Determine if the FAT32 sector was read correctly. */
648 if (media_ptr -> fx_media_driver_status == FX_SUCCESS)
649 {
650
651 /* Yes, setup a pointer into the FAT32 additional information sector. */
652 buffer_ptr = media_ptr -> fx_media_driver_buffer;
653
654 /* Pickup the first signature long word. */
655 signature = _fx_utility_32_unsigned_read(&buffer_ptr[0]);
656
657 /* Determine if the signature is correct. */
658 if (signature == 0x41615252)
659 {
660
661 /* Yes, the first signature is correct, now pickup the next signature. */
662 signature = _fx_utility_32_unsigned_read(&buffer_ptr[484]);
663
664 /* Determine if this signature is correct. */
665 if (signature == 0x61417272)
666 {
667
668 /* Yes, we have a good FAT32 additional information sector. */
669
670 /* Pickup the current available cluster count on the media. */
671 media_ptr -> fx_media_available_clusters = _fx_utility_32_unsigned_read(&buffer_ptr[488]);
672
673 /* Initialize the last reported available cluster count to the same value. */
674 media_ptr -> fx_media_FAT32_additional_info_last_available = media_ptr -> fx_media_available_clusters;
675
676 /* Pickup the hint for the starting free cluster search. */
677 media_ptr -> fx_media_cluster_search_start = _fx_utility_32_unsigned_read(&buffer_ptr[492]);
678
679 /* Perform a quick sanity check on the available cluster count and the starting free
680 cluster search. */
681 if ((media_ptr -> fx_media_available_clusters > media_ptr -> fx_media_total_clusters) ||
682 (media_ptr -> fx_media_cluster_search_start > media_ptr -> fx_media_total_clusters + FX_FAT_ENTRY_START) ||
683 (media_ptr -> fx_media_cluster_search_start < FX_FAT_ENTRY_START))
684 {
685
686 /* Something is wrong, clear the available cluster count and search so the regular processing
687 is used. */
688 media_ptr -> fx_media_available_clusters = 0;
689 media_ptr -> fx_media_cluster_search_start = 0;
690
691 /* We don't invalidate the additional info sector here because only the data is bad. */
692 }
693 }
694 else
695 {
696
697 /* Signature is bad, invalidate the additional info sector. */
698 media_ptr -> fx_media_FAT32_additional_info_sector = 0;
699 }
700 }
701 else
702 {
703
704 /* Signature is bad, invalidate the additional info sector. */
705 media_ptr -> fx_media_FAT32_additional_info_sector = 0;
706 }
707 }
708 else
709 {
710
711 /* IO error trying to read additional information sector, invalidate the additional info sector. */
712 media_ptr -> fx_media_FAT32_additional_info_sector = 0;
713 }
714 }
715
716 /* Search the media to find the first available cluster as well as the total
717 available clusters. */
718
719 /* Determine what type of FAT is present. */
720 if (media_ptr -> fx_media_12_bit_FAT)
721 {
722
723 /* A 12-bit FAT is present. Utilize the FAT entry read utility to pickup
724 each FAT entry's contents. */
725
726 /* Loop to read each cluster entry in the first FAT. */
727 for (cluster_number = FX_FAT_ENTRY_START;
728 cluster_number < (media_ptr -> fx_media_total_clusters) + FX_FAT_ENTRY_START;
729 cluster_number++)
730 {
731
732 /* Read a FAT entry. */
733 status = _fx_utility_FAT_entry_read(media_ptr, cluster_number, &FAT_entry);
734
735 /* Determine if the read was successful. */
736 if (status != FX_SUCCESS)
737 {
738
739 /* Build the "uninitialize" I/O driver request. */
740 media_ptr -> fx_media_driver_request = FX_DRIVER_UNINIT;
741 media_ptr -> fx_media_driver_status = FX_IO_ERROR;
742
743 /* If trace is enabled, insert this event into the trace buffer. */
744 FX_TRACE_IN_LINE_INSERT(FX_TRACE_INTERNAL_IO_DRIVER_UNINIT, media_ptr, 0, 0, 0, FX_TRACE_INTERNAL_EVENTS, 0, 0)
745
746 /* Call the specified I/O driver with the uninitialize request. */
747 (media_ptr -> fx_media_driver_entry) (media_ptr);
748
749 return(FX_FAT_READ_ERROR);
750 }
751
752 /* Now determine if the FAT entry is available. */
753 if (FAT_entry == FX_FREE_CLUSTER)
754 {
755
756 /* Increment the number of available clusters. */
757 media_ptr -> fx_media_available_clusters++;
758
759 /* Determine if the starting free cluster has been found yet. */
760 if (media_ptr -> fx_media_cluster_search_start == 0)
761 {
762
763 /* Remember the first free cluster to start further searches from. */
764 media_ptr -> fx_media_cluster_search_start = cluster_number;
765 }
766 }
767 }
768 }
769 else if (media_ptr -> fx_media_available_clusters == 0)
770 {
771
772 /* A 16 or 32-bit FAT is present. Read directly into the logical sector
773 cache memory to optimize I/O on larger devices. Since we are looking for
774 values of zero, endian issues are not important. */
775
776 /* Invalidate the current logical sector cache. */
777 _fx_utility_logical_sector_flush(media_ptr, ((ULONG64) 1), (ULONG64) (media_ptr -> fx_media_total_sectors), FX_TRUE);
778
779 /* Reset the memory pointer. */
780 media_ptr -> fx_media_memory_buffer = original_memory_ptr;
781
782 /* Loop through all FAT sectors in the primary FAT. The first two entries are
783 examined in this loop, but they are always unavailable. */
784 cluster_number = 0;
785 #ifndef FX_DISABLE_CACHE
786 for (i = 0; i < media_ptr -> fx_media_sectors_per_FAT; i = i + media_ptr -> fx_media_sector_cache_size)
787 {
788
789 /* Calculate the starting next FAT sector. */
790 FAT_sector = media_ptr -> fx_media_reserved_sectors + i;
791
792 /* Calculate how many sectors to read. */
793 FAT_read_sectors = media_ptr -> fx_media_sectors_per_FAT - i;
794
795 /* Determine if there is not enough memory to read the remaining FAT sectors. */
796 if (FAT_read_sectors > media_ptr -> fx_media_sector_cache_size)
797 {
798 FAT_read_sectors = media_ptr -> fx_media_sector_cache_size;
799 }
800 #else
801 for (i = 0; i < media_ptr -> fx_media_sectors_per_FAT; i++)
802 {
803
804 /* Calculate the starting next FAT sector. */
805 FAT_sector = media_ptr -> fx_media_reserved_sectors + i;
806
807 /* Calculate how many sectors to read. */
808 FAT_read_sectors = 1;
809 #endif /* FX_DISABLE_CACHE */
810
811 /* Read the FAT sectors directly from the driver. */
812 media_ptr -> fx_media_driver_request = FX_DRIVER_READ;
813 media_ptr -> fx_media_driver_status = FX_IO_ERROR;
814 media_ptr -> fx_media_driver_buffer = media_ptr -> fx_media_memory_buffer;
815 media_ptr -> fx_media_driver_logical_sector = FAT_sector;
816 media_ptr -> fx_media_driver_sectors = FAT_read_sectors;
817 media_ptr -> fx_media_driver_sector_type = FX_FAT_SECTOR;
818
819 /* If trace is enabled, insert this event into the trace buffer. */
820 FX_TRACE_IN_LINE_INSERT(FX_TRACE_INTERNAL_IO_DRIVER_READ, media_ptr, FAT_sector, FAT_read_sectors, media_ptr -> fx_media_memory_buffer, FX_TRACE_INTERNAL_EVENTS, 0, 0)
821
822 /* Invoke the driver to read the FAT sectors. */
823 (media_ptr -> fx_media_driver_entry) (media_ptr);
824
825 /* Determine if the read was successful. */
826 if (media_ptr -> fx_media_driver_status != FX_SUCCESS)
827 {
828
829 /* Build the "uninitialize" I/O driver request. */
830 media_ptr -> fx_media_driver_request = FX_DRIVER_UNINIT;
831 media_ptr -> fx_media_driver_status = FX_IO_ERROR;
832
833 /* If trace is enabled, insert this event into the trace buffer. */
834 FX_TRACE_IN_LINE_INSERT(FX_TRACE_INTERNAL_IO_DRIVER_UNINIT, media_ptr, 0, 0, 0, FX_TRACE_INTERNAL_EVENTS, 0, 0)
835
836 /* Call the specified I/O driver with the uninitialize request. */
837 (media_ptr -> fx_media_driver_entry) (media_ptr);
838
839 return(FX_FAT_READ_ERROR);
840 }
841
842 /* Calculate the number of bytes in the buffer. */
843 bytes_in_buffer = (media_ptr -> fx_media_bytes_per_sector * FAT_read_sectors);
844
845 /* Walk through the sector cache memory to search for available clusters and the first
846 available if not already found. */
847 for (j = 0; j < bytes_in_buffer;)
848 {
849
850 /* Check for a 32-bit FAT. */
851 if (media_ptr -> fx_media_32_bit_FAT)
852 {
853
854 /* Pickup 32-bit FAT entry. */
855 FAT_entry = *((ULONG *)&(media_ptr -> fx_media_memory_buffer[j]));
856
857 /* Advance to next FAT entry. */
858 j = j + 4;
859 }
860 else
861 {
862
863 /* Process a 16-bit FAT entry. */
864 FAT_entry = (((ULONG)(media_ptr -> fx_media_memory_buffer[j])) & 0xFF) |
865 ((((ULONG)(media_ptr -> fx_media_memory_buffer[j + 1])) & 0xFF) << 8);
866
867 /* Advance to next FAT entry. */
868 j = j + 2;
869 }
870
871 /* Determine if the FAT entry is free. */
872 if (FAT_entry == FX_FREE_CLUSTER)
873 {
874
875 /* Entry is free, increment available clusters. */
876 media_ptr -> fx_media_available_clusters++;
877
878 /* Determine if the starting free cluster has been found yet. */
879 if (media_ptr -> fx_media_cluster_search_start == 0)
880 {
881
882 /* Remember the first free cluster to start further searches from. */
883 media_ptr -> fx_media_cluster_search_start = cluster_number;
884 }
885 }
886
887 /* Increment the cluster number. */
888 cluster_number++;
889
890 /* Determine if we have reviewed all FAT entries. */
891 if (cluster_number >= (media_ptr -> fx_media_total_clusters + FX_FAT_ENTRY_START))
892 {
893
894 /* Yes, we have looked at all the FAT entries. */
895
896 /* Ensure that the outer loop terminates as well. */
897 i = media_ptr -> fx_media_sectors_per_FAT;
898 break;
899 }
900 }
901 }
902 }
903
904 /* If there were no free clusters, just set the search pointer to the
905 first cluster number. */
906 if (media_ptr -> fx_media_cluster_search_start == 0)
907 {
908 media_ptr -> fx_media_cluster_search_start = FX_FAT_ENTRY_START;
909 }
910
911 /* Setup the current working directory fields to default to the root
912 directory. */
913 media_ptr -> fx_media_default_path.fx_path_directory.fx_dir_entry_name =
914 media_ptr -> fx_media_default_path.fx_path_name_buffer;
915 media_ptr -> fx_media_default_path.fx_path_directory.fx_dir_entry_short_name[0] = 0;
916 media_ptr -> fx_media_default_path.fx_path_directory.fx_dir_entry_name[0] = 0;
917 media_ptr -> fx_media_default_path.fx_path_string[0] = (CHAR)0;
918 media_ptr -> fx_media_default_path.fx_path_string[FX_MAXIMUM_PATH - 1] = (CHAR)0;
919 media_ptr -> fx_media_default_path.fx_path_current_entry = 0;
920
921 #ifndef FX_MEDIA_DISABLE_SEARCH_CACHE
922
923 /* Invalidate the previously found directory entry. */
924 media_ptr -> fx_media_last_found_name[0] = 0;
925 #endif
926
927 #ifndef FX_DISABLE_FORCE_MEMORY_OPERATION
928 /* Initialize the opened file linked list and associated counter. */
929 media_ptr -> fx_media_opened_file_list = FX_NULL;
930 media_ptr -> fx_media_opened_file_count = 0;
931 #endif /* FX_DISABLE_FORCE_MEMORY_OPERATION */
932
933 /* Create the media protection structure if FX_SINGLE_THREAD is not
934 defined. */
935 #ifndef FX_SINGLE_THREAD
936
937 #ifndef FX_DONT_CREATE_MUTEX
938
939 /* Create ThreadX mutex for protection. */
940 tx_mutex_create(&(media_ptr -> fx_media_protect), "FileX Media Mutex", TX_NO_INHERIT);
941 #endif
942
943 #endif
944
945 #ifdef FX_DONT_CREATE_MUTEX
946
947 /* Load the media ID field in the media control block. This allows the FX_PROTECT
948 call to succeed. */
949 media_ptr -> fx_media_id = (ULONG)FX_MEDIA_ID;
950
951 /* Protect against other threads accessing the media. */
952 FX_PROTECT
953 #endif
954
955 /* Lockout interrupts. */
956 FX_DISABLE_INTS
957
958 /* At this point, the media has been opened successfully. Place the
959 media on the linked list of currently opened media. */
960
961 /* Load the media ID field in the media control block. */
962 media_ptr -> fx_media_id = (ULONG)FX_MEDIA_ID;
963
964 /* Place the thread on the list of opened media. First,
965 check for an empty list. */
966 if (_fx_system_media_opened_ptr)
967 {
968
969 /* Pickup tail pointer. */
970 tail_ptr = _fx_system_media_opened_ptr -> fx_media_opened_previous;
971
972 /* Place the new media in the list. */
973 _fx_system_media_opened_ptr -> fx_media_opened_previous = media_ptr;
974 tail_ptr -> fx_media_opened_next = media_ptr;
975
976 /* Setup this media's opened links. */
977 media_ptr -> fx_media_opened_previous = tail_ptr;
978 media_ptr -> fx_media_opened_next = _fx_system_media_opened_ptr;
979 }
980 else
981 {
982
983 /* The opened media list is empty. Add the media to empty list. */
984 _fx_system_media_opened_ptr = media_ptr;
985 media_ptr -> fx_media_opened_next = media_ptr;
986 media_ptr -> fx_media_opened_previous = media_ptr;
987 }
988
989 /* Increment the opened media counter. */
990 _fx_system_media_opened_count++;
991
992 /* Invoke media open callback. */
993 if (media_ptr -> fx_media_open_notify)
994 {
995 media_ptr -> fx_media_open_notify(media_ptr);
996 }
997
998 /* Restore interrupts. */
999 FX_RESTORE_INTS
1000
1001 #ifdef FX_DONT_CREATE_MUTEX
1002
1003 /* Release media protection. */
1004 FX_UNPROTECT
1005 #endif
1006
1007 /* Return a successful status. */
1008 return(FX_SUCCESS);
1009 }
1010
1011