#!/usr/bin/env python # Copyright 2017, The Android Open Source Project # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. from __future__ import print_function try: from os import fstat, stat, remove from sys import exit from argparse import ArgumentParser, FileType from ctypes import sizeof, Structure, c_char, c_int from struct import pack, calcsize import zlib except Exception as e: print("some module is needed:" + str(e)) exit(-1) dt_head_info_fmt = '4sII' dt_entry_fmt = 'Q4I2Q' dtimg_version = 1 dtb_count = 1 def write32(output, value): output.write(chr(value & 255)) ; value=value // 256 output.write(chr(value & 255)) ; value=value // 256 output.write(chr(value & 255)) ; value=value // 256 output.write(chr(value & 255)) def compress(filename, input, output): output.write('\037\213\010') output.write(chr(0)) statval = stat(filename) write32(output, 0) output.write('\002') output.write('\003') crcval = zlib.crc32("") compobj = zlib.compressobj(9, zlib.DEFLATED, -zlib.MAX_WBITS, zlib.DEF_MEM_LEVEL, 0) while True: data = input.read(1024) if data == "": break crcval = zlib.crc32(data, crcval) output.write(compobj.compress(data)) output.write(compobj.flush()) write32(output, crcval) write32(output, statval.st_size) def dtb_compress(dtb_file): try: outputname = dtb_file + '.gz' input = open(dtb_file, 'rb') output = open(outputname, 'wb') compress(dtb_file, input, output) input.close() output.close() except Exception as e: print('dtb_compress error:' + str(e)) exit(-1) return outputname class dt_head_info(Structure): _fields_ = [('magic', c_char * 4), ('version', c_int), ('dt_count', c_int)] class dt_entry_t(Structure): _fields_ = [('dtb_size', c_int), ('dtb_offset', c_int)] def align_page_size(offset, pagesize): return (pagesize - (offset % pagesize)) def write_head_info(head_info, args): args.output.write(pack(dt_head_info_fmt, head_info.magic, head_info.version, head_info.dt_count)) def write_dtb_entry_t(dt_entry, args): args.output.write(pack(dt_entry_fmt, 0, # reserved dt_entry.dtb_size, 0, # reserved dt_entry.dtb_offset, 0, # reserved 0, # reserved 0)) # reserved def write_padding(args, padding): for i in range(0, padding): args.output.write('\x00') def write_dtb(args): dtb_file = args.dtb out_dtb = dtb_file if args.compress == True: out_dtb = dtb_compress(dtb_file) try: dtb_offset = calcsize(dt_head_info_fmt) + \ calcsize(dt_entry_fmt) + \ 4 padding = align_page_size(dtb_offset, args.pagesize) dtb_size = stat(out_dtb).st_size dtb_size_padding = align_page_size(dtb_size, args.pagesize) dt_entry = dt_entry_t(dtb_size + dtb_size_padding, dtb_offset + padding) write_dtb_entry_t(dt_entry, args) args.output.write(pack('I', 0)) # SUCCESS code number write_padding(args, padding) with open(out_dtb, 'rb') as dtb_fd: args.output.write(dtb_fd.read(dtb_size)) write_padding(args, dtb_size_padding) except Exception as e: print('write dtb error:' + str(e)) exit(-1) def clean_gz_file(args): try: if args.compress != True: return remove(args.dtb + '.gz') except Exception as e: print('clean gz file error:' + str(e)) exit(-1) def parse_cmdline(): parser = ArgumentParser() parser.add_argument('-c', '--compress', help='compress dtb or not', action='store_true') parser.add_argument('-d', '--dtb', help='path to the dtb', type=str, required=True) parser.add_argument('-s', '--pagesize', help='align page size', type=int, choices=[2**i for i in range(11,15)], default=2048) parser.add_argument('-o', '--output', help='output file name', type=FileType('wb'), required=True) return parser.parse_args() def main(): args = parse_cmdline() dtimg_head_info = dt_head_info('HSDT', dtimg_version, dtb_count) write_head_info(dtimg_head_info, args) write_dtb(args) clean_gz_file(args) if __name__ == '__main__': main()