140681896Sopenharmony_ci#!/usr/bin/env python3 240681896Sopenharmony_ci# -*- coding: utf-8 -*- 340681896Sopenharmony_ci 440681896Sopenharmony_ci# Copyright (c) 2023 Huawei Device Co., Ltd. 540681896Sopenharmony_ci# Licensed under the Apache License, Version 2.0 (the "License"); 640681896Sopenharmony_ci# you may not use this file except in compliance with the License. 740681896Sopenharmony_ci# You may obtain a copy of the License at 840681896Sopenharmony_ci# 940681896Sopenharmony_ci# http://www.apache.org/licenses/LICENSE-2.0 1040681896Sopenharmony_ci# 1140681896Sopenharmony_ci# Unless required by applicable law or agreed to in writing, software 1240681896Sopenharmony_ci# distributed under the License is distributed on an "AS IS" BASIS, 1340681896Sopenharmony_ci# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 1440681896Sopenharmony_ci# See the License for the specific language governing permissions and 1540681896Sopenharmony_ci# limitations under the License. 1640681896Sopenharmony_ci 1740681896Sopenharmony_ciimport os 1840681896Sopenharmony_ciimport sys 1940681896Sopenharmony_ciimport argparse 2040681896Sopenharmony_ciimport subprocess 2140681896Sopenharmony_ciimport secrets 2240681896Sopenharmony_ci 2340681896Sopenharmony_ciMOUNT_POINT = "/module_update" 2440681896Sopenharmony_ciBLOCK_SIZE = 4096 2540681896Sopenharmony_ciHASH_SIZE = 32 2640681896Sopenharmony_ciIMG_MARGIN_SIZE = 16777216 2740681896Sopenharmony_ci 2840681896Sopenharmony_ci 2940681896Sopenharmony_cidef run_cmd(cmd): 3040681896Sopenharmony_ci res = subprocess.Popen(cmd.split(), stdout=subprocess.PIPE, 3140681896Sopenharmony_ci stderr=subprocess.PIPE) 3240681896Sopenharmony_ci sout, serr = res.communicate(timeout=120) 3340681896Sopenharmony_ci 3440681896Sopenharmony_ci return res.pid, res.returncode, sout, serr 3540681896Sopenharmony_ci 3640681896Sopenharmony_ci 3740681896Sopenharmony_cidef verify_ret(res): 3840681896Sopenharmony_ci if res[1]: 3940681896Sopenharmony_ci print(" ".join(["pid ", str(res[0]), " ret ", str(res[1]), "\n", 4040681896Sopenharmony_ci res[2].decode(), res[3].decode()])) 4140681896Sopenharmony_ci print("MkImages failed errno: %s" % str(res[1])) 4240681896Sopenharmony_ci sys.exit(2) 4340681896Sopenharmony_ci 4440681896Sopenharmony_ci 4540681896Sopenharmony_cidef sparse_img2simg(is_sparse, device): 4640681896Sopenharmony_ci # we don't support sparse in mktools. 4740681896Sopenharmony_ci if "sparse" in is_sparse: 4840681896Sopenharmony_ci tmp_device = "%s.tmp" % device 4940681896Sopenharmony_ci run_cmd(" ".join(["img2simg ", device, " ", tmp_device])) 5040681896Sopenharmony_ci os.rename(tmp_device, device) 5140681896Sopenharmony_ci 5240681896Sopenharmony_ci 5340681896Sopenharmony_cidef getdirsize(target_dir): 5440681896Sopenharmony_ci size = 0 5540681896Sopenharmony_ci for root, dirs, files in os.walk(target_dir): 5640681896Sopenharmony_ci size += sum([roundup(os.path.getsize(os.path.join(root, name)), BLOCK_SIZE) for name in files]) 5740681896Sopenharmony_ci return size 5840681896Sopenharmony_ci 5940681896Sopenharmony_ci 6040681896Sopenharmony_cidef roundup(size, unit): 6140681896Sopenharmony_ci return (size + unit - 1) & (~(unit - 1)) 6240681896Sopenharmony_ci 6340681896Sopenharmony_ci 6440681896Sopenharmony_cidef resize_img(device): 6540681896Sopenharmony_ci run_cmd(" ".join(["resize2fs", "-M", device])) 6640681896Sopenharmony_ci 6740681896Sopenharmony_ci 6840681896Sopenharmony_cidef get_hash_tree_size(img_size): 6940681896Sopenharmony_ci treesize = 0 7040681896Sopenharmony_ci size = img_size 7140681896Sopenharmony_ci while size > BLOCK_SIZE: 7240681896Sopenharmony_ci blocknum = size // BLOCK_SIZE 7340681896Sopenharmony_ci level_size = roundup(blocknum * HASH_SIZE, BLOCK_SIZE) 7440681896Sopenharmony_ci treesize += level_size 7540681896Sopenharmony_ci size = level_size 7640681896Sopenharmony_ci return treesize 7740681896Sopenharmony_ci 7840681896Sopenharmony_ci 7940681896Sopenharmony_cidef sign_img(device, pubkey, privkey, output): 8040681896Sopenharmony_ci hvb_tools = "hvbtool.py" 8140681896Sopenharmony_ci source_image = device 8240681896Sopenharmony_ci partition = "update" 8340681896Sopenharmony_ci img_size = os.path.getsize(device) 8440681896Sopenharmony_ci partition_size = img_size + get_hash_tree_size(img_size) + BLOCK_SIZE 8540681896Sopenharmony_ci salt = secrets.token_hex(20) 8640681896Sopenharmony_ci algorithm = "SHA256_RSA2048" 8740681896Sopenharmony_ci rollback_index = "0" 8840681896Sopenharmony_ci rollback_location = "0" 8940681896Sopenharmony_ci run_cmd(" ".join([hvb_tools, "make_hashtree_footer", "--image", device, 9040681896Sopenharmony_ci "--partition", partition, 9140681896Sopenharmony_ci "--partition_size", str(partition_size), 9240681896Sopenharmony_ci "--salt", salt, 9340681896Sopenharmony_ci "--pubkey", pubkey, 9440681896Sopenharmony_ci "--privkey", privkey, 9540681896Sopenharmony_ci "--algorithm", algorithm, 9640681896Sopenharmony_ci "--rollback_index", rollback_index, 9740681896Sopenharmony_ci "--rollback_location", rollback_location, 9840681896Sopenharmony_ci "--output", output])) 9940681896Sopenharmony_ci 10040681896Sopenharmony_ci 10140681896Sopenharmony_cidef build_image(args): 10240681896Sopenharmony_ci image_type = "raw" 10340681896Sopenharmony_ci if args.sparse_image: 10440681896Sopenharmony_ci image_type = "sparse" 10540681896Sopenharmony_ci if args.build_image_tools_path: 10640681896Sopenharmony_ci env_path = ':'.join(args.build_image_tools_path) 10740681896Sopenharmony_ci os.environ['PATH'] = '{}:{}'.format(env_path, os.environ.get('PATH')) 10840681896Sopenharmony_ci src_dir = args.input_path 10940681896Sopenharmony_ci device = args.output_image_path 11040681896Sopenharmony_ci is_sparse = image_type 11140681896Sopenharmony_ci if "ext4" == args.fs_type: 11240681896Sopenharmony_ci fs_type = "ext4" 11340681896Sopenharmony_ci mkfs_tools = "mkextimage.py" 11440681896Sopenharmony_ci elif "f2fs" == args.fs_type: 11540681896Sopenharmony_ci fs_type = "f2fs" 11640681896Sopenharmony_ci mkfs_tools = "mkf2fsimage.py" 11740681896Sopenharmony_ci elif "cpio" == args.fs_type: 11840681896Sopenharmony_ci fs_type = "cpio" 11940681896Sopenharmony_ci mkfs_tools = "mkcpioimage.py" 12040681896Sopenharmony_ci else: 12140681896Sopenharmony_ci print("not support filesystem type!!") 12240681896Sopenharmony_ci sys.exit(1) 12340681896Sopenharmony_ci 12440681896Sopenharmony_ci fs_size = getdirsize(src_dir) + IMG_MARGIN_SIZE 12540681896Sopenharmony_ci fs_type_config = "--fs_type=" + fs_type 12640681896Sopenharmony_ci dac_config = args.dac_config 12740681896Sopenharmony_ci file_context = args.file_context 12840681896Sopenharmony_ci 12940681896Sopenharmony_ci mk_configs = " ".join([src_dir, device, MOUNT_POINT, str(fs_size), fs_type_config, 13040681896Sopenharmony_ci "--dac_config", dac_config, "--file_context", file_context]) 13140681896Sopenharmony_ci res = run_cmd(" ".join([mkfs_tools, mk_configs])) 13240681896Sopenharmony_ci verify_ret(res) 13340681896Sopenharmony_ci sparse_img2simg(is_sparse, device) 13440681896Sopenharmony_ci resize_img(device) 13540681896Sopenharmony_ci if args.pubkey: 13640681896Sopenharmony_ci sign_img(device, args.pubkey, args.privkey, args.output_sign_image_path) 13740681896Sopenharmony_ci else: 13840681896Sopenharmony_ci print("not sign image") 13940681896Sopenharmony_ci 14040681896Sopenharmony_ci 14140681896Sopenharmony_cidef main(argv): 14240681896Sopenharmony_ci parser = argparse.ArgumentParser() 14340681896Sopenharmony_ci parser.add_argument('--image-name', required=True) 14440681896Sopenharmony_ci parser.add_argument('--fs-type', required=True) 14540681896Sopenharmony_ci parser.add_argument('--dac-config', required=True) 14640681896Sopenharmony_ci parser.add_argument('--file-context', required=True) 14740681896Sopenharmony_ci parser.add_argument('--input-path', required=True) 14840681896Sopenharmony_ci parser.add_argument('--output-image-path', required=True) 14940681896Sopenharmony_ci parser.add_argument('--sparse-image', 15040681896Sopenharmony_ci dest="sparse_image", 15140681896Sopenharmony_ci action='store_true') 15240681896Sopenharmony_ci parser.set_defaults(sparse_image=False) 15340681896Sopenharmony_ci parser.add_argument('--build-image-tools-path', nargs='*', required=False) 15440681896Sopenharmony_ci parser.add_argument('--target-cpu', required=False) 15540681896Sopenharmony_ci parser.add_argument('--pubkey', required=False) 15640681896Sopenharmony_ci parser.add_argument('--privkey', required=False) 15740681896Sopenharmony_ci parser.add_argument('--output-sign-image-path', required=False) 15840681896Sopenharmony_ci args = parser.parse_args(argv) 15940681896Sopenharmony_ci 16040681896Sopenharmony_ci if os.path.exists(args.output_image_path): 16140681896Sopenharmony_ci os.remove(args.output_image_path) 16240681896Sopenharmony_ci if os.path.isdir(args.input_path): 16340681896Sopenharmony_ci build_image(args) 16440681896Sopenharmony_ci return 0 16540681896Sopenharmony_ci 16640681896Sopenharmony_ci 16740681896Sopenharmony_ciif __name__ == '__main__': 16840681896Sopenharmony_ci sys.exit(main(sys.argv[1:])) 169