OSDev.org
https://forum.osdev.org/

Next Filesystem to Implement
https://forum.osdev.org/viewtopic.php?f=1&t=12850
Page 1 of 2

Author:  frank [ Fri Feb 02, 2007 11:56 am ]
Post subject:  Next Filesystem to Implement

I was wondering which filesystem I should implement after FAT 12/16/32. I'm looking for something that is easy and a good step up from FAT.

Author:  Tyler [ Fri Feb 02, 2007 12:06 pm ]
Post subject: 

Preferably one you already know quite well and won't have to research in such detail. Especially if you have experience with it. If not i would probably pick whatever the default is in Linux atm. Somethign like Ext2fs which is well documented will be best.

Author:  Mike [ Sun Feb 04, 2007 9:14 pm ]
Post subject: 

Ext2 looks pretty simple. Although I have not implemented it myself, I have looked at the spec.

Plus then you will have a nice balance of the Windows and Linux worlds. :)

Author:  frank [ Mon Feb 05, 2007 3:39 pm ]
Post subject: 

Does any one know of a good way to create and access EXT2 filesystems from withing Windows XP?

Author:  Brynet-Inc [ Mon Feb 05, 2007 5:26 pm ]
Post subject: 

frank wrote:
Does any one know of a good way to create and access EXT2 filesystems from withing Windows XP?


A Google search showed a few results, This one is the most notable.. Looks like it's still fairly maintained...

It's under the GPL licence, Supports both read/write operations.

http://www.ext2fsd.com/

One can always just use a UNIX-like system full time though :wink:

Author:  frank [ Tue Feb 06, 2007 12:18 pm ]
Post subject: 

Thanks

Brynet-Inc wrote:
One can always just use a UNIX-like system full time though :wink:


I would if I could, but I don't have high speed internet, so I can't download it, and I have yet to find a UNIX-like system that works well with my WIN modem. Plus I have no money. :wink:

Author:  Brendan [ Tue Feb 06, 2007 3:22 pm ]
Post subject:  Re: Next Filesystem to Implement

Hi,

frank wrote:
I was wondering which filesystem I should implement after FAT 12/16/32. I'm looking for something that is easy and a good step up from FAT.


I'd probably try to implement ISO9660 (CD-ROM) - mostly because I refuse to implement file system code that may be used to break the security (file system permissions, etc) of other OSs....


Cheers,

Brendan

Author:  frank [ Tue Feb 06, 2007 3:59 pm ]
Post subject:  Re: Next Filesystem to Implement

Quote:
I'd probably try to implement ISO9660 (CD-ROM)


Thanks, I was looking into that one two.

Author:  Dex [ Wed Feb 07, 2007 10:23 am ]
Post subject: 

Or you could implement a basic NTFS.

Author:  Brynet-Inc [ Wed Feb 07, 2007 12:33 pm ]
Post subject: 

Dex wrote:
Or you could implement a basic NTFS.


Now that wouldn't be productive or useful.. or in any way fun.. now would it ;)

Author:  Alboin [ Wed Feb 07, 2007 2:20 pm ]
Post subject: 

frank wrote:
Thanks

Brynet-Inc wrote:
One can always just use a UNIX-like system full time though :wink:


I would if I could, but I don't have high speed internet, so I can't download it, and I have yet to find a UNIX-like system that works well with my WIN modem. Plus I have no money. :wink:


Aye, a WinModem isn't compatible with any Linux\Unix\BSD\SkyOS I know of. I had one, and when I installed Linux it was my first problem. I found that I had to buy a US Robotics Modem, which work quite nicely.

For an easy file system: Why not Minix? I'm sure it's well documented. :)

Author:  Brynet-Inc [ Wed Feb 07, 2007 5:30 pm ]
Post subject: 

One of the main reasons that winmodems don't work on these systems is the actual cards are blank slate.

There firmware is usually located in a closed source binary driver, Targeting Windows normally :P..

Also, Not many of these winmodems are in any way identical, so making a driver that supporting them all is... improbable.

Still, The Linux community has lower standards against binary blobs, There are a few closed source winmodem drivers.

http://linmodems.org/
http://www.google.ca/search?hl=en&safe= ... arch&meta=

Few links above, but again.. Anyone who supports such vendor lock-in is really pathetic.

As Alboin said, Quite a few older (ISA usually) cards work perfectly.. (Normally appearing simply as communications ports, /dev/cua01 would be COM2 OpenBSD as an example..)

For the subject at hand anyway, frank.. You could possibly add support for OpenBSD's Berkeley FFS implementation, Or FreeBSD's UFS2 or w/e.

...Not sure why anyone would implement Minix's file system Alboin :?

Author:  Dex [ Wed Feb 07, 2007 5:30 pm ]
Post subject: 

Brynet-Inc wrote:
Dex wrote:
Or you could implement a basic NTFS.


Now that wouldn't be productive or useful.. or in any way fun.. now would it ;)

This code will find and load a file from a ntfs partion, Sorry its not in C ;).
Here is "mtrdr.asm"
Code:
; KolibriOS bootloader
; this code has been written by diamond in 2005 specially for KolibriOS

