Home | History | Annotate | Download | only in tpm2
      1 // This file was extracted from the TCG Published
      2 // Trusted Platform Module Library
      3 // Part 4: Supporting Routines
      4 // Family "2.0"
      5 // Level 00 Revision 01.16
      6 // October 30, 2014
      7 
      8 #define NV_C
      9 #include "InternalRoutines.h"
     10 #include "Platform.h"
     11 //
     12 //      NV Index/evict object iterator value
     13 //
     14 typedef        UINT32              NV_ITER;              // type of a NV iterator
     15 #define        NV_ITER_INIT        0xFFFFFFFF            // initial value to start an
     16                                                         // iterator
     17 //
     18 //
     19 //           NV Utility Functions
     20 //
     21 //           NvCheckState()
     22 //
     23 //     Function to check the NV state by accessing the platform-specific function to get the NV state. The result
     24 //     state is registered in s_NvIsAvailable that will be reported by NvIsAvailable().
     25 //     This function is called at the beginning of ExecuteCommand() before any potential call to NvIsAvailable().
     26 //
     27 void
     28 NvCheckState(void)
     29 {
     30     int        func_return;
     31     func_return = _plat__IsNvAvailable();
     32     if(func_return == 0)
     33     {
     34         s_NvStatus = TPM_RC_SUCCESS;
     35     }
     36     else if(func_return == 1)
     37     {
     38         s_NvStatus = TPM_RC_NV_UNAVAILABLE;
     39     }
     40     else
     41     {
     42         s_NvStatus = TPM_RC_NV_RATE;
     43     }
     44     return;
     45 }
     46 //
     47 //
     48 //           NvIsAvailable()
     49 //
     50 //     This function returns the NV availability parameter.
     51 //
     52 //     Error Returns                     Meaning
     53 //
     54 //     TPM_RC_SUCCESS                    NV is available
     55 //     TPM_RC_NV_RATE                    NV is unavailable because of rate limit
     56 //     TPM_RC_NV_UNAVAILABLE             NV is inaccessible
     57 //
     58 TPM_RC
     59 NvIsAvailable(
     60     void
     61     )
     62 {
     63     // Make sure that NV state is still good
     64     if (s_NvStatus == TPM_RC_SUCCESS)
     65 	NvCheckState();
     66 
     67     return s_NvStatus;
     68 }
     69 //
     70 //
     71 //           NvCommit
     72 //
     73 //     This is a wrapper for the platform function to commit pending NV writes.
     74 //
     75 BOOL
     76 NvCommit(
     77     void
     78     )
     79 {
     80     BOOL    success = (_plat__NvCommit() == 0);
     81     return success;
     82 }
     83 //
     84 //
     85 //          NvReadMaxCount()
     86 //
     87 //     This function returns the max NV counter value.
     88 //
     89 static UINT64
     90 NvReadMaxCount(
     91     void
     92     )
     93 {
     94     UINT64      countValue;
     95     _plat__NvMemoryRead(s_maxCountAddr, sizeof(UINT64), &countValue);
     96     return countValue;
     97 }
     98 //
     99 //
    100 //          NvWriteMaxCount()
    101 //
    102 //     This function updates the max counter value to NV memory.
    103 //
    104 static void
    105 NvWriteMaxCount(
    106     UINT64               maxCount
    107     )
    108 {
    109     _plat__NvMemoryWrite(s_maxCountAddr, sizeof(UINT64), &maxCount);
    110     return;
    111 }
    112 //
    113 //
    114 //          NV Index and Persistent Object Access Functions
    115 //
    116 //          Introduction
    117 //
    118 //     These functions are used to access an NV Index and persistent object memory. In this implementation,
    119 //     the memory is simulated with RAM. The data in dynamic area is organized as a linked list, starting from
    120 //     address s_evictNvStart. The first 4 bytes of a node in this link list is the offset of next node, followed by
    121 //     the data entry. A 0-valued offset value indicates the end of the list. If the data entry area of the last node
    122 //     happens to reach the end of the dynamic area without space left for an additional 4 byte end marker, the
    123 //     end address, s_evictNvEnd, should serve as the mark of list end
    124 //
    125 //          NvNext()
    126 //
    127 //     This function provides a method to traverse every data entry in NV dynamic area.
    128 //     To begin with, parameter iter should be initialized to NV_ITER_INIT indicating the first element. Every
    129 //     time this function is called, the value in iter would be adjusted pointing to the next element in traversal. If
    130 //     there is no next element, iter value would be 0. This function returns the address of the 'data entry'
    131 //     pointed by the iter. If there is no more element in the set, a 0 value is returned indicating the end of
    132 //     traversal.
    133 //
    134 static UINT32
    135 NvNext(
    136     NV_ITER             *iter
    137     )
    138 {
    139    NV_ITER        currentIter;
    140    // If iterator is at the beginning of list
    141    if(*iter == NV_ITER_INIT)
    142    {
    143        // Initialize iterator
    144        *iter = s_evictNvStart;
    145    }
    146    // If iterator reaches the end of NV space, or iterator indicates list end
    147    if(*iter + sizeof(UINT32) > s_evictNvEnd || *iter == 0)
    148        return 0;
    149    // Save the current iter offset
    150    currentIter = *iter;
    151    // Adjust iter pointer pointing to next entity
    152    // Read pointer value
    153    _plat__NvMemoryRead(*iter, sizeof(UINT32), iter);
    154    if(*iter == 0) return 0;
    155    return currentIter + sizeof(UINT32);                // entity stores after the pointer
    156 }
    157 //
    158 //
    159 //           NvGetEnd()
    160 //
    161 //      Function to find the end of the NV dynamic data list
    162 //
    163 static UINT32
    164 NvGetEnd(
    165    void
    166    )
    167 {
    168    NV_ITER             iter = NV_ITER_INIT;
    169    UINT32              endAddr = s_evictNvStart;
    170    UINT32              currentAddr;
    171    while((currentAddr = NvNext(&iter)) != 0)
    172        endAddr = currentAddr;
    173    if(endAddr != s_evictNvStart)
    174    {
    175        // Read offset
    176        endAddr -= sizeof(UINT32);
    177        _plat__NvMemoryRead(endAddr, sizeof(UINT32), &endAddr);
    178    }
    179    return endAddr;
    180 }
    181 //
    182 //
    183 //           NvGetFreeByte
    184 //
    185 //      This function returns the number of free octets in NV space.
    186 //
    187 static UINT32
    188 NvGetFreeByte(
    189    void
    190    )
    191 {
    192    return s_evictNvEnd - NvGetEnd();
    193 }
    194 //
    195 //           NvGetEvictObjectSize
    196 //
    197 //      This function returns the size of an evict object in NV space
    198 //
    199 static UINT32
    200 NvGetEvictObjectSize(
    201     void
    202     )
    203 {
    204     return sizeof(TPM_HANDLE) + sizeof(OBJECT) + sizeof(UINT32);
    205 }
    206 //
    207 //
    208 //           NvGetCounterSize
    209 //
    210 //      This function returns the size of a counter index in NV space.
    211 //
    212 static UINT32
    213 NvGetCounterSize(
    214     void
    215     )
    216 {
    217     // It takes an offset field, a handle and the sizeof(NV_INDEX) and
    218     // sizeof(UINT64) for counter data
    219     return sizeof(TPM_HANDLE) + sizeof(NV_INDEX) + sizeof(UINT64) + sizeof(UINT32);
    220 }
    221 //
    222 //
    223 //           NvTestSpace()
    224 //
    225 //      This function will test if there is enough space to add a new entity.
    226 //
    227 //      Return Value                      Meaning
    228 //
    229 //      TRUE                              space available
    230 //      FALSE                             no enough space
    231 //
    232 static BOOL
    233 NvTestSpace(
    234     UINT32               size,               // IN: size of the entity to be added
    235     BOOL                 isIndex             // IN: TRUE if the entity is an index
    236     )
    237 {
    238     UINT32         remainByte = NvGetFreeByte();
    239     // For NV Index, need to make sure that we do not allocate and Index if this
    240     // would mean that the TPM cannot allocate the minimum number of evict
    241     // objects.
    242     if(isIndex)
    243     {
    244         // Get the number of persistent objects allocated
    245         UINT32      persistentNum = NvCapGetPersistentNumber();
    246          // If we have not allocated the requisite number of evict objects, then we
    247          // need to reserve space for them.
    248          // NOTE: some of this is not written as simply as it might seem because
    249          // the values are all unsigned and subtracting needs to be done carefully
    250          // so that an underflow doesn't cause problems.
    251          if(persistentNum < MIN_EVICT_OBJECTS)
    252          {
    253              UINT32      needed = (MIN_EVICT_OBJECTS - persistentNum)
    254                                  * NvGetEvictObjectSize();
    255              if(needed > remainByte)
    256                  remainByte = 0;
    257              else
    258                  remainByte -= needed;
    259          }
    260          // if the requisite number of evict objects have been allocated then
    261          // no need to reserve additional space
    262    }
    263    // This checks for the size of the value being added plus the index value.
    264    // NOTE: This does not check to see if the end marker can be placed in
    265    // memory because the end marker will not be written if it will not fit.
    266    return (size + sizeof(UINT32) <= remainByte);
    267 }
    268 //
    269 //
    270 //           NvAdd()
    271 //
    272 //      This function adds a new entity to NV.
    273 //      This function requires that there is enough space to add a new entity (i.e., that NvTestSpace() has been
    274 //      called and the available space is at least as large as the required space).
    275 //
    276 static void
    277 NvAdd(
    278    UINT32                totalSize,       // IN: total size needed for this        entity For
    279                                           //     evict object, totalSize is        the same as
    280                                           //     bufferSize. For NV Index,         totalSize is
    281                                           //     bufferSize plus index data        size
    282    UINT32                bufferSize,      // IN: size of initial buffer
    283    BYTE                 *entity           // IN: initial buffer
    284    )
    285 {
    286    UINT32               endAddr;
    287    UINT32               nextAddr;
    288    UINT32               listEnd = 0;
    289    // Get the end of data list
    290    endAddr = NvGetEnd();
    291    // Calculate the value of next pointer, which is the size of a pointer +
    292    // the entity data size
    293    nextAddr = endAddr + sizeof(UINT32) + totalSize;
    294    // Write next pointer
    295    _plat__NvMemoryWrite(endAddr, sizeof(UINT32), &nextAddr);
    296    // Write entity data
    297    _plat__NvMemoryWrite(endAddr + sizeof(UINT32), bufferSize, entity);
    298    // Write the end of list if it is not going to exceed the NV space
    299    if(nextAddr + sizeof(UINT32) <= s_evictNvEnd)
    300        _plat__NvMemoryWrite(nextAddr, sizeof(UINT32), &listEnd);
    301    // Set the flag so that NV changes are committed before the command completes.
    302    g_updateNV = TRUE;
    303 }
    304 //
    305 //
    306 //           NvDelete()
    307 //
    308 //      This function is used to delete an NV Index or persistent object from NV memory.
    309 //
    310 static void
    311 NvDelete(
    312    UINT32                entityAddr       // IN: address of entity to be deleted
    313    )
    314 {
    315    UINT32              next;
    316    UINT32              entrySize;
    317    UINT32              entryAddr = entityAddr - sizeof(UINT32);
    318    UINT32              listEnd = 0;
    319    // Get the offset of the next entry.
    320    _plat__NvMemoryRead(entryAddr, sizeof(UINT32), &next);
    321    // The size of this entry is the difference between the current entry and the
    322    // next entry.
    323    entrySize = next - entryAddr;
    324    //    Move each entry after the current one to fill the freed space.
    325    //    Stop when we have reached the end of all the indexes. There are two
    326    //    ways to detect the end of the list. The first is to notice that there
    327    //    is no room for anything else because we are at the end of NV. The other
    328    //    indication is that we find an end marker.
    329    // The loop condition checks for the end of NV.
    330    while(next + sizeof(UINT32) <= s_evictNvEnd)
    331    {
    332        UINT32      size, oldAddr, newAddr;
    333          // Now check for the end marker
    334          _plat__NvMemoryRead(next, sizeof(UINT32), &oldAddr);
    335          if(oldAddr == 0)
    336              break;
    337          size = oldAddr - next;
    338          // Move entry
    339          _plat__NvMemoryMove(next, next - entrySize, size);
    340          // Update forward link
    341          newAddr = oldAddr - entrySize;
    342          _plat__NvMemoryWrite(next - entrySize, sizeof(UINT32), &newAddr);
    343          next = oldAddr;
    344    }
    345    // Mark the end of list
    346    _plat__NvMemoryWrite(next - entrySize, sizeof(UINT32), &listEnd);
    347    // Set the flag so that NV changes are committed before the command completes.
    348    g_updateNV = TRUE;
    349 }
    350 //
    351 //
    352 //           RAM-based NV Index Data Access Functions
    353 //
    354 //           Introduction
    355 //
    356 //      The data layout in ram buffer is {size of(NV_handle() + data), NV_handle(), data} for each NV Index data
    357 //      stored in RAM.
    358 //      NV storage is updated when a NV Index is added or deleted. We do NOT updated NV storage when the
    359 //      data is updated/
    360 //
    361 //           NvTestRAMSpace()
    362 //
    363 //      This function indicates if there is enough RAM space to add a data for a new NV Index.
    364 //
    365 //
    366 //
    367 //
    368 //      Return Value                      Meaning
    369 //
    370 //      TRUE                              space available
    371 //      FALSE                             no enough space
    372 //
    373 static BOOL
    374 NvTestRAMSpace(
    375    UINT32                size                // IN: size of the data to be added to RAM
    376    )
    377 {
    378    BOOL           success = (       s_ramIndexSize
    379                                   + size
    380                                   + sizeof(TPM_HANDLE) + sizeof(UINT32)
    381                                   <= RAM_INDEX_SPACE);
    382    return success;
    383 }
    384 //
    385 //
    386 //           NvGetRamIndexOffset
    387 //
    388 //      This function returns the offset of NV data in the RAM buffer
    389 //      This function requires that NV Index is in RAM. That is, the index must be known to exist.
    390 //
    391 static UINT32
    392 NvGetRAMIndexOffset(
    393    TPMI_RH_NV_INDEX           handle               // IN: NV handle
    394    )
    395 {
    396    UINT32         currAddr = 0;
    397    while(currAddr < s_ramIndexSize)
    398    {
    399        TPMI_RH_NV_INDEX    currHandle;
    400        UINT32              currSize;
    401        memcpy(&currHandle, &s_ramIndex[currAddr + sizeof(UINT32)],
    402               sizeof(currHandle));
    403          // Found a match
    404          if(currHandle == handle)
    405               // data buffer follows the handle and size field
    406               break;
    407          memcpy(&currSize, &s_ramIndex[currAddr], sizeof(currSize));
    408          currAddr += sizeof(UINT32) + currSize;
    409    }
    410    // We assume the index data is existing in RAM space
    411    pAssert(currAddr < s_ramIndexSize);
    412    return currAddr + sizeof(TPMI_RH_NV_INDEX) + sizeof(UINT32);
    413 }
    414 //
    415 //
    416 //           NvAddRAM()
    417 //
    418 //      This function adds a new data area to RAM.
    419 //      This function requires that enough free RAM space is available to add the new data.
    420 //
    421 static void
    422 NvAddRAM(
    423    TPMI_RH_NV_INDEX           handle,              // IN: NV handle
    424    UINT32                     size                 // IN: size of data
    425    )
    426 {
    427    // Add data space at the end of reserved RAM buffer
    428    UINT32 value = size + sizeof(TPMI_RH_NV_INDEX);
    429    memcpy(&s_ramIndex[s_ramIndexSize], &value,
    430           sizeof(s_ramIndex[s_ramIndexSize]));
    431    memcpy(&s_ramIndex[s_ramIndexSize + sizeof(UINT32)], &handle,
    432           sizeof(s_ramIndex[s_ramIndexSize + sizeof(UINT32)]));
    433    s_ramIndexSize += sizeof(UINT32) + sizeof(TPMI_RH_NV_INDEX) + size;
    434    pAssert(s_ramIndexSize <= RAM_INDEX_SPACE);
    435    // Update NV version of s_ramIndexSize
    436    _plat__NvMemoryWrite(s_ramIndexSizeAddr, sizeof(UINT32), &s_ramIndexSize);
    437    // Write reserved RAM space to NV to reflect the newly added NV Index
    438    _plat__NvMemoryWrite(s_ramIndexAddr, RAM_INDEX_SPACE, s_ramIndex);
    439    return;
    440 }
    441 //
    442 //
    443 //          NvDeleteRAM()
    444 //
    445 //      This function is used to delete a RAM-backed NV Index data area.
    446 //      This function assumes the data of NV Index exists in RAM
    447 //
    448 static void
    449 NvDeleteRAM(
    450    TPMI_RH_NV_INDEX          handle           // IN: NV handle
    451    )
    452 {
    453    UINT32             nodeOffset;
    454    UINT32             nextNode;
    455    UINT32             size;
    456    nodeOffset = NvGetRAMIndexOffset(handle);
    457    // Move the pointer back to get the size field of this node
    458    nodeOffset -= sizeof(UINT32) + sizeof(TPMI_RH_NV_INDEX);
    459    // Get node size
    460    memcpy(&size, &s_ramIndex[nodeOffset], sizeof(size));
    461    // Get the offset of next node
    462    nextNode = nodeOffset + sizeof(UINT32) + size;
    463    // Move data
    464    MemoryMove(s_ramIndex + nodeOffset, s_ramIndex + nextNode,
    465               s_ramIndexSize - nextNode, s_ramIndexSize - nextNode);
    466    // Update RAM size
    467    s_ramIndexSize -= size + sizeof(UINT32);
    468    // Update NV version of s_ramIndexSize
    469    _plat__NvMemoryWrite(s_ramIndexSizeAddr, sizeof(UINT32), &s_ramIndexSize);
    470    // Write reserved RAM space to NV to reflect the newly delete NV Index
    471    _plat__NvMemoryWrite(s_ramIndexAddr, RAM_INDEX_SPACE, s_ramIndex);
    472    return;
    473 }
    474 //
    475 //
    476 //
    477 //           Utility Functions
    478 //
    479 //           NvInitStatic()
    480 //
    481 //      This function initializes the static variables used in the NV subsystem.
    482 //
    483 static void
    484 NvInitStatic(
    485     void
    486     )
    487 {
    488     UINT16         i;
    489     UINT32         reservedAddr;
    490     s_reservedSize[NV_DISABLE_CLEAR] = sizeof(gp.disableClear);
    491     s_reservedSize[NV_OWNER_ALG] = sizeof(gp.ownerAlg);
    492     s_reservedSize[NV_ENDORSEMENT_ALG] = sizeof(gp.endorsementAlg);
    493     s_reservedSize[NV_LOCKOUT_ALG] = sizeof(gp.lockoutAlg);
    494     s_reservedSize[NV_OWNER_POLICY] = sizeof(gp.ownerPolicy);
    495     s_reservedSize[NV_ENDORSEMENT_POLICY] = sizeof(gp.endorsementPolicy);
    496     s_reservedSize[NV_LOCKOUT_POLICY] = sizeof(gp.lockoutPolicy);
    497     s_reservedSize[NV_OWNER_AUTH] = sizeof(gp.ownerAuth);
    498     s_reservedSize[NV_ENDORSEMENT_AUTH] = sizeof(gp.endorsementAuth);
    499     s_reservedSize[NV_LOCKOUT_AUTH] = sizeof(gp.lockoutAuth);
    500     s_reservedSize[NV_EP_SEED] = sizeof(gp.EPSeed);
    501     s_reservedSize[NV_SP_SEED] = sizeof(gp.SPSeed);
    502     s_reservedSize[NV_PP_SEED] = sizeof(gp.PPSeed);
    503     s_reservedSize[NV_PH_PROOF] = sizeof(gp.phProof);
    504     s_reservedSize[NV_SH_PROOF] = sizeof(gp.shProof);
    505     s_reservedSize[NV_EH_PROOF] = sizeof(gp.ehProof);
    506     s_reservedSize[NV_TOTAL_RESET_COUNT] = sizeof(gp.totalResetCount);
    507     s_reservedSize[NV_RESET_COUNT] = sizeof(gp.resetCount);
    508     s_reservedSize[NV_PCR_POLICIES] = sizeof(gp.pcrPolicies);
    509     s_reservedSize[NV_PCR_ALLOCATED] = sizeof(gp.pcrAllocated);
    510     s_reservedSize[NV_PP_LIST] = sizeof(gp.ppList);
    511     s_reservedSize[NV_FAILED_TRIES] = sizeof(gp.failedTries);
    512     s_reservedSize[NV_MAX_TRIES] = sizeof(gp.maxTries);
    513     s_reservedSize[NV_RECOVERY_TIME] = sizeof(gp.recoveryTime);
    514     s_reservedSize[NV_LOCKOUT_RECOVERY] = sizeof(gp.lockoutRecovery);
    515     s_reservedSize[NV_LOCKOUT_AUTH_ENABLED] = sizeof(gp.lockOutAuthEnabled);
    516     s_reservedSize[NV_ORDERLY] = sizeof(gp.orderlyState);
    517     s_reservedSize[NV_AUDIT_COMMANDS] = sizeof(gp.auditComands);
    518     s_reservedSize[NV_AUDIT_HASH_ALG] = sizeof(gp.auditHashAlg);
    519     s_reservedSize[NV_AUDIT_COUNTER] = sizeof(gp.auditCounter);
    520     s_reservedSize[NV_ALGORITHM_SET] = sizeof(gp.algorithmSet);
    521     s_reservedSize[NV_FIRMWARE_V1] = sizeof(gp.firmwareV1);
    522     s_reservedSize[NV_FIRMWARE_V2] = sizeof(gp.firmwareV2);
    523     s_reservedSize[NV_ORDERLY_DATA] = sizeof(go);
    524     s_reservedSize[NV_STATE_CLEAR] = sizeof(gc);
    525     s_reservedSize[NV_STATE_RESET] = sizeof(gr);
    526     // Initialize reserved data address. In this implementation, reserved data
    527     // is stored at the start of NV memory
    528     reservedAddr = 0;
    529     for(i = 0; i < NV_RESERVE_LAST; i++)
    530     {
    531         s_reservedAddr[i] = reservedAddr;
    532         reservedAddr += s_reservedSize[i];
    533     }
    534     // Initialize auxiliary variable space for index/evict implementation.
    535     // Auxiliary variables are stored after reserved data area
    536     // RAM index copy starts at the beginning
    537     s_ramIndexSizeAddr = reservedAddr;
    538     s_ramIndexAddr = s_ramIndexSizeAddr + sizeof(UINT32);
    539     // Maximum counter value
    540     s_maxCountAddr = s_ramIndexAddr + RAM_INDEX_SPACE;
    541     // dynamic memory start
    542     s_evictNvStart = s_maxCountAddr + sizeof(UINT64);
    543     // dynamic memory ends at the end of NV memory
    544     s_evictNvEnd = NV_MEMORY_SIZE;
    545     return;
    546 }
    547 //
    548 //
    549 //           NvInit()
    550 //
    551 //      This function initializes the NV system at pre-install time.
    552 //      This function should only be called in a manufacturing environment or in a simulation.
    553 //      The layout of NV memory space is an implementation choice.
    554 //
    555 void
    556 NvInit(
    557     void
    558     )
    559 {
    560     UINT32         nullPointer = 0;
    561     UINT64         zeroCounter = 0;
    562     // Initialize static variables
    563     NvInitStatic();
    564     // Initialize RAM index space as unused
    565     _plat__NvMemoryWrite(s_ramIndexSizeAddr, sizeof(UINT32), &nullPointer);
    566     // Initialize max counter value to 0
    567     _plat__NvMemoryWrite(s_maxCountAddr, sizeof(UINT64), &zeroCounter);
    568     // Initialize the next offset of the first entry in evict/index list to 0
    569     _plat__NvMemoryWrite(s_evictNvStart, sizeof(TPM_HANDLE), &nullPointer);
    570     return;
    571 }
    572 //
    573 //
    574 //           NvReadReserved()
    575 //
    576 //      This function is used to move reserved data from NV memory to RAM.
    577 //
    578 void
    579 NvReadReserved(
    580     NV_RESERVE           type,               // IN: type of reserved data
    581     void                *buffer              // OUT: buffer receives the data.
    582     )
    583 {
    584     // Input type should be valid
    585     pAssert(type >= 0 && type < NV_RESERVE_LAST);
    586     _plat__NvMemoryRead(s_reservedAddr[type], s_reservedSize[type], buffer);
    587     return;
    588 }
    589 //
    590 //
    591 //           NvWriteReserved()
    592 //
    593 //      This function is used to post a reserved data for writing to NV memory. Before the TPM completes the
    594 //      operation, the value will be written.
    595 //
    596 void
    597 NvWriteReserved(
    598    NV_RESERVE           type,              // IN: type of reserved data
    599    void                *buffer             // IN: data buffer
    600    )
    601 {
    602    // Input type should be valid
    603    pAssert(type >= 0 && type < NV_RESERVE_LAST);
    604    _plat__NvMemoryWrite(s_reservedAddr[type], s_reservedSize[type], buffer);
    605    // Set the flag that a NV write happens
    606    g_updateNV = TRUE;
    607    return;
    608 }
    609 //
    610 //
    611 //           NvReadPersistent()
    612 //
    613 //      This function reads persistent data to the RAM copy of the gp structure.
    614 //
    615 void
    616 NvReadPersistent(
    617    void
    618    )
    619 {
    620    // Hierarchy persistent data
    621    NvReadReserved(NV_DISABLE_CLEAR, &gp.disableClear);
    622    NvReadReserved(NV_OWNER_ALG, &gp.ownerAlg);
    623    NvReadReserved(NV_ENDORSEMENT_ALG, &gp.endorsementAlg);
    624    NvReadReserved(NV_LOCKOUT_ALG, &gp.lockoutAlg);
    625    NvReadReserved(NV_OWNER_POLICY, &gp.ownerPolicy);
    626    NvReadReserved(NV_ENDORSEMENT_POLICY, &gp.endorsementPolicy);
    627    NvReadReserved(NV_LOCKOUT_POLICY, &gp.lockoutPolicy);
    628    NvReadReserved(NV_OWNER_AUTH, &gp.ownerAuth);
    629    NvReadReserved(NV_ENDORSEMENT_AUTH, &gp.endorsementAuth);
    630    NvReadReserved(NV_LOCKOUT_AUTH, &gp.lockoutAuth);
    631    NvReadReserved(NV_EP_SEED, &gp.EPSeed);
    632    NvReadReserved(NV_SP_SEED, &gp.SPSeed);
    633    NvReadReserved(NV_PP_SEED, &gp.PPSeed);
    634    NvReadReserved(NV_PH_PROOF, &gp.phProof);
    635    NvReadReserved(NV_SH_PROOF, &gp.shProof);
    636    NvReadReserved(NV_EH_PROOF, &gp.ehProof);
    637    // Time persistent data
    638    NvReadReserved(NV_TOTAL_RESET_COUNT, &gp.totalResetCount);
    639    NvReadReserved(NV_RESET_COUNT, &gp.resetCount);
    640    // PCR persistent data
    641    NvReadReserved(NV_PCR_POLICIES, &gp.pcrPolicies);
    642    NvReadReserved(NV_PCR_ALLOCATED, &gp.pcrAllocated);
    643    // Physical Presence persistent data
    644    NvReadReserved(NV_PP_LIST, &gp.ppList);
    645    // Dictionary attack values persistent data
    646    NvReadReserved(NV_FAILED_TRIES, &gp.failedTries);
    647    NvReadReserved(NV_MAX_TRIES, &gp.maxTries);
    648    NvReadReserved(NV_RECOVERY_TIME, &gp.recoveryTime);
    649 //
    650     NvReadReserved(NV_LOCKOUT_RECOVERY, &gp.lockoutRecovery);
    651     NvReadReserved(NV_LOCKOUT_AUTH_ENABLED, &gp.lockOutAuthEnabled);
    652     // Orderly State persistent data
    653     NvReadReserved(NV_ORDERLY, &gp.orderlyState);
    654     // Command audit values persistent data
    655     NvReadReserved(NV_AUDIT_COMMANDS, &gp.auditComands);
    656     NvReadReserved(NV_AUDIT_HASH_ALG, &gp.auditHashAlg);
    657     NvReadReserved(NV_AUDIT_COUNTER, &gp.auditCounter);
    658     // Algorithm selection persistent data
    659     NvReadReserved(NV_ALGORITHM_SET, &gp.algorithmSet);
    660     // Firmware version persistent data
    661 #ifdef EMBEDDED_MODE
    662    _plat__GetFwVersion(&gp.firmwareV1, &gp.firmwareV2);
    663 #else
    664     NvReadReserved(NV_FIRMWARE_V1, &gp.firmwareV1);
    665     NvReadReserved(NV_FIRMWARE_V2, &gp.firmwareV2);
    666 #endif
    667     return;
    668 }
    669 //
    670 //
    671 //           NvIsPlatformPersistentHandle()
    672 //
    673 //      This function indicates if a handle references a persistent object in the range belonging to the platform.
    674 //
    675 //      Return Value                      Meaning
    676 //
    677 //      TRUE                              handle references a platform persistent object
    678 //      FALSE                             handle does not reference platform persistent object and may
    679 //                                        reference an owner persistent object either
    680 //
    681 BOOL
    682 NvIsPlatformPersistentHandle(
    683     TPM_HANDLE           handle              // IN: handle
    684     )
    685 {
    686     return (handle >= PLATFORM_PERSISTENT && handle <= PERSISTENT_LAST);
    687 }
    688 //
    689 //
    690 //           NvIsOwnerPersistentHandle()
    691 //
    692 //      This function indicates if a handle references a persistent object in the range belonging to the owner.
    693 //
    694 //      Return Value                      Meaning
    695 //
    696 //      TRUE                              handle is owner persistent handle
    697 //      FALSE                             handle is not owner persistent handle and may not be a persistent
    698 //                                        handle at all
    699 //
    700 BOOL
    701 NvIsOwnerPersistentHandle(
    702     TPM_HANDLE           handle              // IN: handle
    703     )
    704 {
    705     return (handle >= PERSISTENT_FIRST && handle < PLATFORM_PERSISTENT);
    706 }
    707 //
    708 //
    709 //           NvNextIndex()
    710 //
    711 //      This function returns the offset in NV of the next NV Index entry. A value of 0 indicates the end of the list.
    712 //      Family "2.0"                                   TCG Published                                          Page 131
    713 //      Level 00 Revision 01.16               Copyright  TCG 2006-2014                            October 30, 2014
    714 //      Trusted Platform Module Library                                                Part 4: Supporting Routines
    716 //
    717 static UINT32
    718 NvNextIndex(
    719    NV_ITER             *iter
    720    )
    721 {
    722    UINT32         addr;
    723    TPM_HANDLE     handle;
    724    while((addr = NvNext(iter)) != 0)
    725    {
    726        // Read handle
    727        _plat__NvMemoryRead(addr, sizeof(TPM_HANDLE), &handle);
    728        if(HandleGetType(handle) == TPM_HT_NV_INDEX)
    729            return addr;
    730    }
    731    pAssert(addr == 0);
    732    return addr;
    733 }
    734 //
    735 //
    736 //           NvNextEvict()
    737 //
    738 //      This function returns the offset in NV of the next evict object entry. A value of 0 indicates the end of the
    739 //      list.
    740 //
    741 static UINT32
    742 NvNextEvict(
    743    NV_ITER             *iter
    744    )
    745 {
    746    UINT32         addr;
    747    TPM_HANDLE     handle;
    748    while((addr = NvNext(iter)) != 0)
    749    {
    750        // Read handle
    751        _plat__NvMemoryRead(addr, sizeof(TPM_HANDLE), &handle);
    752        if(HandleGetType(handle) == TPM_HT_PERSISTENT)
    753            return addr;
    754    }
    755    pAssert(addr == 0);
    756    return addr;
    757 }
    758 //
    759 //
    760 //          NvFindHandle()
    761 //
    762 //      this function returns the offset in NV memory of the entity associated with the input handle. A value of
    763 //      zero indicates that handle does not exist reference an existing persistent object or defined NV Index.
    764 //
    765 static UINT32
    766 NvFindHandle(
    767    TPM_HANDLE            handle
    768    )
    769 {
    770    UINT32              addr;
    771    NV_ITER             iter = NV_ITER_INIT;
    772    while((addr = NvNext(&iter)) != 0)
    773    {
    774        TPM_HANDLE          entityHandle;
    775        // Read handle
    776 //
    777           _plat__NvMemoryRead(addr, sizeof(TPM_HANDLE), &entityHandle);
    778           if(entityHandle == handle)
    779               return addr;
    780     }
    781     pAssert(addr == 0);
    782     return addr;
    783 }
    784 
    785 //
    786 //   NvCheckAndMigrateIfNeeded()
    787 //
    788 // Supported only in EMBEDDED_MODE.
    789 //
    790 // Check if the NVRAM storage format changed, and if so - reinitialize the
    791 // NVRAM. No content migration yet, hopefully it will come one day.
    792 //
    793 // Note that the NV_FIRMWARE_V1 and NV_FIRMWARE_V2 values not used to store
    794 // TPM versoion when in embedded mode are used for NVRAM format version
    795 // instead.
    796 //
    797 //
    798 static void
    799 NvCheckAndMigrateIfNeeded(void)
    800 {
    801 #ifdef EMBEDDED_MODE
    802   UINT32 nv_vers1;
    803   UINT32 nv_vers2;
    804 
    805   NvReadReserved(NV_FIRMWARE_V1, &nv_vers1);
    806   NvReadReserved(NV_FIRMWARE_V2, &nv_vers2);
    807 
    808   if ((nv_vers1 == ~nv_vers2) && (nv_vers1 == NV_FORMAT_VERSION))
    809     return; // All is well.
    810 
    811   // This will reinitialize NVRAM to empty. Migration code will come here
    812   // later.
    813   NvInit();
    814 
    815   nv_vers1 = NV_FORMAT_VERSION;
    816   nv_vers2 = ~NV_FORMAT_VERSION;
    817 
    818   NvWriteReserved(NV_FIRMWARE_V1, &nv_vers1);
    819   NvWriteReserved(NV_FIRMWARE_V2, &nv_vers2);
    820 
    821   NvCommit();
    822 #endif
    823 }
    824 
    825 
    826 //
    827 //
    828 //          NvPowerOn()
    829 //
    830 //      This function is called at _TPM_Init() to initialize the NV environment.
    831 //
    832 //      Return Value                      Meaning
    833 //
    834 //      TRUE                              all NV was initialized
    835 //      FALSE                             the NV     containing saved     state    had   an   error   and
    836 //                                        TPM2_Startup(CLEAR) is required
    837 //
    838 BOOL
    839 NvPowerOn(
    840     void
    841     )
    842 {
    843     int          nvError = 0;
    844     // If power was lost, need to re-establish the RAM data that is loaded from
    845     // NV and initialize the static variables
    846     if(_plat__WasPowerLost(TRUE))
    847     {
    848         if((nvError = _plat__NVEnable(0)) < 0)
    849             FAIL(FATAL_ERROR_NV_UNRECOVERABLE);
    850 	NvInitStatic();
    851 	NvCheckAndMigrateIfNeeded();
    852     }
    853     return nvError == 0;
    854 }
    855 //
    856 //
    857 //          NvStateSave()
    858 //
    859 //      This function is used to cause the memory containing the RAM backed NV Indices to be written to NV.
    860 //
    861 void
    862 NvStateSave(
    863     void
    864     )
    865 {
    866     // Write RAM backed NV Index info to NV
    867     // No need to save s_ramIndexSize because we save it to NV whenever it is
    868     // updated.
    869     _plat__NvMemoryWrite(s_ramIndexAddr, RAM_INDEX_SPACE, s_ramIndex);
    870     // Set the flag so that an NV write happens before the command completes.
    871     g_updateNV = TRUE;
    872     return;
    873 }
    874 //
    875 //
    876 //
    877 //           NvEntityStartup()
    878 //
    879 //      This function is called at TPM_Startup(). If the startup completes a TPM Resume cycle, no action is
    880 //      taken. If the startup is a TPM Reset or a TPM Restart, then this function will:
    881 //      a) clear read/write lock;
    882 //      b) reset NV Index data that has TPMA_NV_CLEAR_STCLEAR SET; and
    883 //      c) set the lower bits in orderly counters to 1 for a non-orderly startup
    884 //      It is a prerequisite that NV be available for writing before this function is called.
    885 //
    886 void
    887 NvEntityStartup(
    888     STARTUP_TYPE           type               // IN: start up type
    889     )
    890 {
    891     NV_ITER                   iter = NV_ITER_INIT;
    892     UINT32                    currentAddr;         // offset points to the current entity
    893     // Restore RAM index data
    894     _plat__NvMemoryRead(s_ramIndexSizeAddr, sizeof(UINT32), &s_ramIndexSize);
    895     _plat__NvMemoryRead(s_ramIndexAddr, RAM_INDEX_SPACE, s_ramIndex);
    896     // If recovering from state save, do nothing
    897     if(type == SU_RESUME)
    898         return;
    899     // Iterate all the NV Index to clear the locks
    900     while((currentAddr = NvNextIndex(&iter)) != 0)
    901     {
    902         NV_INDEX    nvIndex;
    903         UINT32      indexAddr;              // NV address points to index info
    904         TPMA_NV     attributes;
    905         UINT32      attributesValue;
    906         UINT32      publicAreaAttributesValue;
    907           indexAddr = currentAddr + sizeof(TPM_HANDLE);
    908           // Read NV Index info structure
    909           _plat__NvMemoryRead(indexAddr, sizeof(NV_INDEX), &nvIndex);
    910           attributes = nvIndex.publicArea.attributes;
    911           // Clear read/write lock
    912           if(attributes.TPMA_NV_READLOCKED == SET)
    913               attributes.TPMA_NV_READLOCKED = CLEAR;
    914           if(         attributes.TPMA_NV_WRITELOCKED == SET
    915                  &&   (   attributes.TPMA_NV_WRITTEN == CLEAR
    916                       || attributes.TPMA_NV_WRITEDEFINE == CLEAR
    917                       )
    918                 )
    919                  attributes.TPMA_NV_WRITELOCKED = CLEAR;
    920           // Reset NV data for TPMA_NV_CLEAR_STCLEAR
    921           if(attributes.TPMA_NV_CLEAR_STCLEAR == SET)
    922           {
    923               attributes.TPMA_NV_WRITTEN = CLEAR;
    924               attributes.TPMA_NV_WRITELOCKED = CLEAR;
    925           }
    926           // Reset NV data for orderly values that are not counters
    927           // NOTE: The function has already exited on a TPM Resume, so the only
    928           // things being processed are TPM Restart and TPM Reset
    929           if(     type == SU_RESET
    930               && attributes.TPMA_NV_ORDERLY == SET
    931               && attributes.TPMA_NV_COUNTER == CLEAR
    932              )
    933                  attributes.TPMA_NV_WRITTEN = CLEAR;
    934          // Write NV Index info back if it has changed
    935          memcpy(&attributesValue, &attributes, sizeof(attributesValue));
    936          memcpy(&publicAreaAttributesValue, &nvIndex.publicArea.attributes,
    937                 sizeof(publicAreaAttributesValue));
    938          if(attributesValue != publicAreaAttributesValue)
    939          {
    940              nvIndex.publicArea.attributes = attributes;
    941              _plat__NvMemoryWrite(indexAddr, sizeof(NV_INDEX), &nvIndex);
    942                  // Set the flag that a NV write happens
    943                  g_updateNV = TRUE;
    944          }
    945          // Set the lower bits in an orderly counter to 1 for a non-orderly startup
    946          if(    g_prevOrderlyState == SHUTDOWN_NONE
    947              && attributes.TPMA_NV_WRITTEN == SET)
    948          {
    949               if(    attributes.TPMA_NV_ORDERLY == SET
    950                   && attributes.TPMA_NV_COUNTER == SET)
    951               {
    952                    TPMI_RH_NV_INDEX    nvHandle;
    953                    UINT64              counter;
    954                      // Read NV handle
    955                      _plat__NvMemoryRead(currentAddr, sizeof(TPM_HANDLE), &nvHandle);
    956                      // Read the counter value saved to NV upon the last roll over.
    957                      // Do not use RAM backed storage for this once.
    958                      nvIndex.publicArea.attributes.TPMA_NV_ORDERLY = CLEAR;
    959                      NvGetIntIndexData(nvHandle, &nvIndex, &counter);
    960                      nvIndex.publicArea.attributes.TPMA_NV_ORDERLY = SET;
    961                      // Set the lower bits of counter to 1's
    962                      counter |= MAX_ORDERLY_COUNT;
    963                      // Write back to RAM
    964                      NvWriteIndexData(nvHandle, &nvIndex, 0, sizeof(counter), &counter);
    965                      // No write to NV because an orderly shutdown will update the
    966                      // counters.
    967                  }
    968          }
    969    }
    970    return;
    971 }
    972 //
    973 //
    974 //           NV Access Functions
    975 //
    976 //             Introduction
    977 //
    978 //      This set of functions provide accessing NV Index and persistent objects based using a handle for
    979 //      reference to the entity.
    980 //
    981 //             NvIsUndefinedIndex()
    982 //
    983 //      This function is used to verify that an NV Index is not defined. This is only used by
    984 //      TPM2_NV_DefineSpace().
    985 //
    986 //
    987 //
    988 //
    989 //      Return Value                      Meaning
    990 //
    991 //      TRUE                              the handle points to an existing NV Index
    992 //      FALSE                             the handle points to a non-existent Index
    993 //
    994 BOOL
    995 NvIsUndefinedIndex(
    996    TPMI_RH_NV_INDEX         handle                 // IN: handle
    997    )
    998 {
    999    UINT32             entityAddr;                  // offset points to the entity
   1000    pAssert(HandleGetType(handle) == TPM_HT_NV_INDEX);
   1001    // Find the address of index
   1002    entityAddr = NvFindHandle(handle);
   1003    // If handle is not found, return TPM_RC_SUCCESS
   1004    if(entityAddr == 0)
   1005        return TPM_RC_SUCCESS;
   1006    // NV Index is defined
   1007    return TPM_RC_NV_DEFINED;
   1008 }
   1009 //
   1010 //
   1011 //          NvIndexIsAccessible()
   1012 //
   1013 //      This function validates that a handle references a defined NV Index and that the Index is currently
   1014 //      accessible.
   1015 //
   1016 //      Error Returns                     Meaning
   1017 //
   1018 //      TPM_RC_HANDLE                     the handle points to an undefined NV Index If shEnable is CLEAR,
   1019 //                                        this would include an index created using ownerAuth. If phEnableNV
   1020 //                                        is CLEAR, this would include and index created using platform auth
   1021 //      TPM_RC_NV_READLOCKED              Index is present but locked for reading and command does not write
   1022 //                                        to the index
   1023 //      TPM_RC_NV_WRITELOCKED             Index is present but locked for writing and command writes to the
   1024 //                                        index
   1025 //
   1026 TPM_RC
   1027 NvIndexIsAccessible(
   1028    TPMI_RH_NV_INDEX         handle,                // IN: handle
   1029    TPM_CC                   commandCode            // IN: the command
   1030    )
   1031 {
   1032    UINT32                  entityAddr;             // offset points to the entity
   1033    NV_INDEX                nvIndex;                //
   1034    pAssert(HandleGetType(handle) == TPM_HT_NV_INDEX);
   1035    // Find the address of index
   1036    entityAddr = NvFindHandle(handle);
   1037    // If handle is not found, return TPM_RC_HANDLE
   1038    if(entityAddr == 0)
   1039        return TPM_RC_HANDLE;
   1040    // Read NV Index info structure
   1041    _plat__NvMemoryRead(entityAddr + sizeof(TPM_HANDLE), sizeof(NV_INDEX),
   1042                            &nvIndex);
   1043    if(gc.shEnable == FALSE || gc.phEnableNV == FALSE)
   1044    {
   1045        // if shEnable is CLEAR, an ownerCreate NV Index should not be
   1046        // indicated as present
   1047        if(nvIndex.publicArea.attributes.TPMA_NV_PLATFORMCREATE == CLEAR)
   1048        {
   1049            /*
   1050             * FWMP is a Chrome OS specific object saved at address 0x100a, it
   1051             * needs to be available for reading even before TPM2_Startup
   1052             * command is issued.
   1053             */
   1054            UINT32 isFwmpRead = (handle == 0x100100a) &&
   1055                IsReadOperation(commandCode);
   1056 
   1057            if((gc.shEnable == FALSE) && !isFwmpRead)
   1058                return TPM_RC_HANDLE;
   1059        }
   1060        // if phEnableNV is CLEAR, a platform created Index should not
   1061        // be visible
   1062        else if(gc.phEnableNV == FALSE)
   1063            return TPM_RC_HANDLE;
   1064    }
   1065    // If the Index is write locked and this is an NV Write operation...
   1066    if(     nvIndex.publicArea.attributes.TPMA_NV_WRITELOCKED
   1067        && IsWriteOperation(commandCode))
   1068    {
   1069        // then return a locked indication unless the command is TPM2_NV_WriteLock
   1070        if(commandCode != TPM_CC_NV_WriteLock)
   1071            return TPM_RC_NV_LOCKED;
   1072        return TPM_RC_SUCCESS;
   1073    }
   1074    // If the Index is read locked and this is an NV Read operation...
   1075    if(     nvIndex.publicArea.attributes.TPMA_NV_READLOCKED
   1076        && IsReadOperation(commandCode))
   1077    {
   1078        // then return a locked indication unless the command is TPM2_NV_ReadLock
   1079        if(commandCode != TPM_CC_NV_ReadLock)
   1080            return TPM_RC_NV_LOCKED;
   1081        return TPM_RC_SUCCESS;
   1082    }
   1083    // NV Index is accessible
   1084    return TPM_RC_SUCCESS;
   1085 }
   1086 //
   1087 //
   1088 //           NvIsUndefinedEvictHandle()
   1089 //
   1090 //      This function indicates if a handle does not reference an existing persistent object. This function requires
   1091 //      that the handle be in the proper range for persistent objects.
   1092 //
   1093 //      Return Value                     Meaning
   1094 //
   1095 //      TRUE                             handle does not reference an existing persistent object
   1096 //      FALSE                            handle does reference an existing persistent object
   1097 //
   1098 static BOOL
   1099 NvIsUndefinedEvictHandle(
   1100    TPM_HANDLE            handle             // IN: handle
   1101    )
   1102 {
   1103    UINT32           entityAddr;    // offset points to the entity
   1104    pAssert(HandleGetType(handle) == TPM_HT_PERSISTENT);
   1105    // Find the address of evict object
   1106    entityAddr = NvFindHandle(handle);
   1107    // If handle is not found, return TRUE
   1108    if(entityAddr == 0)
   1109        return TRUE;
   1110     else
   1111         return FALSE;
   1112 }
   1113 
   1114 //
   1115 //
   1116 //           NvUnmarshalObject()
   1117 //
   1118 //      This function accepts a buffer containing a marshaled OBJECT
   1119 //      structure, a pointer to the area where the input data should be
   1120 //      unmarshaled, and a pointer to the size of the output area.
   1121 //
   1122 //      No error checking is performed, unmarshaled data is guaranteed not to
   1123 //      spill over the allocated space.
   1124 //
   1125 static TPM_RC NvUnmarshalObject(OBJECT *o, BYTE **buf, INT32 *size)
   1126 {
   1127     TPM_RC result;
   1128 
   1129     // There is no generated function to unmarshal the attributes field, do it
   1130     // by hand.
   1131     MemoryCopy(&o->attributes, *buf, sizeof(o->attributes), *size);
   1132     *buf += sizeof(o->attributes);
   1133     *size -= sizeof(o->attributes);
   1134 
   1135     result = TPMT_PUBLIC_Unmarshal(&o->publicArea, buf, size);
   1136     if (result != TPM_RC_SUCCESS)
   1137         return result;
   1138 
   1139     result = TPMT_SENSITIVE_Unmarshal(&o->sensitive, buf, size);
   1140     if (result != TPM_RC_SUCCESS)
   1141         return result;
   1142 
   1143 #ifdef TPM_ALG_RSA
   1144     result = TPM2B_PUBLIC_KEY_RSA_Unmarshal(&o->privateExponent, buf, size);
   1145     if (result != TPM_RC_SUCCESS)
   1146         return result;
   1147 #endif
   1148 
   1149     result = TPM2B_NAME_Unmarshal(&o->qualifiedName, buf, size);
   1150     if (result != TPM_RC_SUCCESS)
   1151         return result;
   1152 
   1153     result = TPMI_DH_OBJECT_Unmarshal(&o->evictHandle, buf, size, TRUE);
   1154     if (result != TPM_RC_SUCCESS)
   1155         return result;
   1156 
   1157     return TPM2B_NAME_Unmarshal(&o->name, buf, size);
   1158 }
   1159 
   1160 //
   1161 //
   1162 //           NvGetEvictObject()
   1163 //
   1164 //      This function is used to dereference an evict object handle and get a pointer to the object.
   1165 //
   1166 //      Error Returns                     Meaning
   1167 //
   1168 //      TPM_RC_HANDLE                     the handle does not point to an existing persistent object
   1169 //
   1170 TPM_RC
   1171 NvGetEvictObject(
   1172     TPM_HANDLE           handle,              // IN: handle
   1173     OBJECT              *object               // OUT: object data
   1174     )
   1175 {
   1176     UINT32              entityAddr;         // offset points to the entity
   1177     TPM_RC              result = TPM_RC_SUCCESS;
   1178     pAssert(HandleGetType(handle) == TPM_HT_PERSISTENT);
   1179     // Find the address of evict object
   1180     entityAddr = NvFindHandle(handle);
   1181     // If handle is not found, return an error
   1182     if(entityAddr == 0) {
   1183         result = TPM_RC_HANDLE;
   1184     } else {
   1185         UINT32   storedSize;
   1186         UINT32   nextEntryAddr;
   1187 
   1188         // Let's calculate the size of object as stored in NVMEM.
   1189         _plat__NvMemoryRead(entityAddr - sizeof(UINT32),
   1190                             sizeof(UINT32), &nextEntryAddr);
   1191 
   1192         storedSize = nextEntryAddr - entityAddr;
   1193 
   1194         if (storedSize == (sizeof(TPM_HANDLE) + sizeof(OBJECT))) {
   1195             // Read evict object stored unmarshaled.
   1196             _plat__NvMemoryRead(entityAddr + sizeof(TPM_HANDLE),
   1197                                 sizeof(OBJECT),
   1198                                 object);
   1199         } else {
   1200             // Must be stored marshaled, let's unmarshal it.
   1201             BYTE marshaled[sizeof(OBJECT)];
   1202             INT32 max_size = sizeof(marshaled);
   1203             BYTE *marshaledPtr = marshaled;
   1204 
   1205             _plat__NvMemoryRead(entityAddr + sizeof(TPM_HANDLE),
   1206                                 storedSize, marshaled);
   1207             result = NvUnmarshalObject(object,  &marshaledPtr, &max_size);
   1208         }
   1209     }
   1210     // whether there is an error or not, make sure that the evict
   1211     // status of the object is set so that the slot will get freed on exit
   1212     object->attributes.evict = SET;
   1213     return result;
   1214 }
   1215 //
   1216 //
   1217 //           NvGetIndexInfo()
   1218 //
   1219 //      This function is used to retrieve the contents of an NV Index.
   1220 //      An implementation is allowed to save the NV Index in a vendor-defined format. If the format is different
   1221 //      from the default used by the reference code, then this function would be changed to reformat the data into
   1222 //      the default format.
   1223 //      A prerequisite to calling this function is that the handle must be known to reference a defined NV Index.
   1224 //
   1225 void
   1226 NvGetIndexInfo(
   1227     TPMI_RH_NV_INDEX          handle,              // IN: handle
   1228     NV_INDEX                 *nvIndex              // OUT: NV index structure
   1229     )
   1230 {
   1231     UINT32                    entityAddr;          // offset points to the entity
   1232     pAssert(HandleGetType(handle) == TPM_HT_NV_INDEX);
   1233     // Find the address of NV index
   1234     entityAddr = NvFindHandle(handle);
   1235     pAssert(entityAddr != 0);
   1236     // This implementation uses the default format so just
   1237     // read the data in
   1238     _plat__NvMemoryRead(entityAddr + sizeof(TPM_HANDLE), sizeof(NV_INDEX),
   1239                         nvIndex);
   1240     return;
   1241 }
   1242 //
   1243 //
   1244 //           NvInitialCounter()
   1245 //
   1246 //      This function returns the value to be used when a counter index is initialized. It will scan the NV counters
   1247 //      and find the highest value in any active counter. It will use that value as the starting point. If there are no
   1248 //      active counters, it will use the value of the previous largest counter.
   1249 //
   1250 UINT64
   1251 NvInitialCounter(
   1252     void
   1253     )
   1254 {
   1255     UINT64              maxCount;
   1256     NV_ITER             iter = NV_ITER_INIT;
   1257     UINT32              currentAddr;
   1258     // Read the maxCount value
   1259     maxCount = NvReadMaxCount();
   1260     // Iterate all existing counters
   1261     while((currentAddr = NvNextIndex(&iter)) != 0)
   1262     {
   1263         TPMI_RH_NV_INDEX    nvHandle;
   1264         NV_INDEX            nvIndex;
   1265          // Read NV handle
   1266          _plat__NvMemoryRead(currentAddr, sizeof(TPM_HANDLE), &nvHandle);
   1267          // Get NV Index
   1268          NvGetIndexInfo(nvHandle, &nvIndex);
   1269          if(    nvIndex.publicArea.attributes.TPMA_NV_COUNTER == SET
   1270              && nvIndex.publicArea.attributes.TPMA_NV_WRITTEN == SET)
   1271          {
   1272              UINT64      countValue;
   1273              // Read counter value
   1274              NvGetIntIndexData(nvHandle, &nvIndex, &countValue);
   1275              if(countValue > maxCount)
   1276                  maxCount = countValue;
   1277          }
   1278     }
   1279     // Initialize the new counter value to be maxCount + 1
   1280     // A counter is only initialized the first time it is written. The
   1281     // way to write a counter is with TPM2_NV_INCREMENT(). Since the
   1282     // "initial" value of a defined counter is the largest count value that
   1283     // may have existed in this index previously, then the first use would
   1284     // add one to that value.
   1285     return maxCount;
   1286 }
   1287 //
   1288 //
   1289 //           NvGetIndexData()
   1290 //
   1291 //      This function is used to access the data in an NV Index. The data is returned as a byte sequence. Since
   1292 //      counter values are kept in native format, they are converted to canonical form before being returned.
   1293 //      Family "2.0"                                  TCG Published                                         Page 139
   1294 //      Level 00 Revision 01.16               Copyright  TCG 2006-2014                            October 30, 2014
   1295 //      Trusted Platform Module Library                                                Part 4: Supporting Routines
   1297 //
   1298 //
   1299 //      This function requires that the NV Index be defined, and that the required data is within the data range. It
   1300 //      also requires that TPMA_NV_WRITTEN of the Index is SET.
   1301 //
   1302 void
   1303 NvGetIndexData(
   1304     TPMI_RH_NV_INDEX          handle,            //   IN: handle
   1305     NV_INDEX                 *nvIndex,           //   IN: RAM image of index header
   1306     UINT32                    offset,            //   IN: offset of NV data
   1307     UINT16                    size,              //   IN: size of NV data
   1308     void                     *data               //   OUT: data buffer
   1309     )
   1310 {
   1311     pAssert(nvIndex->publicArea.attributes.TPMA_NV_WRITTEN == SET);
   1312     if(   nvIndex->publicArea.attributes.TPMA_NV_BITS == SET
   1313        || nvIndex->publicArea.attributes.TPMA_NV_COUNTER == SET)
   1314     {
   1315         // Read bit or counter data in canonical form
   1316         UINT64      dataInInt;
   1317         NvGetIntIndexData(handle, nvIndex, &dataInInt);
   1318         UINT64_TO_BYTE_ARRAY(dataInInt, (BYTE *)data);
   1319     }
   1320     else
   1321     {
   1322         if(nvIndex->publicArea.attributes.TPMA_NV_ORDERLY == SET)
   1323         {
   1324             UINT32      ramAddr;
   1325               // Get data from RAM buffer
   1326               ramAddr = NvGetRAMIndexOffset(handle);
   1327               MemoryCopy(data, s_ramIndex + ramAddr + offset, size, size);
   1328          }
   1329          else
   1330          {
   1331               UINT32      entityAddr;
   1332               entityAddr = NvFindHandle(handle);
   1333               // Get data from NV
   1334               // Skip NV Index info, read data buffer
   1335               entityAddr += sizeof(TPM_HANDLE) + sizeof(NV_INDEX) + offset;
   1336               // Read the data
   1337               _plat__NvMemoryRead(entityAddr, size, data);
   1338         }
   1339     }
   1340     return;
   1341 }
   1342 //
   1343 //
   1344 //           NvGetIntIndexData()
   1345 //
   1346 //      Get data in integer format of a bit or counter NV Index.
   1347 //      This function requires that the NV Index is defined and that the NV Index previously has been written.
   1348 //
   1349 void
   1350 NvGetIntIndexData(
   1351     TPMI_RH_NV_INDEX          handle,            // IN: handle
   1352     NV_INDEX                 *nvIndex,           // IN: RAM image of NV Index header
   1353     UINT64                   *data               // IN: UINT64 pointer for counter or bit
   1354     )
   1355 {
   1356     // Validate that index has been written and is the right type
   1357     pAssert(   nvIndex->publicArea.attributes.TPMA_NV_WRITTEN == SET
   1358             && (   nvIndex->publicArea.attributes.TPMA_NV_BITS == SET
   1359                 || nvIndex->publicArea.attributes.TPMA_NV_COUNTER == SET
   1360                    )
   1361               );
   1362     // bit and counter value is store in native format for TPM CPU.                  So we directly
   1363     // copy the contents of NV to output data buffer
   1364     if(nvIndex->publicArea.attributes.TPMA_NV_ORDERLY == SET)
   1365     {
   1366         UINT32      ramAddr;
   1367           // Get data from RAM buffer
   1368           ramAddr = NvGetRAMIndexOffset(handle);
   1369           MemoryCopy(data, s_ramIndex + ramAddr, sizeof(*data), sizeof(*data));
   1370     }
   1371     else
   1372     {
   1373         UINT32      entityAddr;
   1374         entityAddr = NvFindHandle(handle);
   1375           // Get data from NV
   1376           // Skip NV Index info, read data buffer
   1377           _plat__NvMemoryRead(
   1378               entityAddr + sizeof(TPM_HANDLE) + sizeof(NV_INDEX),
   1379               sizeof(UINT64), data);
   1380     }
   1381     return;
   1382 }
   1383 //
   1384 //
   1385 //           NvWriteIndexInfo()
   1386 //
   1387 //       This function is called to queue the write of NV Index data to persistent memory.
   1388 //       This function requires that NV Index is defined.
   1389 //
   1390 //       Error Returns                        Meaning
   1391 //
   1392 //       TPM_RC_NV_RATE                       NV is rate limiting so retry
   1393 //       TPM_RC_NV_UNAVAILABLE                NV is not available
   1394 //
   1395 TPM_RC
   1396 NvWriteIndexInfo(
   1397     TPMI_RH_NV_INDEX            handle,                // IN: handle
   1398     NV_INDEX                   *nvIndex                // IN: NV Index info to be written
   1399     )
   1400 {
   1401     UINT32             entryAddr;
   1402     TPM_RC             result;
   1403     // Get the starting offset for the index in the RAM image of NV
   1404     entryAddr = NvFindHandle(handle);
   1405     pAssert(entryAddr != 0);
   1406     // Step over the link value
   1407     entryAddr = entryAddr + sizeof(TPM_HANDLE);
   1408     // If the index data is actually changed, then a write to NV is required
   1409     if(_plat__NvIsDifferent(entryAddr, sizeof(NV_INDEX),nvIndex))
   1410     {
   1411         // Make sure that NV is available
   1412         result = NvIsAvailable();
   1413         if(result != TPM_RC_SUCCESS)
   1414             return result;
   1415         _plat__NvMemoryWrite(entryAddr, sizeof(NV_INDEX), nvIndex);
   1416         g_updateNV = TRUE;
   1417     }
   1418     return TPM_RC_SUCCESS;
   1419 }
   1420 //
   1421 //
   1422 //            NvWriteIndexData()
   1423 //
   1424 //       This function is used to write NV index data.
   1425 //       This function requires that the NV Index is defined, and the data is within the defined data range for the
   1426 //       index.
   1427 //
   1428 //       Error Returns                     Meaning
   1429 //
   1430 //       TPM_RC_NV_RATE                    NV is rate limiting so retry
   1431 //       TPM_RC_NV_UNAVAILABLE             NV is not available
   1432 //
   1433 TPM_RC
   1434 NvWriteIndexData(
   1435     TPMI_RH_NV_INDEX          handle,               //   IN: handle
   1436     NV_INDEX                 *nvIndex,              //   IN: RAM copy of NV Index
   1437     UINT32                    offset,               //   IN: offset of NV data
   1438     UINT32                    size,                 //   IN: size of NV data
   1439     void                     *data                  //   OUT: data buffer
   1440     )
   1441 {
   1442     TPM_RC               result;
   1443     // Validate that write falls within range of the index
   1444     pAssert(nvIndex->publicArea.dataSize >= offset + size);
   1445     // Update TPMA_NV_WRITTEN bit if necessary
   1446     if(nvIndex->publicArea.attributes.TPMA_NV_WRITTEN == CLEAR)
   1447     {
   1448         nvIndex->publicArea.attributes.TPMA_NV_WRITTEN = SET;
   1449         result = NvWriteIndexInfo(handle, nvIndex);
   1450         if(result != TPM_RC_SUCCESS)
   1451             return result;
   1452     }
   1453     // Check to see if process for an orderly index is required.
   1454     if(nvIndex->publicArea.attributes.TPMA_NV_ORDERLY == SET)
   1455     {
   1456         UINT32      ramAddr;
   1457           // Write data to RAM buffer
   1458           ramAddr = NvGetRAMIndexOffset(handle);
   1459           MemoryCopy(s_ramIndex + ramAddr + offset, data, size,
   1460                      sizeof(s_ramIndex) - ramAddr - offset);
   1461           // NV update does not happen for orderly index. Have
   1462           // to clear orderlyState to reflect that we have changed the
   1463           // NV and an orderly shutdown is required. Only going to do this if we
   1464           // are not processing a counter that has just rolled over
   1465           if(g_updateNV == FALSE)
   1466               g_clearOrderly = TRUE;
   1467     }
   1468     // Need to process this part if the Index isn't orderly or if it is
   1469     // an orderly counter that just rolled over.
   1470     if(g_updateNV || nvIndex->publicArea.attributes.TPMA_NV_ORDERLY == CLEAR)
   1471     {
   1472         // Processing for an index with TPMA_NV_ORDERLY CLEAR
   1473         UINT32      entryAddr = NvFindHandle(handle);
   1474           pAssert(entryAddr != 0);
   1475 //
   1476           // Offset into the index to the first byte of the data to be written
   1477           entryAddr += sizeof(TPM_HANDLE) + sizeof(NV_INDEX) + offset;
   1478           // If the data is actually changed, then a write to NV is required
   1479           if(_plat__NvIsDifferent(entryAddr, size, data))
   1480           {
   1481               // Make sure that NV is available
   1482               result = NvIsAvailable();
   1483               if(result != TPM_RC_SUCCESS)
   1484                   return result;
   1485               _plat__NvMemoryWrite(entryAddr, size, data);
   1486               g_updateNV = TRUE;
   1487           }
   1488     }
   1489     return TPM_RC_SUCCESS;
   1490 }
   1491 //
   1492 //
   1493 //            NvGetName()
   1494 //
   1495 //       This function is used to compute the Name of an NV Index.
   1496 //       The name buffer receives the bytes of the Name and the return value is the number of octets in the
   1497 //       Name.
   1498 //       This function requires that the NV Index is defined.
   1499 //
   1500 UINT16
   1501 NvGetName(
   1502     TPMI_RH_NV_INDEX          handle,            // IN: handle of the index
   1503     NAME                     *name               // OUT: name of the index
   1504     )
   1505 {
   1506     UINT16                    dataSize, digestSize;
   1507     NV_INDEX                  nvIndex;
   1508     BYTE                      marshalBuffer[sizeof(TPMS_NV_PUBLIC)];
   1509     BYTE                     *buffer;
   1510     INT32                     bufferSize;
   1511     HASH_STATE                hashState;
   1512     // Get NV public info
   1513     NvGetIndexInfo(handle, &nvIndex);
   1514     // Marshal public area
   1515     buffer = marshalBuffer;
   1516     bufferSize = sizeof(TPMS_NV_PUBLIC);
   1517     dataSize = TPMS_NV_PUBLIC_Marshal(&nvIndex.publicArea, &buffer, &bufferSize);
   1518     // hash public area
   1519     digestSize = CryptStartHash(nvIndex.publicArea.nameAlg, &hashState);
   1520     CryptUpdateDigest(&hashState, dataSize, marshalBuffer);
   1521     // Complete digest leaving room for the nameAlg
   1522     CryptCompleteHash(&hashState, digestSize, &((BYTE *)name)[2]);
   1523     // Include the nameAlg
   1524     UINT16_TO_BYTE_ARRAY(nvIndex.publicArea.nameAlg, (BYTE *)name);
   1525     return digestSize + 2;
   1526 }
   1527 //
   1528 //
   1529 //            NvDefineIndex()
   1530 //
   1531 //       This function is used to assign NV memory to an NV Index.
   1532 //
   1533 //
   1534 //
   1535 //       Error Returns                     Meaning
   1536 //
   1537 //       TPM_RC_NV_SPACE                   insufficient NV space
   1538 //
   1539 TPM_RC
   1540 NvDefineIndex(
   1541    TPMS_NV_PUBLIC      *publicArea,          // IN: A template for an area to create.
   1542    TPM2B_AUTH          *authValue            // IN: The initial authorization value
   1543    )
   1544 {
   1545    // The buffer to be written to NV memory
   1546    BYTE            nvBuffer[sizeof(TPM_HANDLE) + sizeof(NV_INDEX)];
   1547    NV_INDEX            *nvIndex;                  // a pointer to the NV_INDEX data in
   1548                                                   //   nvBuffer
   1549    UINT16              entrySize;                 // size of entry
   1550    entrySize = sizeof(TPM_HANDLE) + sizeof(NV_INDEX) + publicArea->dataSize;
   1551    // Check if we have enough space to create the NV Index
   1552    // In this implementation, the only resource limitation is the available NV
   1553    // space. Other implementation may have other limitation on counter or on
   1554    // NV slot
   1555    if(!NvTestSpace(entrySize, TRUE)) return TPM_RC_NV_SPACE;
   1556    // if the index to be defined is RAM backed, check RAM space availability
   1557    // as well
   1558    if(publicArea->attributes.TPMA_NV_ORDERLY == SET
   1559            && !NvTestRAMSpace(publicArea->dataSize))
   1560        return TPM_RC_NV_SPACE;
   1561    // Copy input value to nvBuffer
   1562        // Copy handle
   1563    memcpy(nvBuffer, &publicArea->nvIndex, sizeof(TPM_HANDLE));
   1564        // Copy NV_INDEX
   1565    nvIndex = (NV_INDEX *) (nvBuffer + sizeof(TPM_HANDLE));
   1566    nvIndex->publicArea = *publicArea;
   1567    nvIndex->authValue = *authValue;
   1568    // Add index to NV memory
   1569    NvAdd(entrySize, sizeof(TPM_HANDLE) + sizeof(NV_INDEX), nvBuffer);
   1570    // If the data of NV Index is RAM backed, add the data area in RAM as well
   1571    if(publicArea->attributes.TPMA_NV_ORDERLY == SET)
   1572        NvAddRAM(publicArea->nvIndex, publicArea->dataSize);
   1573    return TPM_RC_SUCCESS;
   1574 }
   1575 
   1576 //
   1577 //
   1578 //           NvMarshalObject()
   1579 //
   1580 //      This function marshals the passed in OBJECT structure into a buffer. A
   1581 //      pointer to pointer to the buffer and a pointer to the size of the
   1582 //      buffer are passed in for this function to update as appropriate.
   1583 //
   1584 //      On top of marshaling the object, this function also modifies one of
   1585 //      the object's properties and sets the evictHandle field of the
   1586 //      marshaled object to the requested value.
   1587 //
   1588 //      Returns
   1589 //
   1590 //      Marshaled size of the object.
   1591 //
   1592 static UINT16 NvMarshalObject(OBJECT *o, TPMI_DH_OBJECT evictHandle,
   1593                               BYTE **buf, INT32 *size)
   1594 {
   1595     UINT16 marshaledSize;
   1596     OBJECT_ATTRIBUTES stored_attributes;
   1597 
   1598     stored_attributes = o->attributes;
   1599     stored_attributes.evict = SET;
   1600     marshaledSize = sizeof(stored_attributes);
   1601     MemoryCopy(*buf, &stored_attributes, marshaledSize, *size);
   1602     *buf += marshaledSize;
   1603     *size -= marshaledSize;
   1604 
   1605     marshaledSize += TPMT_PUBLIC_Marshal(&o->publicArea, buf, size);
   1606     marshaledSize += TPMT_SENSITIVE_Marshal(&o->sensitive, buf, size);
   1607 #ifdef TPM_ALG_RSA
   1608     marshaledSize += TPM2B_PUBLIC_KEY_RSA_Marshal(&o->privateExponent,
   1609                                                   buf, size);
   1610 #endif
   1611     marshaledSize += TPM2B_NAME_Marshal(&o->qualifiedName, buf, size);
   1612 
   1613     // Use the supplied handle instead of the object contents.
   1614     marshaledSize += TPMI_DH_OBJECT_Marshal(&evictHandle, buf, size);
   1615     marshaledSize += TPM2B_NAME_Marshal(&o->name, buf, size);
   1616 
   1617     return marshaledSize;
   1618 }
   1619 
   1620 //
   1621 //
   1622 //           NvAddEvictObject()
   1623 //
   1624 //       This function is used to assign NV memory to a persistent object.
   1625 //
   1626 //       Error Returns                     Meaning
   1627 //
   1628 //       TPM_RC_NV_HANDLE                  the requested handle is already in use
   1629 //       TPM_RC_NV_SPACE                   insufficient NV space
   1630 //
   1631 TPM_RC
   1632 NvAddEvictObject(
   1633    TPMI_DH_OBJECT       evictHandle,         // IN: new evict handle
   1634 //
   1635     OBJECT              *object              // IN: object to be added
   1636     )
   1637 {
   1638     // The buffer to be written to NV memory
   1639     BYTE            nvBuffer[sizeof(TPM_HANDLE) + sizeof(OBJECT)];
   1640     UINT16              entrySize;                // size of entry
   1641     BYTE                *marshalSpace;
   1642     INT32               marshalRoom;
   1643 
   1644     // evict handle type should match the object hierarchy
   1645     pAssert(   (   NvIsPlatformPersistentHandle(evictHandle)
   1646                 && object->attributes.ppsHierarchy == SET)
   1647             || (   NvIsOwnerPersistentHandle(evictHandle)
   1648                 && (   object->attributes.spsHierarchy == SET
   1649                     || object->attributes.epsHierarchy == SET)));
   1650 
   1651     // Do not attemp storing a duplicate handle.
   1652     if(!NvIsUndefinedEvictHandle(evictHandle))
   1653         return TPM_RC_NV_DEFINED;
   1654 
   1655         // Copy handle
   1656     entrySize = sizeof(TPM_HANDLE);
   1657     memcpy(nvBuffer, &evictHandle, entrySize);
   1658 
   1659     // Let's serialize the object before storing it in NVMEM
   1660     marshalSpace = nvBuffer + entrySize;
   1661     marshalRoom = sizeof(nvBuffer) - entrySize;
   1662     entrySize += NvMarshalObject(object, evictHandle,
   1663                                  &marshalSpace, &marshalRoom);
   1664 
   1665     // Check if we have enough space to add this evict object
   1666     if(!NvTestSpace(entrySize, FALSE)) return TPM_RC_NV_SPACE;
   1667 
   1668     // Add evict to NV memory
   1669     NvAdd(entrySize, entrySize, nvBuffer);
   1670     return TPM_RC_SUCCESS;
   1671 }
   1672 //
   1673 //
   1674 //           NvDeleteEntity()
   1675 //
   1676 //       This function will delete a NV Index or an evict object.
   1677 //       This function requires that the index/evict object has been defined.
   1678 //
   1679 void
   1680 NvDeleteEntity(
   1681     TPM_HANDLE           handle              // IN: handle of entity to be deleted
   1682     )
   1683 {
   1684     UINT32         entityAddr;         // pointer to entity
   1685     entityAddr = NvFindHandle(handle);
   1686     pAssert(entityAddr != 0);
   1687     if(HandleGetType(handle) == TPM_HT_NV_INDEX)
   1688     {
   1689         NV_INDEX    nvIndex;
   1690           // Read the NV Index info
   1691           _plat__NvMemoryRead(entityAddr + sizeof(TPM_HANDLE), sizeof(NV_INDEX),
   1692                               &nvIndex);
   1693           // If the entity to be deleted is a counter with the maximum counter
   1694           // value, record it in NV memory
   1695           if(nvIndex.publicArea.attributes.TPMA_NV_COUNTER == SET
   1696                   && nvIndex.publicArea.attributes.TPMA_NV_WRITTEN == SET)
   1697           {
   1698               UINT64      countValue;
   1699               UINT64      maxCount;
   1700               NvGetIntIndexData(handle, &nvIndex, &countValue);
   1701               maxCount = NvReadMaxCount();
   1702               if(countValue > maxCount)
   1703                   NvWriteMaxCount(countValue);
   1704           }
   1705           // If the NV Index is RAM back, delete the RAM data as well
   1706           if(nvIndex.publicArea.attributes.TPMA_NV_ORDERLY == SET)
   1707               NvDeleteRAM(handle);
   1708     }
   1709     NvDelete(entityAddr);
   1710     return;
   1711 }
   1712 //
   1713 //
   1714 //            NvFlushHierarchy()
   1715 //
   1716 //       This function will delete persistent objects belonging to the indicated If the storage hierarchy is selected,
   1717 //       the function will also delete any NV Index define using ownerAuth.
   1718 //
   1719 void
   1720 NvFlushHierarchy(
   1721     TPMI_RH_HIERARCHY         hierarchy          // IN: hierarchy to be flushed.
   1722     )
   1723 {
   1724     NV_ITER             iter = NV_ITER_INIT;
   1725     UINT32              currentAddr;
   1726     while((currentAddr = NvNext(&iter)) != 0)
   1727     {
   1728         TPM_HANDLE      entityHandle;
   1729           // Read handle information.
   1730           _plat__NvMemoryRead(currentAddr, sizeof(TPM_HANDLE), &entityHandle);
   1731           if(HandleGetType(entityHandle) == TPM_HT_NV_INDEX)
   1732           {
   1733               // Handle NV Index
   1734               NV_INDEX    nvIndex;
   1735               // If flush endorsement or platform hierarchy, no NV Index would be
   1736               // flushed
   1737               if(hierarchy == TPM_RH_ENDORSEMENT || hierarchy == TPM_RH_PLATFORM)
   1738                   continue;
   1739               _plat__NvMemoryRead(currentAddr + sizeof(TPM_HANDLE),
   1740                                   sizeof(NV_INDEX), &nvIndex);
   1741               // For storage hierarchy, flush OwnerCreated index
   1742                if(    nvIndex.publicArea.attributes.TPMA_NV_PLATFORMCREATE == CLEAR)
   1743                {
   1744                      // Delete the NV Index
   1745                      NvDelete(currentAddr);
   1746                      // Re-iterate from beginning after a delete
   1747                      iter = NV_ITER_INIT;
   1748                      // If the NV Index is RAM back, delete the RAM data as well
   1749                      if(nvIndex.publicArea.attributes.TPMA_NV_ORDERLY == SET)
   1750                          NvDeleteRAM(entityHandle);
   1751               }
   1752           }
   1753           else if(HandleGetType(entityHandle) == TPM_HT_PERSISTENT)
   1754           {
   1755               OBJECT          object;
   1756                // Get evict object
   1757                NvGetEvictObject(entityHandle, &object);
   1758                // If the evict object belongs to the hierarchy to be flushed
   1759                if(     (    hierarchy == TPM_RH_PLATFORM
   1760                         && object.attributes.ppsHierarchy == SET)
   1761                    || (     hierarchy == TPM_RH_OWNER
   1762                         && object.attributes.spsHierarchy == SET)
   1763                    || (     hierarchy == TPM_RH_ENDORSEMENT
   1764                         && object.attributes.epsHierarchy == SET)
   1765                    )
   1766                {
   1767                      // Delete the evict object
   1768                      NvDelete(currentAddr);
   1769                      // Re-iterate from beginning after a delete
   1770                      iter = NV_ITER_INIT;
   1771                }
   1772           }
   1773           else
   1774           {
   1775                pAssert(FALSE);
   1776           }
   1777    }
   1778    return;
   1779 }
   1780 //
   1781 //
   1782 //              NvSetGlobalLock()
   1783 //
   1784 //       This function is used to SET the TPMA_NV_WRITELOCKED attribute for all NV Indices that have
   1785 //       TPMA_NV_GLOBALLOCK SET. This function is use by TPM2_NV_GlobalWriteLock().
   1786 //
   1787 void
   1788 NvSetGlobalLock(
   1789    void
   1790    )
   1791 {
   1792    NV_ITER               iter = NV_ITER_INIT;
   1793    UINT32                currentAddr;
   1794    // Check all Indices
   1795    while((currentAddr = NvNextIndex(&iter)) != 0)
   1796    {
   1797        NV_INDEX    nvIndex;
   1798           // Read the index data
   1799           _plat__NvMemoryRead(currentAddr + sizeof(TPM_HANDLE),
   1800                               sizeof(NV_INDEX), &nvIndex);
   1801           // See if it should be locked
   1802           if(nvIndex.publicArea.attributes.TPMA_NV_GLOBALLOCK == SET)
   1803           {
   1804                 // if so, lock it
   1805                 nvIndex.publicArea.attributes.TPMA_NV_WRITELOCKED = SET;
   1806                 _plat__NvMemoryWrite(currentAddr + sizeof(TPM_HANDLE),
   1807                                      sizeof(NV_INDEX), &nvIndex);
   1808                 // Set the flag that a NV write happens
   1809                 g_updateNV = TRUE;
   1810           }
   1811    }
   1812    return;
   1813 }
   1814 //
   1815 //
   1816 //              InsertSort()
   1817 //
   1818 //       Sort a handle into handle list in ascending order. The total handle number in the list should not exceed
   1819 //       MAX_CAP_HANDLES
   1820 //
   1821 static void
   1822 InsertSort(
   1823    TPML_HANDLE           *handleList,     // IN/OUT: sorted handle list
   1824    UINT32                 count,          // IN: maximum count in the handle list
   1825    TPM_HANDLE             entityHandle    // IN: handle to be inserted
   1826    )
   1827 {
   1828    UINT32                i, j;
   1829    UINT32                originalCount;
   1830    // For a corner case that the maximum count is 0, do nothing
   1831    if(count == 0) return;
   1832    // For empty list, add the handle at the beginning and return
   1833    if(handleList->count == 0)
   1834    {
   1835        handleList->handle[0] = entityHandle;
   1836        handleList->count++;
   1837        return;
   1838    }
   1839    // Check if the maximum of the list has been reached
   1840    originalCount = handleList->count;
   1841    if(originalCount < count)
   1842        handleList->count++;
   1843    // Insert the handle to the list
   1844    for(i = 0; i < originalCount; i++)
   1845    {
   1846        if(handleList->handle[i] > entityHandle)
   1847        {
   1848            for(j = handleList->count - 1; j > i; j--)
   1849            {
   1850                handleList->handle[j] = handleList->handle[j-1];
   1851            }
   1852            break;
   1853        }
   1854    }
   1855      // If a slot was found, insert the handle in this position
   1856      if(i < originalCount || handleList->count > originalCount)
   1857          handleList->handle[i] = entityHandle;
   1858      return;
   1859 }
   1860 //
   1861 //
   1862 //            NvCapGetPersistent()
   1863 //
   1864 //       This function is used to get a list of handles of the persistent objects, starting at handle.
   1865 //       Handle must be in valid persistent object handle range, but does not have to reference an existing
   1866 //       persistent object.
   1867 //
   1868 //       Return Value                      Meaning
   1869 //
   1870 //       YES                               if there are more handles available
   1871 //       NO                                all the available handles has been returned
   1872 //
   1873 TPMI_YES_NO
   1874 NvCapGetPersistent(
   1875      TPMI_DH_OBJECT       handle,            // IN: start handle
   1876      UINT32               count,             // IN: maximum number of returned handle
   1877      TPML_HANDLE         *handleList         // OUT: list of handle
   1878      )
   1879 {
   1880      TPMI_YES_NO               more = NO;
   1881      NV_ITER                   iter = NV_ITER_INIT;
   1882      UINT32                    currentAddr;
   1883      pAssert(HandleGetType(handle) == TPM_HT_PERSISTENT);
   1884      // Initialize output handle list
   1885      handleList->count = 0;
   1886      // The maximum count of handles we may return is MAX_CAP_HANDLES
   1887      if(count > MAX_CAP_HANDLES) count = MAX_CAP_HANDLES;
   1888      while((currentAddr = NvNextEvict(&iter)) != 0)
   1889      {
   1890          TPM_HANDLE      entityHandle;
   1891           // Read handle information.
   1892           _plat__NvMemoryRead(currentAddr, sizeof(TPM_HANDLE), &entityHandle);
   1893           // Ignore persistent handles that have values less than the input handle
   1894           if(entityHandle < handle)
   1895               continue;
   1896           // if the handles in the list have reached the requested count, and there
   1897           // are still handles need to be inserted, indicate that there are more.
   1898           if(handleList->count == count)
   1899               more = YES;
   1900           // A handle with a value larger than start handle is a candidate
   1901           // for return. Insert sort it to the return list. Insert sort algorithm
   1902           // is chosen here for simplicity based on the assumption that the total
   1903           // number of NV Indices is small. For an implementation that may allow
   1904           // large number of NV Indices, a more efficient sorting algorithm may be
   1905           // used here.
   1906           InsertSort(handleList, count, entityHandle);
   1907 //
   1908      }
   1909      return more;
   1910 }
   1911 //
   1912 //
   1913 //            NvCapGetIndex()
   1914 //
   1915 //       This function returns a list of handles of NV Indices, starting from handle. Handle must be in the range of
   1916 //       NV Indices, but does not have to reference an existing NV Index.
   1917 //
   1918 //       Return Value                      Meaning
   1919 //
   1920 //       YES                               if there are more handles to report
   1921 //       NO                                all the available handles has been reported
   1922 //
   1923 TPMI_YES_NO
   1924 NvCapGetIndex(
   1925      TPMI_DH_OBJECT     handle,              // IN: start handle
   1926      UINT32             count,               // IN: maximum number of returned handle
   1927      TPML_HANDLE       *handleList           // OUT: list of handle
   1928      )
   1929 {
   1930      TPMI_YES_NO             more = NO;
   1931      NV_ITER                 iter = NV_ITER_INIT;
   1932      UINT32                  currentAddr;
   1933      pAssert(HandleGetType(handle) == TPM_HT_NV_INDEX);
   1934      // Initialize output handle list
   1935      handleList->count = 0;
   1936      // The maximum count of handles we may return is MAX_CAP_HANDLES
   1937      if(count > MAX_CAP_HANDLES) count = MAX_CAP_HANDLES;
   1938      while((currentAddr = NvNextIndex(&iter)) != 0)
   1939      {
   1940          TPM_HANDLE      entityHandle;
   1941           // Read handle information.
   1942           _plat__NvMemoryRead(currentAddr, sizeof(TPM_HANDLE), &entityHandle);
   1943           // Ignore index handles that have values less than the 'handle'
   1944           if(entityHandle < handle)
   1945               continue;
   1946           // if the count of handles in the list has reached the requested count,
   1947           // and there are still handles to report, set more.
   1948           if(handleList->count == count)
   1949               more = YES;
   1950           // A handle with a value larger than start handle is a candidate
   1951           // for return. Insert sort it to the return list. Insert sort algorithm
   1952           // is chosen here for simplicity based on the assumption that the total
   1953           // number of NV Indices is small. For an implementation that may allow
   1954           // large number of NV Indices, a more efficient sorting algorithm may be
   1955           // used here.
   1956           InsertSort(handleList, count, entityHandle);
   1957      }
   1958      return more;
   1959 }
   1960 //
   1961 //
   1962 //
   1963 //           NvCapGetIndexNumber()
   1964 //
   1965 //       This function returns the count of NV Indexes currently defined.
   1966 //
   1967 UINT32
   1968 NvCapGetIndexNumber(
   1969    void
   1970    )
   1971 {
   1972    UINT32              num = 0;
   1973    NV_ITER             iter = NV_ITER_INIT;
   1974    while(NvNextIndex(&iter) != 0) num++;
   1975    return num;
   1976 }
   1977 //
   1978 //
   1979 //           NvCapGetPersistentNumber()
   1980 //
   1981 //       Function returns the count of persistent objects currently in NV memory.
   1982 //
   1983 UINT32
   1984 NvCapGetPersistentNumber(
   1985    void
   1986    )
   1987 {
   1988    UINT32              num = 0;
   1989    NV_ITER             iter = NV_ITER_INIT;
   1990    while(NvNextEvict(&iter) != 0) num++;
   1991    return num;
   1992 }
   1993 //
   1994 //
   1995 //           NvCapGetPersistentAvail()
   1996 //
   1997 //       This function returns an estimate of the number of additional persistent objects that could be loaded into
   1998 //       NV memory.
   1999 //
   2000 UINT32
   2001 NvCapGetPersistentAvail(
   2002    void
   2003    )
   2004 {
   2005    UINT32              availSpace;
   2006    UINT32              objectSpace;
   2007    // Compute the available space in NV storage
   2008    availSpace = NvGetFreeByte();
   2009    // Get the space needed to add a persistent object to NV storage
   2010    objectSpace = NvGetEvictObjectSize();
   2011    return availSpace / objectSpace;
   2012 }
   2013 //
   2014 //
   2015 //           NvCapGetCounterNumber()
   2016 //
   2017 //       Get the number of defined NV Indexes that have NV TPMA_NV_COUNTER attribute SET.
   2018 //
   2019 //
   2020 UINT32
   2021 NvCapGetCounterNumber(
   2022    void
   2023    )
   2024 {
   2025    NV_ITER             iter = NV_ITER_INIT;
   2026    UINT32              currentAddr;
   2027    UINT32              num = 0;
   2028    while((currentAddr = NvNextIndex(&iter)) != 0)
   2029    {
   2030        NV_INDEX    nvIndex;
   2031           // Get NV Index info
   2032           _plat__NvMemoryRead(currentAddr + sizeof(TPM_HANDLE),
   2033                                sizeof(NV_INDEX), &nvIndex);
   2034           if(nvIndex.publicArea.attributes.TPMA_NV_COUNTER == SET) num++;
   2035    }
   2036    return num;
   2037 }
   2038 //
   2039 //
   2040 //            NvCapGetCounterAvail()
   2041 //
   2042 //       This function returns an estimate of the number of additional counter type NV Indices that can be defined.
   2043 //
   2044 UINT32
   2045 NvCapGetCounterAvail(
   2046    void
   2047    )
   2048 {
   2049    UINT32              availNVSpace;
   2050    UINT32              availRAMSpace;
   2051    UINT32              counterNVSpace;
   2052    UINT32              counterRAMSpace;
   2053    UINT32              persistentNum = NvCapGetPersistentNumber();
   2054    // Get the available space in NV storage
   2055    availNVSpace = NvGetFreeByte();
   2056    if (persistentNum < MIN_EVICT_OBJECTS)
   2057    {
   2058        // Some space have to be reserved for evict object. Adjust availNVSpace.
   2059        UINT32       reserved = (MIN_EVICT_OBJECTS - persistentNum)
   2060                               * NvGetEvictObjectSize();
   2061        if (reserved > availNVSpace)
   2062             availNVSpace = 0;
   2063        else
   2064             availNVSpace -= reserved;
   2065    }
   2066    // Get the space needed to add a counter index to NV storage
   2067    counterNVSpace = NvGetCounterSize();
   2068    // Compute the available space in RAM
   2069    availRAMSpace = RAM_INDEX_SPACE - s_ramIndexSize;
   2070    // Compute the space needed to add a counter index to RAM storage
   2071    // It takes an size field, a handle and sizeof(UINT64) for counter data
   2072    counterRAMSpace = sizeof(UINT32) + sizeof(TPM_HANDLE) + sizeof(UINT64);
   2073    // Return the min of counter number in NV and in RAM
   2074    if(availNVSpace / counterNVSpace > availRAMSpace / counterRAMSpace)
   2075        return availRAMSpace / counterRAMSpace;
   2076      else
   2077          return availNVSpace / counterNVSpace;
   2078 }
   2079