aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorShao Miller <shao.miller@yrdsb.edu.on.ca>2010-03-09 18:33:35 -0500
committerShao Miller <sha0@terminus.zytor.com>2010-06-10 22:08:41 -0700
commit3a2d5f8b3a75961e621c83890a592db24dd960a6 (patch)
treed35aa2180edf6e6c58741ae306211746e9264db2
parent9d52e438f991e1d7667df6a5eead2e240b0164eb (diff)
downloadsyslinux-3a2d5f8b3a75961e621c83890a592db24dd960a6.tar.gz
syslinux-3a2d5f8b3a75961e621c83890a592db24dd960a6.tar.xz
syslinux-3a2d5f8b3a75961e621c83890a592db24dd960a6.zip
mdiskchk: Support three new features
MDISKCHK.COM now supports three new modes: mdiskchk.com --mbfts This mode will scan between free base memory and 0xA00000 looking for MEMDISK mBFTs. For each one found, its detail will be reported. mdiskchk.com --safe-hooks This mode will attempt to walk the chain of INT 13h "safe hooks". For each MEMDISK "safe hook" found, its detail will be reported. mdiskchk.com --batch-output This mode suppresses the normal detail report and instead outputs a list of DOS SET commands. This is useful if one wishes to populate a batch file and call that batch file to set DOS environment variables, so that programs have access to those MEMDISK kernel arguments passed at boot-time. These command-line options may be combined. For example, your AUTOEXEC.BAT might go: @echo off echo @echo off>setenv.bat mdiskchk.com -m -s -b>>setenv.bat call setenv.bat>nul Signed-off-by: Shao Miller <shao.miller@yrdsb.edu.on.ca>
-rw-r--r--dosutil/mdiskchk.c249
-rw-r--r--dosutil/mdiskchk.combin7273 -> 8184 bytes
2 files changed, 228 insertions, 21 deletions
diff --git a/dosutil/mdiskchk.c b/dosutil/mdiskchk.c
index 42aa5119..ddc57632 100644
--- a/dosutil/mdiskchk.c
+++ b/dosutil/mdiskchk.c
@@ -1,6 +1,7 @@
/* -*- c -*- ------------------------------------------------------------- *
*
* Copyright 2003-2008 H. Peter Anvin - All Rights Reserved
+ * Portions copyright 2010 Shao Miller
*
* 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
@@ -21,6 +22,7 @@
* wcl -3 -osx -mt mdiskchk.c
*/
+#include <ctype.h>
#include <stdio.h>
#include <string.h>
#include <i86.h> /* For MK_FP() */
@@ -29,18 +31,15 @@ typedef unsigned long uint32_t;
typedef unsigned short uint16_t;
typedef unsigned char uint8_t;
+/* OpenWatcom uses a packed structure prefix */
+#define MEMDISK_PACKED_PREFIX _Packed
+#define MEMDISK_PACKED_POSTFIX
+
+/* Pull in MEMDISK common structures */
+#include "../memdisk/mstructs.h"
+
struct memdiskinfo {
- uint16_t bytes; /* Bytes from memdisk */
- uint16_t version; /* Memdisk version */
- uint32_t base; /* Base of disk in high memory */
- uint32_t size; /* Size of disk in sectors */
- char far *cmdline; /* Command line */
- void far *oldint13; /* Old INT 13h */
- void far *oldint15; /* Old INT 15h */
- uint16_t olddosmem;
- uint8_t bootloaderid;
-
- uint8_t _pad;
+ struct mdi mdi;
/* We add our own fields at the end */
int cylinders;
@@ -121,25 +120,233 @@ const char *bootloadername(uint8_t id)
}
}
+/* The function type for an output function */
+#define OUTPUT_FUNC_DECL(x) \
+void x(const int d, const struct memdiskinfo * const m)
+typedef OUTPUT_FUNC_DECL((*output_func));
+
+/* Show MEMDISK information for the passed structure */
+static OUTPUT_FUNC_DECL(normal_output)
+{
+ if (m == NULL)
+ return;
+ printf("Drive %02X is MEMDISK %u.%02u:\n"
+ "\tAddress = 0x%08lx, len = %lu sectors, chs = %u/%u/%u,\n"
+ "\tloader = 0x%02x (%s),\n"
+ "\tcmdline = %Fs\n",
+ d, m->mdi.version_major, m->mdi.version_minor,
+ m->mdi.diskbuf, m->mdi.disksize, m->cylinders, m->heads, m->sectors,
+ m->mdi.bootloaderid, bootloadername(m->mdi.bootloaderid),
+ MK_FP(m->mdi.cmdline.seg_off.segment,
+ m->mdi.cmdline.seg_off.offset));
+}
+
+/* Yield DOS SET command(s) as output for each MEMDISK kernel argument */
+static OUTPUT_FUNC_DECL(batch_output)
+{
+ if (m != NULL) {
+ char buf[256], *bc;
+ const char far *c =
+ MK_FP(m->mdi.cmdline.seg_off.segment,
+ m->mdi.cmdline.seg_off.offset);
+ const char *have_equals, is_set[] = "=1";
+
+ while (*c != '\0') {
+ /* Skip whitespace */
+ while (isspace(*c))
+ c++;
+ if (*c == '\0')
+ /* Trailing whitespace. That's enough processing */
+ break;
+ /* Walk the kernel arguments while filling the buffer,
+ * looking for space or NUL or checking for a full buffer
+ */
+ bc = buf;
+ have_equals = is_set;
+ while ((*c != '\0') && !isspace(*c) &&
+ (bc < &buf[sizeof(buf) - 1])) {
+ /* Check if the param is "x=y" */
+ if (*c == '=')
+ /* "=1" not needed */
+ have_equals = &is_set[sizeof(is_set) - 1];
+ *bc = *c;
+ c++;
+ bc++;
+ }
+ /* Found the end of the parameter and optional value sequence */
+ *bc = '\0';
+ printf("set %s%s\n", buf, have_equals);
+ }
+ }
+}
+
+/* We do not output batch file output by default. We show MEMDISK info */
+static output_func show_memdisk = normal_output;
+
+/* A generic function type */
+#define MDISKCHK_FUNC_DECL(x) \
+void x(void)
+typedef MDISKCHK_FUNC_DECL((*mdiskchk_func));
+
+static MDISKCHK_FUNC_DECL(do_nothing)
+{
+ return;
+}
+
+static MDISKCHK_FUNC_DECL(show_usage)
+{
+ printf("\nUsage: mdiskchk [--safe-hooks] [--mbfts] [--batch-output]\n"
+ "\n"
+ "Action: --safe-hooks . . Will scan INT 13h \"safe hook\" chain\n"
+ " --mbfts . . . . Will scan memory for MEMDISK mBFTs\n"
+ " --batch-output . Will output SET command output based\n"
+ " on MEMDISK kernel arguments\n");
+}
+
+/* Search memory for mBFTs and report them via the output method */
+static MDISKCHK_FUNC_DECL(show_mbfts)
+{
+ const uint16_t far * const free_base_mem =
+ MK_FP(0x0040, 0x0013);
+ int seg;
+ uint8_t chksum;
+ uint32_t i;
+ const struct mBFT far *mbft;
+ struct memdiskinfo m;
+ struct patch_area far *patch_area;
+
+ for (seg = *free_base_mem / 16; seg < 0x9FFF; seg++) {
+ mbft = MK_FP(seg, 0);
+ /* Check for signature */
+ if (mbft->acpi.signature[0] != 'm' ||
+ mbft->acpi.signature[1] != 'B' ||
+ mbft->acpi.signature[2] != 'F' ||
+ mbft->acpi.signature[3] != 'T')
+ continue;
+ if (mbft->acpi.length != sizeof(struct mBFT))
+ continue;
+ /* Check sum */
+ chksum = 0;
+ for (i = 0; i < sizeof(struct mBFT); i++)
+ chksum += ((const uint8_t far *)mbft)[i];
+ if (chksum)
+ continue;
+ /* Copy the MDI from the mBFT */
+ _fmemcpy((void far *)&m, &mbft->mdi, sizeof(struct mdi));
+ /* Adjust C/H/S since we actually know
+ * it directly for any MEMDISK with an mBFT
+ */
+ patch_area = (struct patch_area far *)&mbft->mdi;
+ m.cylinders = patch_area->cylinders;
+ m.heads = patch_area->heads;
+ m.sectors = patch_area->sectors;
+ show_memdisk(patch_area->driveno, &m);
+ }
+}
+
+/* Walk the "safe hook" chain as far as possible
+ * and report MEMDISKs that we find via the output method
+ */
+static MDISKCHK_FUNC_DECL(show_safe_hooks)
+{
+ const real_addr_t far * const int13 =
+ MK_FP(0x0000, 0x0013 * sizeof(real_addr_t));
+ const struct safe_hook far *hook =
+ MK_FP(int13->seg_off.segment, int13->seg_off.offset);
+
+ while ((hook->signature[0] == '$') &&
+ (hook->signature[1] == 'I') &&
+ (hook->signature[2] == 'N') &&
+ (hook->signature[3] == 'T') &&
+ (hook->signature[4] == '1') &&
+ (hook->signature[5] == '3') &&
+ (hook->signature[6] == 'S') &&
+ (hook->signature[7] == 'F')) {
+ /* Found a valid "safe hook" */
+ if ((hook->vendor[0] == 'M') &&
+ (hook->vendor[1] == 'E') &&
+ (hook->vendor[2] == 'M') &&
+ (hook->vendor[3] == 'D') &&
+ (hook->vendor[4] == 'I') &&
+ (hook->vendor[5] == 'S') &&
+ (hook->vendor[6] == 'K')) {
+ /* Found a valid MEMDISK "safe hook". It will have an mBFT */
+ const struct mBFT far *mbft;
+ struct memdiskinfo m;
+ struct patch_area far *patch_area;
+
+ /* Copy the MDI from the mBFT. Offset is a misnomer here */
+ mbft = MK_FP(hook->mBFT.offset >> 4, 0); /* Always aligned */
+ _fmemcpy((void far *)&m, &mbft->mdi, sizeof(struct mdi));
+ /* Adjust C/H/S since we actually know
+ * it directly for any MEMDISK with an mBFT
+ */
+ patch_area = (struct patch_area far *)&mbft->mdi;
+ m.cylinders = patch_area->cylinders;
+ m.heads = patch_area->heads;
+ m.sectors = patch_area->sectors;
+ show_memdisk(patch_area->driveno, &m);
+ } /* if */
+ /* Step to the next hook in the "safe hook" chain */
+ hook = MK_FP(hook->old_hook.seg_off.segment,
+ hook->old_hook.seg_off.offset);
+ } /* while */
+}
+
int main(int argc, char *argv[])
{
int d;
int found = 0;
- struct memdiskinfo *m;
+ const struct memdiskinfo *m;
+ /* Default behaviour */
+ mdiskchk_func usage = do_nothing,
+ safe_hooks = do_nothing,
+ mbfts = do_nothing;
+
+ /* For each argument */
+ while (--argc) {
+ /* Argument should begin with one of these chars */
+ if ((*argv[argc] != '/') && (*argv[argc] != '-')) {
+ /* It doesn't. Print usage soon */
+ usage = show_usage;
+ break;
+ }
+ argv[argc]++;
+
+ /* Next char might be '-' as in "--safe-hooks" */
+ if (*argv[argc] == '-')
+ argv[argc]++;
+
+ switch (*argv[argc]) {
+ case 'S':
+ case 's':
+ safe_hooks = show_safe_hooks;
+ break;
+ case 'M':
+ case 'm':
+ mbfts = show_mbfts;
+ break;
+ case 'B':
+ case 'b':
+ show_memdisk = batch_output;
+ break;
+ default:
+ usage = show_usage;
+ } /* switch */
+ } /* while */
+
+ safe_hooks();
+ mbfts();
for (d = 0; d <= 0xff; d++) {
- if ((m = query_memdisk(d)) != NULL) {
- printf("Drive %02X is MEMDISK %u.%02u:\n"
- "\tAddress = 0x%08lx, len = %lu sectors, chs = %u/%u/%u,\n"
- "\tloader = 0x%02x (%s),\n"
- "\tcmdline = %Fs\n",
- d, m->version >> 8, m->version & 0xff,
- m->base, m->size, m->cylinders, m->heads, m->sectors,
- m->bootloaderid, bootloadername(m->bootloaderid),
- m->cmdline);
+ m = query_memdisk(d);
+ if (m != NULL) {
found++;
+ show_memdisk(d, m);
}
}
+ usage();
return found;
}
+
diff --git a/dosutil/mdiskchk.com b/dosutil/mdiskchk.com
index 78257519..5a6cc8e7 100644
--- a/dosutil/mdiskchk.com
+++ b/dosutil/mdiskchk.com
Binary files differ