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