Good day to all, Gert Hulselmans requested a feature for MDISKCHK.COM that would function roughly like GETARGS.COM[1] by Murali Krishnan Ganapathy: DOS SET command output for MEMDISK kernel arguments passed by previous boot-loaders. He also needed to support the case for MEMDISK-in-a-MEMDISK type situations, where all MEMDISK kernel arguments could be gathered together and output as a list of DOS SET commands. One way to search for "outer" MEMDISKs is via mBFT and/or INT 13h "safe hook" scanning. To support this, some modifications to MEMDISK were needed to allow the sharing of common structure information to MDISKCHK.COM's source code. Also, one MEMDISK bug was found. If you are currently a GETARGS.COM user and your batch file goes like: @echo off getargs.com>setenv.bat call setenv.bat>nul you can accomplish the same thing with MDISKCHK.COM using: @echo off echo @echo off>setenv.bat mdiskchk.com -b>>setenv.bat call setenv.bat>nul Some of the work done on MEMDISK might be useful for COM32 modules at some point, too. How about getting this[2] merged? Thanks for your time, - Shao Miller [1] http://people.cs.uchicago.edu/~gmurali/gui/downloads.html [2] http://git.etherboot.org/?p=people/sha0/syslinux.git;a=log;h=refs/heads/mdiskchk_enhanced
Gert Hulselmans
2010-Mar-11 14:21 UTC
[syslinux] Enhanced MDISKCHK.COM and MEMDISK patches
Shao Miller wrote:> Good day to all, > > Gert Hulselmans requested a feature for MDISKCHK.COM that would function > roughly like GETARGS.COM[1] by Murali Krishnan Ganapathy: DOS SET > command output for MEMDISK kernel arguments passed by previous > boot-loaders. He also needed to support the case for > MEMDISK-in-a-MEMDISK type situations, where all MEMDISK kernel arguments > could be gathered together and output as a list of DOS SET commands. > > One way to search for "outer" MEMDISKs is via mBFT and/or INT 13h "safe > hook" scanning. To support this, some modifications to MEMDISK were > needed to allow the sharing of common structure information to > MDISKCHK.COM's source code. Also, one MEMDISK bug was found. > > If you are currently a GETARGS.COM user and your batch file goes like: > > @echo off > getargs.com>setenv.bat > call setenv.bat>nul > > you can accomplish the same thing with MDISKCHK.COM using: > > @echo off > echo @echo off>setenv.bat > mdiskchk.com -b>>setenv.bat > call setenv.bat>nul > > Some of the work done on MEMDISK might be useful for COM32 modules at > some point, too. > > How about getting this[2] merged? Thanks for your time, > > - Shao Miller > > [1] http://people.cs.uchicago.edu/~gmurali/gui/downloads.html > [2] > http://git.etherboot.org/?p=people/sha0/syslinux.git;a=log;h=refs/heads/mdiskchk_enhanced >A big thank you. So for an optimal result, you need to compile the MEMDISK version included in your branch? - Gert Hulselmans
Shao Miller wrote:> ...Also, one MEMDISK bug was found...The one bug fix might belong in 3.86, if you agree. git remote add shao git://git.etherboot.org/scm/people/sha0/syslinux.git git fetch shao mdiskchk_enhanced branch, commit 7c0e135251d56554350f64e339a8dc7933fa3053 http://git.etherboot.org/?p=people/sha0/syslinux.git;a=commitdiff;h=7c0e135251d56554350f64e339a8dc7933fa3053 - Shao Miller
Gert Hulselmans
2010-Mar-31 00:43 UTC
[syslinux] Enhanced MDISKCHK.COM and MEMDISK patches
Shao Miller wrote:> Good day to all, > > Gert Hulselmans requested a feature for MDISKCHK.COM that would function > roughly like GETARGS.COM[1] by Murali Krishnan Ganapathy: DOS SET > command output for MEMDISK kernel arguments passed by previous > boot-loaders. He also needed to support the case for > MEMDISK-in-a-MEMDISK type situations, where all MEMDISK kernel arguments > could be gathered together and output as a list of DOS SET commands. > > - Shao MillerI just found out that the Freedos image used by UBCD, didn't use GETARGS.COM by Murali Krishnan Ganapathy. It uses GETARGS.COM by Eric Auer. More specific, the "combined-drivecheck-memdisk-getargs" variant: http://www.mail-archive.com/freedos-user at lists.sourceforge.net/msg01631.html Eric Auer wrote:>> In addition to >> http://www.coli.uni-sb.de/~eric/stuff/soft/specials/tiny-memdisk-getargs.zip >> (which is less than 512 bytes and checks MEMDISK load args, if MD.present)>> there now is >> http://www.coli.uni-sb.de/~eric/stuff/soft/specials/combined-drivecheck-memdisk-getargs.zip >> (which is 1024 bytes small and can detect both MEMDISK and NORMAL >> drives, e.g. useful for finding out whether a B: drive exists, whether >> and for which drive letter MEMDISKs are loaded, and which load args were >> used. Plus it checks the boot loader ID - but only for MEMDISK of >> SYSLINUX/ISOLINUX/... 3.0 and newer!)Sadly the links don't work anymore. Luckily the Wayback Machine exists: http://web.archive.org/web/20060620033233/http://www.coli.uni-saarland.de/~eric/stuff/soft/specials/combined-drivecheck-memdisk-getargs.zip It is written in assembler. This might explain why this version was so much smaller than your version, Shao ;-). - Gert Hulselmans $ cat getargs.asm ; Public domain tool to fetch the load arguments of a MEMDISK ; (virtual disk, created by SYSLINUX MEMDISK tool in int 15h ; memory space after booting with SYSLINUX / ISOLINUX / ... ; to simplyfy booting non-Linux operating systems). Based ; on the IFMEMDSK tool. By Eric Auer 9/2004, BIOS mode and ; MAGIC mode and WHO feature added by Eric Auer 3/2005. %define MAGIC 1 ; magic M option, useful for boot loader ID check ; by errorlevel. %define WHO 0 ; enable to have WHO=char variable in normal ; output to report boot loader ID. Only useful ; for boot loader IDs which are also ASCII chars. ; Returned NORMAL Errorlevel: (without / with Win32 running) ; 0 / 16 - 386 or better CPU but no MEMDISK ; 1 / 17 - A: is a MEMDISK ; 2 / 18 - B: is a MEMDISK ; 3 / 19 - C:, or to be more exact, the first harddisk, BIOS disk ; number 80h, is a MEMDISK ; 253 - invalid command line argument (new 3/2005) ; 254 - the CPU is older than an 80286 ; 255 - the CPU is an 80286 only, so no MEMDISK possible %if MAGIC ; Returned MAGIC Errorlevel: If command line option M (upper case) ; given, errorlevel is the boot loader ID, 49 .. 52 ("1" .. "4"), ; if a syslinux 3.0+ family memdisk is found. If no memdisk or an %if WHO ; older memdisk is found, errorlevel is 88 ("X") or the version of %else ; older memdisk is found, errorlevel is 0 or the version of %endif ; syslinux/memdisk found (at most 2, for 2.xx). %endif ; Returned BIOS MODE Errorlevel: (check type of user-selected drive) ; 0 - no such drive ; 1..63 - drive is CHS with n sectors per track ; 65..127 - same, but drive supports LBA (64 would be LBA-only drive) ; Specify 0..1 for floppy, 2..9 for harddisks 80h..87h. %imacro FLAGCHECK 0 pushf ; save push ax ; test value popf ; try to set flags pushf ; check what happened pop ax ; test results popf ; restore %endmacro org 100h ; a .COM file start: mov si,81h cmd: lodsb cmp al,' ' jz cmd cmp al,9 jz cmd cmp al,13 jbe memdsk ; CLASSIC mode: check for memdisks ; cmp al,'?' ; implicit, all invalid args trigger help ; jz help %if MAGIC cmp al,'M' ; "undocumented" MAGIC mode: ask memdisk jz memdsk_magic ; for boot loader type, if memdisk found. cmp al,'m' ; "undocumented" MAGIC mode: ask memdisk jz memdsk_magic ; for boot loader type, if memdisk found. %endif cmp al,'0' jb help ; invalid argument cmp al,'9' ja help ; invalid argument sub al,'0' cbw ; argument AX: drive number cmp al,2 jb floppy ; floppy, or rather harddisk? add al,80h-2 ; 2..9 -> 80h..87h floppy: jmp biosdsk ; NEW MODE: check BIOS disk properties help: mov ah,9 ; string$ output mov dx,helpmsg ; help text int 21h ; DOS API mov ax,4cfdh ; return errorlevel 253 int 21h ; DOS API - exit %if MAGIC memdsk_magic: mov byte [magjmp+1],0 ; zap the jump-over-magic-errorlevel, ; enable boot loader ID in errorlevel. %endif memdsk: xor bp,bp ; errorlevel dec bp dec bp xor ax,ax ; try to zero all flags mov bx,0f000h ; bit mask for high bits FLAGCHECK and ax,bx ; high bits... cmp ax,bx ; ...stuck to 1? 80186 or older! jz known ; *** is186: errorlevel 254, PC XT inc bp ; next assumption: 286 mov ax,bx ; try to set all high bits FLAGCHECK test ax,bx ; all stuck to 0? 80286! jz known ; *** is286: errorlevel 255, PC AT but no 386+ inc bp ; next: 386, but no memdisk found yet. is386: inc bp ; assumption: errorlevel 1, A: is a memdisk mov dl,0 ; A: call memdiskcheck jc known ; only return first match inc bp ; assumption: errorlevel 2, B: is a memdisk mov dl,1 ; B: call memdiskcheck jc known ; only return first match inc bp ; assumption: errorlevel 3, "C:" is a memdisk mov dl,80h ; "C:" call memdiskcheck jc known ; only return first match noABCmemdisk: xor bp,bp ; errorlevel 0, no memdisk but at least a 386. known: mov ax,bp ; fetch errorlevel cbw ; sign-extend AL to AX add ax,ax mov bx,ax mov ah,9 ; string$ output ds:dx mov dx,echomsg int 21h mov dx,[cs:stringtable+bx] ; fetch appropriate message ; - done: mov ah,9 ; string$ output ds:dx int 21h ; DOS API mov dx,memdisk ; write " MEMDISK." and carriage return, line break mov ah,9 int 21h mov ax,bp ; fetch errorlevel call WinCheck ; check for Win32, add 16 to errorlevel if found %if MAGIC magjmp: jmp short skipmagic ; patch this to enable the next mov al,... mov al,[syslver] ; will be "X" or "1" ... "4" skipmagic: %endif mov ah,4ch ; leave program, errorlevel in AL int 21h ; DOS API memdiskcheck: mov eax,454d0800h ; magic1 + AH=8 (get geometry) mov ecx,444d0000h ; magic2 push dx mov edx,53490000h ; magic3 + pop dx ; ... drive number in DL mov ebx,3f4b0000h ; magic4 int 13h ; BIOS DISK API shr eax,16 ; ignore AX shr ebx,16 ; ignore BX shr ecx,16 ; ignore CX (geometry C/S) shr edx,16 ; ignore DX (geometry H in DH) cmp ax,4d21h ; magic5 jnz nomemdisk cmp cx,4d45h ; magic6 jnz nomemdisk cmp dx,4944h ; magic7 jnz nomemdisk cmp bx,4b53h ; magic8 jnz nomemdisk mov al,[es:di+3] ; major version cmp al,3 ; not supported before SYSLINUX 3.0 jb oldsyslinux mov al,[es:di+26] ; boot loader ID mov [syslver],al ; "1".."4" for sys/pxe/iso/extlinux oldsyslinux: %if MAGIC && WHO ; have to save/restore value if both push ax %endif push es push di les di,[es:di+12] call printcommandline pop di pop es %if MAGIC && WHO pop ax mov [syslver],al ; "1".."4" for sys/pxe/iso/extlinux %endif ; ES:DI now points to a data structure... ; dw bytes, dw version, dd disk address in RAM, ; dd size in sectors, dd pointer to commandline, ; dd old int 13h vector, dd old int 15h vector ; dw old [40h:13h] low memory size value stc ; return success ret nomemdisk: clc ; return failure ret dw pcxt, pcat ; entries -2 and -1 of stringtable! stringtable dw xmem, amem, bmem, cmem echomsg db "@echo $" pcxt db "8086, can't have$" ; 254 pcat db "80286, can't have$" ; 255 xmem db "found no$" ; (in A B HDA) ; 0 (or 16) amem db "A: is$" ; 1 (or 17) bmem db "B: is$" ; 2 (or 18) cmem db "1st harddisk is$" ; 3 (or 19) memdisk db " MEMDISK.",13,10,"$" iswin db "@echo Win/" ; "Win (16 bit)" or "Win (NT-ish)" or ... winbits db "32 DOS box!",13,10,"$" ; editable part ; --- winbits db "32 bit) DOS box!",13,10,"$" ; editable part ; shorter: Win/16, Win/32 or Win/NT WinCheck: push bx push cx push dx push ax mov ax,1683h ; get current virtual machine number xor bx,bx ; preset to 0 if no Win at all running int 2fh or bx,bx pop ax jnz IsWin push ax mov ax,1600h ; Win32 install check int 2fh test al,7fh ; 0 / 80 no Win32, 1 Win2, -1 Win2, 3.. Win 3.. pop ax jnz IsWin push ax mov ax,160ah ; Win3+ version check int 2fh ; (modifies BX and CX as well) or ax,ax ; 0 means Win3+ version check supported pop ax jz IsWin ; version is BH.BL for CPU type CX push ax mov ax,3306h ; get internal DOS version (DOS 5+) int 21h ; returns AL=-1 for older DOS versions cmp bx,3205h ; WinNT/2k/XP/... DOS boxes report version 5.50 pop ax ; (modifies BX and DX as well) jnz WinChecked add al,16 ; change errorlevel mov bx,"NT" ; WinNT family ; --- mov dword [winbits+2],"-ish" ; not " bit", but "-ish" :-) jmp short WinIs32 IsWin: add al,16 ; change errorlevel push ax mov ax,1600h ; do Win32 install check int 2fh or al,al ; major version number, or (Win2) +1/-1 pop ax mov bx,"32" ; assume Win32-ish mode jnz WinIs32 ; ah is minor version number. mov bx,"16" ; not in enhanced / Win386 / Win32 mode ; (the Win3.x 286 (standard mode) DOS extender has no version check) WinIs32: mov word [winbits],bx ; not in enhanced / Win386 / Win32 mode push ax mov dx,iswin mov ah,9 int 21h pop ax WinChecked: pop dx pop cx pop bx ret printcommandline: ; string at ES:DI, 0 terminated, space separated ; http://people.cs.uchicago.edu/~gmurali/gui/comboot/getargs.c skips over ; leading and trailing spaces and treats args without = inside as special. push ax push bx push bp %if WHO jmp short dosyslver ; FIRST, create "SET WHO=loader" line %endif nextcl: mov bx,setline+5 ; target pointer xor bp,bp ; "no = yet" skipcl: mov al,[es:di] inc di or al,al jz donecl cmp al,' ' jz skipcl ; skip leading spaces copycl: cmp al,' ' ; suppress control chars jb evil ; those are evil, skip them cmp al,'=' jnz nosign issign: inc bp ; found a = sign, remember that nosign: mov [bx],al ; save useful byte inc bx evil: mov al,[es:di] ; check next source byte inc di or al,al jz donecl cmp al,' ' jnz copycl ; neither eof nor space? keep copying! donecl: cmp bx,setline+5 jz nocl or bp,bp ; already saw a = sign? else add one! jnz hadsign mov word [bx],"=Y" inc bx inc bx hadsign: mov word [bx],0a0dh ; 13,10 (carriage return, linefeed) mov byte [bx+2],'$' ; end of string dosyslver: mov ah,9 mov dx,setline int 21h ; print string to stdout nocl: dec di ; rewind mov al,[es:di] ; the byte which ended THIS argument or al,al ; end of the whole thing? jnz nextcl ; otherwise repeat for NEXT argument pop bp pop bx pop ax ret %if WHO setline db "@SET WHO=" ; first item: "@SET WHO=bootloaderID" syslver db "X",13,10,"$" ; BUFFER for strings follows %else syslver db 0 ; storage space for boot loader ID setline db "@SET " ; BUFFER for strings follows this %endif ; (will overwrite the biosdsk code in getargs mode, no problem) biosdsk: ; check BIOS disk AX properties mov dl,al ; selected drive number push dx mov ah,8 ; get geometry push es ; push di not needed here int 13h ; BIOS DISK API pop es ; pop di not needed here mov al,dl ; number of disks in this "category" pop dx jc nosuchdrive or al,al jz nosuchdrive and cl,63 mov dh,cl ; intermediate result... push dx mov ax,4100h ; LBA presence check mov bx,55aah ; magic value int 13h ; BIOS DISK API pop dx ; ignore further register messing here cmp bx,0aa55h mov ax,nolbamsg jnz nolbadrive test cx,1 jz nolbadrive mov ax,lbadrivemsg add dh,64 ; flag LBA capability nolbadrive: push dx mov dx,ax ; message mov ah,9 ; show string$ int 21h ; DOS API pop dx mov al,dh ; errorlevel jmp short godos nosuchdrive: mov ah,9 ; show string$ mov dx,nodrivemsg int 21h ; DOS API mov al,0 ; return errorlevel 0 godos: mov ah,4ch ; exit with errorlevel AH int 21h ; DOS API nodrivemsg db "No drive.",13,10,"$" nolbamsg db "Normal CHS drive.",13,10,"$" lbadrivemsg db "LBA-enabled drive.",13,10,"$" ; PS: int 13.15 returned AH is 2 if with disk change detector helpmsg db "Public Domain. Finds MEMDISK, writes SET lines with MD params." db 13,10 db "Returns: 0 no MD, 254/255 pre-386 CPU,",13,10 db " 1-3 found MD on A:-C:, add 16 if inside WinXX",13,10 %if MAGIC ; save space: short help if magic on... db "GETARGS n: n=0/1/2/3-9 check A:/B:/1st-8th harddisk, not MD." db 13,10 db "Returns: 0 none, 1-63 sectors, 64-127 LBA" %else db "Or do 'GETARGS n': n=0/1 check A:/B: disk, " db "n=2..9 check 0x80..0x87 harddisk.",13,10 db "Returns: 0 no disk, 1..63 geometry (S), add 64 if LBA okay." %endif db 13,10 %if MAGIC > WHO ; magic on, but who not (have to save space else) db "GETARGS M:",13,10 db "Returns: 0-2 no/old MD, 3-? boot loader ID",13,10 %endif %if MAGIC && WHO db "GETARGS M: Returns MD 3+ boot loader ID.",13,10 %endif db "$"