pepito wrote:It is posible to hook a CALL GATE with a C function using DJGPP?
It is posible to hook a INTERRUPT GATE with a C function using DJGPP?
You can certainly hook the gate using a C function, but you will probably want an asm routine to bounce an interrupt through the gate, since you'll want an
iret instruction at the end.
I use C++ in my kernel and my interrupt gates look something like this.
Code: Select all
class InterruptGate
{
public:
/** Constructs an InterruptGate. */
InterruptGate(u16 segment = 0,
u32 offset = 0,
u08 privilegeLevel = 0,
bool isTrap = false);
/** Dumps the InterruptGate to an output stream. */
std::ostream& printStream(std::ostream& ostr) const;
private:
u16 m_offset00_15;
u16 m_segment;
u08 m_unused2;
u08 m_type:3; /* 6 (INT) or 7 (TRAP) */
u08 m_size:1; /* 0 */
u08 m_isSystemDescriptor:1; /* 0 (16-bit) or 1 (32-bit) */
u08 m_privilegeLevel:2;
u08 m_segmentIsPresent:1; /* 0 (not present) or 1 (present) */
u16 m_offset16_31;
} __attribute__((__packed__);
That's the actual structure the CPU sees when it receives an interrupt.
Here's the implementation of the constructor.
Code: Select all
InterruptGate::
InterruptGate(u16 segment,
u32 offset,
u08 privilegeLevel,
bool isTrap)
: m_offset00_15(offset & 0xffff)
, m_segment(segment)
, m_type(isTrap ? 7 : 6)
, m_size(1)
, m_isSystemDescriptor(0)
, m_privilegeLevel(privilegeLevel)
, m_segmentIsPresent(1)
, m_offset16_31((offset >> 16) & 0xffff)
{ }
The actual hook is something like this, given an instance of the Interrupt Dispatch Table class with an insert() member function.
Code: Select all
extern "C" void _divideErrorException();
extern "C" void _nmiInterrupt();
extern "C" void _breakpointException();
extern "C" void _overflowException();
extern "C" void _boundRangeExceededException();
extern "C" void _invalidOpcodeException();
extern "C" void _deviceNotAvailableException();
extern "C" void _doubleFaultException();
extern "C" void _segmentOverrun();
extern "C" void _invalidTSSException();
extern "C" void _segmentNotPresent();
extern "C" void _stackFaultException();
extern "C" void _generalProtectionFault();
extern "C" void _pageFaultException();
/* ... */
idt.insert(kFAULT_GENERAL_PROTECTION,
InterruptGate(0x08,
(u32)_generalProtectionFault,
0,
false));
Where
_generalProtectionFault is the pointer to an asm trampoline hook.
The trampoline hooks are in GAS format. All they do is push the interrupt/trap number and maybe an error code o the stack and invoke the inetrrupt trampoline. There is one of these hooks for each and every interrupt or trap in the system.
Code: Select all
.macro INTERRUPT LABEL,INT_NUM,HAS_ERROR=no
.text
.globl \LABEL
.type \LABEL,@function
\LABEL:
.ifc \HAS_ERROR,no
pushl 0
.endif
pushl $\INT_NUM
call idtTrampoline
.ifc \HAS_ERROR,no
addl $8,%esp
.else
addl $4,%esp
.endif
iret
.endm
/**
* Reserved CPU interrupt vectors 0 .. 32
*/
INTERRUPT _divideErrorException 0
INTERRUPT _nmiInterrupt 2
INTERRUPT _breakpointException 3
INTERRUPT _overflowException 4
INTERRUPT _boundRangeExceededException 5
INTERRUPT _invalidOpcodeException 6
INTERRUPT _deviceNotAvailableException 7
INTERRUPT _doubleFaultException 8
INTERRUPT _segmentOverrun 9
INTERRUPT _invalidTSSException 10 yes
INTERRUPT _segmentNotPresent 11 yes
INTERRUPT _stackFaultException 12 yes
INTERRUPT _generalProtectionFault 13 yes
INTERRUPT _pageFaultException 14 yes
Finally, the trampoline itself is a namespace-level function. There's only one, and it just calls the interrupt dispatcher object, which then does clever things like call all the chained registered interrupt handlers. All in C++.
Code: Select all
extern "C" void idtTrampoline(long interruptNumber,
int error);
/**
* Bounces a fired interrupt request to the interrupt dispatcher.
*
* @param interruptNumber [IN] The interrupt vector being raised.
* @param error [IN] The error value associated with the trap (if
* any).
*/
void idtTrampoline(long interruptNumber, int error)
{
klog() << "idtTrampoline(" << interruptNumber << ", " << error << ")\n";
gIDT->dispatchInterrupt(interruptNumber);
}
Simple, no? You mileage may vary.
--
smw