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
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
 
4067 shikhin 493
EXT2_S_IRUSR         = 0x0100           ; User read
494
EXT2_S_IWUSR         = 0x0080           ; User write
495
EXT2_S_IXUSR         = 0x0040           ; User execute
496
EXT2_S_IRGRP         = 0x0020           ; Group read
497
EXT2_S_IWGRP         = 0x0010           ; Group write
498
EXT2_S_IXGRP         = 0x0008           ; Group execute
499
EXT2_S_IROTH         = 0x0004           ; Others read
500
EXT2_S_IWOTH         = 0x0002           ; Others write
501
EXT2_S_IXOTH         = 0x0001           ; Others execute
502
 
503
PERMISSIONS          = EXT2_S_IRUSR or EXT2_S_IWUSR \
504
                       or EXT2_S_IRGRP or EXT2_S_IWGRP \
505
                       or EXT2_S_IROTH or EXT2_S_IWOTH
506
 
3935 shikhin 507
; File type defining values in directory entry.
508
EXT2_FT_REG_FILE     = 1                ; Regular file.
509
EXT2_FT_DIR          = 2                ; Directory.
510
 
511
; Flags used by KolibriOS.
512
FS_FT_HIDDEN         = 2
513
FS_FT_DIR            = 0x10             ; Directory.
514
 
515
; ext2 partition flags.
516
EXT2_RO              = 0x01
517
 
518
FS_FT_ASCII          = 0                ; Name in ASCII.
519
FS_FT_UNICODE        = 1                ; Name in Unicode.
520
 
521
EXT2_FEATURE_INCOMPAT_FILETYPE = 0x0002 ; Have file type in directory entry.
522
EXT4_FEATURE_INCOMPAT_EXTENTS  = 0x0040 ; Extents.
523
EXT4_FEATURE_INCOMPAT_FLEX_BG  = 0x0200 ; Flexible block groups.
524
 
525
EXT2_FEATURE_RO_COMPAT_SPARSE_SUPER = 0x0001 ; Sparse Superblock
526
EXT2_FEATURE_RO_COMPAT_LARGE_FILE   = 0x0002 ; Large file support (64-bit file size)
527
 
528
; Implemented ext[2,3,4] features.
529
EXT4_FEATURE_INCOMPAT_SUPP = EXT2_FEATURE_INCOMPAT_FILETYPE \
530
                             or EXT4_FEATURE_INCOMPAT_EXTENTS \
531
                             or EXT4_FEATURE_INCOMPAT_FLEX_BG
532
 
533
; Implemented features which otherwise require "read-only" mount.
534
EXT2_FEATURE_RO_COMPAT_SUPP = EXT2_FEATURE_RO_COMPAT_SPARSE_SUPER \
535
                              or EXT2_FEATURE_RO_COMPAT_LARGE_FILE
536
 
537
; ext4 features not support for write.
538
EXT4_FEATURE_INCOMPAT_W_NOT_SUPP = EXT4_FEATURE_INCOMPAT_EXTENTS \
539
                                   or EXT4_FEATURE_INCOMPAT_FLEX_BG
540
 
541
; Flags specified in i_flags.
542
EXT2_EXTENTS_FL      = 0x00080000       ; Extents.
543
 
544
struct  EXT2_INODE_STRUC
545
        i_mode          dw ?
546
        i_uid           dw ?
547
        i_size          dd ?
548
        i_atime         dd ?
549
        i_ctime         dd ?
550
        i_mtime         dd ?
551
        i_dtime         dd ?
552
        i_gid           dw ?
553
        i_links_count   dw ?
554
        i_blocks        dd ?
555
        i_flags         dd ?
556
        i_osd1          dd ?
557
        i_block         rd 15
558
        i_generation    dd ?
559
        i_file_acl      dd ?
560
        i_dir_acl       dd ?
561
        i_faddr         dd ?
562
        i_osd2          dd ?        ; 12 bytes.
563
ends
564
 
565
struct  EXT2_DIR_STRUC
566
        inode           dd ?
567
        rec_len         dw ?
568
        name_len        db ?
569
        file_type       db ?
570
        name            db ?         ; 255 (max) bytes.
571
ends
572
 
573
struct  EXT2_BLOCK_GROUP_DESC
574
        block_bitmap            dd ?         ; +0
575
        inode_bitmap            dd ?         ; +4
576
        inode_table             dd ?         ; +8
577
        free_blocks_count       dw ?         ; +12
578
        free_inodes_count       dw ?         ; +14
