498 lines
12 KiB
C
Executable file
498 lines
12 KiB
C
Executable file
// SPDX-License-Identifier: GPL-2.0
|
|
/*
|
|
* Samsung Exynos SoC series dsp driver
|
|
*
|
|
* Copyright (c) 2019 Samsung Electronics Co., Ltd.
|
|
* http://www.samsung.com/
|
|
*/
|
|
|
|
#include "dl/dsp-xml-parser.h"
|
|
#include "dl/dsp-sxml.h"
|
|
#include "dl/dsp-common.h"
|
|
#include "dl/dsp-string-tree.h"
|
|
|
|
#define COUNT(arr) (sizeof(arr) / sizeof((arr)[0]))
|
|
#define TOKEN_END (-255)
|
|
#define TOKEN_LIST_NUM (64)
|
|
#define TOKEN_MAX (64)
|
|
#define KERNEL_CNT_MAX (256)
|
|
|
|
static struct dsp_string_tree_node *xml_str;
|
|
struct dsp_xml_lib_table *xml_libs;
|
|
static char *token_value;
|
|
|
|
static const char *const xml_strs[] = {
|
|
"libs",
|
|
"count",
|
|
"lib",
|
|
"name",
|
|
"kernel_count",
|
|
"kernel",
|
|
"id",
|
|
"pre",
|
|
"exe",
|
|
"post"
|
|
};
|
|
|
|
static void __dsp_xml_lib_table_init(void)
|
|
{
|
|
xml_libs->lib_cnt = 0;
|
|
dsp_hash_tab_init(&xml_libs->lib_hash);
|
|
}
|
|
|
|
void dsp_xml_parser_init(void)
|
|
{
|
|
int idx;
|
|
|
|
xml_str = (struct dsp_string_tree_node *)dsp_dl_malloc(
|
|
sizeof(struct dsp_string_tree_node),
|
|
"XML String tree");
|
|
xml_libs = (struct dsp_xml_lib_table *)dsp_dl_malloc(
|
|
sizeof(struct dsp_xml_lib_table),
|
|
"XML lib table");
|
|
token_value = (char *)dsp_dl_malloc(TOKEN_MAX, "Token value");
|
|
|
|
__dsp_xml_lib_table_init();
|
|
|
|
dsp_string_tree_init(xml_str);
|
|
|
|
for (idx = 0; idx < TOKEN_NUM; idx++)
|
|
dsp_string_tree_push(xml_str, xml_strs[idx], idx);
|
|
|
|
}
|
|
|
|
static void __dsp_xml_lib_free(struct dsp_xml_lib *lib)
|
|
{
|
|
unsigned int idx;
|
|
|
|
DL_DEBUG("XML lib free\n");
|
|
dsp_dl_free(lib->name);
|
|
|
|
for (idx = 0; idx < lib->kernel_cnt; idx++) {
|
|
struct dsp_xml_kernel_table *kernel_table = &lib->kernels[idx];
|
|
|
|
if (kernel_table->pre) {
|
|
DL_DEBUG("free pre(%s)\n", kernel_table->pre);
|
|
dsp_dl_free(kernel_table->pre);
|
|
}
|
|
|
|
if (kernel_table->exe) {
|
|
DL_DEBUG("free exe(%s)\n", kernel_table->exe);
|
|
dsp_dl_free(kernel_table->exe);
|
|
}
|
|
|
|
if (kernel_table->post) {
|
|
DL_DEBUG("free post(%s)\n", kernel_table->post);
|
|
dsp_dl_free(kernel_table->post);
|
|
}
|
|
}
|
|
|
|
dsp_dl_free(lib->kernels);
|
|
}
|
|
|
|
static void __dsp_xml_lib_table_free(void)
|
|
{
|
|
int idx;
|
|
|
|
for (idx = 0; idx < DSP_HASH_MAX; idx++) {
|
|
struct dsp_list_node *cur, *next;
|
|
|
|
cur = (&xml_libs->lib_hash.list[idx])->next;
|
|
|
|
while (cur != NULL) {
|
|
struct dsp_hash_node *hash_node =
|
|
container_of(cur, struct dsp_hash_node, node);
|
|
struct dsp_xml_lib *lib =
|
|
(struct dsp_xml_lib *)hash_node->value;
|
|
|
|
next = cur->next;
|
|
__dsp_xml_lib_free(lib);
|
|
cur = next;
|
|
}
|
|
}
|
|
|
|
dsp_hash_free(&xml_libs->lib_hash, 1);
|
|
}
|
|
|
|
void dsp_xml_parser_free(void)
|
|
{
|
|
dsp_string_tree_free(xml_str);
|
|
__dsp_xml_lib_table_free();
|
|
dsp_dl_free(xml_str);
|
|
dsp_dl_free(xml_libs);
|
|
dsp_dl_free(token_value);
|
|
}
|
|
|
|
static int __get_next_token(unsigned short *type, char *buf,
|
|
unsigned int buf_len)
|
|
{
|
|
static int need_parse_token = 1;
|
|
static int token_remained = 1;
|
|
static int parse_end;
|
|
static unsigned int idx;
|
|
static unsigned int token_num;
|
|
static struct dsp_sxml parser;
|
|
static struct dsp_sxml_tok tokens[TOKEN_LIST_NUM];
|
|
struct dsp_sxml_tok token;
|
|
size_t token_value_size;
|
|
|
|
if (buf == NULL) {
|
|
need_parse_token = 1;
|
|
token_remained = 1;
|
|
parse_end = 0;
|
|
idx = 0;
|
|
token_num = 0;
|
|
dsp_sxml_init(&parser);
|
|
return 0;
|
|
}
|
|
|
|
if (idx == token_num) {
|
|
if (token_remained)
|
|
need_parse_token = 1;
|
|
else
|
|
parse_end = 1;
|
|
}
|
|
|
|
if (parse_end)
|
|
return TOKEN_END;
|
|
|
|
if (need_parse_token) {
|
|
enum dsp_sxml_err err = dsp_sxml_parse(&parser, buf, buf_len,
|
|
tokens, COUNT(tokens));
|
|
|
|
DL_DEBUG("Parse num : %u\n", parser.ntokens);
|
|
|
|
switch (err) {
|
|
case SXML_SUCCESS:
|
|
token_remained = 0;
|
|
need_parse_token = 0;
|
|
token_num = parser.ntokens;
|
|
idx = 0;
|
|
break;
|
|
case SXML_ERROR_TOKENSFULL:
|
|
token_remained = 1;
|
|
need_parse_token = 0;
|
|
token_num = parser.ntokens;
|
|
idx = 0;
|
|
|
|
parser.ntokens = 0;
|
|
break;
|
|
case SXML_ERROR_BUFFERDRY:
|
|
DL_ERROR("Larger than buf size\n");
|
|
return TOKEN_END;
|
|
case SXML_ERROR_XMLINVALID:
|
|
DL_ERROR("XML is invalid\n");
|
|
return TOKEN_END;
|
|
default:
|
|
DL_ERROR("Error code is invalid\n");
|
|
return TOKEN_END;
|
|
}
|
|
}
|
|
|
|
token = tokens[idx++];
|
|
token_value_size = token.endpos - token.startpos;
|
|
if (token_value_size >= TOKEN_MAX) {
|
|
DL_ERROR("Token_value_size is too big(%zd/%u)\n",
|
|
token_value_size, TOKEN_MAX);
|
|
return TOKEN_END;
|
|
}
|
|
|
|
memcpy(token_value, buf + token.startpos, token_value_size);
|
|
token_value[token_value_size] = '\0';
|
|
|
|
*type = token.type;
|
|
DL_DEBUG("Token value : %s, type : %d\n", token_value, *type);
|
|
|
|
return dsp_string_tree_get(xml_str, token_value);
|
|
}
|
|
|
|
static void __dsp_xml_kernel_table_init(struct dsp_xml_kernel_table *kt)
|
|
{
|
|
kt->pre = NULL;
|
|
kt->post = NULL;
|
|
kt->exe = NULL;
|
|
}
|
|
|
|
static int __create_kernel_table(struct dsp_xml_lib *lib, char *buf,
|
|
unsigned int buf_len)
|
|
{
|
|
unsigned short type;
|
|
int ret;
|
|
unsigned int idx = 0xFFFFFFFF;
|
|
struct dsp_xml_kernel_table kernel_table;
|
|
int skip_token = 0;
|
|
|
|
__dsp_xml_kernel_table_init(&kernel_table);
|
|
|
|
do {
|
|
if (!skip_token)
|
|
ret = __get_next_token(&type, buf, buf_len);
|
|
else
|
|
skip_token = 0;
|
|
|
|
if (ret == TOKEN_END) {
|
|
DL_ERROR("token end before create xml structure\n");
|
|
return -1;
|
|
} else if (ret == KERNEL && type == SXML_ENDTAG) {
|
|
if (!lib->kernels) {
|
|
DL_ERROR("no memory for kernel tables\n");
|
|
return -1;
|
|
}
|
|
|
|
if (idx == 0xFFFFFFFF) {
|
|
DL_ERROR("no kernel idx\n");
|
|
return -1;
|
|
} else if (idx >= lib->kernel_cnt) {
|
|
DL_ERROR("invalid kernel idx\n");
|
|
return -1;
|
|
}
|
|
lib->kernels[idx] = kernel_table;
|
|
return 0;
|
|
} else if (ret == ID && type == SXML_CDATA) {
|
|
ret = __get_next_token(&type, buf, buf_len);
|
|
if (ret == TOKEN_END) {
|
|
DL_ERROR("token end before create xml\n");
|
|
return -1;
|
|
} else if (type == SXML_CHARACTER) {
|
|
ret = kstrtouint(token_value, 10, &idx);
|
|
if (ret)
|
|
DL_ERROR("Failed to change str(%d)\n",
|
|
ret);
|
|
|
|
DL_DEBUG("kernel idx : %d\n", idx);
|
|
} else {
|
|
DL_ERROR("id token is not character\n");
|
|
return -1;
|
|
}
|
|
} else if (ret == PRE && type == SXML_CDATA) {
|
|
ret = __get_next_token(&type, buf, buf_len);
|
|
if (ret == TOKEN_END) {
|
|
DL_ERROR("token end before create xml\n");
|
|
return -1;
|
|
} else if (type == SXML_CHARACTER) {
|
|
kernel_table.pre =
|
|
(char *)dsp_dl_malloc(
|
|
strlen(token_value) + 1,
|
|
"kernel pre");
|
|
strcpy(kernel_table.pre, token_value);
|
|
DL_DEBUG("kernel pre : %s\n", kernel_table.pre);
|
|
} else {
|
|
DL_DEBUG("No pre kernel\n");
|
|
skip_token = 1;
|
|
}
|
|
} else if (ret == EXE && type == SXML_CDATA) {
|
|
ret = __get_next_token(&type, buf, buf_len);
|
|
if (ret == TOKEN_END) {
|
|
DL_ERROR("token end before create xml\n");
|
|
return -1;
|
|
} else if (type == SXML_CHARACTER) {
|
|
kernel_table.exe =
|
|
(char *)dsp_dl_malloc(
|
|
strlen(token_value) + 1,
|
|
"kernel exe");
|
|
strcpy(kernel_table.exe, token_value);
|
|
DL_DEBUG("kernel exe : %s\n", kernel_table.exe);
|
|
} else {
|
|
DL_ERROR("exe token is not character\n");
|
|
return -1;
|
|
}
|
|
} else if (ret == POST && type == SXML_CDATA) {
|
|
ret = __get_next_token(&type, buf, buf_len);
|
|
if (ret == TOKEN_END) {
|
|
DL_ERROR("token end before create xml\n");
|
|
return -1;
|
|
} else if (type == SXML_CHARACTER) {
|
|
kernel_table.post =
|
|
(char *)dsp_dl_malloc(
|
|
strlen(token_value) + 1,
|
|
"kernel post");
|
|
strcpy(kernel_table.post, token_value);
|
|
DL_DEBUG("kernel post : %s\n",
|
|
kernel_table.post);
|
|
} else {
|
|
DL_DEBUG("No post kernel\n");
|
|
skip_token = 1;
|
|
}
|
|
}
|
|
} while (1);
|
|
}
|
|
|
|
static int __create_lib(char *buf, unsigned int buf_len)
|
|
{
|
|
unsigned short type;
|
|
int ret;
|
|
struct dsp_xml_lib *lib =
|
|
(struct dsp_xml_lib *)dsp_dl_malloc(
|
|
sizeof(*lib), "XML library");
|
|
|
|
lib->kernels = NULL;
|
|
|
|
do {
|
|
ret = __get_next_token(&type, buf, buf_len);
|
|
if (ret == TOKEN_END) {
|
|
if (lib->kernels)
|
|
dsp_dl_free(lib->kernels);
|
|
|
|
dsp_dl_free(lib);
|
|
DL_ERROR("token end before create xml structure\n");
|
|
return -1;
|
|
} else if (ret == LIB && type == SXML_ENDTAG
|
|
&& lib->name != NULL) {
|
|
dsp_hash_push(&xml_libs->lib_hash, lib->name, lib);
|
|
return 0;
|
|
} else if (ret == NAME && type == SXML_CDATA) {
|
|
ret = __get_next_token(&type, buf, buf_len);
|
|
if (ret == TOKEN_END) {
|
|
if (lib->kernels)
|
|
dsp_dl_free(lib->kernels);
|
|
|
|
dsp_dl_free(lib);
|
|
DL_ERROR("token end before create xml\n");
|
|
return -1;
|
|
} else if (type == SXML_CHARACTER) {
|
|
|
|
//TODO: Roll back tmp lib path gen code
|
|
token_value[strlen(token_value) - 6] = '\0';
|
|
|
|
lib->name = (char *)dsp_dl_malloc(
|
|
strlen(token_value) + 1,
|
|
"lib name");
|
|
strcpy(lib->name, token_value);
|
|
DL_DEBUG("lib name : %s\n", lib->name);
|
|
} else {
|
|
if (lib->kernels)
|
|
dsp_dl_free(lib->kernels);
|
|
|
|
dsp_dl_free(lib);
|
|
DL_ERROR("name token is not character\n");
|
|
return -1;
|
|
}
|
|
} else if (ret == KERNEL_COUNT && type == SXML_CDATA) {
|
|
ret = __get_next_token(&type, buf, buf_len);
|
|
if (ret == TOKEN_END) {
|
|
if (lib->kernels)
|
|
dsp_dl_free(lib->kernels);
|
|
|
|
dsp_dl_free(lib);
|
|
DL_ERROR("token end before create xml\n");
|
|
return -1;
|
|
} else if (type == SXML_CHARACTER) {
|
|
ret = kstrtouint(token_value, 10,
|
|
&lib->kernel_cnt);
|
|
if (ret) {
|
|
DL_ERROR("Failed to change str(%d)\n",
|
|
ret);
|
|
dsp_dl_free(lib);
|
|
return -1;
|
|
}
|
|
|
|
if (!lib->kernel_cnt) {
|
|
DL_ERROR("invalid kernel cnt\n");
|
|
dsp_dl_free(lib);
|
|
return -1;
|
|
}
|
|
DL_DEBUG("lib kernel cnt : %u\n",
|
|
lib->kernel_cnt);
|
|
|
|
if (lib->kernel_cnt > KERNEL_CNT_MAX) {
|
|
DL_ERROR("kernel_cnt(%u) is over(%d)\n",
|
|
lib->kernel_cnt,
|
|
KERNEL_CNT_MAX);
|
|
dsp_dl_free(lib);
|
|
return -1;
|
|
}
|
|
|
|
lib->kernels = (struct dsp_xml_kernel_table *)
|
|
dsp_dl_malloc(
|
|
sizeof(*lib->kernels) *
|
|
lib->kernel_cnt,
|
|
"XML kernel table");
|
|
if (!lib->kernels) {
|
|
DL_ERROR("Failed to alloc XML kt\n");
|
|
dsp_dl_free(lib);
|
|
return -1;
|
|
}
|
|
} else {
|
|
if (lib->kernels)
|
|
dsp_dl_free(lib->kernels);
|
|
|
|
dsp_dl_free(lib);
|
|
DL_ERROR("kernel cnt token is not character\n");
|
|
return -1;
|
|
}
|
|
} else if (ret == KERNEL && type == SXML_STARTTAG) {
|
|
if (__create_kernel_table(lib, buf, buf_len) == -1) {
|
|
if (lib->kernels)
|
|
dsp_dl_free(lib->kernels);
|
|
|
|
dsp_dl_free(lib);
|
|
return -1;
|
|
}
|
|
}
|
|
} while (1);
|
|
}
|
|
|
|
static int __create_lib_table(char *buf, unsigned int buf_len)
|
|
{
|
|
unsigned short type;
|
|
int ret;
|
|
|
|
do {
|
|
ret = __get_next_token(&type, buf, buf_len);
|
|
if (ret == TOKEN_END) {
|
|
DL_ERROR("token end before create xml structure\n");
|
|
return -1;
|
|
} else if (ret == LIBS && type == SXML_ENDTAG)
|
|
return 0;
|
|
|
|
else if (ret == COUNT && type == SXML_CDATA) {
|
|
ret = __get_next_token(&type, buf, buf_len);
|
|
if (ret == TOKEN_END) {
|
|
DL_ERROR("token end before create xml\n");
|
|
return -1;
|
|
} else if (type == SXML_CHARACTER) {
|
|
ret = kstrtouint(token_value, 10,
|
|
&xml_libs->lib_cnt);
|
|
if (ret)
|
|
DL_ERROR("Failed to change str(%d)\n",
|
|
ret);
|
|
|
|
DL_DEBUG("libs count : %u\n",
|
|
xml_libs->lib_cnt);
|
|
} else {
|
|
DL_ERROR("count token is not character\n");
|
|
return -1;
|
|
}
|
|
} else if (ret == LIB && type == SXML_STARTTAG) {
|
|
if (__create_lib(buf, buf_len) == -1)
|
|
return -1;
|
|
}
|
|
} while (1);
|
|
}
|
|
|
|
static int __create_xml_structure(char *buf, unsigned int buf_len)
|
|
{
|
|
unsigned short type;
|
|
int ret;
|
|
|
|
ret = __get_next_token(NULL, NULL, 0);
|
|
if (ret != 0) {
|
|
DL_ERROR("Failed to init token\n");
|
|
return -1;
|
|
}
|
|
|
|
do {
|
|
ret = __get_next_token(&type, buf, buf_len);
|
|
if (ret == TOKEN_END) {
|
|
DL_ERROR("token end before create xml structure\n");
|
|
return -1;
|
|
} else if (ret == LIBS && type == SXML_STARTTAG)
|
|
return __create_lib_table(buf, buf_len);
|
|
} while (1);
|
|
}
|
|
|
|
int dsp_xml_parser_parse(struct dsp_dl_lib_file *file)
|
|
{
|
|
dsp_dl_lib_file_reset(file);
|
|
return __create_xml_structure((char *)file->mem, file->size);
|
|
}
|