Add function that displays TPM_PERMANENT_FLAGS requiring arguments

Signed-off-by:Xiaokai Wang <xiaokai.wang@intel.com>

diff --git a/src/tpm_mgmt/tpm_nvinfo.c b/src/tpm_mgmt/tpm_nvinfo.c
index 8964681..6287c95 100644
--- a/src/tpm_mgmt/tpm_nvinfo.c
+++ b/src/tpm_mgmt/tpm_nvinfo.c
@@ -26,9 +26,12 @@
 #include "tpm_utils.h"
 #include "tpm_nvcommon.h"
 
+#define BUFFER_SIZE 1024
 
 static BOOL nvindex_set;
 static unsigned int nvindex;
+static const char *ownerpassword;
+static int perm_flags;
 static BOOL list_only;
 TSS_HCONTEXT hContext = 0;
 
@@ -51,6 +54,14 @@ static int parse(const int aOpt, const char *aArg)
 		nvindex_set = FALSE;
 		break;
 
+	case 'f':
+		perm_flags = 1;
+		break;
+
+	case 'o':
+		ownerpassword = aArg;
+		break;
+
 	default:
 		return -1;
 	}
@@ -64,6 +75,12 @@ static void help(const char* aCmd)
 	logNVIndexCmdOption();
 	logCmdOption("-n, --list-only",
 		     _("Only list the defined NVRAM areas' indices."));
+
+	logCmdOption("-f, --flags",
+		     _("Displays TPM_PERMANENT_FLAGS."));
+
+	logCmdOption("-o, --pwdo",
+		     _("Owner password."));
 }
 
 
@@ -142,10 +159,155 @@ static void nvindexDisplay(TSS_HTPM hTpm, UINT32 nvindex)
 	return;
 }
 
