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.
13 * Nand simulator modelled on a Samsung K9K2G08U0A 8-bit
15 * Need to implement basic commands first:
19 * Random read (ie set read position within current page)
24 #include "nandstore_file.h"
25 #include "nand_store.h"
33 extern int random_seed;
34 extern int simulate_power_failure;
35 static int remaining_ops;
36 static int nops_so_far;
38 struct nandstore_file_private {
39 char backing_file[500];
41 unsigned char * buffer;
45 static void maybe_power_fail(unsigned int nand_chunk, int fail_point)
51 if(simulate_power_failure &&
53 printf("Simulated power failure after %d operations\n",nops_so_far);
54 printf(" power failed on nand_chunk %d, at fail point %d\n",
55 nand_chunk, fail_point);
60 static void power_fail_init(void)
62 remaining_ops = (rand() % 1000) * 5;
65 static int nandstore_file_store(struct nand_store *this, int page,
66 const unsigned char * buffer)
68 struct nandstore_file_private *nsfp =
69 (struct nandstore_file_private *)this->private_data;
70 int pos = nsfp->buff_size * page;
73 maybe_power_fail(page, __LINE__);
75 lseek(nsfp->handle, pos, SEEK_SET);
76 read(nsfp->handle, nsfp->buffer, nsfp->buff_size);
77 for(i = 0; i < nsfp->buff_size; i++)
78 nsfp->buffer[i] &= buffer[i];
79 lseek(nsfp->handle, pos, SEEK_SET);
80 write(nsfp->handle, nsfp->buffer, nsfp->buff_size);
82 maybe_power_fail(page, __LINE__);
87 static int nandstore_file_retrieve(struct nand_store *this, int page,
88 unsigned char * buffer)
90 struct nandstore_file_private *nsfp =
91 (struct nandstore_file_private *)this->private_data;
93 lseek(nsfp->handle, nsfp->buff_size * page, SEEK_SET);
94 read(nsfp->handle, buffer, nsfp->buff_size);
97 static int nandstore_file_erase(struct nand_store *this, int page)
99 int block = page / this->pages_per_block;
100 struct nandstore_file_private *nsfp =
101 (struct nandstore_file_private *)this->private_data;
104 maybe_power_fail(page, __LINE__);
107 block * nsfp->buff_size * this->pages_per_block, SEEK_SET);
108 memset(nsfp->buffer, 0xff, nsfp->buff_size);
109 for(i = 0; i < this->pages_per_block; i++)
110 write(nsfp->handle, nsfp->buffer, nsfp->buff_size);
114 static int nandstore_file_shutdown(struct nand_store *this)
116 struct nandstore_file_private *nsfp =
117 (struct nandstore_file_private *)this->private_data;
124 nandstore_file_init(const char *fname,
127 int data_bytes_per_page,
128 int spare_bytes_per_page)
133 struct nand_store *ns;
134 struct nandstore_file_private *nsfp;
135 unsigned char *buffer;
136 int buff_size = data_bytes_per_page + spare_bytes_per_page;
138 ns = malloc(sizeof(struct nand_store));
139 nsfp = malloc(sizeof(struct nandstore_file_private));
140 buffer = malloc(buff_size);
143 if (!ns || !nsfp || !buffer) {
150 memset(ns, 0, sizeof(*ns));
151 memset(nsfp, 0, sizeof(*nsfp));
152 nsfp->buffer = buffer;
153 nsfp->buff_size = buff_size;
154 ns->private_data = nsfp;
156 ns->store = nandstore_file_store;
157 ns->retrieve = nandstore_file_retrieve;
158 ns->erase = nandstore_file_erase;
159 ns->shutdown = nandstore_file_shutdown;
162 ns->pages_per_block = pages_per_block;
163 ns->data_bytes_per_page = data_bytes_per_page;
164 ns->spare_bytes_per_page = spare_bytes_per_page;
166 strncpy(nsfp->backing_file, fname, sizeof(nsfp->backing_file));
168 nsfp->handle = open(nsfp->backing_file, O_RDWR | O_CREAT, 0666);
169 if(nsfp->handle >=0){
170 fsize = lseek(nsfp->handle,0,SEEK_END);
171 nbytes = ns->blocks * ns->pages_per_block *
172 (ns->data_bytes_per_page + ns->spare_bytes_per_page);
173 if (fsize != nbytes) {
174 printf("Initialising backing file.\n");
175 ftruncate(nsfp->handle,0);
176 for(i = 0; i < ns->blocks; i++)
177 nandstore_file_erase(ns,
178 i * ns->pages_per_block);