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