Simple Operating System
fs.h
Go to the documentation of this file.
1 
8 #ifndef FS_H
9 #define FS_H
10 
11 #ifndef KERNEL
12 #error Only kernel should use this file!
13 #endif
14 
15 #include <types.h>
16 #include <errno.h>
17 #include <io.h>
18 #include <string.h>
19 #include "interrupts.h"
20 
24 #define FILENAME_MAX 16
25 
30 #define SECTORS_PER_TRACK 37
31 
36 #define TRACKS_MAX 3
37 
38 //do it static - only this file should be able to use this
39 struct {
40  char name[FILENAME_MAX];
41  Byte track;
42  Byte beginSector;
43  Byte size;
44 } *files;
45 
49 bool map[TRACKS_MAX][SECTORS_PER_TRACK];//map[0] = 0 because there is no 0th sector, they are counted from 1
50 
51 size_t numberOfFiles = 0;
52 
53 static void saveFATable() {
54  asm("pushw es\n"
55  "mov es, si\n"
56  "int 0x13\n"
57  "popw es"
58  ::"a"(0x0301), "d"(0), "c"(2), "b"(0), "S"(KERNEL_ADDRESS));
59 }
60 
64 void __strncpy ( char * destination, const char * source, size_t num ) {
65  asm("L%=:\n"
66  " mov al, byte ptr ss:[si+bx]\n"
67  " mov byte ptr cs:[di+bx], al\n"
68  " cmp al,0\n"
69  " je after%=\n"
70  " inc bx\n"
71  "loop L%=\n"
72  "after%=:"
73  ::"D"(destination), "S"(source), "b"(0), "c"(num));
74 }
75 
81 int sys_setup() {
82  numberOfFiles = 0;
83  if(*(Byte *)0 != 0xcf || *(Byte *)1 != 0xaa || *(Byte *)2 != 0x55)
84  return -1;
85  files = 3;
86  for(; (*(int *)(numberOfFiles * 19 + 3) != 0) && numberOfFiles * 19 + 3 < 512; numberOfFiles++)
87  for(int i = 0; i < files[numberOfFiles].size; i++) {
88  if(files[numberOfFiles].track < TRACKS_MAX)
89  map[files[numberOfFiles].track][files[numberOfFiles].beginSector + i] = 1;//reserve space
90  }
91 
92  return numberOfFiles;
93 }
94 
101 int sys_open(const int filename) {
102  for(size_t id = 0; id < numberOfFiles; id++) {
103  if(strcmp(files[id].name, filename)) {
104  return files[id].size << 8 | id;
105  }
106  }
107  //file doesn't exist
108  return -ENOENT;
109 }
110 
120 int sys_create(const int filename, size_t size) {
121  if(size <= 0)//must be at least 1 sector
122  size = 1;
123 
124  if(size > SECTORS_PER_TRACK)
125  return -EFBIG;
126 
127  if(sys_open(filename) != -ENOENT)
128  return -EEXIST;
129 
130  //search for free space
131  Byte beginSector = 0;//store first sector of unused cx sectors
132  Byte track = 0;
133  for(track = 0; track < TRACKS_MAX; track++) {
134  for(int i = 1; i < SECTORS_PER_TRACK; i++) {
135  beginSector = i;
136  size_t j;
137  for(j = 0; j < size && j + i < SECTORS_PER_TRACK; j++) {
138  if(map[track][j + i]) {
139  beginSector = 0;
140  break;
141  }
142  }
143  if(j < size)
144  beginSector = 0;
145  if(beginSector != 0)
146  goto end;
147  }
148  }
149 end:
150  if(beginSector == 0)
151  return -ENOSPC;
152  //set file's sectors as used
153  for(size_t i = beginSector; i < size + beginSector; i++)
154  map[track][i] = 1;
155 
156  files[numberOfFiles].beginSector = beginSector;
157  files[numberOfFiles].size = size;
158  files[numberOfFiles].track = track;
159  strncpy(files[numberOfFiles].name, filename, FILENAME_MAX);
160  numberOfFiles++;
161  saveFATable();
162  return numberOfFiles - 1;//return file's ID
163 }
164 
171 int sys_remove(const int filename) {
172  int data = sys_open(filename);
173  if(data == -ENOENT)
174  return -ENOENT;
175 
176  int id = (Byte)data;
177  int track = files[id].track;
178 
179  //free space;
180  for(int j = files[id].beginSector; j < files[id].beginSector + files[id].size; j++)
181  map[files[id].track][j] = 0;
182 
183  //concat file table
184  for(int i = id; files[i].track == track; i++) {
185  files[i].beginSector = files[i + 1].beginSector;
186  files[i].size = files[i + 1].size;
187  files[i].track = files[i + 1].track;
188  strcpy(files[i].name, files[i + 1].name);
189  }
190  numberOfFiles--;
191  saveFATable();
192  return 0;
193 }
194 
203 int sys_read(const Byte id, int ptr, size_t size) {
204  if(id > numberOfFiles)
205  return -ENOENT;
206 
207  int sectors = (size - (size % 512)) / 512;
208  //if wanted more than filesize read whole file
209  if(files[id].size < (size % 512 == 0 ? sectors : sectors + 1)) {
210  size = files[id].size * 512;
211  sectors = files[id].size;
212  }
213 
214  //read whole sectors
215  if(sectors > 0) {
216  asm("int 0x13\n"
217  ::"a"(0x0200|sectors), "b"(ptr), "c"(files[id].track<<8|files[id].beginSector), "d"(0));
218  }
219  //read rest
220  if(size % 512 != 0) {
221  Byte readed[512];
222 
223  asm("pushw es\n"
224  "mov es, si\n"
225  "int 0x13\n"
226  "popw es\n"
227  ::"a"(0x0201), "b"(readed), "c"((files[id].track<<8|files[id].beginSector)+sectors), "d"(0), "S"(KERNEL_ADDRESS));
228 
229  //copy from cs:readed to ss:ptr
230  asm("L%=:\n"
231  " mov al, byte ptr cs:[si+bx]\n"
232  " mov byte ptr ss:[di+bx], al\n"
233  " inc bx\n"
234  "loop L%="
235  ::"D"(ptr+(sectors*512)), "S"(readed), "b"(0), "c"(size%512));
236  }
237  return size;
238 }
239 
249 int sys_write(Byte id, int ptr, size_t size) {
250  if(id > numberOfFiles)
251  return -ENOENT;
252 
253  int sectors = (size - (size % 512)) / 512;
254  //if not enough space try resizing
255  if(files[id].size < sectors + (size % 512 != 0 ? 1 : 0)) {
256  char filename[FILENAME_MAX];
257  strcpy(filename, files[id].name);
258  int ret = sys_remove(filename);
259  if(ret < 0)return ret;
260 
261  ret = sys_create(filename, sectors + (size % 512 != 0 ? 1 : 0));
262  if(ret < 0)return ret;
263  id = ret;
264  }
265 
266  //save whole sectors
267  if(sectors > 0) {
268  asm("int 0x13"
269  ::"a"(0x0300|sectors), "b"(ptr), "c"(files[id].track<<8|files[id].beginSector), "d"(0));
270  }
271  //save rest
272  if(size % 512 != 0) {
273  Byte toSave[512];
274  memset(toSave, 0, 512);
275 
276  //copy from ss:ptr to cs:toSave
277  asm("L%=:\n"
278  " mov al, byte ptr ss:[si+bx]\n"
279  " mov byte ptr cs:[di+bx], al\n"
280  " inc bx\n"
281  "loop L%="
282  ::"D"(toSave), "S"(ptr + (size - (size % 512))), "b"(0), "c"(size % 512));
283 
284  asm("pushw es\n"
285  "mov es, si\n"
286  "int 0x13\n"
287  "popw es"
288  ::"a"(0x0301), "b"(toSave), "c"(files[id].track<<8|(files[id].beginSector+sectors)), "d"(0), "S"(KERNEL_ADDRESS));
289  }
290  return size;
291 }
292 
293 #pragma GCC diagnostic push
294 #pragma GCC diagnostic ignored "-Wunused-parameter"
310 __int void int0x21(interruptFrame * frame) {
311  //DS and CS are on kernel address
312  asm("pushw ds\nmov ds, ax"::"a"(KERNEL_ADDRESS));
313 
314  // registers are backed up, after this function, they are restored
315  int ax = 0, bx = 0, cx = 0, dx = 0, di = 0, si = 0;
316  asm("mov ax,[ebp-24]":"=a"(ax));
317  asm("mov dx,[ebp-20]":"=d"(dx));
318  asm("mov cx,[ebp-16]":"=c"(cx));
319  asm("mov bx,[ebp-12]":"=b"(bx));
320  asm("mov si,[ebp-8]":"=S"(si));
321  asm("mov di,[ebp-4]":"=D"(di));
322  //change ah to ax
323  char fileName[FILENAME_MAX];
324  switch(ax >> 8) {
325  case 0:
326  asm("mov [ebp-24], eax"::"a"(sys_setup()));
327  break;
328  case 1:
329  __strncpy(fileName, bx, FILENAME_MAX);
330  asm("mov [ebp-24], eax"::"a"(sys_open(fileName)));
331  break;
332  case 2:
333  asm("mov [ebp-24], eax"::"a"(sys_read(bx, cx, dx)));
334  break;
335  case 3:
336  asm("mov [ebp-24], eax"::"a"(sys_write(bx, cx, dx)));
337  break;
338  case 4:
339  __strncpy(fileName, bx, FILENAME_MAX);
340  asm("mov [ebp-24], eax"::"a"(sys_create(fileName, cx)));
341  break;
342  case 5:
343  __strncpy(fileName, bx, FILENAME_MAX);
344  asm("mov [ebp-24], eax"::"a"(sys_remove(fileName)));
345  break;
346  default:
347  printf("INT 0x21!\n");
348  asm("mov [ebp-24],eax"::"a"(ENOSYS));
349  break;
350  }
351  asm("popw ds");
352 }
353 #pragma GCC diagnostic pop
354 
355 #endif
__int void int0x21(interruptFrame *frame)
interruption for file system
Definition: fs.h:310
void __strncpy(char *destination, const char *source, size_t num)
Copy from ss:source to cs:destination.
Definition: fs.h:64
int sys_setup()
load file system
Definition: fs.h:81
int sys_create(const int filename, size_t size)
Create file.
Definition: fs.h:120
bool map[TRACKS_MAX][SECTORS_PER_TRACK]
Map of used sectors in tracks.
Definition: fs.h:49
int sys_open(const int filename)
Open file.
Definition: fs.h:101
#define SECTORS_PER_TRACK
Number of sectors per track.
Definition: fs.h:30
int sys_remove(const int filename)
Remove file.
Definition: fs.h:171
#define FILENAME_MAX
Maximal size of file name.
Definition: fs.h:24
int sys_write(Byte id, int ptr, size_t size)
Write to file.
Definition: fs.h:249
#define TRACKS_MAX
Maximal number of tracks in OS.
Definition: fs.h:36
int sys_read(const Byte id, int ptr, size_t size)
Read from file.
Definition: fs.h:203
Setting system interruptions, see interrupts.asm.
Standard input output library.
void printf(const int str,...)
C-like printf function.
Definition: io.h:72
Simple string handling.
int strncpy(int destination, int source, size_t num)
Copy num Bytes from source to destination until \0 appears.
Definition: string.h:131
bool strcmp(int str1, int str2)
Compares two string until \0 appears.
Definition: string.h:20
int memset(int ptr, int value, size_t count)
Set count Bytes of *ptr to value.
Definition: string.h:97
char * strcpy(char *destination, const char *source)
Copy from source to destination until \0 appears.
Definition: string.h:113
frame for interruption, required by gcc for __int
Definition: interrupts.h:29
useful macros, definitions, enums etc.