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