6 * @file BIOS interrupts
11 * Hooked interrupt count
13 * At exit, after unhooking all possible interrupts, this counter
14 * should be examined. If it is non-zero, it means that we failed to
15 * unhook at least one interrupt vector, and so must not free up the
16 * memory we are using. (Note that this also implies that we should
17 * re-hook INT 15 in order to hide ourselves from the memory map).
19 int hooked_bios_interrupts = 0;
24 * @v interrupt INT number
25 * @v handler Offset within .text16 to interrupt handler
26 * @v chain_vector Vector for chaining to previous handler
28 * Hooks in an i386 INT handler. The handler itself must reside
29 * within the .text16 segment. @c chain_vector will be filled in with
30 * the address of the previously-installed handler for this interrupt;
31 * the handler should probably exit by ljmping via this vector.
33 void hook_bios_interrupt ( unsigned int interrupt, unsigned int handler,
34 struct segoff *chain_vector ) {
35 struct segoff vector = {
40 DBG ( "Hooking INT %#02x to %04x:%04x\n",
41 interrupt, rm_cs, handler );
43 if ( ( chain_vector->segment != 0 ) ||
44 ( chain_vector->offset != 0 ) ) {
45 /* Already hooked; do nothing */
46 DBG ( "...already hooked\n" );
50 copy_from_real ( chain_vector, 0, ( interrupt * 4 ),
51 sizeof ( *chain_vector ) );
52 DBG ( "...chaining to %04x:%04x\n",
53 chain_vector->segment, chain_vector->offset );
56 copy_from_real ( code, chain_vector->segment,
57 chain_vector->offset, sizeof ( code ) );
58 DBG_HDA ( *chain_vector, code, sizeof ( code ) );
61 copy_to_real ( 0, ( interrupt * 4 ), &vector, sizeof ( vector ) );
62 hooked_bios_interrupts++;
68 * @v interrupt INT number
69 * @v handler Offset within .text16 to interrupt handler
70 * @v chain_vector Vector containing address of previous handler
72 * Unhooks an i386 interrupt handler hooked by hook_i386_vector().
73 * Note that this operation may fail, if some external code has hooked
74 * the vector since we hooked in our handler. If it fails, it means
75 * that it is not possible to unhook our handler, and we must leave it
76 * (and its chaining vector) resident in memory.
78 int unhook_bios_interrupt ( unsigned int interrupt, unsigned int handler,
79 struct segoff *chain_vector ) {
82 DBG ( "Unhooking INT %#02x from %04x:%04x\n",
83 interrupt, rm_cs, handler );
85 copy_from_real ( &vector, 0, ( interrupt * 4 ), sizeof ( vector ) );
86 if ( ( vector.segment != rm_cs ) || ( vector.offset != handler ) ) {
87 DBG ( "...cannot unhook; vector points to %04x:%04x\n",
88 vector.segment, vector.offset );
92 DBG ( "...restoring to %04x:%04x\n",
93 chain_vector->segment, chain_vector->offset );
94 copy_to_real ( 0, ( interrupt * 4 ), chain_vector,
95 sizeof ( *chain_vector ) );
97 chain_vector->segment = 0;
98 chain_vector->offset = 0;
99 hooked_bios_interrupts--;