kern/env.c \
term/i386/pc/console.c term/i386/vga_common.c \
symlist.c
-kernel_img_HEADERS += machine/biosdisk.h machine/pxe.h i386/pit.h \
- machine/init.h machine/int.h
+kernel_img_HEADERS += machine/pxe.h i386/pit.h machine/int.h
kernel_img_CFLAGS = $(COMMON_CFLAGS) $(TARGET_IMG_CFLAGS)
kernel_img_ASFLAGS = $(COMMON_ASFLAGS)
kernel_img_LDFLAGS = $(COMMON_LDFLAGS) $(TARGET_IMG_LDFLAGS)$(GRUB_KERNEL_MACHINE_LINK_ADDR) $(COMMON_CFLAGS)
return (regs.eax >> 8) & 0xff;
}
+/*
+ * 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.
+ */
+static int
+grub_biosdisk_rw_standard (int ah, int drive, int coff, int hoff,
+ int soff, int nsec, int segment)
+{
+ int ret, i;
+
+ /* Try 3 times. */
+ for (i = 0; i < 3; i++)
+ {
+ struct grub_bios_int_registers regs;
+
+ /* set up CHS information */
+ /* set %ch to low eight bits of cylinder */
+ regs.ecx = (coff << 8) & 0xff00;
+ /* set bits 6-7 of %cl to high two bits of cylinder */
+ regs.ecx |= (coff >> 2) & 0xc0;
+ /* set bits 0-5 of %cl to sector */
+ regs.ecx |= soff & 0x3f;
+
+ /* set %dh to head and %dl to drive */
+ regs.edx = (drive & 0xff) | ((hoff << 8) & 0xff00);
+ /* set %ah to AH */
+ regs.eax = (ah << 8) & 0xff00;
+ /* set %al to NSEC */
+ regs.eax |= nsec & 0xff;
+
+ regs.ebx = 0;
+ regs.es = segment;
+
+ regs.flags = GRUB_CPU_INT_FLAGS_DEFAULT;
+
+ grub_bios_interrupt (0x13, ®s);
+ /* check if successful */
+ if (!(regs.flags & GRUB_CPU_INT_FLAGS_CARRY))
+ return 0;
+
+ /* save return value */
+ ret = regs.eax >> 8;
+
+ /* if fail, reset the disk system */
+ regs.eax = 0;
+ regs.edx = (drive & 0xff);
+ regs.flags = GRUB_CPU_INT_FLAGS_DEFAULT;
+ grub_bios_interrupt (0x13, ®s);
+ }
+ return ret;
+}
+
+/*
+ * Check if LBA is supported for DRIVE. If it is supported, then return
+ * the major version of extensions, otherwise zero.
+ */
+static int
+grub_biosdisk_check_int13_extensions (int drive)
+{
+ struct grub_bios_int_registers regs;
+
+ regs.edx = drive & 0xff;
+ regs.eax = 0x4100;
+ regs.ebx = 0x55aa;
+ regs.flags = GRUB_CPU_INT_FLAGS_DEFAULT;
+ grub_bios_interrupt (0x13, ®s);
+
+ if (regs.flags & GRUB_CPU_INT_FLAGS_CARRY)
+ return 0;
+
+ if ((regs.ebx & 0xffff) != 0xaa55)
+ return 0;
+
+ /* check if AH=0x42 is supported */
+ if (!(regs.ecx & 1))
+ return 0;
+
+ return (regs.eax >> 8) & 0xff;
+}
+
+/*
+ * Return the geometry of DRIVE in CYLINDERS, HEADS and SECTORS. If an
+ * error occurs, then return non-zero, otherwise zero.
+ */
+static int
+grub_biosdisk_get_diskinfo_standard (int drive,
+ unsigned long *cylinders,
+ unsigned long *heads,
+ unsigned long *sectors)
+{
+ struct grub_bios_int_registers regs;
+
+ regs.eax = 0x0800;
+ regs.edx = drive & 0xff;
+
+ regs.flags = GRUB_CPU_INT_FLAGS_DEFAULT;
+ grub_bios_interrupt (0x13, ®s);
+
+ /* Check if unsuccessful. Ignore return value if carry isn't set to
+ workaround some buggy BIOSes. */
+ if ((regs.flags & GRUB_CPU_INT_FLAGS_CARRY) && ((regs.eax & 0xff00) != 0))
+ return (regs.eax & 0xff00) >> 8;
+
+ /* bogus BIOSes may not return an error number */
+ /* 0 sectors means no disk */
+ if (!(regs.ecx & 0x3f))
+ /* XXX 0x60 is one of the unused error numbers */
+ return 0x60;
+
+ /* the number of heads is counted from zero */
+ *heads = ((regs.edx >> 8) & 0xff) + 1;
+ *cylinders = (((regs.ecx >> 8) & 0xff) | ((regs.ecx << 2) & 0x0300)) + 1;
+ *sectors = regs.ecx & 0x3f;
+ return 0;
+}
+
+static int
+grub_biosdisk_get_diskinfo_real (int drive, void *drp, grub_uint16_t ax)
+{
+ struct grub_bios_int_registers regs;
+
+ regs.eax = ax;
+
+ /* compute the address of drive parameters */
+ regs.esi = ((grub_addr_t) drp) & 0xf;
+ regs.ds = ((grub_addr_t) drp) >> 4;
+ regs.edx = drive & 0xff;
+
+ regs.flags = GRUB_CPU_INT_FLAGS_DEFAULT;
+ grub_bios_interrupt (0x13, ®s);
+
+ /* Check if unsuccessful. Ignore return value if carry isn't set to
+ workaround some buggy BIOSes. */
+ if ((regs.flags & GRUB_CPU_INT_FLAGS_CARRY) && ((regs.eax & 0xff00) != 0))
+ return (regs.eax & 0xff00) >> 8;
+
+ return 0;
+}
+
+/*
+ * Return the cdrom information of DRIVE in CDRP. If an error occurs,
+ * then return non-zero, otherwise zero.
+ */
+static int
+grub_biosdisk_get_cdinfo_int13_extensions (int drive, void *cdrp)
+{
+ return grub_biosdisk_get_diskinfo_real (drive, cdrp, 0x4b01);
+}
+
+/*
+ * Return the geometry of DRIVE in a drive parameters, DRP. If an error
+ * occurs, then return non-zero, otherwise zero.
+ */
+static int
+grub_biosdisk_get_diskinfo_int13_extensions (int drive, void *drp)
+{
+ return grub_biosdisk_get_diskinfo_real (drive, drp, 0x4800);
+}
+
static int
grub_biosdisk_get_drive (const char *name)
{
grub_uint64_t block;
} __attribute__ ((packed));
-int EXPORT_FUNC(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,
- void *drp);
-int EXPORT_FUNC(grub_biosdisk_get_cdinfo_int13_extensions) (int drive,
- void *cdrp);
-int EXPORT_FUNC(grub_biosdisk_get_diskinfo_standard) (int drive,
- unsigned long *cylinders,
- unsigned long *heads,
- unsigned long *sectors);
-
void grub_biosdisk_init (void);
void grub_biosdisk_fini (void);
/* Get a memory map entry. Return next continuation value. Zero means
the end. */
-grub_uint32_t EXPORT_FUNC(grub_get_mmap_entry) (struct grub_machine_mmap_entry *entry,
+grub_uint32_t grub_get_mmap_entry (struct grub_machine_mmap_entry *entry,
grub_uint32_t cont);
/* Turn on/off Gate A20. */
#include "../loader.S"
-/*
- * 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.
- */
-
-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
-
- .code16
- 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:
- /* 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
-
- 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.
- */
-
-FUNCTION(grub_biosdisk_check_int13_extensions)
- pushl %ebp
- pushl %ebx
-
- /* 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
-
- 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 */
- jc noclean
- /* Clean return value if carry isn't set to workaround
- some buggy BIOSes. */
- xor %ax, %ax
-noclean:
- 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)
- *
- * Return the geometry of DRIVE in CYLINDERS, HEADS and SECTORS. If an
- * error occurs, then return non-zero, otherwise zero.
- */
-
-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
- /* enter real mode */
- call prot_to_real
-
- .code16
- movb $0x8, %ah
- int $0x13 /* do the operation */
- jc noclean2
- /* Clean return value if carry isn't set to workaround
- some buggy BIOSes. */
- xor %ax, %ax
-noclean2:
- /* 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)
-
- /* 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
-
-
/*
*
* grub_get_memsize(i) : return the memory size in KB. i == 0 for conventional