diff --git a/create_gpt_image.py b/create_gpt_image.py index 71417da..4cd80bf 100755 --- a/create_gpt_image.py +++ b/create_gpt_image.py @@ -26,17 +26,21 @@ basicConfig) from argparse import ArgumentParser from os import remove, stat -from os.path import isfile, normcase, normpath, realpath, abspath, dirname +from os import open as os_open, close as os_close, lseek, O_RDONLY, SEEK_END +from os.path import isfile, normcase, normpath, realpath, abspath, dirname, exists +from stat import S_ISBLK from struct import unpack, pack from uuid import UUID, uuid4 from binascii import crc32 from re import compile as re_compile from collections import namedtuple +from time import time + if version_info < (3, 0, 1): from ConfigParser import SafeConfigParser, ParsingError, NoOptionError, NoSectionError else: - from configparser import SafeConfigParser, ParsingError, NoOptionError, NoSectionError -from math import floor, log + from configparser import ConfigParser, ParsingError, NoOptionError, NoSectionError +from math import floor, ceil, log class MBRInfos(object): @@ -69,8 +73,8 @@ class MBRInfos(object): _FMT = ' 0: units = ('KBytes', 'MBytes', 'GBytes') index = int(floor(log(self.lba_size, 1024))) - computed_size = round(self.lba_size / (1024**index), 2) + computed_size = round(self.lba_size / (1024 ** index), 2) human_size = '{0} {1}'.format(computed_size, units[index]) else: human_size = '0 Bytes' @@ -127,7 +131,7 @@ def read(self, img_file, offset=0): # unpacks the raw MBR to a named tuple self.boot, self.os_type, self.lba_start, self.lba_size, self.dummy_1, \ - self.dummy_2, self.dummy_3, self.sign \ + self.dummy_2, self.dummy_3, self.sign \ = unpack(MBRInfos._FMT, self.raw) def write(self, img_file, offset=0): @@ -135,8 +139,8 @@ def write(self, img_file, offset=0): Used to write MBR in an image file """ self.raw = pack(MBRInfos._FMT, self.boot, self.os_type, - self.lba_start, self.lba_size, '', - MBRInfos._PART_ENTRY, '', self.sign) + self.lba_start, self.lba_size, b'', + MBRInfos._PART_ENTRY, b'', self.sign) img_file.seek(offset) img_file.write(self.raw) @@ -203,8 +207,8 @@ def __init__(self, img_size=2147483648, block_size=512, size=92): # TODO use decorators and properties to subtitute by r/w access in the # raw attribute with pack and unpack function all these attributes - self.sign = 'EFI PART' - self.rev = '\x00\x00\x01\x00' + self.sign = b'EFI PART' + self.rev = b'\x00\x00\x01\x00' self.size = size # sets the length and the entry size of the GPT partition table with @@ -213,13 +217,13 @@ def __init__(self, img_size=2147483648, block_size=512, size=92): self.entry_size = 128 # calculates the size of image in block - size_in_block = img_size / block_size + size_in_block = int(ceil(img_size / block_size)) # sets the lba backup at the value of first lba used by GPT backup self.lba_backup = size_in_block - 1 # calculates the size of the partition table in block - table_size = (self.table_length * self.entry_size) / block_size + table_size = int(ceil((self.table_length * self.entry_size) / block_size)) # sets the lba first at the first usable lba for a partition self.lba_first = table_size + 2 @@ -276,9 +280,9 @@ def read(self, img_file, offset): # unpacks the raw GPT header of the image file to a named tuple self.sign, self.rev, self.size, self.crc, self.lba_current, \ - self.lba_backup, self.lba_first, self.lba_last, self.uuid, \ - self.lba_start, self.table_length, self.entry_size, \ - self.table_crc = unpack(GPTHeaderInfos._FMT, self.raw) + self.lba_backup, self.lba_first, self.lba_last, self.uuid, \ + self.lba_start, self.table_length, self.entry_size, \ + self.table_crc = unpack(GPTHeaderInfos._FMT, self.raw) def write(self, img_file, offset, block_size): """ @@ -300,7 +304,7 @@ def write(self, img_file, offset, block_size): img_file.write(self.raw) # writes zero on unused blocks of GPT header - raw_stuffing = '\x00' * (block_size - len(self.raw)) + raw_stuffing = b'\x00' * (block_size - len(self.raw)) img_file.write(raw_stuffing) # saves the end of the GPT header @@ -420,8 +424,8 @@ def __init__(self, pos, size): def __repr__(self): result = 'UUID partition entry {0}\n'.format(self.pos) - result = '\t{0}type: {1}\n'.format(result, UUID(bytes_le=self.type)) - result = '\t{0}UUID: {1}\n'.format(result, UUID(bytes_le=self.uuid)) + result = '\t{0}type: {1}\n'.format(result, self.type) + result = '\t{0}UUID: {1}\n'.format(result, self.uuid) result = '\t{0}first LBA: {1}\n'.format(result, self.lba_first) result = '\t{0}last LBA: {1}\n'.format(result, self.lba_last) result = '\t{0}attribute flags: 0x{1:08x}\n'.format(result, self.attr) @@ -443,101 +447,15 @@ def read(self, raw_table): # unpacks the raw partition table entry read to a named tuple self.type, self.uuid, self.lba_first, self.lba_last, self.attr, \ - self.name = unpack(TableEntryInfos._FMT, self.raw) + self.name = unpack(TableEntryInfos._FMT, self.raw) def write(self, img_file, offset, entry_info): """ Use to write a partition table entries in an image file """ - types = { - 'Unused': '00000000-0000-0000-0000-000000000000', - 'esp': 'C12A7328-F81F-11D2-BA4B-00A0C93EC93B', - 'fat': '024DEE41-33E7-11D3-9D69-0008C781F39F', - 'bootloader': '2568845D-2332-4675-BC39-8FA5A4748D15', - 'boot': '0fc63daf-8483-4772-8e79-3d69d8477de4', - 'boot_a': '0fc63daf-8483-4772-8e79-3d69d8477de4', - 'boot_b': '0fc63daf-8483-4772-8e79-3d69d8477de4', - 'recovery': '0fc63daf-8483-4772-8e79-3d69d8477de4', - 'misc': '0fc63daf-8483-4772-8e79-3d69d8477de4', - 'metadata': '5808C8AA-7E8F-42E0-85D2-E1E90434CFB3', - 'reserved': '8DA63339-0007-60C0-C436-083AC8230908', - 'linux': { - 'xen_dom0' : '0fc63daf-8483-4772-8e79-3d69d8477de4', - 'xen_misc' : '0fc63daf-8483-4772-8e79-3d69d8477de4', - 'xen_guest' : '0fc63daf-8483-4772-8e79-3d69d8477de4', - 'xen_rootfs' : '0fc63daf-8483-4772-8e79-3d69d8477de4', - 'sos_boot' : '0fc63daf-8483-4772-8e79-3d69d8477de4', - 'uos_boot' : '0fc63daf-8483-4772-8e79-3d69d8477de4', - 'android_guest' : '0fc63daf-8483-4772-8e79-3d69d8477de4', - 'sos_rootfs' : '0fc63daf-8483-4772-8e79-3d69d8477de4', - 'uos_rootfs' : '0fc63daf-8483-4772-8e79-3d69d8477de4', - 'vbmeta': '0fc63daf-8483-4772-8e79-3d69d8477de4', - 'vbmeta_a': '0fc63daf-8483-4772-8e79-3d69d8477de4', - 'vbmeta_b': '0fc63daf-8483-4772-8e79-3d69d8477de4', - 'multiboot' : '0fc63daf-8483-4772-8e79-3d69d8477de4', - 'multiboot_a' : '0fc63daf-8483-4772-8e79-3d69d8477de4', - 'multiboot_b' : '0fc63daf-8483-4772-8e79-3d69d8477de4', - 'tos' : '0fc63daf-8483-4772-8e79-3d69d8477de4', - 'tos_a' : '0fc63daf-8483-4772-8e79-3d69d8477de4', - 'tos_b' : '0fc63daf-8483-4772-8e79-3d69d8477de4', - 'system': '0fc63daf-8483-4772-8e79-3d69d8477de4', - 'system_a': '0fc63daf-8483-4772-8e79-3d69d8477de4', - 'system_b': '0fc63daf-8483-4772-8e79-3d69d8477de4', - 'esp': '0fc63daf-8483-4772-8e79-3d69d8477de4', - 'esp2': '0fc63daf-8483-4772-8e79-3d69d8477de4', - 'bootloader': '0fc63daf-8483-4772-8e79-3d69d8477de4', - 'bootloader_a': '0fc63daf-8483-4772-8e79-3d69d8477de4', - 'bootloader_b': '0fc63daf-8483-4772-8e79-3d69d8477de4', - 'bootloader2': '0fc63daf-8483-4772-8e79-3d69d8477de4', - 'bldr_utils': '0fc63daf-8483-4772-8e79-3d69d8477de4', - 'vendor': '0fc63daf-8483-4772-8e79-3d69d8477de4', - 'vendor_a': '0fc63daf-8483-4772-8e79-3d69d8477de4', - 'vendor_b': '0fc63daf-8483-4772-8e79-3d69d8477de4', - 'vendor_boot': '0fc63daf-8483-4772-8e79-3d69d8477de4', - 'vendor_boot_a': '0fc63daf-8483-4772-8e79-3d69d8477de4', - 'vendor_boot_b': '0fc63daf-8483-4772-8e79-3d69d8477de4', - 'product': '0fc63daf-8483-4772-8e79-3d69d8477de4', - 'product_a': '0fc63daf-8483-4772-8e79-3d69d8477de4', - 'product_b': '0fc63daf-8483-4772-8e79-3d69d8477de4', - 'odm': '0fc63daf-8483-4772-8e79-3d69d8477de4', - 'odm_a': '0fc63daf-8483-4772-8e79-3d69d8477de4', - 'odm_b': '0fc63daf-8483-4772-8e79-3d69d8477de4', - 'acpi': '0fc63daf-8483-4772-8e79-3d69d8477de4', - 'acpi_a': '0fc63daf-8483-4772-8e79-3d69d8477de4', - 'acpi_b': '0fc63daf-8483-4772-8e79-3d69d8477de4', - 'acpio': '0fc63daf-8483-4772-8e79-3d69d8477de4', - 'acpio_a': '0fc63daf-8483-4772-8e79-3d69d8477de4', - 'acpio_b': '0fc63daf-8483-4772-8e79-3d69d8477de4', - 'cache': '0fc63daf-8483-4772-8e79-3d69d8477de4', - 'data': '0fc63daf-8483-4772-8e79-3d69d8477de4', - 'userdata': '0fc63daf-8483-4772-8e79-3d69d8477de4', - 'persistent': ('ebc597d0-2053-4b15-8b64-' - 'e0aac75f4db1'), - 'factory': ('0fc63daf-8483-4772-8e79-' - '3d69d8477de4'), - 'config': ('0fc63daf-8483-4772-8e79-' - '3d69d8477de4'), - 'mfos':'4f33cfe4-a0c1-448b-aec4-40f10a0cef3f', - 'teedata': '0fc63daf-8483-4772-8e79-3d69d8477de4', - 'super': '0fc63daf-8483-4772-8e79-3d69d8477de4', - 'share_data': '0fc63daf-8483-4772-8e79-3d69d8477de4', - 'reserved': '0fc63daf-8483-4772-8e79-3d69d8477de4' - } - } - - # checks if the partition type used is available - if entry_info.type in types: - if isinstance(types[entry_info.type], dict): - tuuid = UUID(types[entry_info.type][entry_info.label]).bytes_le - else: - tuuid = UUID(types[entry_info.type]).bytes_le - else: - error('Unknown partition type: {0} {1}' - .format(entry_info.label, entry_info.type)) - exit(-1) - + tuuid = entry_info.type.bytes_le # sets the partition uuid - puuid = UUID(entry_info.uuid).bytes_le + puuid = entry_info.uuid.bytes_le last = int(entry_info.size) + int(entry_info.begin) - 1 self.raw = pack(TableEntryInfos._FMT, tuuid, puuid, @@ -560,14 +478,14 @@ class TLBInfos(list): def __init__(self, path): super(TLBInfos, self).__init__() self.path = path - self._set_format() self.slotab = 0 + self.format = 'bin' def __repr__(self): result = '' for item in self: - line = ('add -b {0} -s {1} -t {2} -u {3} -l {4}' + line = ('add -b {0} -s {1} -u {2} -u {3} -l {4}' '\n').format(item.begin, item.size, item.type, item.uuid, item.label) result = '{0}{1}'.format(result, line) @@ -601,10 +519,10 @@ def _read_json(self, block_size): """ with open(self.path, 'r') as tlb_file: re_parser = re_compile(r'^add\s-b\s(?P\w+)\s-s\s' - '(?P[\w$()-]+)\s-t\s' - '(?P\w+)\s-u\s' - '(?P[\w-]+)\s' - '-l\s(?P