Index: kernel/trunk/fs/ext2.inc
===================================================================
--- kernel/trunk/fs/ext2.inc	(revision 3700)
+++ kernel/trunk/fs/ext2.inc	(working copy)
@@ -10,6 +10,11 @@
 
 $Revision$
 
+; For fs_type.
+FS_TYPE_UNDEFINED    = 0
+FS_TYPE_EXT	     = 2
+
+; Some set inodes.
 EXT2_BAD_INO         = 1
 EXT2_ROOT_INO        = 2
 EXT2_ACL_IDX_INO     = 3
@@ -17,36 +22,70 @@
 EXT2_BOOT_LOADER_INO = 5
 EXT2_UNDEL_DIR_INO   = 6
 
-;RUS: флаги, указываемые в inode файла   ;ENG: flags specified in file inode
-EXT2_S_IFREG         = 0x8000
-EXT2_S_IFDIR         = 0x4000
-EXT2_S_IFMT          = 0xF000 ;RUS: маска для типа файла  ;ENG: mask for file type
+; EXT2_SUPER_MAGIC.
+EXT2_SUPER_MAGIC     = 0xEF53
+EXT2_VALID_FS	     = 1
 
-;RUS: флаги, указываемые в linked list родительской папки
-;ENG: flags specified in linked list of parent folder
-EXT2_FT_REG_FILE     = 1     ;RUS: это файл, запись в родительском каталоге
-                             ;ENG: this is a file, record in parent catalog
-EXT2_FT_DIR          = 2     ;RUS: это папка   ;ENG: this is a folder
+; Flags defining i_mode values.
+EXT2_S_IFMT          = 0xF000        ; Mask for file type.
 
-;RUS: флаги используемые KolibriOS   ;ENG: flags used by KolibriOS
+EXT2_S_IFREG         = 0x8000        ; Regular file.
+EXT2_S_IFDIR         = 0x4000        ; Directory.
+
+; File type defining values in directory entry.
+EXT2_FT_REG_FILE     = 1        ; Regular file.
+EXT2_FT_DIR          = 2            ; Directory.
+
+; Flags used by KolibriOS.
 FS_FT_HIDDEN         = 2
-FS_FT_DIR            = 0x10  ;RUS: это папка      ;ENG: this is a folder
-FS_FT_ASCII          = 0     ;RUS: имя в ascii    ;ENG: name in ASCII
-FS_FT_UNICODE        = 1     ;RUS: имя в unicode  ;ENG: name in UNICODE
+FS_FT_DIR            = 0x10         ; Directory.
 
-EXT2_FEATURE_INCOMPAT_FILETYPE = 0x0002 ;RUS: тип файла должен указываться в директории
-                                        ;ENG: file type must be specified in the folder
-EXT4_FEATURE_INCOMPAT_EXTENTS  = 0x0040 ;RUS: экстенты   ;ENG: extents
-EXT4_FEATURE_INCOMPAT_FLEX_BG  = 0x0200 ;RUS: гибкие группы блоков   ;ENG: flexible block groups
+; ext2 partition flags.
+EXT2_RO              = 0x01
 
-;RUS: реализованные ext[234] features   ;ENG: implemented ext[234] features
+FS_FT_ASCII          = 0            ; Name in ASCII.
+FS_FT_UNICODE        = 1            ; Name in Unicode.
+
+EXT2_FEATURE_INCOMPAT_FILETYPE = 0x0002        ; Have file type in directory entry.
+EXT4_FEATURE_INCOMPAT_EXTENTS  = 0x0040 ; Extents.
+EXT4_FEATURE_INCOMPAT_FLEX_BG  = 0x0200 ; Flexible block groups.
+
+EXT2_FEATURE_RO_COMPAT_SPARSE_SUPER = 0x0001 ; Sparse Superblock
+EXT2_FEATURE_RO_COMPAT_LARGE_FILE   = 0x0002 ; Large file support (64-bit file size)
+
+; Implemented ext[2,3,4] features.
 EXT4_FEATURE_INCOMPAT_SUPP = EXT2_FEATURE_INCOMPAT_FILETYPE \
-                          or EXT4_FEATURE_INCOMPAT_EXTENTS \
-                          or EXT4_FEATURE_INCOMPAT_FLEX_BG
+                             or EXT4_FEATURE_INCOMPAT_EXTENTS \
+                             or EXT4_FEATURE_INCOMPAT_FLEX_BG
 
-;RUS: флаги, указываемые для inode в i_flags   ;ENG: flags specified for inode in i_flags
-EXT2_EXTENTS_FL      = 0x00080000
+; Implemented features which otherwise require "read-only" mount.
+EXT2_FEATURE_RO_COMPAT_SUPP = EXT2_FEATURE_RO_COMPAT_SPARSE_SUPER \
+                              or EXT2_FEATURE_RO_COMPAT_LARGE_FILE
 
+; ext4 features not support for write.
+EXT4_FEATURE_INCOMPAT_W_NOT_SUPP = EXT4_FEATURE_INCOMPAT_EXTENTS \
+                                   or EXT4_FEATURE_INCOMPAT_FLEX_BG
+
+; Flags specified in i_flags.
+EXT2_EXTENTS_FL      = 0x00080000        ; Extents.
+
+; Helper macros.
+macro KERNEL_ALLOC store, label
+{
+        call    kernel_alloc
+        mov     store, eax
+        test    eax, eax    
+        jz      label   
+}
+
+macro KERNEL_FREE data, label
+{
+        cmp     data, 0
+        jz      label
+        push    data
+        call    kernel_free
+}
+
 struct  EXT2_INODE_STRUC
         i_mode          dw ?
         i_uid           dw ?
@@ -65,7 +104,7 @@
         i_file_acl      dd ?
         i_dir_acl       dd ?
         i_faddr         dd ?
-        i_osd2          dd ? ; 1..12
+        i_osd2          dd ?        ; 12 bytes.
 ends
 
 struct  EXT2_DIR_STRUC
@@ -73,153 +112,172 @@
         rec_len         dw ?
         name_len        db ?
         file_type       db ?
-        name            db ? ; 0..255
+        name            db ?         ; 255 (max) bytes.
 ends
 
 struct  EXT2_BLOCK_GROUP_DESC
-        block_bitmap            dd ? ;+0
-        inode_bitmap            dd ? ;+4
-        inode_table             dd ? ;+8
-        free_blocks_count       dw ? ;+12
-        free_inodes_count       dw ? ;+14
-        used_dirs_count         dw ? ;+16
-        pad                     dw ? ;+18
-        reserved                rb 12;+20
+        block_bitmap            dd ?         ; +0
+        inode_bitmap            dd ?         ; +4
+        inode_table             dd ?         ; +8
+        free_blocks_count       dw ?         ; +12
+        free_inodes_count       dw ?         ; +14
+        used_dirs_count         dw ?         ; +16
+        pad                     dw ?         ; +18
+        reserved                rb 12        ; +20
 ends
 
 struct  EXT2_SB_STRUC
