iPXE
biosint.c
Go to the documentation of this file.
1 #include <string.h>
2 #include <errno.h>
3 #include <realmode.h>
4 #include <biosint.h>
5 
6 /**
7  * @file BIOS interrupts
8  *
9  */
10 
11 FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL );
12 
13 /**
14  * Hook INT vector
15  *
16  * @v interrupt INT number
17  * @v handler Offset within .text16 to interrupt handler
18  * @v chain_vector Vector for chaining to previous handler
19  *
20  * Hooks in an i386 INT handler. The handler itself must reside
21  * within the .text16 segment. @c chain_vector will be filled in with
22  * the address of the previously-installed handler for this interrupt;
23  * the handler should probably exit by ljmping via this vector.
24  */
25 void hook_bios_interrupt ( unsigned int interrupt, unsigned int handler,
26  struct segoff *chain_vector ) {
27  struct segoff vector = {
28  .segment = rm_cs,
29  .offset = handler,
30  };
31 
32  DBG ( "Hooking INT %#02x to %04x:%04x\n",
33  interrupt, rm_cs, handler );
34 
35  if ( ( chain_vector->segment != 0 ) ||
36  ( chain_vector->offset != 0 ) ) {
37  /* Already hooked; do nothing */
38  DBG ( "...already hooked\n" );
39  return;
40  }
41 
42  copy_from_real ( chain_vector, 0, ( interrupt * 4 ),
43  sizeof ( *chain_vector ) );
44  DBG ( "...chaining to %04x:%04x\n",
45  chain_vector->segment, chain_vector->offset );
46  if ( DBG_LOG ) {
47  char code[64];
48  copy_from_real ( code, chain_vector->segment,
49  chain_vector->offset, sizeof ( code ) );
50  DBG_HDA ( *chain_vector, code, sizeof ( code ) );
51  }
52 
53  copy_to_real ( 0, ( interrupt * 4 ), &vector, sizeof ( vector ) );
55 }
56 
57 /**
58  * Unhook INT vector
59  *
60  * @v interrupt INT number
61  * @v handler Offset within .text16 to interrupt handler
62  * @v chain_vector Vector containing address of previous handler
63  *
64  * Unhooks an i386 interrupt handler hooked by hook_i386_vector().
65  * Note that this operation may fail, if some external code has hooked
66  * the vector since we hooked in our handler. If it fails, it means
67  * that it is not possible to unhook our handler, and we must leave it
68  * (and its chaining vector) resident in memory.
69  */
70 int unhook_bios_interrupt ( unsigned int interrupt, unsigned int handler,
71  struct segoff *chain_vector ) {
72  struct segoff vector;
73 
74  DBG ( "Unhooking INT %#02x from %04x:%04x\n",
75  interrupt, rm_cs, handler );
76 
77  copy_from_real ( &vector, 0, ( interrupt * 4 ), sizeof ( vector ) );
78  if ( ( vector.segment != rm_cs ) || ( vector.offset != handler ) ) {
79  DBG ( "...cannot unhook; vector points to %04x:%04x\n",
80  vector.segment, vector.offset );
81  return -EBUSY;
82  }
83 
84  DBG ( "...restoring to %04x:%04x\n",
85  chain_vector->segment, chain_vector->offset );
86  copy_to_real ( 0, ( interrupt * 4 ), chain_vector,
87  sizeof ( *chain_vector ) );
88 
89  chain_vector->segment = 0;
90  chain_vector->offset = 0;
92  return 0;
93 }
94 
95 /**
96  * Dump changes to interrupt vector table (for debugging)
97  *
98  */
99 void check_bios_interrupts ( void ) {
100  static struct segoff vectors[256];
101  static uint8_t initialised;
102  struct segoff vector;
103  unsigned int i;
104 
105  /* Print any changed interrupt vectors */
106  for ( i = 0; i < ( sizeof ( vectors ) / sizeof ( vectors[0] ) ); i++ ) {
107  copy_from_real ( &vector, 0, ( i * sizeof ( vector ) ),
108  sizeof ( vector ) );
109  if ( memcmp ( &vector, &vectors[i], sizeof ( vector ) ) == 0 )
110  continue;
111  if ( initialised ) {
112  dbg_printf ( "INT %02x changed %04x:%04x => "
113  "%04x:%04x\n", i, vectors[i].segment,
114  vectors[i].offset, vector.segment,
115  vector.offset );
116  }
117  memcpy ( &vectors[i], &vector, sizeof ( vectors[i] ) );
118  }
119  initialised = 1;
120 }
uint16_t segment
Definition: registers.h:193
uint16_t segment
Code segment.
Definition: librm.h:138
#define EBUSY
Device or resource busy.
Definition: errno.h:338
#define DBG_HDA(...)
Definition: compiler.h:499
void check_bios_interrupts(void)
Dump changes to interrupt vector table (for debugging)
Definition: biosint.c:99
Error codes.
uint32_t vector
MSI-X vector.
Definition: ena.h:20
static unsigned int code
Response code.
Definition: hyperv.h:26
void hook_bios_interrupt(unsigned int interrupt, unsigned int handler, struct segoff *chain_vector)
Hook INT vector.
Definition: biosint.c:25
int unhook_bios_interrupt(unsigned int interrupt, unsigned int handler, struct segoff *chain_vector)
Unhook INT vector.
Definition: biosint.c:70
void * memcpy(void *dest, const void *src, size_t len) __nonnull
uint16_t offset
Definition: registers.h:192
#define hooked_bios_interrupts
Definition: biosint.h:25
#define copy_to_real
Definition: libkir.h:78
unsigned char uint8_t
Definition: stdint.h:10
#define copy_from_real
Definition: libkir.h:79
#define rm_cs
Definition: libkir.h:38
uint16_t offset
Offset to command line.
Definition: bzimage.h:8
#define DBG(...)
Print a debugging message.
Definition: compiler.h:498
#define DBG_LOG
Definition: compiler.h:317
int memcmp(const void *first, const void *second, size_t len)
Compare memory regions.
Definition: string.c:114
void interrupt(int intr, struct interrupt_frame32 *frame32, struct interrupt_frame64 *frame64)
Interrupt handler.
Definition: librm_mgmt.c:251
String functions.
void dbg_printf(const char *fmt,...)
Print debug message.
Definition: debug.c:38
FILE_LICENCE(GPL2_OR_LATER_OR_UBDL)