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 /**   FileX NOR FLASH Simulator Driver                                    */
18 /**                                                                       */
19 /**************************************************************************/
20 /**************************************************************************/
21 
22 
23 /* Include necessary system files.  */
24 
25 #include "fx_api.h"
26 #include "lx_api.h"
27 
28 
29 /* Create a NOR flash control block.  */
30 
31 LX_NOR_FLASH       nor_flash;
32 
33 
34 /* The simulated NOR driver relies on the fx_media_format call to be made prior to
35    the fx_media_open call.
36 
37         fx_media_format(&ram_disk,
38                             _fx_nor_sim_driver,                 // Driver entry
39                             FX_NULL,                            // Unused
40                             media_memory,                       // Media buffer pointer
41                             sizeof(media_memory),               // Media buffer size
42                             "MY_NOR_DISK",                      // Volume Name
43                             1,                                  // Number of FATs
44                             32,                                 // Directory Entries
45                             0,                                  // Hidden sectors
46                             120,                                // Total sectors
47                             LX_NOR_SECTOR_SIZE * sizeof(ULONG), // Sector size
48                             1,                                  // Sectors per cluster
49                             1,                                  // Heads
50                             1);                                 // Sectors per track
51 
52 */
53 
54 
55 /* Define prototypes.  */
56 
57 UINT  _lx_nor_flash_simulator_initialize(LX_NOR_FLASH *nor_flash);
58 VOID  _fx_nor_flash_simulator_driver(FX_MEDIA *media_ptr);
59 
60 
61 /**************************************************************************/
62 /*                                                                        */
63 /*  FUNCTION                                               RELEASE        */
64 /*                                                                        */
65 /*    _fx_nor_flash_simulator_driver                      PORTABLE C      */
66 /*                                                           6.1.7        */
67 /*  AUTHOR                                                                */
68 /*                                                                        */
69 /*    William E. Lamie, Microsoft Corporation                             */
70 /*                                                                        */
71 /*  DESCRIPTION                                                           */
72 /*                                                                        */
73 /*    This function is the entry point to the generic NOR simulated       */
74 /*    disk driver that is delivered with the flash wear leveling product  */
75 /*    LevelX.                                                             */
76 /*                                                                        */
77 /*    This driver also serves as a template for developing other LevelX   */
78 /*    NOR flash drivers for actual flash devices. Simply replace the      */
79 /*    read/write sector logic with calls to read/write from the           */
80 /*    appropriate physical device access functions.                       */
81 /*                                                                        */
82 /*    FileX NOR FLASH structures look like the following:                 */
83 /*                                                                        */
84 /*          Logical Sector                  Contents                      */
85 /*                                                                        */
86 /*              0                       Boot record                       */
87 /*              1                       FAT Area Start                    */
88 /*              +FAT Sectors            Root Directory Start              */
89 /*              +Directory Sectors      Data Sector Start                 */
90 /*                                                                        */
91 /*                                                                        */
92 /*  INPUT                                                                 */
93 /*                                                                        */
94 /*    media_ptr                             Media control block pointer   */
95 /*                                                                        */
96 /*  OUTPUT                                                                */
97 /*                                                                        */
98 /*    None                                                                */
99 /*                                                                        */
100 /*  CALLS                                                                 */
101 /*                                                                        */
102 /*    lx_nor_flash_close                    Close NOR flash manager       */
103 /*    lx_nor_flash_open                     Open NOR flash manager        */
104 /*    lx_nor_flash_sector_read              Read a NOR sector             */
105 /*    lx_nor_flash_sector_release           Release a NOR sector          */
106 /*    lx_nor_flash_sector_write             Write a NOR sector            */
107 /*                                                                        */
108 /*  CALLED BY                                                             */
109 /*                                                                        */
110 /*    FileX System Functions                                              */
111 /*                                                                        */
112 /*  RELEASE HISTORY                                                       */
113 /*                                                                        */
114 /*    DATE              NAME                      DESCRIPTION             */
115 /*                                                                        */
116 /*  05-19-2020     William E. Lamie         Initial Version 6.0           */
117 /*  09-30-2020     William E. Lamie         Modified comment(s),          */
118 /*                                            resulting in version 6.1    */
119 /*  06-02-2021     Bhupendra Naphade        Modified comment(s),          */
120 /*                                            resulting in version 6.1.7  */
121 /*                                                                        */
122 /**************************************************************************/
_fx_nor_flash_simulator_driver(FX_MEDIA * media_ptr)123 VOID  _fx_nor_flash_simulator_driver(FX_MEDIA *media_ptr)
124 {
125 
126 UCHAR       *source_buffer;
127 UCHAR       *destination_buffer;
128 ULONG       logical_sector;
129 ULONG       i;
130 UINT        status;
131 
132 
133     /* There are several useful/important pieces of information contained in the media
134        structure, some of which are supplied by FileX and others are for the driver to
135        setup. The following is a summary of the necessary FX_MEDIA structure members:
136 
137             FX_MEDIA Member                              Meaning
138 
139         fx_media_driver_request             FileX request type. Valid requests from FileX are
140                                             as follows:
141 
142                                                     FX_DRIVER_READ
143                                                     FX_DRIVER_WRITE
144                                                     FX_DRIVER_FLUSH
145                                                     FX_DRIVER_ABORT
146                                                     FX_DRIVER_INIT
147                                                     FX_DRIVER_BOOT_READ
148                                                     FX_DRIVER_RELEASE_SECTORS
149                                                     FX_DRIVER_BOOT_WRITE
150                                                     FX_DRIVER_UNINIT
151 
152         fx_media_driver_status              This value is RETURNED by the driver. If the
153                                             operation is successful, this field should be
154                                             set to FX_SUCCESS for before returning. Otherwise,
155                                             if an error occurred, this field should be set
156                                             to FX_IO_ERROR.
157 
158         fx_media_driver_buffer              Pointer to buffer to read or write sector data.
159                                             This is supplied by FileX.
160 
161         fx_media_driver_logical_sector      Logical sector FileX is requesting.
162 
163         fx_media_driver_sectors             Number of sectors FileX is requesting.
164 
165 
166        The following is a summary of the optional FX_MEDIA structure members:
167 
168             FX_MEDIA Member                              Meaning
169 
170         fx_media_driver_info                Pointer to any additional information or memory.
171                                             This is optional for the driver use and is setup
172                                             from the fx_media_open call. The RAM disk uses
173                                             this pointer for the RAM disk memory itself.
174 
175         fx_media_driver_write_protect       The DRIVER sets this to FX_TRUE when media is write
176                                             protected. This is typically done in initialization,
177                                             but can be done anytime.
178 
179         fx_media_driver_free_sector_update  The DRIVER sets this to FX_TRUE when it needs to
180                                             know when clusters are released. This is important
181                                             for FLASH wear-leveling drivers.
182 
183         fx_media_driver_system_write        FileX sets this flag to FX_TRUE if the sector being
184                                             written is a system sector, e.g., a boot, FAT, or
185                                             directory sector. The driver may choose to use this
186                                             to initiate error recovery logic for greater fault
187                                             tolerance.
188 
189         fx_media_driver_data_sector_read    FileX sets this flag to FX_TRUE if the sector(s) being
190                                             read are file data sectors, i.e., NOT system sectors.
191 
192         fx_media_driver_sector_type         FileX sets this variable to the specific type of
193                                             sector being read or written. The following sector
194                                             types are identified:
195 
196                                                     FX_UNKNOWN_SECTOR
197                                                     FX_BOOT_SECTOR
198                                                     FX_FAT_SECTOR
199                                                     FX_DIRECTORY_SECTOR
200                                                     FX_DATA_SECTOR
201     */
202 
203     /* Process the driver request specified in the media control block.  */
204     switch(media_ptr -> fx_media_driver_request)
205     {
206 
207         case FX_DRIVER_READ:
208         {
209 
210             /* Setup the destination buffer and logical sector.  */
211             logical_sector =      media_ptr -> fx_media_driver_logical_sector;
212             destination_buffer =  (UCHAR *) media_ptr -> fx_media_driver_buffer;
213 
214             /* Loop to read sectors from flash.  */
215             for (i = 0; i < media_ptr -> fx_media_driver_sectors; i++)
216             {
217 
218                 /* Read a sector from NOR flash.  */
219                 status =  lx_nor_flash_sector_read(&nor_flash, logical_sector, destination_buffer);
220 
221                 /* Determine if the read was successful.  */
222                 if (status != LX_SUCCESS)
223                 {
224 
225                     /* Return an I/O error to FileX.  */
226                     media_ptr -> fx_media_driver_status =  FX_IO_ERROR;
227 
228                     return;
229                 }
230 
231                 /* Move to the next entries.  */
232                 logical_sector++;
233                 destination_buffer =  destination_buffer + media_ptr -> fx_media_bytes_per_sector;
234             }
235 
236             /* Successful driver request.  */
237             media_ptr -> fx_media_driver_status =  FX_SUCCESS;
238             break;
239         }
240 
241         case FX_DRIVER_WRITE:
242         {
243 
244             /* Setup the source buffer and logical sector.  */
245             logical_sector =      media_ptr -> fx_media_driver_logical_sector;
246             source_buffer =       (UCHAR *) media_ptr -> fx_media_driver_buffer;
247 
248             /* Loop to write sectors to flash.  */
249             for (i = 0; i < media_ptr -> fx_media_driver_sectors; i++)
250             {
251 
252                 /* Write a sector to NOR flash.  */
253                 status =  lx_nor_flash_sector_write(&nor_flash, logical_sector, source_buffer);
254 
255                 /* Determine if the write was successful.  */
256                 if (status != LX_SUCCESS)
257                 {
258 
259                     /* Return an I/O error to FileX.  */
260                     media_ptr -> fx_media_driver_status =  FX_IO_ERROR;
261 
262                     return;
263                 }
264 
265                 /* Move to the next entries.  */
266                 logical_sector++;
267                 source_buffer =  source_buffer + media_ptr -> fx_media_bytes_per_sector;
268             }
269 
270             /* Successful driver request.  */
271             media_ptr -> fx_media_driver_status =  FX_SUCCESS;
272             break;
273         }
274 
275         case FX_DRIVER_RELEASE_SECTORS:
276         {
277 
278             /* Setup the logical sector.  */
279             logical_sector =  media_ptr -> fx_media_driver_logical_sector;
280 
281             /* Release sectors.  */
282             for (i = 0; i < media_ptr -> fx_media_driver_sectors; i++)
283             {
284 
285                 /* Release NOR flash sector.  */
286                 status =  lx_nor_flash_sector_release(&nor_flash, logical_sector);
287 
288                 /* Determine if the sector release was successful.  */
289                 if (status != LX_SUCCESS)
290                 {
291 
292                     /* Return an I/O error to FileX.  */
293                     media_ptr -> fx_media_driver_status =  FX_IO_ERROR;
294 
295                     return;
296                 }
297 
298                 /* Move to the next entries.  */
299                 logical_sector++;
300             }
301 
302             /* Successful driver request.  */
303             media_ptr -> fx_media_driver_status =  FX_SUCCESS;
304             break;
305         }
306 
307         case FX_DRIVER_FLUSH:
308         {
309 
310             /* Return driver success.  */
311             media_ptr -> fx_media_driver_status =  FX_SUCCESS;
312             break;
313         }
314 
315         case FX_DRIVER_ABORT:
316         {
317 
318             /* Return driver success.  */
319             media_ptr -> fx_media_driver_status =  FX_SUCCESS;
320             break;
321         }
322 
323         case FX_DRIVER_INIT:
324         {
325 
326             /* FLASH drivers are responsible for setting several fields in the
327                media structure, as follows:
328 
329                     media_ptr -> fx_media_driver_free_sector_update
330                     media_ptr -> fx_media_driver_write_protect
331 
332                The fx_media_driver_free_sector_update flag is used to instruct
333                FileX to inform the driver whenever sectors are not being used.
334                This is especially useful for FLASH managers so they don't have
335                maintain mapping for sectors no longer in use.
336 
337                The fx_media_driver_write_protect flag can be set anytime by the
338                driver to indicate the media is not writable.  Write attempts made
339                when this flag is set are returned as errors.  */
340 
341             /* Perform basic initialization here... since the boot record is going
342                to be read subsequently and again for volume name requests.  */
343 
344             /* With flash wear leveling, FileX should tell wear leveling when sectors
345                are no longer in use.  */
346             media_ptr -> fx_media_driver_free_sector_update =  FX_TRUE;
347 
348             /* Open the NOR flash simulation.  */
349             status =  lx_nor_flash_open(&nor_flash, "sim nor flash", _lx_nor_flash_simulator_initialize);
350 
351             /* Determine if the flash open was successful.  */
352             if (status != LX_SUCCESS)
353             {
354 
355                 /* Return an I/O error to FileX.  */
356                 media_ptr -> fx_media_driver_status =  FX_IO_ERROR;
357 
358                 return;
359             }
360 
361             /* Successful driver request.  */
362             media_ptr -> fx_media_driver_status =  FX_SUCCESS;
363             break;
364         }
365 
366         case FX_DRIVER_UNINIT:
367         {
368 
369             /* There is nothing to do in this case for the RAM driver.  For actual
370                devices some shutdown processing may be necessary.  */
371 
372             /* Close the NOR flash simulation.  */
373             status =  lx_nor_flash_close(&nor_flash);
374 
375             /* Determine if the flash close was successful.  */
376             if (status != LX_SUCCESS)
377             {
378 
379                 /* Return an I/O error to FileX.  */
380                 media_ptr -> fx_media_driver_status =  FX_IO_ERROR;
381 
382                 return;
383             }
384 
385             /* Successful driver request.  */
386             media_ptr -> fx_media_driver_status =  FX_SUCCESS;
387             break;
388         }
389 
390         case FX_DRIVER_BOOT_READ:
391         {
392 
393             /* Read the boot record and return to the caller.  */
394 
395             /* Setup the destination buffer.  */
396             destination_buffer =  (UCHAR *) media_ptr -> fx_media_driver_buffer;
397 
398             /* Read boot sector from NOR flash.  */
399             status =  lx_nor_flash_sector_read(&nor_flash, 0, destination_buffer);
400 
401             /* For NOR driver, determine if the boot record is valid.  */
402             if ((destination_buffer[0] != (UCHAR) 0xEB) ||
403                 (destination_buffer[1] != (UCHAR) 0x34) ||
404                 (destination_buffer[2] != (UCHAR) 0x90))
405             {
406 
407                 /* Invalid boot record, return an error!  */
408                 media_ptr -> fx_media_driver_status =  FX_MEDIA_INVALID;
409                 return;
410             }
411 
412             /* Determine if the boot read was successful.  */
413             if (status != LX_SUCCESS)
414             {
415 
416                 /* Return an I/O error to FileX.  */
417                 media_ptr -> fx_media_driver_status =  FX_IO_ERROR;
418 
419                 return;
420             }
421 
422             /* Successful driver request.  */
423             media_ptr -> fx_media_driver_status =  FX_SUCCESS;
424             break;
425         }
426 
427         case FX_DRIVER_BOOT_WRITE:
428         {
429 
430             /* Make sure the media bytes per sector equals to the LevelX logical sector size.  */
431             if (media_ptr -> fx_media_bytes_per_sector != (LX_NOR_SECTOR_SIZE) * sizeof(ULONG))
432             {
433 
434                 /* Sector size mismatch, return error.  */
435                 media_ptr -> fx_media_driver_status =  FX_IO_ERROR;
436                 break;
437             }
438 
439             /* Write the boot record and return to the caller.  */
440 
441             /* Setup the source buffer.  */
442             source_buffer =       (UCHAR *) media_ptr -> fx_media_driver_buffer;
443 
444             /* Write boot sector to NOR flash.  */
445             status =  lx_nor_flash_sector_write(&nor_flash, 0, source_buffer);
446 
447             /* Determine if the boot write was successful.  */
448             if (status != LX_SUCCESS)
449             {
450 
451                 /* Return an I/O error to FileX.  */
452                 media_ptr -> fx_media_driver_status =  FX_IO_ERROR;
453 
454                 return;
455             }
456 
457             /* Successful driver request.  */
458             media_ptr -> fx_media_driver_status =  FX_SUCCESS;
459             break ;
460         }
461 
462         default:
463         {
464 
465             /* Invalid driver request.  */
466             media_ptr -> fx_media_driver_status =  FX_IO_ERROR;
467             break;
468         }
469     }
470 }
471 
472