Blob Blame History Raw
From 26970c42bc017ad68b864e7134cf941c07443aa8 Mon Sep 17 00:00:00 2001
From: Chris Engel <cengel@linux.vnet.ibm.com>
Date: Tue, 22 Aug 2017 14:59:06 -0500
Subject: [PATCH] Interface for ibm,physical-attestation rtas call

The physical attestation interfaces are provided to allow a
trusted 3rd party client to retrieve information about the
trusted boot state of the target PowerVM system.  This makes
use of the systems physical TPM(s).  These TPM(s) are used
by system firmware to extend measurements during the
boot process.

Signed-off-by: Chris Engel <cengel@linux.vnet.ibm.com>
Reviewed-by: Vasant Hegde <hegdevasant@linux.vnet.ibm.com>
Signed-off-by: Tyrel Datwyler <tyreld@linux.vnet.ibm.com>
---
 librtas_src/librtas.h       |  2 ++
 librtas_src/syscall_calls.c | 63 +++++++++++++++++++++++++++++++++++++++++++++
 2 files changed, 65 insertions(+)

diff --git a/librtas_src/librtas.h b/librtas_src/librtas.h
index ccab3d9..b84fab1 100644
--- a/librtas_src/librtas.h
+++ b/librtas_src/librtas.h
@@ -105,6 +105,8 @@ extern int rtas_set_time(uint32_t year, uint32_t month, uint32_t day,
 extern int rtas_suspend_me(uint64_t streamid);
 extern int rtas_update_nodes(char *workarea, unsigned int scope);
 extern int rtas_update_properties(char *workarea, unsigned int scope);
+extern int rtas_physical_attestation(char *workarea, int seq_num,
+				     int *next_seq_num, int *work_area_bytes);
 
 #ifdef __cplusplus
 }
diff --git a/librtas_src/syscall_calls.c b/librtas_src/syscall_calls.c
index a194e4b..35b6d66 100644
--- a/librtas_src/syscall_calls.c
+++ b/librtas_src/syscall_calls.c
@@ -1329,3 +1329,66 @@ int rtas_update_properties(char *workarea, unsigned int scope)
 	dbg("(%p) %d = %d\n", workarea, scope, rc ? rc : status);
 	return rc ? rc : status;
 }
+
+/**
+ * rtas_physical_attestation
+ * @brief Interface for ibm,physical-attestation rtas call.
+ *
+ * @param workarea input/output work area for rtas call
+ * @param seq_num sequence number of the rtas call
+ * @param next_seq_num next sequence number
+ * @param work_area_bytes size of work area
+ * @return 0 on success, !0 on failure
+ */
+int rtas_physical_attestation(char *workarea, int seq_num, int *next_seq_num,
+			      int *work_area_bytes)
+{
+	uint32_t workarea_pa;
+	uint64_t elapsed = 0;
+	void *kernbuf;
+	int kbuf_sz = 4096;
+	int rc, status;
+	int resp_bytes = *work_area_bytes;
+
+	rc = sanity_check();
+	if (rc)
+		return rc;
+
+	/* Caller provided more data than FW can handle */
+	if (*work_area_bytes == 0 ||
+	    *work_area_bytes > kbuf_sz)
+		return RTAS_IO_ASSERT;
+
+	rc = rtas_get_rmo_buffer(kbuf_sz, &kernbuf, &workarea_pa);
+	if (rc)
+		return rc;
+	memcpy(kernbuf, workarea, *work_area_bytes);
+
+	do {
+		rc = rtas_call("ibm,physical-attestation", 3, 3,
+			       htobe32(workarea_pa), htobe32(kbuf_sz),
+			       htobe32(seq_num),
+			       &status, next_seq_num, &resp_bytes);
+		if (rc < 0)
+			break;
+
+		rc = handle_delay(status, &elapsed);
+	} while (rc == CALL_AGAIN);
+
+	*next_seq_num = be32toh(*next_seq_num);
+
+	/* FW returned more data than we can handle */
+	if (be32toh(resp_bytes) > *work_area_bytes) {
+		(void)rtas_free_rmo_buffer(kernbuf, workarea_pa, kbuf_sz);
+		return RTAS_IO_ASSERT;
+	}
+
+	*work_area_bytes = be32toh(resp_bytes);
+
+	if (rc == 0)
+		memcpy(workarea, kernbuf, *work_area_bytes);
+
+	(void)rtas_free_rmo_buffer(kernbuf, workarea_pa, kbuf_sz);
+
+	return rc ? rc : status;
+}
-- 
2.9.5