/*-1* Copyright (c) 2001 Michael Smith <[email protected]>2* All rights reserved.3*4* Redistribution and use in source and binary forms, with or without5* modification, are permitted provided that the following conditions6* are met:7* 1. Redistributions of source code must retain the above copyright8* notice, this list of conditions and the following disclaimer.9* 2. Redistributions in binary form must reproduce the above copyright10* notice, this list of conditions and the following disclaimer in the11* documentation and/or other materials provided with the distribution.12*13* THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND14* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE15* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE16* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE17* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL18* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS19* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)20* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT21* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY22* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF23* SUCH DAMAGE.24*/2526#include <stand.h>27#include <sys/stdarg.h>28#include <bootstrap.h>29#include <btxv86.h>30#include "libi386.h"3132#include "platform/acfreebsd.h"33#include "acconfig.h"34#define ACPI_SYSTEM_XFACE35#include "actypes.h"36#include "actbl.h"3738/*39* Detect ACPI and export information about the ACPI BIOS into the40* environment.41*/4243static ACPI_TABLE_RSDP *biosacpi_find_rsdp(void);44static ACPI_TABLE_RSDP *biosacpi_search_rsdp(char *base, int length);4546#define RSDP_CHECKSUM_LENGTH 204748void49biosacpi_detect(void)50{51ACPI_TABLE_RSDP *rsdp;52char buf[24];53int revision;5455feature_enable(FEATURE_EARLY_ACPI);5657/* locate and validate the RSDP */58if ((rsdp = biosacpi_find_rsdp()) == NULL)59return;6061/*62* Report the RSDP to the kernel. While this can be found with63* a BIOS boot, the RSDP may be elsewhere when booted from UEFI.64*/65sprintf(buf, "0x%08x", VTOP(rsdp));66setenv("acpi.rsdp", buf, 1);67revision = rsdp->Revision;68if (revision == 0)69revision = 1;70sprintf(buf, "%d", revision);71setenv("acpi.revision", buf, 1);72strncpy(buf, rsdp->OemId, sizeof(rsdp->OemId));73buf[sizeof(rsdp->OemId)] = '\0';74setenv("acpi.oem", buf, 1);75sprintf(buf, "0x%08x", rsdp->RsdtPhysicalAddress);76setenv("acpi.rsdt", buf, 1);77if (revision >= 2) {78/* XXX extended checksum? */79sprintf(buf, "0x%016llx", rsdp->XsdtPhysicalAddress);80setenv("acpi.xsdt", buf, 1);81sprintf(buf, "%d", rsdp->Length);82setenv("acpi.xsdt_length", buf, 1);83}84}8586/*87* Find the RSDP in low memory. See section 5.2.2 of the ACPI spec.88*/89static ACPI_TABLE_RSDP *90biosacpi_find_rsdp(void)91{92ACPI_TABLE_RSDP *rsdp;93uint16_t *addr;9495/* EBDA is the 1 KB addressed by the 16 bit pointer at 0x40E. */96addr = (uint16_t *)PTOV(0x40E);97if ((rsdp = biosacpi_search_rsdp((char *)(*addr << 4), 0x400)) != NULL)98return (rsdp);99100/* Check the upper memory BIOS space, 0xe0000 - 0xfffff. */101if ((rsdp = biosacpi_search_rsdp((char *)0xe0000, 0x20000)) != NULL)102return (rsdp);103104return (NULL);105}106107static ACPI_TABLE_RSDP *108biosacpi_search_rsdp(char *base, int length)109{110ACPI_TABLE_RSDP *rsdp;111uint8_t *cp, sum;112int ofs, idx;113114/* search on 16-byte boundaries */115for (ofs = 0; ofs < length; ofs += 16) {116rsdp = (ACPI_TABLE_RSDP *)PTOV(base + ofs);117118/* compare signature, validate checksum */119if (!strncmp(rsdp->Signature, ACPI_SIG_RSDP, strlen(ACPI_SIG_RSDP))) {120cp = (uint8_t *)rsdp;121sum = 0;122for (idx = 0; idx < RSDP_CHECKSUM_LENGTH; idx++)123sum += *(cp + idx);124if (sum != 0)125continue;126return(rsdp);127}128}129return(NULL);130}131132133