From 6d0134aaa0bb864eece5b4061328106762eb8a5f Mon Sep 17 00:00:00 2001 From: chiteroman Date: Sat, 22 Feb 2025 11:31:27 +0100 Subject: [PATCH] mkdtboimg: update script to python3 --- scripts/Makefile.lib | 2 +- scripts/dtc/libfdt/mkdtboimg.py | 123 ++++++++++++++++++++++---------- 2 files changed, 87 insertions(+), 38 deletions(-) diff --git a/scripts/Makefile.lib b/scripts/Makefile.lib index 665478b5b605..7a18c76c08f6 100644 --- a/scripts/Makefile.lib +++ b/scripts/Makefile.lib @@ -342,7 +342,7 @@ dtc-tmp = $(subst $(comma),_,$(dot-target).dts.tmp) # mkdtimg #---------------------------------------------------------------------------- quiet_cmd_mkdtimg = DTBOIMG $@ -cmd_mkdtimg = python2 $(srctree)/scripts/dtc/libfdt/mkdtboimg.py create $@ --page_size=4096 $(filter-out FORCE,$^) +cmd_mkdtimg = python3 $(srctree)/scripts/dtc/libfdt/mkdtboimg.py create $@ --page_size=4096 $(filter-out FORCE,$^) # cat # --------------------------------------------------------------------------- diff --git a/scripts/dtc/libfdt/mkdtboimg.py b/scripts/dtc/libfdt/mkdtboimg.py index 03f0fd1b727b..2634c76a1b56 100644 --- a/scripts/dtc/libfdt/mkdtboimg.py +++ b/scripts/dtc/libfdt/mkdtboimg.py @@ -1,4 +1,4 @@ -#! /usr/bin/env python +#! /usr/bin/env python3 # Copyright 2017, The Android Open Source Project # # Licensed under the Apache License, Version 2.0 (the "License"); @@ -18,12 +18,13 @@ from __future__ import print_function """Tool for packing multiple DTB/DTBO files into a single image""" import argparse +import fnmatch import os +import struct +import zlib from array import array from collections import namedtuple -import struct from sys import stdout -import zlib class CompressionFormat(object): """Enum representing DT compression format for a DT entry. @@ -36,14 +37,18 @@ class DtEntry(object): """Provides individual DT image file arguments to be added to a DTBO. Attributes: - _REQUIRED_KEYS: 'keys' needed to be present in the dictionary passed to instantiate - an object of this class. - _COMPRESSION_FORMAT_MASK: Mask to retrieve compression info for DT entry from flags field + REQUIRED_KEYS_V0: 'keys' needed to be present in the dictionary passed to instantiate + an object of this class when a DTBO header of version 0 is used. + REQUIRED_KEYS_V1: 'keys' needed to be present in the dictionary passed to instantiate + an object of this class when a DTBO header of version 1 is used. + COMPRESSION_FORMAT_MASK: Mask to retrieve compression info for DT entry from flags field when a DTBO header of version 1 is used. """ - _COMPRESSION_FORMAT_MASK = 0x0f - REQUIRED_KEYS = ('dt_file', 'dt_size', 'dt_offset', 'id', 'rev', 'flags', - 'custom0', 'custom1', 'custom2') + COMPRESSION_FORMAT_MASK = 0x0f + REQUIRED_KEYS_V0 = ('dt_file', 'dt_size', 'dt_offset', 'id', 'rev', + 'custom0', 'custom1', 'custom2', 'custom3') + REQUIRED_KEYS_V1 = ('dt_file', 'dt_size', 'dt_offset', 'id', 'rev', + 'flags', 'custom0', 'custom1', 'custom2') @staticmethod def __get_number_or_prop(arg): @@ -82,7 +87,14 @@ class DtEntry(object): the tuple (_REQUIRED_KEYS) """ - missing_keys = set(self.REQUIRED_KEYS) - set(kwargs) + self.__version = kwargs['version'] + required_keys = None + if self.__version == 0: + required_keys = self.REQUIRED_KEYS_V0 + elif self.__version == 1: + required_keys = self.REQUIRED_KEYS_V1 + + missing_keys = set(required_keys) - set(kwargs) if missing_keys: raise ValueError('Missing keys in DtEntry constructor: %r' % sorted(missing_keys)) @@ -92,10 +104,13 @@ class DtEntry(object): self.__dt_size = kwargs['dt_size'] self.__id = self.__get_number_or_prop(kwargs['id']) self.__rev = self.__get_number_or_prop(kwargs['rev']) - self.__flags = self.__get_number_or_prop(kwargs['flags']) + if self.__version == 1: + self.__flags = self.__get_number_or_prop(kwargs['flags']) self.__custom0 = self.__get_number_or_prop(kwargs['custom0']) self.__custom1 = self.__get_number_or_prop(kwargs['custom1']) self.__custom2 = self.__get_number_or_prop(kwargs['custom2']) + if self.__version == 0: + self.__custom3 = self.__get_number_or_prop(kwargs['custom3']) def __str__(self): sb = [] @@ -107,26 +122,30 @@ class DtEntry(object): value=self.__id)) sb.append('{key:>20} = {value:08x}'.format(key='rev', value=self.__rev)) + if self.__version == 1: + sb.append('{key:>20} = {value:08x}'.format(key='flags', + value=self.__flags)) sb.append('{key:>20} = {value:08x}'.format(key='custom[0]', - value=self.__flags)) - sb.append('{key:>20} = {value:08x}'.format(key='custom[1]', value=self.__custom0)) - sb.append('{key:>20} = {value:08x}'.format(key='custom[2]', + sb.append('{key:>20} = {value:08x}'.format(key='custom[1]', value=self.__custom1)) - sb.append('{key:>20} = {value:08x}'.format(key='custom[3]', + sb.append('{key:>20} = {value:08x}'.format(key='custom[2]', value=self.__custom2)) + if self.__version == 0: + sb.append('{key:>20} = {value:08x}'.format(key='custom[3]', + value=self.__custom3)) return '\n'.join(sb) - def compression_info(self, version): + def compression_info(self): """CompressionFormat: compression format for DT image file. Args: version: Version of DTBO header, compression is only supported from version 1. """ - if version is 0: + if self.__version == 0: return CompressionFormat.NO_COMPRESSION - return self.flags & self._COMPRESSION_FORMAT_MASK + return self.flags & self.COMPRESSION_FORMAT_MASK @property def dt_file(self): @@ -181,6 +200,10 @@ class DtEntry(object): """int: DT entry custom2 for this DT image.""" return self.__custom2 + @property + def custom3(self): + """int: DT entry custom3 for this DT image.""" + return self.__custom3 class Dtbo(object): """ @@ -232,10 +255,17 @@ class Dtbo(object): dtbo_offset: Offset where the DT image file for this dt_entry can be found in the resulting DTBO image. """ - struct.pack_into('>8I', self.__metadata, metadata_offset, dt_entry.size, - dt_entry.dt_offset, dt_entry.image_id, dt_entry.rev, - dt_entry.flags, dt_entry.custom0, dt_entry.custom1, - dt_entry.custom2) + if self.version == 0: + struct.pack_into('>8I', self.__metadata, metadata_offset, dt_entry.size, + dt_entry.dt_offset, dt_entry.image_id, dt_entry.rev, + dt_entry.custom0, dt_entry.custom1, dt_entry.custom2, + dt_entry.custom3) + elif self.version == 1: + struct.pack_into('>8I', self.__metadata, metadata_offset, dt_entry.size, + dt_entry.dt_offset, dt_entry.image_id, dt_entry.rev, + dt_entry.flags, dt_entry.custom0, dt_entry.custom1, + dt_entry.custom2) + def _update_metadata(self): """Updates the DTBO metadata. @@ -244,7 +274,7 @@ class Dtbo(object): Tree table entries and update the DTBO header. """ - self.__metadata = array('c', ' ' * self.__metadata_size) + self.__metadata = array('b', b' ' * self.__metadata_size) metadata_offset = self.header_size for dt_entry in self.__dt_entries: self._update_dt_entry_header(dt_entry, metadata_offset) @@ -290,15 +320,21 @@ class Dtbo(object): if self.__dt_entries: raise ValueError('DTBO DT entries can be added only once') - offset = self.dt_entries_offset / 4 + offset = self.dt_entries_offset // 4 params = {} + params['version'] = self.version params['dt_file'] = None for i in range(0, self.dt_entry_count): dt_table_entry = self.__metadata[offset:offset + self._DT_ENTRY_HEADER_INTS] params['dt_size'] = dt_table_entry[0] params['dt_offset'] = dt_table_entry[1] for j in range(2, self._DT_ENTRY_HEADER_INTS): - params[DtEntry.REQUIRED_KEYS[j + 1]] = str(dt_table_entry[j]) + required_keys = None + if self.version == 0: + required_keys = DtEntry.REQUIRED_KEYS_V0 + elif self.version == 1: + required_keys = DtEntry.REQUIRED_KEYS_V1 + params[required_keys[j + 1]] = str(dt_table_entry[j]) dt_entry = DtEntry(**params) self.__dt_entries.append(dt_entry) offset += self._DT_ENTRY_HEADER_INTS @@ -465,14 +501,13 @@ class Dtbo(object): dt_offset = (self.header_size + dt_entry_count * self.dt_entry_size) - dt_entry_buf = "" + dt_entry_buf = b"" for dt_entry in dt_entries: if not isinstance(dt_entry, DtEntry): raise ValueError('Adding invalid DT entry object to DTBO') entry = self._find_dt_entry_with_same_file(dt_entry) - dt_entry_compression_info = dt_entry.compression_info(self.version) - if entry and (entry.compression_info(self.version) - == dt_entry_compression_info): + dt_entry_compression_info = dt_entry.compression_info() + if entry and (entry.compression_info() == dt_entry_compression_info): dt_entry.dt_offset = entry.dt_offset dt_entry.size = entry.size else: @@ -510,7 +545,7 @@ class Dtbo(object): offset = self.dt_entries[idx].dt_offset self.__file.seek(offset, 0) fout.seek(0) - compression_format = self.dt_entries[idx].compression_info(self.version) + compression_format = self.dt_entries[idx].compression_info() if decompress and compression_format: if (compression_format == CompressionFormat.ZLIB_COMPRESSION or compression_format == CompressionFormat.GZIP_COMPRESSION): @@ -580,6 +615,9 @@ def parse_dt_entry(global_args, arglist): parser.add_argument('--custom2', type=str, dest='custom2', action='store', default=global_args.global_custom2) + parser.add_argument('--custom3', type=str, dest='custom3', + action='store', + default=global_args.global_custom3) return parser.parse_args(arglist) @@ -612,7 +650,7 @@ def parse_dt_entries(global_args, arg_list): raise ValueError('Input DT images must be provided') total_images = len(img_file_idx) - for idx in xrange(total_images): + for idx in range(total_images): start_idx = img_file_idx[idx] if idx == total_images - 1: argv = arg_list[start_idx:] @@ -621,6 +659,7 @@ def parse_dt_entries(global_args, arg_list): argv = arg_list[start_idx:end_idx] args = parse_dt_entry(global_args, argv) params = vars(args) + params['version'] = global_args.version params['dt_offset'] = 0 params['dt_size'] = os.fstat(params['dt_file'].fileno()).st_size dt_entries.append(DtEntry(**params)) @@ -753,6 +792,8 @@ def parse_create_args(arg_list): action='store', default='0') parser.add_argument('--custom2', type=str, dest='global_custom2', action='store', default='0') + parser.add_argument('--custom3', type=str, dest='global_custom3', + action='store', default='0') args = parser.parse_args(argv) return args, remainder @@ -769,7 +810,7 @@ def parse_dump_cmd_args(arglist): parser = argparse.ArgumentParser(prog='dump') parser.add_argument('--output', '-o', nargs='?', - type=argparse.FileType('wb'), + type=argparse.FileType('w'), dest='outfile', default=stdout) parser.add_argument('--dtb', '-b', nargs='?', type=str, @@ -789,7 +830,7 @@ def parse_config_create_cmd_args(arglist): """ parser = argparse.ArgumentParser(prog='cfg_create') parser.add_argument('conf_file', nargs='?', - type=argparse.FileType('rb'), + type=argparse.FileType('r'), default=None) cwd = os.getcwd() parser.add_argument('--dtb-dir', '-d', nargs='?', type=str, @@ -845,15 +886,22 @@ def create_dtbo_image_from_config(fout, argv): if not args.conf_file: raise ValueError('Configuration file must be provided') - _DT_KEYS = ('id', 'rev', 'flags', 'custom0', 'custom1', 'custom2') + _DT_KEYS = ('id', 'rev', 'flags', 'custom0', 'custom1', 'custom2', 'custom3') _GLOBAL_KEY_TYPES = {'dt_type': str, 'page_size': int, 'version': int} global_args, dt_args = parse_config_file(args.conf_file, _DT_KEYS, _GLOBAL_KEY_TYPES) + version = global_args['version'] + params = {} + params['version'] = version dt_entries = [] for dt_arg in dt_args: - filepath = args.dtbdir + os.sep + dt_arg['filename'] + filepath = dt_arg['filename'] + if not os.path.isabs(filepath): + for root, dirnames, filenames in os.walk(args.dtbdir): + for filename in fnmatch.filter(filenames, os.path.basename(filepath)): + filepath = os.path.join(root, filename) params['dt_file'] = open(filepath, 'rb') params['dt_offset'] = 0 params['dt_size'] = os.fstat(params['dt_file'].fileno()).st_size @@ -865,7 +913,7 @@ def create_dtbo_image_from_config(fout, argv): dt_entries.append(DtEntry(**params)) # Create and write DTBO file - dtbo = Dtbo(fout, global_args['dt_type'], global_args['page_size'], global_args['version']) + dtbo = Dtbo(fout, global_args['dt_type'], global_args['page_size'], version) dt_entry_buf = dtbo.add_dt_entries(dt_entries) dtbo.commit(dt_entry_buf) fout.close() @@ -916,6 +964,7 @@ def print_create_usage(progname): sb.append(' --custom0=') sb.append(' --custom1=') sb.append(' --custom2=\n') + sb.append(' --custom3=\n') sb.append(' The value could be a number or a DT node path.') sb.append(' could be a 32-bits digit or hex value, ex. 68000, 0x6800.') @@ -969,7 +1018,7 @@ def print_usage(cmd, _): def main(): """Main entry point for mkdtboimg.""" - parser = argparse.ArgumentParser(prog='mkdtboimg.py') + parser = argparse.ArgumentParser() subparser = parser.add_subparsers(title='subcommand', description='Valid subcommands')