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