/* * $Id$ * * Automatically retry all BIOS reads 0x80<->0x81 (and if (drive&0x80) drive^=1; in genral) * * Derived from: * http://www.jankratochvil.net/project/int13sniff/ */ /* !!! All defines below must be COMMENTED-OUT ! * !!! Define to value 0 has no effect. */ /* Reduce size by omitting DOS-boot header signature to fit in 512 bytes. * Cylinder 0 is requierd, sectors per track == 63 assumed! * This constant is counted from 0 !!! */ #define BACKUP_SECTOR 63 /* Reduce size by omitting DOS-boot header signature to fit in 512 bytes. */ #define STRIP_BOOT_HEADER 1 /* Reduce size by omitting INT 0x18 handler. */ #define STRIP_INT18 1 /* Maintainers: Disable .org macroinstructions: ONLY FOR compilation tuning! * - image produced doen't have any functionality! #define DISABLE_ORG 1 */ /* Internal defines */ #define MEM_KBYTES 0x413 /* BIOS variable */ #define MAX_BOOT_SIZE_100 0xb6 /* LILO: leave some space for NT's and DR DOS' dirty */ #define MAX_BOOT_SIZE (MAX_BOOT_SIZE_100+0x100) /* Macros: */ .macro outchar char movw $0x0E00 | \char,%ax movw $7,%bx int $0x10 .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 */ /********************/ .arch i8086,nojumps .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 */ #ifndef STRIP_BOOT_HEADER places 0x03,8,"BIOSRAID" /* OEM ID */ placex 0x43,3,"0x5E,0x81,0xA2" /* Volume Serial Number: 5E81A2?? as "SERIAL??" */ placex 0x43+3,1,BACKUP_SECTOR /* Volume Serial Number: 5E81A23F as "SERIAL??" */ places 0x47,11,"BIOSauRAID\0" /* Volume Label */ places 0x52,8,"BootOnly" /* Filesystem ID */ #else places 0x03,8,"BIOSRAI2" /* OEM ID */ placex 0x03+8,1,BACKUP_SECTOR /* Sanity checked by: biosautoraid.pl */ placex 0x03+9,1,MAX_BOOT_SIZE_100 /* Sanity checked by: biosautoraid.pl */ #endif InitRawStack: #ifndef STRIP_BOOT_HEADER .org 0x5A + START #endif xorw %ax,%ax movw %ax,%ss movw $0x7C00,%sp sti #if 0 outchar '1' #endif ljmp $0x7C0/*segment*/ , $InitContinue7C0-START/*offset*/ InitContinue7C0: #if 0 outchar '2' #endif /* move to top memory */ xorw %dx,%dx /* DX=null */ movw %dx,%ds movw %ds:MEM_KBYTES,%ax decw %ax /* Allocation size: 1KB */ movw %ax,%ds:MEM_KBYTES movb $6,%cl shlw %cl,%ax movw %ax,%es xorw %di,%di /* buffer=ES:DI */ movw $0x7C00,%si movw $0x200/2,%cx rep movsw pushw %es movw $InitContinueTop-START,%ax pushw %ax lret 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 /* 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: movb $0x0E,%ah /* print character */ movw $7,%bx pushw %ax int $0x10 popw %ax Return1: ret SF13_02_Err_Msg: .ascii "Read16" SnifferErrTail_MSG: .ascii "=error!" TrailNL_Msg: .byte 13,10,0 /* Main initialization */ /***********************/ /* DS invalid, ES==CS */ InitContinueTop: #if 0 outchar ':' #endif pushw %cs cli popw %ss movw $1*1024,%sp /* Allocated 1 KB */ sti movw $HelloMsg-START,%si call PrintString /* 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 /* $SniffFunction0x13-START */ pushw %cs popw %ax stosw #ifndef STRIP_INT18 movw $0x18*4,%di /* ROM basic - failed boot */ movw $SniffFunction0x18-START,%ax stosw pushw %cs popw %ax stosw #endif /* !STRIP_INT18 */ sti /* 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 */ /* Interface to retry-capable INT13, set everything except CX */ /* function may destroy DS value! */ ReadSectors: /* These two numbers get remapped to: BACKUP_SECTOR */ movw $0x0080,%dx /* Head 0, Drive 0x80 */ movw $0x0001,%cx /* Cylinder 0, Sector 1 */ int $0x13 jnc PassControl pushw %dx /* save drive for resetting the controller */ movw $SF13_02_Err_Msg-START,%si call PrintString movb $0x00,%ah /* reset controller - FDC or HDC */ popw %dx /* restore the drive */ int $0x13 jmp ReadSectors PassControl: cmpw $0xAA55,%es:(0x7C00+0x1FE) /* 0x55,0xAA */ movw $BadSignatureMsg-START,%si jne PrintFatal cli /* IMPORTANT: Boot sectors must be run with CLI! */ lret /* lret to 0x0000:0x7C00 */ #ifndef STRIP_INT18 SniffFunction0x18: movw $Interrupt0x18Msg-START,%si /* %ds gets fixed in PrintFatal */ #endif /* !STRIP_INT18 */ /* fallthru */ PrintFatal: call PrintString PrintFatal_dead: jmp PrintFatal_dead /**************************************************************/ /* Section for INT13 sniffing */ /* THIS point may start to be after 0x200 boundary */ /**************************************************************/ SF13_not02: cmpb $0x41,%ah /* presence32 */ jne JumpVector0x13popa cmpw $0x55AA,%bx jne JumpVector0x13popa stc jmp SF13_leave JumpVector0x13popa: popALL popw %ds incw %sp incw %sp /* trash discarded */ incw %sp incw %sp /* original %ax discarded */ popw %dx JumpVector0x13: .byte 0xEA /* ljmp */ OrigVector0x13: .skip 4 SniffFunction0x13: pushw %dx /* original %dx */ pushw %ax /* original %ax */ pushw %ax /* trash */ pushw %ds pushALL #if 0 pushw %cx pushw %dx xorw %cx,%cx movw $0x1,%dx wait0: loopw wait0 decw %dx jnz wait0 popw %dx popw %cx #endif cmpb $0x02,%ah /* read16 */ jne SF13_not02 SF13_do02_retry: #if 0 pushw %cx pushw %dx xorw %cx,%cx movw $0x400,%dx wait1: loopw wait1 decw %dx jnz wait1 popw %dx popw %cx #endif pushw %bp movw %sp,%bp movb /*orig-%dl:*/ %ss:2/*%bp*/+PUSHALL_SIZE+2/*%ds*/+2/*trash*/+2/*orig-%ax*/(%bp),%dl xorb %cs:DriveFlipFlag-START,%dl /* %ds not yet initialized by: PrintString */ movb %dl,/*%dl:*/ %ss:2/*%bp*/+2/*%bp*/+2/*%di*/+2/*%si*/(%bp) popw %bp call CallVector0x13 jnc SF13_selfcheck movw $SF13_02_Err_Msg-START,%si pushw %dx call PrintString popw %dx test $0x80,%dl jz SF13_leave /* just a floppy? */ test $0x7E,%dl jnz SF13_leave /* 0x82+ disk? It may be correct unsuccessful read. */ xorb $0x01,%ds:DriveFlipFlag-START /* %ds already initialized by: PrintString */ jmp SF13_do02_retry /* Prevent: Error 17 * as we must hide ourselves to let read GRUB itself frmo the masterboot. */ SF13_selfcheck: test $0x80,%dl jz SF13_leave /* just a floppy? */ test $0x7E,%dl jnz SF13_leave /* 0x82+ disk? It may be correct unsuccessful read. */ cmpw $0x0001,%cx /* Cylinder 0, Sector 1 ? */ jne SF13_leave_zero cmpb $0x00,%dh /* Head 0 ? */ jne SF13_leave_zero movb $BACKUP_SECTOR/63,%dh movb $1+(BACKUP_SECTOR%63),%cl SF13_self_retry: pushw %dx xorb %cs:DriveFlipFlag-START,%dl /* %ds not yet initialized by: PrintString */ movw $0x0201,%ax CallJumpVector0x13 popw %dx jnc SF13_self_ok xorb $0x01,%cs:DriveFlipFlag-START /* %ds not yet initialized by: PrintString */ jmp SF13_self_retry SF13_self_ok: pushw %bp movw %sp,%bp andb $0xFE,%ss:2/*%bp*/+PUSHALL_SIZE+2/*%ds*/+2/*trash*/+2/*orig-%ax*/+2/*orig-%dx*/+4/*ret-seg:offs*/(%bp) /* flags; clear CF */ popw %bp SF13_leave_zero: #if 0 pushw %bp movw %sp,%bp movb /*%al:*/ %ss:2/*%bp*/+2/*%bp*/+2/*%di*/+2/*%si*/+2/*%dx*/+2/*%cx*/+2/*%bx*/(%bp),%al /* count */ movw /*%cx:*/ %ss:2/*%bp*/+2/*%bp*/+2/*%di*/+2/*%si*/+2/*%dx*/(%bp),%cx /* cylinder, sector */ cmpb $BACKUP_SECTOR/63,/*%dh:*/ %ss:2/*%bp*/+2/*%bp*/+2/*%di*/+2/*%si*/+1/*%dl*/(%bp) /* head */ popw %bp jne SF13_leave SF13_leave_zero_loop: andb %al,%al jz SF13_leave cmpw $1+(BACKUP_SECTOR%63),%cx je SF13_leave_zero_found incw %cx addw $0x200,%bx decb %al /* --count */ jmp SF13_leave_zero_loop SF13_leave_zero_found: movw %bx,%di movw $0x200/2,%cx xorw %ax,%ax rep stosw #endif SF13_leave: popALL popw %ds incw %sp incw %sp /* trash discarded */ incw %sp incw %sp /* original %ax discarded */ popw %dx iret CallVector0x13: popw %ax /* return address */ pushw %bp movw %sp,%bp movw %ax,%ss:2/*%bp*/+PUSHALL_SIZE+2/*%ds*/(%bp) /* store %ax to 'trash' */ movw %ss:2/*%bp*/+PUSHALL_SIZE+2/*%ds*/+2/*trash*/(%bp),%ax /* restore original %ax */ movw %ax,%ss:2/*%bp*/+2/*%bp*/+2/*%di*/+2/*%si*/+2/*%dx*/+2/*%cx*/+2/*%bx*/(%bp) /* rewrite from original %ax */ 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*/+2/*orig-%ax*/+2/*orig-%dx*/+4/*ret-seg:offs*/(%bp) popw %bp popw %ax ret /* to prepared return16 and now will be stack in normal again */ /* Main upper half initialization messages */ /*******************************************/ HelloMsg: #if 0 .ascii "BIOSautoRAID, $Id$" #else .ascii "BaR" #endif .byte 13,10 DriveFlipFlag: .byte 0 BadSignatureMsg: #if 0 .asciz "Disk 0x80 has invalid signature!" #else .asciz "bs" #endif /* Interrupt sniffing messages */ /*******************************/ #ifndef STRIP_INT18 Interrupt0x18Msg: #if 0 .asciz "Interrupt 0x18 - Failed boot!" #else .asciz "18" #endif #endif /* !STRIP_INT18 */ /**************************************************************/ /* Final sector signature */ /**************************************************************/ MYORG(MAX_BOOT_SIZE) /* Partition table */ MYORG(0x1FE) .byte 0x55,0xAA /* vi:ts=8:sw=8 */