Add API to query for the existence of MEMDISK.
authorhpa <hpa>
Wed, 26 Nov 2003 00:10:40 +0000 (00:10 +0000)
committerhpa <hpa>
Wed, 26 Nov 2003 00:10:40 +0000 (00:10 +0000)
NEWS
memdisk/memdisk.asm
memdisk/memdisk.doc
memdisk/memdisk.h
memdisk/setup.c
sample/mdiskchk.c [new file with mode: 0644]
sample/mdiskchk.com [new file with mode: 0755]

diff --git a/NEWS b/NEWS
index 26d8267..236ba35 100644 (file)
--- a/NEWS
+++ b/NEWS
@@ -12,6 +12,7 @@ Changes in 2.08:
        * PXELINUX: Actually free sockets when we get a failure
          (including file not found.)  This bug would cause us to run
          out of sockets and thus "go deaf" after a while.
+       * MEMDISK: Add an API to query for the existence of MEMDISK.
 
 Changes in 2.07:
        * MEMDISK: Workaround for BIOSes which go into a snit when
index f356328..cec4010 100644 (file)
@@ -17,6 +17,8 @@
 ; 
 ; ****************************************************************************
 
+%include       "../version.gen"
+
 ; %define DEBUG_TRACERS                        ; Uncomment to get debugging tracers
 
 %ifdef DEBUG_TRACERS
 %define                P_DS            word [bp+34]
 %define                P_ES            word [bp+32]
 %define                P_EAX           dword [bp+28]
+%define                P_HAX           word [bp+30]
 %define                P_AX            word [bp+28]
 %define                P_AL            byte [bp+28]
 %define                P_AH            byte [bp+29]
 %define                P_ECX           dword [bp+24]
+%define                P_HCX           word [bp+26]
 %define                P_CX            word [bp+24]
 %define                P_CL            byte [bp+24]
 %define                P_CH            byte [bp+25]
 %define                P_EDX           dword [bp+20]
+%define                P_HDX           word [bp+22]
 %define                P_DX            word [bp+20]
 %define                P_DL            byte [bp+20]
 %define                P_DH            byte [bp+21]
 %define                P_EBX           dword [bp+16]
+%define                P_HBX           word [bp+18]
+%define                P_HBXL          byte [bp+18]
 %define                P_BX            word [bp+16]
 %define                P_BL            byte [bp+16]
 %define                P_BH            byte [bp+17]
@@ -250,8 +257,7 @@ GetParms:
                test byte [DriveNo],80h
                jnz .hd
                mov P_DI,DPT
-               mov ax,cs
-               mov P_ES,ax
+               mov P_ES,cs
                mov bl,[DriveType]
                mov P_BL,bl
 .hd:
@@ -264,6 +270,28 @@ GetParms:
                mov ax,[Heads]
                dec ax
                mov P_DH,al
+
+               ;
+               ; Is this MEMDISK installation check?
+               ;
+               cmp P_HAX,'ME'
+               jne .notic
+               cmp P_HCX,'MD'
+               jne .notic
+               cmp P_HDX,'IS'
+               jne .notic
+               cmp P_HBX,'K?'
+               jne .notic
+
+               ; MEMDISK installation check...
+               mov P_HAX,'!M'
+               mov P_HCX,'EM'
+               mov P_HDX,'DI'
+               mov P_HBX,'SK'
+               mov P_ES,cs
+               mov P_DI,MemDisk_Info
+
+.notic:
                xor ax,ax
                ret
                
@@ -498,22 +526,29 @@ Mover_dst2:       db 0                    ; High 8 bits of source addy
 Mover_dummy2:  dd 0, 0, 0, 0           ; More space for the BIOS
 
                alignb 4, db 0
+MemDisk_Info   equ $                   ; Pointed to by installation check
+MDI_Bytes      dw 26                   ; Total bytes in MDI structure
+MDI_Version    db VER_MINOR, VER_MAJOR ; MEMDISK version
+
 PatchArea      equ $                   ; This gets filled in by the installer
 
-Cylinders      dw 0                    ; Cylinder count
-Heads          dw 0                    ; Head count
-Sectors                dd 0                    ; Sector count (zero-extended)
-DiskSize       dd 0                    ; Size of disk in blocks
 DiskBuf                dd 0                    ; Linear address of high memory disk
-
-Mem1MB         dd 0                    ; 1MB-16MB memory amount (1K)
-Mem16MB                dd 0                    ; 16MB-4G memory amount (64K)
+DiskSize       dd 0                    ; Size of disk in blocks
+CommandLine    dw 0, 0                 ; Far pointer to saved command line
 
 OldInt13       dd 0                    ; INT 13h in chain
 OldInt15       dd 0                    ; INT 15h in chain
 
-MemInt1588     dw 0                    ; 1MB-65MB memory amount (1K)
 OldDosMem      dw 0                    ; Old position of DOS mem end
