From 52232721741180be5b6283194615173102e484c9 Mon Sep 17 00:00:00 2001 From: gord Date: Thu, 4 Mar 1999 04:31:30 +0000 Subject: [PATCH] Add LBA support --- ChangeLog | 23 ++++++++ NEWS | 1 + configure.in | 1 - debian/changelog | 6 ++ shared_src/asm.S | 131 +++++++++++++++++++++++++++++++++++-------- shared_src/cmdline.c | 4 +- shared_src/disk_io.c | 7 ++- shared_src/shared.h | 6 +- 8 files changed, 147 insertions(+), 32 deletions(-) diff --git a/ChangeLog b/ChangeLog index 957e7c520..c0b5e498c 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,26 @@ +1999-03-03 Gordon Matzigkeit + + * shared_src/asm.S (biosdisk): Use LBA mode if high nibble of + GEOMETRY is nonzero. + (get_diskinfo): Set high nibble of GEOMETRY (0xf0000000) to 1 if + LBA mode is detected. + +1999-03-02 Gordon Matzigkeit + + * shared_src/disk_io.c (make_saved_active): Use BIOSDISK_READ and + BIOSDISK_WRITE. + + * shared_src/cmdline.c (enter_cmdline): Use BIOSDISK_WRITE. + + * shared_src/shared.h (BIOSDISK_SUBFUNC_READ, + BIOSDISK_SUBFUNC_WRITE): Delete constants. + + * shared_src/asm.S (biosdisk): Change subfunc argument to be + read=0, write=1. + + * configure.in: Drop redundant AC_PROG_INSTALL. From OKUJI + Yoshinori. + 1999-03-01 Gordon Matzigkeit * debian/rules (binary-arch): Properly install README.debian. diff --git a/NEWS b/NEWS index 0ad1fc5ff..a34a83823 100644 --- a/NEWS +++ b/NEWS @@ -3,6 +3,7 @@ NEWS - list of user-visible changes between releases of GRUB New in 0.5.90 - 1999-03-01, Gordon Matzigkeit: * Bug fixes. * GRUB understands symlinks on ext2fs (but still not ffs). +* The GRUB stage2 uses LBA mode and AWARD extensions if they are supported. * Many source code and build cleanups to comply with GNU standards. New in 0.5 - 1998-08-20, Erich Boleyn: diff --git a/configure.in b/configure.in index 42b9aa327..03ef6f9bd 100644 --- a/configure.in +++ b/configure.in @@ -43,7 +43,6 @@ AC_SUBST(stage2debug) # Programs # -AC_PROG_INSTALL AC_CHECK_TOOL(CC, gcc) AC_CHECK_TOOL(LD, ld) AC_CHECK_TOOL(OBJCOPY, objcopy) diff --git a/debian/changelog b/debian/changelog index e72437421..7636817fe 100644 --- a/debian/changelog +++ b/debian/changelog @@ -1,3 +1,9 @@ +grub (0.5.91) unstable; urgency=low + + * Added support for LBA mode and BIOS extensions. + + -- + grub (0.5.90) unstable; urgency=low * Beta-testing release. diff --git a/shared_src/asm.S b/shared_src/asm.S index bff745f63..bd57e6dd5 100644 --- a/shared_src/asm.S +++ b/shared_src/asm.S @@ -330,15 +330,13 @@ realcseg: /* - * biosdisk(subfunc, drive, geometry, sector, nsec, segment) + * biosdisk(write, drive, geometry, sector, nsec, segment) * Read/write "nsec" sectors from disk to real segment "segment" * offset zero * - * If it will fit into the BIOS geometry, it tries the INT 0x13 - * AH= interface, else if it is a hard disk, it will - * try the hard disk LBA calls (not yet implemented). If these - * won't work, or otherwise it is out of the translated area, then - * it returns BIOS_GEOMETRY_ERROR. + * Will try INT 0x13 LBA (AH=0x42/0x43) or standard (AH=0x2/0x3) + * depending on probed geometry. For addresses out of the translated + * area, it returns BIOS_GEOMETRY_ERROR. */ ENTRY(biosdisk) @@ -350,10 +348,56 @@ ENTRY(biosdisk) push %edx push %esi + /* Check whether we have LBA. */ + movb 0x13(%ebp), %al + shrb $4, %al + jz disk_compute_args /* nope. */ + + /* set up disk address packet for extended calls (LBA mode) */ + movl 0x14(%ebp), %eax /* absolute block number */ + movl %eax, dap_block + xorl %eax, %eax + movl %eax, dap_block + 4 + + movb 0x18(%ebp), %al /* number of sectors */ + movw %ax, dap_blocks + + /* set up the buffer address */ + xorl %eax, %eax + movw 0x1c(%ebp), %ax /* segment */ + shll $4, %eax + movl %eax, dap_buffer + movl $disk_address_packet, %esi + + xorb %bl, %bl + movb 0x8(%ebp), %bh /* read=0, write=1 */ + addb $0x42, %bh /* convert to extended subfunction */ + + movb 0xc(%ebp), %dl /* drive */ + + call EXT_C(prot_to_real) /* enter real mode */ + .code16 + + movw %bx, %ax + int $0x13 /* do the operation */ + + /* set success return value */ + movb $0, %bl + + /* did we actually succeed? */ + data32 + jnc disk_exit_16 + + data32 + call EXT_C(real_to_prot) /* back to protected mode */ + .code32 + + /* either failed, or a floppy, so try standard BIOS calls */ +disk_compute_args: /* - * "geometry" is a longword representing the BIOS geometry: - * 6 bit zero - * 10 bit cylinder (bytes 2 & 3) + * GEOMETRY is a longword representing the BIOS geometry: + * 4 bit BIOS extension (0 = none, 1 = LBA) + * 12 bit cylinder (bytes 2 & 3) * 8 bit head (byte 1) * 8 bit sector (byte 0) */ @@ -379,15 +423,27 @@ ENTRY(biosdisk) /* check cylinder offset, is there a geometry problem here? */ movl 0x10(%ebp), %ebx shrl $16, %ebx + andb $0xf, %bh /* mask out bios extension code */ cmpl %ebx, %eax - /* if not, go onto standard read function */ + /* if not, go on to standard read function */ jle disk_use_standard_bios - /* XXX else we better use LBA or generate a geometry error */ movl $BIOSDISK_ERROR_GEOMETRY, %eax jmp disk_exit_32 +disk_address_packet: + .align 4 + .byte 0x20 /* length of packet */ + .byte 0 /* reserved */ +dap_blocks: + .word 0 /* number of blocks */ +dap_buffer: + .long 0 /* buffer address */ +dap_block: + .long 0 /* absolute block number */ + .long 0 + /* * This portion implements the BIOS standardized * INT 0x13/AH= interface. @@ -396,9 +452,10 @@ disk_use_standard_bios: shll $8, %edx /* get head number to %dh */ xchgl %eax, %ecx /* cylinder to %cx, sector to %al */ - /* cylinder; the highest 2 bits of cyl is in %cl */ + /* FIXME: cylinder; bits 10,11 of cyl are in %dh */ + /* cylinder; bits 8,9 of cyl are in %cl */ xchgb %ch, %cl - rorb $2, %cl + shlb $6, %cl incb %al /* sector; sec starts from 1, not 0 */ orb %al, %cl movb 0xc(%ebp), %dl /* drive */ @@ -406,7 +463,8 @@ disk_use_standard_bios: /* prot_to_real will set %es to 0, so must set it ourselves after it is called */ movb 0x18(%ebp), %bl /* number of sectors */ - movb 0x8(%ebp), %bh /* bios disk subfunction */ + movb 0x8(%ebp), %bh /* read=0, write=1 */ + addb $0x2, %bh /* convert to subfunction */ shll $16, %ebx /* shift num sect. and subfunction */ movw 0x1c(%ebp), %bx /* segment */ @@ -528,6 +586,7 @@ probe_loop: movb $1, %dh movb $79, %ch + xorb %bh, %bh /* no BIOS extensions */ data32 jmp probe_success @@ -535,7 +594,27 @@ probe_values: .byte 36, 18, 15, 9, 0 hard_drive: - movb $0x8, %ah /* ask for disk info */ + /* Check for LBA. */ + movb $0x41, %ah + movw $0x55aa, %bx + int $0x13 /* int 13 extensions install check */ + + data32 + jc 1f /* invalid function */ + cmpw $0xaa55, %bx + data32 + jnz 1f /* failed magic */ + + andb $1, %cx + data32 + jnz 1f /* LBA not supported */ + + /* Wahoo! Got LBA! */ + movb $0x1, %bh + jmp 2f + +1: xorb %bh, %bh /* Too bad, no LBA */ +2: movb $0x8, %ah /* ask for disk info */ int $0x13 data32 @@ -546,18 +625,24 @@ hard_drive: probe_success: /* - * form a longword representing all this gunk: - * 6 bit zero - * 10 bit cylinder + * form a dword representing all this gunk: + * 4 bit BIOS extension (0 = none, 1 = LBA) + * 12 bit cylinder * 8 bit head * 8 bit sector */ - movb %cl, %al /* Upper two bits of cylinder count */ - andl $192,%eax - addr32 - leal 0(,%eax,4),%eax /* << 2 */ + movb %bh, %ah /* restore BIOS extensions bits */ + + movb %dh, %al /* bits 10,11 of cylinder count */ + andb $0xc0, %eax + shlw $2, %ax /* << 2 */ + movb %cl, %al /* bits 8,9 of cylinder count */ + andb $0xc0, %al + shlw $2, %ax /* << 2 */ movb %ch, %al /* Lower 8 bits */ - sall $16,%eax /* << 16 */ + shll $16, %eax /* << 16 */ + + andb $0x3f, %ah /* mask of cylinder gunk */ movb %dh, %ah /* max head */ andb $0x3f, %cl /* mask of cylinder gunk */ movb %cl, %al /* max sector (and # sectors) */ diff --git a/shared_src/cmdline.c b/shared_src/cmdline.c index 9449217bc..fc6a6973e 100644 --- a/shared_src/cmdline.c +++ b/shared_src/cmdline.c @@ -450,11 +450,11 @@ returnit: buf_track = -1; if (!errnum - && (biosdisk(BIOSDISK_SUBFUNC_WRITE, + && (biosdisk(BIOSDISK_WRITE, dest_drive, dest_geom, dest_sector, 1, (BOOTSEC_LOCATION>>4)) || (write_stage2_sect - && biosdisk(BIOSDISK_SUBFUNC_WRITE, + && biosdisk(BIOSDISK_WRITE, current_drive, buf_geom, stage2_sect, 1, SCRATCHSEG)))) errnum = ERR_WRITE; diff --git a/shared_src/disk_io.c b/shared_src/disk_io.c index 3bef84a6a..749b4c2df 100644 --- a/shared_src/disk_io.c +++ b/shared_src/disk_io.c @@ -86,6 +86,7 @@ rawread (int drive, int sector, int byte_offset, int byte_len, int addr) if (buf_drive != drive) { buf_geom = get_diskinfo (drive); + printf ("buf_geom = 0x%x\n", buf_geom); /* FIXME */ buf_drive = drive; buf_track = -1; } @@ -118,7 +119,7 @@ rawread (int drive, int sector, int byte_offset, int byte_len, int addr) bufaddr = BUFFERADDR + byte_offset; } - if (bios_err = biosdisk (BIOSDISK_SUBFUNC_READ, drive, buf_geom, + if (bios_err = biosdisk (BIOSDISK_READ, drive, buf_geom, read_start, read_len, BUFFERSEG)) { buf_track = -1; @@ -132,7 +133,7 @@ rawread (int drive, int sector, int byte_offset, int byte_len, int addr) * required sector(s) rather than failing completely. */ if (slen > num_sect - || biosdisk (BIOSDISK_SUBFUNC_READ, drive, buf_geom, + || biosdisk (BIOSDISK_READ, drive, buf_geom, sector, slen, BUFFERSEG)) errnum = ERR_READ; @@ -270,7 +271,7 @@ make_saved_active (void) buf_track = -1; - if (biosdisk (BIOSDISK_SUBFUNC_WRITE, saved_drive, buf_geom, + if (biosdisk (BIOSDISK_WRITE, saved_drive, buf_geom, 0, 1, SCRATCHSEG)) { errnum = ERR_WRITE; diff --git a/shared_src/shared.h b/shared_src/shared.h index 187be48b7..a4c11fe7d 100644 --- a/shared_src/shared.h +++ b/shared_src/shared.h @@ -48,8 +48,8 @@ /* * BIOS disk defines */ -#define BIOSDISK_SUBFUNC_READ 0x2 -#define BIOSDISK_SUBFUNC_WRITE 0x3 +#define BIOSDISK_READ 0x0 +#define BIOSDISK_WRITE 0x1 #define BIOSDISK_ERROR_GEOMETRY 0x100 /* @@ -287,7 +287,7 @@ __attribute__ ((noreturn)); /* low-level disk I/O */ int get_diskinfo (int drive); - int biosdisk (int subfunc, int drive, int geometry, + int biosdisk (int read, int drive, int geometry, int sector, int nsec, int segment); void stop_floppy (void);