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
11FILE_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 */
25void 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 */
70int 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 */
99void 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}
static unsigned int code
Response code.
Definition hyperv.h:26
unsigned char uint8_t
Definition stdint.h:10
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 check_bios_interrupts(void)
Dump changes to interrupt vector table (for debugging)
Definition biosint.c:99
#define hooked_bios_interrupts
Definition biosint.h:25
uint16_t offset
Offset to command line.
Definition bzimage.h:3
uint32_t vector
MSI-X vector.
Definition ena.h:9
Error codes.
#define DBG_HDA(...)
Definition compiler.h:499
void dbg_printf(const char *fmt,...)
Print debug message.
Definition debug.c:39
#define DBG_LOG
Definition compiler.h:317
#define DBG(...)
Print a debugging message.
Definition compiler.h:498
#define FILE_LICENCE(_licence)
Declare a particular licence as applying to a file.
Definition compiler.h:896
#define EBUSY
Device or resource busy.
Definition errno.h:339
String functions.
void * memcpy(void *dest, const void *src, size_t len) __nonnull
#define rm_cs
Definition libkir.h:38
#define copy_to_real
Definition libkir.h:78
#define copy_from_real
Definition libkir.h:79
uint16_t segment
Code segment.
Definition librm.h:3
void interrupt(int intr, struct interrupt_frame32 *frame32, struct interrupt_frame64 *frame64)
Interrupt handler.
Definition librm_mgmt.c:251
int memcmp(const void *first, const void *second, size_t len)
Compare memory regions.
Definition string.c:115
uint16_t segment
Definition registers.h:193
uint16_t offset
Definition registers.h:192