GCC Code Coverage Report
Directory: ./ Exec Total Coverage
File: fx_utility_FAT_entry_read.c Lines: 104 104 100.0 %
Date: 2024-03-11 05:15:45 Branches: 46 46 100.0 %

Line Branch Exec Source
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
/**   Utility                                                             */
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_utility.h"
30
#ifdef FX_ENABLE_FAULT_TOLERANT
31
#include "fx_fault_tolerant.h"
32
#endif /* FX_ENABLE_FAULT_TOLERANT */
33
34
35
/**************************************************************************/
36
/*                                                                        */
37
/*  FUNCTION                                               RELEASE        */
38
/*                                                                        */
39
/*    _fx_utility_FAT_entry_read                          PORTABLE C      */
40
/*                                                           6.2.0        */
41
/*  AUTHOR                                                                */
42
/*                                                                        */
43
/*    William E. Lamie, Microsoft Corporation                             */
44
/*                                                                        */
45
/*  DESCRIPTION                                                           */
46
/*                                                                        */
47
/*    This function reads the supplied FAT entry from the first FAT of    */
48
/*    the media.  12-bit, 16-bit, and 32-bit FAT reading is supported.    */
49
/*                                                                        */
50
/*  INPUT                                                                 */
51
/*                                                                        */
52
/*    media_ptr                             Media control block pointer   */
53
/*    cluster                               Cluster entry number          */
54
/*    entry_ptr                             Pointer to destination for    */
55
/*                                            the FAT entry               */
56
/*                                                                        */
57
/*  OUTPUT                                                                */
58
/*                                                                        */
59
/*    return status                                                       */
60
/*                                                                        */
61
/*  CALLS                                                                 */
62
/*                                                                        */
63
/*    _fx_utility_16_unsigned_read          Read a UINT from FAT buffer   */
64
/*    _fx_utility_32_unsigned_read          Read a ULONG form FAT buffer  */
65
/*    _fx_utility_FAT_flush                 Flush FAT entry cache         */
66
/*    _fx_utility_logical_sector_read       Read FAT sector into memory   */
67
/*    _fx_fault_tolerant_read_FAT           Read FAT entry from log file  */
68
/*                                                                        */
69
/*  CALLED BY                                                             */
70
/*                                                                        */
71
/*    FileX System Functions                                              */
72
/*                                                                        */
73
/*  RELEASE HISTORY                                                       */
74
/*                                                                        */
75
/*    DATE              NAME                      DESCRIPTION             */
76
/*                                                                        */
77
/*  05-19-2020     William E. Lamie         Initial Version 6.0           */
78
/*  09-30-2020     William E. Lamie         Modified comment(s), and      */
79
/*                                            added conditional to        */
80
/*                                            disable fat entry refresh,  */
81
/*                                            resulting in version 6.1    */
82
/*  10-31-2022     Tiejun Zhou              Modified comment(s), and      */
83
/*                                            fixed compiler warning,     */
84
/*                                            resulting in version 6.2.0  */
85
/*                                                                        */
86
/**************************************************************************/
87
4884690
UINT  _fx_utility_FAT_entry_read(FX_MEDIA *media_ptr, ULONG cluster, ULONG *entry_ptr)
88
{
89
90
ULONG               FAT_sector;
91
ULONG               byte_offset, entry32;
92
UCHAR              *FAT_ptr;
93
UINT                entry, index;
94
UINT                status;
95
FX_FAT_CACHE_ENTRY *cache_entry_ptr;
96
#ifndef FX_DISABLE_FAT_ENTRY_REFRESH
97
FX_FAT_CACHE_ENTRY  temp_cache_entry;
98
#endif /* FX_DISABLE_FAT_ENTRY_REFRESH */
99
100
101
#ifdef FX_ENABLE_FAULT_TOLERANT
102
    if (media_ptr -> fx_media_fault_tolerant_enabled &&
103
        (media_ptr -> fx_media_fault_tolerant_state & FX_FAULT_TOLERANT_STATE_STARTED))
104
    {
105
106
        /* Redirect this request to log file. */
107
        status = _fx_fault_tolerant_read_FAT(media_ptr, cluster, entry_ptr, FX_FAULT_TOLERANT_FAT_LOG_TYPE);
108
109
        /* Return on success. */
110
        if (status != FX_READ_CONTINUE)
111
        {
112
            return(status);
113
        }
114
    }
115
#endif /* FX_ENABLE_FAULT_TOLERANT */
116
117
#ifndef FX_MEDIA_STATISTICS_DISABLE
118
/* Increment the number of FAT entry reads and cache hits.  */
119
4884690
media_ptr -> fx_media_fat_entry_reads++;
120
4884690
media_ptr -> fx_media_fat_entry_cache_read_hits++;
121
#endif
122
123
/* Extended port-specific processing macro, which is by default defined to white space.  */
124



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