Files
wzr 3b4bd59a17 TA compile adapt.
Signed-off-by: wzr <wangzhiru1@huawei.com>
2024-04-15 16:53:34 +08:00

339 lines
10 KiB
Python

#!/usr/bin/env python
# coding:utf-8
#
# Copyright (C) 2022 Huawei Technologies Co., Ltd.
# Licensed under the Mulan PSL v2.
# You can use this software according to the terms and conditions of the Mulan
# PSL v2.
# You may obtain a copy of Mulan PSL v2 at:
# http://license.coscl.org.cn/MulanPSL2
# THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY
# KIND, EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO
# NON-INFRINGEMENT, MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
# See the Mulan PSL v2 for more details.
#
import string
import os
import sys
import stat
import logging
from defusedxml import ElementTree as ET
from dyn_conf_checker import dyn_perm_check
from dyn_conf_checker import check_and_classify_attr
from dyn_conf_checker import check_csv_sym
from dyn_conf_checker import check_ta_config
from dyn_conf_checker import dyn_conf_clean
type_trans = {"TYPE_NONE": "-1",
"TYPE_CLASS": "0",
"TYPE_BOOL": "1",
"TYPE_INT": "2",
"TYPE_CHAR": "3"}
# the length len in tlv
DYN_CONF_LEN_LEN = 4
MAP_REGIONS_NUM = 0
tag_dict = {}
type_dict = {}
trans_dict = {}
def get_csv_size(path):
with open(path, "r", encoding="utf-8") as csvfile:
lines = csvfile.readlines()
return len(lines)
return 0
def get_csv_data(path, lnum, rnum):
with open(path, "r", encoding="utf-8") as csvfile:
count = 0
lines = csvfile.readlines()
for line in lines:
if count == lnum:
return str(line.split(",")[rnum]).strip()
count = count + 1
return ""
def classify_tag(tag):
while len(tag) < 3:
tag = "0%s" % (tag)
return tag
# save tag type and trans dict
def handle_tag_dict(path):
for i in range(0, get_csv_size(path)):
dyn_sym = get_csv_data(path, i, 0)
tag_dict[dyn_sym] = classify_tag(get_csv_data(path, i, 1))
type_dict[dyn_sym] = type_trans.get(get_csv_data(path, i, 2))
trans_dict[dyn_sym] = get_csv_data(path, i, 3)
def check_target_data_been_found(sym, find_out, path):
if find_out == 1:
raise RuntimeError(sym + " can only set one time in " + path)
# trans value sym by trans dict
def handle_trans(value, path):
datas = value.split("|")
for i, data in enumerate(datas):
find_out = 0
target_data = data
for j in range(0, get_csv_size(path)):
sym = get_csv_data(path, j, 0)
tag = get_csv_data(path, j, 1)
check_csv_sym(sym)
check_csv_sym(tag)
if sym == target_data:
# if one sym has been set more than one time in csv
check_target_data_been_found(sym, find_out, path)
datas[i] = tag
find_out = 1 # means we find sym in dict
if find_out == 0:
raise RuntimeError("cannot find {} in {}".format(datas[i], path))
ans = datas[0]
for i in range(1, len(datas)):
ans = "%s|%s" % (ans, datas[i])
return ans
def get_value_by_name_in_config(config_name, in_path):
config_file = os.path.join(in_path, config_name)
if not os.path.exists(config_file):
logging.error("configs.xml file doesn't exist")
return ""
xml_tree = ET.parse(config_file)
drv_perm = xml_tree.find('./TA_Basic_Info/service_name')
return drv_perm.text
def get_value_by_name_in_manifest(manifest_name, in_path):
manifest = os.path.join(in_path, "manifest.txt")
if not os.path.exists(manifest):
name = get_value_by_name_in_config("configs.xml", in_path)
if name != "":
return name
else:
with open(manifest, 'r') as mani_fp:
for each_line in mani_fp:
if each_line.startswith("#") or not each_line.strip():
continue
name = each_line.split(":")[0].strip()
if "{" + name + "}" == manifest_name:
return str(each_line.split(":")[1].strip())
raise RuntimeError("{" + manifest_name + "}" + \
"cannot find in " + manifest)
def get_value_trans(old_item, value, attrib, key, in_path):
# if name contains '.csv' means
# we can transform value by {manifest_name}.csv
# manifest_name must in manifest.txt
if ".csv" in trans_dict.get(key):
manifest_name = trans_dict.get(key).split(".csv")[0]
manifest_value = get_value_by_name_in_manifest(manifest_name, in_path)
trans_file_path = os.path.join(in_path, "{}.csv".format(manifest_value))
return handle_trans(value, trans_file_path)
# if name not contains '.csv' means
# we can transform value by {attrib[attri]}.csv
# attrib[attri] must in xml file
for attri in attrib:
if old_item + attri == trans_dict.get(key):
if len(attrib[attri]) == 0:
raise RuntimeError("you should set drv name while \
you set drv permission")
trans_file_path = os.path.join(in_path,
"{}.csv".format(attrib[attri]))
return handle_trans(value, trans_file_path)
raise RuntimeError("cannot find second trans file",\
key, trans_dict.get(key))
def item_zip(old_item, attr, value, attrib, in_path):
dyn_key = old_item + attr
dyn_type = type_dict.get(dyn_key)
origin_value = value
if dyn_type is None:
raise RuntimeError("tag " + dyn_key + " is not support!")
if len(trans_dict.get(dyn_key)) > 0:
value = get_value_trans(old_item, value, attrib, dyn_key, in_path)
# check the xml is invalid for dyn perm
dyn_perm_check(dyn_key, attrib, value, origin_value)
if dyn_type == type_trans.get("TYPE_BOOL"):
if value.lower() == "true":
return "1"
elif value.lower() == "false":
return "0"
else:
raise Exception("bool can only be true or false")
elif dyn_type == type_trans.get("TYPE_INT"):
if '0x' in value:
return str(int(value, base=16))
elif '0b' in value:
return str(int(value, base=2))
else:
return str(int(value, base=10))
elif dyn_type == type_trans.get("TYPE_CHAR"):
return value
else:
raise RuntimeError("unknown type")
def get_length(value):
length = len(value)
off = int((DYN_CONF_LEN_LEN / 2 - 1) * 8)
ans = ""
for _ in range(int(DYN_CONF_LEN_LEN / 2)):
tmp = ""
dyn_len = (length >> off) & 0xFF;
if dyn_len >= 0 and dyn_len <= 0xF:
tmp = "0"
tmp += str(hex(dyn_len)).split("x")[1]
ans += tmp
off -= 8
return ans
def check_map_regions(length):
if int(length, 16) > 1279:
logging.error("regions string is too long\n")
raise RuntimeError("regions has invalid length", int(length, 16))
def do_parser_dyn_conf(old_item, ele, in_path):
attrs = ""
if len(ele.attrib) > 0:
for attr in ele.attrib:
ele.attrib[attr] = check_and_classify_attr(old_item,\
attr, ele.attrib.get(attr))
tag = tag_dict.get(old_item + attr)
dyn_type = type_dict.get(old_item + attr)
if dyn_type == type_trans.get("TYPE_NONE"):
continue
value = item_zip(old_item, attr, ele.attrib[attr],
ele.attrib, in_path)
length = get_length(value)
attrs = attrs + tag + dyn_type + length + value
if tag == "037" and dyn_type == "3":
check_map_regions(length)
global MAP_REGIONS_NUM
MAP_REGIONS_NUM += 1
else:
for child in ele:
tmp_attrs = do_parser_dyn_conf(old_item + child.tag + "/",
child, in_path)
if tmp_attrs == "":
continue
attrs = attrs + tmp_attrs
# handle inner context
if check_ta_config(old_item, ele.text) is True and \
ele.text is not None and len(ele.text.strip()) > 0:
inner_text = item_zip(old_item + ele.tag, "", ele.text, {}, in_path)
attrs = attrs + tag_dict.get(old_item + ele.tag) + \
type_dict.get(old_item + ele.tag) + \
get_length(inner_text) + inner_text
if len(tag_dict.get(old_item)) == 0 or attrs == "":
return ""
return tag_dict.get(old_item) + type_dict.get(old_item) + \
get_length(attrs) + attrs
def parser_dyn_conf(dyn_conf_xml_file_path, manifest_ext_path,
tag_parse_dict_path, in_path):
if not os.path.exists(dyn_conf_xml_file_path):
logging.error("dyn perm xml file doesn't exist")
return
if not os.path.exists(tag_parse_dict_path):
logging.error("tag_parse_dict.csv file doesn't exist")
return
handle_tag_dict(tag_parse_dict_path)
tree = ET.parse(dyn_conf_xml_file_path)
root = tree.getroot()
ans = do_parser_dyn_conf(root.tag + "/", root, in_path)
dyn_conf_clean()
if MAP_REGIONS_NUM > 1:
raise RuntimeError("regions has invalid num", MAP_REGIONS_NUM)
if ans == "":
ans = "00000"
ans = "gpd.ta.dynConf:" + ans + "\n"
if not os.path.exists(manifest_ext_path):
out_tlv = os.path.join(in_path, "config_tlv")
with os.fdopen(os.open(out_tlv, \
os.O_RDWR | os.O_TRUNC | os.O_CREAT, \
stat.S_IWUSR | stat.S_IRUSR), 'w+') as conf:
conf.write(ans)
else:
#write items to mani_ext
manifest_ext_path_fd = os.open(manifest_ext_path, os.O_RDWR, 0o600)
with os.fdopen(manifest_ext_path_fd, 'a+') as mani_ext_fp:
mani_ext_fp.write(ans)
def parser_config_xml(config_xml_file_path, tag_parse_dict_path, \
out_path, in_path):
if not os.path.exists(config_xml_file_path):
logging.error("config xml file doesn't exist")
return
if not os.path.exists(tag_parse_dict_path):
logging.error("tag_parse_dict.csv file doesn't exist")
return
handle_tag_dict(tag_parse_dict_path)
tree = ET.parse(config_xml_file_path)
root = tree.getroot()
ans = do_parser_dyn_conf(root.tag + "/", root, in_path)
dyn_conf_clean()
if ans == "":
ans = "00000"
# write items to mani_ext
config_path_fd = os.open(out_path, os.O_CREAT | os.O_RDWR, 0o600)
with os.fdopen(config_path_fd, 'a+') as config_fp:
config_fp.write(ans)