1#!/usr/bin/env python
2# -*- coding: utf-8 -*-
3
4# Copyright (c) 2020-2021 Huawei Device Co., Ltd.
5#
6# HDF is dual licensed: you can use it either under the terms of
7# the GPL, or the BSD license, at your option.
8# See the LICENSE file in the root of this repository for complete details.
9
10
11import json
12import os
13import hashlib
14import platform
15import configparser
16import re
17from ast import literal_eval
18
19from hdf_tool_exception import HdfToolException
20from hdf_tool_settings import HdfToolSettings
21from command_line.hdf_command_error_code import CommandErrorCode
22
23
24class WordsConverter(object):
25    def __init__(self, words_str):
26        self.words_str = words_str
27        if len(self.words_str) == 0:
28            raise HdfToolException('empty words')
29        self.words_list = self.split()
30        self.upper = '_'.join([w.upper() for w in self.words_list])
31        self.lower = '_'.join([w.lower() for w in self.words_list])
32        self.upper_camel = ''.join([w.capitalize() for w in self.words_list])
33        if len(self.upper_camel) == 1:
34            self.lower_camel = self.upper_camel[0].lower()
35        else:
36            self.lower_camel = '%s%s' % (self.upper_camel[0].lower(),
37                                         self.upper_camel[1:])
38
39    def _capital_pos_generator(self):
40        count = len(self.words_str)
41        for i in range(count):
42            if self.words_str[i].isupper():
43                yield i
44        yield count
45
46    def split(self):
47        words_list = []
48        capital_split_words = []
49        start = 0
50        for i in self._capital_pos_generator():
51            end = i
52            if end != start:
53                capital_split_words.append(self.words_str[start:end])
54                start = end
55        for word in capital_split_words:
56            words_list.extend([w for w in word.split('_') if w])
57        return words_list
58
59    def upper_case(self):
60        return self.upper
61
62    def lower_case(self):
63        return self.lower
64
65    def upper_camel_case(self):
66        return self.upper_camel
67
68    def lower_camel_case(self):
69        return self.lower_camel
70
71
72class SectionRange(object):
73    def __init__(self, start_pos, end_pos):
74        self.start_pos = start_pos
75        self.end_pos = end_pos
76
77
78class SectionContent(object):
79    def __init__(self, begin_flag, content, end_flag):
80        self.begin_flag = begin_flag
81        self.content = content
82        self.end_flag = end_flag
83
84    def to_str(self):
85        return '%s%s%s' % (self.begin_flag, self.content, self.end_flag)
86
87
88def find_section(file_content, section_content):
89    if not file_content or not section_content:
90        return False
91    start_pos = file_content.find(section_content.begin_flag)
92    if start_pos == -1:
93        return False
94    end_pos = file_content.find(section_content.end_flag)
95    if end_pos == -1:
96        return False
97    return SectionRange(start_pos, end_pos + len(section_content.end_flag) - 1)
98
99
100def _write_one_section(file_obj, section_content):
101    if not file_obj or not section_content:
102        return
103    file_obj.write(section_content.begin_flag)
104    file_obj.write(section_content.content)
105    file_obj.write(section_content.end_flag)
106
107
108def add_before_and_save(file_content, file_path, pos_range, new_section):
109    if not file_content or not file_path or not pos_range or not new_section:
110        return
111    config_info = HdfToolSettings().get_file_config_info()
112    write_fd = os.open(file_path, config_info["flags"], config_info["modes"])
113    with os.fdopen(write_fd, "w", newline='\n') as file_write:
114        file_write.write(file_content[:pos_range.start_pos])
115        _write_one_section(file_write, new_section)
116        file_write.write(file_content[pos_range.start_pos:])
117
118
119def add_after_and_save(file_content, file_path, pos_range, new_section):
120    if not file_content or not file_path or not pos_range or not new_section:
121        return
122    with open(file_path, 'w', newline='\n') as file_write:
123        file_write.write(file_content[:pos_range.end_pos + 1])
124        _write_one_section(file_write, new_section)
125        if len(file_content) > pos_range.end_pos + 1:
126            file_write.write(file_content[pos_range.end_pos + 1:])
127
128
129def append_and_save(file_content, file_path, new_section):
130    if not file_content or not file_path or not new_section:
131        return
132    with open(file_path, 'w', newline='\n') as file_write:
133        file_write.write(file_content)
134        _write_one_section(file_write, new_section)
135
136
137def delete_and_save(file_content, file_path, delete_range):
138    if not file_content or not file_path or not delete_range:
139        return
140    length = len(file_content)
141    with open(file_path, 'w', newline='\n') as file_write:
142        file_write.write(file_content[:delete_range.start_pos])
143        if delete_range.end_pos + 1 < length:
144            file_write.write(file_content[delete_range.end_pos + 1:])
145
146
147def replace_and_save(file_content, file_path, old_range, new_section):
148    if not file_content or not file_path or not old_range or not new_section:
149        return
150    with open(file_path, 'w', newline='\n') as file_write:
151        file_write.write(file_content[:old_range.start_pos])
152        _write_one_section(file_write, new_section)
153        file_write.write(file_content[old_range.end_pos + 1:])
154
155
156def get_id(part2):
157    full_name = part2
158    return hashlib.sha256(full_name.encode('utf8')).hexdigest()[:32]
159
160
161def create_dirs(dir_path):
162    if dir_path and not os.path.exists(dir_path):
163        try:
164            os.makedirs(dir_path)
165        except Exception:
166            raise HdfToolException('create dirs fail: %s' % dir_path)
167
168
169def read_file(file_path):
170    with open(file_path, encoding="utf-8") as file_read:
171        content = file_read.read()
172    return content
173
174
175def read_file_lines(file_path, code_type="utf-8"):
176    with open(file_path, encoding=code_type) as file_read:
177        lines = file_read.readlines()
178    return lines
179
180
181def read_file_binary(file_path):
182    with open(file_path, "rb") as file_binary_read:
183        temp_file_lines = file_binary_read.readlines()
184    file_lines = []
185    for line in temp_file_lines:
186        if line.startswith(b"#") or not (line.strip()):
187            continue
188        else:
189            file_lines.append(line.decode("utf-8"))
190    return file_lines
191
192
193def write_file(file_path, content):
194    with open(file_path, 'w+', newline='\n') as file_write:
195        file_write.write(content)
196
197
198def write_file_lines(file_path, content, code_type="utf-8"):
199    config_info = HdfToolSettings().get_file_config_info()
200    write_fd = os.open(file_path, config_info["flags"], config_info["modes"])
201    with os.fdopen(write_fd, "w", encoding=code_type) as file_write:
202        file_write.writelines(content)
203
204
205def get_framework_lite_dir(root):
206    return os.path.join(root, 'drivers', 'adapter', 'khdf', 'liteos')
207
208
209def get_vendor_root_dir(root):
210    return os.path.join(root, 'vendor')
211
212
213def get_vendor_dir(root, vendor):
214    return os.path.join(get_vendor_root_dir(root), vendor)
215
216
217def get_vendor_hdf_dir_framework(root):
218    relative_path = HdfToolSettings().get_drivers_path_framework()
219    return os.path.join(root, relative_path)
220
221
222def module_save_file_info(root):
223    adapter_framework = get_vendor_hdf_dir_framework(root=root)
224    if not os.path.exists(adapter_framework):
225        raise HdfToolException(
226            ' adapter model path  "%s" not exist' %
227            adapter_framework, CommandErrorCode.TARGET_NOT_EXIST)
228    save_file_path = HdfToolSettings().get_module_save_path()
229    create_file_save_path = os.path.join(adapter_framework, save_file_path)
230    if not os.path.exists(create_file_save_path):
231        raise HdfToolException(
232            'create file config "%s" not exist' %
233            create_file_save_path, CommandErrorCode.TARGET_NOT_EXIST)
234    return create_file_save_path
235
236
237def get_vendor_hdf_dir_peripheral(root):
238    relative_path = HdfToolSettings().get_drivers_path_peripheral()
239    return os.path.join(root, relative_path)
240
241
242def get_vendor_hdf_dir_adapter(root, kernel='liteos'):
243    relative_path = HdfToolSettings().get_drivers_path_adapter()
244    return os.path.join(root, relative_path, kernel)
245
246
247def get_vendor_lite_mk_path(root):
248    return os.path.join(get_vendor_hdf_dir_adapter(root), 'hdf_lite.mk')
249
250
251def get_vendor_makefile_path(root, kernel):
252    return os.path.join(get_vendor_hdf_dir_adapter(root, kernel), 'Makefile')
253
254
255def get_dot_configs_path(root, vendor, board):
256    path = os.path.join(root, "vendor", vendor, board, 'kernel_configs')
257    return [os.path.join(path, i) for i in os.listdir(path)]
258
259
260def get_module_dir(root, module=""):
261    return os.path.join(get_vendor_hdf_dir_framework(root), 'model', module)
262
263
264def get_drv_root_dir(root, module):
265    return os.path.join(get_module_dir(root, module), 'driver')
266
267
268def get_drv_dir(root, module, driver):
269    return os.path.join(get_drv_root_dir(root, module), driver)
270
271
272def get_drv_src_dir(root, module):
273    return get_drv_root_dir(root, module)
274
275
276def get_drv_src_dir_peripheral(root, module):
277    return get_vendor_hdf_dir_peripheral(root)
278
279
280def get_drv_include_dir(root, module, driver):
281    return os.path.join(get_drv_dir(root, module, driver), 'include')
282
283
284def get_vendor_kconfig_path(root, kernel):
285    hdf_dir = get_vendor_hdf_dir_adapter(root, kernel)
286    return os.path.join(hdf_dir, 'Kconfig')
287
288
289def get_module_kconfig_path(root, module):
290    return os.path.join(get_drv_root_dir(root, module), 'Kconfig')
291
292
293def get_module_mk_path(root, module):
294    return os.path.join(get_drv_root_dir(root, module), 'Makefile')
295
296
297def get_liteos_a_dot_config_path(root):
298    return os.path.join(root, 'kernel', 'liteos_a', '.config')
299
300
301def get_resources_dir():
302    cur_dir = os.path.realpath(os.path.dirname(__file__))
303    return os.path.join(cur_dir, 'resources')
304
305
306def get_templates_dir():
307    return os.path.join(get_resources_dir(), 'templates')
308
309
310def get_templates_lite_dir():
311    return os.path.join(get_templates_dir(), 'lite')
312
313
314def get_template(template_name, type_='lite'):
315    templates_dir = os.path.join(get_templates_dir(), type_)
316    template = os.path.join(templates_dir, template_name)
317    with open(template) as file_read:
318        template_str = file_read.read()
319    return template_str
320
321
322def get_hdf_lite_settings_mk_path(root_dir):
323    return os.path.join(get_framework_lite_dir(root_dir),
324                        'hdf_lite_settings.mk')
325
326
327def get_hdf_lite_mk_path(root_dir):
328    return os.path.join(get_framework_lite_dir(root_dir),
329                        'hdf_lite.mk')
330
331
332def get_hdf_lite_kconfig_path(root_dir):
333    return os.path.join(get_framework_lite_dir(root_dir),
334                        'Kconfig')
335
336
337def is_commented_line(line, comment_start):
338    if line.strip().startswith(comment_start):
339        return True
340    else:
341        return False
342
343
344def get_vendor_gn_path(root):
345    return os.path.join(get_vendor_hdf_dir_adapter(root), 'model', 'BUILD.gn')
346
347
348def get_template_file_path(root):
349    template_relative_path = HdfToolSettings().get_template_path()
350    relative_path2 = HdfToolSettings().get_drivers_path_framework()
351    return os.path.join(root, relative_path2, template_relative_path)
352
353
354def get_hcs_file_path(root, vendor, board):
355    l2_board_list = list(filter(
356        lambda x: x[0].isupper(),
357        HdfToolSettings().get_board_list()))
358    if board in l2_board_list:
359        return os.path.join(root, "vendor", vendor, board,
360                            "hdf_config", "khdf", "device_info",
361                            "device_info.hcs")
362    else:
363        return os.path.join(root, "vendor", vendor, board,
364                            "hdf_config", "device_info", "device_info.hcs")
365
366
367def template_filename_filtrate(dir_path, kernal):
368    filename_list = []
369    for filename in os.listdir(dir_path):
370        if filename.split("_")[0] == kernal.capitalize():
371            filename_list.append(filename)
372    return filename_list
373
374
375def type_judge(file_path, root, model_file_path, k_filename, path_dict):
376    if isinstance(file_path, list):
377        for file_name in file_path:
378            if not os.path.exists(os.path.join(root, file_name)):
379                model_file_path[k_filename] = " "
380            else:
381                model_file_path[k_filename] = path_dict[k_filename]
382    else:
383        if not os.path.exists(os.path.join(root, file_path)):
384            model_file_path[k_filename] = " "
385        else:
386            model_file_path[k_filename] = path_dict[k_filename]
387
388
389def model_info(path_dict, root, model_file_path, key):
390    if isinstance(path_dict, dict):
391        for k_filename, file_path in path_dict.items():
392            type_judge(file_path, root, model_file_path, k_filename, path_dict)
393    else:
394        hcs_file_path = os.path.join(root, path_dict)
395        if not os.path.exists(hcs_file_path):
396            model_file_path[key] = " "
397        else:
398            model_file_path[key] = path_dict
399    return model_file_path
400
401
402def get_create_model_info(root, create_data):
403    data = json.loads(create_data)
404    out_model_list = []
405    if not data:
406        return []
407    file_key_list = list(list(data.items())[0][-1].keys())[:-1]
408    for k, _ in data.items():
409        model_file_path = {}
410        for key in file_key_list:
411            if key.split("_")[-1] == "path":
412                path_dict = data[k][key]
413                model_file_path = model_info(
414                    path_dict, root, model_file_path, key)
415        out_model_list.append({k: model_file_path})
416    return out_model_list
417
418
419def get_config_config_path(root, kernel):
420    return os.path.join(root, "kernel", kernel, "config", "linux-5.10")
421
422
423def judge_file_path_exists(temp_path):
424    if not os.path.exists(temp_path):
425        raise HdfToolException(
426            'path  "%s" not exist' % temp_path,
427            CommandErrorCode.TARGET_NOT_EXIST)
428
429
430def write_config(root_path, config_file_json, config_name):
431    if platform.system() == "Windows":
432        config_file_replace = json.dumps(config_file_json, indent=4). \
433            replace("{}\\\\".format(root_path.replace('\\', '\\\\')), "")
434        write_file(os.path.join('resources', config_name),
435                   config_file_replace.replace('\\\\', '/'))
436    if platform.system() == "Linux":
437        config_file_replace = json.dumps(config_file_json, indent=4). \
438            replace(root_path + '/', "")
439        write_file(os.path.join('resources', config_name),
440                   config_file_replace)
441
442
443def ini_file_read_operation(section_name, node_name, path=""):
444    if path:
445        ini_config_path = path
446    else:
447        ini_config_path = os.path.join("resources", "config.ini")
448    config = configparser.ConfigParser()
449    config.read(ini_config_path)
450    if node_name:
451        model_child_dir_list = config.get(section=section_name, option=node_name)
452        return literal_eval(model_child_dir_list), config
453    else:
454        model_child_dir_list = config.items(section_name)
455        return model_child_dir_list, config
456
457
458def ini_file_write_operation(model, operation_object, model_child_dir_list):
459    json_format_list = json.dumps(model_child_dir_list)
460    operation_object.set(model, "file_dir", json_format_list)
461    ini_file_path = os.path.join("resources", "config.ini")
462    config_info = HdfToolSettings().get_file_config_info()
463    write_fd = os.open(ini_file_path, config_info["flags"], config_info["modes"])
464    with os.fdopen(write_fd, "w") as write_ini_file:
465        operation_object.write(write_ini_file)
466
467
468def judge_enable_line(enable_line, device_base):
469    if isinstance(enable_line, bytes):
470        if enable_line.find((device_base + " ").encode("utf-8")) == -1:
471            return enable_line
472    else:
473        if enable_line.find(device_base + " ") == -1:
474
475            return enable_line
476
477
478class GnMkFileParse(object):
479    def __init__(self, file_path, temp_re):
480        self.file = file_path
481        self.file_info = self._file_read()
482        self.import_list = []
483        self.module_switch = ""
484        self.module_name = ""
485        self.driver_dict = {}
486        self.driver_name = ""
487        self._start_index = ""
488        self._end_index = ""
489        self.driver_re = temp_re
490
491    def _file_read(self):
492        return read_file_binary(file_path=self.file)
493
494    def split_driver_start_to_end(self, flag_str):
495        count = 0
496        for index, line in enumerate(self.file_info):
497            re_result = re.search(self.driver_re, line.strip())
498            if re_result and count == 0:
499                count += 1
500                self._start_index = index
501                self.driver_name = re_result.group("name")
502                continue
503            if line.strip() == flag_str and count > 0:
504                self._end_index = index
505                count -= 1
506                if count == 0:
507                    self.driver_dict[self.driver_name] = \
508                        [self._start_index, self._end_index]
509        return self.driver_dict
510
511    def get_driver_config_str(self, driver_index):
512        return "".join(self.file_info[driver_index[0]: driver_index[-1] + 1])
513
514
515class MakefileAndKconfigFileParse(object):
516    def __init__(self, file_path, flag_str, re_name):
517        self.file = file_path
518        self.file_info = self._file_read()
519        self.driver_re_name = re_name
520        self.driver_re_flg = flag_str
521        self.driver_dict = {}
522
523    def _file_read(self):
524        return read_file_binary(file_path=self.file)
525
526    def split_driver_start_to_end(self):
527        res_list = re.split(self.driver_re_flg, "".join(self.file_info))
528        for res in res_list:
529            re_name = re.search(self.driver_re_name, res)
530            if res and re_name:
531                res_splicing = "".join([self.driver_re_flg, res])
532                self.driver_dict[re_name.group("name")] = res_splicing
533        return self.driver_dict
534
535    def split_target_block(self, flag_re):
536        res_list = re.split(flag_re, "".join(self.file_info))
537        flag_split_list = []
538        for res in res_list:
539            if res.startswith("-"):
540                flag_split_list.append(res)
541        return flag_split_list
542
543
544def list_dict_tool(couple_list):
545    temp_dict = {}
546    for info in couple_list:
547        temp_dict[info[0]] = info[-1]
548    return temp_dict
549