GCC Code Coverage Report
Directory: ./ Exec Total Coverage
File: fx_utility_FAT_entry_read.c Lines: 104 104 100.0 %
Date: 2026-03-06 18:49:02 Branches: 46 46 100.0 %

Line Branch Exec Source
1
/***************************************************************************
2
 * Copyright (c) 2024 Microsoft Corporation
3
 * Copyright (c) 2026-present Eclipse ThreadX contributors
4
 *
5
 * This program and the accompanying materials are made available under the
6
 * terms of the MIT License which is available at
7
 * https://opensource.org/licenses/MIT.
8
 *
9
 * SPDX-License-Identifier: MIT
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
/**************************************************************************/
75
4884690
UINT  _fx_utility_FAT_entry_read(FX_MEDIA *media_ptr, ULONG cluster, ULONG *entry_ptr)
76
{
77
78
ULONG               FAT_sector;
79
ULONG               byte_offset, entry32;
80
UCHAR              *FAT_ptr;
81
UINT                entry, index;
82
UINT                status;
83
FX_FAT_CACHE_ENTRY *cache_entry_ptr;
84
#ifndef FX_DISABLE_FAT_ENTRY_REFRESH
85
FX_FAT_CACHE_ENTRY  temp_cache_entry;
86
#endif /* FX_DISABLE_FAT_ENTRY_REFRESH */
87
88
89
#ifdef FX_ENABLE_FAULT_TOLERANT
90
    if (media_ptr -> fx_media_fault_tolerant_enabled &&
91
        (media_ptr -> fx_media_fault_tolerant_state & FX_FAULT_TOLERANT_STATE_STARTED))
92
    {
93
94
        /* Redirect this request to log file. */
95
        status = _fx_fault_tolerant_read_FAT(media_ptr, cluster, entry_ptr, FX_FAULT_TOLERANT_FAT_LOG_TYPE);
96
97
        /* Return on success. */
98
        if (status != FX_READ_CONTINUE)
99
        {
100
            return(status);
101
        }
102
    }
103
#endif /* FX_ENABLE_FAULT_TOLERANT */
104
105
#ifndef FX_MEDIA_STATISTICS_DISABLE
106
/* Increment the number of FAT entry reads and cache hits.  */
107
4884690
media_ptr -> fx_media_fat_entry_reads++;
108
4884690
media_ptr -> fx_media_fat_entry_cache_read_hits++;
109
#endif
110
111
/* Extended port-specific processing macro, which is by default defined to white space.  */
112



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