2 * pffs.c - pseudo flash filesystem
4 * author: hackbard@hackdaworld.org
14 #define pffs_check_magic(data) (((data)&PFFS_INDEX_MAGIC_MASK)==PFFS_INDEX_MAGIC)
15 #define pffs_fnlen(data) (((data)&PFFS_FNLEN_MASK)>>4)
16 #define pffs_daddr_msb(data) (((data)&PFFS_LEN_MSB_MASK))
17 #define pffs_sec_erase(pffs,sec) pffs->fe(pffs->base_addr|pffs->sec_addr[sec])
19 u32 pffs_find_index(t_pffs *pffs,u8 sector) {
23 pffs->fr(pffs->base_addr+pffs->sec_addr[sector],&data,2);
25 if((data&0xf000)==PFFS_INDEX_MAGIC) {
26 pffs->index_sec=sector;
27 return PFFS_INDEX_FOUND;
30 return PFFS_NO_INDEX_FOUND;
33 int pffs_sec_empty(t_pffs *pffs,u8 sec) {
38 addr=pffs->base_addr|pffs->sec_addr[sec];
40 while(addr<(pffs->base_addr|pffs->sec_addr[sec+1])) {
41 pffs->fr(addr,&data,2);
43 return PFFS_SEC_NOT_EMPTY;
47 return PFFS_SEC_EMPTY;
50 int pffs_find_data_tmp(t_pffs *pffs,u8 sector) {
52 u32 iaddr,daddr,dend,dstart;
56 iaddr=pffs->base_addr|pffs->sec_addr[pffs->index_sec];
57 dstart=pffs->sec_addr[sector];
58 dend=pffs->sec_addr[sector+1];
60 while(iaddr<(pffs->base_addr|pffs->sec_addr[sector+1])) {
61 pffs->fr(iaddr,data,6);
62 if(pffs_check_magic(data[0]))
64 daddr=pffs_daddr_msb(data[0])|data[1];
65 if((daddr+data[2]<dstart)|(daddr>=dend)) {
66 fnlen=pffs_fnlen(data[0]);
67 iaddr+=(6+fnlen+fnlen);
71 return PFFS_NO_DATA_TMP;
74 pffs->data_tmp_sec=sector;
75 if(pffs_sec_empty(pffs,sector)!=PFFS_SEC_EMPTY)
76 pffs->fe(pffs->base_addr|dstart);
78 return PFFS_DATA_TMP_FOUND;;
81 int pffs_orientate(t_pffs *pffs) {
83 u8 sec,sec0,sec1,found;
85 sec0=pffs->sec_num_index[0];
86 sec1=pffs->sec_num_index[1];
90 /* check index sectors */
91 if(pffs_find_index(pffs,sec0)==PFFS_INDEX_FOUND)
93 else if(pffs_find_index(pffs,sec1)==PFFS_INDEX_FOUND)
96 /* chose temp data sector */
98 sec0=pffs->sec_num_data[0];
99 sec1=pffs->sec_num_data[1];
100 for(sec=sec1;sec>=sec0;sec--)
101 if(pffs_find_data_tmp(pffs,sec)==PFFS_DATA_TMP_FOUND)
104 return PFFS_INDEX_FOUND;
107 /* initial run => no data + no index assumed => check whether erased! */
108 // erase index sectors
109 if(!pffs_sec_empty(pffs,sec0))
110 pffs_sec_erase(pffs,sec0);
111 if(!pffs_sec_empty(pffs,sec1))
112 pffs_sec_erase(pffs,sec1);
113 pffs->index_sec=sec0;
114 // erase data sectors
115 sec0=pffs->sec_num_data[0];
116 sec1=pffs->sec_num_data[1];
117 pffs->data_tmp_sec=sec1;
118 for(sec=sec0;sec<=sec1;sec++)
119 if(!pffs_sec_empty(pffs,sec))
120 pffs_sec_erase(pffs,sec);
125 int pffs_get_data_sec(t_pffs_fd *fd) {
131 sec0=pffs->sec_num_data[0];
132 sec1=pffs->sec_num_data[1];
134 for(sec=sec0;sec<sec1;sec++) {
135 if((addr<pffs->sec_addr[sec+1])&(addr>=pffs->sec_addr[sec])) {
144 int pffs_rearrange(t_pffs *pffs) {
151 int pffs_flash_register(t_pffs *pffs,u32 base_addr,u32 *sec_addr,
152 u8 sec_num_data_min,u8 sec_num_data_max,
153 u8 sec_num_index0,u8 sec_num_index1,
154 int (*fw)(u32 addr,u16 *buf,int len),
155 int (*fr)(u32 addr,u16 *buf,int len),
156 int (*fe)(u32 addr)) {
158 /* assign physical flash specs */
159 pffs->base_addr=base_addr;
160 pffs->sec_addr=sec_addr;
162 /* specified index and data sectors */
163 pffs->sec_num_data[0]=sec_num_data_min;
164 pffs->sec_num_data[1]=sec_num_data_max;
165 pffs->sec_num_index[0]=sec_num_index0;
166 pffs->sec_num_index[1]=sec_num_index1;
168 /* flash acccess function pointers */
173 pffs->state|=PFFS_REGISTERED;
178 int pffs_init(t_pffs *pffs) {
180 /* check whether a flash is registered */
181 if(!(pffs->state&PFFS_REGISTERED))
185 pffs_orientate(pffs);
190 int pffs_find_file(t_pffs *pffs,char *file,u32 *iaddr,u32 *daddr,u16 *len) {
193 u16 data[PFFS_MAX_FILENAME_SIZE+PFFS_HEADER_SIZE];
195 *iaddr=pffs->base_addr|pffs->sec_addr[pffs->index_sec];
197 while(*iaddr<pffs->sec_addr[pffs->index_sec+1]) {
198 pffs->fr(*iaddr,data,3);
200 if(!pffs_check_magic(data[0]))
203 fnl=pffs_fnlen(data[0]);
204 pffs->fr(*iaddr+6,data+3,fnl+fnl);
206 if(!strncmp(file,(char *)(data+3),fnl+fnl)) {
207 *daddr=pffs->base_addr|((data[0]&0x000f)<<16)|data[1];
209 return PFFS_FILE_FOUND;
215 return PFFS_FILE_NOT_FOUND;
218 int pffs_open_read(t_pffs_fd *fd) {
222 ret=pffs_find_file(fd->pffs,fd->file,
223 &(fd->iaddr),&(fd->daddr),&(fd->len));
225 if(ret==PFFS_FILE_FOUND) {
233 int pffs_write_index_init(t_pffs_fd *fd) {
236 u16 data[PFFS_HEADER_SIZE+PFFS_MAX_FILENAME_SIZE];
241 if(fd->iaddr+6+fns+fns>=pffs->sec_addr[pffs->index_sec+1])
242 return PFFS_NO_INDEX_SPACE_LEFT;
244 data[0]=0x7f00|(fns<<4)|((fd->daddr>>16)&0xf);
245 data[1]=fd->daddr&0xffff;
246 pffs->fw(fd->iaddr,data,4);
247 pffs->fw(fd->iaddr+6,fd->file,fns+fns);
249 return PFFS_INDEX_WROTE_INIT;
252 int pffs_write_finish(t_pffs_fd *fd) {
254 fd->pffs->fw(fd->iaddr+4,&(fd->len),2);
259 int pffs_open_write(t_pffs_fd *fd) {
263 ret=pffs_find_file(fd->pffs,fd->file,
264 &(fd->iaddr),&(fd->daddr),&(fd->len));
267 case PFFS_FILE_NOT_FOUND:
268 ret=pffs_write_index_init();
269 if(ret!=PFFS_INDEX_WROTE_INIT)
275 case PFFS_FILE_FOUND:
283 int pffs_open(t_pffs *pffs,t_pffs_fd *fd,char *file,u8 mode) {
287 /* the pffs struct */
291 fd->fn_size=strlen(file);
293 fd->file[fd->fn_size++]='\0';
295 if(fd->fn_size>PFFS_MAX_FILENAME_SIZE)
296 return PFFS_FILENAME_TOO_LONG;
297 strncpy(fd->file,file,fd->fn_size+fd->fn_size);
305 ret=pffs_open_read(fd);
308 ret=pffs_open_write(fd);
312 return PFFS_MODE_UNSUPPORTED;
318 int pffs_read(t_pffs_fd *fd,u8 *buf,int len) {
323 /* check whether valid */
324 if(!(fd->mode&PFFS_READ))
329 return PFFS_INVALID_LEN;
331 /* check how much we read */
332 missing=fd->len-(fd->dptr-fd->daddr);
336 if((fd->dptr+len)>=pffs->sec_addr[pffs->sec_num_data[1]+1])
337 sec_end=pffs->sec_addr[pffs->sec_num_data[1]+1]-fd->dptr;
341 fd->pffs->fr(fd->dptr,(u16 *)buf,len);
347 int pffs_write(t_pffs_fd *fd,u8 buf,int len) {
349 /* check whether valid */
350 if(!(fd->mode&PFFS_WRITE))
355 return PFFS_INVALID_LEN;
357 missing=PFFS_MAX_FILE_SIZE-fd->len;
362 if(fd->dptr+len>=pffs->)