View Javadoc
1   /*
2    * Copyright 2016-2023 The OSHI Project Contributors
3    * SPDX-License-Identifier: MIT
4    */
5   package oshi.hardware.platform.unix.solaris;
6   
7   import static oshi.hardware.platform.unix.solaris.SolarisComputerSystem.SmbType.SMB_TYPE_BIOS;
8   import static oshi.hardware.platform.unix.solaris.SolarisComputerSystem.SmbType.SMB_TYPE_SYSTEM;
9   import static oshi.hardware.platform.unix.solaris.SolarisComputerSystem.SmbType.SMB_TYPE_BASEBOARD;
10  import static oshi.util.Memoizer.memoize;
11  import static oshi.util.ParseUtil.getValueOrUnknown;
12  
13  import java.util.EnumMap;
14  import java.util.HashMap;
15  import java.util.Map;
16  import java.util.function.Supplier;
17  
18  import oshi.annotation.concurrent.Immutable;
19  import oshi.hardware.Baseboard;
20  import oshi.hardware.Firmware;
21  import oshi.hardware.common.AbstractComputerSystem;
22  import oshi.hardware.platform.unix.UnixBaseboard;
23  import oshi.util.ExecutingCommand;
24  import oshi.util.ParseUtil;
25  import oshi.util.Util;
26  
27  /**
28   * Hardware data obtained from smbios.
29   */
30  @Immutable
31  final class SolarisComputerSystem extends AbstractComputerSystem {
32      public enum SmbType {
33          /**
34           * BIOS
35           */
36          SMB_TYPE_BIOS,
37          /**
38           * System
39           */
40          SMB_TYPE_SYSTEM,
41          /**
42           * Baseboard
43           */
44          SMB_TYPE_BASEBOARD
45      }
46  
47      private final Supplier<SmbiosStrings> smbiosStrings = memoize(SolarisComputerSystem::readSmbios);
48  
49      @Override
50      public String getManufacturer() {
51          return smbiosStrings.get().manufacturer;
52      }
53  
54      @Override
55      public String getModel() {
56          return smbiosStrings.get().model;
57      }
58  
59      @Override
60      public String getSerialNumber() {
61          return smbiosStrings.get().serialNumber;
62      }
63  
64      @Override
65      public String getHardwareUUID() {
66          return smbiosStrings.get().uuid;
67      }
68  
69      @Override
70      public Firmware createFirmware() {
71          return new SolarisFirmware(smbiosStrings.get().biosVendor, smbiosStrings.get().biosVersion,
72                  smbiosStrings.get().biosDate);
73      }
74  
75      @Override
76      public Baseboard createBaseboard() {
77          return new UnixBaseboard(smbiosStrings.get().boardManufacturer, smbiosStrings.get().boardModel,
78                  smbiosStrings.get().boardSerialNumber, smbiosStrings.get().boardVersion);
79      }
80  
81      private static SmbiosStrings readSmbios() {
82          // $ smbios
83          // ID SIZE TYPE
84          // 0 87 SMB_TYPE_BIOS (BIOS Information)
85          //
86          // Vendor: Parallels Software International Inc.
87          // Version String: 11.2.1 (32686)
88          // Release Date: 07/15/2016
89          // Address Segment: 0xf000
90          // ... <snip> ...
91          //
92          // ID SIZE TYPE
93          // 1 177 SMB_TYPE_SYSTEM (system information)
94          //
95          // Manufacturer: Parallels Software International Inc.
96          // Product: Parallels Virtual Platforom
97          // Version: None
98          // Serial Number: Parallels-45 2E 7E 2D 57 5C 4B 59 B1 30 28 81 B7 81 89
99          // 34
100         //
101         // UUID: 452e7e2d-575c04b59-b130-2881b7818934
102         // Wake-up Event: 0x6 (Power Switch)
103         // SKU Number: Undefined
104         // Family: Parallels VM
105         //
106         // ID SIZE TYPE
107         // 2 90 SMB_TYPE_BASEBOARD (base board)
108         //
109         // Manufacturer: Parallels Software International Inc.
110         // Product: Parallels Virtual Platform
111         // Version: None
112         // Serial Number: None
113         // ... <snip> ...
114         //
115         // ID SIZE TYPE
116         // 3 .... <snip> ...
117 
118         final String serialNumMarker = "Serial Number";
119 
120         SmbType smbTypeId = null;
121 
122         EnumMap<SmbType, Map<String, String>> smbTypesMap = new EnumMap<>(SmbType.class);
123         smbTypesMap.put(SMB_TYPE_BIOS, new HashMap<>());
124         smbTypesMap.put(SMB_TYPE_SYSTEM, new HashMap<>());
125         smbTypesMap.put(SMB_TYPE_BASEBOARD, new HashMap<>());
126 
127         // Only works with root permissions but it's all we've got
128         for (final String checkLine : ExecutingCommand.runNative("smbios")) {
129             // Change the smbTypeId when hitting a new header
130             if (checkLine.contains("SMB_TYPE_") && (smbTypeId = getSmbType(checkLine)) == null) {
131                 // If we get past what we need, stop iterating
132                 break;
133             }
134             // Based on the smbTypeID we are processing for
135             Integer colonDelimiterIndex = checkLine.indexOf(":");
136             if (smbTypeId != null && colonDelimiterIndex >= 0) {
137                 String key = checkLine.substring(0, colonDelimiterIndex).trim();
138                 String val = checkLine.substring(colonDelimiterIndex + 1).trim();
139                 smbTypesMap.get(smbTypeId).put(key, val);
140             }
141         }
142 
143         Map<String, String> smbTypeBIOSMap = smbTypesMap.get(SMB_TYPE_BIOS);
144         Map<String, String> smbTypeSystemMap = smbTypesMap.get(SMB_TYPE_SYSTEM);
145         Map<String, String> smbTypeBaseboardMap = smbTypesMap.get(SMB_TYPE_BASEBOARD);
146 
147         // If we get to end and haven't assigned, use fallback
148         if (!smbTypeSystemMap.containsKey(serialNumMarker) || Util.isBlank(smbTypeSystemMap.get(serialNumMarker))) {
149             smbTypeSystemMap.put(serialNumMarker, readSerialNumber());
150         }
151         return new SmbiosStrings(smbTypeBIOSMap, smbTypeSystemMap, smbTypeBaseboardMap);
152     }
153 
154     private static SmbType getSmbType(String checkLine) {
155         for (SmbType smbType : SmbType.values()) {
156             if (checkLine.contains(smbType.name())) {
157                 return smbType;
158             }
159         }
160         // First 3 SMB_TYPEs are what we need. After that no need to
161         // continue processing the output
162         return null;
163     }
164 
165     private static String readSerialNumber() {
166         // If they've installed STB (Sun Explorer) this should work
167         String serialNumber = ExecutingCommand.getFirstAnswer("sneep");
168         // if that didn't work, try...
169         if (serialNumber.isEmpty()) {
170             String marker = "chassis-sn:";
171             for (String checkLine : ExecutingCommand.runNative("prtconf -pv")) {
172                 if (checkLine.contains(marker)) {
173                     serialNumber = ParseUtil.getSingleQuoteStringValue(checkLine);
174                     break;
175                 }
176             }
177         }
178         return serialNumber;
179     }
180 
181     private static final class SmbiosStrings {
182         private final String biosVendor;
183         private final String biosVersion;
184         private final String biosDate;
185 
186         private final String manufacturer;
187         private final String model;
188         private final String serialNumber;
189         private final String uuid;
190 
191         private final String boardManufacturer;
192         private final String boardModel;
193         private final String boardVersion;
194         private final String boardSerialNumber;
195 
196         private SmbiosStrings(Map<String, String> smbTypeBIOSStrings, Map<String, String> smbTypeSystemStrings,
197                 Map<String, String> smbTypeBaseboardStrings) {
198             final String vendorMarker = "Vendor";
199             final String biosDateMarker = "Release Date";
200             final String biosVersionMarker = "Version String";
201 
202             final String manufacturerMarker = "Manufacturer";
203             final String productMarker = "Product";
204             final String serialNumMarker = "Serial Number";
205             final String uuidMarker = "UUID";
206             final String versionMarker = "Version";
207 
208             this.biosVendor = getValueOrUnknown(smbTypeBIOSStrings, vendorMarker);
209             this.biosVersion = getValueOrUnknown(smbTypeBIOSStrings, biosVersionMarker);
210             this.biosDate = getValueOrUnknown(smbTypeBIOSStrings, biosDateMarker);
211             this.manufacturer = getValueOrUnknown(smbTypeSystemStrings, manufacturerMarker);
212             this.model = getValueOrUnknown(smbTypeSystemStrings, productMarker);
213             this.serialNumber = getValueOrUnknown(smbTypeSystemStrings, serialNumMarker);
214             this.uuid = getValueOrUnknown(smbTypeSystemStrings, uuidMarker);
215             this.boardManufacturer = getValueOrUnknown(smbTypeBaseboardStrings, manufacturerMarker);
216             this.boardModel = getValueOrUnknown(smbTypeBaseboardStrings, productMarker);
217             this.boardVersion = getValueOrUnknown(smbTypeBaseboardStrings, versionMarker);
218             this.boardSerialNumber = getValueOrUnknown(smbTypeBaseboardStrings, serialNumMarker);
219         }
220     }
221 }