/*++ Copyright (c) 1990 Microsoft Corporation Module Name: trap.c Author: Thomas Parslow [TomP] Mar-01-90 Abstract: General purpose trap handler for 80386 boot loader. When built in debugger is present, output is redirected to the com port. When no debugger is present, output goes to the display. --*/ #include "su.h" extern USHORT InDebugger; extern UCHAR GDTregister; extern UCHAR IDTregister; extern VOID OutPort( USHORT ); extern USHORT InPort( VOID ); extern VOID ReEnterDebugger( VOID ); extern USHORT TssKernel; extern USHORT Redirect; extern VOID RealMode( VOID ); VOID TrapHandler( IN ULONG, IN USHORT ); VOID DumpProcessorContext( VOID ); VOID DumpSystemRegisters( VOID ); VOID DumpCommonRegisters( VOID ); VOID DisplayFlags( ULONG f ); VOID DumpTSS( VOID ); ULONG GetAddress( VOID ); VOID GetNumber( PCHAR cp ); USHORT GetChar( VOID ); VOID DumpAddress( ULONG ); #define PG_FAULT_MSG " =================== PAGE FAULT ================================= \n\n" #define DBL_FAULT_MSG " ================== DOUBLE FAULT ================================ \n\n" #define GP_FAULT_MSG " ============== GENERAL PROTECTION FAULT ======================== \n\n" #define STK_OVERRUN_MSG " ===== STACK SEGMENT OVERRUN or NOT PRESENT FAULT =============== \n\n" #define EX_FAULT_MSG " ===================== EXCEPTION ================================ \n\n" #define DEBUG_EXCEPTION "\nDEBUG TRAP " #define ishex(x) ( ( x >= '0' && x <= '9') || (x >= 'A' && x <= 'F') || (x >= 'a' && x <= 'f') ) // // Global Trap Frame Pointer // PTF TrapFrame=0; VOID TrapHandler( IN ULONG Padding, IN USHORT TF_base ) /*++ Routine Description: Prints minimal trap information Arguments: 386 Trap Frame on Stack Environment: 16-bit protect mode only. --*/ { // // Initialize global trap frame pointer and print trap number // TrapFrame = (PTF)&TF_base; // // Fix esp to point to where it pointed before trap // TrapFrame->Fesp += 24; BlPrint("\n TRAP %lx ",TrapFrame->TrapNum); // // Print the trap specific header and display processor context // switch(TrapFrame->TrapNum) { case 1: case 3: puts( DEBUG_EXCEPTION ); DumpCommonRegisters(); break; case 8: puts( DBL_FAULT_MSG ); DumpTSS(); break; case 12: puts( STK_OVERRUN_MSG ); DumpProcessorContext(); break; case 13: puts( GP_FAULT_MSG ); DumpProcessorContext(); break; case 14: puts( PG_FAULT_MSG ); BlPrint("** At linear address %lx\n",TrapFrame->Fcr2); DumpProcessorContext(); break; default : puts( EX_FAULT_MSG ); DumpProcessorContext(); break; } RealMode(); while (1); //**** WAITFOREVER *** // } VOID DumpProcessorContext( VOID ) /*++ Routine Description: Dumps all the processors registers. Called whenever a trap or fault occurs. Arguments: None Returns: Nothing --*/ { DumpSystemRegisters(); DumpCommonRegisters(); } VOID DumpSystemRegisters( VOID ) /*++ Routine Description: Dumps (writes to the display or com poirt) the x86 processor control registers only. Does not dump the common registers (see DumpCommonRegisters) Arguments: None Returns: Nothing --*/ { BlPrint("\n tr=%x cr0=%lx cr2=%lx cr3=%lx\n", TrapFrame->Ftr,TrapFrame->Fcr0,TrapFrame->Fcr2,TrapFrame->Fcr3); BlPrint(" gdt limit=%x base=%lx idt limit=%x base=%lx\n", *(PUSHORT)&GDTregister,*(PULONG)(&GDTregister + 2), *(PUSHORT)&IDTregister,*(PULONG)(&IDTregister + 2)); } VOID DumpCommonRegisters( VOID ) /*++ Routine Description: Dumps (writes to the display or com poirt) the x86 processor commond registers only. Arguments: None Returns: Nothing --*/ { USHORT err; // // Is the error code valid or just a padding dword // if ((TrapFrame->TrapNum == 8) || (TrapFrame->TrapNum >= 10 && TrapFrame->TrapNum <= 14) ) err = (USHORT)TrapFrame->Error; else err = 0; // // Display the processor's common registers // BlPrint("\n cs:eip=%x:%lx ss:esp=%x:%lx errcode=%x\n", (USHORT)(TrapFrame->Fcs & 0xffff),TrapFrame->Feip,(USHORT)TrapFrame->Fss,TrapFrame->Fesp,err); DisplayFlags(TrapFrame->Feflags); BlPrint(" eax=%lx ebx=%lx ecx=%lx edx=%lx",TrapFrame->Feax,TrapFrame->Febx,TrapFrame->Fecx,TrapFrame->Fedx); BlPrint(" ds=%x es=%x\n",TrapFrame->Fds,TrapFrame->Fes); BlPrint(" edi=%lx esi=%lx ebp=%lx cr0=%lx",TrapFrame->Fedi,TrapFrame->Fesi,TrapFrame->Febp,TrapFrame->Fcr0); BlPrint(" fs=%x gs=%x\n",TrapFrame->Ffs,TrapFrame->Fgs); } VOID DisplayFlags( ULONG f ) /*++ Routine Description: Writes the value of the key flags in the flags register to the display or com port. Arguments: f - the 32bit flags word Returns: Nothing --*/ { BlPrint(" flags=%lx ",f); if (f & FLAG_CF) puts("Cy "); else puts("NoCy "); if (f & FLAG_ZF) puts("Zr "); else puts("NoZr "); if (f & FLAG_IE) puts("IntEn"); else puts("IntDis "); if (f & FLAG_DF) puts("Up "); else puts("Down "); if (f & FLAG_TF) puts("TrapEn \n"); else puts("TrapDis \n"); } VOID DumpTSS( VOID ) /*++ Routine Description: Writes the contents of the TSS to the display or com port when called after a double fault. Arguments: None Returns: Nothing --*/ { PTSS_FRAME pTss; // FP_SEG(Fp) = Fcs; // FP_OFF(Fp) = Fip; pTss = (PTSS_FRAME) &TssKernel; // // Dump the outgoing TSS // BlPrint("Link %x\n",pTss->Link); BlPrint("Esp0 %x\n",pTss->Esp0); BlPrint("SS0 %x\n",pTss->SS0); BlPrint("Esp1 %lx\n",pTss->Esp1); BlPrint("Cr3 %lx\n",pTss->Cr3); BlPrint("Eip %lx\n",pTss->Eip); BlPrint("Eflg %lx\n",pTss->Eflags); BlPrint("Eax %lx\n",pTss->Eax); BlPrint("Ebx %lx\n",pTss->Ebx); BlPrint("Ecx %lx\n",pTss->Ecx); BlPrint("Edx %lx\n",pTss->Edx); BlPrint("Esp %lx\n",pTss->Esp); BlPrint("Ebp %lx\n",pTss->Ebp); BlPrint("Esi %lx\n",pTss->Esi); BlPrint("Edi %lx\n",pTss->Edi); BlPrint("ES %x\n",pTss->ES); BlPrint("CS %x\n",pTss->CS); BlPrint("SS %x\n",pTss->SS); BlPrint("DS %x\n",pTss->DS); BlPrint("FS %x\n",pTss->FS); BlPrint("GS %x\n",pTss->GS); BlPrint("Ldt %x\n",pTss->Ldt); RealMode(); while(1); } // END OF FILE