; this code is loaded by ntldr to 0D00:0000
; and by io.sys from config.sys to xxxx:0100
   format   binary
   use16

   org   0xD000
; entry point for 9x booting
   jmp   @f
   db   'd' xor 'i' xor 'a' xor 'm' xor 'o' xor 'n' xor 'd'
   db   'NTFS'
@@:
   mov   si, load_question + 100h - 0D000h
   call   out_string
;   mov   si, answer + 100h - 0D000h   ; already is
xxy:   mov   ah, 0
   int   16h
   or   al, 20h
   mov   [si], al
   cmp   al, 'y'
   jz   xxz
   cmp   al, 'n'
   jnz   xxy
; continue load Windows
;       call    out_string
;       ret
out_string:
   lodsb
   test   al, al
   jz   .xxx
   mov   ah, 0Eh
   mov   bx, 7
   int   10h
   jmp   out_string
.xxx:   ret
xxz:
; boot KolibriOS
   call   out_string
   push   0
   pop   ds
   mov   word [4], new01handler + 100h - 0D000h
   mov   [6], cs
   pushf
   pop   ax
   or   ah, 1
   push   ax
   popf
;   int   19h
;   pushf      ; there will be no iret
   call   far [19h*4]
xxt:
; TF has been cleared when entered new01handler
;   pushf
;   pop   ax
;   and   ah, not 1
;   push   ax
;   popf
   xor   di, di
   mov   ds, di
   cmp   word [8*4+2], 0F000h
   jz   @f
   les   bx, [8*4]
   mov   eax, [es:bx+1]
   mov   [8*4], eax
@@:
   mov   eax, [8*4]
   mov   [20h*4], eax
   mov   si, 100h
   push   cs
   pop   ds
   push   0D00h
   pop   es
   mov   cx, 2000h/2
   rep   movsw
   jmp   0D00h:0256h
load_question   db   'Load KolibriOS? [y/n]: ',0
answer   db   ?
   db   13,10,0

new01handler:
; [sp]=ip, [sp+2]=cs, [sp+4]=flags
   push   bp
   mov   bp, sp
   push   bx
   push   ds
   lds   bx, [bp+2]
   cmp   word [bx], 19cdh
   jz   xxt
   pop   ds
   pop   bx
   pop   bp
   iret

relative_read:
   add   eax, [partition_start]

; read from hard disk
; drive_size must be already initialized
; in: eax = absolute sector
;     cx = number of sectors
;     es:bx -> buffer
read:
   pushad
   cmp   eax, [drive_size]
   jb   .old_style
; new style - LBA, function 42
   cmp   [has_lba], 0
   jz   disk_error
; allocate disk address packet on the stack
; qword +8: absolute block number
   push   dword 0    ; dword +C is high dword
   push   eax      ; dword +8 is low dword
; dword +4: buffer address
   push   es      ; word +6 is segment
   push   bx      ; word +4 is offset
; word +2: number of blocks = 1
; word +0: size of packet = 10h
   push   dword 10010h
; now pair ss:sp contain address of disk address packet
.patch1:
   mov   ax, 4200h
   mov   dl, [boot_drive]
   mov   si, sp
   push   ds
   push   ss
   pop   ds
   int   13h
   pop   ds
   add   sp, 10h
.end:
   popad
   jc   disk_error
   add   bx, 200h
   inc   eax
   dec   cx
   jnz   read
   ret
.old_style:
; old style - CHS, function 2
; convert absolute sector in eax to cylinder-head-sector coordinates
; calculate sector
   xor   edx, edx
   movzx   ecx, [sectors]
   div   ecx
; sectors are counted from 1
   inc   dl
   mov   cl, dl      ; low 6 bits of cl = sector number
; calculate head number
   shld   edx, eax, 10h   ; convert eax to dx:ax
   div   [heads]
   mov   dh, dl      ; dh = head
   mov   ch, al      ; ch = low 8 bits of cylinder
   shl   ah, 6
   or   cl, ah      ; high 2 bits of cl = high 2 bits of cylinder
.patch2:
   mov   ax, 201h   ; function 2, al=1 - number of sectors
   mov   dl, [boot_drive]
   int   13h
   jmp   .end

disk_error:
   mov   si, disk_error_msg
   call   out_string
   jmp   $

has_lba db   0

disk_error_msg   db   'Disk read error!',0
start_msg   db   2,' KolibriOS bootloader, running on ',0
errfs_msg   db   'unknown filesystem, cannot continue',0
fat16_msg   db   'FAT12/FAT16 - unsupported',13,10,0
fat32_msg   db   'FAT32',13,10,0
ntfs_msg   db   'NTFS',13,10,0
error_msg   db   'Error'
colon      db   ': ',0
mft_string   db   'MFT',0
root_string   db   '\',0
nodata_string   db   '$DATA not found',0
noindex_string   db   '$INDEX_ROOT not found',0
invalid_read_request_string db 'cannot read attribute',0
notfound_string db   'not found',0
directory_string db   'is a directory',0
fragmented_string db   'too fragmented file',0
exmem_string   db   'extended memory error',0
bad_cluster_string db   'bad cluster',0

; init procedure - ntldr jmps here
   repeat   0D256h - $
      db   1
   end   repeat
