New release - version 0.6.1; zasm compiler added - ZeX/OS assembly compiler; lot...
[ZeXOS.git] / kernel / drivers / fs / fat.c
blob4a67e85591eec4a10da1a629bc46f1f31e93ab02
1 /*
2 * ZeX/OS
3 * Copyright (C) 2007 Tomas 'ZeXx86' Jedrzejek (zexx86@gmail.com)
5 * This program is free software: you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation, either version 3 of the License, or
8 * (at your option) any later version.
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
15 * You should have received a copy of the GNU General Public License
16 * along with this program. If not, see <http://www.gnu.org/licenses/>.
20 #include <system.h>
21 #include <string.h>
23 int cele;
24 unsigned long file_cache_id = 0;
26 #define WAIT 0xFFFFFL
28 unsigned char tolower(char c)
30 return ((c >= 'A' && c <= 'Z') ? c + 32: c);
33 static void wait(void)
35 unsigned long wait;
37 for(wait = WAIT; wait != 0; wait--)
38 /* nothing */;
41 void dec2bin (long decimal, char *binary)
43 int k = 0, n = 0;
44 int neg_flag = 0;
45 int remain;
46 char temp[80];
48 // take care of negative input
49 if (decimal < 0)
51 decimal = -decimal;
52 neg_flag = 1;
56 remain = decimal % 2;
57 decimal = decimal / 2; // whittle down decimal
58 temp[k++] = remain + 0x30; // makes characters 0 or 1
59 } while (decimal > 0);
61 if (neg_flag)
62 temp[k++] = '-'; // add back - sign
63 else
64 temp[k++] = ' '; // or space
65 while (k >= 0)
67 binary[n++] = temp[--k]; // reverse spelling
69 binary[n-1] = 0; // end with NULL
72 void parse_attr (char* binary,int y)
75 0x01 000001 Read only
76 0x02 000010 Hidden
77 0x04 000100 System file
78 0x08 001000 Volume ID
79 0x10 010000 Directory
80 0x20 100000 Binary which stands for Archive
83 int i;
84 int x=0;
85 dir[y].read=0;
86 dir[y].hidden=0;
87 dir[y].system=0;
88 dir[y].volume=0;
89 dir[y].dir=0;
90 dir[y].bin=0;
91 for(i = strlen(binary)-1; i>=0; i--)
93 if(binary[i] == '1')
95 switch (x)
97 case 0: dir[y].read=1; break;
98 case 1: dir[y].hidden=1; break;
99 case 2: dir[y].system=1; break;
100 case 3: dir[y].volume=1; break;
101 case 4: dir[y].dir=1; break;
102 case 5: dir[y].bin=1; break;
105 x++;
109 int fat_read (unsigned int byte, unsigned int byte2)
111 BYTE text[512];
112 unsigned char *buf = text;
113 unsigned int i = 0;
114 unsigned int x;
115 unsigned int start = -1;
116 unsigned int next = 0;
117 unsigned int test = 0;
118 unsigned int pom = 0;
120 if (!read_block (1, text, 1))
121 return 0;
123 buf = text;
124 for(x = 0; x < 512; x ++) {
125 //if (i>byte-3 && i<byte+3)
126 //kprintf("%x",*buf);
127 if (i == byte)
128 start = *buf;
130 if (i == byte2 && start != -1) {
131 if (start == 0xf0 && *buf == 0xff)
132 return -2;
134 next = ((*buf << 8 | start) >> 4);
135 test = (*buf << 8 | start);
137 if (cele == 0)
138 next = (*buf << 8 | start) & 0x0FFF;
140 if (next < 0)
141 next = next * (-1);
142 //kprintf("\nnext=%x %d start=%x end=%x byte=%d byte1=%d cele=%d test=%x\n",next,next,start,*buf,byte,byte2,cele,test);
144 return next;
147 *buf ++;
148 i ++;
151 return -1;
155 int fat_nextsector (int i) {
156 cele = (i*150)%100;
157 return (i*150)/100;
160 void read_f (unsigned int cluster){
161 static BYTE text1[512] = "";
162 unsigned char *buf;
163 unsigned int x;
164 // kprintf("\n*** %d\n",cluster);
165 read_block (33 + cluster, text1, 1);
166 //strcpy(buf,text1);
167 //text1[strlen(text1)-4]='\0';
169 unsigned len = 512;
171 /* FIXME: lot of work with elf */
172 //file_cache = (unsigned char *) krealloc ((void *) file_cache, file_cache_id+len);
173 //kprintf ("file_cache: 0x%x\n", file_cache);
174 memcpy (file_cache+file_cache_id, text1, len);
176 file_cache_id += len;
179 // 33 sector = open space
180 unsigned long read_file (int aa)
182 int i;
183 int byte;
184 int next = 0;
185 int sect;
186 cele=0;
187 file_cache[0] = '\0';
188 //kprintf("name=%s start=%d fat=%d\n",dir[aa].name,dir[aa].start,next);
189 next = fat_nextsector (dir[aa].start);
190 sect = fat_read (next,next+1);
191 file_cache_id = 0;
192 next = fat_nextsector (sect);
193 read_f (dir[aa].start-2);
194 // file_cache[strlen(file_cache)-4]='\0';
196 for (i = 0; i < 100; i++) {
197 DPRINT ("next: %d sect: %d\n", next, sect);
199 if (sect<0 || sect==4095)
200 break;
201 //file_cache[strlen (file_cache)-4] = '\0';
202 read_f (sect-2);
203 sect = fat_read (next, next+1);
204 next = fat_nextsector (sect);
207 return file_cache_id;
210 unsigned read_dir (int aa)
212 static BYTE text[512];
213 unsigned char *buf = text;
214 int x;
215 int i = 0;
216 int y = 0;
217 char *bin;
218 int label = 0;
219 unsigned int start;
220 /* vymazeme nazvy vsech souboru */
221 for(x = 0; x < 223; x ++)
222 dir[x].name[0] = '\0';
224 if (aa == -1) {
225 if (!read_block (19, text, 1))
226 return 0;
227 //printf ("ret: %d\n", ret);
228 } else {
229 if (!read_block (33+dir[aa].start-2, text, 1))
230 return 0;
233 buf = text;
235 for (x = 0; x < 512; x ++) {
236 if (i == 31) {
237 i=-1;
238 y++;
239 label = 0;
242 if (i == 26)
243 start = *buf;
245 if (i == 27 && label == 0)
246 dir[y].start = (*buf << 8 | start);
248 if (i == 11 && (*buf == 0x0f || *buf == 0x00)) {
249 strcpy (dir[y].name, "");
250 label = 1;
251 y --;
253 if (i == 11 && *buf != 0x0f && *buf != 0x00) {
254 dec2bin (*buf,bin);
255 parse_attr (bin, y);
257 if (i <= 10 && i >= 0)
258 dir[y].name[i] = tolower (*buf);
260 i ++;
261 *buf ++;
264 return 1;
270 FAT12
271 WRITE function
274 void write_f (unsigned int cluster, char *text1)
276 if (!write_block (33 + cluster, text1, 1)) {
277 printf ("error -> FAT12 -> !floppy write\n");
278 return;
281 DPRINT ("FAT12 -> write_f (): OK");
284 // 33 sector = open space
285 void write_file (int aa, char *buf)
287 int i;
288 int byte;
289 int next = 0;
290 int sect;
291 cele=0;
293 //kprintf("name=%s start=%d fat=%d\n",dir[aa].name,dir[aa].start,next);
295 next = fat_nextsector (dir[aa].start);
296 sect = fat_read (next, next+1);
297 file_cache_id = 0;
299 next = fat_nextsector (sect);
300 read_f (dir[aa].start-2);
302 for(i = 0; i < 100; i++) {
303 DPRINT ("next: %d sect: %d\n", next, sect);
305 if (sect < 0 || sect == 4095)
306 break;
308 write_f (sect-2, buf);
309 sect = fat_read (next, next+1);
310 next = fat_nextsector (sect);
314 /* TODO: in development */
315 void write_dir (int aa)
317 static BYTE text[512];
318 unsigned char *buf = text;
319 int x;
320 int i = 0;
321 int y = 0;
322 char *bin;
323 int label = 0;
324 unsigned int start;
325 /* vymazeme nazvy vsech souboru */
326 for(x = 0; x < 223; x ++)
327 dir[x].name[0] = '\0';
329 if (aa == -1)
330 write_block (19, text, 1);
331 else
332 write_block (33+dir[aa].start-2, text, 1);
334 buf = text;
336 for (x = 0; x < 512; x ++) {
337 if (i == 31) {
338 i=-1;
339 y++;
340 label = 0;
343 if (i == 26)
344 start = *buf;
346 if (i == 27 && label == 0)
347 dir[y].start = (*buf << 8 | start);
349 if (i == 11 && (*buf == 0x0f || *buf == 0x00)) {
350 strcpy (dir[y].name, "");
351 label = 1;
352 y --;
354 if (i == 11 && *buf != 0x0f && *buf != 0x00) {
355 dec2bin (*buf,bin);
356 parse_attr (bin, y);
358 if (i <= 10 && i >= 0)
359 dir[y].name[i] = tolower (*buf);
361 i ++;
362 *buf ++;
368 bool fat_handler (unsigned act, unsigned arg, char *block, unsigned n, unsigned long l)
370 switch (act) {
371 case FS_ACT_INIT:
373 /* nothing */
374 return 1;
376 break;
377 case FS_ACT_READ:
379 switch (arg) {
380 case FS_ARG_FILE:
382 l = read_file (n);
383 block = file_cache;
384 return 1;
386 break;
387 case FS_ARG_DIR:
389 read_dir (n);
390 block = file_cache;
391 //memcpy (block, file_cache, file_cache_id);
392 block[file_cache_id] = '\0';
393 l = file_cache_id;
394 return 1;
396 break;
399 return 0;
401 break;
402 case FS_ACT_WRITE:
404 switch (arg) {
405 case FS_ARG_FILE:
407 unsigned y = 0;
408 while (y < (l+512))
409 y += 512;
411 //printf ("alokovano: %ud\n", y);
412 char *buf = (char *) kmalloc (sizeof (char) * (y+1));
414 if (!buf) {
415 DPRINT ("ERROR -> FAT WRITE : out of memory");
416 return 0;
419 memset (buf, 0, y);
420 memcpy (buf, block, l);
422 int i;
423 for (i = 0; i < (y/512); i ++);
424 write_file (n, buf+(i*512));
426 return 1;
428 break;
429 case FS_ARG_DIR:
431 return 0;
433 break;
436 return 0;
440 return 0;