GCC Code Coverage Report
Directory: ./ Exec Total Coverage
File: fx_media_format.c Lines: 181 181 100.0 %
Date: 2024-03-11 05:15:45 Branches: 72 72 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
/**   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_media.h"
29
#include "fx_utility.h"
30
31
32
/* Define global variables necessary for formatting.  */
33
34
/* Define OEM Name. This name must be 8 characters long and be blank padded.
35
   The default may be changed by modifying this file or calling the
36
   fx_media_format_oem_name_set utility prior to calling fx_media_format.  */
37
38
UCHAR   _fx_media_format_oem_name[8] = "EL FILEX";
39
40
41
/* Define the default media type.  This default may be changed by modifying
42
   this file or calling the fx_media_format_type_set utility prior to calling
43
   fx_media_format.  */
44
45
UCHAR _fx_media_format_media_type =  0xF8;
46
47
48
/* Define the default volume ID.  This default may be changed by modifying
49
   this file or calling the fx_media_format_volume_id_set utility prior to calling
50
   fx_media_format.  */
51
52
ULONG _fx_media_format_volume_id =  1;
53
54
55
/**************************************************************************/
56
/*                                                                        */
57
/*  FUNCTION                                               RELEASE        */
58
/*                                                                        */
59
/*    _fx_media_format                                    PORTABLE C      */
60
/*                                                           6.1.11       */
61
/*  AUTHOR                                                                */
62
/*                                                                        */
63
/*    William E. Lamie, Microsoft Corporation                             */
64
/*                                                                        */
65
/*  DESCRIPTION                                                           */
66
/*                                                                        */
67
/*    This function creates a FAT12/16/32 format with raw calls to the    */
68
/*    I/O driver. It can and must be called before the fx_media_open      */
69
/*    and is designed to utilize the same underlying FileX driver.        */
70
/*                                                                        */
71
/*  INPUT                                                                 */
72
/*                                                                        */
73
/*    media_ptr                             Pointer to media control block*/
74
/*                                            (does not need to be opened)*/
75
/*    driver                                Pointer to FileX driver (must */
76
/*                                            be able to field requests   */
77
/*                                            prior to opening)           */
78
/*    driver_info_ptr                       Optional information pointer  */
79
/*    memory_ptr                            Pointer to memory used by the */
80
/*                                            FileX for this media.       */
81
/*    memory_size                           Size of media memory - must   */
82
/*                                            at least 512 bytes and      */
83
/*                                            one sector size.            */
84
/*    volume_name                           Name of the volume            */
85
/*    number_of_fats                        Number of FAT tables          */
86
/*    directory_entries                     Number of directory entries   */
87
/*    hidden_sectors                        Number of hidden sectors      */
88
/*    total_sectors                         Total number of sectors       */
89
/*    bytes_per_sector                      Number of bytes per sector    */
90
/*    sectors_per_cluster                   Number of sectors per cluster */
91
/*    heads                                 Number of heads               */
92
/*    sectors_per_track                     Number of sectors per track   */
93
/*                                                                        */
94
/*  OUTPUT                                                                */
95
/*                                                                        */
96
/*    Completion Status                                                   */
97
/*                                                                        */
98
/*  CALLS                                                                 */
99
/*                                                                        */
100
/*    Media driver                                                        */
101
/*    _fx_utility_16_unsigned_write         Write 16-bit unsigned         */
102
/*    _fx_utility_32_unsigned_write         Write 32-bit unsigned         */
103
/*                                                                        */
104
/*  CALLED BY                                                             */
105
/*                                                                        */
106
/*    Application Code                                                    */
107
/*                                                                        */
108
/*  RELEASE HISTORY                                                       */
109
/*                                                                        */
110
/*    DATE              NAME                      DESCRIPTION             */
111
/*                                                                        */
112
/*  05-19-2020     William E. Lamie         Initial Version 6.0           */
113
/*  09-30-2020     William E. Lamie         Modified comment(s), and      */
114
/*                                            added conditional to        */
115
/*                                            disable force memset,       */
116
/*                                            resulting in version 6.1    */
117
/*  03-02-2021     William E. Lamie         Modified comment(s),          */
118
/*                                            resulting in version 6.1.5  */
119
/*  08-02-2021     Bhupendra Naphade        Modified comment(s), and      */
120
/*                                            updated boot write logic,   */
121
/*                                            resulting in version 6.1.8  */
122
/*  04-25-2022     Bhupendra Naphade        Modified comment(s), and      */
123
/*                                            updated reserved FAT entry  */
124
/*                                            value,                      */
125
/*                                            resulting in version 6.1.11 */
126
/*                                                                        */
127
/**************************************************************************/
128
6213
UINT  _fx_media_format(FX_MEDIA *media_ptr, VOID (*driver)(FX_MEDIA *media), VOID *driver_info_ptr, UCHAR *memory_ptr, UINT memory_size,
129
                       CHAR *volume_name, UINT number_of_fats, UINT directory_entries, UINT hidden_sectors,
130
                       ULONG total_sectors, UINT bytes_per_sector, UINT sectors_per_cluster,
131
                       UINT heads, UINT sectors_per_track)
