mirror of https://github.com/ipxe/ipxe.git
[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.pull/1/head
parent
0015601f0b
commit
040f7cdf3a
|
@ -41,6 +41,8 @@ struct e820_entry {
|
||||||
uint64_t len;
|
uint64_t len;
|
||||||
/** Type of region */
|
/** Type of region */
|
||||||
uint32_t type;
|
uint32_t type;
|
||||||
|
/** Extended attributes (optional) */
|
||||||
|
uint32_t attrs;
|
||||||
} __attribute__ (( packed ));
|
} __attribute__ (( packed ));
|
||||||
|
|
||||||
#define E820_TYPE_RAM 1 /**< Normal memory */
|
#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_ACPI 3 /**< ACPI reclaim memory */
|
||||||
#define E820_TYPE_NVS 4 /**< ACPI NVS 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 */
|
/** Buffer for INT 15,e820 calls */
|
||||||
static struct e820_entry __bss16 ( e820buf );
|
static struct e820_entry __bss16 ( e820buf );
|
||||||
#define e820buf __use_data16 ( e820buf )
|
#define e820buf __use_data16 ( e820buf )
|
||||||
|
@ -148,8 +156,15 @@ static int meme820 ( struct memory_map *memmap ) {
|
||||||
struct memory_region *region = memmap->regions;
|
struct memory_region *region = memmap->regions;
|
||||||
uint32_t next = 0;
|
uint32_t next = 0;
|
||||||
uint32_t smap;
|
uint32_t smap;
|
||||||
|
size_t size;
|
||||||
unsigned int flags;
|
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 {
|
do {
|
||||||
__asm__ __volatile__ ( REAL_CODE ( "stc\n\t"
|
__asm__ __volatile__ ( REAL_CODE ( "stc\n\t"
|
||||||
|
@ -158,7 +173,7 @@ static int meme820 ( struct memory_map *memmap ) {
|
||||||
"popw %w0\n\t" )
|
"popw %w0\n\t" )
|
||||||
: "=r" ( flags ), "=a" ( smap ),
|
: "=r" ( flags ), "=a" ( smap ),
|
||||||
"=b" ( next ), "=D" ( discard_D ),
|
"=b" ( next ), "=D" ( discard_D ),
|
||||||
"=c" ( discard_c ), "=d" ( discard_d )
|
"=c" ( size ), "=d" ( discard_d )
|
||||||
: "a" ( 0xe820 ), "b" ( next ),
|
: "a" ( 0xe820 ), "b" ( next ),
|
||||||
"D" ( __from_data16 ( &e820buf ) ),
|
"D" ( __from_data16 ( &e820buf ) ),
|
||||||
"c" ( sizeof ( e820buf ) ),
|
"c" ( sizeof ( e820buf ) ),
|
||||||
|
@ -170,17 +185,42 @@ static int meme820 ( struct memory_map *memmap ) {
|
||||||
return -ENOTSUP;
|
return -ENOTSUP;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if ( size < E820_MIN_SIZE ) {
|
||||||
|
DBG ( "INT 15,e820 returned only %zd bytes\n", size );
|
||||||
|
return -EINVAL;
|
||||||
|
}
|
||||||
|
|
||||||
if ( flags & CF ) {
|
if ( flags & CF ) {
|
||||||
DBG ( "INT 15,e820 terminated on CF set\n" );
|
DBG ( "INT 15,e820 terminated on CF set\n" );
|
||||||
break;
|
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 ),
|
e820buf.start, ( e820buf.start + e820buf.len ),
|
||||||
( int ) e820buf.type );
|
( 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 )
|
if ( e820buf.type != E820_TYPE_RAM )
|
||||||
continue;
|
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->start = e820buf.start;
|
||||||
region->end = e820buf.start + e820buf.len;
|
region->end = e820buf.start + e820buf.len;
|
||||||
region++;
|
region++;
|
||||||
|
|
Loading…
Reference in New Issue