From a91b408a36e5310d3790b559e4ac8af7a64dd8db Mon Sep 17 00:00:00 2001 From: Emmanuel Vadot Date: Fri, 2 Oct 2020 18:28:00 +0000 Subject: [PATCH] linuxkpi: Add dmi_* function dmi function are used to get smbios values. The DRM subsystem and drivers use it to enabled (or not) quirks. Reviewed by: hselasky Sponsored by: The FreeBSD Foundation Differential Revision: https://reviews.freebsd.org/D26046 --- .../linuxkpi/common/include/linux/dmi.h | 46 ++++++ sys/compat/linuxkpi/common/include/linux/fs.h | 2 +- .../common/include/linux/mod_devicetable.h | 72 +++++++++ sys/compat/linuxkpi/common/src/linux_dmi.c | 140 ++++++++++++++++++ sys/conf/files | 2 + sys/modules/linuxkpi/Makefile | 1 + 6 files changed, 262 insertions(+), 1 deletion(-) create mode 100644 sys/compat/linuxkpi/common/include/linux/dmi.h create mode 100644 sys/compat/linuxkpi/common/include/linux/mod_devicetable.h create mode 100644 sys/compat/linuxkpi/common/src/linux_dmi.c diff --git a/sys/compat/linuxkpi/common/include/linux/dmi.h b/sys/compat/linuxkpi/common/include/linux/dmi.h new file mode 100644 index 000000000000..b921cc906917 --- /dev/null +++ b/sys/compat/linuxkpi/common/include/linux/dmi.h @@ -0,0 +1,46 @@ +/*- + * 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 __LINUX_DMI_H__ +#define __LINUX_DMI_H__ + +#include + +int linux_dmi_check_system(const struct dmi_system_id *); +bool linux_dmi_match(enum dmi_field, const char *); +const struct dmi_system_id *linux_dmi_first_match(const struct dmi_system_id *); +const char *linux_dmi_get_system_info(int); + +#define dmi_check_system(sysid) linux_dmi_check_system(sysid) +#define dmi_match(f, str) linux_dmi_match(f, str) +#define dmi_first_match(sysid) linux_dmi_first_match(sysid) +#define dmi_get_system_info(sysid) linux_dmi_get_system_info(sysid) + +#endif /* __LINUX_DMI_H__ */ diff --git a/sys/compat/linuxkpi/common/include/linux/fs.h b/sys/compat/linuxkpi/common/include/linux/fs.h index 66a1607b99e2..38911c276216 100644 --- a/sys/compat/linuxkpi/common/include/linux/fs.h +++ b/sys/compat/linuxkpi/common/include/linux/fs.h @@ -180,7 +180,7 @@ struct file_operations { #define FMODE_READ FREAD #define FMODE_WRITE FWRITE #define FMODE_EXEC FEXEC - +#define FMODE_UNSIGNED_OFFSET 0x2000 int __register_chrdev(unsigned int major, unsigned int baseminor, unsigned int count, const char *name, const struct file_operations *fops); diff --git a/sys/compat/linuxkpi/common/include/linux/mod_devicetable.h b/sys/compat/linuxkpi/common/include/linux/mod_devicetable.h new file mode 100644 index 000000000000..f2a913bc6346 --- /dev/null +++ b/sys/compat/linuxkpi/common/include/linux/mod_devicetable.h @@ -0,0 +1,72 @@ +/*- + * 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 __LINUX_MOD_DEVICETABLE_H__ +#define __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; + 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, } + +#endif /* __LINUX_MOD_DEVICETABLE_H__ */ diff --git a/sys/compat/linuxkpi/common/src/linux_dmi.c b/sys/compat/linuxkpi/common/src/linux_dmi.c new file mode 100644 index 000000000000..c0bb9a9f50d6 --- /dev/null +++ b/sys/compat/linuxkpi/common/src/linux_dmi.c @@ -0,0 +1,140 @@ +/*- + * 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); + } + + 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); +} diff --git a/sys/conf/files b/sys/conf/files index 37ca6f6ded3c..e3c142441653 100644 --- a/sys/conf/files +++ b/sys/conf/files @@ -4510,6 +4510,8 @@ compat/linuxkpi/common/src/linux_compat.c optional compat_linuxkpi \ compile-with "${LINUXKPI_C}" compat/linuxkpi/common/src/linux_current.c optional compat_linuxkpi \ compile-with "${LINUXKPI_C}" +compat/linuxkpi/common/src/linux_dmi.c optional compat_linuxkpi \ + compile-with "${LINUXKPI_C}" compat/linuxkpi/common/src/linux_hrtimer.c optional compat_linuxkpi \ compile-with "${LINUXKPI_C}" compat/linuxkpi/common/src/linux_kthread.c optional compat_linuxkpi \ diff --git a/sys/modules/linuxkpi/Makefile b/sys/modules/linuxkpi/Makefile index a47d2336b8c3..97e18f45eb12 100644 --- a/sys/modules/linuxkpi/Makefile +++ b/sys/modules/linuxkpi/Makefile @@ -4,6 +4,7 @@ KMOD= linuxkpi SRCS= linux_compat.c \ linux_current.c \ + linux_dmi.c \ linux_hrtimer.c \ linux_idr.c \ linux_kmod.c \