132
{
133
134
UCHAR *byte_ptr;
135
UINT   reserved_sectors, i, j, root_sectors, total_clusters, bytes_needed;
136
UINT   sectors_per_fat, f, s;
137
138
139
    /* Create & write bootrecord from drive geometry information.  */
140
141
    /* If trace is enabled, insert this event into the trace buffer.  */
142
    FX_TRACE_IN_LINE_INSERT(FX_TRACE_MEDIA_FORMAT, media_ptr, directory_entries, total_sectors, sectors_per_cluster, FX_TRACE_MEDIA_EVENTS, 0, 0)
143
144
    /* Validate bytes per sector value: greater than zero and no more than 4096.  */
145

6213
    if((bytes_per_sector == 0) || (bytes_per_sector > 4096))
146
2
        return(FX_SECTOR_INVALID);
147
148
    /* Validate sectors per cluster value: greater than zero and no more than 128.  */
149

6211
    if((sectors_per_cluster == 0) || (sectors_per_cluster > 128))
150
2
        return(FX_SECTOR_INVALID);
151
152
    /* Setup driver pointer and memory information.  */
153
6209
    media_ptr -> fx_media_driver_entry =                driver;
154
6209
    media_ptr -> fx_media_memory_buffer =               (UCHAR *)memory_ptr;
155
6209
    media_ptr -> fx_media_memory_size =                 memory_size;
156
157
    /* Store geometry information in media record - driver needs this.  */
158
6209
    media_ptr -> fx_media_bytes_per_sector =            bytes_per_sector;
159
6209
    media_ptr -> fx_media_sectors_per_track =           sectors_per_track;
160
6209
    media_ptr -> fx_media_heads =                       heads;
161
6209
    media_ptr -> fx_media_hidden_sectors =              hidden_sectors;
162
163
    /* Initialize the supplied media I/O driver.  First, build the
164
       initialize driver request.  */
165
6209
    media_ptr -> fx_media_driver_request =              FX_DRIVER_INIT;
166
6209
    media_ptr -> fx_media_driver_status =               FX_IO_ERROR;
167
6209
    media_ptr -> fx_media_driver_info =                 driver_info_ptr;
168
6209
    media_ptr -> fx_media_driver_write_protect =        FX_FALSE;
169
6209
    media_ptr -> fx_media_driver_free_sector_update =   FX_FALSE;
170
6209
    media_ptr -> fx_media_driver_data_sector_read =     FX_FALSE;
171
172
    /* If trace is enabled, insert this event into the trace buffer.  */
173
    FX_TRACE_IN_LINE_INSERT(FX_TRACE_INTERNAL_IO_DRIVER_INIT, media_ptr, 0, 0, 0, FX_TRACE_INTERNAL_EVENTS, 0, 0)
174
175
    /* Call the specified I/O driver with the initialize request.  */
176
6209
    (media_ptr -> fx_media_driver_entry) (media_ptr);
177
178
    /* Determine if the I/O driver initialized successfully.  */
179
6209
    if (media_ptr -> fx_media_driver_status != FX_SUCCESS)
180
    {
181
182
        /* Return the driver error status.  */
183
774
        return(FX_IO_ERROR);
184
    }
185
186
    /* Setup driver buffer memory.  */
187
5435
    media_ptr -> fx_media_driver_buffer =  memory_ptr;
188
189
    /* Move the buffer pointer into a local copy.  */
190
5435
    byte_ptr =  media_ptr -> fx_media_driver_buffer;
191
192
#ifndef FX_DISABLE_FORCE_MEMORY_OPERATION
193
    /* Clear the buffer record out, assuming it is large enough for one sector.   */
194
1949947
    for (i = 0; i < bytes_per_sector; i++)
195
    {
196
197
        /* Clear each byte of the boot record.  */
198
1944512
        byte_ptr[i] =  (UCHAR)0;
199
    }
200
#else
201
    _fx_utility_memory_set(byte_ptr, 0, bytes_per_sector);
202
#endif /* FX_DISABLE_FORCE_MEMORY_OPERATION */
203
204
    /* Set jump instruction at the beginning of the sector.  */
205
5435
    byte_ptr[0] =  (UCHAR)0xEB;
206
5435
    byte_ptr[1] =  (UCHAR)0x34;
207
5435
    byte_ptr[2] =  (UCHAR)0x90;
208
209
    /* Set the OEM name in the boot record.  */
210
48915
    for (i = 0; i < 8; i++)
211
    {
212
213
        /* Copy a character from the OEM name.  */
214
43480
        byte_ptr[i + 3] =  _fx_media_format_oem_name[i];
215
    }
216
217
    /* Set the media type in the boot record.  */
218
5435
    byte_ptr[FX_MEDIA_TYPE] =  _fx_media_format_media_type;
219
220
    /* Set the number of bytes per sector.  */
221
5435
    _fx_utility_16_unsigned_write(&byte_ptr[FX_BYTES_SECTOR], bytes_per_sector);
222
223
    /* Set the number of sectors per track.  */
224
5435
    _fx_utility_16_unsigned_write(&byte_ptr[FX_SECTORS_PER_TRK], sectors_per_track);
225
226
    /* Set the number of heads.  */
227
5435
    _fx_utility_16_unsigned_write(&byte_ptr[FX_HEADS], heads);
228
229
#ifdef FX_FORCE_512_BYTE_BOOT_SECTOR
230
231
    /* Calculate the number of reserved sectors. If sector size is smaller than 512 bytes, there will be
232
       reserved sectors, otherwise assumed that only the sector containing bootrecord is reserved.  */
233
    if (bytes_per_sector < 512)
234
    {
235
        reserved_sectors =  512 / bytes_per_sector;
236
    }
237
    else
238
    {
239
        reserved_sectors =  1;
240
    }
241
#else
242
243
    /* The boot sector is the only reserved sector.  */
244
5435
    reserved_sectors =  1;
245
#endif
246
247
248
    /* Calculate the maximum clusters.... This is actually greater than the actual since the FAT
249
       sectors have yet to be accounted for.  */
250
5435
    total_clusters =  (total_sectors - reserved_sectors - ((directory_entries * FX_DIR_ENTRY_SIZE) + (bytes_per_sector - 1)) / bytes_per_sector) / sectors_per_cluster;
251
252
    /* Calculate the maximum number of FAT sectors necessary for FAT12.  */
253
5435
    if (total_clusters % 2)
254
    {
255
5417
        bytes_needed = (total_clusters + total_clusters / 2) + 1;
256
    }
257
    else
258
    {
259
18
        bytes_needed = (total_clusters + total_clusters / 2);
260
    }
261
5435
    sectors_per_fat =  bytes_needed / bytes_per_sector;
262
5435
    if (bytes_needed % bytes_per_sector)
263
    {
264
5426
        sectors_per_fat++;
265
    }
266
267
    /* Now adjust the total clusters by the number of sectors per FAT.  */
268
5435
    total_clusters =  total_clusters - ((sectors_per_fat * number_of_fats) + (sectors_per_cluster - 1)) / sectors_per_cluster;
269
270
    /* Is the total cluster count greater than the FAT12 maximum?  */
271
5435
    if (total_clusters >= FX_12_BIT_FAT_SIZE)
272
    {
273
274
        /* Yes, too big for FAT12, we need to evaluate for FAT16.  */
275
276
        /* Reset the maximum clusters.... This is actually greater than the actual since the FAT
277
           sectors have yet to be accounted for.  */
278
5343
        total_clusters =  (total_sectors - reserved_sectors -  ((directory_entries * FX_DIR_ENTRY_SIZE) + (bytes_per_sector - 1)) / bytes_per_sector) / sectors_per_cluster;
279
280
        /* Calculate 16-bit FAT is present. Each cluster requires a 2 byte entry in the FAT table.  */
281
5343
        sectors_per_fat =  (total_clusters * 2) / bytes_per_sector;
282
5343
        if ((total_clusters * 2) % bytes_per_sector)
283
        {
284
5338
            sectors_per_fat++;
285
        }
286
287
        /* Now adjust the total clusters by the number of sectors per FAT.  */
288
5343
        total_clusters =  total_clusters - ((sectors_per_fat * number_of_fats) + (sectors_per_cluster - 1)) / sectors_per_cluster;
289
290
        /* Is the total cluster count greater than the FAT16 maximum?  */
291
5343
        if (total_clusters >= FX_16_BIT_FAT_SIZE)
292
        {
293
294
            /* Yes, FAT32 is present.  */
295
296
            /* Allocate room for the FAT32 additional information sector. This contains useful information
297
               such as the number of available clusters between successive mounting of the media.  */
298
4279
            if (bytes_per_sector == 512)
299
            {
300
301
                /* Write sector number 1 to the additional information sector.  */
302
3237
                _fx_utility_16_unsigned_write(&byte_ptr[48], 1);
303
304
                /* Increment the reserved sectors count, since this will count as a reserved sector.  */
305
3237
                reserved_sectors++;
306
            }
307
            else
308
            {
309
310
                /* Write value to indicate there is no additional information sector.  */
311
1042
                _fx_utility_16_unsigned_write(&byte_ptr[48], 0xFFFF);
312
            }
313
314
            /* Allocate the first cluster to the root directory.  */
315
4279
            _fx_utility_32_unsigned_write(&byte_ptr[FX_ROOT_CLUSTER_32], FX_FAT_ENTRY_START);
316
317
            /* Determine if the number of root directory entries should be modified.  */
318
4279
            directory_entries =  (sectors_per_cluster * bytes_per_sector) / FX_DIR_ENTRY_SIZE;
319
320
            /* Reset the total_clusters for the FAT32 calculation.  */
321
4279
            total_clusters =  (total_sectors - reserved_sectors) / sectors_per_cluster;
322
323
            /* 32-bit FAT is present. Each cluster requires a 4 byte entry in the FAT table.  */
324
4279
            sectors_per_fat =  (total_clusters * 4) / bytes_per_sector;
325
4279
            if ((total_clusters * 4) % bytes_per_sector)
326
            {
327
4278
                sectors_per_fat++;
328
            }
329
330
            /* Now adjust the total clusters by the number of sectors per FAT.  */
331
4279
            total_clusters =  total_clusters - ((sectors_per_fat * number_of_fats) + (sectors_per_cluster - 1)) / sectors_per_cluster;
332
        }
333
    }
334
335
    /* Set sectors per FAT type.  */
336
5435
    if (total_clusters < FX_16_BIT_FAT_SIZE)
337
    {
338
339
        /* Set the number of sectors per FAT12/16.  */
340
1156
        _fx_utility_16_unsigned_write(&byte_ptr[FX_SECTORS_PER_FAT], sectors_per_fat);
341
342
        /* Set the signature.  */
343
1156
        byte_ptr[FX_BOOT_SIG] =  0x29;
344
345
        /* Setup the volume ID.  */
346
1156
        _fx_utility_32_unsigned_write(&byte_ptr[FX_VOLUME_ID], _fx_media_format_volume_id);
347
    }
348
    else
349
    {
350
351
        /* Set the number of sectors per FAT32.  */
352
4279
        _fx_utility_32_unsigned_write(&byte_ptr[FX_SECTORS_PER_FAT_32], sectors_per_fat);
353
354
        /* Set the signature.  */
355
4279
        byte_ptr[FX_BOOT_SIG_32] =  0x29;
356
357
        /* Setup the volume ID.  */
358
4279
        _fx_utility_32_unsigned_write(&byte_ptr[FX_VOLUME_ID_32], _fx_media_format_volume_id);
359
    }
360
361
    /* Set the total number of sectors.  */
362
5435
    if (total_sectors < (ULONG)0xFFFF)
363
    {
364
365
        /* Write the 16-bit total sector field.  */
366
1155
        _fx_utility_16_unsigned_write(&byte_ptr[FX_SECTORS], (UINT)(total_sectors));
367
368
        /* Set the number of huge sectors.  */
369
1155
        _fx_utility_32_unsigned_write(&byte_ptr[FX_HUGE_SECTORS], 0);
370
    }
371
    else
372
    {
373
374
        /* Write the 16-bit total sector field as 0.  */
375
4280
        _fx_utility_16_unsigned_write(&byte_ptr[FX_SECTORS], (UINT)0);
376
377
        /* Set the number of huge sectors.  */
378
4280
        _fx_utility_32_unsigned_write(&byte_ptr[FX_HUGE_SECTORS], total_sectors);
379
    }
380
381
    /* Set the number of reserved sectors.  */
382
5435
    _fx_utility_16_unsigned_write(&byte_ptr[FX_RESERVED_SECTORS], reserved_sectors);
383
384
    /* Set the number of sectors per cluster */
385
5435
    byte_ptr[FX_SECTORS_CLUSTER] =  (UCHAR)sectors_per_cluster;
386
387
    /* Set the number of FATs.  */
388
5435
    byte_ptr[FX_NUMBER_OF_FATS] =  (UCHAR)number_of_fats;
389
390
    /* Set the number of hidden sectors.  */
391
5435
    _fx_utility_32_unsigned_write(&byte_ptr[FX_HIDDEN_SECTORS], hidden_sectors);
392
393
    /* Determine if a FAT12 or FAT16 is present.  If FAT32 is present, these fields are left alone!   */
394
5435
    if (total_clusters < FX_16_BIT_FAT_SIZE)
395
    {
396
397
        /* Yes, set the number of root directory entries.  */
398
1156
        _fx_utility_16_unsigned_write(&byte_ptr[FX_ROOT_DIR_ENTRIES], directory_entries);
399
    }
400
401
    /* Now setup the volume label. */
402
5435
    if (total_clusters < FX_16_BIT_FAT_SIZE)
403
    {
404
405
        /* FAT12/16 volume label offset.  */
406
1156
        j =  FX_VOLUME_LABEL;
407
    }
408
    else
409
    {
410
411
        /* FAT32 volume label offset.  */
412
4279
        j =  FX_VOLUME_LABEL_32;
413
    }
414
415
5435
    i = 0;
416
49082
    while (i < 11)
417
    {
418
419
        /* Determine if it is NULL.  */
420
46875
        if (volume_name[i] == 0)
421
        {
422
423
            /* Yes, the copying is finished.  */
424
3228
            break;
425
        }
426
427
        /* Otherwise, copy byte of volume name into boot record.  */
428
43647
        byte_ptr[j + i] =  (UCHAR)volume_name[i];
429
430
        /* Increment byte position.  */
431
43647
        i++;
432
    }
433
434
    /* Now blank-pad the remainder of the volume name.  */
435
#ifndef FX_DISABLE_FORCE_MEMORY_OPERATION
436
21573
    while (i < 11)
437
    {
438
439
16138
        byte_ptr[j + i] =  (UCHAR)' ';
440
16138
        i++;
441
    }
442
#else
443
    _fx_utility_memory_set(&byte_ptr[j + i], ' ', (11 - i));
444
#endif /* FX_DISABLE_FORCE_MEMORY_OPERATION */
445
446
447
#ifdef FX_FORCE_512_BYTE_BOOT_SECTOR
448
449
    /* Set bootrecord signature.  */
450
    byte_ptr[510] = 0x55;
451
    byte_ptr[511] = 0xAA;
452
#else
453
454
    /* Set bootrecord signature.  */
455
5435
    byte_ptr[bytes_per_sector - 2] = 0x55;
456
5435
    byte_ptr[bytes_per_sector - 1] = 0xAA;
457
#endif
458
459
    /* Select the boot record write command.  */
460
5435
    media_ptr -> fx_media_driver_request =       FX_DRIVER_BOOT_WRITE;
461
5435
    media_ptr -> fx_media_driver_system_write =  FX_TRUE;
462
5435
    media_ptr -> fx_media_driver_sectors =       1;
463
5435
    media_ptr -> fx_media_driver_sector_type =   FX_BOOT_SECTOR;
464
465
    /* If trace is enabled, insert this event into the trace buffer.  */
466
    FX_TRACE_IN_LINE_INSERT(FX_TRACE_INTERNAL_IO_DRIVER_BOOT_WRITE, media_ptr, memory_ptr, 0, 0, FX_TRACE_INTERNAL_EVENTS, 0, 0)
467
468
    /* Write out the bootrecord */
469
5435
    (driver)(media_ptr);
470
471
    /* Clear the write flag.  */
472
5435
    media_ptr -> fx_media_driver_system_write =  FX_FALSE;
473
474
    /* Determine if it was successful.  */
475
5435
    if (media_ptr -> fx_media_driver_status != FX_SUCCESS)
476
    {
477
403
        return(FX_IO_ERROR);
478
    }
479
480
    /* Calculate the number of root sectors.  */
481
5032
    root_sectors =    ((directory_entries * FX_DIR_ENTRY_SIZE) + bytes_per_sector - 1) / bytes_per_sector;
482
483
    /* Determine if FAT32 is present AND if the bytes per sector is large enough to have
484
       a FSINFO sector.  */
485

5032
    if ((total_clusters >= FX_16_BIT_FAT_SIZE) && (bytes_per_sector == 512))
486
    {
487
488
#ifndef FX_DISABLE_FORCE_MEMORY_OPERATION
489
        /* Clear sector buffer.  */
490
1453842
        for (i = 0; i < bytes_per_sector; i++)
491
        {
492
1451008
            byte_ptr[i] =  (CHAR)0;
493
        }
494
#else
495
        _fx_utility_memory_set(byte_ptr, 0, bytes_per_sector);
496
#endif /* FX_DISABLE_FORCE_MEMORY_OPERATION */
497
498
        /* Build the FSINFO fields.  */
499
500
        /* Build first signature word, used to help verify this is a FSINFO sector.  */
501
2834
        byte_ptr[0] =  0x52;
502
2834
        byte_ptr[1] =  0x52;
503
2834
        byte_ptr[2] =  0x61;
504
2834
        byte_ptr[3] =  0x41;
505
506
        /* Build the next signature word, this too is used to help verify that this is a FSINFO sector.  */
507
2834
        byte_ptr[484] =  0x72;
508
2834
        byte_ptr[485] =  0x72;
509
2834
        byte_ptr[486] =  0x41;
510
2834
        byte_ptr[487] =  0x61;
511
512
        /* Build the final signature word, this too is used to help verify that this is a FSINFO sector.  */
513
2834
        byte_ptr[508] =  0x55;
514
2834
        byte_ptr[509] =  0xAA;
515
516
        /* Setup the total available clusters on the media. We need to subtract 1 for the FAT32 root directory.  */
517
2834
        _fx_utility_32_unsigned_write(&byte_ptr[488], (total_clusters - 1));
518
519
        /* Setup the starting free cluster to 3, since cluster 2 is reserved for the FAT32 root directory.  */
520
2834
        _fx_utility_32_unsigned_write(&byte_ptr[492], 3);
521
522
        /* Now write the FSINFO sector to the media.  */
523
2834
        media_ptr -> fx_media_driver_logical_sector =  1;
524
2834
        media_ptr -> fx_media_driver_request =         FX_DRIVER_WRITE;
525
2834
        media_ptr -> fx_media_driver_sectors =         1;
526
2834
        media_ptr -> fx_media_driver_system_write =    FX_TRUE;
527
2834
        media_ptr -> fx_media_driver_sector_type =     FX_BOOT_SECTOR;
528
529
        /* If trace is enabled, insert this event into the trace buffer.  */
530
        FX_TRACE_IN_LINE_INSERT(FX_TRACE_INTERNAL_IO_DRIVER_WRITE, media_ptr, 1, 1, memory_ptr, FX_TRACE_INTERNAL_EVENTS, 0, 0)
531
532
        /* Write out the sector.  */
533
2834
        (driver)(media_ptr);
534
535
        /* Clear the system write flag.  */
536
2834
        media_ptr -> fx_media_driver_system_write =  FX_FALSE;
537
538
        /* Determine if it was successful.  */
539
2834
        if (media_ptr -> fx_media_driver_status != FX_SUCCESS)
540
        {
541
346
            return(FX_IO_ERROR);
542
        }
543
    }
544
545
    /* At this point we need set up first to FAT entries and clear the remaining FAT sectors area.  */
546
547
    /* Loop through number of FATs. The first is the only one used.  */
548
6901
    for (f = 0; f < number_of_fats; f++)
549
    {
550
551
        /* Loop through all the sectors in this FAT.  */
552
2406476
        for (s = 0; s < sectors_per_fat; s++)
553
        {
554
555
2404261
            if (s == 0)
556
            {
557
558
                /* Reserve the first two FAT table entries.  */
559
4692
                if (total_clusters < FX_12_BIT_FAT_SIZE)
560
                {
561
562
                    /* Reserve the first two FAT-12 entries.  */
563
94
                    byte_ptr[0] =  _fx_media_format_media_type;
564
94
                    byte_ptr[1] =  (UCHAR)0xFF;
565
94
                    byte_ptr[2] =  (UCHAR)0xFF;
566
567
                    /* Start clearing at FAT entry 3.  */
568
94
                    i =  3;
569
                }
570
4598
                else if (total_clusters < FX_16_BIT_FAT_SIZE)
571
                {
572
573
                    /* Reserve the first two FAT-16 entries.  */
574
1067
                    byte_ptr[0] =  _fx_media_format_media_type;
575
1067
                    byte_ptr[1] =  (UCHAR)0xFF;
576
1067
                    byte_ptr[2] =  (UCHAR)0xFF;
577
1067
                    byte_ptr[3] =  (UCHAR)0xFF;
578
579
                    /* Start clearing at FAT entry 3.  */
580
1067
                    i =  4;
581
                }
582
                else
583
                {
584
585
                    /* Reserve the first two FAT-32 entries.   */
586
3531
                    byte_ptr[0] =  _fx_media_format_media_type;
587
3531
                    byte_ptr[1] =  (UCHAR)0xFF;
588
3531
                    byte_ptr[2] =  (UCHAR)0xFF;
589
3531
                    byte_ptr[3] =  (UCHAR)0x0F;
590
3531
                    byte_ptr[4] =  (UCHAR)0xFF;
591
3531
                    byte_ptr[5] =  (UCHAR)0xFF;
592
3531
                    byte_ptr[6] =  (UCHAR)0xFF;
593
3531
                    byte_ptr[7] =  (UCHAR)0x0F;
594
595
                    /* Preallocate the first cluster for the root directory.  */
596
3531
                    byte_ptr[8] =   (UCHAR)0xFF;
597
3531
                    byte_ptr[9] =   (UCHAR)0xFF;
598
3531
                    byte_ptr[10] =  (UCHAR)0xFF;
599
3531
                    byte_ptr[11] =  (UCHAR)0x0F;
600
601
                    /* Start clearing at FAT entry 3.  */
602
3531
                    i =  12;
603
                }
604
            }
605
            else
606
            {
607
2399569
                i = 0;
608
            }
609
610
#ifndef FX_DISABLE_FORCE_MEMORY_OPERATION
611
            /* Clear remainder of sector buffer.  */
612
318601499
            for (; i < bytes_per_sector; i++)
613
            {
614
316197238
                byte_ptr[i] =  (CHAR)0;
615
            }
616
#else
617
            _fx_utility_memory_set(&byte_ptr[i], 0, (bytes_per_sector - i));
618
#endif  /* FX_DISABLE_FORCE_MEMORY_OPERATION */
619
620
            /* Build sector write command.  */
621
2404261
            media_ptr -> fx_media_driver_logical_sector =  reserved_sectors + (f * sectors_per_fat) + s;
622
2404261
            media_ptr -> fx_media_driver_request =         FX_DRIVER_WRITE;
623
2404261
            media_ptr -> fx_media_driver_sectors =         1;
624
2404261
            media_ptr -> fx_media_driver_system_write =    FX_TRUE;
625
2404261
            media_ptr -> fx_media_driver_sector_type =     FX_FAT_SECTOR;
626
627
            /* If trace is enabled, insert this event into the trace buffer.  */
628
            FX_TRACE_IN_LINE_INSERT(FX_TRACE_INTERNAL_IO_DRIVER_WRITE, media_ptr, media_ptr -> fx_media_driver_logical_sector, 1, memory_ptr, FX_TRACE_INTERNAL_EVENTS, 0, 0)
629
630
            /* Write out the sector.  */
631
2404261
            (driver)(media_ptr);
632
633
            /* Clear the system write flag.  */
634
2404261
            media_ptr -> fx_media_driver_system_write =  FX_FALSE;
635
636
            /* Determine if it was successful.  */
637
2404261
            if (media_ptr -> fx_media_driver_status != FX_SUCCESS)
638
            {
639
2477
                return(FX_IO_ERROR);
640
            }
641
        }
642
    }
643
644
#ifndef FX_DISABLE_FORCE_MEMORY_OPERATION
645
    /* Clear sector buffer.  */
646
295009
    for (i = 0; i < bytes_per_sector; i++)
647
    {
648
292800
        byte_ptr[i] =  (CHAR)0;
649
    }
650
#else
651
    _fx_utility_memory_set(byte_ptr, 0, bytes_per_sector);
652
#endif /* FX_DISABLE_FORCE_MEMORY_OPERATION */
653
654
    /* Now clear the root directory sectors.  */
655
15980
    for (s = 0; s < root_sectors; s++)
656
    {
657
658
        /* Build sector write command.  */
659
13772
        media_ptr -> fx_media_driver_logical_sector =  reserved_sectors + (number_of_fats * sectors_per_fat) + s;
660
13772
        media_ptr -> fx_media_driver_request =         FX_DRIVER_WRITE;
661
13772
        media_ptr -> fx_media_driver_sectors =         1;
662
13772
        media_ptr -> fx_media_driver_system_write =    FX_TRUE;
663
13772
        media_ptr -> fx_media_driver_sector_type =     FX_DIRECTORY_SECTOR;
664
665
        /* If trace is enabled, insert this event into the trace buffer.  */
666
        FX_TRACE_IN_LINE_INSERT(FX_TRACE_INTERNAL_IO_DRIVER_WRITE, media_ptr, media_ptr -> fx_media_driver_logical_sector, 1, memory_ptr, FX_TRACE_INTERNAL_EVENTS, 0, 0)
667
668
        /* Write out the sector.  */
669
13772
        (driver)(media_ptr);
670
671
        /* Clear the write flag.  */
672
13772
        media_ptr -> fx_media_driver_system_write =  FX_FALSE;
673
674
        /* Determine if it was successful.  */
675
13772
        if (media_ptr -> fx_media_driver_status != FX_SUCCESS)
676
        {
677
1
            return(FX_IO_ERROR);
678
        }
679
    }
680
681
    /* Build the "uninitialize" I/O driver request.  */
682
2208
    media_ptr -> fx_media_driver_request =      FX_DRIVER_UNINIT;
683
2208
    media_ptr -> fx_media_driver_status =       FX_IO_ERROR;
684
685
    /* If trace is enabled, insert this event into the trace buffer.  */
686
    FX_TRACE_IN_LINE_INSERT(FX_TRACE_INTERNAL_IO_DRIVER_UNINIT, media_ptr, 0, 0, 0, FX_TRACE_INTERNAL_EVENTS, 0, 0)
687
688
    /* Call the specified I/O driver with the uninitialize request.  */
689
2208
    (media_ptr -> fx_media_driver_entry) (media_ptr);
690
691
    /* Return success!  */
692
2208
    return(media_ptr -> fx_media_driver_status);
693
}
694