~smartboyhw/wubi/bug-1080090-new

« back to all changes in this revision

Viewing changes to src/grubutil/grubinst/.svn/text-base/ntfsbs.S.old.svn-base

  • Committer: Howard Chan
  • Date: 2012-11-20 10:16:05 UTC
  • Revision ID: smartboyhw@gmail.com-20121120101605-qfmjfsdynpzg9an9
Added images

Show diffs side-by-side

added added

removed removed

Lines of Context:
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, >16K INDEX record size
37
 
 *  2. Don't support encrypted file
38
 
 *  3. Don't support attribute list, which means root directory can't be too
39
 
 *     large or fragment.
40
 
 *
41
 
 */
42
 
 
43
 
#ifndef INSIDE_GRLDR
44
 
 
45
 
        .text
46
 
 
47
 
        .code16
48
 
#endif
49
 
 
50
 
#define MAX_MFT_RECORD_SIZE     1       // 1<<(1+9) = 1024
51
 
#define MAX_IDX_RECORD_SIZE     5       // 1<<(5+9) = 16384
52
 
 
53
 
#define LOADSEG_NT      0x2000          // IDX loaded at 2000:0
54
 
 
55
 
#define MFT_OFFSET      0x2000          // MFT loaded at 0:2000
56
 
#define MFT_FILE        0x2400          // MFT file at 0:2400
57
 
 
58
 
#define nt_boot_drive   -2(%bp)
59
 
#define nt_blocksize    -4(%bp)
60
 
#define nt_spc          -5(%bp)
61
 
#define nt_MFT_size     -6(%bp)
62
 
#define nt_ATTR_flag    -7(%bp)
63
 
#define nt_IDX_size     -8(%bp)
64
 
#define nt_MFT_run      -12(%bp)
65
 
 
66
 
#define nt_curr_VCN     -16(%bp)
67
 
#define nt_curr_LCN     -20(%bp)
68
 
#define nt_target_VCN   -24(%bp)
69
 
#define nt_read_count   -28(%bp)
70
 
#define nt_remain_leng  -32(%bp)
71
 
 
72
 
//nt_blocksize:
73
 
//      .word   0
74
 
//nt_spc:
75
 
//      .byte   0
76
 
//nt_MFT_size:
77
 
//      .byte   0
78
 
//nt_ATTR_flag:
79
 
//      .byte   0
80
 
//nt_IDX_size:
81
 
//      .byte   0
82
 
//nt_MFT_start:
83
 
//      .long   0
84
 
//nt_curr_VCN:
85
 
//      .long   0
86
 
//nt_curr_LCN:
87
 
//      .long   0
88
 
//nt_target_VCN:
89
 
//      .long   0
90
 
//nt_read_count:
91
 
//      .long   0
92
 
//nt_remain_leng:
93
 
//      .long   0
94
 
 
95
 
#define NTFS_Large_Structure_Error_Code 1
96
 
#define NTFS_Corrupt_Error_Code         2
97
 
#define NTFS_Run_Overflow_Error_Code    3
98
 
#define NTFS_No_Data_Error_Code         4
99
 
#define NTFS_Decompress_Error_Code      5
100
 
 
101
 
//msg_NTFS_Large_Structure_Error:
102
 
//      .ascii "Large structure\0"
103
 
//msg_NTFS_Corrupt_Error:
104
 
//      .ascii "NTFS corrupted\0"
105
 
//msg_NTFS_Run_Overflow_Error:
106
 
//      .ascii "Run list overflow\0"
107
 
//msg_NTFS_No_Data_Error:
108
 
//      .ascii "GRLDR have no data\0"
109
 
//msg_NTFS_Decompress_Error:
110
 
//      .ascii "Decomp error\0"
111
 
 
112
 
        .arch   i586
113
 
 
114
 
Entry_nt:
115
 
        jmp     1f
116
 
 
117
 
        . = Entry_nt + 0x02
118
 
 
119
 
        .byte   0x90    /* for CHS. Another possible value is 0x0e for LBA */
120
 
 
121
 
        .ascii  "NTFS    "
122
 
 
123
 
        .word   0       /* 0B - Bytes per sector */
124
 
        .byte   0       /* 0D - Sectors per cluster */
125
 
        .word   0       /* 0E - reserved sectors, unused */
126
 
        .byte   0       /* 10 - number of FATs, unused */
127
 
        .word   0       /* 11 - Max dir entries for FAT12/FAT16, unused */
128
 
        .word   0       /* 13 - total sectors for FAT12/FAT16, unused */
129
 
        .byte   0xF8    /* 15 - Media descriptor */
130
 
        .word   0       /* 16 - sectors per FAT for FAT12/FAT16, unused */
131
 
        .word   255     /* 18 - Sectors per track */
132
 
        .word   63      /* 1A - Number of heads */
133
 
nt_part_ofs:
134
 
        .long   0       /* 1C - hidden sectors */
135
 
        .long   0       /* 20 - total sectors for FAT32, unused */
136
 
        .long   0x800080
137
 
                        /* 24 - Usually 80 00 80 00, A value of 80 00 00 00 has
138
 
                         * been seen on a USB thumb drive which is formatted
139
 
                         * with NTFS under Windows XP. Note this is removable
140
 
                         * media and is not partitioned, the drive as a whole
141
 
                         * is NTFS formatted.
142
 
                         */
143
 
        .long   0,0     /* 28 - Number of sectors in the volume */
144
 
        .long   0,0     /* 30 - LCN of VCN 0 of the $MFT */
145
 
        .long   0,0     /* 38 - LCN of VCN 0 of the $MFTMirr */
146
 
        .long   0       /* 40 - Clusters per MFT Record */
147
 
        .long   4       /* 44 - Clusters per Index Record */
148
 
        .long   0,0     /* 48 - Volume serial number */
149
 
        .long   0       /* 50 - Checksum, usually 0 */
150
 
 
151
 
1:
152
 
 
153
 
        . = Entry_nt + 0x54
154
 
 
155
 
        cli
156
 
        cld
157
 
 
158
 
        . = Entry_nt + 0x56
