From eb0e82d87024ee4f7a884d2e9e6a884b3ab29ad1 Mon Sep 17 00:00:00 2001 From: jmcneill Date: Mon, 6 Sep 2010 15:54:26 +0000 Subject: [PATCH] Add support for blacklisting ACPI BIOS implementations by year. By default, don't use ACPI on BIOS which advertise release years <= 2000. This can be changed by setting option ACPI_BLACKLIST_YEAR=0 or by setting acpi_force_load=1. --- sys/arch/x86/x86/platform.c | 58 +++++++++++++++++++++++++++++++++++-- sys/dev/acpi/acpi.c | 11 +++++-- sys/dev/acpi/acpi_quirks.c | 29 +++++++++++++++++-- sys/dev/acpi/acpivar.h | 3 +- sys/dev/acpi/files.acpi | 3 +- 5 files changed, 96 insertions(+), 8 deletions(-) diff --git a/sys/arch/x86/x86/platform.c b/sys/arch/x86/x86/platform.c index 9ce3d9e7483a..db162439b565 100644 --- a/sys/arch/x86/x86/platform.c +++ b/sys/arch/x86/x86/platform.c @@ -1,4 +1,4 @@ -/* $NetBSD: platform.c,v 1.8 2009/02/17 21:15:19 ad Exp $ */ +/* $NetBSD: platform.c,v 1.9 2010/09/06 15:54:27 jmcneill Exp $ */ /*- * Copyright (c) 2007 Jared D. McNeill @@ -29,7 +29,7 @@ #include "isa.h" #include -__KERNEL_RCSID(0, "$NetBSD: platform.c,v 1.8 2009/02/17 21:15:19 ad Exp $"); +__KERNEL_RCSID(0, "$NetBSD: platform.c,v 1.9 2010/09/06 15:54:27 jmcneill Exp $"); #include #include @@ -42,6 +42,7 @@ __KERNEL_RCSID(0, "$NetBSD: platform.c,v 1.8 2009/02/17 21:15:19 ad Exp $"); void platform_init(void); /* XXX */ static void platform_add(struct smbtable *, const char *, int); +static void platform_add_date(struct smbtable *, const char *, int); static void platform_print(void); void @@ -49,6 +50,7 @@ platform_init(void) { struct smbtable smbios; struct smbios_sys *psys; + struct smbios_struct_bios *pbios; struct smbios_slot *pslot; int nisa, nother; @@ -62,6 +64,15 @@ platform_init(void) platform_add(&smbios, "system-serial-number", psys->serial); } + smbios.cookie = 0; + if (smbios_find_table(SMBIOS_TYPE_BIOS, &smbios)) { + pbios = smbios.tblhdr; + + platform_add(&smbios, "firmware-vendor", pbios->vendor); + platform_add(&smbios, "firmware-version", pbios->version); + platform_add_date(&smbios, "firmware-date", pbios->release); + } + smbios.cookie = 0; nisa = 0; nother = 0; @@ -118,3 +129,46 @@ platform_add(struct smbtable *tbl, const char *key, int idx) if (smbios_get_string(tbl, idx, tmpbuf, 128) != NULL) pmf_set_platform(key, tmpbuf); } + +static int +platform_scan_date(char *buf, unsigned int *month, unsigned int *day, + unsigned int *year) +{ + char *p, *s; + + s = buf; + p = strchr(s, '/'); + if (p) *p = '\0'; + *month = strtoul(s, NULL, 10); + if (!p) return 1; + + s = p + 1; + p = strchr(s, '/'); + if (p) *p = '\0'; + *day = strtoul(s, NULL, 10); + if (!p) return 2; + + s = p + 1; + *year = strtoul(s, NULL, 10); + return 3; +} + +static void +platform_add_date(struct smbtable *tbl, const char *key, int idx) +{ + unsigned int month, day, year; + char tmpbuf[128], datestr[9]; + + if (smbios_get_string(tbl, idx, tmpbuf, 128) == NULL) + return; + if (platform_scan_date(tmpbuf, &month, &day, &year) != 3) + return; + if (month == 0 || month > 12 || day == 0 || day > 31) + return; + if (year < 100) + year += 1900; + if (year > 9999) + return; + sprintf(datestr, "%04u%02u%02u", year, month, day); + pmf_set_platform(key, datestr); +} diff --git a/sys/dev/acpi/acpi.c b/sys/dev/acpi/acpi.c index 51c1a935fa03..ca92d35a2633 100644 --- a/sys/dev/acpi/acpi.c +++ b/sys/dev/acpi/acpi.c @@ -1,4 +1,4 @@ -/* $NetBSD: acpi.c,v 1.218 2010/08/24 04:36:02 pgoyette Exp $ */ +/* $NetBSD: acpi.c,v 1.219 2010/09/06 15:54:26 jmcneill Exp $ */ /*- * Copyright (c) 2003, 2007 The NetBSD Foundation, Inc. @@ -100,7 +100,7 @@ */ #include -__KERNEL_RCSID(0, "$NetBSD: acpi.c,v 1.218 2010/08/24 04:36:02 pgoyette Exp $"); +__KERNEL_RCSID(0, "$NetBSD: acpi.c,v 1.219 2010/09/06 15:54:26 jmcneill Exp $"); #include "opt_acpi.h" #include "opt_pcifixup.h" @@ -333,6 +333,13 @@ acpi_probe(void) AcpiTerminate(); return 0; } + if (acpi_force_load == 0 && (acpi_find_quirks() & ACPI_QUIRK_OLDBIOS)) { + aprint_normal("ACPI: BIOS is too old (%s). Set acpi_force_load to use.\n", + pmf_get_platform("firmware-date")); + acpi_unmap_rsdt(rsdt); + AcpiTerminate(); + return 0; + } acpi_unmap_rsdt(rsdt); diff --git a/sys/dev/acpi/acpi_quirks.c b/sys/dev/acpi/acpi_quirks.c index 8131eb1355f2..087824cb759f 100644 --- a/sys/dev/acpi/acpi_quirks.c +++ b/sys/dev/acpi/acpi_quirks.c @@ -1,4 +1,4 @@ -/* $NetBSD: acpi_quirks.c,v 1.17 2010/09/06 14:09:54 jakllsch Exp $ */ +/* $NetBSD: acpi_quirks.c,v 1.18 2010/09/06 15:54:27 jmcneill Exp $ */ /* * Copyright 2002 Wasabi Systems, Inc. @@ -37,7 +37,7 @@ #include -__KERNEL_RCSID(0, "$NetBSD: acpi_quirks.c,v 1.17 2010/09/06 14:09:54 jakllsch Exp $"); +__KERNEL_RCSID(0, "$NetBSD: acpi_quirks.c,v 1.18 2010/09/06 15:54:27 jmcneill Exp $"); #include "opt_acpi.h" @@ -106,6 +106,25 @@ acpi_rev_cmp(uint32_t tabval, uint32_t wanted, int op) return 1; } +#ifdef ACPI_BLACKLIST_YEAR +static int +acpi_find_bios_year(void) +{ + const char *datestr = pmf_get_platform("firmware-date"); + unsigned long date; + + if (datestr == NULL) + return -1; + + date = strtoul(datestr, NULL, 10); + if (date == 0 || date == ULONG_MAX) + return -1; + if (date < 19000000 || date > 99999999) + return -1; + return date / 10000; +} +#endif + /* * Simple function to search the quirk table. Only to be used after * AcpiLoadTables has been successfully called. @@ -116,6 +135,12 @@ acpi_find_quirks(void) int i, nquirks; struct acpi_quirk *aqp; ACPI_TABLE_HEADER fadt, dsdt, xsdt, *hdr; +#ifdef ACPI_BLACKLIST_YEAR + int year = acpi_find_bios_year(); + + if (year != -1 && year <= ACPI_BLACKLIST_YEAR) + return ACPI_QUIRK_OLDBIOS; +#endif nquirks = __arraycount(acpi_quirks); diff --git a/sys/dev/acpi/acpivar.h b/sys/dev/acpi/acpivar.h index 8c9f439f0945..ab4c7eba9aec 100644 --- a/sys/dev/acpi/acpivar.h +++ b/sys/dev/acpi/acpivar.h @@ -1,4 +1,4 @@ -/* $NetBSD: acpivar.h,v 1.61 2010/08/07 20:07:25 jruoho Exp $ */ +/* $NetBSD: acpivar.h,v 1.62 2010/09/06 15:54:27 jmcneill Exp $ */ /* * Copyright 2001 Wasabi Systems, Inc. @@ -328,6 +328,7 @@ struct acpi_quirk { #define ACPI_QUIRK_BADPCI 0x00000002 /* bad PCI hierarchy */ #define ACPI_QUIRK_BADBBN 0x00000004 /* _BBN broken */ #define ACPI_QUIRK_IRQ0 0x00000008 /* bad 0->2 irq override */ +#define ACPI_QUIRK_OLDBIOS 0x00000010 /* BIOS date blacklisted */ int acpi_find_quirks(void); diff --git a/sys/dev/acpi/files.acpi b/sys/dev/acpi/files.acpi index 137731734ef0..37e9c71f18fc 100644 --- a/sys/dev/acpi/files.acpi +++ b/sys/dev/acpi/files.acpi @@ -1,10 +1,11 @@ -# $NetBSD: files.acpi,v 1.79 2010/08/13 16:21:50 jruoho Exp $ +# $NetBSD: files.acpi,v 1.80 2010/09/06 15:54:27 jmcneill Exp $ include "dev/acpi/acpica/files.acpica" defflag opt_acpi.h ACPIVERBOSE ACPI_DEBUG ACPI_ACTIVATE_DEV ACPI_DSDT_OVERRIDE ACPI_SCANPCI ACPI_BREAKPOINT defparam opt_acpi.h ACPI_DSDT_FILE := "\"/dev/null\"" +defparam opt_acpi.h ACPI_BLACKLIST_YEAR = 2000 define acpiapmbus { } define acpinodebus { }