kernel_samsung_a53x/drivers/vision3/dsp/dl/dsp-xml-parser.c
2024-06-15 16:02:09 -03:00

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);
}