]> git.ipfire.org Git - thirdparty/ipxe.git/commitdiff
(Redoing check-in lost by SourceForge's failure.)
authorMichael Brown <mcb30@etherboot.org>
Sat, 13 May 2006 11:19:06 +0000 (11:19 +0000)
committerMichael Brown <mcb30@etherboot.org>
Sat, 13 May 2006 11:19:06 +0000 (11:19 +0000)
Add method for hooking real-mode interrupt vectors.

src/arch/i386/include/biosint.h [new file with mode: 0644]
src/arch/i386/interface/pcbios/biosint.c [new file with mode: 0644]

diff --git a/src/arch/i386/include/biosint.h b/src/arch/i386/include/biosint.h
new file mode 100644 (file)
index 0000000..55cb272
--- /dev/null
@@ -0,0 +1,17 @@
+#ifndef BIOSINT_H
+#define BIOSINT_H
+
+/**
+ * @file BIOS interrupts
+ *
+ */
+
+struct segoff;
+
+extern void hook_bios_interrupt ( unsigned int interrupt, unsigned int handler,
+                                 struct segoff *chain_vector );
+extern int unhook_bios_interrupt ( unsigned int interrupt,
+                                  unsigned int handler,
+                                  struct segoff *chain_vector );
+
+#endif /* BIOSINT_H */
diff --git a/src/arch/i386/interface/pcbios/biosint.c b/src/arch/i386/interface/pcbios/biosint.c
new file mode 100644 (file)
index 0000000..345961a
--- /dev/null
@@ -0,0 +1,57 @@
+#include <errno.h>
+#include <realmode.h>
+#include <biosint.h>
+
+/**
+ * @file BIOS interrupts
+ *
+ */
+
+/**
+ * Hook INT vector
+ *
+ * @v interrupt                INT number
+ * @v handler          Offset within .text16 to interrupt handler
+ * @v chain_vector     Vector for chaining to previous handler
+ *
+ * Hooks in an i386 INT handler.  The handler itself must reside
+ * within the .text16 segment.  @c chain_vector will be filled in with
+ * the address of the previously-installed handler for this interrupt;
+ * the handler should probably exit by ljmping via this vector.
+ */
+void hook_bios_interrupt ( unsigned int interrupt, unsigned int handler,
+                          struct segoff *chain_vector ) {
+       struct segoff vector = {
+               .segment = rm_cs,
+               .offset = handler,
+       };
+
+       copy_from_real ( chain_vector, 0, ( interrupt * 4 ),
+                        sizeof ( *chain_vector ) );
+       copy_to_real ( 0, ( interrupt * 4 ), &vector, sizeof ( vector ) );
+}
+
+/**
+ * Unhook INT vector
+ *
+ * @v interrupt                INT number
+ * @v handler          Offset within .text16 to interrupt handler
+ * @v chain_vector     Vector containing address of previous handler
+ *
+ * Unhooks an i386 interrupt handler hooked by hook_i386_vector().
+ * Note that this operation may fail, if some external code has hooked
+ * the vector since we hooked in our handler.  If it fails, it means
+ * that it is not possible to unhook our handler, and we must leave it
+ * (and its chaining vector) resident in memory.
+ */
+int unhook_bios_interrupt ( unsigned int interrupt, unsigned int handler,
+                           struct segoff *chain_vector ) {
+       struct segoff vector;
+
+       copy_from_real ( &vector, 0, ( interrupt * 4 ), sizeof ( vector ) );
+       if ( ( vector.segment != rm_cs ) || ( vector.offset != handler ) )
+               return -EBUSY;
+       copy_to_real ( 0, ( interrupt * 4 ), chain_vector,
+                      sizeof ( *chain_vector ) );
+       return 0;
+}