579
        used_dirs_count         dw ?         ; +16
580
        pad                     dw ?         ; +18
581
        reserved                rb 12        ; +20
582
ends
583
 
584
struct  EXT2_SB_STRUC
585
        inodes_count            dd ?         ; +0
586
        blocks_count            dd ?         ; +4
587
        r_block_count           dd ?         ; +8
588
        free_block_count        dd ?         ; +12
589
        free_inodes_count       dd ?         ; +16
590
        first_data_block        dd ?         ; +20
591
        log_block_size          dd ?         ; +24
592
        log_frag_size           dd ?         ; +28
593
        blocks_per_group        dd ?         ; +32
594
        frags_per_group         dd ?         ; +36
595
        inodes_per_group        dd ?         ; +40
596
        mtime                   dd ?         ; +44
597
        wtime                   dd ?         ; +48
598
        mnt_count               dw ?         ; +52
599
        max_mnt_count           dw ?         ; +54
600
        magic                   dw ?         ; +56
601
        state                   dw ?         ; +58
602
        errors                  dw ?         ; +60
603
        minor_rev_level         dw ?         ; +62
604
        lastcheck               dd ?         ; +64
605
        check_intervals         dd ?         ; +68
606
        creator_os              dd ?         ; +72
607
        rev_level               dd ?         ; +76
608
        def_resuid              dw ?         ; +80
609
        def_resgid              dw ?         ; +82
610
        first_ino               dd ?         ; +84
611
        inode_size              dw ?         ; +88
612
        block_group_nr          dw ?         ; +90
613
        feature_compat          dd ?         ; +92
614
        feature_incompat        dd ?         ; +96
615
        feature_ro_compat       dd ?         ; +100
616
        uuid                    rb 16        ; +104
617
        volume_name             rb 16        ; +120
618
        last_mounted            rb 64        ; +136
619
        algo_bitmap             dd ?         ; +200
620
        prealloc_blocks         db ?         ; +204
621
        preallock_dir_blocks    db ?         ; +205
622
        reserved_gdt_blocks     dw ?         ; +206
623
        journal_uuid            rb 16        ; +208
624
        journal_inum            dd ?         ; +224
625
        journal_dev             dd ?         ; +228
626
        last_orphan             dd ?         ; +232
627
        hash_seed               rd 4         ; +236
628
        def_hash_version        db ?         ; +252
629
        reserved                rb 3         ; +253 (reserved)
630
        default_mount_options   dd ?         ; +256
631
        first_meta_bg           dd ?         ; +260
632
        mkfs_time               dd ?         ; +264
633
        jnl_blocks              rd 17        ; +268
634
        blocks_count_hi         dd ?         ; +336
635
        r_blocks_count_hi       dd ?         ; +340
636
        free_blocks_count_hi    dd ?         ; +344
637
        min_extra_isize         dw ?         ; +348
638
        want_extra_isize        dw ?         ; +350
639
        flags                   dd ?         ; +352
640
        raid_stride             dw ?         ; +356
641
        mmp_interval            dw ?         ; +358
642
        mmp_block               dq ?         ; +360
643
        raid_stripe_width       dd ?         ; +368
644
        log_groups_per_flex     db ?         ; +372
645
ends
646
 
647
; Header block extents.
648
struct EXT4_EXTENT_HEADER
649
        eh_magic        dw ?    ; Magic value of 0xF30A, for ext4.
650
        eh_entries      dw ?    ; Number of blocks covered by the extent.
651
        eh_max          dw ?    ; Capacity of entries.
652
        eh_depth        dw ?    ; Tree depth (if 0, extents in the array are not extent indexes)
653
        eh_generation   dd ?    ; ???
654
ends
655
 
656
; Extent.
657
struct EXT4_EXTENT
658
        ee_block        dd ?    ; First logical block extent covers.
659
        ee_len          dw ?    ; Number of blocks covered by extent.
660
        ee_start_hi     dw ?    ; Upper 16 bits of 48-bit address (unused in KOS)
661
        ee_start_lo     dd ?    ; Lower 32 bits of 48-bit address.
662
ends
663
 
664
; Index on-disk structure; pointer to block of extents/indexes.
665
struct EXT4_EXTENT_IDX
666
        ei_block        dd ?    ; Covers logical blocks from here.
667
        ei_leaf_lo      dd ?    ; Lower 32-bits of pointer to the physical block of the next level.
668
        ei_leaf_hi      dw ?    ; Higher 16-bits (unused in KOS).
669
        ei_unused       dw ?    ; Reserved.
670
ends