159
 
 
160
 
        /* the byte at offset 0x57 stores the real partition number for read.
161
 
         * the format program or the caller should set it to a correct value.
162
 
         * For floppies, it should be 0xff, which stands for whole drive.
163
 
         */
164
 
 
165
 
        movb    $0xff, %dh      /* boot partition number */
166
 
 
167
 
        xorw    %ax, %ax
168
 
        movw    %ax, %ds
169
 
        movw    $0x7c00, %bp
170
 
        movw    %ax, %es
171
 
 
172
 
        movw    %ax, %ss        /* stack and BP-relative moves up, too */
173
 
        leaw    -0x20(%bp), %sp
174
 
        sti
175
 
 
176
 
        movw    %dx, nt_boot_drive
177
 
 
178
 
        /* Test if your BIOS support LBA mode */
179
 
        movb    $0x41, %ah
180
 
        movw    $0x55AA, %bx
181
 
        int     $0x13
182
 
        jc      1f              /* No EBIOS */
183
 
        cmpw    $0xAA55, %bx
184
 
        jne     1f              /* No EBIOS */
185
 
        testb   $1, %cl
186
 
        jz      1f              /* No EBIOS */
187
 
        /* EBIOS supported */
188
 
        movb    $0x42, (ebios_nt - 1 - Entry_nt)(%bp)
189
 
1:
190
 
 
191
 
        cmpl    $0x42555247, (nt_sector_mark - Entry_nt)(%bp)
192
 
        jz      1f                      // Must be called from GRLDR.MBR
193
 
 
194
 
        movw    $0x7E00, %bx
195
 
        movl    (nt_part_ofs - Entry_nt)(%bp), %eax
196
 
        incl    %eax
197
 
        call    readDisk_nt             // Load the second sector from disk
198
 
        call    readDisk_nt             // Load the third sector from disk
199
 
1:
200
 
 
201
 
        xorl    %eax, %eax
202
 
        movw    0xb(%bp), %ax           // Bytes per sector (blocksize)
203
 
        movw    %ax, nt_blocksize
204
 
 
205
 
        call    convert_to_power_2
206
 
        movb    %cl, %bl
207
 
        movb    0xd(%bp), %al           // Sectors per cluster
208
 
        call    convert_to_power_2
209
 
        movb    %cl, %ch
210
 
        addb    %bl, %ch
211
 
        subb    $9, %ch                 // 1<<ch = sectors per cluster
212
 
        movb    %ch, nt_spc
213
 
        movb    0x44(%bp), %al          // Index record size (high bits of eax is 0)
214
 
        call    convert_size
215
 
 
216
 
        cmpb    $MAX_IDX_RECORD_SIZE, %cl
217
 
        jbe     1f
218
 
 
219
 
NTFS_Large_Structure_Error:
220
 
        movb    $NTFS_Large_Structure_Error_Code, %al
221
 
        jmp     NTFS_Error
222
 
 
223
 
1:
224
 
        movb    %cl, nt_IDX_size
225
 
 
226
 
        movb    0x40(%bp), %al          // MFT record size
227
 
        call    convert_size
228
 
 
229
 
        cmpb    $MAX_MFT_RECORD_SIZE, %cl
230
 
        ja      NTFS_Large_Structure_Error
231
 
 
232
 
        movb    %cl, nt_MFT_size
233
 
 
234
 
        movl    0x30(%bp), %eax
235
 
        movl    0x34(%bp), %edx
236
 
 
237
 
        movb    %ch, %cl                // ch still contains nt_spc
238
 
 
239
 
        shldl   %cl, %eax, %edx
240
 
        orl     %edx, %edx
241
 
        jnz     NTFS_Large_Structure_Error
242
 
 
243
 
        shll    %cl, %eax
244
 
        addl    (nt_part_ofs - Entry_nt)(%bp), %eax
245
 
 
246
 
        movw    $1, %dx
247
 
        movb    nt_MFT_size, %cl
248
 
        shlw    %cl, %dx
249
 
        movw    %dx, %cx
250
 
 
251
 
        movw    $MFT_FILE, %bx
252
 
        pushw   %bx
253
 
 
254
 
1:
255
 
        call    readDisk_nt
256
 
        loop    1b
257
 
 
258
 
        popw    %bx
259
 
        //cmpl  $0x454C4946, (%bx)      // Check for the "FILE" label
260
 
        cmpw    $0x4946, (%bx)          // to save space, only test FI
261
 
        jnz     NTFS_Corrupt_Error
262
 
 
263
 
        // dx should still contain the number of sectors in the MFT record
264
 
        movw    %dx, %cx
265
 
        call    ntfs_fixup
266
 
 
267
 
        addw    0x14(%bx), %bx          // Jump to the first attribute
268
 
        movb    $0x80, %al              // find $DATA
269
 
 
270
 
        call    find_attr
271
 
        jc      NTFS_Corrupt_Error
272
 
        addw    0x20(%si), %si
273
 
        movw    %si, nt_MFT_run
274
 
 
275
 
        movb    $0, nt_ATTR_flag
276
 
 
277
 
        // Sector one is almost full, jmp to the second sector
278
 
 
279
 
        jmp     ntfs_search
280
 
 
281
 
// Convert the size of MFT and IDX block
282
 
// Input:
283
 
//     eax: size
284
 
//     ch: spc
285
 
// Output:
286
 
//     cl: convert value
287
 
convert_size:
288
 
        orb     %al, %al
289
 
        js      1f
290
 
        movb    %ch, %cl
291
 
        jmp     2f                      // Jump to 2 in convert_to_power_2
292
 
1:
293
 
        negb    %al
294
 
        subb    $9, %al
295
 
        movb    %al, %cl
296
 
        ret
297
 
 
298
 
// Convert number to a power of 2
299
 
// Input:
300
 
//     eax
301
 
// Output:
302
 
//     cl: 1<<cl = eax
303
 
//     eax: 0
304
 
 
305
 
convert_to_power_2:
306
 
        xorb    %cl, %cl
307
 
2:
308
 
        incb    %cl