+; ---- MDI structure ends here ---
+MemInt1588     dw 0                    ; 1MB-65MB memory amount (1K)
+
+Cylinders      dw 0                    ; Cylinder count
+Heads          dw 0                    ; Head count
+Sectors                dd 0                    ; Sector count (zero-extended)
+
+Mem1MB         dd 0                    ; 1MB-16MB memory amount (1K)
+Mem16MB                dd 0                    ; 16MB-4G memory amount (64K)
 
 DriveNo                db 0                    ; Our drive number
 DriveType      db 0                    ; Our drive type (floppies)
index 700ebec..3d36475 100644 (file)
@@ -81,3 +81,43 @@ network driver, which is part of the PROBOOT.EXE distribution from
 Intel:
 
        http://www.intel.com/support/network/adapter/1000/software.htm
+
+
+Additional technical information:
+
+Starting with version 2.08, MEMDISK now supports an installation check
+API.  This works as follows:
+
+       EAX = 454D0800h ("ME")
+       ECX = 444Dxxxxh ("MD")
+       EDX = 5349xxnnh ("IS") (nn = drive #)
+       EBX = 3F4Bxxxxh ("K?")
+       INT 13h
+
+If drive nn is a MEMDISK, the registers will contain:
+
+       EAX = 4D21xxxxh ("!M")
+       ECX = 4D45xxxxh ("EM")
+       EDX = 4944xxxxh ("DI")
+       EBX = 4B53xxxxh ("SK")
+
+       ES:DI -> MEMDISK info structures
+
+The low parts of EAX/ECX/EDX/EBX have the normal return values for
+INT 13h, AH=08h, i.e. information of the disk geometry etc (see Ralf
+Brown's interrupt list for a detailed description.)
+
+The MEMDISK info structure currently contains:
+
+       [ES:DI]         word    Total size of structure (currently 26 bytes)
+       [ES:DI+2]       byte    MEMDISK minor version
+       [ES:DI+3]       byte    MEMDISK major version
+       [ES:DI+4]       dword   Pointer to MEMDISK data in high memory
+       [ES:DI+8]       dword   Size of MEMDISK data in 512-byte sectors 
+       [ES:DI+12]      16:16   Far pointer to command line
+       [ES:DI+16]      16:16   Old INT 13h pointer
+       [ES:DI+20]      16:16   Old INT 15h pointer
+       [ES:DI+24]      word    Amount of DOS memory before MEMDISK loaded
+
+The program mdiskchk.c in the sample directory is an example on how
+this API can be used.
index bc125cc..ace53b0 100644 (file)
@@ -36,6 +36,15 @@ extern void __attribute__((noreturn)) die(void);
 /* Standard routines */
 #define memcpy(a,b,c) __builtin_memcpy(a,b,c)
 #define memset(a,b,c) __builtin_memset(a,b,c)
+#define strlen(a)     __builtin_strlen(a)
+
+/* memcpy() but returns a pointer to end of buffer */
+static inline void *
+memcpy_endptr(void *__d, const void *__s, unsigned int __n)
+{
+  memcpy(__d, __s, __n);
+  return (void *)((char *)__d + __n);
+}
 
 /* Decompression */
 void *unzip(void *indata, unsigned long zbytes, void *target);
index a078eec..aff0548 100644 (file)
@@ -63,21 +63,23 @@ typedef union {
 } dpt_t;
 
 struct patch_area {
+  uint32_t diskbuf;
+  uint32_t disksize;
+  uint16_t cmdline_off, cmdline_seg;
+  
+  uint32_t oldint13;
+  uint32_t oldint15;
+
+  uint16_t olddosmem;
+  uint16_t memint1588;
+
   uint16_t cylinders;
   uint16_t heads;
   uint32_t sectors;
-  uint32_t disksize;
-  uint32_t diskbuf;
 
   uint32_t mem1mb;
   uint32_t mem16mb;
 
-  uint32_t oldint13;
-  uint32_t oldint15;
-
-  uint16_t memint1588;
-  uint16_t olddosmem;
-
   uint8_t  driveno;
   uint8_t  drivetype;
   uint8_t  drivecnt;
@@ -496,7 +498,7 @@ uint32_t setup(syscall_t cs_syscall, void *cs_bounce)
   uint16_t dosmem_k;
   uint32_t stddosmem;
   const struct geometry *geometry;
-  int total_size;
+  int total_size, cmdlinelen;
   com32sys_t regs;
   uint32_t ramdisk_image, ramdisk_size;
 
@@ -583,9 +585,13 @@ uint32_t setup(syscall_t cs_syscall, void *cs_bounce)
      map -- 12 bytes per range; we may need as many as 2 additional
      ranges (each insertrange() can worst-case turn 1 area into 3)
      plus the terminating range, over what nranges currently show. */
-
-  total_size = hptr->total_size + (nranges+3)*sizeof(ranges[0]) + STACK_NEEDED;
-  printf("Total size needed = %u bytes\n", total_size);
+  cmdlinelen = strlen(shdr->cmdline)+1;
+  total_size  =  hptr->total_size;             /* Actual memdisk code */
+  total_size += (nranges+3)*sizeof(ranges[0]);  /* E820 memory ranges */
+  total_size += cmdlinelen;                    /* Command line */
+  total_size += STACK_NEEDED;                  /* Stack */
+  printf("Total size needed = %u bytes, allocating %uK\n",
+        total_size, (total_size+0x3ff) >> 10);
 
   if ( total_size > dos_mem ) {
     puts("MEMDISK: Insufficient low memory\n");
@@ -649,10 +655,17 @@ uint32_t setup(syscall_t cs_syscall, void *cs_bounce)
     pptr->drivecnt = regs.edx.b[0]+1;
   }
 
-  /* Copy driver followed by E820 table */
-  memcpy((void *)(driverseg << 4), &_binary_memdisk_bin_start, bin_size);
-  memcpy((void *)((driverseg << 4) + bin_size), ranges,
-        (nranges+1)*sizeof(ranges[0]));
+  /* Pointer to the command line */
+  pptr->cmdline_off = bin_size + (nranges+1)*sizeof(ranges[0]);
+  pptr->cmdline_seg = driverseg;
+
+  /* Copy driver followed by E820 table followed by command line */
+  {
+    unsigned char *dpp = (unsigned char *)(driverseg << 4);
+    dpp = memcpy_endptr(dpp, &_binary_memdisk_bin_start, bin_size);
+    dpp = memcpy_endptr(dpp, ranges, (nranges+1)*sizeof(ranges[0]));
+    dpp = memcpy_endptr(dpp, shdr->cmdline, cmdlinelen+1);
+  }
 
   /* Install the interrupt handlers */
   printf("old: int13 = %08x  int15 = %08x\n",
diff --git a/sample/mdiskchk.c b/sample/mdiskchk.c
new file mode 100644 (file)
index 0000000..cf2987e
--- /dev/null
@@ -0,0 +1,105 @@
+/* -*- c -*- ------------------------------------------------------------- *
+ *   
+ *   Copyright 2003 H. Peter Anvin - 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,
+ *   Bostom MA 02111-1307, USA; either version 2 of the License, or
+ *   (at your option) any later version; incorporated herein by reference.
+ *
+ * ----------------------------------------------------------------------- */
+/* $Id$ */
+
+/*
+ * mdiskchk.c
+ *
+ * DOS program to check for the existence of a memdisk.
+ *
+ * This program can be compiled for DOS with the OpenWatcom compiler
+ * (http://www.openwatcom.org/):
+ *
+ * wcl -3 -osx -mt mdiskchk.c
+ */
+
+#include <stdio.h>
+#include <string.h>
+#include <i86.h>               /* For MK_FP() */
+
+typedef unsigned long  uint32_t;
+typedef unsigned int   uint16_t;
+
+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;
+
+  /* We add our own fields at the end */
+  int cylinders;
+  int heads;
+  int sectors;
+};
+
+struct memdiskinfo * query_memdisk(int drive)
+{
+  static struct memdiskinfo mm;
+  uint32_t _eax, _ebx, _ecx, _edx;
+  uint16_t _es, _di;
+  unsigned char _dl = drive;
+
+  __asm {
+    .386 ;
+    mov eax, 454d0800h ;
+    mov ecx, 444d0000h ;
+    mov edx, 53490000h ;
+    mov dl, _dl ;
+    mov ebx, 3f4b0000h ;
+    int 13h ;
+    mov _eax, eax ;
+    mov _ecx, ecx ;
+    mov _edx, edx ;
+    mov _ebx, ebx ;
+    mov _es, es ;
+    mov _di, di
+      }
+  
+  if ( _eax >> 16 != 0x4d21 ||
+       _ecx >> 16 != 0x4d45 ||
+       _edx >> 16 != 0x4944 ||
+       _ebx >> 16 != 0x4b53 )
+    return NULL;
+
+  _fmemcpy((void far *)&mm, (void far *)MK_FP(_es,_di), 26);
+  mm.cylinders = ((_ecx >> 8) & 0xff) + ((_ecx & 0xc0) << 2) + 1;
+  mm.heads     = ((_edx >> 8) & 0xff) + 1;
+  mm.sectors   = (_ecx & 0x3f);
+  
+  return &mm;
+}
+
+
+int main(int argc, char *argv[])
+{
+  int d;
+  int found = 0;
+  struct memdiskinfo *m;
+
+  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"
+            "\tCmdline = %Fs\n",
+            d, m->version >> 8, m->version & 0xff,
+            m->base, m->size, m->cylinders, m->heads, m->sectors,
+            m->cmdline);
+      found++;
+    }
+  }
+  
+  return found;
+}
diff --git a/sample/mdiskchk.com b/sample/mdiskchk.com
new file mode 100755 (executable)
index 0000000..0391f94
Binary files /dev/null and b/sample/mdiskchk.com differ