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_system.h"
29 #include "fx_directory.h"
30 #include "fx_media.h"
31 #include "fx_utility.h"
32 
33 
34 /**************************************************************************/
35 /*                                                                        */
36 /*  FUNCTION                                               RELEASE        */
37 /*                                                                        */
38 /*    _fx_media_volume_get_extended                       PORTABLE C      */
39 /*                                                           6.1.11       */
40 /*  AUTHOR                                                                */
41 /*                                                                        */
42 /*    William E. Lamie, Microsoft Corporation                             */
43 /*                                                                        */
44 /*  DESCRIPTION                                                           */
45 /*                                                                        */
46 /*    This function reads the volume name stored in the media's boot      */
47 /*    record or root directory.                                           */
48 /*                                                                        */
49 /*  INPUT                                                                 */
50 /*                                                                        */
51 /*    media_ptr                             Media control block pointer   */
52 /*    volume_name                           Pointer to destination for    */
53 /*                                            the volume name (maximum    */
54 /*                                            11 characters + NULL)       */
55 /*    volume_name_buffer_length             Buffer length for volume_name */
56 /*    volume_source                         Source of volume              */
57 /*                                                                        */
58 /*  OUTPUT                                                                */
59 /*                                                                        */
60 /*    return status                                                       */
61 /*                                                                        */
62 /*  CALLS                                                                 */
63 /*                                                                        */
64 /*    _fx_utility_logical_sector_read       Read directory sector         */
65 /*    _fx_directory_entry_read              Directory entry read          */
66 /*                                                                        */
67 /*  CALLED BY                                                             */
68 /*                                                                        */
69 /*    Application Code                                                    */
70 /*                                                                        */
71 /*  RELEASE HISTORY                                                       */
72 /*                                                                        */
73 /*    DATE              NAME                      DESCRIPTION             */
74 /*                                                                        */
75 /*  05-19-2020     William E. Lamie         Initial Version 6.0           */
76 /*  09-30-2020     William E. Lamie         Modified comment(s),          */
77 /*                                            resulting in version 6.1    */
78 /*  04-25-2022     Bhupendra Naphade        Modified comment(s), and      */
79 /*                                            updated check for           */
80 /*                                            volume name,                */
81 /*                                            resulting in version 6.1.11 */
82 /*                                                                        */
83 /**************************************************************************/
_fx_media_volume_get_extended(FX_MEDIA * media_ptr,CHAR * volume_name,UINT volume_name_buffer_length,UINT volume_source)84 UINT  _fx_media_volume_get_extended(FX_MEDIA *media_ptr, CHAR *volume_name, UINT volume_name_buffer_length, UINT volume_source)
85 {
86 
87 UINT         status, offset;
88 ULONG        i;
89 INT          j;
90 
91 FX_DIR_ENTRY dir_entry;
92 
93 
94     /* Clear the volume name.  */
95     volume_name[0] =  FX_NULL;
96 
97     /* Check the media to make sure it is open.  */
98     if (media_ptr -> fx_media_id != FX_MEDIA_ID)
99     {
100 
101         /* Return the media not opened error.  */
102         return(FX_MEDIA_NOT_OPEN);
103     }
104 
105     /* If trace is enabled, insert this event into the trace buffer.  */
106     FX_TRACE_IN_LINE_INSERT(FX_TRACE_MEDIA_VOLUME_GET, media_ptr, volume_name, volume_source, 0, FX_TRACE_MEDIA_EVENTS, 0, 0)
107 
108     /* Protect against other threads accessing the media.  */
109     FX_PROTECT
110 
111 
112     /* Ensure the volume name is NULL initially.  */
113     volume_name[0] =  FX_NULL;
114 
115     if (volume_source == FX_DIRECTORY_SECTOR)
116     {
117 
118         /* Setup pointer to media name buffer.  */
119         dir_entry.fx_dir_entry_name =  media_ptr -> fx_media_name_buffer;
120 
121         /* Clear the short name string.  */
122         dir_entry.fx_dir_entry_short_name[0] =  0;
123 
124         /* Attempt to find the volume name in the root directory.  */
125         i =  0;
126         do
127         {
128 
129             /* Read an entry from the root directory.  */
130             status =  _fx_directory_entry_read(media_ptr, FX_NULL, &i, &dir_entry);
131 
132             /* Check for error status.  */
133             if (status != FX_SUCCESS)
134             {
135 
136                 /* Release media protection.  */
137                 FX_UNPROTECT
138 
139                 /* Return to caller.  */
140                 return(status);
141             }
142 
143             /* Check for a volume name.  */
144             if ((dir_entry.fx_dir_entry_attributes & FX_VOLUME) && ((UCHAR)dir_entry.fx_dir_entry_name[0] != (UCHAR)FX_DIR_ENTRY_FREE))
145             {
146 
147                 /* Yes, we have found a previously set volume name.  */
148                 break;
149             }
150 
151             /* Move to next directory entry.  */
152             i++;
153         } while (i < media_ptr -> fx_media_root_directory_entries);
154 
155         /* Determine if a volume entry has been found.  */
156         if (i < media_ptr -> fx_media_root_directory_entries)
157         {
158 
159             /* Read the logical directory sector.  */
160             status =  _fx_utility_logical_sector_read(media_ptr, (ULONG64) dir_entry.fx_dir_entry_log_sector,
161                                                       media_ptr -> fx_media_memory_buffer, ((ULONG) 1), FX_DIRECTORY_SECTOR);
162 
163             /* Determine if an error occurred.  */
164             if (status != FX_SUCCESS)
165             {
166 
167                 /* Release media protection.  */
168                 FX_UNPROTECT
169 
170                 /* Return error code.  */
171                 return(status);
172             }
173 
174             /* Offset to volume label entry.  */
175             offset = dir_entry.fx_dir_entry_byte_offset;
176 
177 
178             /* Skip trailing space characters of volume name. */
179             for (j = 10; j >= 0; j--)
180             {
181 
182                 /* Check for space character.  */
183                 if (media_ptr -> fx_media_memory_buffer[offset + (UINT)j] != (UCHAR)' ')
184                 {
185 
186                     /* Last character found. */
187                     break;
188                 }
189             }
190 
191             /* Check if the buffer is too short for the name.  */
192             if (j >= (INT)volume_name_buffer_length - 1)
193             {
194 
195                 /* Buffer too short, return error.  */
196                 status =  FX_BUFFER_ERROR;
197 
198                 /* Set character count to fit for the buffer.  */
199                 j = (INT)volume_name_buffer_length - 2;
200             }
201 
202             /* NULL terminate the volume name.  */
203             volume_name[j + 1] =  FX_NULL;
204 
205             /* Pickup the remaining characters of the volume name from the boot sector.  */
206             for (; j >= 0; j--)
207             {
208 
209                 /* Pickup byte of volume name.  */
210                 volume_name[j] =  (CHAR)media_ptr -> fx_media_memory_buffer[offset + (UINT)j];
211             }
212 
213             /* Release media protection.  */
214             FX_UNPROTECT
215 
216             /* Return the completion status.  */
217             return(status);
218         }
219     }
220 
221     /* Read volume name from boot record.  */
222     /* Read the logical directory sector 0 - we just do this to get a memory_buffer pointer */
223     status =  _fx_utility_logical_sector_read(media_ptr, ((ULONG64) 0),
224                                               media_ptr -> fx_media_memory_buffer, ((ULONG) 1), FX_DATA_SECTOR);
225 
226     /* Check the return status.  */
227     if (status != FX_SUCCESS)
228     {
229 
230         /* Release media protection.  */
231         FX_UNPROTECT
232 
233         /* Return the error status.  */
234         return(status);
235     }
236 
237 #ifndef FX_MEDIA_STATISTICS_DISABLE
238 
239     /* Increment the number of driver read boot sector requests.  */
240     media_ptr -> fx_media_driver_boot_read_requests++;
241 #endif
242 
243     /* Build the driver request to read the boot record.  */
244     media_ptr -> fx_media_driver_request =      FX_DRIVER_BOOT_READ;
245     media_ptr -> fx_media_driver_status =       FX_IO_ERROR;
246     media_ptr -> fx_media_driver_buffer =       media_ptr -> fx_media_memory_buffer;
247     media_ptr -> fx_media_driver_sectors =      1;
248     media_ptr -> fx_media_driver_sector_type =  FX_BOOT_SECTOR;
249 
250     /* If trace is enabled, insert this event into the trace buffer.  */
251     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)
252 
253     /* Invoke the driver to read the boot sector.  */
254     (media_ptr -> fx_media_driver_entry) (media_ptr);
255 
256     /* Determine if the request is successful.  */
257     if (media_ptr -> fx_media_driver_status)
258     {
259 
260         /* Release media protection.  */
261         FX_UNPROTECT
262 
263         /* An error occurred in the driver.  */
264         return(media_ptr -> fx_media_driver_status);
265     }
266 
267     /* Calculate the offset to the volume name based on the type of FAT.  */
268     if (media_ptr -> fx_media_32_bit_FAT)
269     {
270 
271         /* FAT32 offset to volume name.  */
272         offset =  FX_VOLUME_LABEL_32;
273     }
274     else
275     {
276 
277         /* FAT12/16 offset to volume name.  */
278         offset =  FX_VOLUME_LABEL;
279     }
280 
281     /* Skip trailing space characters of volume name. */
282     for (j = 10; j >= 0; j--)
283     {
284 
285         /* Check for space character.  */
286         if (media_ptr -> fx_media_memory_buffer[offset + (UINT)j] != (UCHAR)' ')
287         {
288 
289             /* Last character found. */
290             break;
291         }
292     }
293 
294     /* Check if the buffer is too short for the name.  */
295     if (j >= (INT)volume_name_buffer_length - 1)
296     {
297 
298         /* Buffer too short, return error.  */
299         status =  FX_BUFFER_ERROR;
300 
301         /* Set character count to fit for the buffer.  */
302         j = (INT)volume_name_buffer_length - 2;
303     }
304 
305     /* NULL terminate the volume name.  */
306     volume_name[j + 1] =  FX_NULL;
307 
308     /* Pickup the remaining characters of the volume name from the boot sector.  */
309     for (; j >= 0; j--)
310     {
311 
312         /* Pickup byte of volume name.  */
313         volume_name[j] =  (CHAR)media_ptr -> fx_media_memory_buffer[offset + (UINT)j];
314     }
315 
316     /* Release media protection.  */
317     FX_UNPROTECT
318 
319     /* Return the completion status.  */
320     return(status);
321 }
322 
323