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 structures, and macros.                        ;;
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
; Recommended move to some kernel-wide bitmap handling code (with a bit of abstraction, of course).
11
 
12
;---------------------------------------------------------------------
13
; Clears a bit.
14
; Input:        eax = index into bitmap.
15
;               [EXTFS.ext2_save_block] = address of bitmap.
16
;               ebp = address of EXTFS.
17
; Output:       Bit cleared.
18
;               eax = non-zero, if already cleared.
19
;---------------------------------------------------------------------
20
bitmap_clear_bit:
21
        push    ebx ecx edx
22
 
23
        xor     edx, edx
24
        mov     ecx, 8
25
        div     ecx
26
 
27
        add     eax, [ebp + EXTFS.ext2_save_block]
28
 
29
        ; Get the mask.
30
        mov     ebx, 1
31
        mov     ecx, edx
32
        shl     ebx, cl
33
 
34
        test    [eax], ebx
35
        jz      .cleared
36
 
37
        not     ebx
38
        and     [eax], ebx
39
 
40
        xor     eax, eax
41
    .return:
42
        pop     edx ecx ebx
43
        ret
44
 
45
    ; Already cleared.
46
    .cleared:
47
        xor     eax, eax
48
        not     eax
49
        jmp     .return
50
 
51
;---------------------------------------------------------------------
52
; Finds free bit in the bitmap.
53
; Input:        ecx = number of bits in the bitmap.
54
;               [EXTFS.ext2_save_block] = address of bitmap.
55
;               ebp = address of EXTFS.
56
; Output:       eax = index of free bit in the bitmap; marked set.
57
;                     0xFFFFFFFF if no free bit found.
58
;---------------------------------------------------------------------
59
ext2_find_free_bit:
60
bitmap_find_free_bit:
61
        push    esi ebx ecx edx
62
        mov     esi, [ebp + EXTFS.ext2_save_block]
63
 
64
        ; Get total DWORDS in eax; total bits in last dword, if any, in edx.
65
        xor     edx, edx
66
        mov     eax, ecx
67
        mov     ecx, 32
68
        div     ecx
69
 
70
        mov     ecx, eax
71
        xor     eax, eax
72
        push    edx
73
 
74
        test    ecx, ecx
75
        jz      .last_bits
76
 
77
    ; Check in the DWORDS.
78
    .dwords:
79
        mov     ebx, [esi]
80
        not     ebx
81
 
82
        bsf     edx, ebx
83
 
84
        ; If 0, then the original value would be 0xFFFFFFFF, hence no free bits.
85
        jz      @F
86
 
87
        ; We found the value. Let's return with it.
88
        add     esp, 4
89
        add     eax, edx
90
        jmp     .return
91
 
92
    @@:
93
        add     esi, 4
94
        add     eax, 32
95
        loop    .dwords
96
 
97
    .last_bits:
98
        ; Check in the last few bits.
99
        pop     ecx
100
        test    ecx, ecx
101
        jz      @F
102
 
103
        mov     ebx, [esi]
104
        not     ebx
105
        bsf     ebx, edx
106
 
107
        ; If 0, no free bits.
108
        jz      @F
109
 
110
        ; If free bit is greater than the last known bit, then error.
111
        cmp     edx, ecx
112
        jg      @F
113
 
114
        add     eax, edx
115
        jmp     .return
116
 
117
    @@:
118
        ; Didn't find any free bits.
119
        xor     eax, eax
120
        not     eax
121
        jmp     @F
122
 
123
    .return:
124
        mov     ecx, edx
125
        mov     edx, 1
126
        shl     edx, cl
127
        or      [esi], edx
128
 
129
    @@:
130
        pop     edx ecx ebx esi
131
        ret
132
 
133
; Recommended move to some kernel-wide string handling code.
134
;---------------------------------------------------------------------
135
; Find the length of a string.
136
; Input:        esi = source.
137
; Output:       length in ecx
138
;---------------------------------------------------------------------
139
strlen:
140
        push    eax esi
