12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394 |
- /* Utility functions to hide Etherboot by manipulating the E820 memory
- * map. These could go in memsizes.c, but are placed here because not
- * all images will need them.
- */
-
- #include "etherboot.h"
- #include "hidemem.h"
-
- #ifdef CODE16
-
- static int mangling = 0;
- static void *mangler = NULL;
-
- #define INSTALLED(x) ( (typeof(&x)) ( (void*)(&x) - (void*)e820mangler \
- + mangler ) )
- #define intercept_int15 INSTALLED(_intercept_int15)
- #define intercepted_int15 INSTALLED(_intercepted_int15)
- #define hide_memory INSTALLED(_hide_memory)
- #define INT15_VECTOR ( (segoff_t*) ( phys_to_virt( 4 * 0x15 ) ) )
-
- int install_e820mangler ( void *new_mangler ) {
- if ( mangling ) return 0;
- memcpy ( new_mangler, &e820mangler, e820mangler_size );
- mangler = new_mangler;
- return 1;
- }
-
- /* Intercept INT15 calls and pass them through the mangler. The
- * mangler must have been copied to base memory before making this
- * call, and "mangler" must point to the base memory copy, which must
- * be 16-byte aligned.
- */
- int hide_etherboot ( void ) {
- if ( mangling ) return 1;
- if ( !mangler ) return 0;
-
- /* Hook INT15 handler */
- *intercepted_int15 = *INT15_VECTOR;
- (*hide_memory)[0].start = virt_to_phys(_text);
- (*hide_memory)[0].length = _end - _text;
- /* IMPORTANT, possibly even FIXME:
- *
- * Etherboot has a tendency to claim a very large area of
- * memory as possible heap; enough to make it impossible to
- * load an OS if we hide all of it. We hide only the portion
- * that's currently in use. This means that we MUST NOT
- * perform further allocations from the heap while the mangler
- * is active.
- */
- (*hide_memory)[1].start = heap_ptr;
- (*hide_memory)[1].length = heap_bot - heap_ptr;
- INT15_VECTOR->segment = SEGMENT(mangler);
- INT15_VECTOR->offset = 0;
-
- mangling = 1;
- return 1;
- }
-
- int unhide_etherboot ( void ) {
- if ( !mangling ) return 1;
-
- /* Restore original INT15 handler
- */
- if ( VIRTUAL(INT15_VECTOR->segment,INT15_VECTOR->offset) != mangler ) {
- /* Oh dear... */
-
- #ifdef WORK_AROUND_BPBATCH_BUG
- /* BpBatch intercepts INT15, so can't unhook it, and
- * then proceeds to ignore our PXENV_KEEP_UNDI return
- * status, which means that it ends up zeroing out the
- * INT15 handler routine.
- *
- * This rather ugly hack involves poking into
- * BpBatch's code and changing it's stored value for
- * the "next handler" in the INT15 chain.
- */
- segoff_t *bp_chain = VIRTUAL ( 0x0060, 0x8254 );
-
- if ( ( bp_chain->segment == SEGMENT(mangler) ) &&
- ( bp_chain->offset == 0 ) ) {
- printf ( "\nBPBATCH bug workaround enabled\n" );
- *bp_chain = *intercepted_int15;
- }
- #endif /* WORK_AROUND_BPBATCH_BUG */
-
- return 0;
- }
- *INT15_VECTOR = *intercepted_int15;
-
- mangling = 0;
- return 1;
- }
-
- #endif /* CODE16 */
|