Path: blob/main/sys/compat/linuxkpi/common/src/linux_dmi.c
39586 views
/*-1* Copyright (c) 2020 The FreeBSD Foundation2*3* This software was developed by Emmanuel Vadot under sponsorship4* from the FreeBSD Foundation.5*6* Redistribution and use in source and binary forms, with or without7* modification, are permitted provided that the following conditions8* are met:9* 1. Redistributions of source code must retain the above copyright10* notice, this list of conditions and the following disclaimer.11* 2. Redistributions in binary form must reproduce the above copyright12* notice, this list of conditions and the following disclaimer in the13* documentation and/or other materials provided with the distribution.14*15* THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND16* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE17* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE18* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE19* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL20* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS21* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)22* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT23* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY24* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF25* SUCH DAMAGE.26*/2728#include <sys/param.h>29#include <sys/systm.h>30#include <sys/kernel.h>3132#include <linux/dmi.h>3334static char *dmi_data[DMI_STRING_MAX];3536static void37linux_dmi_preload(void *arg)38{3940dmi_data[DMI_BIOS_VENDOR] = kern_getenv("smbios.bios.vendor");41dmi_data[DMI_BIOS_VERSION] = kern_getenv("smbios.bios.version");42dmi_data[DMI_BIOS_DATE] = kern_getenv("smbios.bios.reldate");43dmi_data[DMI_SYS_VENDOR] = kern_getenv("smbios.system.maker");44dmi_data[DMI_PRODUCT_NAME] = kern_getenv("smbios.system.product");45dmi_data[DMI_PRODUCT_VERSION] = kern_getenv("smbios.system.version");46dmi_data[DMI_PRODUCT_SERIAL] = kern_getenv("smbios.system.serial");47dmi_data[DMI_PRODUCT_UUID] = kern_getenv("smbios.system.uuid");48dmi_data[DMI_BOARD_VENDOR] = kern_getenv("smbios.planar.maker");49dmi_data[DMI_BOARD_NAME] = kern_getenv("smbios.planar.product");50dmi_data[DMI_BOARD_VERSION] = kern_getenv("smbios.planar.version");51dmi_data[DMI_BOARD_SERIAL] = kern_getenv("smbios.planar.serial");52dmi_data[DMI_BOARD_ASSET_TAG] = kern_getenv("smbios.planar.tag");53dmi_data[DMI_CHASSIS_VENDOR] = kern_getenv("smbios.chassis.maker");54dmi_data[DMI_CHASSIS_TYPE] = kern_getenv("smbios.chassis.type");55dmi_data[DMI_CHASSIS_VERSION] = kern_getenv("smbios.chassis.version");56dmi_data[DMI_CHASSIS_SERIAL] = kern_getenv("smbios.chassis.serial");57dmi_data[DMI_CHASSIS_ASSET_TAG] = kern_getenv("smbios.chassis.tag");58}59SYSINIT(linux_dmi_preload, SI_SUB_DRIVERS, SI_ORDER_ANY, linux_dmi_preload, NULL);6061/* Match a system against a field */62bool63linux_dmi_match(enum dmi_field f, const char *str)64{6566if (f < DMI_STRING_MAX &&67dmi_data[f] != NULL &&68strcmp(dmi_data[f], str) == 0)69return(true);70return (false);71}7273/* Match a system against the struct, all matches must be ok */74static bool75linux_dmi_matches(const struct dmi_system_id *dsi)76{77enum dmi_field slot;78int i;7980for (i = 0; i < nitems(dsi->matches); i++) {81slot = dsi->matches[i].slot;82if (slot == DMI_NONE)83break;84if (slot >= DMI_STRING_MAX ||85dmi_data[slot] == NULL)86return (false);87if (dsi->matches[i].exact_match) {88if (dmi_match(slot, dsi->matches[i].substr))89continue;90} else if (strstr(dmi_data[slot],91dsi->matches[i].substr) != NULL) {92continue;93}94return (false);95}96return (true);97}9899/* Return the string matching the field */100const char *101linux_dmi_get_system_info(int field)102{103104if (field < DMI_STRING_MAX)105return (dmi_data[field]);106return (NULL);107}108109/*110* Match a system against the structs list111* If a match is found return the corresponding structure.112*/113const struct dmi_system_id *114linux_dmi_first_match(const struct dmi_system_id *list)115{116const struct dmi_system_id *dsi;117118for (dsi = list; dsi->matches[0].slot != 0; dsi++) {119if (linux_dmi_matches(dsi))120return (dsi);121}122123return (NULL);124}125126/*127* Match a system against the structs list128* For each match call the callback with the corresponding data129* Return the number of matches.130*/131int132linux_dmi_check_system(const struct dmi_system_id *sysid)133{134const struct dmi_system_id *dsi;135int matches = 0;136137for (dsi = sysid; dsi->matches[0].slot != 0; dsi++) {138if (linux_dmi_matches(dsi)) {139matches++;140if (dsi->callback && dsi->callback(dsi))141break;142}143}144145return (matches);146}147148149