3 * GRUB -- GRand Unified Bootloader
4 * Copyright (C) 1999,2000,2001,2002,2005,2006,2007,2008 Free Software Foundation, Inc.
6 * GRUB is free software: you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation, either version 3 of the License, or
9 * (at your option) any later version.
11 * GRUB is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
16 * You should have received a copy of the GNU General Public License
17 * along with GRUB. If not, see <http://www.gnu.org/licenses/>.
20 #include <grub/boot.h>
21 #include <grub/machine/boot.h>
24 * defines for the code go here
28 This makes the assembler generate the address without support
29 from the linker. (ELF can't relocate 16-bit addresses!) */
30 #define ABS(x) (x-_start+0x7c00)
32 /* Print message string */
33 #define MSG(x) movw $ABS(x), %si; call message
39 /* Tell GAS to generate 16-bit instructions so that this code works
43 .globl _start; _start:
45 * _start is loaded at 0x7c00 and is jumped to with CS:IP 0:0x7c00
49 * Beginning of the sector is compatible with the FAT/HPFS BIOS
54 nop /* do I care about this ??? */
57 * This space is for the BIOS parameter block!!!! Don't change
58 * the first jump, nor start the code anywhere but right after
82 . = _start + GRUB_BOOT_MACHINE_BPB_END
85 * End of BIOS parameter block.
89 .byte GRUB_BOOT_VERSION_MAJOR, GRUB_BOOT_VERSION_MINOR
91 .word GRUB_BOOT_MACHINE_KERNEL_ADDR
93 .word GRUB_BOOT_MACHINE_KERNEL_SEG
97 .byte 0xff /* the disk to load kernel from */
98 /* 0xff means use the boot drive */
105 cli /* we're not safe here! */
108 * This is a workaround for buggy BIOSes which don't pass boot
109 * drive correctly. If GRUB is installed into a HDD, check if
110 * DL is masked correctly. If not, assume that the BIOS passed
111 * a bogus value and set DL to 0x80, since this is the only
112 * possible boot drive. If GRUB is installed into a floppy,
113 * this does nothing (only jump).
116 jmp 1f /* grub-setup may overwrite this jump */
123 * ljmp to the next instruction because some bogus BIOSes
124 * jump to 07C0:0000 instead of 0000:7C00.
126 ljmp $0, $ABS(real_start)
130 /* set up %ds and %ss as offset from 0 */
135 /* set up the REAL stack */
136 movw $GRUB_BOOT_MACHINE_STACK_SEG, %sp
138 sti /* we're safe again */
141 * Check if we have a forced disk reference here
143 /* assign root_drive at the same time */
144 movw ABS(boot_drive), %ax
150 /* save drive reference first thing! */
153 /* print a notification message on the screen */
154 MSG(notification_string)
156 /* set %si to the disk address packet */
157 movw $ABS(disk_address_packet), %si
159 /* do not probe LBA if the drive is a floppy */
160 testb $GRUB_BOOT_MACHINE_BIOS_HD_FLAG, %dl
163 /* check if LBA is supported */
169 * %dl may have been clobbered by INT 13, AH=41H.
170 * This happens, for example, with AST BIOS 1.04.
175 /* use CHS if fails */
188 /* set the mode to non-zero */
194 /* the size and the reserved byte */
197 /* the absolute address */
198 movl ABS(kernel_sector), %ebx
200 movl ABS(kernel_sector + 4), %ebx
203 /* the segment of buffer address */
204 movw $GRUB_BOOT_MACHINE_BUFFER_SEG, 6(%si)
207 * BIOS call "INT 0x13 Function 0x42" to read sectors from disk into memory
208 * Call with %ah = 0x42
210 * %ds:%si = segment:offset of disk address packet
212 * %al = 0x0 on success; err code on failure
218 /* LBA read is not supported, so fallback to CHS. */
221 movw $GRUB_BOOT_MACHINE_BUFFER_SEG, %bx
226 * Determine the hard disk geometry from the BIOS!
227 * We do this first, so that LS-120 IDE floppies work correctly.
234 * The call failed, so maybe use the floppy probe instead.
236 testb $GRUB_BOOT_MACHINE_BIOS_HD_FLAG, %dl
239 /* Nope, we definitely have a hard disk, and we're screwed. */
243 /* set the mode to zero */
247 /* save number of heads */
256 /* save number of cylinders */
263 /* save number of sectors */
267 /* load logical sector start (top half) */
268 movl ABS(kernel_sector + 4), %eax
272 /* load logical sector start (bottom half) */
273 movl ABS(kernel_sector), %eax
278 /* divide by number of sectors */
281 /* save sector start */
284 xorw %dx, %dx /* zero %edx */
285 divl 4(%si) /* divide by number of heads */
287 /* do we need too many cylinders? */
291 /* normalize sector start (1-based) */
294 /* low bits of cylinder start */
297 /* high bits of cylinder start */
302 /* save head start */
313 * BIOS call "INT 0x13 Function 0x2" to read sectors from disk into memory
314 * Call with %ah = 0x2
315 * %al = number of sectors
317 * %cl = sector (bits 6-7 are high bits of "cylinder")
319 * %dl = drive (0x80 for hard disk, 0x0 for floppy disk)
320 * %es:%bx = segment:offset of buffer
322 * %al = 0x0 on success; err code on failure
325 movw $GRUB_BOOT_MACHINE_BUFFER_SEG, %bx
326 movw %bx, %es /* load %es segment with disk buffer */
328 xorw %bx, %bx /* %bx = 0, put it at 0 in the segment */
329 movw $0x0201, %ax /* function 2 */
337 movw ABS(kernel_segment), %es
340 * We need to save %cx and %si because the startup code in
341 * kernel uses them without initializing them.
361 jmp *(kernel_address)
363 /* END OF MAIN LOOP */
366 * BIOS Geometry translation error (past the end of the disk geometry!).
369 MSG(geometry_error_string)
373 * Disk probe failure.
376 MSG(hd_probe_error_string)
380 * Read error on the disk.
383 MSG(read_error_string)
386 MSG(general_error_string)
388 /* go here when you need to stop the machine hard after an error condition */
389 /* tell the BIOS a boot failure, which may result in no effect */
393 notification_string: .string "GRUB "
394 geometry_error_string: .string "Geom"
395 hd_probe_error_string: .string "Hard Disk"
396 read_error_string: .string "Read"
397 general_error_string: .string " Error"
400 * message: write the string pointed to by %si
402 * WARNING: trashes %si, %ax, and %bx
406 * Use BIOS "int 10H Function 0Eh" to write character in teletype mode
407 * %ah = 0xe %al = character
408 * %bh = page %bl = foreground color (graphics modes)
413 int $0x10 /* display a byte */
417 jne 1b /* if not end of string, jmp to display */
421 * Windows NT breaks compatibility by embedding a magic
425 . = _start + GRUB_BOOT_MACHINE_WINDOWS_NT_MAGIC
431 * This is where an MBR would go if on a hard disk. The code
432 * here isn't even referenced unless we're on a floppy. Kinda
437 . = _start + GRUB_BOOT_MACHINE_PART_START
440 .byte 36, 18, 15, 9, 0
444 * Perform floppy probe.
447 movw $ABS(probe_values-1), %si
450 /* reset floppy controller INT 13h AH=0 */
457 /* if number of sectors is 0, display error and die */
462 * Floppy disk probe failure.
464 MSG(fd_probe_error_string)
467 fd_probe_error_string: .string "Floppy"
471 movw $GRUB_BOOT_MACHINE_BUFFER_SEG, %bx
477 /* if error, jump to "probe_loop" */
480 /* %cl is already the correct value! */
486 . = _start + GRUB_BOOT_MACHINE_PART_END
488 /* the last 2 bytes in the sector 0 contain the signature */
489 .word GRUB_BOOT_MACHINE_SIGNATURE