141
        xor     ecx, ecx
142
 
143
    @@:
144
        lodsb
145
        test    al, al
146
        jz      .ret
147
 
148
        inc     ecx
149
        jmp     @B
150
 
151
    .ret:
152
        pop     esi eax
153
        ret
154
 
155
;---------------------------------------------------------------------
156
; Convert UTF-8 string to ASCII-string (codepage 866)
157
; Input:        esi = source.
158
;               edi = buffer.
159
;               ecx = length of source.
160
; Output:       destroys eax, esi, edi
161
;---------------------------------------------------------------------
162
utf8_to_cp866:
163
        ; Check for zero-length string.
164
        jecxz   .return
165
 
166
    .start:
167
        lodsw
168
        cmp     al, 0x80
169
        jb      .ascii
170
 
171
        xchg    al, ah                                  ; Big-endian.
172
        cmp     ax, 0xd080
173
        jz      .yo1
174
 
175
        cmp     ax, 0xd191
176
        jz      .yo2
177
 
178
        cmp     ax, 0xd090
179
        jb      .unk
180
 
181
        cmp     ax, 0xd180
182
        jb      .rus1
183
 
184
        cmp     ax, 0xd190
185
        jb      .rus2
186
 
187
    .unk:
188
        mov     al, '_'
189
        jmp     .doit
190
 
191
    .yo1:
192
        mov     al, 0xf0                                ; Ё capital.
193
        jmp     .doit
194
 
195
    .yo2:
196
        mov     al, 0xf1                                ; ё small.
197
        jmp     .doit
198
 
199
    .rus1:
200
        sub     ax, 0xd090 - 0x80
201
        jmp     .doit
202
 
203
    .rus2:
204
        sub     ax, 0xd18f - 0xEF
205
 
206
    .doit:
207
        stosb
208
        sub     ecx, 2
209
        ja      .start
210
        ret
211
 
212
    .ascii:
213
        stosb
214
        dec     esi
215
        dec     ecx
216
        jnz     .start
217
 
218
    .return:
219
        ret
220
 
221
; Recommended move to some kernel-wide time handling code.
222
 
223
; Total cumulative seconds till each month.
224
cumulative_seconds_in_month:
225
        .january:       dd 0 * (60 * 60 * 24)
226
        .february:      dd 31 * (60 * 60 * 24)
227
        .march:         dd 59 * (60 * 60 * 24)
228
        .april:         dd 90 * (60 * 60 * 24)
229
        .may:           dd 120 * (60 * 60 * 24)
230
        .june:          dd 151 * (60 * 60 * 24)
231
        .july:          dd 181 * (60 * 60 * 24)
232
        .august:        dd 212 * (60 * 60 * 24)
233
        .september:     dd 243 * (60 * 60 * 24)
234
        .october:       dd 273 * (60 * 60 * 24)
235
        .november:      dd 304 * (60 * 60 * 24)
236
        .december:      dd 334 * (60 * 60 * 24)
237
 
238
current_bdfe_time:
239
        dd 0
240
current_bdfe_date:
241
        dd 0
242
 
243
;---------------------------------------------------------------------
244
; Stores current unix time.
245
; Input:        edi = buffer to output Unix time.
246
;---------------------------------------------------------------------
247
current_unix_time:
248
        push    eax esi
249
        mov     esi, current_bdfe_time
250
 
251
        ; Just a small observation:
252
        ; The CMOS is a pretty bad source to get time from. One shouldn't rely on it,
253
        ; since it messes up the time by tiny bits. Of course, this is all technical,
254
        ; but one can look it up on the osdev wiki. What is better is to get the time
255
        ; from CMOS during boot, then update system time using a more accurate timer.
256
        ; I'll probably add that after the Summer of Code, so TODO! TODO! TODO!.
257
 
258
        ; Get time from CMOS.
