acpi_user.c revision 85323
190075Sobrien/*-
2169689Skan * Copyright (c) 1999 Doug Rabson
3169689Skan * Copyright (c) 2000 Mitsuru IWASAKI <iwasaki@FreeBSD.org>
4169689Skan * All rights reserved.
590075Sobrien *
690075Sobrien * Redistribution and use in source and binary forms, with or without
7132718Skan * modification, are permitted provided that the following conditions
890075Sobrien * are met:
9132718Skan * 1. Redistributions of source code must retain the above copyright
10132718Skan *    notice, this list of conditions and the following disclaimer.
11132718Skan * 2. Redistributions in binary form must reproduce the above copyright
12132718Skan *    notice, this list of conditions and the following disclaimer in the
1390075Sobrien *    documentation and/or other materials provided with the distribution.
14132718Skan *
15132718Skan * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
16132718Skan * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
17132718Skan * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
1890075Sobrien * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
19132718Skan * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
20132718Skan * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
21169689Skan * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
22169689Skan * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
2390075Sobrien * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
2490075Sobrien * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
2590075Sobrien * SUCH DAMAGE.
26132718Skan *
27132718Skan *	$Id: acpi_user.c,v 1.5 2000/08/09 14:47:52 iwasaki Exp $
2890075Sobrien *	$FreeBSD: head/usr.sbin/acpi/acpidump/acpi_user.c 85323 2001-10-22 17:25:32Z iwasaki $
2990075Sobrien */
3090075Sobrien
3190075Sobrien#include <sys/param.h>
3290075Sobrien#include <sys/mman.h>
3390075Sobrien#include <sys/queue.h>
3490075Sobrien#include <sys/stat.h>
3590075Sobrien
3690075Sobrien#include <err.h>
3790075Sobrien#include <fcntl.h>
3890075Sobrien#include <stdlib.h>
3990075Sobrien#include <string.h>
4090075Sobrien#include <unistd.h>
4190075Sobrien
4290075Sobrien#include "acpidump.h"
4390075Sobrien
4490075Sobrienstatic int      acpi_mem_fd = -1;
4590075Sobrien
4690075Sobrienstruct acpi_user_mapping {
4790075Sobrien	LIST_ENTRY(acpi_user_mapping) link;
4890075Sobrien	vm_offset_t     pa;
4990075Sobrien	caddr_t         va;
5090075Sobrien	size_t          size;
5190075Sobrien};
5290075Sobrien
5390075SobrienLIST_HEAD(acpi_user_mapping_list, acpi_user_mapping) maplist;
54132718Skan
55132718Skanstatic void
56169689Skanacpi_user_init()
57169689Skan{
58169689Skan
59169689Skan	if (acpi_mem_fd == -1) {
60132718Skan		acpi_mem_fd = open("/dev/mem", O_RDONLY);
61132718Skan		if (acpi_mem_fd == -1)
62132718Skan			err(1, "opening /dev/mem");
63169689Skan		LIST_INIT(&maplist);
64169689Skan	}
65169689Skan}
6690075Sobrien
6790075Sobrienstatic struct acpi_user_mapping *
6890075Sobrienacpi_user_find_mapping(vm_offset_t pa, size_t size)
6990075Sobrien{
7090075Sobrien	struct	acpi_user_mapping *map;
7190075Sobrien
7290075Sobrien	/* First search for an existing mapping */
7390075Sobrien	for (map = LIST_FIRST(&maplist); map; map = LIST_NEXT(map, link)) {
74132718Skan		if (map->pa <= pa && map->size >= pa + size - map->pa)
75132718Skan			return (map);
76132718Skan	}
77132718Skan
78132718Skan	/* Then create a new one */
79132718Skan	size = round_page(pa + size) - trunc_page(pa);
80132718Skan	pa = trunc_page(pa);
81132718Skan	map = malloc(sizeof(struct acpi_user_mapping));
82132718Skan	if (!map)
83132718Skan		errx(1, "out of memory");
84169689Skan	map->pa = pa;
85169689Skan	map->va = mmap(0, size, PROT_READ, MAP_SHARED, acpi_mem_fd, pa);
86132718Skan	map->size = size;
87132718Skan	if ((intptr_t) map->va == -1)
88132718Skan		err(1, "can't map address");
89132718Skan	LIST_INSERT_HEAD(&maplist, map, link);
90132718Skan
91132718Skan	return (map);
92132718Skan}
93132718Skan
94132718Skan/*
95132718Skan * Public interfaces
96132718Skan */
97132718Skan
98132718Skanstruct ACPIrsdp *
99132718Skanacpi_find_rsd_ptr()
100132718Skan{
101132718Skan	int		i;
102132718Skan	u_int8_t	buf[sizeof(struct ACPIrsdp)];
103132718Skan
104132718Skan	acpi_user_init();
105132718Skan	for (i = 0; i < 1024 * 1024; i += 16) {
106132718Skan		read(acpi_mem_fd, buf, 16);
107132718Skan		if (!memcmp(buf, "RSD PTR ", 8)) {
108132718Skan			/* Read the rest of the structure */
109132718Skan			read(acpi_mem_fd, buf + 16, sizeof(struct ACPIrsdp) - 16);
110132718Skan
111132718Skan			/* Verify checksum before accepting it. */
112132718Skan			if (acpi_checksum(buf, sizeof(struct ACPIrsdp)))
113132718Skan				continue;
114169689Skan			return (acpi_map_physical(i, sizeof(struct ACPIrsdp)));
115169689Skan		}
116169689Skan	}
117169689Skan
118169689Skan	return (0);
119169689Skan}
120169689Skan
121169689Skanvoid *
122169689Skanacpi_map_physical(vm_offset_t pa, size_t size)
123169689Skan{
124169689Skan	struct	acpi_user_mapping *map;
125169689Skan
126169689Skan	map = acpi_user_find_mapping(pa, size);
127169689Skan	return (map->va + (pa - map->pa));
128169689Skan}
129169689Skan
130169689Skanvoid
13190075Sobrienacpi_load_dsdt(char *dumpfile, u_int8_t **dpp, u_int8_t **endp)
13290075Sobrien{
13390075Sobrien	u_int8_t	*dp;
13490075Sobrien	u_int8_t	*end;
13590075Sobrien	struct	stat sb;
13690075Sobrien
13790075Sobrien	if ((acpi_mem_fd = open(dumpfile, O_RDONLY)) == -1) {
13890075Sobrien		errx(1, "opening %s\n", dumpfile);
13990075Sobrien	}
14090075Sobrien
14190075Sobrien	LIST_INIT(&maplist);
142132718Skan
143132718Skan	if (fstat(acpi_mem_fd, &sb) == -1) {
144132718Skan		errx(1, "fstat %s\n", dumpfile);
145132718Skan	}
146132718Skan
147132718Skan	dp = mmap(0, sb.st_size, PROT_READ, MAP_PRIVATE, acpi_mem_fd, 0);
148132718Skan	if (dp == NULL) {
149132718Skan		errx(1, "mmap %s\n", dumpfile);
150132718Skan	}
151132718Skan
152132718Skan	if (strncmp(dp, "DSDT", 4) == 0) {
153132718Skan		memcpy(&dsdt_header, dp, SIZEOF_SDT_HDR);
154132718Skan		dp += SIZEOF_SDT_HDR;
155132718Skan		sb.st_size -= SIZEOF_SDT_HDR;
156169689Skan	}
157169689Skan
158169689Skan	end = (u_int8_t *) dp + sb.st_size;
159169689Skan	*dpp = dp;
16090075Sobrien	*endp = end;
16190075Sobrien}
162169689Skan