309
 
        shrl    $1, %eax
310
 
        jnc     2b
311
 
        decb    %cl
312
 
        ret
313
 
 
314
 
/*
315
 
// Read MFT record
316
 
// Input:
317
 
//   BX: Data Offset
318
 
//   EAX: MFT number
319
 
 
320
 
ntfs_read_MFT:
321
 
 
322
 
        pushw   %bx
323
 
 
324
 
        movb    nt_MFT_size, %cl
325
 
        shll    %cl, %eax
326
 
        addl    nt_MFT_start, %eax
327
 
 
328
 
        movw    $1, %dx
329
 
        movb    nt_MFT_size, %cl
330
 
        shlw    %cl, %dx
331
 
        movw    %dx, %cx
332
 
 
333
 
        pushw   %ds
334
 
        popw    %es
335
 
 
336
 
1:
337
 
        call    readDisk_nt
338
 
        loop    1b
339
 
 
340
 
        popw    %bx
341
 
        cmpl    $0x454C4946, (%bx)      // Check for the "FILE" label
342
 
        jnz     NTFS_Corrupt_Error
343
 
 
344
 
        // dx should still contain the number of sectors in the MFT record
345
 
        movw    %dx, %cx
346
 
        //call  ntfs_fixup
347
 
 
348
 
        //ret                           // Continue at ntfs_fixup
349
 
*/
350
 
 
351
 
// Fixup the "FILE" and "INDX" record
352
 
// Input:
353
 
//     ES:BX - data buffer
354
 
//     CX - buffer length in sectors
355
 
//
356
 
 
357
 
ntfs_fixup:
358
 
        push    %bx
359
 
        push    %di
360
 
        movw    %bx, %di
361
 
 
362
 
        movw    %es:6(%bx), %ax         // Size of Update Sequence
363
 
        decw    %ax
364
 
        movw    %ax, %bx
365
 
 
366
 
        mulw    nt_blocksize
367
 
        shlw    $9, %cx
368
 
        cmpw    %ax, %cx
369
 
        jnz     NTFS_Corrupt_Error      // blocksize * count != size
370
 
 
371
 
        movw    %bx, %cx                // cx = count
372
 
 
373
 
        movw    %di, %bx
374
 
        addw    %es:4(%bx), %bx         // Offset to the update sequence
375
 
        movw    %es:(%bx), %ax          // Update Sequence Number
376
 
        subw    $2, %di
377
 
 
378
 
1:
379
 
        addw    nt_blocksize, %di
380
 
        addw    $2, %bx
381
 
        cmpw    %es:(%di), %ax
382
 
        jnz     NTFS_Corrupt_Error
383
 
        movw    %es:(%bx), %dx
384
 
        movw    %dx, %es:(%di)
385
 
        loop    1b
386
 
 
387
 
        popw    %di
388
 
        popw    %bx
389
 
        ret
390
 
 
391
 
NTFS_Corrupt_Error:
392
 
        movb    $NTFS_Corrupt_Error_Code, %al
393
 
        jmp     NTFS_Error
394
 
 
395
 
/* Read a sector from disk, using LBA or CHS
396
 
 * input:       EAX - 32-bit DOS sector number
397
 
 *              ES:BX - destination buffer
398
 
 *              (will be filled with 1 sector of data)
399
 
 * output:      ES:BX points one byte after the last byte read.
400
 
 *              EAX - next sector
401
 
 */
402
 
 
403
 
readDisk_nt:
404
 
 
405
 
        pushal
406
 
        xorl    %edx, %edx      /* EDX:EAX = LBA */
407
 
        pushl   %edx            /* hi 32bit of sector number */
408
 
        pushl   %eax            /* lo 32bit of sector number */
409
 
        pushw   %es             /* buffer segment */
410
 
        pushw   %bx             /* buffer offset */
411
 
        pushw   $1              /* 1 sector to read */
412
 
        pushw   $16             /* size of this parameter block */
413
 
 
414
 
        xorl    %ecx, %ecx
415
 
        pushl   0x18(%bp)       /* lo:sectors per track, hi:number of heads */
416
 
        popw    %cx             /* ECX = sectors per track */
417
 
        divl    %ecx            /* residue is in EDX */
418
 
                                /* quotient is in EAX */
419
 
        incw    %dx             /* sector number in DL */
420
 
        popw    %cx             /* ECX = number of heads */
421
 
        pushw   %dx             /* push sector number into stack */
422
 
        xorw    %dx, %dx        /* EDX:EAX = cylinder * TotalHeads + head */
423
 
        divl    %ecx            /* residue is in EDX, head number */
424
 
                                /* quotient is in EAX, cylinder number */
425
 
        xchgb   %dl, %dh        /* head number should be in DH */
426
 
                                /* DL = 0 */
427
 
        popw    %cx             /* pop sector number from stack */
428
 
        xchgb   %al, %ch        /* lo 8bit cylinder should be in CH */
429
 
                                /* AL = 0 */
430
 
        shlb    $6, %ah         /* hi 2bit cylinder ... */
431
 
        orb     %ah, %cl        /* ... should be in CL */
432
 
 
433
 
        movw    $0x201, %ax     /* read 1 sector */
434
 
ebios_nt: /* ebios_nt - 1 points to 0x02 that can be changed to 0x42 */
435
 
 
436
 
//      cmpb    $0x0e, 2(%bp)   /* force LBA? */
437
 
//      jnz     1f              /* no, continue */
438
 
//      movb    $0x42, %ah      /* yes, use extended disk read */
439
 
//1:
440
 
        movw    %sp, %si        /* DS:SI points to disk address packet */
441
 
        movb    nt_boot_drive, %dl      /* hard disk drive number */
442
 
 
443
 
        int     $0x13
444
 
 
445
 
        popaw                   /* remove parameter block from stack */
446
 
        popal
447
 
        jc      disk_error_nt   /* disk read error, jc 1f if caller handles */
448
 
        incl    %eax            /* next sector */
449
 
        addw    0x0b(%bp), %bx  /* bytes per sector */
