VirtualBox

source: vbox/trunk/src/VBox/Devices/EFI/VBoxSmcUtil-darwin.cpp@ 69162

Last change on this file since 69162 was 62500, checked in by vboxsync, 8 years ago

(C) 2016

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 10.2 KB
Line 
1/* $Id: VBoxSmcUtil-darwin.cpp 62500 2016-07-22 19:06:59Z vboxsync $ */
2/** @file
3 * VBoxSmcUtil - Quick hack for viewing SMC data on a mac.
4 */
5
6/*
7 * Copyright (C) 2013-2016 Oracle Corporation
8 *
9 * This file is part of VirtualBox Open Source Edition (OSE), as
10 * available from http://www.virtualbox.org. This file is free software;
11 * you can redistribute it and/or modify it under the terms of the GNU
12 * General Public License (GPL) as published by the Free Software
13 * Foundation, in version 2 as it comes in the "COPYING" file of the
14 * VirtualBox OSE distribution. VirtualBox OSE is distributed in the
15 * hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
16 */
17
18
19/*********************************************************************************************************************************
20* Header Files *
21*********************************************************************************************************************************/
22#include <iprt/asm.h>
23#include <iprt/err.h>
24#include <iprt/ctype.h>
25#include <iprt/initterm.h>
26#include <iprt/message.h>
27#include <iprt/stream.h>
28#include <iprt/string.h>
29
30#include <mach/mach.h>
31#include <IOKit/IOKitLib.h>
32#include <IOKit/IOReturn.h>
33#include <CoreFoundation/CoreFoundation.h>
34#include <unistd.h>
35
36
37/*********************************************************************************************************************************
38* Structures and Typedefs *
39*********************************************************************************************************************************/
40enum
41{
42 kSMCSuccess = 0,
43 kSMCError = 1
44};
45
46typedef enum
47{
48 kSMCUserClientOpen = 0,
49 kSMCUserClientClose,
50 kSMCHandleYPCEvent,
51
52 kSMCPlaceholder1,
53 kSMCNumberOfMethods,
54
55 kSMCReadKey,
56 kSMCWriteKey,
57 kSMCGetKeyCount,
58 kSMCGetKeyFromIndex,
59 kSMCGetKeyInfo,
60
61 kSMCFireInterrupt,
62 kSMCGetPLimits,
63 kSMCGetVers,
64
65 kSMCPlaceholder2,
66
67 kSMCReadStatus,
68 kSMCReadResult,
69 kSMCVariableCommand
70} KSMCFUNCTION;
71
72typedef struct
73{
74 RTUINT32U uKey;
75 struct
76 {
77 uint8_t uMajor;
78 uint8_t uMinor;
79 uint8_t uBuild;
80 uint8_t uReserved;
81 uint16_t uRelease;
82 } Version;
83 struct
84 {
85 uint16_t uVer;
86 uint16_t cb;
87 uint32_t uCpuPLimit;
88 uint32_t uGpuPLimit;
89 uint32_t uMemPLimit;
90 } SMCPLimitData;
91
92 struct
93 {
94 IOByteCount cbData;
95 RTUINT32U uDataType;
96 uint8_t fAttr;
97 } KeyInfo;
98
99 uint8_t uResult;
100 uint8_t fStatus;
101 uint8_t bData;
102 uint32_t u32Data;
103 uint8_t abValue[32];
104} SMCPARAM;
105
106
107/*********************************************************************************************************************************
108* Global Variables *
109*********************************************************************************************************************************/
110io_service_t g_hSmcService = IO_OBJECT_NULL;
111io_connect_t g_hSmcConnect = IO_OBJECT_NULL;
112
113
114static int ConnectToSmc(void)
115{
116 g_hSmcService = IOServiceGetMatchingService(kIOMasterPortDefault, IOServiceMatching("AppleSMC"));
117 if (g_hSmcService == IO_OBJECT_NULL)
118 return VERR_NOT_FOUND;
119
120 IOReturn rcIo = IOServiceOpen(g_hSmcService, mach_task_self(), 1, &g_hSmcConnect);
121 if (rcIo == kIOReturnSuccess && g_hSmcConnect != IO_OBJECT_NULL)
122 {
123 rcIo = IOConnectCallMethod(g_hSmcConnect, kSMCUserClientOpen, NULL, 0, NULL, 0, NULL, NULL, NULL, NULL);
124 if (rcIo == kIOReturnSuccess)
125 return VINF_SUCCESS;
126 RTMsgError("kSMCUserClientOpen failed: %#x (%#x)\n", rcIo, rcIo);
127 }
128 else
129 {
130 RTMsgError("IOServiceOpen failed: %#x (%#x)\n", rcIo, rcIo);
131 g_hSmcConnect = IO_OBJECT_NULL;
132 }
133 return RTErrConvertFromDarwinIO(rcIo);
134}
135
136
137static void DisconnectFromSmc(void)
138{
139 if (g_hSmcConnect)
140 {
141 IOConnectCallMethod(g_hSmcConnect, kSMCUserClientClose, NULL, 0, NULL, 0, NULL, NULL, NULL, NULL);
142 IOServiceClose(g_hSmcConnect);
143 g_hSmcConnect = IO_OBJECT_NULL;
144 }
145
146 if (g_hSmcService)
147 {
148 IOServiceClose(g_hSmcService);
149 g_hSmcService = IO_OBJECT_NULL;
150 }
151}
152
153static int CallSmc(KSMCFUNCTION enmFunction, SMCPARAM *pIn, SMCPARAM *pOut)
154{
155 RT_ZERO(*pOut);
156 pIn->bData = enmFunction;
157 size_t cbOut = sizeof(*pOut);
158 IOReturn rcIo = IOConnectCallStructMethod(g_hSmcConnect, kSMCHandleYPCEvent, pIn, sizeof(*pIn), pOut, &cbOut);
159 if (rcIo == kIOReturnSuccess)
160 return VINF_SUCCESS;
161 RTMsgError("SMC call %d failed: rcIo=%d (%#x)\n", enmFunction, rcIo, rcIo);
162 return RTErrConvertFromDarwinIO(rcIo);
163}
164
165static int GetKeyCount(uint32_t *pcKeys)
166{
167 SMCPARAM In;
168 SMCPARAM Out;
169 RT_ZERO(In); RT_ZERO(Out);
170 In.KeyInfo.cbData = sizeof(uint32_t);
171 int rc = CallSmc(kSMCGetKeyCount, &In, &Out);
172 if (RT_SUCCESS(rc))
173 *pcKeys = RT_BE2H_U32(Out.u32Data);
174 else
175 *pcKeys = 1;
176 return rc;
177}
178
179static int GetKeyByIndex(uint32_t iKey, SMCPARAM *pKeyData)
180{
181 SMCPARAM In;
182 RT_ZERO(In);
183 In.u32Data = iKey;
184 int rc = CallSmc(kSMCGetKeyFromIndex, &In, pKeyData);
185 if (RT_SUCCESS(rc))
186 {
187 if (pKeyData->uResult == kSMCSuccess)
188 {
189 SMCPARAM Tmp = *pKeyData;
190
191 /* Get the key info. */
192 RT_ZERO(In);
193 In.uKey.u = Tmp.uKey.u;
194 rc = CallSmc(kSMCGetKeyInfo, &In, pKeyData);
195 if (RT_SUCCESS(rc) && pKeyData->uResult == kSMCSuccess)
196 {
197 Tmp.KeyInfo = pKeyData->KeyInfo;
198
199 /* Get the key value. */
200 RT_ZERO(In);
201 In.uKey = Tmp.uKey;
202 In.KeyInfo = Tmp.KeyInfo;
203 rc = CallSmc(kSMCReadKey, &In, pKeyData);
204 if (RT_SUCCESS(rc) && (pKeyData->uResult == kSMCSuccess || pKeyData->uResult == 0x85 /* not readable */))
205 {
206 pKeyData->uKey = Tmp.uKey;
207 pKeyData->KeyInfo = Tmp.KeyInfo;
208 rc = VINF_SUCCESS;
209 }
210 else if (RT_SUCCESS(rc))
211 {
212 RTMsgError("kSMCReadKey failed on #%x/%.4s: %#x\n", iKey, Tmp.uKey.au8, pKeyData->uResult);
213 rc = VERR_IO_GEN_FAILURE;
214 }
215 }
216 else if (RT_SUCCESS(rc))
217 {
218 RTMsgError("kSMCGetKeyInfo failed on #%x/%.4s: %#x\n", iKey, Tmp.uKey.au8, pKeyData->uResult);
219 rc = VERR_IO_GEN_FAILURE;
220 }
221 }
222 else
223 {
224 RTMsgError("kSMCGetKeyFromIndex failed on #%x: %#x\n", iKey, pKeyData->uResult);
225 rc = VERR_IO_GEN_FAILURE;
226 }
227 }
228 return rc;
229}
230
231
232static int GetKeyByName(uint32_t uKey, SMCPARAM *pKeyData)
233{
234 SMCPARAM In;
235 RT_ZERO(In);
236 In.uKey.u = uKey;
237 int rc = CallSmc(kSMCGetKeyInfo, &In, pKeyData);
238 if (RT_SUCCESS(rc) && pKeyData->uResult == kSMCSuccess)
239 {
240 SMCPARAM Tmp = *pKeyData;
241
242 /* Get the key value. */
243 RT_ZERO(In);
244 In.uKey.u = uKey;
245 In.KeyInfo = Tmp.KeyInfo;
246 rc = CallSmc(kSMCReadKey, &In, pKeyData);
247 if (RT_SUCCESS(rc) && (pKeyData->uResult == kSMCSuccess || pKeyData->uResult == 0x85 /* not readable */))
248 {
249 pKeyData->uKey.u = uKey;
250 pKeyData->KeyInfo = Tmp.KeyInfo;
251 rc = VINF_SUCCESS;
252 }
253 else if (RT_SUCCESS(rc))
254 {
255 RTMsgError("kSMCReadKey failed on %.4s: %#x\n", &uKey, pKeyData->uResult);
256 rc = VERR_IO_GEN_FAILURE;
257 }
258 }
259 else if (RT_SUCCESS(rc))
260 {
261 RTMsgError("kSMCGetKeyInfo failed on %.4s: %#x\n", &uKey, pKeyData->uResult);
262 rc = VERR_IO_GEN_FAILURE;
263 }
264 return rc;
265}
266
267static void DisplayKey(SMCPARAM *pKey)
268{
269 pKey->uKey.u = RT_BE2H_U32(pKey->uKey.u);
270 pKey->KeyInfo.uDataType.u = RT_BE2H_U32(pKey->KeyInfo.uDataType.u);
271 RTPrintf("key=%4.4s type=%4.4s cb=%#04x fAttr=%#04x",
272 pKey->uKey.au8, pKey->KeyInfo.uDataType.au8, pKey->KeyInfo.cbData, pKey->KeyInfo.fAttr);
273 if (pKey->uResult == kSMCSuccess)
274 {
275 bool fPrintable = true;
276 for (uint32_t off = 0; off < pKey->KeyInfo.cbData; off++)
277 if (!RT_C_IS_PRINT(pKey->abValue[off]))
278 {
279 fPrintable = false;
280 break;
281 }
282 if (fPrintable)
283 RTPrintf(" %.*s\n", pKey->KeyInfo.cbData, pKey->abValue);
284 else
285 RTPrintf(" %.*Rhxs\n", pKey->KeyInfo.cbData, pKey->abValue);
286 }
287 else if (pKey->uResult == 0x85)
288 RTPrintf(" <not readable>\n");
289}
290
291static void DisplayKeyByName(uint32_t uKey)
292{
293 SMCPARAM Key;
294 int rc = GetKeyByName(uKey, &Key);
295 if (RT_SUCCESS(rc))
296 DisplayKey(&Key);
297}
298
299
300int main(int argc, char **argv)
301{
302 int rc = RTR3InitExe(argc, &argv, 0);
303 if (RT_FAILURE(rc))
304 return RTMsgInitFailure(rc);
305
306 rc = ConnectToSmc();
307 if (RT_SUCCESS(rc))
308 {
309 /*
310 * Dump the keys.
311 */
312 uint32_t cKeys;
313 rc = GetKeyCount(&cKeys);
314 if (RT_SUCCESS(rc))
315 RTPrintf("#Keys=%u\n", cKeys);
316 for (uint32_t iKey = 0; iKey < cKeys; iKey++)
317 {
318 SMCPARAM Key;
319 rc = GetKeyByIndex(iKey, &Key);
320 if (RT_SUCCESS(rc))
321 {
322 RTPrintf("%#06x: ", iKey);
323 DisplayKey(&Key);
324 }
325 }
326
327 /*
328 * Known keys that doesn't make it into the enumeration.
329 */
330 DisplayKeyByName('OSK0');
331 DisplayKeyByName('OSK1');
332 DisplayKeyByName('OSK2');
333
334 /* Negative checks, sometimes maybe. */
335 DisplayKeyByName('$Num');
336 DisplayKeyByName('MSTf');
337 DisplayKeyByName('MSDS');
338 DisplayKeyByName('LSOF');
339 }
340 DisconnectFromSmc();
341
342 if (RT_SUCCESS(rc))
343 return RTEXITCODE_SUCCESS;
344 return RTEXITCODE_FAILURE;
345}
346
Note: See TracBrowser for help on using the repository browser.

© 2024 Oracle Support Privacy / Do Not Sell My Info Terms of Use Trademark Policy Automated Access Etiquette