/* * FreeLoader * Copyright (C) 1998-2002 Brian Palmer * * 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; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License along * with this program; if not, write to the Free Software Foundation, Inc., * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. */ .text .code16 #define ASM #include #include #define SCREEN_ATTR 0x1f /* Bright white on blue background */ .macro SAVE_CPU_REGS movl %eax,i386_EAX movl %ebx,i386_EBX movl %ecx,i386_ECX movl %edx,i386_EDX movl %esp,i386_ESP movl %ebp,i386_EBP movl %esi,i386_ESI movl %edi,i386_EDI movw %ds,%ax movw %ax,i386_DS movw %es,%ax movw %ax,i386_ES movw %fs,%ax movw %ax,i386_FS movw %gs,%ax movw %ax,i386_GS movw %ss,%ax movw %ax,i386_SS popl %eax movl %eax,i386_EIP popl %eax movw %ax,i386_CS popl %eax movl %eax,i386_EFLAGS movl %cr0,%eax movl %eax,i386_CR0 //movl %cr1,%eax //movl %eax,i386_CR1 movl %cr2,%eax movl %eax,i386_CR2 movl %cr3,%eax movl %eax,i386_CR3 movl %dr0,%eax movl %eax,i386_DR0 movl %dr1,%eax movl %eax,i386_DR1 movl %dr2,%eax movl %eax,i386_DR2 movl %dr3,%eax movl %eax,i386_DR3 movl %dr6,%eax movl %eax,i386_DR6 movl %dr7,%eax movl %eax,i386_DR7 sgdt i386_GDTR sidt i386_IDTR sldt i386_LDTR str i386_TR .endm i386ExceptionHandlerText: .ascii "An error occured in FreeLoader\n" .ascii VERSION .ascii "\n" .asciz "Report this error to the ReactOS Development mailing list \n\n" i386DivideByZeroText: .asciz "Exception 00: DIVIDE BY ZERO\n\n" i386DebugExceptionText: .asciz "Exception 01: DEBUG EXCEPTION\n\n" i386NMIExceptionText: .asciz "Exception 02: NON-MASKABLE INTERRUPT EXCEPTION\n\n" i386BreakpointText: .asciz "Exception 03: BREAKPOINT (INT 3)\n\n" i386OverflowText: .asciz "Exception 04: OVERFLOW\n\n" i386BoundExceptionText: .asciz "Exception 05: BOUND EXCEPTION\n\n" i386InvalidOpcodeText: .asciz "Exception 06: INVALID OPCODE\n\n" i386FPUNotAvailableText: .asciz "Exception 07: FPU NOT AVAILABLE\n\n" i386DoubleFaultText: .asciz "Exception 08: DOUBLE FAULT\n\n" i386CoprocessorSegmentText: .asciz "Exception 09: COPROCESSOR SEGMENT OVERRUN\n\n" i386InvalidTSSText: .asciz "Exception 0A: INVALID TSS\n\n" i386SegmentNotPresentText: .asciz "Exception 0B: SEGMENT NOT PRESENT\n\n" i386StackExceptionText: .asciz "Exception 0C: STACK EXCEPTION\n\n" i386GeneralProtectionFaultText: .asciz "Exception 0D: GENERAL PROTECTION FAULT\n\n" i386PageFaultText: .asciz "Exception 0E: PAGE FAULT\n\n" i386CoprocessorErrorText: .asciz "Exception 10: COPROCESSOR ERROR\n\n" i386AlignmentCheckText: .asciz "Exception 11: ALIGNMENT CHECK\n\n" i386MachineCheckText: .asciz "Exception 12: MACHINE CHECK\n\n" i386_EAX_Text: .asciz "EAX: " i386_EBX_Text: .asciz "EBX: " i386_ECX_Text: .asciz "ECX: " i386_EDX_Text: .asciz "EDX: " i386_ESP_Text: .asciz " ESP: " i386_EBP_Text: .asciz " EBP: " i386_ESI_Text: .asciz " ESI: " i386_EDI_Text: .asciz " EDI: " i386_CS_Text: .asciz "CS: " i386_DS_Text: .asciz "DS: " i386_ES_Text: .asciz "ES: " i386_FS_Text: .asciz "FS: " i386_GS_Text: .asciz "GS: " i386_SS_Text: .asciz "SS: " i386_EFLAGS_Text: .asciz " EFLAGS: " i386_EIP_Text: .asciz " EIP: " i386_ERROR_CODE_Text: .asciz " ERROR CODE: " i386_CR0_Text: .asciz " CR0: " i386_CR1_Text: .asciz " CR1: " i386_CR2_Text: .asciz " CR2: " i386_CR3_Text: .asciz " CR3: " i386_DR0_Text: .asciz " DR0: " i386_DR1_Text: .asciz " DR1: " i386_DR2_Text: .asciz " DR2: " i386_DR3_Text: .asciz " DR3: " i386_DR6_Text: .asciz " DR6: " i386_DR7_Text: .asciz " DR7: " i386_GDTR_Text: .asciz " GDTR Base: " i386_IDTR_Text: .asciz " IDTR Base: " i386_Limit_Text: .asciz " Limit: " i386_LDTR_Text: .asciz " LDTR: " i386_TR_Text: .asciz " TR: " i386FramesText: .asciz "Frames:\n" /* Set by each exception handler to the address of the description text */ i386ExceptionDescriptionText: .long 0 /* Used to store the contents of all the registers when an exception occurs */ i386_EAX: .long 0 i386_EBX: .long 0 i386_ECX: .long 0 i386_EDX: .long 0 i386_ESP: .long 0 i386_EBP: .long 0 i386_ESI: .long 0 i386_EDI: .long 0 i386_CS: .word 0 i386_DS: .word 0 i386_ES: .word 0 i386_FS: .word 0 i386_GS: .word 0 i386_SS: .word 0 i386_EFLAGS: .long 0 i386_EIP: .long 0 i386_ERROR_CODE: .long 0 i386_CR0: .long 0 i386_CR1: .long 0 i386_CR2: .long 0 i386_CR3: .long 0 i386_DR0: .long 0 i386_DR1: .long 0 i386_DR2: .long 0 i386_DR3: .long 0 i386_DR6: .long 0 i386_DR7: .long 0 i386_GDTR: .word 0 .long 0 i386_IDTR: .word 0 .long 0 i386_LDTR: .word 0 i386_TR: .word 0 /* Used to store the current X and Y position on the screen */ i386_ScreenPosX: .long 0 i386_ScreenPosY: .long 0 /************************************************************************/ i386CommonExceptionHandler: .code32 SAVE_CPU_REGS pushl $SCREEN_ATTR call _MachVideoClearScreen add $4,%esp movl $i386ExceptionHandlerText,%esi call i386PrintText movl i386ExceptionDescriptionText,%esi call i386PrintText movl $i386_EAX_Text,%esi call i386PrintText movl i386_EAX,%eax call i386PrintHexDword // Display EAX movl $i386_ESP_Text,%esi call i386PrintText movl i386_ESP,%eax call i386PrintHexDword // Display ESP movl $i386_CR0_Text,%esi call i386PrintText movl i386_CR0,%eax call i386PrintHexDword // Display CR0 movl $i386_DR0_Text,%esi call i386PrintText movl i386_DR0,%eax call i386PrintHexDword // Display DR0 movl $0,i386_ScreenPosX incl i386_ScreenPosY movl $i386_EBX_Text,%esi call i386PrintText movl i386_EBX,%eax call i386PrintHexDword // Display EBX movl $i386_EBP_Text,%esi call i386PrintText movl i386_EBP,%eax call i386PrintHexDword // Display EBP movl $i386_CR1_Text,%esi call i386PrintText movl i386_CR1,%eax call i386PrintHexDword // Display CR1 movl $i386_DR1_Text,%esi call i386PrintText movl i386_DR1,%eax call i386PrintHexDword // Display DR1 movl $0,i386_ScreenPosX incl i386_ScreenPosY movl $i386_ECX_Text,%esi call i386PrintText movl i386_ECX,%eax call i386PrintHexDword // Display ECX movl $i386_ESI_Text,%esi call i386PrintText movl i386_ESI,%eax call i386PrintHexDword // Display ESI movl $i386_CR2_Text,%esi call i386PrintText movl i386_CR2,%eax call i386PrintHexDword // Display CR2 movl $i386_DR2_Text,%esi call i386PrintText movl i386_DR2,%eax call i386PrintHexDword // Display DR2 movl $0,i386_ScreenPosX incl i386_ScreenPosY movl $i386_EDX_Text,%esi call i386PrintText movl i386_EDX,%eax call i386PrintHexDword // Display EDX movl $i386_EDI_Text,%esi call i386PrintText movl i386_EDI,%eax call i386PrintHexDword // Display EDI movl $i386_CR3_Text,%esi call i386PrintText movl i386_CR3,%eax call i386PrintHexDword // Display CR3 movl $i386_DR3_Text,%esi call i386PrintText movl i386_DR3,%eax call i386PrintHexDword // Display DR3 incl i386_ScreenPosY movl $55,i386_ScreenPosX movl $i386_DR6_Text,%esi call i386PrintText movl i386_DR6,%eax call i386PrintHexDword // Display DR6 incl i386_ScreenPosY movl $55,i386_ScreenPosX movl $i386_DR7_Text,%esi call i386PrintText movl i386_DR7,%eax call i386PrintHexDword // Display DR7 movl $0,i386_ScreenPosX incl i386_ScreenPosY incl i386_ScreenPosY movl $i386_CS_Text,%esi call i386PrintText movw i386_CS,%ax call i386PrintHexWord // Display CS movl $i386_EIP_Text,%esi call i386PrintText movl i386_EIP,%eax call i386PrintHexDword // Display EIP movl $0,i386_ScreenPosX incl i386_ScreenPosY movl $i386_DS_Text,%esi call i386PrintText movw i386_DS,%ax call i386PrintHexWord // Display DS movl $i386_ERROR_CODE_Text,%esi call i386PrintText movl i386_ERROR_CODE,%eax call i386PrintHexDword // Display ERROR CODE movl $0,i386_ScreenPosX incl i386_ScreenPosY movl $i386_ES_Text,%esi call i386PrintText movw i386_ES,%ax call i386PrintHexWord // Display ES movl $i386_EFLAGS_Text,%esi call i386PrintText movl i386_EFLAGS,%eax call i386PrintHexDword // Display EFLAGS movl $0,i386_ScreenPosX incl i386_ScreenPosY movl $i386_FS_Text,%esi call i386PrintText movw i386_FS,%ax call i386PrintHexWord // Display FS movl $i386_GDTR_Text,%esi call i386PrintText movl i386_GDTR+2,%eax call i386PrintHexDword // Display GDTR Base movl $i386_Limit_Text,%esi call i386PrintText movw i386_GDTR,%ax call i386PrintHexWord // Display GDTR Limit movl $0,i386_ScreenPosX incl i386_ScreenPosY movl $i386_GS_Text,%esi call i386PrintText movw i386_GS,%ax call i386PrintHexWord // Display GS movl $i386_IDTR_Text,%esi call i386PrintText movl i386_IDTR+2,%eax call i386PrintHexDword // Display IDTR Base movl $i386_Limit_Text,%esi call i386PrintText movw i386_IDTR,%ax call i386PrintHexWord // Display IDTR Limit movl $0,i386_ScreenPosX incl i386_ScreenPosY movl $i386_SS_Text,%esi call i386PrintText movw i386_SS,%ax call i386PrintHexWord // Display SS movl $i386_LDTR_Text,%esi call i386PrintText movw i386_LDTR,%ax call i386PrintHexWord // Display LDTR movl $i386_TR_Text,%esi call i386PrintText movw i386_TR,%ax call i386PrintHexWord // Display TR movl $0,i386_ScreenPosX incl i386_ScreenPosY incl i386_ScreenPosY call i386PrintFrames // Display frames incl i386_ScreenPosY incl i386_ScreenPosY cli i386ExceptionHandlerHang: hlt jmp i386ExceptionHandlerHang iret i386PrintFrames: movl $0,i386_ScreenPosX movl $i386FramesText,%esi call i386PrintText movl i386_EBP,%edi printnextframe: test %edi,%edi je nomoreframes movl $STACK32ADDR,%eax cmpl %edi,%eax jbe nomoreframes movl 4(%edi),%eax pushl %edi call i386PrintHexDword // Display frame popl %edi incl i386_ScreenPosX incl i386_ScreenPosX movl 0(%edi),%edi jmp printnextframe nomoreframes: ret /************************************************************************/ /* AL = Char to display */ /************************************************************************/ i386PrintChar: .code32 pushl i386_ScreenPosY pushl i386_ScreenPosX pushl $SCREEN_ATTR andl $0xff,%eax pushl %eax call _MachVideoPutChar addl $16,%esp ret /************************************************************************/ /* ESI = Address of text to display */ /************************************************************************/ i386PrintText: .code32 i386PrintTextLoop: lodsb // Check for end of string char cmp $0,%al je i386PrintTextDone // Check for newline char cmp $0x0a,%al jne i386PrintTextLoop2 incl i386_ScreenPosY movl $0,i386_ScreenPosX jmp i386PrintTextLoop i386PrintTextLoop2: call i386PrintChar incl i386_ScreenPosX jmp i386PrintTextLoop i386PrintTextDone: ret /************************************************************************/ /* Prints the value in EAX on the screen in hex */ /************************************************************************/ i386PrintHexDword: .code32 call i386PrintHex1 i386PrintHex1: call i386PrintHex2 i386PrintHex2: call i386PrintHex3 i386PrintHex3: movb $4,%cl rol %cl,%eax push %eax andb $0x0f,%al movl $i386PrintHexTable,%ebx xlat /*$i386PrintHexTable*/ call i386PrintChar incl i386_ScreenPosX pop %eax ret i386PrintHexTable: .ascii "0123456789ABCDEF" /************************************************************************/ /* Prints the value in AX on the screen in hex */ /************************************************************************/ i386PrintHexWord: .code32 call i386PrintHexWord1 i386PrintHexWord1: call i386PrintHexWord2 i386PrintHexWord2: movb $4,%cl rol %cl,%ax push %eax andb $0x0f,%al movl $i386PrintHexTable,%ebx xlat /*$i386PrintHexTable*/ call i386PrintChar incl i386_ScreenPosX pop %eax ret /************************************************************************/ /* Prints the value in AL on the screen in hex */ /************************************************************************/ i386PrintHexByte: .code32 call i386PrintHexByte1 i386PrintHexByte1: movb $4,%cl rol %cl,%al push %eax andb $0x0f,%al movl $i386PrintHexTable,%ebx xlat /*$i386PrintHexTable*/ call i386PrintChar incl i386_ScreenPosX pop %eax ret /************************************************************************/ EXTERN(i386DivideByZero) .code32 movl $i386DivideByZeroText,i386ExceptionDescriptionText jmp i386CommonExceptionHandler /************************************************************************/ EXTERN(i386DebugException) .code32 movl $i386DebugExceptionText,i386ExceptionDescriptionText jmp i386CommonExceptionHandler /************************************************************************/ EXTERN(i386NMIException) .code32 movl $i386NMIExceptionText,i386ExceptionDescriptionText jmp i386CommonExceptionHandler /************************************************************************/ EXTERN(i386Breakpoint) .code32 movl $i386BreakpointText,i386ExceptionDescriptionText jmp i386CommonExceptionHandler /************************************************************************/ EXTERN(i386Overflow) .code32 movl $i386OverflowText,i386ExceptionDescriptionText jmp i386CommonExceptionHandler /************************************************************************/ EXTERN(i386BoundException) .code32 movl $i386BoundExceptionText,i386ExceptionDescriptionText jmp i386CommonExceptionHandler /************************************************************************/ EXTERN(i386InvalidOpcode) .code32 movl $i386InvalidOpcodeText,i386ExceptionDescriptionText jmp i386CommonExceptionHandler /************************************************************************/ EXTERN(i386FPUNotAvailable) .code32 movl $i386FPUNotAvailableText,i386ExceptionDescriptionText jmp i386CommonExceptionHandler /************************************************************************/ EXTERN(i386DoubleFault) .code32 popl %eax movl %eax,i386_ERROR_CODE movl $i386DoubleFaultText,i386ExceptionDescriptionText jmp i386CommonExceptionHandler /************************************************************************/ EXTERN(i386CoprocessorSegment) .code32 movl $i386CoprocessorSegmentText,i386ExceptionDescriptionText jmp i386CommonExceptionHandler /************************************************************************/ EXTERN(i386InvalidTSS) .code32 popl %eax movl %eax,i386_ERROR_CODE movl $i386InvalidTSSText,i386ExceptionDescriptionText jmp i386CommonExceptionHandler /************************************************************************/ EXTERN(i386SegmentNotPresent) .code32 popl %eax movl %eax,i386_ERROR_CODE movl $i386SegmentNotPresentText,i386ExceptionDescriptionText jmp i386CommonExceptionHandler /************************************************************************/ EXTERN(i386StackException) .code32 popl %eax movl %eax,i386_ERROR_CODE movl $i386StackExceptionText,i386ExceptionDescriptionText jmp i386CommonExceptionHandler /************************************************************************/ EXTERN(i386GeneralProtectionFault) .code32 popl %eax movl %eax,i386_ERROR_CODE movl $i386GeneralProtectionFaultText,i386ExceptionDescriptionText jmp i386CommonExceptionHandler /************************************************************************/ EXTERN(i386PageFault) .code32 popl %eax movl %eax,i386_ERROR_CODE movl $i386PageFaultText,i386ExceptionDescriptionText jmp i386CommonExceptionHandler /************************************************************************/ EXTERN(i386CoprocessorError) .code32 movl $i386CoprocessorErrorText,i386ExceptionDescriptionText jmp i386CommonExceptionHandler /************************************************************************/ EXTERN(i386AlignmentCheck) .code32 movl $i386AlignmentCheckText,i386ExceptionDescriptionText jmp i386CommonExceptionHandler /************************************************************************/ EXTERN(i386MachineCheck) .code32 movl $i386MachineCheckText,i386ExceptionDescriptionText jmp i386CommonExceptionHandler /************************************************************************ * DEBUGGING SUPPORT FUNCTIONS ************************************************************************/ EXTERN(_INSTRUCTION_BREAKPOINT1) .code32 pushl %eax movl 8(%esp),%eax movl %eax,%dr0 movl %dr7,%eax andl $0xfff0ffff,%eax orl $0x00000303,%eax movl %eax,%dr7 popl %eax ret EXTERN(_MEMORY_READWRITE_BREAKPOINT1) .code32 pushl %eax movl 8(%esp),%eax movl %eax,%dr0 movl %dr7,%eax andl $0xfff0ffff,%eax orl $0x00030303,%eax movl %eax,%dr7 popl %eax ret EXTERN(_MEMORY_WRITE_BREAKPOINT1) .code32 pushl %eax movl 8(%esp),%eax movl %eax,%dr0 movl %dr7,%eax andl $0xfff0ffff,%eax orl $0x00010303,%eax movl %eax,%dr7 popl %eax ret EXTERN(_INSTRUCTION_BREAKPOINT2) .code32 pushl %eax movl 8(%esp),%eax movl %eax,%dr1 movl %dr7,%eax andl $0xff0fffff,%eax orl $0x0000030c,%eax movl %eax,%dr7 popl %eax ret EXTERN(_MEMORY_READWRITE_BREAKPOINT2) .code32 pushl %eax movl 8(%esp),%eax movl %eax,%dr1 movl %dr7,%eax andl $0xff0fffff,%eax orl $0x0030030c,%eax movl %eax,%dr7 popl %eax ret EXTERN(_MEMORY_WRITE_BREAKPOINT2) .code32 pushl %eax movl 8(%esp),%eax movl %eax,%dr1 movl %dr7,%eax andl $0xff0fffff,%eax orl $0x0010030c,%eax movl %eax,%dr7 popl %eax ret EXTERN(_INSTRUCTION_BREAKPOINT3) .code32 pushl %eax movl 8(%esp),%eax movl %eax,%dr2 movl %dr7,%eax andl $0xf0ffffff,%eax orl $0x00000330,%eax movl %eax,%dr7 popl %eax ret EXTERN(_MEMORY_READWRITE_BREAKPOINT3) .code32 pushl %eax movl 8(%esp),%eax movl %eax,%dr2 movl %dr7,%eax andl $0xf0ffffff,%eax orl $0x03000330,%eax movl %eax,%dr7 popl %eax ret EXTERN(_MEMORY_WRITE_BREAKPOINT3) .code32 pushl %eax movl 8(%esp),%eax movl %eax,%dr2 movl %dr7,%eax andl $0xf0ffffff,%eax orl $0x01000330,%eax movl %eax,%dr7 popl %eax ret EXTERN(_INSTRUCTION_BREAKPOINT4) .code32 pushl %eax movl 8(%esp),%eax movl %eax,%dr3 movl %dr7,%eax andl $0x0fffffff,%eax orl $0x000003c0,%eax movl %eax,%dr7 popl %eax ret EXTERN(_MEMORY_READWRITE_BREAKPOINT4) .code32 pushl %eax movl 8(%esp),%eax movl %eax,%dr3 movl %dr7,%eax andl $0x0fffffff,%eax orl $0x300003c0,%eax movl %eax,%dr7 popl %eax ret EXTERN(_MEMORY_WRITE_BREAKPOINT4) .code32 pushl %eax movl 8(%esp),%eax movl %eax,%dr3 movl %dr7,%eax andl $0x0fffffff,%eax orl $0x100003c0,%eax movl %eax,%dr7 popl %eax ret