start:
; cs=es=0D00, ds=07C0, ss=0
; esi=edi=ebp=0, esp=7C00
   xor   ax, ax
   mov   ds, ax
   mov   es, ax
; our stack is 4Kb-2b!!! (0xFFE)
   mov   ss, ax
   mov   esp, 0FFFEh

; we are booting from first hard disk
   mov   dl, 80h
   mov   [boot_drive], dl
   cld
   sti
; calculate drive size
   mov   ah, 8   ; 8 = get drive parameters
   int   13h
; now: CF is set on error;
; ch = low 8 bits of maximum cylinder number
; cl : low 6 bits makes maximum sector number, high 2 bits are high 2 bits of maximum cylinder number
; dh = maximum head number
   jnc   @f
   mov   cx, -1
   mov   dh, cl
@@:
   movzx   ax, dh
   inc   ax
; ax = number of heads
   mov   [heads], ax
   mov   dl, cl
   and   dx, 3Fh
; dx = number of sectors
; (note that sectors are counted from 1, and maximum sector number = number of sectors)
   mov   [sectors], dx
   mul   dx
   xchg   cl, ch
   shr   ch, 6
   inc   cx
; cx = number of cylinders
   mov   [cyls], cx
   mul   cx
   mov   word [drive_size], ax
   mov   word [drive_size+2], dx
; this drive supports LBA?
   mov   dl, [boot_drive]
   mov   ah, 41h
   mov   bx, 55AAh
   int   13h
   jc   .no_lba
   cmp   bx, 0AA55h
   jnz   .no_lba
   test   cl, 1
   jz   .no_lba
   inc   [has_lba]
.no_lba:
; say hi to user
   mov   si, start_msg
   call   out_string
; now read first sector to determine file system type
; first sector of disk is MBR sector
   xor   eax, eax
   mov   cx, 1
   mov   bx, 500h
   call   read
   mov   eax, [6C6h]   ; first disk
   mov   [partition_start], eax
   mov   cx, 1
   mov   bx, 500h
   call   read
   movzx   ax, byte [50Dh]
   mov   [sect_per_clust], ax
; determine file system
   cmp   dword [536h], 'FAT1'
   jz   fat1x
   cmp   dword [552h], 'FAT3'
   jz   fat32
   cmp   dword [503h], 'NTFS'
   jz   ntfs
;       mov     si, errfs_msg           ; already is
   call   out_string
   jmp   $
fat1x:
   mov   si, fat16_msg
   call   out_string
   jmp   $
fat32:
   mov   si, fat32_msg
   call   out_string
   movzx   eax, word [50Bh]   ; bytes_per_sect
   movzx   ebx, byte [50Dh]   ; sects_per_clust
   mul   ebx
   mov   [cluster_size], eax
   movzx   ebx, word [50Eh]   ; reserved_sect
   add   ebx, [51Ch]      ; hidden
   mov   [fat_start], ebx
   movzx   eax, byte [510h]   ; num_fats
   mul   dword [524h]      ; sect_fat
   add   eax, ebx
; cluster 2 begins from sector eax
   movzx   ebx, byte [50Dh]   ; sects_per_clust
   sub   eax, ebx
   sub   eax, ebx
   sub   eax, [51Ch]   ; we will use relative_read
   mov   [data_start], eax
   mov   eax, [52Ch]      ; root_cluster
   push   menuet_img_name
   mov   [cur_obj], root_string
   call   fat32_parse_dir
; parse FAT chunk
; runlist at 2000:0000
   mov   di, 5
   push   2000h
   pop   es
   mov   byte [es:di-5], 1   ; of course, non-resident
   mov   dword [es:di-4], 1
   stosd
.parsefat:
   push   es
   push   ds
   pop   es
   call   next_cluster
   pop   es
   jnc   .done
   mov   ecx, [es:di-8]
   add   ecx, [es:di-4]
   cmp   eax, ecx
   jz   .contc
   mov   dword [es:di], 1
   add   di, 4
   stosd
   jmp   .parsefat
.contc:
   inc   dword [es:di-8]
   jmp   .parsefat
.done:
   xor   eax, eax
   stosd
   jmp   read_img_file

ntfs:
   mov   si, ntfs_msg
   call   out_string
   movzx   eax, word [50Bh]   ; bpb_bytes_per_sect
   push   eax
   movzx   ebx, byte [50Dh]   ; bpb_sects_per_clust
   mul   ebx
   mov   [cluster_size], eax
   mov   [data_start], 0
   mov   ecx, [540h]      ; frs_size
   cmp   cl, 0
   jg   .1
   neg   cl
   xor   eax, eax
   inc   eax
   shl   eax, cl
   jmp   .2
.1:
   mul   ecx
.2:
   mov   [frs_size], eax
   pop   ebx
   xor   edx, edx
   div   ebx
   mov   [frs_sectors], ax
; read first MFT record - description of MFT itself
   mov   [cur_obj], mft_string
   movzx   eax, byte [50Dh]   ; bpb_sects_per_clust
   mul   dword [530h]      ; mft_cluster
   mov   cx, [frs_sectors]
   mov   bx, 4000h
   mov   di, bx
   push   bx
   call   relative_read
   call   restore_usa
