mirror of
https://github.com/xcat2/xNBA.git
synced 2024-12-16 00:01:34 +00:00
95 lines
2.7 KiB
C
95 lines
2.7 KiB
C
|
/* 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 */
|