david/ipxe
Archived
1
0

[pcbios] Print INT 15,E820 extended attributes, if present

The ACPI specification defines an additional 4-byte field at offset 20
for an E820 memory map entry.  This field is presumably optional,
since generally E820 gets given only a 20-byte buffer to fill.
However, the bits of this optional field are defined as:

  bit 0 : region is enabled
  bit 1 : region is non-volatile memory rather than RAM

so it seems as though callers that pass in only a 20-byte buffer may
be missing out on some rather important information.
This commit is contained in:
Michael Brown 2008-09-29 03:55:13 +01:00
parent 0015601f0b
commit 040f7cdf3a

View File

@ -41,6 +41,8 @@ struct e820_entry {
uint64_t len;
/** Type of region */
uint32_t type;
/** Extended attributes (optional) */
uint32_t attrs;
} __attribute__ (( packed ));
#define E820_TYPE_RAM 1 /**< Normal memory */
@ -48,6 +50,12 @@ struct e820_entry {
#define E820_TYPE_ACPI 3 /**< ACPI reclaim memory */
#define E820_TYPE_NVS 4 /**< ACPI NVS memory */
#define E820_ATTR_ENABLED 0x00000001UL
#define E820_ATTR_NONVOLATILE 0x00000002UL
#define E820_ATTR_UNKNOWN 0xfffffffcUL
#define E820_MIN_SIZE 20
/** Buffer for INT 15,e820 calls */
static struct e820_entry __bss16 ( e820buf );
#define e820buf __use_data16 ( e820buf )
@ -148,8 +156,15 @@ static int meme820 ( struct memory_map *memmap ) {
struct memory_region *region = memmap->regions;
uint32_t next = 0;
uint32_t smap;
size_t size;
unsigned int flags;
unsigned int discard_c, discard_d, discard_D;
unsigned int discard_d, discard_D;
/* Clear the E820 buffer. Do this once before starting,
* rather than on each call; some BIOSes rely on the contents
* being preserved between calls.
*/
memset ( &e820buf, 0, sizeof ( e820buf ) );
do {
__asm__ __volatile__ ( REAL_CODE ( "stc\n\t"
@ -158,7 +173,7 @@ static int meme820 ( struct memory_map *memmap ) {
"popw %w0\n\t" )
: "=r" ( flags ), "=a" ( smap ),
"=b" ( next ), "=D" ( discard_D ),
"=c" ( discard_c ), "=d" ( discard_d )
"=c" ( size ), "=d" ( discard_d )
: "a" ( 0xe820 ), "b" ( next ),
"D" ( __from_data16 ( &e820buf ) ),
"c" ( sizeof ( e820buf ) ),
@ -170,17 +185,42 @@ static int meme820 ( struct memory_map *memmap ) {
return -ENOTSUP;
}
if ( size < E820_MIN_SIZE ) {
DBG ( "INT 15,e820 returned only %zd bytes\n", size );
return -EINVAL;
}
if ( flags & CF ) {
DBG ( "INT 15,e820 terminated on CF set\n" );
break;
}
DBG ( "INT 15,e820 region [%llx,%llx) type %d\n",
DBG ( "INT 15,e820 region [%llx,%llx) type %d",
e820buf.start, ( e820buf.start + e820buf.len ),
( int ) e820buf.type );
if ( size > offsetof ( typeof ( e820buf ), attrs ) ) {
DBG ( " (%s", ( ( e820buf.attrs & E820_ATTR_ENABLED )
? "enabled" : "disabled" ) );
if ( e820buf.attrs & E820_ATTR_NONVOLATILE )
DBG ( ", non-volatile" );
if ( e820buf.attrs & E820_ATTR_UNKNOWN )
DBG ( ", other [%08lx]", e820buf.attrs );
DBG ( ")" );
}
DBG ( "\n" );
/* Discard non-RAM regions */
if ( e820buf.type != E820_TYPE_RAM )
continue;
/* Check extended attributes, if present */
if ( size > offsetof ( typeof ( e820buf ), attrs ) ) {
if ( ! ( e820buf.attrs & E820_ATTR_ENABLED ) )
continue;
if ( e820buf.attrs & E820_ATTR_NONVOLATILE )
continue;
}
region->start = e820buf.start;
region->end = e820buf.start + e820buf.len;
region++;