; scan for unnamed $DATA attribute
   pop   di
   mov   ax, 80h      ; $DATA
   mov   bx, 700h
   call   load_attr
   mov   si, nodata_string
   jc   find_error_si
   mov   [free], bx
; load menuet.img
; find entry
   mov   eax, 5
   push   menuet_img_name
   mov   [cur_obj], root_string
   call   ntfs_parse_dir
read_img_file:
   xor   si, si
   push   es
   pop   fs
; yes! Now read file to 0x100000
   lods byte [fs:si]
   cmp   al, 0   ; assume nonresident attr
   mov   si, invalid_read_request_string
   jz   find_error_si
   mov   si, 1
   xor   edi, edi
; read buffer to 1000:0000 and move it to extended memory
   push   1000h
   pop   es
   xor   bx, bx
.img_read_block:
   lods dword [fs:si]      ; eax=length
   xchg   eax, ecx
   jecxz   .img_read_done
   lods dword [fs:si]      ; eax=disk cluster
.img_read_cluster:
   pushad
; read part of file
   movzx   ecx, byte [50Dh]
   mul   ecx
   add   eax, [data_start]
   call   relative_read
; move it to extended memory
   mov   ah, 87h
   mov   ecx, [cluster_size]
   push   ecx
   shr   cx, 1
   mov   si, movedesc
   push   es
   push   ds
   pop   es
   int   15h
   pop   es
   cmp   ah, 0
   mov   si, exmem_string
   jnz   find_error_si
   pop   ecx
   add   [dest_addr], ecx
   popad
   inc   eax
   loop   .img_read_cluster
   jmp   .img_read_block
.img_read_done:
; menuet.img loaded; now load kernel.mnt
load_kernel:
   push   ds
   pop   es
   mov   [cur_obj], kernel_mnt_name
; read boot sector
   xor   eax, eax
   mov   bx, 500h
   mov   cx, 1
   call   read_img
; init vars
   mov   ax, [50Eh]   ; reserved_sect
   add   ax, [51Ch]   ; hidden
   mov   word [fat_start], ax
   xchg   ax, bx
   movzx   ax, byte [510h]      ; num_fats
   mul   word [516h]      ; fat_length
   add   ax, bx
; read root dir
   mov   bx, 700h
   mov   cx, [511h]   ; dir_entries
   add   cx, 0Fh
   shr   cx, 4
   call   read_img
   add   ax, cx
   mov   [img_data_start], ax
   shl   cx, 9
   mov   di, bx
   add   bx, cx
   mov   byte [bx], 0
.scan_loop:
   cmp   byte [di], 0
   mov   si, notfound_string
   jz   find_error_si
   mov   si, kernel_mnt_name
   call   fat_compare_name
   jz   .found
   and   di, not 1Fh
   add   di, 20h
   jmp   .scan_loop
.found:
   and   di, not 1Fh
   mov   si, directory_string
   test   byte [di+0Bh], 10h
   jnz   find_error_si
; found, now load it to 1000h:0000h
   mov   ax, [di+1Ah]
; first cluster of kernel.mnt in ax
; translate it to sector on disk in menuet.img
   push   ax
   dec   ax
   dec   ax
   movzx   cx, byte [50Dh]
   mul   cx
   add   ax, [img_data_start]
; now ax is sector in menuet.img
   mov   [kernel_mnt_in_img], ax
   div   [sect_per_clust]
; now ax is cluster in menuet.img and
; dx is offset from the beginning of cluster
   movzx   eax, ax
   push   2000h
   pop   ds
   mov   si, 1
.scani:
   sub   eax, [si]
   jb   .scanidone
; sanity check
   cmp   dword [si], 0
   push   invalid_read_request_string
   jz   find_error_sp
   pop   cx
; next chunk
   add   si, 8
   jmp   .scani
.scanidone:
   add   eax, [si]   ; undo last subtract
   add   eax, [si+4]   ; get cluster
   push   0
   pop   ds
   movzx   ecx, [sect_per_clust]
   push   dx
   mul   ecx      ; get sector
   pop   dx
   movzx   edx, dx
   add   eax, edx
   add   eax, [data_start]
   mov   [kernel_mnt_1st], eax
   pop   ax
   push   1000h
   pop   es
.read_loop:
   push   ax
   xor   bx, bx
   call   img_read_cluster
   shl   cx, 9-4
   mov   ax, es
   add   ax, cx
   mov   es, ax
   pop   ax
   call   img_next_cluster
   jc   .read_loop
   mov   eax, 'KLBR'
   mov   si, loader_block
   jmp   1000h:0000h

img_next_cluster:
   mov   bx, 700h
   push   ax
   shr   ax, 1
   add   ax, [esp]
   mov   dx, ax
   shr   ax, 9
   add   ax, word [fat_start]
   mov   cx, 2
   push   es
   push   ds
   pop   es
   call   read_img
   pop   es
   and   dx, 1FFh
   add   bx, dx
   mov   ax, [bx]
   pop   cx
   test   cx, 1
   jz   .1
   shr   ax, 4
