clear-pkgs-linux-iot-lts2018/0154-mei-dal-add-acp-parser...

786 lines
19 KiB
Diff

From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Yael Samet <yael.samet@intel.com>
Date: Mon, 14 Aug 2017 11:23:38 +0300
Subject: [PATCH] mei: dal: add acp parser code
The ACP (Admin Command Pack) file represents a Java trusted application
(JTA) image to be downloaded to the DAL firmware.
This patch adds ACP file parser.
Change-Id: Ibc71f438b248cc9fc696db22289ad7d4962ea41c
Signed-off-by: Yael Samet <yael.samet@intel.com>
Signed-off-by: Tomas Winkler <tomas.winkler@intel.com>
---
drivers/misc/mei/dal/acp_format.h | 198 ++++++++++++
drivers/misc/mei/dal/acp_parser.c | 507 ++++++++++++++++++++++++++++++
drivers/misc/mei/dal/acp_parser.h | 38 +++
3 files changed, 743 insertions(+)
create mode 100644 drivers/misc/mei/dal/acp_format.h
create mode 100644 drivers/misc/mei/dal/acp_parser.c
create mode 100644 drivers/misc/mei/dal/acp_parser.h
diff --git a/drivers/misc/mei/dal/acp_format.h b/drivers/misc/mei/dal/acp_format.h
new file mode 100644
index 000000000000..7fdef3407152
--- /dev/null
+++ b/drivers/misc/mei/dal/acp_format.h
@@ -0,0 +1,198 @@
+/* SPDX-License-Identifier: BSD-3-Clause OR GPL-2.0 */
+/*
+ * Copyright(c) 2016 - 2018 Intel Corporation. All rights reserved.
+ */
+
+#ifndef _ACP_FORMAT_H
+#define _ACP_FORMAT_H
+
+#include <linux/uuid.h>
+
+#define AC_MAX_INS_REASONS_LENGTH 1024
+#define AC_MAX_USED_SERVICES 20
+#define AC_MAX_PROPS_LENGTH 2048
+#define AC_MAX_PACK_HASH_LEN 32
+
+/**
+ * enum ac_cmd_id - acp file command (acp type)
+ *
+ * @AC_CMD_INVALID: invalid command
+ * @AC_INSTALL_SD: install new sub security domain
+ * @AC_UNINSTALL_SD: uninstall sub security domain
+ * @AC_INSTALL_JTA: install java ta
+ * @AC_UNINSTALL_JTA: uninstall java ta
+ * @AC_INSTALL_NTA: install native ta (currently NOT SUPPORTED)
+ * @AC_UNINSTALL_NTA: uninstall native ta (currently NOT SUPPORTED)
+ * @AC_UPDATE_SVL: update the security version list
+ * @AC_INSTALL_JTA_PROP: ta properties for installation
+ * @AC_CMD_NUM: number of acp commands
+ */
+enum ac_cmd_id {
+ AC_CMD_INVALID,
+ AC_INSTALL_SD,
+ AC_UNINSTALL_SD,
+ AC_INSTALL_JTA,
+ AC_UNINSTALL_JTA,
+ AC_INSTALL_NTA,
+ AC_UNINSTALL_NTA,
+ AC_UPDATE_SVL,
+ AC_INSTALL_JTA_PROP,
+ AC_CMD_NUM
+};
+
+/**
+ * struct ac_pack_hash - ta pack hash
+ *
+ * @data: ta hash
+ */
+struct ac_pack_hash {
+ u8 data[AC_MAX_PACK_HASH_LEN];
+} __packed;
+
+/**
+ * struct ac_pack_header - admin comman pack header
+ *
+ * @magic: magic string which represents an ACP
+ * @version: package format version
+ * @byte_order: byte order of package (0 big endian, 1 little endian)
+ * @reserved: reserved bytes
+ * @size: total package size
+ * @cmd_id: acp command (acp file type)
+ * @svn: security version number
+ *
+ * @idx_num: the number of the indexed sections
+ * @idx_condition: condition section offset
+ * @idx_data: data section offset
+ */
+struct ac_pack_header {
+ /*ACP Header*/
+ u8 magic[4];
+ u8 version;
+ u8 byte_order;
+ u16 reserved;
+ u32 size;
+ u32 cmd_id;
+ u32 svn;
+
+ /* Index Section */
+ u32 idx_num;
+ u32 idx_condition;
+ u32 idx_data;
+} __packed;
+
+/**
+ * struct ac_ta_id_list - A list of ta ids which the ta
+ * is allowed to communicate with.
+ *
+ * @num: ta ids count
+ * @list: ta ids list
+ */
+struct ac_ta_id_list {
+ u32 num;
+ uuid_t list[0];
+} __packed;
+
+/**
+ * struct ac_prop_list - TLV list of acp properties
+ *
+ * @num: number of properties
+ * @len: size of all properties
+ * @data: acp properties. TLV format is "type\0key\0value\0"
+ * (e.g. string\0name\0Tom\0int\0Age\013\0)
+ */
+struct ac_prop_list {
+ u32 num;
+ u32 len;
+ s8 data[0];
+} __packed;
+
+/**
+ * struct ac_ins_reasons - list of event codes that can be
+ * received or posted by ta
+ *
+ * @len: event codes count
+ * @data: event codes list
+ */
+struct ac_ins_reasons {
+ u32 len;
+ u32 data[0];
+} __packed;
+
+/**
+ * struct ac_pack - general struct to hold parsed acp content
+ *
+ * @head: acp pack header
+ * @data: acp parsed content
+ */
+struct ac_pack {
+ struct ac_pack_header *head;
+ char data[0];
+} __packed;
+
+/**
+ * struct ac_ins_ta_header - ta installation header
+ *
+ * @ta_id: ta id
+ * @ta_svn: ta security version number
+ * @hash_alg_type: ta hash algorithm type
+ * @ta_reserved: reserved bytes
+ * @hash: ta pack hash
+ */
+struct ac_ins_ta_header {
+ uuid_t ta_id;
+ u32 ta_svn;
+ u8 hash_alg_type;
+ u8 ta_reserved[3];
+ struct ac_pack_hash hash;
+} __packed;
+
+/**
+ * struct ac_ins_jta_pack - ta installation information
+ *
+ * @ins_cond: ta install conditions (contains some of the manifest data,
+ * including security.version, applet.version, applet.platform,
+ * applet.api.level)
+ * @head: ta installation header
+ */
+struct ac_ins_jta_pack {
+ struct ac_prop_list *ins_cond;
+ struct ac_ins_ta_header *head;
+} __packed;
+
+/**
+ * struct ac_ins_jta_prop_header - ta manifest header
+ *
+ * @mem_quota: ta heap size
+ * @ta_encrypted: ta encrypted by provider flag
+ * @padding: padding
+ * @allowed_inter_session_num: allowed internal session count
+ * @ac_groups: ta permission groups
+ * @timeout: ta timeout in milliseconds
+ */
+struct ac_ins_jta_prop_header {
+ u32 mem_quota;
+ u8 ta_encrypted;
+ u8 padding;
+ u16 allowed_inter_session_num;
+ u64 ac_groups;
+ u32 timeout;
+} __packed;
+
+/**
+ * struct ac_ins_jta_prop - ta manifest
+ *
+ * @head: manifest header
+ * @post_reasons: list of event codes that can be posted by ta
+ * @reg_reasons: list of event codes that can be received by ta
+ * @prop: all other manifest fields (acp properties)
+ * @used_service_list: list of ta ids which ta is allowed to communicate with
+ */
+struct ac_ins_jta_prop {
+ struct ac_ins_jta_prop_header *head;
+ struct ac_ins_reasons *post_reasons;
+ struct ac_ins_reasons *reg_reasons;
+ struct ac_prop_list *prop;
+ struct ac_ta_id_list *used_service_list;
+} __packed;
+
+#endif /* _ACP_FORMAT_H */
diff --git a/drivers/misc/mei/dal/acp_parser.c b/drivers/misc/mei/dal/acp_parser.c
new file mode 100644
index 000000000000..462bd4860692
--- /dev/null
+++ b/drivers/misc/mei/dal/acp_parser.c
@@ -0,0 +1,507 @@
+// SPDX-License-Identifier: BSD-3-Clause OR GPL-2.0
+/*
+ * Copyright(c) 2016 - 2018 Intel Corporation. All rights reserved.
+ */
+
+#include <linux/kernel.h>
+#include <linux/errno.h>
+
+#include "acp_format.h"
+#include "acp_parser.h"
+
+/* CSS Header + CSS Crypto Block
+ * Prefixes each signed ACP package
+ */
+#define AC_CSS_HEADER_LENGTH (128 + 520)
+
+/**
+ * struct ac_pr_state - admin command pack reader state
+ *
+ * @cur : current read position
+ * @head : acp file head
+ * @total : size of acp file
+ */
+struct ac_pr_state {
+ const char *cur;
+ const char *head;
+ unsigned int total;
+};
+
+/**
+ * ac_pr_init - init pack reader
+ *
+ * @pr: pack reader
+ * @data: acp file content (without CSS header)
+ * @n: acp file size (without CSS header)
+ *
+ * Return: 0 on success
+ * -EINVAL on invalid parameters
+ */
+static int ac_pr_init(struct ac_pr_state *pr, const char *data,
+ unsigned int n)
+{
+ /* check integer overflow */
+ if ((size_t)data > SIZE_MAX - n)
+ return -EINVAL;
+
+ pr->cur = data;
+ pr->head = data;
+ pr->total = n;
+ return 0;
+}
+
+/**
+ * ac_pr_8b_align_move - update pack reader cur pointer after reading n_move
+ * bytes. Leave cur aligned to 8 bytes.
+ * (e.g. when n_move is 3, increase cur by 8)
+ *
+ * @pr: pack reader
+ * @n_move: number of bytes to move cur pointer ahead
+ * will be rounded up to keep cur 8 bytes aligned
+ *
+ * Return: 0 on success
+ * -EINVAL on invalid parameters
+ */
+static int ac_pr_8b_align_move(struct ac_pr_state *pr, size_t n_move)
+{
+ unsigned long offset;
+ const char *new_cur = pr->cur + n_move;
+ size_t len_from_head = new_cur - pr->head;
+
+ if ((size_t)pr->cur > SIZE_MAX - n_move || new_cur < pr->head)
+ return -EINVAL;
+
+ offset = ((8 - (len_from_head & 7)) & 7);
+ if ((size_t)new_cur > SIZE_MAX - offset)
+ return -EINVAL;
+
+ new_cur = new_cur + offset;
+ if (new_cur > pr->head + pr->total)
+ return -EINVAL;
+
+ pr->cur = new_cur;
+ return 0;
+}
+
+/**
+ * ac_pr_align_move - update pack reader cur pointer after reading n_move bytes
+ * Leave cur aligned to 4 bytes.
+ * (e.g. when n_move is 1, increase cur by 4)
+ *
+ * @pr: pack reader
+ * @n_move: number of bytes to move cur pointer ahead
+ * will be rounded up to keep cur 4 bytes aligned
+ *
+ * Return: 0 on success
+ * -EINVAL on invalid parameters
+ */
+static int ac_pr_align_move(struct ac_pr_state *pr, size_t n_move)
+{
+ const char *new_cur = pr->cur + n_move;
+ size_t len_from_head = new_cur - pr->head;
+ size_t offset;
+
+ if ((size_t)pr->cur > SIZE_MAX - n_move || new_cur < pr->head)
+ return -EINVAL;
+
+ offset = ((4 - (len_from_head & 3)) & 3);
+ if ((size_t)new_cur > SIZE_MAX - offset)
+ return -EINVAL;
+
+ new_cur = new_cur + offset;
+ if (new_cur > pr->head + pr->total)
+ return -EINVAL;
+
+ pr->cur = new_cur;
+ return 0;
+}
+
+/**
+ * ac_pr_move - update pack reader cur pointer after reading n_move bytes
+ *
+ * @pr: pack reader
+ * @n_move: number of bytes to move cur pointer ahead
+ *
+ * Return: 0 on success
+ * -EINVAL on invalid parameters
+ */
+static int ac_pr_move(struct ac_pr_state *pr, size_t n_move)
+{
+ const char *new_cur = pr->cur + n_move;
+
+ /* integer overflow or out of acp pkg size */
+ if ((size_t)pr->cur > SIZE_MAX - n_move ||
+ new_cur > pr->head + pr->total)
+ return -EINVAL;
+
+ pr->cur = new_cur;
+
+ return 0;
+}
+
+/**
+ * ac_pr_is_safe_to_read - check whether it is safe to read more n_move
+ * bytes from the acp file
+ *
+ * @pr: pack reader
+ * @n_move: number of bytes to check if it is safe to read
+ *
+ * Return: true when it is safe to read more n_move bytes
+ * false otherwise
+ */
+static bool ac_pr_is_safe_to_read(const struct ac_pr_state *pr, size_t n_move)
+{
+ /* pointer overflow */
+ if ((size_t)pr->cur > SIZE_MAX - n_move)
+ return false;
+
+ if (pr->cur + n_move > pr->head + pr->total)
+ return false;
+
+ return true;
+}
+
+/**
+ * ac_pr_is_end - check if cur is at the end of the acp file
+ *
+ * @pr: pack reader
+ *
+ * Return: true when cur is at the end of the acp
+ * false otherwise
+ */
+static bool ac_pr_is_end(const struct ac_pr_state *pr)
+{
+ return (pr->cur == pr->head + pr->total);
+}
+
+/**
+ * acp_load_reasons - load list of event codes that can be
+ * received or posted by ta
+ *
+ * @pr: pack reader
+ * @reasons: out param to hold the list of event codes
+ *
+ * Return: 0 on success
+ * -EINVAL on invalid parameters
+ */
+static int acp_load_reasons(struct ac_pr_state *pr,
+ struct ac_ins_reasons **reasons)
+{
+ size_t len;
+ struct ac_ins_reasons *r;
+
+ if (!ac_pr_is_safe_to_read(pr, sizeof(*r)))
+ return -EINVAL;
+
+ r = (struct ac_ins_reasons *)pr->cur;
+
+ if (r->len > AC_MAX_INS_REASONS_LENGTH)
+ return -EINVAL;
+
+ len = sizeof(*r) + r->len * sizeof(r->data[0]);
+ if (!ac_pr_is_safe_to_read(pr, len))
+ return -EINVAL;
+
+ *reasons = r;
+ return ac_pr_align_move(pr, len);
+}
+
+/**
+ * acp_load_taid_list - load list of ta ids which ta is allowed
+ * to communicate with
+ *
+ * @pr: pack reader
+ * @taid_list: out param to hold the loaded ta ids
+ *
+ * Return: 0 on success
+ * -EINVAL on invalid parameters
+ */
+static int acp_load_taid_list(struct ac_pr_state *pr,
+ struct ac_ta_id_list **taid_list)
+{
+ size_t len;
+ struct ac_ta_id_list *t;
+
+ if (!ac_pr_is_safe_to_read(pr, sizeof(*t)))
+ return -EINVAL;
+
+ t = (struct ac_ta_id_list *)pr->cur;
+ if (t->num > AC_MAX_USED_SERVICES)
+ return -EINVAL;
+
+ len = sizeof(*t) + t->num * sizeof(t->list[0]);
+
+ if (!ac_pr_is_safe_to_read(pr, len))
+ return -EINVAL;
+
+ *taid_list = t;
+ return ac_pr_align_move(pr, len);
+}
+
+/**
+ * acp_load_prop - load property from acp
+ *
+ * @pr: pack reader
+ * @prop: out param to hold the loaded property
+ *
+ * Return: 0 on success
+ * -EINVAL on invalid parameters
+ */
+static int acp_load_prop(struct ac_pr_state *pr, struct ac_prop_list **prop)
+{
+ size_t len;
+ struct ac_prop_list *p;
+
+ if (!ac_pr_is_safe_to_read(pr, sizeof(*p)))
+ return -EINVAL;
+
+ p = (struct ac_prop_list *)pr->cur;
+ if (p->len > AC_MAX_PROPS_LENGTH)
+ return -EINVAL;
+
+ len = sizeof(*p) + p->len * sizeof(p->data[0]);
+
+ if (!ac_pr_is_safe_to_read(pr, len))
+ return -EINVAL;
+
+ *prop = p;
+ return ac_pr_align_move(pr, len);
+}
+
+/**
+ * acp_load_ta_pack - load ta pack from acp
+ *
+ * @pr: pack reader
+ * @ta_pack: out param to hold the ta pack
+ *
+ * Return: 0 on success
+ * -EINVAL on invalid parameters
+ */
+static int acp_load_ta_pack(struct ac_pr_state *pr, char **ta_pack)
+{
+ size_t len;
+ char *t;
+
+ /*8 byte align to obey jeff rule*/
+ if (ac_pr_8b_align_move(pr, 0))
+ return -EINVAL;
+
+ t = (char *)pr->cur;
+
+ /*
+ *assume ta pack is the last item of one package,
+ *move cursor to the end directly
+ */
+ if (pr->cur > pr->head + pr->total)
+ return -EINVAL;
+
+ len = pr->head + pr->total - pr->cur;
+ if (!ac_pr_is_safe_to_read(pr, len))
+ return -EINVAL;
+
+ *ta_pack = t;
+ return ac_pr_move(pr, len);
+}
+
+/**
+ * acp_load_ins_jta_prop_head - load ta manifest header
+ *
+ * @pr: pack reader
+ * @head: out param to hold manifest header
+ *
+ * Return: 0 on success
+ * -EINVAL on invalid parameters
+ */
+static int acp_load_ins_jta_prop_head(struct ac_pr_state *pr,
+ struct ac_ins_jta_prop_header **head)
+{
+ if (!ac_pr_is_safe_to_read(pr, sizeof(**head)))
+ return -EINVAL;
+
+ *head = (struct ac_ins_jta_prop_header *)pr->cur;
+ return ac_pr_align_move(pr, sizeof(**head));
+}
+
+/**
+ * acp_load_ins_jta_prop - load ta properties information (ta manifest)
+ *
+ * @pr: pack reader
+ * @pack: out param to hold ta manifest
+ *
+ * Return: 0 on success
+ * -EINVAL on invalid parameters
+ */
+static int acp_load_ins_jta_prop(struct ac_pr_state *pr,
+ struct ac_ins_jta_prop *pack)
+{
+ int ret;
+
+ ret = acp_load_ins_jta_prop_head(pr, &pack->head);
+ if (ret)
+ return ret;
+
+ ret = acp_load_reasons(pr, &pack->post_reasons);
+ if (ret)
+ return ret;
+
+ ret = acp_load_reasons(pr, &pack->reg_reasons);
+ if (ret)
+ return ret;
+
+ ret = acp_load_prop(pr, &pack->prop);
+ if (ret)
+ return ret;
+
+ ret = acp_load_taid_list(pr, &pack->used_service_list);
+
+ return ret;
+}
+
+/**
+ * acp_load_ins_jta_head - load ta installation header
+ *
+ * @pr: pack reader
+ * @head: out param to hold the installation header
+ *
+ * Return: 0 on success
+ * -EINVAL on invalid parameters
+ */
+static int acp_load_ins_jta_head(struct ac_pr_state *pr,
+ struct ac_ins_ta_header **head)
+{
+ if (!ac_pr_is_safe_to_read(pr, sizeof(**head)))
+ return -EINVAL;
+
+ *head = (struct ac_ins_ta_header *)pr->cur;
+ return ac_pr_align_move(pr, sizeof(**head));
+}
+
+/**
+ * acp_load_ins_jta - load ta installation information from acp
+ *
+ * @pr: pack reader
+ * @pack: out param to hold install information
+ *
+ * Return: 0 on success
+ * -EINVAL on invalid parameters
+ */
+static int acp_load_ins_jta(struct ac_pr_state *pr,
+ struct ac_ins_jta_pack *pack)
+{
+ int ret;
+
+ ret = acp_load_prop(pr, &pack->ins_cond);
+ if (ret)
+ return ret;
+
+ ret = acp_load_ins_jta_head(pr, &pack->head);
+
+ return ret;
+}
+
+/**
+ * acp_load_pack_head - load acp pack header
+ *
+ * @pr: pack reader
+ * @head: out param to hold the acp header
+ *
+ * Return: 0 on success
+ * -EINVAL on invalid parameters
+ */
+static int acp_load_pack_head(struct ac_pr_state *pr,
+ struct ac_pack_header **head)
+{
+ if (!ac_pr_is_safe_to_read(pr, sizeof(**head)))
+ return -EINVAL;
+
+ *head = (struct ac_pack_header *)pr->cur;
+ return ac_pr_align_move(pr, sizeof(**head));
+}
+
+/**
+ * acp_load_pack - load and parse pack from acp file
+ *
+ * @raw_pack: acp file content, without the acp CSS header
+ * @size: acp file size (without CSS header)
+ * @cmd_id: command id
+ * @pack: out param to hold the loaded pack
+ *
+ * Return: 0 on success
+ * -EINVAL on invalid parameters
+ */
+static int acp_load_pack(const char *raw_pack, unsigned int size,
+ unsigned int cmd_id, struct ac_pack *pack)
+{
+ int ret;
+ struct ac_pr_state pr;
+ struct ac_ins_jta_pack_ext *pack_ext;
+ struct ac_ins_jta_prop_ext *prop_ext;
+
+ ret = ac_pr_init(&pr, raw_pack, size);
+ if (ret)
+ return ret;
+
+ if (cmd_id != AC_INSTALL_JTA_PROP) {
+ ret = acp_load_pack_head(&pr, &pack->head);
+ if (ret)
+ return ret;
+ }
+
+ if (cmd_id != AC_INSTALL_JTA_PROP && cmd_id != pack->head->cmd_id)
+ return -EINVAL;
+
+ switch (cmd_id) {
+ case AC_INSTALL_JTA:
+ pack_ext = (struct ac_ins_jta_pack_ext *)pack;
+ ret = acp_load_ins_jta(&pr, &pack_ext->cmd_pack);
+ if (ret)
+ break;
+ ret = acp_load_ta_pack(&pr, &pack_ext->ta_pack);
+ break;
+ case AC_INSTALL_JTA_PROP:
+ prop_ext = (struct ac_ins_jta_prop_ext *)pack;
+ ret = acp_load_ins_jta_prop(&pr, &prop_ext->cmd_pack);
+ if (ret)
+ break;
+ /* Note: the next section is JEFF file,
+ * and not ta_pack(JTA_properties+JEFF file),
+ * but we could reuse the ACP_load_ta_pack() here.
+ */
+ ret = acp_load_ta_pack(&pr, &prop_ext->jeff_pack);
+ break;
+ default:
+ return -EINVAL;
+ }
+
+ if (!ac_pr_is_end(&pr))
+ return -EINVAL;
+
+ return ret;
+}
+
+/**
+ * acp_pload_ins_jta - load and parse ta pack from acp file
+ *
+ * Exported function in acp parser API
+ *
+ * @raw_data: acp file content
+ * @size: acp file size
+ * @pack: out param to hold the ta pack
+ *
+ * Return: 0 on success
+ * -EINVAL on invalid parameters
+ */
+int acp_pload_ins_jta(const void *raw_data, unsigned int size,
+ struct ac_ins_jta_pack_ext *pack)
+{
+ int ret;
+
+ if (!raw_data || size <= AC_CSS_HEADER_LENGTH || !pack)
+ return -EINVAL;
+
+ ret = acp_load_pack((const char *)raw_data + AC_CSS_HEADER_LENGTH,
+ size - AC_CSS_HEADER_LENGTH,
+ AC_INSTALL_JTA, (struct ac_pack *)pack);
+
+ return ret;
+}
diff --git a/drivers/misc/mei/dal/acp_parser.h b/drivers/misc/mei/dal/acp_parser.h
new file mode 100644
index 000000000000..1de625de54f2
--- /dev/null
+++ b/drivers/misc/mei/dal/acp_parser.h
@@ -0,0 +1,38 @@
+/* SPDX-License-Identifier: BSD-3-Clause OR GPL-2.0 */
+/*
+ * Copyright(c) 2016 - 2018 Intel Corporation. All rights reserved.
+ */
+#ifndef _ACP_PARSER_H
+#define _ACP_PARSER_H
+
+#include "acp_format.h"
+
+/**
+ * struct ac_ins_jta_pack_ext - parsed ta pack from acp file
+ *
+ * @head: acp pack header
+ * @cmd_pack: ta installation information pack
+ * @ta_pack: raw ta pack
+ */
+struct ac_ins_jta_pack_ext {
+ struct ac_pack_header *head;
+ struct ac_ins_jta_pack cmd_pack;
+ char *ta_pack;
+} __packed;
+
+/**
+ * struct ac_ins_jta_prop_ext - parsed ta properties information
+ * from acp file
+ *
+ * @cmd_pack: ta installation properties pack
+ * @jeff_pack: ta jeff pack
+ */
+struct ac_ins_jta_prop_ext {
+ struct ac_ins_jta_prop cmd_pack;
+ char *jeff_pack;
+} __packed;
+
+int acp_pload_ins_jta(const void *raw_data, unsigned int size,
+ struct ac_ins_jta_pack_ext *pack);
+
+#endif /* _ACP_PARSER_H */
--
https://clearlinux.org