From 004082b85c0362ab7a47598b889c9d9c4ef570d8 Mon Sep 17 00:00:00 2001 From: Shao Miller Date: Sat, 1 Aug 2009 01:07:50 -0400 Subject: [PATCH] [memdisk] Add disk probing code to support a drive shifting limit Our INT 13h hook will now only shift BIOS drive numbers up to a limit. This limit is found by probing for a contiguous range of BIOS drives. Anything above this range of contiguous drive numbers is not shifted, and will thus be available to callers at the same drive number. --- memdisk/Makefile | 4 +- memdisk/dskprobe.c | 114 +++++++++++++++++++++++++++++++++++++++++++++++++++++ memdisk/dskprobe.h | 21 ++++++++++ memdisk/setup.c | 8 ++++ 4 files changed, 145 insertions(+), 2 deletions(-) create mode 100644 memdisk/dskprobe.c create mode 100644 memdisk/dskprobe.h diff --git a/memdisk/Makefile b/memdisk/Makefile index e1a8935..06413b6 100644 --- a/memdisk/Makefile +++ b/memdisk/Makefile @@ -38,9 +38,9 @@ endif # Important: init.o16 must be first!! OBJS16 = init.o16 init32.o OBJS32 = start32.o setup.o msetup.o e820func.o conio.o memcpy.o memset.o \ - memmove.o unzip.o memdisk_chs.o memdisk_edd.o + memmove.o unzip.o memdisk_chs.o memdisk_edd.o dskprobe.o -CSRC = setup.c msetup.c e820func.c conio.c unzip.c +CSRC = setup.c msetup.c e820func.c conio.c unzip.c dskprobe.c SSRC = start32.S memcpy.S memset.S memmove.S NASMSRC = memdisk_chs.asm memdisk_edd.asm memdisk16.asm diff --git a/memdisk/dskprobe.c b/memdisk/dskprobe.c new file mode 100644 index 0000000..de858bb --- /dev/null +++ b/memdisk/dskprobe.c @@ -0,0 +1,114 @@ +/* ----------------------------------------------------------------------- * + * + * Copyright 2009 Shao Miller - All Rights Reserved + * + * This program 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, Inc., 53 Temple Place Ste 330, + * Boston MA 02111-1307, USA; either version 2 of the License, or + * (at your option) any later version; incorporated herein by reference. + * + * ----------------------------------------------------------------------- */ + +/* + * dskprobe.c + * + * Routines for probing BIOS disk drives + */ + +/* + * Uncomment for debugging + * + * #define DBG_DSKPROBE 1 + */ + +#include +#include "memdisk.h" +#include "bda.h" +#include "conio.h" + +/* + * We will probe a BIOS drive numer using INT 13h, AH=probe + * and will pass along that call's success or failure + */ +int probe_int13_ah(uint8_t drive, uint8_t probe) +{ + int err; + com32sys_t regs; + + memset(®s, 0, sizeof regs); + + regs.eax.b[1] = probe; /* AH = probe */ + regs.edx.b[0] = drive; /* DL = drive number to probe */ + intcall(0x13, ®s, ®s); + + err = !(regs.eflags.l & 1); +#ifdef DBG_DSKPROBE + printf("probe_int13_ah(0x%02x, 0x%02x) == %d\n", drive, probe, err); +#endif + return err; +} + +/* + * We will probe the BIOS Data Area and count the drives found there. + * This heuristic then assumes that all drives of 'drive's type are + * found in a contiguous range, and returns 1 if the probed drive + * is less than or equal to the BDA count. + * This particular function's code is derived from code in setup.c by + * H. Peter Anvin. Please respect that file's copyright for this function + */ +int probe_bda_drive(uint8_t drive) +{ + int bios_drives; + int err; + + if (drive & 0x80) { + bios_drives = rdz_8(BIOS_HD_COUNT); /* HDD count */ + } else { + uint8_t equip = rdz_8(BIOS_EQUIP); + if (equip & 1) + bios_drives = (equip >> 6) + 1; /* Floppy count */ + else + bios_drives = 0; + } + err = (drive - (drive & 0x80)) >= bios_drives ? 0 : 1; +#ifdef DBG_DSKPROBE + printf("probe_bda_drive(0x%02x) == %d, count: %d\n", + drive, err, bios_drives); +#endif + return err; +} + +/* + * We will probe a drive with a few different methods, returning + * the count of succesful probes + */ +int probe_drive(uint8_t drive) +{ + int c = 0; + /* Only probe the BDA for floppies */ + if (drive & 0x80) { + c += probe_int13_ah(drive, 0x08); + c += probe_int13_ah(drive, 0x15); + c += probe_int13_ah(drive, 0x41); + } + c += probe_bda_drive(drive); + return c; +} + +/* + * We will probe a contiguous range of BIOS drive, starting with drive + * number 'start'. We probe with a few different methods, and return + * the first drive which doesn't respond to any of the probes. + */ +uint8_t probe_drive_range(uint8_t start) +{ + uint8_t drive = start; + while (probe_drive(drive)) { + drive++; + /* Check for passing the floppy/HDD boundary */ + if ((drive & 0x7F) == 0) + break; + } + return drive; +} diff --git a/memdisk/dskprobe.h b/memdisk/dskprobe.h new file mode 100644 index 0000000..99bfa66 --- /dev/null +++ b/memdisk/dskprobe.h @@ -0,0 +1,21 @@ +/* ----------------------------------------------------------------------- * + * + * Copyright 2009 Shao Miller - All Rights Reserved + * + * This program 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, Inc., 53 Temple Place Ste 330, + * Boston MA 02111-1307, USA; either version 2 of the License, or + * (at your option) any later version; incorporated herein by reference. + * + * ----------------------------------------------------------------------- */ + +/* + * dskprobe.h + * + * Routines for probing BIOS disk drives + */ + +#include + +extern uint8_t probe_drive_range(uint8_t); diff --git a/memdisk/setup.c b/memdisk/setup.c index b2444f6..e3b9d31 100644 --- a/memdisk/setup.c +++ b/memdisk/setup.c @@ -13,6 +13,7 @@ #include #include "bda.h" +#include "dskprobe.h" #include "e820.h" #include "conio.h" #include "version.h" @@ -999,6 +1000,13 @@ void setup(const struct real_mode_args *rm_args_ptr) if (pptr->drivecnt <= (geometry->driveno & 0x7f)) pptr->drivecnt = (geometry->driveno & 0x7f) + 1; + /* Probe for contiguous range of BIOS drives starting with driveno */ + pptr->driveshiftlimit = probe_drive_range(geometry->driveno) + 1; + if ((pptr->driveshiftlimit & 0x80) != (geometry->driveno & 0x80)) + printf("We lost the last drive in our class of drives.\n"); + printf("Drive probing gives drive shift limit: 0x%02x\n", + pptr->driveshiftlimit); + /* Pointer to the command line */ pptr->cmdline_off = bin_size + (nranges + 1) * sizeof(ranges[0]); pptr->cmdline_seg = driverseg; -- 2.7.4