450
 
        jnc     1f              /* 64K bound check */
451
 
        pushw   %dx
452
 
        movw    %es, %dx
453
 
        addb    $0x10, %dh      /* add 1000h to ES */
454
 
                                /* here, carry is cleared */
455
 
        movw    %dx, %es
456
 
        popw    %dx
457
 
1:
458
 
        /* carry stored on disk read error */
459
 
        ret
460
 
 
461
 
msg_DiskReadError_nt:
462
 
 
463
 
        .ascii  "0\0"
464
 
 
465
 
msg_NTFS_Not_Found_Error:
466
 
        .ascii "No "
467
 
 
468
 
nt_boot_image:
469
 
        .ascii "grldr\0"
470
 
 
471
 
        . = nt_boot_image + 8
472
 
 
473
 
nt_boot_image_end:
474
 
 
475
 
NTFS_Error:
476
 
        addb    %al, (msg_DiskReadError_nt - Entry_nt)(%bp)
477
 
        jmp     disk_error_nt
478
 
 
479
 
// Kernel load address, located at 0x1E8
480
 
        . = Entry_nt + 0x1e8
481
 
 
482
 
nt_loadseg_off:
483
 
        .word   0
484
 
        .word   LOADSEG_NT
485
 
 
486
 
// Boot image offset and length, located at 0x1EE
487
 
// Lower 11 bit is offset, higher 5 bit is length
488
 
        . = Entry_nt + 0x1ec
489
 
 
490
 
nt_boot_image_ofs:
491
 
        .word (nt_boot_image - Entry_nt)+(nt_boot_image_end - nt_boot_image-1)*2048
492
 
 
493
 
        . = Entry_nt + 0x1ee
494
 
 
495
 
disk_error_nt:
496
 
 
497
 
        movw    $(msg_DiskReadError_nt - Entry_nt + 0x7c00), %si
498
 
 
499
 
boot_error_nt:
500
 
 
501
 
/* prints string DS:SI (modifies AX BX SI) */
502
 
 
503
 
//print_32:
504
 
1:
505
 
        lodsb   (%si), %al      /* get token */
506
 
        //xorw  %bx, %bx        /* video page 0 */
507
 
        movb    $0x0e, %ah      /* print it */
508
 
        int     $0x10           /* via TTY mode */
509
 
        cmpb    $0, %al         /* end of string? */
510
 
        jne     1b              /* until done */
511
 
 
512
 
        /* The caller will change this to
513
 
         *      ljmp    $0x9400, $(try_next_partition - _start1)
514
 
         */
515
 
 
516
 
1:      jmp     1b
517
 
 
518
 
        . = Entry_nt + 0x1fc
519
 
 
520
 
        .word   0, 0xAA55
521
 
 
522
 
// Here starts sector #2
523
 
 
524
 
ntfs_search:
525
 
        // %eax = nt_MFT_start
526
 
 
527
 
        xorl    %eax, %eax
528
 
        movb    $5, %al                 // MFT record for root directory
529
 
        call    ntfs_read_MFT
530
 
 
531
 
        addw    0x14(%bx), %bx          // Jump to the first attribute
532
 
        movb    $0x90, %al              // find $INDEX_ROOT
533
 
 
534
 
1:
535
 
 
536
 
        call    find_attr
537
 
 
538
 
        jc      NTFS_Not_Found_Error
539
 
 
540
 
        cmpl    $0x180400,  8(%si)      // resident
541
 
                                        // namelen = 4
542
 
                                        // name offset = 0x18
543
 
        jnz     1b
544
 
        //testw $0xC001, 12(%si)        // not compressed, encrypted or sparse
545
 
        //jnz   1b
546
 
        cmpl    $0x490024, 0x18(%si)    // to save space, only test $ and I
547
 
        jnz     1b
548
 
        //cmpl  $0x300033, 0x1C(%si)
549
 
        //jnz   1b                      // name = "$I30"
550
 
 
551
 
        movw    %si, %di
552
 
        addw    0x14(%di), %di          // di points to index header
553
 
        cmpb    $0x30, (%di)
554
 
        jnz     1b                      // test if it index filenames
555
 
 
556
 
        addw    $0x10, %di              // skip the index root
557
 
 
558
 
        cmpb    $0, 0xC(%di)
559
 
        jnz     3f
560
 
 
561
 
2:
562
 
        xorw    %si, %si                // Small index
563
 
        jmp     2f
564
 
 
565
 
3:
566
 
 
567
 
        movb    $0xA0, %al              // find $INDEX_ALLOCATION
568
 
1:
569
 
        call    find_attr
570
 
        jc      2b
571
 
 
572
 
        cmpl    $0x400401, 8(%si)       // non-resident
573
 
                                        // namelen = 4
574
 
                                        // name offset = 0x40
575
 
        jnz     1b
576
 
        //testw $0xC001, 12(%si)        // not compressed, encrypted or sparse
577
 
        //jnz   1b
578
 
        cmpl    $0x490024, 0x40(%si)    // to save space, only test $ and I
579
 
        jnz     1b
580
 
        //cmpl  $0x300033, 0x44(%si)
581
 
        //jnz   1b                      // name = "$I30"
582
 
 
583
 
        addw    0x20(%si), %si          // bx points to data runs
584
 
 
585
 
2:
586
 
        xchgw   %si, %di
587
 
        addw    (%si), %si              // skip the index header
588
 
 
589
 
        pushl   $0xFFFFFFFF             // end mark
590
 
 
591
 
3:
592
 
 
593
 
        call    ntfs_find_grldr
594
 
 
595
 
        jnc     ntfs_final
596
 
        popl    %eax
597
 
 
598
 
        cmpl    $0xFFFFFFFF, %eax
599
 
        jz      NTFS_Not_Found_Error
600
 
 
601
 
        lesw    (nt_loadseg_off - Entry_nt)(%bp), %bx
602
 
 
603
 
        xorl    %ecx, %ecx
604
 
 
605
 
        movw    $1, %dx
606
 
        movb    nt_IDX_size, %cl
607
 
        shlw    %cl, %dx
