source: bootcd/isolinux/syslinux-6.03/gpxe/src/arch/i386/interface/pcbios/biosint.c

Last change on this file was e16e8f2, checked in by Edwin Eefting <edwin@datux.nl>, 3 years ago

bootstuff

  • Property mode set to 100644
File size: 2.7 KB
Line 
1#include <errno.h>
2#include <realmode.h>
3#include <biosint.h>
4
5/**
6 * @file BIOS interrupts
7 *
8 */
9
10FILE_LICENCE ( GPL2_OR_LATER );
11
12/**
13 * Hook INT vector
14 *
15 * @v interrupt         INT number
16 * @v handler           Offset within .text16 to interrupt handler
17 * @v chain_vector      Vector for chaining to previous handler
18 *
19 * Hooks in an i386 INT handler.  The handler itself must reside
20 * within the .text16 segment.  @c chain_vector will be filled in with
21 * the address of the previously-installed handler for this interrupt;
22 * the handler should probably exit by ljmping via this vector.
23 */
24void hook_bios_interrupt ( unsigned int interrupt, unsigned int handler,
25                           struct segoff *chain_vector ) {
26        struct segoff vector = {
27                .segment = rm_cs,
28                .offset = handler,
29        };
30
31        DBG ( "Hooking INT %#02x to %04x:%04x\n",
32              interrupt, rm_cs, handler );
33
34        if ( ( chain_vector->segment != 0 ) ||
35             ( chain_vector->offset != 0 ) ) {
36                /* Already hooked; do nothing */
37                DBG ( "...already hooked\n" );
38                return;
39        }
40
41        copy_from_real ( chain_vector, 0, ( interrupt * 4 ),
42                         sizeof ( *chain_vector ) );
43        DBG ( "...chaining to %04x:%04x\n",
44              chain_vector->segment, chain_vector->offset );
45        if ( DBG_LOG ) {
46                char code[64];
47                copy_from_real ( code, chain_vector->segment,
48                                 chain_vector->offset, sizeof ( code ) );
49                DBG_HDA ( *chain_vector, code, sizeof ( code ) );
50        }
51
52        copy_to_real ( 0, ( interrupt * 4 ), &vector, sizeof ( vector ) );
53        hooked_bios_interrupts++;
54}
55
56/**
57 * Unhook INT vector
58 *
59 * @v interrupt         INT number
60 * @v handler           Offset within .text16 to interrupt handler
61 * @v chain_vector      Vector containing address of previous handler
62 *
63 * Unhooks an i386 interrupt handler hooked by hook_i386_vector().
64 * Note that this operation may fail, if some external code has hooked
65 * the vector since we hooked in our handler.  If it fails, it means
66 * that it is not possible to unhook our handler, and we must leave it
67 * (and its chaining vector) resident in memory.
68 */
69int unhook_bios_interrupt ( unsigned int interrupt, unsigned int handler,
70                            struct segoff *chain_vector ) {
71        struct segoff vector;
72
73        DBG ( "Unhooking INT %#02x from %04x:%04x\n",
74              interrupt, rm_cs, handler );
75
76        copy_from_real ( &vector, 0, ( interrupt * 4 ), sizeof ( vector ) );
77        if ( ( vector.segment != rm_cs ) || ( vector.offset != handler ) ) {
78                DBG ( "...cannot unhook; vector points to %04x:%04x\n",
79                      vector.segment, vector.offset );
80                return -EBUSY;
81        }
82
83        DBG ( "...restoring to %04x:%04x\n",
84              chain_vector->segment, chain_vector->offset );
85        copy_to_real ( 0, ( interrupt * 4 ), chain_vector,
86                       sizeof ( *chain_vector ) );
87
88        chain_vector->segment = 0;
89        chain_vector->offset = 0;
90        hooked_bios_interrupts--;
91        return 0;
92}
Note: See TracBrowser for help on using the repository browser.