GCC Code Coverage Report
Directory: ./ Exec Total Coverage
File: fx_utility_FAT_entry_read.c Lines: 104 104 100.0 %
Date: 2024-01-10 21:53:23 Branches: 46 46 100.0 %

Line Branch Exec Source
1
/**************************************************************************/
2
/*                                                                        */
3
/*       Copyright (c) Microsoft Corporation. All rights reserved.        */
4
/*                                                                        */
5
/*       This software is licensed under the Microsoft Software License   */
6
/*       Terms for Microsoft Azure RTOS. Full text of the license can be  */
7
/*       found in the LICENSE file at https://aka.ms/AzureRTOS_EULA       */
8
/*       and in the root directory of this software.                      */
9
/*                                                                        */
10
/**************************************************************************/
11
12
13
/**************************************************************************/
14
/**************************************************************************/
15
/**                                                                       */
16
/** FileX Component                                                       */
17
/**                                                                       */
18
/**   Utility                                                             */
19
/**                                                                       */
20
/**************************************************************************/
21
/**************************************************************************/
22
23
#define FX_SOURCE_CODE
24
25
26
/* Include necessary system files.  */
27
28
#include "fx_api.h"
29
#include "fx_system.h"
30
#include "fx_utility.h"
31
#ifdef FX_ENABLE_FAULT_TOLERANT
32
#include "fx_fault_tolerant.h"
33
#endif /* FX_ENABLE_FAULT_TOLERANT */
34
35
36
/**************************************************************************/
37
/*                                                                        */
38
/*  FUNCTION                                               RELEASE        */
39
/*                                                                        */
40
/*    _fx_utility_FAT_entry_read                          PORTABLE C      */
41
/*                                                           6.2.0        */
42
/*  AUTHOR                                                                */
43
/*                                                                        */
44
/*    William E. Lamie, Microsoft Corporation                             */
45
/*                                                                        */
46
/*  DESCRIPTION                                                           */
47
/*                                                                        */
48
/*    This function reads the supplied FAT entry from the first FAT of    */
49
/*    the media.  12-bit, 16-bit, and 32-bit FAT reading is supported.    */
50
/*                                                                        */
51
/*  INPUT                                                                 */
52
/*                                                                        */
53
/*    media_ptr                             Media control block pointer   */
54
/*    cluster                               Cluster entry number          */
55
/*    entry_ptr                             Pointer to destination for    */
56
/*                                            the FAT entry               */
57
/*                                                                        */
58
/*  OUTPUT                                                                */
59
/*                                                                        */
60
/*    return status                                                       */
61
/*                                                                        */
62
/*  CALLS                                                                 */
63
/*                                                                        */
64
/*    _fx_utility_16_unsigned_read          Read a UINT from FAT buffer   */
65
/*    _fx_utility_32_unsigned_read          Read a ULONG form FAT buffer  */
66
/*    _fx_utility_FAT_flush                 Flush FAT entry cache         */
67
/*    _fx_utility_logical_sector_read       Read FAT sector into memory   */
68
/*    _fx_fault_tolerant_read_FAT           Read FAT entry from log file  */
69
/*                                                                        */
70
/*  CALLED BY                                                             */
71
/*                                                                        */
72
/*    FileX System Functions                                              */
73
/*                                                                        */
74
/*  RELEASE HISTORY                                                       */
75
/*                                                                        */
76
/*    DATE              NAME                      DESCRIPTION             */
77
/*                                                                        */
78
/*  05-19-2020     William E. Lamie         Initial Version 6.0           */
79
/*  09-30-2020     William E. Lamie         Modified comment(s), and      */
80
/*                                            added conditional to        */
81
/*                                            disable fat entry refresh,  */
82
/*                                            resulting in version 6.1    */
83
/*  10-31-2022     Tiejun Zhou              Modified comment(s), and      */
84
/*                                            fixed compiler warning,     */
85
/*                                            resulting in version 6.2.0  */
86
/*                                                                        */
87
/**************************************************************************/
88
4884690
UINT  _fx_utility_FAT_entry_read(FX_MEDIA *media_ptr, ULONG cluster, ULONG *entry_ptr)
89
{
90
91
ULONG               FAT_sector;
92
ULONG               byte_offset, entry32;
93
UCHAR              *FAT_ptr;
94
UINT                entry, index;
95
UINT                status;
96
FX_FAT_CACHE_ENTRY *cache_entry_ptr;
97
#ifndef FX_DISABLE_FAT_ENTRY_REFRESH
98
FX_FAT_CACHE_ENTRY  temp_cache_entry;
99
#endif /* FX_DISABLE_FAT_ENTRY_REFRESH */
100
101
102
#ifdef FX_ENABLE_FAULT_TOLERANT
103
    if (media_ptr -> fx_media_fault_tolerant_enabled &&
104
        (media_ptr -> fx_media_fault_tolerant_state & FX_FAULT_TOLERANT_STATE_STARTED))
105
    {
106
107
        /* Redirect this request to log file. */
108
        status = _fx_fault_tolerant_read_FAT(media_ptr, cluster, entry_ptr, FX_FAULT_TOLERANT_FAT_LOG_TYPE);
109
110
        /* Return on success. */
111
        if (status != FX_READ_CONTINUE)
112
        {
113
            return(status);
114
        }
115
    }
116
#endif /* FX_ENABLE_FAULT_TOLERANT */
117
118
#ifndef FX_MEDIA_STATISTICS_DISABLE
119
    /* Increment the number of FAT entry reads and cache hits.  */
120
4884690
    media_ptr -> fx_media_fat_entry_reads++;
121
4884690
    media_ptr -> fx_media_fat_entry_cache_read_hits++;
122
#endif
123
124
    /* Extended port-specific processing macro, which is by default defined to white space.  */
125



4884690
    FX_UTILITY_FAT_ENTRY_READ_EXTENSION
126
127
    /* Calculate the area of the cache for this FAT entry.  */
128
4877214
    index =  (cluster & FX_FAT_CACHE_HASH_MASK) * FX_FAT_CACHE_DEPTH;
129
130
    /* Build a pointer to the cache entry.  */
131
4877214
    cache_entry_ptr =  &media_ptr -> fx_media_fat_cache[index];
132
133
#ifndef FX_DISABLE_FAT_ENTRY_REFRESH
134
    /* Determine if the FAT entry is in the cache - assuming the depth of the FAT cache is
135
       4 entries.  */
136
4877214
    if ((cache_entry_ptr -> fx_fat_cache_entry_cluster) == cluster)
137
    {
138
139
        /* Yes, return the cached value.  */
140
2277101
        *entry_ptr =  cache_entry_ptr -> fx_fat_cache_entry_value;
141
142
        /* Don't move anything since we found the entry.  */
143
144
        /* Return a successful status.  */
145
2277101
        return(FX_SUCCESS);
146
    }
147
2600113
    else if (((cache_entry_ptr + 1) -> fx_fat_cache_entry_cluster) == cluster)
148
    {
149
150
        /* Yes, return the cached value.  */
151
115536
        *entry_ptr =  (cache_entry_ptr + 1) -> fx_fat_cache_entry_value;
152
153
        /* Just swap the first and second entry.  */
154
115536
        temp_cache_entry =        *(cache_entry_ptr);
155
115536
        *(cache_entry_ptr) =      *(cache_entry_ptr + 1);
156
115536
        *(cache_entry_ptr + 1) =  temp_cache_entry;
157
158
        /* Return a successful status.  */
159
115536
        return(FX_SUCCESS);
160
    }
161
2484577
    else if (((cache_entry_ptr + 2) -> fx_fat_cache_entry_cluster) == cluster)
162
    {
163
164
        /* Yes, return the cached value.  */
165
105508
        *entry_ptr =  (cache_entry_ptr + 2) -> fx_fat_cache_entry_value;
166
167
        /* Move the third entry to the top and the first two entries down.  */
168
105508
        temp_cache_entry =        *(cache_entry_ptr);
169
105508
        *(cache_entry_ptr) =      *(cache_entry_ptr + 2);
170
105508
        *(cache_entry_ptr + 2) =  *(cache_entry_ptr + 1);
171
105508
        *(cache_entry_ptr + 1) =  temp_cache_entry;
172
173
        /* Return a successful status.  */
174
105508
        return(FX_SUCCESS);
175
    }
176
2379069
    else if (((cache_entry_ptr + 3) -> fx_fat_cache_entry_cluster) == cluster)
177
    {
178
179
        /* Yes, return the cached value.  */
180
99796
        *entry_ptr =  (cache_entry_ptr + 3) -> fx_fat_cache_entry_value;
181
182
        /* Move the last entry to the top and the first three entries down.  */
183
99796
        temp_cache_entry =        *(cache_entry_ptr);
184
99796
        *(cache_entry_ptr) =      *(cache_entry_ptr + 3);
185
99796
        *(cache_entry_ptr + 3) =  *(cache_entry_ptr + 2);
186
99796
        *(cache_entry_ptr + 2) =  *(cache_entry_ptr + 1);
187
99796
        *(cache_entry_ptr + 1) =  temp_cache_entry;
188
189
        /* Return a successful status.  */
190
99796
        return(FX_SUCCESS);
191
    }
192
#else
193
    for (UINT i = 0; i < 4; i++)
194
    {
195
        if (((cache_entry_ptr + i) -> fx_fat_cache_entry_cluster) == cluster)
196
        {
197
            *entry_ptr =  (cache_entry_ptr + i) -> fx_fat_cache_entry_value;
198
199
            /* Return a successful status.  */
200
            return(FX_SUCCESS);
201
        }
202
    }
203
#endif /* FX_DISABLE_FAT_ENTRY_REFRESH */
204
205
    /* Determine if the oldest entry was modified, i.e. whether or not it is
206
       dirty.  */
207
2279273
    if (media_ptr -> fx_media_fat_cache[index + 3].fx_fat_cache_entry_dirty)
208
    {
209
210
        /* Yes, the entry is dirty and needs to be flushed out.  */
211
25285
        status = _fx_utility_FAT_flush(media_ptr);
212
213
        /* Check for completion status.  */
214
25285
        if (status != FX_SUCCESS)
215
        {
216
217
            /* Return error status.  */
218
20325
            return(status);
219
        }
220
    }
221
222
    /* If we get here, the entry was not found in the FAT entry cache.  We need to
223
       actually read the FAT entry.  */
224
225
#ifndef FX_MEDIA_STATISTICS_DISABLE
226
227
    /* Decrement the number of cache hits.  */
228
2258948
    media_ptr -> fx_media_fat_entry_cache_read_hits--;
229
230
    /* Increment the number of cache misses.  */
231
2258948
    media_ptr -> fx_media_fat_entry_cache_read_misses++;
232
#endif
233
234
    /* Determine which type of FAT is present.  */
235
2258948
    if (media_ptr -> fx_media_12_bit_FAT)
236
    {
237
238
        /* Calculate the byte offset to the cluster entry.  */
239
601625
        byte_offset =  (((ULONG)cluster << 1) + cluster) >> 1;
240
241
        /* Calculate the FAT sector the requested FAT entry resides in.  */
242
601625
        FAT_sector =  (byte_offset / media_ptr -> fx_media_bytes_per_sector) +
243
601625
            (ULONG)media_ptr -> fx_media_reserved_sectors;
244
245
        /* Read the sector in.  */
246
601625
        status =  _fx_utility_logical_sector_read(media_ptr, (ULONG64) FAT_sector,
247
601625
                                                  media_ptr -> fx_media_memory_buffer, ((ULONG) 1), FX_FAT_SECTOR);
248
249
        /* Determine if an error occurred.  */
250
601625
        if (status != FX_SUCCESS)
251
        {
252
            /* Return the error status.  */
253
196710
            return(status);
254
        }
255
256
        /* Now calculate the byte offset into this FAT sector.  */
257
404915
        byte_offset =  byte_offset -
258
404915
            ((FAT_sector - (ULONG)media_ptr -> fx_media_reserved_sectors) *
259
404915
             media_ptr -> fx_media_bytes_per_sector);
260
261
        /* Setup a pointer into the buffer.  */
262
404915
        FAT_ptr =  (UCHAR *)media_ptr -> fx_media_memory_buffer + (UINT)byte_offset;
263
264
        /* Determine if the cluster entry is odd or even.  */
265
404915
        if (cluster & 1)
266
        {
267
268
            /* Odd cluster number.  */
269
270
            /* Pickup the lower nibble of the FAT entry.  */
271
204251
            entry =  (((UINT)*FAT_ptr) & 0xF0) >> 4;
272
273
            /* Move to the next byte of the FAT entry.  */
274
204251
            FAT_ptr++;
275
276
            /* Determine if we are now past the end of the FAT buffer in memory.  */
277
204251
            if (byte_offset == (ULONG)(media_ptr -> fx_media_bytes_per_sector - 1))
278
            {
279
280
                /* Yes, we need to read the next sector.  */
281
1624
                FAT_sector++;
282
1624
                status =  _fx_utility_logical_sector_read(media_ptr, (ULONG64) FAT_sector,
283
1624
                                                          media_ptr -> fx_media_memory_buffer, ((ULONG) 1), FX_FAT_SECTOR);
284
285
                /* Determine if an error occurred.  */
286
1624
                if (status != FX_SUCCESS)
287
                {
288
289
                    /* Return the error status.  */
290
419
                    return(status);
291
                }
292
293
                /* Setup a pointer into the buffer.  */
294
1205
                FAT_ptr =  (UCHAR *)media_ptr -> fx_media_memory_buffer;
295
            }
296
297
            /* Pickup the upper 8 bits of the FAT entry.  */
298
203832
            entry =  entry | (((UINT)*FAT_ptr) << 4);
299
        }
300
        else
301
        {
302
303
            /* Even cluster number.  */
304
305
            /* Pickup the lower byte of the FAT entry.  */
306
200664
            entry =  (UINT)(((UINT)*FAT_ptr) & 0xFF);
307
308
            /* Move to the next nibble of the FAT entry.  */
309
200664
            FAT_ptr++;
310
311
            /* Determine if we are now past the end of the FAT buffer in memory.  */
312
200664
            if (byte_offset == (ULONG)(media_ptr -> fx_media_bytes_per_sector - 1))
313
            {
314
315
                /* Yes, we need to read the next sector.  */
316
1473
                FAT_sector++;
317
1473
                status =  _fx_utility_logical_sector_read(media_ptr, (ULONG64) FAT_sector,
318
1473
                                                          media_ptr -> fx_media_memory_buffer, ((ULONG) 1), FX_FAT_SECTOR);
319
320
                /* Determine if an error occurred.  */
321
1473
                if (status != FX_SUCCESS)
322
                {
323
351
                    return(status);
324
                }
325
326
                /* Setup a pointer into the buffer.  */
327
1122
                FAT_ptr =  (UCHAR *)media_ptr -> fx_media_memory_buffer;
328
            }
329
330
            /* Pickup the upper 4 bits of the FAT entry.  */
331
200313
            entry =  entry | ((((UINT)*FAT_ptr) & 0x0F) << 8);
332
        }
333
334
        /* Determine if we need to do sign extension on the 12-bit eof value.  */
335
404145
        if (entry >= FX_MAX_12BIT_CLUST)
336
        {
337
338
            /* Yes, we need to sign extend.  */
339
177
            entry =  entry | FX_SIGN_EXTEND;
340
        }
341
342
404145
        *entry_ptr =  entry;
343
    }
344
345
    /* Check for a 16-bit FAT.  */
346
#ifdef FX_ENABLE_EXFAT
347
    else if (FX_FAT16  == media_ptr -> fx_media_FAT_type)
348
#else
349
1657323
    else if (!media_ptr -> fx_media_32_bit_FAT)
350
#endif /* FX_ENABLE_EXFAT */
351
    {
352
353
        /* 16-bit FAT is present.  */
354
355
        /* Calculate the byte offset to the cluster entry.  */
356
863457
        byte_offset =  (((ULONG)cluster) * 2);
357
358
        /* Calculate the FAT sector the requested FAT entry resides in.  */
359
863457
        FAT_sector =  (byte_offset / media_ptr -> fx_media_bytes_per_sector) +
360
863457
            (ULONG)media_ptr -> fx_media_reserved_sectors;
361
362
        /* Read the FAT sector.  */
363
863457
        status =  _fx_utility_logical_sector_read(media_ptr, (ULONG64) FAT_sector,
364
863457
                                                  media_ptr -> fx_media_memory_buffer, ((ULONG) 1), FX_FAT_SECTOR);
365
366
        /* Determine if an error occurred.  */
367
863457
        if (status != FX_SUCCESS)
368
        {
369
370
            /* Return the error code.  */
371
198415
            return(status);
372
        }
373
374
        /* Now calculate the byte offset into this FAT sector.  */
375
665042
        byte_offset =  byte_offset -
376
665042
            ((FAT_sector - (ULONG)media_ptr -> fx_media_reserved_sectors) *
377
665042
             media_ptr -> fx_media_bytes_per_sector);
378
379
        /* Setup a pointer into the buffer.  */
380
665042
        FAT_ptr =  (UCHAR *)media_ptr -> fx_media_memory_buffer + (UINT)byte_offset;
381
382
        /* Pickup the FAT entry.  */
383
665042
        entry =  _fx_utility_16_unsigned_read(FAT_ptr);
384
385
665042
        *entry_ptr =  entry;
386
    }
387
#ifdef FX_ENABLE_EXFAT
388
    else if ((media_ptr -> fx_media_FAT_type == FX_FAT32) ||
389
             (media_ptr -> fx_media_FAT_type == FX_exFAT))
390
#else
391
    else
392
#endif /* FX_ENABLE_EXFAT */
393
    {
394
395
        /* Otherwise, a 32 bit FAT present.  */
396
793866
        byte_offset =  (((ULONG)cluster) * 4);
397
398
        /* Calculate the FAT sector the requested FAT entry resides in.  */
399
793866
        FAT_sector =  (byte_offset / media_ptr -> fx_media_bytes_per_sector) +
400
793866
            (ULONG)media_ptr -> fx_media_reserved_sectors;
401
402
        /* Calculate the byte offset to the FAT entry.  */
403
793866
        byte_offset = (byte_offset % media_ptr -> fx_media_bytes_per_sector);
404
405
        /* Read the appropriate FAT sector.  */
406
793866
        status =  _fx_utility_logical_sector_read(media_ptr, (ULONG64) FAT_sector,
407
793866
                                                  media_ptr -> fx_media_memory_buffer, ((ULONG) 1), FX_FAT_SECTOR);
408
409
        /* Determine if an error occurred.  */
410
793866
        if (status != FX_SUCCESS)
411
        {
412
413
            /* Return the error code.  */
414
197161
            return(status);
415
        }
416
417
        /* Setup a pointer into the buffer.  */
418
596705
        FAT_ptr =  (UCHAR *)media_ptr -> fx_media_memory_buffer + (ULONG)byte_offset;
419
420
        /* Pickup the FAT entry.  */
421
596705
        entry32 =  _fx_utility_32_unsigned_read(FAT_ptr);
422
423
#ifdef FX_ENABLE_EXFAT
424
        /* FAT32 uses 28 bit cluster addressing but  exFAT uses 32 bit.  */
425
        if (media_ptr -> fx_media_FAT_type == FX_FAT32)
426
        {
427
#endif /* FX_ENABLE_EXFAT */
428
429
            /* Clear upper nibble.  */
430
596705
            entry32 = entry32 & 0x0FFFFFFF;
431
#ifdef FX_ENABLE_EXFAT
432
        }
433
#endif /* FX_ENABLE_EXFAT */
434
435
596705
        *entry_ptr =  entry32;
436
    }
437
438
    /* Move all the cache entries down so the oldest is at the bottom.  */
439
1665892
    *(cache_entry_ptr + 3) =  *(cache_entry_ptr + 2);
440
1665892
    *(cache_entry_ptr + 2) =  *(cache_entry_ptr + 1);
441
1665892
    *(cache_entry_ptr + 1) =  *(cache_entry_ptr);
442
443
    /* Setup the new FAT entry in the cache.  */
444
1665892
    cache_entry_ptr -> fx_fat_cache_entry_cluster =  cluster;
445
1665892
    cache_entry_ptr -> fx_fat_cache_entry_value   =  *entry_ptr;
446
447
    /* Return success to the caller.  */
448
1665892
    return(FX_SUCCESS);
449
}
450