608
 
        movw    %dx, %cx
609
 
 
610
 
        pushw   %cx
611
 
        call    ntfs_load_vcn
612
 
        popw    %cx
613
 
 
614
 
        lesw    (nt_loadseg_off - Entry_nt)(%bp), %bx
615
 
        //cmpl  $0x58444E49, %es:(%bx)  // "INDX"
616
 
        cmpw    $0x4E49, %es:(%bx)      // to save space, only test IN
617
 
        jnz     NTFS_Corrupt_Error
618
 
 
619
 
        call    ntfs_fixup
620
 
        addw    $0x18, %bx
621
 
        addw    %es:(%bx), %bx
622
 
        movw    %bx, %si
623
 
        jmp     3b
624
 
 
625
 
//test_run:
626
 
//      .byte 0x21,0x14,0x00,0x01,0x11,0x10,0x18,0x11,0x05,0x15,0x01,0x27,0x11,0x20,0x05
627
 
//      .byte 0x42,0x10,0
628
 
//      .long 0x11220000
629
 
 
630
 
NTFS_Not_Found_Error:
631
 
        leaw    (msg_NTFS_Not_Found_Error - Entry_nt)(%bp), %si
632
 
        jmp     boot_error_nt
633
 
 
634
 
// Find a attribute
635
 
// Input:
636
 
//     SI - current item
637
 
//     BX - next item
638
 
//     AL - attribute
639
 
// Output:
640
 
//   Found:
641
 
//     CF - clear
642
 
//   Not found:
643
 
//     CF - set
644
 
find_attr:
645
 
1:
646
 
        movw    %bx, %si
647
 
        addw    4(%bx), %bx
648
 
        cmpb    (%si), %al
649
 
        ja      1b
650
 
        ret
651
 
 
652
 
// Try to find GRLDR in the index
653
 
// Input:
654
 
//     ES:SI - points to index entry
655
 
//  Output:
656
 
//     Found:
657
 
//         CF is clear
658
 
//     Not found:
659
 
//         CF is set
660
 
 
661
 
ntfs_find_grldr:
662
 
        movw    %si, %bx
663
 
        testb   $1, %es: 0xC(%bx)
664
 
        jz      1f
665
 
        addw    %es: 8(%bx), %bx
666
 
        cmpl    $0, %es: -4(%bx)
667
 
        jnz     NTFS_Large_Structure_Error
668
 
        popw    %ax                     // Return address
669
 
        pushl   %es: -8(%bx)            // VCN of subnode
670
 
        pushw   %ax
671
 
        movw    %si, %bx
672
 
1:
673
 
        testb   $2, %es: 0xC(%bx)
674
 
        jz      1f
675
 
        stc
676
 
        ret
677
 
1:
678
 
        xorb    %ch, %ch
679
 
 
680
 
        pushw   %si
681
 
        leaw    (nt_boot_image - Entry_nt)(%bp), %si
682
 
        //addw  %es:0xA(%bx), %bx
683
 
        addw    $0x52, %bx              // The value at %es:0xA(%bx) is wrong sometimes (0x4C)
684
 
        movb    %es:-2(%bx), %cl
685
 
1:
686
 
        lodsb   (%si), %al
687
 
        movb    %es:(%bx), %ah
688
 
        cmpb    $'A', %ah
689
 
        jb      2f
690
 
        cmpb    $'Z', %ah
691
 
        ja      2f
692
 
        addb    $('a'-'A'), %ah         // Convert to lowercase
693
 
2:
694
 
 
695
 
        cmpb    %ah, %al
696
 
        jnz     3f                      // Not match
697
 
 
698
 
        incw    %bx
699
 
        incw    %bx
700
 
        loop    1b
701
 
 
702
 
        cmpb    $0,(%si)
703
 
        jnz     3f
704
 
 
705
 
        popw    %si
706
 
        clc
707
 
        ret                             // Match found
708
 
 
709
 
3:
710
 
 
711
 
        popw    %si
712
 
        addw    %es:8(%si), %si
713
 
 
714
 
        jmp     ntfs_find_grldr
715
 
 
716
 
// Read MFT record
717
 
// Input:
718
 
//   EAX: MFT number
719
 
 
720
 
ntfs_read_MFT:
721
 
        pushw   %di
722
 
 
723
 
        movb    nt_MFT_size, %cl
724
 
        movw    $1, %si
725
 
        movw    %si, %bx
726
 
        shll    %cl, %eax
727
 
        shlw    %cl, %si
728
 
 
729
 
        movb    nt_spc, %cl
730
 
        shlw    %cl, %bx
731
 
        decw    %bx
732
 
        andw    %ax, %bx
733
 
 
734
 
        shrl    %cl, %eax
735
 
 
736
 
        xorl    %ecx, %ecx
737
 
        leaw    (%bx,%si), %cx
738
 
 
739
 
        pushw   %bx
740
 
        pushw   %si
741
 
 
742
 
        lesw    (nt_loadseg_off - Entry_nt)(%bp), %bx
743
 
        movw    nt_MFT_run, %di
744
 
 
745
 
        call    ntfs_load_vcn
746
 
 
747
 
        popw    %cx
748
 
        popw    %si
749
 
 
750
 
        pushw   %cx
751
 
 
752
 
        shlw    $8, %cx
753
 
        shlw    $9, %si
754
 
 
755
 
        movw    $MFT_OFFSET, %di
756
 
        movw    %di, %bx
757
 
        pushw   %ds
758
 
        pushw   %es
759
 
        popw    %ds
760
 
        popw    %es
761
 
 
762
 
        rep     movsw
763
 
 
764
 
        pushw   %es
765
 
        popw    %ds
766
 
 
767
 
        popw    %cx
768
 
 
769
 
        cmpw    $0x4946, (%bx)          // to save space, only test FI
770
 
        jnz     NTFS_Corrupt_Error
771
 
 
772
 
        call    ntfs_fixup
773
 
 
774
 
        popw    %di
775
 
        ret
776
 
 
777
 
// Load data from disk
778
 
// Input:
779
 
//     DI: start of the run list
780
 
