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