Subversion Repositories Kolibri OS

Rev

Rev 4265 | Rev 5565 | Go to most recent revision | Blame | Compare with Previous | Last modification | View Log | Download | RSS feed

  1. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  2. ;;                                                              ;;
  3. ;; Contains ext2 block handling code.                           ;;
  4. ;;                                                              ;;
  5. ;; Copyright (C) KolibriOS team 2013-2014. All rights reserved. ;;
  6. ;; Distributed under terms of the GNU General Public License    ;;
  7. ;;                                                              ;;
  8. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  9.  
  10. $Revision: 4891 $
  11.  
  12.  
  13. ;---------------------------------------------------------------------
  14. ; Write ext2 block from memory to disk.
  15. ; Input:        eax = i_block (block number in ext2 terms);
  16. ;               ebx = buffer address
  17. ;               ebp = pointer to EXTFS
  18. ; Output:       eax = error code (0 implies no error)
  19. ;---------------------------------------------------------------------
  20. ext2_block_write:
  21.         push    edx ebx ecx
  22.  
  23.         mov     edx, fs_write32_sys
  24.         jmp     ext2_block_modify
  25.  
  26. ;---------------------------------------------------------------------
  27. ; Read ext2 block from disk to memory.
  28. ; Input:        eax = i_block (block number in ext2 terms);
  29. ;               ebx = address of where to read block
  30. ;               ebp = pointer to EXTFS
  31. ; Output:       eax = error code (0 implies no error)
  32. ;---------------------------------------------------------------------
  33. ext2_block_read:
  34.         push    edx ebx ecx
  35.        
  36.         mov     edx, fs_read32_sys
  37.         jmp     ext2_block_modify      
  38.  
  39. ;---------------------------------------------------------------------
  40. ; Modify ext2 block.
  41. ; Input:        eax = i_block (block number in ext2 terms);
  42. ;               ebx = I/O buffer address;
  43. ;               edx = fs_read/write32_sys
  44. ;               ebp = pointer to EXTFS
  45. ;               edx, ebx, ecx on stack.
  46. ; Output:       eax = error code (0 implies no error)
  47. ;---------------------------------------------------------------------
  48. ext2_block_modify:
  49.         ; Get block number in hard-disk terms in eax.
  50.         mov     ecx, [ebp + EXTFS.log_block_size]
  51.         shl     eax, cl
  52.         mov     ecx, eax
  53.         push    [ebp + EXTFS.count_block_in_block]
  54.  
  55.     @@:
  56.         mov     eax, ecx
  57.         call    edx
  58.         test    eax, eax
  59.         jnz     .fail
  60.        
  61.         inc     ecx
  62.         add     ebx, 512
  63.         dec     dword[esp]
  64.         jnz     @B
  65.  
  66.         xor     eax, eax
  67.     @@:
  68.         pop     ecx
  69.         pop     ecx ebx edx
  70.         ret
  71.  
  72.     .fail:
  73.         mov     eax, ERROR_DEVICE
  74.         jmp     @B
  75.  
  76. ;---------------------------------------------------------------------
  77. ; Zeroes a block.
  78. ; Input:        ebx = block ID.
  79. ;               ebp = pointer to EXTFS.
  80. ; Output:       eax = error code.
  81. ;---------------------------------------------------------------------
  82. ext2_block_zero:
  83.         push    ebx
  84.  
  85.         mov     eax, ebx
  86.         mov     ebx, [ebp + EXTFS.ext2_temp_block]
  87.  
  88.         call    ext2_block_read
  89.         test    eax, eax
  90.         jnz     .return
  91.  
  92.         push    edi ecx
  93.         xor     eax, eax
  94.         mov     ecx, [ebp + EXTFS.block_size]
  95.         mov     edi, [ebp + EXTFS.ext2_temp_block]
  96.         rep stosb
  97.         pop     ecx edi
  98.  
  99.         mov     eax, [esp]
  100.         call    ext2_block_write
  101.  
  102.     .return:
  103.         pop     ebx
  104.         ret
  105.  
  106. ;---------------------------------------------------------------------
  107. ; Allocates a block.
  108. ; Input:        eax = inode ID for "preference".
  109. ;               ebp = pointer to EXTFS.
  110. ; Output:       Block marked as set in block group.
  111. ;               eax = error code.
  112. ;               ebx = block ID.
  113. ;---------------------------------------------------------------------
  114. ext2_block_alloc:
  115.         push    [ebp + EXTFS.superblock + EXT2_SB_STRUC.blocks_count]
  116.         push    EXT2_BLOCK_GROUP_DESC.free_blocks_count
  117.         push    [ebp + EXTFS.superblock + EXT2_SB_STRUC.blocks_per_group]
  118.  
  119.         lea     ebx, [ebp + EXTFS.superblock + EXT2_SB_STRUC.free_block_count]
  120.         push    ebx
  121.  
  122.         push    ext2_bg_read_blk_bitmap
  123.  
  124.         call    ext2_resource_alloc
  125.  
  126.         ret
  127.  
  128. ;---------------------------------------------------------------------
  129. ; Zero-allocates a block.
  130. ; Input:        eax = inode ID for "preference".
  131. ;               ebp = pointer to EXTFS.
  132. ; Output:       Block marked as set in block group.
  133. ;               eax = error code.
  134. ;               ebx = block ID.
  135. ;---------------------------------------------------------------------
  136. ext2_block_calloc:
  137.         call    ext2_block_alloc
  138.         test    eax, eax
  139.         jnz     @F
  140.  
  141.         call    ext2_block_zero
  142.     @@:
  143.         ret
  144.  
  145. ;---------------------------------------------------------------------
  146. ; Frees a block.
  147. ; Input:        eax = block ID.
  148. ;               ebp = pointer to EXTFS.
  149. ; Output:       Block marked as free in block group.
  150. ;               eax = error code.
  151. ;---------------------------------------------------------------------
  152. ext2_block_free:
  153.         push    edi ecx
  154.  
  155.         mov     edi, ext2_bg_read_blk_bitmap
  156.         xor     ecx, ecx
  157.         call    ext2_resource_free
  158.  
  159.         pop     ecx edi
  160.         ret
  161.  
  162. ;---------------------------------------------------------------------
  163. ; Find parent from file path in block.
  164. ; Input:        esi = file path.
  165. ;               ebx = pointer to directory block.
  166. ;               ebp = pointer to EXTFS structure.
  167. ; Output:       esi = name without parent, or not changed.
  168. ;               ebx = directory record matched.
  169. ;---------------------------------------------------------------------
  170. ext2_block_find_parent:
  171.         sub     esp, 256                      ; Space for EXT2 filename.
  172.         mov     edx, ebx
  173.         add     edx, [ebp + EXTFS.block_size] ; Save block end.
  174.  
  175.     .start_rec:
  176.         cmp     [ebx + EXT2_DIR_STRUC.inode], 0
  177.         jz      .next_rec
  178.  
  179.         mov     edi, esp
  180.         push    esi
  181.         movzx   ecx, [ebx + EXT2_DIR_STRUC.name_len]
  182.         lea     esi, [ebx + EXT2_DIR_STRUC.name]
  183.         call    utf8_to_cp866
  184.  
  185.         mov     ecx, edi
  186.         lea     edi, [esp + 4]
  187.         sub     ecx, edi                       ; Number of bytes in resulting string.
  188.  
  189.         mov     esi, [esp]
  190.  
  191.     ; esi: original file path.
  192.     ; edi: converted string stored on stack.
  193.     ; ecx: size of converted string.
  194.     @@:
  195.         ; If no bytes left in resulting string, test it.
  196.         jecxz   .test_find
  197.         dec     ecx
  198.  
  199.         lodsb
  200.         call    char_toupper
  201.  
  202.         mov     ah, [edi]
  203.         inc     edi
  204.         xchg    al, ah
  205.         call    char_toupper
  206.  
  207.         ; If both are same, check next byte.
  208.         cmp     al, ah
  209.         je      @B
  210.     @@:                                         ; Doesn't match.
  211.         pop     esi
  212.    
  213.     .next_rec:
  214.         movzx   eax, [ebx + EXT2_DIR_STRUC.rec_len]
  215.         add     ebx, eax                        ; Go to next record.
  216.         cmp     ebx, edx                        ; Check if this is the end.
  217.         jb      .start_rec
  218.  
  219.         add     esp, 256
  220.         ret
  221.  
  222.     .test_find:
  223.         cmp     byte [esi], 0
  224.         je      .ret                            ; The end reached.
  225.         cmp     byte [esi], '/'                 ; If not end of directory name, not matched.
  226.         jne     @B
  227.         inc     esi
  228.  
  229.     .ret:
  230.         add     esp, 256 + 4
  231.         ret
  232.  
  233. ;---------------------------------------------------------------------
  234. ; Finds free space in a directory block, modifying last entry appropriately.
  235. ; Input:        ebp = pointer to EXTFS.
  236. ;               ecx = size of free space required.
  237. ;               [EXTFS.ext2_temp_block] contains the block relevant.
  238. ; Output:       edi = free entry.
  239. ;               rec_len of free entry is set.
  240. ;               eax = error code; if the block doesn't link to the next one, this is 0x00000001 on failure.
  241. ;                               ; else, 0xFFFFFFFF.
  242. ;---------------------------------------------------------------------
  243. ext2_block_find_fspace:
  244.         push    ebx edx
  245.  
  246.         mov     edi, [ebp + EXTFS.ext2_temp_block]
  247.         mov     edx, edi
  248.         add     edx, [ebp + EXTFS.block_size]
  249.  
  250.     @@:
  251.         movzx   eax, [edi + EXT2_DIR_STRUC.rec_len]
  252.         test    eax, eax
  253.         jz      .zero_len
  254.  
  255.         cmp     [edi + EXT2_DIR_STRUC.inode], 0
  256.         je      .unused_entry
  257.  
  258.         ; It's a used entry, so see if we can fit it between current one and next.
  259.         ; Subtract the size used by the name and the structure from rec_len.
  260.         movzx   ebx, [edi + EXT2_DIR_STRUC.name_len]
  261.         add     ebx, 8 + 3
  262.         and     ebx, 0xfffffffc                     ; Align it on the next 4-byte boundary.
  263.  
  264.         sub     eax, ebx
  265.         add     edi, ebx
  266.         cmp     eax, ecx
  267.         jb      .next_iter
  268.  
  269.         sub     edi, ebx
  270.         mov     [edi + EXT2_DIR_STRUC.rec_len], bx  ; Make previous entry point to us.
  271.         add     edi, ebx
  272.  
  273.         mov     [edi + EXT2_DIR_STRUC.rec_len], ax  ; Make current entry point to next one.
  274.         jmp     .found
  275.  
  276.     .unused_entry:
  277.         ; It's an unused inode.
  278.         cmp     eax, ecx
  279.         jge     .found
  280.  
  281.     .next_iter:
  282.         add     edi, eax
  283.         cmp     edi, edx
  284.         jb      @B
  285.  
  286.     .not_found:
  287.         xor     eax, eax
  288.         not     eax
  289.         jmp     .ret
  290.  
  291.     ; Zero length entry means we have the rest of the block for us.
  292.     .zero_len:
  293.         mov     eax, edx
  294.         sub     eax, edi
  295.  
  296.         ; Point to next block.
  297.         mov     [edi + EXT2_DIR_STRUC.rec_len], ax
  298.  
  299.         cmp     eax, ecx
  300.         jge     .fits
  301.  
  302.         mov     [edi + EXT2_DIR_STRUC.inode], 0
  303.  
  304.         ; It doesn't fit, but the block doesn't link to the next block.
  305.         xor     eax, eax
  306.         inc     eax
  307.         jmp     .ret
  308.  
  309.     .fits:
  310.         mov     [edi + EXT2_DIR_STRUC.rec_len], cx
  311.  
  312.     .found:
  313.         xor     eax, eax
  314.  
  315.     .ret:
  316.         pop     edx ebx
  317.         ret
  318.  
  319. ;---------------------------------------------------------------------
  320. ; Gets the block group's descriptor.
  321. ; Input:        eax = block group.
  322. ; Output:       eax = if zero, error; else, points to block group descriptor.
  323. ;               [EXTFS.ext2_temp_block] contains relevant block.
  324. ;               ebp = pointer to EXTFS.
  325. ;---------------------------------------------------------------------
  326. ext2_bg_read_desc:
  327.         push    edx ebx
  328.         mov     edx, 32
  329.         mul     edx                             ; Get index of descriptor in global_desc_table.
  330.  
  331.         ; eax: block group descriptor offset relative to global descriptor table start
  332.         ; Find the block this block descriptor is in.
  333.         div     [ebp + EXTFS.block_size]
  334.         add     eax, [ebp + EXTFS.superblock + EXT2_SB_STRUC.first_data_block]
  335.         inc     eax
  336.         mov     ebx, [ebp + EXTFS.ext2_temp_block]
  337.         call    ext2_block_read
  338.         test    eax, eax
  339.         jnz     .fail    
  340.  
  341.         add     ebx, edx                        ; edx: local index of descriptor inside block
  342.         mov     eax, ebx
  343.  
  344.     .return:
  345.         pop     ebx edx
  346.         ret
  347.  
  348.     .fail:
  349.         xor     eax, eax
  350.         jmp     .return
  351.  
  352. ;---------------------------------------------------------------------
  353. ; Writes a block group's descriptor.
  354. ; Input:        eax = block group.
  355. ;               [EXTFS.ext2_temp_data] contains the block relevant.
  356. ;               ebp = pointer to EXTFS.
  357. ; Output:       eax = error code.
  358. ;---------------------------------------------------------------------
  359. ext2_bg_write_desc:
  360.         push    edx ebx
  361.         mov     edx, 32
  362.         mul     edx                             ; Get index of descriptor in global_desc_table.
  363.  
  364.         ; eax: block group descriptor offset relative to global descriptor table start
  365.         ; Find the block this block descriptor is in.
  366.         div     [ebp + EXTFS.block_size]
  367.         add     eax, [ebp + EXTFS.superblock + EXT2_SB_STRUC.first_data_block]
  368.         inc     eax
  369.         mov     ebx, [ebp + EXTFS.ext2_temp_block]
  370.         call    ext2_block_write
  371.  
  372.     .return:
  373.         pop     ebx edx
  374.         ret
  375.  
  376. ;---------------------------------------------------------------------
  377. ; Gets the block group's block bitmap.
  378. ; Input:        eax = block group.
  379. ; Output:       eax = if zero, error; else, points to block group descriptor.
  380. ;               ebx = block bitmap's block (hard disk).
  381. ;---------------------------------------------------------------------
  382. ext2_bg_read_blk_bitmap:
  383.         push    ecx
  384.  
  385.         call    ext2_bg_read_desc
  386.         test    eax, eax
  387.         jz      .fail
  388.  
  389.         mov     ebx, [eax + EXT2_BLOCK_GROUP_DESC.block_bitmap] ; Block number of block group bitmap - in ext2 terms.
  390.  
  391.     .return:
  392.         pop     ecx
  393.         ret
  394.  
  395.     .fail:
  396.         xor     eax, eax
  397.         jmp     .return
  398.  
  399. ;---------------------------------------------------------------------
  400. ; Updates superblock, plus backups.
  401. ; Input:        ebp = pointer to EXTFS.
  402. ; Output:       eax = error code.
  403. ;---------------------------------------------------------------------
  404. ext2_sb_update:
  405.         push    ebx
  406.  
  407.         mov     eax, 2
  408.         lea     ebx, [ebp + EXTFS.superblock]
  409.         call    fs_write32_sys
  410.  
  411.         pop     ebx
  412.         ret
  413.