GCC Code Coverage Report
Directory: ./ Exec Total Coverage
File: fx_nor_flash_simulator_driver.c Lines: 0 84 0.0 %
Date: 2026-03-06 18:45:40 Branches: 0 38 0.0 %

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