.1:
   and   ax, 0FFFh
   mov   si, bad_cluster_string
   cmp   ax, 0FF7h
   jz   find_error_si
   ret
img_read_cluster:
   dec   ax
   dec   ax
   movzx   cx, byte [50Dh]   ; sects_per_clust
   mul   cx
   add   ax, [img_data_start]
   movzx   eax, ax
;   call   read_img
;   ret
read_img:
; in: ax = sector, es:bx->buffer, cx=length in sectors
   pushad
   movzx   ebx, bx
   mov   si, movedesc
   shl   eax, 9
   add   eax, 93100000h
   mov   dword [si+sou_addr-movedesc], eax
   mov   eax, 9300000h
   mov   ax, es
   shl   eax, 4
   add   eax, ebx
   mov   [si+dest_addr-movedesc], eax
   mov   ah, 87h
   shl   cx, 8   ; mul 200h/2
   push   es
   push   0
   pop   es
   int   15h
   pop   es
   cmp   ah, 0
   mov   si, exmem_string
   jnz   find_error_si
   popad
   ret

movedesc:
   times 16 db 0
; source
   dw   0xFFFF      ; segment length
sou_addr dw   0000h      ; linear address
   db   1      ; linear address
   db   93h      ; access rights
   dw   0
; destination
   dw   0xFFFF      ; segment length
dest_addr dd   93100000h   ; high byte contains access rights
            ; three low bytes contains linear address (updated when reading)
   dw   0
   times 32 db 0

find_error_si:
   push   si
find_error_sp:
   mov   si, error_msg
   call   out_string
   mov   si, [cur_obj]
   call   out_string
   mov   si, colon
   call   out_string
   pop   si
   call   out_string
   jmp   $

file_not_found:
   mov   si, [esp+2]
   mov   [cur_obj], si
   push   notfound_string
   jmp   find_error_sp

   include 'fat32.inc'
   include   'ntfs.inc'

write1st:
; callback from kernel.mnt
; write first sector of kernel.mnt from 1000:0000 back to disk
   push   cs
   pop   ds
   push   cs
   pop   es
; sanity check
   mov   bx, 500h
   mov   si, bx
   mov   cx, 1
   push   cx
   mov   eax, [kernel_mnt_1st]
   push   eax
   call   relative_read
   push   1000h
   pop   es
   xor   di, di
   mov   cx, 8
   repz   cmpsw
   mov   si, data_error_msg
   jnz   find_error_si
; ok, now write back to disk
   or   byte [read.patch1+2], 1
   or   byte [read.patch2+2], 1
   xor   bx, bx
   pop   eax
   pop   cx
   call   relative_read
   and   byte [read.patch1+1], not 1
   and   byte [read.patch2+2], not 2
; and to image in memory (probably this may be done by kernel.mnt itself?)
   mov   dword [sou_addr], 93010000h
   movzx   eax, [kernel_mnt_in_img]
   shl   eax, 9
   add   eax, 93100000h
   mov   dword [dest_addr], eax
   mov   si, movedesc
   push   ds
   pop   es
   mov   ah, 87h
   mov   cx, 100h
   int   15h
   cmp   ah, 0
   mov   si, exmem_string
   jnz   find_error_si
   retf
data_error_msg db 'data error',0

loader_block:
   db   1   ; version
   dw   1   ; flags - image is loaded
   dw   write1st   ; offset
   dw   0      ; segment

fat_cur_sector dd -1

; -----------------------------------------------
; ------------------ Settings -------------------
; -----------------------------------------------

; must be in lowercase, see ntfs_parse_dir.scan, fat32_parse_dir.scan
kernel_mnt_name    db   'kernel.mnt',0
menuet_img_name    db   'menuet.img',0

; uninitialized data follows
drive_size      dd   ?   ; in sectors
boot_drive      db   ?
heads         dw   ?
sectors       dw   ?
cyls         dw   ?
partition_start    dd   ?
free         dw   ?
cur_obj       dw   ?
data_start      dd   ?
img_data_start      dw   ?
sect_per_clust      dw   ?
kernel_mnt_in_img   dw   ?
kernel_mnt_1st      dd   ?
; NTFS data
cluster_size      dd   ?   ; in bytes
frs_size      dd   ?   ; in bytes
frs_sectors      dw   ?   ; in sectors
mft_data_attr      dw   ?
index_root      dw   ?
index_alloc      dw   ?
ofs         dw   ?
dir         dw   ?
; FAT32 data
fat_start      dd   ?
cur_cluster      dd   ?
; file must be 16 sectors long

   repeat   0F000h - $
      db   2
   end   repeat

Here is "ntfs.inc"
Code:
restore_usa:
; Update Sequence Array restore
   mov   bx, [di+4]
   mov   cx, [di+6]
   inc   bx
   add   bx, di
   inc   bx
   add   di, 1feh
   dec   cx
@@:
   mov   ax, [bx]
   stosw
   inc   bx
   inc   bx
   add   di, 1feh
   loop   @b
   ret

find_attr:
; in: di->file record, ax=attribute
; out: di->attribute or di=0 if not found
   add   di, [di+14h]
.1:
; attributes codes are formally dwords, but all they fit in word
   cmp   word [di], -1
   jz   .notfound
   cmp   word [di], ax
   jnz   .continue
