1#!/usr/bin/env python
2# -*- coding: utf-8 -*-
3# Copyright (c) 2021 Huawei Device Co., Ltd.
4# Licensed under the Apache License, Version 2.0 (the "License");
5# you may not use this file except in compliance with the License.
6# You may obtain a copy of the License at
7#
8#     http://www.apache.org/licenses/LICENSE-2.0
9#
10# Unless required by applicable law or agreed to in writing, software
11# distributed under the License is distributed on an "AS IS" BASIS,
12# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13# See the License for the specific language governing permissions and
14# limitations under the License.
15
16import sys
17import os
18import shutil
19import argparse
20import json
21from mkimage import mkimages
22
23sys.path.append(
24    os.path.dirname(os.path.dirname(os.path.dirname(
25        os.path.abspath(__file__)))))
26from scripts.util import build_utils
27from build_scripts.build import find_top  # noqa: E402
28
29
30def _prepare_userdata(userdata_path: str):
31    if os.path.exists(userdata_path):
32        shutil.rmtree(userdata_path)
33    os.makedirs(userdata_path, exist_ok=True)
34
35
36def _prepare_root(system_path: str, target_cpu: str):
37    root_dir = os.path.join(os.path.dirname(system_path), 'root')
38    if os.path.exists(root_dir):
39        shutil.rmtree(root_dir)
40    os.makedirs(root_dir, exist_ok=True)
41    _dir_list = [
42        'config', 'dev', 'proc', 'sys', 'updater', 'system', 'vendor', 'data', 'chip_ckm',
43        'storage', 'mnt', 'tmp', 'sys_prod', 'chip_prod', 'module_update', 'eng_system', 'eng_chipset'
44    ]
45    for _dir_name in _dir_list:
46        os.makedirs(os.path.join(root_dir, _dir_name), exist_ok=True)
47    os.symlink('/system/bin', os.path.join(root_dir, 'bin'))
48    os.symlink('/system/bin/init', os.path.join(root_dir, 'init'))
49    os.symlink('/system/etc', os.path.join(root_dir, 'etc'))
50    os.symlink('/vendor', os.path.join(root_dir, 'chipset'))
51    if target_cpu == 'arm64' or target_cpu == 'riscv64':
52        os.symlink('/system/lib64', os.path.join(root_dir, 'lib64'))
53    os.symlink('/system/lib', os.path.join(root_dir, 'lib'))
54
55
56def _prepare_updater(updater_path: str, target_cpu: str):
57    _dir_list = ['dev', 'proc', 'sys', 'system', 'tmp', 'lib', 'lib64', 'vendor']
58    for _dir_name in _dir_list:
59        _path = os.path.join(updater_path, _dir_name)
60        if os.path.exists(_path):
61            continue
62        os.makedirs(_path, exist_ok=True)
63    if not os.path.exists(os.path.join(updater_path, 'init')):
64        os.symlink('bin/init', os.path.join(updater_path, 'init'))
65    if not os.path.exists(os.path.join(updater_path, 'system/bin')):
66        os.symlink('/bin', os.path.join(updater_path, 'system/bin'))
67    if not os.path.exists(os.path.join(updater_path, 'system/lib')):
68        os.symlink('/lib', os.path.join(updater_path, 'system/lib'))
69    if target_cpu == 'arm64':
70        if not os.path.exists(os.path.join(updater_path, 'system/lib64')):
71            os.symlink('/lib64', os.path.join(updater_path, 'system/lib64'))
72        if not os.path.exists(os.path.join(updater_path, 'vendor/lib64')):
73            os.symlink('/lib64', os.path.join(updater_path, 'vendor/lib64'))
74    else:
75        if not os.path.exists(os.path.join(updater_path, 'vendor/lib')):
76            os.symlink('/lib', os.path.join(updater_path, 'vendor/lib'))
77    if not os.path.exists(os.path.join(updater_path, 'system/etc')):
78        os.symlink('/etc', os.path.join(updater_path, 'system/etc'))
79
80
81def _prepare_ramdisk(ramdisk_path: str):
82    _dir_list = ['bin', 'dev', 'etc', 'lib', 'proc', 'sys', 'system', 'usr', 'mnt', 'storage']
83    for _dir_name in _dir_list:
84        _path = os.path.join(ramdisk_path, _dir_name)
85        if os.path.exists(_path):
86            continue
87        os.makedirs(_path, exist_ok=True)
88    if not os.path.exists(os.path.join(ramdisk_path, 'init')):
89        os.symlink('bin/init_early', os.path.join(ramdisk_path, 'init'))
90
91
92def _prepare_eng_ststem(eng_system_path: str, build_variant: str):
93    if os.path.exists(eng_system_path):
94        shutil.rmtree(eng_system_path)
95    os.makedirs(eng_system_path, exist_ok=True)
96    if build_variant == "user":
97        return
98    _dir_list_first = ['etc', 'bin']
99    for _dir_name in _dir_list_first:
100        _path = os.path.join(eng_system_path, _dir_name)
101        if os.path.exists(_path):
102            shutil.rmtree(_path)
103        os.makedirs(_path, exist_ok=True)
104    _dir_list_second = ['param', 'init', 'selinux']
105    for _dir_name in _dir_list_second:
106        _path = os.path.join(eng_system_path, 'etc', _dir_name)
107        if os.path.exists(_path):
108            shutil.rmtree(_path)
109        os.makedirs(_path, exist_ok=True)
110    _target_policy_path = os.path.join(eng_system_path, 'etc', 'selinux', 'targeted', 'policy')
111    if os.path.exists(_target_policy_path):
112        shutil.rmtree(_target_policy_path)
113    os.makedirs(_target_policy_path, exist_ok=True)
114    root_path = find_top()
115    copy_eng_system_config = os.path.join(root_path, "build/ohos/images/mkimage/root_image.json")
116    with open(copy_eng_system_config, 'rb') as input_f:
117        default_build_args = json.load(input_f)
118    for arg in default_build_args.values():
119        sources_file = arg.get('source_file')
120        dest_file = arg.get('dest_file')
121        if(os.path.exists(dest_file)):
122            os.remove(dest_file)
123        if(os.path.exists(sources_file)):
124            shutil.copy(sources_file, dest_file)
125
126
127def _make_image(args):
128    if args.image_name == 'system':
129        _prepare_root(args.input_path, args.target_cpu)
130    elif args.image_name == 'updater':
131        _prepare_updater(args.input_path, args.target_cpu)
132    elif args.image_name == 'updater_ramdisk':
133        _prepare_updater(args.input_path, args.target_cpu)
134    elif args.image_name == 'ramdisk':
135        _prepare_ramdisk(args.input_path)
136    image_type = "raw"
137    if args.sparse_image:
138        image_type = "sparse"
139    config_file = args.image_config_file
140    if (os.path.exists(args.device_image_config_file)):
141        config_file = args.device_image_config_file
142    mk_image_args = [
143        args.input_path, config_file, args.output_image_path,
144        image_type
145    ]
146    if args.build_image_tools_path:
147        env_path = ':'.join(args.build_image_tools_path)
148        os.environ['PATH'] = '{}:{}'.format(env_path, os.environ.get('PATH'))
149    mkimages.mk_images(mk_image_args)
150
151
152def main(argv):
153    parser = argparse.ArgumentParser()
154    parser.add_argument('--depfile', required=True)
155    parser.add_argument('--image-name', required=True)
156    parser.add_argument('--build-variant', required=True)
157    parser.add_argument('--image-config-file', required=True)
158    parser.add_argument('--device-image-config-file', required=True)
159    parser.add_argument('--input-path', required=True)
160    parser.add_argument('--output-image-path', required=True)
161    parser.add_argument('--sparse-image',
162                        dest="sparse_image",
163                        action='store_true')
164    parser.set_defaults(sparse_image=False)
165    parser.add_argument('--build-image-tools-path', nargs='*', required=False)
166    parser.add_argument('--target-cpu', required=False)
167    args = parser.parse_args(argv)
168
169    if os.path.exists(args.output_image_path):
170        os.remove(args.output_image_path)
171    if args.image_name == 'userdata':
172        _prepare_userdata(args.input_path)
173    elif args.image_name == 'eng_system':
174        _prepare_eng_ststem(args.input_path, args.build_variant)
175    if os.path.isdir(args.input_path):
176        _make_image(args)
177        _dep_files = []
178        for _root, _, _files in os.walk(args.input_path):
179            for _file in _files:
180                _dep_files.append(os.path.join(_root, _file))
181        if (os.path.exists(args.device_image_config_file)):
182            _dep_files.append(args.device_image_config_file)
183        build_utils.write_depfile(args.depfile,
184                                  args.output_image_path,
185                                  _dep_files,
186                                  add_pydeps=False)
187    return 0
188
189
190if __name__ == '__main__':
191    sys.exit(main(sys.argv[1:]))
192