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