Subversion Repositories Kolibri OS

Rev

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

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