Skip to content

Commit

Permalink
Browse files Browse the repository at this point in the history
[pcbios] Add facility for testing arbitrary E820 memory maps
We seem to be having issues with various E820 memory maps.  These
problems are often difficult to reproduce, requiring access to the
specific system exhibiting the problem.

Add a facility for hooking in a fake E820 map generator, using an
arbitrary map defined in a C array, solely in order to be able to test
the map-mangling code against arbitrary E820 maps.
  • Loading branch information
Michael Brown committed Sep 25, 2008
1 parent 9c71949 commit c24bc34
Show file tree
Hide file tree
Showing 3 changed files with 112 additions and 0 deletions.
90 changes: 90 additions & 0 deletions src/arch/i386/firmware/pcbios/fakee820.c
@@ -0,0 +1,90 @@
/* Copyright (C) 2008 Michael Brown <mbrown@fensystems.co.uk>.
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License as
* published by the Free Software Foundation; either version 2 of the
* License, or any later version.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/

#include <realmode.h>
#include <biosint.h>

/** Assembly routine in inline asm */
extern void int15_fakee820();

/** Original INT 15 handler */
static struct segoff __text16 ( real_int15_vector );
#define real_int15_vector __use_text16 ( real_int15_vector )

/** An INT 15,e820 memory map entry */
struct e820_entry {
/** Start of region */
uint64_t start;
/** Length of region */
uint64_t len;
/** Type of region */
uint32_t type;
} __attribute__ (( packed ));

#define E820_TYPE_RAM 1 /**< Normal memory */
#define E820_TYPE_RSVD 2 /**< Reserved and unavailable */
#define E820_TYPE_ACPI 3 /**< ACPI reclaim memory */
#define E820_TYPE_NVS 4 /**< ACPI NVS memory */

/** Fake e820 map */
static struct e820_entry __text16_array ( e820map, [] ) __used = {
{ 0x00000000ULL, ( 0x000a0000ULL - 0x00000000ULL ), E820_TYPE_RAM },
{ 0x00100000ULL, ( 0xcfb50000ULL - 0x00100000ULL ), E820_TYPE_RAM },
{ 0xcfb50000ULL, ( 0xcfb64000ULL - 0xcfb50000ULL ), E820_TYPE_RSVD },
{ 0xcfb64000ULL, ( 0xcfb66000ULL - 0xcfb64000ULL ), E820_TYPE_RSVD },
{ 0xcfb66000ULL, ( 0xcfb85c00ULL - 0xcfb66000ULL ), E820_TYPE_ACPI },
{ 0xcfb85c00ULL, ( 0xd0000000ULL - 0xcfb85c00ULL ), E820_TYPE_RSVD },
{ 0xe0000000ULL, ( 0xf0000000ULL - 0xe0000000ULL ), E820_TYPE_RSVD },
{ 0xfe000000ULL, (0x100000000ULL - 0xfe000000ULL ), E820_TYPE_RSVD },
{0x100000000ULL, (0x230000000ULL -0x100000000ULL ), E820_TYPE_RAM },
};
#define e820map __use_text16 ( e820map )

void fake_e820 ( void ) {
__asm__ __volatile__ (
TEXT16_CODE ( "\nint15_fakee820:\n\t"
"pushfw\n\t"
"cmpl $0xe820, %%eax\n\t"
"jne 99f\n\t"
"cmpl $0x534d4150, %%edx\n\t"
"jne 99f\n\t"
"pushaw\n\t"
"leaw e820map(%%bx), %%si\n\t"
"cs rep movsb\n\t"
"popaw\n\t"
"movl %%edx, %%eax\n\t"
"addl $20, %%ebx\n\t"
"cmpl %0, %%ebx\n\t"
"jne 1f\n\t"
"xorl %%ebx,%%ebx\n\t"
"\n1:\n\t"
"popfw\n\t"
"clc\n\t"
"lret $2\n\t"
"\n99:\n\t"
"popfw\n\t"
"ljmp *%%cs:real_int15_vector\n\t" )
: : "i" ( sizeof ( e820map ) ) );

hook_bios_interrupt ( 0x15, ( unsigned int ) int15_fakee820,
&real_int15_vector );
}

void unfake_e820 ( void ) {
unhook_bios_interrupt ( 0x15, ( unsigned int ) int15_fakee820,
&real_int15_vector );
}
15 changes: 15 additions & 0 deletions src/arch/i386/firmware/pcbios/hidemem.c
Expand Up @@ -19,10 +19,14 @@
#include <realmode.h>
#include <biosint.h>
#include <basemem.h>
#include <fakee820.h>
#include <gpxe/init.h>
#include <gpxe/memmap.h>
#include <gpxe/hidemem.h>

/** Set to true if you want to test a fake E820 map */
#define FAKE_E820 0

/** Alignment for hidden memory regions */
#define ALIGN_HIDDEN 4096 /* 4kB page alignment should be enough */

Expand Down Expand Up @@ -135,6 +139,13 @@ static void hide_etherboot ( void ) {
DBG ( "Hiding gPXE 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 ( _text ), virt_to_phys ( _text ) );
Expand Down Expand Up @@ -194,6 +205,10 @@ static void unhide_etherboot ( int flags __unused ) {
*/
unhook_bios_interrupt ( 0x15, ( unsigned int ) int15,
&int15_vector );

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

/** Hide Etherboot startup function */
Expand Down
7 changes: 7 additions & 0 deletions src/arch/i386/include/fakee820.h
@@ -0,0 +1,7 @@
#ifndef _FAKEE820_H
#define _FAKEE820_H

extern void fake_e820 ( void );
extern void unfake_e820 ( void );

#endif /* _FAKEE820_H */

0 comments on commit c24bc34

Please sign in to comment.