iPXE
Data Structures | Defines | Functions | Variables
hidemem.c File Reference
#include <assert.h>
#include <realmode.h>
#include <biosint.h>
#include <basemem.h>
#include <fakee820.h>
#include <ipxe/init.h>
#include <ipxe/io.h>
#include <ipxe/hidemem.h>

Go to the source code of this file.

Data Structures

struct  hidden_region
 A hidden region of iPXE. More...

Defines

#define FAKE_E820   0
 Set to true if you want to test a fake E820 map.
#define ALIGN_HIDDEN   4096 /* 4kB page alignment should be enough */
 Alignment for hidden memory regions.
#define hidemem_base   __use_data16 ( hidemem_base )
#define hidemem_umalloc   __use_data16 ( hidemem_umalloc )
#define hidemem_textdata   __use_data16 ( hidemem_textdata )
#define int15_vector   __use_text16 ( int15_vector )
#define _text16_memsz   ( ( size_t ) _text16_memsz )
#define _data16_memsz   ( ( size_t ) _data16_memsz )

Functions

 FILE_LICENCE (GPL2_OR_LATER_OR_UBDL)
struct hidden_region __data16 (hidemem_base)
 Hidden base memory.
struct hidden_region __data16 (hidemem_umalloc)
 Hidden umalloc memory.
struct hidden_region __data16 (hidemem_textdata)
 Hidden text memory.
void int15 ()
 Assembly routine in e820mangler.S.
struct segoff __text16 (int15_vector)
 Vector for storing original INT 15 handler.
static void hide_region (struct hidden_region *region, physaddr_t start, physaddr_t end)
 Hide region of memory from system memory map.
void hide_basemem (void)
 Hide used base memory.
void hide_umalloc (physaddr_t start, physaddr_t end)
 Hide umalloc() region.
void hide_textdata (void)
 Hide .text and .data.
static void hide_etherboot (void)
 Hide Etherboot.
static void unhide_etherboot (int flags __unused)
 Unhide Etherboot.
struct startup_fn
hide_etherboot_startup_fn 
__startup_fn (STARTUP_EARLY)
 Hide Etherboot startup function.

Variables

struct hidden_region __attribute__
char _textdata []
char _etextdata []
char _text16_memsz []
char _data16_memsz []

Define Documentation

#define FAKE_E820   0

Set to true if you want to test a fake E820 map.

Definition at line 35 of file hidemem.c.

Referenced by hide_etherboot(), and unhide_etherboot().

#define ALIGN_HIDDEN   4096 /* 4kB page alignment should be enough */

Alignment for hidden memory regions.

Definition at line 38 of file hidemem.c.

Referenced by hide_region().

Definition at line 58 of file hidemem.c.

Referenced by hide_basemem().

Definition at line 62 of file hidemem.c.

Referenced by hide_umalloc().

Definition at line 66 of file hidemem.c.

Referenced by hide_textdata().

Definition at line 73 of file hidemem.c.

Referenced by hide_etherboot(), and unhide_etherboot().

#define _text16_memsz   ( ( size_t ) _text16_memsz )

Definition at line 79 of file hidemem.c.

Referenced by hide_etherboot(), and pxe_start_nbp().

#define _data16_memsz   ( ( size_t ) _data16_memsz )

Definition at line 81 of file hidemem.c.

Referenced by hide_etherboot(), and pxe_start_nbp().


Function Documentation

FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL  )
struct hidden_region __data16 ( hidemem_base  ) [read]

Hidden base memory.

struct hidden_region __data16 ( hidemem_umalloc  ) [read]

Hidden umalloc memory.

Hidden text memory.

void int15 ( )

Assembly routine in e820mangler.S.

Referenced by hide_etherboot(), and unhide_etherboot().

struct segoff __text16 ( int15_vector  ) [read]

Vector for storing original INT 15 handler.

static void hide_region ( struct hidden_region region,
physaddr_t  start,
physaddr_t  end 
) [static]

Hide region of memory from system memory map.

Parameters:
regionHidden memory region
startStart of region
endEnd of region

Definition at line 90 of file hidemem.c.

References ALIGN_HIDDEN, DBG, hidden_region::end, and hidden_region::start.

Referenced by hide_textdata(), and hide_umalloc().

                                                             {

        /* Some operating systems get a nasty shock if a region of the
         * E820 map seems to start on a non-page boundary.  Make life
         * safer by rounding out our edited region.
         */
        region->start = ( start & ~( ALIGN_HIDDEN - 1 ) );
        region->end = ( ( end + ALIGN_HIDDEN - 1 ) & ~( ALIGN_HIDDEN - 1 ) );

        DBG ( "Hiding region [%llx,%llx)\n", region->start, region->end );
}
void hide_basemem ( void  )

Hide used base memory.

Definition at line 107 of file hidemem.c.

References get_fbms(), and hidemem_base.

Referenced by hide_etherboot(), and set_fbms().

                           {
        /* Hide from the top of free base memory to 640kB.  Don't use
         * hide_region(), because we don't want this rounded to the
         * nearest page boundary.
         */
        hidemem_base.start = ( get_fbms() * 1024 );
}
void hide_umalloc ( physaddr_t  start,
physaddr_t  end 
)

