From: hpa Date: Wed, 26 Nov 2003 00:10:40 +0000 (+0000) Subject: Add API to query for the existence of MEMDISK. X-Git-Tag: syslinux-3.11~498 X-Git-Url: http://review.tizen.org/git/?a=commitdiff_plain;h=bfae00f12b0ec32d6826f171ff5811d3066a7632;p=platform%2Fupstream%2Fsyslinux.git Add API to query for the existence of MEMDISK. --- diff --git a/NEWS b/NEWS index 26d8267..236ba35 100644 --- 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 diff --git a/memdisk/memdisk.asm b/memdisk/memdisk.asm index f356328..cec4010 100644 --- a/memdisk/memdisk.asm +++ b/memdisk/memdisk.asm @@ -17,6 +17,8 @@ ; ; **************************************************************************** +%include "../version.gen" + ; %define DEBUG_TRACERS ; Uncomment to get debugging tracers %ifdef DEBUG_TRACERS @@ -43,18 +45,23 @@ %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) diff --git a/memdisk/memdisk.doc b/memdisk/memdisk.doc index 700ebec..3d36475 100644 --- a/memdisk/memdisk.doc +++ b/memdisk/memdisk.doc @@ -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. diff --git a/memdisk/memdisk.h b/memdisk/memdisk.h index bc125cc..ace53b0 100644 --- a/memdisk/memdisk.h +++ b/memdisk/memdisk.h @@ -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); diff --git a/memdisk/setup.c b/memdisk/setup.c index a078eec..aff0548 100644 --- a/memdisk/setup.c +++ b/memdisk/setup.c @@ -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 index 0000000..cf2987e --- /dev/null +++ b/sample/mdiskchk.c @@ -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 +#include +#include /* 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 index 0000000..0391f94 Binary files /dev/null and b/sample/mdiskchk.com differ