aboutsummaryrefslogtreecommitdiffstats
path: root/memdisk
diff options
context:
space:
mode:
authorShao Miller <shao.miller@yrdsb.edu.on.ca>2009-08-01 01:07:50 -0400
committerShao Miller <shao.miller@yrdsb.edu.on.ca>2009-08-03 22:09:37 -0400
commit004082b85c0362ab7a47598b889c9d9c4ef570d8 (patch)
tree4ba843f059a90d4e0e5e03cbbb37ec019dbc0c7a /memdisk
parentd5d62c379dde5a852ad049286cbabb770c4955a1 (diff)
downloadsyslinux.git-004082b85c0362ab7a47598b889c9d9c4ef570d8.tar.gz
syslinux.git-004082b85c0362ab7a47598b889c9d9c4ef570d8.tar.xz
syslinux.git-004082b85c0362ab7a47598b889c9d9c4ef570d8.zip
[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.
Diffstat (limited to 'memdisk')
-rw-r--r--memdisk/Makefile4
-rw-r--r--memdisk/dskprobe.c114
-rw-r--r--memdisk/dskprobe.h21
-rw-r--r--memdisk/setup.c8
4 files changed, 145 insertions, 2 deletions
diff --git a/memdisk/Makefile b/memdisk/Makefile
index e1a89351..06413b68 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 00000000..de858bb9
--- /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 <stdint.h>
+#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(&regs, 0, sizeof regs);
+
+ regs.eax.b[1] = probe; /* AH = probe */
+ regs.edx.b[0] = drive; /* DL = drive number to probe */
+ intcall(0x13, &regs, &regs);
+
+ 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 00000000..99bfa666
--- /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 <stdint.h>
+
+extern uint8_t probe_drive_range(uint8_t);
diff --git a/memdisk/setup.c b/memdisk/setup.c
index b2444f61..e3b9d31c 100644
--- a/memdisk/setup.c
+++ b/memdisk/setup.c
@@ -13,6 +13,7 @@
#include <stdint.h>
#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;