Subversion Repositories Kolibri OS

Rev

Go to most recent revision | Blame | Last modification | View Log | Download | RSS feed

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