david/ipxe
david
/
ipxe
Archived
1
0
Fork 0

(Redoing check-in lost by SourceForge's failure.)

Add method for hooking real-mode interrupt vectors.
This commit is contained in:
Michael Brown 2006-05-13 11:19:06 +00:00
parent f7b963da51
commit 847f38f4ac
2 changed files with 74 additions and 0 deletions

View File

@ -0,0 +1,17 @@
#ifndef BIOSINT_H
#define BIOSINT_H
/**
* @file BIOS interrupts
*
*/
struct segoff;
extern void hook_bios_interrupt ( unsigned int interrupt, unsigned int handler,
struct segoff *chain_vector );
extern int unhook_bios_interrupt ( unsigned int interrupt,
unsigned int handler,
struct segoff *chain_vector );
#endif /* BIOSINT_H */

View File

@ -0,0 +1,57 @@
#include <errno.h>
#include <realmode.h>
#include <biosint.h>
/**
* @file BIOS interrupts
*
*/
/**
* Hook INT vector
*
* @v interrupt INT number
* @v handler Offset within .text16 to interrupt handler
* @v chain_vector Vector for chaining to previous handler
*
* Hooks in an i386 INT handler. The handler itself must reside
* within the .text16 segment. @c chain_vector will be filled in with
* the address of the previously-installed handler for this interrupt;
* the handler should probably exit by ljmping via this vector.
*/
void hook_bios_interrupt ( unsigned int interrupt, unsigned int handler,
struct segoff *chain_vector ) {
struct segoff vector = {
.segment = rm_cs,
.offset = handler,
};
copy_from_real ( chain_vector, 0, ( interrupt * 4 ),
sizeof ( *chain_vector ) );
copy_to_real ( 0, ( interrupt * 4 ), &vector, sizeof ( vector ) );
}
/**
* Unhook INT vector
*
* @v interrupt INT number
* @v handler Offset within .text16 to interrupt handler
* @v chain_vector Vector containing address of previous handler
*
* Unhooks an i386 interrupt handler hooked by hook_i386_vector().
* Note that this operation may fail, if some external code has hooked
* the vector since we hooked in our handler. If it fails, it means
* that it is not possible to unhook our handler, and we must leave it
* (and its chaining vector) resident in memory.
*/
int unhook_bios_interrupt ( unsigned int interrupt, unsigned int handler,
struct segoff *chain_vector ) {
struct segoff vector;
copy_from_real ( &vector, 0, ( interrupt * 4 ), sizeof ( vector ) );
if ( ( vector.segment != rm_cs ) || ( vector.offset != handler ) )
return -EBUSY;
copy_to_real ( 0, ( interrupt * 4 ), chain_vector,
sizeof ( *chain_vector ) );
return 0;
}