1
2
3
4
5 package oshi.hardware.platform.mac;
6
7 import static oshi.util.Memoizer.memoize;
8
9 import java.nio.charset.StandardCharsets;
10 import java.util.function.Supplier;
11
12 import com.sun.jna.Native;
13 import com.sun.jna.platform.mac.IOKit.IOIterator;
14 import com.sun.jna.platform.mac.IOKit.IORegistryEntry;
15 import com.sun.jna.platform.mac.IOKitUtil;
16
17 import oshi.annotation.concurrent.Immutable;
18 import oshi.hardware.common.AbstractFirmware;
19 import oshi.util.Constants;
20 import oshi.util.Util;
21 import oshi.util.tuples.Quintet;
22
23
24
25
26 @Immutable
27 final class MacFirmware extends AbstractFirmware {
28
29 private final Supplier<Quintet<String, String, String, String, String>> manufNameDescVersRelease = memoize(
30 MacFirmware::queryEfi);
31
32 @Override
33 public String getManufacturer() {
34 return manufNameDescVersRelease.get().getA();
35 }
36
37 @Override
38 public String getName() {
39 return manufNameDescVersRelease.get().getB();
40 }
41
42 @Override
43 public String getDescription() {
44 return manufNameDescVersRelease.get().getC();
45 }
46
47 @Override
48 public String getVersion() {
49 return manufNameDescVersRelease.get().getD();
50 }
51
52 @Override
53 public String getReleaseDate() {
54 return manufNameDescVersRelease.get().getE();
55 }
56
57 private static Quintet<String, String, String, String, String> queryEfi() {
58 String manufacturer = null;
59 String name = null;
60 String description = null;
61 String version = null;
62 String releaseDate = null;
63
64 IORegistryEntry platformExpert = IOKitUtil.getMatchingService("IOPlatformExpertDevice");
65 byte[] data;
66 if (platformExpert != null) {
67 IOIterator iter = platformExpert.getChildIterator("IODeviceTree");
68 if (iter != null) {
69 IORegistryEntry entry = iter.next();
70 while (entry != null) {
71 switch (entry.getName()) {
72 case "rom":
73 data = entry.getByteArrayProperty("vendor");
74 if (data != null) {
75 manufacturer = Native.toString(data, StandardCharsets.UTF_8);
76 }
77 data = entry.getByteArrayProperty("version");
78 if (data != null) {
79 version = Native.toString(data, StandardCharsets.UTF_8);
80 }
81 data = entry.getByteArrayProperty("release-date");
82 if (data != null) {
83 releaseDate = Native.toString(data, StandardCharsets.UTF_8);
84 }
85 break;
86 case "chosen":
87 data = entry.getByteArrayProperty("booter-name");
88 if (data != null) {
89 name = Native.toString(data, StandardCharsets.UTF_8);
90 }
91 break;
92 case "efi":
93 data = entry.getByteArrayProperty("firmware-abi");
94 if (data != null) {
95 description = Native.toString(data, StandardCharsets.UTF_8);
96 }
97 break;
98 default:
99 if (Util.isBlank(name)) {
100 name = entry.getStringProperty("IONameMatch");
101 }
102 break;
103 }
104 entry.release();
105 entry = iter.next();
106 }
107 iter.release();
108 }
109 if (Util.isBlank(manufacturer)) {
110 data = platformExpert.getByteArrayProperty("manufacturer");
111 if (data != null) {
112 manufacturer = Native.toString(data, StandardCharsets.UTF_8);
113 }
114 }
115 if (Util.isBlank(version)) {
116 data = platformExpert.getByteArrayProperty("target-type");
117 if (data != null) {
118 version = Native.toString(data, StandardCharsets.UTF_8);
119 }
120 }
121 if (Util.isBlank(name)) {
122 data = platformExpert.getByteArrayProperty("device_type");
123 if (data != null) {
124 name = Native.toString(data, StandardCharsets.UTF_8);
125 }
126 }
127 platformExpert.release();
128 }
129 return new Quintet<>(Util.isBlank(manufacturer) ? Constants.UNKNOWN : manufacturer,
130 Util.isBlank(name) ? Constants.UNKNOWN : name,
131 Util.isBlank(description) ? Constants.UNKNOWN : description,
132 Util.isBlank(version) ? Constants.UNKNOWN : version,
133 Util.isBlank(releaseDate) ? Constants.UNKNOWN : releaseDate);
134 }
135 }