1903 lines
50 KiB
Diff
1903 lines
50 KiB
Diff
From 79eeae58155770f8323cb69b19d554a0fdfa293b Mon Sep 17 00:00:00 2001
|
|
From: Yael Samet <yael.samet@intel.com>
|
|
Date: Mon, 14 Aug 2017 11:27:26 +0300
|
|
Subject: [PATCH 173/743] mei: dal: add bh plugin code
|
|
|
|
bh plugin defines and implements the protocol of managing applets in DAL.
|
|
(view to bh_command_id enum for all options)
|
|
This patch adds the code of the bh plugin
|
|
|
|
Change-Id: Ia09cbb903d65e8c1f58becb7ed00238f6f226f12
|
|
Signed-off-by: Yael Samet <yael.samet@intel.com>
|
|
Signed-off-by: Tomas Winkler <tomas.winkler@intel.com>
|
|
---
|
|
drivers/misc/mei/dal/bh_cmd_defs.h | 238 ++++++++
|
|
drivers/misc/mei/dal/bh_errcode.h | 153 ++++++
|
|
drivers/misc/mei/dal/bh_external.c | 475 ++++++++++++++++
|
|
drivers/misc/mei/dal/bh_external.h | 46 ++
|
|
drivers/misc/mei/dal/bh_internal.c | 846 +++++++++++++++++++++++++++++
|
|
drivers/misc/mei/dal/bh_internal.h | 78 +++
|
|
6 files changed, 1836 insertions(+)
|
|
create mode 100644 drivers/misc/mei/dal/bh_cmd_defs.h
|
|
create mode 100644 drivers/misc/mei/dal/bh_errcode.h
|
|
create mode 100644 drivers/misc/mei/dal/bh_external.c
|
|
create mode 100644 drivers/misc/mei/dal/bh_external.h
|
|
create mode 100644 drivers/misc/mei/dal/bh_internal.c
|
|
create mode 100644 drivers/misc/mei/dal/bh_internal.h
|
|
|
|
diff --git a/drivers/misc/mei/dal/bh_cmd_defs.h b/drivers/misc/mei/dal/bh_cmd_defs.h
|
|
new file mode 100644
|
|
index 000000000000..7ced1a26c2a6
|
|
--- /dev/null
|
|
+++ b/drivers/misc/mei/dal/bh_cmd_defs.h
|
|
@@ -0,0 +1,238 @@
|
|
+/* SPDX-License-Identifier: BSD-3-Clause OR GPL-2.0 */
|
|
+/*
|
|
+ * Copyright(c) 2016 - 2018 Intel Corporation. All rights reserved.
|
|
+ */
|
|
+
|
|
+#ifndef __BH_DAL_H_
|
|
+#define __BH_DAL_H_
|
|
+
|
|
+#include <linux/types.h>
|
|
+#include <linux/uuid.h>
|
|
+
|
|
+/**
|
|
+ * enum bh_command_id - bh command ids
|
|
+ *
|
|
+ * @BHP_CMD_INIT: init command
|
|
+ * @BHP_CMD_DEINIT: deinit command
|
|
+ * @BHP_CMD_VERIFY_JAVATA: verify ta
|
|
+ * @BHP_CMD_DOWNLOAD_JAVATA: download ta to DAL
|
|
+ * @BHP_CMD_OPEN_JTASESSION: open session to ta
|
|
+ * @BHP_CMD_CLOSE_JTASESSION: close session with ta
|
|
+ * @BHP_CMD_FORCECLOSE_JTASESSION: force close session
|
|
+ * @BHP_CMD_SENDANDRECV: send and receive massages to ta
|
|
+ * @BHP_CMD_SENDANDRECV_INTERNAL: internal send and receive
|
|
+ * @BHP_CMD_RUN_NATIVETA: run native trusted application
|
|
+ * (currently NOT SUPPORTED)
|
|
+ * @BHP_CMD_STOP_NATIVETA: stop running native ta (currently NOT SUPPORTED)
|
|
+ * @BHP_CMD_OPEN_SDSESSION: open security domain session
|
|
+ * @BHP_CMD_CLOSE_SDSESSION: close security domain session
|
|
+ * @BHP_CMD_INSTALL_SD: install new sub security domain
|
|
+ * @BHP_CMD_UNINSTALL_SD: uninstall sub security domain
|
|
+ * @BHP_CMD_INSTALL_JAVATA: install java ta
|
|
+ * @BHP_CMD_UNINSTALL_JAVATA: uninstall java ta
|
|
+ * @BHP_CMD_INSTALL_NATIVETA: install native ta (currently NOT SUPPORTED)
|
|
+ * @BHP_CMD_UNINSTALL_NATIVETA: uninstall native ta (currently NOT SUPPORTED)
|
|
+ * @BHP_CMD_LIST_SD: get list of all security domains
|
|
+ * @BHP_CMD_LIST_TA: get list of all installed trusted applications
|
|
+ * @BHP_CMD_RESET: reset command
|
|
+ * @BHP_CMD_LIST_TA_PROPERTIES: get list of all ta properties (ta manifest)
|
|
+ * @BHP_CMD_QUERY_TA_PROPERTY: query specified ta property
|
|
+ * @BHP_CMD_LIST_JTA_SESSIONS: get list of all opened ta sessions
|
|
+ * @BHP_CMD_LIST_TA_PACKAGES: get list of all ta packages in DAL
|
|
+ * @BHP_CMD_GET_ISD: get Intel security domain uuid
|
|
+ * @BHP_CMD_GET_SD_BY_TA: get security domain id of ta
|
|
+ * @BHP_CMD_LAUNCH_VM: lunch IVM
|
|
+ * @BHP_CMD_CLOSE_VM: close IVM
|
|
+ * @BHP_CMD_QUERY_NATIVETA_STATUS: query specified native ta status
|
|
+ * (currently NOT SUPPORTED)
|
|
+ * @BHP_CMD_QUERY_SD_STATUS: query specified security domain status
|
|
+ * @BHP_CMD_LIST_DOWNLOADED_NTA: get list of all native trusted applications
|
|
+ * (currently NOT SUPPORTED)
|
|
+ * @BHP_CMD_UPDATE_SVL: update security version list
|
|
+ * @BHP_CMD_CHECK_SVL_TA_BLOCKED_STATE: check if ta security version is blocked
|
|
+ * @BHP_CMD_QUERY_TEE_METADATA: get DAL metadata (including api_level,
|
|
+ * library_version, dal_key_hash and more)
|
|
+ *
|
|
+ * @BHP_CMD_MAX: max command id
|
|
+ */
|
|
+
|
|
+enum bh_command_id {
|
|
+ BHP_CMD_INIT = 0,
|
|
+ BHP_CMD_DEINIT,
|
|
+ BHP_CMD_VERIFY_JAVATA,
|
|
+ BHP_CMD_DOWNLOAD_JAVATA,
|
|
+ BHP_CMD_OPEN_JTASESSION,
|
|
+ BHP_CMD_CLOSE_JTASESSION,
|
|
+ BHP_CMD_FORCECLOSE_JTASESSION,
|
|
+ BHP_CMD_SENDANDRECV,
|
|
+ BHP_CMD_SENDANDRECV_INTERNAL,
|
|
+ BHP_CMD_RUN_NATIVETA,
|
|
+ BHP_CMD_STOP_NATIVETA,
|
|
+ BHP_CMD_OPEN_SDSESSION,
|
|
+ BHP_CMD_CLOSE_SDSESSION,
|
|
+ BHP_CMD_INSTALL_SD,
|
|
+ BHP_CMD_UNINSTALL_SD,
|
|
+ BHP_CMD_INSTALL_JAVATA,
|
|
+ BHP_CMD_UNINSTALL_JAVATA,
|
|
+ BHP_CMD_INSTALL_NATIVETA,
|
|
+ BHP_CMD_UNINSTALL_NATIVETA,
|
|
+ BHP_CMD_LIST_SD,
|
|
+ BHP_CMD_LIST_TA,
|
|
+ BHP_CMD_RESET,
|
|
+ BHP_CMD_LIST_TA_PROPERTIES,
|
|
+ BHP_CMD_QUERY_TA_PROPERTY,
|
|
+ BHP_CMD_LIST_JTA_SESSIONS,
|
|
+ BHP_CMD_LIST_TA_PACKAGES,
|
|
+ BHP_CMD_GET_ISD,
|
|
+ BHP_CMD_GET_SD_BY_TA,
|
|
+ BHP_CMD_LAUNCH_VM,
|
|
+ BHP_CMD_CLOSE_VM,
|
|
+ BHP_CMD_QUERY_NATIVETA_STATUS,
|
|
+ BHP_CMD_QUERY_SD_STATUS,
|
|
+ BHP_CMD_LIST_DOWNLOADED_NTA,
|
|
+ BHP_CMD_UPDATE_SVL,
|
|
+ BHP_CMD_CHECK_SVL_TA_BLOCKED_STATE,
|
|
+ BHP_CMD_QUERY_TEE_METADATA,
|
|
+ BHP_CMD_MAX
|
|
+};
|
|
+
|
|
+#define BH_MSG_RESP_MAGIC 0x55aaa5ff
|
|
+#define BH_MSG_CMD_MAGIC 0x55aaa3ff
|
|
+
|
|
+/**
|
|
+ * struct bh_msg_header - transport header
|
|
+ *
|
|
+ * @magic: BH_MSG_RESP/CMD_MAGIC
|
|
+ * @length: overall message length
|
|
+ */
|
|
+struct bh_msg_header {
|
|
+ u32 magic;
|
|
+ u32 length;
|
|
+};
|
|
+
|
|
+/**
|
|
+ * struct bh_command_header - bh command header
|
|
+ *
|
|
+ * @h: transport header
|
|
+ * @seq: message sequence number
|
|
+ * @id: the command id (enum bh_command_id)
|
|
+ * @pad: padded for 64 bit
|
|
+ * @cmd: command buffer
|
|
+ */
|
|
+struct bh_command_header {
|
|
+ struct bh_msg_header h;
|
|
+ u64 seq;
|
|
+ u32 id;
|
|
+ u8 pad[4];
|
|
+ s8 cmd[0];
|
|
+} __packed;
|
|
+
|
|
+/**
|
|
+ * struct bh_response_header - response header (from the DAL)
|
|
+ *
|
|
+ * @h: transport header
|
|
+ * @seq: message sequence number
|
|
+ * @ta_session_id: session id (DAL firmware address)
|
|
+ * @code: response code
|
|
+ * @pad: padded for 64 bit
|
|
+ * @data: response buffer
|
|
+ */
|
|
+struct bh_response_header {
|
|
+ struct bh_msg_header h;
|
|
+ u64 seq;
|
|
+ u64 ta_session_id;
|
|
+ s32 code;
|
|
+ u8 pad[4];
|
|
+ s8 data[0];
|
|
+} __packed;
|
|
+
|
|
+/**
|
|
+ * struct bh_download_jta_cmd - download java trusted application.
|
|
+ *
|
|
+ * @ta_id: trusted application (ta) id
|
|
+ * @ta_blob: trusted application blob
|
|
+ */
|
|
+struct bh_download_jta_cmd {
|
|
+ uuid_t ta_id;
|
|
+ s8 ta_blob[0];
|
|
+} __packed;
|
|
+
|
|
+/**
|
|
+ * struct bh_open_jta_session_cmd - open session to TA command
|
|
+ *
|
|
+ * @ta_id: trusted application (ta) id
|
|
+ * @buffer: session initial parameters (optional)
|
|
+ */
|
|
+struct bh_open_jta_session_cmd {
|
|
+ uuid_t ta_id;
|
|
+ s8 buffer[0];
|
|
+} __packed;
|
|
+
|
|
+/**
|
|
+ * struct bh_close_jta_session_cmd - close session to TA command
|
|
+ *
|
|
+ * @ta_session_id: session id
|
|
+ */
|
|
+struct bh_close_jta_session_cmd {
|
|
+ u64 ta_session_id;
|
|
+} __packed;
|
|
+
|
|
+/**
|
|
+ * struct bh_cmd - bh command
|
|
+ *
|
|
+ * @ta_session_id: session id
|
|
+ * @command: command id to ta
|
|
+ * @outlen: length of output buffer
|
|
+ * @buffer: data to send
|
|
+ */
|
|
+struct bh_cmd {
|
|
+ u64 ta_session_id;
|
|
+ s32 command;
|
|
+ u32 outlen;
|
|
+ s8 buffer[0];
|
|
+} __packed;
|
|
+
|
|
+/**
|
|
+ * struct bh_check_svl_ta_blocked_state_cmd - command to check if
|
|
+ * the trusted application security version is blocked
|
|
+ *
|
|
+ * @ta_id: trusted application id
|
|
+ */
|
|
+struct bh_check_svl_jta_blocked_state_cmd {
|
|
+ uuid_t ta_id;
|
|
+} __packed;
|
|
+
|
|
+/**
|
|
+ * struct bh_resp - bh response
|
|
+ *
|
|
+ * @response: response code. Originated from java in big endian format
|
|
+ * @buffer: response buffer
|
|
+ */
|
|
+struct bh_resp {
|
|
+ __be32 response;
|
|
+ s8 buffer[0];
|
|
+} __packed;
|
|
+
|
|
+/**
|
|
+ * struct bh_resp_bof - response when output buffer is too small
|
|
+ *
|
|
+ * @response: response code. Originated from java in big endian format
|
|
+ * @request_length: the needed output buffer length
|
|
+ */
|
|
+struct bh_resp_bof {
|
|
+ __be32 response;
|
|
+ __be32 request_length;
|
|
+} __packed;
|
|
+
|
|
+/**
|
|
+ * struct bh_resp_list_ta_packages - list of ta packages from DAL
|
|
+ *
|
|
+ * @count: count of ta packages
|
|
+ * @ta_ids: ta packages ids
|
|
+ */
|
|
+struct bh_resp_list_ta_packages {
|
|
+ u32 count;
|
|
+ uuid_t ta_ids[0];
|
|
+} __packed;
|
|
+
|
|
+#endif /* __BH_DAL_H_*/
|
|
diff --git a/drivers/misc/mei/dal/bh_errcode.h b/drivers/misc/mei/dal/bh_errcode.h
|
|
new file mode 100644
|
|
index 000000000000..145dbc3b9ae4
|
|
--- /dev/null
|
|
+++ b/drivers/misc/mei/dal/bh_errcode.h
|
|
@@ -0,0 +1,153 @@
|
|
+/* SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause */
|
|
+/*
|
|
+ * Copyright(c) 2016 - 2018 Intel Corporation. All rights reserved.
|
|
+ */
|
|
+
|
|
+#ifndef __BH_ERRCODE_H
|
|
+#define __BH_ERRCODE_H
|
|
+
|
|
+/*
|
|
+ * BH Error codes numbers across Beihai Host and Firmware.
|
|
+ */
|
|
+
|
|
+#define BH_SUCCESS 0x000
|
|
+
|
|
+/* BHP specific error code section */
|
|
+
|
|
+#define BPE_NOT_INIT 0x001
|
|
+#define BPE_SERVICE_UNAVAILABLE 0x002
|
|
+#define BPE_INTERNAL_ERROR 0x003
|
|
+#define BPE_COMMS_ERROR 0x004
|
|
+#define BPE_OUT_OF_MEMORY 0x005
|
|
+#define BPE_INVALID_PARAMS 0x006
|
|
+#define BPE_MESSAGE_TOO_SHORT 0x007
|
|
+#define BPE_MESSAGE_ILLEGAL 0x008
|
|
+#define BPE_NO_CONNECTION_TO_FIRMWARE 0x009
|
|
+#define BPE_NOT_IMPLEMENT 0x00A
|
|
+#define BPE_OUT_OF_RESOURCE 0x00B
|
|
+#define BPE_INITIALIZED_ALREADY 0x00C
|
|
+#define BPE_CONNECT_FAILED 0x00D
|
|
+
|
|
+/* General error code section for Beihai on FW: 0x100 */
|
|
+
|
|
+#define BHE_OUT_OF_MEMORY 0x101
|
|
+#define BHE_BAD_PARAMETER 0x102
|
|
+#define BHE_INSUFFICIENT_BUFFER 0x103
|
|
+#define BHE_MUTEX_INIT_FAIL 0x104
|
|
+#define BHE_COND_INIT_FAIL 0x105
|
|
+#define BHE_WD_TIMEOUT 0x106
|
|
+#define BHE_FAILED 0x107
|
|
+#define BHE_INVALID_HANDLE 0x108
|
|
+#define BHE_IPC_ERR_DEFAULT 0x109
|
|
+#define BHE_IPC_ERR_PLATFORM 0x10A
|
|
+#define BHE_IPC_SRV_INIT_FAIL 0x10B
|
|
+
|
|
+/* VM communication error code section: 0x200 */
|
|
+
|
|
+#define BHE_MAILBOX_NOT_FOUND 0x201
|
|
+#define BHE_APPLET_CRASHED BHE_MAILBOX_NOT_FOUND
|
|
+#define BHE_MSG_QUEUE_IS_FULL 0x202
|
|
+#define BHE_MAILBOX_DENIED 0x203
|
|
+
|
|
+/* VM InternalAppletCommunication error 0x240 */
|
|
+
|
|
+#define BHE_IAC_INTERNAL_SESSION_NUM_EXCEED 0x241
|
|
+#define BHE_IAC_CLIENT_SLOT_FULL 0x242
|
|
+#define BHE_IAC_SERVICETA_EXITED 0x243
|
|
+#define BHE_IAC_EXIST_INTERNAL_SESSION 0x244
|
|
+#define BHE_IAC_SERVICETA_UNCAUGHT_EXCEPTION 0x245
|
|
+#define BHE_IAC_SERVICE_SESSION_NOT_FOUND 0x246
|
|
+#define BHE_IAC_SERVICE_HOST_SESSION_NUM_EXCEED 0x247
|
|
+
|
|
+/* Firmware thread/mutex error code section: 0x280 */
|
|
+#define BHE_THREAD_ERROR 0x281
|
|
+#define BHE_THREAD_TIMED_OUT 0x282
|
|
+
|
|
+/* Applet manager error code section: 0x300 */
|
|
+
|
|
+#define BHE_LOAD_JEFF_FAIL 0x303
|
|
+#define BHE_PACKAGE_NOT_FOUND 0x304
|
|
+#define BHE_EXIST_LIVE_SESSION 0x305
|
|
+#define BHE_VM_INSTANCE_INIT_FAIL 0x306
|
|
+#define BHE_QUERY_PROP_NOT_SUPPORT 0x307
|
|
+#define BHE_INVALID_BPK_FILE 0x308
|
|
+#define BHE_PACKAGE_EXIST 0x309
|
|
+#define BHE_VM_INSTNACE_NOT_FOUND 0x312
|
|
+#define BHE_STARTING_JDWP_FAIL 0x313
|
|
+#define BHE_GROUP_CHECK_FAIL 0x314
|
|
+#define BHE_SDID_UNMATCH 0x315
|
|
+#define BHE_APPPACK_UNINITED 0x316
|
|
+#define BHE_SESSION_NUM_EXCEED 0x317
|
|
+#define BHE_TA_PACKAGE_HASH_VERIFY_FAIL 0x318
|
|
+#define BHE_SWITCH_ISD 0x319
|
|
+#define BHE_OPERATION_NOT_PERMITTED 0x31A
|
|
+
|
|
+/* VM Applet instance error code section: 0x400 */
|
|
+#define BHE_APPLET_GENERIC 0x400
|
|
+#define BHE_UNCAUGHT_EXCEPTION 0x401
|
|
+/* Bad parameters to applet */
|
|
+#define BHE_APPLET_BAD_PARAMETER 0x402
|
|
+/* Small response buffer */
|
|
+#define BHE_APPLET_SMALL_BUFFER 0x403
|
|
+/* Bad state */
|
|
+#define BHE_BAD_STATE 0x404
|
|
+
|
|
+/*TODO: Should be removed these UI error code when integrate with ME 9 */
|
|
+#define BHE_UI_EXCEPTION 0x501
|
|
+#define BHE_UI_ILLEGAL_USE 0x502
|
|
+#define BHE_UI_ILLEGAL_PARAMETER 0x503
|
|
+#define BHE_UI_NOT_INITIALIZED 0x504
|
|
+#define BHE_UI_NOT_SUPPORTED 0x505
|
|
+#define BHE_UI_OUT_OF_RESOURCES 0x506
|
|
+
|
|
+/* BeiHai VMInternalError code section: 0x600 */
|
|
+#define BHE_UNKNOWN 0x602
|
|
+#define BHE_MAGIC_UNMATCH 0x603
|
|
+#define BHE_UNIMPLEMENTED 0x604
|
|
+#define BHE_INTR 0x605
|
|
+#define BHE_CLOSED 0x606
|
|
+/* TODO: no used error, should remove*/
|
|
+#define BHE_BUFFER_OVERFLOW 0x607
|
|
+#define BHE_NOT_SUPPORTED 0x608
|
|
+#define BHE_WEAR_OUT_VIOLATION 0x609
|
|
+#define BHE_NOT_FOUND 0x610
|
|
+#define BHE_INVALID_PARAMS 0x611
|
|
+#define BHE_ACCESS_DENIED 0x612
|
|
+#define BHE_INVALID 0x614
|
|
+#define BHE_TIMEOUT 0x615
|
|
+
|
|
+/* SDM specific error code section: 0x800 */
|
|
+#define BHE_SDM_FAILED 0x800
|
|
+#define BHE_SDM_NOT_FOUND 0x801
|
|
+#define BHE_SDM_ALREADY_EXIST 0x803
|
|
+#define BHE_SDM_TATYPE_MISMATCH 0x804
|
|
+#define BHE_SDM_TA_NUMBER_LIMIT 0x805
|
|
+#define BHE_SDM_SIGNAGURE_VERIFY_FAIL 0x806
|
|
+#define BHE_SDM_PERMGROUP_CHECK_FAIL 0x807
|
|
+#define BHE_SDM_INSTALL_CONDITION_FAIL 0x808
|
|
+#define BHE_SDM_SVN_CHECK_FAIL 0x809
|
|
+#define BHE_SDM_TA_DB_NO_FREE_SLOT 0x80A
|
|
+#define BHE_SDM_SD_DB_NO_FREE_SLOT 0x80B
|
|
+#define BHE_SDM_SVL_DB_NO_FREE_SLOT 0x80C
|
|
+#define BHE_SDM_SVL_CHECK_FAIL 0x80D
|
|
+#define BHE_SDM_DB_READ_FAIL 0x80E
|
|
+#define BHE_SDM_DB_WRITE_FAIL 0x80F
|
|
+
|
|
+/* Launcher specific error code section: 0x900 */
|
|
+#define BHE_LAUNCHER_INIT_FAILED 0x901
|
|
+#define BHE_SD_NOT_INSTALLED 0x902
|
|
+#define BHE_NTA_NOT_INSTALLED 0x903
|
|
+#define BHE_PROCESS_SPAWN_FAILED 0x904
|
|
+#define BHE_PROCESS_KILL_FAILED 0x905
|
|
+#define BHE_PROCESS_ALREADY_RUNNING 0x906
|
|
+#define BHE_PROCESS_IN_TERMINATING 0x907
|
|
+#define BHE_PROCESS_NOT_EXIST 0x908
|
|
+#define BHE_PLATFORM_API_ERR 0x909
|
|
+#define BHE_PROCESS_NUM_EXCEED 0x09A
|
|
+
|
|
+/*
|
|
+ * BeihaiHAL Layer error code section:
|
|
+ * 0x1000,0x2000 reserved here, defined in CSG BeihaiStatusHAL.h
|
|
+ */
|
|
+
|
|
+#endif /* __BH_ERRCODE_H */
|
|
diff --git a/drivers/misc/mei/dal/bh_external.c b/drivers/misc/mei/dal/bh_external.c
|
|
new file mode 100644
|
|
index 000000000000..0cbb17ead060
|
|
--- /dev/null
|
|
+++ b/drivers/misc/mei/dal/bh_external.c
|
|
@@ -0,0 +1,475 @@
|
|
+// SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause
|
|
+/*
|
|
+ * Copyright(c) 2016 - 2018 Intel Corporation. All rights reserved.
|
|
+ */
|
|
+
|
|
+#include <linux/string.h>
|
|
+#include <linux/uuid.h>
|
|
+#include <linux/ctype.h>
|
|
+
|
|
+#include "bh_errcode.h"
|
|
+#include "bh_external.h"
|
|
+#include "bh_internal.h"
|
|
+
|
|
+/**
|
|
+ * uuid_is_valid_hyphenless - check if uuid is valid in hyphenless format
|
|
+ *
|
|
+ * @uuid_str: uuid string
|
|
+ *
|
|
+ * Return: true when uuid is valid in hyphenless format
|
|
+ * false when uuid is invalid
|
|
+ */
|
|
+static bool uuid_is_valid_hyphenless(const char *uuid_str)
|
|
+{
|
|
+ unsigned int i;
|
|
+
|
|
+ /* exclude (i == 8 || i == 13 || i == 18 || i == 23) */
|
|
+ for (i = 0; i < UUID_STRING_LEN - 4; i++)
|
|
+ if (!isxdigit(uuid_str[i]))
|
|
+ return false;
|
|
+
|
|
+ return true;
|
|
+}
|
|
+
|
|
+/**
|
|
+ * uuid_normalize_hyphenless - convert uuid from hyphenless format
|
|
+ * to standard format
|
|
+ *
|
|
+ * @uuid_hl: uuid string in hyphenless format
|
|
+ * @uuid_str: output param to hold uuid string in standard format
|
|
+ */
|
|
+static void uuid_normalize_hyphenless(const char *uuid_hl, char *uuid_str)
|
|
+{
|
|
+ unsigned int i;
|
|
+
|
|
+ for (i = 0; i < UUID_STRING_LEN; i++) {
|
|
+ if (i == 8 || i == 13 || i == 18 || i == 23)
|
|
+ uuid_str[i] = '-';
|
|
+ else
|
|
+ uuid_str[i] = *uuid_hl++;
|
|
+ }
|
|
+ uuid_str[i] = '\0';
|
|
+}
|
|
+
|
|
+/**
|
|
+ * dal_uuid_parse - convert uuid string to binary form
|
|
+ *
|
|
+ * Input uuid is in either hyphenless or standard format
|
|
+ *
|
|
+ * @uuid_str: uuid string
|
|
+ * @uuid: output param to hold uuid bin
|
|
+ *
|
|
+ * Return: 0 on success
|
|
+ * <0 on failure
|
|
+ */
|
|
+static int dal_uuid_parse(const char *uuid_str, uuid_t *uuid)
|
|
+{
|
|
+ char __uuid_str[UUID_STRING_LEN + 1];
|
|
+
|
|
+ if (!uuid_str || !uuid)
|
|
+ return -EINVAL;
|
|
+
|
|
+ if (uuid_is_valid_hyphenless(uuid_str)) {
|
|
+ uuid_normalize_hyphenless(uuid_str, __uuid_str);
|
|
+ uuid_str = __uuid_str;
|
|
+ }
|
|
+
|
|
+ return uuid_parse(uuid_str, uuid);
|
|
+}
|
|
+
|
|
+/**
|
|
+ * bh_msg_is_response - check if message is response
|
|
+ *
|
|
+ * @msg: message
|
|
+ * @len: message length
|
|
+ *
|
|
+ * Return: true when message is response
|
|
+ * false otherwise
|
|
+ */
|
|
+bool bh_msg_is_response(const void *msg, size_t len)
|
|
+{
|
|
+ const struct bh_response_header *r = msg;
|
|
+
|
|
+ return (len >= sizeof(*r) && r->h.magic == BH_MSG_RESP_MAGIC);
|
|
+}
|
|
+
|
|
+/**
|
|
+ * bh_msg_is_cmd - check if message is command
|
|
+ *
|
|
+ * @msg: message
|
|
+ * @len: message length
|
|
+ *
|
|
+ * Return: true when message is command
|
|
+ * false otherwise
|
|
+ */
|
|
+bool bh_msg_is_cmd(const void *msg, size_t len)
|
|
+{
|
|
+ const struct bh_command_header *c = msg;
|
|
+
|
|
+ return (len >= sizeof(*c) && c->h.magic == BH_MSG_CMD_MAGIC);
|
|
+}
|
|
+
|
|
+/**
|
|
+ * bh_msg_cmd_hdr - get the command header if message is command
|
|
+ *
|
|
+ * @msg: message
|
|
+ * @len: message length
|
|
+ *
|
|
+ * Return: pointer to the command header when message is command
|
|
+ * NULL otherwise
|
|
+ */
|
|
+const struct bh_command_header *bh_msg_cmd_hdr(const void *msg, size_t len)
|
|
+{
|
|
+ if (!bh_msg_is_cmd(msg, len))
|
|
+ return NULL;
|
|
+
|
|
+ return msg;
|
|
+}
|
|
+
|
|
+/**
|
|
+ * bh_msg_is_cmd_open_session - check if command is open session command
|
|
+ *
|
|
+ * @hdr: message header
|
|
+ *
|
|
+ * Return: true when command is open session command
|
|
+ * false otherwise
|
|
+ */
|
|
+bool bh_msg_is_cmd_open_session(const struct bh_command_header *hdr)
|
|
+{
|
|
+ return hdr->id == BHP_CMD_OPEN_JTASESSION;
|
|
+}
|
|
+
|
|
+/**
|
|
+ * bh_open_session_ta_id - get ta id from open session command
|
|
+ *
|
|
+ * @hdr: message header
|
|
+ * @count: message size
|
|
+ *
|
|
+ * Return: pointer to ta id when command is valid
|
|
+ * NULL otherwise
|
|
+ */
|
|
+const uuid_t *bh_open_session_ta_id(const struct bh_command_header *hdr,
|
|
+ size_t count)
|
|
+{
|
|
+ struct bh_open_jta_session_cmd *open_cmd;
|
|
+
|
|
+ if (count < sizeof(*hdr) + sizeof(*open_cmd))
|
|
+ return NULL;
|
|
+
|
|
+ open_cmd = (struct bh_open_jta_session_cmd *)hdr->cmd;
|
|
+
|
|
+ return &open_cmd->ta_id;
|
|
+}
|
|
+
|
|
+/**
|
|
+ * bh_session_is_killed - check if session is killed
|
|
+ *
|
|
+ * @code: the session return code
|
|
+ *
|
|
+ * Return: true when the session is killed
|
|
+ * false otherwise
|
|
+ */
|
|
+static bool bh_session_is_killed(int code)
|
|
+{
|
|
+ return (code == BHE_WD_TIMEOUT ||
|
|
+ code == BHE_UNCAUGHT_EXCEPTION ||
|
|
+ code == BHE_APPLET_CRASHED);
|
|
+}
|
|
+
|
|
+/**
|
|
+ * bh_ta_session_open - open session to ta
|
|
+ *
|
|
+ * This function will block until VM replied the response
|
|
+ *
|
|
+ * @host_id: out param to hold the session host_id
|
|
+ * @ta_id: trusted application (ta) id
|
|
+ * @ta_pkg: ta binary package
|
|
+ * @pkg_len: ta binary package length
|
|
+ * @init_param: init parameters to the session (optional)
|
|
+ * @init_len: length of the init parameters
|
|
+ *
|
|
+ * Return: 0 on success
|
|
+ * <0 on system failure
|
|
+ * >0 on DAL FW failure
|
|
+ */
|
|
+int bh_ta_session_open(u64 *host_id, const char *ta_id,
|
|
+ const u8 *ta_pkg, size_t pkg_len,
|
|
+ const u8 *init_param, size_t init_len)
|
|
+{
|
|
+ int ret;
|
|
+ uuid_t bin_ta_id;
|
|
+ unsigned int conn_idx;
|
|
+ unsigned int count;
|
|
+ bool found;
|
|
+ uuid_t *ta_ids = NULL;
|
|
+ unsigned int i;
|
|
+
|
|
+ if (!ta_id || !host_id)
|
|
+ return -EINVAL;
|
|
+
|
|
+ if (!ta_pkg || !pkg_len)
|
|
+ return -EINVAL;
|
|
+
|
|
+ if (!init_param && init_len != 0)
|
|
+ return -EINVAL;
|
|
+
|
|
+ if (dal_uuid_parse(ta_id, &bin_ta_id))
|
|
+ return -EINVAL;
|
|
+
|
|
+ *host_id = 0;
|
|
+
|
|
+ ret = bh_proxy_check_svl_jta_blocked_state(&bin_ta_id);
|
|
+ if (ret)
|
|
+ return ret;
|
|
+
|
|
+ /* 1: vm conn_idx is IVM dal FW client */
|
|
+ conn_idx = CONN_IDX_IVM;
|
|
+
|
|
+ /* 2.1: check whether the ta pkg existed in VM or not */
|
|
+ count = 0;
|
|
+ ret = bh_proxy_list_jta_packages(conn_idx, &count, &ta_ids);
|
|
+ if (ret)
|
|
+ return ret;
|
|
+
|
|
+ found = false;
|
|
+ for (i = 0; i < count; i++) {
|
|
+ if (uuid_equal(&bin_ta_id, &ta_ids[i])) {
|
|
+ found = true;
|
|
+ break;
|
|
+ }
|
|
+ }
|
|
+ kfree(ta_ids);
|
|
+
|
|
+ /* 2.2: download ta pkg if not already present. */
|
|
+ if (!found) {
|
|
+ ret = bh_proxy_dnload_jta(conn_idx, &bin_ta_id,
|
|
+ ta_pkg, pkg_len);
|
|
+ if (ret && ret != BHE_PACKAGE_EXIST)
|
|
+ return ret;
|
|
+ }
|
|
+
|
|
+ /* 3: send open session command to VM */
|
|
+ ret = bh_proxy_open_jta_session(conn_idx, &bin_ta_id,
|
|
+ init_param, init_len,
|
|
+ host_id, ta_pkg, pkg_len);
|
|
+ return ret;
|
|
+}
|
|
+
|
|
+/**
|
|
+ * bh_ta_session_command - send and receive data to/from ta
|
|
+ *
|
|
+ * This function will block until VM replied the response
|
|
+ *
|
|
+ * @host_id: session host id
|
|
+ * @command_id: command id
|
|
+ * @input: message to be sent
|
|
+ * @length: sent message size
|
|
+ * @output: output param to hold pointer to the buffer which
|
|
+ * will contain received message.
|
|
+ * This buffer is allocated by Beihai and freed by the user.
|
|
+ * @output_length: input and output param -
|
|
+ * - input: the expected maximum length of the received message
|
|
+ * - output: size of the received message
|
|
+ * @response_code: An optional output param to hold the return value
|
|
+ * from the applet. Can be NULL.
|
|
+ *
|
|
+ * Return: 0 on success
|
|
+ * < 0 on system failure
|
|
+ * > 0 on DAL FW failure
|
|
+ */
|
|
+int bh_ta_session_command(u64 host_id, int command_id,
|
|
+ const void *input, size_t length,
|
|
+ void **output, size_t *output_length,
|
|
+ int *response_code)
|
|
+{
|
|
+ int ret;
|
|
+ struct bh_command_header *h;
|
|
+ struct bh_cmd *cmd;
|
|
+ char cmdbuf[CMD_BUF_SIZE(*cmd)];
|
|
+ struct bh_response_header *resp_hdr;
|
|
+ unsigned int resp_len;
|
|
+ struct bh_session_record *session;
|
|
+ struct bh_resp *resp;
|
|
+ unsigned int conn_idx = CONN_IDX_IVM;
|
|
+ unsigned int len;
|
|
+
|
|
+ memset(cmdbuf, 0, sizeof(cmdbuf));
|
|
+ resp_hdr = NULL;
|
|
+
|
|
+ if (!bh_is_initialized())
|
|
+ return -EFAULT;
|
|
+
|
|
+ if (!input && length != 0)
|
|
+ return -EINVAL;
|
|
+
|
|
+ if (!output_length)
|
|
+ return -EINVAL;
|
|
+
|
|
+ if (output)
|
|
+ *output = NULL;
|
|
+
|
|
+ session = bh_session_find(conn_idx, host_id);
|
|
+ if (!session)
|
|
+ return -EINVAL;
|
|
+
|
|
+ h = (struct bh_command_header *)cmdbuf;
|
|
+ cmd = (struct bh_cmd *)h->cmd;
|
|
+ h->id = BHP_CMD_SENDANDRECV;
|
|
+ cmd->ta_session_id = session->ta_session_id;
|
|
+ cmd->command = command_id;
|
|
+ cmd->outlen = *output_length;
|
|
+
|
|
+ ret = bh_request(conn_idx, h, CMD_BUF_SIZE(*cmd), input, length,
|
|
+ host_id, (void **)&resp_hdr);
|
|
+ if (!resp_hdr)
|
|
+ return ret ? ret : -EFAULT;
|
|
+
|
|
+ if (!ret)
|
|
+ ret = resp_hdr->code;
|
|
+
|
|
+ session->ta_session_id = resp_hdr->ta_session_id;
|
|
+ resp_len = resp_hdr->h.length - sizeof(*resp_hdr);
|
|
+
|
|
+ if (ret == BHE_APPLET_SMALL_BUFFER &&
|
|
+ resp_len == sizeof(struct bh_resp_bof)) {
|
|
+ struct bh_resp_bof *bof =
|
|
+ (struct bh_resp_bof *)resp_hdr->data;
|
|
+
|
|
+ if (response_code)
|
|
+ *response_code = be32_to_cpu(bof->response);
|
|
+
|
|
+ *output_length = be32_to_cpu(bof->request_length);
|
|
+ }
|
|
+
|
|
+ if (ret)
|
|
+ goto out;
|
|
+
|
|
+ if (resp_len < sizeof(struct bh_resp)) {
|
|
+ ret = -EBADMSG;
|
|
+ goto out;
|
|
+ }
|
|
+
|
|
+ resp = (struct bh_resp *)resp_hdr->data;
|
|
+
|
|
+ if (response_code)
|
|
+ *response_code = be32_to_cpu(resp->response);
|
|
+
|
|
+ len = resp_len - sizeof(*resp);
|
|
+
|
|
+ if (*output_length < len) {
|
|
+ ret = -EMSGSIZE;
|
|
+ goto out;
|
|
+ }
|
|
+
|
|
+ if (len && output) {
|
|
+ *output = kmemdup(resp->buffer, len, GFP_KERNEL);
|
|
+ if (!*output) {
|
|
+ ret = -ENOMEM;
|
|
+ goto out;
|
|
+ }
|
|
+ }
|
|
+
|
|
+ *output_length = len;
|
|
+
|
|
+out:
|
|
+ if (bh_session_is_killed(resp_hdr->code))
|
|
+ bh_session_remove(conn_idx, session->host_id);
|
|
+
|
|
+ kfree(resp_hdr);
|
|
+
|
|
+ return ret;
|
|
+}
|
|
+
|
|
+/**
|
|
+ * bh_ta_session_close - close ta session
|
|
+ *
|
|
+ * This function will block until VM replied the response
|
|
+ *
|
|
+ * @host_id: session host id
|
|
+ *
|
|
+ * Return: 0 on success
|
|
+ * <0 on system failure
|
|
+ * >0 on DAL FW failure
|
|
+ */
|
|
+int bh_ta_session_close(u64 host_id)
|
|
+{
|
|
+ int ret;
|
|
+ char cmdbuf[CMD_BUF_SIZE(struct bh_close_jta_session_cmd)];
|
|
+ struct bh_response_header *resp_hdr;
|
|
+ struct bh_session_record *session;
|
|
+ unsigned int conn_idx = CONN_IDX_IVM;
|
|
+
|
|
+ memset(cmdbuf, 0, sizeof(cmdbuf));
|
|
+ resp_hdr = NULL;
|
|
+
|
|
+ session = bh_session_find(conn_idx, host_id);
|
|
+ if (!session)
|
|
+ return -EINVAL;
|
|
+
|
|
+ bh_prep_session_close_cmd(cmdbuf, session->ta_session_id);
|
|
+
|
|
+ ret = bh_request(conn_idx, cmdbuf, sizeof(cmdbuf), NULL, 0, host_id,
|
|
+ (void **)&resp_hdr);
|
|
+
|
|
+ if (!ret)
|
|
+ ret = resp_hdr->code;
|
|
+
|
|
+ kfree(resp_hdr);
|
|
+ /*
|
|
+ * An internal session exists, so we should not close the session.
|
|
+ * It means that host app should call this API at appropriate time.
|
|
+ */
|
|
+ if (ret != BHE_IAC_EXIST_INTERNAL_SESSION)
|
|
+ bh_session_remove(conn_idx, host_id);
|
|
+
|
|
+ return ret;
|
|
+}
|
|
+
|
|
+/**
|
|
+ * bh_filter_hdr - filter the sent message
|
|
+ *
|
|
+ * Allow to send valid messages only.
|
|
+ * The filtering is done using given filter functions table
|
|
+ *
|
|
+ * @hdr: message header
|
|
+ * @count: message size
|
|
+ * @ctx: context to send to the filter functions
|
|
+ * @tbl: filter functions table
|
|
+ *
|
|
+ * Return: 0 when message is valid
|
|
+ * <0 on otherwise
|
|
+ */
|
|
+int bh_filter_hdr(const struct bh_command_header *hdr, size_t count, void *ctx,
|
|
+ const bh_filter_func tbl[])
|
|
+{
|
|
+ int i;
|
|
+ int ret;
|
|
+
|
|
+ for (i = 0; tbl[i]; i++) {
|
|
+ ret = tbl[i](hdr, count, ctx);
|
|
+ if (ret < 0)
|
|
+ return ret;
|
|
+ }
|
|
+ return 0;
|
|
+}
|
|
+
|
|
+/**
|
|
+ * bh_prep_access_denied_response - prepare package with 'access denied'
|
|
+ * response code.
|
|
+ *
|
|
+ * This function is used to send in band error to user who trying to send
|
|
+ * message when he lacks the needed permissions
|
|
+ *
|
|
+ * @cmd: the invalid command message
|
|
+ * @res: out param to hold the response header
|
|
+ */
|
|
+void bh_prep_access_denied_response(const char *cmd,
|
|
+ struct bh_response_header *res)
|
|
+{
|
|
+ struct bh_command_header *cmd_hdr = (struct bh_command_header *)cmd;
|
|
+
|
|
+ res->h.magic = BH_MSG_RESP_MAGIC;
|
|
+ res->h.length = sizeof(*res);
|
|
+ res->code = BHE_OPERATION_NOT_PERMITTED;
|
|
+ res->seq = cmd_hdr->seq;
|
|
+}
|
|
diff --git a/drivers/misc/mei/dal/bh_external.h b/drivers/misc/mei/dal/bh_external.h
|
|
new file mode 100644
|
|
index 000000000000..68b3387a09ca
|
|
--- /dev/null
|
|
+++ b/drivers/misc/mei/dal/bh_external.h
|
|
@@ -0,0 +1,46 @@
|
|
+/* SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause */
|
|
+/*
|
|
+ * Copyright(c) 2016 - 2018 Intel Corporation. All rights reserved.
|
|
+ */
|
|
+
|
|
+#ifndef __BH_EXTERNAL_H
|
|
+#define __BH_EXTERNAL_H
|
|
+
|
|
+#include <linux/kernel.h>
|
|
+#include "bh_cmd_defs.h"
|
|
+
|
|
+# define MSG_SEQ_START_NUMBER BIT_ULL(32)
|
|
+
|
|
+bool bh_is_initialized(void);
|
|
+void bh_init_internal(void);
|
|
+void bh_deinit_internal(void);
|
|
+
|
|
+int bh_ta_session_open(u64 *host_id, const char *ta_id, const u8 *ta_pkg,
|
|
+ size_t pkg_len, const u8 *init_param, size_t init_len);
|
|
+
|
|
+int bh_ta_session_close(u64 host_id);
|
|
+
|
|
+int bh_ta_session_command(u64 host_id, int command_id, const void *input,
|
|
+ size_t length, void **output, size_t *output_length,
|
|
+ int *response_code);
|
|
+
|
|
+const struct bh_command_header *bh_msg_cmd_hdr(const void *msg, size_t len);
|
|
+
|
|
+typedef int (*bh_filter_func)(const struct bh_command_header *hdr,
|
|
+ size_t count, void *ctx);
|
|
+
|
|
+int bh_filter_hdr(const struct bh_command_header *hdr, size_t count, void *ctx,
|
|
+ const bh_filter_func tbl[]);
|
|
+
|
|
+bool bh_msg_is_cmd_open_session(const struct bh_command_header *hdr);
|
|
+
|
|
+const uuid_t *bh_open_session_ta_id(const struct bh_command_header *hdr,
|
|
+ size_t count);
|
|
+
|
|
+void bh_prep_access_denied_response(const char *cmd,
|
|
+ struct bh_response_header *res);
|
|
+
|
|
+bool bh_msg_is_cmd(const void *msg, size_t len);
|
|
+bool bh_msg_is_response(const void *msg, size_t len);
|
|
+
|
|
+#endif /* __BH_EXTERNAL_H */
|
|
diff --git a/drivers/misc/mei/dal/bh_internal.c b/drivers/misc/mei/dal/bh_internal.c
|
|
new file mode 100644
|
|
index 000000000000..6aa24d40d5e0
|
|
--- /dev/null
|
|
+++ b/drivers/misc/mei/dal/bh_internal.c
|
|
@@ -0,0 +1,846 @@
|
|
+// SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause
|
|
+/*
|
|
+ * Copyright(c) 2016 - 2018 Intel Corporation. All rights reserved.
|
|
+ */
|
|
+
|
|
+#define pr_fmt(fmt) KBUILD_MODNAME ":%s: " fmt, __func__
|
|
+
|
|
+#include <linux/types.h>
|
|
+#include <linux/mei_cl_bus.h>
|
|
+#include <linux/completion.h>
|
|
+#include "bh_errcode.h"
|
|
+#include "bh_external.h"
|
|
+#include "bh_internal.h"
|
|
+#include "dal_dev.h"
|
|
+
|
|
+/* BH initialization state */
|
|
+static atomic_t bh_state = ATOMIC_INIT(0);
|
|
+static u64 bh_host_id_number = MSG_SEQ_START_NUMBER;
|
|
+
|
|
+/**
|
|
+ * struct bh_request_cmd - bh request command
|
|
+ *
|
|
+ * @link: link in the request list of bh service
|
|
+ * @cmd: command header and data
|
|
+ * @cmd_len: command buffer length
|
|
+ * @conn_idx: connection index
|
|
+ * @host_id: session host id
|
|
+ * @response: response buffer
|
|
+ * @complete: request completion
|
|
+ * @ret: return value of the request
|
|
+ */
|
|
+struct bh_request_cmd {
|
|
+ struct list_head link;
|
|
+ u8 *cmd;
|
|
+ unsigned int cmd_len;
|
|
+ unsigned int conn_idx;
|
|
+ u64 host_id;
|
|
+ void *response;
|
|
+ struct completion complete;
|
|
+ int ret;
|
|
+};
|
|
+
|
|
+struct bh_service {
|
|
+ struct work_struct work;
|
|
+ struct mutex request_lock; /* request lock */
|
|
+ struct list_head request_list;
|
|
+};
|
|
+
|
|
+static struct bh_service bh_srvc;
|
|
+
|
|
+/*
|
|
+ * dal device session records list (array of list per dal device)
|
|
+ * represents opened sessions to dal fw client
|
|
+ */
|
|
+static struct list_head dal_dev_session_list[MAX_CONNECTIONS];
|
|
+
|
|
+/**
|
|
+ * bh_get_msg_host_id - increase the shared variable bh_host_id_number by 1
|
|
+ * and wrap around if needed
|
|
+ *
|
|
+ * Return: the updated host id number
|
|
+ */
|
|
+u64 bh_get_msg_host_id(void)
|
|
+{
|
|
+ bh_host_id_number++;
|
|
+ /* wrap around. sequence_number must
|
|
+ * not be 0, as required by Firmware VM
|
|
+ */
|
|
+ if (bh_host_id_number == 0)
|
|
+ bh_host_id_number = MSG_SEQ_START_NUMBER;
|
|
+
|
|
+ return bh_host_id_number;
|
|
+}
|
|
+
|
|
+/**
|
|
+ * bh_session_find - find session record by handle
|
|
+ *
|
|
+ * @conn_idx: DAL client connection idx
|
|
+ * @host_id: session host id
|
|
+ *
|
|
+ * Return: pointer to bh_session_record if found
|
|
+ * NULL if the session wasn't found
|
|
+ */
|
|
+struct bh_session_record *bh_session_find(unsigned int conn_idx, u64 host_id)
|
|
+{
|
|
+ struct bh_session_record *pos;
|
|
+ struct list_head *session_list = &dal_dev_session_list[conn_idx];
|
|
+
|
|
+ list_for_each_entry(pos, session_list, link) {
|
|
+ if (pos->host_id == host_id)
|
|
+ return pos;
|
|
+ }
|
|
+
|
|
+ return NULL;
|
|
+}
|
|
+
|
|
+/**
|
|
+ * bh_session_add - add session record to list
|
|
+ *
|
|
+ * @conn_idx: fw client connection idx
|
|
+ * @session: session record
|
|
+ */
|
|
+void bh_session_add(unsigned int conn_idx, struct bh_session_record *session)
|
|
+{
|
|
+ list_add_tail(&session->link, &dal_dev_session_list[conn_idx]);
|
|
+}
|
|
+
|
|
+/**
|
|
+ * bh_session_remove - remove session record from list, ad release its memory
|
|
+ *
|
|
+ * @conn_idx: fw client connection idx
|
|
+ * @host_id: session host id
|
|
+ */
|
|
+void bh_session_remove(unsigned int conn_idx, u64 host_id)
|
|
+{
|
|
+ struct bh_session_record *session;
|
|
+
|
|
+ session = bh_session_find(conn_idx, host_id);
|
|
+
|
|
+ if (session) {
|
|
+ list_del(&session->link);
|
|
+ kfree(session);
|
|
+ }
|
|
+}
|
|
+
|
|
+static void bh_request_free(struct bh_request_cmd *request)
|
|
+{
|
|
+ if (!request)
|
|
+ return;
|
|
+ kfree(request->cmd);
|
|
+ kfree(request->response);
|
|
+ kfree(request);
|
|
+ request = NULL;
|
|
+}
|
|
+
|
|
+static struct bh_request_cmd *bh_request_alloc(const void *hdr,
|
|
+ size_t hdr_len,
|
|
+ const void *data,
|
|
+ size_t data_len,
|
|
+ unsigned int conn_idx,
|
|
+ u64 host_id)
|
|
+{
|
|
+ struct bh_request_cmd *request;
|
|
+ size_t buf_len;
|
|
+
|
|
+ if (!hdr || hdr_len < sizeof(struct bh_command_header))
|
|
+ return ERR_PTR(-EINVAL);
|
|
+
|
|
+ if (!data && data_len)
|
|
+ return ERR_PTR(-EINVAL);
|
|
+
|
|
+ if (check_add_overflow(hdr_len, data_len, &buf_len))
|
|
+ return ERR_PTR(-EOVERFLOW);
|
|
+
|
|
+ request = kzalloc(sizeof(*request), GFP_KERNEL);
|
|
+ if (!request)
|
|
+ return ERR_PTR(-ENOMEM);
|
|
+
|
|
+ request->cmd = kmalloc(buf_len, GFP_KERNEL);
|
|
+ if (!request->cmd) {
|
|
+ kfree(request);
|
|
+ return ERR_PTR(-ENOMEM);
|
|
+ }
|
|
+
|
|
+ memcpy(request->cmd, hdr, hdr_len);
|
|
+ request->cmd_len = hdr_len;
|
|
+
|
|
+ if (data_len) {
|
|
+ memcpy(request->cmd + hdr_len, data, data_len);
|
|
+ request->cmd_len += data_len;
|
|
+ }
|
|
+
|
|
+ request->conn_idx = conn_idx;
|
|
+ request->host_id = host_id;
|
|
+
|
|
+ init_completion(&request->complete);
|
|
+
|
|
+ return request;
|
|
+}
|
|
+
|
|
+/**
|
|
+ * bh_transport_recv - receive message from DAL FW.
|
|
+ *
|
|
+ * @conn_idx: fw client connection idx
|
|
+ * @buffer: output buffer to hold the received message
|
|
+ * @size: output buffer size
|
|
+ *
|
|
+ * Return: 0 on success
|
|
+ * < 0 on failure
|
|
+ */
|
|
+static int bh_transport_recv(unsigned int conn_idx, void *buffer, size_t size)
|
|
+{
|
|
+ return 0;
|
|
+}
|
|
+
|
|
+/**
|
|
+ * bh_recv_message_try - try to receive and prosses message from DAL
|
|
+ *
|
|
+ * @conn_idx: fw client connection idx
|
|
+ * @response: output param to hold the response
|
|
+ * @out_host_id: output param to hold the received message host id
|
|
+ * it should be identical to the sent message host id
|
|
+ *
|
|
+ * Return: 0 on success
|
|
+ * <0 on failure
|
|
+ */
|
|
+static int bh_recv_message_try(unsigned int conn_idx, void **response,
|
|
+ u64 *out_host_id)
|
|
+{
|
|
+ int ret;
|
|
+ char *data;
|
|
+ struct bh_response_header hdr;
|
|
+
|
|
+ if (!response)
|
|
+ return -EINVAL;
|
|
+
|
|
+ *response = NULL;
|
|
+
|
|
+ memset(&hdr, 0, sizeof(hdr));
|
|
+ ret = bh_transport_recv(conn_idx, &hdr, sizeof(hdr));
|
|
+ if (ret)
|
|
+ return ret;
|
|
+
|
|
+ if (hdr.h.length < sizeof(hdr))
|
|
+ return -EBADMSG;
|
|
+
|
|
+ /* check magic */
|
|
+ if (hdr.h.magic != BH_MSG_RESP_MAGIC)
|
|
+ return -EBADMSG;
|
|
+
|
|
+ data = kzalloc(hdr.h.length, GFP_KERNEL);
|
|
+ if (!data)
|
|
+ return -ENOMEM;
|
|
+
|
|
+ memcpy(data, &hdr, sizeof(hdr));
|
|
+
|
|
+ /* message contains hdr only */
|
|
+ if (hdr.h.length == sizeof(hdr))
|
|
+ goto out;
|
|
+
|
|
+ ret = bh_transport_recv(conn_idx, data + sizeof(hdr),
|
|
+ hdr.h.length - sizeof(hdr));
|
|
+out:
|
|
+ if (out_host_id)
|
|
+ *out_host_id = hdr.seq;
|
|
+
|
|
+ *response = data;
|
|
+
|
|
+ return ret;
|
|
+}
|
|
+
|
|
+#define MAX_RETRY_COUNT 3
|
|
+static int bh_recv_message(struct bh_request_cmd *request)
|
|
+{
|
|
+ u32 retry;
|
|
+ u64 res_host_id;
|
|
+ void *resp;
|
|
+ int ret;
|
|
+
|
|
+ for (resp = NULL, retry = 0; retry < MAX_RETRY_COUNT; retry++) {
|
|
+ kfree(resp);
|
|
+ resp = NULL;
|
|
+
|
|
+ res_host_id = 0;
|
|
+ ret = bh_recv_message_try(request->conn_idx,
|
|
+ &resp, &res_host_id);
|
|
+ if (ret) {
|
|
+ pr_debug("failed to recv msg = %d\n", ret);
|
|
+ continue;
|
|
+ }
|
|
+
|
|
+ if (res_host_id != request->host_id) {
|
|
+ pr_debug("recv message with host_id=%llu != sent host_id=%llu\n",
|
|
+ res_host_id, request->host_id);
|
|
+ continue;
|
|
+ }
|
|
+
|
|
+ pr_debug("recv message with try=%d host_id=%llu\n",
|
|
+ retry, request->host_id);
|
|
+ break;
|
|
+ }
|
|
+
|
|
+ if (retry == MAX_RETRY_COUNT) {
|
|
+ pr_err("out of retry attempts\n");
|
|
+ ret = -EFAULT;
|
|
+ }
|
|
+
|
|
+ if (ret) {
|
|
+ kfree(resp);
|
|
+ resp = NULL;
|
|
+ }
|
|
+
|
|
+ request->response = resp;
|
|
+ return ret;
|
|
+}
|
|
+
|
|
+/**
|
|
+ * bh_transport_send - send message to the DAL FW.
|
|
+ *
|
|
+ * @conn_idx: fw client connection idx
|
|
+ * @buffer: message to send
|
|
+ * @size: message size
|
|
+ * @host_id: message host id
|
|
+ *
|
|
+ * Return: 0 on success
|
|
+ * <0 on failure
|
|
+ */
|
|
+static int bh_transport_send(unsigned int conn_idx, const void *buffer,
|
|
+ unsigned int size, u64 host_id)
|
|
+{
|
|
+ return 0;
|
|
+}
|
|
+
|
|
+/**
|
|
+ * bh_send_message - build and send command message to DAL FW.
|
|
+ *
|
|
+ * @request: all request details
|
|
+ *
|
|
+ * Return: 0 on success
|
|
+ * < 0 on failure
|
|
+ */
|
|
+static int bh_send_message(const struct bh_request_cmd *request)
|
|
+{
|
|
+ struct bh_command_header *h;
|
|
+
|
|
+ if (!request)
|
|
+ return -EINVAL;
|
|
+
|
|
+ if (request->cmd_len < sizeof(*h) || !request->cmd)
|
|
+ return -EINVAL;
|
|
+
|
|
+ if (request->conn_idx > DAL_MEI_DEVICE_MAX)
|
|
+ return -ENODEV;
|
|
+
|
|
+ h = (struct bh_command_header *)request->cmd;
|
|
+ h->h.magic = BH_MSG_CMD_MAGIC;
|
|
+ h->h.length = request->cmd_len;
|
|
+ h->seq = request->host_id;
|
|
+
|
|
+ return bh_transport_send(request->conn_idx,
|
|
+ request->cmd, request->cmd_len,
|
|
+ request->host_id);
|
|
+}
|
|
+
|
|
+void bh_prep_session_close_cmd(void *cmdbuf, u64 ta_session_id)
|
|
+{
|
|
+ struct bh_command_header *h = cmdbuf;
|
|
+ struct bh_close_jta_session_cmd *cmd;
|
|
+
|
|
+ cmd = (struct bh_close_jta_session_cmd *)h->cmd;
|
|
+ h->id = BHP_CMD_CLOSE_JTASESSION;
|
|
+ cmd->ta_session_id = ta_session_id;
|
|
+}
|
|
+
|
|
+static int bh_send_recv_message(struct bh_request_cmd *request)
|
|
+{
|
|
+ int ret;
|
|
+
|
|
+ ret = bh_send_message(request);
|
|
+ if (ret)
|
|
+ return ret;
|
|
+
|
|
+ return bh_recv_message(request);
|
|
+}
|
|
+
|
|
+static void bh_request_work(struct work_struct *work)
|
|
+{
|
|
+ struct bh_service *bh_srv;
|
|
+ struct bh_request_cmd *request;
|
|
+ struct bh_command_header *h;
|
|
+ struct bh_response_header *resp_hdr;
|
|
+ int ret;
|
|
+
|
|
+ bh_srv = container_of(work, struct bh_service, work);
|
|
+
|
|
+ mutex_lock(&bh_srv->request_lock);
|
|
+ request = list_first_entry_or_null(&bh_srv->request_list,
|
|
+ struct bh_request_cmd, link);
|
|
+ if (!request) {
|
|
+ ret = -EINVAL;
|
|
+ goto out_free;
|
|
+ }
|
|
+
|
|
+ list_del_init(&request->link);
|
|
+
|
|
+ if (!request->cmd_len || !request->cmd) {
|
|
+ ret = -EINVAL;
|
|
+ goto out_free;
|
|
+ }
|
|
+
|
|
+ ret = bh_send_recv_message(request);
|
|
+ request->ret = ret;
|
|
+
|
|
+ if (wq_has_sleeper(&request->complete.wait)) {
|
|
+ mutex_unlock(&bh_srv->request_lock);
|
|
+ complete(&request->complete);
|
|
+ return;
|
|
+ }
|
|
+
|
|
+ /* no one waits for the response - clean up is needed */
|
|
+ pr_debug("no waiter - clean up is needed\n");
|
|
+ resp_hdr = (struct bh_response_header *)request->response;
|
|
+ /*
|
|
+ * if the command was open_session and
|
|
+ * it was succeeded then close the session
|
|
+ */
|
|
+ if (ret || resp_hdr->code)
|
|
+ goto out_free;
|
|
+
|
|
+ h = (struct bh_command_header *)request->cmd;
|
|
+ if (bh_msg_is_cmd_open_session(h)) {
|
|
+ char cmdbuf[CMD_BUF_SIZE(struct bh_close_jta_session_cmd)];
|
|
+ u64 host_id = request->host_id;
|
|
+
|
|
+ bh_request_free(request);
|
|
+
|
|
+ bh_prep_session_close_cmd(cmdbuf, resp_hdr->ta_session_id);
|
|
+ request = bh_request_alloc(cmdbuf, sizeof(cmdbuf), NULL, 0,
|
|
+ CONN_IDX_IVM, host_id);
|
|
+ if (!IS_ERR(request))
|
|
+ bh_send_recv_message(request);
|
|
+ }
|
|
+
|
|
+out_free:
|
|
+ bh_request_free(request);
|
|
+ mutex_unlock(&bh_srv->request_lock);
|
|
+}
|
|
+
|
|
+/**
|
|
+ * bh_request - send request to DAL FW and receive response back
|
|
+ *
|
|
+ * @conn_idx: fw client connection idx
|
|
+ * @cmd_hdr: command header
|
|
+ * @cmd_hdr_len: command header length
|
|
+ * @cmd_data: command data (message content)
|
|
+ * @cmd_data_len: data length
|
|
+ * @host_id: message host id
|
|
+ * @response: output param to hold the response
|
|
+ *
|
|
+ * Return: 0 on success
|
|
+ * <0 on failure
|
|
+ */
|
|
+int bh_request(unsigned int conn_idx, void *cmd_hdr, unsigned int cmd_hdr_len,
|
|
+ const void *cmd_data, unsigned int cmd_data_len,
|
|
+ u64 host_id, void **response)
|
|
+{
|
|
+ int ret;
|
|
+ struct bh_request_cmd *request;
|
|
+
|
|
+ mutex_lock(&bh_srvc.request_lock);
|
|
+ request = bh_request_alloc(cmd_hdr, cmd_hdr_len, cmd_data, cmd_data_len,
|
|
+ conn_idx, host_id);
|
|
+ if (IS_ERR(request)) {
|
|
+ mutex_unlock(&bh_srvc.request_lock);
|
|
+ return PTR_ERR(request);
|
|
+ }
|
|
+
|
|
+ list_add_tail(&request->link, &bh_srvc.request_list);
|
|
+ mutex_unlock(&bh_srvc.request_lock);
|
|
+
|
|
+ schedule_work(&bh_srvc.work);
|
|
+ ret = wait_for_completion_interruptible(&request->complete);
|
|
+ /*
|
|
+ * if wait was interrupted than do not free allocated memory.
|
|
+ * it is used by the worker
|
|
+ */
|
|
+ if (ret)
|
|
+ return ret;
|
|
+
|
|
+ mutex_lock(&bh_srvc.request_lock);
|
|
+
|
|
+ /* detach response buffer */
|
|
+ *response = request->response;
|
|
+ request->response = NULL;
|
|
+
|
|
+ ret = request->ret;
|
|
+
|
|
+ bh_request_free(request);
|
|
+
|
|
+ mutex_unlock(&bh_srvc.request_lock);
|
|
+
|
|
+ return ret;
|
|
+}
|
|
+
|
|
+/**
|
|
+ * bh_ession_list_free - free session list of given dal fw client
|
|
+ *
|
|
+ * @conn_idx: fw client connection idx
|
|
+ */
|
|
+static void bh_session_list_free(unsigned int conn_idx)
|
|
+{
|
|
+ struct bh_session_record *pos, *next;
|
|
+ struct list_head *session_list = &dal_dev_session_list[conn_idx];
|
|
+
|
|
+ list_for_each_entry_safe(pos, next, session_list, link) {
|
|
+ list_del(&pos->link);
|
|
+ kfree(pos);
|
|
+ }
|
|
+
|
|
+ INIT_LIST_HEAD(session_list);
|
|
+}
|
|
+
|
|
+/**
|
|
+ * bh_session_list_init - initialize session list of given dal fw client
|
|
+ *
|
|
+ * @conn_idx: fw client connection idx
|
|
+ */
|
|
+static void bh_session_list_init(unsigned int conn_idx)
|
|
+{
|
|
+ INIT_LIST_HEAD(&dal_dev_session_list[conn_idx]);
|
|
+}
|
|
+
|
|
+/**
|
|
+ * bh_proxy_check_svl_jta_blocked_state - check if ta security version
|
|
+ * is blocked
|
|
+ *
|
|
+ * When installing a ta, a minimum security version is given,
|
|
+ * so DAL will block installation of this ta from lower version.
|
|
+ * (even after the ta will be uninstalled)
|
|
+ *
|
|
+ * @ta_id: trusted application (ta) id
|
|
+ *
|
|
+ * Return: 0 when ta security version isn't blocked
|
|
+ * <0 on system failure
|
|
+ * >0 on DAL FW failure
|
|
+ */
|
|
+int bh_proxy_check_svl_jta_blocked_state(uuid_t *ta_id)
|
|
+{
|
|
+ int ret;
|
|
+ struct bh_command_header *h;
|
|
+ struct bh_check_svl_jta_blocked_state_cmd *cmd;
|
|
+ char cmdbuf[CMD_BUF_SIZE(*cmd)];
|
|
+ struct bh_response_header *resp_hdr;
|
|
+ u64 host_id;
|
|
+
|
|
+ if (!ta_id)
|
|
+ return -EINVAL;
|
|
+
|
|
+ memset(cmdbuf, 0, sizeof(cmdbuf));
|
|
+ resp_hdr = NULL;
|
|
+
|
|
+ h = (struct bh_command_header *)cmdbuf;
|
|
+ cmd = (struct bh_check_svl_jta_blocked_state_cmd *)h->cmd;
|
|
+ h->id = BHP_CMD_CHECK_SVL_TA_BLOCKED_STATE;
|
|
+ cmd->ta_id = *ta_id;
|
|
+
|
|
+ host_id = bh_get_msg_host_id();
|
|
+ ret = bh_request(CONN_IDX_SDM, h, CMD_BUF_SIZE(*cmd), NULL, 0,
|
|
+ host_id, (void **)&resp_hdr);
|
|
+
|
|
+ if (!ret)
|
|
+ ret = resp_hdr->code;
|
|
+
|
|
+ kfree(resp_hdr);
|
|
+
|
|
+ return ret;
|
|
+}
|
|
+
|
|
+/**
|
|
+ * bh_proxy_list_jta_packages - get list of ta packages in DAL
|
|
+ *
|
|
+ * @conn_idx: fw client connection idx
|
|
+ * @count: out param to hold the count of ta packages in DAL
|
|
+ * @ta_ids: out param to hold pointer to the ids of ta packages in DAL
|
|
+ * The buffer which holds the ids is allocated in this function
|
|
+ * and freed by the caller
|
|
+ *
|
|
+ * Return: 0 when ta security version isn't blocked
|
|
+ * <0 on system failure
|
|
+ * >0 on DAL FW failure
|
|
+ */
|
|
+int bh_proxy_list_jta_packages(unsigned int conn_idx, unsigned int *count,
|
|
+ uuid_t **ta_ids)
|
|
+{
|
|
+ int ret;
|
|
+ struct bh_command_header h;
|
|
+ struct bh_response_header *resp_hdr;
|
|
+ unsigned int resp_len;
|
|
+ struct bh_resp_list_ta_packages *resp;
|
|
+ uuid_t *outbuf;
|
|
+ unsigned int i;
|
|
+ u64 host_id;
|
|
+
|
|
+ memset(&h, 0, sizeof(h));
|
|
+ resp_hdr = NULL;
|
|
+
|
|
+ if (!bh_is_initialized())
|
|
+ return -EFAULT;
|
|
+
|
|
+ if (!count || !ta_ids)
|
|
+ return -EINVAL;
|
|
+
|
|
+ *ta_ids = NULL;
|
|
+ *count = 0;
|
|
+
|
|
+ h.id = BHP_CMD_LIST_TA_PACKAGES;
|
|
+
|
|
+ host_id = bh_get_msg_host_id();
|
|
+ ret = bh_request(conn_idx, &h, sizeof(h), NULL, 0, host_id,
|
|
+ (void **)&resp_hdr);
|
|
+
|
|
+ if (!ret)
|
|
+ ret = resp_hdr->code;
|
|
+ if (ret)
|
|
+ goto out;
|
|
+
|
|
+ resp_len = resp_hdr->h.length - sizeof(*resp_hdr);
|
|
+ if (resp_len < sizeof(*resp)) {
|
|
+ ret = -EBADMSG;
|
|
+ goto out;
|
|
+ }
|
|
+
|
|
+ resp = (struct bh_resp_list_ta_packages *)resp_hdr->data;
|
|
+ if (!resp->count) {
|
|
+ /* return success, there are no ta packages loaded in DAL FW */
|
|
+ ret = 0;
|
|
+ goto out;
|
|
+ }
|
|
+
|
|
+ if (resp_len != sizeof(uuid_t) * resp->count + sizeof(*resp)) {
|
|
+ ret = -EBADMSG;
|
|
+ goto out;
|
|
+ }
|
|
+
|
|
+ outbuf = kcalloc(resp->count, sizeof(uuid_t), GFP_KERNEL);
|
|
+
|
|
+ if (!outbuf) {
|
|
+ ret = -ENOMEM;
|
|
+ goto out;
|
|
+ }
|
|
+
|
|
+ for (i = 0; i < resp->count; i++)
|
|
+ outbuf[i] = resp->ta_ids[i];
|
|
+
|
|
+ *ta_ids = outbuf;
|
|
+ *count = resp->count;
|
|
+
|
|
+out:
|
|
+ kfree(resp_hdr);
|
|
+ return ret;
|
|
+}
|
|
+
|
|
+/**
|
|
+ * bh_proxy_dnload_jta - download ta package to DAL
|
|
+ *
|
|
+ * @conn_idx: fw client connection idx
|
|
+ * @ta_id: trusted application (ta) id
|
|
+ * @ta_pkg: ta binary package
|
|
+ * @pkg_len: ta binary package length
|
|
+ *
|
|
+ * Return: 0 on success
|
|
+ * <0 on system failure
|
|
+ * >0 on DAL FW failure
|
|
+ */
|
|
+int bh_proxy_dnload_jta(unsigned int conn_idx, uuid_t *ta_id,
|
|
+ const char *ta_pkg, unsigned int pkg_len)
|
|
+{
|
|
+ struct bh_command_header *h;
|
|
+ struct bh_download_jta_cmd *cmd;
|
|
+ char cmdbuf[CMD_BUF_SIZE(*cmd)];
|
|
+ struct bh_response_header *resp_hdr;
|
|
+ u64 host_id;
|
|
+ int ret;
|
|
+
|
|
+ if (!ta_pkg || !pkg_len || !ta_id)
|
|
+ return -EINVAL;
|
|
+
|
|
+ memset(cmdbuf, 0, sizeof(cmdbuf));
|
|
+ resp_hdr = NULL;
|
|
+
|
|
+ h = (struct bh_command_header *)cmdbuf;
|
|
+ cmd = (struct bh_download_jta_cmd *)h->cmd;
|
|
+ h->id = BHP_CMD_DOWNLOAD_JAVATA;
|
|
+ cmd->ta_id = *ta_id;
|
|
+
|
|
+ host_id = bh_get_msg_host_id();
|
|
+ ret = bh_request(conn_idx, h, CMD_BUF_SIZE(*cmd), ta_pkg, pkg_len,
|
|
+ host_id, (void **)&resp_hdr);
|
|
+
|
|
+ if (!ret)
|
|
+ ret = resp_hdr->code;
|
|
+
|
|
+ kfree(resp_hdr);
|
|
+
|
|
+ return ret;
|
|
+}
|
|
+
|
|
+/**
|
|
+ * bh_proxy_open_jta_session - send open session command
|
|
+ *
|
|
+ * @conn_idx: fw client connection idx
|
|
+ * @ta_id: trusted application (ta) id
|
|
+ * @init_buffer: init parameters to the session (optional)
|
|
+ * @init_len: length of the init parameters
|
|
+ * @host_id: out param to hold the session host id
|
|
+ * @ta_pkg: ta binary package
|
|
+ * @pkg_len: ta binary package length
|
|
+ *
|
|
+ * Return: 0 on success
|
|
+ * <0 on system failure
|
|
+ * >0 on DAL FW failure
|
|
+ */
|
|
+int bh_proxy_open_jta_session(unsigned int conn_idx,
|
|
+ uuid_t *ta_id,
|
|
+ const char *init_buffer,
|
|
+ unsigned int init_len,
|
|
+ u64 *host_id,
|
|
+ const char *ta_pkg,
|
|
+ unsigned int pkg_len)
|
|
+{
|
|
+ int ret;
|
|
+ struct bh_command_header *h;
|
|
+ struct bh_open_jta_session_cmd *cmd;
|
|
+ char cmdbuf[CMD_BUF_SIZE(*cmd)];
|
|
+ struct bh_response_header *resp_hdr;
|
|
+ struct bh_session_record *session;
|
|
+
|
|
+ if (!host_id || !ta_id)
|
|
+ return -EINVAL;
|
|
+
|
|
+ if (!init_buffer && init_len > 0)
|
|
+ return -EINVAL;
|
|
+
|
|
+ memset(cmdbuf, 0, sizeof(cmdbuf));
|
|
+ resp_hdr = NULL;
|
|
+
|
|
+ h = (struct bh_command_header *)cmdbuf;
|
|
+ cmd = (struct bh_open_jta_session_cmd *)h->cmd;
|
|
+
|
|
+ session = kzalloc(sizeof(*session), GFP_KERNEL);
|
|
+ if (!session)
|
|
+ return -ENOMEM;
|
|
+
|
|
+ session->host_id = bh_get_msg_host_id();
|
|
+ bh_session_add(conn_idx, session);
|
|
+
|
|
+ h->id = BHP_CMD_OPEN_JTASESSION;
|
|
+ cmd->ta_id = *ta_id;
|
|
+
|
|
+ ret = bh_request(conn_idx, h, CMD_BUF_SIZE(*cmd), init_buffer,
|
|
+ init_len, session->host_id, (void **)&resp_hdr);
|
|
+
|
|
+ if (!ret && resp_hdr)
|
|
+ ret = resp_hdr->code;
|
|
+
|
|
+ if (ret == BHE_PACKAGE_NOT_FOUND) {
|
|
+ /*
|
|
+ * VM might delete the TA pkg when no live session.
|
|
+ * Download the TA pkg and open session again
|
|
+ */
|
|
+ ret = bh_proxy_dnload_jta(conn_idx, ta_id, ta_pkg, pkg_len);
|
|
+ if (ret)
|
|
+ goto out;
|
|
+
|
|
+ kfree(resp_hdr);
|
|
+ resp_hdr = NULL;
|
|
+ ret = bh_request(conn_idx, h, CMD_BUF_SIZE(*cmd), init_buffer,
|
|
+ init_len, session->host_id,
|
|
+ (void **)&resp_hdr);
|
|
+
|
|
+ if (!ret && resp_hdr)
|
|
+ ret = resp_hdr->code;
|
|
+ }
|
|
+
|
|
+ if (resp_hdr)
|
|
+ session->ta_session_id = resp_hdr->ta_session_id;
|
|
+ *host_id = session->host_id;
|
|
+
|
|
+out:
|
|
+ if (ret)
|
|
+ bh_session_remove(conn_idx, session->host_id);
|
|
+
|
|
+ kfree(resp_hdr);
|
|
+
|
|
+ return ret;
|
|
+}
|
|
+
|
|
+/**
|
|
+ * bh_request_list_free - free request list of bh_service
|
|
+ *
|
|
+ * @request_list: request list
|
|
+ */
|
|
+static void bh_request_list_free(struct list_head *request_list)
|
|
+{
|
|
+ struct bh_request_cmd *pos, *next;
|
|
+
|
|
+ list_for_each_entry_safe(pos, next, request_list, link) {
|
|
+ list_del(&pos->link);
|
|
+ bh_request_free(pos);
|
|
+ }
|
|
+
|
|
+ INIT_LIST_HEAD(request_list);
|
|
+}
|
|
+
|
|
+/**
|
|
+ * bh_is_initialized - check if bh is initialized
|
|
+ *
|
|
+ * Return: true when bh is initialized and false otherwise
|
|
+ */
|
|
+bool bh_is_initialized(void)
|
|
+{
|
|
+ return atomic_read(&bh_state) == 1;
|
|
+}
|
|
+
|
|
+/**
|
|
+ * bh_init_internal - BH initialization function
|
|
+ *
|
|
+ * The BH initialization creates the session lists for all
|
|
+ * dal devices (dal fw clients)
|
|
+ *
|
|
+ * Return: 0
|
|
+ */
|
|
+void bh_init_internal(void)
|
|
+{
|
|
+ unsigned int i;
|
|
+
|
|
+ if (!atomic_add_unless(&bh_state, 1, 1))
|
|
+ return;
|
|
+
|
|
+ for (i = CONN_IDX_START; i < MAX_CONNECTIONS; i++)
|
|
+ bh_session_list_init(i);
|
|
+
|
|
+ INIT_LIST_HEAD(&bh_srvc.request_list);
|
|
+ mutex_init(&bh_srvc.request_lock);
|
|
+ INIT_WORK(&bh_srvc.work, bh_request_work);
|
|
+}
|
|
+
|
|
+/**
|
|
+ * bh_deinit_internal - BH deinit function
|
|
+ *
|
|
+ * The deinitialization frees the session lists of all
|
|
+ * dal devices (dal fw clients)
|
|
+ */
|
|
+void bh_deinit_internal(void)
|
|
+{
|
|
+ unsigned int i;
|
|
+
|
|
+ if (!atomic_add_unless(&bh_state, -1, 0))
|
|
+ return;
|
|
+
|
|
+ for (i = CONN_IDX_START; i < MAX_CONNECTIONS; i++)
|
|
+ bh_session_list_free(i);
|
|
+
|
|
+ cancel_work_sync(&bh_srvc.work);
|
|
+ bh_request_list_free(&bh_srvc.request_list);
|
|
+}
|
|
diff --git a/drivers/misc/mei/dal/bh_internal.h b/drivers/misc/mei/dal/bh_internal.h
|
|
new file mode 100644
|
|
index 000000000000..e50065b647e0
|
|
--- /dev/null
|
|
+++ b/drivers/misc/mei/dal/bh_internal.h
|
|
@@ -0,0 +1,78 @@
|
|
+/* SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause */
|
|
+/*
|
|
+ * Copyright(c) 2016 - 2018 Intel Corporation. All rights reserved.
|
|
+ */
|
|
+
|
|
+#ifndef __BH_INTERNAL_H
|
|
+#define __BH_INTERNAL_H
|
|
+
|
|
+#include <linux/list.h>
|
|
+#include <linux/slab.h>
|
|
+#include <linux/bitops.h>
|
|
+#include <linux/uuid.h>
|
|
+
|
|
+#include "bh_cmd_defs.h"
|
|
+
|
|
+/**
|
|
+ * struct bh_session_record - session record
|
|
+ *
|
|
+ * @link: link in dal_dev_session_list of dal fw client
|
|
+ * @host_id: message/session host id
|
|
+ * @ta_session_id: session id
|
|
+ */
|
|
+struct bh_session_record {
|
|
+ struct list_head link;
|
|
+ u64 host_id;
|
|
+ u64 ta_session_id;
|
|
+};
|
|
+
|
|
+/* command buffer size */
|
|
+#define CMD_BUF_SIZE(cmd) (sizeof(struct bh_command_header) + sizeof(cmd))
|
|
+
|
|
+/**
|
|
+ * enum bh_connection_index - connection index to dal fw clients
|
|
+ *
|
|
+ * @CONN_IDX_START: start idx
|
|
+ *
|
|
+ * @CONN_IDX_IVM: Intel/Issuer Virtual Machine
|
|
+ * @CONN_IDX_SDM: Security Domain Manager
|
|
+ * @CONN_IDX_LAUNCHER: Run Time Manager (Launcher)
|
|
+ *
|
|
+ * @MAX_CONNECTIONS: max connection idx
|
|
+ */
|
|
+enum bh_connection_index {
|
|
+ CONN_IDX_START = 0,
|
|
+
|
|
+ CONN_IDX_IVM = 0,
|
|
+ CONN_IDX_SDM = 1,
|
|
+ CONN_IDX_LAUNCHER = 2,
|
|
+
|
|
+ MAX_CONNECTIONS
|
|
+};
|
|
+
|
|
+u64 bh_get_msg_host_id(void);
|
|
+
|
|
+struct bh_session_record *bh_session_find(unsigned int conn_idx, u64 host_id);
|
|
+void bh_session_add(unsigned int conn_idx, struct bh_session_record *session);
|
|
+void bh_session_remove(unsigned int conn_idx, u64 host_id);
|
|
+
|
|
+int bh_request(unsigned int conn_idx,
|
|
+ void *hdr, unsigned int hdr_len,
|
|
+ const void *data, unsigned int data_len,
|
|
+ u64 host_id, void **response);
|
|
+
|
|
+int bh_proxy_check_svl_jta_blocked_state(uuid_t *ta_id);
|
|
+
|
|
+int bh_proxy_list_jta_packages(unsigned int conn_idx,
|
|
+ unsigned int *count, uuid_t **ta_ids);
|
|
+
|
|
+int bh_proxy_dnload_jta(unsigned int conn_idx, uuid_t *ta_id,
|
|
+ const char *ta_pkg, unsigned int pkg_len);
|
|
+
|
|
+int bh_proxy_open_jta_session(unsigned int conn_idx, uuid_t *ta_id,
|
|
+ const char *init_buffer, unsigned int init_len,
|
|
+ u64 *host_id, const char *ta_pkg,
|
|
+ unsigned int pkg_len);
|
|
+
|
|
+void bh_prep_session_close_cmd(void *cmdbuf, u64 ta_session_id);
|
|
+#endif /* __BH_INTERNAL_H */
|
|
--
|
|
2.19.2
|
|
|