//     SI: current run list item
781
 
//     EAX: start VCN
782
 
//     ES:BX: points to buffer
783
 
//     ECX: number of sectors to read
784
 
 
785
 
ntfs_load_vcn:
786
 
        movl    %ecx, nt_read_count
787
 
        movw    %di, %si
788
 
 
789
 
        movl    %eax, nt_target_VCN
790
 
        xorl    %edx, %edx              // edx - next VCN
791
 
        movl    %edx, nt_curr_LCN
792
 
 
793
 
1:
794
 
        call    ntfs_runlist_read_block
795
 
 
796
 
        cmpl    nt_target_VCN, %edx
797
 
        jbe     1b
798
 
 
799
 
1:
800
 
 
801
 
        movb    nt_spc, %cl
802
 
 
803
 
        orl     %eax, %eax              // sparse
804
 
        jz      2f
805
 
 
806
 
        movl    nt_target_VCN, %eax
807
 
        subl    nt_curr_VCN, %eax
808
 
        addl    nt_curr_LCN, %eax
809
 
 
810
 
        shll    %cl, %eax
811
 
        addl    (nt_part_ofs - Entry_nt)(%bp), %eax
812
 
 
813
 
2:
814
 
 
815
 
        pushl   %ebx
816
 
        movl    %edx, %ebx
817
 
        subl    nt_target_VCN, %ebx
818
 
        shll    %cl, %ebx
819
 
        movl    %ebx, %ecx
820
 
        popl    %ebx
821
 
 
822
 
        cmpl    nt_read_count, %ecx
823
 
        jbe     2f
824
 
        movl    nt_read_count, %ecx
825
 
2:
826
 
 
827
 
        pushl   %ecx
828
 
 
829
 
        orl     %eax, %eax
830
 
        jnz     3f
831
 
        call    SparseBlock
832
 
        jmp     4f
833
 
 
834
 
3:
835
 
 
836
 
        call    readDisk_nt
837
 
        loop    3b
838
 
 
839
 
4:
840
 
        popl    %ecx
841
 
        subl    %ecx, nt_read_count
842
 
        jbe     1f
843
 
 
844
 
        movl    %edx, nt_target_VCN
845
 
        call    ntfs_runlist_read_block
846
 
        jmp     1b
847
 
 
848
 
1:
849
 
        ret
850
 
 
851
 
// Read run list data
852
 
// Input:
853
 
//     CL = number of bytes
854
 
// Output:
855
 
//     EAX = read bytes
856
 
//     SI points to the next unhandled byte
857
 
 
858
 
ntfs_runlist_read_data:
859
 
        pushw   %cx
860
 
        orb     %cl, %cl
861
 
        jnz     1f
862
 
        popw    %cx
863
 
        xorl    %eax, %eax
864
 
        ret
865
 
1:
866
 
        lodsb   (%si), %al
867
 
        rorl    $8, %eax
868
 
        decb    %cl
869
 
        jnz     1b
870
 
 
871
 
        popw    %cx
872
 
        negb    %cl
873
 
        add     $4, %cl
874
 
        jz      1f
875
 
        shlb    $3, %cl
876
 
        sarl    %cl, %eax               // Don't use shr !
877
 
1:
878
 
        ret
879
 
 
880
 
NTFS_Run_Overflow_Error:
881
 
        movb    $NTFS_Run_Overflow_Error_Code, %al
882
 
        jmp     NTFS_Error
883
 
 
884
 
        . = Entry_nt + 0x3fc
885
 
 
886
 
        .word   0, 0xAA55
887
 
 
888
 
nt_sector_mark:
889
 
        .long   0x42555247              // "GRUB"
890
 
 
891
 
// Here starts sector #3
892
 
 
893
 
// Read run list block
894
 
// Output:
895
 
//     EDX = Next VCN
896
 
//     SI points to the next unhandled byte
897
 
 
898
 
ntfs_runlist_read_block:
899
 
        lodsb   (%si), %al
900
 
        movb    %al, %cl
901
 
        movb    %cl, %ch
902
 
        andb    $0xF, %cl               // cl - Size of length field
903
 
        jz      NTFS_Run_Overflow_Error
904
 
        shrb    $0x4, %ch               // ch - Size of offset field
905
 
 
906
 
        call    ntfs_runlist_read_data
907
 
 
908
 
        movl    %edx, nt_curr_VCN
909
 
        addl    %eax, %edx
910
 
 
911
 
        movb    %ch, %cl
912
 
        call    ntfs_runlist_read_data
913
 
        addl    %eax, nt_curr_LCN
914
 
 
915
 
        ret
916
 
 
917
 
ntfs_final:
918
 
 
919
 
1:
920
 
        //popl  %eax                    // Clear the stack
921
 
        //cmpl  $0xFFFFFFFF, %eax
922
 
        //jnz   1b
923
 
 
924
 
        cmpw    $0, %es:4(%si)
925
 
        jnz     NTFS_Large_Structure_Error
926
 
 
927
 
        //movl  %es: 0x40(%si), %eax    // Real size of file
928
 
        //addl  $0x1FF, %eax
929
 
        //shrl  $9, %eax                // Convert to sector
930
 
 
931
 
        movl    %es: (%si), %eax
932
 
        call    ntfs_read_MFT
933
 
 
934
 
        addw    0x14(%bx), %bx          // Jump to the first attribute
935
 
        movb    $0x80, %al              // find $DATA
936
 
 
937
 
1:
938
 
        call    find_attr
939
 
        jc      NTFS_No_Data_Error
940
 
 
941
 
        cmpw    $0x1, 8(%si)            // non-resident / resident
942
 
                                        // namelen = 0
943
 
        ja      1b
944
 
        jz      3f
945
 
 
946
 
        movw    0x10(%si), %cx          // Resident
947
 
        lesw    (nt_loadseg_off - Entry_nt)(%bp), %di
948
 
        addw    0x14(%si), %si
949
 
        rep     movsb   (%si), %es:(%di)
950
 
        jmp     2f
951
 
 
952
 
