GCC Code Coverage Report


Directory: common/src/
Coverage: low: ≥ 0% medium: ≥ 75.0% high: ≥ 90.0%
Coverage Exec / Excl / Total
Lines: 0.0% 0 / 0 / 84
Functions: 0.0% 0 / 0 / 1
Branches: 0.0% 0 / 0 / 38

fx_nor_flash_simulator_driver.c
Line Branch Exec Source
1 /***************************************************************************
2 * Copyright (c) 2024 Microsoft Corporation
3 * Copyright (c) 2026-present Eclipse ThreadX contributors
4 *
5 * This program and the accompanying materials are made available under the
6 * terms of the MIT License which is available at
7 * https://opensource.org/licenses/MIT.
8 *
9 * SPDX-License-Identifier: MIT
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 /**************************************************************************/
114 ✗ VOID _fx_nor_flash_simulator_driver(FX_MEDIA *media_ptr)
115 {
116
117 UCHAR *source_buffer;
118 UCHAR *destination_buffer;
119 ULONG logical_sector;
120 ULONG i;
121 UINT status;
122
123
124 /* There are several useful/important pieces of information contained in the media
125 structure, some of which are supplied by FileX and others are for the driver to
126 setup. The following is a summary of the necessary FX_MEDIA structure members:
127
128 FX_MEDIA Member Meaning
129
130 fx_media_driver_request FileX request type. Valid requests from FileX are
131 as follows:
132
133 FX_DRIVER_READ
134 FX_DRIVER_WRITE
135 FX_DRIVER_FLUSH
136 FX_DRIVER_ABORT
137 FX_DRIVER_INIT
138 FX_DRIVER_BOOT_READ
139 FX_DRIVER_RELEASE_SECTORS
140 FX_DRIVER_BOOT_WRITE
141 FX_DRIVER_UNINIT
142
143 fx_media_driver_status This value is RETURNED by the driver. If the
144 operation is successful, this field should be
145 set to FX_SUCCESS for before returning. Otherwise,
146 if an error occurred, this field should be set
147 to FX_IO_ERROR.
148
149 fx_media_driver_buffer Pointer to buffer to read or write sector data.
150 This is supplied by FileX.
151
152 fx_media_driver_logical_sector Logical sector FileX is requesting.
153
154 fx_media_driver_sectors Number of sectors FileX is requesting.
155
156
157 The following is a summary of the optional FX_MEDIA structure members:
158
159 FX_MEDIA Member Meaning
160
161 fx_media_driver_info Pointer to any additional information or memory.
162 This is optional for the driver use and is setup
163 from the fx_media_open call. The RAM disk uses
164 this pointer for the RAM disk memory itself.
165
166 fx_media_driver_write_protect The DRIVER sets this to FX_TRUE when media is write
167 protected. This is typically done in initialization,
168 but can be done anytime.
169
170 fx_media_driver_free_sector_update The DRIVER sets this to FX_TRUE when it needs to
171 know when clusters are released. This is important
172 for FLASH wear-leveling drivers.
173
174 fx_media_driver_system_write FileX sets this flag to FX_TRUE if the sector being
175 written is a system sector, e.g., a boot, FAT, or
176 directory sector. The driver may choose to use this
177 to initiate error recovery logic for greater fault
178 tolerance.
179
180 fx_media_driver_data_sector_read FileX sets this flag to FX_TRUE if the sector(s) being
181 read are file data sectors, i.e., NOT system sectors.
182
183 fx_media_driver_sector_type FileX sets this variable to the specific type of
184 sector being read or written. The following sector
185 types are identified:
186
187 FX_UNKNOWN_SECTOR
188 FX_BOOT_SECTOR
189 FX_FAT_SECTOR
190 FX_DIRECTORY_SECTOR
191 FX_DATA_SECTOR
192 */
193
194 /* Process the driver request specified in the media control block. */
195 ✗ switch(media_ptr -> fx_media_driver_request)
196 {
197
198 ✗ case FX_DRIVER_READ:
199 {
200
201 /* Setup the destination buffer and logical sector. */
202 ✗ logical_sector = media_ptr -> fx_media_driver_logical_sector;
203 ✗ destination_buffer = (UCHAR *) media_ptr -> fx_media_driver_buffer;
204
205 /* Loop to read sectors from flash. */
206 ✗ for (i = 0; i < media_ptr -> fx_media_driver_sectors; i++)
207 {
208
209 /* Read a sector from NOR flash. */
210 ✗ status = lx_nor_flash_sector_read(&nor_flash, logical_sector, destination_buffer);
211
212 /* Determine if the read was successful. */
213 ✗ if (status != LX_SUCCESS)
214 {
215
216 /* Return an I/O error to FileX. */
217 ✗ media_ptr -> fx_media_driver_status = FX_IO_ERROR;
218
219 ✗ return;
220 }
221
222 /* Move to the next entries. */
223 ✗ logical_sector++;
224 ✗ destination_buffer = destination_buffer + media_ptr -> fx_media_bytes_per_sector;
225 }
226
227 /* Successful driver request. */
228 ✗ media_ptr -> fx_media_driver_status = FX_SUCCESS;
229 ✗ break;
230 }
231
232 ✗ case FX_DRIVER_WRITE:
233 {
234
235 /* Setup the source buffer and logical sector. */
236 ✗ logical_sector = media_ptr -> fx_media_driver_logical_sector;
237 ✗ source_buffer = (UCHAR *) media_ptr -> fx_media_driver_buffer;
238
239 /* Loop to write sectors to flash. */
240 ✗ for (i = 0; i < media_ptr -> fx_media_driver_sectors; i++)
241 {
242
243 /* Write a sector to NOR flash. */
244 ✗ status = lx_nor_flash_sector_write(&nor_flash, logical_sector, source_buffer);
245
246 /* Determine if the write was successful. */
247 ✗ if (status != LX_SUCCESS)
248 {
249
250 /* Return an I/O error to FileX. */
251 ✗ media_ptr -> fx_media_driver_status = FX_IO_ERROR;
252
253 ✗ return;
254 }
255
256 /* Move to the next entries. */
257 ✗ logical_sector++;
258 ✗ source_buffer = source_buffer + media_ptr -> fx_media_bytes_per_sector;
259 }
260
261 /* Successful driver request. */
262 ✗ media_ptr -> fx_media_driver_status = FX_SUCCESS;
263 ✗ break;
264 }
265
266 ✗ case FX_DRIVER_RELEASE_SECTORS:
267 {
268
269 /* Setup the logical sector. */
270 ✗ logical_sector = media_ptr -> fx_media_driver_logical_sector;
271
272 /* Release sectors. */
273 ✗ for (i = 0; i < media_ptr -> fx_media_driver_sectors; i++)
274 {
275
276 /* Release NOR flash sector. */
277 ✗ status = lx_nor_flash_sector_release(&nor_flash, logical_sector);
278
279 /* Determine if the sector release was successful. */
280 ✗ if (status != LX_SUCCESS)
281 {
282
283 /* Return an I/O error to FileX. */
284 ✗ media_ptr -> fx_media_driver_status = FX_IO_ERROR;
285
286 ✗ return;
287 }
288
289 /* Move to the next entries. */
290 ✗ logical_sector++;
291 }
292
293 /* Successful driver request. */
294 ✗ media_ptr -> fx_media_driver_status = FX_SUCCESS;
295 ✗ break;
296 }
297
298 ✗ case FX_DRIVER_FLUSH:
299 {
300
301 /* Return driver success. */
302 ✗ media_ptr -> fx_media_driver_status = FX_SUCCESS;
303 ✗ break;
304 }
305
306 ✗ case FX_DRIVER_ABORT:
307 {
308
309 /* Return driver success. */
310 ✗ media_ptr -> fx_media_driver_status = FX_SUCCESS;
311 ✗ break;
312 }
313
314 ✗ case FX_DRIVER_INIT:
315 {
316
317 /* FLASH drivers are responsible for setting several fields in the
318 media structure, as follows:
319
320 media_ptr -> fx_media_driver_free_sector_update
321 media_ptr -> fx_media_driver_write_protect
322
323 The fx_media_driver_free_sector_update flag is used to instruct
324 FileX to inform the driver whenever sectors are not being used.
325 This is especially useful for FLASH managers so they don't have
326 maintain mapping for sectors no longer in use.
327
328 The fx_media_driver_write_protect flag can be set anytime by the
329 driver to indicate the media is not writable. Write attempts made
330 when this flag is set are returned as errors. */
331
332 /* Perform basic initialization here... since the boot record is going
333 to be read subsequently and again for volume name requests. */
334
335 /* With flash wear leveling, FileX should tell wear leveling when sectors
336 are no longer in use. */
337 ✗ media_ptr -> fx_media_driver_free_sector_update = FX_TRUE;
338
339 /* Open the NOR flash simulation. */
340 ✗ status = lx_nor_flash_open(&nor_flash, "sim nor flash", _lx_nor_flash_simulator_initialize);
341
342 /* Determine if the flash open was successful. */
343 ✗ if (status != LX_SUCCESS)
344 {
345
346 /* Return an I/O error to FileX. */
347 ✗ media_ptr -> fx_media_driver_status = FX_IO_ERROR;
348
349 ✗ return;
350 }
351
352 /* Successful driver request. */
353 ✗ media_ptr -> fx_media_driver_status = FX_SUCCESS;
354 ✗ break;
355 }
356
357 ✗ case FX_DRIVER_UNINIT:
358 {
359
360 /* There is nothing to do in this case for the RAM driver. For actual
361 devices some shutdown processing may be necessary. */
362
363 /* Close the NOR flash simulation. */
364 ✗ status = lx_nor_flash_close(&nor_flash);
365
366 /* Determine if the flash close was successful. */
367 ✗ if (status != LX_SUCCESS)
368 {
369
370 /* Return an I/O error to FileX. */
371 ✗ media_ptr -> fx_media_driver_status = FX_IO_ERROR;
372
373 ✗ return;
374 }
375
376 /* Successful driver request. */
377 ✗ media_ptr -> fx_media_driver_status = FX_SUCCESS;
378 ✗ break;
379 }
380
381 ✗ case FX_DRIVER_BOOT_READ:
382 {
383
384 /* Read the boot record and return to the caller. */
385
386 /* Setup the destination buffer. */
387 ✗ destination_buffer = (UCHAR *) media_ptr -> fx_media_driver_buffer;
388
389 /* Read boot sector from NOR flash. */
390 ✗ status = lx_nor_flash_sector_read(&nor_flash, 0, destination_buffer);
391
392 /* For NOR driver, determine if the boot record is valid. */
393 ✗ if ((destination_buffer[0] != (UCHAR) 0xEB) ||
394 ✗ (destination_buffer[1] != (UCHAR) 0x34) ||
395 ✗ (destination_buffer[2] != (UCHAR) 0x90))
396 {
397
398 /* Invalid boot record, return an error! */
399 ✗ media_ptr -> fx_media_driver_status = FX_MEDIA_INVALID;
400 ✗ return;
401 }
402
403 /* Determine if the boot read was successful. */
404 ✗ if (status != LX_SUCCESS)
405 {
406
407 /* Return an I/O error to FileX. */
408 ✗ media_ptr -> fx_media_driver_status = FX_IO_ERROR;
409
410 ✗ return;
411 }
412
413 /* Successful driver request. */
414 ✗ media_ptr -> fx_media_driver_status = FX_SUCCESS;
415 ✗ break;
416 }
417
418 ✗ case FX_DRIVER_BOOT_WRITE:
419 {
420
421 /* Make sure the media bytes per sector equals to the LevelX logical sector size. */
422 ✗ if (media_ptr -> fx_media_bytes_per_sector != (LX_NOR_SECTOR_SIZE) * sizeof(ULONG))
423 {
424
425 /* Sector size mismatch, return error. */
426 ✗ media_ptr -> fx_media_driver_status = FX_IO_ERROR;
427 ✗ break;
428 }
429
430 /* Write the boot record and return to the caller. */
431
432 /* Setup the source buffer. */
433 ✗ source_buffer = (UCHAR *) media_ptr -> fx_media_driver_buffer;
434
435 /* Write boot sector to NOR flash. */
436 ✗ status = lx_nor_flash_sector_write(&nor_flash, 0, source_buffer);
437
438 /* Determine if the boot write was successful. */
439 ✗ if (status != LX_SUCCESS)
440 {
441
442 /* Return an I/O error to FileX. */
443 ✗ media_ptr -> fx_media_driver_status = FX_IO_ERROR;
444
445 ✗ return;
446 }
447
448 /* Successful driver request. */
449 ✗ media_ptr -> fx_media_driver_status = FX_SUCCESS;
450 ✗ break ;
451 }
452
453 ✗ default:
454 {
455
456 /* Invalid driver request. */
457 ✗ media_ptr -> fx_media_driver_status = FX_IO_ERROR;
458 ✗ break;
459 }
460 }
461 }
462
463