diff options
author | Shao Miller <shao.miller@yrdsb.edu.on.ca> | 2010-03-09 18:33:35 -0500 |
---|---|---|
committer | Shao Miller <sha0@terminus.zytor.com> | 2010-06-10 22:08:41 -0700 |
commit | 3a2d5f8b3a75961e621c83890a592db24dd960a6 (patch) | |
tree | d35aa2180edf6e6c58741ae306211746e9264db2 | |
parent | 9d52e438f991e1d7667df6a5eead2e240b0164eb (diff) | |
download | syslinux-3a2d5f8b3a75961e621c83890a592db24dd960a6.tar.gz |
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.c | 249 | ||||
-rw-r--r-- | dosutil/mdiskchk.com | bin | 7273 -> 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 Binary files differindex 78257519..5a6cc8e7 100644 --- a/dosutil/mdiskchk.com +++ b/dosutil/mdiskchk.com |