📄 grldrstart.s
字号:
/* * grldrstart.S -- Startup code for GRLDR * Copyright (C) 2004-2007 Tinybit(tinybit@tom.com) * Copyright (C) 2007 Bean(bean@windrv.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. *//* * This program is used to generate the GRLDR file. * * Use the following shell command to generate the GRLDR file: * * cat grldrstart pre_stage2 > grldr * */#define ASM_FILE#include <shared.h>#define ASM_FILE #ifndef STAGE1_5#include <stage2_size.h>#else#error cannot compile with STAGE1_5#endif#ifdef GRLDR_MBR .file "mbrstart.S"#elif defined(GRLDR_INSTALL) .file "bootlacestart.S"#else .file "grldrstart.S"#endif#ifdef GRLDR_INSTALL //.data#else .text .globl start, _startstart:_start:#endif_start1: /* Tell GAS to generate 16-bit real mode instructions */ .code16 . = _start1 + 0x00 /* 1 byte at offset 0x00 will be overwritten for storing the EBIOS * indicator later. This is safe because the jmp instruction only * get executed once. The write happens after the jmp instruction * have got executed. * * The value written would be 0x42 for EBIOS present(LBA) and 0x02 * for non-present(CHS). * */ /* No cli, we use stack! BIOS or caller usually sets SS:SP=0000:0400 */ jmp 1f /* FAT32/NTFS routine comes to offset 0 */ . = _start1 + 0x02 .byte 0x80 /* bit0=1: disable GRLDR search on floppy */ /* bit1=1: disable the boot of the previous MBR with * invalid partition table */ /* bit2=1: disable the feature of unconditional * entrance to the command-line */ /* bit7=1: disable the boot of the previous MBR prior to the search for GRLDR */ /* GRLDR.MBR uses offset 0x03 to indicate a timer counter. */ /* 0xff indicates waiting forever, * other value specifies the time in seconds to wait */ . = _start1 + 0x03 .byte 5 /* a key press to wait. if AX returned from int16 equals this word, * the desired action will occur. */ . = _start1 + 0x04 .word 0x3920 /* the space bar */ . = _start1 + 0x06 .byte 0xff /* preferred boot drive number, 0xff for no-drive(i.e., drive not defined) */ .byte 0xff /* preferred partition number, 0xff for whole drive(a floppy that has no partition table) */ . = _start1 + 8 /* 2 bytes at offset 0x08 will be overwritten for storing the geometry * reported by INT 13/AH=8. * * lo byte = Sectors Per Track * hi byte = Max Head Number(=number of heads minus 1) * * If INT 13/AH=8 returns error, then the word here will be 0xFFFF. * */#if (! defined(GRLDR_MBR)) && (! defined(GRLDR_INSTALL)) /* filled in by mkisofs using the -boot-info-table option */#;bi_pvd: .long 0xDEADBEEF /* LBA of primary volume descript */#;bi_file: .long 0xDEADBEEF /* LBA of boot file */#;bi_length: .long 0xDEADBEEF /* Length of boot file */#;bi_csum: .long 0xDEADBEEF /* Checksum of boot file */#;bi_reserved: .space (10*4) /* Reserved */ . = _start1 + 0x40#else /* filled in with BPB in case the drive(typically USB) is treated as floppy by buggy BIOSes */ . = _start1 + 0x60#endif /* ! defined(GRLDR_MBR) && (! defined(GRLDR_INSTALL)) */1: call 1f#if (! defined(GRLDR_MBR)) && (! defined(GRLDR_INSTALL)) . = _start1 + 0x43#else . = _start1 + 0x63#endif /* ! defined(GRLDR_MBR) && (! defined(GRLDR_INSTALL)) */1: popw %bx /* Instruction Pointer of 1b */#if (! defined(GRLDR_MBR)) && (! defined(GRLDR_INSTALL)) subw $(1b - _start1), %bx /* CS:BX=_start1 */#else subw $(1b - _start1), %bx /* CS:BX=_start1 */#endif /* ! defined(GRLDR_MBR) && (! defined(GRLDR_INSTALL)) */ shrw $4, %bx movw %cs, %ax addw %ax, %bx /* BX:0000=_start1 */#if (! defined(GRLDR_MBR)) && (! defined(GRLDR_INSTALL)) /* we are booted from BOOT.INI, or whole GRLDR image already loaded */ /* Let CS:0000=_start1 */ pushw %bx /* BX:0000=_start1 */ #;pushw $(1f - _start1) .byte 0x6A, (1f - _start1) lret . = . - (. - _start1) / 0x801: addw $((grldr_signature - _start1 + 4 + STAGE2_SIZE - 4) >> 4), %bx movw %bx, %ds cmpl $0xCE1A02B0, ((STAGE2_SIZE - 4) & 0x0F) pushw %cs popw %ds /* DS:0000=_start1 */ je grldr_real_start /* whole image loaded. boot it! */ /* bad! we might be loaded by a buggy BIOS with a no-emulation-mode * bootable CD. The buggy BIOS might load only 1 CD-ROM sector(2048 * bytes) of our grldr image. So we need this check. */ /* Our cdrom_check code begins at 0x1BE and overlaps the partition * table. Just in case someone replace it with a partition table and * use this sector as an MBR, we do this additional test for safety. */ /* We should avoid using opcode 0x00 and 0x80 at cdrom_check. */ /* Note that if cdrom_check code is present, then we are booting from * no-emulation mode cdrom. */ testb $0x7F, cdrom_check - _start1 /* is it 0x00 or 0x80? */ jz 1f /* yes, cdrom_check not found */ call cdrom_check /* no, cdrom_check is present */1:// /* DS:0000=_start1 *///// /* Let CS:0000=_start1 */// pushw %ds//// #;pushw $(1f - _start1)// .byte 0x6A, (1f - _start1)//// lret// . = . - (. - _start1) / 0x80//1:#else /* BX:0000=_start1 */ movw %bx, %ds /* Let CS:0000=_start1 */ pushw %bx #;pushw $(1f - _start1) .byte 0x6A, (1f - _start1) lret . = . - (. - _start1) / 0x801: testb $0x04, 0x02 jz 1f /* set the DUCE indicator */ xorw %ax, %ax movw %ax, %es movw $0x5FC, %di movl $0x45435544, %eax stosl1:#endif /* CS:0000=DS:0000=_start1 */ /* we are loaded by BIOS or another boot loader */#define GRLDR_CS 0x2000 /* grldr code segment */ /* hope this segment never be used by all */ /* subsequent partition boot records */#if 0 /* for single sector boot record */#define MONITOR 0x7e10#else /* for 4-sector NTFS boot record */#define MONITOR 0x8410#endif// cli pushw $GRLDR_CS popw %ss movw $0x9000, %sp /* SS:SP=0x9d000, keep away from EBDA data */// sti /* Extended BIOS Data Area should not take up space below 0x9d000 */ /* * 0x07c00-0x07dff This sector. Another boot loader load us here * 0x0d000-0x14dff partition/floppy boot track(bootsector,etc) * 0x94000-0x9bdff master boot track(MBR,etc,usually 63 sectors) * 0x9be00-0x9c3ff 3 sectors for temp extended partition entries * 0x9c400-0x9cfff 6 sectors for stack */#define FS_BOOT 0xd00 /* segment of partition boot track */ xorw %cx, %cx pushw %cx /* CX=0 */ movw $0x0080, %dx// pushw %dx movb $8, %ah /* read drive parameters changes DX,ES,DI,BX */ call int13// stc// int $0x13// popw %dx popw %ax /* AX=0 */ pushw %ss /* SS=0x9400 */ popw %es /* ES=0x9400 */ jc 1f andb $63, %cl /* AL=sectors per track, CF cleared */ stc jz 1f xchgw %ax, %cx /* this moves CL to AL, and CX=0 */ movb $0x02, %ah movw %ax, %bp /* save AX to BP: read 1 track */ xorw %bx, %bx /* ES already has a known value of 0x9400 */ incw %cx// pushw %dx call int13// stc// int $0x13 /* read master boot track to ES:0000 */// popw %dx jc 1f negb %ah /* set CF=1 if non-zero */1: pushw %cs /* DS=0 */ popw %ds /* DS=CS */ pushfw /* CF=1 on error */ /* CS=DS=old segment. ES=SS=new segment. */ /* Move the code and error messages from DS:0000 to 9400:0000, do not * touch the partition table */ xorw %si, %si xorw %di, %di movw $223, %cx /* 223 words = 446 bytes = 0x1be bytes */ cld repz movsw /* SI=DI=0x1be, CX=0 */ /********************************************************************/ /* At this moment we are still not sure whether the helper is ok. */ /********************************************************************/disk_serial_number_structure:#if (defined(GRLDR_MBR)) || (defined(GRLDR_INSTALL)) /********************************************************************/ /* This piece of code is structured! It contains address 0x1FFC and */ /* a disk serial number that can be created by grub4dos installer. */ /********************************************************************/ movw $0x1FFC, %bx /* .byte 0xBB, 0xFC, 0x1F */ /* if the boot loader has loaded more than one sector, we use them */ movl $0x93cb4d05, %eax /* date-time for disk serial number */ /* "MOV EAX"(0x66, 0xB8) followed by the changeable S.N. */#else movw $(grldr_signature - _start1), %bx /* BX=0x1FFC */ /* if the boot loader has loaded more than one sector, we use them */ movl $0xAA555247, %eax /* "GR" 0x55 0xAA */#endifdisk_serial_number_structure_end://#if (! defined(GRLDR_MBR)) && (! defined(GRLDR_INSTALL)) cmpl %eax, (%bx) /* DS=old segment of 07C0:0000 */ jne 1f /* The MOVE_HELPER code is in the old segment of 07C0:0000 */ call move_helper /* SI=0x1be, CX=0 */1://#endif /* Jump to new segment! */#if 1 ljmp $GRLDR_CS, $(1f - _start1)#else pushw %ss /* 0x9400 */ //pushw $(1f - _start1) .byte 0x6A, (1f - _start1) lret . = . - (. - _start1) / 0x80#endif1: /* We are at the new segment. CS=ES=SS=new segment. */ /* But DS is still old segment. */ pushw %ss popw %ds /* CS=DS=ES=SS=new segment. */ //movw $0x01be, %si /* check the existence of helper */ cmpl %eax, (%bx)#if (! defined(GRLDR_MBR)) && (! defined(GRLDR_INSTALL)) jne Error_or_prev_MBR /* Missing helper */#else je 1f /* try to load helper from floppy */ pushal movw 0x18, %ax /* BPB sectors per track at offset 0x18 */ cmpw $0x3F, %ax ja 3f cmpb $((pre_stage2_start - _start1) >> 9), %al jb 3f decw %ax /* skip the first sector already loaded */ movw $3, %di /* retry 3 times on read failure */2: movb $2, %ah /* BIOS disk read */ cwd /* DX=0 for floppy head 0 */ movw $0x200, %bx /* ES:BX immediately follow this sector */ movw $2, %cx /* skip the first sector already loaded */ call read_disk_with_reset_and_dec_di jnc 3f jnz 2b3: popal cmpl %eax, (%bx) /* helper loaded? */ jne Error_or_prev_MBR /* Missing helper */ /* Helper is loaded from floppy, so we set floppy as preferred. */ //movw $0xff00, 0x06 //movw %cx, 0x06 /* CX=0 */ call set_floppy_preferred1:#endif popfw /* CF=1 on error */ jc try_floppy /* harddisk (hd0) failed, try floppy (fd0) */ /*********************************/ /* Helper is successfully loaded */ /*********************************/1: pushw %cs popw %ds lodsw movb %ah, %dh /* head number */ lodsw movw %ax, %cx /* sector and cylinder number */ andb $63, %al //stc jz helper_call_c /* use BP to calculate the sectors to read within 1 track */ subw %bp, %ax decw %ax /* decb %al */ negb %al /* AL=sectors upto the end of the track */7: movw $3, %di /* retry 3 times on read failure */2: movb $2, %ah pushw $FS_BOOT popw %es /* ES=FS_BOOT */ xorw %bx, %bx /* read partition boot track to FS_BOOT:0000 */#if (! defined(GRLDR_MBR)) && (! defined(GRLDR_INSTALL)) pushaw// int $0x13 /* read partition boot track to FS_BOOT:0000 */ call int13 popaw jnc helper_call pushaw xorw %ax, %ax// int $0x13 call int13 popaw decw %di#else call read_disk_with_reset_and_dec_di jnc helper_call#endif jnz 2bhelper_call_c: stchelper_call: /* find GRLDR in this partition * before the call: * CF=1 : indicates an invalid or corrupt entry * CF=0 : indicates a valid entry * * on return: * CF=1 : means "below", try next entry * CF=0,ZF=1 : means "equal", helper did nothing, so we need * a further try to boot via NT bootsector * CF=0,ZF=0 : means "above", helper succeeded, boot it now */ call helper_start /* change to jmp 6f if helper not present */ ja filesystem_boot /* helper succeeded, directly boot it */6:add_sub_si: /* extended partition check routine will adjust this to * * 0x83, 0xEE, 0x04 for "subw $4, %si" * * or * * 0x83, 0xC6, 0xFC for "addw $-4, %si" * * so that SI keeps the value 0x1fe. */ addw $12, %si /* 0x83, 0xC6, 0x0C */ . = add_sub_si + 3 /* extended partition check routine will adjust the word 0x1fe at * (add_sub_si + 5). The value 0x1ff or greater indicates there are * entries need to be treated. The value 0x1fe indicates no entries * left, and the floppy should be checked. */ cmpw $0x01fe, %si /* 0x81, 0xFE, 0xfe, 0x01 */ /* All entries checked done? */ jb 1b /* No, check the next entry */ ja 5f /* floppy already checked. Fail and hang */try_floppy: movw $0x31b2, %si /* a value big enough */ movb $8, %ah /* read drive parameters changes DX,ES,DI,BX */ cwd /* DL=0 for floppy */ pushw %dx /* DX=0 */// int $0x13 call int13
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -