From: Jan Kratochvil Date: Mon, 6 Sep 2021 14:40:22 +0000 (+0200) Subject: int13sniff: Move the .S file locally as Sourceforge has no longer any X-Git-Url: http://git.jankratochvil.net/?p=www.jankratochvil.net.git;a=commitdiff_plain;h=152b34fec3a02f764a2810aa4a815b9047851e6e int13sniff: Move the .S file locally as Sourceforge has no longer any HTTP access to CVS repositories. --- diff --git a/project/int13sniff/Index.pm b/project/int13sniff/Index.pm index e5292c2..45651a9 100644 --- a/project/int13sniff/Index.pm +++ b/project/int13sniff/Index.pm @@ -33,7 +33,7 @@ our @ListItem=( "priority"=>370, "icon"=>"int13sniff-icon.png", "summary"=>'Trace PC bootloader disk operations', - "download-source"=>'http://surprise.cvs.sourceforge.net/viewvc/surprise/surprise/misc/int13sniff.S?content-type=text/plain', + "download-source"=>'int13sniff.S', "download-gzip(1)ped floppy image head"=>'int13sniff.bin.gz', "link-parent Surprise project"=>"/project/surprise/", "license"=>"GPL", diff --git a/project/int13sniff/int13sniff.S b/project/int13sniff/int13sniff.S new file mode 100644 index 0000000..c82675e --- /dev/null +++ b/project/int13sniff/int13sniff.S @@ -0,0 +1,1019 @@ +/* + * misc/int13sniff.S + * + * Copyright (C) 2000 + * Partition Surprise Team + * + * $Id: int13sniff.S,v 1.4 2001/02/13 00:47:18 kratochvil Exp $ + */ + + +/* + * + * Sniffer for INT13 calls + * + * Prepare your floppy and reboot from it with 0x80 disk for boot-sniffing: + * ANY DATA ON YOUR FLOPPY (/dev/fd0) WILL BE ERASED BY THIS COMMAND! + * + * make int13sniff.fd0 + * + * + */ + + +/* !!! All defines below must be COMMENTED-OUT ! + * !!! Define to value 0 has no effect. + */ + +/* Enable of normal screen dump output. + * You can probably never need to undefine it, only if it severly + * harms some needed (fullscreen) application display output. + */ +#define SCREEN_PRINT 1 + +/* Enable (if defined) dump output to all serials found + */ +#define SERIAL_BAUDRATE 9600 + +/* Enable to refuse dumping output to port without DSR active + * - pro: doesn't get slow by dumping to not-connected ports + * - con: some cables may not have DSR (DTR<->DSR wiring would be sufficient) + */ +#define SERIAL_REQUIRE_DSR + +/* Enable to dump all messages back to floppy + * - con: message output is slowed down a bit + * WARNING: some BIOSes fail to report geometry (INT 0x13/AH=0x08) for HDD! + */ +#define OUTPUT_STORE_DISK 0x00 + +/* Linear sector offset where to start writing buffer sectors + * If undefined, it is calculated to be the last sector of "int13sniff.bin". +#define OUTPUT_STORE_ADDRESS -1 + */ + +/* Stack size to reserve in the top-memory area + * WARNING: Due to SECTORS_LEN reading, this value MUST be always >= + * than the sector size (0x200)! + */ +#define STACKSIZE_TOP 0x200 + +/* Maintainers: Disable occupying of any (0x13 & 0x18) interrupt vectors +#define DISABLE_SNIFF 1 + */ + +/* Maintainers: Disable .org macroinstructions: ONLY FOR compilation tuning! + * - image produced doen't have any functionality! +#define DISABLE_ORG 1 + */ + + +/* Internal defines */ +#define SERIAL_SENDWAIT 16 /* multiplied by 0x10000, Linux kernel has ~15 (looping 1E6 times) */ +#define SERIAL_LCR_INIT (UART_LCR_WLEN8) /* 8N1, no DLAB */ +#define SERIAL_MCR_INIT (UART_MCR_DTR | UART_MCR_RTS) /* we are RTSed! */ +#define MEM_KBYTES 0x413 /* BIOS variable */ +#define PORTADDR_BASE 0x400 /* BIOS variable */ +#define SECTOR2_MAGIC 0xEFBE +#define SERIAL_DIVISOR (115200/SERIAL_BAUDRATE) +#define OUTPUT_STORE_WRITE_RETRIES 5 /* how many times to try Write16 & ResetDisk sequence */ +#define OUTPUT_STORE_EOF 26 + +#define DIVIDE_UP(what,by) (((what)+(by)-1)/(by)) +#define ROUND_UP(what,by) (DIVIDE_UP((what),(by))*(by)) + +#define ALLOC_KB DIVIDE_UP((ALLOC_END-START)+STACKSIZE_TOP,0x400) +#define SECTORS_LEN ((SECTORS_END-START)/0x200) + + +#define NIBBLE_TO_HEX1(nibble) ('0'+(nibble)+('A'-('9'+1))*((nibble&8)&&((nibble&2)||(nibble&4)))) +#define NIBBLE_TO_HEX(nibble) NIBBLE_TO_HEX1((nibble)&0xF) +#define BYTE_TO_HEX(byte) NIBBLE_TO_HEX((byte)>>4),NIBBLE_TO_HEX((byte)) + +/* Extract from : */ +#define UART_TX 0 /* Out: Transmit buffer (DLAB=0) */ +#define UART_DLL 0 /* Out: Divisor Latch Low (DLAB=1) */ +#define UART_IER 1 /* Out: Interrupt Enable Register (DLAB=0) */ +#define UART_DLM 1 /* Out: Divisor Latch High (DLAB=1) */ +#define UART_LCR 3 /* Out: Line Control Register */ +#define UART_MCR 4 /* Out: Modem Control Register */ +#define UART_LSR 5 /* In: Line Status Register */ +#define UART_MSR 6 /* In: Modem Status Register */ + +#define UART_LCR_DLAB 0x80 /* Divisor latch access bit */ +#define UART_LCR_WLEN8 0x03 /* Wordlength: 8 bits */ + +#define UART_MCR_RTS 0x02 /* RTS complement */ +#define UART_MCR_DTR 0x01 /* DTR complement */ + +#define UART_MSR_DSR 0x20 /* Data Set Ready */ + +#define UART_LSR_THRE 0x20 /* Transmit-hold-register empty */ + + +/* Macros: */ + + .macro outchar char + movw $0x0E00 | \char,%ax + movw $7,%bx + int $0x10 + .endm + + .macro stosw_sniff +#ifdef DISABLE_SNIFF + nop +#else + stosw +#endif + .endm + +#ifdef DISABLE_ORG +#define MYORG(offset) +#else +#define MYORG(offset) .org (offset) + START /* "+ START" MUST be on the end of line - WHY?!? */ +#endif + + .macro pushALL + pushw %ax + pushw %bx + pushw %cx + pushw %dx + pushw %si + pushw %di + pushw %bp + .endm + + .macro popALL + popw %bp + popw %di + popw %si + popw %dx + popw %cx + popw %bx + popw %ax + .endm + +#define PUSHALL_SIZE (7*2) +#define PUSHALL_SI ((1/*%bp*/+1/*%di*/)*2) + + .macro CallJumpVector0x13 + pushf /* create 'lret' stack by this pushf... */ + pushw %cs /* ...this segment... */ + call JumpVector0x13 /* ...and this return address */ + .endm + + + +/* Code starts here */ +/********************/ + +#ifdef HAVE_GAS_ARCH_I8086 + .arch i8086,nojumps +#endif + .code16 + .text + .globl _start +_start: + +/* init stack */ +START: + cli /* just a paranoia, shouldn't be needed */ + jmp InitRawStack /* We don't want to have 0x90 on offset 2 (one of recognization rules by DOS) */ + .org START+0x03 + + .macro places offset length string + .org (\offset) + START + .ascii "\string" + .org (\offset) + (\length) + START /* we can't check whether it isn't too short :-( */ + .endm + .macro placex offset length bytes + .org (\offset) + START + .byte \bytes + .org (\offset) + (\length) + START /* we can't check whether it isn't too short :-( */ + .endm + +/* We rather supply empty (=zeroed) FAT filesystem table + */ + places 0x03,8,"I13Sniff" /* OEM ID */ + placex 0x43,4,"0x5E,0x81,0xA2,0x99" /* Volume Serial Number: 5E81A299 as "SERIAL99" */ + places 0x47,11,"Int13Sniff\0" /* Volume Label */ + places 0x52,8,"BootOnly" /* Filesystem ID */ + +InitRawStack: + .org 0x5A + START + + xorw %ax,%ax + movw %ax,%ss + movw $0x7C00,%sp + sti + outchar '1' + ljmp $0x7C0/*segment*/ , $InitContinue7C0-START/*offset*/ + +InitContinue7C0: + outchar '3' + +/* move to top memory */ + xorw %dx,%dx /* DX=null */ + movw %dx,%ds + movw %ds:MEM_KBYTES,%ax + subw $ALLOC_KB,%ax + movw %ax,%ds:MEM_KBYTES + movb $6,%cl + shlw %cl,%ax + movw %ax,%es + xorw %bx,%bx /* buffer=ES:BX= topram:0x0000 */ + movw $0x0200 | SECTORS_LEN,%ax /* READ16 (SECTORS_LEN) sectors */ + xorw %dx,%dx /* Head 0, Drive 0x00 */ + call ReadSectors + xorw %di,%di + pushw %cs + popw %ds + xorw %si,%si + movw $0x200/2,%cx +repe cmpsw + pushw %es + movw $InitContinueTop-START,%ax + pushw %ax + movw $BadCmpMsg-START,%si + jnz PrintFatal + cmpw $SECTOR2_MAGIC,%es:(Sector2_MagicBuf-START) + je LReturn1 +/* fallthru */ +PrintFatal: + call PrintString +PrintFatal_dead: + jmp PrintFatal_dead +LReturn1: + lret + +Return1: + ret + +/* Interface to retry-capable INT13, set everything except CX */ +/* function may destroy DS value! */ +ReadSectors: + movw $0x0001,%cx /* Cylinder 0, Sector 1 */ + int $0x13 + jnc Return1 + pushw %dx /* save drive for resetting the controller */ + pushw %ax /* error code in AH */ + movw $InitMsg-START,%si + call PrintString + pushw %bx /* offset... */ + pushw %es /* and segment of bufffer */ + pushw %ax /* count */ + pushw %dx /* head */ + pushw %cx /* CX */ + pushw %dx /* drive */ + movw $SF13_02_Msg-START,%si + call PrintString + movw $SnifferErrTail_MSG-START,%si + call PrintString_noPref + movb $0x00,%ah /* reset controller - FDC or HDC */ + popw %dx /* restore the drive */ + int $0x13 + jmp ReadSectors + +PrintTrailNL: + movw $TrailNL_Msg-START,%si + jmp PrintString_noPref + +/* String is given in SI, returns updated SI */ +PrintString: + movb $'%',%al + call PrintChar +PrintString_noPref: + pushw %cs + popw %ds +PrintString_loop: + cld + lodsb + testb %al,%al + jz Return1 + movw $PrintString_loop-START,%bx /* from now do just 'ret' to close the loop */ + pushw %bx + testb $0x80,%al /* should be (x&E0==E0) */ + jz PrintChar + testb $0x10,%al + jz PrintString_no0x + pushw %ax + movb $'$',%al + call PrintChar + popw %ax +PrintString_no0x: + popw %bx /* discard $PrintString_loop-START */ + popw %bx /* return address */ + popw %dx /* value to print */ + pushw %bx /* return back the return address */ + movw $PrintString_loop-START,%bx + pushw %bx + testb $0x02,%al + jz PrintString_noHhex + pushw %ax + pushw %dx + call PrintString_Lhex + popw %dx + popw %ax +PrintString_noHhex: + movb %dl,%dh + testb $0x01,%al +Return1_jump1: + jz Return1 + +/* One byte to print is in DH */ +PrintString_Lhex: + pushw %dx + movb $4,%cl + rorb %cl,%dh + call PrintString_Nhex + popw %dx + +/* One nibble to print is in the lower one of DH */ +PrintString_Nhex: + andb $0x0F,%dh + addb $'0',%dh + cmpb $'9'+1,%dh + jc PrintString_charDH + addb $'A'-('9'+1),%dh +PrintString_charDH: + movb %dh,%al +/* fallthru */ + +/* Character is given in AL + * Preserves: DS, ES, SI, DI + * Destroys: AX (even AL!), BX, CX, DX + * DS is sometimes left preserved, sometimes set to DS=CS + */ +PrintChar: +#ifdef SCREEN_PRINT + movb $0x0E,%ah /* print character */ + movw $7,%bx + pushw %ax + int $0x10 + popw %ax +#else + xorb %bh,%bh /* assumed below */ +#endif +#if defined(SERIAL_BAUDRATE) || defined(OUTPUT_STORE_DISK) + pushw %cs + popw %ds /* set DS=CS */ + cmpb %bh,%ds:(SerialEnable-START) + jz Return1_jump1 +#ifdef SERIAL_BAUDRATE + jmp SerialPrintChar +#else /* SERIAL_BAUDRATE */ + jmp OutputStorePrintChar +#endif /* SERIAL_BAUDRATE */ +#else /* defined(SERIAL_BAUDRATE) || defined(OUTPUT_STORE_DISK) */ + ret +#endif /* defined(SERIAL_BAUDRATE) || defined(OUTPUT_STORE_DISK) */ + + +#if defined(SERIAL_BAUDRATE) || defined(OUTPUT_STORE_DISK) +SerialEnable: + .byte 0 /* map of port bits which want to be enabled */ + +#ifdef OUTPUT_STORE_DISK +#define OUTPUT_STORE_SerialEnable (0x02) /* FloppyPrintChar enabled */ +#else +#define OUTPUT_STORE_SerialEnable (0x00) +#endif + +#endif + +InitMsg: + .asciz "INIT: " +BadCmpMsg: + .asciz "Disk 0x00 sector 0 doesn't match myself!" +SF13_02_Msg: + .ascii "Read" +Common16disk_Msg: + .asciz "16(drv=\xF1,CX=\xF3,head=\xF2,count=\xF1,buf=\xF3:\xF3)" +SnifferErrTail_MSG: + .ascii "=\xF2 !" +TrailNL_Msg: + .byte 13,10,0 + +/*******************************************************************/ +/* Storage area - code isn't needed to be primary-sector reachable */ +/*******************************************************************/ + +/**************************************************************/ +/* Final primary-sector signature */ +/**************************************************************/ + + MYORG(0x1FC) + .byte 0xDE,0xAD /* FAT32 defines somehow extended, 32-bit signature (=> 0xDEAD) */ + .byte 0x55,0xAA + +/**************************************************************/ +/* Section run during boot but from the upper half of code */ +/**************************************************************/ + + +/* Main initialization */ +/***********************/ +/* DS invalid, ES==CS */ +InitContinueTop: + outchar ':' + + pushw %cs + cli + popw %ss + movw $ALLOC_KB*1024,%sp + sti + +#ifdef OUTPUT_STORE_DISK + movw $OutputStoreBufSpaceStart-START,%di + movw $((OutputStoreBuf+0x200-OutputStoreBufSpaceStart)+1)/2,%cx /* NOTE_1: Buffer may got +1 overfilled */ + xorw %ax,%ax + rep stosw +#endif + +#ifndef SERIAL_BAUDRATE +#ifdef OUTPUT_STORE_DISK + movb $OUTPUT_STORE_SerialEnable,%cs:(SerialEnable-START) +#endif + movw $HelloMsg-START,%si + call PrintString +#else /* SERIAL_BAUDRATE */ + movb $0x55|OUTPUT_STORE_SerialEnable,%es:(SerialEnable-START) + movw $HelloMsg-START,%si + call PrintString /* this string will not have EOL when SERIAL_BAUDRATE is defined */ + movb %ds:(SerialEnable-START),%cl + movw $PORTADDR_BASE,%si +SerialHello_loop: + xorw %ax,%ax + movw %ax,%ds + lodsw + rorb $1,%cl + jnc SerialHello_skipOne + testw %ax,%ax + jz SerialHello_skipOne + pushw %cx /* push SerialEnable mask, S=1 */ + pushw %si /* push PORTADDR_BASE+x pointer, S=2 */ + pushw %ax /* print port base */ + movw $SerialHelloPort_Msg-START,%si + call PrintString_noPref + popw %si /* restore PORTADDR_BASE+x pointer, S=1 */ + popw %cx /* restore SerialEnable mask, S=0 */ +SerialHello_skipOne: + rorb $1,%cl /* skip unused even bits of SerialEnable mask */ + cmpw $PORTADDR_BASE+4*2,%si + jne SerialHello_loop + call PrintTrailNL +#endif + +/* now install our SniffFunction0x13 sniffer */ + + xorw %ax,%ax + movw %ax,%ds + movw $0x13*4,%si + pushw %cs + popw %es + movw $OrigVector0x13-START,%di + pushw %si + movw $SniffFunction0x13-START,%ax + cld + cli + movsw + movsw + popw %di /* = $0x13*4 */ + pushw %ds + popw %es /* = null */ + stosw_sniff /* $SniffFunction0x13-START */ + pushw %cs + popw %ax + stosw_sniff + movw $0x18*4,%di /* ROM basic - failed boot */ + movw $SniffFunction0x18-START,%ax + stosw_sniff + pushw %cs + popw %ax + stosw_sniff + sti +#ifdef OUTPUT_STORE_DISK + incb %cs:(OutputStoreFlushEnable-START) /* we have now functional JumpVector0x13 */ +#endif + /* we WANT DS left with 0x0000 */ + /* we WANT ES left with 0x0000 */ + +/* and give the system control to disk=0x80/masterboot */ + movw $0x0201,%ax /* READ16 1 sector */ + movw $0x7C00,%bx /* buffer=ES:BX= 0x0000:0x7C00 */ + pushw %ds + pushw %bx /* BX/DS on stack for later 'lret', S=2, prepared for far ret */ + movw $0x0080,%dx /* Head 0, Drive 0x80 */ + call ReadSectors /* it returns only when successfully read */ + cmpw $0xAA55,%es:(0x7C00+0x1FE) /* 0x55,0xAA */ + movw $BadSignatureMsg-START,%si + jne PrintFatal_jump1 + cli /* IMPORTANT: Boot sectors must be run with CLI! */ + lret /* lret to 0x0000:0x7C00 */ + +SniffFunction0x18: + movw $Interrupt0x18Msg-START,%si /* %ds gets fixed in PrintFatal */ +PrintFatal_jump1: + jmp PrintFatal + + +/* SerialPort handling code */ +/****************************/ + +#ifdef SERIAL_BAUDRATE + +SerialPrintChar: + +/* Function assumes DS == CS, it preserves SI, DI, ES but uses ES==0 ! */ +/* Function expects character to print in AL, preserves it. */ + +/* fallthru */ +SerialLoop: + movb $0,%ah /* offset from PORTADDR_BASE for port #1 */ + xorw %bx,%bx /* any register */ + pushw %es /* push ES, S=1 */ + movw %bx,%es + +SerialLoop_loop: + movw $PORTADDR_BASE,%bx + addb %ah,%bl + movw %es:(%bx),%bx + testw %bx,%bx + jz SerialLoop_noport /* now we have port base in BX */ + movb $1,%ch + movb %ah,%cl + rolb %cl,%ch + testb %ch,%ds:(SerialEnable-START) + jz SerialLoop_noport /* disabled port */ + pushw %ax /* push CHARACTER and AH(port offset), S=2 */ + cmpb $'%',%al + jnz SerialLoop_noInit + +/* Serial Init */ + leaw UART_IER(%bx),%dx /* DX=+1, UAT_IER - interrupt enable */ + xorb %al,%al /* NO interrupts */ + outb %al,%dx + incw %dx + incw %dx /* DX=+3, UART_LCR - used as divisor enable */ + movb $SERIAL_LCR_INIT | UART_LCR_DLAB,%al + outb %al,%dx + movw %bx,%dx /* DX=+0, UART_DLL - divisor LOW */ + movb $(SERIAL_DIVISOR & 0xFF),%al + outb %al,%dx + incw %dx /* DX=+1, UART_DLM - divisor HIGH */ + movb $(SERIAL_DIVISOR >> 8),%al + outb %al,%dx + incw %dx + incw %dx /* DX=+3, UART_LCR - line control */ + movb $SERIAL_LCR_INIT,%al + outb %al,%dx + incw %dx /* DX=+4, UART_MCR - modem control */ + movb $SERIAL_MCR_INIT,%al + outb %al,%dx + incw %dx /* DX=+5, UART_LSR - line status */ + inb %dx,%al + incb %al + jz PrintChar_serial_invalidPort /* LSR port is 0xFF - no device on the bus */ + +#ifdef SERIAL_REQUIRE_DSR + incw %dx /* DX=+6, UART_MSR - modem status */ + xorw %cx,%cx /* Try ~ 60msec for DSR transition delayd by pure wiring after our DTR */ +PrintChar_serialWaitDSR: + inb %dx,%al + andb $UART_MSR_DSR,%al /* we MUST have AL==0 when passing to invalidPort ! */ + jnz PrintChar_serialSend + loop PrintChar_serialWaitDSR + jmp PrintChar_serial_invalidPort +#endif /* SERIAL_REQUIRE_DSR */ + +SerialLoop_loop_jump1: + jmp SerialLoop_loop + +SerialLoop_noInit: /* still CHARACTER and AH(port offset) on stack, S=2 */ +PrintChar_serialSend: + movb $SERIAL_SENDWAIT,%ah +PrintChar_serialSend_wait: + leaw UART_LSR(%bx),%dx /* UART_LSR - line status */ + inb %dx,%al + andb $UART_LSR_THRE,%al /* test transmitter-buffer-empty bit */ + jnz PrintChar_serialSend_free /* we MUST have AL==0 when passing to invalidPort ! */ + loop PrintChar_serialSend_wait + decb %ah /* out-loop count SERIAL_SENDWAIT */ + jnz PrintChar_serialSend_wait +PrintChar_serial_invalidPort: + leaw UART_MCR(%bx),%dx /* UART_LSR - line status */ + outb %al,%dx /* assumed AL==0: turn off DTR & RTS of the failing port */ + movb %ds:(SerialEnable-START),%ah + pushw %ax /* pushed AH(SerialEnable), S=3 */ + movb %al,%ds:(SerialEnable-START) /* assumed AL==0; disable temporarily complete serial output */ + pushw %si /* save SI, S=4 */ + pushw %bx /* port base to print out */ + movw $SerialPortError_Msg-START,%si + call PrintString + popw %si /* recover SI, S=3 */ + popw %bx /* restored BH=AH(SerialEnable), S=2 */ + popw %ax /* restored CHARACTER and AH(port offset), S=1 */ + movb %ah,%cl + movb $0xFE /* ==~1 */,%ch + rolb %cl,%ch /* masking-out pattern */ + andb %ch,%bh /* mask-out the original SerialEnable left in BH */ + movb %bh,%ds:(SerialEnable-START) /* disable the failed port for futher serial dumping */ + jmp SerialLoop_noport + +PrintChar_serialSend_free: + movw %bx,%dx /* UART_TX - xmit buffer */ + popw %ax /* restored CHARACTER and AH(port offset), S=1 */ + outb %al,%dx /* final character transmit */ + +SerialLoop_noport: + inc %ah + inc %ah /* skip by two bytes of PORTADDR_BASE entry offset */ + cmp $4*2,%ah + jne SerialLoop_loop_jump1 + popw %es /* pop ES, S=0 */ +#ifndef OUTPUT_STORE_DISK + ret +#else +/* FALLTHRU */ +#endif +#endif /* SERIAL_BAUDRATE */ + +/* OutputStore handling code */ +/*****************************/ + +#ifdef OUTPUT_STORE_DISK + +#if OUTPUT_STORE_DISK!=0x00 +#error "int13sniff WILL destroy the data on OUTPUT_STORE_DISK!!! Are you sure?" +#endif + +OutputStorePrintChar: + +/* Function assumes DS == CS, it preserves SI, DI, ES. */ +/* Function expects character to print in AL. */ + + testb $OUTPUT_STORE_SerialEnable,%ds:(SerialEnable-START) + jz Return3 +OS_NotDisabled: + cmp $13,%al /* we completely ignore and filter-out all '\r' */ + je Return3 + pushw %es /* SAVE %ES */ + pushw %di /* SAVE %DI */ + pushw %si /* SAVE %SI */ + movw %ds:(OutputStoreBufPtr-START),%di + pushw %cs + popw %es /* ES=CS */ + stosb +OutputStoreTerminate: /* we will terminate the OutputStoreBuf at the given %DI position */ + movw %di,%ds:(OutputStoreBufPtr-START) + movb $OUTPUT_STORE_EOF,%ds:(%di) + cmpb $0,%ds:(OutputStoreFlushEnable-START) + jz Return2pop_jump1 /* we cannot yet call CallJumpVector0x13 */ + cmpb $10,%al + je OutputStoreFlush /* always flush bufer on message newline */ + cmpw $(OutputStoreBuf-START)+0x200,%di + jnc OutputStoreFlush +Return2pop_jump1: + jmp Return2pop + +Return3: + ret + +OutputStoreFlush: + movw $OUTPUT_STORE_WRITE_RETRIES,%bp +OS_RetryWrite: + mov $0x08,%ah /* %AH=get drive geometry, WARNING: DESTROYS %DI! */ + mov $OUTPUT_STORE_DISK,%dl + CallJumpVector0x13 /* now %DH=maximum heads, %CX=maximum cylinder§or */ + jc OS_MediaOver + movw %cx,%bx + xchg %bh,%bl + rol $1,%bh + rol $1,%bh + andb $0x03,%bh /* now %BX==# of cylinders */ + andb $0x3F,%cl /* now %CL==# of sectors */ + pushw %cx /* SAVE LOW==# of sectors */ + inc %dh /* now %DH==# of heads */ + movb %dh,%al + mulb %cl /* now %AX==# of sectors in cylinder */ + movw %ax,%cx + /* now we have %CX==# of sectors in cylinder, %BX=# of cylinders */ + movw %cs:(OutputStoreAddress-START+0),%ax + movw %cs:(OutputStoreAddress-START+2),%dx /* %DX:%AX==OutputStoreAddress */ + divw %cx /* now %AX==cylinder, %DX==head§or */ + cmp %ax,%bx + popw %bx /* RESTORE ->%BL==# of sectors */ + jc OS_MediaOver /* cylinders exceeded */ + xchg %ax,%dx + divb %bl /* now %AL==head, %AH=0-based sector (and %DX==cylinder) */ + incb %ah /* now %AL==head, %AH=1-based sector (and %DX==cylinder) */ + testb $0xC0,%ah + jnz OS_MediaOver + testb $0xFC,%dh + jnz OS_MediaOver + movb %ah,%cl + movb %dl,%ch + rorb $1,%dh + rorb $1,%dh + orb %dh,%cl /* now %CX==cylinder§or in BIOS format */ + movb %al,%dh /* now %DH==head */ + pushw %cs + popw %ds /* DS=CS */ + movb $OUTPUT_STORE_DISK,%dl + movw $0x0301,%ax /* %AH=write sectors, %AL=1 sector */ + movw $(OutputStoreBuf-START),%bx + pushw %cs + popw %es /* ES=CS */ + CallJumpVector0x13 + jnc OS_WriteOK + movw %ax,%es /* %ES=Write16 error code */ + xorb %ah,%ah /* %AH=reset drive */ + CallJumpVector0x13 + decw %bp + jnz OS_RetryWrite + andb $~OUTPUT_STORE_SerialEnable,%ds:(SerialEnable-START) /* OutputStorePrintChar got DISABLED here */ + pushw %es /* Write16 error code, for secondary "SnifferErrTail_MSG" */ + /* now parameters for "Common16disk_Msg": */ + pushw %bx /* buf 2nd */ + pushw %cs /* buf 1st (%ES has been destroyed by "Write16 error code" */ + movb $0x01,%al /* "count" has been destroyed by "reset disk" call */ + pushw %ax /* count */ + pushw %dx /* head */ + pushw %cx /* CX */ + pushw %dx /* drive */ + +OS_MediaOver: + movw $OutputFailedWrite_Msg-START,%si + call PrintString + movw $Common16disk_Msg-START,%si + call PrintString_noPref /* pops up 6*2 bytes (6 words) */ + movw $SnifferErrTail_MSG-START,%si + call PrintString_noPref /* pops up 1*2 bytes (1 word ) */ +Return2pop: + popw %si /* RESTORE %SI */ + popw %di /* RESTORE %DI */ + popw %es /* RESTORE %ES */ +Return2: ret + +OS_WriteOK: + cmpw $(OutputStoreBuf-START)+0x200,%ds:(OutputStoreBufPtr-START) + jc Return2pop /* buffer is not yet filled */ + incw %ds:(OutputStoreAddress-START+0) + jnz OS_IncAddrNotWordCarry + incw %ds:(OutputStoreAddress-START+2) +OS_IncAddrNotWordCarry: + movw $OutputStoreBuf-START,%di + pushw %di + xorw %ax,%ax + movw $0x200/2,%cx + rep stosw /* OutputStore got cleared */ + popw %di + movb $10,%al /* we want to immediately Flush even the new sector */ + jmp OutputStoreTerminate + +#endif /* OUTPUT_STORE_DISK */ + +/**************************************************************/ +/* Section for INT13 sniffing */ +/* THIS point may start to be after 0x200 boundary */ +/**************************************************************/ + +SniffFunction0x13: + pushw %ax /* trash */ + pushw %ds + pushALL + + cmpb $0x00,%ah /* reset */ + jne SF13_not00 + movw $JumpVector0x13popa-START,%ax + pushw %ax /* return address */ + pushw %dx /* drive */ + movw $SF13_00_Msg-START,%si +JumpVector0x13printStringPopa: + call PrintString + jmp PrintTrailNL + +SF13_not00: + cmpb $0x02,%ah /* read16 */ + jne SF13_not02 + pushw %bx /* buf 2nd */ + pushw %es /* buf 1st */ + pushw %ax /* count */ + pushw %dx /* head */ + pushw %cx /* CX */ + pushw %dx /* drive */ + movw $SF13_02_Msg-START,%si + call PrintString +Sniffer13bottomStdHalf: + call CallVector0x13 + movw $SnifferOKTail_Msg-START,%si + jnc SF13_not00_tail /* ...if CY is SET */ +Sniffer13DumpErrorAH: + movw $SnifferErrTail_MSG-START,%si + pushw %ax +SF13_not00_tail: +Sniffer13iretPrintStringFinal: + call PrintString_noPref + popALL + popw %ds + incw %sp + incw %sp /* trash discarded */ + iret + +SF13_not02: + cmpb $0x41,%ah /* presence32 */ + jne SF13_not41 + cmpw $0x55AA,%bx + jne SF13_not41 + pushw %dx /* drive */ + movw $SF13_41_Msg-START,%si + call PrintString + call CallVector0x13 + cmp $0xAA55,%bx + jne Sniffer13DumpErrorAH + pushw %cx /* supports */ + pushw %ax /* version */ + movw $SF13_41_out_Msg-START,%si + jmp Sniffer13iretPrintStringFinal + +CallVector0x13: + popw %ax /* return address */ + pushw %bp + movw %sp,%bp + movw %ax,%ss:2/*%bp*/+PUSHALL_SIZE+2/*%ds*/(%bp) /* store %ax to 'trash' */ + popw %bp + popALL + popw %ds + CallJumpVector0x13 + pushw %ds + pushALL /* stack is back to normal NOW */ + pushw %bp /* trash - just to prepare return address16 */ + pushw %ax + pushw %bp + movw %sp,%bp + movw %ss:2/*%bp*/+2/*%ax*/+2/*return16*/+PUSHALL_SIZE+2/*%ds*/(%bp),%ax + movw %ax,%ss:2/*%bp*/+2/*ax*/(%bp) + pushf + pop %ax + movw %ax,%ss:2/*%bp*/+2/*%ax*/+2/*return16*/+PUSHALL_SIZE+2/*%ds*/+2/*trash*/+4/*ret-seg:offs*/(%bp) + popw %bp + popw %ax + ret /* to prepared return16 and now will be stack in normal again */ + +SF13_not41: + cmpb $0x42,%ah /* read32 */ + je SF13_do42 + jmp JumpVector0x13popa /* too far for conditional-jump */ + +SF13_do42: + movb %ds:2(%si),%al /* count */ + pushw %ax + pushw %ds:8(%si) /* LBA32 sector LOWEST */ + pushw %ds:8+2(%si) /* LBA32 sector LOWER */ + pushw %ds:8+4(%si) /* LBA32 sector HIGHER */ + pushw %ds:8+6(%si) /* LBA32 sector HIGHEST */ + pushw %dx /* drive */ + movw $SF13_42_Msg-START,%si + call PrintString /* first half of the entry-message */ + + movw %sp,%bp + movw %ss:PUSHALL_SI(%bp),%si + movw %ss:PUSHALL_SIZE(%bp),%ds /* restore DS:SI packet */ + + movw %ds:4(%si),%ax /* buf16 offset */ + pushw %ax /* buf16 offset */ + andw %ds:4+2(%si),%ax /* buf16 segment */ + pushw %ds:4+2(%si) /* buf16 segment */ + incw %ax + movw $SF13_42_buf16_Msg-START,%si + jnz SF13_42_buf16 /* buf16 was NOT 0xFFFF:0xFFFF => jump as OK */ + addw $4,%sp /* drop buf16 address seg:offs */ + pushw %ds:0x10(%si) /* 64-bit buffer LOWEST */ + pushw %ds:0x10+2(%si) /* 64-bit buffer LOWER */ + pushw %ds:0x10+4(%si) /* 64-bit buffer HIGHER */ + pushw %ds:0x10+6(%si) /* 64-bit buffer HIGHEST */ + movw $SF13_42_buf64_Msg-START,%si + +SF13_42_buf16: /* too far for conditional-jump */ + call PrintString_noPref + jmp Sniffer13bottomStdHalf + +JumpVector0x13popa: + popALL + popw %ds + incw %sp + incw %sp /* trash discarded */ +JumpVector0x13: + .byte 0xEA /* ljmp */ +OrigVector0x13: + .skip 4 + +/* Serial support upper half initialization messages */ +/*****************************************************/ + +#ifdef SERIAL_BAUDRATE + +SerialPortError_Msg: + .asciz "SerialPort \xF3 error: stopping its communication\r\n" + +SerialHelloPort_Msg: + .asciz " \xF3" + +#endif /* SERIAL_BAUDRATE */ + + +/* Main upper half initialization messages */ +/*******************************************/ + +HelloMsg: + .ascii "INT13-Sniff, version ",VERSION,", RCS revision ",REVISION +#ifdef OUTPUT_STORE_DISK + .ascii ", Output Store on disk 0x" + .byte BYTE_TO_HEX(OUTPUT_STORE_DISK) +#endif +#ifdef SERIAL_BAUDRATE + .ascii ", using serial ports:" +#else + .byte 13,10 +#endif + .byte 0 +BadSignatureMsg: + .asciz "Disk 0x80 has invalid signature!" + + +/* Interrupt sniffing messages */ +/*******************************/ + +Interrupt0x18Msg: + .asciz "Interrupt 0x18 - Failed boot!" +SF13_00_Msg: + .asciz "Reset(drv=\xF1)" +SF13_41_Msg: + .asciz "Presence32(drv=\xF1)" +SF13_41_out_Msg: + .ascii "=(version=\xF2,supports=\xF3)" + /* fallthru */ +SnifferOKTail_Msg: + .ascii " OK" + .byte 13,10,0 +SF13_42_Msg: + .asciz "Read32(drv=\xF1,LBA32=\xF3\xE3\xE3\xE3,count=\xF1,buf=" +SF13_42_buf16_Msg: + .asciz "\xF3:\xF3)" +SF13_42_buf64_Msg: + .asciz "\xF3\xE3\xE3\xE3)" + + +/* Output Store messages / variables */ +/*************************************/ +#ifdef OUTPUT_STORE_DISK + +OutputFailedWrite_Msg: + .asciz "Output Store error, stopping store: Write" + +OutputStoreBufPtr: + .word OutputStoreBufSpaceStart-START +OutputStoreAddress: +#ifdef OUTPUT_STORE_ADDRESS + .long OUTPUT_STORE_ADDRESS +#else + .long (OutputStoreBuf-START)/0x200 +#endif +OutputStoreFlushEnable: + .byte 0 /* disable calling of JumpVector0x13 as it is not functional yet */ + +#endif +/**************************************************************/ +/* Sectors finalisation */ +/**************************************************************/ + +#ifndef OUTPUT_STORE_DISK +ALLOC_END: +#endif + + MYORG(ROUND_UP(.+2-START,0x200)-2) +Sector2_MagicBuf: + .word SECTOR2_MAGIC + +#ifdef OUTPUT_STORE_DISK +OutputStoreBuf: +#endif + .ascii "\n\n" +#ifdef OUTPUT_STORE_DISK +OutputStoreBufSpaceStart: + .ascii "Buffer empty, no data stored yet.\n" +#else + .ascii "OUTPUT_STORE_DISK not defined, Output Store disabled!\n" +#endif + .byte OUTPUT_STORE_EOF + + MYORG(ROUND_UP(.-START,0x200)) /* WARNING, we may overfull the buffer by +1 bytes, see NOTE_1 */ + +#ifdef OUTPUT_STORE_DISK + .equ ALLOC_END,.+1 /* we need one 'trash' byte for exceeding OUTPUT_STORE_EOF */ +#endif + +SECTORS_END: + +/* vi:ts=8:sw=8 + */