diff options
| author | Jung-uk Kim <jkim@FreeBSD.org> | 2009-04-15 17:31:22 +0000 | 
|---|---|---|
| committer | Jung-uk Kim <jkim@FreeBSD.org> | 2009-04-15 17:31:22 +0000 | 
| commit | cebe9dc98adf16eecd80299eae1424fa2c89c934 (patch) | |
| tree | 42347e17b226dd42a13dd0a4b0ea3697313e1f46 | |
| parent | b0089534dac28739f0175f1ae58ef59b4ecacbc4 (diff) | |
Notes
| -rw-r--r-- | sys/amd64/include/metadata.h | 1 | ||||
| -rw-r--r-- | sys/amd64/include/pc/bios.h | 4 | ||||
| -rw-r--r-- | sys/boot/i386/libi386/biossmap.c | 131 | ||||
| -rw-r--r-- | sys/i386/include/metadata.h | 1 | ||||
| -rw-r--r-- | sys/i386/include/pc/bios.h | 4 | 
5 files changed, 97 insertions, 44 deletions
| diff --git a/sys/amd64/include/metadata.h b/sys/amd64/include/metadata.h index 84e6f87399704..4c7ec9e154a2a 100644 --- a/sys/amd64/include/metadata.h +++ b/sys/amd64/include/metadata.h @@ -30,5 +30,6 @@  #define	_MACHINE_METADATA_H_  #define	MODINFOMD_SMAP		0x1001 +#define	MODINFOMD_SMAP_XATTR	0x1002  #endif /* !_MACHINE_METADATA_H_ */ diff --git a/sys/amd64/include/pc/bios.h b/sys/amd64/include/pc/bios.h index 782d4bfc66342..364f86cb32e9a 100644 --- a/sys/amd64/include/pc/bios.h +++ b/sys/amd64/include/pc/bios.h @@ -48,6 +48,10 @@ extern u_int32_t	bios_sigsearch(u_int32_t start, u_char *sig, int siglen,  #define	SMAP_TYPE_ACPI_NVS	4  #define	SMAP_TYPE_ACPI_ERROR	5 +#define	SMAP_XATTR_ENABLED	0x00000001 +#define	SMAP_XATTR_NON_VOLATILE	0x00000002 +#define	SMAP_XATTR_MASK		(SMAP_XATTR_ENABLED | SMAP_XATTR_NON_VOLATILE) +  struct bios_smap {      u_int64_t	base;      u_int64_t	length; diff --git a/sys/boot/i386/libi386/biossmap.c b/sys/boot/i386/libi386/biossmap.c index 51f015a2514d4..5a788c1724955 100644 --- a/sys/boot/i386/libi386/biossmap.c +++ b/sys/boot/i386/libi386/biossmap.c @@ -33,74 +33,107 @@ __FBSDID("$FreeBSD$");  #include <stand.h>  #include <sys/param.h>  #include <sys/linker.h> +#include <sys/queue.h> +#include <sys/stddef.h>  #include <machine/metadata.h> +#include <machine/psl.h>  #include <machine/pc/bios.h>  #include "bootstrap.h"  #include "libi386.h"  #include "btxv86.h" -static struct { -	struct bios_smap _smap_entry; -	char pad[8];		/* Bad BIOS writer, no cookie! */ -} smap; +#define	V86_CY(x)	((x) & PSL_C) -static struct bios_smap *smapbase; -static int smaplen; +struct smap_buf { +	struct bios_smap	smap; +	uint32_t		xattr;	/* Extended attribute from ACPI 3.0 */ +	STAILQ_ENTRY(smap_buf)	bufs; +}; + +#define	SMAP_BUFSIZE		offsetof(struct smap_buf, bufs) + +static struct bios_smap		*smapbase; +static uint32_t			*smapattr; +static u_int			smaplen;  void  bios_getsmap(void)  { -	int n; +	struct smap_buf		buf; +	STAILQ_HEAD(smap_head, smap_buf) head = +	    STAILQ_HEAD_INITIALIZER(head); +	struct smap_buf		*cur, *next; +	u_int			n, x; +	STAILQ_INIT(&head);  	n = 0; -	smaplen = 0; -	/* Count up segments in system memory map */ +	x = 0;  	v86.ebx = 0;  	do {  		v86.ctl = V86_FLAGS; -		v86.addr = 0x15;		/* int 0x15 function 0xe820*/ -		v86.eax = 0xe820; -		v86.ecx = sizeof(struct bios_smap); +		v86.addr = 0x15; +		v86.eax = 0xe820;	/* int 0x15 function 0xe820 */ +		v86.ecx = SMAP_BUFSIZE;  		v86.edx = SMAP_SIG; -		v86.es = VTOPSEG(&smap); -		v86.edi = VTOPOFF(&smap); +		v86.es = VTOPSEG(&buf); +		v86.edi = VTOPOFF(&buf);  		v86int(); -		if ((v86.efl & 1) || (v86.eax != SMAP_SIG)) +		if (V86_CY(v86.efl) || v86.eax != SMAP_SIG || +		    v86.ecx < sizeof(buf.smap) || v86.ecx > SMAP_BUFSIZE) +			break; + +		next = malloc(sizeof(*next)); +		if (next == NULL)  			break; +		next->smap = buf.smap; +		if (v86.ecx == SMAP_BUFSIZE) { +			next->xattr = buf.xattr; +			x++; +		} +		STAILQ_INSERT_TAIL(&head, next, bufs);  		n++;  	} while (v86.ebx != 0); -	if (n == 0) -		return; -	n += 10;	/* spare room */ -	smapbase = malloc(n * sizeof(*smapbase)); +	smaplen = n; -	/* Save system memory map */ -	v86.ebx = 0; -	do { -		v86.ctl = V86_FLAGS; -		v86.addr = 0x15;		/* int 0x15 function 0xe820*/ -		v86.eax = 0xe820; -		v86.ecx = sizeof(struct bios_smap); -		v86.edx = SMAP_SIG; -		v86.es = VTOPSEG(&smap); -		v86.edi = VTOPOFF(&smap); -		v86int(); -		bcopy(&smap, &smapbase[smaplen], sizeof(struct bios_smap)); -		smaplen++; -		if ((v86.efl & 1) || (v86.eax != SMAP_SIG)) -			break; -	} while (v86.ebx != 0 && smaplen < n); +	if (smaplen > 0) { +		smapbase = malloc(smaplen * sizeof(*smapbase)); +		if (smapbase != NULL) { +			n = 0; +			STAILQ_FOREACH(cur, &head, bufs) +				smapbase[n++] = cur->smap; +		} +		if (smaplen == x) { +			smapattr = malloc(smaplen * sizeof(*smapattr)); +			if (smapattr != NULL) { +				n = 0; +				STAILQ_FOREACH(cur, &head, bufs) +					smapattr[n++] = cur->xattr & +					    SMAP_XATTR_MASK; +			} +		} else +			smapattr = NULL; +		cur = STAILQ_FIRST(&head); +		while (cur != NULL) { +			next = STAILQ_NEXT(cur, bufs); +			free(cur); +			cur = next; +		} +	}  }  void  bios_addsmapdata(struct preloaded_file *kfp)  { -	int len; +	size_t			size; -	if (smapbase == 0 || smaplen == 0) +	if (smapbase == NULL || smaplen == 0)  		return; -	len = smaplen * sizeof(*smapbase); -	file_addmetadata(kfp, MODINFOMD_SMAP, len, smapbase); +	size = smaplen * sizeof(*smapbase); +	file_addmetadata(kfp, MODINFOMD_SMAP, size, smapbase); +	if (smapattr != NULL) { +		size = smaplen * sizeof(*smapattr); +		file_addmetadata(kfp, MODINFOMD_SMAP_XATTR, size, smapattr); +	}  }  COMMAND_SET(smap, "smap", "show BIOS SMAP", command_smap); @@ -108,12 +141,22 @@ COMMAND_SET(smap, "smap", "show BIOS SMAP", command_smap);  static int  command_smap(int argc, char *argv[])  { -	int i; +	u_int			i; -	if (smapbase == 0 || smaplen == 0) +	if (smapbase == NULL || smaplen == 0)  		return (CMD_ERROR); -	for (i = 0; i < smaplen; i++) -		printf("SMAP type=%02x base=%016llx len=%016llx\n", -		    smapbase[i].type, smapbase[i].base, smapbase[i].length); +	if (smapattr != NULL) +		for (i = 0; i < smaplen; i++) +			printf("SMAP type=%02x base=%016llx len=%016llx attr=%02x\n", +			    (unsigned int)smapbase[i].type, +			    (unsigned long long)smapbase[i].base, +			    (unsigned long long)smapbase[i].length, +			    (unsigned int)smapattr[i]); +	else +		for (i = 0; i < smaplen; i++) +			printf("SMAP type=%02x base=%016llx len=%016llx\n", +			    (unsigned int)smapbase[i].type, +			    (unsigned long long)smapbase[i].base, +			    (unsigned long long)smapbase[i].length);  	return (CMD_OK);  } diff --git a/sys/i386/include/metadata.h b/sys/i386/include/metadata.h index 84e6f87399704..4c7ec9e154a2a 100644 --- a/sys/i386/include/metadata.h +++ b/sys/i386/include/metadata.h @@ -30,5 +30,6 @@  #define	_MACHINE_METADATA_H_  #define	MODINFOMD_SMAP		0x1001 +#define	MODINFOMD_SMAP_XATTR	0x1002  #endif /* !_MACHINE_METADATA_H_ */ diff --git a/sys/i386/include/pc/bios.h b/sys/i386/include/pc/bios.h index ca060249d2904..e705d130baa95 100644 --- a/sys/i386/include/pc/bios.h +++ b/sys/i386/include/pc/bios.h @@ -281,6 +281,10 @@ struct PIR_table  #define	SMAP_TYPE_ACPI_NVS	4  #define	SMAP_TYPE_ACPI_ERROR	5 +#define	SMAP_XATTR_ENABLED	0x00000001 +#define	SMAP_XATTR_NON_VOLATILE	0x00000002 +#define	SMAP_XATTR_MASK		(SMAP_XATTR_ENABLED | SMAP_XATTR_NON_VOLATILE) +  struct bios_smap {      u_int64_t	base;      u_int64_t	length; | 
