GCC Code Coverage Report
Directory: ./ Exec Total Coverage
File: fx_media_boot_info_extract.c Lines: 30 30 100.0 %
Date: 2024-01-10 21:53:23 Branches: 16 16 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
/**   Media                                                               */
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_media.h"
31
#include "fx_utility.h"
32
33
34
/**************************************************************************/
35
/*                                                                        */
36
/*  FUNCTION                                               RELEASE        */
37
/*                                                                        */
38
/*    _fx_media_boot_info_extract                         PORTABLE C      */
39
/*                                                           6.1.10       */
40
/*  AUTHOR                                                                */
41
/*                                                                        */
42
/*    William E. Lamie, Microsoft Corporation                             */
43
/*                                                                        */
44
/*  DESCRIPTION                                                           */
45
/*                                                                        */
46
/*    This function extracts and validates the information from the boot  */
47
/*    record found in the memory buffer.  If the boot record is invalid,  */
48
/*    an FX_MEDIA_INVALID status is returned to the caller.               */
49
/*                                                                        */
50
/*    The FAT boot sector (512 bytes) that is operated on by this         */
51
/*    function must look like the following:                              */
52
/*                                                                        */
53
/*          Byte Offset         Meaning             Size                  */
54
/*                                                                        */
55
/*            0x000         Jump Instructions        3                    */
56
/*            0x003         OEM Name                 8                    */
57
/*            0x00B        *Bytes per Sector         2                    */
58
/*            0x00D        *Sectors per Cluster      1                    */
59
/*            0x00E        *Reserved Sectors         2                    */
60
/*            0x010        *Number of FATs           1                    */
61
/*            0x011        *Max Root Dir Entries     2                    */
62
/*            0x013        *Number of Sectors        2                    */
63
/*            0x015         Media Type               1                    */
64
/*            0x016        *Sectors per FAT          2                    */
65
/*            0x018        *Sectors per Track        2                    */
66
/*            0x01A        *Number of Heads          2                    */
67
/*            0x01C        *Hidden Sectors           4                    */
68
/*            0x020        *Huge Sectors             4                    */
69
/*            0x024         Drive Number             1                    */
70
/*            0x025         Reserved                 1                    */
71
/*            0x026         Boot Signature           1                    */
72
/*            0x027         Volume ID                4                    */
73
/*            0x02B         Volume Label             11                   */
74
/*            0x036         File System Type         8                    */
75
/*             ...              ...                 ...                   */
76
/*            0x1FE       **Signature (0x55aa)       2                    */
77
/*                                                                        */
78
/*            * Denotes which elements of the boot record                 */
79
/*              FileX uses.                                               */
80
/*                                                                        */
81
/*            **Denotes the element is checked by the I/O                 */
82
/*              driver.  This eliminates the need for a minimum           */
83
/*              512-byte buffer for FileX.                                */
84
/*                                                                        */
85
/*  Note: All values above are in little endian format, i.e. the LSB is   */
86
/*        in the lowest address.                                          */
87
/*                                                                        */
88
/*  INPUT                                                                 */
89
/*                                                                        */
90
/*    media_ptr                             Media control block pointer   */
91
/*                                                                        */
92
/*  OUTPUT                                                                */
93
/*                                                                        */
94
/*    return status                                                       */
95
/*                                                                        */
96
/*  CALLS                                                                 */
97
/*                                                                        */
98
/*    _fx_utility_16_unsigned_read          Read a UINT from buffer       */
99
/*    _fx_utility_32_unsigned_read          Read a ULONG from buffer      */
100
/*    _fx_utility_64_unsigned_read          Read a ULONG64 from memory    */
101
/*                                                                        */
102
/*  CALLED BY                                                             */
103
/*                                                                        */
104
/*    _fx_media_open                        Media open function           */
105
/*                                                                        */
106
/*  RELEASE HISTORY                                                       */
107
/*                                                                        */
108
/*    DATE              NAME                      DESCRIPTION             */
109
/*                                                                        */
110
/*  05-19-2020     William E. Lamie         Initial Version 6.0           */
111
/*  09-30-2020     William E. Lamie         Modified comment(s),          */
112
/*                                            resulting in version 6.1    */
113
/*  01-31-2022     Bhupendra Naphade        Modified comment(s), added    */
114
/*                                            check for bimap cache size, */
115
/*                                            resulting in version 6.1.10 */
116
/*                                                                        */
117
/**************************************************************************/
118
6028
UINT  _fx_media_boot_info_extract(FX_MEDIA *media_ptr)
119
{
120
121
UCHAR *boot_sector;
122
123
124
    /* Move the buffer pointer into a local copy.  */
125
6028
    boot_sector =  media_ptr -> fx_media_driver_buffer;
126
127
    /* Extract the number of bytes per sector.  */
128
6028
    media_ptr -> fx_media_bytes_per_sector =    _fx_utility_16_unsigned_read(&boot_sector[FX_BYTES_SECTOR]);
129
6028
    if (media_ptr -> fx_media_bytes_per_sector == 0)
130
#ifdef FX_ENABLE_EXFAT
131
    {
132
        /* Treat as exFAT volume.  */
133
        /* Extract the number of bytes per sector.  */
134
        media_ptr -> fx_media_exfat_bytes_per_sector_shift = boot_sector[FX_EF_BYTE_PER_SECTOR_SHIFT];
135
136
        /* exFAT requires minimal value 9 (512 bytes) and maximum value 12(4096 bytes) for bytes_per_sector_shift */
137
        if((media_ptr -> fx_media_exfat_bytes_per_sector_shift < 9) || (media_ptr -> fx_media_exfat_bytes_per_sector_shift > 12))
138
        {
139
            return(FX_MEDIA_INVALID);
140
        }
141
142
        media_ptr -> fx_media_bytes_per_sector = (UINT)(1 << media_ptr -> fx_media_exfat_bytes_per_sector_shift);
143
144
        /* Validate bytes per sector value: no more than bitmap cache size */
145
        if (media_ptr -> fx_media_bytes_per_sector > sizeof(media_ptr -> fx_media_exfat_bitmap_cache))
146
        {
147
            return(FX_NOT_ENOUGH_MEMORY);
148
        }
149
150
        media_ptr -> fx_media_total_sectors = _fx_utility_64_unsigned_read(&boot_sector[FX_EF_VOLUME_LENGTH]);
151
        if (media_ptr -> fx_media_total_sectors == 0)
152
        {
153
            return(FX_MEDIA_INVALID);
154
        }
155
156
        media_ptr -> fx_media_reserved_sectors = _fx_utility_32_unsigned_read(&boot_sector[FX_EF_FAT_OFFSET]);
157
        if (media_ptr -> fx_media_reserved_sectors == 0)
158
        {
159
            return(FX_MEDIA_INVALID);
160
        }
161
162
        media_ptr -> fx_media_sectors_per_FAT = _fx_utility_32_unsigned_read(&boot_sector[FX_EF_FAT_LENGTH]);
163
        if (media_ptr -> fx_media_sectors_per_FAT == 0)
164
        {
165
            return(FX_MEDIA_INVALID);
166
        }
167
168
        media_ptr -> fx_media_data_sector_start = _fx_utility_32_unsigned_read(&boot_sector[FX_EF_CLUSTER_HEAP_OFFSET]);
169
        if (media_ptr -> fx_media_data_sector_start == 0)
170
        {
171
            return(FX_MEDIA_INVALID);
172
        }
173
174
        media_ptr -> fx_media_total_clusters = _fx_utility_32_unsigned_read(&boot_sector[FX_EF_CLUSTER_COUNT]);
175
        if (media_ptr -> fx_media_total_clusters == 0)
176
        {
177
            return(FX_MEDIA_INVALID);
178
        }
179
180
        media_ptr -> fx_media_exfat_sector_per_clusters_shift = boot_sector[FX_EF_SECTOR_PER_CLUSTER_SHIFT];
181
        if (media_ptr -> fx_media_exfat_sector_per_clusters_shift > 25 - media_ptr -> fx_media_exfat_bytes_per_sector_shift)
182
        {
183
            return(FX_MEDIA_INVALID);
184
        }
185
        media_ptr -> fx_media_sectors_per_cluster = (UINT)(1 << media_ptr -> fx_media_exfat_sector_per_clusters_shift);
186
187
        media_ptr -> fx_media_number_of_FATs = boot_sector[FX_EF_NUMBER_OF_FATS];
188
        if (media_ptr -> fx_media_number_of_FATs == 0)
189
        {
190
            return(FX_MEDIA_INVALID);
191
        }
192
193
        media_ptr -> fx_media_root_cluster_32    = _fx_utility_32_unsigned_read(&boot_sector[FX_EF_FIRST_CLUSTER_OF_ROOT_DIR]);
194
        /* Root cluster starts from at least FX_FAT_ENTRY_START (2), or higher. */
195
        if (media_ptr -> fx_media_root_cluster_32 < FX_FAT_ENTRY_START)
196
        {
197
            return(FX_MEDIA_INVALID);
198
        }
199
200
        /* Overflow check. */
201
        if (((ULONG64)media_ptr -> fx_media_data_sector_start +
202
             (ULONG64)(media_ptr -> fx_media_root_cluster_32 - FX_FAT_ENTRY_START) *
203
             media_ptr -> fx_media_sectors_per_cluster) > 0xFFFFFFFF)
204
        {
205
206
            /* Return the invalid media error status.  */
207
            return(FX_MEDIA_INVALID);
208
        }
209
210
        /* Calculate logical number of root dir sector.  */
211
        media_ptr -> fx_media_root_sector_start = media_ptr -> fx_media_data_sector_start +
212
            (media_ptr -> fx_media_root_cluster_32 - FX_FAT_ENTRY_START) *
213
            media_ptr -> fx_media_sectors_per_cluster;
214
215
        media_ptr -> fx_media_exfat_volume_serial_number  = _fx_utility_32_unsigned_read(&boot_sector[FX_EF_VOLUME_SERIAL_NUMBER]);
216
217
        media_ptr -> fx_media_exfat_file_system_revision  = _fx_utility_16_unsigned_read(&boot_sector[FX_EF_FILE_SYSTEM_REVISION]);
218
219
        media_ptr -> fx_media_exfat_volume_flag          = _fx_utility_16_unsigned_read(&boot_sector[FX_EF_VOLUME_FLAGS]);
220
221
        media_ptr -> fx_media_number_of_FATs = boot_sector[FX_EF_NUMBER_OF_FATS];
222
223
        if (0 == media_ptr -> fx_media_number_of_FATs)
224
        {
225
            return(FX_MEDIA_INVALID);
226
        }
227
228
        /* Extract the number of hidden sectors.  */
229
#ifdef FX_DRIVER_USE_64BIT_LBA
230
        media_ptr -> fx_media_hidden_sectors =      _fx_utility_64_unsigned_read(&boot_sector[FX_EF_PARTITION_OFFSET]);
231
#else
232
        media_ptr -> fx_media_hidden_sectors =      _fx_utility_32_unsigned_read(&boot_sector[FX_EF_PARTITION_OFFSET]);
233
#endif
234
235
        media_ptr -> fx_media_exfat_drive_select       = boot_sector[FX_EF_DRIVE_SELECT];
236
        media_ptr -> fx_media_exfat_percent_in_use       = boot_sector[FX_EF_PERCENT_IN_USE];
237
238
        media_ptr -> fx_media_12_bit_FAT = FX_FALSE;
239
        media_ptr -> fx_media_32_bit_FAT = FX_FALSE;
240
241
        /* Legacy code support:
242
           We will use fx_media_FAT_type for determine FAT type instead of
243
           fx_media_12_bit_FAT and fx_media_32_bit_FAT.  */
244
        media_ptr -> fx_media_12_bit_FAT = FX_FALSE;
245
        media_ptr -> fx_media_32_bit_FAT = FX_FALSE;
246
247
        media_ptr -> fx_media_FAT_type = FX_exFAT;
248
249
        return(_fx_utility_exFAT_geometry_check(media_ptr, boot_sector));
250
    }
251
    else
252
    {
253
#else
254
1
        return(FX_MEDIA_INVALID);
255
#endif /* FX_ENABLE_EXFAT */
256
257
258
        /* FAT12/16/32 volume.  */
259
        /* Extract the number of sectors per track.  */
260
6027
        media_ptr -> fx_media_sectors_per_track =   _fx_utility_16_unsigned_read(&boot_sector[FX_SECTORS_PER_TRK]);
261
262
        /* Extract the number of heads.  */
263
6027
        media_ptr -> fx_media_heads =               _fx_utility_16_unsigned_read(&boot_sector[FX_HEADS]);
264
265
        /* Extract the total number of sectors.  */
266
6027
        media_ptr -> fx_media_total_sectors =       _fx_utility_16_unsigned_read(&boot_sector[FX_SECTORS]);
267
6027
        if (media_ptr -> fx_media_total_sectors == 0)
268
        {
269
3834
            media_ptr -> fx_media_total_sectors = _fx_utility_32_unsigned_read(&boot_sector[FX_HUGE_SECTORS]);
270
        }
271
272
6027
        if (media_ptr -> fx_media_total_sectors == 0)
273
        {
274
1
            return(FX_MEDIA_INVALID);
275
        }
276
277
        /* Extract the number of reserved sectors before the first FAT.  */
278
6026
        media_ptr -> fx_media_reserved_sectors =    _fx_utility_16_unsigned_read(&boot_sector[FX_RESERVED_SECTORS]);
279
6026
        if (media_ptr -> fx_media_reserved_sectors == 0)
280
        {
281
1
            return(FX_MEDIA_INVALID);
282
        }
283
284
        /* Extract the number of sectors per cluster.  */
285
6025
        media_ptr -> fx_media_sectors_per_cluster = ((UINT)boot_sector[FX_SECTORS_CLUSTER] & 0xFF);
286
287
        /* There should always be at least one reserved sector, representing the boot record itself.  */
288
6025
        if (media_ptr -> fx_media_sectors_per_cluster == 0)
289
        {
290
1
            return(FX_MEDIA_INVALID);
291
        }
292
293
        /* Extract the number of sectors per FAT.  */
294
6024
        media_ptr -> fx_media_sectors_per_FAT =     _fx_utility_16_unsigned_read(&boot_sector[FX_SECTORS_PER_FAT]);
295
6024
        if (media_ptr -> fx_media_sectors_per_FAT == 0)
296
        {
297
3833
            media_ptr -> fx_media_sectors_per_FAT = _fx_utility_32_unsigned_read(&boot_sector[FX_SECTORS_PER_FAT_32]);
298
        }
299
300
6024
        if (media_ptr -> fx_media_sectors_per_FAT == 0)
301
        {
302
1
            return(FX_MEDIA_INVALID);
303
        }
304
305
        /* Extract the number of FATs.  */
306
6023
        media_ptr -> fx_media_number_of_FATs =      ((UINT)boot_sector[FX_NUMBER_OF_FATS] & 0xFF);
307
6023
        if (media_ptr -> fx_media_number_of_FATs == 0)
308
        {
309
1
            return(FX_BOOT_ERROR);
310
        }
311
312
        /* Extract the number of hidden sectors.  */
313
#ifdef FX_DRIVER_USE_64BIT_LBA
314
        media_ptr -> fx_media_hidden_sectors =      _fx_utility_64_unsigned_read(&boot_sector[FX_HIDDEN_SECTORS]);
315
#else
316
6022
        media_ptr -> fx_media_hidden_sectors =      _fx_utility_32_unsigned_read(&boot_sector[FX_HIDDEN_SECTORS]);
317
#endif
318
        /* Extract the number of root directory entries.  */
319
6022
        media_ptr -> fx_media_root_directory_entries =  _fx_utility_16_unsigned_read(&boot_sector[FX_ROOT_DIR_ENTRIES]);
320
321
        /* Extract root directory starting cluster (32 bit only) and compute start sector */
322
6022
        media_ptr -> fx_media_root_cluster_32 = _fx_utility_32_unsigned_read(&boot_sector[FX_ROOT_CLUSTER_32]);
323
324
#ifdef FX_ENABLE_EXFAT
325
    }
326
#endif /* FX_ENABLE_EXFAT */
327
328
    /* Return a successful status.  */
329
6022
    return(FX_SUCCESS);
330
}
331