| /* |
| * bootlace.inc -- code shared by 16-bit DOS and 32-bit Linux |
| * Copyright (ABS(C)) 2005 Tinybit(tinybit@163.net) |
| * |
| * This program is free software; you can redistribute it and/or modify |
| * it under the terms of the GNU General Public License as published by |
| * the Free Software Foundation; either version 2 of the License, or |
| * (at your option) any later version. |
| * |
| * This program is distributed in the hope that it will be useful, |
| * but WITHOUT ANY WARRANTY; without even the implied warranty of |
| * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
| * GNU General Public License for more details. |
| * |
| * You should have received a copy of the GNU General Public License |
| * along with this program; if not, write to the Free Software |
| * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. |
| */ |
| |
| .file "bootlace.inc" |
| |
| #ifdef __DOS_16 |
| |
| #undef ABS |
| #define ABS(x) (x - _start + 0x100) |
| |
| #undef iBX |
| #define iBX %bx |
| |
| #undef iSI |
| #define iSI %si |
| |
| #undef iDI |
| #define iDI %di |
| |
| #undef iDX |
| #define iDX %dx |
| |
| #undef LEAL |
| #define LEAL ADDR32 leal |
| |
| #undef MOVZWL |
| #define MOVZWL ADDR32 movzwl |
| |
| #undef MOVL |
| #define MOVL ADDR32 movl |
| |
| #undef MOVW |
| #define MOVW ADDR32 movw |
| |
| #undef CMPL |
| #define CMPL ADDR32 cmpl |
| |
| #undef CMPW |
| #define CMPW ADDR32 cmpw |
| |
| #undef SUBL |
| #define SUBL ADDR32 subl |
| |
| #undef SBBL |
| #define SBBL ADDR32 sbbl |
| |
| #undef NEGL |
| #define NEGL ADDR32 negl |
| |
| #undef NOTL |
| #define NOTL ADDR32 notl |
| |
| #undef ADCL |
| #define ADCL ADDR32 adcl |
| |
| #undef DIVL |
| #define DIVL ADDR32 divl |
| |
| . = _start + 0x34 // dos entry point invalid_dos_exec |
| |
| #if 0 |
| movl $ABS(msg_invalid_dos), %ecx |
| call 8f |
| |
| movw $0x4c01, %ax // EXIT - TERMINATE WITH RETURN CODE 1 |
| int $0x21 // call DOS |
| #else |
| jmp 1f |
| #endif |
| |
| |
| ////////////////////////////////////////////////////////////////////// |
| |
| . = _start + 0x47 // dos entry point |
| |
| 1: |
| /* dos entry point */ |
| |
| movl $0x81, %esi |
| movl %esi, %edi |
| movl $0x7f, %ecx |
| movb $0x0d, %al /* CR */ |
| |
| cld |
| repnz scasb |
| |
| decl %edi /* points to CR */ |
| std |
| movb $0, %al |
| stosb |
| movl %edi, %esi |
| xorl %ecx, %ecx |
| pushl %ecx /* 0 is the end of argv */ |
| xorl %edx, %edx /* find spaces */ |
| 3: |
| cmpl $0x81, %edi |
| jb 3f |
| lodsb |
| cmpb $0x20, %al |
| je 1f |
| cmpb $0x09, %al |
| jne 2f |
| 1: |
| testl %edx, %edx |
| jz 1f |
| notl %edx |
| incl %edi |
| pushl %edi /* argv */ |
| decl %edi |
| 1: |
| movb $0, %al |
| stosb |
| jmp 3b |
| 2: |
| testl %edx, %edx |
| jnz 1f |
| incl %ecx |
| notl %edx |
| 1: |
| stosb |
| jmp 3b |
| 3: |
| testl %edx, %edx |
| jz 1f |
| incl %edi |
| pushl %edi |
| 1: |
| pushl %esi /* dummy for program name */ |
| incl %ecx |
| pushl %ecx /* argc */ |
| cld |
| #else |
| |
| #undef ABS |
| #define ABS(x) (x) |
| |
| #undef iBX |
| #define iBX %ebx |
| |
| #undef iSI |
| #define iSI %esi |
| |
| #undef iDI |
| #define iDI %edi |
| |
| #undef iDX |
| #define iDX %edx |
| |
| #undef LEAL |
| #define LEAL leal |
| |
| #undef MOVZWL |
| #define MOVZWL movzwl |
| |
| #undef MOVL |
| #define MOVL movl |
| |
| #undef MOVW |
| #define MOVW movw |
| |
| #undef CMPL |
| #define CMPL cmpl |
| |
| #undef CMPW |
| #define CMPW cmpw |
| |
| #undef SUBL |
| #define SUBL subl |
| |
| #undef SBBL |
| #define SBBL sbbl |
| |
| #undef NEGL |
| #define NEGL negl |
| |
| #undef NOTL |
| #define NOTL notl |
| |
| #undef ADCL |
| #define ADCL adcl |
| |
| #undef DIVL |
| #define DIVL divl |
| |
| #endif |
| |
| popl %ecx # argc |
| |
| /* argc must be > 1 */ |
| |
| xorl %ebx, %ebx # invalid file descriptor for CLOSE below |
| |
| cmpl $1, %ecx |
| movl $ABS(msg_no_args), %ecx |
| jbe 4f /* error */ |
| |
| /* Note: ECX does not hold the argc now. */ |
| |
| xorl %eax, %eax # EAX will point to file name |
| //movl %ebx, ABS(filename) # save 0 to filename |
| popl %ecx # discard argv[0], the program name |
| 1: |
| popl %ecx # argv |
| movl %ecx, %ebx |
| test %ecx, %ecx |
| jz 1f # end of arguments |
| |
| /* check if it is an option */ |
| cmpb $0x2D, (iBX) # "-" |
| jz 2f |
| |
| /* it is a filename */ |
| |
| testl %eax, %eax # filename already specified? |
| //cmpl $0, ABS(filename) |
| jz 3f |
| |
| /* error: only one file should be specified. */ |
| |
| xorl %ebx, %ebx # invalid file descriptor for CLOSE below |
| |
| movl $ABS(msg_too_many_files), %ecx |
| jmp 4f /* error */ |
| |
| 3: |
| |
| /* not yet, this is the first filename */ |
| |
| movl %ecx, %eax # save ECX to EAX |
| //movl %ecx, ABS(filename) # save ECX to filename |
| jmp 1b # continue |
| |
| 2: |
| |
| /* it is an option */ |
| |
| /* check --no-backup-mbr */ |
| |
| movl $16, %ecx |
| movl $ABS(option_no_backup_mbr), %esi |
| movl %ebx, %edi |
| |
| cld |
| repz cmpsb |
| |
| jnz 3f |
| |
| xorl %ebx, %ebx # invalid file descriptor for CLOSE below |
| |
| cmpl $1, ABS(backup_mbr) |
| movl $ABS(msg_option_backup_mbr), %ecx |
| jnz 4f /* error */ |
| movl $0, ABS(backup_mbr) |
| jmp 1b |
| |
| 3: |
| /* check --force-backup-mbr */ |
| |
| movl $19, %ecx |
| movl $ABS(option_force_backup_mbr), %esi |
| movl %ebx, %edi |
| |
| cld |
| repz cmpsb |
| |
| jnz 3f |
| |
| xorl %ebx, %ebx # invalid file descriptor for CLOSE below |
| |
| cmpl $1, ABS(backup_mbr) |
| movl $ABS(msg_option_backup_mbr), %ecx |
| jnz 4f /* error */ |
| movl $2, ABS(backup_mbr) |
| jmp 1b |
| |
| 3: |
| |
| /* check --mbr-enable-floppy */ |
| |
| movl $20, %ecx |
| movl $ABS(option_mbr_enable_floppy), %esi |
| movl %ebx, %edi |
| |
| cld |
| repz cmpsb |
| |
| jnz 3f |
| |
| xorl %ebx, %ebx # invalid file descriptor for CLOSE below |
| |
| cmpl $0, ABS(mbr_floppy) |
| movl $ABS(msg_option_mbr_floppy), %ecx |
| jnz 4f /* error */ |
| movl $2, ABS(mbr_floppy) |
| jmp 1b |
| |
| 3: |
| |
| /* check --mbr-disable-floppy */ |
| |
| movl $21, %ecx |
| movl $ABS(option_mbr_disable_floppy), %esi |
| movl %ebx, %edi |
| |
| cld |
| repz cmpsb |
| |
| jnz 3f |
| |
| xorl %ebx, %ebx # invalid file descriptor for CLOSE below |
| |
| cmpl $0, ABS(mbr_floppy) |
| movl $ABS(msg_option_mbr_floppy), %ecx |
| jnz 4f /* error */ |
| movl $1, ABS(mbr_floppy) |
| jmp 1b |
| |
| 3: |
| |
| /* check --mbr-enable-osbr */ |
| |
| movl $18, %ecx |
| movl $ABS(option_mbr_enable_osbr), %esi |
| movl %ebx, %edi |
| |
| cld |
| repz cmpsb |
| |
| jnz 3f |
| |
| xorl %ebx, %ebx # invalid file descriptor for CLOSE below |
| |
| cmpl $0, ABS(mbr_osbr) |
| movl $ABS(msg_option_mbr_osbr), %ecx |
| jnz 4f /* error */ |
| movl $2, ABS(mbr_osbr) |
| jmp 1b |
| |
| 3: |
| |
| /* check --mbr-disable-osbr */ |
| |
| movl $19, %ecx |
| movl $ABS(option_mbr_disable_osbr), %esi |
| movl %ebx, %edi |
| |
| cld |
| repz cmpsb |
| |
| jnz 3f |
| |
| xorl %ebx, %ebx # invalid file descriptor for CLOSE below |
| |
| cmpl $0, ABS(mbr_osbr) |
| movl $ABS(msg_option_mbr_osbr), %ecx |
| jnz 4f /* error */ |
| movl $1, ABS(mbr_osbr) |
| jmp 1b |
| |
| 3: |
| |
| /* check --duce */ |
| |
| movl $7, %ecx |
| movl $ABS(option_duce), %esi |
| movl %ebx, %edi |
| |
| cld |
| repz cmpsb |
| |
| jnz 3f |
| |
| xorl %ebx, %ebx # invalid file descriptor for CLOSE below |
| |
| cmpl $0, ABS(duce) |
| movl $ABS(msg_option_duce), %ecx |
| jnz 4f /* error */ |
| movl $1, ABS(duce) |
| jmp 1b |
| |
| 3: |
| |
| /* check --boot-prevmbr-first */ |
| |
| movl $21, %ecx |
| movl $ABS(option_boot_prevmbr_first), %esi |
| movl %ebx, %edi |
| |
| cld |
| repz cmpsb |
| |
| jnz 3f |
| |
| xorl %ebx, %ebx # invalid file descriptor for CLOSE below |
| |
| cmpl $0, ABS(boot_prevmbr) |
| movl $ABS(msg_option_boot_prevmbr), %ecx |
| jnz 4f /* error */ |
| movl $1, ABS(boot_prevmbr) |
| jmp 1b |
| |
| 3: |
| |
| /* check --boot-prevmbr-last */ |
| |
| movl $20, %ecx |
| movl $ABS(option_boot_prevmbr_last), %esi |
| movl %ebx, %edi |
| |
| cld |
| repz cmpsb |
| |
| jnz 3f |
| |
| xorl %ebx, %ebx # invalid file descriptor for CLOSE below |
| |
| cmpl $0, ABS(boot_prevmbr) |
| movl $ABS(msg_option_boot_prevmbr), %ecx |
| jnz 4f /* error */ |
| movl $2, ABS(boot_prevmbr) |
| jmp 1b |
| |
| 3: |
| |
| /* check --preferred-drive= */ |
| |
| movl $18, %ecx |
| movl $ABS(option_preferred_drive), %esi |
| movl %ebx, %edi |
| |
| cld |
| repz cmpsb |
| |
| jnz 3f |
| |
| xorl %ebx, %ebx # invalid file descriptor for CLOSE below |
| |
| cmpl $0xff, ABS(preferred_drive) |
| movl $ABS(msg_option_preferred_drive), %ecx |
| jnz 4f /* error */ |
| |
| movl $0xfe, %ebx |
| call 7f /* parse_number */ |
| movl %ebx, %edi # save EBX to EDI |
| movl $0, %ebx # invalid file descriptor for CLOSE below |
| movl $ABS(msg_invalid_number), %ecx |
| jc 4f /* error */ |
| movl %edi, ABS(preferred_drive) |
| jmp 1b |
| |
| 3: |
| |
| /* check --preferred-partition= */ |
| |
| movl $22, %ecx |
| movl $ABS(option_preferred_partition), %esi |
| movl %ebx, %edi |
| |
| cld |
| repz cmpsb |
| |
| jnz 3f |
| |
| xorl %ebx, %ebx # invalid file descriptor for CLOSE below |
| |
| cmpl $0xff, ABS(preferred_partition) |
| movl $ABS(msg_option_preferred_partition), %ecx |
| jnz 4f /* error */ |
| |
| movl $0xfe, %ebx |
| call 7f /* parse_number */ |
| movl %ebx, %edi # save EBX to EDI |
| movl $0, %ebx # invalid file descriptor for CLOSE below |
| movl $ABS(msg_invalid_number), %ecx |
| jc 4f /* error */ |
| movl %edi, ABS(preferred_partition) |
| jmp 1b |
| |
| 3: |
| |
| /* check --time-out= */ |
| |
| movl $11, %ecx |
| movl $ABS(option_time_out), %esi |
| movl %ebx, %edi |
| |
| cld |
| repz cmpsb |
| |
| jnz 3f |
| |
| xorl %ebx, %ebx # invalid file descriptor for CLOSE below |
| |
| cmpl $0xffffff05, ABS(time_out) |
| movl $ABS(msg_option_time_out), %ecx |
| jnz 4f /* error */ |
| |
| movl $0xff, %ebx |
| call 7f /* parse_number */ |
| movl %ebx, %edi # save EBX to EDI |
| movl $0, %ebx # invalid file descriptor for CLOSE below |
| movl $ABS(msg_invalid_number), %ecx |
| jc 4f /* error */ |
| movl %edi, ABS(time_out) |
| jmp 1b |
| |
| 3: |
| |
| /* check --hot-key= */ |
| |
| movl $10, %ecx |
| movl $ABS(option_hot_key), %esi |
| movl %ebx, %edi |
| |
| cld |
| repz cmpsb |
| |
| jnz 3f |
| |
| xorl %ebx, %ebx # invalid file descriptor for CLOSE below |
| |
| cmpl $0xffff3920, ABS(hot_key) |
| movl $ABS(msg_option_hot_key), %ecx |
| jnz 4f /* error */ |
| |
| movl $0xffff, %ebx |
| call 7f /* parse_number */ |
| movl %ebx, %edi # save EBX to EDI |
| movl $0, %ebx # invalid file descriptor for CLOSE below |
| movl $ABS(msg_invalid_number), %ecx |
| jc 4f /* error */ |
| movl %edi, ABS(hot_key) |
| jmp 1b |
| |
| 3: |
| |
| /* check --install-partition= */ |
| |
| movl $20, %ecx |
| movl $ABS(option_install_partition), %esi |
| movl %ebx, %edi |
| |
| cld |
| repz cmpsb |
| |
| jnz 3f |
| |
| xorl %ebx, %ebx # invalid file descriptor for CLOSE below |
| |
| cmpl $0xffffffff, ABS(install_partition) |
| movl $ABS(msg_option_install_partition), %ecx |
| jnz 4f /* error */ |
| |
| movl $0xffff, %ebx |
| call 7f /* parse_number */ |
| movl %ebx, %edi # save EBX to EDI |
| movl $0, %ebx # invalid file descriptor for CLOSE below |
| movl $ABS(msg_invalid_number), %ecx |
| jc 4f /* error */ |
| movl %edi, ABS(install_partition) |
| jmp 1b |
| |
| 3: |
| |
| /* check --sectors-per-track= */ |
| |
| movl $20, %ecx |
| movl $ABS(option_sectors_per_track), %esi |
| movl %ebx, %edi |
| |
| cld |
| repz cmpsb |
| |
| jnz 3f |
| |
| xorl %ebx, %ebx # invalid file descriptor for CLOSE below |
| |
| cmpl $0xffffff3f, ABS(sectors_per_track) |
| movl $ABS(msg_option_sectors_per_track), %ecx |
| jnz 4f /* error */ |
| |
| movl $0x3f, %ebx # maximum is 63 |
| call 7f /* parse_number */ |
| movl %ebx, %edi # save EBX to EDI |
| movl $0, %ebx # invalid file descriptor for CLOSE below |
| movl $ABS(msg_invalid_number), %ecx |
| jc 4f /* error */ |
| cmpl $0, %edi |
| je 4f /* error */ |
| movl %edi, ABS(sectors_per_track) |
| jmp 1b |
| |
| 3: |
| |
| /* check --heads= */ |
| |
| movl $8, %ecx |
| movl $ABS(option_heads), %esi |
| movl %ebx, %edi |
| |
| cld |
| repz cmpsb |
| |
| jnz 3f |
| |
| xorl %ebx, %ebx # invalid file descriptor for CLOSE below |
| |
| cmpl $0xffff00ff, ABS(heads) |
| movl $ABS(msg_option_heads), %ecx |
| jnz 4f /* error */ |
| |
| movl $0x100, %ebx # maximum is 256 |
| call 7f /* parse_number */ |
| movl %ebx, %edi # save EBX to EDI |
| movl $0, %ebx # invalid file descriptor for CLOSE below |
| movl $ABS(msg_invalid_number), %ecx |
| jc 4f /* error */ |
| cmpl $0, %edi |
| je 4f /* error */ |
| movl %edi, ABS(heads) |
| jmp 1b |
| |
| 3: |
| |
| /* check --start-sector= */ |
| |
| movl $15, %ecx |
| movl $ABS(option_start_sector), %esi |
| movl %ebx, %edi |
| |
| cld |
| repz cmpsb |
| |
| jnz 3f |
| |
| xorl %ebx, %ebx # invalid file descriptor for CLOSE below |
| |
| cmpl $0xffffffff, ABS(start_sector) |
| movl $ABS(msg_option_start_sector), %ecx |
| jnz 4f /* error */ |
| |
| movl $0xfffffffe, %ebx |
| call 7f /* parse_number */ |
| movl %ebx, %edi # save EBX to EDI |
| movl $0, %ebx # invalid file descriptor for CLOSE below |
| movl $ABS(msg_invalid_number), %ecx |
| jc 4f /* error */ |
| movl %edi, ABS(start_sector) |
| jmp 1b |
| |
| 3: |
| |
| /* check --total-sectors= */ |
| |
| movl $16, %ecx |
| movl $ABS(option_total_sectors), %esi |
| movl %ebx, %edi |
| |
| cld |
| repz cmpsb |
| |
| jnz 3f |
| |
| xorl %ebx, %ebx # invalid file descriptor for CLOSE below |
| |
| cmpl $0, ABS(total_sectors) |
| movl $ABS(msg_option_total_sectors), %ecx |
| jnz 4f /* error */ |
| |
| movl $0xffffffff, %ebx |
| call 7f /* parse_number */ |
| movl %ebx, %edi # save EBX to EDI |
| movl $0, %ebx # invalid file descriptor for CLOSE below |
| movl $ABS(msg_invalid_number), %ecx |
| jc 4f /* error */ |
| cmpl $0, %edi |
| je 4f /* error */ |
| movl %edi, ABS(total_sectors) |
| jmp 1b |
| |
| 3: |
| |
| /* check --floppy= */ |
| |
| movl $9, %ecx |
| movl $ABS(option_floppy_partition), %esi |
| movl %ebx, %edi |
| |
| cld |
| repz cmpsb |
| |
| jnz 3f |
| |
| xorl %ebx, %ebx # invalid file descriptor for CLOSE below |
| |
| cmpl $0xffffffff, ABS(floppy) |
| movl $ABS(msg_option_floppy), %ecx |
| jnz 4f /* error */ |
| |
| movl $0xfe, %ebx |
| call 7f /* parse_number */ |
| movl %ebx, %edi # save EBX to EDI |
| movl $0, %ebx # invalid file descriptor for CLOSE below |
| movl $ABS(msg_invalid_number), %ecx |
| jc 4f /* error */ |
| movl %edi, ABS(floppy) |
| jmp 1b |
| |
| 3: |
| |
| /* check --read-only */ |
| |
| movl $12, %ecx |
| movl $ABS(option_read_only), %esi |
| movl %ebx, %edi |
| |
| cld |
| repz cmpsb |
| |
| jnz 3f |
| |
| xorl %ebx, %ebx # invalid file descriptor for CLOSE below |
| |
| cmpl $2, ABS(read_only) |
| movl $ABS(msg_option_read_only), %ecx |
| jnz 4f /* error */ |
| |
| movl $0, ABS(read_only) |
| jmp 1b |
| |
| 3: |
| |
| /* check --floppy */ |
| |
| movl $9, %ecx |
| movl $ABS(option_floppy), %esi |
| movl %ebx, %edi |
| |
| cld |
| repz cmpsb |
| |
| jnz 3f |
| |
| xorl %ebx, %ebx # invalid file descriptor for CLOSE below |
| |
| cmpl $0xffffffff, ABS(floppy) |
| movl $ABS(msg_option_floppy), %ecx |
| jnz 4f /* error */ |
| |
| movl $0xff, ABS(floppy) |
| jmp 1b |
| |
| 3: |
| |
| /* check --lba */ |
| |
| movl $6, %ecx |
| movl $ABS(option_lba), %esi |
| movl %ebx, %edi |
| |
| cld |
| repz cmpsb |
| |
| jnz 3f |
| |
| xorl %ebx, %ebx # invalid file descriptor for CLOSE below |
| |
| cmpl $0xffffffff, ABS(lba) |
| movl $ABS(msg_option_lba), %ecx |
| jnz 4f /* error */ |
| |
| movl $1, ABS(lba) |
| jmp 1b |
| |
| 3: |
| |
| /* check --chs */ |
| |
| movl $6, %ecx |
| movl $ABS(option_chs), %esi |
| movl %ebx, %edi |
| |
| cld |
| repz cmpsb |
| |
| jnz 3f |
| |
| xorl %ebx, %ebx # invalid file descriptor for CLOSE below |
| |
| cmpl $0xffffffff, ABS(lba) |
| movl $ABS(msg_option_lba), %ecx |
| jnz 4f /* error */ |
| |
| movl $0, ABS(lba) |
| jmp 1b |
| |
| 3: |
| |
| /* check --fat12 */ |
| |
| movl $8, %ecx |
| movl $ABS(option_fat12), %esi |
| movl %ebx, %edi |
| |
| cld |
| repz cmpsb |
| |
| jnz 3f |
| |
| xorl %ebx, %ebx # invalid file descriptor for CLOSE below |
| |
| cmpl $0xfffffff7, ABS(fstypes) |
| jnz 2f |
| movl $0, ABS(fstypes) |
| 2: |
| orb $1, ABS(fstypes) |
| jmp 1b |
| |
| 3: |
| |
| /* check --fat16 */ |
| |
| movl $8, %ecx |
| movl $ABS(option_fat16), %esi |
| movl %ebx, %edi |
| |
| cld |
| repz cmpsb |
| |
| jnz 3f |
| |
| xorl %ebx, %ebx # invalid file descriptor for CLOSE below |
| |
| cmpl $0xfffffff7, ABS(fstypes) |
| jnz 2f |
| movl $0, ABS(fstypes) |
| 2: |
| orb $2, ABS(fstypes) |
| jmp 1b |
| |
| 3: |
| |
| /* check --fat32 */ |
| |
| movl $8, %ecx |
| movl $ABS(option_fat32), %esi |
| movl %ebx, %edi |
| |
| cld |
| repz cmpsb |
| |
| jnz 3f |
| |
| xorl %ebx, %ebx # invalid file descriptor for CLOSE below |
| |
| cmpl $0xfffffff7, ABS(fstypes) |
| jnz 2f |
| movl $0, ABS(fstypes) |
| 2: |
| orb $4, ABS(fstypes) |
| jmp 1b |
| |
| 3: |
| |
| /* check --ntfs */ |
| |
| movl $7, %ecx |
| movl $ABS(option_ntfs), %esi |
| movl %ebx, %edi |
| |
| cld |
| repz cmpsb |
| |
| jnz 3f |
| |
| xorl %ebx, %ebx # invalid file descriptor for CLOSE below |
| |
| cmpl $0xfffffff7, ABS(fstypes) |
| jnz 2f |
| movl $0, ABS(fstypes) |
| 2: |
| orb $8, ABS(fstypes) |
| jmp 1b |
| |
| 3: |
| |
| /* check --ext2 */ |
| |
| movl $7, %ecx |
| movl $ABS(option_ext2), %esi |
| movl %ebx, %edi |
| |
| cld |
| repz cmpsb |
| |
| jnz 3f |
| |
| xorl %ebx, %ebx # invalid file descriptor for CLOSE below |
| |
| cmpl $0xfffffff7, ABS(fstypes) |
| jnz 2f |
| movl $0, ABS(fstypes) |
| 2: |
| orb $0x10, ABS(fstypes) |
| jmp 1b |
| |
| 3: |
| |
| /* check --vfat */ |
| |
| movl $7, %ecx |
| movl $ABS(option_vfat), %esi |
| movl %ebx, %edi |
| |
| cld |
| repz cmpsb |
| |
| jnz 3f |
| |
| xorl %ebx, %ebx # invalid file descriptor for CLOSE below |
| |
| cmpl $0xfffffff7, ABS(fstypes) |
| jnz 2f |
| movl $0, ABS(fstypes) |
| 2: |
| orb $7, ABS(fstypes) |
| jmp 1b |
| |
| 3: |
| |
| movl $ABS(msg_invalid_option), %ecx |
| jmp 4f /* error */ |
| |
| 1: |
| |
| //---------------------------------------------------------------------------- |
| /* end of arguments */ |
| |
| /* ECX=EBX=0 */ |
| |
| xorl %ebx, %ebx # invalid file descriptor for CLOSE below |
| |
| testl %eax, %eax # filename already specified? |
| //cmpl $0, ABS(filename) # filename already specified? |
| movl $ABS(msg_no_file), %ecx |
| jz 4f /* error */ |
| |
| xchgl %eax, %ebx # move EAX to EBX |
| //movl ABS(filename), %ebx # move filename to EBX |
| |
| /* EBX points to the pathname of the file. */ |
| |
| /* check if preferred_partition matches preferred_drive */ |
| |
| movb ABS(preferred_drive), %al |
| movb ABS(preferred_partition), %ah |
| |
| cmpb $0xff, %al |
| jne 1f |
| |
| movl %ebx, %edi # save EBX to EDI |
| xorl %ebx, %ebx # invalid file descriptor for CLOSE below |
| cmpb $0xff, %ah |
| movl $ABS(msg_partition_without_drive), %ecx |
| jne 4f /* error */ |
| movl %edi, %ebx # restore EBX from EDI |
| 1: |
| |
| /* EBX points to the pathname of the file. */ |
| |
| movl %ebx, %edi # save EBX to EDI |
| xorl %ebx, %ebx # invalid file descriptor for CLOSE below |
| |
| cmpl $0xffffffff, ABS(floppy) |
| je 1f # --floppy is not specified |
| |
| /* if --floppy is specified, should not specify the options for MBR. */ |
| cmpl $1, ABS(backup_mbr) |
| movl $ABS(msg_option_backup_mbr_with_floppy), %ecx |
| jnz 4f /* error */ |
| |
| cmpl $0, ABS(mbr_floppy) |
| movl $ABS(msg_option_mbr_floppy_with_floppy), %ecx |
| jnz 4f /* error */ |
| |
| cmpl $0, ABS(mbr_osbr) |
| movl $ABS(msg_option_mbr_osbr_with_floppy), %ecx |
| jnz 4f /* error */ |
| |
| cmpl $0, ABS(duce) |
| movl $ABS(msg_option_duce_with_floppy), %ecx |
| jnz 4f /* error */ |
| |
| cmpl $0, ABS(boot_prevmbr) |
| movl $ABS(msg_option_boot_prevmbr_with_floppy), %ecx |
| jnz 4f /* error */ |
| |
| cmpl $0xff, ABS(preferred_drive) |
| movl $ABS(msg_option_preferred_drive_with_floppy), %ecx |
| jnz 4f /* error */ |
| |
| cmpl $0xff, ABS(preferred_partition) |
| movl $ABS(msg_option_preferred_partition_with_floppy), %ecx |
| jnz 4f /* error */ |
| |
| cmpl $0xffffffff, ABS(install_partition) |
| movl $ABS(msg_option_install_partition_with_floppy), %ecx |
| jnz 4f /* error */ |
| |
| cmpl $0xffffff05, ABS(time_out) |
| movl $ABS(msg_option_time_out_with_floppy), %ecx |
| jnz 4f /* error */ |
| |
| cmpl $0xffff3920, ABS(hot_key) |
| movl $ABS(msg_option_hot_key_with_floppy), %ecx |
| jnz 4f /* error */ |
| |
| /* for a floppy, start_sector should be 0, and |
| * for a partition, start_sector should be non-zero |
| */ |
| cmpl $0xff, ABS(floppy) |
| je 2f # a real floppy |
| |
| /* a single partition */ |
| cmpl $0, ABS(start_sector) |
| movl $ABS(msg_partition_start), %ecx |
| jz 4f /* error */ |
| |
| jmp 3f |
| 2: |
| /* a real floppy */ |
| /* */ |
| cmpl $0xffffffff, ABS(start_sector) |
| je 3f |
| cmpl $0, ABS(start_sector) |
| movl $ABS(msg_floppy_start), %ecx |
| jnz 4f /* error */ |
| |
| 3: |
| jmp 2f |
| 1: |
| |
| /* EBX=0 */ |
| |
| cmpl $0xffffffff, ABS(install_partition) |
| je 1f # --install-partition is not specified |
| |
| /* should not specify --install-partition with options for MBR. */ |
| cmpl $1, ABS(backup_mbr) |
| movl $ABS(msg_option_backup_mbr_with_partition), %ecx |
| jnz 4f /* error */ |
| |
| cmpl $0, ABS(mbr_floppy) |
| movl $ABS(msg_option_mbr_floppy_with_partition), %ecx |
| jnz 4f /* error */ |
| |
| cmpl $0, ABS(mbr_osbr) |
| movl $ABS(msg_option_mbr_osbr_with_partition), %ecx |
| jnz 4f /* error */ |
| |
| cmpl $0, ABS(duce) |
| movl $ABS(msg_option_duce_with_partition), %ecx |
| jnz 4f /* error */ |
| |
| cmpl $0, ABS(boot_prevmbr) |
| movl $ABS(msg_option_boot_prevmbr_with_partition), %ecx |
| jnz 4f /* error */ |
| |
| cmpl $0xff, ABS(preferred_drive) |
| movl $ABS(msg_option_preferred_drive_with_partition), %ecx |
| jnz 4f /* error */ |
| |
| cmpl $0xff, ABS(preferred_partition) |
| movl $ABS(msg_option_preferred_partition_with_partition), %ecx |
| jnz 4f /* error */ |
| |
| cmpl $0xffffff05, ABS(time_out) |
| movl $ABS(msg_option_time_out_with_partition), %ecx |
| jnz 4f /* error */ |
| |
| cmpl $0xffff3920, ABS(hot_key) |
| movl $ABS(msg_option_hot_key_with_partition), %ecx |
| jnz 4f /* error */ |
| |
| cmpl $0xffffff3f, ABS(sectors_per_track) |
| movl $ABS(msg_option_sectors_per_track_with_partition), %ecx |
| jnz 4f /* error */ |
| |
| cmpl $0xffff00ff, ABS(heads) |
| movl $ABS(msg_option_heads_with_partition), %ecx |
| jnz 4f /* error */ |
| |
| cmpl $0xffffffff, ABS(start_sector) |
| movl $ABS(msg_option_start_sector_with_partition), %ecx |
| jnz 4f /* error */ |
| |
| cmpl $0, ABS(total_sectors) |
| movl $ABS(msg_option_total_sectors_with_partition), %ecx |
| jnz 4f /* error */ |
| |
| jmp 2f |
| 1: |
| |
| /* EBX=0 */ |
| |
| /* this is an MBR device. Should not specify floppy-specific options. */ |
| |
| testl $1, ABS(boot_prevmbr) /* --boot-prevmbr-first specified? */ |
| jnz 2f /* Yes, specified. Continue */ |
| /* No, not specified. */ |
| /* Should not specify --time-out without --boot-prevmbr-first. */ |
| cmpl $0xffffff05, ABS(time_out) |
| movl $ABS(msg_option_time_out_without_prevmbr), %ecx |
| jne 4f /* error */ |
| |
| /* Should not specify --hot-key without --boot-prevmbr-first. */ |
| cmpl $0xffff3920, ABS(hot_key) |
| movl $ABS(msg_option_hot_key_without_prevmbr), %ecx |
| jne 4f /* error */ |
| |
| 2: |
| |
| /* EBX=0, EDI points to the pathname of the file. */ |
| |
| //---------------------------------------------------------------------------- |
| movl %edi, %ebx # restore EBX from EDI |
| |
| /* EBX=EDI points to the pathname of the file. */ |
| |
| #ifdef __DOS_16 |
| |
| xorl %eax, %eax |
| //movl %ebx, %edi /* EBX points to the pathname of the file. */ |
| movl $0xfe, %ebx |
| call 7f /* parse_number */ |
| jc 2f /* invalid number */ |
| /* EBX holds the bios drive number */ |
| movl %ebx, ABS(bios_drive_number) |
| jmp 1f |
| 2: |
| //AH = 3Dh //OPEN EXISTING FILE |
| //AL = access and sharing modes (see #01402) |
| //DS:DX -> ASCIZ filename |
| //CL = attribute mask of files to look for (server call only) |
| |
| //Return: |
| //CF clear if successful AX = file handle |
| //CF set on error AX = error code (01h,02h,03h,04h,05h,0Ch,56h) |
| |
| movzbl ABS(read_only), %eax |
| movb $0x3d, %ah // open file for read/write |
| movl %edi, %edx // DS:DX points to ASCIZ filename |
| int $0x21 |
| jnc 1f |
| negl %eax /* EAX < 0 */ |
| 1: |
| #else |
| |
| /* int open(const char *pathname, int flags, mode_t mode) */ |
| |
| movl $5, %eax # sys_open |
| movzbl ABS(read_only), %ecx # O_RDWR = 02 |
| int $0x80 |
| #endif |
| xorl %ebx, %ebx # invalid file descriptor for CLOSE below |
| movl $ABS(msg_open_file_rw), %ecx |
| cmpw $2, ABS(read_only) |
| je 1f |
| movl $ABS(msg_open_file_ro), %ecx |
| 1: |
| testl %eax, %eax |
| js 4f /* error */ |
| |
| //---------------------------------------------------------------------------- |
| /* open file succeeded */ |
| |
| pushl %eax # file descriptor, or 0 if specified BIOS drive |
| movl %eax, %ebx |
| |
| /* EBX and the stack holds the file descriptor number or 0 */ |
| |
| #ifdef __DOS_16 |
| |
| xorl %eax, %eax |
| cmpl $0xff, ABS(bios_drive_number) |
| je 1f |
| movw $0x204, %ax # read 4 sectors of the MBR |
| movw $ABS(mbr_63_sectors), %bx |
| movw $1, %cx |
| movw ABS(bios_drive_number), %dx |
| int $0x13 |
| jmp 2f |
| 1: |
| //READ FROM FILE OR DEVICE |
| |
| //AH = 3Fh |
| //BX = file handle |
| //CX = number of bytes to read |
| //DS:DX -> buffer for data |
| |
| //Return: |
| //CF clear if successful AX = number of bytes actually read (0 if at EOF before call) |
| //CF set on error AX = error code (05h,06h) |
| movl $0x3f00, %eax |
| movl $(63*512), %ecx |
| movl $ABS(mbr_63_sectors), %edx |
| int $0x21 |
| 2: |
| jnc 1f |
| negl %eax |
| 1: |
| #else |
| /* ssize_t read(int fd, void *buf, size_t count) */ |
| |
| movl $3, %eax # sys_read |
| movl $ABS(mbr_63_sectors), %ecx |
| movl $(63*512), %edx # read 63 sectors |
| int $0x80 |
| #endif |
| |
| popl %ebx # file descriptor, or 0 if specified BIOS drive |
| testl %eax, %eax |
| movl $ABS(msg_read_file), %ecx |
| js 4f /* error */ |
| |
| //---------------------------------------------------------------------------- |
| |
| /* rewind the file for write! important! */ |
| |
| pushl %ebx # file descriptor, or 0 if specified BIOS drive |
| |
| #ifdef __DOS_16 |
| |
| xorl %eax, %eax |
| cmpl $0xff, ABS(bios_drive_number) |
| jne 1f |
| //LSEEK - SET CURRENT FILE POSITION |
| |
| //AH = 42h |
| //AL = origin of move |
| // 00h start of file |
| // 01h current file position |
| // 02h end of file |
| //BX = file handle |
| //CX:DX = (signed) offset from origin of new file position |
| |
| //Return: |
| //CF clear if successful DX:AX = new file position in bytes from start of file |
| //CF set on error AX = error code (01h,06h) |
| movl $0x4200, %eax |
| movl $0, %ecx |
| movl $0, %edx |
| int $0x21 |
| jnc 1f |
| negl %eax |
| 1: |
| #else |
| /* off_t lseek(int fildes, off_t offset, int whence) */ |
| |
| movl $19, %eax # sys_lseek |
| movl $0, %ecx |
| movl $0, %edx # SEEK_SET = 0 |
| int $0x80 |
| #endif |
| |
| popl %ebx # file descriptor, or 0 if specified BIOS drive |
| testl %eax, %eax |
| movl $ABS(msg_lseek_file), %ecx |
| js 4f /* error */ |
| |
| //---------------------------------------------------------------------------- |
| /* remember EBX holds file descriptor number, and don't touch it */ |
| |
| /* check if the partition table is valid. */ |
| |
| movl $ABS(mbr_63_sectors), %esi |
| cmpw $0xAA55, 0x1fe(iSI) |
| movl $ABS(msg_boot_signature_mbr), %ecx |
| //jne 4f /* error */ |
| clc |
| jne 2f |
| |
| call 9f /* probe_geometry */ |
| jnc 1f |
| |
| 2: |
| |
| /* should be floppy since no partition table or no boot signature. */ |
| |
| /* CF=0 means no boot signature, CF=1 means no partition table. */ |
| |
| jnc 2f |
| |
| movl $ABS(msg_invalid_partition_table), %ecx |
| 2: |
| cmpl $0xffffffff, ABS(floppy) /* Is --floppy specified? */ |
| je 4f /* error */ |
| |
| /* Yes, --floppy is specified */ |
| |
| /* ESI points to ABS(mbr_63_sectors) */ |
| call 5f /* floppy routine */ |
| movl $0, %ecx |
| jc 4f /* error */ |
| |
| jmp 2f /* write file */ |
| 1: |
| |
| //---------------------------------------------------------------------------- |
| /* the image type is MBR. So, should not specify --floppy */ |
| |
| cmpl $0xffffffff, ABS(floppy) |
| movl $ABS(msg_floppy_partition_table), %ecx |
| jne 4f /* error */ |
| |
| cmpl $0xffffff3f, ABS(sectors_per_track) |
| movl $ABS(msg_option_sectors_per_track_for_mbr), %ecx |
| jnz 4f /* error */ |
| |
| cmpl $0xffff00ff, ABS(heads) |
| movl $ABS(msg_option_heads_for_mbr), %ecx |
| jnz 4f /* error */ |
| |
| cmpl $0xffffffff, ABS(start_sector) |
| movl $ABS(msg_option_start_sector_for_mbr), %ecx |
| jnz 4f /* error */ |
| |
| cmpl $0, ABS(total_sectors) |
| movl $ABS(msg_option_total_sectors_for_mbr), %ecx |
| jnz 4f /* error */ |
| |
| cmpl $0xffffffff, ABS(lba) |
| movl $ABS(msg_option_lba_for_mbr), %ecx |
| jnz 4f /* error */ |
| |
| cmpl $0xfffffff7, ABS(fstypes) |
| movl $ABS(msg_option_fstypes_for_mbr), %ecx |
| jnz 4f /* error */ |
| |
| cmpl $((pre_stage2_start - _start1) / 512), ABS(probed_sectors_per_track) |
| movl $ABS(msg_sectors_per_track), %ecx |
| jb 4f /* error */ |
| |
| cmpl $0xffffffff, ABS(install_partition) |
| movl $ABS(msg_option_install_partition_not_implemented), %ecx |
| je 1f |
| jmp 4f /* error */ |
| /* EBX holds the file descriptor number or 0 if it is BIOS drive */ |
| /* move partition table forward to the beginning of the 17th sector */ |
| movl $ABS(mbr_63_sectors + 0x01be), %esi |
| movl $ABS(mbr_63_sectors + 0x2000), %edi |
| movl $0x10, %ecx # 0x10 dwords = 0x40 bytes |
| |
| cld |
| repz movsl |
| |
| /* initialize the current_partition number */ |
| movzbl ABS(install_partition), %eax |
| movl %eax, ABS(current_partition) |
| |
| 3: |
| /* load the next partition and modify the boot record */ |
| call 0f /* partition */ |
| jc 3f /* done */ |
| call 2f /* write to file */ |
| incl ABS(current_partition) |
| movw ABS(install_partition), %ax |
| addb %ah, %al /* Max partition number for install */ |
| cmpb %al, ABS(current_partition) |
| jbe 3b |
| 3: |
| /* all partitions have been installed. */ |
| |
| xorl %eax, %eax # exit code = 0 |
| |
| #ifdef __DOS_16 |
| |
| movb $0x4c, %ah // EXIT - TERMINATE WITH RETURN CODE in AL |
| int $0x21 // call DOS |
| |
| #else |
| xchgl %eax, %ebx # move exit code in EAX to EBX |
| movl $1, %eax # sys_exit |
| int $0x80 |
| #endif |
| |
| ret |
| |
| 1: |
| //---------------------------------------------------------------------------- |
| /* backup mbr */ |
| |
| /* auto backup */ |
| cmpl $1, ABS(backup_mbr) |
| jnz 1f |
| |
| /* check if the second sector consists of 512 dups of one byte */ |
| movb ABS(mbr_63_sectors + 0x200), %al |
| movl $ABS(mbr_63_sectors + 0x200), %edi |
| movl $0x200, %ecx |
| |
| cld |
| repz scasb |
| |
| jz 1f # yes, enable backup |
| |
| movl $0, ABS(backup_mbr) # no, do not backup |
| |
| 1: |
| |
| //---------------------------------------------------------------------------- |
| cmpl $0, ABS(backup_mbr) |
| jz 1f # will not backup |
| |
| movl $ABS(mbr_63_sectors), %esi |
| movl $ABS(mbr_63_sectors + 0x200), %edi |
| movl $0x80, %ecx # 0x80 dwords = 0x200 bytes |
| |
| cld |
| repz movsl |
| |
| 1: |
| |
| //---------------------------------------------------------------------------- |
| /* copy byte 0000 to 01b7 of grldr.mbr to ABS(mbr_63_sectors) */ |
| |
| movl $ABS(_start1), %esi |
| movl $ABS(mbr_63_sectors), %edi |
| movl $0x6e, %ecx # 0x6e dwords = 0x1b8 bytes |
| |
| cld |
| repz movsl |
| |
| /* modify ABS(mbr_floppy) bit */ |
| |
| movb ABS(mbr_floppy), %al |
| andb $0x01, %al |
| movb %al, ABS(mbr_63_sectors + 2) |
| |
| /* modify ABS(mbr_osbr) bit */ |
| |
| movb ABS(mbr_osbr), %al |
| andb $0x01, %al |
| shlb $1, %al |
| orb %al, ABS(mbr_63_sectors + 2) |
| |
| /* modify ABS(duce) bit */ |
| |
| movb ABS(duce), %al |
| andb $0x01, %al |
| shlb $2, %al |
| orb %al, ABS(mbr_63_sectors + 2) |
| |
| /* modify ABS(boot_prevmbr) bit */ |
| |
| movb ABS(boot_prevmbr), %al |
| notb %al |
| andb $0x01, %al |
| rorb $1, %al |
| orb %al, ABS(mbr_63_sectors) + 2 |
| |
| /* modify ABS(time_out) byte */ |
| |
| movb ABS(time_out), %al |
| movb %al, ABS(mbr_63_sectors) + 3 |
| |
| /* modify ABS(hot_key) byte */ |
| |
| movw ABS(hot_key), %ax |
| movw %ax, ABS(mbr_63_sectors) + 4 |
| |
| /* modify ABS(preferred_drive) byte */ |
| |
| movb ABS(preferred_drive), %al |
| movb %al, ABS(mbr_63_sectors) + 6 |
| |
| /* modify ABS(preferred_partition) byte */ |
| |
| movb ABS(preferred_partition), %al |
| movb %al, ABS(mbr_63_sectors) + 7 |
| |
| /* copy byte 0400 and the rest of grldr.mbr to ABS(mbr_63_sectors) */ |
| |
| movl $ABS(_start1 + 0x400), %esi |
| movl $ABS(mbr_63_sectors + 0x400), %edi |
| movl $((pre_stage2_start - _start1 - 0x400) / 4), %ecx |
| |
| cld |
| repz movsl |
| |
| //---------------------------------------------------------------------------- |
| 2: /* label for the above floppy code to jump */ |
| |
| /* OK. Now write file! */ |
| |
| xorl %eax, %eax |
| |
| cmpw $2, ABS(read_only) |
| jne 3f |
| |
| pushl %ebx # file descriptor, or 0 if specified BIOS drive |
| |
| /* for safety, don't write too many sectors */ |
| cmpl $0xffffffff, ABS(install_partition) |
| jne 1f |
| cmpl $0xffffffff, ABS(floppy) |
| je 2f |
| 1: |
| cmpl $4, ABS(sectors_to_write) |
| jbe 1f |
| movl $4, ABS(sectors_to_write) |
| jmp 1f |
| 2: |
| cmpl $((pre_stage2_start - _start1) / 512), ABS(sectors_to_write) |
| jbe 1f |
| movl $((pre_stage2_start - _start1) / 512), ABS(sectors_to_write) |
| 1: |
| #ifdef __DOS_16 |
| |
| xorl %eax, %eax |
| cmpl $0xff, ABS(bios_drive_number) |
| je 1f |
| movb $0x03, %ah # write to disk |
| movb ABS(sectors_to_write), %al |
| // cmpl $0xffffffff, ABS(floppy) |
| // je 2f |
| // movb $4, %al # write 4 sectors if it is floppy |
| //2: |
| movw $ABS(mbr_63_sectors), %bx |
| movw $1, %cx |
| movw ABS(bios_drive_number), %dx |
| int $0x13 |
| jmp 2f |
| 1: |
| //WRITE TO FILE OR DEVICE |
| |
| //AH = 40h |
| //BX = file handle |
| //CX = number of bytes to write |
| //DS:DX -> data to write |
| |
| //Return: |
| //CF clear if successful AX = number of bytes actually written |
| //CF set on error AX = error code (05h,06h) |
| movl $0x4000, %eax |
| movl ABS(sectors_to_write), %ecx |
| shll $9, %ecx |
| //movl $(pre_stage2_start - _start1), %ecx |
| // cmpl $0xffffffff, ABS(floppy) |
| // je 1f |
| // movl $0x800, %ecx # write 4 sectors if it is floppy |
| //1: |
| movl $ABS(mbr_63_sectors), %edx |
| int $0x21 |
| 2: |
| jnc 1f |
| negl %eax |
| 1: |
| #else |
| /* ssize_t write(int fd, const void *buf, size_t count) */ |
| |
| movl $4, %eax # sys_write |
| movl $ABS(mbr_63_sectors), %ecx |
| movl ABS(sectors_to_write), %edx |
| shll $9, %edx |
| //movl $(pre_stage2_start - _start1), %edx # length of grldr.mbr |
| // cmpl $0xffffffff, ABS(floppy) |
| // je 1f |
| // movl $0x800, %edx # write 4 sectors if it is floppy |
| //1: |
| int $0x80 |
| #endif |
| |
| popl %ebx # file descriptor, or 0 if specified BIOS drive |
| 3: |
| cmpl $0xffffffff, ABS(install_partition) |
| je 3f |
| |
| /* for install_partition, SF=0 when success, SF=1 when failure */ |
| testl %eax, %eax |
| ret |
| 3: |
| testl %eax, %eax |
| movl $ABS(msg_write_file), %ecx |
| js 4f /* error */ |
| |
| //---------------------------------------------------------------------------- |
| cmpl $0xffffffff, ABS(floppy) |
| jne 3f |
| |
| movl $ABS(msg_geometry_S), %ecx |
| call 8f /* linux_print */ |
| |
| movl ABS(probed_sectors_per_track), %eax |
| call 6f /* print decimal number */ |
| |
| movl $ABS(msg_geometry_H), %ecx |
| call 8f /* linux_print */ |
| |
| movl ABS(probed_heads), %eax |
| call 6f /* print decimal number */ |
| |
| movl $ABS(msg_success), %ecx |
| call 8f /* linux_print */ |
| 3: |
| //success: |
| |
| # EBX=file descriptor, or 0 if specified BIOS drive |
| |
| xorl %eax, %eax # exit code = 0 |
| |
| jmp 1f |
| |
| //error: |
| 4: |
| # EBX=file descriptor, or 0 if specified BIOS drive |
| |
| testl %ecx, %ecx |
| jz 2f |
| call 8f /* linux_print */ |
| 2: |
| movl $ABS(msg_usage), %ecx |
| call 8f /* linux_print */ |
| |
| movl $1, %eax # exit code = 1 |
| |
| 1: |
| testl %ebx, %ebx |
| jz 1f |
| |
| pushl %eax # exit code |
| |
| #ifdef __DOS_16 |
| |
| movb $0x3e, %ah // close file (BX = file handle) |
| int $0x21 |
| jnc 2f |
| negl %eax /* EAX < 0 */ |
| 2: |
| #else |
| |
| /* int close(int fd); */ |
| movl $6, %eax # sys_close |
| int $0x80 |
| #endif |
| movl $ABS(msg_close_file), %ecx |
| testl %eax, %eax |
| |
| popl %eax # exit code |
| |
| jns 1f |
| |
| call 8f /* linux_print */ |
| |
| //exit: |
| 1: |
| #ifdef __DOS_16 |
| |
| movb $0x4c, %ah // EXIT - TERMINATE WITH RETURN CODE in AL |
| int $0x21 // call DOS |
| |
| #else |
| xchgl %eax, %ebx # move exit code in EAX to EBX |
| movl $1, %eax # sys_exit |
| int $0x80 |
| #endif |
| |
| ret |
| |
| //---------------------------------------------------------------------------- |
| //floppy: |
| 5: |
| |
| pushal |
| |
| /* First, try ext2 */ |
| |
| cmpw $0xEF53, 0x438(iSI) /* Magic signature */ |
| jnz 1f |
| xorl %eax, %eax |
| cmpl %eax, 0x400(iSI) /* s_inodes_count */ |
| jz 1f |
| cmpl %eax, 0x404(iSI) /* s_blocks_count */ |
| jz 1f |
| cmpw %ax, 0x458(iSI) /* s_inode_size, usually 0x80 */ |
| jz 1f |
| cmpl %eax, 0x420(iSI) /* s_blocks_per_group */ |
| jz 1f |
| cmpl %eax, 0x428(iSI) /* s_inodes_per_group */ |
| jz 1f |
| movl 0x414(iSI), %eax /* s_first_data_block */ |
| movw %ax, %bx /* BX=1 for 1K block, 0 otherwise */ |
| shrl $1, %eax /* must be 0 */ |
| jnz 1f |
| movl 0x418(iSI), %ecx /* s_log_block_size */ |
| cmpl $4, %ecx /* max size of block is 16K */ |
| ja 1f |
| negw %cx /* CF clear for 1K block, set otherwise */ |
| adcw %ax, %bx |
| decw %bx |
| jnz 1f |
| |
| /* BX = 0 */ |
| |
| /* super block is sane */ |
| |
| /* is EXT2 allowed write? */ |
| |
| testl $0x10, ABS(fstypes) |
| jnz 2f |
| /* EXT2 write not allowed */ |
| |
| movl $0, ABS(sectors_to_write) |
| |
| movl $ABS(msg_fstype_ext2_deny), %ecx |
| call 8f /* linux_print */ |
| |
| stc |
| popal |
| ret |
| 2: |
| /* write to ext2 boot area */ |
| |
| cld |
| movl $ABS(_start1 + 0x800), %esi /* points to the 5th sector */ |
| movl $ABS(mbr_63_sectors), %edi |
| lodsw /* The first 2 byte: short jmp */ |
| LEAL 0x400(%edi), %esi /* ESI points to super block */ |
| stosw |
| |
| /* lba indicator byte is not used. so we shouldn't touch it. */ |
| |
| /* check lba-chs-mode specified, 1 byte */ |
| cmpl $-1, ABS(lba) /* lba-chs-mode not specified? */ |
| je 2f /* yes, do nothing. */ |
| |
| #if 0 |
| movb $0x42, %al /* initialize to lba mode. */ |
| cmpl $0, ABS(lba) /* chs ? */ |
| jnz 10f /* no, it is not chs.*/ |
| movb $0x02, %al /* yes, it is chs. */ |
| 10: |
| #else |
| /* if specified lba or chs, we simply place a 0x90. */ |
| movb $0x90, %al |
| #endif |
| stosb |
| decl %edi |
| 2: |
| |
| addl $(1+10), %edi /* skip 10-byte OEM name */ |
| |
| /* Sectors per block, byte */ |
| |
| movb 0x18(iSI), %cl /* s_log_block_size */ |
| movl $2, %eax |
| shlw %cl, %ax |
| stosb |
| |
| /* Bytes per block, word */ |
| |
| shlw $9, %ax /* block size is word wide */ |
| stosw |
| |
| /* Pointers covered by an indirect block, dword */ |
| /* Pointers per block, dword */ |
| |
| shrw $2, %ax |
| pushl %eax /* Pointers per block */ |
| addb $8, %cl |
| shll %cl, %eax |
| stosl /* Pointers covered by an indirect block */ |
| popl %eax |
| stosl /* Pointers per block */ |
| |
| /* Sectors per track, word */ |
| |
| cmpl $0xFFFFFF3F, ABS(sectors_per_track) |
| je 10f |
| movb ABS(sectors_per_track), %al |
| cbw |
| stosw |
| subl $2, %edi |
| 10: |
| addl $2, %edi |
| |
| /* Number of heads, word */ |
| |
| cmpl $0xFFFF00FF, ABS(heads) |
| je 10f |
| movw ABS(heads), %ax |
| stosw |
| subl $2, %edi |
| 10: |
| addl $2, %edi |
| |
| /* hidden sectors(i.e., partition start), dword */ |
| |
| movb ABS(floppy), %al /* partition number(0xFF for floppy) */ |
| cmpb $0xff, %al |
| jne 10f |
| /* real floppy */ |
| cmpl $0xffffffff, ABS(start_sector) |
| sete %al |
| movzbl %al, %eax |
| addl ABS(start_sector), %eax |
| stosl |
| jmp 11f |
| 10: |
| /* hard drive partition */ |
| addl $4, %edi |
| cmpl $0xffffffff, ABS(start_sector) |
| je 11f |
| movl ABS(start_sector), %eax |
| subl $4, %edi |
| stosl |
| 11: |
| |
| /* total sectors, dword */ |
| |
| movl %es:(iDI), %eax |
| cmpl %eax, ABS(total_sectors) |
| jbe 10f |
| movl ABS(total_sectors), %eax |
| 10: |
| stosl |
| |
| /* drive number, byte */ |
| |
| //this byte is not used. |
| incl %edi |
| |
| /* partition number, byte */ |
| |
| movb ABS(floppy), %al |
| stosb |
| |
| /* reserved, word */ |
| |
| incl %edi |
| incl %edi |
| |
| /* Number of inodes per group, dword */ |
| |
| movl 0x28(iSI), %eax /* s_inodes_per_group */ |
| stosl |
| |
| /* block number for group descriptors, dword */ |
| |
| movl 0x14(iSI), %eax /* s_first_data_block */ |
| incw %ax |
| stosl |
| |
| /* Machine code begins at offset 0x30, 462 bytes plus |
| * 2 bytes of boot signature */ |
| |
| movl $ABS(_start1 + 0x830), %esi |
| lodsl |
| movb ABS(floppy), %cl /* partition number(0xFF for floppy) */ |
| cmpb $0xff, %cl |
| jne 10f |
| /* real floppy */ |
| cmpl $0x90C031FC, %eax /* FC=cld; 31 C0=xor ax,ax; 90=nop */ |
| jne 10f |
| movl $0x99C031FC, %eax /* FC=cld; 31 C0=xor ax,ax; 99=cwd */ |
| 10: |
| stosl |
| |
| movl $((464 / 4) - 1), %ecx |
| repz movsl |
| |
| movl $1, ABS(sectors_to_write) |
| |
| movl $ABS(msg_fstype_ext2_allow), %ecx |
| call 8f /* linux_print */ |
| |
| clc |
| popal |
| ret |
| |
| 1: |
| /* Secondly, try FAT12/16/32/NTFS */ |
| |
| cld |
| cmpw $0xAA55, 0x1fe(iSI) /* boot signature */ |
| jne 1f /* not a normal BPB */ |
| cmpw $0x200, 0x0b(iSI) /* bytes per sector */ |
| jne 1f /* not a normal BPB */ |
| movb 0x0d(iSI), %al /* sectors per cluster */ |
| testb %al, %al |
| jz 1f /* invalid if = 0 */ |
| movb %al, %cl |
| movw $128, %ax |
| divb %cl /* quo=AL, rem=AH */ |
| testb %ah, %ah |
| jnz 1f /* invalid if not 2^n */ |
| movw 0x18(iSI), %ax /* sectors per track */ |
| testw %ax, %ax |
| jz 1f /* invalid if = 0 */ |
| cmpw $63, %ax |
| ja 1f /* invalid if > 63 */ |
| movw 0x1a(iSI), %ax /* number of heads */ |
| decw %ax /* Max head number, should be a byte */ |
| testb %ah, %ah /* should be 0 */ |
| jnz 1f /* invalid if number of heads > 256 */ |
| cmpb $0xf0, 0x15(iSI) /* media descriptor */ |
| jb 1f |
| |
| // movw $0x0600, %bx /* FAT12/FAT16 */ |
| // movw $0x003c, %cx /* FAT12/FAT16 */ |
| |
| movb 0x10(iSI), %al /* number of FATs(NTFS:0, FAT:1,2) */ |
| cmpb $2, %al |
| ja 1f /* abnormal FAT */ |
| movw 0x11(iSI), %ax /* max root entries */ |
| testw %ax, %ax |
| jnz 2f /* FAT12/FAT16 */ |
| |
| /* FAT32 or NTFS */ |
| movw 0x13(iSI), %ax /* total sectors(small) */ |
| testw %ax, %ax |
| jnz 1f /* invalid FAT32 BPB */ |
| movw 0x16(iSI), %ax /* sectors per FAT(small) */ |
| testw %ax, %ax |
| jnz 1f /* invalid FAT32 BPB */ |
| movb 0x10(iSI), %al /* number of FATs(NTFS:0, FAT:1,2) */ |
| testb %al, %al |
| jz 4f /* NTFS */ |
| |
| /* FAT32 */ |
| movl 0x20(iSI), %eax /* FAT32 total sectors */ |
| testl %eax, %eax |
| jz 1f |
| movl 0x24(iSI), %eax /* FAT32 sectors per FAT */ |
| testl %eax, %eax |
| jz 1f |
| /* sure it is FAT32 */ |
| |
| /* is FAT32 allowed write? */ |
| |
| testl $0x04, ABS(fstypes) |
| jnz 3f |
| /* FAT32 write not allowed */ |
| movl $0, ABS(sectors_to_write) |
| |
| movl $ABS(msg_fstype_fat32_deny), %ecx |
| call 8f /* linux_print */ |
| |
| stc |
| popal |
| ret |
| 3: |
| /* write to FAT32 boot area */ |
| |
| cld |
| movl $ABS(_start1 + 0x400), %esi /* points to the 3rd sector */ |
| movl $ABS(mbr_63_sectors), %edi |
| lodsw /* The first 2 byte: short jmp */ |
| //leal 0x400(%edi), %esi /* ESI points to super block */ |
| stosw |
| |
| /* check lba-chs-mode specified, 1 byte */ |
| cmpl $-1, ABS(lba) /* lba-chs-mode not specified? */ |
| je 3f /* yes, do nothing. */ |
| movb $0x0e, %al /* initialize to lba mode. */ |
| cmpl $0, ABS(lba) /* chs ? */ |
| jnz 10f /* no, it is not chs.*/ |
| movb $0x90, %al /* yes, it is chs. */ |
| 10: |
| stosb |
| decl %edi |
| 3: |
| addl $(1+8+2+1+2+1+2+2+1+2), %edi |
| addl $(1+8+2+1+2+1+2+2+1+2), %esi |
| /* skip 8-byte OEM name and Bytes per sector */ |
| |
| /* and Sectors per cluster, byte */ |
| /* and Reserved sectors, word */ |
| /* and Number of FATs, byte */ |
| /* (Max root dir entries)Must be 0, word */ |
| /* (Total sectors small)Must be 0, word */ |
| /* Media descriptor, byte */ |
| /* (Sectors per FAT)Must be 0, word */ |
| /* sectors per track, word */ |
| lodsw |
| addl $2, %edi |
| cmpl $0xffffff3f, ABS(sectors_per_track) |
| je 3f |
| movb ABS(sectors_per_track), %al |
| cbw |
| subl $2, %edi |
| stosw |
| 3: |
| |
| /* number of heads, word */ |
| lodsw |
| addl $2, %edi |
| cmpl $0xffff00ff, ABS(heads) |
| je 3f |
| movw ABS(heads), %ax |
| subl $2, %edi |
| stosw |
| 3: |
| |
| /* hidden sectors(i.e., partition start), dword */ |
| lodsl |
| addl $4, %edi |
| cmpl $0xffffffff, ABS(start_sector) |
| je 3f |
| movl ABS(start_sector), %eax |
| subl $4, %edi |
| stosl |
| 3: |
| |
| /* total sectors, dword */ |
| lodsl |
| addl $4, %edi |
| cmpl $0, ABS(total_sectors) |
| je 3f |
| movl ABS(total_sectors), %eax |
| subl $4, %edi |
| stosl |
| 3: |
| |
| /* FAT32 sectors per FAT, dword, etc... */ |
| |
| addl $(4+2+2+4+2+2+12+1+1+1+4+11+8), %esi |
| addl $(4+2+2+4+2+2+12+1+1+1+4+11+8), %edi |
| |
| //movl $0xFFB6FCFA, %eax /* CLI, CLD, MOV DH,FF */ |
| lodsw |
| stosw |
| lodsb |
| stosb |
| lodsb |
| |
| //decl %edi |
| |
| /* partition number, byte */ |
| |
| movb ABS(floppy), %al |
| stosb |
| |
| /* Machine code begins at offset 0x5e, 416 bytes without |
| * the ending 2 bytes of boot signature */ |
| |
| //movl $ABS(_start1 + 0x45e), %esi |
| movl $(416 / 4), %ecx |
| repz movsl |
| |
| movl $1, ABS(sectors_to_write) |
| |
| movl $ABS(msg_fstype_fat32_allow), %ecx |
| call 8f /* linux_print */ |
| |
| clc |
| popal |
| ret |
| 4: |
| /* NTFS */ |
| movl 0x20(iSI), %eax /* FAT32 total sectors */ |
| testl %eax, %eax |
| jnz 1f |
| //movw 0x11(%si), %ax /* max root entries */ |
| //testw %ax, %ax |
| //jnz 1f |
| movw 0x0e(iSI), %ax /* reserved sectors */ |
| testw %ax, %ax |
| jnz 1f |
| /* sure it is NTFS */ |
| |
| /* is NTFS allowed write? */ |
| |
| testl $0x08, ABS(fstypes) |
| jnz 3f |
| /* NTFS write not allowed */ |
| movl $0, ABS(sectors_to_write) |
| |
| movl $ABS(msg_fstype_ntfs_deny), %ecx |
| call 8f /* linux_print */ |
| |
| stc |
| popal |
| ret |
| 3: |
| #if 1 |
| /* write to NTFS boot area */ |
| |
| cld |
| movl $ABS(_start1 + 0xA00), %esi /* points to the 6th sector */ |
| movl $ABS(mbr_63_sectors), %edi |
| lodsw /* The first 2 byte: short jmp */ |
| stosw |
| |
| /* check lba-chs-mode specified, 1 byte */ |
| cmpl $-1, ABS(lba) /* lba-chs-mode not specified? */ |
| je 3f /* yes, do nothing. */ |
| movb $0x0e, %al /* initialize to lba mode. */ |
| cmpl $0, ABS(lba) /* chs ? */ |
| jnz 10f /* no, it is not chs.*/ |
| movb $0x90, %al /* yes, it is chs. */ |
| 10: |
| stosb |
| decl %edi |
| 3: |
| addl $(1+8+2+1+2+1+2+2+1+2), %edi |
| addl $(1+8+2+1+2+1+2+2+1+2), %esi |
| /* skip 8-byte OEM name and Bytes per sector */ |
| |
| /* and Sectors per cluster, byte */ |
| /* and Reserved sectors, word */ |
| /* and Number of FATs, byte */ |
| /* (Max root dir entries)Must be 0, word */ |
| /* (Total sectors small)Must be 0, word */ |
| /* Media descriptor, byte */ |
| /* (Sectors per FAT)Must be 0, word */ |
| /* sectors per track, word */ |
| lodsw |
| addl $2, %edi |
| cmpl $0xffffff3f, ABS(sectors_per_track) |
| je 3f |
| movb ABS(sectors_per_track), %al |
| cbw |
| subl $2, %edi |
| stosw |
| 3: |
| |
| /* number of heads, word */ |
| lodsw |
| addl $2, %edi |
| cmpl $0xffff00ff, ABS(heads) |
| je 3f |
| movw ABS(heads), %ax |
| subl $2, %edi |
| stosw |
| 3: |
| |
| /* hidden sectors(i.e., partition start), dword */ |
| lodsl |
| addl $4, %edi |
| cmpl $0xffffffff, ABS(start_sector) |
| je 3f |
| movl ABS(start_sector), %eax |
| subl $4, %edi |
| stosl |
| 3: |
| |
| |
| addl $(4+1+1+1+1+8), %esi |
| addl $(4+1+1+1+1+8), %edi |
| /* total sectors, unused, dword */ |
| /* drive number, byte, and another 3 bytes; Usually 80 00 80 00 */ |
| /* Number of sectors in the volume, qword */ |
| //lodsl |
| //lodsl |
| //addl $8, %edi |
| cmpl $0, ABS(total_sectors) |
| je 3f |
| movl ABS(total_sectors), %eax |
| subl $8, %edi |
| stosl |
| xorl %eax, %eax /* high 32 bits */ |
| stosl |
| 3: |
| |
| addl $(8+8+4+4+8+4), %esi |
| addl $(8+8+4+4+8+4), %edi |
| /* 30 - LCN of VCN 0 of the $MFT, qword */ |
| /* 38 - LCN of VCN 0 of the $MFTMirr, qword */ |
| /* 40 - Clusters per MFT Record, dword */ |
| /* 44 - Clusters per Index Record, dword */ |
| /* 48 - Volume serial number, qword */ |
| /* 50 - Checksum, usually 0, dword */ |
| //movl $0xFFB6FCFA, %eax /* CLI, CLD, MOV DH,FF */ |
| lodsw |
| stosw |
| lodsb |
| stosb |
| lodsb |
| |
| //decl %edi |
| |
| /* partition number, byte */ |
| |
| movb ABS(floppy), %al |
| stosb |
| |
| /* Machine code begins at offset 0x58, ending at 0x7FF, where |
| * we assume that NTFS boot record takes up 4 sectors. */ |
| |
| movl $((0x800 - 0x58)/ 4), %ecx |
| repz movsl |
| |
| movl $4, ABS(sectors_to_write) |
| |
| movl $ABS(msg_fstype_ntfs_allow), %ecx |
| call 8f /* linux_print */ |
| |
| clc |
| popal |
| ret |
| #else |
| /* write to NTFS boot area */ |
| |
| movl $ABS(mbr_63_sectors), %edi |
| LEAL 0x400(%edi), %esi /* ESI points to super block */ |
| |
| /* hidden sectors(i.e., partition start), dword */ |
| cmpl $0xffffffff, ABS(start_sector) |
| je 3f |
| movl ABS(start_sector), %eax |
| movl %eax, 0x1c(iDI) |
| 3: |
| |
| /* drive number needn't touch */ |
| |
| /* partition number */ |
| |
| call 4f |
| jc 5f |
| movl 0x06(iSI), %eax /* NT 4 */ |
| cmpl $0x03E8B800, %eax /* MOV ES,AX */ |
| jnz 3f |
| |
| cmpl $0x680007E8, 0x84(iDI) /* call 008e; push (0D00) */ |
| jnz 3f |
| movb $0xB6, %al /* 0xB6="MOV DH,imm8" */ |
| movb ABS(floppy), %ah /* partition number */ |
| movw %ax, 0x0a(iSI) |
| |
| movl $4, ABS(sectors_to_write) |
| |
| movl $ABS(msg_fstype_ntfs_allow), %ecx |
| call 8f /* linux_print */ |
| |
| clc |
| popal |
| ret |
| 3: |
| /* NT 5.0 */ |
| |
| cmpl $0x680053E8, 0x71(iDI) /* call 00C7; push (0D00) */ |
| jnz 5f |
| |
| movl $0x4b, %ebx |
| movl (iBX, iSI), %eax /* NT 5 */ |
| cmpl $0x03E8B800, %eax /* MOV ES,AX */ |
| jz 3f |
| |
| movl $0x79, %ebx |
| movl (iBX, iSI), %eax /* NT 5p */ |
| cmpl $0x03E8B800, %eax /* MOV ES,AX */ |
| jnz 5f |
| 3: |
| movb $0xB6, %al /* 0xB6="MOV DH,imm8" */ |
| movb ABS(floppy), %ah /* partition number */ |
| movw %ax, 4(iBX, iSI) |
| |
| movl $4, ABS(sectors_to_write) |
| |
| movl $ABS(msg_fstype_ntfs_allow), %ecx |
| call 8f /* linux_print */ |
| |
| clc |
| popal |
| ret |
| 5: |
| /* No NTFS boot record present */ |
| movl $0, ABS(sectors_to_write) |
| |
| movl $ABS(msg_no_ntfs_boot_record), %ecx |
| call 8f /* linux_print */ |
| |
| stc |
| popal |
| ret |
| |
| 4: /* change NT to GR */ |
| |
| pushal |
| cld |
| movl $0x00520047, 0x202(iDI) /* G R L D R */ |
| addl $0x0100, %edi |
| movl $0x00fa, %ecx |
| movw $0x014e, %ax /* AL="N", AH=Carry for SAHF below */ |
| movl $0x52444c54, %ebx /* "TLDR" */ |
| |
| 3: |
| repnz scasb /* find "N" */ |
| jcxz 4f /* gets the end, exit */ |
| cmpl %ebx, (iDI) /* is it "NTLDR"? */ |
| jnz 3b /* no, continue to find */ |
| |
| /* "NTLDR" is found, so we believe it is NT boot sector. */ |
| |
| movw $0x5247, -1(iDI) /* change "NT" to "GR" */ |
| |
| /* CF=0 for now */ |
| |
| lahf /* Load Flags into AH */ |
| /* AH = SF:ZF:xx:AF:xx:PF:xx:CF */ |
| /* AH = binary xxxxxxx0 */ |
| jmp 3b |
| 4: |
| sahf /* Store AH into flags SF ZF xx AF xx PF xx CF */ |
| |
| /* CF=0 means "NTLDR" is found, CF=1 means "NTLDR" is not found. */ |
| |
| popal |
| ret |
| #endif |
| |
| 2: |
| /* FAT12/FAT16 */ |
| movb 0x10(iSI), %al /* number of FATs(NTFS:0, FAT:1,2) */ |
| testb %al, %al |
| jz 1f |
| movw 0x16(iSI), %ax /* sectors per FAT(small) */ |
| testw %ax, %ax |
| jz 1f |
| // movw $(FAT16_message - _start1), %si |
| cmpw $12, %ax |
| ja 4f /* FAT16 */ |
| /* sure it is FAT12 */ |
| |
| /* is FAT12 allowed write? */ |
| |
| testl $0x01, ABS(fstypes) |
| jnz 2f |
| /* FAT12 write not allowed */ |
| movl $0, ABS(sectors_to_write) |
| |
| movl $ABS(msg_fstype_fat12_deny), %ecx |
| call 8f /* linux_print */ |
| |
| stc |
| popal |
| ret |
| 2: |
| /* write to FAT12 boot area */ |
| |
| cld |
| movl $ABS(_start1 + 0x600), %esi /* points to the 4th sector */ |
| movl $ABS(mbr_63_sectors), %edi |
| lodsw /* The first 2 byte: short jmp */ |
| //leal 0x400(%edi), %esi /* ESI points to super block */ |
| stosw |
| |
| /* check lba-chs-mode specified, 1 byte */ |
| cmpl $-1, ABS(lba) /* lba-chs-mode not specified? */ |
| je 2f /* yes, do nothing. */ |
| movb $0x0e, %al /* initialize to lba mode. */ |
| cmpl $0, ABS(lba) /* chs ? */ |
| jnz 10f /* no, it is not chs.*/ |
| movb $0x90, %al /* yes, it is chs. */ |
| 10: |
| stosb |
| decl %edi |
| 2: |
| addl $(1+8+2+1+2+1+2+2+1+2), %edi |
| addl $(1+8+2+1+2+1+2+2+1+2), %esi |
| /* skip 8-byte OEM name and Bytes per sector */ |
| |
| /* and Sectors per cluster, byte */ |
| /* and Reserved sectors, word */ |
| /* and Number of FATs, byte */ |
| /* (Max root dir entries)Must be 0, word */ |
| /* (Total sectors small)Must be 0, word */ |
| /* Media descriptor, byte */ |
| /* (Sectors per FAT)Must be 0, word */ |
| /* sectors per track, word */ |
| lodsw |
| addl $2, %edi |
| cmpl $0xffffff3f, ABS(sectors_per_track) |
| je 2f |
| movb ABS(sectors_per_track), %al |
| cbw |
| subl $2, %edi |
| stosw |
| 2: |
| |
| /* number of heads, word */ |
| lodsw |
| addl $2, %edi |
| cmpl $0xffff00ff, ABS(heads) |
| je 2f |
| movw ABS(heads), %ax |
| subl $2, %edi |
| stosw |
| 2: |
| |
| /* hidden sectors(i.e., partition start), dword */ |
| lodsl |
| addl $4, %edi |
| cmpl $0xffffffff, ABS(start_sector) |
| je 2f |
| movl ABS(start_sector), %eax |
| subl $4, %edi |
| stosl |
| 2: |
| |
| /* total sectors, dword */ |
| lodsl |
| addl $4, %edi |
| cmpl $0, ABS(total_sectors) |
| je 2f |
| movl ABS(total_sectors), %eax |
| subl $4, %edi |
| stosl |
| 2: |
| |
| /* drive number, byte, etc... */ |
| |
| addl $(1+1+1+4+11+8), %esi |
| addl $(1+1+1+4+11+8), %edi |
| |
| //movl $0xFFB6FCFA, %eax /* CLI, CLD, MOV DH,FF */ |
| lodsw |
| stosw |
| lodsb |
| stosb |
| lodsb |
| |
| //decl %edi |
| |
| /* partition number, byte */ |
| |
| movb ABS(floppy), %al |
| stosb |
| |
| /* Machine code begins at offset 0x42, 444 bytes without |
| * the ending 2 bytes of boot signature */ |
| |
| //movl $ABS(_start1 + 0x642), %esi |
| movl $(444 / 4), %ecx |
| repz movsl |
| |
| movl $1, ABS(sectors_to_write) |
| |
| movl $ABS(msg_fstype_fat12_allow), %ecx |
| call 8f /* linux_print */ |
| |
| clc |
| popal |
| ret |
| |
| 4: |
| |
| /* sure it is FAT16 */ |
| |
| /* is FAT16 allowed write? */ |
| |
| testl $0x02, ABS(fstypes) |
| jnz 2f |
| /* FAT16 write not allowed */ |
| movl $0, ABS(sectors_to_write) |
| |
| movl $ABS(msg_fstype_fat16_deny), %ecx |
| call 8f /* linux_print */ |
| |
| stc |
| popal |
| ret |
| 2: |
| /* write to FAT16 boot area */ |
| |
| cld |
| movl $ABS(_start1 + 0x600), %esi /* points to the 4th sector */ |
| movl $ABS(mbr_63_sectors), %edi |
| lodsw /* The first 2 byte: short jmp */ |
| //leal 0x400(%edi), %esi /* ESI points to super block */ |
| stosw |
| |
| /* check lba-chs-mode specified, 1 byte */ |
| cmpl $-1, ABS(lba) /* lba-chs-mode not specified? */ |
| je 2f /* yes, do nothing. */ |
| movb $0x0e, %al /* initialize to lba mode. */ |
| cmpl $0, ABS(lba) /* chs ? */ |
| jnz 10f /* no, it is not chs.*/ |
| movb $0x90, %al /* yes, it is chs. */ |
| 10: |
| stosb |
| decl %edi |
| 2: |
| addl $(1+8+2+1+2+1+2+2+1+2), %edi |
| addl $(1+8+2+1+2+1+2+2+1+2), %esi |
| /* skip 8-byte OEM name and Bytes per sector */ |
| |
| /* and Sectors per cluster, byte */ |
| /* and Reserved sectors, word */ |
| /* and Number of FATs, byte */ |
| /* (Max root dir entries)Must be 0, word */ |
| /* (Total sectors small)Must be 0, word */ |
| /* Media descriptor, byte */ |
| /* (Sectors per FAT)Must be 0, word */ |
| /* sectors per track, word */ |
| lodsw |
| addl $2, %edi |
| cmpl $0xffffff3f, ABS(sectors_per_track) |
| je 2f |
| movb ABS(sectors_per_track), %al |
| cbw |
| subl $2, %edi |
| stosw |
| 2: |
| |
| /* number of heads, word */ |
| lodsw |
| addl $2, %edi |
| cmpl $0xffff00ff, ABS(heads) |
| je 2f |
| movw ABS(heads), %ax |
| subl $2, %edi |
| stosw |
| 2: |
| |
| /* hidden sectors(i.e., partition start), dword */ |
| lodsl |
| addl $4, %edi |
| cmpl $0xffffffff, ABS(start_sector) |
| je 2f |
| movl ABS(start_sector), %eax |
| subl $4, %edi |
| stosl |
| 2: |
| |
| /* total sectors, dword */ |
| lodsl |
| addl $4, %edi |
| cmpl $0, ABS(total_sectors) |
| je 2f |
| movl ABS(total_sectors), %eax |
| subl $4, %edi |
| stosl |
| 2: |
| |
| /* drive number, byte, etc... */ |
| |
| addl $(1+1+1+4+11+8), %esi |
| addl $(1+1+1+4+11+8), %edi |
| |
| //movl $0xFFB6FCFA, %eax /* CLI, CLD, MOV DH,FF */ |
| lodsw |
| stosw |
| lodsb |
| stosb |
| lodsb |
| |
| //decl %edi |
| |
| /* partition number, byte */ |
| |
| movb ABS(floppy), %al |
| stosb |
| |
| /* Machine code begins at offset 0x42, 444 bytes without |
| * the ending 2 bytes of boot signature */ |
| |
| //movl $ABS(_start1 + 0x642), %esi |
| movl $(444 / 4), %ecx |
| repz movsl |
| |
| movl $1, ABS(sectors_to_write) |
| |
| movl $ABS(msg_fstype_fat16_allow), %ecx |
| call 8f /* linux_print */ |
| |
| clc |
| popal |
| ret |
| 1: |
| |
| movl $0, ABS(sectors_to_write) |
| |
| movl $ABS(msg_unsupported_fstype), %ecx |
| call 8f /* linux_print */ |
| |
| stc |
| popal |
| ret |
| |
| //---------------------------------------------------------------------------- |
| //print decimal number in EAX |
| 6: |
| /* print EAX value in decimal format */ |
| pushal |
| |
| #if 0 |
| cld |
| movl $ABS(number_digits), %edi |
| xchgl %eax, %edx // save EAX to EDX |
| movw $0x2020, %ax // two spaces |
| stosw |
| stosw |
| stosw |
| stosw |
| stosw |
| decl %edi // EDI points to the last digit |
| xchgl %eax, %edx // restore EAX from EDX |
| #endif |
| std |
| movl $ABS(number_digits + 9), %edi |
| movl $10, %ebp |
| 1: |
| xorl %edx, %edx |
| divl %ebp // quo=EAX, rem=EDX |
| xchgl %eax, %edx |
| orb $0x30, %al |
| stosb |
| xchgl %eax, %edx |
| testl %eax, %eax |
| jnz 1b |
| |
| /* all digits are stored */ |
| incl %edi // points to the digit string |
| |
| movl %edi, %ecx |
| call 8f /* linux_print */ |
| |
| cld |
| popal |
| ret |
| |
| //---------------------------------------------------------------------------- |
| //parse_number: |
| 7: |
| |
| /* input: EDI points to the number |
| * EBX upper limit of the number |
| * output: EBX the value of the number |
| * EDX changed |
| * ESI changed |
| * EBP changed |
| * CF=1 failure |
| * CF=0 success |
| */ |
| |
| pushl %eax |
| pushl %ebx /* upper limit */ |
| cld |
| movl %edi, %esi |
| movl $0xffffffff, %edx |
| xorl %ebx, %ebx |
| lodsw |
| cmpw $0x5830, %ax /* 0X */ |
| je 1f |
| cmpw $0x7830, %ax /* 0x */ |
| je 1f |
| |
| /* decimal */ |
| decl %esi |
| decl %esi |
| movl $10, %ebp |
| 2: |
| xorl %eax, %eax |
| lodsb |
| cmpb $0, %al |
| je 4f /* CF=0 */ |
| cmpb $0x30, %al |
| jb 3f |
| cmpb $0x39, %al |
| ja 3f |
| subb $0x30, %al |
| pushl %eax |
| movl %ebx, %eax |
| mull %ebp |
| movl %eax, %ebx |
| popl %eax |
| jc 3f |
| addl %eax, %ebx |
| jc 3f |
| popl %eax |
| pushl %eax /* upper limit */ |
| cmpl %eax, %ebx |
| ja 3f |
| jmp 2b |
| 1: |
| |
| /* hex */ |
| movl $16, %ebp |
| 2: |
| xorl %eax, %eax |
| lodsb |
| cmpb $0, %al |
| je 4f /* CF=0 */ |
| cmpb $0x30, %al |
| jb 3f |
| cmpb $0x39, %al |
| jbe 1f |
| orb $0x20, %al |
| cmpb $0x61, %al |
| jb 3f |
| cmpb $0x66, %al |
| ja 3f |
| subb $0x27, %al |
| 1: |
| subb $0x30, %al |
| pushl %eax |
| movl %ebx, %eax |
| mull %ebp |
| movl %eax, %ebx |
| popl %eax |
| jc 3f |
| addl %eax, %ebx |
| jc 3f |
| popl %eax |
| pushl %eax /* upper limit */ |
| cmpl %eax, %ebx |
| ja 3f |
| jmp 2b |
| |
| 3: |
| stc |
| popl %eax /* upper limit */ |
| popl %eax |
| ret |
| 4: |
| testl %edx, %edx /* CF=0 */ |
| jnz 3b |
| popl %eax /* upper limit */ |
| popl %eax |
| ret |
| |
| //---------------------------------------------------------------------------- |
| //linux_print: |
| 8: |
| |
| /* print a message. |
| * input: ECX points to message string |
| * output: message is displayed on the stdout device |
| */ |
| |
| /* ssize_t write(int fd, const void *buf, size_t count) */ |
| |
| pushal |
| |
| #ifdef __DOS_16 |
| |
| cld |
| movl %ecx, %esi |
| // movw %si, %dx |
| // movb $0x09, %ah // WRITE STRING TO STANDARD OUTPUT |
| // int $0x21 // call DOS |
| // ret |
| |
| 1: |
| lodsb (%si), %al // get token |
| cmpb $0, %al // end of string? |
| je 1f |
| #if 0 |
| /* use BIOS independent of DOS */ |
| xorw %bx, %bx // video page 0 |
| movb $0x0e, %ah // print it |
| int $0x10 // via TTY mode |
| #else |
| /* use stdout for redirection of the output */ |
| movb %al, %dl // character to write |
| movb $0x02, %ah // WRITE CHARACTER TO STANDARD OUTPUT |
| int $0x21 // call DOS |
| #endif |
| jmp 1b // until done |
| 1: |
| |
| #else |
| pushl %ecx |
| movl %ecx, %edi # scan the message string ... |
| movl $(msg_end - msg_start), %ecx |
| movb $0, %al # ... find the ending zero byte |
| |
| cld |
| repnz scasb |
| |
| movl %edi, %edx |
| popl %ecx # ECX points to the message |
| subl %ecx, %edx # EDX=message length |
| decl %edx # discard the ending zero byte |
| |
| movl $4, %eax # sys_write |
| movl $1, %ebx # file descriptor = stdout |
| int $0x80 |
| #endif |
| |
| popal |
| ret |
| |
| //---------------------------------------------------------------------------- |
| //probe_geometry: |
| 9: |
| pushal |
| |
| addl $0x200, %esi |
| |
| movw $0, ABS(Cmax) |
| movl $0, ABS(Hmax) |
| movw $0, ABS(Smax) |
| |
| movl $0, ABS(i) # partition number |
| 1: |
| cmpl $4, ABS(i) |
| jae 1f |
| |
| /* the boot indicator must be 0x80(bootable) or 0(non-bootable) */ |
| |
| movl ABS(i), %ebx |
| movl ABS(i), %edi |
| shll $4, %ebx # EBX = ABS(i) * 16 |
| movb -66(iBX, iSI), %al # boot_indicator |
| shlb $1, %al |
| jnz 6f /* geometry_probe_failed */ |
| |
| /* check if the entry is empty, ABS(i).e., all the 16 bytes are 0 */ |
| |
| movl -66(iBX, iSI), %eax |
| orl -62(iBX, iSI), %eax |
| orl -58(iBX, iSI), %eax |
| orl -54(iBX, iSI), %eax |
| jz 2f # empty partition entry |
| |
| /* valid partitions never start at 0, because this is where the MBR |
| * lives; and more, the number of total sectors should be non-zero. |
| */ |
| |
| cmpl $0, -58(iBX, iSI) # start_lba |
| jz 6f /* geometry_probe_failed */ |
| |
| cmpl $0, -54(iBX, iSI) # total_sectors |
| jz 6f /* geometry_probe_failed */ |
| |
| /* the partitions should not overlap each other */ |
| |
| movl $0, ABS(j) |
| 3: |
| cmpl %edi, ABS(j) # i = EDI |
| jae 3f |
| |
| movl -58(iBX, iSI), %ecx # start_lba |
| |
| movl ABS(j), %edx |
| shll $4, %edx # EDX = ABS(j) * 16 |
| MOVL -58(%edx, %esi), %eax # start_lba |
| |
| cmpl %ecx, %eax |
| jae 4f |
| subl %eax, %ecx |
| CMPL -54(%edx, %esi), %ecx # total_sectors |
| jmp 5f |
| 4: |
| subl %ecx, %eax |
| cmpl -54(iBX, iSI), %eax # total_sectors |
| 5: |
| jb 6f /* geometry_probe_failed */ |
| |
| incl ABS(j) |
| jmp 3b |
| 3: |
| |
| /* the start cylinder number */ |
| |
| movzwl -64(iBX, iSI), %eax # start_sector_cylinder |
| |
| movl %eax, %edx |
| andw $0x003f, %dx |
| jz 6f /* geometry_probe_failed */ |
| |
| movw %dx, ABS(X) # the sector number |
| |
| cmpw %dx, ABS(Smax) |
| jae 3f |
| movw %dx, ABS(Smax) |
| 3: |
| movl -58(iBX, iSI), %ecx # start_lba |
| incl %ecx |
| subl %edx, %ecx |
| |
| movl $ABS(L), %edx |
| MOVL %ecx, (%edx, %edi, 8) # L[i] |
| |
| ///* partitions should not start at the first track, the MBR-track */ |
| //movw ABS(Smax), %dx |
| //cmpw %dx, -58(%ebx, %esi) # start_lba |
| //jb 6f /* geometry_probe_failed */ |
| |
| shrb $6, %al |
| xchgb %al, %ah |
| |
| movl $ABS(C), %edx |
| MOVW %ax, (%edx, %edi, 4) # C[i] |
| |
| cmpw %ax, ABS(Cmax) |
| jae 3f |
| movw %ax, ABS(Cmax) |
| 3: |
| |
| //movl ABS(i), %ebx |
| //shll $4, %ebx # EBX = ABS(i) * 16 |
| movzbl -65(iBX, iSI), %eax # start_head |
| movl $ABS(H), %edx |
| MOVL %eax, (%edx, %edi, 4) # H[i] |
| |
| cmpl %eax, ABS(Hmax) |
| jae 3f |
| movl %eax, ABS(Hmax) |
| 3: |
| |
| /* the end cylinder number */ |
| |
| movzwl -60(iBX, iSI), %eax # end_sector_cylinder |
| |
| movl %eax, %edx |
| andw $0x003f, %dx |
| jz 6f /* geometry_probe_failed */ |
| |
| movw %dx, ABS(Y) # the sector number |
| |
| cmpw %dx, ABS(Smax) |
| jae 3f |
| movw %dx, ABS(Smax) |
| 3: |
| movl -58(iBX, iSI), %ecx # start_lba |
| addl -54(iBX, iSI), %ecx # total_sectors |
| # XXX: possible overflow! |
| |
| subl %edx, %ecx |
| jb 6f /* geometry_probe_failed */ |
| |
| addl $4, %edi # EDI=i+4 |
| |
| movl $ABS(L), %edx |
| MOVL %ecx, (%edx, %edi, 8) # L[i+4] |
| |
| movl %ecx, %ebp # save ECX to EBP |
| |
| /* partitions should not start at the first track, the MBR-track */ |
| movw ABS(Smax), %dx |
| cmpw %dx, -58(iBX, iSI) # start_lba |
| jb 6f /* geometry_probe_failed */ |
| |
| shrb $6, %al |
| xchgb %al, %ah |
| |
| movl $ABS(C), %edx |
| MOVW %ax, (%edx, %edi, 4) # C[i+4] |
| |
| cmpw %ax, ABS(Cmax) |
| jae 3f |
| movw %ax, ABS(Cmax) |
| 3: |
| xchgl %eax, %ecx # save AX to CX |
| |
| //movl ABS(i), %ebx |
| //shll $4, %ebx # EBX = ABS(i) * 16 |
| movzbl -61(iBX, iSI), %eax # end_head |
| movl $ABS(H), %edx |
| MOVL %eax, (%edx, %edi, 4) # H[i+4] |
| |
| cmpl %eax, ABS(Hmax) |
| jae 3f |
| movl %eax, ABS(Hmax) |
| 3: |
| |
| /* Check the large disk partition -- Win98 */ |
| cmpw $63, ABS(Y) |
| jne 3f |
| cmpl %eax, ABS(Hmax) # EAX=H[i+4] |
| jne 3f |
| cmpw %cx, ABS(Cmax) # ECX=C[i+4] |
| jne 3f |
| |
| cmpl $254, %eax # EAX=ABS(Hmax) |
| jnb 4f |
| cmpw $1022, %cx # CX=ABS(Cmax) |
| jb 3f |
| 4: |
| movl $63, %edx # EDX=ABS(Y) |
| addl %edx, %ebp |
| incl %eax |
| mull %edx # EDX:EAX=product |
| # EDX=0 |
| # EAX high word = 0 |
| # AX=(Hmax+1)*63 |
| pushl %eax # EAX=(Hmax+1)*63 |
| incl %ecx |
| mull %ecx # EDX:EAX=product |
| # EDX=0 |
| cmpl %ebp, %eax |
| popl %eax # EAX=(Hmax+1)*63 |
| jnb 3f |
| |
| /* EDI=i+4 at this moment */ |
| |
| pushl %eax # EAX=(Hmax+1)*63 |
| subl $4, %edi # EDI=i |
| |
| movl $ABS(C), %ebx |
| MOVZWL (%ebx, %edi, 4), %eax # C[i] |
| |
| movl ABS(Hmax), %ebp # Hmax |
| incl %ebp |
| |
| pushl %eax # EAX=C[i] |
| |
| movl $ABS(H), %ebx |
| MOVL (%ebx, %edi, 4), %ecx # H[i] |
| |
| mull %ebp # EDX=0, EAX=product |
| addl %ecx, %eax |
| movl $63, %edx |
| mull %edx # EDX=0, EAX=product |
| |
| movl $ABS(L), %ebx |
| MOVL (%ebx, %edi, 8), %ebp # L[i] |
| |
| cmpl %ebp, %eax |
| popl %eax # EAX=C[i] |
| |
| jae 4f |
| |
| /* calculate CHS numbers from start LBA */ |
| |
| //pushl %eax # EAX=C[i] |
| |
| xorl %edx, %edx |
| xchgl %eax, %ebp # EBP=C[i], EDX:EAX=L[i] |
| |
| divl ABS(Y) # Y=63 |
| # quo=EAX, rem=EDX |
| incl %edx # sector number |
| cmpw %dx, ABS(X) |
| je 5f |
| cmpw $63, ABS(X) |
| jne 4f |
| 5: |
| xorl %edx, %edx |
| movl ABS(Hmax), %ebx |
| incl %ebx # EBX=Hmax+1 |
| divl %ebx # quo=EAX=cylinder number |
| # rem=EDX=head number |
| cmpl %edx, %ecx # ECX=H[i] |
| je 5f |
| decl %ebx # EBX=Hmax |
| cmpl %ebx, %ecx |
| jne 4f |
| 5: |
| /* EAX=calculated cylinder number, EBP=C[i] */ |
| |
| cmpl ABS(Cmax), %ebp |
| je 4f |
| andw $0x3ff, %ax # low 10 bit of calculated cylinder |
| cmpw %ax, %bp |
| //5: |
| // cmpw ABS(Cmax), %ax |
| // jne 4f |
| // cmpl ABS(Hmax), %ecx |
| // jne 4f |
| // cmpw $63, ABS(X) |
| 4: |
| popl %eax |
| jne 6f /* geometry_probe_failed */ |
| jmp 5f |
| 3: |
| |
| /* Check the large disk partition -- Win2K */ |
| |
| /* EDI=i+4 at this moment */ |
| cmpw $63, ABS(Y) |
| jne 3f |
| movl $ABS(H), %edx |
| MOVL (%edx, %edi, 4), %eax # H[i+4] |
| cmpl %eax, ABS(Hmax) # EAX=H[i+4] |
| jne 3f |
| |
| movl $ABS(L), %edx |
| MOVL (%edx, %edi, 8), %ebp # L[i+4] |
| |
| movl $ABS(C), %edx |
| MOVZWL (%edx, %edi, 4), %ecx # C[i+4] |
| |
| incl %ecx |
| incl %eax |
| |
| mull %ecx # EDX=0, EAX=product |
| mull ABS(Y) # Y=63, EDX=0, EAX=product |
| addl ABS(Y), %ebp |
| cmpl %ebp, %eax |
| jnb 3f |
| |
| movl ABS(Hmax), %eax |
| incl %eax |
| mull ABS(Y) # Y=63, EDX=0, EAX=product |
| |
| xorl %edx, %edx |
| xchgl %eax, %ebp # EBP=(Hmax+1)*63 |
| # EAX=L[i+4]+Y |
| |
| divl %ebp # EAX=quo, EDX=rem |
| testl %edx, %edx |
| jnz 3f |
| decl %eax |
| andl $0x3ff, %eax |
| decl %ecx |
| cmpl %eax, %ecx |
| jne 3f |
| |
| /* EDI=i+4 at this moment */ |
| |
| subl $4, %edi # EDI=i |
| |
| movl $ABS(C), %ebx |
| MOVL (%ebx, %edi, 4), %eax # C[i] |
| |
| pushl %eax |
| |
| mull %ebp # EBP=(Hmax+1)*63 |
| # EDX=0, EAX=product |
| |
| pushl %ebp # EBP=(Hmax+1)*63 |
| |
| xchgl %eax, %ebp # EBP=product |
| movl $ABS(H), %ebx |
| MOVL (%ebx, %edi, 4), %eax # H[i] |
| mull ABS(Y) # Y=63, EDX=0, EAX=H[i]*63 |
| |
| pushl %eax |
| |
| addl %eax, %ebp |
| |
| movl $ABS(L), %ebx |
| MOVL (%ebx, %edi, 8), %eax # L[i] |
| cmpl %eax, %ebp |
| |
| popl %ebx # EBX=H[i]*63 |
| popl %ebp # EBP=(Hmax+1)*63 |
| popl %ecx # ECX=C[i] |
| xchgl %eax, %ebp |
| |
| ja 6f /* geometry_probe_failed */ |
| je 5f |
| xchgl %eax, %ebp |
| subl %ebx, %eax |
| xorl %edx, %edx |
| divl %ebp # EAX=quo, EDX=rem |
| testl %edx, %edx |
| jnz 6f /* geometry_probe_failed */ |
| andl $0x3ff, %eax |
| cmpl %eax, %ecx |
| jne 6f /* geometry_probe_failed */ |
| |
| xchgl %eax, %ebp |
| 5: |
| |
| /* EAX = (Hmax+1)*63 */ |
| |
| movl $ABS(C), %ebx |
| MOVW $0, (%ebx, %edi, 4) # C[i]=0 |
| |
| movl $ABS(H), %ebx |
| MOVL $1, (%ebx, %edi, 4) # H[i]=1 |
| |
| movl $ABS(L), %ebx |
| MOVL $63, (%ebx, %edi, 8) # L[i]=63 |
| |
| addl $4, %edi # EDI=i+4 |
| |
| movl $ABS(C), %ebx |
| MOVW $1, (%ebx, %edi, 4) # C[i+4]=1 |
| |
| movl $ABS(H), %ebx |
| MOVL $0, (%ebx, %edi, 4) # H[i+4]=0 |
| |
| movl $ABS(L), %ebx |
| MOVL %eax, (%ebx, %edi, 8) # L[i+4]=(Hmax+1)*63 |
| 3: |
| jmp 3f |
| |
| 2: /* else */ |
| |
| /* empty entry, zero all the coefficients */ |
| |
| movl $ABS(C), %ebx |
| MOVW $0, (%ebx, %edi, 4) # C[i]=0 |
| |
| movl $ABS(H), %ebx |
| MOVW $0, (%ebx, %edi, 4) # H[i]=0 |
| |
| movl $ABS(L), %ebx |
| MOVL $0, (%ebx, %edi, 8) # L[i]=0 |
| |
| addl $4, %edi |
| movl $ABS(C), %ebx |
| MOVW $0, (%ebx, %edi, 4) # C[i+4]=0 |
| |
| movl $ABS(H), %ebx |
| MOVW $0, (%ebx, %edi, 4) # H[i+4]=0 |
| |
| movl $ABS(L), %ebx |
| MOVL $0, (%ebx, %edi, 8) # L[i+4]=0 |
| |
| 3: |
| |
| incl ABS(i) |
| jmp 1b |
| 1: |
| |
| /* all coefficients are generated ok */ |
| |
| # -------------------------------------------------------------------- |
| |
| #if 0 |
| |
| /* print the coefficients */ |
| |
| xorl %edi, %edi |
| 1: |
| cmpl $4, %edi |
| jae 1f |
| |
| /* print C[i] */ |
| movl $ABS(C), %ebx |
| MOVL (%ebx, %edi, 4), %eax # C[i] |
| |
| call 6b //print decimal number |
| |
| /* print spaces */ |
| movl $ABS(delimit_space), %ecx |
| call 8b /* linux_print */ |
| |
| /* print H[i] */ |
| movl $ABS(H), %ebx |
| MOVL (%ebx, %edi, 4), %eax # H[i] |
| |
| call 6b //print decimal number |
| |
| /* print spaces */ |
| movl $ABS(delimit_space), %ecx |
| call 8b /* linux_print */ |
| |
| /* print L[i] */ |
| movl $ABS(L), %ebx |
| MOVL (%ebx, %edi, 8), %eax # L[i] |
| |
| call 6b //print decimal number |
| |
| /* print spaces */ |
| movl $ABS(delimit_space), %ecx |
| call 8b /* linux_print */ |
| |
| addl $4, %edi |
| |
| /* print C[i] */ |
| movl $ABS(C), %ebx |
| MOVL (%ebx, %edi, 4), %eax # C[i+4] |
| |
| call 6b //print decimal number |
| |
| /* print spaces */ |
| movl $ABS(delimit_space), %ecx |
| call 8b /* linux_print */ |
| |
| /* print H[i] */ |
| movl $ABS(H), %ebx |
| MOVL (%ebx, %edi, 4), %eax # H[i+4] |
| |
| call 6b //print decimal number |
| |
| /* print spaces */ |
| movl $ABS(delimit_space), %ecx |
| call 8b /* linux_print */ |
| |
| /* print L[i] */ |
| movl $ABS(L), %ebx |
| MOVL (%ebx, %edi, 8), %eax # L[i+4] |
| |
| call 6b //print decimal number |
| |
| /* print spaces */ |
| movl $ABS(delimit_newline), %ecx |
| call 8b /* linux_print */ |
| |
| subl $4, %edi |
| |
| incl %edi |
| jmp 1b |
| 1: |
| |
| #endif |
| |
| # -------------------------------------------------------------------- |
| |
| xorl %edi, %edi # equation number ABS(i) |
| 1: |
| cmpl $8, %edi |
| jae 1f |
| |
| movl $ABS(C), %ebx |
| CMPW $0, (%ebx, %edi, 4) # C[i] |
| |
| jne 1f |
| |
| incl %edi |
| jmp 1b |
| 1: |
| |
| cmpl $8, %edi |
| jb 1f |
| |
| /* all C[i] == 0 */ |
| |
| xorl %edi, %edi # equation number ABS(i) |
| movl $ABS(H), %ebx |
| 2: |
| cmpl $8, %edi |
| jae 2f |
| |
| MOVL (%ebx, %edi, 4), %ecx # H[i] |
| testl %ecx, %ecx |
| |
| jne 2f |
| |
| incl %edi |
| jmp 2b |
| 2: |
| |
| cmpl $8, %edi |
| je 6f /* geometry_probe_failed */ # all H[i] == 0 |
| |
| xorl %edx, %edx # equation number j |
| movl $ABS(L), %ebx |
| 2: |
| cmpl %edi, %edx |
| jae 2f |
| |
| CMPW $0, (%ebx, %edx, 8) # L[j] |
| |
| jne 6f /* geometry_probe_failed */ |
| |
| incl %edx |
| jmp 2b |
| 2: |
| |
| /* j == i */ |
| |
| MOVL (%ebx, %edi, 8), %eax # L[i] |
| testl %eax, %eax |
| |
| jle 6f /* geometry_probe_failed */ |
| # OF=0; jmp if SF=1 or ZF=1 |
| |
| cdq # EDX=0 |
| divl %ecx # ECX=H[i] |
| # EAX=quo=sectors_per_track |
| # EDX=rem |
| testl %edx, %edx |
| jnz 6f /* geometry_probe_failed */ |
| |
| movl %eax, ABS(probed_sectors_per_track) |
| |
| cmpl $63, %eax |
| ja 6f /* geometry_probe_failed */ |
| |
| cmpw ABS(Smax), %ax |
| jb 6f /* geometry_probe_failed */ |
| |
| movw %ax, ABS(Smax) |
| |
| movl %edi, %edx |
| incl %edx # equation number j=i+1 |
| 2: |
| cmpl $8, %edx |
| jae 2f |
| |
| movl $ABS(H), %ebx |
| MOVL (%ebx, %edx, 4), %ecx # H[j] |
| |
| movl $ABS(L), %ebx |
| MOVL (%ebx, %edx, 8), %eax # L[j] |
| |
| jecxz 3f |
| |
| pushl %edx |
| |
| xchgl %eax, %ecx # EAX=H[j], ECX=L[j] |
| mull ABS(probed_sectors_per_track) # EAX=product |
| # EDX=0 |
| popl %edx |
| |
| cmpl %eax, %ecx |
| |
| jnz 6f /* geometry_probe_failed */ |
| |
| jmp 4f |
| 3: |
| testl %eax, %eax |
| jnz 6f /* geometry_probe_failed */ |
| 4: |
| |
| incl %edx |
| jmp 2b |
| 2: |
| |
| movl ABS(Hmax), %eax |
| incl %eax |
| movl %eax, ABS(probed_heads) |
| |
| jmp 2f |
| 1: |
| |
| testl %edi, %edi |
| jz 1f |
| |
| /* xchgw C[i], C[0] */ |
| |
| movl $ABS(C), %ebx |
| MOVW (%ebx, %edi, 4), %ax # C[i] |
| movw (iBX), %cx # C[0] |
| |
| movw %ax, (iBX) |
| MOVW %cx, (%ebx, %edi, 4) |
| |
| /* xchgw H[i], H[0] */ |
| |
| movl $ABS(H), %ebx |
| MOVL (%ebx, %edi, 4), %eax # H[i] |
| movl (iBX), %ecx # H[0] |
| |
| movl %eax, (iBX) |
| MOVL %ecx, (%ebx, %edi, 4) |
| |
| /* xchgw L[i], L[0] */ |
| |
| movl $ABS(L), %ebx |
| MOVL (%ebx, %edi, 8), %eax # L[i] |
| movl (iBX), %ecx # L[0] |
| |
| movl %eax, (iBX) |
| MOVL %ecx, (%ebx, %edi, 8) |
| |
| 1: |
| |
| movl $0, ABS(H8) # will store sectors per track |
| |
| /* for (i = 1; i < 8; i++) */ |
| |
| movl $1, %edi |
| 1: |
| cmpl $8, %edi |
| jae 1f |
| |
| movl $ABS(L), %ebx |
| MOVL (%ebx, %edi, 8), %eax # L[i] |
| |
| movzwl ABS(C), %edx # C[0] |
| mull %edx # EDX:EAX=product |
| |
| MOVL %eax, (%ebx, %edi, 8) # L[i] low |
| MOVL %edx, 4(%ebx, %edi, 8) # L[i] high |
| |
| movl $ABS(C), %ebx |
| MOVZWL (%ebx, %edi, 4), %eax # C[i] |
| |
| mull ABS(L) # L[0] |
| |
| movl $ABS(L), %ebx |
| SUBL %eax, (%ebx, %edi, 8) # L[i] low |
| SBBL %edx, 4(%ebx, %edi, 8) # L[i] high |
| |
| movl $ABS(H), %ebx |
| MOVL (%ebx, %edi, 4), %eax # H[i] |
| |
| movzwl ABS(C), %edx # C[0] |
| mull %edx # EDX:EAX=product |
| # EDX=0 |
| |
| MOVL %eax, (%ebx, %edi, 4) # H[i] |
| |
| movl $ABS(C), %ebx |
| MOVZWL (%ebx, %edi, 4), %eax # C[i] |
| |
| mull ABS(H) # H[0] |
| |
| movl $ABS(H), %ebx |
| SUBL %eax, (%ebx, %edi, 4) # H[i] |
| |
| /* if (H[i]) */ |
| |
| jz 3f |
| |
| ja 4f |
| |
| movl $ABS(H), %ebx |
| NEGL (%ebx, %edi, 4) # H[i] |
| |
| movl $ABS(L), %ebx |
| xorl %eax, %eax |
| NEGL (%ebx, %edi, 8) # L[i] low |
| cmc |
| NOTL 4(%ebx, %edi, 8) # L[i] high |
| ADCL %eax, 4(%ebx, %edi, 8) |
| |
| 4: |
| movl $ABS(L), %ebx |
| CMPL $0, 4(%ebx, %edi, 8) # L[i] high |
| jne 6f /* geometry_probe_failed */ |
| |
| MOVL (%ebx, %edi, 8), %eax # L[i] low |
| testl %eax, %eax |
| |
| jle 6f /* geometry_probe_failed */ |
| # OF=0; jmp if SF=1 or ZF=1 |
| |
| cdq # EDX=0 |
| |
| movl $ABS(H), %ebx |
| DIVL (%ebx, %edi, 4) # H[i] |
| # EAX=sectors per track |
| testl %edx, %edx |
| jnz 6f /* geometry_probe_failed */ |
| |
| movl %eax, ABS(L8) |
| |
| cmpl $63, %eax |
| ja 6f /* geometry_probe_failed */ |
| |
| cmpw ABS(Smax), %ax |
| jb 6f /* geometry_probe_failed */ |
| |
| movw %ax, ABS(Smax) |
| |
| cmpl $0, ABS(H8) |
| je 4f |
| |
| cmpl %eax, ABS(H8) # EAX=L[8] |
| jne 6f /* geometry_probe_failed */ |
| |
| jmp 5f |
| 4: |
| movl %eax, ABS(H8) # EAX=L[8] |
| 5: |
| |
| jmp 4f |
| 3: /* else */ |
| movl $ABS(L), %ebx |
| CMPL $0, (%ebx, %edi, 8) # L[i] low |
| jne 6f /* geometry_probe_failed */ |
| |
| CMPL $0, 4(%ebx, %edi, 8) # L[i] high |
| jne 6f /* geometry_probe_failed */ |
| |
| 4: /* end if (H[i]) */ |
| |
| incl %edi |
| jmp 1b |
| 1: /* end for (i = 1; i < 8; i++) */ |
| |
| /* if (ABS(H)[8]) */ |
| |
| cmpl $0, ABS(H8) |
| je 3f |
| |
| /* ABS(H)[8] is sectors per track */ |
| |
| movl ABS(H), %eax # H[0] |
| mull ABS(H8) |
| |
| //movl $ABS(L), %ebx |
| subl %eax, ABS(L) # L[0] low |
| sbbl %edx, ABS(L) + 4 # L[0] high |
| |
| jnz 6f /* geometry_probe_failed */ |
| |
| movl ABS(L), %eax |
| testl %eax, %eax |
| |
| jle 6f /* geometry_probe_failed */ |
| # OF=0; jmp if SF=1 or ZF=1 |
| |
| cdq # EDX=0 |
| |
| divl ABS(H8) |
| |
| testl %edx, %edx |
| jnz 6f /* geometry_probe_failed */ |
| |
| movzwl ABS(C), %ecx # C[0] |
| divl %ecx |
| |
| testl %edx, %edx |
| jnz 6f /* geometry_probe_failed */ |
| |
| movl %eax, ABS(L8) # L[8] is number of heads |
| |
| cmpl $256, %eax |
| ja 6f /* geometry_probe_failed */ |
| |
| cmpl ABS(Hmax), %eax |
| jbe 6f /* geometry_probe_failed */ |
| |
| movl ABS(H8), %eax |
| movl %eax, ABS(probed_sectors_per_track) |
| |
| jmp 4f |
| 3: /* else */ |
| |
| /* fail to set L[8], this means all H[i]==0, i=1,2,3,4,5,6,7 */ |
| |
| /* Now the only equation is: C[0] * H * S + H[0] * S = L[0] */ |
| |
| /* for (i = 63; i >= Smax; i--) */ |
| |
| movl ABS(L), %ebx # EBX=L[0] |
| movl $63, %edi |
| 3: |
| cmpl ABS(Smax), %edi |
| jb 3f |
| |
| movl ABS(H), %eax # H[0] |
| mull %edi # EDX=0 |
| # EAX=product |
| //movl %ebx, ABS(L8) |
| //subl %eax, ABS(L8) |
| |
| subl %ebx, %eax |
| negl %eax |
| |
| jz 5f # continue |
| js 5f # continue |
| |
| cdq # EDX=0 |
| divl %edi |
| |
| testl %edx, %edx |
| jnz 5f |
| |
| movzwl ABS(C), %ecx # C[0] |
| divl %ecx |
| |
| testl %edx, %edx |
| jnz 5f |
| |
| movl %eax, ABS(L8) # L[8] is number of heads |
| |
| cmpl $256, %eax |
| ja 5f |
| |
| cmpl ABS(Hmax), %eax |
| ja 3f |
| 5: |
| decl %edi |
| jmp 3b |
| 3: /* end for (i = 63; i >= Smax; i--) */ |
| |
| cmpl ABS(Smax), %edi |
| jb 6f /* geometry_probe_failed */ |
| |
| movl %edi, ABS(probed_sectors_per_track) |
| |
| 4: /* end if (ABS(H)[8]) */ |
| |
| movl ABS(L8), %eax |
| movl %eax, ABS(probed_heads) |
| |
| 2: /* end if (ABS(i) == 8) */ |
| |
| /* geometry_probe_ok */ |
| |
| clc |
| popal |
| ret |
| |
| //geometry_probe_failed: |
| 6: |
| stc |
| popal |
| ret |
| |
| //partition: |
| 0: |
| #if 0 |
| /* load the next partition and modify the boot record */ |
| |
| /* EBX holds the file descriptor number or 0 if it is BIOS drive */ |
| /* partition table is at ABS(mbr_63_sectors + 0x2000) */ |
| /* current partition number is ABS(current_partition) */ |
| |
| pushal |
| |
| /* enumerate all partitions */ |
| |
| /* initialize the partition table, move start_LBA(the 3rd dword) |
| * to the total_sectors field(the 4th dword) and clear the 3rd dword. |
| * The sum of the 3rd and 4th dwords gives the absolute start_LBA. |
| */ |
| movl $ABS(mbr_63_sectors + 0x2000), %ebp |
| xorl %eax, %eax |
| xchgl %eax, 0x08(%ebp) |
| movl %eax, 0x0c(%ebp) |
| xorl %eax, %eax |
| xchgl %eax, 0x18(%ebp) |
| movl %eax, 0x1c(%ebp) |
| xorl %eax, %eax |
| xchgl %eax, 0x28(%ebp) |
| movl %eax, 0x2c(%ebp) |
| xorl %eax, %eax |
| xchgl %eax, 0x38(%ebp) |
| movl %eax, 0x3c(%ebp) |
| |
| movl $0x04, ABS(total_partition_entries) |
| /* copy extended partition entries to the end of the partition table */ |
| xorl %esi, %esi |
| 1: |
| movb 4(%ebp, %esi), %al # partition id |
| cmpb $0x05, %al |
| je 2f |
| cmpb $0x0f, %al |
| je 2f |
| cmpb $0x15, %al |
| je 2f |
| cmpb $0x1f, %al |
| je 2f |
| cmpb $0x85, %al |
| jne 4f |
| 2: |
| /* extended partition */ |
| |
| /* read one sector of the partition to ABS(mbr_63_sectors) */ |
| ........ |
| /* check if the partition table is valid */ |
| j_invalid 3f |
| /* approve the partition entries and move onto the free entries */ |
| movl ABS(total_partition_entries), %edi |
| shll $4, %edi |
| addl %ebp, %edi # EDI points to the first free entry |
| /* move the extended partition entry onto the first free entry */ |
| movl (%ebp, %esi), %eax |
| stosl |
| movl 4(%ebp, %esi), %eax |
| stosl |
| xorl %eax, %eax |
| stosl |
| movl 8(%ebp, %esi), %eax |
| stosl |
| incl ABS(total_partition_entries) |
| 3: |
| ///* disable the original extended partition entry by clearing its id */ |
| //movb $0, 4(%ebp, %esi) |
| cmpl $0x40, %esi # Is it in the main partition table? |
| jb 4f # yes, keep the entry in its place. |
| |
| # no, remove the entry. |
| pushl %esi |
| addl %ebp, %esi |
| movl %esi, %edi |
| addl $0x10, %esi |
| movl ABS(total_partition_entries), %ecx |
| shll $4, %ecx |
| subl %esi, %ecx |
| shrl $2, %ecx |
| cld |
| repz movsl |
| popl %esi |
| decl ABS(total_partition_entries) |
| subl $0x10, %esi # go back one entry and redo |
| 4: |
| addl $0x10, %esi |
| movl ABS(total_partition_entries), %edi |
| shll $4, %edi |
| cmpl %edi, %esi |
| jb 1b |
| |
| /* end of partition enumeration */ |
| |
| /* recursively resolve extended partition entries */ |
| //xorl %esi, %esi |
| //movl $4, %esi |
| //cmpl ABS(total_partition_entries), %esi |
| |
| |
| cmpl $3, ABS(current_partition) |
| ja 1f |
| /* it is primary partition */ |
| movl ABS(current_partition), %esi |
| shll $4, %esi |
| movl 8(%ebp, %esi), %eax # start LBA |
| movl $ABS(msg_no_such_partition), ABS(error_message_pointer) |
| testl %eax, %eax |
| stc |
| jz 2f |
| /* read 4 sectors at start LBA to ABS(mbr_63_sectors) */ |
| movl $4, %ecx |
| clc /* read */ |
| call 6f |
| movl $ABS(msg_read_file), ABS(error_message_pointer) |
| jc 2f |
| /* modify the boot record */ |
| call 7f |
| movl $ABS(msg_unsupported_fstype), ABS(error_message_pointer) |
| jc 2f |
| /* write sectors to start LBA at ABS(mbr_63_sectors) */ |
| movl ABS(sectors_to_write), %ecx |
| stc /* write */ |
| call 6f |
| movl $ABS(msg_write_file), ABS(error_message_pointer) |
| 2: |
| popal |
| ret |
| |
| 1: |
| /* it is logical partition */ |
| movl $ABS(msg_end_of_partition_chain), ABS(error_message_pointer) |
| popal |
| ret |
| 6: |
| /* before the call: */ |
| /* EAX=start LBA */ |
| /* EBX=file descriptor or 0 for BIOS drive */ |
| /* ECX=sectors */ |
| /* CF=0 for read; CF=1 for write */ |
| /* on return: */ |
| /* CF=0 for success; CF=1 for failure */ |
| |
| pushal |
| |
| popal |
| ret |
| 7: |
| pushal |
| |
| popal |
| ret |
| /* EBX holds the file descriptor number or 0 if it is BIOS drive */ |
| /* move partition table forward to the beginning of the 17th sector */ |
| movl $ABS(mbr_63_sectors + 0x01be), %esi |
| movl $ABS(mbr_63_sectors + 0x2000), %edi |
| movl $0x10, %ecx # 0x10 dwords = 0x40 bytes |
| |
| cld |
| repz movsl |
| |
| /* initialize the current_partition number */ |
| movzbl ABS(install_partition), %eax |
| movl %eax, ABS(current_partition) |
| |
| 3: |
| /* load the next partition and modify the boot record */ |
| call 0f /* partition */ |
| jc 3f /* done */ |
| call 2f /* write to file */ |
| incl ABS(current_partition) |
| movw ABS(install_partition), %ax |
| addb %ah, %al /* Max partition number for install */ |
| cmpb %al, ABS(current_partition) |
| jbe 3b |
| 3: |
| /* all partitions have been installed. */ |
| |
| xorl %eax, %eax # exit code = 0 |
| |
| #ifdef __DOS_16 |
| |
| movb $0x4c, %ah // EXIT - TERMINATE WITH RETURN CODE in AL |
| int $0x21 // call DOS |
| |
| #else |
| xchgl %eax, %ebx # move exit code in EAX to EBX |
| movl $1, %eax # sys_exit |
| int $0x80 |
| #endif |
| |
| #endif |
| ret |
| |