From ad41f9a8f7bb84dcc787d930122cce22035d8589 Mon Sep 17 00:00:00 2001 From: Mike Smith Date: Thu, 30 Aug 2001 00:42:12 +0000 Subject: [PATCH] Teach the loader how to find the system ACPI information, and autoload the ACPI module if the system apperars to be ACPI compliant. This is an initial cut; the load should really be done by Forth support code, and we should check both the BIOS build date and a blacklist. --- sys/boot/i386/libi386/Makefile | 3 +- sys/boot/i386/libi386/biosacpi.c | 126 ++++++++++++++++++++++++++++ sys/boot/i386/libi386/i386_module.c | 11 +++ sys/boot/i386/libi386/libi386.h | 2 + sys/boot/i386/loader/main.c | 3 + 5 files changed, 144 insertions(+), 1 deletion(-) create mode 100644 sys/boot/i386/libi386/biosacpi.c diff --git a/sys/boot/i386/libi386/Makefile b/sys/boot/i386/libi386/Makefile index 2c684ed4b8d2..6bcf8dcc4410 100644 --- a/sys/boot/i386/libi386/Makefile +++ b/sys/boot/i386/libi386/Makefile @@ -6,12 +6,13 @@ NOPROFILE= INTERNALLIB= true INTERNALSTATICLIB= true -SRCS= aout_freebsd.c biosdisk.c biosmem.c biospnp.c biospci.c \ +SRCS= aout_freebsd.c biosacpi.c biosdisk.c biosmem.c biospnp.c biospci.c \ bootinfo.c comconsole.c devicename.c elf_freebsd.c gatea20.c \ i386_copy.c i386_module.c nullconsole.c pxe.c pxetramp.s \ time.c vidconsole.c CFLAGS+= -I${.CURDIR}/../../common -I${.CURDIR}/../btx/lib \ + -I${.CURDIR}/../../../contrib/dev/acpica \ -I${.CURDIR}/../../.. -I. BOOT_COMCONSOLE_PORT?= 0x3f8 diff --git a/sys/boot/i386/libi386/biosacpi.c b/sys/boot/i386/libi386/biosacpi.c new file mode 100644 index 000000000000..343f407c8fbf --- /dev/null +++ b/sys/boot/i386/libi386/biosacpi.c @@ -0,0 +1,126 @@ +/*- + * Copyright (c) 2001 Michael Smith + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * $FreeBSD$ + */ + +#include +#include +#include + +#define COMPILER_DEPENDENT_UINT64 long long +#include "actypes.h" +#include "actbl.h" + +/* + * Detect ACPI and export information about the APCI BIOS into the + * environment. + */ + +static RSDP_DESCRIPTOR *biosacpi_find_rsdp(void); +static RSDP_DESCRIPTOR *biosacpi_search_rsdp(char *base, int length); + +#define RSDP_CHECKSUM_LENGTH 20 + +void +biosacpi_detect(void) +{ + RSDP_DESCRIPTOR *rsdp; + char buf[16]; + int revision; + + /* XXX check the BIOS datestamp */ + + /* locate and validate the RSDP */ + if ((rsdp = biosacpi_find_rsdp()) == NULL) + return; + + /* export values from the RSDP */ + revision = rsdp->Revision; + if (revision == 0) + revision = 1; + sprintf(buf, "%d", revision); + setenv("hint.acpi.0.revision", buf, 1); + sprintf(buf, "%6s", rsdp->OemId); + setenv("hint.acpi.0.oem", buf, 1); + sprintf(buf, "0x%08x", rsdp->RsdtPhysicalAddress); + setenv("hint.acpi.0.rsdt", buf, 1); + if (revision >= 2) { + /* XXX extended checksum? */ + sprintf(buf, "0x%016llx", rsdp->XsdtPhysicalAddress); + setenv("hint.acpi.0.xsdt", buf, 1); + sprintf(buf, "%d", rsdp->Length); + setenv("hint.acpi.0.xsdt_length", buf, 1); + } + /* XXX other tables? */ + + setenv("acpi_load", "YES", 1); +} + +/* + * Find the RSDP in low memory. + */ +static RSDP_DESCRIPTOR * +biosacpi_find_rsdp(void) +{ + RSDP_DESCRIPTOR *rsdp; + + /* search the EBDA */ + if ((rsdp = biosacpi_search_rsdp((char *)0, 0x400)) != NULL) + return(rsdp); + + /* search the BIOS space */ + if ((rsdp = biosacpi_search_rsdp((char *)0xe0000, 0x20000)) != NULL) + return(rsdp); + + return(NULL); +} + +static RSDP_DESCRIPTOR * +biosacpi_search_rsdp(char *base, int length) +{ + RSDP_DESCRIPTOR *rsdp; + u_int8_t *cp, sum; + int ofs, idx; + + /* search on 16-byte boundaries */ + for (ofs = 0; ofs < length; ofs += 16) { + rsdp = (RSDP_DESCRIPTOR *)(base + ofs); + + /* compare signature, validate checksum */ + if (!strncmp(rsdp->Signature, RSDP_SIG, strlen(RSDP_SIG))) { + cp = (u_int8_t *)rsdp; + sum = 0; + for (idx = 0; idx < RSDP_CHECKSUM_LENGTH; idx++) + sum += *(cp + idx); + if (sum != 0) { + printf("acpi: bad RSDP checksum (%d)\n", sum); + continue; + } + return(rsdp); + } + } + return(NULL); +} diff --git a/sys/boot/i386/libi386/i386_module.c b/sys/boot/i386/libi386/i386_module.c index 7040e9fcd300..cafd22b97e06 100644 --- a/sys/boot/i386/libi386/i386_module.c +++ b/sys/boot/i386/libi386/i386_module.c @@ -43,6 +43,17 @@ int i386_autoload(void) { + int error; + /* XXX use PnP to locate stuff here */ + + /* autoload ACPI support */ + /* XXX should be in 4th keyed off acpi_load */ + if ((getenv("acpi_load") && !getenv("hint.acpi.0.disable"))) { + error = mod_load("acpi", 0, NULL); + if (error != 0) + printf("ACPI autoload failed - %s\n", strerror(error)); + } + return(0); } diff --git a/sys/boot/i386/libi386/libi386.h b/sys/boot/i386/libi386/libi386.h index 3db8f062f074..3f83bdcfd9a7 100644 --- a/sys/boot/i386/libi386/libi386.h +++ b/sys/boot/i386/libi386/libi386.h @@ -79,6 +79,8 @@ extern u_int32_t bios_basemem; /* base memory in bytes */ extern u_int32_t bios_extmem; /* extended memory in bytes */ extern vm_offset_t memtop; +void biosacpi_detect(); + void gateA20(void); int i386_autoload(void); diff --git a/sys/boot/i386/loader/main.c b/sys/boot/i386/loader/main.c index b943edbef4b0..8ce0c9d83bba 100644 --- a/sys/boot/i386/loader/main.c +++ b/sys/boot/i386/loader/main.c @@ -125,6 +125,9 @@ main(void) (devsw[i]->dv_init)(); printf("BIOS %dkB/%dkB available memory\n", bios_basemem / 1024, bios_extmem / 1024); + /* detect ACPI for future reference */ + biosacpi_detect(); + printf("\n"); printf("%s, Revision %s\n", bootprog_name, bootprog_rev); printf("(%s, %s)\n", bootprog_maker, bootprog_date);