svn commit: r191111 - in head/sys: amd64/include amd64/include/pc boot/i386/libi386 i386/include i386/include/pc

Jung-uk Kim jkim at FreeBSD.org
Wed Apr 15 17:31:25 UTC 2009


Author: jkim
Date: Wed Apr 15 17:31:22 2009
New Revision: 191111
URL: http://svn.freebsd.org/changeset/base/191111

Log:
  A simple rewrite of biossmap.c:
  
  - Do not iterate int 15h, function e820h twice.  Instead, we use STAILQ to
  store each return buffer and copy all at once.
  - Export optional extended attributes defined in ACPI 3.0 as separate
  metadata.  Currently, there are only two bits defined in the specification.
  For example, if the descriptor has extended attributes and it is not
  enabled, it has to be ignored by OS.  We may implement it in the kernel
  later if it is necessary and proven correct in reality.
  - Check return buffer size strictly as suggested in ACPI 3.0.
  
  Reviewed by:	jhb

Modified:
  head/sys/amd64/include/metadata.h
  head/sys/amd64/include/pc/bios.h
  head/sys/boot/i386/libi386/biossmap.c
  head/sys/i386/include/metadata.h
  head/sys/i386/include/pc/bios.h

Modified: head/sys/amd64/include/metadata.h
==============================================================================
--- head/sys/amd64/include/metadata.h	Wed Apr 15 17:14:43 2009	(r191110)
+++ head/sys/amd64/include/metadata.h	Wed Apr 15 17:31:22 2009	(r191111)
@@ -30,5 +30,6 @@
 #define	_MACHINE_METADATA_H_
 
 #define	MODINFOMD_SMAP		0x1001
+#define	MODINFOMD_SMAP_XATTR	0x1002
 
 #endif /* !_MACHINE_METADATA_H_ */

Modified: head/sys/amd64/include/pc/bios.h
==============================================================================
--- head/sys/amd64/include/pc/bios.h	Wed Apr 15 17:14:43 2009	(r191110)
+++ head/sys/amd64/include/pc/bios.h	Wed Apr 15 17:31:22 2009	(r191111)
@@ -48,6 +48,10 @@ extern u_int32_t	bios_sigsearch(u_int32_
 #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;

Modified: head/sys/boot/i386/libi386/biossmap.c
==============================================================================
--- head/sys/boot/i386/libi386/biossmap.c	Wed Apr 15 17:14:43 2009	(r191110)
+++ head/sys/boot/i386/libi386/biossmap.c	Wed Apr 15 17:31:22 2009	(r191111)
@@ -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 SMA
 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);
 }

Modified: head/sys/i386/include/metadata.h
==============================================================================
--- head/sys/i386/include/metadata.h	Wed Apr 15 17:14:43 2009	(r191110)
+++ head/sys/i386/include/metadata.h	Wed Apr 15 17:31:22 2009	(r191111)
@@ -30,5 +30,6 @@
 #define	_MACHINE_METADATA_H_
 
 #define	MODINFOMD_SMAP		0x1001
+#define	MODINFOMD_SMAP_XATTR	0x1002
 
 #endif /* !_MACHINE_METADATA_H_ */

Modified: head/sys/i386/include/pc/bios.h
==============================================================================
--- head/sys/i386/include/pc/bios.h	Wed Apr 15 17:14:43 2009	(r191110)
+++ head/sys/i386/include/pc/bios.h	Wed Apr 15 17:31:22 2009	(r191111)
@@ -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;


More information about the svn-src-all mailing list