1 /*
2 * Copyright 2020-2023 The OSHI Project Contributors
3 * SPDX-License-Identifier: MIT
4 */
5 package oshi.driver.linux;
6
7 import oshi.annotation.concurrent.ThreadSafe;
8 import oshi.util.ExecutingCommand;
9 import oshi.util.ParseUtil;
10 import oshi.util.UserGroupInfo;
11 import oshi.util.tuples.Pair;
12
13 /**
14 * Utility to read info from {@code dmidecode}
15 */
16 @ThreadSafe
17 public final class Dmidecode {
18
19 private Dmidecode() {
20 }
21
22 // $ sudo dmidecode -t bios
23 // # dmidecode 2.11
24 // SMBIOS 2.4 present.
25 //
26 // Handle 0x0000, DMI type 0, 24 bytes
27 // BIOS Information
28 // Vendor: Phoenix Technologies LTD
29 // Version: 6.00
30 // Release Date: 07/02/2015
31 // Address: 0xEA5E0
32 // Runtime Size: 88608 bytes
33 // ROM Size: 64 kB
34 // Characteristics:
35 // ISA is supported
36 // PCI is supported
37 // PC Card (PCMCIA) is supported
38 // PNP is supported
39 // APM is supported
40 // BIOS is upgradeable
41 // BIOS shadowing is allowed
42 // ESCD support is available
43 // Boot from CD is supported
44 // Selectable boot is supported
45 // EDD is supported
46 // Print screen service is supported (int 5h)
47 // 8042 keyboard services are supported (int 9h)
48 // Serial services are supported (int 14h)
49 // Printer services are supported (int 17h)
50 // CGA/mono video services are supported (int 10h)
51 // ACPI is supported
52 // Smart battery is supported
53 // BIOS boot specification is supported
54 // Function key-initiated network boot is supported
55 // Targeted content distribution is supported
56 // BIOS Revision: 4.6
57 // Firmware Revision: 0.0
58
59 /**
60 * Query the serial number from dmidecode
61 *
62 * @return The serial number if available, null otherwise
63 */
64 public static String querySerialNumber() {
65 // If root privileges this will work
66 if (UserGroupInfo.isElevated()) {
67 String marker = "Serial Number:";
68 for (String checkLine : ExecutingCommand.runNative("dmidecode -t system")) {
69 if (checkLine.contains(marker)) {
70 return checkLine.split(marker)[1].trim();
71 }
72 }
73 }
74 return null;
75 }
76
77 /**
78 * Query the UUID from dmidecode
79 *
80 * @return The UUID if available, null otherwise
81 */
82 public static String queryUUID() {
83 // If root privileges this will work
84 if (UserGroupInfo.isElevated()) {
85 String marker = "UUID:";
86 for (String checkLine : ExecutingCommand.runNative("dmidecode -t system")) {
87 if (checkLine.contains(marker)) {
88 return checkLine.split(marker)[1].trim();
89 }
90 }
91 }
92 return null;
93 }
94
95 /**
96 * Query the name and revision from dmidecode
97 *
98 * @return The a pair containing the name and revision if available, null values in the pair otherwise
99 */
100 public static Pair<String, String> queryBiosNameRev() {
101 String biosName = null;
102 String revision = null;
103
104 // Requires root, may not return anything
105 if (UserGroupInfo.isElevated()) {
106 final String biosMarker = "SMBIOS";
107 final String revMarker = "Bios Revision:";
108
109 for (final String checkLine : ExecutingCommand.runNative("dmidecode -t bios")) {
110 if (checkLine.contains(biosMarker)) {
111 String[] biosArr = ParseUtil.whitespaces.split(checkLine);
112 if (biosArr.length >= 2) {
113 biosName = biosArr[0] + " " + biosArr[1];
114 }
115 }
116 if (checkLine.contains(revMarker)) {
117 revision = checkLine.split(revMarker)[1].trim();
118 // SMBIOS should be first line so if we're here we are done iterating
119 break;
120 }
121 }
122 }
123 return new Pair<>(biosName, revision);
124 }
125 }