Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Replaced memsizes.c with smaller memmap.c, taking advantage of __data16,
and creating a memory map that's easier to work with than the E820 map.
- Loading branch information
Michael Brown
committed
May 24, 2006
1 parent
5e80847
commit 77a6507
Showing
4 changed files
with
239 additions
and
235 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,214 @@ | ||
/* | ||
* Copyright (C) 2006 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 <stdint.h> | ||
#include <errno.h> | ||
#include <realmode.h> | ||
#include <bios.h> | ||
#include <memmap.h> | ||
|
||
/** | ||
* @file | ||
* | ||
* Memory mapping | ||
* | ||
*/ | ||
|
||
/** Magic value for INT 15,e820 calls */ | ||
#define SMAP ( 0x534d4150 ) | ||
|
||
/** 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_RESERVED 2 /**< Reserved and unavailable */ | ||
#define E820_TYPE_ACPI 3 /**< ACPI reclaim memory */ | ||
#define E820_TYPE_NVS 4 /**< ACPI NVS memory */ | ||
|
||
/** Buffer for INT 15,e820 calls */ | ||
static struct e820_entry __data16 ( e820buf ); | ||
#define e820buf __use_data16 ( e820buf ) | ||
|
||
/** | ||
* Get size of base memory from BIOS free base memory counter | ||
* | ||
* @ret basemem Base memory size, in kB | ||
*/ | ||
static unsigned int basememsize ( void ) { | ||
uint16_t basemem; | ||
|
||
get_real ( basemem, BDA_SEG, 0x0013 ); | ||
DBG ( "Base memory size %dkB\n", basemem ); | ||
return basemem; | ||
} | ||
|
||
/** | ||
* Get size of extended memory via INT 15,e801 | ||
* | ||
* @ret extmem Extended memory size, in kB, or 0 | ||
*/ | ||
static unsigned int extmemsize_e801 ( void ) { | ||
uint16_t extmem_1m_to_16m_k, extmem_16m_plus_64k; | ||
uint16_t confmem_1m_to_16m_k, confmem_16m_plus_64k; | ||
unsigned int flags; | ||
unsigned int extmem; | ||
|
||
REAL_EXEC ( rm_mem_e801, | ||
"int $0x15\n\t" | ||
"pushfw\n\t" | ||
"popw %w0\n\t", | ||
5, | ||
OUT_CONSTRAINTS ( "=r" ( flags ), | ||
"=a" ( extmem_1m_to_16m_k ), | ||
"=b" ( extmem_16m_plus_64k ), | ||
"=c" ( confmem_1m_to_16m_k ), | ||
"=d" ( confmem_16m_plus_64k ) ), | ||
IN_CONSTRAINTS ( "a" ( 0xe801 ) ), | ||
CLOBBER ( "cc" ) ); | ||
|
||
if ( flags & CF ) | ||
return 0; | ||
|
||
if ( ! ( extmem_1m_to_16m_k | extmem_16m_plus_64k ) ) { | ||
extmem_1m_to_16m_k = confmem_1m_to_16m_k; | ||
extmem_16m_plus_64k = confmem_16m_plus_64k; | ||
} | ||
|
||
extmem = ( extmem_1m_to_16m_k + ( extmem_16m_plus_64k * 64 ) ); | ||
DBG ( "Extended memory size %d+64*%d=%d kB\n", | ||
extmem_1m_to_16m_k, extmem_16m_plus_64k, extmem ); | ||
return extmem; | ||
} | ||
|
||
/** | ||
* Get size of extended memory via INT 15,88 | ||
* | ||
* @ret extmem Extended memory size, in kB | ||
*/ | ||
static unsigned int extmemsize_88 ( void ) { | ||
uint16_t extmem; | ||
|
||
REAL_EXEC ( rm_mem_88, | ||
"int $0x15\n\t" | ||
"jnc 1f\n\t" | ||
"xorw %%ax, %%ax\n\t" | ||
"\n1:\n\t", | ||
1, | ||
OUT_CONSTRAINTS ( "=a" ( extmem ) ), | ||
IN_CONSTRAINTS ( "a" ( 0x8800 ) ), | ||
CLOBBER ( "cc" ) ); | ||
|
||
DBG ( "Extended memory size %d kB\n", extmem ); | ||
return extmem; | ||
} | ||
|
||
/** | ||
* Get size of extended memory | ||
* | ||
* @ret extmem Extended memory size, in kB | ||
*/ | ||
static unsigned int extmemsize ( void ) { | ||
unsigned int extmem; | ||
|
||
/* Try INT 15,e801 first, then fall back to INT 15,88 */ | ||
extmem = extmemsize_e801(); | ||
if ( ! extmem ) | ||
extmem = extmemsize_88(); | ||
return extmem; | ||
} | ||
|
||
/** | ||
* Get e820 memory map | ||
* | ||
* @v memmap Memory map to fill in | ||
* @v entries Maximum number of entries in memory map | ||
* @ret rc Return status code | ||
*/ | ||
static int meme820 ( struct memory_region *memmap, unsigned int entries ) { | ||
unsigned int index = 0; | ||
uint32_t next = 0; | ||
uint32_t smap; | ||
unsigned int flags; | ||
unsigned int discard_c, discard_d, discard_D; | ||
|
||
do { | ||
REAL_EXEC ( rm_mem_e820, | ||
"int $0x15\n\t" | ||
"pushfw\n\t" | ||
"popw %w0\n\t", | ||
6, | ||
OUT_CONSTRAINTS ( "=r" ( flags ), | ||
"=a" ( smap ), | ||
"=b" ( next ), | ||
"=D" ( discard_D ), | ||
"=c" ( discard_c ), | ||
"=d" ( discard_d ) ), | ||
IN_CONSTRAINTS ( "a" ( 0xe820 ), | ||
"b" ( next ), | ||
"D" ( &__from_data16 ( e820buf )), | ||
"c" ( sizeof ( e820buf ) ), | ||
"d" ( SMAP ) ), | ||
CLOBBER ( "memory" ) ); | ||
if ( smap != SMAP ) | ||
return -ENOTSUP; | ||
if ( flags & CF ) | ||
break; | ||
DBG ( "E820 region [%llx,%llx) type %d\n", e820buf.start, | ||
( e820buf.start + e820buf.len ), ( int ) e820buf.type ); | ||
if ( e820buf.type != E820_TYPE_RAM ) | ||
continue; | ||
memmap[index].start = e820buf.start; | ||
memmap[index].end = e820buf.start + e820buf.len; | ||
index++; | ||
} while ( ( index < entries ) && ( next != 0 ) ); | ||
return 0; | ||
} | ||
|
||
/** | ||
* Get memory map | ||
* | ||
* @v memmap Memory map to fill in | ||
* @v entries Maximum number of entries in memory map (minimum 2) | ||
*/ | ||
void get_memmap ( struct memory_region *memmap, unsigned int entries ) { | ||
unsigned int basemem, extmem; | ||
int rc; | ||
|
||
/* Clear memory map */ | ||
memset ( memmap, 0, ( entries * sizeof ( *memmap ) ) ); | ||
|
||
/* Get base and extended memory sizes */ | ||
basemem = basememsize(); | ||
extmem = extmemsize(); | ||
|
||
/* Try INT 15,e820 first */ | ||
if ( ( rc = meme820 ( memmap, entries ) ) == 0 ) | ||
return; | ||
|
||
/* Fall back to constructing a map from basemem and extmem sizes */ | ||
memmap[0].end = ( basemem * 1024 ); | ||
memmap[1].start = 0x100000; | ||
memmap[1].end = 0x100000 + ( extmem * 1024 ); | ||
} |
Oops, something went wrong.