clear-pkgs-linux-iot-lts2018/0158-mei-dal-add-kernel-spa...

728 lines
19 KiB
Diff

From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Yael Samet <yael.samet@intel.com>
Date: Tue, 5 Sep 2017 14:09:42 +0300
Subject: [PATCH] mei: dal: add kernel space interface
DAL kernel space interface exposes in-kernel API
to access trusted execution service in DAL.
The API is defined in <linux/dal.h> header file.
Change-Id: Ief3de92c3674ce8a21375bc11da38f1ae5fc3cc6
Signed-off-by: Yael Samet <yael.samet@intel.com>
Signed-off-by: Tomas Winkler <tomas.winkler@intel.com>
---
drivers/misc/mei/dal/Makefile | 1 +
drivers/misc/mei/dal/bh_external.c | 4 +-
drivers/misc/mei/dal/bh_internal.c | 37 ++-
drivers/misc/mei/dal/dal_class.c | 11 +-
drivers/misc/mei/dal/dal_dev.h | 6 +
drivers/misc/mei/dal/dal_kdi.c | 478 +++++++++++++++++++++++++++++
include/linux/dal.h | 59 ++++
7 files changed, 593 insertions(+), 3 deletions(-)
create mode 100644 drivers/misc/mei/dal/dal_kdi.c
create mode 100644 include/linux/dal.h
diff --git a/drivers/misc/mei/dal/Makefile b/drivers/misc/mei/dal/Makefile
index 705f53e12a61..c0d8b3d4f58d 100644
--- a/drivers/misc/mei/dal/Makefile
+++ b/drivers/misc/mei/dal/Makefile
@@ -8,3 +8,4 @@ mei_dal-objs += acp_parser.o
mei_dal-objs += bh_external.o
mei_dal-objs += bh_internal.o
mei_dal-objs += dal_cdev.o
+mei_dal-objs += dal_kdi.o
diff --git a/drivers/misc/mei/dal/bh_external.c b/drivers/misc/mei/dal/bh_external.c
index 0cbb17ead060..0679728266a4 100644
--- a/drivers/misc/mei/dal/bh_external.c
+++ b/drivers/misc/mei/dal/bh_external.c
@@ -6,6 +6,7 @@
#include <linux/string.h>
#include <linux/uuid.h>
#include <linux/ctype.h>
+#include <linux/dal.h>
#include "bh_errcode.h"
#include "bh_external.h"
@@ -62,7 +63,7 @@ static void uuid_normalize_hyphenless(const char *uuid_hl, char *uuid_str)
* Return: 0 on success
* <0 on failure
*/
-static int dal_uuid_parse(const char *uuid_str, uuid_t *uuid)
+int dal_uuid_parse(const char *uuid_str, uuid_t *uuid)
{
char __uuid_str[UUID_STRING_LEN + 1];
@@ -76,6 +77,7 @@ static int dal_uuid_parse(const char *uuid_str, uuid_t *uuid)
return uuid_parse(uuid_str, uuid);
}
+EXPORT_SYMBOL(dal_uuid_parse);
/**
* bh_msg_is_response - check if message is response
diff --git a/drivers/misc/mei/dal/bh_internal.c b/drivers/misc/mei/dal/bh_internal.c
index 6aa24d40d5e0..df3565a394c2 100644
--- a/drivers/misc/mei/dal/bh_internal.c
+++ b/drivers/misc/mei/dal/bh_internal.c
@@ -178,6 +178,7 @@ static struct bh_request_cmd *bh_request_alloc(const void *hdr,
return request;
}
+static char skip_buffer[DAL_MAX_BUFFER_SIZE] = {0};
/**
* bh_transport_recv - receive message from DAL FW.
*
@@ -190,6 +191,31 @@ static struct bh_request_cmd *bh_request_alloc(const void *hdr,
*/
static int bh_transport_recv(unsigned int conn_idx, void *buffer, size_t size)
{
+ size_t got;
+ unsigned int count;
+ char *buf = buffer;
+ int ret;
+
+ if (conn_idx > DAL_MEI_DEVICE_MAX)
+ return -ENODEV;
+
+ for (count = 0; count < size; count += got) {
+ got = min_t(size_t, size - count, DAL_MAX_BUFFER_SIZE);
+ if (buf)
+ ret = dal_kdi_recv(conn_idx, buf + count, &got);
+ else
+ ret = dal_kdi_recv(conn_idx, skip_buffer, &got);
+
+ if (!got)
+ return -EFAULT;
+
+ if (ret)
+ return ret;
+ }
+
+ if (count != size)
+ return -EFAULT;
+
return 0;
}
@@ -308,7 +334,16 @@ static int bh_recv_message(struct bh_request_cmd *request)
static int bh_transport_send(unsigned int conn_idx, const void *buffer,
unsigned int size, u64 host_id)
{
- return 0;
+ size_t chunk_sz = DAL_MAX_BUFFER_SIZE;
+ size_t count;
+ int ret;
+
+ for (ret = 0, count = 0; count < size && !ret; count += chunk_sz) {
+ chunk_sz = min_t(size_t, size - count, DAL_MAX_BUFFER_SIZE);
+ ret = dal_kdi_send(conn_idx, buffer + count, chunk_sz, host_id);
+ }
+
+ return ret;
}
/**
diff --git a/drivers/misc/mei/dal/dal_class.c b/drivers/misc/mei/dal/dal_class.c
index ccdf973a7895..c5ce81bea961 100644
--- a/drivers/misc/mei/dal/dal_class.c
+++ b/drivers/misc/mei/dal/dal_class.c
@@ -751,6 +751,9 @@ static void __exit mei_dal_exit(void)
mei_cldev_driver_unregister(&dal_driver);
dal_dev_exit();
+
+ dal_kdi_exit();
+
class_destroy(dal_class);
}
@@ -776,14 +779,20 @@ static int __init mei_dal_init(void)
goto err_class;
}
+ ret = dal_kdi_init();
+ if (ret)
+ goto err_dev;
+
ret = mei_cldev_driver_register(&dal_driver);
if (ret < 0) {
pr_err("mei_cl_driver_register failed with status = %d\n", ret);
- goto err_dev;
+ goto err;
}
return 0;
+err:
+ dal_kdi_exit();
err_dev:
dal_dev_exit();
err_class:
diff --git a/drivers/misc/mei/dal/dal_dev.h b/drivers/misc/mei/dal/dal_dev.h
index 3cad5a85c5de..3c3c696550c8 100644
--- a/drivers/misc/mei/dal/dal_dev.h
+++ b/drivers/misc/mei/dal/dal_dev.h
@@ -146,4 +146,10 @@ void dal_dc_print(struct device *dev, struct dal_client *dc);
int dal_dc_setup(struct dal_device *ddev, enum dal_intf intf);
void dal_dc_destroy(struct dal_device *ddev, enum dal_intf intf);
+int dal_kdi_send(unsigned int handle, const unsigned char *buf,
+ size_t len, u64 seq);
+int dal_kdi_recv(unsigned int handle, unsigned char *buf, size_t *count);
+int dal_kdi_init(void);
+void dal_kdi_exit(void);
+
#endif /* _DAL_KDI_H_ */
diff --git a/drivers/misc/mei/dal/dal_kdi.c b/drivers/misc/mei/dal/dal_kdi.c
new file mode 100644
index 000000000000..f39fb0055b27
--- /dev/null
+++ b/drivers/misc/mei/dal/dal_kdi.c
@@ -0,0 +1,478 @@
+// SPDX-License-Identifier: BSD-3-Clause OR GPL-2.0
+/*
+ * Copyright(c) 2016 - 2018 Intel Corporation. All rights reserved.
+ */
+
+#define pr_fmt(fmt) KBUILD_MODNAME ":%s: " fmt, __func__
+
+#include <linux/kernel.h>
+#include <linux/printk.h>
+#include <linux/atomic.h>
+#include <linux/module.h>
+#include <linux/mei_cl_bus.h>
+#include <linux/mei.h>
+#include <linux/sched.h>
+#include <linux/dal.h>
+
+#include "bh_external.h"
+#include "bh_errcode.h"
+#include "acp_parser.h"
+#include "dal_dev.h"
+
+static DEFINE_MUTEX(dal_kdi_lock);
+
+/**
+ * to_kdi_err- converts error number to kdi error
+ *
+ * Beihai errors (>0) are converted to DAL_KDI errors (those errors came
+ * from DAL FW)
+ * system errors and success value (<=0) stay as is
+ *
+ * @err: error code to convert (either bh err or system err)
+ *
+ * Return: the converted kdi error number or system error
+ */
+static int to_kdi_err(int err)
+{
+ if (err)
+ pr_debug("Error: %d\n", err);
+
+ if (err <= 0)
+ return err;
+
+ /* err > 0: is error from DAL FW */
+ switch (err) {
+ case BPE_INTERNAL_ERROR:
+ return DAL_KDI_STATUS_INTERNAL_ERROR;
+ case BPE_INVALID_PARAMS:
+ case BHE_INVALID_PARAMS:
+ return DAL_KDI_STATUS_INVALID_PARAMS;
+ case BHE_INVALID_HANDLE:
+ return DAL_KDI_STATUS_INVALID_HANDLE;
+ case BPE_NOT_INIT:
+ return DAL_KDI_STATUS_NOT_INITIALIZED;
+ case BPE_OUT_OF_MEMORY:
+ case BHE_OUT_OF_MEMORY:
+ return DAL_KDI_STATUS_OUT_OF_MEMORY;
+ case BHE_INSUFFICIENT_BUFFER:
+ case BHE_APPLET_SMALL_BUFFER:
+ return DAL_KDI_STATUS_BUFFER_TOO_SMALL;
+ case BPE_OUT_OF_RESOURCE:
+ case BHE_VM_INSTANCE_INIT_FAIL:
+ return DAL_KDI_STATUS_OUT_OF_RESOURCE;
+ case BHE_SESSION_NUM_EXCEED:
+ return DAL_KDI_STATUS_MAX_SESSIONS_REACHED;
+ case BHE_UNCAUGHT_EXCEPTION:
+ return DAL_KDI_STATUS_UNCAUGHT_EXCEPTION;
+ case BHE_WD_TIMEOUT:
+ return DAL_KDI_STATUS_WD_TIMEOUT;
+ case BHE_APPLET_CRASHED:
+ return DAL_KDI_STATUS_APPLET_CRASHED;
+ case BHE_TA_PACKAGE_HASH_VERIFY_FAIL:
+ return DAL_KDI_STATUS_INVALID_ACP;
+ case BHE_PACKAGE_NOT_FOUND:
+ return DAL_KDI_STATUS_TA_NOT_FOUND;
+ case BHE_PACKAGE_EXIST:
+ return DAL_KDI_STATUS_TA_EXIST;
+ default:
+ return DAL_KDI_STATUS_INTERNAL_ERROR;
+ }
+}
+
+/**
+ * dal_kdi_send - a callback which is called from bhp to send msg over mei
+ *
+ * @dev_idx: DAL device type
+ * @buf: message buffer
+ * @len: buffer length
+ * @seq: message sequence
+ *
+ * Return: 0 on success
+ * -EINVAL on incorrect input
+ * -ENODEV when the device can't be found
+ * -EFAULT if client is NULL
+ * <0 on dal_write failure
+ */
+int dal_kdi_send(unsigned int dev_idx, const unsigned char *buf,
+ size_t len, u64 seq)
+{
+ enum dal_dev_type mei_device;
+ struct dal_device *ddev;
+ struct dal_client *dc;
+ struct device *dev;
+ ssize_t wr;
+ int ret;
+
+ if (!buf)
+ return -EINVAL;
+
+ if (dev_idx >= DAL_MEI_DEVICE_MAX)
+ return -EINVAL;
+
+ if (!len)
+ return 0;
+
+ if (len > DAL_MAX_BUFFER_SIZE)
+ return -EMSGSIZE;
+
+ mei_device = (enum dal_dev_type)dev_idx;
+ dev = dal_find_dev(mei_device);
+ if (!dev) {
+ dev_dbg(dev, "can't find device\n");
+ return -ENODEV;
+ }
+
+ ddev = to_dal_device(dev);
+ dc = ddev->clients[DAL_INTF_KDI];
+ if (!dc) {
+ dev_dbg(dev, "client is NULL\n");
+ ret = -EFAULT;
+ goto out;
+ }
+
+ wr = dal_write(dc, buf, len, seq);
+ if (wr > 0)
+ ret = 0;
+ else
+ ret = wr;
+out:
+ put_device(dev);
+ return ret;
+}
+
+/**
+ * dal_kdi_recv - a callback which is called from bhp to recv msg from DAL FW
+ *
+ * @dev_idx: DAL device type
+ * @buf: buffer of received message
+ * @count: input and output param -
+ * - input: buffer length
+ * - output: size of the received message
+ *
+ * Return: 0 on success
+ * -EINVAL on incorrect input
+ * -ENODEV when the device can't be found
+ * -EFAULT when client is NULL or copy failed
+ * -EMSGSIZE when buffer is too small
+ * <0 on dal_wait_for_read failure
+ */
+int dal_kdi_recv(unsigned int dev_idx, unsigned char *buf, size_t *count)
+{
+ enum dal_dev_type mei_device;
+ struct dal_device *ddev;
+ struct dal_client *dc;
+ struct device *dev;
+ size_t r_len, len;
+ int ret;
+
+ if (!buf || !count)
+ return -EINVAL;
+
+ if (dev_idx >= DAL_MEI_DEVICE_MAX)
+ return -EINVAL;
+
+ mei_device = (enum dal_dev_type)dev_idx;
+ dev = dal_find_dev(mei_device);
+ if (!dev)
+ return -ENODEV;
+
+ ddev = to_dal_device(dev);
+ dc = ddev->clients[DAL_INTF_KDI];
+ if (!dc) {
+ dev_dbg(dev, "client is NULL\n");
+ ret = -EFAULT;
+ goto out;
+ }
+
+ ret = dal_wait_for_read(dc);
+ if (ret)
+ goto out;
+
+ if (kfifo_is_empty(&dc->read_queue)) {
+ *count = 0;
+ goto out;
+ }
+
+ r_len = kfifo_out(&dc->read_queue, &len, sizeof(len));
+ if (r_len != sizeof(len)) {
+ dev_err(&ddev->dev, "could not copy buffer: cannot fetch size\n");
+ ret = -EFAULT;
+ goto out;
+ }
+
+ if (len > *count) {
+ dev_dbg(&ddev->dev, "could not copy buffer: src size = %zd > dest size = %zd\n",
+ len, *count);
+ ret = -EMSGSIZE;
+ goto out;
+ }
+
+ r_len = kfifo_out(&dc->read_queue, buf, len);
+ if (r_len != len) {
+ dev_err(&ddev->dev, "could not copy buffer: src size = %zd, dest size = %d\n",
+ len, ret);
+ ret = -EFAULT;
+ goto out;
+ }
+
+ *count = len;
+ ret = 0;
+out:
+ put_device(dev);
+ return ret;
+}
+
+/**
+ * dal_create_session - create session to an installed trusted application.
+ *
+ * @session_handle: output param to hold the session handle
+ * @ta_id: trusted application (ta) id
+ * @acp_pkg: acp file of the ta
+ * @acp_pkg_len: acp file length
+ * @init_param: init parameters to the session (optional)
+ * @init_param_len: length of the init parameters
+ *
+ * Return: 0 on success
+ * <0 on system failure
+ * >0 on DAL FW failure
+ */
+int dal_create_session(u64 *session_handle, const char *ta_id,
+ const u8 *acp_pkg, size_t acp_pkg_len,
+ const u8 *init_param, size_t init_param_len)
+{
+ struct ac_ins_jta_pack_ext pack;
+ char *ta_pkg;
+ int ta_pkg_size;
+ int ret;
+
+ if (!ta_id || !acp_pkg || !acp_pkg_len || !session_handle)
+ return -EINVAL;
+
+ /* init_param are optional, if they exists the length shouldn't be 0 */
+ if (!init_param && init_param_len != 0) {
+ pr_debug("INVALID_PARAMS init_param %p init_param_len %zu\n",
+ init_param, init_param_len);
+ return -EINVAL;
+ }
+
+ mutex_lock(&dal_kdi_lock);
+
+ ret = acp_pload_ins_jta(acp_pkg, acp_pkg_len, &pack);
+ if (ret) {
+ pr_debug("acp_pload_ins_jta() return %d\n", ret);
+ goto out;
+ }
+
+ ta_pkg = pack.ta_pack;
+ if (!ta_pkg) {
+ ret = -EINVAL;
+ goto out;
+ }
+
+ ta_pkg_size = ta_pkg - (char *)acp_pkg;
+
+ if (ta_pkg_size < 0 || (unsigned int)ta_pkg_size > acp_pkg_len) {
+ ret = -EINVAL;
+ goto out;
+ }
+
+ ta_pkg_size = acp_pkg_len - ta_pkg_size;
+
+ ret = bh_ta_session_open(session_handle, ta_id, ta_pkg, ta_pkg_size,
+ init_param, init_param_len);
+
+ if (ret)
+ pr_debug("bh_ta_session_open failed = %d\n", ret);
+
+out:
+ mutex_unlock(&dal_kdi_lock);
+
+ return to_kdi_err(ret);
+}
+EXPORT_SYMBOL(dal_create_session);
+
+/**
+ * dal_send_and_receive - send and receive data to/from ta
+ *
+ * @session_handle: session handle
+ * @command_id: command id
+ * @input: message to be sent
+ * @input_len: sent message size
+ * @output: output param to hold a pointer to the buffer which
+ * will contain the received message.
+ * This buffer is allocated by DAL KDI module and freed by the user
+ * @output_len: 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 dal_send_and_receive(u64 session_handle, int command_id, const u8 *input,
+ size_t input_len, u8 **output, size_t *output_len,
+ int *response_code)
+{
+ int ret;
+
+ mutex_lock(&dal_kdi_lock);
+
+ ret = bh_ta_session_command(session_handle, command_id,
+ input, input_len,
+ (void **)output, output_len,
+ response_code);
+
+ if (ret)
+ pr_debug("bh_ta_session_command failed, status = %d\n", ret);
+
+ mutex_unlock(&dal_kdi_lock);
+
+ return to_kdi_err(ret);
+}
+EXPORT_SYMBOL(dal_send_and_receive);
+
+/**
+ * dal_close_session - close ta session
+ *
+ * @session_handle: session handle
+ *
+ * Return: 0 on success
+ * <0 on system failure
+ * >0 on DAL FW failure
+ */
+int dal_close_session(u64 session_handle)
+{
+ int ret;
+
+ mutex_lock(&dal_kdi_lock);
+
+ ret = bh_ta_session_close(session_handle);
+
+ if (ret)
+ pr_debug("hp_close_ta_session failed = %d\n", ret);
+
+ mutex_unlock(&dal_kdi_lock);
+
+ return to_kdi_err(ret);
+}
+EXPORT_SYMBOL(dal_close_session);
+
+#define KDI_MAJOR_VER "1"
+#define KDI_MINOR_VER "0"
+#define KDI_HOTFIX_VER "0"
+
+#define KDI_VERSION KDI_MAJOR_VER "." \
+ KDI_MINOR_VER "." \
+ KDI_HOTFIX_VER
+
+/**
+ * dal_get_version_info - return DAL driver version
+ *
+ * @version_info: output param to hold DAL driver version information
+ *
+ * Return: 0 on success
+ * -EINVAL on incorrect input
+ */
+int dal_get_version_info(struct dal_version_info *version_info)
+{
+ if (!version_info)
+ return -EINVAL;
+
+ memset(version_info, 0, sizeof(*version_info));
+ snprintf(version_info->version, DAL_VERSION_LEN, "%s", KDI_VERSION);
+
+ return 0;
+}
+EXPORT_SYMBOL(dal_get_version_info);
+
+/**
+ * dal_kdi_add_dev - add new dal device (one of dal_dev_type)
+ *
+ * @dev: device object which is associated with dal device
+ * @class_intf: class interface
+ *
+ * Return: 0 on success
+ * <0 on failure
+ *
+ * When new dal device is added, a new client is created for
+ * this device in kernel space interface
+ */
+static int dal_kdi_add_dev(struct device *dev,
+ struct class_interface *class_intf)
+{
+ int ret;
+ struct dal_device *ddev;
+
+ ddev = to_dal_device(dev);
+
+ mutex_lock(&ddev->context_lock);
+ ret = dal_dc_setup(ddev, DAL_INTF_KDI);
+ mutex_unlock(&ddev->context_lock);
+ return ret;
+}
+
+/**
+ * dal_kdi_rm_dev - rm dal device (one of dal_dev_type)
+ *
+ * @dev: device object which is associated with dal device
+ * @class_intf: class interface
+ *
+ * Return: 0 on success
+ * <0 on failure
+ */
+static void dal_kdi_rm_dev(struct device *dev,
+ struct class_interface *class_intf)
+{
+ struct dal_device *ddev;
+
+ ddev = to_dal_device(dev);
+
+ mutex_lock(&ddev->context_lock);
+ dal_dc_destroy(ddev, DAL_INTF_KDI);
+ mutex_unlock(&ddev->context_lock);
+}
+
+/*
+ * dal_kdi_interface handles addition/removal of dal devices
+ */
+static struct class_interface dal_kdi_interface __refdata = {
+ .add_dev = dal_kdi_add_dev,
+ .remove_dev = dal_kdi_rm_dev,
+};
+
+/**
+ * dal_kdi_init - initialize dal kdi
+ *
+ * Return: 0 on success
+ * <0 on failure
+ */
+int dal_kdi_init(void)
+{
+ int ret;
+
+ bh_init_internal();
+
+ dal_kdi_interface.class = dal_class;
+ ret = class_interface_register(&dal_kdi_interface);
+ if (ret) {
+ pr_err("failed to register class interface = %d\n", ret);
+ goto err;
+ }
+
+ return 0;
+
+err:
+ bh_deinit_internal();
+ return ret;
+}
+
+/**
+ * dal_kdi_exit - dal kdi exit function
+ */
+void dal_kdi_exit(void)
+{
+ bh_deinit_internal();
+ class_interface_unregister(&dal_kdi_interface);
+}
diff --git a/include/linux/dal.h b/include/linux/dal.h
new file mode 100644
index 000000000000..19a016ba3b9a
--- /dev/null
+++ b/include/linux/dal.h
@@ -0,0 +1,59 @@
+/* SPDX-License-Identifier: BSD-3-Clause OR GPL-2.0 */
+/*
+ * Copyright(c) 2016 - 2018 Intel Corporation. All rights reserved.
+ */
+
+#ifndef _DAL_H_
+#define _DAL_H_
+
+#include <linux/types.h>
+#include <linux/uuid.h>
+
+#define DAL_VERSION_LEN 32
+
+/**
+ * struct dal_version_info - dal version
+ *
+ * @version: current dal version
+ * @reserved: reserved bytes for future use
+ */
+struct dal_version_info {
+ char version[DAL_VERSION_LEN];
+ u32 reserved[4];
+};
+
+#define DAL_KDI_SUCCESS 0x000
+#define DAL_KDI_STATUS_INTERNAL_ERROR 0xA00
+#define DAL_KDI_STATUS_INVALID_PARAMS 0xA01
+#define DAL_KDI_STATUS_INVALID_HANDLE 0xA02
+#define DAL_KDI_STATUS_NOT_INITIALIZED 0xA03
+#define DAL_KDI_STATUS_OUT_OF_MEMORY 0xA04
+#define DAL_KDI_STATUS_BUFFER_TOO_SMALL 0xA05
+#define DAL_KDI_STATUS_OUT_OF_RESOURCE 0xA06
+#define DAL_KDI_STATUS_MAX_SESSIONS_REACHED 0xA07
+#define DAL_KDI_STATUS_UNCAUGHT_EXCEPTION 0xA08
+#define DAL_KDI_STATUS_WD_TIMEOUT 0xA09
+#define DAL_KDI_STATUS_APPLET_CRASHED 0xA0A
+#define DAL_KDI_STATUS_TA_NOT_FOUND 0xA0B
+#define DAL_KDI_STATUS_TA_EXIST 0xA0C
+#define DAL_KDI_STATUS_INVALID_ACP 0xA0D
+
+#define DAL_KDI_INVALID_HANDLE 0
+
+#define KDI_INIT_FLAGS_NONE 0
+
+int dal_get_version_info(struct dal_version_info *version_info);
+
+int dal_create_session(u64 *session_handle, const char *app_id,
+ const u8 *acp_pkg, size_t acp_pkg_len,
+ const u8 *init_param, size_t init_param_len);
+
+int dal_send_and_receive(u64 session_handle, int command_id, const u8 *input,
+ size_t input_len, u8 **output, size_t *output_len,
+ int *response_code);
+
+int dal_close_session(u64 session_handle);
+
+int dal_uuid_parse(const char *uuid_str, uuid_t *uuid);
+
+#endif /* _DAL_H_ */
--
https://clearlinux.org