2 * YAFFS: Yet Another Flash File System. A NAND-flash specific file system.
4 * Copyright (C) 2002-2018 Aleph One Ltd.
6 * Created by Charles Manning <charles@aleph1.co.uk>
8 * This program is free software; you can redistribute it and/or modify
9 * it under the terms of the GNU General Public License version 2 as
10 * published by the Free Software Foundation.
14 * NAND Simulator for testing YAFFS
18 #include "yaffs_flexible_file_sim.h"
20 #include "yaffs_guts.h"
24 #include <sys/types.h>
32 uint32_t chunks_per_block;
35 uint32_t total_chunk_size;
36 uint32_t total_bytes_per_block;
40 static struct sim_data *dev_to_sim(struct yaffs_dev *dev)
42 return (struct sim_data *)(dev->driver_context);
46 static int yflex_erase_internal(struct sim_data *sim, uint32_t block_id)
50 pos = sim->total_bytes_per_block * block_id;
51 memset(sim->buffer, 0xff, sim->total_bytes_per_block);
53 lseek(sim->handle, pos, SEEK_SET);
54 write(sim->handle, sim->buffer, sim->total_bytes_per_block);
60 static int yflex_read_internal(struct sim_data *sim,
64 int page_pos = page_id * sim->total_chunk_size;
66 lseek(sim->handle, page_pos, SEEK_SET);
67 read(sim->handle, buffer, sim->total_chunk_size);
75 static int yflex_initialise(struct yaffs_dev *dev)
83 static int yflex_deinitialise(struct yaffs_dev *dev)
89 static int yflex_rd_chunk (struct yaffs_dev *dev, int page_id,
90 u8 *data, int data_length,
91 u8 *spare, int spare_length,
92 enum yaffs_ecc_result *ecc_result)
94 struct sim_data *sim = dev_to_sim(dev);
97 page_start = page_id * sim->total_chunk_size;
100 lseek(sim->handle, page_start, SEEK_SET);
101 read(sim->handle, data,data_length);
105 lseek(sim->handle, page_start + sim->chunk_size, SEEK_SET);
106 read(sim->handle, spare,spare_length);
110 *ecc_result = YAFFS_ECC_RESULT_NO_ERROR;
115 static int yflex_wr_chunk (struct yaffs_dev *dev, int page_id,
116 const u8 *data, int data_length,
117 const u8 *spare, int spare_length)
119 struct sim_data *sim = dev_to_sim(dev);
122 page_start = page_id * sim->total_chunk_size;
125 lseek(sim->handle, page_start, SEEK_SET);
126 write(sim->handle, data,data_length);
130 lseek(sim->handle, page_start + sim->chunk_size, SEEK_SET);
131 write(sim->handle, spare, spare_length);
138 static int yflex_erase(struct yaffs_dev *dev, int block_id)
140 struct sim_data *sim = dev_to_sim(dev);
142 return yflex_erase_internal(sim, block_id);
145 static int yflex_check_block_bad(struct yaffs_dev *dev, int block_id)
153 static int yflex_mark_block_bad(struct yaffs_dev *dev, int block_id)
161 static int yflex_sim_init(struct sim_data *sim)
167 sim->total_chunk_size = sim->chunk_size + sim->spare_size;
168 sim->total_bytes_per_block = sim->total_chunk_size * sim->chunks_per_block;
170 sim->buffer = malloc(sim->total_bytes_per_block);
172 h = open(sim->file_name, O_RDWR);
174 fsize = lseek(h, 0, SEEK_END);
175 lseek(h, 0, SEEK_SET);
178 if (fsize != sim->total_bytes_per_block * sim->n_blocks) {
179 /* Need to create the file. */
181 unlink(sim->file_name);
182 h = open(sim->file_name, O_RDWR | O_CREAT | O_TRUNC, 0666);
185 for (i = 0; i < sim->n_blocks; i++)
186 yflex_erase_internal(sim, i);
195 struct yaffs_dev *yaffs_flexible_file_sim_create(
197 const char *sim_file_name,
199 uint32_t start_block, uint32_t end_block,
200 uint32_t chunks_per_block,
201 uint32_t bytes_per_chunk,
202 uint32_t bytes_per_spare)
204 struct sim_data *sim;
205 struct yaffs_dev *dev;
206 struct yaffs_param *p;
207 struct yaffs_driver *d;
209 sim = malloc(sizeof(*sim));
210 dev = malloc(sizeof(*dev));
217 memset(sim, 0, sizeof(*sim));
218 memset(dev, 0, sizeof(*dev));
221 sim->file_name = strdup(sim_file_name);
222 sim->chunks_per_block = chunks_per_block;
223 sim->chunk_size = bytes_per_chunk;
224 sim->spare_size = bytes_per_spare;
225 sim->n_blocks = n_blocks;
227 dev->driver_context= (void *)sim;
233 if(start_block >= sim->n_blocks)
235 if(end_block == 0 || end_block >= sim->n_blocks)
236 end_block = sim->n_blocks - 1;
239 p->name = strdup(name);
240 p->start_block = start_block;
241 p->end_block = end_block;
242 p->total_bytes_per_chunk = bytes_per_chunk;
243 p->spare_bytes_per_chunk = bytes_per_spare;
244 p->chunks_per_block = chunks_per_block;
245 p->n_reserved_blocks = 2;
252 d->drv_initialise_fn = yflex_initialise;
253 d->drv_deinitialise_fn = yflex_deinitialise;
254 d->drv_read_chunk_fn = yflex_rd_chunk;
255 d->drv_write_chunk_fn = yflex_wr_chunk;
256 d->drv_erase_fn = yflex_erase;
257 d->drv_check_bad_fn = yflex_check_block_bad;
258 d->drv_mark_bad_fn = yflex_mark_block_bad;
260 yaffs_add_device(dev);