Secure DPU: Allocate buffer from NS
New commands are added to the secure DPU:
SECURE_DPU_CMD_ALLOCATE_BUFFER: this command sends the request to NS
for allocating buffer with buffer length as the argument. The response
indicates the handle used to map the buffer on the Trusty.
Bug: 176508588
Change-Id: Ida8cbee736bb77928b4abfe45fad059930ae2bc9
diff --git a/interface/secure_dpu/include/interface/secure_dpu/secure_dpu.h b/interface/secure_dpu/include/interface/secure_dpu/secure_dpu.h
index 921d24b..b939d44 100644
--- a/interface/secure_dpu/include/interface/secure_dpu/secure_dpu.h
+++ b/interface/secure_dpu/include/interface/secure_dpu/secure_dpu.h
@@ -23,13 +23,18 @@
*
* The Secure DPU works as the persistent channel between the non-secure and the
* secure world. The channel is established during the boot up stage of the
- * non-secure world system.
+ * non-secure world system. In general, the established channel allows the
+ * secure world applications initiate requests or notifications to the non-secure
+ * world.
*
- * The channel allows the secure world application to issue commands with
- * operations needed to be performed by the non-secure world system. These
- * operations include starting / stopping the secure display mode. The secure
- * world application can only control the display when the system is set as the
- * secure display mode.
+ * For particular devices, the secure world can only perform operations on the
+ * display when in the TUI session if device-specific setup is done by the
+ * non-secure world. Besides, the non-secure world could allocate framebuffer
+ * for the secure world application if the memory is limited in the secure world
+ * on specific devices.
+ *
+ * Currently, supported requests are to start / stop the secure display mode and
+ * to allocate framebuffer.
*
* This header file needs to be synced on both the Trusty and the Android
* codebase.
@@ -48,12 +53,35 @@
* Notify the system to start secure display mode
* @SECURE_DPU_CMD_STOP_SECURE_DISPLAY:
* Notify the system to stop secure display mode
+ * @SECURE_DPU_CMD_ALLOCATE_BUFFER:
+ * Request non-secure world to allocate the buffer
*/
enum secure_dpu_cmd {
SECURE_DPU_CMD_RESP_BIT = 1,
SECURE_DPU_CMD_REQ_SHIFT = 1,
SECURE_DPU_CMD_START_SECURE_DISPLAY = (1 << SECURE_DPU_CMD_REQ_SHIFT),
SECURE_DPU_CMD_STOP_SECURE_DISPLAY = (2 << SECURE_DPU_CMD_REQ_SHIFT),
+ SECURE_DPU_CMD_ALLOCATE_BUFFER = (3 << SECURE_DPU_CMD_REQ_SHIFT),
+};
+
+/**
+ * struct secure_dpu_allocate_buffer_req - payload for
+ * %SECURE_DPU_CMD_ALLOCATE_BUFFER
+ * request
+ * @buffer_len: Requested length
+ */
+struct secure_dpu_allocate_buffer_req {
+ uint64_t buffer_len;
+};
+
+/**
+ * struct secure_dpu_allocate_buffer_resp - payload for
+ * %SECURE_DPU_CMD_ALLOCATE_BUFFER
+ * response
+ * @buffer_len: Allocated length
+ */
+struct secure_dpu_allocate_buffer_resp {
+ uint64_t buffer_len;
};
/**
diff --git a/lib/secure_dpu/include/lib/secure_dpu/secure_dpu.h b/lib/secure_dpu/include/lib/secure_dpu/secure_dpu.h
index 6d6d604..43d0d0d 100644
--- a/lib/secure_dpu/include/lib/secure_dpu/secure_dpu.h
+++ b/lib/secure_dpu/include/lib/secure_dpu/secure_dpu.h
@@ -21,6 +21,11 @@
__BEGIN_CDECLS
+struct secure_dpu_buf_info {
+ void* addr;
+ size_t len;
+};
+
/**
* add_secure_dpu_service() - Add secure_dpu service.
* @hset: pointer to the tipc hset.
@@ -38,21 +43,22 @@
/**
* secure_dpu_allocate_buffer() - Allocate framebuffer.
* @chan: channel handle
- * @buffer_ptr: The physical address of the allocated buffer
- * @buffer_len: The requested size / The size of the allocated buffer
+ * @buffer_len: requested length of the buffer
+ * @buf_info: information of the allocated buffer.
*
* Return: 0 on success, or an error code < 0 on failure.
*/
-int secure_dpu_allocate_buffer(handle_t chan, void** buffer_ptr, size_t* buffer_len);
+int secure_dpu_allocate_buffer(handle_t chan,
+ size_t buffer_len,
+ struct secure_dpu_buf_info* buf_info);
/**
- * secure_dpu_free_buffer() - free framebuffer.
- * @chan: channel handle
- * @buffer_ptr: pointer to buffer to be freed
+ * secure_dpu_release_buffer() - release framebuffer.
+ * @buf_info: information of the buffer to be freed
*
* Return: 0 on success, or an error code < 0 on failure.
*/
-int secure_dpu_free_buffer(handle_t chan, void* buffer_ptr);
+int secure_dpu_release_buffer(struct secure_dpu_buf_info* buf_info);
/**
* secure_dpu_start_secure_display() - notify DPU driver to start secure display
diff --git a/lib/secure_dpu/secure_dpu.c b/lib/secure_dpu/secure_dpu.c
index f26046a..43cffc5 100644
--- a/lib/secure_dpu/secure_dpu.c
+++ b/lib/secure_dpu/secure_dpu.c
@@ -24,6 +24,7 @@
#include <stdlib.h>
#include <string.h>
#include <sys/auxv.h>
+#include <sys/mman.h>
#include <trusty_ipc.h>
#include <trusty_log.h>
#include <uapi/err.h>
@@ -37,7 +38,6 @@
* Update this pointer when connecting / disconnecting.
*/
handle_t* chan;
- void* fb_buf_ptr;
};
static struct secure_dpu_ctx ctx;
@@ -53,8 +53,98 @@
.priv = &ctx,
};
-int secure_dpu_allocate_buffer(handle_t chan, void** buffer_ptr, size_t* buffer_len) {
- if (!buffer_ptr || !buffer_len) {
+static int handle_allocate_buffer_resp(handle_t chan,
+ size_t buffer_len,
+ struct secure_dpu_buf_info* buf_info) {
+ int rc = NO_ERROR;
+ struct uevent evt;
+ struct secure_dpu_resp hdr;
+ struct secure_dpu_allocate_buffer_resp resp;
+ handle_t buf_handle;
+
+ struct iovec iov[] = {
+ {
+ .iov_base = &hdr,
+ .iov_len = sizeof(hdr),
+ },
+ {
+ .iov_base = &resp,
+ .iov_len = sizeof(resp),
+ },
+ };
+
+ struct ipc_msg msg = {
+ .iov = iov,
+ .num_iov = countof(iov),
+ .handles = &buf_handle,
+ .num_handles = 1,
+ };
+
+ rc = wait(chan, &evt, INFINITE_TIME);
+ if (rc != NO_ERROR) {
+ TLOGE("Error waiting for response (%d)\n", rc);
+ return rc;
+ }
+
+ struct ipc_msg_info msg_inf;
+ rc = get_msg(chan, &msg_inf);
+ if (rc) {
+ return rc;
+ }
+
+ if (msg_inf.num_handles != 1) {
+ TLOGE("Message had no handles\n");
+ return ERR_INVALID_ARGS;
+ }
+
+ rc = read_msg(chan, msg_inf.id, 0, &msg);
+ put_msg(chan, msg_inf.id);
+ if (rc != (int)(sizeof(hdr) + sizeof(resp))) {
+ TLOGE("Read length does not match\n");
+ close(buf_handle);
+ return ERR_BAD_LEN;
+ }
+
+ if (hdr.cmd != (SECURE_DPU_CMD_ALLOCATE_BUFFER | SECURE_DPU_CMD_RESP_BIT)) {
+ close(buf_handle);
+ return ERR_CMD_UNKNOWN;
+ }
+
+ if (hdr.status != SECURE_DPU_ERROR_OK) {
+ TLOGE("Failed SECURE_DPU_CMD_ALLOCATE_BUFFER (%d)\n", hdr.status);
+ close(buf_handle);
+ return ERR_GENERIC;
+ }
+
+ if ((size_t)resp.buffer_len < buffer_len) {
+ TLOGE("Not allocated enough buffer length, "
+ "requested (%zu), allocated (%zu)\n", (size_t)buffer_len,
+ (size_t)resp.buffer_len);
+ close(buf_handle);
+ return ERR_NOT_ENOUGH_BUFFER;
+ }
+
+ void* out = mmap(0, (size_t)resp.buffer_len, PROT_READ | PROT_WRITE, 0,
+ buf_handle, 0);
+ if (!out) {
+ TLOGE("Error when calling mmap()\n");
+ return ERR_BAD_HANDLE;
+ }
+ close(buf_handle);
+ buf_info->addr = (void*)out;
+ buf_info->len = (size_t)resp.buffer_len;
+
+ return NO_ERROR;
+}
+
+int secure_dpu_allocate_buffer(handle_t chan,
+ size_t buffer_len,
+ struct secure_dpu_buf_info* buf_info) {
+
+ int rc;
+ struct secure_dpu_req hdr;
+ struct secure_dpu_allocate_buffer_req args;
+ if (!buf_info) {
TLOGE("Invalid arguments to allocate DPU buffer\n");
return ERR_INVALID_ARGS;
}
@@ -63,26 +153,35 @@
return ERR_NOT_READY;
}
- /* TODO: allocate buffer from NS */
- if (!ctx.fb_buf_ptr) {
- ctx.fb_buf_ptr = memalign(getauxval(AT_PAGESZ), *buffer_len);
- }
- if (!ctx.fb_buf_ptr) {
- return ERR_NO_MEMORY;
- }
- *buffer_ptr = ctx.fb_buf_ptr;
+ hdr.cmd = SECURE_DPU_CMD_ALLOCATE_BUFFER;
+ args.buffer_len = (uint64_t)buffer_len;
- return NO_ERROR;
+ rc = tipc_send2(chan, &hdr, sizeof(hdr), &args, sizeof(args));
+ if (rc != (int)(sizeof(hdr) + sizeof(args))) {
+ TLOGE("Failed to send SECURE_DPU_CMD_ALLOCATE_BUFFER request (%d)\n", rc);
+ return rc;
+ }
+
+ rc = handle_allocate_buffer_resp(chan, buffer_len, buf_info);
+ if (rc < 0) {
+ TLOGE("Failed to handle allocate buffer\n");
+ return rc;
+ }
+ return rc;
}
-int secure_dpu_free_buffer(handle_t chan, void* buffer_ptr) {
-
- if (chan == INVALID_IPC_HANDLE) {
- TLOGE("Channel is not ready\n");
- return ERR_NOT_READY;
+int secure_dpu_release_buffer(struct secure_dpu_buf_info* buf_info) {
+ if (!buf_info) {
+ TLOGE("Invalid arguments to release DPU buffer\n");
+ return ERR_INVALID_ARGS;
}
- /* TODO: free buffer from NS */
+ int rc = munmap(buf_info->addr, buf_info->len);
+ if (rc < 0) {
+ TLOGE("Failed to do munmap\n");
+ return rc;
+ }
+
return NO_ERROR;
}
@@ -98,7 +197,7 @@
}
rc = tipc_recv1(chan, sizeof(hdr), &hdr, sizeof(hdr));
- if (rc < 0) {
+ if (rc != sizeof(hdr)) {
TLOGE("Failed to receive SECURE_DPU_CMD_START_SECURE_DISPLAY response (%d)\n", rc);
return rc;
}
@@ -147,7 +246,7 @@
}
rc = tipc_recv1(chan, sizeof(hdr), &hdr, sizeof(hdr));
- if (rc < 0) {
+ if (rc != sizeof(hdr)) {
TLOGE("Failed to receive SECURE_DPU_CMD_STOP_SECURE_DISPLAY response (%d)\n", rc);
return rc;
}