diff options
-rw-r--r-- | mic/utils/gpt_parser.py | 74 |
1 files changed, 51 insertions, 23 deletions
diff --git a/mic/utils/gpt_parser.py b/mic/utils/gpt_parser.py index ad76d03..c38eee1 100644 --- a/mic/utils/gpt_parser.py +++ b/mic/utils/gpt_parser.py @@ -127,16 +127,24 @@ class GptParser: 'hdr_size' : header size in bytes 'hdr_crc' : header CRC32 'hdr_lba' : LBA of this header - 'backup_lba' : backup hader LBA + 'hdr_offs' : byte disk offset of this header + 'backup_lba' : backup header LBA + 'backup_offs' : byte disk offset of backup header 'first_lba' : first usable LBA for partitions + 'first_offs' : first usable byte disk offset for partitions 'last_lba' : last usable LBA for partitions + 'last_offs' : last usable byte disk offset for partitions 'disk_uuid' : UUID of the disk 'ptable_lba' : starting LBA of array of partition entries + 'ptable_offs' : disk byte offset of the start of the partition table + 'ptable_size' : partition table size in bytes 'entries_cnt' : number of available partition table entries 'entry_size' : size of a single partition entry 'ptable_crc' : CRC32 of the partition table 'primary' : a boolean, if 'True', this is the primary GPT header, if 'False' - the secondary + 'primary_str' : contains string "primary" if this is the primary GPT + header, and "backup" otherwise This dictionary corresponds to the GPT header format. Please, see the UEFI standard for the description of these fields. @@ -148,26 +156,36 @@ class GptParser: raw_hdr = self._read_disk(self.sector_size, _GPT_HEADER_SIZE) raw_hdr = struct.unpack(_GPT_HEADER_FORMAT, raw_hdr) _validate_header(raw_hdr) + primary_str = "primary" if not primary: + # Read and validate the backup GPT header raw_hdr = self._read_disk(raw_hdr[6] * self.sector_size, _GPT_HEADER_SIZE) raw_hdr = struct.unpack(_GPT_HEADER_FORMAT, raw_hdr) _validate_header(raw_hdr) + primary_str = "backup" return { 'signature' : raw_hdr[0], 'revision' : raw_hdr[1], 'hdr_size' : raw_hdr[2], 'hdr_crc' : raw_hdr[3], 'hdr_lba' : raw_hdr[5], + 'hdr_offs' : raw_hdr[5] * self.sector_size, 'backup_lba' : raw_hdr[6], + 'backup_offs' : raw_hdr[6] * self.sector_size, 'first_lba' : raw_hdr[7], + 'first_offs' : raw_hdr[7] * self.sector_size, 'last_lba' : raw_hdr[8], + 'last_offs' : raw_hdr[8] * self.sector_size, 'disk_uuid' :_stringify_uuid(raw_hdr[9]), 'ptable_lba' : raw_hdr[10], + 'ptable_offs' : raw_hdr[10] * self.sector_size, + 'ptable_size' : raw_hdr[11] * raw_hdr[12], 'entries_cnt' : raw_hdr[11], 'entry_size' : raw_hdr[12], 'ptable_crc' : raw_hdr[13], - 'primary' : primary } + 'primary' : primary, + 'primary_str' : primary_str } def _read_raw_ptable(self, header): """ Read and validate primary or backup partition table. The 'header' @@ -176,13 +194,13 @@ class GptParser: one. The 'header' argument is a dictionary which is returned by the 'read_header()' method. """ - raw_ptable = self._read_disk(header['ptable_lba'] * self.sector_size, - header['entry_size'] * header['entries_cnt']) + raw_ptable = self._read_disk(header['ptable_offs'], + header['ptable_size']) crc = binascii.crc32(raw_ptable) & 0xFFFFFFFF if crc != header['ptable_crc']: - raise MountError("partition table at LBA %d is corrupted" % \ - header['ptable_lba']) + raise MountError("Partition table at LBA %d (%s) is corrupted" % \ + (header['ptable_lba'], header['primary_str'])) return raw_ptable @@ -190,15 +208,18 @@ class GptParser: """ This is a generator which parses the GPT partition table and generates the following dictionary for each partition: - 'index' : the index of the partition in the partition table - 'type_uuid' : partition type UUID - 'part_uuid' : partition UUID - 'first_lba' : the first LBA - 'last_lba' : the last LBA - 'flags' : attribute flags - 'name' : partition name - 'primary' : a boolean, if 'True', this is the primary partition - table, if 'False' - the secondary + 'index' : the index of the partition table endry + 'offs' : byte disk offset of the partition table entry + 'type_uuid' : partition type UUID + 'part_uuid' : partition UUID + 'first_lba' : the first LBA + 'last_lba' : the last LBA + 'flags' : attribute flags + 'name' : partition name + 'primary' : a boolean, if 'True', this is the primary partition + table, if 'False' - the secondary + 'primary_str' : contains string "primary" if this is the primary GPT + header, and "backup" otherwise This dictionary corresponds to the GPT header format. Please, see the UEFI standard for the description of these fields. @@ -207,6 +228,11 @@ class GptParser: partition table are generated, otherwise partitions from the backup GPT partition table are generated. """ + if primary: + primary_str = "primary" + else: + primary_str = "backup" + header = self.read_header(primary) raw_ptable = self._read_raw_ptable(header) @@ -220,11 +246,13 @@ class GptParser: part_name = str(raw_entry[5].decode('UTF-16').split('\0', 1)[0]) - yield { 'index' : index, - 'type_uuid' : _stringify_uuid(raw_entry[0]), - 'part_uuid' : _stringify_uuid(raw_entry[1]), - 'first_lba' : raw_entry[2], - 'last_lba' : raw_entry[3], - 'flags' : raw_entry[4], - 'name' : part_name, - 'primary' : primary } + yield { 'index' : index, + 'offs' : header['ptable_offs'] + start, + 'type_uuid' : _stringify_uuid(raw_entry[0]), + 'part_uuid' : _stringify_uuid(raw_entry[1]), + 'first_lba' : raw_entry[2], + 'last_lba' : raw_entry[3], + 'flags' : raw_entry[4], + 'name' : part_name, + 'primary' : primary, + 'primary_str' : primary_str } |