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