176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman/* -*- c -*- ------------------------------------------------------------- *
276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman *
376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman *   Copyright 2003-2008 H. Peter Anvin - All Rights Reserved
476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman *   Portions copyright 2010 Shao Miller
576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman *
676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman *   This program is free software; you can redistribute it and/or modify
776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman *   it under the terms of the GNU General Public License as published by
876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman *   the Free Software Foundation, Inc., 53 Temple Place Ste 330,
976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman *   Boston MA 02111-1307, USA; either version 2 of the License, or
1076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman *   (at your option) any later version; incorporated herein by reference.
1176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman *
1276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman * ----------------------------------------------------------------------- */
1376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman
1476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman/*
1576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman * mdiskchk.c
1676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman *
1776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman * DOS program to check for the existence of a memdisk.
1876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman *
1976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman * This program can be compiled for DOS with the OpenWatcom compiler
2076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman * (http://www.openwatcom.org/):
2176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman *
2276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman * wcl -3 -osx -mt mdiskchk.c
2376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman */
2476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman
2576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman#include <ctype.h>
2676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman#include <stdio.h>
2776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman#include <string.h>
2876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman#include <i86.h>		/* For MK_FP() */
2976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman
3076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartmantypedef unsigned long uint32_t;
3176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartmantypedef unsigned short uint16_t;
3276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartmantypedef unsigned char uint8_t;
3376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman
3476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman/* Pull in MEMDISK common structures */
3576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman#include "../memdisk/mstructs.h"
3676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman
3776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartmanstruct memdiskinfo {
3876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman    struct mdi mdi;
3976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman
4076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman    /* We add our own fields at the end */
4176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman    int cylinders;
4276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman    int heads;
4376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman    int sectors;
4476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman};
4576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman
4676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartmanstruct memdiskinfo *query_memdisk(int drive)
4776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman{
4876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman    static struct memdiskinfo mm;
4976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman    uint32_t _eax, _ebx, _ecx, _edx;
5076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman    uint16_t _es, _di;
5176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman    unsigned char _dl = drive;
5276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman    uint16_t bytes;
5376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman
5476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman    __asm {
5576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman	.386;
5676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman	mov eax, 454d0800h;
5776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman	mov ecx, 444d0000h;
5876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman	mov edx, 53490000h;
5976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman	mov dl, _dl;
6076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman	mov ebx, 3f4b0000h;
6176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman	int 13h;
6276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman	mov _eax, eax;
6376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman	mov _ecx, ecx;
6476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman	mov _edx, edx;
6576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman	mov _ebx, ebx;
6676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman	mov _es, es;
6776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman	mov _di, di;
6876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman    }
6976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman
7076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman    if (_eax >> 16 != 0x4d21 ||
7176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman	_ecx >> 16 != 0x4d45 || _edx >> 16 != 0x4944 || _ebx >> 16 != 0x4b53)
7276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman	return NULL;
7376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman
7476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman    memset(&mm, 0, sizeof mm);
7576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman
7676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman    bytes = *(uint16_t far *) MK_FP(_es, _di);
7776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman
7876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman    /* 27 is the most we know how to handle */
7976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman    if (bytes > 27)
8076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman	bytes = 27;
8176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman
8276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman    _fmemcpy((void far *)&mm, (void far *)MK_FP(_es, _di), bytes);
8376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman
8476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman    mm.cylinders = ((_ecx >> 8) & 0xff) + ((_ecx & 0xc0) << 2) + 1;
8576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman    mm.heads = ((_edx >> 8) & 0xff) + 1;
8676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman    mm.sectors = (_ecx & 0x3f);
8776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman
8876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman    return &mm;
8976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman}
9076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman
9176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartmanconst char *bootloadername(uint8_t id)
9276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman{
9376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman    static const struct {
9476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman	uint8_t id, mask;
9576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman	const char *name;
9676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman    } *lp, list[] = {
9776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman	{0x00, 0xf0, "LILO"},
9876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman	{0x10, 0xf0, "LOADLIN"},
9976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman	{0x31, 0xff, "SYSLINUX"},
10076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman	{0x32, 0xff, "PXELINUX"},
10176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman	{0x33, 0xff, "ISOLINUX"},
10276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman	{0x34, 0xff, "EXTLINUX"},
10376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman	{0x30, 0xf0, "SYSLINUX family"},
10476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman	{0x40, 0xf0, "Etherboot"},
10576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman	{0x50, 0xf0, "ELILO"},
10676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman	{0x70, 0xf0, "GrUB"},
10776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman	{0x80, 0xf0, "U-Boot"},
10876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman	{0xA0, 0xf0, "Gujin"},
10976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman	{0xB0, 0xf0, "Qemu"},
11076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman	{0x00, 0x00, "unknown"}
11176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman    };
11276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman
11376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman    for (lp = list;; lp++) {
11476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman	if (((id ^ lp->id) & lp->mask) == 0)
11576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman	    return lp->name;
11676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman    }
11776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman}
11876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman
11976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman/* The function type for an output function */
12076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman#define OUTPUT_FUNC_DECL(x) \
12176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartmanvoid x(const int d, const struct memdiskinfo * const m)
12276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartmantypedef OUTPUT_FUNC_DECL((*output_func));
12376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman
12476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman/* Show MEMDISK information for the passed structure */
12576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartmanstatic OUTPUT_FUNC_DECL(normal_output)
12676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman{
12776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman    if (m == NULL)
12876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman	return;
12976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman    printf("Drive %02X is MEMDISK %u.%02u:\n"
13076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman	   "\tAddress = 0x%08lx, len = %lu sectors, chs = %u/%u/%u,\n"
13176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman	   "\tloader = 0x%02x (%s),\n"
13276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman	   "\tcmdline = %Fs\n",
13376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman	   d, m->mdi.version_major, m->mdi.version_minor,
13476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman	   m->mdi.diskbuf, m->mdi.disksize, m->cylinders, m->heads, m->sectors,
13576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman	   m->mdi.bootloaderid, bootloadername(m->mdi.bootloaderid),
13676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman	   MK_FP(m->mdi.cmdline.seg_off.segment,
13776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman		 m->mdi.cmdline.seg_off.offset));
13876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman}
13976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman
14076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman/* Yield DOS SET command(s) as output for each MEMDISK kernel argument */
14176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartmanstatic OUTPUT_FUNC_DECL(batch_output)
14276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman{
14376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman    if (m != NULL) {
14476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman	char buf[256], *bc;
14576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman	const char far *c =
14676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman	    MK_FP(m->mdi.cmdline.seg_off.segment,
14776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman		  m->mdi.cmdline.seg_off.offset);
14876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman	const char *have_equals, is_set[] = "=1";
14976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman
15076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman	while (*c != '\0') {
15176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman	    /* Skip whitespace */
15276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman	    while (isspace(*c))
15376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman		c++;
15476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman	    if (*c == '\0')
15576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman		/* Trailing whitespace.  That's enough processing */
15676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman		break;
15776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman	    /* Walk the kernel arguments while filling the buffer,
15876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman	     * looking for space or NUL or checking for a full buffer
15976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman	     */
16076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman	    bc = buf;
16176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman	    have_equals = is_set;
16276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman	    while ((*c != '\0') && !isspace(*c) &&
16376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman		   (bc < &buf[sizeof(buf) - 1])) {
16476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman		/* Check if the param is "x=y" */
16576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman		if (*c == '=')
16676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman		    /* "=1" not needed */
16776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman		    have_equals = &is_set[sizeof(is_set) - 1];
16876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman		*bc = *c;
16976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman		c++;
17076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman		bc++;
17176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman	    }
17276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman	    /* Found the end of the parameter and optional value sequence */
17376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman	    *bc = '\0';
17476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman	    printf("set %s%s\n", buf, have_equals);
17576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman	}
17676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman    }
17776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman}
17876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman
17976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman/* We do not output batch file output by default.  We show MEMDISK info */
18076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartmanstatic output_func show_memdisk = normal_output;
18176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman
18276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman/* A generic function type */
18376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman#define MDISKCHK_FUNC_DECL(x) \
18476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartmanvoid x(void)
18576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartmantypedef MDISKCHK_FUNC_DECL((*mdiskchk_func));
18676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman
18776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartmanstatic MDISKCHK_FUNC_DECL(do_nothing)
18876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman{
18976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman    return;
19076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman}
19176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman
19276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartmanstatic MDISKCHK_FUNC_DECL(show_usage)
19376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman{
19476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman    printf("\nUsage: mdiskchk [--safe-hooks] [--mbfts] [--batch-output]\n"
19576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman	   "\n"
19676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman	   "Action: --safe-hooks . . Will scan INT 13h \"safe hook\" chain\n"
19776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman	   "        --mbfts . . . .  Will scan memory for MEMDISK mBFTs\n"
19876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman	   "        --batch-output . Will output SET command output based\n"
19976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman	   "                         on MEMDISK kernel arguments\n"
20076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman	   "        --no-sequential  Suppresses probing all drive numbers\n");
20176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman}
20276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman
20376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman/* Search memory for mBFTs and report them via the output method */
20476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartmanstatic MDISKCHK_FUNC_DECL(show_mbfts)
20576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman{
20676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman    const uint16_t far * const free_base_mem =
20776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman	MK_FP(0x0040, 0x0013);
20876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman    int seg;
20976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman    uint8_t chksum;
21076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman    uint32_t i;
21176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman    const struct mBFT far *mbft;
21276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman    struct memdiskinfo m;
21376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman    struct patch_area far *patch_area;
21476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman
21576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman    for (seg = *free_base_mem / 16; seg < 0x9FFF; seg++) {
21676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman	mbft = MK_FP(seg, 0);
21776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman	/* Check for signature */
21876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman	if (mbft->acpi.signature[0] != 'm' ||
21976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman	    mbft->acpi.signature[1] != 'B' ||
22076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman	    mbft->acpi.signature[2] != 'F' ||
22176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman	    mbft->acpi.signature[3] != 'T')
22276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman	    continue;
22376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman	if (mbft->acpi.length != sizeof(struct mBFT))
22476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman	    continue;
22576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman	/* Check sum */
22676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman	chksum = 0;
22776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman	for (i = 0; i < sizeof(struct mBFT); i++)
22876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman	    chksum += ((const uint8_t far *)mbft)[i];
22976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman	if (chksum)
23076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman	    continue;
23176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman	/* Copy the MDI from the mBFT */
23276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman	_fmemcpy((void far *)&m, &mbft->mdi, sizeof(struct mdi));
23376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman	/* Adjust C/H/S since we actually know
23476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman	 * it directly for any MEMDISK with an mBFT
23576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman	 */
23676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman	patch_area = (struct patch_area far *)&mbft->mdi;
23776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman	m.cylinders = patch_area->cylinders;
23876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman	m.heads = patch_area->heads;
23976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman	m.sectors = patch_area->sectors;
24076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman	show_memdisk(patch_area->driveno, &m);
24176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman    }
24276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman}
24376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman
24476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman/* Walk the "safe hook" chain as far as possible
24576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman * and report MEMDISKs that we find via the output method
24676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman */
24776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartmanstatic MDISKCHK_FUNC_DECL(show_safe_hooks)
24876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman{
24976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman    const real_addr_t far * const int13 =
25076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman	MK_FP(0x0000, 0x0013 * sizeof(real_addr_t));
25176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman    const struct safe_hook far *hook =
25276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman	MK_FP(int13->seg_off.segment, int13->seg_off.offset);
25376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman
25476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman    while ((hook->signature[0] == '$') &&
25576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman	   (hook->signature[1] == 'I') &&
25676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman	   (hook->signature[2] == 'N') &&
25776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman	   (hook->signature[3] == 'T') &&
25876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman	   (hook->signature[4] == '1') &&
25976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman	   (hook->signature[5] == '3') &&
26076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman	   (hook->signature[6] == 'S') &&
26176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman	   (hook->signature[7] == 'F')) {
26276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman	/* Found a valid "safe hook" */
26376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman	if ((hook->vendor[0] == 'M') &&
26476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman	    (hook->vendor[1] == 'E') &&
26576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman	    (hook->vendor[2] == 'M') &&
26676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman	    (hook->vendor[3] == 'D') &&
26776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman	    (hook->vendor[4] == 'I') &&
26876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman	    (hook->vendor[5] == 'S') &&
26976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman	    (hook->vendor[6] == 'K')) {
27076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman	    /* Found a valid MEMDISK "safe hook".  It will have an mBFT */
27176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman	    const struct mBFT far *mbft;
27276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman	    struct memdiskinfo m;
27376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman	    struct patch_area far *patch_area;
27476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman
27576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman	    /* Copy the MDI from the mBFT.  Offset is a misnomer here */
27676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman	    mbft = MK_FP(hook->mbft >> 4, 0);	/* Always aligned */
27776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman	    _fmemcpy((void far *)&m, &mbft->mdi, sizeof(struct mdi));
27876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman	    /* Adjust C/H/S since we actually know
27976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman	     * it directly for any MEMDISK with an mBFT
28076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman	     */
28176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman	    patch_area = (struct patch_area far *)&mbft->mdi;
28276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman	    m.cylinders = patch_area->cylinders;
28376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman	    m.heads = patch_area->heads;
28476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman	    m.sectors = patch_area->sectors;
28576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman	    show_memdisk(patch_area->driveno, &m);
28676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman	} /* if */
28776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman	/* Step to the next hook in the "safe hook" chain */
28876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman	hook = MK_FP(hook->old_hook.seg_off.segment,
28976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman		     hook->old_hook.seg_off.offset);
29076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman    } /* while */
29176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman}
29276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman
29376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartmanint main(int argc, char *argv[])
29476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman{
29576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman    int d;
29676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman    int found = 0;
29776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman    int sequential_scan = 1;	/* Classic behaviour */
29876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman    const struct memdiskinfo *m;
29976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman
30076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman    /* Default behaviour */
30176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman    mdiskchk_func usage = do_nothing,
30276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman	safe_hooks = do_nothing,
30376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman	mbfts = do_nothing;
30476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman
30576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman    /* For each argument */
30676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman    while (--argc) {
30776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman	/* Argument should begin with one of these chars */
30876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman	if ((*argv[argc] != '/') && (*argv[argc] != '-')) {
30976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman	    /* It doesn't.  Print usage soon */
31076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman	    usage = show_usage;
31176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman	    break;
31276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman	}
31376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman	argv[argc]++;
31476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman
31576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman	/* Next char might be '-' as in "--safe-hooks" */
31676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman	if (*argv[argc] == '-')
31776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman	    argv[argc]++;
31876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman
31976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman	switch (*argv[argc]) {
32076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman	    case 'S':
32176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman	    case 's':
32276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman		safe_hooks = show_safe_hooks;
32376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman		break;
32476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman	    case 'M':
32576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman	    case 'm':
32676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman		mbfts = show_mbfts;
32776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman		break;
32876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman	    case 'B':
32976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman	    case 'b':
33076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman		show_memdisk = batch_output;
33176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman		break;
33276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman	    case 'N':
33376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman	    case 'n':
33476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman		sequential_scan = 0;
33576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman		break;
33676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman	    default:
33776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman		usage = show_usage;
33876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman	} /* switch */
33976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman   } /* while */
34076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman
34176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman    safe_hooks();
34276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman    mbfts();
34376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman    if (!sequential_scan)
34476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman	goto skip_sequential;
34576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman    for (d = 0; d <= 0xff; d++) {
34676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman	m = query_memdisk(d);
34776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman	if (m != NULL) {
34876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman	    found++;
34976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman	    show_memdisk(d, m);
35076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman	}
35176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman    }
35276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartmanskip_sequential:
35376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman    usage();
35476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman
35576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman    return found;
35676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman}
35776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman
358