mirror of
https://github.com/Divested-Mobile/DivestOS-Build.git
synced 2024-12-12 01:14:22 -05:00
9752 lines
266 KiB
Diff
9752 lines
266 KiB
Diff
From 04468bc1d72f15e6b8f19014e8c6203038dd6b23 Mon Sep 17 00:00:00 2001
|
|
From: Maggie White <maggiewhite@google.com>
|
|
Date: Fri, 2 Jun 2017 18:10:06 -0700
|
|
Subject: [PATCH] msm: gud: Remove gud driver
|
|
|
|
Complete removal of gud mobicore driver.
|
|
The driver author delivers an updated version of the driver to
|
|
interested parties directly rendering this version obsolete.
|
|
|
|
Bug: 33842910
|
|
CRs-Fixed: 1116560
|
|
Change-Id: I40498d3203b1d6ca04f2b5a2e65461851d84d2d4
|
|
Acked-by: Tony Hamilton <tonyh@qti.qualcomm.com>
|
|
Signed-off-by: Trudy Shearer <tshearer@codeaurora.org>
|
|
Signed-off-by: Dennis Cagle <d-cagle@codeaurora.org>
|
|
Signed-off-by: Maggie White <maggiewhite@google.com>
|
|
---
|
|
drivers/Kconfig | 2 -
|
|
drivers/Makefile | 3 -
|
|
drivers/gud/Kconfig | 35 -
|
|
drivers/gud/Makefile | 6 -
|
|
drivers/gud/MobiCoreDriver/Makefile | 33 -
|
|
drivers/gud/MobiCoreDriver/admin.c | 1011 -------------------
|
|
drivers/gud/MobiCoreDriver/admin.h | 32 -
|
|
drivers/gud/MobiCoreDriver/api.c | 419 --------
|
|
drivers/gud/MobiCoreDriver/api.h | 46 -
|
|
drivers/gud/MobiCoreDriver/arm.h | 88 --
|
|
drivers/gud/MobiCoreDriver/build_tag.h | 15 -
|
|
drivers/gud/MobiCoreDriver/client.c | 572 -----------
|
|
drivers/gud/MobiCoreDriver/client.h | 99 --
|
|
drivers/gud/MobiCoreDriver/clientlib.c | 433 --------
|
|
drivers/gud/MobiCoreDriver/clock.c | 161 ---
|
|
drivers/gud/MobiCoreDriver/clock.h | 53 -
|
|
drivers/gud/MobiCoreDriver/debug.h | 63 --
|
|
drivers/gud/MobiCoreDriver/fastcall.c | 512 ----------
|
|
drivers/gud/MobiCoreDriver/fastcall.h | 38 -
|
|
drivers/gud/MobiCoreDriver/logging.c | 251 -----
|
|
drivers/gud/MobiCoreDriver/logging.h | 51 -
|
|
drivers/gud/MobiCoreDriver/main.c | 750 --------------
|
|
drivers/gud/MobiCoreDriver/main.h | 60 --
|
|
drivers/gud/MobiCoreDriver/mci/mcifc.h | 144 ---
|
|
drivers/gud/MobiCoreDriver/mci/mcimcp.h | 508 ----------
|
|
drivers/gud/MobiCoreDriver/mci/mcinq.h | 86 --
|
|
drivers/gud/MobiCoreDriver/mci/mcloadformat.h | 134 ---
|
|
drivers/gud/MobiCoreDriver/mcp.c | 1067 --------------------
|
|
drivers/gud/MobiCoreDriver/mcp.h | 121 ---
|
|
drivers/gud/MobiCoreDriver/mmu.c | 450 ---------
|
|
drivers/gud/MobiCoreDriver/mmu.h | 44 -
|
|
drivers/gud/MobiCoreDriver/platform.h | 150 ---
|
|
drivers/gud/MobiCoreDriver/pm.c | 62 --
|
|
drivers/gud/MobiCoreDriver/pm.h | 36 -
|
|
drivers/gud/MobiCoreDriver/public/mc_admin.h | 80 --
|
|
drivers/gud/MobiCoreDriver/public/mc_linux.h | 170 ----
|
|
drivers/gud/MobiCoreDriver/public/mc_linux_api.h | 28 -
|
|
.../MobiCoreDriver/public/mobicore_driver_api.h | 450 ---------
|
|
drivers/gud/MobiCoreDriver/scheduler.c | 231 -----
|
|
drivers/gud/MobiCoreDriver/scheduler.h | 25 -
|
|
drivers/gud/MobiCoreDriver/session.c | 779 --------------
|
|
drivers/gud/MobiCoreDriver/session.h | 63 --
|
|
drivers/gud/setupDrivers.sh | 19 -
|
|
43 files changed, 9380 deletions(-)
|
|
delete mode 100644 drivers/gud/Kconfig
|
|
delete mode 100644 drivers/gud/Makefile
|
|
delete mode 100644 drivers/gud/MobiCoreDriver/Makefile
|
|
delete mode 100644 drivers/gud/MobiCoreDriver/admin.c
|
|
delete mode 100644 drivers/gud/MobiCoreDriver/admin.h
|
|
delete mode 100644 drivers/gud/MobiCoreDriver/api.c
|
|
delete mode 100644 drivers/gud/MobiCoreDriver/api.h
|
|
delete mode 100644 drivers/gud/MobiCoreDriver/arm.h
|
|
delete mode 100644 drivers/gud/MobiCoreDriver/build_tag.h
|
|
delete mode 100644 drivers/gud/MobiCoreDriver/client.c
|
|
delete mode 100644 drivers/gud/MobiCoreDriver/client.h
|
|
delete mode 100644 drivers/gud/MobiCoreDriver/clientlib.c
|
|
delete mode 100644 drivers/gud/MobiCoreDriver/clock.c
|
|
delete mode 100644 drivers/gud/MobiCoreDriver/clock.h
|
|
delete mode 100644 drivers/gud/MobiCoreDriver/debug.h
|
|
delete mode 100644 drivers/gud/MobiCoreDriver/fastcall.c
|
|
delete mode 100644 drivers/gud/MobiCoreDriver/fastcall.h
|
|
delete mode 100644 drivers/gud/MobiCoreDriver/logging.c
|
|
delete mode 100644 drivers/gud/MobiCoreDriver/logging.h
|
|
delete mode 100644 drivers/gud/MobiCoreDriver/main.c
|
|
delete mode 100644 drivers/gud/MobiCoreDriver/main.h
|
|
delete mode 100644 drivers/gud/MobiCoreDriver/mci/mcifc.h
|
|
delete mode 100644 drivers/gud/MobiCoreDriver/mci/mcimcp.h
|
|
delete mode 100644 drivers/gud/MobiCoreDriver/mci/mcinq.h
|
|
delete mode 100644 drivers/gud/MobiCoreDriver/mci/mcloadformat.h
|
|
delete mode 100644 drivers/gud/MobiCoreDriver/mcp.c
|
|
delete mode 100644 drivers/gud/MobiCoreDriver/mcp.h
|
|
delete mode 100644 drivers/gud/MobiCoreDriver/mmu.c
|
|
delete mode 100644 drivers/gud/MobiCoreDriver/mmu.h
|
|
delete mode 100644 drivers/gud/MobiCoreDriver/platform.h
|
|
delete mode 100644 drivers/gud/MobiCoreDriver/pm.c
|
|
delete mode 100644 drivers/gud/MobiCoreDriver/pm.h
|
|
delete mode 100644 drivers/gud/MobiCoreDriver/public/mc_admin.h
|
|
delete mode 100644 drivers/gud/MobiCoreDriver/public/mc_linux.h
|
|
delete mode 100644 drivers/gud/MobiCoreDriver/public/mc_linux_api.h
|
|
delete mode 100644 drivers/gud/MobiCoreDriver/public/mobicore_driver_api.h
|
|
delete mode 100644 drivers/gud/MobiCoreDriver/scheduler.c
|
|
delete mode 100644 drivers/gud/MobiCoreDriver/scheduler.h
|
|
delete mode 100644 drivers/gud/MobiCoreDriver/session.c
|
|
delete mode 100644 drivers/gud/MobiCoreDriver/session.h
|
|
delete mode 100644 drivers/gud/setupDrivers.sh
|
|
|
|
diff --git a/drivers/Kconfig b/drivers/Kconfig
|
|
index 0e7c68c62542a..8b796ec00009e 100644
|
|
--- a/drivers/Kconfig
|
|
+++ b/drivers/Kconfig
|
|
@@ -200,8 +200,6 @@ source "drivers/firmware/Kconfig"
|
|
|
|
source "drivers/bif/Kconfig"
|
|
|
|
-source "drivers/gud/Kconfig"
|
|
-
|
|
source "drivers/htc_mnemosyne/Kconfig"
|
|
|
|
endmenu
|
|
diff --git a/drivers/Makefile b/drivers/Makefile
|
|
index fb0cd18143ad5..13236262a1857 100644
|
|
--- a/drivers/Makefile
|
|
+++ b/drivers/Makefile
|
|
@@ -171,9 +171,6 @@ obj-$(CONFIG_BIF) += bif/
|
|
|
|
obj-$(CONFIG_SENSORS_SSC) += sensors/
|
|
|
|
-# <t-base drivers
|
|
-obj-$(CONFIG_MOBICORE_DRIVER) += gud/
|
|
-
|
|
# HTC debug
|
|
obj-$(CONFIG_HTC_DEBUG) += htc_debug/
|
|
obj-$(CONFIG_HTC_DEBUG_FOOTPRINT) += htc_mnemosyne/
|
|
diff --git a/drivers/gud/Kconfig b/drivers/gud/Kconfig
|
|
deleted file mode 100644
|
|
index 0e030bf60878d..0000000000000
|
|
--- a/drivers/gud/Kconfig
|
|
+++ /dev/null
|
|
@@ -1,35 +0,0 @@
|
|
-#
|
|
-# MobiCore configuration
|
|
-#
|
|
-config MOBICORE_DRIVER
|
|
- tristate "MobiCore Driver"
|
|
- ---help---
|
|
- Enable Linux Kernel MobiCore Support
|
|
-
|
|
-config MOBICORE_DEBUG
|
|
- bool "MobiCore Module debug mode"
|
|
- depends on MOBICORE_DRIVER
|
|
- ---help---
|
|
- Enable Debug mode in the MobiCore Driver.
|
|
- It enables printing information about mobicore operations
|
|
-
|
|
-config MOBICORE_VERBOSE
|
|
- bool "MobiCore Module verbose debug mode"
|
|
- depends on MOBICORE_DEBUG
|
|
- ---help---
|
|
- Enable Verbose Debug mode in the MobiCore Driver.
|
|
- It enables printing extra information about mobicore operations
|
|
- Beware: this is only useful for debuging deep in the driver because
|
|
- it prints too much logs
|
|
-
|
|
-config TRUSTONIC_TRUSTED_UI
|
|
- tristate "<t-base TUI"
|
|
- depends on MOBICORE_DRIVER
|
|
- ---help---
|
|
- Enable <t-base Trusted User Interface
|
|
-
|
|
-config TRUSTONIC_TRUSTED_UI_FB_BLANK
|
|
- bool "<t-base TUI with fb_blank"
|
|
- depends on TRUSTONIC_TRUSTED_UI
|
|
- ---help---
|
|
- Blank the framebuffer before starting a TUI session
|
|
diff --git a/drivers/gud/Makefile b/drivers/gud/Makefile
|
|
deleted file mode 100644
|
|
index e782876ce2b5b..0000000000000
|
|
--- a/drivers/gud/Makefile
|
|
+++ /dev/null
|
|
@@ -1,6 +0,0 @@
|
|
-#
|
|
-# Makefile for the <t-base core and trusted UI drivers
|
|
-#
|
|
-
|
|
-obj-$(CONFIG_MOBICORE_DRIVER) := MobiCoreDriver/
|
|
-
|
|
diff --git a/drivers/gud/MobiCoreDriver/Makefile b/drivers/gud/MobiCoreDriver/Makefile
|
|
deleted file mode 100644
|
|
index 4837359674f69..0000000000000
|
|
--- a/drivers/gud/MobiCoreDriver/Makefile
|
|
+++ /dev/null
|
|
@@ -1,33 +0,0 @@
|
|
-#
|
|
-# Makefile for the <t-base core driver
|
|
-#
|
|
-
|
|
-GUD_ROOT_FOLDER := drivers/gud/
|
|
-
|
|
-# add our modules to kernel.
|
|
-obj-$(CONFIG_MOBICORE_DRIVER) += mcDrvModule.o
|
|
-
|
|
-mcDrvModule-y := \
|
|
- admin.o \
|
|
- api.o \
|
|
- client.o \
|
|
- clientlib.o \
|
|
- clock.o \
|
|
- fastcall.o \
|
|
- logging.o \
|
|
- main.o \
|
|
- mcp.o \
|
|
- mmu.o \
|
|
- pm.o \
|
|
- scheduler.o \
|
|
- session.o
|
|
-
|
|
-# Release mode by default
|
|
-ccflags-y += -DNDEBUG
|
|
-ccflags-y += -Wno-declaration-after-statement
|
|
-
|
|
-ccflags-$(CONFIG_MOBICORE_DEBUG) += -DDEBUG
|
|
-
|
|
-# MobiCore Driver includes
|
|
-ccflags-y += -I$(GUD_ROOT_FOLDER)/MobiCoreDriver
|
|
-
|
|
diff --git a/drivers/gud/MobiCoreDriver/admin.c b/drivers/gud/MobiCoreDriver/admin.c
|
|
deleted file mode 100644
|
|
index 0d8fef4df84a8..0000000000000
|
|
--- a/drivers/gud/MobiCoreDriver/admin.c
|
|
+++ /dev/null
|
|
@@ -1,1011 +0,0 @@
|
|
-/*
|
|
- * Copyright (c) 2013-2015 TRUSTONIC LIMITED
|
|
- * All Rights Reserved.
|
|
- *
|
|
- * This program is free software; you can redistribute it and/or
|
|
- * modify it under the terms of the GNU General Public License
|
|
- * version 2 as published by the Free Software Foundation.
|
|
- *
|
|
- * This program is distributed in the hope that it will be useful,
|
|
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
- * GNU General Public License for more details.
|
|
- */
|
|
-
|
|
-#include <asm/atomic.h>
|
|
-#include <linux/slab.h>
|
|
-#include <linux/device.h>
|
|
-#include <linux/mutex.h>
|
|
-#include <linux/cdev.h>
|
|
-#include <linux/fs.h>
|
|
-#include <linux/ioctl.h>
|
|
-#include <linux/uaccess.h>
|
|
-#include <linux/sched.h>
|
|
-#include <linux/completion.h>
|
|
-#include <linux/vmalloc.h>
|
|
-#include <linux/module.h>
|
|
-#include <linux/random.h>
|
|
-#include <linux/delay.h>
|
|
-
|
|
-#include "public/mc_linux.h"
|
|
-#include "public/mc_admin.h"
|
|
-
|
|
-#include "mci/mcloadformat.h"
|
|
-
|
|
-#include "main.h"
|
|
-#include "debug.h"
|
|
-#include "mmu.h" /* For load_check and load_token */
|
|
-#include "mcp.h"
|
|
-#include "client.h"
|
|
-#include "api.h"
|
|
-#include "admin.h"
|
|
-
|
|
-/* We need 2 devices for admin and user interface*/
|
|
-#define MC_DEV_MAX 2
|
|
-
|
|
-static struct admin_ctx {
|
|
- struct device *dev;
|
|
- atomic_t daemon_counter;
|
|
- /* Define a MobiCore device structure for use with dev_debug() etc */
|
|
- struct device_driver mc_dev_name;
|
|
- dev_t mc_dev_admin;
|
|
- struct cdev mc_admin_cdev;
|
|
- int (*tee_start_cb)(void);
|
|
-} g_admin_ctx;
|
|
-
|
|
-static struct mc_admin_driver_request {
|
|
- /* Global */
|
|
- struct mutex mutex; /* Protects access to this struct */
|
|
- struct mutex states_mutex; /* Protect access to the states */
|
|
- enum client_state {
|
|
- IDLE,
|
|
- REQUEST_SENT,
|
|
- BUFFERS_READY,
|
|
- } client_state;
|
|
- enum server_state {
|
|
- NOT_CONNECTED, /* Device not open */
|
|
- READY, /* Waiting for requests */
|
|
- REQUEST_RECEIVED, /* Got a request, is working */
|
|
- RESPONSE_SENT, /* Has sent a response header */
|
|
- DATA_SENT, /* Blocked until data is consumed */
|
|
- } server_state;
|
|
- /* Request */
|
|
- uint32_t request_id;
|
|
- struct mc_admin_request request;
|
|
- struct completion client_complete;
|
|
- /* Response */
|
|
- struct mc_admin_response response;
|
|
- struct completion server_complete;
|
|
- void *buffer; /* Reception buffer (pre-allocated) */
|
|
- size_t size; /* Size of the reception buffer */
|
|
-} g_request;
|
|
-
|
|
-static struct tbase_object *tbase_object_alloc(bool is_sp_trustlet,
|
|
- size_t length)
|
|
-{
|
|
- struct tbase_object *obj;
|
|
- size_t size = sizeof(*obj) + length;
|
|
- size_t header_length = 0;
|
|
-
|
|
- /* Determine required size */
|
|
- if (is_sp_trustlet) {
|
|
- /* Need space for lengths info and containers */
|
|
- header_length = sizeof(struct mc_blob_len_info);
|
|
- size += header_length + 3 * MAX_SO_CONT_SIZE;
|
|
- }
|
|
-
|
|
- /* Allocate memory */
|
|
- obj = vzalloc(size);
|
|
- if (!obj)
|
|
- return NULL;
|
|
-
|
|
- /* A non-zero header_length indicates that we have a SP trustlet */
|
|
- obj->header_length = header_length;
|
|
- obj->length = length;
|
|
- return obj;
|
|
-}
|
|
-
|
|
-void tbase_object_free(struct tbase_object *robj)
|
|
-{
|
|
- vfree(robj);
|
|
-}
|
|
-
|
|
-static inline void client_state_change(enum client_state state)
|
|
-{
|
|
- mutex_lock(&g_request.states_mutex);
|
|
- g_request.client_state = state;
|
|
- mutex_unlock(&g_request.states_mutex);
|
|
-}
|
|
-
|
|
-static inline bool client_state_is(enum client_state state)
|
|
-{
|
|
- bool is;
|
|
-
|
|
- mutex_lock(&g_request.states_mutex);
|
|
- is = g_request.client_state == state;
|
|
- mutex_unlock(&g_request.states_mutex);
|
|
- return is;
|
|
-}
|
|
-
|
|
-static inline void server_state_change(enum server_state state)
|
|
-{
|
|
- mutex_lock(&g_request.states_mutex);
|
|
- g_request.server_state = state;
|
|
- mutex_unlock(&g_request.states_mutex);
|
|
-}
|
|
-
|
|
-static inline bool server_state_is(enum server_state state)
|
|
-{
|
|
- bool is;
|
|
-
|
|
- mutex_lock(&g_request.states_mutex);
|
|
- is = g_request.server_state == state;
|
|
- mutex_unlock(&g_request.states_mutex);
|
|
- return is;
|
|
-}
|
|
-
|
|
-static void request_cancel(void);
|
|
-
|
|
-static int request_send(uint32_t command, const struct mc_uuid_t *uuid,
|
|
- uint32_t is_gp, uint32_t spid)
|
|
-{
|
|
- struct device *dev = g_admin_ctx.dev;
|
|
- int counter = 10;
|
|
- int ret;
|
|
-
|
|
- /* Prepare request */
|
|
- mutex_lock(&g_request.states_mutex);
|
|
- /* Wait a little for daemon to connect */
|
|
- while ((g_request.server_state == NOT_CONNECTED) && counter--) {
|
|
- mutex_unlock(&g_request.states_mutex);
|
|
- ssleep(1);
|
|
- mutex_lock(&g_request.states_mutex);
|
|
- }
|
|
-
|
|
- BUG_ON(g_request.client_state != IDLE);
|
|
- if (g_request.server_state != READY) {
|
|
- mutex_unlock(&g_request.states_mutex);
|
|
- if (g_request.server_state != NOT_CONNECTED) {
|
|
- /* TODO: can we recover? */
|
|
- dev_err(dev, "%s: invalid daemon state %d\n", __func__,
|
|
- g_request.server_state);
|
|
- ret = -EPROTO;
|
|
- goto end;
|
|
- } else {
|
|
- dev_err(dev, "%s: daemon not connected\n", __func__);
|
|
- ret = -ENOTCONN;
|
|
- goto end;
|
|
- }
|
|
- }
|
|
-
|
|
- memset(&g_request.request, 0, sizeof(g_request.request));
|
|
- memset(&g_request.response, 0, sizeof(g_request.response));
|
|
- g_request.request.request_id = g_request.request_id++;
|
|
- g_request.request.command = command;
|
|
- if (uuid)
|
|
- memcpy(&g_request.request.uuid, uuid, sizeof(*uuid));
|
|
- else
|
|
- memset(&g_request.request.uuid, 0, sizeof(*uuid));
|
|
-
|
|
- g_request.request.is_gp = is_gp;
|
|
- g_request.request.spid = spid;
|
|
- g_request.client_state = REQUEST_SENT;
|
|
- mutex_unlock(&g_request.states_mutex);
|
|
-
|
|
- /* Send request */
|
|
- complete(&g_request.client_complete);
|
|
-
|
|
- /* Wait for header (could be interruptible, but then needs more work) */
|
|
- wait_for_completion(&g_request.server_complete);
|
|
-
|
|
- /* Server should be waiting with some data for us */
|
|
- mutex_lock(&g_request.states_mutex);
|
|
- switch (g_request.server_state) {
|
|
- case NOT_CONNECTED:
|
|
- /* Daemon gone */
|
|
- ret = -EPIPE;
|
|
- break;
|
|
- case READY:
|
|
- /* No data to come, likely an error */
|
|
- ret = -g_request.response.error_no;
|
|
- break;
|
|
- case RESPONSE_SENT:
|
|
- case DATA_SENT:
|
|
- /* Normal case, data to come */
|
|
- ret = 0;
|
|
- break;
|
|
- default:
|
|
- /* Should not happen as complete means the state changed */
|
|
- dev_err(dev, "%s: daemon is in a bad state: %d\n", __func__,
|
|
- g_request.server_state);
|
|
- ret = -EPIPE;
|
|
- break;
|
|
- }
|
|
-
|
|
- mutex_unlock(&g_request.states_mutex);
|
|
-
|
|
-end:
|
|
- if (ret)
|
|
- request_cancel();
|
|
-
|
|
- return ret;
|
|
-}
|
|
-
|
|
-static int request_receive(void *address, uint32_t size)
|
|
-{
|
|
- /*
|
|
- * At this point we have received the header and prepared some buffers
|
|
- * to receive data that we know are coming from the server.
|
|
- */
|
|
-
|
|
- /* Check server state */
|
|
- bool server_ok;
|
|
-
|
|
- mutex_lock(&g_request.states_mutex);
|
|
- server_ok = (g_request.server_state == RESPONSE_SENT) ||
|
|
- (g_request.server_state == DATA_SENT);
|
|
- mutex_unlock(&g_request.states_mutex);
|
|
- if (!server_ok) {
|
|
- /* TODO: can we recover? */
|
|
- request_cancel();
|
|
- return -EPIPE;
|
|
- }
|
|
-
|
|
- /* Setup reception buffer */
|
|
- g_request.buffer = address;
|
|
- g_request.size = size;
|
|
- client_state_change(BUFFERS_READY);
|
|
-
|
|
- /* Unlock write of data */
|
|
- complete(&g_request.client_complete);
|
|
-
|
|
- /* Wait for data (far too late to be interruptible) */
|
|
- wait_for_completion(&g_request.server_complete);
|
|
-
|
|
- /* Reset reception buffer */
|
|
- g_request.buffer = NULL;
|
|
- g_request.size = 0;
|
|
-
|
|
- /* Return to idle state */
|
|
- client_state_change(IDLE);
|
|
- return 0;
|
|
-}
|
|
-
|
|
-/* Must be called instead of request_receive() to cancel a pending request */
|
|
-static void request_cancel(void)
|
|
-{
|
|
- /* Unlock write of data */
|
|
- mutex_lock(&g_request.states_mutex);
|
|
- if (g_request.server_state == DATA_SENT)
|
|
- complete(&g_request.client_complete);
|
|
-
|
|
- /* Return to idle state */
|
|
- g_request.client_state = IDLE;
|
|
- mutex_unlock(&g_request.states_mutex);
|
|
-}
|
|
-
|
|
-static int admin_get_root_container(void *address)
|
|
-{
|
|
- struct device *dev = g_admin_ctx.dev;
|
|
- int ret = 0;
|
|
-
|
|
- /* Lock communication channel */
|
|
- mutex_lock(&g_request.mutex);
|
|
-
|
|
- /* Send request and wait for header */
|
|
- ret = request_send(MC_DRV_GET_ROOT_CONTAINER, 0, 0, 0);
|
|
- if (ret)
|
|
- goto end;
|
|
-
|
|
- /* Check length against max */
|
|
- if (g_request.response.length >= MAX_SO_CONT_SIZE) {
|
|
- request_cancel();
|
|
- dev_err(dev, "%s: response length exceeds maximum\n", __func__);
|
|
- ret = EREMOTEIO;
|
|
- goto end;
|
|
- }
|
|
-
|
|
- /* Get data */
|
|
- ret = request_receive(address, g_request.response.length);
|
|
- if (!ret)
|
|
- ret = g_request.response.length;
|
|
-
|
|
-end:
|
|
- mutex_unlock(&g_request.mutex);
|
|
- return ret;
|
|
-}
|
|
-
|
|
-static int admin_get_sp_container(void *address, uint32_t spid)
|
|
-{
|
|
- struct device *dev = g_admin_ctx.dev;
|
|
- int ret = 0;
|
|
-
|
|
- /* Lock communication channel */
|
|
- mutex_lock(&g_request.mutex);
|
|
-
|
|
- /* Send request and wait for header */
|
|
- ret = request_send(MC_DRV_GET_SP_CONTAINER, 0, 0, spid);
|
|
- if (ret)
|
|
- goto end;
|
|
-
|
|
- /* Check length against max */
|
|
- if (g_request.response.length >= MAX_SO_CONT_SIZE) {
|
|
- request_cancel();
|
|
- dev_err(dev, "%s: response length exceeds maximum\n", __func__);
|
|
- ret = EREMOTEIO;
|
|
- goto end;
|
|
- }
|
|
-
|
|
- /* Get data */
|
|
- ret = request_receive(address, g_request.response.length);
|
|
- if (!ret)
|
|
- ret = g_request.response.length;
|
|
-
|
|
-end:
|
|
- mutex_unlock(&g_request.mutex);
|
|
- return ret;
|
|
-}
|
|
-
|
|
-static int admin_get_trustlet_container(void *address,
|
|
- const struct mc_uuid_t *uuid,
|
|
- uint32_t spid)
|
|
-{
|
|
- struct device *dev = g_admin_ctx.dev;
|
|
- int ret = 0;
|
|
-
|
|
- /* Lock communication channel */
|
|
- mutex_lock(&g_request.mutex);
|
|
-
|
|
- /* Send request and wait for header */
|
|
- ret = request_send(MC_DRV_GET_TRUSTLET_CONTAINER, uuid, 0, spid);
|
|
- if (ret)
|
|
- goto end;
|
|
-
|
|
- /* Check length against max */
|
|
- if (g_request.response.length >= MAX_SO_CONT_SIZE) {
|
|
- request_cancel();
|
|
- dev_err(dev, "%s: response length exceeds maximum\n", __func__);
|
|
- ret = EREMOTEIO;
|
|
- goto end;
|
|
- }
|
|
-
|
|
- /* Get data */
|
|
- ret = request_receive(address, g_request.response.length);
|
|
- if (!ret)
|
|
- ret = g_request.response.length;
|
|
-
|
|
-end:
|
|
- mutex_unlock(&g_request.mutex);
|
|
- return ret;
|
|
-}
|
|
-
|
|
-static struct tbase_object *admin_get_trustlet(const struct mc_uuid_t *uuid,
|
|
- uint32_t is_gp, uint32_t *spid)
|
|
-{
|
|
- struct tbase_object *obj = NULL;
|
|
- bool is_sp_tl;
|
|
- int ret = 0;
|
|
-
|
|
- /* Lock communication channel */
|
|
- mutex_lock(&g_request.mutex);
|
|
-
|
|
- /* Send request and wait for header */
|
|
- ret = request_send(MC_DRV_GET_TRUSTLET, uuid, is_gp, 0);
|
|
- if (ret)
|
|
- goto end;
|
|
-
|
|
- /* Allocate memory */
|
|
- is_sp_tl = g_request.response.service_type == SERVICE_TYPE_SP_TRUSTLET;
|
|
- obj = tbase_object_alloc(is_sp_tl, g_request.response.length);
|
|
- if (!obj) {
|
|
- request_cancel();
|
|
- ret = -ENOMEM;
|
|
- goto end;
|
|
- }
|
|
-
|
|
- /* Get data */
|
|
- ret = request_receive(&obj->data[obj->header_length], obj->length);
|
|
- *spid = g_request.response.spid;
|
|
-
|
|
-end:
|
|
- mutex_unlock(&g_request.mutex);
|
|
- if (ret)
|
|
- return ERR_PTR(ret);
|
|
-
|
|
- return obj;
|
|
-}
|
|
-
|
|
-static void mc_admin_sendcrashdump(void)
|
|
-{
|
|
- int ret = 0;
|
|
-
|
|
- /* Lock communication channel */
|
|
- mutex_lock(&g_request.mutex);
|
|
-
|
|
- /* Send request and wait for header */
|
|
- ret = request_send(MC_DRV_SIGNAL_CRASH, NULL, false, 0);
|
|
- if (ret)
|
|
- goto end;
|
|
-
|
|
- /* Done */
|
|
- request_cancel();
|
|
-
|
|
-end:
|
|
- mutex_unlock(&g_request.mutex);
|
|
-}
|
|
-
|
|
-static int tbase_object_make(uint32_t spid, struct tbase_object *obj)
|
|
-{
|
|
- struct mc_blob_len_info *l_info = (struct mc_blob_len_info *)obj->data;
|
|
- uint8_t *address = &obj->data[obj->header_length + obj->length];
|
|
- struct mclf_header_v2 *thdr;
|
|
- int ret;
|
|
-
|
|
- /* Get root container */
|
|
- ret = admin_get_root_container(address);
|
|
- if (ret < 0)
|
|
- goto err;
|
|
-
|
|
- l_info->root_size = ret;
|
|
- address += ret;
|
|
-
|
|
- /* Get SP container */
|
|
- ret = admin_get_sp_container(address, spid);
|
|
- if (ret < 0)
|
|
- goto err;
|
|
-
|
|
- l_info->sp_size = ret;
|
|
- address += ret;
|
|
-
|
|
- /* Get trustlet container */
|
|
- thdr = (struct mclf_header_v2 *)&obj->data[obj->header_length];
|
|
- ret = admin_get_trustlet_container(address, &thdr->uuid, spid);
|
|
- if (ret < 0)
|
|
- goto err;
|
|
-
|
|
- l_info->ta_size = ret;
|
|
- address += ret;
|
|
-
|
|
- /* Setup lengths information */
|
|
- l_info->magic = MC_TLBLOBLEN_MAGIC;
|
|
- obj->length += sizeof(*l_info);
|
|
- obj->length += l_info->root_size + l_info->sp_size + l_info->ta_size;
|
|
- ret = 0;
|
|
-
|
|
-err:
|
|
- return ret;
|
|
-}
|
|
-
|
|
-struct tbase_object *tbase_object_read(uint32_t spid, uintptr_t address,
|
|
- size_t length)
|
|
-{
|
|
- struct device *dev = g_admin_ctx.dev;
|
|
- char __user *addr = (char __user *)address;
|
|
- struct tbase_object *obj;
|
|
- uint8_t *data;
|
|
- struct mclf_header_v2 thdr;
|
|
- int ret;
|
|
-
|
|
- /* Check length */
|
|
- if (length < sizeof(thdr)) {
|
|
- dev_err(dev, "%s: buffer shorter than header size\n", __func__);
|
|
- return ERR_PTR(-EFAULT);
|
|
- }
|
|
-
|
|
- /* Read header */
|
|
- if (copy_from_user(&thdr, addr, sizeof(thdr))) {
|
|
- dev_err(dev, "%s: header: copy_from_user failed\n", __func__);
|
|
- return ERR_PTR(-EFAULT);
|
|
- }
|
|
-
|
|
- /* Allocate memory */
|
|
- obj = tbase_object_alloc(thdr.service_type == SERVICE_TYPE_SP_TRUSTLET,
|
|
- length);
|
|
- if (!obj)
|
|
- return ERR_PTR(-ENOMEM);
|
|
-
|
|
- /* Copy header */
|
|
- data = &obj->data[obj->header_length];
|
|
- memcpy(data, &thdr, sizeof(thdr));
|
|
- /* Copy the rest of the data */
|
|
- data += sizeof(thdr);
|
|
- if (copy_from_user(data, &addr[sizeof(thdr)], length - sizeof(thdr))) {
|
|
- dev_err(dev, "%s: data: copy_from_user failed\n", __func__);
|
|
- vfree(obj);
|
|
- return ERR_PTR(-EFAULT);
|
|
- }
|
|
-
|
|
- if (obj->header_length) {
|
|
- ret = tbase_object_make(spid, obj);
|
|
- if (ret) {
|
|
- vfree(obj);
|
|
- return ERR_PTR(ret);
|
|
- }
|
|
- }
|
|
-
|
|
- return obj;
|
|
-}
|
|
-
|
|
-struct tbase_object *tbase_object_select(const struct mc_uuid_t *uuid)
|
|
-{
|
|
- struct tbase_object *obj;
|
|
- struct mclf_header_v2 *thdr;
|
|
-
|
|
- obj = tbase_object_alloc(false, sizeof(*thdr));
|
|
- if (!obj)
|
|
- return ERR_PTR(-ENOMEM);
|
|
-
|
|
- thdr = (struct mclf_header_v2 *)&obj->data[obj->header_length];
|
|
- memcpy(&thdr->uuid, uuid, sizeof(thdr->uuid));
|
|
- return obj;
|
|
-}
|
|
-
|
|
-struct tbase_object *tbase_object_get(const struct mc_uuid_t *uuid,
|
|
- uint32_t is_gp_uuid)
|
|
-{
|
|
- struct tbase_object *obj;
|
|
- uint32_t spid = 0;
|
|
-
|
|
- /* admin_get_trustlet creates the right object based on service type */
|
|
- obj = admin_get_trustlet(uuid, is_gp_uuid, &spid);
|
|
- if (IS_ERR(obj))
|
|
- return obj;
|
|
-
|
|
- /* SP trustlet: create full secure object with all containers */
|
|
- if (obj->header_length) {
|
|
- int ret;
|
|
-
|
|
- /* Do not return EINVAL in this case as SPID was not found */
|
|
- if (!spid) {
|
|
- vfree(obj);
|
|
- return ERR_PTR(-ENOENT);
|
|
- }
|
|
-
|
|
- ret = tbase_object_make(spid, obj);
|
|
- if (ret) {
|
|
- vfree(obj);
|
|
- return ERR_PTR(ret);
|
|
- }
|
|
- }
|
|
-
|
|
- return obj;
|
|
-}
|
|
-
|
|
-static inline int load_driver(struct tbase_client *client,
|
|
- struct mc_admin_load_info *info)
|
|
-{
|
|
- struct tbase_object *obj;
|
|
- struct mclf_header_v2 *thdr;
|
|
- struct mc_identity identity = {
|
|
- .login_type = TEEC_LOGIN_PUBLIC,
|
|
- };
|
|
- uintptr_t dci = 0;
|
|
- uint32_t dci_len = 0;
|
|
- uint32_t sid;
|
|
- int ret;
|
|
-
|
|
- obj = tbase_object_read(info->spid, info->address, info->length);
|
|
- if (IS_ERR(obj))
|
|
- return PTR_ERR(obj);
|
|
-
|
|
- thdr = (struct mclf_header_v2 *)&obj->data[obj->header_length];
|
|
- if (!(thdr->flags & MC_SERVICE_HEADER_FLAGS_NO_CONTROL_INTERFACE)) {
|
|
- /*
|
|
- * The driver requires a DCI, although we won't be able to use
|
|
- * it to communicate.
|
|
- */
|
|
- dci_len = PAGE_SIZE;
|
|
- ret = api_malloc_cbuf(client, dci_len, &dci, NULL);
|
|
- if (ret)
|
|
- goto end;
|
|
- }
|
|
-
|
|
- /* Open session */
|
|
- ret = client_add_session(client, obj, dci, dci_len, &sid, false,
|
|
- &identity);
|
|
- if (ret)
|
|
- api_free_cbuf(client, dci);
|
|
- else
|
|
- dev_dbg(g_admin_ctx.dev, "driver loaded with sid %x", sid);
|
|
-
|
|
-end:
|
|
- vfree(obj);
|
|
- return ret;
|
|
-}
|
|
-
|
|
-static inline int load_token(struct mc_admin_load_info *token)
|
|
-{
|
|
- struct tbase_mmu *mmu;
|
|
- struct mcp_buffer_map map;
|
|
- int ret;
|
|
-
|
|
- mmu = tbase_mmu_create(current, (void *)(uintptr_t)token->address,
|
|
- token->length);
|
|
- if (IS_ERR(mmu))
|
|
- return PTR_ERR(mmu);
|
|
-
|
|
- tbase_mmu_buffer(mmu, &map);
|
|
- ret = mcp_load_token(token->address, &map);
|
|
- tbase_mmu_delete(mmu);
|
|
- return ret;
|
|
-}
|
|
-
|
|
-static inline int load_check(struct mc_admin_load_info *info)
|
|
-{
|
|
- struct tbase_object *obj;
|
|
- struct tbase_mmu *mmu;
|
|
- struct mcp_buffer_map map;
|
|
- int ret;
|
|
-
|
|
- obj = tbase_object_read(info->spid, info->address, info->length);
|
|
- if (IS_ERR(obj))
|
|
- return PTR_ERR(obj);
|
|
-
|
|
- mmu = tbase_mmu_create(NULL, obj->data, obj->length);
|
|
- if (IS_ERR(mmu))
|
|
- return PTR_ERR(mmu);
|
|
-
|
|
- tbase_mmu_buffer(mmu, &map);
|
|
- ret = mcp_load_check(obj, &map);
|
|
- tbase_mmu_delete(mmu);
|
|
- return ret;
|
|
-}
|
|
-
|
|
-static ssize_t admin_write(struct file *file, const char __user *user,
|
|
- size_t len, loff_t *off)
|
|
-{
|
|
- int ret;
|
|
-
|
|
- /* No offset allowed [yet] */
|
|
- if (*off) {
|
|
- g_request.response.error_no = EPIPE;
|
|
- ret = -ECOMM;
|
|
- goto err;
|
|
- }
|
|
-
|
|
- if (server_state_is(REQUEST_RECEIVED)) {
|
|
- /* Check client state */
|
|
- if (!client_state_is(REQUEST_SENT)) {
|
|
- g_request.response.error_no = EPIPE;
|
|
- ret = -EPIPE;
|
|
- goto err;
|
|
- }
|
|
-
|
|
- /* Receive response header */
|
|
- if (copy_from_user(&g_request.response, user,
|
|
- sizeof(g_request.response))) {
|
|
- g_request.response.error_no = EPIPE;
|
|
- ret = -ECOMM;
|
|
- goto err;
|
|
- }
|
|
-
|
|
- /* Check request ID */
|
|
- if (g_request.request.request_id !=
|
|
- g_request.response.request_id) {
|
|
- g_request.response.error_no = EPIPE;
|
|
- ret = -EBADE;
|
|
- goto err;
|
|
- }
|
|
-
|
|
- /* Response header is acceptable */
|
|
- ret = sizeof(g_request.response);
|
|
- if (g_request.response.length)
|
|
- server_state_change(RESPONSE_SENT);
|
|
- else
|
|
- server_state_change(READY);
|
|
-
|
|
- goto end;
|
|
- } else if (server_state_is(RESPONSE_SENT)) {
|
|
- /* Server is waiting */
|
|
- server_state_change(DATA_SENT);
|
|
-
|
|
- /* Get data */
|
|
- ret = wait_for_completion_interruptible(
|
|
- &g_request.client_complete);
|
|
-
|
|
- /* Server received a signal, let see if it tries again */
|
|
- if (ret) {
|
|
- server_state_change(RESPONSE_SENT);
|
|
- return ret;
|
|
- }
|
|
-
|
|
- /* Check client state */
|
|
- if (!client_state_is(BUFFERS_READY)) {
|
|
- g_request.response.error_no = EPIPE;
|
|
- ret = -EPIPE;
|
|
- goto err;
|
|
- }
|
|
-
|
|
- /* TODO deal with several writes */
|
|
- if (len != g_request.size)
|
|
- len = g_request.size;
|
|
-
|
|
- ret = copy_from_user(g_request.buffer, user, len);
|
|
- if (ret) {
|
|
- g_request.response.error_no = EPIPE;
|
|
- ret = -ECOMM;
|
|
- goto err;
|
|
- }
|
|
-
|
|
- ret = len;
|
|
- server_state_change(READY);
|
|
- goto end;
|
|
- } else {
|
|
- ret = -ECOMM;
|
|
- goto err;
|
|
- }
|
|
-
|
|
-err:
|
|
- server_state_change(READY);
|
|
-end:
|
|
- complete(&g_request.server_complete);
|
|
- return ret;
|
|
-}
|
|
-
|
|
-static long admin_ioctl(struct file *file, unsigned int cmd,
|
|
- unsigned long arg)
|
|
-{
|
|
- struct tbase_client *client = file->private_data;
|
|
- void __user *uarg = (void __user *)arg;
|
|
- int ret = -EINVAL;
|
|
-
|
|
- MCDRV_DBG("%u from %s", _IOC_NR(cmd), current->comm);
|
|
-
|
|
- if (WARN(!client, "No client data available"))
|
|
- return -EFAULT;
|
|
-
|
|
- switch (cmd) {
|
|
- case MC_ADMIN_IO_GET_DRIVER_REQUEST: {
|
|
- /* Block until a request is available */
|
|
- ret = wait_for_completion_interruptible(
|
|
- &g_request.client_complete);
|
|
- if (ret)
|
|
- /* Interrupted by signal */
|
|
- break;
|
|
-
|
|
- /* Check client state */
|
|
- if (!client_state_is(REQUEST_SENT)) {
|
|
- g_request.response.error_no = EPIPE;
|
|
- complete(&g_request.server_complete);
|
|
- ret = -EPIPE;
|
|
- break;
|
|
- }
|
|
-
|
|
- /* Send request (the driver request mutex is held) */
|
|
- ret = copy_to_user(uarg, &g_request.request,
|
|
- sizeof(g_request.request));
|
|
- if (ret) {
|
|
- server_state_change(READY);
|
|
- complete(&g_request.server_complete);
|
|
- ret = -EPROTO;
|
|
- break;
|
|
- }
|
|
-
|
|
- server_state_change(REQUEST_RECEIVED);
|
|
- break;
|
|
- }
|
|
- case MC_ADMIN_IO_GET_INFO: {
|
|
- struct mc_admin_driver_info info;
|
|
-
|
|
- info.drv_version = MC_VERSION(MCDRVMODULEAPI_VERSION_MAJOR,
|
|
- MCDRVMODULEAPI_VERSION_MINOR);
|
|
- info.initial_cmd_id = g_request.request_id;
|
|
- ret = copy_to_user(uarg, &info, sizeof(info));
|
|
- break;
|
|
- }
|
|
- case MC_ADMIN_IO_LOAD_DRIVER: {
|
|
- struct mc_admin_load_info info;
|
|
-
|
|
- ret = copy_from_user(&info, uarg, sizeof(info));
|
|
- if (ret)
|
|
- ret = -EFAULT;
|
|
- else
|
|
- ret = load_driver(client, &info);
|
|
-
|
|
- break;
|
|
- }
|
|
- case MC_ADMIN_IO_LOAD_TOKEN: {
|
|
- struct mc_admin_load_info info;
|
|
-
|
|
- ret = copy_from_user(&info, uarg, sizeof(info));
|
|
- if (ret)
|
|
- ret = -EFAULT;
|
|
- else
|
|
- ret = load_token(&info);
|
|
-
|
|
- break;
|
|
- }
|
|
- case MC_ADMIN_IO_LOAD_CHECK: {
|
|
- struct mc_admin_load_info info;
|
|
-
|
|
- ret = copy_from_user(&info, uarg, sizeof(info));
|
|
- if (ret)
|
|
- ret = -EFAULT;
|
|
- else
|
|
- ret = load_check(&info);
|
|
-
|
|
- break;
|
|
- }
|
|
- default:
|
|
- ret = -ENOIOCTLCMD;
|
|
- }
|
|
-
|
|
- return ret;
|
|
-}
|
|
-
|
|
-/*
|
|
- * mc_fd_release() - This function will be called from user space as close(...)
|
|
- * The client data are freed and the associated memory pages are unreserved.
|
|
- *
|
|
- * @inode
|
|
- * @file
|
|
- *
|
|
- * Returns 0
|
|
- */
|
|
-static int admin_release(struct inode *inode, struct file *file)
|
|
-{
|
|
- struct tbase_client *client = file->private_data;
|
|
- struct device *dev = g_admin_ctx.dev;
|
|
-
|
|
- if (!client)
|
|
- return -EPROTO;
|
|
-
|
|
- api_close_device(client);
|
|
- file->private_data = NULL;
|
|
-
|
|
- /* Requests from driver to daemon */
|
|
- mutex_lock(&g_request.states_mutex);
|
|
- dev_warn(dev, "%s: daemon disconnected\n", __func__);
|
|
- g_request.server_state = NOT_CONNECTED;
|
|
- /* A non-zero command indicates that a thread is waiting */
|
|
- if (g_request.client_state != IDLE) {
|
|
- g_request.response.error_no = ESHUTDOWN;
|
|
- complete(&g_request.server_complete);
|
|
- }
|
|
-
|
|
- mutex_unlock(&g_request.states_mutex);
|
|
- atomic_set(&g_admin_ctx.daemon_counter, 0);
|
|
- /*
|
|
- * ret is quite irrelevant here as most apps don't care about the
|
|
- * return value from close() and it's quite difficult to recover
|
|
- */
|
|
- return 0;
|
|
-}
|
|
-
|
|
-static int admin_open(struct inode *inode, struct file *file)
|
|
-{
|
|
- struct device *dev = g_admin_ctx.dev;
|
|
- struct tbase_client *client;
|
|
- int err;
|
|
-
|
|
- /*
|
|
- * If the daemon is already set we can't allow anybody else to open
|
|
- * the admin interface.
|
|
- */
|
|
- if (atomic_cmpxchg(&g_admin_ctx.daemon_counter, 0, 1) != 0) {
|
|
- MCDRV_ERROR("Daemon is already connected");
|
|
- return -EPROTO;
|
|
- }
|
|
-
|
|
- /* Any value will do */
|
|
- g_request.request_id = 42;
|
|
-
|
|
- /* Setup the usual variables */
|
|
- MCDRV_DBG("accept %s as tbase daemon", current->comm);
|
|
-
|
|
- /*
|
|
- * daemon is connected so now we can safely suppose
|
|
- * the secure world is loaded too
|
|
- */
|
|
- if (!IS_ERR_OR_NULL(g_admin_ctx.tee_start_cb))
|
|
- g_admin_ctx.tee_start_cb = ERR_PTR(g_admin_ctx.tee_start_cb());
|
|
- if (IS_ERR(g_admin_ctx.tee_start_cb)) {
|
|
- MCDRV_ERROR("Failed initializing the SW");
|
|
- err = PTR_ERR(g_admin_ctx.tee_start_cb);
|
|
- goto fail_connection;
|
|
-}
|
|
-
|
|
- /* Create client */
|
|
- client = api_open_device(true);
|
|
- if (!client) {
|
|
- err = -ENOMEM;
|
|
- goto fail_connection;
|
|
- }
|
|
-
|
|
- /* Store client in user file */
|
|
- file->private_data = client;
|
|
-
|
|
- /* Requests from driver to daemon */
|
|
- server_state_change(READY);
|
|
- dev_info(dev, "%s: daemon connected\n", __func__);
|
|
-
|
|
- return 0;
|
|
-
|
|
-fail_connection:
|
|
- atomic_set(&g_admin_ctx.daemon_counter, 0);
|
|
- return err;
|
|
-}
|
|
-
|
|
-/* function table structure of this device driver. */
|
|
-static const struct file_operations mc_admin_fops = {
|
|
- .owner = THIS_MODULE,
|
|
- .open = admin_open,
|
|
- .release = admin_release,
|
|
- .unlocked_ioctl = admin_ioctl,
|
|
-#ifdef CONFIG_COMPAT
|
|
- .compat_ioctl = admin_ioctl,
|
|
-#endif
|
|
- .write = admin_write,
|
|
-};
|
|
-
|
|
-int mc_admin_init(struct class *mc_device_class, dev_t *out_dev,
|
|
- int (*tee_start_cb)(void))
|
|
-{
|
|
- int err = 0;
|
|
-
|
|
- if (!out_dev || !mc_device_class)
|
|
- return -EINVAL;
|
|
-
|
|
- atomic_set(&g_admin_ctx.daemon_counter, 0);
|
|
-
|
|
- /* Requests from driver to daemon */
|
|
- mutex_init(&g_request.mutex);
|
|
- mutex_init(&g_request.states_mutex);
|
|
- init_completion(&g_request.client_complete);
|
|
- init_completion(&g_request.server_complete);
|
|
- mcp_register_crashhandler(mc_admin_sendcrashdump);
|
|
-
|
|
- /* Create char device */
|
|
- cdev_init(&g_admin_ctx.mc_admin_cdev, &mc_admin_fops);
|
|
- err = alloc_chrdev_region(&g_admin_ctx.mc_dev_admin, 0, MC_DEV_MAX,
|
|
- "trustonic_tee");
|
|
- if (err < 0) {
|
|
- MCDRV_ERROR("failed to allocate char dev region");
|
|
- goto fail_alloc_chrdev_region;
|
|
- }
|
|
-
|
|
- err = cdev_add(&g_admin_ctx.mc_admin_cdev, g_admin_ctx.mc_dev_admin, 1);
|
|
- if (err) {
|
|
- MCDRV_ERROR("admin device register failed");
|
|
- goto fail_cdev_add;
|
|
- }
|
|
-
|
|
- g_admin_ctx.mc_admin_cdev.owner = THIS_MODULE;
|
|
- g_admin_ctx.dev = device_create(mc_device_class, NULL,
|
|
- g_admin_ctx.mc_dev_admin, NULL,
|
|
- MC_ADMIN_DEVNODE);
|
|
- if (IS_ERR(g_admin_ctx.dev)) {
|
|
- err = PTR_ERR(g_admin_ctx.dev);
|
|
- goto fail_dev_create;
|
|
- }
|
|
-
|
|
- g_admin_ctx.mc_dev_name.name = "<t-base";
|
|
- g_admin_ctx.dev->driver = &g_admin_ctx.mc_dev_name;
|
|
- *out_dev = g_admin_ctx.mc_dev_admin;
|
|
-
|
|
- /* Register the call back for starting the secure world */
|
|
- g_admin_ctx.tee_start_cb = tee_start_cb;
|
|
-
|
|
- MCDRV_DBG("done");
|
|
- return 0;
|
|
-
|
|
-fail_dev_create:
|
|
- cdev_del(&g_admin_ctx.mc_admin_cdev);
|
|
-
|
|
-fail_cdev_add:
|
|
- unregister_chrdev_region(g_admin_ctx.mc_dev_admin, MC_DEV_MAX);
|
|
-
|
|
-fail_alloc_chrdev_region:
|
|
- MCDRV_ERROR("fail with %d", err);
|
|
- return err;
|
|
-}
|
|
-
|
|
-void mc_admin_exit(struct class *mc_device_class)
|
|
-{
|
|
- device_destroy(mc_device_class, g_admin_ctx.mc_dev_admin);
|
|
- cdev_del(&g_admin_ctx.mc_admin_cdev);
|
|
- unregister_chrdev_region(g_admin_ctx.mc_dev_admin, MC_DEV_MAX);
|
|
- /* Requests from driver to daemon */
|
|
- mutex_destroy(&g_request.states_mutex);
|
|
- MCDRV_DBG("done");
|
|
-}
|
|
diff --git a/drivers/gud/MobiCoreDriver/admin.h b/drivers/gud/MobiCoreDriver/admin.h
|
|
deleted file mode 100644
|
|
index 5a78d943752da..0000000000000
|
|
--- a/drivers/gud/MobiCoreDriver/admin.h
|
|
+++ /dev/null
|
|
@@ -1,32 +0,0 @@
|
|
-/*
|
|
- * Copyright (c) 2013-2015 TRUSTONIC LIMITED
|
|
- * All Rights Reserved.
|
|
- *
|
|
- * This program is free software; you can redistribute it and/or
|
|
- * modify it under the terms of the GNU General Public License
|
|
- * version 2 as published by the Free Software Foundation.
|
|
- *
|
|
- * This program is distributed in the hope that it will be useful,
|
|
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
- * GNU General Public License for more details.
|
|
- */
|
|
-
|
|
-#ifndef ADMIN_FD_H_
|
|
-#define ADMIN_FD_H_
|
|
-
|
|
-struct mc_uuid_t;
|
|
-struct tbase_object;
|
|
-
|
|
-int mc_admin_init(struct class *mc_device_class, dev_t *out_dev,
|
|
- int (*tee_start_cb)(void));
|
|
-void mc_admin_exit(struct class *mc_device_class);
|
|
-
|
|
-struct tbase_object *tbase_object_select(const struct mc_uuid_t *uuid);
|
|
-struct tbase_object *tbase_object_get(const struct mc_uuid_t *uuid,
|
|
- uint32_t is_gp_uuid);
|
|
-struct tbase_object *tbase_object_read(uint32_t spid, uintptr_t address,
|
|
- size_t length);
|
|
-void tbase_object_free(struct tbase_object *out_robj);
|
|
-
|
|
-#endif /* ADMIN_FD_H_ */
|
|
diff --git a/drivers/gud/MobiCoreDriver/api.c b/drivers/gud/MobiCoreDriver/api.c
|
|
deleted file mode 100644
|
|
index 0d2abaf617aea..0000000000000
|
|
--- a/drivers/gud/MobiCoreDriver/api.c
|
|
+++ /dev/null
|
|
@@ -1,419 +0,0 @@
|
|
-/*
|
|
- * Copyright (c) 2013-2015 TRUSTONIC LIMITED
|
|
- * All Rights Reserved.
|
|
- *
|
|
- * This program is free software; you can redistribute it and/or
|
|
- * modify it under the terms of the GNU General Public License
|
|
- * version 2 as published by the Free Software Foundation.
|
|
- *
|
|
- * This program is distributed in the hope that it will be useful,
|
|
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
- * GNU General Public License for more details.
|
|
- */
|
|
-
|
|
-#include <linux/device.h>
|
|
-#include <linux/slab.h>
|
|
-#include <linux/err.h>
|
|
-#include <linux/cred.h>
|
|
-#include <linux/sched.h>
|
|
-
|
|
-#include <public/mc_linux.h> /* MC_MAP_MAX */
|
|
-#include "main.h"
|
|
-#include "debug.h"
|
|
-#include "mcp.h"
|
|
-#include "admin.h"
|
|
-#include "session.h"
|
|
-#include "client.h"
|
|
-#include "api.h"
|
|
-
|
|
-static struct api_ctx {
|
|
- struct mutex clients_lock; /* Clients list + temp notifs */
|
|
- struct list_head clients; /* List of user-space clients */
|
|
-} api_ctx;
|
|
-
|
|
-/*
|
|
- * Initialize a new tbase client object
|
|
- * @return client pointer or NULL if no allocation was possible.
|
|
- */
|
|
-struct tbase_client *api_open_device(bool is_from_kernel)
|
|
-{
|
|
- struct tbase_client *client;
|
|
-
|
|
- /* Allocate and init client object */
|
|
- client = client_create(is_from_kernel);
|
|
- if (!client) {
|
|
- MCDRV_ERROR("Could not create client");
|
|
- return NULL;
|
|
- }
|
|
-
|
|
- /* Add client to list of clients */
|
|
- mutex_lock(&api_ctx.clients_lock);
|
|
- list_add_tail(&client->list, &api_ctx.clients);
|
|
- mutex_unlock(&api_ctx.clients_lock);
|
|
-
|
|
- MCDRV_DBG("created client %p", client);
|
|
- return client;
|
|
-}
|
|
-
|
|
-/*
|
|
- * Try and mark client as "closing"
|
|
- * @return tbase driver error code
|
|
- */
|
|
-int api_freeze_device(struct tbase_client *client)
|
|
-{
|
|
- int err = 0;
|
|
-
|
|
- if (!client_set_closing(client))
|
|
- err = -ENOTEMPTY;
|
|
-
|
|
- MCDRV_DBG("client %p, exit with %d\n", client, err);
|
|
- return err;
|
|
-}
|
|
-
|
|
-/*
|
|
- * Release a client and the session+cbuf objects it contains.
|
|
- * @param client_t client
|
|
- * @return tbase driver error code
|
|
- */
|
|
-void api_close_device(struct tbase_client *client)
|
|
-{
|
|
- /* Remove client from list of active clients */
|
|
- mutex_lock(&api_ctx.clients_lock);
|
|
- list_del(&client->list);
|
|
- mutex_unlock(&api_ctx.clients_lock);
|
|
- /* Close all remaining sessions */
|
|
- client_close_sessions(client);
|
|
- client_put(client);
|
|
- MCDRV_DBG("client %p closed\n", client);
|
|
-}
|
|
-
|
|
-/*
|
|
- * Open TA for given client. TA binary is provided by the daemon.
|
|
- * @param
|
|
- * @return tbase driver error code
|
|
- */
|
|
-int api_open_session(struct tbase_client *client,
|
|
- uint32_t *p_session_id,
|
|
- const struct mc_uuid_t *uuid,
|
|
- uintptr_t tci,
|
|
- size_t tci_len,
|
|
- bool is_gp_uuid,
|
|
- struct mc_identity *identity)
|
|
-{
|
|
- int err = 0;
|
|
- uint32_t sid = 0;
|
|
- struct tbase_object *obj;
|
|
-
|
|
- /* Check parameters */
|
|
- if (!p_session_id)
|
|
- return -EINVAL;
|
|
-
|
|
- if (!uuid)
|
|
- return -EINVAL;
|
|
-
|
|
- /* Get secure object */
|
|
- obj = tbase_object_get(uuid, is_gp_uuid);
|
|
- if (IS_ERR(obj)) {
|
|
- /* Try to select secure object inside the SWd if not found */
|
|
- if ((PTR_ERR(obj) == -ENOENT) && g_ctx.f_ta_auth)
|
|
- obj = tbase_object_select(uuid);
|
|
-
|
|
- if (IS_ERR(obj)) {
|
|
- err = PTR_ERR(obj);
|
|
- goto end;
|
|
- }
|
|
- }
|
|
-
|
|
- /* Open session */
|
|
- err = client_add_session(client, obj, tci, tci_len, &sid, is_gp_uuid,
|
|
- identity);
|
|
- /* Fill in return parameter */
|
|
- if (!err)
|
|
- *p_session_id = sid;
|
|
-
|
|
- /* Delete secure object */
|
|
- tbase_object_free(obj);
|
|
-
|
|
-end:
|
|
-
|
|
- MCDRV_DBG("session %x, exit with %d\n", sid, err);
|
|
- return err;
|
|
-}
|
|
-
|
|
-/*
|
|
- * Open TA for given client. TA binary is provided by the client.
|
|
- * @param
|
|
- * @return tbase driver error code
|
|
- */
|
|
-int api_open_trustlet(struct tbase_client *client,
|
|
- uint32_t *p_session_id,
|
|
- uint32_t spid,
|
|
- uintptr_t trustlet,
|
|
- size_t trustlet_len,
|
|
- uintptr_t tci,
|
|
- size_t tci_len)
|
|
-{
|
|
- struct tbase_object *obj;
|
|
- struct mc_identity identity = {
|
|
- .login_type = TEEC_LOGIN_PUBLIC,
|
|
- };
|
|
- uint32_t sid = 0;
|
|
- int err = 0;
|
|
-
|
|
- /* Check parameters */
|
|
- if (!p_session_id)
|
|
- return -EINVAL;
|
|
-
|
|
- /* Create secure object from user-space trustlet binary */
|
|
- obj = tbase_object_read(spid, trustlet, trustlet_len);
|
|
- if (IS_ERR(obj)) {
|
|
- err = PTR_ERR(obj);
|
|
- goto end;
|
|
- }
|
|
-
|
|
- /* Open session */
|
|
- err = client_add_session(client, obj, tci, tci_len, &sid, false,
|
|
- &identity);
|
|
- /* Fill in return parameter */
|
|
- if (!err)
|
|
- *p_session_id = sid;
|
|
-
|
|
- /* Delete secure object */
|
|
- tbase_object_free(obj);
|
|
-
|
|
-end:
|
|
- MCDRV_DBG("session %x, exit with %d\n", sid, err);
|
|
- return err;
|
|
-}
|
|
-
|
|
-/*
|
|
- * Close a TA
|
|
- * @param
|
|
- * @return tbase driver error code
|
|
- */
|
|
-int api_close_session(struct tbase_client *client, uint32_t session_id)
|
|
-{
|
|
- int ret = client_remove_session(client, session_id);
|
|
-
|
|
- MCDRV_DBG("session %x, exit with %d\n", session_id, ret);
|
|
- return ret;
|
|
-}
|
|
-
|
|
-/*
|
|
- * Send a notification to TA
|
|
- * @return tbase driver error code
|
|
- */
|
|
-int api_notify(struct tbase_client *client, uint32_t session_id)
|
|
-{
|
|
- int err = 0;
|
|
- struct tbase_session *session = NULL;
|
|
-
|
|
- /* Acquire session */
|
|
- session = client_ref_session(client, session_id);
|
|
-
|
|
- /* Send command to SWd */
|
|
- if (!session) {
|
|
- err = -ENXIO;
|
|
- } else {
|
|
- err = session_notify_swd(session);
|
|
-
|
|
- /* Release session */
|
|
- client_unref_session(session);
|
|
- }
|
|
-
|
|
- MCDRV_DBG("session %x, exit with %d\n", session_id, err);
|
|
- return err;
|
|
-}
|
|
-
|
|
-/*
|
|
- * Wait for a notification from TA
|
|
- * @return tbase driver error code
|
|
- */
|
|
-int api_wait_notification(struct tbase_client *client,
|
|
- uint32_t session_id,
|
|
- int32_t timeout)
|
|
-{
|
|
- int err = 0;
|
|
- struct tbase_session *session = NULL;
|
|
-
|
|
- /* Acquire session */
|
|
- session = client_ref_session(client, session_id);
|
|
-
|
|
- /* Wait for notification */
|
|
- if (!session) {
|
|
- err = -ENXIO;
|
|
- } else {
|
|
- err = session_waitnotif(session, timeout);
|
|
-
|
|
- /* Release session */
|
|
- client_unref_session(session);
|
|
- }
|
|
-
|
|
- MCDRV_DBG("session %x, exit with %d\n", session_id, err);
|
|
- return err;
|
|
-}
|
|
-
|
|
-/*
|
|
- * Allocate a contiguous buffer (cbuf) for given client
|
|
- *
|
|
- * @param client client
|
|
- * @param len size of the cbuf
|
|
- * @param **p_addr pointer to the cbuf kva
|
|
- * @return tbase driver error code
|
|
- */
|
|
-int api_malloc_cbuf(struct tbase_client *client, uint32_t len,
|
|
- uintptr_t *addr, struct vm_area_struct *vmarea)
|
|
-{
|
|
- int err = tbase_cbuf_alloc(client, len, addr, vmarea);
|
|
-
|
|
- MCDRV_DBG("exit with %d\n", err);
|
|
- return err;
|
|
-}
|
|
-
|
|
-/*
|
|
- * Free a contiguous buffer from given client
|
|
- * @param client
|
|
- * @param addr kernel virtual address of the buffer
|
|
- *
|
|
- * @return tbase driver error code
|
|
- */
|
|
-int api_free_cbuf(struct tbase_client *client, uintptr_t addr)
|
|
-{
|
|
- int err = tbase_cbuf_free(client, addr);
|
|
-
|
|
- MCDRV_DBG("@ 0x%lx, exit with %d\n", addr, err);
|
|
- return err;
|
|
-}
|
|
-
|
|
-/* Share a buffer with given TA in SWd */
|
|
-int api_map_wsms(struct tbase_client *client, uint32_t session_id,
|
|
- struct mc_ioctl_buffer *bufs)
|
|
-{
|
|
- struct tbase_session *session = NULL;
|
|
- int err = 0;
|
|
-
|
|
- if (!client)
|
|
- return -EINVAL;
|
|
-
|
|
- if (!bufs)
|
|
- return -EINVAL;
|
|
-
|
|
- /* Acquire session */
|
|
- session = client_ref_session(client, session_id);
|
|
-
|
|
- if (session) {
|
|
- /* Add buffer to the session */
|
|
- err = session_wsms_add(session, bufs);
|
|
-
|
|
- /* Release session */
|
|
- client_unref_session(session);
|
|
- } else {
|
|
- err = -ENXIO;
|
|
- }
|
|
-
|
|
- MCDRV_DBG("exit with %d\n", err);
|
|
- return err;
|
|
-}
|
|
-
|
|
-/* Stop sharing a buffer with SWd */
|
|
-int api_unmap_wsms(struct tbase_client *client, uint32_t session_id,
|
|
- const struct mc_ioctl_buffer *bufs)
|
|
-{
|
|
- struct tbase_session *session = NULL;
|
|
- int err = 0;
|
|
-
|
|
- if (!client)
|
|
- return -EINVAL;
|
|
-
|
|
- if (!bufs)
|
|
- return -EINVAL;
|
|
-
|
|
- /* Acquire session */
|
|
- session = client_ref_session(client, session_id);
|
|
-
|
|
- if (!session) {
|
|
- err = -ENXIO;
|
|
- } else {
|
|
- /* Remove buffer from session */
|
|
- err = session_wsms_remove(session, bufs);
|
|
- /* Release session */
|
|
- client_unref_session(session);
|
|
- }
|
|
-
|
|
- MCDRV_DBG("exit with %d\n", err);
|
|
- return err;
|
|
-}
|
|
-
|
|
-/*
|
|
- * Read session exit/termination code
|
|
- */
|
|
-int api_get_session_exitcode(struct tbase_client *client, uint32_t session_id,
|
|
- int32_t *exit_code)
|
|
-{
|
|
- int err = 0;
|
|
- struct tbase_session *session;
|
|
-
|
|
- /* Acquire session */
|
|
- session = client_ref_session(client, session_id);
|
|
-
|
|
- if (!session) {
|
|
- err = -ENXIO;
|
|
- } else {
|
|
- /* Retrieve error */
|
|
- *exit_code = session_exitcode(session);
|
|
-
|
|
- /* Release session */
|
|
- client_unref_session(session);
|
|
-
|
|
- err = 0;
|
|
- }
|
|
-
|
|
- MCDRV_DBG("session %x, exit with %d\n", session_id, err);
|
|
- return err;
|
|
-}
|
|
-
|
|
-void api_init(void)
|
|
-{
|
|
- INIT_LIST_HEAD(&api_ctx.clients);
|
|
- mutex_init(&api_ctx.clients_lock);
|
|
-
|
|
- INIT_LIST_HEAD(&g_ctx.closing_sess);
|
|
- mutex_init(&g_ctx.closing_lock);
|
|
-}
|
|
-
|
|
-int api_info(struct kasnprintf_buf *buf)
|
|
-{
|
|
- struct tbase_client *client;
|
|
- struct tbase_session *session;
|
|
- ssize_t ret = 0;
|
|
-
|
|
- mutex_lock(&api_ctx.clients_lock);
|
|
- if (list_empty(&api_ctx.clients))
|
|
- goto done;
|
|
-
|
|
- list_for_each_entry(client, &api_ctx.clients, list) {
|
|
- ret = client_info(client, buf);
|
|
- if (ret < 0)
|
|
- break;
|
|
- }
|
|
-
|
|
-done:
|
|
- mutex_unlock(&api_ctx.clients_lock);
|
|
-
|
|
- if (ret >= 0) {
|
|
- mutex_lock(&g_ctx.closing_lock);
|
|
- if (!list_empty(&g_ctx.closing_sess))
|
|
- ret = kasnprintf(buf, "closing sessions:\n");
|
|
-
|
|
- list_for_each_entry(session, &g_ctx.closing_sess, list) {
|
|
- ret = session_info(session, buf);
|
|
- if (ret < 0)
|
|
- break;
|
|
- }
|
|
-
|
|
- mutex_unlock(&g_ctx.closing_lock);
|
|
- }
|
|
-
|
|
- return ret;
|
|
-}
|
|
diff --git a/drivers/gud/MobiCoreDriver/api.h b/drivers/gud/MobiCoreDriver/api.h
|
|
deleted file mode 100644
|
|
index 740ec7fb2d5b9..0000000000000
|
|
--- a/drivers/gud/MobiCoreDriver/api.h
|
|
+++ /dev/null
|
|
@@ -1,46 +0,0 @@
|
|
-/*
|
|
- * Copyright (c) 2013-2015 TRUSTONIC LIMITED
|
|
- * All Rights Reserved.
|
|
- *
|
|
- * This program is free software; you can redistribute it and/or
|
|
- * modify it under the terms of the GNU General Public License
|
|
- * version 2 as published by the Free Software Foundation.
|
|
- *
|
|
- * This program is distributed in the hope that it will be useful,
|
|
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
- * GNU General Public License for more details.
|
|
- */
|
|
-
|
|
-#ifndef _API_H_
|
|
-#define _API_H_
|
|
-
|
|
-struct tbase_client;
|
|
-
|
|
-struct tbase_client *api_open_device(bool is_from_kernel);
|
|
-int api_freeze_device(struct tbase_client *client);
|
|
-void api_close_device(struct tbase_client *client);
|
|
-int api_open_session(struct tbase_client *client, uint32_t *session_id,
|
|
- const struct mc_uuid_t *uuid,
|
|
- uintptr_t tci, size_t tci_len, bool is_gp_uuid,
|
|
- struct mc_identity *identity);
|
|
-int api_open_trustlet(struct tbase_client *client, uint32_t *session_id,
|
|
- uint32_t spid, uintptr_t trustlet, size_t trustlet_len,
|
|
- uintptr_t tci, size_t tci_len);
|
|
-int api_close_session(struct tbase_client *client, uint32_t session_id);
|
|
-int api_notify(struct tbase_client *client, uint32_t session_id);
|
|
-int api_wait_notification(struct tbase_client *client, uint32_t session_id,
|
|
- int32_t timeout);
|
|
-int api_malloc_cbuf(struct tbase_client *client, uint32_t len, uintptr_t *addr,
|
|
- struct vm_area_struct *vmarea);
|
|
-int api_free_cbuf(struct tbase_client *client, uintptr_t addr);
|
|
-int api_map_wsms(struct tbase_client *client, uint32_t session_id,
|
|
- struct mc_ioctl_buffer *bufs);
|
|
-int api_unmap_wsms(struct tbase_client *client, uint32_t session_id,
|
|
- const struct mc_ioctl_buffer *bufs);
|
|
-int api_get_session_exitcode(struct tbase_client *client, uint32_t session_id,
|
|
- int32_t *exit_code);
|
|
-void api_init(void);
|
|
-int api_info(struct kasnprintf_buf *buf);
|
|
-
|
|
-#endif /* _API_H_ */
|
|
diff --git a/drivers/gud/MobiCoreDriver/arm.h b/drivers/gud/MobiCoreDriver/arm.h
|
|
deleted file mode 100644
|
|
index 58d91f11f789c..0000000000000
|
|
--- a/drivers/gud/MobiCoreDriver/arm.h
|
|
+++ /dev/null
|
|
@@ -1,88 +0,0 @@
|
|
-/*
|
|
- * Copyright (c) 2013-2014 TRUSTONIC LIMITED
|
|
- * All Rights Reserved.
|
|
- *
|
|
- * This program is free software; you can redistribute it and/or
|
|
- * modify it under the terms of the GNU General Public License
|
|
- * version 2 as published by the Free Software Foundation.
|
|
- *
|
|
- * This program is distributed in the hope that it will be useful,
|
|
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
- * GNU General Public License for more details.
|
|
- */
|
|
-#ifndef _MC_ARM_H_
|
|
-#define _MC_ARM_H_
|
|
-
|
|
-#include "debug.h"
|
|
-
|
|
-#ifdef CONFIG_ARM64
|
|
-inline bool has_security_extensions(void)
|
|
-{
|
|
- return true;
|
|
-}
|
|
-
|
|
-inline bool is_secure_mode(void)
|
|
-{
|
|
- return false;
|
|
-}
|
|
-#else
|
|
-/*
|
|
- * ARM Trustzone specific masks and modes
|
|
- * Vanilla Linux is unaware of TrustZone extension.
|
|
- * I.e. arch/arm/include/asm/ptrace.h does not define monitor mode.
|
|
- * Also TZ bits in cpuid are not defined, ARM port uses magic numbers,
|
|
- * see arch/arm/kernel/setup.c
|
|
- */
|
|
-#define ARM_MONITOR_MODE (0x16) /*(0b10110)*/
|
|
-#define ARM_SECURITY_EXTENSION_MASK (0x30)
|
|
-
|
|
-/* check if CPU supports the ARM TrustZone Security Extensions */
|
|
-inline bool has_security_extensions(void)
|
|
-{
|
|
- u32 fea = 0;
|
|
-
|
|
- asm volatile(
|
|
- "mrc p15, 0, %[fea], cr0, cr1, 0" :
|
|
- [fea]"=r" (fea));
|
|
-
|
|
- MCDRV_DBG_VERBOSE("CPU Features: 0x%X", fea);
|
|
-
|
|
- /*
|
|
- * If the CPU features ID has 0 for security features then the CPU
|
|
- * doesn't support TrustZone at all!
|
|
- */
|
|
- if ((fea & ARM_SECURITY_EXTENSION_MASK) == 0)
|
|
- return false;
|
|
-
|
|
- return true;
|
|
-}
|
|
-
|
|
-/* check if running in secure mode */
|
|
-inline bool is_secure_mode(void)
|
|
-{
|
|
- u32 cpsr = 0;
|
|
- u32 nsacr = 0;
|
|
-
|
|
- asm volatile(
|
|
- "mrc p15, 0, %[nsacr], cr1, cr1, 2\n"
|
|
- "mrs %[cpsr], cpsr\n" :
|
|
- [nsacr]"=r" (nsacr),
|
|
- [cpsr]"=r"(cpsr));
|
|
-
|
|
- MCDRV_DBG_VERBOSE("CPRS.M = set to 0x%X\n", cpsr & MODE_MASK);
|
|
- MCDRV_DBG_VERBOSE("SCR.NS = set to 0x%X\n", nsacr);
|
|
-
|
|
- /*
|
|
- * If the NSACR contains the reset value(=0) then most likely we are
|
|
- * running in Secure MODE.
|
|
- * If the cpsr mode is set to monitor mode then we cannot load!
|
|
- */
|
|
- if (nsacr == 0 || ((cpsr & MODE_MASK) == ARM_MONITOR_MODE))
|
|
- return true;
|
|
-
|
|
- return false;
|
|
-}
|
|
-#endif
|
|
-
|
|
-#endif /* _MC_ARM_H_ */
|
|
diff --git a/drivers/gud/MobiCoreDriver/build_tag.h b/drivers/gud/MobiCoreDriver/build_tag.h
|
|
deleted file mode 100644
|
|
index 51a5d3e0ae7f5..0000000000000
|
|
--- a/drivers/gud/MobiCoreDriver/build_tag.h
|
|
+++ /dev/null
|
|
@@ -1,15 +0,0 @@
|
|
-/*
|
|
- * Copyright (c) 2013-2014 TRUSTONIC LIMITED
|
|
- * All Rights Reserved.
|
|
- *
|
|
- * This program is free software; you can redistribute it and/or
|
|
- * modify it under the terms of the GNU General Public License
|
|
- * version 2 as published by the Free Software Foundation.
|
|
- *
|
|
- * This program is distributed in the hope that it will be useful,
|
|
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
- * GNU General Public License for more details.
|
|
- */
|
|
-#define MOBICORE_COMPONENT_BUILD_TAG \
|
|
- "t-base-QC-MSM8996-Android-302B-V001-20150529_084320_16"
|
|
diff --git a/drivers/gud/MobiCoreDriver/client.c b/drivers/gud/MobiCoreDriver/client.c
|
|
deleted file mode 100644
|
|
index c8bdc07b8742d..0000000000000
|
|
--- a/drivers/gud/MobiCoreDriver/client.c
|
|
+++ /dev/null
|
|
@@ -1,572 +0,0 @@
|
|
-/*
|
|
- * Copyright (c) 2013-2015 TRUSTONIC LIMITED
|
|
- * All Rights Reserved.
|
|
- *
|
|
- * This program is free software; you can redistribute it and/or
|
|
- * modify it under the terms of the GNU General Public License
|
|
- * version 2 as published by the Free Software Foundation.
|
|
- *
|
|
- * This program is distributed in the hope that it will be useful,
|
|
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
- * GNU General Public License for more details.
|
|
- */
|
|
-#include <linux/list.h>
|
|
-#include <linux/slab.h>
|
|
-#include <linux/device.h>
|
|
-#include <linux/mm.h>
|
|
-#include <linux/sched.h>
|
|
-#include <linux/err.h>
|
|
-
|
|
-#include "public/mc_linux.h"
|
|
-#include "public/mc_admin.h"
|
|
-
|
|
-#include "main.h"
|
|
-#include "debug.h"
|
|
-#include "mcp.h"
|
|
-#include "mmu.h"
|
|
-#include "session.h"
|
|
-#include "client.h"
|
|
-
|
|
-/*
|
|
- * Contiguous buffer allocated to TLCs.
|
|
- * These buffers are used as world shared memory (wsm) to share with
|
|
- * secure world.
|
|
- */
|
|
-struct tbase_cbuf {
|
|
- /* Client this cbuf belongs to */
|
|
- struct tbase_client *client;
|
|
- /* List element for client's list of cbuf's */
|
|
- struct list_head list;
|
|
- /* Number of references kept to this buffer */
|
|
- struct kref kref;
|
|
- /* virtual Kernel start address */
|
|
- uintptr_t addr;
|
|
- /* virtual Userspace start address */
|
|
- uintptr_t uaddr;
|
|
- /* physical start address */
|
|
- phys_addr_t phys;
|
|
- /* 2^order = number of pages allocated */
|
|
- unsigned int order;
|
|
- /* Length of memory mapped to user */
|
|
- uint32_t len;
|
|
-};
|
|
-
|
|
-/*
|
|
- * Map a kernel contiguous buffer to user space
|
|
- */
|
|
-static int map_cbuf(struct vm_area_struct *vmarea, uintptr_t addr, uint32_t len,
|
|
- uintptr_t *uaddr)
|
|
-{
|
|
- int ret;
|
|
-
|
|
- if (WARN(!uaddr, "No uaddr pointer available"))
|
|
- return -EINVAL;
|
|
-
|
|
- if (WARN(!vmarea, "No vma available"))
|
|
- return -EINVAL;
|
|
-
|
|
- if (WARN(!addr, "No addr available"))
|
|
- return -EINVAL;
|
|
-
|
|
- if (len != (uint32_t)(vmarea->vm_end - vmarea->vm_start)) {
|
|
- MCDRV_ERROR("cbuf incompatible with vma");
|
|
- return -EINVAL;
|
|
- }
|
|
-
|
|
- vmarea->vm_flags |= VM_IO;
|
|
-
|
|
- /* CPI todo: use io_remap_page_range() to be consistent with VM_IO ? */
|
|
- ret = remap_pfn_range(vmarea, vmarea->vm_start,
|
|
- page_to_pfn(virt_to_page(addr)),
|
|
- vmarea->vm_end - vmarea->vm_start,
|
|
- vmarea->vm_page_prot);
|
|
- if (ret) {
|
|
- *uaddr = 0;
|
|
- MCDRV_ERROR("User mapping failed");
|
|
- return ret;
|
|
- }
|
|
-
|
|
- *uaddr = vmarea->vm_start;
|
|
- return 0;
|
|
-}
|
|
-
|
|
-/*
|
|
- * Allocate and initialize a client object
|
|
- */
|
|
-struct tbase_client *client_create(bool is_from_kernel)
|
|
-{
|
|
- struct tbase_client *client;
|
|
-
|
|
- /* allocate client structure */
|
|
- client = kzalloc(sizeof(*client), GFP_KERNEL);
|
|
- if (!client) {
|
|
- MCDRV_ERROR("Allocation failure");
|
|
- return NULL;
|
|
- }
|
|
-
|
|
- /* init members */
|
|
- client->pid = is_from_kernel ? 0 : current->pid;
|
|
- memcpy(client->comm, current->comm, sizeof(client->comm));
|
|
- kref_init(&client->kref);
|
|
- INIT_LIST_HEAD(&client->cbufs);
|
|
- mutex_init(&client->cbufs_lock);
|
|
- INIT_LIST_HEAD(&client->sessions);
|
|
- mutex_init(&client->sessions_lock);
|
|
- INIT_LIST_HEAD(&client->list);
|
|
-
|
|
- return client;
|
|
-}
|
|
-
|
|
-/*
|
|
- * At this point, nobody has access to the client anymore, so no new sessions
|
|
- * are coming.
|
|
- */
|
|
-void client_close_sessions(struct tbase_client *client)
|
|
-{
|
|
- struct tbase_session *session;
|
|
-
|
|
- mutex_lock(&client->sessions_lock);
|
|
- while (!list_empty(&client->sessions)) {
|
|
- session = list_first_entry(&client->sessions,
|
|
- struct tbase_session, list);
|
|
-
|
|
- /* Move session to closing sessions list */
|
|
- mutex_lock(&g_ctx.closing_lock);
|
|
- list_move(&session->list, &g_ctx.closing_sess);
|
|
- mutex_unlock(&g_ctx.closing_lock);
|
|
- /* Call session_close without lock */
|
|
- mutex_unlock(&client->sessions_lock);
|
|
- session_close(session);
|
|
- mutex_lock(&client->sessions_lock);
|
|
- }
|
|
-
|
|
- mutex_unlock(&client->sessions_lock);
|
|
-}
|
|
-
|
|
-/*
|
|
- * Free client object + all objects it contains.
|
|
- * Can be called only by last user referencing the client,
|
|
- * therefore mutex lock seems overkill
|
|
- */
|
|
-static void client_release(struct kref *kref)
|
|
-{
|
|
- struct tbase_client *client;
|
|
-
|
|
- client = container_of(kref, struct tbase_client, kref);
|
|
- kfree(client);
|
|
-}
|
|
-
|
|
-void client_put(struct tbase_client *client)
|
|
-{
|
|
- kref_put(&client->kref, client_release);
|
|
-}
|
|
-
|
|
-/*
|
|
- * Returns true if client is a kernel object.
|
|
- */
|
|
-bool client_is_kernel(struct tbase_client *client)
|
|
-{
|
|
- return !client->pid;
|
|
-}
|
|
-
|
|
-/*
|
|
- * Set client "closing" state, only if it contains no session.
|
|
- * Once in "closing" state, system "close" can be called.
|
|
- * Return: true if this state could be set.
|
|
- */
|
|
-bool client_set_closing(struct tbase_client *client)
|
|
-{
|
|
- bool clear = false;
|
|
-
|
|
- /* Check for sessions */
|
|
- mutex_lock(&client->sessions_lock);
|
|
- clear = list_empty(&client->sessions);
|
|
- client->closing = clear;
|
|
- mutex_unlock(&client->sessions_lock);
|
|
- MCDRV_DBG("return %d", clear);
|
|
- return clear;
|
|
-}
|
|
-
|
|
-/*
|
|
- * Opens a TA and add corresponding session object to given client
|
|
- * return: t-base driver error code
|
|
- */
|
|
-int client_add_session(struct tbase_client *client,
|
|
- const struct tbase_object *obj, uintptr_t tci,
|
|
- size_t len, uint32_t *session_id, bool is_gp,
|
|
- struct mc_identity *identity)
|
|
-{
|
|
- struct tbase_session *session = NULL;
|
|
- struct tbase_mmu *obj_mmu = NULL;
|
|
- int ret = 0;
|
|
-
|
|
- /*
|
|
- * Create session object with temp sid=0 BEFORE session is started,
|
|
- * otherwise if a GP TA is started and NWd session object allocation
|
|
- * fails, we cannot handle the potentially delayed GP closing.
|
|
- * Adding session to list must be done AFTER it is started (once we have
|
|
- * sid), therefore it cannot be done within session_create().
|
|
- */
|
|
- session = session_create(client, is_gp, identity);
|
|
- if (IS_ERR(session))
|
|
- return PTR_ERR(session);
|
|
-
|
|
- /* Create blob L2 table (blob is allocated by driver, so task=NULL) */
|
|
- obj_mmu = tbase_mmu_create(NULL, obj->data, obj->length);
|
|
- if (IS_ERR(obj_mmu)) {
|
|
- ret = PTR_ERR(obj_mmu);
|
|
- goto err;
|
|
- }
|
|
-
|
|
- /* Open session */
|
|
- ret = session_open(session, obj, obj_mmu, tci, len);
|
|
- /* Blob table no more needed in any case */
|
|
- tbase_mmu_delete(obj_mmu);
|
|
- if (ret)
|
|
- goto err;
|
|
-
|
|
- mutex_lock(&client->sessions_lock);
|
|
- if (unlikely(client->closing)) {
|
|
- /* Client has been frozen, no more sessions allowed */
|
|
- ret = -ENODEV;
|
|
- } else {
|
|
- /* Add session to client */
|
|
- list_add(&session->list, &client->sessions);
|
|
- /* Set sid returned by SWd */
|
|
- *session_id = session->mcp_session.id;
|
|
- }
|
|
-
|
|
- mutex_unlock(&client->sessions_lock);
|
|
-
|
|
-err:
|
|
- /* Close or free session on error */
|
|
- if (ret == -ENODEV) {
|
|
- /* The session must enter the closing process... */
|
|
- mutex_lock(&g_ctx.closing_lock);
|
|
- list_add(&session->list, &g_ctx.closing_sess);
|
|
- mutex_unlock(&g_ctx.closing_lock);
|
|
- session_close(session);
|
|
- } else if (ret) {
|
|
- session_put(session);
|
|
- }
|
|
-
|
|
- return ret;
|
|
-}
|
|
-
|
|
-/*
|
|
- * Remove a session object from client and close corresponding TA
|
|
- * Return: true if session was found and closed
|
|
- */
|
|
-int client_remove_session(struct tbase_client *client, uint32_t session_id)
|
|
-{
|
|
- struct tbase_session *session = NULL, *candidate;
|
|
-
|
|
- /* Move session from main list to closing list */
|
|
- mutex_lock(&client->sessions_lock);
|
|
- list_for_each_entry(candidate, &client->sessions, list) {
|
|
- if (candidate->mcp_session.id == session_id) {
|
|
- session = candidate;
|
|
- mutex_lock(&g_ctx.closing_lock);
|
|
- list_move(&session->list, &g_ctx.closing_sess);
|
|
- mutex_unlock(&g_ctx.closing_lock);
|
|
- break;
|
|
- }
|
|
- }
|
|
-
|
|
- mutex_unlock(&client->sessions_lock);
|
|
-
|
|
- /* Close session */
|
|
- return session_close(session);
|
|
-}
|
|
-
|
|
-/*
|
|
- * Find a session object and increment its reference counter.
|
|
- * Object cannot be freed until its counter reaches 0.
|
|
- * return: pointer to the object, NULL if not found.
|
|
- */
|
|
-struct tbase_session *client_ref_session(struct tbase_client *client,
|
|
- uint32_t session_id)
|
|
-{
|
|
- struct tbase_session *session = NULL, *candidate;
|
|
-
|
|
- mutex_lock(&client->sessions_lock);
|
|
- list_for_each_entry(candidate, &client->sessions, list) {
|
|
- if (candidate->mcp_session.id == session_id) {
|
|
- session = candidate;
|
|
- session_get(session);
|
|
- break;
|
|
- }
|
|
- }
|
|
-
|
|
- mutex_unlock(&client->sessions_lock);
|
|
- return session;
|
|
-}
|
|
-
|
|
-/*
|
|
- * Decrement a session object's reference counter, and frees the object if it
|
|
- * was the last reference.
|
|
- * No lookup since session may have been removed from list
|
|
- */
|
|
-void client_unref_session(struct tbase_session *session)
|
|
-{
|
|
- session_put(session);
|
|
-}
|
|
-
|
|
-static inline int cbuf_info(struct tbase_cbuf *cbuf,
|
|
- struct kasnprintf_buf *buf);
|
|
-
|
|
-int client_info(struct tbase_client *client, struct kasnprintf_buf *buf)
|
|
-{
|
|
- struct tbase_cbuf *cbuf;
|
|
- struct tbase_session *session;
|
|
- int ret;
|
|
-
|
|
- if (client->pid)
|
|
- ret = kasnprintf(buf, "client %p: %s (%d)\n", client,
|
|
- client->comm, client->pid);
|
|
- else
|
|
- ret = kasnprintf(buf, "client %p: [kernel]\n", client);
|
|
-
|
|
- if (ret < 0)
|
|
- return ret;
|
|
-
|
|
- /* Buffers */
|
|
- mutex_lock(&client->cbufs_lock);
|
|
- if (list_empty(&client->cbufs))
|
|
- goto done_cbufs;
|
|
-
|
|
- list_for_each_entry(cbuf, &client->cbufs, list) {
|
|
- ret = cbuf_info(cbuf, buf);
|
|
- if (ret < 0)
|
|
- goto done_cbufs;
|
|
- }
|
|
-
|
|
-done_cbufs:
|
|
- mutex_unlock(&client->cbufs_lock);
|
|
- if (ret < 0)
|
|
- return ret;
|
|
-
|
|
- /* Sessions */
|
|
- mutex_lock(&client->sessions_lock);
|
|
- if (list_empty(&client->sessions))
|
|
- goto done_sessions;
|
|
-
|
|
- list_for_each_entry(session, &client->sessions, list) {
|
|
- ret = session_info(session, buf);
|
|
- if (ret < 0)
|
|
- goto done_sessions;
|
|
- }
|
|
-
|
|
-done_sessions:
|
|
- mutex_unlock(&client->sessions_lock);
|
|
-
|
|
- if (ret < 0)
|
|
- return ret;
|
|
-
|
|
- return 0;
|
|
-}
|
|
-
|
|
-/*
|
|
- * This callback is called on remap
|
|
- */
|
|
-static void cbuf_vm_open(struct vm_area_struct *vmarea)
|
|
-{
|
|
- struct tbase_cbuf *cbuf = vmarea->vm_private_data;
|
|
-
|
|
- tbase_cbuf_get(cbuf);
|
|
-}
|
|
-
|
|
-/*
|
|
- * This callback is called on unmap
|
|
- */
|
|
-static void cbuf_vm_close(struct vm_area_struct *vmarea)
|
|
-{
|
|
- struct tbase_cbuf *cbuf = vmarea->vm_private_data;
|
|
-
|
|
- tbase_cbuf_put(cbuf);
|
|
-}
|
|
-
|
|
-static struct vm_operations_struct cbuf_vm_ops = {
|
|
- .open = cbuf_vm_open,
|
|
- .close = cbuf_vm_close,
|
|
-};
|
|
-
|
|
-/*
|
|
- * Create a cbuf object and add it to client
|
|
- */
|
|
-int tbase_cbuf_alloc(struct tbase_client *client, uint32_t len,
|
|
- uintptr_t *p_addr,
|
|
- struct vm_area_struct *vmarea)
|
|
-{
|
|
- int err = 0;
|
|
- struct tbase_cbuf *cbuf = NULL;
|
|
- unsigned int order;
|
|
-
|
|
- if (WARN(!client, "No client available"))
|
|
- return -EINVAL;
|
|
-
|
|
- if (WARN(!len, "No len available"))
|
|
- return -EINVAL;
|
|
-
|
|
- order = get_order(len);
|
|
- if (order > MAX_ORDER) {
|
|
- MCDRV_DBG_WARN("Buffer size too large");
|
|
- return -ENOMEM;
|
|
- }
|
|
-
|
|
- /* Allocate buffer descriptor structure */
|
|
- cbuf = kzalloc(sizeof(*cbuf), GFP_KERNEL);
|
|
- if (!cbuf) {
|
|
- MCDRV_DBG_WARN("kzalloc failed");
|
|
- return -ENOMEM;
|
|
- }
|
|
-
|
|
- /* Allocate buffer */
|
|
- cbuf->addr = __get_free_pages(GFP_USER | __GFP_ZERO, order);
|
|
- if (!cbuf->addr) {
|
|
- MCDRV_DBG_WARN("get_free_pages failed");
|
|
- kfree(cbuf);
|
|
- return -ENOMEM;
|
|
- }
|
|
-
|
|
- /* Map to user space if applicable */
|
|
- if (!client_is_kernel(client)) {
|
|
- err = map_cbuf(vmarea, cbuf->addr, len, &cbuf->uaddr);
|
|
- if (err) {
|
|
- free_pages(cbuf->addr, order);
|
|
- kfree(cbuf);
|
|
- return err;
|
|
- }
|
|
- }
|
|
-
|
|
- /* Init descriptor members */
|
|
- cbuf->client = client;
|
|
- cbuf->phys = virt_to_phys((void *)cbuf->addr);
|
|
- cbuf->len = len;
|
|
- cbuf->order = order;
|
|
- kref_init(&cbuf->kref);
|
|
- INIT_LIST_HEAD(&cbuf->list);
|
|
-
|
|
- /* Keep cbuf in VMA private data for refcounting (user-space clients) */
|
|
- if (vmarea) {
|
|
- vmarea->vm_private_data = cbuf;
|
|
- vmarea->vm_ops = &cbuf_vm_ops;
|
|
- }
|
|
-
|
|
- /* Fill return parameter for k-api */
|
|
- if (p_addr)
|
|
- *p_addr = cbuf->addr;
|
|
-
|
|
- /* Get a token on the client */
|
|
- client_get(client);
|
|
-
|
|
- /* Add buffer to list */
|
|
- mutex_lock(&client->cbufs_lock);
|
|
- list_add(&cbuf->list, &client->cbufs);
|
|
- mutex_unlock(&client->cbufs_lock);
|
|
- MCDRV_DBG("created cbuf %p: client %p addr %lx uaddr %lx len %u",
|
|
- cbuf, client, cbuf->addr, cbuf->uaddr, cbuf->len);
|
|
- return err;
|
|
-}
|
|
-
|
|
-/*
|
|
- * Remove a cbuf object from client, and mark it for freeing.
|
|
- * Freeing will happen once all current references are released.
|
|
- */
|
|
-int tbase_cbuf_free(struct tbase_client *client, uintptr_t addr)
|
|
-{
|
|
- struct tbase_cbuf *cbuf = tbase_cbuf_get_by_addr(client, addr);
|
|
-
|
|
- if (!cbuf)
|
|
- return -EINVAL;
|
|
-
|
|
- /* Two references to put: the caller's and the one we just took */
|
|
- tbase_cbuf_put(cbuf);
|
|
- tbase_cbuf_put(cbuf);
|
|
- return 0;
|
|
-}
|
|
-
|
|
-/*
|
|
- * Find a contiguous buffer (cbuf) in the cbuf list of given client that
|
|
- * contains given address and take a reference on it.
|
|
- * Return pointer to the object, or NULL if not found.
|
|
- */
|
|
-struct tbase_cbuf *tbase_cbuf_get_by_addr(struct tbase_client *client,
|
|
- uintptr_t addr)
|
|
-{
|
|
- struct tbase_cbuf *cbuf = NULL, *candidate;
|
|
- bool is_kernel = client_is_kernel(client);
|
|
-
|
|
- mutex_lock(&client->cbufs_lock);
|
|
- list_for_each_entry(candidate, &client->cbufs, list) {
|
|
- /* Compare Vs kernel va OR user va depending on client type */
|
|
- uintptr_t start = is_kernel ?
|
|
- candidate->addr : candidate->uaddr;
|
|
- uintptr_t end = start + candidate->len;
|
|
-
|
|
- /* Check that (user) cbuf has not been unmapped */
|
|
- if (!start)
|
|
- break;
|
|
-
|
|
- if ((addr >= start) && (addr < end)) {
|
|
- cbuf = candidate;
|
|
- break;
|
|
- }
|
|
- }
|
|
-
|
|
- if (cbuf)
|
|
- tbase_cbuf_get(cbuf);
|
|
-
|
|
- mutex_unlock(&client->cbufs_lock);
|
|
- return cbuf;
|
|
-}
|
|
-
|
|
-void tbase_cbuf_get(struct tbase_cbuf *cbuf)
|
|
-{
|
|
- kref_get(&cbuf->kref);
|
|
-}
|
|
-
|
|
-static void cbuf_release(struct kref *kref)
|
|
-{
|
|
- struct tbase_cbuf *cbuf = container_of(kref, struct tbase_cbuf, kref);
|
|
- struct tbase_client *client = cbuf->client;
|
|
-
|
|
- /* Unlist from client */
|
|
- mutex_lock(&client->cbufs_lock);
|
|
- list_del_init(&cbuf->list);
|
|
- mutex_unlock(&client->cbufs_lock);
|
|
- /* Release client token */
|
|
- client_put(client);
|
|
- /* Free */
|
|
- free_pages(cbuf->addr, cbuf->order);
|
|
- MCDRV_DBG("freed cbuf %p: client %p addr %lx uaddr %lx len %u",
|
|
- cbuf, client, cbuf->addr, cbuf->uaddr, cbuf->len);
|
|
- kfree(cbuf);
|
|
-}
|
|
-
|
|
-void tbase_cbuf_put(struct tbase_cbuf *cbuf)
|
|
-{
|
|
- kref_put(&cbuf->kref, cbuf_release);
|
|
-}
|
|
-
|
|
-uintptr_t tbase_cbuf_addr(struct tbase_cbuf *cbuf)
|
|
-{
|
|
- return cbuf->addr;
|
|
-}
|
|
-
|
|
-uintptr_t tbase_cbuf_uaddr(struct tbase_cbuf *cbuf)
|
|
-{
|
|
- return cbuf->uaddr;
|
|
-}
|
|
-
|
|
-uint32_t tbase_cbuf_len(struct tbase_cbuf *cbuf)
|
|
-{
|
|
- return cbuf->len;
|
|
-}
|
|
-
|
|
-static inline int cbuf_info(struct tbase_cbuf *cbuf, struct kasnprintf_buf *buf)
|
|
-{
|
|
- return kasnprintf(buf, "\tcbuf %p: addr %lx uaddr %lx len %u\n",
|
|
- cbuf, cbuf->addr, cbuf->uaddr, cbuf->len);
|
|
-}
|
|
diff --git a/drivers/gud/MobiCoreDriver/client.h b/drivers/gud/MobiCoreDriver/client.h
|
|
deleted file mode 100644
|
|
index 3cc833eeffb87..0000000000000
|
|
--- a/drivers/gud/MobiCoreDriver/client.h
|
|
+++ /dev/null
|
|
@@ -1,99 +0,0 @@
|
|
-/*
|
|
- * Copyright (c) 2013-2015 TRUSTONIC LIMITED
|
|
- * All Rights Reserved.
|
|
- *
|
|
- * This program is free software; you can redistribute it and/or
|
|
- * modify it under the terms of the GNU General Public License
|
|
- * version 2 as published by the Free Software Foundation.
|
|
- *
|
|
- * This program is distributed in the hope that it will be useful,
|
|
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
- * GNU General Public License for more details.
|
|
- */
|
|
-
|
|
-#ifndef _CLIENT_H_
|
|
-#define _CLIENT_H_
|
|
-
|
|
-#include <linux/list.h>
|
|
-#include <linux/sched.h> /* TASK_COMM_LEN */
|
|
-
|
|
-struct task_struct;
|
|
-struct tbase_object;
|
|
-struct tbase_session;
|
|
-
|
|
-struct tbase_client {
|
|
- /* PID of task that opened the device, 0 if kernel */
|
|
- pid_t pid;
|
|
- /* Command for task*/
|
|
- char comm[TASK_COMM_LEN];
|
|
- /* Number of references kept to this object */
|
|
- struct kref kref;
|
|
- /* List of contiguous buffers allocated by mcMallocWsm for the client */
|
|
- struct list_head cbufs;
|
|
- struct mutex cbufs_lock; /* lock for the cbufs list */
|
|
- /* List of tbase TA sessions opened by this client */
|
|
- struct list_head sessions;
|
|
- struct mutex sessions_lock; /* sessions list + closing */
|
|
- /* Client state */
|
|
- bool closing;
|
|
- /* The list entry to attach to "ctx.clients" list */
|
|
- struct list_head list;
|
|
-};
|
|
-
|
|
-struct tbase_client *client_create(bool is_from_kernel);
|
|
-
|
|
-void client_close_sessions(struct tbase_client *client);
|
|
-
|
|
-static inline void client_get(struct tbase_client *client)
|
|
-{
|
|
- kref_get(&client->kref);
|
|
-}
|
|
-
|
|
-void client_put(struct tbase_client *client);
|
|
-
|
|
-bool client_is_kernel(struct tbase_client *client);
|
|
-
|
|
-bool client_set_closing(struct tbase_client *client);
|
|
-
|
|
-int client_add_session(struct tbase_client *client,
|
|
- const struct tbase_object *obj, uintptr_t tci,
|
|
- size_t len, uint32_t *p_sid, bool is_gp_uuid,
|
|
- struct mc_identity *identity);
|
|
-
|
|
-int client_remove_session(struct tbase_client *client, uint32_t session_id);
|
|
-
|
|
-struct tbase_session *client_ref_session(struct tbase_client *client,
|
|
- uint32_t session_id);
|
|
-
|
|
-void client_unref_session(struct tbase_session *session);
|
|
-
|
|
-int client_info(struct tbase_client *client, struct kasnprintf_buf *buf);
|
|
-
|
|
-/*
|
|
- * Contiguous buffer allocated to TLCs.
|
|
- * These buffers are uses as world shared memory (wsm) and shared with
|
|
- * secure world.
|
|
- * The virtual kernel address is added for a simpler search algorithm.
|
|
- */
|
|
-struct tbase_cbuf;
|
|
-
|
|
-int tbase_cbuf_alloc(struct tbase_client *client, uint32_t len,
|
|
- uintptr_t *addr, struct vm_area_struct *vmarea);
|
|
-
|
|
-int tbase_cbuf_free(struct tbase_client *client, uintptr_t addr);
|
|
-
|
|
-struct tbase_cbuf *tbase_cbuf_get_by_addr(struct tbase_client *client,
|
|
- uintptr_t addr);
|
|
-
|
|
-void tbase_cbuf_get(struct tbase_cbuf *cbuf);
|
|
-
|
|
-void tbase_cbuf_put(struct tbase_cbuf *cbuf);
|
|
-
|
|
-uintptr_t tbase_cbuf_addr(struct tbase_cbuf *cbuf);
|
|
-
|
|
-uintptr_t tbase_cbuf_uaddr(struct tbase_cbuf *cbuf);
|
|
-
|
|
-uint32_t tbase_cbuf_len(struct tbase_cbuf *cbuf);
|
|
-
|
|
-#endif /* _CLIENT_H_ */
|
|
diff --git a/drivers/gud/MobiCoreDriver/clientlib.c b/drivers/gud/MobiCoreDriver/clientlib.c
|
|
deleted file mode 100644
|
|
index c7d6d023b3a80..0000000000000
|
|
--- a/drivers/gud/MobiCoreDriver/clientlib.c
|
|
+++ /dev/null
|
|
@@ -1,433 +0,0 @@
|
|
-/*
|
|
- * Copyright (c) 2013-2015 TRUSTONIC LIMITED
|
|
- * All Rights Reserved.
|
|
- *
|
|
- * This program is free software; you can redistribute it and/or
|
|
- * modify it under the terms of the GNU General Public License
|
|
- * version 2 as published by the Free Software Foundation.
|
|
- *
|
|
- * This program is distributed in the hope that it will be useful,
|
|
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
- * GNU General Public License for more details.
|
|
- */
|
|
-
|
|
-#include <linux/module.h>
|
|
-#include <linux/init.h>
|
|
-#include <linux/kernel.h>
|
|
-#include <linux/device.h>
|
|
-#include <linux/sched.h>
|
|
-#include <linux/list.h>
|
|
-
|
|
-#include "public/mc_linux.h"
|
|
-#include "public/mc_admin.h"
|
|
-#include "public/mobicore_driver_api.h"
|
|
-
|
|
-#include "main.h"
|
|
-#include "debug.h"
|
|
-#include "client.h"
|
|
-#include "session.h"
|
|
-#include "api.h"
|
|
-
|
|
-enum mc_result convert(int err)
|
|
-{
|
|
- switch (-err) {
|
|
- case 0:
|
|
- return MC_DRV_OK;
|
|
- case ENOMSG:
|
|
- return MC_DRV_NO_NOTIFICATION;
|
|
- case EBADMSG:
|
|
- return MC_DRV_ERR_NOTIFICATION;
|
|
- case EAGAIN:
|
|
- return MC_DRV_ERR_OUT_OF_RESOURCES;
|
|
- case EHOSTDOWN:
|
|
- return MC_DRV_ERR_INIT;
|
|
- case ENODEV:
|
|
- return MC_DRV_ERR_UNKNOWN_DEVICE;
|
|
- case ENXIO:
|
|
- return MC_DRV_ERR_UNKNOWN_SESSION;
|
|
- case EPERM:
|
|
- return MC_DRV_ERR_INVALID_OPERATION;
|
|
- case EBADE:
|
|
- return MC_DRV_ERR_INVALID_RESPONSE;
|
|
- case ETIME:
|
|
- return MC_DRV_ERR_TIMEOUT;
|
|
- case ENOMEM:
|
|
- return MC_DRV_ERR_NO_FREE_MEMORY;
|
|
- case EUCLEAN:
|
|
- return MC_DRV_ERR_FREE_MEMORY_FAILED;
|
|
- case ENOTEMPTY:
|
|
- return MC_DRV_ERR_SESSION_PENDING;
|
|
- case EHOSTUNREACH:
|
|
- return MC_DRV_ERR_DAEMON_UNREACHABLE;
|
|
- case ENOENT:
|
|
- return MC_DRV_ERR_INVALID_DEVICE_FILE;
|
|
- case EINVAL:
|
|
- return MC_DRV_ERR_INVALID_PARAMETER;
|
|
- case EPROTO:
|
|
- return MC_DRV_ERR_KERNEL_MODULE;
|
|
- case EADDRINUSE:
|
|
- return MC_DRV_ERR_BULK_MAPPING;
|
|
- case EADDRNOTAVAIL:
|
|
- return MC_DRV_ERR_BULK_UNMAPPING;
|
|
- case ECOMM:
|
|
- return MC_DRV_INFO_NOTIFICATION;
|
|
- case EUNATCH:
|
|
- return MC_DRV_ERR_NQ_FAILED;
|
|
- default:
|
|
- MCDRV_DBG("error is %d", err);
|
|
- return MC_DRV_ERR_UNKNOWN;
|
|
- }
|
|
-}
|
|
-
|
|
-static inline bool is_valid_device(uint32_t device_id)
|
|
-{
|
|
- return MC_DEVICE_ID_DEFAULT == device_id;
|
|
-}
|
|
-
|
|
-static struct tbase_client *client;
|
|
-static int open_count;
|
|
-static DEFINE_MUTEX(dev_mutex); /* Lock for the device */
|
|
-
|
|
-static bool clientlib_client_get(void)
|
|
-{
|
|
- int ret = true;
|
|
-
|
|
- mutex_lock(&dev_mutex);
|
|
- if (!client)
|
|
- ret = false;
|
|
- else
|
|
- client_get(client);
|
|
-
|
|
- mutex_unlock(&dev_mutex);
|
|
- return ret;
|
|
-}
|
|
-
|
|
-static void clientlib_client_put(void)
|
|
-{
|
|
- mutex_lock(&dev_mutex);
|
|
- client_put(client);
|
|
- mutex_unlock(&dev_mutex);
|
|
-}
|
|
-
|
|
-enum mc_result mc_open_device(uint32_t device_id)
|
|
-{
|
|
- enum mc_result mc_result = MC_DRV_OK;
|
|
-
|
|
- /* Check parameters */
|
|
- if (!is_valid_device(device_id))
|
|
- return MC_DRV_ERR_UNKNOWN_DEVICE;
|
|
-
|
|
- mutex_lock(&dev_mutex);
|
|
- if (!open_count)
|
|
- client = api_open_device(true);
|
|
-
|
|
- if (client) {
|
|
- open_count++;
|
|
- MCDRV_DBG("Successfully opened the device.");
|
|
- } else {
|
|
- mc_result = MC_DRV_ERR_INVALID_DEVICE_FILE;
|
|
- MCDRV_DBG("Could not open device");
|
|
- }
|
|
-
|
|
- mutex_unlock(&dev_mutex);
|
|
- return mc_result;
|
|
-}
|
|
-EXPORT_SYMBOL(mc_open_device);
|
|
-
|
|
-enum mc_result mc_close_device(uint32_t device_id)
|
|
-{
|
|
- enum mc_result mc_result = MC_DRV_OK;
|
|
-
|
|
- /* Check parameters */
|
|
- if (!is_valid_device(device_id))
|
|
- return MC_DRV_ERR_UNKNOWN_DEVICE;
|
|
-
|
|
- mutex_lock(&dev_mutex);
|
|
- if (!client) {
|
|
- mc_result = MC_DRV_ERR_DAEMON_DEVICE_NOT_OPEN;
|
|
- goto end;
|
|
- }
|
|
-
|
|
- if (open_count > 1) {
|
|
- open_count--;
|
|
- goto end;
|
|
- }
|
|
-
|
|
- /* Check sessions and freeze client */
|
|
- mc_result = convert(api_freeze_device(client));
|
|
- if (MC_DRV_OK != mc_result)
|
|
- goto end;
|
|
-
|
|
- /* Close the device */
|
|
- api_close_device(client);
|
|
- client = NULL;
|
|
- open_count = 0;
|
|
-
|
|
-end:
|
|
- mutex_unlock(&dev_mutex);
|
|
- return mc_result;
|
|
-}
|
|
-EXPORT_SYMBOL(mc_close_device);
|
|
-
|
|
-enum mc_result mc_open_session(struct mc_session_handle *session,
|
|
- const struct mc_uuid_t *uuid,
|
|
- uint8_t *tci, uint32_t len)
|
|
-{
|
|
- struct mc_identity identity = {
|
|
- .login_type = TEEC_LOGIN_PUBLIC,
|
|
- };
|
|
- enum mc_result ret;
|
|
-
|
|
- /* Check parameters */
|
|
- if (!session)
|
|
- return MC_DRV_ERR_INVALID_PARAMETER;
|
|
-
|
|
- if (!is_valid_device(session->device_id))
|
|
- return MC_DRV_ERR_UNKNOWN_DEVICE;
|
|
-
|
|
- if (!clientlib_client_get())
|
|
- return MC_DRV_ERR_DAEMON_DEVICE_NOT_OPEN;
|
|
-
|
|
- /* Call core api */
|
|
- ret = convert(api_open_session(client, &session->session_id, uuid,
|
|
- (uintptr_t)tci, len, false, &identity));
|
|
- clientlib_client_put();
|
|
- return ret;
|
|
-}
|
|
-EXPORT_SYMBOL(mc_open_session);
|
|
-
|
|
-enum mc_result mc_open_trustlet(struct mc_session_handle *session,
|
|
- uint32_t spid,
|
|
- uint8_t *trustlet, uint32_t trustlet_len,
|
|
- uint8_t *tci, uint32_t len)
|
|
-{
|
|
- enum mc_result ret;
|
|
-
|
|
- /* Check parameters */
|
|
- if (!session)
|
|
- return MC_DRV_ERR_INVALID_PARAMETER;
|
|
-
|
|
- if (!is_valid_device(session->device_id))
|
|
- return MC_DRV_ERR_UNKNOWN_DEVICE;
|
|
-
|
|
- if (!clientlib_client_get())
|
|
- return MC_DRV_ERR_DAEMON_DEVICE_NOT_OPEN;
|
|
-
|
|
- /* Call core api */
|
|
- ret = convert(api_open_trustlet(client, &session->session_id, spid,
|
|
- (uintptr_t)trustlet, trustlet_len,
|
|
- (uintptr_t)tci, len));
|
|
- clientlib_client_put();
|
|
- return ret;
|
|
-}
|
|
-EXPORT_SYMBOL(mc_open_trustlet);
|
|
-
|
|
-enum mc_result mc_close_session(struct mc_session_handle *session)
|
|
-{
|
|
- enum mc_result ret;
|
|
-
|
|
- /* Check parameters */
|
|
- if (!session)
|
|
- return MC_DRV_ERR_INVALID_PARAMETER;
|
|
-
|
|
- if (!is_valid_device(session->device_id))
|
|
- return MC_DRV_ERR_UNKNOWN_DEVICE;
|
|
-
|
|
- if (!clientlib_client_get())
|
|
- return MC_DRV_ERR_DAEMON_DEVICE_NOT_OPEN;
|
|
-
|
|
- /* Call core api */
|
|
- ret = convert(api_close_session(client, session->session_id));
|
|
- clientlib_client_put();
|
|
- return ret;
|
|
-}
|
|
-EXPORT_SYMBOL(mc_close_session);
|
|
-
|
|
-enum mc_result mc_notify(struct mc_session_handle *session)
|
|
-{
|
|
- enum mc_result ret;
|
|
-
|
|
- /* Check parameters */
|
|
- if (!session)
|
|
- return MC_DRV_ERR_INVALID_PARAMETER;
|
|
-
|
|
- if (!is_valid_device(session->device_id))
|
|
- return MC_DRV_ERR_UNKNOWN_DEVICE;
|
|
-
|
|
- if (!clientlib_client_get())
|
|
- return MC_DRV_ERR_DAEMON_DEVICE_NOT_OPEN;
|
|
-
|
|
- /* Call core api */
|
|
- ret = convert(api_notify(client, session->session_id));
|
|
- clientlib_client_put();
|
|
- return ret;
|
|
-}
|
|
-EXPORT_SYMBOL(mc_notify);
|
|
-
|
|
-enum mc_result mc_wait_notification(struct mc_session_handle *session,
|
|
- int32_t timeout)
|
|
-{
|
|
- enum mc_result ret;
|
|
-
|
|
- /* Check parameters */
|
|
- if (!session)
|
|
- return MC_DRV_ERR_INVALID_PARAMETER;
|
|
-
|
|
- if (!is_valid_device(session->device_id))
|
|
- return MC_DRV_ERR_UNKNOWN_DEVICE;
|
|
-
|
|
- if (!clientlib_client_get())
|
|
- return MC_DRV_ERR_DAEMON_DEVICE_NOT_OPEN;
|
|
-
|
|
- /* Call core api */
|
|
- ret = convert(api_wait_notification(client, session->session_id,
|
|
- timeout));
|
|
- clientlib_client_put();
|
|
- return ret;
|
|
-}
|
|
-EXPORT_SYMBOL(mc_wait_notification);
|
|
-
|
|
-enum mc_result mc_malloc_wsm(uint32_t device_id, uint32_t align, uint32_t len,
|
|
- uint8_t **wsm, uint32_t wsm_flags)
|
|
-{
|
|
- enum mc_result ret;
|
|
- uintptr_t va;
|
|
-
|
|
- /* Check parameters */
|
|
- if (!is_valid_device(device_id))
|
|
- return MC_DRV_ERR_UNKNOWN_DEVICE;
|
|
-
|
|
- if (!len)
|
|
- return MC_DRV_ERR_INVALID_PARAMETER;
|
|
-
|
|
- if (!wsm)
|
|
- return MC_DRV_ERR_INVALID_PARAMETER;
|
|
-
|
|
- if (!clientlib_client_get())
|
|
- return MC_DRV_ERR_DAEMON_DEVICE_NOT_OPEN;
|
|
-
|
|
- /* Call core api */
|
|
- ret = convert(api_malloc_cbuf(client, len, &va, NULL));
|
|
- if (ret == MC_DRV_OK)
|
|
- *wsm = (uint8_t *)va;
|
|
-
|
|
- clientlib_client_put();
|
|
- return ret;
|
|
-}
|
|
-EXPORT_SYMBOL(mc_malloc_wsm);
|
|
-
|
|
-enum mc_result mc_free_wsm(uint32_t device_id, uint8_t *wsm)
|
|
-{
|
|
- enum mc_result ret;
|
|
- uintptr_t va = (uintptr_t)wsm;
|
|
-
|
|
- /* Check parameters */
|
|
- if (!is_valid_device(device_id))
|
|
- return MC_DRV_ERR_UNKNOWN_DEVICE;
|
|
-
|
|
- if (!clientlib_client_get())
|
|
- return MC_DRV_ERR_DAEMON_DEVICE_NOT_OPEN;
|
|
-
|
|
- /* Call core api */
|
|
- ret = convert(api_free_cbuf(client, va));
|
|
- clientlib_client_put();
|
|
- return ret;
|
|
-}
|
|
-EXPORT_SYMBOL(mc_free_wsm);
|
|
-
|
|
-enum mc_result mc_map(struct mc_session_handle *session, void *address,
|
|
- uint32_t length, struct mc_bulk_map *map_info)
|
|
-{
|
|
- enum mc_result ret;
|
|
- struct mc_ioctl_buffer bufs[MC_MAP_MAX];
|
|
- uint32_t i;
|
|
-
|
|
- /* Check parameters */
|
|
- if (!session)
|
|
- return MC_DRV_ERR_INVALID_PARAMETER;
|
|
-
|
|
- if (!is_valid_device(session->device_id))
|
|
- return MC_DRV_ERR_UNKNOWN_DEVICE;
|
|
-
|
|
- if (!map_info)
|
|
- return MC_DRV_ERR_INVALID_PARAMETER;
|
|
-
|
|
- if (!clientlib_client_get())
|
|
- return MC_DRV_ERR_DAEMON_DEVICE_NOT_OPEN;
|
|
-
|
|
- /* Call core api */
|
|
- bufs[0].va = (uintptr_t)address;
|
|
- bufs[0].len = length;
|
|
- for (i = 1; i < MC_MAP_MAX; i++)
|
|
- bufs[i].va = 0;
|
|
-
|
|
- ret = convert(api_map_wsms(client, session->session_id, bufs));
|
|
- if (ret == MC_DRV_OK) {
|
|
- map_info->secure_virt_addr = bufs[0].sva;
|
|
- map_info->secure_virt_len = bufs[0].len;
|
|
- }
|
|
-
|
|
- clientlib_client_put();
|
|
- return ret;
|
|
-}
|
|
-EXPORT_SYMBOL(mc_map);
|
|
-
|
|
-enum mc_result mc_unmap(struct mc_session_handle *session, void *address,
|
|
- struct mc_bulk_map *map_info)
|
|
-{
|
|
- enum mc_result ret;
|
|
- struct mc_ioctl_buffer bufs[MC_MAP_MAX];
|
|
- uint32_t i;
|
|
-
|
|
- /* Check parameters */
|
|
- if (!session)
|
|
- return MC_DRV_ERR_INVALID_PARAMETER;
|
|
-
|
|
- if (!is_valid_device(session->device_id))
|
|
- return MC_DRV_ERR_UNKNOWN_DEVICE;
|
|
-
|
|
- if (!map_info)
|
|
- return MC_DRV_ERR_INVALID_PARAMETER;
|
|
-
|
|
- if (!clientlib_client_get())
|
|
- return MC_DRV_ERR_DAEMON_DEVICE_NOT_OPEN;
|
|
-
|
|
- /* Call core api */
|
|
- bufs[0].va = (uintptr_t)address;
|
|
- bufs[0].len = map_info->secure_virt_len;
|
|
- bufs[0].sva = map_info->secure_virt_addr;
|
|
- for (i = 1; i < MC_MAP_MAX; i++)
|
|
- bufs[i].va = 0;
|
|
-
|
|
- ret = convert(api_unmap_wsms(client, session->session_id, bufs));
|
|
- clientlib_client_put();
|
|
- return ret;
|
|
-}
|
|
-EXPORT_SYMBOL(mc_unmap);
|
|
-
|
|
-enum mc_result mc_get_session_error_code(struct mc_session_handle *session,
|
|
- int32_t *exit_code)
|
|
-{
|
|
- enum mc_result ret;
|
|
-
|
|
- /* Check parameters */
|
|
- if (!session)
|
|
- return MC_DRV_ERR_INVALID_PARAMETER;
|
|
-
|
|
- if (!is_valid_device(session->device_id))
|
|
- return MC_DRV_ERR_UNKNOWN_DEVICE;
|
|
-
|
|
- if (!exit_code)
|
|
- return MC_DRV_ERR_INVALID_PARAMETER;
|
|
-
|
|
- if (!clientlib_client_get())
|
|
- return MC_DRV_ERR_DAEMON_DEVICE_NOT_OPEN;
|
|
-
|
|
- /* Call core api */
|
|
- ret = convert(api_get_session_exitcode(client, session->session_id,
|
|
- exit_code));
|
|
- clientlib_client_put();
|
|
- return ret;
|
|
-}
|
|
-EXPORT_SYMBOL(mc_get_session_error_code);
|
|
diff --git a/drivers/gud/MobiCoreDriver/clock.c b/drivers/gud/MobiCoreDriver/clock.c
|
|
deleted file mode 100644
|
|
index 0195ab794f205..0000000000000
|
|
--- a/drivers/gud/MobiCoreDriver/clock.c
|
|
+++ /dev/null
|
|
@@ -1,161 +0,0 @@
|
|
-/*
|
|
- * Copyright (c) 2013-2015 TRUSTONIC LIMITED
|
|
- * All Rights Reserved.
|
|
- *
|
|
- * This program is free software; you can redistribute it and/or
|
|
- * modify it under the terms of the GNU General Public License
|
|
- * version 2 as published by the Free Software Foundation.
|
|
- *
|
|
- * This program is distributed in the hope that it will be useful,
|
|
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
- * GNU General Public License for more details.
|
|
- */
|
|
-
|
|
-#include "platform.h"
|
|
-
|
|
-#ifdef MC_CRYPTO_CLOCK_MANAGEMENT
|
|
-
|
|
-#include <linux/device.h>
|
|
-#include <linux/clk.h>
|
|
-#include <linux/err.h>
|
|
-#include <linux/of.h>
|
|
-
|
|
-#include "debug.h"
|
|
-#include "clock.h"
|
|
-
|
|
-static struct clk_context {
|
|
- struct clk *mc_ce_iface_clk;
|
|
- struct clk *mc_ce_core_clk;
|
|
- struct clk *mc_ce_bus_clk;
|
|
- struct clk *mc_ce_core_src_clk;
|
|
-} clk_ctx;
|
|
-
|
|
-int mc_clock_init(void)
|
|
-{
|
|
- int ret = 0;
|
|
-#ifdef MC_CLOCK_CORESRC_DEFAULTRATE
|
|
- int core_src_rate = MC_CLOCK_CORESRC_DEFAULTRATE;
|
|
-
|
|
- /* Get core clk src */
|
|
- clk_ctx.mc_ce_core_src_clk = clk_get(g_ctx.mcd, "core_clk_src");
|
|
- if (IS_ERR(clk_ctx.mc_ce_core_src_clk)) {
|
|
- ret = PTR_ERR(clk_ctx.mc_ce_core_src_clk);
|
|
- MCDRV_ERROR("cannot get core src clock: %d", ret);
|
|
- goto error;
|
|
- }
|
|
-
|
|
-#ifdef MC_CRYPTO_CLOCK_CORESRC_PROPNAME
|
|
- if (of_property_read_u32(g_ctx.mcd->of_node,
|
|
- MC_CRYPTO_CLOCK_CORESRC_PROPNAME,
|
|
- &core_src_rate)) {
|
|
- core_src_rate = MC_CLOCK_CORESRC_DEFAULTRATE;
|
|
- MCDRV_ERROR("cannot get ce clock frequency from DT, use %d",
|
|
- core_src_rate);
|
|
- }
|
|
-#endif /* MC_CRYPTO_CLOCK_CORESRC_PROPNAME */
|
|
-
|
|
- ret = clk_set_rate(clk_ctx.mc_ce_core_src_clk, core_src_rate);
|
|
- if (ret) {
|
|
- clk_put(clk_ctx.mc_ce_core_src_clk);
|
|
- clk_ctx.mc_ce_core_src_clk = NULL;
|
|
- MCDRV_ERROR("cannot set core clock src rate: %d", ret);
|
|
- ret = -EIO;
|
|
- goto error;
|
|
- }
|
|
-#endif /* MC_CLOCK_CORESRC_DEFAULTRATE */
|
|
-
|
|
- /* Get core clk */
|
|
- clk_ctx.mc_ce_core_clk = clk_get(g_ctx.mcd, "core_clk");
|
|
- if (IS_ERR(clk_ctx.mc_ce_core_clk)) {
|
|
- ret = PTR_ERR(clk_ctx.mc_ce_core_clk);
|
|
- MCDRV_ERROR("cannot get core clock: %d", ret);
|
|
- goto error;
|
|
- }
|
|
- /* Get Interface clk */
|
|
- clk_ctx.mc_ce_iface_clk = clk_get(g_ctx.mcd, "iface_clk");
|
|
- if (IS_ERR(clk_ctx.mc_ce_iface_clk)) {
|
|
- clk_put(clk_ctx.mc_ce_core_clk);
|
|
- ret = PTR_ERR(clk_ctx.mc_ce_iface_clk);
|
|
- MCDRV_ERROR("cannot get iface clock: %d", ret);
|
|
- goto error;
|
|
- }
|
|
- /* Get AXI clk */
|
|
- clk_ctx.mc_ce_bus_clk = clk_get(g_ctx.mcd, "bus_clk");
|
|
- if (IS_ERR(clk_ctx.mc_ce_bus_clk)) {
|
|
- clk_put(clk_ctx.mc_ce_iface_clk);
|
|
- clk_put(clk_ctx.mc_ce_core_clk);
|
|
- ret = PTR_ERR(clk_ctx.mc_ce_bus_clk);
|
|
- MCDRV_ERROR("cannot get AXI bus clock: %d", ret);
|
|
- goto error;
|
|
- }
|
|
- return ret;
|
|
-
|
|
-error:
|
|
- clk_ctx.mc_ce_core_clk = NULL;
|
|
- clk_ctx.mc_ce_iface_clk = NULL;
|
|
- clk_ctx.mc_ce_bus_clk = NULL;
|
|
- clk_ctx.mc_ce_core_src_clk = NULL;
|
|
- return ret;
|
|
-}
|
|
-
|
|
-void mc_clock_exit(void)
|
|
-{
|
|
- if (clk_ctx.mc_ce_iface_clk)
|
|
- clk_put(clk_ctx.mc_ce_iface_clk);
|
|
-
|
|
- if (clk_ctx.mc_ce_core_clk)
|
|
- clk_put(clk_ctx.mc_ce_core_clk);
|
|
-
|
|
- if (clk_ctx.mc_ce_bus_clk)
|
|
- clk_put(clk_ctx.mc_ce_bus_clk);
|
|
-
|
|
- if (clk_ctx.mc_ce_core_src_clk)
|
|
- clk_put(clk_ctx.mc_ce_core_src_clk);
|
|
-}
|
|
-
|
|
-int mc_clock_enable(void)
|
|
-{
|
|
- int rc;
|
|
-
|
|
- rc = clk_prepare_enable(clk_ctx.mc_ce_core_clk);
|
|
- if (rc) {
|
|
- MCDRV_ERROR("cannot enable core clock");
|
|
- goto err_core;
|
|
- }
|
|
-
|
|
- rc = clk_prepare_enable(clk_ctx.mc_ce_iface_clk);
|
|
- if (rc) {
|
|
- MCDRV_ERROR("cannot enable interface clock");
|
|
- goto err_iface;
|
|
- }
|
|
-
|
|
- rc = clk_prepare_enable(clk_ctx.mc_ce_bus_clk);
|
|
- if (rc) {
|
|
- MCDRV_ERROR("cannot enable bus clock");
|
|
- goto err_bus;
|
|
- }
|
|
-
|
|
- return 0;
|
|
-
|
|
-err_bus:
|
|
- clk_disable_unprepare(clk_ctx.mc_ce_iface_clk);
|
|
-err_iface:
|
|
- clk_disable_unprepare(clk_ctx.mc_ce_core_clk);
|
|
-err_core:
|
|
- return rc;
|
|
-}
|
|
-
|
|
-void mc_clock_disable(void)
|
|
-{
|
|
- if (clk_ctx.mc_ce_iface_clk)
|
|
- clk_disable_unprepare(clk_ctx.mc_ce_iface_clk);
|
|
-
|
|
- if (clk_ctx.mc_ce_core_clk)
|
|
- clk_disable_unprepare(clk_ctx.mc_ce_core_clk);
|
|
-
|
|
- if (clk_ctx.mc_ce_bus_clk)
|
|
- clk_disable_unprepare(clk_ctx.mc_ce_bus_clk);
|
|
-}
|
|
-
|
|
-#endif /* MC_CRYPTO_CLOCK_MANAGEMENT */
|
|
diff --git a/drivers/gud/MobiCoreDriver/clock.h b/drivers/gud/MobiCoreDriver/clock.h
|
|
deleted file mode 100644
|
|
index 21095499efb53..0000000000000
|
|
--- a/drivers/gud/MobiCoreDriver/clock.h
|
|
+++ /dev/null
|
|
@@ -1,53 +0,0 @@
|
|
-/*
|
|
- * Copyright (c) 2013-2015 TRUSTONIC LIMITED
|
|
- * All Rights Reserved.
|
|
- *
|
|
- * This program is free software; you can redistribute it and/or
|
|
- * modify it under the terms of the GNU General Public License
|
|
- * version 2 as published by the Free Software Foundation.
|
|
- *
|
|
- * This program is distributed in the hope that it will be useful,
|
|
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
- * GNU General Public License for more details.
|
|
- */
|
|
-
|
|
-#ifndef _MC_CLOCK_H_
|
|
-#define _MC_CLOCK_H_
|
|
-
|
|
-#include "platform.h" /* MC_CRYPTO_CLOCK_MANAGEMENT */
|
|
-
|
|
-#ifdef MC_CRYPTO_CLOCK_MANAGEMENT
|
|
-
|
|
-/* Initialize secure crypto clocks */
|
|
-int mc_clock_init(void);
|
|
-/* Free secure crypto clocks */
|
|
-void mc_clock_exit(void);
|
|
-/* Enable secure crypto clocks */
|
|
-int mc_clock_enable(void);
|
|
-/* Disable secure crypto clocks */
|
|
-void mc_clock_disable(void);
|
|
-
|
|
-#else /* MC_CRYPTO_CLOCK_MANAGEMENT */
|
|
-
|
|
-static inline int mc_clock_init(void)
|
|
-{
|
|
- return 0;
|
|
-}
|
|
-
|
|
-static inline void mc_clock_exit(void)
|
|
-{
|
|
-}
|
|
-
|
|
-static inline int mc_clock_enable(void)
|
|
-{
|
|
- return 0;
|
|
-}
|
|
-
|
|
-static inline void mc_clock_disable(void)
|
|
-{
|
|
-}
|
|
-
|
|
-#endif /* !MC_CRYPTO_CLOCK_MANAGEMENT */
|
|
-
|
|
-#endif /* _MC_CLOCK_H_ */
|
|
diff --git a/drivers/gud/MobiCoreDriver/debug.h b/drivers/gud/MobiCoreDriver/debug.h
|
|
deleted file mode 100644
|
|
index 9d6a52ab955b6..0000000000000
|
|
--- a/drivers/gud/MobiCoreDriver/debug.h
|
|
+++ /dev/null
|
|
@@ -1,63 +0,0 @@
|
|
-/*
|
|
- * Copyright (c) 2013-2015 TRUSTONIC LIMITED
|
|
- * All Rights Reserved.
|
|
- *
|
|
- * This program is free software; you can redistribute it and/or
|
|
- * modify it under the terms of the GNU General Public License
|
|
- * version 2 as published by the Free Software Foundation.
|
|
- *
|
|
- * This program is distributed in the hope that it will be useful,
|
|
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
- * GNU General Public License for more details.
|
|
- */
|
|
-#ifndef _MC_DEBUG_H_
|
|
-#define _MC_DEBUG_H_
|
|
-
|
|
-#include "main.h" /* g_ctx */
|
|
-
|
|
-#define MCDRV_ERROR(txt, ...) \
|
|
- dev_err(g_ctx.mcd, "%s() ### ERROR: " txt "\n", \
|
|
- __func__, \
|
|
- ##__VA_ARGS__)
|
|
-
|
|
-/* dummy function helper macro. */
|
|
-#define DUMMY_FUNCTION() do {} while (0)
|
|
-
|
|
-#ifdef DEBUG
|
|
-
|
|
-#ifdef DEBUG_VERBOSE
|
|
-#define MCDRV_DBG_VERBOSE MCDRV_DBG
|
|
-#else
|
|
-#define MCDRV_DBG_VERBOSE(...) DUMMY_FUNCTION()
|
|
-#endif
|
|
-
|
|
-#define MCDRV_DBG(txt, ...) \
|
|
- dev_info(g_ctx.mcd, "%s(): " txt "\n", \
|
|
- __func__, \
|
|
- ##__VA_ARGS__)
|
|
-
|
|
-#define MCDRV_DBG_WARN(txt, ...) \
|
|
- dev_warn(g_ctx.mcd, "%s() WARNING: " txt "\n", \
|
|
- __func__, \
|
|
- ##__VA_ARGS__)
|
|
-
|
|
-#define MCDRV_ASSERT(cond) \
|
|
- do { \
|
|
- if (unlikely(!(cond))) { \
|
|
- panic("Assertion failed: %s:%d\n", \
|
|
- __FILE__, __LINE__); \
|
|
- } \
|
|
- } while (0)
|
|
-
|
|
-#else /* DEBUG */
|
|
-
|
|
-#define MCDRV_DBG_VERBOSE(...) DUMMY_FUNCTION()
|
|
-#define MCDRV_DBG(...) DUMMY_FUNCTION()
|
|
-#define MCDRV_DBG_WARN(...) DUMMY_FUNCTION()
|
|
-
|
|
-#define MCDRV_ASSERT(...) DUMMY_FUNCTION()
|
|
-
|
|
-#endif /* !DEBUG */
|
|
-
|
|
-#endif /* _MC_DEBUG_H_ */
|
|
diff --git a/drivers/gud/MobiCoreDriver/fastcall.c b/drivers/gud/MobiCoreDriver/fastcall.c
|
|
deleted file mode 100644
|
|
index ee612632331c8..0000000000000
|
|
--- a/drivers/gud/MobiCoreDriver/fastcall.c
|
|
+++ /dev/null
|
|
@@ -1,512 +0,0 @@
|
|
-/*
|
|
- * Copyright (c) 2013-2015 TRUSTONIC LIMITED
|
|
- * All Rights Reserved.
|
|
- *
|
|
- * This program is free software; you can redistribute it and/or
|
|
- * modify it under the terms of the GNU General Public License
|
|
- * version 2 as published by the Free Software Foundation.
|
|
- *
|
|
- * This program is distributed in the hope that it will be useful,
|
|
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
- * GNU General Public License for more details.
|
|
- */
|
|
-#include <linux/kthread.h>
|
|
-#include <linux/module.h>
|
|
-#include <linux/device.h>
|
|
-#include <linux/workqueue.h>
|
|
-#include <linux/cpu.h>
|
|
-#include <linux/moduleparam.h>
|
|
-
|
|
-#include "public/mc_linux.h"
|
|
-#include "public/mc_linux_api.h"
|
|
-
|
|
-#include "mci/mcifc.h"
|
|
-
|
|
-#include "platform.h" /* MC_FASTCALL_WORKER_THREAD and more */
|
|
-#include "debug.h"
|
|
-#include "clock.h" /* mc_clock_enable, mc_clock_disable */
|
|
-#include "fastcall.h"
|
|
-
|
|
-struct fastcall_work {
|
|
-#ifdef MC_FASTCALL_WORKER_THREAD
|
|
- struct kthread_work work;
|
|
-#else
|
|
- struct work_struct work;
|
|
-#endif
|
|
- void *data;
|
|
-};
|
|
-
|
|
-/* generic fast call parameters */
|
|
-union mc_fc_generic {
|
|
- struct {
|
|
- uint32_t cmd;
|
|
- uint32_t param[3];
|
|
- } as_in;
|
|
- struct {
|
|
- uint32_t resp;
|
|
- uint32_t ret;
|
|
- uint32_t param[2];
|
|
- } as_out;
|
|
-};
|
|
-
|
|
-/* fast call init */
|
|
-union mc_fc_init {
|
|
- union mc_fc_generic as_generic;
|
|
- struct {
|
|
- uint32_t cmd;
|
|
- uint32_t base;
|
|
- uint32_t nq_info;
|
|
- uint32_t mcp_info;
|
|
- } as_in;
|
|
- struct {
|
|
- uint32_t resp;
|
|
- uint32_t ret;
|
|
- uint32_t rfu[2];
|
|
- } as_out;
|
|
-};
|
|
-
|
|
-/* fast call info parameters */
|
|
-union mc_fc_info {
|
|
- union mc_fc_generic as_generic;
|
|
- struct {
|
|
- uint32_t cmd;
|
|
- uint32_t ext_info_id;
|
|
- uint32_t rfu[2];
|
|
- } as_in;
|
|
- struct {
|
|
- uint32_t resp;
|
|
- uint32_t ret;
|
|
- uint32_t state;
|
|
- uint32_t ext_info;
|
|
- } as_out;
|
|
-};
|
|
-
|
|
-#ifdef TBASE_CORE_SWITCHER
|
|
-/* fast call switch Core parameters */
|
|
-union mc_fc_swich_core {
|
|
- union mc_fc_generic as_generic;
|
|
- struct {
|
|
- uint32_t cmd;
|
|
- uint32_t core_id;
|
|
- uint32_t rfu[2];
|
|
- } as_in;
|
|
- struct {
|
|
- uint32_t resp;
|
|
- uint32_t ret;
|
|
- uint32_t state;
|
|
- uint32_t ext_info;
|
|
- } as_out;
|
|
-};
|
|
-#endif
|
|
-
|
|
-#ifdef MC_FASTCALL_WORKER_THREAD
|
|
-static struct task_struct *fastcall_thread;
|
|
-static DEFINE_KTHREAD_WORKER(fastcall_worker);
|
|
-#endif
|
|
-
|
|
-/*
|
|
- * _smc() - fast call to MobiCore
|
|
- *
|
|
- * @data: pointer to fast call data
|
|
- */
|
|
-static inline int _smc(union mc_fc_generic *mc_fc_generic)
|
|
-{
|
|
- if (!mc_fc_generic)
|
|
- return -EINVAL;
|
|
-
|
|
-#ifdef MC_SMC_FASTCALL
|
|
- return smc_fastcall(mc_fc_generic, sizeof(*mc_fc_generic));
|
|
-#else /* MC_SMC_FASTCALL */
|
|
- {
|
|
-#ifdef CONFIG_ARM64
|
|
- /* SMC expect values in x0-x3 */
|
|
- register u64 reg0 __asm__("x0") = mc_fc_generic->as_in.cmd;
|
|
- register u64 reg1 __asm__("x1") = mc_fc_generic->as_in.param[0];
|
|
- register u64 reg2 __asm__("x2") = mc_fc_generic->as_in.param[1];
|
|
- register u64 reg3 __asm__("x3") = mc_fc_generic->as_in.param[2];
|
|
-
|
|
- /*
|
|
- * According to AARCH64 SMC Calling Convention (ARM DEN 0028A),
|
|
- * section 3.1: registers x4-x17 are unpredictable/scratch
|
|
- * registers. So we have to make sure that the compiler does
|
|
- * not allocate any of those registers by letting him know that
|
|
- * the asm code might clobber them.
|
|
- */
|
|
- __asm__ volatile (
|
|
- "smc #0\n"
|
|
- : "+r"(reg0), "+r"(reg1), "+r"(reg2), "+r"(reg3)
|
|
- :
|
|
- : "x4", "x5", "x6", "x7", "x8", "x9", "x10", "x11",
|
|
- "x12", "x13", "x14", "x15", "x16", "x17"
|
|
- );
|
|
-#else /* CONFIG_ARM64 */
|
|
- /* SMC expect values in r0-r3 */
|
|
- register u32 reg0 __asm__("r0") = mc_fc_generic->as_in.cmd;
|
|
- register u32 reg1 __asm__("r1") = mc_fc_generic->as_in.param[0];
|
|
- register u32 reg2 __asm__("r2") = mc_fc_generic->as_in.param[1];
|
|
- register u32 reg3 __asm__("r3") = mc_fc_generic->as_in.param[2];
|
|
-
|
|
- __asm__ volatile (
|
|
-#ifdef MC_ARCH_EXTENSION_SEC
|
|
- /* This pseudo op is supported and required from
|
|
- * binutils 2.21 on */
|
|
- ".arch_extension sec\n"
|
|
-#endif /* MC_ARCH_EXTENSION_SEC */
|
|
- "smc #0\n"
|
|
- : "+r"(reg0), "+r"(reg1), "+r"(reg2), "+r"(reg3)
|
|
- );
|
|
-
|
|
-#ifdef __ARM_VE_A9X4_QEMU__
|
|
- /* Qemu does not return to the address following the SMC
|
|
- * instruction so we have to insert several nop instructions to
|
|
- * workaround this Qemu bug. */
|
|
- __asm__ volatile (
|
|
- "nop\n"
|
|
- "nop\n"
|
|
- "nop\n"
|
|
- "nop"
|
|
- );
|
|
-#endif /* __ARM_VE_A9X4_QEMU__ */
|
|
-#endif /* !CONFIG_ARM64 */
|
|
-
|
|
- /* set response */
|
|
- mc_fc_generic->as_out.resp = reg0;
|
|
- mc_fc_generic->as_out.ret = reg1;
|
|
- mc_fc_generic->as_out.param[0] = reg2;
|
|
- mc_fc_generic->as_out.param[1] = reg3;
|
|
- }
|
|
- return 0;
|
|
-#endif /* !MC_SMC_FASTCALL */
|
|
-}
|
|
-
|
|
-#ifdef TBASE_CORE_SWITCHER
|
|
-static uint32_t active_cpu;
|
|
-
|
|
-#ifdef MC_FASTCALL_WORKER_THREAD
|
|
-static void mc_cpu_offline(int cpu)
|
|
-{
|
|
- int i;
|
|
-
|
|
- if (active_cpu != cpu) {
|
|
- MCDRV_DBG("not active CPU, no action taken\n");
|
|
- return;
|
|
- }
|
|
-
|
|
- /* Chose the first online CPU and switch! */
|
|
- for_each_online_cpu(i) {
|
|
- if (cpu != i) {
|
|
- MCDRV_DBG("CPU %d is dying, switching to %d\n", cpu, i);
|
|
- mc_switch_core(i);
|
|
- break;
|
|
- }
|
|
-
|
|
- MCDRV_DBG("Skipping CPU %d\n", cpu);
|
|
- }
|
|
-}
|
|
-
|
|
-static int mobicore_cpu_callback(struct notifier_block *nfb,
|
|
- unsigned long action, void *hcpu)
|
|
-{
|
|
- unsigned int cpu = (unsigned long)hcpu;
|
|
-
|
|
- switch (action) {
|
|
- case CPU_DOWN_PREPARE:
|
|
- case CPU_DOWN_PREPARE_FROZEN:
|
|
- dev_info(g_ctx.mcd, "Cpu %u is going to die\n", cpu);
|
|
- mc_cpu_offline(cpu);
|
|
- break;
|
|
- case CPU_DEAD:
|
|
- case CPU_DEAD_FROZEN:
|
|
- dev_info(g_ctx.mcd, "Cpu %u is dead\n", cpu);
|
|
- break;
|
|
- }
|
|
- return NOTIFY_OK;
|
|
-}
|
|
-
|
|
-static struct notifier_block mobicore_cpu_notifer = {
|
|
- .notifier_call = mobicore_cpu_callback,
|
|
-};
|
|
-#endif /* MC_FASTCALL_WORKER_THREAD */
|
|
-
|
|
-static cpumask_t mc_exec_core_switch(union mc_fc_generic *mc_fc_generic)
|
|
-{
|
|
- cpumask_t cpu;
|
|
- uint32_t new_cpu;
|
|
- uint32_t cpu_id[] = CPU_IDS;
|
|
-
|
|
- new_cpu = mc_fc_generic->as_in.param[0];
|
|
- mc_fc_generic->as_in.param[0] = cpu_id[mc_fc_generic->as_in.param[0]];
|
|
-
|
|
- if (_smc(mc_fc_generic) != 0 || mc_fc_generic->as_out.ret != 0) {
|
|
- MCDRV_DBG("CoreSwap failed %d -> %d (cpu %d still active)\n",
|
|
- raw_smp_processor_id(),
|
|
- mc_fc_generic->as_in.param[0],
|
|
- raw_smp_processor_id());
|
|
- } else {
|
|
- active_cpu = new_cpu;
|
|
- MCDRV_DBG("CoreSwap ok %d -> %d\n",
|
|
- raw_smp_processor_id(), active_cpu);
|
|
- }
|
|
- cpumask_clear(&cpu);
|
|
- cpumask_set_cpu(active_cpu, &cpu);
|
|
- return cpu;
|
|
-}
|
|
-#else /* TBASE_CORE_SWITCHER */
|
|
-static inline cpumask_t mc_exec_core_switch(union mc_fc_generic *mc_fc_generic)
|
|
-{
|
|
- return CPU_MASK_CPU0;
|
|
-}
|
|
-#endif /* !TBASE_CORE_SWITCHER */
|
|
-
|
|
-#ifdef MC_FASTCALL_WORKER_THREAD
|
|
-static void fastcall_work_func(struct kthread_work *work)
|
|
-#else
|
|
-static void fastcall_work_func(struct work_struct *work)
|
|
-#endif
|
|
-{
|
|
- struct fastcall_work *fc_work =
|
|
- container_of(work, struct fastcall_work, work);
|
|
- union mc_fc_generic *mc_fc_generic = fc_work->data;
|
|
-
|
|
- if (!mc_fc_generic)
|
|
- return;
|
|
-
|
|
- mc_clock_enable();
|
|
-
|
|
- if (mc_fc_generic->as_in.cmd == MC_FC_SWAP_CPU) {
|
|
-#ifdef MC_FASTCALL_WORKER_THREAD
|
|
- cpumask_t new_msk = mc_exec_core_switch(mc_fc_generic);
|
|
-
|
|
- set_cpus_allowed(fastcall_thread, new_msk);
|
|
-#else
|
|
- mc_exec_core_switch(mc_fc_generic);
|
|
-#endif
|
|
- } else {
|
|
- _smc(mc_fc_generic);
|
|
- }
|
|
-
|
|
- mc_clock_disable();
|
|
-}
|
|
-
|
|
-static bool mc_fastcall(void *data)
|
|
-{
|
|
-#ifdef MC_FASTCALL_WORKER_THREAD
|
|
- struct fastcall_work fc_work = {
|
|
- KTHREAD_WORK_INIT(fc_work.work, fastcall_work_func),
|
|
- .data = data,
|
|
- };
|
|
-
|
|
- if (!queue_kthread_work(&fastcall_worker, &fc_work.work))
|
|
- return false;
|
|
-
|
|
- /* If work is queued or executing, wait for it to finish execution */
|
|
- flush_kthread_work(&fc_work.work);
|
|
-#else
|
|
- struct fastcall_work fc_work = {
|
|
- .data = data,
|
|
- };
|
|
-
|
|
- INIT_WORK_ONSTACK(&fc_work.work, fastcall_work_func);
|
|
-
|
|
- if (!schedule_work_on(0, &fc_work.work))
|
|
- return false;
|
|
-
|
|
- flush_work(&fc_work.work);
|
|
-#endif
|
|
- return true;
|
|
-}
|
|
-
|
|
-int mc_fastcall_init(void)
|
|
-{
|
|
- int ret = mc_clock_init();
|
|
-
|
|
- if (ret)
|
|
- return ret;
|
|
-
|
|
-#ifdef MC_FASTCALL_WORKER_THREAD
|
|
- fastcall_thread = kthread_create(kthread_worker_fn, &fastcall_worker,
|
|
- "mc_fastcall");
|
|
- if (IS_ERR(fastcall_thread)) {
|
|
- ret = PTR_ERR(fastcall_thread);
|
|
- fastcall_thread = NULL;
|
|
- MCDRV_ERROR("cannot create fastcall wq (%d)", ret);
|
|
- return ret;
|
|
- }
|
|
-
|
|
- /* this thread MUST run on CPU 0 at startup */
|
|
- set_cpus_allowed(fastcall_thread, CPU_MASK_CPU0);
|
|
-
|
|
- wake_up_process(fastcall_thread);
|
|
-#ifdef TBASE_CORE_SWITCHER
|
|
- ret = register_cpu_notifier(&mobicore_cpu_notifer);
|
|
-#endif
|
|
-#endif /* MC_FASTCALL_WORKER_THREAD */
|
|
- return ret;
|
|
-}
|
|
-
|
|
-void mc_fastcall_exit(void)
|
|
-{
|
|
-#ifdef MC_FASTCALL_WORKER_THREAD
|
|
- if (!IS_ERR_OR_NULL(fastcall_thread)) {
|
|
-#ifdef TBASE_CORE_SWITCHER
|
|
- unregister_cpu_notifier(&mobicore_cpu_notifer);
|
|
-#endif
|
|
- kthread_stop(fastcall_thread);
|
|
- fastcall_thread = NULL;
|
|
- }
|
|
-#endif /* MC_FASTCALL_WORKER_THREAD */
|
|
- mc_clock_exit();
|
|
-}
|
|
-
|
|
-/*
|
|
- * convert fast call return code to linux driver module error code
|
|
- */
|
|
-static int convert_fc_ret(uint32_t ret)
|
|
-{
|
|
- switch (ret) {
|
|
- case MC_FC_RET_OK:
|
|
- return 0;
|
|
- case MC_FC_RET_ERR_INVALID:
|
|
- return -EINVAL;
|
|
- case MC_FC_RET_ERR_ALREADY_INITIALIZED:
|
|
- return -EBUSY;
|
|
- default:
|
|
- return -EFAULT;
|
|
- }
|
|
-}
|
|
-
|
|
-int mc_fc_init(uintptr_t base_pa, ptrdiff_t off, size_t q_len, size_t buf_len)
|
|
-{
|
|
-#ifdef CONFIG_ARM64
|
|
- uint32_t base_high = (uint32_t)(base_pa >> 32);
|
|
-#else
|
|
- uint32_t base_high = 0;
|
|
-#endif
|
|
- union mc_fc_init fc_init;
|
|
-
|
|
- /* Call the INIT fastcall to setup MobiCore initialization */
|
|
- memset(&fc_init, 0, sizeof(fc_init));
|
|
- fc_init.as_in.cmd = MC_FC_INIT;
|
|
- /* base address of mci buffer PAGE_SIZE (default is 4KB) aligned */
|
|
- fc_init.as_in.base = (uint32_t)base_pa;
|
|
- /* notification buffer start/length [16:16] [start, length] */
|
|
- fc_init.as_in.nq_info =
|
|
- ((base_high & 0xFFFF) << 16) | (q_len & 0xFFFF);
|
|
- /* mcp buffer start/length [16:16] [start, length] */
|
|
- fc_init.as_in.mcp_info = (off << 16) | (buf_len & 0xFFFF);
|
|
- MCDRV_DBG("cmd=0x%08x, base=0x%08x,nq_info=0x%08x, mcp_info=0x%08x",
|
|
- fc_init.as_in.cmd, fc_init.as_in.base, fc_init.as_in.nq_info,
|
|
- fc_init.as_in.mcp_info);
|
|
- mc_fastcall(&fc_init.as_generic);
|
|
- MCDRV_DBG("out cmd=0x%08x, ret=0x%08x", fc_init.as_out.resp,
|
|
- fc_init.as_out.ret);
|
|
- return convert_fc_ret(fc_init.as_out.ret);
|
|
-}
|
|
-
|
|
-int mc_fc_info(uint32_t ext_info_id, uint32_t *state, uint32_t *ext_info)
|
|
-{
|
|
- union mc_fc_info fc_info;
|
|
- int ret = 0;
|
|
-
|
|
- memset(&fc_info, 0, sizeof(fc_info));
|
|
- fc_info.as_in.cmd = MC_FC_INFO;
|
|
- fc_info.as_in.ext_info_id = ext_info_id;
|
|
- mc_fastcall(&fc_info.as_generic);
|
|
- ret = convert_fc_ret(fc_info.as_out.ret);
|
|
- if (ret) {
|
|
- if (state)
|
|
- *state = MC_STATUS_NOT_INITIALIZED;
|
|
-
|
|
- if (ext_info)
|
|
- *ext_info = 0;
|
|
-
|
|
- MCDRV_ERROR("code %d for idx %d", ret, ext_info_id);
|
|
- } else {
|
|
- if (state)
|
|
- *state = fc_info.as_out.state;
|
|
-
|
|
- if (ext_info)
|
|
- *ext_info = fc_info.as_out.ext_info;
|
|
- }
|
|
-
|
|
- return ret;
|
|
-}
|
|
-
|
|
-int mc_fc_mem_trace(phys_addr_t buffer, uint32_t size)
|
|
-{
|
|
- union mc_fc_generic mc_fc_generic;
|
|
-
|
|
- memset(&mc_fc_generic, 0, sizeof(mc_fc_generic));
|
|
- mc_fc_generic.as_in.cmd = MC_FC_MEM_TRACE;
|
|
- mc_fc_generic.as_in.param[0] = (uint32_t)buffer;
|
|
-#ifdef CONFIG_ARM64
|
|
- mc_fc_generic.as_in.param[1] = (uint32_t)(buffer >> 32);
|
|
-#endif
|
|
- mc_fc_generic.as_in.param[2] = size;
|
|
- mc_fastcall(&mc_fc_generic);
|
|
- return convert_fc_ret(mc_fc_generic.as_out.ret);
|
|
-}
|
|
-
|
|
-int mc_fc_nsiq(void)
|
|
-{
|
|
- union mc_fc_generic fc;
|
|
- int ret;
|
|
-
|
|
- memset(&fc, 0, sizeof(fc));
|
|
- fc.as_in.cmd = MC_SMC_N_SIQ;
|
|
- mc_fastcall(&fc);
|
|
- ret = convert_fc_ret(fc.as_out.ret);
|
|
- if (ret)
|
|
- MCDRV_ERROR("failed: %d", ret);
|
|
-
|
|
- return ret;
|
|
-}
|
|
-
|
|
-int mc_fc_yield(void)
|
|
-{
|
|
- union mc_fc_generic fc;
|
|
- int ret;
|
|
-
|
|
- memset(&fc, 0, sizeof(fc));
|
|
- fc.as_in.cmd = MC_SMC_N_YIELD;
|
|
- mc_fastcall(&fc);
|
|
- ret = convert_fc_ret(fc.as_out.ret);
|
|
- if (ret)
|
|
- MCDRV_ERROR("failed: %d", ret);
|
|
-
|
|
- return ret;
|
|
-}
|
|
-
|
|
-#ifdef TBASE_CORE_SWITCHER
|
|
-uint32_t mc_active_core(void)
|
|
-{
|
|
- return active_cpu;
|
|
-}
|
|
-
|
|
-int mc_switch_core(uint32_t core_num)
|
|
-{
|
|
- int32_t ret = 0;
|
|
- union mc_fc_swich_core fc_switch_core;
|
|
-
|
|
- if (!cpu_online(core_num))
|
|
- return 1;
|
|
-
|
|
- MCDRV_DBG_VERBOSE("enter\n");
|
|
- memset(&fc_switch_core, 0, sizeof(fc_switch_core));
|
|
- fc_switch_core.as_in.cmd = MC_FC_SWAP_CPU;
|
|
- if (core_num < COUNT_OF_CPUS)
|
|
- fc_switch_core.as_in.core_id = core_num;
|
|
- else
|
|
- fc_switch_core.as_in.core_id = 0;
|
|
-
|
|
- MCDRV_DBG("<- cmd=0x%08x, core_id=0x%08x\n",
|
|
- fc_switch_core.as_in.cmd, fc_switch_core.as_in.core_id);
|
|
- MCDRV_DBG("<- core_num=0x%08x, active_cpu=0x%08x\n",
|
|
- core_num, active_cpu);
|
|
- mc_fastcall(&fc_switch_core.as_generic);
|
|
- ret = convert_fc_ret(fc_switch_core.as_out.ret);
|
|
- MCDRV_DBG_VERBOSE("exit with %d/0x%08X\n", ret, ret);
|
|
- return ret;
|
|
-}
|
|
-#endif
|
|
diff --git a/drivers/gud/MobiCoreDriver/fastcall.h b/drivers/gud/MobiCoreDriver/fastcall.h
|
|
deleted file mode 100644
|
|
index b19b27687ff38..0000000000000
|
|
--- a/drivers/gud/MobiCoreDriver/fastcall.h
|
|
+++ /dev/null
|
|
@@ -1,38 +0,0 @@
|
|
-/*
|
|
- * Copyright (c) 2013-2015 TRUSTONIC LIMITED
|
|
- * All Rights Reserved.
|
|
- *
|
|
- * This program is free software; you can redistribute it and/or
|
|
- * modify it under the terms of the GNU General Public License
|
|
- * version 2 as published by the Free Software Foundation.
|
|
- *
|
|
- * This program is distributed in the hope that it will be useful,
|
|
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
- * GNU General Public License for more details.
|
|
- */
|
|
-
|
|
-#ifndef _TBASE_FASTCALL_H_
|
|
-#define _TBASE_FASTCALL_H_
|
|
-
|
|
-/* Use the arch_extension sec pseudo op before switching to secure world */
|
|
-#if defined(__GNUC__) && \
|
|
- defined(__GNUC_MINOR__) && \
|
|
- defined(__GNUC_PATCHLEVEL__) && \
|
|
- ((__GNUC__ * 10000 + __GNUC_MINOR__ * 100 + __GNUC_PATCHLEVEL__)) \
|
|
- >= 40502
|
|
-#ifndef CONFIG_ARM64
|
|
-#define MC_ARCH_EXTENSION_SEC
|
|
-#endif
|
|
-#endif
|
|
-
|
|
-int mc_fc_init(uintptr_t base_pa, ptrdiff_t off, size_t q_len, size_t buf_len);
|
|
-int mc_fc_info(uint32_t ext_info_id, uint32_t *state, uint32_t *ext_info);
|
|
-int mc_fc_mem_trace(phys_addr_t buffer, uint32_t size);
|
|
-int mc_fc_nsiq(void);
|
|
-int mc_fc_yield(void);
|
|
-
|
|
-int mc_fastcall_init(void);
|
|
-void mc_fastcall_exit(void);
|
|
-
|
|
-#endif /* _TBASE_FASTCALL_H_ */
|
|
diff --git a/drivers/gud/MobiCoreDriver/logging.c b/drivers/gud/MobiCoreDriver/logging.c
|
|
deleted file mode 100644
|
|
index 953de5f149f78..0000000000000
|
|
--- a/drivers/gud/MobiCoreDriver/logging.c
|
|
+++ /dev/null
|
|
@@ -1,251 +0,0 @@
|
|
-/*
|
|
- * Copyright (c) 2013-2015 TRUSTONIC LIMITED
|
|
- * All Rights Reserved.
|
|
- *
|
|
- * This program is free software; you can redistribute it and/or
|
|
- * modify it under the terms of the GNU General Public License
|
|
- * version 2 as published by the Free Software Foundation.
|
|
- *
|
|
- * This program is distributed in the hope that it will be useful,
|
|
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
- * GNU General Public License for more details.
|
|
- */
|
|
-
|
|
-#include <linux/workqueue.h>
|
|
-#include <linux/slab.h>
|
|
-#include <linux/device.h>
|
|
-
|
|
-#include "fastcall.h"
|
|
-#include "main.h"
|
|
-#include "logging.h"
|
|
-
|
|
-#ifndef CONFIG_TRUSTONIC_TEE_NO_TRACES
|
|
-
|
|
-/* Supported log buffer version */
|
|
-#define MC_LOG_VERSION 2
|
|
-
|
|
-/* Default length of the log ring buffer 256KiB */
|
|
-#define LOG_BUF_ORDER 6
|
|
-
|
|
-/* Max Len of a log line for printing */
|
|
-#define LOG_LINE_SIZE 256
|
|
-
|
|
-/* Definitions for log version 2 */
|
|
-#define LOG_TYPE_MASK (0x0007)
|
|
-#define LOG_TYPE_CHAR 0
|
|
-#define LOG_TYPE_INTEGER 1
|
|
-
|
|
-/* Field length */
|
|
-#define LOG_LENGTH_MASK (0x00F8)
|
|
-#define LOG_LENGTH_SHIFT 3
|
|
-
|
|
-/* Extra attributes */
|
|
-#define LOG_EOL (0x0100)
|
|
-#define LOG_INTEGER_DECIMAL (0x0200)
|
|
-#define LOG_INTEGER_SIGNED (0x0400)
|
|
-
|
|
-struct mc_logmsg {
|
|
- uint16_t ctrl; /* Type and format of data */
|
|
- uint16_t source; /* Unique value for each event source */
|
|
- uint32_t log_data; /* Value, if any */
|
|
-};
|
|
-
|
|
-/* MobiCore internal trace buffer structure. */
|
|
-struct mc_trace_buf {
|
|
- uint32_t version; /* version of trace buffer */
|
|
- uint32_t length; /* length of buff */
|
|
- uint32_t head; /* last write position */
|
|
- uint8_t buff[]; /* start of the log buffer */
|
|
-};
|
|
-
|
|
-static struct logging_ctx {
|
|
- struct work_struct work;
|
|
- union {
|
|
- struct mc_trace_buf *trace_buf; /* Circular log buffer */
|
|
- unsigned long trace_page;
|
|
- };
|
|
- bool buffer_is_shared; /* Log buffer cannot be freed */
|
|
- uint32_t tail; /* MobiCore log read position */
|
|
- uint32_t line_len; /* Log Line buffer current length */
|
|
- int thread_err;
|
|
- uint16_t prev_source; /* Previous Log source */
|
|
- char line[LOG_LINE_SIZE]; /* Log Line buffer */
|
|
- bool dead;
|
|
-} log_ctx;
|
|
-
|
|
-static inline void log_eol(uint16_t source)
|
|
-{
|
|
- if (!strnlen(log_ctx.line, LOG_LINE_SIZE)) {
|
|
- /* In case a TA tries to print a 0x0 */
|
|
- log_ctx.line_len = 0;
|
|
- return;
|
|
- }
|
|
-
|
|
- if (log_ctx.prev_source)
|
|
- /* MobiCore Userspace */
|
|
- dev_info(g_ctx.mcd, "%03x|%s\n", log_ctx.prev_source,
|
|
- log_ctx.line);
|
|
- else
|
|
- /* MobiCore kernel */
|
|
- dev_info(g_ctx.mcd, "%s\n", log_ctx.line);
|
|
-
|
|
- log_ctx.line_len = 0;
|
|
- log_ctx.line[0] = 0;
|
|
-}
|
|
-
|
|
-/*
|
|
- * Collect chars in log_ctx.line buffer and output the buffer when it is full.
|
|
- * No locking needed because only "mobicore_log" thread updates this buffer.
|
|
- */
|
|
-static inline void log_char(char ch, uint16_t source)
|
|
-{
|
|
- if (ch == '\n' || ch == '\r') {
|
|
- log_eol(source);
|
|
- return;
|
|
- }
|
|
-
|
|
- if ((log_ctx.line_len >= (LOG_LINE_SIZE - 1)) ||
|
|
- (source != log_ctx.prev_source))
|
|
- log_eol(source);
|
|
-
|
|
- log_ctx.line[log_ctx.line_len++] = ch;
|
|
- log_ctx.line[log_ctx.line_len] = 0;
|
|
- log_ctx.prev_source = source;
|
|
-}
|
|
-
|
|
-static inline void log_string(uint32_t ch, uint16_t source)
|
|
-{
|
|
- while (ch) {
|
|
- log_char(ch & 0xFF, source);
|
|
- ch >>= 8;
|
|
- }
|
|
-}
|
|
-
|
|
-static inline void log_number(uint32_t format, uint32_t value, uint16_t source)
|
|
-{
|
|
- int width = (format & LOG_LENGTH_MASK) >> LOG_LENGTH_SHIFT;
|
|
- char fmt[16];
|
|
- char buffer[32];
|
|
- const char *reader = buffer;
|
|
-
|
|
- if (format & LOG_INTEGER_DECIMAL)
|
|
- if (format & LOG_INTEGER_SIGNED)
|
|
- snprintf(fmt, sizeof(fmt), "%%%ud", width);
|
|
- else
|
|
- snprintf(fmt, sizeof(fmt), "%%%uu", width);
|
|
- else
|
|
- snprintf(fmt, sizeof(fmt), "%%0%ux", width);
|
|
-
|
|
- snprintf(buffer, sizeof(buffer), fmt, value);
|
|
- while (*reader)
|
|
- log_char(*reader++, source);
|
|
-}
|
|
-
|
|
-static inline int log_msg(void *data)
|
|
-{
|
|
- struct mc_logmsg *msg = (struct mc_logmsg *)data;
|
|
- int log_type = msg->ctrl & LOG_TYPE_MASK;
|
|
-
|
|
- switch (log_type) {
|
|
- case LOG_TYPE_CHAR:
|
|
- log_string(msg->log_data, msg->source);
|
|
- break;
|
|
- case LOG_TYPE_INTEGER:
|
|
- log_number(msg->ctrl, msg->log_data, msg->source);
|
|
- break;
|
|
- }
|
|
- if (msg->ctrl & LOG_EOL)
|
|
- log_eol(msg->source);
|
|
-
|
|
- return sizeof(*msg);
|
|
-}
|
|
-
|
|
-static void log_worker(struct work_struct *work)
|
|
-{
|
|
- while (log_ctx.trace_buf->head != log_ctx.tail) {
|
|
- if (log_ctx.trace_buf->version != MC_LOG_VERSION) {
|
|
- dev_err(g_ctx.mcd,
|
|
- "Bad log data v%d (exp. v%d), stop.\n",
|
|
- log_ctx.trace_buf->version,
|
|
- MC_LOG_VERSION);
|
|
- log_ctx.dead = true;
|
|
- break;
|
|
- }
|
|
-
|
|
- log_ctx.tail += log_msg(&log_ctx.trace_buf->buff[log_ctx.tail]);
|
|
- /* Wrap over if no space left for a complete message */
|
|
- if ((log_ctx.tail + sizeof(struct mc_logmsg)) >
|
|
- log_ctx.trace_buf->length)
|
|
- log_ctx.tail = 0;
|
|
- }
|
|
-}
|
|
-
|
|
-/*
|
|
- * Wake up the log reader thread
|
|
- * This should be called from the places where calls into MobiCore have
|
|
- * generated some logs(eg, yield, SIQ...)
|
|
- */
|
|
-void mc_logging_run(void)
|
|
-{
|
|
- if (!log_ctx.dead && (log_ctx.trace_buf->head != log_ctx.tail))
|
|
- schedule_work(&log_ctx.work);
|
|
-}
|
|
-
|
|
-int mc_logging_start(void)
|
|
-{
|
|
- int ret = mc_fc_mem_trace(virt_to_phys((void *)(log_ctx.trace_page)),
|
|
- BIT(LOG_BUF_ORDER) * PAGE_SIZE);
|
|
-
|
|
- if (ret) {
|
|
- dev_err(g_ctx.mcd, "shared traces setup failed\n");
|
|
- return ret;
|
|
- }
|
|
-
|
|
- log_ctx.buffer_is_shared = true;
|
|
- dev_dbg(g_ctx.mcd, "fc_log version %u\n", log_ctx.trace_buf->version);
|
|
- mc_logging_run();
|
|
- return 0;
|
|
-}
|
|
-
|
|
-void mc_logging_stop(void)
|
|
-{
|
|
- if (!mc_fc_mem_trace(0, 0))
|
|
- log_ctx.buffer_is_shared = false;
|
|
-
|
|
- mc_logging_run();
|
|
- flush_work(&log_ctx.work);
|
|
-}
|
|
-
|
|
-/*
|
|
- * Setup MobiCore kernel log. It assumes it's running on CORE 0!
|
|
- * The fastcall will complain is that is not the case!
|
|
- */
|
|
-int mc_logging_init(void)
|
|
-{
|
|
- /*
|
|
- * We are going to map this buffer into virtual address space in SWd.
|
|
- * To reduce complexity there, we use a contiguous buffer.
|
|
- */
|
|
- log_ctx.trace_page = __get_free_pages(GFP_KERNEL | __GFP_ZERO,
|
|
- LOG_BUF_ORDER);
|
|
- if (!log_ctx.trace_page)
|
|
- return -ENOMEM;
|
|
-
|
|
- INIT_WORK(&log_ctx.work, log_worker);
|
|
- return 0;
|
|
-}
|
|
-
|
|
-void mc_logging_exit(void)
|
|
-{
|
|
- /*
|
|
- * This is not racey as the only caller for mc_logging_run is the
|
|
- * scheduler which gets stopped before us, and long before we exit.
|
|
- */
|
|
- if (!log_ctx.buffer_is_shared)
|
|
- free_pages(log_ctx.trace_page, LOG_BUF_ORDER);
|
|
- else
|
|
- dev_err(g_ctx.mcd, "log buffer unregister not supported\n");
|
|
-}
|
|
-
|
|
-#endif /* !CONFIG_TRUSTONIC_TEE_NO_TRACES */
|
|
diff --git a/drivers/gud/MobiCoreDriver/logging.h b/drivers/gud/MobiCoreDriver/logging.h
|
|
deleted file mode 100644
|
|
index 744b41880ea31..0000000000000
|
|
--- a/drivers/gud/MobiCoreDriver/logging.h
|
|
+++ /dev/null
|
|
@@ -1,51 +0,0 @@
|
|
-/*
|
|
- * Copyright (c) 2013-2015 TRUSTONIC LIMITED
|
|
- * All Rights Reserved.
|
|
- *
|
|
- * This program is free software; you can redistribute it and/or
|
|
- * modify it under the terms of the GNU General Public License
|
|
- * version 2 as published by the Free Software Foundation.
|
|
- *
|
|
- * This program is distributed in the hope that it will be useful,
|
|
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
- * GNU General Public License for more details.
|
|
- */
|
|
-#ifndef _MC_LOGGING_H_
|
|
-#define _MC_LOGGING_H_
|
|
-
|
|
-#include "platform.h" /* CONFIG_TRUSTONIC_TEE_NO_TRACES */
|
|
-
|
|
-/* MobiCore internal trace log setup. */
|
|
-#ifndef CONFIG_TRUSTONIC_TEE_NO_TRACES
|
|
-void mc_logging_run(void);
|
|
-int mc_logging_init(void);
|
|
-void mc_logging_exit(void);
|
|
-int mc_logging_start(void);
|
|
-void mc_logging_stop(void);
|
|
-#else /* !CONFIG_TRUSTONIC_TEE_NO_TRACES */
|
|
-static inline void mc_logging_run(void)
|
|
-{
|
|
-}
|
|
-
|
|
-static inline long mc_logging_init(void)
|
|
-{
|
|
- return 0;
|
|
-}
|
|
-
|
|
-static inline void mc_logging_exit(void)
|
|
-{
|
|
-}
|
|
-
|
|
-static inline int mc_logging_start(void)
|
|
-{
|
|
- return 0;
|
|
-}
|
|
-
|
|
-static inline void mc_logging_stop(void)
|
|
-{
|
|
-}
|
|
-
|
|
-#endif /* CONFIG_TRUSTONIC_TEE_NO_TRACES */
|
|
-
|
|
-#endif /* _MC_LOGGING_H_ */
|
|
diff --git a/drivers/gud/MobiCoreDriver/main.c b/drivers/gud/MobiCoreDriver/main.c
|
|
deleted file mode 100644
|
|
index 66b232e5bc8b5..0000000000000
|
|
--- a/drivers/gud/MobiCoreDriver/main.c
|
|
+++ /dev/null
|
|
@@ -1,750 +0,0 @@
|
|
-/*
|
|
- * Copyright (c) 2013-2015 TRUSTONIC LIMITED
|
|
- * All Rights Reserved.
|
|
- *
|
|
- * This program is free software; you can redistribute it and/or
|
|
- * modify it under the terms of the GNU General Public License
|
|
- * version 2 as published by the Free Software Foundation.
|
|
- *
|
|
- * This program is distributed in the hope that it will be useful,
|
|
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
- * GNU General Public License for more details.
|
|
- */
|
|
-#include <asm/pgtable.h>
|
|
-
|
|
-#include <linux/highmem.h>
|
|
-#include <linux/slab.h>
|
|
-#include <linux/kthread.h>
|
|
-#include <linux/platform_device.h>
|
|
-#include <linux/module.h>
|
|
-#include <linux/ioctl.h>
|
|
-#include <linux/mm.h>
|
|
-#include <linux/mman.h>
|
|
-#include <linux/mutex.h>
|
|
-#include <linux/cdev.h>
|
|
-#include <linux/stat.h>
|
|
-#include <linux/debugfs.h>
|
|
-
|
|
-#include "public/mc_linux.h"
|
|
-
|
|
-#include "main.h"
|
|
-#include "fastcall.h"
|
|
-#include "arm.h"
|
|
-#include "mmu.h"
|
|
-#include "scheduler.h"
|
|
-#include "pm.h"
|
|
-#include "debug.h"
|
|
-#include "logging.h"
|
|
-#include "admin.h"
|
|
-#include "mcp.h"
|
|
-#include "session.h"
|
|
-#include "client.h"
|
|
-#include "api.h"
|
|
-
|
|
-#include "build_tag.h"
|
|
-
|
|
-/* Define a MobiCore device structure for use with dev_debug() etc */
|
|
-static struct device_driver driver = {
|
|
- .name = "Trustonic"
|
|
-};
|
|
-
|
|
-static struct device device = {
|
|
- .driver = &driver
|
|
-};
|
|
-
|
|
-struct mc_device_ctx g_ctx = {
|
|
- .mcd = &device
|
|
-};
|
|
-
|
|
-/* device admin */
|
|
-static dev_t mc_dev_admin;
|
|
-/* device user */
|
|
-static dev_t mc_dev_user;
|
|
-
|
|
-/* Need to discover a chrdev region for the driver */
|
|
-static struct cdev mc_user_cdev;
|
|
-/* Device class for the driver assigned major */
|
|
-static struct class *mc_device_class;
|
|
-
|
|
-/*
|
|
- * Get client object from file pointer
|
|
- */
|
|
-static inline struct tbase_client *get_client(struct file *file)
|
|
-{
|
|
- return (struct tbase_client *)file->private_data;
|
|
-}
|
|
-
|
|
-/*
|
|
- * Callback for system mmap()
|
|
- */
|
|
-static int mc_fd_user_mmap(struct file *file, struct vm_area_struct *vmarea)
|
|
-{
|
|
- struct tbase_client *client = get_client(file);
|
|
- uint32_t len = (uint32_t)(vmarea->vm_end - vmarea->vm_start);
|
|
-
|
|
- /* Alloc contiguous buffer for this client */
|
|
- return api_malloc_cbuf(client, len, NULL, vmarea);
|
|
-}
|
|
-
|
|
-/*
|
|
- * Check r/w access to referenced memory
|
|
- */
|
|
-static inline int ioctl_check_pointer(unsigned int cmd, int __user *uarg)
|
|
-{
|
|
- int err = 0;
|
|
-
|
|
- if (_IOC_DIR(cmd) & _IOC_READ)
|
|
- err = !access_ok(VERIFY_WRITE, uarg, _IOC_SIZE(cmd));
|
|
- else if (_IOC_DIR(cmd) & _IOC_WRITE)
|
|
- err = !access_ok(VERIFY_READ, uarg, _IOC_SIZE(cmd));
|
|
-
|
|
- if (err)
|
|
- return -EFAULT;
|
|
-
|
|
- return 0;
|
|
-}
|
|
-
|
|
-/*
|
|
- * Callback for system ioctl()
|
|
- * Implement most of ClientLib API functions
|
|
- * @file pointer to file
|
|
- * @cmd command
|
|
- * @arg arguments
|
|
- *
|
|
- * Returns 0 for OK and an errno in case of error
|
|
- */
|
|
-static long mc_fd_user_ioctl(struct file *file, unsigned int id,
|
|
- unsigned long arg)
|
|
-{
|
|
- struct tbase_client *client = get_client(file);
|
|
- int __user *uarg = (int __user *)arg;
|
|
- int ret = -EINVAL;
|
|
-
|
|
- MCDRV_DBG("%u from %s", _IOC_NR(id), current->comm);
|
|
-
|
|
- if (WARN(!client, "No client data available"))
|
|
- return -EPROTO;
|
|
-
|
|
- if (ioctl_check_pointer(id, uarg))
|
|
- return -EFAULT;
|
|
-
|
|
- switch (id) {
|
|
- case MC_IO_FREEZE:
|
|
- /* Freeze the client */
|
|
- ret = api_freeze_device(client);
|
|
- break;
|
|
-
|
|
- case MC_IO_OPEN_SESSION: {
|
|
- struct mc_ioctl_open_sess sess;
|
|
-
|
|
- if (copy_from_user(&sess, uarg, sizeof(sess))) {
|
|
- ret = -EFAULT;
|
|
- break;
|
|
- }
|
|
-
|
|
- ret = api_open_session(client, &sess.sid, &sess.uuid, sess.tci,
|
|
- sess.tcilen, sess.is_gp_uuid,
|
|
- &sess.identity);
|
|
- if (ret)
|
|
- break;
|
|
-
|
|
- if (copy_to_user(uarg, &sess, sizeof(sess))) {
|
|
- ret = -EFAULT;
|
|
- api_close_session(client, sess.sid);
|
|
- break;
|
|
- }
|
|
- break;
|
|
- }
|
|
- case MC_IO_OPEN_TRUSTLET: {
|
|
- struct mc_ioctl_open_trustlet ta_desc;
|
|
-
|
|
- if (copy_from_user(&ta_desc, uarg, sizeof(ta_desc))) {
|
|
- ret = -EFAULT;
|
|
- break;
|
|
- }
|
|
-
|
|
- /* Call internal api */
|
|
- ret = api_open_trustlet(client, &ta_desc.sid, ta_desc.spid,
|
|
- ta_desc.buffer, ta_desc.tlen,
|
|
- ta_desc.tci, ta_desc.tcilen);
|
|
- if (ret)
|
|
- break;
|
|
-
|
|
- if (copy_to_user(uarg, &ta_desc, sizeof(ta_desc))) {
|
|
- ret = -EFAULT;
|
|
- api_close_session(client, ta_desc.sid);
|
|
- break;
|
|
- }
|
|
- break;
|
|
- }
|
|
- case MC_IO_CLOSE_SESSION: {
|
|
- uint32_t sid = (uint32_t)arg;
|
|
-
|
|
- ret = api_close_session(client, sid);
|
|
- break;
|
|
- }
|
|
- case MC_IO_NOTIFY: {
|
|
- uint32_t sid = (uint32_t)arg;
|
|
-
|
|
- ret = api_notify(client, sid);
|
|
- break;
|
|
- }
|
|
- case MC_IO_WAIT: {
|
|
- struct mc_ioctl_wait wait;
|
|
-
|
|
- if (copy_from_user(&wait, uarg, sizeof(wait))) {
|
|
- ret = -EFAULT;
|
|
- break;
|
|
- }
|
|
- ret = api_wait_notification(client, wait.sid, wait.timeout);
|
|
- break;
|
|
- }
|
|
- case MC_IO_MAP: {
|
|
- struct mc_ioctl_map map;
|
|
-
|
|
- if (copy_from_user(&map, uarg, sizeof(map))) {
|
|
- ret = -EFAULT;
|
|
- break;
|
|
- }
|
|
- ret = api_map_wsms(client, map.sid, map.bufs);
|
|
- if (ret)
|
|
- break;
|
|
-
|
|
- /* Fill in return struct */
|
|
- if (copy_to_user(uarg, &map, sizeof(map))) {
|
|
- ret = -EFAULT;
|
|
- api_unmap_wsms(client, map.sid, map.bufs);
|
|
- break;
|
|
- }
|
|
- break;
|
|
- }
|
|
- case MC_IO_UNMAP: {
|
|
- struct mc_ioctl_map map;
|
|
-
|
|
- if (copy_from_user(&map, uarg, sizeof(map))) {
|
|
- ret = -EFAULT;
|
|
- break;
|
|
- }
|
|
-
|
|
- ret = api_unmap_wsms(client, map.sid, map.bufs);
|
|
- break;
|
|
- }
|
|
- case MC_IO_ERR: {
|
|
- struct mc_ioctl_geterr *uerr = (struct mc_ioctl_geterr *)uarg;
|
|
- uint32_t sid;
|
|
- int32_t exit_code;
|
|
-
|
|
- if (get_user(sid, &uerr->sid)) {
|
|
- ret = -EFAULT;
|
|
- break;
|
|
- }
|
|
-
|
|
- ret = api_get_session_exitcode(client, sid, &exit_code);
|
|
- if (ret)
|
|
- break;
|
|
-
|
|
- /* Fill in return struct */
|
|
- if (put_user(exit_code, &uerr->value)) {
|
|
- ret = -EFAULT;
|
|
- break;
|
|
- }
|
|
-
|
|
- break;
|
|
- }
|
|
- case MC_IO_VERSION: {
|
|
- struct mc_version_info version_info;
|
|
-
|
|
- ret = mcp_get_version(&version_info);
|
|
- if (ret)
|
|
- break;
|
|
-
|
|
- if (copy_to_user(uarg, &version_info, sizeof(version_info)))
|
|
- ret = -EFAULT;
|
|
-
|
|
- break;
|
|
- }
|
|
- case MC_IO_DR_VERSION: {
|
|
- uint32_t version = MC_VERSION(MCDRVMODULEAPI_VERSION_MAJOR,
|
|
- MCDRVMODULEAPI_VERSION_MINOR);
|
|
-
|
|
- ret = put_user(version, uarg);
|
|
- break;
|
|
- }
|
|
- default:
|
|
- MCDRV_ERROR("unsupported cmd=0x%x", id);
|
|
- ret = -ENOIOCTLCMD;
|
|
- }
|
|
-
|
|
- return ret;
|
|
-}
|
|
-
|
|
-/*
|
|
- * Callback for system open()
|
|
- * A set of internal client data are created and initialized.
|
|
- *
|
|
- * @inode
|
|
- * @file
|
|
- * Returns 0 if OK or -ENOMEM if no allocation was possible.
|
|
- */
|
|
-static int mc_fd_user_open(struct inode *inode, struct file *file)
|
|
-{
|
|
- struct tbase_client *client;
|
|
-
|
|
- MCDRV_DBG("from %s", current->comm);
|
|
-
|
|
- /* Create client */
|
|
- client = api_open_device(false);
|
|
- if (!client)
|
|
- return -ENOMEM;
|
|
-
|
|
- /* Store client in user file */
|
|
- file->private_data = client;
|
|
- return 0;
|
|
-}
|
|
-
|
|
-/*
|
|
- * Callback for system close()
|
|
- * The client object is freed.
|
|
- * @inode
|
|
- * @file
|
|
- * Returns 0
|
|
- */
|
|
-static int mc_fd_user_release(struct inode *inode, struct file *file)
|
|
-{
|
|
- struct tbase_client *client = get_client(file);
|
|
-
|
|
- MCDRV_DBG("from %s", current->comm);
|
|
-
|
|
- if (WARN(!client, "No client data available"))
|
|
- return -EPROTO;
|
|
-
|
|
- /* Detach client from user file */
|
|
- file->private_data = NULL;
|
|
-
|
|
- /* Destroy client, including remaining sessions */
|
|
- api_close_device(client);
|
|
- return 0;
|
|
-}
|
|
-
|
|
-static const struct file_operations mc_user_fops = {
|
|
- .owner = THIS_MODULE,
|
|
- .open = mc_fd_user_open,
|
|
- .release = mc_fd_user_release,
|
|
- .unlocked_ioctl = mc_fd_user_ioctl,
|
|
-#ifdef CONFIG_COMPAT
|
|
- .compat_ioctl = mc_fd_user_ioctl,
|
|
-#endif
|
|
- .mmap = mc_fd_user_mmap,
|
|
-};
|
|
-
|
|
-int kasnprintf(struct kasnprintf_buf *buf, const char *fmt, ...)
|
|
-{
|
|
- va_list args;
|
|
- int max_size = buf->size - buf->off;
|
|
- int i;
|
|
-
|
|
- va_start(args, fmt);
|
|
- i = vsnprintf(buf->buf + buf->off, max_size, fmt, args);
|
|
- if (i >= max_size) {
|
|
- int new_size = PAGE_ALIGN(buf->size + i + 1);
|
|
- char *new_buf = krealloc(buf->buf, new_size, buf->gfp);
|
|
-
|
|
- if (!new_buf) {
|
|
- i = -ENOMEM;
|
|
- } else {
|
|
- buf->buf = new_buf;
|
|
- buf->size = new_size;
|
|
- max_size = buf->size - buf->off;
|
|
- i = vsnprintf(buf->buf + buf->off, max_size, fmt, args);
|
|
- }
|
|
- }
|
|
-
|
|
- if (i > 0)
|
|
- buf->off += i;
|
|
-
|
|
- va_end(args);
|
|
- return i;
|
|
-}
|
|
-
|
|
-static ssize_t debug_info_read(struct file *file, char __user *user_buf,
|
|
- size_t count, loff_t *ppos)
|
|
-{
|
|
- /* Add/update buffer */
|
|
- if (!file->private_data || !*ppos) {
|
|
- struct kasnprintf_buf *buf, *old_buf;
|
|
- int ret;
|
|
-
|
|
- buf = kzalloc(GFP_KERNEL, sizeof(*buf));
|
|
- if (!buf)
|
|
- return -ENOMEM;
|
|
-
|
|
- buf->gfp = GFP_KERNEL;
|
|
- ret = api_info(buf);
|
|
- if (ret < 0) {
|
|
- kfree(buf);
|
|
- return ret;
|
|
- }
|
|
-
|
|
- old_buf = file->private_data;
|
|
- file->private_data = buf;
|
|
- kfree(old_buf);
|
|
- }
|
|
-
|
|
- if (file->private_data) {
|
|
- struct kasnprintf_buf *buf = file->private_data;
|
|
-
|
|
- return simple_read_from_buffer(user_buf, count, ppos, buf->buf,
|
|
- buf->off);
|
|
- }
|
|
-
|
|
- return 0;
|
|
-}
|
|
-
|
|
-static int debug_info_release(struct inode *inode, struct file *file)
|
|
-{
|
|
- kfree(file->private_data);
|
|
- return 0;
|
|
-}
|
|
-
|
|
-static const struct file_operations mc_debug_info_ops = {
|
|
- .read = debug_info_read,
|
|
- .llseek = default_llseek,
|
|
- .release = debug_info_release,
|
|
-};
|
|
-
|
|
-static inline int device_admin_init(int (*tee_start_cb)(void))
|
|
-{
|
|
- int ret = 0;
|
|
-
|
|
- cdev_init(&mc_user_cdev, &mc_user_fops);
|
|
-
|
|
- mc_device_class = class_create(THIS_MODULE, "trustonic_tee");
|
|
- if (IS_ERR(mc_device_class)) {
|
|
- MCDRV_ERROR("failed to create device class");
|
|
- return PTR_ERR(mc_device_class);
|
|
- }
|
|
-
|
|
- /* Create the ADMIN node */
|
|
- ret = mc_admin_init(mc_device_class, &mc_dev_admin, tee_start_cb);
|
|
- if (ret < 0) {
|
|
- MCDRV_ERROR("failed to init mobicore device");
|
|
- class_destroy(mc_device_class);
|
|
- return ret;
|
|
- }
|
|
- return 0;
|
|
-}
|
|
-
|
|
-static inline int device_user_init(void)
|
|
-{
|
|
- int ret = 0;
|
|
- struct device *dev;
|
|
-
|
|
- mc_dev_user = MKDEV(MAJOR(mc_dev_admin), 1);
|
|
- /* Create the user node */
|
|
- ret = cdev_add(&mc_user_cdev, mc_dev_user, 1);
|
|
- if (ret) {
|
|
- MCDRV_ERROR("user device register failed");
|
|
- goto err_cdev_add;
|
|
- }
|
|
- mc_user_cdev.owner = THIS_MODULE;
|
|
- dev = device_create(mc_device_class, NULL, mc_dev_user, NULL,
|
|
- MC_USER_DEVNODE);
|
|
- if (IS_ERR(dev)) {
|
|
- ret = PTR_ERR(dev);
|
|
- goto err_device_create;
|
|
- }
|
|
-
|
|
- /* Create debugfs info entry */
|
|
- debugfs_create_file("info", 0400, g_ctx.debug_dir, NULL,
|
|
- &mc_debug_info_ops);
|
|
-
|
|
- return 0;
|
|
-
|
|
-err_device_create:
|
|
- cdev_del(&mc_user_cdev);
|
|
-err_cdev_add:
|
|
- mc_admin_exit(mc_device_class);
|
|
- class_destroy(mc_device_class);
|
|
- MCDRV_DBG("failed with %d", ret);
|
|
- return ret;
|
|
-}
|
|
-
|
|
-static void devices_exit(void)
|
|
-{
|
|
- device_destroy(mc_device_class, mc_dev_user);
|
|
- cdev_del(&mc_user_cdev);
|
|
- mc_admin_exit(mc_device_class);
|
|
- class_destroy(mc_device_class);
|
|
-}
|
|
-
|
|
-static inline int mobicore_start(void)
|
|
-{
|
|
- int ret;
|
|
- struct mc_version_info version_info;
|
|
-
|
|
- ret = mcp_start();
|
|
- if (ret) {
|
|
- MCDRV_ERROR("TEE start failed");
|
|
- goto err_mcp;
|
|
- }
|
|
-
|
|
- ret = mc_logging_start();
|
|
- if (ret) {
|
|
- MCDRV_ERROR("Log start failed");
|
|
- goto err_log;
|
|
- }
|
|
-
|
|
- ret = mc_scheduler_start();
|
|
- if (ret) {
|
|
- MCDRV_ERROR("Scheduler start failed");
|
|
- goto err_sched;
|
|
- }
|
|
-
|
|
- ret = mc_pm_start();
|
|
- if (ret) {
|
|
- MCDRV_ERROR("Power Management start failed");
|
|
- goto err_pm;
|
|
- }
|
|
-
|
|
- ret = mcp_get_version(&version_info);
|
|
- if (ret)
|
|
- goto err_mcp_cmd;
|
|
-
|
|
- MCDRV_DBG("\n"
|
|
- " product_id = %s\n"
|
|
- " version_so = 0x%x\n"
|
|
- " version_mci = 0x%x\n"
|
|
- " version_mclf = 0x%x\n"
|
|
- " version_container = 0x%x\n"
|
|
- " version_mc_config = 0x%x\n"
|
|
- " version_tl_api = 0x%x\n"
|
|
- " version_dr_api = 0x%x\n"
|
|
- " version_cmp = 0x%x\n",
|
|
- version_info.product_id,
|
|
- version_info.version_mci,
|
|
- version_info.version_so,
|
|
- version_info.version_mclf,
|
|
- version_info.version_container,
|
|
- version_info.version_mc_config,
|
|
- version_info.version_tl_api,
|
|
- version_info.version_dr_api,
|
|
- version_info.version_cmp);
|
|
-
|
|
- if (MC_VERSION_MAJOR(version_info.version_mci) > 1) {
|
|
- pr_err("MCI version %d.%d is too recent for this driver",
|
|
- MC_VERSION_MAJOR(version_info.version_mci),
|
|
- MC_VERSION_MINOR(version_info.version_mci));
|
|
- goto err_version;
|
|
- }
|
|
-
|
|
- if ((MC_VERSION_MAJOR(version_info.version_mci) == 0) &&
|
|
- (MC_VERSION_MINOR(version_info.version_mci) < 6)) {
|
|
- pr_err("MCI version %d.%d is too old for this driver",
|
|
- MC_VERSION_MAJOR(version_info.version_mci),
|
|
- MC_VERSION_MINOR(version_info.version_mci));
|
|
- goto err_version;
|
|
- }
|
|
-
|
|
- dev_info(g_ctx.mcd, "MobiCore MCI version is %d.%d\n",
|
|
- MC_VERSION_MAJOR(version_info.version_mci),
|
|
- MC_VERSION_MINOR(version_info.version_mci));
|
|
-
|
|
- /* Determine which features are supported */
|
|
- switch (version_info.version_mci) {
|
|
- case MC_VERSION(1, 2): /* 310 */
|
|
- g_ctx.f_client_login = true;
|
|
- /* Fall through */
|
|
- case MC_VERSION(1, 1):
|
|
- g_ctx.f_multimap = true;
|
|
- /* Fall through */
|
|
- case MC_VERSION(1, 0): /* 302 */
|
|
- g_ctx.f_mem_ext = true;
|
|
- g_ctx.f_ta_auth = true;
|
|
- /* Fall through */
|
|
- case MC_VERSION(0, 7):
|
|
- g_ctx.f_timeout = true;
|
|
- /* Fall through */
|
|
- case MC_VERSION(0, 6): /* 301 */
|
|
- break;
|
|
- }
|
|
-
|
|
- ret = device_user_init();
|
|
- if (ret)
|
|
- goto err_create_dev_user;
|
|
-
|
|
- return 0;
|
|
-
|
|
-err_create_dev_user:
|
|
-err_version:
|
|
-err_mcp_cmd:
|
|
- mc_pm_stop();
|
|
-err_pm:
|
|
- mc_scheduler_stop();
|
|
-err_sched:
|
|
- mc_logging_stop();
|
|
-err_log:
|
|
- mcp_stop();
|
|
-err_mcp:
|
|
- return ret;
|
|
-}
|
|
-
|
|
-static inline void mobicore_stop(void)
|
|
-{
|
|
- mc_pm_stop();
|
|
- mc_scheduler_stop();
|
|
- mc_logging_stop();
|
|
- mcp_stop();
|
|
-}
|
|
-
|
|
-/*
|
|
- * This function is called by the kernel during startup or by a insmod command.
|
|
- * This device is installed and registered as cdev, then interrupt and
|
|
- * queue handling is set up
|
|
- */
|
|
-static int mobicore_init(void)
|
|
-{
|
|
- int err = 0;
|
|
-
|
|
- dev_set_name(g_ctx.mcd, "TEE");
|
|
-
|
|
- /* Do not remove or change the following trace.
|
|
- * The string "MobiCore" is used to detect if <t-base is in of the image
|
|
- */
|
|
- dev_info(g_ctx.mcd, "MobiCore mcDrvModuleApi version is %d.%d\n",
|
|
- MCDRVMODULEAPI_VERSION_MAJOR, MCDRVMODULEAPI_VERSION_MINOR);
|
|
-#ifdef MOBICORE_COMPONENT_BUILD_TAG
|
|
- dev_info(g_ctx.mcd, "MobiCore %s\n", MOBICORE_COMPONENT_BUILD_TAG);
|
|
-#endif
|
|
- /* Hardware does not support ARM TrustZone -> Cannot continue! */
|
|
- if (!has_security_extensions()) {
|
|
- MCDRV_ERROR("Hardware doesn't support ARM TrustZone!");
|
|
- return -ENODEV;
|
|
- }
|
|
-
|
|
- /* Running in secure mode -> Cannot load the driver! */
|
|
- if (is_secure_mode()) {
|
|
- MCDRV_ERROR("Running in secure MODE!");
|
|
- return -ENODEV;
|
|
- }
|
|
-
|
|
- /* Init common API layer */
|
|
- api_init();
|
|
-
|
|
- /* Init plenty of nice features */
|
|
- err = mc_fastcall_init();
|
|
- if (err) {
|
|
- MCDRV_ERROR("Fastcall support init failed!");
|
|
- goto fail_fastcall_init;
|
|
- }
|
|
-
|
|
- err = mcp_init();
|
|
- if (err) {
|
|
- MCDRV_ERROR("MCP init failed!");
|
|
- goto fail_mcp_init;
|
|
- }
|
|
-
|
|
- err = mc_logging_init();
|
|
- if (err) {
|
|
- MCDRV_ERROR("Log init failed!");
|
|
- goto fail_log_init;
|
|
- }
|
|
-
|
|
- /* The scheduler is the first to create a debugfs entry */
|
|
- g_ctx.debug_dir = debugfs_create_dir("trustonic_tee", NULL);
|
|
- err = mc_scheduler_init();
|
|
- if (err) {
|
|
- MCDRV_ERROR("Scheduler init failed!");
|
|
- goto fail_mc_device_sched_init;
|
|
- }
|
|
-
|
|
- /*
|
|
- * Create admin dev so that daemon can already communicate with
|
|
- * the driver
|
|
- */
|
|
- err = device_admin_init(mobicore_start);
|
|
- if (err)
|
|
- goto fail_creat_dev_admin;
|
|
-
|
|
- return 0;
|
|
-
|
|
-fail_creat_dev_admin:
|
|
- mc_scheduler_exit();
|
|
-fail_mc_device_sched_init:
|
|
- debugfs_remove(g_ctx.debug_dir);
|
|
- mc_logging_exit();
|
|
-fail_log_init:
|
|
- mcp_exit();
|
|
-fail_mcp_init:
|
|
- mc_fastcall_exit();
|
|
-fail_fastcall_init:
|
|
- return err;
|
|
-}
|
|
-
|
|
-/*
|
|
- * This function removes this device driver from the Linux device manager .
|
|
- */
|
|
-static void mobicore_exit(void)
|
|
-{
|
|
- MCDRV_DBG("enter");
|
|
-
|
|
- devices_exit();
|
|
- mobicore_stop();
|
|
- mc_scheduler_exit();
|
|
- mc_logging_exit();
|
|
- mcp_exit();
|
|
- mc_fastcall_exit();
|
|
- debugfs_remove_recursive(g_ctx.debug_dir);
|
|
-
|
|
- MCDRV_DBG("exit");
|
|
-}
|
|
-
|
|
-/* Linux Driver Module Macros */
|
|
-
|
|
-#ifdef MC_DEVICE_PROPNAME
|
|
-
|
|
-static int mobicore_probe(struct platform_device *pdev)
|
|
-{
|
|
- g_ctx.mcd->of_node = pdev->dev.of_node;
|
|
- mobicore_init();
|
|
- return 0;
|
|
-}
|
|
-
|
|
-static const struct of_device_id of_match_table[] = {
|
|
- { .compatible = MC_DEVICE_PROPNAME },
|
|
- { }
|
|
-};
|
|
-
|
|
-static struct platform_driver mc_plat_driver = {
|
|
- .probe = mobicore_probe,
|
|
- .driver = {
|
|
- .name = "mcd",
|
|
- .owner = THIS_MODULE,
|
|
- .of_match_table = of_match_table,
|
|
- }
|
|
-};
|
|
-
|
|
-static int mobicore_register(void)
|
|
-{
|
|
- return platform_driver_register(&mc_plat_driver);
|
|
-}
|
|
-
|
|
-static void mobicore_unregister(void)
|
|
-{
|
|
- platform_driver_unregister(&mc_plat_driver);
|
|
- mobicore_exit();
|
|
-}
|
|
-
|
|
-module_init(mobicore_register);
|
|
-module_exit(mobicore_unregister);
|
|
-
|
|
-#else /* MC_DEVICE_PROPNAME */
|
|
-
|
|
-module_init(mobicore_init);
|
|
-module_exit(mobicore_exit);
|
|
-
|
|
-#endif /* !MC_DEVICE_PROPNAME */
|
|
-
|
|
-MODULE_AUTHOR("Trustonic Limited");
|
|
-MODULE_LICENSE("GPL v2");
|
|
-MODULE_DESCRIPTION("MobiCore driver");
|
|
diff --git a/drivers/gud/MobiCoreDriver/main.h b/drivers/gud/MobiCoreDriver/main.h
|
|
deleted file mode 100644
|
|
index cadc3d766147a..0000000000000
|
|
--- a/drivers/gud/MobiCoreDriver/main.h
|
|
+++ /dev/null
|
|
@@ -1,60 +0,0 @@
|
|
-/*
|
|
- * Copyright (c) 2013-2015 TRUSTONIC LIMITED
|
|
- * All Rights Reserved.
|
|
- *
|
|
- * This program is free software; you can redistribute it and/or
|
|
- * modify it under the terms of the GNU General Public License
|
|
- * version 2 as published by the Free Software Foundation.
|
|
- *
|
|
- * This program is distributed in the hope that it will be useful,
|
|
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
- * GNU General Public License for more details.
|
|
- */
|
|
-
|
|
-#ifndef _MC_MAIN_H_
|
|
-#define _MC_MAIN_H_
|
|
-
|
|
-#include <linux/slab.h> /* gfp_t */
|
|
-
|
|
-#define MC_VERSION(major, minor) \
|
|
- (((major & 0x0000ffff) << 16) | (minor & 0x0000ffff))
|
|
-#define MC_VERSION_MAJOR(x) ((x) >> 16)
|
|
-#define MC_VERSION_MINOR(x) ((x) & 0xffff)
|
|
-
|
|
-/* MobiCore Driver Kernel Module context data. */
|
|
-struct mc_device_ctx {
|
|
- struct device *mcd;
|
|
- /* debugfs root */
|
|
- struct dentry *debug_dir;
|
|
-
|
|
- /* GP sessions waiting final close notif */
|
|
- struct list_head closing_sess;
|
|
- struct mutex closing_lock; /* Closing sessions list */
|
|
-
|
|
- /* Features */
|
|
- /* - SWd can set a time out to get scheduled at a future time */
|
|
- bool f_timeout;
|
|
- /* - SWd supports memory extension which allows for bigger TAs */
|
|
- bool f_mem_ext;
|
|
- /* - SWd supports TA authorisation */
|
|
- bool f_ta_auth;
|
|
- /* - SWd can map several buffers at once */
|
|
- bool f_multimap;
|
|
- /* - SWd supports GP client authentication */
|
|
- bool f_client_login;
|
|
-};
|
|
-
|
|
-extern struct mc_device_ctx g_ctx;
|
|
-
|
|
-struct kasnprintf_buf {
|
|
- gfp_t gfp;
|
|
- void *buf;
|
|
- int size;
|
|
- int off;
|
|
-};
|
|
-
|
|
-extern __printf(2, 3)
|
|
-int kasnprintf(struct kasnprintf_buf *buf, const char *fmt, ...);
|
|
-
|
|
-#endif /* _MC_MAIN_H_ */
|
|
diff --git a/drivers/gud/MobiCoreDriver/mci/mcifc.h b/drivers/gud/MobiCoreDriver/mci/mcifc.h
|
|
deleted file mode 100644
|
|
index 4848c9e047fba..0000000000000
|
|
--- a/drivers/gud/MobiCoreDriver/mci/mcifc.h
|
|
+++ /dev/null
|
|
@@ -1,144 +0,0 @@
|
|
-/*
|
|
- * Copyright (c) 2013-2014 TRUSTONIC LIMITED
|
|
- * All Rights Reserved.
|
|
- *
|
|
- * This program is free software; you can redistribute it and/or
|
|
- * modify it under the terms of the GNU General Public License
|
|
- * version 2 as published by the Free Software Foundation.
|
|
- *
|
|
- * This program is distributed in the hope that it will be useful,
|
|
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
- * GNU General Public License for more details.
|
|
- */
|
|
-#ifndef MCIFC_H_
|
|
-#define MCIFC_H_
|
|
-
|
|
-#include "platform.h"
|
|
-
|
|
-/** @name MobiCore FastCall Defines
|
|
- * Defines for the two different FastCall's.
|
|
- */
|
|
-/** @{ */
|
|
-
|
|
-#include "platform.h"
|
|
-
|
|
-/* --- global ---- */
|
|
-#define MC_FC_INVALID ((uint32_t)0) /**< Invalid FastCall ID */
|
|
-
|
|
-#if defined(CONFIG_ARM64) && !defined(MC_ARMV7_FC)
|
|
-
|
|
-/* These should be handled as 64-bit FCs; now they are more like 32bits... */
|
|
-#define MC_FC_STD64_BASE ((uint32_t)0xFF000000)
|
|
-#define MC_FC_STD64(x) ((uint32_t)(MC_FC_STD64_BASE + (x)))
|
|
-
|
|
-#define MC_FC_INIT MC_FC_STD64(1) /**< Initializing FastCall. */
|
|
-#define MC_FC_INFO MC_FC_STD64(2) /**< Info FastCall. */
|
|
-#define MC_FC_MEM_TRACE MC_FC_STD64(10) /**< Enable SWd tracing via memory */
|
|
-#define MC_FC_SWAP_CPU MC_FC_STD64(54) /**< Change new active Core */
|
|
-
|
|
-#else
|
|
-
|
|
-#define MC_FC_INIT ((uint32_t)(-1)) /**< Initializing FastCall. */
|
|
-#define MC_FC_INFO ((uint32_t)(-2)) /**< Info FastCall. */
|
|
-#define MC_FC_MEM_TRACE ((uint32_t)(-31)) /**< Enable SWd tracing via memory */
|
|
-#define MC_FC_SWAP_CPU ((uint32_t)(0x84000005)) /**< Change new active Core */
|
|
-
|
|
-#endif
|
|
-
|
|
-/** @} */
|
|
-
|
|
-/** @name MobiCore SMC Defines
|
|
- * Defines the different secure monitor calls (SMC) for world switching.
|
|
- * @{ */
|
|
-/**< Yield to switch from NWd to SWd. */
|
|
-#define MC_SMC_N_YIELD 3
|
|
-/**< SIQ to switch from NWd to SWd. */
|
|
-#define MC_SMC_N_SIQ 4
|
|
-/** @} */
|
|
-
|
|
-/** @name MobiCore status
|
|
- * MobiCore status information.
|
|
- * @{ */
|
|
-/**< MobiCore is not yet initialized. FastCall FcInit() to set up MobiCore.*/
|
|
-#define MC_STATUS_NOT_INITIALIZED 0
|
|
-/**< Bad parameters have been passed in FcInit(). */
|
|
-#define MC_STATUS_BAD_INIT 1
|
|
-/**< MobiCore did initialize properly. */
|
|
-#define MC_STATUS_INITIALIZED 2
|
|
-/**< MobiCore kernel halted due to an unrecoverable exception. Further
|
|
- * information is available extended info */
|
|
-#define MC_STATUS_HALT 3
|
|
-/** @} */
|
|
-
|
|
-/** @name Extended Info Identifiers
|
|
- * Extended info parameters for MC_FC_INFO to obtain further information depending on MobiCore state.
|
|
- * @{ */
|
|
-/**< Version of the MobiCore Control Interface (MCI) */
|
|
-#define MC_EXT_INFO_ID_MCI_VERSION 0
|
|
-/**< MobiCore control flags */
|
|
-#define MC_EXT_INFO_ID_FLAGS 1
|
|
-/**< MobiCore halt condition code */
|
|
-#define MC_EXT_INFO_ID_HALT_CODE 2
|
|
-/**< MobiCore halt condition instruction pointer */
|
|
-#define MC_EXT_INFO_ID_HALT_IP 3
|
|
-/**< MobiCore fault counter */
|
|
-#define MC_EXT_INFO_ID_FAULT_CNT 4
|
|
-/**< MobiCore last fault cause */
|
|
-#define MC_EXT_INFO_ID_FAULT_CAUSE 5
|
|
-/**< MobiCore last fault meta */
|
|
-#define MC_EXT_INFO_ID_FAULT_META 6
|
|
-/**< MobiCore last fault threadid */
|
|
-#define MC_EXT_INFO_ID_FAULT_THREAD 7
|
|
-/**< MobiCore last fault instruction pointer */
|
|
-#define MC_EXT_INFO_ID_FAULT_IP 8
|
|
-/**< MobiCore last fault stack pointer */
|
|
-#define MC_EXT_INFO_ID_FAULT_SP 9
|
|
-/**< MobiCore last fault ARM arch information */
|
|
-#define MC_EXT_INFO_ID_FAULT_ARCH_DFSR 10
|
|
-/**< MobiCore last fault ARM arch information */
|
|
-#define MC_EXT_INFO_ID_FAULT_ARCH_ADFSR 11
|
|
-/**< MobiCore last fault ARM arch information */
|
|
-#define MC_EXT_INFO_ID_FAULT_ARCH_DFAR 12
|
|
-/**< MobiCore last fault ARM arch information */
|
|
-#define MC_EXT_INFO_ID_FAULT_ARCH_IFSR 13
|
|
-/**< MobiCore last fault ARM arch information */
|
|
-#define MC_EXT_INFO_ID_FAULT_ARCH_AIFSR 14
|
|
-/**< MobiCore last fault ARM arch information */
|
|
-#define MC_EXT_INFO_ID_FAULT_ARCH_IFAR 15
|
|
-/**< MobiCore configured by Daemon via fc_init flag */
|
|
-#define MC_EXT_INFO_ID_MC_CONFIGURED 16
|
|
-/**< MobiCore scheduling status: idle/non-idle */
|
|
-#define MC_EXT_INFO_ID_MC_SCHED_STATUS 17
|
|
-/**< MobiCore runtime status: initialized, halted */
|
|
-#define MC_EXT_INFO_ID_MC_STATUS 18
|
|
-/**< MobiCore exception handler last partner */
|
|
-#define MC_EXT_INFO_ID_MC_EXC_PARTNER 19
|
|
-/**< MobiCore exception handler last peer */
|
|
-#define MC_EXT_INFO_ID_MC_EXC_IPCPEER 20
|
|
-/**< MobiCore exception handler last IPC message */
|
|
-#define MC_EXT_INFO_ID_MC_EXC_IPCMSG 21
|
|
-/**< MobiCore exception handler last IPC data */
|
|
-#define MC_EXT_INFO_ID_MC_EXC_IPCDATA 22
|
|
-/**< MobiCore exception handler last UUID (uses 4 slots: 23 to 26) */
|
|
-#define MC_EXT_INFO_ID_MC_EXC_UUID 23
|
|
-#define MC_EXT_INFO_ID_MC_EXC_UUID1 24
|
|
-#define MC_EXT_INFO_ID_MC_EXC_UUID2 25
|
|
-#define MC_EXT_INFO_ID_MC_EXC_UUID3 26
|
|
-
|
|
-/** @} */
|
|
-
|
|
-/** @name FastCall return values
|
|
- * Return values of the MobiCore FastCalls.
|
|
- * @{ */
|
|
-/**< No error. Everything worked fine. */
|
|
-#define MC_FC_RET_OK 0
|
|
-/**< FastCall was not successful. */
|
|
-#define MC_FC_RET_ERR_INVALID 1
|
|
-/**< MobiCore has already been initialized. */
|
|
-#define MC_FC_RET_ERR_ALREADY_INITIALIZED 5
|
|
-/** @} */
|
|
-
|
|
-#endif /** MCIFC_H_ */
|
|
-
|
|
-/** @} */
|
|
diff --git a/drivers/gud/MobiCoreDriver/mci/mcimcp.h b/drivers/gud/MobiCoreDriver/mci/mcimcp.h
|
|
deleted file mode 100644
|
|
index 3eb2efea2c30c..0000000000000
|
|
--- a/drivers/gud/MobiCoreDriver/mci/mcimcp.h
|
|
+++ /dev/null
|
|
@@ -1,508 +0,0 @@
|
|
-/*
|
|
- * Copyright (c) 2013-2015 TRUSTONIC LIMITED
|
|
- * All Rights Reserved.
|
|
- *
|
|
- * This program is free software; you can redistribute it and/or
|
|
- * modify it under the terms of the GNU General Public License
|
|
- * version 2 as published by the Free Software Foundation.
|
|
- *
|
|
- * This program is distributed in the hope that it will be useful,
|
|
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
- * GNU General Public License for more details.
|
|
- */
|
|
-
|
|
-#ifndef MCP_H_
|
|
-#define MCP_H_
|
|
-
|
|
-#include "mci/mcloadformat.h"
|
|
-
|
|
-/** Indicates a response */
|
|
-#define FLAG_RESPONSE BIT(31)
|
|
-
|
|
-/** Maximum number of buffers that can be mapped at once */
|
|
-#define MCP_MAP_MAX_BUF 4
|
|
-
|
|
-/** MobiCore Return Code Defines.
|
|
- * List of the possible MobiCore return codes.
|
|
- */
|
|
-enum mcp_result {
|
|
- /** Memory has successfully been mapped */
|
|
- MC_MCP_RET_OK = 0,
|
|
- /** The session ID is invalid */
|
|
- MC_MCP_RET_ERR_INVALID_SESSION = 1,
|
|
- /** The UUID of the Trustlet is unknown */
|
|
- MC_MCP_RET_ERR_UNKNOWN_UUID = 2,
|
|
- /** The ID of the driver is unknown */
|
|
- MC_MCP_RET_ERR_UNKNOWN_DRIVER_ID = 3,
|
|
- /** No more session are allowed */
|
|
- MC_MCP_RET_ERR_NO_MORE_SESSIONS = 4,
|
|
- /** The container is invalid */
|
|
- MC_MCP_RET_ERR_CONTAINER_INVALID = 5,
|
|
- /** The Trustlet is invalid */
|
|
- MC_MCP_RET_ERR_TRUSTLET_INVALID = 6,
|
|
- /** The memory block has already been mapped before */
|
|
- MC_MCP_RET_ERR_ALREADY_MAPPED = 7,
|
|
- /** Alignment or length error in the command parameters */
|
|
- MC_MCP_RET_ERR_INVALID_PARAM = 8,
|
|
- /** No space left in the virtual address space of the session */
|
|
- MC_MCP_RET_ERR_OUT_OF_RESOURCES = 9,
|
|
- /** WSM type unknown or broken WSM */
|
|
- MC_MCP_RET_ERR_INVALID_WSM = 10,
|
|
- /** unknown error */
|
|
- MC_MCP_RET_ERR_UNKNOWN = 11,
|
|
- /** Length of map invalid */
|
|
- MC_MCP_RET_ERR_INVALID_MAPPING_LENGTH = 12,
|
|
- /** Map can only be applied to Trustlet session */
|
|
- MC_MCP_RET_ERR_MAPPING_TARGET = 13,
|
|
- /** Couldn't open crypto session */
|
|
- MC_MCP_RET_ERR_OUT_OF_CRYPTO_RESOURCES = 14,
|
|
- /** System Trustlet signature verification failed */
|
|
- MC_MCP_RET_ERR_SIGNATURE_VERIFICATION_FAILED = 15,
|
|
- /** System Trustlet public key is wrong */
|
|
- MC_MCP_RET_ERR_WRONG_PUBLIC_KEY = 16,
|
|
- /** Wrong containter type(s) */
|
|
- MC_MCP_RET_ERR_CONTAINER_TYPE_MISMATCH = 17,
|
|
- /** Container is locked (or not activated) */
|
|
- MC_MCP_RET_ERR_CONTAINER_LOCKED = 18,
|
|
- /** SPID is not registered with root container */
|
|
- MC_MCP_RET_ERR_SP_NO_CHILD = 19,
|
|
- /** UUID is not registered with sp container */
|
|
- MC_MCP_RET_ERR_TL_NO_CHILD = 20,
|
|
- /** Unwrapping of root container failed */
|
|
- MC_MCP_RET_ERR_UNWRAP_ROOT_FAILED = 21,
|
|
- /** Unwrapping of service provider container failed */
|
|
- MC_MCP_RET_ERR_UNWRAP_SP_FAILED = 22,
|
|
- /** Unwrapping of Trustlet container failed */
|
|
- MC_MCP_RET_ERR_UNWRAP_TRUSTLET_FAILED = 23,
|
|
- /** Container version mismatch */
|
|
- MC_MCP_RET_ERR_CONTAINER_VERSION_MISMATCH = 24,
|
|
- /** Decryption of service provider trustlet failed */
|
|
- MC_MCP_RET_ERR_SP_TL_DECRYPTION_FAILED = 25,
|
|
- /** Hash check of service provider trustlet failed */
|
|
- MC_MCP_RET_ERR_SP_TL_HASH_CHECK_FAILED = 26,
|
|
- /** Activation/starting of task failed */
|
|
- MC_MCP_RET_ERR_LAUNCH_TASK_FAILED = 27,
|
|
- /** Closing of task not yet possible, try again later */
|
|
- MC_MCP_RET_ERR_CLOSE_TASK_FAILED = 28,
|
|
- /**< Service is blocked and a session cannot be opened to it */
|
|
- MC_MCP_RET_ERR_SERVICE_BLOCKED = 29,
|
|
- /**< Service is locked and a session cannot be opened to it */
|
|
- MC_MCP_RET_ERR_SERVICE_LOCKED = 30,
|
|
- /**< Service was forcefully killed (due to an administrative command) */
|
|
- MC_MCP_RET_ERR_SERVICE_KILLED = 31,
|
|
- /** The command is unknown */
|
|
- MC_MCP_RET_ERR_UNKNOWN_COMMAND = 50,
|
|
- /** The command data is invalid */
|
|
- MC_MCP_RET_ERR_INVALID_DATA = 51
|
|
-};
|
|
-
|
|
-/** Possible MCP Command IDs
|
|
- * Command ID must be between 0 and 0x7FFFFFFF.
|
|
- */
|
|
-enum cmd_id {
|
|
- /** Invalid command ID */
|
|
- MC_MCP_CMD_ID_INVALID = 0x00,
|
|
- /** Open a session */
|
|
- MC_MCP_CMD_OPEN_SESSION = 0x01,
|
|
- /** Close an existing session */
|
|
- MC_MCP_CMD_CLOSE_SESSION = 0x03,
|
|
- /** Map WSM to session */
|
|
- MC_MCP_CMD_MAP = 0x04,
|
|
- /** Unmap WSM from session */
|
|
- MC_MCP_CMD_UNMAP = 0x05,
|
|
- /** Prepare for suspend */
|
|
- MC_MCP_CMD_SUSPEND = 0x06,
|
|
- /** Resume from suspension */
|
|
- MC_MCP_CMD_RESUME = 0x07,
|
|
- /** Get MobiCore version information */
|
|
- MC_MCP_CMD_GET_MOBICORE_VERSION = 0x09,
|
|
- /** Close MCP and unmap MCI */
|
|
- MC_MCP_CMD_CLOSE_MCP = 0x0A,
|
|
- /** Load token for device attestation */
|
|
- MC_MCP_CMD_LOAD_TOKEN = 0x0B,
|
|
- /** Check that TA can be loaded */
|
|
- MC_MCP_CMD_CHECK_LOAD_TA = 0x0C,
|
|
- /** Map multiple WSMs to session */
|
|
- MC_MCP_CMD_MULTIMAP = 0x0D,
|
|
- /** Unmap multiple WSMs to session */
|
|
- MC_MCP_CMD_MULTIUNMAP = 0x0E,
|
|
-};
|
|
-
|
|
-/*
|
|
- * Types of WSM known to the MobiCore.
|
|
- */
|
|
-#define WSM_TYPE_MASK 0xFF
|
|
-#define WSM_INVALID 0 /** Invalid memory type */
|
|
-#define WSM_L2 2 /** Buffer mapping uses L2/L3 table */
|
|
-#define WSM_L1 3 /** Buffer mapping uses fake L1 table */
|
|
-
|
|
-/** Magic number used to identify if Open Command supports GP client
|
|
- * authentication.
|
|
- */
|
|
-#define MC_GP_CLIENT_AUTH_MAGIC 0x47504131 /* "GPA1" */
|
|
-
|
|
-/** Command header.
|
|
- * It just contains the command ID. Only values specified in cmd_id are
|
|
- * allowed as command IDs. If the command ID is unspecified the MobiCore
|
|
- * returns an empty response with the result set to
|
|
- * MC_MCP_RET_ERR_UNKNOWN_COMMAND.
|
|
- */
|
|
-struct cmd_header {
|
|
- enum cmd_id cmd_id; /** Command ID of the command */
|
|
-};
|
|
-
|
|
-/** Response header.
|
|
- * MobiCore will reply to every MCP command with an MCP response. Like the MCP
|
|
- * command the response consists of a header followed by response data. The
|
|
- * response is written to the same memory location as the MCP command.
|
|
- */
|
|
-struct rsp_header {
|
|
- uint32_t rsp_id; /** Command ID | FLAG_RESPONSE */
|
|
- enum mcp_result result; /** Result of the command execution */
|
|
-};
|
|
-
|
|
-/** @defgroup CMD MCP Commands
|
|
- */
|
|
-
|
|
-/** @defgroup ASMCMD Administrative Commands
|
|
- */
|
|
-
|
|
-/** @defgroup MCPGETMOBICOREVERSION GET_MOBICORE_VERSION
|
|
- * Get MobiCore version info.
|
|
- *
|
|
- */
|
|
-
|
|
-/** Get MobiCore Version Command */
|
|
-struct cmd_get_version {
|
|
- struct cmd_header cmd_header; /** Command header */
|
|
-};
|
|
-
|
|
-/** Get MobiCore Version Command Response */
|
|
-struct rsp_get_version {
|
|
- struct rsp_header rsp_header; /** Response header */
|
|
- struct mc_version_info version_info; /** MobiCore version info */
|
|
-};
|
|
-
|
|
-/** @defgroup POWERCMD Power Management Commands
|
|
- */
|
|
-
|
|
-/** @defgroup MCPSUSPEND SUSPEND
|
|
- * Prepare MobiCore suspension.
|
|
- * This command allows MobiCore and MobiCore drivers to release or clean
|
|
- * resources and save device state.
|
|
- *
|
|
- */
|
|
-
|
|
-/** Suspend Command */
|
|
-struct cmd_suspend {
|
|
- struct cmd_header cmd_header; /** Command header */
|
|
-};
|
|
-
|
|
-/** Suspend Command Response */
|
|
-struct rsp_suspend {
|
|
- struct rsp_header rsp_header; /** Response header */
|
|
-};
|
|
-
|
|
-/** @defgroup MCPRESUME RESUME
|
|
- * Resume MobiCore from suspension.
|
|
- * This command allows MobiCore and MobiCore drivers to reinitialize hardware
|
|
- * affected by suspension.
|
|
- *
|
|
- */
|
|
-
|
|
-/** Resume Command */
|
|
-struct cmd_resume {
|
|
- struct cmd_header cmd_header; /** Command header */
|
|
-};
|
|
-
|
|
-/** Resume Command Response */
|
|
-struct rsp_resume {
|
|
- struct rsp_header rsp_header; /** Response header */
|
|
-};
|
|
-
|
|
-/** @defgroup SESSCMD Session Management Commands
|
|
- */
|
|
-
|
|
-/** @defgroup MCPOPEN OPEN
|
|
- * Load and open a session to a Trustlet.
|
|
- * The OPEN command loads Trustlet data to the MobiCore context and opens a
|
|
- * session to the Trustlet. If wsm_data_type is WSM_INVALID MobiCore tries to
|
|
- * start a pre-installed Trustlet associated with the uuid passed. The uuid
|
|
- * passed must match the uuid contained in the load data (if available).
|
|
- * On success, MobiCore returns the session ID which can be used for further
|
|
- * communication.
|
|
- */
|
|
-
|
|
-/** GP client authentication data */
|
|
-struct cmd_open_data {
|
|
- uint32_t mclf_magic; /** ASCII "MCLF" on older versions */
|
|
- struct identity identity; /** Login method and data */
|
|
-};
|
|
-
|
|
-/** Open Command */
|
|
-struct cmd_open {
|
|
- struct cmd_header cmd_header; /** Command header */
|
|
- struct mc_uuid_t uuid; /** Service UUID */
|
|
- uint8_t unused[4]; /** Padding to be 64-bit aligned */
|
|
- uint64_t adr_tci_buffer; /** Physical address of the TCI MMU */
|
|
- uint64_t adr_load_data; /** Physical address of the data MMU */
|
|
- uint32_t ofs_tci_buffer; /** Offset to the data */
|
|
- uint32_t len_tci_buffer; /** Length of the TCI */
|
|
- uint32_t wsmtype_tci; /** Type of WSM used for the TCI */
|
|
- uint32_t wsm_data_type; /** Type of MMU */
|
|
- uint32_t ofs_load_data; /** Offset to the data */
|
|
- uint32_t len_load_data; /** Length of the data to load */
|
|
- union {
|
|
- struct cmd_open_data cmd_open_data; /** Client login data */
|
|
- union mclf_header tl_header; /** Service header */
|
|
- };
|
|
- uint32_t is_gpta; /** true if looking for an SD/GP-TA */
|
|
-};
|
|
-
|
|
-/** Open Command Response */
|
|
-struct rsp_open {
|
|
- struct rsp_header rsp_header; /** Response header */
|
|
- uint32_t session_id; /** Session ID */
|
|
-};
|
|
-
|
|
-/** TA Load Check Command */
|
|
-struct cmd_check_load {
|
|
- struct cmd_header cmd_header; /** Command header */
|
|
- struct mc_uuid_t uuid; /** Service UUID */
|
|
- uint64_t adr_load_data; /** Physical address of the data */
|
|
- uint32_t wsm_data_type; /** Type of MMU */
|
|
- uint32_t ofs_load_data; /** Offset to the data */
|
|
- uint32_t len_load_data; /** Length of the data to load */
|
|
- union mclf_header tl_header; /** Service header */
|
|
-};
|
|
-
|
|
-/** TA Load Check Response */
|
|
-struct rsp_check_load {
|
|
- struct rsp_header rsp_header; /** Response header */
|
|
-};
|
|
-
|
|
-/** @defgroup MCPCLOSE CLOSE
|
|
- * Close an existing session to a Trustlet.
|
|
- * The CLOSE command terminates a session and frees all resources in the
|
|
- * MobiCore system which are currently occupied by the session. Before closing
|
|
- * the session, the MobiCore runtime management waits until all pending
|
|
- * operations, like calls to drivers, invoked by the Trustlet have been
|
|
- * terminated. Mapped memory will automatically be unmapped from the MobiCore
|
|
- * context. The NWd is responsible for processing the freed memory according to
|
|
- * the Rich-OS needs.
|
|
- *
|
|
- */
|
|
-
|
|
-/** Close Command */
|
|
-struct cmd_close {
|
|
- struct cmd_header cmd_header; /** Command header */
|
|
- uint32_t session_id; /** Session ID */
|
|
-};
|
|
-
|
|
-/** Close Command Response */
|
|
-struct rsp_close {
|
|
- struct rsp_header rsp_header; /** Response header */
|
|
-};
|
|
-
|
|
-/** @defgroup MCPMAP MAP
|
|
- * Map a portion of memory to a session.
|
|
- * The MAP command provides a block of memory to the context of a service.
|
|
- * The memory then becomes world-shared memory (WSM).
|
|
- * The only allowed memory type here is WSM_L2.
|
|
- */
|
|
-
|
|
-/** Map Command */
|
|
-struct cmd_map {
|
|
- struct cmd_header cmd_header; /** Command header */
|
|
- uint32_t session_id; /** Session ID */
|
|
- uint32_t wsm_type; /** Type of MMU */
|
|
- uint32_t ofs_buffer; /** Offset to the payload */
|
|
- uint64_t adr_buffer; /** Physical address of the MMU */
|
|
- uint32_t len_buffer; /** Length of the buffer */
|
|
-};
|
|
-
|
|
-#define MCP_MAP_MAX 0x100000 /** Maximum length for MCP map */
|
|
-
|
|
-/** Map Command Response */
|
|
-struct rsp_map {
|
|
- struct rsp_header rsp_header; /** Response header */
|
|
- /** Virtual address the WSM is mapped to, may include an offset! */
|
|
- uint32_t secure_va;
|
|
-};
|
|
-
|
|
-/** @defgroup MCPUNMAP UNMAP
|
|
- * Unmap a portion of world-shared memory from a session.
|
|
- * The UNMAP command is used to unmap a previously mapped block of
|
|
- * world shared memory from the context of a session.
|
|
- *
|
|
- * Attention: The memory block will be immediately unmapped from the specified
|
|
- * session. If the service is still accessing the memory, the service will
|
|
- * trigger a segmentation fault.
|
|
- */
|
|
-
|
|
-/** Unmap Command */
|
|
-struct cmd_unmap {
|
|
- struct cmd_header cmd_header; /** Command header */
|
|
- uint32_t session_id; /** Session ID */
|
|
- uint32_t wsm_type; /** Type of WSM used of the memory */
|
|
- /** Virtual address the WSM is mapped to, may include an offset! */
|
|
- uint32_t secure_va;
|
|
- uint32_t virtual_buffer_len; /** Length of virtual buffer */
|
|
-};
|
|
-
|
|
-/** Unmap Command Response */
|
|
-struct rsp_unmap {
|
|
- struct rsp_header rsp_header; /** Response header */
|
|
-};
|
|
-
|
|
-/** @defgroup MCPLOADTOKEN
|
|
- * Load a token from the normal world and share it with <t-base
|
|
- * If something fails, the device attestation functionality will be disabled
|
|
- */
|
|
-
|
|
-/** Load Token */
|
|
-struct cmd_load_token {
|
|
- struct cmd_header cmd_header; /** Command header */
|
|
- uint32_t wsm_data_type; /** Type of MMU */
|
|
- uint64_t adr_load_data; /** Physical address of the MMU */
|
|
- uint64_t ofs_load_data; /** Offset to the data */
|
|
- uint64_t len_load_data; /** Length of the data */
|
|
-};
|
|
-
|
|
-/** Load Token Command Response */
|
|
-struct rsp_load_token {
|
|
- struct rsp_header rsp_header; /** Response header */
|
|
-};
|
|
-
|
|
-/** @defgroup MCPMULTIMAP MULTIMAP
|
|
- * Map up to MCP_MAP_MAX_BUF portions of memory to a session.
|
|
- * The MULTIMAP command provides MCP_MAP_MAX_BUF blocks of memory to the context
|
|
- * of a service.
|
|
- * The memory then becomes world-shared memory (WSM).
|
|
- * The only allowed memory type here is WSM_L2.
|
|
- * @{ */
|
|
-
|
|
-/** NWd physical buffer description
|
|
- *
|
|
- * Note: Information is coming from NWd kernel. So it should not be trusted
|
|
- * more than NWd kernel is trusted.
|
|
- */
|
|
-struct buffer_map {
|
|
- uint64_t adr_buffer; /**< Physical address */
|
|
- uint32_t ofs_buffer; /**< Offset of buffer */
|
|
- uint32_t len_buffer; /**< Length of buffer */
|
|
- uint32_t wsm_type; /**< Type of address */
|
|
-};
|
|
-
|
|
-/** MultiMap Command */
|
|
-struct cmd_multimap {
|
|
- struct cmd_header cmd_header; /** Command header */
|
|
- uint32_t session_id; /** Session ID */
|
|
- struct buffer_map bufs[MC_MAP_MAX]; /** NWd buffer info */
|
|
-};
|
|
-
|
|
-/** Multimap Command Response */
|
|
-struct rsp_multimap {
|
|
- struct rsp_header rsp_header; /** Response header */
|
|
- /** Virtual address the WSM is mapped to, may include an offset! */
|
|
- uint64_t secure_va[MC_MAP_MAX];
|
|
-};
|
|
-
|
|
-/** @defgroup MCPMULTIUNMAP MULTIUNMAP
|
|
- * Unmap up to MCP_MAP_MAX_BUF portions of world-shared memory from a session.
|
|
- * The MULTIUNMAP command is used to unmap MCP_MAP_MAX_BUF previously mapped
|
|
- * blocks of world shared memory from the context of a session.
|
|
- *
|
|
- * Attention: The memory blocks will be immediately unmapped from the specified
|
|
- * session. If the service is still accessing the memory, the service will
|
|
- * trigger a segmentation fault.
|
|
- * @{ */
|
|
-
|
|
-/** NWd mapped buffer description
|
|
- *
|
|
- * Note: Information is coming from NWd kernel. So it should not be trusted more
|
|
- * than NWd kernel is trusted.
|
|
- */
|
|
-struct buffer_unmap {
|
|
- uint64_t secure_va; /**< Secure virtual address */
|
|
- uint32_t len_buffer; /**< Length of buffer */
|
|
-};
|
|
-
|
|
-/** Multiunmap Command */
|
|
-struct cmd_multiunmap {
|
|
- struct cmd_header cmd_header; /** Command header */
|
|
- uint32_t session_id; /** Session ID */
|
|
- struct buffer_unmap bufs[MC_MAP_MAX]; /** NWd buffer info */
|
|
-};
|
|
-
|
|
-/** Multiunmap Command Response */
|
|
-struct rsp_multiunmap {
|
|
- struct rsp_header rsp_header; /** Response header */
|
|
-};
|
|
-
|
|
-/** Structure of the MCP buffer */
|
|
-union mcp_message {
|
|
- struct cmd_header cmd_header; /** Command header */
|
|
- struct rsp_header rsp_header;
|
|
- struct cmd_open cmd_open; /** Load and open service */
|
|
- struct rsp_open rsp_open;
|
|
- struct cmd_close cmd_close; /** Close command */
|
|
- struct rsp_close rsp_close;
|
|
- struct cmd_map cmd_map; /** Map WSM to service */
|
|
- struct rsp_map rsp_map;
|
|
- struct cmd_unmap cmd_unmap; /** Unmap WSM from service */
|
|
- struct rsp_unmap rsp_unmap;
|
|
- struct cmd_suspend cmd_suspend; /** Suspend MobiCore */
|
|
- struct rsp_suspend rsp_suspend;
|
|
- struct cmd_resume cmd_resume; /** Resume MobiCore */
|
|
- struct rsp_resume rsp_resume;
|
|
- struct cmd_get_version cmd_get_version; /** Get MobiCore Version */
|
|
- struct rsp_get_version rsp_get_version;
|
|
- struct cmd_load_token cmd_load_token; /** Load token */
|
|
- struct rsp_load_token rsp_load_token;
|
|
- struct cmd_check_load cmd_check_load; /** TA load check */
|
|
- struct rsp_check_load rsp_check_load;
|
|
- struct cmd_multimap cmd_multimap; /** Map multiple WSMs */
|
|
- struct rsp_multimap rsp_multimap;
|
|
- struct cmd_multiunmap cmd_multiunmap; /** Map multiple WSMs */
|
|
- struct rsp_multiunmap rsp_multiunmap;
|
|
-};
|
|
-
|
|
-/** Minimum MCP buffer length (in bytes) */
|
|
-#define MIN_MCP_LEN sizeof(mcp_message_t)
|
|
-
|
|
-#define MC_FLAG_NO_SLEEP_REQ 0
|
|
-#define MC_FLAG_REQ_TO_SLEEP 1
|
|
-
|
|
-#define MC_STATE_NORMAL_EXECUTION 0
|
|
-#define MC_STATE_READY_TO_SLEEP 1
|
|
-
|
|
-struct sleep_mode {
|
|
- uint16_t sleep_req; /** Ask SWd to get ready to sleep */
|
|
- uint16_t ready_to_sleep; /** SWd is now ready to sleep */
|
|
-};
|
|
-
|
|
-/** MobiCore status flags */
|
|
-struct mcp_flags {
|
|
- /** If not MC_FLAG_SCHEDULE_IDLE, MobiCore needsscheduling */
|
|
- uint32_t schedule;
|
|
- struct sleep_mode sleep_mode;
|
|
- /** Secure-world sleep timeout in milliseconds */
|
|
- int32_t timeout_ms;
|
|
- /** Reserved for future use: Must not be interpreted */
|
|
- uint32_t RFU3;
|
|
-};
|
|
-
|
|
-/** MobiCore is idle. No scheduling required */
|
|
-#define MC_FLAG_SCHEDULE_IDLE 0
|
|
-/** MobiCore is non idle, scheduling is required */
|
|
-#define MC_FLAG_SCHEDULE_NON_IDLE 1
|
|
-
|
|
-/** MCP buffer structure */
|
|
-struct mcp_buffer {
|
|
- struct mcp_flags mc_flags; /** MobiCore Flags */
|
|
- union mcp_message mcp_message; /** MCP message buffer */
|
|
-};
|
|
-
|
|
-#endif /* MCP_H_ */
|
|
diff --git a/drivers/gud/MobiCoreDriver/mci/mcinq.h b/drivers/gud/MobiCoreDriver/mci/mcinq.h
|
|
deleted file mode 100644
|
|
index 9f08b190d3222..0000000000000
|
|
--- a/drivers/gud/MobiCoreDriver/mci/mcinq.h
|
|
+++ /dev/null
|
|
@@ -1,86 +0,0 @@
|
|
-/*
|
|
- * Copyright (c) 2013-2015 TRUSTONIC LIMITED
|
|
- * All Rights Reserved.
|
|
- *
|
|
- * This program is free software; you can redistribute it and/or
|
|
- * modify it under the terms of the GNU General Public License
|
|
- * version 2 as published by the Free Software Foundation.
|
|
- *
|
|
- * This program is distributed in the hope that it will be useful,
|
|
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
- * GNU General Public License for more details.
|
|
- */
|
|
-
|
|
-#ifndef NQ_H_
|
|
-#define NQ_H_
|
|
-
|
|
-/** \name NQ Size Defines
|
|
- * Minimum and maximum count of elements in the notification queue.
|
|
- */
|
|
-#define MIN_NQ_ELEM 1 /** Minimum notification queue elements */
|
|
-#define MAX_NQ_ELEM 64 /** Maximum notification queue elements */
|
|
-
|
|
-/** \name NQ Length Defines
|
|
- * Minimum and maximum notification queue length.
|
|
- */
|
|
-/** Minimum notification length (in bytes) */
|
|
-#define MIN_NQ_LEN (MIN_NQ_ELEM * sizeof(struct notification))
|
|
-/** Maximum notification length (in bytes) */
|
|
-#define MAX_NQ_LEN (MAX_NQ_ELEM * sizeof(struct notification))
|
|
-
|
|
-/** \name Session ID Defines
|
|
- * Standard Session IDs.
|
|
- */
|
|
-/** MCP session ID, used to communicate with MobiCore (e.g. to start/stop TA) */
|
|
-#define SID_MCP 0
|
|
-/** Invalid session id, returned in case of error */
|
|
-#define SID_INVALID 0xffffffff
|
|
-
|
|
-/** Notification data structure */
|
|
-struct notification {
|
|
- uint32_t session_id; /** Session ID */
|
|
- int32_t payload; /** Additional notification info */
|
|
-};
|
|
-
|
|
-/** Notification payload codes.
|
|
- * 0 indicated a plain simple notification,
|
|
- * a positive value is a termination reason from the task,
|
|
- * a negative value is a termination reason from MobiCore.
|
|
- * Possible negative values are given below.
|
|
- */
|
|
-enum notification_payload {
|
|
- /** task terminated, but exit code is invalid */
|
|
- ERR_INVALID_EXIT_CODE = -1,
|
|
- /** task terminated due to session end, no exit code available */
|
|
- ERR_SESSION_CLOSE = -2,
|
|
- /** task terminated due to invalid operation */
|
|
- ERR_INVALID_OPERATION = -3,
|
|
- /** session ID is unknown */
|
|
- ERR_INVALID_SID = -4,
|
|
- /** session is not active */
|
|
- ERR_SID_NOT_ACTIVE = -5,
|
|
- /** session was force-killed (due to an administrative command). */
|
|
- ERR_SESSION_KILLED = -6,
|
|
-};
|
|
-
|
|
-/** Declaration of the notification queue header.
|
|
- * layout as specified in the data structure specification.
|
|
- */
|
|
-struct notification_queue_header {
|
|
- uint32_t write_cnt; /** Write counter */
|
|
- uint32_t read_cnt; /** Read counter */
|
|
- uint32_t queue_size; /** Queue size */
|
|
-};
|
|
-
|
|
-/** Queue struct which defines a queue object.
|
|
- * The queue struct is accessed by the queue<operation> type of
|
|
- * function. elementCnt must be a power of two and the power needs
|
|
- * to be smaller than power of uint32_t (obviously 32).
|
|
- */
|
|
-struct notification_queue {
|
|
- struct notification_queue_header hdr; /** Queue header */
|
|
- struct notification notification[MIN_NQ_ELEM]; /** Elements */
|
|
-};
|
|
-
|
|
-#endif /** NQ_H_ */
|
|
diff --git a/drivers/gud/MobiCoreDriver/mci/mcloadformat.h b/drivers/gud/MobiCoreDriver/mci/mcloadformat.h
|
|
deleted file mode 100644
|
|
index f12f618bb0dc6..0000000000000
|
|
--- a/drivers/gud/MobiCoreDriver/mci/mcloadformat.h
|
|
+++ /dev/null
|
|
@@ -1,134 +0,0 @@
|
|
-/*
|
|
- * Copyright (c) 2013-2015 TRUSTONIC LIMITED
|
|
- * All Rights Reserved.
|
|
- *
|
|
- * This program is free software; you can redistribute it and/or
|
|
- * modify it under the terms of the GNU General Public License
|
|
- * version 2 as published by the Free Software Foundation.
|
|
- *
|
|
- * This program is distributed in the hope that it will be useful,
|
|
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
- * GNU General Public License for more details.
|
|
- */
|
|
-#ifndef MCLOADFORMAT_H_
|
|
-#define MCLOADFORMAT_H_
|
|
-
|
|
-/** Trustlet Blob length info */
|
|
-#define MC_TLBLOBLEN_MAGIC 0x7672746C /* Magic for SWd: vrtl */
|
|
-#define MAX_SO_CONT_SIZE 512 /* Max size for a container */
|
|
-
|
|
-/** MCLF flags */
|
|
-/**< Loaded service cannot be unloaded from MobiCore. */
|
|
-#define MC_SERVICE_HEADER_FLAGS_PERMANENT BIT(0)
|
|
-/**< Service has no WSM control interface. */
|
|
-#define MC_SERVICE_HEADER_FLAGS_NO_CONTROL_INTERFACE BIT(1)
|
|
-/**< Service can be debugged. */
|
|
-#define MC_SERVICE_HEADER_FLAGS_DEBUGGABLE BIT(2)
|
|
-/**< New-layout trusted application or trusted driver. */
|
|
-#define MC_SERVICE_HEADER_FLAGS_EXTENDED_LAYOUT BIT(3)
|
|
-
|
|
-/** Service type.
|
|
- * The service type defines the type of executable.
|
|
- */
|
|
-enum service_type {
|
|
- SERVICE_TYPE_ILLEGAL = 0,
|
|
- SERVICE_TYPE_DRIVER = 1,
|
|
- SERVICE_TYPE_SP_TRUSTLET = 2,
|
|
- SERVICE_TYPE_SYSTEM_TRUSTLET = 3,
|
|
- SERVICE_TYPE_MIDDLEWARE = 4,
|
|
- SERVICE_TYPE_LAST_ENTRY = 5,
|
|
-};
|
|
-
|
|
-/**
|
|
- * Descriptor for a memory segment.
|
|
- */
|
|
-struct segment_descriptor {
|
|
- uint32_t start; /**< Virtual start address */
|
|
- uint32_t len; /**< Segment length in bytes */
|
|
-};
|
|
-
|
|
-/**
|
|
- * MCLF intro for data structure identification.
|
|
- * Must be the first element of a valid MCLF file.
|
|
- */
|
|
-struct mclf_intro {
|
|
- uint32_t magic; /**< Header magic value ASCII "MCLF" */
|
|
- uint32_t version; /**< Version the MCLF header struct */
|
|
-};
|
|
-
|
|
-/**
|
|
- * @defgroup MCLF_VER_V2 MCLF Version 32
|
|
- * @ingroup MCLF_VER
|
|
- *
|
|
- * @addtogroup MCLF_VER_V2
|
|
- */
|
|
-
|
|
-/*
|
|
- * GP TA identity.
|
|
- */
|
|
-struct identity {
|
|
- /**< GP TA login type */
|
|
- uint32_t login_type;
|
|
- /**< GP TA login data */
|
|
- uint8_t login_data[16];
|
|
-};
|
|
-
|
|
-/**
|
|
- * Version 2.1/2.2 MCLF header.
|
|
- */
|
|
-struct mclf_header_v2 {
|
|
- /**< MCLF header start with the mandatory intro */
|
|
- struct mclf_intro intro;
|
|
- /**< Service flags */
|
|
- uint32_t flags;
|
|
- /**< Type of memory the service must be executed from */
|
|
- uint32_t mem_type;
|
|
- /**< Type of service */
|
|
- enum service_type service_type;
|
|
- /**< Number of instances which can be run simultaneously */
|
|
- uint32_t num_instances;
|
|
- /**< Loadable service unique identifier (UUID) */
|
|
- struct mc_uuid_t uuid;
|
|
- /**< If the service_type is SERVICE_TYPE_DRIVER the Driver ID is used */
|
|
- uint32_t driver_id;
|
|
- /**<
|
|
- * Number of threads (N) in a service:
|
|
- * SERVICE_TYPE_SP_TRUSTLET: N = 1
|
|
- * SERVICE_TYPE_SYSTEM_TRUSTLET: N = 1
|
|
- * SERVICE_TYPE_DRIVER: N >= 1
|
|
- */
|
|
- uint32_t num_threads;
|
|
- /**< Virtual text segment */
|
|
- struct segment_descriptor text;
|
|
- /**< Virtual data segment */
|
|
- struct segment_descriptor data;
|
|
- /**< Length of the BSS segment in bytes. MUST be at least 8 byte */
|
|
- uint32_t bss_len;
|
|
- /**< Virtual start address of service code */
|
|
- uint32_t entry;
|
|
- /**< Version of the interface the driver exports */
|
|
- uint32_t service_version;
|
|
-};
|
|
-
|
|
-/**
|
|
- * @addtogroup MCLF
|
|
- */
|
|
-
|
|
-/** MCLF header */
|
|
-union mclf_header {
|
|
- /**< Intro for data identification */
|
|
- struct mclf_intro intro;
|
|
- /**< Version 2 header */
|
|
- struct mclf_header_v2 mclf_header_v2;
|
|
-};
|
|
-
|
|
-struct mc_blob_len_info {
|
|
- uint32_t magic; /**< New blob format magic number */
|
|
- uint32_t root_size; /**< Root container size */
|
|
- uint32_t sp_size; /**< SP container size */
|
|
- uint32_t ta_size; /**< TA container size */
|
|
- uint32_t reserved[4]; /**< Reserved for further Use */
|
|
-};
|
|
-
|
|
-#endif /* MCLOADFORMAT_H_ */
|
|
diff --git a/drivers/gud/MobiCoreDriver/mcp.c b/drivers/gud/MobiCoreDriver/mcp.c
|
|
deleted file mode 100644
|
|
index 693fd42e2d4b5..0000000000000
|
|
--- a/drivers/gud/MobiCoreDriver/mcp.c
|
|
+++ /dev/null
|
|
@@ -1,1067 +0,0 @@
|
|
-/*
|
|
- * Copyright (c) 2013-2015 TRUSTONIC LIMITED
|
|
- * All Rights Reserved.
|
|
- *
|
|
- * This program is free software; you can redistribute it and/or
|
|
- * modify it under the terms of the GNU General Public License
|
|
- * version 2 as published by the Free Software Foundation.
|
|
- *
|
|
- * This program is distributed in the hope that it will be useful,
|
|
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
- * GNU General Public License for more details.
|
|
- */
|
|
-
|
|
-#include <linux/err.h>
|
|
-#include <linux/slab.h>
|
|
-#include <linux/mutex.h>
|
|
-#include <linux/device.h>
|
|
-#include <linux/sched.h>
|
|
-#include <linux/completion.h>
|
|
-#include <linux/circ_buf.h>
|
|
-#include <linux/delay.h>
|
|
-#include <linux/interrupt.h>
|
|
-#include <linux/debugfs.h>
|
|
-#include <linux/of_irq.h>
|
|
-
|
|
-#include "public/mc_linux.h"
|
|
-#include "public/mc_admin.h"
|
|
-
|
|
-#include "mci/mcimcp.h"
|
|
-#include "mci/mcifc.h"
|
|
-#include "mci/mcinq.h" /* SID_MCP */
|
|
-
|
|
-#include "platform.h" /* IRQ number */
|
|
-#include "fastcall.h"
|
|
-#include "debug.h"
|
|
-#include "logging.h"
|
|
-#include "mcp.h"
|
|
-
|
|
-/* respond timeout for MCP notification, in secs */
|
|
-#define MCP_TIMEOUT 10
|
|
-#define MCP_RETRIES 5
|
|
-#define MCP_NF_QUEUE_SZ 8
|
|
-#define NQ_NUM_ELEMS 16
|
|
-
|
|
-static void mc_irq_worker(struct work_struct *data);
|
|
-DECLARE_WORK(irq_work, mc_irq_worker);
|
|
-
|
|
-static const struct {
|
|
- unsigned int index;
|
|
- const char *msg;
|
|
-} status_map[] = {
|
|
- /**< MobiCore control flags */
|
|
- { MC_EXT_INFO_ID_FLAGS, "flags"},
|
|
- /**< MobiCore halt condition code */
|
|
- { MC_EXT_INFO_ID_HALT_CODE, "haltCode"},
|
|
- /**< MobiCore halt condition instruction pointer */
|
|
- { MC_EXT_INFO_ID_HALT_IP, "haltIp"},
|
|
- /**< MobiCore fault counter */
|
|
- { MC_EXT_INFO_ID_FAULT_CNT, "faultRec.cnt"},
|
|
- /**< MobiCore last fault cause */
|
|
- { MC_EXT_INFO_ID_FAULT_CAUSE, "faultRec.cause"},
|
|
- /**< MobiCore last fault meta */
|
|
- { MC_EXT_INFO_ID_FAULT_META, "faultRec.meta"},
|
|
- /**< MobiCore last fault threadid */
|
|
- { MC_EXT_INFO_ID_FAULT_THREAD, "faultRec.thread"},
|
|
- /**< MobiCore last fault instruction pointer */
|
|
- { MC_EXT_INFO_ID_FAULT_IP, "faultRec.ip"},
|
|
- /**< MobiCore last fault stack pointer */
|
|
- { MC_EXT_INFO_ID_FAULT_SP, "faultRec.sp"},
|
|
- /**< MobiCore last fault ARM arch information */
|
|
- { MC_EXT_INFO_ID_FAULT_ARCH_DFSR, "faultRec.arch.dfsr"},
|
|
- /**< MobiCore last fault ARM arch information */
|
|
- { MC_EXT_INFO_ID_FAULT_ARCH_ADFSR, "faultRec.arch.adfsr"},
|
|
- /**< MobiCore last fault ARM arch information */
|
|
- { MC_EXT_INFO_ID_FAULT_ARCH_DFAR, "faultRec.arch.dfar"},
|
|
- /**< MobiCore last fault ARM arch information */
|
|
- { MC_EXT_INFO_ID_FAULT_ARCH_IFSR, "faultRec.arch.ifsr"},
|
|
- /**< MobiCore last fault ARM arch information */
|
|
- { MC_EXT_INFO_ID_FAULT_ARCH_AIFSR, "faultRec.arch.aifsr"},
|
|
- /**< MobiCore last fault ARM arch information */
|
|
- { MC_EXT_INFO_ID_FAULT_ARCH_IFAR, "faultRec.arch.ifar"},
|
|
- /**< MobiCore configured by Daemon via fc_init flag */
|
|
- { MC_EXT_INFO_ID_MC_CONFIGURED, "mcData.flags"},
|
|
- /**< MobiCore exception handler last partner */
|
|
- { MC_EXT_INFO_ID_MC_EXC_PARTNER, "mcExcep.partner"},
|
|
- /**< MobiCore exception handler last peer */
|
|
- { MC_EXT_INFO_ID_MC_EXC_IPCPEER, "mcExcep.peer"},
|
|
- /**< MobiCore exception handler last IPC message */
|
|
- { MC_EXT_INFO_ID_MC_EXC_IPCMSG, "mcExcep.cause"},
|
|
- /**< MobiCore exception handler last IPC data */
|
|
- {MC_EXT_INFO_ID_MC_EXC_IPCDATA, "mcExcep.meta"},
|
|
-};
|
|
-
|
|
-static struct mcp_context {
|
|
- struct mutex buffer_lock; /* Lock on SWd communication buffer */
|
|
- struct mutex queue_lock; /* Lock for MCP messages */
|
|
- struct mcp_buffer *mcp_buffer;
|
|
- struct tbase_session *session;
|
|
- struct completion complete;
|
|
- bool mcp_dead;
|
|
- int irq;
|
|
- int (*scheduler_cb)(enum mcp_scheduler_commands);
|
|
- void (*crashhandler_cb)(void);
|
|
- /* MobiCore MCI information */
|
|
- unsigned int order;
|
|
- union {
|
|
- void *base;
|
|
- struct {
|
|
- struct notification_queue *tx;
|
|
- struct notification_queue *rx;
|
|
- } nq;
|
|
- };
|
|
- /*
|
|
- * This notifications list is to be used to queue notifications when the
|
|
- * notification queue overflows, so no session gets its notification
|
|
- * lost, especially MCP.
|
|
- */
|
|
- struct mutex notifications_mutex;
|
|
- struct list_head notifications;
|
|
- struct mcp_session mcp_session; /* Pseudo session for MCP */
|
|
- /* Unexpected notification (during MCP open) */
|
|
- struct mutex unexp_notif_mutex;
|
|
- struct notification unexp_notif;
|
|
- /* Sessions */
|
|
- struct mutex sessions_lock;
|
|
- struct list_head sessions;
|
|
- /* Dump buffer */
|
|
- struct kasnprintf_buf dump;
|
|
-} mcp_ctx;
|
|
-
|
|
-static inline void mark_mcp_dead(void)
|
|
-{
|
|
- mcp_ctx.mcp_dead = true;
|
|
- complete(&mcp_ctx.complete);
|
|
-}
|
|
-
|
|
-static inline int mcp_set_sleep_mode_rq(uint16_t sleep_req)
|
|
-{
|
|
- mutex_lock(&mcp_ctx.buffer_lock);
|
|
- mcp_ctx.mcp_buffer->mc_flags.sleep_mode.sleep_req = sleep_req;
|
|
- mutex_unlock(&mcp_ctx.buffer_lock);
|
|
- return 0;
|
|
-}
|
|
-
|
|
-static ssize_t debug_crashdump_read(struct file *file, char __user *user_buf,
|
|
- size_t count, loff_t *ppos)
|
|
-{
|
|
- if (mcp_ctx.dump.off)
|
|
- return simple_read_from_buffer(user_buf, count, ppos,
|
|
- mcp_ctx.dump.buf,
|
|
- mcp_ctx.dump.off);
|
|
-
|
|
- return 0;
|
|
-}
|
|
-
|
|
-static const struct file_operations mc_debug_crashdump_ops = {
|
|
- .read = debug_crashdump_read,
|
|
- .llseek = default_llseek,
|
|
-};
|
|
-
|
|
-static void mcp_dump_mobicore_status(void)
|
|
-{
|
|
- char uuid_str[33];
|
|
- int ret = 0;
|
|
- int i;
|
|
-
|
|
- if (mcp_ctx.dump.off)
|
|
- ret = -EBUSY;
|
|
-
|
|
- /* read additional info about exception-point and print */
|
|
- dev_err(g_ctx.mcd, "<t-base halted. Status dump:");
|
|
-
|
|
- for (i = 0; i < ARRAY_SIZE(status_map); i++) {
|
|
- uint32_t info;
|
|
-
|
|
- if (!mc_fc_info(status_map[i].index, NULL, &info)) {
|
|
- dev_err(g_ctx.mcd, " %-20s= 0x%08x\n",
|
|
- status_map[i].msg, info);
|
|
- if (ret >= 0)
|
|
- ret = kasnprintf(&mcp_ctx.dump,
|
|
- "%-20s= 0x%08x\n",
|
|
- status_map[i].msg, info);
|
|
- }
|
|
- }
|
|
-
|
|
- /* construct UUID string */
|
|
- for (i = 0; i < 4; i++) {
|
|
- uint32_t info;
|
|
- int j;
|
|
-
|
|
- if (mc_fc_info(MC_EXT_INFO_ID_MC_EXC_UUID + i, NULL, &info))
|
|
- return;
|
|
-
|
|
- for (j = 0; j < sizeof(info); j++) {
|
|
- snprintf(&uuid_str[(i * sizeof(info) + j) * 2], 3,
|
|
- "%02x", (info >> (j * 8)) & 0xff);
|
|
- }
|
|
- }
|
|
-
|
|
- dev_err(g_ctx.mcd, " %-20s= 0x%s\n", "mcExcep.uuid", uuid_str);
|
|
- if (ret >= 0)
|
|
- ret = kasnprintf(&mcp_ctx.dump, "%-20s= 0x%s\n", "mcExcep.uuid",
|
|
- uuid_str);
|
|
-
|
|
- if (ret < 0) {
|
|
- kfree(mcp_ctx.dump.buf);
|
|
- mcp_ctx.dump.off = 0;
|
|
- return;
|
|
- }
|
|
-
|
|
- debugfs_create_file("crashdump", 0400, g_ctx.debug_dir, NULL,
|
|
- &mc_debug_crashdump_ops);
|
|
- if (mcp_ctx.crashhandler_cb)
|
|
- mcp_ctx.crashhandler_cb();
|
|
-}
|
|
-
|
|
-void mcp_session_init(struct mcp_session *session, bool is_gp,
|
|
- const struct identity *identity)
|
|
-{
|
|
- /* close_work is initialized by the caller */
|
|
- INIT_LIST_HEAD(&session->list);
|
|
- INIT_LIST_HEAD(&session->notifications_list);
|
|
- mutex_init(&session->notif_wait_lock);
|
|
- init_completion(&session->completion);
|
|
- mutex_init(&session->exit_code_lock);
|
|
- session->state = MCP_SESSION_RUNNING;
|
|
- session->is_gp = is_gp;
|
|
- if (is_gp)
|
|
- session->identity = *identity;
|
|
-}
|
|
-
|
|
-static inline bool mcp_session_isrunning(struct mcp_session *session)
|
|
-{
|
|
- bool ret;
|
|
-
|
|
- mutex_lock(&mcp_ctx.sessions_lock);
|
|
- ret = session->state == MCP_SESSION_RUNNING;
|
|
- mutex_unlock(&mcp_ctx.sessions_lock);
|
|
- return ret;
|
|
-}
|
|
-
|
|
-/*
|
|
- * session remains valid thanks to the upper layers reference counters, but the
|
|
- * SWd session may have died, in which case we are informed.
|
|
- */
|
|
-int mcp_session_waitnotif(struct mcp_session *session, int32_t timeout)
|
|
-{
|
|
- int ret = 0;
|
|
-
|
|
- mutex_lock(&session->notif_wait_lock);
|
|
- if (!mcp_session_isrunning(session)) {
|
|
- ret = -ENXIO;
|
|
- goto end;
|
|
- }
|
|
-
|
|
- if (mcp_session_exitcode(session)) {
|
|
- ret = -ECOMM;
|
|
- goto end;
|
|
- }
|
|
-
|
|
- if (timeout < 0) {
|
|
- ret = wait_for_completion_interruptible(&session->completion);
|
|
- if (ret)
|
|
- goto end;
|
|
- } else {
|
|
- ret = wait_for_completion_interruptible_timeout(
|
|
- &session->completion, timeout * HZ / 1000);
|
|
- if (ret < 0)
|
|
- /* Interrupted */
|
|
- goto end;
|
|
-
|
|
- if (!ret) {
|
|
- /* Timed out */
|
|
- ret = -ETIME;
|
|
- goto end;
|
|
- }
|
|
-
|
|
- ret = 0;
|
|
- }
|
|
-
|
|
- if (mcp_session_exitcode(session)) {
|
|
- ret = -ECOMM;
|
|
- goto end;
|
|
- }
|
|
-
|
|
- if (!mcp_session_isrunning(session)) {
|
|
- ret = -ENXIO;
|
|
- goto end;
|
|
- }
|
|
-
|
|
-end:
|
|
- mutex_unlock(&session->notif_wait_lock);
|
|
- if (ret)
|
|
- dev_info(g_ctx.mcd, "%s session %x ec %d ret %d\n", __func__,
|
|
- session->id, session->exit_code, ret);
|
|
-
|
|
- return ret;
|
|
-}
|
|
-
|
|
-int32_t mcp_session_exitcode(struct mcp_session *session)
|
|
-{
|
|
- int32_t exit_code;
|
|
-
|
|
- mutex_lock(&session->exit_code_lock);
|
|
- exit_code = session->exit_code;
|
|
- mutex_unlock(&session->exit_code_lock);
|
|
- if (exit_code)
|
|
- dev_info(g_ctx.mcd, "%s session %x ec %d\n", __func__,
|
|
- session->id, exit_code);
|
|
-
|
|
- return exit_code;
|
|
-}
|
|
-
|
|
-int mcp_suspend(void)
|
|
-{
|
|
- return mcp_set_sleep_mode_rq(MC_FLAG_REQ_TO_SLEEP);
|
|
-}
|
|
-
|
|
-int mcp_resume(void)
|
|
-{
|
|
- return mcp_set_sleep_mode_rq(MC_FLAG_NO_SLEEP_REQ);
|
|
-}
|
|
-
|
|
-bool mcp_suspended(void)
|
|
-{
|
|
- struct mcp_flags *flags = &mcp_ctx.mcp_buffer->mc_flags;
|
|
- bool ret;
|
|
-
|
|
- mutex_lock(&mcp_ctx.buffer_lock);
|
|
- ret = flags->sleep_mode.ready_to_sleep & MC_STATE_READY_TO_SLEEP;
|
|
- if (!ret) {
|
|
- MCDRV_DBG("IDLE=%d!", flags->schedule);
|
|
- MCDRV_DBG("Request Sleep=%d!", flags->sleep_mode.sleep_req);
|
|
- MCDRV_DBG("Sleep Ready=%d!", flags->sleep_mode.ready_to_sleep);
|
|
- }
|
|
-
|
|
- mutex_unlock(&mcp_ctx.buffer_lock);
|
|
- return ret;
|
|
-}
|
|
-
|
|
-bool mcp_get_idle_timeout(int32_t *timeout)
|
|
-{
|
|
- uint32_t schedule;
|
|
- bool ret;
|
|
-
|
|
- mutex_lock(&mcp_ctx.buffer_lock);
|
|
- schedule = mcp_ctx.mcp_buffer->mc_flags.schedule;
|
|
- if (schedule == MC_FLAG_SCHEDULE_IDLE) {
|
|
- if (g_ctx.f_timeout)
|
|
- *timeout = mcp_ctx.mcp_buffer->mc_flags.timeout_ms;
|
|
- else
|
|
- *timeout = -1;
|
|
-
|
|
- ret = true;
|
|
- } else {
|
|
- ret = false;
|
|
- }
|
|
-
|
|
- mutex_unlock(&mcp_ctx.buffer_lock);
|
|
- return ret;
|
|
-}
|
|
-
|
|
-void mcp_reset_idle_timeout(void)
|
|
-{
|
|
- mutex_lock(&mcp_ctx.buffer_lock);
|
|
- mcp_ctx.mcp_buffer->mc_flags.timeout_ms = -1;
|
|
- mutex_unlock(&mcp_ctx.buffer_lock);
|
|
-}
|
|
-
|
|
-static inline int wait_mcp_notification(void)
|
|
-{
|
|
- unsigned long timeout = msecs_to_jiffies(MCP_TIMEOUT * 1000);
|
|
- int try;
|
|
-
|
|
- /*
|
|
- * Total timeout is MCP_TIMEOUT * MCP_RETRIES, but we check for a crash
|
|
- * to try and terminate before then if things go wrong.
|
|
- */
|
|
- for (try = 1; try <= MCP_RETRIES; try++) {
|
|
- uint32_t status;
|
|
- int ret;
|
|
-
|
|
- /*
|
|
- * Wait non-interruptible to keep MCP synchronised even if caller
|
|
- * is interrupted by signal.
|
|
- */
|
|
- ret = wait_for_completion_timeout(&mcp_ctx.complete, timeout);
|
|
- if (ret > 0)
|
|
- return 0;
|
|
-
|
|
- MCDRV_ERROR("No answer after %ds", MCP_TIMEOUT * try);
|
|
-
|
|
- /* If SWd halted, exit now */
|
|
- if (!mc_fc_info(MC_EXT_INFO_ID_MCI_VERSION, &status, NULL) &&
|
|
- (status == MC_STATUS_HALT))
|
|
- break;
|
|
- }
|
|
-
|
|
- /* <t-base halted or dead: dump status */
|
|
- mark_mcp_dead();
|
|
- mcp_dump_mobicore_status();
|
|
-
|
|
- return -ETIME;
|
|
-}
|
|
-
|
|
-static int mcp_cmd(union mcp_message *cmd)
|
|
-{
|
|
- int err = 0;
|
|
- union mcp_message *msg = &mcp_ctx.mcp_buffer->mcp_message;
|
|
- enum cmd_id cmd_id = cmd->cmd_header.cmd_id;
|
|
-
|
|
- mutex_lock(&mcp_ctx.queue_lock);
|
|
- if (mcp_ctx.mcp_dead)
|
|
- goto out;
|
|
-
|
|
- /* Copy message to MCP buffer */
|
|
- memcpy(msg, cmd, sizeof(*msg));
|
|
-
|
|
- /* Poke tbase */
|
|
- err = mcp_notify(&mcp_ctx.mcp_session);
|
|
- if (!err)
|
|
- err = wait_mcp_notification();
|
|
-
|
|
- if (err)
|
|
- goto out;
|
|
-
|
|
- /* Check response ID */
|
|
- if (msg->rsp_header.rsp_id != (cmd_id | FLAG_RESPONSE)) {
|
|
- MCDRV_ERROR("MCP command got invalid response (0x%X)",
|
|
- msg->rsp_header.rsp_id);
|
|
- err = -EBADE;
|
|
- goto out;
|
|
- }
|
|
-
|
|
- /* Convert result */
|
|
- switch (msg->rsp_header.result) {
|
|
- case MC_MCP_RET_OK:
|
|
- err = 0;
|
|
- break;
|
|
- case MC_MCP_RET_ERR_CLOSE_TASK_FAILED:
|
|
- case MC_MCP_RET_ERR_NO_MORE_SESSIONS:
|
|
- err = -EBUSY;
|
|
- break;
|
|
- case MC_MCP_RET_ERR_OUT_OF_RESOURCES:
|
|
- err = -ENOSPC;
|
|
- break;
|
|
- case MC_MCP_RET_ERR_UNKNOWN_UUID:
|
|
- err = -ENOENT;
|
|
- break;
|
|
- case MC_MCP_RET_ERR_WRONG_PUBLIC_KEY:
|
|
- err = -EKEYREJECTED;
|
|
- break;
|
|
- case MC_MCP_RET_ERR_SERVICE_BLOCKED:
|
|
- err = -ECONNREFUSED;
|
|
- break;
|
|
- case MC_MCP_RET_ERR_SERVICE_LOCKED:
|
|
- err = -ECONNABORTED;
|
|
- break;
|
|
- case MC_MCP_RET_ERR_SERVICE_KILLED:
|
|
- err = -ECONNRESET;
|
|
- break;
|
|
- default:
|
|
- MCDRV_ERROR("cmd %d returned %d.", cmd_id,
|
|
- msg->rsp_header.result);
|
|
- err = -EPERM;
|
|
- goto out;
|
|
- }
|
|
-
|
|
- /* Copy response back to caller struct */
|
|
- memcpy(cmd, msg, sizeof(*cmd));
|
|
-
|
|
-out:
|
|
- mutex_unlock(&mcp_ctx.queue_lock);
|
|
- return err;
|
|
-}
|
|
-
|
|
-int mcp_get_version(struct mc_version_info *version_info)
|
|
-{
|
|
- union mcp_message cmd;
|
|
- int ret;
|
|
-
|
|
- memset(&cmd, 0, sizeof(cmd));
|
|
- cmd.cmd_header.cmd_id = MC_MCP_CMD_GET_MOBICORE_VERSION;
|
|
- ret = mcp_cmd(&cmd);
|
|
- if (!ret)
|
|
- memcpy(version_info, &cmd.rsp_get_version.version_info,
|
|
- sizeof(*version_info));
|
|
-
|
|
- return ret;
|
|
-}
|
|
-
|
|
-int mcp_load_token(uintptr_t data, const struct mcp_buffer_map *map)
|
|
-{
|
|
- union mcp_message cmd;
|
|
-
|
|
- memset(&cmd, 0, sizeof(cmd));
|
|
- cmd.cmd_header.cmd_id = MC_MCP_CMD_LOAD_TOKEN;
|
|
- cmd.cmd_load_token.wsm_data_type = map->type;
|
|
- cmd.cmd_load_token.adr_load_data = map->phys_addr;
|
|
- cmd.cmd_load_token.ofs_load_data = map->offset;
|
|
- cmd.cmd_load_token.len_load_data = map->length;
|
|
- return mcp_cmd(&cmd);
|
|
-}
|
|
-
|
|
-int mcp_load_check(const struct tbase_object *obj,
|
|
- const struct mcp_buffer_map *map)
|
|
-{
|
|
- const union mclf_header *header;
|
|
- union mcp_message cmd;
|
|
-
|
|
- memset(&cmd, 0, sizeof(cmd));
|
|
- cmd.cmd_header.cmd_id = MC_MCP_CMD_CHECK_LOAD_TA;
|
|
- /* Data */
|
|
- cmd.cmd_check_load.wsm_data_type = map->type;
|
|
- cmd.cmd_check_load.adr_load_data = map->phys_addr;
|
|
- cmd.cmd_check_load.ofs_load_data = map->offset;
|
|
- cmd.cmd_check_load.len_load_data = map->length;
|
|
- /* Header */
|
|
- header = (union mclf_header *)(obj->data + obj->header_length);
|
|
- cmd.cmd_check_load.uuid = header->mclf_header_v2.uuid;
|
|
- return mcp_cmd(&cmd);
|
|
-}
|
|
-
|
|
-int mcp_open_session(struct mcp_session *session,
|
|
- const struct tbase_object *obj,
|
|
- const struct mcp_buffer_map *map,
|
|
- const struct mcp_buffer_map *tci_map)
|
|
-{
|
|
- static DEFINE_MUTEX(local_mutex);
|
|
- const union mclf_header *header;
|
|
- union mcp_message cmd;
|
|
- int ret;
|
|
-
|
|
- memset(&cmd, 0, sizeof(cmd));
|
|
- cmd.cmd_header.cmd_id = MC_MCP_CMD_OPEN_SESSION;
|
|
- /* Data */
|
|
- cmd.cmd_open.wsm_data_type = map->type;
|
|
- cmd.cmd_open.adr_load_data = map->phys_addr;
|
|
- cmd.cmd_open.ofs_load_data = map->offset;
|
|
- cmd.cmd_open.len_load_data = map->length;
|
|
- /* Buffer */
|
|
- if (tci_map) {
|
|
- cmd.cmd_open.wsmtype_tci = tci_map->type;
|
|
- cmd.cmd_open.adr_tci_buffer = tci_map->phys_addr;
|
|
- cmd.cmd_open.ofs_tci_buffer = tci_map->offset;
|
|
- cmd.cmd_open.len_tci_buffer = tci_map->length;
|
|
- } else {
|
|
- cmd.cmd_open.wsmtype_tci = WSM_INVALID;
|
|
- }
|
|
- /* Header */
|
|
- header = (union mclf_header *)(obj->data + obj->header_length);
|
|
- cmd.cmd_open.uuid = header->mclf_header_v2.uuid;
|
|
- cmd.cmd_open.is_gpta = session->is_gp;
|
|
- /* Reset unexpected notification */
|
|
- mutex_lock(&local_mutex);
|
|
- mcp_ctx.unexp_notif.session_id = SID_MCP; /* Cannot be */
|
|
- if (!g_ctx.f_client_login) {
|
|
- memcpy(&cmd.cmd_open.tl_header, header,
|
|
- sizeof(cmd.cmd_open.tl_header));
|
|
- } else {
|
|
- cmd.cmd_open.cmd_open_data.mclf_magic = MC_GP_CLIENT_AUTH_MAGIC;
|
|
- if (session->is_gp)
|
|
- cmd.cmd_open.cmd_open_data.identity = session->identity;
|
|
- }
|
|
-
|
|
- /* Send MCP open command */
|
|
- ret = mcp_cmd(&cmd);
|
|
- if (!ret) {
|
|
- session->id = cmd.rsp_open.session_id;
|
|
- /* Add to list of sessions */
|
|
- mutex_lock(&mcp_ctx.sessions_lock);
|
|
- list_add(&session->list, &mcp_ctx.sessions);
|
|
- mutex_unlock(&mcp_ctx.sessions_lock);
|
|
- /* Check for spurious notification */
|
|
- mutex_lock(&mcp_ctx.unexp_notif_mutex);
|
|
- if (mcp_ctx.unexp_notif.session_id == session->id) {
|
|
- mutex_lock(&session->exit_code_lock);
|
|
- session->exit_code = mcp_ctx.unexp_notif.payload;
|
|
- mutex_unlock(&session->exit_code_lock);
|
|
- complete(&session->completion);
|
|
- }
|
|
-
|
|
- mutex_unlock(&mcp_ctx.unexp_notif_mutex);
|
|
- }
|
|
-
|
|
- mutex_unlock(&local_mutex);
|
|
- return ret;
|
|
-}
|
|
-
|
|
-/*
|
|
- * Legacy and GP TAs close differently:
|
|
- * - GP TAs always send a notification with payload, whether on close or crash
|
|
- * - Legacy TAs only send a notification with payload on crash
|
|
- * - GP TAs may take time to close, and we get -EBUSY back from mcp_cmd
|
|
- * - Legacy TAs always close when asked, unless they are driver in which case
|
|
- * they just don't close at all
|
|
- */
|
|
-int mcp_close_session(struct mcp_session *session)
|
|
-{
|
|
- union mcp_message cmd;
|
|
- int ret;
|
|
-
|
|
- /* state is either MCP_SESSION_RUNNING or MCP_SESSION_CLOSING_GP */
|
|
- mutex_lock(&mcp_ctx.sessions_lock);
|
|
- if (session->state == MCP_SESSION_RUNNING)
|
|
- session->state = MCP_SESSION_CLOSE_PREPARE;
|
|
-
|
|
- mutex_unlock(&mcp_ctx.sessions_lock);
|
|
- /* Signal an eventual waiter that SWd session is going away */
|
|
- complete(&session->completion);
|
|
- /* Send MCP command */
|
|
- memset(&cmd, 0, sizeof(cmd));
|
|
- cmd.cmd_header.cmd_id = MC_MCP_CMD_CLOSE_SESSION;
|
|
- cmd.cmd_close.session_id = session->id;
|
|
- ret = mcp_cmd(&cmd);
|
|
- mutex_lock(&mcp_ctx.sessions_lock);
|
|
- /*
|
|
- * The GP TA may already have sent its exit code, in which case the
|
|
- * state has also been changed to MCP_SESSION_CLOSE_NOTIFIED.
|
|
- */
|
|
- if (!ret) {
|
|
- session->state = MCP_SESSION_CLOSED;
|
|
- list_del(&session->list);
|
|
- mutex_lock(&mcp_ctx.notifications_mutex);
|
|
- list_del(&session->notifications_list);
|
|
- mutex_unlock(&mcp_ctx.notifications_mutex);
|
|
- } else if (ret == -EBUSY) {
|
|
- if (session->state == MCP_SESSION_CLOSE_NOTIFIED)
|
|
- /* GP TA already closed */
|
|
- schedule_work(&session->close_work);
|
|
-
|
|
- session->state = MCP_SESSION_CLOSING_GP;
|
|
- } else {
|
|
- /* Something is not right, assume session is still running */
|
|
- session->state = MCP_SESSION_RUNNING;
|
|
- }
|
|
-
|
|
- mutex_unlock(&mcp_ctx.sessions_lock);
|
|
- return ret;
|
|
-}
|
|
-
|
|
-int mcp_map(uint32_t session_id, struct mcp_buffer_map *map)
|
|
-{
|
|
- union mcp_message cmd;
|
|
- int ret;
|
|
-
|
|
- memset(&cmd, 0, sizeof(cmd));
|
|
- cmd.cmd_header.cmd_id = MC_MCP_CMD_MAP;
|
|
- cmd.cmd_map.session_id = session_id;
|
|
- cmd.cmd_map.wsm_type = map->type;
|
|
- cmd.cmd_map.adr_buffer = map->phys_addr;
|
|
- cmd.cmd_map.ofs_buffer = map->offset;
|
|
- cmd.cmd_map.len_buffer = map->length;
|
|
- ret = mcp_cmd(&cmd);
|
|
- if (!ret)
|
|
- map->secure_va = cmd.rsp_map.secure_va;
|
|
-
|
|
- return ret;
|
|
-}
|
|
-
|
|
-int mcp_unmap(uint32_t session_id, const struct mcp_buffer_map *map)
|
|
-{
|
|
- union mcp_message cmd;
|
|
-
|
|
- memset(&cmd, 0, sizeof(cmd));
|
|
- cmd.cmd_header.cmd_id = MC_MCP_CMD_UNMAP;
|
|
- cmd.cmd_unmap.session_id = session_id;
|
|
- cmd.cmd_unmap.wsm_type = map->type;
|
|
- cmd.cmd_unmap.virtual_buffer_len = map->length;
|
|
- cmd.cmd_unmap.secure_va = map->secure_va;
|
|
- return mcp_cmd(&cmd);
|
|
-}
|
|
-
|
|
-int mcp_multimap(uint32_t session_id, struct mcp_buffer_map *maps)
|
|
-{
|
|
- struct mcp_buffer_map *map = maps;
|
|
- union mcp_message cmd;
|
|
- struct buffer_map *buf = cmd.cmd_multimap.bufs;
|
|
- int ret = 0;
|
|
- uint32_t i;
|
|
-
|
|
- /* Prepare command */
|
|
- memset(&cmd, 0, sizeof(cmd));
|
|
- cmd.cmd_header.cmd_id = MC_MCP_CMD_MULTIMAP;
|
|
- cmd.cmd_multimap.session_id = session_id;
|
|
- for (i = 0; i < MC_MAP_MAX; i++, map++, buf++) {
|
|
- buf->wsm_type = map->type;
|
|
- buf->adr_buffer = map->phys_addr;
|
|
- buf->ofs_buffer = map->offset;
|
|
- buf->len_buffer = map->length;
|
|
- }
|
|
-
|
|
- ret = mcp_cmd(&cmd);
|
|
- if (ret)
|
|
- return ret;
|
|
-
|
|
- /* Return secure virtual addresses */
|
|
- map = maps;
|
|
- for (i = 0; i < MC_MAP_MAX; i++, map++)
|
|
- map->secure_va = cmd.rsp_multimap.secure_va[i];
|
|
-
|
|
- return 0;
|
|
-}
|
|
-
|
|
-int mcp_multiunmap(uint32_t session_id, const struct mcp_buffer_map *maps)
|
|
-{
|
|
- const struct mcp_buffer_map *map = maps;
|
|
- union mcp_message cmd;
|
|
- struct buffer_unmap *buf = cmd.cmd_multiunmap.bufs;
|
|
- uint32_t i;
|
|
-
|
|
- memset(&cmd, 0, sizeof(cmd));
|
|
- cmd.cmd_header.cmd_id = MC_MCP_CMD_MULTIUNMAP;
|
|
- cmd.cmd_multiunmap.session_id = session_id;
|
|
- for (i = 0; i < MC_MAP_MAX; i++, map++, buf++) {
|
|
- buf->secure_va = map->secure_va;
|
|
- buf->len_buffer = map->length;
|
|
- }
|
|
-
|
|
- return mcp_cmd(&cmd);
|
|
-}
|
|
-
|
|
-static int mcp_close(void)
|
|
-{
|
|
- union mcp_message cmd;
|
|
-
|
|
- memset(&cmd, 0, sizeof(cmd));
|
|
- cmd.cmd_header.cmd_id = MC_MCP_CMD_CLOSE_MCP;
|
|
- return mcp_cmd(&cmd);
|
|
-}
|
|
-
|
|
-static inline bool notif_queue_full(void)
|
|
-{
|
|
- struct notification_queue *tx = mcp_ctx.nq.tx;
|
|
-
|
|
- return (tx->hdr.write_cnt - tx->hdr.read_cnt) == tx->hdr.queue_size;
|
|
-}
|
|
-
|
|
-static inline void notif_queue_push(uint32_t session_id)
|
|
-{
|
|
- struct notification_queue_header *hdr = &mcp_ctx.nq.tx->hdr;
|
|
- uint32_t i = hdr->write_cnt % hdr->queue_size;
|
|
-
|
|
- mcp_ctx.nq.tx->notification[i].session_id = session_id;
|
|
- mcp_ctx.nq.tx->notification[i].payload = 0;
|
|
- hdr->write_cnt++;
|
|
-}
|
|
-
|
|
-static inline bool mcp_notifications_flush_nolock(void)
|
|
-{
|
|
- bool flushed = false;
|
|
-
|
|
- while (!list_empty(&mcp_ctx.notifications) && !notif_queue_full()) {
|
|
- struct mcp_session *session;
|
|
-
|
|
- session = list_first_entry(&mcp_ctx.notifications,
|
|
- struct mcp_session,
|
|
- notifications_list);
|
|
- dev_dbg(g_ctx.mcd, "pop %x\n", session->id);
|
|
- notif_queue_push(session->id);
|
|
- list_del_init(&session->notifications_list);
|
|
- flushed = true;
|
|
- }
|
|
-
|
|
- return flushed;
|
|
-}
|
|
-
|
|
-bool mcp_notifications_flush(void)
|
|
-{
|
|
- bool flushed = false;
|
|
-
|
|
- mutex_lock(&mcp_ctx.notifications_mutex);
|
|
- flushed = mcp_notifications_flush_nolock();
|
|
- mutex_unlock(&mcp_ctx.notifications_mutex);
|
|
- return flushed;
|
|
-}
|
|
-
|
|
-int mcp_notify(struct mcp_session *session)
|
|
-{
|
|
- int ret = 0;
|
|
-
|
|
- if (!mcp_ctx.scheduler_cb)
|
|
- return -EAGAIN;
|
|
-
|
|
- mutex_lock(&mcp_ctx.notifications_mutex);
|
|
- if (session->id == SID_MCP)
|
|
- dev_dbg(g_ctx.mcd, "notify MCP");
|
|
- else
|
|
- dev_dbg(g_ctx.mcd, "notify %x", session->id);
|
|
-
|
|
- /* Notify TEE */
|
|
- if (!list_empty(&mcp_ctx.notifications) || notif_queue_full()) {
|
|
- if (!list_empty(&session->notifications_list)) {
|
|
- ret = -EAGAIN;
|
|
- dev_dbg(g_ctx.mcd, "skip %x\n", session->id);
|
|
- } else {
|
|
- list_add(&session->notifications_list,
|
|
- &mcp_ctx.notifications);
|
|
- dev_dbg(g_ctx.mcd, "push %x\n", session->id);
|
|
- }
|
|
-
|
|
- mcp_notifications_flush_nolock();
|
|
-
|
|
- if (mcp_ctx.scheduler_cb(MCP_YIELD)) {
|
|
- MCDRV_ERROR("MC_SMC_N_YIELD failed");
|
|
- ret = -EPROTO;
|
|
- }
|
|
- } else {
|
|
- notif_queue_push(session->id);
|
|
- if (mcp_ctx.scheduler_cb(MCP_NSIQ)) {
|
|
- MCDRV_ERROR("MC_SMC_N_SIQ failed");
|
|
- ret = -EPROTO;
|
|
- }
|
|
- }
|
|
-
|
|
- mutex_unlock(&mcp_ctx.notifications_mutex);
|
|
- return ret;
|
|
-}
|
|
-
|
|
-static inline void handle_mcp_notif(uint32_t exit_code)
|
|
-{
|
|
- dev_dbg(g_ctx.mcd, "notification from MCP ec %d\n", exit_code);
|
|
- complete(&mcp_ctx.complete);
|
|
-}
|
|
-
|
|
-static inline void handle_session_notif(uint32_t session_id, uint32_t exit_code)
|
|
-{
|
|
- struct mcp_session *session = NULL, *s;
|
|
-
|
|
- dev_dbg(g_ctx.mcd, "notification from %x ec %d\n", session_id,
|
|
- exit_code);
|
|
- mutex_lock(&mcp_ctx.sessions_lock);
|
|
- list_for_each_entry(s, &mcp_ctx.sessions, list) {
|
|
- if (s->id == session_id) {
|
|
- session = s;
|
|
- break;
|
|
- }
|
|
- }
|
|
-
|
|
- if (session) {
|
|
- /* TA has terminated */
|
|
- if (exit_code) {
|
|
- /* Update exit code, or not */
|
|
- mutex_lock(&session->exit_code_lock);
|
|
- /*
|
|
- * In GP, the only way to recover the sessions exit code
|
|
- * is to call TEEC_InvokeCommand which will notify. But
|
|
- * notifying a dead session would change the exit code
|
|
- * to ERR_SID_NOT_ACTIVE, hence the check below.
|
|
- */
|
|
- if (!session->is_gp || !session->exit_code ||
|
|
- (exit_code != ERR_SID_NOT_ACTIVE))
|
|
- session->exit_code = exit_code;
|
|
-
|
|
- mutex_unlock(&session->exit_code_lock);
|
|
-
|
|
- /* Update state or schedule close worker */
|
|
- if (session->state == MCP_SESSION_CLOSE_PREPARE)
|
|
- session->state = MCP_SESSION_CLOSE_NOTIFIED;
|
|
- else if (session->state == MCP_SESSION_CLOSING_GP)
|
|
- schedule_work(&session->close_work);
|
|
- }
|
|
-
|
|
- /* Unblock waiter */
|
|
- complete(&session->completion);
|
|
- }
|
|
- mutex_unlock(&mcp_ctx.sessions_lock);
|
|
-
|
|
- /* Unknown session, probably being started */
|
|
- if (!session) {
|
|
- mutex_lock(&mcp_ctx.unexp_notif_mutex);
|
|
- mcp_ctx.unexp_notif.session_id = session_id;
|
|
- mcp_ctx.unexp_notif.payload = exit_code;
|
|
- mutex_unlock(&mcp_ctx.unexp_notif_mutex);
|
|
- }
|
|
-}
|
|
-
|
|
-static void mc_irq_worker(struct work_struct *data)
|
|
-{
|
|
- struct notification_queue *rx = mcp_ctx.nq.rx;
|
|
-
|
|
- /* Deal with all pending notifications in one go */
|
|
- while ((rx->hdr.write_cnt - rx->hdr.read_cnt) > 0) {
|
|
- struct notification nf;
|
|
-
|
|
- nf = rx->notification[rx->hdr.read_cnt++ % rx->hdr.queue_size];
|
|
- if (nf.session_id == SID_MCP)
|
|
- handle_mcp_notif(nf.payload);
|
|
- else
|
|
- handle_session_notif(nf.session_id, nf.payload);
|
|
- }
|
|
-
|
|
- /*
|
|
- * Finished processing notifications. It does not matter whether
|
|
- * there actually were any notification or not. S-SIQs can also
|
|
- * be triggered by an SWd driver which was waiting for a FIQ.
|
|
- * In this case the S-SIQ tells NWd that SWd is no longer idle
|
|
- * an will need scheduling again.
|
|
- */
|
|
- if (mcp_ctx.scheduler_cb)
|
|
- mcp_ctx.scheduler_cb(MCP_NSIQ);
|
|
-}
|
|
-
|
|
-/*
|
|
- * This function represents the interrupt function of the mcDrvModule.
|
|
- * It signals by incrementing of an event counter and the start of the read
|
|
- * waiting queue, the read function a interrupt has occurred.
|
|
- */
|
|
-static irqreturn_t irq_handler(int intr, void *arg)
|
|
-{
|
|
- /* wake up thread to continue handling this interrupt */
|
|
- schedule_work(&irq_work);
|
|
- return IRQ_HANDLED;
|
|
-}
|
|
-
|
|
-void mcp_register_scheduler(int (*scheduler_cb)(enum mcp_scheduler_commands))
|
|
-{
|
|
- mcp_ctx.scheduler_cb = scheduler_cb;
|
|
-}
|
|
-
|
|
-void mcp_register_crashhandler(void (*crashhandler_cb)(void))
|
|
-{
|
|
- mcp_ctx.crashhandler_cb = crashhandler_cb;
|
|
-}
|
|
-
|
|
-int mcp_start(void)
|
|
-{
|
|
- size_t q_len = ALIGN(2 * (sizeof(struct notification_queue_header) +
|
|
- NQ_NUM_ELEMS * sizeof(struct notification)), 4);
|
|
- int ret;
|
|
-
|
|
- /* Make sure we have an interrupt number before going on */
|
|
-#if defined(CONFIG_OF)
|
|
- mcp_ctx.irq = irq_of_parse_and_map(g_ctx.mcd->of_node, 0);
|
|
-#endif
|
|
-#if defined(MC_INTR_SSIQ)
|
|
- if (mcp_ctx.irq <= 0)
|
|
- mcp_ctx.irq = MC_INTR_SSIQ;
|
|
-#endif
|
|
-
|
|
- if (mcp_ctx.irq <= 0) {
|
|
- MCDRV_ERROR("No IRQ number, aborting");
|
|
- return -EINVAL;
|
|
- }
|
|
-
|
|
- /* Call the INIT fastcall to setup shared buffers */
|
|
- ret = mc_fc_init(virt_to_phys(mcp_ctx.base),
|
|
- (uintptr_t)mcp_ctx.mcp_buffer -
|
|
- (uintptr_t)mcp_ctx.base,
|
|
- q_len, sizeof(*mcp_ctx.mcp_buffer));
|
|
- if (ret)
|
|
- return ret;
|
|
-
|
|
- /* First empty N-SIQ to setup of the MCI structure */
|
|
- ret = mc_fc_nsiq();
|
|
- if (ret)
|
|
- return ret;
|
|
-
|
|
- /*
|
|
- * Wait until <t-base state switches to MC_STATUS_INITIALIZED
|
|
- * It is assumed that <t-base always switches state at a certain
|
|
- * point in time.
|
|
- */
|
|
- do {
|
|
- uint32_t status = 0;
|
|
- uint32_t timeslot;
|
|
-
|
|
- ret = mc_fc_info(MC_EXT_INFO_ID_MCI_VERSION, &status, NULL);
|
|
- if (ret)
|
|
- return ret;
|
|
-
|
|
- switch (status) {
|
|
- case MC_STATUS_NOT_INITIALIZED:
|
|
- /* Switch to <t-base to give it more CPU time. */
|
|
- ret = EAGAIN;
|
|
- for (timeslot = 0; timeslot < 10; timeslot++) {
|
|
- int tmp_ret = mc_fc_yield();
|
|
-
|
|
- if (tmp_ret)
|
|
- return tmp_ret;
|
|
- }
|
|
-
|
|
- /* No need to loop like mad */
|
|
- if (ret == EAGAIN)
|
|
- usleep_range(100, 500);
|
|
-
|
|
- break;
|
|
- case MC_STATUS_HALT:
|
|
- mcp_dump_mobicore_status();
|
|
- MCDRV_ERROR("halt during init, state 0x%x", status);
|
|
- return -ENODEV;
|
|
- case MC_STATUS_INITIALIZED:
|
|
- MCDRV_DBG("ready");
|
|
- break;
|
|
- default:
|
|
- /* MC_STATUS_BAD_INIT or anything else */
|
|
- MCDRV_ERROR("MCI init failed, state 0x%x", status);
|
|
- return -EIO;
|
|
- }
|
|
- } while (ret == EAGAIN);
|
|
-
|
|
- /* Set up S-SIQ interrupt handler */
|
|
- return request_irq(mcp_ctx.irq, irq_handler, IRQF_TRIGGER_RISING,
|
|
- MC_ADMIN_DEVNODE, NULL);
|
|
-}
|
|
-
|
|
-void mcp_stop(void)
|
|
-{
|
|
- mcp_close();
|
|
- mcp_ctx.scheduler_cb = NULL;
|
|
- free_irq(mcp_ctx.irq, NULL);
|
|
- flush_work(&irq_work);
|
|
-}
|
|
-
|
|
-int mcp_init(void)
|
|
-{
|
|
- size_t q_len;
|
|
- unsigned long mci;
|
|
-
|
|
- mutex_init(&mcp_ctx.buffer_lock);
|
|
- mutex_init(&mcp_ctx.queue_lock);
|
|
- init_completion(&mcp_ctx.complete);
|
|
- /* Setup notification queue mutex */
|
|
- mutex_init(&mcp_ctx.notifications_mutex);
|
|
- INIT_LIST_HEAD(&mcp_ctx.notifications);
|
|
- mcp_session_init(&mcp_ctx.mcp_session, false, NULL);
|
|
- mcp_ctx.mcp_session.id = SID_MCP;
|
|
- mutex_init(&mcp_ctx.unexp_notif_mutex);
|
|
- INIT_LIST_HEAD(&mcp_ctx.sessions);
|
|
- mutex_init(&mcp_ctx.sessions_lock);
|
|
-
|
|
- /* NQ_NUM_ELEMS must be power of 2 */
|
|
- q_len = ALIGN(2 * (sizeof(struct notification_queue_header) +
|
|
- NQ_NUM_ELEMS * sizeof(struct notification)), 4);
|
|
- if (q_len + sizeof(*mcp_ctx.mcp_buffer) > (uint16_t)-1) {
|
|
- MCDRV_DBG_WARN("queues too large (more than 64k), sorry...");
|
|
- return -EINVAL;
|
|
- }
|
|
-
|
|
- mcp_ctx.order = get_order(q_len + sizeof(*mcp_ctx.mcp_buffer));
|
|
- mci = __get_free_pages(GFP_USER | __GFP_ZERO, mcp_ctx.order);
|
|
- if (!mci)
|
|
- return -ENOMEM;
|
|
-
|
|
- mcp_ctx.nq.tx = (struct notification_queue *)mci;
|
|
- mcp_ctx.nq.tx->hdr.queue_size = NQ_NUM_ELEMS;
|
|
- mci += sizeof(struct notification_queue_header) +
|
|
- mcp_ctx.nq.tx->hdr.queue_size * sizeof(struct notification);
|
|
-
|
|
- mcp_ctx.nq.rx = (struct notification_queue *)mci;
|
|
- mcp_ctx.nq.rx->hdr.queue_size = NQ_NUM_ELEMS;
|
|
- mci += sizeof(struct notification_queue_header) +
|
|
- mcp_ctx.nq.rx->hdr.queue_size * sizeof(struct notification);
|
|
-
|
|
- mcp_ctx.mcp_buffer = (void *)ALIGN(mci, 4);
|
|
- return 0;
|
|
-}
|
|
-
|
|
-void mcp_exit(void)
|
|
-{
|
|
- mark_mcp_dead();
|
|
- if (mcp_ctx.dump.off)
|
|
- kfree(mcp_ctx.dump.buf);
|
|
-
|
|
- free_pages((unsigned long)mcp_ctx.base, mcp_ctx.order);
|
|
-}
|
|
diff --git a/drivers/gud/MobiCoreDriver/mcp.h b/drivers/gud/MobiCoreDriver/mcp.h
|
|
deleted file mode 100644
|
|
index 0eefe573de8bf..0000000000000
|
|
--- a/drivers/gud/MobiCoreDriver/mcp.h
|
|
+++ /dev/null
|
|
@@ -1,121 +0,0 @@
|
|
-/*
|
|
- * Copyright (c) 2013-2015 TRUSTONIC LIMITED
|
|
- * All Rights Reserved.
|
|
- *
|
|
- * This program is free software; you can redistribute it and/or
|
|
- * modify it under the terms of the GNU General Public License
|
|
- * version 2 as published by the Free Software Foundation.
|
|
- *
|
|
- * This program is distributed in the hope that it will be useful,
|
|
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
- * GNU General Public License for more details.
|
|
- */
|
|
-
|
|
-#ifndef _MC_MCP_H_
|
|
-#define _MC_MCP_H_
|
|
-
|
|
-#include "mci/mcloadformat.h" /* struct identity */
|
|
-
|
|
-/* Structure to hold the TA/driver descriptor to pass to MCP */
|
|
-struct tbase_object {
|
|
- uint32_t length; /* Total length */
|
|
- uint32_t header_length; /* Length of header before payload */
|
|
- uint8_t data[]; /* Header followed by payload */
|
|
-};
|
|
-
|
|
-/* Structure to hold all mapped buffer data to pass to MCP */
|
|
-struct mcp_buffer_map {
|
|
- uint64_t phys_addr; /** Page-aligned physical address */
|
|
- uint64_t secure_va; /** Page-aligned physical address */
|
|
- uint32_t offset; /** Data offset inside the first page */
|
|
- uint32_t length; /** Length of the data */
|
|
- uint32_t type; /** Type of MMU */
|
|
-};
|
|
-
|
|
-struct mcp_session {
|
|
- /* Work descriptor to handle delayed closing, set by upper layer */
|
|
- struct work_struct close_work;
|
|
- /* Sessions list (protected by mcp sessions_lock) */
|
|
- struct list_head list;
|
|
- /* Notifications list (protected by mcp notifications_mutex) */
|
|
- struct list_head notifications_list;
|
|
- /* Notification waiter lock */
|
|
- struct mutex notif_wait_lock; /* Only one at a time */
|
|
- /* Notification received */
|
|
- struct completion completion;
|
|
- /* Notification lock */
|
|
- struct mutex exit_code_lock;
|
|
- /* Last notification */
|
|
- int32_t exit_code;
|
|
- /* Session id */
|
|
- uint32_t id;
|
|
- /* Session state (protected by mcp sessions_lock) */
|
|
- enum mcp_session_state {
|
|
- MCP_SESSION_RUNNING,
|
|
- MCP_SESSION_CLOSE_PREPARE,
|
|
- MCP_SESSION_CLOSE_NOTIFIED,
|
|
- MCP_SESSION_CLOSING_GP,
|
|
- MCP_SESSION_CLOSED,
|
|
- } state;
|
|
- /* This TA is of Global Platform type, set by upper layer */
|
|
- bool is_gp;
|
|
- /* GP TAs have login information */
|
|
- struct identity identity;
|
|
-};
|
|
-
|
|
-/* Init for the mcp_session structure */
|
|
-void mcp_session_init(struct mcp_session *session, bool is_gp,
|
|
- const struct identity *identity);
|
|
-int mcp_session_waitnotif(struct mcp_session *session, int32_t timeout);
|
|
-int32_t mcp_session_exitcode(struct mcp_session *mcp_session);
|
|
-
|
|
-/* SWd suspend/resume */
|
|
-int mcp_suspend(void);
|
|
-int mcp_resume(void);
|
|
-bool mcp_suspended(void);
|
|
-
|
|
-/* Callback to scheduler registration */
|
|
-enum mcp_scheduler_commands {
|
|
- MCP_YIELD,
|
|
- MCP_NSIQ,
|
|
-};
|
|
-
|
|
-void mcp_register_scheduler(int (*scheduler_cb)(enum mcp_scheduler_commands));
|
|
-bool mcp_notifications_flush(void);
|
|
-void mcp_register_crashhandler(void (*crashhandler_cb)(void));
|
|
-
|
|
-/*
|
|
- * Get the requested SWd sleep timeout value (ms)
|
|
- * - if the timeout is -1, wait indefinitely
|
|
- * - if the timeout is 0, re-schedule immediately (timeouts in µs in the SWd)
|
|
- * - otherwise sleep for the required time
|
|
- * returns true if sleep is required, false otherwise
|
|
- */
|
|
-bool mcp_get_idle_timeout(int32_t *timeout);
|
|
-void mcp_reset_idle_timeout(void);
|
|
-
|
|
-/* MCP commands */
|
|
-int mcp_get_version(struct mc_version_info *version_info);
|
|
-int mcp_load_token(uintptr_t data, const struct mcp_buffer_map *buffer_map);
|
|
-int mcp_load_check(const struct tbase_object *obj,
|
|
- const struct mcp_buffer_map *buffer_map);
|
|
-int mcp_open_session(struct mcp_session *session,
|
|
- const struct tbase_object *obj,
|
|
- const struct mcp_buffer_map *map,
|
|
- const struct mcp_buffer_map *tci_map);
|
|
-int mcp_close_session(struct mcp_session *session);
|
|
-int mcp_map(uint32_t session_id, struct mcp_buffer_map *buffer_map);
|
|
-int mcp_unmap(uint32_t session_id, const struct mcp_buffer_map *buffer_map);
|
|
-int mcp_multimap(uint32_t session_id, struct mcp_buffer_map *buffer_maps);
|
|
-int mcp_multiunmap(uint32_t session_id,
|
|
- const struct mcp_buffer_map *buffer_maps);
|
|
-int mcp_notify(struct mcp_session *mcp_session);
|
|
-
|
|
-/* MCP initialisation/cleanup */
|
|
-int mcp_init(void);
|
|
-void mcp_exit(void);
|
|
-int mcp_start(void);
|
|
-void mcp_stop(void);
|
|
-
|
|
-#endif /* _MC_MCP_H_ */
|
|
diff --git a/drivers/gud/MobiCoreDriver/mmu.c b/drivers/gud/MobiCoreDriver/mmu.c
|
|
deleted file mode 100644
|
|
index fc769be4d15db..0000000000000
|
|
--- a/drivers/gud/MobiCoreDriver/mmu.c
|
|
+++ /dev/null
|
|
@@ -1,450 +0,0 @@
|
|
-/*
|
|
- * Copyright (c) 2013-2015 TRUSTONIC LIMITED
|
|
- * All Rights Reserved.
|
|
- *
|
|
- * This program is free software; you can redistribute it and/or
|
|
- * modify it under the terms of the GNU General Public License
|
|
- * version 2 as published by the Free Software Foundation.
|
|
- *
|
|
- * This program is distributed in the hope that it will be useful,
|
|
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
- * GNU General Public License for more details.
|
|
- */
|
|
-
|
|
-#include <asm/pgtable.h>
|
|
-#include <linux/semaphore.h>
|
|
-#include <linux/completion.h>
|
|
-#include <linux/mutex.h>
|
|
-#include <linux/highmem.h>
|
|
-#include <linux/slab.h>
|
|
-#include <linux/kthread.h>
|
|
-#include <linux/pagemap.h>
|
|
-#include <linux/device.h>
|
|
-
|
|
-#include "public/mc_linux.h"
|
|
-
|
|
-#include "mci/mcimcp.h"
|
|
-
|
|
-#include "platform.h" /* CONFIG_TRUSTONIC_TEE_LPAE */
|
|
-#include "main.h"
|
|
-#include "debug.h"
|
|
-#include "mcp.h" /* mcp_buffer_map */
|
|
-#include "mmu.h"
|
|
-
|
|
-#ifdef CONFIG_TRUSTONIC_TEE_LPAE
|
|
-#define MMU_TYPE_PAGE (3 << 0)
|
|
-#define MMU_BUFFERABLE BIT(2) /* AttrIndx[0] */
|
|
-#define MMU_CACHEABLE BIT(3) /* AttrIndx[1] */
|
|
-#define MMU_NS BIT(5)
|
|
-#define MMU_AP_RW_ALL BIT(6) /* AP[2:1], RW, at any privilege level */
|
|
-#define MMU_EXT_SHARED (3 << 8) /* SH[1:0], inner shareable */
|
|
-#define MMU_EXT_AF BIT(10) /* Access Flag */
|
|
-#define MMU_EXT_NG BIT(11)
|
|
-#define MMU_EXT_XN (((uint64_t)1) << 54) /* XN */
|
|
-#else
|
|
-#define MMU_TYPE_EXT (3 << 0) /* v5 */
|
|
-#define MMU_TYPE_SMALL (2 << 0)
|
|
-#define MMU_BUFFERABLE BIT(2)
|
|
-#define MMU_CACHEABLE BIT(3)
|
|
-#define MMU_EXT_AP0 BIT(4)
|
|
-#define MMU_EXT_AP1 (2 << 4)
|
|
-#define MMU_EXT_TEX(x) ((x) << 6) /* v5 */
|
|
-#define MMU_EXT_SHARED BIT(10) /* v6 */
|
|
-#define MMU_EXT_NG BIT(11) /* v6 */
|
|
-#endif
|
|
-
|
|
-/*
|
|
- * MobiCore specific page tables for world shared memory.
|
|
- * Linux uses shadow page tables, see arch/arm/include/asm/pgtable-2level.
|
|
- * MobiCore uses the default ARM format.
|
|
- *
|
|
- * Number of page table entries in one L2 MMU table. This is ARM specific, an
|
|
- * MMU table covers 1 MiB by using 256 entries referring to 4KiB pages each.
|
|
- */
|
|
-#define L2_ENTRIES_MAX 256
|
|
-
|
|
-/*
|
|
- * Small buffers (below 1MiB) are mapped using the legacy L2 table, but bigger
|
|
- * buffers now use a fake L1 table that holds 64-bit pointers to L2 tables. As
|
|
- * this must be exactly one page, we can hold up to 512 entries.
|
|
- */
|
|
-#define L1_ENTRIES_MAX 512
|
|
-
|
|
-#ifdef CONFIG_TRUSTONIC_TEE_LPAE
|
|
-
|
|
-/*
|
|
- * Secure world uses 64-bit physical addresses
|
|
- */
|
|
-typedef u64 tbase_pte_t;
|
|
-
|
|
-/*
|
|
- * Linux uses different mappings for SMP systems(the sharing flag is set for
|
|
- * the pte. In order not to confuse things too much in Mobicore make sure the
|
|
- * shared buffers have the same flags. This should also be done in SWD side.
|
|
- */
|
|
-static tbase_pte_t pte_flags = MMU_BUFFERABLE | MMU_CACHEABLE | MMU_EXT_NG |
|
|
-#ifdef CONFIG_SMP
|
|
- MMU_EXT_SHARED |
|
|
-#endif /* CONFIG_SMP */
|
|
- MMU_EXT_XN | MMU_EXT_AF | MMU_AP_RW_ALL |
|
|
- MMU_NS | MMU_TYPE_PAGE;
|
|
-
|
|
-#else /* CONFIG_TRUSTONIC_TEE_LPAE */
|
|
-
|
|
-/*
|
|
- * Secure world uses 32-bit physical addresses
|
|
- */
|
|
-typedef u32 tbase_pte_t;
|
|
-
|
|
-/*
|
|
- * Linux uses different mappings for SMP systems(the sharing flag is set for
|
|
- * the pte. In order not to confuse things too much in Mobicore make sure the
|
|
- * shared buffers have the same flags. This should also be done in SWD side.
|
|
- */
|
|
-static tbase_pte_t pte_flags = MMU_BUFFERABLE | MMU_CACHEABLE | MMU_EXT_NG |
|
|
-#ifdef CONFIG_SMP
|
|
- MMU_EXT_SHARED | MMU_EXT_TEX(1) |
|
|
-#endif /* CONFIG_SMP */
|
|
- MMU_EXT_AP1 | MMU_EXT_AP0 |
|
|
- MMU_TYPE_SMALL | MMU_TYPE_EXT;
|
|
-
|
|
-#endif /* !CONFIG_TRUSTONIC_TEE_LPAE */
|
|
-
|
|
-/*
|
|
- * Fake L1 MMU table.
|
|
- */
|
|
-union l1_table {
|
|
- u64 *pages_phys; /* Array of physical page addresses */
|
|
- unsigned long page;
|
|
-};
|
|
-
|
|
-/*
|
|
- * L2 MMU table, which is more a L3 table in the LPAE case.
|
|
- */
|
|
-union l2_table {
|
|
- tbase_pte_t *ptes; /* Array of PTEs */
|
|
- unsigned long page;
|
|
-};
|
|
-
|
|
-/*
|
|
- * MMU table allocated to the Daemon or a TLC describing a world shared
|
|
- * buffer.
|
|
- * When users map a malloc()ed area into SWd, a MMU table is allocated.
|
|
- * In addition, the area of maximum 1MB virtual address space is mapped into
|
|
- * the MMU table and a handle for this table is returned to the user.
|
|
- */
|
|
-struct tbase_mmu {
|
|
- union l2_table l2_tables[L1_ENTRIES_MAX]; /* L2 tables */
|
|
- size_t l2_tables_nr; /* Actual number of L2 tables */
|
|
- union l1_table l1_table; /* Fake L1 table */
|
|
- union l2_table l1_l2_table; /* L2 table for the L1 table */
|
|
- uint32_t offset;
|
|
- uint32_t length;
|
|
- bool user; /* Pages are from user space */
|
|
-};
|
|
-
|
|
-static void free_all_pages(struct tbase_mmu *mmu_table)
|
|
-{
|
|
- union l2_table *l2_table = &mmu_table->l2_tables[0];
|
|
- size_t i;
|
|
-
|
|
- for (i = 0; i < mmu_table->l2_tables_nr; i++, l2_table++) {
|
|
- if (!l2_table->page)
|
|
- break;
|
|
-
|
|
- free_page(l2_table->page);
|
|
- }
|
|
-
|
|
- if (mmu_table->l1_l2_table.page)
|
|
- free_page(mmu_table->l1_l2_table.page);
|
|
-
|
|
- if (mmu_table->l1_table.page)
|
|
- free_page(mmu_table->l1_table.page);
|
|
-}
|
|
-
|
|
-/*
|
|
- * Create a MMU table for a buffer or trustlet.
|
|
- */
|
|
-static inline int map_buffer(struct task_struct *task, const void *data,
|
|
- unsigned int length, struct tbase_mmu *mmu_table)
|
|
-{
|
|
- const void *reader = (const void *)((uintptr_t)data & PAGE_MASK);
|
|
- struct page **pages; /* Same as above, conveniently typed */
|
|
- unsigned long pages_page; /* Page to contain the page pointers */
|
|
- size_t chunk;
|
|
- unsigned long total_pages_nr;
|
|
- int l1_entries_max;
|
|
- int ret = 0;
|
|
-
|
|
- /* Check that we have enough space to map data */
|
|
- mmu_table->length = length;
|
|
- mmu_table->offset = (uintptr_t)data & ~PAGE_MASK;
|
|
- total_pages_nr = PAGE_ALIGN(mmu_table->offset + length) / PAGE_SIZE;
|
|
- if (g_ctx.f_mem_ext)
|
|
- l1_entries_max = L1_ENTRIES_MAX;
|
|
- else
|
|
- l1_entries_max = 1;
|
|
-
|
|
- if (total_pages_nr > (l1_entries_max * L2_ENTRIES_MAX)) {
|
|
- dev_err(g_ctx.mcd, "data mapping exceeds %d pages",
|
|
- l1_entries_max * L2_ENTRIES_MAX);
|
|
- return -EINVAL;
|
|
- }
|
|
-
|
|
- /* Get number of L2 tables needed */
|
|
- mmu_table->l2_tables_nr = (total_pages_nr + L2_ENTRIES_MAX - 1) /
|
|
- L2_ENTRIES_MAX;
|
|
- dev_dbg(g_ctx.mcd, "total_pages_nr %lu l2_tables_nr %zu",
|
|
- total_pages_nr, mmu_table->l2_tables_nr);
|
|
-
|
|
- /* Get a page to store page pointers */
|
|
- pages_page = get_zeroed_page(GFP_KERNEL);
|
|
- if (!pages_page)
|
|
- return -ENOMEM;
|
|
-
|
|
- pages = (struct page **)pages_page;
|
|
-
|
|
- /* Allocate a page for the L1 table */
|
|
- if (mmu_table->l2_tables_nr > 1) {
|
|
- tbase_pte_t *pte;
|
|
-
|
|
- mmu_table->l1_table.page = get_zeroed_page(GFP_KERNEL);
|
|
- mmu_table->l1_l2_table.page = get_zeroed_page(GFP_KERNEL);
|
|
- if (!mmu_table->l1_table.page || !mmu_table->l1_l2_table.page) {
|
|
- ret = -ENOMEM;
|
|
- goto end;
|
|
- }
|
|
-
|
|
- /* Map it */
|
|
- pte = &mmu_table->l1_l2_table.ptes[0];
|
|
- *pte = virt_to_phys(mmu_table->l1_table.pages_phys);
|
|
- *pte |= pte_flags;
|
|
- }
|
|
-
|
|
- for (chunk = 0; chunk < mmu_table->l2_tables_nr; chunk++) {
|
|
- unsigned long pages_nr, i;
|
|
- tbase_pte_t *pte;
|
|
- struct page **page_ptr;
|
|
-
|
|
- /* Size to map for this chunk */
|
|
- if (chunk == (mmu_table->l2_tables_nr - 1))
|
|
- pages_nr = ((total_pages_nr - 1) % L2_ENTRIES_MAX) + 1;
|
|
- else
|
|
- pages_nr = L2_ENTRIES_MAX;
|
|
-
|
|
- /* Allocate a page for the MMU descriptor */
|
|
- mmu_table->l2_tables[chunk].page = get_zeroed_page(GFP_KERNEL);
|
|
- if (!mmu_table->l2_tables[chunk].page) {
|
|
- ret = -ENOMEM;
|
|
- goto end;
|
|
- }
|
|
-
|
|
- /* Add page address to L1 table if needed */
|
|
- if (mmu_table->l1_table.page)
|
|
- mmu_table->l1_table.pages_phys[chunk] =
|
|
- virt_to_phys(mmu_table->l2_tables[chunk].ptes);
|
|
-
|
|
- /* Get pages */
|
|
- if (task) {
|
|
- long gup_ret;
|
|
-
|
|
- /* Buffer was allocated in user space */
|
|
- down_read(&task->mm->mmap_sem);
|
|
- gup_ret = get_user_pages(task, task->mm,
|
|
- (uintptr_t)reader, pages_nr,
|
|
- 1, 0, pages, 0);
|
|
- reader += pages_nr * PAGE_SIZE;
|
|
- up_read(&task->mm->mmap_sem);
|
|
- if (gup_ret < 0) {
|
|
- ret = gup_ret;
|
|
- dev_err(g_ctx.mcd,
|
|
- "failed to get user pages: %d", ret);
|
|
- goto end;
|
|
- }
|
|
-
|
|
- /* check if we could lock all pages. */
|
|
- if (gup_ret != pages_nr) {
|
|
- dev_err(g_ctx.mcd,
|
|
- "get_user_pages() failed, ret: %ld",
|
|
- gup_ret);
|
|
- release_pages(pages, gup_ret, 0);
|
|
- ret = -ENOMEM;
|
|
- goto end;
|
|
- }
|
|
-
|
|
- mmu_table->user = true;
|
|
- } else if (is_vmalloc_addr(data)) {
|
|
- /* Buffer vmalloc'ed in kernel space */
|
|
- page_ptr = &pages[0];
|
|
- for (i = 0; i < pages_nr; i++) {
|
|
- struct page *page = vmalloc_to_page(reader);
|
|
-
|
|
- if (!page) {
|
|
- dev_err(g_ctx.mcd,
|
|
- "failed to map address");
|
|
- ret = -EINVAL;
|
|
- goto end;
|
|
- }
|
|
-
|
|
- *page_ptr++ = page;
|
|
- reader += PAGE_SIZE;
|
|
- }
|
|
- } else {
|
|
- /* Buffer kmalloc'ed in kernel space */
|
|
- struct page *page = virt_to_page(reader);
|
|
-
|
|
- reader += pages_nr * PAGE_SIZE;
|
|
- page_ptr = &pages[0];
|
|
- for (i = 0; i < pages_nr; i++)
|
|
- *page_ptr++ = page++;
|
|
- }
|
|
-
|
|
- /* Create MMU Table entries */
|
|
- page_ptr = &pages[0];
|
|
- pte = &mmu_table->l2_tables[chunk].ptes[0];
|
|
- for (i = 0; i < pages_nr; i++, page_ptr++, pte++) {
|
|
- /*
|
|
- * Create MMU table entry, see ARM MMU docu for details
|
|
- * about flags stored in the lowest 12 bits. As a side
|
|
- * reference, the Article "ARM's multiply-mapped memory
|
|
- * mess" found in the collection at
|
|
- * http://lwn.net/Articles/409032/ is also worth reading.
|
|
- */
|
|
- unsigned long phys = page_to_phys(*page_ptr);
|
|
-#if defined CONFIG_ARM64 && !defined CONFIG_TRUSTONIC_TEE_LPAE
|
|
- if (phys & 0xffffffff00000000) {
|
|
- dev_err(g_ctx.mcd,
|
|
- "Pointer too big for non-LPAE: 0x%16lx",
|
|
- phys);
|
|
- ret = -EFAULT;
|
|
- goto end;
|
|
- }
|
|
-#endif
|
|
- *pte = phys;
|
|
- *pte |= pte_flags;
|
|
- }
|
|
- }
|
|
-
|
|
-end:
|
|
- if (ret)
|
|
- free_all_pages(mmu_table);
|
|
-
|
|
- free_page(pages_page);
|
|
- return ret;
|
|
-}
|
|
-
|
|
-static inline void unmap_buffer(struct tbase_mmu *mmu_table)
|
|
-{
|
|
- int t;
|
|
-
|
|
- dev_dbg(g_ctx.mcd, "clear MMU table, virt %p", mmu_table);
|
|
- if (!mmu_table->user)
|
|
- goto end;
|
|
-
|
|
- /* Release all locked user space pages */
|
|
- for (t = 0; t < mmu_table->l2_tables_nr; t++) {
|
|
- tbase_pte_t *pte = mmu_table->l2_tables[t].ptes;
|
|
- int i;
|
|
-
|
|
- for (i = 0; i < L2_ENTRIES_MAX; i++, pte++) {
|
|
- struct page *page;
|
|
-
|
|
- /* If not all entries are used, unused ones are 0 */
|
|
- if (!*pte)
|
|
- break;
|
|
-
|
|
- /* pte_page() cannot return NULL */
|
|
- page = pte_page(*pte);
|
|
- dev_dbg(g_ctx.mcd, "MMU entry %d: 0x%llx, virt %p",
|
|
- i, (u64)*pte, page);
|
|
-
|
|
- page_cache_release(page);
|
|
- }
|
|
- }
|
|
-
|
|
-end:
|
|
- free_all_pages(mmu_table);
|
|
-}
|
|
-
|
|
-/*
|
|
- * Delete a MMU table.
|
|
- */
|
|
-void tbase_mmu_delete(struct tbase_mmu *mmu)
|
|
-{
|
|
- if (WARN(!mmu, "NULL mmu pointer given"))
|
|
- return;
|
|
-
|
|
- unmap_buffer(mmu);
|
|
- MCDRV_DBG("freed mmu %p: %s len %u off %u table %lx type L%d",
|
|
- mmu, mmu->user ? "user" : "kernel", mmu->length, mmu->offset,
|
|
- (uintptr_t)(mmu->l1_table.page ? mmu->l1_l2_table.ptes :
|
|
- mmu->l2_tables[0].ptes),
|
|
- mmu->l1_table.page ? 1 : 2);
|
|
- kfree(mmu);
|
|
-}
|
|
-
|
|
-/*
|
|
- * Allocate MMU table and map buffer into it.
|
|
- * That is, create respective table entries.
|
|
- */
|
|
-struct tbase_mmu *tbase_mmu_create(struct task_struct *task,
|
|
- const void *addr,
|
|
- unsigned int length)
|
|
-{
|
|
- struct tbase_mmu *mmu;
|
|
- int ret;
|
|
-
|
|
- /* Check input arguments */
|
|
- if (WARN(!addr, "data address is NULL"))
|
|
- return ERR_PTR(-EINVAL);
|
|
-
|
|
- if (WARN(!length, "data length is 0"))
|
|
- return ERR_PTR(-EINVAL);
|
|
-
|
|
- /* Allocate the struct */
|
|
- mmu = kmalloc(sizeof(*mmu), GFP_KERNEL | __GFP_ZERO);
|
|
- if (!mmu)
|
|
- return ERR_PTR(-ENOMEM);
|
|
-
|
|
- /* Create the MMU mapping for the data */
|
|
- ret = map_buffer(task, addr, length, mmu);
|
|
- if (ret) {
|
|
- kfree(mmu);
|
|
- return ERR_PTR(ret);
|
|
- }
|
|
-
|
|
- MCDRV_DBG("created mmu %p: %s addr %p len %u off %u table %lx type L%d",
|
|
- mmu, mmu->user ? "user" : "kernel", addr, mmu->length,
|
|
- mmu->offset,
|
|
- (uintptr_t)(mmu->l1_table.page ? mmu->l1_l2_table.ptes :
|
|
- mmu->l2_tables[0].ptes),
|
|
- mmu->l1_table.page ? 1 : 2);
|
|
- return mmu;
|
|
-}
|
|
-
|
|
-void tbase_mmu_buffer(const struct tbase_mmu *mmu, struct mcp_buffer_map *map)
|
|
-{
|
|
- if (mmu->l1_table.page) {
|
|
- map->phys_addr = virt_to_phys(mmu->l1_l2_table.ptes);
|
|
- map->type = WSM_L1;
|
|
- } else {
|
|
- map->phys_addr = virt_to_phys(mmu->l2_tables[0].ptes);
|
|
- map->type = WSM_L2;
|
|
- }
|
|
-
|
|
- map->secure_va = 0;
|
|
- map->offset = mmu->offset;
|
|
- map->length = mmu->length;
|
|
-}
|
|
-
|
|
-int tbase_mmu_info(const struct tbase_mmu *mmu, struct kasnprintf_buf *buf)
|
|
-{
|
|
- return kasnprintf(buf,
|
|
- "\t\t\tmmu %p: %s len %u off %u table %lx type L%d\n",
|
|
- mmu, mmu->user ? "user" : "kernel", mmu->length,
|
|
- mmu->offset,
|
|
- (uintptr_t)(mmu->l1_table.page ?
|
|
- mmu->l1_l2_table.ptes : mmu->l2_tables[0].ptes),
|
|
- mmu->l1_table.page ? 1 : 2);
|
|
-}
|
|
diff --git a/drivers/gud/MobiCoreDriver/mmu.h b/drivers/gud/MobiCoreDriver/mmu.h
|
|
deleted file mode 100644
|
|
index 09efea480bef8..0000000000000
|
|
--- a/drivers/gud/MobiCoreDriver/mmu.h
|
|
+++ /dev/null
|
|
@@ -1,44 +0,0 @@
|
|
-/*
|
|
- * Copyright (c) 2013-2015 TRUSTONIC LIMITED
|
|
- * All Rights Reserved.
|
|
- *
|
|
- * This program is free software; you can redistribute it and/or
|
|
- * modify it under the terms of the GNU General Public License
|
|
- * version 2 as published by the Free Software Foundation.
|
|
- *
|
|
- * This program is distributed in the hope that it will be useful,
|
|
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
- * GNU General Public License for more details.
|
|
- */
|
|
-
|
|
-#ifndef _TBASE_MEM_H_
|
|
-#define _TBASE_MEM_H_
|
|
-
|
|
-struct tbase_mmu;
|
|
-struct mcp_buffer_map;
|
|
-
|
|
-/*
|
|
- * Allocate MMU table and map buffer into it.
|
|
- * That is, create respective table entries.
|
|
- */
|
|
-struct tbase_mmu *tbase_mmu_create(struct task_struct *task,
|
|
- const void *wsm_buffer,
|
|
- unsigned int wsm_len);
|
|
-
|
|
-/*
|
|
- * Delete a used MMU table.
|
|
- */
|
|
-void tbase_mmu_delete(struct tbase_mmu *mmu);
|
|
-
|
|
-/*
|
|
- * Fill in buffer info for MMU table.
|
|
- */
|
|
-void tbase_mmu_buffer(const struct tbase_mmu *mmu, struct mcp_buffer_map *map);
|
|
-
|
|
-/*
|
|
- * Add info to debug buffer.
|
|
- */
|
|
-int tbase_mmu_info(const struct tbase_mmu *mmu, struct kasnprintf_buf *buf);
|
|
-
|
|
-#endif /* _TBASE_MEM_H_ */
|
|
diff --git a/drivers/gud/MobiCoreDriver/platform.h b/drivers/gud/MobiCoreDriver/platform.h
|
|
deleted file mode 100644
|
|
index f9c801450f64e..0000000000000
|
|
--- a/drivers/gud/MobiCoreDriver/platform.h
|
|
+++ /dev/null
|
|
@@ -1,150 +0,0 @@
|
|
-/*
|
|
- * Copyright (c) 2013-2014 TRUSTONIC LIMITED
|
|
- * All Rights Reserved.
|
|
- *
|
|
- * This program is free software; you can redistribute it and/or
|
|
- * modify it under the terms of the GNU General Public License
|
|
- * version 2 as published by the Free Software Foundation.
|
|
- *
|
|
- * This program is distributed in the hope that it will be useful,
|
|
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
- * GNU General Public License for more details.
|
|
- */
|
|
-#ifndef _MC_PLATFORM_H_
|
|
-#define _MC_PLATFORM_H_
|
|
-
|
|
-/* MobiCore Interrupt for Qualcomm (DT IRQ has priority if present) */
|
|
-#define MC_INTR_SSIQ 280
|
|
-
|
|
-/* Use SMC for fastcalls */
|
|
-#define MC_SMC_FASTCALL
|
|
-
|
|
-#include <linux/types.h>
|
|
-
|
|
-/*--------------- Implementation -------------- */
|
|
-#if defined(CONFIG_ARCH_APQ8084) || defined(CONFIG_ARCH_MSM8916) || \
|
|
- defined(CONFIG_ARCH_MSM8994) || defined(CONFIG_ARCH_MSM8909) || \
|
|
- defined(CONFIG_ARCH_MSM8996)
|
|
-
|
|
-#include <soc/qcom/scm.h>
|
|
-
|
|
-#if defined(CONFIG_ARM64) || defined(CONFIG_ARCH_MSM8916)
|
|
-
|
|
- #include <soc/qcom/qseecomi.h>
|
|
- #include <linux/slab.h>
|
|
- #include <linux/io.h>
|
|
- #include <linux/mm.h>
|
|
- #include <asm/cacheflush.h>
|
|
- #include <linux/errno.h>
|
|
-
|
|
- #define SCM_MOBIOS_FNID(s, c) (((((s) & 0xFF) << 8) | ((c) & 0xFF)) \
|
|
- | 0x33000000)
|
|
-
|
|
- #define TZ_EXECUTIVE_EXT_ID_PARAM_ID \
|
|
- TZ_SYSCALL_CREATE_PARAM_ID_4( \
|
|
- TZ_SYSCALL_PARAM_TYPE_BUF_RW, \
|
|
- TZ_SYSCALL_PARAM_TYPE_VAL, \
|
|
- TZ_SYSCALL_PARAM_TYPE_BUF_RW, \
|
|
- TZ_SYSCALL_PARAM_TYPE_VAL)
|
|
-
|
|
-#endif
|
|
-
|
|
-#else
|
|
-#include <mach/scm.h>
|
|
-#endif
|
|
-
|
|
-/* from following file */
|
|
-#define SCM_SVC_MOBICORE 250
|
|
-#define SCM_CMD_MOBICORE 1
|
|
-
|
|
-static inline int smc_fastcall(void *fc_generic, size_t size)
|
|
-{
|
|
-#if defined(CONFIG_ARCH_APQ8084) || defined(CONFIG_ARCH_MSM8916) || \
|
|
- defined(CONFIG_ARCH_MSM8994) || defined(CONFIG_ARCH_MSM8996)
|
|
- if (is_scm_armv8()) {
|
|
- struct scm_desc desc = {0};
|
|
- int ret;
|
|
- void *scm_buf = NULL;
|
|
-
|
|
- scm_buf = kzalloc(PAGE_ALIGN(size), GFP_KERNEL);
|
|
- if (!scm_buf)
|
|
- return -ENOMEM;
|
|
- memcpy(scm_buf, fc_generic, size);
|
|
- dmac_flush_range(scm_buf, scm_buf + size);
|
|
-
|
|
- desc.arginfo = TZ_EXECUTIVE_EXT_ID_PARAM_ID;
|
|
- desc.args[0] = virt_to_phys(scm_buf);
|
|
- desc.args[1] = (u32)size;
|
|
- desc.args[2] = virt_to_phys(scm_buf);
|
|
- desc.args[3] = (u32)size;
|
|
-
|
|
- ret = scm_call2(
|
|
- SCM_MOBIOS_FNID(SCM_SVC_MOBICORE, SCM_CMD_MOBICORE),
|
|
- &desc);
|
|
-
|
|
- dmac_flush_range(scm_buf, scm_buf + size);
|
|
-
|
|
- memcpy(fc_generic, scm_buf, size);
|
|
- kfree(scm_buf);
|
|
- return ret;
|
|
- }
|
|
-#endif
|
|
-
|
|
- return scm_call(SCM_SVC_MOBICORE, SCM_CMD_MOBICORE,
|
|
- fc_generic, size,
|
|
- fc_generic, size);
|
|
-}
|
|
-
|
|
-/* Fastcall value should be the one for armv7, even if on armv8,
|
|
- * as long as the __aarch32__ flag is not activated in SW.
|
|
- * But for 8996, architecture is armv8 with __aarch32__ in Sw.
|
|
- */
|
|
-#if !defined(CONFIG_ARCH_MSM8996)
|
|
-#define MC_ARMV7_FC
|
|
-#endif
|
|
-
|
|
-#if defined(CONFIG_ARCH_MSM8996)
|
|
-#define CONFIG_TRUSTONIC_TEE_LPAE
|
|
-#endif
|
|
-
|
|
-/*
|
|
- * Perform crypto clock enable/disable
|
|
- * of clocks
|
|
- * "bus_clk"
|
|
- * "core_clk"
|
|
- * "iface_clk"
|
|
- */
|
|
-#if (!defined(CONFIG_ARCH_MSM8960) && !defined(CONFIG_ARCH_MSM8994)) || \
|
|
- defined(CONFIG_ARCH_MSM8996)
|
|
-#define MC_CRYPTO_CLOCK_MANAGEMENT
|
|
-#endif
|
|
-
|
|
-/*
|
|
- * Perform clock enable/disable for clock "core_clk_src"
|
|
- */
|
|
-#if defined(CONFIG_ARCH_MSM8916) || defined(CONFIG_ARCH_MSM8909) || \
|
|
- defined(CONFIG_ARCH_MSM8996)
|
|
-#define MC_DEVICE_PROPNAME "qcom,mcd"
|
|
-#if defined(MC_CRYPTO_CLOCK_MANAGEMENT)
|
|
-#define MC_CLOCK_CORESRC_PROPNAME "qcom,ce-opp-freq"
|
|
-#define MC_CLOCK_CORESRC_DEFAULTRATE 100000000
|
|
-#endif /* MC_CRYPTO_CLOCK_MANAGEMENT */
|
|
-#endif
|
|
-
|
|
-
|
|
-#if !defined(CONFIG_ARCH_MSM8996)
|
|
-/* uid/gid behave like old kernels but with new types */
|
|
-/* This flag does not exist on 8996 3.10 kernel version */
|
|
-#if !defined(CONFIG_UIDGID_STRICT_TYPE_CHECKS)
|
|
-#define MC_UIDGID_OLDSTYLE
|
|
-#endif
|
|
-/* Fastcall value should be the one for armv7, even if on armv8,
|
|
- * as long as the __aarch32__ flag is not activated in SW.
|
|
- * But for 8996, architecture is armv8 with __aarch32__ in Sw.
|
|
- */
|
|
-#define MC_ARMV7_FC
|
|
-#endif /* not CONFIG_ARCH_MSM8996 */
|
|
-
|
|
-#endif /* _MC_PLATFORM_H_ */
|
|
-
|
|
diff --git a/drivers/gud/MobiCoreDriver/pm.c b/drivers/gud/MobiCoreDriver/pm.c
|
|
deleted file mode 100644
|
|
index 98310f73dfeab..0000000000000
|
|
--- a/drivers/gud/MobiCoreDriver/pm.c
|
|
+++ /dev/null
|
|
@@ -1,62 +0,0 @@
|
|
-/*
|
|
- * Copyright (c) 2013-2015 TRUSTONIC LIMITED
|
|
- * All Rights Reserved.
|
|
- *
|
|
- * This program is free software; you can redistribute it and/or
|
|
- * modify it under the terms of the GNU General Public License
|
|
- * version 2 as published by the Free Software Foundation.
|
|
- *
|
|
- * This program is distributed in the hope that it will be useful,
|
|
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
- * GNU General Public License for more details.
|
|
- */
|
|
-#include <linux/module.h>
|
|
-#include <linux/device.h>
|
|
-#include <linux/suspend.h>
|
|
-#include <linux/err.h>
|
|
-
|
|
-#include "public/mc_linux.h"
|
|
-
|
|
-#include "platform.h" /* MC_PM_RUNTIME */
|
|
-#include "debug.h"
|
|
-#include "scheduler.h" /* SWd suspend/resume commands */
|
|
-#include "pm.h"
|
|
-
|
|
-#ifdef MC_PM_RUNTIME
|
|
-static struct pm_context {
|
|
- struct notifier_block pm_notifier;
|
|
-} pm_ctx;
|
|
-
|
|
-static int mc_suspend_notifier(struct notifier_block *nb, unsigned long event,
|
|
- void *dummy)
|
|
-{
|
|
- switch (event) {
|
|
- case PM_SUSPEND_PREPARE:
|
|
- return mc_scheduler_suspend();
|
|
- case PM_POST_SUSPEND:
|
|
- return mc_scheduler_resume();
|
|
- }
|
|
-
|
|
- return 0;
|
|
-}
|
|
-
|
|
-
|
|
-/* CPI todo: inconsistent handling of ret in below 2 functions */
|
|
-int mc_pm_start(void)
|
|
-{
|
|
- int ret = 0;
|
|
-
|
|
- pm_ctx.pm_notifier.notifier_call = mc_suspend_notifier;
|
|
- ret = register_pm_notifier(&pm_ctx.pm_notifier);
|
|
- MCDRV_DBG_VERBOSE("done, ret = %d", ret);
|
|
-
|
|
- return ret;
|
|
-}
|
|
-
|
|
-void mc_pm_stop(void)
|
|
-{
|
|
- unregister_pm_notifier(&pm_ctx.pm_notifier);
|
|
-}
|
|
-
|
|
-#endif /* MC_PM_RUNTIME */
|
|
diff --git a/drivers/gud/MobiCoreDriver/pm.h b/drivers/gud/MobiCoreDriver/pm.h
|
|
deleted file mode 100644
|
|
index 999599a70b1ab..0000000000000
|
|
--- a/drivers/gud/MobiCoreDriver/pm.h
|
|
+++ /dev/null
|
|
@@ -1,36 +0,0 @@
|
|
-/*
|
|
- * Copyright (c) 2013-2015 TRUSTONIC LIMITED
|
|
- * All Rights Reserved.
|
|
- *
|
|
- * This program is free software; you can redistribute it and/or
|
|
- * modify it under the terms of the GNU General Public License
|
|
- * version 2 as published by the Free Software Foundation.
|
|
- *
|
|
- * This program is distributed in the hope that it will be useful,
|
|
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
- * GNU General Public License for more details.
|
|
- */
|
|
-
|
|
-#ifndef _MC_PM_H_
|
|
-#define _MC_PM_H_
|
|
-
|
|
-#include "platform.h" /* MC_PM_RUNTIME */
|
|
-
|
|
-#ifdef MC_PM_RUNTIME
|
|
-/* Initialize Power Management */
|
|
-int mc_pm_start(void);
|
|
-/* Free all Power Management resources*/
|
|
-void mc_pm_stop(void);
|
|
-#else
|
|
-static inline int mc_pm_start(void)
|
|
-{
|
|
- return 0;
|
|
-}
|
|
-
|
|
-static inline void mc_pm_stop(void)
|
|
-{
|
|
-}
|
|
-#endif
|
|
-
|
|
-#endif /* _MC_PM_H_ */
|
|
diff --git a/drivers/gud/MobiCoreDriver/public/mc_admin.h b/drivers/gud/MobiCoreDriver/public/mc_admin.h
|
|
deleted file mode 100644
|
|
index 3a4078dd6fc30..0000000000000
|
|
--- a/drivers/gud/MobiCoreDriver/public/mc_admin.h
|
|
+++ /dev/null
|
|
@@ -1,80 +0,0 @@
|
|
-/*
|
|
- * Copyright (c) 2013-2014 TRUSTONIC LIMITED
|
|
- * All Rights Reserved.
|
|
- *
|
|
- * This program is free software; you can redistribute it and/or
|
|
- * modify it under the terms of the GNU General Public License
|
|
- * version 2 as published by the Free Software Foundation.
|
|
- *
|
|
- * This program is distributed in the hope that it will be useful,
|
|
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
- * GNU General Public License for more details.
|
|
- */
|
|
-
|
|
-#ifndef __MC_ADMIN_IOCTL_H__
|
|
-#define __MC_ADMIN_IOCTL_H__
|
|
-
|
|
-#ifdef __cplusplus
|
|
-extern "C" {
|
|
-#endif
|
|
-
|
|
-#define MC_ADMIN_DEVNODE "mobicore"
|
|
-
|
|
-/* Driver/daemon commands */
|
|
-enum {
|
|
- /* Command 0 is reserved */
|
|
- MC_DRV_GET_ROOT_CONTAINER = 1,
|
|
- MC_DRV_GET_SP_CONTAINER = 2,
|
|
- MC_DRV_GET_TRUSTLET_CONTAINER = 3,
|
|
- MC_DRV_GET_TRUSTLET = 4,
|
|
- MC_DRV_SIGNAL_CRASH = 5,
|
|
-};
|
|
-
|
|
-/* MobiCore IOCTL magic number */
|
|
-#define MC_IOC_MAGIC 'M'
|
|
-
|
|
-struct mc_admin_request {
|
|
- uint32_t request_id; /* Unique request identifier */
|
|
- uint32_t command; /* Command to daemon */
|
|
- struct mc_uuid_t uuid; /* UUID of trustlet, if relevant */
|
|
- uint32_t is_gp; /* Whether trustlet is GP */
|
|
- uint32_t spid; /* SPID of trustlet, if relevant */
|
|
-};
|
|
-
|
|
-struct mc_admin_response {
|
|
- uint32_t request_id; /* Unique request identifier */
|
|
- uint32_t error_no; /* Errno from daemon */
|
|
- uint32_t spid; /* SPID of trustlet, if relevant */
|
|
- uint32_t service_type; /* Type of trustlet being returned */
|
|
- uint32_t length; /* Length of data to get */
|
|
- /* Any data follows */
|
|
-};
|
|
-
|
|
-struct mc_admin_driver_info {
|
|
- /* Version, and something else..*/
|
|
- uint32_t drv_version;
|
|
- uint32_t initial_cmd_id;
|
|
-};
|
|
-
|
|
-struct mc_admin_load_info {
|
|
- uint32_t spid; /* SPID of trustlet, if relevant */
|
|
- uint64_t address; /* Address of the data */
|
|
- uint32_t length; /* Length of data to get */
|
|
-};
|
|
-
|
|
-#define MC_ADMIN_IO_GET_DRIVER_REQUEST \
|
|
- _IOR(MC_IOC_MAGIC, 0, struct mc_admin_request)
|
|
-#define MC_ADMIN_IO_GET_INFO \
|
|
- _IOR(MC_IOC_MAGIC, 1, struct mc_admin_driver_info)
|
|
-#define MC_ADMIN_IO_LOAD_DRIVER \
|
|
- _IOW(MC_IOC_MAGIC, 2, struct mc_admin_load_info)
|
|
-#define MC_ADMIN_IO_LOAD_TOKEN \
|
|
- _IOW(MC_IOC_MAGIC, 3, struct mc_admin_load_info)
|
|
-#define MC_ADMIN_IO_LOAD_CHECK \
|
|
- _IOW(MC_IOC_MAGIC, 4, struct mc_admin_load_info)
|
|
-
|
|
-#ifdef __cplusplus
|
|
-}
|
|
-#endif
|
|
-#endif /* __MC_ADMIN_IOCTL_H__ */
|
|
diff --git a/drivers/gud/MobiCoreDriver/public/mc_linux.h b/drivers/gud/MobiCoreDriver/public/mc_linux.h
|
|
deleted file mode 100644
|
|
index 2368653f8890d..0000000000000
|
|
--- a/drivers/gud/MobiCoreDriver/public/mc_linux.h
|
|
+++ /dev/null
|
|
@@ -1,170 +0,0 @@
|
|
-/*
|
|
- * Copyright (c) 2013-2015 TRUSTONIC LIMITED
|
|
- * All Rights Reserved.
|
|
- *
|
|
- * This program is free software; you can redistribute it and/or
|
|
- * modify it under the terms of the GNU General Public License
|
|
- * version 2 as published by the Free Software Foundation.
|
|
- *
|
|
- * This program is distributed in the hope that it will be useful,
|
|
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
- * GNU General Public License for more details.
|
|
- */
|
|
-
|
|
-#ifndef _MC_LINUX_H_
|
|
-#define _MC_LINUX_H_
|
|
-
|
|
-#define MCDRVMODULEAPI_VERSION_MAJOR 2
|
|
-#define MCDRVMODULEAPI_VERSION_MINOR 1
|
|
-
|
|
-#ifndef __KERNEL__
|
|
-#include <stdint.h>
|
|
-#endif
|
|
-
|
|
-#define MC_USER_DEVNODE "mobicore-user"
|
|
-
|
|
-/** Maximum length of MobiCore product ID string. */
|
|
-#define MC_PRODUCT_ID_LEN 64
|
|
-
|
|
-/** Number of buffers that can be mapped at once */
|
|
-#define MC_MAP_MAX 4
|
|
-
|
|
-/*
|
|
- * Universally Unique Identifier (UUID) according to ISO/IEC 11578.
|
|
- */
|
|
-struct mc_uuid_t {
|
|
- uint8_t value[16]; /* Value of the UUID. */
|
|
-};
|
|
-
|
|
-/*
|
|
- * GP TA login types.
|
|
- */
|
|
-enum mc_login_type {
|
|
- TEEC_LOGIN_PUBLIC = 0,
|
|
- TEEC_LOGIN_USER,
|
|
- TEEC_LOGIN_GROUP,
|
|
- TEEC_LOGIN_APPLICATION = 4,
|
|
- TEEC_LOGIN_USER_APPLICATION,
|
|
- TEEC_LOGIN_GROUP_APPLICATION,
|
|
-};
|
|
-
|
|
-/*
|
|
- * GP TA identity structure.
|
|
- */
|
|
-struct mc_identity {
|
|
- enum mc_login_type login_type;
|
|
- union {
|
|
- uint8_t login_data[16];
|
|
- gid_t gid; /* Requested group id */
|
|
- struct {
|
|
- uid_t euid;
|
|
- uid_t ruid;
|
|
- } uid;
|
|
- };
|
|
-};
|
|
-
|
|
-/*
|
|
- * Data exchange structure of the MC_IO_OPEN_SESSION ioctl command.
|
|
- */
|
|
-struct mc_ioctl_open_sess {
|
|
- struct mc_uuid_t uuid; /* trustlet uuid */
|
|
- uint32_t is_gp_uuid; /* uuid is for GP TA */
|
|
- uint32_t sid; /* session id (out) */
|
|
- uint64_t tci; /* tci buffer pointer */
|
|
- uint32_t tcilen; /* tci length */
|
|
- struct mc_identity identity; /* GP TA identity */
|
|
-};
|
|
-
|
|
-/*
|
|
- * Data exchange structure of the MC_IO_OPEN_TRUSTLET ioctl command.
|
|
- */
|
|
-struct mc_ioctl_open_trustlet {
|
|
- uint32_t sid; /* session id (out) */
|
|
- uint32_t spid; /* trustlet spid */
|
|
- uint64_t buffer; /* trustlet binary pointer */
|
|
- uint32_t tlen; /* binary length */
|
|
- uint64_t tci; /* tci buffer pointer */
|
|
- uint32_t tcilen; /* tci length */
|
|
-};
|
|
-
|
|
-/*
|
|
- * Data exchange structure of the MC_IO_WAIT ioctl command.
|
|
- */
|
|
-struct mc_ioctl_wait {
|
|
- uint32_t sid; /* session id (in) */
|
|
- int32_t timeout; /* notification timeout */
|
|
-};
|
|
-
|
|
-/*
|
|
- * Data exchange structure of the MC_IO_ALLOC ioctl command.
|
|
- */
|
|
-struct mc_ioctl_alloc {
|
|
- uint32_t len; /* buffer length */
|
|
- uint32_t handle; /* user handle for the buffer (out) */
|
|
-};
|
|
-
|
|
-/*
|
|
- * Buffer mapping incoming and outgoing information.
|
|
- */
|
|
-struct mc_ioctl_buffer {
|
|
- uint64_t va; /* user space address of buffer */
|
|
- uint32_t len; /* buffer length */
|
|
- uint64_t sva; /* SWd virt address of buffer (out) */
|
|
-};
|
|
-
|
|
-/*
|
|
- * Data exchange structure of the MC_IO_MAP and MC_IO_UNMAP ioctl commands.
|
|
- */
|
|
-struct mc_ioctl_map {
|
|
- uint32_t sid; /* session id */
|
|
- struct mc_ioctl_buffer bufs[MC_MAP_MAX];/* buffers info */
|
|
-};
|
|
-
|
|
-/*
|
|
- * Data exchange structure of the MC_IO_ERR ioctl command.
|
|
- */
|
|
-struct mc_ioctl_geterr {
|
|
- uint32_t sid; /* session id */
|
|
- int32_t value; /* error value (out) */
|
|
-};
|
|
-
|
|
-/*
|
|
- * Global MobiCore Version Information.
|
|
- */
|
|
-struct mc_version_info {
|
|
- char product_id[MC_PRODUCT_ID_LEN]; /** Product ID string */
|
|
- uint32_t version_mci; /** Mobicore Control Interface */
|
|
- uint32_t version_so; /** Secure Objects */
|
|
- uint32_t version_mclf; /** MobiCore Load Format */
|
|
- uint32_t version_container; /** MobiCore Container Format */
|
|
- uint32_t version_mc_config; /** MobiCore Config. Block Format */
|
|
- uint32_t version_tl_api; /** MobiCore Trustlet API */
|
|
- uint32_t version_dr_api; /** MobiCore Driver API */
|
|
- uint32_t version_cmp; /** Content Management Protocol */
|
|
-};
|
|
-
|
|
-/*
|
|
- * defines for the ioctl mobicore driver module function call from user space.
|
|
- */
|
|
-/* MobiCore IOCTL magic number */
|
|
-#define MC_IOC_MAGIC 'M'
|
|
-
|
|
-/*
|
|
- * Implement corresponding functions from user api
|
|
- */
|
|
-#define MC_IO_OPEN_SESSION \
|
|
- _IOWR(MC_IOC_MAGIC, 0, struct mc_ioctl_open_sess)
|
|
-#define MC_IO_OPEN_TRUSTLET \
|
|
- _IOWR(MC_IOC_MAGIC, 1, struct mc_ioctl_open_trustlet)
|
|
-#define MC_IO_CLOSE_SESSION _IO(MC_IOC_MAGIC, 2)
|
|
-#define MC_IO_NOTIFY _IO(MC_IOC_MAGIC, 3)
|
|
-#define MC_IO_WAIT _IOW(MC_IOC_MAGIC, 4, struct mc_ioctl_wait)
|
|
-#define MC_IO_MAP _IOWR(MC_IOC_MAGIC, 5, struct mc_ioctl_map)
|
|
-#define MC_IO_UNMAP _IOW(MC_IOC_MAGIC, 6, struct mc_ioctl_map)
|
|
-#define MC_IO_ERR _IOWR(MC_IOC_MAGIC, 7, struct mc_ioctl_geterr)
|
|
-#define MC_IO_FREEZE _IO(MC_IOC_MAGIC, 8)
|
|
-#define MC_IO_VERSION _IOR(MC_IOC_MAGIC, 9, struct mc_version_info)
|
|
-#define MC_IO_DR_VERSION _IOR(MC_IOC_MAGIC, 10, uint32_t)
|
|
-
|
|
-#endif /* _MC_LINUX_H_ */
|
|
diff --git a/drivers/gud/MobiCoreDriver/public/mc_linux_api.h b/drivers/gud/MobiCoreDriver/public/mc_linux_api.h
|
|
deleted file mode 100644
|
|
index 211bc2682b754..0000000000000
|
|
--- a/drivers/gud/MobiCoreDriver/public/mc_linux_api.h
|
|
+++ /dev/null
|
|
@@ -1,28 +0,0 @@
|
|
-/*
|
|
- * Copyright (c) 2013-2014 TRUSTONIC LIMITED
|
|
- * All Rights Reserved.
|
|
- *
|
|
- * This program is free software; you can redistribute it and/or
|
|
- * modify it under the terms of the GNU General Public License
|
|
- * version 2 as published by the Free Software Foundation.
|
|
- *
|
|
- * This program is distributed in the hope that it will be useful,
|
|
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
- * GNU General Public License for more details.
|
|
- */
|
|
-#ifndef _MC_LINUX_API_H_
|
|
-#define _MC_LINUX_API_H_
|
|
-
|
|
-/*
|
|
- * Switch tbase active core to core_num, defined as linux
|
|
- * core id
|
|
- */
|
|
-int mc_switch_core(uint32_t core_num);
|
|
-
|
|
-/*
|
|
- * Return tbase active core as Linux core id
|
|
- */
|
|
-uint32_t mc_active_core(void);
|
|
-
|
|
-#endif /* _MC_LINUX_API_H_ */
|
|
diff --git a/drivers/gud/MobiCoreDriver/public/mobicore_driver_api.h b/drivers/gud/MobiCoreDriver/public/mobicore_driver_api.h
|
|
deleted file mode 100644
|
|
index 005099532d73a..0000000000000
|
|
--- a/drivers/gud/MobiCoreDriver/public/mobicore_driver_api.h
|
|
+++ /dev/null
|
|
@@ -1,450 +0,0 @@
|
|
-/*
|
|
- * Copyright (c) 2013-2015 TRUSTONIC LIMITED
|
|
- * All Rights Reserved.
|
|
- *
|
|
- * This program is free software; you can redistribute it and/or
|
|
- * modify it under the terms of the GNU General Public License
|
|
- * version 2 as published by the Free Software Foundation.
|
|
- *
|
|
- * This program is distributed in the hope that it will be useful,
|
|
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
- * GNU General Public License for more details.
|
|
- */
|
|
-#ifndef _MOBICORE_DRIVER_API_H_
|
|
-#define _MOBICORE_DRIVER_API_H_
|
|
-
|
|
-#include "mc_linux.h"
|
|
-
|
|
-#define __MC_CLIENT_LIB_API
|
|
-
|
|
-/*
|
|
- * Return values of MobiCore driver functions.
|
|
- */
|
|
-enum mc_result {
|
|
- /* Function call succeeded. */
|
|
- MC_DRV_OK = 0,
|
|
- /* No notification available. */
|
|
- MC_DRV_NO_NOTIFICATION = 1,
|
|
- /* Error during notification on communication level. */
|
|
- MC_DRV_ERR_NOTIFICATION = 2,
|
|
- /* Function not implemented. */
|
|
- MC_DRV_ERR_NOT_IMPLEMENTED = 3,
|
|
- /* No more resources available. */
|
|
- MC_DRV_ERR_OUT_OF_RESOURCES = 4,
|
|
- /* Driver initialization failed. */
|
|
- MC_DRV_ERR_INIT = 5,
|
|
- /* Unknown error. */
|
|
- MC_DRV_ERR_UNKNOWN = 6,
|
|
- /* The specified device is unknown. */
|
|
- MC_DRV_ERR_UNKNOWN_DEVICE = 7,
|
|
- /* The specified session is unknown.*/
|
|
- MC_DRV_ERR_UNKNOWN_SESSION = 8,
|
|
- /* The specified operation is not allowed. */
|
|
- MC_DRV_ERR_INVALID_OPERATION = 9,
|
|
- /* The response header from the MC is invalid. */
|
|
- MC_DRV_ERR_INVALID_RESPONSE = 10,
|
|
- /* Function call timed out. */
|
|
- MC_DRV_ERR_TIMEOUT = 11,
|
|
- /* Can not allocate additional memory. */
|
|
- MC_DRV_ERR_NO_FREE_MEMORY = 12,
|
|
- /* Free memory failed. */
|
|
- MC_DRV_ERR_FREE_MEMORY_FAILED = 13,
|
|
- /* Still some open sessions pending. */
|
|
- MC_DRV_ERR_SESSION_PENDING = 14,
|
|
- /* MC daemon not reachable */
|
|
- MC_DRV_ERR_DAEMON_UNREACHABLE = 15,
|
|
- /* The device file of the kernel module could not be opened. */
|
|
- MC_DRV_ERR_INVALID_DEVICE_FILE = 16,
|
|
- /* Invalid parameter. */
|
|
- MC_DRV_ERR_INVALID_PARAMETER = 17,
|
|
- /* Unspecified error from Kernel Module*/
|
|
- MC_DRV_ERR_KERNEL_MODULE = 18,
|
|
- /* Error during mapping of additional bulk memory to session. */
|
|
- MC_DRV_ERR_BULK_MAPPING = 19,
|
|
- /* Error during unmapping of additional bulk memory to session. */
|
|
- MC_DRV_ERR_BULK_UNMAPPING = 20,
|
|
- /* Notification received, exit code available. */
|
|
- MC_DRV_INFO_NOTIFICATION = 21,
|
|
- /* Set up of NWd connection failed. */
|
|
- MC_DRV_ERR_NQ_FAILED = 22,
|
|
- /* Wrong daemon version. */
|
|
- MC_DRV_ERR_DAEMON_VERSION = 23,
|
|
- /* Wrong container version. */
|
|
- MC_DRV_ERR_CONTAINER_VERSION = 24,
|
|
- /* System Trustlet public key is wrong. */
|
|
- MC_DRV_ERR_WRONG_PUBLIC_KEY = 25,
|
|
- /* Wrong container type(s). */
|
|
- MC_DRV_ERR_CONTAINER_TYPE_MISMATCH = 26,
|
|
- /* Container is locked (or not activated). */
|
|
- MC_DRV_ERR_CONTAINER_LOCKED = 27,
|
|
- /* SPID is not registered with root container. */
|
|
- MC_DRV_ERR_SP_NO_CHILD = 28,
|
|
- /* UUID is not registered with sp container. */
|
|
- MC_DRV_ERR_TL_NO_CHILD = 29,
|
|
- /* Unwrapping of root container failed. */
|
|
- MC_DRV_ERR_UNWRAP_ROOT_FAILED = 30,
|
|
- /* Unwrapping of service provider container failed. */
|
|
- MC_DRV_ERR_UNWRAP_SP_FAILED = 31,
|
|
- /* Unwrapping of Trustlet container failed. */
|
|
- MC_DRV_ERR_UNWRAP_TRUSTLET_FAILED = 32,
|
|
- /* No device associated with connection. */
|
|
- MC_DRV_ERR_DAEMON_DEVICE_NOT_OPEN = 33,
|
|
- /* TA blob attestation is incorrect. */
|
|
- MC_DRV_ERR_TA_ATTESTATION_ERROR = 34,
|
|
- /* Interrupted system call. */
|
|
- MC_DRV_ERR_INTERRUPTED_BY_SIGNAL = 35,
|
|
- /* Service is blocked and opensession is thus not allowed. */
|
|
- MC_DRV_ERR_SERVICE_BLOCKED = 36,
|
|
- /* Service is locked and opensession is thus not allowed. */
|
|
- MC_DRV_ERR_SERVICE_LOCKED = 37,
|
|
- /* Service was killed by the TEE (due to an administrative command). */
|
|
- MC_DRV_ERR_SERVICE_KILLED = 38,
|
|
- /* All permitted instances to the service are used */
|
|
- MC_DRV_ERR_NO_FREE_INSTANCES = 39,
|
|
- /* TA blob header is incorrect. */
|
|
- MC_DRV_ERR_TA_HEADER_ERROR = 40,
|
|
-};
|
|
-
|
|
-/*
|
|
- * Structure of Session Handle, includes the Session ID and the Device ID the
|
|
- * Session belongs to.
|
|
- * The session handle will be used for session-based MobiCore communication.
|
|
- * It will be passed to calls which address a communication end point in the
|
|
- * MobiCore environment.
|
|
- */
|
|
-struct mc_session_handle {
|
|
- uint32_t session_id; /* MobiCore session ID */
|
|
- uint32_t device_id; /* Device ID the session belongs to */
|
|
-};
|
|
-
|
|
-/*
|
|
- * Information structure about additional mapped Bulk buffer between the
|
|
- * Trustlet Connector (NWd) and the Trustlet (SWd). This structure is
|
|
- * initialized from a Trustlet Connector by calling mc_map().
|
|
- * In order to use the memory within a Trustlet the Trustlet Connector has to
|
|
- * inform the Trustlet with the content of this structure via the TCI.
|
|
- */
|
|
-struct mc_bulk_map {
|
|
- /* The virtual address of the Bulk buffer regarding the address space
|
|
- * of the Trustlet, already includes a possible offset! */
|
|
- uint32_t secure_virt_addr;
|
|
- uint32_t secure_virt_len; /* Length of the mapped Bulk buffer */
|
|
-};
|
|
-
|
|
-/* The default device ID */
|
|
-#define MC_DEVICE_ID_DEFAULT 0
|
|
-/* Wait infinite for a response of the MC. */
|
|
-#define MC_INFINITE_TIMEOUT ((int32_t)(-1))
|
|
-/* Do not wait for a response of the MC. */
|
|
-#define MC_NO_TIMEOUT 0
|
|
-/* TCI/DCI must not exceed 1MiB */
|
|
-#define MC_MAX_TCI_LEN 0x100000
|
|
-
|
|
-/**
|
|
- * mc_open_device() - Open a new connection to a MobiCore device.
|
|
- * @device_id: Identifier for the MobiCore device to be used.
|
|
- * MC_DEVICE_ID_DEFAULT refers to the default device.
|
|
- *
|
|
- * Initializes all device specific resources required to communicate with a
|
|
- * MobiCore instance located on the specified device in the system. If the
|
|
- * device does not exist the function will return MC_DRV_ERR_UNKNOWN_DEVICE.
|
|
- *
|
|
- * Return codes:
|
|
- * MC_DRV_OK: operation completed successfully
|
|
- * MC_DRV_ERR_INVALID_OPERATION: device already opened
|
|
- * MC_DRV_ERR_DAEMON_UNREACHABLE: problems with daemon
|
|
- * MC_DRV_ERR_UNKNOWN_DEVICE: device_id unknown
|
|
- * MC_DRV_ERR_INVALID_DEVICE_FILE: kernel module under /dev/mobicore
|
|
- * cannot be opened
|
|
- */
|
|
-__MC_CLIENT_LIB_API enum mc_result mc_open_device(uint32_t device_id);
|
|
-
|
|
-/**
|
|
- * mc_close_device() - Close the connection to a MobiCore device.
|
|
- * @device_id: Identifier for the MobiCore device.
|
|
- *
|
|
- * When closing a device, active sessions have to be closed beforehand.
|
|
- * Resources associated with the device will be released.
|
|
- * The device may be opened again after it has been closed.
|
|
- *
|
|
- * MC_DEVICE_ID_DEFAULT refers to the default device.
|
|
- *
|
|
- * Return codes:
|
|
- * MC_DRV_OK: operation completed successfully
|
|
- * MC_DRV_ERR_UNKNOWN_DEVICE: device id is invalid
|
|
- * MC_DRV_ERR_SESSION_PENDING: a session is still open
|
|
- * MC_DRV_ERR_DAEMON_UNREACHABLE: problems with daemon occur
|
|
- */
|
|
-__MC_CLIENT_LIB_API enum mc_result mc_close_device(uint32_t device_id);
|
|
-
|
|
-/**
|
|
- * mc_open_session() - Open a new session to a Trustlet.
|
|
- * @session: On success, the session data will be returned
|
|
- * @uuid: UUID of the Trustlet to be opened
|
|
- * @tci: TCI buffer for communicating with the Trustlet
|
|
- * @tci_len: Length of the TCI buffer. Maximum allowed value
|
|
- * is MC_MAX_TCI_LEN
|
|
- *
|
|
- * The Trustlet with the given UUID has to be available in the flash filesystem.
|
|
- *
|
|
- * Write MCP open message to buffer and notify MobiCore about the availability
|
|
- * of a new command.
|
|
- *
|
|
- * Waits till the MobiCore responses with the new session ID (stored in the MCP
|
|
- * buffer).
|
|
- *
|
|
- * Note that session.device_id has to be the device id of an opened device.
|
|
- *
|
|
- * Return codes:
|
|
- * MC_DRV_OK: operation completed successfully
|
|
- * MC_DRV_INVALID_PARAMETER: session parameter is invalid
|
|
- * MC_DRV_ERR_UNKNOWN_DEVICE: device id is invalid
|
|
- * MC_DRV_ERR_DAEMON_UNREACHABLE: problems with daemon socket occur
|
|
- * MC_DRV_ERR_NQ_FAILED: daemon returns an error
|
|
- */
|
|
-__MC_CLIENT_LIB_API enum mc_result mc_open_session(
|
|
- struct mc_session_handle *session, const struct mc_uuid_t *uuid,
|
|
- uint8_t *tci, uint32_t tci_len);
|
|
-
|
|
-/**
|
|
- * mc_open_trustlet() - Open a new session to the provided Trustlet.
|
|
- * @session: On success, the session data will be returned
|
|
- * @spid: Service Provider ID (for SP trustlets otherwise ignored)
|
|
- * @trustlet Memory buffer containing the Trusted Application binary
|
|
- * @trustlet_len Trusted Application length
|
|
- * @tci: TCI buffer for communicating with the Trustlet
|
|
- * @tci_len: Length of the TCI buffer. Maximum allowed value
|
|
- * is MC_MAX_TCI_LEN
|
|
- *
|
|
- * Write MCP open message to buffer and notify MobiCore about the availability
|
|
- * of a new command.
|
|
- *
|
|
- * Waits till the MobiCore responses with the new session ID (stored in the MCP
|
|
- * buffer).
|
|
- *
|
|
- * Note that session.device_id has to be the device id of an opened device.
|
|
- *
|
|
- * Return codes:
|
|
- * MC_DRV_OK: operation completed successfully
|
|
- * MC_DRV_INVALID_PARAMETER: session parameter is invalid
|
|
- * MC_DRV_ERR_UNKNOWN_DEVICE: device id is invalid
|
|
- * MC_DRV_ERR_DAEMON_UNREACHABLE: problems with daemon socket occur
|
|
- * MC_DRV_ERR_NQ_FAILED: daemon returns an error
|
|
- */
|
|
-__MC_CLIENT_LIB_API enum mc_result mc_open_trustlet(
|
|
- struct mc_session_handle *session, uint32_t spid,
|
|
- uint8_t *trustlet, uint32_t trustlet_len, uint8_t *tci, uint32_t len);
|
|
-
|
|
-/**
|
|
- * mc_close_session() - Close a Trustlet session.
|
|
- * @session: Session to be closed.
|
|
- *
|
|
- * Closes the specified MobiCore session. The call will block until the
|
|
- * session has been closed.
|
|
- *
|
|
- * Device device_id has to be opened in advance.
|
|
- *
|
|
- * Return codes:
|
|
- * MC_DRV_OK: operation completed successfully
|
|
- * MC_DRV_INVALID_PARAMETER: session parameter is invalid
|
|
- * MC_DRV_ERR_UNKNOWN_SESSION: session id is invalid
|
|
- * MC_DRV_ERR_UNKNOWN_DEVICE: device id of session is invalid
|
|
- * MC_DRV_ERR_DAEMON_UNREACHABLE: problems with daemon occur
|
|
- * MC_DRV_ERR_INVALID_DEVICE_FILE: daemon cannot open Trustlet file
|
|
- */
|
|
-__MC_CLIENT_LIB_API enum mc_result mc_close_session(
|
|
- struct mc_session_handle *session);
|
|
-
|
|
-/**
|
|
- * mc_notify() - Notify a session.
|
|
- * @session: The session to be notified.
|
|
- *
|
|
- * Notifies the session end point about available message data.
|
|
- * If the session parameter is correct, notify will always succeed.
|
|
- * Corresponding errors can only be received by mc_wait_notification().
|
|
- *
|
|
- * A session has to be opened in advance.
|
|
- *
|
|
- * Return codes:
|
|
- * MC_DRV_OK: operation completed successfully
|
|
- * MC_DRV_INVALID_PARAMETER: session parameter is invalid
|
|
- * MC_DRV_ERR_UNKNOWN_SESSION: session id is invalid
|
|
- * MC_DRV_ERR_UNKNOWN_DEVICE: device id of session is invalid
|
|
- */
|
|
-__MC_CLIENT_LIB_API enum mc_result mc_notify(struct mc_session_handle *session);
|
|
-
|
|
-/**
|
|
- * mc_wait_notification() - Wait for a notification.
|
|
- * @session: The session the notification should correspond to.
|
|
- * @timeout: Time in milliseconds to wait
|
|
- * (MC_NO_TIMEOUT : direct return, > 0 : milliseconds,
|
|
- * MC_INFINITE_TIMEOUT : wait infinitely)
|
|
- *
|
|
- * Wait for a notification issued by the MobiCore for a specific session.
|
|
- * The timeout parameter specifies the number of milliseconds the call will wait
|
|
- * for a notification.
|
|
- *
|
|
- * If the caller passes 0 as timeout value the call will immediately return.
|
|
- * If timeout value is below 0 the call will block until a notification for the
|
|
- * session has been received.
|
|
- *
|
|
- * If timeout is below 0, call will block.
|
|
- *
|
|
- * Caller has to trust the other side to send a notification to wake him up
|
|
- * again.
|
|
- *
|
|
- * Return codes:
|
|
- * MC_DRV_OK: operation completed successfully
|
|
- * MC_DRV_ERR_TIMEOUT: no notification arrived in time
|
|
- * MC_DRV_INFO_NOTIFICATION: a problem with the session was
|
|
- * encountered. Get more details with
|
|
- * mc_get_session_error_code()
|
|
- * MC_DRV_ERR_NOTIFICATION: a problem with the socket occurred
|
|
- * MC_DRV_INVALID_PARAMETER: a parameter is invalid
|
|
- * MC_DRV_ERR_UNKNOWN_SESSION: session id is invalid
|
|
- * MC_DRV_ERR_UNKNOWN_DEVICE: device id of session is invalid
|
|
- */
|
|
-__MC_CLIENT_LIB_API enum mc_result mc_wait_notification(
|
|
- struct mc_session_handle *session, int32_t timeout);
|
|
-
|
|
-/**
|
|
- * mc_malloc_wsm() - Allocate a block of world shared memory (WSM).
|
|
- * @device_id: The ID of an opened device to retrieve the WSM from.
|
|
- * @align: The alignment (number of pages) of the memory block
|
|
- * (e.g. 0x00000001 for 4kb).
|
|
- * @len: Length of the block in bytes.
|
|
- * @wsm: Virtual address of the world shared memory block.
|
|
- * @wsm_flags: Platform specific flags describing the memory to
|
|
- * be allocated.
|
|
- *
|
|
- * The MC driver allocates a contiguous block of memory which can be used as
|
|
- * WSM.
|
|
- * This implicates that the allocated memory is aligned according to the
|
|
- * alignment parameter.
|
|
- *
|
|
- * Always returns a buffer of size WSM_SIZE aligned to 4K.
|
|
- *
|
|
- * Align and wsm_flags are currently ignored
|
|
- *
|
|
- * Return codes:
|
|
- * MC_DRV_OK: operation completed successfully
|
|
- * MC_DRV_INVALID_PARAMETER: a parameter is invalid
|
|
- * MC_DRV_ERR_UNKNOWN_DEVICE: device id is invalid
|
|
- * MC_DRV_ERR_NO_FREE_MEMORY: no more contiguous memory is
|
|
- * available in this size or for this
|
|
- * process
|
|
- */
|
|
-__MC_CLIENT_LIB_API enum mc_result mc_malloc_wsm(
|
|
- uint32_t device_id,
|
|
- uint32_t align,
|
|
- uint32_t len,
|
|
- uint8_t **wsm,
|
|
- uint32_t wsm_flags
|
|
-);
|
|
-
|
|
-/**
|
|
- * mc_free_wsm() - Free a block of world shared memory (WSM).
|
|
- * @device_id: The ID to which the given address belongs
|
|
- * @wsm: Address of WSM block to be freed
|
|
- *
|
|
- * The MC driver will free a block of world shared memory (WSM) previously
|
|
- * allocated with mc_malloc_wsm(). The caller has to assure that the address
|
|
- * handed over to the driver is a valid WSM address.
|
|
- *
|
|
- * Return codes:
|
|
- * MC_DRV_OK: operation completed successfully
|
|
- * MC_DRV_INVALID_PARAMETER: a parameter is invalid
|
|
- * MC_DRV_ERR_UNKNOWN_DEVICE: when device id is invalid
|
|
- * MC_DRV_ERR_FREE_MEMORY_FAILED: on failure
|
|
- */
|
|
-__MC_CLIENT_LIB_API enum mc_result mc_free_wsm(uint32_t device_id,
|
|
- uint8_t *wsm);
|
|
-
|
|
-/**
|
|
- *mc_map() - Map additional bulk buffer between a Trustlet Connector (TLC)
|
|
- * and the Trustlet (TL) for a session
|
|
- * @session: Session handle with information of the device_id and
|
|
- * the session_id. The given buffer is mapped to the
|
|
- * session specified in the sessionHandle
|
|
- * @buf: Virtual address of a memory portion (relative to TLC)
|
|
- * to be shared with the Trustlet, already includes a
|
|
- * possible offset!
|
|
- * @len: length of buffer block in bytes.
|
|
- * @map_info: Information structure about the mapped Bulk buffer
|
|
- * between the TLC (NWd) and the TL (SWd).
|
|
- *
|
|
- * Memory allocated in user space of the TLC can be mapped as additional
|
|
- * communication channel (besides TCI) to the Trustlet. Limitation of the
|
|
- * Trustlet memory structure apply: only 6 chunks can be mapped with a maximum
|
|
- * chunk size of 1 MiB each.
|
|
- *
|
|
- * It is up to the application layer (TLC) to inform the Trustlet
|
|
- * about the additional mapped bulk memory.
|
|
- *
|
|
- * Return codes:
|
|
- * MC_DRV_OK: operation completed successfully
|
|
- * MC_DRV_INVALID_PARAMETER: a parameter is invalid
|
|
- * MC_DRV_ERR_UNKNOWN_SESSION: session id is invalid
|
|
- * MC_DRV_ERR_UNKNOWN_DEVICE: device id of session is invalid
|
|
- * MC_DRV_ERR_DAEMON_UNREACHABLE: problems with daemon occur
|
|
- * MC_DRV_ERR_BULK_MAPPING: buf is already uses as bulk buffer or
|
|
- * when registering the buffer failed
|
|
- */
|
|
-__MC_CLIENT_LIB_API enum mc_result mc_map(
|
|
- struct mc_session_handle *session, void *buf, uint32_t len,
|
|
- struct mc_bulk_map *map_info);
|
|
-
|
|
-/**
|
|
- * mc_unmap() - Remove additional mapped bulk buffer between Trustlet Connector
|
|
- * (TLC) and the Trustlet (TL) for a session
|
|
- * @session: Session handle with information of the device_id and
|
|
- * the session_id. The given buffer is unmapped from the
|
|
- * session specified in the sessionHandle.
|
|
- * @buf: Virtual address of a memory portion (relative to TLC)
|
|
- * shared with the TL, already includes a possible offset!
|
|
- * @map_info: Information structure about the mapped Bulk buffer
|
|
- * between the TLC (NWd) and the TL (SWd)
|
|
- *
|
|
- * The bulk buffer will immediately be unmapped from the session context.
|
|
- *
|
|
- * The application layer (TLC) must inform the TL about unmapping of the
|
|
- * additional bulk memory before calling mc_unmap!
|
|
- *
|
|
- * The clientlib currently ignores the len field in map_info.
|
|
- *
|
|
- * Return codes:
|
|
- * MC_DRV_OK: operation completed successfully
|
|
- * MC_DRV_INVALID_PARAMETER: a parameter is invalid
|
|
- * MC_DRV_ERR_UNKNOWN_SESSION: session id is invalid
|
|
- * MC_DRV_ERR_UNKNOWN_DEVICE: device id of session is invalid
|
|
- * MC_DRV_ERR_DAEMON_UNREACHABLE: problems with daemon occur
|
|
- * MC_DRV_ERR_BULK_UNMAPPING: buf was not registered earlier
|
|
- * or when unregistering failed
|
|
- */
|
|
-__MC_CLIENT_LIB_API enum mc_result mc_unmap(
|
|
- struct mc_session_handle *session, void *buf,
|
|
- struct mc_bulk_map *map_info);
|
|
-
|
|
-/*
|
|
- * mc_get_session_error_code() - Get additional error information of the last
|
|
- * error that occurred on a session.
|
|
- * @session: Session handle with information of the device_id and
|
|
- * the session_id
|
|
- * @exit_code: >0 Trustlet has terminated itself with this value,
|
|
- * <0 Trustlet is dead because of an error within the
|
|
- * MobiCore (e.g. Kernel exception). See also MCI
|
|
- * definition.
|
|
- *
|
|
- * After the request the stored error code will be deleted.
|
|
- *
|
|
- * Return codes:
|
|
- * MC_DRV_OK: operation completed successfully
|
|
- * MC_DRV_INVALID_PARAMETER: a parameter is invalid
|
|
- * MC_DRV_ERR_UNKNOWN_SESSION: session id is invalid
|
|
- * MC_DRV_ERR_UNKNOWN_DEVICE: device id of session is invalid
|
|
- */
|
|
-__MC_CLIENT_LIB_API enum mc_result mc_get_session_error_code(
|
|
- struct mc_session_handle *session, int32_t *exit_code);
|
|
-
|
|
-#endif /* _MOBICORE_DRIVER_API_H_ */
|
|
diff --git a/drivers/gud/MobiCoreDriver/scheduler.c b/drivers/gud/MobiCoreDriver/scheduler.c
|
|
deleted file mode 100644
|
|
index 444f839d8ad1d..0000000000000
|
|
--- a/drivers/gud/MobiCoreDriver/scheduler.c
|
|
+++ /dev/null
|
|
@@ -1,231 +0,0 @@
|
|
-/*
|
|
- * Copyright (c) 2013-2015 TRUSTONIC LIMITED
|
|
- * All Rights Reserved.
|
|
- *
|
|
- * This program is free software; you can redistribute it and/or
|
|
- * modify it under the terms of the GNU General Public License
|
|
- * version 2 as published by the Free Software Foundation.
|
|
- *
|
|
- * This program is distributed in the hope that it will be useful,
|
|
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
- * GNU General Public License for more details.
|
|
- */
|
|
-
|
|
-#include <linux/slab.h>
|
|
-#include <linux/mutex.h>
|
|
-#include <linux/device.h>
|
|
-#include <linux/kthread.h>
|
|
-#include <linux/completion.h>
|
|
-#include <linux/stringify.h>
|
|
-#include <linux/version.h>
|
|
-
|
|
-#include "public/mc_linux.h"
|
|
-
|
|
-#include "main.h"
|
|
-#include "fastcall.h"
|
|
-#include "debug.h"
|
|
-#include "logging.h"
|
|
-#include "mcp.h"
|
|
-#include "scheduler.h"
|
|
-
|
|
-#define SCHEDULING_FREQ 5 /**< N-SIQ every n-th time */
|
|
-
|
|
-static struct sched_ctx {
|
|
- struct task_struct *thread;
|
|
- bool thread_run;
|
|
- struct completion idle_complete; /* Unblock scheduler thread */
|
|
- struct completion sleep_complete; /* Wait for sleep status */
|
|
- struct mutex sleep_mutex; /* Protect sleep request */
|
|
- struct mutex request_mutex; /* Protect all below */
|
|
- /* The order of this enum matters */
|
|
- enum {
|
|
- NONE, /* No specific request */
|
|
- YIELD, /* Run the SWd */
|
|
- NSIQ, /* Schedule the SWd */
|
|
- SUSPEND, /* Suspend the SWd */
|
|
- RESUME, /* Resume the SWd */
|
|
- } request;
|
|
- bool suspended;
|
|
-} sched_ctx;
|
|
-
|
|
-static int mc_scheduler_command(int command)
|
|
-{
|
|
- if (IS_ERR_OR_NULL(sched_ctx.thread))
|
|
- return -EFAULT;
|
|
-
|
|
- mutex_lock(&sched_ctx.request_mutex);
|
|
- if (sched_ctx.request < command) {
|
|
- sched_ctx.request = command;
|
|
- complete(&sched_ctx.idle_complete);
|
|
- }
|
|
-
|
|
- mutex_unlock(&sched_ctx.request_mutex);
|
|
- return 0;
|
|
-}
|
|
-
|
|
-static int mc_scheduler_pm_command(int command)
|
|
-{
|
|
- int ret = -EPERM;
|
|
-
|
|
- if (IS_ERR_OR_NULL(sched_ctx.thread))
|
|
- return -EFAULT;
|
|
-
|
|
- mutex_lock(&sched_ctx.sleep_mutex);
|
|
-
|
|
- /* Send request */
|
|
- mc_scheduler_command(command);
|
|
-
|
|
- /* Wait for scheduler to reply */
|
|
- wait_for_completion(&sched_ctx.sleep_complete);
|
|
- mutex_lock(&sched_ctx.request_mutex);
|
|
- if (command == SUSPEND) {
|
|
- if (sched_ctx.suspended)
|
|
- ret = 0;
|
|
- } else {
|
|
- if (!sched_ctx.suspended)
|
|
- ret = 0;
|
|
- }
|
|
-
|
|
- mutex_unlock(&sched_ctx.request_mutex);
|
|
-
|
|
- mutex_unlock(&sched_ctx.sleep_mutex);
|
|
- return ret;
|
|
-}
|
|
-
|
|
-static int mc_dev_command(enum mcp_scheduler_commands command)
|
|
-{
|
|
- switch (command) {
|
|
- case MCP_YIELD:
|
|
- return mc_scheduler_command(YIELD);
|
|
- case MCP_NSIQ:
|
|
- return mc_scheduler_command(NSIQ);
|
|
- }
|
|
-
|
|
- return -EINVAL;
|
|
-}
|
|
-
|
|
-int mc_scheduler_suspend(void)
|
|
-{
|
|
- return mc_scheduler_pm_command(SUSPEND);
|
|
-}
|
|
-
|
|
-int mc_scheduler_resume(void)
|
|
-{
|
|
- return mc_scheduler_pm_command(RESUME);
|
|
-}
|
|
-
|
|
-/*
|
|
- * This thread, and only this thread, schedules the SWd. Hence, reading the idle
|
|
- * status and its associated timeout is safe from race conditions.
|
|
- */
|
|
-static int tee_scheduler(void *arg)
|
|
-{
|
|
- int timeslice = 0; /* Actually scheduling period */
|
|
- int ret = 0;
|
|
-
|
|
- MCDRV_DBG("enter");
|
|
- while (1) {
|
|
- int32_t timeout_ms = -1;
|
|
- bool pm_request = false;
|
|
-
|
|
- if (sched_ctx.suspended || mcp_get_idle_timeout(&timeout_ms)) {
|
|
- /* If timeout is 0 we keep scheduling the SWd */
|
|
- if (!timeout_ms)
|
|
- mc_scheduler_command(NSIQ);
|
|
- else if (timeout_ms < 0)
|
|
- wait_for_completion(&sched_ctx.idle_complete);
|
|
- else if (!wait_for_completion_timeout(
|
|
- &sched_ctx.idle_complete,
|
|
- msecs_to_jiffies(timeout_ms)))
|
|
- /* Timed out, force SWd schedule */
|
|
- mc_scheduler_command(NSIQ);
|
|
- }
|
|
-
|
|
- if (kthread_should_stop() || !sched_ctx.thread_run)
|
|
- break;
|
|
-
|
|
- /* Get requested command if any */
|
|
- mutex_lock(&sched_ctx.request_mutex);
|
|
- if (sched_ctx.request == YIELD)
|
|
- /* Yield forced: increment timeslice */
|
|
- timeslice++;
|
|
- else if (sched_ctx.request >= NSIQ) {
|
|
- /* Force N_SIQ, also to suspend/resume SWd */
|
|
- timeslice = 0;
|
|
- if (sched_ctx.request == SUSPEND) {
|
|
- mcp_suspend();
|
|
- pm_request = true;
|
|
- } else if (sched_ctx.request == RESUME) {
|
|
- mcp_resume();
|
|
- pm_request = true;
|
|
- }
|
|
- }
|
|
-
|
|
- sched_ctx.request = NONE;
|
|
- mutex_unlock(&sched_ctx.request_mutex);
|
|
-
|
|
- /* Reset timeout so we don't loop if SWd halted */
|
|
- mcp_reset_idle_timeout();
|
|
- if (timeslice--) {
|
|
- /* Resume SWd from where it was */
|
|
- ret = mc_fc_yield();
|
|
- } else {
|
|
- timeslice = SCHEDULING_FREQ;
|
|
- /* Call SWd scheduler */
|
|
- ret = mc_fc_nsiq();
|
|
- }
|
|
-
|
|
- /* Always flush log buffer after the SWd has run */
|
|
- mc_logging_run();
|
|
- if (ret)
|
|
- break;
|
|
-
|
|
- /* Should have suspended by now if requested */
|
|
- mutex_lock(&sched_ctx.request_mutex);
|
|
- if (pm_request) {
|
|
- sched_ctx.suspended = mcp_suspended();
|
|
- complete(&sched_ctx.sleep_complete);
|
|
- }
|
|
-
|
|
- mutex_unlock(&sched_ctx.request_mutex);
|
|
-
|
|
- /* Flush pending notifications if possible */
|
|
- if (mcp_notifications_flush())
|
|
- complete(&sched_ctx.idle_complete);
|
|
- }
|
|
-
|
|
- MCDRV_DBG("exit, ret is %d", ret);
|
|
- return ret;
|
|
-}
|
|
-
|
|
-int mc_scheduler_start(void)
|
|
-{
|
|
- sched_ctx.thread_run = true;
|
|
- sched_ctx.thread = kthread_run(tee_scheduler, NULL, "tee_scheduler");
|
|
- if (IS_ERR(sched_ctx.thread)) {
|
|
- MCDRV_ERROR("tee_scheduler thread creation failed");
|
|
- return PTR_ERR(sched_ctx.thread);
|
|
- }
|
|
-
|
|
- mcp_register_scheduler(mc_dev_command);
|
|
- complete(&sched_ctx.idle_complete);
|
|
- return 0;
|
|
-}
|
|
-
|
|
-void mc_scheduler_stop(void)
|
|
-{
|
|
- mcp_register_scheduler(NULL);
|
|
- sched_ctx.thread_run = false;
|
|
- complete(&sched_ctx.idle_complete);
|
|
- kthread_stop(sched_ctx.thread);
|
|
-}
|
|
-
|
|
-int mc_scheduler_init(void)
|
|
-{
|
|
- init_completion(&sched_ctx.idle_complete);
|
|
- init_completion(&sched_ctx.sleep_complete);
|
|
- mutex_init(&sched_ctx.sleep_mutex);
|
|
- mutex_init(&sched_ctx.request_mutex);
|
|
- return 0;
|
|
-}
|
|
diff --git a/drivers/gud/MobiCoreDriver/scheduler.h b/drivers/gud/MobiCoreDriver/scheduler.h
|
|
deleted file mode 100644
|
|
index c3c17f1c9017c..0000000000000
|
|
--- a/drivers/gud/MobiCoreDriver/scheduler.h
|
|
+++ /dev/null
|
|
@@ -1,25 +0,0 @@
|
|
-/*
|
|
- * Copyright (c) 2013-2015 TRUSTONIC LIMITED
|
|
- * All Rights Reserved.
|
|
- *
|
|
- * This program is free software; you can redistribute it and/or
|
|
- * modify it under the terms of the GNU General Public License
|
|
- * version 2 as published by the Free Software Foundation.
|
|
- *
|
|
- * This program is distributed in the hope that it will be useful,
|
|
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
- * GNU General Public License for more details.
|
|
- */
|
|
-
|
|
-#ifndef __MC_SCHEDULER_H__
|
|
-#define __MC_SCHEDULER_H__
|
|
-
|
|
-int mc_scheduler_init(void);
|
|
-static inline void mc_scheduler_exit(void) {}
|
|
-int mc_scheduler_start(void);
|
|
-void mc_scheduler_stop(void);
|
|
-int mc_scheduler_suspend(void);
|
|
-int mc_scheduler_resume(void);
|
|
-
|
|
-#endif /* __MC_SCHEDULER_H__ */
|
|
diff --git a/drivers/gud/MobiCoreDriver/session.c b/drivers/gud/MobiCoreDriver/session.c
|
|
deleted file mode 100644
|
|
index 1dbb8900b2b3a..0000000000000
|
|
--- a/drivers/gud/MobiCoreDriver/session.c
|
|
+++ /dev/null
|
|
@@ -1,779 +0,0 @@
|
|
-/*
|
|
- * Copyright (c) 2013-2015 TRUSTONIC LIMITED
|
|
- * All Rights Reserved.
|
|
- *
|
|
- * This program is free software; you can redistribute it and/or
|
|
- * modify it under the terms of the GNU General Public License
|
|
- * version 2 as published by the Free Software Foundation.
|
|
- *
|
|
- * This program is distributed in the hope that it will be useful,
|
|
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
- * GNU General Public License for more details.
|
|
- */
|
|
-#include <linux/types.h>
|
|
-#include <linux/slab.h>
|
|
-#include <linux/device.h>
|
|
-#include <linux/jiffies.h>
|
|
-#include <linux/sched.h>
|
|
-#include <linux/workqueue.h>
|
|
-#include <linux/err.h>
|
|
-#include <linux/mm.h>
|
|
-#include <crypto/hash.h>
|
|
-#include <linux/scatterlist.h>
|
|
-#include <linux/fs.h>
|
|
-
|
|
-#include "public/mc_linux.h"
|
|
-#include "public/mc_admin.h"
|
|
-
|
|
-#include "platform.h" /* MC_UIDGID_OLDSTYLE */
|
|
-#include "main.h"
|
|
-#include "debug.h"
|
|
-#include "mmu.h"
|
|
-#include "mcp.h"
|
|
-#include "client.h" /* *cbuf* */
|
|
-#include "session.h"
|
|
-#include "mci/mcimcp.h"
|
|
-
|
|
-#define SHA1_HASH_SIZE 20
|
|
-
|
|
-struct tbase_wsm {
|
|
- /* Buffer NWd addr (uva or kva, used only for lookup) */
|
|
- uintptr_t va;
|
|
- /* buffer length */
|
|
- uint32_t len;
|
|
- /* Buffer SWd addr */
|
|
- uint32_t sva;
|
|
- /* mmu L2 table */
|
|
- struct tbase_mmu *mmu;
|
|
- /* possibly a pointer to a cbuf */
|
|
- struct tbase_cbuf *cbuf;
|
|
- /* list node */
|
|
- struct list_head list;
|
|
-};
|
|
-
|
|
-/*
|
|
- * Postponed closing for GP TAs.
|
|
- * Implemented as a worker because cannot be executed from within isr_worker.
|
|
- */
|
|
-static void session_close_worker(struct work_struct *work)
|
|
-{
|
|
- struct mcp_session *mcp_session;
|
|
- struct tbase_session *session;
|
|
-
|
|
- mcp_session = container_of(work, struct mcp_session, close_work);
|
|
- session = container_of(mcp_session, struct tbase_session, mcp_session);
|
|
- session_close(session);
|
|
-}
|
|
-
|
|
-/* Forward declarations */
|
|
-static struct tbase_wsm *wsm_create(struct tbase_session *session,
|
|
- uintptr_t buf, uint32_t len);
|
|
-static void wsm_free(struct tbase_wsm *wsm);
|
|
-
|
|
-static int hash_path_and_data(char *hash, const void *data,
|
|
- unsigned int data_len)
|
|
-{
|
|
- struct mm_struct *mm = current->mm;
|
|
- struct hash_desc desc;
|
|
- struct scatterlist sg;
|
|
- char *buf;
|
|
- char *path;
|
|
- unsigned int path_len;
|
|
- int ret = 0;
|
|
-
|
|
- buf = (char *)__get_free_page(GFP_KERNEL);
|
|
- if (!buf)
|
|
- return -ENOMEM;
|
|
-
|
|
- down_read(&mm->mmap_sem);
|
|
- if (!mm->exe_file) {
|
|
- ret = -ENOENT;
|
|
- goto end;
|
|
- }
|
|
-
|
|
- path = d_path(&mm->exe_file->f_path, buf, PAGE_SIZE);
|
|
- if (IS_ERR(path)) {
|
|
- ret = PTR_ERR(path);
|
|
- goto end;
|
|
- }
|
|
-
|
|
- MCDRV_DBG("current process path = ");
|
|
- {
|
|
- char *c;
|
|
-
|
|
- for (c = path; *c; c++)
|
|
- MCDRV_DBG("%c %d", *c, *c);
|
|
- }
|
|
-
|
|
- path_len = strnlen(path, PAGE_SIZE);
|
|
- MCDRV_DBG("path_len = %u", path_len);
|
|
- desc.tfm = crypto_alloc_hash("sha1", 0, CRYPTO_ALG_ASYNC);
|
|
- if (IS_ERR(desc.tfm)) {
|
|
- ret = PTR_ERR(desc.tfm);
|
|
- MCDRV_DBG("could not alloc hash = %d", ret);
|
|
- goto end;
|
|
- }
|
|
-
|
|
- desc.flags = 0;
|
|
- sg_init_one(&sg, path, path_len);
|
|
- crypto_hash_init(&desc);
|
|
- crypto_hash_update(&desc, &sg, path_len);
|
|
- if (data) {
|
|
- MCDRV_DBG("current process path: hashing additional data\n");
|
|
- sg_init_one(&sg, data, data_len);
|
|
- crypto_hash_update(&desc, &sg, data_len);
|
|
- }
|
|
-
|
|
- crypto_hash_final(&desc, hash);
|
|
- crypto_free_hash(desc.tfm);
|
|
-
|
|
-end:
|
|
- up_read(&mm->mmap_sem);
|
|
- free_page((unsigned long)buf);
|
|
-
|
|
- return ret;
|
|
-}
|
|
-
|
|
-static int check_prepare_identity(const struct mc_identity *identity,
|
|
- struct identity *mcp_identity)
|
|
-{
|
|
- struct mc_identity *mcp_id = (struct mc_identity *)mcp_identity;
|
|
- uint8_t hash[SHA1_HASH_SIZE];
|
|
- bool application = false;
|
|
- const void *data;
|
|
- unsigned int data_len;
|
|
-
|
|
- /* Mobicore doesn't support GP client authentication. */
|
|
- if (!g_ctx.f_client_login &&
|
|
- (identity->login_type != TEEC_LOGIN_PUBLIC)) {
|
|
- MCDRV_DBG_WARN("Unsupported login type %d",
|
|
- identity->login_type);
|
|
- return -EINVAL;
|
|
- }
|
|
-
|
|
- /* Copy login type */
|
|
- mcp_identity->login_type = identity->login_type;
|
|
-
|
|
- /* Fill in uid field */
|
|
- if ((identity->login_type == TEEC_LOGIN_USER) ||
|
|
- (identity->login_type == TEEC_LOGIN_USER_APPLICATION)) {
|
|
- /* Set euid and ruid of the process. */
|
|
-#if !defined(KUIDT_INIT) || defined(MC_UIDGID_OLDSTYLE)
|
|
- mcp_id->uid.euid = current_euid();
|
|
- mcp_id->uid.ruid = current_uid();
|
|
-#else
|
|
- mcp_id->uid.euid = current_euid().val;
|
|
- mcp_id->uid.ruid = current_uid().val;
|
|
-#endif
|
|
- }
|
|
-
|
|
- /* Check gid field */
|
|
- if ((identity->login_type == TEEC_LOGIN_GROUP) ||
|
|
- (identity->login_type == TEEC_LOGIN_GROUP_APPLICATION)) {
|
|
-#if !defined(KUIDT_INIT) || defined(MC_UIDGID_OLDSTYLE)
|
|
- gid_t gid = identity->gid;
|
|
-#else
|
|
- kgid_t gid = {
|
|
- .val = identity->gid,
|
|
- };
|
|
-#endif
|
|
- /* Check if gid is one of: egid of the process, its rgid or one
|
|
- * of its supplementary groups */
|
|
- if (!in_egroup_p(gid) && !in_group_p(gid)) {
|
|
- MCDRV_DBG("group %d not allowed", identity->gid);
|
|
- return -EACCES;
|
|
- }
|
|
-
|
|
- MCDRV_DBG("group %d found", identity->gid);
|
|
- mcp_id->gid = identity->gid;
|
|
- }
|
|
-
|
|
- switch (identity->login_type) {
|
|
- case TEEC_LOGIN_PUBLIC:
|
|
- case TEEC_LOGIN_USER:
|
|
- case TEEC_LOGIN_GROUP:
|
|
- break;
|
|
- case TEEC_LOGIN_APPLICATION:
|
|
- application = true;
|
|
- data = NULL;
|
|
- data_len = 0;
|
|
- break;
|
|
- case TEEC_LOGIN_USER_APPLICATION:
|
|
- application = true;
|
|
- data = &mcp_id->uid;
|
|
- data_len = sizeof(mcp_id->uid);
|
|
- break;
|
|
- case TEEC_LOGIN_GROUP_APPLICATION:
|
|
- application = true;
|
|
- data = &identity->gid;
|
|
- data_len = sizeof(identity->gid);
|
|
- break;
|
|
- default:
|
|
- /* Any other login_type value is invalid. */
|
|
- MCDRV_DBG_WARN("Invalid login type");
|
|
- return -EINVAL;
|
|
- }
|
|
-
|
|
- if (application) {
|
|
- if (hash_path_and_data(hash, data, data_len)) {
|
|
- MCDRV_DBG("error in hash calculation");
|
|
- return -EAGAIN;
|
|
- }
|
|
-
|
|
- memcpy(&mcp_id->login_data, hash, sizeof(mcp_id->login_data));
|
|
- }
|
|
-
|
|
- return 0;
|
|
-}
|
|
-
|
|
-/*
|
|
- * Create a session object.
|
|
- * Note: object is not attached to client yet.
|
|
- */
|
|
-struct tbase_session *session_create(struct tbase_client *client, bool is_gp,
|
|
- struct mc_identity *identity)
|
|
-{
|
|
- struct tbase_session *session;
|
|
- struct identity mcp_identity;
|
|
-
|
|
- if (is_gp) {
|
|
- /* Check identity method and data. */
|
|
- int ret = check_prepare_identity(identity, &mcp_identity);
|
|
-
|
|
- if (ret)
|
|
- return ERR_PTR(ret);
|
|
- }
|
|
-
|
|
- /* Allocate session object */
|
|
- session = kzalloc(sizeof(*session), GFP_KERNEL);
|
|
- if (!session)
|
|
- return ERR_PTR(-ENOMEM);
|
|
-
|
|
- mutex_init(&session->close_lock);
|
|
- /* Initialise object members */
|
|
- mcp_session_init(&session->mcp_session, is_gp, &mcp_identity);
|
|
- INIT_WORK(&session->mcp_session.close_work, session_close_worker);
|
|
- session->client = client;
|
|
- kref_init(&session->kref);
|
|
- INIT_LIST_HEAD(&session->list);
|
|
- mutex_init(&session->wsms_lock);
|
|
- INIT_LIST_HEAD(&session->wsms);
|
|
- MCDRV_DBG("created session %p: client %p", session, session->client);
|
|
- return session;
|
|
-}
|
|
-
|
|
-int session_open(struct tbase_session *session, const struct tbase_object *obj,
|
|
- const struct tbase_mmu *obj_mmu, uintptr_t tci, size_t len)
|
|
-{
|
|
- struct mcp_buffer_map map;
|
|
-
|
|
- tbase_mmu_buffer(obj_mmu, &map);
|
|
- /* Create wsm object for tci */
|
|
- if (tci && len) {
|
|
- struct tbase_wsm *wsm;
|
|
- struct mcp_buffer_map tci_map;
|
|
- int ret = 0;
|
|
-
|
|
- mutex_lock(&session->wsms_lock);
|
|
- wsm = wsm_create(session, tci, len);
|
|
- if (IS_ERR(wsm))
|
|
- ret = PTR_ERR(wsm);
|
|
-
|
|
- mutex_unlock(&session->wsms_lock);
|
|
- if (ret)
|
|
- return ret;
|
|
-
|
|
- tbase_mmu_buffer(wsm->mmu, &tci_map);
|
|
- ret = mcp_open_session(&session->mcp_session, obj, &map,
|
|
- &tci_map);
|
|
- if (ret) {
|
|
- mutex_lock(&session->wsms_lock);
|
|
- wsm_free(wsm);
|
|
- mutex_unlock(&session->wsms_lock);
|
|
- }
|
|
-
|
|
- return ret;
|
|
- }
|
|
-
|
|
- if (tci || len) {
|
|
- MCDRV_ERROR("Tci pointer and length are incoherent");
|
|
- return -EINVAL;
|
|
- }
|
|
-
|
|
- return mcp_open_session(&session->mcp_session, obj, &map, NULL);
|
|
-}
|
|
-
|
|
-/*
|
|
- * Close TA and unreference session object.
|
|
- * Object will be freed if reference reaches 0.
|
|
- * Session object is assumed to have been removed from main list, which means
|
|
- * that session_close cannot be called anymore.
|
|
- */
|
|
-int session_close(struct tbase_session *session)
|
|
-{
|
|
- int ret = 0;
|
|
-
|
|
- if (!session)
|
|
- return -ENXIO;
|
|
-
|
|
- mutex_lock(&session->close_lock);
|
|
- switch (mcp_close_session(&session->mcp_session)) {
|
|
- case 0:
|
|
- /* TA is closed, remove from closing list */
|
|
- mutex_lock(&g_ctx.closing_lock);
|
|
- list_del(&session->list);
|
|
- mutex_unlock(&g_ctx.closing_lock);
|
|
- /* Remove the ref we took on creation, exit if session freed */
|
|
- if (session_put(session))
|
|
- return 0;
|
|
-
|
|
- break;
|
|
- case -EBUSY:
|
|
- /*
|
|
- * (GP) TA needs time to close. The "TA closed" notification
|
|
- * will trigger a new call to session_close().
|
|
- * Return OK but do not unref.
|
|
- */
|
|
- break;
|
|
- default:
|
|
- MCDRV_ERROR("Failed to close session %x in SWd",
|
|
- session->mcp_session.id);
|
|
- ret = -EPERM;
|
|
- }
|
|
-
|
|
- mutex_unlock(&session->close_lock);
|
|
- return ret;
|
|
-}
|
|
-
|
|
-/*
|
|
- * Free session object and all objects it contains (wsm).
|
|
- */
|
|
-static void session_free(struct kref *kref)
|
|
-{
|
|
- struct tbase_session *session;
|
|
- struct tbase_wsm *wsm, *next;
|
|
-
|
|
- /* Remove remaining shared buffers (unmapped in SWd by mcp_close) */
|
|
- session = container_of(kref, struct tbase_session, kref);
|
|
- list_for_each_entry_safe(wsm, next, &session->wsms, list) {
|
|
- MCDRV_DBG("session %p: free wsm %p", session, wsm);
|
|
- wsm_free(wsm);
|
|
- }
|
|
-
|
|
- MCDRV_DBG("freed session %p: client %p id %x",
|
|
- session, session->client, session->mcp_session.id);
|
|
- kfree(session);
|
|
-}
|
|
-
|
|
-/*
|
|
- * Unreference session.
|
|
- * Free session object if reference reaches 0.
|
|
- */
|
|
-int session_put(struct tbase_session *session)
|
|
-{
|
|
- return kref_put(&session->kref, session_free);
|
|
-}
|
|
-
|
|
-/*
|
|
- * Send a notification to TA
|
|
- */
|
|
-int session_notify_swd(struct tbase_session *session)
|
|
-{
|
|
- if (!session) {
|
|
- MCDRV_ERROR("Session pointer is null");
|
|
- return -EINVAL;
|
|
- }
|
|
-
|
|
- return mcp_notify(&session->mcp_session);
|
|
-}
|
|
-
|
|
-/*
|
|
- * Read and clear last notification received from TA
|
|
- */
|
|
-int32_t session_exitcode(struct tbase_session *session)
|
|
-{
|
|
- return mcp_session_exitcode(&session->mcp_session);
|
|
-}
|
|
-
|
|
-/*
|
|
- * Free a WSM object
|
|
- */
|
|
-static void wsm_free(struct tbase_wsm *wsm)
|
|
-{
|
|
- /* Remove wsm from its parent session's list */
|
|
- list_del(&wsm->list);
|
|
- /* Free MMU table */
|
|
- if (!IS_ERR_OR_NULL(wsm->mmu))
|
|
- tbase_mmu_delete(wsm->mmu);
|
|
-
|
|
- /* Unref cbuf if applicable */
|
|
- if (wsm->cbuf)
|
|
- tbase_cbuf_put(wsm->cbuf);
|
|
-
|
|
- /* Delete wsm object */
|
|
- MCDRV_DBG("freed wsm %p: mmu %p cbuf %p va %lx len %u",
|
|
- wsm, wsm->mmu, wsm->cbuf, wsm->va, wsm->len);
|
|
- kfree(wsm);
|
|
-}
|
|
-
|
|
-static struct tbase_wsm *wsm_create(struct tbase_session *session,
|
|
- uintptr_t buf, uint32_t len)
|
|
-{
|
|
- struct tbase_wsm *wsm;
|
|
- struct task_struct *task = NULL;
|
|
- uintptr_t va;
|
|
- int ret;
|
|
-
|
|
- /* Allocate structure */
|
|
- wsm = kzalloc(sizeof(*wsm), GFP_KERNEL);
|
|
- if (!wsm) {
|
|
- ret = -ENOMEM;
|
|
- goto err_no_wsm;
|
|
- }
|
|
-
|
|
- /* Add wsm to list so destroy can find it */
|
|
- list_add(&wsm->list, &session->wsms);
|
|
-
|
|
- /* Check if buffer is contained in a cbuf */
|
|
- wsm->cbuf = tbase_cbuf_get_by_addr(session->client, buf);
|
|
- if (wsm->cbuf) {
|
|
- uintptr_t offset;
|
|
-
|
|
- if (client_is_kernel(session->client))
|
|
- offset = buf - tbase_cbuf_addr(wsm->cbuf);
|
|
- else
|
|
- offset = buf - tbase_cbuf_uaddr(wsm->cbuf);
|
|
-
|
|
- if ((offset + len) > tbase_cbuf_len(wsm->cbuf)) {
|
|
- ret = -EINVAL;
|
|
- MCDRV_ERROR("crosses cbuf boundary");
|
|
- goto err;
|
|
- }
|
|
- /* Provide kernel virtual address */
|
|
- va = tbase_cbuf_addr(wsm->cbuf) + offset;
|
|
- } else {
|
|
- /* Not a cbuf. va is uva or kva depending on client. */
|
|
- /* Provide "task" if client is user */
|
|
- va = buf;
|
|
- if (!client_is_kernel(session->client))
|
|
- task = current;
|
|
- }
|
|
-
|
|
- /* Build MMU table for buffer */
|
|
- wsm->mmu = tbase_mmu_create(task, (void *)va, len);
|
|
- if (IS_ERR(wsm->mmu)) {
|
|
- ret = PTR_ERR(wsm->mmu);
|
|
- goto err;
|
|
- }
|
|
-
|
|
- wsm->va = buf;
|
|
- wsm->len = len;
|
|
- MCDRV_DBG("created wsm %p: mmu %p cbuf %p va %lx len %u",
|
|
- wsm, wsm->mmu, wsm->cbuf, wsm->va, wsm->len);
|
|
- goto end;
|
|
-
|
|
-err:
|
|
- wsm_free(wsm);
|
|
-err_no_wsm:
|
|
- wsm = ERR_PTR(ret);
|
|
-end:
|
|
- return wsm;
|
|
-}
|
|
-
|
|
-static inline int wsm_check(struct tbase_session *session,
|
|
- struct mc_ioctl_buffer *buf)
|
|
-{
|
|
- struct tbase_wsm *wsm;
|
|
-
|
|
- list_for_each_entry(wsm, &session->wsms, list) {
|
|
- if ((buf->va < (wsm->va + wsm->len)) &&
|
|
- ((buf->va + buf->len) > wsm->va)) {
|
|
- MCDRV_ERROR("buffer %lx overlaps with existing wsm",
|
|
- wsm->va);
|
|
- return -EADDRINUSE;
|
|
- }
|
|
- }
|
|
-
|
|
- return 0;
|
|
-}
|
|
-
|
|
-static inline struct tbase_wsm *wsm_find(struct tbase_session *session,
|
|
- uintptr_t va)
|
|
-{
|
|
- struct tbase_wsm *wsm;
|
|
-
|
|
- list_for_each_entry(wsm, &session->wsms, list)
|
|
- if (wsm->va == va)
|
|
- return wsm;
|
|
-
|
|
- return NULL;
|
|
-}
|
|
-
|
|
-static inline int wsm_info(struct tbase_wsm *wsm, struct kasnprintf_buf *buf)
|
|
-{
|
|
- ssize_t ret;
|
|
-
|
|
- ret = kasnprintf(buf, "\t\twsm %p: mmu %p cbuf %p va %lx len %u\n",
|
|
- wsm, wsm->mmu, wsm->cbuf, wsm->va, wsm->len);
|
|
- if (ret < 0)
|
|
- return ret;
|
|
-
|
|
- if (wsm->mmu) {
|
|
- ret = tbase_mmu_info(wsm->mmu, buf);
|
|
- if (ret < 0)
|
|
- return ret;
|
|
- }
|
|
-
|
|
- return 0;
|
|
-}
|
|
-
|
|
-/*
|
|
- * Share buffers with SWd and add corresponding WSM objects to session.
|
|
- */
|
|
-int session_wsms_add(struct tbase_session *session,
|
|
- struct mc_ioctl_buffer *bufs)
|
|
-{
|
|
- struct mc_ioctl_buffer *buf;
|
|
- struct mcp_buffer_map maps[MC_MAP_MAX];
|
|
- struct mcp_buffer_map *map;
|
|
- int i, ret = 0;
|
|
- uint32_t n_null_buf = 0;
|
|
-
|
|
- /* Check parameters */
|
|
- if (!session)
|
|
- return -ENXIO;
|
|
-
|
|
- /* Lock the session */
|
|
- mutex_lock(&session->wsms_lock);
|
|
-
|
|
- for (i = 0, buf = bufs, map = maps; i < MC_MAP_MAX; i++, buf++, map++) {
|
|
- if (!buf->va) {
|
|
- n_null_buf++;
|
|
- continue;
|
|
- }
|
|
-
|
|
- /* Avoid mapping overlaps */
|
|
- if (wsm_check(session, buf)) {
|
|
- ret = -EADDRINUSE;
|
|
- MCDRV_ERROR("maps[%d] va=%llx already map'd", i,
|
|
- buf->va);
|
|
- goto unlock;
|
|
- }
|
|
- }
|
|
-
|
|
- if (n_null_buf >= MC_MAP_MAX) {
|
|
- ret = -EINVAL;
|
|
- MCDRV_ERROR("va=NULL");
|
|
- goto unlock;
|
|
- }
|
|
-
|
|
- for (i = 0, buf = bufs, map = maps; i < MC_MAP_MAX; i++, buf++, map++) {
|
|
- struct tbase_wsm *wsm;
|
|
-
|
|
- if (!buf->va) {
|
|
- map->type = WSM_INVALID;
|
|
- continue;
|
|
- }
|
|
-
|
|
- wsm = wsm_create(session, buf->va, buf->len);
|
|
- if (IS_ERR(wsm)) {
|
|
- ret = PTR_ERR(wsm);
|
|
- MCDRV_ERROR("maps[%d] va=%llx create failed: %d", i,
|
|
- buf->va, ret);
|
|
- goto end;
|
|
- }
|
|
-
|
|
- tbase_mmu_buffer(wsm->mmu, map);
|
|
- MCDRV_DBG("maps[%d] va=%llx: t:%u a:%llx o:%u l:%u", i, buf->va,
|
|
- map->type, map->phys_addr, map->offset, map->length);
|
|
- }
|
|
-
|
|
- /* Map buffers */
|
|
- if (g_ctx.f_multimap) {
|
|
- /* Send MCP message to map buffers in SWd */
|
|
- ret = mcp_multimap(session->mcp_session.id, maps);
|
|
- if (ret)
|
|
- MCDRV_ERROR("multimap failed: %d", ret);
|
|
- } else {
|
|
- /* Map each buffer */
|
|
- for (i = 0, buf = bufs, map = maps; i < MC_MAP_MAX; i++, buf++,
|
|
- map++) {
|
|
- if (!buf->va)
|
|
- continue;
|
|
-
|
|
- /* Send MCP message to map buffer in SWd */
|
|
- ret = mcp_map(session->mcp_session.id, map);
|
|
- if (ret) {
|
|
- MCDRV_ERROR("maps[%d] va=%llx map failed: %d",
|
|
- i, buf->va, ret);
|
|
- break;
|
|
- }
|
|
- }
|
|
- }
|
|
-
|
|
-end:
|
|
- for (i = 0, buf = bufs, map = maps; i < MC_MAP_MAX; i++, buf++, map++) {
|
|
- struct tbase_wsm *wsm = wsm_find(session, buf->va);
|
|
-
|
|
- if (!buf->va)
|
|
- continue;
|
|
-
|
|
- if (ret) {
|
|
- if (!wsm)
|
|
- break;
|
|
-
|
|
- /* Destroy mapping */
|
|
- wsm_free(wsm);
|
|
- } else {
|
|
- /* Store mapping */
|
|
- buf->sva = map->secure_va;
|
|
- wsm->sva = buf->sva;
|
|
- MCDRV_DBG("maps[%d] va=%llx map'd len=%u sva=%llx",
|
|
- i, buf->va, buf->len, buf->sva);
|
|
- }
|
|
- }
|
|
-
|
|
-unlock:
|
|
- /* Unlock the session */
|
|
- mutex_unlock(&session->wsms_lock);
|
|
- return ret;
|
|
-}
|
|
-
|
|
-/*
|
|
- * Stop sharing buffers and delete corrsponding WSM objects.
|
|
- */
|
|
-int session_wsms_remove(struct tbase_session *session,
|
|
- const struct mc_ioctl_buffer *bufs)
|
|
-{
|
|
- const struct mc_ioctl_buffer *buf;
|
|
- struct mcp_buffer_map maps[MC_MAP_MAX];
|
|
- struct mcp_buffer_map *map;
|
|
- int i, ret = 0;
|
|
- uint32_t n_null_buf = 0;
|
|
-
|
|
- if (!session) {
|
|
- MCDRV_ERROR("session pointer is null");
|
|
- return -EINVAL;
|
|
- }
|
|
-
|
|
- /* Lock the session */
|
|
- mutex_lock(&session->wsms_lock);
|
|
-
|
|
- /* Find, check and map buffer */
|
|
- for (i = 0, buf = bufs, map = maps; i < MC_MAP_MAX; i++, buf++, map++) {
|
|
- struct tbase_wsm *wsm;
|
|
-
|
|
- if (!buf->va) {
|
|
- n_null_buf++;
|
|
- map->secure_va = 0;
|
|
- continue;
|
|
- }
|
|
-
|
|
- wsm = wsm_find(session, buf->va);
|
|
- if (!wsm) {
|
|
- ret = -EADDRNOTAVAIL;
|
|
- MCDRV_ERROR("maps[%d] va=%llx not found", i,
|
|
- buf->va);
|
|
- goto out;
|
|
- }
|
|
-
|
|
- /* Check input params consistency */
|
|
- /* TODO: fix the spec, "len" is NOT ignored anymore */
|
|
- if ((wsm->sva != buf->sva) || (wsm->len != buf->len)) {
|
|
- MCDRV_ERROR("maps[%d] va=%llx no match: %x != %llx",
|
|
- i, buf->va, wsm->sva, buf->sva);
|
|
- MCDRV_ERROR("maps[%d] va=%llx no match: %u != %u",
|
|
- i, buf->va, wsm->len, buf->len);
|
|
- ret = -EINVAL;
|
|
- goto out;
|
|
- }
|
|
-
|
|
- tbase_mmu_buffer(wsm->mmu, map);
|
|
- map->secure_va = buf->sva;
|
|
- MCDRV_DBG("maps[%d] va=%llx: t:%u a:%llx o:%u l:%u s:%llx", i,
|
|
- buf->va, map->type, map->phys_addr, map->offset,
|
|
- map->length, map->secure_va);
|
|
- }
|
|
-
|
|
- if (n_null_buf >= MC_MAP_MAX) {
|
|
- ret = -EINVAL;
|
|
- MCDRV_ERROR("va=NULL");
|
|
- goto out;
|
|
- }
|
|
-
|
|
- if (g_ctx.f_multimap) {
|
|
- /* Send MCP command to unmap buffers in SWd */
|
|
- ret = mcp_multiunmap(session->mcp_session.id, maps);
|
|
- if (ret)
|
|
- MCDRV_ERROR("mcp_multiunmap failed: %d", ret);
|
|
- } else {
|
|
- for (i = 0, buf = bufs, map = maps; i < MC_MAP_MAX;
|
|
- i++, buf++, map++) {
|
|
- if (!buf->va)
|
|
- continue;
|
|
-
|
|
- /* Send MCP command to unmap buffer in SWd */
|
|
- ret = mcp_unmap(session->mcp_session.id, map);
|
|
- if (ret) {
|
|
- MCDRV_ERROR("maps[%d] va=%llx unmap failed: %d",
|
|
- i, buf->va, ret);
|
|
- break;
|
|
- }
|
|
- }
|
|
- }
|
|
-
|
|
- for (i = 0, buf = bufs; i < MC_MAP_MAX; i++, buf++) {
|
|
- struct tbase_wsm *wsm = wsm_find(session, buf->va);
|
|
-
|
|
- if (!wsm)
|
|
- break;
|
|
-
|
|
- /* Free wsm */
|
|
- wsm_free(wsm);
|
|
- MCDRV_DBG("maps[%d] va=%llx unmap'd len=%u sva=%llx", i,
|
|
- buf->va, buf->len, buf->sva);
|
|
- }
|
|
-
|
|
-out:
|
|
- mutex_unlock(&session->wsms_lock);
|
|
- return ret;
|
|
-}
|
|
-
|
|
-/*
|
|
- * Sleep until next notification from SWd.
|
|
- */
|
|
-int session_waitnotif(struct tbase_session *session, int32_t timeout)
|
|
-{
|
|
- return mcp_session_waitnotif(&session->mcp_session, timeout);
|
|
-}
|
|
-
|
|
-int session_info(struct tbase_session *session, struct kasnprintf_buf *buf)
|
|
-{
|
|
- struct tbase_wsm *wsm;
|
|
- int32_t exit_code = mcp_session_exitcode(&session->mcp_session);
|
|
- int ret;
|
|
-
|
|
- ret = kasnprintf(buf, "\tsession %p: %x rc %d\n", session,
|
|
- session->mcp_session.id, exit_code);
|
|
- if (ret < 0)
|
|
- return ret;
|
|
-
|
|
- /* WMSs */
|
|
- mutex_lock(&session->wsms_lock);
|
|
- if (list_empty(&session->wsms))
|
|
- goto done;
|
|
-
|
|
- list_for_each_entry(wsm, &session->wsms, list) {
|
|
- ret = wsm_info(wsm, buf);
|
|
- if (ret < 0)
|
|
- goto done;
|
|
- }
|
|
-
|
|
-done:
|
|
- mutex_unlock(&session->wsms_lock);
|
|
- if (ret < 0)
|
|
- return ret;
|
|
-
|
|
- return 0;
|
|
-}
|
|
diff --git a/drivers/gud/MobiCoreDriver/session.h b/drivers/gud/MobiCoreDriver/session.h
|
|
deleted file mode 100644
|
|
index aec0c09ae9c9a..0000000000000
|
|
--- a/drivers/gud/MobiCoreDriver/session.h
|
|
+++ /dev/null
|
|
@@ -1,63 +0,0 @@
|
|
-/*
|
|
- * Copyright (c) 2013-2015 TRUSTONIC LIMITED
|
|
- * All Rights Reserved.
|
|
- *
|
|
- * This program is free software; you can redistribute it and/or
|
|
- * modify it under the terms of the GNU General Public License
|
|
- * version 2 as published by the Free Software Foundation.
|
|
- *
|
|
- * This program is distributed in the hope that it will be useful,
|
|
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
- * GNU General Public License for more details.
|
|
- */
|
|
-
|
|
-#ifndef _SESSION_H_
|
|
-#define _SESSION_H_
|
|
-
|
|
-#include <linux/list.h>
|
|
-
|
|
-#include "mcp.h"
|
|
-
|
|
-struct tbase_object;
|
|
-struct tbase_mmu;
|
|
-struct mc_ioctl_buffer;
|
|
-
|
|
-struct tbase_session {
|
|
- /* Session list lock */
|
|
- struct mutex close_lock;
|
|
- /* MCP session descriptor (MUST BE FIRST) */
|
|
- struct mcp_session mcp_session;
|
|
- /* Owner */
|
|
- struct tbase_client *client;
|
|
- /* Number of references kept to this object */
|
|
- struct kref kref;
|
|
- /* The list entry to attach to session list of owner */
|
|
- struct list_head list;
|
|
- /* Session WSMs lock */
|
|
- struct mutex wsms_lock;
|
|
- /* List of WSMs for a session */
|
|
- struct list_head wsms;
|
|
-};
|
|
-
|
|
-struct tbase_session *session_create(struct tbase_client *client, bool is_gp,
|
|
- struct mc_identity *identity);
|
|
-int session_open(struct tbase_session *session, const struct tbase_object *obj,
|
|
- const struct tbase_mmu *obj_mmu, uintptr_t tci, size_t len);
|
|
-int session_close(struct tbase_session *session);
|
|
-static inline void session_get(struct tbase_session *session)
|
|
-{
|
|
- kref_get(&session->kref);
|
|
-}
|
|
-
|
|
-int session_put(struct tbase_session *session);
|
|
-int session_wsms_add(struct tbase_session *session,
|
|
- struct mc_ioctl_buffer *bufs);
|
|
-int session_wsms_remove(struct tbase_session *session,
|
|
- const struct mc_ioctl_buffer *bufs);
|
|
-int32_t session_exitcode(struct tbase_session *session);
|
|
-int session_notify_swd(struct tbase_session *session);
|
|
-int session_waitnotif(struct tbase_session *session, int32_t timeout);
|
|
-int session_info(struct tbase_session *session, struct kasnprintf_buf *buf);
|
|
-
|
|
-#endif /* _SESSION_H_ */
|
|
diff --git a/drivers/gud/setupDrivers.sh b/drivers/gud/setupDrivers.sh
|
|
deleted file mode 100644
|
|
index 994e83e8d9517..0000000000000
|
|
--- a/drivers/gud/setupDrivers.sh
|
|
+++ /dev/null
|
|
@@ -1,19 +0,0 @@
|
|
-#!/bin/bash
|
|
-export COMP_PATH_ROOT=$(dirname $(readlink -f $BASH_SOURCE)) #set this to the absolute path of the folder containing this file
|
|
-
|
|
-# This part has to be set by the customer
|
|
-# To be set, absolute path of kernel folder
|
|
-export LINUX_PATH=
|
|
-# To be set, absolute path! CROSS_COMPILE variable needed by kernel eg /home/user/arm-2009q3/bin/arm-none-linux-gnueabi-
|
|
-export CROSS_COMPILE=
|
|
-# To be set, build mode debug or release
|
|
-export MODE=debug
|
|
-# To be set, the absolute path to the Linux Android NDK
|
|
-export NDK_PATH=
|
|
-
|
|
-# Global variables needed by build scripts
|
|
-export COMP_PATH_Logwrapper=$COMP_PATH_ROOT/Logwrapper/Out
|
|
-export COMP_PATH_MobiCore=$COMP_PATH_ROOT/MobiCore/Out
|
|
-export COMP_PATH_MobiCoreDriverMod=$COMP_PATH_ROOT/mobicore_driver/Out
|
|
-export COMP_PATH_MobiCoreDriverLib=$COMP_PATH_ROOT/daemon/Out
|
|
-export COMP_PATH_AndroidNdkLinux=$NDK_PATH
|