3:                                      // Non-resident
953
 
        movb    12(%si), %al
954
 
        movb    %al, nt_ATTR_flag
955
 
        //testw $0xC001, 12(%si)        // not compressed, encrypted or sparse
956
 
        //jnz   1b
957
 
 
958
 
        movw    %si, %di
959
 
        addw    0x20(%si), %di          // jump to run list
960
 
 
961
 
        lesw    (nt_loadseg_off - Entry_nt)(%bp), %bx
962
 
 
963
 
        movl    0x28(%si), %ecx         // Use allocate size instead of real size
964
 
        shrl    $9, %ecx
965
 
        xorl    %eax, %eax
966
 
 
967
 
        call    ntfs_load_vcn
968
 
 
969
 
2:
970
 
 
971
 
        //movb  $1, (do_pause - Entry_nt)(%bp)
972
 
        //call  pause
973
 
 
974
 
        movw    nt_boot_drive, %dx
975
 
        ljmp    *(nt_loadseg_off - Entry_nt)(%bp)
976
 
 
977
 
NTFS_No_Data_Error:
978
 
        movb    $NTFS_No_Data_Error_Code, %al
979
 
        jmp     NTFS_Error
980
 
 
981
 
// Convert seg:ofs to linear address
982
 
// Input:
983
 
//     On stack: seg:ofs
984
 
// Output:
985
 
//     eax:
986
 
seg_to_lin:
987
 
        pushw   %bp
988
 
        movw    %sp, %bp
989
 
        xorl    %eax, %eax
990
 
        xchgw   6(%bp), %ax
991
 
        shll    $4, %eax
992
 
        addl    4(%bp), %eax
993
 
        popw    %bp
994
 
        ret     $4
995
 
 
996
 
// Convert linear address to seg:ofs
997
 
// Input:
998
 
//     on stack: linear address
999
 
// Output:
1000
 
//     On stack: seg:ofs
1001
 
lin_to_seg:
1002
 
        pushw   %bp
1003
 
        movw    %sp, %bp
1004
 
        shll    $12, 4(%bp)
1005
 
        shrw    $12, 4(%bp)
1006
 
        popw    %bp
1007
 
        ret
1008
 
 
1009
 
fix_segs:
1010
 
        pushw   %ds
1011
 
        pushw   %si
1012
 
        call    seg_to_lin
1013
 
        pushl   %eax
1014
 
        call    lin_to_seg
1015
 
        popw    %si
1016
 
        popw    %ds
1017
 
 
1018
 
fix_es_di:
1019
 
        pushw   %es
1020
 
        pushw   %di
1021
 
        call    seg_to_lin
1022
 
        pushl   %eax
1023
 
        call    lin_to_seg
1024
 
        popw    %di
1025
 
        popw    %es
1026
 
        ret
1027
 
 
1028
 
// Handle sparse block
1029
 
//     DI: points to run list
1030
 
//     SI: current run list item
1031
 
//     ES:BX: points to buffer
1032
 
//     ECX: number of sectors
1033
 
//     EDX: next VCN
1034
 
 
1035
 
SparseBlock:
1036
 
        pushw   %di
1037
 
        pushl   %edx
1038
 
 
1039
 
        shll    $9, %ecx                // ecx - totel number of bytes
1040
 
        movw    %bx, %di
1041
 
 
1042
 
        testb   $1, nt_ATTR_flag        // Not compressed
1043
 
        jz      2f
1044
 
 
1045
 
        xorl    %edx, %edx
1046
 
        movb    nt_target_VCN, %dl
1047
 
        andb    $0xF, %dl
1048
 
        jz      2f
1049
 
 
1050
 
        pushw   %cx
1051
 
 
1052
 
        movb    nt_spc, %cl
1053
 
        addb    $9, %cl
1054
 
        shll    %cl, %edx               // edx: offset from the start of cluster
1055
 
 
1056
 
        push    %es
1057
 
        push    %di
1058
 
        call    seg_to_lin
1059
 
        subl    %edx, %eax              // eax: linear address
1060
 
 
1061
 
        movl    $16, nt_remain_leng
1062
 
        shll    %cl, nt_remain_leng
1063
 
 
1064
 
        popw    %cx
1065
 
 
1066
 
        addl    %edx, %ecx
1067
 
        subl    nt_remain_leng, %ecx
1068
 
 
1069
 
        pushl   %ecx
1070
 
        call    DecompressBlock
1071
 
        popl    %ecx
1072
 
 
1073
 
        addl    nt_remain_leng, %ecx
1074
 
 
1075
 
        jecxz   1f
1076
 
 
1077
 
2:
1078
 
        movl    %ecx, %edx
1079
 
        xorl    %eax, %eax
1080
 
        movl    %eax, %ecx
1081
 
        call    fix_es_di
1082
 
 
1083
 
3:
1084
 
        movw    $0x8000, %cx
1085
 
        cmpl    %edx, %ecx
1086
 
        jbe     4f
1087
 
        movw    %dx, %cx
1088
 
4:
1089
 
        pushw   %cx
1090
 
        shrw    $2, %cx
1091
 
 
1092
 
        rep     stosl   %eax, %es:(%di)
1093
 
        call    fix_es_di
1094
 
        popw    %cx
1095
 
        subl    %ecx, %edx
1096
 
        jnz     3b
1097
 
 
1098
 
1:
1099
 
        movw    %di, %bx
1100
 
 
1101
 
        popl    %edx
1102
 
        popw    %di
1103
 
 
1104
 
        ret
1105
 
 
1106
 
// Decompress block
1107
 
// Input:
1108
 
//     eax: linear address at the beginning of the compressed block
1109
 
// Output:
1110
 
//     ES:DI: points to the end of the block
1111
 
DecompressBlock:
1112
 
        pushw   %ds
1113
 
        pushw   %si
1114
 
 
1115
 
        pushl   %eax
1116
 
        call    lin_to_seg
1117
 
        popw    %si
1118
 
        popw    %ds
1119
 
        movl    nt_remain_leng, %edx
1120
 
        addl    %edx, %eax
1121
 
        pushl   %eax
