2 * GRUB -- GRand Unified Bootloader
3 * Copyright (C) 1999,2000,2001,2002,2003,2005,2006,2007,2008 Free Software Foundation, Inc.
5 * GRUB is free software: you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation, either version 3 of the License, or
8 * (at your option) any later version.
10 * GRUB is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
15 * You should have received a copy of the GNU General Public License
16 * along with GRUB. If not, see <http://www.gnu.org/licenses/>.
21 * Note: These functions defined in this file may be called from C.
22 * Be careful of that you must not modify some registers. Quote
23 * from gcc-2.95.2/gcc/config/i386/i386.h:
25 1 for registers not available across function calls.
26 These must include the FIXED_REGISTERS and also any
27 registers that can be used without being saved.
28 The latter must include the registers where values are returned
29 and the register where structure-value addresses are passed.
30 Aside from that, you can include as many other registers as you like.
32 ax,dx,cx,bx,si,di,bp,sp,st,st1,st2,st3,st4,st5,st6,st7,arg
33 { 1, 1, 1, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 }
37 * Note: GRUB is compiled with the options -mrtd and -mregparm=3.
38 * So the first three arguments are passed in %eax, %edx, and %ecx,
39 * respectively, and if a function has a fixed number of arguments
40 * and the number if greater than three, the function must return
41 * with "ret $N" where N is ((the number of arguments) - 3) * 4.
45 #include <grub/symbol.h>
46 #include <grub/boot.h>
47 #include <grub/machine/boot.h>
48 #include <grub/machine/memory.h>
49 #include <grub/machine/console.h>
50 #include <grub/cpu/linux.h>
51 #include <grub/machine/kernel.h>
52 #include <grub/term.h>
53 #include <multiboot.h>
54 #include <multiboot2.h>
56 #define ABS(x) ((x) - _start + GRUB_BOOT_MACHINE_KERNEL_ADDR + 0x200)
62 /* Tell GAS to generate 16-bit instructions so that this code works
70 * Guarantee that "main" is loaded at 0x0:0x8200.
73 codestart_abs = ABS(codestart) - 0x10000
74 ljmp $0, $(codestart_abs)
76 ljmp $0, $ABS(codestart)
80 * Compatibility version number
82 * These MUST be at byte offset 6 and 7 of the executable
86 .byte GRUB_BOOT_VERSION_MAJOR, GRUB_BOOT_VERSION_MINOR
89 * This is a special data area 8 bytes from the beginning.
94 VARIABLE(grub_total_module_size)
96 VARIABLE(grub_kernel_image_size)
98 VARIABLE(grub_compressed_size)
100 VARIABLE(grub_install_dos_part)
102 VARIABLE(grub_install_bsd_part)
104 VARIABLE(grub_prefix)
105 /* to be filled by grub-mkimage */
108 * Leave some breathing room for the prefix.
111 . = _start + GRUB_KERNEL_MACHINE_DATA_END
121 * Support for booting GRUB from a Multiboot boot loader (e.g. GRUB itself).
122 * This uses the a.out kludge to load raw binary to the area starting at 1MB,
123 * and relocates itself after loaded.
125 .p2align 2 /* force 4-byte alignment */
132 .long -0x1BADB002 - (1 << 16)
134 .long multiboot_header - _start + 0x100000 + 0x200
142 .long multiboot_entry - _start + 0x100000 + 0x200
146 /* obtain the boot device */
149 /* relocate the code */
150 movl $(GRUB_KERNEL_MACHINE_RAW_SIZE + 0x200), %ecx
151 addl EXT_C(grub_compressed_size) - _start + 0x100000 + 0x200, %ecx
153 movl $GRUB_BOOT_MACHINE_KERNEL_ADDR, %edi
157 /* jump to the real address */
158 movl $multiboot_trampoline, %eax
161 multiboot_trampoline:
162 /* fill the boot information */
169 movl %ebx, EXT_C(grub_install_dos_part)
174 movl %ebx, EXT_C(grub_install_bsd_part)
178 /* enter the usual booting */
182 /* the real mode code continues... */
184 cli /* we're not safe here! */
186 /* set up %ds, %ss, and %es */
192 /* set up the real mode/BIOS stack */
193 movl $GRUB_MEMORY_MACHINE_REAL_STACK, %ebp
196 sti /* we're safe again */
198 /* save boot and root drive references */
199 ADDR32 movb %dl, EXT_C(grub_boot_drive)
200 ADDR32 movb %dh, EXT_C(grub_root_drive)
202 /* reset disk system (%ah = 0) */
205 /* transition to protected mode */
206 DATA32 call real_to_prot
208 /* The ".code32" directive takes GAS out of 16-bit mode. */
212 call EXT_C(grub_gate_a20)
214 #if defined(ENABLE_LZO)
215 /* decompress the compressed part and put the result at 1MB */
216 movl $GRUB_MEMORY_MACHINE_DECOMPRESSION_ADDR, %esi
217 movl $(_start + GRUB_KERNEL_MACHINE_RAW_SIZE), %edi
220 pushl EXT_C(grub_compressed_size)
222 call lzo1x_decompress
227 #elif defined(ENABLE_LZMA)
228 movl $GRUB_MEMORY_MACHINE_DECOMPRESSION_ADDR, %edi
229 movl $(_start + GRUB_KERNEL_MACHINE_RAW_SIZE), %esi
232 movl EXT_C(grub_kernel_image_size), %ecx
233 addl EXT_C(grub_total_module_size), %ecx
234 subl $GRUB_KERNEL_MACHINE_RAW_SIZE, %ecx
236 leal (%edi, %ecx), %ebx
238 /* _LzmaDecodeA clears DF, so no need to run cld */
244 /* copy back the decompressed part (except the modules) */
245 subl EXT_C(grub_total_module_size), %ecx
250 /* copy modules before cleaning out the bss */
251 movl EXT_C(grub_total_module_size), %ecx
252 movl EXT_C(grub_kernel_image_size), %esi
256 movl $END_SYMBOL, %edi
265 /* clean out the bss */
266 bss_start_abs = ABS (bss_start)
267 bss_end_abs = ABS (bss_end)
269 movl bss_start_abs, %edi
271 /* compute the bss length */
272 movl bss_end_abs, %ecx
275 /* clean out the bss */
276 movl $BSS_START_SYMBOL, %edi
278 /* compute the bss length */
279 movl $END_SYMBOL, %ecx
290 * Call the start of main body of C code.
292 call EXT_C(grub_main)
294 #include "../realmode.S"
297 * This is the area for all of the special variables.
300 VARIABLE(grub_boot_drive)
303 VARIABLE(grub_root_drive)
306 .p2align 2 /* force 4-byte alignment */
309 * These next two routines, "real_to_prot" and "prot_to_real" are structured
310 * in a very specific way. Be very careful when changing them.
312 * NOTE: Use of either one messes up %eax and %ebp.
319 /* load the GDT register */
323 DATA32 ADDR32 lgdt gdtdesc
325 DATA32 ADDR32 lgdt %cs:gdtdesc
328 /* turn on protected mode */
330 orl $GRUB_MEMORY_MACHINE_CR0_PE_ON, %eax
333 /* jump to relocation, flush prefetch queue, and reload %cs */
334 DATA32 ljmp $GRUB_MEMORY_MACHINE_PROT_MODE_CSEG, $protcseg
338 /* reload other segment registers */
339 movw $GRUB_MEMORY_MACHINE_PROT_MODE_DSEG, %ax
346 /* put the return address in a known safe location */
348 movl %eax, GRUB_MEMORY_MACHINE_REAL_STACK
350 /* get protected mode stack */
355 /* get return address onto the right stack */
356 movl GRUB_MEMORY_MACHINE_REAL_STACK, %eax
362 /* return on the old (or initialized) stack! */
366 * grub_gate_a20(int on)
368 * Gate address-line 20 for high memory.
370 * This routine is probably overconservative in what it does, but so what?
372 * It also eats any keystrokes in the keyboard buffer. :-(
375 FUNCTION(grub_gate_a20)
378 gate_a20_test_current_state:
379 /* first of all, test if already in a good state */
380 call gate_a20_check_state
382 jnz gate_a20_try_bios
386 /* second, try a BIOS call */
397 DATA32 call real_to_prot
401 call gate_a20_check_state
403 jnz gate_a20_try_system_control_port_a
406 gate_a20_try_system_control_port_a:
408 * In macbook, the keyboard test would hang the machine, so we move
411 /* fourth, try the system control port A */
419 /* When turning off Gate A20, do not check the state strictly,
420 because a failure is not fatal usually, and Gate A20 is always
421 on some modern machines. */
424 call gate_a20_check_state
426 jnz gate_a20_try_keyboard_controller
429 gate_a20_flush_keyboard_buffer:
432 jnz gate_a20_flush_keyboard_buffer
442 gate_a20_try_keyboard_controller:
443 /* third, try the keyboard controller */
444 call gate_a20_flush_keyboard_buffer
458 call gate_a20_flush_keyboard_buffer
460 /* output a dummy command (USB keyboard hack) */
463 call gate_a20_flush_keyboard_buffer
465 call gate_a20_check_state
467 /* everything failed, so restart from the beginning */
468 jnz gate_a20_try_bios
471 gate_a20_check_state:
472 /* iterate the checking for a while */
485 /* compare the byte at 0x8000 with that at 0x108000 */
486 movl $GRUB_BOOT_MACHINE_KERNEL_ADDR, %ebx
488 /* save the original byte in CL */
490 /* store the value at 0x108000 in AL */
493 /* try to set one less value at 0x8000 */
501 /* obtain the value at 0x108000 in CH */
505 /* this result is 1 if A20 is on or 0 if it is off */
508 /* restore the original */
515 #if defined(ENABLE_LZO)
517 #elif defined(ENABLE_LZMA)
518 #include "lzma_decode.S"
522 * The code beyond this point is compressed. Assert that the uncompressed
523 * code fits GRUB_KERNEL_MACHINE_RAW_SIZE.
525 . = _start + GRUB_KERNEL_MACHINE_RAW_SIZE
528 * This call is special... it never returns... in fact it should simply
529 * hang at this point!
536 * This next part is sort of evil. It takes advantage of the
537 * byte ordering on the x86 to work in either 16-bit or 32-bit
538 * mode, so think about it before changing it.
541 FUNCTION(grub_hard_stop)
543 jmp EXT_C(grub_hard_stop)
549 * Stop the floppy drive from spinning, so that other software is
550 * jumped to with a known state.
552 FUNCTION(grub_stop_floppy)
566 /* Tell the BIOS a boot failure. If this does not work, reboot. */
574 * Reboot the system. At the moment, rely on BIOS.
576 FUNCTION(grub_reboot)
583 ljmp $0xFFFF, $0x0000
587 * grub_halt(int no_apm)
589 * Halt the system, using APM if possible. If NO_APM is true, don't use
590 * APM even if it is available.
604 jc EXT_C(grub_hard_stop)
605 /* don't check %bx for buggy BIOSes... */
607 /* disconnect APM first */
616 jc EXT_C(grub_hard_stop)
618 /* set APM protocol level - 1.1 or bust. (this covers APM 1.2 also) */
623 jc EXT_C(grub_hard_stop)
625 /* set the power state to off */
631 /* shouldn't reach here */
632 jmp EXT_C(grub_hard_stop)
637 * void grub_chainloader_real_boot (int drive, void *part_addr)
639 * This starts another boot loader.
642 FUNCTION(grub_chainloader_real_boot)
646 call EXT_C(grub_dl_unload_all)
648 /* Turn off Gate A20 */
650 call EXT_C(grub_gate_a20)
652 /* set up to pass boot drive */
655 /* ESI must point to a partition table entry */
660 ljmp $0, $GRUB_MEMORY_MACHINE_BOOT_LOADER_ADDR
663 #include "../loader.S"
666 * int grub_biosdisk_rw_int13_extensions (int ah, int drive, void *dap)
668 * Call IBM/MS INT13 Extensions (int 13 %ah=AH) for DRIVE. DAP
669 * is passed for disk address packet. If an error occurs, return
670 * non-zero, otherwise zero.
673 FUNCTION(grub_biosdisk_rw_int13_extensions)
677 /* compute the address of disk_address_packet */
680 shrl $4, %ecx /* save the segment to cx */
684 /* enter real mode */
690 int $0x13 /* do the operation */
691 movb %ah, %dl /* save return value */
692 /* back to protected mode */
693 DATA32 call real_to_prot
696 movb %dl, %al /* return value in %eax */
704 * int grub_biosdisk_rw_standard (int ah, int drive, int coff, int hoff,
705 * int soff, int nsec, int segment)
707 * Call standard and old INT13 (int 13 %ah=AH) for DRIVE. Read/write
708 * NSEC sectors from COFF/HOFF/SOFF into SEGMENT. If an error occurs,
709 * return non-zero, otherwise zero.
712 FUNCTION(grub_biosdisk_rw_standard)
720 /* set up CHS information */
722 /* set %ch to low eight bits of cylinder */
724 /* set bits 6-7 of %cl to high two bits of cylinder */
726 /* set bits 0-5 of %cl to sector */
728 /* set %dh to head */
732 /* set %al to NSEC */
734 /* save %ax in %di */
736 /* save SEGMENT in %bx */
739 /* enter real mode */
745 movw $3, %si /* attempt at least three times */
749 int $0x13 /* do the operation */
750 jnc 2f /* check if successful */
752 movb %ah, %bl /* save return value */
753 /* if fail, reset the disk system */
763 /* back to protected mode */
764 DATA32 call real_to_prot
767 movb %bl, %al /* return value in %eax */
778 * int grub_biosdisk_check_int13_extensions (int drive)
780 * Check if LBA is supported for DRIVE. If it is supported, then return
781 * the major version of extensions, otherwise zero.
784 FUNCTION(grub_biosdisk_check_int13_extensions)
790 /* enter real mode */
796 int $0x13 /* do the operation */
798 /* check the result */
803 movb %ah, %bl /* save the major version into %bl */
805 /* check if AH=0x42 is supported */
812 /* back to protected mode */
813 DATA32 call real_to_prot
816 movb %bl, %al /* return value in %eax */
825 * int grub_biosdisk_get_cdinfo_int13_extensions (int drive, void *cdrp)
827 * Return the cdrom information of DRIVE in CDRP. If an error occurs,
828 * then return non-zero, otherwise zero.
831 FUNCTION(grub_biosdisk_get_cdinfo_int13_extensions)
836 * int grub_biosdisk_get_diskinfo_int13_extensions (int drive, void *drp)
838 * Return the geometry of DRIVE in a drive parameters, DRP. If an error
839 * occurs, then return non-zero, otherwise zero.
842 FUNCTION(grub_biosdisk_get_diskinfo_int13_extensions)
849 /* compute the address of drive parameters */
853 movw %dx, %bx /* save the segment into %bx */
856 /* enter real mode */
862 int $0x13 /* do the operation */
863 movb %ah, %bl /* save return value in %bl */
864 /* back to protected mode */
865 DATA32 call real_to_prot
868 movb %bl, %al /* return value in %eax */
878 * int grub_biosdisk_get_diskinfo_standard (int drive,
879 * unsigned long *cylinders,
880 * unsigned long *heads,
881 * unsigned long *sectors)
883 * Return the geometry of DRIVE in CYLINDERS, HEADS and SECTORS. If an
884 * error occurs, then return non-zero, otherwise zero.
887 FUNCTION(grub_biosdisk_get_diskinfo_standard)
896 /* SECTORS is on the stack */
900 /* enter real mode */
905 int $0x13 /* do the operation */
906 /* check if successful */
909 /* bogus BIOSes may not return an error number */
910 testb $0x3f, %cl /* 0 sectors means no disk */
911 jnz 1f /* if non-zero, then succeed */
912 /* XXX 0x60 is one of the unused error numbers */
915 movb %ah, %bl /* save return value in %bl */
916 /* back to protected mode */
917 DATA32 call real_to_prot
923 incl %eax /* the number of heads is counted from zero */
930 shrb $6, %ah /* the number of cylinders is counted from zero */
935 movl 0x10(%esp), %edi
941 movb %bl, %al /* return value in %eax */
951 * int grub_biosdisk_get_num_floppies (void)
953 FUNCTION(grub_biosdisk_get_num_floppies)
960 /* reset the disk system first */
965 /* call GET DISK TYPE */
971 /* check if this drive exists */
979 DATA32 call real_to_prot
989 * grub_get_memsize(i) : return the memory size in KB. i == 0 for conventional
990 * memory, i == 1 for extended memory
991 * BIOS call "INT 12H" to get conventional memory size
992 * BIOS call "INT 15H, AH=88H" to get extended memory size
993 * Both have the return value in AX.
997 FUNCTION(grub_get_memsize)
1002 call prot_to_real /* enter real mode */
1018 DATA32 call real_to_prot
1029 * grub_get_eisa_mmap() : return packed EISA memory map, lower 16 bits is
1030 * memory between 1M and 16M in 1K parts, upper 16 bits is
1031 * memory above 16M in 64K parts. If error, return zero.
1032 * BIOS call "INT 15H, AH=E801H" to get EISA memory map,
1033 * AX = memory between 1M and 16M in 1K parts.
1034 * BX = memory above 16M in 64K parts.
1038 FUNCTION(grub_get_eisa_mmap)
1042 call prot_to_real /* enter real mode */
1051 DATA32 call real_to_prot
1066 * grub_get_mmap_entry(addr, cont) : address and old continuation value (zero to
1067 * start), for the Query System Address Map BIOS call.
1069 * Sets the first 4-byte int value of "addr" to the size returned by
1070 * the call. If the call fails, sets it to zero.
1072 * Returns: new (non-zero) continuation value, 0 if done.
1075 FUNCTION(grub_get_mmap_entry)
1084 /* place address (+4) in ES:DI */
1091 /* set continuation value */
1094 /* set default maximum buffer size */
1097 /* set EDX to 'SMAP' */
1098 movl $0x534d4150, %edx
1100 call prot_to_real /* enter real mode */
1109 cmpl $0x534d4150, %eax
1123 /* Apple's cc jumps few bytes before the correct
1124 label in this context. Hence nops. */
1135 DATA32 call real_to_prot
1138 /* write length of buffer (zero if error) into ADDR */
1142 /* set return value to continuation */
1153 * void grub_console_real_putchar (int c)
1155 * Put the character C on the console. Because GRUB wants to write a
1156 * character with an attribute, this implementation is a bit tricky.
1157 * If C is a control character (CR, LF, BEL, BS), use INT 10, AH = 0Eh
1158 * (TELETYPE OUTPUT). Otherwise, save the original position, put a space,
1159 * save the current position, restore the original position, write the
1160 * character and the attribute, and restore the current position.
1162 * The reason why this is so complicated is that there is no easy way to
1163 * get the height of the screen, and the TELETYPE OUTPUT BIOS call doesn't
1164 * support setting a background attribute.
1166 FUNCTION(grub_console_real_putchar)
1169 movb EXT_C(grub_console_cur_color), %bl
1176 /* use teletype output if control character */
1186 /* save the character and the attribute on the stack */
1190 /* get the current position */
1194 /* check the column with the width */
1198 /* print CR and LF, if next write will exceed the width */
1204 /* get the current position */
1209 /* restore the character and the attribute */
1213 /* write the character with the attribute */
1218 /* move the cursor forward */
1229 3: DATA32 call real_to_prot
1237 * int grub_console_getkey (void)
1238 * BIOS call "INT 16H Function 00H" to read character from keyboard
1239 * Call with %ah = 0x0
1240 * Return: %ah = keyboard scan code
1241 * %al = ASCII character
1244 /* this table is used in translate_keycode below */
1246 .word GRUB_CONSOLE_KEY_LEFT, GRUB_TERM_LEFT
1247 .word GRUB_CONSOLE_KEY_RIGHT, GRUB_TERM_RIGHT
1248 .word GRUB_CONSOLE_KEY_UP, GRUB_TERM_UP
1249 .word GRUB_CONSOLE_KEY_DOWN, GRUB_TERM_DOWN
1250 .word GRUB_CONSOLE_KEY_HOME, GRUB_TERM_HOME
1251 .word GRUB_CONSOLE_KEY_END, GRUB_TERM_END
1252 .word GRUB_CONSOLE_KEY_DC, GRUB_TERM_DC
1253 .word GRUB_CONSOLE_KEY_BACKSPACE, GRUB_TERM_BACKSPACE
1254 .word GRUB_CONSOLE_KEY_PPAGE, GRUB_TERM_PPAGE
1255 .word GRUB_CONSOLE_KEY_NPAGE, GRUB_TERM_NPAGE
1259 * translate_keycode translates the key code %dx to an ascii code.
1268 translation_table_abs = ABS (translation_table) - 0x10000
1269 movw $(translation_table_abs), %si
1271 movw $ABS(translation_table), %si
1275 /* check if this is the end */
1278 /* load the ascii code into %ax */
1281 /* check if this matches the key code */
1284 /* translate %dx, if successful */
1293 FUNCTION(grub_console_getkey)
1300 * Due to a bug in apple's bootcamp implementation, INT 16/AH = 0 would
1301 * cause the machine to hang at the second keystroke. However, we can
1302 * work around this problem by ensuring the presence of keystroke with
1303 * INT 16/AH = 1 before calling INT 16/AH = 0.
1318 movw %ax, %dx /* real_to_prot uses %eax */
1319 call translate_keycode
1321 DATA32 call real_to_prot
1331 * int grub_console_checkkey (void)
1332 * if there is a character pending, return it; otherwise return -1
1333 * BIOS call "INT 16H Function 01H" to check whether a character is pending
1334 * Call with %ah = 0x1
1336 * If key waiting to be input:
1337 * %ah = keyboard scan code
1338 * %al = ASCII character
1343 FUNCTION(grub_console_checkkey)
1347 call prot_to_real /* enter real mode */
1362 DATA32 call real_to_prot
1372 * grub_uint16_t grub_console_getxy (void)
1373 * BIOS call "INT 10H Function 03h" to get cursor position
1374 * Call with %ah = 0x03
1376 * Returns %ch = starting scan line
1377 * %cl = ending scan line
1378 * %dh = row (0 is top)
1379 * %dl = column (0 is left)
1383 FUNCTION(grub_console_getxy)
1385 pushl %ebx /* save EBX */
1390 xorb %bh, %bh /* set page to 0 */
1392 int $0x10 /* get cursor position */
1394 DATA32 call real_to_prot
1406 * void grub_console_gotoxy(grub_uint8_t x, grub_uint8_t y)
1407 * BIOS call "INT 10H Function 02h" to set cursor position
1408 * Call with %ah = 0x02
1410 * %dh = row (0 is top)
1411 * %dl = column (0 is left)
1415 FUNCTION(grub_console_gotoxy)
1417 pushl %ebx /* save EBX */
1419 movb %dl, %dh /* %dh = y */
1420 movb %al, %dl /* %dl = x */
1425 xorb %bh, %bh /* set page to 0 */
1427 int $0x10 /* set cursor position */
1429 DATA32 call real_to_prot
1438 * void grub_console_cls (void)
1439 * BIOS call "INT 10H Function 09h" to write character and attribute
1440 * Call with %ah = 0x09
1442 * %bh = (page number)
1444 * %cx = (number of times)
1447 FUNCTION(grub_console_cls)
1449 pushl %ebx /* save EBX */
1454 /* move the cursor to the beginning */
1460 /* write spaces to the entire screen */
1463 movw $(80 * 25), %cx
1466 /* move back the cursor */
1470 DATA32 call real_to_prot
1479 * void grub_console_setcursor (int on)
1480 * BIOS call "INT 10H Function 01h" to set cursor type
1481 * Call with %ah = 0x01
1482 * %ch = cursor starting scanline
1483 * %cl = cursor ending scanline
1486 console_cursor_state:
1488 console_cursor_shape:
1491 FUNCTION(grub_console_setcursor)
1498 /* check if the standard cursor shape has already been saved */
1499 movw console_cursor_shape, %ax
1510 DATA32 call real_to_prot
1513 movw %cx, console_cursor_shape
1515 /* set %cx to the designated cursor shape */
1520 movw console_cursor_shape, %cx
1528 DATA32 call real_to_prot
1537 * if a seconds value can be read, read it and return it (BCD),
1538 * otherwise return 0xFF
1539 * BIOS call "INT 1AH Function 02H" to check whether a character is pending
1540 * Call with %ah = 0x2
1542 * If RT Clock can give correct values
1544 * %cl = minutes (BCD)
1545 * %dh = seconds (BCD)
1546 * %dl = daylight savings time (00h std, 01h daylight)
1547 * Carry flag = clear
1550 * (this indicates that the clock is updating, or
1551 * that it isn't running)
1553 FUNCTION(grub_getrtsecs)
1556 call prot_to_real /* enter real mode */
1567 DATA32 call real_to_prot
1578 * return the real time in ticks, of which there are about
1581 FUNCTION(grub_get_rtc)
1584 call prot_to_real /* enter real mode */
1587 /* %ax is already zero */
1590 DATA32 call real_to_prot
1602 * unsigned char grub_vga_set_mode (unsigned char mode)
1604 FUNCTION(grub_vga_set_mode)
1611 /* get current mode */
1617 /* set the new mode */
1622 DATA32 call real_to_prot
1632 * unsigned char *grub_vga_get_font (void)
1634 FUNCTION(grub_vga_get_font)
1645 DATA32 call real_to_prot
1658 * grub_vbe_bios_status_t grub_vbe_get_controller_info (struct grub_vbe_info_block *controller_info)
1660 * Register allocations for parameters:
1661 * %eax *controller_info
1663 FUNCTION(grub_vbe_bios_get_controller_info)
1668 movw %ax, %di /* Store *controller_info to %edx:%di. */
1671 mov %eax, %edx /* prot_to_real destroys %eax. */
1678 movw %dx, %es /* *controller_info is now on %es:%di. */
1682 movw %ax, %dx /* real_to_prot destroys %eax. */
1686 DATA32 call real_to_prot
1690 andl $0x0FFFF, %eax /* Return value in %eax. */
1698 * grub_vbe_status_t grub_vbe_bios_get_mode_info (grub_uint32_t mode,
1699 * struct grub_vbe_mode_info_block *mode_info)
1701 * Register allocations for parameters:
1705 FUNCTION(grub_vbe_bios_get_mode_info)
1709 movl %eax, %ecx /* Store mode number to %ecx. */
1711 movw %dx, %di /* Store *mode_info to %edx:%di. */
1720 movw %dx, %es /* *mode_info is now on %es:%di. */
1724 movw %ax, %dx /* real_to_prot destroys %eax. */
1728 DATA32 call real_to_prot
1732 andl $0x0FFFF, %eax /* Return value in %eax. */
1739 * grub_vbe_status_t grub_vbe_bios_set_mode (grub_uint32_t mode,
1740 * struct grub_vbe_crtc_info_block *crtc_info)
1742 * Register allocations for parameters:
1746 FUNCTION(grub_vbe_bios_set_mode)
1751 movl %eax, %ebx /* Store mode in %ebx. */
1753 movw %dx, %di /* Store *crtc_info to %edx:%di. */
1762 movw %dx, %es /* *crtc_info is now on %es:%di. */
1767 movw %ax, %dx /* real_to_prot destroys %eax. */
1771 DATA32 call real_to_prot
1775 andl $0xFFFF, %eax /* Return value in %eax. */
1783 * grub_vbe_status_t grub_vbe_bios_get_mode (grub_uint32_t *mode)
1785 * Register allocations for parameters:
1788 FUNCTION(grub_vbe_bios_get_mode)
1793 pushl %eax /* Push *mode to stack. */
1801 movw %ax, %dx /* real_to_prot destroys %eax. */
1803 DATA32 call real_to_prot
1806 popl %edi /* Pops *mode from stack to %edi. */
1811 andl $0xFFFF, %eax /* Return value in %eax. */
1820 * grub_vbe_status_t grub_vbe_bios_set_memory_window (grub_uint32_t window,
1821 * grub_uint32_t position);
1823 * Register allocations for parameters:
1827 FUNCTION(grub_vbe_bios_set_memory_window)
1837 andw $0x00ff, %bx /* BL = window, BH = 0, Set memory window. */
1840 movw %ax, %dx /* real_to_prot destroys %eax. */
1842 DATA32 call real_to_prot
1846 andl $0xFFFF, %eax /* Return value in %eax. */
1853 * grub_vbe_status_t grub_vbe_bios_get_memory_window (grub_uint32_t window,
1854 * grub_uint32_t *position);
1856 * Register allocations for parameters:
1860 FUNCTION(grub_vbe_bios_get_memory_window)
1864 pushl %edx /* Push *position to stack. */
1866 movl %eax, %ebx /* Store window in %ebx. */
1872 andw $0x00ff, %bx /* BL = window. */
1873 orw $0x0100, %bx /* BH = 1, Get memory window. */
1876 movw %ax, %bx /* real_to_prot destroys %eax. */
1878 DATA32 call real_to_prot
1881 popl %edi /* pops *position from stack to %edi. */
1883 movl %edx, (%edi) /* Return position to caller. */
1886 andl $0xFFFF, %eax /* Return value in %eax. */
1894 * grub_vbe_status_t grub_vbe_bios_set_scanline_length (grub_uint32_t length)
1896 * Register allocations for parameters:
1899 FUNCTION(grub_vbe_bios_set_scanline_length)
1904 movl %eax, %ecx /* Store length in %ecx. */
1910 movw $0x0002, %bx /* BL = 2, Set Scan Line in Bytes. */
1913 movw %ax, %dx /* real_to_prot destroys %eax. */
1915 DATA32 call real_to_prot
1919 andl $0xFFFF, %eax /* Return value in %eax. */
1927 * grub_vbe_status_t grub_vbe_bios_get_scanline_length (grub_uint32_t *length)
1929 * Register allocations for parameters:
1932 FUNCTION(grub_vbe_bios_get_scanline_length)
1936 pushl %edx /* Push *length to stack. */
1942 movw $0x0001, %bx /* BL = 1, Get Scan Line Length (in bytes). */
1945 movw %ax, %dx /* real_to_prot destroys %eax. */
1947 DATA32 call real_to_prot
1950 popl %edi /* Pops *length from stack to %edi. */
1952 movl %ebx, (%edi) /* Return length to caller. */
1955 andl $0xFFFF, %eax /* Return value in %eax. */
1963 * grub_vbe_status_t grub_vbe_bios_set_display_start (grub_uint32_t x,
1966 * Register allocations for parameters:
1970 FUNCTION(grub_vbe_bios_set_display_start)
1974 movl %eax, %ecx /* Store x in %ecx. */
1980 movw $0x0080, %bx /* BL = 80h, Set Display Start
1981 during Vertical Retrace. */
1984 movw %ax, %dx /* real_to_prot destroys %eax. */
1986 DATA32 call real_to_prot
1990 andl $0xFFFF, %eax /* Return value in %eax. */
1997 * grub_vbe_status_t grub_vbe_bios_get_display_start (grub_uint32_t *x,
2000 * Register allocations for parameters:
2004 FUNCTION(grub_vbe_bios_get_display_start)
2008 pushl %eax /* Push *x to stack. */
2009 pushl %edx /* Push *y to stack. */
2015 movw $0x0001, %bx /* BL = 1, Get Display Start. */
2018 movw %ax, %bx /* real_to_prot destroys %eax. */
2020 DATA32 call real_to_prot
2023 popl %edi /* Pops *y from stack to %edi. */
2025 movl %edx, (%edi) /* Return y-position to caller. */
2027 popl %edi /* Pops *x from stack to %edi. */
2029 movl %ecx, (%edi) /* Return x-position to caller. */
2032 andl $0xFFFF, %eax /* Return value in %eax. */
2040 * grub_vbe_status_t grub_vbe_bios_set_palette_data (grub_uint32_t color_count,
2041 * grub_uint32_t start_index,
2042 * struct grub_vbe_palette_data *palette_data)
2044 * Register allocations for parameters:
2047 * %ecx *palette_data
2049 FUNCTION(grub_vbe_bios_set_palette_data)
2054 movl %eax, %ebx /* Store color_count in %ebx. */
2056 movw %cx, %di /* Store *palette_data to %ecx:%di. */
2065 movw %cx, %es /* *palette_data is now on %es:%di. */
2066 movw %bx, %cx /* color_count is now on %cx. */
2069 xorw %bx, %bx /* BL = 0, Set Palette Data. */
2072 movw %ax, %dx /* real_to_prot destroys %eax. */
2076 DATA32 call real_to_prot
2080 andl $0xFFFF, %eax /* Return value in %eax. */
2092 * struct grub_pxenv *grub_pxe_scan (void);
2094 FUNCTION(grub_pxe_scan)
2110 cmpl $0x4E455850, %es:(%bx) /* PXEN(V+) */
2112 cmpw $0x201, %es:6(%bx) /* API version */
2114 lesw %es:0x28(%bx), %bx /* !PXE structure */
2115 cmpl $0x45585021, %es:(%bx) /* !PXE */
2126 DATA32 call real_to_prot
2130 leal (%eax, %ecx, 4), %ecx
2131 leal (%ebx, %ecx, 4), %eax /* eax = ecx * 16 + ebx */
2136 movl 0x10(%eax), %ecx
2137 movl %ecx, pxe_rm_entry
2146 * int grub_pxe_call (int func, void* data);
2148 FUNCTION(grub_pxe_call)
2161 movl pxe_rm_entry, %ebx
2175 DATA32 call real_to_prot