1 // This file was extracted from the TCG Published
2 // Trusted Platform Module Library
3 // Part 3: Commands
4 // Family "2.0"
5 // Level 00 Revision 01.16
6 // October 30, 2014
7 
8 #include "InternalRoutines.h"
9 #include "NV_SetBits_fp.h"
10 #include "NV_spt_fp.h"
11 //
12 //
13 //     Error Returns                 Meaning
14 //
15 //     TPM_RC_ATTRIBUTES             the TPMA_NV_BITS attribute is not SET in the Index referenced by
16 //                                   nvIndex
17 //     TPM_RC_NV_AUTHORIZATION       the authorization was valid but the authorizing entity (authHandle) is
18 //                                   not allowed to write to the Index referenced by nvIndex
19 //     TPM_RC_NV_LOCKED              the Index referenced by nvIndex is locked for writing
20 //
21 TPM_RC
TPM2_NV_SetBits(NV_SetBits_In * in)22 TPM2_NV_SetBits(
23    NV_SetBits_In     *in              // IN: input parameter list
24    )
25 {
26    TPM_RC            result;
27    NV_INDEX          nvIndex;
28    UINT64            oldValue;
29    UINT64            newValue;
30 
31 // Input Validation
32 
33    // Common access checks, NvWriteAccessCheck() may return TPM_RC_NV_AUTHORIZATION
34    // or TPM_RC_NV_LOCKED
35    // error may be returned at this point
36    result = NvWriteAccessChecks(in->authHandle, in->nvIndex);
37    if(result != TPM_RC_SUCCESS)
38        return result;
39 
40    // Get NV index info
41    NvGetIndexInfo(in->nvIndex, &nvIndex);
42 
43    // Make sure that this is a bit field
44    if(nvIndex.publicArea.attributes.TPMA_NV_BITS != SET)
45        return TPM_RC_ATTRIBUTES + RC_NV_SetBits_nvIndex;
46 
47    // If index is not been written, initialize it
48    if(nvIndex.publicArea.attributes.TPMA_NV_WRITTEN == CLEAR)
49        oldValue = 0;
50    else
51        // Read index data
52        NvGetIntIndexData(in->nvIndex, &nvIndex, &oldValue);
53 
54    // Figure out what the new value is going to be
55    newValue = oldValue | in->bits;
56 
57    // If the Index is not-orderly and it has changed, or if this is the first
58    // write, NV will need to be updated.
59    if(    (    nvIndex.publicArea.attributes.TPMA_NV_ORDERLY == CLEAR
60            && newValue != oldValue)
61        || nvIndex.publicArea.attributes.TPMA_NV_WRITTEN == CLEAR)
62    {
63 
64 // Internal Data Update
65        // Check if NV is available. NvIsAvailable may return TPM_RC_NV_UNAVAILABLE
66        // TPM_RC_NV_RATE or TPM_RC_SUCCESS.
67        result = NvIsAvailable();
68        if(result != TPM_RC_SUCCESS)
69            return result;
70 
71        // Write index data back. If necessary, this function will SET
72        // TPMA_NV_WRITTEN.
73        result = NvWriteIndexData(in->nvIndex, &nvIndex, 0, 8, &newValue);
74    }
75    return result;
76 
77 }
78