xref: /nrf52832-nimble/rt-thread/components/dfs/filesystems/uffs/src/emu/uffs_fileem_share.c (revision 104654410c56c573564690304ae786df310c91fc)
1 /*
2   This file is part of UFFS, the Ultra-low-cost Flash File System.
3 
4   Copyright (C) 2005-2009 Ricky Zheng <[email protected]>
5 
6   UFFS is free software; you can redistribute it and/or modify it under
7   the GNU Library General Public License as published by the Free Software
8   Foundation; either version 2 of the License, or (at your option) any
9   later version.
10 
11   UFFS is distributed in the hope that it will be useful, but WITHOUT
12   ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
13   FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
14   or GNU Library General Public License, as applicable, for more details.
15 
16   You should have received a copy of the GNU General Public License
17   and GNU Library General Public License along with UFFS; if not, write
18   to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
19   Boston, MA  02110-1301, USA.
20 
21   As a special exception, if other files instantiate templates or use
22   macros or inline functions from this file, or you compile this file
23   and link it with other works to produce a work based on this file,
24   this file does not by itself cause the resulting work to be covered
25   by the GNU General Public License. However the source code for this
26   file must still be made available in accordance with section (3) of
27   the GNU General Public License v2.
28 
29   This exception does not invalidate any other reasons why a work based
30   on this file might be covered by the GNU General Public License.
31 */
32 
33 /**
34  * \file uffs_fileem_share.c
35  * \brief emulate uffs file system, shared functions
36  * \author Ricky Zheng, created Nov, 2010
37  */
38 
39 
40 #include <sys/types.h>
41 #include <string.h>
42 #include <stdio.h>
43 #include <stdlib.h>
44 #include "uffs_config.h"
45 #include "uffs/uffs_device.h"
46 #include "uffs_fileem.h"
47 
48 #define PFX "femu: "
49 
50 /****************************************************************/
51 /*           Shared flash driver functions:                     */
52 /*                                                              */
53 /*   femu_InitFlash(), femu_ReleaseFlash(), femu_EraseBlock()   */
54 /*                                                              */
55 /****************************************************************/
56 
57 static u8 g_page_buf[UFFS_MAX_PAGE_SIZE + UFFS_MAX_SPARE_SIZE];
58 
59 /*
60  * Create emulator disk, initialise monitors, inject manufacture bad blocks, etc.
61  *
62  */
femu_InitFlash(uffs_Device * dev)63 int femu_InitFlash(uffs_Device *dev)
64 {
65 	int i;
66 	int fSize;
67 	int written;
68 	u8 * p = g_page_buf;
69 	uffs_FileEmu *emu;
70 
71 	struct uffs_StorageAttrSt *attr = dev->attr;
72 
73 	int full_page_size = attr->page_data_size + attr->spare_size;
74 	int total_pages = attr->total_blocks * attr->pages_per_block;
75 
76 	emu = (uffs_FileEmu *)(dev->attr->_private);
77 
78 	if (emu->initCount > 0) {
79 		emu->initCount++;
80 		return 0;
81 	}
82 
83 	if (emu->emu_filename == NULL)
84 		emu->emu_filename = UFFS_FEMU_FILE_NAME;
85 
86 	uffs_Perror(UFFS_MSG_NORMAL,  "femu device init.");
87 
88 	emu->em_monitor_page = (u8 *) malloc(sizeof(emu->em_monitor_page[0]) * total_pages);
89 	if (!emu->em_monitor_page)
90 		return -1;
91 	emu->em_monitor_spare = (u8 *) malloc(sizeof(emu->em_monitor_spare[0]) * total_pages);
92 	if (!emu->em_monitor_spare)
93 		return -1;
94 
95 	emu->em_monitor_block = (u32 *) malloc(sizeof(emu->em_monitor_block[0]) * attr->total_blocks);
96 	if (!emu->em_monitor_block)
97 		return -1;
98 
99 	//clear monitor
100 	memset(emu->em_monitor_page, 0, sizeof(emu->em_monitor_page[0]) * total_pages);
101 	memset(emu->em_monitor_spare, 0, sizeof(emu->em_monitor_spare[0]) * total_pages);
102 	memset(emu->em_monitor_block, 0, sizeof(emu->em_monitor_block[0]) * attr->total_blocks);
103 
104 	emu->fp = fopen(emu->emu_filename, "rb");
105 	if (emu->fp == NULL) {
106 		emu->fp = fopen(emu->emu_filename, "ab+");
107 		if (emu->fp == NULL) {
108 			printf(PFX"Failed to create uffs emulation file.");
109 			return -1;
110 		}
111 
112 		fseek(emu->fp, 0, SEEK_END);
113 		fSize = ftell(emu->fp);
114 
115 		if (fSize < total_pages * full_page_size)	{
116 			printf("Creating uffs emulation file\n");
117 			fseek(emu->fp, 0, SEEK_SET);
118 			memset(p, 0xff, full_page_size);
119 			for (i = 0; i < total_pages; i++)	{
120 				written = fwrite(p, 1, full_page_size, emu->fp);
121 				if (written != full_page_size)	{
122 					printf("Write failed\n");
123 					fclose(emu->fp);
124 					emu->fp = NULL;
125 					return -1;
126 				}
127 			}
128 		}
129 	}
130 
131 	fflush(emu->fp);
132 	fclose(emu->fp);
133 
134 	emu->fp = fopen(emu->emu_filename, "rb+");
135 	if (emu->fp == NULL) {
136 		printf(PFX"Can't open emulation file.\n");
137 		return -1;
138 	}
139 
140 	emu->initCount++;
141 
142 	return 0;
143 }
144 
145 /*
146  * Release resources
147  */
femu_ReleaseFlash(uffs_Device * dev)148 int femu_ReleaseFlash(uffs_Device *dev)
149 {
150 	uffs_FileEmu *emu;
151 
152 	emu = (uffs_FileEmu *)(dev->attr->_private);
153 
154 	emu->initCount--;
155 
156 	if (emu->initCount == 0) {
157 
158 		uffs_Perror(UFFS_MSG_NORMAL,  "femu device release.");
159 
160 		if (emu->fp) {
161 			fclose(emu->fp);
162 			emu->fp = NULL;
163 		}
164 
165 		if (emu->em_monitor_page)
166 			free(emu->em_monitor_page);
167 		if (emu->em_monitor_spare)
168 			free(emu->em_monitor_spare);
169 		if (emu->em_monitor_block)
170 			free(emu->em_monitor_block);
171 		emu->em_monitor_page = NULL;
172 		emu->em_monitor_spare = NULL;
173 		emu->em_monitor_block = NULL;
174 	}
175 
176 	return 0;
177 }
178 
femu_EraseBlock(uffs_Device * dev,u32 blockNumber)179 int femu_EraseBlock(uffs_Device *dev, u32 blockNumber)
180 {
181 
182 	int i;
183 	u8 * pg = g_page_buf;
184 	int pg_size, pgd_size, sp_size, blks, blk_pgs, blk_size;
185 	uffs_FileEmu *emu;
186 	emu = (uffs_FileEmu *)(dev->attr->_private);
187 	if (!emu || !(emu->fp))
188 		goto err;
189 
190 	pg_size = dev->attr->page_data_size + dev->attr->spare_size;
191 	pgd_size = dev->attr->page_data_size;
192 	sp_size = dev->attr->spare_size;
193 	blk_pgs = dev->attr->pages_per_block;
194 	blks = dev->attr->total_blocks;
195 	blk_size = dev->attr->page_data_size * dev->attr->pages_per_block;
196 
197 	printf("femu: erase block %d\n", blockNumber);
198 
199 	if ((int)blockNumber >= blks) {
200 		printf("Attempt to erase non-existant block %d\n",blockNumber);
201 		goto err;
202 	}
203 	else {
204 
205 		//clear this block monitors
206 		memset(emu->em_monitor_page + (blockNumber * blk_pgs),
207 			0,
208 			blk_pgs * sizeof(u8));
209 		memset(emu->em_monitor_spare + (blockNumber * blk_pgs),
210 			0,
211 			blk_pgs * sizeof(u8));
212 
213 		emu->em_monitor_block[blockNumber]++;
214 
215 		memset(pg, 0xff, (pgd_size + sp_size));
216 
217 		fseek(emu->fp, blockNumber * blk_pgs * (pgd_size + sp_size), SEEK_SET);
218 
219 		for (i = 0; i < blk_pgs; i++)	{
220 			fwrite(pg, 1, (pgd_size + sp_size), emu->fp);
221 		}
222 
223 		fflush(emu->fp);
224 		dev->st.block_erase_count++;
225 	}
226 
227 	return UFFS_FLASH_NO_ERR;
228 err:
229 	return UFFS_FLASH_IO_ERR;
230 
231 }
232 
233