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