From 040f7cdf3a99ed56a4487efc8e131c84984925bf Mon Sep 17 00:00:00 2001 From: Michael Brown Date: Mon, 29 Sep 2008 03:55:13 +0100 Subject: [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. --- src/arch/i386/firmware/pcbios/memmap.c | 46 +++++++++++++++++++++++++++++++--- 1 file changed, 43 insertions(+), 3 deletions(-) diff --git a/src/arch/i386/firmware/pcbios/memmap.c b/src/arch/i386/firmware/pcbios/memmap.c index e6d6428e..9de10a7a 100644 --- a/src/arch/i386/firmware/pcbios/memmap.c +++ b/src/arch/i386/firmware/pcbios/memmap.c @@ -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++; -- cgit v1.2.3-55-g7522