259
        ; Seconds.
260
        mov     al, 0x00
261
        out     0x70, al
262
        in      al, 0x71
263
        call    bcd2bin
264
        mov     [esi + 0], al
265
 
266
        ; Minute.
267
        mov     al, 0x02
268
        out     0x70, al
269
        in      al, 0x71
270
        call    bcd2bin
271
        mov     [esi + 1], al
272
 
273
        ; Hour.
274
        mov     al, 0x04
275
        out     0x70, al
276
        in      al, 0x71
277
        call    bcd2bin
278
        mov     [esi + 2], al
279
 
280
        ; Get date.
281
 
282
        ; Day.
283
        mov     al, 0x7
284
        out     0x70, al
285
        in      al, 0x71
286
        call    bcd2bin
287
        mov     [esi + 4], al
288
 
289
        ; Month.
290
        mov     al, 0x8
291
        out     0x70, al
292
        in      al, 0x71
293
        call    bcd2bin
294
        mov     [esi + 5], al
295
 
296
        ; Year.
297
        mov     al, 0x9
298
        out     0x70, al
299
        in      al, 0x71
300
        call    bcd2bin
301
        add     ax, 2000        ; CMOS only returns last two digits.
302
                                ; Note that everywhere in KolibriOS this is used.
303
                                ; This is hacky, since the RTC can be incorrectly set
304
                                ; to something before 2000.
305
        mov     [esi + 6], ax
306
 
307
        call    bdfe_to_unix_time
308
        pop     esi eax
309
        ret
310
 
311
;---------------------------------------------------------------------
312
; Convert time+date from BDFE to Unix time.
313
; Input:        esi = pointer to BDFE time+date.
314
;               edi = buffer to output Unix time.
315
;---------------------------------------------------------------------
316
bdfe_to_unix_time:
317
        push    eax ebx ecx edx
318
        mov     dword[edi], 0x00000000
319
 
320
        ; The minimum representable time is 1901-12-13.
321
        cmp     word[esi + 6], 1901
322
        jb      .ret
323
        jg      .max
324
 
325
        cmp     byte[esi + 5], 12
326
        jb      .ret
327
 
328
        cmp     byte[esi + 4], 13
329
        jbe     .ret
330
        jg      .convert
331
 
332
    ; Check if it is more than the maximum representable time.
333
    .max:
334
        ; The maximum representable time is 2038-01-19.
335
        cmp     word[esi + 6], 2038
336
        jg      .ret
337
        jb      .convert
338
 
339
        cmp     byte[esi + 5], 1
340
        jg      .ret
341
 
342
        cmp     byte[esi + 4], 19
343
        jge     .ret
344
 
345
    ; Convert the time.
346
    .convert:
347
        ; Get if current year is leap year in ECX.
348
        xor     ecx, ecx
349
        mov     ebx, 4
350
        xor     edx, edx
351
 
352
        cmp     word[esi + 6], 1970
353
        jb      .negative
354
 
355
        movzx   eax, word[esi + 6]              ; Year.
356
        cmp     byte[esi + 5], 3                ; If the month is less than March, than that year doesn't matter.
357
        jge     @F
358
 
359
        test    eax, 3
360
        ; Not a leap year.
361
        jnz     @F
362
 
363
        inc     ecx
364
    @@:
365
        ; Number of leap years between two years = ((end date - 1)/4) - (1970/4)
366
        dec     eax
367
        div     ebx
368
        sub     eax, 1970/4
369
 
370
        ; EAX is the number of leap years.
371
        add     eax, ecx
372
        mov     ecx, (60 * 60 * 24)             ; Seconds in a day.
373
        mul     ecx
374
 
375
        ; Account for leap years, i.e., one day extra for each.
376
        add     [edi], eax
377
 
378
        ; Get total days in EAX.
379
        movzx   eax, byte[esi + 4]
380
        dec     eax
381
        mul     ecx
382
 