+const char *bool_to_str(int b)
+{
+	return b ? "TRUE" : "FALSE";
+}
+
+void Decode_copy_UINT32(uint32_t *out,unsigned char **blob)
+{
+	*out = Decode_UINT32((BYTE *)*blob);
+	*blob += sizeof(*out);
+}
+
+typedef struct {
+	uint32_t disable                            : 1;
+	uint32_t ownership                          : 1;
+	uint32_t deactivated                        : 1;
+	uint32_t readPubek                          : 1;
+	uint32_t disableOwnerClear                  : 1;
+	uint32_t allowMaintenance                   : 1;
+	uint32_t physicalPresenceLifetimeLock       : 1;
+	uint32_t physicalPresenceHWEnable           : 1;
+	uint32_t physicalPresenceCMDEnable          : 1;
+	uint32_t CEKPUsed                           : 1;
+	uint32_t TPMpost                            : 1;
+	uint32_t TPMpostLock                        : 1;
+	uint32_t FIPS                               : 1;
+	uint32_t Operator                           : 1;
+	uint32_t enableRevokeEK                     : 1;
+	uint32_t nvLocked                           : 1;
+	uint32_t readSRKPub                         : 1;
+	uint32_t tpmEstablished                     : 1;
+	uint32_t maintenanceDone                    : 1;
+} tpm_perm_flags_t;
+
+typedef struct {
+	uint32_t deactivated              : 1;
+	uint32_t disableForceClear        : 1;
+	uint32_t physicalPresence         : 1;
+	uint32_t physicalPresenceLock     : 1;
+	uint32_t bGlobalLock              : 1;
+} tpm_stclear_flags_t;
+
+TSS_RESULT
+display_flags(void)
+{
+	TSS_HPOLICY htpmpolicy = 0;
+	TSS_HCONTEXT hcontext = 0;
+	TSS_HTPM htpm = 0;
+
+	uint32_t i;
+	uint32_t subcap = 0;
+	uint32_t datasize = 0;
+	unsigned char *pbuf;
+	int opswd_len = -1;
+	tpm_perm_flags_t perm_flags;
+	tpm_stclear_flags_t stclear_flags;
+
+	if (contextCreate(&hcontext) != TSS_SUCCESS)
+		goto out_close;
+
+	if (contextConnect(hcontext) != TSS_SUCCESS)
+		goto out_close;
+
+	if (contextGetTpm(hcontext, &htpm) != TSS_SUCCESS)
+		goto out_close;
+
+	if (policyGet(htpm, &htpmpolicy) != TSS_SUCCESS)
+		goto out_close;
+	if (opswd_len < 0)
+		opswd_len = strlen(ownerpassword);
+	if (policySetSecret(htpmpolicy, opswd_len,
+				(BYTE *)ownerpassword) != TSS_SUCCESS)
+		goto out_close;
+
+	if (getCapability(htpm, TSS_TPMCAP_FLAG, 4, (unsigned char *)&subcap,
+	              &datasize, &pbuf) != TSS_SUCCESS) {
+		logMsg(_("error getting TPM_PERMANENT_FLAGS.\n"));
+		goto out_close;
+	}
+
+	if (datasize != 2*sizeof(uint32_t)) {
+		logMsg(_("error getting TPM_PERMANENT_FLAGS.\n"));
+		goto out_close;
+	}
+
+	if (pbuf == NULL) {
+		logMsg(_("error getting TPM_PERMANENT_FLAGS.\n"));
+		goto out_close;
+	}
+
+	logMsg("The response data is:\n");
+	for (i = 0; i < datasize; i++) {
+		logMsg("%02x ", pbuf[i]);
+
+		if (i%16 == 15)
+			logMsg("\n");
+	}
+	logMsg("\n");
+
+	Decode_copy_UINT32((uint32_t *)&perm_flags, &pbuf);
+	Decode_copy_UINT32((uint32_t *)&stclear_flags, &pbuf);
+
+	logMsg("TPM_PERMANENT_FLAGS:\n");
+	logMsg("\t disable: %s\n", bool_to_str(perm_flags.disable));
+	logMsg("\t ownership: %s\n", bool_to_str(perm_flags.ownership));
+	logMsg("\t deactivated: %s\n", bool_to_str(perm_flags.deactivated));
+	logMsg("\t readPubek: %s\n", bool_to_str(perm_flags.readPubek));
+	logMsg("\t disableOwnerClear: %s\n",
+	           bool_to_str(perm_flags.disableOwnerClear));
+	logMsg("\t allowMaintenance: %s\n",
+	           bool_to_str(perm_flags.allowMaintenance));
+	logMsg("\t physicalPresenceLifetimeLock: %s\n",
+	           bool_to_str(perm_flags.physicalPresenceLifetimeLock));
+	logMsg("\t physicalPresenceHWEnable: %s\n",
+	           bool_to_str(perm_flags.physicalPresenceHWEnable));
+	logMsg("\t physicalPresenceCMDEnable: %s\n",
+	           bool_to_str(perm_flags.physicalPresenceCMDEnable));
+	logMsg("\t CEKPUsed: %s\n", bool_to_str(perm_flags.CEKPUsed));
+	logMsg("\t TPMpost: %s\n", bool_to_str(perm_flags.TPMpost));
+	logMsg("\t TPMpostLock: %s\n", bool_to_str(perm_flags.TPMpostLock));
+	logMsg("\t FIPS: %s\n", bool_to_str(perm_flags.FIPS));
+	logMsg("\t Operator: %s\n", bool_to_str(perm_flags.Operator));
+	logMsg("\t enableRevokeEK: %s\n",
+	           bool_to_str(perm_flags.enableRevokeEK));
+	logMsg("\t nvLocked: %s\n", bool_to_str(perm_flags.nvLocked));
+	logMsg("\t readSRKPub: %s\n", bool_to_str(perm_flags.readSRKPub));
+	logMsg("\t tpmEstablished: %s\n",
+	           bool_to_str(perm_flags.tpmEstablished));
+	logMsg("\t maintenanceDone: %s\n",
+	           bool_to_str(perm_flags.maintenanceDone));
+
+	logMsg("\nTPM_STCLEAR_FLAGS:\n");
+	logMsg("\t deactivated: %s\n", bool_to_str(stclear_flags.deactivated));
+	logMsg("\t disableForceClear: %s\n",
+	           bool_to_str(stclear_flags.disableForceClear));
+	logMsg("\t physicalPresence: %s\n",
+	           bool_to_str(stclear_flags.physicalPresence));
+	logMsg("\t physicalPresenceLock: %s\n",
+	           bool_to_str(stclear_flags.physicalPresenceLock));
+	logMsg("\t bGlobalLock: %s\n", bool_to_str(stclear_flags.bGlobalLock));
+
+	out_close:
+	contextClose(hcontext);
+
+	return TSS_SUCCESS;
+}
 
 int main(int argc, char **argv)
 {
-	TSS_HTPM hTpm;
+	TSS_HTPM hTpm = 0;
 	UINT32 ulResultLen;
 	BYTE *pResult = NULL;
 	int iRc = -1;
@@ -153,16 +315,30 @@ int main(int argc, char **argv)
 	struct option hOpts[] = {
 		{"index"    , required_argument, NULL, 'i'},
 		{"list-only",       no_argument, NULL, 'n'},
+		{"ownpasswd", required_argument, NULL, 'o'},
+		{"flags"    ,       no_argument, NULL, 'f'},
 		{NULL       ,       no_argument, NULL, 0},
 	};
 
 	initIntlSys();
 
 	if (genericOptHandler
-		    (argc, argv, "i:o:n", hOpts,
+		    (argc, argv, "i:o:f:n", hOpts,
 		     sizeof(hOpts) / sizeof(struct option), parse, help) != 0)
 		goto out;
 
+	if (perm_flags) {
+		if (ownerpassword == NULL) {
+			logMsg(_("no passwd input!need ownerpassword to display flags.\n"));
+			return iRc;
+		} else if (display_flags() != TSS_SUCCESS)
+			return iRc;
+
+		iRc = 0;
+
+		return iRc;
+	}
+
 	if (contextCreate(&hContext) != TSS_SUCCESS)
 		goto out;
 
