182531Smsmith/*- 282531Smsmith * Copyright (c) 2001 Michael Smith <msmith@freebsd.org> 382531Smsmith * All rights reserved. 482531Smsmith * 582531Smsmith * Redistribution and use in source and binary forms, with or without 682531Smsmith * modification, are permitted provided that the following conditions 782531Smsmith * are met: 882531Smsmith * 1. Redistributions of source code must retain the above copyright 982531Smsmith * notice, this list of conditions and the following disclaimer. 1082531Smsmith * 2. Redistributions in binary form must reproduce the above copyright 1182531Smsmith * notice, this list of conditions and the following disclaimer in the 1282531Smsmith * documentation and/or other materials provided with the distribution. 1382531Smsmith * 1482531Smsmith * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 1582531Smsmith * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 1682531Smsmith * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 1782531Smsmith * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 1882531Smsmith * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 1982531Smsmith * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 2082531Smsmith * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 2182531Smsmith * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 2282531Smsmith * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 2382531Smsmith * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 2482531Smsmith * SUCH DAMAGE. 2582531Smsmith */ 2682531Smsmith 27119482Sobrien#include <sys/cdefs.h> 28119482Sobrien__FBSDID("$FreeBSD$"); 29119482Sobrien 3082531Smsmith#include <stand.h> 3182531Smsmith#include <machine/stdarg.h> 3282531Smsmith#include <bootstrap.h> 33158023Sjhb#include <btxv86.h> 34158023Sjhb#include "libi386.h" 3582531Smsmith 36193530Sjkim#include "platform/acfreebsd.h" 37117529Snjl#include "acconfig.h" 38114246Snjl#define ACPI_SYSTEM_XFACE 3982531Smsmith#include "actypes.h" 4082531Smsmith#include "actbl.h" 4182531Smsmith 4282531Smsmith/* 43215016Sjhb * Detect ACPI and export information about the ACPI BIOS into the 4482531Smsmith * environment. 4582531Smsmith */ 4682531Smsmith 47167814Sjkimstatic ACPI_TABLE_RSDP *biosacpi_find_rsdp(void); 48167814Sjkimstatic ACPI_TABLE_RSDP *biosacpi_search_rsdp(char *base, int length); 4982531Smsmith 5082531Smsmith#define RSDP_CHECKSUM_LENGTH 20 5182531Smsmith 5282531Smsmithvoid 5382531Smsmithbiosacpi_detect(void) 5482531Smsmith{ 55167814Sjkim ACPI_TABLE_RSDP *rsdp; 56145158Snjl char buf[24]; 5782531Smsmith int revision; 5882531Smsmith 5982531Smsmith /* locate and validate the RSDP */ 6082531Smsmith if ((rsdp = biosacpi_find_rsdp()) == NULL) 6182531Smsmith return; 6282531Smsmith 6382531Smsmith /* export values from the RSDP */ 64254733Sjkim sprintf(buf, "0x%08x", VTOP(rsdp)); 65167814Sjkim setenv("hint.acpi.0.rsdp", buf, 1); 6682531Smsmith revision = rsdp->Revision; 6782531Smsmith if (revision == 0) 6882531Smsmith revision = 1; 6982531Smsmith sprintf(buf, "%d", revision); 7082531Smsmith setenv("hint.acpi.0.revision", buf, 1); 71129195Sjdp strncpy(buf, rsdp->OemId, sizeof(rsdp->OemId)); 72129195Sjdp buf[sizeof(rsdp->OemId)] = '\0'; 7382531Smsmith setenv("hint.acpi.0.oem", buf, 1); 7482531Smsmith sprintf(buf, "0x%08x", rsdp->RsdtPhysicalAddress); 7582531Smsmith setenv("hint.acpi.0.rsdt", buf, 1); 7682531Smsmith if (revision >= 2) { 7782531Smsmith /* XXX extended checksum? */ 7882531Smsmith sprintf(buf, "0x%016llx", rsdp->XsdtPhysicalAddress); 7982531Smsmith setenv("hint.acpi.0.xsdt", buf, 1); 8082531Smsmith sprintf(buf, "%d", rsdp->Length); 8182531Smsmith setenv("hint.acpi.0.xsdt_length", buf, 1); 8282531Smsmith } 8382531Smsmith} 8482531Smsmith 8582531Smsmith/* 86129702Snjl * Find the RSDP in low memory. See section 5.2.2 of the ACPI spec. 8782531Smsmith */ 88167814Sjkimstatic ACPI_TABLE_RSDP * 8982531Smsmithbiosacpi_find_rsdp(void) 9082531Smsmith{ 91167814Sjkim ACPI_TABLE_RSDP *rsdp; 92129702Snjl uint16_t *addr; 9382531Smsmith 94129702Snjl /* EBDA is the 1 KB addressed by the 16 bit pointer at 0x40E. */ 95158023Sjhb addr = (uint16_t *)PTOV(0x40E); 96129702Snjl if ((rsdp = biosacpi_search_rsdp((char *)(*addr << 4), 0x400)) != NULL) 97129702Snjl return (rsdp); 9882531Smsmith 99129702Snjl /* Check the upper memory BIOS space, 0xe0000 - 0xfffff. */ 10082531Smsmith if ((rsdp = biosacpi_search_rsdp((char *)0xe0000, 0x20000)) != NULL) 101129702Snjl return (rsdp); 10282531Smsmith 103129702Snjl return (NULL); 10482531Smsmith} 10582531Smsmith 106167814Sjkimstatic ACPI_TABLE_RSDP * 10782531Smsmithbiosacpi_search_rsdp(char *base, int length) 10882531Smsmith{ 109167814Sjkim ACPI_TABLE_RSDP *rsdp; 11082531Smsmith u_int8_t *cp, sum; 11182531Smsmith int ofs, idx; 11282531Smsmith 11382531Smsmith /* search on 16-byte boundaries */ 11482531Smsmith for (ofs = 0; ofs < length; ofs += 16) { 115167814Sjkim rsdp = (ACPI_TABLE_RSDP *)PTOV(base + ofs); 11682531Smsmith 11782531Smsmith /* compare signature, validate checksum */ 118167814Sjkim if (!strncmp(rsdp->Signature, ACPI_SIG_RSDP, strlen(ACPI_SIG_RSDP))) { 11982531Smsmith cp = (u_int8_t *)rsdp; 12082531Smsmith sum = 0; 12182531Smsmith for (idx = 0; idx < RSDP_CHECKSUM_LENGTH; idx++) 12282531Smsmith sum += *(cp + idx); 123200357Sjhb if (sum != 0) 12482531Smsmith continue; 12582531Smsmith return(rsdp); 12682531Smsmith } 12782531Smsmith } 12882531Smsmith return(NULL); 12982531Smsmith} 130