383
        ; Account for days.
384
        add     [edi], eax
385
 
386
        ; Account for month.
387
        movzx   eax, byte[esi + 5]
388
        dec     eax
389
        mov     eax, [cumulative_seconds_in_month + (eax * 4)]
390
        add     [edi], eax
391
 
392
        ; Account for year.
393
        movzx   eax, word[esi + 6]
394
        sub     eax, 1970
395
        mov     ecx, (60 * 60 * 24) * 365       ; Seconds in a year.
396
        mul     ecx
397
        add     [edi], eax
398
 
399
        ; Seconds.
400
        movzx   eax, byte[esi + 0]
401
        add     [edi], eax
402
 
403
        ; Minutes.
404
        movzx   eax, byte[esi + 1]
405
        mov     ecx, 60
406
        mul     ecx
407
        add     [edi], eax
408
 
409
        ; Hours.
410
        movzx   eax, byte[esi + 2]
411
        mov     ecx, (60 * 60)
412
        mul     ecx
413
        add     [edi], eax
414
 
415
    ; The time wanted is before the epoch; handle it here.
416
    .negative:
417
        ; TODO.
418
 
419
    .ret:
420
        pop     edx ecx ebx eax
421
        ret
422
 
423
; Recommended move to some kernel-wide alloc handling code.
424
macro KERNEL_ALLOC store, label
425
{
426
        call    kernel_alloc
427
        mov     store, eax
428
        test    eax, eax
429
        jz      label
430
}
431
 
432
macro KERNEL_FREE data, label
433
{
434
        cmp     data, 0
435
        jz      label
436
        push    data
437
        call    kernel_free
438
}
439
 
440
struct EXTFS PARTITION
441
        lock MUTEX
442
        partition_flags                dd ?
443
        log_block_size                 dd ?
444
        block_size                     dd ?
445
        count_block_in_block           dd ?
446
        blocks_per_group               dd ?
447
        global_desc_table              dd ?
448
        root_inode                     dd ?         ; Pointer to root inode in memory.
449
        inode_size                     dd ?
450
        count_pointer_in_block         dd ?         ; (block_size / 4)
451
        count_pointer_in_block_square  dd ?         ; (block_size / 4)**2
452
        ext2_save_block                dd ?         ; Block for 1 global procedure.
453
        ext2_temp_block                dd ?         ; Block for small procedures.
454
        ext2_save_inode                dd ?         ; inode for global procedures.
455
        ext2_temp_inode                dd ?         ; inode for small procedures.
456
        groups_count                   dd ?
457
        superblock                     rd 1024/4
458
ends
459
 
460
; EXT2 revisions.
461
EXT2_GOOD_OLD_REV    = 0
462
 
463
; For fs_type.
464
FS_TYPE_UNDEFINED    = 0
465
FS_TYPE_EXT          = 2
466
 
467
; Some set inodes.
468
EXT2_BAD_INO         = 1
469
EXT2_ROOT_INO        = 2
470
EXT2_ACL_IDX_INO     = 3
471
EXT2_ACL_DATA_INO    = 4
472
EXT2_BOOT_LOADER_INO = 5
473
EXT2_UNDEL_DIR_INO   = 6
474
 
475
; EXT2_SUPER_MAGIC.
476
EXT2_SUPER_MAGIC     = 0xEF53
477
EXT2_VALID_FS        = 1
478
 
479
; Flags defining i_mode values.
480
EXT2_S_IFMT          = 0xF000           ; Mask for file type.
481
 
482
EXT2_S_IFREG         = 0x8000           ; Regular file.
483
EXT2_S_IFDIR         = 0x4000           ; Directory.
484
 
485
; File type defining values in directory entry.
486
EXT2_FT_REG_FILE     = 1                ; Regular file.
487
EXT2_FT_DIR          = 2                ; Directory.
488
 
489
; Flags used by KolibriOS.
490
FS_FT_HIDDEN         = 2
491
FS_FT_DIR            = 0x10             ; Directory.
492
 