Hide umalloc() region.

Definition at line 119 of file hidemem.c.

References _textdata, assert, hide_region(), hidemem_umalloc, and virt_to_phys().

Referenced by hide_etherboot(), and memtop_urealloc().

                                                       {
        assert ( end <= virt_to_phys ( _textdata ) );
        hide_region ( &hidemem_umalloc, start, end );
}
void hide_textdata ( void  )

Hide .text and .data.

Definition at line 128 of file hidemem.c.

References _etextdata, _textdata, hide_region(), hidemem_textdata, and virt_to_phys().

Referenced by hide_etherboot().

                            {
        hide_region ( &hidemem_textdata, virt_to_phys ( _textdata ),
                      virt_to_phys ( _etextdata ) );
}
static void hide_etherboot ( void  ) [static]

Hide Etherboot.

Installs an INT 15 handler to edit Etherboot out of the memory map returned by the BIOS.

Definition at line 139 of file hidemem.c.

References _data16_memsz, _text16_memsz, _textdata, DBG, FAKE_E820, fake_e820(), get_fbms(), get_memmap(), hide_basemem(), hide_textdata(), hide_umalloc(), hook_bios_interrupt(), int15(), int15_vector, rm_cs, rm_ds, and virt_to_phys().

                                    {
        struct memory_map memmap;
        unsigned int rm_ds_top;
        unsigned int rm_cs_top;
        unsigned int fbms;

        /* Dump memory map before mangling */
        DBG ( "Hiding iPXE from system memory map\n" );
        get_memmap ( &memmap );

        /* Hook in fake E820 map, if we're testing one */
        if ( FAKE_E820 ) {
                DBG ( "Hooking in fake E820 map\n" );
                fake_e820();
                get_memmap ( &memmap );
        }

        /* Initialise the hidden regions */
        hide_basemem();
        hide_umalloc ( virt_to_phys ( _textdata ), virt_to_phys ( _textdata ) );
        hide_textdata();

        /* Some really moronic BIOSes bring up the PXE stack via the
         * UNDI loader entry point and then don't bother to unload it
         * before overwriting the code and data segments.  If this
         * happens, we really don't want to leave INT 15 hooked,
         * because that will cause any loaded OS to die horribly as
         * soon as it attempts to fetch the system memory map.
         *
         * We use a heuristic to guess whether or not we are being
         * loaded sensibly.
         */
        rm_cs_top = ( ( ( rm_cs << 4 ) + _text16_memsz + 1024 - 1 ) >> 10 );
        rm_ds_top = ( ( ( rm_ds << 4 ) + _data16_memsz + 1024 - 1 ) >> 10 );
        fbms = get_fbms();
        if ( ( rm_cs_top < fbms ) && ( rm_ds_top < fbms ) ) {
                DBG ( "Detected potentially unsafe UNDI load at CS=%04x "
                      "DS=%04x FBMS=%dkB\n", rm_cs, rm_ds, fbms );
                DBG ( "Disabling INT 15 memory hiding\n" );
                return;
        }

        /* Hook INT 15 */
        hook_bios_interrupt ( 0x15, ( intptr_t ) int15, &int15_vector );

        /* Dump memory map after mangling */
        DBG ( "Hidden iPXE from system memory map\n" );
        get_memmap ( &memmap );
}
static void unhide_etherboot ( int flags  __unused) [static]

Unhide Etherboot.

Uninstalls the INT 15 handler installed by hide_etherboot(), if possible.

Definition at line 195 of file hidemem.c.

References DBG, FAKE_E820, get_memmap(), hooked_bios_interrupts, int15(), int15_vector, rc, strerror(), unfake_e820(), and unhook_bios_interrupt().

                                                    {
        struct memory_map memmap;
        int rc;

        /* If we have more than one hooked interrupt at this point, it
         * means that some other vector is still hooked, in which case
         * we can't safely unhook INT 15 because we need to keep our
         * memory protected.  (We expect there to be at least one
         * hooked interrupt, because INT 15 itself is still hooked).
         */
        if ( hooked_bios_interrupts > 1 ) {
                DBG ( "Cannot unhide: %d interrupt vectors still hooked\n",
                      hooked_bios_interrupts );
                return;
        }

        /* Try to unhook INT 15 */
        if ( ( rc = unhook_bios_interrupt ( 0x15, ( intptr_t ) int15,
                                            &int15_vector ) ) != 0 ) {
                DBG ( "Cannot unhook INT15: %s\n", strerror ( rc ) );
                /* Leave it hooked; there's nothing else we can do,
                 * and it should be intrinsically safe (though
                 * wasteful of RAM).
                 */
        }

        /* Unhook fake E820 map, if used */
        if ( FAKE_E820 )
                unfake_e820();

        /* Dump memory map after unhiding */
        DBG ( "Unhidden iPXE from system memory map\n" );
        get_memmap ( &memmap );
}
struct startup_fn hide_etherboot_startup_fn __startup_fn ( STARTUP_EARLY  ) [read]

Hide Etherboot startup function.


Variable Documentation

char _textdata[]
char _etextdata[]
char _text16_memsz[]
char _data16_memsz[]