1122
 
        call    lin_to_seg
1123
 
        popw    %di
1124
 
        popw    %es
1125
 
 
1126
 
        pushw   %es
1127
 
        pushw   %di
1128
 
        pushw   %ds
1129
 
        pushw   %si
1130
 
 
1131
 
        xorl    %ecx, %ecx
1132
 
 
1133
 
1:
1134
 
        movw    $0x8000, %cx
1135
 
        cmpl    %edx, %ecx
1136
 
        jbe     2f
1137
 
        movw    %dx, %cx
1138
 
2:
1139
 
        pushw   %cx
1140
 
        shrw    $2, %cx
1141
 
        rep     movsl   (%si), %es:(%di)
1142
 
        call    fix_segs
1143
 
        popw    %cx
1144
 
        subl    %ecx, %edx
1145
 
        jnz     1b
1146
 
 
1147
 
        popw    %di
1148
 
        popw    %es
1149
 
        popw    %si
1150
 
        popw    %ds
1151
 
 
1152
 
1:
1153
 
        xorl    %edx, %edx                      // edx - copied bytes
1154
 
 
1155
 
        lodsw   (%si), %ax
1156
 
        testb   $0x80, %ah
1157
 
        jnz     2f
1158
 
        movw    $0x800, %cx
1159
 
        rep     movsw   (%si), %es:(%di)
1160
 
        movw    $0x1000, %dx
1161
 
        jmp     7f                              // The block is not compressed
1162
 
 
1163
 
2:
1164
 
        movw    %ax, %cx
1165
 
        andw    $0xFFF, %cx
1166
 
        incw    %cx                             // ecx = block length
1167
 
        addw    %si, %cx                        // cx: end marker
1168
 
        xorb    %bh, %bh
1169
 
 
1170
 
3:
1171
 
        cmpw    $0x1000, %dx
1172
 
        ja      NTFS_Decompress_Error
1173
 
 
1174
 
        orb     %bh, %bh
1175
 
        jnz     4f
1176
 
        lodsb   (%si), %al
1177
 
        movb    %al, %bl                        // bl: tag, bh: count
1178
 
        movb    $8, %bh
1179
 
4:
1180
 
 
1181
 
        testb   $1, %bl
1182
 
        jz      5f
1183
 
 
1184
 
        movw    %dx, %ax
1185
 
        decw    %ax
1186
 
 
1187
 
        pushw   %cx
1188
 
        pushw   %bx
1189
 
 
1190
 
        movb    $12, %cl
1191
 
6:
1192
 
        cmpw    $0x10, %ax
1193
 
        jb      6f
1194
 
        shrw    $1, %ax
1195
 
        decb    %cl
1196
 
        jmp     6b
1197
 
6:
1198
 
 
1199
 
        lodsw   (%si), %ax
1200
 
        movw    %ax, %bx
1201
 
        shrw    %cl, %bx                        // bx: delta
1202
 
 
1203
 
        pushw   %dx
1204
 
        movw    $1, %dx
1205
 
        shlw    %cl, %dx
1206
 
        decw    %dx
1207
 
        andw    %dx, %ax
1208
 
        popw    %dx
1209
 
 
1210
 
        addw    $3, %ax
1211
 
        movw    %ax, %cx                        // cx: length
1212
 
        negw    %bx
1213
 
        decw    %bx
1214
 
 
1215
 
6:
1216
 
        movb    %es:(%bx, %di), %al
1217
 
        stosb   %al, %es:(%di)
1218
 
        incw    %dx
1219
 
        loop    6b
1220
 
 
1221
 
        popw    %bx
1222
 
        popw    %cx
1223
 
        jmp     4f
1224
 
 
1225
 
5:
1226
 
        movsb   (%si), %es:(%di)
1227
 
        incw    %dx
1228
 
4:
1229
 
        shrb    $1, %bl
1230
 
        decb    %bh
1231
 
 
1232
 
        cmpw    %cx, %si
1233
 
        jb      3b
1234
 
 
1235
 
7:
1236
 
        call    fix_segs
1237
 
 
1238
 
        subl    %edx, nt_remain_leng    // End of block
1239
 
        jz      1f
1240
 
 
1241
 
        cmpw    $0x1000, %dx
1242
 
        je      1b
1243
 
 
1244
 
1:
1245
 
 
1246
 
        popw    %si
1247
 
        popw    %ds
1248
 
        ret
1249
 
 
1250
 
NTFS_Decompress_Error:
1251
 
        pushw   %ss
1252
 
        popw    %ds
1253
 
        movb    $NTFS_Decompress_Error_Code, %al
1254
 
        jmp     NTFS_Error
1255
 
/*
1256
 
do_pause:
1257
 
        .byte   0
1258
 
 
1259
 
pause:
1260
 
        cmpb    $0, (do_pause - Entry_nt)(%bp)
1261
 
        jnz     1f
1262
 
        ret
1263
 
1:
1264
 
        xorw    %bp, %bp
1265
 
1:
1266
 
        jmp     1b
1267
 
*/
1268
 
 
1269
 
/*
1270
 
hex_out:
1271
 
        pushw   %bp
1272
 
        movw    %sp, %bp
1273
 
        pushaw
1274
 
        movb    $0xE, %ah
1275
 
        movw    $7, %bx
1276
 
        movw    $4, %cx
1277
 
        movw    4(%bp), %dx
1278
 
1:
1279
 
        rol     $4, %dx
1280
 
        movb    %dl, %al
1281
 
        andb    $0xF, %al
1282
 
        cmpb    $10, %al
1283
 
        jb      2f
1284
 
        subb    $('0'-'A'+10), %al
1285
 
2:
1286
 
        addb    $'0', %al
1287
 
        int     $0x10
1288
 
        loop    1b
1289
 
        movb    $' ', %al
1290
 
        int     $0x10
1291
 
        popaw
1292
 
        popw    %bp
1293
 
        ret     $2
1294
 
*/
1295
 
 
1296
 
        . = Entry_nt + 0x5fc
1297
 
 
1298
 
        .word   0, 0xAA55