yaffsfs.c: Fix NULL dereference in yaffs_unmount2_reldev()
[yaffs2.git] / rtems / rtems-y-test / common / yaffs-rtems-flashsim.c
1 /*
2  * Modified verion of yramsim.c.
3  */
4 #include "yaffs-rtems-flashsim.h"
5
6 #include <string.h>
7 #include "../../yaffs_guts.h"
8
9
10
11 #define N_RAM_SIM_DEVS  1
12
13 #define DATA_SIZE       2048
14 #define SPARE_SIZE      64
15 #define PAGE_SIZE       (DATA_SIZE + SPARE_SIZE)
16 #define PAGES_PER_BLOCK 64
17
18
19 #if 0
20 #define dout printf
21 #else
22 #define dout(...) do { } while(0)
23 #endif
24
25
26
27 uint32_t stats_reads;
28 uint32_t stats_writes;
29 uint32_t stats_erases;
30
31 typedef struct {
32         unsigned char page[PAGES_PER_BLOCK][PAGE_SIZE];
33         unsigned blockOk;
34 } Block;
35
36 typedef struct {
37         Block **blockList;
38         int nBlocks;
39 } SimData;
40
41
42 SimData *simDevs[N_RAM_SIM_DEVS];
43
44 static SimData *DevToSim(struct yaffs_dev *dev)
45 {
46         return (SimData*)(dev->driver_context);
47 }
48
49
50 static void CheckInitialised(void)
51 {
52
53 }
54
55 static int yramsim_erase_internal(SimData *sim, unsigned blockId,int force)
56 {
57         if(blockId < 0 || blockId >= sim->nBlocks){
58                 return 0;
59         }
60
61         if(!sim->blockList[blockId]){
62                 return 0;
63         }
64
65         if(!force && !sim->blockList[blockId]->blockOk){
66                 return 0;
67         }
68
69         memset(sim->blockList[blockId],0xff,sizeof(Block));
70         sim->blockList[blockId]->blockOk = 1;
71
72         return 1;
73 }
74
75
76
77
78 static int yramsim_initialise(struct yaffs_dev *dev)
79 {
80         SimData *sim = DevToSim(dev);
81         Block **blockList = sim->blockList;
82         return blockList != NULL;
83 }
84
85
86 static int yramsim_deinitialise(struct yaffs_dev *dev)
87 {
88         return 1;
89 }
90
91 static int yramsim_rd_chunk (struct yaffs_dev *dev, int pageId,
92                                           u8 *data, int dataLength,
93                                           u8 *spare, int spareLength,
94                                           enum yaffs_ecc_result *ecc_result)
95 {
96         SimData *sim = DevToSim(dev);
97         Block **blockList = sim->blockList;
98
99         unsigned blockId = pageId / PAGES_PER_BLOCK;
100         unsigned pageOffset = pageId % PAGES_PER_BLOCK;
101         unsigned char * d;
102         unsigned char *s;
103
104         stats_reads++;
105
106         if(blockId >= sim->nBlocks ||
107            pageOffset >= PAGES_PER_BLOCK ||
108            dataLength >DATA_SIZE ||
109            spareLength > SPARE_SIZE ||
110            !blockList[blockId]->blockOk){
111                    return YAFFS_FAIL;
112         }
113
114         d = blockList[blockId]->page[pageOffset];
115         s = d + DATA_SIZE;
116
117         if(data)
118                 memcpy(data,d,dataLength);
119
120         if(spare)
121                 memcpy(spare,s,spareLength);
122
123         if (ecc_result)
124                 *ecc_result  = YAFFS_ECC_RESULT_NO_ERROR;
125
126         return YAFFS_OK;
127 }
128
129 static int yramsim_wr_chunk (struct yaffs_dev *dev, int pageId,
130                                            const u8 *data, int dataLength,
131                                            const u8 *spare, int spareLength)
132 {
133         SimData *sim = DevToSim(dev);
134         Block **blockList = sim->blockList;
135
136         unsigned blockId = pageId / PAGES_PER_BLOCK;
137         unsigned pageOffset = pageId % PAGES_PER_BLOCK;
138         unsigned char * d;
139         unsigned char *s;
140
141         dout("wr_chunk\n");
142
143         stats_writes++;
144
145         if(blockId >= sim->nBlocks ||
146            pageOffset >= PAGES_PER_BLOCK ||
147            dataLength >DATA_SIZE ||
148            spareLength > SPARE_SIZE ||
149            !blockList[blockId]->blockOk){
150                    return YAFFS_FAIL;
151         }
152
153         d = blockList[blockId]->page[pageOffset];
154         s = d + DATA_SIZE;
155
156         if(data)
157                 memcpy(d,data,dataLength);
158
159         if(spare)
160                 memcpy(s,spare,spareLength);
161
162         return YAFFS_OK;
163 }
164
165
166 static int yramsim_erase(struct yaffs_dev *dev, int blockId)
167 {
168         SimData *sim = DevToSim(dev);
169
170         stats_erases++;
171
172         CheckInitialised();
173         return yramsim_erase_internal(sim,blockId,0);
174 }
175
176 static int yramsim_check_block_bad(struct yaffs_dev *dev, int blockId)
177 {
178         SimData *sim = DevToSim(dev);
179         Block **blockList = sim->blockList;
180         if(blockId >= sim->nBlocks){
181                 return YAFFS_FAIL;
182         }
183
184         return blockList[blockId]->blockOk ? YAFFS_OK : YAFFS_FAIL;
185 }
186
187 static int yramsim_mark_block_bad(struct yaffs_dev *dev, int blockId)
188 {
189         SimData *sim = DevToSim(dev);
190         Block **blockList = sim->blockList;
191         if(blockId >= sim->nBlocks){
192                 return YAFFS_FAIL;
193         }
194
195         blockList[blockId]->blockOk = 0;
196
197         return YAFFS_OK;
198 }
199
200
201 static SimData *yramsim_alloc_sim_data(u32 devId, u32 nBlocks)
202 {
203         int ok = 1;
204
205         Block **blockList;
206         SimData *sim;
207         Block *b;
208         u32 i;
209
210         if(devId >= N_RAM_SIM_DEVS)
211                 return NULL;
212
213         sim = simDevs[devId];
214
215         if(sim)
216                 return sim;
217
218         sim = malloc(sizeof (SimData));
219         if(!sim)
220                 return NULL;
221
222         simDevs[devId] = sim;
223
224         blockList = malloc(nBlocks * sizeof(Block *));
225
226         sim->blockList = blockList;
227         sim->nBlocks = nBlocks;
228         if(!blockList){
229                 free(sim);
230                 return NULL;
231         }
232
233         for(i = 0; i < nBlocks; i++)
234                 blockList[i] = NULL;
235
236         for(i = 0; i < nBlocks && ok; i++){
237                 b=  malloc(sizeof(Block));
238                 if(b){
239                         blockList[i] = b;
240                         yramsim_erase_internal(sim,i,1);
241                 }
242                 else
243                         ok = 0;
244         }
245
246         if(!ok){
247                 for(i = 0; i < nBlocks; i++)
248                         if(blockList[i]){
249                                 free(blockList[i]);
250                                 blockList[i] = NULL;
251                         }
252                 free(blockList);
253                 blockList = NULL;
254                 free(sim);
255                 sim = NULL;
256         }
257
258         return sim;
259 }
260
261
262 struct yaffs_dev *yramsim_CreateRamSim(const YCHAR *name,
263                                 u32 devId, u32 nBlocks,
264                                 u32 start_block, u32 end_block)
265 {
266         SimData *sim;
267         struct yaffs_dev *dev;
268         struct yaffs_param *p;
269         struct yaffs_driver *d;
270
271         sim = yramsim_alloc_sim_data(devId, nBlocks);
272
273         dev = malloc(sizeof(*dev));
274
275         if(!sim || !dev){
276                 free(sim);
277                 free(dev);
278                 printf("Flash Sim creation failed. sim = %p, dev = %p\n",
279                                 sim, dev);
280                 return NULL;
281         }
282
283         memset(dev, 0, sizeof(*dev));
284
285         if(start_block >= sim->nBlocks)
286                 start_block = 0;
287         if(end_block == 0 || end_block >= sim->nBlocks)
288                 end_block = sim->nBlocks - 1;
289
290         p = &dev->param;
291         p->name = strdup(name);
292         p->start_block = start_block;
293         p->end_block = end_block;
294         p->total_bytes_per_chunk = DATA_SIZE;
295         p->spare_bytes_per_chunk= SPARE_SIZE;
296         p->chunks_per_block = PAGES_PER_BLOCK;
297         p->n_reserved_blocks = 2;
298         p->use_nand_ecc = 1;
299         p->inband_tags = 0;
300         p->is_yaffs2 = 1;
301
302         d= &dev->drv;
303         d->drv_initialise_fn = yramsim_initialise;
304         d->drv_deinitialise_fn = yramsim_deinitialise;
305         d->drv_read_chunk_fn = yramsim_rd_chunk;
306         d->drv_write_chunk_fn = yramsim_wr_chunk;
307         d->drv_erase_fn = yramsim_erase;
308         d->drv_check_bad_fn = yramsim_check_block_bad;
309         d->drv_mark_bad_fn = yramsim_mark_block_bad;
310
311         dev->driver_context= (void *)sim;
312
313         printf("Created simulated flash device %p\n", dev);
314         return dev;
315 }
316
317 struct yaffs_dev *yaffs_rtems_flashsim_setup(void)
318 {
319         return yramsim_CreateRamSim("ramsim",
320                                 0, 100,
321                                 0, 99);
322 }
323
324
325 void yaffs_rtems_flashsim_dump_status(void)
326 {
327         printf("\nFlashsim stats\n");
328         printf("reads.....%d\n", stats_reads);
329         printf("writes....%d\n", stats_writes);
330         printf("erases....%d\n", stats_erases);
331 }