18eef2abToomas Soome/*
2199767fToomas Soome * Copyright (c) 1998 Michael Smith <msmith@freebsd.org>
3199767fToomas Soome * All rights reserved.
4199767fToomas Soome *
5199767fToomas Soome * Redistribution and use in source and binary forms, with or without
6199767fToomas Soome * modification, are permitted provided that the following conditions
7199767fToomas Soome * are met:
8199767fToomas Soome * 1. Redistributions of source code must retain the above copyright
9199767fToomas Soome *    notice, this list of conditions and the following disclaimer.
10199767fToomas Soome * 2. Redistributions in binary form must reproduce the above copyright
11199767fToomas Soome *    notice, this list of conditions and the following disclaimer in the
12199767fToomas Soome *    documentation and/or other materials provided with the distribution.
13199767fToomas Soome *
14199767fToomas Soome * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
15199767fToomas Soome * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
16199767fToomas Soome * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
17199767fToomas Soome * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
18199767fToomas Soome * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
19199767fToomas Soome * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
20199767fToomas Soome * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
21199767fToomas Soome * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
22199767fToomas Soome * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
23199767fToomas Soome * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
24199767fToomas Soome * SUCH DAMAGE.
25199767fToomas Soome */
26199767fToomas Soome
27199767fToomas Soome#include <sys/cdefs.h>
28199767fToomas Soome
29199767fToomas Soome/*
30199767fToomas Soome * Obtain memory configuration information from the BIOS
31199767fToomas Soome */
32199767fToomas Soome#include <stand.h>
33199767fToomas Soome#include <sys/param.h>
34199767fToomas Soome#include <sys/linker.h>
35199767fToomas Soome#include <sys/queue.h>
36199767fToomas Soome#include <sys/stddef.h>
37199767fToomas Soome#include <machine/metadata.h>
38199767fToomas Soome#include <machine/pc/bios.h>
39199767fToomas Soome#include "bootstrap.h"
40199767fToomas Soome#include "libi386.h"
41199767fToomas Soome#include "btxv86.h"
42199767fToomas Soome
43199767fToomas Soomestruct smap_buf {
44199767fToomas Soome	struct bios_smap	smap;
45199767fToomas Soome	uint32_t		xattr;	/* Extended attribute from ACPI 3.0 */
46199767fToomas Soome	STAILQ_ENTRY(smap_buf)	bufs;
47199767fToomas Soome};
48199767fToomas Soome
49199767fToomas Soome#define	SMAP_BUFSIZE		offsetof(struct smap_buf, bufs)
50199767fToomas Soome
51199767fToomas Soomestatic struct bios_smap		*smapbase;
52199767fToomas Soomestatic uint32_t			*smapattr;
53199767fToomas Soomestatic u_int			smaplen;
54199767fToomas Soome
55199767fToomas Soomevoid
56199767fToomas Soomebios_getsmap(void)
57199767fToomas Soome{
58199767fToomas Soome	struct smap_buf		buf;
59199767fToomas Soome	STAILQ_HEAD(smap_head, smap_buf) head =
60199767fToomas Soome	    STAILQ_HEAD_INITIALIZER(head);
61199767fToomas Soome	struct smap_buf		*cur, *next;
62199767fToomas Soome	u_int			n, x;
63199767fToomas Soome
64199767fToomas Soome	STAILQ_INIT(&head);
65199767fToomas Soome	n = 0;
66199767fToomas Soome	x = 0;
67199767fToomas Soome	v86.ebx = 0;
68199767fToomas Soome	do {
69199767fToomas Soome		v86.ctl = V86_FLAGS;
70199767fToomas Soome		v86.addr = 0x15;
71199767fToomas Soome		v86.eax = 0xe820;	/* int 0x15 function 0xe820 */
72199767fToomas Soome		v86.ecx = SMAP_BUFSIZE;
73199767fToomas Soome		v86.edx = SMAP_SIG;
74199767fToomas Soome		v86.es = VTOPSEG(&buf);
75199767fToomas Soome		v86.edi = VTOPOFF(&buf);
76199767fToomas Soome		v86int();
77199767fToomas Soome		if (V86_CY(v86.efl) || v86.eax != SMAP_SIG ||
78199767fToomas Soome		    v86.ecx < sizeof(buf.smap) || v86.ecx > SMAP_BUFSIZE)
79199767fToomas Soome			break;
80199767fToomas Soome
81199767fToomas Soome		next = malloc(sizeof(*next));
82199767fToomas Soome		if (next == NULL)
83199767fToomas Soome			break;
84199767fToomas Soome		next->smap = buf.smap;
85199767fToomas Soome		if (v86.ecx == SMAP_BUFSIZE) {
86199767fToomas Soome			next->xattr = buf.xattr;
87199767fToomas Soome			x++;
88199767fToomas Soome		}
89199767fToomas Soome		STAILQ_INSERT_TAIL(&head, next, bufs);
90199767fToomas Soome		n++;
91199767fToomas Soome	} while (v86.ebx != 0);
92199767fToomas Soome	smaplen = n;
93199767fToomas Soome
94199767fToomas Soome	if (smaplen > 0) {
95199767fToomas Soome		smapbase = malloc(smaplen * sizeof(*smapbase));
96199767fToomas Soome		if (smapbase != NULL) {
97199767fToomas Soome			n = 0;
98199767fToomas Soome			STAILQ_FOREACH(cur, &head, bufs)
99199767fToomas Soome				smapbase[n++] = cur->smap;
100199767fToomas Soome		}
101199767fToomas Soome		if (smaplen == x) {
102199767fToomas Soome			smapattr = malloc(smaplen * sizeof(*smapattr));
103199767fToomas Soome			if (smapattr != NULL) {
104199767fToomas Soome				n = 0;
105199767fToomas Soome				STAILQ_FOREACH(cur, &head, bufs)
106199767fToomas Soome					smapattr[n++] = cur->xattr &
107199767fToomas Soome					    SMAP_XATTR_MASK;
108199767fToomas Soome			}
109199767fToomas Soome		} else
110199767fToomas Soome			smapattr = NULL;
111199767fToomas Soome		cur = STAILQ_FIRST(&head);
112199767fToomas Soome		while (cur != NULL) {
113199767fToomas Soome			next = STAILQ_NEXT(cur, bufs);
114199767fToomas Soome			free(cur);
115199767fToomas Soome			cur = next;
116199767fToomas Soome		}
117199767fToomas Soome	}
118199767fToomas Soome}
119199767fToomas Soome
120199767fToomas Soomevoid
121199767fToomas Soomebios_addsmapdata(struct preloaded_file *kfp)
122199767fToomas Soome{
123199767fToomas Soome	size_t			size;
124199767fToomas Soome
125199767fToomas Soome	if (smapbase == NULL || smaplen == 0)
126199767fToomas Soome		return;
127199767fToomas Soome	size = smaplen * sizeof(*smapbase);
128199767fToomas Soome	file_addmetadata(kfp, MODINFOMD_SMAP, size, smapbase);
129199767fToomas Soome	if (smapattr != NULL) {
130199767fToomas Soome		size = smaplen * sizeof(*smapattr);
131199767fToomas Soome		file_addmetadata(kfp, MODINFOMD_SMAP_XATTR, size, smapattr);
132199767fToomas Soome	}
133199767fToomas Soome}
134199767fToomas Soome
135199767fToomas SoomeCOMMAND_SET(smap, "smap", "show BIOS SMAP", command_smap);
136199767fToomas Soome
137199767fToomas Soomestatic int
1388eef2abToomas Soomecommand_smap(int argc __unused, char *argv[] __unused)
139199767fToomas Soome{
140199767fToomas Soome	u_int			i;
141199767fToomas Soome
142199767fToomas Soome	if (smapbase == NULL || smaplen == 0)
143199767fToomas Soome		return (CMD_ERROR);
144199767fToomas Soome	if (smapattr != NULL)
145199767fToomas Soome		for (i = 0; i < smaplen; i++)
146199767fToomas Soome			printf("SMAP type=%02x base=%016llx len=%016llx attr=%02x\n",
147199767fToomas Soome			    (unsigned int)smapbase[i].type,
148199767fToomas Soome			    (unsigned long long)smapbase[i].base,
149199767fToomas Soome			    (unsigned long long)smapbase[i].length,
150199767fToomas Soome			    (unsigned int)smapattr[i]);
151199767fToomas Soome	else
152199767fToomas Soome		for (i = 0; i < smaplen; i++)
153199767fToomas Soome			printf("SMAP type=%02x base=%016llx len=%016llx\n",
154199767fToomas Soome			    (unsigned int)smapbase[i].type,
155199767fToomas Soome			    (unsigned long long)smapbase[i].base,
156199767fToomas Soome			    (unsigned long long)smapbase[i].length);
157199767fToomas Soome	return (CMD_OK);
158199767fToomas Soome}
159