493
; ext2 partition flags.
494
EXT2_RO              = 0x01
495
 
496
FS_FT_ASCII          = 0                ; Name in ASCII.
497
FS_FT_UNICODE        = 1                ; Name in Unicode.
498
 
499
EXT2_FEATURE_INCOMPAT_FILETYPE = 0x0002 ; Have file type in directory entry.
500
EXT4_FEATURE_INCOMPAT_EXTENTS  = 0x0040 ; Extents.
501
EXT4_FEATURE_INCOMPAT_FLEX_BG  = 0x0200 ; Flexible block groups.
502
 
503
EXT2_FEATURE_RO_COMPAT_SPARSE_SUPER = 0x0001 ; Sparse Superblock
504
EXT2_FEATURE_RO_COMPAT_LARGE_FILE   = 0x0002 ; Large file support (64-bit file size)
505
 
506
; Implemented ext[2,3,4] features.
507
EXT4_FEATURE_INCOMPAT_SUPP = EXT2_FEATURE_INCOMPAT_FILETYPE \
508
                             or EXT4_FEATURE_INCOMPAT_EXTENTS \
509
                             or EXT4_FEATURE_INCOMPAT_FLEX_BG
510
 
511
; Implemented features which otherwise require "read-only" mount.
512
EXT2_FEATURE_RO_COMPAT_SUPP = EXT2_FEATURE_RO_COMPAT_SPARSE_SUPER \
513
                              or EXT2_FEATURE_RO_COMPAT_LARGE_FILE
514
 
515
; ext4 features not support for write.
516
EXT4_FEATURE_INCOMPAT_W_NOT_SUPP = EXT4_FEATURE_INCOMPAT_EXTENTS \
517
                                   or EXT4_FEATURE_INCOMPAT_FLEX_BG
518
 
519
; Flags specified in i_flags.
520
EXT2_EXTENTS_FL      = 0x00080000       ; Extents.
521
 
522
struct  EXT2_INODE_STRUC
523
        i_mode          dw ?
524
        i_uid           dw ?
525
        i_size          dd ?
526
        i_atime         dd ?
527
        i_ctime         dd ?
528
        i_mtime         dd ?
529
        i_dtime         dd ?
530
        i_gid           dw ?
531
        i_links_count   dw ?
532
        i_blocks        dd ?
533
        i_flags         dd ?
534
        i_osd1          dd ?
535
        i_block         rd 15
536
        i_generation    dd ?
537
        i_file_acl      dd ?
538
        i_dir_acl       dd ?
539
        i_faddr         dd ?
540
        i_osd2          dd ?        ; 12 bytes.
541
ends
542
 
543
struct  EXT2_DIR_STRUC
544
        inode           dd ?
545
        rec_len         dw ?
546
        name_len        db ?
547
        file_type       db ?
548
        name            db ?         ; 255 (max) bytes.
549
ends
550
 
551
struct  EXT2_BLOCK_GROUP_DESC
552
        block_bitmap            dd ?         ; +0
553
        inode_bitmap            dd ?         ; +4
554
        inode_table             dd ?         ; +8
555
        free_blocks_count       dw ?         ; +12
556
        free_inodes_count       dw ?         ; +14
557
        used_dirs_count         dw ?         ; +16
558
        pad                     dw ?         ; +18
559
        reserved                rb 12        ; +20
560
ends
561
 
562
struct  EXT2_SB_STRUC
563
        inodes_count            dd ?         ; +0
564
        blocks_count            dd ?         ; +4
565
        r_block_count           dd ?         ; +8
566
        free_block_count        dd ?         ; +12
567
        free_inodes_count       dd ?         ; +16
568
        first_data_block        dd ?         ; +20
569
        log_block_size          dd ?         ; +24
570
        log_frag_size           dd ?         ; +28
571
        blocks_per_group        dd ?         ; +32
