diff --git a/conf/i386-pc.rmk b/conf/i386-pc.rmk index 59fc6a3..f779414 100644 --- a/conf/i386-pc.rmk +++ b/conf/i386-pc.rmk @@ -162,7 +162,7 @@ pkglib_MODULES = biosdisk.mod _chain.mod _linux.mod linux.mod normal.mod \ aout.mod _bsd.mod bsd.mod pxe.mod pxecmd.mod # For biosdisk.mod. -biosdisk_mod_SOURCES = disk/i386/pc/biosdisk.c +biosdisk_mod_SOURCES = disk/i386/pc/biosdisk.c disk/i386/pc/biosdisk_stub.S biosdisk_mod_CFLAGS = $(COMMON_CFLAGS) biosdisk_mod_LDFLAGS = $(COMMON_LDFLAGS) diff --git a/disk/i386/pc/biosdisk_stub.S b/disk/i386/pc/biosdisk_stub.S new file mode 100644 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 a00117b..fde9525 100644 --- a/include/grub/i386/pc/kernel.h +++ b/include/grub/i386/pc/kernel.h @@ -86,6 +86,19 @@ 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); +struct grub_real_stub +{ + void *address; + grub_uint32_t length; +}; + +void* EXPORT_FUNC(grub_alloc_real_stub) (int size); +void* EXPORT_FUNC(grub_alloc_real_stub_align) (int size, int align); + +void EXPORT_FUNC(grub_call_real_stub) (struct grub_real_stub *stub); +void EXPORT_FUNC(grub_call_real_stub_align) (struct grub_real_stub *stub, + int align); + #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..eef966f 100644 --- a/include/grub/symbol.h +++ b/include/grub/symbol.h @@ -43,4 +43,13 @@ # define EXPORT_VAR(x) x #endif /* ! GRUB_SYMBOL_GENERATOR */ +#define REAL_STUB_START(x) x ## _stub: ; \ + .long x ## _start ; \ + .long x ## _end - x ## _start ; \ +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..8e7c68d 100644 --- a/kern/i386/pc/startup.S +++ b/kern/i386/pc/startup.S @@ -618,357 +618,157 @@ 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/data to address below 1M. * - * This starts another boot loader. + * On entry, %eax should points to a structure that specifies the code/data to + * be copied: + * + * offset 0: address of code/data + * offset 4: size of code/data + * + * grub_copy_real_stub fetches the address from offset 0, if it's not below 1M or + * properly aligned, it copies it to a reserved area and updates the address at + * offset 0, so that it don't need to do it again the next time. + * + * Currently, the reserved area for stub code/data is 0x80000 - 0x88000. It + * should be big enough for assembly code. */ -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) + * Allocate memory from the stub area. * - * 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. + * void* grub_alloc_real_stub (int size); + * void* grub_alloc_real_stub_align (int size, int align); */ -FUNCTION(grub_biosdisk_rw_int13_extensions) - pushl %ebp - pushl %esi +FUNCTION(grub_alloc_real_stub) + movl $1, %edx - /* compute the address of disk_address_packet */ - movw %cx, %si - xorw %cx, %cx - shrl $4, %ecx /* save the segment to cx */ +FUNCTION(grub_alloc_real_stub_align) + decl %edx - /* ah */ - movb %al, %dh - /* enter real mode */ - call prot_to_real +grub_alloc_real_stub_1: + movl %eax, %ecx + movl real_stub_addr, %eax - .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 + addl %edx, %eax + notl %edx + andl %edx, %eax - movb %dl, %al /* return value in %eax */ + leal (%eax, %ecx), %edx + cmpl $GRUB_MEMORY_MACHINE_REAL_STUB_END, %edx + ja EXT_C(grub_stop) - popl %esi - popl %ebp + movl %edx, real_stub_addr ret /* - * int grub_biosdisk_rw_standard (int ah, int drive, int coff, int hoff, - * int soff, int nsec, int segment) + * Test the address in stub, if it's above 1M or not properly aligned, + * allocate memory from the stub area and copy the code. Then, it switches + * to real mode and execute. * - * 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. + * void grub_call_real_stub (struct grub_real_stub *stub); + * void grub_call_real_stub_align (struct grub_real_stub *stub, + * int align); */ -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 - - /* enter real mode */ - call prot_to_real +FUNCTION(grub_call_real_stub) + pushl %edx + xorl %edx, %edx + jmp 1f - .code16 - movw %bx, %es - xorw %bx, %bx - movw $3, %si /* attempt at least three times */ +FUNCTION(grub_call_real_stub_align) + pushl %edx + decl %edx 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: - /* back to protected mode */ - DATA32 call real_to_prot - .code32 - - movb %bl, %al /* return value in %eax */ - - popl %esi - popl %edi - popl %ebx - popl %ebp + pushl %ecx - ret $(4 * 4) + /* Test if it's below 1M. */ + movl (%eax), %ecx + cmpl $GRUB_MEMORY_MACHINE_UPPER, %ecx + jae 1f + /* Test if it's aligned properly. */ + testl %edx, %ecx + jz 2f -/* - * 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. - */ +1: + pushl %esi + pushl %edi + pushl %eax -FUNCTION(grub_biosdisk_check_int13_extensions) - pushl %ebp - pushl %ebx + movl %ecx, %esi + movl 4(%eax), %eax - /* drive */ - movb %al, %dl - /* enter real mode */ - call prot_to_real + call grub_alloc_real_stub_1 - .code16 - movb $0x41, %ah - movw $0x55aa, %bx - int $0x13 /* do the operation */ + /* On return, %ecx will contain the length. */ - /* check the result */ - jc 1f - cmpw $0xaa55, %bx - jne 1f + movl %eax, %edi + xchgl %eax, (%esp) + movl %edi, (%eax) - movb %ah, %bl /* save the major version into %bl */ + cld + rep movsb - /* check if AH=0x42 is supported */ - andw $1, %cx - jnz 2f + popl %ecx + popl %edi + popl %esi -1: - xorb %bl, %bl 2: - /* back to protected mode */ - DATA32 call real_to_prot - .code32 + shll $12, %ecx + shrw $12, %cx - movb %bl, %al /* return value in %eax */ + movl %ecx, GRUB_MEMORY_MACHINE_REAL_STACK + 0x10 - 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 + popl %ecx + popl %edx - /* 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 */ + lcall *(GRUB_MEMORY_MACHINE_REAL_STACK + 0x10) - popl %esi - popl %ebx - popl %ebp + DATA32 call real_to_prot + .code32 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" /* *