38
38
#include "qemu/timer.h"
39
39
#include "qom/object.h"
40
40
41
+ #if defined(__APPLE__ ) && defined(__MACH__ )
42
+ #include <IOKit/IOKitLib.h>
43
+
44
+ enum {
45
+ kSMCSuccess = 0x00 ,
46
+ kSMCKeyNotFound = 0x84
47
+ };
48
+
49
+ enum {
50
+ kSMCUserClientOpen = 0x00 ,
51
+ kSMCUserClientClose = 0x01 ,
52
+ kSMCHandleYPCEvent = 0x02 ,
53
+ kSMCReadKey = 0x05 ,
54
+ kSMCGetKeyInfo = 0x09
55
+ };
56
+
57
+ typedef struct SMCVersion {
58
+ uint8_t major ;
59
+ uint8_t minor ;
60
+ uint8_t build ;
61
+ uint8_t reserved ;
62
+ uint16_t release ;
63
+ } SMCVersion ;
64
+
65
+ typedef struct SMCPLimitData {
66
+ uint16_t version ;
67
+ uint16_t length ;
68
+ uint32_t cpuPLimit ;
69
+ uint32_t gpuPLimit ;
70
+ uint32_t memPLimit ;
71
+ } SMCPLimitData ;
72
+
73
+ typedef struct SMCKeyInfoData {
74
+ IOByteCount dataSize ;
75
+ uint32_t dataType ;
76
+ uint8_t dataAttributes ;
77
+ } SMCKeyInfoData ;
78
+
79
+ typedef struct {
80
+ uint32_t key ;
81
+ SMCVersion vers ;
82
+ SMCPLimitData pLimitData ;
83
+ SMCKeyInfoData keyInfo ;
84
+ uint8_t result ;
85
+ uint8_t status ;
86
+ uint8_t data8 ;
87
+ uint32_t data32 ;
88
+ uint8_t bytes [32 ];
89
+ } SMCParamStruct ;
90
+
91
+ static IOReturn smc_call_struct_method (uint32_t selector ,
92
+ SMCParamStruct * inputStruct ,
93
+ SMCParamStruct * outputStruct )
94
+ {
95
+ IOReturn ret ;
96
+
97
+ size_t inputStructCnt = sizeof (SMCParamStruct );
98
+ size_t outputStructCnt = sizeof (SMCParamStruct );
99
+
100
+ io_service_t smcService = IO_OBJECT_NULL ;
101
+ io_connect_t smcConnect = IO_OBJECT_NULL ;
102
+
103
+ smcService = IOServiceGetMatchingService (kIOMasterPortDefault ,
104
+ IOServiceMatching ("AppleSMC" ));
105
+ if (smcService == IO_OBJECT_NULL ) {
106
+ ret = kIOReturnNotFound ;
107
+ goto exit ;
108
+ }
109
+
110
+ ret = IOServiceOpen (smcService , mach_task_self (), 1 , & smcConnect );
111
+ if (ret != kIOReturnSuccess ) {
112
+ smcConnect = IO_OBJECT_NULL ;
113
+ goto exit ;
114
+ }
115
+ if (smcConnect == IO_OBJECT_NULL ) {
116
+ ret = kIOReturnError ;
117
+ goto exit ;
118
+ }
119
+
120
+ ret = IOConnectCallMethod (smcConnect , kSMCUserClientOpen ,
121
+ NULL , 0 , NULL , 0 ,
122
+ NULL , NULL , NULL , NULL );
123
+ if (ret != kIOReturnSuccess ) {
124
+ goto exit ;
125
+ }
126
+
127
+ ret = IOConnectCallStructMethod (smcConnect , selector ,
128
+ inputStruct , inputStructCnt ,
129
+ outputStruct , & outputStructCnt );
130
+
131
+ exit :
132
+ if (smcConnect != IO_OBJECT_NULL ) {
133
+ IOConnectCallMethod (smcConnect , kSMCUserClientClose ,
134
+ NULL , 0 , NULL , 0 , NULL ,
135
+ NULL , NULL , NULL );
136
+ IOServiceClose (smcConnect );
137
+ }
138
+
139
+ return ret ;
140
+ }
141
+
142
+ static IOReturn smc_read_key (uint32_t key ,
143
+ uint8_t * bytes ,
144
+ IOByteCount * dataSize )
145
+ {
146
+ IOReturn ret ;
147
+
148
+ SMCParamStruct inputStruct ;
149
+ SMCParamStruct outputStruct ;
150
+
151
+ if (key == 0 || bytes == NULL ) {
152
+ ret = kIOReturnCannotWire ;
153
+ goto exit ;
154
+ }
155
+
156
+ /* determine key's data size */
157
+ memset (& inputStruct , 0 , sizeof (SMCParamStruct ));
158
+ inputStruct .data8 = kSMCGetKeyInfo ;
159
+ inputStruct .key = key ;
160
+
161
+ memset (& outputStruct , 0 , sizeof (SMCParamStruct ));
162
+ ret = smc_call_struct_method (kSMCHandleYPCEvent , & inputStruct , & outputStruct );
163
+ if (ret != kIOReturnSuccess ) {
164
+ goto exit ;
165
+ }
166
+ if (outputStruct .result == kSMCKeyNotFound ) {
167
+ ret = kIOReturnNotFound ;
168
+ goto exit ;
169
+ }
170
+ if (outputStruct .result != kSMCSuccess ) {
171
+ ret = kIOReturnInternalError ;
172
+ goto exit ;
173
+ }
174
+
175
+ /* get key value */
176
+ memset (& inputStruct , 0 , sizeof (SMCParamStruct ));
177
+ inputStruct .data8 = kSMCReadKey ;
178
+ inputStruct .key = key ;
179
+ inputStruct .keyInfo .dataSize = outputStruct .keyInfo .dataSize ;
180
+
181
+ memset (& outputStruct , 0 , sizeof (SMCParamStruct ));
182
+ ret = smc_call_struct_method (kSMCHandleYPCEvent , & inputStruct , & outputStruct );
183
+ if (ret != kIOReturnSuccess ) {
184
+ goto exit ;
185
+ }
186
+ if (outputStruct .result == kSMCKeyNotFound ) {
187
+ ret = kIOReturnNotFound ;
188
+ goto exit ;
189
+ }
190
+ if (outputStruct .result != kSMCSuccess ) {
191
+ ret = kIOReturnInternalError ;
192
+ goto exit ;
193
+ }
194
+
195
+ memset (bytes , 0 , * dataSize );
196
+ if (* dataSize > inputStruct .keyInfo .dataSize ) {
197
+ * dataSize = inputStruct .keyInfo .dataSize ;
198
+ }
199
+ memcpy (bytes , outputStruct .bytes , * dataSize );
200
+
201
+ exit :
202
+ return ret ;
203
+ }
204
+ #endif
205
+
41
206
/* #define DEBUG_SMC */
42
207
43
208
#define APPLESMC_DEFAULT_IOBASE 0x300
@@ -315,6 +480,7 @@ static const MemoryRegionOps applesmc_err_io_ops = {
315
480
static void applesmc_isa_realize (DeviceState * dev , Error * * errp )
316
481
{
317
482
AppleSMCState * s = APPLE_SMC (dev );
483
+ bool valid_key = false;
318
484
319
485
memory_region_init_io (& s -> io_data , OBJECT (s ), & applesmc_data_io_ops , s ,
320
486
"applesmc-data" , 1 );
@@ -331,7 +497,31 @@ static void applesmc_isa_realize(DeviceState *dev, Error **errp)
331
497
isa_register_ioport (& s -> parent_obj , & s -> io_err ,
332
498
s -> iobase + APPLESMC_ERR_PORT );
333
499
334
- if (!s -> osk || (strlen (s -> osk ) != 64 )) {
500
+ if (s -> osk ) {
501
+ valid_key = strlen (s -> osk ) == 64 ;
502
+ } else {
503
+ #if defined(__APPLE__ ) && defined(__MACH__ )
504
+ IOReturn ret ;
505
+ IOByteCount size = 32 ;
506
+
507
+ ret = smc_read_key ('OSK0' , (uint8_t * ) default_osk , & size );
508
+ if (ret != kIOReturnSuccess ) {
509
+ goto failure ;
510
+ }
511
+
512
+ ret = smc_read_key ('OSK1' , (uint8_t * ) default_osk + size , & size );
513
+ if (ret != kIOReturnSuccess ) {
514
+ goto failure ;
515
+ }
516
+
517
+ warn_report ("Using AppleSMC with host key" );
518
+ valid_key = true;
519
+ s -> osk = default_osk ;
520
+ failure :;
521
+ #endif
522
+ }
523
+
524
+ if (!valid_key ) {
335
525
warn_report ("Using AppleSMC with invalid key" );
336
526
s -> osk = default_osk ;
337
527
}
0 commit comments