1/* $NetBSD: acpi_quirks.c,v 1.22 2020/12/06 11:38:28 jmcneill Exp $ */ 2 3/*- 4 * Copyright (c) 2011 The NetBSD Foundation, Inc. 5 * All rights reserved. 6 * 7 * Redistribution and use in source and binary forms, with or without 8 * modification, are permitted provided that the following conditions 9 * are met: 10 * 11 * 1. Redistributions of source code must retain the above copyright 12 * notice, this list of conditions and the following disclaimer. 13 * 2. Redistributions in binary form must reproduce the above copyright 14 * notice, this list of conditions and the following disclaimer in the 15 * documentation and/or other materials provided with the distribution. 16 * 17 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 18 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 19 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 20 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 21 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 22 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 23 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 24 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 25 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 26 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 27 * SUCH DAMAGE. 28 */ 29 30/* 31 * Copyright 2002 Wasabi Systems, Inc. 32 * All rights reserved. 33 * 34 * Written by Frank van der Linden for Wasabi Systems, Inc. 35 * 36 * Redistribution and use in source and binary forms, with or without 37 * modification, are permitted provided that the following conditions 38 * are met: 39 * 1. Redistributions of source code must retain the above copyright 40 * notice, this list of conditions and the following disclaimer. 41 * 2. Redistributions in binary form must reproduce the above copyright 42 * notice, this list of conditions and the following disclaimer in the 43 * documentation and/or other materials provided with the distribution. 44 * 3. All advertising materials mentioning features or use of this software 45 * must display the following acknowledgement: 46 * This product includes software developed for the NetBSD Project by 47 * Wasabi Systems, Inc. 48 * 4. The name of Wasabi Systems, Inc. may not be used to endorse 49 * or promote products derived from this software without specific prior 50 * written permission. 51 * 52 * THIS SOFTWARE IS PROVIDED BY WASABI SYSTEMS, INC. ``AS IS'' AND 53 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED 54 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 55 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL WASABI SYSTEMS, INC 56 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 57 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 58 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 59 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 60 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 61 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 62 * POSSIBILITY OF SUCH DAMAGE. 63 */ 64 65#include <sys/cdefs.h> 66 67__KERNEL_RCSID(0, "$NetBSD: acpi_quirks.c,v 1.22 2020/12/06 11:38:28 jmcneill Exp $"); 68 69#include "opt_acpi.h" 70 71#include <sys/param.h> 72 73#include <dev/acpi/acpireg.h> 74#include <dev/acpi/acpivar.h> 75 76#define _COMPONENT ACPI_UTILITIES 77ACPI_MODULE_NAME ("acpi_quirks") 78 79#define AQ_GT 0 /* > */ 80#define AQ_LT 1 /* < */ 81#define AQ_GTE 2 /* >= */ 82#define AQ_LTE 3 /* <= */ 83#define AQ_EQ 4 /* == */ 84 85static int acpi_quirks_revcmp(uint32_t, uint32_t, int); 86 87static const struct acpi_quirk acpi_quirks[] = { 88 89 { ACPI_SIG_FADT, "ASUS ", 0x30303031, AQ_LTE, "CUV4X-D ", 90 ACPI_QUIRK_BROKEN }, 91 92 { ACPI_SIG_FADT, "PTLTD ", 0x06040000, AQ_LTE, " FACP ", 93 ACPI_QUIRK_BROKEN }, 94 95 { ACPI_SIG_FADT, "NVIDIA", 0x06040000, AQ_EQ, "CK8 ", 96 ACPI_QUIRK_IRQ0 }, 97 98 { ACPI_SIG_FADT, "HP ", 0x06040012, AQ_LTE, "HWPC20F ", 99 ACPI_QUIRK_BROKEN }, 100}; 101 102static int 103acpi_quirks_revcmp(uint32_t tabval, uint32_t wanted, int op) 104{ 105 106 switch (op) { 107 108 case AQ_GT: 109 return (tabval > wanted) ? 0 : 1; 110 111 case AQ_LT: 112 return (tabval < wanted) ? 0 : 1; 113 114 case AQ_LTE: 115 return (tabval <= wanted) ? 0 : 1; 116 117 case AQ_GTE: 118 return (tabval >= wanted) ? 0 : 1; 119 120 case AQ_EQ: 121 return (tabval == wanted) ? 0 : 1; 122 123 default: 124 return 1; 125 } 126} 127 128#ifdef ACPI_BLACKLIST_YEAR 129static int 130acpi_quirks_bios_year(void) 131{ 132 const char *datestr = pmf_get_platform("bios-date"); 133 unsigned long date; 134 135 if (datestr == NULL) 136 return -1; 137 138 date = strtoul(datestr, NULL, 10); 139 if (date == 0 || date == ULONG_MAX) 140 return -1; 141 if (date < 19000000 || date > 99999999) 142 return -1; 143 return date / 10000; 144} 145#endif 146 147/* 148 * Simple function to search the quirk table. Only to be 149 * used after AcpiLoadTables() has been successfully called. 150 */ 151int 152acpi_find_quirks(void) 153{ 154 ACPI_TABLE_HEADER fadt, dsdt, xsdt, *hdr; 155 const struct acpi_quirk *aq; 156 ACPI_STATUS rv; 157 size_t i, len; 158 159#ifdef ACPI_BLACKLIST_YEAR 160 int year = acpi_quirks_bios_year(); 161 162 if (year != -1 && year <= ACPI_BLACKLIST_YEAR) 163 return ACPI_QUIRK_OLDBIOS; 164#endif 165 166 rv = AcpiGetTableHeader(ACPI_SIG_FADT, 0, &fadt); 167 168 if (ACPI_FAILURE(rv)) 169 (void)memset(&fadt, 0, sizeof(fadt)); 170 171 rv = AcpiGetTableHeader(ACPI_SIG_DSDT, 0, &dsdt); 172 173 if (ACPI_FAILURE(rv)) 174 (void)memset(&dsdt, 0, sizeof(dsdt)); 175 176 rv = AcpiGetTableHeader(ACPI_SIG_XSDT, 0, &xsdt); 177 178 if (ACPI_FAILURE(rv)) 179 (void)memset(&xsdt, 0, sizeof(xsdt)); 180 181 for (i = 0; i < __arraycount(acpi_quirks); i++) { 182 183 aq = &acpi_quirks[i]; 184 185 if (strncmp(aq->aq_tabletype, ACPI_SIG_DSDT, 4) == 0) 186 hdr = &dsdt; 187 else if (strncmp(aq->aq_tabletype, ACPI_SIG_XSDT, 4) == 0) 188 hdr = &xsdt; 189 else if (strncmp(aq->aq_tabletype, ACPI_SIG_FADT, 4) == 0) 190 hdr = &fadt; 191 else { 192 continue; 193 } 194 195 len = strlen(aq->aq_oemid); 196 197 if (strncmp(aq->aq_oemid, hdr->OemId, len) != 0) 198 continue; 199 200 if (acpi_quirks_revcmp(aq->aq_oemrev, 201 hdr->OemRevision, aq->aq_cmpop) != 0) 202 continue; 203 204 len = strlen(aq->aq_tabid); 205 206 if (strncmp(aq->aq_tabid, hdr->OemTableId, len) != 0) 207 continue; 208 209 return aq->aq_quirks; 210 } 211 212 return 0; 213} 214