diff --git a/sys/compat/linuxkpi/common/include/linux/mod_devicetable.h b/sys/compat/linuxkpi/common/include/linux/mod_devicetable.h index 5609c6f775e9..441faab6df81 100644 --- a/sys/compat/linuxkpi/common/include/linux/mod_devicetable.h +++ b/sys/compat/linuxkpi/common/include/linux/mod_devicetable.h @@ -1,72 +1,73 @@ /*- * Copyright (c) 2020 The FreeBSD Foundation * * This software was developed by Emmanuel Vadot under sponsorship * from the FreeBSD Foundation. * * 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$ */ #ifndef __LINUXKPI_LINUX_MOD_DEVICETABLE_H__ #define __LINUXKPI_LINUX_MOD_DEVICETABLE_H__ enum dmi_field { DMI_NONE, DMI_BIOS_VENDOR, DMI_BIOS_VERSION, DMI_BIOS_DATE, DMI_SYS_VENDOR, DMI_PRODUCT_NAME, DMI_PRODUCT_VERSION, DMI_PRODUCT_SERIAL, DMI_PRODUCT_UUID, DMI_BOARD_VENDOR, DMI_BOARD_NAME, DMI_BOARD_VERSION, DMI_BOARD_SERIAL, DMI_BOARD_ASSET_TAG, DMI_CHASSIS_VENDOR, DMI_CHASSIS_TYPE, DMI_CHASSIS_VERSION, DMI_CHASSIS_SERIAL, DMI_CHASSIS_ASSET_TAG, DMI_STRING_MAX, }; struct dmi_strmatch { - unsigned char slot; + unsigned char slot : 7; + unsigned char exact_match : 1; char substr[79]; }; struct dmi_system_id { int (*callback)(const struct dmi_system_id *); const char *ident; struct dmi_strmatch matches[4]; void *driver_data; }; #define DMI_MATCH(a, b) { .slot = a, .substr = b } -#define DMI_EXACT_MATCH(a, b) { .slot = a, .substr = b, } +#define DMI_EXACT_MATCH(a, b) { .slot = a, .substr = b, .exact_match = 1 } #endif /* __LINUXKPI_LINUX_MOD_DEVICETABLE_H__ */ diff --git a/sys/compat/linuxkpi/common/src/linux_dmi.c b/sys/compat/linuxkpi/common/src/linux_dmi.c index c0bb9a9f50d6..f5350751a496 100644 --- a/sys/compat/linuxkpi/common/src/linux_dmi.c +++ b/sys/compat/linuxkpi/common/src/linux_dmi.c @@ -1,140 +1,144 @@ /*- * Copyright (c) 2020 The FreeBSD Foundation * * This software was developed by Emmanuel Vadot under sponsorship * from the FreeBSD Foundation. * * 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 #include static char *dmi_data[DMI_STRING_MAX]; static void linux_dmi_preload(void *arg) { dmi_data[DMI_BIOS_VENDOR] = kern_getenv("smbios.bios.vendor"); dmi_data[DMI_BIOS_VERSION] = kern_getenv("smbios.bios.version"); dmi_data[DMI_BIOS_DATE] = kern_getenv("smbios.bios.reldate"); dmi_data[DMI_SYS_VENDOR] = kern_getenv("smbios.system.maker"); dmi_data[DMI_PRODUCT_NAME] = kern_getenv("smbios.system.product"); dmi_data[DMI_PRODUCT_VERSION] = kern_getenv("smbios.system.version"); dmi_data[DMI_PRODUCT_SERIAL] = kern_getenv("smbios.system.serial"); dmi_data[DMI_PRODUCT_UUID] = kern_getenv("smbios.system.uuid"); dmi_data[DMI_BOARD_VENDOR] = kern_getenv("smbios.planar.maker"); dmi_data[DMI_BOARD_NAME] = kern_getenv("smbios.planar.product"); dmi_data[DMI_BOARD_VERSION] = kern_getenv("smbios.planar.version"); dmi_data[DMI_BOARD_SERIAL] = kern_getenv("smbios.planar.serial"); dmi_data[DMI_BOARD_ASSET_TAG] = kern_getenv("smbios.planar.tag"); dmi_data[DMI_CHASSIS_VENDOR] = kern_getenv("smbios.chassis.maker"); dmi_data[DMI_CHASSIS_TYPE] = kern_getenv("smbios.chassis.type"); dmi_data[DMI_CHASSIS_VERSION] = kern_getenv("smbios.chassis.version"); dmi_data[DMI_CHASSIS_SERIAL] = kern_getenv("smbios.chassis.serial"); dmi_data[DMI_CHASSIS_ASSET_TAG] = kern_getenv("smbios.chassis.tag"); } SYSINIT(linux_dmi_preload, SI_SUB_DRIVERS, SI_ORDER_ANY, linux_dmi_preload, NULL); /* Match a system against a field */ bool linux_dmi_match(enum dmi_field f, const char *str) { if (f < DMI_STRING_MAX && dmi_data[f] != NULL && strcmp(dmi_data[f], str) == 0) return(true); return (false); } /* Match a system against the struct, all matches must be ok */ static bool linux_dmi_matches(const struct dmi_system_id *dsi) { int i; for (i = 0; i < nitems(dsi->matches); i++) { if (dsi->matches[i].slot == DMI_NONE) break; - if (dmi_match(dsi->matches[i].slot, - dsi->matches[i].substr) == false) - return (false); + if (dsi->matches[i].exact_match) { + return (dmi_match(dsi->matches[i].slot, + dsi->matches[i].substr)); + } else { + return (strstr(dmi_data[dsi->matches[i].slot], + dsi->matches[i].substr) != NULL); + } } return (true); } /* Return the string matching the field */ const char * linux_dmi_get_system_info(int field) { if (field < DMI_STRING_MAX) return (dmi_data[field]); return (NULL); } /* * Match a system against the structs list * If a match is found return the corresponding structure. */ const struct dmi_system_id * linux_dmi_first_match(const struct dmi_system_id *list) { const struct dmi_system_id *dsi; for (dsi = list; dsi->matches[0].slot != 0; dsi++) { if (linux_dmi_matches(dsi)) return (dsi); } return (NULL); } /* * Match a system against the structs list * For each match call the callback with the corresponding data * Return the number of matches. */ int linux_dmi_check_system(const struct dmi_system_id *sysid) { const struct dmi_system_id *dsi; int matches = 0; for (dsi = sysid; dsi->matches[0].slot != 0; dsi++) { if (linux_dmi_matches(dsi)) { matches++; if (dsi->callback && dsi->callback(dsi)) break; } } return (matches); }