-        inodes_count            dd ? ;+0
-        blocks_count            dd ? ;+4
-        r_block_count           dd ? ;+8
-        free_block_count        dd ? ;+12
-        free_inodes_count       dd ? ;+16
-        first_data_block        dd ? ;+20
-        log_block_size          dd ? ;+24
-        log_frag_size           dd ? ;+28
-        blocks_per_group        dd ? ;+32
-        frags_per_group         dd ? ;+36
-        inodes_per_group        dd ? ;+40
-        mtime                   dd ? ;+44
-        wtime                   dd ? ;+48
-        mnt_count               dw ? ;+52
-        max_mnt_count           dw ? ;+54
-        magic                   dw ? ;+56
-        state                   dw ? ;+58
-        errors                  dw ? ;+60
-        minor_rev_level         dw ? ;+62
-        lastcheck               dd ? ;+64
-        check_intervals         dd ? ;+68
-        creator_os              dd ? ;+72
-        rev_level               dd ? ;+76
-        def_resuid              dw ? ;+80
-        def_resgid              dw ? ;+82
-        first_ino               dd ? ;+84
-        inode_size              dw ? ;+88
-        block_group_nr          dw ? ;+90
-        feature_compat          dd ? ;+92
-        feature_incompat        dd ? ;+96
-        feature_ro_compat       dd ? ;+100
-        uuid                    rb 16 ;+104
-        volume_name             rb 16 ;+120
-        last_mounted            rb 64 ;+136
-        algo_bitmap             dd ? ;+200
-        prealloc_blocks         db ? ;+204
-        preallock_dir_blocks    db ? ;+205
-        reserved_gdt_blocks     dw ? ;+206
-        journal_uuid            rb 16 ;+208
-        journal_inum            dd ? ;+224
-        journal_dev             dd ? ;+228
-        last_orphan             dd ? ;+232
-        hash_seed               rd 4 ;+236
-        def_hash_version        db ? ;+252
-                                rb 3 ;+253 reserved
-        default_mount_options   dd ? ;+256
-        first_meta_bg           dd ? ;+260
-        mkfs_time               dd ? ;+264
-        jnl_blocks              rd 17 ;+268
-        blocks_count_hi         dd ? ;+336
-        r_blocks_count_hi       dd ? ;+340
-        free_blocks_count_hi    dd ? ;+344
-        min_extra_isize         dw ? ;+348
-        want_extra_isize        dw ? ;+350
-        flags                   dd ? ;+352
-        raid_stride             dw ? ;+356
-        mmp_interval            dw ? ;+358
-        mmp_block               dq ? ;+360
-        raid_stripe_width       dd ? ;+368
-        log_groups_per_flex     db ? ;+372
+        inodes_count            dd ?         ; +0
+        blocks_count            dd ?         ; +4
+        r_block_count           dd ?         ; +8
+        free_block_count        dd ?        ; +12
+        free_inodes_count       dd ?         ; +16
+        first_data_block        dd ?        ; +20
+        log_block_size          dd ?         ; +24
+        log_frag_size           dd ?         ; +28
+        blocks_per_group        dd ?         ; +32
+        frags_per_group         dd ?         ; +36
+        inodes_per_group        dd ?         ; +40
+        mtime                   dd ?         ; +44
+        wtime                   dd ?         ; +48
+        mnt_count               dw ?         ; +52
+        max_mnt_count           dw ?         ; +54
+        magic                   dw ?         ; +56
+        state                   dw ?         ; +58
+        errors                  dw ?         ; +60
+        minor_rev_level         dw ?         ; +62
+        lastcheck               dd ?         ; +64
+        check_intervals         dd ?         ; +68
+        creator_os              dd ?         ; +72
+        rev_level               dd ?         ; +76
+        def_resuid              dw ?         ; +80
+        def_resgid              dw ?         ; +82
+        first_ino               dd ?         ; +84
+        inode_size              dw ?         ; +88
+        block_group_nr          dw ?         ; +90
+        feature_compat          dd ?         ; +92
+        feature_incompat        dd ?         ; +96
+        feature_ro_compat       dd ?         ; +100
+        uuid                    rb 16         ; +104
+        volume_name             rb 16         ; +120
+        last_mounted            rb 64         ; +136
+        algo_bitmap             dd ?         ; +200
+        prealloc_blocks         db ?         ; +204
+        preallock_dir_blocks    db ?         ; +205
+        reserved_gdt_blocks     dw ?         ; +206
+        journal_uuid            rb 16        ; +208
+        journal_inum            dd ?        ; +224
+        journal_dev             dd ?         ; +228
+        last_orphan             dd ?         ; +232
+        hash_seed               rd 4         ; +236
+        def_hash_version        db ?         ; +252
+        reserved                rb 3         ; +253 (reserved)
+        default_mount_options   dd ?         ; +256
+        first_meta_bg           dd ?         ; +260
+        mkfs_time               dd ?         ; +264
+        jnl_blocks              rd 17         ; +268
+        blocks_count_hi         dd ?         ; +336
+        r_blocks_count_hi       dd ?         ; +340
+        free_blocks_count_hi    dd ?         ; +344
+        min_extra_isize         dw ?         ; +348
+        want_extra_isize        dw ?         ; +350
+        flags                   dd ?         ; +352
+        raid_stride             dw ?         ; +356
+        mmp_interval            dw ?         ; +358
+        mmp_block               dq ?         ; +360
+        raid_stripe_width       dd ?         ; +368
+        log_groups_per_flex     db ?         ; +372
 ends
 
-struct EXT4_EXTENT_HEADER       ;RUS: заголовок блока экстентов/индексов
-        eh_magic        dw ?    ;RUS: в текущей реализации ext4 должно быть 0xF30A
-        eh_entries      dw ?    ;RUS: количество экстентов/индексов в блоке
-        eh_max          dw ?    ;RUS: max количество (используется при записи)
-        eh_depth        dw ?    ;RUS: глубина дерева (0, если это блок экстентов)
-        eh_generation   dd ?    ;???
+; Header block extents.
+struct EXT4_EXTENT_HEADER
+        eh_magic        dw ?    ; Magic value of 0xF30A, for ext4.
+        eh_entries      dw ?    ; Number of blocks covered by the extent.
+        eh_max          dw ?    ; Capacity of entries.
+        eh_depth        dw ?    ; Tree depth (if 0, extents in the array are not extent indexes)
+        eh_generation   dd ?    ; ???
 ends
 
-struct EXT4_EXTENT              ;RUS: экстент            ;ENG: extent
-        ee_block        dd ?    ;RUS: номер ext4 блока   ;ENG: number of ext4 block
-        ee_len          dw ?    ;RUS: длина экстента     ;ENG: extent length
-        ee_start_hi     dw ?    ;RUS: старшие 16 бит 48-битного адреса (пока не используются в KOS)
-                                ;ENG: upper 16 bits of the 48-bit address (not used in KolibriOS yet)
-        ee_start_lo     dd ?    ;RUS: младшие 32 бита 48-битного адреса
-                                ;ENG: lower 32 bits of the 48-bit address
+; Extent.
+struct EXT4_EXTENT
+        ee_block        dd ?    ; First logical block extent covers.
+        ee_len          dw ?    ; Number of blocks covered by extent.
+        ee_start_hi     dw ?    ; Upper 16 bits of 48-bit address (unused in KOS)
+        ee_start_lo     dd ?    ; Lower 32 bits of 48-bit address.
 ends
 
-struct EXT4_EXTENT_IDX          ;RUS: индекс - указатель на блок с экстентами/индексами
-                                ;ENG: index - pointer to block of extents/indexes
-        ei_block        dd ?    ;RUS: номер ext4 блока   ;ENG: number of ext4 block
-        ei_leaf_lo      dd ?    ;RUS: младшие 32 бит 48-битного адреса
-                                ;ENG: lower 32 bits of the 48-bit address
-        ei_leaf_hi      dw ?    ;RUS: старшие 16 бит 48-битного адреса (пока не используются в KOS)
-                                ;ENG: upper 16 bits of the 48-bit address (not used in KolibriOS yet)
-        ei_unused       dw ?    ;RUS: зарезервировано   ;ENG: reserved
+; Index on-disk structure; pointer to block of extents/indexes.
+struct EXT4_EXTENT_IDX
+        ei_block        dd ?    ; Covers logical blocks from here.
+        ei_leaf_lo      dd ?    ; Lower 32-bits of pointer to the physical block of the next level. 
+        ei_leaf_hi      dw ?    ; Higher 16-bits (unused in KOS).
+        ei_unused       dw ?    ; Reserved.
 ends
 
+;---------------------------------------------------------------------
+; Check if it's a valid ext* superblock.
+; Input:        ebx = buffer;
+; Output:       carry clear if valid EXT2 superblock; set otherwise;
+;---------------------------------------------------------------------
 ext2_test_superblock:
+        ; 0x83 -> linux native filesystem (ext2fs)
         cmp     [fs_type], 0x83
-        jne     .no
+        jne     @F
 
+        ; Reading superblock starting from 1024 bytes (2nd sector).
         mov     eax, [PARTITION_START]
-        add     eax, 2                  ;superblock start at 1024b
+        add     eax, 2
         call    hd_read
 
-        cmp     [ebx + EXT2_SB_STRUC.log_block_size], 3  ;0,1,2,3
-        ja      .no
-        cmp     [ebx + EXT2_SB_STRUC.magic], 0xEF53
-        jne     .no
-        cmp     [ebx + EXT2_SB_STRUC.state], 1        ;EXT_VALID_FS=1
-        jne     .no
+        cmp     [hd_error], 0
+        jne     @F
+
+        ; Allowed 1KiB, 2KiB, 4KiB, 8KiB.
+        cmp     [ebx + EXT2_SB_STRUC.log_block_size], 3  
+        ja      @F
+
+        cmp     [ebx + EXT2_SB_STRUC.magic], EXT2_SUPER_MAGIC
+        jne     @F
+
+        cmp     [ebx + EXT2_SB_STRUC.state], EXT2_VALID_FS
+        jne     @F
+
+        ; Can't have no inodes per group.
         cmp     [ebx + EXT2_SB_STRUC.inodes_per_group], 0
-        je      .no
-        
-        mov     eax, [ebx + EXT2_SB_STRUC.feature_incompat]
-        test    eax, EXT2_FEATURE_INCOMPAT_FILETYPE
-        jz      .no
+        je      @F
+
+        ; If incompatible features required, unusable superblock.
+        mov     eax, [ebx + EXT2_SB_STRUC.feature_incompat] 
         test    eax, not EXT4_FEATURE_INCOMPAT_SUPP
-        jnz     .no
+        jnz     @F
 
-    ; OK, this is correct EXT2 superblock
+        ; Clear carry to indicate EXT2 superblock.
         clc
         ret
