786 lines
19 KiB
Diff
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 0000000..7fdef34
|
|
--- /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 0000000..462bd48
|
|
--- /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 0000000..1de625d
|
|
--- /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
|
|
|