From 847f38f4ac8a4c2c773ae63d07a8ecc77e7bd78f Mon Sep 17 00:00:00 2001 From: Michael Brown Date: Sat, 13 May 2006 11:19:06 +0000 Subject: [PATCH] (Redoing check-in lost by SourceForge's failure.) Add method for hooking real-mode interrupt vectors. --- src/arch/i386/include/biosint.h | 17 +++++++ src/arch/i386/interface/pcbios/biosint.c | 57 ++++++++++++++++++++++++ 2 files changed, 74 insertions(+) create mode 100644 src/arch/i386/include/biosint.h create mode 100644 src/arch/i386/interface/pcbios/biosint.c diff --git a/src/arch/i386/include/biosint.h b/src/arch/i386/include/biosint.h new file mode 100644 index 00000000..55cb2728 --- /dev/null +++ b/src/arch/i386/include/biosint.h @@ -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 */ diff --git a/src/arch/i386/interface/pcbios/biosint.c b/src/arch/i386/interface/pcbios/biosint.c new file mode 100644 index 00000000..345961ac --- /dev/null +++ b/src/arch/i386/interface/pcbios/biosint.c @@ -0,0 +1,57 @@ +#include +#include +#include + +/** + * @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; +}