1N/A * GRUB -- GRand Unified Bootloader 1N/A * Copyright (C) 1999,2000,2001,2002,2004 Free Software Foundation, Inc. 1N/A * This program is free software; you can redistribute it and/or modify 1N/A * it under the terms of the GNU General Public License as published by 1N/A * the Free Software Foundation; either version 2 of the License, or 1N/A * (at your option) any later version. 1N/A * This program is distributed in the hope that it will be useful, 1N/A * but WITHOUT ANY WARRANTY; without even the implied warranty of 1N/A * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 1N/A * GNU General Public License for more details. 1N/A * You should have received a copy of the GNU General Public License 1N/A * along with this program; if not, write to the Free Software 1N/A * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. 1N/A * defines for the code go here 1N/A /* Absolute addresses 1N/A This makes the assembler generate the address without support 1N/A from the linker. (ELF can't relocate 16-bit addresses!) */ 1N/A /* Print message string */ 1N/A /* XXX: binutils-2.9.1.0.x doesn't produce a short opcode for this. */ 1N/A /* Tell GAS to generate 16-bit instructions so that this code works 1N/A * _start is loaded at 0x7c00 and is jumped to with CS:IP 0:0x7c00 1N/A * Beginning of the sector is compatible with the FAT/HPFS BIOS 1N/A nop /* do I care about this ??? */ 1N/A * This space is for the BIOS parameter block!!!! Don't change 1N/A * the first jump, nor start the code anywhere but right after 1N/A * End of BIOS parameter block. 1N/A cli /* we're not safe here! */ 1N/A * This is a workaround for buggy BIOSes which don't pass boot 1N/A * drive correctly. If GRUB is installed into a HDD, check if 1N/A * DL is masked correctly. If not, assume that the BIOS passed 1N/A * a bogus value and set DL to 0x80, since this is the only 1N/A * possible boot drive. If GRUB is installed into a floppy, 1N/A * this does nothing (only jump). 1N/A * ljmp to the next instruction because some bogus BIOSes 1N/A * jump to 07C0:0000 instead of 0000:7C00. 1N/A /* set up %ds and %ss as offset from 0 */ 1N/A /* set up the REAL stack */ 1N/A * Check if we have a forced disk reference here 1N/A /* save drive reference first thing! */ 1N/A /* print a notification message on the screen */ 1N/A /* do not probe LBA if the drive is a floppy */ 1N/A /* check if LBA is supported */ 1N/A * %dl may have been clobbered by INT 13, AH=41H. 1N/A * This happens, for example, with AST BIOS 1.04. 1N/A /* use CHS if fails */ 1N/A /* check if AH=0x42 is supported if FORCE_LBA is zero */ 1N/A /* save the total number of sectors */ 1N/A /* set %si to the disk address packet */ 1N/A /* set the mode to non-zero */ 1N/A /* the size and the reserved byte */ 1N/A /* the absolute address (low 32 bits) */ 1N/A /* the segment of buffer address */ 1N/A * BIOS call "INT 0x13 Function 0x42" to read sectors from disk into memory 1N/A * Call with %ah = 0x42 1N/A * %dl = drive number 1N/A * %ds:%si = segment:offset of disk address packet 1N/A * %al = 0x0 on success; err code on failure 1N/A /* LBA read is not supported, so fallback to CHS. */ 1N/A * Determine the hard disk geometry from the BIOS! 1N/A * We do this first, so that LS-120 IDE floppies work correctly. 1N/A * The call failed, so maybe use the floppy probe instead. 1N/A /* Nope, we definitely have a hard disk, and we're screwed. */ 1N/A /* set the mode to zero */ 1N/A /* save number of heads */ 1N/A /* save number of cylinders */ 1N/A /* save number of sectors */ 1N/A /* load logical sector start (bottom half) */ 1N/A /* divide by number of sectors */ 1N/A /* save sector start */ 1N/A /* save head start */ 1N/A /* save cylinder start */ 1N/A /* do we need too many cylinders? */ 1N/A * This is the loop for taking care of BIOS geometry translation (ugh!) 1N/A /* get high bits of cylinder */ 1N/A from 1-N, not 0-(N-1) ) */ 1N/A movb 12(%
si), %
ch /* sector+hcyl in cl, cylinder in ch */ 1N/A * BIOS call "INT 0x13 Function 0x2" to read sectors from disk into memory 1N/A * Call with %ah = 0x2 1N/A * %al = number of sectors 1N/A * %cl = sector (bits 6-7 are high bits of "cylinder") 1N/A * %dl = drive (0x80 for hard disk, 0x0 for floppy disk) 1N/A * %es:%bx = segment:offset of buffer 1N/A * %al = 0x0 on success; err code on failure 1N/A xorw %
bx, %
bx /* %bx = 0, put it at 0 in the segment */ 1N/A * We need to save %cx and %si because the startup code in 1N/A * stage2 uses them without initializing them. 1N/A/* END OF MAIN LOOP */ 1N/A * BIOS Geometry translation error (past the end of the disk geometry!). 1N/A * Disk probe failure. 1N/A * Read error on the disk. 1N/A/* go here when you need to stop the machine hard after an error condition */ 1N/A * message: write the string pointed to by %si 1N/A * WARNING: trashes %si, %ax, and %bx 1N/A * Use BIOS "int 10H Function 0Eh" to write character in teletype mode 1N/A * %ah = 0xe %al = character 1N/A * %bh = page %bl = foreground color (graphics modes) 1N/A int $
0x10 /* display a byte */ 1N/A jne 1b
/* if not end of string, jmp to display */ 1N/A * Windows NT breaks compatibility by embedding a magic 1N/A * This is where an MBR would go if on a hard disk. The code 1N/A * here isn't even referenced unless we're on a floppy. Kinda 1N/A * Perform floppy probe. 1N/A /* reset floppy controller INT 13h AH=0 */ 1N/A /* if number of sectors is 0, display error and die */ 1N/A * Floppy disk probe failure. 1N/A /* if error, jump to "probe_loop" */ 1N/A /* %cl is already the correct value! */ 1N/A/* the last 2 bytes in the sector 0 contain the signature */