Changeset 29564 in vbox
- Timestamp:
- May 17, 2010 3:19:33 PM (14 years ago)
- Location:
- trunk/src/VBox
- Files:
-
- 2 edited
-
Devices/PC/DevSMC.cpp (modified) (11 diffs)
-
Main/ConsoleImpl2.cpp (modified) (8 diffs)
Legend:
- Unmodified
- Added
- Removed
-
trunk/src/VBox/Devices/PC/DevSMC.cpp
r29522 r29564 55 55 #include <VBox/stam.h> 56 56 #include <iprt/assert.h> 57 #ifdef IN_RING0 58 # include <iprt/asm-amd64-x86.h> 59 # include <iprt/once.h> 60 #endif 57 61 #include <iprt/string.h> 58 62 59 63 #include "../Builtins2.h" 60 64 65 66 /******************************************************************************* 67 * Defined Constants And Macros * 68 *******************************************************************************/ 61 69 /* data port used by Apple SMC */ 62 70 #define APPLESMC_DATA_PORT 0x300 … … 71 79 #define APPLESMC_GET_KEY_TYPE_CMD 0x13 72 80 73 static char osk[64];74 75 81 /** The version of the saved state. */ 76 82 #define SMC_SAVED_STATE_VERSION 1 77 83 84 /** The ring-0 operation number that attempts to get OSK0 and OSK1 from the real 85 * SMC. */ 86 #define SMC_CALLR0_READ_OSK 1 87 88 /******************************************************************************* 89 * Structures and Typedefs * 90 *******************************************************************************/ 78 91 typedef struct AppleSMCData 79 92 { … … 82 95 const char *data; 83 96 } AppleSMCData; 97 98 99 typedef struct 100 { 101 PPDMDEVINSR3 pDevIns; 102 103 uint8_t cmd; 104 uint8_t status; 105 uint8_t key[4]; 106 uint8_t read_pos; 107 uint8_t data_len; 108 uint8_t data_pos; 109 uint8_t data[255]; 110 111 /** The OSK0 value. This is currently only used in the constructor. */ 112 uint8_t abOsk0[32]; 113 /** The OSK1 value. This is currently only used in the constructor */ 114 uint8_t abOsk1[32]; 115 } SMCState; 116 117 /******************************************************************************* 118 * Global Variables * 119 *******************************************************************************/ 120 #ifdef IN_RING3 121 static char osk[64]; 84 122 85 123 /* See http://www.mactel-linux.org/wiki/AppleSMC */ … … 95 133 {0, NULL, NULL } 96 134 }; 97 98 typedef struct 99 { 100 PPDMDEVINSR3 pDevIns; 101 102 uint8_t cmd; 103 uint8_t status; 104 uint8_t key[4]; 105 uint8_t read_pos; 106 uint8_t data_len; 107 uint8_t data_pos; 108 uint8_t data[255]; 109 110 char* pszDeviceKey; 111 } SMCState; 135 #endif /* IN_RING3 */ 136 #ifdef IN_RING0 137 /** Do once for the SMC ring-0 static data (g_abOsk0, g_abOsk1, g_fHaveOsk). */ 138 static RTONCE g_SmcR0Once = RTONCE_INITIALIZER; 139 /** Indicates whether we've successfully queried the OSK* keys. */ 140 static bool g_fHaveOsk = false; 141 /** The OSK0 value. */ 142 static uint8_t g_abOsk0[32]; 143 /** The OSK1 value. */ 144 static uint8_t g_abOsk1[32]; 145 #endif /* IN_RING0 */ 112 146 113 147 #ifndef VBOX_DEVICE_STRUCT_TESTCASE 114 148 149 #ifdef IN_RING0 150 151 /** 152 * Waits for the specified status on the host SMC. 153 * 154 * @returns success indicator. 155 * @param bStatus The desired status. 156 * @param pszWhat What we're currently doing. For the log. 157 */ 158 static bool devR0SmcWaitHostStatus(uint8_t bStatus, const char *pszWhat) 159 { 160 uint8_t bCurStatus; 161 for (uint32_t cMsSleep = 1; cMsSleep <= 64; cMsSleep <<= 1) 162 { 163 RTThreadSleep(cMsSleep); 164 bCurStatus = ASMInU8(APPLESMC_CMD_PORT); 165 if ((bCurStatus & 0xf) == bStatus) 166 return true; 167 } 168 169 LogRel(("devR0Smc: %s: bCurStatus=%#x, wanted %#x.\n", pszWhat, bCurStatus, bStatus)); 170 return false; 171 } 172 173 /** 174 * Reads a key by name from the host SMC. 175 * 176 * @returns success indicator. 177 * @param pszName The key name, must be exactly 4 chars long. 178 * @param pbBuf The output buffer. 179 * @param cbBuf The buffer size. Max 32 bytes. 180 */ 181 static bool devR0SmcQueryHostKey(const char *pszName, uint8_t *pbBuf, size_t cbBuf) 182 { 183 Assert(strlen(pszName) == 4); 184 Assert(cbBuf <= 32); 185 Assert(cbBuf > 0); 186 187 /* 188 * Issue the READ command. 189 */ 190 uint32_t cMsSleep = 1; 191 for (;;) 192 { 193 ASMOutU8(APPLESMC_CMD_PORT, APPLESMC_READ_CMD); 194 RTThreadSleep(cMsSleep); 195 uint8_t bCurStatus = ASMInU8(APPLESMC_CMD_PORT); 196 if ((bCurStatus & 0xf) == 0xc) 197 break; 198 cMsSleep <<= 1; 199 if (cMsSleep > 64) 200 { 201 LogRel(("devR0Smc: %s: bCurStatus=%#x, wanted %#x.\n", "cmd", bCurStatus, 0xc)); 202 return false; 203 } 204 } 205 206 /* 207 * Send it the key. 208 */ 209 for (unsigned off = 0; off < 4; off++) 210 { 211 ASMOutU8(APPLESMC_DATA_PORT, pszName[off]); 212 if (!devR0SmcWaitHostStatus(4, "key")) 213 return false; 214 } 215 216 /* 217 * The desired amount of output. 218 */ 219 ASMOutU8(APPLESMC_DATA_PORT, (uint8_t)cbBuf); 220 221 /* 222 * Read the output. 223 */ 224 for (size_t off = 0; off < cbBuf; off++) 225 { 226 if (!devR0SmcWaitHostStatus(5, off ? "data" : "len")) 227 return false; 228 pbBuf[off] = ASMInU8(APPLESMC_DATA_PORT); 229 } 230 231 return true; 232 } 233 234 /** 235 * RTOnce callback that initializes g_fHaveOsk, g_abOsk0 and g_abOsk1. 236 * 237 * @returns VINF_SUCCESS. 238 * @param pvUser1Ignored Ignored. 239 * @param pvUser2Ignored Ignored. 240 */ 241 static DECLCALLBACK(int) devR0SmcInitOnce(void *pvUser1Ignored, void *pvUser2Ignored) 242 { 243 g_fHaveOsk = devR0SmcQueryHostKey("OSK0", &g_abOsk0[0], sizeof(g_abOsk0)) 244 && devR0SmcQueryHostKey("OSK1", &g_abOsk1[0], sizeof(g_abOsk1)); 245 246 NOREF(pvUser1Ignored); NOREF(pvUser2Ignored); 247 return VINF_SUCCESS; 248 } 249 250 /** 251 * @interface_method_impl{FNPDMDEVREQHANDLERR0} 252 */ 253 PDMBOTHCBDECL(int) devR0SmcReqHandler(PPDMDEVINS pDevIns, uint32_t uOperation, uint64_t u64Arg) 254 { 255 SMCState *pThis = PDMINS_2_DATA(pDevIns, SMCState *); 256 int rc = VERR_INVALID_FUNCTION; 257 258 if (uOperation == SMC_CALLR0_READ_OSK) 259 { 260 rc = RTOnce(&g_SmcR0Once, devR0SmcInitOnce, NULL, NULL); 261 if ( RT_SUCCESS(rc) 262 && g_fHaveOsk) 263 { 264 AssertCompile(sizeof(g_abOsk0) == sizeof(pThis->abOsk0)); 265 AssertCompile(sizeof(g_abOsk1) == sizeof(pThis->abOsk1)); 266 memcpy(pThis->abOsk0, g_abOsk0, sizeof(pThis->abOsk0)); 267 memcpy(pThis->abOsk1, g_abOsk1, sizeof(pThis->abOsk1)); 268 } 269 } 270 return rc; 271 } 272 273 #endif /* IN_RING0 */ 115 274 #ifdef IN_RING3 275 116 276 /** 117 277 * Saves a state of the SMC device. … … 149 309 /** @todo: implement serialization */ 150 310 return VINF_SUCCESS; 151 }152 153 /**154 * Relocation notification.155 *156 * @returns VBox status.157 * @param pDevIns The device instance data.158 * @param offDelta The delta relative to the old address.159 */160 static DECLCALLBACK(void) smcRelocate(PPDMDEVINS pDevIns, RTGCINTPTR offDelta)161 {162 SMCState *pThis = PDMINS_2_DATA(pDevIns, SMCState *);163 /* SMC device lives only in R3 now, thus nothing to relocate yet */164 311 } 165 312 … … 335 482 { 336 483 SMCState *pThis = PDMINS_2_DATA(pDevIns, SMCState *); 337 int rc;338 484 Assert(iInstance == 0); 339 485 … … 346 492 * Validate and read the configuration. 347 493 */ 348 if (!CFGMR3AreValuesValid(pCfg, 349 "DeviceKey\0" 350 )) 351 return PDMDEV_SET_ERROR(pDevIns, VERR_PDM_DEVINS_UNKNOWN_CFG_VALUES, 352 N_("Configuration error: Invalid config value(s) for the SMC device")); 353 354 /* 355 * Query device key 356 */ 357 rc = CFGMR3QueryStringAlloc(pCfg, "DeviceKey", &pThis->pszDeviceKey); 358 if (rc == VERR_CFGM_VALUE_NOT_FOUND) 359 { 360 pThis->pszDeviceKey = RTStrDup("Invalid"); 361 LogRel(("Invalid SMC device key\n")); 362 if (!pThis->pszDeviceKey) 363 return VERR_NO_MEMORY; 364 365 rc = VINF_SUCCESS; 366 } 367 else if (RT_FAILURE(rc)) 494 PDMDEV_VALIDATE_CONFIG_RETURN(pDevIns, "DeviceKey|GetKeyFromRealSMC", ""); 495 496 /* 497 * Read the DeviceKey config value. 498 */ 499 char *pszDeviceKey; 500 int rc = CFGMR3QueryStringAllocDef(pCfg, "DeviceKey", &pszDeviceKey, ""); 501 if (RT_FAILURE(rc)) 368 502 return PDMDevHlpVMSetError(pDevIns, rc, RT_SRC_POS, 369 503 N_("Configuration error: Querying \"DeviceKey\" as a string failed")); 370 504 371 memcpy(osk, pThis->pszDeviceKey, RTStrNLen(pThis->pszDeviceKey, 64)); 505 size_t cchDeviceKey = strlen(pszDeviceKey); 506 if (cchDeviceKey > 0) 507 memcpy(&pThis->abOsk0[0], pszDeviceKey, RT_MIN(cchDeviceKey, sizeof(pThis->abOsk0))); 508 if (cchDeviceKey > sizeof(pThis->abOsk0)) 509 memcpy(&pThis->abOsk1[0], &pszDeviceKey[sizeof(pThis->abOsk0)], 510 RT_MIN(cchDeviceKey - sizeof(pThis->abOsk0), sizeof(pThis->abOsk1))); 511 512 MMR3HeapFree(pszDeviceKey); 513 514 /* 515 * Query the key from the real hardware if asked to do so. 516 */ 517 bool fGetKeyFromRealSMC; 518 rc = CFGMR3QueryBoolDef(pCfg, "GetKeyFromRealSMC", &fGetKeyFromRealSMC, false); 519 if (RT_FAILURE(rc)) 520 return PDMDevHlpVMSetError(pDevIns, rc, RT_SRC_POS, 521 N_("Configuration error: Querying \"GetKeyFromRealSMC\" as a boolean failed")); 522 if (fGetKeyFromRealSMC) 523 { 524 rc = PDMDevHlpCallR0(pDevIns, SMC_CALLR0_READ_OSK, 0 /*u64Arg*/); 525 if (RT_FAILURE(rc)) 526 return PDMDevHlpVMSetError(pDevIns, rc, RT_SRC_POS, 527 N_("Failed to query SMC value from the host")); 528 } 529 530 /* 531 * For practical/historical reasons, the OSK[0|1] data is stored in a 532 * global buffer in ring-3. 533 */ 534 AssertCompile(sizeof(osk) == sizeof(pThis->abOsk0) + sizeof(pThis->abOsk1)); 535 AssertCompile(sizeof(char) == sizeof(uint8_t)); 536 memcpy(osk, pThis->abOsk0, sizeof(pThis->abOsk0)); 537 memcpy(&osk[sizeof(pThis->abOsk0)], pThis->abOsk1, sizeof(pThis->abOsk1)); 372 538 373 539 /* … … 375 541 */ 376 542 rc = PDMDevHlpIOPortRegister(pDevIns, APPLESMC_DATA_PORT, 1, NULL, 377 smcIOPortWrite, smcIOPortRead,378 NULL, NULL, "SMC Data");543 smcIOPortWrite, smcIOPortRead, 544 NULL, NULL, "SMC Data"); 379 545 if (RT_FAILURE(rc)) 380 546 return rc; 381 547 rc = PDMDevHlpIOPortRegister(pDevIns, APPLESMC_CMD_PORT, 1, NULL, 382 smcIOPortWrite, smcIOPortRead,383 NULL, NULL, "SMC Commands");548 smcIOPortWrite, smcIOPortRead, 549 NULL, NULL, "SMC Commands"); 384 550 if (RT_FAILURE(rc)) 385 551 return rc; … … 399 565 */ 400 566 PDMDevHlpDBGFInfoRegister(pDevIns, "smc", "Display SMC status. (no arguments)", smcInfo); 401 402 return VINF_SUCCESS;403 }404 405 406 /**407 * Destruct a device instance.408 *409 * Most VM resources are freed by the VM. This callback is provided so that any non-VM410 * resources can be freed correctly.411 *412 * @param pDevIns The device instance data.413 */414 static DECLCALLBACK(int) smcDestruct(PPDMDEVINS pDevIns)415 {416 SMCState* pThis = PDMINS_2_DATA(pDevIns, SMCState*);417 418 /*419 * Free MM heap pointers.420 */421 if (pThis->pszDeviceKey)422 {423 MMR3HeapFree(pThis->pszDeviceKey);424 pThis->pszDeviceKey = NULL;425 }426 567 427 568 return VINF_SUCCESS; … … 444 585 "System Management Controller (SMC) Device", 445 586 /* fFlags */ 446 PDM_DEVREG_FLAGS_HOST_BITS_DEFAULT | PDM_DEVREG_FLAGS_GUEST_BITS_32_64 | PDM_DEVREG_FLAGS_PAE36 ,587 PDM_DEVREG_FLAGS_HOST_BITS_DEFAULT | PDM_DEVREG_FLAGS_GUEST_BITS_32_64 | PDM_DEVREG_FLAGS_PAE36| PDM_DEVREG_FLAGS_R0, 447 588 /* fClass */ 448 589 PDM_DEVREG_CLASS_MISC, … … 454 595 smcConstruct, 455 596 /* pfnDestruct */ 456 smcDestruct,597 NULL, 457 598 /* pfnRelocate */ 458 smcRelocate,599 NULL, 459 600 /* pfnIOCtl */ 460 601 NULL, -
trunk/src/VBox/Main/ConsoleImpl2.cpp
r29480 r29564 30 30 #endif 31 31 #include "VMMDev.h" 32 #include "Global.h" 32 33 33 34 // generated header … … 38 39 39 40 #include <iprt/buildconfig.h> 41 #include <iprt/ctype.h> 42 #include <iprt/dir.h> 43 #include <iprt/file.h> 44 #include <iprt/param.h> 45 #include <iprt/path.h> 40 46 #include <iprt/string.h> 41 #include <iprt/path.h> 42 #include <iprt/dir.h> 43 #include <iprt/param.h> 47 #include <iprt/system.h> 44 48 #if 0 /* enable to play with lots of memory. */ 45 49 # include <iprt/env.h> 46 50 #endif 47 #include <iprt/file.h>48 51 49 52 #include <VBox/vmapi.h> … … 101 104 #include "DHCPServerRunner.h" 102 105 103 #if defined(RT_OS_DARWIN) && !defined(VBOX_OSE)106 #if defined(RT_OS_DARWIN) 104 107 105 108 # include "IOKit/IOKitLib.h" 106 109 107 static int DarwinSmcKey(char * aKey, uint32_t iKeySize)110 static int DarwinSmcKey(char *pabKey, uint32_t cbKey) 108 111 { 109 112 /* … … 122 125 } AppleSMCBuffer; 123 126 124 AssertReturn( iKeySize>= 65, VERR_INTERNAL_ERROR);127 AssertReturn(cbKey >= 65, VERR_INTERNAL_ERROR); 125 128 126 129 io_service_t service = IOServiceGetMatchingService(kIOMasterPortDefault, 127 130 IOServiceMatching("AppleSMC")); 128 131 if (!service) 129 return VERR_ INTERNAL_ERROR;132 return VERR_NOT_FOUND; 130 133 131 134 io_connect_t port = (io_connect_t)0; … … 134 137 135 138 if (kr != kIOReturnSuccess) 136 return VERR_INTERNAL_ERROR;139 return RTErrConvertFromDarwin(kr); 137 140 138 141 AppleSMCBuffer inputStruct = { 0, {0}, 32, {0}, 5, }; … … 152 155 { 153 156 IOServiceClose(port); 154 return VERR_INTERNAL_ERROR;157 return RTErrConvertFromDarwin(kr); 155 158 } 156 159 157 160 for (int j = 0; j < 32; j++) 158 aKey[j + i*32] = outputStruct.data[j];161 pabKey[j + i*32] = outputStruct.data[j]; 159 162 } 160 163 161 164 IOServiceClose(port); 162 165 163 aKey[64] = 0;166 pabKey[64] = 0; 164 167 165 168 return VINF_SUCCESS; … … 236 239 } 237 240 238 static int getSmcDeviceKey(IMachine * pMachine, BSTR * aKey)241 static int getSmcDeviceKey(IMachine *pMachine, BSTR *aKey, bool *pfGetKeyFromRealSMC) 239 242 { 240 # if defined(RT_OS_DARWIN) && !defined(VBOX_OSE) 241 int rc; 242 char aKeyBuf[65]; 243 244 rc = DarwinSmcKey(aKeyBuf, sizeof aKeyBuf); 243 *pfGetKeyFromRealSMC = false; 244 245 /* 246 * The extra data takes precedence (if non-zero). 247 */ 248 HRESULT hrc = pMachine->GetExtraData(Bstr("VBoxInternal2/SmcDeviceKey"), aKey); 249 if (FAILED(hrc)) 250 return Global::vboxStatusCodeFromCOM(hrc); 251 if ( SUCCEEDED(hrc) 252 && *aKey 253 && **aKey) 254 return VINF_SUCCESS; 255 256 #ifdef RT_OS_DARWIN 257 /* 258 * Query it here and now. 259 */ 260 char abKeyBuf[65]; 261 int rc = DarwinSmcKey(abKeyBuf, sizeof(abKeyBuf)); 245 262 if (SUCCEEDED(rc)) 246 263 { 247 Bstr(a KeyBuf).detachTo(aKey);264 Bstr(abKeyBuf).detachTo(aKey); 248 265 return rc; 249 266 } 267 LogRel(("Warning: DarwinSmcKey failed with rc=%Rrc!\n", rc)); 268 269 #else 270 /* 271 * Is it apple hardware in bootcamp? 272 */ 273 /** @todo implement + test RTSYSDMISTR_MANUFACTURER on all hosts. 274 * Currently falling back on the product name. */ 275 char szManufacturer[256]; 276 szManufacturer[0] = '\0'; 277 RTSystemQueryDmiString(RTSYSDMISTR_MANUFACTURER, szManufacturer, sizeof(szManufacturer)); 278 if (szManufacturer[0] != '\0') 279 { 280 if ( !strcmp(szManufacturer, "Apple Computer, Inc.") 281 || !strcmp(szManufacturer, "Apple Inc.") 282 ) 283 *pfGetKeyFromRealSMC = true; 284 } 285 else 286 { 287 char szProdName[256]; 288 szProdName[0] = '\0'; 289 RTSystemQueryDmiString(RTSYSDMISTR_PRODUCT_NAME, szProdName, sizeof(szProdName)); 290 if ( ( !strncmp(szProdName, "Mac", 3) 291 || !strncmp(szProdName, "iMac", 4) 292 || !strncmp(szProdName, "iMac", 4) 293 || !strncmp(szProdName, "Xserve", 6) 294 ) 295 && !strchr(szProdName, ' ') /* no spaces */ 296 && RT_C_IS_DIGIT(szProdName[strlen(szProdName) - 1]) /* version number */ 297 ) 298 *pfGetKeyFromRealSMC = true; 299 } 300 301 int rc = VINF_SUCCESS; 250 302 #endif 251 303 252 return pMachine->GetExtraData(Bstr("VBoxInternal2/SmcDeviceKey"), aKey);304 return rc; 253 305 } 254 306 … … 674 726 if (fSmcEnabled) 675 727 { 676 Bstr tmpStr2;677 728 rc = CFGMR3InsertNode(pDevices, "smc", &pDev); RC_CHECK(); 678 729 rc = CFGMR3InsertNode(pDev, "0", &pInst); RC_CHECK(); 679 730 rc = CFGMR3InsertInteger(pInst, "Trusted", 1); /* boolean */ RC_CHECK(); 680 731 rc = CFGMR3InsertNode(pInst, "Config", &pCfg); RC_CHECK(); 681 rc = getSmcDeviceKey(pMachine, tmpStr2.asOutParam()); RC_CHECK(); 682 rc = CFGMR3InsertString(pCfg, "DeviceKey", Utf8Str(tmpStr2).raw()); RC_CHECK(); 732 bool fGetKeyFromRealSMC; 733 Bstr bstrKey; 734 rc = getSmcDeviceKey(pMachine, bstrKey.asOutParam(), &fGetKeyFromRealSMC); RC_CHECK(); 735 rc = CFGMR3InsertString(pCfg, "DeviceKey", Utf8Str(bstrKey).raw()); RC_CHECK(); 736 rc = CFGMR3InsertInteger(pCfg, "GetKeyFromRealSMC", fGetKeyFromRealSMC); RC_CHECK(); 683 737 } 684 738
Note:
See TracChangeset
for help on using the changeset viewer.

