// SPDX-License-Identifier: GPL-2.0-only #include <linux/types.h> #include <linux/string.h> #include <linux/init.h> #include <linux/module.h> #include <linux/ctype.h> #include <linux/dmi.h> #include <linux/efi.h> #include <linux/memblock.h> #include <linux/random.h> #include <asm/dmi.h> #include <asm/unaligned.h> #ifndef SMBIOS_ENTRY_POINT_SCAN_START #define SMBIOS_ENTRY_POINT_SCAN_START … #endif struct kobject *dmi_kobj; EXPORT_SYMBOL_GPL(…); /* * DMI stands for "Desktop Management Interface". It is part * of and an antecedent to, SMBIOS, which stands for System * Management BIOS. See further: https://www.dmtf.org/standards */ static const char dmi_empty_string[] = …; static u32 dmi_ver __initdata; static u32 dmi_len; static u16 dmi_num; static u8 smbios_entry_point[32]; static int smbios_entry_point_size; /* DMI system identification string used during boot */ static char dmi_ids_string[128] __initdata; static struct dmi_memdev_info { … } *dmi_memdev; static int dmi_memdev_nr; static int dmi_memdev_populated_nr __initdata; static const char * __init dmi_string_nosave(const struct dmi_header *dm, u8 s) { … } static const char * __init dmi_string(const struct dmi_header *dm, u8 s) { … } /* * We have to be cautious here. We have seen BIOSes with DMI pointers * pointing to completely the wrong place for example */ static void dmi_decode_table(u8 *buf, void (*decode)(const struct dmi_header *, void *), void *private_data) { … } static phys_addr_t dmi_base; static int __init dmi_walk_early(void (*decode)(const struct dmi_header *, void *)) { … } static int __init dmi_checksum(const u8 *buf, u8 len) { … } static const char *dmi_ident[DMI_STRING_MAX]; static LIST_HEAD(dmi_devices); int dmi_available; EXPORT_SYMBOL_GPL(…); /* * Save a DMI string */ static void __init dmi_save_ident(const struct dmi_header *dm, int slot, int string) { … } static void __init dmi_save_release(const struct dmi_header *dm, int slot, int index) { … } static void __init dmi_save_uuid(const struct dmi_header *dm, int slot, int index) { … } static void __init dmi_save_type(const struct dmi_header *dm, int slot, int index) { … } static void __init dmi_save_one_device(int type, const char *name) { … } static void __init dmi_save_devices(const struct dmi_header *dm) { … } static void __init dmi_save_oem_strings_devices(const struct dmi_header *dm) { … } static void __init dmi_save_ipmi_device(const struct dmi_header *dm) { … } static void __init dmi_save_dev_pciaddr(int instance, int segment, int bus, int devfn, const char *name, int type) { … } static void __init dmi_save_extended_devices(const struct dmi_header *dm) { … } static void __init dmi_save_system_slot(const struct dmi_header *dm) { … } static void __init count_mem_devices(const struct dmi_header *dm, void *v) { … } static void __init save_mem_devices(const struct dmi_header *dm, void *v) { … } static void __init dmi_memdev_walk(void) { … } /* * Process a DMI table entry. Right now all we care about are the BIOS * and machine entries. For 2.5 we should pull the smbus controller info * out of here. */ static void __init dmi_decode(const struct dmi_header *dm, void *dummy) { … } static int __init print_filtered(char *buf, size_t len, const char *info) { … } static void __init dmi_format_ids(char *buf, size_t len) { … } /* * Check for DMI/SMBIOS headers in the system firmware image. Any * SMBIOS header must start 16 bytes before the DMI header, so take a * 32 byte buffer and check for DMI at offset 16 and SMBIOS at offset * 0. If the DMI header is present, set dmi_ver accordingly (SMBIOS * takes precedence) and return 0. Otherwise return 1. */ static int __init dmi_present(const u8 *buf) { … } /* * Check for the SMBIOS 3.0 64-bit entry point signature. Unlike the legacy * 32-bit entry point, there is no embedded DMI header (_DMI_) in here. */ static int __init dmi_smbios3_present(const u8 *buf) { … } static void __init dmi_scan_machine(void) { … } static BIN_ATTR_SIMPLE_ADMIN_RO(smbios_entry_point); static BIN_ATTR_SIMPLE_ADMIN_RO(DMI); static int __init dmi_init(void) { … } subsys_initcall(dmi_init); /** * dmi_setup - scan and setup DMI system information * * Scan the DMI system information. This setups DMI identifiers * (dmi_system_id) for printing it out on task dumps and prepares * DIMM entry information (dmi_memdev_info) from the SMBIOS table * for using this when reporting memory errors. */ void __init dmi_setup(void) { … } /** * dmi_matches - check if dmi_system_id structure matches system DMI data * @dmi: pointer to the dmi_system_id structure to check */ static bool dmi_matches(const struct dmi_system_id *dmi) { … } /** * dmi_is_end_of_table - check for end-of-table marker * @dmi: pointer to the dmi_system_id structure to check */ static bool dmi_is_end_of_table(const struct dmi_system_id *dmi) { … } /** * dmi_check_system - check system DMI data * @list: array of dmi_system_id structures to match against * All non-null elements of the list must match * their slot's (field index's) data (i.e., each * list string must be a substring of the specified * DMI slot's string data) to be considered a * successful match. * * Walk the blacklist table running matching functions until someone * returns non zero or we hit the end. Callback function is called for * each successful match. Returns the number of matches. * * dmi_setup must be called before this function is called. */ int dmi_check_system(const struct dmi_system_id *list) { … } EXPORT_SYMBOL(…); /** * dmi_first_match - find dmi_system_id structure matching system DMI data * @list: array of dmi_system_id structures to match against * All non-null elements of the list must match * their slot's (field index's) data (i.e., each * list string must be a substring of the specified * DMI slot's string data) to be considered a * successful match. * * Walk the blacklist table until the first match is found. Return the * pointer to the matching entry or NULL if there's no match. * * dmi_setup must be called before this function is called. */ const struct dmi_system_id *dmi_first_match(const struct dmi_system_id *list) { … } EXPORT_SYMBOL(…); /** * dmi_get_system_info - return DMI data value * @field: data index (see enum dmi_field) * * Returns one DMI data value, can be used to perform * complex DMI data checks. */ const char *dmi_get_system_info(int field) { … } EXPORT_SYMBOL(…); /** * dmi_name_in_serial - Check if string is in the DMI product serial information * @str: string to check for */ int dmi_name_in_serial(const char *str) { … } /** * dmi_name_in_vendors - Check if string is in the DMI system or board vendor name * @str: Case sensitive Name */ int dmi_name_in_vendors(const char *str) { … } EXPORT_SYMBOL(…); /** * dmi_find_device - find onboard device by type/name * @type: device type or %DMI_DEV_TYPE_ANY to match all device types * @name: device name string or %NULL to match all * @from: previous device found in search, or %NULL for new search. * * Iterates through the list of known onboard devices. If a device is * found with a matching @type and @name, a pointer to its device * structure is returned. Otherwise, %NULL is returned. * A new search is initiated by passing %NULL as the @from argument. * If @from is not %NULL, searches continue from next device. */ const struct dmi_device *dmi_find_device(int type, const char *name, const struct dmi_device *from) { … } EXPORT_SYMBOL(…); /** * dmi_get_date - parse a DMI date * @field: data index (see enum dmi_field) * @yearp: optional out parameter for the year * @monthp: optional out parameter for the month * @dayp: optional out parameter for the day * * The date field is assumed to be in the form resembling * [mm[/dd]]/yy[yy] and the result is stored in the out * parameters any or all of which can be omitted. * * If the field doesn't exist, all out parameters are set to zero * and false is returned. Otherwise, true is returned with any * invalid part of date set to zero. * * On return, year, month and day are guaranteed to be in the * range of [0,9999], [0,12] and [0,31] respectively. */ bool dmi_get_date(int field, int *yearp, int *monthp, int *dayp) { … } EXPORT_SYMBOL(…); /** * dmi_get_bios_year - get a year out of DMI_BIOS_DATE field * * Returns year on success, -ENXIO if DMI is not selected, * or a different negative error code if DMI field is not present * or not parseable. */ int dmi_get_bios_year(void) { … } EXPORT_SYMBOL(…); /** * dmi_walk - Walk the DMI table and get called back for every record * @decode: Callback function * @private_data: Private data to be passed to the callback function * * Returns 0 on success, -ENXIO if DMI is not selected or not present, * or a different negative error code if DMI walking fails. */ int dmi_walk(void (*decode)(const struct dmi_header *, void *), void *private_data) { … } EXPORT_SYMBOL_GPL(…); /** * dmi_match - compare a string to the dmi field (if exists) * @f: DMI field identifier * @str: string to compare the DMI field to * * Returns true if the requested field equals to the str (including NULL). */ bool dmi_match(enum dmi_field f, const char *str) { … } EXPORT_SYMBOL_GPL(…); void dmi_memdev_name(u16 handle, const char **bank, const char **device) { … } EXPORT_SYMBOL_GPL(…); u64 dmi_memdev_size(u16 handle) { … } EXPORT_SYMBOL_GPL(…); /** * dmi_memdev_type - get the memory type * @handle: DMI structure handle * * Return the DMI memory type of the module in the slot associated with the * given DMI handle, or 0x0 if no such DMI handle exists. */ u8 dmi_memdev_type(u16 handle) { … } EXPORT_SYMBOL_GPL(…); /** * dmi_memdev_handle - get the DMI handle of a memory slot * @slot: slot number * * Return the DMI handle associated with a given memory slot, or %0xFFFF * if there is no such slot. */ u16 dmi_memdev_handle(int slot) { … } EXPORT_SYMBOL_GPL(…);