VirtualBox

Ignore:
Timestamp:
Aug 3, 2021 10:16:28 AM (3 years ago)
Author:
vboxsync
Message:

Devices: Rename TPM directory to Security, bugref:10075

Location:
trunk/src/VBox/Devices/Security
Files:
1 edited
1 moved

Legend:

Unmodified
Added
Removed
  • trunk/src/VBox/Devices/Security/DevTpm.cpp

    r90465 r90492  
    33 * DevTpm - Trusted Platform Module emulation.
    44 *
    5  * This emulation is based on the spec available under (as of 2021-07-30):
    6  *     https://trustedcomputinggroup.org/wp-content/uploads/TCG_PCClientTPMInterfaceSpecification_TIS__1-3_27_03212013.pdf
     5 * This emulation is based on the spec available under (as of 2021-08-02):
     6 *     https://trustedcomputinggroup.org/wp-content/uploads/PC-Client-Specific-Platform-TPM-Profile-for-TPM-2p0-v1p05p_r14_pub.pdf
    77 */
    88
     
    5252/** Number of localities as mandated by the TPM spec. */
    5353#define TPM_LOCALITY_COUNT                              5
    54 /** Size of each locality in the TPM MMIO area (chapter 5.2).*/
     54/** Size of each locality in the TPM MMIO area (chapter 6.5.2).*/
    5555#define TPM_LOCALITY_MMIO_SIZE                          0x1000
    5656
     
    7272/** On reads indicates whether this locality is active (1) or not (0), writing a 1 relinquishes control for this locality. */
    7373# define TPM_LOCALITY_REG_ACCESS_ACTIVE                 RT_BIT(5)
    74 /** Set bit indicates whether all other bits in the status register have valid data. */
    75 # define TPM_LOCALITY_REG_ACCESS_STS_VALID              RT_BIT(7)
     74/** Set bit indicates whether all other bits in this register have valid data. */
     75# define TPM_LOCALITY_REG_ACCESS_VALID                  RT_BIT(7)
     76/** Writable mask. */
     77# define TPM_LOCALITY_REG_ACCESS_WR_MASK                0x3a
    7678
    7779/** Interrupt enable register. */
     
    114116/** Command ready occured bit, writing a 1 clears the bit. */
    115117# define TPM_LOCALITY_REG_INT_STS_CMD_RDY               RT_BIT_32(7)
     118/** Writable mask. */
     119# define TPM_LOCALITY_REG_INT_STS_WR_MASK               UINT32_C(0x87)
    116120
    117121/** Interfacce capabilities register. */
     
    154158#  define TPM_LOCALITY_REG_IF_CAP_IF_VERSION_IF_1_21    0
    155159/** Interface 1.3. */
    156 #  define TPM_LOCALITY_REG_IF_CAP_IF_VERSION_IF_1_3     1
     160#  define TPM_LOCALITY_REG_IF_CAP_IF_VERSION_IF_1_3     2
     161/** Interface 1.3 for TPM 2.0. */
     162#  define TPM_LOCALITY_REG_IF_CAP_IF_VERSION_IF_1_3_TPM2    3
    157163
    158164/** TPM status register. */
     
    197203
    198204/**
     205 * Possible locality states
     206 * (see chapter 5.6.12.1 Figure 3 State Transition Diagram).
     207 */
     208typedef enum DEVTPMLOCALITYSTATE
     209{
     210    /** Invalid state, do not use. */
     211    DEVTPMLOCALITYSTATE_INVALID = 0,
     212    /** Init state. */
     213    DEVTPMLOCALITYSTATE_INIT,
     214    /** Ready to accept command data. */
     215    DEVTPMLOCALITYSTATE_READY,
     216    /** Command data being transfered. */
     217    DEVTPMLOCALITYSTATE_CMD_RECEPTION,
     218    /** Command is being executed by the TPM. */
     219    DEVTPMLOCALITYSTATE_CMD_EXEC,
     220    /** Command has completed and data can be read. */
     221    DEVTPMLOCALITYSTATE_CMD_COMPLETION,
     222    /** 32bit hack. */
     223    DEVTPMLOCALITYSTATE_32BIT_HACK = 0x7fffffff
     224} DEVTPMLOCALITYSTATE;
     225
     226
     227/**
    199228 * Locality state.
    200229 */
    201230typedef struct DEVTPMLOCALITY
    202231{
     232    /** The current state of the locality. */
     233    DEVTPMLOCALITYSTATE             enmState;
     234    /** Access register state. */
     235    uint32_t                        uRegAccess;
    203236    /** The interrupt enable register. */
    204237    uint32_t                        uRegIntEn;
     
    226259    uint8_t                         uIrq;
    227260
     261    /** Currently selected locality. */
     262    uint8_t                         bLoc;
    228263    /** States of the implemented localities. */
    229264    DEVTPMLOCALITY                  aLoc[TPM_LOCALITY_COUNT];
     
    232267/** Pointer to the shared TPM device state. */
    233268typedef DEVTPM *PDEVTPM;
     269
     270/** The special no current locality selected value. */
     271#define TPM_NO_LOCALITY_SELECTED    0xff
    234272
    235273
     
    276314
    277315
    278 #if 0
    279 PDMBOTHCBDECL(void) tpmIrqReq(PPDMDEVINS pDevIns, int iLvl)
    280 {
    281     PDEVTPM pThis = PDMDEVINS_2_DATA(pDevIns, PDEVTPM);
     316/**
     317 * Sets the IRQ line of the given device to the given state.
     318 *
     319 * @returns nothing.
     320 * @param   pDevIns             Pointer to the PDM device instance data.
     321 * @param   pThis               Pointer to the shared TPM device.
     322 * @param   iLvl                The interrupt level to set.
     323 */
     324DECLINLINE(void) tpmIrqReq(PPDMDEVINS pDevIns, PDEVTPM pThis, int iLvl)
     325{
    282326    PDMDevHlpISASetIrqNoWait(pDevIns, pThis->uIrq, iLvl);
    283327}
    284 #endif
    285 
    286 
     328
     329
     330/**
     331 * Updates the IRQ status of the given locality.
     332 *
     333 * @returns nothing.
     334 * @param   pDevIns             Pointer to the PDM device instance data.
     335 * @param   pThis               Pointer to the shared TPM device.
     336 * @param   pLoc                The locality state.
     337 */
     338PDMBOTHCBDECL(void) tpmLocIrqUpdate(PPDMDEVINS pDevIns, PDEVTPM pThis, PDEVTPMLOCALITY pLoc)
     339{
     340    if (pLoc->uRegIntEn & pLoc->uRegIntSts)
     341        tpmIrqReq(pDevIns, pThis, 1);
     342    else
     343        tpmIrqReq(pDevIns, pThis, 0);
     344}
     345
     346
     347/**
     348 * Returns the given locality being accessed from the given TPM MMIO offset.
     349 *
     350 * @returns Locality number.
     351 * @param   off                 The offset into the TPM MMIO region.
     352 */
    287353DECLINLINE(uint8_t) tpmGetLocalityFromOffset(RTGCPHYS off)
    288354{
     
    291357
    292358
     359/**
     360 * Returns the given register of a particular locality being accessed from the given TPM MMIO offset.
     361 *
     362 * @returns Register index being accessed.
     363 * @param   off                 The offset into the TPM MMIO region.
     364 */
    293365DECLINLINE(uint32_t) tpmGetRegisterFromOffset(RTGCPHYS off)
    294366{
     
    313385    VBOXSTRICTRC rc = VINF_SUCCESS;
    314386    uint32_t uReg = tpmGetRegisterFromOffset(off);
    315     uint8_t uLoc = tpmGetLocalityFromOffset(off);
    316     PDEVTPMLOCALITY pLoc = &pThis->aLoc[uLoc];
     387    uint8_t bLoc = tpmGetLocalityFromOffset(off);
     388    PDEVTPMLOCALITY pLoc = &pThis->aLoc[bLoc];
    317389    uint32_t u32;
    318390    switch (uReg)
    319391    {
     392        case TPM_LOCALITY_REG_ACCESS:
     393            u32 = 0;
     394            break;
    320395        case TPM_LOCALITY_REG_INT_ENABLE:
    321396            u32 = pLoc->uRegIntEn;
    322397            break;
     398        case TPM_LOCALITY_REG_INT_VEC:
     399            u32 = pThis->uIrq;
     400            break;
    323401        case TPM_LOCALITY_REG_INT_STS:
    324402            u32 = pLoc->uRegIntSts;
     403            break;
     404        case TPM_LOCALITY_REG_IF_CAP:
     405            u32 =   TPM_LOCALITY_REG_IF_CAP_INT_DATA_AVAIL
     406                  | TPM_LOCALITY_REG_IF_CAP_INT_STS_VALID
     407                  | TPM_LOCALITY_REG_IF_CAP_INT_LOCALITY_CHANGE
     408                  | TPM_LOCALITY_REG_IF_CAP_INT_LVL_LOW
     409                  | TPM_LOCALITY_REG_IF_CAP_INT_CMD_RDY
     410                  | TPM_LOCALITY_REG_IF_CAP_DATA_XFER_SZ_SET(TPM_LOCALITY_REG_IF_CAP_DATA_XFER_SZ_64B)
     411                  | TPM_LOCALITY_REG_IF_CAP_IF_VERSION_SET(TPM_LOCALITY_REG_IF_CAP_IF_VERSION_IF_1_3); /** @todo Make some of them configurable? */
     412            break;
     413        case TPM_LOCALITY_REG_STS:
     414            if (bLoc != pThis->bLoc)
     415            {
     416                u32 = UINT32_MAX;
     417                break;
     418            }
     419            /** @todo */
     420            break;
     421        case TPM_LOCALITY_REG_DATA_FIFO:
     422        case TPM_LOCALITY_REG_DATA_XFIFO:
     423            /** @todo */
    325424            break;
    326425        case TPM_LOCALITY_REG_DID_VID:
     
    368467    LogFlowFunc((": %RGp %#x\n", off, u32));
    369468
     469    VBOXSTRICTRC rc = VINF_SUCCESS;
    370470    uint32_t uReg = tpmGetRegisterFromOffset(off);
    371     uint8_t uLoc = tpmGetLocalityFromOffset(off);
    372     PDEVTPMLOCALITY pLoc = &pThis->aLoc[uLoc];
    373     RT_NOREF(uReg, uLoc, pLoc);
    374 
    375     VBOXSTRICTRC rc = VINF_SUCCESS;
     471    uint8_t bLoc = tpmGetLocalityFromOffset(off);
     472    PDEVTPMLOCALITY pLoc = &pThis->aLoc[bLoc];
     473    switch (uReg)
     474    {
     475        case TPM_LOCALITY_REG_ACCESS:
     476            u32 &= TPM_LOCALITY_REG_ACCESS_WR_MASK;
     477             /*
     478              * Chapter 5.6.11, 2 states that writing to this register with more than one
     479              * bit set to '1' is vendor specific, we decide to ignore such writes to make the logic
     480              * below simpler.
     481              */
     482            if (!RT_IS_POWER_OF_TWO(u32))
     483                break;
     484            /** @todo */
     485            break;
     486        case TPM_LOCALITY_REG_INT_ENABLE:
     487            if (bLoc != pThis->bLoc)
     488                break;
     489            /** @todo */
     490            break;
     491        case TPM_LOCALITY_REG_INT_STS:
     492            if (bLoc != pThis->bLoc)
     493                break;
     494            pLoc->uRegSts &= ~(u32 & TPM_LOCALITY_REG_INT_STS_WR_MASK);
     495            tpmLocIrqUpdate(pDevIns, pThis, pLoc);
     496            break;
     497        case TPM_LOCALITY_REG_STS:
     498            /*
     499             * Writes are ignored completely if the locality being accessed is not the
     500             * current active one or if the value has multiple bits set (not a power of two),
     501             * see chapter 5.6.12.1.
     502             */
     503            if (   bLoc != pThis->bLoc
     504                || !RT_IS_POWER_OF_TWO(u32))
     505                break;
     506            /** @todo */
     507            break;
     508        case TPM_LOCALITY_REG_DATA_FIFO:
     509        case TPM_LOCALITY_REG_DATA_XFIFO:
     510            if (bLoc != pThis->bLoc)
     511                break;
     512            /** @todo */
     513            break;
     514        case TPM_LOCALITY_REG_INT_VEC:
     515        case TPM_LOCALITY_REG_IF_CAP:
     516        case TPM_LOCALITY_REG_DID_VID:
     517        case TPM_LOCALITY_REG_RID:
     518        default: /* Ignore. */
     519            break;
     520    }
     521
    376522    return rc;
    377523}
     
    452598{
    453599    PDEVTPM   pThis   = PDMDEVINS_2_DATA(pDevIns, PDEVTPM);
    454     PDEVTPMCC pThisCC = PDMDEVINS_2_DATA_CC(pDevIns, PDEVTPMCC);
    455     RT_NOREF(pThis, pThisCC);
    456     /** @todo */
     600
     601    pThis->bLoc = TPM_NO_LOCALITY_SELECTED;
     602    for (uint32_t i = 0; i < RT_ELEMENTS(pThis->aLoc); i++)
     603    {
     604        PDEVTPMLOCALITY pLoc = &pThis->aLoc[i];
     605
     606        pLoc->enmState   = DEVTPMLOCALITYSTATE_INIT;
     607        pLoc->aRegIntEn  = 0;
     608        pLoc->aRegIntSts = 0;
     609    }
    457610}
    458611
Note: See TracChangeset for help on using the changeset viewer.

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