* 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
;
; ****************************************************************************
+%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]
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:
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
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)
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.
/* 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);
} 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;
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;
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");
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",
--- /dev/null
+/* -*- 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;
+}