You are not logged in.
Hi! I'm not sure if I even have enough visitors to ask anything on my own forum but just in case anybody drops in and has anything to add on the subject.
I'm halfway in my FAT12 driver, the VFS part is also mostly done but while thinking about the interfaces towards user programs I'm not sure what would be best.
My initial idea was to have "read_file", "write_file", "del_file", "read_dir", "create_dir" and "del_dir" where the write_file would take arguments for create if it's non-existing, write interval in file only and stuff like that. 6 neat functions that do all, with just extra parameters for special cases and settings. The file path would be needed for each call.
But thinking about it and also having a closer look at how DOS does things have made me doubt this. DOS uses internal file handles for everything where the only function taking a path is "open_file", it then has "file_seek" with handle as input, "file_write" with no. of bytes from current file position, a special function for creating or truncating and one for closing the file.
Is there any good reason to model my API after DOS in this regard, with handles open/close and so on? With my initial thought it would still be possible to read out part of the file, truncate and everything else you might need but with extra parameters instead of all those extra functions.. Also what if you forget to close the file? I'm sure it has some reasons, like file locking while editing? But, hmm.. should still be a better way?
I also have another question about the "read_dir" function, what should it return and in what format? I'm planning to support LFN, so that also raises the question if it should provide an option to get the short filename or only the long version? In any case, pointer to zero terminated names in a row after each other with another reg for total size is that enough? Leaving the rest to user programs? What about file sizes and so on, would a DIR command need to make another call for each file returned to get file information like size, type and last modified date? It wouldn't be hard, but is it bad design to require that? Could use "read_file" with special argument for just getting file info like that.
Anyway, more functions vs less? Any thoughts?
Offline
I've decided to use file handles, but I still might go for the simpler approach inside the fat12-driver. Because I just realized that locking files, keeping track of handles and just presenting a unified API is up to the VFS anyway..
Haha almost forgot about that, since the VFS up until now mostly have been responsible for device drivers and internal structs for device->fs. But obviously it will also be the central point for all incoming file read/write requests with stub functions to call each FS-drivers internal functionality.
Offline
Hi just remembered my password
I thought i would put my input.
I am going the Dos way myself, that's because its well documented and alot of asm tut are based on it.
So by using the same reg other then 32/64bits, beginner will be able to translate old tuts.
You will find it easier to port stuff like fasm and c libs etc.
Offline
hi, hehe good news and great seeing you here!
yeah, a general file handle for opening and seeking is fine, because it's not tied into fat12 so support for that with open, close, seek truncate and everything else is decided. as you said, will probably make my life easier when porting apps too.
but the one thing i'm yet not sure about is how you get a directory listing in dos. all i found was lots of interrupts dealing with what they called FCB (file control block), which seems to be the raw fat12 dir struct for each file, but nowhere do i find an interrupt on how to obtain this fcb block in the first place? and even if i do, i have to basically do a wildcard search for files with the directory FCB... it all seems confusing and when it comes to getting a directorys content i'm not sure how to handle it, what info to include and so on.
if it's just a list with names, it would still be possible to open each file or request additional info like size and last modify date via other functions with full path&filename. one thing is for sure, i do not want to include raw fat12 dir/file entries because it won't be portable between different file systems later.
how does the directory listing work in dex, what output can a user program get when wanting a list of files? btw, do you have sub-dir support, if not - i guess you still have some sort of listing call for the root?
Offline
First most of the info as to how it works are dos virus
But once i new how it works, i must say i realy like it.
Heres a nasm example that helped me
org 100h start: mov ah, 0x1A ; Set DTA table adress mov dx, DTA int 21h ;"find_first mov ah, 0x4E xor cx, cx ; no attributes mov dx, squery int 21h jc theend ; no files matching query found mov ah, 9 mov dx, fname int 21h find_next: call clean_name mov ah, 0x4F mov dx, squery int 21h ; find next matching file jc theend ; no more files found mov ah, 9 mov dx, fname int 21h jmp find_next theend: mov ah, 0x4C int 21h clean_name: mov cx, 13 mov di, fname xor ax, ax repe stosb ; fill name with zeros incase memory has some ugly stuff or smth left from last search ret squery db "*.*", 0x0 ; search query, must end with zero DTA resb 0x15 ; ignore useless DOS data fattr db 0x0 ; file attribute ftime dw 0x0 ; file creation/modification time fdate dw 0x0 ; file creation/modification date fsize dw 0x0 ; file size fsmth dw 0x0 fname resb 14 ; file name terminated with zero db 0xD, 0xA ; New line db "$" ; 0xD - tells DOS to go to new line.
1.First you need to set a new address for "DTA table adress" to send the info about the file
2. then you send the "find_first" function (with search query) of wanted file.
3. test for no files found, if found print it.
4. Then you call "find_next", this over writes the stuff stored in the DTA, so if i was you i would move it to a safe place to print later.
5. you keep loop the "find_next" function untill no more file.
Now this is for Dos, but you just need to implement the above function in BOS.
I am writing the above along with fat12/16 as a driver for my OS you could just implement the driver interface.
PS: I will post a none gui ver of the way it works so you can test, as the gui seem to be the problem in bochs.
Last edited by Dex4u (2012-02-06 19:57:57)
Offline
Oh, ok thanks now when I know what to search for I was also able to find more documentation. It's certainly easier for the OS than giving a complete list of all files - since it's hard to know the size beforehand. I do not have any realloc-thing to resize allocated space so would have to allocate something like 4kb and if thats filled, allocate another 4kb (total 8kb), copy the contents over to the new mem and free the first 4kb. Such techniques would still make it possible to provide a complete list - but as I said, this would be even easier.
Thanks for your input it's been helpful! If you don't mind letting me have the source temporarily I could debug it myself and try to patch it for you so the GUI works in bochs, I'm not sure what license you'r on right now but if it's closed I could make sure to delete after fixing it.
Offline
Okey, I thought the /old/ page meant that the OS source was old too. I'll check that out right away and see if I can't find something out!
Offline
No not the old page.
Go here: http://www.dex-os.com/
And click the download button its in theres.
Offline
making some "progress" now, not excatly polished look on anything yet, but working more on the behind the scenes functions:
working on a parse_path function now that still has a few bugs to work out, it doesn't seem to report any consistent numbers for how many parts the path consists of, should be 0 for fd1 or fd1/, 1 for fd1/folder or fd1/folder/ and 2 for fd1/folder/test or fd1/folder/test/
not quite there yet as you can see, not sure if i dare publish the buggy code since it's not very well coded
btw, right now i just subtract 0x30 from the ASCII number to get binary, but thats only for 1 number and wouldn't work for fd12 or hd54 in case you have that many devices. does anybody know of a good ascii2bin function for ax(2) or eax(4) ascii numbers to binary? should still subtract 0x30 and then *10 on each level to get base right, but I don't feel like doing it myself - there should be plenty of functions out there but i can't find any.
Offline
Nice work , if you take a look in the functionPM folder in DexOSv5 code theres a include thats called convert.inc, you will find the function you need in there.
"testhex" is the one you call, with number in eax and zero terminated string out put is in numbuff2
Hope that helps.
Offline
thanks but I mean the other way around, like:
mov eax, '1234'
call ascii2bin
eax->1234 or 0x4d2 (real number)
eax as input would be enough since i only need for two ascii numbers to convert into int, but why not support 4 bytes while i'm at it anyway, have been searching for a ready made function, but maybe ascii2bin isn't right, might have more luck with ascii2int or something? i'll continue looking.
eh. nevermind... made my own special case function that works ok on two ASCII chars to number:
; ah = first ASCII like 2, al = second ASCII like 1 = making number 21 .convert_cont: push ecx xor ecx, ecx cmp ah, 0 jne .cont_convert pop ecx sub al, 0x30 ; only one ASCII char. jmp .number_found ; done. .cont_convert: mov cl, ah sub cx, 0x30 ; take care of first push ecx ; save it for later.. mov cl, al sub cx, 0x30 shl cx, 1 ; multiply with 10 using mov eax, ecx ; x*8 + x*2 = shl cx, 2 add ax, cx ; x*10 pop ecx add ax, cx ; add first number pop ecx .number_found:
maybe not the most elegant solution there is, but made it work so, will have to do. i feel rusty, like most my current code could have been better. well well, now to debug the other aspects of the function, it will take cl as second parameter, if it's filled = return only that part of the path... so i can loop a path with this and take it one level/dir at a time.
Offline
Finally. Everything seems to work now, so now sub directory support will be easier to achieve. Here's a screenshot on how it looks in action, with the parsed parts outputed in a loop after the first call to check how many they are:
and here's the full function source, in case anybody has some remarks on it. Since it's the first bigger thing I've done in assembly for like 5 years.
;--------------------------------------------------------------; ; parse_path - parse path to get info on each part ; ;--------------------------------------------------------------; ; ; ; in: esi = pointer to full ASCIIZ path ; ; cl = part no. to extract or 0 for none ; ; ; ; out: bl = drive no. (VFS assigned) or zero ; ; bh = number of elements or zero for none ; ; edi = pointer to ASCIIZ part of path in ; ; cl, or 0 on error or no input ; ;--------------------------------------------------------------; parse_path: push eax push ecx push edx push esi cmp byte [esi], 0 je .error cmp byte [esi+1], 0 ; minimum 3 chars drive je .error cmp byte [esi+2], 0 je .error and byte [esi], 11011111b ; (0xDF) to uppercase and byte [esi+1], 11011111b ; (0xDF) to uppercase mov bl, 0x00 ; fd base is 0x00 cmp word [esi], 'FD' ; fd check je .drive_found mov bl, 0x0F ; hd base is 0x0F cmp word [esi], 'HD' ; hd check je .drive_found mov bl, 0x5F ; cd base is 0x5F cmp word [esi], 'CD' ; cd check je .drive_found mov bl, 0x7F ; rd base is 0x7F cmp word [esi], 'RD' ; rd (ram drive) check je .drive_found mov bl, 0x8F ; rm base is 0x8F cmp word [esi], 'RM' ; rm (removable/usb) je .drive_found mov bl, 0xAF ; nd base is 0xAF cmp word [esi], 'ND' ; nd (net) check je .drive_found jmp .error ; no valid drive found ;-----------------------; ; get drive number ; ;-----------------------; .drive_found: xor edx, edx ; esi offest for first / cmp byte [esi+3], 0 ; end of path je .one_number cmp byte [esi+3], '/' ; one number je .one_number mov edx, 4 ; first / after numbers xor eax, eax mov ax, word [esi+2] ; get 2 bytes number jmp .convert_cont .one_number: mov edx, 3 ; first / after numbers xor eax, eax mov al, byte [esi+2] ; 1 byte ASCII number .convert_cont: push ecx xor ecx, ecx cmp ah, 0 jne .cont_convert pop ecx sub al, 0x30 ; only one ASCII char. jmp .number_found ; done. .cont_convert: mov cl, ah sub cx, 0x30 ; take care of first push ecx ; save it for later.. mov cl, al sub cx, 0x30 shl cx, 1 ; multiply with 10 using mov eax, ecx ; x*8 + x*2 = shl cx, 2 add ax, cx ; x*10 pop ecx add ax, cx ; add first number pop ecx .number_found: add bl, al ; add number to base ;------------------------; ; parse parts of path ; ;------------------------; mov bh, 0 ; start at zero add esi, edx ; add start offset cmp byte [esi], '/' jne .end ; root, no parts xor eax, eax ; counter .parts_loop: ; loop for path parts inc esi cmp byte [esi], 0 ; end of path? je .end ; no inc in parts cmp byte [esi], '/' ; end of part? je .new_part cmp eax, 0 jne .cont_parts inc bh ; inc no. of parts .cont_parts: inc eax ; char count inc cmp cl, bh ; check for part to jne .parts_loop ; save, if match: mov edi, .filename_buffer ; get buffer dec edi ; offset starts at 1, add edi, eax ; not 0 - so fixed now push eax mov al, byte [esi] mov byte [edi], al ; put the byte mov byte [edi+1], 0 ; make ASCIIZ pop eax jmp .parts_loop .new_part: xor eax, eax ; reset char count jmp .parts_loop ; loop again ;------------------------; ; cleanup and return ; ;------------------------; .end: mov edi, .filename_buffer pop esi pop edx pop ecx pop eax ret .error: pop esi pop edx pop ecx pop eax mov edi, 0 ; not a valid part mov bl, 0 ; not a valid drive mov bh, 0 ; not a valid path ret .filename_buffer: times 256 db 0
Offline
Nice, i am sure you will soon be back to speed, i started doing some avr asm coding, i was surprised how easy it was to pick it up.
I am working on my file sys, but i am going to stick with the dos method of doing stuff.
It works well and is well documented.
I was thinking of a very simpe VF sys where you us a floppy image.
You load the image in memory at startup read/write every thing to it and on close you write the whole image back to disk.
But for now i will just read write to real disk when needed, as VF sys are more for multi-tasking OS.
[Edit] Have got a copy of that game you ported to DexOS ?.
Last edited by Dex4u (2012-02-11 20:00:31)
Offline
I think we mean different things with vfs, I mean the functions and interface for user apps, that take filename or path and drive no. as arguments and then reads or writes no matter if it's a floppy or hd, fat12 or fat32. it would accomplish this by having vars for each drive with info on type and fs so it knows what drivers to use/call. using the floppy as a kind of ram-disk is another possibility of course, and I'll have a ram disk driver that can use any size and any of the installed fs's.
I'm not sure if I still have it, will take a look. But as far as I remember it never fully worked as it was supposed to, not sure.. The porting to 32-bit was a bigger problem then to dex-os since it used lots of multiplications and other things very 16 bit specific.. I can remember trying to clear the upper half of every register and such to make it work.
Offline
Hi, I found the DEX-OS sources for pitman in a folder on this server!
Here's the URL: http://dex4u.asmhackers.net/
Seems to have a compiled version named .dex but not sure if it runs correctly? as i said, think i got problems with 16->32 bit converting..?
Offline
Hi, yes I'm making progress even if it's slow.. I've broken up the things that needs to be done into (internal) sub functions like this for now:
;--------------------------------------------------------------; ; get_dir_entry - get a directory entry or amount ; ;--------------------------------------------------------------; ; ; ; in: esi = pointer to prev dir entry or 0 for root ; ; cx = entry no. to extract or 0 for none ; ; ; ; out: cx = number of entries or unchanged if set ; ; edi = pointer to dir entry or unchanged if cx=0 ; ;--------------------------------------------------------------; get_dir_entry: ;...... ret ;--------------------------------------------------------------; ; get_fat_entry - get a fat entry/cluster number ; ;--------------------------------------------------------------; ; ; ; in: cx = fat entry/cluster number ; ; ; ; out: cx = next fat entry/cluster no. or 0 if none ; ;--------------------------------------------------------------; get_fat_entry: ;... ret ;--------------------------------------------------------------; ; get_cluster - get a cluster ; ;--------------------------------------------------------------; ; ; ; in: cx = fat entry/cluster number ; ; ; ; out: edi = pointer to cluster or zero if none ; ;--------------------------------------------------------------; get_cluster: ;... ret
Everything is kind of halfway done, but there is quite some dependencies between functions so I'll basically have to wait with testing and debugging until all of it is done.
How about you, any news on DexOS development?
Offline
Great minds think alike, i am working on a better file functions and am doing the same as you, i have broken everything down into small functions (so they can be used many times).
But you have to write so many functions, before you can test them, you hope your not making a debugging nightmare for yourself .
Ps: As a side note, i am coding mine as a module, so it will need to be loaded.
That way you can change to any file sys easily, i will remove any form of file read/write from the kernel.
The main problem is how do you load the driver without read/write, well i will include it as a file in the kernel, so it can be relocated to top of memory, then other drivers can be load by using the fat driver.
Last edited by Dex4u (2012-03-02 01:32:41)
Offline