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 /** RAM Disk Driver */
18 /** */
19 /**************************************************************************/
20 /**************************************************************************/
21
22
23 /* Include necessary system files. */
24
25 #include "fx_api.h"
26
27
28 /* The RAM driver relies on the fx_media_format call to be made prior to
29 the fx_media_open call. The following call will format the default
30 32KB RAM drive, with a sector size of 128 bytes per sector.
31
32 fx_media_format(&ram_disk,
33 _fx_ram_driver, // Driver entry
34 ram_disk_memory, // RAM disk memory pointer
35 media_memory, // Media buffer pointer
36 sizeof(media_memory), // Media buffer size
37 "MY_RAM_DISK", // Volume Name
38 1, // Number of FATs
39 32, // Directory Entries
40 0, // Hidden sectors
41 256, // Total sectors
42 128, // Sector size
43 1, // Sectors per cluster
44 1, // Heads
45 1); // Sectors per track
46
47 */
48
49
50 VOID _fx_ram_driver(FX_MEDIA *media_ptr);
51
52
53 /**************************************************************************/
54 /* */
55 /* FUNCTION RELEASE */
56 /* */
57 /* _fx_ram_driver PORTABLE C */
58 /* 6.1.5 */
59 /* AUTHOR */
60 /* */
61 /* William E. Lamie, Microsoft Corporation */
62 /* */
63 /* DESCRIPTION */
64 /* */
65 /* This function is the entry point to the generic RAM disk driver */
66 /* that is delivered with all versions of FileX. The format of the */
67 /* RAM disk is easily modified by calling fx_media_format prior */
68 /* to opening the media. */
69 /* */
70 /* This driver also serves as a template for developing FileX drivers */
71 /* for actual devices. Simply replace the read/write sector logic with */
72 /* calls to read/write from the appropriate physical device */
73 /* */
74 /* FileX RAM/FLASH structures look like the following: */
75 /* */
76 /* Physical Sector Contents */
77 /* */
78 /* 0 Boot record */
79 /* 1 FAT Area Start */
80 /* +FAT Sectors Root Directory Start */
81 /* +Directory Sectors Data Sector Start */
82 /* */
83 /* */
84 /* INPUT */
85 /* */
86 /* media_ptr Media control block pointer */
87 /* */
88 /* OUTPUT */
89 /* */
90 /* None */
91 /* */
92 /* CALLS */
93 /* */
94 /* _fx_utility_memory_copy Copy sector memory */
95 /* _fx_utility_16_unsigned_read Read 16-bit unsigned */
96 /* */
97 /* CALLED BY */
98 /* */
99 /* FileX System Functions */
100 /* */
101 /* RELEASE HISTORY */
102 /* */
103 /* DATE NAME DESCRIPTION */
104 /* */
105 /* 05-19-2020 William E. Lamie Initial Version 6.0 */
106 /* 09-30-2020 William E. Lamie Modified comment(s), */
107 /* resulting in version 6.1 */
108 /* 03-02-2021 William E. Lamie Modified comment(s), */
109 /* resulting in version 6.1.5 */
110 /* */
111 /**************************************************************************/
_fx_ram_driver(FX_MEDIA * media_ptr)112 VOID _fx_ram_driver(FX_MEDIA *media_ptr)
113 {
114
115 UCHAR *source_buffer;
116 UCHAR *destination_buffer;
117 UINT bytes_per_sector;
118
119
120 /* There are several useful/important pieces of information contained in
121 the media structure, some of which are supplied by FileX and others
122 are for the driver to setup. The following is a summary of the
123 necessary FX_MEDIA structure members:
124
125 FX_MEDIA Member Meaning
126
127 fx_media_driver_request FileX request type. Valid requests from
128 FileX are as follows:
129
130 FX_DRIVER_READ
131 FX_DRIVER_WRITE
132 FX_DRIVER_FLUSH
133 FX_DRIVER_ABORT
134 FX_DRIVER_INIT
135 FX_DRIVER_BOOT_READ
136 FX_DRIVER_RELEASE_SECTORS
137 FX_DRIVER_BOOT_WRITE
138 FX_DRIVER_UNINIT
139
140 fx_media_driver_status This value is RETURNED by the driver.
141 If the operation is successful, this
142 field should be set to FX_SUCCESS for
143 before returning. Otherwise, if an
144 error occurred, this field should be
145 set to FX_IO_ERROR.
146
147 fx_media_driver_buffer Pointer to buffer to read or write
148 sector data. This is supplied by
149 FileX.
150
151 fx_media_driver_logical_sector Logical sector FileX is requesting.
152
153 fx_media_driver_sectors Number of sectors FileX is requesting.
154
155
156 The following is a summary of the optional FX_MEDIA structure members:
157
158 FX_MEDIA Member Meaning
159
160 fx_media_driver_info Pointer to any additional information
161 or memory. This is optional for the
162 driver use and is setup from the
163 fx_media_open call. The RAM disk uses
164 this pointer for the RAM disk memory
165 itself.
166
167 fx_media_driver_write_protect The DRIVER sets this to FX_TRUE when
168 media is write protected. This is
169 typically done in initialization,
170 but can be done anytime.
171
172 fx_media_driver_free_sector_update The DRIVER sets this to FX_TRUE when
173 it needs to know when clusters are
174 released. This is important for FLASH
175 wear-leveling drivers.
176
177 fx_media_driver_system_write FileX sets this flag to FX_TRUE if the
178 sector being written is a system sector,
179 e.g., a boot, FAT, or directory sector.
180 The driver may choose to use this to
181 initiate error recovery logic for greater
182 fault tolerance.
183
184 fx_media_driver_data_sector_read FileX sets this flag to FX_TRUE if the
185 sector(s) being read are file data sectors,
186 i.e., NOT system sectors.
187
188 fx_media_driver_sector_type FileX sets this variable to the specific
189 type of sector being read or written. The
190 following sector types are identified:
191
192 FX_UNKNOWN_SECTOR
193 FX_BOOT_SECTOR
194 FX_FAT_SECTOR
195 FX_DIRECTORY_SECTOR
196 FX_DATA_SECTOR
197 */
198
199 /* Process the driver request specified in the media control block. */
200 switch (media_ptr -> fx_media_driver_request)
201 {
202
203 case FX_DRIVER_READ:
204 {
205
206 /* Calculate the RAM disk sector offset. Note the RAM disk memory is pointed to by
207 the fx_media_driver_info pointer, which is supplied by the application in the
208 call to fx_media_open. */
209 source_buffer = ((UCHAR *)media_ptr -> fx_media_driver_info) +
210 ((media_ptr -> fx_media_driver_logical_sector +
211 media_ptr -> fx_media_hidden_sectors) *
212 media_ptr -> fx_media_bytes_per_sector);
213
214 /* Copy the RAM sector into the destination. */
215 _fx_utility_memory_copy(source_buffer, media_ptr -> fx_media_driver_buffer,
216 media_ptr -> fx_media_driver_sectors *
217 media_ptr -> fx_media_bytes_per_sector);
218
219 /* Successful driver request. */
220 media_ptr -> fx_media_driver_status = FX_SUCCESS;
221 break;
222 }
223
224 case FX_DRIVER_WRITE:
225 {
226
227 /* Calculate the RAM disk sector offset. Note the RAM disk memory is pointed to by
228 the fx_media_driver_info pointer, which is supplied by the application in the
229 call to fx_media_open. */
230 destination_buffer = ((UCHAR *)media_ptr -> fx_media_driver_info) +
231 ((media_ptr -> fx_media_driver_logical_sector +
232 media_ptr -> fx_media_hidden_sectors) *
233 media_ptr -> fx_media_bytes_per_sector);
234
235 /* Copy the source to the RAM sector. */
236 _fx_utility_memory_copy(media_ptr -> fx_media_driver_buffer, destination_buffer,
237 media_ptr -> fx_media_driver_sectors *
238 media_ptr -> fx_media_bytes_per_sector);
239
240 /* Successful driver request. */
241 media_ptr -> fx_media_driver_status = FX_SUCCESS;
242 break;
243 }
244
245 case FX_DRIVER_FLUSH:
246 {
247
248 /* Return driver success. */
249 media_ptr -> fx_media_driver_status = FX_SUCCESS;
250 break;
251 }
252
253 case FX_DRIVER_ABORT:
254 {
255
256 /* Return driver success. */
257 media_ptr -> fx_media_driver_status = FX_SUCCESS;
258 break;
259 }
260
261 case FX_DRIVER_INIT:
262 {
263
264 /* FLASH drivers are responsible for setting several fields in the
265 media structure, as follows:
266
267 media_ptr -> fx_media_driver_free_sector_update
268 media_ptr -> fx_media_driver_write_protect
269
270 The fx_media_driver_free_sector_update flag is used to instruct
271 FileX to inform the driver whenever sectors are not being used.
272 This is especially useful for FLASH managers so they don't have
273 maintain mapping for sectors no longer in use.
274
275 The fx_media_driver_write_protect flag can be set anytime by the
276 driver to indicate the media is not writable. Write attempts made
277 when this flag is set are returned as errors. */
278
279 /* Perform basic initialization here... since the boot record is going
280 to be read subsequently and again for volume name requests. */
281
282 /* Successful driver request. */
283 media_ptr -> fx_media_driver_status = FX_SUCCESS;
284 break;
285 }
286
287 case FX_DRIVER_UNINIT:
288 {
289
290 /* There is nothing to do in this case for the RAM driver. For actual
291 devices some shutdown processing may be necessary. */
292
293 /* Successful driver request. */
294 media_ptr -> fx_media_driver_status = FX_SUCCESS;
295 break;
296 }
297
298 case FX_DRIVER_BOOT_READ:
299 {
300
301 /* Read the boot record and return to the caller. */
302
303 /* Calculate the RAM disk boot sector offset, which is at the very beginning of
304 the RAM disk. Note the RAM disk memory is pointed to by the
305 fx_media_driver_info pointer, which is supplied by the application in the
306 call to fx_media_open. */
307 source_buffer = (UCHAR *)media_ptr -> fx_media_driver_info;
308
309 /* For RAM driver, determine if the boot record is valid. */
310 if ((source_buffer[0] != (UCHAR)0xEB) ||
311 ((source_buffer[1] != (UCHAR)0x34) &&
312 (source_buffer[1] != (UCHAR)0x76)) ||
313 (source_buffer[2] != (UCHAR)0x90))
314 {
315
316 /* Invalid boot record, return an error! */
317 media_ptr -> fx_media_driver_status = FX_MEDIA_INVALID;
318 return;
319 }
320
321 /* For RAM disk only, pickup the bytes per sector. */
322 bytes_per_sector = _fx_utility_16_unsigned_read(&source_buffer[FX_BYTES_SECTOR]);
323
324
325 /* Ensure this is less than the media memory size. */
326 if (bytes_per_sector > media_ptr -> fx_media_memory_size)
327 {
328 media_ptr -> fx_media_driver_status = FX_BUFFER_ERROR;
329 break;
330 }
331
332 /* Copy the RAM boot sector into the destination. */
333 _fx_utility_memory_copy(source_buffer, media_ptr -> fx_media_driver_buffer,
334 bytes_per_sector);
335
336 /* Successful driver request. */
337 media_ptr -> fx_media_driver_status = FX_SUCCESS;
338 break;
339 }
340
341 case FX_DRIVER_BOOT_WRITE:
342 {
343
344 /* Write the boot record and return to the caller. */
345
346 /* Calculate the RAM disk boot sector offset, which is at the very beginning of the
347 RAM disk. Note the RAM disk memory is pointed to by the fx_media_driver_info
348 pointer, which is supplied by the application in the call to fx_media_open. */
349 destination_buffer = (UCHAR *)media_ptr -> fx_media_driver_info;
350
351 /* Copy the RAM boot sector into the destination. */
352 _fx_utility_memory_copy(media_ptr -> fx_media_driver_buffer, destination_buffer,
353 media_ptr -> fx_media_bytes_per_sector);
354
355 /* Successful driver request. */
356 media_ptr -> fx_media_driver_status = FX_SUCCESS;
357 break;
358 }
359
360 default:
361 {
362
363 /* Invalid driver request. */
364 media_ptr -> fx_media_driver_status = FX_IO_ERROR;
365 break;
366 }
367 }
368 }
369
370