Subversion Repositories Kolibri OS

Rev

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