Subversion Repositories Kolibri OS

Rev

Rev 4066 | Go to most recent revision | Details | Compare with Previous | Last modification | View Log | RSS feed

Rev Author Line No. Line
4066 shikhin 1
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
2
;;                                                              ;;
3
;; Contains ext2 block handling code.                           ;;
4
;;                                                              ;;
4850 mario79 5
;; Copyright (C) KolibriOS team 2013-2014. All rights reserved. ;;
4066 shikhin 6
;; Distributed under the terms of the new BSD license.          ;;
7
;;                                                              ;;
8
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
9
 
4850 mario79 10
$Revision: 4850 $
11
 
12
 
4066 shikhin 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