572
        frags_per_group         dd ?         ; +36
573
        inodes_per_group        dd ?         ; +40
574
        mtime                   dd ?         ; +44
575
        wtime                   dd ?         ; +48
576
        mnt_count               dw ?         ; +52
577
        max_mnt_count           dw ?         ; +54
578
        magic                   dw ?         ; +56
579
        state                   dw ?         ; +58
580
        errors                  dw ?         ; +60
581
        minor_rev_level         dw ?         ; +62
582
        lastcheck               dd ?         ; +64
583
        check_intervals         dd ?         ; +68
584
        creator_os              dd ?         ; +72
585
        rev_level               dd ?         ; +76
586
        def_resuid              dw ?         ; +80
587
        def_resgid              dw ?         ; +82
588
        first_ino               dd ?         ; +84
589
        inode_size              dw ?         ; +88
590
        block_group_nr          dw ?         ; +90
591
        feature_compat          dd ?         ; +92
592
        feature_incompat        dd ?         ; +96
593
        feature_ro_compat       dd ?         ; +100
594
        uuid                    rb 16        ; +104
595
        volume_name             rb 16        ; +120
596
        last_mounted            rb 64        ; +136
597
        algo_bitmap             dd ?         ; +200
598
        prealloc_blocks         db ?         ; +204
599
        preallock_dir_blocks    db ?         ; +205
600
        reserved_gdt_blocks     dw ?         ; +206
601
        journal_uuid            rb 16        ; +208
602
        journal_inum            dd ?         ; +224
603
        journal_dev             dd ?         ; +228
604
        last_orphan             dd ?         ; +232
605
        hash_seed               rd 4         ; +236
606
        def_hash_version        db ?         ; +252
607
        reserved                rb 3         ; +253 (reserved)
608
        default_mount_options   dd ?         ; +256
609
        first_meta_bg           dd ?         ; +260
610
        mkfs_time               dd ?         ; +264
611
        jnl_blocks              rd 17        ; +268
612
        blocks_count_hi         dd ?         ; +336
613
        r_blocks_count_hi       dd ?         ; +340
614
        free_blocks_count_hi    dd ?         ; +344
615
        min_extra_isize         dw ?         ; +348
616
        want_extra_isize        dw ?         ; +350
617
        flags                   dd ?         ; +352
618
        raid_stride             dw ?         ; +356
619
        mmp_interval            dw ?         ; +358
620
        mmp_block               dq ?         ; +360
621
        raid_stripe_width       dd ?         ; +368
622
        log_groups_per_flex     db ?         ; +372
623
ends
624
 
625
; Header block extents.
626
struct EXT4_EXTENT_HEADER
627
        eh_magic        dw ?    ; Magic value of 0xF30A, for ext4.
628
        eh_entries      dw ?    ; Number of blocks covered by the extent.
629
        eh_max          dw ?    ; Capacity of entries.
630
        eh_depth        dw ?    ; Tree depth (if 0, extents in the array are not extent indexes)
631
        eh_generation   dd ?    ; ???
632
ends
633
 
634
; Extent.
635
struct EXT4_EXTENT
636
        ee_block        dd ?    ; First logical block extent covers.
637
        ee_len          dw ?    ; Number of blocks covered by extent.
638
        ee_start_hi     dw ?    ; Upper 16 bits of 48-bit address (unused in KOS)
639
        ee_start_lo     dd ?    ; Lower 32 bits of 48-bit address.
640
ends
641
 
642
; Index on-disk structure; pointer to block of extents/indexes.
643
struct EXT4_EXTENT_IDX
644
        ei_block        dd ?    ; Covers logical blocks from here.
645
        ei_leaf_lo      dd ?    ; Lower 32-bits of pointer to the physical block of the next level.
646
        ei_leaf_hi      dw ?    ; Higher 16-bits (unused in KOS).
647
        ei_unused       dw ?    ; Reserved.
648
ends