; for $DATA attribute, scan only unnamed
   cmp   ax, 80h
   jnz   .found
   cmp   byte [di+9], 0
   jz   .found
.continue:
   add   di, [di+4]
   jmp   .1
.notfound:
   xor   di, di
.found:
   ret

process_mcb_nonres:
; in: si->attribute, es:di->buffer
; out: di->buffer end
   add   si, [si+20h]
   xor   ebx, ebx
.loop:
   lodsb
   test   al, al
   jz   .done
   push   invalid_read_request_string
   movzx   cx, al
   shr   cx, 4
   jz   find_error_sp
   xchg   ax, dx
   and   dx, 0Fh
   jz   find_error_sp
   add   si, cx
   add   si, dx
   pop   ax
   push   si
   dec   si
   movsx   eax, byte [si]
   dec   cx
   jz   .l1e
.l1:
   dec   si
   shl   eax, 8
   mov   al, [si]
   loop   .l1
.l1e:
   xchg   ebp, eax
   dec   si
   movsx   eax, byte [si]
   mov   cx, dx
   dec   cx
   jz   .l2e
.l2:
   dec   si
   shl   eax, 8
   mov   al, byte [si]
   loop   .l2
.l2e:
   pop   si
   add   ebx, ebp
; eax=length, ebx=disk block
   stosd
   mov   eax, ebx
   stosd
   jmp   .loop
.done:
   xor   eax, eax
   stosd
   ret

load_attr:
; in: ax=attribute, es:bx->buffer, di->base record
; out: bx->buffer end; CF set if not found
   push   di
   push   ax
   mov   byte [es:bx], 1
   inc   bx
   push   bx
   mov   [ofs], bx
; scan for attrubute
   add   di, [di+14h]
@@:
   call   find_attr.1
   test   di, di
   jz   .notfound1
   cmp   byte [di+8], 0
   jnz   .nonresident
; resident attribute
   mov   si, di
   pop   di
   dec   di
   mov   al, 0
   stosb
   mov   ax, [si+10h]
   stosw
   xchg   ax, cx
   add   si, [si+14h]
   rep   movsb
   mov   bx, di
   pop   ax
   pop   di
   ret
.nonresident:
; nonresident attribute
   cmp   dword [di+10h], 0
   jnz   @b
; read start of data
   mov   si, di
   pop   di
   call   process_mcb_nonres
   push   di
.notfound1:
; $ATTRIBUTE_LIST is always in base file record
   cmp   word [esp+2], 20h
   jz   .nofragmented
; scan for $ATTRIBUTE_LIST = 20h
   mov   di, [esp+4]
   mov   ax, 20h
   call   find_attr
   test   di, di
   jz   .nofragmented
; load $ATTRIBUTE_LIST itself
   push   es
   mov   bx, 0C000h
   mov   di, [esp+4]
   push   bx
   push   [ofs]
   push   ds
   pop   es
   call   load_attr
   pop   [ofs]
   pop   si
   mov   bx, 8000h
   push   bx
   push   si
   call   read_attr_full
   pop   si
   pop   bx
   add   dx, bx
   mov   ax, [esp+2]
   pop   es
.1:
   cmp   [bx], ax
   jnz   .continue1
; only unnamed $DATA attributes!
   cmp   ax, 80h
   jnz   @f
   cmp   byte [bx+6], 0
   jnz   .continue1
@@:
   cmp   dword [bx+10h], 0
   jz   .continue1
   cmp   dword [bx+8], 0
   jnz   @f
   push   ax
   mov   ax, [esp+2]
   cmp   ax, [ofs]
   pop   ax
   jnz   .continue1
@@:
   pushad
   mov   eax, [bx+10h]
   mov   bx, dx
   push   [ofs]
   push   es
   push   ds
   pop   es
   call   read_file_record
   pop   es
   pop   [ofs]
   popad
   pushad
   mov   di, dx
   add   di, [di+14h]
.2:
   call   find_attr.1
   mov   eax, [bx+8]
   cmp   eax, [di+10h]
   jnz   .2
   mov   si, di
   mov   di, [esp+20h]
   sub   di, 4
   call   process_mcb_nonres
   mov   [esp+20h], di
   popad
.continue1:
   add   bx, [bx+4]
   cmp   bx, dx
   jb   .1
.nofragmented:
   pop   bx
   pop   ax
   pop   di
   cmp   bx, [ofs]
   jnz   @f
   dec   bx
   stc
@@:
   ret

read_attr_full:
; in: si->decoded attribute data, bx->buffer
; out: edx=length in bytes
   lodsb
   cmp   al, 0
   jnz   .nonresident
; resident
   lodsw
   movzx   edx, ax
   xchg   ax, cx
   mov   di, bx
   rep   movsb
   ret
.nonresident:
; nonresident :-)
   xor   edx, edx
.loop:
   lodsd
   xchg   ecx, eax
   jecxz   .loopend
   lodsd
   xchg   edi, eax
; read ecx clusters from cluster edi to es:bx
.intloop:
   push   ecx
