/*
* GRUB -- GRand Unified Bootloader
* Copyright (C) 1999,2000,2001 Free Software Foundation, Inc.
*
* 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.
*/
#define ASM_FILE
#include <shared.h>
#ifndef STAGE1_5
#include <stage2_size.h>
#endif
/*
* defines for the code go here
*/
/* Absolute addresses
This makes the assembler generate the address without support
from the linker. (ELF can't relocate 16-bit addresses!) */
#ifdef STAGE1_5
#else
#endif /* STAGE1_5 */
/* Print message string */
.file "start.S"
.text
/* Tell GAS to generate 16-bit instructions so that this code works
in real mode. */
/*
* _start is loaded at 0x8000 and is jumped to with
* CS:IP 0:0x8000 in stage2.
*/
/*
* we continue to use the stack for stage1 and assume that
* some registers are set to correct values. See stage1.S
* for more information.
*/
/* save drive reference first thing! */
/* print a notification message on the screen */
/* this sets up for the first run through "bootloop" */
/* save the sector number of the second sector in %ebp */
/* this is the loop for reading the secondary boot-loader in */
/* check the number of sectors to read */
/* if zero, go to the start function */
/* check if we use LBA or CHS */
/* jump to chs_mode if zero */
/* load logical sector start */
/* the maximum is limited to 0x7f because of Phoenix EDD */
/* how many do we really want to read? */
/* which is greater? */
jg 1f
/* if less than, set to total */
1:
/* subtract from total */
/* add into logical sector start */
/* set up disk address packet */
/* the size and the reserved byte */
/* the number of sectors */
/* the absolute address (low 32 bits) */
/* the segment of buffer address */
/* save %ax from destruction! */
/* zero %eax */
/* the offset of buffer address */
/* the absolute address (high 32 bits) */
/*
* BIOS call "INT 0x13 Function 0x42" to read sectors from disk into memory
* Call with %ah = 0x42
* %dl = drive number
* %ds:%si = segment:offset of disk address packet
* Return:
* %al = 0x0 on success; err code on failure
*/
int $0x13
/* load logical sector start (bottom half) */
/* zero %edx */
/* divide by number of sectors */
/* save sector start */
/* save head start */
/* save cylinder start */
/* do we need too many cylinders? */
/* determine the maximum sector length of this read */
/* subtract sector start */
/* how many do we really want to read? */
/* which is greater? */
jg 2f
/* if less than, set to total */
2:
/* subtract from total */
/* add into logical sector start */
/*
* This is the loop for taking care of BIOS geometry translation (ugh!)
*/
/* get high bits of cylinder */
from 1-N, not 0-(N-1) ) */
/* restore %dx */
/* head number */
/*
* BIOS call "INT 0x13 Function 0x2" to read sectors from disk into memory
* Call with %ah = 0x2
* %al = number of sectors
* %ch = cylinder
* %cl = sector (bits 6-7 are high bits of "cylinder")
* %dh = head
* %dl = drive (0x80 for hard disk, 0x0 for floppy disk)
* %es:%bx = segment:offset of buffer
* Return:
* %al = 0x0 on success; err code on failure
*/
int $0x13
/* save source segment */
/* load addresses for copy from disk buffer to destination */
/* restore %ax */
/* determine the next possible destination address (presuming
512 byte sectors!) */
address for next time */
/* save addressing regs */
/* get the copy length */
cld /* sets the copy direction to forward */
/* perform copy */
rep /* sets a repeat */
movsb /* this runs the actual copy */
/* restore addressing regs and print a dot with correct DS
(MSG modifies SI, which is saved, and unused AX and BX) */
/* check if finished with this dataset */
/* update position to load from */
/* jump to bootloop */
/* END OF MAIN LOOP */
/* print a newline */
#ifdef STAGE1_5
ljmp $0, $0x2200
#else /* ! STAGE1_5 */
ljmp $0, $0x8200
#endif /* ! STAGE1_5 */
/*
* BIOS Geometry translation error (past the end of the disk geometry!).
*/
/*
* Read error on the disk.
*/
/* go here when you need to stop the machine hard after an error condition */
#ifdef STAGE1_5
#else
#endif
/*
* message: write the string pointed to by %si
*
* WARNING: trashes %si, %ax, and %bx
*/
/*
* Use BIOS "int 10H Function 0Eh" to write character in teletype mode
* %ah = 0xe %al = character
* %bh = page %bl = foreground color (graphics modes)
*/
1:
int $0x10 /* display a byte */
/*
* This area is an empty space between the main body of code below which
* grows up (fixed after compilation, but between releases it may change
* in size easily), and the lists of sectors to read, which grows down
* from a fixed top location.
*/
.word 0
.word 0
/* fill the first data listing with the default */
.long 2 /* this is the sector start parameter, in logical
sectors from the start of the disk, sector 0 */
/* this is the number of sectors to read */
#ifdef STAGE1_5
.word 0 /* the command "install" will fill this up */
#else
#endif
#ifdef STAGE1_5
.word 0x220
#else
to load the data into */
#endif