biosacpi.c revision 129195
1/*- 2 * Copyright (c) 2001 Michael Smith <msmith@freebsd.org> 3 * All rights reserved. 4 * 5 * Redistribution and use in source and binary forms, with or without 6 * modification, are permitted provided that the following conditions 7 * are met: 8 * 1. Redistributions of source code must retain the above copyright 9 * notice, this list of conditions and the following disclaimer. 10 * 2. Redistributions in binary form must reproduce the above copyright 11 * notice, this list of conditions and the following disclaimer in the 12 * documentation and/or other materials provided with the distribution. 13 * 14 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 15 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 16 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 17 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 18 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 19 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 20 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 21 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 22 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 23 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 24 * SUCH DAMAGE. 25 */ 26 27#include <sys/cdefs.h> 28__FBSDID("$FreeBSD: head/sys/boot/i386/libi386/biosacpi.c 129195 2004-05-14 01:29:21Z jdp $"); 29 30#include <stand.h> 31#include <machine/stdarg.h> 32#include <bootstrap.h> 33 34#include "acfreebsd.h" 35#include "acconfig.h" 36#define ACPI_SYSTEM_XFACE 37#include "actypes.h" 38#include "actbl.h" 39 40/* 41 * Detect ACPI and export information about the APCI BIOS into the 42 * environment. 43 */ 44 45static RSDP_DESCRIPTOR *biosacpi_find_rsdp(void); 46static RSDP_DESCRIPTOR *biosacpi_search_rsdp(char *base, int length); 47 48#define RSDP_CHECKSUM_LENGTH 20 49 50void 51biosacpi_detect(void) 52{ 53 RSDP_DESCRIPTOR *rsdp; 54 char buf[16]; 55 int revision; 56 57 /* XXX check the BIOS datestamp */ 58 59 /* locate and validate the RSDP */ 60 if ((rsdp = biosacpi_find_rsdp()) == NULL) 61 return; 62 63 /* export values from the RSDP */ 64 revision = rsdp->Revision; 65 if (revision == 0) 66 revision = 1; 67 sprintf(buf, "%d", revision); 68 setenv("hint.acpi.0.revision", buf, 1); 69 strncpy(buf, rsdp->OemId, sizeof(rsdp->OemId)); 70 buf[sizeof(rsdp->OemId)] = '\0'; 71 setenv("hint.acpi.0.oem", buf, 1); 72 sprintf(buf, "0x%08x", rsdp->RsdtPhysicalAddress); 73 setenv("hint.acpi.0.rsdt", buf, 1); 74 if (revision >= 2) { 75 /* XXX extended checksum? */ 76 sprintf(buf, "0x%016llx", rsdp->XsdtPhysicalAddress); 77 setenv("hint.acpi.0.xsdt", buf, 1); 78 sprintf(buf, "%d", rsdp->Length); 79 setenv("hint.acpi.0.xsdt_length", buf, 1); 80 } 81 /* XXX other tables? */ 82 83 setenv("acpi_load", "YES", 1); 84} 85 86/* 87 * Find the RSDP in low memory. 88 */ 89static RSDP_DESCRIPTOR * 90biosacpi_find_rsdp(void) 91{ 92 RSDP_DESCRIPTOR *rsdp; 93 94 /* search the EBDA */ 95 if ((rsdp = biosacpi_search_rsdp((char *)0, 0x400)) != NULL) 96 return(rsdp); 97 98 /* search the BIOS space */ 99 if ((rsdp = biosacpi_search_rsdp((char *)0xe0000, 0x20000)) != NULL) 100 return(rsdp); 101 102 return(NULL); 103} 104 105static RSDP_DESCRIPTOR * 106biosacpi_search_rsdp(char *base, int length) 107{ 108 RSDP_DESCRIPTOR *rsdp; 109 u_int8_t *cp, sum; 110 int ofs, idx; 111 112 /* search on 16-byte boundaries */ 113 for (ofs = 0; ofs < length; ofs += 16) { 114 rsdp = (RSDP_DESCRIPTOR *)(base + ofs); 115 116 /* compare signature, validate checksum */ 117 if (!strncmp(rsdp->Signature, RSDP_SIG, strlen(RSDP_SIG))) { 118 cp = (u_int8_t *)rsdp; 119 sum = 0; 120 for (idx = 0; idx < RSDP_CHECKSUM_LENGTH; idx++) 121 sum += *(cp + idx); 122 if (sum != 0) { 123 printf("acpi: bad RSDP checksum (%d)\n", sum); 124 continue; 125 } 126 return(rsdp); 127 } 128 } 129 return(NULL); 130} 131