Subversion Repositories Kolibri OS

Rev

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

Rev Author Line No. Line
3935 shikhin 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