GCC Code Coverage Report
Directory: ./ Exec Total Coverage
File: fx_media_volume_set.c Lines: 103 103 100.0 %
Date: 2024-01-10 21:53:23 Branches: 54 54 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_directory.h"
31
#include "fx_media.h"
32
#include "fx_utility.h"
33
#ifdef FX_ENABLE_EXFAT
34
#include "fx_directory_exFAT.h"
35
#endif /* FX_ENABLE_EXFAT */
36
37
38
/**************************************************************************/
39
/*                                                                        */
40
/*  FUNCTION                                               RELEASE        */
41
/*                                                                        */
42
/*    _fx_media_volume_set                                PORTABLE C      */
43
/*                                                           6.1.7        */
44
/*  AUTHOR                                                                */
45
/*                                                                        */
46
/*    William E. Lamie, Microsoft Corporation                             */
47
/*                                                                        */
48
/*  DESCRIPTION                                                           */
49
/*                                                                        */
50
/*    This function sets the volume name to the name supplied by the      */
51
/*    caller.                                                             */
52
/*                                                                        */
53
/*  INPUT                                                                 */
54
/*                                                                        */
55
/*    media_ptr                             Media control block pointer   */
56
/*    volume_name                           New volume name               */
57
/*                                                                        */
58
/*  OUTPUT                                                                */
59
/*                                                                        */
60
/*    return status                                                       */
61
/*                                                                        */
62
/*  CALLS                                                                 */
63
/*                                                                        */
64
/*    _fx_directory_entry_read              Read a directory entry        */
65
/*    _fx_utility_logical_sector_read       Read directory sector         */
66
/*    _fx_utility_logical_sector_write      Write directory sector        */
67
/*                                                                        */
68
/*  CALLED BY                                                             */
69
/*                                                                        */
70
/*    Application Code                                                    */
71
/*                                                                        */
72
/*  RELEASE HISTORY                                                       */
73
/*                                                                        */
74
/*    DATE              NAME                      DESCRIPTION             */
75
/*                                                                        */
76
/*  05-19-2020     William E. Lamie         Initial Version 6.0           */
77
/*  09-30-2020     William E. Lamie         Modified comment(s),          */
78
/*                                            resulting in version 6.1    */
79
/*  06-02-2021     Bhupendra Naphade        Modified comment(s),updated   */
80
/*                                            the initialization of       */
81
/*                                            dir_entry for exFAT format, */
82
/*                                            resulting in version 6.1.7  */
83
/*                                                                        */
84
/**************************************************************************/
85
1028
UINT  _fx_media_volume_set(FX_MEDIA *media_ptr, CHAR *volume_name)
86
{
87
88
ULONG        i, j;
89
FX_DIR_ENTRY dir_entry, dir_entry1;
90
UINT         status, offset;
91
UCHAR       *work_ptr;
92
CHAR         alpha;
93
94
95
    /* Check the media to make sure it is open.  */
96
1028
    if (media_ptr -> fx_media_id != FX_MEDIA_ID)
97
    {
98
99
        /* Return the media not opened error.  */
100
1001
        return(FX_MEDIA_NOT_OPEN);
101
    }
102
103
27
    dir_entry.fx_dir_entry_log_sector = 0;
104
27
    dir_entry.fx_dir_entry_byte_offset = 0;
105
106
    /* If trace is enabled, insert this event into the trace buffer.  */
107
    FX_TRACE_IN_LINE_INSERT(FX_TRACE_MEDIA_VOLUME_SET, media_ptr, volume_name, 0, 0, FX_TRACE_MEDIA_EVENTS, 0, 0)
108
109
    /* Protect against other threads accessing the media.  */
110
27
    FX_PROTECT
111
112
#ifdef FX_ENABLE_EXFAT
113
    if (media_ptr -> fx_media_FAT_type == FX_exFAT)
114
    {
115
116
        /* Setup pointer to media name buffer.  */
117
        dir_entry.fx_dir_entry_name =  media_ptr -> fx_media_name_buffer;
118
119
        /* Clear the short name string.  */
120
        dir_entry.fx_dir_entry_short_name[0] =  0;
121
122
        /* Attempt to find the volume name in the root directory.  */
123
        i =  0;
124
        do
125
        {
126
127
            /* Read an entry from the root directory.  */
128
            status =  _fx_directory_entry_read(media_ptr, FX_NULL, &i, &dir_entry);
129
130
            /* Check for error status.  */
131
            if (status != FX_SUCCESS)
132
            {
133
134
                /* Release media protection.  */
135
                FX_UNPROTECT
136
137
                /* Return to caller.  */
138
                return(status);
139
            }
140
141
            /* Check for a volume name.  */
142
            if (dir_entry.fx_dir_entry_type == FX_EXFAT_DIR_ENTRY_TYPE_VOLUME_LABEL)
143
            {
144
145
                /* Yes, we have found a previously set volume name.  */
146
                break;
147
            }
148
149
            /* Move to next directory entry.  */
150
            i++;
151
        } while (i < media_ptr -> fx_media_root_directory_entries);
152
153
        /* Determine if a volume entry has been found.  */
154
        if (i == media_ptr -> fx_media_root_directory_entries)
155
        {
156
157
            /* Volume entry not found, attempt to find a free entry in the root directory.  */
158
            i =  0;
159
            do
160
            {
161
162
                /* Read an entry from the root directory.  */
163
                status =  _fx_directory_entry_read(media_ptr, FX_NULL, &i, &dir_entry);
164
165
                /* Check for error status.  */
166
                if (status != FX_SUCCESS)
167
                {
168
169
                    /* Release media protection.  */
170
                    FX_UNPROTECT
171
172
                    /* Return to caller.  */
173
                    return(status);
174
                }
175
176
                /* Check for a volume name.  */
177
                if (dir_entry.fx_dir_entry_type == FX_EXFAT_DIR_ENTRY_TYPE_FREE)
178
                {
179
180
                    /* Yes, we have found a free directory entry.  */
181
                    break;
182
                }
183
184
                /* Move to next directory entry.  */
185
                i++;
186
            } while (i < media_ptr -> fx_media_root_directory_entries);
187
188
            /* Determine if a free entry has been found.  */
189
            if (i == media_ptr -> fx_media_root_directory_entries)
190
            {
191
192
                /* Release media protection.  */
193
                FX_UNPROTECT
194
195
                /* No existing volume name was found, return an error.  */
196
                return(FX_NOT_FOUND);
197
            }
198
        }
199
200
        /* Read the logical directory sector.  */
201
        status =  _fx_utility_logical_sector_read(media_ptr, (ULONG64) dir_entry.fx_dir_entry_log_sector,
202
                                                  media_ptr -> fx_media_memory_buffer, ((ULONG) 1), FX_DIRECTORY_SECTOR);
203
204
        /* Determine if an error occurred.  */
205
        if (status != FX_SUCCESS)
206
        {
207
208
            /* Release media protection.  */
209
            FX_UNPROTECT
210
211
            /* Return error code.  */
212
            return(status);
213
        }
214
215
        /* Offset to volume label field.  */
216
        offset = dir_entry.fx_dir_entry_byte_offset + FX_EXFAT_VOLUME_LABEL;
217
218
        /* Loop to store the volume name.  */
219
        for (i = 0; volume_name[i]; i++)
220
        {
221
222
            /* Have we reached the end?  */
223
            if (i == 11)
224
            {
225
226
                break;
227
            }
228
229
            /* Pickup volume name byte.  */
230
            alpha =  volume_name[i];
231
232
            /* Store a byte of the volume name.  */
233
            _fx_utility_16_unsigned_write(&media_ptr -> fx_media_memory_buffer[offset], (UINT)alpha);
234
235
            /* Move to next character.  */
236
            offset += 2;
237
        }
238
239
        /* Offset to character count field.  */
240
        offset = dir_entry.fx_dir_entry_byte_offset;
241
242
        /* Store volume label entry type.  */
243
        media_ptr -> fx_media_memory_buffer[offset] = FX_EXFAT_DIR_ENTRY_TYPE_VOLUME_LABEL;
244
245
        /* Store the character count.  */
246
        media_ptr -> fx_media_memory_buffer[offset + FX_EXFAT_CHAR_COUNT] = (UCHAR)i;
247
248
        /* Write the directory sector to the media.  */
249
        status =  _fx_utility_logical_sector_write(media_ptr, (ULONG64) dir_entry.fx_dir_entry_log_sector,
250
                                                   media_ptr -> fx_media_memory_buffer, ((ULONG) 1), FX_DIRECTORY_SECTOR);
251
    }
252
    else
253
    {
254
#endif /* FX_ENABLE_EXFAT */
255
256
        /* First, check for an invalid volume name.  */
257
27
        if (volume_name[0] == 0)
258
        {
259
260
            /* Yes, volume name is invalid.  Return an error.  */
261
1
            return(FX_INVALID_NAME);
262
        }
263
264
        /* Read the logical directory sector 0 - we just do this to get a memory_buffer pointer */
265
26
        status =  _fx_utility_logical_sector_read(media_ptr, ((ULONG64) 0),
266
26
                                                  media_ptr -> fx_media_memory_buffer, ((ULONG) 1), FX_DATA_SECTOR);
267
268
        /* Check the read status.  */
269
26
        if (status != FX_SUCCESS)
270
        {
271
272
            /* Release media protection.  */
273
1
            FX_UNPROTECT
274
275
            /* Return the error status.  */
276
1
            return(status);
277
        }
278
279
#ifndef FX_MEDIA_STATISTICS_DISABLE
280
281
        /* Increment the number of driver read boot sector requests.  */
282
25
        media_ptr -> fx_media_driver_boot_read_requests++;
283
#endif
284
285
        /* Build a driver request to read the boot record.  */
286
25
        media_ptr -> fx_media_driver_request =      FX_DRIVER_BOOT_READ;
287
25
        media_ptr -> fx_media_driver_status =       FX_IO_ERROR;
288
25
        media_ptr -> fx_media_driver_buffer =       media_ptr -> fx_media_memory_buffer;
289
25
        media_ptr -> fx_media_driver_sectors =      1;
290
25
        media_ptr -> fx_media_driver_sector_type =  FX_BOOT_SECTOR;
291
292
        /* If trace is enabled, insert this event into the trace buffer.  */
293
        FX_TRACE_IN_LINE_INSERT(FX_TRACE_INTERNAL_IO_DRIVER_BOOT_READ, media_ptr, media_ptr -> fx_media_memory_buffer, 0, 0, FX_TRACE_INTERNAL_EVENTS, 0, 0)
294
295
        /* Invoke the driver to read the boot sector.  */
296
25
        (media_ptr -> fx_media_driver_entry) (media_ptr);
297
298
        /* Determine if the request is successful.  */
299
25
        if (media_ptr -> fx_media_driver_status)
300
        {
301
302
            /* Release media protection.  */
303
1
            FX_UNPROTECT
304
305
            /* An error occurred in the driver.  */
306
1
            return(media_ptr -> fx_media_driver_status);
307
        }
308
309
        /* Calculate the offset based on the FAT present.  */
310
24
        if (media_ptr -> fx_media_32_bit_FAT)
311
        {
312
313
            /* FAT32 is present.  */
314
5
            offset =  FX_VOLUME_LABEL_32;
315
        }
316
        else
317
        {
318
319
            /* FAT12/16 is present.  */
320
19
            offset =  FX_VOLUME_LABEL;
321
        }
322
323
        /* Loop to store the volume name.  */
324
169
        for (i = 0; volume_name[i]; i++)
325
        {
326
327
            /* Have we reached the end?  */
328
147
            if (i == 11)
329
            {
330
331
2
                break;
332
            }
333
334
            /* Pickup volume name byte.  */
335
145
            alpha =  volume_name[i];
336
337
            /* Determine if alpha needs to be converted to upper case.  */
338

145
            if ((alpha >= 'a') && (alpha <= 'z'))
339
            {
340
341
                /* Convert alpha to upper case.  */
342
25
                alpha =  (CHAR)((INT)alpha - 0x20);
343
            }
344
345
            /* Store a byte of the volume name.  */
346
145
            media_ptr -> fx_media_memory_buffer[offset + i] =  (UCHAR)alpha;
347
        }
348
349
        /* Now pad with spaces.  */
350
143
        for (; i < 11; i++)
351
        {
352
353
            /* Append space character to volume name.  */
354
119
            media_ptr -> fx_media_memory_buffer[offset + i] =  0x20;
355
        }
356
357
#ifndef FX_MEDIA_STATISTICS_DISABLE
358
359
        /* Increment the number of driver write boot sector requests.  */
360
24
        media_ptr -> fx_media_driver_boot_write_requests++;
361
#endif
362
363
        /* Write the boot sector with the new volume name.  */
364
24
        media_ptr -> fx_media_driver_request =      FX_DRIVER_BOOT_WRITE;
365
24
        media_ptr -> fx_media_driver_status =       FX_IO_ERROR;
366
24
        media_ptr -> fx_media_driver_buffer =       media_ptr -> fx_media_memory_buffer;
367
24
        media_ptr -> fx_media_driver_sectors =      1;
368
24
        media_ptr -> fx_media_driver_sector_type =  FX_BOOT_SECTOR;
369
370
        /* Set the system write flag since we are writing the boot sector.  */
371
24
        media_ptr -> fx_media_driver_system_write =  FX_TRUE;
372
373
        /* If trace is enabled, insert this event into the trace buffer.  */
374
        FX_TRACE_IN_LINE_INSERT(FX_TRACE_INTERNAL_IO_DRIVER_BOOT_WRITE, media_ptr, media_ptr -> fx_media_memory_buffer, 0, 0, FX_TRACE_INTERNAL_EVENTS, 0, 0)
375
376
        /* Invoke the driver to write the boot sector.  */
377
24
        (media_ptr -> fx_media_driver_entry) (media_ptr);
378
379
        /* Clear the system write flag.  */
380
24
        media_ptr -> fx_media_driver_system_write =  FX_FALSE;
381
382
        /* Determine if the request is successful.  */
383
24
        if (media_ptr -> fx_media_driver_status)
384
        {
385
386
            /* Release media protection.  */
387
1
            FX_UNPROTECT
388
389
            /* An error occurred in the driver.  */
390
1
            return(media_ptr -> fx_media_driver_status);
391
        }
392
393
        /* Setup pointer to media name buffer.  */
394
23
        dir_entry1.fx_dir_entry_name =  media_ptr -> fx_media_name_buffer;
395
396
        /* Clear the short name string.  */
397
23
        dir_entry1.fx_dir_entry_short_name[0] =  0;
398
399
        /* Now we need to find the copy of the volume name in the root directory.  */
400
23
        i =  0;
401
23
        j =  media_ptr -> fx_media_root_directory_entries + 1;
402
        do
403
        {
404
405
            /* Read an entry from the root directory.  */
406
156
            status =  _fx_directory_entry_read(media_ptr, FX_NULL, &i, &dir_entry1);
407
408
            /* Check for error status.  */
409
156
            if (status != FX_SUCCESS)
410
            {
411
412
                /* Release media protection.  */
413
1
                FX_UNPROTECT
414
415
                /* Return to caller.  */
416
1
                return(status);
417
            }
418
419
            /* Determine if this is an empty entry.  */
420

155
            if ((dir_entry1.fx_dir_entry_name[0] == (CHAR)FX_DIR_ENTRY_FREE) && (dir_entry1.fx_dir_entry_short_name[0] == 0))
421
            {
422
423
                /* Yes, this is free entry.  Is it the first?  */
424
6
                if (i < j)
425
                {
426
427
                    /* Yes, first free entry - remember it.  */
428
5
                    dir_entry =  dir_entry1;
429
5
                    j =  i;
430
                }
431
            }
432
            /* Determine if the directory entries are exhausted.  */
433
149
            else if (dir_entry1.fx_dir_entry_name[0] == FX_DIR_ENTRY_DONE)
434
            {
435
436
                /* Yes, this we are at the end of the directory.  Have there
437
                been any other free entries?  */
438
10
                if (i < j)
439
                {
440
441
                    /* No, we need to remember this as the free entry.  */
442
8
                    dir_entry =  dir_entry1;
443
8
                    j =  i;
444
                }
445
10
                break;
446
            }
447
            /* Check for a volume name.  */
448
139
            else if (dir_entry1.fx_dir_entry_attributes & FX_VOLUME)
449
            {
450
451
                /* Yes, we have found a previously set volume name - use this entry.  */
452
9
                dir_entry =  dir_entry1;
453
9
                j =  i;
454
9
                break;
455
            }
456
457
            /* Move to next directory entry.  */
458
136
            i++;
459
136
        } while (i < media_ptr -> fx_media_root_directory_entries);
460
461
        /* Determine if a volume entry was not found and there are no more empty slots.  */
462
22
        if (i == media_ptr -> fx_media_root_directory_entries)
463
        {
464
465
            /* Determine if there was a free or previous volume name.  */
466
3
            if (j == (media_ptr -> fx_media_root_directory_entries + 1))
467
            {
468
469
                /* No, nothing was available in the root directory.  */
470
471
                /* Release media protection.  */
472
1
                FX_UNPROTECT
473
474
                /* No, existing volume name or space in the root directly was found, return an error.  */
475
1
                return(FX_MEDIA_INVALID);
476
            }
477
        }
478
479
        /* Now set the volume name and attribute.  */
480
481
        /* Read the logical directory sector.  */
482
21
        status =  _fx_utility_logical_sector_read(media_ptr, (ULONG64) dir_entry.fx_dir_entry_log_sector,
483
21
                                                  media_ptr -> fx_media_memory_buffer, ((ULONG) 1), FX_BOOT_SECTOR);
484
485
        /* Check the status of reading the directory entry. */
486
21
        if (status != FX_SUCCESS)
487
        {
488
489
            /* Release media protection.  */
490
1
            FX_UNPROTECT
491
492
            /* Return the error status.  */
493
1
            return(status);
494
        }
495
496
        /* Calculate pointer into directory buffer.  */
497
20
        work_ptr =  media_ptr -> fx_media_memory_buffer +
498
20
            (UINT)dir_entry.fx_dir_entry_byte_offset;
499
500
        /* Copy the volume name into the directory entry.  */
501
151
        for (i = 0; volume_name[i]; i++)
502
        {
503
504
            /* Have we reached the end?  */
505
133
            if (i == 11)
506
            {
507
508
2
                break;
509
            }
510
511
            /* Pickup volume name byte.  */
512
131
            alpha =  volume_name[i];
513
514
            /* Determine if alpha needs to be converted to upper case.  */
515

131
            if ((alpha >= 'a') && (alpha <= 'z'))
516
            {
517
518
                /* Convert alpha to upper case.  */
519
25
                alpha =  (CHAR)((INT)alpha - 0x20);
520
            }
521
522
            /* Store volume name.  */
523
131
            work_ptr[i] =  (UCHAR)alpha;
524
        }
525
526
        /* Pad with space characters.  */
527
109
        for (; i < 11; i++)
528
        {
529
89
            work_ptr[i] =  0x20;
530
        }
531
532
        /* Set the appropriate attributes.  */
533
20
        work_ptr[11] =  FX_VOLUME | FX_ARCHIVE;
534
535
        /* Set the other parts of the volume entry.  */
536
537
        /* Clear the hi word of cluster.  */
538
20
        work_ptr[20] =  0;
539
20
        work_ptr[21] =  0;
540
541
        /* Clear the low word of cluster.  */
542
20
        work_ptr[26] =  0;
543
20
        work_ptr[27] =  0;
544
545
        /* Clear the file size.  */
546
20
        work_ptr[28] =  0;
547
20
        work_ptr[29] =  0;
548
20
        work_ptr[30] =  0;
549
20
        work_ptr[31] =  0;
550
551
        /* Write the directory sector to the media.  */
552
20
        status =  _fx_utility_logical_sector_write(media_ptr, (ULONG64) dir_entry.fx_dir_entry_log_sector,
553
20
                                                   media_ptr -> fx_media_memory_buffer, ((ULONG) 1), FX_DIRECTORY_SECTOR);
554
#ifdef FX_ENABLE_EXFAT
555
    }
556
#endif /* FX_ENABLE_EXFAT */
557
558
    /* Release media protection.  */
559
20
    FX_UNPROTECT
560
561
    /* Return the status.  */
562
20
    return(status);
563
}
564