DevSmc.cpp revision 6d8d7a488de9409b06ba73c63c99d53e28d19645
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster * DevSmc - Apple System Manaagement Controller.
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster * The SMC is controlling power, fans, take measurements (voltage, temperature,
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster * fan speed, ++), and lock Mac OS X to Apple hardware. For more details see:
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster * - http://en.wikipedia.org/wiki/System_Management_Controller
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster * - http://www.parhelia.ch/blog/statics/k3_keys.html
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster * - http://www.nosuchcon.org/talks/D1_02_Alex_Ninjas_and_Harry_Potter.pdf
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster * Copyright (C) 2013 Oracle Corporation
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster * This file is part of VirtualBox Open Source Edition (OSE), as
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster * available from http://www.virtualbox.org. This file is free software;
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster * you can redistribute it and/or modify it under the terms of the GNU
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster * General Public License (GPL) as published by the Free Software
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster * Foundation, in version 2 as it comes in the "COPYING" file of the
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster * VirtualBox OSE distribution. VirtualBox OSE is distributed in the
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster * hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster/*******************************************************************************
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster* Header Files *
1c3134bddb7b413373d1668cbc4b7d95c2477667Mark de Reeper*******************************************************************************/
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster/*******************************************************************************
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster* Defined Constants And Macros *
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster*******************************************************************************/
c184142912cff04e5442d8bf70febe477285fb1cCraig McDonnell/** The current version of the saved state. */
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster#define SMC_SAVED_STATE_VERSION 1 /** @todo later 2 */
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster/** Empty saved state version. */
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster/** The ring-0 operation number that attempts to get OSK0 and OSK1 from the real
0c893a059f84246bf91e2f0fbf63e4c92f8e5165Tony Bamford/** @name Apple SMC port and register definitions.
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster/** The first Apple SMC port. */
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster/** The number of registers (also ports). */
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster/** The data register. */
35ab1c5bca11317474fe12bdd8d22c17cdaf2697Robert Wapshott#define SMC_PORT_DATA (SMC_PORT_FIRST + SMC_REG_DATA)
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster/** The command register. */
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster#define SMC_PORT_CMD (SMC_PORT_FIRST + SMC_REG_CMD)
0c893a059f84246bf91e2f0fbf63e4c92f8e5165Tony Bamford/** Status code register. */
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster#define SMC_PORT_STATUS_CODE (SMC_PORT_FIRST + SMC_REG_STATUS_CODE)
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster/** @name Apple SMC Commands.
35ab1c5bca11317474fe12bdd8d22c17cdaf2697Robert Wapshott/** @name Apple SMC Status Codes.
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster#define SMC_STATUS_CD_COMM_COLLISION UINT8_C(0x80)
35ab1c5bca11317474fe12bdd8d22c17cdaf2697Robert Wapshott#define SMC_STATUS_CD_SPURIOUS_DATA UINT8_C(0x81)
35ab1c5bca11317474fe12bdd8d22c17cdaf2697Robert Wapshott#define SMC_STATUS_CD_BAD_COMMAND UINT8_C(0x82)
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster#define SMC_STATUS_CD_BAD_PARAMETER UINT8_C(0x83)
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster#define SMC_STATUS_CD_KEY_NOT_FOUND UINT8_C(0x84)
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster#define SMC_STATUS_CD_KEY_NOT_READABLE UINT8_C(0x85)
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster#define SMC_STATUS_CD_KEY_NOT_WRITABLE UINT8_C(0x86)
0c893a059f84246bf91e2f0fbf63e4c92f8e5165Tony Bamford#define SMC_STATUS_CD_KEY_SIZE_MISMATCH UINT8_C(0x87)
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster#define SMC_STATUS_CD_FRAMING_ERROR UINT8_C(0x88)
0c893a059f84246bf91e2f0fbf63e4c92f8e5165Tony Bamford#define SMC_STATUS_CD_BAD_ARGUMENT_ERROR UINT8_C(0x89)
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster#define SMC_STATUS_CD_TIMEOUT_ERROR UINT8_C(0xb7)
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster#define SMC_STATUS_CD_KEY_INDEX_RANGE_ERROR UINT8_C(0xb8)
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster#define SMC_STATUS_CD_BAD_FUNC_PARAMETER UINT8_C(0xc0)
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster#define SMC_STATUS_CD_EVENT_BUFF_WRONG_ORDER UINT8_C(0x??)
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster#define SMC_STATUS_CD_EVENT_BUFF_READ_ERROR UINT8_C(0x??)
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster#define SMC_STATUS_CD_DEVICE_ACCESS_ERROR UINT8_C(0xc7)
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster#define SMC_STATUS_CD_UNSUPPORTED_FEATURE UINT8_C(0xcb)
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster#define SMC_STATUS_CD_SMB_ACCESS_ERROR UINT8_C(0xcc)
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster/** @name Apple SMC Key Attributes.
35ab1c5bca11317474fe12bdd8d22c17cdaf2697Robert Wapshott/** The index of the first enumerable key in g_aSmcKeys. */
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster/** Macro for emitting a static DEVSMC4CHID initializer. */
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster#define SMC4CH(a_sz4) { { a_sz4[0], a_sz4[1], a_sz4[2], a_sz4[3] } }
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster * Macro for comparing DEVSMC4CHID with a string value.
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster * @returns true if equal, false if not.
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster#define SMC4CH_EQ(a_pSmcKey, a_sz4) ( (a_pSmcKey)->u32 == RT_MAKE_U32_FROM_U8(a_sz4[0], a_sz4[1], a_sz4[2], a_sz4[3]) )
35ab1c5bca11317474fe12bdd8d22c17cdaf2697Robert Wapshott/** Indicates the we want a 2.x SMC. */
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster/*******************************************************************************
35ab1c5bca11317474fe12bdd8d22c17cdaf2697Robert Wapshott* Structures and Typedefs *
35ab1c5bca11317474fe12bdd8d22c17cdaf2697Robert Wapshott*******************************************************************************/
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster * 4 char identifier
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster /** Byte view. */
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster /** 32-bit unsigned integer view. */
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster * Current key data area for communicating with the guest.
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster /** The key. */
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster /** The data type. */
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster /** Key attributes. */
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster /** The value length. */
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster * The value union. 32 bytes is probably sufficient here, but we provide a
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster * little more room since it doesn't cost us anything. */
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster /** Byte view. */
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster /** 16-bit view. */
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster /** 32-bit view. */
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster/** Pointer to the current key buffer. */
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster/** Const pointer to the current key buffer. */
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster * The device
8af80418ba1ec431c8027fa9668e5678658d3611Allan Fostertypedef struct DEVSMC
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster /** The current command (SMC_PORT_CMD write). */
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster /** Current key offset. */
0c893a059f84246bf91e2f0fbf63e4c92f8e5165Tony Bamford /** Current value offset. */
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster /** Number of keys in the aKeys array. */
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster /** The current key data the user is accessing. */
35ab1c5bca11317474fe12bdd8d22c17cdaf2697Robert Wapshott * Generic read/write register values.
4dc32d1e92477080fa1652a865cadc3f63ae04edBrian Bailey * The DATA register entry is not used at all. The CMD register entry contains
3e9693aa1fe0454cabcfcf9020cf1db11258946eBrian Bailey * the state value.
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster /** Index register view. */
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster /** Named register view. */
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster /** The current state (SMC_PORT_CMD read). */
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster /** The current status code (SMC_PORT_STATUS_CODE). */
35ab1c5bca11317474fe12bdd8d22c17cdaf2697Robert Wapshott /** @name Key data.
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster /** OSK0 and OSK1. */
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster /** $Num - unknown function. */
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster /** MSSD - shutdown reason. */
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster /** NATJ - Ninja action timer job. */
8af80418ba1ec431c8027fa9668e5678658d3611Allan FosterAssertCompileMembersAtSameOffset(DEVSMC, u.abRegsRW[SMC_REG_CMD], DEVSMC, u.s.bState);
8af80418ba1ec431c8027fa9668e5678658d3611Allan FosterAssertCompileMembersAtSameOffset(DEVSMC, u.abRegsRW[SMC_REG_STATUS_CODE], DEVSMC, u.s.bStatusCode);
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster/** Pointer to the SMC state. */
35ab1c5bca11317474fe12bdd8d22c17cdaf2697Robert Wapshott * Method for retriving the key value and/or optionally also attributes.
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster * @returns Apple SMC Status Code.
35ab1c5bca11317474fe12bdd8d22c17cdaf2697Robert Wapshott * @param pThis The SMC instance data.
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster * @param pCurKey The current key structure (input / output).
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster * @param bCmd The current command (mostly for getters that also
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster * provides attributes or type info).
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster * @param pKeyDesc Pointer to the key descriptor so that the getter can
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster * service more than once key.
8af80418ba1ec431c8027fa9668e5678658d3611Allan Fostertypedef DECLCALLBACK(uint8_t) DEVSMCKEYGETTER(PDEVSMC pThis, PDEVSMCCURKEY pCurKey, uint8_t bCmd,
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster * Method for setting the key value.
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster * @returns Apple SMC Status Code.
0c893a059f84246bf91e2f0fbf63e4c92f8e5165Tony Bamford * @param pThis The SMC instance data.
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster * @param pCurKey The current key structure (input / output).
0c893a059f84246bf91e2f0fbf63e4c92f8e5165Tony Bamford * @param bCmd The current command (currently not relevant).
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster * @param pKeyDesc Pointer to the key descriptor so that the getter can
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster * service more than once key.
8af80418ba1ec431c8027fa9668e5678658d3611Allan Fostertypedef DECLCALLBACK(uint8_t) DEVSMCKEYPUTTER(PDEVSMC pThis, PCDEVSMCCURKEY pCurKey, uint8_t bCmd,
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster * Key descriptor.
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster /** The key 4 character identifier. */
0c893a059f84246bf91e2f0fbf63e4c92f8e5165Tony Bamford /** Type 4 character identifier. 0 means the getter will set it dynamically. */
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster /** Getter method, see DEVSMCKEYPUTTER. */
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster /** Putter method, see DEVSMCKEYPUTTER. */
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster /** The keyvalue size. If 0 the pfnGet/pfnPut will define/check the size. */
35ab1c5bca11317474fe12bdd8d22c17cdaf2697Robert Wapshott /** Attributes. 0 means the getter will set it dynamically. */
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster/** Pointer to a constant SMC key descriptor. */
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster/*******************************************************************************
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster* Internal Functions *
0c893a059f84246bf91e2f0fbf63e4c92f8e5165Tony Bamford*******************************************************************************/
35ab1c5bca11317474fe12bdd8d22c17cdaf2697Robert Wapshottstatic DEVSMCKEYPUTTER scmKeyPutDollarNumber;
8af80418ba1ec431c8027fa9668e5678658d3611Allan Fosterstatic DEVSMCKEYGETTER scmKeyGetNinjaTimerAction;
8af80418ba1ec431c8027fa9668e5678658d3611Allan Fosterstatic DEVSMCKEYPUTTER scmKeyPutNinjaTimerAction;
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster/*******************************************************************************
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster* Global Variables *
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster*******************************************************************************/
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster * Apple SMC key descriptor table.
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster /* Non-enum keys first. */
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster { SMC4CH("OSK0"), SMC4CH("ch8*"), scmKeyGetOSKs, NULL, 32, SMC_KEY_ATTR_READ | SMC_KEY_ATTR_FUNCTION },
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster { SMC4CH("OSK1"), SMC4CH("ch8*"), scmKeyGetOSKs, NULL, 32, SMC_KEY_ATTR_READ | SMC_KEY_ATTR_FUNCTION },
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster /* The first enum key is the #KEY value. */
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster { SMC4CH("#KEY"), SMC4CH("ui32"), scmKeyGetKeyCount, NULL, 4, SMC_KEY_ATTR_READ },
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster { SMC4CH("$Adr"), SMC4CH("ui32"), scmKeyGetDollarAddress, NULL, 4, SMC_KEY_ATTR_READ },
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster { SMC4CH("$Num"), SMC4CH("ui8 "), scmKeyGetDollarNumber, scmKeyPutDollarNumber, 1, SMC_KEY_ATTR_READ | SMC_KEY_ATTR_WRITE | SMC_KEY_ATTR_PRIVATE },
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster { SMC4CH("BEMB"), SMC4CH("flag"), scmKeyGetOne, NULL, 1, SMC_KEY_ATTR_READ },
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster { SMC4CH("LSOF"), SMC4CH("flag"), scmKeyGetZero, NULL, 1, SMC_KEY_ATTR_READ },
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster { SMC4CH("MSSD"), SMC4CH("si8 "), scmKeyGetShutdownReason, scmKeyPutShutdownReason, 1, SMC_KEY_ATTR_READ | SMC_KEY_ATTR_WRITE | SMC_KEY_ATTR_PRIVATE },
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster /* MSDS is not present on MacPro3,1 nor MacBookPro10,1, so returning not found is fine. */
35ab1c5bca11317474fe12bdd8d22c17cdaf2697Robert Wapshott { SMC4CH("MSTf"), SMC4CH("ui8 "), scmKeyGetZero, NULL, 1, SMC_KEY_ATTR_READ },
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster { SMC4CH("NATJ"), SMC4CH("ui8 "), scmKeyGetNinjaTimerAction, scmKeyPutNinjaTimerAction, 1, SMC_KEY_ATTR_READ | SMC_KEY_ATTR_WRITE | SMC_KEY_ATTR_PRIVATE },
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster { SMC4CH("REV "), SMC4CH("{rev"), scmKeyGetRevision, NULL, 6, SMC_KEY_ATTR_READ },
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster/** @todo MSSP, NTOK and more. */
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster/** Do once for the SMC ring-0 static data (g_abOsk0And1, g_fHaveOsk). */
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster/** Indicates whether we've successfully queried the OSK* keys. */
8af80418ba1ec431c8027fa9668e5678658d3611Allan Fosterstatic bool g_fHaveOsk = false;
35ab1c5bca11317474fe12bdd8d22c17cdaf2697Robert Wapshott/** The OSK0 and OSK1 values. */
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster * Waits for the specified state on the host SMC.
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster * @returns success indicator.
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster * @param bState The desired state.
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster * @param pszWhat What we're currently doing. For the log.
8af80418ba1ec431c8027fa9668e5678658d3611Allan Fosterstatic bool devR0SmcWaitHostState(uint8_t bState, const char *pszWhat)
35ab1c5bca11317474fe12bdd8d22c17cdaf2697Robert Wapshott for (uint32_t cMsSleep = 1; cMsSleep <= 64; cMsSleep <<= 1)
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster return true;
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster LogRel(("devR0Smc: %s: bCurState=%#x, wanted %#x.\n", pszWhat, bCurState, bState));
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster uint8_t bCurStatus2 = ASMInU8(SMC_PORT_STATUS_CODE);
35ab1c5bca11317474fe12bdd8d22c17cdaf2697Robert Wapshott uint8_t bCurStatus3 = ASMInU8(SMC_PORT_STATUS_CODE);
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster uint16_t wCurStatus3 = ASMInU16(SMC_PORT_STATUS_CODE);
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster uint32_t dwCurStatus3 = ASMInU32(SMC_PORT_STATUS_CODE);
0c893a059f84246bf91e2f0fbf63e4c92f8e5165Tony Bamford LogRel(("SMC: status2=%#x status3=%#x w=%#x dw=%#x\n", bCurStatus2, bCurStatus3, wCurStatus3, dwCurStatus3));
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster return false;
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster * Reads a key by name from the host SMC.
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster * @returns success indicator.
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster * @param pszName The key name, must be exactly 4 chars long.
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster * @param pbBuf The output buffer.
0c893a059f84246bf91e2f0fbf63e4c92f8e5165Tony Bamford * @param cbBuf The buffer size. Max 32 bytes.
8af80418ba1ec431c8027fa9668e5678658d3611Allan Fosterstatic bool devR0SmcQueryHostKey(const char *pszName, uint8_t *pbBuf, size_t cbBuf)
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster * Issue the READ command.
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster ASMOutU32(SMC_PORT_CMD, SMC_CMD_GET_KEY_VALUE);
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster LogRel(("devR0Smc: %s: bCurState=%#x, wanted %#x.\n", "cmd", bCurState, 0xc));
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster return false;
35ab1c5bca11317474fe12bdd8d22c17cdaf2697Robert Wapshott * Send it the key.
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster return false;
35ab1c5bca11317474fe12bdd8d22c17cdaf2697Robert Wapshott * The desired amount of output.
35ab1c5bca11317474fe12bdd8d22c17cdaf2697Robert Wapshott * Read the output.
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster if (!devR0SmcWaitHostState(5, off ? "data" : "len"))
0c893a059f84246bf91e2f0fbf63e4c92f8e5165Tony Bamford return false;
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster return true;
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster * RTOnce callback that initializes g_fHaveOsk and g_abOsk0And1.
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster * @returns VINF_SUCCESS.
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster * @param pvUserIgnored Ignored.
8af80418ba1ec431c8027fa9668e5678658d3611Allan Fosterstatic DECLCALLBACK(int) devR0SmcInitOnce(void *pvUserIgnored)
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster g_fHaveOsk = devR0SmcQueryHostKey("OSK0", &g_abOsk0And1[0], 32)
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster && devR0SmcQueryHostKey("OSK1", &g_abOsk0And1[32], 32);
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster * Dump the device registers.
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster for (uint16_t uPort = 0x300; uPort < 0x320; uPort ++)
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster LogRel(("SMC: %#06x=%#010x w={%#06x, %#06x}, b={%#04x %#04x %#04x %#04x}\n", uPort,
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster ASMInU32(uPort), ASMInU16(uPort), ASMInU16(uPort + 2),
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster ASMInU8(uPort), ASMInU8(uPort + 1), ASMInU8(uPort +2), ASMInU8(uPort + 3) ));
0c893a059f84246bf91e2f0fbf63e4c92f8e5165Tony Bamford * @callback_method_impl{FNPDMDEVREQHANDLERR0}
0c893a059f84246bf91e2f0fbf63e4c92f8e5165Tony BamfordPDMBOTHCBDECL(int) devR0SmcReqHandler(PPDMDEVINS pDevIns, uint32_t uOperation, uint64_t u64Arg)
0c893a059f84246bf91e2f0fbf63e4c92f8e5165Tony Bamford PDEVSMC pThis = PDMINS_2_DATA(pDevIns, PDEVSMC);
0c893a059f84246bf91e2f0fbf63e4c92f8e5165Tony Bamford rc = RTOnce(&g_SmcR0Once, devR0SmcInitOnce, NULL);
fa03f17e603602dd9503a88cec3c310072c93ccaCraig McDonnell AssertCompile(sizeof(g_abOsk0And1) + 1 == sizeof(pThis->szOsk0And1));
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster memcpy(pThis->szOsk0And1, g_abOsk0And1, sizeof(pThis->szOsk0And1) - 1);
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster pThis->szOsk0And1[sizeof(pThis->szOsk0And1) - 1] = '\0';
0c893a059f84246bf91e2f0fbf63e4c92f8e5165Tony Bamford#endif /* IN_RING0 */
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster/** @callback_method_impl{DEVSMCKEYGETTER, OSK0 and OSK1} */
8af80418ba1ec431c8027fa9668e5678658d3611Allan Fosterstatic uint8_t scmKeyGetOSKs(PDEVSMC pThis, PDEVSMCCURKEY pCurKey, uint8_t bCmd, PCDEVSMCKEYDESC pKeyDesc)
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster Assert(SMC4CH_EQ(&pKeyDesc->Key, "OSK0") || SMC4CH_EQ(&pKeyDesc->Key, "OSK1"));
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster/** @callback_method_impl{DEVSMCKEYGETTER, \#KEY} */
8af80418ba1ec431c8027fa9668e5678658d3611Allan Fosterstatic uint8_t scmKeyGetKeyCount(PDEVSMC pThis, PDEVSMCCURKEY pCurKey, uint8_t bCmd, PCDEVSMCKEYDESC pKeyDesc)
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster Assert(pKeyDesc == &g_aSmcKeys[SMC_KEYIDX_FIRST_ENUM]);
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster uint32_t cKeys = RT_ELEMENTS(g_aSmcKeys) - SMC_KEYIDX_FIRST_ENUM;
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster/** @callback_method_impl{DEVSMCKEYGETTER, REV - Source revision.} */
8af80418ba1ec431c8027fa9668e5678658d3611Allan Fosterstatic uint8_t scmKeyGetRevision(PDEVSMC pThis, PDEVSMCCURKEY pCurKey, uint8_t bCmd, PCDEVSMCKEYDESC pKeyDesc)
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster/** @callback_method_impl{DEVSMCKEYGETTER, $Adr - SMC address.} */
8af80418ba1ec431c8027fa9668e5678658d3611Allan Fosterstatic uint8_t scmKeyGetDollarAddress(PDEVSMC pThis, PDEVSMCCURKEY pCurKey, uint8_t bCmd, PCDEVSMCKEYDESC pKeyDesc)
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster pCurKey->Value.u32 = RT_H2BE_U32(SMC_PORT_FIRST);
35ab1c5bca11317474fe12bdd8d22c17cdaf2697Robert Wapshott/** @callback_method_impl{DEVSMCKEYGETTER, $Num - Some kind of number.} */
8af80418ba1ec431c8027fa9668e5678658d3611Allan Fosterstatic uint8_t scmKeyGetDollarNumber(PDEVSMC pThis, PDEVSMCCURKEY pCurKey, uint8_t bCmd, PCDEVSMCKEYDESC pKeyDesc)
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster/** @callback_method_impl{DEVSMCKEYPUTTER, $Num - Some kind of number.} */
8af80418ba1ec431c8027fa9668e5678658d3611Allan Fosterstatic uint8_t scmKeyPutDollarNumber(PDEVSMC pThis, PCDEVSMCCURKEY pCurKey, uint8_t bCmd, PCDEVSMCKEYDESC pKeyDesc)
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster Log(("scmKeyPutDollarNumber: %#x -> %#x\n", pThis->bDollaryNumber, pCurKey->Value.ab[0]));
35ab1c5bca11317474fe12bdd8d22c17cdaf2697Robert Wapshott#endif /* VBOX_WITH_SMC_2_x */
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster/** @callback_method_impl{DEVSMCKEYGETTER, MSSD - Machine Shutdown reason.} */
8af80418ba1ec431c8027fa9668e5678658d3611Allan Fosterstatic uint8_t scmKeyGetShutdownReason(PDEVSMC pThis, PDEVSMCCURKEY pCurKey, uint8_t bCmd, PCDEVSMCKEYDESC pKeyDesc)
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster/** @callback_method_impl{DEVSMCKEYPUTTER, MSSD - Machine Shutdown reason.} */
35ab1c5bca11317474fe12bdd8d22c17cdaf2697Robert Wapshottstatic uint8_t scmKeyPutShutdownReason(PDEVSMC pThis, PCDEVSMCCURKEY pCurKey, uint8_t bCmd, PCDEVSMCKEYDESC pKeyDesc)
35ab1c5bca11317474fe12bdd8d22c17cdaf2697Robert Wapshott Log(("scmKeyPutShutdownReason: %#x -> %#x\n", pThis->bShutdownReason, pCurKey->Value.ab[0]));
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster/** @callback_method_impl{DEVSMCKEYGETTER, MSSD - Ninja timer action job.} */
8af80418ba1ec431c8027fa9668e5678658d3611Allan Fosterstatic uint8_t scmKeyGetNinjaTimerAction(PDEVSMC pThis, PDEVSMCCURKEY pCurKey, uint8_t bCmd, PCDEVSMCKEYDESC pKeyDesc)
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster pCurKey->Value.ab[0] = pThis->bNinjaActionTimerJob;
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster/** @callback_method_impl{DEVSMCKEYPUTTER, NATJ - Ninja timer action job.} */
8af80418ba1ec431c8027fa9668e5678658d3611Allan Fosterstatic uint8_t scmKeyPutNinjaTimerAction(PDEVSMC pThis, PCDEVSMCCURKEY pCurKey, uint8_t bCmd, PCDEVSMCKEYDESC pKeyDesc)
35ab1c5bca11317474fe12bdd8d22c17cdaf2697Robert Wapshott Log(("scmKeyPutNinjaTimerAction: %#x -> %#x\n", pThis->bNinjaActionTimerJob, pCurKey->Value.ab[0]));
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster pThis->bNinjaActionTimerJob = pCurKey->Value.ab[0];
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster/** @callback_method_impl{DEVSMCKEYGETTER, Generic one getter.} */
8af80418ba1ec431c8027fa9668e5678658d3611Allan Fosterstatic uint8_t scmKeyGetOne(PDEVSMC pThis, PDEVSMCCURKEY pCurKey, uint8_t bCmd, PCDEVSMCKEYDESC pKeyDesc)
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster memset(&pCurKey->Value.ab[0], 0, pKeyDesc->cbValue);
return SMC_STATUS_CD_SUCCESS;
static uint8_t scmKeyGetZero(PDEVSMC pThis, PDEVSMCCURKEY pCurKey, uint8_t bCmd, PCDEVSMCKEYDESC pKeyDesc)
return SMC_STATUS_CD_SUCCESS;
while (iKey-- > 0)
return iKey;
return UINT32_MAX;
#ifdef LOG_ENABLED
return SMC_STATUS_CD_SUCCESS;
Log(("smcKeyGetByName: Key not found! key=%4.4s size=%#x\n", &uKeyValueLog, pThis->CurKey.cbValue));
return bRc;
pThis->CurKey.Key.ab[3], pThis->CurKey.Key.ab[2], pThis->CurKey.Key.ab[1], pThis->CurKey.Key.ab[0]));
Log(("smcKeyGetByIndex: Key out or range: %#x, max %#x\n", iKey, RT_ELEMENTS(g_aSmcKeys) - SMC_KEYIDX_FIRST_ENUM));
return bRc;
#ifdef LOG_ENABLED
return SMC_STATUS_CD_SUCCESS;
Log(("smcKeyGetAttrByName: Key not found! key=%4.4s size=%#x\n", &uKeyValueLog, pThis->CurKey.cbValue));
return bRc;
case SMC_CMD_GET_KEY_VALUE:
Log(("smcRegData_r: Reading too much or at wrong time during SMC_CMD_GET_KEY_INFO! bState=%#x offValue=%#x\n",
case SMC_CMD_GET_KEY_INFO:
Log(("smcRegData_r: Reading too much or at wrong time during SMC_CMD_GET_KEY_INFO! bState=%#x offValue=%#x\n",
case SMC_CMD_GET_KEY_BY_INDEX:
Log(("smcRegData_r: Reading too much or at wrong time during GET_KEY_BY_INDEX! bState=%#x offValue=%#x\n",
case SMC_CMD_PUT_KEY:
return VINF_SUCCESS;
case SMC_CMD_GET_KEY_VALUE:
case SMC_CMD_PUT_KEY:
Log(("smcRegData_w: Writing too much data on %s command!\n", pThis->bCmd == SMC_CMD_PUT_KEY ? "put" : "get"));
case SMC_CMD_GET_KEY_INFO:
case SMC_CMD_GET_KEY_BY_INDEX:
return VINF_SUCCESS;
switch (bValue)
case SMC_CMD_GET_KEY_VALUE:
case SMC_CMD_PUT_KEY:
case SMC_CMD_GET_KEY_BY_INDEX:
case SMC_CMD_GET_KEY_INFO:
return VINF_SUCCESS;
return VINF_SUCCESS;
return VINF_SUCCESS;
return VINF_SUCCESS;
return VINF_SUCCESS;
PDMBOTHCBDECL(int) smcIoPortWrite(PPDMDEVINS pDevIns, void *pvUser, RTIOPORT Port, uint32_t u32, unsigned cb)
#ifndef IN_RING3
return VINF_IOM_R3_IOPORT_WRITE;
cb--;
uReg++;
return rc;
PDMBOTHCBDECL(int) smcIoPortRead(PPDMDEVINS pDevIns, void *pvUser, RTIOPORT Port, uint32_t *pu32, unsigned cb)
#ifndef IN_RING3
return VINF_IOM_R3_IOPORT_READ;
cb--;
uReg++;
return rc;
#ifdef IN_RING3
return VINF_SUCCESS;
static DECLCALLBACK(int) smcLoadExec(PPDMDEVINS pDevIns, PSSMHANDLE pSSM, uint32_t uVersion, uint32_t uPass)
return VINF_SUCCESS;
bool fGetKeyFromRealSMC;
if (fGetKeyFromRealSMC)
rc = PDMDevHlpSSMRegister(pDevIns, SMC_SAVED_STATE_VERSION, sizeof(*pThis), smcSaveExec, smcLoadExec);
return rc;
return VINF_SUCCESS;
PDM_DEVREG_FLAGS_HOST_BITS_DEFAULT | PDM_DEVREG_FLAGS_GUEST_BITS_DEFAULT | PDM_DEVREG_FLAGS_R0 | PDM_DEVREG_FLAGS_RC,
sizeof(DEVSMC),
NULL,
NULL,
NULL,
NULL,
NULL,
NULL,
NULL,
NULL,
NULL,
NULL,
NULL,
NULL,
NULL,