[tcp] Allow out-of-order receive queue to be discarded
[gpxe.git] / src / arch / i386 / interface / pcbios / biosint.c
bloba193defa3335ab3f4e2afd1e5323357ae2bda2c3
1 #include <errno.h>
2 #include <realmode.h>
3 #include <biosint.h>
5 /**
6 * @file BIOS interrupts
8 */
10 FILE_LICENCE ( GPL2_OR_LATER );
12 /**
13 * Hook INT vector
15 * @v interrupt INT number
16 * @v handler Offset within .text16 to interrupt handler
17 * @v chain_vector Vector for chaining to previous handler
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.
24 void 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,
31 DBG ( "Hooking INT %#02x to %04x:%04x\n",
32 interrupt, rm_cs, handler );
34 if ( ( chain_vector->segment != 0 ) ||
35 ( chain_vector->offset != 0 ) ) {
36 /* Already hooked; do nothing */
37 DBG ( "...already hooked\n" );
38 return;
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 ) );
52 copy_to_real ( 0, ( interrupt * 4 ), &vector, sizeof ( vector ) );
53 hooked_bios_interrupts++;
56 /**
57 * Unhook INT vector
59 * @v interrupt INT number
60 * @v handler Offset within .text16 to interrupt handler
61 * @v chain_vector Vector containing address of previous handler
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.
69 int unhook_bios_interrupt ( unsigned int interrupt, unsigned int handler,
70 struct segoff *chain_vector ) {
71 struct segoff vector;
73 DBG ( "Unhooking INT %#02x from %04x:%04x\n",
74 interrupt, rm_cs, handler );
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;
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 ) );
88 chain_vector->segment = 0;
89 chain_vector->offset = 0;
90 hooked_bios_interrupts--;
91 return 0;