-   .no:
-    ; No, this superblock isn't EXT2
+    @@:
+        ; Not a (valid/usable) EXT2 superblock.
         stc
         ret
 
+;---------------------------------------------------------------------
+; Setup ext2/3/4.
+; Input:        ebx = buffer;
+;---------------------------------------------------------------------
 ext2_setup:
-        mov     [fs_type], 2
+        mov     [fs_type], FS_TYPE_EXT
 
         push    512
-        call    kernel_alloc                            ; mem for superblock
+        KERNEL_ALLOC [ext2_data.sb], .error
+
+        ; Copy superblock from buffer to reserved memory.
         mov     esi, ebx
         mov     edi, eax
         mov     ecx, 512/4
-        rep movsd                                       ; copy sb to reserved mem
+        rep movsd
+
         mov     ebx, eax
-        mov     [ext2_data.sb], eax
 
+        ; Get total groups.
         mov     eax, [ebx + EXT2_SB_STRUC.blocks_count]
         sub     eax, [ebx + EXT2_SB_STRUC.first_data_block]
         dec     eax
@@ -228,85 +286,157 @@
         inc     eax
         mov     [ext2_data.groups_count], eax
 
+        ; Get log(block_size), such that 1,2,3,4 equ 1KiB,2KiB,4KiB,8KiB.
         mov     ecx, [ebx + EXT2_SB_STRUC.log_block_size]
         inc     ecx
-        mov     [ext2_data.log_block_size], ecx    ; 1, 2, 3, 4   equ 1kb, 2kb, 4kb, 8kb
+        mov     [ext2_data.log_block_size], ecx
 
+        ; 512-byte blocks in ext2 blocks.
         mov     eax, 1
         shl     eax, cl
         mov     [ext2_data.count_block_in_block], eax
 