; read 1 cluster from physical cluster edi to es:bx
   mov   ecx, [cluster_size]
   mov   eax, edi
   mul   ecx
   push   bx
   call   relative_read
   pop   bx
   pop   ecx
   inc   edi
   mov   eax, [cluster_size]
   add   edx, eax
   shr   eax, 4
   mov   bp, es
   add   bp, ax
   mov   es, bp
   loop   .intloop
   jmp   .loop
.loopend:
   mov   es, cx
   ret

read_file_record:
; in: eax=index of record, bx=buffer
   mov   si, 700h
   mov   ecx, [frs_size]
   mul   ecx
   push   bx
   push   [cur_obj]
   mov   [cur_obj], mft_string
   call   read_attr
   pop   [cur_obj]
   pop   di
   call   restore_usa
   ret
read_attr:
; in: edx:eax=offset in bytes, ecx=size in bytes, bx=buffer, si=attribute
   push   invalid_read_request_string
   cmp   byte [si], 0
   jnz   .nonresident
   test   edx, edx
   jnz   find_error_sp
   cmp   eax, 10000h
   jae   find_error_sp
   cmp   ecx, 10000h
   jae   find_error_sp
   cmp   ax, [si+2]
   jae   find_error_sp
   cmp   cx, [si+2]
   ja   find_error_sp
   add   si, 3
   add   si, ax
   mov   di, bx
   rep   movsb
   pop   ax
   ret
.nonresident:
   mov   edi, [cluster_size]
   div   edi
   mov   [ofs], dx
   add   cx, dx
   push   eax
   xchg   eax, ecx
   xor   edx, edx
   dec   eax
   div   edi
   inc   eax
   xchg   eax, ecx
   pop   eax
   add   si, 1
   xor   edx, edx
   push   bx
; eax=offset in clusters, ecx=size in clusters
.scan:
   mov   ebx, [si]
   test   ebx, ebx
   jz   .notfound
   add   edx, ebx
   add   si, 8
   cmp   eax, edx
   jae   .scan
   mov   edi, [si-4]
; now edx=end of block, ebx=length of block, edi=start of block on disk
; eax=required offset, ecx=required length
   push   edx
   push   edi
   sub   edx, eax
   add   edi, ebx
   sub   edi, edx
   cmp   edx, ecx
   jb   @f
   mov   edx, ecx
@@:
; read (edx) clusters from (edi=disk offset in clusters) to ([esp+8])
   cmp   [ofs], 0
   jnz   .ofs_read
.cont:
   pushad
   movzx   ebx, byte [50Dh]
;       xchg    eax, edx
;       mul     ebx
   xchg   ax, dx
   mul   bx
   xchg   cx, ax
   xchg   eax, edi
   mul   ebx
   mov   bx, [esp+8+20h]
   call   relative_read
   mov   [esp+8+20h], bx
   popad
.cont2:
   add   eax, edx
   sub   ecx, edx
.cont3:
   pop   edi
   pop   edx
   jnz   .scan
   pop   bx
   pop   ax
   ret
.ofs_read:
   push   ecx
   movzx   ecx, byte [50Dh]   ; bpb_sects_per_clust
   mov   eax, edi
   push   edx
   mul   ecx
   push   1000h
   pop   es
   xor   bx, bx
   call   relative_read
   mov   cx, bx
   push   si
   push   di
   mov   si, [ofs]
   mov   di, [esp+8+12]
   sub   cx, si
   push   ds
   push   es
   pop   ds
   pop   es
   rep   movsb
   mov   [esp+8+12], di
   push   es
   pop   ds
   pop   di
   pop   si
   pop   edx
   pop   ecx
   inc   edi
   mov   [ofs], 0
   inc   eax
   dec   ecx
   jz   .cont3
   dec   edx
   jnz   .cont
   jmp   .cont2
.notfound:
   mov   si, invalid_read_request_string
   jmp   find_error_si

ntfs_parse_dir:
; in: eax=directory iRecord, [word sp+2]=filename
; out: si=$DATA attribute of file
   mov   bx, [free]
   mov   [dir], bx
   push   bx
   call   read_file_record
   mov   ax, word [frs_size]
   add   [free], ax
   pop   di
; find attributes $INDEX_ROOT, $INDEX_ALLOCATION, $BITMAP
   mov   ax, 90h    ; $INDEX_ROOT
   push   di
   mov   bx, [free]
   mov   [index_root], bx
   call   load_attr
   mov   si, noindex_string
   jc   find_error_si
   mov   [free], bx
   pop   di
   mov   ax, 0A0h   ; $INDEX_ALLOCATION
   mov   bx, [free]
   mov   [index_alloc], bx
   call   load_attr
   jnc   @f
   mov   [index_alloc], 0
@@:
   mov   [free], bx
; search for entry
   mov   si, [index_root]
   mov   bx, [free]
   call   read_attr_full
   mov   ebp, [bx+8]   ; subnode_size
   add   bx, 10h
.scan_record:
   add   bx, [bx]
.scan:
   test   byte [bx+0Ch], 2
   jnz   .not_found
   mov   si, [esp+2]
   movzx   cx, byte [bx+50h]   ; namelen
   lea   di, [bx+52h]      ; name
   xor   ax, ax
