Você não pode selecionar mais de 25 tópicos Os tópicos devem começar com uma letra ou um número, podem incluir traços ('-') e podem ter até 35 caracteres.

biosint.c 3.0KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101
  1. #include <errno.h>
  2. #include <realmode.h>
  3. #include <biosint.h>
  4. /**
  5. * @file BIOS interrupts
  6. *
  7. */
  8. /**
  9. * Hooked interrupt count
  10. *
  11. * At exit, after unhooking all possible interrupts, this counter
  12. * should be examined. If it is non-zero, it means that we failed to
  13. * unhook at least one interrupt vector, and so must not free up the
  14. * memory we are using. (Note that this also implies that we should
  15. * re-hook INT 15 in order to hide ourselves from the memory map).
  16. */
  17. int hooked_bios_interrupts = 0;
  18. /**
  19. * Hook INT vector
  20. *
  21. * @v interrupt INT number
  22. * @v handler Offset within .text16 to interrupt handler
  23. * @v chain_vector Vector for chaining to previous handler
  24. *
  25. * Hooks in an i386 INT handler. The handler itself must reside
  26. * within the .text16 segment. @c chain_vector will be filled in with
  27. * the address of the previously-installed handler for this interrupt;
  28. * the handler should probably exit by ljmping via this vector.
  29. */
  30. void hook_bios_interrupt ( unsigned int interrupt, unsigned int handler,
  31. struct segoff *chain_vector ) {
  32. struct segoff vector = {
  33. .segment = rm_cs,
  34. .offset = handler,
  35. };
  36. DBG ( "Hooking INT %#02x to %04x:%04x\n",
  37. interrupt, rm_cs, handler );
  38. if ( ( chain_vector->segment != 0 ) ||
  39. ( chain_vector->offset != 0 ) ) {
  40. /* Already hooked; do nothing */
  41. DBG ( "...already hooked\n" );
  42. return;
  43. }
  44. copy_from_real ( chain_vector, 0, ( interrupt * 4 ),
  45. sizeof ( *chain_vector ) );
  46. DBG ( "...chaining to %04x:%04x\n",
  47. chain_vector->segment, chain_vector->offset );
  48. if ( DBG_LOG ) {
  49. char code[64];
  50. copy_from_real ( code, chain_vector->segment,
  51. chain_vector->offset, sizeof ( code ) );
  52. DBG_HDA ( *chain_vector, code, sizeof ( code ) );
  53. }
  54. copy_to_real ( 0, ( interrupt * 4 ), &vector, sizeof ( vector ) );
  55. hooked_bios_interrupts++;
  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. DBG ( "Unhooking INT %#02x from %04x:%04x\n",
  74. interrupt, rm_cs, handler );
  75. copy_from_real ( &vector, 0, ( interrupt * 4 ), sizeof ( vector ) );
  76. if ( ( vector.segment != rm_cs ) || ( vector.offset != handler ) ) {
  77. DBG ( "...cannot unhook; vector points to %04x:%04x\n",
  78. vector.segment, vector.offset );
  79. return -EBUSY;
  80. }
  81. DBG ( "...restoring to %04x:%04x\n",
  82. chain_vector->segment, chain_vector->offset );
  83. copy_to_real ( 0, ( interrupt * 4 ), chain_vector,
  84. sizeof ( *chain_vector ) );
  85. chain_vector->segment = 0;
  86. chain_vector->offset = 0;
  87. hooked_bios_interrupts--;
  88. return 0;
  89. }