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