hc
2024-02-20 102a0743326a03cd1a1202ceda21e175b7d3575c
kernel/drivers/firmware/dmi_scan.c
....@@ -1,3 +1,4 @@
1
+// SPDX-License-Identifier: GPL-2.0-only
12 #include <linux/types.h>
23 #include <linux/string.h>
34 #include <linux/init.h>
....@@ -5,10 +6,14 @@
56 #include <linux/ctype.h>
67 #include <linux/dmi.h>
78 #include <linux/efi.h>
8
-#include <linux/bootmem.h>
9
+#include <linux/memblock.h>
910 #include <linux/random.h>
1011 #include <asm/dmi.h>
1112 #include <asm/unaligned.h>
13
+
14
+#ifndef SMBIOS_ENTRY_POINT_SCAN_START
15
+#define SMBIOS_ENTRY_POINT_SCAN_START 0xF0000
16
+#endif
1217
1318 struct kobject *dmi_kobj;
1419 EXPORT_SYMBOL_GPL(dmi_kobj);
....@@ -16,7 +21,7 @@
1621 /*
1722 * DMI stands for "Desktop Management Interface". It is part
1823 * of and an antecedent to, SMBIOS, which stands for System
19
- * Management BIOS. See further: http://www.dmtf.org/standards
24
+ * Management BIOS. See further: https://www.dmtf.org/standards
2025 */
2126 static const char dmi_empty_string[] = "";
2227
....@@ -34,6 +39,7 @@
3439 const char *bank;
3540 u64 size; /* bytes */
3641 u16 handle;
42
+ u8 type; /* DDR2, DDR3, DDR4 etc */
3743 } *dmi_memdev;
3844 static int dmi_memdev_nr;
3945
....@@ -178,6 +184,34 @@
178184 return;
179185
180186 dmi_ident[slot] = p;
187
+}
188
+
189
+static void __init dmi_save_release(const struct dmi_header *dm, int slot,
190
+ int index)
191
+{
192
+ const u8 *minor, *major;
193
+ char *s;
194
+
195
+ /* If the table doesn't have the field, let's return */
196
+ if (dmi_ident[slot] || dm->length < index)
197
+ return;
198
+
199
+ minor = (u8 *) dm + index;
200
+ major = (u8 *) dm + index - 1;
201
+
202
+ /* As per the spec, if the system doesn't support this field,
203
+ * the value is FF
204
+ */
205
+ if (*major == 0xFF && *minor == 0xFF)
206
+ return;
207
+
208
+ s = dmi_alloc(8);
209
+ if (!s)
210
+ return;
211
+
212
+ sprintf(s, "%u.%u", *major, *minor);
213
+
214
+ dmi_ident[slot] = s;
181215 }
182216
183217 static void __init dmi_save_uuid(const struct dmi_header *dm, int slot,
....@@ -390,7 +424,7 @@
390424 u64 bytes;
391425 u16 size;
392426
393
- if (dm->type != DMI_ENTRY_MEM_DEVICE || dm->length < 0x12)
427
+ if (dm->type != DMI_ENTRY_MEM_DEVICE || dm->length < 0x13)
394428 return;
395429 if (nr >= dmi_memdev_nr) {
396430 pr_warn(FW_BUG "Too many DIMM entries in SMBIOS table\n");
....@@ -399,6 +433,7 @@
399433 dmi_memdev[nr].handle = get_unaligned(&dm->handle);
400434 dmi_memdev[nr].device = dmi_string(dm, d[0x10]);
401435 dmi_memdev[nr].bank = dmi_string(dm, d[0x11]);
436
+ dmi_memdev[nr].type = d[0x12];
402437
403438 size = get_unaligned((u16 *)&d[0xC]);
404439 if (size == 0)
....@@ -416,11 +451,8 @@
416451 nr++;
417452 }
418453
419
-void __init dmi_memdev_walk(void)
454
+static void __init dmi_memdev_walk(void)
420455 {
421
- if (!dmi_available)
422
- return;
423
-
424456 if (dmi_walk_early(count_mem_devices) == 0 && dmi_memdev_nr) {
425457 dmi_memdev = dmi_alloc(sizeof(*dmi_memdev) * dmi_memdev_nr);
426458 if (dmi_memdev)
....@@ -440,6 +472,8 @@
440472 dmi_save_ident(dm, DMI_BIOS_VENDOR, 4);
441473 dmi_save_ident(dm, DMI_BIOS_VERSION, 5);
442474 dmi_save_ident(dm, DMI_BIOS_DATE, 8);
475
+ dmi_save_release(dm, DMI_BIOS_RELEASE, 21);
476
+ dmi_save_release(dm, DMI_EC_FIRMWARE_RELEASE, 23);
443477 break;
444478 case 1: /* System Information */
445479 dmi_save_ident(dm, DMI_SYS_VENDOR, 4);
....@@ -614,7 +648,7 @@
614648 return 1;
615649 }
616650
617
-void __init dmi_scan_machine(void)
651
+static void __init dmi_scan_machine(void)
618652 {
619653 char __iomem *p, *q;
620654 char buf[32];
....@@ -663,7 +697,7 @@
663697 return;
664698 }
665699 } else if (IS_ENABLED(CONFIG_DMI_SCAN_MACHINE_NON_EFI_FALLBACK)) {
666
- p = dmi_early_remap(0xF0000, 0x10000);
700
+ p = dmi_early_remap(SMBIOS_ENTRY_POINT_SCAN_START, 0x10000);
667701 if (p == NULL)
668702 goto error;
669703
....@@ -769,15 +803,20 @@
769803 subsys_initcall(dmi_init);
770804
771805 /**
772
- * dmi_set_dump_stack_arch_desc - set arch description for dump_stack()
806
+ * dmi_setup - scan and setup DMI system information
773807 *
774
- * Invoke dump_stack_set_arch_desc() with DMI system information so that
775
- * DMI identifiers are printed out on task dumps. Arch boot code should
776
- * call this function after dmi_scan_machine() if it wants to print out DMI
777
- * identifiers on task dumps.
808
+ * Scan the DMI system information. This setups DMI identifiers
809
+ * (dmi_system_id) for printing it out on task dumps and prepares
810
+ * DIMM entry information (dmi_memdev_info) from the SMBIOS table
811
+ * for using this when reporting memory errors.
778812 */
779
-void __init dmi_set_dump_stack_arch_desc(void)
813
+void __init dmi_setup(void)
780814 {
815
+ dmi_scan_machine();
816
+ if (!dmi_available)
817
+ return;
818
+
819
+ dmi_memdev_walk();
781820 dump_stack_set_arch_desc("%s", dmi_ids_string);
782821 }
783822
....@@ -841,7 +880,7 @@
841880 * returns non zero or we hit the end. Callback function is called for
842881 * each successful match. Returns the number of matches.
843882 *
844
- * dmi_scan_machine must be called before this function is called.
883
+ * dmi_setup must be called before this function is called.
845884 */
846885 int dmi_check_system(const struct dmi_system_id *list)
847886 {
....@@ -871,7 +910,7 @@
871910 * Walk the blacklist table until the first match is found. Return the
872911 * pointer to the matching entry or NULL if there's no match.
873912 *
874
- * dmi_scan_machine must be called before this function is called.
913
+ * dmi_setup must be called before this function is called.
875914 */
876915 const struct dmi_system_id *dmi_first_match(const struct dmi_system_id *list)
877916 {
....@@ -1125,3 +1164,40 @@
11251164 return ~0ull;
11261165 }
11271166 EXPORT_SYMBOL_GPL(dmi_memdev_size);
1167
+
1168
+/**
1169
+ * dmi_memdev_type - get the memory type
1170
+ * @handle: DMI structure handle
1171
+ *
1172
+ * Return the DMI memory type of the module in the slot associated with the
1173
+ * given DMI handle, or 0x0 if no such DMI handle exists.
1174
+ */
1175
+u8 dmi_memdev_type(u16 handle)
1176
+{
1177
+ int n;
1178
+
1179
+ if (dmi_memdev) {
1180
+ for (n = 0; n < dmi_memdev_nr; n++) {
1181
+ if (handle == dmi_memdev[n].handle)
1182
+ return dmi_memdev[n].type;
1183
+ }
1184
+ }
1185
+ return 0x0; /* Not a valid value */
1186
+}
1187
+EXPORT_SYMBOL_GPL(dmi_memdev_type);
1188
+
1189
+/**
1190
+ * dmi_memdev_handle - get the DMI handle of a memory slot
1191
+ * @slot: slot number
1192
+ *
1193
+ * Return the DMI handle associated with a given memory slot, or %0xFFFF
1194
+ * if there is no such slot.
1195
+ */
1196
+u16 dmi_memdev_handle(int slot)
1197
+{
1198
+ if (dmi_memdev && slot >= 0 && slot < dmi_memdev_nr)
1199
+ return dmi_memdev[slot].handle;
1200
+
1201
+ return 0xffff; /* Not a valid value */
1202
+}
1203
+EXPORT_SYMBOL_GPL(dmi_memdev_handle);