You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

hidemem.c 2.7KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394
  1. /* Utility functions to hide Etherboot by manipulating the E820 memory
  2. * map. These could go in memsizes.c, but are placed here because not
  3. * all images will need them.
  4. */
  5. #include "etherboot.h"
  6. #include "hidemem.h"
  7. #ifdef CODE16
  8. static int mangling = 0;
  9. static void *mangler = NULL;
  10. #define INSTALLED(x) ( (typeof(&x)) ( (void*)(&x) - (void*)e820mangler \
  11. + mangler ) )
  12. #define intercept_int15 INSTALLED(_intercept_int15)
  13. #define intercepted_int15 INSTALLED(_intercepted_int15)
  14. #define hide_memory INSTALLED(_hide_memory)
  15. #define INT15_VECTOR ( (segoff_t*) ( phys_to_virt( 4 * 0x15 ) ) )
  16. int install_e820mangler ( void *new_mangler ) {
  17. if ( mangling ) return 0;
  18. memcpy ( new_mangler, &e820mangler, e820mangler_size );
  19. mangler = new_mangler;
  20. return 1;
  21. }
  22. /* Intercept INT15 calls and pass them through the mangler. The
  23. * mangler must have been copied to base memory before making this
  24. * call, and "mangler" must point to the base memory copy, which must
  25. * be 16-byte aligned.
  26. */
  27. int hide_etherboot ( void ) {
  28. if ( mangling ) return 1;
  29. if ( !mangler ) return 0;
  30. /* Hook INT15 handler */
  31. *intercepted_int15 = *INT15_VECTOR;
  32. (*hide_memory)[0].start = virt_to_phys(_text);
  33. (*hide_memory)[0].length = _end - _text;
  34. /* IMPORTANT, possibly even FIXME:
  35. *
  36. * Etherboot has a tendency to claim a very large area of
  37. * memory as possible heap; enough to make it impossible to
  38. * load an OS if we hide all of it. We hide only the portion
  39. * that's currently in use. This means that we MUST NOT
  40. * perform further allocations from the heap while the mangler
  41. * is active.
  42. */
  43. (*hide_memory)[1].start = heap_ptr;
  44. (*hide_memory)[1].length = heap_bot - heap_ptr;
  45. INT15_VECTOR->segment = SEGMENT(mangler);
  46. INT15_VECTOR->offset = 0;
  47. mangling = 1;
  48. return 1;
  49. }
  50. int unhide_etherboot ( void ) {
  51. if ( !mangling ) return 1;
  52. /* Restore original INT15 handler
  53. */
  54. if ( VIRTUAL(INT15_VECTOR->segment,INT15_VECTOR->offset) != mangler ) {
  55. /* Oh dear... */
  56. #ifdef WORK_AROUND_BPBATCH_BUG
  57. /* BpBatch intercepts INT15, so can't unhook it, and
  58. * then proceeds to ignore our PXENV_KEEP_UNDI return
  59. * status, which means that it ends up zeroing out the
  60. * INT15 handler routine.
  61. *
  62. * This rather ugly hack involves poking into
  63. * BpBatch's code and changing it's stored value for
  64. * the "next handler" in the INT15 chain.
  65. */
  66. segoff_t *bp_chain = VIRTUAL ( 0x0060, 0x8254 );
  67. if ( ( bp_chain->segment == SEGMENT(mangler) ) &&
  68. ( bp_chain->offset == 0 ) ) {
  69. printf ( "\nBPBATCH bug workaround enabled\n" );
  70. *bp_chain = *intercepted_int15;
  71. }
  72. #endif /* WORK_AROUND_BPBATCH_BUG */
  73. return 0;
  74. }
  75. *INT15_VECTOR = *intercepted_int15;
  76. mangling = 0;
  77. return 1;
  78. }
  79. #endif /* CODE16 */