diff --git a/conf/i386-pc.rmk b/conf/i386-pc.rmk index 59fc6a3..fd58e17 100644 --- a/conf/i386-pc.rmk +++ b/conf/i386-pc.rmk @@ -154,7 +154,7 @@ grub_install_SOURCES = util/i386/pc/grub-install.in grub_mkrescue_SOURCES = util/i386/pc/grub-mkrescue.in # Modules. -pkglib_MODULES = biosdisk.mod _chain.mod _linux.mod linux.mod normal.mod \ +pkglib_MODULES = biosdisk.mod biosdisk_stub.mod _chain.mod _linux.mod linux.mod normal.mod \ _multiboot.mod chain.mod multiboot.mod reboot.mod halt.mod \ vbe.mod vbetest.mod vbeinfo.mod video.mod gfxterm.mod \ videotest.mod play.mod bitmap.mod tga.mod cpuid.mod serial.mod \ @@ -166,6 +166,16 @@ biosdisk_mod_SOURCES = disk/i386/pc/biosdisk.c biosdisk_mod_CFLAGS = $(COMMON_CFLAGS) biosdisk_mod_LDFLAGS = $(COMMON_LDFLAGS) +# For biosdisk_stub.mod. +biosdisk_stub_mod_SOURCES = disk/i386/pc/biosdisk_stub.S +biosdisk_stub_mod_CFLAGS = $(COMMON_CFLAGS) +biosdisk_stub_mod_LDFLAGS = $(COMMON_LDFLAGS) + +# For biosdiskstub.mod. +biosdiskstub_mod_SOURCES = disk/i386/pc/biosdisk.c +biosdiskstub_mod_CFLAGS = $(COMMON_CFLAGS) +biosdisk_mod_LDFLAGS = $(COMMON_LDFLAGS) + # For _chain.mod. _chain_mod_SOURCES = loader/i386/pc/chainloader.c _chain_mod_CFLAGS = $(COMMON_CFLAGS) diff --git a/disk/i386/pc/biosdisk_stub.S b/disk/i386/pc/biosdisk_stub.S new file mode 100755 index 0000000..05536c6 --- /dev/null +++ b/disk/i386/pc/biosdisk_stub.S @@ -0,0 +1,344 @@ +/* + * GRUB -- GRand Unified Bootloader + * Copyright (C) 2008 Free Software Foundation, Inc. + * + * GRUB 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 3 of the License, or + * (at your option) any later version. + * + * GRUB 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 GRUB. If not, see . + */ + +#define ASM_FILE 1 + +#include +#include + +/* + * int grub_biosdisk_rw_int13_extensions (int ah, int drive, void *dap) + * + * Call IBM/MS INT13 Extensions (int 13 %ah=AH) for DRIVE. DAP + * is passed for disk address packet. If an error occurs, return + * non-zero, otherwise zero. + */ + +REAL_STUB_START(grub_biosdisk_rw_int13_extensions) + movb %dh, %ah + movw %cx, %ds + int $0x13 /* do the operation */ + movb %ah, %dl /* save return value */ + lret +REAL_STUB_END(grub_biosdisk_rw_int13_extensions) + +FUNCTION(grub_biosdisk_rw_int13_extensions) + pushl %ebp + pushl %esi + + /* compute the address of disk_address_packet */ + movw %cx, %si + xorw %cx, %cx + shrl $4, %ecx /* save the segment to cx */ + + /* ah */ + movb %al, %dh + + leal grub_biosdisk_rw_int13_extensions_stub, %eax + call EXT_C(grub_call_real_stub) + + movb %dl, %al /* return value in %eax */ + + popl %esi + popl %ebp + + ret + +/* + * int grub_biosdisk_rw_standard (int ah, int drive, int coff, int hoff, + * int soff, int nsec, int segment) + * + * Call standard and old INT13 (int 13 %ah=AH) for DRIVE. Read/write + * NSEC sectors from COFF/HOFF/SOFF into SEGMENT. If an error occurs, + * return non-zero, otherwise zero. + */ + +REAL_STUB_START(grub_biosdisk_rw_standard) + movw %bx, %es + xorw %bx, %bx + movw $3, %si /* attempt at least three times */ + +1: + movw %di, %ax + int $0x13 /* do the operation */ + jnc 2f /* check if successful */ + + movb %ah, %bl /* save return value */ + /* if fail, reset the disk system */ + xorw %ax, %ax + int $0x13 + + decw %si + cmpw $0, %si + je 2f + xorb %bl, %bl + jmp 1b /* retry */ +2: + lret +REAL_STUB_END(grub_biosdisk_rw_standard) + +FUNCTION(grub_biosdisk_rw_standard) + pushl %ebp + movl %esp, %ebp + + pushl %ebx + pushl %edi + pushl %esi + + /* set up CHS information */ + + /* set %ch to low eight bits of cylinder */ + xchgb %cl, %ch + /* set bits 6-7 of %cl to high two bits of cylinder */ + shlb $6, %cl + /* set bits 0-5 of %cl to sector */ + addb 0xc(%ebp), %cl + /* set %dh to head */ + movb 0x8(%ebp), %dh + /* set %ah to AH */ + movb %al, %ah + /* set %al to NSEC */ + movb 0x10(%ebp), %al + /* save %ax in %di */ + movw %ax, %di + /* save SEGMENT in %bx */ + movw 0x14(%ebp), %bx + + leal grub_biosdisk_rw_standard_stub, %eax + call EXT_C(grub_call_real_stub) + + movb %bl, %al /* return value in %eax */ + + popl %esi + popl %edi + popl %ebx + popl %ebp + + ret $(4 * 4) + + +/* + * int grub_biosdisk_check_int13_extensions (int drive) + * + * Check if LBA is supported for DRIVE. If it is supported, then return + * the major version of extensions, otherwise zero. + */ + +REAL_STUB_START(grub_biosdisk_check_int13_extensions) + movb $0x41, %ah + movw $0x55aa, %bx + int $0x13 /* do the operation */ + + /* check the result */ + jc 1f + cmpw $0xaa55, %bx + jne 1f + + movb %ah, %bl /* save the major version into %bl */ + + /* check if AH=0x42 is supported */ + andw $1, %cx + jnz 2f + +1: + xorb %bl, %bl +2: + lret +REAL_STUB_END(grub_biosdisk_check_int13_extensions) + +FUNCTION(grub_biosdisk_check_int13_extensions) + pushl %ebp + pushl %ebx + + /* drive */ + movb %al, %dl + + leal grub_biosdisk_check_int13_extensions_stub, %eax + call EXT_C(grub_call_real_stub) + + movb %bl, %al /* return value in %eax */ + + popl %ebx + popl %ebp + + ret + + +/* + * int grub_biosdisk_get_cdinfo_int13_extensions (int drive, void *cdrp) + * + * Return the cdrom information of DRIVE in CDRP. If an error occurs, + * then return non-zero, otherwise zero. + */ + +FUNCTION(grub_biosdisk_get_cdinfo_int13_extensions) + movw $0x4B01, %cx + jmp 1f + +/* + * int grub_biosdisk_get_diskinfo_int13_extensions (int drive, void *drp) + * + * Return the geometry of DRIVE in a drive parameters, DRP. If an error + * occurs, then return non-zero, otherwise zero. + */ + +REAL_STUB_START(grub_biosdisk_get_diskinfo_int13_extensions) + movw %cx, %ax + movw %bx, %ds + int $0x13 /* do the operation */ + movb %ah, %bl /* save return value in %bl */ + lret +REAL_STUB_END(grub_biosdisk_get_diskinfo_int13_extensions) + +FUNCTION(grub_biosdisk_get_diskinfo_int13_extensions) + movb $0x48, %ch +1: + pushl %ebp + pushl %ebx + pushl %esi + + /* compute the address of drive parameters */ + movw %dx, %si + andl $0xf, %esi + shrl $4, %edx + movw %dx, %bx /* save the segment into %bx */ + /* drive */ + movb %al, %dl + + leal grub_biosdisk_get_diskinfo_int13_extensions_stub, %eax + call EXT_C(grub_call_real_stub) + + movb %bl, %al /* return value in %eax */ + + popl %esi + popl %ebx + popl %ebp + + ret + + +/* + * int grub_biosdisk_get_diskinfo_standard (int drive, + * unsigned long *cylinders, + * unsigned long *heads, + * unsigned long *sectors) + * + * Return the geometry of DRIVE in CYLINDERS, HEADS and SECTORS. If an + * error occurs, then return non-zero, otherwise zero. + */ +REAL_STUB_START(grub_biosdisk_get_diskinfo_standard) + movb $0x8, %ah + int $0x13 /* do the operation */ + /* check if successful */ + testb %ah, %ah + jnz 1f + /* bogus BIOSes may not return an error number */ + testb $0x3f, %cl /* 0 sectors means no disk */ + jnz 1f /* if non-zero, then succeed */ + /* XXX 0x60 is one of the unused error numbers */ + movb $0x60, %ah +1: + movb %ah, %bl /* save return value in %bl */ + lret +REAL_STUB_END(grub_biosdisk_get_diskinfo_standard) + +FUNCTION(grub_biosdisk_get_diskinfo_standard) + pushl %ebp + pushl %ebx + pushl %edi + + /* push CYLINDERS */ + pushl %edx + /* push HEADS */ + pushl %ecx + /* SECTORS is on the stack */ + + /* drive */ + movb %al, %dl + + leal grub_biosdisk_get_diskinfo_standard_stub, %eax + call EXT_C(grub_call_real_stub) + + /* pop HEADS */ + popl %edi + movb %dh, %al + incl %eax /* the number of heads is counted from zero */ + movl %eax, (%edi) + + /* pop CYLINDERS */ + popl %edi + movb %ch, %al + movb %cl, %ah + shrb $6, %ah /* the number of cylinders is counted from zero */ + incl %eax + movl %eax, (%edi) + + /* SECTORS */ + movl 0x10(%esp), %edi + andb $0x3f, %cl + movzbl %cl, %eax + movl %eax, (%edi) + + xorl %eax, %eax + movb %bl, %al /* return value in %eax */ + + popl %edi + popl %ebx + popl %ebp + + ret $4 + + +/* + * int grub_biosdisk_get_num_floppies (void) + */ + +REAL_STUB_START(grub_biosdisk_get_num_floppies) + /* reset the disk system first */ + int $0x13 +1: + stc + + /* call GET DISK TYPE */ + movb $0x15, %ah + int $0x13 + + jc 2f + + /* check if this drive exists */ + testb $0x3, %ah + jz 2f + + incb %dl + cmpb $2, %dl + jne 1b +2: + lret +REAL_STUB_END(grub_biosdisk_get_num_floppies) + +FUNCTION(grub_biosdisk_get_num_floppies) + pushl %ebp + + xorl %edx, %edx + + leal grub_biosdisk_get_num_floppies_stub, %eax + call EXT_C(grub_call_real_stub) + + movl %edx, %eax + popl %ebp + ret diff --git a/include/grub/i386/pc/biosdisk.h b/include/grub/i386/pc/biosdisk.h index 05d5dc5..da82116 100644 --- a/include/grub/i386/pc/biosdisk.h +++ b/include/grub/i386/pc/biosdisk.h @@ -106,19 +106,19 @@ struct grub_biosdisk_dap grub_uint64_t block; } __attribute__ ((packed)); -int EXPORT_FUNC(grub_biosdisk_rw_int13_extensions) (int ah, int drive, void *dap); -int EXPORT_FUNC(grub_biosdisk_rw_standard) (int ah, int drive, int coff, int hoff, +int grub_biosdisk_rw_int13_extensions (int ah, int drive, void *dap); +int grub_biosdisk_rw_standard (int ah, int drive, int coff, int hoff, int soff, int nsec, int segment); -int EXPORT_FUNC(grub_biosdisk_check_int13_extensions) (int drive); -int EXPORT_FUNC(grub_biosdisk_get_diskinfo_int13_extensions) (int drive, +int grub_biosdisk_check_int13_extensions (int drive); +int grub_biosdisk_get_diskinfo_int13_extensions (int drive, void *drp); -int EXPORT_FUNC(grub_biosdisk_get_cdinfo_int13_extensions) (int drive, +int grub_biosdisk_get_cdinfo_int13_extensions (int drive, void *cdrp); -int EXPORT_FUNC(grub_biosdisk_get_diskinfo_standard) (int drive, +int grub_biosdisk_get_diskinfo_standard (int drive, unsigned long *cylinders, unsigned long *heads, unsigned long *sectors); -int EXPORT_FUNC(grub_biosdisk_get_num_floppies) (void); +int grub_biosdisk_get_num_floppies (void); void grub_biosdisk_init (void); void grub_biosdisk_fini (void); diff --git a/include/grub/i386/pc/kernel.h b/include/grub/i386/pc/kernel.h index 402faa3..3c205ac 100644 --- a/include/grub/i386/pc/kernel.h +++ b/include/grub/i386/pc/kernel.h @@ -86,6 +86,8 @@ extern grub_addr_t grub_end_addr; extern grub_addr_t EXPORT_FUNC(grub_arch_memdisk_addr) (void); extern grub_off_t EXPORT_FUNC(grub_arch_memdisk_size) (void); +void EXPORT_FUNC(grub_call_real_stub) (void); + #endif /* ! ASM_FILE */ #endif /* ! KERNEL_MACHINE_HEADER */ diff --git a/include/grub/i386/pc/memory.h b/include/grub/i386/pc/memory.h index a3e3ed7..55d5dcb 100644 --- a/include/grub/i386/pc/memory.h +++ b/include/grub/i386/pc/memory.h @@ -45,12 +45,17 @@ (GRUB_MEMORY_MACHINE_SCRATCH_ADDR + GRUB_MEMORY_MACHINE_SCRATCH_SIZE \ + GRUB_MEMORY_MACHINE_PROT_STACK_SIZE - 0x10) +#define GRUB_MEMORY_MACHINE_REAL_STUB_START (GRUB_MEMORY_MACHINE_PROT_STACK + 0x10) +#define GRUB_MEMORY_MACHINE_REAL_STUB_SIZE 0x8000 +#define GRUB_MEMORY_MACHINE_REAL_STUB_END \ + (GRUB_MEMORY_MACHINE_REAL_STUB_START + GRUB_MEMORY_MACHINE_REAL_STUB_SIZE) + /* The memory area where GRUB uses its own purpose. This part is not added into free memory for dynamic allocations. */ #define GRUB_MEMORY_MACHINE_RESERVED_START \ GRUB_MEMORY_MACHINE_SCRATCH_ADDR #define GRUB_MEMORY_MACHINE_RESERVED_END \ - (GRUB_MEMORY_MACHINE_PROT_STACK + 0x10) + GRUB_MEMORY_MACHINE_REAL_STUB_END /* The area where GRUB is decompressed at early startup. */ #define GRUB_MEMORY_MACHINE_DECOMPRESSION_ADDR 0x100000 diff --git a/include/grub/symbol.h b/include/grub/symbol.h index e951490..6fd161a 100644 --- a/include/grub/symbol.h +++ b/include/grub/symbol.h @@ -43,4 +43,14 @@ # define EXPORT_VAR(x) x #endif /* ! GRUB_SYMBOL_GENERATOR */ +#define REAL_STUB_START(x) x ## _stub: ; \ + .long x ## _start ; \ + .long x ## _end - x ## _start ; \ + .long 0 ; \ +x ## _start: ; \ + .code16 + +#define REAL_STUB_END(x) .code32 ; \ +x ## _end: + #endif /* ! GRUB_SYMBOL_HEADER */ diff --git a/kern/i386/pc/startup.S b/kern/i386/pc/startup.S index 679ad1f..5b1a2a1 100644 --- a/kern/i386/pc/startup.S +++ b/kern/i386/pc/startup.S @@ -618,357 +618,134 @@ FUNCTION(grub_halt) jmp EXT_C(grub_hard_stop) .code32 +real_stub_addr: + .long GRUB_MEMORY_MACHINE_REAL_STUB_START /* - * void grub_chainloader_real_boot (int drive, void *part_addr) + * Copy code to address below 1M, switch to real mode and execute. * - * This starts another boot loader. - */ - -FUNCTION(grub_chainloader_real_boot) - pushl %edx - pushl %eax - - call EXT_C(grub_dl_unload_all) - - /* Turn off Gate A20 */ - xorl %eax, %eax - call EXT_C(grub_gate_a20) - - /* set up to pass boot drive */ - popl %edx - - /* ESI must point to a partition table entry */ - popl %esi - - call prot_to_real - .code16 - ljmp $0, $GRUB_MEMORY_MACHINE_BOOT_LOADER_ADDR - .code32 - -#include "../loader.S" - -/* - * int grub_biosdisk_rw_int13_extensions (int ah, int drive, void *dap) + * On entry, %eax should points to a structure that specifies the code to be + * copied: + * + * offset 0: address of code + * offset 4: size of code + * offset 8: mapped address + * + * To avoid unnecessary memory transfer, it replaces the code address with + * mapped address, so that it can be used directly the next time. + * + * The real mode stub also holds the address of the structure directly before + * its code. This is used for verification. When the stub area is full, we + * zero it and start again. This would invalidate all mapped block so that + * they must be copied again when used. * - * Call IBM/MS INT13 Extensions (int 13 %ah=AH) for DRIVE. DAP - * is passed for disk address packet. If an error occurs, return - * non-zero, otherwise zero. */ -FUNCTION(grub_biosdisk_rw_int13_extensions) - pushl %ebp - pushl %esi - - /* compute the address of disk_address_packet */ - movw %cx, %si - xorw %cx, %cx - shrl $4, %ecx /* save the segment to cx */ - - /* ah */ - movb %al, %dh - /* enter real mode */ - call prot_to_real +FUNCTION(grub_call_real_stub) + pushl %edi - .code16 - movb %dh, %ah - movw %cx, %ds - int $0x13 /* do the operation */ - movb %ah, %dl /* save return value */ - /* back to protected mode */ - DATA32 call real_to_prot - .code32 + /* Test if we need to map it. */ + movl (%eax), %edi + cmpl $GRUB_MEMORY_MACHINE_UPPER, %edi + jb 3f - movb %dl, %al /* return value in %eax */ + /* Test if we already map it. */ + movl 8(%eax), %edi + orl %edi, %edi + jz 1f - popl %esi - popl %ebp + /* Test if the mapped block is valid. */ + cmpl %eax, -4(%edi) + jz 3f - ret +1: + pushl %esi + pushl %ecx -/* - * int grub_biosdisk_rw_standard (int ah, int drive, int coff, int hoff, - * int soff, int nsec, int segment) - * - * Call standard and old INT13 (int 13 %ah=AH) for DRIVE. Read/write - * NSEC sectors from COFF/HOFF/SOFF into SEGMENT. If an error occurs, - * return non-zero, otherwise zero. - */ + cld -FUNCTION(grub_biosdisk_rw_standard) - pushl %ebp - movl %esp, %ebp + movl 4(%eax), %ecx + movl real_stub_addr, %edi + leal 4(%edi, %ecx), %esi + cmpl $GRUB_MEMORY_MACHINE_REAL_STUB_END, %esi + jbe 2f - pushl %ebx + /* The stub area is full, zero it and start again. */ + pushl %ecx + movl $(GRUB_MEMORY_MACHINE_REAL_STUB_SIZE >> 2), %ecx + movl $GRUB_MEMORY_MACHINE_REAL_STUB_START, %edi pushl %edi - pushl %esi + pushl %eax - /* set up CHS information */ - - /* set %ch to low eight bits of cylinder */ - xchgb %cl, %ch - /* set bits 6-7 of %cl to high two bits of cylinder */ - shlb $6, %cl - /* set bits 0-5 of %cl to sector */ - addb 0xc(%ebp), %cl - /* set %dh to head */ - movb 0x8(%ebp), %dh - /* set %ah to AH */ - movb %al, %ah - /* set %al to NSEC */ - movb 0x10(%ebp), %al - /* save %ax in %di */ - movw %ax, %di - /* save SEGMENT in %bx */ - movw 0x14(%ebp), %bx - - /* enter real mode */ - call prot_to_real + xorl %eax, %eax + rep stosl - .code16 - movw %bx, %es - xorw %bx, %bx - movw $3, %si /* attempt at least three times */ + popl %edi + popl %eax + popl %ecx -1: - movw %di, %ax - int $0x13 /* do the operation */ - jnc 2f /* check if successful */ +2: + stosl - movb %ah, %bl /* save return value */ - /* if fail, reset the disk system */ - xorw %ax, %ax - int $0x13 + pushl %edi + movl %edi, 8(%eax) - decw %si - cmpw $0, %si - je 2f - xorb %bl, %bl - jmp 1b /* retry */ -2: - /* back to protected mode */ - DATA32 call real_to_prot - .code32 + movl (%eax), %esi + rep movsb - movb %bl, %al /* return value in %eax */ + movl %edi, real_stub_addr - popl %esi popl %edi - popl %ebx - popl %ebp - ret $(4 * 4) + popl %ecx + popl %esi +3: -/* - * int grub_biosdisk_check_int13_extensions (int drive) - * - * Check if LBA is supported for DRIVE. If it is supported, then return - * the major version of extensions, otherwise zero. - */ + shll $12, %edi + shrw $12, %di -FUNCTION(grub_biosdisk_check_int13_extensions) - pushl %ebp - pushl %ebx + movl %edi, GRUB_MEMORY_MACHINE_REAL_STACK + 0x10 + popl %edi - /* drive */ - movb %al, %dl - /* enter real mode */ call prot_to_real - .code16 - movb $0x41, %ah - movw $0x55aa, %bx - int $0x13 /* do the operation */ - /* check the result */ - jc 1f - cmpw $0xaa55, %bx - jne 1f + lcall *(GRUB_MEMORY_MACHINE_REAL_STACK + 0x10) - movb %ah, %bl /* save the major version into %bl */ - - /* check if AH=0x42 is supported */ - andw $1, %cx - jnz 2f - -1: - xorb %bl, %bl -2: - /* back to protected mode */ DATA32 call real_to_prot .code32 - movb %bl, %al /* return value in %eax */ - - popl %ebx - popl %ebp - ret - -/* - * int grub_biosdisk_get_cdinfo_int13_extensions (int drive, void *cdrp) - * - * Return the cdrom information of DRIVE in CDRP. If an error occurs, - * then return non-zero, otherwise zero. - */ - -FUNCTION(grub_biosdisk_get_cdinfo_int13_extensions) - movw $0x4B01, %cx - jmp 1f - /* - * int grub_biosdisk_get_diskinfo_int13_extensions (int drive, void *drp) - * - * Return the geometry of DRIVE in a drive parameters, DRP. If an error - * occurs, then return non-zero, otherwise zero. - */ - -FUNCTION(grub_biosdisk_get_diskinfo_int13_extensions) - movb $0x48, %ch -1: - pushl %ebp - pushl %ebx - pushl %esi - - /* compute the address of drive parameters */ - movw %dx, %si - andl $0xf, %esi - shrl $4, %edx - movw %dx, %bx /* save the segment into %bx */ - /* drive */ - movb %al, %dl - /* enter real mode */ - call prot_to_real - - .code16 - movw %cx, %ax - movw %bx, %ds - int $0x13 /* do the operation */ - movb %ah, %bl /* save return value in %bl */ - /* back to protected mode */ - DATA32 call real_to_prot - .code32 - - movb %bl, %al /* return value in %eax */ - - popl %esi - popl %ebx - popl %ebp - - ret - - -/* - * int grub_biosdisk_get_diskinfo_standard (int drive, - * unsigned long *cylinders, - * unsigned long *heads, - * unsigned long *sectors) + * void grub_chainloader_real_boot (int drive, void *part_addr) * - * Return the geometry of DRIVE in CYLINDERS, HEADS and SECTORS. If an - * error occurs, then return non-zero, otherwise zero. + * This starts another boot loader. */ -FUNCTION(grub_biosdisk_get_diskinfo_standard) - pushl %ebp - pushl %ebx - pushl %edi - - /* push CYLINDERS */ +FUNCTION(grub_chainloader_real_boot) pushl %edx - /* push HEADS */ - pushl %ecx - /* SECTORS is on the stack */ - - /* drive */ - movb %al, %dl - /* enter real mode */ - call prot_to_real - - .code16 - movb $0x8, %ah - int $0x13 /* do the operation */ - /* check if successful */ - testb %ah, %ah - jnz 1f - /* bogus BIOSes may not return an error number */ - testb $0x3f, %cl /* 0 sectors means no disk */ - jnz 1f /* if non-zero, then succeed */ - /* XXX 0x60 is one of the unused error numbers */ - movb $0x60, %ah -1: - movb %ah, %bl /* save return value in %bl */ - /* back to protected mode */ - DATA32 call real_to_prot - .code32 - - /* pop HEADS */ - popl %edi - movb %dh, %al - incl %eax /* the number of heads is counted from zero */ - movl %eax, (%edi) - - /* pop CYLINDERS */ - popl %edi - movb %ch, %al - movb %cl, %ah - shrb $6, %ah /* the number of cylinders is counted from zero */ - incl %eax - movl %eax, (%edi) + pushl %eax - /* SECTORS */ - movl 0x10(%esp), %edi - andb $0x3f, %cl - movzbl %cl, %eax - movl %eax, (%edi) + call EXT_C(grub_dl_unload_all) + /* Turn off Gate A20 */ xorl %eax, %eax - movb %bl, %al /* return value in %eax */ - - popl %edi - popl %ebx - popl %ebp - - ret $4 + call EXT_C(grub_gate_a20) + /* set up to pass boot drive */ + popl %edx -/* - * int grub_biosdisk_get_num_floppies (void) - */ -FUNCTION(grub_biosdisk_get_num_floppies) - pushl %ebp + /* ESI must point to a partition table entry */ + popl %esi - xorl %edx, %edx call prot_to_real - .code16 - /* reset the disk system first */ - int $0x13 -1: - stc - - /* call GET DISK TYPE */ - movb $0x15, %ah - int $0x13 - - jc 2f - - /* check if this drive exists */ - testb $0x3, %ah - jz 2f - - incb %dl - cmpb $2, %dl - jne 1b -2: - DATA32 call real_to_prot + ljmp $0, $GRUB_MEMORY_MACHINE_BOOT_LOADER_ADDR .code32 - movl %edx, %eax - popl %ebp - ret - +#include "../loader.S" /* *