+        ; Get block_size/4 (we'll find square later).
         shl     eax, 7
         mov     [ext2_data.count_pointer_in_block], eax
-        mov     edx, eax   ;RUS: потом еще квадрат найдем   ;ENG: we'll find a square later
+        mov     edx, eax
 
+        ; Get block size.
         shl     eax, 2
         mov     [ext2_data.block_size], eax
 
-        push    eax eax                                 ; 2 kernel_alloc
+        ; Save block size for 2 kernel_alloc calls.
+        push    eax eax
 
         mov     eax, edx
         mul     edx
         mov     [ext2_data.count_pointer_in_block_square], eax
 
-        call    kernel_alloc
-        mov     [ext2_data.ext2_save_block], eax        ; and for temp block
-        call    kernel_alloc
-        mov     [ext2_data.ext2_temp_block], eax        ; and for get_inode proc
+        ; Have temporary block storage for get_inode procedure, and one for global procedure.
+        KERNEL_ALLOC [ext2_data.ext2_save_block], .error
+        KERNEL_ALLOC [ext2_data.ext2_temp_block], .error
+        
+        mov     [ext2_data.partition_flags], 0x00000000
+        mov     eax, [ebx + EXT2_SB_STRUC.feature_ro_compat]
+        and     eax, not EXT2_FEATURE_RO_COMPAT_SUPP
+        jnz     .read_only
 
+        mov     eax, [ebx + EXT2_SB_STRUC.feature_incompat]
+        and     eax, EXT4_FEATURE_INCOMPAT_W_NOT_SUPP
+        jz      @F
+
+    .read_only:
+        ; Mark as read-only.
+        or      [ext2_data.partition_flags], EXT2_RO
+    @@:
         movzx   ebp, word [ebx + EXT2_SB_STRUC.inode_size]
         mov     ecx, [ebx + EXT2_SB_STRUC.blocks_per_group]
 
         mov     [ext2_data.inode_size], ebp
         mov     [ext2_data.blocks_per_group], ecx
+	
+        ; Allocate for three inodes (loop would be overkill).
+        push    ebp ebp ebp
 
-        push    ebp ebp ebp                             ;3 kernel_alloc
-        call    kernel_alloc
-        mov     [ext2_data.ext2_save_inode], eax
-        call    kernel_alloc
-        mov     [ext2_data.ext2_temp_inode], eax
-        call    kernel_alloc
-        mov     [ext2_data.root_inode], eax
-
+        KERNEL_ALLOC [ext2_data.ext2_save_inode], .error
+        KERNEL_ALLOC [ext2_data.ext2_temp_inode], .error
+        KERNEL_ALLOC [ext2_data.root_inode], .error
+	
+        ; Read root inode.
         mov     ebx, eax
         mov     eax, EXT2_ROOT_INO
-        call    ext2_get_inode                          ; read root inode
+        call    ext2_get_inode
 
+	test	eax, eax
+	jnz	.error
+
         jmp     return_from_part_set
 
-;==================================================================
-;read ext2 block form FS to memory
-;in:  eax = i_block (address of block in ext2 terms)
-;     ebx = pointer to return memory
-;out: eax - error code (0 = no_error)
+    ; Error in setting up.
+    .error:
+	mov	[fs_type], FS_TYPE_UNDEFINED
+        
+        ; Free super-block memory.
+        KERNEL_FREE [ext2_data.sb], return_from_part_set
+
+        ; Free save block.
+        KERNEL_FREE [ext2_data.ext2_save_block], return_from_part_set
+
+        ; Temporary block.
+        KERNEL_FREE [ext2_data.ext2_temp_block], return_from_part_set
+
+        ; All inodes.
+        KERNEL_FREE [ext2_data.ext2_save_inode], return_from_part_set
+        KERNEL_FREE [ext2_data.ext2_temp_inode], return_from_part_set
+        KERNEL_FREE [ext2_data.root_inode], return_from_part_set
+
+        jmp	return_from_part_set
+
+;---------------------------------------------------------------------
+; Write ext2 block from memory to disk.
+; Input:        eax = i_block (block number in ext2 terms);
+;               ebx = buffer address
+; Output:       eax = error code (0 implies no error)
+;---------------------------------------------------------------------
+ext2_write_block:
+        push    edx ebx ecx
+
+        mov     edx, hd_write
+        jmp     ext2_modify_block
+
+;---------------------------------------------------------------------
+; Read ext2 block from disk to memory.
+; Input:        eax = i_block (block number in ext2 terms);
+;               ebx = address of where to read block
+; Output:       eax = error code (0 implies no error)
+;---------------------------------------------------------------------
 ext2_get_block:
-        push    ebx ecx
+        push    edx ebx ecx
+        
+        mov     edx, hd_read
+        jmp     ext2_modify_block      
+
+;---------------------------------------------------------------------
+; Modify ext2 block.
+; Input:        eax = i_block (block number in ext2 terms);
+;               ebx = I/O buffer address;
+;               edx = hd_write/hd_write
+;               edx, ebx, ecx on stack.
+; Output:       eax = error code (0 implies no error)
+;---------------------------------------------------------------------
+ext2_modify_block:
+        ; Get block number in hard-disk terms in eax.
         mov     ecx, [ext2_data.log_block_size]
         shl     eax, cl
         add     eax, [PARTITION_START]
         mov     ecx, [ext2_data.count_block_in_block]
+
     @@:
-        call    hd_read
+        call    edx
         cmp     [hd_error], 0
         jnz     .fail
+        
         inc     eax
         add     ebx, 512
         loop    @B
+        
         xor     eax, eax
     @@:
-        pop     ecx ebx
+        pop     ecx ebx edx
         ret
+
     .fail:
         mov     eax, ERROR_DEVICE
         jmp     @B
-        
 
-;===================================================================
-;RUS: получает номер блока из extent inode                    ;ENG: receives block number from extent inode
-;RUS: in:  ecx = номер блока по порядку                       ;ENG: in:  ecx = consecutive block number
-;RUS:      ebp = адрес extent header`а                        ;ENG:      ebp = address of extent header
-;RUS: out: ecx - адрес очередного блока в случае успеха       ;ENG: out: ecx - address of next block, if successful
-;RUS:      eax - номер ошибки (если равно 0, то ошибки нет)   ;ENG:      eax - error number (0 - no error)
+; KSOC_EXT2_WRITE_END_TODO: clean this up.
+;---------------------------------------------------------------------
+; Receives block number from extent-based inode.
+; Input:        ecx = number of block in inode
+;               ebp = address of extent header
+; Output:       ecx = address of next block, if successful
+;               eax = error code (0 implies no error)
+;---------------------------------------------------------------------
 ext4_block_recursive_search:
         cmp     word [ebp + EXT4_EXTENT_HEADER.eh_magic], 0xF30A ;EXT4_EXT_MAGIC
         jne     .fail
@@ -375,52 +505,61 @@
         mov     eax, ERROR_FS_FAIL
         ret
 
-;===================================================================
-;получает адрес ext2 блока из inode с определнным номером
-;RUS: in:  ecx = номер блока в inode (0..)   ;ENG: in:  ecx = number of block in inode (0..)
-;RUS:      ebp = адрес inode                 ;ENG:      ebp = inode address
-;RUS: out: ecx = адрес очередного блока      ;ENG: out: ecx = next block address
-;RUS:      eax - error code                  ;ENG:      eax - error code
+;---------------------------------------------------------------------
+; Receives block number from indirect-addressing inode.
+; Input:        ecx = number of block in inode
+;               ebp = address of inode
+; Output:       ecx = address of next block, if successful
+;               eax = error code (0 implies no error)
+;---------------------------------------------------------------------
 ext2_get_inode_block:
+        ; If inode is extent-based, use ext4_block_recursive_search.
         test    [ebp + EXT2_INODE_STRUC.i_flags], EXT2_EXTENTS_FL
         jz      @F
 
         pushad
-        add     ebp, EXT2_INODE_STRUC.i_block             ;ebp - extent_header
+
+        ; Get extent header in EBP.
+        add     ebp, EXT2_INODE_STRUC.i_block
         call    ext4_block_recursive_search
         mov     PUSHAD_ECX, ecx
         mov     PUSHAD_EAX, eax
+
         popad
         ret
 
     @@:
-        cmp     ecx, 12                                         ; 0..11 - direct block address
+        ; 0 to 11: direct blocks.
+        cmp     ecx, 12
         jb      .get_direct_block
 
+        ; Indirect blocks
         sub     ecx, 12
-        cmp     ecx, [ext2_data.count_pointer_in_block]         ; 12.. - indirect blocks
+        cmp     ecx, [ext2_data.count_pointer_in_block] 
         jb      .get_indirect_block
 
+        ; Double indirect blocks.
         sub     ecx, [ext2_data.count_pointer_in_block]
         cmp     ecx, [ext2_data.count_pointer_in_block_square]
         jb      .get_double_indirect_block
 
-        sub     ecx, [ext2_data.count_pointer_in_block_square]
-    ;triple indirect block
+        ; Triple indirect blocks.
+	sub     ecx, [ext2_data.count_pointer_in_block_square]
         push    edx ebx
 
+        ; Get triply-indirect block in temp_block.
         mov     eax, [ebx + EXT2_INODE_STRUC.i_block + 14*4]
         mov     ebx, [ext2_data.ext2_temp_block]
         call    ext2_get_block
         test    eax, eax
         jnz     .fail
 
+        ; Get index in triply-indirect block.
         xor     edx, edx
         mov     eax, ecx
         div     [ext2_data.count_pointer_in_block_square]
 
-    ;RUS: eax - номер в полученном блоке   edx - номер дальше
-    ;ENG: eax - current block number, edx - next block number
+        ; eax: index in triply-indirect block, edx: index in doubly-indirect block.
         mov     eax, [ebx + eax*4]
         call    ext2_get_block
         test    eax, eax
@@ -432,6 +571,7 @@
     .get_double_indirect_block:
         push    edx ebx
 
+        ; Get doubly-indirect block.
         mov     eax, [ebp + EXT2_INODE_STRUC.i_block + 13*4]
         mov     ebx, [ext2_data.ext2_temp_block]
         call    ext2_get_block
@@ -443,6 +583,7 @@
         xor     edx, edx
         div     [ext2_data.count_pointer_in_block]
 
+        ; eax: index in doubly-indirect block, edx: index in indirect block.
         mov     eax, [ebx + eax*4]
         call    ext2_get_block
         test    eax, eax
@@ -455,13 +596,16 @@
 
     .get_indirect_block:
         push    ebx
+
+        ; Get index of indirect block.
         mov     eax, [ebp + EXT2_INODE_STRUC.i_block + 12*4]
         mov     ebx, [ext2_data.ext2_temp_block]
         call    ext2_get_block
         test    eax, eax
-        jnz     @F          ;RUS: если не было ошибки   ;ENG: if there was no error
-
-        mov     ecx, [ebx + ecx*4]   ;RUS: заносим результат   ;ENG: ???
+        jnz     @F
+	
+        ; Get the block ID.
+        mov     ecx, [ebx + ecx*4]
     @@:
         pop     ebx
         ret
@@ -471,93 +615,98 @@
         xor     eax, eax
         ret
 
-;===================================================================
-;get content inode by num
-;in:  eax = inode_num
-;     ebx = address of inode content
-;out: eax - error code
+;---------------------------------------------------------------------
+; Get content of inode by number.
+; Input:        eax = inode number.
+;               ebx = address where to store inode content.
+; Output:       eax = error code (0 implies no error)
+;---------------------------------------------------------------------
 ext2_get_inode:
         pushad
-        mov     edi, ebx   ;сохраним адрес inode
+
+        mov     edi, ebx                        ; Save the address where to store the inode.
         dec     eax
         xor     edx, edx
         
         mov     ecx, [ext2_data.sb]
+        ; EAX = block group.
         div     [ecx + EXT2_SB_STRUC.inodes_per_group]
 
-        push    edx                             ;locale num in group
+        push    edx                             ; Index in group.
 
         mov     edx, 32
-        mul     edx                             ; address block_group in global_desc_table
+        mul     edx                             ; Get index of descriptor in global_desc_table.
 
-        ;RUS: в eax - смещение группы с inode-ом относительно начала глобальной дескрипторной таблицы
-        ;RUS: найдем блок в котором он находится
-        ;ENG: in eax - inode group offset relative to global descriptor table start
-        ;ENG: let's find the block this inode is in
+        ; eax: inode group offset relative to global descriptor table start
+        ; Find the block this inode is in.
         div     [ext2_data.block_size]
         add     eax, [ecx + EXT2_SB_STRUC.first_data_block]
         inc     eax
         mov     ebx, [ext2_data.ext2_temp_block]
         call    ext2_get_block
         test    eax, eax
-        jnz     .fail     
+        jnz     .return     
 
-        add     ebx, edx   ;RUS: локальный номер в блоке   ;ENG: local number inside block
-        mov     eax, [ebx + EXT2_BLOCK_GROUP_DESC.inode_table]   ;RUS: номер блока - в терминах ext2
-                                                                 ;ENG: block number - in ext2 terms
+        add     ebx, edx                        ; edx: local number of descriptor inside block
+        mov     eax, [ebx + EXT2_BLOCK_GROUP_DESC.inode_table]   ; Block number of inode table - in ext2 terms.
         mov     ecx, [ext2_data.log_block_size]
         shl     eax, cl
-        add     eax, [PARTITION_START]          ;RUS: а старт раздела - в терминах hdd (512)
-                                                ;ENG: partition start - in HDD terms (512)
-        ;RUS: eax - указывает на таблицу inode-ов на hdd   ;ENG: eax - points to inode table on HDD
-        mov     esi, eax   ;RUS: сохраним его пока в esi   ;ENG: let's save it in esi for now
+        add     eax, [PARTITION_START]          
 
-        ;RUS: прибавим локальный адрес inode-а   ;ENG: add local address of inode
-        pop     eax                             ; index
+        ; eax: points to inode table on HDD.
+        mov     esi, eax
+
+        ; Add local address of inode.
+        pop     eax
         mov     ecx, [ext2_data.inode_size]
         mul     ecx                             ; (index * inode_size)
+        
         mov     ebp, 512
-        div     ebp        ;RUS: поделим на размер блока        ;ENG: divide by block size
+        div     ebp                             ; Divide by block size.
 
-        add     eax, esi   ;RUS: нашли адрес блока для чтения   ;ENG: found block address to read
+        add     eax, esi                        ; Found block to read.
         mov     ebx, [ext2_data.ext2_temp_block]
         call    hd_read
         cmp     [hd_error], 0
-        jnz     .fail
+        jz      @F
 
-        mov     esi, edx         ;RUS: добавим "остаток"   ;ENG: add the "remainder"
-        add     esi, ebx         ;RUS: к адресу            ;ENG: to the address
-        rep movsb                ;RUS: копируем inode      ;ENG: copy inode
+        mov     eax, ERROR_DEVICE
+        jmp     .return
+
+    @@:
+        mov     esi, edx                        ; The "remainder" is the inode address in the sector.
+        add     esi, ebx
+        rep movsb
+
         xor     eax, eax
-    .fail:
+    .return:
         mov     PUSHAD_EAX, eax
         popad
         ret
 
-;----------------------------------------------------------------
-;
-;  ext2_HdReadFolder - read disk folder
-;
-;  esi  points to filename
-;  ebx  pointer to structure 32-bit number = first wanted block, 0+
-;                          & flags (bitfields)
-; flags: bit 0: 0=ANSI names, 1=UNICODE names
-;  ecx  number of blocks to read, 0+
-;  edx  mem location to return data
-;
-;  ret ebx = blocks read or 0xffffffff folder not found
-;      eax = 0 ok read or other = errormsg
-;
-;--------------------------------------------------------------
+;---------------------------------------------------------------------
+; Read disk folder.
+; Input:        esi = file name.
+;               ebx = pointer to structure.
+;                       +0: first wanted block.
+;                       +4: flags, bit 0: 0=ANSI, 1=UNICODE names.
+;               ecx = number of blocks to read (0+).
+;               edx = mem location to return data.
+; Output:       ebx = blocks read (or 0xFFFFFFFF, folder not found)
+;               eax = error code (0 implies no error)
+;---------------------------------------------------------------------
 ext2_HdReadFolder:
         cmp     byte [esi], 0
         jz      .root_folder
 
         push    ebx ecx edx
-        call    ext2_find_lfn               ;вернет в ebp адрес inode
+        call    ext2_find_lfn                           ; Get inode.
         pop     edx ecx ebx
+
         test    eax, eax
         jnz     .error_ret
+
+        ; If not a directory, then return with error.
         test    [ebp + EXT2_INODE_STRUC.i_mode], EXT2_S_IFDIR
         jz      .error_not_found
         jmp     @F
@@ -566,78 +715,85 @@
         mov     ebp, [ext2_data.root_inode]
         test    [ebp + EXT2_INODE_STRUC.i_mode], EXT2_S_IFDIR
         jz      .error_root
-        ;придется копировать inode
+
+        ; Copy the inode.
         push    ecx
         mov     esi, ebp
+
         mov     edi, [ext2_data.ext2_save_inode]
         mov     ecx, [ext2_data.inode_size]
         shr     ecx, 2
         mov     ebp, edi
         rep movsd
+
         pop     ecx
     @@:
-        cmp     [ebp + EXT2_INODE_STRUC.i_size], 0 ;папка пуста
+        cmp     [ebp + EXT2_INODE_STRUC.i_size], 0      ; Folder is empty.
         je      .error_empty_dir
         
-        push    edx      ;адрес результата              [edi + 28]
-        push    0        ;конец очередного блока папки   [edi + 24]
-        push    ecx      ;сколько файлов нужно прочитать [edi + 20]
-        push    dword [ebx]   ;первый "нужный" файл           [edi + 16]
-        push    dword [ebx + 4];флаги                        [edi + 12]
-        push    0       ;[EXT2_read_in_folder]     [edi + 8]
-        push    0       ;[EXT2_files_in_folder]    [edi + 4]
-        push    0       ;номер блока по порядку    [edi]
+        push    edx                                     ; Result address [edi + 28].
+        push    0                                       ; End of the current block in folder [edi + 24]
+        push    ecx                                     ; Blocks to read [edi + 20]
+        push    dword [ebx]                             ; The first wanted file [edi + 16]
+        push    dword [ebx + 4]                         ; Flags [edi + 12]
+        push    0                                       ; Read files [edi + 8]
+        push    0                                       ; Files in folder [edi + 4]
+        push    0                                       ; Number of blocks read in dir (and current block index) [edi]
 
+        ; Fill header with zeroes.
         mov     edi, edx
         mov     ecx, 32/4
-        rep stosd                               ; fill header zero
+        rep stosd
         
-        mov     edi, esp                        ; edi - указатель на локальные переменные
-        add     edx, 32                         ; edx = current mem for return
+        mov     edi, esp                                ; edi = pointer to local variables.
+        add     edx, 32                                 ; edx = mem to return.
 
-        xor     ecx, ecx                        ; получим номер первого блока
+        xor     ecx, ecx                                ; Get number of first block.
         call    ext2_get_inode_block
         test    eax, eax
         jnz     .error_get_block
 
         mov     eax, ecx
         mov     ebx, [ext2_data.ext2_save_block]
-        call    ext2_get_block                  ; и считываем блок с hdd
+        call    ext2_get_block                          ; Read the block.
         test    eax, eax
         jnz     .error_get_block
 
-        mov     esi, ebx                         ; esi = current dir record
+        mov     esi, ebx                                ; esi: current directory record
         add     ebx, [ext2_data.block_size]
-        mov     [edi + 24], ebx               ; запомним конец очередного блока
+        mov     [edi + 24], ebx
 
-        mov     ecx, [edi + 16]                        ; ecx = first wanted (flags ommited)
+        mov     ecx, [edi + 16]                         ; ecx = first wanted (flags ommited)
 
     .find_wanted_start:
         jecxz   .find_wanted_end
     .find_wanted_cycle:
-        cmp     [esi + EXT2_DIR_STRUC.inode], 0     ; if (inode = 0) => not used
+        cmp     [esi + EXT2_DIR_STRUC.inode], 0         ; Don't count unused inode in total files.
         jz      @F
-        inc     dword [edi + 4]                        ; EXT2_files_in_folder
+
+        inc     dword [edi + 4]                         ; EXT2 files in folder.
         dec     ecx
     @@:
         movzx   ebx, [esi + EXT2_DIR_STRUC.rec_len]
-
-        cmp     ebx, 12                                 ; минимальная длина записи
+        
+        cmp     ebx, 12                                 ; Minimum record length.
         jb      .error_bad_len
-        test    ebx, 0x3                                ; длина записи должна делиться на 4
+        test    ebx, 0x3                                ; Record length must be divisible by four.
         jnz     .error_bad_len
 
-        sub     [ebp + EXT2_INODE_STRUC.i_size], ebx    ;вычитаем напрямую из структуры inode
-        add     esi, ebx                                ; к следующей записи
-        cmp     esi, [edi + 24]                        ; сравниваем с концом блока
+        sub     [ebp + EXT2_INODE_STRUC.i_size], ebx    ; Subtract "processed record" length directly from inode.
+        add     esi, ebx                                ; Go to next record.
+        cmp     esi, [edi + 24]                         ; If not reached the next block, continue.
         jb      .find_wanted_start
 
         push    .find_wanted_start
-   .end_block:                                              ;вылетели из цикла
+   .end_block:                                          ; Get the next block.
         cmp     [ebp + EXT2_INODE_STRUC.i_size], 0
         jle     .end_dir
 
-        inc     dword [edi]                                 ;получаем новый блок
+        inc     dword [edi]                             ; Number of blocks read.
+        
+        ; Read the next block.
         push    ecx
         mov     ecx, [edi]
         call    ext2_get_inode_block
@@ -649,35 +805,38 @@
         call    ext2_get_block
         test    eax, eax
         jnz     .error_get_block
+        pop     ecx
 
-        pop     ecx
         mov     esi, ebx
-        add     ebx, [ext2_data.block_size]
-        mov     [edi + 24], ebx                            ;запомним конец блока
-        ret                                                 ; опять в цикл
+	add     ebx, [ext2_data.block_size]
+        mov     [edi + 24], ebx                         ; Update the end of the current block variable.  
+        ret
 
     .wanted_end:
-        loop    .find_wanted_cycle                          ; ecx 0 => -1 нужно посчитать сколько файлов
+        loop    .find_wanted_cycle                      ; Skip files till we reach wanted one.
 
-    ;дошли до первого "нужного" файла
+    ; First requisite file.
     .find_wanted_end:
         mov     ecx, [edi + 20]
-    .wanted_start:                                          ; ищем first_wanted+count
+    .wanted_start:                                      ; Look for first_wanted + count.
         jecxz   .wanted_end
-        cmp     [esi + EXT2_DIR_STRUC.inode], 0         ; if (inode = 0) => not used
+
+        cmp     [esi + EXT2_DIR_STRUC.inode], 0         ; if (inode == 0): not used;
         jz      .empty_rec
+ 
+        ; Increment "files in dir" and "read files" count.
         inc     dword [edi + 8]
         inc     dword [edi + 4]
 
         push    edi ecx
-        mov     edi, edx                            ;обнуляем место под очереное имя файла/папки
+        mov     edi, edx                                ; Zero out till the name field.
         xor     eax, eax
         mov     ecx, 40 / 4
         rep stosd
         pop     ecx edi
 
         push    esi edi edx
-        mov     eax, [esi + EXT2_DIR_STRUC.inode]             ;получим дочерний inode
+        mov     eax, [esi + EXT2_DIR_STRUC.inode]       ; Get the child inode.
         mov     ebx, [ext2_data.ext2_temp_inode]
         call    ext2_get_inode
         test    eax, eax
@@ -685,9 +844,9 @@
 
         lea     edi, [edx + 8]
 
-        mov     eax, [ebx + EXT2_INODE_STRUC.i_ctime]           ; переведем время в ntfs формат
+        mov     eax, [ebx + EXT2_INODE_STRUC.i_ctime]   ; Convert time in NTFS format.
         xor     edx, edx
-        add     eax, 3054539008                                     ;(369 * 365 + 89) * 24 * 3600
+        add     eax, 3054539008                         ; (369 * 365 + 89) * 24 * 3600
         adc     edx, 2
         call    ntfs_datetime_to_bdfe.sec
 
@@ -703,20 +862,21 @@
         adc     edx, 2
         call    ntfs_datetime_to_bdfe.sec
 
-        pop     edx                                                 ; пока достаем только буфер
-        test    [ebx + EXT2_INODE_STRUC.i_mode], EXT2_S_IFDIR   ; для папки размер
-        jnz     @F                                                  ; не возвращаем
+        pop     edx
+        test    [ebx + EXT2_INODE_STRUC.i_mode], EXT2_S_IFDIR ; If folder, don't report size.
+        jnz     @F
 
-        mov     eax, [ebx + EXT2_INODE_STRUC.i_size]            ;low size
+        mov     eax, [ebx + EXT2_INODE_STRUC.i_size]    ; Low size
         stosd
-        mov     eax, [ebx + EXT2_INODE_STRUC.i_dir_acl]         ;high size
+        mov     eax, [ebx + EXT2_INODE_STRUC.i_dir_acl] ; High size
         stosd
-        xor     dword [edx], FS_FT_DIR                              ;помечаем, что это файл(2 раза xor)
+
+        xor     dword [edx], FS_FT_DIR                  ; Mark as file.
     @@:
-        xor     dword [edx], FS_FT_DIR                              ;помечаем, что это файл
+        xor     dword [edx], FS_FT_DIR                  ; Mark as directory.
 
-        ;теперь скопируем имя, сконвертировав из UTF-8 в CP866
-        push    ecx  ;edi и esi уже сохранены в стеке
+        ; Copy name after converting from UTF-8 to CP866.
+        push    ecx
         movzx   ecx, [esi + EXT2_DIR_STRUC.name_len]
         lea     edi, [edx + 40]
         lea     esi, [esi + EXT2_DIR_STRUC.name]
@@ -724,40 +884,39 @@
         and     byte [edi], 0
         pop     ecx edi esi
 
-        cmp     byte [edx + 40], '.'                    ; в linux файл, начинающийся с точки - скрытый
+        cmp     byte [edx + 40], '.'                    ; If it begins with ".", mark it as hidden.
         jne     @F
         or      dword [edx], FS_FT_HIDDEN
+    
     @@:
-
-        add     edx, 40 + 264                           ; go to next record
-        dec     ecx                                     ; если запись пустая ecx не надо уменьшать
+        add     edx, 40 + 264                           ; Go to next record.
+        dec     ecx
     .empty_rec:
         movzx   ebx, [esi + EXT2_DIR_STRUC.rec_len]
-        cmp     ebx, 12                                 ; минимальная длина записи
+	cmp     ebx, 12                                 ; Illegal length.
         jb      .error_bad_len
-        test    ebx, 0x3                                ; длина записи должна делиться на 4
+        test    ebx, 0x3                                ; Not a multiple of four.
         jnz     .error_bad_len
 
-        sub     [ebp + EXT2_INODE_STRUC.i_size], ebx    ;вычитаем напрямую из структуры inode
-        add     esi, ebx
-        cmp     esi, [edi + 24]                         ;дошли ли до конца блока?
+        sub     [ebp + EXT2_INODE_STRUC.i_size], ebx    ; Subtract directly from the inode.
+        add     esi, ebx     
+	cmp     esi, [edi + 24]                         ; Are we at the end of the block?
         jb      .wanted_start
 
         push    .wanted_start                           ; дошли 
         jmp     .end_block
 
-    .end_dir:   ;конец папки, когда еще не дошли до нужного файла
-        mov     edx, [edi + 28] ;адрес структуры результата
-        mov     ebx, [edi + 8] ;EXT2_read_in_folder
-        mov     ecx, [edi + 4] ;EXT2_files_in_folder
-        mov     dword [edx], 1    ;version
+    .end_dir:                                           ; End of the directory.
+        mov     edx, [edi + 28]                         ; Address of where to return data.
+        mov     ebx, [edi + 8]                          ; EXT2_read_in_folder
+        mov     ecx, [edi + 4]                          ; EXT2_files_in_folder
+        mov     dword [edx], 1                          ; Version
         mov     [edx + 4], ebx
         mov     [edx + 8], ecx
         
         lea     esp, [edi + 32]
         
-        xor     eax, eax        ;RUS: зарезервировано: нули в текущей реализации
-                                ;ENG: reserved: zeros in current implementation
+        xor     eax, eax                                ; Reserved in current implementation.
         lea     edi, [edx + 12]
         mov     ecx, 20 / 4
         rep stosd
@@ -765,60 +924,75 @@
 
     .error_bad_len:
         mov     eax, ERROR_FS_FAIL
+
     .error_read_subinode:
     .error_get_block:
+        ; Fix the stack.
         lea     esp, [edi + 32]
     .error_ret:
         or      ebx, -1
         ret
         
-    .error_empty_dir:   ;RUS: inode папки без блоков   ;ENG: inode of folder without blocks
-    .error_root:        ;RUS: root - не папка          ;ENG: root is not a folder
+    .error_empty_dir:                                   ; inode of folder without blocks.
+    .error_root:                                        ; Root has to be a folder.
         mov     eax, ERROR_FS_FAIL
         jmp     .error_ret
 
-    .error_not_found:   ;RUS: файл не найден           ;ENG: file not found
+    .error_not_found:                                   ; Directory not found.
         mov     eax, ERROR_FILE_NOT_FOUND
         jmp     .error_ret
-            
-;============================================
-;convert UTF-8 string to ASCII-string (codepage 866)
-;in:  ecx = length source
-;     esi = source
-;     edi = buffer
-; destroys: eax,esi,edi
+
+;---------------------------------------------------------------------
+; Convert UTF-8 string to ASCII-string (codepage 866)
+; Input:        esi = source.
+;               edi = buffer.
+;               ecx = length of source.
+; Output:       destroys eax, esi, edi
+;---------------------------------------------------------------------
 utf8_to_cp866:
-        jecxz   .ret
+        ; Check for zero-length string.
+        jecxz   .return
+
     .start:
         lodsw
         cmp     al, 0x80
         jb      .ascii
 
-        xchg    al, ah              ; big-endian
+        xchg    al, ah                                  ; Big-endian.
         cmp     ax, 0xd080
         jz      .yo1
+
         cmp     ax, 0xd191
         jz      .yo2
+
         cmp     ax, 0xd090
         jb      .unk
+
         cmp     ax, 0xd180
         jb      .rus1
+
         cmp     ax, 0xd190
         jb      .rus2
+
     .unk:
         mov     al, '_'
         jmp     .doit
+ 
     .yo1:
-        mov     al, 0xf0    ; Ё capital
+        mov     al, 0xf0                                ; Ё capital.
         jmp     .doit
+
     .yo2:
-        mov     al, 0xf1    ; ё small
+        mov     al, 0xf1                                ; ё small.
         jmp     .doit
+
     .rus1:
         sub     ax, 0xd090 - 0x80
         jmp     .doit
+
     .rus2:
         sub     ax, 0xd18f - 0xEF
+    
     .doit:
         stosb
         sub     ecx, 2
@@ -830,23 +1004,19 @@
         dec     esi
         dec     ecx
         jnz     .start
-    .ret:
+ 
+    .return:
         ret
 
-;----------------------------------------------------------------
-;
-;  ext2_HdRead - read hard disk
-;
-;  esi  points to filename
-;  ebx  pointer to 64-bit number = first wanted byte, 0+
-;       may be ebx=0 - start from first byte
-;  ecx  number of bytes to read, 0+
-;  edx  mem location to return data
-;
-;  ret ebx = bytes read or 0xffffffff file not found
-;      eax = 0 ok read or other = errormsg
-
-;--------------------------------------------------------------
+;---------------------------------------------------------------------
+; Read file from the hard disk.
+; Input:        esi = points to file name.
+;               ebx = pointer to 64-bit no: first byte wanted.
+;               ecx = number of bytes to read.
+;               edx = memory location to return data to.
+; Output:       ebx = bytes read (0xFFFFFFFF -> file not found)
+;               eax = error code (0 implies no error)
+;---------------------------------------------------------------------
 ext2_HdRead:
         cmp     byte [esi], 0
         jnz     @F
@@ -869,25 +1039,28 @@
 
     @@:
         mov     ax, [ebp + EXT2_INODE_STRUC.i_mode]
-        and     ax, EXT2_S_IFMT     ;оставляем только тип inode в ax
+        and     ax, EXT2_S_IFMT                         ; Leave the file format in AX.
+
+        ; Check if file.
         cmp     ax, EXT2_S_IFREG
         jne     .this_is_nofile
 
-        mov     edi, edx            ; edi = pointer to return mem
+        mov     edi, edx
 
         test    ebx, ebx
         jz      @F
-        mov     esi, ebx            ; esi = pointer to first_wanted
+
+        mov     esi, ebx
         mov     ebx, [esi+4]
-        mov     eax, [esi]    ;RUS: ebx : eax - стартовый номер байта   ;ENG: ebx : eax - start byte number
+        mov     eax, [esi]                              ; ebx:eax = start byte number.
 
-        ;RUS: ///// сравним хватит ли нам файла или нет    ;ENG: ///// check if file is big enough for us
+        ; Check if file is big enough for us.
         cmp     [ebp + EXT2_INODE_STRUC.i_dir_acl], ebx
-        ja      .size_great
+        ja      .size_greater
         jb      .size_less
 
         cmp     [ebp + EXT2_INODE_STRUC.i_size], eax
-        ja      .size_great
+        ja      .size_greater
 
     .size_less:
         xor     ebx, ebx
@@ -897,58 +1070,66 @@
     @@:
         xor     ebx, ebx
         xor     eax, eax
-    .size_great:
-        add     eax, ecx    ;RUS: add to first_wanted кол-во байт для чтения
-                            ;ENG: add to first_wanted number of bytes to read
+
+    .size_greater:
+        add     eax, ecx                                ; Get last byte.
         adc     ebx, 0
 
+        ; Check if we've to read whole file, or till requested.
         cmp     [ebp + EXT2_INODE_STRUC.i_dir_acl], ebx
-        ja      .size_great_great
-        jb      .size_great_less
+        ja      .read_till_requested
+        jb      .read_whole_file
         cmp     [ebp + EXT2_INODE_STRUC.i_size], eax
-        jae     .size_great_great   ; and if it's equal, no matter where we jump
+        jae     .read_till_requested
 
-    .size_great_less:
-        push    1            ;RUS: читаем по границе размера   ;ENG: reading till the end of file
+    .read_whole_file:
+        push    1                                       ; Read till the end of file.
         mov     ecx, [ebp + EXT2_INODE_STRUC.i_size]
-        sub     ecx, [esi]   ;RUS: (размер - старт) = сколько читать   ;ENG: to read = (size - start)
+        test    esi, esi
+        jz      @F
+
+        sub     ecx, [esi]                              ; To read = (size - starting byte)
         jmp     @F
 
-    .size_great_great:
-        push    0            ;RUS: читаем столько, сколько запросили   ;ENG: reading as much as requested
+    .read_till_requested:
+        push    0                                       ; Read as much as requested.
 
     @@:
-        ;здесь мы точно знаем сколько байт читать - ecx
-        ;edi - return memory
-        ;esi -> first wanted
+        ; ecx = bytes to read.
+        ; edi = return memory
+        ; [esi] = starting byte.
 
-        push    ecx                             ;количество считанных байт
+        push    ecx                                     ; Number of bytes to read.
         test    esi, esi
         jz      .zero_start
 
-        ;получим кусок из первого блока
-        mov     edx, [esi+4]
+        ; Get part of the first block.
+        mov     edx, [esi + 4]
         mov     eax, [esi]
         div     [ext2_data.block_size]
 
-        push    eax       ;счетчик блоков ложим в стек
+        push    eax                                     ; Save block counter to stack.
         
         push    ecx
         mov     ecx, eax
         call    ext2_get_inode_block
         test    eax, eax
         jnz     .error_at_first_block
+
         mov     ebx, [ext2_data.ext2_save_block]
         mov     eax, ecx
         call    ext2_get_block
         test    eax, eax
         jnz     .error_at_first_block
+
         pop     ecx
+        ; Get index inside block.
         add     ebx, edx
 
         neg     edx
-        add     edx, [ext2_data.block_size]     ;RUS: block_size - стартовый байт = сколько байт 1-го блока
-                                                ;ENG: block_size - start byte = number of bytes in 1st block
+        add     edx, [ext2_data.block_size]             ; Get number of bytes in this block.
+
+        ; If it's smaller than total bytes to read, then only one block.
         cmp     ecx, edx
         jbe     .only_one_block
 
@@ -957,43 +1138,52 @@
         mov     ecx, edx
 
         mov     esi, ebx
-        rep movsb                               ;RUS: кусок 1-го блока   ;ENG: part of 1st block
+        rep movsb                                       ; Copy part of 1st block.
         jmp     .calc_blocks_count
 
     .zero_start:
         mov     eax, ecx
-        push    0                               ;счетчик блоков ложим в стек
-        ;теперь в eax кол-во оставшихся байт для чтения
+        push    0xFFFFFFFF                              ; Save block counter to stack (we inc this soon, so it'll roll-over to 0).
+
+        ; eax -> bytes to read.
     .calc_blocks_count:
-        mov     ebx, edi                        ;чтение блока прям в ->ebx
+        mov     ebx, edi                                ; Read the block in ebx.
         xor     edx, edx
-        div     [ext2_data.block_size]       ;кол-во байт в последнем блоке (остаток) в edx
-        mov     edi, eax                        ;кол-во целых блоков в edi
+        div     [ext2_data.block_size]                  ; Get number of bytes in last block in edx.
+        mov     edi, eax                                ; Get number of blocks in edi.
+
     @@:
+        ; Test if all blocks are done.
         test    edi, edi
         jz      .finish_block
+        
         inc     dword [esp]
         mov     ecx, [esp]
         call    ext2_get_inode_block
+
         test    eax, eax
         jnz     .error_at_read_cycle
 
-        mov     eax, ecx                        ;а ebx уже забит нужным значением
+        mov     eax, ecx                                ; ebx already contains desired values.
         call    ext2_get_block
+
         test    eax, eax
         jnz     .error_at_read_cycle
+
         add     ebx, [ext2_data.block_size]
 
         dec     edi
         jmp     @B
 
-    .finish_block:          ;в edx - кол-во байт в последнем блоке
+    ; In edx -- number of bytes in the last block.
+    .finish_block:          
         test    edx, edx
         jz      .end_read
 
-        pop     ecx         ;счетчик блоков -> ecx
+        pop     ecx                                     ; Pop block counter in ECX.
         inc     ecx
         call    ext2_get_inode_block
+        
         test    eax, eax
         jnz     .error_at_finish_block
 
@@ -1001,19 +1191,20 @@
         mov     eax, ecx
         mov     ebx, [ext2_data.ext2_save_block]
         call    ext2_get_block
+
         test    eax, eax
         jnz     .error_at_finish_block
 
         mov     ecx, edx 
         mov     esi, ebx
-        rep movsb                               ;кусок last блока
+        rep movsb                                       ; Copy last piece of block.
         jmp     @F
 
     .end_read:
-        pop     ecx                             ;счетчик блоков, который хранился в стеке
+        pop     ecx                                     ; Pop block counter in ECX.
     @@:
-        pop     ebx                             ;количество считанных байт
-        pop     eax                             ; 1 или 0 - достигли ли конца файла
+        pop     ebx                                     ; Number of bytes read.
+        pop     eax                                     ; If we were asked to read more, say EOF.
         test    eax, eax
         jz      @F
 
@@ -1025,27 +1216,29 @@
         
     .only_one_block:
         mov     esi, ebx
-        rep movsb                               ;кусок last блока
+        rep movsb                                       ; Copy last piece of block.
         jmp     .end_read
         
-   .error_at_first_block:
+    .error_at_first_block:
         pop     edx
-   .error_at_read_cycle:
+    .error_at_read_cycle:
         pop     ebx 
-   .error_at_finish_block:
+    .error_at_finish_block:
         pop     ecx edx
         or      ebx, -1
         ret
 
-;----------------------------------------------------------------
-; in:  esi = file path
-;      ebx = pointer to dir block
-; out: esi - name without parent or not_changed
-;      ebx - dir_rec of inode children
+;---------------------------------------------------------------------
+; Find parent from file path in block.
+; Input:        esi = file path.
+;               ebx = pointer to directory block.
+; Output:       esi = name without parent, or not changed.
+;               ebx = directory record matched.
+;---------------------------------------------------------------------
 ext2_test_block_by_name:
-        sub     esp, 256        ;EXT2_filename
+        sub     esp, 256                      ; Space for EXT2 filename.
         mov     edx, ebx
-        add     edx, [ext2_data.block_size]   ;RUS: запомним конец блока   ;ENG: save block end
+        add     edx, [ext2_data.block_size]   ; Save block end.
 
     .start_rec:
         cmp     [ebx + EXT2_DIR_STRUC.inode], 0
@@ -1059,10 +1252,15 @@
 
         mov     ecx, edi
         lea     edi, [esp + 4]
-        sub     ecx, edi   ;RUS: кол-во байт в получившейся строке   ;ENG: number of bytes in resulting string
+        sub     ecx, edi                       ; Number of bytes in resulting string.
 
         mov     esi, [esp]
+
+    ; esi: original file path.
+    ; edi: converted string stored on stack.
+    ; ecx: size of converted string.
     @@:
+        ; If no bytes left in resulting string, test it.
         jecxz   .test_find
         dec     ecx
 
@@ -1073,42 +1271,52 @@
         inc     edi
         xchg    al, ah
         call    char_toupper
+
+        ; If both are same, check next byte.
         cmp     al, ah
         je      @B
-    @@:                           ;RUS: не подошло   ;ENG: didn't fit
+    @@:                                         ; Doesn't match.
         pop     esi
+    
     .next_rec:
         movzx   eax, [ebx + EXT2_DIR_STRUC.rec_len]
-        add     ebx, eax          ;RUS: к след. записи      ;ENG: go to next record
-        cmp     ebx, edx          ;RUS: проверим конец ли   ;ENG: check if this is the end
+        add     ebx, eax                        ; Go to next record.
+        cmp     ebx, edx                        ; Check if this is the end.
         jb      .start_rec
+ 
         add     esp, 256
         ret
 
     .test_find:
         cmp     byte [esi], 0
-        je      .ret              ;RUS: нашли конец         ;ENG: the end reached
-        cmp     byte [esi], '/'
+        je      .ret                            ; The end reached.
+        cmp     byte [esi], '/'                 ; If not end of directory name, not matched.
         jne     @B
         inc     esi
+
     .ret:
         add     esp, 256 + 4
         ret
 
-;========================
-;Ищет inode по строке пути
-;in:  esi = name
-;out: eax - error code
-;     ebp = inode
-;      dl - первый байт из имени файла/папки
+;---------------------------------------------------------------------
+; Seek inode from the path.
+; Input:        esi = name.
+; Output:       eax = error code (0 implies no error)
+;               ebp = inode
+;                dl = first byte of file/folder name.
+;                     [ext2_data.ext2_save_inode] stores the inode.
+;---------------------------------------------------------------------
 ext2_find_lfn:
         mov     ebp, [ext2_data.root_inode]
+
+        ; Check for empty root.
         cmp     [ebp + EXT2_INODE_STRUC.i_blocks], 0
         je      .error_empty_root
         
     .next_path_part:
         push    [ebp + EXT2_INODE_STRUC.i_blocks]
         xor     ecx, ecx
+
     .folder_block_cycle:
         push    ecx
         call    ext2_get_inode_block
@@ -1116,7 +1324,7 @@
         jnz     .error_get_inode_block
         
         mov     eax, ecx
-        mov     ebx, [ext2_data.ext2_save_block]        ;ebx = cur dir record
+        mov     ebx, [ext2_data.ext2_save_block]                ; Get directory records from directory.
         call    ext2_get_block
         test    eax, eax
         jnz     .error_get_block
@@ -1125,28 +1333,30 @@
         call    ext2_test_block_by_name
         pop     edi ecx
 
-        cmp     edi, esi             ;RUS: нашли имя?   ;ENG: did we find a name?
-        je      .next_folder_block   ;RUS: не нашли -> к след. блоку   ;ENG: we didn't -> moving to next block
+        cmp     edi, esi                                        ; Did something match?
+        je      .next_folder_block                              ; No, move to next block.
         
-        cmp     byte [esi], 0   ;RUS: дошли до "конца" пути -> возваращаемся
-                                ;ENG: reached the "end" of path -> returning
-        jz      .get_inode_ret
+        cmp     byte [esi], 0                                   ; Reached the "end" of path successfully. 
+        je      .get_inode_ret
 
-        cmp     [ebx + EXT2_DIR_STRUC.file_type], EXT2_FT_DIR   ;RUS: нашли, но это не папка
-        jne     .not_found                                      ;ENG: found, but it's not a folder
-
         mov     eax, [ebx + EXT2_DIR_STRUC.inode]
-        mov     ebx, [ext2_data.ext2_save_inode]   ;RUS: все же папка.   ;ENG: it's a folder afterall
+        mov     ebx, [ext2_data.ext2_save_inode]
         call    ext2_get_inode
         test    eax, eax
         jnz     .error_get_inode
-        pop     ecx   ;RUS: в стеке лежит кол-во блоков   ;ENG: stack top contains number of blocks
+
+        movzx   eax, [ebx + EXT2_INODE_STRUC.i_mode]
+        and     eax, EXT2_S_IFMT                                ; Get the mask.
+        cmp     eax, EXT2_S_IFDIR
+        jne     .not_found                                      ; Matched till part, but directory entry we got doesn't point to folder.
+
+        pop     ecx                                             ; Stack top contains number of blocks.
         mov     ebp, ebx
         jmp     .next_path_part
         
     .next_folder_block:
-        ;к следующему блоку в текущей папке
-        pop     eax                ;RUS: счетчик блоков   ;ENG: blocks counter
+        ; Next block in current folder.
+        pop     eax                                             ; Get blocks counter.
         sub     eax, [ext2_data.count_block_in_block]
         jle     .not_found
         
@@ -1159,13 +1369,16 @@
         ret
 
     .get_inode_ret:
-        pop     ecx   ;RUS: в стеке лежит кол-во блоков   ;ENG: stack top contains number of blocks
-        mov     dl, [ebx + EXT2_DIR_STRUC.name]   ;RUS: в dl - первый символ ()   ;ENG: ???
+        pop     ecx                                             ; Stack top contains number of blocks.
+
+        mov     dl, [ebx + EXT2_DIR_STRUC.name]                 ; First character of file-name.
         mov     eax, [ebx + EXT2_DIR_STRUC.inode]
         mov     ebx, [ext2_data.ext2_save_inode]
+
+        ; If we can't get the inode, eax contains the error.        
         call    ext2_get_inode
+
         mov     ebp, ebx
-        xor     eax, eax
         ret
 
     .error_get_inode_block:
@@ -1177,14 +1390,13 @@
         mov     eax, ERROR_FS_FAIL
         ret
 
-;----------------------------------------------------------------
-;ext2_HdGetFileInfo - read file info from block device
-;
-;in: esi  points to filename
-;    edx  mem location to return data
-;--------------------------------------------------------------
+;---------------------------------------------------------------------
+; Read file information from block device.
+; Input:        esi = file name.
+;               edx = memory location to return data.
+; Output:       eax = error code.
+;---------------------------------------------------------------------
 ext2_HdGetFileInfo:
-        xchg    bx, bx
         cmp     byte [esi], 0
         jz      .is_root
 
@@ -1197,30 +1409,35 @@
         ret
 
     .is_root:
-        xor     ebx, ebx      ;RUS: root не может быть скрытым   ;ENG: root cannot be hidden
+        xor     ebx, ebx                                ; Clear out first char, since we don't want to set hidden flag on root.
         mov     ebp, [ext2_data.root_inode]
+
     @@:
         xor     eax, eax
         mov     edi, edx
         mov     ecx, 40/4
-        rep stosd                   ; fill zero
+        rep stosd                                       ; Zero fill buffer.
 
         cmp     bl, '.'
         jne     @F
         or      dword [edx], FS_FT_HIDDEN
+
     @@:
+        test    [ebp + EXT2_INODE_STRUC.i_mode], EXT2_S_IFDIR
+        jnz     @F                                      ; If a directory, don't put in file size.
 
-        test    [ebp + EXT2_INODE_STRUC.i_mode], EXT2_S_IFDIR
-        jnz     @F
-        mov     eax, [ebp + EXT2_INODE_STRUC.i_size]            ;low size
-        mov     ebx, [ebp + EXT2_INODE_STRUC.i_dir_acl]         ;high size
+        mov     eax, [ebp + EXT2_INODE_STRUC.i_size]    ; Low file size.
+        mov     ebx, [ebp + EXT2_INODE_STRUC.i_dir_acl] ; High file size.
         mov     dword [edx+32], eax
         mov     dword [edx+36], ebx
-        xor     dword [edx], FS_FT_DIR
+
+        xor     dword [edx], FS_FT_DIR                  ; Next XOR will clean this, to mark it as a file.
     @@:
-        xor     dword [edx], FS_FT_DIR
+        xor     dword [edx], FS_FT_DIR                  ; Mark as directory.
 
         lea     edi, [edx + 8]
+
+        ; Store all time.
         mov     eax, [ebp + EXT2_INODE_STRUC.i_ctime]
         xor     edx, edx
         add     eax, 3054539008
Index: kernel/trunk/fs/part_set.inc
===================================================================
--- kernel/trunk/fs/part_set.inc	(revision 3700)
+++ kernel/trunk/fs/part_set.inc	(working copy)
@@ -27,7 +27,7 @@
 ;******************************************************
 PARTITION_START      dd 0x3f
 PARTITION_END        dd 0
-fs_type              db 0       ; 1=NTFS, 2=EXT2/3, 16=FAT16, 32=FAT32
+fs_type              db 0       ; 1=NTFS, 2=EXT2/3/4, 16=FAT16, 32=FAT32
 align 4
 
 fs_dependent_data_start:
@@ -83,6 +83,7 @@
     .ext2_temp_inode                dd ?   ;RUS: inode для мелких процедур        ;ENG: inode for small procedures
     .sb                             dd ?   ; superblock
     .groups_count                   dd ?
+    .partition_flags                dd ?
 if $ > fs_dependent_data_end
 ERROR:
        increase sizeof(fs_dependent_data)!