@@:
   lodsb
   cmp   al, 'a'
   jb   .notletter
   cmp   al, 'z'
   ja   .notletter
   or   byte [di], 20h
.notletter:
   scasw
   loopz   @b
   jz   .file_found
   jb   .not_found
   add   bx, [bx+8]
   jmp   .scan
.not_found:
   test   byte [bx+0Ch], 1
   jz   file_not_found
   cmp   [index_alloc], 0
   jz   file_not_found
   add   bx, [bx+8]
   mov   eax, [bx-8]
   mul   [cluster_size]
   mov   si, [index_alloc]
   mov   ecx, ebp
   mov   bx, [free]
   call   read_attr
   mov   di, [free]
   call   restore_usa
   mov   bx, [free]
   add   bx, 18h
   jmp   .scan_record
.file_found:
   mov   si, [esp+2]
   mov   [cur_obj], si
   mov   si, directory_string
   test   byte [bx+48h+3], 10h   ; directory?
   jnz   find_error_si
; read entry
   mov   eax, [bx]
   mov   bx, [dir]
   mov   [free], bx
   mov   bx, 4000h
   push   bx
   call   read_file_record
   pop   di
   mov   ax, 80h
   push   2000h
   pop   es
   xor   bx, bx
   call   load_attr
   mov   si, nodata_string
   jz   find_error_si
   mov   [free], bx
   ret   2

Here is fat.inc
Code:
fat32_parse_dir:
; in: eax=directory cluster
; out: eax=entry cluster
   mov   bx, 900h
   mov   di, bx
   push   eax
   call   read_cluster
   mov   cx, word [cluster_size]
   shr   cx, 5      ; div 20h
.scan_cluster:
   pop   eax
   cmp   byte [di], 0
   jz   file_not_found
   mov   si, [esp+2]
   push   eax
   call   fat_compare_name
   jz   .file_found
   and   di, not 1Fh
   add   di, 20h
   loop   .scan_cluster
   pop   eax
   call   next_cluster
   jnc   file_not_found
   jc   fat32_parse_dir
.file_found:
   pop   eax
   mov   si, [esp+2]
   mov   [cur_obj], si
   and   di, not 1Fh
   mov   si, directory_string
   test   byte [di+0Bh], 10h
   jnz   find_error_si
   mov   ax, [di+14h]
   shl   eax, 10h
   mov   ax, [di+1Ah]
   test   eax, eax
   mov   si, nodata_string
   jz   find_error_si
   ret   2

fat_compare_name:
   push   cx
   mov   cx, 9
.scan:
   lodsb
   cmp   al, '.'
   jz   .ext
   cmp   al, 0
   jz   .nameend
   cmp   al, 'a'
   jb   .notletter
   cmp   al, 'z'
   ja   .notletter
   or   byte [di], 20h
.notletter:
   scasb
   loopz   .scan
.notfound:
   inc   cx   ; to clear ZF flag
   pop   cx
   ret
.ext:
   mov   al, ' '
   dec   cx
   repz   scasb
   jnz   .notfound
   test   di, 1
   jnz   .notfound
   mov   cx, 4
   jmp   .scan
.nameend:
   mov   al, ' '
   dec   cx
   repz   scasb
   jnz   .notfound
   test   di, 1
   jnz   .file_found
   mov   cx, 3
   repz   scasb
   jnz   .notfound
.file_found:
   xor   cx, cx   ; to set ZF flag
   pop   cx
   ret

read_cluster:
; in: eax=cluster,bx->buffer
   and   eax, 0FFFFFFFh
   movzx   ecx, byte [50Dh]   ; sects_per_clust
   mul   ecx
   add   eax, [data_start]
;   call   read
;   ret
   jmp   relative_read
next_cluster:
   mov   bx, 700h
; sector is 200h bytes long, one entry in FAT occupies 4 bytes => 80h entries in sector
   push   eax
   shr   eax, 7      ; div 80h
   cmp   eax, [fat_cur_sector]
   jz   @f
   mov   [fat_cur_sector], eax
   add   eax, [fat_start]
   mov   cx, 1
   call   read
@@:
   pop   eax
   and   eax, 7Fh
   mov   eax, [700h+eax*4]
   and   eax, 0FFFFFFFh
   cmp   eax, 0FFFFFF7h
   mov   si, bad_cluster_string
   jz   find_error_si
   ret

Author:  Alboin [ Wed Feb 07, 2007 6:41 pm ]
Post subject: 

Brynet-Inc wrote:
...Not sure why anyone would implement Minix's file system Alboin :?


Well, I figured it's well documented, and shouldn't be too hard to implement. Moreover, it's probably a little better than FATx. (x being whatever you want it to be.) And well.....that's all really..... Just a suggestion....Besides, it's just about as useful as UFS.

Author:  frank [ Wed Feb 07, 2007 7:27 pm ]
Post subject: 

I know a winmodem won't work on linux, thats why I can't get linux, I don't have enough money for a real modem.

@Dex
Thanks for the code, I will try to look though it when I get the time

Page 1 of 2 All times are UTC - 6 hours
Powered by phpBB © 2000, 2002, 2005, 2007 phpBB Group
http://www.phpbb.com/