source: grub-pc/trunk/fuentes/debian/grub-extras/ntldr-img/ntfsbs.S @ 22

Last change on this file since 22 was 22, checked in by mabarracus, 4 years ago

updated version and apply net.ifnames=0 into debian/rules

File size: 25.2 KB
Line 
1/*
2 *  GRUB Utilities --  Utilities for GRUB Legacy, GRUB2 and GRUB for DOS
3 *  Copyright (C) 2007 Bean (bean123@126.com)
4 *
5 *  This program is free software; you can redistribute it and/or modify
6 *  it under the terms of the GNU General Public License as published by
7 *  the Free Software Foundation; either version 2 of the License, or
8 *  (at your option) any later version.
9 *
10 *  This program is distributed in the hope that it will be useful,
11 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
12 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13 *  GNU General Public License for more details.
14 *
15 *  You should have received a copy of the GNU General Public License
16 *  along with this program; if not, write to the Free Software
17 *  Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
18 */
19
20/* NTFS boot sector for loading GRLDR , written by bean
21 *
22 * This file can be compiled as standaolne boot sector, or it can be embeded in
23 * GRLDR.MBR at 0xA00 , right after the ext2 boot sector
24 *
25 * To compile the standalone ntfsbs.bin:
26 *     gcc -c -o ntfsbs.o ntfsbs.S
27 *     gcc -nostdlib -Wl,-N -Wl,-Ttext -Wl,7C00 -o ntfsbs_exec ntfsbs.o
28 *     objcopy -O binary ntfsbs_exec ntfsbs.bin
29 *
30 * To install the standalone ntfsbs.bin:
31 *     grubinst --restore=ntfsbs.bin DEVICE_OR_FILE
32 *
33 * Where DEVICE_OR_FILE specify a NTFS partition
34 *
35 * Limitations:
36 *  1. Don't support >1K MFT record size, >4K INDEX record size
37 *  2. Don't support encrypted file
38 *  3. Don't support >4K non-resident attribute list and $BITMAP
39 *
40 */
41
42#ifndef INSIDE_GRLDR
43
44        .text
45
46        .code16
47#endif
48
49#define AT_STANDARD_INFORMATION 0x10
50#define AT_ATTRIBUTE_LIST       0x20
51#define AT_FILENAME             0x30
52#define AT_OBJECT_ID            0x40
53#define AT_SECURITY_DESCRIPTOR  0x50
54#define AT_VOLUME_NAME          0x60
55#define AT_VOLUME_INFORMATION   0x70
56#define AT_DATA                 0x80
57#define AT_INDEX_ROOT           0x90
58#define AT_INDEX_ALLOCATION     0xA0
59#define AT_BITMAP               0xB0
60#define AT_SYMLINK              0xC0
61#define AT_EA_INFORMATION       0xD0
62#define AT_EA                   0xE0
63
64#define MAX_MFT_SIZE    1               // 1<<(1+9) = 1024
65#define MAX_IDX_SIZE    3               // 1<<(3+9) = 4096
66
67#define LOADSEG_NT      0x2000
68
69#define MMFT_BASE       0x2000
70#define MMFT_EMFT       (MMFT_BASE +1024)
71#define MMFT_EBUF       (MMFT_BASE + 2048)
72
73#define CMFT_BASE       (MMFT_BASE + 6144)
74#define CMFT_EMFT       (CMFT_BASE + 1024)
75#define CMFT_EBUF       (CMFT_BASE + 2048)
76
77#define INDX_BASE       (CMFT_BASE + 6144)
78
79#define SBUF_BASE       (INDX_BASE + 4096)
80
81#define NTFS_Large_Structure_Error_Code 1
82#define NTFS_Corrupt_Error_Code         2
83#define NTFS_Run_Overflow_Error_Code    3
84#define NTFS_No_Data_Error_Code         4
85#define NTFS_Decompress_Error_Code      5
86
87#define NT_FG_COMP      1
88#define NT_FG_MMFT      2
89#define NT_FG_ALST      4
90#define NT_FG_GPOS      8
91
92#define nt_boot_drive   -2(%bp)
93#define nt_blocksize    -4(%bp)
94#define nt_spc          -5(%bp)
95#define nt_mft_size     -6(%bp)
96#define nt_idx_size     -7(%bp)
97#define nt_mft_start    -12(%bp)
98#define nt_remain_len   -16(%bp)
99//#define nt_file_count -18(%bp)
100
101#define nt_flag         (%di)
102#define nt_attr_cur     2(%di)
103#define nt_attr_nxt     4(%di)
104#define nt_attr_end     6(%di)
105#define nt_curr_vcn     8(%di)
106#define nt_curr_lcn     0x10(%di)
107#define nt_attr_ofs     0x14(%di)
108#define nt_target_vcn   0x18(%di)
109#define nt_read_count   0x1C(%di)
110#define nt_vcn_offset   0x20(%di)
111
112#define nt_emft_buf     1024(%di)
113#define nt_edat_buf     2048(%di)
114
115        .arch   i586
116
117Entry_nt:
118        jmp     1f
119
120        . = Entry_nt + 0x02
121
122        .byte   0x90    /* for CHS. Another possible value is 0x0e for LBA */
123
124        .ascii  "NTFS    "
125
126        .word   0       /* 0B - Bytes per sector */
127        .byte   0       /* 0D - Sectors per cluster */
128        .word   0       /* 0E - reserved sectors, unused */
129        .byte   0       /* 10 - number of FATs, unused */
130        .word   0       /* 11 - Max dir entries for FAT12/FAT16, unused */
131        .word   0       /* 13 - total sectors for FAT12/FAT16, unused */
132        .byte   0xF8    /* 15 - Media descriptor */
133        .word   0       /* 16 - sectors per FAT for FAT12/FAT16, unused */
134        .word   255     /* 18 - Sectors per track */
135        .word   63      /* 1A - Number of heads */
136nt_part_ofs:
137        .long   0       /* 1C - hidden sectors */
138        .long   0       /* 20 - total sectors for FAT32, unused */
139        .long   0x800080
140                        /* 24 - Usually 80 00 80 00, A value of 80 00 00 00 has
141                         * been seen on a USB thumb drive which is formatted
142                         * with NTFS under Windows XP. Note this is removable
143                         * media and is not partitioned, the drive as a whole
144                         * is NTFS formatted.
145                         */
146        .long   0,0     /* 28 - Number of sectors in the volume */
147        .long   0,0     /* 30 - LCN of VCN 0 of the $MFT */
148        .long   0,0     /* 38 - LCN of VCN 0 of the $MFTMirr */
149        .long   0       /* 40 - Clusters per MFT Record */
150        .long   4       /* 44 - Clusters per Index Record */
151        .long   0,0     /* 48 - Volume serial number */
152        .long   0       /* 50 - Checksum, usually 0 */
153
1541:
155
156        . = Entry_nt + 0x54
157
158        cli
159        cld
160
161        . = Entry_nt + 0x56
162
163        /* the byte at offset 0x57 stores the real partition number for read.
164         * the format program or the caller should set it to a correct value.
165         * For floppies, it should be 0xff, which stands for whole drive.
166         */
167
168        movb    $0xff, %dh      /* boot partition number */
169
170        xorw    %ax, %ax
171        movw    %ax, %ds
172        movw    $0x7c00, %bp
173        movw    %ax, %es
174
175        movw    %ax, %ss        /* stack and BP-relative moves up, too */
176        leaw    -0x20(%bp), %sp
177        sti
178
179        movw    %dx, nt_boot_drive
180
181        /* Test if your BIOS support LBA mode */
182        movb    $0x41, %ah
183        movw    $0x55AA, %bx
184        int     $0x13
185        jc      1f              /* No EBIOS */
186        cmpw    $0xAA55, %bx
187        jne     1f              /* No EBIOS */
188        testb   $1, %cl
189        jz      1f              /* No EBIOS */
190        /* EBIOS supported */
191        movb    $0x42, (ebios_nt - 1 - Entry_nt)(%bp)
1921:
193
194        cmpl    $0x42555247, (nt_sector_mark - Entry_nt)(%bp)
195        jz      1f                      // Must be called from GRLDR.MBR
196
197        movw    $0x7E00, %bx
198        movl    (nt_part_ofs - Entry_nt)(%bp), %eax
199        incl    %eax
200        call    readDisk_nt             // Load the second sector from disk
201        call    readDisk_nt             // Load the third sector from disk
202        call    readDisk_nt
2031:
204
205        xorl    %eax, %eax
206        movw    0xb(%bp), %ax           // Bytes per sector (blocksize)
207        movw    %ax, nt_blocksize
208
209        call    convert_to_power_2
210        movb    %cl, %bl
211        movb    0xd(%bp), %al           // Sectors per cluster
212        call    convert_to_power_2
213        movb    %cl, %ch
214        addb    %bl, %ch
215        subb    $9, %ch                 // 1<<ch = sectors per cluster
216        movb    %ch, nt_spc
217        movb    0x44(%bp), %al          // Index record size (high bits of eax is 0)
218        call    convert_size
219
220        cmpb    $MAX_IDX_SIZE, %cl
221        jbe     1f
222
223NTFS_Large_Structure_Error:
224        movb    $NTFS_Large_Structure_Error_Code, %al
225        jmp     NTFS_Error
226
2271:
228        movb    %cl, nt_idx_size
229
230        movb    0x40(%bp), %al          // MFT record size
231        call    convert_size
232
233        cmpb    $MAX_MFT_SIZE, %cl
234        jnz     NTFS_Large_Structure_Error
235
236        movb    %cl, nt_mft_size
237
238        movl    0x30(%bp), %eax
239        movl    0x34(%bp), %edx
240
241        movb    %ch, %cl                // ch still contains nt_spc
242
243        shldl   %cl, %eax, %edx
244        orl     %edx, %edx
245        jnz     NTFS_Large_Structure_Error
246
247        shll    %cl, %eax
248        addl    (nt_part_ofs - Entry_nt)(%bp), %eax
249        movl    %eax, nt_mft_start
250
251        movw    $1, %dx
252        movb    nt_mft_size, %cl
253        shlw    %cl, %dx
254        movw    %dx, %cx
255
256        movw    $MMFT_BASE, %bx
257        pushw   %bx
2581:
259        call    readDisk_nt
260        loop    1b
261
262        popw    %bx
263        cmpw    $0x4946, (%bx)          // "FI"
264        jnz     NTFS_Corrupt_Error
265
266        // dx should still contain the number of sectors in the MFT record
267        movw    %dx, %cx
268        call    ntfs_fixup
269
270        movw    %bx, %di
271        movb    $AT_DATA, %al           // find $DATA
272
273        call    ntfs_locate_attr
274        jc      NTFS_Corrupt_Error
275
276        movw    $CMFT_BASE, %bx
277        xorl    %eax, %eax
278        movb    $0x5, %al
279        call    ntfs_read_mft
280        movw    %bx, %di
281
282        jmp     ntfs_search
283
284// Convert the size of MFT and IDX block
285// Input:
286//     eax: size
287//     ch: spc
288// Output:
289//     cl: convert value
290convert_size:
291        orb     %al, %al
292        js      1f
293        movb    %ch, %cl
294        jmp     2f                      // Jump to 2 in convert_to_power_2
2951:
296        negb    %al
297        subb    $9, %al
298        movb    %al, %cl
299        ret
300
301// Convert number to a power of 2
302// Input:
303//     eax
304// Output:
305//     cl: 1<<cl = eax
306//     eax: 0
307
308convert_to_power_2:
309        xorb    %cl, %cl
3102:
311        incb    %cl
312        shrl    $1, %eax
313        jnc     2b
314        decb    %cl
315        ret
316
317// Fixup the "FILE" and "INDX" record
318// Input:
319//     DS:BX - data buffer
320//     CX - buffer length in sectors
321//
322
323ntfs_fixup:
324        push    %bx
325        push    %di
326        movw    %bx, %di
327
328        movw    6(%bx), %ax             // Size of Update Sequence
329        decw    %ax
330        movw    %ax, %bx
331
332        mulw    nt_blocksize
333        shlw    $9, %cx
334        cmpw    %ax, %cx
335        jnz     NTFS_Corrupt_Error      // blocksize * count != size
336
337        movw    %bx, %cx                // cx = count
338
339        movw    %di, %bx
340        addw    4(%bx), %bx             // Offset to the update sequence
341        movw    (%bx), %ax              // Update Sequence Number
342        subw    $2, %di
343
3441:
345        addw    nt_blocksize, %di
346        addw    $2, %bx
347        cmpw    (%di), %ax
348        jnz     NTFS_Corrupt_Error
349        movw    (%bx), %dx
350        movw    %dx, (%di)
351        loop    1b
352
353        popw    %di
354        popw    %bx
355        ret
356
357NTFS_Corrupt_Error:
358        movb    $NTFS_Corrupt_Error_Code, %al
359        jmp     NTFS_Error
360
361/* Read a sector from disk, using LBA or CHS
362 * input:       EAX - 32-bit DOS sector number
363 *              ES:BX - destination buffer
364 *              (will be filled with 1 sector of data)
365 * output:      ES:BX points one byte after the last byte read.
366 *              EAX - next sector
367 */
368
369readDisk_nt:
370
371        pushal
372        xorl    %edx, %edx      /* EDX:EAX = LBA */
373        pushl   %edx            /* hi 32bit of sector number */
374        pushl   %eax            /* lo 32bit of sector number */
375        pushw   %es             /* buffer segment */
376        pushw   %bx             /* buffer offset */
377        pushw   $1              /* 1 sector to read */
378        pushw   $16             /* size of this parameter block */
379
380        xorl    %ecx, %ecx
381        pushl   0x18(%bp)       /* lo:sectors per track, hi:number of heads */
382        popw    %cx             /* ECX = sectors per track */
383        divl    %ecx            /* residue is in EDX */
384                                /* quotient is in EAX */
385        incw    %dx             /* sector number in DL */
386        popw    %cx             /* ECX = number of heads */
387        pushw   %dx             /* push sector number into stack */
388        xorw    %dx, %dx        /* EDX:EAX = cylinder * TotalHeads + head */
389        divl    %ecx            /* residue is in EDX, head number */
390                                /* quotient is in EAX, cylinder number */
391        xchgb   %dl, %dh        /* head number should be in DH */
392                                /* DL = 0 */
393        popw    %cx             /* pop sector number from stack */
394        xchgb   %al, %ch        /* lo 8bit cylinder should be in CH */
395                                /* AL = 0 */
396        shlb    $6, %ah         /* hi 2bit cylinder ... */
397        orb     %ah, %cl        /* ... should be in CL */
398
399        movw    $0x201, %ax     /* read 1 sector */
400ebios_nt: /* ebios_nt - 1 points to 0x02 that can be changed to 0x42 */
401
402//      cmpb    $0x0e, 2(%bp)   /* force LBA? */
403//      jnz     1f              /* no, continue */
404//      movb    $0x42, %ah      /* yes, use extended disk read */
405//1:
406        movw    %sp, %si        /* DS:SI points to disk address packet */
407        movb    nt_boot_drive, %dl      /* hard disk drive number */
408
409        int     $0x13
410
411        popaw                   /* remove parameter block from stack */
412        popal
413        jc      disk_error_nt   /* disk read error, jc 1f if caller handles */
414        incl    %eax            /* next sector */
415        addw    0x0b(%bp), %bx  /* bytes per sector */
416        jnc     1f              /* 64K bound check */
417        pushw   %dx
418        movw    %es, %dx
419        addb    $0x10, %dh      /* add 1000h to ES */
420                                /* here, carry is cleared */
421        movw    %dx, %es
422        popw    %dx
4231:
424        /* carry stored on disk read error */
425        ret
426
427msg_DiskReadError_nt:
428
429        .ascii  "0\0"
430
431msg_NTFS_Not_Found_Error:
432        .ascii "No "
433
434nt_boot_image:
435#ifdef  BOOTGRUB2
436        .ascii "g2ldr\0"
437#else
438        .ascii "grldr\0"
439#endif
440
441        . = nt_boot_image + 8
442
443nt_boot_image_end:
444
445NTFS_Error:
446        addb    %al, (msg_DiskReadError_nt - Entry_nt)(%bp)
447        jmp     disk_error_nt
448
449// Kernel load address, located at 0x1E8
450        . = Entry_nt + 0x1e8
451
452nt_loadseg_off:
453        .word   0
454        .word   LOADSEG_NT
455
456// Boot image offset and length, located at 0x1EE
457// Lower 11 bit is offset, higher 5 bit is length
458        . = Entry_nt + 0x1ec
459
460nt_boot_image_ofs:
461        .word (nt_boot_image - Entry_nt)+(nt_boot_image_end - nt_boot_image-1)*2048
462
463        . = Entry_nt + 0x1ee
464
465disk_error_nt:
466
467        movw    $(msg_DiskReadError_nt - Entry_nt + 0x7c00), %si
468
469boot_error_nt:
470
471/* prints string DS:SI (modifies AX BX SI) */
472
473//print_32:
4741:
475        lodsb   (%si), %al      /* get token */
476        //xorw  %bx, %bx        /* video page 0 */
477        movb    $0x0e, %ah      /* print it */
478        int     $0x10           /* via TTY mode */
479        cmpb    $0, %al         /* end of string? */
480        jne     1b              /* until done */
481
482        /* The caller will change this to
483         *      ljmp    $0x9400, $(try_next_partition - _start1)
484         */
485
4861:      jmp     1b
487
488        . = Entry_nt + 0x1fc
489
490        .word   0, 0xAA55
491
492// Here starts sector #2
493
494// Input:
495//     DI - current mft
496ntfs_search:
497        //movw  $0, nt_file_count
498        call    ntfs_init_attr
499        movb    $AT_INDEX_ROOT, %al
500
5011:
502        call    ntfs_find_attr
503        jc      NTFS_Not_Found_Error
504
505        cmpl    $0x180400,  8(%si)      // resident
506                                        // namelen = 4
507                                        // name offset = 0x18
508        jnz     1b
509        //cmpl  $0x490024, 0x18(%si)    // "$I"
510        //jnz   1b
511        //cmpl  $0x300033, 0x1C(%si)
512        //jnz   1b                      // "30"
513        //testw $0xC001, 12(%si)        // not compressed, encrypted or sparse
514        //jnz   1b
515
516        addw    0x14(%si), %si          // jump to attribute
517        cmpb    $0x30, (%si)
518        jnz     1b                      // test if it index filenames
519
520        addw    $0x10, %si              // skip the index root
521        addw    (%si), %si
522
523        call    ntfs_find_grldr
524        jnc     ntfs_final
525
526        call    ntfs_init_attr
527        movb    $AT_BITMAP, %al
5281:
529        call    ntfs_find_attr
530        jc      NTFS_Not_Found_Error
531        movw    9(%si), %bx
532        cmpb    $4, %bl
533        jnz     1b
534        //shrw  $4, %bx
535        //cmpl  $0x490024, (%bx, %si)   // "$I"
536        //jnz   1b
537        cmpb    $0, 8(%si)
538        jnz     1f
539        pushw   0x10(%si)
540        addw    0x14(%si), %si
541        pushw   %si
542        jmp     2f
5431:
544        pushw   0x30(%si)
545        xorl    %edx, %edx
546        movl    0x28(%si), %ecx
547        cmpw    $4096, %cx
548        ja      NTFS_Not_Found_Error
549        shrl    $9, %ecx
550        movw    $SBUF_BASE, %bx
551        pushw   %bx
552        call    ntfs_read_data
5532:
554
555        movb    $AT_INDEX_ALLOCATION, %al
556
5571:
558        call    ntfs_locate_attr
559        jc      NTFS_Not_Found_Error
560
561        cmpl    $0x400401, 8(%si)       // non-resident
562                                        // namelen = 4
563                                        // name offset = 0x40
564        jnz     1b
565        //cmpl  $0x490024, 0x40(%si)    // "$I"
566        //jnz   1b
567        //cmpl  $0x300033, 0x44(%si)
568        //jnz   1b                      // "30"
569        //testw $0xC001, 12(%si)        // not compressed, encrypted or sparse
570        //jnz   1b
571
572        movb    nt_idx_size, %cl
573        xorl    %ebx, %ebx
574        movb    $1, %bl
575        shll    %cl, %ebx               // ebx - index size
576        xorl    %edx, %edx              // edx - index offset
577
578
579        popw    %si
580        popw    %cx
581
5821:
583        pushw   %cx
584        lodsb   (%si), %al
585
586        movw    $8, %cx
5872:
588        pushw   %cx
589        pushw   %ax
590        testb   $1, %al
591        jz      3f
592        pushw   %si
593        pushl   %edx
594        pushl   %ebx
595
596        movl    %ebx, %ecx
597        movw    $INDX_BASE, %bx
598        call    ntfs_read_attr
599        jc      NTFS_Not_Found_Error
600        cmpw    $0x4E49, (%bx)          // "IN"
601        jnz     NTFS_Not_Found_Error
602        call    ntfs_fixup
603        movw    %bx, %si
604        addw    $0x18, %si
605        addw    (%si), %si
606
607        call    ntfs_find_grldr
608        jnc     ntfs_final_0
609
610        popl    %ebx
611        popl    %edx
612        popw    %si
613
6143:
615        addl    %ebx, %edx
616
617        popw    %ax
618        shrb    $1, %al
619        popw    %cx
620        loop    2b
621
622        popw    %cx
623        loop    1b
624
625        //pushw nt_file_count
626        //call  hex_out
627
628NTFS_Not_Found_Error:
629        leaw    (msg_NTFS_Not_Found_Error - Entry_nt)(%bp), %si
630        jmp     boot_error_nt
631
632ntfs_final_0:
633        //addw  $16, %sp
634
635// Input:
636//     DI - current mft
637//     SI - index entry
638ntfs_final:
639        cmpw    $0, 4(%si)
640        jnz     NTFS_Large_Structure_Error
641
642        movl    (%si), %eax
643        movw    %di, %bx
644        call    ntfs_read_mft
645
646        movb    $AT_DATA, %al
647        call    ntfs_locate_attr
648        jc      NTFS_No_Data_Error
649
650        cmpb    $1, 8(%si)              // non-resident / resident
651        jz      1f
652
653        movw    0x10(%si), %cx          // Resident
654        lesw    (nt_loadseg_off - Entry_nt)(%bp), %di
655        addw    0x14(%si), %si
656        rep     movsb   (%si), %es:(%di)
657        jmp     2f
658
6591:
660
661        xorl    %edx, %edx
662        movl    0x28(%si), %ecx         // Use allocate size instead of real size
663        shrl    $9, %ecx
664
665        lesw    (nt_loadseg_off - Entry_nt)(%bp), %bx
666        call    ntfs_read_data
667
668
6692:
670
671        //movb  $1, (do_pause - Entry_nt)(%bp)
672        //call  pause
673
674        movw    nt_boot_drive, %dx
675        ljmp    *(nt_loadseg_off - Entry_nt)(%bp)
676
677NTFS_No_Data_Error:
678        movb    $NTFS_No_Data_Error_Code, %al
679        jmp     NTFS_Error
680
681// Try to find GRLDR in the index
682// Input:
683//     DS:SI - points to index entry
684// Output:
685//     CF - status
686
687ntfs_find_grldr:
688        movw    %si, %bx
689        testb   $2, 0xC(%bx)
690        jz      1f
691        stc
692        ret
6931:
694        //incw  nt_file_count
695
696        xorb    %ch, %ch
697
698        pushw   %si
699        leaw    (nt_boot_image - Entry_nt)(%bp), %si
700        addw    $0x52, %bx              // The value at 0xA(%bx) is wrong sometimes (0x4C)
701        movb    -2(%bx), %cl
7021:
703        lodsb   (%si), %al
704        movb    (%bx), %ah
705        cmpb    $'A', %ah
706        jb      2f
707        cmpb    $'Z', %ah
708        ja      2f
709        addb    $('a'-'A'), %ah         // Convert to lowercase
7102:
711
712        cmpb    %ah, %al
713        jnz     3f                      // Not match
714
715        incw    %bx
716        incw    %bx
717        loop    1b
718
719        cmpb    $0,(%si)
720        jnz     3f
721
722        popw    %si
723        clc
724        ret                             // Match found
725
7263:
727
728        popw    %si
729        addw    8(%si), %si
730
731        jmp     ntfs_find_grldr
732
733// Locate an attribute
734// Input:
735//     DI - pointer to buffer
736//     AL - attribute
737ntfs_locate_attr:
738        call    ntfs_init_attr
739        call    ntfs_find_attr
740        jc      1f
7412:
742        testb   $NT_FG_ALST, nt_flag
743        jnz     2f
744        call    ntfs_find_attr
745        jnc     2b
746        call    ntfs_init_attr
747        call    ntfs_find_attr
7482:
749        clc
7501:
751        ret
752
753// Prepare to find attribute
754// Input:
755//     DI - pointer to buffer
756ntfs_init_attr:
757        pushw   %ax
758        xorw    %ax, %ax
759        movw    %ax, nt_flag
760        movw    %ax, nt_attr_end
761        movw    nt_attr_ofs, %ax
762        addw    %di, %ax
763        movw    %ax, nt_attr_nxt
764        popw    %ax
765        cmpw    $MMFT_BASE, %di
766        jnz     1f
767        orb     $NT_FG_MMFT, nt_flag
7681:
769        ret
770
771// Find an attribute
772// Input:
773//     DI - pointer to buffer
774//     AL - attribute
775// Output:
776//     SI - current item
777//     CF - status
778ntfs_find_attr:
779        movw    nt_attr_nxt, %bx
780        testb   $NT_FG_ALST, nt_flag
781        jnz     6f
7821:
783        movw    %bx, %si
784        cmpb    $0xFF, (%si)
785        jz      3f
786
787        cmpb    $AT_ATTRIBUTE_LIST, (%si)
788        jnz     2f
789        movw    %si, nt_attr_end
7902:
791        addw    4(%bx), %bx
792        cmpb    %al, (%si)
793        jnz     1b
794        movw    %bx, nt_attr_nxt
795        movw    %si, nt_attr_cur
7962:
797        ret
7983:
799        cmpw    $1, nt_attr_end
800        jb      2b
801        movw    nt_attr_end, %si
802        cmpb    $0, 8(%si)
803        jnz     4f
804        movw    %si, %bx
805        addw    0x14(%bx), %bx
806        addw    4(%si), %si
807        jmp     5f
8084:
809        movl    0x28(%si), %ecx
810        shrl    $9, %ecx
811        cmpw    $8, %cx
812        ja      NTFS_Corrupt_Error
813        leaw    nt_edat_buf, %bx
814        pushw   %ax
815        xorl    %edx, %edx
816        call    ntfs_read_data
817        popw    %ax
818        jc      2b
819        movw    0x30(%si), %si
820        addw    %bx, %si
8215:
822        movw    %si, nt_attr_end
823        orb     $NT_FG_ALST, nt_flag
824        testb   $NT_FG_MMFT, nt_flag
825        jz      6f
826        cmpb    $AT_DATA, %al
827        jnz     6f
828        call    ntfs_fix_mmft
8296:
830        movw    %bx, %si
831        cmpw    nt_attr_end, %bx
832        jb      1f
8337:
834        stc
835        ret
8361:
837        addw    4(%bx), %bx
838        cmpb    %al, (%si)
839        jnz     6b
840
841        pushw   %ax
842        pushw   %es
843        pushw   %ds
844        popw    %es
845        movw    %si, nt_attr_cur
846        movw    %bx, nt_attr_nxt
847        movl    0x10(%si), %eax
848        leaw    nt_emft_buf, %bx
849        testb   $NT_FG_MMFT, nt_flag
850        jnz     2f
851        call    ntfs_read_mft
852        jmp     3f
8532:
854        pushw   %bx
855        call    readDisk_nt
856        movl    0x14(%si), %eax
857        call    readDisk_nt
858        popw    %bx
859        cmpw    $0x4946, (%bx)                  // "FI"
860        jnz     NTFS_Corrupt_Error
861        movw    $2, %cx
862        call    ntfs_fixup
8633:
864        popw    %es
865        popw    %ax
866        addw    0x14(%bx), %bx
8674:
868        cmpb    $0xFF, (%bx)
869        jz      7b
870        cmpb    %al, (%bx)
871        jz      5f
872        addw    4(%bx), %bx
873        jmp     4b
8745:
875        movw    %bx, %si
876        ret
877
878// Fix $MFT
879// Input:
880//     DI - pointer to buffer
881//     BX - attr cur
882ntfs_fix_mmft:
883        pushw   %ax
884        orb     $NT_FG_GPOS, nt_flag
885
8861:
887        cmpw    nt_attr_end, %bx
888        jae     NTFS_Corrupt_Error
889        cmpb    %al, (%bx)
890        jz      2f
891        addw    4(%bx), %bx
892        jmp     1b
8932:
894
895        movw    %bx, nt_attr_cur
896
897        movl    nt_mft_start, %eax
898        movl    %eax, 0x10(%bx)
899        incl    %eax
900        movl    %eax, 0x14(%bx)
9011:
902        addw    4(%bx), %bx
903
904        cmpw    nt_attr_end, %bx
905        jae     2f
906        cmpb    $AT_DATA, (%bx)
907        jnz     2f
908
909        movl    0x10(%bx), %edx
910        movb    nt_mft_size, %cl
911        shll    %cl, %edx
912
913        call    ntfs_read_attr
914
915        orl     %eax, %eax
916        jz      NTFS_Corrupt_Error
917        movl    %eax, 0x10(%bx)
918        movl    %edx, 0x14(%bx)
919        jmp     1b
9202:
921        movw    nt_attr_cur, %bx
922        andb    $(~NT_FG_GPOS), nt_flag
923        popw    %ax
924
925        ret
926
927// Read MFT record
928// Input:
929//     DS:BX - buffer
930//     EAX - mft number
931ntfs_read_mft:
932        pushw   %di
933        movw    $MMFT_BASE, %di
934        movb    nt_mft_size, %cl
935        shll    %cl, %eax
936        movl    %eax, %edx
937        movl    $1, %eax
938        shll    %cl, %eax
939        movl    %eax, %ecx
940        call    ntfs_read_attr
941        jc      NTFS_Corrupt_Error
942        cmpw    $0x4946, (%bx)                  // "FI"
943        jnz     NTFS_Corrupt_Error
944        call    ntfs_fixup
945        popw    %di
946        ret
947
948// Read attribute
949// Input:
950//     DI - pointer to buffer
951//     ES:BX - buffer
952//     EDX - start sector
953//     ECX - sector count
954// Output:
955//     CF - status
956ntfs_read_attr:
957        pushw   nt_attr_cur
958        pushl   %edx
959        pushl   %ecx
960        pushw   %bx
961
962        movw    nt_attr_cur, %si
963        movb    (%si), %al
964
965        testb   $NT_FG_ALST, nt_flag
966        jz      2f
967        movw    %si, %bx
968        movb    nt_spc, %cl
969        shrl    %cl, %edx
970
9711:
972        cmpw    nt_attr_end, %bx
973        jae     2f
974        cmpb    %al, (%bx)
975        jnz     2f
976        cmpl    %edx, 8(%bx)
977        ja      2f
978        movw    %bx, %si
979        addw    4(%bx), %bx
980        jmp     1b
9812:
982
983        movw    %si, nt_attr_nxt
984        call    ntfs_find_attr
985
986        popw    %bx
987        popl    %ecx
988        popl    %edx
989        jc      1f
990        call    ntfs_read_data
991        clc
9921:
993        popw    nt_attr_cur
994        ret
995
996// Read data
997// Input:
998//     DI: pointer to buffer
999//     SI: current item
1000//     ES:BX: buffer
1001//     EDX: start sector
1002//     ECX: sector count
1003ntfs_read_data:
1004        pushw   %cx
1005        pushw   %bx
1006        testb   $1, 8(%si)
1007        jz      NTFS_Corrupt_Error
1008        movb    0xC(%si), %al
1009        andb    $1, %al
1010        orb     %al, nt_flag
1011
1012        movl    %ecx, nt_read_count
1013        movb    nt_spc, %cl
1014
1015        movl    %edx, %eax
1016        shrl    %cl, %eax
1017        movl    %eax, nt_target_vcn
1018        shll    %cl, %eax
1019        subl    %eax, %edx
1020        movl    %edx, nt_vcn_offset
1021
1022        xorw    %dx, %dx                // edx - next VCN
1023        movl    %edx, nt_curr_lcn
1024
1025        movl    0x10(%si), %edx
1026
1027        addw    0x20(%si), %si
10281:
1029        call    ntfs_runlist_read_block
1030
1031        cmpl    nt_target_vcn, %edx
1032        jbe     1b
10331:
1034        movb    nt_spc, %cl
1035
1036        orl     %eax, %eax              // sparse
1037        jz      2f
1038
1039        movl    nt_target_vcn, %eax
1040        subl    nt_curr_vcn, %eax
1041        addl    nt_curr_lcn, %eax
1042
1043        shll    %cl, %eax
1044        addl    nt_vcn_offset, %eax
1045
1046        testb   $NT_FG_GPOS, nt_flag
1047        jz      3f
1048        pushl   %eax
1049        incl    %eax
1050        subl    nt_curr_vcn, %edx
1051        addl    nt_curr_lcn, %edx
1052        shll    %cl, %edx
1053        cmpl    %eax, %edx
1054        jnz     4f
1055        pushw   %cx
1056        call    ntfs_runlist_read_block
1057        popw    %cx
1058        movl    nt_curr_lcn, %eax
1059        shll    %cl, %eax
10604:
1061        movl    %eax, %edx
1062        popl    %eax
1063        addl    (nt_part_ofs - Entry_nt)(%bp), %edx
10643:
1065
1066        addl    (nt_part_ofs - Entry_nt)(%bp), %eax
1067
10682:
1069        testb   $NT_FG_GPOS, nt_flag
1070        jnz     1f
1071
1072        pushl   %ebx
1073        movl    %edx, %ebx
1074        subl    nt_target_vcn, %ebx
1075        shll    %cl, %ebx
1076        movl    %ebx, %ecx
1077        popl    %ebx
1078
1079        subl    nt_vcn_offset, %ecx
1080        movl    $0, nt_vcn_offset
1081        cmpl    nt_read_count, %ecx
1082        jbe     2f
1083        movl    nt_read_count, %ecx
10842:
1085
1086        pushl   %ecx
1087
1088        orl     %eax, %eax
1089        jnz     3f
1090        call    ntfs_sparse_block
1091        jmp     4f
1092
10933:
1094        call    readDisk_nt
1095        loop    3b
1096
10974:
1098        popl    %ecx
1099        subl    %ecx, nt_read_count
1100        jbe     1f
1101
1102        movl    %edx, nt_target_vcn
1103        call    ntfs_runlist_read_block
1104        jmp     1b
1105
11061:
1107        popw    %bx
1108        popw    %cx
1109        ret
1110
1111// Read run list data
1112// Input:
1113//     CL = number of bytes
1114// Output:
1115//     EAX = read bytes
1116//     SI points to the next unhandled byte
1117
1118ntfs_runlist_read_data:
1119        pushw   %cx
1120        orb     %cl, %cl
1121        jnz     1f
1122        popw    %cx
1123        xorl    %eax, %eax
1124        ret
11251:
1126        lodsb   (%si), %al
1127        rorl    $8, %eax
1128        decb    %cl
1129        jnz     1b
1130
1131        popw    %cx
1132        negb    %cl
1133        add     $4, %cl
1134        shlb    $3, %cl
1135        ret
1136
1137NTFS_Run_Overflow_Error:
1138        movb    $NTFS_Run_Overflow_Error_Code, %al
1139        jmp     NTFS_Error
1140
1141// Read run list block
1142// Output:
1143//     EDX = Next VCN
1144//     SI points to the next unhandled byte
1145
1146ntfs_runlist_read_block:
1147        lodsb   (%si), %al
1148        movb    %al, %cl
1149        movb    %cl, %ch
1150        andb    $0xF, %cl               // cl - Size of length field
1151        jz      1f
1152        shrb    $0x4, %ch               // ch - Size of offset field
1153
1154        call    ntfs_runlist_read_data
1155        shrl    %cl, %eax
1156
1157        movl    %edx, nt_curr_vcn
1158        addl    %eax, %edx
1159
1160        movb    %ch, %cl
1161        call    ntfs_runlist_read_data
1162        sarl    %cl, %eax
1163
1164        addl    %eax, nt_curr_lcn
1165
1166        ret
1167
11681:
1169        testb   $NT_FG_ALST, nt_flag
1170        jz      NTFS_Run_Overflow_Error
1171
1172        pushl   %edx
1173        pushw   %bx
1174        movw    nt_attr_cur, %si
1175        movb    (%si), %al
1176        call    ntfs_find_attr
1177        jc      NTFS_Run_Overflow_Error
1178        cmpb    $0, 8(%si)
1179        jz      NTFS_Run_Overflow_Error
1180        movl    $0, nt_curr_lcn
1181        popw    %bx
1182        popl    %edx
1183        addw    0x20(%si), %si
1184        jmp     ntfs_runlist_read_block
1185
1186// Convert seg:ofs to linear address
1187// Input:
1188//     On stack: seg:ofs
1189// Output:
1190//     eax:
1191seg_to_lin:
1192        pushw   %bp
1193        movw    %sp, %bp
1194        xorl    %eax, %eax
1195        xchgw   6(%bp), %ax
1196        shll    $4, %eax
1197        addl    4(%bp), %eax
1198        popw    %bp
1199        ret     $4
1200
1201// Convert linear address to seg:ofs
1202// Input:
1203//     on stack: linear address
1204// Output:
1205//     On stack: seg:ofs
1206lin_to_seg:
1207        pushw   %bp
1208        movw    %sp, %bp
1209        shll    $12, 4(%bp)
1210        shrw    $12, 4(%bp)
1211        popw    %bp
1212        ret
1213
1214fix_segs:
1215        pushw   %ds
1216        pushw   %si
1217        call    seg_to_lin
1218        pushl   %eax
1219        call    lin_to_seg
1220        popw    %si
1221        popw    %ds
1222
1223fix_es_di:
1224        pushw   %es
1225        pushw   %di
1226        call    seg_to_lin
1227        pushl   %eax
1228        call    lin_to_seg
1229        popw    %di
1230        popw    %es
1231        ret
1232
1233// Handle sparse block
1234//     DI: points to buffer
1235//     ES:BX: points to buffer
1236//     ECX: number of sectors
1237//     EDX: next VCN
1238
1239ntfs_sparse_block:
1240        pushw   %di
1241        pushl   %edx
1242
1243        shll    $9, %ecx                // ecx - totel number of bytes
1244
1245        testb   $1, nt_flag             // Not compressed
1246        jz      2f
1247
1248        xorl    %edx, %edx
1249        movb    nt_target_vcn, %dl
1250        andb    $0xF, %dl
1251        jz      2f
1252
1253        movw    %bx, %di
1254
1255        pushw   %cx
1256
1257        movb    nt_spc, %cl
1258        addb    $9, %cl
1259        shll    %cl, %edx               // edx: offset from the start of cluster
1260
1261        push    %es
1262        push    %di
1263        call    seg_to_lin
1264        subl    %edx, %eax              // eax: linear address
1265
1266        movl    $16, nt_remain_len
1267        shll    %cl, nt_remain_len
1268
1269        popw    %cx
1270
1271        addl    %edx, %ecx
1272        subl    nt_remain_len, %ecx
1273
1274        pushl   %ecx
1275        call    ntfs_decomp_block
1276        popl    %ecx
1277
1278        addl    nt_remain_len, %ecx
1279
1280        jecxz   1f
1281
1282        movw    %di, %bx
1283
12842:
1285        movw    %bx, %di
1286        movl    %ecx, %edx
1287        xorl    %eax, %eax
1288        movl    %eax, %ecx
1289        call    fix_es_di
1290
12913:
1292        movw    $0x8000, %cx
1293        cmpl    %edx, %ecx
1294        jbe     4f
1295        movw    %dx, %cx
12964:
1297        pushw   %cx
1298        shrw    $2, %cx
1299
1300        rep     stosl   %eax, %es:(%di)
1301        call    fix_es_di
1302        popw    %cx
1303        subl    %ecx, %edx
1304        jnz     3b
1305
13061:
1307        movw    %di, %bx
1308
1309        popl    %edx
1310        popw    %di
1311
1312        ret
1313
1314// Decompress block
1315// Input:
1316//     eax: linear address at the beginning of the compressed block
1317// Output:
1318//     ES:DI: points to the end of the block
1319ntfs_decomp_block:
1320        pushw   %ds
1321        pushw   %si
1322
1323        pushl   %eax
1324        call    lin_to_seg
1325        popw    %si
1326        popw    %ds
1327        movl    nt_remain_len, %edx
1328        addl    %edx, %eax
1329        pushl   %eax
1330        call    lin_to_seg
1331        popw    %di
1332        popw    %es
1333
1334        pushw   %es
1335        pushw   %di
1336        pushw   %ds
1337        pushw   %si
1338
1339        xorl    %ecx, %ecx
1340
13411:
1342        movw    $0x8000, %cx
1343        cmpl    %edx, %ecx
1344        jbe     2f
1345        movw    %dx, %cx
13462:
1347        pushw   %cx
1348        shrw    $2, %cx
1349        rep     movsl   (%si), %es:(%di)
1350        call    fix_segs
1351        popw    %cx
1352        subl    %ecx, %edx
1353        jnz     1b
1354
1355        popw    %di
1356        popw    %es
1357        popw    %si
1358        popw    %ds
1359
13601:
1361        xorl    %edx, %edx                      // edx - copied bytes
1362
1363        lodsw   (%si), %ax
1364        testb   $0x80, %ah
1365        jnz     2f
1366        movw    $0x800, %cx
1367        rep     movsw   (%si), %es:(%di)
1368        movw    $0x1000, %dx
1369        jmp     7f                              // The block is not compressed
1370
13712:
1372        movw    %ax, %cx
1373        andw    $0xFFF, %cx
1374        incw    %cx                             // ecx = block length
1375        addw    %si, %cx                        // cx: end marker
1376        xorb    %bh, %bh
1377
13783:
1379        cmpw    $0x1000, %dx
1380        ja      NTFS_Decompress_Error
1381
1382        orb     %bh, %bh
1383        jnz     4f
1384        lodsb   (%si), %al
1385        movb    %al, %bl                        // bl: tag, bh: count
1386        movb    $8, %bh
13874:
1388
1389        testb   $1, %bl
1390        jz      5f
1391
1392        movw    %dx, %ax
1393        decw    %ax
1394
1395        pushw   %cx
1396        pushw   %bx
1397
1398        movb    $12, %cl
13996:
1400        cmpw    $0x10, %ax
1401        jb      6f
1402        shrw    $1, %ax
1403        decb    %cl
1404        jmp     6b
14056:
1406
1407        lodsw   (%si), %ax
1408        movw    %ax, %bx
1409        shrw    %cl, %bx                        // bx: delta
1410
1411        pushw   %dx
1412        movw    $1, %dx
1413        shlw    %cl, %dx
1414        decw    %dx
1415        andw    %dx, %ax
1416        popw    %dx
1417
1418        addw    $3, %ax
1419        movw    %ax, %cx                        // cx: length
1420        negw    %bx
1421        decw    %bx
1422
14236:
1424        movb    %es:(%bx, %di), %al
1425        stosb   %al, %es:(%di)
1426        incw    %dx
1427        loop    6b
1428
1429        popw    %bx
1430        popw    %cx
1431        jmp     4f
1432
14335:
1434        movsb   (%si), %es:(%di)
1435        incw    %dx
14364:
1437        shrb    $1, %bl
1438        decb    %bh
1439
1440        cmpw    %cx, %si
1441        jb      3b
1442
14437:
1444        call    fix_segs
1445
1446        subl    %edx, nt_remain_len     // End of block
1447        jz      1f
1448
1449        cmpw    $0x1000, %dx
1450        je      1b
1451
14521:
1453
1454        popw    %si
1455        popw    %ds
1456        ret
1457
1458NTFS_Decompress_Error:
1459        pushw   %ss
1460        popw    %ds
1461        movb    $NTFS_Decompress_Error_Code, %al
1462        jmp     NTFS_Error
1463
1464/*
1465do_pause:
1466        .byte   0
1467
1468pause:
1469        cmpb    $0, (do_pause - Entry_nt)(%bp)
1470        jnz     1f
1471        ret
14721:
1473        xorw    %bp, %bp
14741:
1475        jmp     1b
1476*/
1477
1478/*
1479hex_out:
1480        pushw   %bp
1481        movw    %sp, %bp
1482        pushaw
1483        movb    $0xE, %ah
1484        movw    $7, %bx
1485        movw    $4, %cx
1486        movw    4(%bp), %dx
14871:
1488        rol     $4, %dx
1489        movb    %dl, %al
1490        andb    $0xF, %al
1491        cmpb    $10, %al
1492        jb      2f
1493        subb    $('0'-'A'+10), %al
14942:
1495        addb    $'0', %al
1496        int     $0x10
1497        loop    1b
1498        movb    $' ', %al
1499        int     $0x10
1500        popaw
1501        popw    %bp
1502        ret     $2
1503*/
1504
1505        . = Entry_nt + 0x7fc
1506
1507nt_sector_mark:
1508        .long   0x42555247              // "GRUB"
Note: See TracBrowser for help on using the repository browser.