playing around with pffs (NOT FINISHED, DOESNT COMPILE!)
[my-code/arm.git] / betty / pffs.c
1 /*
2  * pffs.c - pseudo flash filesystem
3  *
4  * author: hackbard@hackdaworld.org
5  *
6  */
7
8 #include "pffs.h"
9
10 /*
11  * functions
12  */
13
14 u32 pffs_get_ptr(t_pffs *pffs,u8 sector) {
15
16         u16 data[3];
17         u32 iaddr;
18         u32 daddr;
19         u8 fnlen;
20         u8 found;
21
22         iaddr=0;
23         daddr=0;
24         found=0;
25
26         while(1) {
27                 pffs->fr(pffs->base_addr+pffs->sec_addr[sector]+iaddr,data,6);
28                 if(!((data[0]&0xff00)==PFFS_INDEX_MAGIC))
29                         break;
30                 found=1;
31                 fnlen=(data[0]&0x00f0)>>4;
32                 iaddr+=(6+fnlen+fnlen);
33                 daddr=((data[0]&0x000f)<<16)|data[1];
34         }
35
36         pffs->data_ptr=daddr;
37
38         if(found) {
39                 pffs->index_ptr[0]=pffs->sec_addr[sector];
40                 pffs->index_ptr[1]=pffs->sec_addr[sector]+iaddr;
41                 return 0;
42         }
43         else
44                 return -1;
45 }
46
47 int pffs_sec_empty(t_pffs *pffs,u8 sec) {
48
49         u32 addr;
50         u16 data;
51
52         addr=pffs->base_addr|pffs->sec_addr[sec];
53
54         while(addr<(pffs->base_addr|pffs->sec_addr[sec+1])) {
55                 data=*((u16 *)(addr));
56                 if(data!=0xffff)
57                         return 0;
58                 addr+=2;
59         }
60
61         return 1;
62 }
63
64 #define pffs_sec_erase(pffs,sec) pffs->fe(pffs->base_addr|pffs->sec_addr[sec])
65
66 int pffs_orientate(t_pffs *pffs) {
67
68         u8 sec,sec0,sec1;
69
70         /* check index sectors */
71         sec0=pffs->sec_num_index[0];
72         sec1=pffs->sec_num_index[1];
73         if(!(pffs_get_ptr(pffs,sec0)&pffs_get_ptr(pffs,sec1)))
74                 return 0;
75
76         /* initial run => no data + no index assumed => check whether erased! */
77         // erase index sectors
78         if(!pffs_sec_empty(pffs,sec0))
79                 pffs_sec_erase(pffs,sec0);
80         if(!pffs_sec_empty(pffs,sec1))
81                 pffs_sec_erase(pffs,sec1);
82         // erase data sectors
83         sec0=pffs->sec_num_data[0];
84         sec1=pffs->sec_num_data[1];
85         for(sec=sec0;sec<=sec1;sec++)
86                 if(!pffs_sec_empty(pffs,sec))
87                         pffs_sec_erase(pffs,sec);
88
89         return 0;
90 }
91
92 int pffs_flash_register(t_pffs *pffs,u32 base_addr,u32 *sec_addr,
93                         u8 sec_num_data_min,u8 sec_num_data_max,
94                         u8 sec_num_index0,u8 sec_num_index1,
95                         int (*fw)(u32 addr,u16 *buf,int len),
96                         int (*fr)(u32 addr,u16 *buf,int len),
97                         int (*fe)(u32 addr)) {
98
99         /* assign physical flash specs */
100         pffs->base_addr=base_addr;
101         pffs->sec_addr=sec_addr;
102
103         /* specified index and data sectors */
104         pffs->sec_num_data[0]=sec_num_data_min;
105         pffs->sec_num_data[1]=sec_num_data_max;
106         pffs->sec_num_index[0]=sec_num_index0;
107         pffs->sec_num_index[1]=sec_num_index1;
108
109         /* flash acccess function pointers */
110         pffs->fw=fw;
111         pffs->fr=fr;
112         pffs->fe=fe;
113
114         pffs->state|=PFFS_REGISTERED;
115
116         return 0;
117 }
118
119 int pffs_init(t_pffs *pffs) {
120
121         /* check whether a flash is registered */
122         if(!(pffs->state&PFFS_REGISTERED))
123                 return -1;
124
125         /* orientate */
126         pffs_orientate(pffs);
127
128         return 0;
129 }
130
131 #define pffs_check_magic(data) (((data)&PFFS_INDEX_MAGIC_MASK)==PFFS_INDEX_MAGIC)
132 #define pffs_fnlen(data) (((data)&PFFS_FNLEN_MASK)>>4)
133 #define pffs_daddr_msb(data) (((data)&))
134
135 int pffs_find_file(t_pffs *pffs,char *file,u32 *iaddr,u32 *daddr,u16 *len) {
136
137         u8 fnl;
138         u16 data[PFFS_MAX_FILENAME_SIZE+PFFS_HEADER_SIZE];
139
140         pffs->index_ptr[2]=pffs->base_addr|pffs->index_ptr[0];
141
142         while(pffs->index_ptr[2]<pffs->index_ptr[1])
143                 pffs->fr(iaddr,data,3);
144
145                 if(!pffs_check_magic(data[0]))
146                         break;
147
148                 fnl=pffs_fnlen(data[0]);
149                 pffs->fr(iaddr+6,data+3,fnl+fnl);
150
151                 if(!strncmp(fd->file,(char *)(data+3),fnl+fnl)) {
152                         *daddr=((data[0]&0x000f)<<16)|data[1];
153                         *len=data[2];
154                         pffs->index_ptr[2]=*iaddr;
155                         return PFFS_FILE_EXISTS;
156                 }
157                 pffs->fr(iaddr,data,3);
158         }
159         
160         return PFFS_FILE_NOT_FOUND;
161 }
162
163 int pffs_open_read(t_pffs *pffs,t_pffs_fd *fd) {
164
165         u32 iaddr;
166         u32 daddr;
167         u16 data[PFFS_MAX_FILENAME+PFFS_HEADER_SIZE];
168
169         iaddr=pffs->base_addr|pffs->index_ptr[0];
170
171         return 0x23;
172 }
173
174 int pffs_open(t_pffs *pffs,t_pffs_fd *fd,char *file,u8 mode) {
175
176         /* the pffs struct */
177         fd->pffs=pffs;
178
179         /* filename */
180         fd->fn_size=strlen(file);
181         if(fd->fn_size>30)
182                 return PFFS_FILENAME_TOO_LONG;
183         strncpy(fd->file,file,fd->fn_size);
184         if(fd->fn_size&1)
185                 fd->file[fd->fn_size++]='\0';
186
187         /* mode */
188         fd->mode=mode;
189
190         /* action */
191         switch(mode) {
192                 case PFFS_READ:
193                         pffs_open_read(pffs,fd);
194                         break;
195                 case PFFS_WRITE:
196                         break;
197                 case PFFS_RDWR:
198                 default:
199                         return PFFS_MODE_UNSUPPORTED;
200         }
201
202         return 0;
203 }
204